import type { Size, Point } from './rectangle'; import { Area } from './rectangle'; import type { BoxPlotData, DonutSlice, LegendOptions, SeriesType } from './chart-types'; import type { RangeScale } from '../../treb-utils/src/index'; export interface Metrics { width: number; height: number; y_offset: number; } /** * FIXME: normalize API, make canvas version */ export declare class ChartRenderer { parent: HTMLElement; svg_node: SVGElement; text_measurement_node?: SVGTextElement; container_group: SVGGElement; group: SVGGElement; axis_group: SVGGElement; label_group: SVGGElement; size: Size; bounds: Area; constructor(); Initialize(node: HTMLElement): void; Legend(options: LegendOptions): void; Clear(class_name?: string): void; Resize(): void; /** * initialize before render. this assumes that document layout/scroll * won't change during the render pass, so we can cache some values. */ Prerender(): void; /** * render title. this method modifies "area" in place -- that's * the style we want to use going forward. * * @param title * @param area * @param margin * @param layout */ RenderTitle(title: string, area: Area, margin: number, layout: 'top' | 'bottom'): void; /** * measure a label, optionally with class name(s) * * this is silly. you are doing the measurement on a random node and * trying to match classes, while you could just do the measurement on * the actual node, get actual classes right, and not bother with junk * nodes. * * FIXME: decprecate * */ MeasureText(label: string, classes?: string | string[], ceil?: boolean): Metrics; RenderTicks(area: Area, top: number, bottom: number, count: number, classes?: string | string[]): void; /** specialization for bar; it's different enough that we want special treatment */ RenderXAxisBar(area: Area, offset: boolean, labels: string[], metrics: Metrics[], classes?: string | string[]): void; RenderXAxisTicks(area: Area, offset: boolean, count: number): void; /** * render x axis labels; skips over labels to prevent overlap * * @param offset - move label by 1/2 step width, to center it under columns. */ RenderXAxis(area: Area, offset: boolean, labels: string[], metrics: Metrics[], classes?: string | string[]): void; /** specialization for bar; it's different enough that we want special treatment */ RenderYAxisBar(area: Area, left: number, labels: Array<{ label: string; metrics: Metrics; }>, classes?: string | string[]): void; /** * render y axis labels; skips over labels to prevent overlap */ RenderYAxis(area: Area, x: number, labels: Array<{ label: string; metrics: Metrics; }>, classes?: string | string[], align?: 'left' | 'right'): void; LineProperties(a: Point, b: Point): { length: number; angle: number; }; RenderSmoothLine(area: Area, data: Array, fill?: boolean, titles?: string[], classes?: string | string[]): void; RenderLine(area: Area, data: Array, fill?: boolean, titles?: string[], classes?: string | string[]): void; /** * the other RenderGrid function has semantics specifically for area/line. * rather than try to shoehorn this in we'll use a different method. */ RenderBarGrid(area: Area, x_count: number, classes?: string | string[]): void; RenderGrid(area: Area, y_count: number, x_count?: number, classes?: string | string[], zeros?: number[]): void; MultiplyPoint(point: Point, scalar: number): Point; AddPoints(a: Point, b: Point): Point; /** * algo from * https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline */ CatmullRomSpline(P: Point[], n: number): Point[]; /** * NOTE: we are munging the point list here, so don't use it after * calling this function or pass in a temp copy * * OK so that was rude, we will not munge the list */ CatmullRomChain(original: Point[], n?: number): Point[]; RenderDataLabels(area: Area, x: Array, y: Array, x_scale: RangeScale, y_scale: RangeScale, data_labels: Array, series_index: number): void; RenderBoxAndWhisker(area: Area, data: BoxPlotData['data'][0], index: number, max_n: number, scale: RangeScale, n: number, classes?: string | string[]): void; RenderBubbleSeries(area: Area, series: SeriesType, x_scale: RangeScale, y_scale: RangeScale, classes?: string | string[]): void; RenderScatterSeries(area: Area, x: Array, y: Array, x_scale: RangeScale, y_scale: RangeScale, lines?: boolean, plot_points?: boolean, filled?: boolean, markers?: boolean, smooth?: boolean, classes?: string | string[]): void; RenderPoints(area: Area, x: number[], y: number[], classes?: string | string[]): void; RenderPoint(cx: number, cy: number, classes?: string | string[]): void; RenderCalloutLines(lines: Array<{ x1: number; y1: number; x2: number; y2: number; label?: string; classes?: string; }>): void; RenderRectangle(area: Area, corner_radius?: number[], classes?: string | string[], title?: string, label?: string, label_point?: Point): void; /** * render text at point */ RenderText(target: SVGElement | undefined, text: string, align: 'center' | 'left' | 'right', point: Point, classes?: string | string[]): void; /** * render a donut, given a list of slices (as %) * @param values */ RenderDonut(slices: DonutSlice[], center: Point, outer_radius: number, inner_radius: number, bounds_area: Area, callouts: boolean, classes?: string | string[]): void; }