semiotic 3.4.1 → 3.5.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.
Files changed (164) hide show
  1. package/CLAUDE.md +114 -9
  2. package/README.md +45 -4
  3. package/ai/behaviorContracts.cjs +311 -0
  4. package/ai/chartSuggestions.cjs +291 -0
  5. package/ai/cli.js +255 -30
  6. package/ai/componentMetadata.cjs +107 -0
  7. package/ai/dist/mcp-server.js +907 -227
  8. package/ai/schema.json +3954 -2537
  9. package/ai/system-prompt.md +23 -4
  10. package/dist/components/LinkedCharts.d.ts +5 -1
  11. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  12. package/dist/components/charts/custom/NetworkCustomChart.d.ts +64 -0
  13. package/dist/components/charts/custom/OrdinalCustomChart.d.ts +71 -0
  14. package/dist/components/charts/custom/XYCustomChart.d.ts +59 -0
  15. package/dist/components/charts/geo/ChoroplethMap.d.ts +93 -2
  16. package/dist/components/charts/geo/DistanceCartogram.d.ts +51 -4
  17. package/dist/components/charts/geo/FlowMap.d.ts +55 -0
  18. package/dist/components/charts/geo/ProportionalSymbolMap.d.ts +53 -0
  19. package/dist/components/charts/index.d.ts +6 -0
  20. package/dist/components/charts/network/ChordDiagram.d.ts +34 -2
  21. package/dist/components/charts/network/CirclePack.d.ts +36 -1
  22. package/dist/components/charts/network/ForceDirectedGraph.d.ts +130 -2
  23. package/dist/components/charts/network/OrbitDiagram.d.ts +37 -0
  24. package/dist/components/charts/network/SankeyDiagram.d.ts +51 -2
  25. package/dist/components/charts/network/TreeDiagram.d.ts +37 -2
  26. package/dist/components/charts/network/Treemap.d.ts +36 -2
  27. package/dist/components/charts/ordinal/BarChart.d.ts +111 -1
  28. package/dist/components/charts/ordinal/BoxPlot.d.ts +31 -0
  29. package/dist/components/charts/ordinal/DonutChart.d.ts +36 -0
  30. package/dist/components/charts/ordinal/DotPlot.d.ts +31 -0
  31. package/dist/components/charts/ordinal/FunnelChart.d.ts +40 -0
  32. package/dist/components/charts/ordinal/GaugeChart.d.ts +45 -0
  33. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +38 -0
  34. package/dist/components/charts/ordinal/Histogram.d.ts +95 -0
  35. package/dist/components/charts/ordinal/LikertChart.d.ts +42 -0
  36. package/dist/components/charts/ordinal/PieChart.d.ts +90 -1
  37. package/dist/components/charts/ordinal/RidgelinePlot.d.ts +27 -0
  38. package/dist/components/charts/ordinal/StackedBarChart.d.ts +38 -0
  39. package/dist/components/charts/ordinal/SwarmPlot.d.ts +36 -0
  40. package/dist/components/charts/ordinal/SwimlaneChart.d.ts +60 -0
  41. package/dist/components/charts/ordinal/ViolinPlot.d.ts +32 -0
  42. package/dist/components/charts/realtime/RealtimeHeatmap.d.ts +22 -4
  43. package/dist/components/charts/realtime/RealtimeHistogram.d.ts +5 -2
  44. package/dist/components/charts/realtime/RealtimeLineChart.d.ts +24 -3
  45. package/dist/components/charts/realtime/RealtimeSwarmChart.d.ts +12 -0
  46. package/dist/components/charts/realtime/RealtimeWaterfallChart.d.ts +14 -0
  47. package/dist/components/charts/realtime/defaultRealtimeTooltip.d.ts +43 -0
  48. package/dist/components/charts/realtime/resolveWindowSize.d.ts +26 -0
  49. package/dist/components/charts/shared/chartSpecs.d.ts +91 -0
  50. package/dist/components/charts/shared/colorPalettes.d.ts +62 -0
  51. package/dist/components/charts/shared/colorUtils.d.ts +9 -10
  52. package/dist/components/charts/shared/numberFormat.d.ts +58 -0
  53. package/dist/components/charts/shared/sparseArray.d.ts +27 -0
  54. package/dist/components/charts/shared/streamPropsHelpers.d.ts +113 -0
  55. package/dist/components/charts/shared/timeFormat.d.ts +60 -0
  56. package/dist/components/charts/shared/useChartSetup.d.ts +8 -0
  57. package/dist/components/charts/shared/useCustomChartSetup.d.ts +84 -0
  58. package/dist/components/charts/shared/useFrameImperativeHandle.d.ts +28 -0
  59. package/dist/components/charts/shared/useOrdinalStreaming.d.ts +6 -19
  60. package/dist/components/charts/shared/useStreamingLegend.d.ts +27 -11
  61. package/dist/components/charts/shared/validateProps.d.ts +2 -2
  62. package/dist/components/charts/shared/validationMap.d.ts +2 -1
  63. package/dist/components/charts/shared/withChartWrapper.d.ts +13 -4
  64. package/dist/components/charts/xy/AreaChart.d.ts +30 -1
  65. package/dist/components/charts/xy/CandlestickChart.d.ts +33 -6
  66. package/dist/components/charts/xy/ConnectedScatterplot.d.ts +24 -0
  67. package/dist/components/charts/xy/MinimapChart.d.ts +51 -0
  68. package/dist/components/charts/xy/MultiAxisLineChart.d.ts +27 -0
  69. package/dist/components/charts/xy/QuadrantChart.d.ts +21 -0
  70. package/dist/components/charts/xy/Scatterplot.d.ts +34 -2
  71. package/dist/components/charts/xy/ScatterplotMatrix.d.ts +16 -0
  72. package/dist/components/charts/xy/StackedAreaChart.d.ts +49 -1
  73. package/dist/components/export/selectionSerializer.d.ts +1 -1
  74. package/dist/components/realtime/types.d.ts +7 -9
  75. package/dist/components/recipes/bullet.d.ts +86 -0
  76. package/dist/components/recipes/calendar.d.ts +43 -0
  77. package/dist/components/recipes/dagre.d.ts +56 -0
  78. package/dist/components/recipes/flextree.d.ts +55 -0
  79. package/dist/components/recipes/marimekko.d.ts +55 -0
  80. package/dist/components/recipes/parallelCoordinates.d.ts +97 -0
  81. package/dist/components/recipes/recipeUtils.d.ts +27 -0
  82. package/dist/components/recipes/waffle.d.ts +46 -0
  83. package/dist/components/semiotic-ai.d.ts +4 -0
  84. package/dist/components/semiotic-network.d.ts +3 -0
  85. package/dist/components/semiotic-ordinal.d.ts +3 -0
  86. package/dist/components/semiotic-recipes.d.ts +24 -0
  87. package/dist/components/semiotic-xy.d.ts +3 -0
  88. package/dist/components/semiotic.d.ts +2 -2
  89. package/dist/components/server/renderToStaticSVG.d.ts +8 -2
  90. package/dist/components/server/serverChartConfigs.d.ts +47 -1
  91. package/dist/components/server/staticAnnotations.d.ts +6 -0
  92. package/dist/components/store/ObservationStore.d.ts +1 -3
  93. package/dist/components/store/SelectionStore.d.ts +2 -4
  94. package/dist/components/store/ThemeStore.d.ts +4 -4
  95. package/dist/components/store/TooltipStore.d.ts +5 -3
  96. package/dist/components/store/createStore.d.ts +4 -2
  97. package/dist/components/store/useSelection.d.ts +7 -4
  98. package/dist/components/stream/CanvasHitTester.d.ts +10 -8
  99. package/dist/components/stream/DataSourceAdapter.d.ts +9 -0
  100. package/dist/components/stream/GeoPipelineStore.d.ts +9 -0
  101. package/dist/components/stream/GeoTileRenderer.d.ts +14 -0
  102. package/dist/components/stream/NetworkPipelineStore.d.ts +25 -0
  103. package/dist/components/stream/NetworkSVGOverlay.d.ts +18 -12
  104. package/dist/components/stream/OrdinalPipelineStore.d.ts +12 -0
  105. package/dist/components/stream/PipelineStore.d.ts +51 -0
  106. package/dist/components/stream/SVGOverlay.d.ts +12 -0
  107. package/dist/components/stream/SceneGraph.d.ts +15 -1
  108. package/dist/components/stream/SceneToSVG.d.ts +1 -1
  109. package/dist/components/stream/categoryDomain.d.ts +4 -0
  110. package/dist/components/stream/composeOverlays.d.ts +15 -0
  111. package/dist/components/stream/customLayout.d.ts +76 -0
  112. package/dist/components/stream/customLayoutPalette.d.ts +29 -0
  113. package/dist/components/stream/geoTypes.d.ts +33 -8
  114. package/dist/components/stream/hoverUtils.d.ts +4 -10
  115. package/dist/components/stream/keyboardNav.d.ts +18 -6
  116. package/dist/components/stream/networkCustomLayout.d.ts +67 -0
  117. package/dist/components/stream/networkTypes.d.ts +87 -21
  118. package/dist/components/stream/ordinalCustomLayout.d.ts +84 -0
  119. package/dist/components/stream/ordinalTypes.d.ts +47 -13
  120. package/dist/components/stream/renderers/barFunnelCanvasRenderer.d.ts +9 -1
  121. package/dist/components/stream/renderers/canvasRenderHelpers.d.ts +92 -0
  122. package/dist/components/stream/sampleCurvePath.d.ts +9 -0
  123. package/dist/components/stream/types.d.ts +57 -10
  124. package/dist/components/stream/useHydration.d.ts +89 -0
  125. package/dist/components/stream/useStableShallow.d.ts +1 -0
  126. package/dist/components/stream/xySceneBuilders/types.d.ts +4 -0
  127. package/dist/geo.min.js +2 -1
  128. package/dist/geo.module.min.js +2 -1
  129. package/dist/network.min.js +2 -1
  130. package/dist/network.module.min.js +2 -1
  131. package/dist/ordinal.min.js +2 -1
  132. package/dist/ordinal.module.min.js +2 -1
  133. package/dist/realtime.min.js +2 -1
  134. package/dist/realtime.module.min.js +2 -1
  135. package/dist/semiotic-ai.d.ts +69 -65
  136. package/dist/semiotic-ai.min.js +2 -1
  137. package/dist/semiotic-ai.module.min.js +2 -1
  138. package/dist/semiotic-data.d.ts +4 -4
  139. package/dist/semiotic-geo.d.ts +15 -15
  140. package/dist/semiotic-network.d.ts +19 -16
  141. package/dist/semiotic-ordinal.d.ts +31 -28
  142. package/dist/semiotic-realtime.d.ts +17 -17
  143. package/dist/semiotic-recipes.d.ts +24 -0
  144. package/dist/semiotic-recipes.min.js +1 -0
  145. package/dist/semiotic-recipes.module.min.js +1 -0
  146. package/dist/semiotic-server.d.ts +6 -6
  147. package/dist/semiotic-statisticalOverlays-C3DsOgr_.js +1 -0
  148. package/dist/semiotic-themes.d.ts +3 -3
  149. package/dist/semiotic-themes.min.js +2 -1
  150. package/dist/semiotic-themes.module.min.js +2 -1
  151. package/dist/semiotic-utils.d.ts +23 -23
  152. package/dist/semiotic-utils.min.js +2 -1
  153. package/dist/semiotic-utils.module.min.js +2 -1
  154. package/dist/semiotic-xy.d.ts +27 -24
  155. package/dist/semiotic.d.ts +63 -63
  156. package/dist/semiotic.min.js +2 -1
  157. package/dist/semiotic.module.min.js +2 -1
  158. package/dist/server.min.js +1 -1
  159. package/dist/server.module.min.js +1 -1
  160. package/dist/test-utils/canvasMock.d.ts +34 -5
  161. package/dist/xy.min.js +2 -1
  162. package/dist/xy.module.min.js +2 -1
  163. package/package.json +40 -20
  164. package/dist/semiotic-statisticalOverlays-Ckd_jM8z.js +0 -1
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Compose a stack of overlay ReactNodes into a single fragment, dropping
4
+ * null/undefined sources. Each frame paints its `resolvedForeground`
5
+ * (axes, legends, annotations, react overlay) and may layer additional
6
+ * sources on top — currently `customLayoutOverlays` from recipe-managed
7
+ * chrome, with brush UIs and recipe-owned legends planned. Centralising
8
+ * the merge here keeps SSR and client branches in sync and gives future
9
+ * overlay sources one obvious place to plug in.
10
+ *
11
+ * Returns the single non-null source as-is when only one is present
12
+ * (avoids an unnecessary fragment); returns `null` when every source is
13
+ * absent so callers can skip the overlay subtree entirely.
14
+ */
15
+ export declare function composeOverlays(...sources: Array<React.ReactNode | null | undefined>): React.ReactNode;
@@ -0,0 +1,76 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Datum } from "../charts/shared/datumTypes";
3
+ import type { MarginType } from "../types/marginType";
4
+ import type { SceneNode, StreamScales, Style, ThemeSemanticColors } from "./types";
5
+ /**
6
+ * customLayout — escape hatch for bespoke chart geometry.
7
+ *
8
+ * A customLayout function receives the same context the built-in scene
9
+ * builders use (scales, theme, resolvers, dimensions) and returns scene
10
+ * nodes. The frame still owns hit testing, transitions, decay, theme
11
+ * cascade, and SSR — the layout owns geometry only.
12
+ *
13
+ * Surface is intentionally narrow. Resist adding fields until a real
14
+ * recipe demands them.
15
+ */
16
+ export type CustomLayout<C extends object = Record<string, unknown>> = (ctx: LayoutContext<C>) => LayoutResult;
17
+ /**
18
+ * Context handed to every customLayout invocation. Six fields:
19
+ * data, scales, dimensions, theme, resolveColor, config.
20
+ *
21
+ * `resolveColor` is the contract that makes user layouts theme-aware —
22
+ * always prefer it over hardcoded color literals. `--doctor` flags
23
+ * layouts that emit nodes with literal hex/rgb fills.
24
+ */
25
+ export interface LayoutContext<C extends object = Record<string, unknown>> {
26
+ /** Buffered, post-filter data the frame is currently drawing. */
27
+ data: Datum[];
28
+ /** Scales constructed by the frame from the resolved x/y domains. */
29
+ scales: StreamScales;
30
+ /**
31
+ * Plot-area geometry. All scene-node coordinates are plot-relative —
32
+ * the canvas/SVG group already lives inside `margin.left`/`margin.top`,
33
+ * so `width`/`height` describe the plot rect (same as `plot.width`/
34
+ * `plot.height`). Read `margin` if you need the outer canvas size.
35
+ */
36
+ dimensions: {
37
+ width: number;
38
+ height: number;
39
+ margin: MarginType;
40
+ plot: {
41
+ x: number;
42
+ y: number;
43
+ width: number;
44
+ height: number;
45
+ };
46
+ };
47
+ /** Theme-resolved semantic colors + categorical palette. */
48
+ theme: {
49
+ semantic: ThemeSemanticColors;
50
+ categorical: string[];
51
+ };
52
+ /**
53
+ * Resolves a color for a given group/category, honoring
54
+ * CategoryColorProvider → colorScheme → theme cascade. Always prefer
55
+ * this over hardcoded literals.
56
+ */
57
+ resolveColor: (group: string, datum?: Datum) => string;
58
+ /** User-supplied config blob threaded through `layoutConfig`. */
59
+ config: C;
60
+ }
61
+ export interface LayoutResult {
62
+ /** Scene nodes to render. Get hit testing, transitions, decay, SSR for free. */
63
+ nodes?: SceneNode[];
64
+ /** SVG overlays composited above the canvas (labels, annotations). */
65
+ overlays?: ReactNode;
66
+ }
67
+ /**
68
+ * Note on extents: customLayout v1 does not return extents. Layouts that
69
+ * need to drive axis domains (e.g. horizon banding a continuous series)
70
+ * should pass `xExtent` / `yExtent` props on the chart — those flow into
71
+ * scale construction *before* the layout runs, so the layout sees correct
72
+ * scales. Layouts that don't use scales (waffle, calendar, treemap) can
73
+ * ignore extents entirely.
74
+ */
75
+ /** Convenience helper: build a Style object that defers fill/stroke to the theme. */
76
+ export declare function themedStyle(color: string, overrides?: Style): Style;
@@ -0,0 +1,29 @@
1
+ import { STREAMING_PALETTE } from "../charts/shared/colorUtils";
2
+ import { schemeCategory10 } from "../charts/shared/colorPalettes";
3
+ /**
4
+ * Shared palette resolution for the network and ordinal customLayout
5
+ * escape hatches. XY's customLayout uses `PipelineStore.resolveGroupColor`
6
+ * (richer cascade with CategoryColorProvider integration) so it doesn't
7
+ * call this helper.
8
+ *
9
+ * Precedence:
10
+ * 1. Explicit `colorScheme` array — used as-is.
11
+ * 2. Named scheme string (e.g. "tableau10") — looked up in
12
+ * `COLOR_SCHEMES`. Unknown names fall through.
13
+ * 3. Theme categorical (when non-empty).
14
+ * 4. The provided fallback palette.
15
+ *
16
+ * @param colorScheme `colorScheme` from the chart's pipeline config
17
+ * @param themeCategorical `themeCategorical` from theme resolution
18
+ * @param fallback Palette to use when nothing else matches.
19
+ * Network passes `schemeCategory10`; ordinal passes
20
+ * `STREAMING_PALETTE`. Caller's choice.
21
+ */
22
+ export declare function resolveCustomLayoutPalette(colorScheme: string | string[] | undefined, themeCategorical: string[] | undefined, fallback: readonly string[]): readonly string[];
23
+ /**
24
+ * Build a stable hash → palette index resolver. Used by the network and
25
+ * ordinal customLayout contexts so the same key always returns the same
26
+ * color for the lifetime of the closure.
27
+ */
28
+ export declare function buildResolveColor(palette: readonly string[]): (key: string) => string;
29
+ export { schemeCategory10, STREAMING_PALETTE };
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { GeoProjection, GeoPath, GeoPermissibleObjects } from "d3-geo";
3
- import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, PointSceneNode, LineSceneNode, ThemeSemanticColors } from "./types";
3
+ import type { GradientLegendConfig, LegendGroup } from "../types/legendTypes";
4
+ import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, SceneDatum, PointSceneNode, ThemeSemanticColors } from "./types";
4
5
  import type { AnimateProp } from "./pipelineTransitionUtils";
5
6
  import type { HoverAnnotationConfig, HoverData } from "../realtime/types";
6
7
  import type { GeoParticleStyle } from "./GeoParticlePool";
@@ -38,7 +39,7 @@ export interface GeoAreaSceneNode {
38
39
  /** Screen-space area in px² */
39
40
  screenArea: number;
40
41
  style: Style;
41
- datum: any;
42
+ datum: SceneDatum;
42
43
  group?: string;
43
44
  interactive?: boolean;
44
45
  /** Lazily-cached Path2D parsed from pathData (avoids re-parsing on every hit test) */
@@ -47,8 +48,15 @@ export interface GeoAreaSceneNode {
47
48
  _pulseIntensity?: number;
48
49
  _pulseColor?: string;
49
50
  }
51
+ export interface GeoLineSceneNode {
52
+ type: "line";
53
+ path: [number, number][];
54
+ style: Style;
55
+ datum: SceneDatum;
56
+ group?: string;
57
+ }
50
58
  /** Union of all scene node types that GeoFrame produces */
51
- export type GeoSceneNode = GeoAreaSceneNode | PointSceneNode | LineSceneNode;
59
+ export type GeoSceneNode = GeoAreaSceneNode | PointSceneNode | GeoLineSceneNode;
52
60
  export interface GeoScales {
53
61
  projection: GeoProjection;
54
62
  geoPath: GeoPath<any, GeoPermissibleObjects>;
@@ -62,7 +70,7 @@ export interface GeoPipelineConfig {
62
70
  fitPadding?: number;
63
71
  xAccessor?: string | ((d: Datum) => number);
64
72
  yAccessor?: string | ((d: Datum) => number);
65
- lineDataAccessor?: string | ((d: Datum) => any[]);
73
+ lineDataAccessor?: string | ((d: Datum) => Datum[]);
66
74
  lineType?: "geo" | "line";
67
75
  /** Flow rendering style: "basic" (straight/great-circle), "offset" (bidirectional offset), "arc" (curved arcs) @default "basic" */
68
76
  flowStyle?: "basic" | "offset" | "arc";
@@ -70,7 +78,7 @@ export interface GeoPipelineConfig {
70
78
  pointStyle?: (d: Datum) => Style & {
71
79
  r?: number;
72
80
  };
73
- lineStyle?: Style | ((d: any, group?: string) => Style);
81
+ lineStyle?: Style | ((d: Datum, group?: string) => Style);
74
82
  colorScheme?: string | string[];
75
83
  /** Theme-resolved semantic role colors — default fallback before hardcoded hex. See `ThemeSemanticColors` in ./types. */
76
84
  themeSemantic?: ThemeSemanticColors;
@@ -98,7 +106,7 @@ export interface StreamGeoFrameProps<T = Datum> {
98
106
  lines?: T[];
99
107
  xAccessor?: string | ((d: T) => number);
100
108
  yAccessor?: string | ((d: T) => number);
101
- lineDataAccessor?: string | ((d: T) => any[]);
109
+ lineDataAccessor?: string | ((d: T) => Datum[]);
102
110
  pointIdAccessor?: string | ((d: T) => string);
103
111
  lineType?: "geo" | "line";
104
112
  /** Flow rendering style: "basic" (straight/great-circle), "offset" (bidirectional offset), "arc" (curved arcs) @default "basic" */
@@ -145,8 +153,17 @@ export interface StreamGeoFrameProps<T = Datum> {
145
153
  pointStyle?: (d: Datum) => Style & {
146
154
  r?: number;
147
155
  };
148
- lineStyle?: Style | ((d: any, group?: string) => Style);
156
+ lineStyle?: Style | ((d: Datum, group?: string) => Style);
149
157
  colorScheme?: string | string[];
158
+ /**
159
+ * Categorical color field. For ChoroplethMap reads from area `properties`
160
+ * (or top-level fallback); for ProportionalSymbolMap reads from each point.
161
+ * Server-side legend auto-build groups by this field when `showLegend` is
162
+ * set and no explicit `legend` prop is provided. The function form accepts
163
+ * either the point datum `T` or a GeoJSON Feature so choropleth callers can
164
+ * write `(f) => f.properties.region` without a cast.
165
+ */
166
+ colorBy?: string | ((d: T | GeoJSON.Feature) => string);
150
167
  enableHover?: boolean;
151
168
  hoverAnnotation?: boolean | HoverAnnotationConfig;
152
169
  tooltipContent?: (d: HoverData) => ReactNode;
@@ -164,7 +181,11 @@ export interface StreamGeoFrameProps<T = Datum> {
164
181
  backgroundGraphics?: ReactNode;
165
182
  foregroundGraphics?: ReactNode;
166
183
  title?: string | ReactNode;
167
- legend?: any;
184
+ legend?: ReactNode | {
185
+ legendGroups: LegendGroup[];
186
+ } | {
187
+ gradient: GradientLegendConfig;
188
+ };
168
189
  legendPosition?: "right" | "left" | "top" | "bottom";
169
190
  legendHoverBehavior?: (item: {
170
191
  label: string;
@@ -174,6 +195,10 @@ export interface StreamGeoFrameProps<T = Datum> {
174
195
  }) => void;
175
196
  legendHighlightedCategory?: string | null;
176
197
  legendIsolatedCategories?: Set<string>;
198
+ /** Accessor used to report the current legend category domain in push mode. */
199
+ legendCategoryAccessor?: string | ((d: T) => string);
200
+ /** Fires when the current legend category domain changes after scene rebuilds. */
201
+ onCategoriesChange?: (categories: string[]) => void;
177
202
  showAxes?: boolean;
178
203
  /** Render a visually-hidden data table from the scene graph for screen readers */
179
204
  accessibleTable?: boolean;
@@ -1,4 +1,3 @@
1
- import type { Datum } from "../charts/shared/datumTypes";
2
1
  /**
3
2
  * Shared hover data utilities for stream frames.
4
3
  *
@@ -20,16 +19,11 @@ export interface HoverPointerCoords {
20
19
  clientX: number;
21
20
  clientY: number;
22
21
  }
23
- /**
24
- * Spread raw datum properties onto HoverData if it's a non-null,
25
- * non-array object. Class instances (Date, etc.) are included —
26
- * this matches the historical behavior where all datum fields are
27
- * accessible directly on the hover object (d.fieldName).
28
- */
29
- export declare function spreadDatum(rawDatum: any): Datum;
30
22
  /**
31
23
  * Build a HoverData object from a raw datum and pixel coordinates.
32
- * Spreads plain-object datum properties for backwards compatibility
33
- * (consumers can access d.fieldName directly in addition to d.data.fieldName).
24
+ * The raw datum is preserved as `hover.data` for tooltip / callback
25
+ * consumers; pixel coordinates land on `x` / `y`. Anything else
26
+ * relevant to a specific frame family — `category`, `stats`,
27
+ * `nodeOrEdge`, `xValue`, etc. — is layered in via `extra`.
34
28
  */
35
29
  export declare function buildHoverData(rawDatum: any, x: number, y: number, extra?: Partial<HoverData>): HoverData;
@@ -10,10 +10,15 @@
10
10
  * HoverData state that mouse hover does.
11
11
  */
12
12
  import type { HoverData } from "../realtime/types";
13
+ import type { Datum } from "../charts/shared/datumTypes";
14
+ import type { NetworkSceneEdge, NetworkSceneNode } from "./networkTypes";
15
+ import type { SceneNode } from "./types";
16
+ import type { OrdinalSceneNode } from "./ordinalTypes";
17
+ import type { GeoSceneNode } from "./geoTypes";
13
18
  export interface NavPoint {
14
19
  x: number;
15
20
  y: number;
16
- datum: any;
21
+ datum: Datum | null;
17
22
  /** Shape hint for focus ring rendering */
18
23
  shape?: "circle" | "rect" | "wedge";
19
24
  /** Width of rect-shaped elements (bars, sankey nodes) */
@@ -73,18 +78,18 @@ export declare function nextGraphIndex(key: string, pos: NavPosition, graph: Nav
73
78
  * Lines/areas carry a `group` field identifying the series.
74
79
  * ArrowRight/Left = within series, ArrowUp/Down = switch series.
75
80
  */
76
- export declare function extractXYNavPoints(scene: any[]): NavPoint[];
81
+ export declare function extractXYNavPoints(scene: SceneNode[]): NavPoint[];
77
82
  /**
78
83
  * Extract navigable points from ordinal scene nodes.
79
84
  * Bars use `node.group` (stack/group key) falling back to `datum.category`.
80
85
  * ArrowRight/Left = across categories, ArrowUp/Down = within stacked segments.
81
86
  */
82
- export declare function extractOrdinalNavPoints(scene: any[]): NavPoint[];
87
+ export declare function extractOrdinalNavPoints(scene: OrdinalSceneNode[]): NavPoint[];
83
88
  /**
84
89
  * Extract navigable points from network scene nodes.
85
90
  * Each node's group is its own id, enabling neighbor traversal via edges.
86
91
  */
87
- export declare function extractNetworkNavPoints(scene: any[]): NavPoint[];
92
+ export declare function extractNetworkNavPoints(scene: NetworkSceneNode[]): NavPoint[];
88
93
  /**
89
94
  * Network-specific navigation: spatial arrow keys + edge following.
90
95
  *
@@ -94,14 +99,20 @@ export declare function extractNetworkNavPoints(scene: any[]): NavPoint[];
94
99
  *
95
100
  * Returns the flat index of the target node, -1 to clear, or null for unhandled keys.
96
101
  */
97
- export declare function nextNetworkIndex(key: string, pos: NavPosition, graph: NavGraph, edges: any[], neighborIndexRef: {
102
+ export declare function nextNetworkIndex(key: string, pos: NavPosition, graph: NavGraph, edges: EdgeLike[], neighborIndexRef: {
98
103
  current: number;
99
104
  }): number | null;
105
+ /** Collect neighbor node ids from edge list for a given node. */
106
+ type EdgeLike = NetworkSceneEdge | {
107
+ source?: unknown;
108
+ target?: unknown;
109
+ datum?: Datum | null;
110
+ };
100
111
  /**
101
112
  * Extract navigable points from geo scene nodes.
102
113
  * Flat navigation only (no meaningful grouping for geo).
103
114
  */
104
- export declare function extractGeoNavPoints(scene: any[]): NavPoint[];
115
+ export declare function extractGeoNavPoints(scene: GeoSceneNode[]): NavPoint[];
105
116
  /**
106
117
  * Compute the next focus index given a key and current index.
107
118
  * Returns -1 to clear focus. Returns null for unhandled keys.
@@ -113,3 +124,4 @@ export declare function nextIndex(key: string, current: number, total: number):
113
124
  * Convert a NavPoint to HoverData for the tooltip system.
114
125
  */
115
126
  export declare function navPointToHover(point: NavPoint): HoverData;
127
+ export {};
@@ -0,0 +1,67 @@
1
+ import type { ReactNode } from "react";
2
+ import type { NetworkSceneNode, NetworkSceneEdge, NetworkLabel, RealtimeNode, RealtimeEdge } from "./networkTypes";
3
+ import type { ThemeSemanticColors } from "./types";
4
+ /**
5
+ * customLayout escape hatch for `StreamNetworkFrame`.
6
+ *
7
+ * A network layout is a pure function: given raw nodes/edges plus the
8
+ * frame's dimensions/theme, return positioned scene primitives — circles,
9
+ * rects, lines, beziers — and optional labels/overlays. The frame still
10
+ * owns hit testing, decay, accessibility, and SSR.
11
+ *
12
+ * Mirrors the XY `CustomLayout` pattern. Reach for it when the catalog
13
+ * (force, sankey, chord, tree, treemap, circle-pack, orbit) doesn't fit
14
+ * — e.g. `d3-flextree`, `dagre`, custom radial layouts.
15
+ */
16
+ export type NetworkCustomLayout<C extends object = Record<string, unknown>> = (ctx: NetworkLayoutContext<C>) => NetworkLayoutResult;
17
+ export interface NetworkLayoutContext<C extends object = Record<string, unknown>> {
18
+ /** Raw nodes from the data prop / push API. May or may not have positions. */
19
+ nodes: RealtimeNode[];
20
+ /** Raw edges. Source/target may be id strings or node references. */
21
+ edges: RealtimeEdge[];
22
+ /**
23
+ * Plot-area geometry. All scene-node coordinates are plot-relative —
24
+ * the canvas/SVG group already lives inside `margin.left`/`margin.top`.
25
+ */
26
+ dimensions: {
27
+ width: number;
28
+ height: number;
29
+ plot: {
30
+ x: number;
31
+ y: number;
32
+ width: number;
33
+ height: number;
34
+ };
35
+ };
36
+ /** Theme-resolved semantic + categorical colors. */
37
+ theme: {
38
+ semantic: ThemeSemanticColors;
39
+ categorical: string[];
40
+ };
41
+ /**
42
+ * Resolves a stable color for a given key (typically a node id or
43
+ * category) by hashing into the frame-resolved categorical palette.
44
+ * The palette comes from `colorScheme` (array or named d3 scheme like
45
+ * `"tableau10"` / `"set3"`), then the active theme's `categorical`,
46
+ * then a fallback. The same key always returns the same color for the
47
+ * lifetime of this store.
48
+ *
49
+ * Note: this does *not* honor `CategoryColorProvider` — network charts
50
+ * don't currently thread that into the pipeline. If you need
51
+ * cross-chart category color sync, pass a matching `colorScheme` to
52
+ * each chart instead.
53
+ */
54
+ resolveColor: (key: string) => string;
55
+ /** User-supplied config blob threaded through `layoutConfig`. */
56
+ config: C;
57
+ }
58
+ export interface NetworkLayoutResult {
59
+ /** Positioned scene primitives. Circles, rects, or arcs. */
60
+ sceneNodes?: NetworkSceneNode[];
61
+ /** Positioned edges. Lines, beziers, ribbons, or curved. */
62
+ sceneEdges?: NetworkSceneEdge[];
63
+ /** Optional labels placed at arbitrary plot-relative positions. */
64
+ labels?: NetworkLabel[];
65
+ /** SVG overlays composited above the canvas. */
66
+ overlays?: ReactNode;
67
+ }
@@ -2,7 +2,7 @@ import type { ReactNode } from "react";
2
2
  import type { OnObservationCallback } from "../store/ObservationStore";
3
3
  import type { HoverData, AnnotationContext } from "../realtime/types";
4
4
  import type { LegendGroup } from "../types/legendTypes";
5
- import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, ThemeSemanticColors } from "./types";
5
+ import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, ThemeSemanticColors, SceneDatum } from "./types";
6
6
  import type { AnimateProp } from "./pipelineTransitionUtils";
7
7
  import type { Datum } from "../charts/shared/datumTypes";
8
8
  export interface TensionConfig {
@@ -40,6 +40,29 @@ export interface RealtimeNode {
40
40
  _pulseIntensity?: number;
41
41
  _pulseColor?: string;
42
42
  _pulseGlowRadius?: number;
43
+ /**
44
+ * @internal Hierarchy-layout-only extension fields. Set by
45
+ * `hierarchyLayoutPlugin` / `orbitLayoutPlugin` during layout and
46
+ * read by `hierarchySceneBuilders`. Typed `unknown` because the d3
47
+ * `HierarchyNode` shape is layout-specific (rectangular, circular,
48
+ * point) — consumers narrow with the structural fields they need.
49
+ */
50
+ __hierarchyNode?: unknown;
51
+ /** @internal Circle-pack layout radius. Set by `hierarchyLayoutPlugin`. */
52
+ __radius?: number;
53
+ /**
54
+ * @internal Chord-layout extension. Carries the start/end angles
55
+ * for the arc segment representing this node, computed by
56
+ * `chordLayoutPlugin` and read by its `buildScene`. Concretely
57
+ * typed (unlike `__hierarchyNode`) because chord is the only
58
+ * layout that writes this field, so the shape is fixed — no
59
+ * narrowing-at-read needed. `__` prefix matches the convention
60
+ * used by `__hierarchyNode` / `__radius` on this same interface.
61
+ */
62
+ __arcData?: {
63
+ startAngle: number;
64
+ endAngle: number;
65
+ };
43
66
  }
44
67
  export interface RealtimeEdge {
45
68
  source: RealtimeNode | string;
@@ -58,7 +81,7 @@ export interface RealtimeEdge {
58
81
  _introFromZero?: boolean;
59
82
  direction?: string;
60
83
  circular?: boolean;
61
- circularPathData?: any;
84
+ circularPathData?: CircularPathData;
62
85
  bezier?: BezierCache;
63
86
  data?: Datum;
64
87
  /** Unique key for this edge (supports parallel edges between same node pair) */
@@ -69,6 +92,17 @@ export interface RealtimeEdge {
69
92
  /** @internal Circular sankey layout fields */
70
93
  _circularWidth?: number;
71
94
  _circularStub?: boolean;
95
+ /**
96
+ * @internal Chord-layout extension. Carries the d3-chord-generated
97
+ * source/target arc spans for this edge, set by `chordLayoutPlugin`
98
+ * during `computeLayout` and read by its `buildScene`. Typed
99
+ * `unknown` because the d3 `Chord` interface lives in `d3-chord`
100
+ * and importing the type here would couple `networkTypes` to that
101
+ * dep — consumers narrow at the read site. `__` prefix matches the
102
+ * `_circularWidth` / `_circularStub` internal-field convention on
103
+ * this same interface.
104
+ */
105
+ __chordData?: unknown;
72
106
  }
73
107
  export interface BezierPoint {
74
108
  x: number;
@@ -80,6 +114,27 @@ export interface BezierCache {
80
114
  segments?: Array<[BezierPoint, BezierPoint, BezierPoint, BezierPoint]>;
81
115
  halfWidth: number;
82
116
  }
117
+ export interface CircularPathData {
118
+ sourceX: number;
119
+ targetX: number;
120
+ sourceY: number;
121
+ targetY: number;
122
+ rightFullExtent: number;
123
+ leftFullExtent: number;
124
+ verticalFullExtent: number;
125
+ rightInnerExtent: number;
126
+ leftInnerExtent: number;
127
+ verticalRightInnerExtent: number;
128
+ verticalLeftInnerExtent: number;
129
+ rightSmallArcRadius: number;
130
+ rightLargeArcRadius: number;
131
+ leftSmallArcRadius: number;
132
+ leftLargeArcRadius: number;
133
+ sourceWidth: number;
134
+ rightNodeBuffer: number;
135
+ leftNodeBuffer: number;
136
+ arcRadius: number;
137
+ }
83
138
  export interface Particle {
84
139
  t: number;
85
140
  offset: number;
@@ -133,7 +188,7 @@ export interface RealtimeNetworkFrameProps {
133
188
  enableHover?: boolean;
134
189
  tooltipContent?: (d: {
135
190
  type: "node" | "edge";
136
- data: any;
191
+ data: Datum | null;
137
192
  }) => ReactNode;
138
193
  onTopologyChange?: (nodes: RealtimeNode[], edges: RealtimeEdge[]) => void;
139
194
  background?: string;
@@ -147,7 +202,7 @@ export interface NetworkCircleNode {
147
202
  cy: number;
148
203
  r: number;
149
204
  style: Style;
150
- datum: any;
205
+ datum: SceneDatum;
151
206
  id?: string;
152
207
  label?: string;
153
208
  depth?: number;
@@ -163,7 +218,7 @@ export interface NetworkRectNode {
163
218
  w: number;
164
219
  h: number;
165
220
  style: Style;
166
- datum: any;
221
+ datum: SceneDatum;
167
222
  id?: string;
168
223
  label?: string;
169
224
  depth?: number;
@@ -184,7 +239,7 @@ export interface NetworkArcNode {
184
239
  /** End angle in radians, canvas convention */
185
240
  endAngle: number;
186
241
  style: Style;
187
- datum: any;
242
+ datum: SceneDatum;
188
243
  id?: string;
189
244
  label?: string;
190
245
  _pulseIntensity?: number;
@@ -199,7 +254,7 @@ export interface NetworkLineEdge {
199
254
  x2: number;
200
255
  y2: number;
201
256
  style: Style;
202
- datum: any;
257
+ datum: SceneDatum;
203
258
  _pulseIntensity?: number;
204
259
  _pulseColor?: string;
205
260
  }
@@ -209,7 +264,7 @@ export interface NetworkBezierEdge {
209
264
  pathD: string;
210
265
  bezierCache?: BezierCache;
211
266
  style: Style;
212
- datum: any;
267
+ datum: SceneDatum;
213
268
  _pulseIntensity?: number;
214
269
  _pulseColor?: string;
215
270
  /** Lazily-built Path2D for hit testing; invalidated when pathD changes. */
@@ -221,7 +276,7 @@ export interface NetworkRibbonEdge {
221
276
  type: "ribbon";
222
277
  pathD: string;
223
278
  style: Style;
224
- datum: any;
279
+ datum: SceneDatum;
225
280
  _pulseIntensity?: number;
226
281
  _pulseColor?: string;
227
282
  _cachedPath2D?: Path2D;
@@ -232,7 +287,7 @@ export interface NetworkCurvedEdge {
232
287
  type: "curved";
233
288
  pathD: string;
234
289
  style: Style;
235
- datum: any;
290
+ datum: SceneDatum;
236
291
  _pulseIntensity?: number;
237
292
  _pulseColor?: string;
238
293
  _cachedPath2D?: Path2D;
@@ -306,18 +361,18 @@ export interface NetworkPipelineConfig {
306
361
  valueAccessor?: string | ((d: Datum) => number);
307
362
  /** Edge ID accessor for removeEdge(edgeId) — enables single-ID edge removal */
308
363
  edgeIdAccessor?: string | ((d: Datum) => string);
309
- childrenAccessor?: string | ((d: Datum) => any[]);
364
+ childrenAccessor?: string | ((d: Datum) => Datum[]);
310
365
  hierarchySum?: string | ((d: Datum) => number);
311
366
  orientation?: "horizontal" | "vertical";
312
367
  nodeAlign?: "justify" | "left" | "right" | "center";
313
368
  nodePaddingRatio?: number;
314
369
  nodeWidth?: number;
315
- edgeSort?: (a: any, b: any) => number;
370
+ edgeSort?: (a: unknown, b: unknown) => number;
316
371
  iterations?: number;
317
372
  forceStrength?: number;
318
373
  padAngle?: number;
319
374
  groupWidth?: number;
320
- sortGroups?: (a: any, b: any) => number;
375
+ sortGroups?: (a: unknown, b: unknown) => number;
321
376
  treeOrientation?: "vertical" | "horizontal" | "radial";
322
377
  edgeType?: "line" | "curve";
323
378
  padding?: number;
@@ -352,11 +407,11 @@ export interface NetworkPipelineConfig {
352
407
  * "atomic" ([2,8] electron shell), or custom capacities. @default "flat" */
353
408
  orbitMode?: "flat" | "solar" | "atomic" | number[];
354
409
  /** Ring size divisor per depth. Larger = tighter orbits. @default 2.95 */
355
- orbitSize?: number | ((node: any) => number);
410
+ orbitSize?: number | ((node: Datum) => number);
356
411
  /** Orbit speed multiplier (higher = faster rotation). @default 0.25 */
357
412
  orbitSpeed?: number;
358
413
  /** Per-node speed modifier. @default (node) => 1 / (node.depth + 1) */
359
- orbitRevolution?: (node: any) => number;
414
+ orbitRevolution?: (node: Datum) => number;
360
415
  /**
361
416
  * Built-in revolution style presets:
362
417
  * - "locked": children rotate with parent at decreasing speed (default)
@@ -367,7 +422,7 @@ export interface NetworkPipelineConfig {
367
422
  */
368
423
  orbitRevolutionStyle?: "locked" | "decay" | "alternate";
369
424
  /** Vertical squash for elliptical orbits. 1 = circle. @default 1 */
370
- orbitEccentricity?: number | ((node: any) => number);
425
+ orbitEccentricity?: number | ((node: Datum) => number);
371
426
  /** Show orbital ring ellipses as foreground graphics. @default true */
372
427
  orbitShowRings?: boolean;
373
428
  /** Enable orbit animation. @default true */
@@ -381,6 +436,11 @@ export interface NetworkPipelineConfig {
381
436
  x: number;
382
437
  y: number;
383
438
  }>;
439
+ /** When provided, replaces both layout dispatch and scene building.
440
+ * Receives raw nodes/edges and returns positioned scene primitives. */
441
+ customNetworkLayout?: import("./networkCustomLayout").NetworkCustomLayout;
442
+ /** User-supplied config blob threaded through to NetworkLayoutContext.config. */
443
+ layoutConfig?: object;
384
444
  }
385
445
  export interface StreamNetworkFrameProps<T = Datum> {
386
446
  chartType: NetworkChartType;
@@ -405,8 +465,8 @@ export interface StreamNetworkFrameProps<T = Datum> {
405
465
  forceStrength?: number;
406
466
  padAngle?: number;
407
467
  groupWidth?: number;
408
- sortGroups?: (a: any, b: any) => number;
409
- edgeSort?: (a: any, b: any) => number;
468
+ sortGroups?: (a: unknown, b: unknown) => number;
469
+ edgeSort?: (a: unknown, b: unknown) => number;
410
470
  treeOrientation?: "vertical" | "horizontal" | "radial";
411
471
  edgeType?: "line" | "curve";
412
472
  padding?: number;
@@ -473,11 +533,11 @@ export interface StreamNetworkFrameProps<T = Datum> {
473
533
  staleness?: StalenessConfig;
474
534
  thresholds?: ThresholdAlertConfig;
475
535
  orbitMode?: "flat" | "solar" | "atomic" | number[];
476
- orbitSize?: number | ((node: any) => number);
536
+ orbitSize?: number | ((node: Datum) => number);
477
537
  orbitSpeed?: number;
478
- orbitRevolution?: (node: any) => number;
538
+ orbitRevolution?: (node: Datum) => number;
479
539
  orbitRevolutionStyle?: "locked" | "decay" | "alternate";
480
- orbitEccentricity?: number | ((node: any) => number);
540
+ orbitEccentricity?: number | ((node: Datum) => number);
481
541
  orbitShowRings?: boolean;
482
542
  orbitAnimated?: boolean;
483
543
  /** Render a visually-hidden data table from the scene graph for screen readers */
@@ -486,6 +546,12 @@ export interface StreamNetworkFrameProps<T = Datum> {
486
546
  description?: string;
487
547
  /** Accessible summary rendered as a screen-reader-only note */
488
548
  summary?: string;
549
+ /** Replaces network layout + scene dispatch with a user-supplied function.
550
+ * Receives raw nodes/edges + dimensions/theme, returns positioned scene
551
+ * primitives. See `semiotic/recipes` for reference layouts (flextree, dagre). */
552
+ customNetworkLayout?: import("./networkCustomLayout").NetworkCustomLayout;
553
+ /** User-supplied config blob threaded through to NetworkLayoutContext.config. */
554
+ layoutConfig?: object;
489
555
  }
490
556
  export interface StreamNetworkFrameHandle {
491
557
  push(edge: EdgePush): void;