import { AnchorPlacement } from '@graphysdk/viz-engine'; import { BrandMarkVariant } from '@graphysdk/viz-engine'; import { CartesianCoordSystem } from '@graphysdk/viz-engine'; import { ColorScheme } from '@graphysdk/viz-engine'; import { Command } from '@graphysdk/viz-engine'; import { CommandStackSnapshot } from '@graphysdk/viz-engine'; import { Component } from 'react'; import { ComponentType } from 'react'; import { CoordSystem } from '@graphysdk/viz-engine'; import { CreateSpecBuilderOptions } from '@graphysdk/viz-engine'; import { CSSProperties } from 'react'; import { CustomPalettes } from '@graphysdk/viz-engine'; import { Data } from '@graphysdk/viz-engine'; import { DispatchOptions } from '@graphysdk/viz-engine'; import { Edge } from '@graphysdk/viz-engine'; import { EdgeSizes } from '@graphysdk/viz-engine'; import { EditTarget } from '@graphysdk/viz-engine'; import { ErrorInfo } from 'react'; import { FontSpec } from '@graphysdk/viz-engine'; import { FormattedAxis } from '@graphysdk/viz-engine'; import { FormattedHeadline } from '@graphysdk/viz-engine'; import { FormattedLegend } from '@graphysdk/viz-engine'; import { Geom } from '@graphysdk/viz-engine'; import { GeomName } from '@graphysdk/viz-engine'; import { GeomStyleReaders } from '@graphysdk/viz-engine'; import { GraphLayout } from '@graphysdk/viz-engine'; import { HeadlineMeasurer } from '@graphysdk/viz-engine'; import { HoverHit } from '@graphysdk/viz-engine'; import { HoverState } from '@graphysdk/viz-engine'; import { IntroStaggerOrder } from '@graphysdk/viz-engine'; import { JSX } from 'react/jsx-runtime'; import { LayerIntroPlan } from '@graphysdk/viz-engine'; import { LineType } from '@graphysdk/viz-engine'; import { Locale } from '@graphysdk/viz-engine'; import { MeasuredText } from '@graphysdk/viz-engine'; import { Observation } from '@graphysdk/viz-engine'; import { Plugin as Plugin_2 } from '@graphysdk/viz-engine'; import { PointerRegion } from '@graphysdk/viz-engine'; import { PolarCoordSystem } from '@graphysdk/viz-engine'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { Rect } from '@graphysdk/viz-engine'; import { Ref } from 'react'; import { RefObject } from 'react'; import { RenderHitTester } from '@graphysdk/viz-engine'; import { ResolvedHeadlineSize } from '@graphysdk/viz-engine'; import { ResolvedSpec } from '@graphysdk/viz-engine'; import { ScaledPositionAestheticKey } from '@graphysdk/viz-engine'; import { Scene } from '@graphysdk/viz-engine'; import { SceneLayer } from '@graphysdk/viz-engine'; import { SceneLayerFor } from '@graphysdk/viz-engine'; import { SourceContent } from '@graphysdk/viz-engine'; import { Spec } from '@graphysdk/viz-engine'; import { SpecBuilder } from '@graphysdk/viz-engine'; import { StoreApi } from 'zustand'; import { StyleReadersForLayer } from '@graphysdk/viz-engine'; import { StyleReaderTree } from '@graphysdk/viz-engine'; import { StyleResolver } from '@graphysdk/viz-engine'; import { SVGProps } from 'react'; import { TextContent } from '@graphysdk/viz-engine'; import { TextMeasurer } from '@graphysdk/viz-engine'; import { TextStyle } from '@graphysdk/viz-engine'; import { TooltipContent } from '@graphysdk/viz-engine'; import { VizDiagnostic } from '@graphysdk/viz-engine'; import { XYPoint } from '@graphysdk/viz-engine'; /** The axis identity and optional tick address spread onto a label's containing group. */ export declare type AxisEditTargetAttributes = { /** The axis family read by the editor. */ [EDIT_TARGET_KIND_ATTRIBUTE]: 'axis'; /** The position scale selected by a press on the label. */ [EDIT_TARGET_AXIS_ATTRIBUTE]: ScaledPositionAestheticKey; /** The rendered tick index used for double-click narrowing; absent for a title. */ [EDIT_TARGET_TICK_INDEX_ATTRIBUTE]?: string; }; /** * Props for the AxisLabel slot — the axis title of every axis (e.g. "Revenue"), overridable via * `slots.AxisLabel`. `labelRects` are SVG-local, keyed by edge. The tick band is a separate slot — see * `AxisTicks`. */ export declare interface AxisLabelSlotProps { formattedAxes: FormattedAxis[]; labelRects: Partial>; } /** * Props for the AxisTicks slot — the tick lines and tick labels of every axis, overridable via * `slots.AxisTicks`. `tickRects` are SVG-local, keyed by edge. The axis title is a separate slot — see * `AxisLabel`. */ export declare interface AxisTicksSlotProps { formattedAxes: FormattedAxis[]; tickRects: Partial>; } /** Made with Graphy provenance badge — capsule + glyph + system-face copy. */ export declare const BrandMark: ({ visual, placement }: BrandMarkProps) => JSX.Element; declare interface BrandMarkProps { visual: Exclude; placement: 'footer' | 'header'; } /** * How the badge paints at the current frame size: * - `full` — glyph + "Made with Graphy" pill * - `mini` — circular glyph capsule (also the under-200 px ladder step) * - `hidden` — flag off, or frame below the minimum footprint */ export declare type BrandMarkVisual = 'full' | 'mini' | 'hidden'; /** * Browser text measurer backed by OffscreenCanvas. * * Uses the same Canvas `measureText()` API that the rendering engine uses, * ensuring measurement/rendering consistency. * * **Font loading:** Use the async `create()` factory to ensure all declared * `@font-face` fonts are loaded before any measurements. This avoids * measuring against fallback fonts and caching incorrect widths. * The sync constructor is available for controlled environments where font * readiness is managed externally (e.g. backend with pre-registered fonts). * * Includes an emoji correction that compensates for the known discrepancy * where Canvas `measureText()` reports wider widths for emoji than the DOM * actually renders (Chrome/Firefox at font sizes < ~24px). The correction * is computed once per font by comparing Canvas vs DOM measurement of a * reference emoji, then cached. */ export declare class CanvasTextMeasurer implements TextMeasurer { private readonly ctx; /** * Caches the per-font emoji correction factor. */ private readonly emojiCorrections; /** * Tracks the last font string set on the context. */ private currentFont; constructor(); /** * Creates a CanvasTextMeasurer after all declared `@font-face` fonts * have finished loading. This ensures measurements use the correct font * glyphs from the first call, avoiding stale cache entries. * * Falls back to immediate construction if `document.fonts` is unavailable * (e.g. non-browser environment). * * Note: document.fonts.ready still resolves even if some fonts fail to load. */ static create(): Promise; measureText(text: string, font: FontSpec): MeasuredText; /** * Skip redundant `ctx.font` assignments * Setting the property triggers CSS font string parsing and font resolution. */ private setFont; /** * Computes the per-emoji width correction for a given font. * Measures the reference emoji in both Canvas and DOM, caches the difference. * Returns 0 if DOM is unavailable or the difference is negligible (< 0.5px). */ private getEmojiCorrection; } declare type CoordKind = CoordSystem['type']; /** Maps a coord-kind discriminator to the corresponding `CoordSystem` member. */ declare type CoordSystemFor = C extends 'cartesian' ? CartesianCoordSystem : C extends 'polar' ? PolarCoordSystem : never; /** * Ergonomic entry point for a React app: pass `plugins` once and get back a {@link GraphyKit} — the * typed builder plus a `GraphProvider` that already carries them. Pure sugar over the primitives * (`createSpecBuilder`, ``); use those directly for headless or advanced * wiring. The `const` type parameter captures the `plugins` tuple literally, so `kit.geom.` * is typed. */ export declare function createGraphyKit(options?: CreateSpecBuilderOptions

): GraphyKit

; /** * Per-chart Zustand store for what is selected. Nothing in the geom paint path reads it, so a * selection change repaints no geoms and re-runs no layout. * * `setSelection` holds the current state when the incoming selection is structurally equal to it: a * target is rebuilt from whatever was clicked rather than handed back, so only a structural check * keeps a repeated click on the same thing from notifying every subscriber. */ declare const createSelectionStore: () => StoreApi; /** * Per-chart Zustand store for the target boundary. It sits on the read-only context, beside the selection, * because the hook reading it is public and must not reach editing code; only the editor writes it. Nothing * in the geom paint path reads it. * * `setBoundary` holds the current state when the incoming boundary is structurally equal to it: a boundary is * rebuilt on every frame of a scroll, so only a structural check keeps a still chart from notifying. */ declare const createTargetBoundaryStore: () => StoreApi; /** vanilla-extract class that binds the dark token values; set it on any ancestor to flip to dark. */ export declare const darkTheme: string; /** Default paint for the footer region — caption, source line, and optional footer-anchored badge. */ export declare const DefaultFooter: ({ ref, footerRect, mode, caption, isCaptionVisible, source, isSourceVisible, captionStyle, sourceStyle, brandMark, }: FooterSlotProps) => JSX.Element | null; /** * Default paint for the grid region — per-tick grid lines, drawn inside the panel frame rect. Where a press * can take a guide, each drawn line is a stamped group holding the stroke and a transparent hit stroke * `GRID_LINE_HIT_WIDTH_PX` wide on the same coordinates. The hit stroke is solid, so a dashed line answers * along its whole length, gaps included. Of two crossing lines the one painted later answers. */ export declare const DefaultGrid: ({ axes, panelBorderSizes, panelFrameRect, panelRect }: GridSlotProps) => JSX.Element; /** Default paint for the header region — title, subtitle, and optional header-anchored badge. */ export declare const DefaultHeader: ({ ref, headerRect, mode, title, isTitleVisible, subtitle, isSubtitleVisible, headingStyle, subtitleStyle, brandMark, }: HeaderSlotProps) => JSX.Element | null; /** The built-in glyph for each {@link SwatchShape}. */ export declare const DefaultSwatch: ({ shape, color, lineType, width, height, strokeWidth, alpha, cornerRadius, }: Omit) => JSX.Element; /** * Default tooltip body. Paints the box, heading, and rows from the formatted {@link content}, and * resolves each row's swatch shape off its geom's render contract for the active coord system. * Positioning lives in the {@link Tooltip} wrapper, never here. */ export declare const DefaultTooltip: ({ content }: TooltipSlotProps) => JSX.Element; /** * Dual-target renderer binding, keyed on whether the first argument is a compile definition or a built-in * geom name: * * - **Whole new geom** — `defineGeomRenderer(definition, contract)` pairs the render contract with its * compile definition, producing a {@link GeomRendererDefinition}. Registering the result registers both * sides: the compile definition is reachable at `.definition` and the geom name is read from it, so the * two halves cannot drift. * - **Render-only override** — `defineGeomRenderer('bar', contract)` rebinds only the paint half of an * existing built-in, producing a {@link ResolvedGeomRenderer} that carries no `.definition`. The built-in * compile half keeps running (nothing re-seeds the compile registry); only the render registry changes. * The name is constrained to {@link GeomName}, so a by-name override of an unknown built-in is a * compile-time error. To restyle a *custom* geom, rebind its definition (which you hold) via the first form. */ export declare function defineGeomRenderer>(definition: Definition, contract: GeomRenderContract): GeomRendererDefinition & { readonly definition: Definition; }; export declare function defineGeomRenderer(geom: G, contract: GeomRenderContract): ResolvedGeomRenderer; /** Dev-only compile-cache inspector; render inside a ``. See {@link DevToolsPanelProps}. */ export declare const DevToolsPanel: ({ width, style, className }?: DevToolsPanelProps) => JSX.Element; /** * Dev-only panel that visualises the compile cache. Drop it inside a `` to see, in * real time, which compile stages re-ran vs. hit cache for the most recent dispatch, plus a * bounded log of recent compiles and the cumulative hit/miss counters. */ export declare interface DevToolsPanelProps { /** Panel width in pixels. Defaults to 440. */ width?: number; /** Style override merged onto the outer wrapper. */ style?: CSSProperties; /** Class applied to the outer wrapper. */ className?: string; } /** Addresses the axis a stamped node belongs to. */ declare const EDIT_TARGET_AXIS_ATTRIBUTE = "data-edit-axis"; /** Names the family painted by a node, which the shared pointer resolver reads. */ declare const EDIT_TARGET_KIND_ATTRIBUTE = "data-edit-kind"; /** Indexes the axis's rendered FormattedAxis.ticks array for double-click narrowing. */ declare const EDIT_TARGET_TICK_INDEX_ATTRIBUTE = "data-edit-tick-index"; /** Props the renderer passes to the editor layer filling the `EditorSurface` slot. */ export declare interface EditorSurfaceSlotProps { /** The frame's content box — the element the layer measures, listens on and aligns its chrome to. */ frameElement: HTMLElement; /** The panel's rect within that box, so chrome positioned from `layout` shares its origin. */ panelRect: Rect; /** The axes as the chart paints them, whose ticks a stamped tick index addresses. */ formattedAxes: readonly FormattedAxis[]; /** Whether the chart animates between states, so what the editor draws over its geoms can follow. */ shouldAnimateTransitions: boolean; } /** Round marks of one size, which the outline grows from their rim. */ export declare interface EditOutlineDots { kind: 'dots'; /** Each dot's centre, in panel pixels. */ centers: readonly XYPoint[]; /** The diameter every dot covers, its border included, in pixels. */ size: number; } /** A filled region, which the outline grows from its edge. */ export declare interface EditOutlineRegion extends MorphingEditOutlineShape { kind: 'region'; /** `'evenodd'` punches a subpath inside another out of it, as a ring's hole. */ fillRule?: 'nonzero' | 'evenodd'; } /** One shape point and edit outlines. It carries no paint: the editor draws the outline round it in its own look. */ export declare type EditOutlineShape = EditOutlineRegion | EditOutlineStroke | EditOutlineDots; /** * The input a geom's {@link GeomRenderContract.getEditOutlineShapes} receives: the observations to outline as a * layer, and what their shapes are placed and sized by. */ declare interface EditOutlineShapesInput { /** The outlined observations. */ layer: SceneLayerOf; /** The full layer `layer` was taken from — for context the subset can't see, like a stack's silhouette. */ sourceLayer: SceneLayerOf; coordSystem: CoordSystemFor; /** The panel's pixel rect. Shapes are placed in its local `0…width` / `0…height`. */ panelRect: GraphLayout['panel']; /** Cascade readers for this layer, for the sizes a shape matches: a line's width, a point's size. */ styleReaders: StyleReadersOf; /** Whether the chart animates transitions, for a shape to copy where the geom's paint springs. */ shouldAnimateTransitions: boolean; } /** A stroke, which the outline grows from either side of its thickness. */ export declare interface EditOutlineStroke extends MorphingEditOutlineShape { kind: 'stroke'; /** The thickness the stroke is drawn at, in pixels. */ width: number; } /** * Props for the Footer slot, overridable via `slots.Footer` on `GraphRenderer`. Caption editing in * `editable` mode is internal to this default — it hands off to the editor `/editable` supplies — * and an override replacing the region opts out of it. */ export declare interface FooterSlotProps { /** Forward this to the region's outer element — the layout measures the rendered DOM to reserve its space. */ ref?: React.Ref; footerRect: Rect; mode?: GraphMode; caption: TextContent | null; isCaptionVisible: boolean; source: SourceContent | null; isSourceVisible: boolean; captionStyle: TextStyle; sourceStyle: SourceStyle; /** * Resolved badge visual for footer placement. `hidden` when the mark is off, below the min * footprint, or configured for header placement. */ brandMark: BrandMarkVisual; } /** A custom geom `getEditOutlineShapes` handler's input: the observations to outline as a layer, plus `sourceLayer`. */ export declare type GeomEditOutlineShapesRendererInput = EditOutlineShapesInput; /** A custom geom `renderHoverCompanions` handler's input: the layer plus the primary and related hover hits. */ export declare type GeomHoverCompanionsRendererInput = HoverCompanionsRenderInput; /** Page-relative cursor coordinates the push-path tooltip anchors to. */ export declare interface GeomHoverCursor { clientX: number; clientY: number; } /** * Pushes a hovered observation key into the central hover, or clears this layer's hover with `null`. * A non-null key requires a `cursor` — the overlay intercepts the pointer events the cursor-follow * tooltip would otherwise read, so the anchor can only come from the geom's own handler. Consumed by * {@link InteractiveOverlayApi.pushHover} and returned by `useGeomHover`. */ export declare interface GeomHoverPush { (key: string, cursor: GeomHoverCursor): void; (key: null): void; } /** A custom geom `renderHover` handler's input: the hovered layer plus the primary/group/related hover hits. */ export declare type GeomHoverRendererInput = HoverRenderInput; /** A custom geom `getOverlayAnchor` handler's input: the layer, coord system, and the matched observation. */ export declare type GeomOverlayAnchorRendererInput = OverlayAnchorInput; /** An overlay-hosted geom's paint function — receives the guaranteed overlay wiring on `input.overlay`. */ export declare type GeomOverlayRenderFn = (input: GeomOverlayRenderInput) => ReactNode; /** * The input an overlay-hosted render (`{ fn, options: { overlay: true } }`) receives: the standard render * input plus a guaranteed {@link InteractiveOverlayApi}. The renderer always supplies it, so the geom's * render uses `overlay` unconditionally — it never decides where it is mounted, only what it paints. */ export declare interface GeomOverlayRenderInput extends GeomRenderInput { overlay: InteractiveOverlayApi; } /** * A geom's `render`: either a plain panel-SVG paint function, or an overlay-hosted one paired with * `options` — so a geom that must paint into the interactive overlay declares * `{ fn, options: { overlay: true } }` without a second render entry point. The * renderer decides where each is mounted; the geom only decides what it paints. `render` is the single * paint declaration either way. */ export declare type GeomRender = GeomRenderFn | { fn: GeomOverlayRenderFn; options: GeomRenderOptions; }; /** * The render side of a geom: everything a single `(geom, coord)` composition needs to render and * respond to hover. Generic over the geom name and coord kind, so a built-in renderer parameterised * as `GeomRenderContract<'bar', 'cartesian'>` receives param-narrowed inputs (`SceneLayerFor<'bar'>`, * `CartesianCoordSystem`), while the default `` instantiation is the base/custom * contract a plugin author writes against. The geom's name, highlight strategy, and `params` type are * NOT restated here — they are read off the compile definition this contract is bound to (see * {@link defineGeomRenderer}). This is the single declaration of a geom's render contract; the built-in * narrow form below and the base/custom form (`geom-renderer.ts`) are both instantiations of it. */ export declare interface GeomRenderContract { /** The coord system this contract paints under. A geom may bind one contract per coord. */ coord: C; swatchShape?: SwatchShape; /** * The hover-guide mode this `(geom, coord)` draws when it is the hovered layer (a * {@link HoverGuideMode}). Omit it — or contribute `null` — to draw no guide (the geom's mark is its * own highlight). A declared mode the composition can't realise draws nothing: a polar bar's `'band'` * fills a wedge, but a pie/donut (no category band) resolves to an empty one. `resolveHoverGuideMode` * reads the hovered layer's mode to pick the one guide the chart draws. */ guideMode?: HoverGuideMode | null; /** * The geom's paint. A plain function paints into the panel SVG; the `{ fn, options: { overlay: true } }` * form paints into a screen-aligned portal above the central capture layer for a live/drag-driven geom * that owns its pointer events (force-directed), with the wiring on `input.overlay`. */ render: GeomRender; /** * Optional repaint of the matched subset for the highlight overlay. Omit it and the highlight layer * falls back to {@link render}. A geom overrides it when the plain column-grouped render would * misrepresent a matched subset — a bar repaints each matched observation as an isolated stack segment * (from its compiled stack role), so a lone mid-stack match keeps its square-edged silhouette and * single-width border instead of regrouping into a standalone rounded bar. */ renderHighlight?: (input: HighlightRenderInput) => ReactNode; renderHover: (input: HoverRenderInput) => ReactNode; renderHoverCompanions: (input: HoverCompanionsRenderInput) => ReactNode; /** * Editing only: the shapes point and edit outlines for the observations in `layer`, as data in panel pixels. * A region is what they cover, one path where there are many, with rounded corners traced into it; a line is * a stroke at the width it is drawn; round marks are dots at their size. Omit it and the editor outlines each * observation's bounding box. */ getEditOutlineShapes?: (input: EditOutlineShapesInput) => readonly EditOutlineShape[]; /** * Render-side spatial query for a `'render-hit-test'` layer whose geometry is precomputed into the * scene (sankey ribbons, treemap tiles, voronoi cells). A * **factory**: given the render input it returns the per-cursor {@link RenderHitTester}; * the renderer memoizes the factory on `layer.data` and the panel pixel frame, so the read runs once * per data or panel-size change and the per-move query allocates nothing. The author writes no hook; * the renderer registers the tester on its behalf. The cursor arrives in panel-local `[0,1]` with a * top-left origin — the frame the geom paints in. Returns the declared identity key of the observation * under the cursor, or `null` for a miss. */ hitTest?: (input: GeomRenderInput) => RenderHitTester; /** Panel-space anchor for a matched observation; required when the def highlights via overlay-anchor. */ getOverlayAnchor?: (input: OverlayAnchorInput) => OverlayAnchor | null; } /** * A render contract paired with the compile definition it paints for. The engine recovers the definition * structurally from `.definition` (React-free), and the renderer reads the geom name from the same * definition — so the compile and render sides are one declaration consumed twice, never two matched by * a string. */ export declare interface GeomRendererDefinition extends ResolvedGeomRenderer { /** The compile definition this renderer paints for. Held by reference — the single source of identity. */ readonly definition: Geom; } /** A custom geom render handler's input — the base instantiation of the typed built-in inputs, including the style cascade. */ export declare type GeomRendererInput = GeomRenderInput; /** A geom's panel-SVG paint function — the plain `render` form. */ export declare type GeomRenderFn = (input: GeomRenderInput) => ReactNode; declare interface GeomRenderInput extends GeomRenderInputBase { layer: SceneLayerOf; coordSystem: CoordSystemFor; shouldAnimateTransitions: boolean; formattingLocale: Locale; intro?: LayerIntroPlan | null; /** * The panel's pixel rect — the data rectangle geoms paint into, already inset from axes and chrome. * Same frame hover and highlight receive. Width and height are the paint size; x/y are already * applied by the geom-layers SVG, so marks are placed in local `0…width` / `0…height`. */ panelRect: GraphLayout['panel']; } /** * The cascade paint context every geom render handler receives. Visual readers such as `getColor` * see the data tier only; plugin paint should read {@link GeomRenderInputBase.styleReaders} so tokens, * overrides, and the built-in default reach the mark. */ export declare interface GeomRenderInputBase { /** The provider's colour scheme — pass to `createStyleResolver` when a plugin needs readers beyond this layer. */ colorScheme: ColorScheme; /** Cascade readers for this layer: override → data → default, resolved for {@link GeomRenderInputBase.colorScheme}. */ styleReaders: GeomStyleReaders; } /** * Hosting options for an overlay render. The presence of the object form already declares overlay hosting; * `overlay: true` makes the call site read explicitly (and leaves room for further hosting options later). */ export declare interface GeomRenderOptions { /** * Mount this render's output in a screen-aligned portal above the central capture layer, rather than in * the panel SVG — for a live or drag-driven geom that must own its pointer events (force-directed). The * renderer then supplies {@link GeomOverlayRenderInput.overlay}. */ overlay: true; } /** * Chart display and interaction mode. * - 'readonly': Normal chart display with full interactivity but no editing (default) * - 'editable': Chart with inline editing capabilities for labels, titles, etc. * - 'point-and-edit': A press on the chart selects what it hit: an observation, its band, or the chart */ export declare const GRAPH_MODES: { readonly readonly: "readonly"; readonly editable: "editable"; readonly pointAndEdit: "point-and-edit"; }; /** * Animation settings for a graph. `false` disables every animation. A viewer who prefers reduced * motion gets no animation whatever this asks for. */ export declare type GraphAnimation = boolean | GraphAnimationProps; /** Per-kind animation settings. Each kind is independent: turning one off leaves the other running. */ export declare interface GraphAnimationProps { /** * Settings for the intro animation played when the chart first mounts or the chart type changes. * `false` disables it, an object overrides individual intro settings. Defaults on. */ intro?: boolean | Partial; /** Whether geoms animate to their new position when the underlying data changes. Defaults on. */ transitions?: boolean; /** * Total geom count across all layers above which the graph plays no animation, intro or * transitions. A line or area is one geom however many points it draws, so a dense live line * stays under the ceiling; turn `transitions` off for it. Defaults to 1500. */ maxAnimatedGeoms?: number; } /** Write access to the graph's spec: applying {@link Command}s and closing the runs they form. */ export declare interface GraphCommands { /** Applies a command to the provider's live spec. */ dispatch: (command: Command, options?: DispatchOptions) => void; /** * Closes a run of `{ transient: true }` dispatches and fires `onSpecChange` once for it. Call it when * the gesture ends — pointer up, blur. Forgetting only delays the notification rather than * corrupting undo: the run covers one {@link EditTarget}, and the next committed dispatch, undo, * redo or external change closes it. */ commit: () => void; } /** * The single place a chart surfaces an error in place — instead of unwinding the page to a blank * screen. Two failure modes converge here: a non-throwing **compile failure** the host passes via * {@link GraphErrorBoundaryProps.forcedErrors}, and a **render-throw** from a renderer component that * this boundary catches. Both render the same {@link GraphErrorPanel}, so there is exactly one panel * call site rather than one per failure mode. */ export declare class GraphErrorBoundary extends Component { state: GraphErrorBoundaryState; static getDerivedStateFromError(error: Error): GraphErrorBoundaryState; componentDidCatch(error: Error, info: ErrorInfo): void; componentDidUpdate(prevProps: GraphErrorBoundaryProps): void; render(): ReactNode; } declare interface GraphErrorBoundaryProps { children: ReactNode; /** * Compile failures to surface in place, rendered through the same panel as a caught render-throw * so a chart has one predictable place for its errors. */ forcedErrors?: VizDiagnostic[] | null; /** * When any key changes after a caught render-throw, the boundary clears it and * retries — so a fixed spec recovers. */ resetKeys?: readonly unknown[]; /** * Called with a single-element list when a child throws during render * (not for `forcedErrors`, which the host already reported). */ onError?: (errors: VizDiagnostic[]) => void; } declare interface GraphErrorBoundaryState { caughtDiagnostic: VizDiagnostic | null; } /** * Shared in-place fallback for a chart that failed to compile or render. Shows each diagnostic's * `code`, `message`, and `suggestion` — richer than a bare error message — so an end user can file * a useful report and a developer can see what to fix. Theme-independent: it can render before the * theme provider mounts. */ export declare const GraphErrorPanel: ({ errors }: GraphErrorPanelProps) => JSX.Element; declare interface GraphErrorPanelProps { /** The compile failure(s). The first headlines; any remaining are listed beneath it. */ errors: VizDiagnostic[]; } /** * Imperative handle on a graph, for an app's key handling, toolbar or menu bar mounted above the * tree the hooks can reach. Obtained through {@link GraphProviderProps.handleRef}. */ export declare interface GraphHandle { /** Write access to the graph's spec, the same surface {@link useGraphCommands} serves inside the tree. */ commands: GraphCommands; /** * Registers a listener fired on every change to the graph; returns the unsubscribe. With * {@link GraphHandle.getScene} it is what `useSyncExternalStore` needs, so a surface outside the * graph's tree stays in step with it. Subscribing before the graph compiles is valid. */ subscribe: (onGraphChange: () => void) => () => void; /** The graph's scene as of now, or `null` before its first successful compile. */ getScene: () => Scene | null; /** * Reverse the most recent command. Returns whether the chart took the step, so a caller driving * this from a keystroke can leave the key to the app when the chart has nothing to undo or the * older spec no longer compiles. */ undo: () => boolean; /** Re-apply the most recently undone command. Returns whether the chart took the step. */ redo: () => boolean; /** What the chart holds selected as of now; empty when nothing is. */ getSelection: () => readonly EditTarget[]; /** Replace what the chart holds selected. */ setSelection: (next: readonly EditTarget[]) => void; /** Registers a listener fired on every change to the selection; returns the unsubscribe. */ subscribeSelection: (onSelectionChange: () => void) => () => void; } /** Undo/redo controls plus the command stack's own snapshot, which a history UI reads. */ export declare type GraphHistory = CommandStackSnapshot & { /** Reverses the most recent command; returns whether the chart took the step, as {@link GraphHandle.undo}. */ undo: () => boolean; /** Re-applies the most recently undone command; returns whether the chart took the step, as {@link GraphHandle.undo}. */ redo: () => boolean; }; export declare interface GraphHistoryShortcutsOptions { /** * What to listen on. Defaults to `window`; an element — or a ref holding one — scopes the chords * to a subtree, and `null` binds nothing. */ target?: EventTarget | RefObject | null; /** Set to `false` to unbind without moving the call out of the component. Defaults to `true`. */ enabled?: boolean; } /** The mode a chart runs in, which `GraphRenderer` takes as a prop and every row of `MODE_SURFACES` is keyed by. */ export declare type GraphMode = (typeof GRAPH_MODES)[keyof typeof GRAPH_MODES]; /** * Owns the scene for a graph and exposes it via {@link useSceneSelector}, plus a * `dispatch` for applying {@link Command}s. Both failure modes — a non-throwing compile failure and a * render-throw from a renderer component — converge on a single {@link GraphErrorBoundary} that shows * the error in place, so a broken chart never blanks the page. */ export declare const GraphProvider: ({ data, spec, plugins, formattingLocale, handleRef, onSpecChange, onError, onWarnings, customPalettes, colorScheme, children, }: GraphProviderProps) => JSX.Element; /** Props for {@link GraphProvider}: the data and spec to compile, plus color scheme, locale and plugin wiring. */ export declare interface GraphProviderProps { data: Data; spec: Spec; /** * Custom geoms, stats, and transforms (and their render halves) registered for this graph. Seeds * the compiler and builds the per-provider render resolver from one array. Construction-time config, * frozen at mount — change the registered set by remounting (React `key`); `data`/`spec`/`colorScheme` * stay reactive. */ plugins?: readonly Plugin_2[]; formattingLocale?: Locale; /** * Filled with this graph's {@link GraphHandle}, for callers mounted outside the provider where the * hooks can't reach. `useGraphHistoryShortcuts` binds the undo/redo chords to one. */ handleRef?: Ref; onSpecChange?: (next: Spec) => void; /** Fires with the compile failure(s) whenever a compile/recompile/dispatch produces errors. */ onError?: (errors: VizDiagnostic[]) => void; /** Fires with any warnings a successful compile produced. */ onWarnings?: (warnings: VizDiagnostic[]) => void; colorScheme?: ColorScheme; customPalettes?: CustomPalettes; children: ReactNode; } /** * Renders the scene held by the surrounding ``. The renderer owns * layout + DOM — the provider owns the spec and derives the scene output from it. There's * no `config` prop: every consumer must wrap with `` so commands can operate * on the live spec. */ export declare const GraphRenderer: (props: GraphRendererProps) => JSX.Element; /** Props for {@link GraphRenderer}: container sizing, interaction toggles and per-region slot overrides. */ export declare interface GraphRendererProps { /** Controls how the graph responds to its container size. Defaults to filling the parent container. */ sizing?: GraphSizing; /** * Callback invoked when the graph's container is resized. Fires in every sizing mode. Reports the * container, not the panel. */ onResize?: ResizeObserverOnResize; /** * Animation settings. A boolean disables/enables animations globally, an object tunes the intro * and data transitions separately. A reduced-motion preference disables everything regardless, * and so does a chart denser than `maxAnimatedGeoms`. */ animation?: GraphAnimation; showTooltips?: boolean; mode?: GraphMode; /** Per-region component overrides. Unspecified regions render their default. */ slots?: GraphSlots; } /** Controls how the graph claims space in its container. */ export declare type GraphSizing = { mode: 'responsive'; } | { mode: 'fixed'; width: number; height: number; } | { mode: 'keepAspectRatio'; intrinsicWidth: number; intrinsicHeight: number; } | { mode: 'keepAspectRatio'; intrinsicWidth: number; aspectRatio: number; } | { mode: 'keepAspectRatio'; intrinsicHeight: number; aspectRatio: number; }; /** * Region overrides for `GraphRenderer`. A slot replaces how one region paints; the viz-engine `ResolvedSpec` * still owns whether a region exists and what data it receives, and an override gets the same * render-ready props as its default. * * Layout-safe regions (`Header`, `Footer`, `Tooltip`, `Grid`, `Swatch`, `EditorSurface`) are bare * components — DOM-measured, reserving no edge space or painting inside a box the layout already sized. * Layout-coupled regions (`AxisTicks`, `AxisLabel`, `Legend`, `Headline`) are * {@link SlotOverride}s that also declare their reserved size via `measure`, else paint and the * reserved band desync. The tick and title bands are separate slots so overriding one leaves the other * on its default. */ export declare interface GraphSlots { Header?: ComponentType; Footer?: ComponentType; Tooltip?: ComponentType; Grid?: ComponentType; Swatch?: ComponentType; /** * The chart's editor layer, mounted over the frame in `mode="editable"`. Only * `@graphysdk/react-renderer/editable` exports something that fills it, so a read-only embed bundles * no editing code. */ EditorSurface?: ComponentType; Legend?: SlotOverride number>; Headline?: SlotOverride; AxisTicks?: SlotOverride number>; AxisLabel?: SlotOverride number>; } /** * A plugin-bound authoring kit: the typed `geom`/`stat`/`transform`/`scale`/`coord` factories plus * `createSpec`/`pipe`, and a `GraphProvider` pre-bound to the same `plugins` — so what can be written * and what can render derive from one array and cannot diverge. Generic over the `plugins` tuple so * the typed per-plugin builder methods (`geom.`, …) flow through to the React entry point. */ export declare interface GraphyKit

extends SpecBuilder

{ GraphProvider: (props: Omit) => ReactElement; } /** The axis identity spread onto the group holding one grid line's stroke and its hit stroke. */ export declare type GridEditTargetAttributes = { /** The grid family read by the editor. */ [EDIT_TARGET_KIND_ATTRIBUTE]: 'grid'; /** The scale the line belongs to, kept as its own key so a secondary axis is told apart from the primary. */ [EDIT_TARGET_AXIS_ATTRIBUTE]: ScaledPositionAestheticKey; }; /** * Props for the Grid slot, overridable via `slots.Grid` on `GraphRenderer`. `panelRect` is in * SVG-local coordinates. * * A grid filling this slot spreads `stampGridEditTarget` on the group holding each line it draws, with a * hit area of its own inside that group, where `useGuidesTakePress` is true; a line it hides or moves * takes its hit area with it, and a line it does not stamp takes no press. */ export declare interface GridSlotProps { axes: FormattedAxis[]; panelBorderSizes: EdgeSizes; panelFrameRect: GraphLayout['panelFrame']; panelRect: GraphLayout['panel']; } /** * Props for the Header slot, overridable via `slots.Header` on `GraphRenderer`. Title editing in * `editable` mode is internal to this default — it hands off to the editor `/editable` supplies — * and an override replacing the region opts out of it. */ export declare interface HeaderSlotProps { /** Forward this to the region's outer element — the layout measures the rendered DOM to reserve its space. */ ref?: React.Ref; headerRect: Rect; mode?: GraphMode; title: TextContent | null; isTitleVisible: boolean; subtitle: TextContent | null; isSubtitleVisible: boolean; headingStyle: TextStyle; subtitleStyle: TextStyle; /** * Resolved badge visual for header placement. `hidden` when the mark is off, below the min * footprint, or configured for footer placement. */ brandMark: BrandMarkVisual; } /** Props for the Headline slot, overridable via `slots.Headline` on `GraphRenderer`. */ export declare interface HeadlineSlotProps { headline: FormattedHeadline; rect: Rect; resolvedSize: ResolvedHeadlineSize; /** Leading strip items to paint; the rest are hidden because they would overflow the band. */ visibleItemCount: number; /** * Whether this figure sits in the donut hole. Strip polar totals reuse the grand-total class, so * paint cannot infer the hole from CSS — only the placement input knows. */ isInDonutHole?: boolean; } /** * The input a geom's {@link GeomRenderContract.renderHighlight} receives: the matched-subset layer plus * the full source layer (context the subset can't see, like a stack's silhouette). A superset of * {@link GeomRenderInput}, so a geom that doesn't override `renderHighlight` still paints through the * plain `render`. */ declare interface HighlightRenderInput extends GeomRenderInput { /** The full layer `layer` was filtered from — for context the subset can't see, like a stack's silhouette. */ sourceLayer: SceneLayerOf; } declare interface HoverCompanionsRenderInput extends GeomRenderInputBase { layer: SceneLayerOf; primary: HoverHit; related: HoverHit[]; } /** * The shape of positional guide the `HoverGuide` draws for a hovered observation, contributed per * `(geom, coord)` renderer via `guideMode`: * * - `'band'` — a rectangle over the hovered category's band on the main axis (bars). * - `'crosshair'` — a rule at the hovered value: a straight line under cartesian, a centre-to-rim spoke * under polar (line and area). * * A renderer that omits `guideMode` draws no guide (scatter points). A declared `'band'` still draws * nothing where the composition has no category band — a pie/donut resolves to an empty wedge. The chart * draws the guide of whichever layer the cursor resolves to, so a combo shows a band over a hovered bar * and a crosshair over a hovered line; see `resolveHoverGuideMode`. */ declare type HoverGuideMode = 'crosshair' | 'band'; /** * Hosts the hover store + engine for the surrounding ``. Subscribes only to the * `layers` and `coordSystem` slices of the scene — the engine never reads anything else, * so unrelated stage outputs (scales, guides, summarize, visual mapper) cannot trigger a rebuild. */ export declare const HoverProvider: ({ children }: HoverProviderProps) => JSX.Element; declare interface HoverProviderProps { children: ReactNode; } declare interface HoverRenderInput extends GeomRenderInputBase { layer: SceneLayerOf; coordSystem: CoordSystemFor; primary: HoverHit; group: HoverHit[]; related: HoverHit[]; panelRect: GraphLayout['panel']; } declare interface HoverSlice { hover: HoverState; /** * Box the tooltip anchors against while the pointer is over a pinned anchor, in client * coordinates. `null` during normal cursor hover, when the tooltip follows the cursor. */ tooltipAnchor: TooltipAnchor | null; /** * Chrome hit regions the tracker tests before the geom hit-test, highest priority first. Whoever * paints over the plot publishes its area here so hover detection stays in one pointer pipeline. */ pointerRegions: readonly PointerRegion[]; /** A gesture owns the pointer: the tracker runs no query, so nothing recomputes behind it. */ isPointerSuspended: boolean; /** * An editing surface makes the one query a frame and writes the hover itself: the tracker keeps the * viewport and runs no query, so a chart with no such surface mounted keeps its own. */ isQueryOwnedByEditor: boolean; } declare interface HoverStoreActions { setHoverState: (next: HoverState) => void; setTooltipAnchor: (next: TooltipAnchor | null) => void; /** * Replaces one publisher's regions. Keying by publisher lets several features hold regions at once * without clobbering each other; an empty list retracts the publisher entirely. */ publishPointerRegions: (publisher: string, regions: readonly PointerRegion[]) => void; setPointerSuspended: (next: boolean) => void; setQueryOwnedByEditor: (next: boolean) => void; } /** State of the hover store: the current {@link HoverState} plus its setter. */ declare type HoverStoreState = HoverSlice & HoverStoreActions; /** * The overlay wiring handed to an overlay-hosted render via {@link GeomOverlayRenderInput.overlay}. The * geom writes only its simulation, marks, and drag handlers; the renderer owns the on-screen rect * measurement, the portal alignment, and the push wiring. */ export declare interface InteractiveOverlayApi { /** Feeds the hovered observation's identity key into the unified hover store — the push path. */ pushHover: GeomHoverPush; /** * The panel's on-screen rect in client pixels, so the overlay can place its marks. Distinct from * {@link GeomRenderInput.panelRect} (layout pixels). */ panelRect: ScreenRect; } declare interface IntroAnimationOptions { /** Whether the entrance plays at all */ enabled: boolean; /** Multiplier applied to every entrance duration and stagger delay. */ durationScale: number; /** Whether geoms that support staggered entrance (bars) enter staggered rather than all at once. */ stagger: boolean; /** The order staggered point geoms enter in. Bars and slices always enter in visual order. */ staggerOrder: IntroStaggerOrder; } /** Which of the chart's drawn legends a pill belongs to. */ declare const LEGEND_INDEX_ATTRIBUTE = "data-legend-index"; /** Which item of that legend the pill paints. */ declare const LEGEND_ITEM_INDEX_ATTRIBUTE = "data-legend-item-index"; /** The legend identity and item address spread onto a pill. */ export declare type LegendEditTargetAttributes = LegendItemAttributes & { /** The legend family read by the editor. */ [EDIT_TARGET_KIND_ATTRIBUTE]: 'legend'; }; /** Where the item a pill paints sits in the chart's drawn legends. */ export declare interface LegendItemAddress { /** Counts `formattedLegends`, which `formatLegends` maps one to one from `guides.legends.drawn`. */ legendIndex: number; /** Counts that legend's items, in the order it lists them. */ itemIndex: number; } /** The inert attributes a pill carries, spread onto the element it already renders. */ declare type LegendItemAttributes = { /** The drawn legend index read by the editor. */ [LEGEND_INDEX_ATTRIBUTE]: string; /** The item index within the drawn legend read by the editor. */ [LEGEND_ITEM_INDEX_ATTRIBUTE]: string; }; /** * Props for the Legend slot, overridable via `slots.Legend` on `GraphRenderer`. * * A legend filling this slot spreads `stampLegendEditTarget` on every pill and direct label it paints where * `useGuidesTakePress` is true, and lets it take the pointer, or a press there selects the chart: the press * reads the legend and the item it stands for off those attributes. */ export declare interface LegendSlotProps { formattedLegends: FormattedLegend[]; rects: Partial>; } /** Scales the color's HSL lightness up by `amount` (0–1). */ export declare const lightenCss: (colorString: string, amount: number) => string; /** vanilla-extract class that binds the light token values; the default theme. */ export declare const lightTheme: string; declare interface MorphingEditOutlineShape { /** SVG path data in panel pixels. */ pathData: string; /** Identifies the shape across renders, such as a line's group, so a morph starts from where it was. */ key?: string; /** Whether a change of shape morphs to the new one, as the geom's paint does. Snaps when omitted. */ shouldAnimateTransitions?: boolean; } /** * Anchor point in normalized [0,1] coord-space where a highlight overlay marker * should be painted for one observation. Renderer turns [0,1] into pixels. */ export declare interface OverlayAnchor { x: number; y: number; } declare interface OverlayAnchorInput { layer: SceneLayerOf; coordSystem: CoordSystemFor; observation: Observation; } /** * Drops the selected targets `spec` no longer holds, and hands back the same list when it holds all * of them — a selection that survived a command must not churn its subscribers. * * Validated against the spec rather than compiled output: the compiler silently drops annotations it * cannot place, and a target whose annotation failed to resolve has to stay selected for the user to * be able to repair it. */ export declare const pruneSelection: (selection: readonly EditTarget[], spec: ResolvedSpec) => readonly EditTarget[]; export { RenderHitTester } /** Fires on each deduped size change — the shape of `GraphRenderer`'s `onResize` callback. */ export declare type ResizeObserverOnResize = (state: ResizeObserverState) => void; /** The observed element's content-box size in CSS pixels, rounded to integers. */ export declare interface ResizeObserverState { width: number; height: number; /** True until the first ResizeObserver measurement lands. */ isDefault: boolean; } /** Frame-size ladder: hidden below 120×80, mini below 200 wide (or when variant is mini). */ export declare const resolveBrandMarkVisual: (enabled: boolean, frameSize: { width: number; height: number; }, variant?: BrandMarkVariant) => BrandMarkVisual; /** * A render contract with its resolved geom name attached — the shape the per-provider resolver returns * and every render site consumes. Both a built-in `GeomRenderer` and a custom {@link GeomRendererDefinition} * conform to it, so the consumers paint built-ins and customs through one type. */ export declare interface ResolvedGeomRenderer extends GeomRenderContract { /** The geom name this renderer paints — the resolver dispatches on it. */ geom: string; } /** * The compiled layer a renderer's handlers receive. A built-in renderer keyed to a `GeomName` gets * its param-narrowed `SceneLayerFor`; a custom renderer (`G = string`) is downstream of * serialisation, never sees the plugins array, and reads the base {@link SceneLayer} dynamically. */ declare type SceneLayerOf = G extends GeomName ? SceneLayerFor : SceneLayer; /** An element's on-screen rect in client coordinates — what a fixed-position overlay aligns to. */ export declare interface ScreenRect { left: number; top: number; width: number; height: number; } declare interface SelectionSlice { /** * The {@link EditTarget}s the graph holds selected. A list even though nothing selects more than * one target: widening it later would break the handle, the panel contract and every consumer at * once. */ selection: readonly EditTarget[]; } /** The vanilla zustand store `GraphProvider` holds; consumers read it via `useGraphSelection`. */ export declare type SelectionStore = ReturnType; declare interface SelectionStoreActions { setSelection: (next: readonly EditTarget[]) => void; clearSelection: () => void; } /** State of the selection store: what the graph holds selected plus the actions replacing it. */ export declare type SelectionStoreState = SelectionSlice & SelectionStoreActions; /** * Passed as the second argument to a layout-coupled slot's `measure`, so it can size its band from * real text metrics — the same Canvas-backed measurer the built-in measurers use — rather than * constructing its own. A `measure` whose size is unrelated to text can ignore it. */ export declare interface SlotMeasureContext { /** Measures a string at a given font; returns `{ width, height, ascent, descent }` in CSS pixels. */ measureText: TextMeasurer['measureText']; /** Active text-scale multiplier; multiply an em size by this to get the pixel size to measure at. */ textScale: number; } /** * A layout-coupled slot: the region's `render` paired with the `measure` the layout uses to reserve * its space. `measure` mirrors the matching `LayoutMeasurer` method, so paint and reserved space can't * disagree. Give it a stable reference — a `measure` whose identity changes each render takes effect on * the next paint but doesn't retrigger layout. */ export declare interface SlotOverride { /** The component that paints the region. */ render: ComponentType; /** * Returns the region's reserved size. Receives the region's formatted data plus a * {@link SlotMeasureContext} (`measureText`, `textScale`) for sizing from real text metrics. */ measure: Measure; } /** The source line's type: the label and the URL. A bare source entry never paints the link. */ declare interface SourceStyle { label: TextStyle; link: TextStyle; } /** * Identifies an axis label and its rendered tick; omitting the tick index identifies an axis title. The * index is the tick's place in `FormattedAxis.ticks` as the layout handed them, which a double click reads * the tick back from, so a slot drawing only some of the ticks still stamps each with its index in the full * array. */ export declare const stampAxisEditTarget: (scaleAestheticKey: ScaledPositionAestheticKey, tickIndex?: number) => AxisEditTargetAttributes; /** Identifies one drawn grid line of a scale, on the group holding its stroke and its hit stroke. */ export declare const stampGridEditTarget: (scaleAestheticKey: ScaledPositionAestheticKey) => GridEditTargetAttributes; /** Identifies a legend pill and the compiled item its label represents. */ export declare const stampLegendEditTarget: (address: LegendItemAddress) => LegendEditTargetAttributes; /** * The style readers a handler that cannot call `useStyleReaders` receives: a built-in geom's own, whose * builtin-backed properties resolve NonNullable, and the shared readers for a custom geom. */ declare type StyleReadersOf = G extends GeomName ? StyleReadersForLayer> : GeomStyleReaders; /** * The vocabulary of legend/tooltip/headline marks the {@link Swatch} can paint. A geom picks the one * that best evokes its on-canvas mark via `swatchShape` on its render contract (see * {@link GeomRenderContract}); it is a render concern, so the engine never resolves it. * * - `square` — a filled rect (bars) * - `line` — a horizontal stroke (lines) * - `area` — a filled region with a stroke accent (areas) * - `circle` — a filled dot (points) * - `slice` — a pie / donut wedge (polar bars) */ export declare type SwatchShape = 'square' | 'line' | 'circle' | 'area' | 'slice'; /** * Props for the Swatch slot (`slots.Swatch` on `GraphRenderer`). An override must paint inside the * `width` × `height` box it receives. * * Switch on `shape`, `surface` or `label` and delegate the rest to * {@link DefaultSwatch}. */ export declare interface SwatchSlotProps { shape: SwatchShape; color: string; surface: SwatchSurface; label?: string; lineType?: LineType; width?: number; height?: number; /** Line/area stroke width. Absent, {@link DefaultSwatch} draws at 2. */ strokeWidth?: number; /** Owning layer `alpha`. Omit so {@link DefaultSwatch} keeps today's opacities. */ alpha?: number; /** Square corner radius in px. Omit so {@link DefaultSwatch} keeps `rx={2}`. */ cornerRadius?: number; } /** The UI surface a swatch is painted on. Lets a Swatch slot restyle one surface and delegate the rest. */ export declare type SwatchSurface = 'legend' | 'tooltip' | 'headline' | 'callout' | 'rule-label'; /** The target boundary: the one box round the selected target, which a menu is placed beside. */ export declare interface TargetBoundary { /** The box in pixels from the chart frame's top left, at the chart's own layout scale. */ frame: Rect; /** The same box on screen, in client pixels, which a host places a menu of its own against. */ client: Rect; } declare interface TargetBoundarySlice { /** `null` while nothing is selected, or where the chart draws nothing for what is. */ boundary: TargetBoundary | null; } /** The vanilla zustand store `GraphProvider` holds; hosts read it via `useTargetBoundary`. */ export declare type TargetBoundaryStore = ReturnType; declare interface TargetBoundaryStoreActions { setBoundary: (next: TargetBoundary | null) => void; } /** State of the target boundary store: the boundary the editor last measured plus the action replacing it. */ export declare type TargetBoundaryStoreState = TargetBoundarySlice & TargetBoundaryStoreActions; /** * Creates a font-ready, cached text measurer and shares it with descendants via context. * Renders nothing until the measurer resolves, so consumers reading the context always * see a non-null value, and never longer than {@link FONT_READY_DEADLINE_MS}. * * The measurer is recreated when additional fonts finish loading (e.g. in iframes where * `document.fonts.ready` resolves before stylesheets inject their `@font-face` rules). * The new instance gets a fresh cache so stale measurements from fallback fonts are * discarded. * * Falls back to `HeuristicTextMeasurer` when `OffscreenCanvas` is unavailable. */ export declare const TextMeasurerProvider: ({ children, measurer: override }: TextMeasurerProviderProps) => JSX.Element | null; declare interface TextMeasurerProviderProps { children: ReactNode; /** * Optional override. Production callers omit this and the provider creates its own * font-ready measurer. Tests pass a synchronous measurer (e.g. `HeuristicTextMeasurer`) * to bypass the font-loading round-trip. */ measurer?: TextMeasurer; } /** The name of a single theme token. */ export declare type ThemeKey = keyof ThemeValues; /** * A partial set of token values layered over a base theme — the shape of leftover chrome * overrides. Every token takes its CSS string value. */ export declare type ThemeOverrides = Partial; /** Resolves the base theme into token values and publishes them to the subtree. */ export declare const ThemeProvider: ({ colorScheme, textScale, graphBackground, graphFontFamily, headingFontFamily, children, }: ThemeProviderProps) => JSX.Element; declare interface ThemeProviderProps { colorScheme: ColorScheme; /** The chart's text scale, from `style.graph({ textScale })`. Omit it where there is no chart, as an editing panel does. */ textScale?: number; /** The chart's resolved background. Omit it where there is no chart; the theme token then stands. */ graphBackground?: string; /** * The stylesheet's `style.graph({ fontFamily })`, written into the `fontFamily` token so * token-painted text (tooltips, headline, content, legend) follows it too. Omit it when * undeclared; the token keeps the built-in family. */ graphFontFamily?: string; /** * The stylesheet's resolved heading family (`style.heading.h1`, falling back to a bare * `style.heading` then `style.graph`), written into the `fontFamilyHeading` token the heading * shorthands compose. Omit it when undeclared; the token keeps the built-in family. */ headingFontFamily?: string; children: ReactNode; } /** Every theme token mapped to its resolved CSS string value. */ export declare type ThemeValues = Record; /** * Where a pinned callout asks the tooltip to anchor: the marker point in client coordinates, plus * the direction the mini sits, so the tooltip expands over the mini the way it was placed. */ declare interface TooltipAnchor { x: number; y: number; placement: AnchorPlacement; /** * Annotation the anchor belongs to, so the tooltip can resolve a comment's text by id. Absent when * a geom overlay anchors to the cursor instead. */ annotationId?: string; } /** Props for the Tooltip slot, overridable via `slots.Tooltip` on `GraphRenderer`. Positioning stays built in. */ export declare interface TooltipSlotProps { /** Render-ready tooltip body, already formatted by the viz-engine runtime. */ content: TooltipContent; } /** A unit-space rectangle (`[0, 1]²`, top-left origin) that {@link UnitBoxSvg} occupies. */ export declare interface UnitBox { x0: number; y0: number; x1: number; y1: number; } /** * A nested SVG over a unit-space box, placed in panel percentages, with no viewBox. Children live in the * box's own unscaled space (`50%` is the centre, a pixel radius is a pixel) and are clipped by the viewport. */ export declare const UnitBoxSvg: ({ box, children }: { box: UnitBox; children: ReactNode; }) => ReactNode; /** * A nested SVG that establishes a `[0, 1]` unit coordinate space (top-left origin) stretched to fill * the geom panel. A layout geom paints its geometry in raw unit coords so paint and hit-test never re-project against each * other. `preserveAspectRatio="none"` maps the unit square onto the (usually non-square) panel exactly. * Circles and glyphs stretch here — put them in {@link UnitBoxSvg}. */ export declare const UnitSpaceSvg: ({ children, ...rest }: UnitSpaceSvgProps) => ReactNode; declare interface UnitSpaceSvgProps extends Omit, 'viewBox' | 'preserveAspectRatio'> { children: ReactNode; } /** * Tracks an element's on-screen rect, so that a fixed-position overlay can sit exactly over it in pixel * space. `screenRect` is `null` until the first measurement lands, and drops back to `null` whenever the * element collapses to nothing. * * The element's own size changes go through the shared {@link useResizeObserver} lifecycle; this hook adds * the screen-position concerns the observer can't see — viewport scroll/resize move the element's screen * position without resizing it. Every trigger is coalesced into at most one `getBoundingClientRect` per * animation frame, so a burst of scroll events forces a single reflow rather than one per event. Only a * changed rect updates state, so a settled overlay does not re-render every frame. */ export declare function useElementScreenRect(): { measureRef: (node: T | null) => void; screenRect: ScreenRect | null; }; /** * Registers a layout geom's render-side hit tester so a `'render-hit-test'` layer inherits central hover * and the built-in tooltip — the path `bar` takes — with no pointer overlay of its own. The pull path. * * The cursor passed to the tester is panel-local `[0, 1]`, top-left origin — the frame the geom paints in. */ export declare function useGeomHitTest(layerId: string, tester: RenderHitTester): void; /** * The push half of the render-hit-test keystone, for a geom whose geometry keeps changing after it is * drawn (a live simulation) and so owns its own pointer surface above the central capture layer. The * geom's pointer handlers call the returned setter with the hovered observation's `identityKey`; the * engine resolves it through the same `byKey` lookup the pull path uses, so the geom inherits the tooltip * and `renderHover`. Since the overlay intercepts the pointer events, the tooltip is anchored at the * supplied cursor. Pass `null` to clear. Geoms with geometry fixed once drawn use `useGeomHitTest`. * * Escape hatch: an interactive geom should instead declare an overlay-hosted `render` * (`{ fn, options: { overlay: true } }`), which the renderer portals into a screen-aligned overlay and * hands a ready `pushHover` via `input.overlay`. Reach for this hook only when that form is not enough. */ export declare function useGeomHover(layerId: string): GeomHoverPush; /** The resolver's `geom` subtree, one object per resolver, so the selector never re-renders on a chrome change. */ export declare const useGeomReaderTree: () => StyleReaderTree["geom"]; /** * Returns the graph's command controls. * * @example * ```tsx * const { dispatch, commit } = useGraphCommands(); * * const handleChange = (event: React.ChangeEvent) => { * const rule = style.graph({ cornerRadius: event.target.valueAsNumber }); * dispatch(new SetStyleRuleCommand({ list: 'defaults', rule, id: 'frame-radius' }), { transient: true }); * }; * * const handlePointerUp = () => commit(); * * * ``` */ export declare const useGraphCommands: () => GraphCommands; /** * The graph a surface edits: the handle it was given, or one synthesized from the `` * it sits inside. An explicit handle wins, so a surface nested inside one chart can still edit * another. Returns `null` for a surface that is neither. * * A host writing its own editing UI needs this and nothing else from us, which is why it sits here * rather than beside the panel: reaching a chart is not itself an editing concern. */ export declare const useGraphHandle: (handle?: GraphHandle) => GraphHandle | null; /** * Subscribes to the graph's undo history. Every command that reaches the chart — a renderer's own * inline edit, a host panel's dispatch, an agent's streamed command — is undoable through it. * * @example * ```tsx * const { undo, canUndo, undoDescription } = useGraphHistory(); * * ``` */ export declare const useGraphHistory: () => GraphHistory; /** * Binds ⌘/Ctrl+Z, ⌘/Ctrl+Shift+Z and Ctrl+Y to a graph's undo history for as long as the calling * component is mounted, driving the {@link GraphHandle} a `` fills. * * Going through the ref rather than the context means it can be called from wherever the app's key * handling lives — typically above the provider, out of reach of the hooks. * * @example * ```tsx * const EditableChart = () => { * const handleRef = useRef(null); * useGraphHistoryShortcuts(handleRef); * * return ( * * * * ); * }; * ``` * * A chord the app or an inline editor already handled is left alone, as is one typed into a text * control and one the chart declines — nothing to step, or an older spec the loaded data can no * longer render. An app-level undo sharing the page keeps those. */ export declare const useGraphHistoryShortcuts: (handleRef: RefObject, options?: GraphHistoryShortcutsOptions) => void; /** * Subscribes to what the graph holds selected, from inside a ``. The store is * per-chart and shared with {@link GraphHandle}, so a surface outside the tree and one inside it * always agree on what is selected. A surface outside the tree writes through the handle's * `setSelection`; the canvas overlay writes to the same store off the context. * * @example * ```tsx * const selection = useGraphSelection(); * const selected = selection.length === 1 ? selection[0] : null; * ``` */ export declare const useGraphSelection: () => readonly EditTarget[]; /** * Whether a press in the chart's mode takes a guide. A guide renderer, the default or a slot, reads it to * give its stamped nodes a hit area and the pointer only where a press on them selects the guide. */ export declare const useGuidesTakePress: () => boolean; /** * The graph's scene, re-read whenever the graph changes, or `null` before its first * successful compile. * * Returns the whole scene: `useSyncExternalStore` compares snapshots by reference, so a selector * building a fresh object per call would re-render forever. Derive slices at the call site. */ export declare const useHandleScene: (handle: GraphHandle) => Scene | null; /** * Subscribe to a slice of the hover state from inside a `HoverProvider`. */ export declare function useHoverState(selector: (state: HoverStoreState) => T): T; /** Memoizes a module-level style read. Pass the read function, then the arguments it needs. */ export declare const useResolvedStyle: (read: (...args: TArgs) => TResult, ...args: TArgs) => TResult; /** * Subscribes to a derived slice of the scene. The subscription only fires when the * selector's result changes by reference, so combined with the compiler's per-stage memoization * this skips re-renders whenever the selected slice is unchanged. * * @example * ```ts * const layers = useSceneSelector((scene) => scene.layers); * const xAxis = useSceneSelector((scene) => scene.guides.axes[0]); * ``` */ export declare const useSceneSelector: (selector: (scene: Scene) => Selected) => Selected; /** * Style readers for a layer, resolving paint through the stylesheet cascade. Takes either a base layer * or a highlight's filtered sub-layer. A known geom kind gets back its own readers, whose * builtin-backed properties resolve NonNullable. * * Reads the tree's `geom` subtree, which the resolver shares across every chrome, so a chrome-only * recompile does not re-render callers. * * Plugin paint can also read the same cascade from `input.styleReaders` on the geom render contract. */ export declare const useStyleReaders: (layer: L) => StyleReadersForLayer; /** * Nested chart style tree from the provider resolver. Subscribes to `scene.chrome`, so a chrome * recompile re-renders callers. {@link useStyleReaders} does not, which is why this is a separate hook. */ export declare const useStyleReaderTree: () => StyleReaderTree; /** The chart's stylesheet resolver. One instance per provider, rebuilt when the colour scheme flips. */ export declare const useStyleResolver: () => StyleResolver; /** * Subscribes to the target boundary, from inside a ``: the one box round what is selected, * which a host places a menu of its own beside. The editor measures it when the selection, the scene or the * frame's size changes, and moves its `client` box with the page. `null` while nothing is selected, where the * chart draws nothing for what is, and on a chart no editor is mounted on. * * @example * ```tsx * const boundary = useTargetBoundary(); * if (boundary === null) return null; * return ; * ``` */ export declare const useTargetBoundary: () => TargetBoundary | null; /** Returns the {@link TextMeasurer} from context; throws outside a ``. */ export declare const useTextMeasurer: () => TextMeasurer; /** CSS custom-property references for every theme token; read at paint sites as `vars.textPrimary`, etc. */ export declare const vars: { white: `var(--${string})`; black: `var(--${string})`; transparent: `var(--${string})`; gray100: `var(--${string})`; gray95: `var(--${string})`; gray90: `var(--${string})`; gray85: `var(--${string})`; gray80: `var(--${string})`; gray75: `var(--${string})`; gray70: `var(--${string})`; gray60: `var(--${string})`; gray50: `var(--${string})`; gray0: `var(--${string})`; grayGradient80: `var(--${string})`; green60: `var(--${string})`; green50: `var(--${string})`; red60: `var(--${string})`; red50: `var(--${string})`; amber70: `var(--${string})`; amber50: `var(--${string})`; amber40: `var(--${string})`; amber30: `var(--${string})`; blue80: `var(--${string})`; blue60: `var(--${string})`; purple50: `var(--${string})`; purple30: `var(--${string})`; brand: `var(--${string})`; success: `var(--${string})`; warning: `var(--${string})`; alert: `var(--${string})`; textPrimary: `var(--${string})`; textSecondary: `var(--${string})`; textDisabled: `var(--${string})`; iconPrimary: `var(--${string})`; iconSecondary: `var(--${string})`; iconStickerBackground: `var(--${string})`; border100: `var(--${string})`; border50: `var(--${string})`; border10: `var(--${string})`; sunkenBackground: `var(--${string})`; defaultBackground: `var(--${string})`; raisedBackground: `var(--${string})`; overlayBackground: `var(--${string})`; overlayBorderGradient: `var(--${string})`; graphBackground: `var(--${string})`; legendFocusOutlineColor: `var(--${string})`; annotationOutlineColor: `var(--${string})`; editMenuTriggerIconColor: `var(--${string})`; tooltipRowGap: `var(--${string})`; editorControlHeight: `var(--${string})`; legendSwatchGap: `var(--${string})`; headlineRowGap: `var(--${string})`; canvasDefault: `var(--${string})`; canvasBlue: `var(--${string})`; canvasCyan: `var(--${string})`; canvasGreen: `var(--${string})`; canvasYellow: `var(--${string})`; canvasOrange: `var(--${string})`; canvasRed: `var(--${string})`; canvasPink: `var(--${string})`; canvasPurple: `var(--${string})`; canvasGray: `var(--${string})`; canvasInverse: `var(--${string})`; elevationXs: `var(--${string})`; elevationSm: `var(--${string})`; elevationMd: `var(--${string})`; elevationLg: `var(--${string})`; radiiXs: `var(--${string})`; radiiSm: `var(--${string})`; radiiMd: `var(--${string})`; radiiLg: `var(--${string})`; spaceXxs: `var(--${string})`; spaceXs: `var(--${string})`; spaceSm: `var(--${string})`; spaceMd: `var(--${string})`; spaceLg: `var(--${string})`; spaceXl: `var(--${string})`; zIndexToolbar: `var(--${string})`; zIndexToolbarTooltip: `var(--${string})`; zIndexToolbarPopover: `var(--${string})`; zIndexEditorPopover: `var(--${string})`; toolbarBackgroundColor: `var(--${string})`; toolbarButtonBackgroundColor: `var(--${string})`; toolbarButtonBackgroundColorHovered: `var(--${string})`; toolbarButtonBackgroundColorSelected: `var(--${string})`; toolbarSeparatorColor: `var(--${string})`; fontFamily: `var(--${string})`; fontFamilyHeading: `var(--${string})`; fontWeightRegular: `var(--${string})`; fontWeightMedium: `var(--${string})`; fontWeightSemibold: `var(--${string})`; fontWeightBold: `var(--${string})`; fontWeightExtraBold: `var(--${string})`; textScale: `var(--${string})`; fontSizeXxs: `var(--${string})`; fontSizeXs: `var(--${string})`; fontSizeSm: `var(--${string})`; fontSizeMd: `var(--${string})`; fontSizeLg: `var(--${string})`; fontSizeXl: `var(--${string})`; fontLineHeightXxs: `var(--${string})`; fontLineHeightXs: `var(--${string})`; fontLineHeightSm: `var(--${string})`; fontLineHeightMd: `var(--${string})`; fontLineHeightLg: `var(--${string})`; fontLineHeightXl: `var(--${string})`; fontSizeEditorBody: `var(--${string})`; fontSizeHeadingSm: `var(--${string})`; fontSizeHeadingMd: `var(--${string})`; fontSizeHeadingLg: `var(--${string})`; fontLineHeightEditorBody: `var(--${string})`; fontLineHeightHeadingSm: `var(--${string})`; fontLineHeightHeadingMd: `var(--${string})`; fontLineHeightHeadingLg: `var(--${string})`; fontButton: `var(--${string})`; fontInput: `var(--${string})`; fontInputLabel: `var(--${string})`; fontSelectLabel: `var(--${string})`; fontSelectDescription: `var(--${string})`; fontColorSelectLabel: `var(--${string})`; fontMenuTitle: `var(--${string})`; fontMenuGroupTitle: `var(--${string})`; fontMenuItemLabel: `var(--${string})`; fontMenuItemLabelSecondary: `var(--${string})`; fontUITooltip: `var(--${string})`; fontUITooltipSecondary: `var(--${string})`; fontErrorBoundaryTitle: `var(--${string})`; fontErrorBoundaryMessage: `var(--${string})`; fontTableCell: `var(--${string})`; fontTableHeaderCell: `var(--${string})`; fontSourceLabel: `var(--${string})`; fontSourceLink: `var(--${string})`; fontTextEditorH1: `var(--${string})`; fontTextEditorH2: `var(--${string})`; fontTextEditorH3: `var(--${string})`; fontTextEditorH6: `var(--${string})`; fontTextEditorBody: `var(--${string})`; fontTextEditorLink: `var(--${string})`; fontHighlightModeTitle: `var(--${string})`; fontHighlightModeSubtitle: `var(--${string})`; fontEditorControlLabel: `var(--${string})`; fontEditorControlValue: `var(--${string})`; fontEditorSectionTitle: `var(--${string})`; fontEditorCaption: `var(--${string})`; }; export { VizDiagnostic } export { }