blazeplot 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/core/RingBuffer.ts","../src/core/MinMaxPyramid.ts","../src/core/SeriesStore.ts","../src/render/ShaderPrograms.ts","../src/render/Renderer.ts","../src/render/ReglBackend.ts","../src/interaction/InputController.ts","../src/interaction/Camera2D.ts","../src/interaction/AxisController.ts","../src/ui/Chart.ts"],"sourcesContent":["import type { TimeRange } from \"./types.js\";\n\nexport class RingBuffer {\n readonly capacity: number;\n private _length: number = 0;\n private _head: number = 0;\n\n private readonly xData: Float64Array;\n private readonly yData: Float32Array;\n\n constructor(capacity: number) {\n if (!Number.isInteger(capacity) || capacity <= 0) {\n throw new RangeError(\"RingBuffer capacity must be a positive integer.\");\n }\n\n this.capacity = capacity;\n this.xData = new Float64Array(capacity);\n this.yData = new Float32Array(capacity);\n }\n\n get length(): number {\n return this._length;\n }\n\n get range(): TimeRange | null {\n if (this._length === 0) return null;\n return { start: this.getX(0), end: this.getX(this._length - 1) };\n }\n\n push(x: number, y: number): void {\n this.xData[this._head] = x;\n this.yData[this._head] = y;\n this._head = (this._head + 1) % this.capacity;\n if (this._length < this.capacity) this._length++;\n }\n\n get(index: number): { x: number; y: number } | null {\n if (index < 0 || index >= this._length) return null;\n return { x: this.getX(index), y: this.getY(index) };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[this.logicalToPhysical(index)]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[this.logicalToPhysical(index)]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n clear(): void {\n this._length = 0;\n this._head = 0;\n }\n\n private logicalToPhysical(index: number): number {\n return (this._head - this._length + index + this.capacity) % this.capacity;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this._length) {\n throw new RangeError(`RingBuffer index out of range: ${index}`);\n }\n }\n}\n","import type { LODView, Viewport } from \"./types.js\";\nimport { RingBuffer } from \"./RingBuffer.js\";\n\nconst MAX_LEVELS = 16;\n\nexport class MinMaxPyramid {\n private levels: Float32Array[] = [];\n private levelLengths: Uint32Array;\n private levelSampleWidths: Uint32Array;\n\n constructor(readonly bucketSize: number = 2) {\n if (!Number.isInteger(bucketSize) || bucketSize < 2) {\n throw new RangeError(\"MinMaxPyramid bucketSize must be an integer >= 2.\");\n }\n\n this.levelLengths = new Uint32Array(MAX_LEVELS);\n this.levelSampleWidths = new Uint32Array(MAX_LEVELS);\n }\n\n build(source: RingBuffer): void {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n\n let srcLen = source.length;\n if (srcLen === 0) return;\n\n let prevLevel: Float32Array | null = null;\n let level = 0;\n\n while (srcLen > 0 && level < MAX_LEVELS) {\n const nextLen = Math.ceil(srcLen / this.bucketSize);\n const levelData = new Float32Array(nextLen * 2);\n\n for (let i = 0; i < srcLen; i += this.bucketSize) {\n let minY = Infinity;\n let maxY = -Infinity;\n const end = Math.min(i + this.bucketSize, srcLen);\n for (let j = i; j < end; j++) {\n if (prevLevel) {\n const prevMin = prevLevel[j * 2]!;\n const prevMax = prevLevel[j * 2 + 1]!;\n if (prevMin < minY) minY = prevMin;\n if (prevMax > maxY) maxY = prevMax;\n } else {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n const outIdx = Math.floor(i / this.bucketSize);\n levelData[outIdx * 2] = minY;\n levelData[outIdx * 2 + 1] = maxY;\n }\n\n this.levels[level] = levelData;\n this.levelLengths[level] = nextLen;\n this.levelSampleWidths[level] = this.bucketSize ** (level + 1);\n\n if (nextLen === 1) break;\n\n prevLevel = levelData;\n srcLen = nextLen;\n level++;\n }\n }\n\n query(_viewport: Viewport, pixelWidth: number, xRange: { start: number; length: number }): LODView {\n if (pixelWidth <= 0 || xRange.length <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const visibleSamples = xRange.length;\n const samplesPerPixel = Math.max(1, visibleSamples / pixelWidth);\n const level = Math.min(\n Math.max(0, Math.ceil(Math.log2(samplesPerPixel)) - 1),\n this.levels.length - 1,\n );\n\n const levelData = this.levels[level];\n const levelLen = this.levelLengths[level];\n const sampleWidth = this.levelSampleWidths[level];\n if (!levelData || levelLen === undefined || sampleWidth === undefined || levelLen === 0 || sampleWidth === 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel };\n }\n\n const queryStart = Math.max(0, xRange.start);\n const queryEnd = queryStart + xRange.length;\n const bucketStart = Math.max(0, Math.floor(queryStart / sampleWidth));\n const bucketEnd = Math.min(levelLen, Math.ceil(queryEnd / sampleWidth));\n const count = bucketEnd - bucketStart;\n\n if (count <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level, samplesPerPixel };\n }\n\n const result = new Float32Array(count * 2);\n for (let i = 0; i < count; i++) {\n const j = (bucketStart + i) * 2;\n result[i * 2] = levelData[j]!;\n result[i * 2 + 1] = levelData[j + 1]!;\n }\n\n return { buckets: result, bucketCount: count, level, samplesPerPixel };\n }\n}\n","import type { SeriesConfig, SeriesStyle, LODView, Viewport } from \"./types.js\";\nimport { RingBuffer } from \"./RingBuffer.js\";\nimport { MinMaxPyramid } from \"./MinMaxPyramid.js\";\n\nexport class SeriesStore {\n readonly config: SeriesConfig;\n readonly style: SeriesStyle;\n private readonly buffer: RingBuffer;\n private readonly pyramid: MinMaxPyramid;\n\n private _dirty: boolean = false;\n private _visible: boolean = true;\n\n constructor(config: SeriesConfig, style: SeriesStyle) {\n this.config = config;\n this.buffer = new RingBuffer(config.capacity);\n this.pyramid = new MinMaxPyramid();\n this.style = style;\n }\n\n get dirty(): boolean {\n return this._dirty;\n }\n\n get length(): number {\n return this.buffer.length;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n setVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n const n = Math.min(x.length, y.length);\n for (let i = 0; i < n; i++) {\n this.buffer.push(x[i]!, y[i]!);\n }\n this._dirty = true;\n }\n\n clear(): void {\n this.buffer.clear();\n this.pyramid.build(this.buffer);\n this._dirty = false;\n }\n\n rebuildPyramid(): void {\n if (!this._dirty) return;\n this.pyramid.build(this.buffer);\n this._dirty = false;\n }\n\n query(viewport: Viewport, pixelWidth: number): LODView {\n const range = this.buffer.range;\n if (!range) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n\n return this.pyramid.query(viewport, pixelWidth, {\n start,\n length: Math.max(0, end - start),\n });\n }\n\n visibleSampleCount(viewport: Viewport): number {\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n return Math.max(0, end - start);\n }\n\n copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number): number {\n if (maxPoints <= 0 || target.length < maxPoints * 2) return 0;\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const stride = Math.max(1, Math.ceil(visible / maxPoints));\n let count = 0;\n for (let i = start; i < end && count < maxPoints; i += stride) {\n target[count * 2] = this.buffer.getX(i);\n target[count * 2 + 1] = this.buffer.getY(i);\n count++;\n }\n\n return count;\n }\n\n copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number): number {\n if (maxSegments <= 0 || target.length < maxSegments * 4) return 0;\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const segmentCount = Math.min(maxSegments, visible);\n let vertexCount = 0;\n for (let segment = 0; segment < segmentCount; segment++) {\n const segmentStart = start + Math.floor((segment * visible) / segmentCount);\n const segmentEnd = start + Math.max(\n Math.floor(((segment + 1) * visible) / segmentCount),\n Math.floor((segment * visible) / segmentCount) + 1,\n );\n const clampedEnd = Math.min(end, segmentEnd);\n\n let minY = Infinity;\n let maxY = -Infinity;\n for (let i = segmentStart; i < clampedEnd; i++) {\n const y = this.buffer.getY(i);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n const x = this.buffer.getX(segmentStart + ((clampedEnd - segmentStart) >> 1));\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = minY;\n vertexCount++;\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = maxY;\n vertexCount++;\n }\n\n return vertexCount;\n }\n}\n","import lineVert from \"./shaders/line.vert?raw\";\nimport lineFrag from \"./shaders/line.frag?raw\";\nimport segmentVert from \"./shaders/segment.vert?raw\";\nimport segmentFrag from \"./shaders/segment.frag?raw\";\n\nexport const ShaderPrograms = {\n line: { vert: lineVert, frag: lineFrag },\n segment: { vert: segmentVert, frag: segmentFrag },\n} as const;\n","import { ShaderPrograms } from \"./ShaderPrograms.js\";\nimport type { Camera2D } from \"../interaction/Camera2D.js\";\nimport type { GpuBackend, GpuBuffer, GpuProgram } from \"./types.js\";\nimport type { SeriesStyle } from \"../core/types.js\";\n\nexport class Renderer {\n private readonly lineProgram: GpuProgram;\n private readonly scaleUniform: Float32Array = new Float32Array(2);\n private readonly offsetUniform: Float32Array = new Float32Array(2);\n\n constructor(private backend: GpuBackend) {\n this.lineProgram = this.backend.createProgram(ShaderPrograms.line.vert, ShaderPrograms.line.frag);\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.backend.clear(r, g, b, a);\n }\n\n createFloatBuffer(floatCount: number): GpuBuffer {\n return this.backend.createBuffer({ usage: \"stream\", type: \"float\", length: floatCount });\n }\n\n updateFloatBuffer(buffer: GpuBuffer, data: Float32Array): void {\n this.backend.updateBuffer(buffer, data);\n }\n\n viewport(x: number, y: number, width: number, height: number): void {\n this.backend.viewport(x, y, width, height);\n }\n\n drawLines(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"lines\", positions, count, style, camera);\n }\n\n drawLineStrip(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"line_strip\", positions, count, style, camera);\n }\n\n private drawLinePrimitive(primitive: \"lines\" | \"line_strip\", positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.scaleUniform[0] = camera.xScale;\n this.scaleUniform[1] = camera.yScale;\n this.offsetUniform[0] = camera.xOffset;\n this.offsetUniform[1] = camera.yOffset;\n\n this.backend.draw({\n program: this.lineProgram,\n primitive,\n count,\n attributes: { position: positions },\n uniforms: {\n uScale: this.scaleUniform,\n uOffset: this.offsetUniform,\n uColor: style.color,\n },\n });\n }\n\n drawMinMaxSegments(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLines(positions, count, style, camera);\n }\n\n dispose(): void {\n this.backend.destroy();\n }\n}\n","import createRegl from \"regl\";\nimport type { AttributeState, Buffer as ReglBuffer, DrawCommand, PrimitiveType, Regl, Uniform } from \"regl\";\nimport type { GpuBackend, GpuBuffer, GpuProgram, GpuResource, BufferSpec, DrawSpec, UniformValue } from \"./types.js\";\n\ntype ReglGpuBuffer = GpuBuffer & {\n readonly buffer: ReglBuffer;\n};\n\ntype ReglGpuProgram = GpuProgram & {\n readonly id: number;\n readonly vert: string;\n readonly frag: string;\n};\n\ninterface DrawProps {\n readonly count: number;\n readonly instances: number;\n readonly attributes: Readonly<Record<string, ReglBuffer>>;\n readonly uniforms: Readonly<Record<string, UniformValue>>;\n}\n\nfunction toReglContext(gl: WebGL2RenderingContext): WebGLRenderingContext {\n // regl's public types accept WebGLRenderingContext even though regl can run on WebGL2 contexts.\n return gl as unknown as WebGLRenderingContext;\n}\n\nexport class ReglBackend implements GpuBackend {\n private gl: WebGL2RenderingContext;\n private regl: Regl;\n private nextProgramId: number = 1;\n private commandCache: Map<string, DrawCommand> = new Map();\n\n constructor(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!gl) {\n throw new Error(\"BlazePlot requires WebGL2, but this browser/context does not support it.\");\n }\n\n this.gl = gl;\n this.regl = createRegl({\n gl: toReglContext(this.gl),\n extensions: [],\n optionalExtensions: [\n \"ext_disjoint_timer_query_webgl2\",\n ],\n });\n }\n\n createBuffer(spec: BufferSpec): GpuBuffer {\n const bytesPerElement = spec.type === \"float\" ? 4 : 2;\n return {\n length: spec.length,\n type: spec.type,\n buffer: this.regl.buffer({\n length: spec.length * bytesPerElement,\n usage: spec.usage,\n type: spec.type === \"float\" ? \"float\" : \"uint16\",\n }),\n } as ReglGpuBuffer;\n }\n\n updateBuffer(buffer: GpuBuffer, data: Float32Array | Uint16Array, offset: number = 0): void {\n if (data.length + offset > buffer.length) {\n throw new RangeError(\"GPU buffer update exceeds allocated buffer length.\");\n }\n\n const bytesPerElement = buffer.type === \"float\" ? 4 : 2;\n this.asReglBuffer(buffer).buffer.subdata(data, offset * bytesPerElement);\n }\n\n createProgram(vert: string, frag: string): GpuProgram {\n return {\n id: this.nextProgramId++,\n vert,\n frag,\n } as ReglGpuProgram;\n }\n\n draw(spec: DrawSpec): void {\n if (spec.count <= 0) return;\n\n const program = this.asReglProgram(spec.program);\n const attributeNames = Object.keys(spec.attributes).sort();\n const uniformNames = Object.keys(spec.uniforms).sort();\n const key = [program.id, spec.primitive, attributeNames.join(\",\"), uniformNames.join(\",\"), spec.instances === undefined ? 0 : 1].join(\"|\");\n let command = this.commandCache.get(key);\n\n if (!command) {\n command = this.createDrawCommand(program, spec.primitive, attributeNames, uniformNames, spec.instances !== undefined);\n this.commandCache.set(key, command);\n }\n\n const attributes: Record<string, ReglBuffer> = {};\n for (const name of attributeNames) {\n attributes[name] = this.asReglBuffer(spec.attributes[name]!).buffer;\n }\n\n command({\n count: spec.count,\n instances: spec.instances ?? 0,\n attributes,\n uniforms: spec.uniforms,\n });\n }\n\n dispose(resource: GpuResource): void {\n if (this.isReglBuffer(resource)) resource.buffer.destroy();\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.regl.clear({ color: [r, g, b, a] });\n }\n\n viewport(_x: number, _y: number, _w: number, _h: number): void {\n // Handled by regl internally via canvas size\n }\n\n destroy(): void {\n this.regl.destroy();\n }\n\n private createDrawCommand(\n program: ReglGpuProgram,\n primitive: DrawSpec[\"primitive\"],\n attributeNames: readonly string[],\n uniformNames: readonly string[],\n instanced: boolean,\n ): DrawCommand {\n const attributes: Record<string, (context: object, props: DrawProps) => AttributeState> = {};\n for (const name of attributeNames) {\n attributes[name] = (_context, props) => props.attributes[name]!;\n }\n\n const uniforms: Record<string, (context: object, props: DrawProps) => Uniform> = {};\n for (const name of uniformNames) {\n uniforms[name] = (_context, props) => props.uniforms[name] as Uniform;\n }\n\n return this.regl({\n vert: program.vert,\n frag: program.frag,\n attributes,\n uniforms,\n primitive: this.toReglPrimitive(primitive),\n count: (_context: object, props: DrawProps) => props.count,\n instances: instanced ? (_context: object, props: DrawProps) => props.instances : undefined,\n depth: { enable: false },\n });\n }\n\n private asReglBuffer(buffer: GpuBuffer): ReglGpuBuffer {\n return buffer as ReglGpuBuffer;\n }\n\n private asReglProgram(program: GpuProgram): ReglGpuProgram {\n return program as ReglGpuProgram;\n }\n\n private isReglBuffer(resource: GpuResource): resource is ReglGpuBuffer {\n return \"length\" in resource && \"type\" in resource && \"buffer\" in resource;\n }\n\n private toReglPrimitive(primitive: DrawSpec[\"primitive\"]): PrimitiveType {\n switch (primitive) {\n case \"line_strip\":\n return \"line strip\";\n case \"triangle_strip\":\n return \"triangle strip\";\n default:\n return primitive;\n }\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\nimport type { PanIntent, ViewportPolicy, ZoomIntent } from \"./types.js\";\n\nexport class InputController {\n private _enabled: boolean = true;\n private activePointerId: number | null = null;\n private lastX: number = 0;\n private lastY: number = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly camera: Camera2D,\n private readonly policy?: ViewportPolicy,\n ) {\n this.bindEvents();\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n private bindEvents(): void {\n this.canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.addEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.addEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.addEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this._enabled || this.activePointerId !== null) return;\n this.activePointerId = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this._enabled || e.pointerId !== this.activePointerId) return;\n const rect = this.canvas.getBoundingClientRect();\n const dx = rect.width > 0 ? (this.lastX - e.clientX) / rect.width : 0;\n const dy = rect.height > 0 ? (e.clientY - this.lastY) / rect.height : 0;\n const intent = this.applyPanPolicy({ dx, dy });\n if (intent) this.camera.pan(intent);\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointerId) return;\n this.activePointerId = null;\n if (this.canvas.hasPointerCapture(e.pointerId)) {\n this.canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n private onWheel = (e: WheelEvent): void => {\n if (!this._enabled) return;\n e.preventDefault();\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n const rect = this.canvas.getBoundingClientRect();\n const cx = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5;\n const cy = rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0.5;\n const intent = this.applyZoomPolicy({ factor, cx, cy, axis: \"xy\" });\n if (intent) this.camera.zoom(intent);\n };\n\n private applyPanPolicy(intent: PanIntent): PanIntent | null {\n if (!this.policy?.beforePan) return intent;\n return this.policy.beforePan(this.camera, intent);\n }\n\n private applyZoomPolicy(intent: ZoomIntent): ZoomIntent | null {\n if (!this.policy?.beforeZoom) return intent;\n return this.policy.beforeZoom(this.camera, intent);\n }\n\n dispose(): void {\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.onWheel);\n }\n}\n","import type { Viewport } from \"../core/types.js\";\nimport type { PanIntent, ZoomIntent } from \"./types.js\";\n\nexport class Camera2D {\n private _xMin: number = 0;\n private _xMax: number = 1;\n private _yMin: number = 0;\n private _yMax: number = 1;\n\n get xMin(): number {\n return this._xMin;\n }\n\n get xMax(): number {\n return this._xMax;\n }\n\n get yMin(): number {\n return this._yMin;\n }\n\n get yMax(): number {\n return this._yMax;\n }\n\n get viewport(): Viewport {\n return { xMin: this._xMin, xMax: this._xMax, yMin: this._yMin, yMax: this._yMax };\n }\n\n get xScale(): number {\n return 2 / (this._xMax - this._xMin);\n }\n\n get xOffset(): number {\n return -(this._xMin + this._xMax) / (this._xMax - this._xMin);\n }\n\n get yScale(): number {\n return 2 / (this._yMax - this._yMin);\n }\n\n get yOffset(): number {\n return -(this._yMin + this._yMax) / (this._yMax - this._yMin);\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n const next = {\n xMin: v.xMin ?? this._xMin,\n xMax: v.xMax ?? this._xMax,\n yMin: v.yMin ?? this._yMin,\n yMax: v.yMax ?? this._yMax,\n };\n Camera2D.assertValidViewport(next);\n this._xMin = next.xMin;\n this._xMax = next.xMax;\n this._yMin = next.yMin;\n this._yMax = next.yMax;\n }\n\n pan(intent: PanIntent): void {\n const { dx, dy } = intent;\n Camera2D.assertFinite(\"dx\", dx);\n Camera2D.assertFinite(\"dy\", dy);\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n this.setViewport({\n xMin: this._xMin + dx * rangeX,\n xMax: this._xMax + dx * rangeX,\n yMin: this._yMin + dy * rangeY,\n yMax: this._yMax + dy * rangeY,\n });\n }\n\n zoom(intent: ZoomIntent): void {\n const { factor, cx, cy, axis } = intent;\n Camera2D.assertFinite(\"factor\", factor);\n Camera2D.assertFinite(\"cx\", cx);\n Camera2D.assertFinite(\"cy\", cy);\n if (factor <= 0) throw new RangeError(\"Camera2D zoom factor must be > 0.\");\n\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n const dataCx = this._xMin + rangeX * cx;\n const dataCy = this._yMin + rangeY * cy;\n const newRangeX = axis === \"y\" ? rangeX : rangeX / factor;\n const newRangeY = axis === \"x\" ? rangeY : rangeY / factor;\n this.setViewport({\n xMin: dataCx - newRangeX * cx,\n xMax: dataCx + newRangeX * (1 - cx),\n yMin: dataCy - newRangeY * cy,\n yMax: dataCy + newRangeY * (1 - cy),\n });\n }\n\n toClip(x: number, y: number): [number, number] {\n return [\n x * this.xScale + this.xOffset,\n y * this.yScale + this.yOffset,\n ];\n }\n\n toScreen(clipX: number, clipY: number, canvasWidth: number, canvasHeight: number): [number, number] {\n return [\n (clipX + 1) * 0.5 * canvasWidth,\n (1 - clipY) * 0.5 * canvasHeight,\n ];\n }\n\n clone(): Camera2D {\n const c = new Camera2D();\n c.setViewport(this.viewport);\n return c;\n }\n\n private static assertValidViewport(v: Viewport): void {\n Camera2D.assertFinite(\"xMin\", v.xMin);\n Camera2D.assertFinite(\"xMax\", v.xMax);\n Camera2D.assertFinite(\"yMin\", v.yMin);\n Camera2D.assertFinite(\"yMax\", v.yMax);\n if (v.xMax <= v.xMin) throw new RangeError(\"Camera2D requires xMax > xMin.\");\n if (v.yMax <= v.yMin) throw new RangeError(\"Camera2D requires yMax > yMin.\");\n }\n\n private static assertFinite(name: string, value: number): void {\n if (!Number.isFinite(value)) throw new RangeError(`Camera2D ${name} must be finite.`);\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\n\nexport class AxisController {\n constructor(private readonly camera: Camera2D) {}\n\n getXTickValues(canvasWidth: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.xMin, this.camera.xMax, canvasWidth, maxTicks, 80, target);\n }\n\n getYTickValues(canvasHeight: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.yMin, this.camera.yMax, canvasHeight, maxTicks, 48, target);\n }\n\n formatValue(value: number): string {\n if (Math.abs(value) < 1e-12) return \"0\";\n const abs = Math.abs(value);\n if (abs >= 1e6 || abs < 1e-3) return value.toExponential(2);\n if (abs >= 100) return value.toFixed(0);\n if (abs >= 10) return value.toFixed(1);\n return value.toFixed(2);\n }\n\n private getTickValues(min: number, max: number, pixelSize: number, maxTicks: number, minPixelSpacing: number, target: number[]): number[] {\n target.length = 0;\n if (pixelSize <= 0 || maxTicks <= 0) return target;\n\n const range = max - min;\n if (!Number.isFinite(range) || range <= 0) return target;\n\n const targetTicks = Math.max(2, Math.min(maxTicks, Math.floor(pixelSize / minPixelSpacing)));\n const step = this.niceStep(range / (targetTicks - 1));\n const firstIndex = Math.floor(min / step);\n const lastIndex = Math.ceil(max / step);\n\n for (let index = firstIndex; index <= lastIndex && target.length < maxTicks + 2; index++) {\n target.push(this.normalizeTick(index * step, step));\n }\n\n return target;\n }\n\n private niceStep(rawStep: number): number {\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const normalized = rawStep / magnitude;\n\n if (normalized <= 1.5) return magnitude;\n if (normalized <= 3) return 2 * magnitude;\n if (normalized <= 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n\n private normalizeTick(value: number, step: number): number {\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n const normalized = Number(value.toFixed(decimals));\n return Object.is(normalized, -0) ? 0 : normalized;\n }\n}\n","import type { SeriesConfig, SeriesStyle } from \"../core/types.js\";\nimport { SeriesStore } from \"../core/SeriesStore.js\";\nimport { Renderer } from \"../render/Renderer.js\";\nimport { ReglBackend } from \"../render/ReglBackend.js\";\nimport type { GpuBuffer } from \"../render/types.js\";\nimport { InputController } from \"../interaction/InputController.js\";\nimport { Camera2D } from \"../interaction/Camera2D.js\";\nimport { AxisController } from \"../interaction/AxisController.js\";\nimport type { ViewportPolicy } from \"../interaction/types.js\";\n\nconst RAW_LINE_VERTEX_CAPACITY = 16_384;\nconst GRID_LINE_VERTEX_CAPACITY = 64;\n\nexport interface ChartOptions {\n readonly viewportPolicy?: ViewportPolicy;\n readonly grid?: boolean;\n readonly gridStyle?: Partial<SeriesStyle>;\n}\n\nexport interface ChartFrameStats {\n fps: number;\n frameMs: number;\n pointsRendered: number;\n drawCalls: number;\n uploadBytes: number;\n renderMode: \"none\" | \"raw\" | \"minmax\" | \"mixed\";\n}\n\nexport class Chart {\n private series: SeriesStore[] = [];\n private camera: Camera2D;\n private axis: AxisController;\n private renderer: Renderer;\n private input: InputController;\n private rawLineBuffer: GpuBuffer;\n private rawLineData: Float32Array;\n private gridBuffer: GpuBuffer;\n private gridData: Float32Array;\n private gridStyle: SeriesStyle;\n private readonly xTicks: number[] = [];\n private readonly yTicks: number[] = [];\n private stats: ChartFrameStats = {\n fps: 0,\n frameMs: 0,\n pointsRendered: 0,\n drawCalls: 0,\n uploadBytes: 0,\n renderMode: \"none\",\n };\n private resizeObserver: ResizeObserver | null = null;\n private lastFrameAt: number = 0;\n private _rafId: number = 0;\n\n constructor(private readonly canvas: HTMLCanvasElement, private readonly options: ChartOptions = {}) {\n this.applyCanvasSize();\n this.camera = new Camera2D();\n this.axis = new AxisController(this.camera);\n this.renderer = new Renderer(new ReglBackend(canvas));\n this.input = new InputController(canvas, this.camera, options.viewportPolicy);\n this.rawLineData = new Float32Array(RAW_LINE_VERTEX_CAPACITY * 2);\n this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length);\n this.gridData = new Float32Array(GRID_LINE_VERTEX_CAPACITY * 2);\n this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length);\n this.gridStyle = {\n color: options.gridStyle?.color ?? [0.22, 0.30, 0.44, 0.45],\n lineWidth: options.gridStyle?.lineWidth ?? 1,\n };\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.canvas);\n }\n }\n\n addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore {\n const s = new SeriesStore(config, {\n color: style?.color ?? [0.3, 0.6, 1.0, 1.0],\n lineWidth: style?.lineWidth ?? 1,\n });\n this.series.push(s);\n return s;\n }\n\n removeSeries(series: SeriesStore): boolean {\n const index = this.series.indexOf(series);\n if (index === -1) return false;\n\n this.series.splice(index, 1);\n return true;\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n this.camera.setViewport(v);\n }\n\n resize(dpr: number = globalThis.devicePixelRatio): boolean {\n const resized = this.applyCanvasSize(dpr);\n if (resized) {\n this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n return resized;\n }\n\n getFrameStats(target: ChartFrameStats = { fps: 0, frameMs: 0, pointsRendered: 0, drawCalls: 0, uploadBytes: 0, renderMode: \"none\" }): ChartFrameStats {\n target.fps = this.stats.fps;\n target.frameMs = this.stats.frameMs;\n target.pointsRendered = this.stats.pointsRendered;\n target.drawCalls = this.stats.drawCalls;\n target.uploadBytes = this.stats.uploadBytes;\n target.renderMode = this.stats.renderMode;\n return target;\n }\n\n start(): void {\n const frame = (): void => {\n this._rafId = requestAnimationFrame(frame);\n this.render();\n };\n this._rafId = requestAnimationFrame(frame);\n }\n\n stop(): void {\n cancelAnimationFrame(this._rafId);\n }\n\n private render(): void {\n const frameStartedAt = performance.now();\n if (this.lastFrameAt > 0) {\n this.stats.fps = 1000 / (frameStartedAt - this.lastFrameAt);\n }\n this.lastFrameAt = frameStartedAt;\n this.stats.pointsRendered = 0;\n this.stats.drawCalls = 0;\n this.stats.uploadBytes = 0;\n this.stats.renderMode = \"none\";\n\n this.options.viewportPolicy?.beforeRender?.(this.camera);\n this.renderer.clear(0.08, 0.10, 0.16, 1);\n\n const viewport = this.camera.viewport;\n if (this.options.grid !== false) {\n const gridVertexCount = this.writeGridVertices(viewport);\n if (gridVertexCount > 0) {\n this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData);\n this.renderer.drawLines(this.gridBuffer, gridVertexCount, this.gridStyle, this.camera);\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.gridData.byteLength;\n }\n }\n\n for (const s of this.series) {\n if (!s.visible) continue;\n const visibleSamples = s.visibleSampleCount(viewport);\n const dense = visibleSamples > RAW_LINE_VERTEX_CAPACITY;\n const count = dense\n ? s.copyMinMaxVisible(viewport, this.rawLineData, Math.min(this.canvas.width, RAW_LINE_VERTEX_CAPACITY >> 1))\n : s.copyRawVisible(viewport, this.rawLineData, RAW_LINE_VERTEX_CAPACITY);\n if (count < 2) continue;\n this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData);\n if (dense) {\n this.renderer.drawMinMaxSegments(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"minmax\");\n } else {\n this.renderer.drawLineStrip(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"raw\");\n }\n this.stats.pointsRendered += count;\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.rawLineData.byteLength;\n }\n\n this.stats.frameMs = performance.now() - frameStartedAt;\n }\n\n dispose(): void {\n this.stop();\n this.resizeObserver?.disconnect();\n this.input.dispose();\n this.renderer.dispose();\n }\n\n private applyCanvasSize(dpr: number = globalThis.devicePixelRatio): boolean {\n const scale = Number.isFinite(dpr) ? Math.max(1, dpr) : 1;\n const width = Math.max(1, Math.floor(this.canvas.clientWidth * scale));\n const height = Math.max(1, Math.floor(this.canvas.clientHeight * scale));\n if (this.canvas.width === width && this.canvas.height === height) return false;\n\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n private writeGridVertices(viewport: { xMin: number; xMax: number; yMin: number; yMax: number }): number {\n this.axis.getXTickValues(this.canvas.width, 12, this.xTicks);\n this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);\n\n let vertexCount = 0;\n for (const x of this.xTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMin;\n vertexCount++;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMax;\n vertexCount++;\n }\n\n for (const y of this.yTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = viewport.xMin;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n this.gridData[vertexCount * 2] = viewport.xMax;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n }\n\n return vertexCount;\n }\n\n private recordRenderMode(mode: \"raw\" | \"minmax\"): void {\n if (this.stats.renderMode === \"none\") {\n this.stats.renderMode = mode;\n } else if (this.stats.renderMode !== mode) {\n this.stats.renderMode = \"mixed\";\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/core/MinMaxPyramid.ts","../src/core/SeriesStore.ts","../src/core/RingBuffer.ts","../src/render/ShaderPrograms.ts","../src/render/Renderer.ts","../src/render/ReglBackend.ts","../src/interaction/InputController.ts","../src/interaction/Camera2D.ts","../src/interaction/AxisController.ts","../src/ui/Chart.ts","../src/core/StaticDataset.ts"],"sourcesContent":["import type { Dataset, LODView, Viewport } from \"./types.js\";\n\nconst MAX_LEVELS = 16;\n\nexport class MinMaxPyramid {\n private levels: Float32Array[] = [];\n private levelLengths: Uint32Array;\n private levelSampleWidths: Uint32Array;\n private _builtLen: number = 0;\n private _lastRangeStart: number = NaN;\n\n constructor(readonly bucketSize: number = 2) {\n if (!Number.isInteger(bucketSize) || bucketSize < 2) {\n throw new RangeError(\"MinMaxPyramid bucketSize must be an integer >= 2.\");\n }\n\n this.levelLengths = new Uint32Array(MAX_LEVELS);\n this.levelSampleWidths = new Uint32Array(MAX_LEVELS);\n }\n\n build(source: Dataset): void {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n\n let srcLen = source.length;\n if (srcLen === 0) {\n this._builtLen = 0;\n this._lastRangeStart = NaN;\n return;\n }\n\n let prevLevel: Float32Array | null = null;\n let level = 0;\n\n while (srcLen > 0 && level < MAX_LEVELS) {\n const nextLen = Math.ceil(srcLen / this.bucketSize);\n const levelData = new Float32Array(nextLen * 2);\n\n for (let i = 0; i < srcLen; i += this.bucketSize) {\n let minY = Infinity;\n let maxY = -Infinity;\n const end = Math.min(i + this.bucketSize, srcLen);\n for (let j = i; j < end; j++) {\n if (prevLevel) {\n const prevMin = prevLevel[j * 2]!;\n const prevMax = prevLevel[j * 2 + 1]!;\n if (prevMin < minY) minY = prevMin;\n if (prevMax > maxY) maxY = prevMax;\n } else {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n const outIdx = Math.floor(i / this.bucketSize);\n levelData[outIdx * 2] = minY;\n levelData[outIdx * 2 + 1] = maxY;\n }\n\n this.levels[level] = levelData;\n this.levelLengths[level] = nextLen;\n this.levelSampleWidths[level] = this.bucketSize ** (level + 1);\n\n if (nextLen === 1) break;\n\n prevLevel = levelData;\n srcLen = nextLen;\n level++;\n }\n\n this._builtLen = source.length;\n this._lastRangeStart = source.range?.start ?? NaN;\n }\n\n incrementalBuild(source: Dataset): void {\n const newLen = source.length;\n const rangeStart = source.range?.start ?? NaN;\n\n if (newLen === 0) {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n this._builtLen = 0;\n this._lastRangeStart = NaN;\n return;\n }\n\n if (newLen < this._builtLen || rangeStart !== this._lastRangeStart) {\n this.build(source);\n return;\n }\n\n if (newLen === this._builtLen) return;\n\n this.appendTail(source, newLen - this._builtLen);\n this._builtLen = newLen;\n }\n\n private appendTail(source: Dataset, appendedCount: number): void {\n const newLen = source.length;\n const W = this.bucketSize;\n let changedIdx = newLen - appendedCount;\n\n for (let L = 0; L < MAX_LEVELS; L++) {\n const items: number = L === 0 ? newLen : this.levelLengths[L - 1]!;\n const first = Math.floor(changedIdx / W);\n const last = Math.ceil(items / W) - 1;\n\n if (first > last) break;\n\n this.levelSampleWidths[L] = W ** (L + 1);\n this.ensureLevelData(L, last + 1);\n\n for (let b = first; b <= last; b++) {\n const start = b * W;\n const end = Math.min((b + 1) * W, items);\n\n let minY = Infinity;\n let maxY = -Infinity;\n\n if (L === 0) {\n for (let j = start; j < end; j++) {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n } else {\n const prev = this.levels[L - 1]!;\n for (let j = start; j < end; j++) {\n const pMin = prev[j * 2]!;\n const pMax = prev[j * 2 + 1]!;\n if (pMin < minY) minY = pMin;\n if (pMax > maxY) maxY = pMax;\n }\n }\n\n const dst = this.levels[L]!;\n dst[b * 2] = minY;\n dst[b * 2 + 1] = maxY;\n }\n\n this.levelLengths[L] = last + 1;\n changedIdx = first;\n\n if (this.levelLengths[L]! <= 1) break;\n }\n }\n\n private ensureLevelData(level: number, minBuckets: number): void {\n const needed = minBuckets * 2;\n const current = this.levels[level];\n if (current && current.length >= needed) return;\n\n const next = new Float32Array(needed);\n if (current) {\n next.set(current.subarray(0, Math.min(current.length, needed)));\n }\n this.levels[level] = next;\n }\n\n query(_viewport: Viewport, pixelWidth: number, xRange: { start: number; length: number }): LODView {\n if (pixelWidth <= 0 || xRange.length <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const visibleSamples = xRange.length;\n const samplesPerPixel = Math.max(1, visibleSamples / pixelWidth);\n const level = Math.min(\n Math.max(0, Math.ceil(Math.log2(samplesPerPixel)) - 1),\n this.levels.length - 1,\n );\n\n const levelData = this.levels[level];\n const levelLen = this.levelLengths[level];\n const sampleWidth = this.levelSampleWidths[level];\n if (!levelData || levelLen === undefined || sampleWidth === undefined || levelLen === 0 || sampleWidth === 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel };\n }\n\n const queryStart = Math.max(0, xRange.start);\n const queryEnd = queryStart + xRange.length;\n const bucketStart = Math.max(0, Math.floor(queryStart / sampleWidth));\n const bucketEnd = Math.min(levelLen, Math.ceil(queryEnd / sampleWidth));\n const count = bucketEnd - bucketStart;\n\n if (count <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level, samplesPerPixel };\n }\n\n const result = new Float32Array(count * 2);\n for (let i = 0; i < count; i++) {\n const j = (bucketStart + i) * 2;\n result[i * 2] = levelData[j]!;\n result[i * 2 + 1] = levelData[j + 1]!;\n }\n\n return { buckets: result, bucketCount: count, level, samplesPerPixel };\n }\n}\n","import type { Dataset, AppendableDataset, LODView, Viewport, SeriesConfig, SeriesStyle } from \"./types.js\";\nimport { MinMaxPyramid } from \"./MinMaxPyramid.js\";\n\nexport class SeriesStore {\n readonly config: SeriesConfig;\n readonly style: SeriesStyle;\n private readonly dataset: Dataset;\n private readonly pyramid: MinMaxPyramid;\n\n private _dirty: boolean = false;\n private _visible: boolean = true;\n\n constructor(dataset: Dataset, config: SeriesConfig, style: SeriesStyle) {\n this.dataset = dataset;\n this.config = config;\n this.pyramid = new MinMaxPyramid();\n this.style = style;\n\n if (dataset.length > 0) {\n this.pyramid.build(dataset);\n }\n }\n\n get dirty(): boolean {\n return this._dirty;\n }\n\n get length(): number {\n return this.dataset.length;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n setVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n if (!(\"push\" in this.dataset)) {\n throw new TypeError(\"SeriesStore dataset is not appendable.\");\n }\n\n const appendable = this.dataset as AppendableDataset;\n appendable.append(x, y);\n this._dirty = true;\n }\n\n clear(): void {\n if (!(\"clear\" in this.dataset)) {\n throw new TypeError(\"SeriesStore dataset is not clearable.\");\n }\n\n (this.dataset as AppendableDataset).clear();\n this.pyramid.build(this.dataset);\n this._dirty = false;\n }\n\n rebuildPyramid(): void {\n if (!this._dirty) return;\n this.pyramid.incrementalBuild(this.dataset);\n this._dirty = false;\n }\n\n query(viewport: Viewport, pixelWidth: number): LODView {\n const range = this.dataset.range;\n if (!range) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n\n return this.pyramid.query(viewport, pixelWidth, {\n start,\n length: Math.max(0, end - start),\n });\n }\n\n visibleSampleCount(viewport: Viewport): number {\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n return Math.max(0, end - start);\n }\n\n copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number): number {\n if (maxPoints <= 0 || target.length < maxPoints * 2) return 0;\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const stride = Math.max(1, Math.ceil(visible / maxPoints));\n let count = 0;\n for (let i = start; i < end && count < maxPoints; i += stride) {\n target[count * 2] = this.dataset.getX(i);\n target[count * 2 + 1] = this.dataset.getY(i);\n count++;\n }\n\n return count;\n }\n\n copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number): number {\n if (maxSegments <= 0 || target.length < maxSegments * 4) return 0;\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const segmentCount = Math.min(maxSegments, visible);\n let vertexCount = 0;\n for (let segment = 0; segment < segmentCount; segment++) {\n const segmentStart = start + Math.floor((segment * visible) / segmentCount);\n const segmentEnd = start + Math.max(\n Math.floor(((segment + 1) * visible) / segmentCount),\n Math.floor((segment * visible) / segmentCount) + 1,\n );\n const clampedEnd = Math.min(end, segmentEnd);\n\n let minY = Infinity;\n let maxY = -Infinity;\n for (let i = segmentStart; i < clampedEnd; i++) {\n const y = this.dataset.getY(i);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n const x = this.dataset.getX(segmentStart + ((clampedEnd - segmentStart) >> 1));\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = minY;\n vertexCount++;\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = maxY;\n vertexCount++;\n }\n\n return vertexCount;\n }\n}\n","import type { TimeRange } from \"./types.js\";\n\nexport class RingBuffer {\n readonly capacity: number;\n private _length: number = 0;\n private _head: number = 0;\n\n private readonly xData: Float64Array;\n private readonly yData: Float32Array;\n\n constructor(capacity: number) {\n if (!Number.isInteger(capacity) || capacity <= 0) {\n throw new RangeError(\"RingBuffer capacity must be a positive integer.\");\n }\n\n this.capacity = capacity;\n this.xData = new Float64Array(capacity);\n this.yData = new Float32Array(capacity);\n }\n\n get length(): number {\n return this._length;\n }\n\n get range(): TimeRange | null {\n if (this._length === 0) return null;\n return { start: this.getX(0), end: this.getX(this._length - 1) };\n }\n\n push(x: number, y: number): void {\n this.xData[this._head] = x;\n this.yData[this._head] = y;\n this._head = (this._head + 1) % this.capacity;\n if (this._length < this.capacity) this._length++;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n const n = Math.min(x.length, y.length);\n for (let i = 0; i < n; i++) {\n this.push(x[i]!, y[i]!);\n }\n }\n\n get(index: number): { x: number; y: number } | null {\n if (index < 0 || index >= this._length) return null;\n return { x: this.getX(index), y: this.getY(index) };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[this.logicalToPhysical(index)]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[this.logicalToPhysical(index)]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n clear(): void {\n this._length = 0;\n this._head = 0;\n }\n\n private logicalToPhysical(index: number): number {\n return (this._head - this._length + index + this.capacity) % this.capacity;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this._length) {\n throw new RangeError(`RingBuffer index out of range: ${index}`);\n }\n }\n}\n","import lineVert from \"./shaders/line.vert?raw\";\nimport lineFrag from \"./shaders/line.frag?raw\";\nimport segmentVert from \"./shaders/segment.vert?raw\";\nimport segmentFrag from \"./shaders/segment.frag?raw\";\n\nexport const ShaderPrograms = {\n line: { vert: lineVert, frag: lineFrag },\n segment: { vert: segmentVert, frag: segmentFrag },\n} as const;\n","import { ShaderPrograms } from \"./ShaderPrograms.js\";\nimport type { Camera2D } from \"../interaction/Camera2D.js\";\nimport type { GpuBackend, GpuBuffer, GpuProgram } from \"./types.js\";\nimport type { SeriesStyle } from \"../core/types.js\";\n\nexport class Renderer {\n private readonly lineProgram: GpuProgram;\n private readonly scaleUniform: Float32Array = new Float32Array(2);\n private readonly offsetUniform: Float32Array = new Float32Array(2);\n\n constructor(private backend: GpuBackend) {\n this.lineProgram = this.backend.createProgram(ShaderPrograms.line.vert, ShaderPrograms.line.frag);\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.backend.clear(r, g, b, a);\n }\n\n createFloatBuffer(floatCount: number): GpuBuffer {\n return this.backend.createBuffer({ usage: \"stream\", type: \"float\", length: floatCount });\n }\n\n updateFloatBuffer(buffer: GpuBuffer, data: Float32Array): void {\n this.backend.updateBuffer(buffer, data);\n }\n\n viewport(x: number, y: number, width: number, height: number): void {\n this.backend.viewport(x, y, width, height);\n }\n\n drawLines(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"lines\", positions, count, style, camera);\n }\n\n drawLineStrip(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"line_strip\", positions, count, style, camera);\n }\n\n private drawLinePrimitive(primitive: \"lines\" | \"line_strip\", positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.scaleUniform[0] = camera.xScale;\n this.scaleUniform[1] = camera.yScale;\n this.offsetUniform[0] = camera.xOffset;\n this.offsetUniform[1] = camera.yOffset;\n\n this.backend.draw({\n program: this.lineProgram,\n primitive,\n count,\n attributes: { position: positions },\n uniforms: {\n uScale: this.scaleUniform,\n uOffset: this.offsetUniform,\n uColor: style.color,\n },\n });\n }\n\n drawMinMaxSegments(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLines(positions, count, style, camera);\n }\n\n dispose(): void {\n this.backend.destroy();\n }\n}\n","import createRegl from \"regl\";\nimport type { AttributeState, Buffer as ReglBuffer, DrawCommand, PrimitiveType, Regl, Uniform } from \"regl\";\nimport type { GpuBackend, GpuBuffer, GpuProgram, GpuResource, BufferSpec, DrawSpec, UniformValue } from \"./types.js\";\n\ntype ReglGpuBuffer = GpuBuffer & {\n readonly buffer: ReglBuffer;\n};\n\ntype ReglGpuProgram = GpuProgram & {\n readonly id: number;\n readonly vert: string;\n readonly frag: string;\n};\n\ninterface DrawProps {\n readonly count: number;\n readonly instances: number;\n readonly attributes: Readonly<Record<string, ReglBuffer>>;\n readonly uniforms: Readonly<Record<string, UniformValue>>;\n}\n\nfunction toReglContext(gl: WebGL2RenderingContext): WebGLRenderingContext {\n // regl's public types accept WebGLRenderingContext even though regl can run on WebGL2 contexts.\n return gl as unknown as WebGLRenderingContext;\n}\n\nexport class ReglBackend implements GpuBackend {\n private gl: WebGL2RenderingContext;\n private regl: Regl;\n private nextProgramId: number = 1;\n private commandCache: Map<string, DrawCommand> = new Map();\n\n constructor(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!gl) {\n throw new Error(\"BlazePlot requires WebGL2, but this browser/context does not support it.\");\n }\n\n this.gl = gl;\n this.regl = createRegl({\n gl: toReglContext(this.gl),\n extensions: [],\n optionalExtensions: [\n \"ext_disjoint_timer_query_webgl2\",\n ],\n });\n }\n\n createBuffer(spec: BufferSpec): GpuBuffer {\n const bytesPerElement = spec.type === \"float\" ? 4 : 2;\n return {\n length: spec.length,\n type: spec.type,\n buffer: this.regl.buffer({\n length: spec.length * bytesPerElement,\n usage: spec.usage,\n type: spec.type === \"float\" ? \"float\" : \"uint16\",\n }),\n } as ReglGpuBuffer;\n }\n\n updateBuffer(buffer: GpuBuffer, data: Float32Array | Uint16Array, offset: number = 0): void {\n if (data.length + offset > buffer.length) {\n throw new RangeError(\"GPU buffer update exceeds allocated buffer length.\");\n }\n\n const bytesPerElement = buffer.type === \"float\" ? 4 : 2;\n this.asReglBuffer(buffer).buffer.subdata(data, offset * bytesPerElement);\n }\n\n createProgram(vert: string, frag: string): GpuProgram {\n return {\n id: this.nextProgramId++,\n vert,\n frag,\n } as ReglGpuProgram;\n }\n\n draw(spec: DrawSpec): void {\n if (spec.count <= 0) return;\n\n const program = this.asReglProgram(spec.program);\n const attributeNames = Object.keys(spec.attributes).sort();\n const uniformNames = Object.keys(spec.uniforms).sort();\n const key = [program.id, spec.primitive, attributeNames.join(\",\"), uniformNames.join(\",\"), spec.instances === undefined ? 0 : 1].join(\"|\");\n let command = this.commandCache.get(key);\n\n if (!command) {\n command = this.createDrawCommand(program, spec.primitive, attributeNames, uniformNames, spec.instances !== undefined);\n this.commandCache.set(key, command);\n }\n\n const attributes: Record<string, ReglBuffer> = {};\n for (const name of attributeNames) {\n attributes[name] = this.asReglBuffer(spec.attributes[name]!).buffer;\n }\n\n command({\n count: spec.count,\n instances: spec.instances ?? 0,\n attributes,\n uniforms: spec.uniforms,\n });\n }\n\n dispose(resource: GpuResource): void {\n if (this.isReglBuffer(resource)) resource.buffer.destroy();\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.regl.clear({ color: [r, g, b, a] });\n }\n\n viewport(_x: number, _y: number, _w: number, _h: number): void {\n // Handled by regl internally via canvas size\n }\n\n destroy(): void {\n this.regl.destroy();\n }\n\n private createDrawCommand(\n program: ReglGpuProgram,\n primitive: DrawSpec[\"primitive\"],\n attributeNames: readonly string[],\n uniformNames: readonly string[],\n instanced: boolean,\n ): DrawCommand {\n const attributes: Record<string, (context: object, props: DrawProps) => AttributeState> = {};\n for (const name of attributeNames) {\n attributes[name] = (_context, props) => props.attributes[name]!;\n }\n\n const uniforms: Record<string, (context: object, props: DrawProps) => Uniform> = {};\n for (const name of uniformNames) {\n uniforms[name] = (_context, props) => props.uniforms[name] as Uniform;\n }\n\n return this.regl({\n vert: program.vert,\n frag: program.frag,\n attributes,\n uniforms,\n primitive: this.toReglPrimitive(primitive),\n count: (_context: object, props: DrawProps) => props.count,\n instances: instanced ? (_context: object, props: DrawProps) => props.instances : undefined,\n depth: { enable: false },\n });\n }\n\n private asReglBuffer(buffer: GpuBuffer): ReglGpuBuffer {\n return buffer as ReglGpuBuffer;\n }\n\n private asReglProgram(program: GpuProgram): ReglGpuProgram {\n return program as ReglGpuProgram;\n }\n\n private isReglBuffer(resource: GpuResource): resource is ReglGpuBuffer {\n return \"length\" in resource && \"type\" in resource && \"buffer\" in resource;\n }\n\n private toReglPrimitive(primitive: DrawSpec[\"primitive\"]): PrimitiveType {\n switch (primitive) {\n case \"line_strip\":\n return \"line strip\";\n case \"triangle_strip\":\n return \"triangle strip\";\n default:\n return primitive;\n }\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\nimport type { PanIntent, ViewportPolicy, ZoomIntent } from \"./types.js\";\n\nexport class InputController {\n private _enabled: boolean = true;\n private activePointerId: number | null = null;\n private lastX: number = 0;\n private lastY: number = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly camera: Camera2D,\n private readonly policy?: ViewportPolicy,\n ) {\n this.bindEvents();\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n private bindEvents(): void {\n this.canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.addEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.addEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.addEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this._enabled || this.activePointerId !== null) return;\n this.activePointerId = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this._enabled || e.pointerId !== this.activePointerId) return;\n const rect = this.canvas.getBoundingClientRect();\n const dx = rect.width > 0 ? (this.lastX - e.clientX) / rect.width : 0;\n const dy = rect.height > 0 ? (e.clientY - this.lastY) / rect.height : 0;\n const intent = this.applyPanPolicy({ dx, dy });\n if (intent) this.camera.pan(intent);\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointerId) return;\n this.activePointerId = null;\n if (this.canvas.hasPointerCapture(e.pointerId)) {\n this.canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n private onWheel = (e: WheelEvent): void => {\n if (!this._enabled) return;\n e.preventDefault();\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n const rect = this.canvas.getBoundingClientRect();\n const cx = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5;\n const cy = rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0.5;\n const intent = this.applyZoomPolicy({ factor, cx, cy, axis: \"xy\" });\n if (intent) this.camera.zoom(intent);\n };\n\n private applyPanPolicy(intent: PanIntent): PanIntent | null {\n if (!this.policy?.beforePan) return intent;\n return this.policy.beforePan(this.camera, intent);\n }\n\n private applyZoomPolicy(intent: ZoomIntent): ZoomIntent | null {\n if (!this.policy?.beforeZoom) return intent;\n return this.policy.beforeZoom(this.camera, intent);\n }\n\n dispose(): void {\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.onWheel);\n }\n}\n","import type { Viewport } from \"../core/types.js\";\nimport type { PanIntent, ZoomIntent } from \"./types.js\";\n\nexport class Camera2D {\n private _xMin: number = 0;\n private _xMax: number = 1;\n private _yMin: number = 0;\n private _yMax: number = 1;\n\n get xMin(): number {\n return this._xMin;\n }\n\n get xMax(): number {\n return this._xMax;\n }\n\n get yMin(): number {\n return this._yMin;\n }\n\n get yMax(): number {\n return this._yMax;\n }\n\n get viewport(): Viewport {\n return { xMin: this._xMin, xMax: this._xMax, yMin: this._yMin, yMax: this._yMax };\n }\n\n get xScale(): number {\n return 2 / (this._xMax - this._xMin);\n }\n\n get xOffset(): number {\n return -(this._xMin + this._xMax) / (this._xMax - this._xMin);\n }\n\n get yScale(): number {\n return 2 / (this._yMax - this._yMin);\n }\n\n get yOffset(): number {\n return -(this._yMin + this._yMax) / (this._yMax - this._yMin);\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n const next = {\n xMin: v.xMin ?? this._xMin,\n xMax: v.xMax ?? this._xMax,\n yMin: v.yMin ?? this._yMin,\n yMax: v.yMax ?? this._yMax,\n };\n Camera2D.assertValidViewport(next);\n this._xMin = next.xMin;\n this._xMax = next.xMax;\n this._yMin = next.yMin;\n this._yMax = next.yMax;\n }\n\n pan(intent: PanIntent): void {\n const { dx, dy } = intent;\n Camera2D.assertFinite(\"dx\", dx);\n Camera2D.assertFinite(\"dy\", dy);\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n this.setViewport({\n xMin: this._xMin + dx * rangeX,\n xMax: this._xMax + dx * rangeX,\n yMin: this._yMin + dy * rangeY,\n yMax: this._yMax + dy * rangeY,\n });\n }\n\n zoom(intent: ZoomIntent): void {\n const { factor, cx, cy, axis } = intent;\n Camera2D.assertFinite(\"factor\", factor);\n Camera2D.assertFinite(\"cx\", cx);\n Camera2D.assertFinite(\"cy\", cy);\n if (factor <= 0) throw new RangeError(\"Camera2D zoom factor must be > 0.\");\n\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n const dataCx = this._xMin + rangeX * cx;\n const dataCy = this._yMin + rangeY * cy;\n const newRangeX = axis === \"y\" ? rangeX : rangeX / factor;\n const newRangeY = axis === \"x\" ? rangeY : rangeY / factor;\n this.setViewport({\n xMin: dataCx - newRangeX * cx,\n xMax: dataCx + newRangeX * (1 - cx),\n yMin: dataCy - newRangeY * cy,\n yMax: dataCy + newRangeY * (1 - cy),\n });\n }\n\n toClip(x: number, y: number): [number, number] {\n return [\n x * this.xScale + this.xOffset,\n y * this.yScale + this.yOffset,\n ];\n }\n\n toScreen(clipX: number, clipY: number, canvasWidth: number, canvasHeight: number): [number, number] {\n return [\n (clipX + 1) * 0.5 * canvasWidth,\n (1 - clipY) * 0.5 * canvasHeight,\n ];\n }\n\n clone(): Camera2D {\n const c = new Camera2D();\n c.setViewport(this.viewport);\n return c;\n }\n\n private static assertValidViewport(v: Viewport): void {\n Camera2D.assertFinite(\"xMin\", v.xMin);\n Camera2D.assertFinite(\"xMax\", v.xMax);\n Camera2D.assertFinite(\"yMin\", v.yMin);\n Camera2D.assertFinite(\"yMax\", v.yMax);\n if (v.xMax <= v.xMin) throw new RangeError(\"Camera2D requires xMax > xMin.\");\n if (v.yMax <= v.yMin) throw new RangeError(\"Camera2D requires yMax > yMin.\");\n }\n\n private static assertFinite(name: string, value: number): void {\n if (!Number.isFinite(value)) throw new RangeError(`Camera2D ${name} must be finite.`);\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\n\nexport class AxisController {\n constructor(private readonly camera: Camera2D) {}\n\n getXTickValues(canvasWidth: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.xMin, this.camera.xMax, canvasWidth, maxTicks, 80, target);\n }\n\n getYTickValues(canvasHeight: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.yMin, this.camera.yMax, canvasHeight, maxTicks, 48, target);\n }\n\n formatValue(value: number): string {\n if (Math.abs(value) < 1e-12) return \"0\";\n const abs = Math.abs(value);\n if (abs >= 1e6 || abs < 1e-3) return value.toExponential(2);\n if (abs >= 100) return value.toFixed(0);\n if (abs >= 10) return value.toFixed(1);\n return value.toFixed(2);\n }\n\n private getTickValues(min: number, max: number, pixelSize: number, maxTicks: number, minPixelSpacing: number, target: number[]): number[] {\n target.length = 0;\n if (pixelSize <= 0 || maxTicks <= 0) return target;\n\n const range = max - min;\n if (!Number.isFinite(range) || range <= 0) return target;\n\n const targetTicks = Math.max(2, Math.min(maxTicks, Math.floor(pixelSize / minPixelSpacing)));\n const step = this.niceStep(range / (targetTicks - 1));\n const firstIndex = Math.floor(min / step);\n const lastIndex = Math.ceil(max / step);\n\n for (let index = firstIndex; index <= lastIndex && target.length < maxTicks + 2; index++) {\n target.push(this.normalizeTick(index * step, step));\n }\n\n return target;\n }\n\n private niceStep(rawStep: number): number {\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const normalized = rawStep / magnitude;\n\n if (normalized <= 1.5) return magnitude;\n if (normalized <= 3) return 2 * magnitude;\n if (normalized <= 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n\n private normalizeTick(value: number, step: number): number {\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n const normalized = Number(value.toFixed(decimals));\n return Object.is(normalized, -0) ? 0 : normalized;\n }\n}\n","import type { SeriesConfig, SeriesStyle, Dataset } from \"../core/types.js\";\nimport { SeriesStore } from \"../core/SeriesStore.js\";\nimport { RingBuffer } from \"../core/RingBuffer.js\";\nimport { Renderer } from \"../render/Renderer.js\";\nimport { ReglBackend } from \"../render/ReglBackend.js\";\nimport type { GpuBuffer } from \"../render/types.js\";\nimport { InputController } from \"../interaction/InputController.js\";\nimport { Camera2D } from \"../interaction/Camera2D.js\";\nimport { AxisController } from \"../interaction/AxisController.js\";\nimport type { ViewportPolicy } from \"../interaction/types.js\";\n\nconst RAW_LINE_VERTEX_CAPACITY = 16_384;\nconst GRID_LINE_VERTEX_CAPACITY = 64;\n\nexport interface ChartOptions {\n readonly viewportPolicy?: ViewportPolicy;\n readonly grid?: boolean;\n readonly gridStyle?: Partial<SeriesStyle>;\n}\n\nexport interface ChartFrameStats {\n fps: number;\n frameMs: number;\n pointsRendered: number;\n drawCalls: number;\n uploadBytes: number;\n renderMode: \"none\" | \"raw\" | \"minmax\" | \"mixed\";\n}\n\nexport class Chart {\n private series: SeriesStore[] = [];\n private camera: Camera2D;\n private axis: AxisController;\n private renderer: Renderer;\n private input: InputController;\n private rawLineBuffer: GpuBuffer;\n private rawLineData: Float32Array;\n private gridBuffer: GpuBuffer;\n private gridData: Float32Array;\n private gridStyle: SeriesStyle;\n private readonly xTicks: number[] = [];\n private readonly yTicks: number[] = [];\n private stats: ChartFrameStats = {\n fps: 0,\n frameMs: 0,\n pointsRendered: 0,\n drawCalls: 0,\n uploadBytes: 0,\n renderMode: \"none\",\n };\n private resizeObserver: ResizeObserver | null = null;\n private lastFrameAt: number = 0;\n private _rafId: number = 0;\n\n constructor(private readonly canvas: HTMLCanvasElement, private readonly options: ChartOptions = {}) {\n this.applyCanvasSize();\n this.camera = new Camera2D();\n this.axis = new AxisController(this.camera);\n this.renderer = new Renderer(new ReglBackend(canvas));\n this.input = new InputController(canvas, this.camera, options.viewportPolicy);\n this.rawLineData = new Float32Array(RAW_LINE_VERTEX_CAPACITY * 2);\n this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length);\n this.gridData = new Float32Array(GRID_LINE_VERTEX_CAPACITY * 2);\n this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length);\n this.gridStyle = {\n color: options.gridStyle?.color ?? [0.22, 0.30, 0.44, 0.45],\n lineWidth: options.gridStyle?.lineWidth ?? 1,\n };\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.canvas);\n }\n }\n\n addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore {\n const dataset: Dataset = config.dataset ?? new RingBuffer(config.capacity);\n const s = new SeriesStore(dataset, config, {\n color: style?.color ?? [0.3, 0.6, 1.0, 1.0],\n lineWidth: style?.lineWidth ?? 1,\n });\n this.series.push(s);\n return s;\n }\n\n removeSeries(series: SeriesStore): boolean {\n const index = this.series.indexOf(series);\n if (index === -1) return false;\n\n this.series.splice(index, 1);\n return true;\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n this.camera.setViewport(v);\n }\n\n resize(dpr: number = globalThis.devicePixelRatio): boolean {\n const resized = this.applyCanvasSize(dpr);\n if (resized) {\n this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n return resized;\n }\n\n getFrameStats(target: ChartFrameStats = { fps: 0, frameMs: 0, pointsRendered: 0, drawCalls: 0, uploadBytes: 0, renderMode: \"none\" }): ChartFrameStats {\n target.fps = this.stats.fps;\n target.frameMs = this.stats.frameMs;\n target.pointsRendered = this.stats.pointsRendered;\n target.drawCalls = this.stats.drawCalls;\n target.uploadBytes = this.stats.uploadBytes;\n target.renderMode = this.stats.renderMode;\n return target;\n }\n\n start(): void {\n const frame = (): void => {\n this._rafId = requestAnimationFrame(frame);\n this.render();\n };\n this._rafId = requestAnimationFrame(frame);\n }\n\n stop(): void {\n cancelAnimationFrame(this._rafId);\n }\n\n private render(): void {\n const frameStartedAt = performance.now();\n if (this.lastFrameAt > 0) {\n this.stats.fps = 1000 / (frameStartedAt - this.lastFrameAt);\n }\n this.lastFrameAt = frameStartedAt;\n this.stats.pointsRendered = 0;\n this.stats.drawCalls = 0;\n this.stats.uploadBytes = 0;\n this.stats.renderMode = \"none\";\n\n this.options.viewportPolicy?.beforeRender?.(this.camera);\n this.renderer.clear(0.08, 0.10, 0.16, 1);\n\n const viewport = this.camera.viewport;\n if (this.options.grid !== false) {\n const gridVertexCount = this.writeGridVertices(viewport);\n if (gridVertexCount > 0) {\n this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData);\n this.renderer.drawLines(this.gridBuffer, gridVertexCount, this.gridStyle, this.camera);\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.gridData.byteLength;\n }\n }\n\n for (const s of this.series) {\n if (!s.visible) continue;\n const visibleSamples = s.visibleSampleCount(viewport);\n const dense = visibleSamples > RAW_LINE_VERTEX_CAPACITY;\n const count = dense\n ? s.copyMinMaxVisible(viewport, this.rawLineData, Math.min(this.canvas.width, RAW_LINE_VERTEX_CAPACITY >> 1))\n : s.copyRawVisible(viewport, this.rawLineData, RAW_LINE_VERTEX_CAPACITY);\n if (count < 2) continue;\n this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData);\n if (dense) {\n this.renderer.drawMinMaxSegments(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"minmax\");\n } else {\n this.renderer.drawLineStrip(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"raw\");\n }\n this.stats.pointsRendered += count;\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.rawLineData.byteLength;\n }\n\n this.stats.frameMs = performance.now() - frameStartedAt;\n }\n\n dispose(): void {\n this.stop();\n this.resizeObserver?.disconnect();\n this.input.dispose();\n this.renderer.dispose();\n }\n\n private applyCanvasSize(dpr: number = globalThis.devicePixelRatio): boolean {\n const scale = Number.isFinite(dpr) ? Math.max(1, dpr) : 1;\n const width = Math.max(1, Math.floor(this.canvas.clientWidth * scale));\n const height = Math.max(1, Math.floor(this.canvas.clientHeight * scale));\n if (this.canvas.width === width && this.canvas.height === height) return false;\n\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n private writeGridVertices(viewport: { xMin: number; xMax: number; yMin: number; yMax: number }): number {\n this.axis.getXTickValues(this.canvas.width, 12, this.xTicks);\n this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);\n\n let vertexCount = 0;\n for (const x of this.xTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMin;\n vertexCount++;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMax;\n vertexCount++;\n }\n\n for (const y of this.yTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = viewport.xMin;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n this.gridData[vertexCount * 2] = viewport.xMax;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n }\n\n return vertexCount;\n }\n\n private recordRenderMode(mode: \"raw\" | \"minmax\"): void {\n if (this.stats.renderMode === \"none\") {\n this.stats.renderMode = mode;\n } else if (this.stats.renderMode !== mode) {\n this.stats.renderMode = \"mixed\";\n }\n }\n}\n","import type { Dataset, TimeRange } from \"./types.js\";\n\nexport class StaticDataset implements Dataset {\n constructor(\n private readonly xData: ArrayLike<number>,\n private readonly yData: ArrayLike<number>,\n ) {}\n\n get length(): number {\n return Math.min(this.xData.length, this.yData.length);\n }\n\n get range(): TimeRange | null {\n if (this.length === 0) return null;\n return { start: this.xData[0]!, end: this.xData[this.length - 1]! };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[index]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[index]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this.length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.xData[mid]! < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this.length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.xData[mid]! <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this.length) {\n throw new RangeError(`StaticDataset index out of range: ${index}`);\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/ui/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAK9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD;AAED,qBAAa,KAAK;IAyBJ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAqB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBhF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,KAAK,CAOX;IACF,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAa;gBAEE,MAAM,EAAE,iBAAiB,EAAmB,OAAO,GAAE,YAAiB;IAoBnG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW;IAS1E,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAQ1C,WAAW,CAAC,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIpF,MAAM,CAAC,GAAG,GAAE,MAAoC,GAAG,OAAO;IAQ1D,aAAa,CAAC,MAAM,GAAE,eAA6G,GAAG,eAAe;IAUrJ,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,MAAM;IAiDd,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,gBAAgB;CAOzB"}
1
+ {"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/ui/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAW,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAK9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD;AAED,qBAAa,KAAK;IAyBJ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAqB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBhF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,KAAK,CAOX;IACF,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAa;gBAEE,MAAM,EAAE,iBAAiB,EAAmB,OAAO,GAAE,YAAiB;IAoBnG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW;IAU1E,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAQ1C,WAAW,CAAC,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIpF,MAAM,CAAC,GAAG,GAAE,MAAoC,GAAG,OAAO;IAQ1D,aAAa,CAAC,MAAM,GAAE,eAA6G,GAAG,eAAe;IAUrJ,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,MAAM;IAiDd,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,gBAAgB;CAOzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blazeplot",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "author": {
5
5
  "name": "BlazePlot contributors"
6
6
  },
@@ -25,8 +25,7 @@
25
25
  "files": [
26
26
  "dist",
27
27
  "README.md",
28
- "LICENSE",
29
- "ROADMAP.md"
28
+ "LICENSE"
30
29
  ],
31
30
  "scripts": {
32
31
  "dev": "vite",
package/ROADMAP.md DELETED
@@ -1,263 +0,0 @@
1
- # BlazePlot — Roadmap
2
-
3
- **BlazePlot is a real-time LOD time series rendering engine, not a plotting library.**
4
-
5
- Target: 10M points resident, 60 Hz append/update, pan/zoom fluid, render O(pixel) not O(samples), zero allocations in frame loop, multi-series, line/envelope/scatter.
6
-
7
- ---
8
-
9
- ## Architecture
10
-
11
- ```
12
- src/
13
- core/ # Data engine — no UI, no GPU
14
- render/ # GPU abstraction + regl V1 backend
15
- interaction/ # Camera, input, axis ticks
16
- ui/ # Orchestrator (Chart)
17
- tests/ # bun test — RingBuffer, MinMaxPyramid, Camera2D
18
- preview/ # Dev preview harness, detached from package build
19
- ```
20
-
21
- The core split: **data engine** and **renderer** are separate. A `SeriesStore` owns a `RingBuffer` + `MinMaxPyramid`. The renderer reads LOD views, never raw data.
22
-
23
- ```
24
- interface GpuBackend { … } # abstract GPU
25
- class ReglBackend { … } # V1 implementation
26
- class FutureWebGPUBackend { …} # V3
27
- ```
28
-
29
- **Camera2D** is the canonical viewport model (data-space xMin/xMax/yMin/yMax). Scale/offset for shader uniforms are derived getters. `ViewportPlanner` was removed — its pan/zoom live on `Camera2D` directly.
30
-
31
- Package output is detached from the preview app:
32
- - `bun run dev` serves `preview/`.
33
- - `bun run build` emits `dist/index.js` and `dist/index.d.ts` from `src/index.ts`.
34
- - `preview/` is excluded from npm package contents.
35
-
36
- ---
37
-
38
- ## Phase 1 — Vertical slice: line on screen
39
-
40
- **Status: in progress**
41
-
42
- Get one end-to-end path working: append → visible raw extraction → GPU upload → draw.
43
-
44
- - [x] WebGL2 context + regl init
45
- - [x] Canvas resize + DPR handling
46
- - [x] Streaming append with debug overlay
47
- - [x] `ReglBackend` — createBuffer, updateBuffer, createProgram, cached draw commands
48
- - [x] Raw line strip draw via regl
49
- - [x] Wire `Chart.render()`: clear → copy visible raw range → upload → draw
50
- - [x] **Benchmark overlay**: fps, ms/frame, points rendered, draw calls, upload bytes
51
-
52
- This is the shortest path to seeing data on screen. Benchmarking the full pipeline comes after.
53
-
54
- ---
55
-
56
- ## Phase 2 — Core data engine
57
-
58
- **Status: basic scaffold implemented, correctness tests passing**
59
-
60
- - [x] `RingBuffer` — append-only, Float64Array x / Float32Array y, logical index access, ring-wrap aware search
61
- - [x] `MinMaxPyramid` — min/max per level (bucket size 2), correct higher-level aggregation, ring-wrap aware builds, `query()` returns `LODView`
62
- - [x] `SeriesStore` — buffer + pyramid + style, dirty tracking
63
- - [x] `Camera2D` — viewport model with pan, zoom, setViewport, clip/screen transforms
64
- - [x] `DataCursor` — binary search by timestamp
65
- - [x] Tests for `RingBuffer`, `MinMaxPyramid`, and `Camera2D` (bun test runner)
66
- - [ ] **Incremental pyramid update** — current: full rebuild on every `build()`. Target: O(log N) per append, updating only closed buckets in the chain. This is the core competitive advantage — must be designed before release.
67
-
68
- ---
69
-
70
- ## Phase 2.5 — Worker pipeline
71
-
72
- **Status: not started**
73
-
74
- ```
75
- producer thread / worker ──► SharedArrayBuffer ──► downsampling worker ──► main thread
76
- ```
77
-
78
- - [ ] Ingest worker — receives data, writes to ring buffer via SharedArrayBuffer
79
- - [ ] Downsample worker — incremental pyramid update off main thread
80
- - [ ] Main thread — reads coherent snapshot, uploads visible range to GPU
81
- - [ ] `OffscreenCanvas` optional path
82
-
83
- Data structures have correctness coverage, but the incremental pyramid API must be finalized before moving them off main thread.
84
-
85
- ---
86
-
87
- ## Phase 3 — regl renderer (full)
88
-
89
- **Status: not started**
90
-
91
- - [x] `ReglBackend` — createBuffer, updateBuffer (subdata), createProgram, draw command cache
92
- - [ ] Persistent buffer pool (no Float32Array allocs per frame)
93
- - [x] Raw line strip for few visible points
94
- - [x] `MinMaxSegmentRenderer` — vertical min/max segments for dense viewports
95
- - [ ] Instanced draw for segment mode
96
- - [x] Camera transform as uniforms (scale/offset getters on Camera2D)
97
- - [ ] Two shader modes: `line.vert/frag` and `segment.vert/frag`
98
- - [x] `Renderer.drawMinMaxSegments`
99
- - [ ] Draw call batching per shader mode
100
-
101
- ---
102
-
103
- ## Phase 4 — Interaction
104
-
105
- **Status: implemented (camera + input)**
106
-
107
- - [x] `Camera2D` — viewport model with pan, zoom, setViewport
108
- - [x] `InputController` — pointer pan, wheel zoom, touch via Pointer Events
109
- - [x] `ViewportPolicy` — transforms pan/zoom intents and can update camera before render
110
- - [x] Preview synced-X policy — X stays live-followed while wheel zoom/pan affect Y only
111
- - [x] Camera uniforms propagated to shaders per frame
112
- - [ ] LOD re-query on pan/zoom (viewport change → new LODView)
113
- - [x] `AxisController` — smart tick generation and label formatting
114
- - [ ] Axis tick rendering (smart tick count, label formatting)
115
- - [x] Grid line rendering
116
-
117
- Camera modifies `Camera2D`, renderer reads it. No direct data access from interaction layer.
118
-
119
- ---
120
-
121
- ## Phase 5 — Multi-series
122
-
123
- **Status: data model ready**
124
-
125
- - [x] `Chart.addSeries()` supports multiple stores
126
- - [x] Each `SeriesStore` has independent buffer + pyramid + style
127
- - [ ] Batched draw calls (same shader → one draw per series group)
128
- - [ ] Shared X axis optional, independent Y per series
129
- - [x] Color/style per-series
130
- - [x] Series visibility toggle
131
-
132
- Limit: solid lines only, no markers, no antialias, no spline, no fill.
133
-
134
- ---
135
-
136
- ## Phase 6 — Public API
137
-
138
- **Status: basic shape exists**
139
-
140
- - [x] `new Chart(canvas)`
141
- - [x] `new Chart(canvas, { viewportPolicy })`
142
- - [x] `chart.addSeries(config, style)`
143
- - [x] `chart.setViewport({ xMin, xMax, yMin, yMax })`
144
- - [x] `chart.start()` / `chart.stop()`
145
- - [x] `chart.resize()` — handle container resize with DPR
146
- - [x] `series.append(x, y)` — accepts typed arrays
147
- - [x] `series.clear()`
148
- - [x] `chart.removeSeries(series)`
149
- - [ ] Axis labels / tick rendering
150
- - [x] Grid
151
- - [ ] Legend
152
- - [ ] Tooltip / hit testing
153
- - [ ] Export image
154
- - [ ] Theme system
155
- - [x] ResizeObserver integration
156
-
157
- Package status:
158
- - [x] `exports`, `main`, `module`, and `types` point at `dist/`
159
- - [x] Vite library build from `src/index.ts`
160
- - [x] Declaration emit from `src/` only via Vite d.ts plugin
161
- - [x] `bun pm pack --dry-run` includes package files only
162
-
163
- ---
164
-
165
- ## Downsampler — LOD engine
166
-
167
- **Status: basic pyramid built, not incremental**
168
-
169
- Current: `MinMaxPyramid.build()` does a full bottom-up rebuild. Target:
170
-
171
- ```
172
- raw level: x: Float64Array, y: Float32Array
173
- level 1: minY/maxY per bucket of 2
174
- level 2: minY/maxY per bucket of 4
175
- level 3: minY/maxY per bucket of 8
176
-
177
- ```
178
-
179
- **Incremental append**: each append updates only the chain of closed buckets. Query is O(buckets in viewport).
180
-
181
- Planned incremental design:
182
- - Raw samples are addressed by monotonically increasing logical sample index, not physical ring position.
183
- - Level `n` bucket width is `bucketSize ** (n + 1)` raw samples.
184
- - Appending a sample updates only level 0 while its bucket is open.
185
- - When a bucket closes, its min/max pair is propagated upward as one input sample for the next level.
186
- - Higher levels never read raw Y values; they combine child min/max pairs.
187
- - Ring wrap invalidates buckets whose covered logical index range was overwritten.
188
- - Query receives a visible logical index range from x-search and maps that range to bucket indices using the selected level width.
189
-
190
- **Query**: `samples_per_pixel = visible_samples / plotWidthPx`, pick `level = max(0, ceil(log2(samples_per_pixel)) - 1)`, return min/max pairs.
191
-
192
- **Render decision**:
193
- - few points → raw line strip
194
- - many points → vertical min/max segments
195
- - very many → envelope mesh
196
-
197
- ---
198
-
199
- ## Backend strategy
200
-
201
- ```
202
- V1: WebGL2 + regl ← CURRENT
203
- V2: Backend abstraction ← In place (GpuBackend interface)
204
- V3: WebGPU backend ← Future
205
- ```
206
-
207
- regl is the V1 backend, not the architecture. The `GpuBackend` interface decouples core from GPU.
208
-
209
- regl rules for V1:
210
- - Persistent buffers (no re-create per frame)
211
- - Precompiled regl commands
212
- - `subdata` on small ranges
213
- - Batched draw calls
214
- - Simple shaders, camera in uniforms
215
- - WebGL2 required (no fallback)
216
-
217
- ---
218
-
219
- ## Overflow semantics
220
-
221
- **Status: undecided**
222
-
223
- `RingBuffer` wraps silently at capacity. For streaming this is usually correct, but it should be explicit. Options:
224
- - Ring-buffer with wrap notification
225
- - Fixed capacity with error on overflow
226
- - Auto-growing buffer (breaks streaming contract)
227
-
228
- Deferred until we have a concrete use case.
229
-
230
- ---
231
-
232
- ## What we're NOT doing (V1)
233
-
234
- - SVG / Canvas2D fallback
235
- - Spline interpolation
236
- - Complex fill (gradient, area below)
237
- - Markers / point symbols
238
- - Antialias perfection
239
- - Recalculating axes in render loop
240
- - Per-series draw call without batching
241
-
242
- ---
243
-
244
- ## Competitive advantage
245
-
246
- Not WebGL. The core differentiator:
247
-
248
- > Incremental min/max pyramid + zero-allocation render loop + Camera2D viewport model
249
-
250
- Never render 10M points. Render `plotWidthPx * 2` (2k–8k vertices).
251
-
252
- ---
253
-
254
- ## Future / difficult
255
-
256
- - Multi-chart sync
257
- - Multiple Y axes
258
- - Spectrogram / heatmap
259
- - Large scatter ( > 1M points )
260
- - OHLC / candlestick
261
- - FFT / waterfall
262
- - Out-of-core data ( > RAM)
263
- - WebGPU backend