@graphysdk/react-renderer 0.0.1-experimental.8 → 0.0.1-plugins.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react/jsx-runtime"),u=require("react"),g=require("react-dom"),i=require("./tooltip-body-B4Mj-oru.cjs"),v=require("@graphysdk/viz-engine");function m(e,t){return{type:e.type,zOrder:t.zOrder,draw:t.draw}}const w=2147483646;function p(){const e=u.useRef(null),[t,o]=u.useState(null),n=u.useCallback(()=>{const r=e.current;if(!r)return;const l=r.getBoundingClientRect(),c={left:l.left,top:l.top,width:l.width,height:l.height};o(a=>a&&b(a,c)?a:c)},[]),s=u.useCallback(r=>{e.current=r},[]);return u.useLayoutEffect(()=>{if(!e.current)return;n();const r=new ResizeObserver(n);return r.observe(e.current),window.addEventListener("resize",n),window.addEventListener("scroll",n,!0),()=>{r.disconnect(),window.removeEventListener("resize",n),window.removeEventListener("scroll",n,!0)}},[n]),{ref:s,rect:t}}function R({rect:e,children:t}){return g.createPortal(d.jsx("div",{style:{position:"fixed",left:e.left,top:e.top,width:e.width,height:e.height,pointerEvents:"none",zIndex:w,overflow:"visible"},children:t}),document.body)}function b(e,t){return e.left===t.left&&e.top===t.top&&e.width===t.width&&e.height===t.height}function*P(e,t){for(const o of e)yield{kind:o[t],observation:o}}function x(e,t,o,n){return e>=o&&t>=n}const S=({children:e,style:t,...o})=>d.jsx("svg",{width:"100%",height:"100%",viewBox:"0 0 1 1",preserveAspectRatio:"none",...o,style:{overflow:"visible",...t},children:e});function y(){return u.useMemo(()=>{const e=v.DEFAULT_COLOR_PALETTE;return t=>e[t%e.length]??e[0]??"#000000"},[])}function E(e,t){const{hitTesterRegistry:o}=i.useHoverContext(),n=u.useRef(t);n.current=t,u.useLayoutEffect(()=>{const s=r=>n.current(r);return o.set(e,s),()=>{o.delete(e)}},[o,e])}function C(e){const{engine:t,store:o,setCursor:n}=i.useHoverContext();return u.useCallback((s,r)=>{if(s===null){o.getState().setHoverState(v.RESTING_HOVER_STATE),n(null);return}o.getState().setHoverState(t.hoverByKey(e,s)),r&&n(r)},[t,o,n,e])}function h(e,t,o){const n=f(e),s=f(t),r=(l,c)=>Math.round(l+(c-l)*o);return`rgb(${r(n.red,s.red)}, ${r(n.green,s.green)}, ${r(n.blue,s.blue)})`}function T(e,t){return h(e,"#ffffff",t)}function f(e){const t=e.replace("#","");return{red:Number.parseInt(t.slice(0,2),16),green:Number.parseInt(t.slice(2,4),16),blue:Number.parseInt(t.slice(4,6),16)}}exports.CompanionDot=i.CompanionDot;exports.PrimaryDot=i.PrimaryDot;exports.Swatch=i.Swatch;exports.TooltipBody=i.TooltipBody;exports.TooltipRowView=i.TooltipRowView;exports.defineGeomPlugin=i.defineGeomPlugin;exports.defineGeomRenderer=i.defineGeomRenderer;exports.emToPx=i.emToPx;exports.toPercent=i.toPercent;exports.toViewBoxX=i.toViewBoxX;exports.toViewBoxY=i.toViewBoxY;exports.useSvgPathMorph=i.useSvgPathMorph;exports.vars=i.vars;exports.PanelOverlayPortal=R;exports.UnitSpaceSvg=S;exports.defineAnnotationRenderer=m;exports.fitsLabel=x;exports.lighten=T;exports.mixColor=h;exports.partitionByKind=P;exports.useCategoricalColor=y;exports.useGeomHitTest=E;exports.useGeomHover=C;exports.usePanelScreenRect=p;
@@ -0,0 +1,635 @@
1
+ import { AnimationPlaybackOptions } from 'motion/react';
2
+ import { AnnotationDef } from '@graphysdk/viz-engine/extensions';
3
+ import { AnnotationZOrder } from '@graphysdk/viz-engine';
4
+ import { CartesianCoordSystem } from '@graphysdk/viz-engine';
5
+ import { CompiledLayerFor } from '@graphysdk/viz-engine';
6
+ import { CoordSystem } from '@graphysdk/viz-engine';
7
+ import { Geom } from '@graphysdk/viz-engine/extensions';
8
+ import { GeomIdentity } from '@graphysdk/viz-engine';
9
+ import { GeomName } from '@graphysdk/viz-engine';
10
+ import { GraphLayout } from '@graphysdk/viz-engine';
11
+ import { HighlightStrategy } from '@graphysdk/viz-engine';
12
+ import { HoverHit } from '@graphysdk/viz-engine';
13
+ import { JSX } from 'react/jsx-runtime';
14
+ import { LineStyleType } from '@graphysdk/viz-engine';
15
+ import { Locale } from '@graphysdk/viz-engine';
16
+ import { MotionValue } from 'motion/react';
17
+ import { Observation } from '@graphysdk/viz-engine';
18
+ import { PanelHitTester } from '@graphysdk/viz-engine';
19
+ import { PolarCoordSystem } from '@graphysdk/viz-engine';
20
+ import { ReactNode } from 'react';
21
+ import { RefCallback } from 'react';
22
+ import { ResolvedTarget } from '@graphysdk/viz-engine';
23
+ import { SVGProps } from 'react';
24
+ import { SwatchShape } from '@graphysdk/viz-engine';
25
+ import { TooltipContent } from '@graphysdk/viz-engine';
26
+ import { TooltipRow } from '@graphysdk/viz-engine';
27
+
28
+ /**
29
+ * The drawing surface a custom annotation paints into (ADR-035): a panel-positioned [0,1] frame.
30
+ * `targets` are the resolved coordinates in **top-left [0,1]**; `area` carries the panel's pixel size
31
+ * for the cases [0,1] cannot express (text extents, fixed-length leaders); `params` is the kind's typed
32
+ * params. The draw function returns static nodes — annotations have no hover or tooltip.
33
+ */
34
+ export declare interface AnnotationDrawInput<TParams extends object = object> {
35
+ targets: readonly ResolvedTarget[];
36
+ area: {
37
+ width: number;
38
+ height: number;
39
+ };
40
+ params: TParams;
41
+ }
42
+
43
+ /**
44
+ * A custom annotation's render half. `type` resolves it for a compiled annotation; `zOrder` is the
45
+ * kind's default slot (background paints before geoms, foreground after) — overridable per instance;
46
+ * `draw` is a React render function that may reuse the render kit (theme tokens, `toPercent`, value
47
+ * readers) but never participates in hover.
48
+ */
49
+ export declare interface AnnotationPlugin {
50
+ type: string;
51
+ zOrder: AnnotationZOrder;
52
+ draw: (input: AnnotationDrawInput) => ReactNode;
53
+ }
54
+
55
+ /** The render half an author supplies to {@link defineAnnotationRenderer} — everything but `type`. */
56
+ declare interface AnnotationRenderHalf<TParams extends object> {
57
+ zOrder: AnnotationZOrder;
58
+ draw: (input: AnnotationDrawInput<TParams>) => ReactNode;
59
+ }
60
+
61
+ export { AnnotationZOrder }
62
+
63
+ /**
64
+ * Hover-overlay dot drawn at a non-primary hit's `(x, y)`: a single circle at reduced opacity
65
+ * so it reads as secondary. Used for any companion hit — same-layer sibling (e.g. another
66
+ * series at the primary X) or cross-layer related.
67
+ */
68
+ export declare const CompanionDot: ({ hit }: CompanionDotProps) => JSX.Element;
69
+
70
+ declare interface CompanionDotProps {
71
+ hit: HoverHit;
72
+ }
73
+
74
+ export declare type CoordKind = CoordSystem['type'];
75
+
76
+ /** Maps a coord-kind discriminator to the corresponding `CoordSystem` member. */
77
+ declare type CoordSystemFor<C extends CoordKind> = C extends 'cartesian' ? CartesianCoordSystem : C extends 'polar' ? PolarCoordSystem : never;
78
+
79
+ /**
80
+ * Binds a custom annotation's render half to its imported compile-half {@link AnnotationDef}: the kind
81
+ * name (`def.type`) and the params type (`def.defaultParams`) are read from `def`, so the half never
82
+ * re-declares them and cannot disagree with the definition — the construction-level handshake mirroring
83
+ * `defineGeomRenderer`. `draw` receives the resolved targets with `params` typed from the def.
84
+ */
85
+ export declare function defineAnnotationRenderer<TParams extends object>(def: AnnotationDef<TParams>, half: AnnotationRenderHalf<TParams>): AnnotationPlugin;
86
+
87
+ /**
88
+ * Type-narrowing constructor for a plugin. Each plugin file declares its `(geom, coord)` pair and its
89
+ * `highlightStrategy` inline; TypeScript infers `G`/`C`/`S` from the object literal — handlers then
90
+ * receive `CompiledLayerFor<G>` / `CoordSystemFor<C>` with no `as` casts. Whether `getOverlayAnchor` is
91
+ * required follows from the declared `highlightStrategy` via {@link GeomPluginForStrategy}. A custom geom
92
+ * supplies its params type `TParams` (e.g. by annotating `render`'s input) to type `layer.params`.
93
+ *
94
+ * Returns the broad `GeomPlugin` type (with the type parameters erased) so all plugins fit into one
95
+ * registry. The cast inside this helper is safe because the registry routes every call to the plugin
96
+ * keyed by `(geom, coord)`.
97
+ */
98
+ export declare function defineGeomPlugin<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams = PluginParams<G>>(plugin: GeomPluginForStrategy<G, C, S, TParams>): GeomPlugin;
99
+
100
+ /**
101
+ * Binds a geom's render half to its imported compile-half {@link Geom} definition: the geom name
102
+ * (`def.type`), the highlight strategy (`def.highlightStrategy`), and the params type
103
+ * (`def.defaultParams`) are all read from `def`, so the half never re-declares them and cannot disagree
104
+ * with the definition — the construction-level handshake. Whether `getOverlayAnchor` is required follows
105
+ * from the def's declared `highlightStrategy`, and `render`/`renderHover` receive `layer.params` typed
106
+ * from the def with no annotation. Built-in plugins keep {@link defineGeomPlugin}; reach for this only to
107
+ * pair a custom geom's two halves.
108
+ *
109
+ * Returns the broad {@link GeomPlugin} (type parameters erased) so every plugin fits one registry; the
110
+ * cast is the same variance bypass {@link defineGeomPlugin} performs, safe because the registry routes
111
+ * each call by `(geom, coord)`.
112
+ */
113
+ export declare function defineGeomRenderer<Def extends Geom, C extends CoordKind>(def: Def, half: GeomRenderHalf<Def, C>): GeomPlugin;
114
+
115
+ export declare const emToPx: (em: number, textScale: number) => number;
116
+
117
+ /**
118
+ * Whether a region is large enough to carry a label: both dimensions must clear their minimum. Works in
119
+ * any single consistent space — pass unit dimensions with unit thresholds, or pixels with pixel
120
+ * thresholds. A space-filling geom (treemap) culls labels with it so a tile too small to fit text stays
121
+ * unlabelled rather than overflowing.
122
+ */
123
+ export declare function fitsLabel(width: number, height: number, minWidth: number, minHeight: number): boolean;
124
+
125
+ /** A geom's declared highlight composition strategy, or `null` when it opts out of highlighting. */
126
+ declare type GeomHighlightStrategy = HighlightStrategy | null;
127
+
128
+ /**
129
+ * Self-contained module owning everything a single `(geom, coord)` composition needs to paint
130
+ * and respond to hover. Plugins are dispatched via the registry keyed on `(geom, coord)` —
131
+ * the registry guarantees the input shapes match the plugin's identity.
132
+ *
133
+ * Generic by default: a plugin parameterised as `GeomPlugin<'bar', 'cartesian'>` declares
134
+ * narrow input types so its handlers receive `CompiledLayerFor<'bar'>` /
135
+ * `CartesianCoordSystem` directly, no runtime checks. Use {@link defineGeomPlugin} to build
136
+ * one — the helper centralizes the variance cast so individual plugin files stay free of
137
+ * `as` assertions.
138
+ *
139
+ * The public shape is a flat `NoOverlayAnchor | OverlayAnchor` union so call sites can
140
+ * invoke `plugin.render(...)` against `CompiledLayerFor<GeomIdentity>` without each call site
141
+ * having to discriminate. Per-plugin enforcement of `getOverlayAnchor` happens at the
142
+ * {@link defineGeomPlugin} boundary via {@link GeomPluginForStrategy}, keyed on the plugin's own
143
+ * declared `highlightStrategy` — so a custom geom is gated by what it declares, not a name lookup.
144
+ */
145
+ export declare type GeomPlugin<G extends string = GeomIdentity, C extends CoordKind = CoordKind> = NoOverlayAnchorGeomPlugin<G, C, GeomHighlightStrategy, PluginParams<G>> | OverlayAnchorGeomPlugin<G, C, GeomHighlightStrategy, PluginParams<G>>;
146
+
147
+ declare interface GeomPluginBase<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams> {
148
+ geom: G;
149
+ coord: C;
150
+ /**
151
+ * The geom's highlight composition strategy — the same value its compile-half declares. Drives the
152
+ * `getOverlayAnchor` requirement at the {@link defineGeomPlugin} boundary, so the render contract is
153
+ * derived from a declared strategy rather than a closed geom-name lookup.
154
+ */
155
+ highlightStrategy: S;
156
+ guideMode: HoverGuideMode | null;
157
+ render: (input: GeomRenderInput<G, C, TParams>) => ReactNode;
158
+ renderHover: (input: HoverRenderInput<G, C, TParams>) => ReactNode;
159
+ renderHoverCompanions: (input: HoverCompanionsRenderInput<G, TParams>) => ReactNode;
160
+ /**
161
+ * Optional: paints the tooltip body when one of this geom's observations is the primary hit. The
162
+ * renderer keeps the positioned, themed card and calls this for its contents only; returning `null`
163
+ * falls through to the default body. The input carries the engine-built {@link TooltipContent} (feed
164
+ * it to `TooltipBody` to reproduce the default) and the raw `primary.observation`.
165
+ */
166
+ renderTooltip?: (input: TooltipRenderInput<G, C, TParams>) => ReactNode;
167
+ }
168
+
169
+ /**
170
+ * Picks the plugin shape required for a plugin's own declared `highlightStrategy`. Only the
171
+ * `'overlay-anchor'` strategy demands the anchor reader; `'observation-rerender'` and `null` (no
172
+ * highlight) both resolve to {@link NoOverlayAnchorGeomPlugin}.
173
+ *
174
+ * Used by {@link defineGeomPlugin} to enforce the strategy→shape coupling at plugin-definition
175
+ * sites — `observation-rerender` plugins cannot declare `getOverlayAnchor`, `overlay-anchor` ones must
176
+ * — for any geom name, built-in or custom, with no closed geom-name lookup.
177
+ */
178
+ declare type GeomPluginForStrategy<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams> = S extends 'overlay-anchor' ? OverlayAnchorGeomPlugin<G, C, S, TParams> : NoOverlayAnchorGeomPlugin<G, C, S, TParams>;
179
+
180
+ /**
181
+ * The render half an author supplies to {@link defineGeomRenderer}: every field of a plugin except the
182
+ * two its imported compile-half definition already declares — `geom` and `highlightStrategy`.
183
+ * `getOverlayAnchor` is gated on the def's declared strategy via {@link GeomPluginForStrategy}, so the
184
+ * render contract is bound to the definition rather than re-declared.
185
+ */
186
+ declare type GeomRenderHalf<Def extends Geom, C extends CoordKind> = Omit<GeomPluginForStrategy<Def['type'] & string, C, Def['highlightStrategy'], Def['defaultParams']>, 'geom' | 'highlightStrategy'>;
187
+
188
+ export declare interface GeomRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
189
+ layer: CompiledLayerFor<G, TParams>;
190
+ coordSystem: CoordSystemFor<C>;
191
+ isAnimated: boolean;
192
+ formattingLocale: Locale;
193
+ }
194
+
195
+ export declare interface HoverCompanionsRenderInput<G extends string = GeomName, TParams = PluginParams<G>> {
196
+ layer: CompiledLayerFor<G, TParams>;
197
+ primary: HoverHit;
198
+ related: HoverHit[];
199
+ }
200
+
201
+ export declare type HoverGuideMode = 'continuous' | 'bar';
202
+
203
+ export declare interface HoverRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
204
+ layer: CompiledLayerFor<G, TParams>;
205
+ coordSystem: CoordSystemFor<C>;
206
+ primary: HoverHit;
207
+ group: HoverHit[];
208
+ related: HoverHit[];
209
+ panelRect: GraphLayout['panel'];
210
+ }
211
+
212
+ /** Lightens a hex colour by mixing it toward white by `amount` (`0` keeps the colour, `1` is white). */
213
+ export declare function lighten(hex: string, amount: number): string;
214
+
215
+ /**
216
+ * Mixes a hex colour toward another by `amount` in `[0, 1]` (`0` keeps `hex`, `1` returns `towardHex`),
217
+ * channel-wise in sRGB. Returns an `rgb(...)` string. Used for within-group shading where leaves share a
218
+ * group hue and vary only in lightness.
219
+ */
220
+ export declare function mixColor(hex: string, towardHex: string, amount: number): string;
221
+
222
+ /**
223
+ * Plugin shape for geoms that don't compute an overlay anchor — either `'observation-rerender'`
224
+ * geoms (matched rows re-render in place) or geoms that opt out of highlighting entirely
225
+ * (`null` strategy). The renderer never asks these plugins for an anchor, so the property is forbidden.
226
+ */
227
+ declare interface NoOverlayAnchorGeomPlugin<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams> extends GeomPluginBase<G, C, S, TParams> {
228
+ getOverlayAnchor?: never;
229
+ }
230
+
231
+ /**
232
+ * Anchor point in normalized [0,1] coord-space where a highlight overlay marker
233
+ * should be painted for one observation. Renderer turns [0,1] into pixels.
234
+ */
235
+ export declare interface OverlayAnchor {
236
+ x: number;
237
+ y: number;
238
+ }
239
+
240
+ declare interface OverlayAnchorGeomPlugin<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams> extends GeomPluginBase<G, C, S, TParams> {
241
+ /** Returns the panel-space anchor for a matched observation. */
242
+ getOverlayAnchor: (input: OverlayAnchorInput<G, C, TParams>) => OverlayAnchor | null;
243
+ }
244
+
245
+ export declare interface OverlayAnchorInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
246
+ layer: CompiledLayerFor<G, TParams>;
247
+ coordSystem: CoordSystemFor<C>;
248
+ observation: Observation;
249
+ }
250
+
251
+ export { PanelHitTester }
252
+
253
+ /**
254
+ * Portals an interactive overlay to `document.body`, fixed over the given panel rect at the documented
255
+ * top `z-index`. Owns only the placement and chrome; the simulation canvas it wraps paints inside. Sized
256
+ * to the rect with `pointerEvents: 'none'` so gaps fall through to the chart — the overlay's own marks
257
+ * re-enable pointer events to capture drags.
258
+ */
259
+ export declare function PanelOverlayPortal({ rect, children }: {
260
+ rect: PanelScreenRect;
261
+ children: ReactNode;
262
+ }): ReactNode;
263
+
264
+ /** The panel's on-screen rectangle in page-relative pixels — the frame a portalled overlay aligns to. */
265
+ export declare interface PanelScreenRect {
266
+ left: number;
267
+ top: number;
268
+ width: number;
269
+ height: number;
270
+ }
271
+
272
+ /**
273
+ * Walks a kind-tagged Tier-C dataset (the output of `createMarkTable`), yielding each observation paired
274
+ * with its discriminant `kind`. The render half switches on `kind` to build its per-kind marks, instead
275
+ * of re-reading the kind column inline in every plugin. `Kind` narrows the discriminant to the geom's own
276
+ * union (e.g. `'node' | 'link'`) for an exhaustive switch.
277
+ */
278
+ export declare function partitionByKind<Kind extends string = string>(data: Iterable<Observation>, kindColumn: string): Generator<{
279
+ kind: Kind;
280
+ observation: Observation;
281
+ }>;
282
+
283
+ /** The compiled-layer params a plugin's handlers see — built-ins default from the geom name; a custom geom supplies its own. */
284
+ declare type PluginParams<G extends string> = CompiledLayerFor<G>['params'];
285
+
286
+ /**
287
+ * Hover-overlay dot drawn at the primary hit's `(x, y)`: colored disc with a thicker white
288
+ * border and an outer white ring offset by a 1px gap. Radius is data-driven so bubble charts
289
+ * whose size channel carries data don't distort under hover.
290
+ */
291
+ export declare const PrimaryDot: ({ hit, ...rest }: PrimaryDotProps) => JSX.Element;
292
+
293
+ declare interface PrimaryDotProps {
294
+ hit: HoverHit;
295
+ 'data-testid'?: string;
296
+ }
297
+
298
+ export { ResolvedTarget }
299
+
300
+ /**
301
+ * Shared shape glyph used by both the tooltip and the legend.
302
+ */
303
+ export declare const Swatch: ({ shape, color, lineType, width, height, }: SwatchProps) => JSX.Element;
304
+
305
+ declare interface SwatchProps {
306
+ shape: SwatchShape;
307
+ color: string;
308
+ lineType?: LineStyleType;
309
+ width?: number;
310
+ height?: number;
311
+ }
312
+
313
+ /**
314
+ * The default tooltip body — the optional header and one row per hovered observation, with the
315
+ * in-place primary-row highlight. Presentational and engine-decoupled: it renders a
316
+ * {@link TooltipContent} and nothing else, so the built-in `Tooltip` and a custom geom's
317
+ * `renderTooltip` paint the same rows. The positioned, themed card around it stays the renderer's.
318
+ */
319
+ export declare const TooltipBody: ({ content }: TooltipBodyProps) => JSX.Element;
320
+
321
+ declare interface TooltipBodyProps {
322
+ content: TooltipContent;
323
+ }
324
+
325
+ /** Page-relative cursor position the tooltip anchors to. `null` when the pointer is outside the chart. */
326
+ export declare interface TooltipCursor {
327
+ clientX: number;
328
+ clientY: number;
329
+ }
330
+
331
+ /**
332
+ * Input a plugin's {@link GeomPluginBase.renderTooltip} receives when one of its observations is the
333
+ * primary hit. `content` is the body the built-in tooltip would render — feed it to `TooltipBody` to
334
+ * reproduce the default — while `primary.observation` carries the geom's own columns for a bespoke
335
+ * layout. The card around the body (positioning, theme) stays the renderer's.
336
+ */
337
+ export declare interface TooltipRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
338
+ content: TooltipContent;
339
+ layer: CompiledLayerFor<G, TParams>;
340
+ coordSystem: CoordSystemFor<C>;
341
+ primary: HoverHit;
342
+ group: HoverHit[];
343
+ related: ReadonlyMap<string, HoverHit[]>;
344
+ }
345
+
346
+ /**
347
+ * One tooltip row — swatch, label, value, with the optional in-place highlight. Exposed so a custom
348
+ * geom's `renderTooltip` can map `content.rows` itself and interleave its own content between rows,
349
+ * rather than rendering the whole {@link TooltipBody} as an opaque block.
350
+ */
351
+ export declare const TooltipRowView: ({ row, shouldHighlight }: TooltipRowViewProps) => JSX.Element;
352
+
353
+ declare interface TooltipRowViewProps {
354
+ row: TooltipRow;
355
+ shouldHighlight: boolean;
356
+ }
357
+
358
+ export declare const toPercent: (value: number) => string;
359
+
360
+ /**
361
+ * Converts a normalized [0,1] x-coordinate to viewBox coordinate (identity transform).
362
+ * Used inside nested SVGs with viewBox="0 0 1 1".
363
+ */
364
+ export declare function toViewBoxX(normalized: number): number;
365
+
366
+ /**
367
+ * Converts a normalized [0,1] y-coordinate to viewBox coordinate (Y-inverted).
368
+ * SVG y=0 is at the top, but data y=0 is at the bottom, so we invert.
369
+ * Used inside nested SVGs with viewBox="0 0 1 1".
370
+ */
371
+ export declare function toViewBoxY(normalized: number): number;
372
+
373
+ /**
374
+ * An `<svg>` preset for painting Tier-C geometry in panel `[0,1]` unit space: `viewBox="0 0 1 1"`,
375
+ * `preserveAspectRatio="none"` (so unit coordinates stretch to fill the panel exactly, the way a bar
376
+ * chart's bars do), and `overflow: visible`.
377
+ *
378
+ * Chrome gotcha (documented once here, so geoms don't rediscover it): with a sub-unit `viewBox`, native
379
+ * SVG fill hit-testing is unreliable at this scale — which is why Tier-C geoms answer a numeric
380
+ * `useGeomHitTest` query instead of relying on pointer events landing on these shapes. Paint here; hit-test
381
+ * through the engine.
382
+ */
383
+ export declare const UnitSpaceSvg: ({ children, style, ...rest }: SVGProps<SVGSVGElement>) => ReactNode;
384
+
385
+ /**
386
+ * Returns an `index → colour` resolver over the chart's default categorical palette — the same
387
+ * `DEFAULT_COLOR_PALETTE` the compiler bakes into a colour-encoded layer — so a custom geom that
388
+ * assigns its own colour indices draws from the chart's palette instead of inventing a private one.
389
+ * Colours therefore match what a sibling layer's colour scale would produce, and follow the engine's
390
+ * palette rather than a hardcoded array.
391
+ *
392
+ * Out of scope (ADR-034 open question #4): declaring a colour *aesthetic* with its own scale + legend,
393
+ * or honouring a per-spec custom palette. This primitive only ensures the colours match the default.
394
+ */
395
+ export declare function useCategoricalColor(): (index: number) => string;
396
+
397
+ /**
398
+ * Registers a Tier-C geom's render-side hit-test for its layer, so the central hover engine routes
399
+ * the cursor to it — the geom inherits the built-in hover, tooltip, and (in time) accessibility
400
+ * instead of hand-rolling a pointer overlay. The geom declares `spatialKind: 'render-hit-test'`; this
401
+ * hook supplies the matching closure.
402
+ *
403
+ * The `tester` receives the cursor in panel `[0, 1]` with a top-left origin (the frame the geom
404
+ * paints in) and returns the declared identity key of the observation under it, or `null`. It may
405
+ * close over freshly computed geometry each render — a stable wrapper reads the latest through a ref,
406
+ * so the registration effect runs once per layer rather than every render.
407
+ */
408
+ export declare function useGeomHitTest(layerId: string, tester: PanelHitTester): void;
409
+
410
+ /**
411
+ * The push counterpart to `useGeomHitTest`, for a Tier-C geom that owns its own pointer surface — a
412
+ * live simulation whose interactive overlay intercepts pointer events before the central capture
413
+ * layer sees them, so the engine cannot pull a hit. The geom already knows which observation is under
414
+ * the cursor and pushes its declared identity key; the engine resolves it to the same unified
415
+ * `HoverState` the pull path produces, and the cursor is forwarded so the central tooltip tracks.
416
+ *
417
+ * Returns a stable `setHovered(key, cursor?)`: a key with the page-relative cursor opens the tooltip
418
+ * on that observation; `null` clears it.
419
+ */
420
+ export declare function useGeomHover(layerId: string): (key: string | null, cursor?: TooltipCursor) => void;
421
+
422
+ /**
423
+ * Tracks the on-screen rect of the element the returned `ref` is attached to, across container resize and
424
+ * page scroll. Only a live-simulation geom needs this (ADR-034 decision 4): it paints and hit-tests
425
+ * render-side every frame, so its interactive overlay must sit above the chart in pixel space. Every other
426
+ * Tier-C geom routes hover through the engine (decision 2) and never tracks a screen rect.
427
+ */
428
+ export declare function usePanelScreenRect(): {
429
+ ref: RefCallback<Element>;
430
+ rect: PanelScreenRect | null;
431
+ };
432
+
433
+ /**
434
+ * Animates SVG path transitions using `d3-interpolate-path` for smooth morphing
435
+ * when data points are added or removed (Framer Motion doesn't support this natively).
436
+ *
437
+ * Based on: https://github.com/framer/motion/issues/451#issuecomment-761302824
438
+ */
439
+ export declare const useSvgPathMorph: (pathDefinition: string, config: AnimationPlaybackOptions) => MotionValue<string>;
440
+
441
+ export declare const vars: {
442
+ white: `var(--${string})`;
443
+ black: `var(--${string})`;
444
+ transparent: `var(--${string})`;
445
+ grey100: `var(--${string})`;
446
+ grey95: `var(--${string})`;
447
+ grey90: `var(--${string})`;
448
+ grey85: `var(--${string})`;
449
+ grey80: `var(--${string})`;
450
+ grey75: `var(--${string})`;
451
+ grey70: `var(--${string})`;
452
+ grey60: `var(--${string})`;
453
+ grey50: `var(--${string})`;
454
+ grey0: `var(--${string})`;
455
+ greyGradient80: `var(--${string})`;
456
+ green60: `var(--${string})`;
457
+ green50: `var(--${string})`;
458
+ red60: `var(--${string})`;
459
+ red50: `var(--${string})`;
460
+ amber70: `var(--${string})`;
461
+ amber50: `var(--${string})`;
462
+ amber40: `var(--${string})`;
463
+ amber30: `var(--${string})`;
464
+ blue80: `var(--${string})`;
465
+ blue60: `var(--${string})`;
466
+ purple50: `var(--${string})`;
467
+ purple30: `var(--${string})`;
468
+ brand: `var(--${string})`;
469
+ success: `var(--${string})`;
470
+ warning: `var(--${string})`;
471
+ alert: `var(--${string})`;
472
+ textPrimary: `var(--${string})`;
473
+ textSecondary: `var(--${string})`;
474
+ textDisabled: `var(--${string})`;
475
+ iconPrimary: `var(--${string})`;
476
+ iconSecondary: `var(--${string})`;
477
+ iconStickerBackground: `var(--${string})`;
478
+ border100: `var(--${string})`;
479
+ border50: `var(--${string})`;
480
+ border10: `var(--${string})`;
481
+ sunkenBackground: `var(--${string})`;
482
+ defaultBackground: `var(--${string})`;
483
+ raisedBackground: `var(--${string})`;
484
+ overlayBackground: `var(--${string})`;
485
+ overlayBorderGradient: `var(--${string})`;
486
+ graphBackground: `var(--${string})`;
487
+ gridLineColor: `var(--${string})`;
488
+ originLineColor: `var(--${string})`;
489
+ targetLineColor: `var(--${string})`;
490
+ targetLineMarkerColor: `var(--${string})`;
491
+ targetLineLabelTextColor: `var(--${string})`;
492
+ legendBackground: `var(--${string})`;
493
+ legendBorderColor: `var(--${string})`;
494
+ legendFocusOutlineColor: `var(--${string})`;
495
+ legendTextColor: `var(--${string})`;
496
+ dimmedSeriesLabelTextColor: `var(--${string})`;
497
+ dimmedSeriesLabelLineColor: `var(--${string})`;
498
+ trendNegativeColor: `var(--${string})`;
499
+ trendPositiveColor: `var(--${string})`;
500
+ trendNeutralColor: `var(--${string})`;
501
+ defaultAnnotationArrowStroke: `var(--${string})`;
502
+ defaultAnnotationShapeStroke: `var(--${string})`;
503
+ defaultAnnotationShapeFill: `var(--${string})`;
504
+ arrowAnnotationStickerOutlineColor: `var(--${string})`;
505
+ arrowAnnotationStickerOutlineColorInverse: `var(--${string})`;
506
+ annotationFrameBorderColor: `var(--${string})`;
507
+ annotationMenuTriggerIconColor: `var(--${string})`;
508
+ heatmapEmptyTileBackground: `var(--${string})`;
509
+ dataLabelOutsideBackground: `var(--${string})`;
510
+ canvasDefault: `var(--${string})`;
511
+ canvasBlue: `var(--${string})`;
512
+ canvasCyan: `var(--${string})`;
513
+ canvasGreen: `var(--${string})`;
514
+ canvasYellow: `var(--${string})`;
515
+ canvasOrange: `var(--${string})`;
516
+ canvasRed: `var(--${string})`;
517
+ canvasPink: `var(--${string})`;
518
+ canvasPurple: `var(--${string})`;
519
+ canvasGray: `var(--${string})`;
520
+ canvasInverse: `var(--${string})`;
521
+ elevationXs: `var(--${string})`;
522
+ elevationSm: `var(--${string})`;
523
+ elevationMd: `var(--${string})`;
524
+ elevationLg: `var(--${string})`;
525
+ radiiXs: `var(--${string})`;
526
+ radiiSm: `var(--${string})`;
527
+ radiiMd: `var(--${string})`;
528
+ radiiLg: `var(--${string})`;
529
+ spaceXxs: `var(--${string})`;
530
+ spaceXs: `var(--${string})`;
531
+ spaceSm: `var(--${string})`;
532
+ spaceMd: `var(--${string})`;
533
+ spaceLg: `var(--${string})`;
534
+ spaceXl: `var(--${string})`;
535
+ zIndexToolbar: `var(--${string})`;
536
+ zIndexToolbarTooltip: `var(--${string})`;
537
+ zIndexToolbarPopover: `var(--${string})`;
538
+ toolbarBackgroundColor: `var(--${string})`;
539
+ toolbarButtonBackgroundColor: `var(--${string})`;
540
+ toolbarButtonBackgroundColorHovered: `var(--${string})`;
541
+ toolbarButtonBackgroundColorSelected: `var(--${string})`;
542
+ toolbarSeparatorColor: `var(--${string})`;
543
+ tooltipBackground: `var(--${string})`;
544
+ tooltipBorderColor: `var(--${string})`;
545
+ tooltipHeadingTextColor: `var(--${string})`;
546
+ tooltipLabelTextColor: `var(--${string})`;
547
+ tooltipValueTextColor: `var(--${string})`;
548
+ tooltipPrimaryRowColor: `var(--${string})`;
549
+ hoverGuideLineColor: `var(--${string})`;
550
+ hoverGuideFillColor: `var(--${string})`;
551
+ hoveredBarBorderColor: `var(--${string})`;
552
+ hoveredPointRingColor: `var(--${string})`;
553
+ pointStrokeColor: `var(--${string})`;
554
+ stackedBarHoverBorderColor: `var(--${string})`;
555
+ fontFamilyDefault: `var(--${string})`;
556
+ fontFamilyHeading: `var(--${string})`;
557
+ fontWeightRegular: `var(--${string})`;
558
+ fontWeightMedium: `var(--${string})`;
559
+ fontWeightSemibold: `var(--${string})`;
560
+ fontWeightBold: `var(--${string})`;
561
+ fontWeightExtraBold: `var(--${string})`;
562
+ fontWeightBlack: `var(--${string})`;
563
+ textScale: `var(--${string})`;
564
+ fontSizeXxs: `var(--${string})`;
565
+ fontSizeXs: `var(--${string})`;
566
+ fontSizeSm: `var(--${string})`;
567
+ fontSizeMd: `var(--${string})`;
568
+ fontSizeLg: `var(--${string})`;
569
+ fontSizeXl: `var(--${string})`;
570
+ fontLineHeightXxs: `var(--${string})`;
571
+ fontLineHeightXs: `var(--${string})`;
572
+ fontLineHeightSm: `var(--${string})`;
573
+ fontLineHeightMd: `var(--${string})`;
574
+ fontLineHeightLg: `var(--${string})`;
575
+ fontLineHeightXl: `var(--${string})`;
576
+ fontSizeEditorBody: `var(--${string})`;
577
+ fontSizeHeadingSm: `var(--${string})`;
578
+ fontSizeHeadingMd: `var(--${string})`;
579
+ fontSizeHeadingLg: `var(--${string})`;
580
+ fontLineHeightEditorBody: `var(--${string})`;
581
+ fontLineHeightHeadingSm: `var(--${string})`;
582
+ fontLineHeightHeadingMd: `var(--${string})`;
583
+ fontLineHeightHeadingLg: `var(--${string})`;
584
+ fontTickLabel: `var(--${string})`;
585
+ fontAxisLabel: `var(--${string})`;
586
+ fontDataLabel: `var(--${string})`;
587
+ fontStackTotal: `var(--${string})`;
588
+ fontLegendLabel: `var(--${string})`;
589
+ fontSeriesLabel: `var(--${string})`;
590
+ fontTooltipLabel: `var(--${string})`;
591
+ fontTooltipHeading: `var(--${string})`;
592
+ fontTooltipFooter: `var(--${string})`;
593
+ fontJumboTooltipLabel: `var(--${string})`;
594
+ fontJumboTooltip: `var(--${string})`;
595
+ fontMiniTooltipLabel: `var(--${string})`;
596
+ fontMiniTooltipFooter: `var(--${string})`;
597
+ fontTooltipCaption: `var(--${string})`;
598
+ fontTooltipCaptionSmall: `var(--${string})`;
599
+ fontTrendTag: `var(--${string})`;
600
+ fontTrendTagSmall: `var(--${string})`;
601
+ fontGoalLineLabel: `var(--${string})`;
602
+ fontPieLabel: `var(--${string})`;
603
+ fontPieChartTotal: `var(--${string})`;
604
+ fontDifferenceArrowSmall: `var(--${string})`;
605
+ fontDifferenceArrowMedium: `var(--${string})`;
606
+ fontDifferenceArrowLarge: `var(--${string})`;
607
+ fontButton: `var(--${string})`;
608
+ fontInput: `var(--${string})`;
609
+ fontInputLabel: `var(--${string})`;
610
+ fontSelectLabel: `var(--${string})`;
611
+ fontSelectDescription: `var(--${string})`;
612
+ fontColorSelectLabel: `var(--${string})`;
613
+ fontMenuTitle: `var(--${string})`;
614
+ fontMenuGroupTitle: `var(--${string})`;
615
+ fontMenuItemLabel: `var(--${string})`;
616
+ fontMenuItemLabelSecondary: `var(--${string})`;
617
+ fontUITooltip: `var(--${string})`;
618
+ fontUITooltipSecondary: `var(--${string})`;
619
+ fontErrorBoundaryTitle: `var(--${string})`;
620
+ fontErrorBoundaryMessage: `var(--${string})`;
621
+ fontTableCell: `var(--${string})`;
622
+ fontTableHeaderCell: `var(--${string})`;
623
+ fontSourceLabel: `var(--${string})`;
624
+ fontSourceLink: `var(--${string})`;
625
+ fontTextEditorH1: `var(--${string})`;
626
+ fontTextEditorH2: `var(--${string})`;
627
+ fontTextEditorH3: `var(--${string})`;
628
+ fontTextEditorH6: `var(--${string})`;
629
+ fontTextEditorBody: `var(--${string})`;
630
+ fontTextEditorLink: `var(--${string})`;
631
+ fontHighlightModeTitle: `var(--${string})`;
632
+ fontHighlightModeSubtitle: `var(--${string})`;
633
+ };
634
+
635
+ export { }