import type { ColumnDataMap } from "../../data/view-reader"; import type { CategoricalLevel } from "../../axis/categorical-axis"; import { type AxisMode, type NumericCategoryDomain } from "../common/category-axis-resolver"; export interface CandleSeriesInfo { seriesId: number; splitIdx: number; splitKey: string; label: string; } /** * Logical candle record. Synthesized on demand from {@link CandleColumns} * via {@link readCandleRecord} for tooltip / hover paths. The pipeline * never materializes these — see `CandleColumns` for the columnar * storage that replaces the legacy `CandleRecord[]`. */ export interface CandleRecord { catIdx: number; splitIdx: number; seriesId: number; xCenter: number; halfWidth: number; open: number; close: number; high: number; low: number; isUp: boolean; } /** * Columnar storage for the candle record set. Replaces the legacy * `CandleRecord[]` to avoid per-record POJO allocation at scale. * * Records are appended in `(splitIdx, catIdx)` order as the pipeline * loop is structured (outer split, inner category) — both `xCenter` and * `catIdx` are monotonically non-decreasing within a split, which the * hit-test uses for binary-search narrowing. * * `count` is the active record count; the underlying typed arrays may * be over-allocated for capacity reuse across builds. */ export interface CandleColumns { count: number; catIdx: Int32Array; splitIdx: Int32Array; seriesId: Int32Array; xCenter: Float64Array; halfWidth: Float64Array; open: Float64Array; close: Float64Array; high: Float64Array; low: Float64Array; /** * 1 = up (close ≥ open), 0 = down. */ isUp: Uint8Array; } export declare function emptyCandleColumns(): CandleColumns; /** * Reuse `prev`'s typed arrays when capacity is sufficient, else allocate * fresh. Resets `count` to 0; pipeline writes from index 0. */ export declare function ensureCandleColumnsCapacity(prev: CandleColumns | null, capacity: number): CandleColumns; /** * Synthesize a {@link CandleRecord} POJO for record `i`. Used by * tooltip / pinned tooltip / hover return paths; not called in any * frame-rate hot loop. */ export declare function readCandleRecord(cols: CandleColumns, i: number): CandleRecord; export interface CandlestickPipelineInput { columns: ColumnDataMap; numRows: number; columnSlots: (string | null)[]; groupBy: string[]; splitBy: string[]; /** * Source-column types for `group_by` columns. Same shape as the bar * pipeline — used to stringify non-string row-paths and to enable * numeric-axis mode for a single non-string non-boolean group_by. */ groupByTypes: Record; /** * Band-slot geometry knobs sourced from * {@link PluginConfig.band_inner_frac} / `bar_inner_pad`. Forwarded * to `computeSlotGeometry`. Replace the `BAND_INNER_FRAC` / * `BAR_INNER_PAD` constants. */ bandInnerFrac: number; barInnerPad: number; /** * Reusable scratch — pipeline writes records into the typed arrays * in place. Pass the previous build's columns to amortize * allocation across data reloads. */ scratchCandles?: CandleColumns | null; } export type { NumericCategoryDomain }; export interface CandlestickPipelineResult { splitPrefixes: string[]; rowPaths: CategoricalLevel[]; numCategories: number; rowOffset: number; /** * Axis mode discriminator (see bar-build for semantics). */ axisMode: AxisMode; numericCategoryDomain: NumericCategoryDomain | null; /** * Per-category X position (real data units) in numeric mode. */ categoryPositions: Float64Array | null; series: CandleSeriesInfo[]; candles: CandleColumns; yDomain: { min: number; max: number; }; } /** * Pure pipeline: turn a raw `ColumnDataMap` into a columnar * {@link CandleColumns}. Column slots (Open / Close / High / Low) mirror * d3fc's convention: * - `Open` is required. * - `Close` falls back to the next row's Open (last row: own Open). * - `High` falls back to `max(open, close)`. * - `Low` falls back to `min(open, close)`. * * The fallbacks apply per series when `split_by` is active, so each * split reads the "next row" from its own series. */ export declare function buildCandlestickPipeline(input: CandlestickPipelineInput): CandlestickPipelineResult;