import type { PillCSSPlacement, TipPoint } from "../geometry/stickPositioning"; /** * Pure geometry snapshot consumed by the per-frame interpolators. Any time * the underlying layout changes (size tier, stick angle, label content), the * caller computes a fresh `StickFrameGeometry` and the next animation frame * naturally reflects it. */ export type StickFrameGeometry = Readonly<{ /** Tip position in anchor-relative coordinates (anchor = origin). */ tip: TipPoint; /** CSS placement for the surface's expanded (pill-at-tip) state. */ pillCSS: PillCSSPlacement; /** * Half-extents of the SVG that draws the line/dot. The SVG sits centered on * the anchor; its internal origin is `(svgHalfExtentX, svgHalfExtentY)`, * which is also the anchor in the SVG's own coordinate space. */ svgHalfExtentX: number; svgHalfExtentY: number; /** Visible circle diameter in collapsed/circle form. */ circleDiameterPx: number; /** Outer pill height — also the diameter of the cap circle. */ pillHeightPx: number; /** Stick anchor dot radius in pixels. */ dotRadiusPx: number; }>; export type SurfacePlacement = Readonly<{ /** Constant pixel `left` for the surface (top-left of the pill envelope at t=1). */ leftPx: number; /** Constant pixel `top` for the surface (top-left of the pill envelope at t=1). */ topPx: number; /** Animated transform components, ready to write into `style.transform`. */ translateXPct: number; translateXPx: number; translateYPx: number; }>; export type LineEndpoint = Readonly<{ x2: number; y2: number; }>; export type DotAppearance = Readonly<{ opacity: number; scale: number; }>; /** * The constant pixel `left`/`top` for the surface — these never change during * the animation. The outer container is anchor-zero (positioned exactly at * the geographic anchor), so the surface's `left`/`top` are simply the * pill's anchor-relative placement (`pillCSS`) with no extra offset adapter. */ export declare const computeSurfaceFixedOrigin: (geometry: StickFrameGeometry) => { leftPx: number; topPx: number; }; /** * Interpolates surface transform between the resting circle-at-anchor pose * and the expanded pill-at-tip pose. * * - At `t = 0`: the visible circle sits centered on the anchor. Implemented * by translating the surface's top-left back from its expanded `left`/`top` * so the circle of diameter `circleDiameterPx` aligns with the anchor. * - At `t = 1`: the surface is at its expanded pose with `pillCSS.translateXPct` * placing the appropriate pill cap at the tip. */ export declare const interpolateSurfacePlacement: (t: number, geometry: StickFrameGeometry) => SurfacePlacement; /** * Format a transform string in the same three-function shape used previously. * Centralized so the spring loop and React renders agree byte-for-byte. */ export declare const formatSurfaceTransform: (placement: SurfacePlacement) => string; /** * Interpolates the SVG line endpoint between the anchor (zero-length line) and * the tip. Coordinates are in the SVG's own coordinate space — the SVG's * internal origin `(svgHalfExtentX, svgHalfExtentY)` is the anchor, so the tip * lands at `(svgHalfExtentX + tip.x, svgHalfExtentY + tip.y)` at `t=1`. */ export declare const interpolateLineEndpoint: (t: number, geometry: StickFrameGeometry) => LineEndpoint; /** * Interpolates the anchor dot's opacity and scale. Linear blend keeps the dot * visually tied to the same progress value as the surface and line. */ export declare const interpolateDot: (t: number) => DotAppearance;