import type { Datum } from "../../charts/shared/datumTypes";
/**
 * Ribbon scene builder — the unified primitive for painting a closed
 * top/bottom envelope underneath a line/area, used by:
 *
 * - `boundsAccessor` (symmetric ±offset around `yAccessor`)
 * - `band` (asymmetric `y0Accessor` / `y1Accessor` per BandConfig, with
 *   multi-band fan support)
 *
 * Both public APIs normalize to `ResolvedRibbon[]` at the PipelineStore
 * layer; the scene builders, y-extent expansion, and tooltip enrichment
 * all read that single array.
 *
 * Consumed by: lineScene, areaScene, mixedScene (each renders ribbons
 * before lines/areas so they sit underneath in z-order).
 */
import type { AreaSceneNode, Style } from "../types";
import type { XYSceneContext } from "./types";
/**
 * One ribbon worth of geometry + style. The PipelineStore owns the
 * normalization from `boundsAccessor` and `band` public props into this
 * single internal shape.
 */
export interface ResolvedRibbon {
    /**
     * Origin of this ribbon:
     * - `"bounds"`: produced by `boundsAccessor` (decorative-only)
     * - `"band"`: produced by `band` (eligible for `datum.band` tooltip
     *   enrichment in the hover handler)
     */
    kind: "bounds" | "band";
    /**
     * Top y-value for each datum. Return `NaN` to skip a datum entirely
     * (gap behavior). Bounds resolves this from `y + offset` (collapsing
     * to `y` when offset is non-finite, matching legacy behavior); band
     * resolves it from `y1Accessor`.
     */
    getTop: (d: Datum) => number;
    /**
     * Bottom y-value for each datum. Same gap semantics as `getTop`.
     */
    getBottom: (d: Datum) => number;
    /**
     * Style override. When omitted, the scene builder falls back to
     * `ctx.resolveBoundsStyle(group, sampleDatum)` — line color at 0.2
     * fillOpacity. Functions get the first datum and group key.
     */
    style?: Style | ((d: Datum, group?: string) => Style);
    /**
     * `true` → one ribbon per group, colored to match each line.
     * `false` → a single aggregate ribbon across the whole dataset.
     * Bounds is always `true`. Band defaults to `true`; the public
     * `BandConfig.perSeries: false` opt-out flips this.
     */
    perSeries: boolean;
    /**
     * Whether the ribbon area participates in hit testing. Bounds is
     * always `false`. Band defaults to `false` but supports `interactive: true`.
     */
    interactive: boolean;
}
/**
 * Build a single ribbon scene node for one slice of data.
 *
 * Iterates the data once, evaluates `getTop`/`getBottom` per datum, and
 * collects coordinate pairs. Any datum with non-finite x, top, or bottom
 * is skipped (gap semantics — equivalent to `gapStrategy: "break"`).
 * Returns `null` when fewer than two valid points remain (a single
 * point can't form a visible ribbon).
 */
export declare function buildRibbonForGroup(ctx: XYSceneContext, data: Datum[], group: string, ribbon: ResolvedRibbon): AreaSceneNode | null;
/**
 * Split ribbons by `perSeries` so the caller can dispatch correctly:
 * per-series ribbons render once per group; aggregate ribbons render
 * once across the full dataset.
 */
export declare function partitionRibbons(ribbons: ResolvedRibbon[] | undefined): {
    perSeries: ResolvedRibbon[];
    aggregate: ResolvedRibbon[];
};
/**
 * Build all aggregate ribbons (perSeries=false) for the whole dataset.
 * Each ribbon emits at most one AreaSceneNode under the synthetic
 * group key `__ribbon_aggregate`.
 */
export declare function buildAggregateRibbons(ctx: XYSceneContext, data: Datum[], ribbons: ResolvedRibbon[]): AreaSceneNode[];
/**
 * Build all per-series ribbons for one grouped data slice. Each ribbon
 * in the list emits at most one AreaSceneNode for the given group.
 */
export declare function buildPerSeriesRibbons(ctx: XYSceneContext, data: Datum[], group: string, ribbons: ResolvedRibbon[]): AreaSceneNode[];
/**
 * Enrich a hovered datum with band values so user tooltips can read
 * `datum.band = { y0, y1 }` (first band) and `datum.bands = [...]`
 * (all bands). Returns a shallow copy so the original data row is
 * never mutated.
 *
 * Bounds-sourced ribbons (`kind: "bounds"`) are intentionally excluded
 * — they're decorative, and the tooltip enrichment contract is
 * band-only. Returns the input datum unchanged when no band-kind
 * ribbons are configured or none produce finite values at this datum.
 *
 * Consumed by every code path that produces a `HoverData` in
 * StreamXYFrame: pointer hover, multi-mode per-series datum, and
 * keyboard navigation.
 */
export declare function enrichDatumWithBand(datum: Datum | null | undefined, ribbons: ResolvedRibbon[] | undefined): Datum;
