import type { ReactNode } from "react";
import type { ScaleLinear, ScaleBand } from "d3-scale";
import type { WindowMode, HoverAnnotationConfig, HoverData, AnnotationContext } from "../realtime/types";
import type { AutoPlaceAnnotations } from "../recipes/annotationLayout";
import type { Style, SceneDatum, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, ThemeSemanticColors } from "./types";
import type { AnimateProp } from "./pipelineTransitionUtils";
import type { GradientLegendConfig, LegendGroup, LegendLayout } from "../types/legendTypes";
import type { Datum } from "../charts/shared/datumTypes";
export type OrdinalChartType = "bar" | "clusterbar" | "point" | "swarm" | "pie" | "donut" | "boxplot" | "violin" | "histogram" | "ridgeline" | "timeline" | "funnel" | "bar-funnel" | "swimlane" | "custom";
export interface OrdinalScales {
    o: ScaleBand<string>;
    r: ScaleLinear<number, number>;
    projection: "vertical" | "horizontal" | "radial";
}
export interface WedgeSceneNode {
    type: "wedge";
    cx: number;
    cy: number;
    innerRadius: number;
    outerRadius: number;
    /** Start angle in radians, canvas convention (0 = 3 o'clock, positive = clockwise) */
    startAngle: number;
    /** End angle in radians, canvas convention */
    endAngle: number;
    /** Corner radius for rounded wedge arcs (d3-shape arc.cornerRadius).
     *  When set on its own, rounds ALL FOUR corners (the d3-shape default).
     *  Pair with `roundedEnds` to round only the gauge's outer endpoints —
     *  the swimlane analogue for radial sectors: first wedge's start side
     *  + last wedge's end side rounded, internal zone seams stay square. */
    cornerRadius?: number;
    /** Selective per-end rounding. When omitted, `cornerRadius` rounds all
     *  four corners. When provided, `cornerRadius` rounds ONLY the sides
     *  marked `true` — `{ start: true }` rounds the wedge's startAngle
     *  side (both inner and outer corners at that angle), `{ end: true }`
     *  rounds the endAngle side. The gauge scene builder uses this to
     *  paint outer endpoints rounded but internal zone seams square. */
    roundedEnds?: {
        start?: boolean;
        end?: boolean;
    };
    /** Render the wedge's interior as N equal angular slices, each filled
     *  with the corresponding color from `colors`. The wedge's own shape
     *  (incl. `cornerRadius` + `roundedEnds`) is used as a clip mask so
     *  only the slice geometry shows through the rounded outline. Used by
     *  GaugeChart's gradient-fill mode: the band reads as one continuous
     *  rounded arc with a gradient sampled along its length, without any
     *  individual slice (which would be far too narrow to host its own
     *  rounded corners) needing to round. Slices are an internal
     *  rendering detail — they do not appear as separate scene nodes,
     *  participate in hit testing, or transition independently. */
    _gradientBand?: {
        colors: string[];
    };
    style: Style;
    datum: SceneDatum;
    category?: string;
    _pulseIntensity?: number;
    _pulseColor?: string;
    _pulseGlowRadius?: number;
    _targetOpacity?: number;
    _targetStartAngle?: number;
    _targetEndAngle?: number;
    _transitionKey?: string;
}
export interface BoxplotSceneNode {
    type: "boxplot";
    /** Pixel x position of the column center */
    x: number;
    /** Pixel y of the value axis origin */
    y: number;
    projection: "vertical" | "horizontal";
    columnWidth: number;
    /** Pre-projected pixel positions for each quantile */
    minPos: number;
    q1Pos: number;
    medianPos: number;
    q3Pos: number;
    maxPos: number;
    stats: DistributionStats;
    style: Style;
    datum: Datum;
    category?: string;
    outliers?: {
        px: number;
        py: number;
        value: number;
        datum: Datum;
    }[];
    _pulseIntensity?: number;
    _pulseColor?: string;
    _pulseGlowRadius?: number;
    _targetOpacity?: number;
    _transitionKey?: string;
}
export interface DistributionStats {
    n: number;
    min: number;
    q1: number;
    median: number;
    q3: number;
    max: number;
    mean: number;
}
export interface ViolinSceneNode {
    type: "violin";
    /** Pre-computed SVG path string for Path2D */
    pathString: string;
    /** Translation for the path */
    translateX: number;
    translateY: number;
    /** Bounding box for hit testing */
    bounds?: {
        x: number;
        y: number;
        width: number;
        height: number;
    };
    /** Optional IQR line overlay */
    iqrLine?: {
        q1Pos: number;
        medianPos: number;
        q3Pos: number;
        centerPos: number;
        isVertical: boolean;
    };
    /** Pre-computed distribution statistics for tooltips */
    stats?: DistributionStats;
    style: Style;
    datum: Datum;
    category?: string;
    _pulseIntensity?: number;
    _pulseColor?: string;
    _pulseGlowRadius?: number;
    _targetOpacity?: number;
    _transitionKey?: string;
}
export interface ConnectorSceneNode {
    type: "connector";
    x1: number;
    y1: number;
    x2: number;
    y2: number;
    style: Style;
    datum: Datum;
    group?: string;
    _pulseIntensity?: number;
    _pulseColor?: string;
    _pulseGlowRadius?: number;
    _targetOpacity?: number;
    _transitionKey?: string;
}
export interface TrapezoidSceneNode {
    type: "trapezoid";
    /** Four corners: [top-left, top-right, bottom-right, bottom-left] */
    points: [number, number][];
    style: Style;
    datum: Datum;
    category?: string;
    _pulseIntensity?: number;
    _pulseColor?: string;
    _pulseGlowRadius?: number;
    _targetOpacity?: number;
    _transitionKey?: string;
}
export type { Style, PointSceneNode, RectSceneNode } from "./types";
import type { PointSceneNode, RectSceneNode } from "./types";
export type OrdinalSceneNode = RectSceneNode | PointSceneNode | WedgeSceneNode | BoxplotSceneNode | ViolinSceneNode | ConnectorSceneNode | TrapezoidSceneNode;
export interface OrdinalColumn {
    name: string;
    x: number;
    y: number;
    width: number;
    middle: number;
    padding: number;
    pieceData: Datum[];
    /** For radial: proportion of total (0-1) */
    pct: number;
    /** For radial: cumulative start proportion */
    pctStart: number;
}
export interface OrdinalPipelineConfig {
    chartType: OrdinalChartType;
    runtimeMode?: "bounded" | "streaming";
    windowSize: number;
    windowMode: WindowMode;
    extentPadding: number;
    /** When `"exact"`, the value-axis domain is pinned to the literal data
     *  min/max — `extentPadding` is skipped so the first and last ticks
     *  land on the actual data bounds. Default `"nice"` keeps the existing
     *  padded domain so symbols at the extremes don't clip the plot edge. */
    axisExtent?: import("../charts/shared/axisExtent").AxisExtentMode;
    projection: "vertical" | "horizontal" | "radial";
    categoryAccessor?: string | ((d: Datum) => string);
    valueAccessor?: string | ((d: Datum) => number) | Array<string | ((d: Datum) => number)>;
    colorAccessor?: string | ((d: Datum) => string);
    stackBy?: string | ((d: Datum) => string);
    groupBy?: string | ((d: Datum) => string);
    timeAccessor?: string | ((d: Datum) => number);
    /** @deprecated Use categoryAccessor */
    oAccessor?: string | ((d: Datum) => string);
    /** @deprecated Use valueAccessor */
    rAccessor?: string | ((d: Datum) => number) | Array<string | ((d: Datum) => number)>;
    multiAxis?: boolean;
    rExtent?: [number?, number?];
    oExtent?: string[];
    barPadding?: number;
    /** Rounded top corner radius for bar charts. Only the end away from the baseline is rounded. For stacked bars, only the topmost segment gets rounded. */
    roundedTop?: number;
    /** Gradient fill for bar rects. `{ topOpacity, bottomOpacity }` fades the
     *  resolved fill color from tip (opposite the baseline) to base; `{ colorStops }`
     *  renders a multi-color gradient along the same axis. Direction follows the
     *  bar's orientation (tip → base). Same shape as AreaChart.gradientFill
     *  sans the `boolean` case — the HOC resolves `true` to default opacities. */
    gradientFill?: {
        topOpacity: number;
        bottomOpacity: number;
    } | {
        colorStops: Array<{
            offset: number;
            color: string;
        }>;
    };
    /** Swimlane "track" fill — a rect drawn behind each lane spanning the
     *  full value-axis range, sized to the lane's bandwidth. Used to make
     *  budget/progress lanes read as filled vs. empty. Pass a color (CSS
     *  var supported) or `{ color, opacity }`. Honored by `chartType="swimlane"` only. */
    trackFill?: string | {
        color: string;
        opacity?: number;
    };
    /** When true, adds padding below the 0 baseline. When false (default), bars are flush with the axis line. */
    baselinePadding?: boolean;
    innerRadius?: number;
    /** Corner radius for rounded wedge arcs (pie/donut) */
    cornerRadius?: number;
    normalize?: boolean;
    startAngle?: number;
    /** Total arc sweep in degrees (default 360 = full circle). Used by GaugeChart for partial arcs. */
    sweepAngle?: number;
    bins?: number;
    showOutliers?: boolean;
    showIQR?: boolean;
    amplitude?: number;
    connectorOpacity?: number;
    showLabels?: boolean;
    oSort?: ((a: string, b: string) => number) | boolean | "asc" | "desc" | "auto";
    connectorAccessor?: string | ((d: Datum) => string);
    connectorStyle?: Style | ((d: Datum) => Style);
    dynamicColumnWidth?: string | ((data: Datum[]) => number);
    pieceStyle?: (d: Datum, category?: string) => Style;
    summaryStyle?: (d: Datum, category?: string) => Style;
    colorScheme?: string | string[];
    themeCategorical?: string[];
    /** Theme-resolved semantic role colors — default fallback before hardcoded hex. See `ThemeSemanticColors` in ./types. */
    themeSemantic?: ThemeSemanticColors;
    /** Theme sequential scheme name — fallback for magnitude encodings. */
    themeSequential?: string;
    /** Theme diverging scheme name — fallback for midpoint encodings (LikertChart). */
    themeDiverging?: string;
    barColors?: Record<string, string>;
    /** ID accessor for remove() — extracts a unique identifier from each datum */
    dataIdAccessor?: string | ((d: Datum) => string);
    decay?: DecayConfig;
    pulse?: PulseConfig;
    transition?: TransitionConfig;
    /** Whether to animate elements on first render (bars grow from baseline, wedges sweep in) */
    introAnimation?: boolean;
    staleness?: StalenessConfig;
    /** When provided, replaces chart-type dispatch in scene building.
     *  Receives an OrdinalLayoutContext (scales, dimensions, theme,
     *  resolveColor) and returns scene nodes plus optional overlays. */
    customLayout?: import("./ordinalCustomLayout").OrdinalCustomLayout;
    /** User-supplied config blob threaded through to OrdinalLayoutContext.config. */
    layoutConfig?: object;
    /** Resolved margin — passed through so OrdinalLayoutContext.dimensions.margin
     *  reflects what the frame actually used. */
    layoutMargin?: import("../types/marginType").MarginType;
}
export interface StreamOrdinalFrameProps<T = Datum> {
    chartType: OrdinalChartType;
    runtimeMode?: "bounded" | "streaming";
    data?: T[];
    /** Category field — the ordinal dimension (replaces oAccessor) */
    categoryAccessor?: string | ((d: T) => string);
    /** Value field — the quantitative dimension (replaces rAccessor). Can be array for multiAxis. */
    valueAccessor?: string | ((d: T) => number) | Array<string | ((d: T) => number)>;
    colorAccessor?: string | ((d: T) => string);
    stackBy?: string | ((d: T) => string);
    groupBy?: string | ((d: T) => string);
    timeAccessor?: string | ((d: T) => number);
    /** @deprecated Use categoryAccessor instead */
    oAccessor?: string | ((d: T) => string);
    /** @deprecated Use valueAccessor instead */
    rAccessor?: string | ((d: T) => number) | Array<string | ((d: T) => number)>;
    multiAxis?: boolean;
    projection?: "vertical" | "horizontal" | "radial";
    size?: [number, number];
    responsiveWidth?: boolean;
    responsiveHeight?: boolean;
    margin?: {
        top?: number;
        right?: number;
        bottom?: number;
        left?: number;
    };
    barPadding?: number;
    roundedTop?: number;
    /** Gradient fill for bar rects. Same shape as AreaChart.gradientFill sans
     *  the boolean case — resolve booleans at the HOC layer. */
    gradientFill?: {
        topOpacity: number;
        bottomOpacity: number;
    } | {
        colorStops: Array<{
            offset: number;
            color: string;
        }>;
    };
    /** Swimlane "track" fill — see OrdinalPipelineConfig.trackFill */
    trackFill?: string | {
        color: string;
        opacity?: number;
    };
    baselinePadding?: boolean;
    innerRadius?: number;
    cornerRadius?: number;
    normalize?: boolean;
    startAngle?: number;
    sweepAngle?: number;
    dynamicColumnWidth?: string | ((data: T[]) => number);
    bins?: number;
    showOutliers?: boolean;
    showIQR?: boolean;
    amplitude?: number;
    connectorOpacity?: number;
    showLabels?: boolean;
    rExtent?: [number?, number?];
    oExtent?: string[];
    extentPadding?: number;
    oSort?: ((a: string, b: string) => number) | boolean | "asc" | "desc" | "auto";
    windowMode?: WindowMode;
    windowSize?: number;
    connectorAccessor?: string | ((d: T) => string);
    connectorStyle?: Style | ((d: Datum) => Style);
    /** ID accessor for remove()/update() — extracts a unique identifier from each datum */
    dataIdAccessor?: string | ((d: Datum) => string);
    /** Custom tick values for the value (r) axis. Overrides the default d3 ticks. */
    rTickValues?: number[];
    /** Align first tick label to start and last tick label to end. Default false. */
    tickLabelEdgeAlign?: boolean;
    /** Axis extent mode for the value (r) axis. `"nice"` (default) uses
     *  d3-scale's rounded tick generator. `"exact"` pins the first and
     *  last tick to the actual data min and max with equidistant
     *  intermediate ticks. The categorical (o) axis is unaffected since
     *  it's a band scale, not a continuous one. Ignored when explicit
     *  `rTickValues` are provided — caller has hand-picked positions. */
    axisExtent?: import("../charts/shared/axisExtent").AxisExtentMode;
    pieceStyle?: (d: Datum, category?: string) => Style;
    summaryStyle?: (d: Datum, category?: string) => Style;
    colorScheme?: string | string[];
    barColors?: Record<string, string>;
    showAxes?: boolean;
    showCategoryTicks?: boolean;
    /** Category axis label */
    categoryLabel?: string;
    /** Value axis label */
    valueLabel?: string;
    /** Category tick formatter */
    categoryFormat?: (d: string, index?: number) => string | ReactNode;
    /** Value tick formatter */
    valueFormat?: (d: number | string) => string;
    /** @deprecated Use categoryLabel */
    oLabel?: string;
    /** @deprecated Use valueLabel */
    rLabel?: string;
    /** @deprecated Use categoryFormat */
    oFormat?: (d: string, index?: number) => string | ReactNode;
    /** @deprecated Use valueFormat */
    rFormat?: (d: number | string) => string;
    enableHover?: boolean;
    hoverAnnotation?: boolean | HoverAnnotationConfig;
    tooltipContent?: (d: HoverData) => ReactNode;
    customHoverBehavior?: (d: HoverData | null) => void;
    annotations?: Datum[];
    autoPlaceAnnotations?: AutoPlaceAnnotations;
    svgAnnotationRules?: (annotation: Datum, index: number, context: AnnotationContext) => ReactNode;
    showGrid?: boolean;
    legend?: ReactNode | {
        legendGroups: LegendGroup[];
    } | {
        gradient: GradientLegendConfig;
    };
    legendHoverBehavior?: (item: {
        label: string;
    } | null) => void;
    legendClickBehavior?: (item: {
        label: string;
    }) => void;
    legendHighlightedCategory?: string | null;
    legendIsolatedCategories?: Set<string>;
    legendPosition?: "right" | "left" | "top" | "bottom";
    legendLayout?: LegendLayout;
    /** Accessor used to report the current legend category domain in push mode. */
    legendCategoryAccessor?: string | ((d: T) => string);
    /** Fires when the current legend category domain changes after scene rebuilds. */
    onCategoriesChange?: (categories: string[]) => void;
    backgroundGraphics?: ReactNode;
    foregroundGraphics?: ReactNode;
    title?: string | ReactNode;
    className?: string;
    background?: string;
    centerContent?: ReactNode;
    /** Brush configuration. "r" brushes the value axis. */
    brush?: boolean | "r" | {
        dimension?: "r";
    };
    /** Callback when brush selection changes. Extent is in data coordinates, or null when cleared. */
    onBrush?: (extent: {
        r: [number, number];
    } | null) => void;
    decay?: DecayConfig;
    pulse?: PulseConfig;
    transition?: TransitionConfig;
    /** Declarative animation: `true` for defaults (300ms ease-out), or config object.
     *  When enabled, charts animate on first render (intro) and on data change.
     *  Set `{ intro: false }` to disable the intro animation. */
    animate?: AnimateProp;
    staleness?: StalenessConfig;
    /** Render a visually-hidden data table from the scene graph for screen readers */
    accessibleTable?: boolean;
    /** Accessible description overriding the auto-generated aria-label on the chart container */
    description?: string;
    /** Accessible summary rendered as a screen-reader-only note */
    summary?: string;
    /** Replaces ordinal scene dispatch with a user-supplied function.
     *  Receives an OrdinalLayoutContext (scales, dimensions, theme,
     *  resolveColor), returns scene nodes + optional overlays. See
     *  `semiotic/recipes` for reference layouts (marimekko, parallel
     *  coordinates, bullet). */
    customLayout?: import("./ordinalCustomLayout").OrdinalCustomLayout;
    /** User-supplied config blob threaded through to OrdinalLayoutContext.config. */
    layoutConfig?: object;
}
export interface StreamOrdinalFrameHandle<T = Datum> {
    push(datum: T): void;
    pushMany(data: T[]): void;
    /** Replace all data. Unlike `clear() + pushMany()`, `replace()` preserves
     *  the previous scene's position snapshot so data-change transitions fire.
     *  Use when you need to swap in a full new dataset (e.g. re-aggregated
     *  values from streaming input) and want the bars/points/etc. to animate
     *  between the old and new positions.
     *
     *  Note: for datasets within the DataSourceAdapter chunk threshold (the
     *  common case for aggregator HOCs like LikertChart) the replacement
     *  lands in a single changeset. Larger datasets fall through to the
     *  progressive-chunked path used by the `data` prop — the first chunk
     *  resets + seeds the buffer, subsequent chunks append on successive
     *  animation frames, so replacement is not instantaneous for large N. */
    replace(data: T[]): void;
    /** Remove data items by ID. Requires dataIdAccessor. */
    remove(id: string | string[]): T[];
    /** Update data items by ID in place. Requires dataIdAccessor. Returns previous values. */
    update(id: string | string[], updater: (d: T) => T): T[];
    clear(): void;
    getData(): T[];
    getScales(): OrdinalScales | null;
}
export interface OrdinalLayout {
    width: number;
    height: number;
}
export type OrdinalRendererFn = (ctx: CanvasRenderingContext2D, nodes: OrdinalSceneNode[], scales: OrdinalScales, layout: OrdinalLayout) => void;
export type { HoverData, HoverAnnotationConfig, AnnotationContext, WindowMode };
export type { ArrowOfTime } from "../realtime/types";
