import { BackgroundOptions } from '../../entities/background'; import { CaptionOptions } from '../../entities/caption'; import { GradientLegendOptions } from '../../entities/gradient-legend'; import { LegendOptions } from '../../entities/legend'; import { AnnotationOptions } from '../../features/annotations'; import { ChartState } from '../../features/chart-state'; import { CrosshairOptions } from '../../features/crosshair'; import { HighlightOptions } from '../../features/highlight'; import { LocaleOptions } from '../../features/locale'; import { NavigatorOptions } from '../../features/navigator'; import { ChartListeners, SelectionOptions } from '../../features/selection'; import { SyncMember, SyncOptions } from '../../features/sync'; import { TooltipOptions } from '../../features/tooltip'; import { ZoomOptions, ZoomWindow } from '../../features/zoom'; import { AnimationOptions } from '../../shared/animation'; import { ChartWidgetModule, AxisPosition, DataFrame, DomainAnchor, HighlightState, ImperativeOptions, ModuleRegistry, NodeRef, SelectedNode, ThemeContext } from '../../shared/kernel'; import { Datum, PaddingValue, Switchable } from '../../shared/options'; import { Scene } from '../../shared/scene'; /** * Input contract of the widget. The public typed ChartOptions * (discriminated unions) is assembled in app/chart-factory and is * structurally compatible with this contract; concrete series/axis types * are resolved via the registry. */ export interface CartesianChartInputs { data?: Datum[]; series?: Array<{ type: string; }>; axes?: Array<{ type: string; position?: AxisPosition; }>; title?: CaptionOptions; subtitle?: CaptionOptions; padding?: PaddingValue; background?: BackgroundOptions; legend?: LegendOptions; gradientLegend?: GradientLegendOptions; tooltip?: TooltipOptions; highlight?: HighlightOptions; loading?: boolean; overlays?: OverlaysOptions; zoom?: ZoomOptions; navigator?: NavigatorOptions; crosshair?: CrosshairOptions; annotations?: AnnotationOptions[]; selection?: SelectionOptions; listeners?: ChartListeners; locale?: LocaleOptions; sync?: SyncOptions; animation?: AnimationOptions; initialState?: ChartState; } export interface OverlaysOptions { loading?: Switchable & { text?: string; }; noData?: Switchable & { text?: string; }; /** * Shown when nothing could be drawn — every visible series refused the scales * it was given, or the axis domain came to nothing. The reason itself goes to * the console; this is the word the reader gets instead of an empty plot. */ error?: Switchable & { text?: string; }; } export declare class CartesianChart implements SyncMember { private readonly scene; private readonly registry; private readonly requestRender; private inputs; private theme; private series; private axes; private legend; private navigator; private readonly hiddenSeries; private highlight; private plot; private readonly tooltip; private zoomX; private zoomY; /** zoom.visibleCount already turned into a window; guards against reapplying it. */ private appliedVisibleCount; private pointer; /** The data under an open tooltip has changed — it is re-read once the layout has run. */ private tooltipStale; /** Where a running update is going; the value axis is scaled by it while the frames arrive. */ private settledData; /** Share of a band each row of the frame takes — the rows arriving and leaving take less. */ private bandWeights; /** How far a running update has travelled; the value axes walk their bounds by it. */ private transitionT; /** The bounds each value axis set off from — the other end of that walk. */ private readonly startDomains; /** Room each axis took when it was last laid out at rest, and the room it set off from. */ private readonly axisZones; private readonly startZones; private dragMode; private selectRect; private draggedAnnotation; /** Data Selection: seriesId → selected indices. */ private readonly selectedMap; private readonly animator; private hasAnimated; /** Dimming animation: 0 — no fading, 1 — fully dimmed. */ private readonly hoverAnimator; private hoverT; private fadeHighlight; private leaveSync; private suppressSyncBroadcast; /** * Series that threw on the scales they were given. A render must not take the * chart down with it: the animation tick and the ResizeObserver call it from * outside anyone's try, so a throw there is an unhandled error every frame. */ private readonly failedSeries; /** The chart itself has nothing to draw — a domain that parsed to nothing. */ private chartError; /** Reasons already spoken; a render runs many times a second and says each one once. */ private readonly reportedIssues; constructor(scene: Scene, registry: ModuleRegistry, requestRender: () => void, container?: HTMLElement); /** Optional feature from the registry; warn if the options request it but it is absent. */ private feature; /** * Runs the part of a render a series is allowed to refuse — it may be handed * scales its marks cannot be drawn on. What it throws is the reason it draws * nothing, and everything else on the chart is drawn regardless: a render is * called from the animation tick and from a ResizeObserver, outside any try * of the caller's, so a throw here would be an unhandled error every frame. */ private guard; /** Says a thing once: a render runs many times a second and the reason does not change. */ private report; setOptions(inputs: CartesianChartInputs, theme: ThemeContext): void; /** * The rows of a single frame while an update flows into place. Everything the * options built stays as it is — the series keep their state, and the pointer * keeps whatever it was on. `settled` is where the data is going, and what the * value axis is scaled by for as long as the frames keep coming. */ setData(data: Datum[], frame?: DataFrame): void; /** * Room an axis takes beside the plot. Its labels change with the data, and a * zone that changed with them would step the plot rect sideways under * everything drawn in it — so partway through an update it walks from the room * the axis took before to the room it takes now. */ private axisZone; /** Numeric bounds of the axes as they stand, keyed by which axis of the chart they are. */ private numericDomains; /** * Hands the bounds of the axes that were to the ones just built. The axes are * new objects on every update, and an axis that walks from where its * predecessor stood is the only one that does not jump. */ private carryDomainsOver; /** A highlight the new configuration can still answer for; nothing otherwise. */ private stillPointsAtSomething; /** * The tooltip on screen, read off the data of the frame. Numbers on their way * to new values are the numbers it prints too — a tooltip left saying what a * bar used to be while the bar moves under it is worse than none. */ private refreshTooltip; /** Value fields of the series: what an axis binds by is what a row grows from. */ valueFields(): string[]; getState(): ChartState; setState(state: ChartState): void; /** * What the legend has switched off, applied to a series: the series itself, * and — for one that puts several items in the legend — those items, which * are held as `#` in the same set. */ private applyHiddenState; /** * Sizes the starting window to zoom.visibleCount. Runs once per value of the * option, so a wheel or a reset afterwards stays put, while a new count applies. * An empty dataset defers it to the update that brings the data in. */ private applyVisibleCount; isZoomed(): boolean; resetZoom(options?: ImperativeOptions): void; /** * The same states the pointer drives, addressed by datum instead. The tooltip * and the highlight need a node on screen, so they answer false once the datum * is outside the zoom window; the selection is bookkeeping and takes any index. */ showTooltip(target: NodeRef): boolean; hideTooltip(): void; clickNode(target: NodeRef, options?: ImperativeOptions): boolean; getSelection(): SelectedNode[]; setSelection(targets: NodeRef[], options?: ImperativeOptions): void; zoomTo(window: { x?: ZoomWindow; y?: ZoomWindow; }, options?: ImperativeOptions): void; zoomToCount(count: number, options?: ImperativeOptions & { anchor?: DomainAnchor; }): void; /** The node a reference points at; without a series id the visible ones answer in order. */ private resolveNode; private buildSeries; private get swapped(); private buildAxes; /** true — the axis runs along the categories (the X direction), not the values. */ private alongCategories; private maybeAnimateEntrance; private joinSync; onRemoteHighlight(highlight: HighlightState | undefined): void; onRemoteZoom(window: ZoomWindow): void; /** Full pass: domains → layout → render into the scene. */ layoutAndRender(): void; /** * Room the labels ask for, kept in two piles because the layout owes them * different things: a tick label hangs over the end of its own axis and the * chart area has to grow for it, while a value label belongs inside the plot * and the scales pull in instead. Value labels are therefore measured against * the frame the scales already run in — a label sticking out of it by the same * amount every pass is what the layout converges on. */ private labelOverflow; private renderCache; /** * Fast hover/highlight path: only the series and overlay groups are * rebuilt from the last layout cache (no domain/axis recalculation). */ private renderDynamicLayers; /** Values of the first visible series for the navigator thumbnail. */ private miniChartValues; private renderCrosshairIfNeeded; /** Human-readable axis value at a pixel position. */ private axisLabelAt; private renderOverlays; private collectYCategories; private collectCategories; /** * How much of a band each category of the frame takes. The weight belongs to * a row of the update; a category is what a row is drawn over, and where two * rows share one the widest of them speaks for the band. */ private collectCategoryWeights; private computeSeriesStacks; private collectValueDomain; /** Band slots: each stackGroup is one slot, each standalone bar series gets its own. */ private assignBandSlots; handlePointerMove(x: number, y: number): void; /** Shared mode: rows of all visible series for the category under the cursor. */ private sharedTooltipContent; /** Tooltip anchor point respecting tooltip.position. */ private tooltipAnchor; handlePointerLeave(): void; /** Smooth transition of the dimming factor towards target (0|1). */ private animateHover; handleClick(x: number, y: number): void; private handleLegendClick; handleDoubleClick(): void; handleWheel(x: number, y: number, deltaY: number, preventDefault: () => void): void; private applyWheelZoom; private zoomByFactor; handleDragStart(x: number, y: number, modifiers?: { alt: boolean; ctrl: boolean; shift: boolean; meta: boolean; }): void; handleDragMove(x: number, _y: number, dx: number, _dy: number): void; handleDragEnd(): void; /** Finds an annotation line under the cursor (5px) for dragging. */ private hitAnnotation; /** Moves an annotation line to the cursor coordinate. */ private moveAnnotation; /** Current dimming accounting for the transition animation. */ private effectiveDimOpacity; /** Text for the ARIA announcement of the highlighted point. */ describeHighlight(): string | undefined; /** Pinch zoom around the gesture center. */ handlePinch(x: number, y: number, scale: number): void; /** Keyboard traversal of the first visible series' points. */ handleKeyStep(delta: number): void; private afterZoomChange; private broadcastHighlightIfSynced; private emitNodeClick; /** * What was clicked or selected, in the terms of the series it belongs to: a * data row for most, and for a series that counts something else (histogram * bins) the node itself — reading its index as a row index picks a stranger. */ private describeNode; /** Click semantics of the selection: single replaces it, multiple toggles the node. */ private toggleSelected; private afterSelectionChange; private collectSelection; private emitSelectionChange; private selectionActive; private pickNearest; destroy(): void; } export declare const cartesianChartModule: ChartWidgetModule;