import * as React from "react";
import type { ReactNode } from "react";
import type { SemioticTheme } from "../store/ThemeStore";
import { useResponsiveSize } from "./useResponsiveSize";
import { resolveAnimateConfig } from "./pipelineTransitionUtils";
import type { AnimateProp } from "./pipelineTransitionUtils";
import type { TransitionConfig } from "./types";
import type { HoverPointerCoords } from "./hoverUtils";
/**
 * Frame-supplied margin defaults. Each Stream Frame has its own — XY's
 * differs from Ordinal's, Network has both a default and a CENTERED variant
 * for radial chart types. The hook accepts the resolved default and
 * shallow-merges user margin on top.
 */
export interface FrameMargin {
    top: number;
    right: number;
    bottom: number;
    left: number;
}
/**
 * Foreground/background graphics can be a ReactNode (rendered as-is) or a
 * function that receives the current `{ size, margin }` and returns one.
 * The function form lets users place chrome relative to the chart area.
 */
export type FrameGraphicsProp = ReactNode | ((ctx: {
    size: number[];
    margin: FrameMargin;
}) => ReactNode);
export interface UseFrameInput {
    /** Resolved size `[width, height]`. Each frame defaults its `size` prop
     *  before calling, so this is never undefined. */
    sizeProp: [number, number];
    /** Frame's `responsiveWidth` prop. */
    responsiveWidth: boolean | undefined;
    /** Frame's `responsiveHeight` prop. */
    responsiveHeight: boolean | undefined;
    /** Frame's user-supplied margin (always partial — each side optional).
     *  Matches the `margin?:` prop type on every Stream Frame. */
    userMargin: Partial<FrameMargin> | undefined;
    /** Frame's family-default margin. Shallow-merged with `userMargin`. */
    marginDefault: FrameMargin;
    /** Frame's `foregroundGraphics` prop. */
    foregroundGraphics?: FrameGraphicsProp;
    /** Frame's `backgroundGraphics` prop. */
    backgroundGraphics?: FrameGraphicsProp;
    /** Frame's `animate` prop. */
    animate?: AnimateProp;
    /** Frame's `transition` prop (legacy / explicit form). */
    transitionProp?: TransitionConfig;
    /**
     * Frame's `dirtyRef` (the flag that forces a full canvas redraw on the
     * next paint). When provided, useFrame installs a theme-change effect
     * that bumps it to `true`, clears the CSS-var cache, and queues a
     * render — the pattern that all four frames duplicated.
     *
     * Optional because this is a Tier B add-on; before the migration the
     * frames installed this themselves. The hook keeps the input optional
     * so a frame can opt in independently, but in practice all four pass
     * it.
     *
     * `dirtyRef` is owned by the frame (not the hook) because its initial
     * value differs — only `StreamXYFrame` inits to `false`; Ordinal,
     * Network, and Geo all init to `true` (load-bearing for first-paint
     * timing on those three).
     */
    themeDirtyRef?: React.MutableRefObject<boolean>;
}
export interface UseFrameResult {
    /** Reduced-motion preference at last render (for re-render gating). */
    reducedMotion: boolean;
    /** Reduced-motion ref-mirror so render closures see the latest value
     *  without depending on it. */
    reducedMotionRef: React.MutableRefObject<boolean>;
    /** Ref to attach to the responsive container. */
    responsiveRef: ReturnType<typeof useResponsiveSize>[0];
    /** Resolved size `[width, height]` accounting for `responsiveWidth/Height`. */
    size: [number, number];
    /** Effective margin (`marginDefault` ⊕ `userMargin`). */
    margin: FrameMargin;
    /** `size[0] - margin.left - margin.right`. */
    adjustedWidth: number;
    /** `size[1] - margin.top - margin.bottom`. */
    adjustedHeight: number;
    /** Resolved foreground (function-or-node, evaluated). */
    resolvedForeground: ReactNode;
    /** Resolved background (function-or-node, evaluated). */
    resolvedBackground: ReactNode;
    /** Current theme from the ThemeStore — re-renders on theme change. */
    currentTheme: SemioticTheme;
    /** Resolved transition config from `animate`/`transition` props. */
    transition: ReturnType<typeof resolveAnimateConfig>["transition"];
    /** Whether the intro animation should run on first render. */
    introEnabled: boolean;
    /** Stable id for the AccessibleDataTable region (hash-suffixed). */
    tableId: string;
    /** Token of the pending rAF, or 0 if none. */
    rafRef: React.MutableRefObject<number>;
    /** Frame assigns its render closure here. */
    renderFnRef: React.MutableRefObject<() => void>;
    /** Queue a render on the next animation frame. Coalesces. */
    scheduleRender: () => void;
    /** Frame assigns its hover handler closure here. */
    hoverHandlerRef: React.MutableRefObject<(coords: HoverPointerCoords) => void>;
    /** Frame assigns its pointer-leave closure here. */
    hoverLeaveRef: React.MutableRefObject<() => void>;
    /** Stable callback to attach to canvas's onPointerMove (or onMouseMove).
     *  Captures the coords and queues a single rAF to drain into hoverHandlerRef. */
    onPointerMove: (e: {
        clientX: number;
        clientY: number;
    }) => void;
    /** Stable callback to attach to canvas's onPointerLeave (or onMouseLeave).
     *  Cancels any pending hover rAF and invokes hoverLeaveRef. */
    onPointerLeave: () => void;
}
/**
 * Bundles the universally-shared setup boilerplate that opens every
 * Stream Frame. See `FRAME_COMPOSITION_LOG.md` for which concerns are
 * inside this hook vs. left frame-specific.
 */
export declare function useFrame(input: UseFrameInput): UseFrameResult;
