@graphysdk/react-renderer 0.0.1-plugins.1 → 0.0.1-plugins.10

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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { AnimationPlaybackOptions } from 'motion/react';
2
+ import { AnnotationDef } from '@graphysdk/viz-engine';
1
3
  import { AnnotationZOrder } from '@graphysdk/viz-engine';
2
4
  import { AppearanceConfig } from '@graphysdk/viz-engine';
3
5
  import { CartesianCoordSystem } from '@graphysdk/viz-engine';
@@ -10,7 +12,7 @@ import { CSSProperties } from 'react';
10
12
  import { CustomPalettesInput } from '@graphysdk/viz-engine';
11
13
  import { Data } from '@graphysdk/viz-engine';
12
14
  import { FontSpec } from '@graphysdk/viz-engine';
13
- import { Geom } from '@graphysdk/viz-engine/extensions';
15
+ import { Geom } from '@graphysdk/viz-engine';
14
16
  import { GeomIdentity } from '@graphysdk/viz-engine';
15
17
  import { GeomName } from '@graphysdk/viz-engine';
16
18
  import { GraphLayout } from '@graphysdk/viz-engine';
@@ -19,14 +21,23 @@ import { HighlightStrategy } from '@graphysdk/viz-engine';
19
21
  import { HoverHit } from '@graphysdk/viz-engine';
20
22
  import { HoverState } from '@graphysdk/viz-engine';
21
23
  import { JSX } from 'react/jsx-runtime';
24
+ import { LineStyleType } from '@graphysdk/viz-engine';
22
25
  import { Locale } from '@graphysdk/viz-engine';
23
26
  import { MeasuredText } from '@graphysdk/viz-engine';
27
+ import { MotionValue } from 'motion/react';
24
28
  import { Observation } from '@graphysdk/viz-engine';
29
+ import { PanelHitTester } from '@graphysdk/viz-engine';
25
30
  import { PolarCoordSystem } from '@graphysdk/viz-engine';
26
31
  import { ReactNode } from 'react';
32
+ import { RefCallback } from 'react';
27
33
  import { ResolvedTarget } from '@graphysdk/viz-engine';
34
+ import { Stat } from '@graphysdk/viz-engine';
35
+ import { SVGProps } from 'react';
36
+ import { SwatchShape } from '@graphysdk/viz-engine';
28
37
  import { TextMeasurer } from '@graphysdk/viz-engine';
29
38
  import { TooltipContent } from '@graphysdk/viz-engine';
39
+ import { TooltipRow } from '@graphysdk/viz-engine';
40
+ import { TransformStrategy } from '@graphysdk/viz-engine';
30
41
 
31
42
  /**
32
43
  * The drawing surface a custom annotation paints into (ADR-035): a panel-positioned [0,1] frame.
@@ -34,7 +45,7 @@ import { TooltipContent } from '@graphysdk/viz-engine';
34
45
  * for the cases [0,1] cannot express (text extents, fixed-length leaders); `params` is the kind's typed
35
46
  * params. The draw function returns static nodes — annotations have no hover or tooltip.
36
47
  */
37
- declare interface AnnotationDrawInput<TParams extends object = object> {
48
+ export declare interface AnnotationDrawInput<TParams extends object = object> {
38
49
  targets: readonly ResolvedTarget[];
39
50
  area: {
40
51
  width: number;
@@ -49,12 +60,20 @@ declare interface AnnotationDrawInput<TParams extends object = object> {
49
60
  * `draw` is a React render function that may reuse the render kit (theme tokens, `toPercent`, value
50
61
  * readers) but never participates in hover.
51
62
  */
52
- declare interface AnnotationPlugin {
63
+ export declare interface AnnotationPlugin {
53
64
  type: string;
54
65
  zOrder: AnnotationZOrder;
55
66
  draw: (input: AnnotationDrawInput) => ReactNode;
56
67
  }
57
68
 
69
+ /** The render half an author supplies to {@link defineAnnotationRenderer} — everything but `type`. */
70
+ declare interface AnnotationRenderHalf<TParams extends object> {
71
+ zOrder: AnnotationZOrder;
72
+ draw: (input: AnnotationDrawInput<TParams>) => ReactNode;
73
+ }
74
+
75
+ export { AnnotationZOrder }
76
+
58
77
  /**
59
78
  * Browser text measurer backed by OffscreenCanvas.
60
79
  *
@@ -109,13 +128,60 @@ export declare class CanvasTextMeasurer implements TextMeasurer {
109
128
  private getEmojiCorrection;
110
129
  }
111
130
 
112
- declare type CoordKind = CoordSystem['type'];
131
+ /**
132
+ * Hover-overlay dot drawn at a non-primary hit's `(x, y)`: a single circle at reduced opacity
133
+ * so it reads as secondary. Used for any companion hit — same-layer sibling (e.g. another
134
+ * series at the primary X) or cross-layer related.
135
+ */
136
+ export declare const CompanionDot: ({ hit }: CompanionDotProps) => JSX.Element;
137
+
138
+ declare interface CompanionDotProps {
139
+ hit: HoverHit;
140
+ }
141
+
142
+ export declare type CoordKind = CoordSystem['type'];
113
143
 
114
144
  /** Maps a coord-kind discriminator to the corresponding `CoordSystem` member. */
115
145
  declare type CoordSystemFor<C extends CoordKind> = C extends 'cartesian' ? CartesianCoordSystem : C extends 'polar' ? PolarCoordSystem : never;
116
146
 
117
147
  export declare const darkTheme: string;
118
148
 
149
+ /**
150
+ * Binds a custom annotation's render half to its imported compile-half {@link AnnotationDef}: the kind
151
+ * name (`def.type`) and the params type (`def.defaultParams`) are read from `def`, so the half never
152
+ * re-declares them and cannot disagree with the definition — the construction-level handshake mirroring
153
+ * `defineGeomRenderer`. `draw` receives the resolved targets with `params` typed from the def.
154
+ */
155
+ export declare function defineAnnotationRenderer<TParams extends object>(def: AnnotationDef<TParams>, half: AnnotationRenderHalf<TParams>): AnnotationPlugin;
156
+
157
+ /**
158
+ * Type-narrowing constructor for a plugin. Each plugin file declares its `(geom, coord)` pair and its
159
+ * `highlightStrategy` inline; TypeScript infers `G`/`C`/`S` from the object literal — handlers then
160
+ * receive `CompiledLayerFor<G>` / `CoordSystemFor<C>` with no `as` casts. Whether `getOverlayAnchor` is
161
+ * required follows from the declared `highlightStrategy` via {@link GeomPluginForStrategy}. A custom geom
162
+ * supplies its params type `TParams` (e.g. by annotating `render`'s input) to type `layer.params`.
163
+ *
164
+ * Returns the broad `GeomPlugin` type (with the type parameters erased) so all plugins fit into one
165
+ * registry. The cast inside this helper is safe because the registry routes every call to the plugin
166
+ * keyed by `(geom, coord)`.
167
+ */
168
+ export declare function defineGeomPlugin<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams = PluginParams<G>>(plugin: GeomPluginForStrategy<G, C, S, TParams>): GeomPlugin;
169
+
170
+ /**
171
+ * Binds a geom's render half to its imported compile-half {@link Geom} definition: the geom name
172
+ * (`def.type`), the highlight strategy (`def.highlightStrategy`), and the params type
173
+ * (`def.defaultParams`) are all read from `def`, so the half never re-declares them and cannot disagree
174
+ * with the definition — the construction-level handshake. Whether `getOverlayAnchor` is required follows
175
+ * from the def's declared `highlightStrategy`, and `render`/`renderHover` receive `layer.params` typed
176
+ * from the def with no annotation. Built-in plugins keep {@link defineGeomPlugin}; reach for this only to
177
+ * pair a custom geom's two halves.
178
+ *
179
+ * Returns the broad {@link GeomPlugin} (type parameters erased) so every plugin fits one registry; the
180
+ * cast is the same variance bypass {@link defineGeomPlugin} performs, safe because the registry routes
181
+ * each call by `(geom, coord)`.
182
+ */
183
+ export declare function defineGeomRenderer<Def extends Geom, C extends CoordKind>(def: Def, half: GeomRenderHalf<Def, C>): GeomPlugin;
184
+
119
185
  export declare const DevToolsPanel: ({ width, style, className }?: DevToolsPanelProps) => JSX.Element;
120
186
 
121
187
  /**
@@ -132,6 +198,16 @@ export declare interface DevToolsPanelProps {
132
198
  className?: string;
133
199
  }
134
200
 
201
+ export declare const emToPx: (em: number, textScale: number) => number;
202
+
203
+ /**
204
+ * Whether a region is large enough to carry a label: both dimensions must clear their minimum. Works in
205
+ * any single consistent space — pass unit dimensions with unit thresholds, or pixels with pixel
206
+ * thresholds. A space-filling geom (treemap) culls labels with it so a tile too small to fit text stays
207
+ * unlabelled rather than overflowing.
208
+ */
209
+ export declare function fitsLabel(width: number, height: number, minWidth: number, minHeight: number): boolean;
210
+
135
211
  /** A geom's declared highlight composition strategy, or `null` when it opts out of highlighting. */
136
212
  declare type GeomHighlightStrategy = HighlightStrategy | null;
137
213
 
@@ -152,7 +228,7 @@ declare type GeomHighlightStrategy = HighlightStrategy | null;
152
228
  * {@link defineGeomPlugin} boundary via {@link GeomPluginForStrategy}, keyed on the plugin's own
153
229
  * declared `highlightStrategy` — so a custom geom is gated by what it declares, not a name lookup.
154
230
  */
155
- declare type GeomPlugin<G extends string = GeomIdentity, C extends CoordKind = CoordKind> = NoOverlayAnchorGeomPlugin<G, C, GeomHighlightStrategy, PluginParams<G>> | OverlayAnchorGeomPlugin<G, C, GeomHighlightStrategy, PluginParams<G>>;
231
+ export declare type GeomPlugin<G extends string = GeomIdentity, C extends CoordKind = CoordKind> = NoOverlayAnchorGeomPlugin<G, C, GeomHighlightStrategy, PluginParams<G>> | OverlayAnchorGeomPlugin<G, C, GeomHighlightStrategy, PluginParams<G>>;
156
232
 
157
233
  declare interface GeomPluginBase<G extends string, C extends CoordKind, S extends GeomHighlightStrategy, TParams> {
158
234
  geom: G;
@@ -176,7 +252,26 @@ declare interface GeomPluginBase<G extends string, C extends CoordKind, S extend
176
252
  renderTooltip?: (input: TooltipRenderInput<G, C, TParams>) => ReactNode;
177
253
  }
178
254
 
179
- declare interface GeomRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
255
+ /**
256
+ * Picks the plugin shape required for a plugin's own declared `highlightStrategy`. Only the
257
+ * `'overlay-anchor'` strategy demands the anchor reader; `'observation-rerender'` and `null` (no
258
+ * highlight) both resolve to {@link NoOverlayAnchorGeomPlugin}.
259
+ *
260
+ * Used by {@link defineGeomPlugin} to enforce the strategy→shape coupling at plugin-definition
261
+ * sites — `observation-rerender` plugins cannot declare `getOverlayAnchor`, `overlay-anchor` ones must
262
+ * — for any geom name, built-in or custom, with no closed geom-name lookup.
263
+ */
264
+ 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>;
265
+
266
+ /**
267
+ * The render half an author supplies to {@link defineGeomRenderer}: every field of a plugin except the
268
+ * two its imported compile-half definition already declares — `geom` and `highlightStrategy`.
269
+ * `getOverlayAnchor` is gated on the def's declared strategy via {@link GeomPluginForStrategy}, so the
270
+ * render contract is bound to the definition rather than re-declared.
271
+ */
272
+ declare type GeomRenderHalf<Def extends Geom, C extends CoordKind> = Omit<GeomPluginForStrategy<Def['type'] & string, C, Def['highlightStrategy'], Def['defaultParams']>, 'geom' | 'highlightStrategy'>;
273
+
274
+ export declare interface GeomRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
180
275
  layer: CompiledLayerFor<G, TParams>;
181
276
  coordSystem: CoordSystemFor<C>;
182
277
  isAnimated: boolean;
@@ -191,10 +286,12 @@ declare interface GeomRenderInput<G extends string = GeomName, C extends CoordKi
191
286
  export declare type GraphMode = 'readonly' | 'editable';
192
287
 
193
288
  /**
194
- * Owns the compiled spec for a graph and exposes it via {@link useCompiledSpec}, plus a
195
- * `dispatch` for applying {@link Command}s.
289
+ * Owns the compiled spec for a graph and exposes it via {@link useCompiledSelector}, plus a
290
+ * `dispatch` for applying {@link Command}s. Wraps the chart in {@link GraphErrorBoundary} so an
291
+ * invalid spec surfaces its error in place instead of unwinding the surrounding app — every chart
292
+ * gets this isolation for free, with no per-chart boundary to author.
196
293
  */
197
- export declare const GraphProvider: ({ data, input, formattingLocale, onChange, customPalettes, theme, themeOverrides: themeOverridesInput, geoms, plugins, annotationPlugins, children, }: GraphProviderProps) => JSX.Element;
294
+ export declare const GraphProvider: (props: GraphProviderProps) => JSX.Element;
198
295
 
199
296
  declare interface GraphProviderProps {
200
297
  data: Data;
@@ -206,10 +303,16 @@ declare interface GraphProviderProps {
206
303
  customPalettes?: CustomPalettesInput;
207
304
  /** Custom geom definitions, injected per-instance into the compiler (override built-ins by name). */
208
305
  geoms?: readonly Geom[];
306
+ /** Custom stat definitions (`defineStat`), injected per-instance into the compiler (override built-ins by `type`). */
307
+ stats?: readonly Stat[];
308
+ /** Custom transform strategies (`defineTransform`), injected per-instance (override built-ins by `transformType`). */
309
+ transforms?: readonly TransformStrategy[];
209
310
  /** Custom geom render plugins, injected per-instance (override built-ins by `(geom, coord)`). */
210
311
  plugins?: readonly GeomPlugin[];
211
312
  /** Custom annotation render plugins, injected per-instance and resolved by annotation `type` (ADR-035). */
212
313
  annotationPlugins?: readonly AnnotationPlugin[];
314
+ /** Stable chart id. Stamped onto the rendered root as `data-graphy-id`; enables the editor bridge. */
315
+ id?: string;
213
316
  children: ReactNode;
214
317
  }
215
318
 
@@ -219,23 +322,47 @@ declare interface GraphProviderProps {
219
322
  * no `config` prop: every consumer must wrap with `<GraphProvider>` so commands can operate
220
323
  * on the live spec.
221
324
  */
222
- export declare const GraphRenderer: (props: GraphRendererProps) => JSX.Element;
325
+ export declare const GraphRenderer: ({ sizing, onResize, ...props }: GraphRendererProps) => JSX.Element;
223
326
 
327
+ /** Props for {@link GraphRenderer}: container sizing, interaction toggles, and display mode. */
224
328
  export declare interface GraphRendererProps {
225
- width: number;
226
- height: number;
329
+ /** Controls how the graph responds to its container size. Defaults to filling the parent container. */
330
+ sizing?: GraphSizing;
331
+ /** Callback invoked when the graph's container is resized. Fires in every sizing mode. */
332
+ onResize?: ResizeObserverOnResize;
227
333
  isAnimated?: boolean;
228
334
  showTooltips?: boolean;
229
335
  mode?: GraphMode;
230
336
  }
231
337
 
232
- declare interface HoverCompanionsRenderInput<G extends string = GeomName, TParams = PluginParams<G>> {
338
+ /** Controls how the graph claims space in its container. */
339
+ export declare type GraphSizing = {
340
+ mode: 'responsive';
341
+ } | {
342
+ mode: 'fixed';
343
+ width: number;
344
+ height: number;
345
+ } | {
346
+ mode: 'keepAspectRatio';
347
+ intrinsicWidth: number;
348
+ intrinsicHeight: number;
349
+ } | {
350
+ mode: 'keepAspectRatio';
351
+ intrinsicWidth: number;
352
+ aspectRatio: number;
353
+ } | {
354
+ mode: 'keepAspectRatio';
355
+ intrinsicHeight: number;
356
+ aspectRatio: number;
357
+ };
358
+
359
+ export declare interface HoverCompanionsRenderInput<G extends string = GeomName, TParams = PluginParams<G>> {
233
360
  layer: CompiledLayerFor<G, TParams>;
234
361
  primary: HoverHit;
235
362
  related: HoverHit[];
236
363
  }
237
364
 
238
- declare type HoverGuideMode = 'continuous' | 'bar';
365
+ export declare type HoverGuideMode = 'continuous' | 'bar';
239
366
 
240
367
  /**
241
368
  * Hosts the hover store + engine for the surrounding `<GraphProvider>`. Subscribes only to the
@@ -248,7 +375,7 @@ declare interface HoverProviderProps {
248
375
  children: ReactNode;
249
376
  }
250
377
 
251
- declare interface HoverRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
378
+ export declare interface HoverRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
252
379
  layer: CompiledLayerFor<G, TParams>;
253
380
  coordSystem: CoordSystemFor<C>;
254
381
  primary: HoverHit;
@@ -275,8 +402,18 @@ declare interface HoverStoreActions {
275
402
 
276
403
  declare type HoverStoreState = HoverSlice & HoverStoreActions;
277
404
 
405
+ /** Lightens a hex colour by mixing it toward white by `amount` (`0` keeps the colour, `1` is white). */
406
+ export declare function lighten(hex: string, amount: number): string;
407
+
278
408
  export declare const lightTheme: string;
279
409
 
410
+ /**
411
+ * Mixes a hex colour toward another by `amount` in `[0, 1]` (`0` keeps `hex`, `1` returns `towardHex`),
412
+ * channel-wise in sRGB. Returns an `rgb(...)` string. Used for within-group shading where leaves share a
413
+ * group hue and vary only in lightness.
414
+ */
415
+ export declare function mixColor(hex: string, towardHex: string, amount: number): string;
416
+
280
417
  /**
281
418
  * Plugin shape for geoms that don't compute an overlay anchor — either `'observation-rerender'`
282
419
  * geoms (matched rows re-render in place) or geoms that opt out of highlighting entirely
@@ -290,7 +427,7 @@ declare interface NoOverlayAnchorGeomPlugin<G extends string, C extends CoordKin
290
427
  * Anchor point in normalized [0,1] coord-space where a highlight overlay marker
291
428
  * should be painted for one observation. Renderer turns [0,1] into pixels.
292
429
  */
293
- declare interface OverlayAnchor {
430
+ export declare interface OverlayAnchor {
294
431
  x: number;
295
432
  y: number;
296
433
  }
@@ -300,15 +437,83 @@ declare interface OverlayAnchorGeomPlugin<G extends string, C extends CoordKind,
300
437
  getOverlayAnchor: (input: OverlayAnchorInput<G, C, TParams>) => OverlayAnchor | null;
301
438
  }
302
439
 
303
- declare interface OverlayAnchorInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
440
+ export declare interface OverlayAnchorInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
304
441
  layer: CompiledLayerFor<G, TParams>;
305
442
  coordSystem: CoordSystemFor<C>;
306
443
  observation: Observation;
307
444
  }
308
445
 
446
+ export { PanelHitTester }
447
+
448
+ /**
449
+ * Portals an interactive overlay to `document.body`, fixed over the given panel rect at the documented
450
+ * top `z-index`. Owns only the placement and chrome; the simulation canvas it wraps paints inside. Sized
451
+ * to the rect with `pointerEvents: 'none'` so gaps fall through to the chart — the overlay's own marks
452
+ * re-enable pointer events to capture drags.
453
+ */
454
+ export declare function PanelOverlayPortal({ rect, children }: {
455
+ rect: PanelScreenRect;
456
+ children: ReactNode;
457
+ }): ReactNode;
458
+
459
+ /** The panel's on-screen rectangle in page-relative pixels — the frame a portalled overlay aligns to. */
460
+ export declare interface PanelScreenRect {
461
+ left: number;
462
+ top: number;
463
+ width: number;
464
+ height: number;
465
+ }
466
+
467
+ /**
468
+ * Walks a kind-tagged geom-layout dataset (the output of `createMarkTable`), yielding each observation paired
469
+ * with its discriminant `kind`. The render half switches on `kind` to build its per-kind marks, instead
470
+ * of re-reading the kind column inline in every plugin. `Kind` narrows the discriminant to the geom's own
471
+ * union (e.g. `'node' | 'link'`) for an exhaustive switch.
472
+ */
473
+ export declare function partitionByKind<Kind extends string = string>(data: Iterable<Observation>, kindColumn: string): Generator<{
474
+ kind: Kind;
475
+ observation: Observation;
476
+ }>;
477
+
309
478
  /** The compiled-layer params a plugin's handlers see — built-ins default from the geom name; a custom geom supplies its own. */
310
479
  declare type PluginParams<G extends string> = CompiledLayerFor<G>['params'];
311
480
 
481
+ /**
482
+ * Hover-overlay dot drawn at the primary hit's `(x, y)`: colored disc with a thicker white
483
+ * border and an outer white ring offset by a 1px gap. Radius is data-driven so bubble charts
484
+ * whose size channel carries data don't distort under hover.
485
+ */
486
+ export declare const PrimaryDot: ({ hit, ...rest }: PrimaryDotProps) => JSX.Element;
487
+
488
+ declare interface PrimaryDotProps {
489
+ hit: HoverHit;
490
+ 'data-testid'?: string;
491
+ }
492
+
493
+ export declare type ResizeObserverOnResize = (state: ResizeObserverState) => void;
494
+
495
+ export declare interface ResizeObserverState {
496
+ width: number;
497
+ height: number;
498
+ /** True until the first ResizeObserver measurement lands. */
499
+ isDefault: boolean;
500
+ }
501
+
502
+ export { ResolvedTarget }
503
+
504
+ /**
505
+ * Shared shape glyph used by both the tooltip and the legend.
506
+ */
507
+ export declare const Swatch: ({ shape, color, lineType, width, height, }: SwatchProps) => JSX.Element;
508
+
509
+ declare interface SwatchProps {
510
+ shape: SwatchShape;
511
+ color: string;
512
+ lineType?: LineStyleType;
513
+ width?: number;
514
+ height?: number;
515
+ }
516
+
312
517
  /**
313
518
  * Creates a font-ready, cached text measurer and shares it with descendants via context.
314
519
  * Renders nothing until the measurer resolves, so consumers reading the context always
@@ -348,13 +553,31 @@ declare interface ThemeProviderProps {
348
553
 
349
554
  export declare type ThemeValues = Record<keyof typeof vars, string>;
350
555
 
556
+ /**
557
+ * The default tooltip body — the optional header and one row per hovered observation, with the
558
+ * in-place primary-row highlight. Presentational and engine-decoupled: it renders a
559
+ * {@link TooltipContent} and nothing else, so the built-in `Tooltip` and a custom geom's
560
+ * `renderTooltip` paint the same rows. The positioned, themed card around it stays the renderer's.
561
+ */
562
+ export declare const TooltipBody: ({ content }: TooltipBodyProps) => JSX.Element;
563
+
564
+ declare interface TooltipBodyProps {
565
+ content: TooltipContent;
566
+ }
567
+
568
+ /** Page-relative cursor position the tooltip anchors to. `null` when the pointer is outside the chart. */
569
+ export declare interface TooltipCursor {
570
+ clientX: number;
571
+ clientY: number;
572
+ }
573
+
351
574
  /**
352
575
  * Input a plugin's {@link GeomPluginBase.renderTooltip} receives when one of its observations is the
353
576
  * primary hit. `content` is the body the built-in tooltip would render — feed it to `TooltipBody` to
354
577
  * reproduce the default — while `primary.observation` carries the geom's own columns for a bespoke
355
578
  * layout. The card around the body (positioning, theme) stays the renderer's.
356
579
  */
357
- declare interface TooltipRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
580
+ export declare interface TooltipRenderInput<G extends string = GeomName, C extends CoordKind = CoordKind, TParams = PluginParams<G>> {
358
581
  content: TooltipContent;
359
582
  layer: CompiledLayerFor<G, TParams>;
360
583
  coordSystem: CoordSystemFor<C>;
@@ -363,6 +586,57 @@ declare interface TooltipRenderInput<G extends string = GeomName, C extends Coor
363
586
  related: ReadonlyMap<string, HoverHit[]>;
364
587
  }
365
588
 
589
+ /**
590
+ * One tooltip row — swatch, label, value, with the optional in-place highlight. Exposed so a custom
591
+ * geom's `renderTooltip` can map `content.rows` itself and interleave its own content between rows,
592
+ * rather than rendering the whole {@link TooltipBody} as an opaque block.
593
+ */
594
+ export declare const TooltipRowView: ({ row, shouldHighlight }: TooltipRowViewProps) => JSX.Element;
595
+
596
+ declare interface TooltipRowViewProps {
597
+ row: TooltipRow;
598
+ shouldHighlight: boolean;
599
+ }
600
+
601
+ export declare const toPercent: (value: number) => string;
602
+
603
+ /**
604
+ * Converts a normalized [0,1] x-coordinate to viewBox coordinate (identity transform).
605
+ * Used inside nested SVGs with viewBox="0 0 1 1".
606
+ */
607
+ export declare function toViewBoxX(normalized: number): number;
608
+
609
+ /**
610
+ * Converts a normalized [0,1] y-coordinate to viewBox coordinate (Y-inverted).
611
+ * SVG y=0 is at the top, but data y=0 is at the bottom, so we invert.
612
+ * Used inside nested SVGs with viewBox="0 0 1 1".
613
+ */
614
+ export declare function toViewBoxY(normalized: number): number;
615
+
616
+ /**
617
+ * An `<svg>` preset for painting geom-layout geometry in panel `[0,1]` unit space: `viewBox="0 0 1 1"`,
618
+ * `preserveAspectRatio="none"` (so unit coordinates stretch to fill the panel exactly, the way a bar
619
+ * chart's bars do), and `overflow: visible`.
620
+ *
621
+ * Chrome gotcha (documented once here, so geoms don't rediscover it): with a sub-unit `viewBox`, native
622
+ * SVG fill hit-testing is unreliable at this scale — which is why geom-layout geoms answer a numeric
623
+ * `useGeomHitTest` query instead of relying on pointer events landing on these shapes. Paint here; hit-test
624
+ * through the engine.
625
+ */
626
+ export declare const UnitSpaceSvg: ({ children, style, ...rest }: SVGProps<SVGSVGElement>) => ReactNode;
627
+
628
+ /**
629
+ * Returns an `index → colour` resolver over the chart's default categorical palette — the same
630
+ * `DEFAULT_COLOR_PALETTE` the compiler bakes into a colour-encoded layer — so a custom geom that
631
+ * assigns its own colour indices draws from the chart's palette instead of inventing a private one.
632
+ * Colours therefore match what a sibling layer's colour scale would produce, and follow the engine's
633
+ * palette rather than a hardcoded array.
634
+ *
635
+ * Out of scope (ADR-034 open question #4): declaring a colour *aesthetic* with its own scale + legend,
636
+ * or honouring a per-spec custom palette. This primitive only ensures the colours match the default.
637
+ */
638
+ export declare function useCategoricalColor(): (index: number) => string;
639
+
366
640
  /**
367
641
  * Subscribes to a derived slice of the compiled spec. The subscription only fires when the
368
642
  * selector's result changes by reference, so combined with the compiler's per-stage memoization
@@ -376,6 +650,31 @@ declare interface TooltipRenderInput<G extends string = GeomName, C extends Coor
376
650
  */
377
651
  export declare const useCompiledSelector: <Selected>(selector: (compiled: CompiledSpec) => Selected) => Selected;
378
652
 
653
+ /**
654
+ * Registers a geom-layout geom's render-side hit-test for its layer, so the central hover engine routes
655
+ * the cursor to it — the geom inherits the built-in hover, tooltip, and (in time) accessibility
656
+ * instead of hand-rolling a pointer overlay. The geom declares `spatialKind: 'render-hit-test'`; this
657
+ * hook supplies the matching closure.
658
+ *
659
+ * The `tester` receives the cursor in panel `[0, 1]` with a top-left origin (the frame the geom
660
+ * paints in) and returns the declared identity key of the observation under it, or `null`. It may
661
+ * close over freshly computed geometry each render — a stable wrapper reads the latest through a ref,
662
+ * so the registration effect runs once per layer rather than every render.
663
+ */
664
+ export declare function useGeomHitTest(layerId: string, tester: PanelHitTester): void;
665
+
666
+ /**
667
+ * The push counterpart to `useGeomHitTest`, for a geom-layout geom that owns its own pointer surface — a
668
+ * live simulation whose interactive overlay intercepts pointer events before the central capture
669
+ * layer sees them, so the engine cannot pull a hit. The geom already knows which observation is under
670
+ * the cursor and pushes its declared identity key; the engine resolves it to the same unified
671
+ * `HoverState` the pull path produces, and the cursor is forwarded so the central tooltip tracks.
672
+ *
673
+ * Returns a stable `setHovered(key, cursor?)`: a key with the page-relative cursor opens the tooltip
674
+ * on that observation; `null` clears it.
675
+ */
676
+ export declare function useGeomHover(layerId: string): (key: string | null, cursor?: TooltipCursor) => void;
677
+
379
678
  export declare const useGraphCommandDispatcher: () => ((command: Command) => void);
380
679
 
381
680
  /**
@@ -383,6 +682,25 @@ export declare const useGraphCommandDispatcher: () => ((command: Command) => voi
383
682
  */
384
683
  export declare function useHoverState<T>(selector: (state: HoverStoreState) => T): T;
385
684
 
685
+ /**
686
+ * Tracks the on-screen rect of the element the returned `ref` is attached to, across container resize and
687
+ * page scroll. Only a live-simulation geom needs this (ADR-034 decision 4): it paints and hit-tests
688
+ * render-side every frame, so its interactive overlay must sit above the chart in pixel space. Every other
689
+ * geom-layout geom routes hover through the engine (decision 2) and never tracks a screen rect.
690
+ */
691
+ export declare function usePanelScreenRect(): {
692
+ ref: RefCallback<Element>;
693
+ rect: PanelScreenRect | null;
694
+ };
695
+
696
+ /**
697
+ * Animates SVG path transitions using `d3-interpolate-path` for smooth morphing
698
+ * when data points are added or removed (Framer Motion doesn't support this natively).
699
+ *
700
+ * Based on: https://github.com/framer/motion/issues/451#issuecomment-761302824
701
+ */
702
+ export declare const useSvgPathMorph: (pathDefinition: string, config: AnimationPlaybackOptions) => MotionValue<string>;
703
+
386
704
  export declare const useTextMeasurer: () => TextMeasurer;
387
705
 
388
706
  export declare const vars: {