chartgpu 0.1.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/ChartGPU.d.ts +74 -0
  4. package/dist/ChartGPU.d.ts.map +1 -0
  5. package/dist/components/createDataZoomSlider.d.ts +14 -0
  6. package/dist/components/createDataZoomSlider.d.ts.map +1 -0
  7. package/dist/components/createLegend.d.ts +9 -0
  8. package/dist/components/createLegend.d.ts.map +1 -0
  9. package/dist/components/createTextOverlay.d.ts +17 -0
  10. package/dist/components/createTextOverlay.d.ts.map +1 -0
  11. package/dist/components/createTooltip.d.ts +12 -0
  12. package/dist/components/createTooltip.d.ts.map +1 -0
  13. package/dist/components/formatTooltip.d.ts +12 -0
  14. package/dist/components/formatTooltip.d.ts.map +1 -0
  15. package/dist/config/OptionResolver.d.ts +97 -0
  16. package/dist/config/OptionResolver.d.ts.map +1 -0
  17. package/dist/config/defaults.d.ts +33 -0
  18. package/dist/config/defaults.d.ts.map +1 -0
  19. package/dist/config/types.d.ts +224 -0
  20. package/dist/config/types.d.ts.map +1 -0
  21. package/dist/core/GPUContext.d.ts +210 -0
  22. package/dist/core/GPUContext.d.ts.map +1 -0
  23. package/dist/core/RenderScheduler.d.ts +132 -0
  24. package/dist/core/RenderScheduler.d.ts.map +1 -0
  25. package/dist/core/createAnimationController.d.ts +15 -0
  26. package/dist/core/createAnimationController.d.ts.map +1 -0
  27. package/dist/core/createRenderCoordinator.d.ts +71 -0
  28. package/dist/core/createRenderCoordinator.d.ts.map +1 -0
  29. package/dist/data/createDataStore.d.ts +33 -0
  30. package/dist/data/createDataStore.d.ts.map +1 -0
  31. package/dist/data/createStreamBuffer.d.ts +20 -0
  32. package/dist/data/createStreamBuffer.d.ts.map +1 -0
  33. package/dist/data/lttbSample.d.ts +5 -0
  34. package/dist/data/lttbSample.d.ts.map +1 -0
  35. package/dist/data/sampleSeries.d.ts +3 -0
  36. package/dist/data/sampleSeries.d.ts.map +1 -0
  37. package/dist/index.d.ts +25 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +5977 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/interaction/createChartSync.d.ts +12 -0
  42. package/dist/interaction/createChartSync.d.ts.map +1 -0
  43. package/dist/interaction/createEventManager.d.ts +24 -0
  44. package/dist/interaction/createEventManager.d.ts.map +1 -0
  45. package/dist/interaction/createHoverState.d.ts +20 -0
  46. package/dist/interaction/createHoverState.d.ts.map +1 -0
  47. package/dist/interaction/createInsideZoom.d.ts +14 -0
  48. package/dist/interaction/createInsideZoom.d.ts.map +1 -0
  49. package/dist/interaction/createZoomState.d.ts +37 -0
  50. package/dist/interaction/createZoomState.d.ts.map +1 -0
  51. package/dist/interaction/findNearestPoint.d.ts +61 -0
  52. package/dist/interaction/findNearestPoint.d.ts.map +1 -0
  53. package/dist/interaction/findPieSlice.d.ts +36 -0
  54. package/dist/interaction/findPieSlice.d.ts.map +1 -0
  55. package/dist/interaction/findPointsAtX.d.ts +37 -0
  56. package/dist/interaction/findPointsAtX.d.ts.map +1 -0
  57. package/dist/renderers/createAreaRenderer.d.ts +18 -0
  58. package/dist/renderers/createAreaRenderer.d.ts.map +1 -0
  59. package/dist/renderers/createAxisRenderer.d.ts +19 -0
  60. package/dist/renderers/createAxisRenderer.d.ts.map +1 -0
  61. package/dist/renderers/createBarRenderer.d.ts +20 -0
  62. package/dist/renderers/createBarRenderer.d.ts.map +1 -0
  63. package/dist/renderers/createCrosshairRenderer.d.ts +43 -0
  64. package/dist/renderers/createCrosshairRenderer.d.ts.map +1 -0
  65. package/dist/renderers/createGridRenderer.d.ts +44 -0
  66. package/dist/renderers/createGridRenderer.d.ts.map +1 -0
  67. package/dist/renderers/createHighlightRenderer.d.ts +39 -0
  68. package/dist/renderers/createHighlightRenderer.d.ts.map +1 -0
  69. package/dist/renderers/createLineRenderer.d.ts +18 -0
  70. package/dist/renderers/createLineRenderer.d.ts.map +1 -0
  71. package/dist/renderers/createPieRenderer.d.ts +18 -0
  72. package/dist/renderers/createPieRenderer.d.ts.map +1 -0
  73. package/dist/renderers/createScatterRenderer.d.ts +19 -0
  74. package/dist/renderers/createScatterRenderer.d.ts.map +1 -0
  75. package/dist/renderers/rendererUtils.d.ts +100 -0
  76. package/dist/renderers/rendererUtils.d.ts.map +1 -0
  77. package/dist/themes/darkTheme.d.ts +11 -0
  78. package/dist/themes/darkTheme.d.ts.map +1 -0
  79. package/dist/themes/index.d.ts +8 -0
  80. package/dist/themes/index.d.ts.map +1 -0
  81. package/dist/themes/lightTheme.d.ts +11 -0
  82. package/dist/themes/lightTheme.d.ts.map +1 -0
  83. package/dist/themes/types.d.ts +14 -0
  84. package/dist/themes/types.d.ts.map +1 -0
  85. package/dist/utils/checkWebGPU.d.ts +39 -0
  86. package/dist/utils/checkWebGPU.d.ts.map +1 -0
  87. package/dist/utils/colors.d.ts +14 -0
  88. package/dist/utils/colors.d.ts.map +1 -0
  89. package/dist/utils/easing.d.ts +9 -0
  90. package/dist/utils/easing.d.ts.map +1 -0
  91. package/dist/utils/scales.d.ts +79 -0
  92. package/dist/utils/scales.d.ts.map +1 -0
  93. package/package.json +56 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/core/GPUContext.ts","../src/data/createDataStore.ts","../src/data/lttbSample.ts","../src/data/sampleSeries.ts","../src/shaders/grid.wgsl?raw","../src/renderers/rendererUtils.ts","../src/utils/colors.ts","../src/renderers/createAxisRenderer.ts","../src/renderers/createGridRenderer.ts","../src/shaders/area.wgsl?raw","../src/renderers/createAreaRenderer.ts","../src/shaders/line.wgsl?raw","../src/renderers/createLineRenderer.ts","../src/shaders/bar.wgsl?raw","../src/renderers/createBarRenderer.ts","../src/shaders/scatter.wgsl?raw","../src/renderers/createScatterRenderer.ts","../src/shaders/pie.wgsl?raw","../src/renderers/createPieRenderer.ts","../src/shaders/crosshair.wgsl?raw","../src/data/createStreamBuffer.ts","../src/renderers/createCrosshairRenderer.ts","../src/shaders/highlight.wgsl?raw","../src/renderers/createHighlightRenderer.ts","../src/interaction/createEventManager.ts","../src/interaction/createInsideZoom.ts","../src/interaction/createZoomState.ts","../src/interaction/findNearestPoint.ts","../src/interaction/findPointsAtX.ts","../src/interaction/findPieSlice.ts","../src/utils/scales.ts","../src/components/createTextOverlay.ts","../src/components/createLegend.ts","../src/components/createTooltip.ts","../src/components/formatTooltip.ts","../src/core/createAnimationController.ts","../src/utils/easing.ts","../src/core/createRenderCoordinator.ts","../src/config/defaults.ts","../src/themes/darkTheme.ts","../src/themes/lightTheme.ts","../src/themes/index.ts","../src/config/OptionResolver.ts","../src/components/createDataZoomSlider.ts","../src/utils/checkWebGPU.ts","../src/ChartGPU.ts","../src/interaction/createChartSync.ts","../src/core/RenderScheduler.ts","../src/index.ts"],"sourcesContent":["/**\n * GPUContext - WebGPU device and adapter management\n * \n * Handles WebGPU initialization, adapter selection, and device creation\n * following WebGPU best practices for resource management and error handling.\n * \n * This module provides both functional and class-based APIs for maximum flexibility.\n */\n\n/**\n * Represents the state of a GPU context.\n * All properties are readonly to ensure immutability.\n */\nexport interface GPUContextState {\n readonly adapter: GPUAdapter | null;\n readonly device: GPUDevice | null;\n readonly initialized: boolean;\n readonly canvas: HTMLCanvasElement | null;\n readonly canvasContext: GPUCanvasContext | null;\n readonly preferredFormat: GPUTextureFormat | null;\n}\n\n/**\n * Creates a new GPUContext state with initial values.\n * \n * @param canvas - Optional HTMLCanvasElement to configure for WebGPU rendering\n * @returns A new GPUContextState instance\n */\nexport function createGPUContext(canvas?: HTMLCanvasElement): GPUContextState {\n return {\n adapter: null,\n device: null,\n initialized: false,\n canvas: canvas || null,\n canvasContext: null,\n preferredFormat: null,\n };\n}\n\n/**\n * Initializes the WebGPU context by requesting an adapter and device.\n * Returns a new state object with initialized values.\n * \n * @param context - The GPU context state to initialize\n * @returns A new GPUContextState with initialized adapter and device\n * @throws {Error} If WebGPU is not available in the browser\n * @throws {Error} If adapter request fails\n * @throws {Error} If device request fails\n * @throws {Error} If already initialized\n */\nexport async function initializeGPUContext(\n context: GPUContextState\n): Promise<GPUContextState> {\n if (context.initialized) {\n throw new Error('GPUContext is already initialized. Call destroyGPUContext() before reinitializing.');\n }\n\n // Check for WebGPU support\n if (!navigator.gpu) {\n throw new Error(\n 'WebGPU is not available in this browser. ' +\n 'Please use a browser that supports WebGPU (Chrome 113+, Edge 113+, or Safari 18+). ' +\n 'Ensure WebGPU is enabled in browser flags if needed.'\n );\n }\n\n let device: GPUDevice | null = null;\n\n try {\n // Request adapter with high-performance preference\n const adapter = await navigator.gpu.requestAdapter({\n powerPreference: 'high-performance',\n });\n\n if (!adapter) {\n throw new Error(\n 'Failed to request WebGPU adapter. ' +\n 'No compatible adapter found. This may occur if no GPU is available or WebGPU is disabled.'\n );\n }\n\n // Request device from adapter\n device = await adapter.requestDevice();\n\n if (!device) {\n throw new Error('Failed to request WebGPU device from adapter.');\n }\n\n // Set up device lost handler for error recovery\n device.addEventListener('uncapturederror', (event: GPUUncapturedErrorEvent) => {\n console.error('WebGPU uncaptured error:', event.error);\n });\n\n let canvasContext: GPUCanvasContext | null = null;\n let preferredFormat: GPUTextureFormat | null = null;\n\n // Configure canvas if provided\n if (context.canvas) {\n const webgpuContext = context.canvas.getContext('webgpu') as GPUCanvasContext | null;\n \n if (!webgpuContext) {\n // Clean up device before throwing\n try {\n device.destroy();\n } catch (error) {\n console.warn('Error destroying device during canvas setup failure:', error);\n }\n throw new Error('Failed to get WebGPU context from canvas.');\n }\n\n // Handle device pixel ratio for high-DPI displays\n const dpr = window.devicePixelRatio || 1;\n const displayWidth = context.canvas.clientWidth || context.canvas.width;\n const displayHeight = context.canvas.clientHeight || context.canvas.height;\n \n // Set canvas internal size based on device pixel ratio\n context.canvas.width = Math.max(1, Math.floor(displayWidth * dpr));\n context.canvas.height = Math.max(1, Math.floor(displayHeight * dpr));\n\n // Get preferred format from adapter, fallback to bgra8unorm\n // Note: getPreferredCanvasFormat may not be in type definitions yet\n const adapterWithFormat = adapter as GPUAdapter & { getPreferredCanvasFormat?: () => GPUTextureFormat };\n preferredFormat = adapterWithFormat.getPreferredCanvasFormat?.() || 'bgra8unorm';\n\n // Configure the canvas context\n webgpuContext.configure({\n device: device,\n format: preferredFormat,\n });\n\n canvasContext = webgpuContext;\n }\n\n return {\n adapter,\n device,\n initialized: true,\n canvas: context.canvas,\n canvasContext,\n preferredFormat,\n };\n } catch (error) {\n // If a device was created but initialization failed, destroy it to avoid leaks.\n if (device) {\n try {\n device.destroy();\n } catch (destroyError) {\n console.warn('Error destroying device during initialization failure:', destroyError);\n }\n }\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(`Failed to initialize GPUContext: ${String(error)}`);\n }\n}\n\n/**\n * Gets the current texture from the canvas context.\n * \n * @param context - The GPU context state\n * @returns The current canvas texture\n * @throws {Error} If canvas is not configured or context is not initialized\n * \n * @example\n * ```typescript\n * const texture = getCanvasTexture(context);\n * // Use texture in render pass\n * ```\n */\nexport function getCanvasTexture(context: GPUContextState): GPUTexture {\n if (!context.canvas) {\n throw new Error('Canvas is not configured. Provide a canvas element when creating the context.');\n }\n\n if (!context.initialized || !context.canvasContext) {\n throw new Error('GPUContext is not initialized. Call initializeGPUContext() first.');\n }\n\n return context.canvasContext.getCurrentTexture();\n}\n\n/**\n * Clears the canvas to a solid color.\n * Creates a command encoder, begins a render pass with the specified clear color,\n * ends the pass, and submits it to the queue.\n * \n * @param context - The GPU context state\n * @param r - Red component (0.0 to 1.0)\n * @param g - Green component (0.0 to 1.0)\n * @param b - Blue component (0.0 to 1.0)\n * @param a - Alpha component (0.0 to 1.0)\n * @throws {Error} If canvas is not configured or context is not initialized\n * @throws {Error} If device is not available\n * \n * @example\n * ```typescript\n * // Clear to dark purple (#1a1a2e)\n * clearScreen(context, 0x1a / 255, 0x1a / 255, 0x2e / 255, 1.0);\n * ```\n */\nexport function clearScreen(\n context: GPUContextState,\n r: number,\n g: number,\n b: number,\n a: number\n): void {\n // Validate color component ranges\n if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1 || a < 0 || a > 1) {\n throw new Error('Color components must be in the range [0.0, 1.0]');\n }\n\n if (!context.canvas) {\n throw new Error('Canvas is not configured. Provide a canvas element when creating the context.');\n }\n\n if (!context.initialized || !context.device || !context.canvasContext) {\n throw new Error('GPUContext is not initialized. Call initializeGPUContext() first.');\n }\n\n // Get the current texture from the canvas\n const texture = getCanvasTexture(context);\n\n // Create command encoder\n const encoder = context.device.createCommandEncoder();\n\n // Begin render pass with clear color\n const renderPass = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: texture.createView(),\n clearValue: { r, g, b, a },\n loadOp: 'clear',\n storeOp: 'store',\n },\n ],\n });\n\n // End render pass\n renderPass.end();\n\n // Submit command buffer to queue\n context.device.queue.submit([encoder.finish()]);\n}\n\n/**\n * Destroys the WebGPU device and cleans up resources.\n * Returns a new state object with reset values.\n * After calling this, the context must be reinitialized before use.\n * \n * @param context - The GPU context state to destroy\n * @returns A new GPUContextState with reset values\n */\nexport function destroyGPUContext(context: GPUContextState): GPUContextState {\n if (context.device) {\n try {\n context.device.destroy();\n } catch (error) {\n console.warn('Error destroying GPU device:', error);\n }\n }\n\n return {\n adapter: null,\n device: null,\n initialized: false,\n canvas: context.canvas,\n canvasContext: null,\n preferredFormat: null,\n };\n}\n\n/**\n * Convenience function that creates and initializes a GPU context in one step.\n * \n * @param canvas - Optional HTMLCanvasElement to configure for WebGPU rendering\n * @returns A fully initialized GPUContextState\n * @throws {Error} If initialization fails\n * \n * @example\n * ```typescript\n * const context = await createGPUContextAsync();\n * const device = context.device;\n * ```\n * \n * @example\n * ```typescript\n * const canvas = document.querySelector('canvas');\n * const context = await createGPUContextAsync(canvas);\n * const texture = getCanvasTexture(context);\n * ```\n */\nexport async function createGPUContextAsync(\n canvas?: HTMLCanvasElement\n): Promise<GPUContextState> {\n const context = createGPUContext(canvas);\n return initializeGPUContext(context);\n}\n\n/**\n * GPUContext class wrapper for backward compatibility.\n * \n * This class provides a class-based API that internally uses the functional implementation.\n * Use the functional API directly for better type safety and immutability.\n */\nexport class GPUContext {\n private _state: GPUContextState;\n\n /**\n * Gets the WebGPU adapter, or null if not initialized.\n */\n get adapter(): GPUAdapter | null {\n return this._state.adapter;\n }\n\n /**\n * Gets the WebGPU device, or null if not initialized.\n */\n get device(): GPUDevice | null {\n return this._state.device;\n }\n\n /**\n * Checks if the context has been initialized.\n */\n get initialized(): boolean {\n return this._state.initialized;\n }\n\n /**\n * Gets the canvas element, or null if not provided.\n */\n get canvas(): HTMLCanvasElement | null {\n return this._state.canvas;\n }\n\n /**\n * Gets the WebGPU canvas context, or null if canvas is not configured.\n */\n get canvasContext(): GPUCanvasContext | null {\n return this._state.canvasContext;\n }\n\n /**\n * Gets the preferred canvas format, or null if canvas is not configured.\n */\n get preferredFormat(): GPUTextureFormat | null {\n return this._state.preferredFormat;\n }\n\n /**\n * Creates a new GPUContext instance.\n * \n * @param canvas - Optional HTMLCanvasElement to configure for WebGPU rendering\n */\n constructor(canvas?: HTMLCanvasElement) {\n this._state = createGPUContext(canvas);\n }\n\n /**\n * Initializes the WebGPU context by requesting an adapter and device.\n * \n * @throws {Error} If WebGPU is not available in the browser\n * @throws {Error} If adapter request fails\n * @throws {Error} If device request fails\n * @throws {Error} If already initialized\n */\n async initialize(): Promise<void> {\n this._state = await initializeGPUContext(this._state);\n }\n\n /**\n * Static factory method to create and initialize a GPUContext instance.\n * \n * @param canvas - Optional HTMLCanvasElement to configure for WebGPU rendering\n * @returns A fully initialized GPUContext instance\n * @throws {Error} If initialization fails\n * \n * @example\n * ```typescript\n * const context = await GPUContext.create();\n * const device = context.device;\n * ```\n * \n * @example\n * ```typescript\n * const canvas = document.querySelector('canvas');\n * const context = await GPUContext.create(canvas);\n * const texture = context.getCanvasTexture();\n * ```\n */\n static async create(canvas?: HTMLCanvasElement): Promise<GPUContext> {\n const context = new GPUContext(canvas);\n await context.initialize();\n return context;\n }\n\n /**\n * Gets the current texture from the canvas context.\n * \n * @returns The current canvas texture\n * @throws {Error} If canvas is not configured or context is not initialized\n * \n * @example\n * ```typescript\n * const texture = context.getCanvasTexture();\n * // Use texture in render pass\n * ```\n */\n getCanvasTexture(): GPUTexture {\n return getCanvasTexture(this._state);\n }\n\n /**\n * Clears the canvas to a solid color.\n * Creates a command encoder, begins a render pass with the specified clear color,\n * ends the pass, and submits it to the queue.\n * \n * @param r - Red component (0.0 to 1.0)\n * @param g - Green component (0.0 to 1.0)\n * @param b - Blue component (0.0 to 1.0)\n * @param a - Alpha component (0.0 to 1.0)\n * @throws {Error} If canvas is not configured or context is not initialized\n * @throws {Error} If device is not available\n * \n * @example\n * ```typescript\n * // Clear to dark purple (#1a1a2e)\n * context.clearScreen(0x1a / 255, 0x1a / 255, 0x2e / 255, 1.0);\n * ```\n */\n clearScreen(r: number, g: number, b: number, a: number): void {\n clearScreen(this._state, r, g, b, a);\n }\n\n /**\n * Destroys the WebGPU device and cleans up resources.\n * After calling destroy(), the context must be reinitialized before use.\n */\n destroy(): void {\n this._state = destroyGPUContext(this._state);\n }\n}\n","import type { DataPoint, DataPointTuple } from '../config/types';\n\nexport interface DataStore {\n setSeries(index: number, data: ReadonlyArray<DataPoint>): void;\n /**\n * Appends new points to an existing series without re-uploading the entire buffer when possible.\n *\n * - Reuses the same geometric growth policy as `setSeries`.\n * - When no reallocation is needed, writes only the appended byte range via `queue.writeBuffer(...)`.\n * - Maintains `pointCount` and a CPU-side combined data array so `getSeriesData(...)` remains correct.\n *\n * Throws if the series has not been set yet.\n */\n appendSeries(index: number, newPoints: ReadonlyArray<DataPoint>): void;\n removeSeries(index: number): void;\n getSeriesBuffer(index: number): GPUBuffer;\n /**\n * Returns the number of points last set for the given series index.\n *\n * Throws if the series has not been set yet.\n */\n getSeriesPointCount(index: number): number;\n /**\n * Returns the last CPU-side data set for the given series index.\n *\n * This is intended for internal metadata/hit-testing paths that need the same\n * input array that was packed into the GPU buffer (without re-threading it\n * through other state). Throws if the series has not been set yet.\n */\n getSeriesData(index: number): ReadonlyArray<DataPoint>;\n dispose(): void;\n}\n\ntype SeriesEntry = {\n readonly buffer: GPUBuffer;\n readonly capacityBytes: number;\n readonly pointCount: number;\n readonly hash32: number;\n // Store a mutable array so streaming append can update in-place.\n readonly data: DataPoint[];\n};\n\nconst MIN_BUFFER_BYTES = 4;\n\nfunction roundUpToMultipleOf4(bytes: number): number {\n return (bytes + 3) & ~3;\n}\n\nfunction nextPow2(bytes: number): number {\n if (!Number.isFinite(bytes) || bytes <= 0) return 1;\n const n = Math.ceil(bytes);\n return 2 ** Math.ceil(Math.log2(n));\n}\n\nfunction computeGrownCapacityBytes(currentCapacityBytes: number, requiredBytes: number): number {\n // Grow geometrically to reduce buffer churn (power-of-two policy).\n // Enforce 4-byte alignment via MIN_BUFFER_BYTES (>= 4) and power-of-two growth.\n const required = Math.max(MIN_BUFFER_BYTES, roundUpToMultipleOf4(requiredBytes));\n const grown = Math.max(MIN_BUFFER_BYTES, nextPow2(required));\n return Math.max(currentCapacityBytes, grown);\n}\n\nfunction isTupleDataPoint(point: DataPoint): point is DataPointTuple {\n // `DataPoint` uses a readonly tuple; `Array.isArray` doesn't narrow it well without a predicate.\n return Array.isArray(point);\n}\n\nfunction packDataPoints(\n data: ReadonlyArray<DataPoint>\n): { readonly buffer: ArrayBuffer; readonly f32: Float32Array } {\n // Allocate with an explicit ArrayBuffer so we can upload that buffer directly\n // (typed as `ArrayBuffer`) to satisfy `@webgpu/types` without unsafe casts.\n const buffer = new ArrayBuffer(data.length * 2 * 4);\n const f32 = new Float32Array(buffer);\n\n for (let i = 0; i < data.length; i++) {\n const point = data[i];\n const x = isTupleDataPoint(point) ? point[0] : point.x;\n const y = isTupleDataPoint(point) ? point[1] : point.y;\n f32[i * 2 + 0] = x;\n f32[i * 2 + 1] = y;\n }\n\n return { buffer, f32 };\n}\n\nfunction fnv1aUpdate(hash: number, words: Uint32Array): number {\n let h = hash >>> 0;\n for (let i = 0; i < words.length; i++) {\n h ^= words[i]!;\n h = Math.imul(h, 0x01000193) >>> 0; // FNV prime\n }\n return h >>> 0;\n}\n\n/**\n * Computes a stable 32-bit hash of the Float32 contents using their IEEE-754\n * bit patterns (not numeric equality), to cheaply detect changes.\n */\nfunction hashFloat32ArrayBits(data: Float32Array): number {\n const u32 = new Uint32Array(data.buffer, data.byteOffset, data.byteLength / 4);\n return fnv1aUpdate(0x811c9dc5, u32); // FNV-1a offset basis\n}\n\nexport function createDataStore(device: GPUDevice): DataStore {\n const series = new Map<number, SeriesEntry>();\n let disposed = false;\n\n const assertNotDisposed = (): void => {\n if (disposed) {\n throw new Error('DataStore is disposed.');\n }\n };\n\n const getSeriesEntry = (index: number): SeriesEntry => {\n assertNotDisposed();\n const entry = series.get(index);\n if (!entry) {\n throw new Error(`Series ${index} has no data. Call setSeries(${index}, data) first.`);\n }\n return entry;\n };\n\n const setSeries = (index: number, data: ReadonlyArray<DataPoint>): void => {\n assertNotDisposed();\n\n const packed = packDataPoints(data);\n const pointCount = data.length;\n const hash32 = hashFloat32ArrayBits(packed.f32);\n\n const requiredBytes = roundUpToMultipleOf4(packed.f32.byteLength);\n const targetBytes = Math.max(MIN_BUFFER_BYTES, requiredBytes);\n\n const existing = series.get(index);\n const unchanged = existing && existing.pointCount === pointCount && existing.hash32 === hash32;\n if (unchanged) return;\n\n let buffer = existing?.buffer ?? null;\n let capacityBytes = existing?.capacityBytes ?? 0;\n\n if (!buffer || targetBytes > capacityBytes) {\n const maxBufferSize = device.limits.maxBufferSize;\n if (targetBytes > maxBufferSize) {\n throw new Error(\n `DataStore.setSeries(${index}): required buffer size ${targetBytes} exceeds device.limits.maxBufferSize (${maxBufferSize}).`\n );\n }\n\n if (buffer) {\n try {\n buffer.destroy();\n } catch {\n // Ignore destroy errors; we are replacing the buffer anyway.\n }\n }\n\n const grownCapacityBytes = computeGrownCapacityBytes(capacityBytes, targetBytes);\n if (grownCapacityBytes > maxBufferSize) {\n // If geometric growth would exceed the limit, fall back to the exact required size.\n // (Still no shrink: if current capacity was already larger, we'd keep it above.)\n // NOTE: targetBytes is already checked against maxBufferSize above.\n capacityBytes = targetBytes;\n } else {\n capacityBytes = grownCapacityBytes;\n }\n\n buffer = device.createBuffer({\n size: capacityBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n // Avoid 0-byte writes (empty series). The buffer is still valid for binding.\n if (packed.f32.byteLength > 0) {\n device.queue.writeBuffer(buffer, 0, packed.buffer);\n }\n\n series.set(index, {\n buffer,\n capacityBytes,\n pointCount,\n hash32,\n data: data.length === 0 ? [] : data.slice(),\n });\n };\n\n const appendSeries = (index: number, newPoints: ReadonlyArray<DataPoint>): void => {\n assertNotDisposed();\n if (!newPoints || newPoints.length === 0) return;\n\n const existing = getSeriesEntry(index);\n const prevPointCount = existing.pointCount;\n const nextPointCount = prevPointCount + newPoints.length;\n\n const appendPacked = packDataPoints(newPoints);\n const appendBytes = appendPacked.f32.byteLength;\n\n // Each point is 2 floats (x, y) = 8 bytes.\n const requiredBytes = roundUpToMultipleOf4(nextPointCount * 2 * 4);\n const targetBytes = Math.max(MIN_BUFFER_BYTES, requiredBytes);\n\n let buffer = existing.buffer;\n let capacityBytes = existing.capacityBytes;\n\n // Ensure the CPU-side store is updated regardless of GPU growth path.\n const nextData = existing.data;\n nextData.push(...newPoints);\n\n const maxBufferSize = device.limits.maxBufferSize;\n\n if (targetBytes > capacityBytes) {\n if (targetBytes > maxBufferSize) {\n throw new Error(\n `DataStore.appendSeries(${index}): required buffer size ${targetBytes} exceeds device.limits.maxBufferSize (${maxBufferSize}).`\n );\n }\n\n // Replace buffer (no shrink). This is the slow path; we re-upload the full series.\n try {\n buffer.destroy();\n } catch {\n // Ignore destroy errors; we are replacing the buffer anyway.\n }\n\n const grownCapacityBytes = computeGrownCapacityBytes(capacityBytes, targetBytes);\n capacityBytes = grownCapacityBytes > maxBufferSize ? targetBytes : grownCapacityBytes;\n\n buffer = device.createBuffer({\n size: capacityBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n\n const fullPacked = packDataPoints(nextData);\n if (fullPacked.f32.byteLength > 0) {\n device.queue.writeBuffer(buffer, 0, fullPacked.buffer);\n }\n\n series.set(index, {\n buffer,\n capacityBytes,\n pointCount: nextPointCount,\n hash32: hashFloat32ArrayBits(fullPacked.f32),\n data: nextData,\n });\n return;\n }\n\n // Fast path: write only the appended range into the existing buffer.\n if (appendBytes > 0) {\n const byteOffset = prevPointCount * 2 * 4;\n device.queue.writeBuffer(buffer, byteOffset, appendPacked.buffer);\n }\n\n // Incremental FNV-1a update over the appended IEEE-754 bit patterns.\n const appendWords = new Uint32Array(appendPacked.f32.buffer, appendPacked.f32.byteOffset, appendPacked.f32.byteLength / 4);\n const nextHash32 = fnv1aUpdate(existing.hash32, appendWords);\n\n series.set(index, {\n buffer,\n capacityBytes,\n pointCount: nextPointCount,\n hash32: nextHash32,\n data: nextData,\n });\n };\n\n const removeSeries = (index: number): void => {\n assertNotDisposed();\n\n const entry = series.get(index);\n if (!entry) return;\n\n try {\n entry.buffer.destroy();\n } catch {\n // Ignore destroy errors; removal should be best-effort.\n }\n series.delete(index);\n };\n\n const getSeriesBuffer = (index: number): GPUBuffer => {\n return getSeriesEntry(index).buffer;\n };\n\n const getSeriesPointCount = (index: number): number => {\n return getSeriesEntry(index).pointCount;\n };\n\n const getSeriesData = (index: number): ReadonlyArray<DataPoint> => {\n return getSeriesEntry(index).data;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n\n for (const entry of series.values()) {\n try {\n entry.buffer.destroy();\n } catch {\n // Ignore destroy errors; disposal should be best-effort.\n }\n }\n series.clear();\n };\n\n return {\n setSeries,\n appendSeries,\n removeSeries,\n getSeriesBuffer,\n getSeriesPointCount,\n getSeriesData,\n dispose,\n };\n}\n\n","import type { DataPoint, DataPointTuple } from '../config/types';\n\nfunction isTupleDataPoint(point: DataPoint): point is DataPointTuple {\n // `DataPoint` uses a readonly tuple; `Array.isArray` doesn't narrow it well without a predicate.\n return Array.isArray(point);\n}\n\nfunction lttbIndicesForInterleavedXY(data: Float32Array, targetPoints: number): Int32Array {\n const n = data.length >>> 1; // floor(length / 2)\n const lastIndex = n - 1;\n\n if (targetPoints <= 0 || n === 0) return new Int32Array(0);\n if (targetPoints === 1) return new Int32Array([0]);\n if (targetPoints === 2) return n >= 2 ? new Int32Array([0, lastIndex]) : new Int32Array([0]);\n if (n <= targetPoints) {\n const indices = new Int32Array(n);\n for (let i = 0; i < n; i++) indices[i] = i;\n return indices;\n }\n\n const indices = new Int32Array(targetPoints);\n indices[0] = 0;\n indices[targetPoints - 1] = lastIndex;\n\n const bucketSize = (n - 2) / (targetPoints - 2);\n\n let a = 0;\n let out = 1;\n\n const lastX = data[lastIndex * 2 + 0];\n const lastY = data[lastIndex * 2 + 1];\n\n for (let bucket = 0; bucket < targetPoints - 2; bucket++) {\n // Current bucket: candidate points are [rangeStart, rangeEndExclusive) and never include lastIndex.\n let rangeStart = Math.floor(bucketSize * bucket) + 1;\n let rangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 1)) + 1, lastIndex);\n if (rangeStart >= rangeEndExclusive) {\n // Defensive: ensure at least one candidate point.\n rangeStart = Math.min(rangeStart, lastIndex - 1);\n rangeEndExclusive = Math.min(rangeStart + 1, lastIndex);\n }\n\n // Next bucket for average: [nextRangeStart, nextRangeEndExclusive)\n const nextRangeStart = Math.floor(bucketSize * (bucket + 1)) + 1;\n const nextRangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 2)) + 1, lastIndex);\n\n // If there are no points in the next bucket, use the last point as the average.\n let avgX = lastX;\n let avgY = lastY;\n if (nextRangeStart < nextRangeEndExclusive) {\n let sumX = 0;\n let sumY = 0;\n let avgCount = 0;\n for (let i = nextRangeStart; i < nextRangeEndExclusive; i++) {\n sumX += data[i * 2 + 0];\n sumY += data[i * 2 + 1];\n avgCount++;\n }\n if (avgCount > 0) {\n avgX = sumX / avgCount;\n avgY = sumY / avgCount;\n }\n }\n\n const ax = data[a * 2 + 0];\n const ay = data[a * 2 + 1];\n\n let maxArea = -1;\n let maxIndex = rangeStart;\n for (let i = rangeStart; i < rangeEndExclusive; i++) {\n const bx = data[i * 2 + 0];\n const by = data[i * 2 + 1];\n const area2 = (ax - avgX) * (by - ay) - (ax - bx) * (avgY - ay);\n const absArea2 = area2 < 0 ? -area2 : area2;\n if (absArea2 > maxArea) {\n maxArea = absArea2;\n maxIndex = i;\n }\n }\n\n indices[out++] = maxIndex;\n a = maxIndex;\n }\n\n return indices;\n}\n\nfunction lttbIndicesForDataPoints(data: ReadonlyArray<DataPoint>, targetPoints: number): Int32Array {\n const n = data.length;\n const lastIndex = n - 1;\n\n if (targetPoints <= 0 || n === 0) return new Int32Array(0);\n if (targetPoints === 1) return new Int32Array([0]);\n if (targetPoints === 2) return n >= 2 ? new Int32Array([0, lastIndex]) : new Int32Array([0]);\n if (n <= targetPoints) {\n const indices = new Int32Array(n);\n for (let i = 0; i < n; i++) indices[i] = i;\n return indices;\n }\n\n const indices = new Int32Array(targetPoints);\n indices[0] = 0;\n indices[targetPoints - 1] = lastIndex;\n\n const bucketSize = (n - 2) / (targetPoints - 2);\n\n let a = 0;\n let out = 1;\n\n const pLast = data[lastIndex]!;\n const lastX = isTupleDataPoint(pLast) ? pLast[0] : pLast.x;\n const lastY = isTupleDataPoint(pLast) ? pLast[1] : pLast.y;\n\n for (let bucket = 0; bucket < targetPoints - 2; bucket++) {\n // Current bucket: candidate points are [rangeStart, rangeEndExclusive) and never include lastIndex.\n let rangeStart = Math.floor(bucketSize * bucket) + 1;\n let rangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 1)) + 1, lastIndex);\n if (rangeStart >= rangeEndExclusive) {\n // Defensive: ensure at least one candidate point.\n rangeStart = Math.min(rangeStart, lastIndex - 1);\n rangeEndExclusive = Math.min(rangeStart + 1, lastIndex);\n }\n\n // Next bucket for average: [nextRangeStart, nextRangeEndExclusive)\n const nextRangeStart = Math.floor(bucketSize * (bucket + 1)) + 1;\n const nextRangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 2)) + 1, lastIndex);\n\n // If there are no points in the next bucket, use the last point as the average.\n let avgX = lastX;\n let avgY = lastY;\n if (nextRangeStart < nextRangeEndExclusive) {\n let sumX = 0;\n let sumY = 0;\n let avgCount = 0;\n for (let i = nextRangeStart; i < nextRangeEndExclusive; i++) {\n const p = data[i]!;\n const x = isTupleDataPoint(p) ? p[0] : p.x;\n const y = isTupleDataPoint(p) ? p[1] : p.y;\n sumX += x;\n sumY += y;\n avgCount++;\n }\n if (avgCount > 0) {\n avgX = sumX / avgCount;\n avgY = sumY / avgCount;\n }\n }\n\n const pa = data[a]!;\n const ax = isTupleDataPoint(pa) ? pa[0] : pa.x;\n const ay = isTupleDataPoint(pa) ? pa[1] : pa.y;\n\n let maxArea = -1;\n let maxIndex = rangeStart;\n for (let i = rangeStart; i < rangeEndExclusive; i++) {\n const pb = data[i]!;\n const bx = isTupleDataPoint(pb) ? pb[0] : pb.x;\n const by = isTupleDataPoint(pb) ? pb[1] : pb.y;\n const area2 = (ax - avgX) * (by - ay) - (ax - bx) * (avgY - ay);\n const absArea2 = area2 < 0 ? -area2 : area2;\n if (absArea2 > maxArea) {\n maxArea = absArea2;\n maxIndex = i;\n }\n }\n\n indices[out++] = maxIndex;\n a = maxIndex;\n }\n\n return indices;\n}\n\nexport function lttbSample(data: Float32Array, targetPoints: number): Float32Array;\nexport function lttbSample(data: DataPoint[], targetPoints: number): DataPoint[];\nexport function lttbSample(data: ReadonlyArray<DataPoint>, targetPoints: number): ReadonlyArray<DataPoint>;\nexport function lttbSample(\n data: ReadonlyArray<DataPoint> | Float32Array,\n targetPoints: number\n): ReadonlyArray<DataPoint> | Float32Array {\n const threshold = Math.floor(targetPoints);\n\n if (data instanceof Float32Array) {\n const n = data.length >>> 1;\n if (threshold <= 0 || n === 0) return new Float32Array(0);\n\n // If we're already under the target, avoid copying.\n if (n <= threshold) return data;\n\n const indices = lttbIndicesForInterleavedXY(data, threshold);\n const out = new Float32Array(indices.length * 2);\n for (let i = 0; i < indices.length; i++) {\n const idx = indices[i]!;\n out[i * 2 + 0] = data[idx * 2 + 0];\n out[i * 2 + 1] = data[idx * 2 + 1];\n }\n return out;\n }\n\n const n = data.length;\n if (threshold <= 0 || n === 0) return [];\n\n // Story requirement: when data is shorter than the target, return original.\n if (n <= threshold) return data;\n\n const indices = lttbIndicesForDataPoints(data, threshold);\n const out = new Array<DataPoint>(indices.length);\n for (let i = 0; i < indices.length; i++) {\n out[i] = data[indices[i]!]!;\n }\n return out;\n}\n\n","import type { DataPoint, DataPointTuple, SeriesSampling } from '../config/types';\nimport { lttbSample } from './lttbSample';\n\nfunction isTupleDataPoint(point: DataPoint): point is DataPointTuple {\n return Array.isArray(point);\n}\n\nfunction getXY(point: DataPoint): { readonly x: number; readonly y: number } {\n if (isTupleDataPoint(point)) return { x: point[0], y: point[1] };\n return { x: point.x, y: point.y };\n}\n\nfunction getSize(point: DataPoint): number | undefined {\n if (isTupleDataPoint(point)) return point[2];\n return point.size;\n}\n\nfunction clampTargetPoints(targetPoints: number): number {\n const t = Math.floor(targetPoints);\n return Number.isFinite(t) ? t : 0;\n}\n\ntype BucketMode = 'average' | 'max' | 'min';\n\nfunction sampleByBuckets(\n data: ReadonlyArray<DataPoint>,\n targetPoints: number,\n mode: BucketMode\n): ReadonlyArray<DataPoint> {\n const n = data.length;\n const threshold = clampTargetPoints(targetPoints);\n\n if (threshold <= 0 || n === 0) return [];\n if (threshold === 1) return [data[0]!];\n if (threshold === 2) return n >= 2 ? [data[0]!, data[n - 1]!] : [data[0]!];\n if (n <= threshold) return data;\n\n const lastIndex = n - 1;\n const out = new Array<DataPoint>(threshold);\n out[0] = data[0]!;\n out[threshold - 1] = data[lastIndex]!;\n\n const bucketSize = (n - 2) / (threshold - 2);\n\n for (let bucket = 0; bucket < threshold - 2; bucket++) {\n let rangeStart = Math.floor(bucketSize * bucket) + 1;\n let rangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 1)) + 1, lastIndex);\n\n if (rangeStart >= rangeEndExclusive) {\n rangeStart = Math.min(rangeStart, lastIndex - 1);\n rangeEndExclusive = Math.min(rangeStart + 1, lastIndex);\n }\n\n let chosen: DataPoint | null = null;\n\n if (mode === 'average') {\n let sumX = 0;\n let sumY = 0;\n let sumSize = 0;\n let count = 0;\n let sizeCount = 0;\n for (let i = rangeStart; i < rangeEndExclusive; i++) {\n const p = data[i]!;\n const { x, y } = getXY(p);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n sumX += x;\n sumY += y;\n count++;\n\n const size = getSize(p);\n if (typeof size === 'number' && Number.isFinite(size)) {\n sumSize += size;\n sizeCount++;\n }\n }\n\n if (count > 0) {\n const avgX = sumX / count;\n const avgY = sumY / count;\n if (sizeCount > 0) {\n chosen = [avgX, avgY, sumSize / sizeCount];\n } else {\n chosen = [avgX, avgY];\n }\n }\n } else {\n let bestY = mode === 'max' ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;\n for (let i = rangeStart; i < rangeEndExclusive; i++) {\n const p = data[i]!;\n const { y } = getXY(p);\n if (!Number.isFinite(y)) continue;\n if (mode === 'max') {\n if (y > bestY) {\n bestY = y;\n chosen = p;\n }\n } else {\n if (y < bestY) {\n bestY = y;\n chosen = p;\n }\n }\n }\n }\n\n out[bucket + 1] = chosen ?? data[rangeStart]!;\n }\n\n return out;\n}\n\nexport function sampleSeriesDataPoints(\n data: ReadonlyArray<DataPoint>,\n sampling: SeriesSampling,\n samplingThreshold: number\n): ReadonlyArray<DataPoint> {\n const threshold = clampTargetPoints(samplingThreshold);\n\n // Disabled or already under threshold: keep original reference (avoid extra allocations).\n if (sampling === 'none') return data;\n if (!(threshold > 0)) return data;\n if (data.length <= threshold) return data;\n\n switch (sampling) {\n case 'lttb':\n return lttbSample(data, threshold);\n case 'average':\n return sampleByBuckets(data, threshold, 'average');\n case 'max':\n return sampleByBuckets(data, threshold, 'max');\n case 'min':\n return sampleByBuckets(data, threshold, 'min');\n default: {\n // Defensive for JS callers / widened types.\n return data;\n }\n }\n}\n\n","export default \"// grid.wgsl\\n// Minimal grid line shader:\\n// - Vertex input: vec2<f32> position in clip-space coordinates\\n// - Uniforms: identity transform + solid RGBA color\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct FSUniforms {\\n color: vec4<f32>,\\n};\\n\\n@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;\\n\\nstruct VSIn {\\n @location(0) position: vec2<f32>,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn) -> VSOut {\\n var out: VSOut;\\n out.clipPosition = vsUniforms.transform * vec4<f32>(in.position, 0.0, 1.0);\\n return out;\\n}\\n\\n@fragment\\nfn fsMain() -> @location(0) vec4<f32> {\\n return fsUniforms.color;\\n}\\n\"","/**\n * Shared renderer utilities.\n *\n * Minimal, library-friendly helpers for common WebGPU boilerplate:\n * - shader module creation\n * - render pipeline creation (ergonomic config + sensible defaults)\n * - uniform buffer creation + updates\n *\n * Notes:\n * - All helpers are pure functions; they create resources but do not mutate external state.\n * - First argument is always `device: GPUDevice`.\n */\n\nexport type ShaderStageModuleSource =\n | {\n /** Use an existing module. */\n readonly module: GPUShaderModule;\n readonly entryPoint?: string;\n readonly constants?: Record<string, GPUPipelineConstantValue>;\n }\n | {\n /** Provide WGSL code to compile. */\n readonly code: string;\n readonly label?: string;\n readonly entryPoint?: string;\n readonly constants?: Record<string, GPUPipelineConstantValue>;\n };\n\nexport type VertexStageConfig = ShaderStageModuleSource & {\n readonly buffers?: readonly GPUVertexBufferLayout[];\n};\n\nexport type FragmentStageConfig = ShaderStageModuleSource & {\n /**\n * Provide full color target states directly (most flexible).\n * If omitted, `formats` must be provided.\n */\n readonly targets?: readonly GPUColorTargetState[];\n /**\n * Convenience: provide one or more target formats and optionally a shared blend/writeMask.\n * Ignored if `targets` is provided.\n */\n readonly formats?: GPUTextureFormat | readonly GPUTextureFormat[];\n readonly blend?: GPUBlendState;\n readonly writeMask?: GPUColorWriteFlags;\n};\n\nexport type RenderPipelineConfig =\n | (RenderPipelineConfigBase & { readonly fragment: FragmentStageConfig })\n | (RenderPipelineConfigBase & { readonly fragment?: undefined });\n\nexport interface RenderPipelineConfigBase {\n readonly label?: string;\n\n /**\n * Defaults to `'auto'`.\n *\n * If you provide `bindGroupLayouts`, a pipeline layout will be created for you.\n * If both are provided, `layout` wins.\n */\n readonly layout?: GPUPipelineLayout | 'auto';\n readonly bindGroupLayouts?: readonly GPUBindGroupLayout[];\n\n readonly vertex: VertexStageConfig;\n\n readonly primitive?: GPUPrimitiveState;\n readonly depthStencil?: GPUDepthStencilState;\n readonly multisample?: GPUMultisampleState;\n}\n\nconst DEFAULT_VERTEX_ENTRY = 'vsMain';\nconst DEFAULT_FRAGMENT_ENTRY = 'fsMain';\n\nconst isPowerOfTwo = (n: number): boolean => Number.isInteger(n) && n > 0 && (n & (n - 1)) === 0;\n\nconst alignTo = (value: number, alignment: number): number => {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`alignTo(value): value must be a finite non-negative number. Received: ${String(value)}`);\n }\n if (!isPowerOfTwo(alignment)) {\n throw new Error(`alignTo(alignment): alignment must be a positive power of two. Received: ${String(alignment)}`);\n }\n const v = Math.floor(value);\n return (v + alignment - 1) & ~(alignment - 1);\n};\n\nconst getStageModule = (\n device: GPUDevice,\n stage: ShaderStageModuleSource\n): { readonly module: GPUShaderModule; readonly entryPoint: string; readonly constants?: Record<string, GPUPipelineConstantValue> } => {\n if ('module' in stage) {\n return {\n module: stage.module,\n entryPoint: stage.entryPoint || '',\n constants: stage.constants,\n };\n }\n\n return {\n module: createShaderModule(device, stage.code, stage.label),\n entryPoint: stage.entryPoint || '',\n constants: stage.constants,\n };\n};\n\n/**\n * Creates a shader module from WGSL source.\n */\nexport function createShaderModule(device: GPUDevice, code: string, label?: string): GPUShaderModule {\n if (typeof code !== 'string' || code.length === 0) {\n throw new Error('createShaderModule(code): WGSL code must be a non-empty string.');\n }\n return device.createShaderModule({ code, label });\n}\n\n/**\n * Creates a render pipeline with reduced boilerplate and sensible defaults.\n *\n * Defaults:\n * - `layout: 'auto'`\n * - `vertex.entryPoint: 'vsMain'`\n * - `fragment.entryPoint: 'fsMain'` (if fragment present)\n * - `primitive.topology: 'triangle-list'`\n * - `multisample.count: 1`\n */\nexport function createRenderPipeline(device: GPUDevice, config: RenderPipelineConfig): GPURenderPipeline {\n const layout: GPUPipelineLayout | 'auto' =\n config.layout ??\n (config.bindGroupLayouts ? device.createPipelineLayout({ bindGroupLayouts: [...config.bindGroupLayouts] }) : 'auto');\n\n const vertexStage = getStageModule(device, config.vertex);\n const vertexEntryPoint = vertexStage.entryPoint || DEFAULT_VERTEX_ENTRY;\n\n let fragment: GPUFragmentState | undefined = undefined;\n if (config.fragment) {\n const fragmentStage = getStageModule(device, config.fragment);\n const fragmentEntryPoint = fragmentStage.entryPoint || DEFAULT_FRAGMENT_ENTRY;\n\n let targets: readonly GPUColorTargetState[] | undefined = config.fragment.targets;\n if (!targets) {\n const formats = config.fragment.formats;\n if (!formats) {\n throw new Error(\n \"createRenderPipeline(fragment): provide either `fragment.targets` or `fragment.formats` when a fragment stage is present.\"\n );\n }\n const formatList = Array.isArray(formats) ? formats : [formats];\n targets = formatList.map((format) => ({\n format,\n blend: config.fragment!.blend,\n writeMask: config.fragment!.writeMask,\n }));\n }\n\n fragment = {\n module: fragmentStage.module,\n entryPoint: fragmentEntryPoint,\n targets: [...targets],\n constants: fragmentStage.constants,\n };\n }\n\n const primitive: GPUPrimitiveState = config.primitive ?? { topology: 'triangle-list' };\n const multisample: GPUMultisampleState = config.multisample ?? { count: 1 };\n\n return device.createRenderPipeline({\n label: config.label,\n layout,\n vertex: {\n module: vertexStage.module,\n entryPoint: vertexEntryPoint,\n buffers: config.vertex.buffers ? [...config.vertex.buffers] : [],\n constants: vertexStage.constants,\n },\n fragment,\n primitive,\n depthStencil: config.depthStencil,\n multisample,\n });\n}\n\n/**\n * Creates a uniform buffer suitable for `@group/@binding` uniform bindings.\n *\n * Notes:\n * - WebGPU's `queue.writeBuffer()` requires `byteLength` and offsets to be multiples of 4.\n * - Uniform data layout in WGSL is typically aligned to 16 bytes; we default to a 16-byte size alignment.\n * - If you plan to use this buffer with *dynamic offsets*, you must additionally align offsets to\n * `device.limits.minUniformBufferOffsetAlignment` (commonly 256). This helper does not enforce that.\n */\nexport function createUniformBuffer(\n device: GPUDevice,\n size: number,\n options?: { readonly label?: string; readonly alignment?: number }\n): GPUBuffer {\n if (!Number.isFinite(size) || size <= 0) {\n throw new Error(`createUniformBuffer(size): size must be a positive number. Received: ${String(size)}`);\n }\n\n const alignment = options?.alignment ?? 16;\n const alignedSize = alignTo(size, Math.max(4, alignment));\n\n const maxSize = device.limits.maxUniformBufferBindingSize;\n if (alignedSize > maxSize) {\n throw new Error(\n `createUniformBuffer(size): requested size ${alignedSize} exceeds device.limits.maxUniformBufferBindingSize (${maxSize}).`\n );\n }\n\n return device.createBuffer({\n label: options?.label,\n size: alignedSize,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n}\n\n/**\n * Writes CPU data into a uniform buffer (default offset 0).\n *\n * `data` must be a `BufferSource`:\n * - `ArrayBuffer` or `ArrayBufferView` (TypedArray/DataView)\n *\n * Important WebGPU constraint:\n * - `queue.writeBuffer()` requires write size (and offsets) to be multiples of 4 bytes.\n */\nexport function writeUniformBuffer(device: GPUDevice, buffer: GPUBuffer, data: BufferSource): void {\n const src =\n data instanceof ArrayBuffer\n ? { arrayBuffer: data, offset: 0, size: data.byteLength }\n : { arrayBuffer: data.buffer, offset: data.byteOffset, size: data.byteLength };\n\n if (src.size === 0) return;\n\n if ((src.offset & 3) !== 0 || (src.size & 3) !== 0) {\n throw new Error(\n `writeUniformBuffer(data): data byteOffset (${src.offset}) and byteLength (${src.size}) must be multiples of 4 for queue.writeBuffer().`\n );\n }\n\n if (src.size > buffer.size) {\n throw new Error(`writeUniformBuffer(data): data byteLength (${src.size}) exceeds buffer.size (${buffer.size}).`);\n }\n\n device.queue.writeBuffer(buffer, 0, src.arrayBuffer, src.offset, src.size);\n}\n","export type Rgba01 = readonly [r: number, g: number, b: number, a: number];\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst clamp255 = (v: number): number => Math.min(255, Math.max(0, v));\n\nconst parseHexNibble = (hex: string): number => {\n const n = Number.parseInt(hex, 16);\n return Number.isFinite(n) ? n : 0;\n};\n\nconst parseHexByte = (hex: string): number => {\n const n = Number.parseInt(hex, 16);\n return Number.isFinite(n) ? n : 0;\n};\n\nconst parseHexColorToRgba01 = (color: string): Rgba01 | null => {\n const c = color.trim();\n if (!c.startsWith('#')) return null;\n\n const hex = c.slice(1);\n\n // #rgb\n if (hex.length === 3) {\n const r = parseHexNibble(hex[0]);\n const g = parseHexNibble(hex[1]);\n const b = parseHexNibble(hex[2]);\n return [(r * 17) / 255, (g * 17) / 255, (b * 17) / 255, 1];\n }\n\n // #rgba\n if (hex.length === 4) {\n const r = parseHexNibble(hex[0]);\n const g = parseHexNibble(hex[1]);\n const b = parseHexNibble(hex[2]);\n const a = parseHexNibble(hex[3]);\n return [(r * 17) / 255, (g * 17) / 255, (b * 17) / 255, (a * 17) / 255];\n }\n\n // #rrggbb\n if (hex.length === 6) {\n const r = parseHexByte(hex.slice(0, 2));\n const g = parseHexByte(hex.slice(2, 4));\n const b = parseHexByte(hex.slice(4, 6));\n return [r / 255, g / 255, b / 255, 1];\n }\n\n // #rrggbbaa\n if (hex.length === 8) {\n const r = parseHexByte(hex.slice(0, 2));\n const g = parseHexByte(hex.slice(2, 4));\n const b = parseHexByte(hex.slice(4, 6));\n const a = parseHexByte(hex.slice(6, 8));\n return [r / 255, g / 255, b / 255, a / 255];\n }\n\n return null;\n};\n\nconst parseRgbNumberOrPercent = (token: string): number | null => {\n const t = token.trim();\n if (t.length === 0) return null;\n\n if (t.endsWith('%')) {\n const n = Number.parseFloat(t.slice(0, -1));\n if (!Number.isFinite(n)) return null;\n return clamp255((n / 100) * 255);\n }\n\n const n = Number.parseFloat(t);\n if (!Number.isFinite(n)) return null;\n return clamp255(n);\n};\n\nconst parseAlphaNumberOrPercent = (token: string): number | null => {\n const t = token.trim();\n if (t.length === 0) return null;\n\n if (t.endsWith('%')) {\n const n = Number.parseFloat(t.slice(0, -1));\n if (!Number.isFinite(n)) return null;\n return clamp01(n / 100);\n }\n\n const n = Number.parseFloat(t);\n if (!Number.isFinite(n)) return null;\n return clamp01(n);\n};\n\nconst parseRgbFuncToRgba01 = (color: string): Rgba01 | null => {\n const c = color.trim();\n const m = /^(rgba?|RGBA?)\\(\\s*([^\\)]*)\\s*\\)$/.exec(c);\n if (!m) return null;\n\n const fn = m[1].toLowerCase();\n const argsRaw = m[2];\n\n // Requirement scope: support comma-separated rgb()/rgba().\n // (We intentionally do not attempt full CSS Color 4 space-separated syntax here.)\n const parts = argsRaw.split(',').map((p) => p.trim());\n if (fn === 'rgb') {\n if (parts.length !== 3) return null;\n const r = parseRgbNumberOrPercent(parts[0]);\n const g = parseRgbNumberOrPercent(parts[1]);\n const b = parseRgbNumberOrPercent(parts[2]);\n if (r == null || g == null || b == null) return null;\n return [r / 255, g / 255, b / 255, 1];\n }\n\n if (fn === 'rgba') {\n if (parts.length !== 4) return null;\n const r = parseRgbNumberOrPercent(parts[0]);\n const g = parseRgbNumberOrPercent(parts[1]);\n const b = parseRgbNumberOrPercent(parts[2]);\n const a = parseAlphaNumberOrPercent(parts[3]);\n if (r == null || g == null || b == null || a == null) return null;\n return [r / 255, g / 255, b / 255, a];\n }\n\n return null;\n};\n\n/**\n * Parse a CSS color string into RGBA floats in [0..1].\n *\n * Supported:\n * - #rgb / #rgba / #rrggbb / #rrggbbaa\n * - rgb(r,g,b)\n * - rgba(r,g,b,a)\n *\n * Returns null when parsing fails.\n */\nexport const parseCssColorToRgba01 = (color: string): Rgba01 | null => {\n if (typeof color !== 'string') return null;\n const c = color.trim();\n if (c.length === 0) return null;\n\n const hex = parseHexColorToRgba01(c);\n if (hex) return hex;\n\n const rgb = parseRgbFuncToRgba01(c);\n if (rgb) return rgb;\n\n return null;\n};\n\nexport const parseCssColorToGPUColor = (\n color: string,\n fallback: GPUColor = { r: 0, g: 0, b: 0, a: 1 }\n): GPUColor => {\n const rgba = parseCssColorToRgba01(color);\n if (!rgba) return fallback;\n const [r, g, b, a] = rgba;\n return { r, g, b, a };\n};\n\n","import gridWgsl from '../shaders/grid.wgsl?raw';\nimport type { AxisConfig } from '../config/types';\nimport type { LinearScale } from '../utils/scales';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\nimport type { GridArea } from './createGridRenderer';\nimport { parseCssColorToRgba01 } from '../utils/colors';\n\nexport interface AxisRenderer {\n prepare(\n axisConfig: AxisConfig,\n scale: LinearScale,\n orientation: 'x' | 'y',\n gridArea: GridArea,\n axisLineColor?: string,\n axisTickColor?: string\n ): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface AxisRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_TICK_COUNT = 5;\nconst DEFAULT_TICK_LENGTH_CSS_PX = 6;\nconst DEFAULT_AXIS_RGBA: readonly [number, number, number, number] = [1, 1, 1, 0.8];\n\nconst createIdentityMat4Buffer = (): ArrayBuffer => {\n // Column-major identity mat4x4\n const buffer = new ArrayBuffer(16 * 4);\n new Float32Array(buffer).set([\n 1, 0, 0, 0, // col0\n 0, 1, 0, 0, // col1\n 0, 0, 1, 0, // col2\n 0, 0, 0, 1, // col3\n ]);\n return buffer;\n};\n\nconst isFiniteGridArea = (gridArea: GridArea): boolean =>\n Number.isFinite(gridArea.left) &&\n Number.isFinite(gridArea.right) &&\n Number.isFinite(gridArea.top) &&\n Number.isFinite(gridArea.bottom) &&\n Number.isFinite(gridArea.canvasWidth) &&\n Number.isFinite(gridArea.canvasHeight);\n\nconst generateAxisVertices = (\n axisConfig: AxisConfig,\n scale: LinearScale,\n orientation: 'x' | 'y',\n gridArea: GridArea\n): Float32Array => {\n const { left, right, top, bottom, canvasWidth, canvasHeight } = gridArea;\n\n if (!isFiniteGridArea(gridArea)) {\n throw new Error('AxisRenderer.prepare: gridArea dimensions must be finite numbers.');\n }\n if (canvasWidth <= 0 || canvasHeight <= 0) {\n throw new Error('AxisRenderer.prepare: canvas dimensions must be positive.');\n }\n\n const dpr = window.devicePixelRatio || 1;\n const plotLeft = left * dpr;\n const plotRight = canvasWidth - right * dpr;\n const plotTop = top * dpr;\n const plotBottom = canvasHeight - bottom * dpr;\n\n const plotLeftClip = (plotLeft / canvasWidth) * 2.0 - 1.0;\n const plotRightClip = (plotRight / canvasWidth) * 2.0 - 1.0;\n const plotTopClip = 1.0 - (plotTop / canvasHeight) * 2.0; // flip Y\n const plotBottomClip = 1.0 - (plotBottom / canvasHeight) * 2.0; // flip Y\n\n const tickLengthCssPx = axisConfig.tickLength ?? DEFAULT_TICK_LENGTH_CSS_PX;\n if (!Number.isFinite(tickLengthCssPx) || tickLengthCssPx < 0) {\n throw new Error('AxisRenderer.prepare: tickLength must be a finite non-negative number.');\n }\n\n const tickCount: number = DEFAULT_TICK_COUNT;\n const tickLengthDevicePx = tickLengthCssPx * dpr;\n const tickDeltaClipX = (tickLengthDevicePx / canvasWidth) * 2.0;\n const tickDeltaClipY = (tickLengthDevicePx / canvasHeight) * 2.0;\n\n const domainMin =\n axisConfig.min ??\n (orientation === 'x' ? scale.invert(plotLeftClip) : scale.invert(plotBottomClip));\n const domainMax =\n axisConfig.max ??\n (orientation === 'x' ? scale.invert(plotRightClip) : scale.invert(plotTopClip));\n\n // Line-list segments:\n // - 1 baseline segment\n // - tickCount tick segments\n const totalSegments = 1 + tickCount;\n const vertices = new Float32Array(totalSegments * 2 * 2); // segments * 2 vertices * vec2<f32>\n\n let idx = 0;\n\n if (orientation === 'x') {\n // Baseline along bottom edge of plot rect.\n vertices[idx++] = plotLeftClip;\n vertices[idx++] = plotBottomClip;\n vertices[idx++] = plotRightClip;\n vertices[idx++] = plotBottomClip;\n\n // Ticks extend downward (outside plot).\n const y0 = plotBottomClip;\n const y1 = y0 - tickDeltaClipY;\n\n for (let i = 0; i < tickCount; i++) {\n const t = tickCount === 1 ? 0.5 : i / (tickCount - 1);\n const v = domainMin + t * (domainMax - domainMin);\n const x = scale.scale(v);\n\n vertices[idx++] = x;\n vertices[idx++] = y0;\n vertices[idx++] = x;\n vertices[idx++] = y1;\n }\n } else {\n // Baseline along left edge of plot rect.\n vertices[idx++] = plotLeftClip;\n vertices[idx++] = plotBottomClip;\n vertices[idx++] = plotLeftClip;\n vertices[idx++] = plotTopClip;\n\n // Ticks extend left (outside plot).\n const x0 = plotLeftClip;\n const x1 = x0 - tickDeltaClipX;\n\n for (let i = 0; i < tickCount; i++) {\n const t = tickCount === 1 ? 0.5 : i / (tickCount - 1);\n const v = domainMin + t * (domainMax - domainMin);\n const y = scale.scale(v);\n\n vertices[idx++] = x0;\n vertices[idx++] = y;\n vertices[idx++] = x1;\n vertices[idx++] = y;\n }\n }\n\n return vertices;\n};\n\nexport function createAxisRenderer(device: GPUDevice, options?: AxisRendererOptions): AxisRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\n ],\n });\n\n const vsUniformBuffer = createUniformBuffer(device, 64, { label: 'axisRenderer/vsUniforms' });\n const fsUniformBufferLine = createUniformBuffer(device, 16, { label: 'axisRenderer/fsUniformsLine' });\n const fsUniformBufferTick = createUniformBuffer(device, 16, { label: 'axisRenderer/fsUniformsTick' });\n\n const bindGroupLine = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBufferLine } },\n ],\n });\n\n const bindGroupTick = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBufferTick } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'axisRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: gridWgsl,\n label: 'grid.wgsl',\n buffers: [\n {\n arrayStride: 8,\n stepMode: 'vertex',\n attributes: [{ shaderLocation: 0, format: 'float32x2', offset: 0 }],\n },\n ],\n },\n fragment: {\n code: gridWgsl,\n label: 'grid.wgsl',\n formats: targetFormat,\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'line-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let vertexBuffer: GPUBuffer | null = null;\n let vertexCount = 0;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('AxisRenderer is disposed.');\n };\n\n const prepare: AxisRenderer['prepare'] = (axisConfig, scale, orientation, gridArea, axisLineColor, axisTickColor) => {\n assertNotDisposed();\n\n if (orientation !== 'x' && orientation !== 'y') {\n throw new Error(\"AxisRenderer.prepare: orientation must be 'x' or 'y'.\");\n }\n\n const vertices = generateAxisVertices(axisConfig, scale, orientation, gridArea);\n const requiredSize = vertices.byteLength;\n const bufferSize = Math.max(4, requiredSize);\n\n if (!vertexBuffer || vertexBuffer.size < bufferSize) {\n if (vertexBuffer) {\n try {\n vertexBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n vertexBuffer = device.createBuffer({\n label: 'axisRenderer/vertexBuffer',\n size: bufferSize,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n device.queue.writeBuffer(vertexBuffer, 0, vertices.buffer, 0, vertices.byteLength);\n vertexCount = vertices.length / 2;\n\n // Identity transform (vertices already in clip-space).\n writeUniformBuffer(device, vsUniformBuffer, createIdentityMat4Buffer());\n\n // Separate colors for baseline vs ticks.\n // Gracefully fall back to legacy (slightly brighter than grid) when parsing fails.\n const axisLineColorString = axisLineColor ?? 'rgba(255,255,255,0.8)';\n const axisTickColorString = axisTickColor ?? axisLineColorString;\n\n const axisLineRgba = parseCssColorToRgba01(axisLineColorString) ?? DEFAULT_AXIS_RGBA;\n const axisTickRgba = parseCssColorToRgba01(axisTickColorString) ?? axisLineRgba;\n\n const lineColorBuffer = new ArrayBuffer(4 * 4);\n new Float32Array(lineColorBuffer).set([\n axisLineRgba[0],\n axisLineRgba[1],\n axisLineRgba[2],\n axisLineRgba[3],\n ]);\n writeUniformBuffer(device, fsUniformBufferLine, lineColorBuffer);\n\n const tickColorBuffer = new ArrayBuffer(4 * 4);\n new Float32Array(tickColorBuffer).set([\n axisTickRgba[0],\n axisTickRgba[1],\n axisTickRgba[2],\n axisTickRgba[3],\n ]);\n writeUniformBuffer(device, fsUniformBufferTick, tickColorBuffer);\n };\n\n const render: AxisRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (vertexCount === 0 || !vertexBuffer) return;\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setVertexBuffer(0, vertexBuffer);\n\n // Baseline: first 2 vertices.\n passEncoder.setBindGroup(0, bindGroupLine);\n passEncoder.draw(Math.min(2, vertexCount));\n\n // Ticks: remaining vertices.\n if (vertexCount > 2) {\n passEncoder.setBindGroup(0, bindGroupTick);\n passEncoder.draw(vertexCount - 2, 1, 2, 0);\n }\n };\n\n const dispose: AxisRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBufferLine.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBufferTick.destroy();\n } catch {\n // best-effort\n }\n if (vertexBuffer) {\n try {\n vertexBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n\n vertexBuffer = null;\n vertexCount = 0;\n };\n\n return { prepare, render, dispose };\n}\n\n","import gridWgsl from '../shaders/grid.wgsl?raw';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\nimport { parseCssColorToRgba01 } from '../utils/colors';\n\nexport interface GridRenderer {\n /**\n * Backward compatible:\n * - `prepare(gridArea, lineCount)` where `lineCount` is `{ horizontal?, vertical? }`\n *\n * Preferred:\n * - `prepare(gridArea, { lineCount, color })`\n */\n prepare(gridArea: GridArea, lineCountOrOptions?: GridLineCount | GridPrepareOptions): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface GridArea {\n readonly left: number; // Left margin in CSS pixels\n readonly right: number; // Right margin in CSS pixels\n readonly top: number; // Top margin in CSS pixels\n readonly bottom: number; // Bottom margin in CSS pixels\n readonly canvasWidth: number; // Canvas width in device pixels\n readonly canvasHeight: number; // Canvas height in device pixels\n}\n\nexport interface GridLineCount {\n readonly horizontal?: number; // Default: 5\n readonly vertical?: number; // Default: 6\n}\n\nexport interface GridPrepareOptions {\n readonly lineCount?: GridLineCount;\n /**\n * CSS color string used for grid lines.\n *\n * Expected formats: `#rgb`, `#rrggbb`, `#rrggbbaa`, `rgb(r,g,b)`, `rgba(r,g,b,a)`.\n */\n readonly color?: string;\n}\n\nexport interface GridRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_HORIZONTAL_LINES = 5;\nconst DEFAULT_VERTICAL_LINES = 6;\nconst DEFAULT_GRID_COLOR = 'rgba(255,255,255,0.15)';\nconst DEFAULT_GRID_RGBA: readonly [number, number, number, number] = [1, 1, 1, 0.15];\n\nconst createIdentityMat4Buffer = (): ArrayBuffer => {\n // Column-major identity mat4x4\n const buffer = new ArrayBuffer(16 * 4);\n new Float32Array(buffer).set([\n 1, 0, 0, 0, // col0\n 0, 1, 0, 0, // col1\n 0, 0, 1, 0, // col2\n 0, 0, 0, 1, // col3\n ]);\n return buffer;\n};\n\nconst generateGridVertices = (gridArea: GridArea, horizontal: number, vertical: number): Float32Array => {\n const { left, right, top, bottom, canvasWidth, canvasHeight } = gridArea;\n\n // Get device pixel ratio (assumed to be encoded in canvasWidth/canvasHeight)\n // Calculate plot area in device pixels\n const dpr = window.devicePixelRatio || 1;\n const plotLeft = left * dpr;\n const plotRight = canvasWidth - right * dpr;\n const plotTop = top * dpr;\n const plotBottom = canvasHeight - bottom * dpr;\n\n const plotWidth = plotRight - plotLeft;\n const plotHeight = plotBottom - plotTop;\n\n // Total vertices: (horizontal + vertical) * 2 vertices per line\n const totalLines = horizontal + vertical;\n const vertices = new Float32Array(totalLines * 2 * 2); // 2 vertices * 2 floats per vertex\n\n let idx = 0;\n\n // Generate horizontal lines (constant Y, varying X)\n for (let i = 0; i < horizontal; i++) {\n // Calculate t parameter for even spacing\n const t = horizontal === 1 ? 0.5 : i / (horizontal - 1);\n const yDevice = plotTop + t * plotHeight;\n\n // Convert to clip space\n const xClipLeft = (plotLeft / canvasWidth) * 2.0 - 1.0;\n const xClipRight = (plotRight / canvasWidth) * 2.0 - 1.0;\n const yClip = 1.0 - (yDevice / canvasHeight) * 2.0; // Flip Y-axis\n\n // First vertex (left edge)\n vertices[idx++] = xClipLeft;\n vertices[idx++] = yClip;\n\n // Second vertex (right edge)\n vertices[idx++] = xClipRight;\n vertices[idx++] = yClip;\n }\n\n // Generate vertical lines (constant X, varying Y)\n for (let i = 0; i < vertical; i++) {\n // Calculate t parameter for even spacing\n const t = vertical === 1 ? 0.5 : i / (vertical - 1);\n const xDevice = plotLeft + t * plotWidth;\n\n // Convert to clip space\n const xClip = (xDevice / canvasWidth) * 2.0 - 1.0;\n const yClipTop = 1.0 - (plotTop / canvasHeight) * 2.0; // Flip Y-axis\n const yClipBottom = 1.0 - (plotBottom / canvasHeight) * 2.0; // Flip Y-axis\n\n // First vertex (top edge)\n vertices[idx++] = xClip;\n vertices[idx++] = yClipTop;\n\n // Second vertex (bottom edge)\n vertices[idx++] = xClip;\n vertices[idx++] = yClipBottom;\n }\n\n return vertices;\n};\n\nexport function createGridRenderer(device: GPUDevice, options?: GridRendererOptions): GridRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\n ],\n });\n\n const vsUniformBuffer = createUniformBuffer(device, 64, { label: 'gridRenderer/vsUniforms' });\n const fsUniformBuffer = createUniformBuffer(device, 16, { label: 'gridRenderer/fsUniforms' });\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBuffer } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'gridRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: gridWgsl,\n label: 'grid.wgsl',\n buffers: [\n {\n arrayStride: 8, // vec2<f32> = 2 * 4 bytes\n stepMode: 'vertex',\n attributes: [{ shaderLocation: 0, format: 'float32x2', offset: 0 }],\n },\n ],\n },\n fragment: {\n code: gridWgsl,\n label: 'grid.wgsl',\n formats: targetFormat,\n // Enable standard alpha blending so `fsUniforms.color.a` behaves as expected\n // (blends into the cleared background instead of making the canvas pixels transparent).\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'line-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let vertexBuffer: GPUBuffer | null = null;\n let vertexCount = 0;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('GridRenderer is disposed.');\n };\n\n const prepare: GridRenderer['prepare'] = (gridArea, lineCountOrOptions) => {\n assertNotDisposed();\n\n const isOptionsObject =\n lineCountOrOptions != null &&\n typeof lineCountOrOptions === 'object' &&\n ('lineCount' in lineCountOrOptions || 'color' in lineCountOrOptions);\n\n const options: GridPrepareOptions | undefined = isOptionsObject\n ? (lineCountOrOptions as GridPrepareOptions)\n : undefined;\n\n const lineCount: GridLineCount | undefined = isOptionsObject\n ? options?.lineCount\n : (lineCountOrOptions as GridLineCount | undefined);\n\n const horizontal = lineCount?.horizontal ?? DEFAULT_HORIZONTAL_LINES;\n const vertical = lineCount?.vertical ?? DEFAULT_VERTICAL_LINES;\n const colorString = options?.color ?? DEFAULT_GRID_COLOR;\n\n // Validate inputs\n if (horizontal < 0 || vertical < 0) {\n throw new Error('GridRenderer.prepare: line counts must be non-negative.');\n }\n if (\n !Number.isFinite(gridArea.left) ||\n !Number.isFinite(gridArea.right) ||\n !Number.isFinite(gridArea.top) ||\n !Number.isFinite(gridArea.bottom) ||\n !Number.isFinite(gridArea.canvasWidth) ||\n !Number.isFinite(gridArea.canvasHeight)\n ) {\n throw new Error('GridRenderer.prepare: gridArea dimensions must be finite numbers.');\n }\n if (gridArea.canvasWidth <= 0 || gridArea.canvasHeight <= 0) {\n throw new Error('GridRenderer.prepare: canvas dimensions must be positive.');\n }\n\n // Early return if no lines to draw\n if (horizontal === 0 && vertical === 0) {\n vertexCount = 0;\n return;\n }\n\n // Generate vertices\n const vertices = generateGridVertices(gridArea, horizontal, vertical);\n const requiredSize = vertices.byteLength;\n\n // Ensure minimum buffer size of 4 bytes\n const bufferSize = Math.max(4, requiredSize);\n\n // Create or recreate vertex buffer if needed\n if (!vertexBuffer || vertexBuffer.size < bufferSize) {\n if (vertexBuffer) {\n try {\n vertexBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n\n vertexBuffer = device.createBuffer({\n label: 'gridRenderer/vertexBuffer',\n size: bufferSize,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n // Write vertex data\n device.queue.writeBuffer(vertexBuffer, 0, vertices.buffer, 0, vertices.byteLength);\n vertexCount = (horizontal + vertical) * 2;\n\n // Write uniforms\n // VS uniform: identity transform (vertices already in clip space)\n const transformBuffer = createIdentityMat4Buffer();\n writeUniformBuffer(device, vsUniformBuffer, transformBuffer);\n\n // FS uniform: theme-driven (grid lines)\n const rgba = parseCssColorToRgba01(colorString) ?? DEFAULT_GRID_RGBA;\n const colorBuffer = new ArrayBuffer(4 * 4);\n new Float32Array(colorBuffer).set([rgba[0], rgba[1], rgba[2], rgba[3]]);\n writeUniformBuffer(device, fsUniformBuffer, colorBuffer);\n };\n\n const render: GridRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (vertexCount === 0 || !vertexBuffer) return;\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, vertexBuffer);\n passEncoder.draw(vertexCount);\n };\n\n const dispose: GridRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n if (vertexBuffer) {\n try {\n vertexBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n\n vertexBuffer = null;\n vertexCount = 0;\n };\n\n return { prepare, render, dispose };\n}\n","export default \"// area.wgsl\\n// Minimal area-fill shader (triangle-strip):\\n// - Vertex input: vec2<f32> position in data coords\\n// - Uniforms: clip-space transform + baseline value + solid RGBA color\\n// - Topology: triangle-strip\\n// - CPU duplicates vertices as p0,p0,p1,p1,... and we use vertex_index parity:\\n// even index -> \\\"top\\\" vertex (original y)\\n// odd index -> \\\"baseline\\\" vertex (uniform baseline)\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n baseline: f32,\\n // Pad to 16-byte multiple (uniform buffer layout requirements).\\n _pad0: vec3<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct FSUniforms {\\n color: vec4<f32>,\\n};\\n\\n@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;\\n\\nstruct VSIn {\\n @location(0) position: vec2<f32>,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {\\n var out: VSOut;\\n let useBaseline = (vertexIndex & 1u) == 1u;\\n let y = select(in.position.y, vsUniforms.baseline, useBaseline);\\n let pos = vec2<f32>(in.position.x, y);\\n out.clipPosition = vsUniforms.transform * vec4<f32>(pos, 0.0, 1.0);\\n return out;\\n}\\n\\n@fragment\\nfn fsMain() -> @location(0) vec4<f32> {\\n return fsUniforms.color;\\n}\\n\\n\"","import areaWgsl from '../shaders/area.wgsl?raw';\nimport type { ResolvedAreaSeriesConfig } from '../config/OptionResolver';\nimport type { DataPointTuple } from '../config/types';\nimport type { LinearScale } from '../utils/scales';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\n\nexport interface AreaRenderer {\n prepare(\n seriesConfig: ResolvedAreaSeriesConfig,\n data: ResolvedAreaSeriesConfig['data'],\n xScale: LinearScale,\n yScale: LinearScale,\n baseline?: number\n ): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface AreaRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\ntype Rgba = readonly [r: number, g: number, b: number, a: number];\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst parseSeriesColorToRgba01 = (color: string): Rgba =>\n parseCssColorToRgba01(color) ?? ([0, 0, 0, 1] as const);\n\nconst isTupleDataPoint = (point: ResolvedAreaSeriesConfig['data'][number]): point is DataPointTuple => Array.isArray(point);\n\nconst getPointXY = (\n point: ResolvedAreaSeriesConfig['data'][number]\n): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(point)) return { x: point[0], y: point[1] };\n return { x: point.x, y: point.y };\n};\n\nconst computeDataBounds = (\n data: ResolvedAreaSeriesConfig['data']\n): { readonly xMin: number; readonly xMax: number; readonly yMin: number; readonly yMax: number } => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return { xMin: 0, xMax: 1, yMin: 0, yMax: 1 };\n }\n\n // Avoid degenerate domains for affine derivation (handled later too, but keep stable samples).\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst computeClipAffineFromScale = (\n scale: LinearScale,\n v0: number,\n v1: number\n): { readonly a: number; readonly b: number } => {\n const p0 = scale.scale(v0);\n const p1 = scale.scale(v1);\n\n // If the domain sample is degenerate or non-finite, fall back to constant output.\n if (!Number.isFinite(v0) || !Number.isFinite(v1) || v0 === v1 || !Number.isFinite(p0) || !Number.isFinite(p1)) {\n return { a: 0, b: Number.isFinite(p0) ? p0 : 0 };\n }\n\n const a = (p1 - p0) / (v1 - v0);\n const b = p0 - a * v0;\n return { a: Number.isFinite(a) ? a : 0, b: Number.isFinite(b) ? b : 0 };\n};\n\nconst writeTransformMat4F32 = (out: Float32Array, ax: number, bx: number, ay: number, by: number): void => {\n // Column-major mat4x4 for: clip = M * vec4(x, y, 0, 1)\n out[0] = ax;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0; // col0\n out[4] = 0;\n out[5] = ay;\n out[6] = 0;\n out[7] = 0; // col1\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0; // col2\n out[12] = bx;\n out[13] = by;\n out[14] = 0;\n out[15] = 1; // col3\n};\n\nconst createAreaVertices = (data: ResolvedAreaSeriesConfig['data']): Float32Array => {\n // Triangle-strip expects duplicated vertices:\n // p0,p0,p1,p1,... and WGSL uses vertex_index parity to swap y to baseline for odd indices.\n const n = data.length;\n const out = new Float32Array(n * 2 * 2); // n * 2 vertices * vec2<f32>\n\n let idx = 0;\n for (let i = 0; i < n; i++) {\n const { x, y } = getPointXY(data[i]);\n out[idx++] = x;\n out[idx++] = y;\n out[idx++] = x;\n out[idx++] = y;\n }\n\n return out;\n};\n\nexport function createAreaRenderer(device: GPUDevice, options?: AreaRendererOptions): AreaRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\n ],\n });\n\n const vsUniformBuffer = createUniformBuffer(device, 96, { label: 'areaRenderer/vsUniforms' });\n const fsUniformBuffer = createUniformBuffer(device, 16, { label: 'areaRenderer/fsUniforms' });\n\n // Reused CPU-side staging for uniform writes (avoid per-frame allocations).\n const vsUniformScratchBuffer = new ArrayBuffer(96);\n const vsUniformScratchF32 = new Float32Array(vsUniformScratchBuffer);\n const fsUniformScratchF32 = new Float32Array(4);\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBuffer } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'areaRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: areaWgsl,\n label: 'area.wgsl',\n buffers: [\n {\n arrayStride: 8,\n stepMode: 'vertex',\n attributes: [{ shaderLocation: 0, format: 'float32x2', offset: 0 }],\n },\n ],\n },\n fragment: {\n code: areaWgsl,\n label: 'area.wgsl',\n formats: targetFormat,\n // Enable standard alpha blending so `areaStyle.opacity` behaves correctly.\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'triangle-strip', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let vertexBuffer: GPUBuffer | null = null;\n let vertexCount = 0;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('AreaRenderer is disposed.');\n };\n\n const writeVsUniforms = (ax: number, bx: number, ay: number, by: number, baseline: number): void => {\n // VSUniforms:\n // - mat4x4<f32> (64 bytes)\n // - baseline: f32 (4 bytes)\n // - (implicit padding to next 16B boundary) (12 bytes)\n // - _pad0: vec3<f32> (occupies 16 bytes in a uniform buffer)\n // Total: 96 bytes.\n //\n // Layout details (uniform address space):\n // - transform at byte offset 0\n // - baseline at byte offset 64 (f32[16])\n // - _pad0 at byte offset 80 (f32[20..22]) with trailing 4B padding\n writeTransformMat4F32(vsUniformScratchF32, ax, bx, ay, by);\n vsUniformScratchF32[16] = baseline;\n vsUniformScratchF32[17] = 0;\n vsUniformScratchF32[18] = 0;\n vsUniformScratchF32[19] = 0;\n vsUniformScratchF32[20] = 0;\n vsUniformScratchF32[21] = 0;\n vsUniformScratchF32[22] = 0;\n vsUniformScratchF32[23] = 0;\n writeUniformBuffer(device, vsUniformBuffer, vsUniformScratchBuffer);\n };\n\n const prepare: AreaRenderer['prepare'] = (seriesConfig, data, xScale, yScale, baseline) => {\n assertNotDisposed();\n\n const vertices = createAreaVertices(data);\n const requiredSize = vertices.byteLength;\n const bufferSize = Math.max(4, requiredSize);\n\n if (!vertexBuffer || vertexBuffer.size < bufferSize) {\n if (vertexBuffer) {\n try {\n vertexBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n vertexBuffer = device.createBuffer({\n label: 'areaRenderer/vertexBuffer',\n size: bufferSize,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n if (vertices.byteLength > 0) {\n device.queue.writeBuffer(vertexBuffer, 0, vertices.buffer, 0, vertices.byteLength);\n }\n vertexCount = vertices.length / 2;\n\n const { xMin, xMax, yMin, yMax } = computeDataBounds(data);\n const { a: ax, b: bx } = computeClipAffineFromScale(xScale, xMin, xMax);\n const { a: ay, b: by } = computeClipAffineFromScale(yScale, yMin, yMax);\n\n const baselineValue =\n Number.isFinite(baseline ?? Number.NaN) ? (baseline as number) : Number.isFinite(yMin) ? yMin : 0;\n\n writeVsUniforms(ax, bx, ay, by, baselineValue);\n\n // Use the resolved fill color from areaStyle.color (not seriesConfig.color).\n const [r, g, b, a] = parseSeriesColorToRgba01(seriesConfig.areaStyle.color);\n const opacity = clamp01(seriesConfig.areaStyle.opacity);\n fsUniformScratchF32[0] = r;\n fsUniformScratchF32[1] = g;\n fsUniformScratchF32[2] = b;\n fsUniformScratchF32[3] = clamp01(a * opacity);\n writeUniformBuffer(device, fsUniformBuffer, fsUniformScratchF32);\n };\n\n const render: AreaRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!vertexBuffer || vertexCount < 4) return;\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, vertexBuffer);\n passEncoder.draw(vertexCount);\n };\n\n const dispose: AreaRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n if (vertexBuffer) {\n try {\n vertexBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n vertexBuffer = null;\n vertexCount = 0;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n };\n\n return { prepare, render, dispose };\n}\n\n","export default \"// line.wgsl\\n// Minimal line-strip shader:\\n// - Vertex input: vec2<f32> position in data coords\\n// - Uniforms: clip-space transform + solid RGBA color\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct FSUniforms {\\n color: vec4<f32>,\\n};\\n\\n@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;\\n\\nstruct VSIn {\\n @location(0) position: vec2<f32>,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn) -> VSOut {\\n var out: VSOut;\\n out.clipPosition = vsUniforms.transform * vec4<f32>(in.position, 0.0, 1.0);\\n return out;\\n}\\n\\n@fragment\\nfn fsMain() -> @location(0) vec4<f32> {\\n return fsUniforms.color;\\n}\\n\\n\"","import lineWgsl from '../shaders/line.wgsl?raw';\nimport type { ResolvedLineSeriesConfig } from '../config/OptionResolver';\nimport type { DataPointTuple } from '../config/types';\nimport type { LinearScale } from '../utils/scales';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\n\nexport interface LineRenderer {\n prepare(seriesConfig: ResolvedLineSeriesConfig, dataBuffer: GPUBuffer, xScale: LinearScale, yScale: LinearScale): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface LineRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\ntype Rgba = readonly [r: number, g: number, b: number, a: number];\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst parseSeriesColorToRgba01 = (color: string): Rgba =>\n parseCssColorToRgba01(color) ?? ([0, 0, 0, 1] as const);\n\nconst isTupleDataPoint = (\n point: ResolvedLineSeriesConfig['data'][number]\n): point is DataPointTuple => Array.isArray(point);\n\nconst getPointXY = (point: ResolvedLineSeriesConfig['data'][number]): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(point)) return { x: point[0], y: point[1] };\n return { x: point.x, y: point.y };\n};\n\nconst computeDataBounds = (\n data: ResolvedLineSeriesConfig['data']\n): { readonly xMin: number; readonly xMax: number; readonly yMin: number; readonly yMax: number } => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return { xMin: 0, xMax: 1, yMin: 0, yMax: 1 };\n }\n\n // Avoid degenerate domains for affine derivation (handled later too, but keep stable samples).\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst computeClipAffineFromScale = (\n scale: LinearScale,\n v0: number,\n v1: number\n): { readonly a: number; readonly b: number } => {\n const p0 = scale.scale(v0);\n const p1 = scale.scale(v1);\n\n // If the domain sample is degenerate or non-finite, fall back to constant output.\n if (!Number.isFinite(v0) || !Number.isFinite(v1) || v0 === v1 || !Number.isFinite(p0) || !Number.isFinite(p1)) {\n return { a: 0, b: Number.isFinite(p0) ? p0 : 0 };\n }\n\n const a = (p1 - p0) / (v1 - v0);\n const b = p0 - a * v0;\n return { a: Number.isFinite(a) ? a : 0, b: Number.isFinite(b) ? b : 0 };\n};\n\nconst writeTransformMat4F32 = (out: Float32Array, ax: number, bx: number, ay: number, by: number): void => {\n // Column-major mat4x4 for: clip = M * vec4(x, y, 0, 1)\n out[0] = ax;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0; // col0\n out[4] = 0;\n out[5] = ay;\n out[6] = 0;\n out[7] = 0; // col1\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0; // col2\n out[12] = bx;\n out[13] = by;\n out[14] = 0;\n out[15] = 1; // col3\n};\n\nexport function createLineRenderer(device: GPUDevice, options?: LineRendererOptions): LineRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\n ],\n });\n\n const vsUniformBuffer = createUniformBuffer(device, 64, { label: 'lineRenderer/vsUniforms' });\n const fsUniformBuffer = createUniformBuffer(device, 16, { label: 'lineRenderer/fsUniforms' });\n\n // Reused CPU-side staging for uniform writes (avoid per-frame allocations).\n const vsUniformScratchBuffer = new ArrayBuffer(64);\n const vsUniformScratchF32 = new Float32Array(vsUniformScratchBuffer);\n const fsUniformScratchF32 = new Float32Array(4);\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBuffer } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'lineRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: lineWgsl,\n label: 'line.wgsl',\n buffers: [\n {\n arrayStride: 8,\n stepMode: 'vertex',\n attributes: [{ shaderLocation: 0, format: 'float32x2', offset: 0 }],\n },\n ],\n },\n fragment: {\n code: lineWgsl,\n label: 'line.wgsl',\n formats: targetFormat,\n // Enable standard alpha blending so per-series `lineStyle.opacity` behaves\n // correctly against an opaque cleared background.\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'line-strip', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let currentVertexBuffer: GPUBuffer | null = null;\n let currentVertexCount = 0;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('LineRenderer is disposed.');\n };\n\n const prepare: LineRenderer['prepare'] = (seriesConfig, dataBuffer, xScale, yScale) => {\n assertNotDisposed();\n\n currentVertexBuffer = dataBuffer;\n currentVertexCount = seriesConfig.data.length;\n\n const { xMin, xMax, yMin, yMax } = computeDataBounds(seriesConfig.data);\n const { a: ax, b: bx } = computeClipAffineFromScale(xScale, xMin, xMax);\n const { a: ay, b: by } = computeClipAffineFromScale(yScale, yMin, yMax);\n\n writeTransformMat4F32(vsUniformScratchF32, ax, bx, ay, by);\n writeUniformBuffer(device, vsUniformBuffer, vsUniformScratchBuffer);\n\n const [r, g, b, a] = parseSeriesColorToRgba01(seriesConfig.color);\n const opacity = clamp01(seriesConfig.lineStyle.opacity);\n fsUniformScratchF32[0] = r;\n fsUniformScratchF32[1] = g;\n fsUniformScratchF32[2] = b;\n fsUniformScratchF32[3] = clamp01(a * opacity);\n writeUniformBuffer(device, fsUniformBuffer, fsUniformScratchF32);\n };\n\n const render: LineRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!currentVertexBuffer || currentVertexCount < 2) return;\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, currentVertexBuffer);\n passEncoder.draw(currentVertexCount);\n };\n\n const dispose: LineRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n currentVertexBuffer = null;\n currentVertexCount = 0;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n };\n\n return { prepare, render, dispose };\n}\n","export default \"// bar.wgsl\\n// Instanced bar/rect shader:\\n// - Per-instance vertex input:\\n// - rect = vec4<f32>(x, y, width, height) in CLIP space\\n// - color = vec4<f32>(r, g, b, a) in [0..1]\\n// - Draw call: draw(6, instanceCount) using triangle-list expansion in VS\\n// - Uniforms:\\n// - @group(0) @binding(0): VSUniforms { transform }\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct VSIn {\\n // rect.xy = origin, rect.zw = size (width, height)\\n @location(0) rect: vec4<f32>,\\n @location(1) color: vec4<f32>,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n @location(0) color: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {\\n // Fixed local corners for 2 triangles (triangle-list).\\n let corners = array<vec2<f32>, 6>(\\n vec2<f32>(0.0, 0.0),\\n vec2<f32>(1.0, 0.0),\\n vec2<f32>(0.0, 1.0),\\n vec2<f32>(0.0, 1.0),\\n vec2<f32>(1.0, 0.0),\\n vec2<f32>(1.0, 1.0)\\n );\\n\\n // Normalize negative width/height by computing min/max extents.\\n let p0 = in.rect.xy;\\n let p1 = in.rect.xy + in.rect.zw;\\n let rectMin = min(p0, p1);\\n let rectMax = max(p0, p1);\\n let rectSize = rectMax - rectMin;\\n\\n let corner = corners[vertexIndex];\\n let pos = rectMin + corner * rectSize;\\n\\n var out: VSOut;\\n out.clipPosition = vsUniforms.transform * vec4<f32>(pos, 0.0, 1.0);\\n out.color = in.color;\\n return out;\\n}\\n\\n@fragment\\nfn fsMain(in: VSOut) -> @location(0) vec4<f32> {\\n return in.color;\\n}\\n\\n\"","import barWgsl from '../shaders/bar.wgsl?raw';\nimport type { ResolvedBarSeriesConfig } from '../config/OptionResolver';\nimport type { DataPoint, DataPointTuple } from '../config/types';\nimport type { LinearScale } from '../utils/scales';\nimport type { GridArea } from './createGridRenderer';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport type { DataStore } from '../data/createDataStore';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\n\nexport interface BarRenderer {\n prepare(\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n dataStore: DataStore,\n xScale: LinearScale,\n yScale: LinearScale,\n gridArea: GridArea\n ): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface BarRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\ntype Rgba = readonly [r: number, g: number, b: number, a: number];\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_BAR_GAP = 0.1;\nconst DEFAULT_BAR_CATEGORY_GAP = 0.2;\nconst INSTANCE_STRIDE_BYTES = 32; // rect vec4 + color vec4\nconst INSTANCE_STRIDE_FLOATS = INSTANCE_STRIDE_BYTES / 4;\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst parseSeriesColorToRgba01 = (color: string): Rgba =>\n parseCssColorToRgba01(color) ?? ([0, 0, 0, 1] as const);\n\nconst nextPow2 = (v: number): number => {\n if (!Number.isFinite(v) || v <= 0) return 1;\n const n = Math.ceil(v);\n return 2 ** Math.ceil(Math.log2(n));\n};\n\nconst createIdentityMat4Buffer = (): ArrayBuffer => {\n // Column-major identity mat4x4\n const buffer = new ArrayBuffer(16 * 4);\n new Float32Array(buffer).set([\n 1, 0, 0, 0, // col0\n 0, 1, 0, 0, // col1\n 0, 0, 1, 0, // col2\n 0, 0, 0, 1, // col3\n ]);\n return buffer;\n};\n\nconst parsePercent = (value: string): number | null => {\n const m = value.trim().match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (!m) return null;\n const p = Number(m[1]) / 100;\n return Number.isFinite(p) ? p : null;\n};\n\nconst normalizeStackId = (stack: unknown): string => {\n if (typeof stack !== 'string') return '';\n const trimmed = stack.trim();\n return trimmed.length > 0 ? trimmed : '';\n};\n\nconst isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p);\n\nconst getPointXY = (p: DataPoint): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(p)) return { x: p[0], y: p[1] };\n return { x: p.x, y: p.y };\n};\n\nconst computePlotSizeCssPx = (gridArea: GridArea): { readonly plotWidthCss: number; readonly plotHeightCss: number } | null => {\n const dpr = window.devicePixelRatio || 1;\n if (!(dpr > 0)) return null;\n const canvasCssWidth = gridArea.canvasWidth / dpr;\n const canvasCssHeight = gridArea.canvasHeight / dpr;\n const plotWidthCss = canvasCssWidth - gridArea.left - gridArea.right;\n const plotHeightCss = canvasCssHeight - gridArea.top - gridArea.bottom;\n if (!(plotWidthCss > 0) || !(plotHeightCss > 0)) return null;\n return { plotWidthCss, plotHeightCss };\n};\n\nconst computePlotClipRect = (\n gridArea: GridArea\n): { readonly left: number; readonly right: number; readonly top: number; readonly bottom: number } => {\n const { left, right, top, bottom, canvasWidth, canvasHeight } = gridArea;\n const dpr = window.devicePixelRatio || 1;\n\n const plotLeft = left * dpr;\n const plotRight = canvasWidth - right * dpr;\n const plotTop = top * dpr;\n const plotBottom = canvasHeight - bottom * dpr;\n\n const plotLeftClip = (plotLeft / canvasWidth) * 2.0 - 1.0;\n const plotRightClip = (plotRight / canvasWidth) * 2.0 - 1.0;\n const plotTopClip = 1.0 - (plotTop / canvasHeight) * 2.0; // flip Y\n const plotBottomClip = 1.0 - (plotBottom / canvasHeight) * 2.0; // flip Y\n\n return { left: plotLeftClip, right: plotRightClip, top: plotTopClip, bottom: plotBottomClip };\n};\n\nconst computeCategoryWidthClip = (\n xScale: LinearScale,\n categoryStep: number,\n plotClipRect: Readonly<{ left: number; right: number }>,\n fallbackCategoryCount: number\n): number => {\n if (Number.isFinite(categoryStep) && categoryStep > 0) {\n const x0 = 0;\n const p0 = xScale.scale(x0);\n const p1 = xScale.scale(x0 + categoryStep);\n const w = Math.abs(p1 - p0);\n if (Number.isFinite(w) && w > 0) return w;\n }\n\n const clipWidth = Math.abs(plotClipRect.right - plotClipRect.left);\n if (!(clipWidth > 0)) return 0;\n const n = Math.max(1, Math.floor(fallbackCategoryCount));\n return clipWidth / n;\n};\n\nexport function createBarRenderer(device: GPUDevice, options?: BarRendererOptions): BarRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n ],\n });\n\n const vsUniformBuffer = createUniformBuffer(device, 64, { label: 'barRenderer/vsUniforms' });\n // Default to identity: we upload rects in clip-space.\n writeUniformBuffer(device, vsUniformBuffer, createIdentityMat4Buffer());\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'barRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: barWgsl,\n label: 'bar.wgsl',\n buffers: [\n {\n arrayStride: INSTANCE_STRIDE_BYTES, // rect vec4 + color vec4\n stepMode: 'instance',\n attributes: [\n { shaderLocation: 0, format: 'float32x4', offset: 0 },\n { shaderLocation: 1, format: 'float32x4', offset: 16 },\n ],\n },\n ],\n },\n fragment: {\n code: barWgsl,\n label: 'bar.wgsl',\n formats: targetFormat,\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'triangle-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let instanceBuffer: GPUBuffer | null = null;\n let instanceCount = 0;\n let cpuInstanceStagingBuffer = new ArrayBuffer(0);\n let cpuInstanceStagingF32 = new Float32Array(cpuInstanceStagingBuffer);\n const categoryXScratch: number[] = [];\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('BarRenderer is disposed.');\n };\n\n const ensureCpuInstanceCapacityFloats = (requiredFloats: number): void => {\n if (requiredFloats <= cpuInstanceStagingF32.length) return;\n // Grow geometrically (power-of-two) to reduce churn.\n const nextFloats = Math.max(8, nextPow2(requiredFloats));\n cpuInstanceStagingBuffer = new ArrayBuffer(nextFloats * 4);\n cpuInstanceStagingF32 = new Float32Array(cpuInstanceStagingBuffer);\n };\n\n const computeBarCategoryStep = (seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>): number => {\n categoryXScratch.length = 0;\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s].data;\n for (let i = 0; i < data.length; i++) {\n const { x } = getPointXY(data[i]);\n if (Number.isFinite(x)) categoryXScratch.push(x);\n }\n }\n\n if (categoryXScratch.length < 2) return 1;\n categoryXScratch.sort((a, b) => a - b);\n\n let minStep = Number.POSITIVE_INFINITY;\n for (let i = 1; i < categoryXScratch.length; i++) {\n const d = categoryXScratch[i] - categoryXScratch[i - 1];\n if (d > 0 && d < minStep) minStep = d;\n }\n return Number.isFinite(minStep) && minStep > 0 ? minStep : 1;\n };\n\n const computeSharedBarLayout = (\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>\n ): { readonly barWidth?: number | string; readonly barGap?: number; readonly barCategoryGap?: number } => {\n let barWidth: number | string | undefined = undefined;\n let barGap: number | undefined = undefined;\n let barCategoryGap: number | undefined = undefined;\n\n for (let i = 0; i < seriesConfigs.length; i++) {\n const s = seriesConfigs[i];\n if (barWidth === undefined && s.barWidth !== undefined) barWidth = s.barWidth;\n if (barGap === undefined && s.barGap !== undefined) barGap = s.barGap;\n if (barCategoryGap === undefined && s.barCategoryGap !== undefined) barCategoryGap = s.barCategoryGap;\n }\n\n return { barWidth, barGap, barCategoryGap };\n };\n\n const computeBaselineForBarsFromData = (seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>): number => {\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s].data;\n for (let i = 0; i < data.length; i++) {\n const { y } = getPointXY(data[i]);\n if (!Number.isFinite(y)) continue;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n }\n\n if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) return 0;\n if (yMin <= 0 && 0 <= yMax) return 0;\n return Math.abs(yMin) < Math.abs(yMax) ? yMin : yMax;\n };\n\n const computeBaselineForBarsFromAxis = (\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n yScale: LinearScale,\n plotClipRect: Readonly<{ top: number; bottom: number }>\n ): number => {\n // Determine the visible y-domain from the yScale + plot clip rect (clip-space).\n const yDomainA = yScale.invert(plotClipRect.bottom);\n const yDomainB = yScale.invert(plotClipRect.top);\n const yMin = Math.min(yDomainA, yDomainB);\n const yMax = Math.max(yDomainA, yDomainB);\n\n // If scale/range is degenerate, fall back.\n if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return computeBaselineForBarsFromData(seriesConfigs);\n }\n\n if (yMin <= 0 && 0 <= yMax) return 0;\n if (yMin > 0) return yMin;\n if (yMax < 0) return yMax;\n\n // Should be unreachable with finite min/max, but keep a safe fallback.\n return computeBaselineForBarsFromData(seriesConfigs);\n };\n\n const prepare: BarRenderer['prepare'] = (seriesConfigs, dataStore, xScale, yScale, gridArea) => {\n assertNotDisposed();\n void dataStore;\n\n if (seriesConfigs.length === 0) {\n instanceCount = 0;\n return;\n }\n\n const plotSize = computePlotSizeCssPx(gridArea);\n if (!plotSize) {\n instanceCount = 0;\n return;\n }\n\n const plotClipRect = computePlotClipRect(gridArea);\n const plotClipWidth = plotClipRect.right - plotClipRect.left;\n const plotClipHeight = plotClipRect.top - plotClipRect.bottom;\n const clipPerCssX = plotSize.plotWidthCss > 0 ? plotClipWidth / plotSize.plotWidthCss : 0;\n void plotClipHeight; // reserved for future y-size conversions (e.g. border radius)\n\n // Cluster slots:\n // - Each unique non-empty stackId gets a single cluster slot.\n // - Each unstacked series gets its own cluster slot.\n const stackIdToClusterIndex = new Map<string, number>();\n const clusterIndexBySeries: number[] = new Array(seriesConfigs.length);\n let clusterCount = 0;\n for (let i = 0; i < seriesConfigs.length; i++) {\n const stackId = normalizeStackId(seriesConfigs[i].stack);\n if (stackId !== '') {\n const existing = stackIdToClusterIndex.get(stackId);\n if (existing !== undefined) {\n clusterIndexBySeries[i] = existing;\n } else {\n const idx = clusterCount++;\n stackIdToClusterIndex.set(stackId, idx);\n clusterIndexBySeries[i] = idx;\n }\n } else {\n clusterIndexBySeries[i] = clusterCount++;\n }\n }\n clusterCount = Math.max(1, clusterCount);\n\n const categoryStep = computeBarCategoryStep(seriesConfigs);\n const layout = computeSharedBarLayout(seriesConfigs);\n const barGap = clamp01(layout.barGap ?? DEFAULT_BAR_GAP);\n const barCategoryGap = clamp01(layout.barCategoryGap ?? DEFAULT_BAR_CATEGORY_GAP);\n\n let fallbackCategoryCount = 1;\n for (let s = 0; s < seriesConfigs.length; s++) {\n fallbackCategoryCount = Math.max(fallbackCategoryCount, Math.floor(seriesConfigs[s].data.length));\n }\n\n const categoryWidthClip = computeCategoryWidthClip(xScale, categoryStep, plotClipRect, fallbackCategoryCount);\n const categoryInnerWidthClip = Math.max(0, categoryWidthClip * (1 - barCategoryGap));\n\n let barWidthClip = 0;\n const rawBarWidth = layout.barWidth;\n if (typeof rawBarWidth === 'number') {\n barWidthClip = Math.max(0, rawBarWidth) * clipPerCssX;\n } else if (typeof rawBarWidth === 'string') {\n const p = parsePercent(rawBarWidth);\n barWidthClip = p == null ? 0 : categoryInnerWidthClip * clamp01(p);\n }\n\n if (!(barWidthClip > 0)) {\n const denom = clusterCount + Math.max(0, clusterCount - 1) * barGap;\n barWidthClip = denom > 0 ? categoryInnerWidthClip / denom : 0;\n }\n barWidthClip = Math.min(barWidthClip, categoryInnerWidthClip);\n\n const gapClip = barWidthClip * barGap;\n const clusterWidthClip = clusterCount * barWidthClip + Math.max(0, clusterCount - 1) * gapClip;\n\n let baselineDomain = computeBaselineForBarsFromAxis(seriesConfigs, yScale, plotClipRect);\n let baselineClip = yScale.scale(baselineDomain);\n if (!Number.isFinite(baselineClip)) {\n // Fallback for pathological scales: revert to data-derived baseline, then 0.\n const fallbackBaselineDomain = computeBaselineForBarsFromData(seriesConfigs);\n baselineDomain = fallbackBaselineDomain;\n baselineClip = yScale.scale(fallbackBaselineDomain);\n if (!Number.isFinite(baselineClip)) {\n baselineDomain = 0;\n baselineClip = yScale.scale(0);\n }\n if (!Number.isFinite(baselineClip)) {\n instanceCount = 0;\n return;\n }\n }\n\n let maxBars = 0;\n for (let s = 0; s < seriesConfigs.length; s++) maxBars += Math.max(0, seriesConfigs[s].data.length);\n\n ensureCpuInstanceCapacityFloats(maxBars * INSTANCE_STRIDE_FLOATS);\n const f32 = cpuInstanceStagingF32;\n let outFloats = 0;\n\n // Per-stack, per-x running sums in domain units (supports negative stacking too).\n const stackSumsByStackId = new Map<string, Map<number, { posSum: number; negSum: number }>>();\n\n for (let seriesIndex = 0; seriesIndex < seriesConfigs.length; seriesIndex++) {\n const series = seriesConfigs[seriesIndex];\n const data = series.data;\n const [r, g, b, a] = parseSeriesColorToRgba01(series.color);\n const stackId = normalizeStackId(series.stack);\n const clusterIndex = clusterIndexBySeries[seriesIndex] ?? 0;\n\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]);\n const xClipCenter = xScale.scale(x);\n if (!Number.isFinite(xClipCenter) || !Number.isFinite(y)) continue;\n\n const left = xClipCenter - clusterWidthClip / 2 + clusterIndex * (barWidthClip + gapClip);\n\n let baseClip = baselineClip;\n let height = 0;\n\n if (stackId !== '') {\n let sumsForX = stackSumsByStackId.get(stackId);\n if (!sumsForX) {\n sumsForX = new Map<number, { posSum: number; negSum: number }>();\n stackSumsByStackId.set(stackId, sumsForX);\n }\n\n // NOTE: Never key stacks by raw `x` (float equality is fragile). Instead, compute a stable\n // integer \"category\" key so visually-equivalent bars stack together even with tiny noise.\n let xKey: number;\n if (Number.isFinite(categoryWidthClip) && categoryWidthClip > 0 && Number.isFinite(xClipCenter)) {\n xKey = Math.round((xClipCenter - plotClipRect.left) / categoryWidthClip);\n } else if (Number.isFinite(categoryStep) && categoryStep > 0) {\n xKey = Math.round(x / categoryStep);\n } else {\n // Last-resort: stable-ish quantization in domain space.\n xKey = Math.round(x * 1e6);\n }\n\n let sums = sumsForX.get(xKey);\n if (!sums) {\n sums = { posSum: baselineDomain, negSum: baselineDomain };\n sumsForX.set(xKey, sums);\n }\n\n // Stack upward for y>=0, downward for y<0 (domain units).\n let baseDomain: number;\n let topDomain: number;\n if (y >= 0) {\n baseDomain = sums.posSum;\n topDomain = baseDomain + y;\n sums.posSum = topDomain;\n } else {\n baseDomain = sums.negSum;\n topDomain = baseDomain + y;\n sums.negSum = topDomain;\n }\n\n const bClip = yScale.scale(baseDomain);\n const tClip = yScale.scale(topDomain);\n if (!Number.isFinite(bClip) || !Number.isFinite(tClip)) continue;\n baseClip = bClip;\n height = tClip - bClip;\n } else {\n const yClip = yScale.scale(y);\n if (!Number.isFinite(yClip)) continue;\n height = yClip - baselineClip;\n }\n\n f32[outFloats + 0] = left;\n f32[outFloats + 1] = baseClip;\n f32[outFloats + 2] = barWidthClip;\n f32[outFloats + 3] = height;\n f32[outFloats + 4] = r;\n f32[outFloats + 5] = g;\n f32[outFloats + 6] = b;\n f32[outFloats + 7] = a;\n outFloats += INSTANCE_STRIDE_FLOATS;\n }\n }\n\n // If we skipped invalid points, resize the effective instance count.\n instanceCount = outFloats / INSTANCE_STRIDE_FLOATS;\n const requiredBytes = Math.max(4, instanceCount * INSTANCE_STRIDE_BYTES);\n\n if (!instanceBuffer || instanceBuffer.size < requiredBytes) {\n const grownBytes = Math.max(Math.max(4, nextPow2(requiredBytes)), instanceBuffer ? instanceBuffer.size : 0);\n if (instanceBuffer) {\n try {\n instanceBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n instanceBuffer = device.createBuffer({\n label: 'barRenderer/instanceBuffer',\n size: grownBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n if (instanceCount > 0) {\n device.queue.writeBuffer(instanceBuffer, 0, cpuInstanceStagingBuffer, 0, instanceCount * INSTANCE_STRIDE_BYTES);\n }\n };\n\n const render: BarRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!instanceBuffer || instanceCount === 0) return;\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, instanceBuffer);\n passEncoder.draw(6, instanceCount);\n };\n\n const dispose: BarRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n if (instanceBuffer) {\n try {\n instanceBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n instanceBuffer = null;\n instanceCount = 0;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n };\n\n return { prepare, render, dispose };\n}\n\n","export default \"// scatter.wgsl\\n// Instanced anti-aliased circle shader (SDF):\\n// - Per-instance vertex input:\\n// - center = vec2<f32> point center (transformed by VSUniforms.transform)\\n// - radiusPx = f32 circle radius in pixels\\n// - Draw call: draw(6, instanceCount) using triangle-list expansion in VS\\n// - Uniforms:\\n// - @group(0) @binding(0): VSUniforms { transform, viewportPx }\\n// - @group(0) @binding(1): FSUniforms { color }\\n//\\n// Notes:\\n// - `viewportPx` is the current render target size in pixels (width, height).\\n// - The quad is expanded in clip space using `radiusPx` and `viewportPx`.\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n viewportPx: vec2<f32>,\\n // Pad to 16-byte alignment (mat4x4 is 64B; vec2 adds 8B; pad to 80B).\\n _pad0: vec2<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct FSUniforms {\\n color: vec4<f32>,\\n};\\n\\n@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;\\n\\nstruct VSIn {\\n @location(0) center: vec2<f32>,\\n @location(1) radiusPx: f32,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n @location(0) localPx: vec2<f32>,\\n @location(1) radiusPx: f32,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {\\n // Fixed local corners for 2 triangles (triangle-list).\\n // `localNdc` is a quad in [-1, 1]^2; we convert it to pixel offsets via radiusPx.\\n let localNdc = array<vec2<f32>, 6>(\\n vec2<f32>(-1.0, -1.0),\\n vec2<f32>( 1.0, -1.0),\\n vec2<f32>(-1.0, 1.0),\\n vec2<f32>(-1.0, 1.0),\\n vec2<f32>( 1.0, -1.0),\\n vec2<f32>( 1.0, 1.0)\\n );\\n\\n let corner = localNdc[vertexIndex];\\n let localPx = corner * in.radiusPx;\\n\\n // Convert pixel offset to clip-space offset.\\n // Clip space spans [-1, 1] across the viewport, so px -> clip is (2 / viewportPx).\\n let localClip = localPx * (2.0 / vsUniforms.viewportPx);\\n\\n let centerClip = (vsUniforms.transform * vec4<f32>(in.center, 0.0, 1.0)).xy;\\n\\n var out: VSOut;\\n out.clipPosition = vec4<f32>(centerClip + localClip, 0.0, 1.0);\\n out.localPx = localPx;\\n out.radiusPx = in.radiusPx;\\n return out;\\n}\\n\\n@fragment\\nfn fsMain(in: VSOut) -> @location(0) vec4<f32> {\\n // Signed distance to the circle boundary (negative inside).\\n let dist = length(in.localPx) - in.radiusPx;\\n\\n // Analytic-ish AA: smooth edge based on derivative of dist in screen space.\\n let w = fwidth(dist);\\n let a = 1.0 - smoothstep(0.0, w, dist);\\n\\n // Discard fully outside to avoid unnecessary blending work.\\n if (a <= 0.0) {\\n discard;\\n }\\n\\n return vec4<f32>(fsUniforms.color.rgb, fsUniforms.color.a * a);\\n}\\n\\n\"","import scatterWgsl from '../shaders/scatter.wgsl?raw';\nimport type { ResolvedScatterSeriesConfig } from '../config/OptionResolver';\nimport type { DataPoint, DataPointTuple, ScatterPointTuple } from '../config/types';\nimport type { LinearScale } from '../utils/scales';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport type { GridArea } from './createGridRenderer';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\n\nexport interface ScatterRenderer {\n prepare(\n seriesConfig: ResolvedScatterSeriesConfig,\n data: ResolvedScatterSeriesConfig['data'],\n xScale: LinearScale,\n yScale: LinearScale,\n gridArea?: GridArea\n ): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface ScatterRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\ntype Rgba = readonly [r: number, g: number, b: number, a: number];\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_SCATTER_RADIUS_CSS_PX = 4;\nconst INSTANCE_STRIDE_BYTES = 16; // center.xy, radiusPx, pad\nconst INSTANCE_STRIDE_FLOATS = INSTANCE_STRIDE_BYTES / 4;\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst clampInt = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v | 0));\n\nconst parseSeriesColorToRgba01 = (color: string): Rgba =>\n parseCssColorToRgba01(color) ?? ([0, 0, 0, 1] as const);\n\nconst nextPow2 = (v: number): number => {\n if (!Number.isFinite(v) || v <= 0) return 1;\n const n = Math.ceil(v);\n return 2 ** Math.ceil(Math.log2(n));\n};\n\nconst isTupleDataPoint = (point: DataPoint): point is DataPointTuple => Array.isArray(point);\n\nconst getPointXY = (point: DataPoint): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(point)) return { x: point[0], y: point[1] };\n return { x: point.x, y: point.y };\n};\n\nconst getPointSizeCssPx = (point: DataPoint): number | null => {\n if (isTupleDataPoint(point)) {\n const s = point[2];\n return typeof s === 'number' && Number.isFinite(s) ? s : null;\n }\n const s = point.size;\n return typeof s === 'number' && Number.isFinite(s) ? s : null;\n};\n\nconst toScatterTuple = (point: DataPoint): ScatterPointTuple => {\n if (isTupleDataPoint(point)) return point;\n return [point.x, point.y, point.size] as const;\n};\n\nconst computeDataBounds = (\n data: ReadonlyArray<DataPoint>\n): { readonly xMin: number; readonly xMax: number; readonly yMin: number; readonly yMax: number } => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return { xMin: 0, xMax: 1, yMin: 0, yMax: 1 };\n }\n\n // Avoid degenerate domains for affine derivation (handled later too, but keep stable samples).\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst computeClipAffineFromScale = (\n scale: LinearScale,\n v0: number,\n v1: number\n): { readonly a: number; readonly b: number } => {\n const p0 = scale.scale(v0);\n const p1 = scale.scale(v1);\n\n // If the domain sample is degenerate or non-finite, fall back to constant output.\n if (!Number.isFinite(v0) || !Number.isFinite(v1) || v0 === v1 || !Number.isFinite(p0) || !Number.isFinite(p1)) {\n return { a: 0, b: Number.isFinite(p0) ? p0 : 0 };\n }\n\n const a = (p1 - p0) / (v1 - v0);\n const b = p0 - a * v0;\n return { a: Number.isFinite(a) ? a : 0, b: Number.isFinite(b) ? b : 0 };\n};\n\nconst writeTransformMat4F32 = (out: Float32Array, ax: number, bx: number, ay: number, by: number): void => {\n // Column-major mat4x4 for: clip = M * vec4(x, y, 0, 1)\n out[0] = ax;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0; // col0\n out[4] = 0;\n out[5] = ay;\n out[6] = 0;\n out[7] = 0; // col1\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0; // col2\n out[12] = bx;\n out[13] = by;\n out[14] = 0;\n out[15] = 1; // col3\n};\n\nconst computePlotScissorDevicePx = (\n gridArea: GridArea\n): { readonly x: number; readonly y: number; readonly w: number; readonly h: number } => {\n const dpr = window.devicePixelRatio || 1;\n const { canvasWidth, canvasHeight } = gridArea;\n\n const plotLeftDevice = gridArea.left * dpr;\n const plotRightDevice = canvasWidth - gridArea.right * dpr;\n const plotTopDevice = gridArea.top * dpr;\n const plotBottomDevice = canvasHeight - gridArea.bottom * dpr;\n\n const scissorX = clampInt(Math.floor(plotLeftDevice), 0, Math.max(0, canvasWidth));\n const scissorY = clampInt(Math.floor(plotTopDevice), 0, Math.max(0, canvasHeight));\n const scissorR = clampInt(Math.ceil(plotRightDevice), 0, Math.max(0, canvasWidth));\n const scissorB = clampInt(Math.ceil(plotBottomDevice), 0, Math.max(0, canvasHeight));\n const scissorW = Math.max(0, scissorR - scissorX);\n const scissorH = Math.max(0, scissorB - scissorY);\n\n return { x: scissorX, y: scissorY, w: scissorW, h: scissorH };\n};\n\nexport function createScatterRenderer(device: GPUDevice, options?: ScatterRendererOptions): ScatterRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\n ],\n });\n\n // VSUniforms: mat4x4 (64) + viewportPx vec2 (8) + pad vec2 (8) = 80 bytes.\n const vsUniformBuffer = createUniformBuffer(device, 80, { label: 'scatterRenderer/vsUniforms' });\n const fsUniformBuffer = createUniformBuffer(device, 16, { label: 'scatterRenderer/fsUniforms' });\n\n // Reused CPU-side staging for uniform writes (avoid per-frame allocations).\n const vsUniformScratchBuffer = new ArrayBuffer(80);\n const vsUniformScratchF32 = new Float32Array(vsUniformScratchBuffer);\n const fsUniformScratchF32 = new Float32Array(4);\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBuffer } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'scatterRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: scatterWgsl,\n label: 'scatter.wgsl',\n buffers: [\n {\n arrayStride: INSTANCE_STRIDE_BYTES,\n stepMode: 'instance',\n attributes: [\n { shaderLocation: 0, format: 'float32x2', offset: 0 },\n { shaderLocation: 1, format: 'float32', offset: 8 },\n ],\n },\n ],\n },\n fragment: {\n code: scatterWgsl,\n label: 'scatter.wgsl',\n formats: targetFormat,\n // Standard alpha blending (circle AA uses alpha, and series color may be translucent).\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'triangle-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let instanceBuffer: GPUBuffer | null = null;\n let instanceCount = 0;\n let cpuInstanceStagingBuffer = new ArrayBuffer(0);\n let cpuInstanceStagingF32 = new Float32Array(cpuInstanceStagingBuffer);\n\n let lastCanvasWidth = 0;\n let lastCanvasHeight = 0;\n let lastViewportPx: readonly [number, number] = [1, 1];\n let lastScissor: { readonly x: number; readonly y: number; readonly w: number; readonly h: number } | null = null;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('ScatterRenderer is disposed.');\n };\n\n const ensureCpuInstanceCapacityFloats = (requiredFloats: number): void => {\n if (requiredFloats <= cpuInstanceStagingF32.length) return;\n const nextFloats = Math.max(8, nextPow2(requiredFloats));\n cpuInstanceStagingBuffer = new ArrayBuffer(nextFloats * 4);\n cpuInstanceStagingF32 = new Float32Array(cpuInstanceStagingBuffer);\n };\n\n const writeVsUniforms = (\n ax: number,\n bx: number,\n ay: number,\n by: number,\n viewportW: number,\n viewportH: number\n ): void => {\n const w = Number.isFinite(viewportW) && viewportW > 0 ? viewportW : 1;\n const h = Number.isFinite(viewportH) && viewportH > 0 ? viewportH : 1;\n\n writeTransformMat4F32(vsUniformScratchF32, ax, bx, ay, by);\n vsUniformScratchF32[16] = w;\n vsUniformScratchF32[17] = h;\n vsUniformScratchF32[18] = 0;\n vsUniformScratchF32[19] = 0;\n writeUniformBuffer(device, vsUniformBuffer, vsUniformScratchBuffer);\n\n lastViewportPx = [w, h];\n };\n\n const prepare: ScatterRenderer['prepare'] = (seriesConfig, data, xScale, yScale, gridArea) => {\n assertNotDisposed();\n\n const { xMin, xMax, yMin, yMax } = computeDataBounds(data);\n const { a: ax, b: bx } = computeClipAffineFromScale(xScale, xMin, xMax);\n const { a: ay, b: by } = computeClipAffineFromScale(yScale, yMin, yMax);\n\n if (gridArea) {\n lastCanvasWidth = gridArea.canvasWidth;\n lastCanvasHeight = gridArea.canvasHeight;\n writeVsUniforms(ax, bx, ay, by, gridArea.canvasWidth, gridArea.canvasHeight);\n lastScissor = computePlotScissorDevicePx(gridArea);\n } else {\n // Backward-compatible: keep rendering with the last known viewport (or safe default).\n writeVsUniforms(ax, bx, ay, by, lastViewportPx[0], lastViewportPx[1]);\n lastScissor = null;\n }\n\n const [r, g, b, a] = parseSeriesColorToRgba01(seriesConfig.color);\n fsUniformScratchF32[0] = r;\n fsUniformScratchF32[1] = g;\n fsUniformScratchF32[2] = b;\n fsUniformScratchF32[3] = clamp01(a);\n writeUniformBuffer(device, fsUniformBuffer, fsUniformScratchF32);\n\n const dpr = window.devicePixelRatio || 1;\n const hasValidDpr = dpr > 0 && Number.isFinite(dpr);\n\n const seriesSymbolSize = seriesConfig.symbolSize;\n const getSeriesSizeCssPx =\n typeof seriesSymbolSize === 'function'\n ? (point: DataPoint): number => {\n const v = seriesSymbolSize(toScatterTuple(point));\n return typeof v === 'number' && Number.isFinite(v) ? v : DEFAULT_SCATTER_RADIUS_CSS_PX;\n }\n : typeof seriesSymbolSize === 'number' && Number.isFinite(seriesSymbolSize)\n ? (): number => seriesSymbolSize\n : (): number => DEFAULT_SCATTER_RADIUS_CSS_PX;\n\n ensureCpuInstanceCapacityFloats(data.length * INSTANCE_STRIDE_FLOATS);\n const f32 = cpuInstanceStagingF32;\n let outFloats = 0;\n\n for (let i = 0; i < data.length; i++) {\n const p = data[i];\n const { x, y } = getPointXY(p);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n\n const sizeCss = getPointSizeCssPx(p) ?? getSeriesSizeCssPx(p);\n const radiusCss = Number.isFinite(sizeCss) ? Math.max(0, sizeCss) : DEFAULT_SCATTER_RADIUS_CSS_PX;\n const radiusDevicePx = hasValidDpr ? radiusCss * dpr : radiusCss;\n if (!(radiusDevicePx > 0)) continue;\n\n f32[outFloats + 0] = x;\n f32[outFloats + 1] = y;\n f32[outFloats + 2] = radiusDevicePx;\n f32[outFloats + 3] = 0; // pad\n outFloats += INSTANCE_STRIDE_FLOATS;\n }\n\n instanceCount = outFloats / INSTANCE_STRIDE_FLOATS;\n const requiredBytes = Math.max(4, instanceCount * INSTANCE_STRIDE_BYTES);\n\n if (!instanceBuffer || instanceBuffer.size < requiredBytes) {\n const grownBytes = Math.max(Math.max(4, nextPow2(requiredBytes)), instanceBuffer ? instanceBuffer.size : 0);\n if (instanceBuffer) {\n try {\n instanceBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n instanceBuffer = device.createBuffer({\n label: 'scatterRenderer/instanceBuffer',\n size: grownBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n if (instanceBuffer && instanceCount > 0) {\n device.queue.writeBuffer(instanceBuffer, 0, cpuInstanceStagingBuffer, 0, instanceCount * INSTANCE_STRIDE_BYTES);\n }\n };\n\n const render: ScatterRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!instanceBuffer || instanceCount === 0) return;\n\n // Clip to plot area when available.\n if (lastScissor && lastCanvasWidth > 0 && lastCanvasHeight > 0) {\n passEncoder.setScissorRect(lastScissor.x, lastScissor.y, lastScissor.w, lastScissor.h);\n }\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, instanceBuffer);\n passEncoder.draw(6, instanceCount);\n\n // Reset scissor to full canvas to avoid impacting later renderers.\n if (lastScissor && lastCanvasWidth > 0 && lastCanvasHeight > 0) {\n passEncoder.setScissorRect(0, 0, lastCanvasWidth, lastCanvasHeight);\n }\n };\n\n const dispose: ScatterRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n if (instanceBuffer) {\n try {\n instanceBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n instanceBuffer = null;\n instanceCount = 0;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n\n lastCanvasWidth = 0;\n lastCanvasHeight = 0;\n lastViewportPx = [1, 1];\n lastScissor = null;\n };\n\n return { prepare, render, dispose };\n}\n\n","export default \"// pie.wgsl\\n// Instanced anti-aliased pie-slice shader (instanced quad + SDF mask).\\n//\\n// - Per-instance vertex input:\\n// - center = vec2<f32> slice center (transformed by VSUniforms.transform)\\n// - startAngleRad = f32 start angle in radians\\n// - endAngleRad = f32 end angle in radians\\n// - radiiPx = vec2<f32>(innerRadiusPx, outerRadiusPx) in *device pixels*\\n// - color = vec4<f32> RGBA color in [0..1]\\n//\\n// - Draw call: draw(6, instanceCount) using triangle-list expansion in VS\\n//\\n// - Uniforms:\\n// - @group(0) @binding(0): VSUniforms { transform, viewportPx }\\n//\\n// Notes:\\n// - The quad is expanded in clip space using `radiusPx` and `viewportPx`.\\n// - Fragment uses an SDF mask for the circle boundary + an angular wedge mask.\\n// - Fully outside fragments are discarded to avoid unnecessary blending work.\\n//\\n// Conventions: matches other shaders in this repo (vsMain/fsMain, group 0 bindings,\\n// and explicit uniform padding/alignment where needed).\\n\\nconst PI: f32 = 3.141592653589793;\\nconst TAU: f32 = 6.283185307179586; // 2*pi\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n viewportPx: vec2<f32>,\\n // Pad to 16-byte alignment (mat4x4 is 64B; vec2 adds 8B; pad to 80B).\\n _pad0: vec2<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct VSIn {\\n @location(0) center: vec2<f32>,\\n @location(1) startAngleRad: f32,\\n @location(2) endAngleRad: f32,\\n @location(3) radiiPx: vec2<f32>, // (innerPx, outerPx)\\n @location(4) color: vec4<f32>,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n @location(0) localPx: vec2<f32>,\\n @location(1) startAngleRad: f32,\\n @location(2) endAngleRad: f32,\\n @location(3) radiiPx: vec2<f32>,\\n @location(4) color: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {\\n // Fixed local corners for 2 triangles (triangle-list).\\n // `localNdc` is a quad in [-1, 1]^2; we convert it to pixel offsets via radiusPx.\\n let localNdc = array<vec2<f32>, 6>(\\n vec2<f32>(-1.0, -1.0),\\n vec2<f32>( 1.0, -1.0),\\n vec2<f32>(-1.0, 1.0),\\n vec2<f32>(-1.0, 1.0),\\n vec2<f32>( 1.0, -1.0),\\n vec2<f32>( 1.0, 1.0)\\n );\\n\\n let corner = localNdc[vertexIndex];\\n let outerPx = in.radiiPx.y;\\n let localPx = corner * outerPx;\\n\\n // Convert pixel offset to clip-space offset.\\n // Clip space spans [-1, 1] across the viewport, so px -> clip is (2 / viewportPx).\\n let localClip = localPx * (2.0 / vsUniforms.viewportPx);\\n\\n let centerClip = (vsUniforms.transform * vec4<f32>(in.center, 0.0, 1.0)).xy;\\n\\n var out: VSOut;\\n out.clipPosition = vec4<f32>(centerClip + localClip, 0.0, 1.0);\\n out.localPx = localPx;\\n out.startAngleRad = in.startAngleRad;\\n out.endAngleRad = in.endAngleRad;\\n out.radiiPx = in.radiiPx;\\n out.color = in.color;\\n return out;\\n}\\n\\nfn wrapToTau(theta: f32) -> f32 {\\n // Maps theta to [0, TAU). (Input often comes from atan2 in [-PI, PI].)\\n return select(theta, theta + TAU, theta < 0.0);\\n}\\n\\n@fragment\\nfn fsMain(in: VSOut) -> @location(0) vec4<f32> {\\n let p = in.localPx;\\n let r = length(p);\\n\\n let innerPx = in.radiiPx.x;\\n let outerPx = in.radiiPx.y;\\n\\n // --- Radial mask: ring between inner and outer radii (inner==0 => pie) ---\\n // Positive inside the ring, negative outside.\\n let radialDist = min(r - innerPx, outerPx - r);\\n let radialW = fwidth(radialDist);\\n let radialA = smoothstep(-radialW, radialW, radialDist);\\n\\n if (radialA <= 0.0) {\\n discard;\\n }\\n\\n // Compute fragment angle in [0, TAU).\\n let angle = wrapToTau(atan2(p.y, p.x));\\n\\n // --- Angular mask: wedge between start/end angles with wrap ---\\n let start = in.startAngleRad;\\n let end = in.endAngleRad;\\n\\n // Compute span in [0, 2π) with wrap.\\n var span = end - start;\\n span = span + select(0.0, TAU, span < 0.0);\\n\\n // Compute rel in [0, 2π) with wrap.\\n var rel = angle - start;\\n rel = rel + select(0.0, TAU, rel < 0.0);\\n\\n let inside = rel <= span;\\n\\n // Signed angular distance (in radians) to nearest boundary.\\n // - Inside: +min(rel, span-rel)\\n // - Outside: -min(rel-span, 2π-rel)\\n let dIn = min(rel, max(span - rel, 0.0));\\n let dOutA = max(rel - span, 0.0);\\n let dOutB = max(TAU - rel, 0.0);\\n let dOut = min(dOutA, dOutB);\\n\\n let signedAngleDist = select(-dOut, dIn, inside);\\n\\n // Convert to approximate pixel distance to the boundary ray.\\n // (For small angles, perpendicular distance to a ray ≈ r * angle.)\\n let angleDistPx = signedAngleDist * max(r, 1.0);\\n\\n let angW = fwidth(angleDistPx);\\n let angularA = smoothstep(-angW, angW, angleDistPx);\\n\\n let aOut = radialA * angularA;\\n if (aOut <= 0.0) {\\n discard;\\n }\\n\\n return vec4<f32>(in.color.rgb, in.color.a * aOut);\\n}\\n\\n\"","import pieWgsl from '../shaders/pie.wgsl?raw';\nimport type { ResolvedPieSeriesConfig } from '../config/OptionResolver';\nimport type { PieCenter, PieRadius } from '../config/types';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport type { GridArea } from './createGridRenderer';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\n\nexport interface PieRenderer {\n prepare(seriesConfig: ResolvedPieSeriesConfig, gridArea: GridArea): void;\n render(passEncoder: GPURenderPassEncoder): void;\n dispose(): void;\n}\n\nexport interface PieRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\ntype Rgba = readonly [r: number, g: number, b: number, a: number];\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\n\n// Instance layout (must match `pie.wgsl` locations):\n// @location(0) center: vec2<f32>\n// @location(1) startAngleRad: f32\n// @location(2) endAngleRad: f32\n// @location(3) radiiPx: vec2<f32> (innerPx, outerPx) in device pixels\n// @location(4) color: vec4<f32>\nconst INSTANCE_STRIDE_BYTES = 40;\nconst INSTANCE_STRIDE_FLOATS = INSTANCE_STRIDE_BYTES / 4;\n\nconst TAU = Math.PI * 2;\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst clampInt = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v | 0));\n\nconst nextPow2 = (v: number): number => {\n if (!Number.isFinite(v) || v <= 0) return 1;\n const n = Math.ceil(v);\n return 2 ** Math.ceil(Math.log2(n));\n};\n\nconst wrapToTau = (thetaRad: number): number => {\n if (!Number.isFinite(thetaRad)) return 0;\n const t = thetaRad % TAU;\n return t < 0 ? t + TAU : t;\n};\n\nconst parseColor = (cssColor: string, fallbackCssColor: string): Rgba => {\n const parsed = parseCssColorToRgba01(cssColor);\n if (parsed) return [parsed[0], parsed[1], parsed[2], clamp01(parsed[3])] as const;\n\n const fb = parseCssColorToRgba01(fallbackCssColor);\n if (fb) return [fb[0], fb[1], fb[2], clamp01(fb[3])] as const;\n\n return [0, 0, 0, 1] as const;\n};\n\nconst parseNumberOrPercent = (value: number | string, basis: number): number | null => {\n if (typeof value === 'number') return Number.isFinite(value) ? value : null;\n if (typeof value !== 'string') return null;\n\n const s = value.trim();\n if (s.length === 0) return null;\n\n if (s.endsWith('%')) {\n const pct = Number.parseFloat(s.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return (pct / 100) * basis;\n }\n\n // Be permissive: allow numeric strings like \"120\" even though the public type primarily documents percent strings.\n const n = Number.parseFloat(s);\n return Number.isFinite(n) ? n : null;\n};\n\nconst resolveCenterPlotCss = (\n center: PieCenter | undefined,\n plotWidthCss: number,\n plotHeightCss: number\n): { readonly x: number; readonly y: number } => {\n const xRaw = center?.[0] ?? '50%';\n const yRaw = center?.[1] ?? '50%';\n\n const x = parseNumberOrPercent(xRaw, plotWidthCss);\n const y = parseNumberOrPercent(yRaw, plotHeightCss);\n\n return {\n x: Number.isFinite(x) ? x! : plotWidthCss * 0.5,\n y: Number.isFinite(y) ? y! : plotHeightCss * 0.5,\n };\n};\n\nconst isRadiusTuple = (\n radius: PieRadius\n): radius is readonly [inner: number | string, outer: number | string] => Array.isArray(radius);\n\nconst resolveRadiiCss = (\n radius: PieRadius | undefined,\n maxRadiusCss: number\n): { readonly inner: number; readonly outer: number } => {\n // Default similar to common chart libs.\n if (radius == null) return { inner: 0, outer: maxRadiusCss * 0.7 };\n\n if (isRadiusTuple(radius)) {\n const inner = parseNumberOrPercent(radius[0], maxRadiusCss);\n const outer = parseNumberOrPercent(radius[1], maxRadiusCss);\n const innerCss = Math.max(0, Number.isFinite(inner) ? inner! : 0);\n const outerCss = Math.max(innerCss, Number.isFinite(outer) ? outer! : maxRadiusCss * 0.7);\n return { inner: innerCss, outer: Math.min(maxRadiusCss, outerCss) };\n }\n\n const outer = parseNumberOrPercent(radius, maxRadiusCss);\n const outerCss = Math.max(0, Number.isFinite(outer) ? outer! : maxRadiusCss * 0.7);\n return { inner: 0, outer: Math.min(maxRadiusCss, outerCss) };\n};\n\nconst computePlotScissorDevicePx = (\n gridArea: GridArea\n): { readonly x: number; readonly y: number; readonly w: number; readonly h: number } => {\n const dpr = window.devicePixelRatio || 1;\n const { canvasWidth, canvasHeight } = gridArea;\n\n const plotLeftDevice = gridArea.left * dpr;\n const plotRightDevice = canvasWidth - gridArea.right * dpr;\n const plotTopDevice = gridArea.top * dpr;\n const plotBottomDevice = canvasHeight - gridArea.bottom * dpr;\n\n const scissorX = clampInt(Math.floor(plotLeftDevice), 0, Math.max(0, canvasWidth));\n const scissorY = clampInt(Math.floor(plotTopDevice), 0, Math.max(0, canvasHeight));\n const scissorR = clampInt(Math.ceil(plotRightDevice), 0, Math.max(0, canvasWidth));\n const scissorB = clampInt(Math.ceil(plotBottomDevice), 0, Math.max(0, canvasHeight));\n const scissorW = Math.max(0, scissorR - scissorX);\n const scissorH = Math.max(0, scissorB - scissorY);\n\n return { x: scissorX, y: scissorY, w: scissorW, h: scissorH };\n};\n\nconst IDENTITY_MAT4_F32 = new Float32Array([\n 1, 0, 0, 0, // col0\n 0, 1, 0, 0, // col1\n 0, 0, 1, 0, // col2\n 0, 0, 0, 1, // col3\n]);\n\nexport function createPieRenderer(device: GPUDevice, options?: PieRendererOptions): PieRenderer {\n let disposed = false;\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } }],\n });\n\n // VSUniforms in `pie.wgsl`: mat4x4 (64) + viewportPx vec2 (8) + pad vec2 (8) = 80 bytes.\n const vsUniformBuffer = createUniformBuffer(device, 80, { label: 'pieRenderer/vsUniforms' });\n\n // Reused CPU-side staging for uniform writes (avoid per-frame allocations).\n const vsUniformScratchBuffer = new ArrayBuffer(80);\n const vsUniformScratchF32 = new Float32Array(vsUniformScratchBuffer);\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [{ binding: 0, resource: { buffer: vsUniformBuffer } }],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'pieRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: pieWgsl,\n label: 'pie.wgsl',\n buffers: [\n {\n arrayStride: INSTANCE_STRIDE_BYTES,\n stepMode: 'instance',\n attributes: [\n { shaderLocation: 0, format: 'float32x2', offset: 0 }, // center\n { shaderLocation: 1, format: 'float32', offset: 8 }, // startAngleRad\n { shaderLocation: 2, format: 'float32', offset: 12 }, // endAngleRad\n { shaderLocation: 3, format: 'float32x2', offset: 16 }, // radiiPx\n { shaderLocation: 4, format: 'float32x4', offset: 24 }, // color\n ],\n },\n ],\n },\n fragment: {\n code: pieWgsl,\n label: 'pie.wgsl',\n formats: targetFormat,\n // Standard alpha blending for AA edges and translucent slice colors.\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'triangle-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let instanceBuffer: GPUBuffer | null = null;\n let instanceCount = 0;\n let cpuInstanceStagingBuffer = new ArrayBuffer(0);\n let cpuInstanceStagingF32 = new Float32Array(cpuInstanceStagingBuffer);\n\n let lastCanvasWidth = 0;\n let lastCanvasHeight = 0;\n let lastScissor: { readonly x: number; readonly y: number; readonly w: number; readonly h: number } | null = null;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('PieRenderer is disposed.');\n };\n\n const ensureCpuInstanceCapacityFloats = (requiredFloats: number): void => {\n if (requiredFloats <= cpuInstanceStagingF32.length) return;\n const nextFloats = Math.max(8, nextPow2(requiredFloats));\n cpuInstanceStagingBuffer = new ArrayBuffer(nextFloats * 4);\n cpuInstanceStagingF32 = new Float32Array(cpuInstanceStagingBuffer);\n };\n\n const writeVsUniforms = (viewportWDevicePx: number, viewportHDevicePx: number): void => {\n const w = Number.isFinite(viewportWDevicePx) && viewportWDevicePx > 0 ? viewportWDevicePx : 1;\n const h = Number.isFinite(viewportHDevicePx) && viewportHDevicePx > 0 ? viewportHDevicePx : 1;\n\n vsUniformScratchF32.set(IDENTITY_MAT4_F32, 0);\n vsUniformScratchF32[16] = w;\n vsUniformScratchF32[17] = h;\n vsUniformScratchF32[18] = 0;\n vsUniformScratchF32[19] = 0;\n writeUniformBuffer(device, vsUniformBuffer, vsUniformScratchBuffer);\n };\n\n const prepare: PieRenderer['prepare'] = (seriesConfig, gridArea) => {\n assertNotDisposed();\n\n const dprRaw = window.devicePixelRatio || 1;\n const dpr = dprRaw > 0 && Number.isFinite(dprRaw) ? dprRaw : 1;\n\n lastCanvasWidth = gridArea.canvasWidth;\n lastCanvasHeight = gridArea.canvasHeight;\n writeVsUniforms(gridArea.canvasWidth, gridArea.canvasHeight);\n lastScissor = computePlotScissorDevicePx(gridArea);\n\n const canvasCssWidth = gridArea.canvasWidth / dpr;\n const canvasCssHeight = gridArea.canvasHeight / dpr;\n if (!(canvasCssWidth > 0) || !(canvasCssHeight > 0)) {\n instanceCount = 0;\n return;\n }\n\n const plotWidthCss = canvasCssWidth - gridArea.left - gridArea.right;\n const plotHeightCss = canvasCssHeight - gridArea.top - gridArea.bottom;\n if (!(plotWidthCss > 0) || !(plotHeightCss > 0)) {\n instanceCount = 0;\n return;\n }\n\n const maxRadiusCss = 0.5 * Math.min(plotWidthCss, plotHeightCss);\n if (!(maxRadiusCss > 0)) {\n instanceCount = 0;\n return;\n }\n\n // Center specified in plot-local CSS px (or %), then shifted by GridArea CSS margins.\n const centerPlotCss = resolveCenterPlotCss(seriesConfig.center, plotWidthCss, plotHeightCss);\n const centerCanvasCssX = gridArea.left + centerPlotCss.x;\n const centerCanvasCssY = gridArea.top + centerPlotCss.y;\n\n // Instance center is in clip space; VS transform is identity.\n const centerClipX = (centerCanvasCssX / canvasCssWidth) * 2 - 1;\n const centerClipY = 1 - (centerCanvasCssY / canvasCssHeight) * 2;\n if (!Number.isFinite(centerClipX) || !Number.isFinite(centerClipY)) {\n instanceCount = 0;\n return;\n }\n\n // Radii specified in CSS px (or % of max radius), converted to device px for the shader.\n const radiiCss = resolveRadiiCss(seriesConfig.radius, maxRadiusCss);\n const innerCss = Math.max(0, Math.min(radiiCss.inner, radiiCss.outer));\n const outerCss = Math.max(innerCss, radiiCss.outer);\n const innerPx = innerCss * dpr;\n const outerPx = outerCss * dpr;\n if (!(outerPx > 0)) {\n instanceCount = 0;\n return;\n }\n\n // Total positive value for angle allocation.\n let total = 0;\n let validCount = 0;\n for (let i = 0; i < seriesConfig.data.length; i++) {\n const v = seriesConfig.data[i]?.value;\n if (typeof v === 'number' && Number.isFinite(v) && v > 0) {\n total += v;\n validCount++;\n }\n }\n if (!(total > 0) || validCount === 0) {\n instanceCount = 0;\n return;\n }\n\n ensureCpuInstanceCapacityFloats(validCount * INSTANCE_STRIDE_FLOATS);\n const f32 = cpuInstanceStagingF32;\n\n // IMPORTANT: shader assumes start/end are already wrapped to [0, 2π) (it only adds TAU once).\n const startDeg =\n typeof seriesConfig.startAngle === 'number' && Number.isFinite(seriesConfig.startAngle) ? seriesConfig.startAngle : 90;\n let current = wrapToTau((startDeg * Math.PI) / 180);\n\n // Make the last slice close the circle (reduces float drift).\n let accumulated = 0;\n let outFloats = 0;\n let emitted = 0;\n\n for (let i = 0; i < seriesConfig.data.length; i++) {\n const item = seriesConfig.data[i];\n const v = item?.value;\n if (typeof v !== 'number' || !Number.isFinite(v) || v <= 0) continue;\n\n emitted++;\n const isLast = emitted === validCount;\n\n const frac = v / total;\n let span = frac * TAU;\n if (isLast) {\n span = Math.max(0, TAU - accumulated);\n } else {\n // Keep accumulated stable and avoid pathological spans from weird inputs.\n span = Math.max(0, Math.min(TAU, span));\n }\n accumulated += span;\n if (!(span > 0)) continue;\n\n const startRad = current;\n const endRad = wrapToTau(current + span);\n current = endRad;\n\n const [r, g, b, a] = parseColor(item.color, seriesConfig.color);\n\n f32[outFloats + 0] = centerClipX;\n f32[outFloats + 1] = centerClipY;\n f32[outFloats + 2] = startRad;\n f32[outFloats + 3] = endRad;\n f32[outFloats + 4] = innerPx;\n f32[outFloats + 5] = outerPx;\n f32[outFloats + 6] = r;\n f32[outFloats + 7] = g;\n f32[outFloats + 8] = b;\n f32[outFloats + 9] = a;\n outFloats += INSTANCE_STRIDE_FLOATS;\n }\n\n instanceCount = outFloats / INSTANCE_STRIDE_FLOATS;\n const requiredBytes = Math.max(4, instanceCount * INSTANCE_STRIDE_BYTES);\n\n if (!instanceBuffer || instanceBuffer.size < requiredBytes) {\n const grownBytes = Math.max(Math.max(4, nextPow2(requiredBytes)), instanceBuffer ? instanceBuffer.size : 0);\n if (instanceBuffer) {\n try {\n instanceBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n instanceBuffer = device.createBuffer({\n label: 'pieRenderer/instanceBuffer',\n size: grownBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n\n if (instanceBuffer && instanceCount > 0) {\n device.queue.writeBuffer(instanceBuffer, 0, cpuInstanceStagingBuffer, 0, instanceCount * INSTANCE_STRIDE_BYTES);\n }\n };\n\n const render: PieRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!instanceBuffer || instanceCount === 0) return;\n\n // Clip to plot area (scissor is in device pixels).\n if (lastScissor && lastCanvasWidth > 0 && lastCanvasHeight > 0) {\n passEncoder.setScissorRect(lastScissor.x, lastScissor.y, lastScissor.w, lastScissor.h);\n }\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, instanceBuffer);\n passEncoder.draw(6, instanceCount);\n\n // Reset scissor to full canvas to avoid impacting later renderers.\n if (lastScissor && lastCanvasWidth > 0 && lastCanvasHeight > 0) {\n passEncoder.setScissorRect(0, 0, lastCanvasWidth, lastCanvasHeight);\n }\n };\n\n const dispose: PieRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n if (instanceBuffer) {\n try {\n instanceBuffer.destroy();\n } catch {\n // best-effort\n }\n }\n instanceBuffer = null;\n instanceCount = 0;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n\n lastCanvasWidth = 0;\n lastCanvasHeight = 0;\n lastScissor = null;\n };\n\n return { prepare, render, dispose };\n}\n\n","export default \"// crosshair.wgsl\\n// Minimal crosshair line shader:\\n// - Vertex input: vec2<f32> position in clip-space coordinates\\n// - VS uniform: transform mat4 (identity)\\n// - FS uniform: solid RGBA color\\n\\nstruct VSUniforms {\\n transform: mat4x4<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct FSUniforms {\\n color: vec4<f32>,\\n};\\n\\n@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;\\n\\nstruct VSIn {\\n @location(0) position: vec2<f32>,\\n};\\n\\nstruct VSOut {\\n @builtin(position) clipPosition: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(in: VSIn) -> VSOut {\\n var out: VSOut;\\n out.clipPosition = vsUniforms.transform * vec4<f32>(in.position, 0.0, 1.0);\\n return out;\\n}\\n\\n@fragment\\nfn fsMain() -> @location(0) vec4<f32> {\\n return fsUniforms.color;\\n}\\n\\n\"","export interface StreamBuffer {\n /**\n * Writes a new vertex payload into the streaming buffer.\n *\n * Notes:\n * - `data` is interpreted as interleaved `vec2<f32>` vertices: `[x0, y0, x1, y1, ...]`.\n * - Uses double buffering (alternates GPU buffers each write) to avoid writing into the same\n * buffer the GPU might still be reading from the prior frame.\n * - Uses a per-buffer CPU mirror (Uint32 bit patterns) to compute partial updates.\n */\n write(data: Float32Array): void;\n /** Returns the GPUBuffer that contains the most recently written data. */\n getBuffer(): GPUBuffer;\n /** Returns the vertex count for the most recently written data. */\n getVertexCount(): number;\n /** Destroys GPU resources (best-effort). Safe to call multiple times. */\n dispose(): void;\n}\n\nconst align4 = (n: number): number => (n + 3) & ~3;\n\n// Small payloads are cheaper to just full-write (avoid diff overhead).\nconst SMALL_FULL_WRITE_MAX_BYTES = 1024;\n\n// Heuristic guard against pathological alternating-word diffs which would produce many tiny ranges.\n// If exceeded, we do a single full-range write for the used bytes.\nconst MAX_DIFF_RANGES_BEFORE_FULL_WRITE = 128;\nconst MAX_CHANGED_WORDS_BEFORE_FULL_WRITE = 16_384;\n\nconst toU32View = (data: Float32Array): Uint32Array => {\n if ((data.byteOffset & 3) !== 0) {\n // This should never happen for Float32Array, but keep it explicit for correctness.\n throw new Error('createStreamBuffer.write: data.byteOffset must be 4-byte aligned.');\n }\n return new Uint32Array(data.buffer, data.byteOffset, data.byteLength >>> 2);\n};\n\nexport function createStreamBuffer(device: GPUDevice, maxSize: number): StreamBuffer {\n if (!Number.isFinite(maxSize) || maxSize <= 0) {\n throw new Error(`createStreamBuffer(maxSize): maxSize (bytes) must be a positive number. Received: ${String(maxSize)}`);\n }\n\n const clamped = Math.max(4, Math.floor(maxSize));\n const capacityBytes = align4(clamped);\n\n const limit = device.limits.maxBufferSize;\n if (capacityBytes > limit) {\n throw new Error(\n `createStreamBuffer(maxSize): requested size ${capacityBytes} bytes exceeds device.limits.maxBufferSize (${limit}).`\n );\n }\n\n const capacityWords = capacityBytes >>> 2;\n\n const createSlot = (label: string): { readonly buffer: GPUBuffer; readonly mirror: Uint32Array } => ({\n buffer: device.createBuffer({\n label,\n size: capacityBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n }),\n mirror: new Uint32Array(capacityWords),\n });\n\n const slots = [createSlot('streamBuffer/a'), createSlot('streamBuffer/b')] as const;\n\n let disposed = false;\n let currentIndex = 0; // getBuffer() returns slots[currentIndex]\n let vertexCount = 0;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('createStreamBuffer: StreamBuffer is disposed.');\n };\n\n const writeFull = (slotIndex: number, newWords: Uint32Array, usedWords: number): void => {\n const slot = slots[slotIndex];\n const mirror = slot.mirror;\n\n if (usedWords < 0 || usedWords > newWords.length) {\n throw new Error('createStreamBuffer.write: internal error (invalid usedWords).');\n }\n if (usedWords === 0) return;\n\n const usedBytes = usedWords << 2;\n device.queue.writeBuffer(slot.buffer, 0, newWords.buffer, newWords.byteOffset, usedBytes);\n mirror.set(newWords.subarray(0, usedWords), 0);\n };\n\n const writeRangesByDiff = (slotIndex: number, newWords: Uint32Array, usedWords: number): void => {\n const slot = slots[slotIndex];\n const mirror = slot.mirror;\n\n // Guard against programming errors.\n if (usedWords < 0 || usedWords > newWords.length) {\n throw new Error('createStreamBuffer.write: internal error (invalid usedWords).');\n }\n\n // Small-buffer fast path: diffing overhead dominates.\n const usedBytes = usedWords << 2;\n if (usedBytes > 0 && usedBytes <= SMALL_FULL_WRITE_MAX_BYTES) {\n writeFull(slotIndex, newWords, usedWords);\n return;\n }\n\n // First pass: collect ranges and decide whether we should fall back to a full write.\n const ranges: Array<[start: number, end: number]> = [];\n let rangeCount = 0;\n let changedWords = 0;\n\n let i = 0;\n while (i < usedWords) {\n // Find first differing word.\n while (i < usedWords && mirror[i] === newWords[i]) i++;\n if (i >= usedWords) break;\n\n const start = i;\n i++;\n // Extend to contiguous run of differing words.\n while (i < usedWords && mirror[i] !== newWords[i]) i++;\n const end = i;\n\n ranges.push([start, end]);\n rangeCount++;\n changedWords += end - start;\n\n // Pathological case guard: alternating changes can create many tiny ranges.\n if (rangeCount > MAX_DIFF_RANGES_BEFORE_FULL_WRITE || changedWords > MAX_CHANGED_WORDS_BEFORE_FULL_WRITE) {\n writeFull(slotIndex, newWords, usedWords);\n return;\n }\n }\n\n // Second pass: apply range writes.\n for (let r = 0; r < ranges.length; r++) {\n const [start, end] = ranges[r];\n const byteOffset = start << 2;\n const byteSize = (end - start) << 2;\n\n // WebGPU requires offsets/sizes to be multiples of 4 bytes (satisfied by word addressing).\n device.queue.writeBuffer(slot.buffer, byteOffset, newWords.buffer, newWords.byteOffset + byteOffset, byteSize);\n mirror.set(newWords.subarray(start, end), start);\n }\n };\n\n const write: StreamBuffer['write'] = (data) => {\n assertNotDisposed();\n\n if (data.length & 1) {\n throw new Error('createStreamBuffer.write: data length must be even (vec2<f32> vertices).');\n }\n\n const bytes = data.byteLength;\n if (bytes > capacityBytes) {\n throw new Error(\n `createStreamBuffer.write: data.byteLength (${bytes}) exceeds capacity (${capacityBytes}). Increase maxSize.`\n );\n }\n\n const nextVertexCount = data.length >>> 1;\n if (bytes === 0) {\n // Avoid swapping buffers for empty payloads.\n vertexCount = nextVertexCount;\n return;\n }\n\n const words = toU32View(data);\n const nextIndex = 1 - currentIndex;\n\n // Only swap after the write succeeds so we never expose a partially-updated \"current\" buffer.\n writeRangesByDiff(nextIndex, words, words.length);\n currentIndex = nextIndex;\n vertexCount = nextVertexCount;\n };\n\n const getBuffer: StreamBuffer['getBuffer'] = () => {\n assertNotDisposed();\n return slots[currentIndex].buffer;\n };\n\n const getVertexCount: StreamBuffer['getVertexCount'] = () => {\n assertNotDisposed();\n return vertexCount;\n };\n\n const dispose: StreamBuffer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n vertexCount = 0;\n\n for (const slot of slots) {\n try {\n slot.buffer.destroy();\n } catch {\n // best-effort\n }\n }\n };\n\n return { write, getBuffer, getVertexCount, dispose };\n}\n\n","import crosshairWgsl from '../shaders/crosshair.wgsl?raw';\nimport { createStreamBuffer } from '../data/createStreamBuffer';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\nimport type { GridArea } from './createGridRenderer';\n\nexport interface CrosshairRenderOptions {\n /** Whether to render the vertical crosshair line. */\n readonly showX: boolean;\n /** Whether to render the horizontal crosshair line. */\n readonly showY: boolean;\n /** CSS color string for the crosshair lines. */\n readonly color: string;\n /**\n * Desired line width in CSS pixels.\n *\n * Note: WebGPU wide lines are not reliably supported; the renderer emulates thickness by\n * drawing multiple 1px lines in device-pixel offsets (best-effort, deterministic).\n */\n readonly lineWidth: number;\n}\n\nexport interface CrosshairRenderer {\n /**\n * Positions the crosshair for rendering.\n *\n * Coordinate contract:\n * - `x`, `y` are CANVAS-LOCAL CSS pixels (e.g. eventManager payload x/y)\n * - `gridArea` margins are CSS pixels; `gridArea.canvasWidth/Height` are device pixels\n */\n prepare(x: number, y: number, gridArea: GridArea, options: CrosshairRenderOptions): void;\n /** Draws the crosshair (if visible) clipped to the plot rect. */\n render(passEncoder: GPURenderPassEncoder): void;\n /** Shows/hides the crosshair without destroying GPU resources. */\n setVisible(visible: boolean): void;\n /** Cleans up GPU resources (best-effort). */\n dispose(): void;\n}\n\nexport interface CrosshairRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_CROSSHAIR_RGBA: readonly [number, number, number, number] = [1, 1, 1, 0.8];\n\nconst MAX_THICKNESS_DEVICE_PX = 8;\nconst DASH_ON_DEVICE_PX = 6;\nconst DASH_OFF_DEVICE_PX = 4;\n\n// Hard cap to keep CPU-side dash segmentation inexpensive/deterministic.\nconst MAX_VERTICES = 8192; // vec2<f32> vertices, i.e. floats/2.\n\nconst createIdentityMat4Buffer = (): ArrayBuffer => {\n // Column-major identity mat4x4\n const buffer = new ArrayBuffer(16 * 4);\n new Float32Array(buffer).set([\n 1, 0, 0, 0, // col0\n 0, 1, 0, 0, // col1\n 0, 0, 1, 0, // col2\n 0, 0, 0, 1, // col3\n ]);\n return buffer;\n};\n\nconst isFiniteGridArea = (gridArea: GridArea): boolean =>\n Number.isFinite(gridArea.left) &&\n Number.isFinite(gridArea.right) &&\n Number.isFinite(gridArea.top) &&\n Number.isFinite(gridArea.bottom) &&\n Number.isFinite(gridArea.canvasWidth) &&\n Number.isFinite(gridArea.canvasHeight);\n\nconst clampInt = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v | 0));\n\nconst computeThicknessOffsetsDevicePx = (lineWidthCssPx: number, dpr: number): readonly number[] => {\n if (!Number.isFinite(lineWidthCssPx) || lineWidthCssPx < 0) {\n throw new Error('CrosshairRenderer.prepare: lineWidth must be a finite non-negative number.');\n }\n if (lineWidthCssPx === 0) return [];\n\n // Convert to device px, then clamp to a small deterministic maximum.\n const widthDevicePx = lineWidthCssPx * dpr;\n const thickness = Math.max(1, Math.min(MAX_THICKNESS_DEVICE_PX, Math.round(widthDevicePx)));\n\n // Symmetric offsets around center (even thickness yields ±0.5 style offsets).\n const mid = (thickness - 1) / 2;\n const out: number[] = [];\n for (let i = 0; i < thickness; i++) out.push(i - mid);\n return out;\n};\n\nconst devicePxToClipX = (xDevicePx: number, canvasWidthDevicePx: number): number =>\n (xDevicePx / canvasWidthDevicePx) * 2.0 - 1.0;\nconst devicePxToClipY = (yDevicePx: number, canvasHeightDevicePx: number): number =>\n 1.0 - (yDevicePx / canvasHeightDevicePx) * 2.0;\n\ntype Segment2D = readonly [x0: number, y0: number, x1: number, y1: number];\n\nconst appendSegmentVerticesClip = (out: number[], seg: Segment2D): void => {\n out.push(seg[0], seg[1], seg[2], seg[3]);\n};\n\nconst generateDashedSegmentsAxisAligned = (start: number, end: number): readonly [number, number][] => {\n // Returns a list of [a,b] segments in *device* space along a single axis.\n if (!Number.isFinite(start) || !Number.isFinite(end)) return [];\n\n const a0 = Math.min(start, end);\n const a1 = Math.max(start, end);\n if (a1 <= a0) return [];\n\n const on = DASH_ON_DEVICE_PX;\n const off = DASH_OFF_DEVICE_PX;\n const period = on + off;\n if (period <= 0 || !Number.isFinite(period)) return [];\n\n // Conservative cap: if this many segments would exceed MAX_VERTICES after thickness expansion,\n // the caller will fall back to a single solid segment.\n const approxSegments = Math.ceil((a1 - a0) / period);\n if (!Number.isFinite(approxSegments) || approxSegments <= 0) return [];\n\n const segments: Array<[number, number]> = [];\n let t = a0;\n while (t < a1) {\n const s0 = t;\n const s1 = Math.min(t + on, a1);\n if (s1 > s0) segments.push([s0, s1]);\n t += period;\n }\n return segments;\n};\n\nconst generateCrosshairVertices = (\n xCssPx: number,\n yCssPx: number,\n gridArea: GridArea,\n options: CrosshairRenderOptions\n): {\n readonly vertices: Float32Array;\n readonly scissor: { readonly x: number; readonly y: number; readonly w: number; readonly h: number };\n} => {\n if (!Number.isFinite(xCssPx) || !Number.isFinite(yCssPx)) {\n throw new Error('CrosshairRenderer.prepare: x and y must be finite numbers.');\n }\n if (!isFiniteGridArea(gridArea)) {\n throw new Error('CrosshairRenderer.prepare: gridArea dimensions must be finite numbers.');\n }\n if (gridArea.canvasWidth <= 0 || gridArea.canvasHeight <= 0) {\n throw new Error('CrosshairRenderer.prepare: canvas dimensions must be positive.');\n }\n if (gridArea.left < 0 || gridArea.right < 0 || gridArea.top < 0 || gridArea.bottom < 0) {\n throw new Error('CrosshairRenderer.prepare: gridArea margins must be non-negative.');\n }\n\n const { canvasWidth, canvasHeight } = gridArea;\n const dpr = window.devicePixelRatio || 1;\n\n const plotLeftDevice = gridArea.left * dpr;\n const plotRightDevice = canvasWidth - gridArea.right * dpr;\n const plotTopDevice = gridArea.top * dpr;\n const plotBottomDevice = canvasHeight - gridArea.bottom * dpr;\n\n const scissorX = clampInt(Math.floor(plotLeftDevice), 0, Math.max(0, canvasWidth));\n const scissorY = clampInt(Math.floor(plotTopDevice), 0, Math.max(0, canvasHeight));\n const scissorR = clampInt(Math.ceil(plotRightDevice), 0, Math.max(0, canvasWidth));\n const scissorB = clampInt(Math.ceil(plotBottomDevice), 0, Math.max(0, canvasHeight));\n const scissorW = Math.max(0, scissorR - scissorX);\n const scissorH = Math.max(0, scissorB - scissorY);\n\n // Convert the requested position from CSS px (canvas-local) to device px.\n const xDevice = xCssPx * dpr;\n const yDevice = yCssPx * dpr;\n\n const thicknessOffsets = computeThicknessOffsetsDevicePx(options.lineWidth, dpr);\n if (thicknessOffsets.length === 0 || (!options.showX && !options.showY)) {\n return {\n vertices: new Float32Array(0),\n scissor: { x: scissorX, y: scissorY, w: scissorW, h: scissorH },\n };\n }\n\n const floats: number[] = [];\n\n // Compute how many dashed segments we *might* generate and fall back to solid if too many.\n const dashSegmentsY = options.showX ? generateDashedSegmentsAxisAligned(plotTopDevice, plotBottomDevice) : [];\n const dashSegmentsX = options.showY ? generateDashedSegmentsAxisAligned(plotLeftDevice, plotRightDevice) : [];\n\n const segmentsPerThickness =\n (options.showX ? dashSegmentsY.length : 0) + (options.showY ? dashSegmentsX.length : 0);\n const projectedVertexCount = segmentsPerThickness * thicknessOffsets.length * 2; // 2 vertices per segment\n\n const useDashed = projectedVertexCount > 0 && projectedVertexCount <= MAX_VERTICES;\n\n const addVerticalSolid = (xDevicePx: number): void => {\n const xClip = devicePxToClipX(xDevicePx, canvasWidth);\n const y0 = devicePxToClipY(plotTopDevice, canvasHeight);\n const y1 = devicePxToClipY(plotBottomDevice, canvasHeight);\n appendSegmentVerticesClip(floats, [xClip, y0, xClip, y1]);\n };\n\n const addHorizontalSolid = (yDevicePx: number): void => {\n const yClip = devicePxToClipY(yDevicePx, canvasHeight);\n const x0 = devicePxToClipX(plotLeftDevice, canvasWidth);\n const x1 = devicePxToClipX(plotRightDevice, canvasWidth);\n appendSegmentVerticesClip(floats, [x0, yClip, x1, yClip]);\n };\n\n if (options.showX) {\n for (let i = 0; i < thicknessOffsets.length; i++) {\n const xd = xDevice + thicknessOffsets[i];\n if (!useDashed) {\n addVerticalSolid(xd);\n continue;\n }\n\n const xClip = devicePxToClipX(xd, canvasWidth);\n for (let s = 0; s < dashSegmentsY.length; s++) {\n const [ya, yb] = dashSegmentsY[s];\n const y0 = devicePxToClipY(ya, canvasHeight);\n const y1 = devicePxToClipY(yb, canvasHeight);\n appendSegmentVerticesClip(floats, [xClip, y0, xClip, y1]);\n }\n }\n }\n\n if (options.showY) {\n for (let i = 0; i < thicknessOffsets.length; i++) {\n const yd = yDevice + thicknessOffsets[i];\n if (!useDashed) {\n addHorizontalSolid(yd);\n continue;\n }\n\n const yClip = devicePxToClipY(yd, canvasHeight);\n for (let s = 0; s < dashSegmentsX.length; s++) {\n const [xa, xb] = dashSegmentsX[s];\n const x0 = devicePxToClipX(xa, canvasWidth);\n const x1 = devicePxToClipX(xb, canvasWidth);\n appendSegmentVerticesClip(floats, [x0, yClip, x1, yClip]);\n }\n }\n }\n\n const vertices = new Float32Array(floats);\n return { vertices, scissor: { x: scissorX, y: scissorY, w: scissorW, h: scissorH } };\n};\n\nexport function createCrosshairRenderer(device: GPUDevice, options?: CrosshairRendererOptions): CrosshairRenderer {\n let disposed = false;\n let visible = true;\n\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\n ],\n });\n\n const vsUniformBuffer = createUniformBuffer(device, 64, { label: 'crosshairRenderer/vsUniforms' });\n const fsUniformBuffer = createUniformBuffer(device, 16, { label: 'crosshairRenderer/fsUniforms' });\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: vsUniformBuffer } },\n { binding: 1, resource: { buffer: fsUniformBuffer } },\n ],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'crosshairRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: {\n code: crosshairWgsl,\n label: 'crosshair.wgsl',\n buffers: [\n {\n arrayStride: 8,\n stepMode: 'vertex',\n attributes: [{ shaderLocation: 0, format: 'float32x2', offset: 0 }],\n },\n ],\n },\n fragment: {\n code: crosshairWgsl,\n label: 'crosshair.wgsl',\n formats: targetFormat,\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'line-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n const stream = createStreamBuffer(device, MAX_VERTICES * 8);\n let vertexCount = 0;\n let lastCanvasWidth = 0;\n let lastCanvasHeight = 0;\n let lastScissor = { x: 0, y: 0, w: 0, h: 0 };\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('CrosshairRenderer is disposed.');\n };\n\n const prepare: CrosshairRenderer['prepare'] = (x, y, gridArea, renderOptions) => {\n assertNotDisposed();\n\n // Validate options up-front for deterministic behavior.\n if (typeof renderOptions.showX !== 'boolean' || typeof renderOptions.showY !== 'boolean') {\n throw new Error('CrosshairRenderer.prepare: showX/showY must be boolean.');\n }\n if (typeof renderOptions.color !== 'string') {\n throw new Error('CrosshairRenderer.prepare: color must be a string.');\n }\n if (!Number.isFinite(renderOptions.lineWidth) || renderOptions.lineWidth < 0) {\n throw new Error('CrosshairRenderer.prepare: lineWidth must be a finite non-negative number.');\n }\n\n const { vertices, scissor } = generateCrosshairVertices(x, y, gridArea, renderOptions);\n if (vertices.byteLength === 0) {\n vertexCount = 0;\n } else {\n stream.write(vertices);\n vertexCount = stream.getVertexCount();\n }\n\n // Identity transform (vertices are already in clip-space).\n writeUniformBuffer(device, vsUniformBuffer, createIdentityMat4Buffer());\n\n // Color.\n const rgba = parseCssColorToRgba01(renderOptions.color) ?? DEFAULT_CROSSHAIR_RGBA;\n const colorBuffer = new ArrayBuffer(4 * 4);\n new Float32Array(colorBuffer).set([rgba[0], rgba[1], rgba[2], rgba[3]]);\n writeUniformBuffer(device, fsUniformBuffer, colorBuffer);\n\n lastCanvasWidth = gridArea.canvasWidth;\n lastCanvasHeight = gridArea.canvasHeight;\n lastScissor = scissor;\n };\n\n const render: CrosshairRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!visible) return;\n if (vertexCount === 0) return;\n if (lastCanvasWidth <= 0 || lastCanvasHeight <= 0) return;\n\n // Clip to plot area (device pixels).\n passEncoder.setScissorRect(lastScissor.x, lastScissor.y, lastScissor.w, lastScissor.h);\n\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.setVertexBuffer(0, stream.getBuffer());\n passEncoder.draw(vertexCount);\n\n // Reset scissor to full canvas (avoid affecting subsequent renderers).\n passEncoder.setScissorRect(0, 0, lastCanvasWidth, lastCanvasHeight);\n };\n\n const setVisible: CrosshairRenderer['setVisible'] = (v) => {\n assertNotDisposed();\n visible = Boolean(v);\n };\n\n const dispose: CrosshairRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n try {\n vsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n try {\n fsUniformBuffer.destroy();\n } catch {\n // best-effort\n }\n stream.dispose();\n\n vertexCount = 0;\n lastCanvasWidth = 0;\n lastCanvasHeight = 0;\n lastScissor = { x: 0, y: 0, w: 0, h: 0 };\n };\n\n return { prepare, render, setVisible, dispose };\n}\n\n","export default \"// highlight.wgsl\\n// Draws an anti-aliased ring highlight around a point.\\n//\\n// Contract:\\n// - `@builtin(position)` in the fragment stage is framebuffer-space pixels.\\n// - The renderer supplies `center` and ring sizes in *device pixels*.\\n\\nstruct Uniforms {\\n center: vec2<f32>,\\n radius: f32,\\n thickness: f32,\\n color: vec4<f32>,\\n outlineColor: vec4<f32>,\\n};\\n\\n@group(0) @binding(0) var<uniform> u: Uniforms;\\n\\nstruct VSOut {\\n @builtin(position) position: vec4<f32>,\\n};\\n\\n@vertex\\nfn vsMain(@builtin(vertex_index) vertexIndex: u32) -> VSOut {\\n // Fullscreen triangle.\\n // Covers clip-space [-1,1] with 3 verts: (-1,-1), (3,-1), (-1,3)\\n let positions = array<vec2<f32>, 3>(\\n vec2<f32>(-1.0, -1.0),\\n vec2<f32>(3.0, -1.0),\\n vec2<f32>(-1.0, 3.0)\\n );\\n\\n var out: VSOut;\\n out.position = vec4<f32>(positions[vertexIndex], 0.0, 1.0);\\n return out;\\n}\\n\\nfn ringCoverage(distancePx: f32, radiusPx: f32, thicknessPx: f32) -> f32 {\\n let aa = 1.0; // ~1px antialias band (device pixels)\\n let halfT = max(0.5, thicknessPx * 0.5);\\n let a0 = smoothstep(radiusPx - halfT - aa, radiusPx - halfT + aa, distancePx);\\n let a1 = smoothstep(radiusPx + halfT - aa, radiusPx + halfT + aa, distancePx);\\n return clamp(a0 - a1, 0.0, 1.0);\\n}\\n\\n@fragment\\nfn fsMain(@builtin(position) fragPos: vec4<f32>) -> @location(0) vec4<f32> {\\n let d = distance(fragPos.xy, u.center);\\n\\n let ring = ringCoverage(d, u.radius, u.thickness);\\n let outline = ringCoverage(d, u.radius, u.thickness + 2.0);\\n\\n let cover = max(ring, outline);\\n if (cover <= 0.0) {\\n discard;\\n }\\n\\n // Blend between outline and ring color based on relative coverage,\\n // then apply total coverage as alpha.\\n let t = clamp(select(0.0, ring / cover, cover > 0.0), 0.0, 1.0);\\n let rgb = mix(u.outlineColor.rgb, u.color.rgb, t);\\n let a = mix(u.outlineColor.a, u.color.a, t) * cover;\\n return vec4<f32>(rgb, a);\\n}\\n\\n\"","import highlightWgsl from '../shaders/highlight.wgsl?raw';\nimport { parseCssColorToRgba01 } from '../utils/colors';\nimport { createRenderPipeline, createUniformBuffer, writeUniformBuffer } from './rendererUtils';\n\nexport type HighlightPoint = Readonly<{\n /** Center in *device pixels* (same coordinate space as fragment `@builtin(position)`). */\n centerDeviceX: number;\n centerDeviceY: number;\n\n /** Canvas dimensions in *device pixels* (used to reset scissor). */\n canvasWidth: number;\n canvasHeight: number;\n\n /** Plot scissor rect in *device pixels*. */\n scissor: Readonly<{ x: number; y: number; w: number; h: number }>;\n}>;\n\nexport interface HighlightRenderer {\n /**\n * Prepares the highlight ring.\n *\n * Coordinate contract:\n * - `point.centerDeviceX/Y` are device pixels in the same space as fragment `@builtin(position)`.\n * - `size` is specified in CSS pixels; the renderer will scale it by DPR.\n */\n prepare(point: HighlightPoint, color: string, size: number): void;\n render(passEncoder: GPURenderPassEncoder): void;\n setVisible(visible: boolean): void;\n dispose(): void;\n}\n\nexport interface HighlightRendererOptions {\n /**\n * Must match the canvas context format used for the render pass color attachment.\n * Usually this is `gpuContext.preferredFormat`.\n *\n * Defaults to `'bgra8unorm'` for backward compatibility.\n */\n readonly targetFormat?: GPUTextureFormat;\n}\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_RGBA: readonly [number, number, number, number] = [1, 1, 1, 1];\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst clampInt = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v | 0));\n\nconst isFiniteScissor = (s: HighlightPoint['scissor']): boolean =>\n Number.isFinite(s.x) && Number.isFinite(s.y) && Number.isFinite(s.w) && Number.isFinite(s.h);\n\nconst brighten = (rgba: readonly [number, number, number, number], factor: number): readonly [number, number, number, number] => {\n const f = Number.isFinite(factor) ? factor : 1;\n return [clamp01(rgba[0] * f), clamp01(rgba[1] * f), clamp01(rgba[2] * f), clamp01(rgba[3])] as const;\n};\n\nconst luminance = (rgba: readonly [number, number, number, number]): number =>\n 0.2126 * rgba[0] + 0.7152 * rgba[1] + 0.0722 * rgba[2];\n\nexport function createHighlightRenderer(device: GPUDevice, options?: HighlightRendererOptions): HighlightRenderer {\n let disposed = false;\n let visible = true;\n\n const targetFormat = options?.targetFormat ?? DEFAULT_TARGET_FORMAT;\n\n const bindGroupLayout = device.createBindGroupLayout({\n entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } }],\n });\n\n // Uniform layout (WGSL):\n // center.xy, radius, thickness, color.rgba, outlineColor.rgba\n // = 12 floats = 48 bytes\n const uniformBuffer = createUniformBuffer(device, 48, { label: 'highlightRenderer/uniforms' });\n\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout,\n entries: [{ binding: 0, resource: { buffer: uniformBuffer } }],\n });\n\n const pipeline = createRenderPipeline(device, {\n label: 'highlightRenderer/pipeline',\n bindGroupLayouts: [bindGroupLayout],\n vertex: { code: highlightWgsl, label: 'highlight.wgsl' },\n fragment: {\n code: highlightWgsl,\n label: 'highlight.wgsl',\n formats: targetFormat,\n blend: {\n color: { operation: 'add', srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' },\n alpha: { operation: 'add', srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n primitive: { topology: 'triangle-list', cullMode: 'none' },\n multisample: { count: 1 },\n });\n\n let lastCanvasWidth = 0;\n let lastCanvasHeight = 0;\n let lastScissor = { x: 0, y: 0, w: 0, h: 0 };\n let hasPrepared = false;\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('HighlightRenderer is disposed.');\n };\n\n const prepare: HighlightRenderer['prepare'] = (point, cssColor, sizeCssPx) => {\n assertNotDisposed();\n\n if (!Number.isFinite(point.centerDeviceX) || !Number.isFinite(point.centerDeviceY)) {\n throw new Error('HighlightRenderer.prepare: point center must be finite.');\n }\n if (!Number.isFinite(point.canvasWidth) || !Number.isFinite(point.canvasHeight) || point.canvasWidth <= 0 || point.canvasHeight <= 0) {\n throw new Error('HighlightRenderer.prepare: canvasWidth/canvasHeight must be positive finite numbers.');\n }\n if (!isFiniteScissor(point.scissor)) {\n throw new Error('HighlightRenderer.prepare: scissor must be finite.');\n }\n if (!Number.isFinite(sizeCssPx) || sizeCssPx < 0) {\n throw new Error('HighlightRenderer.prepare: size must be a finite non-negative number.');\n }\n\n const dpr = window.devicePixelRatio || 1;\n const baseRadiusDevicePx = sizeCssPx * dpr;\n\n // Slightly larger than the implied \"normal\" point size.\n const radius = Math.max(1, baseRadiusDevicePx * 1.5);\n const thickness = Math.max(1, Math.round(Math.max(2, radius * 0.25)));\n\n const seriesRgba = parseCssColorToRgba01(cssColor) ?? DEFAULT_RGBA;\n const ringRgba = brighten(seriesRgba, 1.25);\n const useDarkOutline = luminance(seriesRgba) > 0.7;\n const outlineRgba: readonly [number, number, number, number] = useDarkOutline ? [0, 0, 0, 0.9] : [1, 1, 1, 0.9];\n\n const buf = new ArrayBuffer(12 * 4);\n new Float32Array(buf).set([\n point.centerDeviceX,\n point.centerDeviceY,\n radius,\n thickness,\n ringRgba[0],\n ringRgba[1],\n ringRgba[2],\n 1.0,\n outlineRgba[0],\n outlineRgba[1],\n outlineRgba[2],\n outlineRgba[3],\n ]);\n writeUniformBuffer(device, uniformBuffer, buf);\n\n lastCanvasWidth = point.canvasWidth;\n lastCanvasHeight = point.canvasHeight;\n\n // Clamp scissor to valid canvas bounds (defensive).\n const x0 = clampInt(Math.floor(point.scissor.x), 0, Math.max(0, point.canvasWidth));\n const y0 = clampInt(Math.floor(point.scissor.y), 0, Math.max(0, point.canvasHeight));\n const x1 = clampInt(Math.ceil(point.scissor.x + point.scissor.w), 0, Math.max(0, point.canvasWidth));\n const y1 = clampInt(Math.ceil(point.scissor.y + point.scissor.h), 0, Math.max(0, point.canvasHeight));\n lastScissor = { x: x0, y: y0, w: Math.max(0, x1 - x0), h: Math.max(0, y1 - y0) };\n\n hasPrepared = true;\n };\n\n const render: HighlightRenderer['render'] = (passEncoder) => {\n assertNotDisposed();\n if (!visible) return;\n if (!hasPrepared) return;\n if (lastCanvasWidth <= 0 || lastCanvasHeight <= 0) return;\n if (lastScissor.w === 0 || lastScissor.h === 0) return;\n\n passEncoder.setScissorRect(lastScissor.x, lastScissor.y, lastScissor.w, lastScissor.h);\n passEncoder.setPipeline(pipeline);\n passEncoder.setBindGroup(0, bindGroup);\n passEncoder.draw(3);\n passEncoder.setScissorRect(0, 0, lastCanvasWidth, lastCanvasHeight);\n };\n\n const setVisible: HighlightRenderer['setVisible'] = (v) => {\n assertNotDisposed();\n visible = Boolean(v);\n };\n\n const dispose: HighlightRenderer['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n try {\n uniformBuffer.destroy();\n } catch {\n // best-effort\n }\n\n lastCanvasWidth = 0;\n lastCanvasHeight = 0;\n lastScissor = { x: 0, y: 0, w: 0, h: 0 };\n hasPrepared = false;\n };\n\n return { prepare, render, setVisible, dispose };\n}\n\n","import type { GridArea } from '../renderers/createGridRenderer';\n\nexport type ChartGPUEventName = 'mousemove' | 'click' | 'mouseleave';\n\nexport type ChartGPUEventPayload = {\n readonly x: number;\n readonly y: number;\n readonly gridX: number;\n readonly gridY: number;\n /** Plot (grid) width in CSS pixels. */\n readonly plotWidthCss: number;\n /** Plot (grid) height in CSS pixels. */\n readonly plotHeightCss: number;\n readonly isInGrid: boolean;\n readonly originalEvent: PointerEvent;\n};\n\nexport type ChartGPUEventCallback = (payload: ChartGPUEventPayload) => void;\n\nexport interface EventManager {\n readonly canvas: HTMLCanvasElement;\n on(event: ChartGPUEventName, callback: ChartGPUEventCallback): void;\n off(event: ChartGPUEventName, callback: ChartGPUEventCallback): void;\n updateGridArea(gridArea: GridArea): void;\n dispose(): void;\n}\n\ntype ListenerRegistry = Readonly<Record<ChartGPUEventName, Set<ChartGPUEventCallback>>>;\n\ntype TapCandidate = {\n readonly pointerId: number;\n readonly startClientX: number;\n readonly startClientY: number;\n readonly startTimeMs: number;\n};\n\nconst DEFAULT_TAP_MAX_DISTANCE_CSS_PX = 6;\nconst DEFAULT_TAP_MAX_TIME_MS = 500;\n\nexport function createEventManager(canvas: HTMLCanvasElement, initialGridArea: GridArea): EventManager {\n let disposed = false;\n let gridArea = initialGridArea;\n\n const listeners: ListenerRegistry = {\n mousemove: new Set<ChartGPUEventCallback>(),\n click: new Set<ChartGPUEventCallback>(),\n mouseleave: new Set<ChartGPUEventCallback>(),\n };\n\n let tapCandidate: TapCandidate | null = null;\n let suppressNextLostPointerCaptureId: number | null = null;\n\n const toPayload = (e: PointerEvent): ChartGPUEventPayload | null => {\n const rect = canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return null;\n\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n const plotLeftCss = gridArea.left;\n const plotTopCss = gridArea.top;\n const plotWidthCss = rect.width - gridArea.left - gridArea.right;\n const plotHeightCss = rect.height - gridArea.top - gridArea.bottom;\n\n const gridX = x - plotLeftCss;\n const gridY = y - plotTopCss;\n\n const isInGrid =\n gridX >= 0 &&\n gridX <= plotWidthCss &&\n gridY >= 0 &&\n gridY <= plotHeightCss;\n\n return { x, y, gridX, gridY, plotWidthCss, plotHeightCss, isInGrid, originalEvent: e };\n };\n\n const emit = (eventName: ChartGPUEventName, e: PointerEvent): void => {\n const payload = toPayload(e);\n if (!payload) return;\n\n for (const cb of listeners[eventName]) cb(payload);\n };\n\n const clearTapCandidateIfMatches = (e: PointerEvent): void => {\n if (!tapCandidate) return;\n if (!e.isPrimary) return;\n if (e.pointerId !== tapCandidate.pointerId) return;\n tapCandidate = null;\n };\n\n const onPointerMove = (e: PointerEvent): void => {\n if (disposed) return;\n emit('mousemove', e);\n };\n\n const onPointerLeave = (e: PointerEvent): void => {\n if (disposed) return;\n clearTapCandidateIfMatches(e);\n emit('mouseleave', e);\n };\n\n const onPointerCancel = (e: PointerEvent): void => {\n if (disposed) return;\n clearTapCandidateIfMatches(e);\n emit('mouseleave', e);\n };\n\n const onLostPointerCapture = (e: PointerEvent): void => {\n if (disposed) return;\n if (suppressNextLostPointerCaptureId === e.pointerId) {\n suppressNextLostPointerCaptureId = null;\n return;\n }\n clearTapCandidateIfMatches(e);\n emit('mouseleave', e);\n };\n\n const onPointerDown = (e: PointerEvent): void => {\n if (disposed) return;\n if (!e.isPrimary) return;\n\n // For mouse, only allow left button.\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n\n // If canvas has no size, treat as non-interactive (and avoid tap tracking).\n const rect = canvas.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) return;\n\n tapCandidate = {\n pointerId: e.pointerId,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startTimeMs: e.timeStamp,\n };\n\n // Optional pointer capture improves reliability for touch/pen.\n try {\n canvas.setPointerCapture(e.pointerId);\n } catch {\n // best-effort\n }\n };\n\n const onPointerUp = (e: PointerEvent): void => {\n if (disposed) return;\n if (!e.isPrimary) return;\n if (!tapCandidate || e.pointerId !== tapCandidate.pointerId) return;\n\n const dt = e.timeStamp - tapCandidate.startTimeMs;\n const dx = e.clientX - tapCandidate.startClientX;\n const dy = e.clientY - tapCandidate.startClientY;\n const distSq = dx * dx + dy * dy;\n\n tapCandidate = null;\n\n // Release capture if we have it; suppress the resulting lostpointercapture.\n try {\n if (canvas.hasPointerCapture(e.pointerId)) {\n suppressNextLostPointerCaptureId = e.pointerId;\n canvas.releasePointerCapture(e.pointerId);\n }\n } catch {\n // best-effort\n }\n\n const maxDist = DEFAULT_TAP_MAX_DISTANCE_CSS_PX;\n const isTap =\n dt <= DEFAULT_TAP_MAX_TIME_MS && distSq <= maxDist * maxDist;\n\n if (isTap) emit('click', e);\n };\n\n canvas.addEventListener('pointermove', onPointerMove, { passive: true });\n canvas.addEventListener('pointerleave', onPointerLeave, { passive: true });\n canvas.addEventListener('pointercancel', onPointerCancel, { passive: true });\n canvas.addEventListener('lostpointercapture', onLostPointerCapture, { passive: true });\n canvas.addEventListener('pointerdown', onPointerDown, { passive: true });\n canvas.addEventListener('pointerup', onPointerUp, { passive: true });\n\n const on: EventManager['on'] = (event, callback) => {\n if (disposed) return;\n listeners[event].add(callback);\n };\n\n const off: EventManager['off'] = (event, callback) => {\n listeners[event].delete(callback);\n };\n\n const updateGridArea: EventManager['updateGridArea'] = (nextGridArea) => {\n gridArea = nextGridArea;\n };\n\n const dispose: EventManager['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n tapCandidate = null;\n suppressNextLostPointerCaptureId = null;\n\n canvas.removeEventListener('pointermove', onPointerMove);\n canvas.removeEventListener('pointerleave', onPointerLeave);\n canvas.removeEventListener('pointercancel', onPointerCancel);\n canvas.removeEventListener('lostpointercapture', onLostPointerCapture);\n canvas.removeEventListener('pointerdown', onPointerDown);\n canvas.removeEventListener('pointerup', onPointerUp);\n\n listeners.mousemove.clear();\n listeners.click.clear();\n listeners.mouseleave.clear();\n };\n\n return { canvas, on, off, updateGridArea, dispose };\n}\n","import type { EventManager, ChartGPUEventPayload } from './createEventManager';\nimport type { ZoomState } from './createZoomState';\n\nexport type InsideZoom = Readonly<{\n enable(): void;\n disable(): void;\n dispose(): void;\n}>;\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v));\n\nconst normalizeWheelDelta = (e: WheelEvent, basisCssPx: number): number => {\n const raw = e.deltaY;\n if (!Number.isFinite(raw) || raw === 0) return 0;\n\n // Normalize to CSS pixels-ish so sensitivity is stable across deltaMode.\n switch (e.deltaMode) {\n case WheelEvent.DOM_DELTA_PIXEL:\n return raw;\n case WheelEvent.DOM_DELTA_LINE:\n return raw * 16;\n case WheelEvent.DOM_DELTA_PAGE:\n return raw * (Number.isFinite(basisCssPx) && basisCssPx > 0 ? basisCssPx : 800);\n default:\n return raw;\n }\n};\n\nconst wheelDeltaToZoomFactor = (deltaCssPx: number): number => {\n // Positive delta = scroll down = zoom out; negative = zoom in.\n const abs = Math.abs(deltaCssPx);\n if (!Number.isFinite(abs) || abs === 0) return 1;\n\n // Cap extreme deltas (some devices can emit huge values).\n const capped = Math.min(abs, 200);\n const sensitivity = 0.002;\n return Math.exp(capped * sensitivity);\n};\n\nconst isMiddleButtonDrag = (e: PointerEvent): boolean =>\n e.pointerType === 'mouse' && (e.buttons & 4) !== 0;\n\nconst isShiftLeftDrag = (e: PointerEvent): boolean =>\n e.pointerType === 'mouse' && e.shiftKey && (e.buttons & 1) !== 0;\n\n/**\n * Internal “inside” zoom interaction:\n * - wheel zoom centered at cursor-x (only when inside grid)\n * - shift+left drag OR middle-mouse drag pans left/right (only when inside grid)\n */\nexport function createInsideZoom(eventManager: EventManager, zoomState: ZoomState): InsideZoom {\n let disposed = false;\n let enabled = false;\n\n let lastPointer: ChartGPUEventPayload | null = null;\n let isPanning = false;\n let lastPanGridX = 0;\n\n const clearPan = (): void => {\n isPanning = false;\n lastPanGridX = 0;\n };\n\n const onMouseMove = (payload: ChartGPUEventPayload): void => {\n lastPointer = payload;\n if (!enabled) return;\n\n // Pan only for mouse drags, only when inside grid.\n const e = payload.originalEvent;\n const shouldPan = payload.isInGrid && (isShiftLeftDrag(e) || isMiddleButtonDrag(e));\n\n if (!shouldPan) {\n clearPan();\n return;\n }\n\n const plotWidthCss = payload.plotWidthCss;\n if (!(plotWidthCss > 0) || !Number.isFinite(plotWidthCss)) {\n clearPan();\n return;\n }\n\n if (!isPanning) {\n isPanning = true;\n lastPanGridX = payload.gridX;\n return;\n }\n\n const dxCss = payload.gridX - lastPanGridX;\n lastPanGridX = payload.gridX;\n if (!Number.isFinite(dxCss) || dxCss === 0) return;\n\n const { start, end } = zoomState.getRange();\n const span = end - start;\n if (!Number.isFinite(span) || span === 0) return;\n\n // Convert grid-local px to percent points *within the current window*.\n // “Grab to pan” behavior: dragging right should move the window left (show earlier data).\n const deltaPct = -(dxCss / plotWidthCss) * span;\n if (!Number.isFinite(deltaPct) || deltaPct === 0) return;\n zoomState.pan(deltaPct);\n };\n\n const onMouseLeave = (_payload: ChartGPUEventPayload): void => {\n lastPointer = null;\n clearPan();\n };\n\n const onWheel = (e: WheelEvent): void => {\n if (!enabled || disposed) return;\n\n const p = lastPointer;\n if (!p || !p.isInGrid) return;\n\n const plotWidthCss = p.plotWidthCss;\n const plotHeightCss = p.plotHeightCss;\n if (!(plotWidthCss > 0) || !(plotHeightCss > 0)) return;\n\n const deltaCss = normalizeWheelDelta(e, plotHeightCss);\n if (deltaCss === 0) return;\n\n const factor = wheelDeltaToZoomFactor(deltaCss);\n if (!(factor > 1)) return;\n\n const { start, end } = zoomState.getRange();\n const span = end - start;\n if (!Number.isFinite(span) || span === 0) return;\n const r = clamp(p.gridX / plotWidthCss, 0, 1);\n const centerPct = clamp(start + r * span, 0, 100);\n\n // Only prevent default when we are actually consuming the wheel to zoom.\n e.preventDefault();\n\n if (deltaCss < 0) zoomState.zoomIn(centerPct, factor);\n else zoomState.zoomOut(centerPct, factor);\n };\n\n const enable: InsideZoom['enable'] = () => {\n if (disposed || enabled) return;\n enabled = true;\n eventManager.on('mousemove', onMouseMove);\n eventManager.on('mouseleave', onMouseLeave);\n eventManager.canvas.addEventListener('wheel', onWheel, { passive: false });\n };\n\n const disable: InsideZoom['disable'] = () => {\n if (disposed || !enabled) return;\n enabled = false;\n eventManager.off('mousemove', onMouseMove);\n eventManager.off('mouseleave', onMouseLeave);\n eventManager.canvas.removeEventListener('wheel', onWheel);\n lastPointer = null;\n clearPan();\n };\n\n const dispose: InsideZoom['dispose'] = () => {\n if (disposed) return;\n disable();\n disposed = true;\n };\n\n return { enable, disable, dispose };\n}\n\n","export type ZoomRange = Readonly<{ start: number; end: number }>;\n\nexport type ZoomRangeChangeCallback = (range: ZoomRange) => void;\n\nexport interface ZoomState {\n /**\n * Returns the current zoom window in percent space, clamped to [0, 100].\n */\n getRange(): ZoomRange;\n /**\n * Sets the zoom window in percent space.\n */\n setRange(start: number, end: number): void;\n /**\n * Zooms in around `center` by shrinking the span by `factor`.\n *\n * `factor <= 1` is treated as a no-op.\n */\n zoomIn(center: number, factor: number): void;\n /**\n * Zooms out around `center` by growing the span by `factor`.\n *\n * `factor <= 1` is treated as a no-op.\n */\n zoomOut(center: number, factor: number): void;\n /**\n * Pans the zoom window by `delta` percent points (preserving span).\n */\n pan(delta: number): void;\n /**\n * Subscribes to changes. Returns an unsubscribe function.\n */\n onChange(callback: ZoomRangeChangeCallback): () => void;\n}\n\nconst DEFAULT_MIN_SPAN = 0;\nconst DEFAULT_MAX_SPAN = 100;\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v));\nconst clamp01 = (v: number): number => clamp(v, 0, 1);\n\nconst normalizeZero = (v: number): number => (Object.is(v, -0) ? 0 : v);\n\nconst copyRange = (r: ZoomRange): ZoomRange => ({ start: r.start, end: r.end });\n\nexport function createZoomState(initialStart: number, initialEnd: number): ZoomState {\n let start = 0;\n let end = 100;\n let lastEmitted: ZoomRange | null = null;\n\n const listeners = new Set<ZoomRangeChangeCallback>();\n\n const minSpan = (() => {\n const v = Number.isFinite(DEFAULT_MIN_SPAN) ? DEFAULT_MIN_SPAN : 0;\n return clamp(v, 0, 100);\n })();\n\n const maxSpan = (() => {\n const v = Number.isFinite(DEFAULT_MAX_SPAN) ? DEFAULT_MAX_SPAN : 100;\n return clamp(v, 0, 100);\n })();\n\n const normalizedMinSpan = Math.min(minSpan, maxSpan);\n const normalizedMaxSpan = Math.max(minSpan, maxSpan);\n\n const emit = (): void => {\n const next: ZoomRange = { start, end };\n if (\n lastEmitted !== null &&\n lastEmitted.start === next.start &&\n lastEmitted.end === next.end\n ) {\n return;\n }\n\n lastEmitted = copyRange(next);\n\n // Emit to a snapshot so additions/removals during emit don't affect this flush.\n const snapshot = Array.from(listeners);\n for (const cb of snapshot) cb({ start, end });\n };\n\n const applyNextRange = (\n nextStart: number,\n nextEnd: number,\n options?: { readonly emit?: boolean; readonly anchor?: { readonly center: number; readonly ratio: number } },\n ): void => {\n if (!Number.isFinite(nextStart) || !Number.isFinite(nextEnd)) return;\n\n let s = nextStart;\n let e = nextEnd;\n\n if (s > e) {\n const t = s;\n s = e;\n e = t;\n }\n\n // Enforce span constraints by resizing around the proposed midpoint.\n let span = e - s;\n if (!Number.isFinite(span) || span < 0) return;\n\n const targetSpan = clamp(span, normalizedMinSpan, normalizedMaxSpan);\n if (targetSpan !== span) {\n const anchorCenter =\n options?.anchor && Number.isFinite(options.anchor.center)\n ? clamp(options.anchor.center, 0, 100)\n : (s + e) * 0.5;\n const anchorRatio =\n options?.anchor && Number.isFinite(options.anchor.ratio)\n ? clamp01(options.anchor.ratio)\n : 0.5;\n\n // Resize around the anchor so zoom operations preserve the cursor location.\n s = anchorCenter - anchorRatio * targetSpan;\n e = s + targetSpan;\n span = targetSpan;\n }\n\n // If span exceeds bounds (shouldn't happen with normalizedMaxSpan <= 100), clamp to full extent.\n if (span > 100) {\n s = 0;\n e = 100;\n span = 100;\n }\n\n // Shift into bounds without changing span.\n if (s < 0) {\n const shift = -s;\n s += shift;\n e += shift;\n }\n if (e > 100) {\n const shift = e - 100;\n s -= shift;\n e -= shift;\n }\n\n // Final clamp for tiny floating point drift.\n s = clamp(s, 0, 100);\n e = clamp(e, 0, 100);\n\n s = normalizeZero(s);\n e = normalizeZero(e);\n\n if (s === start && e === end) return;\n start = s;\n end = e;\n\n if (options?.emit === false) return;\n emit();\n };\n\n // Initialize state (no emit by default).\n applyNextRange(initialStart, initialEnd, { emit: false });\n\n const getRange: ZoomState['getRange'] = () => ({ start, end });\n\n const setRange: ZoomState['setRange'] = (nextStart, nextEnd) => {\n applyNextRange(nextStart, nextEnd);\n };\n\n const zoomIn: ZoomState['zoomIn'] = (center, factor) => {\n if (!Number.isFinite(center) || !Number.isFinite(factor)) return;\n if (factor <= 1) return;\n\n const c = clamp(center, 0, 100);\n const span = end - start;\n const r = span === 0 ? 0.5 : clamp01((c - start) / span);\n const nextSpan = span / factor;\n const nextStart = c - r * nextSpan;\n const nextEnd = nextStart + nextSpan;\n applyNextRange(nextStart, nextEnd, { anchor: { center: c, ratio: r } });\n };\n\n const zoomOut: ZoomState['zoomOut'] = (center, factor) => {\n if (!Number.isFinite(center) || !Number.isFinite(factor)) return;\n if (factor <= 1) return;\n\n const c = clamp(center, 0, 100);\n const span = end - start;\n const r = span === 0 ? 0.5 : clamp01((c - start) / span);\n const nextSpan = span * factor;\n const nextStart = c - r * nextSpan;\n const nextEnd = nextStart + nextSpan;\n applyNextRange(nextStart, nextEnd, { anchor: { center: c, ratio: r } });\n };\n\n const pan: ZoomState['pan'] = (delta) => {\n if (!Number.isFinite(delta)) return;\n applyNextRange(start + delta, end + delta);\n };\n\n const onChange: ZoomState['onChange'] = (callback) => {\n listeners.add(callback);\n return () => {\n listeners.delete(callback);\n };\n };\n\n return { getRange, setRange, zoomIn, zoomOut, pan, onChange };\n}\n\n","import type { DataPoint, DataPointTuple, ScatterPointTuple } from '../config/types';\nimport type {\n ResolvedBarSeriesConfig,\n ResolvedScatterSeriesConfig,\n ResolvedSeriesConfig,\n} from '../config/OptionResolver';\nimport type { LinearScale } from '../utils/scales';\n\nconst DEFAULT_MAX_DISTANCE_PX = 20;\nconst DEFAULT_BAR_GAP = 0.1;\nconst DEFAULT_BAR_CATEGORY_GAP = 0.2;\nconst DEFAULT_SCATTER_RADIUS_CSS_PX = 4;\n\n// Cache (Story 4.10): used only for scatter-series pruning so we don't degrade to O(n)\n// scans per pointer move when no candidate has been found yet.\nconst scatterMaxRadiusCache = new WeakMap<ResolvedScatterSeriesConfig, number>();\n\nexport type NearestPointMatch = Readonly<{\n seriesIndex: number;\n dataIndex: number;\n point: DataPoint;\n /** Euclidean distance in range units. */\n distance: number;\n}>;\n\ntype TuplePoint = DataPointTuple;\ntype ObjectPoint = Readonly<{ x: number; y: number; size?: number }>;\n\nexport type BarBounds = { left: number; right: number; top: number; bottom: number };\n\nexport function isPointInBar(x: number, y: number, barBounds: BarBounds): boolean {\n // Inclusive bounds.\n // Note: stacked bar segments can share edges; tie-breaking is handled by the caller.\n return (\n x >= barBounds.left &&\n x <= barBounds.right &&\n y >= barBounds.top &&\n y <= barBounds.bottom\n );\n}\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\n\nconst parsePercent = (value: string): number | null => {\n const m = value.trim().match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (!m) return null;\n const p = Number(m[1]) / 100;\n return Number.isFinite(p) ? p : null;\n};\n\nconst normalizeStackId = (stack: unknown): string => {\n if (typeof stack !== 'string') return '';\n const trimmed = stack.trim();\n return trimmed.length > 0 ? trimmed : '';\n};\n\nconst isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p);\n\nconst getPointXY = (p: DataPoint): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(p)) return { x: p[0], y: p[1] };\n return { x: p.x, y: p.y };\n};\n\nconst getPointSizeCssPx = (p: DataPoint): number | null => {\n if (isTupleDataPoint(p)) {\n const s = p[2];\n return typeof s === 'number' && Number.isFinite(s) ? s : null;\n }\n const s = p.size;\n return typeof s === 'number' && Number.isFinite(s) ? s : null;\n};\n\nconst toScatterTuple = (p: DataPoint): ScatterPointTuple => {\n if (isTupleDataPoint(p)) return p;\n return [p.x, p.y, p.size] as const;\n};\n\nconst safeCallSymbolSize = (\n fn: (value: ScatterPointTuple) => number,\n value: ScatterPointTuple,\n): number | null => {\n try {\n const v = fn(value);\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n } catch {\n return null;\n }\n};\n\nconst getScatterRadiusCssPx = (seriesCfg: ResolvedScatterSeriesConfig, p: DataPoint): number => {\n // Mirrors `createScatterRenderer.ts` size semantics (but stays in CSS px):\n // point.size -> series.symbolSize -> default 4px.\n const perPoint = getPointSizeCssPx(p);\n if (perPoint != null) return Math.max(0, perPoint);\n\n const seriesSymbolSize = seriesCfg.symbolSize;\n if (typeof seriesSymbolSize === 'number') {\n return Number.isFinite(seriesSymbolSize)\n ? Math.max(0, seriesSymbolSize)\n : DEFAULT_SCATTER_RADIUS_CSS_PX;\n }\n if (typeof seriesSymbolSize === 'function') {\n const v = safeCallSymbolSize(seriesSymbolSize, toScatterTuple(p));\n return v == null ? DEFAULT_SCATTER_RADIUS_CSS_PX : Math.max(0, v);\n }\n\n return DEFAULT_SCATTER_RADIUS_CSS_PX;\n};\n\nconst getMaxScatterRadiusCssPx = (seriesCfg: ResolvedScatterSeriesConfig): number => {\n const cached = scatterMaxRadiusCache.get(seriesCfg);\n if (cached !== undefined) return cached;\n\n const data = seriesCfg.data;\n const seriesSymbolSize = seriesCfg.symbolSize;\n\n let maxRadius = 0;\n\n // Fast path: numeric (or missing) series size means max is just max(point.size, series/default).\n if (typeof seriesSymbolSize !== 'function') {\n const seriesFallback =\n typeof seriesSymbolSize === 'number' && Number.isFinite(seriesSymbolSize)\n ? Math.max(0, seriesSymbolSize)\n : DEFAULT_SCATTER_RADIUS_CSS_PX;\n\n let maxPerPoint = 0;\n let anyPointWithoutSize = false;\n for (let i = 0; i < data.length; i++) {\n const pSize = getPointSizeCssPx(data[i]);\n if (pSize == null) {\n anyPointWithoutSize = true;\n } else {\n const r = Math.max(0, pSize);\n if (r > maxPerPoint) maxPerPoint = r;\n }\n }\n maxRadius = anyPointWithoutSize ? Math.max(maxPerPoint, seriesFallback) : maxPerPoint;\n } else {\n // Slow path: symbolSize function can vary per point, so compute true max once and cache it.\n for (let i = 0; i < data.length; i++) {\n const r = getScatterRadiusCssPx(seriesCfg, data[i]);\n if (r > maxRadius) maxRadius = r;\n }\n }\n\n maxRadius = Number.isFinite(maxRadius) ? Math.max(0, maxRadius) : DEFAULT_SCATTER_RADIUS_CSS_PX;\n scatterMaxRadiusCache.set(seriesCfg, maxRadius);\n return maxRadius;\n};\n\n// Note: we intentionally do NOT compute “nearest bar by distance”.\n// Bars are only considered a match when the cursor is inside their rect bounds.\n\nexport type BarClusterSlots = Readonly<{\n clusterIndexBySeries: ReadonlyArray<number>;\n clusterCount: number;\n stackIdBySeries: ReadonlyArray<string>;\n}>;\n\nexport function computeBarClusterSlots(\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n): BarClusterSlots {\n // Cluster slots (mirrors `createBarRenderer.ts`):\n // - Each unique non-empty stackId gets a single cluster slot.\n // - Each unstacked series gets its own cluster slot.\n const stackIdToClusterIndex = new Map<string, number>();\n const clusterIndexBySeries: number[] = new Array(seriesConfigs.length);\n const stackIdBySeries: string[] = new Array(seriesConfigs.length);\n\n let clusterCount = 0;\n for (let i = 0; i < seriesConfigs.length; i++) {\n const stackId = normalizeStackId(seriesConfigs[i].stack);\n stackIdBySeries[i] = stackId;\n\n if (stackId !== '') {\n const existing = stackIdToClusterIndex.get(stackId);\n if (existing !== undefined) {\n clusterIndexBySeries[i] = existing;\n } else {\n const idx = clusterCount++;\n stackIdToClusterIndex.set(stackId, idx);\n clusterIndexBySeries[i] = idx;\n }\n } else {\n clusterIndexBySeries[i] = clusterCount++;\n }\n }\n\n return {\n clusterIndexBySeries,\n clusterCount: Math.max(1, clusterCount),\n stackIdBySeries,\n };\n}\n\nexport function computeBarCategoryStep(seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>): number {\n const xs: number[] = [];\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s].data;\n for (let i = 0; i < data.length; i++) {\n const { x } = getPointXY(data[i]);\n if (Number.isFinite(x)) xs.push(x);\n }\n }\n\n if (xs.length < 2) return 1;\n xs.sort((a, b) => a - b);\n\n let minStep = Number.POSITIVE_INFINITY;\n for (let i = 1; i < xs.length; i++) {\n const d = xs[i] - xs[i - 1];\n if (d > 0 && d < minStep) minStep = d;\n }\n return Number.isFinite(minStep) && minStep > 0 ? minStep : 1;\n}\n\nexport function computeCategoryWidthPx(\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n xScale: LinearScale,\n categoryStep: number,\n): number {\n // Primary path (mirrors renderer): derive width from domain step via scale().\n if (Number.isFinite(categoryStep) && categoryStep > 0) {\n const x0 = 0;\n const p0 = xScale.scale(x0);\n const p1 = xScale.scale(x0 + categoryStep);\n const w = Math.abs(p1 - p0);\n if (Number.isFinite(w) && w > 0) return w;\n }\n\n // Fallback: compute min positive delta in *scaled* x positions.\n const sx: number[] = [];\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s].data;\n for (let i = 0; i < data.length; i++) {\n const { x } = getPointXY(data[i]);\n if (!Number.isFinite(x)) continue;\n const px = xScale.scale(x);\n if (Number.isFinite(px)) sx.push(px);\n }\n }\n if (sx.length < 2) return 0;\n sx.sort((a, b) => a - b);\n\n let minDx = Number.POSITIVE_INFINITY;\n for (let i = 1; i < sx.length; i++) {\n const d = sx[i] - sx[i - 1];\n if (d > 0 && d < minDx) minDx = d;\n }\n\n return Number.isFinite(minDx) && minDx > 0 ? minDx : 0;\n}\n\ntype BarSharedLayout = Readonly<{\n barWidth?: number | string;\n barGap?: number;\n barCategoryGap?: number;\n}>;\n\nconst computeSharedBarLayout = (\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n): BarSharedLayout => {\n let barWidth: number | string | undefined = undefined;\n let barGap: number | undefined = undefined;\n let barCategoryGap: number | undefined = undefined;\n\n for (let i = 0; i < seriesConfigs.length; i++) {\n const s = seriesConfigs[i];\n if (barWidth === undefined && s.barWidth !== undefined) barWidth = s.barWidth;\n if (barGap === undefined && s.barGap !== undefined) barGap = s.barGap;\n if (barCategoryGap === undefined && s.barCategoryGap !== undefined) barCategoryGap = s.barCategoryGap;\n }\n\n return { barWidth, barGap, barCategoryGap };\n};\n\nexport type BarLayoutPx = Readonly<{\n categoryStep: number;\n categoryWidthPx: number;\n barWidthPx: number;\n gapPx: number;\n clusterWidthPx: number;\n clusterSlots: BarClusterSlots;\n}>;\n\nexport function computeBarLayoutPx(\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n xScale: LinearScale,\n): BarLayoutPx {\n const clusterSlots = computeBarClusterSlots(seriesConfigs);\n const clusterCount = clusterSlots.clusterCount;\n\n const categoryStep = computeBarCategoryStep(seriesConfigs);\n const categoryWidthPx = computeCategoryWidthPx(seriesConfigs, xScale, categoryStep);\n\n const layout = computeSharedBarLayout(seriesConfigs);\n const barGap = clamp01(layout.barGap ?? DEFAULT_BAR_GAP);\n const barCategoryGap = clamp01(layout.barCategoryGap ?? DEFAULT_BAR_CATEGORY_GAP);\n\n const categoryInnerWidthPx = Math.max(0, categoryWidthPx * (1 - barCategoryGap));\n\n let barWidthPx = 0;\n const rawBarWidth = layout.barWidth;\n if (typeof rawBarWidth === 'number') {\n barWidthPx = Math.max(0, rawBarWidth);\n } else if (typeof rawBarWidth === 'string') {\n const p = parsePercent(rawBarWidth);\n barWidthPx = p == null ? 0 : categoryInnerWidthPx * clamp01(p);\n }\n\n if (!(barWidthPx > 0)) {\n const denom = clusterCount + Math.max(0, clusterCount - 1) * barGap;\n barWidthPx = denom > 0 ? categoryInnerWidthPx / denom : 0;\n }\n\n barWidthPx = Math.min(barWidthPx, categoryInnerWidthPx);\n const gapPx = barWidthPx * barGap;\n const clusterWidthPx = clusterCount * barWidthPx + Math.max(0, clusterCount - 1) * gapPx;\n\n return {\n categoryStep,\n categoryWidthPx,\n barWidthPx,\n gapPx,\n clusterWidthPx,\n clusterSlots,\n };\n}\n\nconst computeBaselineForBarsFromData = (seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>): number => {\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s].data;\n for (let i = 0; i < data.length; i++) {\n const { y } = getPointXY(data[i]);\n if (!Number.isFinite(y)) continue;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n }\n\n if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) return 0;\n if (yMin <= 0 && 0 <= yMax) return 0;\n return Math.abs(yMin) < Math.abs(yMax) ? yMin : yMax;\n};\n\nexport function inferPlotHeightPxForBarHitTesting(\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n yScale: LinearScale,\n): number {\n // We don't have direct access to the scale range endpoints, so infer the plot height in range-space.\n // In the common ChartGPU interaction setup, yScale.range(plotHeightCss, 0), so max(scaledY) should\n // approximate plotHeightCss (or be <= plotHeightCss if axis min/max are overridden).\n let maxY = 0;\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s].data;\n for (let i = 0; i < data.length; i++) {\n const { y } = getPointXY(data[i]);\n if (!Number.isFinite(y)) continue;\n const py = yScale.scale(y);\n if (Number.isFinite(py) && py > maxY) maxY = py;\n }\n }\n return Math.max(0, maxY);\n}\n\nexport function computeBaselineDomainAndPx(\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n yScale: LinearScale,\n plotHeightPx: number,\n): Readonly<{ baselineDomain: number; baselinePx: number }> {\n // Axis-aware baseline logic (mirrors `createBarRenderer.ts`, but in px-space):\n // Determine visible y-domain from yScale via invert(bottom/top) where top=0 and bottom=plotHeightPx.\n const yDomainA = yScale.invert(plotHeightPx);\n const yDomainB = yScale.invert(0);\n const yMin = Math.min(yDomainA, yDomainB);\n const yMax = Math.max(yDomainA, yDomainB);\n\n let baselineDomain: number;\n if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n baselineDomain = computeBaselineForBarsFromData(seriesConfigs);\n } else if (yMin <= 0 && 0 <= yMax) {\n baselineDomain = 0;\n } else if (yMin > 0) {\n baselineDomain = yMin;\n } else if (yMax < 0) {\n baselineDomain = yMax;\n } else {\n baselineDomain = computeBaselineForBarsFromData(seriesConfigs);\n }\n\n let baselinePx = yScale.scale(baselineDomain);\n if (!Number.isFinite(baselinePx)) {\n baselineDomain = computeBaselineForBarsFromData(seriesConfigs);\n baselinePx = yScale.scale(baselineDomain);\n }\n if (!Number.isFinite(baselinePx)) {\n baselineDomain = 0;\n baselinePx = yScale.scale(0);\n }\n\n return { baselineDomain, baselinePx };\n}\n\nexport function bucketStackedXKey(\n xCenterPx: number,\n categoryWidthPx: number,\n xDomain: number,\n categoryStep: number,\n): number {\n // Match renderer intent:\n // - Prefer bucketing in *range-space* to avoid float-equality issues in domain-x.\n // - Requirement: Math.round(xCenterPx / categoryWidthPx) (grid-local).\n if (Number.isFinite(categoryWidthPx) && categoryWidthPx > 0 && Number.isFinite(xCenterPx)) {\n return Math.round(xCenterPx / categoryWidthPx);\n }\n if (Number.isFinite(categoryStep) && categoryStep > 0 && Number.isFinite(xDomain)) {\n return Math.round(xDomain / categoryStep);\n }\n return Math.round(xDomain * 1e6);\n}\n\nconst lowerBoundTuple = (\n data: ReadonlyArray<TuplePoint>,\n xTarget: number,\n): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid][0];\n if (x < xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst lowerBoundObject = (\n data: ReadonlyArray<ObjectPoint>,\n xTarget: number,\n): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid].x;\n if (x < xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\n/**\n * Finds the nearest data point to the given cursor position across all series.\n *\n * Coordinate system contract:\n * - `x`/`y` MUST be in the same units as `xScale`/`yScale` **range**.\n * - If you pass **grid-local CSS pixels** (e.g. `payload.gridX` / `payload.gridY` from `createEventManager`),\n * then `xScale.range()` / `yScale.range()` must also be in **CSS pixels**.\n * - If your scales are in **clip space** (e.g. \\([-1, 1]\\)), pass cursor coordinates in clip space too.\n *\n * DPR/WebGPU note:\n * - Pointer events are naturally in CSS pixels; WebGPU rendering often uses device pixels or clip space.\n * This helper stays agnostic and only computes Euclidean distance in the provided **range-space**.\n *\n * Performance notes:\n * - Assumes each series is sorted by increasing x in domain space.\n * - Uses per-series lower-bound binary search on x, then expands outward while x-distance alone can still win.\n * - Uses squared distance comparisons and computes `sqrt` only for the final match.\n * - Skips non-finite points and any points whose scaled coordinates are NaN.\n */\nexport function findNearestPoint(\n series: ReadonlyArray<ResolvedSeriesConfig>,\n x: number,\n y: number,\n xScale: LinearScale,\n yScale: LinearScale,\n maxDistance: number = DEFAULT_MAX_DISTANCE_PX,\n): NearestPointMatch | null {\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\n const md = Number.isFinite(maxDistance)\n ? Math.max(0, maxDistance)\n : DEFAULT_MAX_DISTANCE_PX;\n const maxDistSq = md * md;\n\n const xTarget = xScale.invert(x);\n if (!Number.isFinite(xTarget)) return null;\n\n let bestSeriesIndex = -1;\n let bestDataIndex = -1;\n let bestPoint: DataPoint | null = null;\n let bestDistSq = Number.POSITIVE_INFINITY;\n\n // Story 4.6: Bar hit-testing (range-space bounds).\n // - Only counts as a match when cursor is inside a bar rect.\n // - For stacked bars, uses the same stacking bucket logic as the bar renderer (xKey bucketing).\n // - If multiple segments match (shared edges), prefer visually topmost (smallest `top` in CSS px).\n // If still tied, prefer larger `seriesIndex` for determinism.\n const barSeriesConfigs: ResolvedBarSeriesConfig[] = [];\n const barSeriesIndexByBar: number[] = [];\n for (let s = 0; s < series.length; s++) {\n const cfg = series[s];\n if (cfg?.type === 'bar') {\n barSeriesConfigs.push(cfg);\n barSeriesIndexByBar.push(s);\n }\n }\n\n if (barSeriesConfigs.length > 0) {\n const layoutPx = computeBarLayoutPx(barSeriesConfigs, xScale);\n if (layoutPx.barWidthPx > 0 && layoutPx.clusterWidthPx >= 0) {\n const plotHeightPx = inferPlotHeightPxForBarHitTesting(barSeriesConfigs, yScale);\n const { baselineDomain, baselinePx } = computeBaselineDomainAndPx(barSeriesConfigs, yScale, plotHeightPx);\n\n const { clusterSlots, barWidthPx, gapPx, clusterWidthPx, categoryWidthPx, categoryStep } = layoutPx;\n const stackSumsByStackId = new Map<string, Map<number, { posSum: number; negSum: number }>>();\n\n let bestBarHit:\n | {\n readonly seriesIndex: number;\n readonly dataIndex: number;\n readonly top: number;\n }\n | null = null;\n\n for (let b = 0; b < barSeriesConfigs.length; b++) {\n const seriesCfg = barSeriesConfigs[b];\n const originalSeriesIndex = barSeriesIndexByBar[b] ?? -1;\n if (originalSeriesIndex < 0) continue;\n\n const data = seriesCfg.data;\n const clusterIndex = clusterSlots.clusterIndexBySeries[b] ?? 0;\n const stackId = clusterSlots.stackIdBySeries[b] ?? '';\n\n for (let i = 0; i < data.length; i++) {\n const { x: xDomain, y: yDomain } = getPointXY(data[i]);\n if (!Number.isFinite(xDomain) || !Number.isFinite(yDomain)) continue;\n\n const xCenterPx = xScale.scale(xDomain);\n if (!Number.isFinite(xCenterPx)) continue;\n\n const left = xCenterPx - clusterWidthPx / 2 + clusterIndex * (barWidthPx + gapPx);\n const right = left + barWidthPx;\n\n let baseDomain = baselineDomain;\n let topDomain = yDomain;\n\n if (stackId !== '') {\n let sumsForX = stackSumsByStackId.get(stackId);\n if (!sumsForX) {\n sumsForX = new Map<number, { posSum: number; negSum: number }>();\n stackSumsByStackId.set(stackId, sumsForX);\n }\n\n const xKey = bucketStackedXKey(xCenterPx, categoryWidthPx, xDomain, categoryStep);\n let sums = sumsForX.get(xKey);\n if (!sums) {\n sums = { posSum: baselineDomain, negSum: baselineDomain };\n sumsForX.set(xKey, sums);\n }\n\n if (yDomain >= 0) {\n baseDomain = sums.posSum;\n topDomain = baseDomain + yDomain;\n sums.posSum = topDomain;\n } else {\n baseDomain = sums.negSum;\n topDomain = baseDomain + yDomain;\n sums.negSum = topDomain;\n }\n } else {\n baseDomain = baselineDomain;\n topDomain = yDomain;\n }\n\n const basePx = stackId !== '' ? yScale.scale(baseDomain) : baselinePx;\n const topPx = yScale.scale(topDomain);\n if (!Number.isFinite(basePx) || !Number.isFinite(topPx)) continue;\n\n const bounds: BarBounds = {\n left,\n right,\n top: Math.min(basePx, topPx),\n bottom: Math.max(basePx, topPx),\n };\n\n if (!isPointInBar(x, y, bounds)) continue;\n\n const isBetter =\n bestBarHit === null ||\n bounds.top < bestBarHit.top ||\n (bounds.top === bestBarHit.top && originalSeriesIndex > bestBarHit.seriesIndex);\n\n if (isBetter) {\n bestBarHit = { seriesIndex: originalSeriesIndex, dataIndex: i, top: bounds.top };\n }\n }\n }\n\n if (bestBarHit) {\n const point = series[bestBarHit.seriesIndex]?.data[bestBarHit.dataIndex] as DataPoint | undefined;\n if (point) {\n return {\n seriesIndex: bestBarHit.seriesIndex,\n dataIndex: bestBarHit.dataIndex,\n point,\n distance: 0,\n };\n }\n }\n }\n }\n\n for (let s = 0; s < series.length; s++) {\n const seriesCfg = series[s];\n // Pie series are non-cartesian; they don't participate in x/y nearest-point hit-testing.\n if (seriesCfg.type === 'pie') continue;\n\n const data = seriesCfg.data;\n const n = data.length;\n if (n === 0) continue;\n\n const isScatter = seriesCfg.type === 'scatter';\n const scatterCfg = isScatter ? (seriesCfg as ResolvedScatterSeriesConfig) : null;\n const maxRadiusInSeries = scatterCfg ? getMaxScatterRadiusCssPx(scatterCfg) : 0;\n const seriesCutoffSq = isScatter ? (md + maxRadiusInSeries) * (md + maxRadiusInSeries) : maxDistSq;\n\n const first = data[0];\n const isTuple = Array.isArray(first);\n\n if (isTuple) {\n const tupleData = data as ReadonlyArray<TuplePoint>;\n const insertionIndex = lowerBoundTuple(tupleData, xTarget);\n\n let left = insertionIndex - 1;\n let right = insertionIndex;\n\n // Expand outward while x-distance alone could still beat bestDistSq.\n while (left >= 0 || right < n) {\n const pruneSq = Math.min(bestDistSq, seriesCutoffSq);\n\n let dxSqLeft = Number.POSITIVE_INFINITY;\n if (left >= 0) {\n const px = tupleData[left][0];\n if (Number.isFinite(px)) {\n const sx = xScale.scale(px);\n if (Number.isFinite(sx)) {\n const dx = sx - x;\n dxSqLeft = dx * dx;\n }\n }\n }\n\n let dxSqRight = Number.POSITIVE_INFINITY;\n if (right < n) {\n const px = tupleData[right][0];\n if (Number.isFinite(px)) {\n const sx = xScale.scale(px);\n if (Number.isFinite(sx)) {\n const dx = sx - x;\n dxSqRight = dx * dx;\n }\n }\n }\n\n if (dxSqLeft > pruneSq && dxSqRight > pruneSq) break;\n\n // If both sides are equally close in x, evaluate both for stable tie behavior.\n if (dxSqLeft <= dxSqRight && dxSqLeft <= pruneSq && left >= 0) {\n const py = tupleData[left][1];\n if (Number.isFinite(py)) {\n const sy = yScale.scale(py);\n if (Number.isFinite(sy)) {\n const dy = sy - y;\n const distSq = dxSqLeft + dy * dy;\n const p = data[left] as DataPoint;\n\n const allowedSq = scatterCfg\n ? (() => {\n const r = getScatterRadiusCssPx(scatterCfg, p);\n const allowed = md + r;\n return allowed * allowed;\n })()\n : maxDistSq;\n\n if (distSq <= allowedSq) {\n const isBetter =\n distSq < bestDistSq ||\n (distSq === bestDistSq &&\n (bestPoint === null ||\n s < bestSeriesIndex ||\n (s === bestSeriesIndex && left < bestDataIndex)));\n if (isBetter) {\n bestDistSq = distSq;\n bestSeriesIndex = s;\n bestDataIndex = left;\n bestPoint = p;\n }\n }\n }\n }\n left--;\n } else if (dxSqLeft <= dxSqRight) {\n left--;\n }\n\n if (dxSqRight <= dxSqLeft && dxSqRight <= pruneSq && right < n) {\n const py = tupleData[right][1];\n if (Number.isFinite(py)) {\n const sy = yScale.scale(py);\n if (Number.isFinite(sy)) {\n const dy = sy - y;\n const distSq = dxSqRight + dy * dy;\n const p = data[right] as DataPoint;\n\n const allowedSq = scatterCfg\n ? (() => {\n const r = getScatterRadiusCssPx(scatterCfg, p);\n const allowed = md + r;\n return allowed * allowed;\n })()\n : maxDistSq;\n\n if (distSq <= allowedSq) {\n const isBetter =\n distSq < bestDistSq ||\n (distSq === bestDistSq &&\n (bestPoint === null ||\n s < bestSeriesIndex ||\n (s === bestSeriesIndex && right < bestDataIndex)));\n if (isBetter) {\n bestDistSq = distSq;\n bestSeriesIndex = s;\n bestDataIndex = right;\n bestPoint = p;\n }\n }\n }\n }\n right++;\n } else if (dxSqRight < dxSqLeft) {\n right++;\n }\n }\n } else {\n const objectData = data as ReadonlyArray<ObjectPoint>;\n const insertionIndex = lowerBoundObject(objectData, xTarget);\n\n let left = insertionIndex - 1;\n let right = insertionIndex;\n\n while (left >= 0 || right < n) {\n const pruneSq = Math.min(bestDistSq, seriesCutoffSq);\n\n let dxSqLeft = Number.POSITIVE_INFINITY;\n if (left >= 0) {\n const px = objectData[left].x;\n if (Number.isFinite(px)) {\n const sx = xScale.scale(px);\n if (Number.isFinite(sx)) {\n const dx = sx - x;\n dxSqLeft = dx * dx;\n }\n }\n }\n\n let dxSqRight = Number.POSITIVE_INFINITY;\n if (right < n) {\n const px = objectData[right].x;\n if (Number.isFinite(px)) {\n const sx = xScale.scale(px);\n if (Number.isFinite(sx)) {\n const dx = sx - x;\n dxSqRight = dx * dx;\n }\n }\n }\n\n if (dxSqLeft > pruneSq && dxSqRight > pruneSq) break;\n\n if (dxSqLeft <= dxSqRight && dxSqLeft <= pruneSq && left >= 0) {\n const py = objectData[left].y;\n if (Number.isFinite(py)) {\n const sy = yScale.scale(py);\n if (Number.isFinite(sy)) {\n const dy = sy - y;\n const distSq = dxSqLeft + dy * dy;\n const p = data[left] as DataPoint;\n\n const allowedSq = scatterCfg\n ? (() => {\n const r = getScatterRadiusCssPx(scatterCfg, p);\n const allowed = md + r;\n return allowed * allowed;\n })()\n : maxDistSq;\n\n if (distSq <= allowedSq) {\n const isBetter =\n distSq < bestDistSq ||\n (distSq === bestDistSq &&\n (bestPoint === null ||\n s < bestSeriesIndex ||\n (s === bestSeriesIndex && left < bestDataIndex)));\n if (isBetter) {\n bestDistSq = distSq;\n bestSeriesIndex = s;\n bestDataIndex = left;\n bestPoint = p;\n }\n }\n }\n }\n left--;\n } else if (dxSqLeft <= dxSqRight) {\n left--;\n }\n\n if (dxSqRight <= dxSqLeft && dxSqRight <= pruneSq && right < n) {\n const py = objectData[right].y;\n if (Number.isFinite(py)) {\n const sy = yScale.scale(py);\n if (Number.isFinite(sy)) {\n const dy = sy - y;\n const distSq = dxSqRight + dy * dy;\n const p = data[right] as DataPoint;\n\n const allowedSq = scatterCfg\n ? (() => {\n const r = getScatterRadiusCssPx(scatterCfg, p);\n const allowed = md + r;\n return allowed * allowed;\n })()\n : maxDistSq;\n\n if (distSq <= allowedSq) {\n const isBetter =\n distSq < bestDistSq ||\n (distSq === bestDistSq &&\n (bestPoint === null ||\n s < bestSeriesIndex ||\n (s === bestSeriesIndex && right < bestDataIndex)));\n if (isBetter) {\n bestDistSq = distSq;\n bestSeriesIndex = s;\n bestDataIndex = right;\n bestPoint = p;\n }\n }\n }\n }\n right++;\n } else if (dxSqRight < dxSqLeft) {\n right++;\n }\n }\n }\n }\n\n if (bestPoint === null) return null;\n if (!Number.isFinite(bestDistSq)) return null;\n\n return {\n seriesIndex: bestSeriesIndex,\n dataIndex: bestDataIndex,\n point: bestPoint,\n distance: Math.sqrt(bestDistSq),\n };\n}\n\n","import type { DataPoint } from '../config/types';\nimport type { ResolvedBarSeriesConfig, ResolvedSeriesConfig } from '../config/OptionResolver';\nimport type { LinearScale } from '../utils/scales';\nimport { computeBarLayoutPx } from './findNearestPoint';\n\nexport type PointsAtXMatch = Readonly<{\n seriesIndex: number;\n dataIndex: number;\n point: DataPoint;\n}>;\n\ntype TuplePoint = readonly [x: number, y: number];\ntype ObjectPoint = Readonly<{ x: number; y: number }>;\n\nconst hasNaNXCache = new WeakMap<ReadonlyArray<unknown>, boolean>();\n\nconst seriesHasNaNX = (data: ReadonlyArray<DataPoint>, isTuple: boolean): boolean => {\n if (hasNaNXCache.has(data)) return hasNaNXCache.get(data)!;\n\n let hasNaN = false;\n\n if (isTuple) {\n const tupleData = data as ReadonlyArray<TuplePoint>;\n for (let i = 0; i < tupleData.length; i++) {\n const x = tupleData[i][0];\n if (Number.isNaN(x)) {\n hasNaN = true;\n break;\n }\n }\n } else {\n const objectData = data as ReadonlyArray<ObjectPoint>;\n for (let i = 0; i < objectData.length; i++) {\n const x = objectData[i].x;\n if (Number.isNaN(x)) {\n hasNaN = true;\n break;\n }\n }\n }\n\n hasNaNXCache.set(data, hasNaN);\n return hasNaN;\n};\n\ntype BarHitTestLayout = Readonly<{\n /** bar width in xScale range units (grid-local CSS px) */\n barWidth: number;\n /** gap between cluster slots, in xScale range units */\n gap: number;\n /** total cluster width (all bar slots), in xScale range units */\n clusterWidth: number;\n /** maps global series index -> cluster slot index */\n clusterIndexByGlobalSeriesIndex: ReadonlyMap<number, number>;\n}>;\n\nconst computeBarHitTestLayout = (\n series: ReadonlyArray<ResolvedSeriesConfig>,\n xScale: LinearScale\n): BarHitTestLayout | null => {\n // Mirror the bar renderer's shared layout math via `computeBarLayoutPx(...)`, but in xScale range units.\n // IMPORTANT: Bar layout depends on all bar series (stacking + grouped slots), not per-series.\n const barSeries: { readonly globalSeriesIndex: number; readonly s: ResolvedBarSeriesConfig }[] = [];\n for (let i = 0; i < series.length; i++) {\n const s = series[i];\n if (s?.type === 'bar') barSeries.push({ globalSeriesIndex: i, s });\n }\n if (barSeries.length === 0) return null;\n\n const layout = computeBarLayoutPx(\n barSeries.map((b) => b.s),\n xScale\n );\n\n const barWidthRange = layout.barWidthPx;\n const gap = layout.gapPx;\n const clusterWidth = layout.clusterWidthPx;\n if (!Number.isFinite(barWidthRange) || !(barWidthRange > 0)) return null;\n\n const clusterIndexByGlobalSeriesIndex = new Map<number, number>();\n for (let i = 0; i < barSeries.length; i++) {\n const globalSeriesIndex = barSeries[i].globalSeriesIndex;\n const clusterIndex = layout.clusterSlots.clusterIndexBySeries[i] ?? 0;\n clusterIndexByGlobalSeriesIndex.set(globalSeriesIndex, clusterIndex);\n }\n\n return {\n barWidth: barWidthRange,\n gap,\n clusterWidth,\n clusterIndexByGlobalSeriesIndex,\n };\n};\n\nconst lowerBoundTuple = (data: ReadonlyArray<TuplePoint>, xTarget: number): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid][0];\n if (x < xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst lowerBoundObject = (data: ReadonlyArray<ObjectPoint>, xTarget: number): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid].x;\n if (x < xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\n/**\n * Finds (at most) one nearest point per series at a given x position.\n *\n * Coordinate system contract (mirrors `findNearestPoint`):\n * - `xValue` and optional `tolerance` MUST be in the same units as `xScale` **range**.\n * (Example: if your `xScale.range()` is in grid-local CSS pixels, pass `payload.gridX` from `createEventManager`.)\n * Note: ChartGPU's internal renderer scales are currently in clip space (NDC, typically \\[-1, 1\\]); in that case\n * convert your pointer x into clip space before calling this helper.\n *\n * Behavior:\n * - Assumes each series is sorted by increasing x in domain space.\n * - Uses a lower-bound binary search in domain-x, then expands outward while x-distance alone can still improve.\n * - Skips points with non-finite domain x or non-finite scaled x. If a series contains any NaN x values, this helper\n * falls back to an O(n) scan for correctness (NaN breaks total ordering for binary search).\n * - Stable tie-breaking: for equal distance, chooses the smaller `dataIndex`.\n *\n * If `tolerance` is provided, it is interpreted in **xScale range units**. Matches beyond tolerance are omitted.\n * If `tolerance` is omitted (or non-finite), the nearest point per series is returned when possible.\n *\n * Bar series special-case:\n * - Bars occupy x-intervals \\([left, right)\\) in **xScale range units** (grid-local CSS px for interaction scales),\n * using the same shared layout math as the bar renderer (grouping + stacking slots).\n * - If `tolerance` is finite, a bar match is only returned when `xValue` falls inside the bar interval expanded by\n * `tolerance` on both sides: \\([left - tolerance, right + tolerance)\\).\n * - If `tolerance` is omitted / non-finite, we first attempt an exact interval hit (no expansion) and otherwise fall\n * back to the existing nearest-x behavior (so axis-trigger tooltips still work away from bars).\n */\nexport function findPointsAtX(\n series: ReadonlyArray<ResolvedSeriesConfig>,\n xValue: number,\n xScale: LinearScale,\n tolerance?: number,\n): ReadonlyArray<PointsAtXMatch> {\n if (!Number.isFinite(xValue)) return [];\n\n const maxDx =\n tolerance === undefined || !Number.isFinite(tolerance) ? Number.POSITIVE_INFINITY : Math.max(0, tolerance);\n const maxDxSq = maxDx * maxDx;\n\n const xTarget = xScale.invert(xValue);\n if (!Number.isFinite(xTarget)) return [];\n\n const matches: PointsAtXMatch[] = [];\n const barLayout = computeBarHitTestLayout(series, xScale);\n\n for (let s = 0; s < series.length; s++) {\n const seriesConfig = series[s];\n // Pie is non-cartesian; it can't match an x position.\n if (seriesConfig.type === 'pie') continue;\n\n const data = seriesConfig.data;\n const n = data.length;\n if (n === 0) continue;\n\n const first = data[0];\n const isTuple = Array.isArray(first);\n\n // Bar series: return the correct bar dataIndex for xValue when inside the bar interval.\n // When tolerance is finite: require an (expanded) interval hit.\n // When tolerance is non-finite: attempt exact hit, otherwise fall back to nearest-x behavior below.\n if (seriesConfig.type === 'bar' && barLayout) {\n const clusterIndex = barLayout.clusterIndexByGlobalSeriesIndex.get(s);\n if (clusterIndex !== undefined) {\n const { barWidth, gap, clusterWidth } = barLayout;\n const offsetLeftFromCategoryCenter = -clusterWidth / 2 + clusterIndex * (barWidth + gap);\n\n const hitTol =\n tolerance === undefined || !Number.isFinite(tolerance) ? 0 : Math.max(0, tolerance);\n\n // If we can't safely compute an interval hit, don't guess when tolerance is finite.\n if (Number.isFinite(barWidth) && barWidth > 0 && Number.isFinite(offsetLeftFromCategoryCenter)) {\n let hitIndex = -1;\n\n const isHit = (xCenterRange: number): boolean => {\n if (!Number.isFinite(xCenterRange)) return false;\n const left = xCenterRange + offsetLeftFromCategoryCenter;\n const right = left + barWidth;\n // Expanded interval: [left - tol, right + tol)\n return xValue >= left - hitTol && xValue < right + hitTol;\n };\n\n if (seriesHasNaNX(data, isTuple)) {\n // NaN breaks ordering; linear scan for correctness.\n if (isTuple) {\n const tupleData = data as ReadonlyArray<TuplePoint>;\n for (let i = 0; i < n; i++) {\n const px = tupleData[i][0];\n if (!Number.isFinite(px)) continue;\n const xCenter = xScale.scale(px);\n if (isHit(xCenter)) {\n hitIndex = hitIndex < 0 ? i : Math.min(hitIndex, i);\n }\n }\n } else {\n const objectData = data as ReadonlyArray<ObjectPoint>;\n for (let i = 0; i < n; i++) {\n const px = objectData[i].x;\n if (!Number.isFinite(px)) continue;\n const xCenter = xScale.scale(px);\n if (isHit(xCenter)) {\n hitIndex = hitIndex < 0 ? i : Math.min(hitIndex, i);\n }\n }\n }\n } else {\n // Use a lower-bound search around the adjusted x (accounts for cluster offset).\n const xTargetAdjusted = xScale.invert(xValue - offsetLeftFromCategoryCenter);\n if (Number.isFinite(xTargetAdjusted)) {\n const insertionIndex = isTuple\n ? lowerBoundTuple(data as ReadonlyArray<TuplePoint>, xTargetAdjusted)\n : lowerBoundObject(data as ReadonlyArray<ObjectPoint>, xTargetAdjusted);\n\n const getXCenterAt = (idx: number): number | null => {\n if (idx < 0 || idx >= n) return null;\n const px = isTuple\n ? (data as ReadonlyArray<TuplePoint>)[idx][0]\n : (data as ReadonlyArray<ObjectPoint>)[idx].x;\n if (!Number.isFinite(px)) return null;\n const xCenter = xScale.scale(px);\n return Number.isFinite(xCenter) ? xCenter : null;\n };\n\n // Scan left while intervals could still contain xValue.\n for (let i = insertionIndex - 1; i >= 0; i--) {\n const xCenter = getXCenterAt(i);\n if (xCenter === null) continue;\n const left = xCenter + offsetLeftFromCategoryCenter;\n const right = left + barWidth;\n if (right + hitTol <= xValue) break;\n if (xValue >= left - hitTol && xValue < right + hitTol) {\n hitIndex = hitIndex < 0 ? i : Math.min(hitIndex, i);\n }\n }\n\n // Scan right until intervals start strictly after xValue.\n for (let i = insertionIndex; i < n; i++) {\n const xCenter = getXCenterAt(i);\n if (xCenter === null) continue;\n const left = xCenter + offsetLeftFromCategoryCenter;\n if (left - hitTol > xValue) break;\n const right = left + barWidth;\n if (xValue < right + hitTol) {\n hitIndex = hitIndex < 0 ? i : Math.min(hitIndex, i);\n }\n }\n }\n }\n\n if (hitIndex >= 0) {\n matches.push({ seriesIndex: s, dataIndex: hitIndex, point: data[hitIndex] as DataPoint });\n continue;\n }\n\n // If tolerance is finite, require a hit (no nearest-x fallback).\n if (tolerance !== undefined && Number.isFinite(tolerance)) {\n continue;\n }\n // Else: fall through to nearest-x behavior (existing logic) for axis-trigger tooltips.\n } else if (tolerance !== undefined && Number.isFinite(tolerance)) {\n continue;\n }\n }\n }\n\n let bestDataIndex = -1;\n let bestPoint: DataPoint | null = null;\n let bestDxSq = maxDxSq;\n\n const tryUpdate = (idx: number, dxSq: number) => {\n if (!Number.isFinite(dxSq)) return;\n const isBetter =\n dxSq < bestDxSq || (dxSq === bestDxSq && (bestDataIndex < 0 || idx < bestDataIndex));\n if (!isBetter) return;\n bestDxSq = dxSq;\n bestDataIndex = idx;\n bestPoint = data[idx] as DataPoint;\n };\n\n // If the series contains NaN x values, binary search cannot be trusted (NaN breaks ordering).\n // Fall back to a linear scan for correctness. Cached per data array for performance.\n if (seriesHasNaNX(data, isTuple)) {\n if (isTuple) {\n const tupleData = data as ReadonlyArray<TuplePoint>;\n for (let i = 0; i < n; i++) {\n const px = tupleData[i][0];\n if (!Number.isFinite(px)) continue;\n const sx = xScale.scale(px);\n if (!Number.isFinite(sx)) continue;\n const dx = sx - xValue;\n tryUpdate(i, dx * dx);\n }\n } else {\n const objectData = data as ReadonlyArray<ObjectPoint>;\n for (let i = 0; i < n; i++) {\n const px = objectData[i].x;\n if (!Number.isFinite(px)) continue;\n const sx = xScale.scale(px);\n if (!Number.isFinite(sx)) continue;\n const dx = sx - xValue;\n tryUpdate(i, dx * dx);\n }\n }\n } else if (isTuple) {\n const tupleData = data as ReadonlyArray<TuplePoint>;\n const insertionIndex = lowerBoundTuple(tupleData, xTarget);\n\n let left = insertionIndex - 1;\n let right = insertionIndex;\n\n const dxSqAt = (idx: number): number | null => {\n const px = tupleData[idx][0];\n if (!Number.isFinite(px)) return null;\n const sx = xScale.scale(px);\n if (!Number.isFinite(sx)) return null;\n const dx = sx - xValue;\n return dx * dx;\n };\n\n while (left >= 0 || right < n) {\n while (left >= 0 && dxSqAt(left) === null) left--;\n while (right < n && dxSqAt(right) === null) right++;\n if (left < 0 && right >= n) break;\n\n const dxSqLeft = left >= 0 ? (dxSqAt(left) ?? Number.POSITIVE_INFINITY) : Number.POSITIVE_INFINITY;\n const dxSqRight = right < n ? (dxSqAt(right) ?? Number.POSITIVE_INFINITY) : Number.POSITIVE_INFINITY;\n\n if (dxSqLeft > bestDxSq && dxSqRight > bestDxSq) break;\n\n // If both sides are equally close in x, evaluate left first (smaller index) for stable ties.\n if (dxSqLeft <= dxSqRight) {\n if (left >= 0 && dxSqLeft <= bestDxSq) tryUpdate(left, dxSqLeft);\n left--;\n if (right < n && dxSqRight <= bestDxSq && dxSqRight === dxSqLeft) {\n tryUpdate(right, dxSqRight);\n right++;\n }\n } else {\n if (right < n && dxSqRight <= bestDxSq) tryUpdate(right, dxSqRight);\n right++;\n }\n }\n } else {\n const objectData = data as ReadonlyArray<ObjectPoint>;\n const insertionIndex = lowerBoundObject(objectData, xTarget);\n\n let left = insertionIndex - 1;\n let right = insertionIndex;\n\n const dxSqAt = (idx: number): number | null => {\n const px = objectData[idx].x;\n if (!Number.isFinite(px)) return null;\n const sx = xScale.scale(px);\n if (!Number.isFinite(sx)) return null;\n const dx = sx - xValue;\n return dx * dx;\n };\n\n while (left >= 0 || right < n) {\n while (left >= 0 && dxSqAt(left) === null) left--;\n while (right < n && dxSqAt(right) === null) right++;\n if (left < 0 && right >= n) break;\n\n const dxSqLeft = left >= 0 ? (dxSqAt(left) ?? Number.POSITIVE_INFINITY) : Number.POSITIVE_INFINITY;\n const dxSqRight = right < n ? (dxSqAt(right) ?? Number.POSITIVE_INFINITY) : Number.POSITIVE_INFINITY;\n\n if (dxSqLeft > bestDxSq && dxSqRight > bestDxSq) break;\n\n if (dxSqLeft <= dxSqRight) {\n if (left >= 0 && dxSqLeft <= bestDxSq) tryUpdate(left, dxSqLeft);\n left--;\n if (right < n && dxSqRight <= bestDxSq && dxSqRight === dxSqLeft) {\n tryUpdate(right, dxSqRight);\n right++;\n }\n } else {\n if (right < n && dxSqRight <= bestDxSq) tryUpdate(right, dxSqRight);\n right++;\n }\n }\n }\n\n if (bestPoint !== null) matches.push({ seriesIndex: s, dataIndex: bestDataIndex, point: bestPoint });\n }\n\n return matches;\n}\n\n","import type { ResolvedPieSeriesConfig } from '../config/OptionResolver';\n\nconst TAU = Math.PI * 2;\n\nconst wrapToTau = (thetaRad: number): number => {\n if (!Number.isFinite(thetaRad)) return 0;\n const t = thetaRad % TAU;\n return t < 0 ? t + TAU : t;\n};\n\nexport type PieSliceMatch = Readonly<{\n seriesIndex: number;\n dataIndex: number;\n slice: ResolvedPieSeriesConfig['data'][number];\n}>;\n\nexport type PieHitTestConfig = Readonly<{\n seriesIndex: number;\n series: ResolvedPieSeriesConfig;\n}>;\n\nexport type PieCenterCssPx = Readonly<{ x: number; y: number }>;\nexport type PieRadiusCssPx = Readonly<{ inner: number; outer: number }>;\n\n/**\n * Finds the pie slice under a given pointer position.\n *\n * Coordinate contract:\n * - `x`/`y` are plot/grid-local CSS pixels (origin at plot top-left, +y down).\n * - `center` is plot-local CSS pixels.\n * - `radius` is CSS pixels (inner/outer). Points within the donut hole are not hoverable.\n *\n * Angle conventions:\n * - Uses +y up for polar angle (to match `pie.wgsl` atan2(p.y, p.x)).\n * - Wraps angles to [0, 2π).\n * - Matches `createPieRenderer.ts` start angle default (90°).\n *\n * Value conventions:\n * - Ignores non-finite and non-positive slice values (mirrors renderer).\n */\nexport function findPieSlice(\n x: number,\n y: number,\n pieConfig: PieHitTestConfig,\n center: PieCenterCssPx,\n radius: PieRadiusCssPx\n): PieSliceMatch | null {\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n if (!Number.isFinite(center.x) || !Number.isFinite(center.y)) return null;\n\n const inner = Number.isFinite(radius.inner) ? Math.max(0, radius.inner) : 0;\n const outer = Number.isFinite(radius.outer) ? Math.max(0, radius.outer) : 0;\n if (!(outer > 0)) return null;\n\n // Polar coordinates:\n // - Pointer `y` is down in CSS px, but shader uses +y up (atan2(p.y, p.x)).\n const dx = x - center.x;\n const dyUp = center.y - y;\n const r = Math.hypot(dx, dyUp);\n if (!Number.isFinite(r)) return null;\n\n // Donut hole is non-hoverable; outer bound must be inside.\n if (r <= inner) return null;\n if (r > outer) return null;\n\n const angle = wrapToTau(Math.atan2(dyUp, dx));\n\n const series = pieConfig.series;\n const data = series.data;\n\n // Total positive value for angle allocation (mirrors renderer).\n let total = 0;\n let validCount = 0;\n for (let i = 0; i < data.length; i++) {\n const v = data[i]?.value;\n if (typeof v === 'number' && Number.isFinite(v) && v > 0) {\n total += v;\n validCount++;\n }\n }\n if (!(total > 0) || validCount === 0) return null;\n\n const startDeg =\n typeof series.startAngle === 'number' && Number.isFinite(series.startAngle) ? series.startAngle : 90;\n let current = wrapToTau((startDeg * Math.PI) / 180);\n\n // Mirror renderer float-drift mitigation: force last slice to close the circle.\n let accumulated = 0;\n let emitted = 0;\n\n for (let i = 0; i < data.length; i++) {\n const slice = data[i];\n const v = slice?.value;\n if (typeof v !== 'number' || !Number.isFinite(v) || v <= 0) continue;\n\n emitted++;\n const isLast = emitted === validCount;\n\n const frac = v / total;\n let span = frac * TAU;\n if (isLast) {\n span = Math.max(0, TAU - accumulated);\n } else {\n span = Math.max(0, Math.min(TAU, span));\n }\n accumulated += span;\n if (!(span > 0)) continue;\n\n const start = current;\n const end = wrapToTau(current + span);\n current = end;\n\n // Match `pie.wgsl` wedge test (span and rel in [0, TAU) with wrap).\n let wedgeSpan = end - start;\n if (wedgeSpan < 0) wedgeSpan += TAU;\n\n let rel = angle - start;\n if (rel < 0) rel += TAU;\n\n if (rel <= wedgeSpan) {\n return { seriesIndex: pieConfig.seriesIndex, dataIndex: i, slice };\n }\n }\n\n return null;\n}\n\n","export interface LinearScale {\n /**\n * Sets the scale domain (data range). Returns self for chaining.\n */\n domain(min: number, max: number): LinearScale;\n\n /**\n * Sets the scale range (pixel range). Returns self for chaining.\n */\n range(min: number, max: number): LinearScale;\n\n /**\n * Maps a domain value to a range value.\n *\n * Notes:\n * - No clamping (will extrapolate outside the domain).\n * - If the domain span is 0 (min === max), returns the midpoint of the range.\n */\n scale(value: number): number;\n\n /**\n * Maps a range value (pixel) back to a domain value.\n *\n * Notes:\n * - No clamping (will extrapolate outside the range).\n * - If the domain span is 0 (min === max), returns domain min for any input.\n */\n invert(pixel: number): number;\n}\n\nexport interface CategoryScale {\n /**\n * Sets the category domain (ordered list of unique category names).\n * Returns self for chaining.\n *\n * Throws if duplicates exist (ambiguous mapping).\n */\n domain(categories: string[]): CategoryScale;\n\n /**\n * Sets the scale range (pixel range). Returns self for chaining.\n */\n range(min: number, max: number): CategoryScale;\n\n /**\n * Returns the center x-position for a category.\n *\n * Edge cases:\n * - Unknown category: returns NaN\n * - Empty domain: returns midpoint of range\n */\n scale(category: string): number;\n\n /**\n * Width allocated per category (always non-negative).\n *\n * Edge cases:\n * - Empty domain: returns 0\n * - Reversed ranges allowed\n */\n bandwidth(): number;\n\n /**\n * Returns the index of a category in the current domain.\n *\n * Edge cases:\n * - Unknown category: returns -1\n */\n categoryIndex(category: string): number;\n}\n\nconst assertFinite = (label: string, value: number): void => {\n if (!Number.isFinite(value)) {\n throw new Error(`${label} must be a finite number. Received: ${String(value)}`);\n }\n};\n\n/**\n * Creates a linear scale for mapping a numeric domain to a numeric range.\n *\n * Defaults to an identity mapping:\n * domain [0, 1] -> range [0, 1]\n */\nexport function createLinearScale(): LinearScale {\n let domainMin = 0;\n let domainMax = 1;\n let rangeMin = 0;\n let rangeMax = 1;\n\n const self: LinearScale = {\n domain(min: number, max: number) {\n assertFinite('domain min', min);\n assertFinite('domain max', max);\n domainMin = min;\n domainMax = max;\n return self;\n },\n\n range(min: number, max: number) {\n assertFinite('range min', min);\n assertFinite('range max', max);\n rangeMin = min;\n rangeMax = max;\n return self;\n },\n\n scale(value: number) {\n if (!Number.isFinite(value)) return Number.NaN;\n\n if (domainMin === domainMax) {\n return (rangeMin + rangeMax) / 2;\n }\n\n const t = (value - domainMin) / (domainMax - domainMin);\n return rangeMin + t * (rangeMax - rangeMin);\n },\n\n invert(pixel: number) {\n if (!Number.isFinite(pixel)) return Number.NaN;\n\n if (domainMin === domainMax) {\n return domainMin;\n }\n\n if (rangeMin === rangeMax) {\n return (domainMin + domainMax) / 2;\n }\n\n const t = (pixel - rangeMin) / (rangeMax - rangeMin);\n return domainMin + t * (domainMax - domainMin);\n },\n };\n\n return self;\n}\n\n/**\n * Creates a category scale for mapping string categories to evenly spaced\n * x-positions across a numeric range.\n *\n * Defaults:\n * - domain: []\n * - range: [0, 1]\n */\nexport function createCategoryScale(): CategoryScale {\n let categories: readonly string[] = [];\n let indexByCategory = new Map<string, number>();\n let rangeMin = 0;\n let rangeMax = 1;\n\n const rebuildIndex = (nextCategories: readonly string[]) => {\n const nextIndex = new Map<string, number>();\n for (let i = 0; i < nextCategories.length; i++) {\n const c = nextCategories[i];\n // Enforce uniqueness to avoid ambiguous mapping\n if (nextIndex.has(c)) {\n throw new Error(`Category domain must not contain duplicates. Duplicate: ${JSON.stringify(c)}`);\n }\n nextIndex.set(c, i);\n }\n indexByCategory = nextIndex;\n };\n\n const self: CategoryScale = {\n domain(nextCategories: string[]) {\n categories = [...nextCategories];\n rebuildIndex(categories);\n return self;\n },\n\n range(min: number, max: number) {\n assertFinite('range min', min);\n assertFinite('range max', max);\n rangeMin = min;\n rangeMax = max;\n return self;\n },\n\n categoryIndex(category: string) {\n const idx = indexByCategory.get(category);\n return idx === undefined ? -1 : idx;\n },\n\n bandwidth() {\n const n = categories.length;\n if (n === 0) return 0;\n return Math.abs((rangeMax - rangeMin) / n);\n },\n\n scale(category: string) {\n const n = categories.length;\n if (n === 0) {\n return (rangeMin + rangeMax) / 2;\n }\n\n const i = self.categoryIndex(category);\n if (i < 0) return Number.NaN;\n\n const step = (rangeMax - rangeMin) / n; // can be negative (reversed range)\n return rangeMin + (i + 0.5) * step;\n },\n };\n\n return self;\n}\n","export type TextOverlayAnchor = 'start' | 'middle' | 'end';\n\nexport interface TextOverlayLabelOptions {\n readonly fontSize?: number;\n readonly color?: string;\n readonly anchor?: TextOverlayAnchor;\n /**\n * Rotation in degrees (CSS `rotate(<deg>deg)`).\n */\n readonly rotation?: number;\n}\n\nexport interface TextOverlay {\n clear(): void;\n addLabel(\n text: string,\n x: number,\n y: number,\n options?: TextOverlayLabelOptions\n ): HTMLSpanElement;\n dispose(): void;\n}\n\nconst getAnchorTransform = (\n anchor: TextOverlayAnchor\n): Readonly<{ translateX: string; originX: string }> => {\n switch (anchor) {\n case 'start':\n return { translateX: '0%', originX: '0%' };\n case 'middle':\n return { translateX: '-50%', originX: '50%' };\n case 'end':\n return { translateX: '-100%', originX: '100%' };\n }\n};\n\nexport function createTextOverlay(container: HTMLElement): TextOverlay {\n const computedPosition = getComputedStyle(container).position;\n const didSetRelative = computedPosition === 'static';\n const previousInlinePosition = didSetRelative ? container.style.position : null;\n\n if (didSetRelative) {\n container.style.position = 'relative';\n }\n\n const overlay = document.createElement('div');\n overlay.style.position = 'absolute';\n overlay.style.inset = '0';\n overlay.style.pointerEvents = 'none';\n overlay.style.overflow = 'hidden';\n container.appendChild(overlay);\n\n let disposed = false;\n\n const clear = (): void => {\n if (disposed) return;\n overlay.replaceChildren();\n };\n\n const addLabel: TextOverlay['addLabel'] = (text, x, y, options) => {\n if (disposed) {\n // Keep it non-throwing so callsites don't need try/catch in teardown paths.\n return document.createElement('span');\n }\n\n const span = document.createElement('span');\n span.textContent = text;\n span.style.position = 'absolute';\n span.style.left = `${x}px`;\n span.style.top = `${y}px`;\n span.style.pointerEvents = 'none';\n span.style.userSelect = 'none';\n span.style.whiteSpace = 'nowrap';\n span.style.lineHeight = '1';\n\n if (options?.fontSize != null) span.style.fontSize = `${options.fontSize}px`;\n if (options?.color != null) span.style.color = options.color;\n\n const rotation = options?.rotation ?? 0;\n const anchor = options?.anchor ?? 'start';\n const { translateX, originX } = getAnchorTransform(anchor);\n\n span.style.transformOrigin = `${originX} 50%`;\n span.style.transform = `translateX(${translateX}) translateY(-50%) rotate(${rotation}deg)`;\n\n overlay.appendChild(span);\n return span;\n };\n\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n\n try {\n overlay.remove();\n } finally {\n if (previousInlinePosition !== null) {\n container.style.position = previousInlinePosition;\n }\n }\n };\n\n return { clear, addLabel, dispose };\n}\n\n","import type { SeriesConfig } from '../config/types';\nimport type { ThemeConfig } from '../themes/types';\n\nexport type LegendPosition = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface Legend {\n update(series: ReadonlyArray<SeriesConfig>, theme: ThemeConfig): void;\n dispose(): void;\n}\n\nconst getSeriesName = (series: SeriesConfig, index: number): string => {\n const candidate = series.name?.trim();\n return candidate ? candidate : `Series ${index + 1}`;\n};\n\nconst getSeriesColor = (\n series: SeriesConfig,\n index: number,\n theme: ThemeConfig\n): string => {\n const explicit = series.color?.trim();\n if (explicit) return explicit;\n\n const palette = theme.colorPalette;\n if (palette.length > 0) return palette[index % palette.length] ?? '#000000';\n return '#000000';\n};\n\nconst getPieSliceLabel = (sliceName: string | undefined, sliceIndex: number): string => {\n const candidate = sliceName?.trim();\n return candidate ? candidate : `Slice ${sliceIndex + 1}`;\n};\n\nconst getPieSliceColor = (\n sliceColor: string | undefined,\n seriesIndex: number,\n sliceIndex: number,\n theme: ThemeConfig\n): string => {\n const explicit = sliceColor?.trim();\n if (explicit) return explicit;\n\n const palette = theme.colorPalette;\n const len = palette.length;\n if (len > 0) return palette[(seriesIndex + sliceIndex) % len] ?? '#000000';\n return '#000000';\n};\n\nexport function createLegend(\n container: HTMLElement,\n position: LegendPosition = 'right'\n): Legend {\n const computedPosition = getComputedStyle(container).position;\n const didSetRelative = computedPosition === 'static';\n const previousInlinePosition = didSetRelative ? container.style.position : null;\n\n if (didSetRelative) {\n container.style.position = 'relative';\n }\n\n const root = document.createElement('div');\n root.style.position = 'absolute';\n root.style.pointerEvents = 'none';\n root.style.userSelect = 'none';\n root.style.boxSizing = 'border-box';\n\n // Theme-driven styling (set/update in update()).\n root.style.padding = '8px';\n root.style.borderRadius = '8px';\n root.style.borderStyle = 'solid';\n root.style.borderWidth = '1px';\n root.style.maxHeight = 'calc(100% - 16px)';\n root.style.overflow = 'auto';\n\n const list = document.createElement('div');\n list.style.display = 'flex';\n list.style.gap = '8px';\n root.appendChild(list);\n\n const applyPositionStyles = (p: LegendPosition): void => {\n // Clear positional styles first so changing position is safe/idempotent.\n root.style.top = '';\n root.style.right = '';\n root.style.bottom = '';\n root.style.left = '';\n root.style.maxWidth = '';\n\n list.style.flexDirection = '';\n list.style.flexWrap = '';\n list.style.alignItems = '';\n\n switch (p) {\n case 'right': {\n root.style.top = '8px';\n root.style.right = '8px';\n root.style.maxWidth = '40%';\n\n list.style.flexDirection = 'column';\n list.style.flexWrap = 'nowrap';\n list.style.alignItems = 'flex-start';\n return;\n }\n case 'left': {\n root.style.top = '8px';\n root.style.left = '8px';\n root.style.maxWidth = '40%';\n\n list.style.flexDirection = 'column';\n list.style.flexWrap = 'nowrap';\n list.style.alignItems = 'flex-start';\n return;\n }\n case 'top': {\n root.style.top = '8px';\n root.style.left = '8px';\n root.style.right = '8px';\n\n list.style.flexDirection = 'row';\n list.style.flexWrap = 'wrap';\n list.style.alignItems = 'center';\n return;\n }\n case 'bottom': {\n root.style.bottom = '8px';\n root.style.left = '8px';\n root.style.right = '8px';\n\n list.style.flexDirection = 'row';\n list.style.flexWrap = 'wrap';\n list.style.alignItems = 'center';\n return;\n }\n }\n };\n\n applyPositionStyles(position);\n container.appendChild(root);\n\n let disposed = false;\n\n const update: Legend['update'] = (series, theme) => {\n if (disposed) return;\n\n root.style.color = theme.textColor;\n root.style.background = theme.backgroundColor;\n root.style.borderColor = theme.axisLineColor;\n root.style.fontFamily = theme.fontFamily;\n root.style.fontSize = `${theme.fontSize}px`;\n\n const items: HTMLElement[] = [];\n for (let seriesIndex = 0; seriesIndex < series.length; seriesIndex++) {\n const s = series[seriesIndex];\n\n if (s.type === 'pie') {\n for (let sliceIndex = 0; sliceIndex < s.data.length; sliceIndex++) {\n const slice = s.data[sliceIndex];\n\n const item = document.createElement('div');\n item.style.display = 'flex';\n item.style.alignItems = 'center';\n item.style.gap = '6px';\n item.style.lineHeight = '1.1';\n item.style.whiteSpace = 'nowrap';\n\n const swatch = document.createElement('div');\n swatch.style.width = '10px';\n swatch.style.height = '10px';\n swatch.style.borderRadius = '2px';\n swatch.style.flex = '0 0 auto';\n swatch.style.background = getPieSliceColor(slice?.color, seriesIndex, sliceIndex, theme);\n swatch.style.border = `1px solid ${theme.axisLineColor}`;\n\n const label = document.createElement('span');\n label.textContent = getPieSliceLabel(slice?.name, sliceIndex);\n\n item.appendChild(swatch);\n item.appendChild(label);\n items.push(item);\n }\n } else {\n const item = document.createElement('div');\n item.style.display = 'flex';\n item.style.alignItems = 'center';\n item.style.gap = '6px';\n item.style.lineHeight = '1.1';\n item.style.whiteSpace = 'nowrap';\n\n const swatch = document.createElement('div');\n swatch.style.width = '10px';\n swatch.style.height = '10px';\n swatch.style.borderRadius = '2px';\n swatch.style.flex = '0 0 auto';\n swatch.style.background = getSeriesColor(s, seriesIndex, theme);\n swatch.style.border = `1px solid ${theme.axisLineColor}`;\n\n const label = document.createElement('span');\n label.textContent = getSeriesName(s, seriesIndex);\n\n item.appendChild(swatch);\n item.appendChild(label);\n items.push(item);\n }\n }\n\n list.replaceChildren(...items);\n };\n\n const dispose: Legend['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n try {\n root.remove();\n } finally {\n if (previousInlinePosition !== null) {\n container.style.position = previousInlinePosition;\n }\n }\n };\n\n return { update, dispose };\n}\n\n","export interface Tooltip {\n /**\n * Show tooltip at container-local CSS pixel coordinates.\n *\n * `content` is treated as HTML (assigned via `innerHTML`).\n */\n show(x: number, y: number, content: string): void;\n hide(): void;\n dispose(): void;\n}\n\nconst clamp = (value: number, min: number, max: number): number => {\n if (max < min) return min;\n if (value < min) return min;\n if (value > max) return max;\n return value;\n};\n\nexport function createTooltip(container: HTMLElement): Tooltip {\n const computedPosition = getComputedStyle(container).position;\n const didSetRelative = computedPosition === 'static';\n const previousInlinePosition = didSetRelative ? container.style.position : null;\n\n if (didSetRelative) {\n container.style.position = 'relative';\n }\n\n const root = document.createElement('div');\n root.style.position = 'absolute';\n root.style.left = '0';\n root.style.top = '0';\n root.style.pointerEvents = 'none';\n root.style.userSelect = 'none';\n root.style.boxSizing = 'border-box';\n\n // Theme-friendly default visuals with CSS variable override points.\n root.style.zIndex = 'var(--chartgpu-tooltip-z, 10)';\n root.style.padding = 'var(--chartgpu-tooltip-padding, 6px 8px)';\n root.style.borderRadius = 'var(--chartgpu-tooltip-radius, 8px)';\n root.style.borderStyle = 'solid';\n root.style.borderWidth = 'var(--chartgpu-tooltip-border-width, 1px)';\n root.style.borderColor =\n 'var(--chartgpu-tooltip-border, rgba(224,224,224,0.35))';\n root.style.boxShadow =\n 'var(--chartgpu-tooltip-shadow, 0 6px 18px rgba(0,0,0,0.35))';\n root.style.maxWidth = 'var(--chartgpu-tooltip-max-width, min(320px, 100%))';\n root.style.overflow = 'hidden';\n root.style.fontFamily =\n 'var(--chartgpu-tooltip-font-family, system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\")';\n root.style.fontSize = 'var(--chartgpu-tooltip-font-size, 12px)';\n root.style.lineHeight = 'var(--chartgpu-tooltip-line-height, 1.2)';\n root.style.color = 'var(--chartgpu-tooltip-color, #e0e0e0)';\n root.style.background = 'var(--chartgpu-tooltip-bg, rgba(26,26,46,0.95))';\n root.style.whiteSpace = 'normal';\n\n // Transition-ready baseline; keep fade-out visible until completion.\n root.style.opacity = '0';\n root.style.transitionProperty = 'opacity';\n const fadeMs = 140;\n root.style.transitionDuration = `${fadeMs}ms`;\n root.style.transitionTimingFunction = 'ease';\n root.style.willChange = 'opacity';\n\n // Keep it out of layout/paint when hidden.\n root.style.display = 'none';\n root.style.visibility = 'hidden';\n\n root.setAttribute('role', 'tooltip');\n container.appendChild(root);\n\n let disposed = false;\n let transitionToken = 0;\n let hideTimeoutId: number | null = null;\n let rafId: number | null = null;\n\n const clearPendingTransitions = (): void => {\n if (hideTimeoutId != null) {\n window.clearTimeout(hideTimeoutId);\n hideTimeoutId = null;\n }\n if (rafId != null) {\n window.cancelAnimationFrame(rafId);\n rafId = null;\n }\n };\n\n const isCurrentlyHidden = (): boolean =>\n root.style.display === 'none' || root.style.visibility === 'hidden';\n\n const measureSize = (): Readonly<{ width: number; height: number }> => {\n // Measure without touching opacity to avoid restarting fades.\n // If the tooltip is currently visible, this temporarily hides it from paint\n // within the same call (no flicker between frames).\n const prevVisibility = root.style.visibility;\n root.style.visibility = 'hidden';\n\n // offsetWidth/offsetHeight are rounded but stable for layout decisions here.\n const width = root.offsetWidth;\n const height = root.offsetHeight;\n\n root.style.visibility = prevVisibility;\n return { width, height };\n };\n\n const show: Tooltip['show'] = (x, y, content) => {\n if (disposed) return;\n\n transitionToken += 1;\n clearPendingTransitions();\n\n const wasHidden = isCurrentlyHidden();\n\n root.innerHTML = content;\n\n const dx = 12;\n const dy = 12;\n const pad = 8;\n\n // Ensure it participates in layout for measurement & positioning.\n // Keep it hidden from paint until we finish placing it.\n root.style.display = 'block';\n root.style.visibility = 'hidden';\n\n const { width: w, height: h } = measureSize();\n\n const containerW = container.clientWidth;\n const containerH = container.clientHeight;\n\n let left = x + dx;\n let top = y + dy;\n\n if (left + w > containerW - pad) left = x - dx - w;\n if (top + h > containerH - pad) top = y - dy - h;\n\n left = clamp(left, pad, containerW - pad - w);\n top = clamp(top, pad, containerH - pad - h);\n\n root.style.left = `${left}px`;\n root.style.top = `${top}px`;\n\n root.style.visibility = 'visible';\n\n if (wasHidden) {\n // Only fade in on hidden -> visible transition.\n root.style.opacity = '0';\n const myToken = transitionToken;\n rafId = window.requestAnimationFrame(() => {\n rafId = null;\n if (disposed) return;\n if (myToken !== transitionToken) return;\n root.style.opacity = '1';\n });\n } else {\n // Frequent updates while visible should not restart the fade.\n // Also cancels an in-progress hide fade-out by restoring opacity.\n root.style.opacity = '1';\n }\n };\n\n const hide: Tooltip['hide'] = () => {\n if (disposed) return;\n\n transitionToken += 1;\n clearPendingTransitions();\n\n // If it's already hidden, keep idempotent and avoid extra work.\n if (root.style.display === 'none' || root.style.visibility === 'hidden') {\n root.style.opacity = '0';\n root.style.visibility = 'hidden';\n root.style.display = 'none';\n return;\n }\n\n root.style.opacity = '0';\n\n const myToken = transitionToken;\n hideTimeoutId = window.setTimeout(() => {\n hideTimeoutId = null;\n if (disposed) return;\n if (myToken !== transitionToken) return;\n root.style.visibility = 'hidden';\n root.style.display = 'none';\n }, fadeMs + 50);\n };\n\n const dispose: Tooltip['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n try {\n clearPendingTransitions();\n root.remove();\n } finally {\n if (previousInlinePosition !== null) {\n container.style.position = previousInlinePosition;\n }\n }\n };\n\n return { show, hide, dispose };\n}\n\n","import type { TooltipParams } from '../config/types';\n\nconst EM_DASH = '\\u2014';\n\nfunction escapeHtml(text: string): string {\n // Escapes text for safe insertion into HTML text/attribute contexts.\n // (We only use it for text nodes here, but keeping it generic is fine.)\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction formatNumber(value: number): string {\n if (!Number.isFinite(value)) return EM_DASH;\n\n // Normalize -0 to 0 for display stability.\n const normalized = Object.is(value, -0) ? 0 : value;\n\n // Maximum 2 decimal places, trim trailing zeros.\n const fixed = normalized.toFixed(2);\n const trimmed = fixed.replace(/\\.?0+$/, '');\n return trimmed === '-0' ? '0' : trimmed;\n}\n\nfunction resolveSeriesName(params: TooltipParams): string {\n const trimmed = params.seriesName.trim();\n return trimmed.length > 0 ? trimmed : `Series ${params.seriesIndex + 1}`;\n}\n\nfunction sanitizeCssColor(value: string): string {\n // Tooltip content is assigned via innerHTML, so treat color as untrusted.\n // Allow only common safe color syntaxes; otherwise fall back.\n const s = value.trim();\n if (s.length === 0) return '#888';\n\n // Hex: #RGB, #RRGGBB, #RRGGBBAA\n if (/^#[0-9a-fA-F]{3}$/.test(s)) return s;\n if (/^#[0-9a-fA-F]{6}$/.test(s)) return s;\n if (/^#[0-9a-fA-F]{8}$/.test(s)) return s;\n\n // rgb()/rgba() numeric forms (commas or space-separated with optional slash alpha)\n if (\n /^rgba?\\(\\s*\\d{1,3}\\s*(?:,\\s*|\\s+)\\d{1,3}\\s*(?:,\\s*|\\s+)\\d{1,3}(?:\\s*(?:,\\s*|\\/\\s*)(?:0|1|0?\\.\\d+))?\\s*\\)$/.test(\n s,\n )\n ) {\n return s;\n }\n\n // Named colors: basic CSS ident (letters only) to avoid weird tokens.\n if (/^[a-zA-Z]+$/.test(s)) return s;\n\n return '#888';\n}\n\nfunction formatRowHtml(params: TooltipParams, valueText: string): string {\n const safeName = escapeHtml(resolveSeriesName(params));\n const safeValue = escapeHtml(valueText);\n const safeColor = escapeHtml(sanitizeCssColor(params.color));\n\n return [\n '<div style=\"display:flex;align-items:center;justify-content:space-between;gap:12px;\">',\n '<span style=\"display:flex;align-items:center;gap:8px;min-width:0;\">',\n `<span style=\"width:8px;height:8px;border-radius:999px;flex:0 0 auto;background-color:${safeColor};\"></span>`,\n `<span style=\"overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\">${safeName}</span>`,\n '</span>',\n `<span style=\"font-variant-numeric:tabular-nums;white-space:nowrap;\">${safeValue}</span>`,\n '</div>',\n ].join('');\n}\n\n/**\n * Default tooltip formatter for item mode.\n * Returns a compact single-row HTML snippet: dot + series name + y value.\n */\nexport function formatTooltipItem(params: TooltipParams): string {\n return formatRowHtml(params, formatNumber(params.value[1]));\n}\n\n/**\n * Default tooltip formatter for axis mode.\n * Renders an x header line then one row per series with the y value.\n */\nexport function formatTooltipAxis(params: TooltipParams[]): string {\n if (params.length === 0) return '';\n\n const xText = `x: ${formatNumber(params[0].value[0])}`;\n const header = `<div style=\"margin:0 0 6px 0;font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap;\">${escapeHtml(\n xText,\n )}</div>`;\n\n const rows = params\n .map((p) => formatRowHtml(p, formatNumber(p.value[1])))\n .join('<div style=\"height:4px;\"></div>');\n\n return `${header}${rows}`;\n}\n\n","import type { EasingFunction } from '../utils/easing';\n\nexport type AnimationId = symbol;\n\nexport interface AnimationController {\n animate(\n from: number,\n to: number,\n duration: number,\n easing: EasingFunction,\n onUpdate: (value: number) => void,\n onComplete?: () => void,\n ): AnimationId;\n animate(\n from: ReadonlyArray<number>,\n to: ReadonlyArray<number>,\n duration: number,\n easing: EasingFunction,\n onUpdate: (value: ReadonlyArray<number>) => void,\n onComplete?: () => void,\n ): AnimationId;\n\n cancel(animationId: AnimationId): void;\n cancelAll(): void;\n\n /**\n * Progresses all active animations to `timestamp` (ms).\n * Intended to be called once per frame by the caller (e.g. a render loop).\n */\n update(timestamp: number): void;\n}\n\ntype ScalarAnimation = Readonly<{\n kind: 'scalar';\n from: number;\n to: number;\n duration: number;\n easing: EasingFunction;\n onUpdate: (value: number) => void;\n onComplete?: () => void;\n startTime: number | null;\n}>;\n\ntype ArrayAnimation = Readonly<{\n kind: 'array';\n from: ReadonlyArray<number>;\n to: ReadonlyArray<number>;\n duration: number;\n easing: EasingFunction;\n onUpdate: (value: ReadonlyArray<number>) => void;\n onComplete?: () => void;\n startTime: number | null;\n out: number[];\n}>;\n\ntype AnimationInternal = ScalarAnimation | ArrayAnimation;\n\nconst normalizeDurationMs = (duration: number): number =>\n Number.isFinite(duration) ? duration : 0;\n\nconst normalizeTimestampMs = (timestamp: number): number | null =>\n Number.isFinite(timestamp) ? timestamp : null;\n\nexport function createAnimationController(): AnimationController {\n const animations = new Map<AnimationId, AnimationInternal>();\n\n function animate(\n from: number | ReadonlyArray<number>,\n to: number | ReadonlyArray<number>,\n duration: number,\n easing: EasingFunction,\n onUpdate: ((value: number) => void) | ((value: ReadonlyArray<number>) => void),\n onComplete?: () => void,\n ): AnimationId {\n const id: AnimationId = Symbol('Animation');\n\n if (Array.isArray(from) || Array.isArray(to)) {\n if (!Array.isArray(from) || !Array.isArray(to)) {\n throw new Error('Array animation requires both \"from\" and \"to\" to be arrays');\n }\n if (from.length !== to.length) {\n throw new Error(\n `Array animation length mismatch: from.length=${from.length}, to.length=${to.length}`,\n );\n }\n\n const out = new Array<number>(from.length);\n animations.set(id, {\n kind: 'array',\n from,\n to,\n duration,\n easing,\n onUpdate: onUpdate as (value: ReadonlyArray<number>) => void,\n onComplete,\n startTime: null,\n out,\n });\n return id;\n }\n\n animations.set(id, {\n kind: 'scalar',\n from: from as number,\n to: to as number,\n duration,\n easing,\n onUpdate: onUpdate as (value: number) => void,\n onComplete,\n startTime: null,\n });\n return id;\n }\n\n function cancel(animationId: AnimationId): void {\n animations.delete(animationId);\n }\n\n function cancelAll(): void {\n animations.clear();\n }\n\n function update(timestamp: number): void {\n const ts = normalizeTimestampMs(timestamp);\n if (ts === null) return;\n\n // Snapshot IDs to tolerate cancellation during callbacks and to ensure\n // animations started during callbacks don't run until next tick.\n const ids = Array.from(animations.keys());\n for (const id of ids) {\n const anim = animations.get(id);\n if (!anim) continue; // cancelled\n\n const startTime = anim.startTime ?? ts;\n if (anim.startTime === null) {\n // Mutate by replacement to keep internal entries immutable-by-type.\n animations.set(id, { ...anim, startTime });\n }\n\n const durationMs = normalizeDurationMs(anim.duration);\n const elapsed = Math.max(0, ts - startTime);\n\n const shouldComplete = durationMs <= 0 || elapsed >= durationMs;\n const rawT = durationMs <= 0 ? 1 : elapsed / durationMs;\n const t = shouldComplete ? 1 : anim.easing(rawT);\n\n if (anim.kind === 'scalar') {\n const value = anim.from + (anim.to - anim.from) * t;\n anim.onUpdate(value);\n\n // Cancellation during callback should prevent onComplete.\n if (!animations.has(id)) continue;\n } else {\n const n = anim.out.length;\n for (let i = 0; i < n; i++) {\n const a = anim.from[i] ?? 0;\n const b = anim.to[i] ?? 0;\n anim.out[i] = a + (b - a) * t;\n }\n anim.onUpdate(anim.out);\n\n // Cancellation during callback should prevent onComplete.\n if (!animations.has(id)) continue;\n }\n\n if (shouldComplete) {\n anim.onComplete?.();\n // If it was cancelled inside onComplete, deletion is harmless.\n animations.delete(id);\n }\n }\n }\n\n return {\n animate: animate as AnimationController['animate'],\n cancel,\n cancelAll,\n update,\n };\n}\n","export type EasingFunction = (t: number) => number;\n\nimport type { AnimationConfig } from '../config/types';\n\nexport type EasingName = NonNullable<AnimationConfig['easing']>;\n\nconst clamp01 = (t: number): number => {\n if (Number.isNaN(t)) return 0;\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n return t;\n};\n\nexport function easeLinear(t: number): number {\n return clamp01(t);\n}\n\nexport function easeCubicOut(t: number): number {\n const x = clamp01(t);\n const inv = 1 - x;\n return 1 - inv * inv * inv;\n}\n\nexport function easeCubicInOut(t: number): number {\n const x = clamp01(t);\n // Standard easeInOutCubic:\n // - accelerating cubic for the first half\n // - decelerating cubic for the second half\n if (x < 0.5) return 4 * x * x * x;\n const y = -2 * x + 2;\n return 1 - (y * y * y) / 2;\n}\n\nexport function easeBounceOut(t: number): number {\n const x = clamp01(t);\n // Standard easeOutBounce (Robert Penner) piecewise approximation.\n const n1 = 7.5625;\n const d1 = 2.75;\n\n if (x < 1 / d1) {\n return n1 * x * x;\n }\n if (x < 2 / d1) {\n const a = x - 1.5 / d1;\n return n1 * a * a + 0.75;\n }\n if (x < 2.5 / d1) {\n const a = x - 2.25 / d1;\n return n1 * a * a + 0.9375;\n }\n\n const a = x - 2.625 / d1;\n return n1 * a * a + 0.984375;\n}\n\nexport function getEasing(\n name: AnimationConfig['easing'] | null | undefined,\n): EasingFunction {\n switch (name) {\n case 'linear':\n return easeLinear;\n case 'cubicOut':\n return easeCubicOut;\n case 'cubicInOut':\n return easeCubicInOut;\n case 'bounceOut':\n return easeBounceOut;\n default:\n return easeLinear;\n }\n}\n","import type {\n ResolvedAreaSeriesConfig,\n ResolvedBarSeriesConfig,\n ResolvedChartGPUOptions,\n ResolvedPieSeriesConfig,\n} from '../config/OptionResolver';\nimport type { AnimationConfig, DataPoint, DataPointTuple, PieCenter, PieRadius } from '../config/types';\nimport { createDataStore } from '../data/createDataStore';\nimport { sampleSeriesDataPoints } from '../data/sampleSeries';\nimport { createAxisRenderer } from '../renderers/createAxisRenderer';\nimport { createGridRenderer } from '../renderers/createGridRenderer';\nimport type { GridArea } from '../renderers/createGridRenderer';\nimport { createAreaRenderer } from '../renderers/createAreaRenderer';\nimport { createLineRenderer } from '../renderers/createLineRenderer';\nimport { createBarRenderer } from '../renderers/createBarRenderer';\nimport { createScatterRenderer } from '../renderers/createScatterRenderer';\nimport { createPieRenderer } from '../renderers/createPieRenderer';\nimport { createCrosshairRenderer } from '../renderers/createCrosshairRenderer';\nimport type { CrosshairRenderOptions } from '../renderers/createCrosshairRenderer';\nimport { createHighlightRenderer } from '../renderers/createHighlightRenderer';\nimport type { HighlightPoint } from '../renderers/createHighlightRenderer';\nimport { createEventManager } from '../interaction/createEventManager';\nimport type { ChartGPUEventPayload } from '../interaction/createEventManager';\nimport { createInsideZoom } from '../interaction/createInsideZoom';\nimport { createZoomState } from '../interaction/createZoomState';\nimport type { ZoomRange, ZoomState } from '../interaction/createZoomState';\nimport { findNearestPoint } from '../interaction/findNearestPoint';\nimport { findPointsAtX } from '../interaction/findPointsAtX';\nimport { findPieSlice } from '../interaction/findPieSlice';\nimport { createLinearScale } from '../utils/scales';\nimport type { LinearScale } from '../utils/scales';\nimport { parseCssColorToGPUColor, parseCssColorToRgba01 } from '../utils/colors';\nimport { createTextOverlay } from '../components/createTextOverlay';\nimport type { TextOverlay, TextOverlayAnchor } from '../components/createTextOverlay';\nimport { createLegend } from '../components/createLegend';\nimport type { Legend } from '../components/createLegend';\nimport { createTooltip } from '../components/createTooltip';\nimport type { Tooltip } from '../components/createTooltip';\nimport type { TooltipParams } from '../config/types';\nimport { formatTooltipAxis, formatTooltipItem } from '../components/formatTooltip';\nimport { createAnimationController } from './createAnimationController';\nimport type { AnimationId } from './createAnimationController';\nimport { getEasing } from '../utils/easing';\nimport type { EasingFunction } from '../utils/easing';\n\nexport interface GPUContextLike {\n readonly device: GPUDevice | null;\n readonly canvas: HTMLCanvasElement | null;\n readonly canvasContext: GPUCanvasContext | null;\n readonly preferredFormat: GPUTextureFormat | null;\n readonly initialized: boolean;\n}\n\nexport interface RenderCoordinator {\n setOptions(resolvedOptions: ResolvedChartGPUOptions): void;\n /**\n * Appends new points to a cartesian series’ runtime data without requiring a full `setOptions(...)`\n * resolver pass.\n *\n * Appends are coalesced and flushed once per render frame.\n */\n appendData(seriesIndex: number, newPoints: ReadonlyArray<DataPoint>): void;\n /**\n * Gets the current “interaction x” in domain units (or `null` when inactive).\n *\n * This is derived from pointer movement inside the plot grid and can also be driven\n * externally via `setInteractionX(...)` (e.g. chart sync).\n */\n getInteractionX(): number | null;\n /**\n * Drives the chart’s crosshair + tooltip from a domain-space x value.\n *\n * Passing `null` clears the interaction (hides crosshair/tooltip).\n */\n setInteractionX(x: number | null, source?: unknown): void;\n /**\n * Subscribes to interaction x changes (domain units).\n *\n * Returns an unsubscribe function.\n */\n onInteractionXChange(callback: (x: number | null, source?: unknown) => void): () => void;\n /**\n * Returns the current percent-space zoom window (or `null` when zoom is disabled).\n */\n getZoomRange(): Readonly<{ start: number; end: number }> | null;\n /**\n * Sets the percent-space zoom window.\n *\n * No-op when zoom is disabled.\n */\n setZoomRange(start: number, end: number): void;\n /**\n * Subscribes to zoom window changes (percent space).\n *\n * Returns an unsubscribe function.\n */\n onZoomRangeChange(cb: (range: Readonly<{ start: number; end: number }>) => void): () => void;\n render(): void;\n dispose(): void;\n}\n\nexport type RenderCoordinatorCallbacks = Readonly<{\n /**\n * Optional hook for render-on-demand systems (like `ChartGPU`) to re-render when\n * interaction state changes (e.g. crosshair on pointer move).\n */\n readonly onRequestRender?: () => void;\n}>;\n\ntype Bounds = Readonly<{ xMin: number; xMax: number; yMin: number; yMax: number }>;\n\nconst DEFAULT_TARGET_FORMAT: GPUTextureFormat = 'bgra8unorm';\nconst DEFAULT_TICK_COUNT: number = 5;\nconst DEFAULT_TICK_LENGTH_CSS_PX: number = 6;\nconst LABEL_PADDING_CSS_PX = 4;\nconst DEFAULT_CROSSHAIR_LINE_WIDTH_CSS_PX = 1;\nconst DEFAULT_HIGHLIGHT_SIZE_CSS_PX = 4;\n\n// Story 5.17: CPU-side update interpolation can be expensive for very large series.\n// We still animate domains for large series, but skip per-point y interpolation past this cap.\nconst MAX_ANIMATED_POINTS_PER_SERIES = 20_000;\n\nconst assertUnreachable = (value: never): never => {\n // Intentionally minimal message: this is used for compile-time exhaustiveness.\n throw new Error(`RenderCoordinator: unreachable value: ${String(value)}`);\n};\n\nconst isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p);\n\nconst getPointXY = (p: DataPoint): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(p)) return { x: p[0], y: p[1] };\n return { x: p.x, y: p.y };\n};\n\nconst computeRawBoundsFromData = (data: ReadonlyArray<DataPoint>): Bounds | null => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]!);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return null;\n }\n\n // Keep bounds usable for downstream scale derivation.\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst extendBoundsWithDataPoints = (bounds: Bounds | null, points: ReadonlyArray<DataPoint>): Bounds | null => {\n if (points.length === 0) return bounds;\n\n let b = bounds;\n if (!b) {\n // Try to seed from the appended points.\n const seeded = computeRawBoundsFromData(points);\n if (!seeded) return bounds;\n b = seeded;\n }\n\n let xMin = b.xMin;\n let xMax = b.xMax;\n let yMin = b.yMin;\n let yMax = b.yMax;\n\n for (let i = 0; i < points.length; i++) {\n const { x, y } = getPointXY(points[i]!);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n // Keep bounds usable for downstream scale derivation.\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst computeGlobalBounds = (\n series: ResolvedChartGPUOptions['series'],\n runtimeRawBoundsByIndex?: ReadonlyArray<Bounds | null> | null\n): Bounds => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let s = 0; s < series.length; s++) {\n const seriesConfig = series[s];\n // Pie series are non-cartesian; they don't participate in x/y bounds.\n if (seriesConfig.type === 'pie') continue;\n\n const runtimeBoundsCandidate = runtimeRawBoundsByIndex?.[s] ?? null;\n if (runtimeBoundsCandidate) {\n const b = runtimeBoundsCandidate;\n if (\n Number.isFinite(b.xMin) &&\n Number.isFinite(b.xMax) &&\n Number.isFinite(b.yMin) &&\n Number.isFinite(b.yMax)\n ) {\n if (b.xMin < xMin) xMin = b.xMin;\n if (b.xMax > xMax) xMax = b.xMax;\n if (b.yMin < yMin) yMin = b.yMin;\n if (b.yMax > yMax) yMax = b.yMax;\n continue;\n }\n }\n\n // Prefer precomputed bounds from the original (unsampled) data when available.\n // This ensures sampling cannot affect axis auto-bounds and avoids per-render O(n) scans.\n const rawBoundsCandidate = seriesConfig.rawBounds;\n if (rawBoundsCandidate) {\n const b = rawBoundsCandidate;\n if (\n Number.isFinite(b.xMin) &&\n Number.isFinite(b.xMax) &&\n Number.isFinite(b.yMin) &&\n Number.isFinite(b.yMax)\n ) {\n if (b.xMin < xMin) xMin = b.xMin;\n if (b.xMax > xMax) xMax = b.xMax;\n if (b.yMin < yMin) yMin = b.yMin;\n if (b.yMax > yMax) yMax = b.yMax;\n continue;\n }\n }\n\n const data = seriesConfig.data;\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return { xMin: 0, xMax: 1, yMin: 0, yMax: 1 };\n }\n\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n}; \n\nconst normalizeDomain = (\n minCandidate: number,\n maxCandidate: number\n): { readonly min: number; readonly max: number } => {\n let min = minCandidate;\n let max = maxCandidate;\n\n if (!Number.isFinite(min) || !Number.isFinite(max)) {\n min = 0;\n max = 1;\n }\n\n if (min === max) {\n max = min + 1;\n } else if (min > max) {\n const t = min;\n min = max;\n max = t;\n }\n\n return { min, max };\n};\n\nconst computeGridArea = (gpuContext: GPUContextLike, options: ResolvedChartGPUOptions): GridArea => {\n const canvas = gpuContext.canvas;\n if (!canvas) throw new Error('RenderCoordinator: gpuContext.canvas is required.');\n\n return {\n left: options.grid.left,\n right: options.grid.right,\n top: options.grid.top,\n bottom: options.grid.bottom,\n canvasWidth: canvas.width,\n canvasHeight: canvas.height,\n };\n};\n\nconst rgba01ToCssRgba = (rgba: readonly [number, number, number, number]): string => {\n const r = Math.max(0, Math.min(255, Math.round(rgba[0] * 255)));\n const g = Math.max(0, Math.min(255, Math.round(rgba[1] * 255)));\n const b = Math.max(0, Math.min(255, Math.round(rgba[2] * 255)));\n const a = Math.max(0, Math.min(1, rgba[3]));\n return `rgba(${r},${g},${b},${a})`;\n};\n\nconst withAlpha = (cssColor: string, alphaMultiplier: number): string => {\n const parsed = parseCssColorToRgba01(cssColor);\n if (!parsed) return cssColor;\n const a = Math.max(0, Math.min(1, parsed[3] * alphaMultiplier));\n return rgba01ToCssRgba([parsed[0], parsed[1], parsed[2], a]);\n};\n\nconst computePlotClipRect = (\n gridArea: GridArea\n): { readonly left: number; readonly right: number; readonly top: number; readonly bottom: number } => {\n const { left, right, top, bottom, canvasWidth, canvasHeight } = gridArea;\n const dpr = window.devicePixelRatio || 1;\n\n const plotLeft = left * dpr;\n const plotRight = canvasWidth - right * dpr;\n const plotTop = top * dpr;\n const plotBottom = canvasHeight - bottom * dpr;\n\n const plotLeftClip = (plotLeft / canvasWidth) * 2.0 - 1.0;\n const plotRightClip = (plotRight / canvasWidth) * 2.0 - 1.0;\n const plotTopClip = 1.0 - (plotTop / canvasHeight) * 2.0; // flip Y\n const plotBottomClip = 1.0 - (plotBottom / canvasHeight) * 2.0; // flip Y\n\n return {\n left: plotLeftClip,\n right: plotRightClip,\n top: plotTopClip,\n bottom: plotBottomClip,\n };\n};\n\nconst clamp01 = (v: number): number => Math.min(1, Math.max(0, v));\nconst clampInt = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v | 0));\n\nconst lerp = (a: number, b: number, t01: number): number => a + (b - a) * clamp01(t01);\n\nconst lerpDomain = (\n from: { readonly min: number; readonly max: number },\n to: { readonly min: number; readonly max: number },\n t01: number\n): { readonly min: number; readonly max: number } => {\n return normalizeDomain(lerp(from.min, to.min, t01), lerp(from.max, to.max, t01));\n};\n\nconst computePlotScissorDevicePx = (\n gridArea: GridArea\n): { readonly x: number; readonly y: number; readonly w: number; readonly h: number } => {\n const dpr = window.devicePixelRatio || 1;\n const { canvasWidth, canvasHeight } = gridArea;\n\n const plotLeftDevice = gridArea.left * dpr;\n const plotRightDevice = canvasWidth - gridArea.right * dpr;\n const plotTopDevice = gridArea.top * dpr;\n const plotBottomDevice = canvasHeight - gridArea.bottom * dpr;\n\n const scissorX = clampInt(Math.floor(plotLeftDevice), 0, Math.max(0, canvasWidth));\n const scissorY = clampInt(Math.floor(plotTopDevice), 0, Math.max(0, canvasHeight));\n const scissorR = clampInt(Math.ceil(plotRightDevice), 0, Math.max(0, canvasWidth));\n const scissorB = clampInt(Math.ceil(plotBottomDevice), 0, Math.max(0, canvasHeight));\n const scissorW = Math.max(0, scissorR - scissorX);\n const scissorH = Math.max(0, scissorB - scissorY);\n\n return { x: scissorX, y: scissorY, w: scissorW, h: scissorH };\n};\n\nconst clipXToCanvasCssPx = (xClip: number, canvasCssWidth: number): number => ((xClip + 1) / 2) * canvasCssWidth;\nconst clipYToCanvasCssPx = (yClip: number, canvasCssHeight: number): number => ((1 - yClip) / 2) * canvasCssHeight;\n\ntype TuplePoint = DataPointTuple;\ntype ObjectPoint = Readonly<{ x: number; y: number; size?: number }>;\n\nconst isTuplePoint = (p: DataPoint): p is TuplePoint => Array.isArray(p);\nconst isTupleDataArray = (data: ReadonlyArray<DataPoint>): data is ReadonlyArray<TuplePoint> =>\n data.length > 0 && isTuplePoint(data[0]!);\n\nconst isMonotonicNonDecreasingFiniteX = (data: ReadonlyArray<DataPoint>, isTuple: boolean): boolean => {\n let prevX = Number.NEGATIVE_INFINITY;\n\n if (isTuple) {\n const tupleData = data as ReadonlyArray<TuplePoint>;\n for (let i = 0; i < tupleData.length; i++) {\n const x = tupleData[i][0];\n if (!Number.isFinite(x)) return false;\n if (x < prevX) return false;\n prevX = x;\n }\n return true;\n }\n\n const objectData = data as ReadonlyArray<ObjectPoint>;\n for (let i = 0; i < objectData.length; i++) {\n const x = objectData[i].x;\n if (!Number.isFinite(x)) return false;\n if (x < prevX) return false;\n prevX = x;\n }\n return true;\n};\n\nconst lowerBoundXTuple = (data: ReadonlyArray<TuplePoint>, xTarget: number): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid][0];\n if (x < xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst upperBoundXTuple = (data: ReadonlyArray<TuplePoint>, xTarget: number): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid][0];\n if (x <= xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst lowerBoundXObject = (data: ReadonlyArray<ObjectPoint>, xTarget: number): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid].x;\n if (x < xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst upperBoundXObject = (data: ReadonlyArray<ObjectPoint>, xTarget: number): number => {\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const x = data[mid].x;\n if (x <= xTarget) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst sliceVisibleRangeByX = (data: ReadonlyArray<DataPoint>, xMin: number, xMax: number): ReadonlyArray<DataPoint> => {\n const n = data.length;\n if (n === 0) return data;\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax)) return data;\n\n const isTuple = isTupleDataArray(data);\n const canBinarySearch = isMonotonicNonDecreasingFiniteX(data, isTuple);\n\n if (canBinarySearch) {\n const lo = isTuple\n ? lowerBoundXTuple(data as ReadonlyArray<TuplePoint>, xMin)\n : lowerBoundXObject(data as ReadonlyArray<ObjectPoint>, xMin);\n const hi = isTuple\n ? upperBoundXTuple(data as ReadonlyArray<TuplePoint>, xMax)\n : upperBoundXObject(data as ReadonlyArray<ObjectPoint>, xMax);\n\n if (lo <= 0 && hi >= n) return data;\n if (hi <= lo) return [];\n return data.slice(lo, hi);\n }\n\n // Safe fallback: linear filter (preserves order, ignores non-finite x).\n const out: DataPoint[] = [];\n for (let i = 0; i < n; i++) {\n const p = data[i]!;\n const { x } = getPointXY(p);\n if (!Number.isFinite(x)) continue;\n if (x >= xMin && x <= xMax) out.push(p);\n }\n return out;\n};\n\nconst parseNumberOrPercent = (value: number | string, basis: number): number | null => {\n if (typeof value === 'number') return Number.isFinite(value) ? value : null;\n if (typeof value !== 'string') return null;\n\n const s = value.trim();\n if (s.length === 0) return null;\n\n if (s.endsWith('%')) {\n const pct = Number.parseFloat(s.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return (pct / 100) * basis;\n }\n\n // Be permissive: allow numeric strings like \"120\".\n const n = Number.parseFloat(s);\n return Number.isFinite(n) ? n : null;\n};\n\nconst resolvePieCenterPlotCss = (\n center: PieCenter | undefined,\n plotWidthCss: number,\n plotHeightCss: number\n): { readonly x: number; readonly y: number } => {\n const xRaw = center?.[0] ?? '50%';\n const yRaw = center?.[1] ?? '50%';\n\n const x = parseNumberOrPercent(xRaw, plotWidthCss);\n const y = parseNumberOrPercent(yRaw, plotHeightCss);\n\n return {\n x: Number.isFinite(x) ? x! : plotWidthCss * 0.5,\n y: Number.isFinite(y) ? y! : plotHeightCss * 0.5,\n };\n};\n\nconst isPieRadiusTuple = (\n radius: PieRadius\n): radius is readonly [inner: number | string, outer: number | string] => Array.isArray(radius);\n\nconst resolvePieRadiiCss = (\n radius: PieRadius | undefined,\n maxRadiusCss: number\n): { readonly inner: number; readonly outer: number } => {\n // Default similar to common chart libs (mirrors `createPieRenderer.ts`).\n if (radius == null) return { inner: 0, outer: maxRadiusCss * 0.7 };\n\n if (isPieRadiusTuple(radius)) {\n const inner = parseNumberOrPercent(radius[0], maxRadiusCss);\n const outer = parseNumberOrPercent(radius[1], maxRadiusCss);\n const innerCss = Math.max(0, Number.isFinite(inner) ? inner! : 0);\n const outerCss = Math.max(innerCss, Number.isFinite(outer) ? outer! : maxRadiusCss * 0.7);\n return { inner: innerCss, outer: Math.min(maxRadiusCss, outerCss) };\n }\n\n const outer = parseNumberOrPercent(radius, maxRadiusCss);\n const outerCss = Math.max(0, Number.isFinite(outer) ? outer! : maxRadiusCss * 0.7);\n return { inner: 0, outer: Math.min(maxRadiusCss, outerCss) };\n};\n\nconst DEFAULT_MAX_TICK_FRACTION_DIGITS = 6;\n\nconst computeMaxFractionDigitsFromStep = (tickStep: number, cap: number = DEFAULT_MAX_TICK_FRACTION_DIGITS): number => {\n const stepAbs = Math.abs(tickStep);\n if (!Number.isFinite(stepAbs) || stepAbs === 0) return 0;\n\n // Prefer “clean” decimal representations (e.g. 2.5, 0.25, 0.125) without relying on magnitude alone.\n // We accept floating-point noise and cap the search to keep formatting reasonable.\n for (let d = 0; d <= cap; d++) {\n const scaled = stepAbs * 10 ** d;\n const rounded = Math.round(scaled);\n const err = Math.abs(scaled - rounded);\n const tol = 1e-9 * Math.max(1, Math.abs(scaled));\n if (err <= tol) return d;\n }\n\n // Fallback for repeating decimals (e.g. 1/3): show a small number of digits based on magnitude.\n // The +1 nudges values like 0.333.. towards 2 decimals rather than 1.\n return Math.max(0, Math.min(cap, Math.ceil(-Math.log10(stepAbs)) + 1));\n};\n\nconst createTickFormatter = (tickStep: number): Intl.NumberFormat => {\n const maximumFractionDigits = computeMaxFractionDigitsFromStep(tickStep);\n return new Intl.NumberFormat(undefined, { maximumFractionDigits });\n};\n\nconst formatTickValue = (nf: Intl.NumberFormat, v: number): string | null => {\n if (!Number.isFinite(v)) return null;\n // Avoid displaying \"-0\" from floating-point artifacts.\n const normalized = Math.abs(v) < 1e-12 ? 0 : v;\n const formatted = nf.format(normalized);\n // Guard against unexpected output like \"NaN\" even after the finite check (defensive).\n return formatted === 'NaN' ? null : formatted;\n};\n\nconst computeBaseXDomain = (\n options: ResolvedChartGPUOptions,\n runtimeRawBoundsByIndex?: ReadonlyArray<Bounds | null> | null\n): { readonly min: number; readonly max: number } => {\n const bounds = computeGlobalBounds(options.series, runtimeRawBoundsByIndex);\n const baseMin = options.xAxis.min ?? bounds.xMin;\n const baseMax = options.xAxis.max ?? bounds.xMax;\n return normalizeDomain(baseMin, baseMax);\n};\n\nconst computeBaseYDomain = (\n options: ResolvedChartGPUOptions,\n runtimeRawBoundsByIndex?: ReadonlyArray<Bounds | null> | null\n): { readonly min: number; readonly max: number } => {\n const bounds = computeGlobalBounds(options.series, runtimeRawBoundsByIndex);\n const yMin = options.yAxis.min ?? bounds.yMin;\n const yMax = options.yAxis.max ?? bounds.yMax;\n return normalizeDomain(yMin, yMax);\n};\n\nconst computeVisibleXDomain = (\n baseXDomain: { readonly min: number; readonly max: number },\n zoomRange?: ZoomRange | null\n): { readonly min: number; readonly max: number; readonly spanFraction: number } => {\n if (!zoomRange) return { ...baseXDomain, spanFraction: 1 };\n const span = baseXDomain.max - baseXDomain.min;\n if (!Number.isFinite(span) || span === 0) return { ...baseXDomain, spanFraction: 1 };\n\n const start = zoomRange.start;\n const end = zoomRange.end;\n const xMin = baseXDomain.min + (start / 100) * span;\n const xMax = baseXDomain.min + (end / 100) * span;\n const normalized = normalizeDomain(xMin, xMax);\n\n const fractionRaw = (end - start) / 100;\n const spanFraction = Number.isFinite(fractionRaw) ? Math.max(0, Math.min(1, fractionRaw)) : 1;\n return { min: normalized.min, max: normalized.max, spanFraction };\n};\n\ntype IntroPhase = 'pending' | 'running' | 'done';\n\nconst resolveAnimationConfig = (\n animation: ResolvedChartGPUOptions['animation']\n):\n | {\n readonly durationMs: number;\n readonly delayMs: number;\n readonly easing: EasingFunction;\n }\n | null => {\n if (animation === false || animation == null) return null;\n\n const cfg: AnimationConfig | null = animation === true ? {} : animation;\n if (!cfg) return null;\n\n const durationMsRaw = cfg.duration ?? 300;\n const delayMsRaw = cfg.delay ?? 0;\n\n const durationMs = Number.isFinite(durationMsRaw) ? Math.max(0, durationMsRaw) : 300;\n const delayMs = Number.isFinite(delayMsRaw) ? Math.max(0, delayMsRaw) : 0;\n\n return {\n durationMs,\n delayMs,\n easing: getEasing(cfg.easing),\n };\n};\n\nconst resolveIntroAnimationConfig = (animation: ResolvedChartGPUOptions['animation']) => resolveAnimationConfig(animation);\nconst resolveUpdateAnimationConfig = (animation: ResolvedChartGPUOptions['animation']) => resolveAnimationConfig(animation);\n\nconst computeBaselineForBarsFromData = (seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>): number => {\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let s = 0; s < seriesConfigs.length; s++) {\n const data = seriesConfigs[s]!.data;\n for (let i = 0; i < data.length; i++) {\n const { y } = getPointXY(data[i]!);\n if (!Number.isFinite(y)) continue;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n }\n\n if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) return 0;\n if (yMin <= 0 && 0 <= yMax) return 0;\n return Math.abs(yMin) < Math.abs(yMax) ? yMin : yMax;\n};\n\nconst computeBaselineForBarsFromAxis = (\n seriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n yScale: LinearScale,\n plotClipRect: Readonly<{ top: number; bottom: number }>\n): number => {\n const yDomainA = yScale.invert(plotClipRect.bottom);\n const yDomainB = yScale.invert(plotClipRect.top);\n const yMin = Math.min(yDomainA, yDomainB);\n const yMax = Math.max(yDomainA, yDomainB);\n\n if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return computeBaselineForBarsFromData(seriesConfigs);\n }\n\n if (yMin <= 0 && 0 <= yMax) return 0;\n if (yMin > 0) return yMin;\n if (yMax < 0) return yMax;\n return computeBaselineForBarsFromData(seriesConfigs);\n};\n\nconst createAnimatedBarYScale = (\n baseYScale: LinearScale,\n plotClipRect: Readonly<{ top: number; bottom: number }>,\n barSeriesConfigs: ReadonlyArray<ResolvedBarSeriesConfig>,\n progress01: number\n): LinearScale => {\n const p = clamp01(progress01);\n if (p >= 1) return baseYScale;\n\n const baselineDomain = computeBaselineForBarsFromAxis(barSeriesConfigs, baseYScale, plotClipRect);\n const baselineClip = baseYScale.scale(baselineDomain);\n\n const wrapper: LinearScale = {\n domain(min: number, max: number) {\n baseYScale.domain(min, max);\n return wrapper;\n },\n range(min: number, max: number) {\n baseYScale.range(min, max);\n return wrapper;\n },\n scale(value: number) {\n const v = baseYScale.scale(value);\n if (!Number.isFinite(v) || !Number.isFinite(baselineClip)) return v;\n return baselineClip + (v - baselineClip) * p;\n },\n invert(pixel: number) {\n return baseYScale.invert(pixel);\n },\n };\n\n return wrapper;\n};\n\nexport function createRenderCoordinator(\n gpuContext: GPUContextLike,\n options: ResolvedChartGPUOptions,\n callbacks?: RenderCoordinatorCallbacks\n): RenderCoordinator {\n if (!gpuContext.initialized) {\n throw new Error('RenderCoordinator: gpuContext must be initialized.');\n }\n const device = gpuContext.device;\n if (!device) {\n throw new Error('RenderCoordinator: gpuContext.device is required.');\n }\n if (!gpuContext.canvas) {\n throw new Error('RenderCoordinator: gpuContext.canvas is required.');\n }\n if (!gpuContext.canvasContext) {\n throw new Error('RenderCoordinator: gpuContext.canvasContext is required.');\n }\n\n const targetFormat = gpuContext.preferredFormat ?? DEFAULT_TARGET_FORMAT;\n const overlayContainer = gpuContext.canvas.parentElement;\n const overlay: TextOverlay | null = overlayContainer ? createTextOverlay(overlayContainer) : null;\n const legend: Legend | null = overlayContainer ? createLegend(overlayContainer, 'right') : null;\n\n let disposed = false;\n let currentOptions: ResolvedChartGPUOptions = options;\n let lastSeriesCount = options.series.length;\n\n // Story 5.16: initial-load intro animation (series marks only).\n let introPhase: IntroPhase = 'pending';\n let introProgress01 = 0;\n const introAnimController = createAnimationController();\n let introAnimId: AnimationId | null = null;\n\n // Story 5.17 (step 1): data update transition state (snapshots only; interpolation occurs later).\n type UpdateTransitionSnapshot = Readonly<{\n readonly xBaseDomain: { readonly min: number; readonly max: number };\n readonly xVisibleDomain: { readonly min: number; readonly max: number };\n readonly yBaseDomain: { readonly min: number; readonly max: number };\n readonly series: ResolvedChartGPUOptions['series'];\n }>;\n\n type UpdateTransition = Readonly<{\n readonly from: UpdateTransitionSnapshot;\n readonly to: UpdateTransitionSnapshot;\n }>;\n\n let hasRenderedOnce = false;\n const updateAnimController = createAnimationController();\n let updateAnimId: AnimationId | null = null;\n let updateProgress01 = 1;\n let updateTransition: UpdateTransition | null = null;\n\n type UpdateInterpolationCaches = Readonly<{\n readonly cartesianDataBySeriesIndex: Array<DataPoint[] | null>;\n readonly pieDataBySeriesIndex: Array<ResolvedPieSeriesConfig['data'] | null>;\n }>;\n\n const updateInterpolationCaches: UpdateInterpolationCaches = {\n cartesianDataBySeriesIndex: [],\n pieDataBySeriesIndex: [],\n };\n\n const resetUpdateInterpolationCaches = (): void => {\n updateInterpolationCaches.cartesianDataBySeriesIndex.length = 0;\n updateInterpolationCaches.pieDataBySeriesIndex.length = 0;\n };\n\n const interpolateCartesianSeriesDataByIndex = (\n fromData: ReadonlyArray<DataPoint>,\n toData: ReadonlyArray<DataPoint>,\n t01: number,\n cache: DataPoint[] | null\n ): DataPoint[] | null => {\n if (fromData.length !== toData.length) return null;\n const n = toData.length;\n if (n === 0) return cache ?? [];\n\n const out =\n cache && cache.length === n\n ? cache\n : (() => {\n const created: DataPoint[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const pTo = toData[i]!;\n const { x } = getPointXY(pTo);\n const size = isTupleDataPoint(pTo) ? pTo[2] : (pTo as any)?.size;\n created[i] = isTupleDataPoint(pTo)\n ? (size == null ? ([x, 0] as const) : ([x, 0, size] as const))\n : (size == null ? ({ x, y: 0 } as const) : ({ x, y: 0, size } as const));\n }\n return created;\n })();\n\n const t = clamp01(t01);\n for (let i = 0; i < n; i++) {\n const yFrom = getPointXY(fromData[i]!).y;\n const yTo = getPointXY(toData[i]!).y;\n const y = Number.isFinite(yFrom) && Number.isFinite(yTo) ? lerp(yFrom, yTo, t) : yTo;\n const p = out[i]!;\n if (isTupleDataPoint(p)) {\n (p as unknown as number[])[1] = y;\n } else {\n (p as any).y = y;\n }\n }\n\n return out;\n };\n\n const interpolatePieSeriesByIndex = (\n fromSeries: ResolvedPieSeriesConfig,\n toSeries: ResolvedPieSeriesConfig,\n t01: number,\n cache: ResolvedPieSeriesConfig['data'] | null\n ): ResolvedPieSeriesConfig => {\n const fromData = fromSeries.data;\n const toData = toSeries.data;\n if (fromData.length !== toData.length) return toSeries;\n\n const n = toData.length;\n const out =\n cache && cache.length === n\n ? cache\n : (() => {\n const created: any[] = new Array(n);\n for (let i = 0; i < n; i++) {\n // Preserve name/color from \"to\"; patch value per frame.\n created[i] = { ...toData[i]!, value: 0 };\n }\n return created as ResolvedPieSeriesConfig['data'];\n })();\n\n const t = clamp01(t01);\n for (let i = 0; i < n; i++) {\n const vFrom = (fromData[i] as any)?.value;\n const vTo = (toData[i] as any)?.value;\n const next =\n typeof vFrom === 'number' && typeof vTo === 'number' && Number.isFinite(vFrom) && Number.isFinite(vTo)\n ? Math.max(0, lerp(vFrom, vTo, t))\n : typeof vTo === 'number' && Number.isFinite(vTo)\n ? vTo\n : 0;\n (out[i] as any).value = next;\n }\n\n return { ...toSeries, data: out };\n };\n\n const interpolateSeriesForUpdate = (\n fromSeries: ResolvedChartGPUOptions['series'],\n toSeries: ResolvedChartGPUOptions['series'],\n t01: number,\n caches: UpdateInterpolationCaches | null\n ): ResolvedChartGPUOptions['series'] => {\n if (fromSeries.length !== toSeries.length) return toSeries;\n\n const out: ResolvedChartGPUOptions['series'][number][] = new Array(toSeries.length);\n\n for (let i = 0; i < toSeries.length; i++) {\n const a = fromSeries[i]!;\n const b = toSeries[i]!;\n\n if (a.type !== b.type) {\n out[i] = b;\n continue;\n }\n\n if (b.type === 'pie') {\n const cache = caches?.pieDataBySeriesIndex[i] ?? null;\n const animated = interpolatePieSeriesByIndex(a as ResolvedPieSeriesConfig, b as ResolvedPieSeriesConfig, t01, cache);\n if (caches) caches.pieDataBySeriesIndex[i] = animated.data as any;\n out[i] = animated;\n continue;\n }\n\n // Cartesian series: interpolate y-values by index. Keep x from \"to\".\n const aAny = a as unknown as { readonly data: ReadonlyArray<DataPoint> };\n const bAny = b as unknown as { readonly data: ReadonlyArray<DataPoint> };\n const aData = aAny.data;\n const bData = bAny.data;\n\n if (aData.length !== bData.length) {\n out[i] = b;\n continue;\n }\n if (bData.length > MAX_ANIMATED_POINTS_PER_SERIES) {\n out[i] = b;\n continue;\n }\n\n const cache = caches?.cartesianDataBySeriesIndex[i] ?? null;\n const animatedData = interpolateCartesianSeriesDataByIndex(aData, bData, t01, cache);\n if (!animatedData) {\n out[i] = b;\n continue;\n }\n if (caches) caches.cartesianDataBySeriesIndex[i] = animatedData;\n\n out[i] = { ...(b as any), data: animatedData };\n }\n\n return out;\n };\n\n const computeUpdateSnapshotAtProgress = (\n transition: UpdateTransition,\n t01: number,\n zoomRange: ZoomRange | null\n ): UpdateTransitionSnapshot => {\n const xBase = lerpDomain(transition.from.xBaseDomain, transition.to.xBaseDomain, t01);\n const xVisible = computeVisibleXDomain(xBase, zoomRange);\n const yBase = lerpDomain(transition.from.yBaseDomain, transition.to.yBaseDomain, t01);\n const series = interpolateSeriesForUpdate(transition.from.series, transition.to.series, t01, null);\n return {\n xBaseDomain: xBase,\n xVisibleDomain: { min: xVisible.min, max: xVisible.max },\n yBaseDomain: yBase,\n series,\n };\n };\n\n // Prevent spamming console.warn for repeated misuse.\n const warnedPieAppendSeries = new Set<number>();\n\n // Coordinator-owned runtime series store (cartesian only).\n // - `runtimeRawDataByIndex[i]` owns a mutable array for streaming appends.\n // - `runtimeRawBoundsByIndex[i]` tracks raw bounds for axis auto-bounds and zoom mapping.\n let runtimeRawDataByIndex: Array<DataPoint[] | null> = new Array(options.series.length).fill(null);\n let runtimeRawBoundsByIndex: Array<Bounds | null> = new Array(options.series.length).fill(null);\n\n // Baseline sampled series list derived from runtime raw data (used as the “full span” baseline).\n // Zoom-visible resampling is derived from this baseline + runtime raw as needed.\n let runtimeBaseSeries: ResolvedChartGPUOptions['series'] = currentOptions.series;\n\n // Zoom-aware sampled series list used for rendering + cartesian hit-testing.\n // Derived from `currentOptions.series` (which still includes baseline sampled `data`).\n let renderSeries: ResolvedChartGPUOptions['series'] = currentOptions.series;\n // Unified flush scheduler (appends + zoom-aware resampling + optional GPU streaming updates).\n let flushScheduled = false;\n let flushRafId: number | null = null;\n let flushTimeoutId: number | null = null;\n\n // Zoom changes are debounced to avoid churn while wheel/drag is active.\n // When the debounce fires, we mark resampling \"due\" and schedule a unified flush.\n let zoomResampleDebounceTimer: number | null = null;\n let zoomResampleDue = false;\n\n // Coalesced streaming appends (flushed at the start of `render()`).\n const pendingAppendByIndex = new Map<number, DataPoint[]>();\n\n // Tracks what the DataStore currently represents for each series index.\n // Used to decide whether `appendSeries(...)` is a correct fast-path.\n type GpuSeriesKind = 'unknown' | 'fullRawLine' | 'other';\n let gpuSeriesKindByIndex: GpuSeriesKind[] = new Array(currentOptions.series.length).fill('unknown');\n const appendedGpuThisFrame = new Set<number>();\n\n // Tooltip is a DOM overlay element; enable by default unless explicitly disabled.\n let tooltip: Tooltip | null =\n overlayContainer && currentOptions.tooltip?.show !== false ? createTooltip(overlayContainer) : null;\n\n legend?.update(currentOptions.series, currentOptions.theme);\n\n let dataStore = createDataStore(device);\n\n const gridRenderer = createGridRenderer(device, { targetFormat });\n const xAxisRenderer = createAxisRenderer(device, { targetFormat });\n const yAxisRenderer = createAxisRenderer(device, { targetFormat });\n const crosshairRenderer = createCrosshairRenderer(device, { targetFormat });\n crosshairRenderer.setVisible(false);\n const highlightRenderer = createHighlightRenderer(device, { targetFormat });\n highlightRenderer.setVisible(false);\n\n const initialGridArea = computeGridArea(gpuContext, currentOptions);\n const eventManager = createEventManager(gpuContext.canvas, initialGridArea);\n\n type PointerSource = 'mouse' | 'sync';\n\n type PointerState = Readonly<{\n source: PointerSource;\n x: number;\n y: number;\n gridX: number;\n gridY: number;\n isInGrid: boolean;\n hasPointer: boolean;\n }>;\n\n let pointerState: PointerState = {\n source: 'mouse',\n x: 0,\n y: 0,\n gridX: 0,\n gridY: 0,\n isInGrid: false,\n hasPointer: false,\n };\n\n // Interaction-x state (domain units). This drives chart sync.\n let interactionX: number | null = null;\n let interactionXSource: unknown = undefined;\n const interactionXListeners = new Set<(x: number | null, source?: unknown) => void>();\n\n // Cached interaction scales from the last render (used for pointer -> domain-x mapping).\n let lastInteractionScales:\n | {\n readonly xScale: LinearScale;\n readonly yScale: LinearScale;\n readonly plotWidthCss: number;\n readonly plotHeightCss: number;\n }\n | null = null;\n\n const emitInteractionX = (nextX: number | null, source?: unknown): void => {\n const snapshot = Array.from(interactionXListeners);\n for (const cb of snapshot) cb(nextX, source);\n };\n\n const setInteractionXInternal = (nextX: number | null, source?: unknown): void => {\n const normalized = nextX !== null && Number.isFinite(nextX) ? nextX : null;\n if (interactionX === normalized && interactionXSource === source) return;\n interactionX = normalized;\n interactionXSource = source;\n emitInteractionX(interactionX, interactionXSource);\n };\n\n const requestRender = (): void => {\n callbacks?.onRequestRender?.();\n };\n\n const isFullSpanZoomRange = (range: ZoomRange | null): boolean => {\n if (!range) return true;\n return (\n Number.isFinite(range.start) &&\n Number.isFinite(range.end) &&\n range.start <= 0 &&\n range.end >= 100\n );\n };\n\n const cancelScheduledFlush = (): void => {\n if (flushRafId !== null) {\n cancelAnimationFrame(flushRafId);\n flushRafId = null;\n }\n if (flushTimeoutId !== null) {\n clearTimeout(flushTimeoutId);\n flushTimeoutId = null;\n }\n flushScheduled = false;\n };\n\n const cancelZoomResampleDebounce = (): void => {\n if (zoomResampleDebounceTimer !== null) {\n clearTimeout(zoomResampleDebounceTimer);\n zoomResampleDebounceTimer = null;\n }\n };\n\n const flushPendingAppends = (): boolean => {\n if (pendingAppendByIndex.size === 0) return false;\n\n appendedGpuThisFrame.clear();\n\n const zoomRangeBefore = zoomState?.getRange() ?? null;\n const isFullSpanZoomBefore = isFullSpanZoomRange(zoomRangeBefore);\n const canAutoScroll =\n currentOptions.autoScroll === true &&\n zoomState != null &&\n currentOptions.xAxis.min == null &&\n currentOptions.xAxis.max == null;\n\n // Capture the pre-append visible domain so we can preserve it for “panned away” behavior.\n const prevBaseXDomain = computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex);\n const prevVisibleXDomain = zoomRangeBefore ? computeVisibleXDomain(prevBaseXDomain, zoomRangeBefore) : null;\n\n let didAppendAny = false;\n\n for (const [seriesIndex, points] of pendingAppendByIndex) {\n if (points.length === 0) continue;\n const s = currentOptions.series[seriesIndex];\n if (!s || s.type === 'pie') continue;\n didAppendAny = true;\n\n let raw = runtimeRawDataByIndex[seriesIndex];\n if (!raw) {\n const seed = (s.rawData ?? s.data) as ReadonlyArray<DataPoint>;\n raw = seed.length === 0 ? [] : seed.slice();\n runtimeRawDataByIndex[seriesIndex] = raw;\n runtimeRawBoundsByIndex[seriesIndex] = s.rawBounds ?? computeRawBoundsFromData(raw);\n }\n\n // Optional fast-path: if the GPU buffer currently represents the full, unsampled line series,\n // we can append just the new points to the existing GPU buffer (no full re-upload).\n if (\n s.type === 'line' &&\n s.sampling === 'none' &&\n isFullSpanZoomBefore &&\n gpuSeriesKindByIndex[seriesIndex] === 'fullRawLine'\n ) {\n try {\n dataStore.appendSeries(seriesIndex, points);\n appendedGpuThisFrame.add(seriesIndex);\n } catch {\n // If the DataStore has not been initialized for this index (or any other error occurs),\n // fall back to the normal full upload path later in render().\n }\n }\n\n raw.push(...points);\n runtimeRawBoundsByIndex[seriesIndex] = extendBoundsWithDataPoints(runtimeRawBoundsByIndex[seriesIndex], points);\n }\n\n pendingAppendByIndex.clear();\n if (!didAppendAny) return false;\n\n // Auto-scroll is applied only on append (not on `setOptions`).\n if (canAutoScroll && zoomRangeBefore && prevVisibleXDomain) {\n const r = zoomRangeBefore;\n if (r.end >= 99.5) {\n const span = r.end - r.start;\n zoomState!.setRange(100 - span, 100);\n } else {\n const nextBaseXDomain = computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex);\n const span = nextBaseXDomain.max - nextBaseXDomain.min;\n if (Number.isFinite(span) && span > 0) {\n const nextStartRaw = ((prevVisibleXDomain.min - nextBaseXDomain.min) / span) * 100;\n const nextEndRaw = ((prevVisibleXDomain.max - nextBaseXDomain.min) / span) * 100;\n // Clamp defensively; ZoomState also clamps/orders internally.\n const nextStart = Math.max(0, Math.min(100, nextStartRaw));\n const nextEnd = Math.max(0, Math.min(100, nextEndRaw));\n zoomState!.setRange(nextStart, nextEnd);\n }\n }\n }\n\n recomputeRuntimeBaseSeries();\n\n // If zoom is disabled or full-span, `renderSeries` is just the baseline.\n // (Zoom-visible resampling is handled by the unified flush when needed.)\n const zoomRangeAfter = zoomState?.getRange() ?? null;\n if (zoomRangeAfter == null || isFullSpanZoomRange(zoomRangeAfter)) {\n renderSeries = runtimeBaseSeries;\n }\n\n return true;\n };\n\n const executeFlush = (options?: { readonly requestRenderAfter?: boolean }): void => {\n if (disposed) return;\n\n const requestRenderAfter = options?.requestRenderAfter ?? true;\n\n const didAppend = flushPendingAppends();\n\n const zoomRange = zoomState?.getRange() ?? null;\n const zoomIsFullSpan = isFullSpanZoomRange(zoomRange);\n const zoomActiveNotFullSpan = zoomRange != null && !zoomIsFullSpan;\n\n let didResample = false;\n\n // Zoom changes (debounced): apply on flush.\n if (zoomResampleDue) {\n zoomResampleDue = false;\n cancelZoomResampleDebounce();\n\n if (!zoomRange || zoomIsFullSpan) {\n renderSeries = runtimeBaseSeries;\n } else {\n recomputeRenderSeries();\n }\n didResample = true;\n } else if (didAppend && zoomActiveNotFullSpan) {\n // Appends during an active zoom window require resampling the visible range.\n // (Avoid doing this work when zoom is full-span or disabled.)\n zoomResampleDue = false;\n cancelZoomResampleDebounce();\n recomputeRenderSeries();\n didResample = true;\n }\n\n if ((didAppend || didResample) && requestRenderAfter) {\n requestRender();\n }\n };\n\n const scheduleFlush = (options?: { readonly immediate?: boolean }): void => {\n if (disposed) return;\n if (flushScheduled && !options?.immediate) return;\n\n // Cancel any previous schedule so we coalesce to exactly one pending flush.\n if (flushRafId !== null) {\n cancelAnimationFrame(flushRafId);\n flushRafId = null;\n }\n if (flushTimeoutId !== null) {\n clearTimeout(flushTimeoutId);\n flushTimeoutId = null;\n }\n\n flushScheduled = true;\n\n flushRafId = requestAnimationFrame(() => {\n flushRafId = null;\n if (disposed) {\n cancelScheduledFlush();\n return;\n }\n // rAF fired first: cancel the fallback timeout.\n if (flushTimeoutId !== null) {\n clearTimeout(flushTimeoutId);\n flushTimeoutId = null;\n }\n flushScheduled = false;\n executeFlush();\n });\n\n // Fallback: ensure we flush even if rAF is delayed (high-frequency streams > 60Hz).\n flushTimeoutId = window.setTimeout(() => {\n if (disposed) {\n cancelScheduledFlush();\n return;\n }\n if (!flushScheduled) return;\n\n if (flushRafId !== null) {\n cancelAnimationFrame(flushRafId);\n flushRafId = null;\n }\n flushScheduled = false;\n flushTimeoutId = null;\n executeFlush();\n }, 16);\n };\n\n const scheduleZoomResample = (): void => {\n if (disposed) return;\n\n cancelZoomResampleDebounce();\n zoomResampleDue = false;\n\n zoomResampleDebounceTimer = window.setTimeout(() => {\n zoomResampleDebounceTimer = null;\n if (disposed) return;\n zoomResampleDue = true;\n scheduleFlush();\n }, 100);\n };\n\n const getPlotSizeCssPx = (\n canvas: HTMLCanvasElement,\n gridArea: GridArea\n ): { readonly plotWidthCss: number; readonly plotHeightCss: number } | null => {\n const rect = canvas.getBoundingClientRect();\n if (!(rect.width > 0) || !(rect.height > 0)) return null;\n\n const plotWidthCss = rect.width - gridArea.left - gridArea.right;\n const plotHeightCss = rect.height - gridArea.top - gridArea.bottom;\n if (!(plotWidthCss > 0) || !(plotHeightCss > 0)) return null;\n\n return { plotWidthCss, plotHeightCss };\n };\n\n const computeInteractionScalesGridCssPx = (\n gridArea: GridArea,\n domains: { readonly xDomain: { readonly min: number; readonly max: number }; readonly yDomain: { readonly min: number; readonly max: number } }\n ):\n | {\n readonly xScale: LinearScale;\n readonly yScale: LinearScale;\n readonly plotWidthCss: number;\n readonly plotHeightCss: number;\n }\n | null => {\n const canvas = gpuContext.canvas;\n if (!canvas) return null;\n\n const plotSize = getPlotSizeCssPx(canvas, gridArea);\n if (!plotSize) return null;\n\n // IMPORTANT: grid-local CSS px ranges (0..plotWidth/Height), for interaction hit-testing.\n const xScale = createLinearScale().domain(domains.xDomain.min, domains.xDomain.max).range(0, plotSize.plotWidthCss);\n const yScale = createLinearScale().domain(domains.yDomain.min, domains.yDomain.max).range(plotSize.plotHeightCss, 0);\n\n return { xScale, yScale, plotWidthCss: plotSize.plotWidthCss, plotHeightCss: plotSize.plotHeightCss };\n };\n\n const buildTooltipParams = (seriesIndex: number, dataIndex: number, point: DataPoint): TooltipParams => {\n const s = currentOptions.series[seriesIndex];\n const { x, y } = getPointXY(point);\n return {\n seriesName: s?.name ?? '',\n seriesIndex,\n dataIndex,\n value: [x, y],\n color: s?.color ?? '#888',\n };\n };\n\n const onMouseMove = (payload: ChartGPUEventPayload): void => {\n pointerState = {\n source: 'mouse',\n x: payload.x,\n y: payload.y,\n gridX: payload.gridX,\n gridY: payload.gridY,\n isInGrid: payload.isInGrid,\n hasPointer: true,\n };\n\n // If we're over the plot and we have recent interaction scales, update interaction-x in domain units.\n // (Best-effort; render() refreshes scales and overlays.)\n if (payload.isInGrid && lastInteractionScales) {\n const xDomain = lastInteractionScales.xScale.invert(payload.gridX);\n setInteractionXInternal(Number.isFinite(xDomain) ? xDomain : null, 'mouse');\n } else if (!payload.isInGrid) {\n // Clear interaction-x when leaving the plot area (keeps synced charts from “sticking”).\n setInteractionXInternal(null, 'mouse');\n }\n\n crosshairRenderer.setVisible(payload.isInGrid);\n requestRender();\n };\n\n const onMouseLeave = (_payload: ChartGPUEventPayload): void => {\n // Only clear interaction overlays for real pointer interaction.\n // If we're being driven by a sync-x, leaving the canvas shouldn't hide the overlays.\n if (pointerState.source !== 'mouse') return;\n\n pointerState = { ...pointerState, isInGrid: false, hasPointer: false };\n crosshairRenderer.setVisible(false);\n tooltip?.hide();\n setInteractionXInternal(null, 'mouse');\n requestRender();\n };\n\n eventManager.on('mousemove', onMouseMove);\n eventManager.on('mouseleave', onMouseLeave);\n\n // Optional internal “inside zoom” (wheel zoom + drag pan).\n let zoomState: ZoomState | null = null;\n let insideZoom: ReturnType<typeof createInsideZoom> | null = null;\n let unsubscribeZoom: (() => void) | null = null;\n let lastOptionsZoomRange: Readonly<{ start: number; end: number }> | null = null;\n const zoomRangeListeners = new Set<(range: Readonly<{ start: number; end: number }>) => void>();\n\n const emitZoomRange = (range: Readonly<{ start: number; end: number }>): void => {\n const snapshot = Array.from(zoomRangeListeners);\n for (const cb of snapshot) cb(range);\n };\n\n const getZoomOptionsConfig = (\n opts: ResolvedChartGPUOptions\n ): { readonly start: number; readonly end: number; readonly hasInside: boolean } | null => {\n // Zoom is enabled when *either* inside or slider exists. A single shared percent-space\n // window is used for both.\n const insideCfg = opts.dataZoom?.find((z) => z?.type === 'inside');\n const sliderCfg = opts.dataZoom?.find((z) => z?.type === 'slider');\n const cfg = insideCfg ?? sliderCfg;\n if (!cfg) return null;\n const start = Number.isFinite(cfg.start) ? cfg.start! : 0;\n const end = Number.isFinite(cfg.end) ? cfg.end! : 100;\n return { start, end, hasInside: !!insideCfg };\n };\n\n const updateZoom = (): void => {\n const cfg = getZoomOptionsConfig(currentOptions);\n\n if (!cfg) {\n insideZoom?.dispose();\n insideZoom = null;\n unsubscribeZoom?.();\n unsubscribeZoom = null;\n zoomState = null;\n lastOptionsZoomRange = null;\n return;\n }\n\n if (!zoomState) {\n zoomState = createZoomState(cfg.start, cfg.end);\n lastOptionsZoomRange = { start: cfg.start, end: cfg.end };\n unsubscribeZoom = zoomState.onChange((range) => {\n // Immediate render for UI feedback (axes/crosshair/slider).\n requestRender();\n // Debounce resampling; the unified flush will do the work.\n scheduleZoomResample();\n // Ensure listeners get a stable readonly object.\n emitZoomRange({ start: range.start, end: range.end });\n });\n } else if (\n lastOptionsZoomRange == null ||\n lastOptionsZoomRange.start !== cfg.start ||\n lastOptionsZoomRange.end !== cfg.end\n ) {\n // Only apply option-provided start/end when:\n // - zoom is first created, or\n // - start/end actually changed in options\n zoomState.setRange(cfg.start, cfg.end);\n lastOptionsZoomRange = { start: cfg.start, end: cfg.end };\n }\n\n // Only enable inside zoom handler when `{ type: 'inside' }` exists.\n if (cfg.hasInside) {\n if (!insideZoom) {\n insideZoom = createInsideZoom(eventManager, zoomState);\n insideZoom.enable();\n }\n } else {\n insideZoom?.dispose();\n insideZoom = null;\n }\n };\n\n const initRuntimeSeriesFromOptions = (): void => {\n const count = currentOptions.series.length;\n runtimeRawDataByIndex = new Array(count).fill(null);\n runtimeRawBoundsByIndex = new Array(count).fill(null);\n pendingAppendByIndex.clear();\n\n for (let i = 0; i < count; i++) {\n const s = currentOptions.series[i]!;\n if (s.type === 'pie') continue;\n\n const raw = (s.rawData ?? s.data) as ReadonlyArray<DataPoint>;\n // Coordinator-owned: copy into a mutable array (streaming appends mutate this).\n const owned = raw.length === 0 ? [] : raw.slice();\n runtimeRawDataByIndex[i] = owned;\n runtimeRawBoundsByIndex[i] = s.rawBounds ?? computeRawBoundsFromData(owned);\n }\n };\n\n const recomputeRuntimeBaseSeries = (): void => {\n const next: ResolvedChartGPUOptions['series'][number][] = new Array(currentOptions.series.length);\n for (let i = 0; i < currentOptions.series.length; i++) {\n const s = currentOptions.series[i]!;\n if (s.type === 'pie') {\n next[i] = s;\n continue;\n }\n\n const raw = runtimeRawDataByIndex[i] ?? ((s.rawData ?? s.data) as ReadonlyArray<DataPoint>);\n const bounds = runtimeRawBoundsByIndex[i] ?? s.rawBounds ?? undefined;\n const baselineSampled = sampleSeriesDataPoints(raw, s.sampling, s.samplingThreshold);\n next[i] = { ...s, rawData: raw, rawBounds: bounds, data: baselineSampled };\n }\n runtimeBaseSeries = next;\n };\n\n function recomputeRenderSeries(): void {\n const zoomRange = zoomState?.getRange() ?? null;\n const baseXDomain = computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex);\n const visibleX = computeVisibleXDomain(baseXDomain, zoomRange);\n\n // Sampling scale behavior:\n // - Use `samplingThreshold` as baseline at full span.\n // - As zoom span shrinks, raise the threshold so fewer points are dropped (more detail).\n // - Clamp to avoid huge allocations / pathological thresholds.\n const MIN_TARGET_POINTS = 2;\n const MAX_TARGET_POINTS_ABS = 200_000;\n const MAX_TARGET_MULTIPLIER = 32;\n const spanFracSafe = Math.max(1e-3, Math.min(1, visibleX.spanFraction));\n\n const next: ResolvedChartGPUOptions['series'][number][] = new Array(runtimeBaseSeries.length);\n\n for (let i = 0; i < runtimeBaseSeries.length; i++) {\n const s = runtimeBaseSeries[i]!;\n\n if (s.type === 'pie') {\n next[i] = s;\n continue;\n }\n\n const rawData = runtimeRawDataByIndex[i] ?? ((s.rawData ?? s.data) as ReadonlyArray<DataPoint>);\n\n // Fast path: no zoom window / full span. Use baseline resolved `data` (already sampled by resolver).\n const isFullSpan =\n zoomRange == null ||\n (Number.isFinite(zoomRange.start) &&\n Number.isFinite(zoomRange.end) &&\n zoomRange.start <= 0 &&\n zoomRange.end >= 100);\n if (isFullSpan) {\n next[i] = s;\n continue;\n }\n\n const visibleRaw = sliceVisibleRangeByX(rawData, visibleX.min, visibleX.max);\n\n const sampling = s.sampling;\n const baseThreshold = s.samplingThreshold;\n\n const baseT = Number.isFinite(baseThreshold) ? Math.max(1, baseThreshold | 0) : 1;\n const maxTarget = Math.min(MAX_TARGET_POINTS_ABS, Math.max(MIN_TARGET_POINTS, baseT * MAX_TARGET_MULTIPLIER));\n const target = clampInt(Math.round(baseT / spanFracSafe), MIN_TARGET_POINTS, maxTarget);\n\n const sampled = sampleSeriesDataPoints(visibleRaw, sampling, target);\n next[i] = { ...s, data: sampled };\n }\n\n renderSeries = next;\n }\n\n updateZoom();\n initRuntimeSeriesFromOptions();\n recomputeRuntimeBaseSeries();\n recomputeRenderSeries();\n\n const areaRenderers: Array<ReturnType<typeof createAreaRenderer>> = [];\n const lineRenderers: Array<ReturnType<typeof createLineRenderer>> = [];\n const scatterRenderers: Array<ReturnType<typeof createScatterRenderer>> = [];\n const pieRenderers: Array<ReturnType<typeof createPieRenderer>> = [];\n const barRenderer = createBarRenderer(device, { targetFormat });\n\n const ensureAreaRendererCount = (count: number): void => {\n while (areaRenderers.length > count) {\n const r = areaRenderers.pop();\n r?.dispose();\n }\n while (areaRenderers.length < count) {\n areaRenderers.push(createAreaRenderer(device, { targetFormat }));\n }\n };\n\n const ensureLineRendererCount = (count: number): void => {\n while (lineRenderers.length > count) {\n const r = lineRenderers.pop();\n r?.dispose();\n }\n while (lineRenderers.length < count) {\n lineRenderers.push(createLineRenderer(device, { targetFormat }));\n }\n };\n\n const ensureScatterRendererCount = (count: number): void => {\n while (scatterRenderers.length > count) {\n const r = scatterRenderers.pop();\n r?.dispose();\n }\n while (scatterRenderers.length < count) {\n scatterRenderers.push(createScatterRenderer(device, { targetFormat }));\n }\n };\n\n const ensurePieRendererCount = (count: number): void => {\n while (pieRenderers.length > count) {\n const r = pieRenderers.pop();\n r?.dispose();\n }\n while (pieRenderers.length < count) {\n pieRenderers.push(createPieRenderer(device, { targetFormat }));\n }\n };\n\n ensureAreaRendererCount(currentOptions.series.length);\n ensureLineRendererCount(currentOptions.series.length);\n ensureScatterRendererCount(currentOptions.series.length);\n ensurePieRendererCount(currentOptions.series.length);\n\n const assertNotDisposed = (): void => {\n if (disposed) throw new Error('RenderCoordinator is disposed.');\n };\n\n const cancelUpdateTransition = (): void => {\n if (updateAnimId) {\n try {\n updateAnimController.cancel(updateAnimId);\n } catch {\n // best-effort\n }\n }\n updateAnimId = null;\n updateProgress01 = 1;\n updateTransition = null;\n resetUpdateInterpolationCaches();\n };\n\n const isDomainEqual = (a: { readonly min: number; readonly max: number }, b: { readonly min: number; readonly max: number }): boolean =>\n a.min === b.min && a.max === b.max;\n\n const didSeriesDataLikelyChange = (\n prev: ResolvedChartGPUOptions['series'],\n next: ResolvedChartGPUOptions['series']\n ): boolean => {\n if (prev.length !== next.length) return true;\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i]!;\n const b = next[i]!;\n if (a.type !== b.type) return true;\n\n // Prefer cheap reference checks (good enough for eligibility gating).\n if (a.type === 'pie') {\n const aPie = a as ResolvedPieSeriesConfig;\n const bPie = b as ResolvedPieSeriesConfig;\n if (aPie.data !== bPie.data) return true;\n if (aPie.data.length !== bPie.data.length) return true;\n } else {\n const aAny = a as unknown as { readonly rawData?: ReadonlyArray<DataPoint>; readonly data: ReadonlyArray<DataPoint> };\n const bAny = b as unknown as { readonly rawData?: ReadonlyArray<DataPoint>; readonly data: ReadonlyArray<DataPoint> };\n const aRaw = (aAny.rawData ?? aAny.data) as ReadonlyArray<DataPoint>;\n const bRaw = (bAny.rawData ?? bAny.data) as ReadonlyArray<DataPoint>;\n if (aRaw !== bRaw) return true;\n if (aRaw.length !== bRaw.length) return true;\n }\n }\n return false;\n };\n\n const setOptions: RenderCoordinator['setOptions'] = (resolvedOptions) => {\n assertNotDisposed();\n\n // Capture \"from\" snapshot BEFORE overwriting coordinator state.\n const fromZoomRange = zoomState?.getRange() ?? null;\n const fromSnapshot: UpdateTransitionSnapshot = (() => {\n // Requirement (mid-flight updates): if a transition is running, rebase from the current blended state.\n if (updateTransition && updateAnimId) {\n try {\n updateAnimController.update(performance.now());\n } catch {\n // best-effort\n }\n return computeUpdateSnapshotAtProgress(updateTransition, updateProgress01, fromZoomRange);\n }\n\n const fromXBase = computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex);\n const fromXVisible = computeVisibleXDomain(fromXBase, fromZoomRange);\n const fromYBase = computeBaseYDomain(currentOptions, runtimeRawBoundsByIndex);\n return {\n xBaseDomain: fromXBase,\n xVisibleDomain: { min: fromXVisible.min, max: fromXVisible.max },\n yBaseDomain: fromYBase,\n series: renderSeries,\n };\n })();\n\n // Cancel any prior update transition AFTER capturing the rebased \"from\" snapshot.\n cancelUpdateTransition();\n const likelyDataChanged = didSeriesDataLikelyChange(currentOptions.series, resolvedOptions.series);\n\n currentOptions = resolvedOptions;\n runtimeBaseSeries = resolvedOptions.series;\n renderSeries = resolvedOptions.series;\n gpuSeriesKindByIndex = new Array(resolvedOptions.series.length).fill('unknown');\n legend?.update(resolvedOptions.series, resolvedOptions.theme);\n updateZoom();\n cancelZoomResampleDebounce();\n zoomResampleDue = false;\n cancelScheduledFlush();\n initRuntimeSeriesFromOptions();\n recomputeRuntimeBaseSeries();\n recomputeRenderSeries();\n\n // Tooltip enablement may change at runtime.\n if (overlayContainer) {\n const shouldHaveTooltip = currentOptions.tooltip?.show !== false;\n if (shouldHaveTooltip && !tooltip) tooltip = createTooltip(overlayContainer);\n if (!shouldHaveTooltip && tooltip) tooltip.hide();\n } else {\n tooltip?.hide();\n }\n\n const nextCount = resolvedOptions.series.length;\n ensureAreaRendererCount(nextCount);\n ensureLineRendererCount(nextCount);\n ensureScatterRendererCount(nextCount);\n ensurePieRendererCount(nextCount);\n\n // When the series count shrinks, explicitly destroy per-index GPU buffers for removed series.\n // This avoids recreating the entire DataStore and keeps existing buffers for retained indices.\n if (nextCount < lastSeriesCount) {\n for (let i = nextCount; i < lastSeriesCount; i++) {\n dataStore.removeSeries(i);\n }\n }\n lastSeriesCount = nextCount;\n\n // If animation is explicitly disabled mid-flight, stop the intro without scheduling more frames.\n if (currentOptions.animation === false && introPhase === 'running') {\n introAnimController.cancelAll();\n introAnimId = null;\n introPhase = 'done';\n introProgress01 = 1;\n }\n\n // If animation is explicitly disabled, ensure any running update transition is stopped.\n if (currentOptions.animation === false) {\n cancelUpdateTransition();\n return;\n }\n\n // Capture \"to\" snapshot after recompute.\n const toZoomRange = zoomState?.getRange() ?? null;\n const toXBase = computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex);\n const toXVisible = computeVisibleXDomain(toXBase, toZoomRange);\n const toYBase = computeBaseYDomain(currentOptions, runtimeRawBoundsByIndex);\n const toSeriesForTransition = renderSeries;\n\n const domainChanged = !isDomainEqual(fromSnapshot.xBaseDomain, toXBase) || !isDomainEqual(fromSnapshot.yBaseDomain, toYBase);\n\n const shouldAnimateUpdate = hasRenderedOnce && (domainChanged || likelyDataChanged);\n if (!shouldAnimateUpdate) return;\n\n const updateCfg = resolveUpdateAnimationConfig(currentOptions.animation);\n if (!updateCfg) return;\n\n updateTransition = {\n from: {\n xBaseDomain: fromSnapshot.xBaseDomain,\n xVisibleDomain: fromSnapshot.xVisibleDomain,\n yBaseDomain: fromSnapshot.yBaseDomain,\n series: fromSnapshot.series,\n },\n to: {\n xBaseDomain: toXBase,\n xVisibleDomain: { min: toXVisible.min, max: toXVisible.max },\n yBaseDomain: toYBase,\n series: toSeriesForTransition,\n },\n };\n resetUpdateInterpolationCaches();\n\n const totalMs = updateCfg.delayMs + updateCfg.durationMs;\n const easingWithDelay: EasingFunction = (t01) => {\n const t = clamp01(t01);\n if (!(totalMs > 0)) return 1;\n\n const elapsedMs = t * totalMs;\n if (elapsedMs <= updateCfg.delayMs) return 0;\n\n if (!(updateCfg.durationMs > 0)) return 1;\n const innerT = (elapsedMs - updateCfg.delayMs) / updateCfg.durationMs;\n return updateCfg.easing(innerT);\n };\n\n updateProgress01 = 0;\n const id = updateAnimController.animate(\n 0,\n 1,\n totalMs,\n easingWithDelay,\n (value) => {\n if (disposed || updateAnimId !== id) return;\n updateProgress01 = clamp01(value);\n // Render-on-demand: request frames only while the update transition is active.\n if (updateProgress01 < 1) requestRender();\n },\n () => {\n if (disposed || updateAnimId !== id) return;\n updateProgress01 = 1;\n updateTransition = null;\n updateAnimId = null;\n resetUpdateInterpolationCaches();\n }\n );\n updateAnimId = id;\n };\n\n const appendData: RenderCoordinator['appendData'] = (seriesIndex, newPoints) => {\n assertNotDisposed();\n if (!Number.isFinite(seriesIndex)) return;\n if (seriesIndex < 0 || seriesIndex >= currentOptions.series.length) return;\n if (!newPoints || newPoints.length === 0) return;\n\n const s = currentOptions.series[seriesIndex]!;\n if (s.type === 'pie') {\n // Pie series are non-cartesian and currently not supported by streaming append.\n if (!warnedPieAppendSeries.has(seriesIndex)) {\n warnedPieAppendSeries.add(seriesIndex);\n console.warn(\n `RenderCoordinator.appendData(${seriesIndex}, ...): pie series are not supported by streaming append.`\n );\n }\n return;\n }\n\n const existing = pendingAppendByIndex.get(seriesIndex);\n if (existing) {\n existing.push(...newPoints);\n } else {\n // Copy into a mutable staging array so repeated appends coalesce without extra allocations.\n pendingAppendByIndex.set(seriesIndex, Array.from(newPoints));\n }\n\n // Coalesce appends + any required resampling + GPU streaming updates into a single flush.\n scheduleFlush();\n };\n\n const shouldRenderArea = (series: ResolvedChartGPUOptions['series'][number]): boolean => {\n switch (series.type) {\n case 'area':\n return true;\n case 'line':\n return series.areaStyle != null;\n case 'bar':\n return false;\n case 'scatter':\n return false;\n case 'pie':\n return false;\n default:\n return assertUnreachable(series);\n }\n };\n\n const render: RenderCoordinator['render'] = () => {\n assertNotDisposed();\n if (!gpuContext.canvasContext || !gpuContext.canvas) return;\n\n // Safety: if a render is triggered for other reasons (e.g. pointer movement) while appends\n // are queued, flush them now so this frame draws up-to-date data. This avoids doing any work\n // when there are no appends.\n if (pendingAppendByIndex.size > 0 || zoomResampleDue) {\n cancelScheduledFlush();\n executeFlush({ requestRenderAfter: false });\n }\n\n const hasCartesianSeries = currentOptions.series.some((s) => s.type !== 'pie');\n const seriesForIntro = renderSeries;\n\n // Story 5.16: start/update intro animation once we have drawable series marks.\n if (introPhase !== 'done') {\n const introCfg = resolveIntroAnimationConfig(currentOptions.animation);\n\n const hasDrawableSeriesMarks = (() => {\n for (let i = 0; i < seriesForIntro.length; i++) {\n const s = seriesForIntro[i]!;\n switch (s.type) {\n case 'pie': {\n // Pie renderer only emits slices with value > 0.\n if (s.data.some((it) => typeof it?.value === 'number' && Number.isFinite(it.value) && it.value > 0)) {\n return true;\n }\n break;\n }\n case 'line':\n case 'area':\n case 'bar':\n case 'scatter': {\n if (s.data.length > 0) return true;\n break;\n }\n default:\n assertUnreachable(s);\n }\n }\n return false;\n })();\n\n if (introPhase === 'pending' && introCfg && hasDrawableSeriesMarks) {\n const totalMs = introCfg.delayMs + introCfg.durationMs;\n const easingWithDelay: EasingFunction = (t01) => {\n const t = clamp01(t01);\n if (!(totalMs > 0)) return 1;\n\n const elapsedMs = t * totalMs;\n if (elapsedMs <= introCfg.delayMs) return 0;\n\n if (!(introCfg.durationMs > 0)) return 1;\n const innerT = (elapsedMs - introCfg.delayMs) / introCfg.durationMs;\n return introCfg.easing(innerT);\n };\n\n introProgress01 = 0;\n introPhase = 'running';\n introAnimId = introAnimController.animate(\n 0,\n 1,\n totalMs,\n easingWithDelay,\n (value) => {\n if (disposed || introPhase !== 'running') return;\n introProgress01 = clamp01(value);\n // Render-on-demand: request frames only while the intro is active.\n if (introProgress01 < 1) requestRender();\n },\n () => {\n if (disposed) return;\n introPhase = 'done';\n introProgress01 = 1;\n introAnimId = null;\n }\n );\n }\n\n // Progress animations based on wall-clock time. This is cheap when no animations are active.\n introAnimController.update(performance.now());\n }\n\n // Story 5.17: progress update animation based on wall-clock time.\n // (Interpolation is applied below; this tick just advances progress.)\n if (updateTransition !== null && updateAnimId) {\n updateAnimController.update(performance.now());\n }\n\n const gridArea = computeGridArea(gpuContext, currentOptions);\n eventManager.updateGridArea(gridArea);\n const zoomRange = zoomState?.getRange() ?? null;\n\n const updateP = updateTransition ? clamp01(updateProgress01) : 1;\n const baseXDomain = updateTransition\n ? lerpDomain(updateTransition.from.xBaseDomain, updateTransition.to.xBaseDomain, updateP)\n : computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex);\n const yBaseDomain = updateTransition\n ? lerpDomain(updateTransition.from.yBaseDomain, updateTransition.to.yBaseDomain, updateP)\n : computeBaseYDomain(currentOptions, runtimeRawBoundsByIndex);\n const visibleXDomain = computeVisibleXDomain(baseXDomain, zoomRange);\n\n const plotClipRect = computePlotClipRect(gridArea);\n const plotScissor = computePlotScissorDevicePx(gridArea);\n\n const xScale = createLinearScale()\n .domain(visibleXDomain.min, visibleXDomain.max)\n .range(plotClipRect.left, plotClipRect.right);\n const yScale = createLinearScale().domain(yBaseDomain.min, yBaseDomain.max).range(plotClipRect.bottom, plotClipRect.top);\n\n const interactionScales = computeInteractionScalesGridCssPx(gridArea, {\n xDomain: { min: visibleXDomain.min, max: visibleXDomain.max },\n yDomain: yBaseDomain,\n });\n lastInteractionScales = interactionScales;\n\n // Story 5.17: during update transitions, render animated series snapshots.\n const seriesForRender =\n updateTransition && updateP < 1\n ? interpolateSeriesForUpdate(updateTransition.from.series, updateTransition.to.series, updateP, updateInterpolationCaches)\n : renderSeries;\n\n // Keep `interactionX` in sync with real pointer movement (domain units).\n if (\n pointerState.source === 'mouse' &&\n pointerState.hasPointer &&\n pointerState.isInGrid &&\n interactionScales\n ) {\n const xDomain = interactionScales.xScale.invert(pointerState.gridX);\n setInteractionXInternal(Number.isFinite(xDomain) ? xDomain : null, 'mouse');\n }\n\n // Compute the effective interaction state:\n // - mouse: use the latest pointer event payload\n // - sync: derive a synthetic pointer position from `interactionX` (x only; y is arbitrary)\n let effectivePointer: PointerState = pointerState;\n if (pointerState.source === 'sync') {\n if (interactionX === null || !interactionScales) {\n effectivePointer = { ...pointerState, hasPointer: false, isInGrid: false };\n } else {\n const gridX = interactionScales.xScale.scale(interactionX);\n const gridY = interactionScales.plotHeightCss * 0.5;\n const isInGrid =\n Number.isFinite(gridX) &&\n Number.isFinite(gridY) &&\n gridX >= 0 &&\n gridX <= interactionScales.plotWidthCss &&\n gridY >= 0 &&\n gridY <= interactionScales.plotHeightCss;\n\n effectivePointer = {\n source: 'sync',\n gridX: Number.isFinite(gridX) ? gridX : 0,\n gridY: Number.isFinite(gridY) ? gridY : 0,\n // Crosshair/tooltip expect CANVAS-LOCAL CSS px.\n x: gridArea.left + (Number.isFinite(gridX) ? gridX : 0),\n y: gridArea.top + (Number.isFinite(gridY) ? gridY : 0),\n isInGrid,\n hasPointer: isInGrid,\n };\n }\n }\n\n gridRenderer.prepare(gridArea, { color: currentOptions.theme.gridLineColor });\n if (hasCartesianSeries) {\n xAxisRenderer.prepare(\n currentOptions.xAxis,\n xScale,\n 'x',\n gridArea,\n currentOptions.theme.axisLineColor,\n currentOptions.theme.axisTickColor\n );\n yAxisRenderer.prepare(\n currentOptions.yAxis,\n yScale,\n 'y',\n gridArea,\n currentOptions.theme.axisLineColor,\n currentOptions.theme.axisTickColor\n );\n }\n\n // Crosshair prepare uses canvas-local CSS px (EventManager payload x/y) and current gridArea.\n if (effectivePointer.hasPointer && effectivePointer.isInGrid) {\n const crosshairOptions: CrosshairRenderOptions = {\n showX: true,\n // Sync has no meaningful y, so avoid horizontal line.\n showY: effectivePointer.source !== 'sync',\n color: withAlpha(currentOptions.theme.axisLineColor, 0.6),\n lineWidth: DEFAULT_CROSSHAIR_LINE_WIDTH_CSS_PX,\n };\n crosshairRenderer.prepare(effectivePointer.x, effectivePointer.y, gridArea, crosshairOptions);\n crosshairRenderer.setVisible(true);\n } else {\n crosshairRenderer.setVisible(false);\n }\n\n // Highlight: on hover, find nearest point and draw a ring highlight clipped to plot rect.\n if (effectivePointer.source === 'mouse' && effectivePointer.hasPointer && effectivePointer.isInGrid) {\n if (interactionScales) {\n const match = findNearestPoint(\n seriesForRender,\n effectivePointer.gridX,\n effectivePointer.gridY,\n interactionScales.xScale,\n interactionScales.yScale\n );\n\n if (match) {\n const { x, y } = getPointXY(match.point);\n const xGridCss = interactionScales.xScale.scale(x);\n const yGridCss = interactionScales.yScale.scale(y);\n\n if (Number.isFinite(xGridCss) && Number.isFinite(yGridCss)) {\n const dpr = window.devicePixelRatio || 1;\n const centerCssX = gridArea.left + xGridCss;\n const centerCssY = gridArea.top + yGridCss;\n\n const plotScissor = computePlotScissorDevicePx(gridArea);\n const point: HighlightPoint = {\n centerDeviceX: centerCssX * dpr,\n centerDeviceY: centerCssY * dpr,\n canvasWidth: gridArea.canvasWidth,\n canvasHeight: gridArea.canvasHeight,\n scissor: plotScissor,\n };\n\n const seriesColor = currentOptions.series[match.seriesIndex]?.color ?? '#888';\n highlightRenderer.prepare(point, seriesColor, DEFAULT_HIGHLIGHT_SIZE_CSS_PX);\n highlightRenderer.setVisible(true);\n } else {\n highlightRenderer.setVisible(false);\n }\n } else {\n highlightRenderer.setVisible(false);\n }\n } else {\n highlightRenderer.setVisible(false);\n }\n } else {\n highlightRenderer.setVisible(false);\n }\n\n // Tooltip: on hover, find matches and render tooltip near cursor.\n if (tooltip && effectivePointer.hasPointer && effectivePointer.isInGrid) {\n const canvas = gpuContext.canvas;\n\n if (interactionScales && canvas && currentOptions.tooltip?.show !== false) {\n const formatter = currentOptions.tooltip?.formatter;\n const trigger = currentOptions.tooltip?.trigger ?? 'item';\n\n const containerX = canvas.offsetLeft + effectivePointer.x;\n const containerY = canvas.offsetTop + effectivePointer.y;\n\n if (effectivePointer.source === 'sync') {\n // Sync semantics:\n // - Tooltip should be driven by x only (no y).\n // - In 'axis' mode, show one entry per series nearest in x.\n // - In 'item' mode, pick a deterministic single entry (first matching series).\n const matches = findPointsAtX(seriesForRender, effectivePointer.gridX, interactionScales.xScale);\n if (matches.length === 0) {\n tooltip.hide();\n } else if (trigger === 'axis') {\n const paramsArray = matches.map((m) => buildTooltipParams(m.seriesIndex, m.dataIndex, m.point));\n const content = formatter\n ? (formatter as (p: ReadonlyArray<TooltipParams>) => string)(paramsArray)\n : formatTooltipAxis(paramsArray);\n if (content) tooltip.show(containerX, containerY, content);\n else tooltip.hide();\n } else {\n const m0 = matches[0];\n const params = buildTooltipParams(m0.seriesIndex, m0.dataIndex, m0.point);\n const content = formatter ? (formatter as (p: TooltipParams) => string)(params) : formatTooltipItem(params);\n if (content) tooltip.show(containerX, containerY, content);\n else tooltip.hide();\n }\n } else if (trigger === 'axis') {\n // Story 4.14: pie slice tooltip hit-testing (mouse only).\n // If the cursor is over a pie slice, prefer showing that slice tooltip.\n const pieMatch = (() => {\n const plotWidthCss = interactionScales.plotWidthCss;\n const plotHeightCss = interactionScales.plotHeightCss;\n const maxRadiusCss = 0.5 * Math.min(plotWidthCss, plotHeightCss);\n if (!(maxRadiusCss > 0)) return null;\n\n for (let i = currentOptions.series.length - 1; i >= 0; i--) {\n const s = seriesForRender[i];\n if (s.type !== 'pie') continue;\n const pieSeries = s as ResolvedPieSeriesConfig;\n const center = resolvePieCenterPlotCss(pieSeries.center, plotWidthCss, plotHeightCss);\n const radii = resolvePieRadiiCss(pieSeries.radius, maxRadiusCss);\n const m = findPieSlice(\n effectivePointer.gridX,\n effectivePointer.gridY,\n { seriesIndex: i, series: pieSeries },\n center,\n radii\n );\n if (m) return m;\n }\n return null;\n })();\n\n if (pieMatch) {\n const params: TooltipParams = {\n seriesName: pieMatch.slice.name,\n seriesIndex: pieMatch.seriesIndex,\n dataIndex: pieMatch.dataIndex,\n value: [0, pieMatch.slice.value],\n color: pieMatch.slice.color,\n };\n\n const content = formatter\n ? (formatter as (p: ReadonlyArray<TooltipParams>) => string)([params])\n : formatTooltipItem(params);\n if (content) tooltip.show(containerX, containerY, content);\n else tooltip.hide();\n } else {\n const matches = findPointsAtX(seriesForRender, effectivePointer.gridX, interactionScales.xScale);\n if (matches.length === 0) {\n tooltip.hide();\n } else {\n const paramsArray = matches.map((m) => buildTooltipParams(m.seriesIndex, m.dataIndex, m.point));\n const content = formatter\n ? (formatter as (p: ReadonlyArray<TooltipParams>) => string)(paramsArray)\n : formatTooltipAxis(paramsArray);\n if (content) tooltip.show(containerX, containerY, content);\n else tooltip.hide();\n }\n }\n } else {\n // Story 4.14: pie slice tooltip hit-testing (mouse only).\n // If the cursor is over a pie slice, prefer showing that slice tooltip.\n const pieMatch = (() => {\n const plotWidthCss = interactionScales.plotWidthCss;\n const plotHeightCss = interactionScales.plotHeightCss;\n const maxRadiusCss = 0.5 * Math.min(plotWidthCss, plotHeightCss);\n if (!(maxRadiusCss > 0)) return null;\n\n for (let i = currentOptions.series.length - 1; i >= 0; i--) {\n const s = seriesForRender[i];\n if (s.type !== 'pie') continue;\n const pieSeries = s as ResolvedPieSeriesConfig;\n const center = resolvePieCenterPlotCss(pieSeries.center, plotWidthCss, plotHeightCss);\n const radii = resolvePieRadiiCss(pieSeries.radius, maxRadiusCss);\n const m = findPieSlice(\n effectivePointer.gridX,\n effectivePointer.gridY,\n { seriesIndex: i, series: pieSeries },\n center,\n radii\n );\n if (m) return m;\n }\n return null;\n })();\n\n if (pieMatch) {\n const params: TooltipParams = {\n seriesName: pieMatch.slice.name,\n seriesIndex: pieMatch.seriesIndex,\n dataIndex: pieMatch.dataIndex,\n value: [0, pieMatch.slice.value],\n color: pieMatch.slice.color,\n };\n const content = formatter\n ? (formatter as (p: TooltipParams) => string)(params)\n : formatTooltipItem(params);\n if (content) tooltip.show(containerX, containerY, content);\n else tooltip.hide();\n } else {\n const match = findNearestPoint(\n seriesForRender,\n effectivePointer.gridX,\n effectivePointer.gridY,\n interactionScales.xScale,\n interactionScales.yScale\n );\n if (!match) {\n tooltip.hide();\n } else {\n const params = buildTooltipParams(match.seriesIndex, match.dataIndex, match.point);\n const content = formatter\n ? (formatter as (p: TooltipParams) => string)(params)\n : formatTooltipItem(params);\n if (content) tooltip.show(containerX, containerY, content);\n else tooltip.hide();\n }\n }\n }\n } else {\n tooltip.hide();\n }\n } else {\n tooltip?.hide();\n }\n\n const defaultBaseline = currentOptions.yAxis.min ?? yBaseDomain.min;\n const barSeriesConfigs: ResolvedBarSeriesConfig[] = [];\n\n const introP = introPhase === 'running' ? clamp01(introProgress01) : 1;\n\n for (let i = 0; i < seriesForRender.length; i++) {\n const s = seriesForRender[i];\n switch (s.type) {\n case 'area': {\n const baseline = s.baseline ?? defaultBaseline;\n areaRenderers[i].prepare(s, s.data, xScale, yScale, baseline);\n break;\n }\n case 'line': {\n // Always prepare the line stroke.\n // If we already appended into the DataStore this frame (fast-path), avoid a full re-upload.\n if (!appendedGpuThisFrame.has(i)) {\n dataStore.setSeries(i, s.data);\n }\n const buffer = dataStore.getSeriesBuffer(i);\n lineRenderers[i].prepare(s, buffer, xScale, yScale);\n\n // Track the GPU buffer kind for future append fast-path decisions.\n const zoomRange = zoomState?.getRange() ?? null;\n const isFullSpanZoom =\n zoomRange == null ||\n (Number.isFinite(zoomRange.start) &&\n Number.isFinite(zoomRange.end) &&\n zoomRange.start <= 0 &&\n zoomRange.end >= 100);\n if (isFullSpanZoom && s.sampling === 'none') {\n gpuSeriesKindByIndex[i] = 'fullRawLine';\n } else {\n gpuSeriesKindByIndex[i] = 'other';\n }\n\n // If `areaStyle` is provided on a line series, render a fill behind it.\n if (s.areaStyle) {\n const areaLike: ResolvedAreaSeriesConfig = {\n type: 'area',\n name: s.name,\n rawData: s.data,\n data: s.data,\n color: s.areaStyle.color,\n areaStyle: s.areaStyle,\n sampling: s.sampling,\n samplingThreshold: s.samplingThreshold,\n };\n\n areaRenderers[i].prepare(areaLike, areaLike.data, xScale, yScale, defaultBaseline);\n }\n\n break;\n }\n case 'bar': {\n barSeriesConfigs.push(s);\n break;\n }\n case 'scatter': {\n // Scatter renderer sets/resets its own scissor. Animate intro via alpha fade.\n const animated = introP < 1 ? ({ ...s, color: withAlpha(s.color, introP) } as const) : s;\n scatterRenderers[i].prepare(animated, s.data, xScale, yScale, gridArea);\n break;\n }\n case 'pie': {\n // Pie renderer sets/resets its own scissor. Animate intro via radius scale (CSS px).\n if (introP < 1) {\n const canvas = gpuContext.canvas;\n const plotWidthCss = interactionScales?.plotWidthCss ?? (canvas ? getPlotSizeCssPx(canvas, gridArea)?.plotWidthCss : null);\n const plotHeightCss =\n interactionScales?.plotHeightCss ?? (canvas ? getPlotSizeCssPx(canvas, gridArea)?.plotHeightCss : null);\n const maxRadiusCss =\n typeof plotWidthCss === 'number' && typeof plotHeightCss === 'number'\n ? 0.5 * Math.min(plotWidthCss, plotHeightCss)\n : 0;\n\n if (maxRadiusCss > 0) {\n const radiiCss = resolvePieRadiiCss(s.radius, maxRadiusCss);\n const inner = Math.max(0, radiiCss.inner) * introP;\n const outer = Math.max(inner, radiiCss.outer) * introP;\n const animated: ResolvedPieSeriesConfig = { ...s, radius: [inner, outer] as const };\n pieRenderers[i].prepare(animated, gridArea);\n break;\n }\n }\n pieRenderers[i].prepare(s, gridArea);\n break;\n }\n default:\n assertUnreachable(s);\n }\n }\n\n // Bars are prepared once and rendered via a single instanced draw call.\n const yScaleForBars = introP < 1 ? createAnimatedBarYScale(yScale, plotClipRect, barSeriesConfigs, introP) : yScale;\n barRenderer.prepare(barSeriesConfigs, dataStore, xScale, yScaleForBars, gridArea);\n\n const textureView = gpuContext.canvasContext.getCurrentTexture().createView();\n const encoder = device.createCommandEncoder({ label: 'renderCoordinator/commandEncoder' });\n const clearValue = parseCssColorToGPUColor(currentOptions.theme.backgroundColor, { r: 0, g: 0, b: 0, a: 1 });\n\n const pass = encoder.beginRenderPass({\n label: 'renderCoordinator/renderPass',\n colorAttachments: [\n {\n view: textureView,\n clearValue,\n loadOp: 'clear',\n storeOp: 'store',\n },\n ],\n });\n\n // Render order:\n // - grid first (background)\n // - pies early (non-cartesian, visible behind cartesian series)\n // - area fills next (so they don't cover strokes/axes)\n // - bars next (fills)\n // - scatter next (points on top of fills, below strokes/overlays)\n // - line strokes next\n // - highlight next (on top of strokes)\n // - axes last (on top)\n gridRenderer.render(pass);\n\n for (let i = 0; i < seriesForRender.length; i++) {\n if (seriesForRender[i].type === 'pie') {\n pieRenderers[i].render(pass);\n }\n }\n\n for (let i = 0; i < seriesForRender.length; i++) {\n if (shouldRenderArea(seriesForRender[i])) {\n // Line/area intro reveal: left-to-right plot scissor.\n if (introP < 1) {\n const w = clampInt(Math.floor(plotScissor.w * introP), 0, plotScissor.w);\n if (w > 0 && plotScissor.h > 0) {\n pass.setScissorRect(plotScissor.x, plotScissor.y, w, plotScissor.h);\n areaRenderers[i].render(pass);\n pass.setScissorRect(0, 0, gridArea.canvasWidth, gridArea.canvasHeight);\n }\n } else {\n areaRenderers[i].render(pass);\n }\n }\n }\n barRenderer.render(pass);\n for (let i = 0; i < seriesForRender.length; i++) {\n if (seriesForRender[i].type === 'scatter') {\n scatterRenderers[i].render(pass);\n }\n }\n for (let i = 0; i < seriesForRender.length; i++) {\n if (seriesForRender[i].type === 'line') {\n // Line intro reveal: left-to-right plot scissor.\n if (introP < 1) {\n const w = clampInt(Math.floor(plotScissor.w * introP), 0, plotScissor.w);\n if (w > 0 && plotScissor.h > 0) {\n pass.setScissorRect(plotScissor.x, plotScissor.y, w, plotScissor.h);\n lineRenderers[i].render(pass);\n pass.setScissorRect(0, 0, gridArea.canvasWidth, gridArea.canvasHeight);\n }\n } else {\n lineRenderers[i].render(pass);\n }\n }\n }\n\n highlightRenderer.render(pass);\n if (hasCartesianSeries) {\n xAxisRenderer.render(pass);\n yAxisRenderer.render(pass);\n }\n crosshairRenderer.render(pass);\n\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n hasRenderedOnce = true;\n\n if (overlay && overlayContainer) {\n const canvas = gpuContext.canvas;\n // IMPORTANT: overlay positioning must be done in *CSS pixels* and in the overlayContainer's\n // coordinate space (its padding box). Using `canvas.width / dpr` + `getBoundingClientRect()`\n // deltas can drift under CSS scaling/zoom and misalign with container padding/border.\n const canvasCssWidth = canvas.clientWidth;\n const canvasCssHeight = canvas.clientHeight;\n if (canvasCssWidth <= 0 || canvasCssHeight <= 0) return;\n\n // Since the overlay is absolutely positioned relative to the canvas container,\n // `offsetLeft/offsetTop` match that coordinate space.\n const offsetX = canvas.offsetLeft;\n const offsetY = canvas.offsetTop;\n\n const plotLeftCss = clipXToCanvasCssPx(plotClipRect.left, canvasCssWidth);\n const plotRightCss = clipXToCanvasCssPx(plotClipRect.right, canvasCssWidth);\n const plotTopCss = clipYToCanvasCssPx(plotClipRect.top, canvasCssHeight);\n const plotBottomCss = clipYToCanvasCssPx(plotClipRect.bottom, canvasCssHeight);\n\n overlay.clear();\n if (!hasCartesianSeries) return;\n\n // Mirror tick generation logic from `createAxisRenderer` exactly (tick count and domain fallback).\n const xTickCount = DEFAULT_TICK_COUNT;\n const xTickLengthCssPx = currentOptions.xAxis.tickLength ?? DEFAULT_TICK_LENGTH_CSS_PX;\n const xDomainMin = currentOptions.xAxis.min ?? xScale.invert(plotClipRect.left);\n const xDomainMax = currentOptions.xAxis.max ?? xScale.invert(plotClipRect.right);\n const xTickStep = xTickCount === 1 ? 0 : (xDomainMax - xDomainMin) / (xTickCount - 1);\n const xFormatter = createTickFormatter(xTickStep);\n const xLabelY = plotBottomCss + xTickLengthCssPx + LABEL_PADDING_CSS_PX + currentOptions.theme.fontSize * 0.5;\n\n for (let i = 0; i < xTickCount; i++) {\n const t = xTickCount === 1 ? 0.5 : i / (xTickCount - 1);\n const v = xDomainMin + t * (xDomainMax - xDomainMin);\n const xClip = xScale.scale(v);\n const xCss = clipXToCanvasCssPx(xClip, canvasCssWidth);\n\n const anchor: TextOverlayAnchor = i === 0 ? 'start' : i === xTickCount - 1 ? 'end' : 'middle';\n const label = formatTickValue(xFormatter, v);\n if (label == null) continue;\n const span = overlay.addLabel(label, offsetX + xCss, offsetY + xLabelY, {\n fontSize: currentOptions.theme.fontSize,\n color: currentOptions.theme.textColor,\n anchor,\n });\n span.dir = 'auto';\n span.style.fontFamily = currentOptions.theme.fontFamily;\n }\n\n const yTickCount = DEFAULT_TICK_COUNT;\n const yTickLengthCssPx = currentOptions.yAxis.tickLength ?? DEFAULT_TICK_LENGTH_CSS_PX;\n const yDomainMin = currentOptions.yAxis.min ?? yScale.invert(plotClipRect.bottom);\n const yDomainMax = currentOptions.yAxis.max ?? yScale.invert(plotClipRect.top);\n const yTickStep = yTickCount === 1 ? 0 : (yDomainMax - yDomainMin) / (yTickCount - 1);\n const yFormatter = createTickFormatter(yTickStep);\n const yLabelX = plotLeftCss - yTickLengthCssPx - LABEL_PADDING_CSS_PX;\n const ySpans: HTMLSpanElement[] = [];\n\n for (let i = 0; i < yTickCount; i++) {\n const t = yTickCount === 1 ? 0.5 : i / (yTickCount - 1);\n const v = yDomainMin + t * (yDomainMax - yDomainMin);\n const yClip = yScale.scale(v);\n const yCss = clipYToCanvasCssPx(yClip, canvasCssHeight);\n\n const label = formatTickValue(yFormatter, v);\n if (label == null) continue;\n const span = overlay.addLabel(label, offsetX + yLabelX, offsetY + yCss, {\n fontSize: currentOptions.theme.fontSize,\n color: currentOptions.theme.textColor,\n anchor: 'end',\n });\n span.dir = 'auto';\n span.style.fontFamily = currentOptions.theme.fontFamily;\n ySpans.push(span);\n }\n\n const axisNameFontSize = Math.max(\n currentOptions.theme.fontSize + 1,\n Math.round(currentOptions.theme.fontSize * 1.15)\n );\n\n const xAxisName = currentOptions.xAxis.name?.trim() ?? '';\n if (xAxisName.length > 0) {\n const xCenter = (plotLeftCss + plotRightCss) / 2;\n const xTitleY =\n xLabelY + currentOptions.theme.fontSize * 0.5 + LABEL_PADDING_CSS_PX + axisNameFontSize * 0.5;\n const span = overlay.addLabel(xAxisName, offsetX + xCenter, offsetY + xTitleY, {\n fontSize: axisNameFontSize,\n color: currentOptions.theme.textColor,\n anchor: 'middle',\n });\n span.dir = 'auto';\n span.style.fontFamily = currentOptions.theme.fontFamily;\n span.style.fontWeight = '600';\n }\n\n const yAxisName = currentOptions.yAxis.name?.trim() ?? '';\n if (yAxisName.length > 0) {\n const maxTickLabelWidth =\n ySpans.length === 0\n ? 0\n : ySpans.reduce((max, s) => Math.max(max, s.getBoundingClientRect().width), 0);\n\n const yCenter = (plotTopCss + plotBottomCss) / 2;\n const yTickLabelLeft = yLabelX - maxTickLabelWidth;\n const yTitleX = yTickLabelLeft - LABEL_PADDING_CSS_PX - axisNameFontSize * 0.5;\n\n const span = overlay.addLabel(yAxisName, offsetX + yTitleX, offsetY + yCenter, {\n fontSize: axisNameFontSize,\n color: currentOptions.theme.textColor,\n anchor: 'middle',\n rotation: -90,\n });\n span.dir = 'auto';\n span.style.fontFamily = currentOptions.theme.fontFamily;\n span.style.fontWeight = '600';\n }\n }\n };\n\n const dispose: RenderCoordinator['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n // Story 5.16: stop intro animation and avoid further render requests.\n try {\n if (introAnimId) introAnimController.cancel(introAnimId);\n introAnimController.cancelAll();\n } catch {\n // best-effort\n }\n introAnimId = null;\n introPhase = 'done';\n introProgress01 = 1;\n\n // Story 5.17: stop update animation and avoid further render requests.\n try {\n if (updateAnimId) updateAnimController.cancel(updateAnimId);\n updateAnimController.cancelAll();\n } catch {\n // best-effort\n }\n updateAnimId = null;\n updateProgress01 = 1;\n updateTransition = null;\n\n cancelScheduledFlush();\n cancelZoomResampleDebounce();\n zoomResampleDue = false;\n\n pendingAppendByIndex.clear();\n\n insideZoom?.dispose();\n insideZoom = null;\n unsubscribeZoom?.();\n unsubscribeZoom = null;\n zoomState = null;\n lastOptionsZoomRange = null;\n zoomRangeListeners.clear();\n\n eventManager.dispose();\n crosshairRenderer.dispose();\n highlightRenderer.dispose();\n\n for (let i = 0; i < areaRenderers.length; i++) {\n areaRenderers[i].dispose();\n }\n areaRenderers.length = 0;\n\n for (let i = 0; i < lineRenderers.length; i++) {\n lineRenderers[i].dispose();\n }\n lineRenderers.length = 0;\n\n for (let i = 0; i < scatterRenderers.length; i++) {\n scatterRenderers[i].dispose();\n }\n scatterRenderers.length = 0;\n\n for (let i = 0; i < pieRenderers.length; i++) {\n pieRenderers[i].dispose();\n }\n pieRenderers.length = 0;\n\n barRenderer.dispose();\n\n gridRenderer.dispose();\n xAxisRenderer.dispose();\n yAxisRenderer.dispose();\n\n dataStore.dispose();\n\n // Dispose tooltip/legend before the text overlay (all touch container positioning).\n tooltip?.dispose();\n tooltip = null;\n legend?.dispose();\n overlay?.dispose();\n };\n\n const getInteractionX: RenderCoordinator['getInteractionX'] = () => interactionX;\n\n const setInteractionX: RenderCoordinator['setInteractionX'] = (x, source) => {\n assertNotDisposed();\n const normalized = x !== null && Number.isFinite(x) ? x : null;\n\n // External interaction should not depend on y, so we treat it as “sync” mode.\n pointerState = { ...pointerState, source: normalized === null ? 'mouse' : 'sync' };\n\n setInteractionXInternal(normalized, source);\n\n if (normalized === null && pointerState.hasPointer === false) {\n crosshairRenderer.setVisible(false);\n highlightRenderer.setVisible(false);\n tooltip?.hide();\n }\n requestRender();\n };\n\n const onInteractionXChange: RenderCoordinator['onInteractionXChange'] = (callback) => {\n assertNotDisposed();\n interactionXListeners.add(callback);\n return () => {\n interactionXListeners.delete(callback);\n };\n };\n\n const getZoomRange: RenderCoordinator['getZoomRange'] = () => {\n return zoomState?.getRange() ?? null;\n };\n\n const setZoomRange: RenderCoordinator['setZoomRange'] = (start, end) => {\n assertNotDisposed();\n if (!zoomState) return;\n zoomState.setRange(start, end);\n // onChange will requestRender + emit.\n };\n\n const onZoomRangeChange: RenderCoordinator['onZoomRangeChange'] = (cb) => {\n assertNotDisposed();\n zoomRangeListeners.add(cb);\n return () => {\n zoomRangeListeners.delete(cb);\n };\n };\n\n return {\n setOptions,\n appendData,\n getInteractionX,\n setInteractionX,\n onInteractionXChange,\n getZoomRange,\n setZoomRange,\n onZoomRangeChange,\n render,\n dispose,\n };\n}\n\n","import type { AreaStyleConfig, ChartGPUOptions, GridConfig, LineStyleConfig } from './types';\n\nexport const defaultGrid = {\n left: 60,\n right: 20,\n top: 40,\n bottom: 40,\n} as const satisfies Required<GridConfig>;\n\nexport const defaultPalette = [\n '#5470C6',\n '#91CC75',\n '#FAC858',\n '#EE6666',\n '#73C0DE',\n '#3BA272',\n '#FC8452',\n '#9A60B4',\n '#EA7CCC',\n] as const;\n\nexport const defaultLineStyle = {\n width: 2,\n opacity: 1,\n} as const satisfies Required<Omit<LineStyleConfig, 'color'>>;\n\nexport const defaultAreaStyle = {\n opacity: 0.25,\n} as const satisfies Required<Omit<AreaStyleConfig, 'color'>>;\n\nexport const defaultOptions = {\n grid: defaultGrid,\n xAxis: { type: 'value' },\n yAxis: { type: 'value' },\n autoScroll: false,\n theme: 'dark',\n palette: defaultPalette,\n series: [],\n} as const satisfies Readonly<\n Required<Pick<ChartGPUOptions, 'grid' | 'xAxis' | 'yAxis' | 'autoScroll' | 'theme' | 'palette'>> & {\n readonly series: readonly [];\n }\n>;\n\n","import type { ThemeConfig } from './types';\n\nconst palette = [\n '#00E5FF',\n '#FF2D95',\n '#B026FF',\n '#00F5A0',\n '#FFD300',\n '#FF6B00',\n '#4D5BFF',\n '#FF3D3D',\n] as const;\n\nexport const darkTheme = {\n backgroundColor: '#1a1a2e',\n textColor: '#e0e0e0',\n axisLineColor: 'rgba(224,224,224,0.35)',\n axisTickColor: 'rgba(224,224,224,0.55)',\n gridLineColor: 'rgba(255,255,255,0.1)',\n colorPalette: [...palette],\n fontFamily:\n 'system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n fontSize: 12,\n} satisfies ThemeConfig;\n","import type { ThemeConfig } from './types';\n\nconst palette = [\n '#1F77B4',\n '#FF7F0E',\n '#2CA02C',\n '#D62728',\n '#9467BD',\n '#8C564B',\n '#E377C2',\n '#17BECF',\n] as const;\n\nexport const lightTheme = {\n backgroundColor: '#ffffff',\n textColor: '#333333',\n axisLineColor: 'rgba(0,0,0,0.35)',\n axisTickColor: 'rgba(0,0,0,0.55)',\n gridLineColor: 'rgba(0,0,0,0.1)',\n colorPalette: [...palette],\n fontFamily:\n 'system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n fontSize: 12,\n} satisfies ThemeConfig;\n","import type { ThemeConfig } from './types';\nimport { darkTheme } from './darkTheme';\nimport { lightTheme } from './lightTheme';\n\nexport { darkTheme, lightTheme };\nexport type { ThemeConfig };\n\nexport type ThemeName = 'dark' | 'light';\n\nexport function getTheme(name: ThemeName): ThemeConfig {\n return name === 'dark' ? darkTheme : lightTheme;\n}\n","import type {\n AreaStyleConfig,\n AxisConfig,\n ChartGPUOptions,\n DataPoint,\n DataPointTuple,\n DataZoomConfig,\n GridConfig,\n LineStyleConfig,\n AreaSeriesConfig,\n BarSeriesConfig,\n LineSeriesConfig,\n PieDataItem,\n PieSeriesConfig,\n ScatterSeriesConfig,\n SeriesSampling,\n} from './types';\nimport { defaultAreaStyle, defaultLineStyle, defaultOptions, defaultPalette } from './defaults';\nimport { getTheme } from '../themes';\nimport type { ThemeConfig } from '../themes/types';\nimport { sampleSeriesDataPoints } from '../data/sampleSeries';\n\nexport type ResolvedGridConfig = Readonly<Required<GridConfig>>;\nexport type ResolvedLineStyleConfig = Readonly<Required<Omit<LineStyleConfig, 'color'>> & { readonly color: string }>;\nexport type ResolvedAreaStyleConfig = Readonly<Required<Omit<AreaStyleConfig, 'color'>> & { readonly color: string }>;\n\nexport type RawBounds = Readonly<{ xMin: number; xMax: number; yMin: number; yMax: number }>;\n\nexport type ResolvedLineSeriesConfig = Readonly<\n Omit<LineSeriesConfig, 'color' | 'lineStyle' | 'areaStyle' | 'sampling' | 'samplingThreshold' | 'data'> & {\n readonly color: string;\n readonly lineStyle: ResolvedLineStyleConfig;\n readonly areaStyle?: ResolvedAreaStyleConfig;\n readonly sampling: SeriesSampling;\n readonly samplingThreshold: number;\n /**\n * Original (unsampled) series data.\n *\n * Used at runtime for zoom-aware re-sampling so we can increase detail when zoomed-in without\n * losing outliers or permanently discarding points.\n */\n readonly rawData: Readonly<LineSeriesConfig['data']>;\n readonly data: Readonly<LineSeriesConfig['data']>;\n /**\n * Bounds computed from the original (unsampled) data. Used for axis auto-bounds so sampling\n * cannot clip outliers.\n */\n readonly rawBounds?: RawBounds;\n }\n>;\n\nexport type ResolvedAreaSeriesConfig = Readonly<\n Omit<AreaSeriesConfig, 'color' | 'areaStyle' | 'sampling' | 'samplingThreshold' | 'data'> & {\n readonly color: string;\n readonly areaStyle: ResolvedAreaStyleConfig;\n readonly sampling: SeriesSampling;\n readonly samplingThreshold: number;\n /** Original (unsampled) series data (see `ResolvedLineSeriesConfig.rawData`). */\n readonly rawData: Readonly<AreaSeriesConfig['data']>;\n readonly data: Readonly<AreaSeriesConfig['data']>;\n /**\n * Bounds computed from the original (unsampled) data. Used for axis auto-bounds so sampling\n * cannot clip outliers.\n */\n readonly rawBounds?: RawBounds;\n }\n>;\n\nexport type ResolvedBarSeriesConfig = Readonly<\n Omit<BarSeriesConfig, 'color' | 'sampling' | 'samplingThreshold' | 'data'> & {\n readonly color: string;\n readonly sampling: SeriesSampling;\n readonly samplingThreshold: number;\n /** Original (unsampled) series data (see `ResolvedLineSeriesConfig.rawData`). */\n readonly rawData: Readonly<BarSeriesConfig['data']>;\n readonly data: Readonly<BarSeriesConfig['data']>;\n /**\n * Bounds computed from the original (unsampled) data. Used for axis auto-bounds so sampling\n * cannot clip outliers.\n */\n readonly rawBounds?: RawBounds;\n }\n>;\n\nexport type ResolvedScatterSeriesConfig = Readonly<\n Omit<ScatterSeriesConfig, 'color' | 'sampling' | 'samplingThreshold' | 'data'> & {\n readonly color: string;\n readonly sampling: SeriesSampling;\n readonly samplingThreshold: number;\n /** Original (unsampled) series data (see `ResolvedLineSeriesConfig.rawData`). */\n readonly rawData: Readonly<ScatterSeriesConfig['data']>;\n readonly data: Readonly<ScatterSeriesConfig['data']>;\n /**\n * Bounds computed from the original (unsampled) data. Used for axis auto-bounds so sampling\n * cannot clip outliers.\n */\n readonly rawBounds?: RawBounds;\n }\n>;\n\nexport type ResolvedPieDataItem = Readonly<Omit<PieDataItem, 'color'> & { readonly color: string }>;\n\nexport type ResolvedPieSeriesConfig = Readonly<\n Omit<PieSeriesConfig, 'color' | 'data'> & {\n readonly color: string;\n readonly data: ReadonlyArray<ResolvedPieDataItem>;\n }\n>;\n\nexport type ResolvedSeriesConfig =\n | ResolvedLineSeriesConfig\n | ResolvedAreaSeriesConfig\n | ResolvedBarSeriesConfig\n | ResolvedScatterSeriesConfig\n | ResolvedPieSeriesConfig;\n\nexport interface ResolvedChartGPUOptions\n extends Omit<ChartGPUOptions, 'grid' | 'xAxis' | 'yAxis' | 'theme' | 'palette' | 'series'> {\n readonly grid: ResolvedGridConfig;\n readonly xAxis: AxisConfig;\n readonly yAxis: AxisConfig;\n readonly autoScroll: boolean;\n readonly theme: ThemeConfig;\n readonly palette: ReadonlyArray<string>;\n readonly series: ReadonlyArray<ResolvedSeriesConfig>;\n}\n\nconst sanitizeDataZoom = (input: unknown): ReadonlyArray<DataZoomConfig> | undefined => {\n if (!Array.isArray(input)) return undefined;\n\n const out: DataZoomConfig[] = [];\n\n for (const item of input) {\n if (item === null || typeof item !== 'object' || Array.isArray(item)) continue;\n const record = item as Record<string, unknown>;\n\n const type = record.type;\n if (type !== 'inside' && type !== 'slider') continue;\n\n const xAxisIndexRaw = record.xAxisIndex;\n const startRaw = record.start;\n const endRaw = record.end;\n const minSpanRaw = record.minSpan;\n const maxSpanRaw = record.maxSpan;\n\n const xAxisIndex =\n typeof xAxisIndexRaw === 'number' && Number.isFinite(xAxisIndexRaw) ? xAxisIndexRaw : undefined;\n const start = typeof startRaw === 'number' && Number.isFinite(startRaw) ? startRaw : undefined;\n const end = typeof endRaw === 'number' && Number.isFinite(endRaw) ? endRaw : undefined;\n const minSpan =\n typeof minSpanRaw === 'number' && Number.isFinite(minSpanRaw) ? minSpanRaw : undefined;\n const maxSpan =\n typeof maxSpanRaw === 'number' && Number.isFinite(maxSpanRaw) ? maxSpanRaw : undefined;\n\n out.push({ type, xAxisIndex, start, end, minSpan, maxSpan });\n }\n\n return out;\n};\n\nconst sanitizePalette = (palette: unknown): string[] => {\n if (!Array.isArray(palette)) return [];\n return palette\n .filter((c): c is string => typeof c === 'string')\n .map((c) => c.trim())\n .filter((c) => c.length > 0);\n};\n\nconst resolveTheme = (themeInput: unknown): ThemeConfig => {\n const base = getTheme('dark');\n\n if (typeof themeInput === 'string') {\n const name = themeInput.trim().toLowerCase();\n return name === 'light' ? getTheme('light') : getTheme('dark');\n }\n\n if (themeInput === null || typeof themeInput !== 'object' || Array.isArray(themeInput)) {\n return base;\n }\n\n const input = themeInput as Partial<Record<keyof ThemeConfig, unknown>>;\n const takeString = (key: keyof ThemeConfig): string | undefined => {\n const v = input[key];\n if (typeof v !== 'string') return undefined;\n const trimmed = v.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n };\n\n const fontSizeRaw = input.fontSize;\n const fontSize =\n typeof fontSizeRaw === 'number' && Number.isFinite(fontSizeRaw) ? fontSizeRaw : undefined;\n\n const colorPaletteCandidate = sanitizePalette(input.colorPalette);\n\n return {\n backgroundColor: takeString('backgroundColor') ?? base.backgroundColor,\n textColor: takeString('textColor') ?? base.textColor,\n axisLineColor: takeString('axisLineColor') ?? base.axisLineColor,\n axisTickColor: takeString('axisTickColor') ?? base.axisTickColor,\n gridLineColor: takeString('gridLineColor') ?? base.gridLineColor,\n colorPalette: colorPaletteCandidate.length > 0 ? colorPaletteCandidate : Array.from(base.colorPalette),\n fontFamily: takeString('fontFamily') ?? base.fontFamily,\n fontSize: fontSize ?? base.fontSize,\n };\n};\n\nconst normalizeOptionalColor = (color: unknown): string | undefined => {\n if (typeof color !== 'string') return undefined;\n const trimmed = color.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\nconst normalizeSampling = (value: unknown): SeriesSampling | undefined => {\n if (typeof value !== 'string') return undefined;\n const v = value.trim().toLowerCase();\n return v === 'none' || v === 'lttb' || v === 'average' || v === 'max' || v === 'min'\n ? (v as SeriesSampling)\n : undefined;\n};\n\nconst normalizeSamplingThreshold = (value: unknown): number | undefined => {\n if (typeof value !== 'number' || !Number.isFinite(value)) return undefined;\n const t = Math.floor(value);\n return t > 0 ? t : undefined;\n};\n\nconst isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p);\n\nconst computeRawBoundsFromData = (data: ReadonlyArray<DataPoint>): RawBounds | undefined => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < data.length; i++) {\n const p = data[i]!;\n const x = isTupleDataPoint(p) ? p[0] : p.x;\n const y = isTupleDataPoint(p) ? p[1] : p.y;\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return undefined;\n }\n\n // Keep bounds usable for downstream scale derivation.\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst assertUnreachable = (value: never): never => {\n // Should never happen if SeriesConfig union is exhaustively handled.\n // This is defensive runtime safety for JS callers / invalid inputs.\n throw new Error(\n `Unhandled series type: ${\n (value as unknown as { readonly type?: unknown } | null)?.type ?? 'unknown'\n }`\n );\n};\n\nexport function resolveOptions(userOptions: ChartGPUOptions = {}): ResolvedChartGPUOptions {\n const baseTheme = resolveTheme(userOptions.theme);\n\n // runtime safety for JS callers\n const autoScrollRaw = (userOptions as unknown as { readonly autoScroll?: unknown }).autoScroll;\n const autoScroll = typeof autoScrollRaw === 'boolean' ? autoScrollRaw : defaultOptions.autoScroll;\n\n // runtime safety for JS callers\n const animationRaw = (userOptions as unknown as { readonly animation?: unknown }).animation;\n const animationCandidate: ChartGPUOptions['animation'] =\n typeof animationRaw === 'boolean' ||\n (animationRaw !== null && typeof animationRaw === 'object' && !Array.isArray(animationRaw))\n ? (animationRaw as ChartGPUOptions['animation'])\n : undefined;\n // Default: animation enabled (with defaults) unless explicitly disabled.\n const animation: ChartGPUOptions['animation'] = animationCandidate ?? true;\n\n // Backward compatibility:\n // - If `userOptions.palette` is provided (non-empty), treat it as an override for the theme palette.\n const paletteOverride = sanitizePalette(userOptions.palette);\n\n const themeCandidate: ThemeConfig =\n paletteOverride.length > 0 ? { ...baseTheme, colorPalette: paletteOverride } : baseTheme;\n\n // Ensure palette used for modulo indexing is never empty.\n const paletteFromTheme = sanitizePalette(themeCandidate.colorPalette);\n const safePalette =\n paletteFromTheme.length > 0\n ? paletteFromTheme\n : sanitizePalette(defaultOptions.palette ?? defaultPalette).length > 0\n ? sanitizePalette(defaultOptions.palette ?? defaultPalette)\n : Array.from(defaultPalette);\n\n const paletteForIndexing = safePalette.length > 0 ? safePalette : ['#000000'];\n const theme: ThemeConfig = { ...themeCandidate, colorPalette: paletteForIndexing.slice() };\n\n const grid: ResolvedGridConfig = {\n left: userOptions.grid?.left ?? defaultOptions.grid.left,\n right: userOptions.grid?.right ?? defaultOptions.grid.right,\n top: userOptions.grid?.top ?? defaultOptions.grid.top,\n bottom: userOptions.grid?.bottom ?? defaultOptions.grid.bottom,\n };\n\n const xAxis: AxisConfig = userOptions.xAxis\n ? {\n ...defaultOptions.xAxis,\n ...userOptions.xAxis,\n // runtime safety for JS callers\n type: (userOptions.xAxis as unknown as Partial<AxisConfig>).type ?? defaultOptions.xAxis.type,\n }\n : { ...defaultOptions.xAxis };\n\n const yAxis: AxisConfig = userOptions.yAxis\n ? {\n ...defaultOptions.yAxis,\n ...userOptions.yAxis,\n // runtime safety for JS callers\n type: (userOptions.yAxis as unknown as Partial<AxisConfig>).type ?? defaultOptions.yAxis.type,\n }\n : { ...defaultOptions.yAxis };\n\n const series: ReadonlyArray<ResolvedSeriesConfig> = (userOptions.series ?? []).map((s, i) => {\n const explicitColor = normalizeOptionalColor(s.color);\n const inheritedColor = theme.colorPalette[i % theme.colorPalette.length];\n const color = explicitColor ?? inheritedColor;\n\n const sampling: SeriesSampling = normalizeSampling((s as unknown as { sampling?: unknown }).sampling) ?? 'lttb';\n const samplingThreshold: number =\n normalizeSamplingThreshold((s as unknown as { samplingThreshold?: unknown }).samplingThreshold) ?? 5000;\n\n switch (s.type) {\n case 'area': {\n // Resolve effective fill color with precedence: areaStyle.color → series.color → palette\n const areaStyleColor = normalizeOptionalColor(s.areaStyle?.color);\n const effectiveColor = areaStyleColor ?? explicitColor ?? inheritedColor;\n\n const areaStyle: ResolvedAreaStyleConfig = {\n opacity: s.areaStyle?.opacity ?? defaultAreaStyle.opacity,\n color: effectiveColor,\n };\n\n const rawBounds = computeRawBoundsFromData(s.data);\n return {\n ...s,\n rawData: s.data,\n data: sampleSeriesDataPoints(s.data, sampling, samplingThreshold),\n color: effectiveColor,\n areaStyle,\n sampling,\n samplingThreshold,\n rawBounds,\n };\n }\n case 'line': {\n // Resolve effective stroke color with precedence: lineStyle.color → series.color → palette\n const lineStyleColor = normalizeOptionalColor(s.lineStyle?.color);\n const effectiveStrokeColor = lineStyleColor ?? explicitColor ?? inheritedColor;\n\n const lineStyle: ResolvedLineStyleConfig = {\n width: s.lineStyle?.width ?? defaultLineStyle.width,\n opacity: s.lineStyle?.opacity ?? defaultLineStyle.opacity,\n color: effectiveStrokeColor,\n };\n\n // Avoid leaking the unresolved (user) areaStyle shape via object spread.\n const { areaStyle: _userAreaStyle, ...rest } = s;\n const rawBounds = computeRawBoundsFromData(s.data);\n const sampledData = sampleSeriesDataPoints(s.data, sampling, samplingThreshold);\n\n return {\n ...rest,\n rawData: s.data,\n data: sampledData,\n color: effectiveStrokeColor,\n lineStyle,\n ...(s.areaStyle\n ? {\n areaStyle: {\n opacity: s.areaStyle.opacity ?? defaultAreaStyle.opacity,\n // Fill color precedence: areaStyle.color → resolved stroke color\n color: normalizeOptionalColor(s.areaStyle.color) ?? effectiveStrokeColor,\n },\n }\n : {}),\n sampling,\n samplingThreshold,\n rawBounds,\n };\n }\n case 'bar': {\n const rawBounds = computeRawBoundsFromData(s.data);\n return {\n ...s,\n rawData: s.data,\n data: sampleSeriesDataPoints(s.data, sampling, samplingThreshold),\n color,\n sampling,\n samplingThreshold,\n rawBounds,\n };\n }\n case 'scatter': {\n const rawBounds = computeRawBoundsFromData(s.data);\n return {\n ...s,\n rawData: s.data,\n data: sampleSeriesDataPoints(s.data, sampling, samplingThreshold),\n color,\n sampling,\n samplingThreshold,\n rawBounds,\n };\n }\n case 'pie': {\n // Pie series intentionally do NOT support sampling at runtime.\n // For JS callers, strip any extra sampling keys so they don't leak through the resolver.\n const { sampling: _sampling, samplingThreshold: _samplingThreshold, ...rest } = s as PieSeriesConfig & {\n readonly sampling?: unknown;\n readonly samplingThreshold?: unknown;\n };\n\n const resolvedData: ReadonlyArray<ResolvedPieDataItem> = (s.data ?? []).map((item, itemIndex) => {\n const itemColor = normalizeOptionalColor(item?.color);\n const fallback = theme.colorPalette[(i + itemIndex) % theme.colorPalette.length];\n return {\n ...item,\n color: itemColor ?? fallback,\n };\n });\n\n return { ...rest, color, data: resolvedData };\n }\n default: {\n return assertUnreachable(s);\n }\n }\n });\n\n return {\n grid,\n xAxis,\n yAxis,\n autoScroll,\n dataZoom: sanitizeDataZoom((userOptions as ChartGPUOptions).dataZoom),\n animation,\n theme,\n palette: theme.colorPalette,\n series,\n };\n}\n\nexport const OptionResolver = { resolve: resolveOptions } as const;\n\n","import type { ZoomRange, ZoomState } from '../interaction/createZoomState';\nimport type { ThemeConfig } from '../themes/types';\n\nexport interface DataZoomSlider {\n update(theme: ThemeConfig): void;\n dispose(): void;\n}\n\nexport interface DataZoomSliderOptions {\n readonly height?: number;\n readonly marginTop?: number;\n readonly zIndex?: number;\n readonly showPreview?: boolean;\n}\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v));\n\nconst normalizeRange = (range: ZoomRange): ZoomRange => {\n let { start, end } = range;\n if (start > end) {\n const t = start;\n start = end;\n end = t;\n }\n return { start: clamp(start, 0, 100), end: clamp(end, 0, 100) };\n};\n\ntype DragMode = 'left-handle' | 'right-handle' | 'pan-window';\n\nexport function createDataZoomSlider(\n container: HTMLElement,\n zoomState: ZoomState,\n options?: DataZoomSliderOptions\n): DataZoomSlider {\n const height = options?.height ?? 32;\n const marginTop = options?.marginTop ?? 8;\n const zIndex = options?.zIndex ?? 4;\n const showPreview = options?.showPreview ?? false;\n\n const root = document.createElement('div');\n root.style.display = 'block';\n root.style.width = '100%';\n root.style.height = `${height}px`;\n root.style.marginTop = `${marginTop}px`;\n root.style.boxSizing = 'border-box';\n root.style.position = 'relative';\n root.style.zIndex = `${zIndex}`;\n root.style.userSelect = 'none';\n root.style.touchAction = 'none';\n\n // track: full-width bar that hosts preview + window selection.\n const track = document.createElement('div');\n track.style.position = 'relative';\n track.style.height = '100%';\n track.style.width = '100%';\n track.style.boxSizing = 'border-box';\n track.style.borderRadius = '8px';\n track.style.borderStyle = 'solid';\n track.style.borderWidth = '1px';\n track.style.overflow = 'hidden';\n root.appendChild(track);\n\n // preview: miniature context under the selection (optional; can be a solid bar for now).\n const preview = document.createElement('div');\n preview.style.position = 'absolute';\n preview.style.inset = '0';\n preview.style.pointerEvents = 'none';\n preview.style.opacity = '0.4';\n preview.style.display = showPreview ? 'block' : 'none';\n track.appendChild(preview);\n\n // window: the selected range.\n const windowEl = document.createElement('div');\n windowEl.style.position = 'absolute';\n windowEl.style.top = '0';\n windowEl.style.bottom = '0';\n windowEl.style.left = '0%';\n windowEl.style.width = '100%';\n windowEl.style.boxSizing = 'border-box';\n windowEl.style.cursor = 'grab';\n track.appendChild(windowEl);\n\n // left/right handles.\n const leftHandle = document.createElement('div');\n leftHandle.style.position = 'absolute';\n leftHandle.style.left = '0';\n leftHandle.style.top = '0';\n leftHandle.style.bottom = '0';\n leftHandle.style.width = '10px';\n leftHandle.style.cursor = 'ew-resize';\n windowEl.appendChild(leftHandle);\n\n const rightHandle = document.createElement('div');\n rightHandle.style.position = 'absolute';\n rightHandle.style.right = '0';\n rightHandle.style.top = '0';\n rightHandle.style.bottom = '0';\n rightHandle.style.width = '10px';\n rightHandle.style.cursor = 'ew-resize';\n windowEl.appendChild(rightHandle);\n\n // center grip (hit target for panning).\n const centerGrip = document.createElement('div');\n centerGrip.style.position = 'absolute';\n centerGrip.style.left = '10px';\n centerGrip.style.right = '10px';\n centerGrip.style.top = '0';\n centerGrip.style.bottom = '0';\n centerGrip.style.cursor = 'grab';\n windowEl.appendChild(centerGrip);\n\n container.appendChild(root);\n\n let disposed = false;\n let activeDragCleanup: (() => void) | null = null;\n\n const applyRangeToDom = (range: ZoomRange): void => {\n const r = normalizeRange(range);\n const span = clamp(r.end - r.start, 0, 100);\n windowEl.style.left = `${r.start}%`;\n windowEl.style.width = `${span}%`;\n };\n\n const getTrackWidthPx = (): number | null => {\n // getBoundingClientRect() is robust even if the container is scaled.\n const w = track.getBoundingClientRect().width;\n return Number.isFinite(w) && w > 0 ? w : null;\n };\n\n const pxToPercent = (dxPx: number): number | null => {\n const w = getTrackWidthPx();\n if (w === null) return null;\n const p = (dxPx / w) * 100;\n return Number.isFinite(p) ? p : null;\n };\n\n const setPointerCaptureBestEffort = (el: Element, pointerId: number): void => {\n try {\n (el as HTMLElement).setPointerCapture(pointerId);\n } catch {\n // Ignore (best-effort).\n }\n };\n\n const releasePointerCaptureBestEffort = (el: Element, pointerId: number): void => {\n try {\n (el as HTMLElement).releasePointerCapture(pointerId);\n } catch {\n // Ignore (best-effort).\n }\n };\n\n const startDrag = (e: PointerEvent, mode: DragMode): void => {\n if (disposed) return;\n if (e.button !== 0) return;\n\n e.preventDefault();\n\n // If we somehow start a new drag while another is in-flight, clean up first.\n activeDragCleanup?.();\n activeDragCleanup = null;\n\n const dragStartX = e.clientX;\n const startRange = zoomState.getRange();\n\n const target = e.currentTarget instanceof Element ? e.currentTarget : windowEl;\n setPointerCaptureBestEffort(target, e.pointerId);\n\n if (mode === 'pan-window') {\n windowEl.style.cursor = 'grabbing';\n centerGrip.style.cursor = 'grabbing';\n }\n\n const onMove = (ev: PointerEvent): void => {\n if (disposed) return;\n if (ev.pointerId !== e.pointerId) return;\n\n ev.preventDefault();\n\n const dxPercent = pxToPercent(ev.clientX - dragStartX);\n if (dxPercent === null) return;\n\n switch (mode) {\n case 'left-handle': {\n // UX: don't allow handle crossing; clamp left <= current end.\n const nextStart = Math.min(startRange.end, startRange.start + dxPercent);\n zoomState.setRange(nextStart, startRange.end);\n return;\n }\n case 'right-handle': {\n // UX: don't allow handle crossing; clamp right >= current start.\n const nextEnd = Math.max(startRange.start, startRange.end + dxPercent);\n zoomState.setRange(startRange.start, nextEnd);\n return;\n }\n case 'pan-window': {\n zoomState.pan(dxPercent);\n return;\n }\n }\n };\n\n let cleanedUp = false;\n\n const cleanup = (): void => {\n if (cleanedUp) return;\n cleanedUp = true;\n\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', finish);\n window.removeEventListener('pointercancel', finish);\n\n if (mode === 'pan-window') {\n windowEl.style.cursor = 'grab';\n centerGrip.style.cursor = 'grab';\n }\n\n releasePointerCaptureBestEffort(target, e.pointerId);\n\n // Only clear if we're still the active drag.\n if (activeDragCleanup === cleanup) activeDragCleanup = null;\n };\n\n const finish = (ev: PointerEvent): void => {\n if (ev.pointerId !== e.pointerId) return;\n cleanup();\n };\n\n activeDragCleanup = cleanup;\n\n window.addEventListener('pointermove', onMove, { passive: false });\n window.addEventListener('pointerup', finish, { passive: true });\n window.addEventListener('pointercancel', finish, { passive: true });\n };\n\n const onLeftDown = (e: PointerEvent): void => startDrag(e, 'left-handle');\n const onRightDown = (e: PointerEvent): void => startDrag(e, 'right-handle');\n const onPanDown = (e: PointerEvent): void => startDrag(e, 'pan-window');\n\n leftHandle.addEventListener('pointerdown', onLeftDown, { passive: false });\n rightHandle.addEventListener('pointerdown', onRightDown, { passive: false });\n centerGrip.addEventListener('pointerdown', onPanDown, { passive: false });\n\n // Keep DOM in sync with state.\n const unsubscribe = zoomState.onChange((range) => {\n if (disposed) return;\n applyRangeToDom(range);\n });\n\n // Initialize UI.\n applyRangeToDom(zoomState.getRange());\n\n const update: DataZoomSlider['update'] = (theme) => {\n if (disposed) return;\n\n // Baseline track styling.\n track.style.background = theme.backgroundColor;\n track.style.borderColor = theme.axisLineColor;\n\n // Preview styling (placeholder).\n preview.style.background = theme.gridLineColor;\n\n // Window styling.\n windowEl.style.background = theme.gridLineColor;\n windowEl.style.border = `1px solid ${theme.axisTickColor}`;\n windowEl.style.borderRadius = '8px';\n windowEl.style.boxSizing = 'border-box';\n\n // Handles styling.\n const handleBorder = `1px solid ${theme.axisLineColor}`;\n leftHandle.style.background = theme.axisTickColor;\n leftHandle.style.borderRight = handleBorder;\n rightHandle.style.background = theme.axisTickColor;\n rightHandle.style.borderLeft = handleBorder;\n\n // Center grip styling: subtle stripes.\n centerGrip.style.background = 'transparent';\n centerGrip.style.backgroundImage =\n 'linear-gradient(90deg, rgba(255,255,255,0.0) 0, rgba(255,255,255,0.0) 42%, rgba(255,255,255,0.18) 42%, rgba(255,255,255,0.18) 46%, rgba(255,255,255,0.0) 46%, rgba(255,255,255,0.0) 54%, rgba(255,255,255,0.18) 54%, rgba(255,255,255,0.18) 58%, rgba(255,255,255,0.0) 58%, rgba(255,255,255,0.0) 100%)';\n centerGrip.style.mixBlendMode = 'normal';\n };\n\n const dispose: DataZoomSlider['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n // If dispose happens during an active drag, ensure we remove all window listeners.\n activeDragCleanup?.();\n activeDragCleanup = null;\n\n try {\n unsubscribe();\n } catch {\n // Best-effort.\n }\n\n leftHandle.removeEventListener('pointerdown', onLeftDown);\n rightHandle.removeEventListener('pointerdown', onRightDown);\n centerGrip.removeEventListener('pointerdown', onPanDown);\n\n root.remove();\n };\n\n return { update, dispose };\n}\n\n","/**\n * WebGPU support detection and validation\n * \n * Provides utilities to check if WebGPU is available and usable in the current environment.\n * Results are memoized to avoid redundant checks.\n */\n\n/**\n * Result of WebGPU support check\n */\nexport interface WebGPUSupportResult {\n /** Whether WebGPU is supported and available */\n readonly supported: boolean;\n /** Optional reason explaining why WebGPU is not supported */\n readonly reason?: string;\n}\n\n// Memoized support check result\nlet cachedSupportCheck: Promise<WebGPUSupportResult> | null = null;\n\n/**\n * Checks if WebGPU is supported and available in the current environment.\n * \n * This function performs comprehensive checks:\n * - SSR-safe: validates that window and navigator are available\n * - Checks for navigator.gpu API presence\n * - Attempts to request a WebGPU adapter to verify actual support\n * - First tries high-performance adapter to match GPUContext behavior\n * - Falls back to default adapter if high-performance fails\n * \n * The result is memoized for performance, so multiple calls return the same promise.\n * \n * @returns Promise resolving to support check result with optional reason\n * \n * @example\n * ```typescript\n * const { supported, reason } = await checkWebGPUSupport();\n * if (!supported) {\n * console.error('WebGPU not available:', reason);\n * }\n * ```\n */\nexport async function checkWebGPUSupport(): Promise<WebGPUSupportResult> {\n // Return cached result if available\n if (cachedSupportCheck) {\n return cachedSupportCheck;\n }\n\n // Create and cache the promise\n cachedSupportCheck = (async (): Promise<WebGPUSupportResult> => {\n // SSR-safe checks: ensure we're in a browser environment\n if (typeof window === 'undefined') {\n return {\n supported: false,\n reason: 'Not running in a browser environment (window is undefined).',\n };\n }\n\n if (typeof navigator === 'undefined') {\n return {\n supported: false,\n reason: 'Navigator is not available in this environment.',\n };\n }\n\n // Check for navigator.gpu API\n if (!navigator.gpu) {\n return {\n supported: false,\n reason: 'WebGPU API (navigator.gpu) is not available. Your browser does not support WebGPU.',\n };\n }\n\n // Attempt to request an adapter to verify actual support\n try {\n // First attempt: high-performance adapter (aligns with GPUContext behavior)\n let adapter = await navigator.gpu.requestAdapter({\n powerPreference: 'high-performance',\n });\n\n // Second attempt: default adapter if high-performance is unavailable\n if (!adapter) {\n adapter = await navigator.gpu.requestAdapter();\n }\n\n // If both attempts fail, WebGPU is not usable\n if (!adapter) {\n return {\n supported: false,\n reason: 'No compatible WebGPU adapter found. This may occur if: (1) no GPU is available, (2) GPU drivers are outdated or incompatible, (3) running in a VM or headless environment, or (4) WebGPU is disabled in browser settings.',\n };\n }\n\n // Success: WebGPU is supported and an adapter is available\n return { supported: true };\n } catch (error) {\n // Adapter request threw an error\n let reason = 'Failed to request WebGPU adapter.';\n\n // Try to extract useful error information\n if (error instanceof DOMException) {\n reason = `Failed to request WebGPU adapter: ${error.name}`;\n if (error.message) {\n reason += ` - ${error.message}`;\n }\n } else if (error instanceof Error) {\n reason = `Failed to request WebGPU adapter: ${error.message}`;\n } else {\n reason = `Failed to request WebGPU adapter: ${String(error)}`;\n }\n\n return { supported: false, reason };\n }\n })();\n\n return cachedSupportCheck;\n}\n","import { GPUContext } from './core/GPUContext';\nimport { createRenderCoordinator } from './core/createRenderCoordinator';\nimport type { RenderCoordinator } from './core/createRenderCoordinator';\nimport { resolveOptions } from './config/OptionResolver';\nimport type { ResolvedChartGPUOptions, ResolvedPieSeriesConfig } from './config/OptionResolver';\nimport type { ChartGPUOptions, DataPoint, DataPointTuple, PieCenter, PieRadius } from './config/types';\nimport { createDataZoomSlider } from './components/createDataZoomSlider';\nimport type { DataZoomSlider } from './components/createDataZoomSlider';\nimport type { ZoomRange, ZoomState } from './interaction/createZoomState';\nimport { findNearestPoint } from './interaction/findNearestPoint';\nimport type { NearestPointMatch } from './interaction/findNearestPoint';\nimport { findPieSlice } from './interaction/findPieSlice';\nimport { createLinearScale } from './utils/scales';\nimport type { LinearScale } from './utils/scales';\nimport { checkWebGPUSupport } from './utils/checkWebGPU';\n\nexport interface ChartGPUInstance {\n readonly options: Readonly<ChartGPUOptions>;\n readonly disposed: boolean;\n setOption(options: ChartGPUOptions): void;\n /**\n * Appends new points to a cartesian series at runtime (streaming).\n *\n * Pie series are non-cartesian and are currently not supported by streaming append.\n */\n appendData(seriesIndex: number, newPoints: DataPoint[]): void;\n resize(): void;\n dispose(): void;\n on(eventName: 'crosshairMove', callback: ChartGPUCrosshairMoveCallback): void;\n on(eventName: ChartGPUEventName, callback: ChartGPUEventCallback): void;\n off(eventName: 'crosshairMove', callback: ChartGPUCrosshairMoveCallback): void;\n off(eventName: ChartGPUEventName, callback: ChartGPUEventCallback): void;\n /**\n * Gets the current “interaction x” in domain units (or `null` when inactive).\n *\n * This is derived from pointer movement inside the plot grid and can also be driven\n * externally via `setInteractionX(...)` (e.g. chart sync).\n */\n getInteractionX(): number | null;\n /**\n * Drives the chart’s crosshair + tooltip from a domain-space x value.\n *\n * Passing `null` clears the interaction (hides crosshair/tooltip).\n */\n setInteractionX(x: number | null, source?: unknown): void;\n /**\n * Alias for `setInteractionX(...)` for chart sync semantics.\n */\n setCrosshairX(x: number | null, source?: unknown): void;\n /**\n * Subscribes to interaction x changes (domain units).\n *\n * Returns an unsubscribe function.\n */\n onInteractionXChange(callback: (x: number | null, source?: unknown) => void): () => void;\n /**\n * Returns the current percent-space zoom window (or `null` when zoom is disabled).\n */\n getZoomRange(): Readonly<{ start: number; end: number }> | null;\n /**\n * Sets the percent-space zoom window.\n *\n * No-op when zoom is disabled.\n */\n setZoomRange(start: number, end: number): void;\n}\n\n// Type-only alias so callsites can write `ChartGPU[]` for chart instances (while `ChartGPU` the value\n// remains the creation API exported from `src/index.ts`).\nexport type ChartGPU = ChartGPUInstance;\n\nexport type ChartGPUEventName = 'click' | 'mouseover' | 'mouseout' | 'crosshairMove';\n\nexport type ChartGPUEventPayload = Readonly<{\n readonly seriesIndex: number | null;\n readonly dataIndex: number | null;\n readonly value: readonly [number, number] | null;\n readonly seriesName: string | null;\n readonly event: PointerEvent;\n}>;\n\nexport type ChartGPUCrosshairMovePayload = Readonly<{\n readonly x: number | null;\n readonly source?: unknown;\n}>;\n\nexport type ChartGPUEventCallback = (payload: ChartGPUEventPayload) => void;\n\nexport type ChartGPUCrosshairMoveCallback = (payload: ChartGPUCrosshairMovePayload) => void;\n\ntype AnyChartGPUEventCallback = ChartGPUEventCallback | ChartGPUCrosshairMoveCallback;\n\ntype ListenerRegistry = Readonly<Record<ChartGPUEventName, Set<AnyChartGPUEventCallback>>>;\n\ntype TapCandidate = {\n readonly pointerId: number;\n readonly startClientX: number;\n readonly startClientY: number;\n readonly startTimeMs: number;\n};\n\nconst DEFAULT_TAP_MAX_DISTANCE_CSS_PX = 6;\nconst DEFAULT_TAP_MAX_TIME_MS = 500;\n\ntype Bounds = Readonly<{ xMin: number; xMax: number; yMin: number; yMax: number }>;\n\nconst DATA_ZOOM_SLIDER_HEIGHT_CSS_PX = 32;\nconst DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX = 8;\nconst DATA_ZOOM_SLIDER_RESERVE_CSS_PX = DATA_ZOOM_SLIDER_HEIGHT_CSS_PX + DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX;\n\nconst isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p);\n\nconst getPointXY = (p: DataPoint): { readonly x: number; readonly y: number } => {\n if (isTupleDataPoint(p)) return { x: p[0], y: p[1] };\n return { x: p.x, y: p.y };\n};\n\nconst hasSliderDataZoom = (options: ChartGPUOptions): boolean => options.dataZoom?.some((z) => z?.type === 'slider') ?? false;\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v));\n\nconst resolveOptionsForChart = (options: ChartGPUOptions): ResolvedChartGPUOptions => {\n const base: ResolvedChartGPUOptions = { ...resolveOptions(options), tooltip: options.tooltip };\n if (!hasSliderDataZoom(options)) return base;\n return {\n ...base,\n grid: {\n ...base.grid,\n bottom: base.grid.bottom + DATA_ZOOM_SLIDER_RESERVE_CSS_PX,\n },\n };\n};\n\ntype InteractionScalesCache = {\n rectWidthCss: number;\n rectHeightCss: number;\n plotWidthCss: number;\n plotHeightCss: number;\n xDomainMin: number;\n xDomainMax: number;\n yDomainMin: number;\n yDomainMax: number;\n xScale: LinearScale;\n yScale: LinearScale;\n};\n\nconst computeRawBoundsFromData = (data: ReadonlyArray<DataPoint>): Bounds | null => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]!);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return null;\n }\n\n // Keep bounds usable for downstream scale derivation.\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst extendBoundsWithDataPoints = (bounds: Bounds | null, points: ReadonlyArray<DataPoint>): Bounds | null => {\n if (points.length === 0) return bounds;\n\n let b = bounds;\n if (!b) {\n const seeded = computeRawBoundsFromData(points);\n if (!seeded) return bounds;\n b = seeded;\n }\n\n let xMin = b.xMin;\n let xMax = b.xMax;\n let yMin = b.yMin;\n let yMax = b.yMax;\n\n for (let i = 0; i < points.length; i++) {\n const { x, y } = getPointXY(points[i]!);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n\n // Keep bounds usable for downstream scale derivation.\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst computeGlobalBounds = (\n series: ResolvedChartGPUOptions['series'],\n runtimeRawBoundsByIndex?: ReadonlyArray<Bounds | null> | null\n): Bounds => {\n let xMin = Number.POSITIVE_INFINITY;\n let xMax = Number.NEGATIVE_INFINITY;\n let yMin = Number.POSITIVE_INFINITY;\n let yMax = Number.NEGATIVE_INFINITY;\n\n for (let s = 0; s < series.length; s++) {\n const seriesConfig = series[s]!;\n // Pie series are non-cartesian; they don't participate in x/y bounds.\n if (seriesConfig.type === 'pie') continue;\n\n // Prefer the chart-owned runtime bounds (kept up to date by appendData()).\n const runtimeBoundsCandidate = runtimeRawBoundsByIndex?.[s] ?? null;\n if (runtimeBoundsCandidate) {\n const b = runtimeBoundsCandidate;\n if (\n Number.isFinite(b.xMin) &&\n Number.isFinite(b.xMax) &&\n Number.isFinite(b.yMin) &&\n Number.isFinite(b.yMax)\n ) {\n if (b.xMin < xMin) xMin = b.xMin;\n if (b.xMax > xMax) xMax = b.xMax;\n if (b.yMin < yMin) yMin = b.yMin;\n if (b.yMax > yMax) yMax = b.yMax;\n continue;\n }\n }\n\n // Prefer resolver-provided bounds when available (avoids O(n) scans on initial setOption()).\n // (Resolved series types include `rawBounds` for cartesian series; keep this defensive.)\n const rawBoundsCandidate = (seriesConfig as unknown as { rawBounds?: Bounds | null }).rawBounds ?? null;\n if (rawBoundsCandidate) {\n const b = rawBoundsCandidate;\n if (\n Number.isFinite(b.xMin) &&\n Number.isFinite(b.xMax) &&\n Number.isFinite(b.yMin) &&\n Number.isFinite(b.yMax)\n ) {\n if (b.xMin < xMin) xMin = b.xMin;\n if (b.xMax > xMax) xMax = b.xMax;\n if (b.yMin < yMin) yMin = b.yMin;\n if (b.yMax > yMax) yMax = b.yMax;\n continue;\n }\n }\n\n const data = seriesConfig.data as ReadonlyArray<DataPoint>;\n for (let i = 0; i < data.length; i++) {\n const { x, y } = getPointXY(data[i]!);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n if (x < xMin) xMin = x;\n if (x > xMax) xMax = x;\n if (y < yMin) yMin = y;\n if (y > yMax) yMax = y;\n }\n }\n\n if (!Number.isFinite(xMin) || !Number.isFinite(xMax) || !Number.isFinite(yMin) || !Number.isFinite(yMax)) {\n return { xMin: 0, xMax: 1, yMin: 0, yMax: 1 };\n }\n\n if (xMin === xMax) xMax = xMin + 1;\n if (yMin === yMax) yMax = yMin + 1;\n\n return { xMin, xMax, yMin, yMax };\n};\n\nconst normalizeDomain = (\n minCandidate: number,\n maxCandidate: number\n): { readonly min: number; readonly max: number } => {\n let min = minCandidate;\n let max = maxCandidate;\n\n if (!Number.isFinite(min) || !Number.isFinite(max)) {\n min = 0;\n max = 1;\n }\n\n if (min === max) {\n max = min + 1;\n } else if (min > max) {\n const t = min;\n min = max;\n max = t;\n }\n\n return { min, max };\n};\n\ntype CartesianHitTestMatch = Readonly<{\n kind: 'cartesian';\n match: NearestPointMatch;\n}>;\n\ntype PieHitTestMatch = Readonly<{\n kind: 'pie';\n seriesIndex: number;\n dataIndex: number;\n sliceValue: number;\n}>;\n\ntype HitTestMatch = CartesianHitTestMatch | PieHitTestMatch;\n\nconst parseNumberOrPercent = (value: number | string, basis: number): number | null => {\n if (typeof value === 'number') return Number.isFinite(value) ? value : null;\n if (typeof value !== 'string') return null;\n\n const s = value.trim();\n if (s.length === 0) return null;\n\n if (s.endsWith('%')) {\n const pct = Number.parseFloat(s.slice(0, -1));\n if (!Number.isFinite(pct)) return null;\n return (pct / 100) * basis;\n }\n\n // Be permissive: allow numeric strings like \"120\" even though the public type primarily documents percent strings.\n const n = Number.parseFloat(s);\n return Number.isFinite(n) ? n : null;\n};\n\nconst resolvePieCenterPlotCss = (\n center: PieCenter | undefined,\n plotWidthCss: number,\n plotHeightCss: number\n): { readonly x: number; readonly y: number } => {\n const xRaw = center?.[0] ?? '50%';\n const yRaw = center?.[1] ?? '50%';\n\n const x = parseNumberOrPercent(xRaw, plotWidthCss);\n const y = parseNumberOrPercent(yRaw, plotHeightCss);\n\n return {\n x: Number.isFinite(x) ? x! : plotWidthCss * 0.5,\n y: Number.isFinite(y) ? y! : plotHeightCss * 0.5,\n };\n};\n\nconst isPieRadiusTuple = (radius: PieRadius): radius is readonly [inner: number | string, outer: number | string] =>\n Array.isArray(radius);\n\nconst resolvePieRadiiCss = (\n radius: PieRadius | undefined,\n maxRadiusCss: number\n): { readonly inner: number; readonly outer: number } => {\n // Default similar to common chart libs (mirrors `createPieRenderer.ts` and coordinator helpers).\n if (radius == null) return { inner: 0, outer: maxRadiusCss * 0.7 };\n\n if (isPieRadiusTuple(radius)) {\n const inner = parseNumberOrPercent(radius[0], maxRadiusCss);\n const outer = parseNumberOrPercent(radius[1], maxRadiusCss);\n const innerCss = Math.max(0, Number.isFinite(inner) ? inner! : 0);\n const outerCss = Math.max(innerCss, Number.isFinite(outer) ? outer! : maxRadiusCss * 0.7);\n return { inner: innerCss, outer: Math.min(maxRadiusCss, outerCss) };\n }\n\n const outer = parseNumberOrPercent(radius, maxRadiusCss);\n const outerCss = Math.max(0, Number.isFinite(outer) ? outer! : maxRadiusCss * 0.7);\n return { inner: 0, outer: Math.min(maxRadiusCss, outerCss) };\n};\n\nexport async function createChartGPU(\n container: HTMLElement,\n options: ChartGPUOptions\n): Promise<ChartGPUInstance> {\n // Check WebGPU support before creating canvas or any resources\n const supportCheck = await checkWebGPUSupport();\n if (!supportCheck.supported) {\n const reason = supportCheck.reason || 'Unknown reason';\n throw new Error(\n `ChartGPU: WebGPU is not available.\\n` +\n `Reason: ${reason}\\n` +\n `Browser support: Chrome/Edge 113+, Safari 18+, Firefox not yet supported.\\n` +\n `Resources:\\n` +\n ` - MDN WebGPU API: https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API\\n` +\n ` - Browser compatibility: https://caniuse.com/webgpu\\n` +\n ` - WebGPU specification: https://www.w3.org/TR/webgpu/\\n` +\n ` - Check your system: https://webgpureport.org/`\n );\n }\n\n const canvas = document.createElement('canvas');\n\n // Ensure the canvas participates in layout and can size via the container.\n canvas.style.display = 'block';\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n\n // Append before awaiting so it appears immediately and has measurable size.\n container.appendChild(canvas);\n\n let disposed = false;\n let gpuContext: GPUContext | null = null;\n let coordinator: RenderCoordinator | null = null;\n let coordinatorTargetFormat: GPUTextureFormat | null = null;\n let unsubscribeCoordinatorInteractionXChange: (() => void) | null = null;\n\n let dataZoomSliderHost: HTMLDivElement | null = null;\n let dataZoomSlider: DataZoomSlider | null = null;\n\n let currentOptions: ChartGPUOptions = options;\n let resolvedOptions: ResolvedChartGPUOptions = resolveOptionsForChart(currentOptions);\n\n // Chart-owned runtime series store for hit-testing only (cartesian only).\n // - `runtimeRawDataByIndex[i]` is a mutable array used to reflect streaming appends.\n // - `runtimeRawBoundsByIndex[i]` is incrementally updated to keep scale/bounds derivation cheap.\n let runtimeRawDataByIndex: DataPoint[][] = new Array(resolvedOptions.series.length).fill(null).map(() => []);\n let runtimeRawBoundsByIndex: Array<Bounds | null> = new Array(resolvedOptions.series.length).fill(null);\n let runtimeHitTestSeriesCache: ResolvedChartGPUOptions['series'] | null = null;\n let runtimeHitTestSeriesVersion = 0;\n\n const initRuntimeHitTestStoreFromResolvedOptions = (): void => {\n runtimeRawDataByIndex = new Array(resolvedOptions.series.length).fill(null).map(() => []);\n runtimeRawBoundsByIndex = new Array(resolvedOptions.series.length).fill(null);\n runtimeHitTestSeriesCache = null;\n runtimeHitTestSeriesVersion++;\n\n for (let i = 0; i < resolvedOptions.series.length; i++) {\n const s = resolvedOptions.series[i]!;\n if (s.type === 'pie') continue;\n\n const raw = ((s as unknown as { rawData?: ReadonlyArray<DataPoint> }).rawData ?? s.data) as ReadonlyArray<DataPoint>;\n runtimeRawDataByIndex[i] = raw.length === 0 ? [] : raw.slice();\n runtimeRawBoundsByIndex[i] = ((s as unknown as { rawBounds?: Bounds | null }).rawBounds ?? null) ?? computeRawBoundsFromData(raw);\n }\n };\n\n const getRuntimeHitTestSeries = (): ResolvedChartGPUOptions['series'] => {\n if (runtimeHitTestSeriesCache) return runtimeHitTestSeriesCache;\n // Replace cartesian series `data` with chart-owned runtime data (pie series are unchanged).\n runtimeHitTestSeriesCache = resolvedOptions.series.map((s, i) => {\n if (s.type === 'pie') return s;\n return { ...s, data: runtimeRawDataByIndex[i] ?? (s.data as ReadonlyArray<DataPoint>) };\n }) as ResolvedChartGPUOptions['series'];\n return runtimeHitTestSeriesCache;\n };\n\n initRuntimeHitTestStoreFromResolvedOptions();\n\n // Cache global bounds and interaction scales; avoids O(N) data scans per pointer move.\n let cachedGlobalBounds: Bounds = computeGlobalBounds(resolvedOptions.series, runtimeRawBoundsByIndex);\n let interactionScalesCache: InteractionScalesCache | null = null;\n\n const listeners: ListenerRegistry = {\n click: new Set<ChartGPUEventCallback>(),\n mouseover: new Set<ChartGPUEventCallback>(),\n mouseout: new Set<ChartGPUEventCallback>(),\n crosshairMove: new Set<ChartGPUCrosshairMoveCallback>(),\n };\n\n let tapCandidate: TapCandidate | null = null;\n let suppressNextLostPointerCaptureId: number | null = null;\n\n let hovered: HitTestMatch | null = null;\n\n // Prevent spamming console.warn for repeated misuse.\n const warnedPieAppendSeries = new Set<number>();\n\n let scheduledRaf: number | null = null;\n let lastConfigured: { width: number; height: number; format: GPUTextureFormat } | null = null;\n\n const hasHoverListeners = (): boolean => listeners.mouseover.size > 0 || listeners.mouseout.size > 0;\n const hasClickListeners = (): boolean => listeners.click.size > 0;\n\n const cancelPendingFrame = (): void => {\n if (scheduledRaf === null) return;\n cancelAnimationFrame(scheduledRaf);\n scheduledRaf = null;\n };\n\n const requestRender = (): void => {\n if (disposed) return;\n if (scheduledRaf !== null) return;\n\n scheduledRaf = requestAnimationFrame(() => {\n scheduledRaf = null;\n if (disposed) return;\n\n // Requirement: on RAF tick, call resize() first.\n resizeInternal(false);\n coordinator?.render();\n });\n };\n\n const unbindCoordinatorInteractionXChange = (): void => {\n if (!unsubscribeCoordinatorInteractionXChange) return;\n try {\n unsubscribeCoordinatorInteractionXChange();\n } finally {\n unsubscribeCoordinatorInteractionXChange = null;\n }\n };\n\n const disposeDataZoomSlider = (): void => {\n dataZoomSlider?.dispose();\n dataZoomSlider = null;\n };\n\n const disposeDataZoomSliderHost = (): void => {\n dataZoomSliderHost?.remove();\n dataZoomSliderHost = null;\n };\n\n const disposeDataZoomUi = (): void => {\n disposeDataZoomSlider();\n disposeDataZoomSliderHost();\n };\n\n const ensureDataZoomSliderHost = (): HTMLDivElement => {\n if (dataZoomSliderHost) return dataZoomSliderHost;\n\n // Ensure the host's absolute positioning is anchored to the chart container.\n // If the container is already positioned, avoid overwriting user styles.\n try {\n const pos = window.getComputedStyle(container).position;\n if (pos === 'static') container.style.position = 'relative';\n } catch {\n // best-effort\n }\n\n const host = document.createElement('div');\n host.style.position = 'absolute';\n host.style.left = '0';\n host.style.right = '0';\n host.style.bottom = '0';\n host.style.height = `${DATA_ZOOM_SLIDER_RESERVE_CSS_PX}px`;\n host.style.paddingTop = `${DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX}px`;\n host.style.boxSizing = 'border-box';\n host.style.pointerEvents = 'auto';\n host.style.zIndex = '5';\n container.appendChild(host);\n dataZoomSliderHost = host;\n return host;\n };\n\n const computeZoomInOutAnchorRatio = (range: ZoomRange, center: number): number => {\n const span = range.end - range.start;\n if (!Number.isFinite(span) || span === 0) return 0.5;\n return clamp((center - range.start) / span, 0, 1);\n };\n\n const createCoordinatorZoomStateLike = (): ZoomState => {\n const getRange: ZoomState['getRange'] = () => coordinator?.getZoomRange() ?? { start: 0, end: 100 };\n const setRange: ZoomState['setRange'] = (start, end) => {\n coordinator?.setZoomRange(start, end);\n };\n const zoomIn: ZoomState['zoomIn'] = (center, factor) => {\n if (!Number.isFinite(center) || !Number.isFinite(factor) || factor <= 1) return;\n const r = coordinator?.getZoomRange();\n if (!r) return;\n const c = clamp(center, 0, 100);\n const ratio = computeZoomInOutAnchorRatio(r, c);\n const span = r.end - r.start;\n const nextSpan = span / factor;\n const nextStart = c - ratio * nextSpan;\n coordinator?.setZoomRange(nextStart, nextStart + nextSpan);\n };\n const zoomOut: ZoomState['zoomOut'] = (center, factor) => {\n if (!Number.isFinite(center) || !Number.isFinite(factor) || factor <= 1) return;\n const r = coordinator?.getZoomRange();\n if (!r) return;\n const c = clamp(center, 0, 100);\n const ratio = computeZoomInOutAnchorRatio(r, c);\n const span = r.end - r.start;\n const nextSpan = span * factor;\n const nextStart = c - ratio * nextSpan;\n coordinator?.setZoomRange(nextStart, nextStart + nextSpan);\n };\n const pan: ZoomState['pan'] = (delta) => {\n if (!Number.isFinite(delta)) return;\n const r = coordinator?.getZoomRange();\n if (!r) return;\n coordinator?.setZoomRange(r.start + delta, r.end + delta);\n };\n const onChange: ZoomState['onChange'] = (callback) => coordinator?.onZoomRangeChange(callback) ?? (() => {});\n\n return { getRange, setRange, zoomIn, zoomOut, pan, onChange };\n };\n\n const syncDataZoomUi = (): void => {\n const shouldHaveSlider = hasSliderDataZoom(currentOptions);\n if (!shouldHaveSlider) {\n disposeDataZoomUi();\n return;\n }\n\n // Slider requires a coordinator-backed zoom state.\n if (!coordinator) return;\n if (!coordinator.getZoomRange()) return;\n\n const host = ensureDataZoomSliderHost();\n if (!dataZoomSlider) {\n dataZoomSlider = createDataZoomSlider(host, createCoordinatorZoomStateLike(), {\n height: DATA_ZOOM_SLIDER_HEIGHT_CSS_PX,\n marginTop: 0, // host provides vertical spacing\n });\n }\n dataZoomSlider.update(resolvedOptions.theme);\n };\n\n const bindCoordinatorInteractionXChange = (): void => {\n unbindCoordinatorInteractionXChange();\n if (disposed) return;\n if (!coordinator) return;\n\n unsubscribeCoordinatorInteractionXChange = coordinator.onInteractionXChange((x, source) => {\n emit('crosshairMove', { x, source });\n });\n };\n\n const recreateCoordinator = (): void => {\n if (disposed) return;\n if (!gpuContext || !gpuContext.initialized) return;\n\n const prevZoomRange = coordinator?.getZoomRange() ?? null;\n\n unbindCoordinatorInteractionXChange();\n // Coordinator recreation invalidates zoom subscriptions; recreate the slider if present.\n disposeDataZoomSlider();\n coordinator?.dispose();\n coordinator = createRenderCoordinator(gpuContext, resolvedOptions, { onRequestRender: requestRender });\n coordinatorTargetFormat = gpuContext.preferredFormat;\n bindCoordinatorInteractionXChange();\n\n if (prevZoomRange) coordinator.setZoomRange(prevZoomRange.start, prevZoomRange.end);\n syncDataZoomUi();\n };\n\n const resizeInternal = (shouldRequestRenderAfterChanges: boolean): void => {\n if (disposed) return;\n\n const rect = canvas.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n\n const maxDimension = gpuContext?.device?.limits.maxTextureDimension2D ?? 8192;\n const width = Math.min(maxDimension, Math.max(1, Math.round(rect.width * dpr)));\n const height = Math.min(maxDimension, Math.max(1, Math.round(rect.height * dpr)));\n\n const sizeChanged = canvas.width !== width || canvas.height !== height;\n if (sizeChanged) {\n canvas.width = width;\n canvas.height = height;\n }\n\n const device = gpuContext?.device;\n const canvasContext = gpuContext?.canvasContext;\n const preferredFormat = gpuContext?.preferredFormat;\n\n let didConfigure = false;\n if (device && canvasContext && preferredFormat) {\n const shouldConfigure =\n sizeChanged ||\n !lastConfigured ||\n lastConfigured.width !== canvas.width ||\n lastConfigured.height !== canvas.height ||\n lastConfigured.format !== preferredFormat;\n\n if (shouldConfigure) {\n canvasContext.configure({\n device,\n format: preferredFormat,\n alphaMode: 'opaque',\n });\n lastConfigured = { width: canvas.width, height: canvas.height, format: preferredFormat };\n didConfigure = true;\n\n // Requirement: if the target format changes, recreate coordinator/pipelines.\n if (coordinator && coordinatorTargetFormat !== preferredFormat) {\n recreateCoordinator();\n }\n }\n }\n\n if (shouldRequestRenderAfterChanges && (sizeChanged || didConfigure)) {\n // Requirement: resize() requests a render after size/config changes.\n requestRender();\n }\n };\n\n const resize = (): void => resizeInternal(true);\n\n const getNearestPointFromPointerEvent = (\n e: PointerEvent\n ): { readonly match: HitTestMatch | null; readonly isInGrid: boolean } => {\n const rect = canvas.getBoundingClientRect();\n if (!(rect.width > 0) || !(rect.height > 0)) return { match: null, isInGrid: false };\n\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n\n const plotLeftCss = resolvedOptions.grid.left;\n const plotTopCss = resolvedOptions.grid.top;\n const plotWidthCss = rect.width - resolvedOptions.grid.left - resolvedOptions.grid.right;\n const plotHeightCss = rect.height - resolvedOptions.grid.top - resolvedOptions.grid.bottom;\n if (!(plotWidthCss > 0) || !(plotHeightCss > 0)) return { match: null, isInGrid: false };\n\n const gridX = x - plotLeftCss;\n const gridY = y - plotTopCss;\n\n const isInGrid =\n gridX >= 0 &&\n gridX <= plotWidthCss &&\n gridY >= 0 &&\n gridY <= plotHeightCss;\n\n if (!isInGrid) return { match: null, isInGrid: false };\n\n const xMin = resolvedOptions.xAxis.min ?? cachedGlobalBounds.xMin;\n const xMax = resolvedOptions.xAxis.max ?? cachedGlobalBounds.xMax;\n const yMin = resolvedOptions.yAxis.min ?? cachedGlobalBounds.yMin;\n const yMax = resolvedOptions.yAxis.max ?? cachedGlobalBounds.yMax;\n\n // Make hit-testing zoom-aware (mirror coordinator percent->domain mapping).\n const baseXDomain = normalizeDomain(xMin, xMax);\n const zoomRange = coordinator?.getZoomRange() ?? null;\n const xDomain = (() => {\n if (!zoomRange) return baseXDomain;\n const span = baseXDomain.max - baseXDomain.min;\n if (!Number.isFinite(span) || span === 0) return baseXDomain;\n const start = zoomRange.start;\n const end = zoomRange.end;\n const zMin = baseXDomain.min + (start / 100) * span;\n const zMax = baseXDomain.min + (end / 100) * span;\n return normalizeDomain(zMin, zMax);\n })();\n const yDomain = normalizeDomain(yMin, yMax);\n\n // Cache hit-testing scales for identical (rect, grid, axis domain) inputs.\n const canReuseScales =\n interactionScalesCache !== null &&\n interactionScalesCache.rectWidthCss === rect.width &&\n interactionScalesCache.rectHeightCss === rect.height &&\n interactionScalesCache.plotWidthCss === plotWidthCss &&\n interactionScalesCache.plotHeightCss === plotHeightCss &&\n interactionScalesCache.xDomainMin === xDomain.min &&\n interactionScalesCache.xDomainMax === xDomain.max &&\n interactionScalesCache.yDomainMin === yDomain.min &&\n interactionScalesCache.yDomainMax === yDomain.max;\n\n if (!canReuseScales) {\n // IMPORTANT: grid-local CSS px ranges (0..plotWidth/Height), for interaction hit-testing.\n const xScale = createLinearScale().domain(xDomain.min, xDomain.max).range(0, plotWidthCss);\n const yScale = createLinearScale().domain(yDomain.min, yDomain.max).range(plotHeightCss, 0);\n interactionScalesCache = {\n rectWidthCss: rect.width,\n rectHeightCss: rect.height,\n plotWidthCss,\n plotHeightCss,\n xDomainMin: xDomain.min,\n xDomainMax: xDomain.max,\n yDomainMin: yDomain.min,\n yDomainMax: yDomain.max,\n xScale,\n yScale,\n };\n }\n\n // At this point, the cache must exist (either reused or created above).\n const scales = interactionScalesCache!;\n\n // Story 4.14: pie slice hit-testing (grid-local CSS px).\n const pieMatch = (() => {\n const maxRadiusCss = 0.5 * Math.min(plotWidthCss, plotHeightCss);\n if (!(maxRadiusCss > 0)) return null;\n\n // Prefer later series indices (deterministic and mirrors the coordinator tooltip logic).\n for (let i = resolvedOptions.series.length - 1; i >= 0; i--) {\n const s = resolvedOptions.series[i];\n if (s.type !== 'pie') continue;\n const pieSeries = s as ResolvedPieSeriesConfig;\n const center = resolvePieCenterPlotCss(pieSeries.center, plotWidthCss, plotHeightCss);\n const radii = resolvePieRadiiCss(pieSeries.radius, maxRadiusCss);\n const m = findPieSlice(gridX, gridY, { seriesIndex: i, series: pieSeries }, center, radii);\n if (!m) continue;\n\n const v = m.slice.value;\n return {\n kind: 'pie' as const,\n seriesIndex: m.seriesIndex,\n dataIndex: m.dataIndex,\n sliceValue: typeof v === 'number' && Number.isFinite(v) ? v : 0,\n };\n }\n return null;\n })();\n\n if (pieMatch) return { match: pieMatch, isInGrid: true };\n\n const cartesianMatch = findNearestPoint(\n getRuntimeHitTestSeries(),\n gridX,\n gridY,\n scales.xScale,\n scales.yScale\n );\n\n return {\n match: cartesianMatch ? ({ kind: 'cartesian', match: cartesianMatch } as const) : null,\n isInGrid: true,\n };\n };\n\n const buildPayload = (match: HitTestMatch | null, event: PointerEvent): ChartGPUEventPayload => {\n if (!match) {\n return { seriesIndex: null, dataIndex: null, value: null, seriesName: null, event };\n }\n\n const seriesIndex = match.kind === 'cartesian' ? match.match.seriesIndex : match.seriesIndex;\n const dataIndex = match.kind === 'cartesian' ? match.match.dataIndex : match.dataIndex;\n\n const series = resolvedOptions.series[seriesIndex];\n const seriesNameRaw = series?.name ?? null;\n const seriesName = seriesNameRaw && seriesNameRaw.trim().length > 0 ? seriesNameRaw : null;\n\n if (match.kind === 'pie') {\n // Pie series are non-cartesian; expose slice value in y so consumers can read a numeric.\n return {\n seriesIndex,\n dataIndex,\n value: [0, match.sliceValue],\n seriesName,\n event,\n };\n }\n\n const { x, y } = getPointXY(match.match.point);\n return {\n seriesIndex,\n dataIndex,\n value: [x, y],\n seriesName,\n event,\n };\n };\n\n const emit = (\n eventName: ChartGPUEventName,\n payload: ChartGPUEventPayload | ChartGPUCrosshairMovePayload\n ): void => {\n if (disposed) return;\n for (const cb of listeners[eventName]) (cb as (p: typeof payload) => void)(payload);\n };\n\n const setHovered = (next: HitTestMatch | null, event: PointerEvent): void => {\n const prev = hovered;\n hovered = next;\n\n if (prev === null && next === null) return;\n\n if (prev === null && next !== null) {\n emit('mouseover', buildPayload(next, event));\n return;\n }\n\n if (prev !== null && next === null) {\n emit('mouseout', buildPayload(prev, event));\n return;\n }\n\n if (prev === null || next === null) return;\n\n const prevSeriesIndex = prev.kind === 'cartesian' ? prev.match.seriesIndex : prev.seriesIndex;\n const prevDataIndex = prev.kind === 'cartesian' ? prev.match.dataIndex : prev.dataIndex;\n const nextSeriesIndex = next.kind === 'cartesian' ? next.match.seriesIndex : next.seriesIndex;\n const nextDataIndex = next.kind === 'cartesian' ? next.match.dataIndex : next.dataIndex;\n\n const samePoint = prevSeriesIndex === nextSeriesIndex && prevDataIndex === nextDataIndex;\n if (samePoint) return;\n\n emit('mouseout', buildPayload(prev, event));\n emit('mouseover', buildPayload(next, event));\n };\n\n const clearTapCandidateIfMatches = (e: PointerEvent): void => {\n if (!tapCandidate) return;\n if (!e.isPrimary) return;\n if (e.pointerId !== tapCandidate.pointerId) return;\n tapCandidate = null;\n };\n\n const onPointerMove = (e: PointerEvent): void => {\n if (disposed) return;\n if (!hasHoverListeners()) return;\n const { match, isInGrid } = getNearestPointFromPointerEvent(e);\n if (!isInGrid) {\n setHovered(null, e);\n return;\n }\n setHovered(match, e);\n };\n\n const onPointerLeave = (e: PointerEvent): void => {\n if (disposed) return;\n if (!hasHoverListeners() && !tapCandidate) return;\n clearTapCandidateIfMatches(e);\n setHovered(null, e);\n };\n\n const onPointerCancel = (e: PointerEvent): void => {\n if (disposed) return;\n if (!hasHoverListeners() && !tapCandidate) return;\n clearTapCandidateIfMatches(e);\n setHovered(null, e);\n };\n\n const onLostPointerCapture = (e: PointerEvent): void => {\n if (disposed) return;\n if (!hasHoverListeners() && !tapCandidate && suppressNextLostPointerCaptureId !== e.pointerId) return;\n if (suppressNextLostPointerCaptureId === e.pointerId) {\n suppressNextLostPointerCaptureId = null;\n return;\n }\n clearTapCandidateIfMatches(e);\n setHovered(null, e);\n };\n\n const onPointerDown = (e: PointerEvent): void => {\n if (disposed) return;\n if (!hasClickListeners()) return;\n if (!e.isPrimary) return;\n\n // For mouse, only allow left button.\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n\n tapCandidate = {\n pointerId: e.pointerId,\n startClientX: e.clientX,\n startClientY: e.clientY,\n startTimeMs: e.timeStamp,\n };\n\n // Optional pointer capture improves reliability for touch/pen.\n try {\n canvas.setPointerCapture(e.pointerId);\n } catch {\n // best-effort\n }\n };\n\n const onPointerUp = (e: PointerEvent): void => {\n if (disposed) return;\n if (!hasClickListeners()) return;\n if (!e.isPrimary) return;\n if (!tapCandidate || e.pointerId !== tapCandidate.pointerId) return;\n\n const dt = e.timeStamp - tapCandidate.startTimeMs;\n const dx = e.clientX - tapCandidate.startClientX;\n const dy = e.clientY - tapCandidate.startClientY;\n const distSq = dx * dx + dy * dy;\n\n tapCandidate = null;\n\n // Release capture if we have it; suppress the resulting lostpointercapture.\n try {\n if (canvas.hasPointerCapture(e.pointerId)) {\n suppressNextLostPointerCaptureId = e.pointerId;\n canvas.releasePointerCapture(e.pointerId);\n }\n } catch {\n // best-effort\n }\n\n const maxDist = DEFAULT_TAP_MAX_DISTANCE_CSS_PX;\n const isTap = dt <= DEFAULT_TAP_MAX_TIME_MS && distSq <= maxDist * maxDist;\n if (!isTap) return;\n\n const { match } = getNearestPointFromPointerEvent(e);\n emit('click', buildPayload(match, e));\n };\n\n canvas.addEventListener('pointermove', onPointerMove, { passive: true });\n canvas.addEventListener('pointerleave', onPointerLeave, { passive: true });\n canvas.addEventListener('pointercancel', onPointerCancel, { passive: true });\n canvas.addEventListener('lostpointercapture', onLostPointerCapture, { passive: true });\n canvas.addEventListener('pointerdown', onPointerDown, { passive: true });\n canvas.addEventListener('pointerup', onPointerUp, { passive: true });\n\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n\n try {\n // Requirement: dispose order: cancel RAF, coordinator.dispose(), gpuContext.destroy(), remove canvas.\n cancelPendingFrame();\n disposeDataZoomUi();\n unbindCoordinatorInteractionXChange();\n coordinator?.dispose();\n coordinator = null;\n coordinatorTargetFormat = null;\n gpuContext?.destroy();\n } finally {\n tapCandidate = null;\n suppressNextLostPointerCaptureId = null;\n hovered = null;\n interactionScalesCache = null;\n\n canvas.removeEventListener('pointermove', onPointerMove);\n canvas.removeEventListener('pointerleave', onPointerLeave);\n canvas.removeEventListener('pointercancel', onPointerCancel);\n canvas.removeEventListener('lostpointercapture', onLostPointerCapture);\n canvas.removeEventListener('pointerdown', onPointerDown);\n canvas.removeEventListener('pointerup', onPointerUp);\n\n listeners.click.clear();\n listeners.mouseover.clear();\n listeners.mouseout.clear();\n listeners.crosshairMove.clear();\n\n gpuContext = null;\n canvas.remove();\n }\n };\n\n const instance: ChartGPUInstance = {\n get options() {\n return currentOptions;\n },\n get disposed() {\n return disposed;\n },\n setOption(nextOptions) {\n if (disposed) return;\n currentOptions = nextOptions;\n resolvedOptions = resolveOptionsForChart(nextOptions);\n coordinator?.setOptions(resolvedOptions);\n initRuntimeHitTestStoreFromResolvedOptions();\n cachedGlobalBounds = computeGlobalBounds(resolvedOptions.series, runtimeRawBoundsByIndex);\n interactionScalesCache = null;\n syncDataZoomUi();\n\n // Requirement: setOption triggers a render (and thus series parsing/extent/scales update inside render).\n requestRender();\n },\n appendData(seriesIndex, newPoints) {\n if (disposed) return;\n if (!Number.isFinite(seriesIndex)) return;\n if (seriesIndex < 0 || seriesIndex >= resolvedOptions.series.length) return;\n if (!newPoints || newPoints.length === 0) return;\n\n const s = resolvedOptions.series[seriesIndex]!;\n if (s.type === 'pie') {\n // Pie series are non-cartesian and currently not supported by streaming append.\n if (!warnedPieAppendSeries.has(seriesIndex)) {\n warnedPieAppendSeries.add(seriesIndex);\n console.warn(\n `ChartGPU.appendData(${seriesIndex}, ...): pie series are not supported by streaming append. Use setOption(...) to replace pie data.`\n );\n }\n return;\n }\n\n // Forward to coordinator (GPU buffers + render-state updates), then keep ChartGPU's\n // hit-testing runtime store in sync.\n coordinator?.appendData(seriesIndex, newPoints);\n\n const owned = runtimeRawDataByIndex[seriesIndex] ?? [];\n owned.push(...newPoints);\n runtimeRawDataByIndex[seriesIndex] = owned;\n\n runtimeRawBoundsByIndex[seriesIndex] = extendBoundsWithDataPoints(runtimeRawBoundsByIndex[seriesIndex], newPoints);\n cachedGlobalBounds = computeGlobalBounds(resolvedOptions.series, runtimeRawBoundsByIndex);\n\n runtimeHitTestSeriesCache = null;\n runtimeHitTestSeriesVersion++;\n interactionScalesCache = null;\n\n // Ensure a render is scheduled (coalesced) like setOption does.\n requestRender();\n },\n resize,\n dispose,\n on(eventName, callback) {\n if (disposed) return;\n listeners[eventName].add(callback as AnyChartGPUEventCallback);\n },\n off(eventName, callback) {\n listeners[eventName].delete(callback as AnyChartGPUEventCallback);\n },\n getInteractionX() {\n if (disposed) return null;\n return coordinator?.getInteractionX() ?? null;\n },\n setInteractionX(x, source) {\n if (disposed) return;\n coordinator?.setInteractionX(x, source);\n },\n setCrosshairX(x, source) {\n if (disposed) return;\n coordinator?.setInteractionX(x, source);\n },\n onInteractionXChange(callback) {\n if (disposed) return () => {};\n return coordinator?.onInteractionXChange(callback) ?? (() => {});\n },\n getZoomRange() {\n if (disposed) return null;\n return coordinator?.getZoomRange() ?? null;\n },\n setZoomRange(start, end) {\n if (disposed) return;\n coordinator?.setZoomRange(start, end);\n },\n };\n\n try {\n // Establish initial canvas backing size before WebGPU initialization.\n resizeInternal(false);\n\n // Try to create GPU context; wrap errors with detailed WebGPU unavailability message\n try {\n gpuContext = await GPUContext.create(canvas);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(\n `ChartGPU: WebGPU is not available.\\n` +\n `Reason: ${errorMessage}\\n` +\n `Browser support: Chrome/Edge 113+, Safari 18+, Firefox not yet supported.\\n` +\n `Resources:\\n` +\n ` - MDN WebGPU API: https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API\\n` +\n ` - Browser compatibility: https://caniuse.com/webgpu\\n` +\n ` - WebGPU specification: https://www.w3.org/TR/webgpu/\\n` +\n ` - Check your system: https://webgpureport.org/`\n );\n }\n\n gpuContext.device?.lost.then((info) => {\n if (disposed) return;\n if (info.reason !== 'destroyed') {\n console.warn('WebGPU device lost:', info);\n }\n // Requirement: device loss routes through the same dispose path.\n dispose();\n });\n\n // Ensure canvas configuration matches the final measured size/format.\n resizeInternal(false);\n\n // Requirement: after GPUContext is initialized, create RenderCoordinator with resolved options.\n recreateCoordinator();\n\n // Mount data-zoom UI (if configured).\n syncDataZoomUi();\n\n // Kick an initial render.\n requestRender();\n return instance;\n } catch (error) {\n instance.dispose();\n throw error;\n }\n}\n\nexport const ChartGPU = {\n create: createChartGPU,\n};\n\n","import type { ChartGPU, ChartGPUCrosshairMovePayload } from '../ChartGPU';\n\nexport type DisconnectCharts = () => void;\n\n/**\n * Connects multiple charts so pointer movement in one chart drives crosshair/tooltip x\n * in the other charts (domain x sync). Returns a `disconnect()` function.\n *\n * Notes:\n * - Syncs interaction only (crosshair + tooltip x), not zoom/options.\n * - Uses a per-connection loop guard to prevent feedback.\n */\nexport function connectCharts(charts: ChartGPU[]): DisconnectCharts {\n const connectionToken = Symbol('ChartGPU.connectCharts');\n\n let disconnected = false;\n const unsubscribeFns: Array<() => void> = [];\n\n const broadcast = (sourceChart: ChartGPU, x: number | null): void => {\n for (const chart of charts) {\n if (chart === sourceChart) continue;\n if (chart.disposed) continue;\n chart.setCrosshairX(x, connectionToken);\n }\n };\n\n for (const chart of charts) {\n if (chart.disposed) continue;\n\n const onCrosshairMove = (payload: ChartGPUCrosshairMovePayload): void => {\n if (disconnected) return;\n if (payload.source === connectionToken) return;\n if (chart.disposed) return;\n broadcast(chart, payload.x);\n };\n\n chart.on('crosshairMove', onCrosshairMove);\n const unsub = (): void => chart.off('crosshairMove', onCrosshairMove);\n unsubscribeFns.push(unsub);\n }\n\n return () => {\n if (disconnected) return;\n disconnected = true;\n\n for (const unsub of unsubscribeFns) unsub();\n unsubscribeFns.length = 0;\n\n // Clear any “stuck” remote interactions.\n for (const chart of charts) {\n if (chart.disposed) continue;\n chart.setCrosshairX(null, connectionToken);\n }\n };\n}\n\n","/**\n * RenderScheduler - 60fps render loop management\n * \n * Manages a requestAnimationFrame-based render loop that runs at 60fps,\n * providing delta time tracking and frame scheduling control.\n * \n * This module provides both functional and class-based APIs for maximum flexibility.\n * The functional API is preferred for better type safety and immutability.\n */\n\n/**\n * Callback function type for render frames.\n * Receives delta time in milliseconds since the last frame.\n */\nexport type RenderCallback = (deltaTime: number) => void;\n\n/**\n * Represents the state of a render scheduler.\n * All properties are readonly to ensure immutability.\n */\nexport interface RenderSchedulerState {\n readonly id: symbol;\n readonly running: boolean;\n}\n\n/**\n * Internal mutable state for the render scheduler.\n * Stored separately from the public state interface.\n */\ninterface RenderSchedulerInternalState {\n rafId: number | null;\n callback: RenderCallback | null;\n lastFrameTime: number;\n dirty: boolean;\n}\n\n/**\n * Map to store internal mutable state for each scheduler state instance.\n * Keyed by the state's unique ID symbol.\n */\nconst internalStateMap = new Map<symbol, RenderSchedulerInternalState>();\n\n/**\n * Creates a new RenderScheduler state with initial values.\n * \n * @returns A new RenderSchedulerState instance\n */\nexport function createRenderScheduler(): RenderSchedulerState {\n const id = Symbol('RenderScheduler');\n const state: RenderSchedulerState = {\n id,\n running: false,\n };\n\n // Initialize internal mutable state\n internalStateMap.set(id, {\n rafId: null,\n callback: null,\n lastFrameTime: 0,\n dirty: false,\n });\n\n return state;\n}\n\n/**\n * Starts the render loop.\n * \n * Begins a requestAnimationFrame loop that calls the provided callback\n * every frame with the delta time in milliseconds since the last frame.\n * Returns a new state object with running set to true.\n * \n * @param state - The scheduler state to start\n * @param callback - Function to call each frame with delta time\n * @returns A new RenderSchedulerState with running set to true\n * @throws {Error} If callback is not provided\n * @throws {Error} If scheduler is already running\n * @throws {Error} If state is invalid\n */\nexport function startRenderScheduler(\n state: RenderSchedulerState,\n callback: RenderCallback\n): RenderSchedulerState {\n if (!callback) {\n throw new Error('Render callback is required');\n }\n\n const internalState = internalStateMap.get(state.id);\n if (!internalState) {\n throw new Error('Invalid scheduler state. Use createRenderScheduler() to create a new state.');\n }\n\n if (state.running) {\n throw new Error('RenderScheduler is already running. Call stopRenderScheduler() before starting again.');\n }\n\n // Update internal state\n internalState.callback = callback;\n internalState.lastFrameTime = performance.now();\n internalState.dirty = true;\n\n const schedulerId = state.id;\n const frameHandler = (currentTime: number) => {\n // Look up internal state - may be null if scheduler was destroyed\n const currentInternalState = internalStateMap.get(schedulerId);\n if (!currentInternalState || !currentInternalState.callback) {\n // Scheduler was stopped or destroyed, exit gracefully\n return;\n }\n\n const deltaTime = currentTime - currentInternalState.lastFrameTime;\n currentInternalState.lastFrameTime = currentTime;\n\n // Future optimization: skip render if not dirty\n // Currently always renders, but dirty flag is tracked for future use\n if (currentInternalState.dirty) {\n // Reset dirty flag after checking (for future frame-skipping optimization)\n currentInternalState.dirty = false;\n }\n\n // Call the render callback with delta time\n currentInternalState.callback(deltaTime);\n\n // Continue the loop if still running\n // Re-check internal state in case it was destroyed during callback execution\n const nextInternalState = internalStateMap.get(schedulerId);\n if (nextInternalState && nextInternalState.callback) {\n nextInternalState.rafId = requestAnimationFrame(frameHandler);\n }\n };\n\n // Start the first frame\n internalState.rafId = requestAnimationFrame(frameHandler);\n\n // Return new state with running set to true\n return {\n id: state.id,\n running: true,\n };\n}\n\n/**\n * Stops the render loop.\n * \n * Cancels any pending requestAnimationFrame calls and stops the loop.\n * Returns a new state object with running set to false.\n * The scheduler can be restarted by calling startRenderScheduler() again.\n * \n * @param state - The scheduler state to stop\n * @returns A new RenderSchedulerState with running set to false\n * @throws {Error} If state is invalid\n */\nexport function stopRenderScheduler(state: RenderSchedulerState): RenderSchedulerState {\n const internalState = internalStateMap.get(state.id);\n if (!internalState) {\n throw new Error('Invalid scheduler state. Use createRenderScheduler() to create a new state.');\n }\n\n internalState.callback = null;\n\n if (internalState.rafId !== null) {\n cancelAnimationFrame(internalState.rafId);\n internalState.rafId = null;\n }\n\n // Return new state with running set to false\n return {\n id: state.id,\n running: false,\n };\n}\n\n/**\n * Marks the current frame as dirty, indicating it needs to be rendered.\n * \n * This function is prepared for future optimization where frames can be\n * skipped if nothing has changed. Currently, all frames render regardless\n * of the dirty flag.\n * \n * @param state - The scheduler state\n * @throws {Error} If state is invalid\n */\nexport function requestRender(state: RenderSchedulerState): void {\n const internalState = internalStateMap.get(state.id);\n if (!internalState) {\n throw new Error('Invalid scheduler state. Use createRenderScheduler() to create a new state.');\n }\n\n // Mark as dirty even if not running (for future use when scheduler starts)\n internalState.dirty = true;\n}\n\n/**\n * Destroys the render scheduler and cleans up resources.\n * Stops the loop if running and removes internal state from the map.\n * Returns a new state object with reset values.\n * After calling this, the scheduler must be recreated before use.\n * \n * **Important:** Always call this function when done with a scheduler to prevent memory leaks.\n * The internal state map will retain entries until explicitly destroyed.\n * \n * @param state - The scheduler state to destroy\n * @returns A new RenderSchedulerState with reset values\n */\nexport function destroyRenderScheduler(state: RenderSchedulerState): RenderSchedulerState {\n const internalState = internalStateMap.get(state.id);\n \n if (internalState) {\n // Stop the loop if running\n if (internalState.rafId !== null) {\n cancelAnimationFrame(internalState.rafId);\n internalState.rafId = null;\n }\n \n // Clear callback to prevent further execution\n internalState.callback = null;\n \n // Clean up internal state from map to prevent memory leak\n internalStateMap.delete(state.id);\n }\n\n // Return new state with reset values\n return createRenderScheduler();\n}\n\n/**\n * Convenience function that creates a scheduler and starts it in one step.\n * \n * @param callback - Function to call each frame with delta time\n * @returns A RenderSchedulerState with the loop running\n * @throws {Error} If callback is not provided\n * \n * @example\n * ```typescript\n * const scheduler = createRenderSchedulerAsync((deltaTime) => {\n * renderFrame(deltaTime);\n * });\n * ```\n */\nexport function createRenderSchedulerAsync(callback: RenderCallback): RenderSchedulerState {\n const state = createRenderScheduler();\n return startRenderScheduler(state, callback);\n}\n\n/**\n * RenderScheduler class wrapper for backward compatibility.\n * \n * This class provides a class-based API that internally uses the functional implementation.\n * Use the functional API directly for better type safety and immutability.\n */\nexport class RenderScheduler {\n private _state: RenderSchedulerState;\n\n /**\n * Checks if the scheduler is currently running.\n */\n get running(): boolean {\n return this._state.running;\n }\n\n /**\n * Creates a new RenderScheduler instance.\n */\n constructor() {\n this._state = createRenderScheduler();\n }\n\n /**\n * Starts the render loop.\n * \n * @param callback - Function to call each frame with delta time\n * @throws {Error} If callback is not provided or scheduler already running\n */\n start(callback: RenderCallback): void {\n this._state = startRenderScheduler(this._state, callback);\n }\n\n /**\n * Stops the render loop.\n */\n stop(): void {\n this._state = stopRenderScheduler(this._state);\n }\n\n /**\n * Marks the current frame as dirty, indicating it needs to be rendered.\n */\n requestRender(): void {\n requestRender(this._state);\n }\n\n /**\n * Destroys the render scheduler and cleans up resources.\n * After calling destroy(), the scheduler must be recreated before use.\n */\n destroy(): void {\n this._state = destroyRenderScheduler(this._state);\n }\n}\n","/**\n * ChartGPU - A GPU-accelerated charting library built with WebGPU\n */\n\nexport const version = '1.0.0';\n\n// Chart API (Phase 1)\nexport { ChartGPU } from './ChartGPU';\nexport { createChartGPU as createChart } from './ChartGPU';\nexport type { ChartGPUInstance } from './ChartGPU';\nexport type {\n ChartGPUEventName,\n ChartGPUEventPayload,\n ChartGPUCrosshairMovePayload,\n ChartGPUEventCallback,\n ChartGPUCrosshairMoveCallback,\n} from './ChartGPU';\nexport type {\n AreaStyleConfig,\n AnimationConfig,\n BarItemStyleConfig,\n AxisConfig,\n AxisType,\n ChartGPUOptions,\n DataZoomConfig,\n DataPoint,\n GridConfig,\n LineStyleConfig,\n AreaSeriesConfig,\n LineSeriesConfig,\n BarSeriesConfig,\n PieCenter,\n PieDataItem,\n PieItemStyleConfig,\n PieRadius,\n PieSeriesConfig,\n ScatterSeriesConfig,\n ScatterSymbol,\n ScatterPointTuple,\n SeriesConfig,\n SeriesSampling,\n SeriesType,\n TooltipParams,\n} from './config/types';\n\n// Options defaults + resolution\nexport { defaultOptions } from './config/defaults';\nexport { OptionResolver, resolveOptions } from './config/OptionResolver';\nexport type {\n ResolvedChartGPUOptions,\n ResolvedAreaSeriesConfig,\n ResolvedAreaStyleConfig,\n ResolvedGridConfig,\n ResolvedLineSeriesConfig,\n ResolvedLineStyleConfig,\n ResolvedSeriesConfig,\n} from './config/OptionResolver';\n\n// Themes\nexport type { ThemeConfig } from './themes/types';\nexport { darkTheme, lightTheme, getTheme } from './themes';\nexport type { ThemeName } from './themes';\n\n// Scales - Pure utilities\nexport { createLinearScale, createCategoryScale } from './utils/scales';\nexport type { LinearScale, CategoryScale } from './utils/scales';\n\n// Chart sync (interaction)\nexport { connectCharts } from './interaction/createChartSync';\n\n// Core exports - Functional API (preferred)\nexport type { GPUContextState } from './core/GPUContext';\nexport {\n createGPUContext,\n createGPUContextAsync,\n initializeGPUContext,\n getCanvasTexture,\n clearScreen,\n destroyGPUContext,\n} from './core/GPUContext';\n\n// Class-based API (for backward compatibility)\nexport { GPUContext } from './core/GPUContext';\n\n// Render scheduler - Functional API (preferred)\nexport type { RenderSchedulerState, RenderCallback } from './core/RenderScheduler';\nexport {\n createRenderScheduler,\n createRenderSchedulerAsync,\n startRenderScheduler,\n stopRenderScheduler,\n requestRender,\n destroyRenderScheduler,\n} from './core/RenderScheduler';\n\n// Class-based API (for backward compatibility)\nexport { RenderScheduler } from './core/RenderScheduler';\n"],"names":["createGPUContext","canvas","initializeGPUContext","context","_a","device","adapter","event","canvasContext","preferredFormat","webgpuContext","error","dpr","displayWidth","displayHeight","adapterWithFormat","destroyError","getCanvasTexture","clearScreen","r","g","b","a","texture","encoder","destroyGPUContext","createGPUContextAsync","GPUContext","MIN_BUFFER_BYTES","roundUpToMultipleOf4","bytes","nextPow2","n","computeGrownCapacityBytes","currentCapacityBytes","requiredBytes","required","grown","isTupleDataPoint","point","packDataPoints","data","buffer","f32","i","x","y","fnv1aUpdate","hash","words","h","hashFloat32ArrayBits","u32","createDataStore","series","disposed","assertNotDisposed","getSeriesEntry","index","entry","packed","pointCount","hash32","targetBytes","existing","capacityBytes","maxBufferSize","grownCapacityBytes","newPoints","prevPointCount","nextPointCount","appendPacked","appendBytes","nextData","fullPacked","byteOffset","appendWords","nextHash32","lttbIndicesForInterleavedXY","targetPoints","lastIndex","indices","bucketSize","out","lastX","lastY","bucket","rangeStart","rangeEndExclusive","nextRangeStart","nextRangeEndExclusive","avgX","avgY","sumX","sumY","avgCount","ax","ay","maxArea","maxIndex","bx","by","area2","absArea2","lttbIndicesForDataPoints","pLast","p","pa","pb","lttbSample","threshold","idx","getXY","getSize","clampTargetPoints","sampleByBuckets","mode","chosen","sumSize","count","sizeCount","size","bestY","sampleSeriesDataPoints","sampling","samplingThreshold","gridWgsl","DEFAULT_VERTEX_ENTRY","DEFAULT_FRAGMENT_ENTRY","isPowerOfTwo","alignTo","value","alignment","getStageModule","stage","createShaderModule","code","label","createRenderPipeline","config","layout","vertexStage","vertexEntryPoint","fragment","fragmentStage","fragmentEntryPoint","targets","formats","format","primitive","multisample","createUniformBuffer","options","alignedSize","maxSize","writeUniformBuffer","src","clamp01","v","clamp255","parseHexNibble","hex","parseHexByte","parseHexColorToRgba01","color","c","parseRgbNumberOrPercent","token","parseAlphaNumberOrPercent","parseRgbFuncToRgba01","m","fn","parts","parseCssColorToRgba01","rgb","parseCssColorToGPUColor","fallback","rgba","DEFAULT_TARGET_FORMAT","DEFAULT_TICK_COUNT","DEFAULT_TICK_LENGTH_CSS_PX","DEFAULT_AXIS_RGBA","createIdentityMat4Buffer","isFiniteGridArea","gridArea","generateAxisVertices","axisConfig","scale","orientation","left","right","top","bottom","canvasWidth","canvasHeight","plotLeft","plotRight","plotTop","plotBottom","plotLeftClip","plotRightClip","plotTopClip","plotBottomClip","tickLengthCssPx","tickCount","tickLengthDevicePx","tickDeltaClipX","tickDeltaClipY","domainMin","domainMax","totalSegments","vertices","y0","y1","t","x0","x1","createAxisRenderer","targetFormat","bindGroupLayout","vsUniformBuffer","fsUniformBufferLine","fsUniformBufferTick","bindGroupLine","bindGroupTick","pipeline","vertexBuffer","vertexCount","axisLineColor","axisTickColor","requiredSize","bufferSize","axisLineColorString","axisTickColorString","axisLineRgba","axisTickRgba","lineColorBuffer","tickColorBuffer","passEncoder","DEFAULT_HORIZONTAL_LINES","DEFAULT_VERTICAL_LINES","DEFAULT_GRID_COLOR","DEFAULT_GRID_RGBA","generateGridVertices","horizontal","vertical","plotWidth","plotHeight","totalLines","yDevice","xClipLeft","xClipRight","yClip","xClip","yClipTop","yClipBottom","createGridRenderer","fsUniformBuffer","bindGroup","lineCountOrOptions","isOptionsObject","lineCount","colorString","transformBuffer","colorBuffer","areaWgsl","parseSeriesColorToRgba01","getPointXY","computeDataBounds","xMin","xMax","yMin","yMax","computeClipAffineFromScale","v0","v1","p0","p1","writeTransformMat4F32","createAreaVertices","createAreaRenderer","vsUniformScratchBuffer","vsUniformScratchF32","fsUniformScratchF32","writeVsUniforms","baseline","seriesConfig","xScale","yScale","baselineValue","opacity","lineWgsl","createLineRenderer","currentVertexBuffer","currentVertexCount","dataBuffer","barWgsl","DEFAULT_BAR_GAP","DEFAULT_BAR_CATEGORY_GAP","INSTANCE_STRIDE_BYTES","INSTANCE_STRIDE_FLOATS","parsePercent","normalizeStackId","stack","trimmed","computePlotSizeCssPx","canvasCssWidth","canvasCssHeight","plotWidthCss","plotHeightCss","computePlotClipRect","computeCategoryWidthClip","categoryStep","plotClipRect","fallbackCategoryCount","w","clipWidth","createBarRenderer","instanceBuffer","instanceCount","cpuInstanceStagingBuffer","cpuInstanceStagingF32","categoryXScratch","ensureCpuInstanceCapacityFloats","requiredFloats","nextFloats","computeBarCategoryStep","seriesConfigs","s","minStep","d","computeSharedBarLayout","barWidth","barGap","barCategoryGap","computeBaselineForBarsFromData","computeBaselineForBarsFromAxis","yDomainA","yDomainB","dataStore","plotSize","plotClipWidth","clipPerCssX","stackIdToClusterIndex","clusterIndexBySeries","clusterCount","stackId","categoryWidthClip","categoryInnerWidthClip","barWidthClip","rawBarWidth","denom","gapClip","clusterWidthClip","baselineDomain","baselineClip","fallbackBaselineDomain","maxBars","outFloats","stackSumsByStackId","seriesIndex","clusterIndex","xClipCenter","baseClip","height","sumsForX","xKey","sums","baseDomain","topDomain","bClip","tClip","grownBytes","scatterWgsl","DEFAULT_SCATTER_RADIUS_CSS_PX","clampInt","lo","hi","getPointSizeCssPx","toScatterTuple","computePlotScissorDevicePx","plotLeftDevice","plotRightDevice","plotTopDevice","plotBottomDevice","scissorX","scissorY","scissorR","scissorB","scissorW","scissorH","createScatterRenderer","lastCanvasWidth","lastCanvasHeight","lastViewportPx","lastScissor","viewportW","viewportH","hasValidDpr","seriesSymbolSize","getSeriesSizeCssPx","sizeCss","radiusCss","radiusDevicePx","pieWgsl","TAU","wrapToTau","thetaRad","parseColor","cssColor","fallbackCssColor","parsed","fb","parseNumberOrPercent","basis","pct","resolveCenterPlotCss","center","xRaw","yRaw","isRadiusTuple","radius","resolveRadiiCss","maxRadiusCss","inner","outer","innerCss","outerCss","IDENTITY_MAT4_F32","createPieRenderer","viewportWDevicePx","viewportHDevicePx","dprRaw","centerPlotCss","centerCanvasCssX","centerCanvasCssY","centerClipX","centerClipY","radiiCss","innerPx","outerPx","total","validCount","startDeg","current","accumulated","emitted","item","isLast","span","startRad","endRad","crosshairWgsl","align4","SMALL_FULL_WRITE_MAX_BYTES","MAX_DIFF_RANGES_BEFORE_FULL_WRITE","MAX_CHANGED_WORDS_BEFORE_FULL_WRITE","toU32View","createStreamBuffer","clamped","limit","capacityWords","createSlot","slots","currentIndex","writeFull","slotIndex","newWords","usedWords","slot","mirror","usedBytes","writeRangesByDiff","ranges","rangeCount","changedWords","start","end","byteSize","nextVertexCount","nextIndex","DEFAULT_CROSSHAIR_RGBA","MAX_THICKNESS_DEVICE_PX","DASH_ON_DEVICE_PX","DASH_OFF_DEVICE_PX","MAX_VERTICES","computeThicknessOffsetsDevicePx","lineWidthCssPx","widthDevicePx","thickness","mid","devicePxToClipX","xDevicePx","canvasWidthDevicePx","devicePxToClipY","yDevicePx","canvasHeightDevicePx","appendSegmentVerticesClip","seg","generateDashedSegmentsAxisAligned","a0","a1","on","period","approxSegments","segments","s0","s1","generateCrosshairVertices","xCssPx","yCssPx","xDevice","thicknessOffsets","floats","dashSegmentsY","dashSegmentsX","projectedVertexCount","useDashed","addVerticalSolid","addHorizontalSolid","xd","ya","yb","yd","xa","xb","createCrosshairRenderer","visible","stream","renderOptions","scissor","highlightWgsl","DEFAULT_RGBA","isFiniteScissor","brighten","factor","f","luminance","createHighlightRenderer","uniformBuffer","hasPrepared","sizeCssPx","baseRadiusDevicePx","seriesRgba","ringRgba","outlineRgba","buf","DEFAULT_TAP_MAX_DISTANCE_CSS_PX","DEFAULT_TAP_MAX_TIME_MS","createEventManager","initialGridArea","listeners","tapCandidate","suppressNextLostPointerCaptureId","toPayload","e","rect","plotLeftCss","plotTopCss","gridX","gridY","isInGrid","emit","eventName","payload","cb","clearTapCandidateIfMatches","onPointerMove","onPointerLeave","onPointerCancel","onLostPointerCapture","onPointerDown","onPointerUp","dt","dx","dy","distSq","maxDist","callback","nextGridArea","clamp","normalizeWheelDelta","basisCssPx","raw","wheelDeltaToZoomFactor","deltaCssPx","abs","capped","isMiddleButtonDrag","isShiftLeftDrag","createInsideZoom","eventManager","zoomState","enabled","lastPointer","isPanning","lastPanGridX","clearPan","onMouseMove","dxCss","deltaPct","onMouseLeave","_payload","onWheel","deltaCss","centerPct","enable","disable","DEFAULT_MIN_SPAN","DEFAULT_MAX_SPAN","normalizeZero","copyRange","createZoomState","initialStart","initialEnd","lastEmitted","minSpan","maxSpan","normalizedMinSpan","normalizedMaxSpan","next","snapshot","applyNextRange","nextStart","nextEnd","targetSpan","anchorCenter","anchorRatio","shift","nextSpan","delta","DEFAULT_MAX_DISTANCE_PX","scatterMaxRadiusCache","isPointInBar","barBounds","safeCallSymbolSize","getScatterRadiusCssPx","seriesCfg","perPoint","getMaxScatterRadiusCssPx","cached","maxRadius","seriesFallback","maxPerPoint","anyPointWithoutSize","pSize","computeBarClusterSlots","stackIdBySeries","xs","computeCategoryWidthPx","sx","px","minDx","computeBarLayoutPx","clusterSlots","categoryWidthPx","categoryInnerWidthPx","barWidthPx","gapPx","clusterWidthPx","inferPlotHeightPxForBarHitTesting","maxY","py","computeBaselineDomainAndPx","plotHeightPx","baselinePx","bucketStackedXKey","xCenterPx","xDomain","lowerBoundTuple","xTarget","lowerBoundObject","findNearestPoint","maxDistance","md","maxDistSq","bestSeriesIndex","bestDataIndex","bestPoint","bestDistSq","barSeriesConfigs","barSeriesIndexByBar","cfg","layoutPx","bestBarHit","originalSeriesIndex","yDomain","basePx","topPx","bounds","isScatter","scatterCfg","maxRadiusInSeries","seriesCutoffSq","first","tupleData","insertionIndex","pruneSq","dxSqLeft","dxSqRight","sy","allowedSq","allowed","objectData","hasNaNXCache","seriesHasNaNX","isTuple","hasNaN","computeBarHitTestLayout","barSeries","barWidthRange","gap","clusterWidth","clusterIndexByGlobalSeriesIndex","globalSeriesIndex","findPointsAtX","xValue","tolerance","maxDx","maxDxSq","matches","barLayout","offsetLeftFromCategoryCenter","hitTol","hitIndex","isHit","xCenterRange","xCenter","xTargetAdjusted","getXCenterAt","bestDxSq","tryUpdate","dxSq","dxSqAt","findPieSlice","pieConfig","dyUp","angle","slice","wedgeSpan","rel","assertFinite","createLinearScale","rangeMin","rangeMax","self","min","max","pixel","createCategoryScale","categories","indexByCategory","rebuildIndex","nextCategories","category","step","getAnchorTransform","anchor","createTextOverlay","container","didSetRelative","previousInlinePosition","overlay","text","rotation","translateX","originX","getSeriesName","candidate","getSeriesColor","theme","explicit","palette","getPieSliceLabel","sliceName","sliceIndex","getPieSliceColor","sliceColor","len","createLegend","position","root","list","items","swatch","createTooltip","fadeMs","transitionToken","hideTimeoutId","rafId","clearPendingTransitions","isCurrentlyHidden","measureSize","prevVisibility","width","content","wasHidden","pad","containerW","containerH","myToken","EM_DASH","escapeHtml","formatNumber","resolveSeriesName","params","sanitizeCssColor","formatRowHtml","valueText","safeName","safeValue","formatTooltipItem","formatTooltipAxis","xText","header","rows","normalizeDurationMs","duration","normalizeTimestampMs","timestamp","createAnimationController","animations","animate","from","to","easing","onUpdate","onComplete","id","cancel","animationId","cancelAll","update","ts","ids","anim","startTime","durationMs","elapsed","shouldComplete","rawT","easeLinear","easeCubicOut","inv","easeCubicInOut","easeBounceOut","n1","d1","getEasing","name","LABEL_PADDING_CSS_PX","DEFAULT_CROSSHAIR_LINE_WIDTH_CSS_PX","DEFAULT_HIGHLIGHT_SIZE_CSS_PX","MAX_ANIMATED_POINTS_PER_SERIES","assertUnreachable","computeRawBoundsFromData","extendBoundsWithDataPoints","points","seeded","computeGlobalBounds","runtimeRawBoundsByIndex","runtimeBoundsCandidate","rawBoundsCandidate","normalizeDomain","minCandidate","maxCandidate","computeGridArea","gpuContext","rgba01ToCssRgba","withAlpha","alphaMultiplier","lerp","t01","lerpDomain","clipXToCanvasCssPx","clipYToCanvasCssPx","isTuplePoint","isTupleDataArray","isMonotonicNonDecreasingFiniteX","prevX","lowerBoundXTuple","upperBoundXTuple","lowerBoundXObject","upperBoundXObject","sliceVisibleRangeByX","resolvePieCenterPlotCss","isPieRadiusTuple","resolvePieRadiiCss","DEFAULT_MAX_TICK_FRACTION_DIGITS","computeMaxFractionDigitsFromStep","tickStep","cap","stepAbs","scaled","rounded","err","tol","createTickFormatter","maximumFractionDigits","formatTickValue","nf","normalized","formatted","computeBaseXDomain","baseMin","baseMax","computeBaseYDomain","computeVisibleXDomain","baseXDomain","zoomRange","fractionRaw","spanFraction","resolveAnimationConfig","animation","durationMsRaw","delayMsRaw","delayMs","resolveIntroAnimationConfig","resolveUpdateAnimationConfig","createAnimatedBarYScale","baseYScale","progress01","wrapper","createRenderCoordinator","callbacks","overlayContainer","legend","currentOptions","lastSeriesCount","introPhase","introProgress01","introAnimController","introAnimId","hasRenderedOnce","updateAnimController","updateAnimId","updateProgress01","updateTransition","updateInterpolationCaches","resetUpdateInterpolationCaches","interpolateCartesianSeriesDataByIndex","fromData","toData","cache","created","pTo","yFrom","yTo","interpolatePieSeriesByIndex","fromSeries","toSeries","_b","vFrom","vTo","interpolateSeriesForUpdate","caches","animated","aAny","bAny","aData","bData","animatedData","computeUpdateSnapshotAtProgress","transition","xBase","xVisible","yBase","warnedPieAppendSeries","runtimeRawDataByIndex","runtimeBaseSeries","renderSeries","flushScheduled","flushRafId","flushTimeoutId","zoomResampleDebounceTimer","zoomResampleDue","pendingAppendByIndex","gpuSeriesKindByIndex","appendedGpuThisFrame","tooltip","gridRenderer","xAxisRenderer","yAxisRenderer","crosshairRenderer","highlightRenderer","pointerState","interactionX","interactionXSource","interactionXListeners","lastInteractionScales","emitInteractionX","nextX","source","setInteractionXInternal","requestRender","isFullSpanZoomRange","range","cancelScheduledFlush","cancelZoomResampleDebounce","flushPendingAppends","zoomRangeBefore","isFullSpanZoomBefore","canAutoScroll","prevBaseXDomain","prevVisibleXDomain","didAppendAny","seed","nextBaseXDomain","nextStartRaw","nextEndRaw","recomputeRuntimeBaseSeries","zoomRangeAfter","executeFlush","requestRenderAfter","didAppend","zoomIsFullSpan","zoomActiveNotFullSpan","didResample","recomputeRenderSeries","scheduleFlush","scheduleZoomResample","getPlotSizeCssPx","computeInteractionScalesGridCssPx","domains","buildTooltipParams","dataIndex","insideZoom","unsubscribeZoom","lastOptionsZoomRange","zoomRangeListeners","emitZoomRange","getZoomOptionsConfig","opts","insideCfg","z","sliderCfg","updateZoom","initRuntimeSeriesFromOptions","owned","baselineSampled","visibleX","MIN_TARGET_POINTS","MAX_TARGET_POINTS_ABS","MAX_TARGET_MULTIPLIER","spanFracSafe","rawData","visibleRaw","baseThreshold","baseT","maxTarget","target","sampled","areaRenderers","lineRenderers","scatterRenderers","pieRenderers","barRenderer","ensureAreaRendererCount","ensureLineRendererCount","ensureScatterRendererCount","ensurePieRendererCount","cancelUpdateTransition","isDomainEqual","didSeriesDataLikelyChange","prev","aPie","bPie","aRaw","bRaw","setOptions","resolvedOptions","fromZoomRange","fromSnapshot","fromXBase","fromXVisible","fromYBase","likelyDataChanged","shouldHaveTooltip","nextCount","toZoomRange","toXBase","toXVisible","toYBase","toSeriesForTransition","domainChanged","updateCfg","totalMs","easingWithDelay","elapsedMs","innerT","appendData","shouldRenderArea","_c","_d","_e","_f","_g","_h","hasCartesianSeries","seriesForIntro","introCfg","hasDrawableSeriesMarks","it","updateP","yBaseDomain","visibleXDomain","plotScissor","interactionScales","seriesForRender","effectivePointer","crosshairOptions","match","xGridCss","yGridCss","centerCssX","centerCssY","seriesColor","formatter","trigger","containerX","containerY","paramsArray","m0","pieMatch","pieSeries","radii","defaultBaseline","introP","areaLike","yScaleForBars","textureView","clearValue","pass","offsetX","offsetY","plotRightCss","plotBottomCss","xTickCount","xTickLengthCssPx","xDomainMin","xDomainMax","xTickStep","xFormatter","xLabelY","xCss","yTickCount","yTickLengthCssPx","yDomainMin","yDomainMax","yTickStep","yFormatter","yLabelX","ySpans","yCss","axisNameFontSize","xAxisName","xTitleY","yAxisName","maxTickLabelWidth","yCenter","yTitleX","defaultGrid","defaultPalette","defaultLineStyle","defaultAreaStyle","defaultOptions","darkTheme","lightTheme","getTheme","sanitizeDataZoom","input","record","type","xAxisIndexRaw","startRaw","endRaw","minSpanRaw","maxSpanRaw","xAxisIndex","sanitizePalette","resolveTheme","themeInput","base","takeString","key","fontSizeRaw","fontSize","colorPaletteCandidate","normalizeOptionalColor","normalizeSampling","normalizeSamplingThreshold","resolveOptions","userOptions","baseTheme","autoScrollRaw","autoScroll","animationRaw","paletteOverride","themeCandidate","paletteFromTheme","safePalette","paletteForIndexing","grid","xAxis","yAxis","explicitColor","inheritedColor","effectiveColor","areaStyle","rawBounds","effectiveStrokeColor","lineStyle","_userAreaStyle","rest","sampledData","_sampling","_samplingThreshold","resolvedData","itemIndex","itemColor","OptionResolver","normalizeRange","createDataZoomSlider","marginTop","zIndex","showPreview","track","preview","windowEl","leftHandle","rightHandle","centerGrip","activeDragCleanup","applyRangeToDom","getTrackWidthPx","pxToPercent","dxPx","setPointerCaptureBestEffort","el","pointerId","releasePointerCaptureBestEffort","startDrag","dragStartX","startRange","onMove","ev","dxPercent","cleanedUp","cleanup","finish","onLeftDown","onRightDown","onPanDown","unsubscribe","handleBorder","cachedSupportCheck","checkWebGPUSupport","reason","DATA_ZOOM_SLIDER_HEIGHT_CSS_PX","DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX","DATA_ZOOM_SLIDER_RESERVE_CSS_PX","hasSliderDataZoom","resolveOptionsForChart","createChartGPU","supportCheck","coordinator","coordinatorTargetFormat","unsubscribeCoordinatorInteractionXChange","dataZoomSliderHost","dataZoomSlider","runtimeHitTestSeriesCache","initRuntimeHitTestStoreFromResolvedOptions","getRuntimeHitTestSeries","cachedGlobalBounds","interactionScalesCache","hovered","scheduledRaf","lastConfigured","hasHoverListeners","hasClickListeners","cancelPendingFrame","resizeInternal","unbindCoordinatorInteractionXChange","disposeDataZoomSlider","disposeDataZoomSliderHost","disposeDataZoomUi","ensureDataZoomSliderHost","host","computeZoomInOutAnchorRatio","createCoordinatorZoomStateLike","ratio","syncDataZoomUi","bindCoordinatorInteractionXChange","recreateCoordinator","prevZoomRange","shouldRequestRenderAfterChanges","maxDimension","sizeChanged","didConfigure","resize","getNearestPointFromPointerEvent","zMin","zMax","scales","cartesianMatch","buildPayload","seriesNameRaw","seriesName","setHovered","prevSeriesIndex","prevDataIndex","nextSeriesIndex","nextDataIndex","dispose","instance","nextOptions","errorMessage","info","ChartGPU","connectCharts","charts","connectionToken","disconnected","unsubscribeFns","broadcast","sourceChart","chart","onCrosshairMove","unsub","internalStateMap","createRenderScheduler","state","startRenderScheduler","internalState","schedulerId","frameHandler","currentTime","currentInternalState","deltaTime","nextInternalState","stopRenderScheduler","destroyRenderScheduler","createRenderSchedulerAsync","RenderScheduler","version"],"mappings":"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"}