@opendata-ai/openchart-vanilla 6.15.0 → 6.16.0
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/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/gradient-utils.ts +9 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/export.ts","../src/graph/simulation-worker-url.ts","../src/graph-mount.ts","../src/graph/canvas-renderer.ts","../src/graph/zoom.ts","../src/graph/interaction.ts","../src/graph/keyboard.ts","../src/graph/search.ts","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/center.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/add.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/cover.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/data.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/extent.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/quad.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/find.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/remove.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/root.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/size.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/visit.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/visitAfter.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/x.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/y.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/quadtree.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/constant.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/jiggle.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/collide.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/link.js","../../../node_modules/.bun/d3-dispatch@3.0.1/node_modules/d3-dispatch/src/dispatch.js","../../../node_modules/.bun/d3-timer@3.0.1/node_modules/d3-timer/src/timer.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/lcg.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/simulation.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/manyBody.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/x.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/y.js","../src/graph/simulation.ts","../src/graph/spatial-index.ts","../src/resize-observer.ts","../src/tooltip.ts","../src/mount.ts","../src/animation.ts","../src/svg-renderer.ts","../src/gradient-utils.ts","../src/text-edit-overlay.ts","../src/renderers/table-cells.ts","../src/sankey-mount.ts","../src/sankey-renderer.ts","../src/table-keyboard.ts","../src/table-mount.ts","../src/table-renderer.ts"],"sourcesContent":["/**\n * Export utilities: serialize charts to SVG, PNG, JPG, or CSV.\n *\n * - SVG: serializes the rendered DOM element via XMLSerializer\n * - SVG with fonts: async version that embeds @font-face data URIs\n * - PNG: renders SVG to canvas, then extracts as Blob\n * - JPG: same as PNG but with JPEG compression and background fill\n * - CSV: converts a data array to comma-separated text\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SVGExportOptions {\n /** Embed fonts as base64 data URIs in the SVG. Defaults to true. */\n embedFonts?: boolean;\n}\n\nexport interface PNGExportOptions extends SVGExportOptions {\n /** DPI scaling factor. Defaults to 2 for retina-quality output. */\n dpi?: number;\n}\n\nexport interface JPGExportOptions extends PNGExportOptions {\n /** JPEG quality from 0 to 1. Defaults to 0.92. */\n quality?: number;\n}\n\ninterface FontFaceData {\n family: string;\n weight: string;\n style: string;\n base64: string;\n format: string;\n}\n\n// ---------------------------------------------------------------------------\n// Dimension parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Extract dimensions from an SVG element, trying width/height attributes\n * first, then falling back to viewBox.\n */\nfunction getSVGDimensions(svg: SVGElement): { width: number; height: number } {\n const w = parseFloat(svg.getAttribute('width') || '');\n const h = parseFloat(svg.getAttribute('height') || '');\n if (w && h) return { width: w, height: h };\n\n const vb = svg.getAttribute('viewBox');\n if (vb) {\n const parts = vb.split(/[\\s,]+/).map(Number);\n if (parts.length >= 4 && parts[2] && parts[3]) {\n return { width: parts[2], height: parts[3] };\n }\n }\n\n return { width: 600, height: 400 };\n}\n\n/**\n * Ensure an SVG string has explicit width/height attributes.\n *\n * When an SVG only has a viewBox (no width/height), browsers loading it as\n * an Image blob may use 300x150 as the intrinsic size instead of the viewBox\n * dimensions. This causes clipping at non-1x DPI scaling. Injecting explicit\n * width/height into the root <svg> tag fixes the intrinsic size.\n */\nfunction ensureSVGDimensions(svgString: string, width: number, height: number): string {\n // If the <svg> already has a width attribute, leave it alone\n if (/^<svg[^>]*\\swidth\\s*=/.test(svgString)) return svgString;\n // Inject width and height right after <svg\n return svgString.replace(/^(<svg)/, `$1 width=\"${width}\" height=\"${height}\"`);\n}\n\n// ---------------------------------------------------------------------------\n// Font embedding\n// ---------------------------------------------------------------------------\n\n/**\n * Collect unique font-family + font-weight combos from all <text> elements.\n */\nfunction collectUsedFonts(svgElement: SVGElement): Map<string, Set<string>> {\n const fonts = new Map<string, Set<string>>();\n const textElements = svgElement.querySelectorAll('text');\n\n for (const el of textElements) {\n const family = el.getAttribute('font-family');\n const weight = el.getAttribute('font-weight') || '400';\n if (family) {\n // Take the first font in the stack (e.g., \"Inter, sans-serif\" → \"Inter\")\n const primary = family.split(',')[0].trim().replace(/[\"']/g, '');\n if (!fonts.has(primary)) fonts.set(primary, new Set());\n fonts.get(primary)!.add(String(weight));\n }\n }\n\n return fonts;\n}\n\n/**\n * Find @font-face rules in document stylesheets that match the requested fonts.\n * Returns the src URLs for .woff2 files.\n */\nfunction findFontFaceRules(\n usedFonts: Map<string, Set<string>>,\n): Array<{ family: string; weight: string; style: string; url: string; format: string }> {\n const results: Array<{\n family: string;\n weight: string;\n style: string;\n url: string;\n format: string;\n }> = [];\n\n try {\n for (const sheet of document.styleSheets) {\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n // Cross-origin stylesheet, skip\n continue;\n }\n\n for (const rule of rules) {\n if (!(rule instanceof CSSFontFaceRule)) continue;\n\n const familyRaw = rule.style.getPropertyValue('font-family').replace(/[\"']/g, '').trim();\n const weight = rule.style.getPropertyValue('font-weight') || '400';\n const style = rule.style.getPropertyValue('font-style') || 'normal';\n const src = rule.style.getPropertyValue('src');\n\n const weights = usedFonts.get(familyRaw);\n if (!weights) continue;\n\n // Check if this weight is used (handle ranges like \"100 900\")\n const weightMatch = weights.has(weight) || weight.includes(' ');\n if (!weightMatch) continue;\n\n // Extract woff2 URL from src descriptor\n const woff2Match = src.match(/url\\([\"']?([^\"')]+\\.woff2[^\"')]*?)[\"']?\\)/);\n if (woff2Match) {\n results.push({\n family: familyRaw,\n weight,\n style,\n url: woff2Match[1],\n format: 'woff2',\n });\n }\n }\n }\n } catch {\n // Stylesheet access failed entirely, return empty\n }\n\n return results;\n}\n\n/**\n * Fetch font files and convert to base64 data URIs.\n */\nasync function fetchFontsAsBase64(\n fontRules: Array<{ family: string; weight: string; style: string; url: string; format: string }>,\n): Promise<FontFaceData[]> {\n const results: FontFaceData[] = [];\n\n const fetches = fontRules.map(async (rule) => {\n try {\n const response = await fetch(rule.url);\n if (!response.ok) return;\n const buffer = await response.arrayBuffer();\n const base64 = arrayBufferToBase64(buffer);\n results.push({\n family: rule.family,\n weight: rule.weight,\n style: rule.style,\n base64,\n format: rule.format,\n });\n } catch {\n // Font fetch failed (CORS, network, etc.) - skip this font\n }\n });\n\n await Promise.all(fetches);\n return results;\n}\n\nfunction arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Inject @font-face rules with base64 data URIs into the SVG's <defs>.\n */\nfunction injectFontsIntoSVG(svgElement: SVGElement, fonts: FontFaceData[]): void {\n if (fonts.length === 0) return;\n\n const cssRules = fonts\n .map(\n (f) =>\n `@font-face { font-family: '${f.family}'; font-weight: ${f.weight}; font-style: ${f.style}; src: url(data:font/${f.format};base64,${f.base64}) format('${f.format}'); }`,\n )\n .join('\\n');\n\n const ns = 'http://www.w3.org/2000/svg';\n let defs = svgElement.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS(ns, 'defs');\n svgElement.insertBefore(defs, svgElement.firstChild);\n }\n\n const styleEl = document.createElementNS(ns, 'style');\n styleEl.textContent = cssRules;\n defs.insertBefore(styleEl, defs.firstChild);\n}\n\n/**\n * Embed fonts into an SVG element by finding matching @font-face rules\n * in the page's stylesheets, fetching the font files, and injecting\n * them as base64 data URIs.\n *\n * Modifies the SVG element in place. Call this before serialization.\n * If font fetching fails for any font, that font is silently skipped\n * and the export proceeds with system font fallback for that face.\n */\nasync function embedFonts(svgElement: SVGElement): Promise<void> {\n const usedFonts = collectUsedFonts(svgElement);\n if (usedFonts.size === 0) return;\n\n const fontRules = findFontFaceRules(usedFonts);\n if (fontRules.length === 0) return;\n\n const fontData = await fetchFontsAsBase64(fontRules);\n injectFontsIntoSVG(svgElement, fontData);\n}\n\n// ---------------------------------------------------------------------------\n// SVG background color\n// ---------------------------------------------------------------------------\n\n/**\n * Read the chart's background color from its first rect element.\n */\nfunction getSVGBackgroundColor(svgElement: SVGElement): string {\n const firstRect = svgElement.querySelector('rect');\n return firstRect?.getAttribute('fill') || '#ffffff';\n}\n\n// ---------------------------------------------------------------------------\n// SVG export\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize an SVG element to an XML string.\n *\n * @param svgElement - The rendered SVG element to serialize.\n * @returns The SVG markup as a string.\n */\nexport function exportSVG(svgElement: SVGElement): string {\n const serializer = new XMLSerializer();\n return serializer.serializeToString(svgElement);\n}\n\n/**\n * Serialize an SVG element with embedded fonts to an XML string.\n *\n * Collects font-family declarations from the SVG's text elements,\n * finds matching @font-face rules in the page's stylesheets, fetches\n * the font files, and embeds them as base64 data URIs. The resulting\n * SVG is self-contained and renders correctly without external fonts.\n *\n * @param svgElement - The rendered SVG element to serialize.\n * @param options - Export options.\n * @returns A Promise resolving to the SVG markup as a string.\n */\nexport async function exportSVGWithFonts(\n svgElement: SVGElement,\n options?: SVGExportOptions,\n): Promise<string> {\n const shouldEmbed = options?.embedFonts ?? true;\n if (shouldEmbed) {\n await embedFonts(svgElement);\n }\n return exportSVG(svgElement);\n}\n\n// ---------------------------------------------------------------------------\n// Raster export (PNG / JPG)\n// ---------------------------------------------------------------------------\n\n/**\n * Render an SVG element to a PNG Blob via a canvas.\n *\n * Embeds fonts by default so the exported image matches on-screen rendering.\n * Set `embedFonts: false` to skip font embedding for faster exports.\n *\n * @param svgElement - The rendered SVG element.\n * @param options - Optional DPI scaling and font embedding.\n * @returns A Promise resolving to the PNG Blob.\n */\nexport async function exportPNG(svgElement: SVGElement, options?: PNGExportOptions): Promise<Blob> {\n const dpi = options?.dpi ?? 2;\n const shouldEmbed = options?.embedFonts ?? true;\n\n if (shouldEmbed) {\n await embedFonts(svgElement);\n }\n\n const { width, height } = getSVGDimensions(svgElement);\n\n // Ensure the SVG has explicit width/height attributes so that when loaded\n // as a standalone Image blob the browser knows the intrinsic size. Without\n // these, browsers may default to 300x150 or use heuristics that break at\n // non-1x DPI scaling.\n const svgString = ensureSVGDimensions(exportSVG(svgElement), width, height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width * dpi;\n canvas.height = height * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas 2D context not available');\n }\n\n ctx.scale(dpi, dpi);\n\n const img = new Image();\n const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<Blob>((resolve, reject) => {\n img.onload = () => {\n ctx.drawImage(img, 0, 0, width, height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob((result) => {\n if (result) {\n resolve(result);\n } else {\n reject(new Error('Canvas toBlob returned null'));\n }\n }, 'image/png');\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load SVG as image'));\n };\n\n img.src = url;\n });\n}\n\n/**\n * Render an SVG element to a JPEG Blob via a canvas.\n *\n * Same pipeline as exportPNG but outputs JPEG with configurable quality.\n * The canvas is filled with the chart's background color before drawing\n * to avoid transparent backgrounds rendering as black in JPEG format.\n *\n * @param svgElement - The rendered SVG element.\n * @param options - Optional DPI scaling, JPEG quality, and font embedding.\n * @returns A Promise resolving to the JPEG Blob.\n */\nexport async function exportJPG(svgElement: SVGElement, options?: JPGExportOptions): Promise<Blob> {\n const dpi = options?.dpi ?? 2;\n const quality = options?.quality ?? 0.92;\n const shouldEmbed = options?.embedFonts ?? true;\n\n if (shouldEmbed) {\n await embedFonts(svgElement);\n }\n\n const { width, height } = getSVGDimensions(svgElement);\n const svgString = ensureSVGDimensions(exportSVG(svgElement), width, height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width * dpi;\n canvas.height = height * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas 2D context not available');\n }\n\n // Fill with the chart's actual background color (not hardcoded white)\n ctx.fillStyle = getSVGBackgroundColor(svgElement);\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n ctx.scale(dpi, dpi);\n\n const img = new Image();\n const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<Blob>((resolve, reject) => {\n img.onload = () => {\n ctx.drawImage(img, 0, 0, width, height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(\n (result) => {\n if (result) {\n resolve(result);\n } else {\n reject(new Error('Canvas toBlob returned null'));\n }\n },\n 'image/jpeg',\n quality,\n );\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load SVG as image'));\n };\n\n img.src = url;\n });\n}\n\n// ---------------------------------------------------------------------------\n// CSV export\n// ---------------------------------------------------------------------------\n\n/**\n * Convert an array of data objects to a CSV string.\n *\n * Uses the keys from the first row as column headers.\n * Values are quoted if they contain commas, quotes, or newlines.\n *\n * @param data - Array of row objects.\n * @returns CSV-formatted string.\n */\nexport function exportCSV(data: Record<string, unknown>[]): string {\n if (data.length === 0) return '';\n\n const headers = Object.keys(data[0]);\n const rows = [headers.map(csvEscape).join(',')];\n\n for (const row of data) {\n const values = headers.map((h) => csvEscape(String(row[h] ?? '')));\n rows.push(values.join(','));\n }\n\n return rows.join('\\n');\n}\n\nfunction csvEscape(value: string): string {\n if (value.includes(',') || value.includes('\"') || value.includes('\\n') || value.includes('\\r')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n","/**\n * Creates a Web Worker running the force simulation.\n *\n * References the built .js file via `new URL` + `import.meta.url`.\n * The consuming app's bundler resolves the worker path at build time.\n *\n * Note: SimulationManager handles .js/.ts fallback internally. This\n * helper is exported for consumers who want to manage the worker directly.\n */\nexport function createSimulationWorker(): Worker {\n return new Worker(new URL('./simulation-worker.js', import.meta.url), { type: 'module' });\n}\n","/**\n * Graph mount API: the main entry point for vanilla JS graph usage.\n *\n * createGraph() takes a container, GraphSpec, and options, compiles the graph,\n * creates a force simulation, canvas renderer, spatial index, interaction\n * manager, and search manager, then runs an animation loop driven by\n * simulation ticks. Returns a GraphInstance with update/search/zoom/destroy.\n */\n\nimport type { CompileOptions, DarkMode, GraphSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport type {\n CompiledGraphEdge,\n CompiledGraphNode,\n GraphCompilation,\n} from '@opendata-ai/openchart-engine';\nimport { compileGraph } from '@opendata-ai/openchart-engine';\n\nimport { GraphCanvasRenderer } from './graph/canvas-renderer';\nimport { GraphInteractionManager } from './graph/interaction';\nimport { attachGraphKeyboardNav } from './graph/keyboard';\nimport { GraphSearchManager } from './graph/search';\nimport { SimulationManager } from './graph/simulation';\nimport { SpatialIndex } from './graph/spatial-index';\nimport type { GraphRenderState, PositionedEdge, PositionedNode } from './graph/types';\nimport type { SimEdge, SimNode } from './graph/worker-protocol';\nimport { ZoomTransform } from './graph/zoom';\nimport { observeResize } from './resize-observer';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface GraphMountOptions {\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Show the built-in tooltip on node/edge hover. Defaults to true. */\n tooltip?: boolean;\n /** Show the built-in legend. Defaults to true. */\n legend?: boolean;\n onNodeClick?: (node: Record<string, unknown>) => void;\n onNodeDoubleClick?: (node: Record<string, unknown>) => void;\n onNodeHover?: (node: Record<string, unknown> | null) => void;\n onEdgeHover?: (edge: Record<string, unknown> | null) => void;\n onSelectionChange?: (nodeIds: string[]) => void;\n}\n\nexport interface GraphInstance {\n update(spec: GraphSpec): void;\n /** Re-compile encoding/legend/chrome without restarting the simulation. Preserves node positions. */\n updateVisuals(spec: GraphSpec): void;\n search(query: string): void;\n clearSearch(): void;\n zoomToFit(): void;\n zoomToNode(nodeId: string): void;\n selectNode(nodeId: string): void;\n getSelectedNodes(): string[];\n resize(): void;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a graph instance from a spec and mount it into a container.\n *\n * @param container - The DOM element to render into.\n * @param spec - The graph spec.\n * @param options - Mount options.\n * @returns A GraphInstance with update/search/zoom/destroy methods.\n */\nexport function createGraph(\n container: HTMLElement,\n spec: GraphSpec,\n options?: GraphMountOptions,\n): GraphInstance {\n let currentSpec = spec;\n let compilation: GraphCompilation;\n let destroyed = false;\n\n // DOM elements\n let wrapper: HTMLElement | null = null;\n let canvas: HTMLCanvasElement | null = null;\n let chromeEl: HTMLElement | null = null;\n let legendEl: HTMLElement | null = null;\n\n // Subsystems\n let renderer: GraphCanvasRenderer | null = null;\n let simulation: SimulationManager | null = null;\n const spatialIndex = new SpatialIndex();\n let interactionManager: GraphInteractionManager | null = null;\n const searchManager = new GraphSearchManager();\n let tooltipManager: TooltipManager | null = null;\n let cleanupKeyboard: (() => void) | null = null;\n let disconnectResize: (() => void) | null = null;\n\n // State\n let positionedNodes: PositionedNode[] = [];\n let positionedEdges: PositionedEdge[] = [];\n let adjacencyMap = new Map<string, Set<string>>();\n let nodeDataMap = new Map<string, Record<string, unknown>>();\n let edgeDataMap = new Map<string, Record<string, unknown>>();\n let hoveredNodeId: string | null = null;\n let hoveredEdgeId: string | null = null;\n let selectedNodeIds = new Set<string>();\n let animFrameId: number | null = null;\n let needsRender = false;\n let isGesturing = false;\n let gestureTimeout: ReturnType<typeof setTimeout> | null = null;\n let lastEdgeHitTime = 0;\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n function markGesture(): void {\n isGesturing = true;\n if (gestureTimeout !== null) clearTimeout(gestureTimeout);\n gestureTimeout = setTimeout(() => {\n isGesturing = false;\n gestureTimeout = null;\n needsRender = true;\n scheduleRender();\n }, 150);\n }\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n function compile(): GraphCompilation {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n };\n\n return compileGraph(currentSpec, compileOpts);\n }\n\n function buildDataMaps(): void {\n nodeDataMap = new Map(compilation.nodes.map((n) => [n.id, n.data ?? {}]));\n edgeDataMap = new Map(compilation.edges.map((e) => [`${e.source}->${e.target}`, e.data ?? {}]));\n }\n\n function buildAdjacencyMap(edges: CompiledGraphEdge[]): Map<string, Set<string>> {\n const map = new Map<string, Set<string>>();\n for (const edge of edges) {\n if (!map.has(edge.source)) map.set(edge.source, new Set());\n if (!map.has(edge.target)) map.set(edge.target, new Set());\n map.get(edge.source)!.add(edge.target);\n map.get(edge.target)!.add(edge.source);\n }\n return map;\n }\n\n function toSimNodes(nodes: CompiledGraphNode[]): SimNode[] {\n return nodes.map((n) => ({\n id: n.id,\n radius: n.radius,\n community: n.community,\n }));\n }\n\n function toSimEdges(edges: CompiledGraphEdge[]): SimEdge[] {\n return edges.map((e) => ({\n source: e.source,\n target: e.target,\n }));\n }\n\n /**\n * Look up a node's data from the compilation by id.\n * Falls back to an empty object if not found.\n */\n function nodeDataById(nodeId: string): Record<string, unknown> {\n return nodeDataMap.get(nodeId) ?? {};\n }\n\n /**\n * Point-to-line-segment distance for edge hit testing.\n * Returns the shortest distance from point (px, py) to the segment (ax, ay)-(bx, by).\n */\n function pointToSegmentDist(\n px: number,\n py: number,\n ax: number,\n ay: number,\n bx: number,\n by: number,\n ): number {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n if (lenSq === 0) return Math.hypot(px - ax, py - ay);\n const t = Math.max(0, Math.min(1, ((px - ax) * dx + (py - ay) * dy) / lenSq));\n return Math.hypot(px - (ax + t * dx), py - (ay + t * dy));\n }\n\n /**\n * Find the edge closest to a graph-space point, within a threshold.\n * Returns an edge key \"source->target\" or null.\n */\n function hitTestEdge(graphX: number, graphY: number, threshold: number): string | null {\n let bestDist = threshold;\n let bestEdgeId: string | null = null;\n\n for (const edge of positionedEdges) {\n const dist = pointToSegmentDist(\n graphX,\n graphY,\n edge.sourceX,\n edge.sourceY,\n edge.targetX,\n edge.targetY,\n );\n if (dist < bestDist) {\n bestDist = dist;\n bestEdgeId = `${edge.source}->${edge.target}`;\n }\n }\n\n return bestEdgeId;\n }\n\n /**\n * Look up edge data by edge id (\"source->target\").\n */\n function edgeDataById(edgeId: string): Record<string, unknown> | null {\n return edgeDataMap.get(edgeId) ?? null;\n }\n\n // ---------------------------------------------------------------------------\n // DOM creation\n // ---------------------------------------------------------------------------\n\n function createDOM(): void {\n const { width, height } = getContainerDimensions();\n const isDark = resolveDarkMode(options?.darkMode);\n\n // Wrapper\n wrapper = document.createElement('div');\n wrapper.className = isDark ? 'oc-graph-wrapper oc-dark' : 'oc-graph-wrapper';\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Apply theme colors as CSS custom properties so chrome HTML picks them up.\n // Without this, consumer-supplied theme.colors.text only affects canvas-drawn\n // labels but not the HTML title/subtitle which read from --oc-text.\n const resolvedTheme = compilation.theme;\n if (resolvedTheme) {\n const s = wrapper.style;\n s.setProperty('--oc-bg', resolvedTheme.colors.background);\n s.setProperty('--oc-text', resolvedTheme.colors.text);\n s.setProperty('--oc-text-secondary', resolvedTheme.colors.axis ?? resolvedTheme.colors.text);\n s.setProperty('--oc-font-family', resolvedTheme.fonts.family);\n s.fontFamily = resolvedTheme.fonts.family;\n }\n\n // Chrome (title, subtitle)\n chromeEl = document.createElement('div');\n chromeEl.className = 'oc-graph-chrome';\n renderChrome();\n wrapper.appendChild(chromeEl);\n\n // Canvas\n canvas = document.createElement('canvas');\n canvas.className = 'oc-graph-canvas';\n canvas.setAttribute('role', 'img');\n if (compilation.a11y?.altText) {\n canvas.setAttribute('aria-label', compilation.a11y.altText);\n }\n wrapper.appendChild(canvas);\n\n // Legend\n if (options?.legend !== false) {\n legendEl = document.createElement('div');\n legendEl.className = 'oc-graph-legend';\n renderLegend();\n wrapper.appendChild(legendEl);\n }\n\n container.appendChild(wrapper);\n\n // Canvas uses the full container height; chrome overlays on top\n const canvasHeight = Math.max(height, 200);\n renderer = new GraphCanvasRenderer(canvas);\n renderer.resize(width, canvasHeight);\n }\n\n function renderChrome(): void {\n if (!chromeEl) return;\n let html = '';\n\n if (compilation.chrome.title) {\n html += `<h2 class=\"oc-title\">${escapeHtml(compilation.chrome.title.text)}</h2>`;\n }\n if (compilation.chrome.subtitle) {\n html += `<p class=\"oc-subtitle\">${escapeHtml(compilation.chrome.subtitle.text)}</p>`;\n }\n\n chromeEl.innerHTML = html;\n\n // Hide chrome if empty\n if (!html) {\n chromeEl.style.display = 'none';\n } else {\n chromeEl.style.display = '';\n }\n }\n\n function renderLegend(): void {\n if (!legendEl) return;\n\n const entries = compilation.legend.entries;\n if (entries.length === 0) {\n legendEl.style.display = 'none';\n return;\n }\n\n legendEl.style.display = '';\n let html = '';\n for (const entry of entries) {\n html += '<div class=\"oc-graph-legend-item\">';\n html += `<span class=\"oc-graph-legend-swatch\" style=\"background:${escapeHtml(entry.color)}\"></span>`;\n html += `<span>${escapeHtml(entry.label)}</span>`;\n html += '</div>';\n }\n legendEl.innerHTML = html;\n }\n\n // ---------------------------------------------------------------------------\n // Simulation and animation\n // ---------------------------------------------------------------------------\n\n function initSimulation(): void {\n const simNodes = toSimNodes(compilation.nodes);\n const simEdges = toSimEdges(compilation.edges);\n const config = compilation.simulationConfig;\n\n simulation = SimulationManager.create(simNodes, simEdges, {\n chargeStrength: config.chargeStrength,\n linkDistance: config.linkDistance,\n clustering: config.clustering,\n alphaDecay: config.alphaDecay,\n velocityDecay: config.velocityDecay,\n collisionRadius: config.collisionRadius,\n collisionPadding: config.collisionPadding,\n linkStrength: config.linkStrength,\n centerForce: config.centerForce,\n });\n\n let initialSettleDone = false;\n let initialFitDone = false;\n\n simulation.onTick((positions, _alpha) => {\n if (destroyed) return;\n\n // Build position lookup\n const posMap = new Map<string, { x: number; y: number }>();\n for (const p of positions) {\n posMap.set(p.id, { x: p.x, y: p.y });\n }\n\n // Build positioned nodes\n positionedNodes = compilation.nodes.map((node) => {\n const pos = posMap.get(node.id) ?? { x: 0, y: 0 };\n return { ...node, x: pos.x, y: pos.y };\n });\n\n // Build positioned edges\n positionedEdges = compilation.edges.map((edge) => {\n const src = posMap.get(edge.source) ?? { x: 0, y: 0 };\n const tgt = posMap.get(edge.target) ?? { x: 0, y: 0 };\n return {\n ...edge,\n sourceX: src.x,\n sourceY: src.y,\n targetX: tgt.x,\n targetY: tgt.y,\n };\n });\n\n // Rebuild spatial index\n spatialIndex.rebuild(positionedNodes);\n\n // Fit the viewport once on the first tick so the graph is visible and\n // centered immediately. After that, let the user interact freely while\n // the simulation continues settling in the background.\n if (!initialFitDone && positionedNodes.length > 0 && interactionManager) {\n initialFitDone = true;\n const { width: cw, height: ch } = getCanvasDimensions();\n const { transform: fitTransform } = ZoomTransform.fitBounds(positionedNodes, cw, ch);\n interactionManager.setTransform(fitTransform);\n }\n\n needsRender = true;\n scheduleRender();\n });\n\n simulation.onSettled(() => {\n if (initialSettleDone) return;\n initialSettleDone = true;\n });\n }\n\n function getCanvasDimensions(): { width: number; height: number } {\n if (!canvas) return { width: 600, height: 400 };\n const rect = canvas.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n function scheduleRender(): void {\n if (animFrameId !== null || destroyed) return;\n animFrameId = requestAnimationFrame(renderFrame);\n }\n\n function renderFrame(): void {\n animFrameId = null;\n if (destroyed || !renderer || !interactionManager) return;\n\n if (needsRender) {\n needsRender = false;\n\n const transform = interactionManager.getTransform();\n const state: GraphRenderState = {\n nodes: positionedNodes,\n edges: positionedEdges,\n transform: { x: transform.x, y: transform.y, k: transform.k },\n hoveredNodeId,\n hoveredEdgeId,\n selectedNodeIds,\n adjacencyMap,\n theme: compilation.theme,\n searchMatches: searchManager.getMatches(),\n isGesturing,\n watermark: compilation.watermark,\n };\n\n renderer.render(state);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Interaction wiring\n // ---------------------------------------------------------------------------\n\n function initInteraction(): void {\n if (!canvas) return;\n\n if (options?.tooltip !== false) {\n tooltipManager = createTooltipManager(wrapper!);\n }\n\n interactionManager = new GraphInteractionManager(canvas, spatialIndex, {\n onTransformChange(_transform) {\n markGesture();\n needsRender = true;\n scheduleRender();\n },\n onHoverChange(nodeId) {\n hoveredNodeId = nodeId;\n needsRender = true;\n scheduleRender();\n\n // Fire onNodeHover callback\n if (nodeId) {\n options?.onNodeHover?.(nodeDataById(nodeId));\n } else {\n options?.onNodeHover?.(null);\n }\n\n // Show or hide tooltip\n if (nodeId && tooltipManager) {\n // Clear edge hover when hovering a node\n if (hoveredEdgeId) {\n hoveredEdgeId = null;\n options?.onEdgeHover?.(null);\n }\n const content = compilation.tooltipDescriptors.get(nodeId);\n if (content) {\n const node = positionedNodes.find((n) => n.id === nodeId);\n if (node && interactionManager) {\n const screen = interactionManager.getTransform().graphToScreen(node.x, node.y);\n tooltipManager.show(content, screen.x, screen.y);\n }\n }\n } else if (!nodeId) {\n // Tooltip hiding handled in onBackgroundHover (edge may show tooltip)\n // If no edge hover happens, tooltip stays hidden\n tooltipManager?.hide();\n }\n },\n onBackgroundHover(graphX, graphY, screenX, screenY) {\n // Throttle edge hit testing to avoid O(n) scan on every mousemove\n const now = performance.now();\n if (now - lastEdgeHitTime < 32) {\n // When throttled, clear edge hover so hover-off transitions stay snappy\n if (hoveredEdgeId) {\n hoveredEdgeId = null;\n needsRender = true;\n scheduleRender();\n options?.onEdgeHover?.(null);\n tooltipManager?.hide();\n }\n return;\n }\n lastEdgeHitTime = now;\n\n // Edge hit testing: check proximity to edge line segments\n const transform = interactionManager?.getTransform();\n const threshold = 5 / (transform?.k ?? 1); // 5px in screen space\n const edgeId = hitTestEdge(graphX, graphY, threshold);\n\n if (edgeId !== hoveredEdgeId) {\n hoveredEdgeId = edgeId;\n needsRender = true;\n scheduleRender();\n\n if (edgeId) {\n const data = edgeDataById(edgeId);\n options?.onEdgeHover?.(data);\n\n // Show edge tooltip\n if (tooltipManager && data) {\n const fields = Object.entries(data)\n .filter(([key]) => key !== 'source' && key !== 'target')\n .filter(([, value]) => value != null)\n .map(([key, value]) => ({\n label: key,\n value: typeof value === 'number' ? value.toLocaleString() : String(value),\n }));\n\n const [source, target] = edgeId.split('->');\n tooltipManager.show({ title: `${source} → ${target}`, fields }, screenX, screenY);\n }\n } else {\n options?.onEdgeHover?.(null);\n tooltipManager?.hide();\n }\n }\n },\n onSelectionChange(nodeIds) {\n selectedNodeIds = new Set(nodeIds);\n needsRender = true;\n scheduleRender();\n options?.onSelectionChange?.(nodeIds);\n\n // Fire onNodeClick for the most recently added node\n if (nodeIds.length > 0) {\n const lastId = nodeIds[nodeIds.length - 1];\n options?.onNodeClick?.(nodeDataById(lastId));\n }\n },\n onNodeDragStart(nodeId) {\n // Pin at the node's current position to avoid visual snap to origin\n const node = positionedNodes.find((n) => n.id === nodeId);\n const x = node?.x ?? 0;\n const y = node?.y ?? 0;\n simulation?.pinNode(nodeId, x, y);\n canvas?.classList.add('oc-graph-canvas--dragging');\n },\n onNodeDrag(nodeId, x, y) {\n simulation?.dragNode(nodeId, x, y);\n },\n onNodeDragEnd(nodeId) {\n simulation?.unpinNode(nodeId);\n canvas?.classList.remove('oc-graph-canvas--dragging');\n },\n onDoubleClick(nodeId) {\n options?.onNodeDoubleClick?.(nodeDataById(nodeId));\n },\n });\n\n // Wire keyboard navigation\n cleanupKeyboard = attachGraphKeyboardNav({\n canvas,\n getNodes: () => positionedNodes,\n getSelectedIds: () => [...selectedNodeIds],\n getAdjacency: () => adjacencyMap,\n onSelect(nodeId) {\n selectedNodeIds = new Set([nodeId]);\n needsRender = true;\n scheduleRender();\n options?.onNodeClick?.(nodeDataById(nodeId));\n options?.onSelectionChange?.([nodeId]);\n },\n onDeselect() {\n selectedNodeIds.clear();\n needsRender = true;\n scheduleRender();\n options?.onSelectionChange?.([]);\n },\n onZoom(direction) {\n if (!interactionManager || !canvas) return;\n const t = interactionManager.getTransform();\n const { width: cw, height: ch } = getCanvasDimensions();\n const factor = direction === 'in' ? 1.2 : 0.8;\n const newK = t.k * factor;\n const newTransform = t.zoomAt(newK, cw / 2, ch / 2);\n interactionManager.setTransform(newTransform);\n needsRender = true;\n scheduleRender();\n },\n onFitAll() {\n zoomToFit();\n },\n });\n\n // Handle node clicks (from interaction manager selection change wiring above)\n // We catch clicks via the interaction manager's onSelectionChange callback\n }\n\n // ---------------------------------------------------------------------------\n // Public API methods\n // ---------------------------------------------------------------------------\n\n function search(query: string): void {\n if (destroyed) return;\n searchManager.search(query, positionedNodes);\n needsRender = true;\n scheduleRender();\n }\n\n function clearSearch(): void {\n if (destroyed) return;\n searchManager.clearSearch();\n needsRender = true;\n scheduleRender();\n }\n\n function zoomToFit(): void {\n if (destroyed || !interactionManager || positionedNodes.length === 0) return;\n const { width: cw, height: ch } = getCanvasDimensions();\n const { transform: fitTransform } = ZoomTransform.fitBounds(positionedNodes, cw, ch);\n interactionManager.setTransform(fitTransform);\n needsRender = true;\n scheduleRender();\n }\n\n function zoomToNode(nodeId: string): void {\n if (destroyed || !interactionManager || !canvas) return;\n const node = positionedNodes.find((n) => n.id === nodeId);\n if (!node) return;\n\n const { width: cw, height: ch } = getCanvasDimensions();\n // Zoom to 2x and center on node\n const k = 2;\n const tx = cw / 2 - node.x * k;\n const ty = ch / 2 - node.y * k;\n const newTransform = new ZoomTransform(tx, ty, k);\n interactionManager.setTransform(newTransform);\n needsRender = true;\n scheduleRender();\n }\n\n function selectNode(nodeId: string): void {\n if (destroyed) return;\n selectedNodeIds = new Set([nodeId]);\n needsRender = true;\n scheduleRender();\n options?.onSelectionChange?.([nodeId]);\n }\n\n function getSelectedNodes(): string[] {\n return [...selectedNodeIds];\n }\n\n function doResize(): void {\n if (destroyed || !canvas || !renderer || !wrapper) return;\n const { width, height } = getContainerDimensions();\n const canvasHeight = Math.max(height, 200);\n renderer.resize(width, canvasHeight);\n needsRender = true;\n scheduleRender();\n }\n\n function update(newSpec: GraphSpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n\n // Tear down old simulation + interaction\n teardownSubsystems();\n\n // Recompile\n compilation = compile();\n adjacencyMap = buildAdjacencyMap(compilation.edges);\n buildDataMaps();\n\n // Update DOM chrome/legend\n renderChrome();\n renderLegend();\n\n // Reinit\n initSimulation();\n initInteraction();\n\n // Reset state\n hoveredNodeId = null;\n hoveredEdgeId = null;\n selectedNodeIds = new Set();\n searchManager.clearSearch();\n }\n\n function updateVisuals(newSpec: GraphSpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n\n // Build a position lookup from current positioned nodes\n const posMap = new Map<string, { x: number; y: number }>();\n for (const node of positionedNodes) {\n posMap.set(node.id, { x: node.x, y: node.y });\n }\n\n // Recompile with new spec (encoding, chrome, nodeOverrides, etc.)\n compilation = compile();\n adjacencyMap = buildAdjacencyMap(compilation.edges);\n buildDataMaps();\n\n // Transfer positions to new compiled nodes\n positionedNodes = compilation.nodes.map((node) => {\n const pos = posMap.get(node.id) ?? { x: 0, y: 0 };\n return { ...node, x: pos.x, y: pos.y };\n });\n\n // Rebuild positioned edges from existing positions\n positionedEdges = compilation.edges.map((edge) => {\n const src = posMap.get(edge.source) ?? { x: 0, y: 0 };\n const tgt = posMap.get(edge.target) ?? { x: 0, y: 0 };\n return {\n ...edge,\n sourceX: src.x,\n sourceY: src.y,\n targetX: tgt.x,\n targetY: tgt.y,\n };\n });\n\n // Rebuild spatial index with updated visuals\n spatialIndex.rebuild(positionedNodes);\n\n // Update DOM chrome/legend\n renderChrome();\n renderLegend();\n\n // Re-render canvas without restarting simulation\n needsRender = true;\n scheduleRender();\n }\n\n function teardownSubsystems(): void {\n if (animFrameId !== null) {\n cancelAnimationFrame(animFrameId);\n animFrameId = null;\n }\n if (cleanupKeyboard) {\n cleanupKeyboard();\n cleanupKeyboard = null;\n }\n interactionManager?.destroy();\n interactionManager = null;\n simulation?.destroy();\n simulation = null;\n tooltipManager?.destroy();\n tooltipManager = null;\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n if (gestureTimeout !== null) {\n clearTimeout(gestureTimeout);\n gestureTimeout = null;\n }\n\n teardownSubsystems();\n\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n\n if (wrapper?.parentNode) {\n wrapper.parentNode.removeChild(wrapper);\n }\n wrapper = null;\n canvas = null;\n chromeEl = null;\n legendEl = null;\n renderer = null;\n\n container.classList.remove('oc-dark');\n }\n\n // ---------------------------------------------------------------------------\n // Initialize\n // ---------------------------------------------------------------------------\n\n try {\n compilation = compile();\n adjacencyMap = buildAdjacencyMap(compilation.edges);\n buildDataMaps();\n createDOM();\n initSimulation();\n initInteraction();\n } catch (err) {\n console.error('[viz] Graph mount failed:', err);\n // Return a no-op instance so callers don't crash\n return {\n update() {},\n updateVisuals() {},\n search() {},\n clearSearch() {},\n zoomToFit() {},\n zoomToNode() {},\n selectNode() {},\n getSelectedNodes: () => [],\n resize() {},\n destroy() {},\n };\n }\n\n // Responsive resize\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n doResize();\n });\n }\n\n return {\n update,\n updateVisuals,\n search,\n clearSearch,\n zoomToFit,\n zoomToNode,\n selectNode,\n getSelectedNodes,\n resize: doResize,\n destroy,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Util\n// ---------------------------------------------------------------------------\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n","/**\n * Canvas 2D renderer for force-directed graph visualization.\n *\n * Stateless renderer: receives a GraphRenderState each frame and draws it.\n * Handles DPR scaling, viewport culling, LOD labels, dark mode glow effects,\n * and batched drawing for performance at 10k+ nodes.\n *\n * Performance strategy:\n * - Edges batched by (stroke, strokeWidth, dash) key → one stroke() per group\n * - Nodes batched by fill color → one fill() per color group\n * - Node strokes batched by stroke color\n * - Labels and glow skipped during active pan/zoom gestures\n */\n\nimport { BRAND_FONT_SIZE, BRAND_MIN_WIDTH } from '@opendata-ai/openchart-core';\nimport type { GraphRenderState, PositionedEdge, PositionedNode } from './types';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LABEL_FONT_MIN = 8;\nconst LABEL_FONT_MAX = 12;\nconst EDGE_ALPHA_DEFAULT = 0.35;\nconst EDGE_ALPHA_CONNECTED = 1.0;\nconst EDGE_ALPHA_DIMMED = 0.05;\nconst SEARCH_NON_MATCH_ALPHA = 0.15;\nconst GLOW_NODE_THRESHOLD = 2000;\nconst GLOW_RADIUS_MULTIPLIER = 1.3;\nconst GLOW_ALPHA = 0.15;\nconst CULL_MARGIN = 50;\nconst TWO_PI = Math.PI * 2;\n\n/** Minimum node radius in screen pixels. Keeps nodes visible when zoomed out. */\nconst MIN_SCREEN_RADIUS = 2.5;\n\n// ---------------------------------------------------------------------------\n// Helpers (exported for testing)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute label visibility threshold from zoom level.\n * At zoom 0.2 (zoomed out): threshold ~1.0 (only top ~5% visible).\n * At zoom 2.0+: threshold ~0.0 (all visible).\n */\nexport function labelThreshold(zoom: number): number {\n const t = Math.max(0, Math.min(1, (zoom - 0.2) / 1.8));\n return 1 - t;\n}\n\n/** Compute visible rect in graph coordinates from canvas size + transform. */\nexport function visibleRect(\n canvasWidth: number,\n canvasHeight: number,\n transform: { x: number; y: number; k: number },\n margin: number = CULL_MARGIN,\n): { minX: number; minY: number; maxX: number; maxY: number } {\n const { x, y, k } = transform;\n return {\n minX: (-x - margin) / k,\n minY: (-y - margin) / k,\n maxX: (canvasWidth - x + margin) / k,\n maxY: (canvasHeight - y + margin) / k,\n };\n}\n\n/** Check if a node falls within the visible rect. */\nfunction nodeInView(\n node: PositionedNode,\n rect: { minX: number; minY: number; maxX: number; maxY: number },\n): boolean {\n return (\n node.x + node.radius >= rect.minX &&\n node.x - node.radius <= rect.maxX &&\n node.y + node.radius >= rect.minY &&\n node.y - node.radius <= rect.maxY\n );\n}\n\n/** Check if an edge has at least one endpoint in view. */\nfunction edgeInView(\n edge: PositionedEdge,\n rect: { minX: number; minY: number; maxX: number; maxY: number },\n): boolean {\n return (\n (edge.sourceX >= rect.minX &&\n edge.sourceX <= rect.maxX &&\n edge.sourceY >= rect.minY &&\n edge.sourceY <= rect.maxY) ||\n (edge.targetX >= rect.minX &&\n edge.targetX <= rect.maxX &&\n edge.targetY >= rect.minY &&\n edge.targetY <= rect.maxY)\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dash patterns for edge styles\n// ---------------------------------------------------------------------------\n\nconst DASH_PATTERNS: Record<string, number[]> = {\n solid: [],\n dashed: [6, 4],\n dotted: [2, 3],\n};\n\n// ---------------------------------------------------------------------------\n// GraphCanvasRenderer\n// ---------------------------------------------------------------------------\n\nexport class GraphCanvasRenderer {\n private canvas: HTMLCanvasElement;\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via this-destructuring\n private ctx: CanvasRenderingContext2D;\n private dpr: number;\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via this-destructuring\n private cssWidth = 0;\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via this-destructuring\n private cssHeight = 0;\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.ctx = canvas.getContext('2d')!;\n this.dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n }\n\n /** Update canvas dimensions with DPR scaling. CSS size stays at css values. */\n resize(width: number, height: number): void {\n this.cssWidth = width;\n this.cssHeight = height;\n this.canvas.width = width * this.dpr;\n this.canvas.height = height * this.dpr;\n }\n\n /** Clear canvas and render the full graph state. */\n render(state: GraphRenderState): void {\n const { ctx, dpr, cssWidth, cssHeight } = this;\n const {\n nodes,\n edges,\n transform,\n hoveredNodeId,\n hoveredEdgeId,\n selectedNodeIds,\n adjacencyMap,\n theme,\n searchMatches,\n isGesturing,\n } = state;\n\n const hasActiveNode = hoveredNodeId !== null || selectedNodeIds.size > 0;\n const activeNodeIds = new Set<string>();\n if (hoveredNodeId) activeNodeIds.add(hoveredNodeId);\n for (const id of selectedNodeIds) activeNodeIds.add(id);\n\n // Collect all nodes connected to any active node\n const connectedNodeIds = new Set<string>();\n for (const id of activeNodeIds) {\n connectedNodeIds.add(id);\n const neighbors = adjacencyMap.get(id);\n if (neighbors) {\n for (const nid of neighbors) connectedNodeIds.add(nid);\n }\n }\n\n // Viewport culling\n const rect = visibleRect(cssWidth, cssHeight, transform);\n const visibleNodes = nodes.filter((n) => nodeInView(n, rect));\n const visibleEdges = edges.filter((e) => edgeInView(e, rect));\n\n const isDark = theme.isDark;\n const showGlow = isDark && !isGesturing && visibleNodes.length < GLOW_NODE_THRESHOLD;\n const threshold = labelThreshold(transform.k);\n // Minimum radius in graph coordinates so nodes stay visible when zoomed out\n const minRadius = MIN_SCREEN_RADIUS / transform.k;\n\n // -- Clear and apply transform --\n ctx.save();\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, cssWidth, cssHeight);\n\n // Fill background (skip if transparent to let page background show through)\n if (theme.colors.background !== 'transparent') {\n ctx.fillStyle = theme.colors.background;\n ctx.fillRect(0, 0, cssWidth, cssHeight);\n }\n\n ctx.translate(transform.x, transform.y);\n ctx.scale(transform.k, transform.k);\n\n // -- Draw edges (batched by style key) --\n this.drawEdgesBatched(\n ctx,\n visibleEdges,\n hasActiveNode,\n connectedNodeIds,\n isGesturing ? null : searchMatches,\n hoveredEdgeId,\n );\n\n // -- Draw nodes (batched by fill color) --\n this.drawNodesBatched(\n ctx,\n visibleNodes,\n hoveredNodeId,\n selectedNodeIds,\n isGesturing ? null : searchMatches,\n showGlow,\n theme,\n minRadius,\n );\n\n // -- Draw labels (skipped during gestures) --\n if (!isGesturing) {\n this.drawLabels(\n ctx,\n visibleNodes,\n threshold,\n hoveredNodeId,\n selectedNodeIds,\n searchMatches,\n transform.k,\n theme,\n );\n }\n\n ctx.restore();\n\n // Brand watermark in screen coordinates (unaffected by pan/zoom)\n if (state.watermark) {\n this.drawBrand(ctx, cssWidth, cssHeight, theme);\n }\n }\n\n // -------------------------------------------------------------------------\n // Brand rendering\n // -------------------------------------------------------------------------\n\n private drawBrand(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: GraphRenderState['theme'],\n ): void {\n if (w < BRAND_MIN_WIDTH) return;\n const { dpr } = this;\n ctx.save();\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n const padding = theme.spacing.padding;\n const x = w - padding;\n const y = h - padding;\n ctx.font = `600 ${BRAND_FONT_SIZE}px ${theme.fonts.family}`;\n ctx.fillStyle = theme.colors.axis;\n ctx.globalAlpha = 0.55;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'alphabetic';\n ctx.fillText('tryOpenData.ai', x, y);\n ctx.restore();\n }\n\n // -------------------------------------------------------------------------\n // Batched edge drawing\n // -------------------------------------------------------------------------\n\n private drawEdgesBatched(\n ctx: CanvasRenderingContext2D,\n edges: PositionedEdge[],\n hasActiveNode: boolean,\n connectedNodeIds: Set<string>,\n searchMatches: Set<string> | null,\n hoveredEdgeId: string | null,\n ): void {\n // Classify edges by alpha level, then batch by visual style within each level\n const dimmedEdges: PositionedEdge[] = [];\n const defaultEdges: PositionedEdge[] = [];\n const connectedEdges: PositionedEdge[] = [];\n let hoveredEdge: PositionedEdge | null = null;\n\n for (const edge of edges) {\n const edgeId = `${edge.source}->${edge.target}`;\n if (edgeId === hoveredEdgeId) {\n hoveredEdge = edge;\n continue; // Draw hovered edge last, on top\n }\n\n const isConnected =\n hasActiveNode && connectedNodeIds.has(edge.source) && connectedNodeIds.has(edge.target);\n const isDimmed = hasActiveNode && !isConnected;\n\n if (isConnected) {\n connectedEdges.push(edge);\n } else if (isDimmed) {\n dimmedEdges.push(edge);\n } else {\n defaultEdges.push(edge);\n }\n }\n\n // Draw dimmed first, then default, then connected (on top)\n this.drawEdgeGroupBatched(ctx, dimmedEdges, EDGE_ALPHA_DIMMED, searchMatches);\n this.drawEdgeGroupBatched(ctx, defaultEdges, EDGE_ALPHA_DEFAULT, searchMatches);\n this.drawEdgeGroupBatched(ctx, connectedEdges, EDGE_ALPHA_CONNECTED, searchMatches);\n\n // Draw hovered edge on top with highlight\n if (hoveredEdge) {\n const dash = DASH_PATTERNS[hoveredEdge.style] ?? DASH_PATTERNS.solid;\n ctx.setLineDash(dash);\n ctx.strokeStyle = hoveredEdge.stroke;\n ctx.lineWidth = hoveredEdge.strokeWidth * 2;\n ctx.globalAlpha = EDGE_ALPHA_CONNECTED;\n ctx.beginPath();\n ctx.moveTo(hoveredEdge.sourceX, hoveredEdge.sourceY);\n ctx.lineTo(hoveredEdge.targetX, hoveredEdge.targetY);\n ctx.stroke();\n ctx.setLineDash([]);\n ctx.globalAlpha = 1;\n }\n }\n\n /**\n * Draw a group of edges at a given alpha, batched by (stroke, strokeWidth, style).\n * When search is inactive, all edges of the same style are drawn in a single path.\n * When search is active, edges split by search-match status for alpha dimming.\n */\n private drawEdgeGroupBatched(\n ctx: CanvasRenderingContext2D,\n edges: PositionedEdge[],\n alpha: number,\n searchMatches: Set<string> | null,\n ): void {\n if (edges.length === 0) return;\n\n // Group by visual key: stroke + strokeWidth + style\n const groups = new Map<string, PositionedEdge[]>();\n for (const edge of edges) {\n const key = `${edge.stroke}|${edge.strokeWidth}|${edge.style}`;\n let group = groups.get(key);\n if (!group) {\n group = [];\n groups.set(key, group);\n }\n group.push(edge);\n }\n\n for (const [, group] of groups) {\n const sample = group[0];\n const dash = DASH_PATTERNS[sample.style] ?? DASH_PATTERNS.solid;\n ctx.setLineDash(dash);\n ctx.strokeStyle = sample.stroke;\n ctx.lineWidth = sample.strokeWidth;\n\n if (!searchMatches) {\n // Fast path: single batched path for all edges in this group\n ctx.globalAlpha = alpha;\n ctx.beginPath();\n for (const edge of group) {\n ctx.moveTo(edge.sourceX, edge.sourceY);\n ctx.lineTo(edge.targetX, edge.targetY);\n }\n ctx.stroke();\n } else {\n // Search active: split into matched and non-matched batches\n ctx.globalAlpha = alpha;\n ctx.beginPath();\n let hasMatched = false;\n\n const nonMatchPath: PositionedEdge[] = [];\n\n for (const edge of group) {\n const srcMatch = searchMatches.has(edge.source);\n const tgtMatch = searchMatches.has(edge.target);\n if (srcMatch || tgtMatch) {\n ctx.moveTo(edge.sourceX, edge.sourceY);\n ctx.lineTo(edge.targetX, edge.targetY);\n hasMatched = true;\n } else {\n nonMatchPath.push(edge);\n }\n }\n if (hasMatched) ctx.stroke();\n\n // Draw non-matching edges dimmed\n if (nonMatchPath.length > 0) {\n ctx.globalAlpha = SEARCH_NON_MATCH_ALPHA * alpha;\n ctx.beginPath();\n for (const edge of nonMatchPath) {\n ctx.moveTo(edge.sourceX, edge.sourceY);\n ctx.lineTo(edge.targetX, edge.targetY);\n }\n ctx.stroke();\n }\n }\n }\n\n ctx.setLineDash([]);\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Batched node drawing\n // -------------------------------------------------------------------------\n\n private drawNodesBatched(\n ctx: CanvasRenderingContext2D,\n nodes: PositionedNode[],\n hoveredNodeId: string | null,\n selectedNodeIds: Set<string>,\n searchMatches: Set<string> | null,\n showGlow: boolean,\n theme: GraphRenderState['theme'],\n minRadius: number,\n ): void {\n // Separate special nodes (hovered/selected) from bulk nodes.\n // Special nodes need individual treatment; bulk nodes get batched by color.\n const bulkNodes: PositionedNode[] = [];\n const specialNodes: PositionedNode[] = [];\n\n for (const node of nodes) {\n if (node.id === hoveredNodeId || selectedNodeIds.has(node.id)) {\n specialNodes.push(node);\n } else {\n bulkNodes.push(node);\n }\n }\n\n // Helper: effective radius clamped to minimum screen size\n const r = (node: PositionedNode) => Math.max(node.radius, minRadius);\n\n // --- Glow pass (dark mode only, before fills) ---\n if (showGlow) {\n this.drawGlowBatched(ctx, bulkNodes, searchMatches, minRadius);\n }\n\n // --- Bulk fill pass: batch by fill color ---\n const fillGroups = new Map<string, PositionedNode[]>();\n for (const node of bulkNodes) {\n let group = fillGroups.get(node.fill);\n if (!group) {\n group = [];\n fillGroups.set(node.fill, group);\n }\n group.push(node);\n }\n\n if (!searchMatches) {\n // Fast path: no search dimming\n ctx.globalAlpha = 1;\n for (const [fill, group] of fillGroups) {\n ctx.fillStyle = fill;\n ctx.beginPath();\n for (const node of group) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.fill();\n }\n } else {\n // Search active: split each color group into matched/dimmed batches\n for (const [fill, group] of fillGroups) {\n ctx.fillStyle = fill;\n\n // Matched nodes\n ctx.globalAlpha = 1;\n ctx.beginPath();\n let hasMatched = false;\n const dimmedNodes: PositionedNode[] = [];\n\n for (const node of group) {\n if (searchMatches.has(node.id)) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n hasMatched = true;\n } else {\n dimmedNodes.push(node);\n }\n }\n if (hasMatched) ctx.fill();\n\n // Dimmed nodes\n if (dimmedNodes.length > 0) {\n ctx.globalAlpha = SEARCH_NON_MATCH_ALPHA;\n ctx.beginPath();\n for (const node of dimmedNodes) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.fill();\n }\n }\n }\n\n // --- Bulk stroke pass: batch by stroke color ---\n const strokeGroups = new Map<string, PositionedNode[]>();\n for (const node of bulkNodes) {\n const key = `${node.stroke}|${node.strokeWidth}`;\n let group = strokeGroups.get(key);\n if (!group) {\n group = [];\n strokeGroups.set(key, group);\n }\n group.push(node);\n }\n\n for (const [key, group] of strokeGroups) {\n const [stroke, widthStr] = key.split('|');\n ctx.strokeStyle = stroke;\n ctx.lineWidth = parseFloat(widthStr);\n\n if (!searchMatches) {\n ctx.globalAlpha = 1;\n ctx.beginPath();\n for (const node of group) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.stroke();\n } else {\n // Split matched/dimmed for strokes too\n ctx.globalAlpha = 1;\n ctx.beginPath();\n let hasMatched = false;\n const dimmedNodes: PositionedNode[] = [];\n\n for (const node of group) {\n if (searchMatches.has(node.id)) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n hasMatched = true;\n } else {\n dimmedNodes.push(node);\n }\n }\n if (hasMatched) ctx.stroke();\n\n if (dimmedNodes.length > 0) {\n ctx.globalAlpha = SEARCH_NON_MATCH_ALPHA;\n ctx.beginPath();\n for (const node of dimmedNodes) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.stroke();\n }\n }\n }\n\n // --- Special nodes (hovered/selected) drawn individually ---\n for (const node of specialNodes) {\n const isHovered = node.id === hoveredNodeId;\n const isSelected = selectedNodeIds.has(node.id);\n const dimmed = searchMatches !== null && !searchMatches.has(node.id);\n const baseRadius = Math.max(node.radius, minRadius);\n const radius = isHovered ? baseRadius * 1.15 : baseRadius;\n\n ctx.globalAlpha = dimmed ? SEARCH_NON_MATCH_ALPHA : 1;\n\n // Glow for special nodes\n if (showGlow && !dimmed) {\n ctx.beginPath();\n ctx.arc(node.x, node.y, radius * GLOW_RADIUS_MULTIPLIER, 0, TWO_PI);\n ctx.fillStyle = node.fill;\n ctx.globalAlpha = GLOW_ALPHA;\n ctx.fill();\n ctx.globalAlpha = dimmed ? SEARCH_NON_MATCH_ALPHA : 1;\n }\n\n // Fill\n ctx.beginPath();\n ctx.arc(node.x, node.y, radius, 0, TWO_PI);\n ctx.fillStyle = isHovered ? brighten(node.fill) : node.fill;\n ctx.fill();\n\n // Stroke\n ctx.strokeStyle = node.stroke;\n ctx.lineWidth = node.strokeWidth;\n ctx.stroke();\n\n // Selection ring\n if (isSelected) {\n ctx.beginPath();\n ctx.arc(node.x, node.y, radius + 3, 0, TWO_PI);\n ctx.strokeStyle = theme.colors.categorical[0] ?? '#3b82f6';\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n }\n\n ctx.globalAlpha = 1;\n }\n\n /** Batch glow circles by fill color. */\n private drawGlowBatched(\n ctx: CanvasRenderingContext2D,\n nodes: PositionedNode[],\n searchMatches: Set<string> | null,\n minRadius: number,\n ): void {\n const glowGroups = new Map<string, PositionedNode[]>();\n for (const node of nodes) {\n if (searchMatches && !searchMatches.has(node.id)) continue;\n let group = glowGroups.get(node.fill);\n if (!group) {\n group = [];\n glowGroups.set(node.fill, group);\n }\n group.push(node);\n }\n\n ctx.globalAlpha = GLOW_ALPHA;\n for (const [fill, group] of glowGroups) {\n ctx.fillStyle = fill;\n ctx.beginPath();\n for (const node of group) {\n const gr = Math.max(node.radius, minRadius) * GLOW_RADIUS_MULTIPLIER;\n ctx.moveTo(node.x + gr, node.y);\n ctx.arc(node.x, node.y, gr, 0, TWO_PI);\n }\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Labels (drawn individually, skipped during gestures)\n // -------------------------------------------------------------------------\n\n private drawLabels(\n ctx: CanvasRenderingContext2D,\n nodes: PositionedNode[],\n threshold: number,\n hoveredNodeId: string | null,\n selectedNodeIds: Set<string>,\n searchMatches: Set<string> | null,\n zoom: number,\n theme: GraphRenderState['theme'],\n ): void {\n // Font size inversely scaled by zoom, clamped to readable range\n const rawSize = 10 / zoom;\n const fontSize = Math.max(LABEL_FONT_MIN, Math.min(LABEL_FONT_MAX, rawSize));\n\n ctx.font = `${fontSize}px ${theme.fonts.family}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'top';\n\n for (const node of nodes) {\n if (!node.label) continue;\n\n const isHovered = node.id === hoveredNodeId;\n const isSelected = selectedNodeIds.has(node.id);\n const forced = isHovered || isSelected;\n const dimmed = searchMatches !== null && !searchMatches.has(node.id);\n\n // LOD: skip labels below threshold unless forced\n if (!forced && node.labelPriority < threshold) continue;\n\n ctx.globalAlpha = dimmed ? SEARCH_NON_MATCH_ALPHA : 1;\n\n const labelY = node.y + node.radius + 3;\n\n // Halo for readability: stroke behind text in the background color\n // so labels stay legible over edges and other nodes.\n if (theme.colors.background !== 'transparent') {\n ctx.strokeStyle = theme.colors.background;\n } else {\n // Transparent bg: infer page background from text luminance.\n // Light text = dark page, dark text = light page.\n ctx.strokeStyle = isLightColor(theme.colors.text)\n ? 'rgba(0, 0, 0, 0.7)'\n : 'rgba(255, 255, 255, 0.85)';\n }\n ctx.lineWidth = 3;\n ctx.lineJoin = 'round';\n ctx.miterLimit = 2;\n ctx.strokeText(node.label, node.x, labelY);\n\n ctx.fillStyle = theme.colors.text;\n ctx.fillText(node.label, node.x, labelY);\n }\n\n ctx.globalAlpha = 1;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Color helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Brighten a hex/rgb color by ~20% for hover effect.\n * Quick and dirty approach: parse hex, lighten each channel.\n */\nfunction brighten(color: string): string {\n // Handle rgb(r,g,b) or rgb(r, g, b)\n const rgbMatch = color.match(/^rgb\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/);\n if (rgbMatch) {\n const r = Math.min(255, parseInt(rgbMatch[1], 10) + 40);\n const g = Math.min(255, parseInt(rgbMatch[2], 10) + 40);\n const b = Math.min(255, parseInt(rgbMatch[3], 10) + 40);\n return `rgb(${r},${g},${b})`;\n }\n\n // Handle hex colors (#rgb and #rrggbb)\n const hex = color.replace('#', '');\n const full =\n hex.length === 3\n ? hex\n .split('')\n .map((c) => c + c)\n .join('')\n : hex;\n\n if (full.length === 6) {\n const r = Math.min(255, parseInt(full.slice(0, 2), 16) + 40);\n const g = Math.min(255, parseInt(full.slice(2, 4), 16) + 40);\n const b = Math.min(255, parseInt(full.slice(4, 6), 16) + 40);\n return `rgb(${r},${g},${b})`;\n }\n\n return color;\n}\n\n/**\n * Returns true if a color is perceptually light (luminance > 0.5).\n * Used to pick a contrasting halo color for labels on transparent backgrounds.\n */\nfunction isLightColor(color: string): boolean {\n const hex = color.replace('#', '');\n const full =\n hex.length === 3\n ? hex\n .split('')\n .map((c) => c + c)\n .join('')\n : hex;\n if (full.length !== 6) return false;\n const r = parseInt(full.slice(0, 2), 16) / 255;\n const g = parseInt(full.slice(2, 4), 16) / 255;\n const b = parseInt(full.slice(4, 6), 16) / 255;\n const toLinear = (c: number) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);\n return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b) > 0.5;\n}\n","/**\n * Immutable zoom transform for graph pan/zoom.\n *\n * Provides coordinate conversion between screen space (canvas pixels)\n * and graph space (simulation coordinates). All mutations return new\n * instances rather than modifying in place.\n */\n\nimport type { PositionedNode } from './types';\n\nexport class ZoomTransform {\n constructor(\n readonly x: number,\n readonly y: number,\n readonly k: number,\n ) {}\n\n /** Convert screen coordinates to graph coordinates. */\n screenToGraph(sx: number, sy: number): { x: number; y: number } {\n return {\n x: (sx - this.x) / this.k,\n y: (sy - this.y) / this.k,\n };\n }\n\n /** Convert graph coordinates to screen coordinates. */\n graphToScreen(gx: number, gy: number): { x: number; y: number } {\n return {\n x: gx * this.k + this.x,\n y: gy * this.k + this.y,\n };\n }\n\n /**\n * Zoom to a target scale, keeping the given screen-space pivot\n * point fixed (content under the cursor stays under the cursor).\n */\n zoomAt(targetK: number, pivotX: number, pivotY: number): ZoomTransform {\n // The graph point under the pivot should remain at the same screen position.\n // Before: pivotX = gx * k + x => gx = (pivotX - x) / k\n // After: pivotX = gx * targetK + newX => newX = pivotX - gx * targetK\n const gx = (pivotX - this.x) / this.k;\n const gy = (pivotY - this.y) / this.k;\n return new ZoomTransform(pivotX - gx * targetK, pivotY - gy * targetK, targetK);\n }\n\n /** Pan by a screen-space delta. */\n pan(dx: number, dy: number): ZoomTransform {\n return new ZoomTransform(this.x + dx, this.y + dy, this.k);\n }\n\n /**\n * Compute a transform that fits all nodes within the given canvas\n * dimensions with the specified padding.\n *\n * Returns the transform and the ideal content height (in screen pixels)\n * so callers can shrink the canvas to eliminate dead space.\n */\n static fitBounds(\n nodes: PositionedNode[],\n canvasW: number,\n canvasH: number,\n padding: number = 40,\n ): { transform: ZoomTransform; contentHeight: number } {\n if (nodes.length === 0) {\n return { transform: ZoomTransform.identity(), contentHeight: canvasH };\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const n of nodes) {\n const r = n.radius;\n if (n.x - r < minX) minX = n.x - r;\n if (n.y - r < minY) minY = n.y - r;\n if (n.x + r > maxX) maxX = n.x + r;\n if (n.y + r > maxY) maxY = n.y + r;\n }\n\n let graphW = maxX - minX;\n let graphH = maxY - minY;\n\n if (graphW === 0 && graphH === 0) {\n // All nodes at the same point; just center\n return {\n transform: new ZoomTransform(canvasW / 2 - minX, canvasH / 2 - minY, 1),\n contentHeight: padding * 2,\n };\n }\n\n // When called early in the simulation (first tick), the bounding box\n // underestimates the final spread. Apply a spread multiplier based on\n // node count: larger graphs expand more as charge forces push nodes\n // apart over subsequent ticks. The sqrt scaling mirrors how d3-force\n // charge repulsion grows with node count.\n if (nodes.length > 50) {\n const spread = 1 + Math.sqrt(nodes.length) / 120;\n const cx = (minX + maxX) / 2;\n const cy = (minY + maxY) / 2;\n graphW *= spread;\n graphH *= spread;\n minX = cx - graphW / 2;\n maxX = cx + graphW / 2;\n minY = cy - graphH / 2;\n maxY = cy + graphH / 2;\n }\n\n const availW = canvasW - padding * 2;\n const availH = canvasH - padding * 2;\n // Cap at 1 so the graph never renders larger than its natural size\n const k = Math.min(1, availW / graphW, availH / graphH);\n\n // Center both axes so the graph sits in the middle of the viewport\n const cx = (minX + maxX) / 2;\n const cy = (minY + maxY) / 2;\n const tx = canvasW / 2 - cx * k;\n const ty = canvasH / 2 - cy * k;\n\n // Content height = scaled graph extent + top and bottom padding\n const contentHeight = graphH * k + padding * 2;\n\n return {\n transform: new ZoomTransform(tx, ty, k),\n contentHeight,\n };\n }\n\n /** Identity transform (no pan, no zoom). */\n static identity(): ZoomTransform {\n return new ZoomTransform(0, 0, 1);\n }\n}\n","/**\n * Graph interaction manager.\n *\n * Handles mouse/touch events on the canvas and translates them into\n * high-level graph interactions: pan, zoom, hover, select, drag nodes.\n * Uses the spatial index for hit testing and ZoomTransform for coordinate\n * conversion.\n */\n\nimport type { SpatialIndex } from './spatial-index';\nimport { ZoomTransform } from './zoom';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst ZOOM_MIN = 0.05;\nconst ZOOM_MAX = 15;\nconst ZOOM_STEP = -0.001;\nconst HIT_DISTANCE = 5;\n\n// ---------------------------------------------------------------------------\n// Callback interface\n// ---------------------------------------------------------------------------\n\nexport interface InteractionCallbacks {\n onTransformChange(transform: ZoomTransform): void;\n onHoverChange(nodeId: string | null): void;\n /** Called during mouse move when no node is hit, with graph-space coordinates for edge hit testing. */\n onBackgroundHover?(graphX: number, graphY: number, screenX: number, screenY: number): void;\n onSelectionChange(nodeIds: string[]): void;\n onNodeDragStart(nodeId: string): void;\n onNodeDrag(nodeId: string, x: number, y: number): void;\n onNodeDragEnd(nodeId: string): void;\n onDoubleClick(nodeId: string): void;\n}\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\ninterface DragState {\n nodeId: string;\n started: boolean;\n}\n\ninterface PanState {\n startX: number;\n startY: number;\n}\n\n// ---------------------------------------------------------------------------\n// GraphInteractionManager\n// ---------------------------------------------------------------------------\n\nexport class GraphInteractionManager {\n private canvas: HTMLCanvasElement;\n private spatialIndex: SpatialIndex;\n private callbacks: InteractionCallbacks;\n private transform = ZoomTransform.identity();\n\n private dragState: DragState | null = null;\n private panState: PanState | null = null;\n private mousedownNodeId: string | null = null;\n private selectedIds: Set<string> = new Set();\n\n // Touch state\n private lastTouchDist: number | null = null;\n private lastTouchCenter: { x: number; y: number } | null = null;\n\n // Bound handlers for cleanup\n private boundWheel: (e: WheelEvent) => void;\n private boundMouseDown: (e: MouseEvent) => void;\n private boundMouseMove: (e: MouseEvent) => void;\n private boundMouseUp: (e: MouseEvent) => void;\n private boundDblClick: (e: MouseEvent) => void;\n private boundTouchStart: (e: TouchEvent) => void;\n private boundTouchMove: (e: TouchEvent) => void;\n private boundTouchEnd: (e: TouchEvent) => void;\n private boundMouseLeave: (e: MouseEvent) => void;\n\n constructor(\n canvas: HTMLCanvasElement,\n spatialIndex: SpatialIndex,\n callbacks: InteractionCallbacks,\n ) {\n this.canvas = canvas;\n this.spatialIndex = spatialIndex;\n this.callbacks = callbacks;\n\n // Bind handlers\n this.boundWheel = this.onWheel.bind(this);\n this.boundMouseDown = this.onMouseDown.bind(this);\n this.boundMouseMove = this.onMouseMove.bind(this);\n this.boundMouseUp = this.onMouseUp.bind(this);\n this.boundMouseLeave = this.onMouseLeave.bind(this);\n this.boundDblClick = this.onDblClick.bind(this);\n this.boundTouchStart = this.onTouchStart.bind(this);\n this.boundTouchMove = this.onTouchMove.bind(this);\n this.boundTouchEnd = this.onTouchEnd.bind(this);\n\n // Attach event listeners\n canvas.addEventListener('wheel', this.boundWheel, { passive: false });\n canvas.addEventListener('mousedown', this.boundMouseDown);\n canvas.addEventListener('mousemove', this.boundMouseMove);\n canvas.addEventListener('mouseup', this.boundMouseUp);\n canvas.addEventListener('mouseleave', this.boundMouseLeave);\n canvas.addEventListener('dblclick', this.boundDblClick);\n canvas.addEventListener('touchstart', this.boundTouchStart, {\n passive: false,\n });\n canvas.addEventListener('touchmove', this.boundTouchMove, {\n passive: false,\n });\n canvas.addEventListener('touchend', this.boundTouchEnd);\n }\n\n setTransform(transform: ZoomTransform): void {\n this.transform = transform;\n }\n\n getTransform(): ZoomTransform {\n return this.transform;\n }\n\n destroy(): void {\n this.canvas.removeEventListener('wheel', this.boundWheel);\n this.canvas.removeEventListener('mousedown', this.boundMouseDown);\n this.canvas.removeEventListener('mousemove', this.boundMouseMove);\n this.canvas.removeEventListener('mouseup', this.boundMouseUp);\n this.canvas.removeEventListener('mouseleave', this.boundMouseLeave);\n this.canvas.removeEventListener('dblclick', this.boundDblClick);\n this.canvas.removeEventListener('touchstart', this.boundTouchStart);\n this.canvas.removeEventListener('touchmove', this.boundTouchMove);\n this.canvas.removeEventListener('touchend', this.boundTouchEnd);\n }\n\n // -------------------------------------------------------------------------\n // Mouse handlers\n // -------------------------------------------------------------------------\n\n private canvasXY(e: MouseEvent): { x: number; y: number } {\n const rect = this.canvas.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n }\n\n private hitTest(screenX: number, screenY: number): string | null {\n const graph = this.transform.screenToGraph(screenX, screenY);\n const node = this.spatialIndex.findNearest(graph.x, graph.y, HIT_DISTANCE / this.transform.k);\n return node?.id ?? null;\n }\n\n private onWheel(e: WheelEvent): void {\n e.preventDefault();\n const { x, y } = this.canvasXY(e);\n const factor = e.deltaY * ZOOM_STEP;\n const newK = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, this.transform.k * (1 + factor)));\n this.transform = this.transform.zoomAt(newK, x, y);\n this.callbacks.onTransformChange(this.transform);\n }\n\n private onMouseDown(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n const hitId = this.hitTest(x, y);\n\n if (hitId) {\n // Start potential node drag\n this.dragState = { nodeId: hitId, started: false };\n this.mousedownNodeId = hitId;\n } else {\n // Start pan\n this.panState = { startX: x, startY: y };\n this.mousedownNodeId = null;\n }\n }\n\n private onMouseMove(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n\n if (this.dragState) {\n const graph = this.transform.screenToGraph(x, y);\n if (!this.dragState.started) {\n this.dragState.started = true;\n this.callbacks.onNodeDragStart(this.dragState.nodeId);\n }\n this.callbacks.onNodeDrag(this.dragState.nodeId, graph.x, graph.y);\n return;\n }\n\n if (this.panState) {\n const dx = x - this.panState.startX;\n const dy = y - this.panState.startY;\n this.transform = this.transform.pan(dx, dy);\n this.panState = { startX: x, startY: y };\n this.callbacks.onTransformChange(this.transform);\n return;\n }\n\n // Hover detection\n const hitId = this.hitTest(x, y);\n this.callbacks.onHoverChange(hitId);\n\n // If no node hit, check edges via callback\n if (!hitId) {\n const graph = this.transform.screenToGraph(x, y);\n this.callbacks.onBackgroundHover?.(graph.x, graph.y, x, y);\n }\n\n // Update cursor\n this.canvas.style.cursor = hitId ? 'pointer' : 'default';\n }\n\n private onMouseUp(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n\n if (this.dragState) {\n if (this.dragState.started) {\n this.callbacks.onNodeDragEnd(this.dragState.nodeId);\n } else {\n // Was a click on a node (no drag movement)\n this.handleNodeClick(this.dragState.nodeId, e.shiftKey);\n }\n this.dragState = null;\n return;\n }\n\n if (this.panState) {\n this.panState = null;\n\n // If mouse up is on background (no node), treat as background click\n if (!this.mousedownNodeId) {\n const hitId = this.hitTest(x, y);\n if (!hitId) {\n // Background click: clear selection\n this.selectedIds.clear();\n this.callbacks.onSelectionChange([]);\n }\n }\n return;\n }\n }\n\n private onDblClick(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n const hitId = this.hitTest(x, y);\n if (hitId) {\n this.callbacks.onDoubleClick(hitId);\n }\n }\n\n private onMouseLeave(_e: MouseEvent): void {\n this.callbacks.onHoverChange(null);\n this.canvas.style.cursor = 'default';\n\n // Cancel any in-progress pan\n if (this.panState) {\n this.panState = null;\n }\n }\n\n private handleNodeClick(nodeId: string, shiftKey: boolean): void {\n if (shiftKey) {\n // Toggle node in multi-select\n if (this.selectedIds.has(nodeId)) {\n this.selectedIds.delete(nodeId);\n } else {\n this.selectedIds.add(nodeId);\n }\n } else {\n // Single select\n this.selectedIds.clear();\n this.selectedIds.add(nodeId);\n }\n\n this.callbacks.onSelectionChange([...this.selectedIds]);\n }\n\n // -------------------------------------------------------------------------\n // Touch handlers\n // -------------------------------------------------------------------------\n\n private onTouchStart(e: TouchEvent): void {\n e.preventDefault();\n\n if (e.touches.length === 2) {\n // Pinch-zoom start\n const [t0, t1] = [e.touches[0], e.touches[1]];\n this.lastTouchDist = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);\n this.lastTouchCenter = {\n x: (t0.clientX + t1.clientX) / 2,\n y: (t0.clientY + t1.clientY) / 2,\n };\n } else if (e.touches.length === 1) {\n const touch = e.touches[0];\n const rect = this.canvas.getBoundingClientRect();\n const x = touch.clientX - rect.left;\n const y = touch.clientY - rect.top;\n\n const hitId = this.hitTest(x, y);\n if (hitId) {\n this.mousedownNodeId = hitId;\n } else {\n this.panState = { startX: x, startY: y };\n this.mousedownNodeId = null;\n }\n }\n }\n\n private onTouchMove(e: TouchEvent): void {\n e.preventDefault();\n\n if (e.touches.length === 2 && this.lastTouchDist !== null) {\n const [t0, t1] = [e.touches[0], e.touches[1]];\n const newDist = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);\n const rect = this.canvas.getBoundingClientRect();\n const centerX = (t0.clientX + t1.clientX) / 2 - rect.left;\n const centerY = (t0.clientY + t1.clientY) / 2 - rect.top;\n\n const scale = newDist / this.lastTouchDist;\n const newK = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, this.transform.k * scale));\n this.transform = this.transform.zoomAt(newK, centerX, centerY);\n\n // Pan from center movement\n if (this.lastTouchCenter) {\n const dx = centerX - (this.lastTouchCenter.x - rect.left);\n const dy = centerY - (this.lastTouchCenter.y - rect.top);\n this.transform = this.transform.pan(dx, dy);\n }\n\n this.lastTouchDist = newDist;\n this.lastTouchCenter = {\n x: (t0.clientX + t1.clientX) / 2,\n y: (t0.clientY + t1.clientY) / 2,\n };\n this.callbacks.onTransformChange(this.transform);\n } else if (e.touches.length === 1 && this.panState) {\n const touch = e.touches[0];\n const rect = this.canvas.getBoundingClientRect();\n const x = touch.clientX - rect.left;\n const y = touch.clientY - rect.top;\n\n const dx = x - this.panState.startX;\n const dy = y - this.panState.startY;\n this.transform = this.transform.pan(dx, dy);\n this.panState = { startX: x, startY: y };\n this.callbacks.onTransformChange(this.transform);\n }\n }\n\n private onTouchEnd(e: TouchEvent): void {\n if (e.touches.length === 0) {\n // Tap-select\n if (this.mousedownNodeId && !this.panState) {\n this.handleNodeClick(this.mousedownNodeId, false);\n } else if (!this.mousedownNodeId && this.panState) {\n // Background tap: clear selection\n this.selectedIds.clear();\n this.callbacks.onSelectionChange([]);\n }\n\n this.panState = null;\n this.mousedownNodeId = null;\n this.lastTouchDist = null;\n this.lastTouchCenter = null;\n }\n }\n}\n","/**\n * Keyboard navigation for the graph canvas.\n *\n * Provides accessible keyboard control: Tab to focus, arrow keys to\n * navigate between adjacent nodes (following edges), Enter to select,\n * Escape to clear, +/- to zoom, Home to fit all, / to focus search.\n */\n\nimport type { PositionedNode } from './types';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface KeyboardNavOptions {\n canvas: HTMLCanvasElement;\n getNodes(): PositionedNode[];\n getSelectedIds(): string[];\n getAdjacency(): Map<string, Set<string>>;\n onSelect(nodeId: string): void;\n onDeselect(): void;\n onZoom(direction: 'in' | 'out'): void;\n onFitAll(): void;\n onFocusSearch?(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Attach keyboard navigation to a graph canvas.\n * Returns a cleanup function that removes all listeners.\n */\nexport function attachGraphKeyboardNav(options: KeyboardNavOptions): () => void {\n const {\n canvas,\n getNodes,\n getSelectedIds,\n getAdjacency,\n onSelect,\n onDeselect,\n onZoom,\n onFitAll,\n onFocusSearch,\n } = options;\n\n let focusedNodeId: string | null = null;\n\n // Make canvas focusable\n if (!canvas.hasAttribute('tabindex')) {\n canvas.setAttribute('tabindex', '0');\n }\n\n function findNodeById(id: string): PositionedNode | undefined {\n return getNodes().find((n) => n.id === id);\n }\n\n /**\n * Given a set of neighbor node ids, pick the one that best matches\n * the arrow key direction relative to the current focused node.\n */\n function pickDirectionalNeighbor(\n fromNode: PositionedNode,\n neighborIds: Set<string>,\n direction: 'up' | 'down' | 'left' | 'right',\n ): string | null {\n const nodes = getNodes();\n const candidates = nodes.filter((n) => neighborIds.has(n.id));\n if (candidates.length === 0) return null;\n\n // Score each candidate by how well it matches the desired direction\n let best: PositionedNode | null = null;\n let bestScore = -Infinity;\n\n for (const c of candidates) {\n const dx = c.x - fromNode.x;\n const dy = c.y - fromNode.y;\n let score: number;\n\n switch (direction) {\n case 'right':\n score = dx - Math.abs(dy) * 0.5;\n break;\n case 'left':\n score = -dx - Math.abs(dy) * 0.5;\n break;\n case 'down':\n score = dy - Math.abs(dx) * 0.5;\n break;\n case 'up':\n score = -dy - Math.abs(dx) * 0.5;\n break;\n }\n\n if (score > bestScore) {\n bestScore = score;\n best = c;\n }\n }\n\n return best?.id ?? null;\n }\n\n function onKeyDown(e: KeyboardEvent): void {\n switch (e.key) {\n case 'Tab': {\n // Focus first/selected node\n const selected = getSelectedIds();\n const nodes = getNodes();\n if (nodes.length === 0) return;\n\n if (selected.length > 0) {\n focusedNodeId = selected[0];\n } else if (!focusedNodeId || !findNodeById(focusedNodeId)) {\n focusedNodeId = nodes[0].id;\n }\n\n e.preventDefault();\n break;\n }\n\n case 'ArrowUp':\n case 'ArrowDown':\n case 'ArrowLeft':\n case 'ArrowRight': {\n if (!focusedNodeId) return;\n e.preventDefault();\n\n const focusedNode = findNodeById(focusedNodeId);\n if (!focusedNode) return;\n\n const adjacency = getAdjacency();\n const neighbors = adjacency.get(focusedNodeId);\n if (!neighbors || neighbors.size === 0) return;\n\n const dirMap: Record<string, 'up' | 'down' | 'left' | 'right'> = {\n ArrowUp: 'up',\n ArrowDown: 'down',\n ArrowLeft: 'left',\n ArrowRight: 'right',\n };\n\n const nextId = pickDirectionalNeighbor(focusedNode, neighbors, dirMap[e.key]);\n if (nextId) {\n focusedNodeId = nextId;\n onSelect(nextId);\n }\n break;\n }\n\n case 'Enter': {\n if (focusedNodeId) {\n e.preventDefault();\n const selected = getSelectedIds();\n if (selected.includes(focusedNodeId)) {\n onDeselect();\n } else {\n onSelect(focusedNodeId);\n }\n }\n break;\n }\n\n case 'Escape': {\n e.preventDefault();\n focusedNodeId = null;\n onDeselect();\n break;\n }\n\n case '+':\n case '=': {\n e.preventDefault();\n onZoom('in');\n break;\n }\n\n case '-':\n case '_': {\n e.preventDefault();\n onZoom('out');\n break;\n }\n\n case 'Home': {\n e.preventDefault();\n onFitAll();\n break;\n }\n\n case '/': {\n if (onFocusSearch) {\n e.preventDefault();\n onFocusSearch();\n }\n break;\n }\n }\n }\n\n canvas.addEventListener('keydown', onKeyDown);\n\n // Return cleanup function\n return () => {\n canvas.removeEventListener('keydown', onKeyDown);\n };\n}\n","/**\n * Graph search manager.\n *\n * Provides case-insensitive substring matching against node labels/ids.\n * Returns a Set of matching node ids that the renderer uses to dim\n * non-matching nodes and edges.\n */\n\nexport class GraphSearchManager {\n private matchedIds: Set<string> | null = null;\n\n /**\n * Search for nodes matching the query string.\n * Returns a Set of matching node ids, or an empty set if nothing matches.\n */\n search(query: string, nodes: Array<{ id: string; label?: string }>): Set<string> {\n const q = query.toLowerCase().trim();\n\n if (q === '') {\n this.matchedIds = null;\n return new Set();\n }\n\n const matches = new Set<string>();\n for (const node of nodes) {\n const label = (node.label ?? '').toLowerCase();\n const id = node.id.toLowerCase();\n if (label.includes(q) || id.includes(q)) {\n matches.add(node.id);\n }\n }\n\n this.matchedIds = matches;\n return matches;\n }\n\n /**\n * Clear the current search.\n * Returns null to indicate no active search.\n */\n clearSearch(): Set<string> | null {\n this.matchedIds = null;\n return null;\n }\n\n /** Get the current set of matched ids, or null if no search is active. */\n getMatches(): Set<string> | null {\n return this.matchedIds;\n }\n}\n","export default function(x, y) {\n var nodes, strength = 1;\n\n if (x == null) x = 0;\n if (y == null) y = 0;\n\n function force() {\n var i,\n n = nodes.length,\n node,\n sx = 0,\n sy = 0;\n\n for (i = 0; i < n; ++i) {\n node = nodes[i], sx += node.x, sy += node.y;\n }\n\n for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, i = 0; i < n; ++i) {\n node = nodes[i], node.x -= sx, node.y -= sy;\n }\n }\n\n force.initialize = function(_) {\n nodes = _;\n };\n\n force.x = function(_) {\n return arguments.length ? (x = +_, force) : x;\n };\n\n force.y = function(_) {\n return arguments.length ? (y = +_, force) : y;\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = +_, force) : strength;\n };\n\n return force;\n}\n","export default function(d) {\n const x = +this._x.call(null, d),\n y = +this._y.call(null, d);\n return add(this.cover(x, y), x, y, d);\n}\n\nfunction add(tree, x, y, d) {\n if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points\n\n var parent,\n node = tree._root,\n leaf = {data: d},\n x0 = tree._x0,\n y0 = tree._y0,\n x1 = tree._x1,\n y1 = tree._y1,\n xm,\n ym,\n xp,\n yp,\n right,\n bottom,\n i,\n j;\n\n // If the tree is empty, initialize the root as a leaf.\n if (!node) return tree._root = leaf, tree;\n\n // Find the existing leaf for the new point, or add it.\n while (node.length) {\n if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;\n if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;\n if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;\n }\n\n // Is the new point is exactly coincident with the existing point?\n xp = +tree._x.call(null, node.data);\n yp = +tree._y.call(null, node.data);\n if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;\n\n // Otherwise, split the leaf node until the old and new point are separated.\n do {\n parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);\n if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;\n if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;\n } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));\n return parent[j] = node, parent[i] = leaf, tree;\n}\n\nexport function addAll(data) {\n var d, i, n = data.length,\n x,\n y,\n xz = new Array(n),\n yz = new Array(n),\n x0 = Infinity,\n y0 = Infinity,\n x1 = -Infinity,\n y1 = -Infinity;\n\n // Compute the points and their extent.\n for (i = 0; i < n; ++i) {\n if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;\n xz[i] = x;\n yz[i] = y;\n if (x < x0) x0 = x;\n if (x > x1) x1 = x;\n if (y < y0) y0 = y;\n if (y > y1) y1 = y;\n }\n\n // If there were no (valid) points, abort.\n if (x0 > x1 || y0 > y1) return this;\n\n // Expand the tree to cover the new points.\n this.cover(x0, y0).cover(x1, y1);\n\n // Add the new points.\n for (i = 0; i < n; ++i) {\n add(this, xz[i], yz[i], data[i]);\n }\n\n return this;\n}\n","export default function(x, y) {\n if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points\n\n var x0 = this._x0,\n y0 = this._y0,\n x1 = this._x1,\n y1 = this._y1;\n\n // If the quadtree has no extent, initialize them.\n // Integer extent are necessary so that if we later double the extent,\n // the existing quadrant boundaries don’t change due to floating point error!\n if (isNaN(x0)) {\n x1 = (x0 = Math.floor(x)) + 1;\n y1 = (y0 = Math.floor(y)) + 1;\n }\n\n // Otherwise, double repeatedly to cover.\n else {\n var z = x1 - x0 || 1,\n node = this._root,\n parent,\n i;\n\n while (x0 > x || x >= x1 || y0 > y || y >= y1) {\n i = (y < y0) << 1 | (x < x0);\n parent = new Array(4), parent[i] = node, node = parent, z *= 2;\n switch (i) {\n case 0: x1 = x0 + z, y1 = y0 + z; break;\n case 1: x0 = x1 - z, y1 = y0 + z; break;\n case 2: x1 = x0 + z, y0 = y1 - z; break;\n case 3: x0 = x1 - z, y0 = y1 - z; break;\n }\n }\n\n if (this._root && this._root.length) this._root = node;\n }\n\n this._x0 = x0;\n this._y0 = y0;\n this._x1 = x1;\n this._y1 = y1;\n return this;\n}\n","export default function() {\n var data = [];\n this.visit(function(node) {\n if (!node.length) do data.push(node.data); while (node = node.next)\n });\n return data;\n}\n","export default function(_) {\n return arguments.length\n ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])\n : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];\n}\n","export default function(node, x0, y0, x1, y1) {\n this.node = node;\n this.x0 = x0;\n this.y0 = y0;\n this.x1 = x1;\n this.y1 = y1;\n}\n","import Quad from \"./quad.js\";\n\nexport default function(x, y, radius) {\n var data,\n x0 = this._x0,\n y0 = this._y0,\n x1,\n y1,\n x2,\n y2,\n x3 = this._x1,\n y3 = this._y1,\n quads = [],\n node = this._root,\n q,\n i;\n\n if (node) quads.push(new Quad(node, x0, y0, x3, y3));\n if (radius == null) radius = Infinity;\n else {\n x0 = x - radius, y0 = y - radius;\n x3 = x + radius, y3 = y + radius;\n radius *= radius;\n }\n\n while (q = quads.pop()) {\n\n // Stop searching if this quadrant can’t contain a closer node.\n if (!(node = q.node)\n || (x1 = q.x0) > x3\n || (y1 = q.y0) > y3\n || (x2 = q.x1) < x0\n || (y2 = q.y1) < y0) continue;\n\n // Bisect the current quadrant.\n if (node.length) {\n var xm = (x1 + x2) / 2,\n ym = (y1 + y2) / 2;\n\n quads.push(\n new Quad(node[3], xm, ym, x2, y2),\n new Quad(node[2], x1, ym, xm, y2),\n new Quad(node[1], xm, y1, x2, ym),\n new Quad(node[0], x1, y1, xm, ym)\n );\n\n // Visit the closest quadrant first.\n if (i = (y >= ym) << 1 | (x >= xm)) {\n q = quads[quads.length - 1];\n quads[quads.length - 1] = quads[quads.length - 1 - i];\n quads[quads.length - 1 - i] = q;\n }\n }\n\n // Visit this point. (Visiting coincident points isn’t necessary!)\n else {\n var dx = x - +this._x.call(null, node.data),\n dy = y - +this._y.call(null, node.data),\n d2 = dx * dx + dy * dy;\n if (d2 < radius) {\n var d = Math.sqrt(radius = d2);\n x0 = x - d, y0 = y - d;\n x3 = x + d, y3 = y + d;\n data = node.data;\n }\n }\n }\n\n return data;\n}\n","export default function(d) {\n if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points\n\n var parent,\n node = this._root,\n retainer,\n previous,\n next,\n x0 = this._x0,\n y0 = this._y0,\n x1 = this._x1,\n y1 = this._y1,\n x,\n y,\n xm,\n ym,\n right,\n bottom,\n i,\n j;\n\n // If the tree is empty, initialize the root as a leaf.\n if (!node) return this;\n\n // Find the leaf node for the point.\n // While descending, also retain the deepest parent with a non-removed sibling.\n if (node.length) while (true) {\n if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;\n if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;\n if (!(parent = node, node = node[i = bottom << 1 | right])) return this;\n if (!node.length) break;\n if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;\n }\n\n // Find the point to remove.\n while (node.data !== d) if (!(previous = node, node = node.next)) return this;\n if (next = node.next) delete node.next;\n\n // If there are multiple coincident points, remove just the point.\n if (previous) return (next ? previous.next = next : delete previous.next), this;\n\n // If this is the root point, remove it.\n if (!parent) return this._root = next, this;\n\n // Remove this leaf.\n next ? parent[i] = next : delete parent[i];\n\n // If the parent now contains exactly one leaf, collapse superfluous parents.\n if ((node = parent[0] || parent[1] || parent[2] || parent[3])\n && node === (parent[3] || parent[2] || parent[1] || parent[0])\n && !node.length) {\n if (retainer) retainer[j] = node;\n else this._root = node;\n }\n\n return this;\n}\n\nexport function removeAll(data) {\n for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);\n return this;\n}\n","export default function() {\n return this._root;\n}\n","export default function() {\n var size = 0;\n this.visit(function(node) {\n if (!node.length) do ++size; while (node = node.next)\n });\n return size;\n}\n","import Quad from \"./quad.js\";\n\nexport default function(callback) {\n var quads = [], q, node = this._root, child, x0, y0, x1, y1;\n if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));\n while (q = quads.pop()) {\n if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {\n var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;\n if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));\n if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));\n if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));\n if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));\n }\n }\n return this;\n}\n","import Quad from \"./quad.js\";\n\nexport default function(callback) {\n var quads = [], next = [], q;\n if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));\n while (q = quads.pop()) {\n var node = q.node;\n if (node.length) {\n var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;\n if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));\n if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));\n if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));\n if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));\n }\n next.push(q);\n }\n while (q = next.pop()) {\n callback(q.node, q.x0, q.y0, q.x1, q.y1);\n }\n return this;\n}\n","export function defaultX(d) {\n return d[0];\n}\n\nexport default function(_) {\n return arguments.length ? (this._x = _, this) : this._x;\n}\n","export function defaultY(d) {\n return d[1];\n}\n\nexport default function(_) {\n return arguments.length ? (this._y = _, this) : this._y;\n}\n","import tree_add, {addAll as tree_addAll} from \"./add.js\";\nimport tree_cover from \"./cover.js\";\nimport tree_data from \"./data.js\";\nimport tree_extent from \"./extent.js\";\nimport tree_find from \"./find.js\";\nimport tree_remove, {removeAll as tree_removeAll} from \"./remove.js\";\nimport tree_root from \"./root.js\";\nimport tree_size from \"./size.js\";\nimport tree_visit from \"./visit.js\";\nimport tree_visitAfter from \"./visitAfter.js\";\nimport tree_x, {defaultX} from \"./x.js\";\nimport tree_y, {defaultY} from \"./y.js\";\n\nexport default function quadtree(nodes, x, y) {\n var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);\n return nodes == null ? tree : tree.addAll(nodes);\n}\n\nfunction Quadtree(x, y, x0, y0, x1, y1) {\n this._x = x;\n this._y = y;\n this._x0 = x0;\n this._y0 = y0;\n this._x1 = x1;\n this._y1 = y1;\n this._root = undefined;\n}\n\nfunction leaf_copy(leaf) {\n var copy = {data: leaf.data}, next = copy;\n while (leaf = leaf.next) next = next.next = {data: leaf.data};\n return copy;\n}\n\nvar treeProto = quadtree.prototype = Quadtree.prototype;\n\ntreeProto.copy = function() {\n var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),\n node = this._root,\n nodes,\n child;\n\n if (!node) return copy;\n\n if (!node.length) return copy._root = leaf_copy(node), copy;\n\n nodes = [{source: node, target: copy._root = new Array(4)}];\n while (node = nodes.pop()) {\n for (var i = 0; i < 4; ++i) {\n if (child = node.source[i]) {\n if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});\n else node.target[i] = leaf_copy(child);\n }\n }\n }\n\n return copy;\n};\n\ntreeProto.add = tree_add;\ntreeProto.addAll = tree_addAll;\ntreeProto.cover = tree_cover;\ntreeProto.data = tree_data;\ntreeProto.extent = tree_extent;\ntreeProto.find = tree_find;\ntreeProto.remove = tree_remove;\ntreeProto.removeAll = tree_removeAll;\ntreeProto.root = tree_root;\ntreeProto.size = tree_size;\ntreeProto.visit = tree_visit;\ntreeProto.visitAfter = tree_visitAfter;\ntreeProto.x = tree_x;\ntreeProto.y = tree_y;\n","export default function(x) {\n return function() {\n return x;\n };\n}\n","export default function(random) {\n return (random() - 0.5) * 1e-6;\n}\n","import {quadtree} from \"d3-quadtree\";\nimport constant from \"./constant.js\";\nimport jiggle from \"./jiggle.js\";\n\nfunction x(d) {\n return d.x + d.vx;\n}\n\nfunction y(d) {\n return d.y + d.vy;\n}\n\nexport default function(radius) {\n var nodes,\n radii,\n random,\n strength = 1,\n iterations = 1;\n\n if (typeof radius !== \"function\") radius = constant(radius == null ? 1 : +radius);\n\n function force() {\n var i, n = nodes.length,\n tree,\n node,\n xi,\n yi,\n ri,\n ri2;\n\n for (var k = 0; k < iterations; ++k) {\n tree = quadtree(nodes, x, y).visitAfter(prepare);\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n ri = radii[node.index], ri2 = ri * ri;\n xi = node.x + node.vx;\n yi = node.y + node.vy;\n tree.visit(apply);\n }\n }\n\n function apply(quad, x0, y0, x1, y1) {\n var data = quad.data, rj = quad.r, r = ri + rj;\n if (data) {\n if (data.index > node.index) {\n var x = xi - data.x - data.vx,\n y = yi - data.y - data.vy,\n l = x * x + y * y;\n if (l < r * r) {\n if (x === 0) x = jiggle(random), l += x * x;\n if (y === 0) y = jiggle(random), l += y * y;\n l = (r - (l = Math.sqrt(l))) / l * strength;\n node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));\n node.vy += (y *= l) * r;\n data.vx -= x * (r = 1 - r);\n data.vy -= y * r;\n }\n }\n return;\n }\n return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;\n }\n }\n\n function prepare(quad) {\n if (quad.data) return quad.r = radii[quad.data.index];\n for (var i = quad.r = 0; i < 4; ++i) {\n if (quad[i] && quad[i].r > quad.r) {\n quad.r = quad[i].r;\n }\n }\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length, node;\n radii = new Array(n);\n for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);\n }\n\n force.initialize = function(_nodes, _random) {\n nodes = _nodes;\n random = _random;\n initialize();\n };\n\n force.iterations = function(_) {\n return arguments.length ? (iterations = +_, force) : iterations;\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = +_, force) : strength;\n };\n\n force.radius = function(_) {\n return arguments.length ? (radius = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : radius;\n };\n\n return force;\n}\n","import constant from \"./constant.js\";\nimport jiggle from \"./jiggle.js\";\n\nfunction index(d) {\n return d.index;\n}\n\nfunction find(nodeById, nodeId) {\n var node = nodeById.get(nodeId);\n if (!node) throw new Error(\"node not found: \" + nodeId);\n return node;\n}\n\nexport default function(links) {\n var id = index,\n strength = defaultStrength,\n strengths,\n distance = constant(30),\n distances,\n nodes,\n count,\n bias,\n random,\n iterations = 1;\n\n if (links == null) links = [];\n\n function defaultStrength(link) {\n return 1 / Math.min(count[link.source.index], count[link.target.index]);\n }\n\n function force(alpha) {\n for (var k = 0, n = links.length; k < iterations; ++k) {\n for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {\n link = links[i], source = link.source, target = link.target;\n x = target.x + target.vx - source.x - source.vx || jiggle(random);\n y = target.y + target.vy - source.y - source.vy || jiggle(random);\n l = Math.sqrt(x * x + y * y);\n l = (l - distances[i]) / l * alpha * strengths[i];\n x *= l, y *= l;\n target.vx -= x * (b = bias[i]);\n target.vy -= y * b;\n source.vx += x * (b = 1 - b);\n source.vy += y * b;\n }\n }\n }\n\n function initialize() {\n if (!nodes) return;\n\n var i,\n n = nodes.length,\n m = links.length,\n nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])),\n link;\n\n for (i = 0, count = new Array(n); i < m; ++i) {\n link = links[i], link.index = i;\n if (typeof link.source !== \"object\") link.source = find(nodeById, link.source);\n if (typeof link.target !== \"object\") link.target = find(nodeById, link.target);\n count[link.source.index] = (count[link.source.index] || 0) + 1;\n count[link.target.index] = (count[link.target.index] || 0) + 1;\n }\n\n for (i = 0, bias = new Array(m); i < m; ++i) {\n link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);\n }\n\n strengths = new Array(m), initializeStrength();\n distances = new Array(m), initializeDistance();\n }\n\n function initializeStrength() {\n if (!nodes) return;\n\n for (var i = 0, n = links.length; i < n; ++i) {\n strengths[i] = +strength(links[i], i, links);\n }\n }\n\n function initializeDistance() {\n if (!nodes) return;\n\n for (var i = 0, n = links.length; i < n; ++i) {\n distances[i] = +distance(links[i], i, links);\n }\n }\n\n force.initialize = function(_nodes, _random) {\n nodes = _nodes;\n random = _random;\n initialize();\n };\n\n force.links = function(_) {\n return arguments.length ? (links = _, initialize(), force) : links;\n };\n\n force.id = function(_) {\n return arguments.length ? (id = _, force) : id;\n };\n\n force.iterations = function(_) {\n return arguments.length ? (iterations = +_, force) : iterations;\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initializeStrength(), force) : strength;\n };\n\n force.distance = function(_) {\n return arguments.length ? (distance = typeof _ === \"function\" ? _ : constant(+_), initializeDistance(), force) : distance;\n };\n\n return force;\n}\n","var noop = {value: () => {}};\n\nfunction dispatch() {\n for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {\n if (!(t = arguments[i] + \"\") || (t in _) || /[\\s.]/.test(t)) throw new Error(\"illegal type: \" + t);\n _[t] = [];\n }\n return new Dispatch(_);\n}\n\nfunction Dispatch(_) {\n this._ = _;\n}\n\nfunction parseTypenames(typenames, types) {\n return typenames.trim().split(/^|\\s+/).map(function(t) {\n var name = \"\", i = t.indexOf(\".\");\n if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);\n if (t && !types.hasOwnProperty(t)) throw new Error(\"unknown type: \" + t);\n return {type: t, name: name};\n });\n}\n\nDispatch.prototype = dispatch.prototype = {\n constructor: Dispatch,\n on: function(typename, callback) {\n var _ = this._,\n T = parseTypenames(typename + \"\", _),\n t,\n i = -1,\n n = T.length;\n\n // If no callback was specified, return the callback of the given type and name.\n if (arguments.length < 2) {\n while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;\n return;\n }\n\n // If a type was specified, set the callback for the given type and name.\n // Otherwise, if a null callback was specified, remove callbacks of the given name.\n if (callback != null && typeof callback !== \"function\") throw new Error(\"invalid callback: \" + callback);\n while (++i < n) {\n if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);\n else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);\n }\n\n return this;\n },\n copy: function() {\n var copy = {}, _ = this._;\n for (var t in _) copy[t] = _[t].slice();\n return new Dispatch(copy);\n },\n call: function(type, that) {\n if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];\n if (!this._.hasOwnProperty(type)) throw new Error(\"unknown type: \" + type);\n for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n },\n apply: function(type, that, args) {\n if (!this._.hasOwnProperty(type)) throw new Error(\"unknown type: \" + type);\n for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n }\n};\n\nfunction get(type, name) {\n for (var i = 0, n = type.length, c; i < n; ++i) {\n if ((c = type[i]).name === name) {\n return c.value;\n }\n }\n}\n\nfunction set(type, name, callback) {\n for (var i = 0, n = type.length; i < n; ++i) {\n if (type[i].name === name) {\n type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));\n break;\n }\n }\n if (callback != null) type.push({name: name, value: callback});\n return type;\n}\n\nexport default dispatch;\n","var frame = 0, // is an animation frame pending?\n timeout = 0, // is a timeout pending?\n interval = 0, // are any timers active?\n pokeDelay = 1000, // how frequently we check for clock skew\n taskHead,\n taskTail,\n clockLast = 0,\n clockNow = 0,\n clockSkew = 0,\n clock = typeof performance === \"object\" && performance.now ? performance : Date,\n setFrame = typeof window === \"object\" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); };\n\nexport function now() {\n return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);\n}\n\nfunction clearNow() {\n clockNow = 0;\n}\n\nexport function Timer() {\n this._call =\n this._time =\n this._next = null;\n}\n\nTimer.prototype = timer.prototype = {\n constructor: Timer,\n restart: function(callback, delay, time) {\n if (typeof callback !== \"function\") throw new TypeError(\"callback is not a function\");\n time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);\n if (!this._next && taskTail !== this) {\n if (taskTail) taskTail._next = this;\n else taskHead = this;\n taskTail = this;\n }\n this._call = callback;\n this._time = time;\n sleep();\n },\n stop: function() {\n if (this._call) {\n this._call = null;\n this._time = Infinity;\n sleep();\n }\n }\n};\n\nexport function timer(callback, delay, time) {\n var t = new Timer;\n t.restart(callback, delay, time);\n return t;\n}\n\nexport function timerFlush() {\n now(); // Get the current time, if not already set.\n ++frame; // Pretend we’ve set an alarm, if we haven’t already.\n var t = taskHead, e;\n while (t) {\n if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e);\n t = t._next;\n }\n --frame;\n}\n\nfunction wake() {\n clockNow = (clockLast = clock.now()) + clockSkew;\n frame = timeout = 0;\n try {\n timerFlush();\n } finally {\n frame = 0;\n nap();\n clockNow = 0;\n }\n}\n\nfunction poke() {\n var now = clock.now(), delay = now - clockLast;\n if (delay > pokeDelay) clockSkew -= delay, clockLast = now;\n}\n\nfunction nap() {\n var t0, t1 = taskHead, t2, time = Infinity;\n while (t1) {\n if (t1._call) {\n if (time > t1._time) time = t1._time;\n t0 = t1, t1 = t1._next;\n } else {\n t2 = t1._next, t1._next = null;\n t1 = t0 ? t0._next = t2 : taskHead = t2;\n }\n }\n taskTail = t0;\n sleep(time);\n}\n\nfunction sleep(time) {\n if (frame) return; // Soonest alarm already set, or will be.\n if (timeout) timeout = clearTimeout(timeout);\n var delay = time - clockNow; // Strictly less than if we recomputed clockNow.\n if (delay > 24) {\n if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);\n if (interval) interval = clearInterval(interval);\n } else {\n if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);\n frame = 1, setFrame(wake);\n }\n}\n","// https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use\nconst a = 1664525;\nconst c = 1013904223;\nconst m = 4294967296; // 2^32\n\nexport default function() {\n let s = 1;\n return () => (s = (a * s + c) % m) / m;\n}\n","import {dispatch} from \"d3-dispatch\";\nimport {timer} from \"d3-timer\";\nimport lcg from \"./lcg.js\";\n\nexport function x(d) {\n return d.x;\n}\n\nexport function y(d) {\n return d.y;\n}\n\nvar initialRadius = 10,\n initialAngle = Math.PI * (3 - Math.sqrt(5));\n\nexport default function(nodes) {\n var simulation,\n alpha = 1,\n alphaMin = 0.001,\n alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),\n alphaTarget = 0,\n velocityDecay = 0.6,\n forces = new Map(),\n stepper = timer(step),\n event = dispatch(\"tick\", \"end\"),\n random = lcg();\n\n if (nodes == null) nodes = [];\n\n function step() {\n tick();\n event.call(\"tick\", simulation);\n if (alpha < alphaMin) {\n stepper.stop();\n event.call(\"end\", simulation);\n }\n }\n\n function tick(iterations) {\n var i, n = nodes.length, node;\n\n if (iterations === undefined) iterations = 1;\n\n for (var k = 0; k < iterations; ++k) {\n alpha += (alphaTarget - alpha) * alphaDecay;\n\n forces.forEach(function(force) {\n force(alpha);\n });\n\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n if (node.fx == null) node.x += node.vx *= velocityDecay;\n else node.x = node.fx, node.vx = 0;\n if (node.fy == null) node.y += node.vy *= velocityDecay;\n else node.y = node.fy, node.vy = 0;\n }\n }\n\n return simulation;\n }\n\n function initializeNodes() {\n for (var i = 0, n = nodes.length, node; i < n; ++i) {\n node = nodes[i], node.index = i;\n if (node.fx != null) node.x = node.fx;\n if (node.fy != null) node.y = node.fy;\n if (isNaN(node.x) || isNaN(node.y)) {\n var radius = initialRadius * Math.sqrt(0.5 + i), angle = i * initialAngle;\n node.x = radius * Math.cos(angle);\n node.y = radius * Math.sin(angle);\n }\n if (isNaN(node.vx) || isNaN(node.vy)) {\n node.vx = node.vy = 0;\n }\n }\n }\n\n function initializeForce(force) {\n if (force.initialize) force.initialize(nodes, random);\n return force;\n }\n\n initializeNodes();\n\n return simulation = {\n tick: tick,\n\n restart: function() {\n return stepper.restart(step), simulation;\n },\n\n stop: function() {\n return stepper.stop(), simulation;\n },\n\n nodes: function(_) {\n return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes;\n },\n\n alpha: function(_) {\n return arguments.length ? (alpha = +_, simulation) : alpha;\n },\n\n alphaMin: function(_) {\n return arguments.length ? (alphaMin = +_, simulation) : alphaMin;\n },\n\n alphaDecay: function(_) {\n return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;\n },\n\n alphaTarget: function(_) {\n return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;\n },\n\n velocityDecay: function(_) {\n return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;\n },\n\n randomSource: function(_) {\n return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random;\n },\n\n force: function(name, _) {\n return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);\n },\n\n find: function(x, y, radius) {\n var i = 0,\n n = nodes.length,\n dx,\n dy,\n d2,\n node,\n closest;\n\n if (radius == null) radius = Infinity;\n else radius *= radius;\n\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n dx = x - node.x;\n dy = y - node.y;\n d2 = dx * dx + dy * dy;\n if (d2 < radius) closest = node, radius = d2;\n }\n\n return closest;\n },\n\n on: function(name, _) {\n return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);\n }\n };\n}\n","import {quadtree} from \"d3-quadtree\";\nimport constant from \"./constant.js\";\nimport jiggle from \"./jiggle.js\";\nimport {x, y} from \"./simulation.js\";\n\nexport default function() {\n var nodes,\n node,\n random,\n alpha,\n strength = constant(-30),\n strengths,\n distanceMin2 = 1,\n distanceMax2 = Infinity,\n theta2 = 0.81;\n\n function force(_) {\n var i, n = nodes.length, tree = quadtree(nodes, x, y).visitAfter(accumulate);\n for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length, node;\n strengths = new Array(n);\n for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);\n }\n\n function accumulate(quad) {\n var strength = 0, q, c, weight = 0, x, y, i;\n\n // For internal nodes, accumulate forces from child quadrants.\n if (quad.length) {\n for (x = y = i = 0; i < 4; ++i) {\n if ((q = quad[i]) && (c = Math.abs(q.value))) {\n strength += q.value, weight += c, x += c * q.x, y += c * q.y;\n }\n }\n quad.x = x / weight;\n quad.y = y / weight;\n }\n\n // For leaf nodes, accumulate forces from coincident quadrants.\n else {\n q = quad;\n q.x = q.data.x;\n q.y = q.data.y;\n do strength += strengths[q.data.index];\n while (q = q.next);\n }\n\n quad.value = strength;\n }\n\n function apply(quad, x1, _, x2) {\n if (!quad.value) return true;\n\n var x = quad.x - node.x,\n y = quad.y - node.y,\n w = x2 - x1,\n l = x * x + y * y;\n\n // Apply the Barnes-Hut approximation if possible.\n // Limit forces for very close nodes; randomize direction if coincident.\n if (w * w / theta2 < l) {\n if (l < distanceMax2) {\n if (x === 0) x = jiggle(random), l += x * x;\n if (y === 0) y = jiggle(random), l += y * y;\n if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);\n node.vx += x * quad.value * alpha / l;\n node.vy += y * quad.value * alpha / l;\n }\n return true;\n }\n\n // Otherwise, process points directly.\n else if (quad.length || l >= distanceMax2) return;\n\n // Limit forces for very close nodes; randomize direction if coincident.\n if (quad.data !== node || quad.next) {\n if (x === 0) x = jiggle(random), l += x * x;\n if (y === 0) y = jiggle(random), l += y * y;\n if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);\n }\n\n do if (quad.data !== node) {\n w = strengths[quad.data.index] * alpha / l;\n node.vx += x * w;\n node.vy += y * w;\n } while (quad = quad.next);\n }\n\n force.initialize = function(_nodes, _random) {\n nodes = _nodes;\n random = _random;\n initialize();\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n };\n\n force.distanceMin = function(_) {\n return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);\n };\n\n force.distanceMax = function(_) {\n return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);\n };\n\n force.theta = function(_) {\n return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);\n };\n\n return force;\n}\n","import constant from \"./constant.js\";\n\nexport default function(x) {\n var strength = constant(0.1),\n nodes,\n strengths,\n xz;\n\n if (typeof x !== \"function\") x = constant(x == null ? 0 : +x);\n\n function force(alpha) {\n for (var i = 0, n = nodes.length, node; i < n; ++i) {\n node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;\n }\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length;\n strengths = new Array(n);\n xz = new Array(n);\n for (i = 0; i < n; ++i) {\n strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);\n }\n }\n\n force.initialize = function(_) {\n nodes = _;\n initialize();\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n };\n\n force.x = function(_) {\n return arguments.length ? (x = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : x;\n };\n\n return force;\n}\n","import constant from \"./constant.js\";\n\nexport default function(y) {\n var strength = constant(0.1),\n nodes,\n strengths,\n yz;\n\n if (typeof y !== \"function\") y = constant(y == null ? 0 : +y);\n\n function force(alpha) {\n for (var i = 0, n = nodes.length, node; i < n; ++i) {\n node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;\n }\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length;\n strengths = new Array(n);\n yz = new Array(n);\n for (i = 0; i < n; ++i) {\n strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);\n }\n }\n\n force.initialize = function(_) {\n nodes = _;\n initialize();\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n };\n\n force.y = function(_) {\n return arguments.length ? (y = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : y;\n };\n\n return force;\n}\n","/**\n * SimulationManager: spawns a Web Worker for the force simulation,\n * or falls back to synchronous d3-force on the main thread.\n *\n * The worker is always preferred when available. Synchronous fallback\n * is only used when Web Workers are unavailable (SSR, test environments).\n * The sync path batches ticks via requestAnimationFrame to avoid\n * blocking the main thread.\n */\n\nimport {\n forceCenter,\n forceCollide,\n forceLink,\n forceManyBody,\n forceSimulation,\n forceX,\n forceY,\n type Simulation,\n type SimulationNodeDatum,\n} from 'd3-force';\n\nimport type { SimEdge, SimNode, WorkerOutMessage, WorkerSimulationConfig } from './worker-protocol';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SYNC_MAX_TICKS = 300;\nconst SYNC_TICKS_PER_BATCH = 15;\n\n// ---------------------------------------------------------------------------\n// Internal node shape for sync simulation\n// ---------------------------------------------------------------------------\n\ninterface SyncNode extends SimulationNodeDatum {\n id: string;\n radius: number;\n community?: string;\n fx?: number | null;\n fy?: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Cluster force (duplicated in simulation-worker.ts for the Web Worker path.\n// Worker can't import from workspace packages, so both copies must stay in sync.)\n// ---------------------------------------------------------------------------\n\nfunction forceCluster(nodes: SyncNode[], strength: number) {\n return (alpha: number) => {\n const cx = new Map<string, number>();\n const cy = new Map<string, number>();\n const count = new Map<string, number>();\n\n for (const node of nodes) {\n if (!node.community) continue;\n const c = node.community;\n cx.set(c, (cx.get(c) ?? 0) + (node.x ?? 0));\n cy.set(c, (cy.get(c) ?? 0) + (node.y ?? 0));\n count.set(c, (count.get(c) ?? 0) + 1);\n }\n\n for (const [c, n] of count) {\n cx.set(c, cx.get(c)! / n);\n cy.set(c, cy.get(c)! / n);\n }\n\n const k = strength * alpha;\n for (const node of nodes) {\n if (!node.community) continue;\n const targetX = cx.get(node.community)!;\n const targetY = cy.get(node.community)!;\n node.vx = (node.vx ?? 0) + (targetX - (node.x ?? 0)) * k;\n node.vy = (node.vy ?? 0) + (targetY - (node.y ?? 0)) * k;\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// SimulationManager\n// ---------------------------------------------------------------------------\n\ntype TickCallback = (positions: Array<{ id: string; x: number; y: number }>, alpha: number) => void;\n\ntype SettledCallback = () => void;\n\nexport class SimulationManager {\n private worker: Worker | null = null;\n private syncSim: Simulation<SyncNode, undefined> | null = null;\n private syncNodes: SyncNode[] = [];\n private syncNodeMap: Map<string, SyncNode> = new Map();\n private tickCb: TickCallback | null = null;\n private settledCb: SettledCallback | null = null;\n private destroyed = false;\n private syncRafId: number | null = null;\n\n // Stored for worker->sync fallback\n private initNodes: SimNode[] = [];\n private initEdges: SimEdge[] = [];\n private initConfig: WorkerSimulationConfig | null = null;\n\n private constructor() {}\n\n /**\n * Create a SimulationManager. Uses Web Worker for large graphs,\n * synchronous fallback for small graphs or when Worker unavailable.\n */\n static create(\n nodes: SimNode[],\n edges: SimEdge[],\n config: WorkerSimulationConfig,\n ): SimulationManager {\n const mgr = new SimulationManager();\n\n const useWorker = typeof Worker !== 'undefined';\n\n if (useWorker) {\n mgr.initWorker(nodes, edges, config);\n } else {\n mgr.initSync(nodes, edges, config);\n }\n\n return mgr;\n }\n\n /** Register a callback for position updates. */\n onTick(cb: TickCallback): void {\n this.tickCb = cb;\n }\n\n /** Register a callback for when the simulation has settled. */\n onSettled(cb: SettledCallback): void {\n this.settledCb = cb;\n }\n\n /** Reheat the simulation. */\n reheat(alpha?: number): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'reheat', alpha });\n } else if (this.syncSim) {\n this.syncSim.alpha(alpha ?? 0.3).restart();\n this.runSyncTicks();\n }\n }\n\n /** Pin a node to fixed x/y coordinates. */\n pinNode(id: string, x: number, y: number): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'pin', nodeId: id, x, y });\n } else {\n const node = this.syncNodeMap.get(id);\n if (node) {\n node.fx = x;\n node.fy = y;\n }\n }\n }\n\n /** Unpin a node and reheat so forces settle it into equilibrium. */\n unpinNode(id: string): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'unpin', nodeId: id });\n } else {\n const node = this.syncNodeMap.get(id);\n if (node) {\n node.fx = null;\n node.fy = null;\n }\n if (this.syncSim && this.syncSim.alpha() < 0.1) {\n this.syncSim.alpha(0.1).restart();\n this.runSyncTicks();\n }\n }\n }\n\n /** Drag a node (pins it and reheats slightly). */\n dragNode(id: string, x: number, y: number): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'drag', nodeId: id, x, y });\n } else {\n const node = this.syncNodeMap.get(id);\n if (node) {\n node.fx = x;\n node.fy = y;\n }\n if (this.syncSim && this.syncSim.alpha() < 0.1) {\n this.syncSim.alpha(0.1).restart();\n this.runSyncTicks();\n }\n }\n }\n\n /** Tear down the simulation and release resources. */\n destroy(): void {\n this.destroyed = true;\n\n if (this.syncRafId !== null) {\n cancelAnimationFrame(this.syncRafId);\n this.syncRafId = null;\n }\n\n if (this.worker) {\n this.worker.postMessage({ type: 'stop' });\n this.worker.terminate();\n this.worker = null;\n }\n\n if (this.syncSim) {\n this.syncSim.stop();\n this.syncSim = null;\n }\n\n this.tickCb = null;\n this.settledCb = null;\n }\n\n // -------------------------------------------------------------------------\n // Worker path\n // -------------------------------------------------------------------------\n\n private initWorker(nodes: SimNode[], edges: SimEdge[], config: WorkerSimulationConfig): void {\n // Store for fallback if worker fails to load\n this.initNodes = nodes;\n this.initEdges = edges;\n this.initConfig = config;\n\n // Worker URL resolution:\n // - Built dist/ consumers: import.meta.url points at dist/index.js,\n // so ./simulation-worker.js resolves to dist/simulation-worker.js.\n // - Vite dev with source aliases (Ladle): import.meta.url points at\n // src/graph/simulation.ts, so ./simulation-worker.js doesn't exist.\n // The .js worker fails to load, and the onerror handler retries\n // with .ts which Vite transforms on the fly.\n // - Vite production build: detects `new Worker(new URL(...))` and\n // bundles the worker as a hashed .js asset.\n const initMsg = { type: 'init' as const, nodes, edges, config };\n const wireWorker = (worker: Worker) => {\n this.worker = worker;\n\n worker.onmessage = (event: MessageEvent<WorkerOutMessage>) => {\n if (this.destroyed) return;\n const msg = event.data;\n\n switch (msg.type) {\n case 'positions':\n this.tickCb?.(msg.nodes, msg.alpha);\n break;\n case 'settled':\n this.settledCb?.();\n break;\n case 'error':\n console.error('[SimulationManager] Worker error:', msg.message);\n break;\n }\n };\n\n worker.postMessage(initMsg);\n };\n\n try {\n const w = new Worker(new URL('./simulation-worker.js', import.meta.url), {\n type: 'module',\n });\n\n w.onerror = () => {\n // .js failed (likely Vite dev with source aliases). Try .ts.\n // The URL is constructed dynamically to prevent bundlers (Rollup)\n // from statically analyzing it and trying to resolve the .ts file\n // as an asset entry point in production builds.\n if (this.destroyed) return;\n w.terminate();\n this.worker = null;\n\n try {\n const tsUrl = new URL(import.meta.url.replace(/\\/[^/]+$/, '/simulation-worker.ts'));\n const w2 = new Worker(tsUrl, { type: 'module' });\n\n w2.onerror = () => {\n // Both .js and .ts failed - fall back to sync.\n if (this.destroyed) return;\n console.warn('[SimulationManager] Worker failed to load, falling back to sync');\n w2.terminate();\n this.worker = null;\n this.initSync(this.initNodes, this.initEdges, this.initConfig!);\n };\n\n wireWorker(w2);\n } catch {\n console.warn('[SimulationManager] Worker creation failed, using sync fallback');\n this.initSync(this.initNodes, this.initEdges, this.initConfig!);\n }\n };\n\n wireWorker(w);\n } catch {\n // Worker construction failed (e.g. SSR or restrictive CSP)\n console.warn('[SimulationManager] Worker creation failed, using sync fallback');\n this.initSync(nodes, edges, config);\n }\n }\n\n // -------------------------------------------------------------------------\n // Synchronous fallback\n // -------------------------------------------------------------------------\n\n private initSync(nodes: SimNode[], edges: SimEdge[], config: WorkerSimulationConfig): void {\n this.syncNodes = nodes.map((n) => ({\n id: n.id,\n x: n.x,\n y: n.y,\n radius: n.radius,\n community: n.community,\n }));\n\n this.syncNodeMap = new Map(this.syncNodes.map((n) => [n.id, n]));\n\n const linkForce = forceLink(edges.map((e) => ({ ...e })))\n .id((d) => (d as SyncNode).id)\n .distance(config.linkDistance);\n if (config.linkStrength != null) {\n linkForce.strength(config.linkStrength);\n }\n\n const padding = config.collisionPadding ?? 2;\n\n this.syncSim = forceSimulation<SyncNode>(this.syncNodes)\n .force('link', linkForce)\n .force('charge', forceManyBody().strength(config.chargeStrength))\n .force(\n 'collide',\n forceCollide<SyncNode>().radius((d) => d.radius + padding),\n )\n // Weak gravity keeps disconnected nodes from drifting far from center\n .force('gravityX', forceX<SyncNode>(0).strength(0.05))\n .force('gravityY', forceY<SyncNode>(0).strength(0.05))\n .alphaDecay(config.alphaDecay)\n .velocityDecay(config.velocityDecay)\n .stop(); // Don't auto-run; we tick manually\n\n // Center force (default true)\n if (config.centerForce !== false) {\n this.syncSim.force('center', forceCenter(0, 0));\n }\n\n // Add clustering force if configured\n if (config.clustering) {\n const clusterFn = forceCluster(this.syncNodes, config.clustering.strength);\n // d3 calls force functions with (alpha) on each tick\n this.syncSim.force('cluster', clusterFn as unknown as ReturnType<typeof forceCenter>);\n }\n\n // Defer initial delivery: callbacks aren't wired yet at create() time\n this.runSyncTicks(true);\n }\n\n /**\n * Run simulation ticks in batches, yielding to the main thread between\n * batches via requestAnimationFrame. This prevents a multi-second freeze\n * when the sync fallback handles large graphs (1k+ nodes).\n *\n * Each batch runs SYNC_TICKS_PER_BATCH ticks, emits positions for\n * progressive rendering, then schedules the next batch.\n *\n * @param deferred - When true, start via microtask (initial run where\n * callbacks aren't wired yet). Otherwise start immediately.\n */\n private runSyncTicks(deferred = false): void {\n if (!this.syncSim || this.destroyed) return;\n\n // Cancel any in-flight batched run (e.g. from a previous reheat)\n if (this.syncRafId !== null) {\n cancelAnimationFrame(this.syncRafId);\n this.syncRafId = null;\n }\n\n const sim = this.syncSim;\n let tickCount = 0;\n\n const runBatch = () => {\n if (this.destroyed || !this.syncSim) return;\n this.syncRafId = null;\n\n for (let i = 0; i < SYNC_TICKS_PER_BATCH && tickCount < SYNC_MAX_TICKS; i++, tickCount++) {\n sim.tick();\n if (sim.alpha() < 0.001) {\n tickCount = SYNC_MAX_TICKS;\n break;\n }\n }\n\n const positions = this.syncNodes.map((n) => ({\n id: n.id,\n x: n.x ?? 0,\n y: n.y ?? 0,\n }));\n const alpha = sim.alpha();\n const settled = alpha < 0.001 || tickCount >= SYNC_MAX_TICKS;\n\n this.tickCb?.(positions, alpha);\n\n if (settled) {\n this.settledCb?.();\n } else {\n this.syncRafId = requestAnimationFrame(runBatch);\n }\n };\n\n if (deferred) {\n queueMicrotask(runBatch);\n } else {\n runBatch();\n }\n }\n}\n","/**\n * Spatial index for fast node hit-testing.\n *\n * Wraps d3-quadtree to provide findNearest (accounts for node radius)\n * and findInRect queries. Tracks a generation counter to avoid unnecessary\n * rebuilds when positions haven't changed.\n */\n\nimport { type Quadtree, quadtree } from 'd3-quadtree';\nimport type { PositionedNode } from './types';\n\nexport class SpatialIndex {\n private tree: Quadtree<PositionedNode> | null = null;\n private nodes: PositionedNode[] = [];\n private maxRadius = 0;\n private generation = 0;\n\n /** Rebuild the quadtree from the current set of positioned nodes. */\n rebuild(nodes: PositionedNode[]): void {\n this.nodes = nodes;\n this.maxRadius = 0;\n for (const n of nodes) {\n if (n.radius > this.maxRadius) this.maxRadius = n.radius;\n }\n\n this.tree = quadtree<PositionedNode>()\n .x((d) => d.x)\n .y((d) => d.y)\n .addAll(nodes);\n this.generation++;\n }\n\n /** Current generation counter. Increments on each rebuild. */\n getGeneration(): number {\n return this.generation;\n }\n\n /**\n * Find the nearest node to (x, y) within maxDistance.\n * Accounts for node radius: a hit occurs if the point is inside\n * the node circle (distance to center < node.radius), or if the\n * edge-to-edge distance is within maxDistance.\n */\n findNearest(x: number, y: number, maxDistance: number = Infinity): PositionedNode | null {\n if (!this.tree || this.nodes.length === 0) return null;\n\n // The effective search radius for the quadtree needs to include\n // the largest node radius, because we might be \"inside\" a large node\n // whose center is far from our search point.\n const searchRadius = maxDistance + this.maxRadius;\n\n let best: PositionedNode | null = null;\n let bestEffectiveDist = maxDistance + this.maxRadius + 1;\n\n this.tree.visit((node, x0, y0, x1, y1) => {\n // Closest point in this quad to our target\n const closestX = Math.max(x0, Math.min(x, x1));\n const closestY = Math.max(y0, Math.min(y, y1));\n const quadDist = Math.hypot(closestX - x, closestY - y);\n\n // Prune: if the closest edge of this quad is beyond searchRadius, skip\n if (quadDist > searchRadius) return true;\n\n // Check leaf data\n if (!node.length) {\n let current = node;\n do {\n const d = current.data;\n if (d) {\n const dist = Math.hypot(d.x - x, d.y - y);\n // Effective distance: subtract the node's radius.\n // If we're inside the circle, effective distance is 0.\n const effectiveDist = Math.max(0, dist - d.radius);\n if (effectiveDist <= maxDistance && effectiveDist < bestEffectiveDist) {\n bestEffectiveDist = effectiveDist;\n best = d;\n }\n }\n } while ((current = current.next!));\n }\n\n return false;\n });\n\n return best;\n }\n\n /** Find all nodes whose centers fall within the given rectangle. */\n findInRect(x1: number, y1: number, x2: number, y2: number): PositionedNode[] {\n if (!this.tree) return [];\n\n const minX = Math.min(x1, x2);\n const minY = Math.min(y1, y2);\n const maxX = Math.max(x1, x2);\n const maxY = Math.max(y1, y2);\n\n const results: PositionedNode[] = [];\n\n this.tree.visit((node, qx0, qy0, qx1, qy1) => {\n // If quad doesn't overlap the search rect, skip\n if (qx0 > maxX || qx1 < minX || qy0 > maxY || qy1 < minY) {\n return true;\n }\n\n // Check leaf nodes\n if (!node.length) {\n let current = node;\n do {\n const d = current.data;\n if (d && d.x >= minX && d.x <= maxX && d.y >= minY && d.y <= maxY) {\n results.push(d);\n }\n } while ((current = current.next!));\n }\n\n return false;\n });\n\n return results;\n }\n}\n","/**\n * Resize observer: thin wrapper around ResizeObserver with debounce.\n *\n * Watches a container element for size changes and calls back with\n * the new width and height. Debounced at ~60fps (16ms) to avoid\n * excessive re-renders during drag resizes.\n */\n\nconst DEBOUNCE_MS = 16;\n\n/**\n * Observe a container element for size changes.\n *\n * @param container - The element to watch.\n * @param callback - Called with (width, height) when size changes.\n * @returns A cleanup function that disconnects the observer.\n */\nexport function observeResize(\n container: HTMLElement,\n callback: (width: number, height: number) => void,\n): () => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const observer = new ResizeObserver((entries) => {\n // Debounce to ~60fps\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n callback(width, height);\n }\n timeoutId = null;\n }, DEBOUNCE_MS);\n });\n\n observer.observe(container);\n\n return () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n observer.disconnect();\n };\n}\n","/**\n * Tooltip manager: creates and positions a floating tooltip element.\n *\n * Shows tooltip content near the mouse/touch position with viewport\n * edge avoidance via @floating-ui/dom. Touch support via tap-to-show,\n * tap-outside-to-hide.\n */\n\nimport { computePosition, flip, offset, shift } from '@floating-ui/dom';\nimport type { TooltipContent } from '@opendata-ai/openchart-core';\n\nexport interface TooltipManager {\n /** Show the tooltip with content at a given position. */\n show(content: TooltipContent, x: number, y: number): void;\n /** Hide the tooltip. */\n hide(): void;\n /** Remove the tooltip element and clean up event listeners. */\n destroy(): void;\n}\n\nconst TOOLTIP_OFFSET = 12;\n\n/**\n * Create a tooltip manager attached to a container element.\n *\n * The manager creates a floating div positioned relative to the container.\n * Content is rendered as a title line with optional color indicator,\n * followed by a compact list of field-value pairs.\n *\n * @param container - The parent element for the tooltip.\n * @returns TooltipManager with show/hide/destroy methods.\n */\nexport function createTooltipManager(container: HTMLElement): TooltipManager {\n const tooltip = document.createElement('div');\n tooltip.className = 'oc-tooltip';\n tooltip.setAttribute('role', 'tooltip');\n\n container.style.position = container.style.position || 'relative';\n container.appendChild(tooltip);\n\n // Track last content to skip innerHTML when only position changes\n let lastContentKey = '';\n // Generation counter to discard stale async position callbacks\n let currentPositionId = 0;\n\n // Hide on tap-outside for touch devices\n const handleDocumentTouch = (e: Event): void => {\n if (!container.contains(e.target as Node)) {\n hide();\n }\n };\n document.addEventListener('touchstart', handleDocumentTouch);\n\n function show(content: TooltipContent, x: number, y: number): void {\n // Fast content identity check: title + field count + first/last field values\n const contentKey = `${content.title}|${content.fields.length}|${content.fields[0]?.value}|${content.fields[content.fields.length - 1]?.value}`;\n\n if (contentKey !== lastContentKey) {\n lastContentKey = contentKey;\n\n let html = '';\n\n // Title row: optional color dot + title text\n if (content.title) {\n const titleColor = content.fields.find((f) => f.color)?.color;\n html += '<div class=\"oc-tooltip-header\">';\n if (titleColor) {\n html += `<span class=\"oc-tooltip-dot\" style=\"background:${esc(titleColor)}\"></span>`;\n }\n html += `<span class=\"oc-tooltip-title\">${esc(content.title)}</span>`;\n html += '</div>';\n }\n\n // Field rows\n if (content.fields.length > 0) {\n html += '<div class=\"oc-tooltip-body\">';\n for (const field of content.fields) {\n html += '<div class=\"oc-tooltip-row\">';\n html += `<span class=\"oc-tooltip-label\">${esc(field.label)}</span>`;\n html += `<span class=\"oc-tooltip-value\">${esc(field.value)}</span>`;\n html += '</div>';\n }\n html += '</div>';\n }\n\n tooltip.innerHTML = html;\n }\n\n tooltip.style.display = 'block';\n\n // Position with viewport-aware edge avoidance via @floating-ui/dom.\n // Uses a virtual element since the reference point is a coordinate,\n // not a DOM element.\n const positionId = ++currentPositionId;\n const virtualRef = {\n getBoundingClientRect() {\n const rect = container.getBoundingClientRect();\n return {\n x: rect.left + x,\n y: rect.top + y,\n width: 0,\n height: 0,\n top: rect.top + y,\n left: rect.left + x,\n right: rect.left + x,\n bottom: rect.top + y,\n };\n },\n };\n\n computePosition(virtualRef, tooltip, {\n placement: 'bottom-start',\n middleware: [offset(TOOLTIP_OFFSET), flip(), shift({ padding: 5 })],\n }).then(({ x: fx, y: fy }) => {\n // Discard stale callbacks from earlier show() calls\n if (positionId !== currentPositionId) return;\n // computePosition returns coordinates relative to the tooltip's offset\n // parent (the container with position: relative), so apply directly.\n tooltip.style.left = `${fx}px`;\n tooltip.style.top = `${fy}px`;\n });\n }\n\n function hide(): void {\n tooltip.style.display = 'none';\n lastContentKey = '';\n }\n\n function destroy(): void {\n document.removeEventListener('touchstart', handleDocumentTouch);\n if (tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n }\n }\n\n return { show, hide, destroy };\n}\n\nfunction esc(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n","/**\n * Mount API: the main entry point for vanilla JS usage.\n *\n * createChart() takes a container, spec, and options, compiles the chart,\n * renders it as SVG, sets up responsive resizing, tooltip interaction\n * (mouse/touch/keyboard), keyboard navigation between data points,\n * and returns a ChartInstance with update/resize/export/destroy methods.\n */\n\nimport type {\n Annotation,\n AnnotationOffset,\n ChartEventHandlers,\n ChartLayout,\n ChartSpec,\n ChromeKey,\n CompileOptions,\n DarkMode,\n ElementEdit,\n ElementRef,\n GraphSpec,\n LayerSpec,\n MeasureTextFn,\n RangeAnnotation,\n RefLineAnnotation,\n TextAnnotation,\n ThemeConfig,\n TooltipContent,\n} from '@opendata-ai/openchart-core';\nimport { elementRef, getRepresentativeColor, isLayerSpec } from '@opendata-ai/openchart-core';\nimport { compileChart, compileLayer } from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, setupAnimationCleanup } from './animation';\nimport {\n exportCSV,\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport { observeResize } from './resize-observer';\nimport { renderChartSVG } from './svg-renderer';\nimport { createTextEditOverlay } from './text-edit-overlay';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface MountOptions extends ChartEventHandlers {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting: \"auto\" (system pref), \"force\", or \"off\". */\n darkMode?: DarkMode;\n /** Callback when a data point is clicked. @deprecated Use onMarkClick instead. */\n onDataPointClick?: (data: Record<string, unknown>) => void;\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Initial selected element. */\n selectedElement?: ElementRef;\n}\n\nexport interface UpdateOptions {\n /** Override the selected element after update. When omitted, preserves current selection. */\n selectedElement?: ElementRef;\n}\n\nexport interface ExportOptions extends JPGExportOptions {\n // Extensible for future formats (extends JPGExportOptions which extends PNGExportOptions)\n}\n\nexport interface ChartInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: ChartSpec | LayerSpec | GraphSpec, options?: UpdateOptions): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the chart. */\n export(format: 'svg'): string;\n export(format: 'svg-with-fonts', options?: SVGExportOptions): Promise<string>;\n export(format: 'png', options?: ExportOptions): Promise<Blob>;\n export(format: 'jpg', options?: ExportOptions): Promise<Blob>;\n export(format: 'csv'): string;\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'csv',\n options?: ExportOptions,\n ): string | Promise<Blob> | Promise<string>;\n /** Remove all DOM elements and disconnect observers. */\n destroy(): void;\n /** The current compiled layout (for hooks / debugging). */\n readonly layout: ChartLayout;\n /** Get the currently selected element, or null if none. */\n getSelectedElement(): ElementRef | null;\n /** Programmatically select an element. Silent no-op if element not found. */\n select(ref: ElementRef): void;\n /** Deselect the current element. */\n deselect(): void;\n /** Whether inline text editing is active. */\n readonly isEditing: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n // \"auto\": check system preference\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// measureText via hidden canvas\n// ---------------------------------------------------------------------------\n\nfunction createMeasureText(): MeasureTextFn {\n let canvas: HTMLCanvasElement | null = null;\n let ctx: CanvasRenderingContext2D | null = null;\n\n return (\n text: string,\n fontSize: number,\n fontWeight?: number,\n ): { width: number; height: number } => {\n if (!canvas) {\n canvas = document.createElement('canvas');\n ctx = canvas.getContext('2d');\n }\n if (!ctx) {\n // Fallback: heuristic estimation\n return { width: text.length * fontSize * 0.6, height: fontSize * 1.2 };\n }\n\n const weight = fontWeight ?? 400;\n ctx.font = `${weight} ${fontSize}px Inter, sans-serif`;\n const metrics = ctx.measureText(text);\n return {\n width: metrics.width,\n height: fontSize * 1.2,\n };\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tooltip event wiring\n// ---------------------------------------------------------------------------\n\n/**\n * Wire tooltip events on mark elements inside an SVG.\n * Returns a cleanup function to remove all listeners.\n */\nfunction wireTooltipEvents(\n svg: SVGElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n): () => void {\n const markElements = svg.querySelectorAll('[data-mark-id]');\n const cleanups: Array<() => void> = [];\n\n for (const el of markElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = tooltipDescriptors.get(markId);\n if (!content) continue;\n\n // Mouse enter -> show tooltip\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n };\n\n // Mouse move -> reposition tooltip\n const handleMouseMove = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n };\n\n // Mouse leave -> hide tooltip\n const handleMouseLeave = () => {\n tooltipManager.hide();\n };\n\n // Touch: tap to show\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length > 0) {\n const touch = touchEvent.touches[0];\n const svgRect = svg.getBoundingClientRect();\n const x = touch.clientX - svgRect.left;\n const y = touch.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('touchstart', handleTouchStart);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('touchstart', handleTouchStart);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Voronoi overlay tooltip wiring (nearest-point lookup for line/area charts)\n// ---------------------------------------------------------------------------\n\n/** A single data point with pixel coordinates, datum, and pre-computed tooltip. */\ninterface VoronoiPoint {\n x: number;\n y: number;\n datum: Record<string, unknown>;\n tooltip?: TooltipContent;\n color: string;\n}\n\n/**\n * Collect all dataPoints from line and area marks for nearest-point lookup.\n */\nfunction collectVoronoiPoints(layout: ChartLayout): VoronoiPoint[] {\n const points: VoronoiPoint[] = [];\n for (const mark of layout.marks) {\n if ((mark.type === 'line' || mark.type === 'area') && mark.dataPoints) {\n const color = mark.type === 'line' ? mark.stroke : getRepresentativeColor(mark.fill);\n for (const dp of mark.dataPoints) {\n points.push({ ...dp, color });\n }\n }\n }\n return points;\n}\n\n/**\n * Find the nearest VoronoiPoint to a given (x, y) position using linear scan.\n * Returns null if no points exist.\n */\nfunction findNearestPoint(points: VoronoiPoint[], x: number, y: number): VoronoiPoint | null {\n if (points.length === 0) return null;\n\n let nearest = points[0];\n let minDist = (points[0].x - x) ** 2 + (points[0].y - y) ** 2;\n\n for (let i = 1; i < points.length; i++) {\n const dist = (points[i].x - x) ** 2 + (points[i].y - y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n nearest = points[i];\n }\n }\n\n return nearest;\n}\n\n/**\n * Wire voronoi overlay tooltip events for line/area charts.\n * Uses a transparent overlay rect with nearest-point lookup instead of\n * per-point event listeners, eliminating DOM bloat.\n * Returns a cleanup function.\n */\nfunction wireVoronoiTooltipEvents(\n svg: SVGElement,\n layout: ChartLayout,\n tooltipManager: TooltipManager,\n): () => void {\n const overlay = svg.querySelector('[data-voronoi-overlay]');\n if (!overlay) return () => {};\n\n const voronoiPoints = collectVoronoiPoints(layout);\n if (voronoiPoints.length === 0) return () => {};\n\n const cleanups: Array<() => void> = [];\n\n const handleMouseMove = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgEl = svg as unknown as SVGSVGElement;\n const svgRect = svgEl.getBoundingClientRect();\n const viewBox = svgEl.viewBox?.baseVal;\n\n // Convert client coordinates to SVG viewBox coordinates\n const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;\n const svgX = (mouseEvent.clientX - svgRect.left) * scaleX;\n const svgY = (mouseEvent.clientY - svgRect.top) * scaleY;\n\n const nearest = findNearestPoint(voronoiPoints, svgX, svgY);\n if (!nearest?.tooltip) return;\n\n // Show tooltip at the mouse position (relative to container, not SVG viewBox)\n const containerX = mouseEvent.clientX - svgRect.left;\n const containerY = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(nearest.tooltip, containerX, containerY);\n };\n\n const handleMouseLeave = () => {\n tooltipManager.hide();\n };\n\n // Touch support\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length > 0) {\n const touch = touchEvent.touches[0];\n const svgEl = svg as unknown as SVGSVGElement;\n const svgRect = svgEl.getBoundingClientRect();\n const viewBox = svgEl.viewBox?.baseVal;\n\n const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;\n const svgX = (touch.clientX - svgRect.left) * scaleX;\n const svgY = (touch.clientY - svgRect.top) * scaleY;\n\n const nearest = findNearestPoint(voronoiPoints, svgX, svgY);\n if (!nearest?.tooltip) return;\n\n const containerX = touch.clientX - svgRect.left;\n const containerY = touch.clientY - svgRect.top;\n tooltipManager.show(nearest.tooltip, containerX, containerY);\n }\n };\n\n overlay.addEventListener('mousemove', handleMouseMove);\n overlay.addEventListener('mouseleave', handleMouseLeave);\n overlay.addEventListener('touchstart', handleTouchStart);\n\n cleanups.push(() => {\n overlay.removeEventListener('mousemove', handleMouseMove);\n overlay.removeEventListener('mouseleave', handleMouseLeave);\n overlay.removeEventListener('touchstart', handleTouchStart);\n });\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Chart event wiring (click, hover, leave on marks; legend toggle; annotation click)\n// ---------------------------------------------------------------------------\n\n/**\n * Build a map from data-mark-id to { datum, series } so event handlers\n * can look up the data row associated with a clicked/hovered mark element.\n */\nfunction buildMarkDataMap(\n layout: ChartLayout,\n): Map<string, { datum: Record<string, unknown>; series?: string }> {\n const map = new Map<string, { datum: Record<string, unknown>; series?: string }>();\n\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n switch (mark.type) {\n case 'line':\n map.set(`line-${mark.seriesKey ?? i}`, {\n // For line marks, data is an array. Use the first row as representative.\n datum: mark.data[0] ?? {},\n series: mark.seriesKey,\n });\n break;\n case 'area':\n map.set(`area-${mark.seriesKey ?? i}`, {\n datum: mark.data[0] ?? {},\n series: mark.seriesKey,\n });\n break;\n case 'rect':\n map.set(`rect-${i}`, { datum: mark.data });\n break;\n case 'arc':\n map.set(`arc-${i}`, { datum: mark.data });\n break;\n case 'point':\n map.set(`point-${i}`, { datum: mark.data });\n break;\n }\n }\n\n return map;\n}\n\n/**\n * Wire chart event handlers (onMarkClick, onMarkHover, onMarkLeave) to mark\n * elements, onLegendToggle to legend entries, and onAnnotationClick to annotation\n * elements inside an SVG.\n *\n * Returns a cleanup function to remove all listeners.\n */\nfunction wireChartEvents(\n svg: SVGElement,\n layout: ChartLayout,\n specAnnotations: import('@opendata-ai/openchart-core').Annotation[],\n handlers: ChartEventHandlers,\n): () => void {\n const cleanups: Array<() => void> = [];\n const markDataMap = buildMarkDataMap(layout);\n\n // Wire mark click/hover/leave events\n if (handlers.onMarkClick || handlers.onMarkHover || handlers.onMarkLeave) {\n const markElements = svg.querySelectorAll('[data-mark-id]');\n\n for (const el of markElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const markInfo = markDataMap.get(markId);\n if (!markInfo) continue;\n\n const series = markInfo.series ?? el.getAttribute('data-series') ?? undefined;\n\n if (handlers.onMarkClick) {\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n handlers.onMarkClick!({\n datum: markInfo.datum,\n series,\n position: {\n x: mouseEvent.clientX - svgRect.left,\n y: mouseEvent.clientY - svgRect.top,\n },\n event: mouseEvent,\n });\n };\n el.addEventListener('click', handleClick);\n cleanups.push(() => el.removeEventListener('click', handleClick));\n }\n\n if (handlers.onMarkHover) {\n const handleEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n handlers.onMarkHover!({\n datum: markInfo.datum,\n series,\n position: {\n x: mouseEvent.clientX - svgRect.left,\n y: mouseEvent.clientY - svgRect.top,\n },\n event: mouseEvent,\n });\n };\n el.addEventListener('mouseenter', handleEnter);\n cleanups.push(() => el.removeEventListener('mouseenter', handleEnter));\n }\n\n if (handlers.onMarkLeave) {\n const handleLeave = () => {\n handlers.onMarkLeave!();\n };\n el.addEventListener('mouseleave', handleLeave);\n cleanups.push(() => el.removeEventListener('mouseleave', handleLeave));\n }\n }\n }\n\n // Wire annotation click events\n if (handlers.onAnnotationClick) {\n const annotationElements = svg.querySelectorAll('.oc-annotation');\n\n for (let i = 0; i < annotationElements.length; i++) {\n const el = annotationElements[i];\n const specAnnotation = specAnnotations[i];\n if (!specAnnotation) continue;\n\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n handlers.onAnnotationClick!(specAnnotation, mouseEvent);\n };\n\n el.addEventListener('click', handleClick);\n cleanups.push(() => el.removeEventListener('click', handleClick));\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Shared drag handler utility\n// ---------------------------------------------------------------------------\n\ninterface DragConfig {\n element: SVGElement;\n svg: SVGSVGElement;\n onMove: (dx: number, dy: number) => void;\n onEnd: (dx: number, dy: number, moved: boolean) => void;\n setDragging: (dragging: boolean) => void;\n threshold?: number; // default: 3\n}\n\n/**\n * Reusable drag handler for SVG elements.\n * Handles mouse and touch events, viewBox scaling, threshold detection,\n * click suppression after drag, and cursor state.\n *\n * Returns a cleanup function that removes all listeners.\n */\nfunction createDragHandler(config: DragConfig): () => void {\n const { element, svg, onMove, onEnd, setDragging, threshold = 3 } = config;\n const cleanups: Array<() => void> = [];\n\n // Track active document listeners so cleanup can remove them mid-drag\n let activeDocMouseMove: ((e: MouseEvent) => void) | null = null;\n let activeDocMouseUp: ((e: MouseEvent) => void) | null = null;\n let activeDocTouchMove: ((e: TouchEvent) => void) | null = null;\n let activeDocTouchEnd: ((e: TouchEvent) => void) | null = null;\n let activeDocTouchCancel: ((e: TouchEvent) => void) | null = null;\n\n function getScale(): { scaleX: number; scaleY: number } {\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n return {\n scaleX: viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1,\n scaleY: viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1,\n };\n }\n\n function startDrag(startX: number, startY: number): void {\n setDragging(true);\n const { scaleX, scaleY } = getScale();\n\n element.style.cursor = 'grabbing';\n // Prevent text selection during drag\n svg.style.userSelect = 'none';\n\n const handleMove = (clientX: number, clientY: number) => {\n const dx = (clientX - startX) * scaleX;\n const dy = (clientY - startY) * scaleY;\n onMove(dx, dy);\n };\n\n const cleanupDocListeners = () => {\n if (activeDocMouseMove) {\n document.removeEventListener('mousemove', activeDocMouseMove);\n activeDocMouseMove = null;\n }\n if (activeDocMouseUp) {\n document.removeEventListener('mouseup', activeDocMouseUp);\n activeDocMouseUp = null;\n }\n if (activeDocTouchMove) {\n document.removeEventListener('touchmove', activeDocTouchMove);\n activeDocTouchMove = null;\n }\n if (activeDocTouchEnd) {\n document.removeEventListener('touchend', activeDocTouchEnd);\n activeDocTouchEnd = null;\n }\n if (activeDocTouchCancel) {\n document.removeEventListener('touchcancel', activeDocTouchCancel);\n activeDocTouchCancel = null;\n }\n };\n\n const handleEnd = (clientX: number, clientY: number) => {\n const dx = (clientX - startX) * scaleX;\n const dy = (clientY - startY) * scaleY;\n const moved = Math.abs(dx) > threshold || Math.abs(dy) > threshold;\n\n onEnd(dx, dy, moved);\n\n // Suppress click if drag actually moved\n if (moved) {\n element.addEventListener(\n 'click',\n (clickE) => {\n clickE.stopPropagation();\n },\n { capture: true, once: true },\n );\n }\n\n element.style.cursor = 'grab';\n svg.style.userSelect = '';\n\n cleanupDocListeners();\n setDragging(false);\n };\n\n // Mouse listeners\n const onMouseMove = (moveEvent: MouseEvent) => {\n handleMove(moveEvent.clientX, moveEvent.clientY);\n };\n const onMouseUp = (upEvent: MouseEvent) => {\n handleEnd(upEvent.clientX, upEvent.clientY);\n };\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n activeDocMouseMove = onMouseMove;\n activeDocMouseUp = onMouseUp;\n\n // Touch listeners\n const onTouchMove = (moveEvent: TouchEvent) => {\n if (moveEvent.touches.length > 0) {\n moveEvent.preventDefault();\n handleMove(moveEvent.touches[0].clientX, moveEvent.touches[0].clientY);\n }\n };\n const onTouchEnd = (endEvent: TouchEvent) => {\n const touch = endEvent.changedTouches[0];\n if (touch) {\n handleEnd(touch.clientX, touch.clientY);\n } else {\n handleEnd(startX, startY);\n }\n };\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', onTouchEnd);\n document.addEventListener('touchcancel', onTouchEnd);\n activeDocTouchMove = onTouchMove;\n activeDocTouchEnd = onTouchEnd;\n activeDocTouchCancel = onTouchEnd;\n }\n\n // Mouse down handler\n const handleMouseDown = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n mouseEvent.preventDefault();\n startDrag(mouseEvent.clientX, mouseEvent.clientY);\n };\n\n // Touch start handler\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length === 1) {\n touchEvent.preventDefault();\n startDrag(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n }\n };\n\n element.addEventListener('mousedown', handleMouseDown);\n element.addEventListener('touchstart', handleTouchStart, { passive: false });\n cleanups.push(() => {\n element.removeEventListener('mousedown', handleMouseDown);\n element.removeEventListener('touchstart', handleTouchStart);\n });\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n // Clean up any active document listeners (mid-drag unmount)\n if (activeDocMouseMove) {\n document.removeEventListener('mousemove', activeDocMouseMove);\n activeDocMouseMove = null;\n }\n if (activeDocMouseUp) {\n document.removeEventListener('mouseup', activeDocMouseUp);\n activeDocMouseUp = null;\n }\n if (activeDocTouchMove) {\n document.removeEventListener('touchmove', activeDocTouchMove);\n activeDocTouchMove = null;\n }\n if (activeDocTouchEnd) {\n document.removeEventListener('touchend', activeDocTouchEnd);\n activeDocTouchEnd = null;\n }\n if (activeDocTouchCancel) {\n document.removeEventListener('touchcancel', activeDocTouchCancel);\n activeDocTouchCancel = null;\n }\n // Restore user-select in case of mid-drag cleanup\n svg.style.userSelect = '';\n };\n}\n\n// ---------------------------------------------------------------------------\n// Annotation drag editing\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag-to-reposition on text annotation labels.\n * Only activates for text annotations (not range or refline).\n * During drag, applies a CSS transform for real-time visual feedback and\n * counter-adjusts straight connector endpoints so the data-point end stays fixed.\n * On mouseup, fires the callback with the updated offset values.\n *\n * Returns a cleanup function to remove all listeners.\n */\nfunction wireAnnotationDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onAnnotationEdit:\n | ((annotation: TextAnnotation, updatedOffset: AnnotationOffset) => void)\n | undefined,\n onEdit: ((edit: ElementEdit) => void) | undefined,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const annotationElements = svg.querySelectorAll('.oc-annotation-text');\n const cleanups: Array<() => void> = [];\n\n for (const el of annotationElements) {\n const indexStr = el.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation || specAnnotation.type !== 'text') continue;\n\n const textAnnotation = specAnnotation as TextAnnotation;\n const annotationG = el as SVGGElement;\n\n // Visual affordance: show grab cursor\n annotationG.style.cursor = 'grab';\n\n // Stash connector info for real-time updates during drag\n const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const origX2 = connectorLine ? Number(connectorLine.getAttribute('x2')) : 0;\n const origY2 = connectorLine ? Number(connectorLine.getAttribute('y2')) : 0;\n\n // For curved connectors, stash path/polygon elements to hide during drag\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n const arrowhead = annotationG.querySelector('polygon.oc-annotation-connector');\n const hasCurvedConnector = curvedPath !== null;\n\n const origDx = textAnnotation.offset?.dx ?? 0;\n const origDy = textAnnotation.offset?.dy ?? 0;\n\n const cleanup = createDragHandler({\n element: annotationG,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n // Move the entire annotation group\n annotationG.setAttribute('transform', `translate(${dx}, ${dy})`);\n\n // For straight connectors, counter-adjust the data-point end\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2 - dx));\n connectorLine.setAttribute('y2', String(origY2 - dy));\n }\n\n // Hide curved connector elements during drag\n if (hasCurvedConnector) {\n if (curvedPath) curvedPath.setAttribute('display', 'none');\n if (arrowhead) arrowhead.setAttribute('display', 'none');\n }\n },\n onEnd: (dx, dy, moved) => {\n // Clean up visual state\n annotationG.removeAttribute('transform');\n\n // Restore straight connector to original values\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2));\n connectorLine.setAttribute('y2', String(origY2));\n }\n\n // Restore curved connector elements\n if (hasCurvedConnector) {\n if (curvedPath) curvedPath.removeAttribute('display');\n if (arrowhead) arrowhead.removeAttribute('display');\n }\n\n if (moved) {\n const newOffset: AnnotationOffset = {\n dx: origDx + dx,\n dy: origDy + dy,\n };\n // Fire legacy callback\n onAnnotationEdit?.(textAnnotation, newOffset);\n // Fire unified edit callback\n onEdit?.({ type: 'annotation', annotation: textAnnotation, offset: newOffset });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Connector endpoint drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on connector endpoint handles for text annotations.\n * Dynamically creates invisible handle circles at connector endpoints\n * so they only exist when editing is active (not in every chart).\n * During drag, updates the handle position and the connector line endpoints.\n * On end, fires onEdit with the accumulated endpoint offset.\n *\n * Shows handles on hover over the parent annotation group.\n * Returns a cleanup function that removes handles and all listeners.\n */\nfunction wireConnectorEndpointDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const SVG_NS = 'http://www.w3.org/2000/svg';\n const cleanups: Array<() => void> = [];\n const annotationGroups = svg.querySelectorAll('.oc-annotation-text');\n\n for (const el of annotationGroups) {\n const annotationG = el as SVGGElement;\n const indexStr = annotationG.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation || specAnnotation.type !== 'text') continue;\n\n const textAnnotation = specAnnotation as TextAnnotation;\n\n // Find connector line or curved connector to determine endpoints\n const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n if (!connectorLine && !curvedPath) continue;\n\n // Determine connector endpoint positions from the connector element\n let fromX: number, fromY: number, toX: number, toY: number;\n if (connectorLine) {\n fromX = Number(connectorLine.getAttribute('x1')) || 0;\n fromY = Number(connectorLine.getAttribute('y1')) || 0;\n toX = Number(connectorLine.getAttribute('x2')) || 0;\n toY = Number(connectorLine.getAttribute('y2')) || 0;\n } else {\n // For curved connectors, get positions from the path data\n // The path starts at M x y, so parse the first coordinates\n const pathD = curvedPath!.getAttribute('d') ?? '';\n const mMatch = pathD.match(/M\\s*([\\d.e+-]+)\\s+([\\d.e+-]+)/);\n fromX = mMatch ? Number(mMatch[1]) : 0;\n fromY = mMatch ? Number(mMatch[2]) : 0;\n // For curved connectors, the arrow polygon has the target\n const arrowhead = annotationG.querySelector('polygon.oc-annotation-connector');\n const points = arrowhead?.getAttribute('points') ?? '';\n const firstPoint = points.split(' ')[0] ?? '0,0';\n const [px, py] = firstPoint.split(',');\n toX = Number(px) || 0;\n toY = Number(py) || 0;\n }\n\n // Create handles dynamically\n const endpoints: Array<{ name: 'from' | 'to'; cx: number; cy: number }> = [\n { name: 'from', cx: fromX, cy: fromY },\n { name: 'to', cx: toX, cy: toY },\n ];\n\n const createdHandles: SVGCircleElement[] = [];\n\n for (const ep of endpoints) {\n // Skip endpoints with invalid coordinates to prevent NaN in SVG attributes\n if (!Number.isFinite(ep.cx) || !Number.isFinite(ep.cy)) continue;\n\n const handleEl = document.createElementNS(SVG_NS, 'circle') as SVGCircleElement;\n handleEl.setAttribute('class', 'oc-connector-handle');\n handleEl.setAttribute('data-endpoint', ep.name);\n handleEl.setAttribute('cx', String(ep.cx));\n handleEl.setAttribute('cy', String(ep.cy));\n handleEl.setAttribute('r', '4');\n handleEl.setAttribute('opacity', '0');\n handleEl.setAttribute('fill', 'currentColor');\n handleEl.setAttribute('stroke', 'currentColor');\n annotationG.appendChild(handleEl);\n createdHandles.push(handleEl);\n\n const origCx = ep.cx;\n const origCy = ep.cy;\n\n // Prevent parent annotation drag from firing\n const stopProp = (e: Event) => {\n e.stopPropagation();\n };\n handleEl.addEventListener('mousedown', stopProp);\n handleEl.addEventListener('touchstart', stopProp);\n cleanups.push(() => {\n handleEl.removeEventListener('mousedown', stopProp);\n handleEl.removeEventListener('touchstart', stopProp);\n });\n\n const cleanup = createDragHandler({\n element: handleEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n handleEl.setAttribute('cx', String(origCx + dx));\n handleEl.setAttribute('cy', String(origCy + dy));\n\n if (connectorLine) {\n if (ep.name === 'from') {\n connectorLine.setAttribute('x1', String(origCx + dx));\n connectorLine.setAttribute('y1', String(origCy + dy));\n } else {\n connectorLine.setAttribute('x2', String(origCx + dx));\n connectorLine.setAttribute('y2', String(origCy + dy));\n }\n }\n },\n onEnd: (dx, dy, moved) => {\n handleEl.setAttribute('cx', String(origCx));\n handleEl.setAttribute('cy', String(origCy));\n\n if (connectorLine) {\n if (ep.name === 'from') {\n connectorLine.setAttribute('x1', String(origCx));\n connectorLine.setAttribute('y1', String(origCy));\n } else {\n connectorLine.setAttribute('x2', String(origCx));\n connectorLine.setAttribute('y2', String(origCy));\n }\n }\n\n if (moved) {\n const existingOffset = textAnnotation.connectorOffset?.[ep.name];\n const origEndDx = existingOffset?.dx ?? 0;\n const origEndDy = existingOffset?.dy ?? 0;\n onEdit({\n type: 'annotation-connector',\n annotation: textAnnotation,\n endpoint: ep.name,\n offset: { dx: origEndDx + dx, dy: origEndDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n // Wire hover to show/hide handles\n const showHandles = () => {\n for (const h of createdHandles) {\n h.setAttribute('opacity', '0.6');\n }\n };\n const hideHandles = () => {\n for (const h of createdHandles) {\n h.setAttribute('opacity', '0');\n }\n };\n\n annotationG.addEventListener('mouseenter', showHandles);\n annotationG.addEventListener('mouseleave', hideHandles);\n cleanups.push(() => {\n annotationG.removeEventListener('mouseenter', showHandles);\n annotationG.removeEventListener('mouseleave', hideHandles);\n // Remove dynamically created handles\n for (const h of createdHandles) {\n h.remove();\n }\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Range/refline annotation label drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on range and refline annotation labels.\n * On drag end, fires onEdit with the label offset.\n * Returns a cleanup function.\n */\nfunction wireAnnotationLabelDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const cleanups: Array<() => void> = [];\n\n // Target range and refline annotation labels\n const selectors = [\n '.oc-annotation-range .oc-annotation-label',\n '.oc-annotation-refline .oc-annotation-label',\n ];\n\n for (const selector of selectors) {\n const labels = svg.querySelectorAll(selector);\n\n for (const label of labels) {\n const annotationG = label.closest('.oc-annotation') as SVGGElement | null;\n if (!annotationG) continue;\n\n const indexStr = annotationG.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation) continue;\n\n const labelEl = label as SVGTextElement;\n labelEl.style.cursor = 'grab';\n\n const isRange = specAnnotation.type === 'range';\n const existingLabelOffset = isRange\n ? (specAnnotation as RangeAnnotation).labelOffset\n : (specAnnotation as RefLineAnnotation).labelOffset;\n const origLabelDx = existingLabelOffset?.dx ?? 0;\n const origLabelDy = existingLabelOffset?.dy ?? 0;\n\n const cleanup = createDragHandler({\n element: labelEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n if (isRange) {\n onEdit({\n type: 'range-label',\n annotation: specAnnotation as RangeAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n } else {\n onEdit({\n type: 'refline-label',\n annotation: specAnnotation as RefLineAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n }\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Chrome text drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on chrome text elements (title, subtitle, source, byline, footer).\n * On drag end, fires onEdit with the chrome key, text, and offset.\n * Returns a cleanup function.\n */\nfunction wireChromeDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const chromeTexts = svg.querySelectorAll('.oc-chrome text[data-chrome-key]');\n const cleanups: Array<() => void> = [];\n\n // Read existing chrome offsets from the spec\n const chromeConfig = 'chrome' in spec ? spec.chrome : undefined;\n\n for (const el of chromeTexts) {\n const textEl = el as SVGTextElement;\n const key = textEl.getAttribute('data-chrome-key') as ChromeKey;\n if (!key) continue;\n\n // Read existing offset for this chrome element\n const chromeEntry = chromeConfig?.[key];\n const existingOffset =\n typeof chromeEntry === 'object' && chromeEntry !== null ? chromeEntry.offset : undefined;\n const origChromeDx = existingOffset?.dx ?? 0;\n const origChromeDy = existingOffset?.dy ?? 0;\n\n textEl.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: textEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (textEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (textEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({\n type: 'chrome',\n key,\n text: textEl.textContent ?? '',\n offset: { dx: origChromeDx + dx, dy: origChromeDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legend drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on the legend group.\n * Click suppression prevents legend toggle from firing after a drag.\n * On drag end, fires onEdit with the legend offset.\n * Returns a cleanup function.\n */\nfunction wireLegendDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const legendG = svg.querySelector('.oc-legend') as SVGGElement | null;\n if (!legendG) return () => {};\n\n const cleanups: Array<() => void> = [];\n\n // Read existing legend offset from the spec\n const legendConfig = 'legend' in spec ? spec.legend : undefined;\n const origLegendDx = legendConfig?.offset?.dx ?? 0;\n const origLegendDy = legendConfig?.offset?.dy ?? 0;\n\n // Set grab cursor on the legend background, not on entry elements\n legendG.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: legendG,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (legendG as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (legendG as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({ type: 'legend', offset: { dx: origLegendDx + dx, dy: origLegendDy + dy } });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Series label drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on series label elements (.oc-mark-label[data-series]).\n * On drag end, fires onEdit with the series name and offset.\n * Returns a cleanup function.\n */\nfunction wireSeriesLabelDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const labels = svg.querySelectorAll('.oc-mark-label');\n const cleanups: Array<() => void> = [];\n\n // Read existing label offsets from the spec\n const labelsConfig = 'labels' in spec ? spec.labels : undefined;\n\n for (const label of labels) {\n const labelEl = label as SVGTextElement;\n // Check label itself first, then fall back to the parent mark group's data-series\n const series =\n labelEl.getAttribute('data-series') ??\n labelEl.closest('[data-series]')?.getAttribute('data-series');\n if (!series) continue;\n\n // Read existing offset for this series label\n const existingSeriesOffset = labelsConfig?.offsets?.[series];\n const origSeriesDx = existingSeriesOffset?.dx ?? 0;\n const origSeriesDy = existingSeriesOffset?.dy ?? 0;\n\n labelEl.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: labelEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({\n type: 'series-label',\n series,\n offset: { dx: origSeriesDx + dx, dy: origSeriesDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legend interactivity\n// ---------------------------------------------------------------------------\n\n/**\n * Wire click handlers on legend entries to toggle series visibility.\n * Fires onEdit with { type: 'legend-toggle', series, hidden } for each toggle,\n * and optionally calls the legacy onLegendToggle callback.\n * Legend entries for hidden series stay visible but dimmed (opacity 0.3).\n * Returns a cleanup function.\n */\nfunction wireLegendInteraction(\n svg: SVGElement,\n _layout: ChartLayout,\n onLegendToggle?: (series: string, visible: boolean) => void,\n onEdit?: (edit: ElementEdit) => void,\n): () => void {\n const legendEntries = svg.querySelectorAll('[data-legend-index]');\n const cleanups: Array<() => void> = [];\n\n // Track which series are hidden\n const hiddenSeries = new Set<string>();\n\n for (const entry of legendEntries) {\n // Skip overflow indicator entries (\"+N more\")\n if (entry.getAttribute('data-legend-overflow') === 'true') continue;\n\n const handleClick = () => {\n const label = entry.getAttribute('data-legend-label');\n if (!label) return;\n\n if (hiddenSeries.has(label)) {\n hiddenSeries.delete(label);\n entry.setAttribute('opacity', '1');\n entry.setAttribute('aria-label', `${label}: visible`);\n onLegendToggle?.(label, true);\n onEdit?.({ type: 'legend-toggle', series: label, hidden: false });\n } else {\n hiddenSeries.add(label);\n entry.setAttribute('opacity', '0.3');\n entry.setAttribute('aria-label', `${label}: hidden`);\n onLegendToggle?.(label, false);\n onEdit?.({ type: 'legend-toggle', series: label, hidden: true });\n }\n\n // Toggle visibility of marks with matching series.\n // Uses the data-series attribute set by the SVG renderer, which works\n // for all mark types (line, area, rect, arc, point).\n const marks = svg.querySelectorAll('.oc-mark');\n for (const mark of marks) {\n const seriesName = mark.getAttribute('data-series');\n if (!seriesName) continue;\n\n if (hiddenSeries.has(seriesName)) {\n (mark as SVGElement).style.display = 'none';\n } else {\n (mark as SVGElement).style.display = '';\n }\n }\n };\n\n entry.addEventListener('click', handleClick);\n cleanups.push(() => entry.removeEventListener('click', handleClick));\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Keyboard navigation\n// ---------------------------------------------------------------------------\n\n/**\n * Wire keyboard navigation on the SVG element.\n * Arrow keys move focus between mark elements. Enter/Space shows tooltip.\n * Escape hides tooltip. Returns a cleanup function.\n */\nfunction wireKeyboardNav(\n svg: SVGElement,\n container: HTMLElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n layout: ChartLayout,\n): () => void {\n // Make container focusable\n container.setAttribute('tabindex', '0');\n container.setAttribute('aria-roledescription', 'chart');\n container.setAttribute('aria-label', layout.a11y.altText);\n\n // Collect navigable mark elements (those with tooltip content)\n const markElements: SVGElement[] = [];\n const allMarkEls = svg.querySelectorAll('[data-mark-id]');\n for (const el of allMarkEls) {\n const markId = el.getAttribute('data-mark-id');\n if (markId && tooltipDescriptors.has(markId)) {\n markElements.push(el as SVGElement);\n }\n }\n\n let focusIndex = -1;\n\n function highlightMark(index: number): void {\n // Remove previous highlight\n if (focusIndex >= 0 && focusIndex < markElements.length) {\n markElements[focusIndex].classList.remove('oc-mark-focused');\n markElements[focusIndex].removeAttribute('aria-selected');\n }\n\n focusIndex = index;\n\n if (focusIndex >= 0 && focusIndex < markElements.length) {\n const el = markElements[focusIndex];\n el.classList.add('oc-mark-focused');\n el.setAttribute('aria-selected', 'true');\n }\n }\n\n function showTooltipForFocused(): void {\n if (focusIndex < 0 || focusIndex >= markElements.length) return;\n\n const el = markElements[focusIndex];\n const markId = el.getAttribute('data-mark-id');\n if (!markId) return;\n\n const content = tooltipDescriptors.get(markId);\n if (!content) return;\n\n // Position tooltip near the mark element\n const bbox = el.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const x = bbox.left + bbox.width / 2 - containerRect.left;\n const y = bbox.top - containerRect.top;\n tooltipManager.show(content, x, y);\n }\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (markElements.length === 0) return;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowDown': {\n e.preventDefault();\n const next = focusIndex < markElements.length - 1 ? focusIndex + 1 : 0;\n highlightMark(next);\n showTooltipForFocused();\n break;\n }\n case 'ArrowLeft':\n case 'ArrowUp': {\n e.preventDefault();\n const prev = focusIndex > 0 ? focusIndex - 1 : markElements.length - 1;\n highlightMark(prev);\n showTooltipForFocused();\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (focusIndex >= 0) {\n showTooltipForFocused();\n } else if (markElements.length > 0) {\n highlightMark(0);\n showTooltipForFocused();\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n tooltipManager.hide();\n highlightMark(-1);\n break;\n }\n }\n };\n\n container.addEventListener('keydown', handleKeyDown);\n\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n container.removeAttribute('tabindex');\n container.removeAttribute('aria-roledescription');\n container.removeAttribute('aria-label');\n };\n}\n\n// ---------------------------------------------------------------------------\n// Hidden data table for screen readers\n// ---------------------------------------------------------------------------\n\n/**\n * Create a visually-hidden data table from the chart's a11y fallback data.\n * Returns the table element (append to container) and a cleanup function.\n */\nfunction createScreenReaderTable(\n layout: ChartLayout,\n container: HTMLElement,\n): HTMLTableElement | null {\n const data = layout.a11y.dataTableFallback;\n if (!data || data.length === 0) return null;\n\n const table = document.createElement('table');\n table.className = 'oc-sr-only';\n // Inline critical SR-only styles so the table stays hidden even when the\n // external stylesheet isn't loaded (e.g. CDN / esm.sh usage).\n table.style.position = 'absolute';\n table.style.width = '1px';\n table.style.height = '1px';\n table.style.padding = '0';\n table.style.margin = '-1px';\n table.style.overflow = 'hidden';\n table.style.clipPath = 'inset(50%)';\n table.style.whiteSpace = 'nowrap';\n table.style.borderWidth = '0';\n table.setAttribute('role', 'table');\n table.setAttribute('aria-label', `Data table: ${layout.a11y.altText}`);\n\n // First row is headers\n if (data.length > 0) {\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n const headers = data[0] as unknown[];\n for (const header of headers) {\n const th = document.createElement('th');\n th.textContent = String(header ?? '');\n th.setAttribute('scope', 'col');\n headerRow.appendChild(th);\n }\n thead.appendChild(headerRow);\n table.appendChild(thead);\n }\n\n // Remaining rows are data\n if (data.length > 1) {\n const tbody = document.createElement('tbody');\n for (let i = 1; i < data.length; i++) {\n const tr = document.createElement('tr');\n const cells = data[i] as unknown[];\n for (const cell of cells) {\n const td = document.createElement('td');\n td.textContent = String(cell ?? '');\n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n table.appendChild(tbody);\n }\n\n container.appendChild(table);\n return table;\n}\n\n// ---------------------------------------------------------------------------\n// Editable element helpers\n// ---------------------------------------------------------------------------\n\n/** CSS for editable hover feedback, injected into the SVG as a <style> element. */\nconst EDITABLE_HOVER_CSS = `\n.oc-editable-hover {\n outline: 1.5px solid rgba(79, 70, 229, 0.35);\n outline-offset: 2px;\n border-radius: 2px;\n}\n`;\n\n/**\n * Inject editable styles into an SVG element and make it focusable.\n * Called when any editing callback is provided.\n */\nfunction makeEditable(svg: SVGElement): void {\n svg.setAttribute('tabindex', '0');\n svg.style.outline = 'none';\n\n // Inject hover style into SVG defs\n const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');\n style.textContent = EDITABLE_HOVER_CSS;\n svg.insertBefore(style, svg.firstChild);\n}\n\n/**\n * Check whether any editing-related callback is provided in the options.\n */\nfunction hasEditingCallbacks(opts?: MountOptions): boolean {\n return !!(opts?.onEdit || opts?.onSelect || opts?.onDeselect || opts?.onTextEdit);\n}\n\n/**\n * Find a DOM element inside the SVG that matches the given ElementRef.\n */\nfunction findElementByRef(svg: SVGElement, ref: ElementRef): SVGElement | null {\n switch (ref.type) {\n case 'annotation': {\n // Prefer id-based lookup when available\n if (ref.id) {\n const byId = svg.querySelector(`[data-annotation-id=\"${ref.id}\"]`);\n if (byId) return byId as SVGElement;\n }\n return svg.querySelector(`[data-annotation-index=\"${ref.index}\"]`) as SVGElement | null;\n }\n case 'chrome':\n return svg.querySelector(`[data-chrome-key=\"${ref.key}\"]`) as SVGElement | null;\n case 'series-label':\n return svg.querySelector(`.oc-mark-label[data-series=\"${ref.series}\"]`) as SVGElement | null;\n case 'legend':\n return svg.querySelector('.oc-legend') as SVGElement | null;\n case 'legend-entry':\n return svg.querySelector(`[data-legend-index=\"${ref.index}\"]`) as SVGElement | null;\n }\n}\n\n/**\n * Build an ElementRef from a DOM element's data attributes.\n * Walks up the tree to find the closest editable ancestor if needed.\n */\nfunction buildElementRef(element: Element, _specAnnotations: Annotation[]): ElementRef | null {\n // Check for annotation\n const annotationEl = element.closest('[data-annotation-index]');\n if (annotationEl) {\n const index = Number(annotationEl.getAttribute('data-annotation-index'));\n const id = annotationEl.getAttribute('data-annotation-id') ?? undefined;\n return elementRef.annotation(index, id);\n }\n\n // Check for chrome\n const chromeEl = element.closest('[data-chrome-key]');\n if (chromeEl) {\n const key = chromeEl.getAttribute('data-chrome-key') as ChromeKey;\n if (key) return elementRef.chrome(key);\n }\n\n // Check for series label\n const seriesLabelEl = element.closest('.oc-mark-label[data-series]');\n if (seriesLabelEl) {\n const series = seriesLabelEl.getAttribute('data-series');\n if (series) return elementRef.seriesLabel(series);\n }\n\n // Check for legend entry\n const legendEntryEl = element.closest('[data-legend-index]');\n if (legendEntryEl) {\n const index = Number(legendEntryEl.getAttribute('data-legend-index'));\n const series = legendEntryEl.getAttribute('data-legend-label') ?? '';\n return elementRef.legendEntry(series, index);\n }\n\n // Check for legend group\n const legendEl = element.closest('.oc-legend');\n if (legendEl) return elementRef.legend();\n\n return null;\n}\n\n/**\n * Get an ordered list of all editable ElementRefs from the current spec and layout.\n * Order: chrome (title, subtitle, source, byline, footer), annotations by index,\n * series labels alphabetical, legend.\n */\nfunction getEditableElements(\n spec: ChartSpec | LayerSpec | GraphSpec,\n layout: ChartLayout,\n): ElementRef[] {\n const refs: ElementRef[] = [];\n\n // Chrome keys in display order\n const chromeKeys: ChromeKey[] = ['title', 'subtitle', 'source', 'byline', 'footer'];\n for (const key of chromeKeys) {\n if (layout.chrome[key]) {\n refs.push(elementRef.chrome(key));\n }\n }\n\n // Annotations by index\n const annotations: Annotation[] =\n 'annotations' in spec && Array.isArray(spec.annotations) ? spec.annotations : [];\n for (let i = 0; i < annotations.length; i++) {\n refs.push(elementRef.annotation(i, annotations[i].id));\n }\n\n // Series labels (alphabetical)\n const seriesLabels: string[] = [];\n for (const mark of layout.marks) {\n if (mark.type === 'line' && mark.label?.visible && mark.seriesKey) {\n seriesLabels.push(mark.seriesKey);\n }\n }\n seriesLabels.sort();\n for (const series of seriesLabels) {\n refs.push(elementRef.seriesLabel(series));\n }\n\n // Legend\n if (layout.legend.entries.length > 0) {\n refs.push(elementRef.legend());\n }\n\n return refs;\n}\n\n/**\n * Check if an ElementRef points to a text-editable element (chrome text or text annotation).\n */\nfunction isTextEditable(ref: ElementRef, specAnnotations: Annotation[]): boolean {\n if (ref.type === 'chrome') return true;\n if (ref.type === 'annotation') {\n const annotation = specAnnotations[ref.index];\n return annotation?.type === 'text';\n }\n return false;\n}\n\n/**\n * Get the current text content for an element ref.\n */\nfunction getElementText(ref: ElementRef, spec: ChartSpec | LayerSpec | GraphSpec): string | null {\n if (ref.type === 'chrome') {\n const chromeConfig = 'chrome' in spec ? spec.chrome : undefined;\n if (!chromeConfig) return null;\n const entry = chromeConfig[ref.key];\n if (typeof entry === 'string') return entry;\n if (typeof entry === 'object' && entry !== null && 'text' in entry) {\n return (entry as { text: string }).text;\n }\n return null;\n }\n if (ref.type === 'annotation') {\n const annotations: Annotation[] =\n 'annotations' in spec && Array.isArray(spec.annotations) ? spec.annotations : [];\n const annotation = annotations[ref.index];\n if (annotation?.type === 'text') return (annotation as TextAnnotation).text ?? null;\n if (annotation?.label) return annotation.label;\n return null;\n }\n return null;\n}\n\n/**\n * Compare two ElementRefs for equality.\n */\nfunction refsEqual(a: ElementRef | null, b: ElementRef | null): boolean {\n if (a === null || b === null) return a === b;\n if (a.type !== b.type) return false;\n switch (a.type) {\n case 'annotation': {\n const bAnno = b as typeof a;\n if (a.id && bAnno.id) return a.id === bAnno.id;\n return a.index === bAnno.index;\n }\n case 'chrome':\n return a.key === (b as typeof a).key;\n case 'series-label':\n return a.series === (b as typeof a).series;\n case 'legend':\n return true;\n case 'legend-entry': {\n const bEntry = b as typeof a;\n return a.index === bEntry.index && a.series === bEntry.series;\n }\n }\n}\n\n/**\n * Render a selection overlay rectangle around a target element.\n * Returns the overlay group element.\n */\nfunction renderSelectionOverlay(\n svg: SVGElement,\n ref: ElementRef,\n layout: ChartLayout,\n): SVGGElement | null {\n const target = findElementByRef(svg, ref);\n if (!target) return null;\n\n const bbox = (target as SVGGraphicsElement).getBBox();\n const padding = 4;\n\n // Resolve accent color from theme\n const accentColor = layout.theme.colors.categorical?.[0] ?? '#4f46e5';\n\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n g.setAttribute('class', 'oc-selection-overlay');\n\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n rect.setAttribute('x', String(bbox.x - padding));\n rect.setAttribute('y', String(bbox.y - padding));\n rect.setAttribute('width', String(bbox.width + padding * 2));\n rect.setAttribute('height', String(bbox.height + padding * 2));\n rect.setAttribute('rx', '3');\n rect.setAttribute('fill', 'transparent');\n rect.setAttribute('stroke', accentColor);\n rect.setAttribute('stroke-width', '1.5');\n rect.setAttribute('pointer-events', 'none');\n\n g.appendChild(rect);\n svg.appendChild(g);\n\n return g;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a chart instance from a spec and mount it into a container.\n *\n * @param container - The DOM element to render into.\n * @param spec - The visualization spec.\n * @param options - Mount options (theme, darkMode, responsive, etc.).\n * @returns A ChartInstance with update/resize/export/destroy methods.\n */\nexport function createChart(\n container: HTMLElement,\n spec: ChartSpec | LayerSpec | GraphSpec,\n options?: MountOptions,\n): ChartInstance {\n let currentSpec: ChartSpec | LayerSpec | GraphSpec = spec;\n let currentLayout: ChartLayout;\n let svgElement: SVGElement | null = null;\n let tooltipManager: TooltipManager | null = null;\n let disconnectResize: (() => void) | null = null;\n let cleanupTooltipEvents: (() => void) | null = null;\n let cleanupVoronoiEvents: (() => void) | null = null;\n let cleanupKeyboardNav: (() => void) | null = null;\n let cleanupLegend: (() => void) | null = null;\n let cleanupChartEvents: (() => void) | null = null;\n let cleanupAnnotationDrag: (() => void) | null = null;\n let cleanupEditDrags: (() => void) | null = null;\n let cleanupSelection: (() => void) | null = null;\n let cleanupKeyboardEdit: (() => void) | null = null;\n let srTable: HTMLTableElement | null = null;\n let destroyed = false;\n let isDragging = false;\n let pendingRender = false;\n let resizeTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Animation state\n let isFirstRender = true;\n let cleanupAnimations: (() => void) | null = null;\n let pendingResize = false;\n\n // Selection and text editing state\n let selectedElement: ElementRef | null = options?.selectedElement ?? null;\n let overlayElement: SVGGElement | null = null;\n let isTextEditingActive = false;\n let textEditCleanup: (() => void) | null = null;\n\n const measureText = createMeasureText();\n\n function compile(): ChartLayout {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n measureText,\n };\n\n if (isLayerSpec(currentSpec)) {\n return compileLayer(currentSpec as LayerSpec, compileOpts);\n }\n return compileChart(currentSpec as ChartSpec | GraphSpec, compileOpts);\n }\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n /** Get the current spec's annotations array. */\n function getSpecAnnotations(): Annotation[] {\n return 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n }\n\n /** Select an element: render overlay, fire onSelect, update state. */\n function selectElement(ref: ElementRef): void {\n if (!svgElement) return;\n\n // Confirm the target element exists before deselecting the previous one\n const target = findElementByRef(svgElement, ref);\n if (!target) return;\n\n // Deselect previous if different\n if (selectedElement && !refsEqual(selectedElement, ref)) {\n deselectElement();\n }\n\n selectedElement = ref;\n overlayElement = renderSelectionOverlay(svgElement, ref, currentLayout);\n options?.onSelect?.(ref);\n\n // Focus SVG for keyboard events\n (svgElement as SVGSVGElement).focus();\n }\n\n /** Deselect the current element: remove overlay, fire onDeselect, clear state. */\n function deselectElement(): void {\n if (!selectedElement) return;\n\n // Cancel text editing if active\n if (isTextEditingActive && textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n\n const prev = selectedElement;\n selectedElement = null;\n\n if (overlayElement?.parentNode) {\n overlayElement.parentNode.removeChild(overlayElement);\n }\n overlayElement = null;\n\n options?.onDeselect?.(prev);\n }\n\n /** Enter text editing mode for the currently selected element. */\n function enterTextEditing(): void {\n if (!svgElement || !selectedElement || isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n if (!isTextEditable(selectedElement, specAnnotations)) return;\n\n const currentText = getElementText(selectedElement, currentSpec);\n if (currentText === null) return;\n\n // Find the text element within the selected element\n const target = findElementByRef(svgElement, selectedElement);\n if (!target) return;\n\n // The target might be a group; find the actual text element\n const textEl = target.tagName === 'text' ? target : target.querySelector('text');\n if (!textEl) return;\n\n isTextEditingActive = true;\n const editRef = selectedElement;\n\n const overlay = createTextEditOverlay({\n container,\n svg: svgElement as SVGSVGElement,\n targetElement: textEl as SVGElement,\n currentText,\n onCommit: (newText: string) => {\n isTextEditingActive = false;\n textEditCleanup = null;\n\n if (newText !== currentText) {\n // Fire text edit callbacks\n options?.onTextEdit?.(editRef, currentText, newText);\n options?.onEdit?.({\n type: 'text-edit',\n element: editRef,\n oldText: currentText,\n newText,\n });\n }\n },\n onCancel: () => {\n isTextEditingActive = false;\n textEditCleanup = null;\n },\n });\n\n textEditCleanup = overlay.destroy;\n }\n\n /**\n * Wire click-based selection events on the SVG.\n * Uses event delegation for efficiency.\n */\n function wireSelectionEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n const cleanups: Array<() => void> = [];\n\n // Click handler for selection\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n\n // Don't interfere with text editing\n if (isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref) {\n // Clicked on an editable element\n selectElement(ref);\n } else {\n // Clicked on empty area / non-editable element, deselect\n deselectElement();\n }\n };\n\n svg.addEventListener('click', handleClick);\n cleanups.push(() => svg.removeEventListener('click', handleClick));\n\n // Hover feedback on editable elements\n const handleMouseEnter = (e: Event) => {\n const target = (e.target as Element).closest(\n '[data-annotation-index], [data-chrome-key], .oc-mark-label[data-series], .oc-legend, [data-legend-index]',\n );\n if (target) {\n (target as SVGElement).classList.add('oc-editable-hover');\n }\n };\n\n const handleMouseLeave = (e: Event) => {\n const target = (e.target as Element).closest('.oc-editable-hover');\n if (target) {\n (target as SVGElement).classList.remove('oc-editable-hover');\n }\n };\n\n svg.addEventListener('mouseenter', handleMouseEnter, true);\n svg.addEventListener('mouseleave', handleMouseLeave, true);\n cleanups.push(() => {\n svg.removeEventListener('mouseenter', handleMouseEnter, true);\n svg.removeEventListener('mouseleave', handleMouseLeave, true);\n });\n\n // Double-click to enter text editing\n const handleDblClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref && isTextEditable(ref, specAnnotations)) {\n // Select first if not already selected\n if (!refsEqual(selectedElement, ref)) {\n selectElement(ref);\n }\n enterTextEditing();\n }\n };\n\n svg.addEventListener('dblclick', handleDblClick);\n cleanups.push(() => svg.removeEventListener('dblclick', handleDblClick));\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n /**\n * Wire keyboard events for edit actions on the SVG.\n * Delete/Backspace -> delete, Escape -> cancel/deselect, Tab -> cycle, Enter -> text edit.\n */\n function wireKeyboardEditEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n const specAnnotations = getSpecAnnotations();\n\n switch (e.key) {\n case 'Delete':\n case 'Backspace': {\n if (selectedElement && !isTextEditingActive) {\n e.preventDefault();\n options?.onEdit?.({ type: 'delete', element: selectedElement });\n // Stay selected (consumer decides whether to remove the element)\n }\n break;\n }\n\n case 'Escape': {\n e.preventDefault();\n if (isTextEditingActive && textEditCleanup) {\n // Cancel text editing, remain selected\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n } else if (selectedElement) {\n deselectElement();\n }\n break;\n }\n\n case 'ArrowDown':\n case 'ArrowRight': {\n if (!isTextEditingActive && selectedElement) {\n e.preventDefault();\n const editables = getEditableElements(currentSpec, currentLayout);\n if (editables.length === 0) break;\n\n const currentIndex = editables.findIndex((r) => refsEqual(r, selectedElement));\n const nextIndex = currentIndex >= editables.length - 1 ? 0 : currentIndex + 1;\n\n selectElement(editables[nextIndex]);\n }\n break;\n }\n\n case 'ArrowUp':\n case 'ArrowLeft': {\n if (!isTextEditingActive && selectedElement) {\n e.preventDefault();\n const editables = getEditableElements(currentSpec, currentLayout);\n if (editables.length === 0) break;\n\n const currentIndex = editables.findIndex((r) => refsEqual(r, selectedElement));\n const nextIndex = currentIndex <= 0 ? editables.length - 1 : currentIndex - 1;\n\n selectElement(editables[nextIndex]);\n }\n break;\n }\n\n case 'Enter': {\n if (selectedElement && !isTextEditingActive) {\n if (isTextEditable(selectedElement, specAnnotations)) {\n e.preventDefault();\n enterTextEditing();\n }\n }\n break;\n }\n }\n };\n\n svg.addEventListener('keydown', handleKeyDown);\n\n return () => {\n svg.removeEventListener('keydown', handleKeyDown);\n };\n }\n\n function render(): void {\n // Defer re-render if a drag is in progress to avoid destroying the dragged element\n if (isDragging) {\n pendingRender = true;\n return;\n }\n\n // Cancel any in-progress entrance animations before tearing down\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n cancelAnimations(svgElement);\n\n // Clean up previous render\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n if (cleanupVoronoiEvents) {\n cleanupVoronoiEvents();\n cleanupVoronoiEvents = null;\n }\n if (cleanupKeyboardNav) {\n cleanupKeyboardNav();\n cleanupKeyboardNav = null;\n }\n if (cleanupLegend) {\n cleanupLegend();\n cleanupLegend = null;\n }\n if (cleanupChartEvents) {\n cleanupChartEvents();\n cleanupChartEvents = null;\n }\n if (cleanupAnnotationDrag) {\n cleanupAnnotationDrag();\n cleanupAnnotationDrag = null;\n }\n if (cleanupEditDrags) {\n cleanupEditDrags();\n cleanupEditDrags = null;\n }\n if (cleanupSelection) {\n cleanupSelection();\n cleanupSelection = null;\n }\n if (cleanupKeyboardEdit) {\n cleanupKeyboardEdit();\n cleanupKeyboardEdit = null;\n }\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n overlayElement = null;\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n if (tooltipManager) {\n tooltipManager.destroy();\n }\n if (srTable?.parentNode) {\n srTable.parentNode.removeChild(srTable);\n srTable = null;\n }\n\n currentLayout = compile();\n const shouldAnimate = isFirstRender && !!currentLayout.animation?.enabled;\n svgElement = renderChartSVG(currentLayout, container, { animate: shouldAnimate });\n tooltipManager = createTooltipManager(container);\n\n // Wire tooltip events on mark elements\n cleanupTooltipEvents = wireTooltipEvents(\n svgElement,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n );\n\n // Wire voronoi overlay tooltip events for line/area charts\n cleanupVoronoiEvents = wireVoronoiTooltipEvents(svgElement, currentLayout, tooltipManager);\n\n // Wire keyboard navigation\n cleanupKeyboardNav = wireKeyboardNav(\n svgElement,\n container,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n currentLayout,\n );\n\n // Wire legend interactivity\n cleanupLegend = wireLegendInteraction(\n svgElement,\n currentLayout,\n options?.onLegendToggle,\n options?.onEdit,\n );\n\n // Wire chart event handlers (mark click/hover/leave, annotation click)\n if (\n options?.onMarkClick ||\n options?.onMarkHover ||\n options?.onMarkLeave ||\n options?.onAnnotationClick\n ) {\n const specAnnotations: import('@opendata-ai/openchart-core').Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n cleanupChartEvents = wireChartEvents(svgElement, currentLayout, specAnnotations, options);\n }\n\n // Shared setDragging callback for all drag handlers\n const setDragging = (dragging: boolean) => {\n isDragging = dragging;\n if (!dragging && pendingRender) {\n pendingRender = false;\n render();\n }\n };\n\n // Shared annotation list for drag handlers (computed once)\n const dragAnnotations: Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n\n // Wire annotation drag editing (activates when onAnnotationEdit or onEdit is provided)\n if (options?.onAnnotationEdit || options?.onEdit) {\n cleanupAnnotationDrag = wireAnnotationDrag(\n svgElement,\n dragAnnotations,\n options?.onAnnotationEdit,\n options?.onEdit,\n setDragging,\n );\n }\n\n // Wire all edit drag handlers when onEdit is provided\n if (options?.onEdit) {\n const editCleanups: Array<() => void> = [];\n\n // Connector endpoint drag\n editCleanups.push(\n wireConnectorEndpointDrag(svgElement, dragAnnotations, options.onEdit, setDragging),\n );\n\n // Range/refline annotation label drag\n editCleanups.push(\n wireAnnotationLabelDrag(svgElement, dragAnnotations, options.onEdit, setDragging),\n );\n\n // Chrome text drag\n const editSpec = currentSpec as ChartSpec | GraphSpec;\n editCleanups.push(wireChromeDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n // Legend drag\n editCleanups.push(wireLegendDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n // Series label drag\n editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n cleanupEditDrags = () => {\n for (const cleanup of editCleanups) {\n cleanup();\n }\n };\n }\n\n // Wire selection and keyboard edit events when editing callbacks are provided\n if (hasEditingCallbacks(options)) {\n makeEditable(svgElement);\n cleanupSelection = wireSelectionEvents();\n cleanupKeyboardEdit = wireKeyboardEditEvents();\n\n // Restore selection overlay after re-render\n if (selectedElement) {\n const target = findElementByRef(svgElement, selectedElement);\n if (target) {\n overlayElement = renderSelectionOverlay(svgElement, selectedElement, currentLayout);\n } else {\n // Element no longer exists in DOM, clear selection silently\n selectedElement = null;\n overlayElement = null;\n }\n }\n }\n\n // Create hidden data table for screen readers\n srTable = createScreenReaderTable(currentLayout, container);\n\n // Apply container classes for CSS variable scoping and dark mode\n container.classList.add('oc-root');\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Set up animation cleanup on first render only.\n // onComplete fires when animations finish naturally (not on cancellation/destroy).\n // It nulls out cleanupAnimations so resizes work after the animation window,\n // and replays any resize that was skipped mid-animation.\n if (shouldAnimate && svgElement) {\n cleanupAnimations = setupAnimationCleanup(svgElement, () => {\n cleanupAnimations = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n if (isFirstRender) {\n isFirstRender = false;\n }\n }\n\n function update(newSpec: ChartSpec | GraphSpec, updateOpts?: UpdateOptions): void {\n if (destroyed) return;\n currentSpec = newSpec;\n if (updateOpts && 'selectedElement' in updateOpts) {\n selectedElement = updateOpts.selectedElement ?? null;\n }\n render();\n }\n\n function resize(): void {\n if (destroyed) return;\n // Skip resize during entrance animation. The resize observer fires\n // immediately when the container first enters DOM layout, and re-rendering\n // would destroy the animated SVG. Resizes during this window are queued\n // and replayed once the animation completes via the onComplete callback.\n if (cleanupAnimations) {\n pendingResize = true;\n return;\n }\n render();\n }\n\n function doExport(format: 'svg'): string;\n function doExport(format: 'svg-with-fonts', exportOptions?: SVGExportOptions): Promise<string>;\n function doExport(format: 'png', exportOptions?: ExportOptions): Promise<Blob>;\n function doExport(format: 'jpg', exportOptions?: ExportOptions): Promise<Blob>;\n function doExport(format: 'csv'): string;\n function doExport(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'csv',\n exportOptions?: ExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) {\n throw new Error('Chart is not rendered yet');\n }\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement, exportOptions);\n case 'png':\n return exportPNG(svgElement, exportOptions);\n case 'jpg':\n return exportJPG(svgElement, exportOptions);\n case 'csv':\n return exportCSV(\n 'data' in currentSpec && Array.isArray(currentSpec.data) ? currentSpec.data : [],\n );\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel entrance animations (cancellation does not fire onComplete)\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n pendingResize = false;\n }\n cancelAnimations(svgElement);\n\n if (resizeTimer !== null) {\n clearTimeout(resizeTimer);\n resizeTimer = null;\n }\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n if (cleanupVoronoiEvents) {\n cleanupVoronoiEvents();\n cleanupVoronoiEvents = null;\n }\n if (cleanupKeyboardNav) {\n cleanupKeyboardNav();\n cleanupKeyboardNav = null;\n }\n if (cleanupLegend) {\n cleanupLegend();\n cleanupLegend = null;\n }\n if (cleanupChartEvents) {\n cleanupChartEvents();\n cleanupChartEvents = null;\n }\n if (cleanupAnnotationDrag) {\n cleanupAnnotationDrag();\n cleanupAnnotationDrag = null;\n }\n if (cleanupEditDrags) {\n cleanupEditDrags();\n cleanupEditDrags = null;\n }\n if (cleanupSelection) {\n cleanupSelection();\n cleanupSelection = null;\n }\n if (cleanupKeyboardEdit) {\n cleanupKeyboardEdit();\n cleanupKeyboardEdit = null;\n }\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n selectedElement = null;\n overlayElement = null;\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n svgElement = null;\n }\n if (srTable?.parentNode) {\n srTable.parentNode.removeChild(srTable);\n srTable = null;\n }\n container.classList.remove('oc-dark');\n container.classList.remove('oc-root');\n }\n\n // Initial render\n render();\n\n // Set up responsive resize with debounce to avoid full SVG rebuild on every frame\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n if (resizeTimer !== null) clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => {\n resizeTimer = null;\n resize();\n }, 100);\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n destroy,\n get layout() {\n return currentLayout;\n },\n getSelectedElement(): ElementRef | null {\n return selectedElement;\n },\n select(ref: ElementRef): void {\n if (destroyed) return;\n selectElement(ref);\n },\n deselect(): void {\n if (destroyed) return;\n deselectElement();\n },\n get isEditing(): boolean {\n return isTextEditingActive;\n },\n };\n}\n","/**\n * Animation runtime for entrance animations.\n *\n * All animations are CSS-driven (keyframes + clip-path + transforms + opacity).\n * This module handles lifecycle: cleanup after completion, cancellation on update.\n * No WAAPI needed since clip-path handles line/area drawing.\n */\n\n/**\n * Cancel entrance animations and clean up.\n * Called when update() is invoked during animation, or on destroy.\n */\nexport function cancelAnimations(svg: SVGElement | null): void {\n if (svg) {\n svg.classList.remove('oc-animate');\n }\n}\n\n/**\n * Set up animation cleanup that removes oc-animate after all animations complete.\n *\n * Uses the computed total animation time (duration + stagger * elementCount + annotation delay)\n * rather than animationend events, because animationend fires per-element and the first\n * element to finish would prematurely kill staggered animations still in progress.\n */\nexport function setupAnimationCleanup(svg: SVGElement, onComplete?: () => void): () => void {\n // Read the animation timing from the CSS custom properties set by the renderer\n const style = svg.style;\n const duration = parseFloat(style.getPropertyValue('--oc-animation-duration')) || 600;\n const stagger = parseFloat(style.getPropertyValue('--oc-animation-stagger')) || 0;\n const annotationDelay = parseFloat(style.getPropertyValue('--oc-annotation-delay')) || 200;\n\n // Count animated elements to compute total stagger span\n const animatedElements = svg.querySelectorAll('[data-animation-index]').length;\n const totalStagger = stagger * Math.max(0, animatedElements - 1);\n\n // Total time: last element's stagger delay + its duration + annotation delay + buffer\n const totalTime = totalStagger + duration + annotationDelay + 500;\n\n const timer = setTimeout(() => {\n svg.classList.remove('oc-animate');\n onComplete?.();\n }, totalTime);\n\n return () => {\n clearTimeout(timer);\n cancelAnimations(svg);\n };\n}\n\n/**\n * Set up animation cleanup for table entrance animations.\n *\n * Same timeout-based approach as chart animations: compute total time from\n * CSS custom properties and row count, then remove oc-animate after completion.\n */\nexport function setupTableAnimationCleanup(wrapper: HTMLElement): () => void {\n const style = wrapper.style;\n const duration = parseFloat(style.getPropertyValue('--oc-animation-duration')) || 500;\n const stagger = parseFloat(style.getPropertyValue('--oc-animation-stagger')) || 0;\n\n const rows = wrapper.querySelectorAll('tbody tr').length;\n const totalStagger = stagger * Math.max(0, rows - 1);\n\n // Total: last row stagger + duration + buffer\n const totalTime = totalStagger + duration + 300;\n\n const timer = setTimeout(() => {\n wrapper.classList.remove('oc-animate');\n }, totalTime);\n\n return () => {\n clearTimeout(timer);\n wrapper.classList.remove('oc-animate');\n };\n}\n","/**\n * SVG renderer: converts a ChartLayout into SVG DOM elements.\n *\n * Creates an <svg> element with viewBox matching layout dimensions,\n * renders chrome (title/subtitle/source), axes, marks, annotations,\n * and legend. All styling via inline SVG attributes from layout data.\n *\n * Mark rendering dispatches per mark type with dedicated renderers\n * for line, area, rect, arc, and point marks.\n */\n\nimport type {\n ArcMark,\n AreaMark,\n AxisLayout,\n ChartLayout,\n LegendLayout,\n LineMark,\n Mark,\n MeasureTextFn,\n Point,\n PointMark,\n RectMark,\n ResolvedAnimation,\n ResolvedAnnotation,\n ResolvedChromeElement,\n RuleMarkLayout,\n TextMarkLayout,\n TextStyle,\n TickMarkLayout,\n} from '@opendata-ai/openchart-core';\nimport { BRAND_FONT_SIZE, BRAND_MIN_WIDTH, estimateTextWidth } from '@opendata-ai/openchart-core';\nimport { clampStaggerDelay } from '@opendata-ai/openchart-engine';\nimport { buildGradientDefs, resolveMarkFill } from './gradient-utils';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Module-level animation state. Set by renderChartSVG before rendering marks\n * so mark renderers can read it without changing their function signatures.\n */\nlet currentAnimation: ResolvedAnimation | undefined;\n\n/**\n * Module-level gradient map. Set by renderChartSVG after building gradient defs\n * so mark renderers can resolve gradient fills without signature changes.\n */\nlet currentGradientMap: Map<string, string> = new Map();\n\n/**\n * Stamp animation index attributes on a mark element when animation is enabled.\n * Sets `data-animation-index` (for querySelector) and `--oc-mark-index`\n * (for CSS calc-based stagger delay).\n */\nfunction stampAnimationAttrs(\n el: SVGElement,\n mark: { animationIndex?: number },\n fallbackIndex: number,\n): void {\n if (!currentAnimation?.enabled) return;\n const idx = mark.animationIndex ?? fallbackIndex;\n el.setAttribute('data-animation-index', String(idx));\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('--oc-mark-index', String(idx));\n}\n\n/** CSS easing preset map for inline style custom properties. */\nconst EASE_VAR_MAP: Record<string, string> = {\n smooth: 'var(--oc-ease-smooth)',\n snappy: 'var(--oc-ease-snappy)',\n};\n\n/**\n * Compute the vertical extent of x-axis labels below the chart area.\n * Accounts for rotated tick labels which need more vertical space.\n */\nfunction computeXAxisExtent(layout: ChartLayout): number {\n const xAxis = layout.axes.x;\n if (!xAxis) return 0;\n\n if (xAxis.tickAngle && Math.abs(xAxis.tickAngle) > 10) {\n // Rotated labels: estimate height from the longest tick label.\n const fontSize = xAxis.tickLabelStyle.fontSize;\n const fontWeight = xAxis.tickLabelStyle.fontWeight;\n const angleRad = Math.abs(xAxis.tickAngle) * (Math.PI / 180);\n let maxLabelWidth = 40;\n for (const tick of xAxis.ticks) {\n const w = estimateTextWidth(tick.label, fontSize, fontWeight);\n if (w > maxLabelWidth) maxLabelWidth = w;\n }\n const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);\n return xAxis.label ? rotatedHeight + 20 : rotatedHeight;\n }\n\n return xAxis.label ? 48 : 26;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createSVGElement(tag: string): SVGElement {\n return document.createElementNS(SVG_NS, tag);\n}\n\nfunction setAttrs(el: SVGElement, attrs: Record<string, string | number>): void {\n for (const [key, value] of Object.entries(attrs)) {\n el.setAttribute(key, String(value));\n }\n}\n\nfunction applyTextStyle(el: SVGElement, style: TextStyle): void {\n setAttrs(el, {\n 'font-family': style.fontFamily,\n 'font-size': style.fontSize,\n 'font-weight': style.fontWeight,\n });\n // Use inline style for fill so it takes priority over CSS class defaults\n // (e.g. .oc-title { fill: var(--oc-text) } which would override attributes)\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', style.fill);\n if (style.textAnchor) {\n el.setAttribute('text-anchor', style.textAnchor);\n }\n if (style.dominantBaseline) {\n el.setAttribute('dominant-baseline', style.dominantBaseline);\n }\n if (style.fontVariant) {\n el.setAttribute('font-variant', style.fontVariant);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Chrome rendering\n// ---------------------------------------------------------------------------\n\n/**\n * Break text into lines that fit within maxWidth using word wrapping.\n * Uses a character-width heuristic (same as text-measure.ts).\n */\nfunction wrapText(\n text: string,\n fontSize: number,\n fontWeight: number,\n maxWidth: number,\n measureText?: MeasureTextFn,\n): string[] {\n if (maxWidth <= 0) return [text];\n\n // Split on explicit newlines first\n const segments = text.split('\\n');\n if (segments.length > 1) {\n return segments.flatMap((segment) =>\n segment.length === 0 ? [''] : wrapText(segment, fontSize, fontWeight, maxWidth, measureText),\n );\n }\n\n // Use real text measurement when available\n if (measureText) {\n const textWidth = measureText(text, fontSize, fontWeight).width;\n if (textWidth <= maxWidth) return [text];\n\n const words = text.split(' ');\n const lines: string[] = [];\n let current = '';\n\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n const candidateWidth = measureText(candidate, fontSize, fontWeight).width;\n if (candidateWidth > maxWidth && current) {\n lines.push(current);\n current = word;\n } else {\n current = candidate;\n }\n }\n if (current) lines.push(current);\n\n return lines;\n }\n\n // Heuristic character width matching text-measure.ts\n const AVG_CHAR_WIDTH = 0.55;\n const WEIGHT_FACTORS: Record<number, number> = {\n 100: 0.9,\n 200: 0.92,\n 300: 0.95,\n 400: 1.0,\n 500: 1.02,\n 600: 1.05,\n 700: 1.08,\n 800: 1.1,\n 900: 1.12,\n };\n const weightFactor = WEIGHT_FACTORS[fontWeight] ?? 1.0;\n const charWidth = fontSize * AVG_CHAR_WIDTH * weightFactor;\n const maxChars = Math.floor(maxWidth / charWidth);\n\n if (text.length <= maxChars) return [text];\n\n const words = text.split(' ');\n const lines: string[] = [];\n let current = '';\n\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n if (candidate.length > maxChars && current) {\n lines.push(current);\n current = word;\n } else {\n current = candidate;\n }\n }\n if (current) lines.push(current);\n\n return lines;\n}\n\nfunction renderChromeElement(\n parent: SVGElement,\n element: ResolvedChromeElement,\n className: string,\n chromeKey: string,\n measureText?: MeasureTextFn,\n): void {\n const text = createSVGElement('text');\n setAttrs(text, { x: element.x, y: element.y });\n applyTextStyle(text, element.style);\n text.setAttribute('class', className);\n text.setAttribute('data-chrome-key', chromeKey);\n\n const lines = wrapText(\n element.text,\n element.style.fontSize,\n element.style.fontWeight,\n element.maxWidth,\n measureText,\n );\n\n if (lines.length === 1) {\n text.textContent = element.text;\n } else {\n const lineHeight = element.style.fontSize * (element.style.lineHeight ?? 1.3);\n for (let i = 0; i < lines.length; i++) {\n const tspan = createSVGElement('tspan');\n setAttrs(tspan, { x: element.x, dy: i === 0 ? 0 : lineHeight });\n tspan.textContent = lines[i];\n text.appendChild(tspan);\n }\n }\n\n parent.appendChild(text);\n}\n\nfunction renderChrome(parent: SVGElement, layout: ChartLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-chrome');\n\n const { chrome, measureText } = layout;\n\n // Top chrome: render at their stored y positions (already absolute)\n if (chrome.title) {\n renderChromeElement(g, chrome.title, 'oc-title', 'title', measureText);\n }\n if (chrome.subtitle) {\n renderChromeElement(g, chrome.subtitle, 'oc-subtitle', 'subtitle', measureText);\n }\n\n // Bottom chrome starts below x-axis labels/title, not at chart area bottom.\n // Accounts for rotated tick labels which need more vertical space.\n const xAxisExtent = computeXAxisExtent(layout);\n const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;\n if (chrome.source) {\n renderChromeElement(\n g,\n { ...chrome.source, y: bottomOffset + chrome.source.y },\n 'oc-source',\n 'source',\n measureText,\n );\n }\n if (chrome.byline) {\n renderChromeElement(\n g,\n { ...chrome.byline, y: bottomOffset + chrome.byline.y },\n 'oc-byline',\n 'byline',\n measureText,\n );\n }\n if (chrome.footer) {\n renderChromeElement(\n g,\n { ...chrome.footer, y: bottomOffset + chrome.footer.y },\n 'oc-footer',\n 'footer',\n measureText,\n );\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Axis rendering\n// ---------------------------------------------------------------------------\n\nfunction renderAxis(\n parent: SVGElement,\n axis: AxisLayout,\n orientation: 'x' | 'y',\n layout: ChartLayout,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', `oc-axis oc-axis-${orientation}`);\n\n const { area } = layout;\n\n // Only draw axis line for x-axis (bottom baseline).\n // Horizontal gridlines already guide y-values, so the vertical y-axis line is redundant.\n if (orientation === 'x') {\n const line = createSVGElement('line');\n line.setAttribute('class', 'oc-axis-line');\n setAttrs(line, {\n x1: axis.start.x,\n y1: axis.start.y,\n x2: axis.end.x,\n y2: axis.end.y,\n stroke: layout.theme.colors.axis,\n 'stroke-width': 1,\n });\n g.appendChild(line);\n }\n\n // Ticks and labels\n // Tick positions are absolute pixel coordinates from D3 scales whose range\n // was set to [chartArea.x, chartArea.x + chartArea.width] (and similarly for y).\n // Don't add area.x/area.y again or you'll double-offset everything.\n for (const tick of axis.ticks) {\n if (orientation === 'x') {\n // Label (no tick marks -- gridlines provide sufficient reference)\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-axis-tick');\n\n if (axis.tickAngle && Math.abs(axis.tickAngle) > 10) {\n // Rotated labels: anchor at the rotation pivot point\n const labelX = tick.position;\n const labelY = area.y + area.height + 6;\n setAttrs(label, {\n x: labelX,\n y: labelY,\n 'text-anchor': axis.tickAngle < 0 ? 'end' : 'start',\n 'dominant-baseline': 'central',\n transform: `rotate(${axis.tickAngle}, ${labelX}, ${labelY})`,\n });\n } else {\n setAttrs(label, {\n x: tick.position,\n y: area.y + area.height + 14,\n 'text-anchor': 'middle',\n });\n }\n\n applyTextStyle(label, axis.tickLabelStyle);\n label.textContent = tick.label;\n g.appendChild(label);\n } else {\n // Label (no tick marks -- gridlines provide sufficient reference)\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-axis-tick');\n setAttrs(label, {\n x: area.x - 6,\n y: tick.position,\n 'text-anchor': 'end',\n 'dominant-baseline': 'central',\n });\n applyTextStyle(label, axis.tickLabelStyle);\n label.textContent = tick.label;\n g.appendChild(label);\n }\n }\n\n // Gridlines (positions are also absolute from the scales)\n for (const gridline of axis.gridlines) {\n const gl = createSVGElement('line');\n gl.setAttribute('class', 'oc-gridline');\n if (orientation === 'y') {\n setAttrs(gl, {\n x1: area.x,\n y1: gridline.position,\n x2: area.x + area.width,\n y2: gridline.position,\n stroke: layout.theme.colors.gridline,\n 'stroke-width': 1,\n 'stroke-opacity': 0.6,\n });\n } else {\n setAttrs(gl, {\n x1: gridline.position,\n y1: area.y,\n x2: gridline.position,\n y2: area.y + area.height,\n stroke: layout.theme.colors.gridline,\n 'stroke-width': 1,\n 'stroke-opacity': 0.6,\n });\n }\n g.appendChild(gl);\n }\n\n // Axis label\n if (axis.label && axis.labelStyle) {\n const axisLabel = createSVGElement('text');\n axisLabel.setAttribute('class', 'oc-axis-title');\n applyTextStyle(axisLabel, axis.labelStyle);\n axisLabel.textContent = axis.label;\n\n if (orientation === 'x') {\n // Position axis title below tick labels. For rotated labels, compute\n // the vertical extent of the rotated ticks and place the title below.\n let titleY = area.y + area.height + 35;\n if (axis.tickAngle && Math.abs(axis.tickAngle) > 10) {\n const angleRad = Math.abs(axis.tickAngle) * (Math.PI / 180);\n let maxLabelWidth = 40;\n for (const tick of axis.ticks) {\n const w = estimateTextWidth(\n tick.label,\n axis.tickLabelStyle.fontSize,\n axis.tickLabelStyle.fontWeight,\n );\n if (w > maxLabelWidth) maxLabelWidth = w;\n }\n const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);\n titleY = area.y + area.height + rotatedHeight + 14;\n }\n setAttrs(axisLabel, {\n x: area.x + area.width / 2,\n y: titleY,\n 'text-anchor': 'middle',\n });\n } else {\n // Rotated y-axis label\n setAttrs(axisLabel, {\n x: area.x - 45,\n y: area.y + area.height / 2,\n 'text-anchor': 'middle',\n transform: `rotate(-90, ${area.x - 45}, ${area.y + area.height / 2})`,\n });\n }\n g.appendChild(axisLabel);\n }\n\n parent.appendChild(g);\n}\n\nfunction renderAxes(parent: SVGElement, layout: ChartLayout): void {\n if (layout.axes.x) {\n renderAxis(parent, layout.axes.x, 'x', layout);\n }\n if (layout.axes.y) {\n renderAxis(parent, layout.axes.y, 'y', layout);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mark rendering (dispatch per mark type)\n// ---------------------------------------------------------------------------\n\ntype MarkRenderer<T extends Mark> = (mark: T, index: number) => SVGElement;\n\nconst markRenderers: Record<string, MarkRenderer<Mark>> = {};\n\n/**\n * Register a mark renderer for a specific mark type.\n * Built-in renderers are registered below for all chart types.\n */\nexport function registerMarkRenderer<T extends Mark>(\n type: T['type'],\n renderer: MarkRenderer<T>,\n): void {\n markRenderers[type] = renderer as MarkRenderer<Mark>;\n}\n\nfunction renderLineMark(mark: LineMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `line-${mark.seriesKey ?? index}`);\n g.setAttribute('class', 'oc-mark oc-mark-line');\n stampAnimationAttrs(g, mark, index);\n\n if (mark.points.length > 1) {\n const path = createSVGElement('path');\n // Use the pre-computed D3 curve path when available (smooth monotone),\n // otherwise fall back to straight M/L segments.\n const d =\n mark.path ?? mark.points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');\n setAttrs(path, {\n d,\n fill: 'none',\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n if (mark.strokeDasharray) {\n path.setAttribute('stroke-dasharray', mark.strokeDasharray);\n }\n if (mark.opacity != null) {\n path.setAttribute('opacity', String(mark.opacity));\n }\n // Note: line drawing animation is handled via CSS clip-path on the group,\n // no inline dasharray/dashoffset needed.\n g.appendChild(path);\n }\n\n // Render end-of-line label if present and visible\n if (mark.label?.visible) {\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-mark-label');\n if (mark.seriesKey) {\n label.setAttribute('data-series', mark.seriesKey);\n }\n setAttrs(label, { x: mark.label.x, y: mark.label.y });\n applyTextStyle(label, mark.label.style);\n label.textContent = mark.label.text;\n g.appendChild(label);\n\n // Render connector line if label was offset from anchor\n if (mark.label.connector) {\n const connector = createSVGElement('line');\n connector.setAttribute('class', 'oc-mark-connector');\n setAttrs(connector, {\n x1: mark.label.connector.from.x,\n y1: mark.label.connector.from.y,\n x2: mark.label.connector.to.x,\n y2: mark.label.connector.to.y,\n stroke: mark.label.connector.stroke,\n 'stroke-width': 1,\n 'stroke-opacity': 0.5,\n });\n g.appendChild(connector);\n }\n }\n\n return g;\n}\n\nfunction renderAreaMark(mark: AreaMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `area-${mark.seriesKey ?? index}`);\n g.setAttribute('class', 'oc-mark oc-mark-area');\n stampAnimationAttrs(g, mark, index);\n\n if (mark.path) {\n // Area fill: the full closed shape (top line + baseline), no stroke\n const fill = createSVGElement('path');\n setAttrs(fill, {\n d: mark.path,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n 'fill-opacity': mark.fillOpacity,\n stroke: 'none',\n });\n g.appendChild(fill);\n\n // Top-line stroke: only along the data points, not the baseline\n if (mark.stroke && mark.topPath) {\n const strokePath = createSVGElement('path');\n strokePath.setAttribute('class', 'oc-area-top');\n setAttrs(strokePath, {\n d: mark.topPath,\n fill: 'none',\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth ?? 1,\n });\n // Note: area drawing animation is handled via CSS clip-path on the group,\n // no inline dasharray/dashoffset needed.\n g.appendChild(strokePath);\n }\n }\n\n return g;\n}\n\nfunction renderRectMark(mark: RectMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `rect-${index}`);\n g.setAttribute('class', 'oc-mark oc-mark-rect');\n stampAnimationAttrs(g, mark, index);\n // Use engine-provided orientation for animation direction\n if (currentAnimation?.enabled && mark.orient === 'horizontal') {\n g.setAttribute('data-orient', 'horizontal');\n }\n\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: mark.x,\n y: mark.y,\n width: mark.width,\n height: mark.height,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n });\n if (mark.stroke) {\n rect.setAttribute('stroke', mark.stroke);\n }\n if (mark.strokeWidth) {\n rect.setAttribute('stroke-width', String(mark.strokeWidth));\n }\n if (mark.cornerRadius) {\n setAttrs(rect, { rx: mark.cornerRadius, ry: mark.cornerRadius });\n }\n g.appendChild(rect);\n\n // Render value label if present and visible\n if (mark.label?.visible) {\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-mark-label');\n setAttrs(label, { x: mark.label.x, y: mark.label.y });\n applyTextStyle(label, mark.label.style);\n label.textContent = mark.label.text;\n g.appendChild(label);\n }\n\n return g;\n}\n\nfunction renderArcMark(mark: ArcMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `arc-${index}`);\n g.setAttribute('class', 'oc-mark oc-mark-arc');\n g.setAttribute('transform', `translate(${mark.center.x},${mark.center.y})`);\n stampAnimationAttrs(g, mark, index);\n\n const path = createSVGElement('path');\n setAttrs(path, {\n d: mark.path,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n g.appendChild(path);\n\n // Render label if present and visible\n if (mark.label?.visible) {\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-mark-label');\n // Label position is in absolute coords, but we're in a translated group,\n // so subtract the center offset\n setAttrs(label, {\n x: mark.label.x - mark.center.x,\n y: mark.label.y - mark.center.y,\n });\n applyTextStyle(label, mark.label.style);\n label.textContent = mark.label.text;\n g.appendChild(label);\n }\n\n return g;\n}\n\nfunction renderPointMark(mark: PointMark, index: number): SVGElement {\n const circle = createSVGElement('circle');\n circle.setAttribute('data-mark-id', `point-${index}`);\n circle.setAttribute('class', 'oc-mark oc-mark-point');\n stampAnimationAttrs(circle, mark, index);\n\n setAttrs(circle, {\n cx: mark.cx,\n cy: mark.cy,\n r: mark.r,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n if (mark.fillOpacity !== undefined) {\n circle.setAttribute('fill-opacity', String(mark.fillOpacity));\n }\n return circle;\n}\n\nfunction renderTextMark(mark: TextMarkLayout, index: number): SVGElement {\n const text = createSVGElement('text');\n text.setAttribute('data-mark-id', `textMark-${index}`);\n text.setAttribute('class', 'oc-mark oc-mark-text');\n stampAnimationAttrs(text, mark, index);\n\n setAttrs(text, {\n x: mark.x,\n y: mark.y,\n 'font-size': mark.fontSize,\n 'text-anchor': mark.textAnchor,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', mark.fill);\n if (mark.fontWeight) {\n text.setAttribute('font-weight', String(mark.fontWeight));\n }\n if (mark.fontFamily) {\n text.setAttribute('font-family', mark.fontFamily);\n }\n if (mark.angle) {\n text.setAttribute('transform', `rotate(${mark.angle}, ${mark.x}, ${mark.y})`);\n }\n text.textContent = mark.text;\n return text;\n}\n\nfunction renderRuleMark(mark: RuleMarkLayout, index: number): SVGElement {\n const line = createSVGElement('line');\n line.setAttribute('data-mark-id', `rule-${index}`);\n line.setAttribute('class', 'oc-mark oc-mark-rule');\n stampAnimationAttrs(line, mark, index);\n\n setAttrs(line, {\n x1: mark.x1,\n y1: mark.y1,\n x2: mark.x2,\n y2: mark.y2,\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n if (mark.strokeDasharray) {\n line.setAttribute('stroke-dasharray', mark.strokeDasharray);\n }\n if (mark.opacity != null) {\n line.setAttribute('opacity', String(mark.opacity));\n }\n return line;\n}\n\nfunction renderTickMark(mark: TickMarkLayout, index: number): SVGElement {\n const line = createSVGElement('line');\n line.setAttribute('data-mark-id', `tick-${index}`);\n line.setAttribute('class', 'oc-mark oc-mark-tick');\n stampAnimationAttrs(line, mark, index);\n\n // Tick is a short line segment centered at (x, y)\n const half = mark.length / 2;\n if (mark.orient === 'vertical') {\n setAttrs(line, {\n x1: mark.x,\n y1: mark.y - half,\n x2: mark.x,\n y2: mark.y + half,\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n } else {\n setAttrs(line, {\n x1: mark.x - half,\n y1: mark.y,\n x2: mark.x + half,\n y2: mark.y,\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n }\n\n if (mark.opacity != null) {\n line.setAttribute('opacity', String(mark.opacity));\n }\n return line;\n}\n\n// Register built-in renderers\nregisterMarkRenderer('line', renderLineMark as MarkRenderer<Mark>);\nregisterMarkRenderer('area', renderAreaMark as MarkRenderer<Mark>);\nregisterMarkRenderer('rect', renderRectMark as MarkRenderer<Mark>);\nregisterMarkRenderer('arc', renderArcMark as MarkRenderer<Mark>);\nregisterMarkRenderer('point', renderPointMark as MarkRenderer<Mark>);\nregisterMarkRenderer('textMark', renderTextMark as MarkRenderer<Mark>);\nregisterMarkRenderer('rule', renderRuleMark as MarkRenderer<Mark>);\nregisterMarkRenderer('tick', renderTickMark as MarkRenderer<Mark>);\n\n/** Extract series name from a mark for legend toggle matching. */\nfunction getMarkSeries(mark: Mark): string | undefined {\n // Line and area marks have an explicit seriesKey\n if (mark.type === 'line' || mark.type === 'area') {\n return mark.seriesKey;\n }\n // For arc marks, the category name is the first part of the aria label (before ':')\n if (mark.type === 'arc') {\n return mark.aria.label.split(':')[0]?.trim();\n }\n // For rect/point, the aria label may be \"category: value\" or \"category, group: value\".\n // The series name is the category part (before the colon).\n if (mark.aria?.label) {\n const beforeColon = mark.aria.label.split(':')[0]?.trim();\n if (beforeColon) return beforeColon;\n }\n return undefined;\n}\n\nfunction renderMarks(parent: SVGElement, layout: ChartLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-marks');\n\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n const renderer = markRenderers[mark.type];\n if (!renderer) continue;\n\n const el = renderer(mark, i);\n // Add ARIA label if present\n if (mark.aria?.label) {\n el.setAttribute('aria-label', mark.aria.label);\n }\n // Add data-series attribute for legend toggle matching\n const series = getMarkSeries(mark);\n if (series) {\n el.setAttribute('data-series', series);\n }\n\n // For stacked segments, set stack position for sequential animation chaining.\n // stackPos is computed by the engine on RectMark during compilation.\n if (currentAnimation?.enabled && mark.type === 'rect') {\n const rect = mark as RectMark;\n if (rect.stackGroup && rect.stackPos !== undefined) {\n el.setAttribute('data-stack-pos', String(rect.stackPos));\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty(\n '--oc-stack-pos',\n String(rect.stackPos),\n );\n }\n }\n\n g.appendChild(el);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Annotation rendering\n// ---------------------------------------------------------------------------\n\nfunction renderAnnotations(parent: SVGElement, layout: ChartLayout): void {\n if (layout.annotations.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-annotations');\n\n // Annotations are already sorted by zIndex from the engine, so render in order\n const bgColor = layout.theme.colors.background;\n for (let i = 0; i < layout.annotations.length; i++) {\n renderAnnotation(g, layout.annotations[i], i, bgColor);\n }\n\n parent.appendChild(g);\n}\n\n/**\n * Render a curved arrow connector from a label to a data point.\n * Uses a cubic bezier that sweeps outward then curves toward the\n * target, with a triangular arrowhead at the tip.\n */\nfunction renderCurvedArrow(parent: SVGElement, from: Point, to: Point, stroke: string): void {\n // Pad above the target so the arrow doesn't sit right on the element.\n const pad = 6;\n const tipY = to.y - pad;\n\n const dy = tipY - from.y;\n const dist = Math.sqrt((to.x - from.x) ** 2 + dy ** 2) || 1;\n\n // Arrowhead geometry\n const arrowLen = 8;\n const arrowWidth = 4;\n\n // cp2 directly above target so arrow arrives pointing straight down.\n const bulge = Math.max(dist * 0.4, 35);\n const cp1x = from.x + bulge;\n const cp1y = from.y + dy * 0.35;\n const cp2x = to.x;\n const cp2y = tipY - Math.abs(dy) * 0.25;\n\n // Tangent at the tip (from cp2 → tip), used for arrowhead direction.\n const tx = to.x - cp2x;\n const ty = tipY - cp2y;\n const tLen = Math.sqrt(tx * tx + ty * ty) || 1;\n const ux = tx / tLen;\n const uy = ty / tLen;\n\n // End the curve path at the arrowhead BASE so the stroke doesn't\n // poke through the filled triangle.\n const baseX = to.x - ux * arrowLen;\n const baseY = tipY - uy * arrowLen;\n\n const path = createSVGElement('path');\n path.setAttribute('class', 'oc-annotation-connector');\n setAttrs(path, {\n d: `M ${from.x} ${from.y} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${baseX} ${baseY}`,\n fill: 'none',\n stroke,\n 'stroke-width': 1.5,\n });\n parent.appendChild(path);\n\n // Arrowhead triangle: perpendicular to tangent direction.\n const px = -uy;\n const py = ux;\n\n const arrow = createSVGElement('polygon');\n arrow.setAttribute('class', 'oc-annotation-connector');\n setAttrs(arrow, {\n points: [\n `${to.x},${tipY}`,\n `${baseX + px * arrowWidth},${baseY + py * arrowWidth}`,\n `${baseX - px * arrowWidth},${baseY - py * arrowWidth}`,\n ].join(' '),\n fill: stroke,\n });\n parent.appendChild(arrow);\n}\n\nfunction renderAnnotation(\n parent: SVGElement,\n annotation: ResolvedAnnotation,\n index: number,\n bgColor?: string,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', `oc-annotation oc-annotation-${annotation.type}`);\n g.setAttribute('data-annotation-index', String(index));\n if (annotation.id) {\n g.setAttribute('data-annotation-id', annotation.id);\n }\n\n // Range rect\n if (annotation.rect) {\n const rect = createSVGElement('rect');\n rect.setAttribute('class', 'oc-annotation-range');\n setAttrs(rect, {\n x: annotation.rect.x,\n y: annotation.rect.y,\n width: annotation.rect.width,\n height: annotation.rect.height,\n });\n if (annotation.fill) rect.setAttribute('fill', annotation.fill);\n if (annotation.opacity !== undefined) {\n rect.setAttribute('fill-opacity', String(annotation.opacity));\n }\n g.appendChild(rect);\n }\n\n // Reference line\n if (annotation.line) {\n const line = createSVGElement('line');\n line.setAttribute('class', 'oc-annotation-line');\n setAttrs(line, {\n x1: annotation.line.start.x,\n y1: annotation.line.start.y,\n x2: annotation.line.end.x,\n y2: annotation.line.end.y,\n 'stroke-width': annotation.strokeWidth ?? 1,\n });\n if (annotation.stroke) line.setAttribute('stroke', annotation.stroke);\n if (annotation.strokeDasharray) {\n line.setAttribute('stroke-dasharray', annotation.strokeDasharray);\n }\n g.appendChild(line);\n }\n\n // Label with optional connector line\n if (annotation.label?.visible) {\n // Render connector first (behind the label text)\n if (annotation.label.connector) {\n const c = annotation.label.connector;\n if (c.style === 'curve') {\n renderCurvedArrow(g, c.from, c.to, c.stroke);\n } else {\n const connector = createSVGElement('line');\n connector.setAttribute('class', 'oc-annotation-connector');\n setAttrs(connector, {\n x1: c.from.x,\n y1: c.from.y,\n x2: c.to.x,\n y2: c.to.y,\n stroke: c.stroke,\n 'stroke-width': 1,\n 'stroke-opacity': 0.5,\n });\n g.appendChild(connector);\n }\n }\n\n const text = createSVGElement('text');\n text.setAttribute('class', 'oc-annotation-label');\n setAttrs(text, { x: annotation.label.x, y: annotation.label.y });\n applyTextStyle(text, annotation.label.style);\n\n const lines = annotation.label.text.split('\\n');\n const fontSize = annotation.label.style.fontSize ?? 12;\n const lineHeight = fontSize * (annotation.label.style.lineHeight ?? 1.3);\n const isMultiLine = lines.length > 1;\n\n // Multi-line text uses center alignment for a cleaner look\n if (isMultiLine) {\n text.setAttribute('text-anchor', 'middle');\n for (let i = 0; i < lines.length; i++) {\n const tspan = createSVGElement('tspan');\n setAttrs(tspan, { x: annotation.label.x, dy: i === 0 ? 0 : lineHeight });\n tspan.textContent = lines[i];\n text.appendChild(tspan);\n }\n } else {\n text.textContent = annotation.label.text;\n }\n\n // Render background rect behind text if specified, otherwise use\n // paint-order stroke halo to knock out lines behind text\n if (annotation.label.background) {\n const charWidth = fontSize * 0.55;\n const maxLineWidth = Math.max(...lines.map((l) => l.length)) * charWidth;\n const totalHeight = lines.length * lineHeight;\n const pad = 3;\n const bgX = isMultiLine\n ? annotation.label.x - maxLineWidth / 2 - pad\n : annotation.label.x - pad;\n const bgRect = createSVGElement('rect');\n bgRect.setAttribute('class', 'oc-annotation-bg');\n setAttrs(bgRect, {\n x: bgX,\n y: annotation.label.y - fontSize + (lineHeight - fontSize) / 2 - pad,\n width: maxLineWidth + pad * 2,\n height: totalHeight + pad * 2,\n fill: annotation.label.background,\n rx: 2,\n });\n g.appendChild(bgRect);\n } else if (bgColor) {\n text.style.paintOrder = 'stroke';\n text.style.stroke = bgColor;\n text.style.strokeWidth = `${Math.round(fontSize * 0.3)}px`;\n text.style.strokeLinejoin = 'round';\n }\n\n g.appendChild(text);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Legend rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLegend(parent: SVGElement, legend: LegendLayout): void {\n if (legend.entries.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-legend');\n g.setAttribute('role', 'list');\n g.setAttribute('aria-label', 'Chart legend');\n\n const isHorizontal = legend.position === 'top' || legend.position === 'bottom';\n let offsetX = legend.bounds.x;\n let offsetY = legend.bounds.y;\n\n for (let i = 0; i < legend.entries.length; i++) {\n const entry = legend.entries[i];\n\n // Pre-check: wrap to next line if this entry would overflow bounds\n if (isHorizontal && i > 0) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n if (offsetX + entryWidth > legend.bounds.x + legend.bounds.width) {\n offsetX = legend.bounds.x;\n offsetY += legend.swatchSize + 6;\n }\n }\n const entryG = createSVGElement('g');\n entryG.setAttribute('class', 'oc-legend-entry');\n entryG.setAttribute('role', 'listitem');\n entryG.setAttribute('data-legend-index', String(i));\n entryG.setAttribute('data-legend-label', entry.label);\n if (entry.overflow) {\n entryG.setAttribute('data-legend-overflow', 'true');\n entryG.setAttribute('aria-label', entry.label);\n entryG.setAttribute('opacity', '0.5');\n } else {\n entryG.setAttribute(\n 'aria-label',\n `${entry.label}: ${entry.active !== false ? 'visible' : 'hidden'}`,\n );\n entryG.setAttribute('style', 'cursor: pointer');\n\n // Apply dimming for inactive entries\n if (entry.active === false) {\n entryG.setAttribute('opacity', '0.3');\n }\n }\n\n // Swatch\n if (entry.shape === 'circle') {\n const circle = createSVGElement('circle');\n setAttrs(circle, {\n cx: offsetX + legend.swatchSize / 2,\n cy: offsetY + legend.swatchSize / 2,\n r: legend.swatchSize / 2,\n fill: entry.color,\n });\n entryG.appendChild(circle);\n } else if (entry.shape === 'line') {\n // Line swatch: a short line segment with a dot in the middle\n const line = createSVGElement('line');\n setAttrs(line, {\n x1: offsetX,\n y1: offsetY + legend.swatchSize / 2,\n x2: offsetX + legend.swatchSize,\n y2: offsetY + legend.swatchSize / 2,\n stroke: entry.color,\n 'stroke-width': 2,\n });\n entryG.appendChild(line);\n // Small dot at center\n const dot = createSVGElement('circle');\n setAttrs(dot, {\n cx: offsetX + legend.swatchSize / 2,\n cy: offsetY + legend.swatchSize / 2,\n r: 2.5,\n fill: entry.color,\n });\n entryG.appendChild(dot);\n } else {\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: offsetX,\n y: offsetY,\n width: legend.swatchSize,\n height: legend.swatchSize,\n fill: entry.color,\n rx: 2,\n });\n entryG.appendChild(rect);\n }\n\n // Label\n const label = createSVGElement('text');\n setAttrs(label, {\n x: offsetX + legend.swatchSize + legend.swatchGap,\n y: offsetY + legend.swatchSize / 2,\n 'dominant-baseline': 'central',\n });\n applyTextStyle(label, legend.labelStyle);\n label.textContent = entry.label;\n entryG.appendChild(label);\n\n g.appendChild(entryG);\n\n // Advance position for next entry\n if (isHorizontal) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n offsetX += entryWidth;\n } else {\n offsetY += legend.swatchSize + legend.entryGap;\n }\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Brand rendering\n// ---------------------------------------------------------------------------\n\nconst BRAND_URL = 'https://tryopendata.ai';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/**\n * Render the \"OpenData\" brand as a footer-row element, right-aligned on the\n * same baseline as the first bottom chrome text (source/byline/footer).\n * Uses the same font size as chrome source text so it blends in as a subtle\n * footer item rather than occupying independent visual space.\n */\nfunction renderBrand(parent: SVGElement, layout: ChartLayout): void {\n if (layout.dimensions.width < BRAND_MIN_WIDTH) return;\n\n const { width } = layout.dimensions;\n const padding = layout.theme.spacing.padding;\n const rightEdge = width - padding;\n const fill = layout.theme.colors.axis;\n\n // Vertically align with the first bottom chrome element.\n const { chrome } = layout;\n const xAxisExtent = computeXAxisExtent(layout);\n const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;\n const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;\n const chromeY = firstBottom\n ? bottomOffset + firstBottom.y\n : bottomOffset + layout.theme.spacing.chartToFooter;\n\n const a = createSVGElement('a');\n a.setAttribute('href', BRAND_URL);\n a.setAttributeNS(XLINK_NS, 'xlink:href', BRAND_URL);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.setAttribute('class', 'oc-chrome-ref');\n\n // \"try\" in normal weight, \"OpenData\" in semibold, \".ai\" in normal weight,\n // rendered as a single right-aligned text element with three tspans.\n // Use alphabetic baseline so mixed-size tspans share a common bottom line.\n const BRAND_LARGE = 16;\n const text = createSVGElement('text');\n setAttrs(text, {\n x: rightEdge,\n y: chromeY + BRAND_LARGE,\n 'dominant-baseline': 'alphabetic',\n 'font-family': layout.theme.fonts.family,\n 'font-size': BRAND_FONT_SIZE,\n 'text-anchor': 'end',\n 'fill-opacity': 0.55,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', fill);\n\n const trySpan = createSVGElement('tspan');\n trySpan.setAttribute('font-weight', '500');\n trySpan.textContent = 'try';\n text.appendChild(trySpan);\n\n const openDataSpan = createSVGElement('tspan');\n openDataSpan.setAttribute('font-weight', '600');\n openDataSpan.setAttribute('font-size', String(BRAND_LARGE));\n openDataSpan.textContent = 'OpenData';\n text.appendChild(openDataSpan);\n\n const aiSpan = createSVGElement('tspan');\n aiSpan.setAttribute('font-weight', '500');\n aiSpan.textContent = '.ai';\n text.appendChild(aiSpan);\n\n a.appendChild(text);\n parent.appendChild(a);\n}\n\n// ---------------------------------------------------------------------------\n// Main render function\n// ---------------------------------------------------------------------------\n\n/**\n * Render a compiled ChartLayout into an SVG element and append it to a container.\n *\n * @param layout - Compiled ChartLayout from compileChart().\n * @param container - DOM element to mount the SVG into.\n * @returns The created SVG element.\n */\nexport function renderChartSVG(\n layout: ChartLayout,\n container: HTMLElement,\n opts?: { animate?: boolean },\n): SVGElement {\n const { width, height } = layout.dimensions;\n const animation = layout.animation;\n\n // Set module-level animation state so mark renderers can access it\n currentAnimation = animation;\n\n const svg = createSVGElement('svg') as SVGSVGElement;\n setAttrs(svg, {\n viewBox: `0 0 ${width} ${height}`,\n xmlns: SVG_NS,\n // WebKit/iOS Safari getBBox() bug: text with dominant-baseline:hanging\n // reports bounding boxes extending above y=0. The SVG spec default\n // overflow is \"hidden\", which clips this phantom extent. Setting\n // overflow:visible prevents the clipping. Chart marks are already\n // constrained by a clipPath, so nothing bleeds out.\n overflow: 'visible',\n });\n // Set explicit pixel height via inline style. iOS Safari misresolves CSS\n // height:100% when the ancestor chain uses minHeight instead of height,\n // causing the top of the chart (title) to clip on real mobile devices.\n svg.style.height = `${height}px`;\n svg.setAttribute('role', layout.a11y.role);\n svg.setAttribute('aria-label', layout.a11y.altText);\n\n // oc-animate must be set before the SVG enters the DOM to prevent a flash\n // of the final state. mount.ts passes animate: true only on genuine first render.\n const classes = opts?.animate ? 'oc-chart oc-animate' : 'oc-chart';\n svg.setAttribute('class', classes);\n\n // Set animation CSS custom properties when enabled\n if (animation?.enabled) {\n const markCount = layout.marks.length;\n const stagger = clampStaggerDelay(animation.staggerDelay, markCount);\n svg.style.setProperty('--oc-animation-duration', `${animation.duration}ms`);\n svg.style.setProperty('--oc-animation-stagger', `${stagger}ms`);\n svg.style.setProperty('--oc-annotation-delay', `${animation.annotationDelay}ms`);\n const easeVar = EASE_VAR_MAP[animation.ease] || EASE_VAR_MAP.smooth;\n svg.style.setProperty('--oc-animation-ease', easeVar);\n\n // Compute per-segment duration for stacked bars so the total bar animation\n // time stays consistent regardless of segment count.\n // stackPos is set by the engine (0-indexed position within each stack group).\n let maxSegments = 0;\n for (const m of layout.marks) {\n if (m.type === 'rect') {\n const pos = (m as RectMark).stackPos;\n if (pos !== undefined && pos + 1 > maxSegments) {\n maxSegments = pos + 1;\n }\n }\n }\n if (maxSegments > 0) {\n const segDuration = Math.round(animation.duration / maxSegments);\n svg.style.setProperty('--oc-stack-segment-duration', `${segDuration}ms`);\n }\n }\n\n // Background\n const bg = createSVGElement('rect');\n setAttrs(bg, {\n x: 0,\n y: 0,\n width,\n height,\n fill: layout.theme.colors.background,\n });\n svg.appendChild(bg);\n\n // Clip path to prevent marks (especially area fills) from overflowing\n // into the chrome region (title/subtitle). Extends full width so\n // end-of-line labels aren't clipped, but constrains vertically.\n const clipId = `oc-clip-${Math.random().toString(36).slice(2, 8)}`;\n const defs = createSVGElement('defs');\n const clipPath = createSVGElement('clipPath');\n clipPath.setAttribute('id', clipId);\n const clipRect = createSVGElement('rect');\n setAttrs(clipRect, {\n x: 0,\n y: layout.area.y,\n width,\n height: layout.area.height + 2,\n });\n clipPath.appendChild(clipRect);\n defs.appendChild(clipPath);\n\n // Build gradient defs for marks with gradient fills\n currentGradientMap = buildGradientDefs(layout.marks as Array<{ fill?: unknown }>, defs);\n\n svg.appendChild(defs);\n\n // Render layers in order (back to front)\n // Axes render outside clip (labels extend beyond chart area)\n renderAxes(svg, layout);\n\n // Marks are clipped to chart area so area fills don't cover chrome\n const clippedGroup = createSVGElement('g');\n clippedGroup.setAttribute('clip-path', `url(#${clipId})`);\n renderMarks(clippedGroup, layout);\n\n // Add transparent overlay rect for line/area charts to enable voronoi tooltip lookup.\n // Only added when there are line or area marks with dataPoints, and no explicit\n // PointMark objects (which use per-element event handling instead).\n const hasLineOrAreaWithDataPoints = layout.marks.some(\n (m) => (m.type === 'line' || m.type === 'area') && m.dataPoints && m.dataPoints.length > 0,\n );\n const hasPointMarks = layout.marks.some((m) => m.type === 'point');\n if (hasLineOrAreaWithDataPoints && !hasPointMarks) {\n const overlay = createSVGElement('rect');\n setAttrs(overlay, {\n x: layout.area.x,\n y: layout.area.y,\n width: layout.area.width,\n height: layout.area.height,\n fill: 'transparent',\n });\n overlay.setAttribute('class', 'oc-voronoi-overlay');\n overlay.setAttribute('data-voronoi-overlay', 'true');\n clippedGroup.appendChild(overlay);\n }\n\n svg.appendChild(clippedGroup);\n\n renderAnnotations(svg, layout);\n renderLegend(svg, layout.legend);\n\n // Chrome renders on top so titles are never obscured by chart elements\n renderChrome(svg, layout);\n\n // Brand renders as a footer item, right-aligned on the source/footer row\n if (layout.watermark) {\n renderBrand(svg, layout);\n }\n\n // Reset module-level state after rendering\n currentAnimation = undefined;\n currentGradientMap = new Map();\n\n container.appendChild(svg);\n return svg;\n}\n","/**\n * SVG gradient utilities: creates <linearGradient> and <radialGradient>\n * elements from GradientDef specs and resolves mark fills to url(#id) refs.\n */\n\nimport type { GradientDef, LinearGradient, RadialGradient } from '@opendata-ai/openchart-core';\nimport { isGradientDef } from '@opendata-ai/openchart-core';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Produce a stable, deterministic key for a GradientDef.\n * Used for deduplication so identical gradients share one SVG element.\n * Recursively sorts object keys for stability across property order variations.\n */\nfunction gradientKey(def: GradientDef): string {\n return sortedStringify(def);\n}\n\nfunction sortedStringify(value: unknown): string {\n if (value === null || value === undefined) return String(value);\n if (Array.isArray(value)) return `[${value.map(sortedStringify).join(',')}]`;\n if (typeof value === 'object') {\n const sorted = Object.keys(value)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${sortedStringify((value as Record<string, unknown>)[k])}`);\n return `{${sorted.join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\n/**\n * Create a single SVG gradient element (<linearGradient> or <radialGradient>).\n * Uses gradientUnits=\"objectBoundingBox\" so coordinates are in [0,1] space.\n */\nfunction createGradientElement(def: GradientDef, id: string): SVGElement {\n if (def.gradient === 'linear') {\n return createLinearGradient(def, id);\n }\n return createRadialGradient(def, id);\n}\n\nfunction createLinearGradient(def: LinearGradient, id: string): SVGElement {\n const el = document.createElementNS(SVG_NS, 'linearGradient');\n el.setAttribute('id', id);\n el.setAttribute('gradientUnits', 'objectBoundingBox');\n el.setAttribute('x1', String(def.x1 ?? 0));\n el.setAttribute('y1', String(def.y1 ?? 0));\n el.setAttribute('x2', String(def.x2 ?? 0));\n el.setAttribute('y2', String(def.y2 ?? 1));\n\n for (const stop of def.stops) {\n appendStop(el, stop);\n }\n\n return el;\n}\n\nfunction createRadialGradient(def: RadialGradient, id: string): SVGElement {\n const el = document.createElementNS(SVG_NS, 'radialGradient');\n el.setAttribute('id', id);\n el.setAttribute('gradientUnits', 'objectBoundingBox');\n // SVG radialGradient: cx/cy/r = outer circle, fx/fy/fr = focal (inner) circle\n // Spec: x2/y2/r2 = outer, x1/y1/r1 = inner (focal)\n el.setAttribute('cx', String(def.x2 ?? 0.5));\n el.setAttribute('cy', String(def.y2 ?? 0.5));\n el.setAttribute('r', String(def.r2 ?? 0.5));\n el.setAttribute('fx', String(def.x1 ?? 0.5));\n el.setAttribute('fy', String(def.y1 ?? 0.5));\n el.setAttribute('fr', String(def.r1 ?? 0));\n\n for (const stop of def.stops) {\n appendStop(el, stop);\n }\n\n return el;\n}\n\nfunction appendStop(\n parent: SVGElement,\n stop: { offset: number; color: string; opacity?: number },\n): void {\n const stopEl = document.createElementNS(SVG_NS, 'stop');\n stopEl.setAttribute('offset', String(stop.offset));\n stopEl.setAttribute('stop-color', stop.color);\n if (stop.opacity !== undefined) {\n stopEl.setAttribute('stop-opacity', String(stop.opacity));\n }\n parent.appendChild(stopEl);\n}\n\n/**\n * Scan all marks for GradientDef fill values, create SVG gradient elements\n * in the provided <defs> node, and return a map from gradient key to element ID.\n *\n * Identical gradients (by key) share a single SVG element.\n */\nexport function buildGradientDefs(\n marks: Array<{ fill?: unknown }>,\n defs: SVGElement,\n): Map<string, string> {\n const map = new Map<string, string>();\n let counter = 0;\n\n for (const mark of marks) {\n const fill = mark.fill;\n if (fill && isGradientDef(fill)) {\n const key = gradientKey(fill);\n if (!map.has(key)) {\n const id = `oc-grad-${counter++}`;\n const el = createGradientElement(fill, id);\n defs.appendChild(el);\n map.set(key, id);\n }\n }\n }\n\n return map;\n}\n\n/**\n * Resolve a mark's fill value to a CSS/SVG fill string.\n * Returns the color string directly for plain fills,\n * or \"url(#gradientId)\" for gradient fills.\n */\nexport function resolveMarkFill(\n fill: string | GradientDef,\n gradientMap: Map<string, string>,\n): string {\n if (typeof fill === 'string') return fill;\n const key = gradientKey(fill);\n const id = gradientMap.get(key);\n return id ? `url(#${id})` : '#000000';\n}\n","/**\n * Text edit overlay: creates a positioned textarea over an SVG text element\n * for inline editing. Handles commit (Enter), cancel (Escape), and\n * click-outside-to-commit behavior.\n */\n\nexport interface TextEditOverlayConfig {\n /** The container div that holds the SVG. */\n container: HTMLElement;\n /** The root SVG element. */\n svg: SVGSVGElement;\n /** The SVG text element being edited. */\n targetElement: SVGElement;\n /** Current text content to populate the textarea. */\n currentText: string;\n /** Called when the user commits the edit (Enter or click outside). */\n onCommit: (newText: string) => void;\n /** Called when the user cancels the edit (Escape). */\n onCancel: () => void;\n}\n\n/**\n * Get the viewBox-to-pixel scale factors for an SVG element.\n * Same approach used by the drag handlers in mount.ts.\n */\nfunction getScale(svg: SVGSVGElement): { scaleX: number; scaleY: number } {\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n return {\n scaleX: viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1,\n scaleY: viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1,\n };\n}\n\n/**\n * Read computed font styles from an SVG text element and map them to CSS.\n */\nfunction getTextStyles(\n targetElement: SVGElement,\n scale: { scaleX: number; scaleY: number },\n): {\n fontFamily: string;\n fontSize: string;\n fontWeight: string;\n color: string;\n textAlign: string;\n lineHeight: string;\n} {\n const computed = window.getComputedStyle(targetElement);\n\n // Font size needs to be scaled from SVG viewBox units to pixel units\n const svgFontSize = parseFloat(\n targetElement.getAttribute('font-size') ?? computed.fontSize ?? '14',\n );\n const pixelFontSize = svgFontSize * scale.scaleY;\n\n const fontFamily = targetElement.getAttribute('font-family') ?? computed.fontFamily ?? 'inherit';\n const fontWeight = targetElement.getAttribute('font-weight') ?? computed.fontWeight ?? '400';\n\n // Get fill color from inline style or attribute\n const fill =\n (targetElement as SVGElement & ElementCSSInlineStyle).style.getPropertyValue('fill') ||\n targetElement.getAttribute('fill') ||\n computed.color ||\n '#000';\n\n // Map SVG text-anchor to CSS text-align\n const textAnchor = targetElement.getAttribute('text-anchor') ?? 'start';\n let textAlign = 'left';\n if (textAnchor === 'middle') textAlign = 'center';\n else if (textAnchor === 'end') textAlign = 'right';\n\n return {\n fontFamily,\n fontSize: `${pixelFontSize}px`,\n fontWeight,\n color: fill,\n textAlign,\n lineHeight: '1.3',\n };\n}\n\n/**\n * Compute the pixel position and size for the textarea based on the\n * target SVG element's bounding box.\n */\nfunction computePosition(\n targetElement: SVGElement,\n svg: SVGSVGElement,\n container: HTMLElement,\n): { top: number; left: number; width: number; height: number } {\n const bbox = (targetElement as SVGGraphicsElement).getBBox();\n const scale = getScale(svg);\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n\n // SVG viewBox coords -> pixel coords relative to the container\n const padding = 4;\n const left = bbox.x * scale.scaleX + (svgRect.left - containerRect.left) - padding;\n const top = bbox.y * scale.scaleY + (svgRect.top - containerRect.top) - padding;\n const width = bbox.width * scale.scaleX + padding * 2;\n const height = bbox.height * scale.scaleY + padding * 2;\n\n return {\n top: Math.max(0, top),\n left: Math.max(0, left),\n width: Math.max(width, 60),\n height: Math.max(height, 24),\n };\n}\n\n/**\n * Create an inline text editing overlay positioned over an SVG text element.\n * Returns an object with a `destroy()` method to clean up.\n */\nexport function createTextEditOverlay(config: TextEditOverlayConfig): { destroy: () => void } {\n const { container, svg, targetElement, currentText, onCommit, onCancel } = config;\n\n let destroyed = false;\n\n // Hide the underlying SVG text element (not display:none to preserve layout)\n const originalOpacity = targetElement.getAttribute('opacity');\n targetElement.setAttribute('opacity', '0');\n\n // Compute position and styles\n const scale = getScale(svg);\n const styles = getTextStyles(targetElement, scale);\n const position = computePosition(targetElement, svg, container);\n\n // Create the textarea\n const textarea = document.createElement('textarea');\n textarea.value = currentText;\n\n // Ensure container is positioned so absolute children work\n const containerPosition = window.getComputedStyle(container).position;\n const containerWasStatic = containerPosition === 'static';\n if (containerWasStatic) {\n container.style.position = 'relative';\n }\n\n // Style the textarea to match the SVG text\n Object.assign(textarea.style, {\n position: 'absolute',\n top: `${position.top}px`,\n left: `${position.left}px`,\n width: `${position.width}px`,\n minHeight: `${position.height}px`,\n fontFamily: styles.fontFamily,\n fontSize: styles.fontSize,\n fontWeight: styles.fontWeight,\n color: styles.color,\n textAlign: styles.textAlign,\n lineHeight: styles.lineHeight,\n padding: '2px 4px',\n margin: '0',\n border: '1px solid rgba(79, 70, 229, 0.4)',\n borderRadius: '3px',\n background: 'rgba(255, 255, 255, 0.95)',\n outline: 'none',\n resize: 'none',\n overflow: 'hidden',\n boxSizing: 'border-box',\n zIndex: '10000',\n // Remove default textarea appearance\n WebkitAppearance: 'none',\n appearance: 'none',\n } as Record<string, string>);\n\n container.appendChild(textarea);\n\n // Auto-select all text\n textarea.focus();\n textarea.select();\n\n // Cleanup function\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Restore SVG text visibility\n if (originalOpacity !== null) {\n targetElement.setAttribute('opacity', originalOpacity);\n } else {\n targetElement.removeAttribute('opacity');\n }\n\n // Remove event listeners\n textarea.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n resizeObserver.disconnect();\n\n // Restore container position if we changed it\n if (containerWasStatic) {\n container.style.position = '';\n }\n\n // Remove the textarea\n if (textarea.parentNode) {\n textarea.parentNode.removeChild(textarea);\n }\n }\n\n function commit(): void {\n if (destroyed) return;\n const newText = textarea.value;\n destroy();\n onCommit(newText);\n }\n\n function cancel(): void {\n if (destroyed) return;\n destroy();\n onCancel();\n }\n\n // Keyboard handling\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n commit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancel();\n }\n };\n\n textarea.addEventListener('keydown', handleKeyDown);\n\n // Click outside to commit\n const handleClickOutside = (e: MouseEvent) => {\n if (!textarea.contains(e.target as Node)) {\n commit();\n }\n };\n\n // Delay attaching click-outside so the current click event doesn't trigger it\n requestAnimationFrame(() => {\n if (!destroyed) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n });\n\n // Reposition on container resize\n const resizeObserver = new ResizeObserver(() => {\n if (destroyed) return;\n const newPosition = computePosition(targetElement, svg, container);\n textarea.style.top = `${newPosition.top}px`;\n textarea.style.left = `${newPosition.left}px`;\n textarea.style.width = `${newPosition.width}px`;\n textarea.style.minHeight = `${newPosition.height}px`;\n });\n resizeObserver.observe(container);\n\n return { destroy };\n}\n","/**\n * Table cell renderers: produce DOM elements for each cell type.\n *\n * Each renderer takes a resolved TableCell and returns an HTMLElement\n * (typically a <td>) with appropriate content, styling, and classes.\n */\n\nimport type {\n BarTableCell,\n CategoryTableCell,\n FlagTableCell,\n HeatmapTableCell,\n ImageTableCell,\n SparklineData,\n SparklineTableCell,\n TableCell,\n TextTableCell,\n} from '@opendata-ai/openchart-core';\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/** Apply common cell styles (background, color, font weight, font variant). */\nfunction applyCellStyle(td: HTMLTableCellElement, cell: TableCell): void {\n if (cell.style.backgroundColor) {\n td.style.background = cell.style.backgroundColor;\n }\n if (cell.style.color) {\n td.style.color = cell.style.color;\n }\n if (cell.style.fontWeight) {\n td.style.fontWeight = String(cell.style.fontWeight);\n }\n if (cell.style.fontVariant) {\n td.style.fontVariant = cell.style.fontVariant;\n }\n if (cell.aria) {\n td.setAttribute('aria-label', cell.aria);\n }\n}\n\n/**\n * Convert a 2-char ISO 3166-1 alpha-2 country code to a flag emoji.\n * Each letter maps to a Regional Indicator Symbol (offset 0x1F1A5 from ASCII).\n */\nfunction countryToEmoji(code: string): string {\n return [...code.toUpperCase()]\n .map((c) => String.fromCodePoint(c.charCodeAt(0) + 0x1f1a5))\n .join('');\n}\n\n/**\n * Lookup map for common country names by ISO 3166-1 alpha-2 code.\n * Falls back to the raw code for unrecognized values.\n */\nconst COUNTRY_NAMES: Record<string, string> = {\n US: 'United States',\n CN: 'China',\n IN: 'India',\n ID: 'Indonesia',\n BR: 'Brazil',\n PK: 'Pakistan',\n NG: 'Nigeria',\n BD: 'Bangladesh',\n RU: 'Russia',\n MX: 'Mexico',\n JP: 'Japan',\n DE: 'Germany',\n GB: 'United Kingdom',\n FR: 'France',\n IT: 'Italy',\n CA: 'Canada',\n AU: 'Australia',\n KR: 'South Korea',\n ES: 'Spain',\n AR: 'Argentina',\n CO: 'Colombia',\n ZA: 'South Africa',\n TR: 'Turkey',\n SA: 'Saudi Arabia',\n UA: 'Ukraine',\n PL: 'Poland',\n NL: 'Netherlands',\n SE: 'Sweden',\n NO: 'Norway',\n DK: 'Denmark',\n FI: 'Finland',\n CH: 'Switzerland',\n AT: 'Austria',\n BE: 'Belgium',\n PT: 'Portugal',\n IE: 'Ireland',\n NZ: 'New Zealand',\n SG: 'Singapore',\n IL: 'Israel',\n AE: 'United Arab Emirates',\n EG: 'Egypt',\n TH: 'Thailand',\n VN: 'Vietnam',\n PH: 'Philippines',\n MY: 'Malaysia',\n CL: 'Chile',\n PE: 'Peru',\n CZ: 'Czech Republic',\n GR: 'Greece',\n HU: 'Hungary',\n RO: 'Romania',\n ET: 'Ethiopia',\n};\n\n/** Get a human-readable name for a country code. */\nfunction getCountryName(code: string): string {\n return COUNTRY_NAMES[code.toUpperCase()] || code.toUpperCase();\n}\n\n/**\n * Describe a sparkline trend for screen readers.\n * Compares first and last values to determine direction.\n */\nfunction describeSparklineTrend(data: SparklineData): string {\n if (data.type === 'line' && data.points.length >= 2) {\n const first = data.points[0].y;\n const last = data.points[data.points.length - 1].y;\n const count = data.points.length;\n if (last > first) return `Sparkline with ${count} points, trending upward`;\n if (last < first) return `Sparkline with ${count} points, trending downward`;\n return `Sparkline with ${count} points, roughly flat`;\n }\n if ((data.type === 'bar' || data.type === 'column') && data.bars.length > 0) {\n return `${data.type === 'column' ? 'Column' : 'Bar'} sparkline with ${data.bars.length} values`;\n }\n return 'Sparkline';\n}\n\n// ---------------------------------------------------------------------------\n// Cell renderers\n// ---------------------------------------------------------------------------\n\n/** Render a plain text cell. */\nexport function renderTextCell(cell: TextTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.textContent = cell.formattedValue;\n applyCellStyle(td, cell);\n return td;\n}\n\n/** Render a heatmap-colored cell. */\nexport function renderHeatmapCell(cell: HeatmapTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.className = 'oc-table-heatmap';\n td.textContent = cell.formattedValue;\n applyCellStyle(td, cell);\n return td;\n}\n\n/** Render a category-colored cell. */\nexport function renderCategoryCell(cell: CategoryTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.className = 'oc-table-category';\n td.textContent = cell.formattedValue;\n applyCellStyle(td, cell);\n return td;\n}\n\n/** Render a cell with an inline bar visualization. */\nexport function renderBarCell(cell: BarTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.className = 'oc-table-bar';\n applyCellStyle(td, cell);\n\n const fill = document.createElement('div');\n fill.className = 'oc-table-bar-fill';\n fill.style.width = `${Math.round(cell.barWidth * 100)}%`;\n fill.style.left = `${Math.round(cell.barOffset * 100)}%`;\n fill.style.background = cell.barColor;\n td.appendChild(fill);\n\n const valueSpan = document.createElement('span');\n valueSpan.className = 'oc-table-bar-value';\n valueSpan.textContent = cell.formattedValue;\n td.appendChild(valueSpan);\n\n return td;\n}\n\n/**\n * Format a sparkline endpoint value for display.\n * Keeps it compact: no decimals for values >= 100, one decimal otherwise.\n */\nfunction formatSparklineValue(v: number): string {\n if (Math.abs(v) >= 1000) {\n return v.toLocaleString('en-US', { maximumFractionDigits: 0 });\n }\n if (Math.abs(v) >= 100) {\n return v.toFixed(0);\n }\n return v.toFixed(1);\n}\n\n/** Render a cell with an inline sparkline SVG. */\nexport function renderSparklineCell(cell: SparklineTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n applyCellStyle(td, cell);\n\n const sparklineData = cell.sparklineData;\n if (!sparklineData || sparklineData.count === 0) {\n td.textContent = cell.formattedValue || '';\n return td;\n }\n\n // Add aria-label describing the trend for screen readers\n const trendDescription = describeSparklineTrend(sparklineData);\n if (!td.getAttribute('aria-label')) {\n td.setAttribute('aria-label', trendDescription);\n }\n\n const wrapper = document.createElement('span');\n wrapper.className = 'oc-table-sparkline';\n\n const svgNS = 'http://www.w3.org/2000/svg';\n\n if (sparklineData.type === 'line') {\n // Infrographic-style sparkline: SVG polyline fills cell width via percentage x-coords.\n // Dots are HTML elements (not SVG circles) to avoid aspect-ratio distortion.\n // Labels are HTML below the SVG.\n const svgH = 28;\n const padY = 4;\n const lineH = svgH - padY * 2;\n\n const svg = document.createElementNS(svgNS, 'svg');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('xmlns', svgNS);\n svg.style.height = `${svgH}px`;\n\n // Compute y positions in pixel space (no viewBox scaling)\n const yPositions = sparklineData.points.map((p) => padY + (1 - p.y) * lineH);\n\n // SVG polyline doesn't support % in points attribute, so use a viewBox\n // with a wide aspect ratio and map x to 0-1000 range. preserveAspectRatio=\"none\"\n // stretches the x-axis to fill the cell width. Y values stay in pixel space\n // since viewBox height matches the SVG height. Only the polyline is in the SVG;\n // dots are HTML elements to avoid circle distortion from the non-uniform scaling.\n const viewW = 1000;\n svg.setAttribute('viewBox', `0 0 ${viewW} ${svgH}`);\n svg.setAttribute('preserveAspectRatio', 'none');\n\n const ptsScaled = sparklineData.points.map((p, i) => ({\n x: p.x * viewW,\n y: yPositions[i],\n }));\n const scaledPointsStr = ptsScaled.map((p) => `${p.x},${p.y}`).join(' ');\n\n const polyline = document.createElementNS(svgNS, 'polyline');\n polyline.setAttribute('points', scaledPointsStr);\n polyline.setAttribute('fill', 'none');\n polyline.setAttribute('stroke', sparklineData.color);\n polyline.setAttribute('stroke-width', '1.5');\n polyline.setAttribute('stroke-linejoin', 'round');\n polyline.setAttribute('vector-effect', 'non-scaling-stroke');\n svg.appendChild(polyline);\n\n wrapper.appendChild(svg);\n\n // HTML dots at start and end (positioned absolutely over the SVG)\n const firstY = yPositions[0];\n const lastY = yPositions[yPositions.length - 1];\n const dotSize = 5;\n\n const startDot = document.createElement('span');\n startDot.className = 'oc-table-sparkline-dot';\n startDot.style.left = '0';\n startDot.style.top = `${firstY - dotSize / 2}px`;\n startDot.style.background = sparklineData.color;\n wrapper.appendChild(startDot);\n\n const endDot = document.createElement('span');\n endDot.className = 'oc-table-sparkline-dot';\n endDot.style.right = '0';\n endDot.style.top = `${lastY - dotSize / 2}px`;\n endDot.style.background = sparklineData.color;\n wrapper.appendChild(endDot);\n\n // HTML labels below the SVG, positioned at left and right edges\n const labelsRow = document.createElement('span');\n labelsRow.className = 'oc-table-sparkline-labels';\n labelsRow.style.color = sparklineData.color;\n\n const startLabel = document.createElement('span');\n startLabel.textContent = formatSparklineValue(sparklineData.startValue);\n labelsRow.appendChild(startLabel);\n\n const endLabel = document.createElement('span');\n endLabel.textContent = formatSparklineValue(sparklineData.endValue);\n labelsRow.appendChild(endLabel);\n\n wrapper.appendChild(labelsRow);\n } else if (sparklineData.type === 'column') {\n // Vertical bars at proportional heights\n const width = 80;\n const height = 20;\n const padding = 2;\n const innerW = width - padding * 2;\n const innerH = height - padding * 2;\n\n const svg = document.createElementNS(svgNS, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n svg.setAttribute('aria-hidden', 'true');\n\n const barCount = sparklineData.bars.length;\n if (barCount > 0) {\n const gap = 1;\n const barW = Math.max(1, (innerW - gap * (barCount - 1)) / barCount);\n\n for (let i = 0; i < barCount; i++) {\n const barH = Math.max(1, sparklineData.bars[i] * innerH);\n const x = padding + i * (barW + gap);\n const y = padding + innerH - barH;\n\n const rect = document.createElementNS(svgNS, 'rect');\n rect.setAttribute('x', String(x));\n rect.setAttribute('y', String(y));\n rect.setAttribute('width', String(barW));\n rect.setAttribute('height', String(barH));\n rect.setAttribute('rx', '1.5');\n rect.setAttribute('fill', sparklineData.color);\n svg.appendChild(rect);\n }\n }\n\n wrapper.appendChild(svg);\n } else {\n // 'bar' type: horizontal bars at proportional widths\n const width = 80;\n const height = 20;\n const padding = 2;\n const innerW = width - padding * 2;\n const innerH = height - padding * 2;\n\n const svg = document.createElementNS(svgNS, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n svg.setAttribute('aria-hidden', 'true');\n\n const barCount = sparklineData.bars.length;\n if (barCount > 0) {\n const gap = 1;\n const barH = Math.max(1, (innerH - gap * (barCount - 1)) / barCount);\n\n for (let i = 0; i < barCount; i++) {\n const barW = Math.max(1, sparklineData.bars[i] * innerW);\n const x = padding;\n const y = padding + i * (barH + gap);\n\n const rect = document.createElementNS(svgNS, 'rect');\n rect.setAttribute('x', String(x));\n rect.setAttribute('y', String(y));\n rect.setAttribute('width', String(barW));\n rect.setAttribute('height', String(barH));\n rect.setAttribute('rx', '1.5');\n rect.setAttribute('fill', sparklineData.color);\n svg.appendChild(rect);\n }\n }\n\n wrapper.appendChild(svg);\n }\n\n td.appendChild(wrapper);\n\n return td;\n}\n\n/** Render a cell with an image. */\nexport function renderImageCell(cell: ImageTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n applyCellStyle(td, cell);\n\n const wrapper = document.createElement('span');\n wrapper.className = `oc-table-image${cell.rounded ? ' oc-table-image-rounded' : ''}`;\n\n const img = document.createElement('img');\n img.src = cell.src;\n img.alt = cell.formattedValue || '';\n img.width = cell.imageWidth;\n img.height = cell.imageHeight;\n img.loading = 'lazy';\n\n wrapper.appendChild(img);\n td.appendChild(wrapper);\n\n return td;\n}\n\n/** Render a cell with a country flag emoji. */\nexport function renderFlagCell(cell: FlagTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n applyCellStyle(td, cell);\n\n const span = document.createElement('span');\n span.className = 'oc-table-flag';\n span.setAttribute('role', 'img');\n\n if (cell.countryCode && cell.countryCode.length === 2) {\n const countryName = getCountryName(cell.countryCode);\n span.textContent = countryToEmoji(cell.countryCode);\n span.setAttribute('aria-label', `Flag: ${countryName}`);\n } else {\n span.textContent = cell.formattedValue;\n span.setAttribute('aria-label', cell.formattedValue);\n }\n\n td.appendChild(span);\n\n return td;\n}\n\n// ---------------------------------------------------------------------------\n// Dispatcher\n// ---------------------------------------------------------------------------\n\n/** Render any table cell by dispatching on its cellType. */\nexport function renderCell(cell: TableCell): HTMLTableCellElement {\n switch (cell.cellType) {\n case 'text':\n return renderTextCell(cell);\n case 'heatmap':\n return renderHeatmapCell(cell);\n case 'category':\n return renderCategoryCell(cell);\n case 'bar':\n return renderBarCell(cell);\n case 'sparkline':\n return renderSparklineCell(cell);\n case 'image':\n return renderImageCell(cell);\n case 'flag':\n return renderFlagCell(cell);\n default:\n // Exhaustive check fallback\n return renderTextCell(cell as TextTableCell);\n }\n}\n","/**\n * Sankey mount API: the main entry point for vanilla JS sankey usage.\n *\n * createSankey() takes a container, SankeySpec, and options, compiles the\n * sankey, renders it as SVG, sets up responsive resizing, tooltip interaction,\n * hover highlighting, and returns a SankeyInstance with update/resize/export/destroy.\n */\n\nimport type {\n CompileOptions,\n DarkMode,\n SankeyLayout,\n SankeySpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { compileSankey } from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, setupAnimationCleanup } from './animation';\nimport {\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport { observeResize } from './resize-observer';\nimport { renderSankeySVG } from './sankey-renderer';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SankeyMountOptions {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting: \"auto\" (system pref), \"force\", or \"off\". */\n darkMode?: DarkMode;\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Show tooltips on hover. Defaults to true. */\n tooltip?: boolean;\n /** Callback when a node is clicked. */\n onNodeClick?: (node: Record<string, unknown>) => void;\n /** Callback when a link is clicked. */\n onLinkClick?: (link: Record<string, unknown>) => void;\n /** Callback when a node is hovered (null on mouse leave). */\n onNodeHover?: (node: Record<string, unknown> | null) => void;\n /** Callback when a link is hovered (null on mouse leave). */\n onLinkHover?: (link: Record<string, unknown> | null) => void;\n}\n\nexport interface SankeyInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: SankeySpec): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the sankey diagram. */\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n options?: JPGExportOptions,\n ): string | Promise<Blob> | Promise<string>;\n /** Remove all DOM elements and disconnect observers. */\n destroy(): void;\n /** The current compiled layout. */\n readonly layout: SankeyLayout;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Opacity for links connected to hovered node. */\nconst HIGHLIGHT_OPACITY = 0.7;\n/** Opacity for links NOT connected to hovered node. */\nconst DIM_OPACITY = 0.15;\n/** Opacity for nodes NOT connected to hovered node. */\nconst NODE_DIM_OPACITY = 0.2;\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a sankey instance from a spec and mount it into a container.\n */\nexport function createSankey(\n container: HTMLElement,\n spec: SankeySpec,\n options?: SankeyMountOptions,\n): SankeyInstance {\n let currentSpec = spec;\n let currentLayout: SankeyLayout;\n let destroyed = false;\n\n // DOM\n let svgElement: SVGSVGElement | null = null;\n\n // Subsystems\n let tooltipManager: TooltipManager | null = null;\n let cleanupTooltipEvents: (() => void) | null = null;\n let disconnectResize: (() => void) | null = null;\n\n // Animation state\n let isFirstRender = true;\n let animationCleanup: (() => void) | null = null;\n let pendingResize = false;\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n function compile(): SankeyLayout {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n };\n\n return compileSankey(currentSpec, compileOpts);\n }\n\n // ---------------------------------------------------------------------------\n // Tooltip and interaction wiring\n // ---------------------------------------------------------------------------\n\n function wireTooltipAndInteraction(svg: SVGSVGElement, layout: SankeyLayout): () => void {\n const cleanups: Array<() => void> = [];\n\n // Wire tooltip on node elements\n const nodeElements = svg.querySelectorAll('.oc-sankey-node');\n for (const el of nodeElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = layout.tooltipDescriptors.get(markId);\n const nodeId = el.getAttribute('data-node-id');\n const nodeData = nodeId ? (layout.nodes.find((n) => n.nodeId === nodeId)?.data ?? {}) : {};\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n if (content && tooltipManager) {\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n options?.onNodeHover?.(nodeData);\n if (nodeId) highlightConnectedLinks(svg, nodeId, layout);\n };\n\n const handleMouseMove = (e: Event) => {\n if (content && tooltipManager) {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n const handleMouseLeave = () => {\n tooltipManager?.hide();\n options?.onNodeHover?.(null);\n resetLinkOpacity(svg, layout);\n };\n\n const handleClick = () => {\n options?.onNodeClick?.(nodeData);\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('click', handleClick);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('click', handleClick);\n });\n }\n\n // Wire tooltip on link elements\n const linkElements = svg.querySelectorAll('.oc-sankey-link');\n for (const el of linkElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = layout.tooltipDescriptors.get(markId);\n const sourceId = el.getAttribute('data-source');\n const targetId = el.getAttribute('data-target');\n const linkData = findLinkData(layout, sourceId, targetId);\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n if (content && tooltipManager) {\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n options?.onLinkHover?.(linkData);\n };\n\n const handleMouseMove = (e: Event) => {\n if (content && tooltipManager) {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n const handleMouseLeave = () => {\n tooltipManager?.hide();\n options?.onLinkHover?.(null);\n };\n\n const handleClick = () => {\n options?.onLinkClick?.(linkData);\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('click', handleClick);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('click', handleClick);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n /**\n * Find the data record for a link by source/target ids.\n */\n function findLinkData(\n layout: SankeyLayout,\n sourceId: string | null,\n targetId: string | null,\n ): Record<string, unknown> {\n if (!sourceId || !targetId) return {};\n const link = layout.links.find((l) => l.sourceId === sourceId && l.targetId === targetId);\n return link?.data ?? {};\n }\n\n /**\n * Highlight links connected to a node and dim unconnected links.\n */\n function highlightConnectedLinks(\n svg: SVGSVGElement,\n nodeId: string,\n _layout: SankeyLayout,\n ): void {\n // Collect connected node IDs (the hovered node + its direct neighbors)\n const connectedNodeIds = new Set<string>([nodeId]);\n const linkElements = svg.querySelectorAll('.oc-sankey-link');\n for (const el of linkElements) {\n const source = el.getAttribute('data-source');\n const target = el.getAttribute('data-target');\n const path = el.querySelector('path');\n if (!path) continue;\n\n const isConnected = source === nodeId || target === nodeId;\n path.setAttribute('fill-opacity', String(isConnected ? HIGHLIGHT_OPACITY : DIM_OPACITY));\n if (isConnected) {\n if (source) connectedNodeIds.add(source);\n if (target) connectedNodeIds.add(target);\n }\n }\n\n // Dim unconnected nodes (rect + label)\n const nodeElements = svg.querySelectorAll('.oc-sankey-node');\n for (const el of nodeElements) {\n const nid = el.getAttribute('data-node-id');\n if (!nid) continue;\n const isConnected = connectedNodeIds.has(nid);\n (el as SVGElement).style.opacity = isConnected ? '1' : String(NODE_DIM_OPACITY);\n }\n }\n\n /**\n * Reset all link opacities and node opacities to their original values.\n */\n function resetLinkOpacity(svg: SVGSVGElement, layout: SankeyLayout): void {\n const linkElements = svg.querySelectorAll('.oc-sankey-link');\n for (const el of linkElements) {\n const path = el.querySelector('path');\n if (!path) continue;\n // Look up the original opacity via data attributes rather than positional index\n const source = el.getAttribute('data-source');\n const target = el.getAttribute('data-target');\n const link = layout.links.find((l) => l.sourceId === source && l.targetId === target);\n path.setAttribute('fill-opacity', String(link?.fillOpacity ?? 0.5));\n }\n\n // Restore all node opacities\n const nodeElements = svg.querySelectorAll('.oc-sankey-node');\n for (const el of nodeElements) {\n (el as SVGElement).style.opacity = '1';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n function render(): void {\n if (destroyed) return;\n\n // Cancel in-progress animations before tearing down\n if (animationCleanup) {\n animationCleanup();\n animationCleanup = null;\n }\n if (svgElement) {\n cancelAnimations(svgElement);\n }\n\n // Clean up previous tooltip listeners\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n\n // Remove old SVG\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n\n // Compile\n currentLayout = compile();\n\n // Determine if we should animate\n const shouldAnimate = isFirstRender && currentLayout.animation?.enabled;\n isFirstRender = false;\n\n // Render\n const animation = shouldAnimate ? currentLayout.animation : undefined;\n svgElement = renderSankeySVG(currentLayout, animation);\n container.appendChild(svgElement);\n\n // Dark mode class on container\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Wire tooltip + interaction events\n if (options?.tooltip !== false && svgElement) {\n if (!tooltipManager) {\n tooltipManager = createTooltipManager(container);\n }\n cleanupTooltipEvents = wireTooltipAndInteraction(svgElement, currentLayout);\n }\n\n // Animation cleanup on first render\n if (shouldAnimate && svgElement) {\n animationCleanup = setupAnimationCleanup(svgElement, () => {\n animationCleanup = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n function update(newSpec: SankeySpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n isFirstRender = true; // Allow animation on update\n render();\n }\n\n function resize(): void {\n if (destroyed) return;\n // Skip resize during entrance animation to avoid tearing down the animated SVG.\n // Queued resizes replay once animation completes.\n if (animationCleanup) {\n pendingResize = true;\n return;\n }\n render();\n }\n\n function doExport(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n exportOptions?: JPGExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) {\n throw new Error('Sankey is not rendered yet');\n }\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement, exportOptions as SVGExportOptions);\n case 'png':\n return exportPNG(svgElement, exportOptions);\n case 'jpg':\n return exportJPG(svgElement, exportOptions);\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel entrance animations\n if (animationCleanup) {\n animationCleanup();\n animationCleanup = null;\n pendingResize = false;\n }\n if (svgElement) {\n cancelAnimations(svgElement);\n }\n\n // Disconnect resize observer\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n\n // Clean up tooltip events\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n\n // Destroy tooltip manager\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n\n // Remove SVG\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n svgElement = null;\n\n container.classList.remove('oc-dark');\n }\n\n // ---------------------------------------------------------------------------\n // Initialize\n // ---------------------------------------------------------------------------\n\n try {\n currentLayout = compile();\n\n // Determine if we should animate\n const shouldAnimate = currentLayout.animation?.enabled;\n isFirstRender = false;\n\n // Render\n const animation = shouldAnimate ? currentLayout.animation : undefined;\n svgElement = renderSankeySVG(currentLayout, animation);\n container.appendChild(svgElement);\n\n // Dark mode class on container\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Wire tooltip + interaction events\n if (options?.tooltip !== false && svgElement) {\n tooltipManager = createTooltipManager(container);\n cleanupTooltipEvents = wireTooltipAndInteraction(svgElement, currentLayout);\n }\n\n // Animation cleanup\n if (shouldAnimate && svgElement) {\n animationCleanup = setupAnimationCleanup(svgElement, () => {\n animationCleanup = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n } catch (err) {\n console.error('[viz] Sankey mount failed:', err);\n // Re-throw so callers can handle the error rather than silently returning a broken instance\n throw err;\n }\n\n // Responsive resize\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n resize();\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n destroy,\n get layout() {\n return currentLayout;\n },\n };\n}\n","/**\n * Sankey SVG renderer: converts a SankeyLayout into SVG DOM elements.\n *\n * Creates an <svg> with gradient defs, links (behind), nodes, labels,\n * legend, and chrome. All styling via inline SVG attributes from layout data.\n * Animation is pure CSS, driven by data attributes and CSS custom properties.\n */\n\nimport type {\n LegendLayout,\n ResolvedAnimation,\n ResolvedChromeElement,\n SankeyLayout,\n SankeyLinkMark,\n SankeyNodeMark,\n TextStyle,\n} from '@opendata-ai/openchart-core';\nimport { BRAND_FONT_SIZE, BRAND_MIN_WIDTH, estimateTextWidth } from '@opendata-ai/openchart-core';\nimport { clampStaggerDelay } from '@opendata-ai/openchart-engine';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\nconst BRAND_URL = 'https://tryopendata.ai';\n\n/** CSS easing preset map for inline style custom properties. */\nconst EASE_VAR_MAP: Record<string, string> = {\n smooth: 'var(--oc-ease-smooth)',\n snappy: 'var(--oc-ease-snappy)',\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createSVGElement(tag: string): SVGElement {\n return document.createElementNS(SVG_NS, tag);\n}\n\nfunction setAttrs(el: SVGElement, attrs: Record<string, string | number>): void {\n for (const [key, value] of Object.entries(attrs)) {\n el.setAttribute(key, String(value));\n }\n}\n\nfunction applyTextStyle(el: SVGElement, style: TextStyle): void {\n setAttrs(el, {\n 'font-family': style.fontFamily,\n 'font-size': style.fontSize,\n 'font-weight': style.fontWeight,\n });\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', style.fill);\n if (style.textAnchor) {\n el.setAttribute('text-anchor', style.textAnchor);\n }\n if (style.dominantBaseline) {\n el.setAttribute('dominant-baseline', style.dominantBaseline);\n }\n if (style.fontVariant) {\n el.setAttribute('font-variant', style.fontVariant);\n }\n}\n\n/**\n * Stamp animation index attributes on a mark element when animation is enabled.\n */\nfunction stampAnimationAttrs(\n el: SVGElement,\n mark: { animationIndex?: number },\n fallbackIndex: number,\n animation?: ResolvedAnimation,\n): void {\n if (!animation?.enabled) return;\n const idx = mark.animationIndex ?? fallbackIndex;\n el.setAttribute('data-animation-index', String(idx));\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('--oc-mark-index', String(idx));\n}\n\n// ---------------------------------------------------------------------------\n// Chrome rendering\n// ---------------------------------------------------------------------------\n\n/**\n * Break text into lines that fit within maxWidth using word wrapping.\n */\nfunction wrapText(text: string, fontSize: number, fontWeight: number, maxWidth: number): string[] {\n if (maxWidth <= 0) return [text];\n\n const AVG_CHAR_WIDTH = 0.55;\n const WEIGHT_FACTORS: Record<number, number> = {\n 100: 0.9,\n 200: 0.92,\n 300: 0.95,\n 400: 1.0,\n 500: 1.02,\n 600: 1.05,\n 700: 1.08,\n 800: 1.1,\n 900: 1.12,\n };\n const weightFactor = WEIGHT_FACTORS[fontWeight] ?? 1.0;\n const charWidth = fontSize * AVG_CHAR_WIDTH * weightFactor;\n const maxChars = Math.floor(maxWidth / charWidth);\n\n if (text.length <= maxChars) return [text];\n\n const words = text.split(' ');\n const lines: string[] = [];\n let current = '';\n\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n if (candidate.length > maxChars && current) {\n lines.push(current);\n current = word;\n } else {\n current = candidate;\n }\n }\n if (current) lines.push(current);\n\n return lines;\n}\n\nfunction renderChromeElement(\n parent: SVGElement,\n element: ResolvedChromeElement,\n className: string,\n chromeKey: string,\n): void {\n const text = createSVGElement('text');\n setAttrs(text, { x: element.x, y: element.y });\n applyTextStyle(text, element.style);\n text.setAttribute('class', className);\n text.setAttribute('data-chrome-key', chromeKey);\n\n const lines = wrapText(\n element.text,\n element.style.fontSize,\n element.style.fontWeight,\n element.maxWidth,\n );\n\n if (lines.length === 1) {\n text.textContent = element.text;\n } else {\n const lineHeight = element.style.fontSize * (element.style.lineHeight ?? 1.3);\n for (let i = 0; i < lines.length; i++) {\n const tspan = createSVGElement('tspan');\n setAttrs(tspan, { x: element.x, dy: i === 0 ? 0 : lineHeight });\n tspan.textContent = lines[i];\n text.appendChild(tspan);\n }\n }\n\n parent.appendChild(text);\n}\n\nfunction renderChrome(parent: SVGElement, layout: SankeyLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-chrome');\n\n const { chrome } = layout;\n\n if (chrome.title) {\n renderChromeElement(g, chrome.title, 'oc-title', 'title');\n }\n if (chrome.subtitle) {\n renderChromeElement(g, chrome.subtitle, 'oc-subtitle', 'subtitle');\n }\n\n // Bottom chrome: positioned below the sankey drawing area.\n // Sankey has no x-axis, so no extra axis extent to account for.\n const bottomOffset = layout.area.y + layout.area.height;\n if (chrome.source) {\n renderChromeElement(\n g,\n { ...chrome.source, y: bottomOffset + chrome.source.y },\n 'oc-source',\n 'source',\n );\n }\n if (chrome.byline) {\n renderChromeElement(\n g,\n { ...chrome.byline, y: bottomOffset + chrome.byline.y },\n 'oc-byline',\n 'byline',\n );\n }\n if (chrome.footer) {\n renderChromeElement(\n g,\n { ...chrome.footer, y: bottomOffset + chrome.footer.y },\n 'oc-footer',\n 'footer',\n );\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Brand rendering\n// ---------------------------------------------------------------------------\n\nfunction renderBrand(parent: SVGElement, layout: SankeyLayout): void {\n if (layout.dimensions.width < BRAND_MIN_WIDTH) return;\n\n const { width } = layout.dimensions;\n const padding = layout.theme.spacing.padding;\n const rightEdge = width - padding;\n const fill = layout.theme.colors.axis;\n\n const bottomOffset = layout.area.y + layout.area.height;\n const { chrome } = layout;\n const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;\n const chromeY = firstBottom\n ? bottomOffset + firstBottom.y\n : bottomOffset + layout.theme.spacing.chartToFooter;\n\n const a = createSVGElement('a');\n a.setAttribute('href', BRAND_URL);\n a.setAttributeNS(XLINK_NS, 'xlink:href', BRAND_URL);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.setAttribute('class', 'oc-chrome-ref');\n\n const BRAND_LARGE = 16;\n const text = createSVGElement('text');\n setAttrs(text, {\n x: rightEdge,\n y: chromeY + BRAND_LARGE,\n 'dominant-baseline': 'alphabetic',\n 'text-anchor': 'end',\n 'font-family': layout.theme.fonts.family,\n 'font-size': BRAND_FONT_SIZE,\n 'fill-opacity': 0.55,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', fill);\n\n const trySpan = createSVGElement('tspan');\n setAttrs(trySpan, { 'font-weight': 500 });\n trySpan.textContent = 'try';\n\n const openDataSpan = createSVGElement('tspan');\n setAttrs(openDataSpan, { 'font-weight': 600, 'font-size': BRAND_LARGE });\n openDataSpan.textContent = 'OpenData';\n\n const aiSpan = createSVGElement('tspan');\n setAttrs(aiSpan, { 'font-weight': 500 });\n aiSpan.textContent = '.ai';\n\n text.appendChild(trySpan);\n text.appendChild(openDataSpan);\n text.appendChild(aiSpan);\n a.appendChild(text);\n parent.appendChild(a);\n}\n\n// ---------------------------------------------------------------------------\n// Legend rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLegend(parent: SVGElement, legend: LegendLayout): void {\n if (legend.entries.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-legend');\n g.setAttribute('role', 'list');\n g.setAttribute('aria-label', 'Chart legend');\n\n const isHorizontal = legend.position === 'top' || legend.position === 'bottom';\n let offsetX = legend.bounds.x;\n let offsetY = legend.bounds.y;\n\n for (let i = 0; i < legend.entries.length; i++) {\n const entry = legend.entries[i];\n\n // Wrap to next line if this entry would overflow bounds\n if (isHorizontal && i > 0) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n if (offsetX + entryWidth > legend.bounds.x + legend.bounds.width) {\n offsetX = legend.bounds.x;\n offsetY += legend.swatchSize + 6;\n }\n }\n\n const entryG = createSVGElement('g');\n entryG.setAttribute('class', 'oc-legend-entry');\n entryG.setAttribute('role', 'listitem');\n entryG.setAttribute('data-legend-index', String(i));\n entryG.setAttribute('data-legend-label', entry.label);\n\n if (entry.overflow) {\n entryG.setAttribute('data-legend-overflow', 'true');\n entryG.setAttribute('aria-label', entry.label);\n entryG.setAttribute('opacity', '0.5');\n } else {\n entryG.setAttribute(\n 'aria-label',\n `${entry.label}: ${entry.active !== false ? 'visible' : 'hidden'}`,\n );\n entryG.setAttribute('style', 'cursor: pointer');\n if (entry.active === false) {\n entryG.setAttribute('opacity', '0.3');\n }\n }\n\n // Swatch (always rect for sankey)\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: offsetX,\n y: offsetY,\n width: legend.swatchSize,\n height: legend.swatchSize,\n fill: entry.color,\n rx: 2,\n });\n entryG.appendChild(rect);\n\n // Label\n const label = createSVGElement('text');\n setAttrs(label, {\n x: offsetX + legend.swatchSize + legend.swatchGap,\n y: offsetY + legend.swatchSize / 2,\n 'dominant-baseline': 'central',\n });\n applyTextStyle(label, legend.labelStyle);\n label.textContent = entry.label;\n entryG.appendChild(label);\n\n g.appendChild(entryG);\n\n // Advance position for next entry\n if (isHorizontal) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n offsetX += entryWidth;\n } else {\n offsetY += legend.swatchSize + legend.entryGap;\n }\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Gradient defs\n// ---------------------------------------------------------------------------\n\n/**\n * Build a node position lookup for gradient x1/x2 coordinates.\n * Maps nodeId to { x, width } so we can compute gradient endpoints.\n */\nfunction buildNodePositionMap(nodes: SankeyNodeMark[]): Map<string, { x: number; width: number }> {\n const map = new Map<string, { x: number; width: number }>();\n for (const node of nodes) {\n map.set(node.nodeId, { x: node.x, width: node.width });\n }\n return map;\n}\n\n/** Sanitize a string for use as an SVG element ID (no spaces, $, or other invalid chars). */\nfunction sanitizeId(s: string): string {\n return s.replace(/[^a-zA-Z0-9_-]/g, '_');\n}\n\nfunction renderGradientDefs(\n defs: SVGElement,\n links: SankeyLinkMark[],\n nodePositions: Map<string, { x: number; width: number }>,\n): void {\n for (let i = 0; i < links.length; i++) {\n const link = links[i];\n // Only create gradients when source and target colors differ\n if (link.sourceColor === link.targetColor) continue;\n\n // Use sanitized node names for debuggability, with index suffix for uniqueness\n const gradId = `oc-sg-${sanitizeId(link.sourceId)}-${sanitizeId(link.targetId)}-${i}`;\n const gradient = createSVGElement('linearGradient');\n gradient.setAttribute('id', gradId);\n gradient.setAttribute('gradientUnits', 'userSpaceOnUse');\n\n // x1 = right edge of source node, x2 = left edge of target node\n const sourcePos = nodePositions.get(link.sourceId);\n const targetPos = nodePositions.get(link.targetId);\n const x1 = sourcePos ? sourcePos.x + sourcePos.width : 0;\n const x2 = targetPos ? targetPos.x : 0;\n\n gradient.setAttribute('x1', String(x1));\n gradient.setAttribute('x2', String(x2));\n\n const stop0 = createSVGElement('stop');\n setAttrs(stop0, { offset: '0%', 'stop-color': link.sourceColor });\n gradient.appendChild(stop0);\n\n const stop1 = createSVGElement('stop');\n setAttrs(stop1, { offset: '100%', 'stop-color': link.targetColor });\n gradient.appendChild(stop1);\n\n defs.appendChild(gradient);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Links rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLinks(\n parent: SVGElement,\n links: SankeyLinkMark[],\n _nodePositions: Map<string, { x: number; width: number }>,\n animation?: ResolvedAnimation,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-sankey-links');\n\n for (let i = 0; i < links.length; i++) {\n const link = links[i];\n\n const linkG = createSVGElement('g');\n linkG.setAttribute('class', 'oc-sankey-link');\n linkG.setAttribute('data-mark-id', `link-${link.sourceId}-${link.targetId}-${i}`);\n linkG.setAttribute('data-source', link.sourceId);\n linkG.setAttribute('data-target', link.targetId);\n\n if (link.aria?.label) {\n linkG.setAttribute('aria-label', link.aria.label);\n }\n\n stampAnimationAttrs(linkG, link, i, animation);\n\n const path = createSVGElement('path');\n path.setAttribute('d', link.path);\n path.setAttribute('stroke', 'none');\n path.setAttribute('fill-opacity', String(link.fillOpacity));\n\n // Use gradient fill when colors differ, otherwise solid fill\n if (link.sourceColor !== link.targetColor) {\n const gradId = `oc-sg-${sanitizeId(link.sourceId)}-${sanitizeId(link.targetId)}-${i}`;\n path.setAttribute('fill', `url(#${gradId})`);\n } else {\n path.setAttribute('fill', link.sourceColor);\n }\n\n linkG.appendChild(path);\n g.appendChild(linkG);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Nodes rendering\n// ---------------------------------------------------------------------------\n\nfunction renderNodes(\n parent: SVGElement,\n nodes: SankeyNodeMark[],\n animation?: ResolvedAnimation,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-sankey-nodes');\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n\n const nodeG = createSVGElement('g');\n nodeG.setAttribute('class', 'oc-sankey-node');\n nodeG.setAttribute('data-mark-id', `node-${node.nodeId}`);\n nodeG.setAttribute('data-node-id', node.nodeId);\n\n if (node.aria?.label) {\n nodeG.setAttribute('aria-label', node.aria.label);\n }\n\n stampAnimationAttrs(nodeG, node, i, animation);\n\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: node.x,\n y: node.y,\n width: node.width,\n height: Math.max(node.height, 1), // Ensure at least 1px visibility\n fill: node.fill,\n rx: node.cornerRadius,\n });\n\n if (node.stroke) {\n rect.setAttribute('stroke', node.stroke);\n }\n if (node.strokeWidth) {\n rect.setAttribute('stroke-width', String(node.strokeWidth));\n }\n\n nodeG.appendChild(rect);\n g.appendChild(nodeG);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Labels rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLabels(parent: SVGElement, nodes: SankeyNodeMark[]): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-sankey-labels');\n\n for (const node of nodes) {\n const { label } = node;\n if (!label.visible) continue;\n\n const text = createSVGElement('text');\n setAttrs(text, { x: label.x, y: label.y });\n applyTextStyle(text, label.style);\n text.textContent = label.text;\n\n g.appendChild(text);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Main render function\n// ---------------------------------------------------------------------------\n\n/**\n * Render a SankeyLayout into an SVG element.\n *\n * The SVG structure is: background > defs (gradients) > links > nodes > labels > legend > chrome > brand.\n * Links render before nodes so they appear visually behind.\n */\nexport function renderSankeySVG(\n layout: SankeyLayout,\n animation?: ResolvedAnimation,\n): SVGSVGElement {\n const { width, height } = layout.dimensions;\n\n const svg = createSVGElement('svg') as SVGSVGElement;\n setAttrs(svg, {\n viewBox: `0 0 ${width} ${height}`,\n xmlns: SVG_NS,\n overflow: 'visible',\n });\n svg.style.height = `${height}px`;\n svg.setAttribute('role', layout.a11y.role);\n svg.setAttribute('aria-label', layout.a11y.altText);\n\n // Classes: oc-chart oc-sankey, plus oc-animate if animated\n const animate = animation?.enabled;\n const classes = animate ? 'oc-chart oc-sankey oc-animate' : 'oc-chart oc-sankey';\n svg.setAttribute('class', classes);\n\n // Set animation CSS custom properties when enabled\n if (animation?.enabled) {\n const totalMarks = layout.nodes.length + layout.links.length;\n const stagger = clampStaggerDelay(animation.staggerDelay, totalMarks);\n svg.style.setProperty('--oc-animation-duration', `${animation.duration}ms`);\n svg.style.setProperty('--oc-animation-stagger', `${stagger}ms`);\n svg.style.setProperty('--oc-annotation-delay', `${animation.annotationDelay}ms`);\n const easeVar = EASE_VAR_MAP[animation.ease] || EASE_VAR_MAP.smooth;\n svg.style.setProperty('--oc-animation-ease', easeVar);\n }\n\n // Background\n const bg = createSVGElement('rect');\n bg.setAttribute('class', 'oc-background');\n setAttrs(bg, {\n x: 0,\n y: 0,\n width,\n height,\n fill: layout.theme.colors.background,\n });\n svg.appendChild(bg);\n\n // Defs: gradient definitions for links\n const nodePositions = buildNodePositionMap(layout.nodes);\n const defs = createSVGElement('defs');\n renderGradientDefs(defs, layout.links, nodePositions);\n svg.appendChild(defs);\n\n // Links (behind nodes)\n renderLinks(svg, layout.links, nodePositions, animation);\n\n // Nodes\n renderNodes(svg, layout.nodes, animation);\n\n // Labels\n renderLabels(svg, layout.nodes);\n\n // Legend\n renderLegend(svg, layout.legend);\n\n // Chrome (title, subtitle, source, byline, footer) renders on top\n renderChrome(svg, layout);\n\n // Brand\n if (layout.watermark) {\n renderBrand(svg, layout);\n }\n\n return svg;\n}\n","/**\n * Table keyboard navigation: arrow-key cell navigation, Enter to sort,\n * Escape to clear search, and aria-activedescendant management.\n *\n * Designed to be wired up by table-mount.ts after render. Returns a\n * cleanup function to remove listeners on re-render or destroy.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface KeyboardNavOptions {\n /** The wrapper element containing the whole table UI. */\n wrapper: HTMLElement;\n /** Callback to trigger sort on a column. */\n onSort: (columnKey: string) => void;\n /** Callback to clear search and return focus to the table body. */\n onClearSearch: () => void;\n /** Callback to announce text to screen readers via the live region. */\n onAnnounce: (message: string) => void;\n}\n\ninterface CellPosition {\n row: number;\n col: number;\n}\n\n// ---------------------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------------------\n\n/**\n * Attach keyboard navigation to a rendered table.\n *\n * @returns A cleanup function that removes all event listeners.\n */\nexport function attachKeyboardNav(options: KeyboardNavOptions): () => void {\n const { wrapper, onSort, onClearSearch, onAnnounce } = options;\n\n let focusedCell: CellPosition = { row: -1, col: 0 };\n\n const table = wrapper.querySelector('table');\n if (!table) return () => {};\n\n const tbody = table.querySelector('tbody');\n const thead = table.querySelector('thead');\n if (!tbody || !thead) return () => {};\n\n // Make tbody focusable\n tbody.setAttribute('tabindex', '0');\n\n function getRows(): HTMLTableRowElement[] {\n if (!tbody) return [];\n return Array.from(tbody.querySelectorAll('tr'));\n }\n\n function getHeaderCells(): HTMLTableCellElement[] {\n if (!thead) return [];\n const headerRow = thead.querySelector('tr');\n if (!headerRow) return [];\n return Array.from(headerRow.querySelectorAll('th'));\n }\n\n function getCellsInRow(tr: HTMLTableRowElement): HTMLTableCellElement[] {\n return Array.from(tr.querySelectorAll('td'));\n }\n\n function getColCount(): number {\n const rows = getRows();\n if (rows.length === 0) return getHeaderCells().length;\n return getCellsInRow(rows[0]).length;\n }\n\n function clearFocusHighlight(): void {\n const prev = wrapper.querySelector('.oc-table-cell-focus');\n if (prev) {\n prev.classList.remove('oc-table-cell-focus');\n prev.removeAttribute('id');\n }\n }\n\n function setFocusedCell(row: number, col: number): void {\n clearFocusHighlight();\n const rows = getRows();\n const colCount = getColCount();\n\n // Clamp values\n if (rows.length === 0) return;\n row = Math.max(0, Math.min(row, rows.length - 1));\n col = Math.max(0, Math.min(col, colCount - 1));\n\n focusedCell = { row, col };\n\n // Highlight the cell\n const tr = rows[row];\n if (!tr) return;\n const cells = getCellsInRow(tr);\n const cell = cells[col];\n if (!cell) return;\n\n const cellId = `oc-cell-${row}-${col}`;\n cell.id = cellId;\n cell.classList.add('oc-table-cell-focus');\n cell.setAttribute('data-row', String(row));\n cell.setAttribute('data-col', String(col));\n\n // Set aria-activedescendant on tbody\n if (tbody) {\n tbody.setAttribute('aria-activedescendant', cellId);\n }\n\n // Scroll cell into view if needed\n cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n\n function handleTbodyFocus(): void {\n // When tbody receives focus, highlight the first cell (or restore last)\n if (focusedCell.row < 0) {\n setFocusedCell(0, 0);\n } else {\n setFocusedCell(focusedCell.row, focusedCell.col);\n }\n }\n\n function handleTbodyKeydown(e: KeyboardEvent): void {\n const rows = getRows();\n if (rows.length === 0) return;\n\n const colCount = getColCount();\n const { row, col } = focusedCell;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (row < rows.length - 1) {\n setFocusedCell(row + 1, col);\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (row > 0) {\n setFocusedCell(row - 1, col);\n } else {\n // Move focus to the header\n focusHeaderCell(col);\n }\n break;\n case 'ArrowRight':\n e.preventDefault();\n if (col < colCount - 1) {\n setFocusedCell(row, col + 1);\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (col > 0) {\n setFocusedCell(row, col - 1);\n }\n break;\n case 'Home':\n e.preventDefault();\n setFocusedCell(row, 0);\n break;\n case 'End':\n e.preventDefault();\n setFocusedCell(row, colCount - 1);\n break;\n }\n }\n\n // Header cell keyboard handling\n function focusHeaderCell(col: number): void {\n const headers = getHeaderCells();\n if (col >= 0 && col < headers.length) {\n clearFocusHighlight();\n headers[col].focus();\n }\n }\n\n function handleHeaderKeydown(e: KeyboardEvent): void {\n const th = e.currentTarget as HTMLTableCellElement;\n const headers = getHeaderCells();\n const colIndex = headers.indexOf(th);\n if (colIndex < 0) return;\n\n switch (e.key) {\n case 'ArrowRight':\n e.preventDefault();\n if (colIndex < headers.length - 1) {\n headers[colIndex + 1].focus();\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (colIndex > 0) {\n headers[colIndex - 1].focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n // Move focus to first body row at this column\n if (tbody) {\n tbody.focus();\n setFocusedCell(0, colIndex);\n }\n break;\n case 'Enter':\n case ' ': {\n e.preventDefault();\n const sortColumn = th.getAttribute('data-column');\n const sortBtn = th.querySelector('[data-sort-column]');\n if (sortColumn && sortBtn) {\n onSort(sortColumn);\n }\n break;\n }\n }\n }\n\n // Search escape handling\n const searchInput = wrapper.querySelector('.oc-table-search input') as HTMLInputElement | null;\n\n function handleSearchKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClearSearch();\n // Return focus to tbody\n if (tbody) {\n tbody.focus();\n onAnnounce('Search cleared');\n }\n }\n }\n\n // Wire up event listeners\n tbody.addEventListener('focus', handleTbodyFocus);\n tbody.addEventListener('keydown', handleTbodyKeydown as EventListener);\n\n // Make header cells focusable and wire keyboard\n const headerCells = getHeaderCells();\n for (const th of headerCells) {\n th.setAttribute('tabindex', '0');\n th.addEventListener('keydown', handleHeaderKeydown as EventListener);\n }\n\n if (searchInput) {\n searchInput.addEventListener('keydown', handleSearchKeydown as EventListener);\n }\n\n // Cleanup\n return () => {\n tbody.removeEventListener('focus', handleTbodyFocus);\n tbody.removeEventListener('keydown', handleTbodyKeydown as EventListener);\n\n for (const th of headerCells) {\n th.removeEventListener('keydown', handleHeaderKeydown as EventListener);\n }\n\n if (searchInput) {\n searchInput.removeEventListener('keydown', handleSearchKeydown as EventListener);\n }\n\n clearFocusHighlight();\n };\n}\n","/**\n * Table mount API: the main entry point for vanilla JS table usage.\n *\n * createTable() takes a container, spec, and options, compiles the table,\n * renders it as HTML, sets up responsive resizing, sort/search/pagination\n * interactivity, and returns a TableInstance with update/resize/export/destroy.\n *\n * Supports both controlled and uncontrolled modes:\n * - Uncontrolled (default): manages sort/search/page internally\n * - Controlled: reads state from externalState, fires onStateChange\n */\n\nimport type {\n CompileTableOptions,\n DarkMode,\n SortState,\n TableLayout,\n TableSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { getBreakpoint } from '@opendata-ai/openchart-core';\nimport { compileTable } from '@opendata-ai/openchart-engine';\nimport { setupTableAnimationCleanup } from './animation';\nimport { observeResize } from './resize-observer';\nimport { attachKeyboardNav } from './table-keyboard';\nimport { renderTable } from './table-renderer';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TableState {\n sort: SortState | null;\n search: string;\n page: number;\n}\n\nexport interface TableMountOptions {\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n onRowClick?: (row: Record<string, unknown>) => void;\n onStateChange?: (state: TableState) => void;\n externalState?: { sort?: SortState | null; search?: string; page?: number };\n}\n\nexport interface TableInstance {\n update(spec: TableSpec): void;\n resize(): void;\n export(format: 'csv'): string;\n getState(): TableState;\n setState(partial: Partial<TableState>): void;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// CSV export\n// ---------------------------------------------------------------------------\n\nfunction csvEscape(value: string): string {\n if (value.includes(',') || value.includes('\"') || value.includes('\\n') || value.includes('\\r')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Sort cycling\n// ---------------------------------------------------------------------------\n\n/**\n * Cycle sort state: clicking same column cycles none -> asc -> desc -> none.\n * Clicking a different column resets to asc.\n */\nfunction cycleSort(current: SortState | null, column: string): SortState | null {\n if (!current || current.column !== column) {\n return { column, direction: 'asc' };\n }\n if (current.direction === 'asc') {\n return { column, direction: 'desc' };\n }\n // desc -> none\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a table instance from a spec and mount it into a container.\n *\n * @param container - The DOM element to render into.\n * @param spec - The table spec.\n * @param options - Mount options.\n * @returns A TableInstance with update/resize/export/destroy methods.\n */\nexport function createTable(\n container: HTMLElement,\n spec: TableSpec,\n options?: TableMountOptions,\n): TableInstance {\n let currentSpec = spec;\n let currentLayout: TableLayout;\n let wrapperElement: HTMLElement | null = null;\n let disconnectResize: (() => void) | null = null;\n let cleanupKeyboard: (() => void) | null = null;\n let cleanupAnimations: (() => void) | null = null;\n let isFirstRender = true;\n let destroyed = false;\n\n // Internal state (used in uncontrolled mode)\n const internalState: TableState = {\n sort: null,\n search: '',\n page: 0,\n };\n\n // Debounce timers\n let searchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n let resizeDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const isControlled = options?.externalState !== undefined;\n\n function getState(): TableState {\n if (isControlled && options?.externalState) {\n return {\n sort: options.externalState.sort ?? null,\n search: options.externalState.search ?? '',\n page: options.externalState.page ?? 0,\n };\n }\n return { ...internalState };\n }\n\n function updateState(partial: Partial<TableState>): void {\n if (isControlled) {\n // In controlled mode, notify parent\n const current = getState();\n const next: TableState = {\n sort: partial.sort !== undefined ? partial.sort : current.sort,\n search: partial.search !== undefined ? partial.search : current.search,\n page: partial.page !== undefined ? partial.page : current.page,\n };\n options?.onStateChange?.(next);\n } else {\n // In uncontrolled mode, update internal state\n if (partial.sort !== undefined) internalState.sort = partial.sort;\n if (partial.search !== undefined) internalState.search = partial.search;\n if (partial.page !== undefined) internalState.page = partial.page;\n options?.onStateChange?.({ ...internalState });\n }\n }\n\n function compile(): TableLayout {\n const state = getState();\n const darkMode = resolveDarkMode(options?.darkMode);\n const { width } = getContainerDimensions();\n\n const compileOpts: CompileTableOptions = {\n width,\n height: 600,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n sort: state.sort ?? undefined,\n search: state.search || undefined,\n page: state.page,\n };\n\n return compileTable(currentSpec, compileOpts);\n }\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n /**\n * Announce a message to screen readers via the live region.\n */\n function announce(message: string): void {\n if (!wrapperElement) return;\n const liveRegion = wrapperElement.querySelector('.oc-table-live-region');\n if (liveRegion) {\n liveRegion.textContent = message;\n }\n }\n\n /**\n * Apply responsive breakpoint class based on container width.\n * Only auto-adds compact mode at small sizes. Never removes compact\n * if the spec explicitly requests it (layout.compact === true).\n */\n function applyBreakpointClass(): void {\n if (!wrapperElement) return;\n const { width } = getContainerDimensions();\n const bp = getBreakpoint(width);\n\n if (bp === 'compact' || bp === 'medium') {\n wrapperElement.classList.add('oc-table--compact');\n } else if (!currentLayout?.compact) {\n // Only remove compact if the spec didn't explicitly request it\n wrapperElement.classList.remove('oc-table--compact');\n }\n }\n\n function render(): void {\n if (destroyed) return;\n\n try {\n // Cancel any in-flight animations before re-rendering\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n\n // Clean up previous keyboard nav\n if (cleanupKeyboard) {\n cleanupKeyboard();\n cleanupKeyboard = null;\n }\n\n // Clean up previous render\n if (wrapperElement?.parentNode) {\n wrapperElement.parentNode.removeChild(wrapperElement);\n wrapperElement = null;\n }\n\n currentLayout = compile();\n const shouldAnimate = isFirstRender && !!currentLayout.animation?.enabled;\n wrapperElement = renderTable(currentLayout, container, { animate: shouldAnimate });\n\n // Set up animation cleanup on first animated render\n if (shouldAnimate && wrapperElement) {\n cleanupAnimations = setupTableAnimationCleanup(wrapperElement);\n }\n if (isFirstRender) {\n isFirstRender = false;\n }\n\n // Apply dark mode class\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Apply responsive breakpoint\n applyBreakpointClass();\n\n // Add clickable class if onRowClick is provided\n if (options?.onRowClick) {\n wrapperElement.classList.add('oc-table--clickable');\n }\n\n // Wire up event handlers\n wireEvents();\n\n // Wire up keyboard navigation\n if (wrapperElement) {\n cleanupKeyboard = attachKeyboardNav({\n wrapper: wrapperElement,\n onSort: (columnKey: string) => {\n const state = getState();\n const newSort = cycleSort(state.sort, columnKey);\n updateState({ sort: newSort, page: 0 });\n\n // Announce sort change\n if (newSort) {\n const dir = newSort.direction === 'asc' ? 'ascending' : 'descending';\n announce(`Sorted by ${columnKey} ${dir}`);\n } else {\n announce('Sort cleared');\n }\n\n if (!isControlled) {\n rerender();\n }\n },\n onClearSearch: () => {\n updateState({ search: '', page: 0 });\n if (!isControlled) {\n rerender();\n }\n },\n onAnnounce: announce,\n });\n }\n } catch (err) {\n console.error('[viz] Table render failed:', err);\n }\n }\n\n function wireEvents(): void {\n if (!wrapperElement) return;\n\n // Sort click handlers on thead buttons\n const sortBtns = wrapperElement.querySelectorAll('[data-sort-column]');\n for (const btn of sortBtns) {\n btn.addEventListener('click', handleSortClick);\n }\n\n // Search input\n const searchInput = wrapperElement.querySelector(\n '.oc-table-search input',\n ) as HTMLInputElement | null;\n if (searchInput) {\n searchInput.addEventListener('input', handleSearchInput);\n }\n\n // Pagination buttons\n const pageButtons = wrapperElement.querySelectorAll('[data-page-action]');\n for (const btn of pageButtons) {\n btn.addEventListener('click', handlePageClick);\n }\n\n // Row click\n if (options?.onRowClick) {\n const rows = wrapperElement.querySelectorAll('tbody tr');\n for (const row of rows) {\n row.addEventListener('click', handleRowClick);\n }\n }\n }\n\n function handleSortClick(e: Event): void {\n const btn = e.currentTarget as HTMLElement;\n const column = btn.getAttribute('data-sort-column');\n if (!column) return;\n\n const state = getState();\n const newSort = cycleSort(state.sort, column);\n\n updateState({ sort: newSort, page: 0 });\n\n // Announce sort change for screen readers\n if (newSort) {\n const dir = newSort.direction === 'asc' ? 'ascending' : 'descending';\n announce(`Sorted by ${column} ${dir}`);\n } else {\n announce('Sort cleared');\n }\n\n if (!isControlled) {\n rerender();\n }\n }\n\n function handleSearchInput(e: Event): void {\n const input = e.target as HTMLInputElement;\n const query = input.value;\n\n if (searchDebounceTimer !== null) {\n clearTimeout(searchDebounceTimer);\n }\n\n searchDebounceTimer = setTimeout(() => {\n searchDebounceTimer = null;\n updateState({ search: query, page: 0 });\n\n if (!isControlled) {\n rerender();\n // Announce search result count\n const rowCount = currentLayout?.rows?.length ?? 0;\n if (query) {\n announce(`${rowCount} result${rowCount !== 1 ? 's' : ''} found`);\n }\n }\n }, 200);\n }\n\n function handlePageClick(e: Event): void {\n const btn = e.currentTarget as HTMLElement;\n const action = btn.getAttribute('data-page-action');\n const state = getState();\n\n if (action === 'prev' && state.page > 0) {\n updateState({ page: state.page - 1 });\n } else if (action === 'next') {\n updateState({ page: state.page + 1 });\n }\n\n if (!isControlled) {\n rerender();\n }\n }\n\n function handleRowClick(e: Event): void {\n const tr = e.currentTarget as HTMLElement;\n const rowId = tr.getAttribute('data-row-id');\n if (!rowId || !currentLayout) return;\n\n const row = currentLayout.rows.find((r) => r.id === rowId);\n if (row) {\n options?.onRowClick?.(row.data);\n }\n }\n\n /**\n * Re-render the table, preserving search input focus across the DOM rebuild.\n */\n function rerender(): void {\n if (destroyed) return;\n\n // Capture current search input state before re-render\n const searchInput = wrapperElement?.querySelector(\n '.oc-table-search input',\n ) as HTMLInputElement | null;\n const hadFocus = searchInput && document.activeElement === searchInput;\n const selectionStart = searchInput?.selectionStart ?? 0;\n const selectionEnd = searchInput?.selectionEnd ?? 0;\n\n render();\n\n // Restore search focus after re-render\n if (hadFocus) {\n const newInput = wrapperElement?.querySelector(\n '.oc-table-search input',\n ) as HTMLInputElement | null;\n if (newInput) {\n newInput.focus();\n newInput.setSelectionRange(selectionStart, selectionEnd);\n }\n }\n }\n\n function update(newSpec: TableSpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n render();\n }\n\n function resize(): void {\n if (destroyed) return;\n if (cleanupAnimations) return; // Skip resize during entrance animation\n render();\n }\n\n function doExport(format: 'csv'): string {\n if (format !== 'csv') {\n throw new Error(`Unsupported export format: ${format}`);\n }\n\n // Export all filtered/sorted data (not just current page)\n // Re-compile without pagination\n const state = getState();\n const darkMode = resolveDarkMode(options?.darkMode);\n const { width } = getContainerDimensions();\n\n const fullLayout = compileTable(currentSpec, {\n width,\n height: 600,\n theme: options?.theme,\n darkMode,\n sort: state.sort ?? undefined,\n search: state.search || undefined,\n // No page/pageSize: get all rows\n });\n\n const headers = fullLayout.columns.map((c) => c.label);\n const csvRows = [headers.map(csvEscape).join(',')];\n\n for (const row of fullLayout.rows) {\n const values = row.cells.map((cell) => csvEscape(cell.formattedValue));\n csvRows.push(values.join(','));\n }\n\n return csvRows.join('\\n');\n }\n\n function setState(partial: Partial<TableState>): void {\n if (destroyed) return;\n\n if (partial.sort !== undefined) internalState.sort = partial.sort;\n if (partial.search !== undefined) internalState.search = partial.search;\n if (partial.page !== undefined) internalState.page = partial.page;\n\n render();\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n if (cleanupKeyboard) {\n cleanupKeyboard();\n cleanupKeyboard = null;\n }\n if (searchDebounceTimer !== null) {\n clearTimeout(searchDebounceTimer);\n searchDebounceTimer = null;\n }\n if (resizeDebounceTimer !== null) {\n clearTimeout(resizeDebounceTimer);\n resizeDebounceTimer = null;\n }\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n if (wrapperElement?.parentNode) {\n wrapperElement.parentNode.removeChild(wrapperElement);\n wrapperElement = null;\n }\n container.classList.remove('oc-dark');\n }\n\n // Initial render\n render();\n\n // Set up responsive resize with breakpoint detection\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n if (resizeDebounceTimer !== null) {\n clearTimeout(resizeDebounceTimer);\n }\n resizeDebounceTimer = setTimeout(() => {\n resizeDebounceTimer = null;\n // Update breakpoint class without full re-render when possible\n applyBreakpointClass();\n resize();\n }, 100);\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n getState,\n setState,\n destroy,\n };\n}\n","/**\n * Table renderer: produces semantic HTML from a TableLayout.\n *\n * renderTable() creates the full DOM structure: chrome, search bar,\n * scrollable table with sticky column support, pagination, and footer.\n * The returned element replaces or appends to the given container.\n */\n\nimport type { ResolvedColumn, TableLayout, TableRow } from '@opendata-ai/openchart-core';\nimport { BRAND_FONT_SIZE } from '@opendata-ai/openchart-core';\nimport { clampStaggerDelay } from '@opendata-ai/openchart-engine';\nimport { renderCell } from './renderers/table-cells';\n\n/** Options for renderTable(). */\nexport interface TableRenderOptions {\n /** Whether to apply entrance animation on this render. */\n animate?: boolean;\n}\n\n/** CSS easing preset map for animation custom properties. */\nconst EASE_VAR_MAP: Record<string, string> = {\n smooth: 'var(--oc-ease-smooth)',\n snappy: 'var(--oc-ease-snappy)',\n};\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst BRAND_URL = 'https://tryopendata.ai';\n\n// ---------------------------------------------------------------------------\n// Chrome rendering\n// ---------------------------------------------------------------------------\n\n/** Create chrome (title/subtitle or source/footer) block. */\nfunction renderChromeBlock(\n layout: TableLayout,\n position: 'header' | 'footer',\n): HTMLDivElement | null {\n const chrome = layout.chrome;\n\n if (position === 'header') {\n if (!chrome.title && !chrome.subtitle) return null;\n\n const div = document.createElement('div');\n div.className = 'oc-chrome';\n\n if (chrome.title) {\n const h = document.createElement('div');\n h.className = 'oc-table-title';\n h.textContent = chrome.title.text;\n div.appendChild(h);\n }\n if (chrome.subtitle) {\n const sub = document.createElement('div');\n sub.className = 'oc-table-subtitle';\n sub.textContent = chrome.subtitle.text;\n div.appendChild(sub);\n }\n\n return div;\n }\n\n // Footer position\n if (!chrome.source && !chrome.footer) return null;\n\n const div = document.createElement('div');\n div.className = 'oc-chrome oc-chrome-footer';\n\n if (chrome.source) {\n const src = document.createElement('div');\n src.className = 'oc-table-source';\n src.textContent = chrome.source.text;\n div.appendChild(src);\n }\n if (chrome.footer) {\n const foot = document.createElement('div');\n foot.className = 'oc-table-footer-text';\n foot.textContent = chrome.footer.text;\n div.appendChild(foot);\n }\n\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Table head\n// ---------------------------------------------------------------------------\n\nfunction renderThead(\n columns: ResolvedColumn[],\n sort: TableLayout['sort'],\n): HTMLTableSectionElement {\n const thead = document.createElement('thead');\n const tr = document.createElement('tr');\n tr.setAttribute('role', 'row');\n\n for (const col of columns) {\n const th = document.createElement('th');\n th.setAttribute('scope', 'col');\n th.setAttribute('role', 'columnheader');\n th.style.textAlign = col.align;\n th.style.width = `${col.width}px`;\n\n // Sort state: use 'ascending'/'descending' per WAI-ARIA spec\n let ariaSortValue: string = 'none';\n if (sort && sort.column === col.key) {\n ariaSortValue = sort.direction === 'asc' ? 'ascending' : 'descending';\n }\n th.setAttribute('aria-sort', ariaSortValue);\n th.setAttribute('data-column', col.key);\n\n // Label\n const labelSpan = document.createTextNode(col.label);\n th.appendChild(labelSpan);\n\n // Sort button\n if (col.sortable) {\n const btn = document.createElement('button');\n btn.className = 'oc-table-sort-btn';\n btn.setAttribute('aria-label', `Sort by ${col.label}`);\n btn.setAttribute('data-sort-column', col.key);\n btn.type = 'button';\n th.appendChild(btn);\n }\n\n tr.appendChild(th);\n }\n\n thead.appendChild(tr);\n return thead;\n}\n\n// ---------------------------------------------------------------------------\n// Table body\n// ---------------------------------------------------------------------------\n\nfunction renderTbody(rows: TableRow[], columns: ResolvedColumn[]): HTMLTableSectionElement {\n const tbody = document.createElement('tbody');\n\n for (let r = 0; r < rows.length; r++) {\n const row = rows[r];\n const tr = document.createElement('tr');\n tr.setAttribute('role', 'row');\n tr.setAttribute('data-row-id', row.id);\n tr.style.setProperty('--oc-row-index', String(r));\n\n for (let c = 0; c < columns.length; c++) {\n const cell = row.cells[c];\n if (!cell) continue;\n\n const td = renderCell(cell);\n td.setAttribute('role', 'gridcell');\n td.style.textAlign = columns[c].align;\n tr.appendChild(td);\n }\n\n tbody.appendChild(tr);\n }\n\n return tbody;\n}\n\n// ---------------------------------------------------------------------------\n// Search bar\n// ---------------------------------------------------------------------------\n\nfunction renderSearchBar(layout: TableLayout): HTMLDivElement | null {\n if (!layout.search.enabled) return null;\n\n const div = document.createElement('div');\n div.className = 'oc-table-search';\n\n const input = document.createElement('input');\n input.type = 'search';\n input.placeholder = layout.search.placeholder;\n input.setAttribute('aria-label', 'Search table');\n input.value = layout.search.query;\n\n div.appendChild(input);\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\nfunction renderPagination(layout: TableLayout): HTMLDivElement | null {\n if (!layout.pagination) return null;\n\n const { page, pageSize, totalRows, totalPages } = layout.pagination;\n\n const div = document.createElement('div');\n div.className = 'oc-table-pagination';\n\n const info = document.createElement('span');\n info.className = 'oc-table-pagination-info';\n\n if (totalRows === 0) {\n info.textContent = 'No results';\n } else {\n const start = page * pageSize + 1;\n const end = Math.min((page + 1) * pageSize, totalRows);\n info.textContent = `Showing ${start}-${end} of ${totalRows}`;\n }\n\n div.appendChild(info);\n\n const btnGroup = document.createElement('span');\n btnGroup.className = 'oc-table-pagination-btns';\n\n const prevBtn = document.createElement('button');\n prevBtn.setAttribute('aria-label', 'Previous page');\n prevBtn.setAttribute('data-page-action', 'prev');\n prevBtn.textContent = 'Prev';\n prevBtn.disabled = page <= 0;\n btnGroup.appendChild(prevBtn);\n\n const nextBtn = document.createElement('button');\n nextBtn.setAttribute('aria-label', 'Next page');\n nextBtn.setAttribute('data-page-action', 'next');\n nextBtn.textContent = 'Next';\n nextBtn.disabled = page >= totalPages - 1;\n btnGroup.appendChild(nextBtn);\n\n div.appendChild(btnGroup);\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Empty state\n// ---------------------------------------------------------------------------\n\nfunction renderEmptyState(message: string): HTMLDivElement {\n const div = document.createElement('div');\n div.className = 'oc-table-empty';\n div.setAttribute('aria-live', 'polite');\n div.textContent = message;\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Main render\n// ---------------------------------------------------------------------------\n\n/**\n * Render a TableLayout into a full DOM structure.\n *\n * @param layout - The compiled table layout.\n * @param container - The container element to render into.\n * @returns The wrapper element that was created.\n */\nexport function renderTable(\n layout: TableLayout,\n container: HTMLElement,\n opts?: TableRenderOptions,\n): HTMLElement {\n const wrapper = document.createElement('div');\n wrapper.className = 'oc-table-wrapper';\n\n // Apply theme colors as CSS custom properties so table CSS picks them up.\n // Without this, dark-background themes show invisible text since the\n // CSS defaults (--oc-text etc.) are light-mode values.\n const { theme, chrome } = layout;\n if (theme) {\n const s = wrapper.style;\n s.setProperty('--oc-bg', theme.colors.background);\n s.setProperty('--oc-text', theme.colors.text);\n s.setProperty('--oc-text-secondary', theme.colors.axis ?? theme.colors.text);\n s.setProperty('--oc-text-muted', theme.colors.axis ?? theme.colors.text);\n s.setProperty('--oc-gridline', theme.colors.gridline);\n s.setProperty('--oc-border', theme.colors.gridline);\n s.setProperty('--oc-font-family', theme.fonts.family);\n s.fontFamily = theme.fonts.family;\n }\n\n // Set computed chrome CSS custom properties so chrome elements pick up\n // theme-resolved values via CSS fallbacks (e.g. --oc-title-computed-size).\n {\n const s = wrapper.style;\n if (chrome.title) {\n s.setProperty('--oc-title-computed-size', `${chrome.title.style.fontSize}px`);\n s.setProperty('--oc-title-computed-weight', String(chrome.title.style.fontWeight));\n s.setProperty('--oc-title-computed-color', chrome.title.style.fill);\n }\n if (chrome.subtitle) {\n s.setProperty('--oc-subtitle-computed-size', `${chrome.subtitle.style.fontSize}px`);\n s.setProperty('--oc-subtitle-computed-weight', String(chrome.subtitle.style.fontWeight));\n s.setProperty('--oc-subtitle-computed-color', chrome.subtitle.style.fill);\n }\n if (chrome.source) {\n s.setProperty('--oc-source-computed-size', `${chrome.source.style.fontSize}px`);\n s.setProperty('--oc-source-computed-color', chrome.source.style.fill);\n }\n if (chrome.footer) {\n s.setProperty('--oc-footer-computed-size', `${chrome.footer.style.fontSize}px`);\n s.setProperty('--oc-footer-computed-color', chrome.footer.style.fill);\n }\n }\n\n // Apply class modifiers\n if (layout.compact) {\n wrapper.classList.add('oc-table--compact');\n }\n\n // Header chrome\n const headerChrome = renderChromeBlock(layout, 'header');\n if (headerChrome) {\n wrapper.appendChild(headerChrome);\n }\n\n // Search bar\n const searchBar = renderSearchBar(layout);\n if (searchBar) {\n wrapper.appendChild(searchBar);\n }\n\n // Handle empty data\n if (layout.rows.length === 0) {\n const message = layout.search.query ? 'No results found' : 'No data';\n wrapper.appendChild(renderEmptyState(message));\n } else {\n // Scroll container\n const scroll = document.createElement('div');\n scroll.className = 'oc-table-scroll';\n\n // Table\n const table = document.createElement('table');\n table.setAttribute('role', 'grid');\n table.setAttribute('aria-label', layout.a11y.caption);\n\n if (layout.stickyFirstColumn) {\n table.classList.add('oc-table--sticky');\n }\n\n // Caption (screen reader only – inline styles ensure hiding even without\n // the external stylesheet, e.g. CDN / esm.sh usage)\n const caption = document.createElement('caption');\n caption.className = 'oc-sr-only';\n caption.style.position = 'absolute';\n caption.style.width = '1px';\n caption.style.height = '1px';\n caption.style.padding = '0';\n caption.style.margin = '-1px';\n caption.style.overflow = 'hidden';\n caption.style.clipPath = 'inset(50%)';\n caption.style.whiteSpace = 'nowrap';\n caption.style.borderWidth = '0';\n caption.textContent = layout.a11y.summary;\n table.appendChild(caption);\n\n // Thead\n table.appendChild(renderThead(layout.columns, layout.sort));\n\n // Tbody\n table.appendChild(renderTbody(layout.rows, layout.columns));\n\n scroll.appendChild(table);\n wrapper.appendChild(scroll);\n }\n\n // Pagination\n const pagination = renderPagination(layout);\n if (pagination) {\n wrapper.appendChild(pagination);\n }\n\n // Footer chrome\n const footerChrome = renderChromeBlock(layout, 'footer');\n if (footerChrome) {\n wrapper.appendChild(footerChrome);\n }\n\n // Live region for screen reader announcements (sort changes, search results)\n const liveRegion = document.createElement('div');\n liveRegion.className = 'oc-table-live-region oc-sr-only';\n liveRegion.style.position = 'absolute';\n liveRegion.style.width = '1px';\n liveRegion.style.height = '1px';\n liveRegion.style.padding = '0';\n liveRegion.style.margin = '-1px';\n liveRegion.style.overflow = 'hidden';\n liveRegion.style.clipPath = 'inset(50%)';\n liveRegion.style.whiteSpace = 'nowrap';\n liveRegion.style.borderWidth = '0';\n liveRegion.setAttribute('aria-live', 'polite');\n liveRegion.setAttribute('aria-atomic', 'true');\n liveRegion.setAttribute('role', 'status');\n wrapper.appendChild(liveRegion);\n\n // Brand watermark\n if (layout.watermark) {\n const brandColor = theme ? theme.colors.axis : '#999999';\n const brand = document.createElement('div');\n brand.className = 'oc-table-ref';\n brand.style.cssText = 'text-align: right; padding: 4px 8px;';\n const brandLink = document.createElement('a');\n brandLink.href = BRAND_URL;\n brandLink.target = '_blank';\n brandLink.rel = 'noopener';\n brandLink.style.cssText = `font-size: ${BRAND_FONT_SIZE}px; font-weight: 600; color: ${brandColor}; opacity: 0.55; text-decoration: none; font-family: ${theme ? theme.fonts.family : 'sans-serif'};`;\n brandLink.textContent = 'tryOpenData.ai';\n brand.appendChild(brandLink);\n wrapper.appendChild(brand);\n }\n\n // Animation: stamp CSS custom properties and add oc-animate class BEFORE\n // DOM insertion to avoid a flash of final state.\n if (opts?.animate && layout.animation?.enabled) {\n const anim = layout.animation;\n const rowCount = layout.rows.length;\n const stagger = clampStaggerDelay(anim.staggerDelay, rowCount);\n const s = wrapper.style;\n s.setProperty('--oc-animation-duration', `${anim.duration}ms`);\n s.setProperty('--oc-animation-stagger', `${stagger}ms`);\n s.setProperty('--oc-animation-ease', EASE_VAR_MAP[anim.ease] || EASE_VAR_MAP.smooth);\n wrapper.classList.add('oc-animate');\n }\n\n container.appendChild(wrapper);\n return wrapper;\n}\n"],"mappings":"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","names":["x","y","c","x","y","cx","cy","x","y","c","x","y","x","y","x","y","x","y","x2","y2","x3","y3","x","y","x","y","x","x","y","x","y","m","i","c","now","x","y","x","y","node","strength","c","x2","x_default","x","y_default","y","c","x","y","x_default","y_default","x","y","x2","y2","x","y","renderChrome","renderLegend","now","x","y","timer","BRAND_FONT_SIZE","BRAND_MIN_WIDTH","SVG_NS","words","lines","current","index","c","BRAND_MIN_WIDTH","a","BRAND_FONT_SIZE","m","computePosition","resolveDarkMode","x","y","getScale","index","SVG_NS","cleanup","a","c","x","y","BRAND_FONT_SIZE","BRAND_MIN_WIDTH","estimateTextWidth","clampStaggerDelay","SVG_NS","XLINK_NS","BRAND_URL","EASE_VAR_MAP","createSVGElement","setAttrs","applyTextStyle","stampAnimationAttrs","wrapText","renderChromeElement","renderChrome","renderBrand","a","renderLegend","x2","resolveDarkMode","x","y","BRAND_FONT_SIZE","clampStaggerDelay","EASE_VAR_MAP","BRAND_URL","div","c","BRAND_FONT_SIZE","clampStaggerDelay","resolveDarkMode","csvEscape","c"]}
|
|
1
|
+
{"version":3,"sources":["../src/export.ts","../src/graph/simulation-worker-url.ts","../src/graph-mount.ts","../src/graph/canvas-renderer.ts","../src/graph/zoom.ts","../src/graph/interaction.ts","../src/graph/keyboard.ts","../src/graph/search.ts","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/center.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/add.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/cover.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/data.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/extent.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/quad.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/find.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/remove.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/root.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/size.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/visit.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/visitAfter.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/x.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/y.js","../../../node_modules/.bun/d3-quadtree@3.0.1/node_modules/d3-quadtree/src/quadtree.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/constant.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/jiggle.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/collide.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/link.js","../../../node_modules/.bun/d3-dispatch@3.0.1/node_modules/d3-dispatch/src/dispatch.js","../../../node_modules/.bun/d3-timer@3.0.1/node_modules/d3-timer/src/timer.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/lcg.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/simulation.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/manyBody.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/x.js","../../../node_modules/.bun/d3-force@3.0.0/node_modules/d3-force/src/y.js","../src/graph/simulation.ts","../src/graph/spatial-index.ts","../src/resize-observer.ts","../src/tooltip.ts","../src/mount.ts","../src/animation.ts","../src/svg-renderer.ts","../src/gradient-utils.ts","../src/text-edit-overlay.ts","../src/renderers/table-cells.ts","../src/sankey-mount.ts","../src/sankey-renderer.ts","../src/table-keyboard.ts","../src/table-mount.ts","../src/table-renderer.ts"],"sourcesContent":["/**\n * Export utilities: serialize charts to SVG, PNG, JPG, or CSV.\n *\n * - SVG: serializes the rendered DOM element via XMLSerializer\n * - SVG with fonts: async version that embeds @font-face data URIs\n * - PNG: renders SVG to canvas, then extracts as Blob\n * - JPG: same as PNG but with JPEG compression and background fill\n * - CSV: converts a data array to comma-separated text\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SVGExportOptions {\n /** Embed fonts as base64 data URIs in the SVG. Defaults to true. */\n embedFonts?: boolean;\n}\n\nexport interface PNGExportOptions extends SVGExportOptions {\n /** DPI scaling factor. Defaults to 2 for retina-quality output. */\n dpi?: number;\n}\n\nexport interface JPGExportOptions extends PNGExportOptions {\n /** JPEG quality from 0 to 1. Defaults to 0.92. */\n quality?: number;\n}\n\ninterface FontFaceData {\n family: string;\n weight: string;\n style: string;\n base64: string;\n format: string;\n}\n\n// ---------------------------------------------------------------------------\n// Dimension parsing\n// ---------------------------------------------------------------------------\n\n/**\n * Extract dimensions from an SVG element, trying width/height attributes\n * first, then falling back to viewBox.\n */\nfunction getSVGDimensions(svg: SVGElement): { width: number; height: number } {\n const w = parseFloat(svg.getAttribute('width') || '');\n const h = parseFloat(svg.getAttribute('height') || '');\n if (w && h) return { width: w, height: h };\n\n const vb = svg.getAttribute('viewBox');\n if (vb) {\n const parts = vb.split(/[\\s,]+/).map(Number);\n if (parts.length >= 4 && parts[2] && parts[3]) {\n return { width: parts[2], height: parts[3] };\n }\n }\n\n return { width: 600, height: 400 };\n}\n\n/**\n * Ensure an SVG string has explicit width/height attributes.\n *\n * When an SVG only has a viewBox (no width/height), browsers loading it as\n * an Image blob may use 300x150 as the intrinsic size instead of the viewBox\n * dimensions. This causes clipping at non-1x DPI scaling. Injecting explicit\n * width/height into the root <svg> tag fixes the intrinsic size.\n */\nfunction ensureSVGDimensions(svgString: string, width: number, height: number): string {\n // If the <svg> already has a width attribute, leave it alone\n if (/^<svg[^>]*\\swidth\\s*=/.test(svgString)) return svgString;\n // Inject width and height right after <svg\n return svgString.replace(/^(<svg)/, `$1 width=\"${width}\" height=\"${height}\"`);\n}\n\n// ---------------------------------------------------------------------------\n// Font embedding\n// ---------------------------------------------------------------------------\n\n/**\n * Collect unique font-family + font-weight combos from all <text> elements.\n */\nfunction collectUsedFonts(svgElement: SVGElement): Map<string, Set<string>> {\n const fonts = new Map<string, Set<string>>();\n const textElements = svgElement.querySelectorAll('text');\n\n for (const el of textElements) {\n const family = el.getAttribute('font-family');\n const weight = el.getAttribute('font-weight') || '400';\n if (family) {\n // Take the first font in the stack (e.g., \"Inter, sans-serif\" → \"Inter\")\n const primary = family.split(',')[0].trim().replace(/[\"']/g, '');\n if (!fonts.has(primary)) fonts.set(primary, new Set());\n fonts.get(primary)!.add(String(weight));\n }\n }\n\n return fonts;\n}\n\n/**\n * Find @font-face rules in document stylesheets that match the requested fonts.\n * Returns the src URLs for .woff2 files.\n */\nfunction findFontFaceRules(\n usedFonts: Map<string, Set<string>>,\n): Array<{ family: string; weight: string; style: string; url: string; format: string }> {\n const results: Array<{\n family: string;\n weight: string;\n style: string;\n url: string;\n format: string;\n }> = [];\n\n try {\n for (const sheet of document.styleSheets) {\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n // Cross-origin stylesheet, skip\n continue;\n }\n\n for (const rule of rules) {\n if (!(rule instanceof CSSFontFaceRule)) continue;\n\n const familyRaw = rule.style.getPropertyValue('font-family').replace(/[\"']/g, '').trim();\n const weight = rule.style.getPropertyValue('font-weight') || '400';\n const style = rule.style.getPropertyValue('font-style') || 'normal';\n const src = rule.style.getPropertyValue('src');\n\n const weights = usedFonts.get(familyRaw);\n if (!weights) continue;\n\n // Check if this weight is used (handle ranges like \"100 900\")\n const weightMatch = weights.has(weight) || weight.includes(' ');\n if (!weightMatch) continue;\n\n // Extract woff2 URL from src descriptor\n const woff2Match = src.match(/url\\([\"']?([^\"')]+\\.woff2[^\"')]*?)[\"']?\\)/);\n if (woff2Match) {\n results.push({\n family: familyRaw,\n weight,\n style,\n url: woff2Match[1],\n format: 'woff2',\n });\n }\n }\n }\n } catch {\n // Stylesheet access failed entirely, return empty\n }\n\n return results;\n}\n\n/**\n * Fetch font files and convert to base64 data URIs.\n */\nasync function fetchFontsAsBase64(\n fontRules: Array<{ family: string; weight: string; style: string; url: string; format: string }>,\n): Promise<FontFaceData[]> {\n const results: FontFaceData[] = [];\n\n const fetches = fontRules.map(async (rule) => {\n try {\n const response = await fetch(rule.url);\n if (!response.ok) return;\n const buffer = await response.arrayBuffer();\n const base64 = arrayBufferToBase64(buffer);\n results.push({\n family: rule.family,\n weight: rule.weight,\n style: rule.style,\n base64,\n format: rule.format,\n });\n } catch {\n // Font fetch failed (CORS, network, etc.) - skip this font\n }\n });\n\n await Promise.all(fetches);\n return results;\n}\n\nfunction arrayBufferToBase64(buffer: ArrayBuffer): string {\n let binary = '';\n const bytes = new Uint8Array(buffer);\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Inject @font-face rules with base64 data URIs into the SVG's <defs>.\n */\nfunction injectFontsIntoSVG(svgElement: SVGElement, fonts: FontFaceData[]): void {\n if (fonts.length === 0) return;\n\n const cssRules = fonts\n .map(\n (f) =>\n `@font-face { font-family: '${f.family}'; font-weight: ${f.weight}; font-style: ${f.style}; src: url(data:font/${f.format};base64,${f.base64}) format('${f.format}'); }`,\n )\n .join('\\n');\n\n const ns = 'http://www.w3.org/2000/svg';\n let defs = svgElement.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS(ns, 'defs');\n svgElement.insertBefore(defs, svgElement.firstChild);\n }\n\n const styleEl = document.createElementNS(ns, 'style');\n styleEl.textContent = cssRules;\n defs.insertBefore(styleEl, defs.firstChild);\n}\n\n/**\n * Embed fonts into an SVG element by finding matching @font-face rules\n * in the page's stylesheets, fetching the font files, and injecting\n * them as base64 data URIs.\n *\n * Modifies the SVG element in place. Call this before serialization.\n * If font fetching fails for any font, that font is silently skipped\n * and the export proceeds with system font fallback for that face.\n */\nasync function embedFonts(svgElement: SVGElement): Promise<void> {\n const usedFonts = collectUsedFonts(svgElement);\n if (usedFonts.size === 0) return;\n\n const fontRules = findFontFaceRules(usedFonts);\n if (fontRules.length === 0) return;\n\n const fontData = await fetchFontsAsBase64(fontRules);\n injectFontsIntoSVG(svgElement, fontData);\n}\n\n// ---------------------------------------------------------------------------\n// SVG background color\n// ---------------------------------------------------------------------------\n\n/**\n * Read the chart's background color from its first rect element.\n */\nfunction getSVGBackgroundColor(svgElement: SVGElement): string {\n const firstRect = svgElement.querySelector('rect');\n return firstRect?.getAttribute('fill') || '#ffffff';\n}\n\n// ---------------------------------------------------------------------------\n// SVG export\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize an SVG element to an XML string.\n *\n * @param svgElement - The rendered SVG element to serialize.\n * @returns The SVG markup as a string.\n */\nexport function exportSVG(svgElement: SVGElement): string {\n const serializer = new XMLSerializer();\n return serializer.serializeToString(svgElement);\n}\n\n/**\n * Serialize an SVG element with embedded fonts to an XML string.\n *\n * Collects font-family declarations from the SVG's text elements,\n * finds matching @font-face rules in the page's stylesheets, fetches\n * the font files, and embeds them as base64 data URIs. The resulting\n * SVG is self-contained and renders correctly without external fonts.\n *\n * @param svgElement - The rendered SVG element to serialize.\n * @param options - Export options.\n * @returns A Promise resolving to the SVG markup as a string.\n */\nexport async function exportSVGWithFonts(\n svgElement: SVGElement,\n options?: SVGExportOptions,\n): Promise<string> {\n const shouldEmbed = options?.embedFonts ?? true;\n if (shouldEmbed) {\n await embedFonts(svgElement);\n }\n return exportSVG(svgElement);\n}\n\n// ---------------------------------------------------------------------------\n// Raster export (PNG / JPG)\n// ---------------------------------------------------------------------------\n\n/**\n * Render an SVG element to a PNG Blob via a canvas.\n *\n * Embeds fonts by default so the exported image matches on-screen rendering.\n * Set `embedFonts: false` to skip font embedding for faster exports.\n *\n * @param svgElement - The rendered SVG element.\n * @param options - Optional DPI scaling and font embedding.\n * @returns A Promise resolving to the PNG Blob.\n */\nexport async function exportPNG(svgElement: SVGElement, options?: PNGExportOptions): Promise<Blob> {\n const dpi = options?.dpi ?? 2;\n const shouldEmbed = options?.embedFonts ?? true;\n\n if (shouldEmbed) {\n await embedFonts(svgElement);\n }\n\n const { width, height } = getSVGDimensions(svgElement);\n\n // Ensure the SVG has explicit width/height attributes so that when loaded\n // as a standalone Image blob the browser knows the intrinsic size. Without\n // these, browsers may default to 300x150 or use heuristics that break at\n // non-1x DPI scaling.\n const svgString = ensureSVGDimensions(exportSVG(svgElement), width, height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width * dpi;\n canvas.height = height * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas 2D context not available');\n }\n\n ctx.scale(dpi, dpi);\n\n const img = new Image();\n const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<Blob>((resolve, reject) => {\n img.onload = () => {\n ctx.drawImage(img, 0, 0, width, height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob((result) => {\n if (result) {\n resolve(result);\n } else {\n reject(new Error('Canvas toBlob returned null'));\n }\n }, 'image/png');\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load SVG as image'));\n };\n\n img.src = url;\n });\n}\n\n/**\n * Render an SVG element to a JPEG Blob via a canvas.\n *\n * Same pipeline as exportPNG but outputs JPEG with configurable quality.\n * The canvas is filled with the chart's background color before drawing\n * to avoid transparent backgrounds rendering as black in JPEG format.\n *\n * @param svgElement - The rendered SVG element.\n * @param options - Optional DPI scaling, JPEG quality, and font embedding.\n * @returns A Promise resolving to the JPEG Blob.\n */\nexport async function exportJPG(svgElement: SVGElement, options?: JPGExportOptions): Promise<Blob> {\n const dpi = options?.dpi ?? 2;\n const quality = options?.quality ?? 0.92;\n const shouldEmbed = options?.embedFonts ?? true;\n\n if (shouldEmbed) {\n await embedFonts(svgElement);\n }\n\n const { width, height } = getSVGDimensions(svgElement);\n const svgString = ensureSVGDimensions(exportSVG(svgElement), width, height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width * dpi;\n canvas.height = height * dpi;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas 2D context not available');\n }\n\n // Fill with the chart's actual background color (not hardcoded white)\n ctx.fillStyle = getSVGBackgroundColor(svgElement);\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n\n ctx.scale(dpi, dpi);\n\n const img = new Image();\n const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<Blob>((resolve, reject) => {\n img.onload = () => {\n ctx.drawImage(img, 0, 0, width, height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(\n (result) => {\n if (result) {\n resolve(result);\n } else {\n reject(new Error('Canvas toBlob returned null'));\n }\n },\n 'image/jpeg',\n quality,\n );\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Failed to load SVG as image'));\n };\n\n img.src = url;\n });\n}\n\n// ---------------------------------------------------------------------------\n// CSV export\n// ---------------------------------------------------------------------------\n\n/**\n * Convert an array of data objects to a CSV string.\n *\n * Uses the keys from the first row as column headers.\n * Values are quoted if they contain commas, quotes, or newlines.\n *\n * @param data - Array of row objects.\n * @returns CSV-formatted string.\n */\nexport function exportCSV(data: Record<string, unknown>[]): string {\n if (data.length === 0) return '';\n\n const headers = Object.keys(data[0]);\n const rows = [headers.map(csvEscape).join(',')];\n\n for (const row of data) {\n const values = headers.map((h) => csvEscape(String(row[h] ?? '')));\n rows.push(values.join(','));\n }\n\n return rows.join('\\n');\n}\n\nfunction csvEscape(value: string): string {\n if (value.includes(',') || value.includes('\"') || value.includes('\\n') || value.includes('\\r')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n","/**\n * Creates a Web Worker running the force simulation.\n *\n * References the built .js file via `new URL` + `import.meta.url`.\n * The consuming app's bundler resolves the worker path at build time.\n *\n * Note: SimulationManager handles .js/.ts fallback internally. This\n * helper is exported for consumers who want to manage the worker directly.\n */\nexport function createSimulationWorker(): Worker {\n return new Worker(new URL('./simulation-worker.js', import.meta.url), { type: 'module' });\n}\n","/**\n * Graph mount API: the main entry point for vanilla JS graph usage.\n *\n * createGraph() takes a container, GraphSpec, and options, compiles the graph,\n * creates a force simulation, canvas renderer, spatial index, interaction\n * manager, and search manager, then runs an animation loop driven by\n * simulation ticks. Returns a GraphInstance with update/search/zoom/destroy.\n */\n\nimport type { CompileOptions, DarkMode, GraphSpec, ThemeConfig } from '@opendata-ai/openchart-core';\nimport type {\n CompiledGraphEdge,\n CompiledGraphNode,\n GraphCompilation,\n} from '@opendata-ai/openchart-engine';\nimport { compileGraph } from '@opendata-ai/openchart-engine';\n\nimport { GraphCanvasRenderer } from './graph/canvas-renderer';\nimport { GraphInteractionManager } from './graph/interaction';\nimport { attachGraphKeyboardNav } from './graph/keyboard';\nimport { GraphSearchManager } from './graph/search';\nimport { SimulationManager } from './graph/simulation';\nimport { SpatialIndex } from './graph/spatial-index';\nimport type { GraphRenderState, PositionedEdge, PositionedNode } from './graph/types';\nimport type { SimEdge, SimNode } from './graph/worker-protocol';\nimport { ZoomTransform } from './graph/zoom';\nimport { observeResize } from './resize-observer';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface GraphMountOptions {\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Show the built-in tooltip on node/edge hover. Defaults to true. */\n tooltip?: boolean;\n /** Show the built-in legend. Defaults to true. */\n legend?: boolean;\n onNodeClick?: (node: Record<string, unknown>) => void;\n onNodeDoubleClick?: (node: Record<string, unknown>) => void;\n onNodeHover?: (node: Record<string, unknown> | null) => void;\n onEdgeHover?: (edge: Record<string, unknown> | null) => void;\n onSelectionChange?: (nodeIds: string[]) => void;\n}\n\nexport interface GraphInstance {\n update(spec: GraphSpec): void;\n /** Re-compile encoding/legend/chrome without restarting the simulation. Preserves node positions. */\n updateVisuals(spec: GraphSpec): void;\n search(query: string): void;\n clearSearch(): void;\n zoomToFit(): void;\n zoomToNode(nodeId: string): void;\n selectNode(nodeId: string): void;\n getSelectedNodes(): string[];\n resize(): void;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a graph instance from a spec and mount it into a container.\n *\n * @param container - The DOM element to render into.\n * @param spec - The graph spec.\n * @param options - Mount options.\n * @returns A GraphInstance with update/search/zoom/destroy methods.\n */\nexport function createGraph(\n container: HTMLElement,\n spec: GraphSpec,\n options?: GraphMountOptions,\n): GraphInstance {\n let currentSpec = spec;\n let compilation: GraphCompilation;\n let destroyed = false;\n\n // DOM elements\n let wrapper: HTMLElement | null = null;\n let canvas: HTMLCanvasElement | null = null;\n let chromeEl: HTMLElement | null = null;\n let legendEl: HTMLElement | null = null;\n\n // Subsystems\n let renderer: GraphCanvasRenderer | null = null;\n let simulation: SimulationManager | null = null;\n const spatialIndex = new SpatialIndex();\n let interactionManager: GraphInteractionManager | null = null;\n const searchManager = new GraphSearchManager();\n let tooltipManager: TooltipManager | null = null;\n let cleanupKeyboard: (() => void) | null = null;\n let disconnectResize: (() => void) | null = null;\n\n // State\n let positionedNodes: PositionedNode[] = [];\n let positionedEdges: PositionedEdge[] = [];\n let adjacencyMap = new Map<string, Set<string>>();\n let nodeDataMap = new Map<string, Record<string, unknown>>();\n let edgeDataMap = new Map<string, Record<string, unknown>>();\n let hoveredNodeId: string | null = null;\n let hoveredEdgeId: string | null = null;\n let selectedNodeIds = new Set<string>();\n let animFrameId: number | null = null;\n let needsRender = false;\n let isGesturing = false;\n let gestureTimeout: ReturnType<typeof setTimeout> | null = null;\n let lastEdgeHitTime = 0;\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n function markGesture(): void {\n isGesturing = true;\n if (gestureTimeout !== null) clearTimeout(gestureTimeout);\n gestureTimeout = setTimeout(() => {\n isGesturing = false;\n gestureTimeout = null;\n needsRender = true;\n scheduleRender();\n }, 150);\n }\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n function compile(): GraphCompilation {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n };\n\n return compileGraph(currentSpec, compileOpts);\n }\n\n function buildDataMaps(): void {\n nodeDataMap = new Map(compilation.nodes.map((n) => [n.id, n.data ?? {}]));\n edgeDataMap = new Map(compilation.edges.map((e) => [`${e.source}->${e.target}`, e.data ?? {}]));\n }\n\n function buildAdjacencyMap(edges: CompiledGraphEdge[]): Map<string, Set<string>> {\n const map = new Map<string, Set<string>>();\n for (const edge of edges) {\n if (!map.has(edge.source)) map.set(edge.source, new Set());\n if (!map.has(edge.target)) map.set(edge.target, new Set());\n map.get(edge.source)!.add(edge.target);\n map.get(edge.target)!.add(edge.source);\n }\n return map;\n }\n\n function toSimNodes(nodes: CompiledGraphNode[]): SimNode[] {\n return nodes.map((n) => ({\n id: n.id,\n radius: n.radius,\n community: n.community,\n }));\n }\n\n function toSimEdges(edges: CompiledGraphEdge[]): SimEdge[] {\n return edges.map((e) => ({\n source: e.source,\n target: e.target,\n }));\n }\n\n /**\n * Look up a node's data from the compilation by id.\n * Falls back to an empty object if not found.\n */\n function nodeDataById(nodeId: string): Record<string, unknown> {\n return nodeDataMap.get(nodeId) ?? {};\n }\n\n /**\n * Point-to-line-segment distance for edge hit testing.\n * Returns the shortest distance from point (px, py) to the segment (ax, ay)-(bx, by).\n */\n function pointToSegmentDist(\n px: number,\n py: number,\n ax: number,\n ay: number,\n bx: number,\n by: number,\n ): number {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n if (lenSq === 0) return Math.hypot(px - ax, py - ay);\n const t = Math.max(0, Math.min(1, ((px - ax) * dx + (py - ay) * dy) / lenSq));\n return Math.hypot(px - (ax + t * dx), py - (ay + t * dy));\n }\n\n /**\n * Find the edge closest to a graph-space point, within a threshold.\n * Returns an edge key \"source->target\" or null.\n */\n function hitTestEdge(graphX: number, graphY: number, threshold: number): string | null {\n let bestDist = threshold;\n let bestEdgeId: string | null = null;\n\n for (const edge of positionedEdges) {\n const dist = pointToSegmentDist(\n graphX,\n graphY,\n edge.sourceX,\n edge.sourceY,\n edge.targetX,\n edge.targetY,\n );\n if (dist < bestDist) {\n bestDist = dist;\n bestEdgeId = `${edge.source}->${edge.target}`;\n }\n }\n\n return bestEdgeId;\n }\n\n /**\n * Look up edge data by edge id (\"source->target\").\n */\n function edgeDataById(edgeId: string): Record<string, unknown> | null {\n return edgeDataMap.get(edgeId) ?? null;\n }\n\n // ---------------------------------------------------------------------------\n // DOM creation\n // ---------------------------------------------------------------------------\n\n function createDOM(): void {\n const { width, height } = getContainerDimensions();\n const isDark = resolveDarkMode(options?.darkMode);\n\n // Wrapper\n wrapper = document.createElement('div');\n wrapper.className = isDark ? 'oc-graph-wrapper oc-dark' : 'oc-graph-wrapper';\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Apply theme colors as CSS custom properties so chrome HTML picks them up.\n // Without this, consumer-supplied theme.colors.text only affects canvas-drawn\n // labels but not the HTML title/subtitle which read from --oc-text.\n const resolvedTheme = compilation.theme;\n if (resolvedTheme) {\n const s = wrapper.style;\n s.setProperty('--oc-bg', resolvedTheme.colors.background);\n s.setProperty('--oc-text', resolvedTheme.colors.text);\n s.setProperty('--oc-text-secondary', resolvedTheme.colors.axis ?? resolvedTheme.colors.text);\n s.setProperty('--oc-font-family', resolvedTheme.fonts.family);\n s.fontFamily = resolvedTheme.fonts.family;\n }\n\n // Chrome (title, subtitle)\n chromeEl = document.createElement('div');\n chromeEl.className = 'oc-graph-chrome';\n renderChrome();\n wrapper.appendChild(chromeEl);\n\n // Canvas\n canvas = document.createElement('canvas');\n canvas.className = 'oc-graph-canvas';\n canvas.setAttribute('role', 'img');\n if (compilation.a11y?.altText) {\n canvas.setAttribute('aria-label', compilation.a11y.altText);\n }\n wrapper.appendChild(canvas);\n\n // Legend\n if (options?.legend !== false) {\n legendEl = document.createElement('div');\n legendEl.className = 'oc-graph-legend';\n renderLegend();\n wrapper.appendChild(legendEl);\n }\n\n container.appendChild(wrapper);\n\n // Canvas uses the full container height; chrome overlays on top\n const canvasHeight = Math.max(height, 200);\n renderer = new GraphCanvasRenderer(canvas);\n renderer.resize(width, canvasHeight);\n }\n\n function renderChrome(): void {\n if (!chromeEl) return;\n let html = '';\n\n if (compilation.chrome.title) {\n html += `<h2 class=\"oc-title\">${escapeHtml(compilation.chrome.title.text)}</h2>`;\n }\n if (compilation.chrome.subtitle) {\n html += `<p class=\"oc-subtitle\">${escapeHtml(compilation.chrome.subtitle.text)}</p>`;\n }\n\n chromeEl.innerHTML = html;\n\n // Hide chrome if empty\n if (!html) {\n chromeEl.style.display = 'none';\n } else {\n chromeEl.style.display = '';\n }\n }\n\n function renderLegend(): void {\n if (!legendEl) return;\n\n const entries = compilation.legend.entries;\n if (entries.length === 0) {\n legendEl.style.display = 'none';\n return;\n }\n\n legendEl.style.display = '';\n let html = '';\n for (const entry of entries) {\n html += '<div class=\"oc-graph-legend-item\">';\n html += `<span class=\"oc-graph-legend-swatch\" style=\"background:${escapeHtml(entry.color)}\"></span>`;\n html += `<span>${escapeHtml(entry.label)}</span>`;\n html += '</div>';\n }\n legendEl.innerHTML = html;\n }\n\n // ---------------------------------------------------------------------------\n // Simulation and animation\n // ---------------------------------------------------------------------------\n\n function initSimulation(): void {\n const simNodes = toSimNodes(compilation.nodes);\n const simEdges = toSimEdges(compilation.edges);\n const config = compilation.simulationConfig;\n\n simulation = SimulationManager.create(simNodes, simEdges, {\n chargeStrength: config.chargeStrength,\n linkDistance: config.linkDistance,\n clustering: config.clustering,\n alphaDecay: config.alphaDecay,\n velocityDecay: config.velocityDecay,\n collisionRadius: config.collisionRadius,\n collisionPadding: config.collisionPadding,\n linkStrength: config.linkStrength,\n centerForce: config.centerForce,\n });\n\n let initialSettleDone = false;\n let initialFitDone = false;\n\n simulation.onTick((positions, _alpha) => {\n if (destroyed) return;\n\n // Build position lookup\n const posMap = new Map<string, { x: number; y: number }>();\n for (const p of positions) {\n posMap.set(p.id, { x: p.x, y: p.y });\n }\n\n // Build positioned nodes\n positionedNodes = compilation.nodes.map((node) => {\n const pos = posMap.get(node.id) ?? { x: 0, y: 0 };\n return { ...node, x: pos.x, y: pos.y };\n });\n\n // Build positioned edges\n positionedEdges = compilation.edges.map((edge) => {\n const src = posMap.get(edge.source) ?? { x: 0, y: 0 };\n const tgt = posMap.get(edge.target) ?? { x: 0, y: 0 };\n return {\n ...edge,\n sourceX: src.x,\n sourceY: src.y,\n targetX: tgt.x,\n targetY: tgt.y,\n };\n });\n\n // Rebuild spatial index\n spatialIndex.rebuild(positionedNodes);\n\n // Fit the viewport once on the first tick so the graph is visible and\n // centered immediately. After that, let the user interact freely while\n // the simulation continues settling in the background.\n if (!initialFitDone && positionedNodes.length > 0 && interactionManager) {\n initialFitDone = true;\n const { width: cw, height: ch } = getCanvasDimensions();\n const { transform: fitTransform } = ZoomTransform.fitBounds(positionedNodes, cw, ch);\n interactionManager.setTransform(fitTransform);\n }\n\n needsRender = true;\n scheduleRender();\n });\n\n simulation.onSettled(() => {\n if (initialSettleDone) return;\n initialSettleDone = true;\n });\n }\n\n function getCanvasDimensions(): { width: number; height: number } {\n if (!canvas) return { width: 600, height: 400 };\n const rect = canvas.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n function scheduleRender(): void {\n if (animFrameId !== null || destroyed) return;\n animFrameId = requestAnimationFrame(renderFrame);\n }\n\n function renderFrame(): void {\n animFrameId = null;\n if (destroyed || !renderer || !interactionManager) return;\n\n if (needsRender) {\n needsRender = false;\n\n const transform = interactionManager.getTransform();\n const state: GraphRenderState = {\n nodes: positionedNodes,\n edges: positionedEdges,\n transform: { x: transform.x, y: transform.y, k: transform.k },\n hoveredNodeId,\n hoveredEdgeId,\n selectedNodeIds,\n adjacencyMap,\n theme: compilation.theme,\n searchMatches: searchManager.getMatches(),\n isGesturing,\n watermark: compilation.watermark,\n };\n\n renderer.render(state);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Interaction wiring\n // ---------------------------------------------------------------------------\n\n function initInteraction(): void {\n if (!canvas) return;\n\n if (options?.tooltip !== false) {\n tooltipManager = createTooltipManager(wrapper!);\n }\n\n interactionManager = new GraphInteractionManager(canvas, spatialIndex, {\n onTransformChange(_transform) {\n markGesture();\n needsRender = true;\n scheduleRender();\n },\n onHoverChange(nodeId) {\n hoveredNodeId = nodeId;\n needsRender = true;\n scheduleRender();\n\n // Fire onNodeHover callback\n if (nodeId) {\n options?.onNodeHover?.(nodeDataById(nodeId));\n } else {\n options?.onNodeHover?.(null);\n }\n\n // Show or hide tooltip\n if (nodeId && tooltipManager) {\n // Clear edge hover when hovering a node\n if (hoveredEdgeId) {\n hoveredEdgeId = null;\n options?.onEdgeHover?.(null);\n }\n const content = compilation.tooltipDescriptors.get(nodeId);\n if (content) {\n const node = positionedNodes.find((n) => n.id === nodeId);\n if (node && interactionManager) {\n const screen = interactionManager.getTransform().graphToScreen(node.x, node.y);\n tooltipManager.show(content, screen.x, screen.y);\n }\n }\n } else if (!nodeId) {\n // Tooltip hiding handled in onBackgroundHover (edge may show tooltip)\n // If no edge hover happens, tooltip stays hidden\n tooltipManager?.hide();\n }\n },\n onBackgroundHover(graphX, graphY, screenX, screenY) {\n // Throttle edge hit testing to avoid O(n) scan on every mousemove\n const now = performance.now();\n if (now - lastEdgeHitTime < 32) {\n // When throttled, clear edge hover so hover-off transitions stay snappy\n if (hoveredEdgeId) {\n hoveredEdgeId = null;\n needsRender = true;\n scheduleRender();\n options?.onEdgeHover?.(null);\n tooltipManager?.hide();\n }\n return;\n }\n lastEdgeHitTime = now;\n\n // Edge hit testing: check proximity to edge line segments\n const transform = interactionManager?.getTransform();\n const threshold = 5 / (transform?.k ?? 1); // 5px in screen space\n const edgeId = hitTestEdge(graphX, graphY, threshold);\n\n if (edgeId !== hoveredEdgeId) {\n hoveredEdgeId = edgeId;\n needsRender = true;\n scheduleRender();\n\n if (edgeId) {\n const data = edgeDataById(edgeId);\n options?.onEdgeHover?.(data);\n\n // Show edge tooltip\n if (tooltipManager && data) {\n const fields = Object.entries(data)\n .filter(([key]) => key !== 'source' && key !== 'target')\n .filter(([, value]) => value != null)\n .map(([key, value]) => ({\n label: key,\n value: typeof value === 'number' ? value.toLocaleString() : String(value),\n }));\n\n const [source, target] = edgeId.split('->');\n tooltipManager.show({ title: `${source} → ${target}`, fields }, screenX, screenY);\n }\n } else {\n options?.onEdgeHover?.(null);\n tooltipManager?.hide();\n }\n }\n },\n onSelectionChange(nodeIds) {\n selectedNodeIds = new Set(nodeIds);\n needsRender = true;\n scheduleRender();\n options?.onSelectionChange?.(nodeIds);\n\n // Fire onNodeClick for the most recently added node\n if (nodeIds.length > 0) {\n const lastId = nodeIds[nodeIds.length - 1];\n options?.onNodeClick?.(nodeDataById(lastId));\n }\n },\n onNodeDragStart(nodeId) {\n // Pin at the node's current position to avoid visual snap to origin\n const node = positionedNodes.find((n) => n.id === nodeId);\n const x = node?.x ?? 0;\n const y = node?.y ?? 0;\n simulation?.pinNode(nodeId, x, y);\n canvas?.classList.add('oc-graph-canvas--dragging');\n },\n onNodeDrag(nodeId, x, y) {\n simulation?.dragNode(nodeId, x, y);\n },\n onNodeDragEnd(nodeId) {\n simulation?.unpinNode(nodeId);\n canvas?.classList.remove('oc-graph-canvas--dragging');\n },\n onDoubleClick(nodeId) {\n options?.onNodeDoubleClick?.(nodeDataById(nodeId));\n },\n });\n\n // Wire keyboard navigation\n cleanupKeyboard = attachGraphKeyboardNav({\n canvas,\n getNodes: () => positionedNodes,\n getSelectedIds: () => [...selectedNodeIds],\n getAdjacency: () => adjacencyMap,\n onSelect(nodeId) {\n selectedNodeIds = new Set([nodeId]);\n needsRender = true;\n scheduleRender();\n options?.onNodeClick?.(nodeDataById(nodeId));\n options?.onSelectionChange?.([nodeId]);\n },\n onDeselect() {\n selectedNodeIds.clear();\n needsRender = true;\n scheduleRender();\n options?.onSelectionChange?.([]);\n },\n onZoom(direction) {\n if (!interactionManager || !canvas) return;\n const t = interactionManager.getTransform();\n const { width: cw, height: ch } = getCanvasDimensions();\n const factor = direction === 'in' ? 1.2 : 0.8;\n const newK = t.k * factor;\n const newTransform = t.zoomAt(newK, cw / 2, ch / 2);\n interactionManager.setTransform(newTransform);\n needsRender = true;\n scheduleRender();\n },\n onFitAll() {\n zoomToFit();\n },\n });\n\n // Handle node clicks (from interaction manager selection change wiring above)\n // We catch clicks via the interaction manager's onSelectionChange callback\n }\n\n // ---------------------------------------------------------------------------\n // Public API methods\n // ---------------------------------------------------------------------------\n\n function search(query: string): void {\n if (destroyed) return;\n searchManager.search(query, positionedNodes);\n needsRender = true;\n scheduleRender();\n }\n\n function clearSearch(): void {\n if (destroyed) return;\n searchManager.clearSearch();\n needsRender = true;\n scheduleRender();\n }\n\n function zoomToFit(): void {\n if (destroyed || !interactionManager || positionedNodes.length === 0) return;\n const { width: cw, height: ch } = getCanvasDimensions();\n const { transform: fitTransform } = ZoomTransform.fitBounds(positionedNodes, cw, ch);\n interactionManager.setTransform(fitTransform);\n needsRender = true;\n scheduleRender();\n }\n\n function zoomToNode(nodeId: string): void {\n if (destroyed || !interactionManager || !canvas) return;\n const node = positionedNodes.find((n) => n.id === nodeId);\n if (!node) return;\n\n const { width: cw, height: ch } = getCanvasDimensions();\n // Zoom to 2x and center on node\n const k = 2;\n const tx = cw / 2 - node.x * k;\n const ty = ch / 2 - node.y * k;\n const newTransform = new ZoomTransform(tx, ty, k);\n interactionManager.setTransform(newTransform);\n needsRender = true;\n scheduleRender();\n }\n\n function selectNode(nodeId: string): void {\n if (destroyed) return;\n selectedNodeIds = new Set([nodeId]);\n needsRender = true;\n scheduleRender();\n options?.onSelectionChange?.([nodeId]);\n }\n\n function getSelectedNodes(): string[] {\n return [...selectedNodeIds];\n }\n\n function doResize(): void {\n if (destroyed || !canvas || !renderer || !wrapper) return;\n const { width, height } = getContainerDimensions();\n const canvasHeight = Math.max(height, 200);\n renderer.resize(width, canvasHeight);\n needsRender = true;\n scheduleRender();\n }\n\n function update(newSpec: GraphSpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n\n // Tear down old simulation + interaction\n teardownSubsystems();\n\n // Recompile\n compilation = compile();\n adjacencyMap = buildAdjacencyMap(compilation.edges);\n buildDataMaps();\n\n // Update DOM chrome/legend\n renderChrome();\n renderLegend();\n\n // Reinit\n initSimulation();\n initInteraction();\n\n // Reset state\n hoveredNodeId = null;\n hoveredEdgeId = null;\n selectedNodeIds = new Set();\n searchManager.clearSearch();\n }\n\n function updateVisuals(newSpec: GraphSpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n\n // Build a position lookup from current positioned nodes\n const posMap = new Map<string, { x: number; y: number }>();\n for (const node of positionedNodes) {\n posMap.set(node.id, { x: node.x, y: node.y });\n }\n\n // Recompile with new spec (encoding, chrome, nodeOverrides, etc.)\n compilation = compile();\n adjacencyMap = buildAdjacencyMap(compilation.edges);\n buildDataMaps();\n\n // Transfer positions to new compiled nodes\n positionedNodes = compilation.nodes.map((node) => {\n const pos = posMap.get(node.id) ?? { x: 0, y: 0 };\n return { ...node, x: pos.x, y: pos.y };\n });\n\n // Rebuild positioned edges from existing positions\n positionedEdges = compilation.edges.map((edge) => {\n const src = posMap.get(edge.source) ?? { x: 0, y: 0 };\n const tgt = posMap.get(edge.target) ?? { x: 0, y: 0 };\n return {\n ...edge,\n sourceX: src.x,\n sourceY: src.y,\n targetX: tgt.x,\n targetY: tgt.y,\n };\n });\n\n // Rebuild spatial index with updated visuals\n spatialIndex.rebuild(positionedNodes);\n\n // Update DOM chrome/legend\n renderChrome();\n renderLegend();\n\n // Re-render canvas without restarting simulation\n needsRender = true;\n scheduleRender();\n }\n\n function teardownSubsystems(): void {\n if (animFrameId !== null) {\n cancelAnimationFrame(animFrameId);\n animFrameId = null;\n }\n if (cleanupKeyboard) {\n cleanupKeyboard();\n cleanupKeyboard = null;\n }\n interactionManager?.destroy();\n interactionManager = null;\n simulation?.destroy();\n simulation = null;\n tooltipManager?.destroy();\n tooltipManager = null;\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n if (gestureTimeout !== null) {\n clearTimeout(gestureTimeout);\n gestureTimeout = null;\n }\n\n teardownSubsystems();\n\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n\n if (wrapper?.parentNode) {\n wrapper.parentNode.removeChild(wrapper);\n }\n wrapper = null;\n canvas = null;\n chromeEl = null;\n legendEl = null;\n renderer = null;\n\n container.classList.remove('oc-dark');\n }\n\n // ---------------------------------------------------------------------------\n // Initialize\n // ---------------------------------------------------------------------------\n\n try {\n compilation = compile();\n adjacencyMap = buildAdjacencyMap(compilation.edges);\n buildDataMaps();\n createDOM();\n initSimulation();\n initInteraction();\n } catch (err) {\n console.error('[viz] Graph mount failed:', err);\n // Return a no-op instance so callers don't crash\n return {\n update() {},\n updateVisuals() {},\n search() {},\n clearSearch() {},\n zoomToFit() {},\n zoomToNode() {},\n selectNode() {},\n getSelectedNodes: () => [],\n resize() {},\n destroy() {},\n };\n }\n\n // Responsive resize\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n doResize();\n });\n }\n\n return {\n update,\n updateVisuals,\n search,\n clearSearch,\n zoomToFit,\n zoomToNode,\n selectNode,\n getSelectedNodes,\n resize: doResize,\n destroy,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Util\n// ---------------------------------------------------------------------------\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n","/**\n * Canvas 2D renderer for force-directed graph visualization.\n *\n * Stateless renderer: receives a GraphRenderState each frame and draws it.\n * Handles DPR scaling, viewport culling, LOD labels, dark mode glow effects,\n * and batched drawing for performance at 10k+ nodes.\n *\n * Performance strategy:\n * - Edges batched by (stroke, strokeWidth, dash) key → one stroke() per group\n * - Nodes batched by fill color → one fill() per color group\n * - Node strokes batched by stroke color\n * - Labels and glow skipped during active pan/zoom gestures\n */\n\nimport { BRAND_FONT_SIZE, BRAND_MIN_WIDTH } from '@opendata-ai/openchart-core';\nimport type { GraphRenderState, PositionedEdge, PositionedNode } from './types';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst LABEL_FONT_MIN = 8;\nconst LABEL_FONT_MAX = 12;\nconst EDGE_ALPHA_DEFAULT = 0.35;\nconst EDGE_ALPHA_CONNECTED = 1.0;\nconst EDGE_ALPHA_DIMMED = 0.05;\nconst SEARCH_NON_MATCH_ALPHA = 0.15;\nconst GLOW_NODE_THRESHOLD = 2000;\nconst GLOW_RADIUS_MULTIPLIER = 1.3;\nconst GLOW_ALPHA = 0.15;\nconst CULL_MARGIN = 50;\nconst TWO_PI = Math.PI * 2;\n\n/** Minimum node radius in screen pixels. Keeps nodes visible when zoomed out. */\nconst MIN_SCREEN_RADIUS = 2.5;\n\n// ---------------------------------------------------------------------------\n// Helpers (exported for testing)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute label visibility threshold from zoom level.\n * At zoom 0.2 (zoomed out): threshold ~1.0 (only top ~5% visible).\n * At zoom 2.0+: threshold ~0.0 (all visible).\n */\nexport function labelThreshold(zoom: number): number {\n const t = Math.max(0, Math.min(1, (zoom - 0.2) / 1.8));\n return 1 - t;\n}\n\n/** Compute visible rect in graph coordinates from canvas size + transform. */\nexport function visibleRect(\n canvasWidth: number,\n canvasHeight: number,\n transform: { x: number; y: number; k: number },\n margin: number = CULL_MARGIN,\n): { minX: number; minY: number; maxX: number; maxY: number } {\n const { x, y, k } = transform;\n return {\n minX: (-x - margin) / k,\n minY: (-y - margin) / k,\n maxX: (canvasWidth - x + margin) / k,\n maxY: (canvasHeight - y + margin) / k,\n };\n}\n\n/** Check if a node falls within the visible rect. */\nfunction nodeInView(\n node: PositionedNode,\n rect: { minX: number; minY: number; maxX: number; maxY: number },\n): boolean {\n return (\n node.x + node.radius >= rect.minX &&\n node.x - node.radius <= rect.maxX &&\n node.y + node.radius >= rect.minY &&\n node.y - node.radius <= rect.maxY\n );\n}\n\n/** Check if an edge has at least one endpoint in view. */\nfunction edgeInView(\n edge: PositionedEdge,\n rect: { minX: number; minY: number; maxX: number; maxY: number },\n): boolean {\n return (\n (edge.sourceX >= rect.minX &&\n edge.sourceX <= rect.maxX &&\n edge.sourceY >= rect.minY &&\n edge.sourceY <= rect.maxY) ||\n (edge.targetX >= rect.minX &&\n edge.targetX <= rect.maxX &&\n edge.targetY >= rect.minY &&\n edge.targetY <= rect.maxY)\n );\n}\n\n// ---------------------------------------------------------------------------\n// Dash patterns for edge styles\n// ---------------------------------------------------------------------------\n\nconst DASH_PATTERNS: Record<string, number[]> = {\n solid: [],\n dashed: [6, 4],\n dotted: [2, 3],\n};\n\n// ---------------------------------------------------------------------------\n// GraphCanvasRenderer\n// ---------------------------------------------------------------------------\n\nexport class GraphCanvasRenderer {\n private canvas: HTMLCanvasElement;\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via this-destructuring\n private ctx: CanvasRenderingContext2D;\n private dpr: number;\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via this-destructuring\n private cssWidth = 0;\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: accessed via this-destructuring\n private cssHeight = 0;\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.ctx = canvas.getContext('2d')!;\n this.dpr = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n }\n\n /** Update canvas dimensions with DPR scaling. CSS size stays at css values. */\n resize(width: number, height: number): void {\n this.cssWidth = width;\n this.cssHeight = height;\n this.canvas.width = width * this.dpr;\n this.canvas.height = height * this.dpr;\n }\n\n /** Clear canvas and render the full graph state. */\n render(state: GraphRenderState): void {\n const { ctx, dpr, cssWidth, cssHeight } = this;\n const {\n nodes,\n edges,\n transform,\n hoveredNodeId,\n hoveredEdgeId,\n selectedNodeIds,\n adjacencyMap,\n theme,\n searchMatches,\n isGesturing,\n } = state;\n\n const hasActiveNode = hoveredNodeId !== null || selectedNodeIds.size > 0;\n const activeNodeIds = new Set<string>();\n if (hoveredNodeId) activeNodeIds.add(hoveredNodeId);\n for (const id of selectedNodeIds) activeNodeIds.add(id);\n\n // Collect all nodes connected to any active node\n const connectedNodeIds = new Set<string>();\n for (const id of activeNodeIds) {\n connectedNodeIds.add(id);\n const neighbors = adjacencyMap.get(id);\n if (neighbors) {\n for (const nid of neighbors) connectedNodeIds.add(nid);\n }\n }\n\n // Viewport culling\n const rect = visibleRect(cssWidth, cssHeight, transform);\n const visibleNodes = nodes.filter((n) => nodeInView(n, rect));\n const visibleEdges = edges.filter((e) => edgeInView(e, rect));\n\n const isDark = theme.isDark;\n const showGlow = isDark && !isGesturing && visibleNodes.length < GLOW_NODE_THRESHOLD;\n const threshold = labelThreshold(transform.k);\n // Minimum radius in graph coordinates so nodes stay visible when zoomed out\n const minRadius = MIN_SCREEN_RADIUS / transform.k;\n\n // -- Clear and apply transform --\n ctx.save();\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, cssWidth, cssHeight);\n\n // Fill background (skip if transparent to let page background show through)\n if (theme.colors.background !== 'transparent') {\n ctx.fillStyle = theme.colors.background;\n ctx.fillRect(0, 0, cssWidth, cssHeight);\n }\n\n ctx.translate(transform.x, transform.y);\n ctx.scale(transform.k, transform.k);\n\n // -- Draw edges (batched by style key) --\n this.drawEdgesBatched(\n ctx,\n visibleEdges,\n hasActiveNode,\n connectedNodeIds,\n isGesturing ? null : searchMatches,\n hoveredEdgeId,\n );\n\n // -- Draw nodes (batched by fill color) --\n this.drawNodesBatched(\n ctx,\n visibleNodes,\n hoveredNodeId,\n selectedNodeIds,\n isGesturing ? null : searchMatches,\n showGlow,\n theme,\n minRadius,\n );\n\n // -- Draw labels (skipped during gestures) --\n if (!isGesturing) {\n this.drawLabels(\n ctx,\n visibleNodes,\n threshold,\n hoveredNodeId,\n selectedNodeIds,\n searchMatches,\n transform.k,\n theme,\n );\n }\n\n ctx.restore();\n\n // Brand watermark in screen coordinates (unaffected by pan/zoom)\n if (state.watermark) {\n this.drawBrand(ctx, cssWidth, cssHeight, theme);\n }\n }\n\n // -------------------------------------------------------------------------\n // Brand rendering\n // -------------------------------------------------------------------------\n\n private drawBrand(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n theme: GraphRenderState['theme'],\n ): void {\n if (w < BRAND_MIN_WIDTH) return;\n const { dpr } = this;\n ctx.save();\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n const padding = theme.spacing.padding;\n const x = w - padding;\n const y = h - padding;\n ctx.font = `600 ${BRAND_FONT_SIZE}px ${theme.fonts.family}`;\n ctx.fillStyle = theme.colors.axis;\n ctx.globalAlpha = 0.55;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'alphabetic';\n ctx.fillText('tryOpenData.ai', x, y);\n ctx.restore();\n }\n\n // -------------------------------------------------------------------------\n // Batched edge drawing\n // -------------------------------------------------------------------------\n\n private drawEdgesBatched(\n ctx: CanvasRenderingContext2D,\n edges: PositionedEdge[],\n hasActiveNode: boolean,\n connectedNodeIds: Set<string>,\n searchMatches: Set<string> | null,\n hoveredEdgeId: string | null,\n ): void {\n // Classify edges by alpha level, then batch by visual style within each level\n const dimmedEdges: PositionedEdge[] = [];\n const defaultEdges: PositionedEdge[] = [];\n const connectedEdges: PositionedEdge[] = [];\n let hoveredEdge: PositionedEdge | null = null;\n\n for (const edge of edges) {\n const edgeId = `${edge.source}->${edge.target}`;\n if (edgeId === hoveredEdgeId) {\n hoveredEdge = edge;\n continue; // Draw hovered edge last, on top\n }\n\n const isConnected =\n hasActiveNode && connectedNodeIds.has(edge.source) && connectedNodeIds.has(edge.target);\n const isDimmed = hasActiveNode && !isConnected;\n\n if (isConnected) {\n connectedEdges.push(edge);\n } else if (isDimmed) {\n dimmedEdges.push(edge);\n } else {\n defaultEdges.push(edge);\n }\n }\n\n // Draw dimmed first, then default, then connected (on top)\n this.drawEdgeGroupBatched(ctx, dimmedEdges, EDGE_ALPHA_DIMMED, searchMatches);\n this.drawEdgeGroupBatched(ctx, defaultEdges, EDGE_ALPHA_DEFAULT, searchMatches);\n this.drawEdgeGroupBatched(ctx, connectedEdges, EDGE_ALPHA_CONNECTED, searchMatches);\n\n // Draw hovered edge on top with highlight\n if (hoveredEdge) {\n const dash = DASH_PATTERNS[hoveredEdge.style] ?? DASH_PATTERNS.solid;\n ctx.setLineDash(dash);\n ctx.strokeStyle = hoveredEdge.stroke;\n ctx.lineWidth = hoveredEdge.strokeWidth * 2;\n ctx.globalAlpha = EDGE_ALPHA_CONNECTED;\n ctx.beginPath();\n ctx.moveTo(hoveredEdge.sourceX, hoveredEdge.sourceY);\n ctx.lineTo(hoveredEdge.targetX, hoveredEdge.targetY);\n ctx.stroke();\n ctx.setLineDash([]);\n ctx.globalAlpha = 1;\n }\n }\n\n /**\n * Draw a group of edges at a given alpha, batched by (stroke, strokeWidth, style).\n * When search is inactive, all edges of the same style are drawn in a single path.\n * When search is active, edges split by search-match status for alpha dimming.\n */\n private drawEdgeGroupBatched(\n ctx: CanvasRenderingContext2D,\n edges: PositionedEdge[],\n alpha: number,\n searchMatches: Set<string> | null,\n ): void {\n if (edges.length === 0) return;\n\n // Group by visual key: stroke + strokeWidth + style\n const groups = new Map<string, PositionedEdge[]>();\n for (const edge of edges) {\n const key = `${edge.stroke}|${edge.strokeWidth}|${edge.style}`;\n let group = groups.get(key);\n if (!group) {\n group = [];\n groups.set(key, group);\n }\n group.push(edge);\n }\n\n for (const [, group] of groups) {\n const sample = group[0];\n const dash = DASH_PATTERNS[sample.style] ?? DASH_PATTERNS.solid;\n ctx.setLineDash(dash);\n ctx.strokeStyle = sample.stroke;\n ctx.lineWidth = sample.strokeWidth;\n\n if (!searchMatches) {\n // Fast path: single batched path for all edges in this group\n ctx.globalAlpha = alpha;\n ctx.beginPath();\n for (const edge of group) {\n ctx.moveTo(edge.sourceX, edge.sourceY);\n ctx.lineTo(edge.targetX, edge.targetY);\n }\n ctx.stroke();\n } else {\n // Search active: split into matched and non-matched batches\n ctx.globalAlpha = alpha;\n ctx.beginPath();\n let hasMatched = false;\n\n const nonMatchPath: PositionedEdge[] = [];\n\n for (const edge of group) {\n const srcMatch = searchMatches.has(edge.source);\n const tgtMatch = searchMatches.has(edge.target);\n if (srcMatch || tgtMatch) {\n ctx.moveTo(edge.sourceX, edge.sourceY);\n ctx.lineTo(edge.targetX, edge.targetY);\n hasMatched = true;\n } else {\n nonMatchPath.push(edge);\n }\n }\n if (hasMatched) ctx.stroke();\n\n // Draw non-matching edges dimmed\n if (nonMatchPath.length > 0) {\n ctx.globalAlpha = SEARCH_NON_MATCH_ALPHA * alpha;\n ctx.beginPath();\n for (const edge of nonMatchPath) {\n ctx.moveTo(edge.sourceX, edge.sourceY);\n ctx.lineTo(edge.targetX, edge.targetY);\n }\n ctx.stroke();\n }\n }\n }\n\n ctx.setLineDash([]);\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Batched node drawing\n // -------------------------------------------------------------------------\n\n private drawNodesBatched(\n ctx: CanvasRenderingContext2D,\n nodes: PositionedNode[],\n hoveredNodeId: string | null,\n selectedNodeIds: Set<string>,\n searchMatches: Set<string> | null,\n showGlow: boolean,\n theme: GraphRenderState['theme'],\n minRadius: number,\n ): void {\n // Separate special nodes (hovered/selected) from bulk nodes.\n // Special nodes need individual treatment; bulk nodes get batched by color.\n const bulkNodes: PositionedNode[] = [];\n const specialNodes: PositionedNode[] = [];\n\n for (const node of nodes) {\n if (node.id === hoveredNodeId || selectedNodeIds.has(node.id)) {\n specialNodes.push(node);\n } else {\n bulkNodes.push(node);\n }\n }\n\n // Helper: effective radius clamped to minimum screen size\n const r = (node: PositionedNode) => Math.max(node.radius, minRadius);\n\n // --- Glow pass (dark mode only, before fills) ---\n if (showGlow) {\n this.drawGlowBatched(ctx, bulkNodes, searchMatches, minRadius);\n }\n\n // --- Bulk fill pass: batch by fill color ---\n const fillGroups = new Map<string, PositionedNode[]>();\n for (const node of bulkNodes) {\n let group = fillGroups.get(node.fill);\n if (!group) {\n group = [];\n fillGroups.set(node.fill, group);\n }\n group.push(node);\n }\n\n if (!searchMatches) {\n // Fast path: no search dimming\n ctx.globalAlpha = 1;\n for (const [fill, group] of fillGroups) {\n ctx.fillStyle = fill;\n ctx.beginPath();\n for (const node of group) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.fill();\n }\n } else {\n // Search active: split each color group into matched/dimmed batches\n for (const [fill, group] of fillGroups) {\n ctx.fillStyle = fill;\n\n // Matched nodes\n ctx.globalAlpha = 1;\n ctx.beginPath();\n let hasMatched = false;\n const dimmedNodes: PositionedNode[] = [];\n\n for (const node of group) {\n if (searchMatches.has(node.id)) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n hasMatched = true;\n } else {\n dimmedNodes.push(node);\n }\n }\n if (hasMatched) ctx.fill();\n\n // Dimmed nodes\n if (dimmedNodes.length > 0) {\n ctx.globalAlpha = SEARCH_NON_MATCH_ALPHA;\n ctx.beginPath();\n for (const node of dimmedNodes) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.fill();\n }\n }\n }\n\n // --- Bulk stroke pass: batch by stroke color ---\n const strokeGroups = new Map<string, PositionedNode[]>();\n for (const node of bulkNodes) {\n const key = `${node.stroke}|${node.strokeWidth}`;\n let group = strokeGroups.get(key);\n if (!group) {\n group = [];\n strokeGroups.set(key, group);\n }\n group.push(node);\n }\n\n for (const [key, group] of strokeGroups) {\n const [stroke, widthStr] = key.split('|');\n ctx.strokeStyle = stroke;\n ctx.lineWidth = parseFloat(widthStr);\n\n if (!searchMatches) {\n ctx.globalAlpha = 1;\n ctx.beginPath();\n for (const node of group) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.stroke();\n } else {\n // Split matched/dimmed for strokes too\n ctx.globalAlpha = 1;\n ctx.beginPath();\n let hasMatched = false;\n const dimmedNodes: PositionedNode[] = [];\n\n for (const node of group) {\n if (searchMatches.has(node.id)) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n hasMatched = true;\n } else {\n dimmedNodes.push(node);\n }\n }\n if (hasMatched) ctx.stroke();\n\n if (dimmedNodes.length > 0) {\n ctx.globalAlpha = SEARCH_NON_MATCH_ALPHA;\n ctx.beginPath();\n for (const node of dimmedNodes) {\n const nr = r(node);\n ctx.moveTo(node.x + nr, node.y);\n ctx.arc(node.x, node.y, nr, 0, TWO_PI);\n }\n ctx.stroke();\n }\n }\n }\n\n // --- Special nodes (hovered/selected) drawn individually ---\n for (const node of specialNodes) {\n const isHovered = node.id === hoveredNodeId;\n const isSelected = selectedNodeIds.has(node.id);\n const dimmed = searchMatches !== null && !searchMatches.has(node.id);\n const baseRadius = Math.max(node.radius, minRadius);\n const radius = isHovered ? baseRadius * 1.15 : baseRadius;\n\n ctx.globalAlpha = dimmed ? SEARCH_NON_MATCH_ALPHA : 1;\n\n // Glow for special nodes\n if (showGlow && !dimmed) {\n ctx.beginPath();\n ctx.arc(node.x, node.y, radius * GLOW_RADIUS_MULTIPLIER, 0, TWO_PI);\n ctx.fillStyle = node.fill;\n ctx.globalAlpha = GLOW_ALPHA;\n ctx.fill();\n ctx.globalAlpha = dimmed ? SEARCH_NON_MATCH_ALPHA : 1;\n }\n\n // Fill\n ctx.beginPath();\n ctx.arc(node.x, node.y, radius, 0, TWO_PI);\n ctx.fillStyle = isHovered ? brighten(node.fill) : node.fill;\n ctx.fill();\n\n // Stroke\n ctx.strokeStyle = node.stroke;\n ctx.lineWidth = node.strokeWidth;\n ctx.stroke();\n\n // Selection ring\n if (isSelected) {\n ctx.beginPath();\n ctx.arc(node.x, node.y, radius + 3, 0, TWO_PI);\n ctx.strokeStyle = theme.colors.categorical[0] ?? '#3b82f6';\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n }\n\n ctx.globalAlpha = 1;\n }\n\n /** Batch glow circles by fill color. */\n private drawGlowBatched(\n ctx: CanvasRenderingContext2D,\n nodes: PositionedNode[],\n searchMatches: Set<string> | null,\n minRadius: number,\n ): void {\n const glowGroups = new Map<string, PositionedNode[]>();\n for (const node of nodes) {\n if (searchMatches && !searchMatches.has(node.id)) continue;\n let group = glowGroups.get(node.fill);\n if (!group) {\n group = [];\n glowGroups.set(node.fill, group);\n }\n group.push(node);\n }\n\n ctx.globalAlpha = GLOW_ALPHA;\n for (const [fill, group] of glowGroups) {\n ctx.fillStyle = fill;\n ctx.beginPath();\n for (const node of group) {\n const gr = Math.max(node.radius, minRadius) * GLOW_RADIUS_MULTIPLIER;\n ctx.moveTo(node.x + gr, node.y);\n ctx.arc(node.x, node.y, gr, 0, TWO_PI);\n }\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Labels (drawn individually, skipped during gestures)\n // -------------------------------------------------------------------------\n\n private drawLabels(\n ctx: CanvasRenderingContext2D,\n nodes: PositionedNode[],\n threshold: number,\n hoveredNodeId: string | null,\n selectedNodeIds: Set<string>,\n searchMatches: Set<string> | null,\n zoom: number,\n theme: GraphRenderState['theme'],\n ): void {\n // Font size inversely scaled by zoom, clamped to readable range\n const rawSize = 10 / zoom;\n const fontSize = Math.max(LABEL_FONT_MIN, Math.min(LABEL_FONT_MAX, rawSize));\n\n ctx.font = `${fontSize}px ${theme.fonts.family}`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'top';\n\n for (const node of nodes) {\n if (!node.label) continue;\n\n const isHovered = node.id === hoveredNodeId;\n const isSelected = selectedNodeIds.has(node.id);\n const forced = isHovered || isSelected;\n const dimmed = searchMatches !== null && !searchMatches.has(node.id);\n\n // LOD: skip labels below threshold unless forced\n if (!forced && node.labelPriority < threshold) continue;\n\n ctx.globalAlpha = dimmed ? SEARCH_NON_MATCH_ALPHA : 1;\n\n const labelY = node.y + node.radius + 3;\n\n // Halo for readability: stroke behind text in the background color\n // so labels stay legible over edges and other nodes.\n if (theme.colors.background !== 'transparent') {\n ctx.strokeStyle = theme.colors.background;\n } else {\n // Transparent bg: infer page background from text luminance.\n // Light text = dark page, dark text = light page.\n ctx.strokeStyle = isLightColor(theme.colors.text)\n ? 'rgba(0, 0, 0, 0.7)'\n : 'rgba(255, 255, 255, 0.85)';\n }\n ctx.lineWidth = 3;\n ctx.lineJoin = 'round';\n ctx.miterLimit = 2;\n ctx.strokeText(node.label, node.x, labelY);\n\n ctx.fillStyle = theme.colors.text;\n ctx.fillText(node.label, node.x, labelY);\n }\n\n ctx.globalAlpha = 1;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Color helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Brighten a hex/rgb color by ~20% for hover effect.\n * Quick and dirty approach: parse hex, lighten each channel.\n */\nfunction brighten(color: string): string {\n // Handle rgb(r,g,b) or rgb(r, g, b)\n const rgbMatch = color.match(/^rgb\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/);\n if (rgbMatch) {\n const r = Math.min(255, parseInt(rgbMatch[1], 10) + 40);\n const g = Math.min(255, parseInt(rgbMatch[2], 10) + 40);\n const b = Math.min(255, parseInt(rgbMatch[3], 10) + 40);\n return `rgb(${r},${g},${b})`;\n }\n\n // Handle hex colors (#rgb and #rrggbb)\n const hex = color.replace('#', '');\n const full =\n hex.length === 3\n ? hex\n .split('')\n .map((c) => c + c)\n .join('')\n : hex;\n\n if (full.length === 6) {\n const r = Math.min(255, parseInt(full.slice(0, 2), 16) + 40);\n const g = Math.min(255, parseInt(full.slice(2, 4), 16) + 40);\n const b = Math.min(255, parseInt(full.slice(4, 6), 16) + 40);\n return `rgb(${r},${g},${b})`;\n }\n\n return color;\n}\n\n/**\n * Returns true if a color is perceptually light (luminance > 0.5).\n * Used to pick a contrasting halo color for labels on transparent backgrounds.\n */\nfunction isLightColor(color: string): boolean {\n const hex = color.replace('#', '');\n const full =\n hex.length === 3\n ? hex\n .split('')\n .map((c) => c + c)\n .join('')\n : hex;\n if (full.length !== 6) return false;\n const r = parseInt(full.slice(0, 2), 16) / 255;\n const g = parseInt(full.slice(2, 4), 16) / 255;\n const b = parseInt(full.slice(4, 6), 16) / 255;\n const toLinear = (c: number) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);\n return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b) > 0.5;\n}\n","/**\n * Immutable zoom transform for graph pan/zoom.\n *\n * Provides coordinate conversion between screen space (canvas pixels)\n * and graph space (simulation coordinates). All mutations return new\n * instances rather than modifying in place.\n */\n\nimport type { PositionedNode } from './types';\n\nexport class ZoomTransform {\n constructor(\n readonly x: number,\n readonly y: number,\n readonly k: number,\n ) {}\n\n /** Convert screen coordinates to graph coordinates. */\n screenToGraph(sx: number, sy: number): { x: number; y: number } {\n return {\n x: (sx - this.x) / this.k,\n y: (sy - this.y) / this.k,\n };\n }\n\n /** Convert graph coordinates to screen coordinates. */\n graphToScreen(gx: number, gy: number): { x: number; y: number } {\n return {\n x: gx * this.k + this.x,\n y: gy * this.k + this.y,\n };\n }\n\n /**\n * Zoom to a target scale, keeping the given screen-space pivot\n * point fixed (content under the cursor stays under the cursor).\n */\n zoomAt(targetK: number, pivotX: number, pivotY: number): ZoomTransform {\n // The graph point under the pivot should remain at the same screen position.\n // Before: pivotX = gx * k + x => gx = (pivotX - x) / k\n // After: pivotX = gx * targetK + newX => newX = pivotX - gx * targetK\n const gx = (pivotX - this.x) / this.k;\n const gy = (pivotY - this.y) / this.k;\n return new ZoomTransform(pivotX - gx * targetK, pivotY - gy * targetK, targetK);\n }\n\n /** Pan by a screen-space delta. */\n pan(dx: number, dy: number): ZoomTransform {\n return new ZoomTransform(this.x + dx, this.y + dy, this.k);\n }\n\n /**\n * Compute a transform that fits all nodes within the given canvas\n * dimensions with the specified padding.\n *\n * Returns the transform and the ideal content height (in screen pixels)\n * so callers can shrink the canvas to eliminate dead space.\n */\n static fitBounds(\n nodes: PositionedNode[],\n canvasW: number,\n canvasH: number,\n padding: number = 40,\n ): { transform: ZoomTransform; contentHeight: number } {\n if (nodes.length === 0) {\n return { transform: ZoomTransform.identity(), contentHeight: canvasH };\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const n of nodes) {\n const r = n.radius;\n if (n.x - r < minX) minX = n.x - r;\n if (n.y - r < minY) minY = n.y - r;\n if (n.x + r > maxX) maxX = n.x + r;\n if (n.y + r > maxY) maxY = n.y + r;\n }\n\n let graphW = maxX - minX;\n let graphH = maxY - minY;\n\n if (graphW === 0 && graphH === 0) {\n // All nodes at the same point; just center\n return {\n transform: new ZoomTransform(canvasW / 2 - minX, canvasH / 2 - minY, 1),\n contentHeight: padding * 2,\n };\n }\n\n // When called early in the simulation (first tick), the bounding box\n // underestimates the final spread. Apply a spread multiplier based on\n // node count: larger graphs expand more as charge forces push nodes\n // apart over subsequent ticks. The sqrt scaling mirrors how d3-force\n // charge repulsion grows with node count.\n if (nodes.length > 50) {\n const spread = 1 + Math.sqrt(nodes.length) / 120;\n const cx = (minX + maxX) / 2;\n const cy = (minY + maxY) / 2;\n graphW *= spread;\n graphH *= spread;\n minX = cx - graphW / 2;\n maxX = cx + graphW / 2;\n minY = cy - graphH / 2;\n maxY = cy + graphH / 2;\n }\n\n const availW = canvasW - padding * 2;\n const availH = canvasH - padding * 2;\n // Cap at 1 so the graph never renders larger than its natural size\n const k = Math.min(1, availW / graphW, availH / graphH);\n\n // Center both axes so the graph sits in the middle of the viewport\n const cx = (minX + maxX) / 2;\n const cy = (minY + maxY) / 2;\n const tx = canvasW / 2 - cx * k;\n const ty = canvasH / 2 - cy * k;\n\n // Content height = scaled graph extent + top and bottom padding\n const contentHeight = graphH * k + padding * 2;\n\n return {\n transform: new ZoomTransform(tx, ty, k),\n contentHeight,\n };\n }\n\n /** Identity transform (no pan, no zoom). */\n static identity(): ZoomTransform {\n return new ZoomTransform(0, 0, 1);\n }\n}\n","/**\n * Graph interaction manager.\n *\n * Handles mouse/touch events on the canvas and translates them into\n * high-level graph interactions: pan, zoom, hover, select, drag nodes.\n * Uses the spatial index for hit testing and ZoomTransform for coordinate\n * conversion.\n */\n\nimport type { SpatialIndex } from './spatial-index';\nimport { ZoomTransform } from './zoom';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst ZOOM_MIN = 0.05;\nconst ZOOM_MAX = 15;\nconst ZOOM_STEP = -0.001;\nconst HIT_DISTANCE = 5;\n\n// ---------------------------------------------------------------------------\n// Callback interface\n// ---------------------------------------------------------------------------\n\nexport interface InteractionCallbacks {\n onTransformChange(transform: ZoomTransform): void;\n onHoverChange(nodeId: string | null): void;\n /** Called during mouse move when no node is hit, with graph-space coordinates for edge hit testing. */\n onBackgroundHover?(graphX: number, graphY: number, screenX: number, screenY: number): void;\n onSelectionChange(nodeIds: string[]): void;\n onNodeDragStart(nodeId: string): void;\n onNodeDrag(nodeId: string, x: number, y: number): void;\n onNodeDragEnd(nodeId: string): void;\n onDoubleClick(nodeId: string): void;\n}\n\n// ---------------------------------------------------------------------------\n// Internal state\n// ---------------------------------------------------------------------------\n\ninterface DragState {\n nodeId: string;\n started: boolean;\n}\n\ninterface PanState {\n startX: number;\n startY: number;\n}\n\n// ---------------------------------------------------------------------------\n// GraphInteractionManager\n// ---------------------------------------------------------------------------\n\nexport class GraphInteractionManager {\n private canvas: HTMLCanvasElement;\n private spatialIndex: SpatialIndex;\n private callbacks: InteractionCallbacks;\n private transform = ZoomTransform.identity();\n\n private dragState: DragState | null = null;\n private panState: PanState | null = null;\n private mousedownNodeId: string | null = null;\n private selectedIds: Set<string> = new Set();\n\n // Touch state\n private lastTouchDist: number | null = null;\n private lastTouchCenter: { x: number; y: number } | null = null;\n\n // Bound handlers for cleanup\n private boundWheel: (e: WheelEvent) => void;\n private boundMouseDown: (e: MouseEvent) => void;\n private boundMouseMove: (e: MouseEvent) => void;\n private boundMouseUp: (e: MouseEvent) => void;\n private boundDblClick: (e: MouseEvent) => void;\n private boundTouchStart: (e: TouchEvent) => void;\n private boundTouchMove: (e: TouchEvent) => void;\n private boundTouchEnd: (e: TouchEvent) => void;\n private boundMouseLeave: (e: MouseEvent) => void;\n\n constructor(\n canvas: HTMLCanvasElement,\n spatialIndex: SpatialIndex,\n callbacks: InteractionCallbacks,\n ) {\n this.canvas = canvas;\n this.spatialIndex = spatialIndex;\n this.callbacks = callbacks;\n\n // Bind handlers\n this.boundWheel = this.onWheel.bind(this);\n this.boundMouseDown = this.onMouseDown.bind(this);\n this.boundMouseMove = this.onMouseMove.bind(this);\n this.boundMouseUp = this.onMouseUp.bind(this);\n this.boundMouseLeave = this.onMouseLeave.bind(this);\n this.boundDblClick = this.onDblClick.bind(this);\n this.boundTouchStart = this.onTouchStart.bind(this);\n this.boundTouchMove = this.onTouchMove.bind(this);\n this.boundTouchEnd = this.onTouchEnd.bind(this);\n\n // Attach event listeners\n canvas.addEventListener('wheel', this.boundWheel, { passive: false });\n canvas.addEventListener('mousedown', this.boundMouseDown);\n canvas.addEventListener('mousemove', this.boundMouseMove);\n canvas.addEventListener('mouseup', this.boundMouseUp);\n canvas.addEventListener('mouseleave', this.boundMouseLeave);\n canvas.addEventListener('dblclick', this.boundDblClick);\n canvas.addEventListener('touchstart', this.boundTouchStart, {\n passive: false,\n });\n canvas.addEventListener('touchmove', this.boundTouchMove, {\n passive: false,\n });\n canvas.addEventListener('touchend', this.boundTouchEnd);\n }\n\n setTransform(transform: ZoomTransform): void {\n this.transform = transform;\n }\n\n getTransform(): ZoomTransform {\n return this.transform;\n }\n\n destroy(): void {\n this.canvas.removeEventListener('wheel', this.boundWheel);\n this.canvas.removeEventListener('mousedown', this.boundMouseDown);\n this.canvas.removeEventListener('mousemove', this.boundMouseMove);\n this.canvas.removeEventListener('mouseup', this.boundMouseUp);\n this.canvas.removeEventListener('mouseleave', this.boundMouseLeave);\n this.canvas.removeEventListener('dblclick', this.boundDblClick);\n this.canvas.removeEventListener('touchstart', this.boundTouchStart);\n this.canvas.removeEventListener('touchmove', this.boundTouchMove);\n this.canvas.removeEventListener('touchend', this.boundTouchEnd);\n }\n\n // -------------------------------------------------------------------------\n // Mouse handlers\n // -------------------------------------------------------------------------\n\n private canvasXY(e: MouseEvent): { x: number; y: number } {\n const rect = this.canvas.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n }\n\n private hitTest(screenX: number, screenY: number): string | null {\n const graph = this.transform.screenToGraph(screenX, screenY);\n const node = this.spatialIndex.findNearest(graph.x, graph.y, HIT_DISTANCE / this.transform.k);\n return node?.id ?? null;\n }\n\n private onWheel(e: WheelEvent): void {\n e.preventDefault();\n const { x, y } = this.canvasXY(e);\n const factor = e.deltaY * ZOOM_STEP;\n const newK = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, this.transform.k * (1 + factor)));\n this.transform = this.transform.zoomAt(newK, x, y);\n this.callbacks.onTransformChange(this.transform);\n }\n\n private onMouseDown(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n const hitId = this.hitTest(x, y);\n\n if (hitId) {\n // Start potential node drag\n this.dragState = { nodeId: hitId, started: false };\n this.mousedownNodeId = hitId;\n } else {\n // Start pan\n this.panState = { startX: x, startY: y };\n this.mousedownNodeId = null;\n }\n }\n\n private onMouseMove(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n\n if (this.dragState) {\n const graph = this.transform.screenToGraph(x, y);\n if (!this.dragState.started) {\n this.dragState.started = true;\n this.callbacks.onNodeDragStart(this.dragState.nodeId);\n }\n this.callbacks.onNodeDrag(this.dragState.nodeId, graph.x, graph.y);\n return;\n }\n\n if (this.panState) {\n const dx = x - this.panState.startX;\n const dy = y - this.panState.startY;\n this.transform = this.transform.pan(dx, dy);\n this.panState = { startX: x, startY: y };\n this.callbacks.onTransformChange(this.transform);\n return;\n }\n\n // Hover detection\n const hitId = this.hitTest(x, y);\n this.callbacks.onHoverChange(hitId);\n\n // If no node hit, check edges via callback\n if (!hitId) {\n const graph = this.transform.screenToGraph(x, y);\n this.callbacks.onBackgroundHover?.(graph.x, graph.y, x, y);\n }\n\n // Update cursor\n this.canvas.style.cursor = hitId ? 'pointer' : 'default';\n }\n\n private onMouseUp(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n\n if (this.dragState) {\n if (this.dragState.started) {\n this.callbacks.onNodeDragEnd(this.dragState.nodeId);\n } else {\n // Was a click on a node (no drag movement)\n this.handleNodeClick(this.dragState.nodeId, e.shiftKey);\n }\n this.dragState = null;\n return;\n }\n\n if (this.panState) {\n this.panState = null;\n\n // If mouse up is on background (no node), treat as background click\n if (!this.mousedownNodeId) {\n const hitId = this.hitTest(x, y);\n if (!hitId) {\n // Background click: clear selection\n this.selectedIds.clear();\n this.callbacks.onSelectionChange([]);\n }\n }\n return;\n }\n }\n\n private onDblClick(e: MouseEvent): void {\n const { x, y } = this.canvasXY(e);\n const hitId = this.hitTest(x, y);\n if (hitId) {\n this.callbacks.onDoubleClick(hitId);\n }\n }\n\n private onMouseLeave(_e: MouseEvent): void {\n this.callbacks.onHoverChange(null);\n this.canvas.style.cursor = 'default';\n\n // Cancel any in-progress pan\n if (this.panState) {\n this.panState = null;\n }\n }\n\n private handleNodeClick(nodeId: string, shiftKey: boolean): void {\n if (shiftKey) {\n // Toggle node in multi-select\n if (this.selectedIds.has(nodeId)) {\n this.selectedIds.delete(nodeId);\n } else {\n this.selectedIds.add(nodeId);\n }\n } else {\n // Single select\n this.selectedIds.clear();\n this.selectedIds.add(nodeId);\n }\n\n this.callbacks.onSelectionChange([...this.selectedIds]);\n }\n\n // -------------------------------------------------------------------------\n // Touch handlers\n // -------------------------------------------------------------------------\n\n private onTouchStart(e: TouchEvent): void {\n e.preventDefault();\n\n if (e.touches.length === 2) {\n // Pinch-zoom start\n const [t0, t1] = [e.touches[0], e.touches[1]];\n this.lastTouchDist = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);\n this.lastTouchCenter = {\n x: (t0.clientX + t1.clientX) / 2,\n y: (t0.clientY + t1.clientY) / 2,\n };\n } else if (e.touches.length === 1) {\n const touch = e.touches[0];\n const rect = this.canvas.getBoundingClientRect();\n const x = touch.clientX - rect.left;\n const y = touch.clientY - rect.top;\n\n const hitId = this.hitTest(x, y);\n if (hitId) {\n this.mousedownNodeId = hitId;\n } else {\n this.panState = { startX: x, startY: y };\n this.mousedownNodeId = null;\n }\n }\n }\n\n private onTouchMove(e: TouchEvent): void {\n e.preventDefault();\n\n if (e.touches.length === 2 && this.lastTouchDist !== null) {\n const [t0, t1] = [e.touches[0], e.touches[1]];\n const newDist = Math.hypot(t1.clientX - t0.clientX, t1.clientY - t0.clientY);\n const rect = this.canvas.getBoundingClientRect();\n const centerX = (t0.clientX + t1.clientX) / 2 - rect.left;\n const centerY = (t0.clientY + t1.clientY) / 2 - rect.top;\n\n const scale = newDist / this.lastTouchDist;\n const newK = Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, this.transform.k * scale));\n this.transform = this.transform.zoomAt(newK, centerX, centerY);\n\n // Pan from center movement\n if (this.lastTouchCenter) {\n const dx = centerX - (this.lastTouchCenter.x - rect.left);\n const dy = centerY - (this.lastTouchCenter.y - rect.top);\n this.transform = this.transform.pan(dx, dy);\n }\n\n this.lastTouchDist = newDist;\n this.lastTouchCenter = {\n x: (t0.clientX + t1.clientX) / 2,\n y: (t0.clientY + t1.clientY) / 2,\n };\n this.callbacks.onTransformChange(this.transform);\n } else if (e.touches.length === 1 && this.panState) {\n const touch = e.touches[0];\n const rect = this.canvas.getBoundingClientRect();\n const x = touch.clientX - rect.left;\n const y = touch.clientY - rect.top;\n\n const dx = x - this.panState.startX;\n const dy = y - this.panState.startY;\n this.transform = this.transform.pan(dx, dy);\n this.panState = { startX: x, startY: y };\n this.callbacks.onTransformChange(this.transform);\n }\n }\n\n private onTouchEnd(e: TouchEvent): void {\n if (e.touches.length === 0) {\n // Tap-select\n if (this.mousedownNodeId && !this.panState) {\n this.handleNodeClick(this.mousedownNodeId, false);\n } else if (!this.mousedownNodeId && this.panState) {\n // Background tap: clear selection\n this.selectedIds.clear();\n this.callbacks.onSelectionChange([]);\n }\n\n this.panState = null;\n this.mousedownNodeId = null;\n this.lastTouchDist = null;\n this.lastTouchCenter = null;\n }\n }\n}\n","/**\n * Keyboard navigation for the graph canvas.\n *\n * Provides accessible keyboard control: Tab to focus, arrow keys to\n * navigate between adjacent nodes (following edges), Enter to select,\n * Escape to clear, +/- to zoom, Home to fit all, / to focus search.\n */\n\nimport type { PositionedNode } from './types';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface KeyboardNavOptions {\n canvas: HTMLCanvasElement;\n getNodes(): PositionedNode[];\n getSelectedIds(): string[];\n getAdjacency(): Map<string, Set<string>>;\n onSelect(nodeId: string): void;\n onDeselect(): void;\n onZoom(direction: 'in' | 'out'): void;\n onFitAll(): void;\n onFocusSearch?(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Attach keyboard navigation to a graph canvas.\n * Returns a cleanup function that removes all listeners.\n */\nexport function attachGraphKeyboardNav(options: KeyboardNavOptions): () => void {\n const {\n canvas,\n getNodes,\n getSelectedIds,\n getAdjacency,\n onSelect,\n onDeselect,\n onZoom,\n onFitAll,\n onFocusSearch,\n } = options;\n\n let focusedNodeId: string | null = null;\n\n // Make canvas focusable\n if (!canvas.hasAttribute('tabindex')) {\n canvas.setAttribute('tabindex', '0');\n }\n\n function findNodeById(id: string): PositionedNode | undefined {\n return getNodes().find((n) => n.id === id);\n }\n\n /**\n * Given a set of neighbor node ids, pick the one that best matches\n * the arrow key direction relative to the current focused node.\n */\n function pickDirectionalNeighbor(\n fromNode: PositionedNode,\n neighborIds: Set<string>,\n direction: 'up' | 'down' | 'left' | 'right',\n ): string | null {\n const nodes = getNodes();\n const candidates = nodes.filter((n) => neighborIds.has(n.id));\n if (candidates.length === 0) return null;\n\n // Score each candidate by how well it matches the desired direction\n let best: PositionedNode | null = null;\n let bestScore = -Infinity;\n\n for (const c of candidates) {\n const dx = c.x - fromNode.x;\n const dy = c.y - fromNode.y;\n let score: number;\n\n switch (direction) {\n case 'right':\n score = dx - Math.abs(dy) * 0.5;\n break;\n case 'left':\n score = -dx - Math.abs(dy) * 0.5;\n break;\n case 'down':\n score = dy - Math.abs(dx) * 0.5;\n break;\n case 'up':\n score = -dy - Math.abs(dx) * 0.5;\n break;\n }\n\n if (score > bestScore) {\n bestScore = score;\n best = c;\n }\n }\n\n return best?.id ?? null;\n }\n\n function onKeyDown(e: KeyboardEvent): void {\n switch (e.key) {\n case 'Tab': {\n // Focus first/selected node\n const selected = getSelectedIds();\n const nodes = getNodes();\n if (nodes.length === 0) return;\n\n if (selected.length > 0) {\n focusedNodeId = selected[0];\n } else if (!focusedNodeId || !findNodeById(focusedNodeId)) {\n focusedNodeId = nodes[0].id;\n }\n\n e.preventDefault();\n break;\n }\n\n case 'ArrowUp':\n case 'ArrowDown':\n case 'ArrowLeft':\n case 'ArrowRight': {\n if (!focusedNodeId) return;\n e.preventDefault();\n\n const focusedNode = findNodeById(focusedNodeId);\n if (!focusedNode) return;\n\n const adjacency = getAdjacency();\n const neighbors = adjacency.get(focusedNodeId);\n if (!neighbors || neighbors.size === 0) return;\n\n const dirMap: Record<string, 'up' | 'down' | 'left' | 'right'> = {\n ArrowUp: 'up',\n ArrowDown: 'down',\n ArrowLeft: 'left',\n ArrowRight: 'right',\n };\n\n const nextId = pickDirectionalNeighbor(focusedNode, neighbors, dirMap[e.key]);\n if (nextId) {\n focusedNodeId = nextId;\n onSelect(nextId);\n }\n break;\n }\n\n case 'Enter': {\n if (focusedNodeId) {\n e.preventDefault();\n const selected = getSelectedIds();\n if (selected.includes(focusedNodeId)) {\n onDeselect();\n } else {\n onSelect(focusedNodeId);\n }\n }\n break;\n }\n\n case 'Escape': {\n e.preventDefault();\n focusedNodeId = null;\n onDeselect();\n break;\n }\n\n case '+':\n case '=': {\n e.preventDefault();\n onZoom('in');\n break;\n }\n\n case '-':\n case '_': {\n e.preventDefault();\n onZoom('out');\n break;\n }\n\n case 'Home': {\n e.preventDefault();\n onFitAll();\n break;\n }\n\n case '/': {\n if (onFocusSearch) {\n e.preventDefault();\n onFocusSearch();\n }\n break;\n }\n }\n }\n\n canvas.addEventListener('keydown', onKeyDown);\n\n // Return cleanup function\n return () => {\n canvas.removeEventListener('keydown', onKeyDown);\n };\n}\n","/**\n * Graph search manager.\n *\n * Provides case-insensitive substring matching against node labels/ids.\n * Returns a Set of matching node ids that the renderer uses to dim\n * non-matching nodes and edges.\n */\n\nexport class GraphSearchManager {\n private matchedIds: Set<string> | null = null;\n\n /**\n * Search for nodes matching the query string.\n * Returns a Set of matching node ids, or an empty set if nothing matches.\n */\n search(query: string, nodes: Array<{ id: string; label?: string }>): Set<string> {\n const q = query.toLowerCase().trim();\n\n if (q === '') {\n this.matchedIds = null;\n return new Set();\n }\n\n const matches = new Set<string>();\n for (const node of nodes) {\n const label = (node.label ?? '').toLowerCase();\n const id = node.id.toLowerCase();\n if (label.includes(q) || id.includes(q)) {\n matches.add(node.id);\n }\n }\n\n this.matchedIds = matches;\n return matches;\n }\n\n /**\n * Clear the current search.\n * Returns null to indicate no active search.\n */\n clearSearch(): Set<string> | null {\n this.matchedIds = null;\n return null;\n }\n\n /** Get the current set of matched ids, or null if no search is active. */\n getMatches(): Set<string> | null {\n return this.matchedIds;\n }\n}\n","export default function(x, y) {\n var nodes, strength = 1;\n\n if (x == null) x = 0;\n if (y == null) y = 0;\n\n function force() {\n var i,\n n = nodes.length,\n node,\n sx = 0,\n sy = 0;\n\n for (i = 0; i < n; ++i) {\n node = nodes[i], sx += node.x, sy += node.y;\n }\n\n for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, i = 0; i < n; ++i) {\n node = nodes[i], node.x -= sx, node.y -= sy;\n }\n }\n\n force.initialize = function(_) {\n nodes = _;\n };\n\n force.x = function(_) {\n return arguments.length ? (x = +_, force) : x;\n };\n\n force.y = function(_) {\n return arguments.length ? (y = +_, force) : y;\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = +_, force) : strength;\n };\n\n return force;\n}\n","export default function(d) {\n const x = +this._x.call(null, d),\n y = +this._y.call(null, d);\n return add(this.cover(x, y), x, y, d);\n}\n\nfunction add(tree, x, y, d) {\n if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points\n\n var parent,\n node = tree._root,\n leaf = {data: d},\n x0 = tree._x0,\n y0 = tree._y0,\n x1 = tree._x1,\n y1 = tree._y1,\n xm,\n ym,\n xp,\n yp,\n right,\n bottom,\n i,\n j;\n\n // If the tree is empty, initialize the root as a leaf.\n if (!node) return tree._root = leaf, tree;\n\n // Find the existing leaf for the new point, or add it.\n while (node.length) {\n if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;\n if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;\n if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;\n }\n\n // Is the new point is exactly coincident with the existing point?\n xp = +tree._x.call(null, node.data);\n yp = +tree._y.call(null, node.data);\n if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;\n\n // Otherwise, split the leaf node until the old and new point are separated.\n do {\n parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);\n if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;\n if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;\n } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));\n return parent[j] = node, parent[i] = leaf, tree;\n}\n\nexport function addAll(data) {\n var d, i, n = data.length,\n x,\n y,\n xz = new Array(n),\n yz = new Array(n),\n x0 = Infinity,\n y0 = Infinity,\n x1 = -Infinity,\n y1 = -Infinity;\n\n // Compute the points and their extent.\n for (i = 0; i < n; ++i) {\n if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;\n xz[i] = x;\n yz[i] = y;\n if (x < x0) x0 = x;\n if (x > x1) x1 = x;\n if (y < y0) y0 = y;\n if (y > y1) y1 = y;\n }\n\n // If there were no (valid) points, abort.\n if (x0 > x1 || y0 > y1) return this;\n\n // Expand the tree to cover the new points.\n this.cover(x0, y0).cover(x1, y1);\n\n // Add the new points.\n for (i = 0; i < n; ++i) {\n add(this, xz[i], yz[i], data[i]);\n }\n\n return this;\n}\n","export default function(x, y) {\n if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points\n\n var x0 = this._x0,\n y0 = this._y0,\n x1 = this._x1,\n y1 = this._y1;\n\n // If the quadtree has no extent, initialize them.\n // Integer extent are necessary so that if we later double the extent,\n // the existing quadrant boundaries don’t change due to floating point error!\n if (isNaN(x0)) {\n x1 = (x0 = Math.floor(x)) + 1;\n y1 = (y0 = Math.floor(y)) + 1;\n }\n\n // Otherwise, double repeatedly to cover.\n else {\n var z = x1 - x0 || 1,\n node = this._root,\n parent,\n i;\n\n while (x0 > x || x >= x1 || y0 > y || y >= y1) {\n i = (y < y0) << 1 | (x < x0);\n parent = new Array(4), parent[i] = node, node = parent, z *= 2;\n switch (i) {\n case 0: x1 = x0 + z, y1 = y0 + z; break;\n case 1: x0 = x1 - z, y1 = y0 + z; break;\n case 2: x1 = x0 + z, y0 = y1 - z; break;\n case 3: x0 = x1 - z, y0 = y1 - z; break;\n }\n }\n\n if (this._root && this._root.length) this._root = node;\n }\n\n this._x0 = x0;\n this._y0 = y0;\n this._x1 = x1;\n this._y1 = y1;\n return this;\n}\n","export default function() {\n var data = [];\n this.visit(function(node) {\n if (!node.length) do data.push(node.data); while (node = node.next)\n });\n return data;\n}\n","export default function(_) {\n return arguments.length\n ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])\n : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];\n}\n","export default function(node, x0, y0, x1, y1) {\n this.node = node;\n this.x0 = x0;\n this.y0 = y0;\n this.x1 = x1;\n this.y1 = y1;\n}\n","import Quad from \"./quad.js\";\n\nexport default function(x, y, radius) {\n var data,\n x0 = this._x0,\n y0 = this._y0,\n x1,\n y1,\n x2,\n y2,\n x3 = this._x1,\n y3 = this._y1,\n quads = [],\n node = this._root,\n q,\n i;\n\n if (node) quads.push(new Quad(node, x0, y0, x3, y3));\n if (radius == null) radius = Infinity;\n else {\n x0 = x - radius, y0 = y - radius;\n x3 = x + radius, y3 = y + radius;\n radius *= radius;\n }\n\n while (q = quads.pop()) {\n\n // Stop searching if this quadrant can’t contain a closer node.\n if (!(node = q.node)\n || (x1 = q.x0) > x3\n || (y1 = q.y0) > y3\n || (x2 = q.x1) < x0\n || (y2 = q.y1) < y0) continue;\n\n // Bisect the current quadrant.\n if (node.length) {\n var xm = (x1 + x2) / 2,\n ym = (y1 + y2) / 2;\n\n quads.push(\n new Quad(node[3], xm, ym, x2, y2),\n new Quad(node[2], x1, ym, xm, y2),\n new Quad(node[1], xm, y1, x2, ym),\n new Quad(node[0], x1, y1, xm, ym)\n );\n\n // Visit the closest quadrant first.\n if (i = (y >= ym) << 1 | (x >= xm)) {\n q = quads[quads.length - 1];\n quads[quads.length - 1] = quads[quads.length - 1 - i];\n quads[quads.length - 1 - i] = q;\n }\n }\n\n // Visit this point. (Visiting coincident points isn’t necessary!)\n else {\n var dx = x - +this._x.call(null, node.data),\n dy = y - +this._y.call(null, node.data),\n d2 = dx * dx + dy * dy;\n if (d2 < radius) {\n var d = Math.sqrt(radius = d2);\n x0 = x - d, y0 = y - d;\n x3 = x + d, y3 = y + d;\n data = node.data;\n }\n }\n }\n\n return data;\n}\n","export default function(d) {\n if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points\n\n var parent,\n node = this._root,\n retainer,\n previous,\n next,\n x0 = this._x0,\n y0 = this._y0,\n x1 = this._x1,\n y1 = this._y1,\n x,\n y,\n xm,\n ym,\n right,\n bottom,\n i,\n j;\n\n // If the tree is empty, initialize the root as a leaf.\n if (!node) return this;\n\n // Find the leaf node for the point.\n // While descending, also retain the deepest parent with a non-removed sibling.\n if (node.length) while (true) {\n if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;\n if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;\n if (!(parent = node, node = node[i = bottom << 1 | right])) return this;\n if (!node.length) break;\n if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;\n }\n\n // Find the point to remove.\n while (node.data !== d) if (!(previous = node, node = node.next)) return this;\n if (next = node.next) delete node.next;\n\n // If there are multiple coincident points, remove just the point.\n if (previous) return (next ? previous.next = next : delete previous.next), this;\n\n // If this is the root point, remove it.\n if (!parent) return this._root = next, this;\n\n // Remove this leaf.\n next ? parent[i] = next : delete parent[i];\n\n // If the parent now contains exactly one leaf, collapse superfluous parents.\n if ((node = parent[0] || parent[1] || parent[2] || parent[3])\n && node === (parent[3] || parent[2] || parent[1] || parent[0])\n && !node.length) {\n if (retainer) retainer[j] = node;\n else this._root = node;\n }\n\n return this;\n}\n\nexport function removeAll(data) {\n for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);\n return this;\n}\n","export default function() {\n return this._root;\n}\n","export default function() {\n var size = 0;\n this.visit(function(node) {\n if (!node.length) do ++size; while (node = node.next)\n });\n return size;\n}\n","import Quad from \"./quad.js\";\n\nexport default function(callback) {\n var quads = [], q, node = this._root, child, x0, y0, x1, y1;\n if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));\n while (q = quads.pop()) {\n if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {\n var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;\n if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));\n if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));\n if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));\n if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));\n }\n }\n return this;\n}\n","import Quad from \"./quad.js\";\n\nexport default function(callback) {\n var quads = [], next = [], q;\n if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));\n while (q = quads.pop()) {\n var node = q.node;\n if (node.length) {\n var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;\n if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));\n if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));\n if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));\n if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));\n }\n next.push(q);\n }\n while (q = next.pop()) {\n callback(q.node, q.x0, q.y0, q.x1, q.y1);\n }\n return this;\n}\n","export function defaultX(d) {\n return d[0];\n}\n\nexport default function(_) {\n return arguments.length ? (this._x = _, this) : this._x;\n}\n","export function defaultY(d) {\n return d[1];\n}\n\nexport default function(_) {\n return arguments.length ? (this._y = _, this) : this._y;\n}\n","import tree_add, {addAll as tree_addAll} from \"./add.js\";\nimport tree_cover from \"./cover.js\";\nimport tree_data from \"./data.js\";\nimport tree_extent from \"./extent.js\";\nimport tree_find from \"./find.js\";\nimport tree_remove, {removeAll as tree_removeAll} from \"./remove.js\";\nimport tree_root from \"./root.js\";\nimport tree_size from \"./size.js\";\nimport tree_visit from \"./visit.js\";\nimport tree_visitAfter from \"./visitAfter.js\";\nimport tree_x, {defaultX} from \"./x.js\";\nimport tree_y, {defaultY} from \"./y.js\";\n\nexport default function quadtree(nodes, x, y) {\n var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);\n return nodes == null ? tree : tree.addAll(nodes);\n}\n\nfunction Quadtree(x, y, x0, y0, x1, y1) {\n this._x = x;\n this._y = y;\n this._x0 = x0;\n this._y0 = y0;\n this._x1 = x1;\n this._y1 = y1;\n this._root = undefined;\n}\n\nfunction leaf_copy(leaf) {\n var copy = {data: leaf.data}, next = copy;\n while (leaf = leaf.next) next = next.next = {data: leaf.data};\n return copy;\n}\n\nvar treeProto = quadtree.prototype = Quadtree.prototype;\n\ntreeProto.copy = function() {\n var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),\n node = this._root,\n nodes,\n child;\n\n if (!node) return copy;\n\n if (!node.length) return copy._root = leaf_copy(node), copy;\n\n nodes = [{source: node, target: copy._root = new Array(4)}];\n while (node = nodes.pop()) {\n for (var i = 0; i < 4; ++i) {\n if (child = node.source[i]) {\n if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});\n else node.target[i] = leaf_copy(child);\n }\n }\n }\n\n return copy;\n};\n\ntreeProto.add = tree_add;\ntreeProto.addAll = tree_addAll;\ntreeProto.cover = tree_cover;\ntreeProto.data = tree_data;\ntreeProto.extent = tree_extent;\ntreeProto.find = tree_find;\ntreeProto.remove = tree_remove;\ntreeProto.removeAll = tree_removeAll;\ntreeProto.root = tree_root;\ntreeProto.size = tree_size;\ntreeProto.visit = tree_visit;\ntreeProto.visitAfter = tree_visitAfter;\ntreeProto.x = tree_x;\ntreeProto.y = tree_y;\n","export default function(x) {\n return function() {\n return x;\n };\n}\n","export default function(random) {\n return (random() - 0.5) * 1e-6;\n}\n","import {quadtree} from \"d3-quadtree\";\nimport constant from \"./constant.js\";\nimport jiggle from \"./jiggle.js\";\n\nfunction x(d) {\n return d.x + d.vx;\n}\n\nfunction y(d) {\n return d.y + d.vy;\n}\n\nexport default function(radius) {\n var nodes,\n radii,\n random,\n strength = 1,\n iterations = 1;\n\n if (typeof radius !== \"function\") radius = constant(radius == null ? 1 : +radius);\n\n function force() {\n var i, n = nodes.length,\n tree,\n node,\n xi,\n yi,\n ri,\n ri2;\n\n for (var k = 0; k < iterations; ++k) {\n tree = quadtree(nodes, x, y).visitAfter(prepare);\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n ri = radii[node.index], ri2 = ri * ri;\n xi = node.x + node.vx;\n yi = node.y + node.vy;\n tree.visit(apply);\n }\n }\n\n function apply(quad, x0, y0, x1, y1) {\n var data = quad.data, rj = quad.r, r = ri + rj;\n if (data) {\n if (data.index > node.index) {\n var x = xi - data.x - data.vx,\n y = yi - data.y - data.vy,\n l = x * x + y * y;\n if (l < r * r) {\n if (x === 0) x = jiggle(random), l += x * x;\n if (y === 0) y = jiggle(random), l += y * y;\n l = (r - (l = Math.sqrt(l))) / l * strength;\n node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));\n node.vy += (y *= l) * r;\n data.vx -= x * (r = 1 - r);\n data.vy -= y * r;\n }\n }\n return;\n }\n return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;\n }\n }\n\n function prepare(quad) {\n if (quad.data) return quad.r = radii[quad.data.index];\n for (var i = quad.r = 0; i < 4; ++i) {\n if (quad[i] && quad[i].r > quad.r) {\n quad.r = quad[i].r;\n }\n }\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length, node;\n radii = new Array(n);\n for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);\n }\n\n force.initialize = function(_nodes, _random) {\n nodes = _nodes;\n random = _random;\n initialize();\n };\n\n force.iterations = function(_) {\n return arguments.length ? (iterations = +_, force) : iterations;\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = +_, force) : strength;\n };\n\n force.radius = function(_) {\n return arguments.length ? (radius = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : radius;\n };\n\n return force;\n}\n","import constant from \"./constant.js\";\nimport jiggle from \"./jiggle.js\";\n\nfunction index(d) {\n return d.index;\n}\n\nfunction find(nodeById, nodeId) {\n var node = nodeById.get(nodeId);\n if (!node) throw new Error(\"node not found: \" + nodeId);\n return node;\n}\n\nexport default function(links) {\n var id = index,\n strength = defaultStrength,\n strengths,\n distance = constant(30),\n distances,\n nodes,\n count,\n bias,\n random,\n iterations = 1;\n\n if (links == null) links = [];\n\n function defaultStrength(link) {\n return 1 / Math.min(count[link.source.index], count[link.target.index]);\n }\n\n function force(alpha) {\n for (var k = 0, n = links.length; k < iterations; ++k) {\n for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {\n link = links[i], source = link.source, target = link.target;\n x = target.x + target.vx - source.x - source.vx || jiggle(random);\n y = target.y + target.vy - source.y - source.vy || jiggle(random);\n l = Math.sqrt(x * x + y * y);\n l = (l - distances[i]) / l * alpha * strengths[i];\n x *= l, y *= l;\n target.vx -= x * (b = bias[i]);\n target.vy -= y * b;\n source.vx += x * (b = 1 - b);\n source.vy += y * b;\n }\n }\n }\n\n function initialize() {\n if (!nodes) return;\n\n var i,\n n = nodes.length,\n m = links.length,\n nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])),\n link;\n\n for (i = 0, count = new Array(n); i < m; ++i) {\n link = links[i], link.index = i;\n if (typeof link.source !== \"object\") link.source = find(nodeById, link.source);\n if (typeof link.target !== \"object\") link.target = find(nodeById, link.target);\n count[link.source.index] = (count[link.source.index] || 0) + 1;\n count[link.target.index] = (count[link.target.index] || 0) + 1;\n }\n\n for (i = 0, bias = new Array(m); i < m; ++i) {\n link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);\n }\n\n strengths = new Array(m), initializeStrength();\n distances = new Array(m), initializeDistance();\n }\n\n function initializeStrength() {\n if (!nodes) return;\n\n for (var i = 0, n = links.length; i < n; ++i) {\n strengths[i] = +strength(links[i], i, links);\n }\n }\n\n function initializeDistance() {\n if (!nodes) return;\n\n for (var i = 0, n = links.length; i < n; ++i) {\n distances[i] = +distance(links[i], i, links);\n }\n }\n\n force.initialize = function(_nodes, _random) {\n nodes = _nodes;\n random = _random;\n initialize();\n };\n\n force.links = function(_) {\n return arguments.length ? (links = _, initialize(), force) : links;\n };\n\n force.id = function(_) {\n return arguments.length ? (id = _, force) : id;\n };\n\n force.iterations = function(_) {\n return arguments.length ? (iterations = +_, force) : iterations;\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initializeStrength(), force) : strength;\n };\n\n force.distance = function(_) {\n return arguments.length ? (distance = typeof _ === \"function\" ? _ : constant(+_), initializeDistance(), force) : distance;\n };\n\n return force;\n}\n","var noop = {value: () => {}};\n\nfunction dispatch() {\n for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {\n if (!(t = arguments[i] + \"\") || (t in _) || /[\\s.]/.test(t)) throw new Error(\"illegal type: \" + t);\n _[t] = [];\n }\n return new Dispatch(_);\n}\n\nfunction Dispatch(_) {\n this._ = _;\n}\n\nfunction parseTypenames(typenames, types) {\n return typenames.trim().split(/^|\\s+/).map(function(t) {\n var name = \"\", i = t.indexOf(\".\");\n if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);\n if (t && !types.hasOwnProperty(t)) throw new Error(\"unknown type: \" + t);\n return {type: t, name: name};\n });\n}\n\nDispatch.prototype = dispatch.prototype = {\n constructor: Dispatch,\n on: function(typename, callback) {\n var _ = this._,\n T = parseTypenames(typename + \"\", _),\n t,\n i = -1,\n n = T.length;\n\n // If no callback was specified, return the callback of the given type and name.\n if (arguments.length < 2) {\n while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;\n return;\n }\n\n // If a type was specified, set the callback for the given type and name.\n // Otherwise, if a null callback was specified, remove callbacks of the given name.\n if (callback != null && typeof callback !== \"function\") throw new Error(\"invalid callback: \" + callback);\n while (++i < n) {\n if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);\n else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);\n }\n\n return this;\n },\n copy: function() {\n var copy = {}, _ = this._;\n for (var t in _) copy[t] = _[t].slice();\n return new Dispatch(copy);\n },\n call: function(type, that) {\n if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];\n if (!this._.hasOwnProperty(type)) throw new Error(\"unknown type: \" + type);\n for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n },\n apply: function(type, that, args) {\n if (!this._.hasOwnProperty(type)) throw new Error(\"unknown type: \" + type);\n for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n }\n};\n\nfunction get(type, name) {\n for (var i = 0, n = type.length, c; i < n; ++i) {\n if ((c = type[i]).name === name) {\n return c.value;\n }\n }\n}\n\nfunction set(type, name, callback) {\n for (var i = 0, n = type.length; i < n; ++i) {\n if (type[i].name === name) {\n type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));\n break;\n }\n }\n if (callback != null) type.push({name: name, value: callback});\n return type;\n}\n\nexport default dispatch;\n","var frame = 0, // is an animation frame pending?\n timeout = 0, // is a timeout pending?\n interval = 0, // are any timers active?\n pokeDelay = 1000, // how frequently we check for clock skew\n taskHead,\n taskTail,\n clockLast = 0,\n clockNow = 0,\n clockSkew = 0,\n clock = typeof performance === \"object\" && performance.now ? performance : Date,\n setFrame = typeof window === \"object\" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); };\n\nexport function now() {\n return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);\n}\n\nfunction clearNow() {\n clockNow = 0;\n}\n\nexport function Timer() {\n this._call =\n this._time =\n this._next = null;\n}\n\nTimer.prototype = timer.prototype = {\n constructor: Timer,\n restart: function(callback, delay, time) {\n if (typeof callback !== \"function\") throw new TypeError(\"callback is not a function\");\n time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);\n if (!this._next && taskTail !== this) {\n if (taskTail) taskTail._next = this;\n else taskHead = this;\n taskTail = this;\n }\n this._call = callback;\n this._time = time;\n sleep();\n },\n stop: function() {\n if (this._call) {\n this._call = null;\n this._time = Infinity;\n sleep();\n }\n }\n};\n\nexport function timer(callback, delay, time) {\n var t = new Timer;\n t.restart(callback, delay, time);\n return t;\n}\n\nexport function timerFlush() {\n now(); // Get the current time, if not already set.\n ++frame; // Pretend we’ve set an alarm, if we haven’t already.\n var t = taskHead, e;\n while (t) {\n if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e);\n t = t._next;\n }\n --frame;\n}\n\nfunction wake() {\n clockNow = (clockLast = clock.now()) + clockSkew;\n frame = timeout = 0;\n try {\n timerFlush();\n } finally {\n frame = 0;\n nap();\n clockNow = 0;\n }\n}\n\nfunction poke() {\n var now = clock.now(), delay = now - clockLast;\n if (delay > pokeDelay) clockSkew -= delay, clockLast = now;\n}\n\nfunction nap() {\n var t0, t1 = taskHead, t2, time = Infinity;\n while (t1) {\n if (t1._call) {\n if (time > t1._time) time = t1._time;\n t0 = t1, t1 = t1._next;\n } else {\n t2 = t1._next, t1._next = null;\n t1 = t0 ? t0._next = t2 : taskHead = t2;\n }\n }\n taskTail = t0;\n sleep(time);\n}\n\nfunction sleep(time) {\n if (frame) return; // Soonest alarm already set, or will be.\n if (timeout) timeout = clearTimeout(timeout);\n var delay = time - clockNow; // Strictly less than if we recomputed clockNow.\n if (delay > 24) {\n if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);\n if (interval) interval = clearInterval(interval);\n } else {\n if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);\n frame = 1, setFrame(wake);\n }\n}\n","// https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use\nconst a = 1664525;\nconst c = 1013904223;\nconst m = 4294967296; // 2^32\n\nexport default function() {\n let s = 1;\n return () => (s = (a * s + c) % m) / m;\n}\n","import {dispatch} from \"d3-dispatch\";\nimport {timer} from \"d3-timer\";\nimport lcg from \"./lcg.js\";\n\nexport function x(d) {\n return d.x;\n}\n\nexport function y(d) {\n return d.y;\n}\n\nvar initialRadius = 10,\n initialAngle = Math.PI * (3 - Math.sqrt(5));\n\nexport default function(nodes) {\n var simulation,\n alpha = 1,\n alphaMin = 0.001,\n alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),\n alphaTarget = 0,\n velocityDecay = 0.6,\n forces = new Map(),\n stepper = timer(step),\n event = dispatch(\"tick\", \"end\"),\n random = lcg();\n\n if (nodes == null) nodes = [];\n\n function step() {\n tick();\n event.call(\"tick\", simulation);\n if (alpha < alphaMin) {\n stepper.stop();\n event.call(\"end\", simulation);\n }\n }\n\n function tick(iterations) {\n var i, n = nodes.length, node;\n\n if (iterations === undefined) iterations = 1;\n\n for (var k = 0; k < iterations; ++k) {\n alpha += (alphaTarget - alpha) * alphaDecay;\n\n forces.forEach(function(force) {\n force(alpha);\n });\n\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n if (node.fx == null) node.x += node.vx *= velocityDecay;\n else node.x = node.fx, node.vx = 0;\n if (node.fy == null) node.y += node.vy *= velocityDecay;\n else node.y = node.fy, node.vy = 0;\n }\n }\n\n return simulation;\n }\n\n function initializeNodes() {\n for (var i = 0, n = nodes.length, node; i < n; ++i) {\n node = nodes[i], node.index = i;\n if (node.fx != null) node.x = node.fx;\n if (node.fy != null) node.y = node.fy;\n if (isNaN(node.x) || isNaN(node.y)) {\n var radius = initialRadius * Math.sqrt(0.5 + i), angle = i * initialAngle;\n node.x = radius * Math.cos(angle);\n node.y = radius * Math.sin(angle);\n }\n if (isNaN(node.vx) || isNaN(node.vy)) {\n node.vx = node.vy = 0;\n }\n }\n }\n\n function initializeForce(force) {\n if (force.initialize) force.initialize(nodes, random);\n return force;\n }\n\n initializeNodes();\n\n return simulation = {\n tick: tick,\n\n restart: function() {\n return stepper.restart(step), simulation;\n },\n\n stop: function() {\n return stepper.stop(), simulation;\n },\n\n nodes: function(_) {\n return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes;\n },\n\n alpha: function(_) {\n return arguments.length ? (alpha = +_, simulation) : alpha;\n },\n\n alphaMin: function(_) {\n return arguments.length ? (alphaMin = +_, simulation) : alphaMin;\n },\n\n alphaDecay: function(_) {\n return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;\n },\n\n alphaTarget: function(_) {\n return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;\n },\n\n velocityDecay: function(_) {\n return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;\n },\n\n randomSource: function(_) {\n return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random;\n },\n\n force: function(name, _) {\n return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);\n },\n\n find: function(x, y, radius) {\n var i = 0,\n n = nodes.length,\n dx,\n dy,\n d2,\n node,\n closest;\n\n if (radius == null) radius = Infinity;\n else radius *= radius;\n\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n dx = x - node.x;\n dy = y - node.y;\n d2 = dx * dx + dy * dy;\n if (d2 < radius) closest = node, radius = d2;\n }\n\n return closest;\n },\n\n on: function(name, _) {\n return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);\n }\n };\n}\n","import {quadtree} from \"d3-quadtree\";\nimport constant from \"./constant.js\";\nimport jiggle from \"./jiggle.js\";\nimport {x, y} from \"./simulation.js\";\n\nexport default function() {\n var nodes,\n node,\n random,\n alpha,\n strength = constant(-30),\n strengths,\n distanceMin2 = 1,\n distanceMax2 = Infinity,\n theta2 = 0.81;\n\n function force(_) {\n var i, n = nodes.length, tree = quadtree(nodes, x, y).visitAfter(accumulate);\n for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length, node;\n strengths = new Array(n);\n for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);\n }\n\n function accumulate(quad) {\n var strength = 0, q, c, weight = 0, x, y, i;\n\n // For internal nodes, accumulate forces from child quadrants.\n if (quad.length) {\n for (x = y = i = 0; i < 4; ++i) {\n if ((q = quad[i]) && (c = Math.abs(q.value))) {\n strength += q.value, weight += c, x += c * q.x, y += c * q.y;\n }\n }\n quad.x = x / weight;\n quad.y = y / weight;\n }\n\n // For leaf nodes, accumulate forces from coincident quadrants.\n else {\n q = quad;\n q.x = q.data.x;\n q.y = q.data.y;\n do strength += strengths[q.data.index];\n while (q = q.next);\n }\n\n quad.value = strength;\n }\n\n function apply(quad, x1, _, x2) {\n if (!quad.value) return true;\n\n var x = quad.x - node.x,\n y = quad.y - node.y,\n w = x2 - x1,\n l = x * x + y * y;\n\n // Apply the Barnes-Hut approximation if possible.\n // Limit forces for very close nodes; randomize direction if coincident.\n if (w * w / theta2 < l) {\n if (l < distanceMax2) {\n if (x === 0) x = jiggle(random), l += x * x;\n if (y === 0) y = jiggle(random), l += y * y;\n if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);\n node.vx += x * quad.value * alpha / l;\n node.vy += y * quad.value * alpha / l;\n }\n return true;\n }\n\n // Otherwise, process points directly.\n else if (quad.length || l >= distanceMax2) return;\n\n // Limit forces for very close nodes; randomize direction if coincident.\n if (quad.data !== node || quad.next) {\n if (x === 0) x = jiggle(random), l += x * x;\n if (y === 0) y = jiggle(random), l += y * y;\n if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);\n }\n\n do if (quad.data !== node) {\n w = strengths[quad.data.index] * alpha / l;\n node.vx += x * w;\n node.vy += y * w;\n } while (quad = quad.next);\n }\n\n force.initialize = function(_nodes, _random) {\n nodes = _nodes;\n random = _random;\n initialize();\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n };\n\n force.distanceMin = function(_) {\n return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);\n };\n\n force.distanceMax = function(_) {\n return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);\n };\n\n force.theta = function(_) {\n return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);\n };\n\n return force;\n}\n","import constant from \"./constant.js\";\n\nexport default function(x) {\n var strength = constant(0.1),\n nodes,\n strengths,\n xz;\n\n if (typeof x !== \"function\") x = constant(x == null ? 0 : +x);\n\n function force(alpha) {\n for (var i = 0, n = nodes.length, node; i < n; ++i) {\n node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;\n }\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length;\n strengths = new Array(n);\n xz = new Array(n);\n for (i = 0; i < n; ++i) {\n strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);\n }\n }\n\n force.initialize = function(_) {\n nodes = _;\n initialize();\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n };\n\n force.x = function(_) {\n return arguments.length ? (x = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : x;\n };\n\n return force;\n}\n","import constant from \"./constant.js\";\n\nexport default function(y) {\n var strength = constant(0.1),\n nodes,\n strengths,\n yz;\n\n if (typeof y !== \"function\") y = constant(y == null ? 0 : +y);\n\n function force(alpha) {\n for (var i = 0, n = nodes.length, node; i < n; ++i) {\n node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;\n }\n }\n\n function initialize() {\n if (!nodes) return;\n var i, n = nodes.length;\n strengths = new Array(n);\n yz = new Array(n);\n for (i = 0; i < n; ++i) {\n strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);\n }\n }\n\n force.initialize = function(_) {\n nodes = _;\n initialize();\n };\n\n force.strength = function(_) {\n return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n };\n\n force.y = function(_) {\n return arguments.length ? (y = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : y;\n };\n\n return force;\n}\n","/**\n * SimulationManager: spawns a Web Worker for the force simulation,\n * or falls back to synchronous d3-force on the main thread.\n *\n * The worker is always preferred when available. Synchronous fallback\n * is only used when Web Workers are unavailable (SSR, test environments).\n * The sync path batches ticks via requestAnimationFrame to avoid\n * blocking the main thread.\n */\n\nimport {\n forceCenter,\n forceCollide,\n forceLink,\n forceManyBody,\n forceSimulation,\n forceX,\n forceY,\n type Simulation,\n type SimulationNodeDatum,\n} from 'd3-force';\n\nimport type { SimEdge, SimNode, WorkerOutMessage, WorkerSimulationConfig } from './worker-protocol';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SYNC_MAX_TICKS = 300;\nconst SYNC_TICKS_PER_BATCH = 15;\n\n// ---------------------------------------------------------------------------\n// Internal node shape for sync simulation\n// ---------------------------------------------------------------------------\n\ninterface SyncNode extends SimulationNodeDatum {\n id: string;\n radius: number;\n community?: string;\n fx?: number | null;\n fy?: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Cluster force (duplicated in simulation-worker.ts for the Web Worker path.\n// Worker can't import from workspace packages, so both copies must stay in sync.)\n// ---------------------------------------------------------------------------\n\nfunction forceCluster(nodes: SyncNode[], strength: number) {\n return (alpha: number) => {\n const cx = new Map<string, number>();\n const cy = new Map<string, number>();\n const count = new Map<string, number>();\n\n for (const node of nodes) {\n if (!node.community) continue;\n const c = node.community;\n cx.set(c, (cx.get(c) ?? 0) + (node.x ?? 0));\n cy.set(c, (cy.get(c) ?? 0) + (node.y ?? 0));\n count.set(c, (count.get(c) ?? 0) + 1);\n }\n\n for (const [c, n] of count) {\n cx.set(c, cx.get(c)! / n);\n cy.set(c, cy.get(c)! / n);\n }\n\n const k = strength * alpha;\n for (const node of nodes) {\n if (!node.community) continue;\n const targetX = cx.get(node.community)!;\n const targetY = cy.get(node.community)!;\n node.vx = (node.vx ?? 0) + (targetX - (node.x ?? 0)) * k;\n node.vy = (node.vy ?? 0) + (targetY - (node.y ?? 0)) * k;\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// SimulationManager\n// ---------------------------------------------------------------------------\n\ntype TickCallback = (positions: Array<{ id: string; x: number; y: number }>, alpha: number) => void;\n\ntype SettledCallback = () => void;\n\nexport class SimulationManager {\n private worker: Worker | null = null;\n private syncSim: Simulation<SyncNode, undefined> | null = null;\n private syncNodes: SyncNode[] = [];\n private syncNodeMap: Map<string, SyncNode> = new Map();\n private tickCb: TickCallback | null = null;\n private settledCb: SettledCallback | null = null;\n private destroyed = false;\n private syncRafId: number | null = null;\n\n // Stored for worker->sync fallback\n private initNodes: SimNode[] = [];\n private initEdges: SimEdge[] = [];\n private initConfig: WorkerSimulationConfig | null = null;\n\n private constructor() {}\n\n /**\n * Create a SimulationManager. Uses Web Worker for large graphs,\n * synchronous fallback for small graphs or when Worker unavailable.\n */\n static create(\n nodes: SimNode[],\n edges: SimEdge[],\n config: WorkerSimulationConfig,\n ): SimulationManager {\n const mgr = new SimulationManager();\n\n const useWorker = typeof Worker !== 'undefined';\n\n if (useWorker) {\n mgr.initWorker(nodes, edges, config);\n } else {\n mgr.initSync(nodes, edges, config);\n }\n\n return mgr;\n }\n\n /** Register a callback for position updates. */\n onTick(cb: TickCallback): void {\n this.tickCb = cb;\n }\n\n /** Register a callback for when the simulation has settled. */\n onSettled(cb: SettledCallback): void {\n this.settledCb = cb;\n }\n\n /** Reheat the simulation. */\n reheat(alpha?: number): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'reheat', alpha });\n } else if (this.syncSim) {\n this.syncSim.alpha(alpha ?? 0.3).restart();\n this.runSyncTicks();\n }\n }\n\n /** Pin a node to fixed x/y coordinates. */\n pinNode(id: string, x: number, y: number): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'pin', nodeId: id, x, y });\n } else {\n const node = this.syncNodeMap.get(id);\n if (node) {\n node.fx = x;\n node.fy = y;\n }\n }\n }\n\n /** Unpin a node and reheat so forces settle it into equilibrium. */\n unpinNode(id: string): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'unpin', nodeId: id });\n } else {\n const node = this.syncNodeMap.get(id);\n if (node) {\n node.fx = null;\n node.fy = null;\n }\n if (this.syncSim && this.syncSim.alpha() < 0.1) {\n this.syncSim.alpha(0.1).restart();\n this.runSyncTicks();\n }\n }\n }\n\n /** Drag a node (pins it and reheats slightly). */\n dragNode(id: string, x: number, y: number): void {\n if (this.destroyed) return;\n\n if (this.worker) {\n this.worker.postMessage({ type: 'drag', nodeId: id, x, y });\n } else {\n const node = this.syncNodeMap.get(id);\n if (node) {\n node.fx = x;\n node.fy = y;\n }\n if (this.syncSim && this.syncSim.alpha() < 0.1) {\n this.syncSim.alpha(0.1).restart();\n this.runSyncTicks();\n }\n }\n }\n\n /** Tear down the simulation and release resources. */\n destroy(): void {\n this.destroyed = true;\n\n if (this.syncRafId !== null) {\n cancelAnimationFrame(this.syncRafId);\n this.syncRafId = null;\n }\n\n if (this.worker) {\n this.worker.postMessage({ type: 'stop' });\n this.worker.terminate();\n this.worker = null;\n }\n\n if (this.syncSim) {\n this.syncSim.stop();\n this.syncSim = null;\n }\n\n this.tickCb = null;\n this.settledCb = null;\n }\n\n // -------------------------------------------------------------------------\n // Worker path\n // -------------------------------------------------------------------------\n\n private initWorker(nodes: SimNode[], edges: SimEdge[], config: WorkerSimulationConfig): void {\n // Store for fallback if worker fails to load\n this.initNodes = nodes;\n this.initEdges = edges;\n this.initConfig = config;\n\n // Worker URL resolution:\n // - Built dist/ consumers: import.meta.url points at dist/index.js,\n // so ./simulation-worker.js resolves to dist/simulation-worker.js.\n // - Vite dev with source aliases (Ladle): import.meta.url points at\n // src/graph/simulation.ts, so ./simulation-worker.js doesn't exist.\n // The .js worker fails to load, and the onerror handler retries\n // with .ts which Vite transforms on the fly.\n // - Vite production build: detects `new Worker(new URL(...))` and\n // bundles the worker as a hashed .js asset.\n const initMsg = { type: 'init' as const, nodes, edges, config };\n const wireWorker = (worker: Worker) => {\n this.worker = worker;\n\n worker.onmessage = (event: MessageEvent<WorkerOutMessage>) => {\n if (this.destroyed) return;\n const msg = event.data;\n\n switch (msg.type) {\n case 'positions':\n this.tickCb?.(msg.nodes, msg.alpha);\n break;\n case 'settled':\n this.settledCb?.();\n break;\n case 'error':\n console.error('[SimulationManager] Worker error:', msg.message);\n break;\n }\n };\n\n worker.postMessage(initMsg);\n };\n\n try {\n const w = new Worker(new URL('./simulation-worker.js', import.meta.url), {\n type: 'module',\n });\n\n w.onerror = () => {\n // .js failed (likely Vite dev with source aliases). Try .ts.\n // The URL is constructed dynamically to prevent bundlers (Rollup)\n // from statically analyzing it and trying to resolve the .ts file\n // as an asset entry point in production builds.\n if (this.destroyed) return;\n w.terminate();\n this.worker = null;\n\n try {\n const tsUrl = new URL(import.meta.url.replace(/\\/[^/]+$/, '/simulation-worker.ts'));\n const w2 = new Worker(tsUrl, { type: 'module' });\n\n w2.onerror = () => {\n // Both .js and .ts failed - fall back to sync.\n if (this.destroyed) return;\n console.warn('[SimulationManager] Worker failed to load, falling back to sync');\n w2.terminate();\n this.worker = null;\n this.initSync(this.initNodes, this.initEdges, this.initConfig!);\n };\n\n wireWorker(w2);\n } catch {\n console.warn('[SimulationManager] Worker creation failed, using sync fallback');\n this.initSync(this.initNodes, this.initEdges, this.initConfig!);\n }\n };\n\n wireWorker(w);\n } catch {\n // Worker construction failed (e.g. SSR or restrictive CSP)\n console.warn('[SimulationManager] Worker creation failed, using sync fallback');\n this.initSync(nodes, edges, config);\n }\n }\n\n // -------------------------------------------------------------------------\n // Synchronous fallback\n // -------------------------------------------------------------------------\n\n private initSync(nodes: SimNode[], edges: SimEdge[], config: WorkerSimulationConfig): void {\n this.syncNodes = nodes.map((n) => ({\n id: n.id,\n x: n.x,\n y: n.y,\n radius: n.radius,\n community: n.community,\n }));\n\n this.syncNodeMap = new Map(this.syncNodes.map((n) => [n.id, n]));\n\n const linkForce = forceLink(edges.map((e) => ({ ...e })))\n .id((d) => (d as SyncNode).id)\n .distance(config.linkDistance);\n if (config.linkStrength != null) {\n linkForce.strength(config.linkStrength);\n }\n\n const padding = config.collisionPadding ?? 2;\n\n this.syncSim = forceSimulation<SyncNode>(this.syncNodes)\n .force('link', linkForce)\n .force('charge', forceManyBody().strength(config.chargeStrength))\n .force(\n 'collide',\n forceCollide<SyncNode>().radius((d) => d.radius + padding),\n )\n // Weak gravity keeps disconnected nodes from drifting far from center\n .force('gravityX', forceX<SyncNode>(0).strength(0.05))\n .force('gravityY', forceY<SyncNode>(0).strength(0.05))\n .alphaDecay(config.alphaDecay)\n .velocityDecay(config.velocityDecay)\n .stop(); // Don't auto-run; we tick manually\n\n // Center force (default true)\n if (config.centerForce !== false) {\n this.syncSim.force('center', forceCenter(0, 0));\n }\n\n // Add clustering force if configured\n if (config.clustering) {\n const clusterFn = forceCluster(this.syncNodes, config.clustering.strength);\n // d3 calls force functions with (alpha) on each tick\n this.syncSim.force('cluster', clusterFn as unknown as ReturnType<typeof forceCenter>);\n }\n\n // Defer initial delivery: callbacks aren't wired yet at create() time\n this.runSyncTicks(true);\n }\n\n /**\n * Run simulation ticks in batches, yielding to the main thread between\n * batches via requestAnimationFrame. This prevents a multi-second freeze\n * when the sync fallback handles large graphs (1k+ nodes).\n *\n * Each batch runs SYNC_TICKS_PER_BATCH ticks, emits positions for\n * progressive rendering, then schedules the next batch.\n *\n * @param deferred - When true, start via microtask (initial run where\n * callbacks aren't wired yet). Otherwise start immediately.\n */\n private runSyncTicks(deferred = false): void {\n if (!this.syncSim || this.destroyed) return;\n\n // Cancel any in-flight batched run (e.g. from a previous reheat)\n if (this.syncRafId !== null) {\n cancelAnimationFrame(this.syncRafId);\n this.syncRafId = null;\n }\n\n const sim = this.syncSim;\n let tickCount = 0;\n\n const runBatch = () => {\n if (this.destroyed || !this.syncSim) return;\n this.syncRafId = null;\n\n for (let i = 0; i < SYNC_TICKS_PER_BATCH && tickCount < SYNC_MAX_TICKS; i++, tickCount++) {\n sim.tick();\n if (sim.alpha() < 0.001) {\n tickCount = SYNC_MAX_TICKS;\n break;\n }\n }\n\n const positions = this.syncNodes.map((n) => ({\n id: n.id,\n x: n.x ?? 0,\n y: n.y ?? 0,\n }));\n const alpha = sim.alpha();\n const settled = alpha < 0.001 || tickCount >= SYNC_MAX_TICKS;\n\n this.tickCb?.(positions, alpha);\n\n if (settled) {\n this.settledCb?.();\n } else {\n this.syncRafId = requestAnimationFrame(runBatch);\n }\n };\n\n if (deferred) {\n queueMicrotask(runBatch);\n } else {\n runBatch();\n }\n }\n}\n","/**\n * Spatial index for fast node hit-testing.\n *\n * Wraps d3-quadtree to provide findNearest (accounts for node radius)\n * and findInRect queries. Tracks a generation counter to avoid unnecessary\n * rebuilds when positions haven't changed.\n */\n\nimport { type Quadtree, quadtree } from 'd3-quadtree';\nimport type { PositionedNode } from './types';\n\nexport class SpatialIndex {\n private tree: Quadtree<PositionedNode> | null = null;\n private nodes: PositionedNode[] = [];\n private maxRadius = 0;\n private generation = 0;\n\n /** Rebuild the quadtree from the current set of positioned nodes. */\n rebuild(nodes: PositionedNode[]): void {\n this.nodes = nodes;\n this.maxRadius = 0;\n for (const n of nodes) {\n if (n.radius > this.maxRadius) this.maxRadius = n.radius;\n }\n\n this.tree = quadtree<PositionedNode>()\n .x((d) => d.x)\n .y((d) => d.y)\n .addAll(nodes);\n this.generation++;\n }\n\n /** Current generation counter. Increments on each rebuild. */\n getGeneration(): number {\n return this.generation;\n }\n\n /**\n * Find the nearest node to (x, y) within maxDistance.\n * Accounts for node radius: a hit occurs if the point is inside\n * the node circle (distance to center < node.radius), or if the\n * edge-to-edge distance is within maxDistance.\n */\n findNearest(x: number, y: number, maxDistance: number = Infinity): PositionedNode | null {\n if (!this.tree || this.nodes.length === 0) return null;\n\n // The effective search radius for the quadtree needs to include\n // the largest node radius, because we might be \"inside\" a large node\n // whose center is far from our search point.\n const searchRadius = maxDistance + this.maxRadius;\n\n let best: PositionedNode | null = null;\n let bestEffectiveDist = maxDistance + this.maxRadius + 1;\n\n this.tree.visit((node, x0, y0, x1, y1) => {\n // Closest point in this quad to our target\n const closestX = Math.max(x0, Math.min(x, x1));\n const closestY = Math.max(y0, Math.min(y, y1));\n const quadDist = Math.hypot(closestX - x, closestY - y);\n\n // Prune: if the closest edge of this quad is beyond searchRadius, skip\n if (quadDist > searchRadius) return true;\n\n // Check leaf data\n if (!node.length) {\n let current = node;\n do {\n const d = current.data;\n if (d) {\n const dist = Math.hypot(d.x - x, d.y - y);\n // Effective distance: subtract the node's radius.\n // If we're inside the circle, effective distance is 0.\n const effectiveDist = Math.max(0, dist - d.radius);\n if (effectiveDist <= maxDistance && effectiveDist < bestEffectiveDist) {\n bestEffectiveDist = effectiveDist;\n best = d;\n }\n }\n } while ((current = current.next!));\n }\n\n return false;\n });\n\n return best;\n }\n\n /** Find all nodes whose centers fall within the given rectangle. */\n findInRect(x1: number, y1: number, x2: number, y2: number): PositionedNode[] {\n if (!this.tree) return [];\n\n const minX = Math.min(x1, x2);\n const minY = Math.min(y1, y2);\n const maxX = Math.max(x1, x2);\n const maxY = Math.max(y1, y2);\n\n const results: PositionedNode[] = [];\n\n this.tree.visit((node, qx0, qy0, qx1, qy1) => {\n // If quad doesn't overlap the search rect, skip\n if (qx0 > maxX || qx1 < minX || qy0 > maxY || qy1 < minY) {\n return true;\n }\n\n // Check leaf nodes\n if (!node.length) {\n let current = node;\n do {\n const d = current.data;\n if (d && d.x >= minX && d.x <= maxX && d.y >= minY && d.y <= maxY) {\n results.push(d);\n }\n } while ((current = current.next!));\n }\n\n return false;\n });\n\n return results;\n }\n}\n","/**\n * Resize observer: thin wrapper around ResizeObserver with debounce.\n *\n * Watches a container element for size changes and calls back with\n * the new width and height. Debounced at ~60fps (16ms) to avoid\n * excessive re-renders during drag resizes.\n */\n\nconst DEBOUNCE_MS = 16;\n\n/**\n * Observe a container element for size changes.\n *\n * @param container - The element to watch.\n * @param callback - Called with (width, height) when size changes.\n * @returns A cleanup function that disconnects the observer.\n */\nexport function observeResize(\n container: HTMLElement,\n callback: (width: number, height: number) => void,\n): () => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const observer = new ResizeObserver((entries) => {\n // Debounce to ~60fps\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n callback(width, height);\n }\n timeoutId = null;\n }, DEBOUNCE_MS);\n });\n\n observer.observe(container);\n\n return () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n observer.disconnect();\n };\n}\n","/**\n * Tooltip manager: creates and positions a floating tooltip element.\n *\n * Shows tooltip content near the mouse/touch position with viewport\n * edge avoidance via @floating-ui/dom. Touch support via tap-to-show,\n * tap-outside-to-hide.\n */\n\nimport { computePosition, flip, offset, shift } from '@floating-ui/dom';\nimport type { TooltipContent } from '@opendata-ai/openchart-core';\n\nexport interface TooltipManager {\n /** Show the tooltip with content at a given position. */\n show(content: TooltipContent, x: number, y: number): void;\n /** Hide the tooltip. */\n hide(): void;\n /** Remove the tooltip element and clean up event listeners. */\n destroy(): void;\n}\n\nconst TOOLTIP_OFFSET = 12;\n\n/**\n * Create a tooltip manager attached to a container element.\n *\n * The manager creates a floating div positioned relative to the container.\n * Content is rendered as a title line with optional color indicator,\n * followed by a compact list of field-value pairs.\n *\n * @param container - The parent element for the tooltip.\n * @returns TooltipManager with show/hide/destroy methods.\n */\nexport function createTooltipManager(container: HTMLElement): TooltipManager {\n const tooltip = document.createElement('div');\n tooltip.className = 'oc-tooltip';\n tooltip.setAttribute('role', 'tooltip');\n\n container.style.position = container.style.position || 'relative';\n container.appendChild(tooltip);\n\n // Track last content to skip innerHTML when only position changes\n let lastContentKey = '';\n // Generation counter to discard stale async position callbacks\n let currentPositionId = 0;\n\n // Hide on tap-outside for touch devices\n const handleDocumentTouch = (e: Event): void => {\n if (!container.contains(e.target as Node)) {\n hide();\n }\n };\n document.addEventListener('touchstart', handleDocumentTouch);\n\n function show(content: TooltipContent, x: number, y: number): void {\n // Fast content identity check: title + field count + first/last field values\n const contentKey = `${content.title}|${content.fields.length}|${content.fields[0]?.value}|${content.fields[content.fields.length - 1]?.value}`;\n\n if (contentKey !== lastContentKey) {\n lastContentKey = contentKey;\n\n let html = '';\n\n // Title row: optional color dot + title text\n if (content.title) {\n const titleColor = content.fields.find((f) => f.color)?.color;\n html += '<div class=\"oc-tooltip-header\">';\n if (titleColor) {\n html += `<span class=\"oc-tooltip-dot\" style=\"background:${esc(titleColor)}\"></span>`;\n }\n html += `<span class=\"oc-tooltip-title\">${esc(content.title)}</span>`;\n html += '</div>';\n }\n\n // Field rows\n if (content.fields.length > 0) {\n html += '<div class=\"oc-tooltip-body\">';\n for (const field of content.fields) {\n html += '<div class=\"oc-tooltip-row\">';\n html += `<span class=\"oc-tooltip-label\">${esc(field.label)}</span>`;\n html += `<span class=\"oc-tooltip-value\">${esc(field.value)}</span>`;\n html += '</div>';\n }\n html += '</div>';\n }\n\n tooltip.innerHTML = html;\n }\n\n tooltip.style.display = 'block';\n\n // Position with viewport-aware edge avoidance via @floating-ui/dom.\n // Uses a virtual element since the reference point is a coordinate,\n // not a DOM element.\n const positionId = ++currentPositionId;\n const virtualRef = {\n getBoundingClientRect() {\n const rect = container.getBoundingClientRect();\n return {\n x: rect.left + x,\n y: rect.top + y,\n width: 0,\n height: 0,\n top: rect.top + y,\n left: rect.left + x,\n right: rect.left + x,\n bottom: rect.top + y,\n };\n },\n };\n\n computePosition(virtualRef, tooltip, {\n placement: 'bottom-start',\n middleware: [offset(TOOLTIP_OFFSET), flip(), shift({ padding: 5 })],\n }).then(({ x: fx, y: fy }) => {\n // Discard stale callbacks from earlier show() calls\n if (positionId !== currentPositionId) return;\n // computePosition returns coordinates relative to the tooltip's offset\n // parent (the container with position: relative), so apply directly.\n tooltip.style.left = `${fx}px`;\n tooltip.style.top = `${fy}px`;\n });\n }\n\n function hide(): void {\n tooltip.style.display = 'none';\n lastContentKey = '';\n }\n\n function destroy(): void {\n document.removeEventListener('touchstart', handleDocumentTouch);\n if (tooltip.parentNode) {\n tooltip.parentNode.removeChild(tooltip);\n }\n }\n\n return { show, hide, destroy };\n}\n\nfunction esc(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n","/**\n * Mount API: the main entry point for vanilla JS usage.\n *\n * createChart() takes a container, spec, and options, compiles the chart,\n * renders it as SVG, sets up responsive resizing, tooltip interaction\n * (mouse/touch/keyboard), keyboard navigation between data points,\n * and returns a ChartInstance with update/resize/export/destroy methods.\n */\n\nimport type {\n Annotation,\n AnnotationOffset,\n ChartEventHandlers,\n ChartLayout,\n ChartSpec,\n ChromeKey,\n CompileOptions,\n DarkMode,\n ElementEdit,\n ElementRef,\n GraphSpec,\n LayerSpec,\n MeasureTextFn,\n RangeAnnotation,\n RefLineAnnotation,\n TextAnnotation,\n ThemeConfig,\n TooltipContent,\n} from '@opendata-ai/openchart-core';\nimport { elementRef, getRepresentativeColor, isLayerSpec } from '@opendata-ai/openchart-core';\nimport { compileChart, compileLayer } from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, setupAnimationCleanup } from './animation';\nimport {\n exportCSV,\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport { observeResize } from './resize-observer';\nimport { renderChartSVG } from './svg-renderer';\nimport { createTextEditOverlay } from './text-edit-overlay';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface MountOptions extends ChartEventHandlers {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting: \"auto\" (system pref), \"force\", or \"off\". */\n darkMode?: DarkMode;\n /** Callback when a data point is clicked. @deprecated Use onMarkClick instead. */\n onDataPointClick?: (data: Record<string, unknown>) => void;\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Initial selected element. */\n selectedElement?: ElementRef;\n}\n\nexport interface UpdateOptions {\n /** Override the selected element after update. When omitted, preserves current selection. */\n selectedElement?: ElementRef;\n}\n\nexport interface ExportOptions extends JPGExportOptions {\n // Extensible for future formats (extends JPGExportOptions which extends PNGExportOptions)\n}\n\nexport interface ChartInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: ChartSpec | LayerSpec | GraphSpec, options?: UpdateOptions): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the chart. */\n export(format: 'svg'): string;\n export(format: 'svg-with-fonts', options?: SVGExportOptions): Promise<string>;\n export(format: 'png', options?: ExportOptions): Promise<Blob>;\n export(format: 'jpg', options?: ExportOptions): Promise<Blob>;\n export(format: 'csv'): string;\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'csv',\n options?: ExportOptions,\n ): string | Promise<Blob> | Promise<string>;\n /** Remove all DOM elements and disconnect observers. */\n destroy(): void;\n /** The current compiled layout (for hooks / debugging). */\n readonly layout: ChartLayout;\n /** Get the currently selected element, or null if none. */\n getSelectedElement(): ElementRef | null;\n /** Programmatically select an element. Silent no-op if element not found. */\n select(ref: ElementRef): void;\n /** Deselect the current element. */\n deselect(): void;\n /** Whether inline text editing is active. */\n readonly isEditing: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n // \"auto\": check system preference\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// measureText via hidden canvas\n// ---------------------------------------------------------------------------\n\nfunction createMeasureText(): MeasureTextFn {\n let canvas: HTMLCanvasElement | null = null;\n let ctx: CanvasRenderingContext2D | null = null;\n\n return (\n text: string,\n fontSize: number,\n fontWeight?: number,\n ): { width: number; height: number } => {\n if (!canvas) {\n canvas = document.createElement('canvas');\n ctx = canvas.getContext('2d');\n }\n if (!ctx) {\n // Fallback: heuristic estimation\n return { width: text.length * fontSize * 0.6, height: fontSize * 1.2 };\n }\n\n const weight = fontWeight ?? 400;\n ctx.font = `${weight} ${fontSize}px Inter, sans-serif`;\n const metrics = ctx.measureText(text);\n return {\n width: metrics.width,\n height: fontSize * 1.2,\n };\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tooltip event wiring\n// ---------------------------------------------------------------------------\n\n/**\n * Wire tooltip events on mark elements inside an SVG.\n * Returns a cleanup function to remove all listeners.\n */\nfunction wireTooltipEvents(\n svg: SVGElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n): () => void {\n const markElements = svg.querySelectorAll('[data-mark-id]');\n const cleanups: Array<() => void> = [];\n\n for (const el of markElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = tooltipDescriptors.get(markId);\n if (!content) continue;\n\n // Mouse enter -> show tooltip\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n };\n\n // Mouse move -> reposition tooltip\n const handleMouseMove = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n };\n\n // Mouse leave -> hide tooltip\n const handleMouseLeave = () => {\n tooltipManager.hide();\n };\n\n // Touch: tap to show\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length > 0) {\n const touch = touchEvent.touches[0];\n const svgRect = svg.getBoundingClientRect();\n const x = touch.clientX - svgRect.left;\n const y = touch.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('touchstart', handleTouchStart);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('touchstart', handleTouchStart);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Voronoi overlay tooltip wiring (nearest-point lookup for line/area charts)\n// ---------------------------------------------------------------------------\n\n/** A single data point with pixel coordinates, datum, and pre-computed tooltip. */\ninterface VoronoiPoint {\n x: number;\n y: number;\n datum: Record<string, unknown>;\n tooltip?: TooltipContent;\n color: string;\n}\n\n/**\n * Collect all dataPoints from line and area marks for nearest-point lookup.\n */\nfunction collectVoronoiPoints(layout: ChartLayout): VoronoiPoint[] {\n const points: VoronoiPoint[] = [];\n for (const mark of layout.marks) {\n if ((mark.type === 'line' || mark.type === 'area') && mark.dataPoints) {\n const color = mark.type === 'line' ? mark.stroke : getRepresentativeColor(mark.fill);\n for (const dp of mark.dataPoints) {\n points.push({ ...dp, color });\n }\n }\n }\n return points;\n}\n\n/**\n * Find the nearest VoronoiPoint to a given (x, y) position using linear scan.\n * Returns null if no points exist.\n */\nfunction findNearestPoint(points: VoronoiPoint[], x: number, y: number): VoronoiPoint | null {\n if (points.length === 0) return null;\n\n let nearest = points[0];\n let minDist = (points[0].x - x) ** 2 + (points[0].y - y) ** 2;\n\n for (let i = 1; i < points.length; i++) {\n const dist = (points[i].x - x) ** 2 + (points[i].y - y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n nearest = points[i];\n }\n }\n\n return nearest;\n}\n\n/**\n * Wire voronoi overlay tooltip events for line/area charts.\n * Uses a transparent overlay rect with nearest-point lookup instead of\n * per-point event listeners, eliminating DOM bloat.\n * Returns a cleanup function.\n */\nfunction wireVoronoiTooltipEvents(\n svg: SVGElement,\n layout: ChartLayout,\n tooltipManager: TooltipManager,\n): () => void {\n const overlay = svg.querySelector('[data-voronoi-overlay]');\n if (!overlay) return () => {};\n\n const voronoiPoints = collectVoronoiPoints(layout);\n if (voronoiPoints.length === 0) return () => {};\n\n const cleanups: Array<() => void> = [];\n\n const handleMouseMove = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgEl = svg as unknown as SVGSVGElement;\n const svgRect = svgEl.getBoundingClientRect();\n const viewBox = svgEl.viewBox?.baseVal;\n\n // Convert client coordinates to SVG viewBox coordinates\n const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;\n const svgX = (mouseEvent.clientX - svgRect.left) * scaleX;\n const svgY = (mouseEvent.clientY - svgRect.top) * scaleY;\n\n const nearest = findNearestPoint(voronoiPoints, svgX, svgY);\n if (!nearest?.tooltip) return;\n\n // Show tooltip at the mouse position (relative to container, not SVG viewBox)\n const containerX = mouseEvent.clientX - svgRect.left;\n const containerY = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(nearest.tooltip, containerX, containerY);\n };\n\n const handleMouseLeave = () => {\n tooltipManager.hide();\n };\n\n // Touch support\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length > 0) {\n const touch = touchEvent.touches[0];\n const svgEl = svg as unknown as SVGSVGElement;\n const svgRect = svgEl.getBoundingClientRect();\n const viewBox = svgEl.viewBox?.baseVal;\n\n const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;\n const svgX = (touch.clientX - svgRect.left) * scaleX;\n const svgY = (touch.clientY - svgRect.top) * scaleY;\n\n const nearest = findNearestPoint(voronoiPoints, svgX, svgY);\n if (!nearest?.tooltip) return;\n\n const containerX = touch.clientX - svgRect.left;\n const containerY = touch.clientY - svgRect.top;\n tooltipManager.show(nearest.tooltip, containerX, containerY);\n }\n };\n\n overlay.addEventListener('mousemove', handleMouseMove);\n overlay.addEventListener('mouseleave', handleMouseLeave);\n overlay.addEventListener('touchstart', handleTouchStart);\n\n cleanups.push(() => {\n overlay.removeEventListener('mousemove', handleMouseMove);\n overlay.removeEventListener('mouseleave', handleMouseLeave);\n overlay.removeEventListener('touchstart', handleTouchStart);\n });\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Chart event wiring (click, hover, leave on marks; legend toggle; annotation click)\n// ---------------------------------------------------------------------------\n\n/**\n * Build a map from data-mark-id to { datum, series } so event handlers\n * can look up the data row associated with a clicked/hovered mark element.\n */\nfunction buildMarkDataMap(\n layout: ChartLayout,\n): Map<string, { datum: Record<string, unknown>; series?: string }> {\n const map = new Map<string, { datum: Record<string, unknown>; series?: string }>();\n\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n switch (mark.type) {\n case 'line':\n map.set(`line-${mark.seriesKey ?? i}`, {\n // For line marks, data is an array. Use the first row as representative.\n datum: mark.data[0] ?? {},\n series: mark.seriesKey,\n });\n break;\n case 'area':\n map.set(`area-${mark.seriesKey ?? i}`, {\n datum: mark.data[0] ?? {},\n series: mark.seriesKey,\n });\n break;\n case 'rect':\n map.set(`rect-${i}`, { datum: mark.data });\n break;\n case 'arc':\n map.set(`arc-${i}`, { datum: mark.data });\n break;\n case 'point':\n map.set(`point-${i}`, { datum: mark.data });\n break;\n }\n }\n\n return map;\n}\n\n/**\n * Wire chart event handlers (onMarkClick, onMarkHover, onMarkLeave) to mark\n * elements, onLegendToggle to legend entries, and onAnnotationClick to annotation\n * elements inside an SVG.\n *\n * Returns a cleanup function to remove all listeners.\n */\nfunction wireChartEvents(\n svg: SVGElement,\n layout: ChartLayout,\n specAnnotations: import('@opendata-ai/openchart-core').Annotation[],\n handlers: ChartEventHandlers,\n): () => void {\n const cleanups: Array<() => void> = [];\n const markDataMap = buildMarkDataMap(layout);\n\n // Wire mark click/hover/leave events\n if (handlers.onMarkClick || handlers.onMarkHover || handlers.onMarkLeave) {\n const markElements = svg.querySelectorAll('[data-mark-id]');\n\n for (const el of markElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const markInfo = markDataMap.get(markId);\n if (!markInfo) continue;\n\n const series = markInfo.series ?? el.getAttribute('data-series') ?? undefined;\n\n if (handlers.onMarkClick) {\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n handlers.onMarkClick!({\n datum: markInfo.datum,\n series,\n position: {\n x: mouseEvent.clientX - svgRect.left,\n y: mouseEvent.clientY - svgRect.top,\n },\n event: mouseEvent,\n });\n };\n el.addEventListener('click', handleClick);\n cleanups.push(() => el.removeEventListener('click', handleClick));\n }\n\n if (handlers.onMarkHover) {\n const handleEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n handlers.onMarkHover!({\n datum: markInfo.datum,\n series,\n position: {\n x: mouseEvent.clientX - svgRect.left,\n y: mouseEvent.clientY - svgRect.top,\n },\n event: mouseEvent,\n });\n };\n el.addEventListener('mouseenter', handleEnter);\n cleanups.push(() => el.removeEventListener('mouseenter', handleEnter));\n }\n\n if (handlers.onMarkLeave) {\n const handleLeave = () => {\n handlers.onMarkLeave!();\n };\n el.addEventListener('mouseleave', handleLeave);\n cleanups.push(() => el.removeEventListener('mouseleave', handleLeave));\n }\n }\n }\n\n // Wire annotation click events\n if (handlers.onAnnotationClick) {\n const annotationElements = svg.querySelectorAll('.oc-annotation');\n\n for (let i = 0; i < annotationElements.length; i++) {\n const el = annotationElements[i];\n const specAnnotation = specAnnotations[i];\n if (!specAnnotation) continue;\n\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n handlers.onAnnotationClick!(specAnnotation, mouseEvent);\n };\n\n el.addEventListener('click', handleClick);\n cleanups.push(() => el.removeEventListener('click', handleClick));\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Shared drag handler utility\n// ---------------------------------------------------------------------------\n\ninterface DragConfig {\n element: SVGElement;\n svg: SVGSVGElement;\n onMove: (dx: number, dy: number) => void;\n onEnd: (dx: number, dy: number, moved: boolean) => void;\n setDragging: (dragging: boolean) => void;\n threshold?: number; // default: 3\n}\n\n/**\n * Reusable drag handler for SVG elements.\n * Handles mouse and touch events, viewBox scaling, threshold detection,\n * click suppression after drag, and cursor state.\n *\n * Returns a cleanup function that removes all listeners.\n */\nfunction createDragHandler(config: DragConfig): () => void {\n const { element, svg, onMove, onEnd, setDragging, threshold = 3 } = config;\n const cleanups: Array<() => void> = [];\n\n // Track active document listeners so cleanup can remove them mid-drag\n let activeDocMouseMove: ((e: MouseEvent) => void) | null = null;\n let activeDocMouseUp: ((e: MouseEvent) => void) | null = null;\n let activeDocTouchMove: ((e: TouchEvent) => void) | null = null;\n let activeDocTouchEnd: ((e: TouchEvent) => void) | null = null;\n let activeDocTouchCancel: ((e: TouchEvent) => void) | null = null;\n\n function getScale(): { scaleX: number; scaleY: number } {\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n return {\n scaleX: viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1,\n scaleY: viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1,\n };\n }\n\n function startDrag(startX: number, startY: number): void {\n setDragging(true);\n const { scaleX, scaleY } = getScale();\n\n element.style.cursor = 'grabbing';\n // Prevent text selection during drag\n svg.style.userSelect = 'none';\n\n const handleMove = (clientX: number, clientY: number) => {\n const dx = (clientX - startX) * scaleX;\n const dy = (clientY - startY) * scaleY;\n onMove(dx, dy);\n };\n\n const cleanupDocListeners = () => {\n if (activeDocMouseMove) {\n document.removeEventListener('mousemove', activeDocMouseMove);\n activeDocMouseMove = null;\n }\n if (activeDocMouseUp) {\n document.removeEventListener('mouseup', activeDocMouseUp);\n activeDocMouseUp = null;\n }\n if (activeDocTouchMove) {\n document.removeEventListener('touchmove', activeDocTouchMove);\n activeDocTouchMove = null;\n }\n if (activeDocTouchEnd) {\n document.removeEventListener('touchend', activeDocTouchEnd);\n activeDocTouchEnd = null;\n }\n if (activeDocTouchCancel) {\n document.removeEventListener('touchcancel', activeDocTouchCancel);\n activeDocTouchCancel = null;\n }\n };\n\n const handleEnd = (clientX: number, clientY: number) => {\n const dx = (clientX - startX) * scaleX;\n const dy = (clientY - startY) * scaleY;\n const moved = Math.abs(dx) > threshold || Math.abs(dy) > threshold;\n\n onEnd(dx, dy, moved);\n\n // Suppress click if drag actually moved\n if (moved) {\n element.addEventListener(\n 'click',\n (clickE) => {\n clickE.stopPropagation();\n },\n { capture: true, once: true },\n );\n }\n\n element.style.cursor = 'grab';\n svg.style.userSelect = '';\n\n cleanupDocListeners();\n setDragging(false);\n };\n\n // Mouse listeners\n const onMouseMove = (moveEvent: MouseEvent) => {\n handleMove(moveEvent.clientX, moveEvent.clientY);\n };\n const onMouseUp = (upEvent: MouseEvent) => {\n handleEnd(upEvent.clientX, upEvent.clientY);\n };\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n activeDocMouseMove = onMouseMove;\n activeDocMouseUp = onMouseUp;\n\n // Touch listeners\n const onTouchMove = (moveEvent: TouchEvent) => {\n if (moveEvent.touches.length > 0) {\n moveEvent.preventDefault();\n handleMove(moveEvent.touches[0].clientX, moveEvent.touches[0].clientY);\n }\n };\n const onTouchEnd = (endEvent: TouchEvent) => {\n const touch = endEvent.changedTouches[0];\n if (touch) {\n handleEnd(touch.clientX, touch.clientY);\n } else {\n handleEnd(startX, startY);\n }\n };\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n document.addEventListener('touchend', onTouchEnd);\n document.addEventListener('touchcancel', onTouchEnd);\n activeDocTouchMove = onTouchMove;\n activeDocTouchEnd = onTouchEnd;\n activeDocTouchCancel = onTouchEnd;\n }\n\n // Mouse down handler\n const handleMouseDown = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n mouseEvent.preventDefault();\n startDrag(mouseEvent.clientX, mouseEvent.clientY);\n };\n\n // Touch start handler\n const handleTouchStart = (e: Event) => {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length === 1) {\n touchEvent.preventDefault();\n startDrag(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n }\n };\n\n element.addEventListener('mousedown', handleMouseDown);\n element.addEventListener('touchstart', handleTouchStart, { passive: false });\n cleanups.push(() => {\n element.removeEventListener('mousedown', handleMouseDown);\n element.removeEventListener('touchstart', handleTouchStart);\n });\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n // Clean up any active document listeners (mid-drag unmount)\n if (activeDocMouseMove) {\n document.removeEventListener('mousemove', activeDocMouseMove);\n activeDocMouseMove = null;\n }\n if (activeDocMouseUp) {\n document.removeEventListener('mouseup', activeDocMouseUp);\n activeDocMouseUp = null;\n }\n if (activeDocTouchMove) {\n document.removeEventListener('touchmove', activeDocTouchMove);\n activeDocTouchMove = null;\n }\n if (activeDocTouchEnd) {\n document.removeEventListener('touchend', activeDocTouchEnd);\n activeDocTouchEnd = null;\n }\n if (activeDocTouchCancel) {\n document.removeEventListener('touchcancel', activeDocTouchCancel);\n activeDocTouchCancel = null;\n }\n // Restore user-select in case of mid-drag cleanup\n svg.style.userSelect = '';\n };\n}\n\n// ---------------------------------------------------------------------------\n// Annotation drag editing\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag-to-reposition on text annotation labels.\n * Only activates for text annotations (not range or refline).\n * During drag, applies a CSS transform for real-time visual feedback and\n * counter-adjusts straight connector endpoints so the data-point end stays fixed.\n * On mouseup, fires the callback with the updated offset values.\n *\n * Returns a cleanup function to remove all listeners.\n */\nfunction wireAnnotationDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onAnnotationEdit:\n | ((annotation: TextAnnotation, updatedOffset: AnnotationOffset) => void)\n | undefined,\n onEdit: ((edit: ElementEdit) => void) | undefined,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const annotationElements = svg.querySelectorAll('.oc-annotation-text');\n const cleanups: Array<() => void> = [];\n\n for (const el of annotationElements) {\n const indexStr = el.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation || specAnnotation.type !== 'text') continue;\n\n const textAnnotation = specAnnotation as TextAnnotation;\n const annotationG = el as SVGGElement;\n\n // Visual affordance: show grab cursor\n annotationG.style.cursor = 'grab';\n\n // Stash connector info for real-time updates during drag\n const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const origX2 = connectorLine ? Number(connectorLine.getAttribute('x2')) : 0;\n const origY2 = connectorLine ? Number(connectorLine.getAttribute('y2')) : 0;\n\n // For curved connectors, stash path/polygon elements to hide during drag\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n const arrowhead = annotationG.querySelector('polygon.oc-annotation-connector');\n const hasCurvedConnector = curvedPath !== null;\n\n const origDx = textAnnotation.offset?.dx ?? 0;\n const origDy = textAnnotation.offset?.dy ?? 0;\n\n const cleanup = createDragHandler({\n element: annotationG,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n // Move the entire annotation group\n annotationG.setAttribute('transform', `translate(${dx}, ${dy})`);\n\n // For straight connectors, counter-adjust the data-point end\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2 - dx));\n connectorLine.setAttribute('y2', String(origY2 - dy));\n }\n\n // Hide curved connector elements during drag\n if (hasCurvedConnector) {\n if (curvedPath) curvedPath.setAttribute('display', 'none');\n if (arrowhead) arrowhead.setAttribute('display', 'none');\n }\n },\n onEnd: (dx, dy, moved) => {\n // Clean up visual state\n annotationG.removeAttribute('transform');\n\n // Restore straight connector to original values\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2));\n connectorLine.setAttribute('y2', String(origY2));\n }\n\n // Restore curved connector elements\n if (hasCurvedConnector) {\n if (curvedPath) curvedPath.removeAttribute('display');\n if (arrowhead) arrowhead.removeAttribute('display');\n }\n\n if (moved) {\n const newOffset: AnnotationOffset = {\n dx: origDx + dx,\n dy: origDy + dy,\n };\n // Fire legacy callback\n onAnnotationEdit?.(textAnnotation, newOffset);\n // Fire unified edit callback\n onEdit?.({ type: 'annotation', annotation: textAnnotation, offset: newOffset });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Connector endpoint drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on connector endpoint handles for text annotations.\n * Dynamically creates invisible handle circles at connector endpoints\n * so they only exist when editing is active (not in every chart).\n * During drag, updates the handle position and the connector line endpoints.\n * On end, fires onEdit with the accumulated endpoint offset.\n *\n * Shows handles on hover over the parent annotation group.\n * Returns a cleanup function that removes handles and all listeners.\n */\nfunction wireConnectorEndpointDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const SVG_NS = 'http://www.w3.org/2000/svg';\n const cleanups: Array<() => void> = [];\n const annotationGroups = svg.querySelectorAll('.oc-annotation-text');\n\n for (const el of annotationGroups) {\n const annotationG = el as SVGGElement;\n const indexStr = annotationG.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation || specAnnotation.type !== 'text') continue;\n\n const textAnnotation = specAnnotation as TextAnnotation;\n\n // Find connector line or curved connector to determine endpoints\n const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n if (!connectorLine && !curvedPath) continue;\n\n // Determine connector endpoint positions from the connector element\n let fromX: number, fromY: number, toX: number, toY: number;\n if (connectorLine) {\n fromX = Number(connectorLine.getAttribute('x1')) || 0;\n fromY = Number(connectorLine.getAttribute('y1')) || 0;\n toX = Number(connectorLine.getAttribute('x2')) || 0;\n toY = Number(connectorLine.getAttribute('y2')) || 0;\n } else {\n // For curved connectors, get positions from the path data\n // The path starts at M x y, so parse the first coordinates\n const pathD = curvedPath!.getAttribute('d') ?? '';\n const mMatch = pathD.match(/M\\s*([\\d.e+-]+)\\s+([\\d.e+-]+)/);\n fromX = mMatch ? Number(mMatch[1]) : 0;\n fromY = mMatch ? Number(mMatch[2]) : 0;\n // For curved connectors, the arrow polygon has the target\n const arrowhead = annotationG.querySelector('polygon.oc-annotation-connector');\n const points = arrowhead?.getAttribute('points') ?? '';\n const firstPoint = points.split(' ')[0] ?? '0,0';\n const [px, py] = firstPoint.split(',');\n toX = Number(px) || 0;\n toY = Number(py) || 0;\n }\n\n // Create handles dynamically\n const endpoints: Array<{ name: 'from' | 'to'; cx: number; cy: number }> = [\n { name: 'from', cx: fromX, cy: fromY },\n { name: 'to', cx: toX, cy: toY },\n ];\n\n const createdHandles: SVGCircleElement[] = [];\n\n for (const ep of endpoints) {\n // Skip endpoints with invalid coordinates to prevent NaN in SVG attributes\n if (!Number.isFinite(ep.cx) || !Number.isFinite(ep.cy)) continue;\n\n const handleEl = document.createElementNS(SVG_NS, 'circle') as SVGCircleElement;\n handleEl.setAttribute('class', 'oc-connector-handle');\n handleEl.setAttribute('data-endpoint', ep.name);\n handleEl.setAttribute('cx', String(ep.cx));\n handleEl.setAttribute('cy', String(ep.cy));\n handleEl.setAttribute('r', '4');\n handleEl.setAttribute('opacity', '0');\n handleEl.setAttribute('fill', 'currentColor');\n handleEl.setAttribute('stroke', 'currentColor');\n annotationG.appendChild(handleEl);\n createdHandles.push(handleEl);\n\n const origCx = ep.cx;\n const origCy = ep.cy;\n\n // Prevent parent annotation drag from firing\n const stopProp = (e: Event) => {\n e.stopPropagation();\n };\n handleEl.addEventListener('mousedown', stopProp);\n handleEl.addEventListener('touchstart', stopProp);\n cleanups.push(() => {\n handleEl.removeEventListener('mousedown', stopProp);\n handleEl.removeEventListener('touchstart', stopProp);\n });\n\n const cleanup = createDragHandler({\n element: handleEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n handleEl.setAttribute('cx', String(origCx + dx));\n handleEl.setAttribute('cy', String(origCy + dy));\n\n if (connectorLine) {\n if (ep.name === 'from') {\n connectorLine.setAttribute('x1', String(origCx + dx));\n connectorLine.setAttribute('y1', String(origCy + dy));\n } else {\n connectorLine.setAttribute('x2', String(origCx + dx));\n connectorLine.setAttribute('y2', String(origCy + dy));\n }\n }\n },\n onEnd: (dx, dy, moved) => {\n handleEl.setAttribute('cx', String(origCx));\n handleEl.setAttribute('cy', String(origCy));\n\n if (connectorLine) {\n if (ep.name === 'from') {\n connectorLine.setAttribute('x1', String(origCx));\n connectorLine.setAttribute('y1', String(origCy));\n } else {\n connectorLine.setAttribute('x2', String(origCx));\n connectorLine.setAttribute('y2', String(origCy));\n }\n }\n\n if (moved) {\n const existingOffset = textAnnotation.connectorOffset?.[ep.name];\n const origEndDx = existingOffset?.dx ?? 0;\n const origEndDy = existingOffset?.dy ?? 0;\n onEdit({\n type: 'annotation-connector',\n annotation: textAnnotation,\n endpoint: ep.name,\n offset: { dx: origEndDx + dx, dy: origEndDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n // Wire hover to show/hide handles\n const showHandles = () => {\n for (const h of createdHandles) {\n h.setAttribute('opacity', '0.6');\n }\n };\n const hideHandles = () => {\n for (const h of createdHandles) {\n h.setAttribute('opacity', '0');\n }\n };\n\n annotationG.addEventListener('mouseenter', showHandles);\n annotationG.addEventListener('mouseleave', hideHandles);\n cleanups.push(() => {\n annotationG.removeEventListener('mouseenter', showHandles);\n annotationG.removeEventListener('mouseleave', hideHandles);\n // Remove dynamically created handles\n for (const h of createdHandles) {\n h.remove();\n }\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Range/refline annotation label drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on range and refline annotation labels.\n * On drag end, fires onEdit with the label offset.\n * Returns a cleanup function.\n */\nfunction wireAnnotationLabelDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const cleanups: Array<() => void> = [];\n\n // Target range and refline annotation labels\n const selectors = [\n '.oc-annotation-range .oc-annotation-label',\n '.oc-annotation-refline .oc-annotation-label',\n ];\n\n for (const selector of selectors) {\n const labels = svg.querySelectorAll(selector);\n\n for (const label of labels) {\n const annotationG = label.closest('.oc-annotation') as SVGGElement | null;\n if (!annotationG) continue;\n\n const indexStr = annotationG.getAttribute('data-annotation-index');\n if (indexStr === null) continue;\n\n const index = Number(indexStr);\n const specAnnotation = specAnnotations[index];\n if (!specAnnotation) continue;\n\n const labelEl = label as SVGTextElement;\n labelEl.style.cursor = 'grab';\n\n const isRange = specAnnotation.type === 'range';\n const existingLabelOffset = isRange\n ? (specAnnotation as RangeAnnotation).labelOffset\n : (specAnnotation as RefLineAnnotation).labelOffset;\n const origLabelDx = existingLabelOffset?.dx ?? 0;\n const origLabelDy = existingLabelOffset?.dy ?? 0;\n\n const cleanup = createDragHandler({\n element: labelEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n if (isRange) {\n onEdit({\n type: 'range-label',\n annotation: specAnnotation as RangeAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n } else {\n onEdit({\n type: 'refline-label',\n annotation: specAnnotation as RefLineAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n }\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Chrome text drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on chrome text elements (title, subtitle, source, byline, footer).\n * On drag end, fires onEdit with the chrome key, text, and offset.\n * Returns a cleanup function.\n */\nfunction wireChromeDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const chromeTexts = svg.querySelectorAll('.oc-chrome text[data-chrome-key]');\n const cleanups: Array<() => void> = [];\n\n // Read existing chrome offsets from the spec\n const chromeConfig = 'chrome' in spec ? spec.chrome : undefined;\n\n for (const el of chromeTexts) {\n const textEl = el as SVGTextElement;\n const key = textEl.getAttribute('data-chrome-key') as ChromeKey;\n if (!key) continue;\n\n // Read existing offset for this chrome element\n const chromeEntry = chromeConfig?.[key];\n const existingOffset =\n typeof chromeEntry === 'object' && chromeEntry !== null ? chromeEntry.offset : undefined;\n const origChromeDx = existingOffset?.dx ?? 0;\n const origChromeDy = existingOffset?.dy ?? 0;\n\n textEl.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: textEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (textEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (textEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({\n type: 'chrome',\n key,\n text: textEl.textContent ?? '',\n offset: { dx: origChromeDx + dx, dy: origChromeDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legend drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on the legend group.\n * Click suppression prevents legend toggle from firing after a drag.\n * On drag end, fires onEdit with the legend offset.\n * Returns a cleanup function.\n */\nfunction wireLegendDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const legendG = svg.querySelector('.oc-legend') as SVGGElement | null;\n if (!legendG) return () => {};\n\n const cleanups: Array<() => void> = [];\n\n // Read existing legend offset from the spec\n const legendConfig = 'legend' in spec ? spec.legend : undefined;\n const origLegendDx = legendConfig?.offset?.dx ?? 0;\n const origLegendDy = legendConfig?.offset?.dy ?? 0;\n\n // Set grab cursor on the legend background, not on entry elements\n legendG.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: legendG,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (legendG as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (legendG as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({ type: 'legend', offset: { dx: origLegendDx + dx, dy: origLegendDy + dy } });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Series label drag\n// ---------------------------------------------------------------------------\n\n/**\n * Wire drag on series label elements (.oc-mark-label[data-series]).\n * On drag end, fires onEdit with the series name and offset.\n * Returns a cleanup function.\n */\nfunction wireSeriesLabelDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n const labels = svg.querySelectorAll('.oc-mark-label');\n const cleanups: Array<() => void> = [];\n\n // Read existing label offsets from the spec\n const labelsConfig = 'labels' in spec ? spec.labels : undefined;\n\n for (const label of labels) {\n const labelEl = label as SVGTextElement;\n // Check label itself first, then fall back to the parent mark group's data-series\n const series =\n labelEl.getAttribute('data-series') ??\n labelEl.closest('[data-series]')?.getAttribute('data-series');\n if (!series) continue;\n\n // Read existing offset for this series label\n const existingSeriesOffset = labelsConfig?.offsets?.[series];\n const origSeriesDx = existingSeriesOffset?.dx ?? 0;\n const origSeriesDy = existingSeriesOffset?.dy ?? 0;\n\n labelEl.style.cursor = 'grab';\n\n const cleanup = createDragHandler({\n element: labelEl,\n svg: svg as unknown as SVGSVGElement,\n onMove: (dx, dy) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform =\n `translate(${dx}px, ${dy}px)`;\n },\n onEnd: (dx, dy, moved) => {\n (labelEl as SVGElement & ElementCSSInlineStyle).style.transform = '';\n\n if (moved) {\n onEdit({\n type: 'series-label',\n series,\n offset: { dx: origSeriesDx + dx, dy: origSeriesDy + dy },\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legend interactivity\n// ---------------------------------------------------------------------------\n\n/**\n * Wire click handlers on legend entries to toggle series visibility.\n * Fires onEdit with { type: 'legend-toggle', series, hidden } for each toggle,\n * and optionally calls the legacy onLegendToggle callback.\n * Legend entries for hidden series stay visible but dimmed (opacity 0.3).\n * Returns a cleanup function.\n */\nfunction wireLegendInteraction(\n svg: SVGElement,\n _layout: ChartLayout,\n onLegendToggle?: (series: string, visible: boolean) => void,\n onEdit?: (edit: ElementEdit) => void,\n): () => void {\n const legendEntries = svg.querySelectorAll('[data-legend-index]');\n const cleanups: Array<() => void> = [];\n\n // Track which series are hidden\n const hiddenSeries = new Set<string>();\n\n for (const entry of legendEntries) {\n // Skip overflow indicator entries (\"+N more\")\n if (entry.getAttribute('data-legend-overflow') === 'true') continue;\n\n const handleClick = () => {\n const label = entry.getAttribute('data-legend-label');\n if (!label) return;\n\n if (hiddenSeries.has(label)) {\n hiddenSeries.delete(label);\n entry.setAttribute('opacity', '1');\n entry.setAttribute('aria-label', `${label}: visible`);\n onLegendToggle?.(label, true);\n onEdit?.({ type: 'legend-toggle', series: label, hidden: false });\n } else {\n hiddenSeries.add(label);\n entry.setAttribute('opacity', '0.3');\n entry.setAttribute('aria-label', `${label}: hidden`);\n onLegendToggle?.(label, false);\n onEdit?.({ type: 'legend-toggle', series: label, hidden: true });\n }\n\n // Toggle visibility of marks with matching series.\n // Uses the data-series attribute set by the SVG renderer, which works\n // for all mark types (line, area, rect, arc, point).\n const marks = svg.querySelectorAll('.oc-mark');\n for (const mark of marks) {\n const seriesName = mark.getAttribute('data-series');\n if (!seriesName) continue;\n\n if (hiddenSeries.has(seriesName)) {\n (mark as SVGElement).style.display = 'none';\n } else {\n (mark as SVGElement).style.display = '';\n }\n }\n };\n\n entry.addEventListener('click', handleClick);\n cleanups.push(() => entry.removeEventListener('click', handleClick));\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Keyboard navigation\n// ---------------------------------------------------------------------------\n\n/**\n * Wire keyboard navigation on the SVG element.\n * Arrow keys move focus between mark elements. Enter/Space shows tooltip.\n * Escape hides tooltip. Returns a cleanup function.\n */\nfunction wireKeyboardNav(\n svg: SVGElement,\n container: HTMLElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n layout: ChartLayout,\n): () => void {\n // Make container focusable\n container.setAttribute('tabindex', '0');\n container.setAttribute('aria-roledescription', 'chart');\n container.setAttribute('aria-label', layout.a11y.altText);\n\n // Collect navigable mark elements (those with tooltip content)\n const markElements: SVGElement[] = [];\n const allMarkEls = svg.querySelectorAll('[data-mark-id]');\n for (const el of allMarkEls) {\n const markId = el.getAttribute('data-mark-id');\n if (markId && tooltipDescriptors.has(markId)) {\n markElements.push(el as SVGElement);\n }\n }\n\n let focusIndex = -1;\n\n function highlightMark(index: number): void {\n // Remove previous highlight\n if (focusIndex >= 0 && focusIndex < markElements.length) {\n markElements[focusIndex].classList.remove('oc-mark-focused');\n markElements[focusIndex].removeAttribute('aria-selected');\n }\n\n focusIndex = index;\n\n if (focusIndex >= 0 && focusIndex < markElements.length) {\n const el = markElements[focusIndex];\n el.classList.add('oc-mark-focused');\n el.setAttribute('aria-selected', 'true');\n }\n }\n\n function showTooltipForFocused(): void {\n if (focusIndex < 0 || focusIndex >= markElements.length) return;\n\n const el = markElements[focusIndex];\n const markId = el.getAttribute('data-mark-id');\n if (!markId) return;\n\n const content = tooltipDescriptors.get(markId);\n if (!content) return;\n\n // Position tooltip near the mark element\n const bbox = el.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const x = bbox.left + bbox.width / 2 - containerRect.left;\n const y = bbox.top - containerRect.top;\n tooltipManager.show(content, x, y);\n }\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (markElements.length === 0) return;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowDown': {\n e.preventDefault();\n const next = focusIndex < markElements.length - 1 ? focusIndex + 1 : 0;\n highlightMark(next);\n showTooltipForFocused();\n break;\n }\n case 'ArrowLeft':\n case 'ArrowUp': {\n e.preventDefault();\n const prev = focusIndex > 0 ? focusIndex - 1 : markElements.length - 1;\n highlightMark(prev);\n showTooltipForFocused();\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (focusIndex >= 0) {\n showTooltipForFocused();\n } else if (markElements.length > 0) {\n highlightMark(0);\n showTooltipForFocused();\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n tooltipManager.hide();\n highlightMark(-1);\n break;\n }\n }\n };\n\n container.addEventListener('keydown', handleKeyDown);\n\n return () => {\n container.removeEventListener('keydown', handleKeyDown);\n container.removeAttribute('tabindex');\n container.removeAttribute('aria-roledescription');\n container.removeAttribute('aria-label');\n };\n}\n\n// ---------------------------------------------------------------------------\n// Hidden data table for screen readers\n// ---------------------------------------------------------------------------\n\n/**\n * Create a visually-hidden data table from the chart's a11y fallback data.\n * Returns the table element (append to container) and a cleanup function.\n */\nfunction createScreenReaderTable(\n layout: ChartLayout,\n container: HTMLElement,\n): HTMLTableElement | null {\n const data = layout.a11y.dataTableFallback;\n if (!data || data.length === 0) return null;\n\n const table = document.createElement('table');\n table.className = 'oc-sr-only';\n // Inline critical SR-only styles so the table stays hidden even when the\n // external stylesheet isn't loaded (e.g. CDN / esm.sh usage).\n table.style.position = 'absolute';\n table.style.width = '1px';\n table.style.height = '1px';\n table.style.padding = '0';\n table.style.margin = '-1px';\n table.style.overflow = 'hidden';\n table.style.clipPath = 'inset(50%)';\n table.style.whiteSpace = 'nowrap';\n table.style.borderWidth = '0';\n table.setAttribute('role', 'table');\n table.setAttribute('aria-label', `Data table: ${layout.a11y.altText}`);\n\n // First row is headers\n if (data.length > 0) {\n const thead = document.createElement('thead');\n const headerRow = document.createElement('tr');\n const headers = data[0] as unknown[];\n for (const header of headers) {\n const th = document.createElement('th');\n th.textContent = String(header ?? '');\n th.setAttribute('scope', 'col');\n headerRow.appendChild(th);\n }\n thead.appendChild(headerRow);\n table.appendChild(thead);\n }\n\n // Remaining rows are data\n if (data.length > 1) {\n const tbody = document.createElement('tbody');\n for (let i = 1; i < data.length; i++) {\n const tr = document.createElement('tr');\n const cells = data[i] as unknown[];\n for (const cell of cells) {\n const td = document.createElement('td');\n td.textContent = String(cell ?? '');\n tr.appendChild(td);\n }\n tbody.appendChild(tr);\n }\n table.appendChild(tbody);\n }\n\n container.appendChild(table);\n return table;\n}\n\n// ---------------------------------------------------------------------------\n// Editable element helpers\n// ---------------------------------------------------------------------------\n\n/** CSS for editable hover feedback, injected into the SVG as a <style> element. */\nconst EDITABLE_HOVER_CSS = `\n.oc-editable-hover {\n outline: 1.5px solid rgba(79, 70, 229, 0.35);\n outline-offset: 2px;\n border-radius: 2px;\n}\n`;\n\n/**\n * Inject editable styles into an SVG element and make it focusable.\n * Called when any editing callback is provided.\n */\nfunction makeEditable(svg: SVGElement): void {\n svg.setAttribute('tabindex', '0');\n svg.style.outline = 'none';\n\n // Inject hover style into SVG defs\n const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');\n style.textContent = EDITABLE_HOVER_CSS;\n svg.insertBefore(style, svg.firstChild);\n}\n\n/**\n * Check whether any editing-related callback is provided in the options.\n */\nfunction hasEditingCallbacks(opts?: MountOptions): boolean {\n return !!(opts?.onEdit || opts?.onSelect || opts?.onDeselect || opts?.onTextEdit);\n}\n\n/**\n * Find a DOM element inside the SVG that matches the given ElementRef.\n */\nfunction findElementByRef(svg: SVGElement, ref: ElementRef): SVGElement | null {\n switch (ref.type) {\n case 'annotation': {\n // Prefer id-based lookup when available\n if (ref.id) {\n const byId = svg.querySelector(`[data-annotation-id=\"${ref.id}\"]`);\n if (byId) return byId as SVGElement;\n }\n return svg.querySelector(`[data-annotation-index=\"${ref.index}\"]`) as SVGElement | null;\n }\n case 'chrome':\n return svg.querySelector(`[data-chrome-key=\"${ref.key}\"]`) as SVGElement | null;\n case 'series-label':\n return svg.querySelector(`.oc-mark-label[data-series=\"${ref.series}\"]`) as SVGElement | null;\n case 'legend':\n return svg.querySelector('.oc-legend') as SVGElement | null;\n case 'legend-entry':\n return svg.querySelector(`[data-legend-index=\"${ref.index}\"]`) as SVGElement | null;\n }\n}\n\n/**\n * Build an ElementRef from a DOM element's data attributes.\n * Walks up the tree to find the closest editable ancestor if needed.\n */\nfunction buildElementRef(element: Element, _specAnnotations: Annotation[]): ElementRef | null {\n // Check for annotation\n const annotationEl = element.closest('[data-annotation-index]');\n if (annotationEl) {\n const index = Number(annotationEl.getAttribute('data-annotation-index'));\n const id = annotationEl.getAttribute('data-annotation-id') ?? undefined;\n return elementRef.annotation(index, id);\n }\n\n // Check for chrome\n const chromeEl = element.closest('[data-chrome-key]');\n if (chromeEl) {\n const key = chromeEl.getAttribute('data-chrome-key') as ChromeKey;\n if (key) return elementRef.chrome(key);\n }\n\n // Check for series label\n const seriesLabelEl = element.closest('.oc-mark-label[data-series]');\n if (seriesLabelEl) {\n const series = seriesLabelEl.getAttribute('data-series');\n if (series) return elementRef.seriesLabel(series);\n }\n\n // Check for legend entry\n const legendEntryEl = element.closest('[data-legend-index]');\n if (legendEntryEl) {\n const index = Number(legendEntryEl.getAttribute('data-legend-index'));\n const series = legendEntryEl.getAttribute('data-legend-label') ?? '';\n return elementRef.legendEntry(series, index);\n }\n\n // Check for legend group\n const legendEl = element.closest('.oc-legend');\n if (legendEl) return elementRef.legend();\n\n return null;\n}\n\n/**\n * Get an ordered list of all editable ElementRefs from the current spec and layout.\n * Order: chrome (title, subtitle, source, byline, footer), annotations by index,\n * series labels alphabetical, legend.\n */\nfunction getEditableElements(\n spec: ChartSpec | LayerSpec | GraphSpec,\n layout: ChartLayout,\n): ElementRef[] {\n const refs: ElementRef[] = [];\n\n // Chrome keys in display order\n const chromeKeys: ChromeKey[] = ['title', 'subtitle', 'source', 'byline', 'footer'];\n for (const key of chromeKeys) {\n if (layout.chrome[key]) {\n refs.push(elementRef.chrome(key));\n }\n }\n\n // Annotations by index\n const annotations: Annotation[] =\n 'annotations' in spec && Array.isArray(spec.annotations) ? spec.annotations : [];\n for (let i = 0; i < annotations.length; i++) {\n refs.push(elementRef.annotation(i, annotations[i].id));\n }\n\n // Series labels (alphabetical)\n const seriesLabels: string[] = [];\n for (const mark of layout.marks) {\n if (mark.type === 'line' && mark.label?.visible && mark.seriesKey) {\n seriesLabels.push(mark.seriesKey);\n }\n }\n seriesLabels.sort();\n for (const series of seriesLabels) {\n refs.push(elementRef.seriesLabel(series));\n }\n\n // Legend\n if (layout.legend.entries.length > 0) {\n refs.push(elementRef.legend());\n }\n\n return refs;\n}\n\n/**\n * Check if an ElementRef points to a text-editable element (chrome text or text annotation).\n */\nfunction isTextEditable(ref: ElementRef, specAnnotations: Annotation[]): boolean {\n if (ref.type === 'chrome') return true;\n if (ref.type === 'annotation') {\n const annotation = specAnnotations[ref.index];\n return annotation?.type === 'text';\n }\n return false;\n}\n\n/**\n * Get the current text content for an element ref.\n */\nfunction getElementText(ref: ElementRef, spec: ChartSpec | LayerSpec | GraphSpec): string | null {\n if (ref.type === 'chrome') {\n const chromeConfig = 'chrome' in spec ? spec.chrome : undefined;\n if (!chromeConfig) return null;\n const entry = chromeConfig[ref.key];\n if (typeof entry === 'string') return entry;\n if (typeof entry === 'object' && entry !== null && 'text' in entry) {\n return (entry as { text: string }).text;\n }\n return null;\n }\n if (ref.type === 'annotation') {\n const annotations: Annotation[] =\n 'annotations' in spec && Array.isArray(spec.annotations) ? spec.annotations : [];\n const annotation = annotations[ref.index];\n if (annotation?.type === 'text') return (annotation as TextAnnotation).text ?? null;\n if (annotation?.label) return annotation.label;\n return null;\n }\n return null;\n}\n\n/**\n * Compare two ElementRefs for equality.\n */\nfunction refsEqual(a: ElementRef | null, b: ElementRef | null): boolean {\n if (a === null || b === null) return a === b;\n if (a.type !== b.type) return false;\n switch (a.type) {\n case 'annotation': {\n const bAnno = b as typeof a;\n if (a.id && bAnno.id) return a.id === bAnno.id;\n return a.index === bAnno.index;\n }\n case 'chrome':\n return a.key === (b as typeof a).key;\n case 'series-label':\n return a.series === (b as typeof a).series;\n case 'legend':\n return true;\n case 'legend-entry': {\n const bEntry = b as typeof a;\n return a.index === bEntry.index && a.series === bEntry.series;\n }\n }\n}\n\n/**\n * Render a selection overlay rectangle around a target element.\n * Returns the overlay group element.\n */\nfunction renderSelectionOverlay(\n svg: SVGElement,\n ref: ElementRef,\n layout: ChartLayout,\n): SVGGElement | null {\n const target = findElementByRef(svg, ref);\n if (!target) return null;\n\n const bbox = (target as SVGGraphicsElement).getBBox();\n const padding = 4;\n\n // Resolve accent color from theme\n const accentColor = layout.theme.colors.categorical?.[0] ?? '#4f46e5';\n\n const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n g.setAttribute('class', 'oc-selection-overlay');\n\n const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n rect.setAttribute('x', String(bbox.x - padding));\n rect.setAttribute('y', String(bbox.y - padding));\n rect.setAttribute('width', String(bbox.width + padding * 2));\n rect.setAttribute('height', String(bbox.height + padding * 2));\n rect.setAttribute('rx', '3');\n rect.setAttribute('fill', 'transparent');\n rect.setAttribute('stroke', accentColor);\n rect.setAttribute('stroke-width', '1.5');\n rect.setAttribute('pointer-events', 'none');\n\n g.appendChild(rect);\n svg.appendChild(g);\n\n return g;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a chart instance from a spec and mount it into a container.\n *\n * @param container - The DOM element to render into.\n * @param spec - The visualization spec.\n * @param options - Mount options (theme, darkMode, responsive, etc.).\n * @returns A ChartInstance with update/resize/export/destroy methods.\n */\nexport function createChart(\n container: HTMLElement,\n spec: ChartSpec | LayerSpec | GraphSpec,\n options?: MountOptions,\n): ChartInstance {\n let currentSpec: ChartSpec | LayerSpec | GraphSpec = spec;\n let currentLayout: ChartLayout;\n let svgElement: SVGElement | null = null;\n let tooltipManager: TooltipManager | null = null;\n let disconnectResize: (() => void) | null = null;\n let cleanupTooltipEvents: (() => void) | null = null;\n let cleanupVoronoiEvents: (() => void) | null = null;\n let cleanupKeyboardNav: (() => void) | null = null;\n let cleanupLegend: (() => void) | null = null;\n let cleanupChartEvents: (() => void) | null = null;\n let cleanupAnnotationDrag: (() => void) | null = null;\n let cleanupEditDrags: (() => void) | null = null;\n let cleanupSelection: (() => void) | null = null;\n let cleanupKeyboardEdit: (() => void) | null = null;\n let srTable: HTMLTableElement | null = null;\n let destroyed = false;\n let isDragging = false;\n let pendingRender = false;\n let resizeTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Animation state\n let isFirstRender = true;\n let cleanupAnimations: (() => void) | null = null;\n let pendingResize = false;\n\n // Selection and text editing state\n let selectedElement: ElementRef | null = options?.selectedElement ?? null;\n let overlayElement: SVGGElement | null = null;\n let isTextEditingActive = false;\n let textEditCleanup: (() => void) | null = null;\n\n const measureText = createMeasureText();\n\n function compile(): ChartLayout {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n measureText,\n };\n\n if (isLayerSpec(currentSpec)) {\n return compileLayer(currentSpec as LayerSpec, compileOpts);\n }\n return compileChart(currentSpec as ChartSpec | GraphSpec, compileOpts);\n }\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n /** Get the current spec's annotations array. */\n function getSpecAnnotations(): Annotation[] {\n return 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n }\n\n /** Select an element: render overlay, fire onSelect, update state. */\n function selectElement(ref: ElementRef): void {\n if (!svgElement) return;\n\n // Confirm the target element exists before deselecting the previous one\n const target = findElementByRef(svgElement, ref);\n if (!target) return;\n\n // Deselect previous if different\n if (selectedElement && !refsEqual(selectedElement, ref)) {\n deselectElement();\n }\n\n selectedElement = ref;\n overlayElement = renderSelectionOverlay(svgElement, ref, currentLayout);\n options?.onSelect?.(ref);\n\n // Focus SVG for keyboard events\n (svgElement as SVGSVGElement).focus();\n }\n\n /** Deselect the current element: remove overlay, fire onDeselect, clear state. */\n function deselectElement(): void {\n if (!selectedElement) return;\n\n // Cancel text editing if active\n if (isTextEditingActive && textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n\n const prev = selectedElement;\n selectedElement = null;\n\n if (overlayElement?.parentNode) {\n overlayElement.parentNode.removeChild(overlayElement);\n }\n overlayElement = null;\n\n options?.onDeselect?.(prev);\n }\n\n /** Enter text editing mode for the currently selected element. */\n function enterTextEditing(): void {\n if (!svgElement || !selectedElement || isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n if (!isTextEditable(selectedElement, specAnnotations)) return;\n\n const currentText = getElementText(selectedElement, currentSpec);\n if (currentText === null) return;\n\n // Find the text element within the selected element\n const target = findElementByRef(svgElement, selectedElement);\n if (!target) return;\n\n // The target might be a group; find the actual text element\n const textEl = target.tagName === 'text' ? target : target.querySelector('text');\n if (!textEl) return;\n\n isTextEditingActive = true;\n const editRef = selectedElement;\n\n const overlay = createTextEditOverlay({\n container,\n svg: svgElement as SVGSVGElement,\n targetElement: textEl as SVGElement,\n currentText,\n onCommit: (newText: string) => {\n isTextEditingActive = false;\n textEditCleanup = null;\n\n if (newText !== currentText) {\n // Fire text edit callbacks\n options?.onTextEdit?.(editRef, currentText, newText);\n options?.onEdit?.({\n type: 'text-edit',\n element: editRef,\n oldText: currentText,\n newText,\n });\n }\n },\n onCancel: () => {\n isTextEditingActive = false;\n textEditCleanup = null;\n },\n });\n\n textEditCleanup = overlay.destroy;\n }\n\n /**\n * Wire click-based selection events on the SVG.\n * Uses event delegation for efficiency.\n */\n function wireSelectionEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n const cleanups: Array<() => void> = [];\n\n // Click handler for selection\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n\n // Don't interfere with text editing\n if (isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref) {\n // Clicked on an editable element\n selectElement(ref);\n } else {\n // Clicked on empty area / non-editable element, deselect\n deselectElement();\n }\n };\n\n svg.addEventListener('click', handleClick);\n cleanups.push(() => svg.removeEventListener('click', handleClick));\n\n // Hover feedback on editable elements\n const handleMouseEnter = (e: Event) => {\n const target = (e.target as Element).closest(\n '[data-annotation-index], [data-chrome-key], .oc-mark-label[data-series], .oc-legend, [data-legend-index]',\n );\n if (target) {\n (target as SVGElement).classList.add('oc-editable-hover');\n }\n };\n\n const handleMouseLeave = (e: Event) => {\n const target = (e.target as Element).closest('.oc-editable-hover');\n if (target) {\n (target as SVGElement).classList.remove('oc-editable-hover');\n }\n };\n\n svg.addEventListener('mouseenter', handleMouseEnter, true);\n svg.addEventListener('mouseleave', handleMouseLeave, true);\n cleanups.push(() => {\n svg.removeEventListener('mouseenter', handleMouseEnter, true);\n svg.removeEventListener('mouseleave', handleMouseLeave, true);\n });\n\n // Double-click to enter text editing\n const handleDblClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref && isTextEditable(ref, specAnnotations)) {\n // Select first if not already selected\n if (!refsEqual(selectedElement, ref)) {\n selectElement(ref);\n }\n enterTextEditing();\n }\n };\n\n svg.addEventListener('dblclick', handleDblClick);\n cleanups.push(() => svg.removeEventListener('dblclick', handleDblClick));\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n /**\n * Wire keyboard events for edit actions on the SVG.\n * Delete/Backspace -> delete, Escape -> cancel/deselect, Tab -> cycle, Enter -> text edit.\n */\n function wireKeyboardEditEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n const specAnnotations = getSpecAnnotations();\n\n switch (e.key) {\n case 'Delete':\n case 'Backspace': {\n if (selectedElement && !isTextEditingActive) {\n e.preventDefault();\n options?.onEdit?.({ type: 'delete', element: selectedElement });\n // Stay selected (consumer decides whether to remove the element)\n }\n break;\n }\n\n case 'Escape': {\n e.preventDefault();\n if (isTextEditingActive && textEditCleanup) {\n // Cancel text editing, remain selected\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n } else if (selectedElement) {\n deselectElement();\n }\n break;\n }\n\n case 'ArrowDown':\n case 'ArrowRight': {\n if (!isTextEditingActive && selectedElement) {\n e.preventDefault();\n const editables = getEditableElements(currentSpec, currentLayout);\n if (editables.length === 0) break;\n\n const currentIndex = editables.findIndex((r) => refsEqual(r, selectedElement));\n const nextIndex = currentIndex >= editables.length - 1 ? 0 : currentIndex + 1;\n\n selectElement(editables[nextIndex]);\n }\n break;\n }\n\n case 'ArrowUp':\n case 'ArrowLeft': {\n if (!isTextEditingActive && selectedElement) {\n e.preventDefault();\n const editables = getEditableElements(currentSpec, currentLayout);\n if (editables.length === 0) break;\n\n const currentIndex = editables.findIndex((r) => refsEqual(r, selectedElement));\n const nextIndex = currentIndex <= 0 ? editables.length - 1 : currentIndex - 1;\n\n selectElement(editables[nextIndex]);\n }\n break;\n }\n\n case 'Enter': {\n if (selectedElement && !isTextEditingActive) {\n if (isTextEditable(selectedElement, specAnnotations)) {\n e.preventDefault();\n enterTextEditing();\n }\n }\n break;\n }\n }\n };\n\n svg.addEventListener('keydown', handleKeyDown);\n\n return () => {\n svg.removeEventListener('keydown', handleKeyDown);\n };\n }\n\n function render(): void {\n // Defer re-render if a drag is in progress to avoid destroying the dragged element\n if (isDragging) {\n pendingRender = true;\n return;\n }\n\n // Cancel any in-progress entrance animations before tearing down\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n cancelAnimations(svgElement);\n\n // Clean up previous render\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n if (cleanupVoronoiEvents) {\n cleanupVoronoiEvents();\n cleanupVoronoiEvents = null;\n }\n if (cleanupKeyboardNav) {\n cleanupKeyboardNav();\n cleanupKeyboardNav = null;\n }\n if (cleanupLegend) {\n cleanupLegend();\n cleanupLegend = null;\n }\n if (cleanupChartEvents) {\n cleanupChartEvents();\n cleanupChartEvents = null;\n }\n if (cleanupAnnotationDrag) {\n cleanupAnnotationDrag();\n cleanupAnnotationDrag = null;\n }\n if (cleanupEditDrags) {\n cleanupEditDrags();\n cleanupEditDrags = null;\n }\n if (cleanupSelection) {\n cleanupSelection();\n cleanupSelection = null;\n }\n if (cleanupKeyboardEdit) {\n cleanupKeyboardEdit();\n cleanupKeyboardEdit = null;\n }\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n overlayElement = null;\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n if (tooltipManager) {\n tooltipManager.destroy();\n }\n if (srTable?.parentNode) {\n srTable.parentNode.removeChild(srTable);\n srTable = null;\n }\n\n currentLayout = compile();\n const shouldAnimate = isFirstRender && !!currentLayout.animation?.enabled;\n svgElement = renderChartSVG(currentLayout, container, { animate: shouldAnimate });\n tooltipManager = createTooltipManager(container);\n\n // Wire tooltip events on mark elements\n cleanupTooltipEvents = wireTooltipEvents(\n svgElement,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n );\n\n // Wire voronoi overlay tooltip events for line/area charts\n cleanupVoronoiEvents = wireVoronoiTooltipEvents(svgElement, currentLayout, tooltipManager);\n\n // Wire keyboard navigation\n cleanupKeyboardNav = wireKeyboardNav(\n svgElement,\n container,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n currentLayout,\n );\n\n // Wire legend interactivity\n cleanupLegend = wireLegendInteraction(\n svgElement,\n currentLayout,\n options?.onLegendToggle,\n options?.onEdit,\n );\n\n // Wire chart event handlers (mark click/hover/leave, annotation click)\n if (\n options?.onMarkClick ||\n options?.onMarkHover ||\n options?.onMarkLeave ||\n options?.onAnnotationClick\n ) {\n const specAnnotations: import('@opendata-ai/openchart-core').Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n cleanupChartEvents = wireChartEvents(svgElement, currentLayout, specAnnotations, options);\n }\n\n // Shared setDragging callback for all drag handlers\n const setDragging = (dragging: boolean) => {\n isDragging = dragging;\n if (!dragging && pendingRender) {\n pendingRender = false;\n render();\n }\n };\n\n // Shared annotation list for drag handlers (computed once)\n const dragAnnotations: Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n\n // Wire annotation drag editing (activates when onAnnotationEdit or onEdit is provided)\n if (options?.onAnnotationEdit || options?.onEdit) {\n cleanupAnnotationDrag = wireAnnotationDrag(\n svgElement,\n dragAnnotations,\n options?.onAnnotationEdit,\n options?.onEdit,\n setDragging,\n );\n }\n\n // Wire all edit drag handlers when onEdit is provided\n if (options?.onEdit) {\n const editCleanups: Array<() => void> = [];\n\n // Connector endpoint drag\n editCleanups.push(\n wireConnectorEndpointDrag(svgElement, dragAnnotations, options.onEdit, setDragging),\n );\n\n // Range/refline annotation label drag\n editCleanups.push(\n wireAnnotationLabelDrag(svgElement, dragAnnotations, options.onEdit, setDragging),\n );\n\n // Chrome text drag\n const editSpec = currentSpec as ChartSpec | GraphSpec;\n editCleanups.push(wireChromeDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n // Legend drag\n editCleanups.push(wireLegendDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n // Series label drag\n editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec, options.onEdit, setDragging));\n\n cleanupEditDrags = () => {\n for (const cleanup of editCleanups) {\n cleanup();\n }\n };\n }\n\n // Wire selection and keyboard edit events when editing callbacks are provided\n if (hasEditingCallbacks(options)) {\n makeEditable(svgElement);\n cleanupSelection = wireSelectionEvents();\n cleanupKeyboardEdit = wireKeyboardEditEvents();\n\n // Restore selection overlay after re-render\n if (selectedElement) {\n const target = findElementByRef(svgElement, selectedElement);\n if (target) {\n overlayElement = renderSelectionOverlay(svgElement, selectedElement, currentLayout);\n } else {\n // Element no longer exists in DOM, clear selection silently\n selectedElement = null;\n overlayElement = null;\n }\n }\n }\n\n // Create hidden data table for screen readers\n srTable = createScreenReaderTable(currentLayout, container);\n\n // Apply container classes for CSS variable scoping and dark mode\n container.classList.add('oc-root');\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Set up animation cleanup on first render only.\n // onComplete fires when animations finish naturally (not on cancellation/destroy).\n // It nulls out cleanupAnimations so resizes work after the animation window,\n // and replays any resize that was skipped mid-animation.\n if (shouldAnimate && svgElement) {\n cleanupAnimations = setupAnimationCleanup(svgElement, () => {\n cleanupAnimations = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n if (isFirstRender) {\n isFirstRender = false;\n }\n }\n\n function update(newSpec: ChartSpec | GraphSpec, updateOpts?: UpdateOptions): void {\n if (destroyed) return;\n currentSpec = newSpec;\n if (updateOpts && 'selectedElement' in updateOpts) {\n selectedElement = updateOpts.selectedElement ?? null;\n }\n render();\n }\n\n function resize(): void {\n if (destroyed) return;\n // Skip resize during entrance animation. The resize observer fires\n // immediately when the container first enters DOM layout, and re-rendering\n // would destroy the animated SVG. Resizes during this window are queued\n // and replayed once the animation completes via the onComplete callback.\n if (cleanupAnimations) {\n pendingResize = true;\n return;\n }\n render();\n }\n\n function doExport(format: 'svg'): string;\n function doExport(format: 'svg-with-fonts', exportOptions?: SVGExportOptions): Promise<string>;\n function doExport(format: 'png', exportOptions?: ExportOptions): Promise<Blob>;\n function doExport(format: 'jpg', exportOptions?: ExportOptions): Promise<Blob>;\n function doExport(format: 'csv'): string;\n function doExport(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'csv',\n exportOptions?: ExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) {\n throw new Error('Chart is not rendered yet');\n }\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement, exportOptions);\n case 'png':\n return exportPNG(svgElement, exportOptions);\n case 'jpg':\n return exportJPG(svgElement, exportOptions);\n case 'csv':\n return exportCSV(\n 'data' in currentSpec && Array.isArray(currentSpec.data) ? currentSpec.data : [],\n );\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel entrance animations (cancellation does not fire onComplete)\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n pendingResize = false;\n }\n cancelAnimations(svgElement);\n\n if (resizeTimer !== null) {\n clearTimeout(resizeTimer);\n resizeTimer = null;\n }\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n if (cleanupVoronoiEvents) {\n cleanupVoronoiEvents();\n cleanupVoronoiEvents = null;\n }\n if (cleanupKeyboardNav) {\n cleanupKeyboardNav();\n cleanupKeyboardNav = null;\n }\n if (cleanupLegend) {\n cleanupLegend();\n cleanupLegend = null;\n }\n if (cleanupChartEvents) {\n cleanupChartEvents();\n cleanupChartEvents = null;\n }\n if (cleanupAnnotationDrag) {\n cleanupAnnotationDrag();\n cleanupAnnotationDrag = null;\n }\n if (cleanupEditDrags) {\n cleanupEditDrags();\n cleanupEditDrags = null;\n }\n if (cleanupSelection) {\n cleanupSelection();\n cleanupSelection = null;\n }\n if (cleanupKeyboardEdit) {\n cleanupKeyboardEdit();\n cleanupKeyboardEdit = null;\n }\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n selectedElement = null;\n overlayElement = null;\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n svgElement = null;\n }\n if (srTable?.parentNode) {\n srTable.parentNode.removeChild(srTable);\n srTable = null;\n }\n container.classList.remove('oc-dark');\n container.classList.remove('oc-root');\n }\n\n // Initial render\n render();\n\n // Set up responsive resize with debounce to avoid full SVG rebuild on every frame\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n if (resizeTimer !== null) clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => {\n resizeTimer = null;\n resize();\n }, 100);\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n destroy,\n get layout() {\n return currentLayout;\n },\n getSelectedElement(): ElementRef | null {\n return selectedElement;\n },\n select(ref: ElementRef): void {\n if (destroyed) return;\n selectElement(ref);\n },\n deselect(): void {\n if (destroyed) return;\n deselectElement();\n },\n get isEditing(): boolean {\n return isTextEditingActive;\n },\n };\n}\n","/**\n * Animation runtime for entrance animations.\n *\n * All animations are CSS-driven (keyframes + clip-path + transforms + opacity).\n * This module handles lifecycle: cleanup after completion, cancellation on update.\n * No WAAPI needed since clip-path handles line/area drawing.\n */\n\n/**\n * Cancel entrance animations and clean up.\n * Called when update() is invoked during animation, or on destroy.\n */\nexport function cancelAnimations(svg: SVGElement | null): void {\n if (svg) {\n svg.classList.remove('oc-animate');\n }\n}\n\n/**\n * Set up animation cleanup that removes oc-animate after all animations complete.\n *\n * Uses the computed total animation time (duration + stagger * elementCount + annotation delay)\n * rather than animationend events, because animationend fires per-element and the first\n * element to finish would prematurely kill staggered animations still in progress.\n */\nexport function setupAnimationCleanup(svg: SVGElement, onComplete?: () => void): () => void {\n // Read the animation timing from the CSS custom properties set by the renderer\n const style = svg.style;\n const duration = parseFloat(style.getPropertyValue('--oc-animation-duration')) || 600;\n const stagger = parseFloat(style.getPropertyValue('--oc-animation-stagger')) || 0;\n const annotationDelay = parseFloat(style.getPropertyValue('--oc-annotation-delay')) || 200;\n\n // Count animated elements to compute total stagger span\n const animatedElements = svg.querySelectorAll('[data-animation-index]').length;\n const totalStagger = stagger * Math.max(0, animatedElements - 1);\n\n // Total time: last element's stagger delay + its duration + annotation delay + buffer\n const totalTime = totalStagger + duration + annotationDelay + 500;\n\n const timer = setTimeout(() => {\n svg.classList.remove('oc-animate');\n onComplete?.();\n }, totalTime);\n\n return () => {\n clearTimeout(timer);\n cancelAnimations(svg);\n };\n}\n\n/**\n * Set up animation cleanup for table entrance animations.\n *\n * Same timeout-based approach as chart animations: compute total time from\n * CSS custom properties and row count, then remove oc-animate after completion.\n */\nexport function setupTableAnimationCleanup(wrapper: HTMLElement): () => void {\n const style = wrapper.style;\n const duration = parseFloat(style.getPropertyValue('--oc-animation-duration')) || 500;\n const stagger = parseFloat(style.getPropertyValue('--oc-animation-stagger')) || 0;\n\n const rows = wrapper.querySelectorAll('tbody tr').length;\n const totalStagger = stagger * Math.max(0, rows - 1);\n\n // Total: last row stagger + duration + buffer\n const totalTime = totalStagger + duration + 300;\n\n const timer = setTimeout(() => {\n wrapper.classList.remove('oc-animate');\n }, totalTime);\n\n return () => {\n clearTimeout(timer);\n wrapper.classList.remove('oc-animate');\n };\n}\n","/**\n * SVG renderer: converts a ChartLayout into SVG DOM elements.\n *\n * Creates an <svg> element with viewBox matching layout dimensions,\n * renders chrome (title/subtitle/source), axes, marks, annotations,\n * and legend. All styling via inline SVG attributes from layout data.\n *\n * Mark rendering dispatches per mark type with dedicated renderers\n * for line, area, rect, arc, and point marks.\n */\n\nimport type {\n ArcMark,\n AreaMark,\n AxisLayout,\n ChartLayout,\n LegendLayout,\n LineMark,\n Mark,\n MeasureTextFn,\n Point,\n PointMark,\n RectMark,\n ResolvedAnimation,\n ResolvedAnnotation,\n ResolvedChromeElement,\n RuleMarkLayout,\n TextMarkLayout,\n TextStyle,\n TickMarkLayout,\n} from '@opendata-ai/openchart-core';\nimport { BRAND_FONT_SIZE, BRAND_MIN_WIDTH, estimateTextWidth } from '@opendata-ai/openchart-core';\nimport { clampStaggerDelay } from '@opendata-ai/openchart-engine';\nimport { buildGradientDefs, resolveMarkFill } from './gradient-utils';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Module-level animation state. Set by renderChartSVG before rendering marks\n * so mark renderers can read it without changing their function signatures.\n */\nlet currentAnimation: ResolvedAnimation | undefined;\n\n/**\n * Module-level gradient map. Set by renderChartSVG after building gradient defs\n * so mark renderers can resolve gradient fills without signature changes.\n */\nlet currentGradientMap: Map<string, string> = new Map();\n\n/**\n * Stamp animation index attributes on a mark element when animation is enabled.\n * Sets `data-animation-index` (for querySelector) and `--oc-mark-index`\n * (for CSS calc-based stagger delay).\n */\nfunction stampAnimationAttrs(\n el: SVGElement,\n mark: { animationIndex?: number },\n fallbackIndex: number,\n): void {\n if (!currentAnimation?.enabled) return;\n const idx = mark.animationIndex ?? fallbackIndex;\n el.setAttribute('data-animation-index', String(idx));\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('--oc-mark-index', String(idx));\n}\n\n/** CSS easing preset map for inline style custom properties. */\nconst EASE_VAR_MAP: Record<string, string> = {\n smooth: 'var(--oc-ease-smooth)',\n snappy: 'var(--oc-ease-snappy)',\n};\n\n/**\n * Compute the vertical extent of x-axis labels below the chart area.\n * Accounts for rotated tick labels which need more vertical space.\n */\nfunction computeXAxisExtent(layout: ChartLayout): number {\n const xAxis = layout.axes.x;\n if (!xAxis) return 0;\n\n if (xAxis.tickAngle && Math.abs(xAxis.tickAngle) > 10) {\n // Rotated labels: estimate height from the longest tick label.\n const fontSize = xAxis.tickLabelStyle.fontSize;\n const fontWeight = xAxis.tickLabelStyle.fontWeight;\n const angleRad = Math.abs(xAxis.tickAngle) * (Math.PI / 180);\n let maxLabelWidth = 40;\n for (const tick of xAxis.ticks) {\n const w = estimateTextWidth(tick.label, fontSize, fontWeight);\n if (w > maxLabelWidth) maxLabelWidth = w;\n }\n const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);\n return xAxis.label ? rotatedHeight + 20 : rotatedHeight;\n }\n\n return xAxis.label ? 48 : 26;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createSVGElement(tag: string): SVGElement {\n return document.createElementNS(SVG_NS, tag);\n}\n\nfunction setAttrs(el: SVGElement, attrs: Record<string, string | number>): void {\n for (const [key, value] of Object.entries(attrs)) {\n el.setAttribute(key, String(value));\n }\n}\n\nfunction applyTextStyle(el: SVGElement, style: TextStyle): void {\n setAttrs(el, {\n 'font-family': style.fontFamily,\n 'font-size': style.fontSize,\n 'font-weight': style.fontWeight,\n });\n // Use inline style for fill so it takes priority over CSS class defaults\n // (e.g. .oc-title { fill: var(--oc-text) } which would override attributes)\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', style.fill);\n if (style.textAnchor) {\n el.setAttribute('text-anchor', style.textAnchor);\n }\n if (style.dominantBaseline) {\n el.setAttribute('dominant-baseline', style.dominantBaseline);\n }\n if (style.fontVariant) {\n el.setAttribute('font-variant', style.fontVariant);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Chrome rendering\n// ---------------------------------------------------------------------------\n\n/**\n * Break text into lines that fit within maxWidth using word wrapping.\n * Uses a character-width heuristic (same as text-measure.ts).\n */\nfunction wrapText(\n text: string,\n fontSize: number,\n fontWeight: number,\n maxWidth: number,\n measureText?: MeasureTextFn,\n): string[] {\n if (maxWidth <= 0) return [text];\n\n // Split on explicit newlines first\n const segments = text.split('\\n');\n if (segments.length > 1) {\n return segments.flatMap((segment) =>\n segment.length === 0 ? [''] : wrapText(segment, fontSize, fontWeight, maxWidth, measureText),\n );\n }\n\n // Use real text measurement when available\n if (measureText) {\n const textWidth = measureText(text, fontSize, fontWeight).width;\n if (textWidth <= maxWidth) return [text];\n\n const words = text.split(' ');\n const lines: string[] = [];\n let current = '';\n\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n const candidateWidth = measureText(candidate, fontSize, fontWeight).width;\n if (candidateWidth > maxWidth && current) {\n lines.push(current);\n current = word;\n } else {\n current = candidate;\n }\n }\n if (current) lines.push(current);\n\n return lines;\n }\n\n // Heuristic character width matching text-measure.ts\n const AVG_CHAR_WIDTH = 0.55;\n const WEIGHT_FACTORS: Record<number, number> = {\n 100: 0.9,\n 200: 0.92,\n 300: 0.95,\n 400: 1.0,\n 500: 1.02,\n 600: 1.05,\n 700: 1.08,\n 800: 1.1,\n 900: 1.12,\n };\n const weightFactor = WEIGHT_FACTORS[fontWeight] ?? 1.0;\n const charWidth = fontSize * AVG_CHAR_WIDTH * weightFactor;\n const maxChars = Math.floor(maxWidth / charWidth);\n\n if (text.length <= maxChars) return [text];\n\n const words = text.split(' ');\n const lines: string[] = [];\n let current = '';\n\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n if (candidate.length > maxChars && current) {\n lines.push(current);\n current = word;\n } else {\n current = candidate;\n }\n }\n if (current) lines.push(current);\n\n return lines;\n}\n\nfunction renderChromeElement(\n parent: SVGElement,\n element: ResolvedChromeElement,\n className: string,\n chromeKey: string,\n measureText?: MeasureTextFn,\n): void {\n const text = createSVGElement('text');\n setAttrs(text, { x: element.x, y: element.y });\n applyTextStyle(text, element.style);\n text.setAttribute('class', className);\n text.setAttribute('data-chrome-key', chromeKey);\n\n const lines = wrapText(\n element.text,\n element.style.fontSize,\n element.style.fontWeight,\n element.maxWidth,\n measureText,\n );\n\n if (lines.length === 1) {\n text.textContent = element.text;\n } else {\n const lineHeight = element.style.fontSize * (element.style.lineHeight ?? 1.3);\n for (let i = 0; i < lines.length; i++) {\n const tspan = createSVGElement('tspan');\n setAttrs(tspan, { x: element.x, dy: i === 0 ? 0 : lineHeight });\n tspan.textContent = lines[i];\n text.appendChild(tspan);\n }\n }\n\n parent.appendChild(text);\n}\n\nfunction renderChrome(parent: SVGElement, layout: ChartLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-chrome');\n\n const { chrome, measureText } = layout;\n\n // Top chrome: render at their stored y positions (already absolute)\n if (chrome.title) {\n renderChromeElement(g, chrome.title, 'oc-title', 'title', measureText);\n }\n if (chrome.subtitle) {\n renderChromeElement(g, chrome.subtitle, 'oc-subtitle', 'subtitle', measureText);\n }\n\n // Bottom chrome starts below x-axis labels/title, not at chart area bottom.\n // Accounts for rotated tick labels which need more vertical space.\n const xAxisExtent = computeXAxisExtent(layout);\n const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;\n if (chrome.source) {\n renderChromeElement(\n g,\n { ...chrome.source, y: bottomOffset + chrome.source.y },\n 'oc-source',\n 'source',\n measureText,\n );\n }\n if (chrome.byline) {\n renderChromeElement(\n g,\n { ...chrome.byline, y: bottomOffset + chrome.byline.y },\n 'oc-byline',\n 'byline',\n measureText,\n );\n }\n if (chrome.footer) {\n renderChromeElement(\n g,\n { ...chrome.footer, y: bottomOffset + chrome.footer.y },\n 'oc-footer',\n 'footer',\n measureText,\n );\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Axis rendering\n// ---------------------------------------------------------------------------\n\nfunction renderAxis(\n parent: SVGElement,\n axis: AxisLayout,\n orientation: 'x' | 'y',\n layout: ChartLayout,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', `oc-axis oc-axis-${orientation}`);\n\n const { area } = layout;\n\n // Only draw axis line for x-axis (bottom baseline).\n // Horizontal gridlines already guide y-values, so the vertical y-axis line is redundant.\n if (orientation === 'x') {\n const line = createSVGElement('line');\n line.setAttribute('class', 'oc-axis-line');\n setAttrs(line, {\n x1: axis.start.x,\n y1: axis.start.y,\n x2: axis.end.x,\n y2: axis.end.y,\n stroke: layout.theme.colors.axis,\n 'stroke-width': 1,\n });\n g.appendChild(line);\n }\n\n // Ticks and labels\n // Tick positions are absolute pixel coordinates from D3 scales whose range\n // was set to [chartArea.x, chartArea.x + chartArea.width] (and similarly for y).\n // Don't add area.x/area.y again or you'll double-offset everything.\n for (const tick of axis.ticks) {\n if (orientation === 'x') {\n // Label (no tick marks -- gridlines provide sufficient reference)\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-axis-tick');\n\n if (axis.tickAngle && Math.abs(axis.tickAngle) > 10) {\n // Rotated labels: anchor at the rotation pivot point\n const labelX = tick.position;\n const labelY = area.y + area.height + 6;\n setAttrs(label, {\n x: labelX,\n y: labelY,\n 'text-anchor': axis.tickAngle < 0 ? 'end' : 'start',\n 'dominant-baseline': 'central',\n transform: `rotate(${axis.tickAngle}, ${labelX}, ${labelY})`,\n });\n } else {\n setAttrs(label, {\n x: tick.position,\n y: area.y + area.height + 14,\n 'text-anchor': 'middle',\n });\n }\n\n applyTextStyle(label, axis.tickLabelStyle);\n label.textContent = tick.label;\n g.appendChild(label);\n } else {\n // Label (no tick marks -- gridlines provide sufficient reference)\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-axis-tick');\n setAttrs(label, {\n x: area.x - 6,\n y: tick.position,\n 'text-anchor': 'end',\n 'dominant-baseline': 'central',\n });\n applyTextStyle(label, axis.tickLabelStyle);\n label.textContent = tick.label;\n g.appendChild(label);\n }\n }\n\n // Gridlines (positions are also absolute from the scales)\n for (const gridline of axis.gridlines) {\n const gl = createSVGElement('line');\n gl.setAttribute('class', 'oc-gridline');\n if (orientation === 'y') {\n setAttrs(gl, {\n x1: area.x,\n y1: gridline.position,\n x2: area.x + area.width,\n y2: gridline.position,\n stroke: layout.theme.colors.gridline,\n 'stroke-width': 1,\n 'stroke-opacity': 0.6,\n });\n } else {\n setAttrs(gl, {\n x1: gridline.position,\n y1: area.y,\n x2: gridline.position,\n y2: area.y + area.height,\n stroke: layout.theme.colors.gridline,\n 'stroke-width': 1,\n 'stroke-opacity': 0.6,\n });\n }\n g.appendChild(gl);\n }\n\n // Axis label\n if (axis.label && axis.labelStyle) {\n const axisLabel = createSVGElement('text');\n axisLabel.setAttribute('class', 'oc-axis-title');\n applyTextStyle(axisLabel, axis.labelStyle);\n axisLabel.textContent = axis.label;\n\n if (orientation === 'x') {\n // Position axis title below tick labels. For rotated labels, compute\n // the vertical extent of the rotated ticks and place the title below.\n let titleY = area.y + area.height + 35;\n if (axis.tickAngle && Math.abs(axis.tickAngle) > 10) {\n const angleRad = Math.abs(axis.tickAngle) * (Math.PI / 180);\n let maxLabelWidth = 40;\n for (const tick of axis.ticks) {\n const w = estimateTextWidth(\n tick.label,\n axis.tickLabelStyle.fontSize,\n axis.tickLabelStyle.fontWeight,\n );\n if (w > maxLabelWidth) maxLabelWidth = w;\n }\n const rotatedHeight = Math.min(maxLabelWidth * Math.sin(angleRad) + 6, 120);\n titleY = area.y + area.height + rotatedHeight + 14;\n }\n setAttrs(axisLabel, {\n x: area.x + area.width / 2,\n y: titleY,\n 'text-anchor': 'middle',\n });\n } else {\n // Rotated y-axis label\n setAttrs(axisLabel, {\n x: area.x - 45,\n y: area.y + area.height / 2,\n 'text-anchor': 'middle',\n transform: `rotate(-90, ${area.x - 45}, ${area.y + area.height / 2})`,\n });\n }\n g.appendChild(axisLabel);\n }\n\n parent.appendChild(g);\n}\n\nfunction renderAxes(parent: SVGElement, layout: ChartLayout): void {\n if (layout.axes.x) {\n renderAxis(parent, layout.axes.x, 'x', layout);\n }\n if (layout.axes.y) {\n renderAxis(parent, layout.axes.y, 'y', layout);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mark rendering (dispatch per mark type)\n// ---------------------------------------------------------------------------\n\ntype MarkRenderer<T extends Mark> = (mark: T, index: number) => SVGElement;\n\nconst markRenderers: Record<string, MarkRenderer<Mark>> = {};\n\n/**\n * Register a mark renderer for a specific mark type.\n * Built-in renderers are registered below for all chart types.\n */\nexport function registerMarkRenderer<T extends Mark>(\n type: T['type'],\n renderer: MarkRenderer<T>,\n): void {\n markRenderers[type] = renderer as MarkRenderer<Mark>;\n}\n\nfunction renderLineMark(mark: LineMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `line-${mark.seriesKey ?? index}`);\n g.setAttribute('class', 'oc-mark oc-mark-line');\n stampAnimationAttrs(g, mark, index);\n\n if (mark.points.length > 1) {\n const path = createSVGElement('path');\n // Use the pre-computed D3 curve path when available (smooth monotone),\n // otherwise fall back to straight M/L segments.\n const d =\n mark.path ?? mark.points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');\n setAttrs(path, {\n d,\n fill: 'none',\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n if (mark.strokeDasharray) {\n path.setAttribute('stroke-dasharray', mark.strokeDasharray);\n }\n if (mark.opacity != null) {\n path.setAttribute('opacity', String(mark.opacity));\n }\n // Note: line drawing animation is handled via CSS clip-path on the group,\n // no inline dasharray/dashoffset needed.\n g.appendChild(path);\n }\n\n // Render end-of-line label if present and visible\n if (mark.label?.visible) {\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-mark-label');\n if (mark.seriesKey) {\n label.setAttribute('data-series', mark.seriesKey);\n }\n setAttrs(label, { x: mark.label.x, y: mark.label.y });\n applyTextStyle(label, mark.label.style);\n label.textContent = mark.label.text;\n g.appendChild(label);\n\n // Render connector line if label was offset from anchor\n if (mark.label.connector) {\n const connector = createSVGElement('line');\n connector.setAttribute('class', 'oc-mark-connector');\n setAttrs(connector, {\n x1: mark.label.connector.from.x,\n y1: mark.label.connector.from.y,\n x2: mark.label.connector.to.x,\n y2: mark.label.connector.to.y,\n stroke: mark.label.connector.stroke,\n 'stroke-width': 1,\n 'stroke-opacity': 0.5,\n });\n g.appendChild(connector);\n }\n }\n\n return g;\n}\n\nfunction renderAreaMark(mark: AreaMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `area-${mark.seriesKey ?? index}`);\n g.setAttribute('class', 'oc-mark oc-mark-area');\n stampAnimationAttrs(g, mark, index);\n\n if (mark.path) {\n // Area fill: the full closed shape (top line + baseline), no stroke\n const fill = createSVGElement('path');\n setAttrs(fill, {\n d: mark.path,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n 'fill-opacity': mark.fillOpacity,\n stroke: 'none',\n });\n g.appendChild(fill);\n\n // Top-line stroke: only along the data points, not the baseline\n if (mark.stroke && mark.topPath) {\n const strokePath = createSVGElement('path');\n strokePath.setAttribute('class', 'oc-area-top');\n setAttrs(strokePath, {\n d: mark.topPath,\n fill: 'none',\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth ?? 1,\n });\n // Note: area drawing animation is handled via CSS clip-path on the group,\n // no inline dasharray/dashoffset needed.\n g.appendChild(strokePath);\n }\n }\n\n return g;\n}\n\nfunction renderRectMark(mark: RectMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `rect-${index}`);\n g.setAttribute('class', 'oc-mark oc-mark-rect');\n stampAnimationAttrs(g, mark, index);\n // Use engine-provided orientation for animation direction\n if (currentAnimation?.enabled && mark.orient === 'horizontal') {\n g.setAttribute('data-orient', 'horizontal');\n }\n\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: mark.x,\n y: mark.y,\n width: mark.width,\n height: mark.height,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n });\n if (mark.stroke) {\n rect.setAttribute('stroke', mark.stroke);\n }\n if (mark.strokeWidth) {\n rect.setAttribute('stroke-width', String(mark.strokeWidth));\n }\n if (mark.cornerRadius) {\n setAttrs(rect, { rx: mark.cornerRadius, ry: mark.cornerRadius });\n }\n g.appendChild(rect);\n\n // Render value label if present and visible\n if (mark.label?.visible) {\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-mark-label');\n setAttrs(label, { x: mark.label.x, y: mark.label.y });\n applyTextStyle(label, mark.label.style);\n label.textContent = mark.label.text;\n g.appendChild(label);\n }\n\n return g;\n}\n\nfunction renderArcMark(mark: ArcMark, index: number): SVGElement {\n const g = createSVGElement('g');\n g.setAttribute('data-mark-id', `arc-${index}`);\n g.setAttribute('class', 'oc-mark oc-mark-arc');\n g.setAttribute('transform', `translate(${mark.center.x},${mark.center.y})`);\n stampAnimationAttrs(g, mark, index);\n\n const path = createSVGElement('path');\n setAttrs(path, {\n d: mark.path,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n g.appendChild(path);\n\n // Render label if present and visible\n if (mark.label?.visible) {\n const label = createSVGElement('text');\n label.setAttribute('class', 'oc-mark-label');\n // Label position is in absolute coords, but we're in a translated group,\n // so subtract the center offset\n setAttrs(label, {\n x: mark.label.x - mark.center.x,\n y: mark.label.y - mark.center.y,\n });\n applyTextStyle(label, mark.label.style);\n label.textContent = mark.label.text;\n g.appendChild(label);\n }\n\n return g;\n}\n\nfunction renderPointMark(mark: PointMark, index: number): SVGElement {\n const circle = createSVGElement('circle');\n circle.setAttribute('data-mark-id', `point-${index}`);\n circle.setAttribute('class', 'oc-mark oc-mark-point');\n stampAnimationAttrs(circle, mark, index);\n\n setAttrs(circle, {\n cx: mark.cx,\n cy: mark.cy,\n r: mark.r,\n fill: resolveMarkFill(mark.fill, currentGradientMap),\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n if (mark.fillOpacity !== undefined) {\n circle.setAttribute('fill-opacity', String(mark.fillOpacity));\n }\n return circle;\n}\n\nfunction renderTextMark(mark: TextMarkLayout, index: number): SVGElement {\n const text = createSVGElement('text');\n text.setAttribute('data-mark-id', `textMark-${index}`);\n text.setAttribute('class', 'oc-mark oc-mark-text');\n stampAnimationAttrs(text, mark, index);\n\n setAttrs(text, {\n x: mark.x,\n y: mark.y,\n 'font-size': mark.fontSize,\n 'text-anchor': mark.textAnchor,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', mark.fill);\n if (mark.fontWeight) {\n text.setAttribute('font-weight', String(mark.fontWeight));\n }\n if (mark.fontFamily) {\n text.setAttribute('font-family', mark.fontFamily);\n }\n if (mark.angle) {\n text.setAttribute('transform', `rotate(${mark.angle}, ${mark.x}, ${mark.y})`);\n }\n text.textContent = mark.text;\n return text;\n}\n\nfunction renderRuleMark(mark: RuleMarkLayout, index: number): SVGElement {\n const line = createSVGElement('line');\n line.setAttribute('data-mark-id', `rule-${index}`);\n line.setAttribute('class', 'oc-mark oc-mark-rule');\n stampAnimationAttrs(line, mark, index);\n\n setAttrs(line, {\n x1: mark.x1,\n y1: mark.y1,\n x2: mark.x2,\n y2: mark.y2,\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n if (mark.strokeDasharray) {\n line.setAttribute('stroke-dasharray', mark.strokeDasharray);\n }\n if (mark.opacity != null) {\n line.setAttribute('opacity', String(mark.opacity));\n }\n return line;\n}\n\nfunction renderTickMark(mark: TickMarkLayout, index: number): SVGElement {\n const line = createSVGElement('line');\n line.setAttribute('data-mark-id', `tick-${index}`);\n line.setAttribute('class', 'oc-mark oc-mark-tick');\n stampAnimationAttrs(line, mark, index);\n\n // Tick is a short line segment centered at (x, y)\n const half = mark.length / 2;\n if (mark.orient === 'vertical') {\n setAttrs(line, {\n x1: mark.x,\n y1: mark.y - half,\n x2: mark.x,\n y2: mark.y + half,\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n } else {\n setAttrs(line, {\n x1: mark.x - half,\n y1: mark.y,\n x2: mark.x + half,\n y2: mark.y,\n stroke: mark.stroke,\n 'stroke-width': mark.strokeWidth,\n });\n }\n\n if (mark.opacity != null) {\n line.setAttribute('opacity', String(mark.opacity));\n }\n return line;\n}\n\n// Register built-in renderers\nregisterMarkRenderer('line', renderLineMark as MarkRenderer<Mark>);\nregisterMarkRenderer('area', renderAreaMark as MarkRenderer<Mark>);\nregisterMarkRenderer('rect', renderRectMark as MarkRenderer<Mark>);\nregisterMarkRenderer('arc', renderArcMark as MarkRenderer<Mark>);\nregisterMarkRenderer('point', renderPointMark as MarkRenderer<Mark>);\nregisterMarkRenderer('textMark', renderTextMark as MarkRenderer<Mark>);\nregisterMarkRenderer('rule', renderRuleMark as MarkRenderer<Mark>);\nregisterMarkRenderer('tick', renderTickMark as MarkRenderer<Mark>);\n\n/** Extract series name from a mark for legend toggle matching. */\nfunction getMarkSeries(mark: Mark): string | undefined {\n // Line and area marks have an explicit seriesKey\n if (mark.type === 'line' || mark.type === 'area') {\n return mark.seriesKey;\n }\n // For arc marks, the category name is the first part of the aria label (before ':')\n if (mark.type === 'arc') {\n return mark.aria.label.split(':')[0]?.trim();\n }\n // For rect/point, the aria label may be \"category: value\" or \"category, group: value\".\n // The series name is the category part (before the colon).\n if (mark.aria?.label) {\n const beforeColon = mark.aria.label.split(':')[0]?.trim();\n if (beforeColon) return beforeColon;\n }\n return undefined;\n}\n\nfunction renderMarks(parent: SVGElement, layout: ChartLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-marks');\n\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n const renderer = markRenderers[mark.type];\n if (!renderer) continue;\n\n const el = renderer(mark, i);\n // Add ARIA label if present\n if (mark.aria?.label) {\n el.setAttribute('aria-label', mark.aria.label);\n }\n // Add data-series attribute for legend toggle matching\n const series = getMarkSeries(mark);\n if (series) {\n el.setAttribute('data-series', series);\n }\n\n // For stacked segments, set stack position for sequential animation chaining.\n // stackPos is computed by the engine on RectMark during compilation.\n if (currentAnimation?.enabled && mark.type === 'rect') {\n const rect = mark as RectMark;\n if (rect.stackGroup && rect.stackPos !== undefined) {\n el.setAttribute('data-stack-pos', String(rect.stackPos));\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty(\n '--oc-stack-pos',\n String(rect.stackPos),\n );\n }\n }\n\n g.appendChild(el);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Annotation rendering\n// ---------------------------------------------------------------------------\n\nfunction renderAnnotations(parent: SVGElement, layout: ChartLayout): void {\n if (layout.annotations.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-annotations');\n\n // Annotations are already sorted by zIndex from the engine, so render in order\n const bgColor = layout.theme.colors.background;\n for (let i = 0; i < layout.annotations.length; i++) {\n renderAnnotation(g, layout.annotations[i], i, bgColor);\n }\n\n parent.appendChild(g);\n}\n\n/**\n * Render a curved arrow connector from a label to a data point.\n * Uses a cubic bezier that sweeps outward then curves toward the\n * target, with a triangular arrowhead at the tip.\n */\nfunction renderCurvedArrow(parent: SVGElement, from: Point, to: Point, stroke: string): void {\n // Pad above the target so the arrow doesn't sit right on the element.\n const pad = 6;\n const tipY = to.y - pad;\n\n const dy = tipY - from.y;\n const dist = Math.sqrt((to.x - from.x) ** 2 + dy ** 2) || 1;\n\n // Arrowhead geometry\n const arrowLen = 8;\n const arrowWidth = 4;\n\n // cp2 directly above target so arrow arrives pointing straight down.\n const bulge = Math.max(dist * 0.4, 35);\n const cp1x = from.x + bulge;\n const cp1y = from.y + dy * 0.35;\n const cp2x = to.x;\n const cp2y = tipY - Math.abs(dy) * 0.25;\n\n // Tangent at the tip (from cp2 → tip), used for arrowhead direction.\n const tx = to.x - cp2x;\n const ty = tipY - cp2y;\n const tLen = Math.sqrt(tx * tx + ty * ty) || 1;\n const ux = tx / tLen;\n const uy = ty / tLen;\n\n // End the curve path at the arrowhead BASE so the stroke doesn't\n // poke through the filled triangle.\n const baseX = to.x - ux * arrowLen;\n const baseY = tipY - uy * arrowLen;\n\n const path = createSVGElement('path');\n path.setAttribute('class', 'oc-annotation-connector');\n setAttrs(path, {\n d: `M ${from.x} ${from.y} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${baseX} ${baseY}`,\n fill: 'none',\n stroke,\n 'stroke-width': 1.5,\n });\n parent.appendChild(path);\n\n // Arrowhead triangle: perpendicular to tangent direction.\n const px = -uy;\n const py = ux;\n\n const arrow = createSVGElement('polygon');\n arrow.setAttribute('class', 'oc-annotation-connector');\n setAttrs(arrow, {\n points: [\n `${to.x},${tipY}`,\n `${baseX + px * arrowWidth},${baseY + py * arrowWidth}`,\n `${baseX - px * arrowWidth},${baseY - py * arrowWidth}`,\n ].join(' '),\n fill: stroke,\n });\n parent.appendChild(arrow);\n}\n\nfunction renderAnnotation(\n parent: SVGElement,\n annotation: ResolvedAnnotation,\n index: number,\n bgColor?: string,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', `oc-annotation oc-annotation-${annotation.type}`);\n g.setAttribute('data-annotation-index', String(index));\n if (annotation.id) {\n g.setAttribute('data-annotation-id', annotation.id);\n }\n\n // Range rect\n if (annotation.rect) {\n const rect = createSVGElement('rect');\n rect.setAttribute('class', 'oc-annotation-range');\n setAttrs(rect, {\n x: annotation.rect.x,\n y: annotation.rect.y,\n width: annotation.rect.width,\n height: annotation.rect.height,\n });\n if (annotation.fill) rect.setAttribute('fill', annotation.fill);\n if (annotation.opacity !== undefined) {\n rect.setAttribute('fill-opacity', String(annotation.opacity));\n }\n g.appendChild(rect);\n }\n\n // Reference line\n if (annotation.line) {\n const line = createSVGElement('line');\n line.setAttribute('class', 'oc-annotation-line');\n setAttrs(line, {\n x1: annotation.line.start.x,\n y1: annotation.line.start.y,\n x2: annotation.line.end.x,\n y2: annotation.line.end.y,\n 'stroke-width': annotation.strokeWidth ?? 1,\n });\n if (annotation.stroke) line.setAttribute('stroke', annotation.stroke);\n if (annotation.strokeDasharray) {\n line.setAttribute('stroke-dasharray', annotation.strokeDasharray);\n }\n g.appendChild(line);\n }\n\n // Label with optional connector line\n if (annotation.label?.visible) {\n // Render connector first (behind the label text)\n if (annotation.label.connector) {\n const c = annotation.label.connector;\n if (c.style === 'curve') {\n renderCurvedArrow(g, c.from, c.to, c.stroke);\n } else {\n const connector = createSVGElement('line');\n connector.setAttribute('class', 'oc-annotation-connector');\n setAttrs(connector, {\n x1: c.from.x,\n y1: c.from.y,\n x2: c.to.x,\n y2: c.to.y,\n stroke: c.stroke,\n 'stroke-width': 1,\n 'stroke-opacity': 0.5,\n });\n g.appendChild(connector);\n }\n }\n\n const text = createSVGElement('text');\n text.setAttribute('class', 'oc-annotation-label');\n setAttrs(text, { x: annotation.label.x, y: annotation.label.y });\n applyTextStyle(text, annotation.label.style);\n\n const lines = annotation.label.text.split('\\n');\n const fontSize = annotation.label.style.fontSize ?? 12;\n const lineHeight = fontSize * (annotation.label.style.lineHeight ?? 1.3);\n const isMultiLine = lines.length > 1;\n\n // Multi-line text uses center alignment for a cleaner look\n if (isMultiLine) {\n text.setAttribute('text-anchor', 'middle');\n for (let i = 0; i < lines.length; i++) {\n const tspan = createSVGElement('tspan');\n setAttrs(tspan, { x: annotation.label.x, dy: i === 0 ? 0 : lineHeight });\n tspan.textContent = lines[i];\n text.appendChild(tspan);\n }\n } else {\n text.textContent = annotation.label.text;\n }\n\n // Render background rect behind text if specified, otherwise use\n // paint-order stroke halo to knock out lines behind text\n if (annotation.label.background) {\n const charWidth = fontSize * 0.55;\n const maxLineWidth = Math.max(...lines.map((l) => l.length)) * charWidth;\n const totalHeight = lines.length * lineHeight;\n const pad = 3;\n const bgX = isMultiLine\n ? annotation.label.x - maxLineWidth / 2 - pad\n : annotation.label.x - pad;\n const bgRect = createSVGElement('rect');\n bgRect.setAttribute('class', 'oc-annotation-bg');\n setAttrs(bgRect, {\n x: bgX,\n y: annotation.label.y - fontSize + (lineHeight - fontSize) / 2 - pad,\n width: maxLineWidth + pad * 2,\n height: totalHeight + pad * 2,\n fill: annotation.label.background,\n rx: 2,\n });\n g.appendChild(bgRect);\n } else if (bgColor) {\n text.style.paintOrder = 'stroke';\n text.style.stroke = bgColor;\n text.style.strokeWidth = `${Math.round(fontSize * 0.3)}px`;\n text.style.strokeLinejoin = 'round';\n }\n\n g.appendChild(text);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Legend rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLegend(parent: SVGElement, legend: LegendLayout): void {\n if (legend.entries.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-legend');\n g.setAttribute('role', 'list');\n g.setAttribute('aria-label', 'Chart legend');\n\n const isHorizontal = legend.position === 'top' || legend.position === 'bottom';\n let offsetX = legend.bounds.x;\n let offsetY = legend.bounds.y;\n\n for (let i = 0; i < legend.entries.length; i++) {\n const entry = legend.entries[i];\n\n // Pre-check: wrap to next line if this entry would overflow bounds\n if (isHorizontal && i > 0) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n if (offsetX + entryWidth > legend.bounds.x + legend.bounds.width) {\n offsetX = legend.bounds.x;\n offsetY += legend.swatchSize + 6;\n }\n }\n const entryG = createSVGElement('g');\n entryG.setAttribute('class', 'oc-legend-entry');\n entryG.setAttribute('role', 'listitem');\n entryG.setAttribute('data-legend-index', String(i));\n entryG.setAttribute('data-legend-label', entry.label);\n if (entry.overflow) {\n entryG.setAttribute('data-legend-overflow', 'true');\n entryG.setAttribute('aria-label', entry.label);\n entryG.setAttribute('opacity', '0.5');\n } else {\n entryG.setAttribute(\n 'aria-label',\n `${entry.label}: ${entry.active !== false ? 'visible' : 'hidden'}`,\n );\n entryG.setAttribute('style', 'cursor: pointer');\n\n // Apply dimming for inactive entries\n if (entry.active === false) {\n entryG.setAttribute('opacity', '0.3');\n }\n }\n\n // Swatch\n if (entry.shape === 'circle') {\n const circle = createSVGElement('circle');\n setAttrs(circle, {\n cx: offsetX + legend.swatchSize / 2,\n cy: offsetY + legend.swatchSize / 2,\n r: legend.swatchSize / 2,\n fill: entry.color,\n });\n entryG.appendChild(circle);\n } else if (entry.shape === 'line') {\n // Line swatch: a short line segment with a dot in the middle\n const line = createSVGElement('line');\n setAttrs(line, {\n x1: offsetX,\n y1: offsetY + legend.swatchSize / 2,\n x2: offsetX + legend.swatchSize,\n y2: offsetY + legend.swatchSize / 2,\n stroke: entry.color,\n 'stroke-width': 2,\n });\n entryG.appendChild(line);\n // Small dot at center\n const dot = createSVGElement('circle');\n setAttrs(dot, {\n cx: offsetX + legend.swatchSize / 2,\n cy: offsetY + legend.swatchSize / 2,\n r: 2.5,\n fill: entry.color,\n });\n entryG.appendChild(dot);\n } else {\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: offsetX,\n y: offsetY,\n width: legend.swatchSize,\n height: legend.swatchSize,\n fill: entry.color,\n rx: 2,\n });\n entryG.appendChild(rect);\n }\n\n // Label\n const label = createSVGElement('text');\n setAttrs(label, {\n x: offsetX + legend.swatchSize + legend.swatchGap,\n y: offsetY + legend.swatchSize / 2,\n 'dominant-baseline': 'central',\n });\n applyTextStyle(label, legend.labelStyle);\n label.textContent = entry.label;\n entryG.appendChild(label);\n\n g.appendChild(entryG);\n\n // Advance position for next entry\n if (isHorizontal) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n offsetX += entryWidth;\n } else {\n offsetY += legend.swatchSize + legend.entryGap;\n }\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Brand rendering\n// ---------------------------------------------------------------------------\n\nconst BRAND_URL = 'https://tryopendata.ai';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/**\n * Render the \"OpenData\" brand as a footer-row element, right-aligned on the\n * same baseline as the first bottom chrome text (source/byline/footer).\n * Uses the same font size as chrome source text so it blends in as a subtle\n * footer item rather than occupying independent visual space.\n */\nfunction renderBrand(parent: SVGElement, layout: ChartLayout): void {\n if (layout.dimensions.width < BRAND_MIN_WIDTH) return;\n\n const { width } = layout.dimensions;\n const padding = layout.theme.spacing.padding;\n const rightEdge = width - padding;\n const fill = layout.theme.colors.axis;\n\n // Vertically align with the first bottom chrome element.\n const { chrome } = layout;\n const xAxisExtent = computeXAxisExtent(layout);\n const bottomOffset = layout.area.y + layout.area.height + xAxisExtent;\n const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;\n const chromeY = firstBottom\n ? bottomOffset + firstBottom.y\n : bottomOffset + layout.theme.spacing.chartToFooter;\n\n const a = createSVGElement('a');\n a.setAttribute('href', BRAND_URL);\n a.setAttributeNS(XLINK_NS, 'xlink:href', BRAND_URL);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.setAttribute('class', 'oc-chrome-ref');\n\n // \"try\" in normal weight, \"OpenData\" in semibold, \".ai\" in normal weight,\n // rendered as a single right-aligned text element with three tspans.\n // Use alphabetic baseline so mixed-size tspans share a common bottom line.\n const BRAND_LARGE = 16;\n const text = createSVGElement('text');\n setAttrs(text, {\n x: rightEdge,\n y: chromeY + BRAND_LARGE,\n 'dominant-baseline': 'alphabetic',\n 'font-family': layout.theme.fonts.family,\n 'font-size': BRAND_FONT_SIZE,\n 'text-anchor': 'end',\n 'fill-opacity': 0.55,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', fill);\n\n const trySpan = createSVGElement('tspan');\n trySpan.setAttribute('font-weight', '500');\n trySpan.textContent = 'try';\n text.appendChild(trySpan);\n\n const openDataSpan = createSVGElement('tspan');\n openDataSpan.setAttribute('font-weight', '600');\n openDataSpan.setAttribute('font-size', String(BRAND_LARGE));\n openDataSpan.textContent = 'OpenData';\n text.appendChild(openDataSpan);\n\n const aiSpan = createSVGElement('tspan');\n aiSpan.setAttribute('font-weight', '500');\n aiSpan.textContent = '.ai';\n text.appendChild(aiSpan);\n\n a.appendChild(text);\n parent.appendChild(a);\n}\n\n// ---------------------------------------------------------------------------\n// Main render function\n// ---------------------------------------------------------------------------\n\n/**\n * Render a compiled ChartLayout into an SVG element and append it to a container.\n *\n * @param layout - Compiled ChartLayout from compileChart().\n * @param container - DOM element to mount the SVG into.\n * @returns The created SVG element.\n */\nexport function renderChartSVG(\n layout: ChartLayout,\n container: HTMLElement,\n opts?: { animate?: boolean },\n): SVGElement {\n const { width, height } = layout.dimensions;\n const animation = layout.animation;\n\n // Set module-level animation state so mark renderers can access it\n currentAnimation = animation;\n\n const svg = createSVGElement('svg') as SVGSVGElement;\n setAttrs(svg, {\n viewBox: `0 0 ${width} ${height}`,\n xmlns: SVG_NS,\n // WebKit/iOS Safari getBBox() bug: text with dominant-baseline:hanging\n // reports bounding boxes extending above y=0. The SVG spec default\n // overflow is \"hidden\", which clips this phantom extent. Setting\n // overflow:visible prevents the clipping. Chart marks are already\n // constrained by a clipPath, so nothing bleeds out.\n overflow: 'visible',\n });\n // Set explicit pixel height via inline style. iOS Safari misresolves CSS\n // height:100% when the ancestor chain uses minHeight instead of height,\n // causing the top of the chart (title) to clip on real mobile devices.\n svg.style.height = `${height}px`;\n svg.setAttribute('role', layout.a11y.role);\n svg.setAttribute('aria-label', layout.a11y.altText);\n\n // oc-animate must be set before the SVG enters the DOM to prevent a flash\n // of the final state. mount.ts passes animate: true only on genuine first render.\n const classes = opts?.animate ? 'oc-chart oc-animate' : 'oc-chart';\n svg.setAttribute('class', classes);\n\n // Set animation CSS custom properties when enabled\n if (animation?.enabled) {\n const markCount = layout.marks.length;\n const stagger = clampStaggerDelay(animation.staggerDelay, markCount);\n svg.style.setProperty('--oc-animation-duration', `${animation.duration}ms`);\n svg.style.setProperty('--oc-animation-stagger', `${stagger}ms`);\n svg.style.setProperty('--oc-annotation-delay', `${animation.annotationDelay}ms`);\n const easeVar = EASE_VAR_MAP[animation.ease] || EASE_VAR_MAP.smooth;\n svg.style.setProperty('--oc-animation-ease', easeVar);\n\n // Compute per-segment duration for stacked bars so the total bar animation\n // time stays consistent regardless of segment count.\n // stackPos is set by the engine (0-indexed position within each stack group).\n let maxSegments = 0;\n for (const m of layout.marks) {\n if (m.type === 'rect') {\n const pos = (m as RectMark).stackPos;\n if (pos !== undefined && pos + 1 > maxSegments) {\n maxSegments = pos + 1;\n }\n }\n }\n if (maxSegments > 0) {\n const segDuration = Math.round(animation.duration / maxSegments);\n svg.style.setProperty('--oc-stack-segment-duration', `${segDuration}ms`);\n }\n }\n\n // Background\n const bg = createSVGElement('rect');\n setAttrs(bg, {\n x: 0,\n y: 0,\n width,\n height,\n fill: layout.theme.colors.background,\n });\n svg.appendChild(bg);\n\n // Clip path to prevent marks (especially area fills) from overflowing\n // into the chrome region (title/subtitle). Extends full width so\n // end-of-line labels aren't clipped, but constrains vertically.\n const clipId = `oc-clip-${Math.random().toString(36).slice(2, 8)}`;\n const defs = createSVGElement('defs');\n const clipPath = createSVGElement('clipPath');\n clipPath.setAttribute('id', clipId);\n const clipRect = createSVGElement('rect');\n setAttrs(clipRect, {\n x: 0,\n y: layout.area.y,\n width,\n height: layout.area.height + 2,\n });\n clipPath.appendChild(clipRect);\n defs.appendChild(clipPath);\n\n // Build gradient defs for marks with gradient fills\n currentGradientMap = buildGradientDefs(layout.marks as Array<{ fill?: unknown }>, defs);\n\n svg.appendChild(defs);\n\n // Render layers in order (back to front)\n // Axes render outside clip (labels extend beyond chart area)\n renderAxes(svg, layout);\n\n // Marks are clipped to chart area so area fills don't cover chrome\n const clippedGroup = createSVGElement('g');\n clippedGroup.setAttribute('clip-path', `url(#${clipId})`);\n renderMarks(clippedGroup, layout);\n\n // Add transparent overlay rect for line/area charts to enable voronoi tooltip lookup.\n // Only added when there are line or area marks with dataPoints, and no explicit\n // PointMark objects (which use per-element event handling instead).\n const hasLineOrAreaWithDataPoints = layout.marks.some(\n (m) => (m.type === 'line' || m.type === 'area') && m.dataPoints && m.dataPoints.length > 0,\n );\n const hasPointMarks = layout.marks.some((m) => m.type === 'point');\n if (hasLineOrAreaWithDataPoints && !hasPointMarks) {\n const overlay = createSVGElement('rect');\n setAttrs(overlay, {\n x: layout.area.x,\n y: layout.area.y,\n width: layout.area.width,\n height: layout.area.height,\n fill: 'transparent',\n });\n overlay.setAttribute('class', 'oc-voronoi-overlay');\n overlay.setAttribute('data-voronoi-overlay', 'true');\n clippedGroup.appendChild(overlay);\n }\n\n svg.appendChild(clippedGroup);\n\n renderAnnotations(svg, layout);\n renderLegend(svg, layout.legend);\n\n // Chrome renders on top so titles are never obscured by chart elements\n renderChrome(svg, layout);\n\n // Brand renders as a footer item, right-aligned on the source/footer row\n if (layout.watermark) {\n renderBrand(svg, layout);\n }\n\n // Reset module-level state after rendering\n currentAnimation = undefined;\n currentGradientMap = new Map();\n\n container.appendChild(svg);\n return svg;\n}\n","/**\n * SVG gradient utilities: creates <linearGradient> and <radialGradient>\n * elements from GradientDef specs and resolves mark fills to url(#id) refs.\n */\n\nimport type { GradientDef, LinearGradient, RadialGradient } from '@opendata-ai/openchart-core';\nimport { isGradientDef } from '@opendata-ai/openchart-core';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Produce a stable, deterministic key for a GradientDef.\n * Used for deduplication so identical gradients share one SVG element.\n * Recursively sorts object keys for stability across property order variations.\n */\nfunction gradientKey(def: GradientDef): string {\n return sortedStringify(def);\n}\n\nfunction sortedStringify(value: unknown): string {\n if (value === null || value === undefined) return String(value);\n if (Array.isArray(value)) return `[${value.map(sortedStringify).join(',')}]`;\n if (typeof value === 'object') {\n const sorted = Object.keys(value)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${sortedStringify((value as Record<string, unknown>)[k])}`);\n return `{${sorted.join(',')}}`;\n }\n return JSON.stringify(value);\n}\n\n/**\n * Create a single SVG gradient element (<linearGradient> or <radialGradient>).\n * Uses gradientUnits=\"objectBoundingBox\" so coordinates are in [0,1] space.\n */\nfunction createGradientElement(def: GradientDef, id: string): SVGElement {\n if (def.gradient === 'linear') {\n return createLinearGradient(def, id);\n }\n return createRadialGradient(def, id);\n}\n\nfunction createLinearGradient(def: LinearGradient, id: string): SVGElement {\n const el = document.createElementNS(SVG_NS, 'linearGradient');\n el.setAttribute('id', id);\n el.setAttribute('gradientUnits', 'objectBoundingBox');\n el.setAttribute('x1', String(def.x1 ?? 0));\n el.setAttribute('y1', String(def.y1 ?? 0));\n el.setAttribute('x2', String(def.x2 ?? 0));\n el.setAttribute('y2', String(def.y2 ?? 1));\n\n for (const stop of def.stops) {\n appendStop(el, stop);\n }\n\n return el;\n}\n\nfunction createRadialGradient(def: RadialGradient, id: string): SVGElement {\n const el = document.createElementNS(SVG_NS, 'radialGradient');\n el.setAttribute('id', id);\n el.setAttribute('gradientUnits', 'objectBoundingBox');\n // SVG radialGradient: cx/cy/r = outer circle, fx/fy/fr = focal (inner) circle\n // Spec: x2/y2/r2 = outer, x1/y1/r1 = inner (focal)\n el.setAttribute('cx', String(def.x2 ?? 0.5));\n el.setAttribute('cy', String(def.y2 ?? 0.5));\n el.setAttribute('r', String(def.r2 ?? 0.5));\n el.setAttribute('fx', String(def.x1 ?? 0.5));\n el.setAttribute('fy', String(def.y1 ?? 0.5));\n el.setAttribute('fr', String(def.r1 ?? 0));\n\n for (const stop of def.stops) {\n appendStop(el, stop);\n }\n\n return el;\n}\n\nfunction appendStop(\n parent: SVGElement,\n stop: { offset: number; color: string; opacity?: number },\n): void {\n const stopEl = document.createElementNS(SVG_NS, 'stop');\n stopEl.setAttribute('offset', String(stop.offset));\n stopEl.setAttribute('stop-color', stop.color);\n if (stop.opacity !== undefined) {\n stopEl.setAttribute('stop-opacity', String(stop.opacity));\n }\n parent.appendChild(stopEl);\n}\n\n/**\n * Global counter for gradient IDs. Ensures uniqueness across all charts\n * on the same page, since SVG url(#id) resolves globally in the document.\n */\nlet globalGradientCounter = 0;\n\n/**\n * Scan all marks for GradientDef fill values, create SVG gradient elements\n * in the provided <defs> node, and return a map from gradient key to element ID.\n *\n * Identical gradients (by key) share a single SVG element within one chart.\n * IDs are globally unique across charts to avoid SVG url(#id) collisions.\n */\nexport function buildGradientDefs(\n marks: Array<{ fill?: unknown }>,\n defs: SVGElement,\n): Map<string, string> {\n const map = new Map<string, string>();\n\n for (const mark of marks) {\n const fill = mark.fill;\n if (fill && isGradientDef(fill)) {\n const key = gradientKey(fill);\n if (!map.has(key)) {\n const id = `oc-grad-${globalGradientCounter++}`;\n const el = createGradientElement(fill, id);\n defs.appendChild(el);\n map.set(key, id);\n }\n }\n }\n\n return map;\n}\n\n/**\n * Resolve a mark's fill value to a CSS/SVG fill string.\n * Returns the color string directly for plain fills,\n * or \"url(#gradientId)\" for gradient fills.\n */\nexport function resolveMarkFill(\n fill: string | GradientDef,\n gradientMap: Map<string, string>,\n): string {\n if (typeof fill === 'string') return fill;\n const key = gradientKey(fill);\n const id = gradientMap.get(key);\n return id ? `url(#${id})` : '#000000';\n}\n","/**\n * Text edit overlay: creates a positioned textarea over an SVG text element\n * for inline editing. Handles commit (Enter), cancel (Escape), and\n * click-outside-to-commit behavior.\n */\n\nexport interface TextEditOverlayConfig {\n /** The container div that holds the SVG. */\n container: HTMLElement;\n /** The root SVG element. */\n svg: SVGSVGElement;\n /** The SVG text element being edited. */\n targetElement: SVGElement;\n /** Current text content to populate the textarea. */\n currentText: string;\n /** Called when the user commits the edit (Enter or click outside). */\n onCommit: (newText: string) => void;\n /** Called when the user cancels the edit (Escape). */\n onCancel: () => void;\n}\n\n/**\n * Get the viewBox-to-pixel scale factors for an SVG element.\n * Same approach used by the drag handlers in mount.ts.\n */\nfunction getScale(svg: SVGSVGElement): { scaleX: number; scaleY: number } {\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n return {\n scaleX: viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1,\n scaleY: viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1,\n };\n}\n\n/**\n * Read computed font styles from an SVG text element and map them to CSS.\n */\nfunction getTextStyles(\n targetElement: SVGElement,\n scale: { scaleX: number; scaleY: number },\n): {\n fontFamily: string;\n fontSize: string;\n fontWeight: string;\n color: string;\n textAlign: string;\n lineHeight: string;\n} {\n const computed = window.getComputedStyle(targetElement);\n\n // Font size needs to be scaled from SVG viewBox units to pixel units\n const svgFontSize = parseFloat(\n targetElement.getAttribute('font-size') ?? computed.fontSize ?? '14',\n );\n const pixelFontSize = svgFontSize * scale.scaleY;\n\n const fontFamily = targetElement.getAttribute('font-family') ?? computed.fontFamily ?? 'inherit';\n const fontWeight = targetElement.getAttribute('font-weight') ?? computed.fontWeight ?? '400';\n\n // Get fill color from inline style or attribute\n const fill =\n (targetElement as SVGElement & ElementCSSInlineStyle).style.getPropertyValue('fill') ||\n targetElement.getAttribute('fill') ||\n computed.color ||\n '#000';\n\n // Map SVG text-anchor to CSS text-align\n const textAnchor = targetElement.getAttribute('text-anchor') ?? 'start';\n let textAlign = 'left';\n if (textAnchor === 'middle') textAlign = 'center';\n else if (textAnchor === 'end') textAlign = 'right';\n\n return {\n fontFamily,\n fontSize: `${pixelFontSize}px`,\n fontWeight,\n color: fill,\n textAlign,\n lineHeight: '1.3',\n };\n}\n\n/**\n * Compute the pixel position and size for the textarea based on the\n * target SVG element's bounding box.\n */\nfunction computePosition(\n targetElement: SVGElement,\n svg: SVGSVGElement,\n container: HTMLElement,\n): { top: number; left: number; width: number; height: number } {\n const bbox = (targetElement as SVGGraphicsElement).getBBox();\n const scale = getScale(svg);\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n\n // SVG viewBox coords -> pixel coords relative to the container\n const padding = 4;\n const left = bbox.x * scale.scaleX + (svgRect.left - containerRect.left) - padding;\n const top = bbox.y * scale.scaleY + (svgRect.top - containerRect.top) - padding;\n const width = bbox.width * scale.scaleX + padding * 2;\n const height = bbox.height * scale.scaleY + padding * 2;\n\n return {\n top: Math.max(0, top),\n left: Math.max(0, left),\n width: Math.max(width, 60),\n height: Math.max(height, 24),\n };\n}\n\n/**\n * Create an inline text editing overlay positioned over an SVG text element.\n * Returns an object with a `destroy()` method to clean up.\n */\nexport function createTextEditOverlay(config: TextEditOverlayConfig): { destroy: () => void } {\n const { container, svg, targetElement, currentText, onCommit, onCancel } = config;\n\n let destroyed = false;\n\n // Hide the underlying SVG text element (not display:none to preserve layout)\n const originalOpacity = targetElement.getAttribute('opacity');\n targetElement.setAttribute('opacity', '0');\n\n // Compute position and styles\n const scale = getScale(svg);\n const styles = getTextStyles(targetElement, scale);\n const position = computePosition(targetElement, svg, container);\n\n // Create the textarea\n const textarea = document.createElement('textarea');\n textarea.value = currentText;\n\n // Ensure container is positioned so absolute children work\n const containerPosition = window.getComputedStyle(container).position;\n const containerWasStatic = containerPosition === 'static';\n if (containerWasStatic) {\n container.style.position = 'relative';\n }\n\n // Style the textarea to match the SVG text\n Object.assign(textarea.style, {\n position: 'absolute',\n top: `${position.top}px`,\n left: `${position.left}px`,\n width: `${position.width}px`,\n minHeight: `${position.height}px`,\n fontFamily: styles.fontFamily,\n fontSize: styles.fontSize,\n fontWeight: styles.fontWeight,\n color: styles.color,\n textAlign: styles.textAlign,\n lineHeight: styles.lineHeight,\n padding: '2px 4px',\n margin: '0',\n border: '1px solid rgba(79, 70, 229, 0.4)',\n borderRadius: '3px',\n background: 'rgba(255, 255, 255, 0.95)',\n outline: 'none',\n resize: 'none',\n overflow: 'hidden',\n boxSizing: 'border-box',\n zIndex: '10000',\n // Remove default textarea appearance\n WebkitAppearance: 'none',\n appearance: 'none',\n } as Record<string, string>);\n\n container.appendChild(textarea);\n\n // Auto-select all text\n textarea.focus();\n textarea.select();\n\n // Cleanup function\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Restore SVG text visibility\n if (originalOpacity !== null) {\n targetElement.setAttribute('opacity', originalOpacity);\n } else {\n targetElement.removeAttribute('opacity');\n }\n\n // Remove event listeners\n textarea.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n resizeObserver.disconnect();\n\n // Restore container position if we changed it\n if (containerWasStatic) {\n container.style.position = '';\n }\n\n // Remove the textarea\n if (textarea.parentNode) {\n textarea.parentNode.removeChild(textarea);\n }\n }\n\n function commit(): void {\n if (destroyed) return;\n const newText = textarea.value;\n destroy();\n onCommit(newText);\n }\n\n function cancel(): void {\n if (destroyed) return;\n destroy();\n onCancel();\n }\n\n // Keyboard handling\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n commit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancel();\n }\n };\n\n textarea.addEventListener('keydown', handleKeyDown);\n\n // Click outside to commit\n const handleClickOutside = (e: MouseEvent) => {\n if (!textarea.contains(e.target as Node)) {\n commit();\n }\n };\n\n // Delay attaching click-outside so the current click event doesn't trigger it\n requestAnimationFrame(() => {\n if (!destroyed) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n });\n\n // Reposition on container resize\n const resizeObserver = new ResizeObserver(() => {\n if (destroyed) return;\n const newPosition = computePosition(targetElement, svg, container);\n textarea.style.top = `${newPosition.top}px`;\n textarea.style.left = `${newPosition.left}px`;\n textarea.style.width = `${newPosition.width}px`;\n textarea.style.minHeight = `${newPosition.height}px`;\n });\n resizeObserver.observe(container);\n\n return { destroy };\n}\n","/**\n * Table cell renderers: produce DOM elements for each cell type.\n *\n * Each renderer takes a resolved TableCell and returns an HTMLElement\n * (typically a <td>) with appropriate content, styling, and classes.\n */\n\nimport type {\n BarTableCell,\n CategoryTableCell,\n FlagTableCell,\n HeatmapTableCell,\n ImageTableCell,\n SparklineData,\n SparklineTableCell,\n TableCell,\n TextTableCell,\n} from '@opendata-ai/openchart-core';\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/** Apply common cell styles (background, color, font weight, font variant). */\nfunction applyCellStyle(td: HTMLTableCellElement, cell: TableCell): void {\n if (cell.style.backgroundColor) {\n td.style.background = cell.style.backgroundColor;\n }\n if (cell.style.color) {\n td.style.color = cell.style.color;\n }\n if (cell.style.fontWeight) {\n td.style.fontWeight = String(cell.style.fontWeight);\n }\n if (cell.style.fontVariant) {\n td.style.fontVariant = cell.style.fontVariant;\n }\n if (cell.aria) {\n td.setAttribute('aria-label', cell.aria);\n }\n}\n\n/**\n * Convert a 2-char ISO 3166-1 alpha-2 country code to a flag emoji.\n * Each letter maps to a Regional Indicator Symbol (offset 0x1F1A5 from ASCII).\n */\nfunction countryToEmoji(code: string): string {\n return [...code.toUpperCase()]\n .map((c) => String.fromCodePoint(c.charCodeAt(0) + 0x1f1a5))\n .join('');\n}\n\n/**\n * Lookup map for common country names by ISO 3166-1 alpha-2 code.\n * Falls back to the raw code for unrecognized values.\n */\nconst COUNTRY_NAMES: Record<string, string> = {\n US: 'United States',\n CN: 'China',\n IN: 'India',\n ID: 'Indonesia',\n BR: 'Brazil',\n PK: 'Pakistan',\n NG: 'Nigeria',\n BD: 'Bangladesh',\n RU: 'Russia',\n MX: 'Mexico',\n JP: 'Japan',\n DE: 'Germany',\n GB: 'United Kingdom',\n FR: 'France',\n IT: 'Italy',\n CA: 'Canada',\n AU: 'Australia',\n KR: 'South Korea',\n ES: 'Spain',\n AR: 'Argentina',\n CO: 'Colombia',\n ZA: 'South Africa',\n TR: 'Turkey',\n SA: 'Saudi Arabia',\n UA: 'Ukraine',\n PL: 'Poland',\n NL: 'Netherlands',\n SE: 'Sweden',\n NO: 'Norway',\n DK: 'Denmark',\n FI: 'Finland',\n CH: 'Switzerland',\n AT: 'Austria',\n BE: 'Belgium',\n PT: 'Portugal',\n IE: 'Ireland',\n NZ: 'New Zealand',\n SG: 'Singapore',\n IL: 'Israel',\n AE: 'United Arab Emirates',\n EG: 'Egypt',\n TH: 'Thailand',\n VN: 'Vietnam',\n PH: 'Philippines',\n MY: 'Malaysia',\n CL: 'Chile',\n PE: 'Peru',\n CZ: 'Czech Republic',\n GR: 'Greece',\n HU: 'Hungary',\n RO: 'Romania',\n ET: 'Ethiopia',\n};\n\n/** Get a human-readable name for a country code. */\nfunction getCountryName(code: string): string {\n return COUNTRY_NAMES[code.toUpperCase()] || code.toUpperCase();\n}\n\n/**\n * Describe a sparkline trend for screen readers.\n * Compares first and last values to determine direction.\n */\nfunction describeSparklineTrend(data: SparklineData): string {\n if (data.type === 'line' && data.points.length >= 2) {\n const first = data.points[0].y;\n const last = data.points[data.points.length - 1].y;\n const count = data.points.length;\n if (last > first) return `Sparkline with ${count} points, trending upward`;\n if (last < first) return `Sparkline with ${count} points, trending downward`;\n return `Sparkline with ${count} points, roughly flat`;\n }\n if ((data.type === 'bar' || data.type === 'column') && data.bars.length > 0) {\n return `${data.type === 'column' ? 'Column' : 'Bar'} sparkline with ${data.bars.length} values`;\n }\n return 'Sparkline';\n}\n\n// ---------------------------------------------------------------------------\n// Cell renderers\n// ---------------------------------------------------------------------------\n\n/** Render a plain text cell. */\nexport function renderTextCell(cell: TextTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.textContent = cell.formattedValue;\n applyCellStyle(td, cell);\n return td;\n}\n\n/** Render a heatmap-colored cell. */\nexport function renderHeatmapCell(cell: HeatmapTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.className = 'oc-table-heatmap';\n td.textContent = cell.formattedValue;\n applyCellStyle(td, cell);\n return td;\n}\n\n/** Render a category-colored cell. */\nexport function renderCategoryCell(cell: CategoryTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.className = 'oc-table-category';\n td.textContent = cell.formattedValue;\n applyCellStyle(td, cell);\n return td;\n}\n\n/** Render a cell with an inline bar visualization. */\nexport function renderBarCell(cell: BarTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n td.className = 'oc-table-bar';\n applyCellStyle(td, cell);\n\n const fill = document.createElement('div');\n fill.className = 'oc-table-bar-fill';\n fill.style.width = `${Math.round(cell.barWidth * 100)}%`;\n fill.style.left = `${Math.round(cell.barOffset * 100)}%`;\n fill.style.background = cell.barColor;\n td.appendChild(fill);\n\n const valueSpan = document.createElement('span');\n valueSpan.className = 'oc-table-bar-value';\n valueSpan.textContent = cell.formattedValue;\n td.appendChild(valueSpan);\n\n return td;\n}\n\n/**\n * Format a sparkline endpoint value for display.\n * Keeps it compact: no decimals for values >= 100, one decimal otherwise.\n */\nfunction formatSparklineValue(v: number): string {\n if (Math.abs(v) >= 1000) {\n return v.toLocaleString('en-US', { maximumFractionDigits: 0 });\n }\n if (Math.abs(v) >= 100) {\n return v.toFixed(0);\n }\n return v.toFixed(1);\n}\n\n/** Render a cell with an inline sparkline SVG. */\nexport function renderSparklineCell(cell: SparklineTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n applyCellStyle(td, cell);\n\n const sparklineData = cell.sparklineData;\n if (!sparklineData || sparklineData.count === 0) {\n td.textContent = cell.formattedValue || '';\n return td;\n }\n\n // Add aria-label describing the trend for screen readers\n const trendDescription = describeSparklineTrend(sparklineData);\n if (!td.getAttribute('aria-label')) {\n td.setAttribute('aria-label', trendDescription);\n }\n\n const wrapper = document.createElement('span');\n wrapper.className = 'oc-table-sparkline';\n\n const svgNS = 'http://www.w3.org/2000/svg';\n\n if (sparklineData.type === 'line') {\n // Infrographic-style sparkline: SVG polyline fills cell width via percentage x-coords.\n // Dots are HTML elements (not SVG circles) to avoid aspect-ratio distortion.\n // Labels are HTML below the SVG.\n const svgH = 28;\n const padY = 4;\n const lineH = svgH - padY * 2;\n\n const svg = document.createElementNS(svgNS, 'svg');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('xmlns', svgNS);\n svg.style.height = `${svgH}px`;\n\n // Compute y positions in pixel space (no viewBox scaling)\n const yPositions = sparklineData.points.map((p) => padY + (1 - p.y) * lineH);\n\n // SVG polyline doesn't support % in points attribute, so use a viewBox\n // with a wide aspect ratio and map x to 0-1000 range. preserveAspectRatio=\"none\"\n // stretches the x-axis to fill the cell width. Y values stay in pixel space\n // since viewBox height matches the SVG height. Only the polyline is in the SVG;\n // dots are HTML elements to avoid circle distortion from the non-uniform scaling.\n const viewW = 1000;\n svg.setAttribute('viewBox', `0 0 ${viewW} ${svgH}`);\n svg.setAttribute('preserveAspectRatio', 'none');\n\n const ptsScaled = sparklineData.points.map((p, i) => ({\n x: p.x * viewW,\n y: yPositions[i],\n }));\n const scaledPointsStr = ptsScaled.map((p) => `${p.x},${p.y}`).join(' ');\n\n const polyline = document.createElementNS(svgNS, 'polyline');\n polyline.setAttribute('points', scaledPointsStr);\n polyline.setAttribute('fill', 'none');\n polyline.setAttribute('stroke', sparklineData.color);\n polyline.setAttribute('stroke-width', '1.5');\n polyline.setAttribute('stroke-linejoin', 'round');\n polyline.setAttribute('vector-effect', 'non-scaling-stroke');\n svg.appendChild(polyline);\n\n wrapper.appendChild(svg);\n\n // HTML dots at start and end (positioned absolutely over the SVG)\n const firstY = yPositions[0];\n const lastY = yPositions[yPositions.length - 1];\n const dotSize = 5;\n\n const startDot = document.createElement('span');\n startDot.className = 'oc-table-sparkline-dot';\n startDot.style.left = '0';\n startDot.style.top = `${firstY - dotSize / 2}px`;\n startDot.style.background = sparklineData.color;\n wrapper.appendChild(startDot);\n\n const endDot = document.createElement('span');\n endDot.className = 'oc-table-sparkline-dot';\n endDot.style.right = '0';\n endDot.style.top = `${lastY - dotSize / 2}px`;\n endDot.style.background = sparklineData.color;\n wrapper.appendChild(endDot);\n\n // HTML labels below the SVG, positioned at left and right edges\n const labelsRow = document.createElement('span');\n labelsRow.className = 'oc-table-sparkline-labels';\n labelsRow.style.color = sparklineData.color;\n\n const startLabel = document.createElement('span');\n startLabel.textContent = formatSparklineValue(sparklineData.startValue);\n labelsRow.appendChild(startLabel);\n\n const endLabel = document.createElement('span');\n endLabel.textContent = formatSparklineValue(sparklineData.endValue);\n labelsRow.appendChild(endLabel);\n\n wrapper.appendChild(labelsRow);\n } else if (sparklineData.type === 'column') {\n // Vertical bars at proportional heights\n const width = 80;\n const height = 20;\n const padding = 2;\n const innerW = width - padding * 2;\n const innerH = height - padding * 2;\n\n const svg = document.createElementNS(svgNS, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n svg.setAttribute('aria-hidden', 'true');\n\n const barCount = sparklineData.bars.length;\n if (barCount > 0) {\n const gap = 1;\n const barW = Math.max(1, (innerW - gap * (barCount - 1)) / barCount);\n\n for (let i = 0; i < barCount; i++) {\n const barH = Math.max(1, sparklineData.bars[i] * innerH);\n const x = padding + i * (barW + gap);\n const y = padding + innerH - barH;\n\n const rect = document.createElementNS(svgNS, 'rect');\n rect.setAttribute('x', String(x));\n rect.setAttribute('y', String(y));\n rect.setAttribute('width', String(barW));\n rect.setAttribute('height', String(barH));\n rect.setAttribute('rx', '1.5');\n rect.setAttribute('fill', sparklineData.color);\n svg.appendChild(rect);\n }\n }\n\n wrapper.appendChild(svg);\n } else {\n // 'bar' type: horizontal bars at proportional widths\n const width = 80;\n const height = 20;\n const padding = 2;\n const innerW = width - padding * 2;\n const innerH = height - padding * 2;\n\n const svg = document.createElementNS(svgNS, 'svg');\n svg.setAttribute('width', String(width));\n svg.setAttribute('height', String(height));\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n svg.setAttribute('aria-hidden', 'true');\n\n const barCount = sparklineData.bars.length;\n if (barCount > 0) {\n const gap = 1;\n const barH = Math.max(1, (innerH - gap * (barCount - 1)) / barCount);\n\n for (let i = 0; i < barCount; i++) {\n const barW = Math.max(1, sparklineData.bars[i] * innerW);\n const x = padding;\n const y = padding + i * (barH + gap);\n\n const rect = document.createElementNS(svgNS, 'rect');\n rect.setAttribute('x', String(x));\n rect.setAttribute('y', String(y));\n rect.setAttribute('width', String(barW));\n rect.setAttribute('height', String(barH));\n rect.setAttribute('rx', '1.5');\n rect.setAttribute('fill', sparklineData.color);\n svg.appendChild(rect);\n }\n }\n\n wrapper.appendChild(svg);\n }\n\n td.appendChild(wrapper);\n\n return td;\n}\n\n/** Render a cell with an image. */\nexport function renderImageCell(cell: ImageTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n applyCellStyle(td, cell);\n\n const wrapper = document.createElement('span');\n wrapper.className = `oc-table-image${cell.rounded ? ' oc-table-image-rounded' : ''}`;\n\n const img = document.createElement('img');\n img.src = cell.src;\n img.alt = cell.formattedValue || '';\n img.width = cell.imageWidth;\n img.height = cell.imageHeight;\n img.loading = 'lazy';\n\n wrapper.appendChild(img);\n td.appendChild(wrapper);\n\n return td;\n}\n\n/** Render a cell with a country flag emoji. */\nexport function renderFlagCell(cell: FlagTableCell): HTMLTableCellElement {\n const td = document.createElement('td');\n applyCellStyle(td, cell);\n\n const span = document.createElement('span');\n span.className = 'oc-table-flag';\n span.setAttribute('role', 'img');\n\n if (cell.countryCode && cell.countryCode.length === 2) {\n const countryName = getCountryName(cell.countryCode);\n span.textContent = countryToEmoji(cell.countryCode);\n span.setAttribute('aria-label', `Flag: ${countryName}`);\n } else {\n span.textContent = cell.formattedValue;\n span.setAttribute('aria-label', cell.formattedValue);\n }\n\n td.appendChild(span);\n\n return td;\n}\n\n// ---------------------------------------------------------------------------\n// Dispatcher\n// ---------------------------------------------------------------------------\n\n/** Render any table cell by dispatching on its cellType. */\nexport function renderCell(cell: TableCell): HTMLTableCellElement {\n switch (cell.cellType) {\n case 'text':\n return renderTextCell(cell);\n case 'heatmap':\n return renderHeatmapCell(cell);\n case 'category':\n return renderCategoryCell(cell);\n case 'bar':\n return renderBarCell(cell);\n case 'sparkline':\n return renderSparklineCell(cell);\n case 'image':\n return renderImageCell(cell);\n case 'flag':\n return renderFlagCell(cell);\n default:\n // Exhaustive check fallback\n return renderTextCell(cell as TextTableCell);\n }\n}\n","/**\n * Sankey mount API: the main entry point for vanilla JS sankey usage.\n *\n * createSankey() takes a container, SankeySpec, and options, compiles the\n * sankey, renders it as SVG, sets up responsive resizing, tooltip interaction,\n * hover highlighting, and returns a SankeyInstance with update/resize/export/destroy.\n */\n\nimport type {\n CompileOptions,\n DarkMode,\n SankeyLayout,\n SankeySpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { compileSankey } from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, setupAnimationCleanup } from './animation';\nimport {\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport { observeResize } from './resize-observer';\nimport { renderSankeySVG } from './sankey-renderer';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SankeyMountOptions {\n /** Theme overrides. */\n theme?: ThemeConfig;\n /** Dark mode setting: \"auto\" (system pref), \"force\", or \"off\". */\n darkMode?: DarkMode;\n /** Enable responsive resizing. Defaults to true. */\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n /** Show tooltips on hover. Defaults to true. */\n tooltip?: boolean;\n /** Callback when a node is clicked. */\n onNodeClick?: (node: Record<string, unknown>) => void;\n /** Callback when a link is clicked. */\n onLinkClick?: (link: Record<string, unknown>) => void;\n /** Callback when a node is hovered (null on mouse leave). */\n onNodeHover?: (node: Record<string, unknown> | null) => void;\n /** Callback when a link is hovered (null on mouse leave). */\n onLinkHover?: (link: Record<string, unknown> | null) => void;\n}\n\nexport interface SankeyInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: SankeySpec): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the sankey diagram. */\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n options?: JPGExportOptions,\n ): string | Promise<Blob> | Promise<string>;\n /** Remove all DOM elements and disconnect observers. */\n destroy(): void;\n /** The current compiled layout. */\n readonly layout: SankeyLayout;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Opacity for links connected to hovered node. */\nconst HIGHLIGHT_OPACITY = 0.7;\n/** Opacity for links NOT connected to hovered node. */\nconst DIM_OPACITY = 0.15;\n/** Opacity for nodes NOT connected to hovered node. */\nconst NODE_DIM_OPACITY = 0.2;\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a sankey instance from a spec and mount it into a container.\n */\nexport function createSankey(\n container: HTMLElement,\n spec: SankeySpec,\n options?: SankeyMountOptions,\n): SankeyInstance {\n let currentSpec = spec;\n let currentLayout: SankeyLayout;\n let destroyed = false;\n\n // DOM\n let svgElement: SVGSVGElement | null = null;\n\n // Subsystems\n let tooltipManager: TooltipManager | null = null;\n let cleanupTooltipEvents: (() => void) | null = null;\n let disconnectResize: (() => void) | null = null;\n\n // Animation state\n let isFirstRender = true;\n let animationCleanup: (() => void) | null = null;\n let pendingResize = false;\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n function compile(): SankeyLayout {\n const { width, height } = getContainerDimensions();\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n };\n\n return compileSankey(currentSpec, compileOpts);\n }\n\n // ---------------------------------------------------------------------------\n // Tooltip and interaction wiring\n // ---------------------------------------------------------------------------\n\n function wireTooltipAndInteraction(svg: SVGSVGElement, layout: SankeyLayout): () => void {\n const cleanups: Array<() => void> = [];\n\n // Wire tooltip on node elements\n const nodeElements = svg.querySelectorAll('.oc-sankey-node');\n for (const el of nodeElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = layout.tooltipDescriptors.get(markId);\n const nodeId = el.getAttribute('data-node-id');\n const nodeData = nodeId ? (layout.nodes.find((n) => n.nodeId === nodeId)?.data ?? {}) : {};\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n if (content && tooltipManager) {\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n options?.onNodeHover?.(nodeData);\n if (nodeId) highlightConnectedLinks(svg, nodeId, layout);\n };\n\n const handleMouseMove = (e: Event) => {\n if (content && tooltipManager) {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n const handleMouseLeave = () => {\n tooltipManager?.hide();\n options?.onNodeHover?.(null);\n resetLinkOpacity(svg, layout);\n };\n\n const handleClick = () => {\n options?.onNodeClick?.(nodeData);\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('click', handleClick);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('click', handleClick);\n });\n }\n\n // Wire tooltip on link elements\n const linkElements = svg.querySelectorAll('.oc-sankey-link');\n for (const el of linkElements) {\n const markId = el.getAttribute('data-mark-id');\n if (!markId) continue;\n\n const content = layout.tooltipDescriptors.get(markId);\n const sourceId = el.getAttribute('data-source');\n const targetId = el.getAttribute('data-target');\n const linkData = findLinkData(layout, sourceId, targetId);\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n if (content && tooltipManager) {\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n options?.onLinkHover?.(linkData);\n };\n\n const handleMouseMove = (e: Event) => {\n if (content && tooltipManager) {\n const mouseEvent = e as MouseEvent;\n const svgRect = svg.getBoundingClientRect();\n const x = mouseEvent.clientX - svgRect.left;\n const y = mouseEvent.clientY - svgRect.top;\n tooltipManager.show(content, x, y);\n }\n };\n\n const handleMouseLeave = () => {\n tooltipManager?.hide();\n options?.onLinkHover?.(null);\n };\n\n const handleClick = () => {\n options?.onLinkClick?.(linkData);\n };\n\n el.addEventListener('mouseenter', handleMouseEnter);\n el.addEventListener('mousemove', handleMouseMove);\n el.addEventListener('mouseleave', handleMouseLeave);\n el.addEventListener('click', handleClick);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handleMouseEnter);\n el.removeEventListener('mousemove', handleMouseMove);\n el.removeEventListener('mouseleave', handleMouseLeave);\n el.removeEventListener('click', handleClick);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n /**\n * Find the data record for a link by source/target ids.\n */\n function findLinkData(\n layout: SankeyLayout,\n sourceId: string | null,\n targetId: string | null,\n ): Record<string, unknown> {\n if (!sourceId || !targetId) return {};\n const link = layout.links.find((l) => l.sourceId === sourceId && l.targetId === targetId);\n return link?.data ?? {};\n }\n\n /**\n * Highlight links connected to a node and dim unconnected links.\n */\n function highlightConnectedLinks(\n svg: SVGSVGElement,\n nodeId: string,\n _layout: SankeyLayout,\n ): void {\n // Collect connected node IDs (the hovered node + its direct neighbors)\n const connectedNodeIds = new Set<string>([nodeId]);\n const linkElements = svg.querySelectorAll('.oc-sankey-link');\n for (const el of linkElements) {\n const source = el.getAttribute('data-source');\n const target = el.getAttribute('data-target');\n const path = el.querySelector('path');\n if (!path) continue;\n\n const isConnected = source === nodeId || target === nodeId;\n path.setAttribute('fill-opacity', String(isConnected ? HIGHLIGHT_OPACITY : DIM_OPACITY));\n if (isConnected) {\n if (source) connectedNodeIds.add(source);\n if (target) connectedNodeIds.add(target);\n }\n }\n\n // Dim unconnected nodes (rect + label)\n const nodeElements = svg.querySelectorAll('.oc-sankey-node');\n for (const el of nodeElements) {\n const nid = el.getAttribute('data-node-id');\n if (!nid) continue;\n const isConnected = connectedNodeIds.has(nid);\n (el as SVGElement).style.opacity = isConnected ? '1' : String(NODE_DIM_OPACITY);\n }\n }\n\n /**\n * Reset all link opacities and node opacities to their original values.\n */\n function resetLinkOpacity(svg: SVGSVGElement, layout: SankeyLayout): void {\n const linkElements = svg.querySelectorAll('.oc-sankey-link');\n for (const el of linkElements) {\n const path = el.querySelector('path');\n if (!path) continue;\n // Look up the original opacity via data attributes rather than positional index\n const source = el.getAttribute('data-source');\n const target = el.getAttribute('data-target');\n const link = layout.links.find((l) => l.sourceId === source && l.targetId === target);\n path.setAttribute('fill-opacity', String(link?.fillOpacity ?? 0.5));\n }\n\n // Restore all node opacities\n const nodeElements = svg.querySelectorAll('.oc-sankey-node');\n for (const el of nodeElements) {\n (el as SVGElement).style.opacity = '1';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n function render(): void {\n if (destroyed) return;\n\n // Cancel in-progress animations before tearing down\n if (animationCleanup) {\n animationCleanup();\n animationCleanup = null;\n }\n if (svgElement) {\n cancelAnimations(svgElement);\n }\n\n // Clean up previous tooltip listeners\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n\n // Remove old SVG\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n\n // Compile\n currentLayout = compile();\n\n // Determine if we should animate\n const shouldAnimate = isFirstRender && currentLayout.animation?.enabled;\n isFirstRender = false;\n\n // Render\n const animation = shouldAnimate ? currentLayout.animation : undefined;\n svgElement = renderSankeySVG(currentLayout, animation);\n container.appendChild(svgElement);\n\n // Dark mode class on container\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Wire tooltip + interaction events\n if (options?.tooltip !== false && svgElement) {\n if (!tooltipManager) {\n tooltipManager = createTooltipManager(container);\n }\n cleanupTooltipEvents = wireTooltipAndInteraction(svgElement, currentLayout);\n }\n\n // Animation cleanup on first render\n if (shouldAnimate && svgElement) {\n animationCleanup = setupAnimationCleanup(svgElement, () => {\n animationCleanup = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n function update(newSpec: SankeySpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n isFirstRender = true; // Allow animation on update\n render();\n }\n\n function resize(): void {\n if (destroyed) return;\n // Skip resize during entrance animation to avoid tearing down the animated SVG.\n // Queued resizes replay once animation completes.\n if (animationCleanup) {\n pendingResize = true;\n return;\n }\n render();\n }\n\n function doExport(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n exportOptions?: JPGExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) {\n throw new Error('Sankey is not rendered yet');\n }\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement, exportOptions as SVGExportOptions);\n case 'png':\n return exportPNG(svgElement, exportOptions);\n case 'jpg':\n return exportJPG(svgElement, exportOptions);\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel entrance animations\n if (animationCleanup) {\n animationCleanup();\n animationCleanup = null;\n pendingResize = false;\n }\n if (svgElement) {\n cancelAnimations(svgElement);\n }\n\n // Disconnect resize observer\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n\n // Clean up tooltip events\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n\n // Destroy tooltip manager\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n\n // Remove SVG\n if (svgElement?.parentNode) {\n svgElement.parentNode.removeChild(svgElement);\n }\n svgElement = null;\n\n container.classList.remove('oc-dark');\n }\n\n // ---------------------------------------------------------------------------\n // Initialize\n // ---------------------------------------------------------------------------\n\n try {\n currentLayout = compile();\n\n // Determine if we should animate\n const shouldAnimate = currentLayout.animation?.enabled;\n isFirstRender = false;\n\n // Render\n const animation = shouldAnimate ? currentLayout.animation : undefined;\n svgElement = renderSankeySVG(currentLayout, animation);\n container.appendChild(svgElement);\n\n // Dark mode class on container\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Wire tooltip + interaction events\n if (options?.tooltip !== false && svgElement) {\n tooltipManager = createTooltipManager(container);\n cleanupTooltipEvents = wireTooltipAndInteraction(svgElement, currentLayout);\n }\n\n // Animation cleanup\n if (shouldAnimate && svgElement) {\n animationCleanup = setupAnimationCleanup(svgElement, () => {\n animationCleanup = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n });\n }\n } catch (err) {\n console.error('[viz] Sankey mount failed:', err);\n // Re-throw so callers can handle the error rather than silently returning a broken instance\n throw err;\n }\n\n // Responsive resize\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n resize();\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n destroy,\n get layout() {\n return currentLayout;\n },\n };\n}\n","/**\n * Sankey SVG renderer: converts a SankeyLayout into SVG DOM elements.\n *\n * Creates an <svg> with gradient defs, links (behind), nodes, labels,\n * legend, and chrome. All styling via inline SVG attributes from layout data.\n * Animation is pure CSS, driven by data attributes and CSS custom properties.\n */\n\nimport type {\n LegendLayout,\n ResolvedAnimation,\n ResolvedChromeElement,\n SankeyLayout,\n SankeyLinkMark,\n SankeyNodeMark,\n TextStyle,\n} from '@opendata-ai/openchart-core';\nimport { BRAND_FONT_SIZE, BRAND_MIN_WIDTH, estimateTextWidth } from '@opendata-ai/openchart-core';\nimport { clampStaggerDelay } from '@opendata-ai/openchart-engine';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\nconst BRAND_URL = 'https://tryopendata.ai';\n\n/** CSS easing preset map for inline style custom properties. */\nconst EASE_VAR_MAP: Record<string, string> = {\n smooth: 'var(--oc-ease-smooth)',\n snappy: 'var(--oc-ease-snappy)',\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createSVGElement(tag: string): SVGElement {\n return document.createElementNS(SVG_NS, tag);\n}\n\nfunction setAttrs(el: SVGElement, attrs: Record<string, string | number>): void {\n for (const [key, value] of Object.entries(attrs)) {\n el.setAttribute(key, String(value));\n }\n}\n\nfunction applyTextStyle(el: SVGElement, style: TextStyle): void {\n setAttrs(el, {\n 'font-family': style.fontFamily,\n 'font-size': style.fontSize,\n 'font-weight': style.fontWeight,\n });\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', style.fill);\n if (style.textAnchor) {\n el.setAttribute('text-anchor', style.textAnchor);\n }\n if (style.dominantBaseline) {\n el.setAttribute('dominant-baseline', style.dominantBaseline);\n }\n if (style.fontVariant) {\n el.setAttribute('font-variant', style.fontVariant);\n }\n}\n\n/**\n * Stamp animation index attributes on a mark element when animation is enabled.\n */\nfunction stampAnimationAttrs(\n el: SVGElement,\n mark: { animationIndex?: number },\n fallbackIndex: number,\n animation?: ResolvedAnimation,\n): void {\n if (!animation?.enabled) return;\n const idx = mark.animationIndex ?? fallbackIndex;\n el.setAttribute('data-animation-index', String(idx));\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('--oc-mark-index', String(idx));\n}\n\n// ---------------------------------------------------------------------------\n// Chrome rendering\n// ---------------------------------------------------------------------------\n\n/**\n * Break text into lines that fit within maxWidth using word wrapping.\n */\nfunction wrapText(text: string, fontSize: number, fontWeight: number, maxWidth: number): string[] {\n if (maxWidth <= 0) return [text];\n\n const AVG_CHAR_WIDTH = 0.55;\n const WEIGHT_FACTORS: Record<number, number> = {\n 100: 0.9,\n 200: 0.92,\n 300: 0.95,\n 400: 1.0,\n 500: 1.02,\n 600: 1.05,\n 700: 1.08,\n 800: 1.1,\n 900: 1.12,\n };\n const weightFactor = WEIGHT_FACTORS[fontWeight] ?? 1.0;\n const charWidth = fontSize * AVG_CHAR_WIDTH * weightFactor;\n const maxChars = Math.floor(maxWidth / charWidth);\n\n if (text.length <= maxChars) return [text];\n\n const words = text.split(' ');\n const lines: string[] = [];\n let current = '';\n\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n if (candidate.length > maxChars && current) {\n lines.push(current);\n current = word;\n } else {\n current = candidate;\n }\n }\n if (current) lines.push(current);\n\n return lines;\n}\n\nfunction renderChromeElement(\n parent: SVGElement,\n element: ResolvedChromeElement,\n className: string,\n chromeKey: string,\n): void {\n const text = createSVGElement('text');\n setAttrs(text, { x: element.x, y: element.y });\n applyTextStyle(text, element.style);\n text.setAttribute('class', className);\n text.setAttribute('data-chrome-key', chromeKey);\n\n const lines = wrapText(\n element.text,\n element.style.fontSize,\n element.style.fontWeight,\n element.maxWidth,\n );\n\n if (lines.length === 1) {\n text.textContent = element.text;\n } else {\n const lineHeight = element.style.fontSize * (element.style.lineHeight ?? 1.3);\n for (let i = 0; i < lines.length; i++) {\n const tspan = createSVGElement('tspan');\n setAttrs(tspan, { x: element.x, dy: i === 0 ? 0 : lineHeight });\n tspan.textContent = lines[i];\n text.appendChild(tspan);\n }\n }\n\n parent.appendChild(text);\n}\n\nfunction renderChrome(parent: SVGElement, layout: SankeyLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-chrome');\n\n const { chrome } = layout;\n\n if (chrome.title) {\n renderChromeElement(g, chrome.title, 'oc-title', 'title');\n }\n if (chrome.subtitle) {\n renderChromeElement(g, chrome.subtitle, 'oc-subtitle', 'subtitle');\n }\n\n // Bottom chrome: positioned below the sankey drawing area.\n // Sankey has no x-axis, so no extra axis extent to account for.\n const bottomOffset = layout.area.y + layout.area.height;\n if (chrome.source) {\n renderChromeElement(\n g,\n { ...chrome.source, y: bottomOffset + chrome.source.y },\n 'oc-source',\n 'source',\n );\n }\n if (chrome.byline) {\n renderChromeElement(\n g,\n { ...chrome.byline, y: bottomOffset + chrome.byline.y },\n 'oc-byline',\n 'byline',\n );\n }\n if (chrome.footer) {\n renderChromeElement(\n g,\n { ...chrome.footer, y: bottomOffset + chrome.footer.y },\n 'oc-footer',\n 'footer',\n );\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Brand rendering\n// ---------------------------------------------------------------------------\n\nfunction renderBrand(parent: SVGElement, layout: SankeyLayout): void {\n if (layout.dimensions.width < BRAND_MIN_WIDTH) return;\n\n const { width } = layout.dimensions;\n const padding = layout.theme.spacing.padding;\n const rightEdge = width - padding;\n const fill = layout.theme.colors.axis;\n\n const bottomOffset = layout.area.y + layout.area.height;\n const { chrome } = layout;\n const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;\n const chromeY = firstBottom\n ? bottomOffset + firstBottom.y\n : bottomOffset + layout.theme.spacing.chartToFooter;\n\n const a = createSVGElement('a');\n a.setAttribute('href', BRAND_URL);\n a.setAttributeNS(XLINK_NS, 'xlink:href', BRAND_URL);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.setAttribute('class', 'oc-chrome-ref');\n\n const BRAND_LARGE = 16;\n const text = createSVGElement('text');\n setAttrs(text, {\n x: rightEdge,\n y: chromeY + BRAND_LARGE,\n 'dominant-baseline': 'alphabetic',\n 'text-anchor': 'end',\n 'font-family': layout.theme.fonts.family,\n 'font-size': BRAND_FONT_SIZE,\n 'fill-opacity': 0.55,\n });\n (text as SVGElement & ElementCSSInlineStyle).style.setProperty('fill', fill);\n\n const trySpan = createSVGElement('tspan');\n setAttrs(trySpan, { 'font-weight': 500 });\n trySpan.textContent = 'try';\n\n const openDataSpan = createSVGElement('tspan');\n setAttrs(openDataSpan, { 'font-weight': 600, 'font-size': BRAND_LARGE });\n openDataSpan.textContent = 'OpenData';\n\n const aiSpan = createSVGElement('tspan');\n setAttrs(aiSpan, { 'font-weight': 500 });\n aiSpan.textContent = '.ai';\n\n text.appendChild(trySpan);\n text.appendChild(openDataSpan);\n text.appendChild(aiSpan);\n a.appendChild(text);\n parent.appendChild(a);\n}\n\n// ---------------------------------------------------------------------------\n// Legend rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLegend(parent: SVGElement, legend: LegendLayout): void {\n if (legend.entries.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-legend');\n g.setAttribute('role', 'list');\n g.setAttribute('aria-label', 'Chart legend');\n\n const isHorizontal = legend.position === 'top' || legend.position === 'bottom';\n let offsetX = legend.bounds.x;\n let offsetY = legend.bounds.y;\n\n for (let i = 0; i < legend.entries.length; i++) {\n const entry = legend.entries[i];\n\n // Wrap to next line if this entry would overflow bounds\n if (isHorizontal && i > 0) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n if (offsetX + entryWidth > legend.bounds.x + legend.bounds.width) {\n offsetX = legend.bounds.x;\n offsetY += legend.swatchSize + 6;\n }\n }\n\n const entryG = createSVGElement('g');\n entryG.setAttribute('class', 'oc-legend-entry');\n entryG.setAttribute('role', 'listitem');\n entryG.setAttribute('data-legend-index', String(i));\n entryG.setAttribute('data-legend-label', entry.label);\n\n if (entry.overflow) {\n entryG.setAttribute('data-legend-overflow', 'true');\n entryG.setAttribute('aria-label', entry.label);\n entryG.setAttribute('opacity', '0.5');\n } else {\n entryG.setAttribute(\n 'aria-label',\n `${entry.label}: ${entry.active !== false ? 'visible' : 'hidden'}`,\n );\n entryG.setAttribute('style', 'cursor: pointer');\n if (entry.active === false) {\n entryG.setAttribute('opacity', '0.3');\n }\n }\n\n // Swatch (always rect for sankey)\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: offsetX,\n y: offsetY,\n width: legend.swatchSize,\n height: legend.swatchSize,\n fill: entry.color,\n rx: 2,\n });\n entryG.appendChild(rect);\n\n // Label\n const label = createSVGElement('text');\n setAttrs(label, {\n x: offsetX + legend.swatchSize + legend.swatchGap,\n y: offsetY + legend.swatchSize / 2,\n 'dominant-baseline': 'central',\n });\n applyTextStyle(label, legend.labelStyle);\n label.textContent = entry.label;\n entryG.appendChild(label);\n\n g.appendChild(entryG);\n\n // Advance position for next entry\n if (isHorizontal) {\n const labelWidth = estimateTextWidth(\n entry.label,\n legend.labelStyle.fontSize,\n legend.labelStyle.fontWeight,\n );\n const entryWidth = legend.swatchSize + legend.swatchGap + labelWidth + legend.entryGap;\n offsetX += entryWidth;\n } else {\n offsetY += legend.swatchSize + legend.entryGap;\n }\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Gradient defs\n// ---------------------------------------------------------------------------\n\n/**\n * Build a node position lookup for gradient x1/x2 coordinates.\n * Maps nodeId to { x, width } so we can compute gradient endpoints.\n */\nfunction buildNodePositionMap(nodes: SankeyNodeMark[]): Map<string, { x: number; width: number }> {\n const map = new Map<string, { x: number; width: number }>();\n for (const node of nodes) {\n map.set(node.nodeId, { x: node.x, width: node.width });\n }\n return map;\n}\n\n/** Sanitize a string for use as an SVG element ID (no spaces, $, or other invalid chars). */\nfunction sanitizeId(s: string): string {\n return s.replace(/[^a-zA-Z0-9_-]/g, '_');\n}\n\nfunction renderGradientDefs(\n defs: SVGElement,\n links: SankeyLinkMark[],\n nodePositions: Map<string, { x: number; width: number }>,\n): void {\n for (let i = 0; i < links.length; i++) {\n const link = links[i];\n // Only create gradients when source and target colors differ\n if (link.sourceColor === link.targetColor) continue;\n\n // Use sanitized node names for debuggability, with index suffix for uniqueness\n const gradId = `oc-sg-${sanitizeId(link.sourceId)}-${sanitizeId(link.targetId)}-${i}`;\n const gradient = createSVGElement('linearGradient');\n gradient.setAttribute('id', gradId);\n gradient.setAttribute('gradientUnits', 'userSpaceOnUse');\n\n // x1 = right edge of source node, x2 = left edge of target node\n const sourcePos = nodePositions.get(link.sourceId);\n const targetPos = nodePositions.get(link.targetId);\n const x1 = sourcePos ? sourcePos.x + sourcePos.width : 0;\n const x2 = targetPos ? targetPos.x : 0;\n\n gradient.setAttribute('x1', String(x1));\n gradient.setAttribute('x2', String(x2));\n\n const stop0 = createSVGElement('stop');\n setAttrs(stop0, { offset: '0%', 'stop-color': link.sourceColor });\n gradient.appendChild(stop0);\n\n const stop1 = createSVGElement('stop');\n setAttrs(stop1, { offset: '100%', 'stop-color': link.targetColor });\n gradient.appendChild(stop1);\n\n defs.appendChild(gradient);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Links rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLinks(\n parent: SVGElement,\n links: SankeyLinkMark[],\n _nodePositions: Map<string, { x: number; width: number }>,\n animation?: ResolvedAnimation,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-sankey-links');\n\n for (let i = 0; i < links.length; i++) {\n const link = links[i];\n\n const linkG = createSVGElement('g');\n linkG.setAttribute('class', 'oc-sankey-link');\n linkG.setAttribute('data-mark-id', `link-${link.sourceId}-${link.targetId}-${i}`);\n linkG.setAttribute('data-source', link.sourceId);\n linkG.setAttribute('data-target', link.targetId);\n\n if (link.aria?.label) {\n linkG.setAttribute('aria-label', link.aria.label);\n }\n\n stampAnimationAttrs(linkG, link, i, animation);\n\n const path = createSVGElement('path');\n path.setAttribute('d', link.path);\n path.setAttribute('stroke', 'none');\n path.setAttribute('fill-opacity', String(link.fillOpacity));\n\n // Use gradient fill when colors differ, otherwise solid fill\n if (link.sourceColor !== link.targetColor) {\n const gradId = `oc-sg-${sanitizeId(link.sourceId)}-${sanitizeId(link.targetId)}-${i}`;\n path.setAttribute('fill', `url(#${gradId})`);\n } else {\n path.setAttribute('fill', link.sourceColor);\n }\n\n linkG.appendChild(path);\n g.appendChild(linkG);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Nodes rendering\n// ---------------------------------------------------------------------------\n\nfunction renderNodes(\n parent: SVGElement,\n nodes: SankeyNodeMark[],\n animation?: ResolvedAnimation,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-sankey-nodes');\n\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n\n const nodeG = createSVGElement('g');\n nodeG.setAttribute('class', 'oc-sankey-node');\n nodeG.setAttribute('data-mark-id', `node-${node.nodeId}`);\n nodeG.setAttribute('data-node-id', node.nodeId);\n\n if (node.aria?.label) {\n nodeG.setAttribute('aria-label', node.aria.label);\n }\n\n stampAnimationAttrs(nodeG, node, i, animation);\n\n const rect = createSVGElement('rect');\n setAttrs(rect, {\n x: node.x,\n y: node.y,\n width: node.width,\n height: Math.max(node.height, 1), // Ensure at least 1px visibility\n fill: node.fill,\n rx: node.cornerRadius,\n });\n\n if (node.stroke) {\n rect.setAttribute('stroke', node.stroke);\n }\n if (node.strokeWidth) {\n rect.setAttribute('stroke-width', String(node.strokeWidth));\n }\n\n nodeG.appendChild(rect);\n g.appendChild(nodeG);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Labels rendering\n// ---------------------------------------------------------------------------\n\nfunction renderLabels(parent: SVGElement, nodes: SankeyNodeMark[]): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-sankey-labels');\n\n for (const node of nodes) {\n const { label } = node;\n if (!label.visible) continue;\n\n const text = createSVGElement('text');\n setAttrs(text, { x: label.x, y: label.y });\n applyTextStyle(text, label.style);\n text.textContent = label.text;\n\n g.appendChild(text);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Main render function\n// ---------------------------------------------------------------------------\n\n/**\n * Render a SankeyLayout into an SVG element.\n *\n * The SVG structure is: background > defs (gradients) > links > nodes > labels > legend > chrome > brand.\n * Links render before nodes so they appear visually behind.\n */\nexport function renderSankeySVG(\n layout: SankeyLayout,\n animation?: ResolvedAnimation,\n): SVGSVGElement {\n const { width, height } = layout.dimensions;\n\n const svg = createSVGElement('svg') as SVGSVGElement;\n setAttrs(svg, {\n viewBox: `0 0 ${width} ${height}`,\n xmlns: SVG_NS,\n overflow: 'visible',\n });\n svg.style.height = `${height}px`;\n svg.setAttribute('role', layout.a11y.role);\n svg.setAttribute('aria-label', layout.a11y.altText);\n\n // Classes: oc-chart oc-sankey, plus oc-animate if animated\n const animate = animation?.enabled;\n const classes = animate ? 'oc-chart oc-sankey oc-animate' : 'oc-chart oc-sankey';\n svg.setAttribute('class', classes);\n\n // Set animation CSS custom properties when enabled\n if (animation?.enabled) {\n const totalMarks = layout.nodes.length + layout.links.length;\n const stagger = clampStaggerDelay(animation.staggerDelay, totalMarks);\n svg.style.setProperty('--oc-animation-duration', `${animation.duration}ms`);\n svg.style.setProperty('--oc-animation-stagger', `${stagger}ms`);\n svg.style.setProperty('--oc-annotation-delay', `${animation.annotationDelay}ms`);\n const easeVar = EASE_VAR_MAP[animation.ease] || EASE_VAR_MAP.smooth;\n svg.style.setProperty('--oc-animation-ease', easeVar);\n }\n\n // Background\n const bg = createSVGElement('rect');\n bg.setAttribute('class', 'oc-background');\n setAttrs(bg, {\n x: 0,\n y: 0,\n width,\n height,\n fill: layout.theme.colors.background,\n });\n svg.appendChild(bg);\n\n // Defs: gradient definitions for links\n const nodePositions = buildNodePositionMap(layout.nodes);\n const defs = createSVGElement('defs');\n renderGradientDefs(defs, layout.links, nodePositions);\n svg.appendChild(defs);\n\n // Links (behind nodes)\n renderLinks(svg, layout.links, nodePositions, animation);\n\n // Nodes\n renderNodes(svg, layout.nodes, animation);\n\n // Labels\n renderLabels(svg, layout.nodes);\n\n // Legend\n renderLegend(svg, layout.legend);\n\n // Chrome (title, subtitle, source, byline, footer) renders on top\n renderChrome(svg, layout);\n\n // Brand\n if (layout.watermark) {\n renderBrand(svg, layout);\n }\n\n return svg;\n}\n","/**\n * Table keyboard navigation: arrow-key cell navigation, Enter to sort,\n * Escape to clear search, and aria-activedescendant management.\n *\n * Designed to be wired up by table-mount.ts after render. Returns a\n * cleanup function to remove listeners on re-render or destroy.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface KeyboardNavOptions {\n /** The wrapper element containing the whole table UI. */\n wrapper: HTMLElement;\n /** Callback to trigger sort on a column. */\n onSort: (columnKey: string) => void;\n /** Callback to clear search and return focus to the table body. */\n onClearSearch: () => void;\n /** Callback to announce text to screen readers via the live region. */\n onAnnounce: (message: string) => void;\n}\n\ninterface CellPosition {\n row: number;\n col: number;\n}\n\n// ---------------------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------------------\n\n/**\n * Attach keyboard navigation to a rendered table.\n *\n * @returns A cleanup function that removes all event listeners.\n */\nexport function attachKeyboardNav(options: KeyboardNavOptions): () => void {\n const { wrapper, onSort, onClearSearch, onAnnounce } = options;\n\n let focusedCell: CellPosition = { row: -1, col: 0 };\n\n const table = wrapper.querySelector('table');\n if (!table) return () => {};\n\n const tbody = table.querySelector('tbody');\n const thead = table.querySelector('thead');\n if (!tbody || !thead) return () => {};\n\n // Make tbody focusable\n tbody.setAttribute('tabindex', '0');\n\n function getRows(): HTMLTableRowElement[] {\n if (!tbody) return [];\n return Array.from(tbody.querySelectorAll('tr'));\n }\n\n function getHeaderCells(): HTMLTableCellElement[] {\n if (!thead) return [];\n const headerRow = thead.querySelector('tr');\n if (!headerRow) return [];\n return Array.from(headerRow.querySelectorAll('th'));\n }\n\n function getCellsInRow(tr: HTMLTableRowElement): HTMLTableCellElement[] {\n return Array.from(tr.querySelectorAll('td'));\n }\n\n function getColCount(): number {\n const rows = getRows();\n if (rows.length === 0) return getHeaderCells().length;\n return getCellsInRow(rows[0]).length;\n }\n\n function clearFocusHighlight(): void {\n const prev = wrapper.querySelector('.oc-table-cell-focus');\n if (prev) {\n prev.classList.remove('oc-table-cell-focus');\n prev.removeAttribute('id');\n }\n }\n\n function setFocusedCell(row: number, col: number): void {\n clearFocusHighlight();\n const rows = getRows();\n const colCount = getColCount();\n\n // Clamp values\n if (rows.length === 0) return;\n row = Math.max(0, Math.min(row, rows.length - 1));\n col = Math.max(0, Math.min(col, colCount - 1));\n\n focusedCell = { row, col };\n\n // Highlight the cell\n const tr = rows[row];\n if (!tr) return;\n const cells = getCellsInRow(tr);\n const cell = cells[col];\n if (!cell) return;\n\n const cellId = `oc-cell-${row}-${col}`;\n cell.id = cellId;\n cell.classList.add('oc-table-cell-focus');\n cell.setAttribute('data-row', String(row));\n cell.setAttribute('data-col', String(col));\n\n // Set aria-activedescendant on tbody\n if (tbody) {\n tbody.setAttribute('aria-activedescendant', cellId);\n }\n\n // Scroll cell into view if needed\n cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }\n\n function handleTbodyFocus(): void {\n // When tbody receives focus, highlight the first cell (or restore last)\n if (focusedCell.row < 0) {\n setFocusedCell(0, 0);\n } else {\n setFocusedCell(focusedCell.row, focusedCell.col);\n }\n }\n\n function handleTbodyKeydown(e: KeyboardEvent): void {\n const rows = getRows();\n if (rows.length === 0) return;\n\n const colCount = getColCount();\n const { row, col } = focusedCell;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (row < rows.length - 1) {\n setFocusedCell(row + 1, col);\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (row > 0) {\n setFocusedCell(row - 1, col);\n } else {\n // Move focus to the header\n focusHeaderCell(col);\n }\n break;\n case 'ArrowRight':\n e.preventDefault();\n if (col < colCount - 1) {\n setFocusedCell(row, col + 1);\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (col > 0) {\n setFocusedCell(row, col - 1);\n }\n break;\n case 'Home':\n e.preventDefault();\n setFocusedCell(row, 0);\n break;\n case 'End':\n e.preventDefault();\n setFocusedCell(row, colCount - 1);\n break;\n }\n }\n\n // Header cell keyboard handling\n function focusHeaderCell(col: number): void {\n const headers = getHeaderCells();\n if (col >= 0 && col < headers.length) {\n clearFocusHighlight();\n headers[col].focus();\n }\n }\n\n function handleHeaderKeydown(e: KeyboardEvent): void {\n const th = e.currentTarget as HTMLTableCellElement;\n const headers = getHeaderCells();\n const colIndex = headers.indexOf(th);\n if (colIndex < 0) return;\n\n switch (e.key) {\n case 'ArrowRight':\n e.preventDefault();\n if (colIndex < headers.length - 1) {\n headers[colIndex + 1].focus();\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (colIndex > 0) {\n headers[colIndex - 1].focus();\n }\n break;\n case 'ArrowDown':\n e.preventDefault();\n // Move focus to first body row at this column\n if (tbody) {\n tbody.focus();\n setFocusedCell(0, colIndex);\n }\n break;\n case 'Enter':\n case ' ': {\n e.preventDefault();\n const sortColumn = th.getAttribute('data-column');\n const sortBtn = th.querySelector('[data-sort-column]');\n if (sortColumn && sortBtn) {\n onSort(sortColumn);\n }\n break;\n }\n }\n }\n\n // Search escape handling\n const searchInput = wrapper.querySelector('.oc-table-search input') as HTMLInputElement | null;\n\n function handleSearchKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClearSearch();\n // Return focus to tbody\n if (tbody) {\n tbody.focus();\n onAnnounce('Search cleared');\n }\n }\n }\n\n // Wire up event listeners\n tbody.addEventListener('focus', handleTbodyFocus);\n tbody.addEventListener('keydown', handleTbodyKeydown as EventListener);\n\n // Make header cells focusable and wire keyboard\n const headerCells = getHeaderCells();\n for (const th of headerCells) {\n th.setAttribute('tabindex', '0');\n th.addEventListener('keydown', handleHeaderKeydown as EventListener);\n }\n\n if (searchInput) {\n searchInput.addEventListener('keydown', handleSearchKeydown as EventListener);\n }\n\n // Cleanup\n return () => {\n tbody.removeEventListener('focus', handleTbodyFocus);\n tbody.removeEventListener('keydown', handleTbodyKeydown as EventListener);\n\n for (const th of headerCells) {\n th.removeEventListener('keydown', handleHeaderKeydown as EventListener);\n }\n\n if (searchInput) {\n searchInput.removeEventListener('keydown', handleSearchKeydown as EventListener);\n }\n\n clearFocusHighlight();\n };\n}\n","/**\n * Table mount API: the main entry point for vanilla JS table usage.\n *\n * createTable() takes a container, spec, and options, compiles the table,\n * renders it as HTML, sets up responsive resizing, sort/search/pagination\n * interactivity, and returns a TableInstance with update/resize/export/destroy.\n *\n * Supports both controlled and uncontrolled modes:\n * - Uncontrolled (default): manages sort/search/page internally\n * - Controlled: reads state from externalState, fires onStateChange\n */\n\nimport type {\n CompileTableOptions,\n DarkMode,\n SortState,\n TableLayout,\n TableSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { getBreakpoint } from '@opendata-ai/openchart-core';\nimport { compileTable } from '@opendata-ai/openchart-engine';\nimport { setupTableAnimationCleanup } from './animation';\nimport { observeResize } from './resize-observer';\nimport { attachKeyboardNav } from './table-keyboard';\nimport { renderTable } from './table-renderer';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TableState {\n sort: SortState | null;\n search: string;\n page: number;\n}\n\nexport interface TableMountOptions {\n theme?: ThemeConfig;\n darkMode?: DarkMode;\n responsive?: boolean;\n /** Show the tryOpenData.ai watermark. Defaults to true. */\n watermark?: boolean;\n onRowClick?: (row: Record<string, unknown>) => void;\n onStateChange?: (state: TableState) => void;\n externalState?: { sort?: SortState | null; search?: string; page?: number };\n}\n\nexport interface TableInstance {\n update(spec: TableSpec): void;\n resize(): void;\n export(format: 'csv'): string;\n getState(): TableState;\n setState(partial: Partial<TableState>): void;\n destroy(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction resolveDarkMode(mode?: DarkMode): boolean {\n if (mode === 'force') return true;\n if (mode === 'off' || mode === undefined) return false;\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// CSV export\n// ---------------------------------------------------------------------------\n\nfunction csvEscape(value: string): string {\n if (value.includes(',') || value.includes('\"') || value.includes('\\n') || value.includes('\\r')) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// Sort cycling\n// ---------------------------------------------------------------------------\n\n/**\n * Cycle sort state: clicking same column cycles none -> asc -> desc -> none.\n * Clicking a different column resets to asc.\n */\nfunction cycleSort(current: SortState | null, column: string): SortState | null {\n if (!current || current.column !== column) {\n return { column, direction: 'asc' };\n }\n if (current.direction === 'asc') {\n return { column, direction: 'desc' };\n }\n // desc -> none\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a table instance from a spec and mount it into a container.\n *\n * @param container - The DOM element to render into.\n * @param spec - The table spec.\n * @param options - Mount options.\n * @returns A TableInstance with update/resize/export/destroy methods.\n */\nexport function createTable(\n container: HTMLElement,\n spec: TableSpec,\n options?: TableMountOptions,\n): TableInstance {\n let currentSpec = spec;\n let currentLayout: TableLayout;\n let wrapperElement: HTMLElement | null = null;\n let disconnectResize: (() => void) | null = null;\n let cleanupKeyboard: (() => void) | null = null;\n let cleanupAnimations: (() => void) | null = null;\n let isFirstRender = true;\n let destroyed = false;\n\n // Internal state (used in uncontrolled mode)\n const internalState: TableState = {\n sort: null,\n search: '',\n page: 0,\n };\n\n // Debounce timers\n let searchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n let resizeDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n const isControlled = options?.externalState !== undefined;\n\n function getState(): TableState {\n if (isControlled && options?.externalState) {\n return {\n sort: options.externalState.sort ?? null,\n search: options.externalState.search ?? '',\n page: options.externalState.page ?? 0,\n };\n }\n return { ...internalState };\n }\n\n function updateState(partial: Partial<TableState>): void {\n if (isControlled) {\n // In controlled mode, notify parent\n const current = getState();\n const next: TableState = {\n sort: partial.sort !== undefined ? partial.sort : current.sort,\n search: partial.search !== undefined ? partial.search : current.search,\n page: partial.page !== undefined ? partial.page : current.page,\n };\n options?.onStateChange?.(next);\n } else {\n // In uncontrolled mode, update internal state\n if (partial.sort !== undefined) internalState.sort = partial.sort;\n if (partial.search !== undefined) internalState.search = partial.search;\n if (partial.page !== undefined) internalState.page = partial.page;\n options?.onStateChange?.({ ...internalState });\n }\n }\n\n function compile(): TableLayout {\n const state = getState();\n const darkMode = resolveDarkMode(options?.darkMode);\n const { width } = getContainerDimensions();\n\n const compileOpts: CompileTableOptions = {\n width,\n height: 600,\n theme: options?.theme,\n darkMode,\n watermark: options?.watermark,\n sort: state.sort ?? undefined,\n search: state.search || undefined,\n page: state.page,\n };\n\n return compileTable(currentSpec, compileOpts);\n }\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n return {\n width: Math.max(rect.width || 600, 100),\n height: Math.max(rect.height || 400, 100),\n };\n }\n\n /**\n * Announce a message to screen readers via the live region.\n */\n function announce(message: string): void {\n if (!wrapperElement) return;\n const liveRegion = wrapperElement.querySelector('.oc-table-live-region');\n if (liveRegion) {\n liveRegion.textContent = message;\n }\n }\n\n /**\n * Apply responsive breakpoint class based on container width.\n * Only auto-adds compact mode at small sizes. Never removes compact\n * if the spec explicitly requests it (layout.compact === true).\n */\n function applyBreakpointClass(): void {\n if (!wrapperElement) return;\n const { width } = getContainerDimensions();\n const bp = getBreakpoint(width);\n\n if (bp === 'compact' || bp === 'medium') {\n wrapperElement.classList.add('oc-table--compact');\n } else if (!currentLayout?.compact) {\n // Only remove compact if the spec didn't explicitly request it\n wrapperElement.classList.remove('oc-table--compact');\n }\n }\n\n function render(): void {\n if (destroyed) return;\n\n try {\n // Cancel any in-flight animations before re-rendering\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n\n // Clean up previous keyboard nav\n if (cleanupKeyboard) {\n cleanupKeyboard();\n cleanupKeyboard = null;\n }\n\n // Clean up previous render\n if (wrapperElement?.parentNode) {\n wrapperElement.parentNode.removeChild(wrapperElement);\n wrapperElement = null;\n }\n\n currentLayout = compile();\n const shouldAnimate = isFirstRender && !!currentLayout.animation?.enabled;\n wrapperElement = renderTable(currentLayout, container, { animate: shouldAnimate });\n\n // Set up animation cleanup on first animated render\n if (shouldAnimate && wrapperElement) {\n cleanupAnimations = setupTableAnimationCleanup(wrapperElement);\n }\n if (isFirstRender) {\n isFirstRender = false;\n }\n\n // Apply dark mode class\n const isDark = resolveDarkMode(options?.darkMode);\n if (isDark) {\n container.classList.add('oc-dark');\n } else {\n container.classList.remove('oc-dark');\n }\n\n // Apply responsive breakpoint\n applyBreakpointClass();\n\n // Add clickable class if onRowClick is provided\n if (options?.onRowClick) {\n wrapperElement.classList.add('oc-table--clickable');\n }\n\n // Wire up event handlers\n wireEvents();\n\n // Wire up keyboard navigation\n if (wrapperElement) {\n cleanupKeyboard = attachKeyboardNav({\n wrapper: wrapperElement,\n onSort: (columnKey: string) => {\n const state = getState();\n const newSort = cycleSort(state.sort, columnKey);\n updateState({ sort: newSort, page: 0 });\n\n // Announce sort change\n if (newSort) {\n const dir = newSort.direction === 'asc' ? 'ascending' : 'descending';\n announce(`Sorted by ${columnKey} ${dir}`);\n } else {\n announce('Sort cleared');\n }\n\n if (!isControlled) {\n rerender();\n }\n },\n onClearSearch: () => {\n updateState({ search: '', page: 0 });\n if (!isControlled) {\n rerender();\n }\n },\n onAnnounce: announce,\n });\n }\n } catch (err) {\n console.error('[viz] Table render failed:', err);\n }\n }\n\n function wireEvents(): void {\n if (!wrapperElement) return;\n\n // Sort click handlers on thead buttons\n const sortBtns = wrapperElement.querySelectorAll('[data-sort-column]');\n for (const btn of sortBtns) {\n btn.addEventListener('click', handleSortClick);\n }\n\n // Search input\n const searchInput = wrapperElement.querySelector(\n '.oc-table-search input',\n ) as HTMLInputElement | null;\n if (searchInput) {\n searchInput.addEventListener('input', handleSearchInput);\n }\n\n // Pagination buttons\n const pageButtons = wrapperElement.querySelectorAll('[data-page-action]');\n for (const btn of pageButtons) {\n btn.addEventListener('click', handlePageClick);\n }\n\n // Row click\n if (options?.onRowClick) {\n const rows = wrapperElement.querySelectorAll('tbody tr');\n for (const row of rows) {\n row.addEventListener('click', handleRowClick);\n }\n }\n }\n\n function handleSortClick(e: Event): void {\n const btn = e.currentTarget as HTMLElement;\n const column = btn.getAttribute('data-sort-column');\n if (!column) return;\n\n const state = getState();\n const newSort = cycleSort(state.sort, column);\n\n updateState({ sort: newSort, page: 0 });\n\n // Announce sort change for screen readers\n if (newSort) {\n const dir = newSort.direction === 'asc' ? 'ascending' : 'descending';\n announce(`Sorted by ${column} ${dir}`);\n } else {\n announce('Sort cleared');\n }\n\n if (!isControlled) {\n rerender();\n }\n }\n\n function handleSearchInput(e: Event): void {\n const input = e.target as HTMLInputElement;\n const query = input.value;\n\n if (searchDebounceTimer !== null) {\n clearTimeout(searchDebounceTimer);\n }\n\n searchDebounceTimer = setTimeout(() => {\n searchDebounceTimer = null;\n updateState({ search: query, page: 0 });\n\n if (!isControlled) {\n rerender();\n // Announce search result count\n const rowCount = currentLayout?.rows?.length ?? 0;\n if (query) {\n announce(`${rowCount} result${rowCount !== 1 ? 's' : ''} found`);\n }\n }\n }, 200);\n }\n\n function handlePageClick(e: Event): void {\n const btn = e.currentTarget as HTMLElement;\n const action = btn.getAttribute('data-page-action');\n const state = getState();\n\n if (action === 'prev' && state.page > 0) {\n updateState({ page: state.page - 1 });\n } else if (action === 'next') {\n updateState({ page: state.page + 1 });\n }\n\n if (!isControlled) {\n rerender();\n }\n }\n\n function handleRowClick(e: Event): void {\n const tr = e.currentTarget as HTMLElement;\n const rowId = tr.getAttribute('data-row-id');\n if (!rowId || !currentLayout) return;\n\n const row = currentLayout.rows.find((r) => r.id === rowId);\n if (row) {\n options?.onRowClick?.(row.data);\n }\n }\n\n /**\n * Re-render the table, preserving search input focus across the DOM rebuild.\n */\n function rerender(): void {\n if (destroyed) return;\n\n // Capture current search input state before re-render\n const searchInput = wrapperElement?.querySelector(\n '.oc-table-search input',\n ) as HTMLInputElement | null;\n const hadFocus = searchInput && document.activeElement === searchInput;\n const selectionStart = searchInput?.selectionStart ?? 0;\n const selectionEnd = searchInput?.selectionEnd ?? 0;\n\n render();\n\n // Restore search focus after re-render\n if (hadFocus) {\n const newInput = wrapperElement?.querySelector(\n '.oc-table-search input',\n ) as HTMLInputElement | null;\n if (newInput) {\n newInput.focus();\n newInput.setSelectionRange(selectionStart, selectionEnd);\n }\n }\n }\n\n function update(newSpec: TableSpec): void {\n if (destroyed) return;\n currentSpec = newSpec;\n render();\n }\n\n function resize(): void {\n if (destroyed) return;\n if (cleanupAnimations) return; // Skip resize during entrance animation\n render();\n }\n\n function doExport(format: 'csv'): string {\n if (format !== 'csv') {\n throw new Error(`Unsupported export format: ${format}`);\n }\n\n // Export all filtered/sorted data (not just current page)\n // Re-compile without pagination\n const state = getState();\n const darkMode = resolveDarkMode(options?.darkMode);\n const { width } = getContainerDimensions();\n\n const fullLayout = compileTable(currentSpec, {\n width,\n height: 600,\n theme: options?.theme,\n darkMode,\n sort: state.sort ?? undefined,\n search: state.search || undefined,\n // No page/pageSize: get all rows\n });\n\n const headers = fullLayout.columns.map((c) => c.label);\n const csvRows = [headers.map(csvEscape).join(',')];\n\n for (const row of fullLayout.rows) {\n const values = row.cells.map((cell) => csvEscape(cell.formattedValue));\n csvRows.push(values.join(','));\n }\n\n return csvRows.join('\\n');\n }\n\n function setState(partial: Partial<TableState>): void {\n if (destroyed) return;\n\n if (partial.sort !== undefined) internalState.sort = partial.sort;\n if (partial.search !== undefined) internalState.search = partial.search;\n if (partial.page !== undefined) internalState.page = partial.page;\n\n render();\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n if (cleanupKeyboard) {\n cleanupKeyboard();\n cleanupKeyboard = null;\n }\n if (searchDebounceTimer !== null) {\n clearTimeout(searchDebounceTimer);\n searchDebounceTimer = null;\n }\n if (resizeDebounceTimer !== null) {\n clearTimeout(resizeDebounceTimer);\n resizeDebounceTimer = null;\n }\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n if (wrapperElement?.parentNode) {\n wrapperElement.parentNode.removeChild(wrapperElement);\n wrapperElement = null;\n }\n container.classList.remove('oc-dark');\n }\n\n // Initial render\n render();\n\n // Set up responsive resize with breakpoint detection\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n if (resizeDebounceTimer !== null) {\n clearTimeout(resizeDebounceTimer);\n }\n resizeDebounceTimer = setTimeout(() => {\n resizeDebounceTimer = null;\n // Update breakpoint class without full re-render when possible\n applyBreakpointClass();\n resize();\n }, 100);\n });\n }\n\n return {\n update,\n resize,\n export: doExport,\n getState,\n setState,\n destroy,\n };\n}\n","/**\n * Table renderer: produces semantic HTML from a TableLayout.\n *\n * renderTable() creates the full DOM structure: chrome, search bar,\n * scrollable table with sticky column support, pagination, and footer.\n * The returned element replaces or appends to the given container.\n */\n\nimport type { ResolvedColumn, TableLayout, TableRow } from '@opendata-ai/openchart-core';\nimport { BRAND_FONT_SIZE } from '@opendata-ai/openchart-core';\nimport { clampStaggerDelay } from '@opendata-ai/openchart-engine';\nimport { renderCell } from './renderers/table-cells';\n\n/** Options for renderTable(). */\nexport interface TableRenderOptions {\n /** Whether to apply entrance animation on this render. */\n animate?: boolean;\n}\n\n/** CSS easing preset map for animation custom properties. */\nconst EASE_VAR_MAP: Record<string, string> = {\n smooth: 'var(--oc-ease-smooth)',\n snappy: 'var(--oc-ease-snappy)',\n};\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst BRAND_URL = 'https://tryopendata.ai';\n\n// ---------------------------------------------------------------------------\n// Chrome rendering\n// ---------------------------------------------------------------------------\n\n/** Create chrome (title/subtitle or source/footer) block. */\nfunction renderChromeBlock(\n layout: TableLayout,\n position: 'header' | 'footer',\n): HTMLDivElement | null {\n const chrome = layout.chrome;\n\n if (position === 'header') {\n if (!chrome.title && !chrome.subtitle) return null;\n\n const div = document.createElement('div');\n div.className = 'oc-chrome';\n\n if (chrome.title) {\n const h = document.createElement('div');\n h.className = 'oc-table-title';\n h.textContent = chrome.title.text;\n div.appendChild(h);\n }\n if (chrome.subtitle) {\n const sub = document.createElement('div');\n sub.className = 'oc-table-subtitle';\n sub.textContent = chrome.subtitle.text;\n div.appendChild(sub);\n }\n\n return div;\n }\n\n // Footer position\n if (!chrome.source && !chrome.footer) return null;\n\n const div = document.createElement('div');\n div.className = 'oc-chrome oc-chrome-footer';\n\n if (chrome.source) {\n const src = document.createElement('div');\n src.className = 'oc-table-source';\n src.textContent = chrome.source.text;\n div.appendChild(src);\n }\n if (chrome.footer) {\n const foot = document.createElement('div');\n foot.className = 'oc-table-footer-text';\n foot.textContent = chrome.footer.text;\n div.appendChild(foot);\n }\n\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Table head\n// ---------------------------------------------------------------------------\n\nfunction renderThead(\n columns: ResolvedColumn[],\n sort: TableLayout['sort'],\n): HTMLTableSectionElement {\n const thead = document.createElement('thead');\n const tr = document.createElement('tr');\n tr.setAttribute('role', 'row');\n\n for (const col of columns) {\n const th = document.createElement('th');\n th.setAttribute('scope', 'col');\n th.setAttribute('role', 'columnheader');\n th.style.textAlign = col.align;\n th.style.width = `${col.width}px`;\n\n // Sort state: use 'ascending'/'descending' per WAI-ARIA spec\n let ariaSortValue: string = 'none';\n if (sort && sort.column === col.key) {\n ariaSortValue = sort.direction === 'asc' ? 'ascending' : 'descending';\n }\n th.setAttribute('aria-sort', ariaSortValue);\n th.setAttribute('data-column', col.key);\n\n // Label\n const labelSpan = document.createTextNode(col.label);\n th.appendChild(labelSpan);\n\n // Sort button\n if (col.sortable) {\n const btn = document.createElement('button');\n btn.className = 'oc-table-sort-btn';\n btn.setAttribute('aria-label', `Sort by ${col.label}`);\n btn.setAttribute('data-sort-column', col.key);\n btn.type = 'button';\n th.appendChild(btn);\n }\n\n tr.appendChild(th);\n }\n\n thead.appendChild(tr);\n return thead;\n}\n\n// ---------------------------------------------------------------------------\n// Table body\n// ---------------------------------------------------------------------------\n\nfunction renderTbody(rows: TableRow[], columns: ResolvedColumn[]): HTMLTableSectionElement {\n const tbody = document.createElement('tbody');\n\n for (let r = 0; r < rows.length; r++) {\n const row = rows[r];\n const tr = document.createElement('tr');\n tr.setAttribute('role', 'row');\n tr.setAttribute('data-row-id', row.id);\n tr.style.setProperty('--oc-row-index', String(r));\n\n for (let c = 0; c < columns.length; c++) {\n const cell = row.cells[c];\n if (!cell) continue;\n\n const td = renderCell(cell);\n td.setAttribute('role', 'gridcell');\n td.style.textAlign = columns[c].align;\n tr.appendChild(td);\n }\n\n tbody.appendChild(tr);\n }\n\n return tbody;\n}\n\n// ---------------------------------------------------------------------------\n// Search bar\n// ---------------------------------------------------------------------------\n\nfunction renderSearchBar(layout: TableLayout): HTMLDivElement | null {\n if (!layout.search.enabled) return null;\n\n const div = document.createElement('div');\n div.className = 'oc-table-search';\n\n const input = document.createElement('input');\n input.type = 'search';\n input.placeholder = layout.search.placeholder;\n input.setAttribute('aria-label', 'Search table');\n input.value = layout.search.query;\n\n div.appendChild(input);\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Pagination\n// ---------------------------------------------------------------------------\n\nfunction renderPagination(layout: TableLayout): HTMLDivElement | null {\n if (!layout.pagination) return null;\n\n const { page, pageSize, totalRows, totalPages } = layout.pagination;\n\n const div = document.createElement('div');\n div.className = 'oc-table-pagination';\n\n const info = document.createElement('span');\n info.className = 'oc-table-pagination-info';\n\n if (totalRows === 0) {\n info.textContent = 'No results';\n } else {\n const start = page * pageSize + 1;\n const end = Math.min((page + 1) * pageSize, totalRows);\n info.textContent = `Showing ${start}-${end} of ${totalRows}`;\n }\n\n div.appendChild(info);\n\n const btnGroup = document.createElement('span');\n btnGroup.className = 'oc-table-pagination-btns';\n\n const prevBtn = document.createElement('button');\n prevBtn.setAttribute('aria-label', 'Previous page');\n prevBtn.setAttribute('data-page-action', 'prev');\n prevBtn.textContent = 'Prev';\n prevBtn.disabled = page <= 0;\n btnGroup.appendChild(prevBtn);\n\n const nextBtn = document.createElement('button');\n nextBtn.setAttribute('aria-label', 'Next page');\n nextBtn.setAttribute('data-page-action', 'next');\n nextBtn.textContent = 'Next';\n nextBtn.disabled = page >= totalPages - 1;\n btnGroup.appendChild(nextBtn);\n\n div.appendChild(btnGroup);\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Empty state\n// ---------------------------------------------------------------------------\n\nfunction renderEmptyState(message: string): HTMLDivElement {\n const div = document.createElement('div');\n div.className = 'oc-table-empty';\n div.setAttribute('aria-live', 'polite');\n div.textContent = message;\n return div;\n}\n\n// ---------------------------------------------------------------------------\n// Main render\n// ---------------------------------------------------------------------------\n\n/**\n * Render a TableLayout into a full DOM structure.\n *\n * @param layout - The compiled table layout.\n * @param container - The container element to render into.\n * @returns The wrapper element that was created.\n */\nexport function renderTable(\n layout: TableLayout,\n container: HTMLElement,\n opts?: TableRenderOptions,\n): HTMLElement {\n const wrapper = document.createElement('div');\n wrapper.className = 'oc-table-wrapper';\n\n // Apply theme colors as CSS custom properties so table CSS picks them up.\n // Without this, dark-background themes show invisible text since the\n // CSS defaults (--oc-text etc.) are light-mode values.\n const { theme, chrome } = layout;\n if (theme) {\n const s = wrapper.style;\n s.setProperty('--oc-bg', theme.colors.background);\n s.setProperty('--oc-text', theme.colors.text);\n s.setProperty('--oc-text-secondary', theme.colors.axis ?? theme.colors.text);\n s.setProperty('--oc-text-muted', theme.colors.axis ?? theme.colors.text);\n s.setProperty('--oc-gridline', theme.colors.gridline);\n s.setProperty('--oc-border', theme.colors.gridline);\n s.setProperty('--oc-font-family', theme.fonts.family);\n s.fontFamily = theme.fonts.family;\n }\n\n // Set computed chrome CSS custom properties so chrome elements pick up\n // theme-resolved values via CSS fallbacks (e.g. --oc-title-computed-size).\n {\n const s = wrapper.style;\n if (chrome.title) {\n s.setProperty('--oc-title-computed-size', `${chrome.title.style.fontSize}px`);\n s.setProperty('--oc-title-computed-weight', String(chrome.title.style.fontWeight));\n s.setProperty('--oc-title-computed-color', chrome.title.style.fill);\n }\n if (chrome.subtitle) {\n s.setProperty('--oc-subtitle-computed-size', `${chrome.subtitle.style.fontSize}px`);\n s.setProperty('--oc-subtitle-computed-weight', String(chrome.subtitle.style.fontWeight));\n s.setProperty('--oc-subtitle-computed-color', chrome.subtitle.style.fill);\n }\n if (chrome.source) {\n s.setProperty('--oc-source-computed-size', `${chrome.source.style.fontSize}px`);\n s.setProperty('--oc-source-computed-color', chrome.source.style.fill);\n }\n if (chrome.footer) {\n s.setProperty('--oc-footer-computed-size', `${chrome.footer.style.fontSize}px`);\n s.setProperty('--oc-footer-computed-color', chrome.footer.style.fill);\n }\n }\n\n // Apply class modifiers\n if (layout.compact) {\n wrapper.classList.add('oc-table--compact');\n }\n\n // Header chrome\n const headerChrome = renderChromeBlock(layout, 'header');\n if (headerChrome) {\n wrapper.appendChild(headerChrome);\n }\n\n // Search bar\n const searchBar = renderSearchBar(layout);\n if (searchBar) {\n wrapper.appendChild(searchBar);\n }\n\n // Handle empty data\n if (layout.rows.length === 0) {\n const message = layout.search.query ? 'No results found' : 'No data';\n wrapper.appendChild(renderEmptyState(message));\n } else {\n // Scroll container\n const scroll = document.createElement('div');\n scroll.className = 'oc-table-scroll';\n\n // Table\n const table = document.createElement('table');\n table.setAttribute('role', 'grid');\n table.setAttribute('aria-label', layout.a11y.caption);\n\n if (layout.stickyFirstColumn) {\n table.classList.add('oc-table--sticky');\n }\n\n // Caption (screen reader only – inline styles ensure hiding even without\n // the external stylesheet, e.g. CDN / esm.sh usage)\n const caption = document.createElement('caption');\n caption.className = 'oc-sr-only';\n caption.style.position = 'absolute';\n caption.style.width = '1px';\n caption.style.height = '1px';\n caption.style.padding = '0';\n caption.style.margin = '-1px';\n caption.style.overflow = 'hidden';\n caption.style.clipPath = 'inset(50%)';\n caption.style.whiteSpace = 'nowrap';\n caption.style.borderWidth = '0';\n caption.textContent = layout.a11y.summary;\n table.appendChild(caption);\n\n // Thead\n table.appendChild(renderThead(layout.columns, layout.sort));\n\n // Tbody\n table.appendChild(renderTbody(layout.rows, layout.columns));\n\n scroll.appendChild(table);\n wrapper.appendChild(scroll);\n }\n\n // Pagination\n const pagination = renderPagination(layout);\n if (pagination) {\n wrapper.appendChild(pagination);\n }\n\n // Footer chrome\n const footerChrome = renderChromeBlock(layout, 'footer');\n if (footerChrome) {\n wrapper.appendChild(footerChrome);\n }\n\n // Live region for screen reader announcements (sort changes, search results)\n const liveRegion = document.createElement('div');\n liveRegion.className = 'oc-table-live-region oc-sr-only';\n liveRegion.style.position = 'absolute';\n liveRegion.style.width = '1px';\n liveRegion.style.height = '1px';\n liveRegion.style.padding = '0';\n liveRegion.style.margin = '-1px';\n liveRegion.style.overflow = 'hidden';\n liveRegion.style.clipPath = 'inset(50%)';\n liveRegion.style.whiteSpace = 'nowrap';\n liveRegion.style.borderWidth = '0';\n liveRegion.setAttribute('aria-live', 'polite');\n liveRegion.setAttribute('aria-atomic', 'true');\n liveRegion.setAttribute('role', 'status');\n wrapper.appendChild(liveRegion);\n\n // Brand watermark\n if (layout.watermark) {\n const brandColor = theme ? theme.colors.axis : '#999999';\n const brand = document.createElement('div');\n brand.className = 'oc-table-ref';\n brand.style.cssText = 'text-align: right; padding: 4px 8px;';\n const brandLink = document.createElement('a');\n brandLink.href = BRAND_URL;\n brandLink.target = '_blank';\n brandLink.rel = 'noopener';\n brandLink.style.cssText = `font-size: ${BRAND_FONT_SIZE}px; font-weight: 600; color: ${brandColor}; opacity: 0.55; text-decoration: none; font-family: ${theme ? theme.fonts.family : 'sans-serif'};`;\n brandLink.textContent = 'tryOpenData.ai';\n brand.appendChild(brandLink);\n wrapper.appendChild(brand);\n }\n\n // Animation: stamp CSS custom properties and add oc-animate class BEFORE\n // DOM insertion to avoid a flash of final state.\n if (opts?.animate && layout.animation?.enabled) {\n const anim = layout.animation;\n const rowCount = layout.rows.length;\n const stagger = clampStaggerDelay(anim.staggerDelay, rowCount);\n const s = wrapper.style;\n s.setProperty('--oc-animation-duration', `${anim.duration}ms`);\n s.setProperty('--oc-animation-stagger', `${stagger}ms`);\n s.setProperty('--oc-animation-ease', EASE_VAR_MAP[anim.ease] || EASE_VAR_MAP.smooth);\n wrapper.classList.add('oc-animate');\n }\n\n container.appendChild(wrapper);\n return wrapper;\n}\n"],"mappings":"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","names":["x","y","c","x","y","cx","cy","x","y","c","x","y","x","y","x","y","x","y","x2","y2","x3","y3","x","y","x","y","x","x","y","x","y","m","i","c","now","x","y","x","y","node","strength","c","x2","x_default","x","y_default","y","c","x","y","x_default","y_default","x","y","x2","y2","x","y","renderChrome","renderLegend","now","x","y","timer","BRAND_FONT_SIZE","BRAND_MIN_WIDTH","SVG_NS","words","lines","current","index","c","BRAND_MIN_WIDTH","a","BRAND_FONT_SIZE","m","computePosition","resolveDarkMode","x","y","getScale","index","SVG_NS","cleanup","a","c","x","y","BRAND_FONT_SIZE","BRAND_MIN_WIDTH","estimateTextWidth","clampStaggerDelay","SVG_NS","XLINK_NS","BRAND_URL","EASE_VAR_MAP","createSVGElement","setAttrs","applyTextStyle","stampAnimationAttrs","wrapText","renderChromeElement","renderChrome","renderBrand","a","renderLegend","x2","resolveDarkMode","x","y","BRAND_FONT_SIZE","clampStaggerDelay","EASE_VAR_MAP","BRAND_URL","div","c","BRAND_FONT_SIZE","clampStaggerDelay","resolveDarkMode","csvEscape","c"]}
|