@opendata-ai/openchart-vanilla 8.1.1 → 8.2.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/{chunk-RQNAZZJM.js → chunk-RC5PGDQX.js} +151 -4
- package/dist/chunk-RC5PGDQX.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{mount-CL-nA0f-.d.ts → mount-Djb1VvKO.d.ts} +10 -0
- package/dist/story/index.d.ts +2 -2
- package/dist/story/index.js +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-RQNAZZJM.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resize-observer.ts","../src/tooltip.ts","../src/scatter-canvas/renderer.ts","../src/scatter-canvas/state.ts","../src/export-canvas.ts","../src/motion/easing.ts","../src/text-edit-overlay.ts","../src/transition/keys.ts","../src/transition/gate.ts","../src/transition/driver.ts","../src/transition/apply.ts","../../../node_modules/.bun/d3-color@3.1.0/node_modules/d3-color/src/define.js","../../../node_modules/.bun/d3-color@3.1.0/node_modules/d3-color/src/color.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/basis.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/basisClosed.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/constant.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/color.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/rgb.js","../../../node_modules/.bun/d3-interpolate@3.0.1/node_modules/d3-interpolate/src/zoom.js","../src/transition/canvas-tweens.ts","../src/transition/chrome-tweens.ts","../src/transition/interpolate.ts","../src/transition/dom-index.ts","../src/transition/svg-tweens.ts","../src/you-draw-it.ts","../src/mount.ts","../src/animation.ts","../src/interactions/chart-events.ts","../src/interactions/crosshair.ts","../src/interactions/drag-handler.ts","../src/interactions/editing-drags.ts","../src/interactions/invert.ts","../src/interactions/keyboard-nav.ts","../src/interactions/legend-interaction.ts","../src/interactions/selection.ts","../src/interactions/tooltip-events.ts","../src/measure-text.ts","../src/resolve-dark-mode.ts","../src/scatter-canvas/interactions.ts","../src/motion/scheduler.ts","../../../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","../src/spatial-index.ts","../src/motion/tween.ts","../src/scatter-canvas/entrance.ts","../src/scatter-canvas/layer.ts","../src/series-search.ts","../src/theme-tokens.ts","../src/story/tween.ts","../src/story/camera-math.ts","../src/map-mount.ts","../src/map-camera.ts","../src/map-renderer.ts","../src/map-transition.ts"],"sourcesContent":["/**\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 type { Placement } from '@floating-ui/dom';\nimport { computePosition, flip, offset, shift } from '@floating-ui/dom';\nimport type { TooltipContent } from '@opendata-ai/openchart-core';\n\nexport interface TooltipShowOptions {\n /**\n * Floating-ui placement. Defaults to 'bottom-start' for mark hover\n * (the legacy behavior). Line/area snap-tooltips pass 'right-start'\n * so the card sits beside the snapped point and flips to 'left-start'\n * via the flip middleware when crowding the right edge.\n */\n placement?: Placement;\n}\n\n/**\n * Content accepted by {@link TooltipManager.show}. A structured\n * {@link TooltipContent} is rendered by the manager; `{ text }` is inserted as\n * plain text (escaped via textContent); `{ element }` is a caller-owned node\n * trusted verbatim (the host owns sanitization).\n */\nexport type TooltipInput = TooltipContent | { text: string } | { element: HTMLElement };\n\nexport interface TooltipManager {\n /** Show the tooltip with content at a given position. */\n show(content: TooltipInput, x: number, y: number, opts?: TooltipShowOptions): 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 // WCAG 1.4.13: hover-triggered content must be dismissible without moving\n // the pointer. Document-level so it works while hovering, when the chart\n // container does not have keyboard focus.\n const handleDocumentKeydown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && tooltip.style.display === 'block') {\n hide();\n }\n };\n document.addEventListener('keydown', handleDocumentKeydown);\n\n function show(input: TooltipInput, x: number, y: number, opts?: TooltipShowOptions): void {\n // Custom-element form: trusted verbatim (host owns sanitization).\n if ('element' in input) {\n lastContentKey = '';\n tooltip.replaceChildren(input.element);\n position(x, y, opts);\n return;\n }\n // Plain-text form: escaped via textContent, never innerHTML.\n if ('text' in input) {\n lastContentKey = '';\n tooltip.textContent = input.text;\n position(x, y, opts);\n return;\n }\n\n const content = input;\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 // Multi-series tooltips put a swatch on each row instead of in the\n // header, so detect that case once.\n const colorRowCount = content.fields.filter((f) => f.color).length;\n const perRowSwatches = colorRowCount > 1;\n\n // Title row: header dot only when there's a single color (single-series)\n if (content.title) {\n const titleColor = perRowSwatches ? undefined : 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\">';\n if (perRowSwatches && field.color) {\n html += `<span class=\"oc-tooltip-row-swatch\" style=\"background:${esc(field.color)}\"></span>`;\n }\n html += `${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 position(x, y, opts);\n }\n\n /** Show and position the tooltip at a container-relative coordinate. */\n function position(x: number, y: number, opts?: TooltipShowOptions): void {\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: opts?.placement ?? 'bottom-start',\n middleware: [offset(TOOLTIP_OFFSET), flip(), shift({ padding: 8 })],\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 document.removeEventListener('keydown', handleDocumentKeydown);\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 * Canvas 2D renderer for high-cardinality scatter point marks.\n *\n * Stateless: receives a `ScatterCanvasState` each frame and paints it. Trimmed\n * from `graph/canvas-renderer.ts` — no edges, labels, glow, focus dimming or\n * zoom transform, because the scatter layer paints in layout coordinates and\n * every point is equal.\n *\n * Performance strategy (the whole reason this layer exists):\n * - Trivial rect cull against the clip rect before a point is drawn at all\n * - Redundant `fillStyle`/`strokeStyle`/`globalAlpha` writes skipped across\n * runs of identically-styled points\n * - Fills and strokes issued PER POINT, not merged into shared paths. Merging\n * looks like the obvious optimization and is wrong twice over: it breaks\n * translucent compositing (see `drawPoints`) and it measures slower.\n *\n * Gradient fills are flattened to a solid color upstream (`state.flattenFill`);\n * exports materialize a true-gradient SVG render instead.\n */\n\nimport type { CanvasRect, ScatterCanvasState } from './types';\n\nconst TWO_PI = Math.PI * 2;\n\n/**\n * Cap the backing-store scale. Above 2x the extra pixels are invisible but the\n * fill rate cost is real, and phones report 3-4x.\n */\nconst MAX_DPR = 2;\n\n/** Extra radius on the hover ring, in CSS px. */\nconst HOVER_RING_PAD = 2;\n\nfunction currentDpr(): number {\n if (typeof window === 'undefined') return 1;\n return Math.min(window.devicePixelRatio || 1, MAX_DPR);\n}\n\n/** True when the circle at (x, y, r) can possibly touch the rect. */\nfunction inRect(x: number, y: number, r: number, rect: CanvasRect): boolean {\n return (\n x + r >= rect.x &&\n x - r <= rect.x + rect.width &&\n y + r >= rect.y &&\n y - r <= rect.y + rect.height\n );\n}\n\nexport class ScatterCanvasRenderer {\n private readonly canvas: HTMLCanvasElement;\n /**\n * `null` when the environment has no 2D context (happy-dom without a stub,\n * or a browser that refused the context). `render()` becomes a no-op rather\n * than throwing — a chart missing its dots beats a chart that crashes.\n */\n private readonly ctx: CanvasRenderingContext2D | null;\n private dpr: number;\n private cssWidth = 0;\n private cssHeight = 0;\n\n /**\n * A DPR to use instead of the display's. Set only for offscreen export\n * rasters, where the output resolution is a deliberate choice and must not\n * follow whatever monitor the browser happens to be on.\n */\n private readonly pinnedDpr: number | undefined;\n\n constructor(canvas: HTMLCanvasElement, pinnedDpr?: number) {\n this.canvas = canvas;\n this.ctx = canvas.getContext('2d');\n this.pinnedDpr = pinnedDpr;\n this.dpr = pinnedDpr ?? currentDpr();\n }\n\n /**\n * Resize the backing store. DPR is re-read here, not frozen in the\n * constructor: dragging a window between a Retina and a non-Retina display\n * changes `devicePixelRatio` mid-life, and resize is exactly when we find out.\n * A pinned DPR opts out -- an export raster has no display to follow.\n */\n resize(width: number, height: number): void {\n this.dpr = this.pinnedDpr ?? currentDpr();\n this.cssWidth = width;\n this.cssHeight = height;\n this.canvas.width = Math.round(width * this.dpr);\n this.canvas.height = Math.round(height * this.dpr);\n }\n\n /** Clear and paint the full state. */\n render(state: ScatterCanvasState): void {\n const ctx = this.ctx;\n if (!ctx) return;\n const dpr = this.dpr;\n const cssWidth = this.cssWidth;\n const cssHeight = this.cssHeight;\n\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n ctx.clearRect(0, 0, cssWidth, cssHeight);\n\n // Background full-bleed: the SVG suppresses its background rect in canvas\n // mode, so this layer owns the figure's surface color.\n if (state.background && state.background !== 'transparent') {\n ctx.fillStyle = state.background;\n ctx.fillRect(0, 0, cssWidth, cssHeight);\n }\n\n const clip = state.clipRect;\n ctx.save();\n ctx.beginPath();\n ctx.rect(clip.x, clip.y, clip.width, clip.height);\n ctx.clip();\n\n this.drawGridlines(ctx, state);\n if (state.exiting && state.exiting.alpha > 0) this.drawGhosts(ctx, state);\n this.drawPoints(ctx, state);\n this.drawStrokes(ctx, state);\n this.drawHoverRing(ctx, state);\n\n ctx.globalAlpha = 1;\n ctx.restore();\n }\n\n // -------------------------------------------------------------------------\n // Gridlines\n // -------------------------------------------------------------------------\n\n /**\n * Gridlines, batched per alpha. Geometry mirrors `renderers/axes.ts`:\n * y-axis lines span the plot width, x-axis lines span the plot height.\n */\n private drawGridlines(ctx: CanvasRenderingContext2D, state: ScatterCanvasState): void {\n if (state.gridlines.length === 0) return;\n const area = state.plotRect;\n\n const byAlpha = new Map<number, ScatterCanvasState['gridlines']>();\n for (const gridline of state.gridlines) {\n const bucket = byAlpha.get(gridline.alpha);\n if (bucket) bucket.push(gridline);\n else byAlpha.set(gridline.alpha, [gridline]);\n }\n\n ctx.strokeStyle = state.gridlineStroke;\n ctx.lineWidth = state.gridlineWidth;\n for (const [alpha, bucket] of byAlpha) {\n if (alpha <= 0) continue;\n ctx.globalAlpha = alpha;\n ctx.beginPath();\n for (const gridline of bucket) {\n if (gridline.orient === 'y') {\n ctx.moveTo(area.x, gridline.position);\n ctx.lineTo(area.x + area.width, gridline.position);\n } else {\n ctx.moveTo(gridline.position, area.y);\n ctx.lineTo(gridline.position, area.y + area.height);\n }\n }\n ctx.stroke();\n }\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Exit ghosts (painted UNDER the live points)\n // -------------------------------------------------------------------------\n\n /**\n * Per-ghost `fill()`, same reasoning as `drawPoints`: a shared path would\n * union overlapping ghosts and fade the union once, so a dense exiting\n * cluster would visibly lighten the moment the transition started.\n */\n private drawGhosts(ctx: CanvasRenderingContext2D, state: ScatterCanvasState): void {\n const exiting = state.exiting;\n if (!exiting) return;\n const clip = state.clipRect;\n\n ctx.globalAlpha = exiting.alpha;\n let lastFill = '';\n for (let i = 0; i < exiting.r.length; i++) {\n const r = exiting.r[i];\n if (r <= 0) continue;\n const x = exiting.x[i];\n const y = exiting.y[i];\n if (!inRect(x, y, r, clip)) continue;\n\n const fill = exiting.fill[i];\n if (fill !== lastFill) {\n ctx.fillStyle = fill;\n lastFill = fill;\n }\n\n ctx.beginPath();\n ctx.arc(x, y, r, 0, TWO_PI);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Live points\n // -------------------------------------------------------------------------\n\n /**\n * Fill pass: one `fill()` per point.\n *\n * NOT batched into shared paths, and that is load-bearing. Circles that\n * overlap inside a single path are unioned by the fill rule, so one `fill()`\n * at `globalAlpha` fades the whole union ONCE -- a six-deep stack at opacity\n * 0.35 came out at 0.65 luminance instead of 0.12. SVG composites every\n * `<circle>` independently and builds toward opaque. Batching made dense\n * scatters render washed out while their exports (real SVG) looked correct.\n *\n * Per-circle is also measurably FASTER at every point count we care about\n * (~1.5x at 4k, ~3.7x at 50k in headless Chromium): thousands of tiny\n * independent fills beat one enormous multi-subpath tessellation. So there is\n * no correctness-vs-speed tradeoff being made here -- batching lost on both.\n *\n * Points are painted in mark order, NOT sorted by fill. Sorting would cut\n * `fillStyle` assignments but reorder which dot lands on top, and with\n * translucent marks paint order is visible -- SVG paints in mark order, so\n * matching it is the whole point. The cheap `lastFill`/`lastAlpha` guards\n * below skip redundant state writes within same-colored runs instead.\n */\n private drawPoints(ctx: CanvasRenderingContext2D, state: ScatterCanvasState): void {\n const marks = state.marks;\n const enterAlpha = state.enterAlpha;\n const clip = state.clipRect;\n\n let lastFill = '';\n let lastAlpha = -1;\n for (let i = 0; i < marks.n; i++) {\n const r = marks.r[i];\n if (r <= 0) continue;\n const x = marks.x[i];\n const y = marks.y[i];\n if (!inRect(x, y, r, clip)) continue;\n const alpha = marks.fillOpacity[i] * (enterAlpha ? enterAlpha[i] : 1);\n if (alpha <= 0) continue;\n\n const fill = marks.fill[i];\n if (fill !== lastFill) {\n ctx.fillStyle = fill;\n lastFill = fill;\n }\n if (alpha !== lastAlpha) {\n ctx.globalAlpha = alpha;\n lastAlpha = alpha;\n }\n\n ctx.beginPath();\n ctx.arc(x, y, r, 0, TWO_PI);\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n }\n\n /**\n * Stroke pass: one `stroke()` per point, for the same compositing reason as\n * `drawPoints` -- translucent strokes on overlapping dots must accumulate.\n */\n private drawStrokes(ctx: CanvasRenderingContext2D, state: ScatterCanvasState): void {\n const marks = state.marks;\n const enterAlpha = state.enterAlpha;\n const clip = state.clipRect;\n\n let lastStroke = '';\n let lastWidth = -1;\n let lastAlpha = -1;\n for (let i = 0; i < marks.n; i++) {\n const width = marks.strokeWidth[i];\n const stroke = marks.stroke[i];\n if (!stroke || width <= 0) continue;\n const r = marks.r[i];\n if (r <= 0) continue;\n const x = marks.x[i];\n const y = marks.y[i];\n if (!inRect(x, y, r, clip)) continue;\n // `enterAlpha` only. `fillOpacity` is deliberately excluded to match the\n // SVG renderer, where `fill-opacity` never touches the stroke.\n const alpha = enterAlpha ? enterAlpha[i] : 1;\n if (alpha <= 0) continue;\n\n if (stroke !== lastStroke) {\n ctx.strokeStyle = stroke;\n lastStroke = stroke;\n }\n if (width !== lastWidth) {\n ctx.lineWidth = width;\n lastWidth = width;\n }\n if (alpha !== lastAlpha) {\n ctx.globalAlpha = alpha;\n lastAlpha = alpha;\n }\n\n ctx.beginPath();\n ctx.arc(x, y, r, 0, TWO_PI);\n ctx.stroke();\n }\n ctx.globalAlpha = 1;\n }\n\n // -------------------------------------------------------------------------\n // Hover\n // -------------------------------------------------------------------------\n\n private drawHoverRing(ctx: CanvasRenderingContext2D, state: ScatterCanvasState): void {\n const i = state.hoverIndex;\n if (i < 0 || i >= state.marks.n) return;\n const marks = state.marks;\n const r = marks.r[i];\n if (r <= 0) return;\n\n ctx.globalAlpha = 1;\n ctx.strokeStyle = state.accent;\n ctx.lineWidth = 2;\n ctx.beginPath();\n ctx.arc(marks.x[i], marks.y[i], r + HOVER_RING_PAD, 0, TWO_PI);\n ctx.stroke();\n }\n}\n","/**\n * Build the canvas render state from a compiled ChartLayout.\n *\n * The canvas is sized to the FULL figure, not `layout.area`, so canvas\n * coordinates equal layout coordinates and the layer can paint the theme\n * background full-bleed. Everything the renderer needs is resolved here once\n * per layout; the render loop reads only typed arrays.\n */\n\nimport type { AxisLayout, ChartLayout, GradientDef, PointMark } from '@opendata-ai/openchart-core';\nimport type { CanvasGridline, CanvasRect, ScatterCanvasState, ScatterPointsSoA } from './types';\n\n/**\n * Reduce a fill to a single solid color for canvas painting.\n *\n * Gradients flatten to their FIRST stop. Canvas could paint a real\n * `createLinearGradient`, but per-mark gradient objects would break the\n * fill-color batching that makes this layer fast, and scatter gradients are\n * near-uniform at point scale. Exports render true gradients by materializing\n * an SVG-mode render instead (a later stage), so the flattening is screen-only.\n */\nexport function flattenFill(fill: string | GradientDef): string {\n // 'transparent', not 'none': canvas silently ignores invalid fillStyle\n // assignments, so 'none' would leave the previous fill color in effect.\n if (typeof fill === 'string') return fill.toLowerCase() === 'none' ? 'transparent' : fill;\n return fill.stops[0]?.color ?? 'transparent';\n}\n\n/**\n * Normalize a stroke color for canvas painting.\n *\n * SVG accepts `stroke=\"none\"` as \"draw no stroke\"; canvas does not. Assigning\n * an invalid string to `strokeStyle` is silently IGNORED, so a 'none' that\n * reaches the stroke pass strokes every point with whatever color was set\n * last. The renderer skips points whose stroke is the empty string, so '' is\n * the canvas spelling of \"no stroke\" — and unlike 'transparent' (which is\n * normalized here too), it skips the per-point `stroke()` call entirely.\n */\nexport function normalizeStroke(stroke: string | undefined): string {\n if (!stroke) return '';\n const lower = stroke.toLowerCase();\n return lower === 'none' || lower === 'transparent' ? '' : stroke;\n}\n\n/** Collect gridlines from one axis into canvas-space records. */\nfunction collectGridlines(\n axis: AxisLayout | undefined,\n orient: 'x' | 'y',\n out: CanvasGridline[],\n): void {\n if (!axis) return;\n // Mirrors renderers/axes.ts: a right-side y-axis renders no gridlines (the\n // left axis already supplies them).\n if (orient === 'y' && axis.orient === 'right') return;\n for (const gridline of axis.gridlines) {\n out.push({ orient, position: gridline.position, alpha: GRIDLINE_ALPHA });\n }\n}\n\n/** Matches the SVG renderer's `stroke-opacity` on `.oc-gridline`. */\nconst GRIDLINE_ALPHA = 0.6;\n\n/** Matches the SVG renderer's `stroke-width` on `.oc-gridline`. */\nconst GRIDLINE_WIDTH = 1;\n\n/**\n * Compute the mark clip rect. Byte-for-byte the same formula as\n * `svg-renderer.ts` so the canvas and SVG layers clip identically: full figure\n * width, vertically padded by the largest point radius (min 2px).\n */\nexport function computeClipRect(layout: ChartLayout): CanvasRect {\n const maxPointR = layout.marks.reduce(\n (max, m) => (m.type === 'point' && m.r ? Math.max(max, m.r) : max),\n 0,\n );\n const clipPad = Math.max(maxPointR, 2);\n return {\n x: 0,\n y: layout.area.y - clipPad,\n width: layout.dimensions.width,\n height: layout.area.height + clipPad * 2,\n };\n}\n\n/** Pack every point mark in the layout into a struct-of-arrays. */\nexport function buildPointsSoA(layout: ChartLayout): ScatterPointsSoA {\n // Two passes: the first counts so every typed array is allocated exactly once.\n const points: { mark: PointMark; markId: string }[] = [];\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n if (mark.type !== 'point') continue;\n // `point-${i}` keys off the ORIGINAL marks index — tooltip descriptors and\n // chart-event payloads are built the same way (see interactions/chart-events).\n points.push({ mark, markId: `point-${i}` });\n }\n\n const n = points.length;\n const soa: ScatterPointsSoA = {\n n,\n x: new Float32Array(n),\n y: new Float32Array(n),\n r: new Float32Array(n),\n fill: new Array<string>(n),\n fillOpacity: new Float32Array(n),\n stroke: new Array<string>(n),\n strokeWidth: new Float32Array(n),\n keys: new Array<string | undefined>(n),\n markIds: new Array<string>(n),\n animationIndex: new Uint32Array(n),\n data: new Array<unknown>(n),\n };\n\n for (let j = 0; j < n; j++) {\n const { mark, markId } = points[j];\n soa.x[j] = mark.cx;\n soa.y[j] = mark.cy;\n soa.r[j] = mark.r;\n soa.fill[j] = flattenFill(mark.fill);\n soa.fillOpacity[j] = mark.fillOpacity ?? 1;\n soa.stroke[j] = normalizeStroke(mark.stroke);\n soa.strokeWidth[j] = mark.strokeWidth ?? 0;\n soa.keys[j] = mark.key;\n soa.markIds[j] = markId;\n soa.animationIndex[j] = mark.animationIndex ?? 0;\n soa.data[j] = mark.data;\n }\n\n return soa;\n}\n\n/** Build the full canvas render state for a layout. */\nexport function buildScatterCanvasState(layout: ChartLayout): ScatterCanvasState {\n const gridlines: CanvasGridline[] = [];\n collectGridlines(layout.axes.y, 'y', gridlines);\n collectGridlines(layout.axes.y2, 'y', gridlines);\n collectGridlines(layout.axes.x, 'x', gridlines);\n\n return {\n width: layout.dimensions.width,\n height: layout.dimensions.height,\n clipRect: computeClipRect(layout),\n background: layout.theme.colors.background,\n marks: buildPointsSoA(layout),\n gridlines,\n gridlineStroke: layout.theme.colors.gridline,\n gridlineWidth: GRIDLINE_WIDTH,\n plotRect: {\n x: layout.area.x,\n y: layout.area.y,\n width: layout.area.width,\n height: layout.area.height,\n },\n accent: layout.theme.colors.categorical[0] ?? layout.theme.colors.text,\n enterAlpha: null,\n exiting: null,\n hoverIndex: -1,\n };\n}\n","/**\n * Exports for charts rendered in canvas mark mode.\n *\n * On screen, canvas mode splits the figure across two surfaces: a `<canvas>`\n * painting background, gridlines and dots, and an SVG carrying axes, trendline,\n * annotations and chrome. Serializing the SVG alone would export a chart with\n * no data in it, so every format has to re-materialize the missing half.\n *\n * Two strategies, chosen by point count:\n *\n * - **Vector** (at or below `VECTOR_EXPORT_MAX_POINTS`): re-render the layout\n * as if canvas mode had never been asked for. `renderChartSVG` keys ONLY on\n * `opts.canvasMarks`, never on `layout.markRenderMode`, so simply omitting\n * the option yields a full-fidelity SVG by construction -- true gradients,\n * vector gridlines, real background rect, one `<circle>` per dot. Pixel-\n * identical to what an SVG-mode chart of the same spec exports.\n *\n * - **Raster marks** (above it): keep the SVG vector for everything except the\n * dots, and inline one canvas pass of the marks as an `<image>`. 50,000\n * `<circle>` elements is not a file anyone wants; the gridlines, axes and\n * text stay crisp and only the dot cloud rasterizes.\n */\n\nimport type { ChartLayout } from '@opendata-ai/openchart-core';\nimport { ScatterCanvasRenderer } from './scatter-canvas/renderer';\nimport { buildScatterCanvasState } from './scatter-canvas/state';\nimport { renderChartSVG } from './svg-renderer';\n\n/**\n * Point count above which SVG/PNG export inlines the marks as a raster\n * `<image>` instead of emitting one `<circle>` each.\n *\n * A judgment cap. Below it the per-element cost is worth full vector fidelity;\n * above it the file size and the consuming editor's patience are not.\n */\nexport const VECTOR_EXPORT_MAX_POINTS = 5000;\n\n/** Device pixel ratio for the offscreen mark raster. */\nconst RASTER_DPR = 2;\n\n/** Count the point marks in a layout. */\nfunction pointCount(layout: ChartLayout): number {\n let n = 0;\n for (const mark of layout.marks) {\n if (mark.type === 'point') n++;\n }\n return n;\n}\n\n/**\n * Render `layout` to a detached SVG exactly as SVG mode would.\n *\n * Detached rendering is safe here: `renderChartSVG` takes no measurements off\n * the live document, its generated ids come from a monotonic module counter, and\n * it injects nothing into `<head>`. The container is never inserted, so this\n * costs one render and no layout.\n */\nfunction materializeSvgModeSVG(layout: ChartLayout): SVGElement {\n const host = document.createElement('div');\n // No `canvasMarks` option: the renderer emits the full SVG -- background,\n // gridlines and every point circle.\n return renderChartSVG(layout, host, { animate: false });\n}\n\n/**\n * Render `layout` with vector everything-but-the-dots, and the dots inlined as\n * a single raster `<image>`.\n *\n * The image goes in as the FIRST child of the clipped marks group, so it lands\n * under the trendline and any overlays -- matching the on-screen stack, where\n * the canvas sits below the SVG.\n */\nfunction materializeRasterMarkSVG(layout: ChartLayout): SVGElement {\n const host = document.createElement('div');\n // Full SVG first, then strip the circles. NOT `canvasMarks: true`: that\n // option also suppresses the background rect and the gridlines, and this\n // path wants both of those in vector -- only the dot cloud rasterizes.\n const svg = renderChartSVG(layout, host, { animate: false });\n\n const dataUrl = rasterizeMarks(layout);\n // No raster available (no 2D context, no toDataURL): keep the vector circles\n // rather than shipping an empty plot. A large file beats a blank chart.\n if (!dataUrl) {\n console.warn(\n '[viz] Canvas raster export unavailable in this environment; exporting all points as vector SVG (larger file).',\n );\n return svg;\n }\n\n for (const circle of svg.querySelectorAll('circle.oc-mark-point')) {\n circle.remove();\n }\n\n const { width, height } = layout.dimensions;\n const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n image.setAttribute('x', '0');\n image.setAttribute('y', '0');\n image.setAttribute('width', String(width));\n image.setAttribute('height', String(height));\n image.setAttribute('href', dataUrl);\n // Older consumers (some editors, librsvg) only honor the namespaced form.\n image.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', dataUrl);\n image.setAttribute('aria-hidden', 'true');\n\n const marksGroup = svg.querySelector('[data-oc-marks-group]');\n if (marksGroup) marksGroup.insertBefore(image, marksGroup.firstChild);\n return svg;\n}\n\n/**\n * Paint just the marks to an offscreen canvas and return a data URL.\n *\n * Background and gridlines are stripped from the state rather than skipped in\n * the renderer: the SVG already draws both as vector, and painting them again\n * underneath would double the gridline strokes and hide the vector background.\n *\n * Returns `null` when the environment cannot produce a raster (no 2D context,\n * no `toDataURL`), so the caller falls back to a marks-free SVG rather than\n * throwing. A chart missing its dots beats an export that crashes.\n */\nfunction rasterizeMarks(layout: ChartLayout): string | null {\n const { width, height } = layout.dimensions;\n const canvas = document.createElement('canvas');\n\n const state = buildScatterCanvasState(layout);\n // Marks only: the SVG underneath already carries a vector background and\n // vector gridlines, and painting them again here would double them up.\n // Blank rather than 'transparent' -- the renderer skips the background on a\n // falsy value, so this holds for any theme, including one whose background\n // resolves to 'none' or an alpha-zero rgba() that is truthy but invisible.\n state.background = '';\n state.gridlines = [];\n\n const renderer = new ScatterCanvasRenderer(canvas, RASTER_DPR);\n renderer.resize(width, height);\n renderer.render(state);\n\n if (typeof canvas.toDataURL !== 'function') return null;\n try {\n return canvas.toDataURL('image/png');\n } catch {\n // Tainted canvas, or a stub that only pretends to implement the API.\n return null;\n }\n}\n\n/**\n * Materialize a canvas-mode layout into a single self-contained SVG element.\n *\n * This is what every export format consumes: SVG serializes it directly, and\n * PNG/JPG/GIF rasterize it. Raster formats always take the vector path\n * regardless of point count -- they are becoming pixels anyway, so the one-shot\n * cost of the full SVG buys pixel-parity with SVG mode for free.\n *\n * This is also why the GIF path needs no canvas compositing. Handing the\n * encoder a complete SVG means the existing frame pipeline works unchanged: no\n * per-frame `drawImage` of the live mark canvas, no background sourced from a\n * suppressed rect, no second code path to keep in sync with the first.\n */\nexport function materializeCanvasModeSVG(\n layout: ChartLayout,\n opts?: { forceVector?: boolean },\n): SVGElement {\n if (opts?.forceVector || pointCount(layout) <= VECTOR_EXPORT_MAX_POINTS) {\n return materializeSvgModeSVG(layout);\n }\n return materializeRasterMarkSVG(layout);\n}\n","/**\n * Shared easing and interpolation primitives.\n *\n * Single source of truth for the hand-rolled easings used by the canvas\n * scheduler (motion/tween.ts), the update-transition driver (transition.ts)\n * and the story tweens (story/tween.ts). No `d3-ease` dependency.\n */\n\n/** Linear (identity) easing. Required for stacked/segmented handoffs. */\nexport function linear(t: number): number {\n return t;\n}\n\n/** Cubic-out: decelerates into place. Maps to `'snappy'`. */\nexport function cubicOut(t: number): number {\n const f = 1 - t;\n return 1 - f * f * f;\n}\n\n/** Cubic-in-out: eases in and out. Maps to `'smooth'`. */\nexport function cubicInOut(t: number): number {\n return t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;\n}\n\nexport const clamp01 = (t: number): number => Math.min(1, Math.max(0, t));\n\nexport const lerp = (a: number, b: number, t: number): number => a + (b - a) * t;\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)', // intentionally 0.4, not --oc-editable-hover (0.35)\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// ---------------------------------------------------------------------------\n// Position-based overlay (for creating new annotations at a click position)\n// ---------------------------------------------------------------------------\n\nexport interface TextEditOverlayAtPositionConfig {\n container: HTMLElement;\n svg: SVGSVGElement;\n position: { x: number; y: number };\n onCommit: (text: string) => void;\n onCancel: () => void;\n}\n\nexport function createTextEditOverlayAtPosition(config: TextEditOverlayAtPositionConfig): {\n destroy: () => void;\n} {\n const { container, svg, position, onCommit, onCancel } = config;\n\n let destroyed = false;\n\n const scale = getScale(svg);\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n\n const padding = 4;\n const left = position.x * scale.scaleX + (svgRect.left - containerRect.left) - padding;\n const top = position.y * scale.scaleY + (svgRect.top - containerRect.top) - padding;\n\n const computedStyle = window.getComputedStyle(svg);\n const fontFamily = computedStyle.getPropertyValue('--oc-font-family').trim() || 'inherit';\n const textColor =\n computedStyle.getPropertyValue('--oc-text-color').trim() || computedStyle.color || '#333';\n const surfaceColor =\n computedStyle.getPropertyValue('--oc-surface-color').trim() || 'rgba(255, 255, 255, 0.95)';\n const fontSize = 13 * scale.scaleY;\n\n const textarea = document.createElement('textarea');\n textarea.value = '';\n textarea.placeholder = 'Type annotation text...';\n\n const containerPosition = window.getComputedStyle(container).position;\n const containerWasStatic = containerPosition === 'static';\n if (containerWasStatic) {\n container.style.position = 'relative';\n }\n\n Object.assign(textarea.style, {\n position: 'absolute',\n top: `${Math.max(0, top)}px`,\n left: `${Math.max(0, left)}px`,\n width: '160px',\n minHeight: '24px',\n fontFamily,\n fontSize: `${fontSize}px`,\n fontWeight: '400',\n color: textColor,\n textAlign: 'left',\n lineHeight: '1.3',\n padding: '2px 4px',\n margin: '0',\n border: '1px solid rgba(79, 70, 229, 0.4)',\n borderRadius: '3px',\n background: surfaceColor,\n outline: 'none',\n resize: 'none',\n overflow: 'hidden',\n boxSizing: 'border-box',\n zIndex: '10000',\n WebkitAppearance: 'none',\n appearance: 'none',\n } as Record<string, string>);\n\n container.appendChild(textarea);\n textarea.focus();\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n textarea.removeEventListener('keydown', handleKeyDown);\n document.removeEventListener('mousedown', handleClickOutside);\n\n if (containerWasStatic) {\n container.style.position = '';\n }\n\n if (textarea.parentNode) {\n textarea.parentNode.removeChild(textarea);\n }\n }\n\n function commit(): void {\n if (destroyed) return;\n const text = textarea.value.trim();\n destroy();\n if (text) {\n onCommit(text);\n } else {\n onCancel();\n }\n }\n\n function cancel(): void {\n if (destroyed) return;\n destroy();\n onCancel();\n }\n\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 const handleClickOutside = (e: MouseEvent) => {\n if (!textarea.contains(e.target as Node)) {\n commit();\n }\n };\n\n requestAnimationFrame(() => {\n if (!destroyed) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n });\n\n return { destroy };\n}\n","import type { ResolvedAnnotation } from '@opendata-ai/openchart-core';\n\n/**\n * Stable identity for an annotation across layout snapshots.\n *\n * Annotations have no engine-assigned `mark.key`. When the author supplies\n * `annotation.id` that is the identity; otherwise fall back to type + text,\n * which is stable as long as the annotation keeps saying the same thing.\n *\n * Deliberately NOT keyed on position: an annotation that moves is the same\n * annotation and should tween to its new spot, not cross-fade with itself.\n * And deliberately NOT `data-annotation-index`: that is positional, so\n * inserting an annotation ahead of another would renumber it and make every\n * later annotation look brand new and re-fade.\n *\n * Duplicate keys (same type and text twice) are disambiguated by occurrence\n * order in `keyAnnotations` below, not here.\n */\nexport function annotationKey(a: ResolvedAnnotation): string {\n if (a.id) return `id:${a.id}`;\n return `${a.type}:${a.label?.text ?? ''}`;\n}\n\n/**\n * Key a layout's annotations, suffixing duplicates so every key is unique\n * within the snapshot. Two annotations sharing a key would otherwise both\n * match the same element and fight over it.\n */\nexport function keyAnnotations(annotations: ResolvedAnnotation[]): string[] {\n const seen = new Map<string, number>();\n return annotations.map((a) => {\n const base = annotationKey(a);\n const n = seen.get(base) ?? 0;\n seen.set(base, n + 1);\n return n === 0 ? base : `${base}#${n}`;\n });\n}\n","import type { ChartLayout } from '@opendata-ai/openchart-core';\n\nimport { keyAnnotations } from './keys';\n\n// ---------------------------------------------------------------------------\n// canTransition gate\n// ---------------------------------------------------------------------------\n\n/**\n * Mark types that support data-update transitions.\n *\n * Sparklines are NOT excluded: a live-updating sparkline is the canonical\n * real-time tile, and the line/area path morph works at sparkline scale like\n * anywhere else.\n */\nexport const TRANSITIONABLE_MARKS = new Set(['bar', 'line', 'area', 'point', 'beeswarm', 'arc']);\n\n/**\n * Default cap on the mark count that still runs a tweened data-update\n * transition. Override per chart with `animation.update.maxMarks`.\n */\nexport const DEFAULT_UPDATE_MAX_MARKS = 500;\n\n/**\n * Default cap when the destination layout renders its points on canvas.\n *\n * Two orders of magnitude above the SVG cap because the cost model is\n * different: a canvas frame writes into typed arrays and issues one batched\n * fill per color bucket, where the SVG path writes attributes on one DOM\n * element per mark. The cap that keeps low-end devices honest for DOM writes\n * would veto exactly the high-cardinality morphs canvas mode exists to serve.\n */\nexport const CANVAS_DEFAULT_UPDATE_MAX_MARKS = 20_000;\n\n/**\n * Spec-shape half of the transition gate (mark type + encoding identity),\n * usable before either spec has been compiled. Exported so callers that\n * need to predict transition eligibility ahead of a compile (e.g. the\n * scrollytelling story layer deciding whether to arm its crossfade\n * fallback) can reuse the exact same rule the post-compile gate enforces,\n * rather than re-deriving it and risking drift.\n *\n * This is gate checks 3-4 of `canTransition` in isolation; it does NOT\n * check layout-derived conditions (dimensions, mark count, geometry delta)\n * since those require a compiled `ChartLayout`.\n */\nexport function canTransitionSpecShape(prevSpec: unknown, nextSpec: unknown): boolean {\n const prev = prevSpec as Record<string, unknown>;\n const next = nextSpec as Record<string, unknown>;\n if (!prev || !next || !('mark' in prev) || !('mark' in next)) return false;\n const prevMark =\n typeof prev.mark === 'string' ? prev.mark : (prev.mark as Record<string, unknown>)?.type;\n const nextMark =\n typeof next.mark === 'string' ? next.mark : (next.mark as Record<string, unknown>)?.type;\n if (prevMark !== nextMark) return false;\n if (!TRANSITIONABLE_MARKS.has(prevMark as string)) return false;\n\n const prevEnc = (prev as { encoding?: Record<string, Record<string, unknown>> }).encoding;\n const nextEnc = (next as { encoding?: Record<string, Record<string, unknown>> }).encoding;\n if (!prevEnc || !nextEnc) return false;\n return !(\n prevEnc.x?.field !== nextEnc.x?.field ||\n prevEnc.x?.type !== nextEnc.x?.type ||\n prevEnc.y?.field !== nextEnc.y?.field ||\n prevEnc.y?.type !== nextEnc.y?.type ||\n prevEnc.theta?.field !== nextEnc.theta?.field ||\n prevEnc.theta?.type !== nextEnc.theta?.type ||\n prevEnc.color?.field !== nextEnc.color?.field ||\n prevEnc.key?.field !== nextEnc.key?.field ||\n prevEnc.facet?.field !== nextEnc.facet?.field ||\n prevEnc.row?.field !== nextEnc.row?.field ||\n prevEnc.column?.field !== nextEnc.column?.field\n );\n}\n\n/**\n * Determine whether a data-update transition should run instead of\n * a full tear-down + re-render.\n *\n * Nine gate checks must all pass. If any fails, the caller should fall\n * through to the standard render path (instant swap).\n */\nexport function canTransition(args: {\n prevLayout: ChartLayout | null;\n nextLayout: ChartLayout;\n prevSpec: unknown;\n nextSpec: unknown;\n isFirstRender: boolean;\n entranceInFlight: boolean;\n}): boolean {\n const { prevLayout, nextLayout, prevSpec, nextSpec, isFirstRender, entranceInFlight } = args;\n\n // 1. Previous layout + spec exist and not first render\n if (!prevLayout || !prevSpec || isFirstRender) return false;\n\n // 2. Resolved animation.update present on next layout\n if (!nextLayout.animation?.update) return false;\n\n // 3-4. Mark type + encoding identity unchanged (spec-shape half of the gate)\n if (!canTransitionSpecShape(prevSpec, nextSpec)) return false;\n\n // 5. Entrance animation not in flight\n if (entranceInFlight) return false;\n\n // 6. Layout dimensions unchanged\n if (\n prevLayout.dimensions.width !== nextLayout.dimensions.width ||\n prevLayout.dimensions.height !== nextLayout.dimensions.height\n ) {\n return false;\n }\n\n // 7. Mark count within the update cap. Per-frame SVG attribute writes on\n // thousands of elements drop frames on low-end devices, so past the cap\n // the caller falls through to an instant swap.\n //\n // The cap comes from the DESTINATION mode, and so do exit ghosts -- they\n // are rendered into the next layout's surface. That makes the count that\n // matters `max(prev, next)`, not `next` alone: a 4,341-point canvas chart\n // updating down to 400 SVG points looks cheap by `next`, but the update\n // would mint ~3,941 SVG ghost circles, which is precisely the jank this\n // cap exists to prevent. (svg -> canvas needs no such guard: the canvas\n // cap applies and the exits paint on canvas.)\n const cap =\n nextLayout.animation.update.maxMarks ??\n (nextLayout.markRenderMode === 'canvas'\n ? CANVAS_DEFAULT_UPDATE_MAX_MARKS\n : DEFAULT_UPDATE_MAX_MARKS);\n if (Math.max(prevLayout.marks.length, nextLayout.marks.length) > cap) return false;\n\n // 8. Something visible actually changed (zero-delta check)\n if (!hasVisibleChange(prevLayout, nextLayout)) return false;\n\n // 9. prefers-reduced-motion not active\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n try {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return false;\n } catch {\n // happy-dom may not support matchMedia fully; treat as no preference\n }\n }\n\n return true;\n}\n\n/**\n * Check whether anything the transition can animate differs between layouts.\n *\n * Gate check 8. This is broader than geometry on purpose: a step that only\n * recolors (an `encoding.color.highlight` mute) or only adds an annotation\n * moves no mark by a single pixel. Testing geometry alone reported \"nothing\n * changed\" for those, vetoing the transition and leaving `render()`'s instant\n * swap as the only thing that happened -- so the highlight snapped and the\n * annotation popped in, even though the machinery to fade both already existed\n * further down this file.\n */\nexport function hasVisibleChange(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n return (\n hasGeometryChanged(prevLayout, nextLayout) ||\n hasColorChanged(prevLayout, nextLayout) ||\n hasAnnotationChanged(prevLayout, nextLayout)\n );\n}\n\n/** Check if any mark's fill or stroke differs (e.g. a highlight mute). */\nexport function hasColorChanged(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n const prevMarks = prevLayout.marks;\n const nextMarks = nextLayout.marks;\n if (prevMarks.length !== nextMarks.length) return true;\n\n for (let i = 0; i < prevMarks.length; i++) {\n const p = prevMarks[i] as { fill?: string; stroke?: string };\n const n = nextMarks[i] as { fill?: string; stroke?: string };\n if (p.fill !== n.fill || p.stroke !== n.stroke) return true;\n }\n return false;\n}\n\n/** Check if annotations were added, removed, reordered, or moved. */\nexport function hasAnnotationChanged(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n const prev = prevLayout.annotations ?? [];\n const next = nextLayout.annotations ?? [];\n if (prev.length !== next.length) return true;\n\n const prevKeys = keyAnnotations(prev);\n const nextKeys = keyAnnotations(next);\n\n for (let i = 0; i < prev.length; i++) {\n if (prevKeys[i] !== nextKeys[i]) return true;\n const p = prev[i];\n const n = next[i];\n if (p.label?.x !== n.label?.x || p.label?.y !== n.label?.y) return true;\n if (p.opacity !== n.opacity) return true;\n }\n return false;\n}\n\n/** Check if any mark geometry differs between prev and next layouts. */\nexport function hasGeometryChanged(prevLayout: ChartLayout, nextLayout: ChartLayout): boolean {\n const prevMarks = prevLayout.marks;\n const nextMarks = nextLayout.marks;\n\n if (prevMarks.length !== nextMarks.length) return true;\n\n for (let i = 0; i < prevMarks.length; i++) {\n const p = prevMarks[i];\n const n = nextMarks[i];\n if (p.type !== n.type || p.key !== n.key) return true;\n\n if (p.type === 'rect' && n.type === 'rect') {\n if (p.x !== n.x || p.y !== n.y || p.width !== n.width || p.height !== n.height) return true;\n } else if (p.type === 'line' && n.type === 'line') {\n if (p.path !== n.path || p.points.length !== n.points.length) return true;\n for (let j = 0; j < p.points.length; j++) {\n if (p.points[j].x !== n.points[j].x || p.points[j].y !== n.points[j].y) return true;\n }\n } else if (p.type === 'area' && n.type === 'area') {\n if (p.path !== n.path) return true;\n } else if (p.type === 'arc' && n.type === 'arc') {\n if (\n p.startAngle !== n.startAngle ||\n p.endAngle !== n.endAngle ||\n p.innerRadius !== n.innerRadius ||\n p.outerRadius !== n.outerRadius ||\n p.center.x !== n.center.x ||\n p.center.y !== n.center.y\n ) {\n return true;\n }\n } else if (p.type === 'point' && n.type === 'point') {\n if (p.cx !== n.cx || p.cy !== n.cy || p.r !== n.r) return true;\n } else if (p.type === 'rule' && n.type === 'rule') {\n if (p.x1 !== n.x1 || p.y1 !== n.y1 || p.x2 !== n.x2 || p.y2 !== n.y2) return true;\n } else if (p.type === 'tick' && n.type === 'tick') {\n if (p.x !== n.x || p.y !== n.y) return true;\n } else if (p.type === 'textMark' && n.type === 'textMark') {\n if (p.x !== n.x || p.y !== n.y) return true;\n }\n }\n return false;\n}\n","/**\n * Data-update transition driver for bar/column, line, area, scatter/dot,\n * rule, tick, and text charts. Also transitions axis ticks, tick labels,\n * and gridlines so the whole chart adjusts as one system.\n *\n * Matches marks across layout snapshots by `key`, then animates geometry\n * changes (position, size, path) using a single rAF loop. Enter/exit/update\n * choreography runs in one timeline with cubic-out easing for a smooth\n * deceleration feel.\n *\n * For rect marks: tweens position/size directly.\n * For line/area marks: normalizes point arrays to equal length, interpolates\n * point positions per frame, and rebuilds SVG paths via d3 curve generators.\n * For point marks (scatter/dot/line overlay): tweens cx/cy/r.\n * For rule/tick marks: tweens line endpoints (x1/y1/x2/y2).\n * For text marks: tweens x/y position.\n * For axis ticks/gridlines: matches by value key and tweens positions.\n *\n * Ghost elements handle exits: cloned into the marks container, they\n * collapse + fade out then get removed. No CSS animations are used here\n * because transitions tween computed geometry, not class-toggled states.\n */\n\nimport type {\n AreaMark,\n ChartLayout,\n LineMark,\n ResolvedAnimation,\n} from '@opendata-ai/openchart-core';\nimport { isGradientDef } from '@opendata-ai/openchart-core';\nimport { buildAreaPath, buildLinePath, EXIT_DEFAULTS } from '@opendata-ai/openchart-engine';\nimport { buildGradientDefs } from '../gradient-utils';\nimport { cubicOut } from '../motion/easing';\n\nimport { applyTweenState, getKeyForTween, lerpArcGeom, snapTweenToFinal } from './apply';\nimport { buildCanvasGridlinesTween, buildCanvasPointsTween } from './canvas-tweens';\nimport { buildAnnotationTweens, buildAxisTweens, buildColorTweens } from './chrome-tweens';\nimport { buildMarkDomIndex } from './dom-index';\nimport {\n applyFinalAreaPaths,\n applyFinalLinePath,\n interpolatePoints,\n lerpGeom,\n} from './interpolate';\nimport {\n buildArcTweens,\n buildAreaTweens,\n buildLineTweens,\n buildPointTweens,\n buildRectTweens,\n buildRuleTweens,\n buildTextMarkTweens,\n buildTickTweens,\n} from './svg-tweens';\nimport type {\n CanvasLayerLike,\n GeometrySnapshot,\n SnapshotGeometry,\n TransitionHandle,\n Tween,\n} from './types';\n\n// ---------------------------------------------------------------------------\n// runTransition\n// ---------------------------------------------------------------------------\n\nexport function runTransition(args: {\n svg: SVGSVGElement;\n prevLayout: ChartLayout;\n nextLayout: ChartLayout;\n animation: ResolvedAnimation;\n onComplete: () => void;\n /** Snapshot from a cancelled in-flight transition for retargeting. */\n fromSnapshot?: GeometrySnapshot;\n /**\n * Suppress the internal rAF loop; the caller drives the transition via\n * `handle.step(elapsedMs)`. Used by headless frame capture. `onComplete` is\n * NOT called automatically in manual mode — the caller finalizes by stepping\n * to `totalMs` (which snaps to final) or calling `cancel()`.\n */\n manual?: boolean;\n /**\n * The canvas mark layer, when the NEXT layout renders points on canvas. Point\n * geometry is then tweened into `canvas.state` instead of onto SVG circles,\n * and this one rAF loop paints it — the layer's own scheduler stays idle for\n * the duration (entrance blocks transitions; hover is suspended).\n */\n canvas?: CanvasLayerLike;\n}): TransitionHandle {\n const { svg, prevLayout, nextLayout, animation, onComplete, fromSnapshot, manual, canvas } = args;\n const update = animation.update!;\n const exit = animation.exit ?? { ...EXIT_DEFAULTS };\n\n // Total timeline\n const totalMs = Math.max(update.duration, exit.duration);\n const enterDelay = 0.4 * update.duration; // enters start at 40% of update duration\n const enterDuration = update.duration - enterDelay; // remaining 60%\n\n // Find the marks container in the SVG\n const marksContainer = svg.querySelector('.oc-marks') as SVGElement | null;\n if (!marksContainer) {\n onComplete();\n return {\n cancel() {},\n get running() {\n return false;\n },\n snapshot() {\n return new Map();\n },\n step() {\n return false;\n },\n totalMs: 0,\n };\n }\n\n // One DOM pass for every keyed mark element; valid for the whole transition\n // (the transition owns the DOM until onComplete, and ghosts carry no data-key).\n const dom = buildMarkDomIndex(marksContainer);\n\n // Build all tweens\n const tweens: Tween[] = [];\n const ghosts: SVGElement[] = [];\n\n // Fix gradient ghosts: ensure exiting marks with gradient fills have valid\n // gradient defs in the new SVG. Build any missing gradients into <defs>.\n const defs = svg.querySelector('defs') as SVGElement | null;\n let ghostGradientMap = new Map<string, string>();\n if (defs) {\n // Collect gradient fills from exiting marks (marks in prev but not next)\n const nextKeySet = new Set(nextLayout.marks.filter((m) => m.key).map((m) => m.key));\n const exitingMarks = prevLayout.marks.filter(\n (m) => m.key && !nextKeySet.has(m.key) && 'fill' in m,\n );\n const gradientMarks = exitingMarks.filter(\n (m) => 'fill' in m && isGradientDef((m as { fill: unknown }).fill),\n );\n if (gradientMarks.length > 0) {\n ghostGradientMap = buildGradientDefs(gradientMarks as Array<{ fill?: unknown }>, defs);\n }\n }\n\n // Determine what mark types we're dealing with\n const hasRects =\n prevLayout.marks.some((m) => m.type === 'rect') ||\n nextLayout.marks.some((m) => m.type === 'rect');\n const hasLines =\n prevLayout.marks.some((m) => m.type === 'line') ||\n nextLayout.marks.some((m) => m.type === 'line');\n const hasAreas =\n prevLayout.marks.some((m) => m.type === 'area') ||\n nextLayout.marks.some((m) => m.type === 'area');\n const hasArcs =\n prevLayout.marks.some((m) => m.type === 'arc') ||\n nextLayout.marks.some((m) => m.type === 'arc');\n const hasPoints =\n prevLayout.marks.some((m) => m.type === 'point') ||\n nextLayout.marks.some((m) => m.type === 'point');\n const hasRules =\n prevLayout.marks.some((m) => m.type === 'rule') ||\n nextLayout.marks.some((m) => m.type === 'rule');\n const hasTicks =\n prevLayout.marks.some((m) => m.type === 'tick') ||\n nextLayout.marks.some((m) => m.type === 'tick');\n const hasTextMarks =\n prevLayout.marks.some((m) => m.type === 'textMark') ||\n nextLayout.marks.some((m) => m.type === 'textMark');\n\n if (hasRects) {\n buildRectTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n dom,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n if (hasLines) {\n buildLineTweens(prevLayout, nextLayout, marksContainer, dom, tweens, ghosts, fromSnapshot);\n }\n if (hasAreas) {\n buildAreaTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n dom,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n if (hasArcs) {\n buildArcTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n dom,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n if (hasPoints) {\n // Either/or, never both: in canvas mode the SVG carries no point circles\n // for the DOM builder to find, and every point (including exit ghosts)\n // lives on the layer.\n if (canvas) {\n buildCanvasPointsTween(prevLayout, nextLayout, canvas, tweens, fromSnapshot);\n } else {\n buildPointTweens(\n prevLayout,\n nextLayout,\n marksContainer,\n dom,\n tweens,\n ghosts,\n ghostGradientMap,\n fromSnapshot,\n );\n }\n }\n if (hasRules) {\n buildRuleTweens(prevLayout, nextLayout, marksContainer, dom, tweens, ghosts, fromSnapshot);\n }\n if (hasTicks) {\n buildTickTweens(prevLayout, nextLayout, marksContainer, dom, tweens, ghosts, fromSnapshot);\n }\n if (hasTextMarks) {\n buildTextMarkTweens(prevLayout, nextLayout, marksContainer, dom, tweens, ghosts, fromSnapshot);\n }\n\n // Axis tick/gridline transitions. In canvas mode the SVG axes carry tick\n // labels but no gridlines (the layer paints those), so both run: the SVG pass\n // finds zero `.oc-gridline` elements and only tweens labels.\n buildAxisTweens(svg, prevLayout, nextLayout, tweens, ghosts);\n if (canvas) {\n buildCanvasGridlinesTween(prevLayout, nextLayout, canvas, tweens);\n }\n\n // Mark fill/stroke (a highlight mute recolors marks that never move)\n buildColorTweens(prevLayout, nextLayout, dom, tweens);\n\n // Annotations: keyed diff, so only NEW annotations fade in and surviving\n // ones hold steady instead of blinking.\n buildAnnotationTweens(svg, prevLayout, nextLayout, tweens);\n\n // Secondary element crossfade: endpoint labels and mark labels still use the\n // blanket fade (annotations were promoted to the keyed path above).\n const secondaryEls = collectSecondaryElements(svg);\n // Store original opacities so we can restore them on completion\n const secondaryOriginalOpacity = secondaryEls.map((el) => el.style.opacity ?? '');\n\n // Apply all from-states SYNCHRONOUSLY before scheduling the first rAF\n for (const tw of tweens) {\n applyTweenState(tw, 0, update, exit, enterDelay, enterDuration);\n }\n // ...and paint them. The state writes above only rewind the layer's data; the\n // bitmap still shows the final state until something repaints. Relying on\n // rAF-runs-before-paint is an accident of ordering, and manual mode has no\n // paint at all between beginManualUpdate() and the first step().\n canvas?.repaint();\n // Hit-testing is off while marks are in motion: the spatial index still\n // describes the destination layout, and rebuilding it per frame at 4k points\n // is exactly the cost the canvas layer exists to avoid.\n canvas?.setInteractionSuspended(true);\n // Set secondary elements to invisible at start\n for (const el of secondaryEls) {\n el.style.opacity = '0';\n }\n\n // Animation loop state\n let rafId: number | null = null;\n let running = true;\n let startTime: number | null = null;\n let lastElapsed = 0;\n\n // Track line/area marks that need final path snapping\n const nextLineMarks = nextLayout.marks.filter((m): m is LineMark => m.type === 'line');\n const nextAreaMarks = nextLayout.marks.filter((m): m is AreaMark => m.type === 'area');\n\n function tick(now: number): void {\n if (!running) return;\n if (startTime === null) startTime = now;\n\n const elapsed = now - startTime;\n lastElapsed = elapsed;\n const tGlobal = Math.min(elapsed / totalMs, 1);\n\n for (const tw of tweens) {\n applyTweenState(tw, elapsed, update, exit, enterDelay, enterDuration);\n }\n\n // Crossfade secondary elements: delayed 40%, over 60% of update duration\n applySecondaryOpacity(secondaryEls, elapsed, enterDelay, enterDuration);\n\n // One paint per frame, after every tween has written its state.\n canvas?.repaint();\n\n if (tGlobal >= 1) {\n finish();\n } else {\n rafId = requestAnimationFrame(tick);\n }\n }\n\n /** Settle the canvas layer: repaint the final state, re-index, re-arm hover. */\n function settleCanvas(): void {\n if (!canvas) return;\n canvas.repaint();\n canvas.rebuildIndex();\n canvas.setInteractionSuspended(false);\n }\n\n function finish(): void {\n if (!running) return;\n running = false;\n rafId = null;\n\n snapToFinal();\n removeGhosts();\n settleCanvas();\n // Restore secondary element opacities to their rendered values\n for (let i = 0; i < secondaryEls.length; i++) {\n secondaryEls[i].style.opacity = secondaryOriginalOpacity[i];\n }\n onComplete();\n }\n\n function snapToFinal(): void {\n for (const tw of tweens) {\n snapTweenToFinal(tw);\n }\n // Snap line/area paths to exact final mark paths (not interpolated)\n // to ensure round-trip invariant\n for (const mark of nextLineMarks) {\n if (!mark.key) continue;\n const el = dom.any(mark.key);\n if (el) applyFinalLinePath(el, mark);\n }\n for (const mark of nextAreaMarks) {\n if (!mark.key) continue;\n const el = dom.any(mark.key);\n if (el) applyFinalAreaPaths(el, mark);\n }\n }\n\n function removeGhosts(): void {\n for (const ghost of ghosts) {\n ghost.parentNode?.removeChild(ghost);\n }\n }\n\n /** Capture the current interpolated geometry of all in-flight tweens. */\n function captureSnapshot(): GeometrySnapshot {\n const snap: GeometrySnapshot = new Map();\n const tUpdate = Math.min(lastElapsed / update.duration, 1);\n const easedUpdate = cubicOut(tUpdate);\n\n for (const tw of tweens) {\n if (tw.kind !== 'update') continue;\n\n // Canvas points snapshot per-point from the packed arrays. The emitted\n // entries are plain `{type:'point'}` -- identical to what the SVG path\n // emits -- so an interrupted transition retargets correctly even across\n // an svg <-> canvas mode flip.\n if (tw.tweenType === 'canvasPoints') {\n for (let s = 0; s < tw.soaIndex.length; s++) {\n snap.set(tw.soaKeys[s], {\n type: 'point',\n cx: tw.fromCx[s] + (tw.toCx[s] - tw.fromCx[s]) * easedUpdate,\n cy: tw.fromCy[s] + (tw.toCy[s] - tw.fromCy[s]) * easedUpdate,\n r: tw.fromR[s] + (tw.toR[s] - tw.fromR[s]) * easedUpdate,\n });\n }\n continue;\n }\n\n const key = getKeyForTween(tw);\n if (!key) continue;\n\n switch (tw.tweenType) {\n case 'rect': {\n const g = lerpGeom(tw.from, tw.to, easedUpdate);\n snap.set(key, { type: 'rect', ...g });\n break;\n }\n case 'point': {\n const cx = tw.fromCx + (tw.toCx - tw.fromCx) * easedUpdate;\n const cy = tw.fromCy + (tw.toCy - tw.fromCy) * easedUpdate;\n const entry: SnapshotGeometry = { type: 'point', cx, cy };\n if (tw.fromR !== undefined && tw.toR !== undefined) {\n entry.r = tw.fromR + (tw.toR - tw.fromR) * easedUpdate;\n }\n snap.set(key, entry);\n break;\n }\n case 'rule':\n case 'tick': {\n snap.set(key, {\n type: tw.tweenType,\n x1: tw.fromX1 + (tw.toX1 - tw.fromX1) * easedUpdate,\n y1: tw.fromY1 + (tw.toY1 - tw.fromY1) * easedUpdate,\n x2: tw.fromX2 + (tw.toX2 - tw.fromX2) * easedUpdate,\n y2: tw.fromY2 + (tw.toY2 - tw.fromY2) * easedUpdate,\n });\n break;\n }\n case 'textMark': {\n snap.set(key, {\n type: 'textMark',\n x: tw.fromX + (tw.toX - tw.fromX) * easedUpdate,\n y: tw.fromY + (tw.toY - tw.fromY) * easedUpdate,\n });\n break;\n }\n case 'line': {\n // Freeze the current interpolated path string\n const pts = interpolatePoints(tw.fromPts, tw.toPts, easedUpdate);\n const d = buildLinePath(pts, tw.interpolate);\n snap.set(key, { type: 'line', d });\n break;\n }\n case 'area': {\n const top = interpolatePoints(tw.fromTop, tw.toTop, easedUpdate);\n const bottom = interpolatePoints(tw.fromBottom, tw.toBottom, easedUpdate);\n const d = buildAreaPath(top, bottom, tw.interpolate);\n let topD: string | undefined;\n if (tw.hasStroke) {\n topD = buildLinePath(top, tw.interpolate);\n }\n snap.set(key, { type: 'area', d, topD });\n break;\n }\n case 'arc': {\n snap.set(key, {\n type: 'arc',\n ...lerpArcGeom(tw.from, tw.to, easedUpdate),\n cx: tw.fromCenter.x + (tw.toCenter.x - tw.fromCenter.x) * easedUpdate,\n cy: tw.fromCenter.y + (tw.toCenter.y - tw.fromCenter.y) * easedUpdate,\n });\n break;\n }\n }\n }\n return snap;\n }\n\n // In manual mode the caller drives the transition via `step()`; skip the rAF\n // clock entirely. Otherwise start the normal real-time animation.\n if (!manual) {\n rafId = requestAnimationFrame(tick);\n }\n\n return {\n cancel(): void {\n if (!running) return;\n running = false;\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n snapToFinal();\n removeGhosts();\n settleCanvas();\n // Restore secondary element opacities on cancel\n for (let i = 0; i < secondaryEls.length; i++) {\n secondaryEls[i].style.opacity = secondaryOriginalOpacity[i];\n }\n },\n get running() {\n return running;\n },\n snapshot(): GeometrySnapshot {\n return captureSnapshot();\n },\n step(elapsedMs: number): boolean {\n // Apply the same per-tween state the rAF `tick` computes, at an explicit\n // time. No requestAnimationFrame — the caller (headless capture) rasterizes\n // between steps. Mirrors tick()'s body minus the rAF scheduling.\n lastElapsed = elapsedMs;\n for (const tw of tweens) {\n applyTweenState(tw, elapsedMs, update, exit, enterDelay, enterDuration);\n }\n applySecondaryOpacity(secondaryEls, elapsedMs, enterDelay, enterDuration);\n if (elapsedMs >= totalMs) {\n // Snap to exact final geometry (paths, ghosts removed) so the last frame\n // is pixel-correct, but do NOT flip `running` — the caller decides when\n // to finalize the manual run via `cancel()`.\n snapToFinal();\n removeGhosts();\n settleCanvas();\n return false;\n }\n // Manual mode rasterizes between steps with no rAF in between, so the\n // paint has to happen here or the captured frame is a stale bitmap.\n canvas?.repaint();\n return true;\n },\n totalMs,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Secondary element helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Collect endpoint-label and mark-label groups for the blanket crossfade.\n *\n * Annotations used to be in here, which is why an annotation that was already\n * on screen blinked out and back in on every update: the blanket fade drives\n * every element it collects from opacity 0, with no notion of which ones are\n * actually new. They now go through `buildAnnotationTweens` instead, which\n * diffs them by key. Do not re-add them here -- the blanket fade runs after the\n * tweens and would clobber the keyed opacity.\n */\nexport function collectSecondaryElements(svg: SVGSVGElement): SVGElement[] {\n const els: SVGElement[] = [];\n const epLabels = svg.querySelector('.oc-endpoint-labels') as SVGElement | null;\n if (epLabels) els.push(epLabels);\n const markLabels = svg.querySelector('.oc-mark-labels') as SVGElement | null;\n if (markLabels) els.push(markLabels);\n return els;\n}\n\n/** Apply delayed fade-in to secondary elements during transition. */\nexport function applySecondaryOpacity(\n els: SVGElement[],\n elapsed: number,\n enterDelay: number,\n enterDuration: number,\n): void {\n if (els.length === 0) return;\n let t: number;\n if (elapsed < enterDelay) {\n t = 0;\n } else {\n t = Math.min((elapsed - enterDelay) / enterDuration, 1);\n }\n const opacity = String(cubicOut(t));\n for (const el of els) {\n el.style.opacity = opacity;\n }\n}\n","import { buildArcPath } from '@opendata-ai/openchart-engine';\nimport { interpolateRgb } from 'd3-interpolate';\nimport { cubicOut } from '../motion/easing';\n\nimport {\n applyCanvasGridlinesState,\n applyCanvasPointsState,\n snapCanvasGridlinesToFinal,\n snapCanvasPointsToFinal,\n} from './canvas-tweens';\nimport {\n applyAreaPaths,\n applyGeomToElement,\n applyLinePath,\n interpolatePoints,\n lerpGeom,\n} from './interpolate';\nimport type { ArcGeom, ArcTween, Tween } from './types';\n\n// ---------------------------------------------------------------------------\n// Arc helpers (shared by the per-frame step and the final snap)\n// ---------------------------------------------------------------------------\n\n/** Lerp arc angle/radius geometry. */\nexport function lerpArcGeom(from: ArcGeom, to: ArcGeom, t: number): ArcGeom {\n return {\n startAngle: from.startAngle + (to.startAngle - from.startAngle) * t,\n endAngle: from.endAngle + (to.endAngle - from.endAngle) * t,\n innerRadius: from.innerRadius + (to.innerRadius - from.innerRadius) * t,\n outerRadius: from.outerRadius + (to.outerRadius - from.outerRadius) * t,\n };\n}\n\n/** Write an interpolated arc state onto the mark group's path + transform. */\nfunction applyArcState(tw: ArcTween, eased: number): void {\n const geom = lerpArcGeom(tw.from, tw.to, eased);\n const pathEl = tw.el.tagName === 'path' ? tw.el : tw.el.querySelector('path');\n pathEl?.setAttribute('d', buildArcPath(geom));\n if (tw.fromCenter.x !== tw.toCenter.x || tw.fromCenter.y !== tw.toCenter.y) {\n const cx = tw.fromCenter.x + (tw.toCenter.x - tw.fromCenter.x) * eased;\n const cy = tw.fromCenter.y + (tw.toCenter.y - tw.fromCenter.y) * eased;\n tw.el.setAttribute('transform', `translate(${cx},${cy})`);\n }\n}\n\n/** Get the data-key for a tween's element (used for snapshot keying). */\nexport function getKeyForTween(tw: Tween): string | null {\n // Canvas points are keyed per-point inside the record, not per-element.\n if (tw.tweenType === 'canvasPoints' || tw.tweenType === 'canvasGridlines') return null;\n if ('ghost' in tw && tw.ghost) return null; // ghosts don't carry keys\n return tw.el.getAttribute('data-key');\n}\n\n// ---------------------------------------------------------------------------\n// Tween state application (shared across all tween types)\n// ---------------------------------------------------------------------------\n\nexport function resolveLineElement(el: SVGElement): SVGElement {\n return el.tagName === 'line' ? el : ((el.querySelector('line') as SVGElement) ?? el);\n}\n\nexport function applyTweenState(\n tw: Tween,\n elapsed: number,\n update: { duration: number },\n exit: { duration: number },\n enterDelay: number,\n enterDuration: number,\n): void {\n // Canvas points carry all three phases in one record and have no element for\n // the shared geometry/opacity steps below to write to, so they short-circuit.\n if (tw.tweenType === 'canvasPoints') {\n applyCanvasPointsState(tw, elapsed, update, exit, enterDelay, enterDuration);\n return;\n }\n if (tw.tweenType === 'canvasGridlines') {\n applyCanvasGridlinesState(tw, elapsed, update, enterDelay, enterDuration);\n return;\n }\n\n let tLocal: number;\n\n if (tw.kind === 'exit') {\n tLocal = Math.min(elapsed / exit.duration, 1);\n } else if (tw.kind === 'enter') {\n if (elapsed < enterDelay) {\n tLocal = 0;\n } else {\n tLocal = Math.min((elapsed - enterDelay) / enterDuration, 1);\n }\n } else {\n tLocal = Math.min(elapsed / update.duration, 1);\n }\n\n const eased = cubicOut(tLocal);\n\n switch (tw.tweenType) {\n case 'rect': {\n const geom = lerpGeom(tw.from, tw.to, eased);\n applyGeomToElement(tw.el, geom, tw.mark);\n break;\n }\n case 'line': {\n const pts = interpolatePoints(tw.fromPts, tw.toPts, eased);\n applyLinePath(tw.el, pts, tw.interpolate);\n break;\n }\n case 'area': {\n const top = interpolatePoints(tw.fromTop, tw.toTop, eased);\n const bottom = interpolatePoints(tw.fromBottom, tw.toBottom, eased);\n applyAreaPaths(tw.el, top, bottom, tw.interpolate, tw.hasStroke);\n break;\n }\n case 'arc': {\n applyArcState(tw, eased);\n break;\n }\n case 'point': {\n const cx = tw.fromCx + (tw.toCx - tw.fromCx) * eased;\n const cy = tw.fromCy + (tw.toCy - tw.fromCy) * eased;\n tw.el.setAttribute('cx', String(cx));\n tw.el.setAttribute('cy', String(cy));\n if (tw.fromR !== undefined && tw.toR !== undefined) {\n const r = tw.fromR + (tw.toR - tw.fromR) * eased;\n tw.el.setAttribute('r', String(r));\n }\n break;\n }\n case 'rule':\n case 'tick': {\n const lineEl = resolveLineElement(tw.el);\n lineEl.setAttribute('x1', String(tw.fromX1 + (tw.toX1 - tw.fromX1) * eased));\n lineEl.setAttribute('y1', String(tw.fromY1 + (tw.toY1 - tw.fromY1) * eased));\n lineEl.setAttribute('x2', String(tw.fromX2 + (tw.toX2 - tw.fromX2) * eased));\n lineEl.setAttribute('y2', String(tw.fromY2 + (tw.toY2 - tw.fromY2) * eased));\n break;\n }\n case 'textMark': {\n const x = tw.fromX + (tw.toX - tw.fromX) * eased;\n const y = tw.fromY + (tw.toY - tw.fromY) * eased;\n tw.el.setAttribute('x', String(x));\n tw.el.setAttribute('y', String(y));\n break;\n }\n case 'axisTick': {\n if (tw.crossfade) {\n // Crossfade: only tween opacity, don't move\n break;\n }\n const pos = tw.fromPos + (tw.toPos - tw.fromPos) * eased;\n if (tw.posAttr === 'x') {\n tw.el.setAttribute('x', String(pos));\n } else {\n tw.el.setAttribute('y', String(pos));\n }\n break;\n }\n case 'gridline': {\n const pos = tw.fromPos + (tw.toPos - tw.fromPos) * eased;\n if (tw.orientation === 'y') {\n // Horizontal gridline: y1 and y2 share the same position\n tw.el.setAttribute('y1', String(pos));\n tw.el.setAttribute('y2', String(pos));\n } else {\n // Vertical gridline: x1 and x2 share the same position\n tw.el.setAttribute('x1', String(pos));\n tw.el.setAttribute('x2', String(pos));\n }\n break;\n }\n case 'color': {\n tw.el.setAttribute(tw.attr, interpolateRgb(tw.from, tw.to)(eased));\n break;\n }\n case 'annotation': {\n // Ease the offset back to zero: the group is already rendered at its\n // final position, so (0,0) is the destination. SVG transform attribute,\n // not CSS -- CSS transform would replace any SVG transform attribute\n // (see .claude/rules/svg-animation.md), and this composes cleanly since\n // the annotations renderer sets none.\n const dx = tw.fromDx * (1 - eased);\n const dy = tw.fromDy * (1 - eased);\n if (dx !== 0 || dy !== 0) {\n tw.el.setAttribute('transform', `translate(${dx} ${dy})`);\n }\n break;\n }\n }\n\n // Apply opacity interpolation if defined\n if (tw.fromOpacity !== undefined && tw.toOpacity !== undefined) {\n const opacity = tw.fromOpacity + (tw.toOpacity - tw.fromOpacity) * eased;\n tw.el.style.opacity = String(opacity);\n }\n}\n\nexport function snapTweenToFinal(tw: Tween): void {\n // No element; the shared opacity/suppressed-point steps below would throw.\n if (tw.tweenType === 'canvasPoints') {\n snapCanvasPointsToFinal(tw);\n return;\n }\n if (tw.tweenType === 'canvasGridlines') {\n snapCanvasGridlinesToFinal(tw);\n return;\n }\n\n switch (tw.tweenType) {\n case 'rect':\n applyGeomToElement(tw.el, tw.to, tw.mark);\n break;\n case 'line':\n applyLinePath(tw.el, tw.toPts, tw.interpolate);\n break;\n case 'area':\n applyAreaPaths(tw.el, tw.toTop, tw.toBottom, tw.interpolate, tw.hasStroke);\n break;\n case 'arc': {\n // Snap to the engine's exact rendered path (not a rebuilt one) so the\n // DOM round-trips to what render() produced. Ghosts are removed anyway.\n const pathEl = tw.el.tagName === 'path' ? tw.el : tw.el.querySelector('path');\n pathEl?.setAttribute('d', tw.mark.path);\n tw.el.setAttribute('transform', `translate(${tw.toCenter.x},${tw.toCenter.y})`);\n break;\n }\n case 'point':\n tw.el.setAttribute('cx', String(tw.toCx));\n tw.el.setAttribute('cy', String(tw.toCy));\n if (tw.toR !== undefined) {\n tw.el.setAttribute('r', String(tw.toR));\n }\n break;\n case 'rule':\n case 'tick': {\n const lineEl = resolveLineElement(tw.el);\n lineEl.setAttribute('x1', String(tw.toX1));\n lineEl.setAttribute('y1', String(tw.toY1));\n lineEl.setAttribute('x2', String(tw.toX2));\n lineEl.setAttribute('y2', String(tw.toY2));\n break;\n }\n case 'textMark':\n tw.el.setAttribute('x', String(tw.toX));\n tw.el.setAttribute('y', String(tw.toY));\n break;\n case 'axisTick':\n if (!tw.crossfade) {\n if (tw.posAttr === 'x') {\n tw.el.setAttribute('x', String(tw.toPos));\n } else {\n tw.el.setAttribute('y', String(tw.toPos));\n }\n }\n break;\n case 'gridline':\n if (tw.orientation === 'y') {\n tw.el.setAttribute('y1', String(tw.toPos));\n tw.el.setAttribute('y2', String(tw.toPos));\n } else {\n tw.el.setAttribute('x1', String(tw.toPos));\n tw.el.setAttribute('x2', String(tw.toPos));\n }\n break;\n case 'color':\n tw.el.setAttribute(tw.attr, tw.to);\n break;\n case 'annotation':\n // The group is rendered at its final position; drop the offset entirely\n // rather than writing translate(0 0), so the DOM returns to the exact\n // shape render() produced.\n tw.el.removeAttribute('transform');\n break;\n }\n\n if (tw.toOpacity !== undefined) {\n tw.el.style.opacity = String(tw.toOpacity);\n }\n\n // Restore suppressed-point opacity\n if (tw.tweenType === 'point' && tw.suppressedOpacity !== undefined) {\n tw.el.setAttribute('opacity', tw.suppressedOpacity);\n }\n}\n","export default function(constructor, factory, prototype) {\n constructor.prototype = factory.prototype = prototype;\n prototype.constructor = constructor;\n}\n\nexport function extend(parent, definition) {\n var prototype = Object.create(parent.prototype);\n for (var key in definition) prototype[key] = definition[key];\n return prototype;\n}\n","import define, {extend} from \"./define.js\";\n\nexport function Color() {}\n\nexport var darker = 0.7;\nexport var brighter = 1 / darker;\n\nvar reI = \"\\\\s*([+-]?\\\\d+)\\\\s*\",\n reN = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\",\n reP = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\",\n reHex = /^#([0-9a-f]{3,8})$/,\n reRgbInteger = new RegExp(`^rgb\\\\(${reI},${reI},${reI}\\\\)$`),\n reRgbPercent = new RegExp(`^rgb\\\\(${reP},${reP},${reP}\\\\)$`),\n reRgbaInteger = new RegExp(`^rgba\\\\(${reI},${reI},${reI},${reN}\\\\)$`),\n reRgbaPercent = new RegExp(`^rgba\\\\(${reP},${reP},${reP},${reN}\\\\)$`),\n reHslPercent = new RegExp(`^hsl\\\\(${reN},${reP},${reP}\\\\)$`),\n reHslaPercent = new RegExp(`^hsla\\\\(${reN},${reP},${reP},${reN}\\\\)$`);\n\nvar named = {\n aliceblue: 0xf0f8ff,\n antiquewhite: 0xfaebd7,\n aqua: 0x00ffff,\n aquamarine: 0x7fffd4,\n azure: 0xf0ffff,\n beige: 0xf5f5dc,\n bisque: 0xffe4c4,\n black: 0x000000,\n blanchedalmond: 0xffebcd,\n blue: 0x0000ff,\n blueviolet: 0x8a2be2,\n brown: 0xa52a2a,\n burlywood: 0xdeb887,\n cadetblue: 0x5f9ea0,\n chartreuse: 0x7fff00,\n chocolate: 0xd2691e,\n coral: 0xff7f50,\n cornflowerblue: 0x6495ed,\n cornsilk: 0xfff8dc,\n crimson: 0xdc143c,\n cyan: 0x00ffff,\n darkblue: 0x00008b,\n darkcyan: 0x008b8b,\n darkgoldenrod: 0xb8860b,\n darkgray: 0xa9a9a9,\n darkgreen: 0x006400,\n darkgrey: 0xa9a9a9,\n darkkhaki: 0xbdb76b,\n darkmagenta: 0x8b008b,\n darkolivegreen: 0x556b2f,\n darkorange: 0xff8c00,\n darkorchid: 0x9932cc,\n darkred: 0x8b0000,\n darksalmon: 0xe9967a,\n darkseagreen: 0x8fbc8f,\n darkslateblue: 0x483d8b,\n darkslategray: 0x2f4f4f,\n darkslategrey: 0x2f4f4f,\n darkturquoise: 0x00ced1,\n darkviolet: 0x9400d3,\n deeppink: 0xff1493,\n deepskyblue: 0x00bfff,\n dimgray: 0x696969,\n dimgrey: 0x696969,\n dodgerblue: 0x1e90ff,\n firebrick: 0xb22222,\n floralwhite: 0xfffaf0,\n forestgreen: 0x228b22,\n fuchsia: 0xff00ff,\n gainsboro: 0xdcdcdc,\n ghostwhite: 0xf8f8ff,\n gold: 0xffd700,\n goldenrod: 0xdaa520,\n gray: 0x808080,\n green: 0x008000,\n greenyellow: 0xadff2f,\n grey: 0x808080,\n honeydew: 0xf0fff0,\n hotpink: 0xff69b4,\n indianred: 0xcd5c5c,\n indigo: 0x4b0082,\n ivory: 0xfffff0,\n khaki: 0xf0e68c,\n lavender: 0xe6e6fa,\n lavenderblush: 0xfff0f5,\n lawngreen: 0x7cfc00,\n lemonchiffon: 0xfffacd,\n lightblue: 0xadd8e6,\n lightcoral: 0xf08080,\n lightcyan: 0xe0ffff,\n lightgoldenrodyellow: 0xfafad2,\n lightgray: 0xd3d3d3,\n lightgreen: 0x90ee90,\n lightgrey: 0xd3d3d3,\n lightpink: 0xffb6c1,\n lightsalmon: 0xffa07a,\n lightseagreen: 0x20b2aa,\n lightskyblue: 0x87cefa,\n lightslategray: 0x778899,\n lightslategrey: 0x778899,\n lightsteelblue: 0xb0c4de,\n lightyellow: 0xffffe0,\n lime: 0x00ff00,\n limegreen: 0x32cd32,\n linen: 0xfaf0e6,\n magenta: 0xff00ff,\n maroon: 0x800000,\n mediumaquamarine: 0x66cdaa,\n mediumblue: 0x0000cd,\n mediumorchid: 0xba55d3,\n mediumpurple: 0x9370db,\n mediumseagreen: 0x3cb371,\n mediumslateblue: 0x7b68ee,\n mediumspringgreen: 0x00fa9a,\n mediumturquoise: 0x48d1cc,\n mediumvioletred: 0xc71585,\n midnightblue: 0x191970,\n mintcream: 0xf5fffa,\n mistyrose: 0xffe4e1,\n moccasin: 0xffe4b5,\n navajowhite: 0xffdead,\n navy: 0x000080,\n oldlace: 0xfdf5e6,\n olive: 0x808000,\n olivedrab: 0x6b8e23,\n orange: 0xffa500,\n orangered: 0xff4500,\n orchid: 0xda70d6,\n palegoldenrod: 0xeee8aa,\n palegreen: 0x98fb98,\n paleturquoise: 0xafeeee,\n palevioletred: 0xdb7093,\n papayawhip: 0xffefd5,\n peachpuff: 0xffdab9,\n peru: 0xcd853f,\n pink: 0xffc0cb,\n plum: 0xdda0dd,\n powderblue: 0xb0e0e6,\n purple: 0x800080,\n rebeccapurple: 0x663399,\n red: 0xff0000,\n rosybrown: 0xbc8f8f,\n royalblue: 0x4169e1,\n saddlebrown: 0x8b4513,\n salmon: 0xfa8072,\n sandybrown: 0xf4a460,\n seagreen: 0x2e8b57,\n seashell: 0xfff5ee,\n sienna: 0xa0522d,\n silver: 0xc0c0c0,\n skyblue: 0x87ceeb,\n slateblue: 0x6a5acd,\n slategray: 0x708090,\n slategrey: 0x708090,\n snow: 0xfffafa,\n springgreen: 0x00ff7f,\n steelblue: 0x4682b4,\n tan: 0xd2b48c,\n teal: 0x008080,\n thistle: 0xd8bfd8,\n tomato: 0xff6347,\n turquoise: 0x40e0d0,\n violet: 0xee82ee,\n wheat: 0xf5deb3,\n white: 0xffffff,\n whitesmoke: 0xf5f5f5,\n yellow: 0xffff00,\n yellowgreen: 0x9acd32\n};\n\ndefine(Color, color, {\n copy(channels) {\n return Object.assign(new this.constructor, this, channels);\n },\n displayable() {\n return this.rgb().displayable();\n },\n hex: color_formatHex, // Deprecated! Use color.formatHex.\n formatHex: color_formatHex,\n formatHex8: color_formatHex8,\n formatHsl: color_formatHsl,\n formatRgb: color_formatRgb,\n toString: color_formatRgb\n});\n\nfunction color_formatHex() {\n return this.rgb().formatHex();\n}\n\nfunction color_formatHex8() {\n return this.rgb().formatHex8();\n}\n\nfunction color_formatHsl() {\n return hslConvert(this).formatHsl();\n}\n\nfunction color_formatRgb() {\n return this.rgb().formatRgb();\n}\n\nexport default function color(format) {\n var m, l;\n format = (format + \"\").trim().toLowerCase();\n return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000\n : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00\n : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000\n : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000\n : null) // invalid hex\n : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)\n : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)\n : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)\n : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)\n : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)\n : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)\n : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins\n : format === \"transparent\" ? new Rgb(NaN, NaN, NaN, 0)\n : null;\n}\n\nfunction rgbn(n) {\n return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);\n}\n\nfunction rgba(r, g, b, a) {\n if (a <= 0) r = g = b = NaN;\n return new Rgb(r, g, b, a);\n}\n\nexport function rgbConvert(o) {\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Rgb;\n o = o.rgb();\n return new Rgb(o.r, o.g, o.b, o.opacity);\n}\n\nexport function rgb(r, g, b, opacity) {\n return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);\n}\n\nexport function Rgb(r, g, b, opacity) {\n this.r = +r;\n this.g = +g;\n this.b = +b;\n this.opacity = +opacity;\n}\n\ndefine(Rgb, rgb, extend(Color, {\n brighter(k) {\n k = k == null ? brighter : Math.pow(brighter, k);\n return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);\n },\n darker(k) {\n k = k == null ? darker : Math.pow(darker, k);\n return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);\n },\n rgb() {\n return this;\n },\n clamp() {\n return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity));\n },\n displayable() {\n return (-0.5 <= this.r && this.r < 255.5)\n && (-0.5 <= this.g && this.g < 255.5)\n && (-0.5 <= this.b && this.b < 255.5)\n && (0 <= this.opacity && this.opacity <= 1);\n },\n hex: rgb_formatHex, // Deprecated! Use color.formatHex.\n formatHex: rgb_formatHex,\n formatHex8: rgb_formatHex8,\n formatRgb: rgb_formatRgb,\n toString: rgb_formatRgb\n}));\n\nfunction rgb_formatHex() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`;\n}\n\nfunction rgb_formatHex8() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;\n}\n\nfunction rgb_formatRgb() {\n const a = clampa(this.opacity);\n return `${a === 1 ? \"rgb(\" : \"rgba(\"}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a === 1 ? \")\" : `, ${a})`}`;\n}\n\nfunction clampa(opacity) {\n return isNaN(opacity) ? 1 : Math.max(0, Math.min(1, opacity));\n}\n\nfunction clampi(value) {\n return Math.max(0, Math.min(255, Math.round(value) || 0));\n}\n\nfunction hex(value) {\n value = clampi(value);\n return (value < 16 ? \"0\" : \"\") + value.toString(16);\n}\n\nfunction hsla(h, s, l, a) {\n if (a <= 0) h = s = l = NaN;\n else if (l <= 0 || l >= 1) h = s = NaN;\n else if (s <= 0) h = NaN;\n return new Hsl(h, s, l, a);\n}\n\nexport function hslConvert(o) {\n if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Hsl;\n if (o instanceof Hsl) return o;\n o = o.rgb();\n var r = o.r / 255,\n g = o.g / 255,\n b = o.b / 255,\n min = Math.min(r, g, b),\n max = Math.max(r, g, b),\n h = NaN,\n s = max - min,\n l = (max + min) / 2;\n if (s) {\n if (r === max) h = (g - b) / s + (g < b) * 6;\n else if (g === max) h = (b - r) / s + 2;\n else h = (r - g) / s + 4;\n s /= l < 0.5 ? max + min : 2 - max - min;\n h *= 60;\n } else {\n s = l > 0 && l < 1 ? 0 : h;\n }\n return new Hsl(h, s, l, o.opacity);\n}\n\nexport function hsl(h, s, l, opacity) {\n return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);\n}\n\nfunction Hsl(h, s, l, opacity) {\n this.h = +h;\n this.s = +s;\n this.l = +l;\n this.opacity = +opacity;\n}\n\ndefine(Hsl, hsl, extend(Color, {\n brighter(k) {\n k = k == null ? brighter : Math.pow(brighter, k);\n return new Hsl(this.h, this.s, this.l * k, this.opacity);\n },\n darker(k) {\n k = k == null ? darker : Math.pow(darker, k);\n return new Hsl(this.h, this.s, this.l * k, this.opacity);\n },\n rgb() {\n var h = this.h % 360 + (this.h < 0) * 360,\n s = isNaN(h) || isNaN(this.s) ? 0 : this.s,\n l = this.l,\n m2 = l + (l < 0.5 ? l : 1 - l) * s,\n m1 = 2 * l - m2;\n return new Rgb(\n hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),\n hsl2rgb(h, m1, m2),\n hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),\n this.opacity\n );\n },\n clamp() {\n return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity));\n },\n displayable() {\n return (0 <= this.s && this.s <= 1 || isNaN(this.s))\n && (0 <= this.l && this.l <= 1)\n && (0 <= this.opacity && this.opacity <= 1);\n },\n formatHsl() {\n const a = clampa(this.opacity);\n return `${a === 1 ? \"hsl(\" : \"hsla(\"}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a === 1 ? \")\" : `, ${a})`}`;\n }\n}));\n\nfunction clamph(value) {\n value = (value || 0) % 360;\n return value < 0 ? value + 360 : value;\n}\n\nfunction clampt(value) {\n return Math.max(0, Math.min(1, value || 0));\n}\n\n/* From FvD 13.37, CSS Color Module Level 3 */\nfunction hsl2rgb(h, m1, m2) {\n return (h < 60 ? m1 + (m2 - m1) * h / 60\n : h < 180 ? m2\n : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60\n : m1) * 255;\n}\n","export function basis(t1, v0, v1, v2, v3) {\n var t2 = t1 * t1, t3 = t2 * t1;\n return ((1 - 3 * t1 + 3 * t2 - t3) * v0\n + (4 - 6 * t2 + 3 * t3) * v1\n + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2\n + t3 * v3) / 6;\n}\n\nexport default function(values) {\n var n = values.length - 1;\n return function(t) {\n var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),\n v1 = values[i],\n v2 = values[i + 1],\n v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,\n v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n","import {basis} from \"./basis.js\";\n\nexport default function(values) {\n var n = values.length;\n return function(t) {\n var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),\n v0 = values[(i + n - 1) % n],\n v1 = values[i % n],\n v2 = values[(i + 1) % n],\n v3 = values[(i + 2) % n];\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n","export default x => () => x;\n","import constant from \"./constant.js\";\n\nfunction linear(a, d) {\n return function(t) {\n return a + t * d;\n };\n}\n\nfunction exponential(a, b, y) {\n return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {\n return Math.pow(a + t * b, y);\n };\n}\n\nexport function hue(a, b) {\n var d = b - a;\n return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a);\n}\n\nexport function gamma(y) {\n return (y = +y) === 1 ? nogamma : function(a, b) {\n return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a);\n };\n}\n\nexport default function nogamma(a, b) {\n var d = b - a;\n return d ? linear(a, d) : constant(isNaN(a) ? b : a);\n}\n","import {rgb as colorRgb} from \"d3-color\";\nimport basis from \"./basis.js\";\nimport basisClosed from \"./basisClosed.js\";\nimport nogamma, {gamma} from \"./color.js\";\n\nexport default (function rgbGamma(y) {\n var color = gamma(y);\n\n function rgb(start, end) {\n var r = color((start = colorRgb(start)).r, (end = colorRgb(end)).r),\n g = color(start.g, end.g),\n b = color(start.b, end.b),\n opacity = nogamma(start.opacity, end.opacity);\n return function(t) {\n start.r = r(t);\n start.g = g(t);\n start.b = b(t);\n start.opacity = opacity(t);\n return start + \"\";\n };\n }\n\n rgb.gamma = rgbGamma;\n\n return rgb;\n})(1);\n\nfunction rgbSpline(spline) {\n return function(colors) {\n var n = colors.length,\n r = new Array(n),\n g = new Array(n),\n b = new Array(n),\n i, color;\n for (i = 0; i < n; ++i) {\n color = colorRgb(colors[i]);\n r[i] = color.r || 0;\n g[i] = color.g || 0;\n b[i] = color.b || 0;\n }\n r = spline(r);\n g = spline(g);\n b = spline(b);\n color.opacity = 1;\n return function(t) {\n color.r = r(t);\n color.g = g(t);\n color.b = b(t);\n return color + \"\";\n };\n };\n}\n\nexport var rgbBasis = rgbSpline(basis);\nexport var rgbBasisClosed = rgbSpline(basisClosed);\n","var epsilon2 = 1e-12;\n\nfunction cosh(x) {\n return ((x = Math.exp(x)) + 1 / x) / 2;\n}\n\nfunction sinh(x) {\n return ((x = Math.exp(x)) - 1 / x) / 2;\n}\n\nfunction tanh(x) {\n return ((x = Math.exp(2 * x)) - 1) / (x + 1);\n}\n\nexport default (function zoomRho(rho, rho2, rho4) {\n\n // p0 = [ux0, uy0, w0]\n // p1 = [ux1, uy1, w1]\n function zoom(p0, p1) {\n var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],\n ux1 = p1[0], uy1 = p1[1], w1 = p1[2],\n dx = ux1 - ux0,\n dy = uy1 - uy0,\n d2 = dx * dx + dy * dy,\n i,\n S;\n\n // Special case for u0 ≅ u1.\n if (d2 < epsilon2) {\n S = Math.log(w1 / w0) / rho;\n i = function(t) {\n return [\n ux0 + t * dx,\n uy0 + t * dy,\n w0 * Math.exp(rho * t * S)\n ];\n }\n }\n\n // General case.\n else {\n var d1 = Math.sqrt(d2),\n b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),\n b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),\n r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),\n r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);\n S = (r1 - r0) / rho;\n i = function(t) {\n var s = t * S,\n coshr0 = cosh(r0),\n u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));\n return [\n ux0 + u * dx,\n uy0 + u * dy,\n w0 * coshr0 / cosh(rho * s + r0)\n ];\n }\n }\n\n i.duration = S * 1000 * rho / Math.SQRT2;\n\n return i;\n }\n\n zoom.rho = function(_) {\n var _1 = Math.max(1e-3, +_), _2 = _1 * _1, _4 = _2 * _2;\n return zoomRho(_1, _2, _4);\n };\n\n return zoom;\n})(Math.SQRT2, 2, 4);\n","import type { AxisLayout, ChartLayout, PointMark } from '@opendata-ai/openchart-core';\nimport { serializeKeyValue } from '@opendata-ai/openchart-engine';\nimport { cubicOut } from '../motion/easing';\nimport { flattenFill } from '../scatter-canvas/state';\n\nimport { computeGridlineDeltas } from './chrome-tweens';\nimport type {\n CanvasGridlinesTween,\n CanvasLayerLike,\n CanvasPointsTween,\n GeometrySnapshot,\n Tween,\n} from './types';\n\n// ---------------------------------------------------------------------------\n// Canvas point tween building\n// ---------------------------------------------------------------------------\n\n/**\n * Canvas counterpart of `buildPointTweens`: the same keyed diff, minus the DOM.\n *\n * Where the SVG builder does a `querySelector` per key and emits one tween per\n * mark, this resolves keys against the layer's SoA (already built from the NEXT\n * layout by `render()`) and emits exactly one packed tween.\n */\nexport function buildCanvasPointsTween(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n layer: CanvasLayerLike,\n tweens: Tween[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevPoints = prevLayout.marks.filter((m): m is PointMark => m.type === 'point');\n const nextPoints = nextLayout.marks.filter((m): m is PointMark => m.type === 'point');\n\n const prevByKey = new Map<string, PointMark>();\n for (const m of prevPoints) {\n if (m.key) prevByKey.set(m.key, m);\n }\n\n // The layer's SoA is the authority on where a point lives on the canvas.\n // `nextPoints` is only used to confirm the layer and the layout agree.\n const soa = layer.state.marks;\n const survivors: number[] = [];\n const enters: number[] = [];\n for (let i = 0; i < soa.n; i++) {\n const key = soa.keys[i];\n if (key !== undefined && prevByKey.has(key)) survivors.push(i);\n else enters.push(i);\n }\n\n const exits: PointMark[] = [];\n const nextKeys = new Set<string>();\n for (const m of nextPoints) {\n if (m.key) nextKeys.add(m.key);\n }\n for (const [key, prev] of prevByKey) {\n if (!nextKeys.has(key)) exits.push(prev);\n }\n\n const sn = survivors.length;\n const soaIndex = new Uint32Array(sn);\n const fromCx = new Float32Array(sn);\n const fromCy = new Float32Array(sn);\n const fromR = new Float32Array(sn);\n const toCx = new Float32Array(sn);\n const toCy = new Float32Array(sn);\n const toR = new Float32Array(sn);\n const soaKeys: string[] = new Array(sn);\n\n for (let s = 0; s < sn; s++) {\n const i = survivors[s];\n // `survivors` holds exactly the indices whose key is present in prevByKey,\n // so both lookups are total.\n const key = soa.keys[i] as string;\n const prev = prevByKey.get(key) as PointMark;\n\n // Retarget from an interrupted transition's frozen geometry when present.\n // The snapshot is mode-agnostic (`{type:'point'}`), so a canvas transition\n // interrupted by an SVG-mode update retargets correctly and vice versa.\n let px = prev.cx;\n let py = prev.cy;\n let pr = prev.r;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'point') {\n px = snap.cx;\n py = snap.cy;\n if (snap.r !== undefined) pr = snap.r;\n }\n\n soaIndex[s] = i;\n soaKeys[s] = key;\n fromCx[s] = px;\n fromCy[s] = py;\n fromR[s] = pr;\n // The SoA already holds the destination geometry -- render() built it from\n // nextLayout before the transition started.\n toCx[s] = soa.x[i];\n toCy[s] = soa.y[i];\n toR[s] = soa.r[i];\n }\n\n const enterSoaIndex = Uint32Array.from(enters);\n if (enters.length > 0) {\n // Entering points fade via `enterAlpha`, the whole-mark channel the\n // entrance animation uses, NOT `fillOpacity`: on canvas as in SVG,\n // fill-opacity must not drag the stroke down with it. Seed the array at\n // full alpha so every surviving point stays opaque; the tween only ever\n // writes the entering indices.\n const alpha = new Float32Array(soa.n).fill(1);\n for (const i of enters) alpha[i] = 0;\n layer.state.enterAlpha = alpha;\n }\n\n const exitCx = new Float32Array(exits.length);\n const exitCy = new Float32Array(exits.length);\n const exitR = new Float32Array(exits.length);\n const exitFill: string[] = new Array(exits.length);\n for (let x = 0; x < exits.length; x++) {\n const m = exits[x];\n exitCx[x] = m.cx;\n exitCy[x] = m.cy;\n exitR[x] = m.r;\n exitFill[x] = flattenFill(m.fill);\n }\n // alpha: 1 matches the synchronous t=0 applyTweenState pass.\n const exitState =\n exits.length > 0 ? { x: exitCx, y: exitCy, r: exitR, fill: exitFill, alpha: 1 } : null;\n\n tweens.push({\n tweenType: 'canvasPoints',\n kind: 'update',\n layer,\n soaIndex,\n fromCx,\n fromCy,\n fromR,\n toCx,\n toCy,\n toR,\n soaKeys,\n enterSoaIndex,\n exitState,\n });\n}\n\n/**\n * Write one frame of a canvas point tween into the layer's SoA.\n *\n * Enters and exits run on their own clocks here rather than through the shared\n * `kind` prologue, because a single record carries all three phases.\n */\nexport function applyCanvasPointsState(\n tw: CanvasPointsTween,\n elapsed: number,\n update: { duration: number },\n exit: { duration: number },\n enterDelay: number,\n enterDuration: number,\n): void {\n const soa = tw.layer.state.marks;\n const easedUpdate = cubicOut(Math.min(elapsed / update.duration, 1));\n\n for (let s = 0; s < tw.soaIndex.length; s++) {\n const i = tw.soaIndex[s];\n soa.x[i] = tw.fromCx[s] + (tw.toCx[s] - tw.fromCx[s]) * easedUpdate;\n soa.y[i] = tw.fromCy[s] + (tw.toCy[s] - tw.fromCy[s]) * easedUpdate;\n soa.r[i] = tw.fromR[s] + (tw.toR[s] - tw.fromR[s]) * easedUpdate;\n }\n\n // Enters fade in, delayed 40% of the update duration -- same phase math the\n // SVG point path uses, so both modes read as one motion.\n const alpha = tw.layer.state.enterAlpha;\n if (alpha && tw.enterSoaIndex.length > 0) {\n const tEnter = elapsed < enterDelay ? 0 : Math.min((elapsed - enterDelay) / enterDuration, 1);\n const easedEnter = cubicOut(tEnter);\n for (let e = 0; e < tw.enterSoaIndex.length; e++) {\n alpha[tw.enterSoaIndex[e]] = easedEnter;\n }\n }\n\n // Exit ghosts hold their prev position and fade out on the exit clock.\n // The record is preallocated; only alpha changes frame to frame.\n if (tw.exitState) {\n const easedExit = cubicOut(Math.min(elapsed / exit.duration, 1));\n tw.exitState.alpha = 1 - easedExit;\n tw.layer.state.exiting = tw.exitState;\n }\n}\n\n/**\n * The axes that contribute canvas gridlines, in the order `buildScatterCanvasState`\n * walks them. `layer.state.gridlines` is a flat array, so the tween can only index\n * into it by replaying that exact traversal -- keep the two in lockstep.\n */\nexport function canvasGridlineAxes(\n layout: ChartLayout,\n): { axis: AxisLayout | undefined; orient: 'x' | 'y' }[] {\n return [\n { axis: layout.axes.y, orient: 'y' as const },\n { axis: layout.axes.y2, orient: 'y' as const },\n { axis: layout.axes.x, orient: 'x' as const },\n ];\n}\n\n/** True when this axis renders gridlines at all (mirrors `collectGridlines`). */\nexport function axisEmitsGridlines(\n axis: AxisLayout | undefined,\n orient: 'x' | 'y',\n): axis is AxisLayout {\n if (!axis) return false;\n return !(orient === 'y' && axis.orient === 'right');\n}\n\n/**\n * Build the canvas gridline tween.\n *\n * The layer's `gridlines` array is already at the NEXT layout's positions, so\n * this only has to compute where each one came FROM. Survivors rewind to their\n * prev position at full alpha; new gridlines hold position and fade in on the\n * enter clock. Exits are dropped rather than ghosted: the next layout's array\n * has no slot for them, and a gridline fading out under 4k points is not worth\n * a parallel ghost array.\n */\nexport function buildCanvasGridlinesTween(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n layer: CanvasLayerLike,\n tweens: Tween[],\n): void {\n const live = layer.state.gridlines;\n const index: number[] = [];\n const fromPos: number[] = [];\n const toPos: number[] = [];\n const fromAlpha: number[] = [];\n const toAlpha: number[] = [];\n\n const prevAxes = canvasGridlineAxes(prevLayout);\n const nextAxes = canvasGridlineAxes(nextLayout);\n\n let cursor = 0;\n for (let a = 0; a < nextAxes.length; a++) {\n const nextAxis = nextAxes[a].axis;\n const orient = nextAxes[a].orient;\n if (!axisEmitsGridlines(nextAxis, orient)) continue;\n\n const prevAxis = prevAxes[a].axis;\n const deltas = axisEmitsGridlines(prevAxis, orient)\n ? computeGridlineDeltas(prevAxis, nextAxis)\n : null;\n\n // Position -> tick value for THIS axis, so each flat-array slot can be\n // resolved back to the key the deltas are keyed by.\n const valueAtPosition = new Map<number, string>();\n for (const tick of nextAxis.ticks) {\n valueAtPosition.set(tick.position, serializeKeyValue(tick.value));\n }\n\n for (const gridline of nextAxis.gridlines) {\n const slot = cursor++;\n // Defensive: the layer was built from this same layout, so the arrays\n // must be the same length. Bail rather than write past the end.\n if (slot >= live.length) break;\n\n const key = valueAtPosition.get(gridline.position);\n const prevPos = key !== undefined ? deltas?.prevGridByValue.get(key) : undefined;\n\n index.push(slot);\n toPos.push(gridline.position);\n toAlpha.push(live[slot].alpha);\n if (prevPos !== undefined) {\n // Survivor: slide, no fade.\n fromPos.push(prevPos);\n fromAlpha.push(live[slot].alpha);\n } else {\n // Enter: hold position, fade in.\n fromPos.push(gridline.position);\n fromAlpha.push(0);\n }\n }\n }\n\n if (index.length === 0) return;\n\n tweens.push({\n tweenType: 'canvasGridlines',\n kind: 'update',\n layer,\n index: Uint32Array.from(index),\n fromPos: Float32Array.from(fromPos),\n toPos: Float32Array.from(toPos),\n fromAlpha: Float32Array.from(fromAlpha),\n toAlpha: Float32Array.from(toAlpha),\n });\n}\n\n/** Write one frame of a canvas gridline tween into the layer state. */\nexport function applyCanvasGridlinesState(\n tw: CanvasGridlinesTween,\n elapsed: number,\n update: { duration: number },\n enterDelay: number,\n enterDuration: number,\n): void {\n const live = tw.layer.state.gridlines;\n const easedUpdate = cubicOut(Math.min(elapsed / update.duration, 1));\n // Enters share the point tween's delayed-fade clock so the whole update\n // reads as one motion.\n const tEnter = elapsed < enterDelay ? 0 : Math.min((elapsed - enterDelay) / enterDuration, 1);\n const easedEnter = cubicOut(tEnter);\n\n for (let i = 0; i < tw.index.length; i++) {\n const g = live[tw.index[i]];\n g.position = tw.fromPos[i] + (tw.toPos[i] - tw.fromPos[i]) * easedUpdate;\n const from = tw.fromAlpha[i];\n const to = tw.toAlpha[i];\n g.alpha = from === to ? to : from + (to - from) * easedEnter;\n }\n}\n\n/** Snap a canvas gridline tween to its exact destination. */\nexport function snapCanvasGridlinesToFinal(tw: CanvasGridlinesTween): void {\n const live = tw.layer.state.gridlines;\n for (let i = 0; i < tw.index.length; i++) {\n const g = live[tw.index[i]];\n g.position = tw.toPos[i];\n g.alpha = tw.toAlpha[i];\n }\n}\n\n/** Snap a canvas point tween to its exact destination and drop the ghosts. */\nexport function snapCanvasPointsToFinal(tw: CanvasPointsTween): void {\n const soa = tw.layer.state.marks;\n for (let s = 0; s < tw.soaIndex.length; s++) {\n const i = tw.soaIndex[s];\n soa.x[i] = tw.toCx[s];\n soa.y[i] = tw.toCy[s];\n soa.r[i] = tw.toR[s];\n }\n tw.layer.state.exiting = null;\n // Null rather than fill(1): the renderer skips the alpha multiply entirely\n // when this is null, and every point is at full alpha once the fade lands.\n // Safe to clobber unconditionally -- gate 5 bars a transition while an\n // entrance is in flight, so nothing else owns this array.\n tw.layer.state.enterAlpha = null;\n}\n","import type { AxisLayout, ChartLayout } from '@opendata-ai/openchart-core';\nimport { serializeKeyValue } from '@opendata-ai/openchart-engine';\n\nimport type { MarkDomIndex } from './dom-index';\nimport { keyAnnotations } from './keys';\nimport type { Tween } from './types';\n\n// ---------------------------------------------------------------------------\n// Color tween building\n// ---------------------------------------------------------------------------\n\n/**\n * The child element a mark's `fill` or `stroke` is actually written to.\n *\n * Resolved per attribute, not once per mark: an area is two stacked paths, and\n * they do not carry the same channels. `renderAreaMark` appends the closed fill\n * shape first (`stroke: 'none'`) and the `.oc-area-top` line second -- that\n * second path is the only thing carrying the stroke, and it traces the data\n * points alone rather than the baseline. A blanket `querySelector` returns the\n * *first* match, so writing a stroke through it would paint an outline around\n * the whole closed area (baseline included) and `snapTweenToFinal` would leave\n * it there for good.\n */\nexport function markShapeElement(el: SVGElement, attr: 'fill' | 'stroke'): SVGElement {\n if (el.tagName === 'circle' || el.tagName === 'rect' || el.tagName === 'path') return el;\n if (attr === 'stroke') {\n const areaTop = el.querySelector('.oc-area-top') as SVGElement | null;\n if (areaTop) return areaTop;\n }\n return (el.querySelector('rect, path, circle, line') as SVGElement | null) ?? el;\n}\n\n/** Gradient fills are `url(#id)` refs and cannot be interpolated numerically. */\nexport function isInterpolableColor(v: unknown): v is string {\n return typeof v === 'string' && v !== '' && v !== 'none' && !v.startsWith('url(');\n}\n\n/**\n * Build fill/stroke tweens for marks present in both layouts whose color moved.\n *\n * Mark-type agnostic on purpose: every mark carries `fill`/`stroke` resolved by\n * the compiler, so matching on `key` and diffing the two strings covers rects,\n * lines, areas and points in one pass. Marks whose color did not change emit no\n * tween, so the common data-update case costs nothing.\n */\nexport function buildColorTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n dom: MarkDomIndex,\n tweens: Tween[],\n): void {\n type Colored = { key?: string; fill?: unknown; stroke?: unknown };\n const prevByKey = new Map<string, Colored>();\n for (const m of prevLayout.marks as Colored[]) {\n if (m.key) prevByKey.set(m.key, m);\n }\n\n for (const next of nextLayout.marks as Colored[]) {\n if (!next.key) continue;\n const prev = prevByKey.get(next.key);\n if (!prev) continue;\n\n const group = dom.any(next.key);\n if (!group) continue;\n\n for (const attr of ['fill', 'stroke'] as const) {\n const from = prev[attr];\n const to = next[attr];\n if (from === to) continue;\n if (!isInterpolableColor(from) || !isInterpolableColor(to)) continue;\n tweens.push({\n tweenType: 'color',\n kind: 'update',\n el: markShapeElement(group, attr),\n attr,\n from,\n to,\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Annotation tween building\n// ---------------------------------------------------------------------------\n\n/**\n * Build keyed enter/update/exit tweens for annotations.\n *\n * Follows the `buildAxisTweens` pattern rather than the mark builders': the\n * annotation group is a SIBLING of the clipped marks group, so it must be\n * queried from the `svg` root. A `marksContainer.querySelector` would never\n * find it.\n *\n * Surviving annotations tween from their old position to their new one via a\n * transform offset (the alternative -- re-resolving label x/y, connector path,\n * dot, subtitle and background rect individually -- is a lot of surface for no\n * extra fidelity). Entering ones fade in. See the note at the bottom for why\n * exiting ones do not fade out.\n */\nexport function buildAnnotationTweens(\n svg: SVGSVGElement,\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n tweens: Tween[],\n): void {\n const prev = prevLayout.annotations ?? [];\n const next = nextLayout.annotations ?? [];\n if (prev.length === 0 && next.length === 0) return;\n\n const container = svg.querySelector('.oc-annotations');\n if (!container) return;\n\n const prevByKey = new Map(keyAnnotations(prev).map((k, i) => [k, prev[i]]));\n const nextKeys = keyAnnotations(next);\n\n // The rendered DOM matches nextLayout, so index i is nextKeys[i].\n const els = container.querySelectorAll('.oc-annotation');\n\n for (let i = 0; i < next.length; i++) {\n const el = els[i] as SVGElement | undefined;\n if (!el) continue;\n const before = prevByKey.get(nextKeys[i]);\n\n if (!before) {\n // Entering: fade in on the annotation cadence.\n tweens.push({\n tweenType: 'annotation',\n kind: 'enter',\n el,\n fromDx: 0,\n fromDy: 0,\n fromOpacity: 0,\n toOpacity: 1,\n });\n continue;\n }\n\n // Surviving: hold at full opacity, slide from the old position if it moved.\n const dx = (before.label?.x ?? 0) - (next[i].label?.x ?? 0);\n const dy = (before.label?.y ?? 0) - (next[i].label?.y ?? 0);\n if (dx === 0 && dy === 0) continue;\n tweens.push({\n tweenType: 'annotation',\n kind: 'update',\n el,\n fromDx: dx,\n fromDy: dy,\n });\n }\n\n // Exiting annotations are NOT ghosted. render() has already torn down the old\n // SVG, so the removed node is gone and there is nothing left to clone -- the\n // elements still in the DOM belong to nextLayout, and cloning one by the old\n // index would ghost an annotation that actually survived. Building a faithful\n // ghost would mean re-rendering the annotation from prevLayout (the marks\n // path can do this via `renderSingleMark`; annotations have no such entry\n // point that takes a single ResolvedAnnotation).\n //\n // So a removed annotation disappears immediately. That matches the behavior\n // before this change and is not what the blink bug was about; adding a real\n // exit fade means exposing a single-annotation renderer first.\n}\n\n// ---------------------------------------------------------------------------\n// Axis tick and gridline tween building\n// ---------------------------------------------------------------------------\n\n/**\n * Build tweens for axis tick labels and gridlines across both x and y axes.\n * Matches ticks by `data-tick-key` (stamped at render time).\n */\nexport function buildAxisTweens(\n svg: SVGSVGElement,\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n tweens: Tween[],\n ghosts: SVGElement[],\n): void {\n // Process each axis orientation\n buildSingleAxisTweens(svg, prevLayout.axes.x, nextLayout.axes.x, 'x', nextLayout, tweens, ghosts);\n buildSingleAxisTweens(svg, prevLayout.axes.y, nextLayout.axes.y, 'y', nextLayout, tweens, ghosts);\n}\n\n/**\n * Match an axis's gridlines between two layouts, keyed by TICK VALUE.\n *\n * Gridlines carry no key of their own, so identity is borrowed from the tick\n * that shares their position -- a value-keyed match, which is why a rescale\n * that keeps no tick values (900 -> 20) reads as a full fade-out/fade-in rather\n * than a slide, and why one that keeps them all slides even when every position\n * moved.\n *\n * The `g.position === tick.position` join is an exact float compare, which is\n * only safe because both arrays come out of the same scale call in the same\n * layout pass. Anything that recomputes gridline positions independently --\n * even via an algebraically identical expression -- would silently match\n * nothing and degrade every gridline to a fade.\n *\n * Pure so the canvas path can consume the same deltas without a DOM.\n */\nexport function computeGridlineDeltas(\n prevAxis: AxisLayout,\n nextAxis: AxisLayout,\n): { prevGridByValue: Map<string, number>; nextGridByValue: Map<string, number> } {\n const byValue = (axis: AxisLayout): Map<string, number> => {\n const map = new Map<string, number>();\n for (const tick of axis.ticks) {\n const matching = axis.gridlines.find((g) => g.position === tick.position);\n if (matching) map.set(serializeKeyValue(tick.value), matching.position);\n }\n return map;\n };\n return { prevGridByValue: byValue(prevAxis), nextGridByValue: byValue(nextAxis) };\n}\n\nexport function buildSingleAxisTweens(\n svg: SVGSVGElement,\n prevAxis: AxisLayout | undefined,\n nextAxis: AxisLayout | undefined,\n orientation: 'x' | 'y',\n layout: ChartLayout,\n tweens: Tween[],\n ghosts: SVGElement[],\n): void {\n if (!prevAxis || !nextAxis) return;\n\n const axisClass = `oc-axis-${orientation}`;\n const axisGroup = svg.querySelector(`.${axisClass}`) as SVGElement | null;\n if (!axisGroup) return;\n\n const isRotated = !!(nextAxis.tickAngle && Math.abs(nextAxis.tickAngle) > 10);\n\n // Build tick value -> position maps from layouts (NOT from DOM). Labels\n // nudged inward off the container edge carry their own `labelPosition`;\n // tween to that or the label snaps back over the edge mid-transition.\n const prevTickMap = new Map<string, number>();\n for (const tick of prevAxis.ticks) {\n prevTickMap.set(serializeKeyValue(tick.value), tick.labelPosition ?? tick.position);\n }\n const nextTickMap = new Map<string, number>();\n for (const tick of nextAxis.ticks) {\n nextTickMap.set(serializeKeyValue(tick.value), tick.labelPosition ?? tick.position);\n }\n\n // Position attribute: 'x' for x-axis tick labels, 'y' for y-axis tick labels\n const posAttr = orientation === 'x' ? 'x' : 'y';\n\n // Tick labels\n const tickLabels = axisGroup.querySelectorAll('.oc-axis-tick[data-tick-key]');\n const matchedNextKeys = new Set<string>();\n\n for (const labelEl of tickLabels) {\n const key = labelEl.getAttribute('data-tick-key');\n if (!key) continue;\n\n const nextPos = nextTickMap.get(key);\n const prevPos = prevTickMap.get(key);\n\n if (prevPos !== undefined && nextPos !== undefined) {\n // Updated tick: slide to new position\n matchedNextKeys.add(key);\n tweens.push({\n tweenType: 'axisTick',\n kind: 'update',\n el: labelEl as SVGElement,\n posAttr,\n fromPos: prevPos,\n toPos: nextPos,\n crossfade: isRotated,\n });\n } else if (prevPos === undefined && nextPos !== undefined) {\n // Entering tick: fade in\n matchedNextKeys.add(key);\n tweens.push({\n tweenType: 'axisTick',\n kind: 'enter',\n el: labelEl as SVGElement,\n posAttr,\n fromPos: nextPos,\n toPos: nextPos,\n crossfade: false,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n // Exiting ticks are handled below (they won't be in the new SVG's DOM,\n // so we clone from the prev state)\n }\n\n // Exiting tick labels: create ghost elements\n for (const [key, prevPos] of prevTickMap) {\n if (nextTickMap.has(key)) continue;\n // Find the tick label in the rendered SVG by data-tick-key\n // It won't be there since the SVG was already re-rendered from nextLayout,\n // so we need to create a ghost text element\n const prevTick = prevAxis.ticks.find((t) => serializeKeyValue(t.value) === key);\n if (!prevTick) continue;\n\n const ghost = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n ghost.setAttribute('class', 'oc-axis-tick oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.textContent = prevTick.label;\n // Copy positioning from prevAxis ticks\n const area = layout.area;\n if (orientation === 'x') {\n ghost.setAttribute('x', String(prevPos));\n const xLabelPad = nextAxis.labelPadding ?? layout.theme.spacing.xAxisLabelPadding;\n const fontSize = nextAxis.tickLabelStyle.fontSize;\n ghost.setAttribute('y', String(area.y + area.height + xLabelPad + fontSize * 0.8));\n ghost.setAttribute('text-anchor', 'middle');\n } else {\n const TICK_LABEL_OFFSET = 8;\n ghost.setAttribute('x', String(area.x - TICK_LABEL_OFFSET));\n ghost.setAttribute('y', String(prevPos));\n ghost.setAttribute('text-anchor', 'end');\n ghost.setAttribute('dominant-baseline', 'central');\n }\n axisGroup.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'axisTick',\n kind: 'exit',\n el: ghost,\n posAttr,\n fromPos: prevPos,\n toPos: prevPos,\n crossfade: false,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n\n // Gridlines\n const { prevGridByValue, nextGridByValue } = computeGridlineDeltas(prevAxis, nextAxis);\n\n const gridlines = axisGroup.querySelectorAll('.oc-gridline[data-tick-key]');\n\n for (const glEl of gridlines) {\n const key = glEl.getAttribute('data-tick-key');\n if (!key) continue;\n\n const nextPos = nextGridByValue.get(key);\n const prevPos = prevGridByValue.get(key);\n\n if (prevPos !== undefined && nextPos !== undefined) {\n tweens.push({\n tweenType: 'gridline',\n kind: 'update',\n el: glEl as SVGElement,\n orientation,\n fromPos: prevPos,\n toPos: nextPos,\n });\n } else if (prevPos === undefined && nextPos !== undefined) {\n tweens.push({\n tweenType: 'gridline',\n kind: 'enter',\n el: glEl as SVGElement,\n orientation,\n fromPos: nextPos,\n toPos: nextPos,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n }\n\n // Exiting gridlines\n for (const [key, prevPos] of prevGridByValue) {\n if (nextGridByValue.has(key)) continue;\n\n const ghost = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n ghost.setAttribute('class', 'oc-gridline oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n if (orientation === 'y') {\n // Horizontal gridline at y=prevPos\n const area = layout.area;\n ghost.setAttribute('x1', String(area.x));\n ghost.setAttribute('y1', String(prevPos));\n ghost.setAttribute('x2', String(area.x + area.width));\n ghost.setAttribute('y2', String(prevPos));\n } else {\n // Vertical gridline at x=prevPos\n const area = layout.area;\n ghost.setAttribute('x1', String(prevPos));\n ghost.setAttribute('y1', String(area.y));\n ghost.setAttribute('x2', String(prevPos));\n ghost.setAttribute('y2', String(area.y + area.height));\n }\n axisGroup.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'gridline',\n kind: 'exit',\n el: ghost,\n orientation,\n fromPos: prevPos,\n toPos: prevPos,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n","import type { AreaMark, LineMark, Point, RectMark } from '@opendata-ai/openchart-core';\nimport { buildAreaPath, buildLinePath } from '@opendata-ai/openchart-engine';\nimport { rectPathWithCorners } from '../renderers/marks';\n\nimport type { RectGeom } from './types';\n\n// ---------------------------------------------------------------------------\n// Geometry helpers (rect)\n// ---------------------------------------------------------------------------\n\nexport function geomFromMark(m: RectMark): RectGeom {\n return { x: m.x, y: m.y, width: m.width, height: m.height };\n}\n\nexport function applyGeomToElement(el: SVGElement, geom: RectGeom, mark: RectMark): void {\n const shapeEl = el.querySelector('rect, path') as SVGElement | null;\n if (!shapeEl) return;\n\n const sides = mark.cornerRadiusSides;\n const partialCorners =\n !!sides && (!sides.tl || !sides.tr || !sides.br || !sides.bl) && !!mark.cornerRadius;\n\n if (partialCorners && shapeEl.tagName === 'path') {\n const tempMark = { ...mark, ...geom };\n shapeEl.setAttribute('d', rectPathWithCorners(tempMark, sides));\n } else {\n shapeEl.setAttribute('x', String(geom.x));\n shapeEl.setAttribute('y', String(geom.y));\n shapeEl.setAttribute('width', String(geom.width));\n shapeEl.setAttribute('height', String(geom.height));\n }\n}\n\nexport function lerpGeom(from: RectGeom, to: RectGeom, t: number): RectGeom {\n return {\n x: from.x + (to.x - from.x) * t,\n y: from.y + (to.y - from.y) * t,\n width: from.width + (to.width - from.width) * t,\n height: from.height + (to.height - from.height) * t,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Point interpolation helpers (line/area morphing)\n// ---------------------------------------------------------------------------\n\nexport function lerpPoint(a: Point, b: Point, t: number): Point {\n return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };\n}\n\n/**\n * Normalize two point arrays (prev and next) to equal length by matching\n * on pointKeys. Inserted/removed points get synthetic positions interpolated\n * from surviving neighbors.\n *\n * Returns [fromPts, toPts] of equal length.\n */\nexport function normalizePointArrays(\n prevPoints: Point[],\n nextPoints: Point[],\n prevKeys: string[],\n nextKeys: string[],\n): [Point[], Point[]] {\n // Build merged key sequence preserving order from both sides\n const nextKeySet = new Set(nextKeys);\n\n // Check for zero survivors (no keys in common)\n const survivors = prevKeys.filter((k) => nextKeySet.has(k));\n if (survivors.length === 0) {\n // Crossfade path: return arrays as-is (caller handles opacity crossfade)\n return [prevPoints, nextPoints];\n }\n\n // Build key-to-point maps\n const prevByKey = new Map<string, Point>();\n for (let i = 0; i < prevKeys.length; i++) {\n prevByKey.set(prevKeys[i], prevPoints[i]);\n }\n const nextByKey = new Map<string, Point>();\n for (let i = 0; i < nextKeys.length; i++) {\n nextByKey.set(nextKeys[i], nextPoints[i]);\n }\n\n // Merge keys in order: walk both arrays maintaining relative order\n const merged = mergeKeyOrder(prevKeys, nextKeys);\n\n // Precompute merged index map for O(1) lookups in insertion/removal helpers\n const mergedIndex = new Map<string, number>();\n for (let i = 0; i < merged.length; i++) {\n mergedIndex.set(merged[i], i);\n }\n\n const fromPts: Point[] = [];\n const toPts: Point[] = [];\n\n for (const key of merged) {\n const inPrev = prevByKey.has(key);\n const inNext = nextByKey.has(key);\n\n if (inPrev && inNext) {\n // Matched point: straightforward interpolation\n fromPts.push(prevByKey.get(key)!);\n toPts.push(nextByKey.get(key)!);\n } else if (inNext && !inPrev) {\n // Inserted point: \"to\" is nextPoint; \"from\" is interpolated on prev line\n const nextPt = nextByKey.get(key)!;\n toPts.push(nextPt);\n fromPts.push(findInsertionPosition(key, merged, mergedIndex, prevByKey, nextByKey, nextPt));\n } else if (inPrev && !inNext) {\n // Removed point: \"from\" is prevPoint; \"to\" is collapse position\n const prevPt = prevByKey.get(key)!;\n fromPts.push(prevPt);\n toPts.push(findRemovalPosition(key, merged, mergedIndex, prevByKey, nextByKey, prevPt));\n }\n }\n\n return [fromPts, toPts];\n}\n\n/**\n * Merge two key arrays preserving the relative order from both.\n * Keys present in both appear once at their first occurrence position.\n */\nexport function mergeKeyOrder(prevKeys: string[], nextKeys: string[]): string[] {\n // Precompute index maps for O(1) lookups instead of indexOf\n const nextIndex = new Map<string, number>();\n for (let i = 0; i < nextKeys.length; i++) {\n if (!nextIndex.has(nextKeys[i])) nextIndex.set(nextKeys[i], i);\n }\n const prevIndex = new Map<string, number>();\n for (let i = 0; i < prevKeys.length; i++) {\n if (!prevIndex.has(prevKeys[i])) prevIndex.set(prevKeys[i], i);\n }\n\n const result: string[] = [];\n const added = new Set<string>();\n let pi = 0;\n let ni = 0;\n\n while (pi < prevKeys.length && ni < nextKeys.length) {\n const pk = prevKeys[pi];\n const nk = nextKeys[ni];\n\n if (added.has(pk)) {\n pi++;\n continue;\n }\n if (added.has(nk)) {\n ni++;\n continue;\n }\n\n if (pk === nk) {\n result.push(pk);\n added.add(pk);\n pi++;\n ni++;\n } else {\n const pkInNext = nextIndex.has(pk) && nextIndex.get(pk)! >= ni ? nextIndex.get(pk)! : -1;\n const nkInPrev = prevIndex.has(nk) && prevIndex.get(nk)! >= pi ? prevIndex.get(nk)! : -1;\n\n if (pkInNext === -1 && nkInPrev === -1) {\n result.push(pk);\n added.add(pk);\n pi++;\n } else if (pkInNext === -1) {\n result.push(pk);\n added.add(pk);\n pi++;\n } else if (nkInPrev === -1) {\n result.push(nk);\n added.add(nk);\n ni++;\n } else {\n if (pkInNext <= nkInPrev) {\n result.push(pk);\n added.add(pk);\n pi++;\n } else {\n result.push(nk);\n added.add(nk);\n ni++;\n }\n }\n }\n }\n\n // Drain remaining\n while (pi < prevKeys.length) {\n if (!added.has(prevKeys[pi])) {\n result.push(prevKeys[pi]);\n added.add(prevKeys[pi]);\n }\n pi++;\n }\n while (ni < nextKeys.length) {\n if (!added.has(nextKeys[ni])) {\n result.push(nextKeys[ni]);\n added.add(nextKeys[ni]);\n }\n ni++;\n }\n\n return result;\n}\n\n/**\n * Find where an inserted point should start from on the previous line.\n * Interpolates between the nearest surviving neighbors' prev positions,\n * proportional to the new point's x between neighbors' next x positions.\n * If at head/tail, uses the nearest surviving endpoint's prev position.\n */\nexport function findInsertionPosition(\n key: string,\n merged: string[],\n mergedIndex: Map<string, number>,\n prevByKey: Map<string, Point>,\n nextByKey: Map<string, Point>,\n nextPt: Point,\n): Point {\n const idx = mergedIndex.get(key) ?? -1;\n\n // Find nearest surviving neighbor before\n let beforeKey: string | null = null;\n for (let i = idx - 1; i >= 0; i--) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n beforeKey = merged[i];\n break;\n }\n }\n\n // Find nearest surviving neighbor after\n let afterKey: string | null = null;\n for (let i = idx + 1; i < merged.length; i++) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n afterKey = merged[i];\n break;\n }\n }\n\n if (beforeKey && afterKey) {\n // Interpolate between neighbors\n const beforeNext = nextByKey.get(beforeKey)!;\n const afterNext = nextByKey.get(afterKey)!;\n const beforePrev = prevByKey.get(beforeKey)!;\n const afterPrev = prevByKey.get(afterKey)!;\n\n const range = afterNext.x - beforeNext.x;\n const t = range === 0 ? 0.5 : (nextPt.x - beforeNext.x) / range;\n return lerpPoint(beforePrev, afterPrev, Math.max(0, Math.min(1, t)));\n }\n\n if (beforeKey) {\n // At tail: unfold from nearest surviving endpoint\n return { ...prevByKey.get(beforeKey)! };\n }\n\n if (afterKey) {\n // At head: unfold from nearest surviving endpoint\n return { ...prevByKey.get(afterKey)! };\n }\n\n // No survivors (shouldn't happen since we check above, but safe fallback)\n return nextPt;\n}\n\n/**\n * Find where a removed point should collapse to on the next line.\n * Mirror of findInsertionPosition but for the destination side.\n */\nexport function findRemovalPosition(\n key: string,\n merged: string[],\n mergedIndex: Map<string, number>,\n prevByKey: Map<string, Point>,\n nextByKey: Map<string, Point>,\n prevPt: Point,\n): Point {\n const idx = mergedIndex.get(key) ?? -1;\n\n // Find nearest surviving neighbor before\n let beforeKey: string | null = null;\n for (let i = idx - 1; i >= 0; i--) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n beforeKey = merged[i];\n break;\n }\n }\n\n // Find nearest surviving neighbor after\n let afterKey: string | null = null;\n for (let i = idx + 1; i < merged.length; i++) {\n if (prevByKey.has(merged[i]) && nextByKey.has(merged[i])) {\n afterKey = merged[i];\n break;\n }\n }\n\n if (beforeKey && afterKey) {\n const beforePrev = prevByKey.get(beforeKey)!;\n const afterPrev = prevByKey.get(afterKey)!;\n const beforeNext = nextByKey.get(beforeKey)!;\n const afterNext = nextByKey.get(afterKey)!;\n\n const range = afterPrev.x - beforePrev.x;\n const t = range === 0 ? 0.5 : (prevPt.x - beforePrev.x) / range;\n return lerpPoint(beforeNext, afterNext, Math.max(0, Math.min(1, t)));\n }\n\n if (beforeKey) {\n return { ...nextByKey.get(beforeKey)! };\n }\n\n if (afterKey) {\n return { ...nextByKey.get(afterKey)! };\n }\n\n return prevPt;\n}\n\n// ---------------------------------------------------------------------------\n// Line/area path application helpers\n// ---------------------------------------------------------------------------\n\n/** Interpolate a point array at parameter t. */\nexport function interpolatePoints(fromPts: Point[], toPts: Point[], t: number): Point[] {\n const len = Math.min(fromPts.length, toPts.length);\n const result: Point[] = new Array(len);\n for (let i = 0; i < len; i++) {\n result[i] = lerpPoint(fromPts[i], toPts[i], t);\n }\n return result;\n}\n\n/** Apply an interpolated path to a line mark's path element. */\nexport function applyLinePath(el: SVGElement, points: Point[], interpolate?: string): void {\n const pathEl = el.querySelector('path') as SVGElement | null;\n if (!pathEl) return;\n pathEl.setAttribute('d', buildLinePath(points, interpolate));\n}\n\n/** Apply interpolated paths to an area mark's fill and stroke path elements. */\nexport function applyAreaPaths(\n el: SVGElement,\n topPoints: Point[],\n bottomPoints: Point[],\n interpolate?: string,\n hasStroke?: boolean,\n): void {\n const paths = el.querySelectorAll('path');\n // First path is the area fill\n if (paths[0]) {\n paths[0].setAttribute('d', buildAreaPath(topPoints, bottomPoints, interpolate));\n }\n // Second path (if present) is the top-line stroke\n if (hasStroke && paths[1]) {\n paths[1].setAttribute('d', buildLinePath(topPoints, interpolate));\n }\n}\n\n/** Apply the exact final path from the mark data (not from interpolated points). */\nexport function applyFinalLinePath(el: SVGElement, mark: LineMark): void {\n const pathEl = el.querySelector('path') as SVGElement | null;\n if (!pathEl || !mark.path) return;\n pathEl.setAttribute('d', mark.path);\n}\n\n/** Apply the exact final paths from the area mark data. */\nexport function applyFinalAreaPaths(el: SVGElement, mark: AreaMark): void {\n const paths = el.querySelectorAll('path');\n if (paths[0]) {\n paths[0].setAttribute('d', mark.path);\n }\n if (paths[1] && mark.topPath) {\n paths[1].setAttribute('d', mark.topPath);\n }\n}\n","// ---------------------------------------------------------------------------\n// Mark DOM index\n// ---------------------------------------------------------------------------\n\n/**\n * One-pass index of `[data-key]` mark elements, built once per transition and\n * shared by every tween builder plus `snapToFinal`. Replaces per-key\n * `querySelector` calls, which were O(marks x DOM nodes) and threw a\n * SyntaxError when a data value contained `\"` or `\\` (keys are raw String(v)\n * from the engine, never escaped).\n *\n * The same key can legitimately appear on different mark types (a rule and its\n * text label both keyed on the category), so class-qualified buckets mirror the\n * class-qualified selectors they replace. Exit ghosts strip `data-key` before\n * they are appended, so the index never sees them.\n */\nexport interface MarkDomIndex {\n /** First element in document order with this key (querySelector parity). */\n any(key: string): SVGElement | null;\n point(key: string): SVGElement | null; // circle.oc-mark-point\n rule(key: string): SVGElement | null; // .oc-mark-rule\n tick(key: string): SVGElement | null; // .oc-mark-tick\n text(key: string): SVGElement | null; // .oc-mark-text\n}\n\nexport function buildMarkDomIndex(marksContainer: SVGElement): MarkDomIndex {\n const anyM = new Map<string, SVGElement>();\n const pointM = new Map<string, SVGElement>();\n const ruleM = new Map<string, SVGElement>();\n const tickM = new Map<string, SVGElement>();\n const textM = new Map<string, SVGElement>();\n for (const node of marksContainer.querySelectorAll('[data-key]')) {\n const el = node as SVGElement;\n const key = el.getAttribute('data-key');\n if (!key) continue;\n if (!anyM.has(key)) anyM.set(key, el);\n const cl = el.classList;\n if (el.tagName === 'circle' && cl.contains('oc-mark-point')) {\n if (!pointM.has(key)) pointM.set(key, el);\n } else if (cl.contains('oc-mark-rule')) {\n if (!ruleM.has(key)) ruleM.set(key, el);\n } else if (cl.contains('oc-mark-tick')) {\n if (!tickM.has(key)) tickM.set(key, el);\n } else if (cl.contains('oc-mark-text')) {\n if (!textM.has(key)) textM.set(key, el);\n }\n }\n const g = (m: Map<string, SVGElement>) => (key: string) => m.get(key) ?? null;\n return { any: g(anyM), point: g(pointM), rule: g(ruleM), tick: g(tickM), text: g(textM) };\n}\n","import type {\n ArcMark,\n AreaMark,\n ChartLayout,\n GradientDef,\n LineMark,\n PointMark,\n RectMark,\n RuleMarkLayout,\n TextMarkLayout,\n TickMarkLayout,\n} from '@opendata-ai/openchart-core';\nimport { resolveMarkFill } from '../gradient-utils';\nimport { renderSingleMark } from '../renderers/marks';\n\nimport type { MarkDomIndex } from './dom-index';\nimport { geomFromMark, normalizePointArrays } from './interpolate';\nimport type { ArcGeom, GeometrySnapshot, RectGeom, Tween } from './types';\n\n// ---------------------------------------------------------------------------\n// Gradient ghost helper\n// ---------------------------------------------------------------------------\n\n/**\n * For marks with gradient fills, resolve the gradient to a url(#id) reference\n * using the ghost gradient map. This ensures ghosts reference valid gradient\n * IDs in the new SVG's <defs>.\n */\nexport function resolveGhostGradientFill<T extends { fill?: string | GradientDef }>(\n mark: T,\n ghostGradientMap: Map<string, string>,\n): T {\n if (!mark.fill || typeof mark.fill === 'string' || ghostGradientMap.size === 0) return mark;\n const resolved = resolveMarkFill(mark.fill, ghostGradientMap);\n return { ...mark, fill: resolved };\n}\n\n// ---------------------------------------------------------------------------\n// Rect tween building (extracted from original runTransition)\n// ---------------------------------------------------------------------------\n\nexport function buildRectTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevRects = prevLayout.marks.filter((m): m is RectMark => m.type === 'rect');\n const nextRects = nextLayout.marks.filter((m): m is RectMark => m.type === 'rect');\n\n const prevByKey = new Map<string, RectMark>();\n for (const m of prevRects) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, RectMark>();\n for (const m of nextRects) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n // Retarget: use snapshot geometry if available (interrupted transition)\n let fromGeom = geomFromMark(prev);\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'rect') {\n fromGeom = { x: snap.x, y: snap.y, width: snap.width, height: snap.height };\n }\n\n tweens.push({\n tweenType: 'rect',\n kind: 'update',\n el,\n from: fromGeom,\n to: geomFromMark(next),\n mark: next,\n });\n }\n\n // Entered\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n let fromGeom: RectGeom;\n if (next.orient === 'horizontal') {\n fromGeom = { x: next.x, y: next.y, width: 0, height: next.height };\n } else {\n fromGeom = { x: next.x, y: next.y + next.height, width: next.width, height: 0 };\n }\n\n tweens.push({\n tweenType: 'rect',\n kind: 'enter',\n el,\n from: fromGeom,\n to: geomFromMark(next),\n mark: next,\n });\n }\n\n // Exited\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n // Resolve gradient fill for ghost if needed\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n let toGeom: RectGeom;\n if (prev.orient === 'horizontal') {\n toGeom = { x: prev.x, y: prev.y, width: 0, height: prev.height };\n } else {\n toGeom = { x: prev.x, y: prev.y + prev.height, width: prev.width, height: 0 };\n }\n\n tweens.push({\n tweenType: 'rect',\n kind: 'exit',\n el: ghost,\n from: geomFromMark(prev),\n to: toGeom,\n mark: prev,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Line tween building\n// ---------------------------------------------------------------------------\n\nexport function buildLineTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevLines = prevLayout.marks.filter((m): m is LineMark => m.type === 'line');\n const nextLines = nextLayout.marks.filter((m): m is LineMark => m.type === 'line');\n\n const prevByKey = new Map<string, LineMark>();\n for (const m of prevLines) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, LineMark>();\n for (const m of nextLines) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated series\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n // If interrupted mid-morph, freeze the current path and crossfade\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'line') {\n // Create ghost carrying the frozen mid-morph path\n const ghost = el.cloneNode(true) as SVGElement;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n const ghostPath = ghost.querySelector('path');\n if (ghostPath) ghostPath.setAttribute('d', snap.d);\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'line',\n kind: 'exit',\n el: ghost,\n fromPts: next.points, // placeholder, not used for path\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n\n // Fade in the new final path\n tweens.push({\n tweenType: 'line',\n kind: 'enter',\n el,\n fromPts: next.points,\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n fromOpacity: 0,\n toOpacity: 1,\n });\n continue;\n }\n\n const prevPKs = prev.pointKeys ?? prev.points.map((_, i) => `${i}`);\n const nextPKs = next.pointKeys ?? next.points.map((_, i) => `${i}`);\n\n // Check if zero survivors (fully replaced dataset)\n const prevKeySet = new Set(prevPKs);\n const hasSurvivors = nextPKs.some((k) => prevKeySet.has(k));\n\n if (!hasSurvivors) {\n // Crossfade: fade out old (ghost), fade in new\n const ghost = renderSingleMark(prev, 0);\n if (ghost) {\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'line',\n kind: 'exit',\n el: ghost,\n fromPts: prev.points,\n toPts: prev.points,\n finalPoints: prev.points,\n interpolate: prev.interpolate,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n\n // Fade in the new one\n tweens.push({\n tweenType: 'line',\n kind: 'enter',\n el,\n fromPts: next.points,\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n fromOpacity: 0,\n toOpacity: 1,\n });\n } else {\n // Normal morph with point matching\n const [fromPts, toPts] = normalizePointArrays(prev.points, next.points, prevPKs, nextPKs);\n\n tweens.push({\n tweenType: 'line',\n kind: 'update',\n el,\n fromPts,\n toPts,\n finalPoints: next.points,\n interpolate: next.interpolate,\n });\n }\n }\n\n // Entering series (only in next)\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n tweens.push({\n tweenType: 'line',\n kind: 'enter',\n el,\n fromPts: next.points,\n toPts: next.points,\n finalPoints: next.points,\n interpolate: next.interpolate,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting series (only in prev)\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'line',\n kind: 'exit',\n el: ghost,\n fromPts: prev.points,\n toPts: prev.points,\n finalPoints: prev.points,\n interpolate: prev.interpolate,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Area tween building\n// ---------------------------------------------------------------------------\n\nexport function buildAreaTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevAreas = prevLayout.marks.filter((m): m is AreaMark => m.type === 'area');\n const nextAreas = nextLayout.marks.filter((m): m is AreaMark => m.type === 'area');\n\n const prevByKey = new Map<string, AreaMark>();\n for (const m of prevAreas) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, AreaMark>();\n for (const m of nextAreas) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated series\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n // If interrupted mid-morph, freeze and crossfade\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'area') {\n const ghost = el.cloneNode(true) as SVGElement;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n const ghostPaths = ghost.querySelectorAll('path');\n if (ghostPaths[0]) ghostPaths[0].setAttribute('d', snap.d);\n if (ghostPaths[1] && snap.topD) ghostPaths[1].setAttribute('d', snap.topD);\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'area',\n kind: 'exit',\n el: ghost,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n\n tweens.push({\n tweenType: 'area',\n kind: 'enter',\n el,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n fromOpacity: 0,\n toOpacity: 1,\n });\n continue;\n }\n\n const prevPKs = prev.pointKeys ?? prev.topPoints.map((_, i) => `${i}`);\n const nextPKs = next.pointKeys ?? next.topPoints.map((_, i) => `${i}`);\n\n const prevKeySet = new Set(prevPKs);\n const hasSurvivors = nextPKs.some((k) => prevKeySet.has(k));\n\n if (!hasSurvivors) {\n // Crossfade\n const ghost = renderSingleMark(prev, 0);\n if (ghost) {\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'area',\n kind: 'exit',\n el: ghost,\n fromTop: prev.topPoints,\n toTop: prev.topPoints,\n fromBottom: prev.bottomPoints,\n toBottom: prev.bottomPoints,\n finalTopPoints: prev.topPoints,\n finalBottomPoints: prev.bottomPoints,\n interpolate: prev.interpolate,\n hasStroke: !!prev.stroke && !!prev.topPath,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n\n tweens.push({\n tweenType: 'area',\n kind: 'enter',\n el,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n fromOpacity: 0,\n toOpacity: 1,\n });\n } else {\n // Morph\n const [fromTop, toTop] = normalizePointArrays(\n prev.topPoints,\n next.topPoints,\n prevPKs,\n nextPKs,\n );\n const [fromBottom, toBottom] = normalizePointArrays(\n prev.bottomPoints,\n next.bottomPoints,\n prevPKs,\n nextPKs,\n );\n\n tweens.push({\n tweenType: 'area',\n kind: 'update',\n el,\n fromTop,\n toTop,\n fromBottom,\n toBottom,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n });\n }\n }\n\n // Entering series\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n tweens.push({\n tweenType: 'area',\n kind: 'enter',\n el,\n fromTop: next.topPoints,\n toTop: next.topPoints,\n fromBottom: next.bottomPoints,\n toBottom: next.bottomPoints,\n finalTopPoints: next.topPoints,\n finalBottomPoints: next.bottomPoints,\n interpolate: next.interpolate,\n hasStroke: !!next.stroke && !!next.topPath,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting series\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'area',\n kind: 'exit',\n el: ghost,\n fromTop: prev.topPoints,\n toTop: prev.topPoints,\n fromBottom: prev.bottomPoints,\n toBottom: prev.bottomPoints,\n finalTopPoints: prev.topPoints,\n finalBottomPoints: prev.bottomPoints,\n interpolate: prev.interpolate,\n hasStroke: !!prev.stroke && !!prev.topPath,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Arc tween building (pie/donut slices)\n// ---------------------------------------------------------------------------\n\n/** Angle/radius geometry lifted off an arc mark for interpolation. */\nfunction arcGeomFromMark(m: ArcMark): ArcGeom {\n return {\n startAngle: m.startAngle,\n endAngle: m.endAngle,\n innerRadius: m.innerRadius,\n outerRadius: m.outerRadius,\n };\n}\n\nexport function buildArcTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevArcs = prevLayout.marks.filter((m): m is ArcMark => m.type === 'arc');\n const nextArcs = nextLayout.marks.filter((m): m is ArcMark => m.type === 'arc');\n\n const prevByKey = new Map<string, ArcMark>();\n for (const m of prevArcs) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, ArcMark>();\n for (const m of nextArcs) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated: interpolate angles/radii; the path is rebuilt per frame.\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n let fromGeom = arcGeomFromMark(prev);\n let fromCenter = prev.center;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'arc') {\n fromGeom = {\n startAngle: snap.startAngle,\n endAngle: snap.endAngle,\n innerRadius: snap.innerRadius,\n outerRadius: snap.outerRadius,\n };\n fromCenter = { x: snap.cx, y: snap.cy };\n }\n\n tweens.push({\n tweenType: 'arc',\n kind: 'update',\n el,\n from: fromGeom,\n to: arcGeomFromMark(next),\n fromCenter,\n toCenter: next.center,\n mark: next,\n });\n }\n\n // Entered: grow from a zero-width sweep at the slice's own start angle.\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.any(key);\n if (!el) continue;\n\n tweens.push({\n tweenType: 'arc',\n kind: 'enter',\n el,\n from: { ...arcGeomFromMark(next), endAngle: next.startAngle },\n to: arcGeomFromMark(next),\n fromCenter: next.center,\n toCenter: next.center,\n mark: next,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exited: ghost collapses its sweep to the midpoint angle and fades out.\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n const mid = (prev.startAngle + prev.endAngle) / 2;\n tweens.push({\n tweenType: 'arc',\n kind: 'exit',\n el: ghost,\n from: arcGeomFromMark(prev),\n to: { ...arcGeomFromMark(prev), startAngle: mid, endAngle: mid },\n fromCenter: prev.center,\n toCenter: prev.center,\n mark: prev,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Point tween building (scatter/dot/line overlay circle marks)\n// ---------------------------------------------------------------------------\n\nexport function buildPointTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n ghostGradientMap: Map<string, string>,\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevPoints = prevLayout.marks.filter((m): m is PointMark => m.type === 'point');\n const nextPoints = nextLayout.marks.filter((m): m is PointMark => m.type === 'point');\n\n const prevByKey = new Map<string, PointMark>();\n for (const m of prevPoints) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, PointMark>();\n for (const m of nextPoints) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated points: tween cx/cy/r\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.point(key);\n if (!el) continue;\n\n // Read the element's current opacity attribute (NOT style.opacity)\n // to detect suppressed points (opacity=\"0\" set by renderer for endpoint markers)\n const renderedOpacity = el.getAttribute('opacity');\n const isSuppressed = renderedOpacity === '0';\n\n // Retarget from snapshot if interrupted\n let fromCx = prev.cx;\n let fromCy = prev.cy;\n let fromR = prev.r !== next.r ? prev.r : undefined;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'point') {\n fromCx = snap.cx;\n fromCy = snap.cy;\n if (snap.r !== undefined && snap.r !== next.r) {\n fromR = snap.r;\n }\n }\n\n tweens.push({\n tweenType: 'point',\n kind: 'update',\n el,\n fromCx,\n fromCy,\n toCx: next.cx,\n toCy: next.cy,\n fromR: fromR,\n toR: fromR !== undefined ? next.r : undefined,\n // Do NOT tween opacity for updated points - preserve renderer state\n suppressedOpacity: isSuppressed ? '0' : undefined,\n });\n }\n\n // Entering points: fade in\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.point(key);\n if (!el) continue;\n\n // Read rendered opacity for the final value\n const renderedOpacity = el.getAttribute('opacity');\n const targetOpacity = renderedOpacity != null ? Number(renderedOpacity) : 1;\n\n tweens.push({\n tweenType: 'point',\n kind: 'enter',\n el,\n fromCx: next.cx,\n fromCy: next.cy,\n toCx: next.cx,\n toCy: next.cy,\n fromOpacity: 0,\n toOpacity: targetOpacity,\n suppressedOpacity: renderedOpacity === '0' ? '0' : undefined,\n });\n }\n\n // Exiting points: ghost fade out\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n\n const ghostMark = resolveGhostGradientFill(prev, ghostGradientMap);\n const ghost = renderSingleMark(ghostMark, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n\n tweens.push({\n tweenType: 'point',\n kind: 'exit',\n el: ghost,\n fromCx: prev.cx,\n fromCy: prev.cy,\n toCx: prev.cx,\n toCy: prev.cy,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rule tween building\n// ---------------------------------------------------------------------------\n\nexport function buildRuleTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevRules = prevLayout.marks.filter((m): m is RuleMarkLayout => m.type === 'rule');\n const nextRules = nextLayout.marks.filter((m): m is RuleMarkLayout => m.type === 'rule');\n\n const prevByKey = new Map<string, RuleMarkLayout>();\n for (const m of prevRules) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, RuleMarkLayout>();\n for (const m of nextRules) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.rule(key);\n if (!el) continue;\n\n let fromX1 = prev.x1;\n let fromY1 = prev.y1;\n let fromX2 = prev.x2;\n let fromY2 = prev.y2;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'rule') {\n fromX1 = snap.x1;\n fromY1 = snap.y1;\n fromX2 = snap.x2;\n fromY2 = snap.y2;\n }\n\n tweens.push({\n tweenType: 'rule',\n kind: 'update',\n el,\n fromX1,\n fromY1,\n fromX2,\n fromY2,\n toX1: next.x1,\n toY1: next.y1,\n toX2: next.x2,\n toY2: next.y2,\n });\n }\n\n // Entering\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.rule(key);\n if (!el) continue;\n tweens.push({\n tweenType: 'rule',\n kind: 'enter',\n el,\n fromX1: next.x1,\n fromY1: next.y1,\n fromX2: next.x2,\n fromY2: next.y2,\n toX1: next.x1,\n toY1: next.y1,\n toX2: next.x2,\n toY2: next.y2,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n tweens.push({\n tweenType: 'rule',\n kind: 'exit',\n el: ghost,\n fromX1: prev.x1,\n fromY1: prev.y1,\n fromX2: prev.x2,\n fromY2: prev.y2,\n toX1: prev.x1,\n toY1: prev.y1,\n toX2: prev.x2,\n toY2: prev.y2,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tick tween building\n// ---------------------------------------------------------------------------\n\nexport function buildTickTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevTicks = prevLayout.marks.filter((m): m is TickMarkLayout => m.type === 'tick');\n const nextTicks = nextLayout.marks.filter((m): m is TickMarkLayout => m.type === 'tick');\n\n const prevByKey = new Map<string, TickMarkLayout>();\n for (const m of prevTicks) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, TickMarkLayout>();\n for (const m of nextTicks) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n function tickEndpoints(t: TickMarkLayout) {\n const half = t.length / 2;\n if (t.orient === 'vertical') {\n return { x1: t.x, y1: t.y - half, x2: t.x, y2: t.y + half };\n }\n return { x1: t.x - half, y1: t.y, x2: t.x + half, y2: t.y };\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.tick(key);\n if (!el) continue;\n let pEnd = tickEndpoints(prev);\n const nEnd = tickEndpoints(next);\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'tick') {\n pEnd = { x1: snap.x1, y1: snap.y1, x2: snap.x2, y2: snap.y2 };\n }\n tweens.push({\n tweenType: 'tick',\n kind: 'update',\n el,\n fromX1: pEnd.x1,\n fromY1: pEnd.y1,\n fromX2: pEnd.x2,\n fromY2: pEnd.y2,\n toX1: nEnd.x1,\n toY1: nEnd.y1,\n toX2: nEnd.x2,\n toY2: nEnd.y2,\n });\n }\n\n // Entering\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.tick(key);\n if (!el) continue;\n const nEnd = tickEndpoints(next);\n tweens.push({\n tweenType: 'tick',\n kind: 'enter',\n el,\n fromX1: nEnd.x1,\n fromY1: nEnd.y1,\n fromX2: nEnd.x2,\n fromY2: nEnd.y2,\n toX1: nEnd.x1,\n toY1: nEnd.y1,\n toX2: nEnd.x2,\n toY2: nEnd.y2,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n const pEnd = tickEndpoints(prev);\n tweens.push({\n tweenType: 'tick',\n kind: 'exit',\n el: ghost,\n fromX1: pEnd.x1,\n fromY1: pEnd.y1,\n fromX2: pEnd.x2,\n fromY2: pEnd.y2,\n toX1: pEnd.x1,\n toY1: pEnd.y1,\n toX2: pEnd.x2,\n toY2: pEnd.y2,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Text mark tween building\n// ---------------------------------------------------------------------------\n\nexport function buildTextMarkTweens(\n prevLayout: ChartLayout,\n nextLayout: ChartLayout,\n marksContainer: SVGElement,\n dom: MarkDomIndex,\n tweens: Tween[],\n ghosts: SVGElement[],\n fromSnapshot?: GeometrySnapshot,\n): void {\n const prevTexts = prevLayout.marks.filter((m): m is TextMarkLayout => m.type === 'textMark');\n const nextTexts = nextLayout.marks.filter((m): m is TextMarkLayout => m.type === 'textMark');\n\n const prevByKey = new Map<string, TextMarkLayout>();\n for (const m of prevTexts) {\n if (m.key) prevByKey.set(m.key, m);\n }\n const nextByKey = new Map<string, TextMarkLayout>();\n for (const m of nextTexts) {\n if (m.key) nextByKey.set(m.key, m);\n }\n\n // Updated\n for (const [key, next] of nextByKey) {\n const prev = prevByKey.get(key);\n if (!prev) continue;\n const el = dom.text(key);\n if (!el) continue;\n\n let fromX = prev.x;\n let fromY = prev.y;\n const snap = fromSnapshot?.get(key);\n if (snap && snap.type === 'textMark') {\n fromX = snap.x;\n fromY = snap.y;\n }\n\n tweens.push({\n tweenType: 'textMark',\n kind: 'update',\n el,\n fromX,\n fromY,\n toX: next.x,\n toY: next.y,\n });\n }\n\n // Entering\n for (const [key, next] of nextByKey) {\n if (prevByKey.has(key)) continue;\n const el = dom.text(key);\n if (!el) continue;\n tweens.push({\n tweenType: 'textMark',\n kind: 'enter',\n el,\n fromX: next.x,\n fromY: next.y,\n toX: next.x,\n toY: next.y,\n fromOpacity: 0,\n toOpacity: 1,\n });\n }\n\n // Exiting\n for (const [key, prev] of prevByKey) {\n if (nextByKey.has(key)) continue;\n const ghost = renderSingleMark(prev, 0);\n if (!ghost) continue;\n ghost.classList.add('oc-ghost');\n ghost.setAttribute('aria-hidden', 'true');\n ghost.setAttribute('pointer-events', 'none');\n ghost.removeAttribute('data-key');\n marksContainer.appendChild(ghost);\n ghosts.push(ghost);\n tweens.push({\n tweenType: 'textMark',\n kind: 'exit',\n el: ghost,\n fromX: prev.x,\n fromY: prev.y,\n toX: prev.x,\n toY: prev.y,\n ghost,\n fromOpacity: 1,\n toOpacity: 0,\n });\n }\n}\n","/**\n * \"You draw it\" interaction layer: the DOM/SVG overlay for the `youDrawIt`\n * spec option (NYT-style draw-then-reveal engagement format).\n *\n * SVG-space elements (hatched drawing region, reader's guess path, reveal\n * clip rect, pointer-capture overlay) render inside the chart's own SVG so\n * they clip and scale with it. The prompt text and skip-to-reveal button are\n * a small HTML overlay positioned over the drawing region, following the\n * series-search precedent (`series-search.ts`): a native `<button>` gets\n * keyboard semantics for free instead of hand-rolling SVG focus handling.\n *\n * State (the reader's in-progress guess) lives in this module's closure,\n * matching mount.ts's per-instance-closure convention (StrictMode double-\n * mount safe): a fresh `createYouDrawIt()` call gets a fresh closure.\n */\n\nimport type { Point, ResolvedYouDrawIt } from '@opendata-ai/openchart-core';\nimport { createSVGElement, SVG_NS, setAttrs } from './renderers/svg-dom';\nimport { nextSvgId } from './svg-ids';\n\nexport interface YouDrawItOptions {\n /** The chart container (`.oc-root`). Must be position: relative. */\n container: HTMLElement;\n /** Fired once the drawing is revealed, with the guess in data coordinates ordered by x. */\n onReveal?: (guess: Array<{ x: string | number; y: number }>) => void;\n}\n\nexport interface YouDrawItController {\n /** Reposition, resync geometry, and (re)wire pointer capture against a freshly rendered layout + SVG. */\n update(config: ResolvedYouDrawIt, svg: SVGSVGElement): void;\n /** Hide (spec no longer wants youDrawIt on this render, e.g. mark type changed). */\n hide(): void;\n /** Reveal the real line and fire onReveal, without requiring reader interaction (skip-to-reveal). */\n reveal(): void;\n /** Clear the reader's guess and return to the drawing state. */\n reset(): void;\n /** Whether the drawing has been revealed. */\n readonly isRevealed: boolean;\n /** Remove all DOM elements. */\n destroy(): void;\n}\n\n/** Minimum touch target size (effective hit area), per WCAG 2.5.5 / mobile a11y conventions. */\nconst MIN_TOUCH_TARGET = 24;\n\n/** Build the \"M x,y L x,y ...\" path string for a straight-segment line through points, sorted by x. */\nfunction buildLinearPath(points: Point[]): string {\n if (points.length === 0) return '';\n const sorted = [...points].sort((a, b) => a.x - b.x);\n return sorted.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');\n}\n\n/**\n * Create the you-draw-it control. Mounted once per chart instance and kept\n * across re-renders so the in-progress drawing survives; `update()` re-syncs\n * geometry and re-wires pointer capture after each render.\n */\nexport function createYouDrawIt(options: YouDrawItOptions): YouDrawItController {\n const { container, onReveal } = options;\n\n let destroyed = false;\n let revealed = false;\n let config: ResolvedYouDrawIt | null = null;\n let svgEl: SVGSVGElement | null = null;\n /** Reader's guess: pixel y keyed by pixel x sample. */\n const guessByX = new Map<number, number>();\n let cleanupPointerEvents: (() => void) | null = null;\n\n // ---------------------------------------------------------------------------\n // SVG elements (rebuilt each update() since the SVG itself is rebuilt on render)\n // ---------------------------------------------------------------------------\n\n function buildHatchPattern(id: string, color: string): SVGElement {\n const pattern = document.createElementNS(SVG_NS, 'pattern');\n pattern.setAttribute('id', id);\n pattern.setAttribute('patternUnits', 'userSpaceOnUse');\n pattern.setAttribute('width', '8');\n pattern.setAttribute('height', '8');\n pattern.setAttribute('patternTransform', 'rotate(45)');\n const line = document.createElementNS(SVG_NS, 'line');\n setAttrs(line, { x1: 0, y1: 0, x2: 0, y2: 8, stroke: color, 'stroke-width': 1 });\n line.setAttribute('stroke-opacity', '0.5');\n pattern.appendChild(line);\n return pattern;\n }\n\n /** Locate the target line's <path> in the freshly rendered SVG. */\n function findTargetLinePath(svg: SVGSVGElement, seriesKey?: string): SVGPathElement | null {\n // Line marks render as <g data-mark-id=\"line-{seriesKey ?? index}\"> with a\n // single <path> child (see renderers/marks.ts). Prefer the seriesKey match;\n // fall back to the first line mark for single-series charts (no color enc).\n if (seriesKey) {\n const escaped =\n typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(seriesKey)\n : seriesKey.replace(/\"/g, '\\\\\"');\n const byKey = svg.querySelector<SVGPathElement>(`[data-mark-id=\"line-${escaped}\"] path`);\n if (byKey) return byKey;\n }\n return svg.querySelector<SVGPathElement>('.oc-mark-line path');\n }\n\n function render(cfg: ResolvedYouDrawIt, svg: SVGSVGElement): void {\n // Remove any previous you-draw-it group (SVG is rebuilt each render, but\n // defensive against re-entrant calls).\n svg.querySelector('[data-you-draw-it]')?.remove();\n\n const group = createSVGElement('g') as SVGGElement;\n group.setAttribute('data-you-draw-it', 'true');\n group.setAttribute('class', 'oc-ydi');\n\n const { area, fromX } = cfg;\n const regionWidth = Math.max(0, area.x + area.width - fromX);\n\n // Hatch pattern + reveal clip defs.\n const defs = createSVGElement('defs');\n const patternId = nextSvgId('oc-ydi-hatch');\n defs.appendChild(buildHatchPattern(patternId, cfg.lineColor));\n\n // Reveal clip: masks the real line's post-from segment until reveal.\n // Applied to the target line path element itself (not a <g>), matching\n // the SVG clip-path gotcha in .claude/rules/svg-animation.md.\n const clipId = nextSvgId('oc-ydi-clip');\n const clipPath = createSVGElement('clipPath');\n clipPath.setAttribute('id', clipId);\n const clipRect = createSVGElement('rect');\n setAttrs(clipRect, {\n x: area.x,\n y: area.y,\n width: revealed ? area.width : Math.max(0, fromX - area.x),\n height: area.height,\n });\n clipRect.setAttribute('data-ydi-clip-rect', 'true');\n clipRect.setAttribute('class', 'oc-ydi-clip-rect');\n clipPath.appendChild(clipRect);\n defs.appendChild(clipPath);\n group.appendChild(defs);\n\n // Hatched \"draw here\" region.\n const region = createSVGElement('rect');\n setAttrs(region, {\n x: fromX,\n y: area.y,\n width: regionWidth,\n height: area.height,\n fill: `url(#${patternId})`,\n });\n region.setAttribute('class', 'oc-ydi-region');\n region.setAttribute('data-ydi-region', 'true');\n region.setAttribute('pointer-events', 'none');\n if (revealed) region.setAttribute('data-ydi-hidden', 'true');\n group.appendChild(region);\n\n // \"from\" boundary marker: a thin dashed rule where drawing begins.\n const boundary = createSVGElement('line');\n setAttrs(boundary, { x1: fromX, y1: area.y, x2: fromX, y2: area.y + area.height });\n boundary.setAttribute('class', 'oc-ydi-boundary');\n boundary.setAttribute('pointer-events', 'none');\n group.appendChild(boundary);\n\n const targetLineEl = findTargetLinePath(svg, cfg.targetSeriesKey);\n if (targetLineEl) {\n targetLineEl.setAttribute('clip-path', `url(#${clipId})`);\n }\n\n // Optional comparison line (host-supplied \"everyone else's guess\").\n if (cfg.comparisonPoints && cfg.comparisonPoints.length > 0) {\n const compPath = createSVGElement('path');\n setAttrs(compPath, { d: buildLinearPath(cfg.comparisonPoints), fill: 'none' });\n compPath.setAttribute('class', 'oc-ydi-comparison');\n compPath.setAttribute('pointer-events', 'none');\n group.appendChild(compPath);\n }\n\n // Reader's guess path (pen style), populated as the reader draws.\n const guessPath = createSVGElement('path');\n setAttrs(guessPath, { d: '', fill: 'none' });\n guessPath.setAttribute('class', 'oc-ydi-guess');\n guessPath.setAttribute('data-ydi-guess-path', 'true');\n guessPath.setAttribute('pointer-events', 'none');\n group.appendChild(guessPath);\n\n // Pointer-capture overlay over the drawing region only.\n if (!revealed) {\n const overlay = createSVGElement('rect');\n setAttrs(overlay, {\n x: fromX,\n y: area.y,\n width: regionWidth,\n height: area.height,\n fill: 'transparent',\n });\n overlay.setAttribute('class', 'oc-ydi-overlay');\n overlay.setAttribute('data-ydi-overlay', 'true');\n overlay.setAttribute('role', 'img');\n overlay.setAttribute(\n 'aria-label',\n 'Drawing area: drag to sketch your guess of the trend, or use the reveal button to skip.',\n );\n overlay.style.touchAction = 'none';\n overlay.style.cursor = 'crosshair';\n group.appendChild(overlay);\n }\n\n svg.appendChild(group);\n }\n\n function redrawGuessPath(): void {\n if (!svgEl) return;\n const path = svgEl.querySelector<SVGPathElement>('[data-ydi-guess-path]');\n if (!path) return;\n const points: Point[] = Array.from(guessByX.entries()).map(([x, y]) => ({ x, y }));\n path.setAttribute('d', buildLinearPath(points));\n }\n\n function snapToNearestSample(px: number): number | null {\n if (!config || config.samples.length === 0) return null;\n let nearestPx = config.samples[0].px;\n let best = Math.abs(nearestPx - px);\n for (const s of config.samples) {\n const d = Math.abs(s.px - px);\n if (d < best) {\n best = d;\n nearestPx = s.px;\n }\n }\n return nearestPx;\n }\n\n function clampY(py: number): number {\n if (!config) return py;\n return Math.min(config.area.y + config.area.height, Math.max(config.area.y, py));\n }\n\n // ---------------------------------------------------------------------------\n // Pointer capture (mouse + touch), following the crosshair toSvgCoords pattern\n // ---------------------------------------------------------------------------\n\n function wirePointerEvents(svg: SVGSVGElement): () => void {\n const overlay = svg.querySelector('[data-ydi-overlay]');\n if (!overlay) return () => {};\n\n let dragging = false;\n\n const toSvgCoords = (clientX: number, clientY: number) => {\n const svgRect = svg.getBoundingClientRect();\n const viewBox = svg.viewBox?.baseVal;\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 return {\n svgX: (clientX - svgRect.left) * scaleX,\n svgY: (clientY - svgRect.top) * scaleY,\n };\n };\n\n const paintAt = (clientX: number, clientY: number) => {\n const { svgX, svgY } = toSvgCoords(clientX, clientY);\n const snapped = snapToNearestSample(svgX);\n if (snapped === null) return;\n guessByX.set(snapped, clampY(svgY));\n redrawGuessPath();\n };\n\n const handleMouseDown = (e: Event) => {\n const me = e as MouseEvent;\n dragging = true;\n paintAt(me.clientX, me.clientY);\n };\n const handleMouseMove = (e: Event) => {\n if (!dragging) return;\n const me = e as MouseEvent;\n paintAt(me.clientX, me.clientY);\n };\n const handleMouseUp = () => {\n dragging = false;\n };\n\n const handleTouchStart = (e: Event) => {\n const te = e as TouchEvent;\n if (te.touches.length === 0) return;\n if (te.cancelable) te.preventDefault();\n dragging = true;\n paintAt(te.touches[0].clientX, te.touches[0].clientY);\n };\n const handleTouchMove = (e: Event) => {\n if (!dragging) return;\n const te = e as TouchEvent;\n if (te.touches.length === 0) return;\n if (te.cancelable) te.preventDefault();\n paintAt(te.touches[0].clientX, te.touches[0].clientY);\n };\n const handleTouchEnd = () => {\n dragging = false;\n };\n\n overlay.addEventListener('mousedown', handleMouseDown);\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n overlay.addEventListener('touchstart', handleTouchStart, { passive: false });\n overlay.addEventListener('touchmove', handleTouchMove, { passive: false });\n overlay.addEventListener('touchend', handleTouchEnd);\n overlay.addEventListener('touchcancel', handleTouchEnd);\n\n return () => {\n overlay.removeEventListener('mousedown', handleMouseDown);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n overlay.removeEventListener('touchstart', handleTouchStart);\n overlay.removeEventListener('touchmove', handleTouchMove);\n overlay.removeEventListener('touchend', handleTouchEnd);\n overlay.removeEventListener('touchcancel', handleTouchEnd);\n };\n }\n\n // ---------------------------------------------------------------------------\n // Prompt + reveal button (HTML overlay, positioned over the drawing region)\n // ---------------------------------------------------------------------------\n\n const root = document.createElement('div');\n root.className = 'oc-ydi-controls';\n root.style.display = 'none';\n root.style.position = 'absolute';\n\n const prompt = document.createElement('div');\n prompt.className = 'oc-ydi-prompt';\n\n const revealButton = document.createElement('button');\n revealButton.type = 'button';\n revealButton.className = 'oc-ydi-reveal-button';\n\n root.append(prompt, revealButton);\n container.style.position = container.style.position || 'relative';\n container.appendChild(root);\n\n function reduceMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n !!window.matchMedia &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n }\n\n /**\n * Map a drawn pixel y back to a data value via the linear yInvert anchors.\n *\n * This interpolates linearly in pixel space between the top and bottom\n * anchors. For a linear y-scale that is exact. For a log or pow scale it is\n * an approximation: the true inverse is curved, so a guess drawn halfway up\n * the plot reads back as the arithmetic midpoint of the domain rather than\n * the geometric (log) or power midpoint. The you-draw-it guess is a rough\n * \"where did the reader think the line went\" signal, not a precise readout,\n * so the linear approximation is acceptable here; revisit if a non-linear\n * scale ever needs an exact guess value.\n */\n function pixelYToData(py: number): number {\n if (!config) return py;\n const inv = config.yInvert;\n if (!inv) {\n // No invertible scale: report the pixel y normalized to the area (1 at\n // top, 0 at bottom) so callers still get relative shape.\n const area = config.area;\n return 1 - (py - area.y) / (area.height || 1);\n }\n const span = inv.bottomPixel - inv.topPixel;\n if (span === 0) return inv.topData;\n const t = (py - inv.topPixel) / span;\n return inv.topData + t * (inv.bottomData - inv.topData);\n }\n\n function getGuessData(): Array<{ x: string | number; y: number }> {\n if (!config) return [];\n const valueByPx = new Map(config.samples.map((s) => [s.px, s.xValue]));\n return Array.from(guessByX.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([px, py]) => ({ x: valueByPx.get(px) ?? px, y: pixelYToData(py) }));\n }\n\n function doReveal(): void {\n if (destroyed || revealed || !svgEl || !config) return;\n revealed = true;\n\n const clipRect = svgEl.querySelector<SVGRectElement>('[data-ydi-clip-rect]');\n if (clipRect) {\n if (reduceMotion()) {\n clipRect.setAttribute('width', String(config.area.width));\n } else {\n clipRect.classList.add('oc-ydi-clip-animate');\n // Force layout so the transition on the width change is observed. The\n // update-transition rAF driver only tracks marks, so a scoped CSS\n // transition on the clip rect is the plan's accepted fallback.\n void clipRect.getBoundingClientRect();\n clipRect.setAttribute('width', String(config.area.width));\n }\n }\n const region = svgEl.querySelector<SVGRectElement>('[data-ydi-region]');\n region?.setAttribute('data-ydi-hidden', 'true');\n svgEl.querySelector('[data-ydi-overlay]')?.remove();\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n root.classList.add('oc-ydi-revealed');\n prompt.textContent = '';\n revealButton.disabled = true;\n\n onReveal?.(getGuessData());\n }\n\n revealButton.addEventListener('click', doReveal);\n\n return {\n update(cfg: ResolvedYouDrawIt, svg: SVGSVGElement): void {\n if (destroyed) return;\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n\n config = cfg;\n svgEl = svg;\n\n render(cfg, svg);\n redrawGuessPath();\n\n prompt.textContent = revealed ? '' : cfg.prompt;\n revealButton.textContent = cfg.revealLabel;\n revealButton.setAttribute('aria-label', cfg.revealLabel);\n revealButton.style.minHeight = `${MIN_TOUCH_TARGET}px`;\n revealButton.disabled = revealed;\n if (revealed) root.classList.add('oc-ydi-revealed');\n else root.classList.remove('oc-ydi-revealed');\n\n // Position the HTML controls over the drawing region. Same viewBox-scale\n // approach as series-search / the text edit overlay.\n const viewBox = svg.viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const scaleX = viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1;\n const regionWidth = Math.max(0, cfg.area.x + cfg.area.width - cfg.fromX);\n root.style.left = `${cfg.fromX * scaleX + (svgRect.left - containerRect.left)}px`;\n root.style.top = `${cfg.area.y * scaleY + (svgRect.top - containerRect.top)}px`;\n root.style.width = `${regionWidth * scaleX}px`;\n root.style.height = `${cfg.area.height * scaleY}px`;\n root.style.display = 'flex';\n\n if (!revealed) {\n cleanupPointerEvents = wirePointerEvents(svg);\n }\n },\n hide(): void {\n root.style.display = 'none';\n svgEl?.querySelector('[data-you-draw-it]')?.remove();\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n },\n reveal(): void {\n doReveal();\n },\n reset(): void {\n if (destroyed) return;\n revealed = false;\n guessByX.clear();\n revealButton.disabled = false;\n root.classList.remove('oc-ydi-revealed');\n if (config && svgEl) {\n render(config, svgEl);\n prompt.textContent = config.prompt;\n cleanupPointerEvents?.();\n cleanupPointerEvents = wirePointerEvents(svgEl);\n }\n },\n get isRevealed(): boolean {\n return revealed;\n },\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n cleanupPointerEvents?.();\n cleanupPointerEvents = null;\n root.remove();\n },\n };\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 ChartEventHandlers,\n ChartLayout,\n ChartSpec,\n CompileOptions,\n DarkMode,\n DataRow,\n ElementRef,\n GraphSpec,\n LayerSpec,\n TextAnnotation,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { cssTokenDefault, isGraphSpec, isLayerSpec } from '@opendata-ai/openchart-core';\nimport {\n compileChart,\n compileLayer,\n facetMinHeight,\n legendGap,\n} from '@opendata-ai/openchart-engine';\nimport { cancelAnimations, computeAnimationDuration, setupAnimationCleanup } from './animation';\nimport {\n exportCSV,\n exportJPG,\n exportPNG,\n exportSVG,\n exportSVGWithFonts,\n type JPGExportOptions,\n type SVGExportOptions,\n} from './export';\nimport { materializeCanvasModeSVG } from './export-canvas';\nimport type { GIFExportOptions } from './export-gif';\nimport {\n buildElementRef,\n createScreenReaderTable,\n findElementByRef,\n getEditableElements,\n getElementText,\n invertScale,\n isTextEditable,\n refsEqual,\n renderSelectionOverlay,\n wireAnchorDrag,\n wireAnnotationDrag,\n wireAnnotationLabelDrag,\n wireChartEvents,\n wireChromeDrag,\n wireConnectorEndpointDrag,\n wireKeyboardNav,\n wireLegendDrag,\n wireLegendInteraction,\n wireSeriesLabelDrag,\n wireTooltipEvents,\n wireVoronoiTooltipEvents,\n} from './interactions';\nimport { createMeasureText, resolveFontFamily, scheduleFontReload } from './measure-text';\nimport { observeResize } from './resize-observer';\nimport { resolveDarkMode } from './resolve-dark-mode';\nimport type { EntranceHandle } from './scatter-canvas/entrance';\nimport { wireCanvasInteractions } from './scatter-canvas/interactions';\nimport { createScatterCanvasLayer, type ScatterCanvasLayer } from './scatter-canvas/layer';\nimport { createSeriesSearch, type SeriesSearchController } from './series-search';\nimport { renderChartSVG } from './svg-renderer';\nimport { createTextEditOverlay, createTextEditOverlayAtPosition } from './text-edit-overlay';\nimport { stampThemeProperties } from './theme-tokens';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\nimport {\n canTransition,\n type GeometrySnapshot,\n runTransition,\n type TransitionHandle,\n} from './transition';\nimport { createYouDrawIt, type YouDrawItController } from './you-draw-it';\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 /**\n * Rendering backend for point marks (mirrors vega-embed's `renderer`\n * option). `'auto'` (default) promotes dense scatters (>1,000 points) to a\n * canvas mark layer; `'svg'`/`'canvas'` force a backend. Ignored with a\n * console warning for non-point marks and faceted/layered/sparkline charts.\n */\n renderer?: 'auto' | 'svg' | 'canvas';\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 /**\n * Re-render with a new spec and start a MANUAL update transition the caller\n * drives via `handle.step(elapsedMs)`, with no rAF clock. Returns the handle,\n * or null when no transition applies (the render already swapped instantly).\n * For headless frame capture (e.g. GIF export of a spec-swap stepper).\n */\n beginManualUpdate(spec: ChartSpec | LayerSpec | GraphSpec): TransitionHandle | null;\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: 'gif', options?: GIFExportOptions): Promise<Blob>;\n export(format: 'csv'): string;\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'gif' | 'csv',\n options?: ExportOptions | GIFExportOptions,\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 /** Set highlight values on the color encoding and re-render. Pass null to clear. */\n setHighlight(values: string[] | null): void;\n /**\n * Reset a \"you draw it\" (`youDrawIt`) drawing: clears the reader's guess and\n * returns to the drawing state. No-op when youDrawIt isn't enabled.\n */\n resetDrawing(): void;\n /**\n * Reveal a \"you draw it\" drawing programmatically (equivalent to the\n * skip-to-reveal button). No-op when youDrawIt isn't enabled.\n */\n revealDrawing(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Container sizing\n// ---------------------------------------------------------------------------\n\n/**\n * Fallback height when the container doesn't constrain height. For\n * auto-height ChartSpec mounts this is the fixed budget for the\n * visualization itself (padding + axes + plot); chrome, the top legend\n * block, and the metrics bar grow the figure on top of it.\n */\nconst FALLBACK_HEIGHT = 400;\n\n// ---------------------------------------------------------------------------\n// Editable element helpers\n// ---------------------------------------------------------------------------\n\nconst EDITABLE_HOVER_CSS = `\n.oc-editable-hover {\n outline: 1.5px solid ${cssTokenDefault('--oc-editable-hover', 'light')};\n outline-offset: 2px;\n border-radius: 2px;\n}\n`;\n\nfunction makeEditable(svg: SVGElement): void {\n svg.setAttribute('tabindex', '0');\n svg.style.outline = 'none';\n\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\nfunction hasEditingCallbacks(opts?: MountOptions): boolean {\n return !!(opts?.onEdit || opts?.onSelect || opts?.onDeselect || opts?.onTextEdit);\n}\n\n// ---------------------------------------------------------------------------\n// Series search helpers\n// ---------------------------------------------------------------------------\n\n/** The authored encoding.color.highlight as an array (empty when unset). */\nfunction authoredHighlight(spec: ChartSpec | LayerSpec | GraphSpec): string[] {\n if (isLayerSpec(spec) || isGraphSpec(spec as unknown as Record<string, unknown>)) return [];\n const colorEnc = (spec as ChartSpec).encoding?.color;\n if (!colorEnc || typeof colorEnc !== 'object' || !('field' in colorEnc)) return [];\n const raw = (colorEnc as { highlight?: string | string[] }).highlight;\n if (raw == null) return [];\n return Array.isArray(raw) ? [...raw] : [raw];\n}\n\n/** True when the spec enables the series search input. */\nfunction wantsSeriesSearch(spec: ChartSpec | LayerSpec | GraphSpec): boolean {\n if (isLayerSpec(spec) || isGraphSpec(spec as unknown as Record<string, unknown>)) return false;\n return !!(spec as ChartSpec).seriesSearch;\n}\n\n/** True when the spec enables the \"you draw it\" interactive format. */\nfunction wantsYouDrawIt(spec: ChartSpec | LayerSpec | GraphSpec): boolean {\n if (isLayerSpec(spec) || isGraphSpec(spec as unknown as Record<string, unknown>)) return false;\n return !!(spec as ChartSpec).youDrawIt;\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a chart instance from a spec and mount it into a container.\n */\nexport function createChart<TData extends DataRow = DataRow>(\n container: HTMLElement,\n spec: ChartSpec<TData> | LayerSpec<TData> | GraphSpec,\n options?: MountOptions,\n): ChartInstance {\n let currentSpec: ChartSpec | LayerSpec | GraphSpec = spec as ChartSpec | LayerSpec | GraphSpec;\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 // Canvas mark layer, present only while currentLayout.markRenderMode is\n // 'canvas'. render() is a full teardown/rebuild, so StrictMode double-mounts\n // and resizes need no canvas-specific handling beyond destroying it here.\n let canvasLayer: ScatterCanvasLayer | null = null;\n let cleanupCanvasEvents: (() => void) | null = null;\n let canvasEntrance: EntranceHandle | null = null;\n let warnedCanvasEditMode = false;\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\n // Animation state\n let isFirstRender = true;\n let cleanupAnimations: (() => void) | null = null;\n let pendingResize = false;\n\n // Auto-height sizing state. `isAutoHeight` latches whether the host\n // constrains the container's height:\n // null = unknown — every measurement so far was an all-zero rect\n // (display:none / detached); keep re-checking each measure.\n // true = auto-height — the figure grows with chrome (ChartSpec only).\n // false = explicit height — fit inside the host's box (today's behavior).\n // The latch matters because the SVG's own style.height gives the container\n // a nonzero rect after the first render, so auto-height cannot be\n // re-derived per measure.\n let isAutoHeight: boolean | null = null;\n let lastRenderedWidth: number | null = null;\n let lastRenderedSvgHeight: number | null = null;\n\n // Data-update transition state\n let transitionHandle: TransitionHandle | null = null;\n let transitionSnapshot: GeometrySnapshot | null = null;\n\n // Set when webfonts have loaded and a recompile is owed to reflect final font\n // metrics. The next render() that actually recompiles flips\n // data-oc-fonts-state to 'ready' and clears this. Deferring the flip (rather\n // than setting it right after resize()) keeps the attribute honest when the\n // entrance animation makes resize() defer to pendingResize.\n let fontsReloadPending = 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\n // Runtime legend-toggle state\n const runtimeHiddenSeries = new Set<string>();\n const runtimeShownSeries = new Set<string>();\n let textEditCleanup: (() => void) | null = null;\n\n // Series search state. The control persists across renders (so focus and\n // chips survive the re-render each selection triggers); the baseline is the\n // authored encoding.color.highlight, captured before setHighlight mutates\n // currentSpec, so clearing the search restores it exactly.\n let seriesSearch: SeriesSearchController | null = null;\n let searchBaseline: string[] = authoredHighlight(currentSpec);\n let editSuppressWarned = false;\n\n // \"You draw it\" state. The controller persists across renders so the reader's\n // in-progress guess (and revealed state) survive the re-render each resize\n // triggers; update() re-syncs geometry and re-wires pointer capture.\n let youDrawIt: YouDrawItController | null = null;\n let ydiEditSuppressWarned = false;\n\n // Apply the root class up front so getComputedStyle can read --oc-font-family\n // before we build the text measurer.\n container.classList.add('oc-root');\n\n // Resolve the effective font family the way compile() will. compile merges\n // { ...spec.theme, ...options.theme }, so options.theme wins over the\n // spec-level theme; fall back to the container's computed font. Measuring\n // against a different font than compile renders (e.g. a spec that sets\n // theme.fonts.family) desyncs layout metrics and the font-reload watcher.\n function resolveEffectiveFont(): string {\n return (\n options?.theme?.fonts?.family ??\n currentSpec.theme?.fonts?.family ??\n resolveFontFamily(container)\n );\n }\n let fontFamily = resolveEffectiveFont();\n let measureText = createMeasureText(fontFamily);\n let renderGen = 0;\n\n // ---------------------------------------------------------------------------\n // Compilation\n // ---------------------------------------------------------------------------\n\n function compileAt(width: number, height: number): ChartLayout {\n const darkMode = resolveDarkMode(options?.darkMode);\n\n const compileOpts: CompileOptions = {\n width,\n height,\n theme: options?.theme,\n darkMode,\n renderer: options?.renderer,\n watermark: options?.watermark,\n measureText,\n };\n\n if (isLayerSpec(currentSpec)) {\n return compileLayer(withRuntimeHidden(currentSpec as LayerSpec) as LayerSpec, compileOpts);\n }\n return compileChart(withRuntimeHidden(currentSpec) as ChartSpec | GraphSpec, compileOpts);\n }\n\n /**\n * Vertical overheads that grow an auto-height figure beyond the\n * FALLBACK_HEIGHT budget: top+bottom chrome (bottom chrome already includes\n * a bottom legend's reservation), the top legend block (height + gap), and\n * the KPI metrics bar. topPad and the axis gap are plot clearance, not\n * chrome — they stay inside the budget.\n *\n * For faceted charts, extra rows beyond what the base budget can fit\n * also contribute: each additional row needs space for the panel itself\n * plus its header and gap.\n */\n function verticalOverheads(layout: ChartLayout, width: number): number {\n // Sum EVERY top legend, not just the primary. A chart can carry a color\n // legend and a size legend; counting one and growing the container by its\n // height alone leaves the other squeezing the plot.\n let topLegendBlock = 0;\n for (const legend of layout.legends ?? [layout.legend]) {\n if (legend.position !== 'top') continue;\n const hasContent =\n legend.type === 'continuous' || legend.type === 'size'\n ? legend.bounds.height > 0\n : 'entries' in legend && legend.entries.length > 0;\n if (hasContent) topLegendBlock += legend.bounds.height + legendGap(width);\n }\n\n let facetGrowth = 0;\n if (layout.facet) {\n const needed = facetMinHeight(layout.facet.panels.length, layout.facet.columns);\n const budgetForPanels =\n FALLBACK_HEIGHT - layout.chrome.topHeight - layout.chrome.bottomHeight - topLegendBlock;\n if (needed > budgetForPanels) {\n facetGrowth = needed - budgetForPanels;\n }\n }\n\n return (\n layout.chrome.topHeight +\n layout.chrome.bottomHeight +\n topLegendBlock +\n (layout.metrics?.height ?? 0) +\n facetGrowth\n );\n }\n\n function compile(): ChartLayout {\n const { width, height } = getContainerDimensions();\n\n // Auto-height growth applies to ChartSpec mounts only. GraphSpec,\n // LayerSpec, and sparkline mounts keep the fixed-fallback behavior.\n const growsWithChrome =\n isAutoHeight === true &&\n !isLayerSpec(currentSpec) &&\n !isGraphSpec(currentSpec as unknown as Record<string, unknown>) &&\n (currentSpec as ChartSpec).display !== 'sparkline';\n if (!growsWithChrome) {\n return compileAt(width, height);\n }\n\n // Bounded convergence loop, max 3 compiles. Chrome height depends on\n // width (text wrap), not height — but the engine's chrome-strip guardrail\n // strips chrome when the residual plot is too small, which makes chrome\n // height-dependent at the budget boundary: growing the figure can\n // un-strip chrome, changing the overheads once more. (Height classes are\n // not the issue — they only strip below 200/350px, and growing from 400\n // moves away from those thresholds.) Pass 3 is accepted unconditionally.\n let layout = compileAt(width, height);\n const overheads = verticalOverheads(layout, width);\n if (overheads > 0) {\n layout = compileAt(width, height + overheads);\n const overheads2 = verticalOverheads(layout, width);\n if (overheads2 !== overheads) {\n layout = compileAt(width, height + overheads2);\n }\n }\n return layout;\n }\n\n function withRuntimeHidden<T extends { hiddenSeries?: string[]; annotations?: Annotation[] }>(\n spec: T,\n ): T {\n if (runtimeHiddenSeries.size === 0 && runtimeShownSeries.size === 0) return spec;\n const userHidden = spec.hiddenSeries ?? [];\n const finalHidden = new Set<string>(userHidden);\n for (const s of runtimeHiddenSeries) finalHidden.add(s);\n for (const s of runtimeShownSeries) finalHidden.delete(s);\n const out: T = { ...spec, hiddenSeries: Array.from(finalHidden) };\n if (finalHidden.size > 0 && spec.annotations) {\n const filtered = spec.annotations.filter((a) => a.type !== 'text');\n out.annotations = filtered.length > 0 ? filtered : undefined;\n }\n return out;\n }\n\n // ---------------------------------------------------------------------------\n // Legend toggle\n // ---------------------------------------------------------------------------\n\n function countSeries(spec: ChartSpec | GraphSpec | LayerSpec): number {\n if (isLayerSpec(spec)) return Infinity;\n const enc = (spec as ChartSpec).encoding;\n const colorEnc = enc?.color;\n if (!colorEnc || 'condition' in colorEnc) return Infinity;\n if (!('field' in colorEnc) || !colorEnc.field) return Infinity;\n if (colorEnc.type === 'quantitative') return Infinity;\n const field = colorEnc.field;\n const seen = new Set<string>();\n for (const row of (spec as ChartSpec).data ?? []) {\n seen.add(String((row as Record<string, unknown>)[field]));\n }\n return seen.size;\n }\n\n function isSeriesHidden(series: string): boolean {\n if (runtimeShownSeries.has(series)) return false;\n if (runtimeHiddenSeries.has(series)) return true;\n const userHidden = (currentSpec as { hiddenSeries?: string[] }).hiddenSeries ?? [];\n return userHidden.includes(series);\n }\n\n function toggleSeriesVisibility(series: string): boolean {\n const wasHidden = isSeriesHidden(series);\n if (!wasHidden) {\n const total = countSeries(currentSpec);\n if (Number.isFinite(total)) {\n const userHidden = new Set((currentSpec as { hiddenSeries?: string[] }).hiddenSeries ?? []);\n let visibleAfter = 0;\n const seriesField = getColorField(currentSpec);\n if (seriesField) {\n const allSeries = new Set<string>();\n for (const row of (currentSpec as ChartSpec).data ?? []) {\n allSeries.add(String((row as Record<string, unknown>)[seriesField]));\n }\n for (const s of allSeries) {\n if (s === series) continue;\n if (runtimeShownSeries.has(s)) {\n visibleAfter++;\n continue;\n }\n if (runtimeHiddenSeries.has(s)) continue;\n if (!userHidden.has(s)) visibleAfter++;\n }\n }\n if (visibleAfter === 0) return false;\n }\n }\n if (wasHidden) {\n runtimeHiddenSeries.delete(series);\n const userHidden = (currentSpec as { hiddenSeries?: string[] }).hiddenSeries ?? [];\n if (userHidden.includes(series)) runtimeShownSeries.add(series);\n } else {\n runtimeShownSeries.delete(series);\n runtimeHiddenSeries.add(series);\n }\n render();\n return !wasHidden;\n }\n\n function getColorField(spec: ChartSpec | GraphSpec | LayerSpec): string | undefined {\n if (isLayerSpec(spec)) return undefined;\n const colorEnc = (spec as ChartSpec).encoding?.color;\n if (!colorEnc || 'condition' in colorEnc) return undefined;\n if (!('field' in colorEnc) || !colorEnc.field) return undefined;\n return colorEnc.field;\n }\n\n // ---------------------------------------------------------------------------\n // Container dimensions\n // ---------------------------------------------------------------------------\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n const isSparkline =\n 'display' in currentSpec && (currentSpec as ChartSpec).display === 'sparkline';\n if (isSparkline) {\n let width = rect.width;\n let height = rect.height;\n if (!height && container.parentElement) {\n const parentRect = container.parentElement.getBoundingClientRect();\n height = parentRect.height;\n if (!width) width = parentRect.width;\n }\n return {\n width: Math.max(width || 200, 30),\n height: Math.max(height || 40, 20),\n };\n }\n // Latch auto-height on the first NONZERO measurement: height 0 with a\n // real width means the host doesn't constrain height. An all-zero rect\n // (display:none / detached) stays \"unknown\" — keep re-checking until the\n // container produces a real measurement.\n if (isAutoHeight === null && (rect.width > 0 || rect.height > 0)) {\n isAutoHeight = rect.height === 0 && rect.width > 0;\n }\n\n return {\n width: Math.max(rect.width || 600, 100),\n // Latched-auto mounts always compile against the fixed budget: after\n // the first render the container's measured height is just our own\n // SVG, so reading it back would re-pin whatever we rendered last.\n height:\n isAutoHeight === true ? FALLBACK_HEIGHT : Math.max(rect.height || FALLBACK_HEIGHT, 100),\n };\n }\n\n // ---------------------------------------------------------------------------\n // Selection & text editing\n // ---------------------------------------------------------------------------\n\n function getSpecAnnotations(): Annotation[] {\n return 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n }\n\n function selectElement(ref: ElementRef): void {\n if (!svgElement) return;\n\n const target = findElementByRef(svgElement, ref);\n if (!target) return;\n\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 (svgElement as SVGSVGElement).focus();\n }\n\n function deselectElement(): void {\n if (!selectedElement) return;\n\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 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 const target = findElementByRef(svgElement, selectedElement);\n if (!target) return;\n\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 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 function wireSelectionEvents(): () => void {\n if (!svgElement) return () => {};\n\n const svg = svgElement;\n const cleanups: Array<() => void> = [];\n\n const handleClick = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n const target = mouseEvent.target as Element;\n\n if (isTextEditingActive) return;\n\n const specAnnotations = getSpecAnnotations();\n const ref = buildElementRef(target, specAnnotations);\n\n if (ref) {\n selectElement(ref);\n } else {\n deselectElement();\n }\n };\n\n svg.addEventListener('click', handleClick);\n cleanups.push(() => svg.removeEventListener('click', handleClick));\n\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:not(.oc-legend--size), [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 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 if (!refsEqual(selectedElement, ref)) {\n selectElement(ref);\n }\n enterTextEditing();\n return;\n }\n\n // Double-click on empty canvas: create a new annotation\n if (!ref && options?.onEdit && currentLayout?.xInvert && currentLayout?.yInvert) {\n const svgEl = svg as SVGSVGElement;\n const viewBox = svgEl.viewBox?.baseVal;\n const svgRect = svgEl.getBoundingClientRect();\n if (!viewBox || !svgRect.width || !svgRect.height) return;\n\n const vbScaleX = viewBox.width / svgRect.width;\n const vbScaleY = viewBox.height / svgRect.height;\n const svgX = (mouseEvent.clientX - svgRect.left) * vbScaleX;\n const svgY = (mouseEvent.clientY - svgRect.top) * vbScaleY;\n\n const area = currentLayout.area;\n if (svgX < area.x || svgX > area.x + area.width) return;\n if (svgY < area.y || svgY > area.y + area.height) return;\n\n const dataX = invertScale(currentLayout.xInvert, svgX);\n const dataY = invertScale(currentLayout.yInvert, svgY);\n\n isTextEditingActive = true;\n const overlay = createTextEditOverlayAtPosition({\n container,\n svg: svgEl,\n position: { x: svgX, y: svgY },\n onCommit: (text: string) => {\n isTextEditingActive = false;\n textEditCleanup = null;\n const annotation: TextAnnotation = { type: 'text', x: dataX, y: dataY, text };\n options.onEdit!({ type: 'add', annotation });\n },\n onCancel: () => {\n isTextEditingActive = false;\n textEditCleanup = null;\n },\n });\n textEditCleanup = overlay.destroy;\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 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 }\n break;\n }\n\n case 'Escape': {\n e.preventDefault();\n if (isTextEditingActive && textEditCleanup) {\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 // ---------------------------------------------------------------------------\n // Render cycle\n // ---------------------------------------------------------------------------\n\n function render(): void {\n if (isDragging) {\n pendingRender = true;\n return;\n }\n\n // Cancel any in-progress data-update transition\n if (transitionHandle) {\n transitionHandle.cancel();\n transitionHandle = null;\n }\n\n // Cancel any in-progress entrance animations before tearing down\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n }\n canvasEntrance?.cancel();\n canvasEntrance = null;\n cancelAnimations(svgElement);\n\n // Clean up previous render\n cleanupTooltipEvents?.();\n cleanupTooltipEvents = null;\n cleanupVoronoiEvents?.();\n cleanupVoronoiEvents = null;\n cleanupCanvasEvents?.();\n cleanupCanvasEvents = null;\n canvasLayer?.destroy();\n canvasLayer = null;\n cleanupKeyboardNav?.();\n cleanupKeyboardNav = null;\n cleanupLegend?.();\n cleanupLegend = null;\n cleanupChartEvents?.();\n cleanupChartEvents = null;\n cleanupAnnotationDrag?.();\n cleanupAnnotationDrag = null;\n cleanupEditDrags?.();\n cleanupEditDrags = null;\n cleanupSelection?.();\n cleanupSelection = null;\n cleanupKeyboardEdit?.();\n cleanupKeyboardEdit = null;\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 // Recorded for the ResizeObserver's self-induced-resize guard.\n lastRenderedWidth = currentLayout.dimensions.width;\n lastRenderedSvgHeight = currentLayout.dimensions.height;\n const shouldAnimate = isFirstRender && !!currentLayout.animation?.enter;\n const crosshair = !!currentLayout.crosshair;\n\n // Canvas mark mode: the canvas is created BEFORE the SVG so DOM order puts\n // it underneath (both are positioned, so DOM order decides paint order).\n const canvasMode = currentLayout.markRenderMode === 'canvas';\n if (canvasMode) {\n canvasLayer = createScatterCanvasLayer(container, currentLayout);\n canvasLayer.repaint();\n\n // Point marks are pixels on a canvas, not selectable elements, so\n // per-mark edit selection is unavailable. Annotation, chrome, and legend\n // editing still work -- those stay in the SVG. Warned once per mount.\n if (\n !warnedCanvasEditMode &&\n (options?.editable || hasEditingCallbacks(options) || options?.onAnnotationEdit)\n ) {\n warnedCanvasEditMode = true;\n console.warn(\n 'openchart: canvas mark mode does not support per-mark edit selection. ' +\n 'Annotation, chrome, and legend editing still work. ' +\n \"Pass renderer: 'svg' to createChart() if you need to select individual points.\",\n );\n }\n }\n\n svgElement = renderChartSVG(currentLayout, container, {\n animate: shouldAnimate,\n crosshair,\n canvasMarks: canvasMode,\n });\n tooltipManager = createTooltipManager(container);\n\n // Canvas hit-testing replaces per-element listeners for point marks.\n // wireTooltipEvents below still runs and is simply inert for points --\n // canvas mode emits no [data-mark-id] circles for it to bind to.\n if (canvasMode && canvasLayer) {\n cleanupCanvasEvents = wireCanvasInteractions({\n layer: canvasLayer,\n svg: svgElement,\n tooltipDescriptors: currentLayout.tooltipDescriptors,\n tooltipManager,\n options,\n });\n }\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. Skipped when the author hid the chart from\n // assistive technology (a11y.hidden): a hidden chart must not be a tab stop.\n if (!currentLayout.a11y.hidden) {\n cleanupKeyboardNav = wireKeyboardNav(\n svgElement,\n container,\n currentLayout.tooltipDescriptors,\n tooltipManager,\n currentLayout,\n );\n }\n\n // seriesSearch and edit mode are mutually exclusive per instance: when\n // the spec enables seriesSearch, edit interactions are suppressed\n // (search wins -- the engine already reserved the search band).\n const editSuppressed = wantsSeriesSearch(currentSpec);\n if (\n editSuppressed &&\n !editSuppressWarned &&\n (options?.editable || hasEditingCallbacks(options) || options?.onAnnotationEdit)\n ) {\n editSuppressWarned = true;\n console.warn(\n '[openchart] seriesSearch and edit mode are mutually exclusive; edit interactions are disabled while seriesSearch is enabled.',\n );\n }\n\n // Wire legend interactivity\n cleanupLegend = wireLegendInteraction(\n svgElement,\n currentLayout,\n toggleSeriesVisibility,\n options?.onLegendToggle,\n editSuppressed ? undefined : 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: 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 const dragAnnotations: Annotation[] =\n 'annotations' in currentSpec && Array.isArray(currentSpec.annotations)\n ? currentSpec.annotations\n : [];\n\n // Wire annotation drag editing\n if (\n !editSuppressed &&\n (options?.editable ?? Boolean(options?.onAnnotationEdit || options?.onEdit))\n ) {\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 (or editable is true)\n if (!editSuppressed && (options?.editable ?? Boolean(options?.onEdit))) {\n const editCleanups: Array<() => void> = [];\n const onEditFn = options?.onEdit ?? (() => {});\n\n editCleanups.push(\n wireConnectorEndpointDrag(svgElement, dragAnnotations, onEditFn, setDragging),\n );\n editCleanups.push(\n wireAnnotationLabelDrag(svgElement, dragAnnotations, onEditFn, setDragging),\n );\n\n if (currentLayout.xInvert && currentLayout.yInvert) {\n editCleanups.push(\n wireAnchorDrag(svgElement, dragAnnotations, currentLayout, onEditFn, setDragging),\n );\n }\n\n const editSpec = currentSpec as ChartSpec | GraphSpec;\n editCleanups.push(wireChromeDrag(svgElement, editSpec, onEditFn, setDragging));\n editCleanups.push(wireLegendDrag(svgElement, editSpec, onEditFn, setDragging));\n editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec, onEditFn, 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 (!editSuppressed && (options?.editable ?? hasEditingCallbacks(options))) {\n makeEditable(svgElement);\n cleanupSelection = wireSelectionEvents();\n cleanupKeyboardEdit = wireKeyboardEditEvents();\n\n if (selectedElement) {\n const target = findElementByRef(svgElement, selectedElement);\n if (target) {\n overlayElement = renderSelectionOverlay(svgElement, selectedElement, currentLayout);\n } else {\n selectedElement = null;\n overlayElement = null;\n }\n }\n }\n\n // Create hidden data table for screen readers (not when the author hid\n // the chart from assistive technology)\n if (!currentLayout.a11y.hidden) {\n srTable = createScreenReaderTable(currentLayout, container);\n }\n\n // Mount/refresh the series search overlay on its reserved band. Created\n // once and kept across renders so typing focus and chips survive the\n // re-render each selection triggers.\n if (currentLayout.seriesSearch) {\n if (!seriesSearch) {\n seriesSearch = createSeriesSearch({ container, onChange: handleSearchChange });\n }\n seriesSearch.update(currentLayout.seriesSearch, svgElement);\n } else if (seriesSearch) {\n if (wantsSeriesSearch(currentSpec)) {\n // The layout stripped the band (e.g. hidden chrome mode at cramped\n // sizes) but the spec still wants search: keep the control and its\n // chips, just hide it until the band comes back.\n seriesSearch.hide();\n } else {\n seriesSearch.destroy();\n seriesSearch = null;\n }\n }\n\n // Mount/refresh the \"you draw it\" overlay. Created once and kept across\n // renders so the reader's in-progress guess survives each resize's\n // re-render. Mutually exclusive with edit mode: when editing callbacks are\n // present, youDrawIt is disabled (warn once) per plans 11/17's rule.\n const ydiEditConflict = wantsYouDrawIt(currentSpec) && hasEditingCallbacks(options);\n if (ydiEditConflict && !ydiEditSuppressWarned) {\n ydiEditSuppressWarned = true;\n console.warn(\n '[openchart] youDrawIt and edit mode are mutually exclusive; youDrawIt is disabled while editing callbacks are provided.',\n );\n }\n if (currentLayout.youDrawIt && !ydiEditConflict) {\n if (!youDrawIt) {\n youDrawIt = createYouDrawIt({ container, onReveal: options?.onReveal });\n }\n youDrawIt.update(currentLayout.youDrawIt, svgElement as SVGSVGElement);\n } else if (youDrawIt) {\n if (wantsYouDrawIt(currentSpec) && !ydiEditConflict) {\n // Layout stripped the config (e.g. empty data at this size) but the\n // spec still wants it: keep the controller (and its guess), just hide.\n youDrawIt.hide();\n } else {\n youDrawIt.destroy();\n youDrawIt = null;\n }\n }\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 // Stamp resolved theme as CSS custom properties on the container\n // so CSS consumers read from the same source of truth as the JS engine.\n stampThemeProperties(container, currentLayout.theme);\n\n // Set up animation cleanup on first render only\n if (shouldAnimate && svgElement) {\n // Canvas mode animates points on the canvas scheduler, not via CSS, so\n // the cleanup timer must be told how long that actually takes. The\n // DOM-counting estimate sees no point elements and would fire early.\n let entranceTotalMs: number | undefined;\n if (canvasMode && canvasLayer && currentLayout.animation?.enter) {\n canvasEntrance = canvasLayer.playEntrance(currentLayout.animation.enter);\n if (canvasEntrance) {\n // Take the longer of the two clocks: the SVG side still animates\n // axes, chrome, and annotations on its own schedule.\n entranceTotalMs = Math.max(\n computeAnimationDuration(svgElement),\n canvasEntrance.totalMs + (currentLayout.animation.annotationDelay ?? 0) + 500,\n );\n }\n }\n\n cleanupAnimations = setupAnimationCleanup(\n svgElement,\n () => {\n cleanupAnimations = null;\n canvasEntrance = null;\n if (pendingResize) {\n pendingResize = false;\n resize();\n }\n },\n entranceTotalMs,\n );\n }\n // Bump the render generation so tests (and consumers) can observe every\n // full recompile, including the post-font-load one.\n renderGen += 1;\n container.dataset.ocRenderGen = String(renderGen);\n\n // This render recompiled with the loaded webfonts, so the layout now\n // reflects final font metrics. Publish 'ready' only now (not right after\n // the fonts-ready resize(), which may have deferred to pendingResize while\n // the entrance animation was still running).\n if (fontsReloadPending) {\n fontsReloadPending = false;\n container.dataset.ocFontsState = 'ready';\n }\n\n if (isFirstRender) {\n isFirstRender = false;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API methods\n // ---------------------------------------------------------------------------\n\n function update(newSpec: ChartSpec | GraphSpec, updateOpts?: UpdateOptions): void {\n doUpdate(newSpec, updateOpts, false);\n }\n\n /**\n * Re-render with a new spec and start a MANUAL transition the caller drives via\n * `handle.step(elapsedMs)`. Returns the handle, or null when no transition\n * applies (unchanged shape, first render, etc. — the render already swapped\n * instantly). Used by headless frame capture (GIF export of a spec-swap\n * stepper) to sample the update tween deterministically. No rAF runs.\n */\n function beginManualUpdate(newSpec: ChartSpec | LayerSpec | GraphSpec): TransitionHandle | null {\n return doUpdate(newSpec as ChartSpec | GraphSpec, undefined, true);\n }\n\n function doUpdate(\n newSpec: ChartSpec | GraphSpec,\n updateOpts: UpdateOptions | undefined,\n manual: boolean,\n ): TransitionHandle | null {\n if (destroyed) return null;\n\n // Capture pre-update state for transition gating\n const prevSpec = currentSpec;\n const prevLayout = currentLayout;\n const entranceWasRunning = cleanupAnimations != null;\n\n // Snapshot in-flight transition geometry before render() cancels it.\n // This enables retargeting: the next transition starts from the\n // interrupted position instead of snapping to the previous final state.\n if (transitionHandle?.running) {\n transitionSnapshot = transitionHandle.snapshot();\n }\n\n currentSpec = newSpec;\n // A new spec can change theme.fonts.family; rebuild the measurer so layout\n // measures the font compile will actually render with.\n const nextFont = resolveEffectiveFont();\n if (nextFont !== fontFamily) {\n fontFamily = nextFont;\n measureText = createMeasureText(fontFamily);\n }\n runtimeHiddenSeries.clear();\n runtimeShownSeries.clear();\n // The new spec is the source of truth: re-capture the authored highlight\n // baseline and drop any search selections layered on the previous spec.\n searchBaseline = authoredHighlight(newSpec);\n seriesSearch?.setSelected([]);\n // A new spec re-arms the conflict warnings (youDrawIt/edit and\n // seriesSearch/edit) so a newly-introduced conflict warns once again.\n ydiEditSuppressWarned = false;\n editSuppressWarned = false;\n if (updateOpts && 'selectedElement' in updateOpts) {\n selectedElement = updateOpts.selectedElement ?? null;\n }\n render();\n\n // After render, check if we can run a smooth transition instead of the\n // instant swap that render() already performed.\n if (\n svgElement &&\n canTransition({\n prevLayout,\n nextLayout: currentLayout,\n prevSpec,\n nextSpec: newSpec,\n isFirstRender: false,\n entranceInFlight: entranceWasRunning,\n })\n ) {\n // Consume snapshot (if any) for retargeting, then clear\n const snapshot = transitionSnapshot;\n transitionSnapshot = null;\n\n const handle = runTransition({\n svg: svgElement as SVGSVGElement,\n prevLayout,\n nextLayout: currentLayout,\n animation: currentLayout.animation!,\n fromSnapshot: snapshot ?? undefined,\n manual,\n // render() above already rebuilt the layer for the NEXT layout, so this\n // is the destination-mode layer the tween writes into.\n canvas: canvasLayer ?? undefined,\n onComplete: () => {\n transitionHandle = null;\n },\n });\n // A manual transition is caller-owned: the caller steps it and finalizes\n // via `cancel()`, and `onComplete` never fires in manual mode. Don't track\n // it on the instance field, or it would be left pointing at a cancelled\n // handle. The auto (rAF) path keeps tracking so retargeting can snapshot it.\n if (!manual) transitionHandle = handle;\n return handle;\n }\n // No transition started; clear any stale snapshot\n transitionSnapshot = null;\n return null;\n }\n\n function resize(): void {\n if (destroyed) return;\n if (cleanupAnimations) {\n // Canvas mode cancels the entrance and re-renders immediately instead of\n // deferring. The SVG is fluid (`.oc-chart { width: 100% }`) while the\n // canvas is sized in fixed layout pixels, so deferring would leave the\n // two layers visibly out of register for the rest of the entrance.\n if (canvasEntrance) {\n cleanupAnimations();\n cleanupAnimations = null;\n canvasEntrance.cancel();\n canvasEntrance = null;\n render();\n return;\n }\n pendingResize = true;\n return;\n }\n render();\n }\n\n /**\n * Apply a search selection change: the effective highlight is the authored\n * baseline plus the selected values, so clearing every chip restores the\n * authored highlight exactly. Fires onHighlightChange on every change.\n */\n function handleSearchChange(selected: string[]): void {\n const merged = [...searchBaseline];\n for (const v of selected) {\n if (!merged.includes(v)) merged.push(v);\n }\n setHighlight(merged.length > 0 ? merged : null);\n options?.onHighlightChange?.(merged);\n }\n\n function setHighlight(values: string[] | null): void {\n if (destroyed) return;\n if (isLayerSpec(currentSpec) || isGraphSpec(currentSpec as unknown as Record<string, unknown>))\n return;\n const spec = currentSpec as ChartSpec;\n const colorEnc = spec.encoding?.color;\n if (!colorEnc || typeof colorEnc !== 'object' || !('field' in colorEnc)) return;\n const current = (colorEnc as { highlight?: string | string[] }).highlight;\n if (!values?.length && !current) return;\n const updatedColor = { ...colorEnc };\n if (values && values.length > 0) {\n updatedColor.highlight = values;\n } else {\n delete updatedColor.highlight;\n }\n currentSpec = {\n ...spec,\n encoding: { ...spec.encoding, color: updatedColor },\n } as ChartSpec;\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: 'gif', exportOptions?: GIFExportOptions): Promise<Blob>;\n function doExport(format: 'csv'): string;\n function doExport(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg' | 'gif' | 'csv',\n exportOptions?: ExportOptions | GIFExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) {\n throw new Error('Chart is not rendered yet');\n }\n // In canvas mode the on-screen SVG has no dots, no gridlines and no\n // background -- the canvas owns those. Serializing it would export an\n // empty chart, so every format works off a materialized SVG that has the\n // missing half folded back in. Raster formats force the vector path: they\n // are becoming pixels anyway, and it buys parity with SVG mode for free.\n const svg =\n canvasLayer && currentLayout.markRenderMode === 'canvas'\n ? materializeCanvasModeSVG(currentLayout, {\n forceVector: format === 'png' || format === 'jpg' || format === 'gif',\n })\n : svgElement;\n // The resolved theme, defaulted into the export options, so class-based\n // chrome fills (metrics, brand dot, legend) survive serialization away from\n // the page stylesheet. An explicit options.theme still wins.\n const theme = 'theme' in currentLayout ? currentLayout.theme : undefined;\n const withTheme = <T extends { theme?: unknown }>(o: T | undefined): T =>\n ({ theme, ...(o ?? {}) }) as T;\n\n switch (format) {\n case 'svg':\n return exportSVG(svg);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svg, withTheme(exportOptions as SVGExportOptions | undefined));\n case 'png':\n return exportPNG(svg, withTheme(exportOptions as ExportOptions | undefined));\n case 'jpg':\n return exportJPG(svg, withTheme(exportOptions as ExportOptions | undefined));\n case 'gif': {\n // Dynamic import keeps the GIF encoder (optional `gifenc` peer) out of\n // the core bundle — only consumers who export GIFs load this chunk.\n const gifOptions = withTheme(exportOptions as GIFExportOptions | undefined);\n const gifBlob: Promise<Blob> = import('./export-gif').then(({ exportGIF }) =>\n exportGIF(svg, currentLayout.animation, gifOptions),\n );\n return gifBlob;\n }\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 any in-progress data-update transition\n if (transitionHandle) {\n transitionHandle.cancel();\n transitionHandle = null;\n }\n transitionSnapshot = null;\n\n if (cleanupAnimations) {\n cleanupAnimations();\n cleanupAnimations = null;\n pendingResize = false;\n }\n cancelAnimations(svgElement);\n\n cleanupTooltipEvents?.();\n cleanupTooltipEvents = null;\n cleanupVoronoiEvents?.();\n cleanupVoronoiEvents = null;\n cleanupCanvasEvents?.();\n cleanupCanvasEvents = null;\n // Cancel before destroying the layer, matching render()/resize(). The\n // layer's own destroy() stops the scheduler, so this is not a live timer;\n // what it drops is this closure's reference to the layer state, whose\n // typed arrays scale with the point count.\n canvasEntrance?.cancel();\n canvasEntrance = null;\n canvasLayer?.destroy();\n canvasLayer = null;\n cleanupKeyboardNav?.();\n cleanupKeyboardNav = null;\n cleanupLegend?.();\n cleanupLegend = null;\n cleanupChartEvents?.();\n cleanupChartEvents = null;\n cleanupAnnotationDrag?.();\n cleanupAnnotationDrag = null;\n cleanupEditDrags?.();\n cleanupEditDrags = null;\n cleanupSelection?.();\n cleanupSelection = null;\n cleanupKeyboardEdit?.();\n cleanupKeyboardEdit = null;\n if (textEditCleanup) {\n textEditCleanup();\n textEditCleanup = null;\n isTextEditingActive = false;\n }\n selectedElement = null;\n overlayElement = null;\n if (seriesSearch) {\n seriesSearch.destroy();\n seriesSearch = null;\n }\n if (youDrawIt) {\n youDrawIt.destroy();\n youDrawIt = null;\n }\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 // Recompile once after webfonts load. On real devices the primary font\n // (e.g. Inter via display=swap) often swaps in after first paint, changing\n // text metrics; without a re-measure, titles wrap wrong and labels collide.\n // Desktop Chrome has the font cached, so it renders 'ready' immediately.\n const pending = scheduleFontReload(\n fontFamily,\n () => !destroyed,\n () => {\n // Mark the reload owed, then trigger a recompile. render() flips the\n // attribute to 'ready' once it actually recompiles — including the\n // pendingResize replay after the entrance animation finishes.\n fontsReloadPending = true;\n resize();\n },\n );\n container.dataset.ocFontsState = pending ? 'pending' : 'ready';\n\n // Set up responsive resize\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, (width, height) => {\n // Self-induced-resize guard, scoped to latched-auto mounts: growing\n // the SVG grows the container, which re-fires this observer. A fire\n // whose height matches the SVG we just rendered (and whose width is\n // unchanged) is our own echo — re-rendering on it would loop; the\n // 16ms debounce alone doesn't break the cycle.\n if (isAutoHeight === true) {\n const widthChanged = width !== lastRenderedWidth;\n const selfInducedHeight = height === lastRenderedSvgHeight;\n if (!widthChanged && selfInducedHeight) return;\n if (!selfInducedHeight) {\n // Any other height delta is host-driven: un-latch so the next\n // measure re-derives (and re-latches explicit if the container\n // now reports a height that isn't ours).\n isAutoHeight = null;\n }\n resize();\n return;\n }\n // Explicit-height (and not-yet-latched) mounts keep today's\n // re-render-on-every-fire behavior.\n resize();\n });\n }\n\n return {\n update,\n beginManualUpdate,\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 setHighlight,\n resetDrawing(): void {\n if (destroyed) return;\n youDrawIt?.reset();\n },\n revealDrawing(): void {\n if (destroyed) return;\n youDrawIt?.reveal();\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 * Compute the total entrance-animation time for a rendered SVG, in ms.\n *\n * Reads the timing from the CSS custom properties the renderer stamps\n * (`--oc-animation-duration`, `--oc-animation-stagger`, `--oc-annotation-delay`)\n * and counts animated elements to derive the last element's stagger delay.\n * Formula: `totalStagger + duration + annotationDelay + 500ms buffer`.\n *\n * Shared by `setupAnimationCleanup` (to time the oc-animate removal) and by GIF\n * export (to size the capture window), so the two never drift.\n */\nexport function computeAnimationDuration(svg: SVGElement): number {\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 const animatedElements = svg.querySelectorAll('[data-animation-index]').length;\n const totalStagger = stagger * Math.max(0, animatedElements - 1);\n\n return totalStagger + duration + annotationDelay + 500;\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(\n svg: SVGElement,\n onComplete?: () => void,\n totalMs?: number,\n): () => void {\n // `totalMs` overrides the DOM-derived estimate. Canvas mark mode needs it:\n // computeAnimationDuration counts [data-animation-index] ELEMENTS, and canvas\n // mode emits no point elements at all, so the estimate collapses to roughly\n // one element's worth of time. The timer would then fire mid-entrance,\n // nulling cleanupAnimations, replaying a deferred resize into a teardown, and\n // letting update() past the entrance-in-flight gate while the canvas tween is\n // still writing alpha.\n const totalTime = totalMs ?? computeAnimationDuration(svg);\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","import type { Annotation, ChartEventHandlers, ChartLayout } from '@opendata-ai/openchart-core';\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 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 */\nexport function wireChartEvents(\n svg: SVGElement,\n layout: ChartLayout,\n specAnnotations: Annotation[],\n handlers: ChartEventHandlers,\n): () => void {\n const cleanups: Array<() => void> = [];\n const markDataMap = buildMarkDataMap(layout);\n\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 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","import type { ChartLayout, TooltipContent } from '@opendata-ai/openchart-core';\nimport { getRepresentativeColor } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\n\ninterface SeriesPoint {\n x: number;\n y: number;\n datum: Record<string, unknown>;\n tooltip?: TooltipContent;\n}\n\ninterface SeriesGroup {\n seriesKey: string;\n color: string;\n pointsByX: Map<number, SeriesPoint>;\n}\n\nfunction snapKey(x: number): number {\n return Math.round(x);\n}\n\nfunction collectSeriesGroups(layout: ChartLayout): SeriesGroup[] {\n // Dedupe by seriesKey: area charts emit BOTH an AreaMark and a derived\n // LineMark per series. Without dedupe, single-series area charts show\n // \"line-0\" / \"area-1\" in the tooltip instead of the actual data fields.\n // Prefer the line mark (same logic as endpoint-labels).\n const byKey = new Map<string, SeriesGroup>();\n const markTypeByKey = new Map<string, 'line' | 'area'>();\n for (let i = 0; i < layout.marks.length; i++) {\n const mark = layout.marks[i];\n if ((mark.type === 'line' || mark.type === 'area') && mark.dataPoints?.length) {\n const key = mark.seriesKey ?? '__default__';\n const existingType = markTypeByKey.get(key);\n if (existingType === 'line' && mark.type === 'area') continue;\n const color = mark.type === 'line' ? mark.stroke : getRepresentativeColor(mark.fill);\n const pointsByX = new Map<number, SeriesPoint>();\n for (const dp of mark.dataPoints) {\n pointsByX.set(snapKey(dp.x), { ...dp });\n }\n byKey.set(key, { seriesKey: key, color, pointsByX });\n markTypeByKey.set(key, mark.type);\n }\n }\n return Array.from(byKey.values());\n}\n\nfunction collectSnapXs(groups: SeriesGroup[]): number[] {\n const seen = new Set<number>();\n for (const g of groups) {\n for (const k of g.pointsByX.keys()) seen.add(k);\n }\n return Array.from(seen).sort((a, b) => a - b);\n}\n\nfunction findNearestX(sortedXs: number[], x: number): number | null {\n if (sortedXs.length === 0) return null;\n let lo = 0;\n let hi = sortedXs.length - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (sortedXs[mid] < x) lo = mid + 1;\n else hi = mid;\n }\n const candidate = sortedXs[lo];\n if (lo > 0) {\n const prev = sortedXs[lo - 1];\n if (Math.abs(prev - x) < Math.abs(candidate - x)) return prev;\n }\n return candidate;\n}\n\nfunction buildSliceTooltip(\n hits: Array<{ group: SeriesGroup; point: SeriesPoint }>,\n): TooltipContent | null {\n if (hits.length === 0) return null;\n\n const title = hits[0].point.tooltip?.title;\n const fields: Array<{ label: string; value: string; color?: string }> = [];\n\n const isMulti = hits.length > 1;\n for (const { group, point } of hits) {\n const tip = point.tooltip;\n if (!tip) continue;\n if (isMulti) {\n const yField =\n tip.fields.find((f) => !f.color && f.label !== title) ??\n tip.fields[tip.fields.length - 1] ??\n null;\n if (!yField) continue;\n fields.push({\n label: group.seriesKey,\n value: yField.value,\n color: group.color,\n });\n } else {\n for (const f of tip.fields) {\n fields.push({ ...f, color: f.color ?? group.color });\n }\n }\n }\n\n if (fields.length === 0) return null;\n return { title, fields };\n}\n\n/**\n * Wire snap-to-x multi-series tooltip events for line/area charts.\n * On mousemove over the chart area we find the nearest x in the union of all\n * series, render one snap dot per series at that x, and show one merged\n * tooltip listing every series' value.\n */\nexport function 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 groups = collectSeriesGroups(layout);\n if (groups.length === 0) return () => {};\n\n const snapXs = collectSnapXs(groups);\n if (snapXs.length === 0) return () => {};\n\n const crosshair = svg.querySelector('[data-crosshair]') as SVGLineElement | null;\n const dotsLayer = svg.querySelector('[data-snap-dots]') as SVGGElement | null;\n\n const dots: SVGCircleElement[] = [];\n if (dotsLayer) {\n while (dotsLayer.firstChild) dotsLayer.removeChild(dotsLayer.firstChild);\n for (const group of groups) {\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n circle.setAttribute('r', '4');\n circle.setAttribute('fill', layout.theme.colors.background);\n circle.setAttribute('stroke', group.color);\n circle.setAttribute('stroke-width', '2');\n circle.setAttribute('pointer-events', 'none');\n circle.style.display = 'none';\n dotsLayer.appendChild(circle);\n dots.push(circle);\n }\n }\n\n const positionAt = (svgX: number, _svgY: number, viewBoxToContainer: number): boolean => {\n const snappedX = findNearestX(snapXs, svgX);\n if (snappedX === null) return false;\n\n const hits: Array<{ group: SeriesGroup; point: SeriesPoint }> = [];\n let anchorY = 0;\n let anchorCount = 0;\n for (let i = 0; i < groups.length; i++) {\n const group = groups[i];\n const point = group.pointsByX.get(snappedX);\n const dot = dots[i];\n if (point) {\n hits.push({ group, point });\n anchorY += point.y;\n anchorCount += 1;\n if (dot) {\n dot.setAttribute('cx', String(point.x));\n dot.setAttribute('cy', String(point.y));\n dot.style.display = '';\n }\n } else if (dot) {\n dot.style.display = 'none';\n }\n }\n\n if (crosshair) {\n crosshair.setAttribute('x1', String(snappedX));\n crosshair.setAttribute('x2', String(snappedX));\n crosshair.style.display = '';\n }\n\n const tooltip = buildSliceTooltip(hits);\n if (!tooltip) return false;\n\n const containerAnchorX = snappedX * viewBoxToContainer;\n const containerAnchorY = anchorCount > 0 ? (anchorY / anchorCount) * viewBoxToContainer : 0;\n tooltipManager.show(tooltip, containerAnchorX, containerAnchorY, {\n placement: 'right',\n });\n return true;\n };\n\n const toSvgCoords = (clientX: number, clientY: number) => {\n const svgEl = svg as unknown as SVGSVGElement;\n const svgRect = svgEl.getBoundingClientRect();\n const viewBox = svgEl.viewBox?.baseVal;\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 = (clientX - svgRect.left) * scaleX;\n const svgY = (clientY - svgRect.top) * scaleY;\n const viewBoxToContainer = scaleX > 0 ? 1 / scaleX : 1;\n return { svgX, svgY, viewBoxToContainer };\n };\n\n const handleMouseMove = (e: Event) => {\n const me = e as MouseEvent;\n const { svgX, svgY, viewBoxToContainer } = toSvgCoords(me.clientX, me.clientY);\n positionAt(svgX, svgY, viewBoxToContainer);\n };\n\n const hideAll = () => {\n if (crosshair) crosshair.style.display = 'none';\n for (const dot of dots) dot.style.display = 'none';\n tooltipManager.hide();\n };\n\n const handleTouch = (e: Event) => {\n const te = e as TouchEvent;\n if (te.touches.length === 0) return;\n const t = te.touches[0];\n const { svgX, svgY, viewBoxToContainer } = toSvgCoords(t.clientX, t.clientY);\n if (te.cancelable) te.preventDefault();\n positionAt(svgX, svgY, viewBoxToContainer);\n };\n\n overlay.addEventListener('mousemove', handleMouseMove);\n overlay.addEventListener('mouseleave', hideAll);\n overlay.addEventListener('touchstart', handleTouch, { passive: false });\n overlay.addEventListener('touchmove', handleTouch, { passive: false });\n overlay.addEventListener('touchend', hideAll);\n\n return () => {\n overlay.removeEventListener('mousemove', handleMouseMove);\n overlay.removeEventListener('mouseleave', hideAll);\n overlay.removeEventListener('touchstart', handleTouch);\n overlay.removeEventListener('touchmove', handleTouch);\n overlay.removeEventListener('touchend', hideAll);\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\nexport interface 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;\n}\n\nexport function createDragHandler(config: DragConfig): () => void {\n const { element, svg, onMove, onEnd, setDragging, threshold = 3 } = config;\n const cleanups: Array<() => void> = [];\n\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 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 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 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 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 const handleMouseDown = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n mouseEvent.preventDefault();\n startDrag(mouseEvent.clientX, mouseEvent.clientY);\n };\n\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 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 svg.style.userSelect = '';\n };\n}\n","import {\n type Annotation,\n type AnnotationOffset,\n type ChartLayout,\n type ChartSpec,\n type ChromeKey,\n type ElementEdit,\n elementRef,\n type GraphSpec,\n type RangeAnnotation,\n type RefLineAnnotation,\n type TextAnnotation,\n} from '@opendata-ai/openchart-core';\nimport { createDragHandler } from './drag-handler';\nimport { invertScale } from './invert';\n\n/**\n * Wire drag-to-reposition on text annotation labels.\n * Returns a cleanup function to remove all listeners.\n */\nexport function 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 annotationG.style.cursor = 'grab';\n\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 const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n const arrowhead = annotationG.querySelector('polyline.oc-annotation-arrowhead');\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 annotationG.setAttribute('transform', `translate(${dx}, ${dy})`);\n\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2 - dx));\n connectorLine.setAttribute('y2', String(origY2 - dy));\n }\n\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 annotationG.removeAttribute('transform');\n\n if (connectorLine && !hasCurvedConnector) {\n connectorLine.setAttribute('x2', String(origX2));\n connectorLine.setAttribute('y2', String(origY2));\n }\n\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 onAnnotationEdit?.(textAnnotation, newOffset);\n onEdit?.({\n type: 'annotation',\n element: elementRef.annotation(\n index,\n textAnnotation.id,\n `/annotations/${index}/offset`,\n ),\n annotation: textAnnotation,\n offset: newOffset,\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 * Wire drag on connector endpoint handles for text annotations.\n * Returns a cleanup function that removes handles and all listeners.\n */\nexport function 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 const connectorLine = annotationG.querySelector('line.oc-annotation-connector');\n const curvedPath = annotationG.querySelector('path.oc-annotation-connector');\n if (!connectorLine && !curvedPath) continue;\n\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 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 // The open-V arrowhead is a polyline \"baseLeft tip baseRight\": the tip is\n // the middle point.\n const arrowhead = annotationG.querySelector('polyline.oc-annotation-arrowhead');\n const points = arrowhead?.getAttribute('points')?.split(' ') ?? [];\n const [px, py] = (points[1] ?? '0,0').split(',');\n toX = Number(px) || 0;\n toY = Number(py) || 0;\n }\n\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 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 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 element: elementRef.annotation(\n index,\n textAnnotation.id,\n `/annotations/${index}/connectorOffset/${ep.name}`,\n ),\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 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 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 * Wire drag on range and refline annotation labels.\n * Returns a cleanup function.\n */\nexport function 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 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 element: elementRef.annotation(\n index,\n specAnnotation.id,\n `/annotations/${index}/labelOffset`,\n ),\n annotation: specAnnotation as RangeAnnotation,\n labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy },\n });\n } else {\n onEdit({\n type: 'refline-label',\n element: elementRef.annotation(\n index,\n specAnnotation.id,\n `/annotations/${index}/labelOffset`,\n ),\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 * Wire drag on chrome text elements (title, subtitle, source, byline, footer).\n * Returns a cleanup function.\n */\nexport function 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 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 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 * Wire drag on the legend group.\n * Returns a cleanup function.\n */\nexport function wireLegendDrag(\n svg: SVGElement,\n spec: ChartSpec | GraphSpec,\n onEdit: (edit: ElementEdit) => void,\n setDragging: (dragging: boolean) => void,\n): () => void {\n // The color legend: it owns `spec.legend.offset`, which is what a drag writes\n // back. The size legend is not draggable and must not be picked up here.\n const legendG = svg.querySelector('.oc-legend:not(.oc-legend--size)') as SVGGElement | null;\n if (!legendG) return () => {};\n\n const cleanups: Array<() => void> = [];\n\n const legendConfig = 'legend' in spec ? spec.legend : undefined;\n // Only the chart LegendConfig object carries a draggable `offset`; the graph\n // legend union (boolean | { interactive; counts }) does not.\n const legendOffset =\n legendConfig && typeof legendConfig === 'object' && 'offset' in legendConfig\n ? legendConfig.offset\n : undefined;\n const origLegendDx = legendOffset?.dx ?? 0;\n const origLegendDy = legendOffset?.dy ?? 0;\n\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 * Wire drag on series label elements (.oc-mark-label[data-series]).\n * Returns a cleanup function.\n */\nexport function 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 const rawLabels = 'labels' in spec ? spec.labels : undefined;\n const labelsConfig = typeof rawLabels === 'object' ? rawLabels : undefined;\n\n for (const label of labels) {\n const labelEl = label as SVGTextElement;\n const series =\n labelEl.getAttribute('data-series') ??\n labelEl.closest('[data-series]')?.getAttribute('data-series');\n if (!series) continue;\n\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 * Wire drag on annotation anchor handles (the data-point dot).\n * Dragging the anchor repositions the annotation in data space, emitting\n * new x/y values via onEdit. Returns a cleanup function.\n */\nexport function wireAnchorDrag(\n svg: SVGElement,\n specAnnotations: Annotation[],\n layout: ChartLayout,\n onEdit: ((edit: ElementEdit) => void) | undefined,\n setDragging: (d: boolean) => void,\n): () => void {\n if (!onEdit || !layout.xInvert || !layout.yInvert) return () => {};\n\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 const resolved = layout.annotations.find((a) => a.specIndex === index);\n if (!resolved?.dot) continue;\n\n const anchorX = resolved.dot.x;\n const anchorY = resolved.dot.y;\n\n const handleEl = document.createElementNS(SVG_NS, 'circle') as SVGCircleElement;\n handleEl.setAttribute('class', 'oc-anchor-handle');\n handleEl.setAttribute('cx', String(anchorX));\n handleEl.setAttribute('cy', String(anchorY));\n handleEl.setAttribute('r', '4');\n handleEl.setAttribute('opacity', '0');\n handleEl.setAttribute('fill', 'currentColor');\n handleEl.setAttribute('stroke', 'currentColor');\n handleEl.style.cursor = 'grab';\n annotationG.appendChild(handleEl);\n\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(anchorX + dx));\n handleEl.setAttribute('cy', String(anchorY + dy));\n },\n onEnd: (dx, dy, moved) => {\n handleEl.setAttribute('cx', String(anchorX));\n handleEl.setAttribute('cy', String(anchorY));\n\n if (moved) {\n const newX = invertScale(layout.xInvert!, anchorX + dx);\n const newY = invertScale(layout.yInvert!, anchorY + dy);\n onEdit({\n type: 'annotation-anchor',\n element: elementRef.annotation(index, textAnnotation.id, `/annotations/${index}`),\n annotation: textAnnotation,\n x: newX,\n y: newY,\n });\n }\n },\n setDragging,\n });\n\n cleanups.push(cleanup);\n\n const showHandle = () => {\n handleEl.setAttribute('opacity', '0.6');\n };\n const hideHandle = () => {\n handleEl.setAttribute('opacity', '0');\n };\n\n annotationG.addEventListener('mouseenter', showHandle);\n annotationG.addEventListener('mouseleave', hideHandle);\n cleanups.push(() => {\n annotationG.removeEventListener('mouseenter', showHandle);\n annotationG.removeEventListener('mouseleave', hideHandle);\n handleEl.remove();\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n}\n","import type { ScaleInvert } from '@opendata-ai/openchart-core';\n\n/**\n * Convert a pixel position back to a data-space value using the serialized\n * scale inversion anchors from ChartLayout. For band/point scales, snaps to\n * the nearest domain value. For continuous scales, applies the inverse of\n * the scale transform (log, pow, sqrt, symlog, or linear).\n */\nexport function invertScale(invert: ScaleInvert, pixel: number): string | number {\n // Band/point: snap to nearest domain value\n if (invert.domain && invert.positions && invert.domain.length > 0) {\n let closest = 0;\n let minDist = Infinity;\n for (let i = 0; i < invert.positions.length; i++) {\n const dist = Math.abs(invert.positions[i] - pixel);\n if (dist < minDist) {\n minDist = dist;\n closest = i;\n }\n }\n return invert.domain[closest];\n }\n // Continuous: interpolate in the scale's native space\n const span = invert.bottomPixel - invert.topPixel;\n if (span === 0) return invert.topData;\n const t = (pixel - invert.topPixel) / span;\n\n const { topData, bottomData, scaleType } = invert;\n\n if (scaleType === 'log') {\n if (topData <= 0 || bottomData <= 0) return topData + t * (bottomData - topData);\n return Math.exp(Math.log(topData) + t * (Math.log(bottomData) - Math.log(topData)));\n }\n if (scaleType === 'sqrt') {\n const sqrtTop = Math.sqrt(Math.abs(topData)) * Math.sign(topData);\n const sqrtBottom = Math.sqrt(Math.abs(bottomData)) * Math.sign(bottomData);\n const sqrtVal = sqrtTop + t * (sqrtBottom - sqrtTop);\n return sqrtVal * Math.abs(sqrtVal);\n }\n if (scaleType === 'pow') {\n const powTop = Math.sign(topData) * Math.abs(topData) ** 0.5;\n const powBottom = Math.sign(bottomData) * Math.abs(bottomData) ** 0.5;\n const powVal = powTop + t * (powBottom - powTop);\n return Math.sign(powVal) * Math.abs(powVal) ** 2;\n }\n if (scaleType === 'symlog') {\n const symlog = (x: number) => Math.sign(x) * Math.log1p(Math.abs(x));\n const symexp = (x: number) => Math.sign(x) * Math.expm1(Math.abs(x));\n return symexp(symlog(topData) + t * (symlog(bottomData) - symlog(topData)));\n }\n\n // linear, time, or unspecified\n return topData + t * (bottomData - topData);\n}\n","import type { ChartLayout, TooltipContent } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\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 */\nexport function wireKeyboardNav(\n svg: SVGElement,\n container: HTMLElement,\n tooltipDescriptors: Map<string, TooltipContent>,\n tooltipManager: TooltipManager,\n layout: ChartLayout,\n): () => void {\n container.setAttribute('tabindex', '0');\n container.setAttribute('aria-roledescription', 'chart');\n container.setAttribute('aria-label', layout.a11y.altText);\n\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 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 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","import type { ChartLayout, ElementEdit } from '@opendata-ai/openchart-core';\n\n/**\n * Wire click handlers on legend entries to toggle series visibility.\n * Returns a cleanup function.\n */\nexport function wireLegendInteraction(\n svg: SVGElement,\n _layout: ChartLayout,\n toggleSeries: (series: string) => boolean,\n onLegendToggle?: (series: string, visible: boolean) => void,\n onEdit?: (edit: ElementEdit) => void,\n): () => void {\n // Scoped OUT of the size legend explicitly. Clicking a legend entry toggles a\n // *series*, and a size legend's circles are values, not series -- clicking\n // \"500M\" must not try to hide a series by that name. The size legend already\n // emits no `data-legend-index`, but a bare `[data-legend-index]` sweep would\n // silently pick one up the moment that changed, and the failure would be a\n // click that quietly hides the wrong thing rather than an error.\n const legendEntries = svg.querySelectorAll(\n '.oc-legend:not(.oc-legend--size) [data-legend-index]',\n );\n const cleanups: Array<() => void> = [];\n\n for (const entry of legendEntries) {\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 const nowHidden = toggleSeries(label);\n onLegendToggle?.(label, !nowHidden);\n onEdit?.({ type: 'legend-toggle', series: label, hidden: nowHidden });\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","import type {\n Annotation,\n ChartLayout,\n ChartSpec,\n ChromeKey,\n ElementRef,\n GraphSpec,\n LayerSpec,\n TextAnnotation,\n} from '@opendata-ai/openchart-core';\nimport { elementRef } from '@opendata-ai/openchart-core';\n\n/**\n * Find a DOM element inside the SVG that matches the given ElementRef.\n */\nexport function findElementByRef(svg: SVGElement, ref: ElementRef): SVGElement | null {\n switch (ref.type) {\n case 'annotation': {\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 // The editable legend is the color legend. Excluding the size legend\n // explicitly rather than relying on it rendering second: `querySelector`\n // takes the first match, so a bare `.oc-legend` would silently retarget\n // (and drag) the wrong legend if render order ever changed.\n case 'legend':\n return svg.querySelector('.oc-legend:not(.oc-legend--size)') as SVGElement | null;\n case 'legend-entry':\n return svg.querySelector(\n `.oc-legend:not(.oc-legend--size) [data-legend-index=\"${ref.index}\"]`,\n ) as SVGElement | null;\n }\n}\n\n/**\n * Build an ElementRef from a DOM element's data attributes.\n */\nexport function encodePointerToken(token: string): string {\n return token.replace(/~/g, '~0').replace(/\\//g, '~1');\n}\n\nexport function buildElementRef(\n element: Element,\n _specAnnotations: Annotation[],\n): ElementRef | null {\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, `/annotations/${index}`);\n }\n\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, `/chrome/${key}`);\n }\n\n const seriesLabelEl = element.closest('.oc-mark-label[data-series]');\n if (seriesLabelEl) {\n const series = seriesLabelEl.getAttribute('data-series');\n if (series)\n return elementRef.seriesLabel(series, `/labels/offsets/${encodePointerToken(series)}`);\n }\n\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 // Only the color legend is selectable/editable. A click inside the size legend\n // resolves to no ref rather than reporting the *color* legend's ref, which is\n // what a bare `.oc-legend` match would do.\n const legendEl = element.closest('.oc-legend');\n if (legendEl && !legendEl.classList.contains('oc-legend--size'))\n return elementRef.legend('/legend');\n\n return null;\n}\n\n/**\n * Get an ordered list of all editable ElementRefs from the current spec and layout.\n */\nexport function getEditableElements(\n spec: ChartSpec | LayerSpec | GraphSpec,\n layout: ChartLayout,\n): ElementRef[] {\n const refs: ElementRef[] = [];\n\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 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 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 if ('entries' in layout.legend && 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.\n */\nexport function 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 */\nexport function getElementText(\n ref: ElementRef,\n spec: ChartSpec | LayerSpec | GraphSpec,\n): 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 */\nexport function 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 */\nexport function 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 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 * Create a visually-hidden data table from the chart's a11y fallback data.\n */\nexport function 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 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 // totalRows is only set when the table was truncated, so its presence is the\n // signal to tell the reader how many rows they are not getting.\n const totalRows = layout.a11y.totalRows;\n if (totalRows != null) {\n const caption = document.createElement('caption');\n caption.textContent = `Showing first ${(data.length - 1).toLocaleString()} of ${totalRows.toLocaleString()} rows; full data via CSV export`;\n table.appendChild(caption);\n }\n\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 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","import type { TooltipContent } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\n\n/**\n * Wire tooltip events on mark elements inside an SVG.\n * Returns a cleanup function to remove all listeners.\n */\nexport function 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 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 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 const handleMouseLeave = () => {\n tooltipManager.hide();\n };\n\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 * Canvas-backed text measurement factory.\n *\n * Shared by mount.ts (charts) and sankey-mount.ts (sankey diagrams) so both\n * pipelines get accurate browser-measured text widths instead of the heuristic\n * fallback. Falls back to the heuristic when canvas isn't available (e.g. SSR).\n *\n * The font family is passed in (resolved from the container's --oc-font-family\n * or the spec theme) rather than hardcoded, so measurement matches what the SVG\n * text actually renders with. This matters on real devices where the primary\n * webfont (e.g. Inter) loads late: measuring against the wrong font produces\n * wrong widths and mangles layout.\n */\n\nimport type { MeasureTextFn } from '@opendata-ai/openchart-core';\nimport { estimateTextWidth } from '@opendata-ai/openchart-core';\n\nconst DEFAULT_FONT_FAMILY = 'Inter, sans-serif';\n\nexport function createMeasureText(fontFamily: string = DEFAULT_FONT_FAMILY): 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 {\n width: estimateTextWidth(text, fontSize, fontWeight ?? 400),\n height: fontSize * 1.2,\n };\n }\n\n const weight = fontWeight ?? 400;\n ctx.font = `${weight} ${fontSize}px ${fontFamily}`;\n const metrics = ctx.measureText(text);\n return {\n width: metrics.width,\n height: fontSize * 1.2,\n };\n };\n}\n\n/**\n * Resolve the font family a container's SVG text will actually render with.\n *\n * Reads the --oc-font-family custom property (set by tokens.css once .oc-root\n * is applied, or overridden per-spec by the theme resolver), falling back to\n * the container's computed fontFamily, then to the default Inter stack. Returns\n * the previous hardcoded stack when there is no DOM (SSR) or no computed style.\n */\nexport function resolveFontFamily(container: HTMLElement): string {\n if (typeof window === 'undefined' || typeof getComputedStyle !== 'function') {\n return DEFAULT_FONT_FAMILY;\n }\n try {\n const style = getComputedStyle(container);\n const custom = style.getPropertyValue('--oc-font-family').trim();\n if (custom) return custom;\n const computed = style.fontFamily?.trim();\n if (computed) return computed;\n } catch {\n // getComputedStyle can throw on detached nodes in some engines; fall through.\n }\n return DEFAULT_FONT_FAMILY;\n}\n\n/**\n * The first family in a CSS font stack, with surrounding quotes stripped, e.g.\n * `'\"Inter Variable\", Inter, sans-serif'` -> `Inter Variable`. Used to build a\n * representative check string for document.fonts.check().\n */\nexport function primaryFontName(fontFamily: string): string {\n const first = fontFamily.split(',')[0]?.trim() ?? '';\n return first.replace(/^[\"']|[\"']$/g, '').trim();\n}\n\n/**\n * True when the primary font of the resolved stack is not yet loaded and a\n * later document.fonts.ready may change text metrics. False when fonts are\n * ready, unavailable (SSR / no FontFaceSet), or the primary is a generic family.\n */\nexport function fontsPending(fontFamily: string): boolean {\n if (typeof document === 'undefined') return false;\n const fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n if (!fonts || typeof fonts.check !== 'function') return false;\n const name = primaryFontName(fontFamily);\n if (!name) return false;\n const generics = new Set([\n 'sans-serif',\n 'serif',\n 'monospace',\n 'system-ui',\n 'cursive',\n 'fantasy',\n 'ui-sans-serif',\n 'ui-serif',\n 'ui-monospace',\n ]);\n if (generics.has(name.toLowerCase())) return false;\n try {\n return !fonts.check(`12px \"${name}\"`);\n } catch {\n return false;\n }\n}\n\n/**\n * Run `onReady` exactly once after webfonts finish loading, if they were\n * pending at call time. `isAlive` is checked before invoking so a destroyed\n * chart is never re-rendered. Returns the initial pending state so callers can\n * set their `ocFontsState` dataset flag. No-op (returns false) under SSR or\n * when the primary font is already loaded.\n */\nexport function scheduleFontReload(\n fontFamily: string,\n isAlive: () => boolean,\n onReady: () => void,\n): boolean {\n if (!fontsPending(fontFamily)) return false;\n const fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n if (!fonts?.ready) return false;\n fonts.ready.then(() => {\n if (isAlive()) onReady();\n });\n return true;\n}\n","import type { DarkMode } from '@opendata-ai/openchart-core';\n\n/**\n * Resolve a DarkMode option to a boolean. 'auto' consults the OS preference\n * via matchMedia; environments without matchMedia (SSR, happy-dom) resolve\n * to light.\n */\nexport function 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 * Pointer interactions for the canvas mark layer.\n *\n * In SVG mode each mark is its own element and the browser does hit-testing for\n * us (`interactions/tooltip-events.ts`, `interactions/chart-events.ts`). Canvas\n * has no elements, so listeners live on the canvas itself and hit-testing goes\n * through the layer's quadtree. Payload shapes are reproduced from\n * `chart-events.ts` rather than imported: that module walks `[data-mark-id]`\n * elements, which don't exist here.\n */\n\nimport type { ChartEventHandlers, TooltipContent } from '@opendata-ai/openchart-core';\nimport type { TooltipManager } from '../tooltip';\nimport type { ScatterCanvasLayer } from './layer';\n\n/** Hit tolerance in CSS px, beyond the point's own radius. */\nconst HIT_TOLERANCE_MOUSE = 8;\n/** Fingers are blunter than mice. */\nconst HIT_TOLERANCE_TOUCH = 24;\n\nexport interface CanvasInteractionOptions {\n layer: ScatterCanvasLayer;\n /** The chart SVG. Coordinates are reported relative to its box, matching SVG mode. */\n svg: SVGElement;\n tooltipDescriptors: Map<string, TooltipContent>;\n tooltipManager: TooltipManager;\n options?: ChartEventHandlers;\n}\n\n/**\n * Wire pointer listeners on the layer's canvas. Returns a cleanup function that\n * removes them.\n */\nexport function wireCanvasInteractions({\n layer,\n svg,\n tooltipDescriptors,\n tooltipManager,\n options,\n}: CanvasInteractionOptions): () => void {\n const canvas = layer.canvas;\n const state = layer.state;\n\n /**\n * Cached element boxes.\n *\n * `getBoundingClientRect()` forces layout, and reading two of them on every\n * `pointermove` is exactly the per-event cost this layer exists to avoid.\n * Neither box moves on its own: a container resize tears the layer down and\n * `render()` rebuilds it, so within one layer's life the boxes shift only\n * when the page moves underneath them. Invalidate on scroll (capture phase,\n * so ancestor scroll containers count), on resize, and on `pointerenter` —\n * a layout shift with no scroll and no resize (content above the chart\n * expanding, a font loading) still moves the boxes, and starting each hover\n * session with a fresh measurement bounds that staleness to mid-hover\n * shifts. Re-measure lazily on the next event that needs a box.\n */\n let svgRect: DOMRect | null = null;\n let canvasRect: DOMRect | null = null;\n const invalidateRects = (): void => {\n svgRect = null;\n canvasRect = null;\n };\n\n /**\n * Container-relative coordinates. `tooltip-events.ts` measures against the SVG\n * box and the tooltip manager positions inside the same container, so the\n * canvas must use the same origin — not its own rect, which can differ if the\n * SVG scales with the container.\n */\n function toLocal(e: PointerEvent): { x: number; y: number } {\n if (!svgRect) svgRect = svg.getBoundingClientRect();\n return { x: e.clientX - svgRect.left, y: e.clientY - svgRect.top };\n }\n\n /** Layout-space coordinates for hit testing (the canvas is 1:1 with layout). */\n function toCanvas(e: PointerEvent): { x: number; y: number } {\n if (!canvasRect) canvasRect = canvas.getBoundingClientRect();\n return { x: e.clientX - canvasRect.left, y: e.clientY - canvasRect.top };\n }\n\n function tolerance(e: PointerEvent): number {\n return e.pointerType === 'touch' ? HIT_TOLERANCE_TOUCH : HIT_TOLERANCE_MOUSE;\n }\n\n function markPayload(index: number, local: { x: number; y: number }, e: PointerEvent) {\n const datum = state.marks.data[index];\n return {\n datum: (datum ?? {}) as Record<string, unknown>,\n series: undefined,\n position: local,\n event: e as unknown as MouseEvent,\n };\n }\n\n function clearHover(): void {\n if (state.hoverIndex === -1) return;\n state.hoverIndex = -1;\n layer.scheduleRepaint();\n }\n\n const handlePointerMove = (e: PointerEvent): void => {\n if (layer.isInteractionSuspended()) return;\n const { x, y } = toCanvas(e);\n const hit = layer.hitTest(x, y, tolerance(e));\n\n if (!hit) {\n tooltipManager.hide();\n if (state.hoverIndex !== -1) {\n clearHover();\n options?.onMarkLeave?.();\n }\n return;\n }\n\n const local = toLocal(e);\n const content = tooltipDescriptors.get(state.marks.markIds[hit.index]);\n if (content) tooltipManager.show(content, local.x, local.y);\n\n const changed = state.hoverIndex !== hit.index;\n if (changed) {\n state.hoverIndex = hit.index;\n layer.scheduleRepaint();\n options?.onMarkHover?.(markPayload(hit.index, local, e));\n }\n };\n\n const handlePointerDown = (e: PointerEvent): void => {\n if (layer.isInteractionSuspended()) return;\n if (!options?.onMarkClick) return;\n const { x, y } = toCanvas(e);\n const hit = layer.hitTest(x, y, tolerance(e));\n if (!hit) return;\n options.onMarkClick(markPayload(hit.index, toLocal(e), e));\n };\n\n const handlePointerLeave = (): void => {\n if (layer.isInteractionSuspended()) return;\n tooltipManager.hide();\n if (state.hoverIndex !== -1) {\n clearHover();\n options?.onMarkLeave?.();\n }\n };\n\n canvas.addEventListener('pointermove', handlePointerMove);\n canvas.addEventListener('pointerdown', handlePointerDown);\n canvas.addEventListener('pointerleave', handlePointerLeave);\n canvas.addEventListener('pointerenter', invalidateRects);\n // Capture phase: a scroll in any ancestor moves our boxes, and scroll events\n // from those do not bubble.\n window.addEventListener('scroll', invalidateRects, true);\n window.addEventListener('resize', invalidateRects);\n\n return () => {\n canvas.removeEventListener('pointermove', handlePointerMove);\n canvas.removeEventListener('pointerdown', handlePointerDown);\n canvas.removeEventListener('pointerleave', handlePointerLeave);\n canvas.removeEventListener('pointerenter', invalidateRects);\n window.removeEventListener('scroll', invalidateRects, true);\n window.removeEventListener('resize', invalidateRects);\n };\n}\n","/**\n * Canvas animation scheduler.\n *\n * Owns the set of running rAF-driven animations and the first-frame arming.\n * The mount's render loop ticks the scheduler once per frame and re-arms rAF\n * only while animations are active — a continuous loop that costs nothing when\n * idle (the base render loop stays strictly dirty-flag).\n *\n * Shared by the graph canvas and the scatter canvas mark layer.\n *\n * Two hazards this design guards against:\n *\n * 1. **First-frame arming is the scheduler's job, not the call site's.** `add()`\n * invokes the injected `requestFrame` on the idle→active transition, so no\n * call site can forget to arm the first frame.\n *\n * 2. **Reentrancy.** A tween's `onDone` may call `update()` / `destroy()`, which\n * trigger `finishAll` / `cancelAll` mid-tick. `tick()` iterates a SNAPSHOT of\n * the animation list; `remove` / `cancelAll` are safe to call mid-tick.\n */\n\n/** A single rAF-driven animation. */\nexport interface Animation {\n /** Advance to `now` (ms). Returns true while running, false when complete. */\n tick(now: number): boolean;\n /** Jump to the final state and fire completion callbacks. */\n finish(): void;\n /** Stop immediately without applying the final state or firing completion. */\n cancel(): void;\n}\n\n/** Manages a set of active animations and drives frame arming. */\nexport class AnimationScheduler {\n private animations = new Set<Animation>();\n private readonly requestFrame: () => void;\n\n /**\n * @param requestFrame Called on the idle→active transition to arm the first\n * frame (typically the mount's `scheduleRender`).\n */\n constructor(requestFrame: () => void) {\n this.requestFrame = requestFrame;\n }\n\n /** Add an animation. Arms the first frame if the scheduler was idle. */\n add(a: Animation): void {\n const wasIdle = this.animations.size === 0;\n this.animations.add(a);\n if (wasIdle) this.requestFrame();\n }\n\n /** Remove an animation without finishing or cancelling it. Safe mid-tick. */\n remove(a: Animation): void {\n this.animations.delete(a);\n }\n\n /**\n * Advance all animations to `now`. Completed animations are removed. Returns\n * true if any animation ran this frame (so the caller marks the frame dirty).\n *\n * Iterates a snapshot so an `onDone` that mutates the set (via update/destroy)\n * can't corrupt the loop.\n */\n tick(now: number): boolean {\n if (this.animations.size === 0) return false;\n const snapshot = [...this.animations];\n let ran = false;\n for (const a of snapshot) {\n // An earlier animation's onDone may have removed this one mid-loop.\n if (!this.animations.has(a)) continue;\n ran = true;\n const running = a.tick(now);\n if (!running) this.animations.delete(a);\n }\n return ran;\n }\n\n /** True while any animation is active (drives rAF re-arming). */\n get active(): boolean {\n return this.animations.size > 0;\n }\n\n /** Cancel every animation (no final state, no onDone). Used on teardown. */\n cancelAll(): void {\n const snapshot = [...this.animations];\n this.animations.clear();\n for (const a of snapshot) a.cancel();\n }\n\n /** Finish every animation (snap to final, fire onDone). Used before update(). */\n finishAll(): void {\n const snapshot = [...this.animations];\n this.animations.clear();\n for (const a of snapshot) a.finish();\n }\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","/**\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';\n\n/** Minimum shape a spatial-index entry must have. */\nexport interface SpatialEntry {\n x: number;\n y: number;\n radius: number;\n}\n\nexport class SpatialIndex<T extends SpatialEntry = SpatialEntry> {\n private tree: Quadtree<T> | null = null;\n private nodes: T[] = [];\n private maxRadius = 0;\n private generation = 0;\n\n /** Rebuild the quadtree from the current set of positioned nodes. */\n rebuild(nodes: T[]): 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<T>()\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): T | 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: T | 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): T[] {\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: T[] = [];\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 * Canvas motion primitives: easings, reduced-motion detection, and a generic\n * time-based tween.\n *\n * Canvas marks animate via a rAF scheduler (see scheduler.ts), NOT via CSS\n * keyframes like SVG charts. Only the easing vocabulary is shared with charts\n * (`'smooth'` / `'snappy'`). No `d3-ease` dependency — easings are hand-rolled,\n * matching `transition.ts`'s `cubicOut`.\n */\n\nimport type { AnimationEase } from '@opendata-ai/openchart-core';\nimport { cubicInOut, cubicOut } from './easing';\nimport type { Animation } from './scheduler';\n\n// ---------------------------------------------------------------------------\n// Easings (shared definitions live in easing.ts; re-exported for callers)\n// ---------------------------------------------------------------------------\n\nexport { cubicInOut, cubicOut, linear } from './easing';\n\n/** Resolve a named ease preset to an easing function. */\nexport function resolveEase(ease: AnimationEase): (t: number) => number {\n return ease === 'snappy' ? cubicOut : cubicInOut;\n}\n\n// ---------------------------------------------------------------------------\n// Reduced motion\n// ---------------------------------------------------------------------------\n\n/**\n * Whether the user prefers reduced motion. Mirrors `transition.ts`: guards\n * SSR/happy-dom where matchMedia may be missing or throw.\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n try {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Tween\n// ---------------------------------------------------------------------------\n\n/** Options for {@link createTween}. */\nexport interface TweenOptions {\n /** Duration in ms. A duration <= 0 completes on the first tick. */\n duration: number;\n /** Easing function applied to the normalized 0..1 progress. */\n ease: (t: number) => number;\n /** Called each tick with the eased progress. */\n apply: (t: number) => void;\n /** Called once when the tween completes (not on cancel). */\n onDone?: () => void;\n}\n\n/**\n * Create a time-based tween as an {@link Animation}.\n *\n * The start time locks on the FIRST `tick(now)` call (not at construction), so\n * a tween added while the scheduler is idle starts cleanly on the next frame\n * and tests get deterministic progress from a controllable clock.\n */\nexport function createTween(opts: TweenOptions): Animation {\n const { duration, ease, apply, onDone } = opts;\n let startTime: number | null = null;\n let finished = false;\n\n function settleAt(t: number): void {\n apply(ease(t));\n }\n\n return {\n tick(now: number): boolean {\n if (finished) return false;\n if (startTime === null) startTime = now;\n const elapsed = now - startTime;\n const raw = duration <= 0 ? 1 : Math.min(1, elapsed / duration);\n settleAt(raw);\n if (raw >= 1) {\n finished = true;\n onDone?.();\n return false;\n }\n return true;\n },\n finish(): void {\n if (finished) return;\n finished = true;\n settleAt(1);\n onDone?.();\n },\n cancel(): void {\n finished = true;\n },\n };\n}\n","/**\n * Canvas entrance animation.\n *\n * Replicates the CSS point-mark entrance (`core/src/styles/animation.css`,\n * the `circle.oc-mark-point` rule) on canvas: fade-only, per-point duration\n * 40% of the configured enter duration, delayed by `stagger * markIndex`.\n *\n * Canvas mode emits no point elements, so the CSS rule matches nothing and this\n * scheduler-driven tween stands in for it. Everything else in the chart (axes,\n * chrome, annotations) still animates via CSS on the SVG above.\n */\n\nimport type { ResolvedAnimationPhase } from '@opendata-ai/openchart-core';\nimport type { Animation } from '../motion/scheduler';\nimport { createTween, prefersReducedMotion, resolveEase } from '../motion/tween';\nimport type { ScatterCanvasState } from './types';\n\n/**\n * Maximum total stagger time in ms. Mirrors MAX_TOTAL_STAGGER_MS in\n * `engine/src/compiler/animation.ts` -- duplicated rather than imported\n * because vanilla does not depend on the engine at runtime.\n */\nexport const MAX_TOTAL_STAGGER_MS = 2000;\n\n/** Fraction of the enter duration a single point takes to fade in. */\nexport const POINT_DURATION_FRACTION = 0.4;\n\n/**\n * Clamp the stagger so the whole sweep fits in MAX_TOTAL_STAGGER_MS.\n * Mirrors `clampStaggerDelay` in the engine.\n */\nexport function clampStagger(delay: number, elementCount: number): number {\n if (elementCount <= 1) return 0;\n return Math.min(delay, MAX_TOTAL_STAGGER_MS / elementCount);\n}\n\n/**\n * Total wall-clock time of the canvas entrance, in ms: the last point's delay\n * plus its own fade duration. Used both to drive the tween and to size the\n * cleanup timer, so the two cannot drift.\n */\nexport function computeEntranceDuration(enter: ResolvedAnimationPhase, markCount: number): number {\n const stagger = clampStagger(enter.staggerDelay, markCount);\n const pointDuration = enter.duration * POINT_DURATION_FRACTION;\n return stagger * Math.max(0, markCount - 1) + pointDuration;\n}\n\n/**\n * Per-point alpha at time `t` (ms into the entrance), given its stagger slot.\n * Exported so GIF capture can step the entrance deterministically without a\n * scheduler.\n */\nexport function entranceAlphaAt(\n t: number,\n markIndex: number,\n enter: ResolvedAnimationPhase,\n markCount: number,\n ease: (p: number) => number,\n): number {\n const stagger = clampStagger(enter.staggerDelay, markCount);\n const pointDuration = enter.duration * POINT_DURATION_FRACTION;\n if (pointDuration <= 0) return 1;\n const local = (t - stagger * markIndex) / pointDuration;\n if (local <= 0) return 0;\n if (local >= 1) return 1;\n return ease(local);\n}\n\n/** Write the alpha for every point at time `t` into `state.enterAlpha`. */\nfunction applyEntranceAt(\n state: ScatterCanvasState,\n t: number,\n enter: ResolvedAnimationPhase,\n ease: (p: number) => number,\n): void {\n const alpha = state.enterAlpha;\n if (!alpha) return;\n const { n, animationIndex } = state.marks;\n for (let i = 0; i < n; i++) {\n alpha[i] = entranceAlphaAt(t, animationIndex[i], enter, n, ease);\n }\n}\n\nexport interface EntranceHandle {\n /** Total duration in ms, including the full stagger sweep. */\n totalMs: number;\n /** Stop the entrance without snapping to the final state. */\n cancel(): void;\n}\n\n/**\n * Start the canvas entrance. Returns null when there is nothing to animate\n * (no points, or reduced motion), having already left the state fully opaque.\n */\nexport function playCanvasEntrance(args: {\n state: ScatterCanvasState;\n enter: ResolvedAnimationPhase;\n addAnimation: (a: Animation) => void;\n removeAnimation: (a: Animation) => void;\n requestPaint: () => void;\n onDone?: () => void;\n}): EntranceHandle | null {\n const { state, enter, addAnimation, removeAnimation, requestPaint, onDone } = args;\n const n = state.marks.n;\n\n // Reduced motion and empty charts skip straight to the final state. Leaving\n // enterAlpha null means the renderer paints at full fillOpacity.\n if (n === 0 || prefersReducedMotion()) {\n state.enterAlpha = null;\n requestPaint();\n onDone?.();\n return null;\n }\n\n const ease = resolveEase(enter.ease);\n const totalMs = computeEntranceDuration(enter, n);\n\n const alpha = new Float32Array(n);\n state.enterAlpha = alpha;\n // Seed the from-state synchronously so the first painted frame is the start\n // of the entrance, not a flash of the final state.\n applyEntranceAt(state, 0, enter, ease);\n\n const tween: Animation = createTween({\n duration: totalMs,\n // The per-point windows carry the easing; the driving clock stays linear so\n // stagger slots land at the times the formula says they do.\n ease: (p) => p,\n apply: (p) => {\n applyEntranceAt(state, p * totalMs, enter, ease);\n },\n onDone: () => {\n // Null rather than filled with 1s: the renderer treats null as \"no\n // entrance in flight\" and skips the per-point multiply entirely.\n state.enterAlpha = null;\n onDone?.();\n },\n });\n\n addAnimation(tween);\n requestPaint();\n\n return {\n totalMs,\n cancel() {\n removeAnimation(tween);\n state.enterAlpha = null;\n requestPaint();\n },\n };\n}\n","/**\n * The scatter canvas mark layer: a `<canvas>` sibling of the chart SVG that\n * owns background, gridlines and point marks in canvas mode.\n *\n * Layering: the canvas is absolutely positioned at the container's top-left and\n * inserted BEFORE the SVG, sized to the full figure so canvas coordinates equal\n * layout coordinates. Mount sets `position: relative` on the SVG so both are\n * positioned and DOM order decides the stack (canvas below).\n *\n * The layer owns its own dirty-flag rAF loop plus an `AnimationScheduler` for\n * entrance/hover animations. Data-update transitions are driven by\n * `transition.ts` instead (one rAF for the whole chart), which calls `repaint()`\n * synchronously — the two loops never run at once.\n */\n\nimport type { ChartLayout, ResolvedAnimationPhase } from '@opendata-ai/openchart-core';\nimport { AnimationScheduler } from '../motion/scheduler';\nimport { SpatialIndex } from '../spatial-index';\nimport { type EntranceHandle, playCanvasEntrance } from './entrance';\nimport { ScatterCanvasRenderer } from './renderer';\nimport { buildScatterCanvasState } from './state';\nimport type { ScatterCanvasState } from './types';\n\n/** A point entry in the hit-test index. */\nexport interface ScatterHit {\n /** Index into `state.marks`. */\n index: number;\n x: number;\n y: number;\n radius: number;\n}\n\nexport interface ScatterCanvasLayer {\n /** The canvas element. Owned by the layer; removed on `destroy()`. */\n readonly canvas: HTMLCanvasElement;\n /** Mutable render state. Transitions write into this, then call `repaint()`. */\n readonly state: ScatterCanvasState;\n /** The scheduler driving entrance/hover animations on this layer. */\n readonly scheduler: AnimationScheduler;\n /** Paint the current state immediately (synchronous). */\n repaint(): void;\n /** Mark the layer dirty; paints on the next animation frame. */\n scheduleRepaint(): void;\n /** Nearest point within `maxDist` of (x, y) in layout coords, or `null`. */\n hitTest(x: number, y: number, maxDist: number): ScatterHit | null;\n /** Rebuild the spatial index from the current state. Never call per frame. */\n rebuildIndex(): void;\n /**\n * Fade the points in, replicating the CSS point entrance. Returns null when\n * there is nothing to animate (no points, or reduced motion), having already\n * settled the final state. The handle's `totalMs` must be used to size the\n * mount's animation-cleanup timer -- canvas mode emits no animated elements\n * for the DOM-counting estimate to find.\n */\n playEntrance(enter: ResolvedAnimationPhase, onDone?: () => void): EntranceHandle | null;\n /** Suspend/resume pointer interactions (used while a transition runs). */\n setInteractionSuspended(suspended: boolean): void;\n /** True while interactions are suspended. */\n isInteractionSuspended(): boolean;\n /** Cancel pending frames, stop animations, and remove the canvas. */\n destroy(): void;\n}\n\n/**\n * Create a canvas mark layer for a compiled layout and append it to `container`.\n *\n * The caller is responsible for inserting the SVG after this call so DOM order\n * puts the canvas underneath.\n */\nexport function createScatterCanvasLayer(\n container: HTMLElement,\n layout: ChartLayout,\n): ScatterCanvasLayer {\n const { width, height } = layout.dimensions;\n\n const canvas = document.createElement('canvas');\n canvas.className = 'oc-mark-canvas';\n // The SVG carries the chart's role/label; the canvas is a pure paint surface.\n canvas.setAttribute('aria-hidden', 'true');\n // Top-left anchored rather than `inset: 0`: the canvas is sized in explicit\n // layout pixels, and `inset` would let a flexed container stretch it out of\n // sync with the layout coordinate space it paints in.\n canvas.style.position = 'absolute';\n canvas.style.left = '0';\n canvas.style.top = '0';\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n container.appendChild(canvas);\n\n const renderer = new ScatterCanvasRenderer(canvas);\n renderer.resize(width, height);\n\n const state = buildScatterCanvasState(layout);\n const index = new SpatialIndex<ScatterHit>();\n\n let destroyed = false;\n let frameId: number | null = null;\n let needsPaint = false;\n let interactionSuspended = false;\n\n function repaint(): void {\n if (destroyed) return;\n needsPaint = false;\n renderer.render(state);\n }\n\n function scheduleRepaint(): void {\n needsPaint = true;\n scheduleFrame();\n }\n\n function scheduleFrame(): void {\n if (frameId !== null || destroyed) return;\n frameId = requestAnimationFrame(onFrame);\n }\n\n const scheduler = new AnimationScheduler(scheduleFrame);\n\n function onFrame(now: number): void {\n frameId = null;\n if (destroyed) return;\n // Animations mutate layer state only; they never paint or re-arm rAF.\n if (scheduler.tick(now)) needsPaint = true;\n if (needsPaint) repaint();\n // Re-arm only while animations run, so the loop idles at zero cost.\n if (scheduler.active) scheduleFrame();\n }\n\n function rebuildIndex(): void {\n const marks = state.marks;\n const entries: ScatterHit[] = new Array(marks.n);\n for (let i = 0; i < marks.n; i++) {\n entries[i] = { index: i, x: marks.x[i], y: marks.y[i], radius: marks.r[i] };\n }\n index.rebuild(entries);\n }\n\n rebuildIndex();\n repaint();\n\n return {\n canvas,\n state,\n scheduler,\n repaint,\n scheduleRepaint,\n hitTest(x, y, maxDist) {\n return index.findNearest(x, y, maxDist);\n },\n rebuildIndex,\n playEntrance(enter, onDone) {\n return playCanvasEntrance({\n state,\n enter,\n addAnimation: (a) => scheduler.add(a),\n removeAnimation: (a) => scheduler.remove(a),\n requestPaint: scheduleRepaint,\n onDone,\n });\n },\n setInteractionSuspended(suspended: boolean) {\n interactionSuspended = suspended;\n },\n isInteractionSuspended() {\n return interactionSuspended;\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n scheduler.cancelAll();\n if (frameId !== null) {\n cancelAnimationFrame(frameId);\n frameId = null;\n }\n canvas.remove();\n },\n };\n}\n","/**\n * Series search combobox: the DOM overlay for the `seriesSearch` spec option.\n *\n * Renders an ARIA 1.2 editable combobox (input + popup listbox) with\n * multi-select chips, absolutely positioned inside `.oc-root` over the band\n * the chrome layout reserves (`layout.seriesSearch`). Because the overlay is\n * position: absolute, mounting or updating it never changes the observed\n * container's size, so it cannot re-trigger the container ResizeObserver.\n *\n * Matching is a diacritic-insensitive normalized prefix/substring match\n * (prefix matches rank first). No fuzzy-ranking dependency.\n */\n\nimport type { ResolvedSeriesSearch } from '@opendata-ai/openchart-core';\n\nexport interface SeriesSearchOptions {\n /** The chart container (`.oc-root`). Must be position: relative. */\n container: HTMLElement;\n /** Fired with the full selection (insertion order) after every add/remove. */\n onChange: (selected: string[]) => void;\n}\n\nexport interface SeriesSearchController {\n /** Reposition and refresh the control against a freshly rendered layout. */\n update(band: ResolvedSeriesSearch, svg: SVGElement): void;\n /** Hide the control (layout stripped the band but the spec still wants it). */\n hide(): void;\n /** Currently selected values, in insertion order. */\n getSelected(): string[];\n /** Replace the selection without firing onChange (e.g. reset on spec update). */\n setSelected(values: string[]): void;\n /** Remove the control from the DOM. */\n destroy(): void;\n}\n\nlet seriesSearchIdCounter = 0;\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Fold a string for matching: lowercase with combining diacritical marks\n * stripped. `map[i]` is the index in the original string that produced\n * folded character `i`, so match ranges can be mapped back for emphasis.\n */\nfunction foldWithMap(s: string): { folded: string; map: number[] } {\n let folded = '';\n const map: number[] = [];\n for (let i = 0; i < s.length; i++) {\n const f = s[i]\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase();\n for (const ch of f) {\n folded += ch;\n map.push(i);\n }\n }\n return { folded, map };\n}\n\nfunction fold(s: string): string {\n return foldWithMap(s).folded;\n}\n\n/** Small stroke icon (magnifier or cross) built from SVG path data. */\nfunction createIcon(size: number, paths: string[]): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, 'svg');\n svg.setAttribute('width', String(size));\n svg.setAttribute('height', String(size));\n svg.setAttribute('viewBox', '0 0 16 16');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('aria-hidden', 'true');\n for (const d of paths) {\n const path = document.createElementNS(SVG_NS, 'path');\n path.setAttribute('d', d);\n path.setAttribute('stroke', 'currentColor');\n path.setAttribute('stroke-width', '1.5');\n path.setAttribute('stroke-linecap', 'round');\n svg.appendChild(path);\n }\n return svg;\n}\n\n/**\n * Create the series search control. Mounted once per chart instance and kept\n * across re-renders (so typing focus and chips survive highlight re-renders);\n * `update()` re-syncs position, values, and placeholder after each render.\n */\nexport function createSeriesSearch(options: SeriesSearchOptions): SeriesSearchController {\n const { container, onChange } = options;\n\n const id = `oc-series-search-${++seriesSearchIdCounter}`;\n const listboxId = `${id}-listbox`;\n\n let values: string[] = [];\n let selected: string[] = [];\n let matches: string[] = [];\n let activeIndex = -1;\n let open = false;\n let destroyed = false;\n\n // ---------------------------------------------------------------------------\n // DOM\n // ---------------------------------------------------------------------------\n\n const root = document.createElement('div');\n root.className = 'oc-series-search';\n root.style.display = 'none';\n\n const chips = document.createElement('div');\n chips.className = 'oc-series-search-chips';\n\n const box = document.createElement('div');\n box.className = 'oc-series-search-box';\n\n const icon = createIcon(14, [\n 'M7 11.5a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z',\n 'M10.5 10.5 13.5 13.5',\n ]);\n icon.classList.add('oc-series-search-icon');\n\n const input = document.createElement('input');\n input.className = 'oc-series-search-input';\n input.type = 'text';\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-controls', listboxId);\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-haspopup', 'listbox');\n input.autocomplete = 'off';\n input.spellcheck = false;\n\n const listbox = document.createElement('ul');\n listbox.className = 'oc-series-search-listbox';\n listbox.id = listboxId;\n listbox.setAttribute('role', 'listbox');\n listbox.hidden = true;\n\n box.append(icon, input, listbox);\n root.append(chips, box);\n // Ensure absolute children position against the chart container, matching\n // the tooltip manager's approach.\n container.style.position = container.style.position || 'relative';\n // First child so the tab order matches the visual order (search above chart);\n // render() re-appends the SVG after this node on every re-render.\n container.insertBefore(root, container.firstChild);\n\n // ---------------------------------------------------------------------------\n // Matching\n // ---------------------------------------------------------------------------\n\n function computeMatches(): string[] {\n const q = fold(input.value.trim());\n const available = values.filter((v) => !selected.includes(v));\n if (!q) return available;\n const prefix: string[] = [];\n const substring: string[] = [];\n for (const v of available) {\n const idx = fold(v).indexOf(q);\n if (idx === 0) prefix.push(v);\n else if (idx > 0) substring.push(v);\n }\n return [...prefix, ...substring];\n }\n\n /** Append the option label with the matched substring emphasized. */\n function appendOptionText(li: HTMLLIElement, value: string): void {\n const q = fold(input.value.trim());\n if (!q) {\n li.textContent = value;\n return;\n }\n const { folded, map } = foldWithMap(value);\n const idx = folded.indexOf(q);\n if (idx < 0) {\n li.textContent = value;\n return;\n }\n const start = map[idx];\n const end = idx + q.length < folded.length ? map[idx + q.length] : value.length;\n li.append(document.createTextNode(value.slice(0, start)));\n const match = document.createElement('span');\n match.className = 'oc-series-search-match';\n match.textContent = value.slice(start, end);\n li.append(match, document.createTextNode(value.slice(end)));\n }\n\n // ---------------------------------------------------------------------------\n // Rendering\n // ---------------------------------------------------------------------------\n\n function renderChips(): void {\n chips.textContent = '';\n for (const value of selected) {\n const chip = document.createElement('span');\n chip.className = 'oc-series-search-chip';\n chip.append(document.createTextNode(value));\n\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'oc-series-search-chip-remove';\n remove.setAttribute('aria-label', `Remove ${value}`);\n remove.appendChild(createIcon(8, ['M3 3 13 13', 'M13 3 3 13']));\n remove.addEventListener('click', () => {\n removeValue(value);\n input.focus();\n });\n\n chip.appendChild(remove);\n chips.appendChild(chip);\n }\n }\n\n function renderList(): void {\n matches = computeMatches();\n if (activeIndex >= matches.length) activeIndex = matches.length - 1;\n listbox.textContent = '';\n\n if (matches.length === 0) {\n const empty = document.createElement('li');\n empty.className = 'oc-series-search-empty';\n empty.setAttribute('role', 'presentation');\n empty.textContent = 'No matches';\n listbox.appendChild(empty);\n input.removeAttribute('aria-activedescendant');\n return;\n }\n\n matches.forEach((value, i) => {\n const li = document.createElement('li');\n li.className = 'oc-series-search-option';\n li.id = `${id}-opt-${i}`;\n li.setAttribute('role', 'option');\n li.setAttribute('aria-selected', String(i === activeIndex));\n appendOptionText(li, value);\n li.addEventListener('click', () => selectValue(value));\n listbox.appendChild(li);\n });\n\n if (activeIndex >= 0) {\n input.setAttribute('aria-activedescendant', `${id}-opt-${activeIndex}`);\n const activeEl = listbox.children[activeIndex] as HTMLElement | undefined;\n activeEl?.scrollIntoView?.({ block: 'nearest' });\n } else {\n input.removeAttribute('aria-activedescendant');\n }\n }\n\n function openList(): void {\n if (open) return;\n open = true;\n listbox.hidden = false;\n input.setAttribute('aria-expanded', 'true');\n }\n\n function closeList(): void {\n if (!open) return;\n open = false;\n activeIndex = -1;\n listbox.hidden = true;\n input.setAttribute('aria-expanded', 'false');\n input.removeAttribute('aria-activedescendant');\n }\n\n // ---------------------------------------------------------------------------\n // Selection\n // ---------------------------------------------------------------------------\n\n function selectValue(value: string): void {\n if (!selected.includes(value)) selected.push(value);\n input.value = '';\n closeList();\n renderChips();\n onChange([...selected]);\n }\n\n function removeValue(value: string): void {\n const idx = selected.indexOf(value);\n if (idx < 0) return;\n selected.splice(idx, 1);\n renderChips();\n onChange([...selected]);\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n input.addEventListener('input', () => {\n openList();\n activeIndex = computeMatches().length > 0 ? 0 : -1;\n renderList();\n });\n\n input.addEventListener('keydown', (e: KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n e.preventDefault();\n const wasOpen = open;\n openList();\n if (!wasOpen) {\n matches = computeMatches();\n activeIndex = matches.length > 0 ? 0 : -1;\n } else if (matches.length > 0) {\n const delta = e.key === 'ArrowDown' ? 1 : -1;\n activeIndex = (activeIndex + delta + matches.length) % matches.length;\n }\n renderList();\n break;\n }\n case 'Enter': {\n if (open && activeIndex >= 0 && activeIndex < matches.length) {\n e.preventDefault();\n selectValue(matches[activeIndex]);\n }\n break;\n }\n case 'Escape': {\n if (open) {\n e.preventDefault();\n e.stopPropagation();\n closeList();\n }\n break;\n }\n case 'Backspace': {\n if (input.value === '' && selected.length > 0) {\n removeValue(selected[selected.length - 1]);\n }\n break;\n }\n case 'Tab': {\n closeList();\n break;\n }\n }\n });\n\n // Keep focus in the input while clicking options/chips inside the popup.\n listbox.addEventListener('mousedown', (e) => e.preventDefault());\n\n // Close when focus leaves the whole control.\n root.addEventListener('focusout', (e: FocusEvent) => {\n const next = e.relatedTarget as Node | null;\n if (!next || !root.contains(next)) closeList();\n });\n\n // ---------------------------------------------------------------------------\n // Controller\n // ---------------------------------------------------------------------------\n\n return {\n update(band: ResolvedSeriesSearch, svg: SVGElement): void {\n if (destroyed) return;\n values = band.values;\n input.placeholder = band.placeholder;\n input.setAttribute('aria-label', band.placeholder);\n\n // Layout coords -> pixel coords relative to the container, same\n // viewBox-scale approach as the text edit overlay.\n const viewBox = (svg as SVGSVGElement).viewBox?.baseVal;\n const svgRect = svg.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const scaleX = viewBox?.width && svgRect.width ? svgRect.width / viewBox.width : 1;\n const scaleY = viewBox?.height && svgRect.height ? svgRect.height / viewBox.height : 1;\n root.style.left = `${band.x * scaleX + (svgRect.left - containerRect.left)}px`;\n root.style.top = `${band.y * scaleY + (svgRect.top - containerRect.top)}px`;\n root.style.width = `${band.width * scaleX}px`;\n root.style.height = `${band.height * scaleY}px`;\n root.style.display = 'flex';\n\n if (open) renderList();\n },\n hide(): void {\n root.style.display = 'none';\n closeList();\n },\n getSelected(): string[] {\n return [...selected];\n },\n setSelected(next: string[]): void {\n selected = [...next];\n renderChips();\n },\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n root.remove();\n },\n };\n}\n","/**\n * Generate CSS custom properties from a resolved JS theme.\n *\n * Stamped on the .oc-root container at mount time so CSS consumers\n * read from the same source of truth as the JS engine. The static\n * values in tokens.css / dark.css serve as fallback defaults for\n * contexts where JS hasn't mounted (SSR, static HTML).\n */\n\nimport type { ResolvedTheme } from '@opendata-ai/openchart-core';\nimport { adaptForLightLineStroke, cssTokenDefault } from '@opendata-ai/openchart-core';\n\nexport function stampThemeProperties(el: HTMLElement, theme: ResolvedTheme): void {\n const accent = theme.colors.categorical[0] ?? cssTokenDefault('--oc-accent', 'light');\n const bg =\n theme.colors.background === 'transparent'\n ? theme.isDark\n ? cssTokenDefault('--oc-bg', 'dark')\n : cssTokenDefault('--oc-bg', 'light')\n : theme.colors.background;\n\n const props: [string, string][] = [\n ['--oc-font-family', theme.fonts.family],\n ['--oc-font-mono', theme.fonts.mono],\n ['--oc-title-size', `${theme.chrome.title.fontSize}px`],\n ['--oc-title-weight', `${theme.chrome.title.fontWeight}`],\n ['--oc-subtitle-size', `${theme.chrome.subtitle.fontSize}px`],\n ['--oc-subtitle-weight', `${theme.chrome.subtitle.fontWeight}`],\n ['--oc-source-size', `${theme.chrome.source.fontSize}px`],\n ['--oc-source-weight', `${theme.chrome.source.fontWeight}`],\n ['--oc-body-size', `${theme.fonts.sizes.body}px`],\n ['--oc-eyebrow-size', `${theme.chrome.eyebrow.fontSize}px`],\n ['--oc-eyebrow-weight', `${theme.chrome.eyebrow.fontWeight}`],\n ['--oc-bg', bg],\n ['--oc-text', theme.colors.text],\n ['--oc-text-muted', theme.colors.axis],\n ['--oc-gridline', theme.colors.gridline],\n ['--oc-axis', theme.colors.axis],\n ['--oc-border-radius', `${theme.borderRadius}px`],\n ['--oc-accent', accent],\n ['--oc-accent-strong', adaptForLightLineStroke(accent)],\n ['--oc-positive', theme.colors.positive],\n ['--oc-negative', theme.colors.negative],\n ['--oc-space-2', `${theme.spacing.chromeGap * 2}px`],\n ['--oc-space-4', `${theme.spacing.padding}px`],\n ];\n\n for (const [name, value] of props) {\n el.style.setProperty(name, value);\n }\n}\n","/**\n * Numeric rAF tweening for scrollytelling story steps.\n *\n * Owns imperative numeric interpolation: the story driver and camera math\n * mutate scalar/vector values per frame using these primitives instead of\n * hand-rolling rAF loops. Ported from opendata/shared/lib/tween.ts.\n *\n * Everything here is SSR-safe: no `window`/`performance` access at module\n * scope. Callers are expected to invoke these client-side.\n */\n\nimport { clamp01, cubicInOut, cubicOut, lerp, linear } from '../motion/easing';\n\nexport { clamp01, lerp };\n\nexport type EasingFn = (t: number) => number;\n\nexport const easingFns = {\n linear,\n easeOutCubic: cubicOut,\n easeInOutCubic: cubicInOut,\n easeOutQuint: (t: number) => 1 - (1 - t) ** 5,\n} as const satisfies Record<string, EasingFn>;\n\n/**\n * Duration tokens (ms) for story state changes. Use these instead of\n * arbitrary numbers so all stories share one timing scale.\n */\nexport const storyMotion = {\n /** Small opacity/emphasis shifts */\n fast: 300,\n /** Step state transitions */\n base: 500,\n /** Whole-chart crossfade fallback (steps outside the morph gate) */\n crossfade: 400,\n /** Step-mode camera transitions */\n camera: 600,\n /** Scrub-mode camera damping time constant */\n cameraTau: 100,\n} as const;\n\nexport interface TweenConfig<T> {\n initial: T;\n lerp: (a: T, b: T, t: number) => T;\n /** Default `storyMotion.base` */\n duration?: number;\n /** Default `easingFns.easeOutCubic` */\n ease?: EasingFn;\n onFrame: (value: T) => void;\n}\n\nexport interface Tween<T> {\n /**\n * Retarget the tween. If a tween is mid-flight, the new tween starts FROM\n * THE LIVE INTERPOLATED VALUE, not the previous target -- fast retargeting\n * never jumps. `snap: true` applies the target synchronously with no rAF.\n */\n to: (target: T, opts?: { snap?: boolean }) => void;\n get: () => T;\n cancel: () => void;\n}\n\n/**\n * Retargetable tween over an arbitrary shape T.\n */\nexport function createTween<T>(config: TweenConfig<T>): Tween<T> {\n const {\n lerp: lerpT,\n duration = storyMotion.base,\n ease = easingFns.easeOutCubic,\n onFrame,\n } = config;\n\n let current = config.initial;\n let rafId = 0;\n let running = false;\n\n const stop = () => {\n if (running) {\n cancelAnimationFrame(rafId);\n running = false;\n }\n };\n\n const to = (target: T, opts?: { snap?: boolean }) => {\n stop();\n if (opts?.snap || duration <= 0) {\n current = target;\n onFrame(current);\n return;\n }\n\n const from = current;\n const start = performance.now();\n running = true;\n\n const tick = (now: number) => {\n const t = clamp01((now - start) / duration);\n current = lerpT(from, target, ease(t));\n onFrame(current);\n if (t < 1) {\n rafId = requestAnimationFrame(tick);\n } else {\n running = false;\n }\n };\n\n rafId = requestAnimationFrame(tick);\n };\n\n return { to, get: () => current, cancel: stop };\n}\n","import { lerp } from './tween';\n\n/**\n * Pure math for the scrollytelling camera. `createChartStory` owns DOM\n * writes; everything here is testable without a browser. Ported from\n * opendata/shared/lib/scrolly/camera-math.ts.\n *\n * The camera is a center + zoom over a fixed viewBox, applied as a\n * `transform` on a dedicated wrapper `<g>` around the marks group (NOT\n * viewBox interpolation -- that scales text and gives labels no way to\n * counter-scale). See .claude/rules/svg-animation.md: CSS transform\n * replaces SVG transform attributes, so the camera transform must compose\n * with, not replace, existing SVG transforms on marks.\n */\n\nexport interface Camera {\n cx: number;\n cy: number;\n /** Zoom factor. 1 = full viewBox visible. */\n k: number;\n}\n\nexport interface CameraTarget {\n x: number;\n y: number;\n width: number;\n height: number;\n /** ViewBox units added on all sides before fitting */\n padding?: number;\n}\n\nexport interface ViewBoxSize {\n width: number;\n height: number;\n}\n\nexport const FULL_VIEW = (vb: ViewBoxSize): CameraTarget => ({\n x: 0,\n y: 0,\n width: vb.width,\n height: vb.height,\n});\n\n/** Fit a target rect inside the viewBox, preserving aspect ratio. */\nexport function fitTarget(target: CameraTarget, vb: ViewBoxSize): Camera {\n const pad = target.padding ?? 0;\n const w = target.width + 2 * pad;\n const h = target.height + 2 * pad;\n return {\n cx: target.x + target.width / 2,\n cy: target.y + target.height / 2,\n k: Math.min(vb.width / w, vb.height / h),\n };\n}\n\n/**\n * Pan lerps linearly; zoom lerps in LOG space so the zoom rate reads\n * constant (a 1->4 zoom passes through 2 at the midpoint, not 2.5).\n */\nexport function interpolateCamera(a: Camera, b: Camera, t: number): Camera {\n return {\n cx: lerp(a.cx, b.cx, t),\n cy: lerp(a.cy, b.cy, t),\n k: Math.exp(lerp(Math.log(a.k), Math.log(b.k), t)),\n };\n}\n\n/** SVG transform string that frames the camera inside the viewBox. */\nexport function cameraTransform(c: Camera, vb: ViewBoxSize): string {\n return `translate(${vb.width / 2} ${vb.height / 2}) scale(${c.k}) translate(${-c.cx} ${-c.cy})`;\n}\n\n/**\n * Frame-rate-independent exponential damping: two 8ms steps land where one\n * 16ms step does. `tauMs` is the time constant (~63% of the gap per tau).\n */\nexport function damp(current: number, target: number, tauMs: number, dtMs: number): number {\n if (tauMs <= 0) return target;\n return current + (target - current) * (1 - Math.exp(-dtMs / tauMs));\n}\n\nexport function dampCamera(current: Camera, target: Camera, tauMs: number, dtMs: number): Camera {\n return {\n cx: damp(current.cx, target.cx, tauMs, dtMs),\n cy: damp(current.cy, target.cy, tauMs, dtMs),\n // k damped in log space, same rationale as interpolateCamera\n k: Math.exp(damp(Math.log(current.k), Math.log(target.k), tauMs, dtMs)),\n };\n}\n\nexport function camerasClose(a: Camera, b: Camera, epsilon = 1e-3): boolean {\n return (\n Math.abs(a.cx - b.cx) < epsilon &&\n Math.abs(a.cy - b.cy) < epsilon &&\n Math.abs(Math.log(a.k) - Math.log(b.k)) < epsilon\n );\n}\n\n/**\n * Where the scrub camera should point for a given frame.\n *\n * Hold-zone semantics: the camera DWELLS on the active step's target while\n * the reader reads, and only transitions toward the next step's target in\n * the tail of the span (`stepProgress > holdUntil`). Interpolating across\n * the whole span would mean the camera departs the moment a step activates\n * and never rests on what the text is describing.\n */\nexport function scrubCamera(\n step: number,\n stepProgress: number,\n fitted: Camera[],\n holdUntil: number,\n ease: (t: number) => number,\n): Camera {\n const n = fitted.length;\n if (n === 0) return { cx: 0, cy: 0, k: 1 };\n const clamped = Math.min(Math.max(step, 0), n - 1);\n const current = fitted[clamped]!;\n const next = fitted[Math.min(clamped + 1, n - 1)]!;\n if (step < 0 || clamped >= n - 1 || stepProgress <= holdUntil) {\n return current;\n }\n const t = (stepProgress - holdUntil) / (1 - holdUntil);\n return interpolateCamera(current, next, ease(t));\n}\n","/**\n * Map mount API: the main entry point for vanilla JS map usage.\n *\n * createGeoMap() takes a container, GeoMapSpec, and options, compiles the\n * map, renders it as SVG, sets up responsive resizing, tooltip interaction,\n * and returns a GeoMapInstance with update/resize/export/destroy.\n */\n\nimport type {\n CompileOptions,\n DarkMode,\n GeoMapLayout,\n GeoMapSpec,\n ThemeConfig,\n} from '@opendata-ai/openchart-core';\nimport { compileGeoMap } 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 {\n applyMapCamera,\n cameraForTarget,\n FOCUS_DIM_OPACITY,\n focusTargetForFeatures,\n type GeoMapCameraOptions,\n} from './map-camera';\nimport { renderMapSVG } from './map-renderer';\nimport { captureMapSnapshot, runMapFillTransition } from './map-transition';\nimport { createMeasureText, resolveFontFamily, scheduleFontReload } from './measure-text';\nimport { observeResize } from './resize-observer';\nimport { resolveDarkMode } from './resolve-dark-mode';\nimport type { Camera } from './story/camera-math';\nimport { interpolateCamera } from './story/camera-math';\nimport type { Tween } from './story/tween';\nimport { createTween, easingFns, storyMotion } from './story/tween';\nimport { createTooltipManager, type TooltipManager } from './tooltip';\n\n/**\n * A stable string for a resolved focus, used to detect focus changes between\n * `update()` calls. Includes the target rect (rounded) so a points focus\n * (which has empty ids) still re-fits when the fitted cluster moves; ids alone\n * would miss that. `null` focus -> null (no camera target).\n */\nfunction focusSignature(focus: GeoMapLayout['focus']): string | null {\n if (!focus) return null;\n const t = focus.target;\n const ids = focus.ids.map(String).sort().join(',');\n return `${ids}|${Math.round(t.x)},${Math.round(t.y)},${Math.round(t.width)},${Math.round(t.height)},${t.padding}`;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type GeoMapMarkEvent = {\n kind: 'feature' | 'point';\n id: string | number;\n name?: string;\n data: Record<string, unknown> | null;\n};\n\nexport interface GeoMapMountOptions {\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 feature or point is clicked. */\n onMarkClick?: (event: GeoMapMarkEvent) => void;\n /** Callback when a feature or point is hovered (null on mouse leave). */\n onMarkHover?: (event: GeoMapMarkEvent | null) => void;\n}\n\nexport interface GeoMapInstance {\n /** Re-compile and re-render with a new spec. */\n update(spec: GeoMapSpec): void;\n /** Re-compile at current container dimensions. */\n resize(): void;\n /** Export the map. */\n export(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n options?: JPGExportOptions | SVGExportOptions,\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: GeoMapLayout;\n /** Zoom to one or more features by ID. */\n zoomTo(featureId: string | number | Array<string | number>, opts?: GeoMapCameraOptions): void;\n /** Pan to a feature keeping the current zoom level. */\n panTo(featureId: string | number, opts?: GeoMapCameraOptions): void;\n /** Fit the camera to an arbitrary bounding box, or reset to full view if no target. */\n fitBounds(\n target?: { x: number; y: number; width: number; height: number; padding?: number },\n opts?: GeoMapCameraOptions,\n ): void;\n /** Reset the camera to the full map view. */\n resetView(opts?: GeoMapCameraOptions): void;\n /** Get a snapshot of the current camera state. */\n getCamera(): Camera;\n /** Set the camera to an exact state (no animation). */\n setCamera(camera: Camera): void;\n}\n\n// ---------------------------------------------------------------------------\n// Dark mode resolution\n// ---------------------------------------------------------------------------\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n try {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a map instance from a spec and mount it into a container.\n */\nexport function createGeoMap(\n container: HTMLElement,\n spec: GeoMapSpec,\n options?: GeoMapMountOptions,\n): GeoMapInstance {\n let currentSpec = spec;\n let currentLayout: GeoMapLayout;\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 animationCleanup: (() => void) | null = null;\n let fillTransitionHandle: { cancel: () => void } | null = null;\n let pendingResize = false;\n\n // Camera state\n let currentCamera: Camera = { cx: 0, cy: 0, k: 1 };\n let currentFocusIds: Array<string | number> | null = null;\n let cameraTween: Tween<Camera> | null = null;\n\n // Track whether this is the first render (for snap-to-focus).\n let isFirstRender = true;\n\n // Set when webfonts have loaded and a recompile is owed.\n let fontsReloadPending = false;\n\n // Apply the root class up front so getComputedStyle sees --oc-font-family\n container.classList.add('oc-map-root');\n\n // Resolve the effective font the same way compile() will.\n function resolveEffectiveFont(): string {\n return (\n options?.theme?.fonts?.family ??\n currentSpec.theme?.fonts?.family ??\n resolveFontFamily(container)\n );\n }\n let fontFamily = resolveEffectiveFont();\n let measureText = createMeasureText(fontFamily);\n let renderGen = 0;\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n let isAutoHeight: boolean | null = null;\n\n function getContainerDimensions(): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n const width = Math.max(rect.width || 600, 100);\n\n if (isAutoHeight === null && (rect.width > 0 || rect.height > 0)) {\n isAutoHeight = rect.height === 0 && rect.width > 0;\n }\n\n // Explicit host height is a hard budget: return it as-is so the\n // compiler keeps the SVG inside its box.\n if (isAutoHeight === false && rect.height > 0) {\n return { width, height: Math.max(rect.height, 100) };\n }\n\n // Auto-height host: pick our own budget.\n return { width, height: Math.round(width * 0.625) };\n }\n\n function compile(): GeoMapLayout {\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 return compileGeoMap(currentSpec, compileOpts);\n }\n\n // ---------------------------------------------------------------------------\n // Tooltip and interaction wiring\n // ---------------------------------------------------------------------------\n\n function wireTooltipAndInteraction(svg: SVGSVGElement, layout: GeoMapLayout): () => void {\n const cleanups: Array<() => void> = [];\n\n const featureElements = svg.querySelectorAll('.oc-map-feature');\n for (const el of featureElements) {\n const featureId = el.getAttribute('data-feature-id');\n if (!featureId) continue;\n\n const content = layout.tooltipDescriptors.get(featureId);\n const feature = layout.features.find((f) => String(f.id) === featureId);\n\n const handleMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('cursor', 'pointer');\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('filter', 'brightness(1.1)');\n if (content && tooltipManager && options?.tooltip !== false) {\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 if (feature) {\n options?.onMarkHover?.({\n kind: 'feature',\n id: feature.id,\n name: feature.name,\n data: feature.data,\n });\n }\n };\n\n const handleMouseMove = (e: Event) => {\n if (content && tooltipManager && options?.tooltip !== false) {\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 (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('cursor');\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('filter');\n tooltipManager?.hide();\n options?.onMarkHover?.(null);\n };\n\n const handleClick = () => {\n if (feature) {\n options?.onMarkClick?.({\n kind: 'feature',\n id: feature.id,\n name: feature.name,\n data: feature.data,\n });\n }\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 point interactions\n const pointMarksByKey = new Map(layout.pointMarks.map((p) => [p.key, p]));\n const pointElements = svg.querySelectorAll('.oc-map-point');\n for (const el of pointElements) {\n const pointKey = el.getAttribute('data-point-key');\n if (!pointKey) continue;\n\n const content = layout.tooltipDescriptors.get(`point:${pointKey}`);\n const pointMark = pointMarksByKey.get(pointKey);\n\n const handlePointMouseEnter = (e: Event) => {\n const mouseEvent = e as MouseEvent;\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('cursor', 'pointer');\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty('filter', 'brightness(1.15)');\n if (content && tooltipManager && options?.tooltip !== false) {\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 if (pointMark) {\n options?.onMarkHover?.({\n kind: 'point',\n id: pointKey,\n data: pointMark.data,\n });\n }\n };\n\n const handlePointMouseMove = (e: Event) => {\n if (content && tooltipManager && options?.tooltip !== false) {\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 handlePointMouseLeave = () => {\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('cursor');\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('filter');\n tooltipManager?.hide();\n options?.onMarkHover?.(null);\n };\n\n const handlePointClick = () => {\n if (pointMark) {\n options?.onMarkClick?.({\n kind: 'point',\n id: pointKey,\n data: pointMark.data,\n });\n }\n };\n\n el.addEventListener('mouseenter', handlePointMouseEnter);\n el.addEventListener('mousemove', handlePointMouseMove);\n el.addEventListener('mouseleave', handlePointMouseLeave);\n el.addEventListener('click', handlePointClick);\n\n cleanups.push(() => {\n el.removeEventListener('mouseenter', handlePointMouseEnter);\n el.removeEventListener('mousemove', handlePointMouseMove);\n el.removeEventListener('mouseleave', handlePointMouseLeave);\n el.removeEventListener('click', handlePointClick);\n });\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n };\n }\n\n // ---------------------------------------------------------------------------\n // Camera helpers\n // ---------------------------------------------------------------------------\n\n function resolveCamera(): Camera {\n if (currentFocusIds && currentFocusIds.length > 0) {\n const target = focusTargetForFeatures(currentLayout, currentFocusIds);\n return cameraForTarget(currentLayout, target);\n }\n return cameraForTarget(currentLayout, null);\n }\n\n function animateCamera(target: Camera, duration: number): void {\n if (cameraTween) cameraTween.cancel();\n cameraTween = createTween<Camera>({\n initial: currentCamera,\n lerp: interpolateCamera,\n duration,\n ease: easingFns.easeInOutCubic,\n onFrame(cam) {\n currentCamera = cam;\n if (svgElement) applyMapCamera(svgElement, cam, currentLayout);\n },\n });\n cameraTween.to(target);\n }\n\n function driveCamera(cam: Camera, duration: number): void {\n if (duration === 0 || prefersReducedMotion()) {\n currentCamera = cam;\n if (svgElement) applyMapCamera(svgElement, cam, currentLayout);\n } else {\n animateCamera(cam, duration);\n }\n }\n\n function updateA11yLive(ids: Array<string | number> | null): void {\n let liveEl = container.querySelector('.oc-map-live') as HTMLElement | null;\n if (!liveEl) {\n liveEl = document.createElement('div');\n liveEl.className = 'oc-map-live oc-sr-only';\n liveEl.setAttribute('aria-live', 'polite');\n container.appendChild(liveEl);\n }\n if (!ids || ids.length === 0) {\n liveEl.textContent = 'Showing full map';\n return;\n }\n const names = ids.map((id) => {\n const f = currentLayout.features.find((feat) => String(feat.id) === String(id));\n return f?.name ?? String(id);\n });\n liveEl.textContent = `Zoomed to ${names.join(', ')}`;\n }\n\n function applyFocusDim(ids: Array<string | number> | null): void {\n if (!svgElement) return;\n const features = svgElement.querySelectorAll('.oc-map-feature');\n if (!ids || ids.length === 0) {\n for (const el of features) {\n (el as SVGElement & ElementCSSInlineStyle).style.removeProperty('opacity');\n }\n return;\n }\n const focusSet = new Set(ids.map(String));\n for (const el of features) {\n const fid = el.getAttribute('data-feature-id');\n (el as SVGElement & ElementCSSInlineStyle).style.setProperty(\n 'opacity',\n fid && focusSet.has(fid) ? '1' : String(FOCUS_DIM_OPACITY),\n );\n }\n }\n\n // ---------------------------------------------------------------------------\n // Render + update\n // ---------------------------------------------------------------------------\n\n function render(animate = false): void {\n // Cancel running animations\n if (animationCleanup) {\n animationCleanup();\n animationCleanup = null;\n }\n if (fillTransitionHandle) {\n fillTransitionHandle.cancel();\n fillTransitionHandle = null;\n }\n\n // Render new SVG before removing old to avoid a paint gap\n const oldSvg = svgElement;\n const newSvg = renderMapSVG(currentLayout, { animate });\n\n if (oldSvg) {\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n container.replaceChild(newSvg, oldSvg);\n } else {\n container.appendChild(newSvg);\n }\n svgElement = newSvg;\n\n // Wire interactions\n cleanupTooltipEvents = wireTooltipAndInteraction(newSvg, currentLayout);\n\n // Setup tooltips if enabled\n if (options?.tooltip !== false) {\n if (!tooltipManager) {\n tooltipManager = createTooltipManager(container);\n }\n }\n\n // Setup animation cleanup only when actually animating\n const isAnimating = animate && !!currentLayout.animation?.enter;\n if (isAnimating) {\n animationCleanup = setupAnimationCleanup(newSvg, () => {\n if (pendingResize && !destroyed) {\n pendingResize = false;\n resize();\n }\n // Apply deferred focus dim after animation completes\n if (currentFocusIds && currentFocusIds.length > 0) {\n applyFocusDim(currentFocusIds);\n }\n });\n }\n\n // Re-apply camera transform after render if zoomed or focused\n if (currentCamera.k > 1 + 1e-3 || (currentFocusIds && currentFocusIds.length > 0)) {\n applyMapCamera(newSvg, currentCamera, currentLayout);\n }\n\n renderGen += 1;\n container.dataset.ocRenderGen = String(renderGen);\n\n if (fontsReloadPending) {\n fontsReloadPending = false;\n container.dataset.ocFontsState = 'ready';\n }\n\n // On first render, initialize the camera so subsequent tweens start\n // from the correct position (not the {0,0,1} default).\n if (isFirstRender) {\n if (currentLayout.focus) {\n const target = currentLayout.focus.target;\n currentFocusIds = [...currentLayout.focus.ids];\n const cam = cameraForTarget(currentLayout, target);\n currentCamera = cam;\n if (svgElement) applyMapCamera(svgElement, cam, currentLayout);\n if (!isAnimating) applyFocusDim(currentFocusIds);\n } else {\n currentCamera = cameraForTarget(currentLayout, null);\n }\n }\n isFirstRender = false;\n }\n\n function update(newSpec: GeoMapSpec): void {\n currentSpec = newSpec;\n const nextFont = resolveEffectiveFont();\n if (nextFont !== fontFamily) {\n fontFamily = nextFont;\n measureText = createMeasureText(fontFamily);\n }\n\n // Capture paint + point geometry optimistically; gate the tween on the\n // *new* layout's animation config after compile\n const canAnimate = !animationCleanup && !prefersReducedMotion();\n const prevPaint = canAnimate ? captureMapSnapshot(svgElement) : null;\n\n // Remember previous focus to detect changes. The signature includes the\n // target rect, not just ids+padding, so a points-focus ({ points: true },\n // which resolves to empty ids) still re-fits the camera when the fitted\n // cluster moves between steps.\n const prevFocusIds = currentFocusIds ? currentFocusIds.map(String).sort().join(',') : null;\n const prevFocusSig = focusSignature(currentLayout.focus);\n\n currentLayout = compile();\n render();\n\n // Run the update tween if the *new* layout enables update animation\n if (\n canAnimate &&\n prevPaint &&\n (prevPaint.fills.size > 0 || prevPaint.points.size > 0) &&\n svgElement &&\n currentLayout.animation?.update\n ) {\n fillTransitionHandle = runMapFillTransition(svgElement, prevPaint, {\n duration: currentLayout.animation.update.duration,\n });\n }\n\n // Declarative focus from spec: tween camera if focus changed\n const nextFocus = currentLayout.focus;\n const nextFocusSig = focusSignature(nextFocus);\n\n if (nextFocusSig !== prevFocusSig) {\n if (nextFocus) {\n currentFocusIds = [...nextFocus.ids];\n const cam = cameraForTarget(currentLayout, nextFocus.target);\n driveCamera(cam, prefersReducedMotion() ? 0 : storyMotion.camera);\n applyFocusDim(currentFocusIds);\n } else if (prevFocusIds !== null) {\n currentFocusIds = null;\n const cam = cameraForTarget(currentLayout, null);\n driveCamera(cam, prefersReducedMotion() ? 0 : storyMotion.camera);\n applyFocusDim(null);\n }\n }\n }\n\n function resize(): void {\n if (destroyed) return;\n // If animation is running, queue the resize for after it completes\n if (animationCleanup) {\n pendingResize = true;\n return;\n }\n\n // Cancel any running camera tween: the resize recomputes the camera for the\n // new dimensions, and a stale tween would overwrite it on the next frame.\n if (cameraTween) {\n cameraTween.cancel();\n cameraTween = null;\n }\n\n currentLayout = compile();\n render();\n\n // Re-resolve camera against new layout dimensions.\n // Imperative focus (set via zoomTo/panTo) takes precedence over declarative.\n if (currentFocusIds && currentFocusIds.length > 0) {\n currentCamera = resolveCamera();\n if (svgElement) applyMapCamera(svgElement, currentCamera, currentLayout);\n } else if (currentLayout.focus) {\n currentFocusIds = [...currentLayout.focus.ids];\n currentCamera = cameraForTarget(currentLayout, currentLayout.focus.target);\n if (svgElement) applyMapCamera(svgElement, currentCamera, currentLayout);\n }\n applyFocusDim(currentFocusIds);\n }\n\n // ---------------------------------------------------------------------------\n // Export\n // ---------------------------------------------------------------------------\n\n function exportChart(\n format: 'svg' | 'svg-with-fonts' | 'png' | 'jpg',\n options_?: JPGExportOptions | SVGExportOptions,\n ): string | Promise<Blob> | Promise<string> {\n if (!svgElement) return '';\n\n switch (format) {\n case 'svg':\n return exportSVG(svgElement);\n case 'svg-with-fonts':\n return exportSVGWithFonts(svgElement);\n case 'png':\n return exportPNG(svgElement, options_ as JPGExportOptions);\n case 'jpg':\n return exportJPG(svgElement, options_ as JPGExportOptions);\n default:\n return '';\n }\n }\n\n // ---------------------------------------------------------------------------\n // Destroy\n // ---------------------------------------------------------------------------\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n\n // Cancel running animations\n if (animationCleanup) {\n cancelAnimations(svgElement);\n animationCleanup();\n animationCleanup = null;\n }\n if (fillTransitionHandle) {\n fillTransitionHandle.cancel();\n fillTransitionHandle = null;\n }\n if (cameraTween) {\n cameraTween.cancel();\n cameraTween = null;\n }\n\n // Clean up events\n if (cleanupTooltipEvents) {\n cleanupTooltipEvents();\n cleanupTooltipEvents = null;\n }\n\n // Remove SVG\n if (svgElement) {\n svgElement.remove();\n svgElement = null;\n }\n\n // Remove a11y live region\n const liveEl = container.querySelector('.oc-map-live');\n if (liveEl) liveEl.remove();\n\n // Unmount tooltip manager\n if (tooltipManager) {\n tooltipManager.destroy();\n tooltipManager = null;\n }\n\n // Disconnect resize observer\n if (disconnectResize) {\n disconnectResize();\n disconnectResize = null;\n }\n\n // Remove root classes\n container.classList.remove('oc-map-root', 'oc-dark');\n }\n\n // ---------------------------------------------------------------------------\n // Initialize\n // ---------------------------------------------------------------------------\n\n if (resolveDarkMode(options?.darkMode)) {\n container.classList.add('oc-dark');\n }\n\n // Initial compile and render (animate on first mount)\n currentLayout = compile();\n render(true);\n\n // Recompile once after webfonts load\n const fontsPending = scheduleFontReload(\n fontFamily,\n () => !destroyed,\n () => {\n fontsReloadPending = true;\n resize();\n },\n );\n container.dataset.ocFontsState = fontsPending ? 'pending' : 'ready';\n\n // Setup responsive resizing\n if (options?.responsive !== false) {\n disconnectResize = observeResize(container, () => {\n resize();\n });\n }\n\n return {\n update,\n resize,\n export: exportChart,\n destroy,\n get layout(): GeoMapLayout {\n return currentLayout;\n },\n zoomTo(featureId: string | number | Array<string | number>, opts?: GeoMapCameraOptions): void {\n const ids = Array.isArray(featureId) ? featureId : [featureId];\n const target = focusTargetForFeatures(currentLayout, ids, opts?.padding ?? 16);\n if (!target) {\n console.warn(`[openchart] zoomTo: no features found for ids: ${ids.join(', ')}`);\n return;\n }\n currentFocusIds = ids;\n const cam = cameraForTarget(currentLayout, target);\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n applyFocusDim(ids);\n updateA11yLive(ids);\n },\n panTo(featureId: string | number, opts?: GeoMapCameraOptions): void {\n const target = focusTargetForFeatures(currentLayout, [featureId], opts?.padding ?? 16);\n if (!target) {\n console.warn(`[openchart] panTo: no feature found for id: ${featureId}`);\n return;\n }\n const cam: Camera = {\n cx: target.x + target.width / 2,\n cy: target.y + target.height / 2,\n k: currentCamera.k,\n };\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n updateA11yLive([featureId]);\n },\n fitBounds(\n target?: { x: number; y: number; width: number; height: number; padding?: number },\n opts?: GeoMapCameraOptions,\n ): void {\n currentFocusIds = null;\n const cam = cameraForTarget(currentLayout, target ?? null);\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n applyFocusDim(null);\n },\n resetView(opts?: GeoMapCameraOptions): void {\n currentFocusIds = null;\n const cam = cameraForTarget(currentLayout, null);\n driveCamera(cam, opts?.duration ?? storyMotion.camera);\n applyFocusDim(null);\n updateA11yLive(null);\n },\n getCamera(): Camera {\n return { ...currentCamera };\n },\n setCamera(camera: Camera): void {\n currentCamera = camera;\n currentFocusIds = null;\n if (svgElement) applyMapCamera(svgElement, camera, currentLayout);\n },\n };\n}\n","/**\n * Map camera utilities: zoom, pan, and focus for map visualizations.\n *\n * Reuses the existing camera-math infrastructure from the scrollytelling\n * system. The camera transform is applied as an SVG `transform` attribute\n * on the `[data-oc-map-camera]` group, never as a CSS transform.\n */\n\nimport type { GeoMapLayout } from '@opendata-ai/openchart-core';\nimport type { Camera, CameraTarget } from './story/camera-math';\nimport { cameraTransform, FULL_VIEW, fitTarget } from './story/camera-math';\n\nexport type { Camera } from './story/camera-math';\n\n/** Resting opacity for features outside the current focus set. */\nexport const FOCUS_DIM_OPACITY = 0.25;\n\nexport interface GeoMapCameraOptions {\n /** Transition duration in ms. 0 snaps instantly. Default 600. */\n duration?: number;\n /** Padding in map-local units around the target. Default 16. */\n padding?: number;\n}\n\n/**\n * Compute a CameraTarget from the union of feature bounds.\n * Returns null if no matching features found.\n */\nexport function focusTargetForFeatures(\n layout: GeoMapLayout,\n ids: Array<string | number>,\n padding = 16,\n): CameraTarget | null {\n const idSet = new Set(ids.map(String));\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let found = false;\n\n for (const f of layout.features) {\n if (idSet.has(String(f.id))) {\n found = true;\n minX = Math.min(minX, f.bounds.x);\n minY = Math.min(minY, f.bounds.y);\n maxX = Math.max(maxX, f.bounds.x + f.bounds.width);\n maxY = Math.max(maxY, f.bounds.y + f.bounds.height);\n }\n }\n\n if (!found) return null;\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY, padding };\n}\n\n/**\n * Compute the Camera for a target, fitting against mapSize.\n * Returns the full-view camera if no target provided.\n */\nexport function cameraForTarget(layout: GeoMapLayout, target?: CameraTarget | null): Camera {\n const vb = layout.mapSize;\n if (!target) return fitTarget(FULL_VIEW(vb), vb);\n const cam = fitTarget(target, vb);\n return { ...cam, k: Math.max(1, Math.min(40, cam.k)) };\n}\n\n/**\n * Apply a camera transform to the map's camera group.\n * Toggles vector-effect=\"non-scaling-stroke\" on features/borders while zoomed.\n */\nexport function applyMapCamera(svg: SVGElement, camera: Camera, layout: GeoMapLayout): void {\n const cameraGroup = svg.querySelector('[data-oc-map-camera]');\n if (!cameraGroup) return;\n\n const vb = layout.mapSize;\n const isZoomed = Math.abs(camera.k - 1) > 1e-3;\n\n if (isZoomed) {\n cameraGroup.setAttribute('transform', cameraTransform(camera, vb));\n // Toggle non-scaling-stroke so strokes don't fatten when zoomed\n const paths = svg.querySelectorAll('.oc-map-feature, .oc-map-borders path');\n for (const p of paths) {\n p.setAttribute('vector-effect', 'non-scaling-stroke');\n }\n // Counter-scale point radii so dots keep constant screen size through zoom.\n // Only use attribute counter-scaling (r/k, stroke-width/k) without\n // vector-effect: the group transform scales both back to constant screen\n // size. Adding vector-effect on top would double-compensate stroke.\n const points = svg.querySelectorAll('.oc-map-point');\n for (const p of points) {\n const baseR = Number(p.getAttribute('data-base-r') ?? 5);\n const baseSW = Number(p.getAttribute('data-base-stroke-width') ?? 1);\n p.setAttribute('r', String(baseR / camera.k));\n p.setAttribute('stroke-width', String(baseSW / camera.k));\n }\n } else {\n cameraGroup.removeAttribute('transform');\n const paths = svg.querySelectorAll('.oc-map-feature, .oc-map-borders path');\n for (const p of paths) {\n p.removeAttribute('vector-effect');\n }\n // Reset point radii when not zoomed\n const points = svg.querySelectorAll('.oc-map-point');\n for (const p of points) {\n const baseR = Number(p.getAttribute('data-base-r') ?? 5);\n const baseSW = Number(p.getAttribute('data-base-stroke-width') ?? 1);\n p.setAttribute('r', String(baseR));\n p.setAttribute('stroke-width', String(baseSW));\n p.removeAttribute('vector-effect');\n }\n }\n}\n","/**\n * Map SVG renderer: converts a GeoMapLayout into SVG DOM elements.\n *\n * Creates an <svg> with geo feature paths, border overlays, gradient or\n * categorical legend, and chrome. All styling via inline SVG attributes from\n * layout data. Animation is pure CSS, driven by data attributes.\n */\n\nimport type {\n GeoMapBorders,\n GeoMapFeatureMark,\n GeoMapLayout,\n GeoMapPointMark,\n ResolvedAnimation,\n} from '@opendata-ai/openchart-core';\nimport { stampAnimationVars } from './animation-vars';\nimport { FOCUS_DIM_OPACITY } from './map-camera';\nimport { renderChromeElement } from './renderers/chrome';\nimport { renderLegend } from './renderers/legend';\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// Above this count, skip per-feature CSS fill animations (not GPU-compositable)\n// and fade the entire features group with a single opacity animation instead.\nconst BULK_ANIMATION_THRESHOLD = 200;\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\n// ---------------------------------------------------------------------------\n// Chrome rendering (delegates to the shared helper for text wrapping)\n// ---------------------------------------------------------------------------\n\nfunction renderChrome(parent: SVGElement, layout: GeoMapLayout): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-chrome');\n\n const { chrome, measureText } = layout;\n const bottomOffset = chrome.bottomAnchorY ?? layout.area.y + layout.area.height;\n\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 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// Watermark rendering\n// ---------------------------------------------------------------------------\n\nfunction renderWatermark(parent: SVGElement, layout: GeoMapLayout): void {\n if (layout.width < 480) return;\n\n const { width, height, theme } = layout;\n const padding = theme.spacing.padding;\n const rightEdge = width - padding;\n const bottomEdge = height - padding;\n const fill = theme.colors.axis;\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 text = createSVGElement('text');\n setAttrs(text, {\n x: rightEdge,\n y: bottomEdge,\n 'dominant-baseline': 'alphabetic',\n 'text-anchor': 'end',\n 'font-family': theme.fonts.family,\n 'font-size': 12,\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': 16 });\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// Border rendering\n// ---------------------------------------------------------------------------\n\nfunction renderBorders(parent: SVGElement, borders: GeoMapBorders): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-map-borders');\n\n // Interior borders (between features)\n if (borders.interiorPath) {\n const interior = createSVGElement('path');\n setAttrs(interior, {\n d: borders.interiorPath,\n fill: 'none',\n stroke: borders.interiorStroke,\n 'stroke-width': 0.5,\n 'stroke-linejoin': 'round',\n });\n interior.setAttribute('class', 'oc-map-border-interior');\n interior.setAttribute('pointer-events', 'none');\n g.appendChild(interior);\n }\n\n // Outline border (coastline / outer boundary)\n if (borders.outlinePath) {\n const outline = createSVGElement('path');\n setAttrs(outline, {\n d: borders.outlinePath,\n fill: 'none',\n stroke: borders.outlineStroke,\n 'stroke-width': 1,\n 'stroke-linejoin': 'round',\n });\n outline.setAttribute('class', 'oc-map-border-outline');\n outline.setAttribute('pointer-events', 'none');\n g.appendChild(outline);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Feature rendering\n// ---------------------------------------------------------------------------\n\nfunction renderFeatures(\n parent: SVGElement,\n features: GeoMapFeatureMark[],\n animation?: ResolvedAnimation,\n staggerBudget = 0,\n focusIds?: Set<string>,\n): void {\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-map-features');\n g.setAttribute('role', 'list');\n\n const bulk = features.length > BULK_ANIMATION_THRESHOLD;\n\n if (bulk && animation?.enter) {\n g.setAttribute('data-bulk-animate', '');\n }\n\n const maxIdx = features.length - 1;\n\n // Build evenly spaced delays then shuffle for organic pop-in\n // (skipped in bulk mode where the whole group fades as one)\n const shuffledDelays: number[] = [];\n if (!bulk && staggerBudget > 0 && maxIdx > 0) {\n for (let i = 0; i <= maxIdx; i++) {\n shuffledDelays.push((i / maxIdx) * staggerBudget);\n }\n // Seeded Fisher-Yates shuffle (deterministic per-map via first feature id)\n let seed = 0x9e3779b9 ^ (features.length * 2654435761);\n for (let i = maxIdx; i > 0; i--) {\n seed = (seed + 0x6d2b79f5) | 0;\n let t = seed ^ (seed >>> 15);\n t = Math.imul(t, t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n const r = ((t ^ (t >>> 14)) >>> 0) % (i + 1);\n [shuffledDelays[i], shuffledDelays[r]] = [shuffledDelays[r], shuffledDelays[i]];\n }\n }\n\n for (let i = 0; i < features.length; i++) {\n const feature = features[i];\n const path = createSVGElement('path');\n path.setAttribute('class', 'oc-map-feature');\n path.setAttribute('role', 'listitem');\n setAttrs(path, {\n d: feature.path,\n fill: feature.fill,\n stroke: feature.stroke,\n 'stroke-width': feature.strokeWidth,\n });\n path.setAttribute('data-feature-id', String(feature.id));\n path.setAttribute('data-key', String(feature.id));\n if (feature.name) {\n path.setAttribute('data-feature-name', feature.name);\n }\n if (feature.aria?.label) {\n path.setAttribute('aria-label', feature.aria.label);\n }\n\n // Under a focus, features outside the set rest at the dim opacity. Set it\n // as the resting inline opacity (correct in every render path) and as the\n // entrance animation's target so they fade straight to dim instead of\n // hitting full opacity and snapping down when the dim lands post-animation.\n const dimmed = focusIds ? !focusIds.has(String(feature.id)) : false;\n const s = (path as SVGElement & ElementCSSInlineStyle).style;\n if (dimmed) {\n s.setProperty('opacity', String(FOCUS_DIM_OPACITY));\n }\n\n // Per-feature animation props only in non-bulk mode\n if (!bulk && animation?.enter) {\n const idx = feature.animationIndex ?? i;\n path.setAttribute('data-animation-index', String(idx));\n s.setProperty('--oc-mark-index', String(idx));\n s.setProperty('--oc-feature-fill', feature.fill);\n if (dimmed) {\n s.setProperty('--oc-feature-target-opacity', String(FOCUS_DIM_OPACITY));\n }\n if (staggerBudget > 0 && maxIdx > 0) {\n s.setProperty('--oc-map-delay', `${shuffledDelays[i]}ms`);\n }\n }\n\n g.appendChild(path);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Point mark rendering\n// ---------------------------------------------------------------------------\n\nfunction renderPointMarks(\n parent: SVGElement,\n points: GeoMapPointMark[],\n animation?: ResolvedAnimation,\n): void {\n if (points.length === 0) return;\n\n const g = createSVGElement('g');\n g.setAttribute('class', 'oc-map-points');\n\n for (const pt of points) {\n const circle = createSVGElement('circle');\n circle.setAttribute('class', 'oc-map-point');\n setAttrs(circle, {\n cx: pt.cx,\n cy: pt.cy,\n r: pt.r,\n fill: pt.fill,\n 'fill-opacity': pt.fillOpacity,\n stroke: pt.stroke,\n 'stroke-width': pt.strokeWidth,\n });\n circle.setAttribute('data-point-key', pt.key);\n circle.setAttribute('data-base-r', String(pt.r));\n circle.setAttribute('data-base-stroke-width', String(pt.strokeWidth));\n if (pt.aria?.label) {\n circle.setAttribute('aria-label', pt.aria.label);\n }\n if (animation?.enter) {\n const s = (circle as unknown as ElementCSSInlineStyle).style;\n s.setProperty('--oc-mark-index', String(pt.animationIndex));\n s.setProperty('transform-origin', `${pt.cx}px ${pt.cy}px`);\n }\n g.appendChild(circle);\n }\n\n parent.appendChild(g);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Render a GeoMapLayout to an SVG element.\n */\nexport function renderMapSVG(layout: GeoMapLayout, opts?: { animate?: boolean }): SVGSVGElement {\n const { width, height, features, borders, a11y, watermark, animation } = layout;\n const animate = opts?.animate && !!animation?.enter;\n\n const svg = createSVGElement('svg') as SVGSVGElement;\n svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n svg.setAttribute('role', 'img');\n if (a11y.altText) {\n svg.setAttribute('aria-label', a11y.altText);\n }\n\n const classes = animate ? 'oc-map oc-animate' : 'oc-map';\n svg.setAttribute('class', classes);\n\n const bulk = features.length > BULK_ANIMATION_THRESHOLD;\n let mapStaggerBudget = 0;\n if (animate && animation?.enter) {\n const dur = animation.enter.duration;\n const perFeature = Math.min(dur, 500);\n if (!bulk) {\n mapStaggerBudget = Math.round(dur * 1.2);\n }\n const n = Math.max(features.length, 1);\n const stagger = !bulk && n > 1 ? mapStaggerBudget / (n - 1) : 0;\n stampAnimationVars(svg, {\n duration: perFeature,\n stagger,\n annotationDelay: animation.annotationDelay,\n ease: animation.enter.ease,\n });\n }\n\n // Empty defs element (will be filled by gradient legend)\n const defs = createSVGElement('defs');\n svg.appendChild(defs);\n\n // Create map group offset to the drawing area\n const mapGroup = createSVGElement('g');\n mapGroup.setAttribute('class', 'oc-map-group');\n mapGroup.setAttribute('transform', `translate(${layout.area.x},${layout.area.y})`);\n\n // Camera group wraps features + borders only (chrome, legend, watermark stay outside)\n const cameraGroup = createSVGElement('g');\n cameraGroup.setAttribute('class', 'oc-map-camera');\n cameraGroup.setAttribute('data-oc-map-camera', '');\n\n // Features outside the focus set rest dimmed; the renderer stamps that so it's\n // correct in every render path and the entrance fades straight to it. This\n // handles *declarative* focus (layout.focus from the spec) only. Imperative\n // focus set via zoomTo()/panTo() never re-renders, so it dims through\n // applyMapCamera + applyFocusDim on the live SVG instead.\n const focusIdSet =\n layout.focus && layout.focus.ids.length > 0 ? new Set(layout.focus.ids.map(String)) : undefined;\n\n // Render features first (so borders overlay them)\n renderFeatures(\n cameraGroup,\n features,\n animate ? animation : undefined,\n mapStaggerBudget,\n focusIdSet,\n );\n\n // Render borders on top of features\n renderBorders(cameraGroup, borders);\n\n // Render point marks inside camera group (above borders).\n // Stamp a per-point stagger so the total spread stays bounded regardless of\n // point count (the CSS hardcoded 60ms per point which explodes past ~15 pts).\n if (animate && animation?.enter && layout.pointMarks.length > 1) {\n const pointStaggerBudget = animation.enter.duration * 0.5;\n const perPoint = pointStaggerBudget / (layout.pointMarks.length - 1);\n svg.style.setProperty('--oc-point-stagger', `${perPoint}ms`);\n }\n renderPointMarks(cameraGroup, layout.pointMarks, animate ? animation : undefined);\n\n mapGroup.appendChild(cameraGroup);\n svg.appendChild(mapGroup);\n\n // Render chrome AFTER the map group so the title/subtitle paint on top of a\n // focus-zoomed map that overflows up into the chrome band. Earlier SVG\n // children paint underneath later ones, so chrome must come last of the two.\n renderChrome(svg, layout);\n\n // Render legend (continuous for quantitative, categorical for nominal)\n if (layout.continuousLegend) {\n renderLegend(svg, layout.continuousLegend);\n } else if (layout.categoricalLegend) {\n renderLegend(svg, layout.categoricalLegend);\n }\n\n // Render point legends with a semi-transparent background so they read\n // clearly over map geography (e.g. AK/HI insets in Albers USA).\n const ptLegend = layout.pointCategoricalLegend ?? layout.pointContinuousLegend;\n if (ptLegend) {\n const isDark = layout.theme.isDark;\n const padX = 10;\n const padY = 8;\n\n // Compute content width from entries so the background wraps tightly\n const swatchSize =\n 'swatchSize' in ptLegend ? (ptLegend as { swatchSize: number }).swatchSize : 10;\n const swatchGap = 'swatchGap' in ptLegend ? (ptLegend as { swatchGap: number }).swatchGap : 6;\n const entryGap = 'entryGap' in ptLegend ? (ptLegend as { entryGap: number }).entryGap : 16;\n let contentWidth = ptLegend.bounds.width;\n if ('entries' in ptLegend && ptLegend.entries) {\n const cat = ptLegend as typeof layout.pointCategoricalLegend & {\n entries: Array<{ label: string }>;\n };\n if (cat && cat.entries.length > 0) {\n const fontSize = ptLegend.labelStyle.fontSize;\n let w = 0;\n for (const entry of cat.entries) {\n w += swatchSize + swatchGap + entry.label.length * fontSize * 0.6 + entryGap;\n }\n w -= entryGap;\n contentWidth = Math.min(w, ptLegend.bounds.width);\n }\n }\n\n // Center the background rect vertically around the swatch content.\n // Overlay continuous legends ('top-left') float over map geography, so\n // their backdrop must cover the full bounds (tick labels hang below the\n // bar) instead of just the swatch row. Categorical rows keep the\n // swatch-centered backdrop in both positions.\n const isOverlayContinuous =\n ptLegend.position === 'top-left' && !('entries' in ptLegend && ptLegend.entries);\n const contentCenterY = ptLegend.bounds.y + swatchSize / 2;\n const bgHeight = isOverlayContinuous\n ? ptLegend.bounds.height + padY * 2\n : swatchSize + padY * 2;\n const bgY = isOverlayContinuous ? ptLegend.bounds.y - padY : contentCenterY - bgHeight / 2;\n const bg = createSVGElement('rect');\n setAttrs(bg, {\n x: ptLegend.bounds.x - padX,\n y: bgY,\n width: contentWidth + padX * 2,\n height: bgHeight,\n rx: 4,\n fill: isDark ? 'rgba(24,24,27,0.9)' : 'rgba(255,255,255,0.9)',\n });\n svg.appendChild(bg);\n renderLegend(svg, ptLegend);\n }\n\n // Render watermark\n if (watermark) {\n renderWatermark(svg, layout);\n }\n\n return svg;\n}\n","/**\n * Map update transition: tweens feature fills and point geometry between\n * layout snapshots.\n *\n * Captures current fill colors (and, for the point layer, radius and center)\n * before a re-render, then interpolates from previous to new values using a\n * rAF loop. Same approach as the main chart transition driver, scoped to\n * map-specific concerns.\n *\n * Features tween fill only: their geometry is a projected path, and morphing\n * one path `d` string into another is the intractable case the chart driver\n * handles with freeze-and-crossfade. Points are bare circles, so `r`/`cx`/`cy`\n * are three numbers that interpolate directly.\n */\n\nimport { interpolateRgb } from 'd3-interpolate';\nimport { easingFns } from './story/tween';\n\n/** Per-point geometry captured alongside fill so it can be tweened. */\nexport interface MapPointSnapshot {\n fill?: string;\n r?: number;\n cx?: number;\n cy?: number;\n}\n\nexport interface MapTransitionSnapshot {\n /** Feature fills, keyed by `data-key`. */\n fills: Map<string, string>;\n /** Point fill + geometry, keyed by `data-point-key`. */\n points: Map<string, MapPointSnapshot>;\n}\n\nfunction numAttr(el: Element, name: string): number | undefined {\n const raw = el.getAttribute(name);\n if (raw === null) return undefined;\n const n = Number(raw);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/**\n * Snapshot the current paint/geometry of a rendered map.\n *\n * Point keys are stored in their own map rather than being namespaced into the\n * feature map, so a point and a feature that happen to share an id can't\n * collide.\n */\nexport function captureMapSnapshot(svg: SVGElement | null): MapTransitionSnapshot {\n const fills = new Map<string, string>();\n const points = new Map<string, MapPointSnapshot>();\n if (!svg) return { fills, points };\n\n const paths = svg.querySelectorAll('.oc-map-feature[data-key]');\n for (const p of paths) {\n const key = p.getAttribute('data-key');\n const fill = p.getAttribute('fill');\n if (key && fill) fills.set(key, fill);\n }\n\n const pts = svg.querySelectorAll('.oc-map-point[data-point-key]');\n for (const p of pts) {\n const key = p.getAttribute('data-point-key');\n if (key === null) continue;\n points.set(key, {\n fill: p.getAttribute('fill') ?? undefined,\n r: numAttr(p, 'r'),\n cx: numAttr(p, 'cx'),\n cy: numAttr(p, 'cy'),\n });\n }\n\n return { fills, points };\n}\n\n/**\n * Back-compat shim for callers that only need feature fills.\n *\n * @deprecated Use {@link captureMapSnapshot}, which also carries point geometry.\n */\nexport function captureFeatureFills(svg: SVGElement | null): Map<string, string> {\n const { fills, points } = captureMapSnapshot(svg);\n const merged = new Map(fills);\n for (const [key, snap] of points) {\n if (snap.fill !== undefined) merged.set(`pt:${key}`, snap.fill);\n }\n return merged;\n}\n\n/** A single attribute being interpolated over the transition. */\ntype Tween =\n | { kind: 'fill'; el: Element; to: string; interp: (t: number) => string }\n | { kind: 'num'; el: Element; attr: 'r' | 'cx' | 'cy'; from: number; to: number };\n\nfunction applyTween(tw: Tween, eased: number): void {\n if (tw.kind === 'fill') {\n tw.el.setAttribute('fill', tw.interp(eased));\n } else {\n tw.el.setAttribute(tw.attr, String(tw.from + (tw.to - tw.from) * eased));\n }\n}\n\nfunction snapTween(tw: Tween): void {\n if (tw.kind === 'fill') {\n tw.el.setAttribute('fill', tw.to);\n } else {\n tw.el.setAttribute(tw.attr, String(tw.to));\n }\n}\n\n/**\n * Tween a re-rendered map from a previous snapshot to its current state.\n *\n * The SVG is already rendered in its final state when this is called, so every\n * from-value is written back synchronously before the first frame. Without that\n * the first painted frame would show the final state and the transition would\n * read as a snap (the same synchronous from-state rule the chart driver uses).\n */\nexport function runMapFillTransition(\n svg: SVGElement,\n prev: MapTransitionSnapshot | Map<string, string>,\n opts: { duration: number },\n): { cancel: () => void } {\n // Accept the legacy flat fill map so external callers keep working.\n const snapshot: MapTransitionSnapshot =\n prev instanceof Map\n ? {\n fills: prev,\n points: new Map(\n Array.from(prev)\n .filter(([k]) => k.startsWith('pt:'))\n .map(([k, fill]) => [k.slice(3), { fill }]),\n ),\n }\n : prev;\n\n const tweens: Tween[] = [];\n\n const features = svg.querySelectorAll('.oc-map-feature[data-key]');\n for (const p of features) {\n const key = p.getAttribute('data-key');\n const to = p.getAttribute('fill');\n const from = key ? snapshot.fills.get(key) : undefined;\n if (from && to && from !== to) {\n tweens.push({ kind: 'fill', el: p, to, interp: interpolateRgb(from, to) });\n p.setAttribute('fill', from);\n }\n }\n\n const points = svg.querySelectorAll('.oc-map-point[data-point-key]');\n for (const p of points) {\n const key = p.getAttribute('data-point-key');\n const before = key === null ? undefined : snapshot.points.get(key);\n if (!before) continue;\n\n const toFill = p.getAttribute('fill');\n if (before.fill && toFill && before.fill !== toFill) {\n tweens.push({\n kind: 'fill',\n el: p,\n to: toFill,\n interp: interpolateRgb(before.fill, toFill),\n });\n p.setAttribute('fill', before.fill);\n }\n\n // Radius and center: a step that re-encodes the size channel, or one that\n // shifts the projection, moves these. Without tweening them the dots snap\n // to their new size/place while the color eases, which reads as a reset\n // rather than a transition.\n for (const attr of ['r', 'cx', 'cy'] as const) {\n const from = before[attr];\n const to = numAttr(p, attr);\n if (from === undefined || to === undefined || from === to) continue;\n tweens.push({ kind: 'num', el: p, attr, from, to });\n p.setAttribute(attr, String(from));\n }\n }\n\n if (tweens.length === 0 || opts.duration <= 0) {\n for (const tw of tweens) snapTween(tw);\n return { cancel: () => {} };\n }\n\n const duration = opts.duration;\n let startTime: number | null = null;\n let rafId = 0;\n let cancelled = false;\n\n function tick(now: number) {\n if (cancelled) return;\n if (startTime === null) startTime = now;\n const elapsed = now - startTime;\n const t = Math.min(1, elapsed / duration);\n const eased = easingFns.easeInOutCubic(t);\n\n for (const tw of tweens) {\n applyTween(tw, eased);\n }\n\n if (t < 1) {\n rafId = requestAnimationFrame(tick);\n }\n }\n\n rafId = requestAnimationFrame(tick);\n\n return {\n cancel() {\n cancelled = true;\n cancelAnimationFrame(rafId);\n // Snap to final state\n for (const tw of tweens) {\n snapTween(tw);\n }\n },\n };\n}\n"],"mappings":"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","names":["computePosition","buildAreaPath","buildLinePath","linear","linear","color","rgb","serializeKeyValue","serializeKeyValue","buildLinePath","buildAreaPath","color","cssTokenDefault","color","getScale","SVG_NS","cleanup","elementRef","SVG_NS","cssTokenDefault","spec","createTween","SVG_NS","createSVGElement","setAttrs","prefersReducedMotion","createTween","fontsPending"]}
|