import type { Datum } from "../shared/datumTypes";
import * as React from "react";
import type { StreamXYFrameProps } from "../../stream/types";
import type { RealtimeFrameHandle } from "../../realtime/types";
import type { LegendInteractionMode, LegendPosition } from "../shared/hooks";
import type { BaseChartProps, AxisConfig, ChartAccessor } from "../shared/types";
import { type TooltipProp } from "../../Tooltip/Tooltip";
/**
 * DifferenceChart props
 */
export interface DifferenceChartProps<TDatum extends Datum = Datum> extends BaseChartProps, AxisConfig {
    /** Array of `{x, a, b}` data points. Omit for push API mode. */
    data?: TDatum[];
    /** Accessor for the x value. Default `"x"`. */
    xAccessor?: ChartAccessor<TDatum, number>;
    /** Accessor for series A. Default `"a"`. */
    seriesAAccessor?: ChartAccessor<TDatum, number>;
    /** Accessor for series B. Default `"b"`. */
    seriesBAccessor?: ChartAccessor<TDatum, number>;
    /** Display label for series A (legend + tooltip). Default `"A"`. */
    seriesALabel?: string;
    /** Display label for series B. Default `"B"`. */
    seriesBLabel?: string;
    /** Fill color when series A is above series B. Default `"var(--semiotic-danger, #dc2626)"`. */
    seriesAColor?: string;
    /** Fill color when series B is above series A. Default `"var(--semiotic-info, #2563eb)"`. */
    seriesBColor?: string;
    /** Show the A and B series as overlay lines on top of the filled difference. Default `true`. */
    showLines?: boolean;
    /** Line stroke width when `showLines` is true. Default `1.5`. */
    lineWidth?: number;
    /** Show data points on the overlay lines. Default `false`. */
    showPoints?: boolean;
    /** Point radius when `showPoints` is true. Default `3`. */
    pointRadius?: number;
    /** Curve interpolation for both the area boundary and overlay lines. Default `"linear"`. */
    curve?: "linear" | "monotoneX" | "monotoneY" | "step" | "stepAfter" | "stepBefore" | "basis" | "cardinal" | "catmullRom";
    /** Fill opacity for the difference region. Default `0.6`. */
    areaOpacity?: number;
    /** Gradient fill across each segment, same shape as AreaChart.gradientFill. */
    gradientFill?: boolean | {
        topOpacity: number;
        bottomOpacity: number;
    } | {
        colorStops: Array<{
            offset: number;
            color: string;
        }>;
    };
    /** Enable hover annotations. */
    enableHover?: boolean;
    /** Show grid lines. Default `false`. */
    showGrid?: boolean;
    /** Show legend. Default `true`. */
    showLegend?: boolean;
    /** Legend interaction mode. */
    legendInteraction?: LegendInteractionMode;
    /** Legend position. */
    legendPosition?: LegendPosition;
    /** Tooltip config. */
    tooltip?: TooltipProp;
    /** Annotation objects. */
    annotations?: Datum[];
    /** Fixed x domain. */
    xExtent?: [number | undefined, number | undefined] | [number];
    /** Fixed y domain. */
    yExtent?: [number | undefined, number | undefined] | [number];
    /** Stable ID accessor for push-mode `remove()` / `update()`. */
    pointIdAccessor?: string | ((d: Datum) => string);
    /** Maximum number of raw rows kept in the push buffer. When exceeded,
     *  oldest rows are evicted FIFO (sliding window). Default: unbounded.
     *  Recommended for long-running streams so the per-render segment
     *  recomputation stays bounded. */
    windowSize?: number;
    /** Pass-through StreamXYFrame props. */
    frameProps?: Partial<Omit<StreamXYFrameProps, "chartType" | "data" | "size">>;
}
/**
 * Crossover-segmented record used by the area pipeline. One row per
 * vertex along either the upper or lower boundary; `__diffSegment` is a
 * group key per segment so the area scene builder produces one polygon
 * per id with the correct fill color.
 */
interface SegmentRow {
    __x: number;
    /** Upper boundary y value (max of A, B). The area pipeline reads this. */
    __y: number;
    /** Lower boundary y value (min of A, B) — picked up as per-datum y0. */
    __y0: number;
    /** Segment id. Format: `"seg-<index>-<winner>"`. */
    __diffSegment: string;
    /** Which series is on top in this segment ("A" or "B"). Drives fill. */
    __diffWinner: "A" | "B";
    /** Original A value at this x (or interpolated at crossovers). */
    __valA: number;
    /** Original B value at this x (or interpolated at crossovers). */
    __valB: number;
    /** Original datum (for tooltip lookup at non-crossover vertices). */
    __sourceDatum?: Datum;
}
/**
 * Walk sorted data, splitting at each A↔B crossover. Inserts an
 * interpolated vertex on BOTH sides of every crossover so adjacent
 * segments meet at a zero-width point (no jagged edges).
 *
 * Non-finite rows are skipped; the algorithm tracks the most recent
 * VALID non-tie row (not the index neighbor) for crossover detection,
 * so a non-finite gap doesn't drop a crossover that straddles it.
 *
 * Tie rows (a === b) are handled distinctly from non-tie rows:
 *
 *   - When a tie row sits BETWEEN two non-tie rows with the SAME
 *     winner, the tie is emitted in that winner's segment as a
 *     zero-width vertex.
 *   - When a tie row sits between non-tie rows with DIFFERENT winners,
 *     the FIRST tie of the run becomes the crossover vertex. The old
 *     segment closes at the tie's x, the new segment opens at the same
 *     point, and any subsequent tie rows (multi-tie runs) carry into
 *     the new segment as zero-width vertices.
 *
 * This preserves the data's actual zero-difference point: if the user
 * supplied a tie row explicitly, the fill switches color exactly at
 * that x rather than at a linear-interpolated x that ignored the tie.
 *
 * Exported for direct unit-testing — the area pipeline depends on the
 * exact crossover-vertex shape produced here.
 */
export declare function computeDifferenceSegments<TDatum extends Datum>(raw: TDatum[], getX: (d: TDatum) => number, getA: (d: TDatum) => number, getB: (d: TDatum) => number): SegmentRow[];
/**
 * DifferenceChart — fills the area between two series with a color
 * that switches based on which series is higher at each x. Crossover
 * points are interpolated so segments meet cleanly. Both series can
 * optionally be drawn as overlay lines on top of the fill.
 *
 * Classic uses: temperature anomaly (actual vs. normal), forecast
 * accuracy (actual vs. predicted), budget variance, A/B comparison.
 *
 * @example
 * ```tsx
 * <DifferenceChart
 *   data={[
 *     { date: 1, actual: 50, forecast: 45 },
 *     { date: 2, actual: 52, forecast: 60 },
 *     { date: 3, actual: 70, forecast: 58 },
 *   ]}
 *   xAccessor="date"
 *   seriesAAccessor="actual"
 *   seriesBAccessor="forecast"
 *   seriesALabel="Actual"
 *   seriesBLabel="Forecast"
 * />
 * ```
 *
 * @example
 * ```tsx
 * // Streaming via push API — omit `data`, push raw {x, a, b} rows.
 * const ref = useRef<RealtimeFrameHandle>(null)
 * useEffect(() => {
 *   const id = setInterval(() => {
 *     const t = Date.now()
 *     ref.current?.push({ x: t, a: 50 + Math.random() * 10, b: 50 + Math.random() * 10 })
 *   }, 500)
 *   return () => clearInterval(id)
 * }, [])
 * return <DifferenceChart ref={ref} xAccessor="x" seriesAAccessor="a" seriesBAccessor="b" />
 * ```
 */
export declare const DifferenceChart: {
    <TDatum extends Datum = Datum>(props: DifferenceChartProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
    displayName?: string;
};
export {};
