semiotic 3.7.0 → 3.7.2

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 (70) hide show
  1. package/CLAUDE.md +3 -2
  2. package/README.md +46 -7
  3. package/ai/behaviorContracts.cjs +19 -9
  4. package/ai/cli.js +15 -0
  5. package/ai/dist/mcp-server.js +583 -66
  6. package/ai/schema.json +1 -1
  7. package/ai/system-prompt.md +3 -3
  8. package/dist/components/AccessibleNavTree.d.ts +2 -1
  9. package/dist/components/Annotation.d.ts +1 -1
  10. package/dist/components/CategoryColors.d.ts +1 -1
  11. package/dist/components/ChartGrid.d.ts +1 -1
  12. package/dist/components/ContextLayout.d.ts +1 -1
  13. package/dist/components/DataSummaryContext.d.ts +1 -1
  14. package/dist/components/DetailsPanel.d.ts +1 -1
  15. package/dist/components/Legend.d.ts +3 -2
  16. package/dist/components/LinkedCharts.d.ts +1 -1
  17. package/dist/components/ThemeProvider.d.ts +1 -1
  18. package/dist/components/Tooltip/FlippingTooltip.d.ts +1 -1
  19. package/dist/components/Tooltip/Tooltip.d.ts +2 -2
  20. package/dist/components/ai/qualityScorecard.d.ts +11 -0
  21. package/dist/components/charts/geo/ChoroplethMap.d.ts +2 -1
  22. package/dist/components/charts/network/CirclePack.d.ts +2 -1
  23. package/dist/components/charts/network/OrbitDiagram.d.ts +1 -1
  24. package/dist/components/charts/network/TreeDiagram.d.ts +2 -1
  25. package/dist/components/charts/network/Treemap.d.ts +2 -1
  26. package/dist/components/charts/realtime/RealtimeHistogram.d.ts +1 -1
  27. package/dist/components/charts/shared/ChartError.d.ts +2 -1
  28. package/dist/components/charts/shared/withChartWrapper.d.ts +1 -1
  29. package/dist/components/charts/xy/MinimapChart.d.ts +2 -1
  30. package/dist/components/charts/xy/ScatterplotMatrix.d.ts +2 -1
  31. package/dist/components/semiotic-server.d.ts +2 -1
  32. package/dist/components/server/renderEvidence.d.ts +92 -0
  33. package/dist/components/server/renderToStaticSVG.d.ts +14 -1
  34. package/dist/components/stream/AccessibleDataTable.d.ts +5 -5
  35. package/dist/components/stream/FocusRing.d.ts +2 -1
  36. package/dist/components/stream/MarginalGraphics.d.ts +2 -1
  37. package/dist/components/stream/NetworkCanvasHitTester.d.ts +3 -2
  38. package/dist/components/stream/NetworkPipelineStore.d.ts +46 -1
  39. package/dist/components/stream/NetworkSVGOverlay.d.ts +2 -1
  40. package/dist/components/stream/OrdinalBrushOverlay.d.ts +19 -1
  41. package/dist/components/stream/OrdinalSVGOverlay.d.ts +2 -2
  42. package/dist/components/stream/PipelineStore.d.ts +6 -0
  43. package/dist/components/stream/SVGOverlay.d.ts +3 -2
  44. package/dist/components/stream/StalenessBadge.d.ts +19 -0
  45. package/dist/components/stream/XYBrushOverlay.d.ts +21 -1
  46. package/dist/components/stream/quadtreeHitTest.d.ts +7 -1
  47. package/dist/geo.min.js +1 -1
  48. package/dist/geo.module.min.js +1 -1
  49. package/dist/network.min.js +1 -1
  50. package/dist/network.module.min.js +1 -1
  51. package/dist/ordinal.min.js +1 -1
  52. package/dist/ordinal.module.min.js +1 -1
  53. package/dist/realtime.min.js +1 -1
  54. package/dist/realtime.module.min.js +1 -1
  55. package/dist/semiotic-ai.min.js +1 -1
  56. package/dist/semiotic-ai.module.min.js +1 -1
  57. package/dist/semiotic-server.d.ts +2 -1
  58. package/dist/semiotic-themes.min.js +1 -1
  59. package/dist/semiotic-themes.module.min.js +1 -1
  60. package/dist/semiotic-utils.min.js +1 -1
  61. package/dist/semiotic-utils.module.min.js +1 -1
  62. package/dist/semiotic-value.min.js +1 -1
  63. package/dist/semiotic-value.module.min.js +1 -1
  64. package/dist/semiotic.min.js +1 -1
  65. package/dist/semiotic.module.min.js +1 -1
  66. package/dist/server.min.js +1 -1
  67. package/dist/server.module.min.js +1 -1
  68. package/dist/xy.min.js +1 -1
  69. package/dist/xy.module.min.js +1 -1
  70. package/package.json +2 -2
package/ai/schema.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "name": "semiotic",
4
- "version": "3.7.0",
4
+ "version": "3.7.2",
5
5
  "description": "React data visualization library for charts, networks, and beyond",
6
6
  "tools": [
7
7
  {
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- semiotic-bundle-sizes:start -->
4
4
  <!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
5
- **Use sub-path imports** — `semiotic/xy` (90KB gz), `semiotic/ordinal` (74KB gz), `semiotic/network` (68KB gz), `semiotic/geo` (55KB gz), `semiotic/realtime` (95KB gz), `semiotic/server` (127KB gz), `semiotic/utils` (37KB gz), `semiotic/recipes` (9KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (6KB gz), `semiotic/ai` (246KB gz). Full `semiotic` is 203KB gz.
5
+ **Use sub-path imports** — `semiotic/xy` (90KB gz), `semiotic/ordinal` (74KB gz), `semiotic/network` (68KB gz), `semiotic/geo` (55KB gz), `semiotic/realtime` (95KB gz), `semiotic/server` (128KB gz), `semiotic/utils` (38KB gz), `semiotic/recipes` (9KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/value` (6KB gz), `semiotic/ai` (250KB gz). Full `semiotic` is 203KB gz.
6
6
  <!-- semiotic-bundle-sizes:end -->
7
7
 
8
8
  ## Flat Array Data (`data: object[]`)
@@ -140,7 +140,7 @@ These rules are generated from `ai/behaviorContracts.cjs` and are consumed by `s
140
140
 
141
141
  ## Key Patterns
142
142
  - **Percentile band + main line**: Layer `<AreaChart yAccessor="p95" y0Accessor="p5" showLine={false} />` + `<LineChart yAccessor="p50" />`. AreaChart's `showLine` only draws the top edge, NOT a separate main line.
143
- - **SSR**: `renderChart("BarChart", props)` from `semiotic/server` — uses HOC names. Also `"Sparkline"` (no axes, 2px margins). `renderToImage()` (PNG), `renderToAnimatedGif()` (GIF), `renderDashboard()` (multi-chart). All accept `theme`. Required props: StackedBarChart needs `stackBy`, GroupedBarChart needs `groupBy`, StackedAreaChart needs `areaBy`, BubbleChart needs `sizeBy`, FunnelChart uses `stepAccessor`, GaugeChart needs `value` (`thresholds` optional).
143
+ - **SSR**: `renderChart("BarChart", props)` from `semiotic/server` — uses HOC names. Also `"Sparkline"` (no axes, 2px margins). `renderChartWithEvidence()` returns `{ svg, evidence }` (mark counts by scene type, axis domains, empty flag, annotation count, accessible name) so agents can verify the render drew data marks. `renderToImage()` (PNG), `renderToAnimatedGif()` (GIF), `renderDashboard()` (multi-chart). All accept `theme`. Required props: StackedBarChart needs `stackBy`, GroupedBarChart needs `groupBy`, StackedAreaChart needs `areaBy`, BubbleChart needs `sizeBy`, FunnelChart uses `stepAccessor`, GaugeChart needs `value` (`thresholds` optional).
144
144
  - **CLI**: `npx semiotic-ai --list` shows components/import paths/renderability; `npx semiotic-ai --schema GaugeChart` prints one component schema with metadata; `--doctor` validates props JSON and behavior contracts.
145
- - **MCP**: `npx semiotic-mcp` exposes tools (`getSchema`, `suggestChart`, `diagnoseConfig`, `renderChart`, `applyTheme`, `reportIssue`), resources (`semiotic://schema`, `semiotic://components`, `semiotic://behavior-contracts`, `semiotic://system-prompt`, `semiotic://examples`), and prompts (`build-semiotic-chart`, `debug-semiotic-chart`).
145
+ - **MCP**: `npx semiotic-mcp` exposes schema, suggestion, diagnosis, accessibility, grounding, issue, theme, static render (`renderChart`), and ChatGPT Apps render (`renderInteractiveChart`) tools. Resources include `semiotic://schema`, `semiotic://components`, `semiotic://behavior-contracts`, `semiotic://system-prompt`, `semiotic://examples`, and the widget template `ui://semiotic/chart-widget.html`. Prompts: `build-semiotic-chart`, `debug-semiotic-chart`.
146
146
  - **exportChart**: Pass the wrapper div, not the SVG element: `exportChart(wrapperDiv, { format: "png" })`. It finds canvas+SVG internally.
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  import { type NavTreeNode } from "./ai/navigationTree";
2
3
  export interface AccessibleNavTreeProps {
3
4
  tree: NavTreeNode;
@@ -22,4 +23,4 @@ export interface AccessibleNavTreeProps {
22
23
  */
23
24
  chartId?: string;
24
25
  }
25
- export declare function AccessibleNavTree({ tree, label, visible, className, onActiveChange, activeId: controlledActiveId, chartId }: AccessibleNavTreeProps): import("react/jsx-runtime").JSX.Element;
26
+ export declare function AccessibleNavTree({ tree, label, visible, className, onActiveChange, activeId: controlledActiveId, chartId }: AccessibleNavTreeProps): React.JSX.Element;
@@ -65,5 +65,5 @@ export interface AnnotationProps {
65
65
  [key: string]: unknown;
66
66
  };
67
67
  }
68
- export default function SemioticAnnotation(props: AnnotationProps): import("react/jsx-runtime").JSX.Element;
68
+ export default function SemioticAnnotation(props: AnnotationProps): React.JSX.Element;
69
69
  export {};
@@ -37,7 +37,7 @@ export interface CategoryColorProviderProps {
37
37
  * </CategoryColorProvider>
38
38
  * ```
39
39
  */
40
- export declare function CategoryColorProvider({ colors, categories, colorScheme, children, }: CategoryColorProviderProps): import("react/jsx-runtime").JSX.Element;
40
+ export declare function CategoryColorProvider({ colors, categories, colorScheme, children, }: CategoryColorProviderProps): React.JSX.Element;
41
41
  export declare namespace CategoryColorProvider {
42
42
  var displayName: string;
43
43
  }
@@ -33,7 +33,7 @@ export interface ChartGridProps {
33
33
  * </ChartGrid>
34
34
  * ```
35
35
  */
36
- export declare function ChartGrid({ children, columns, minCellWidth, gap, className, style, }: ChartGridProps): import("react/jsx-runtime").JSX.Element;
36
+ export declare function ChartGrid({ children, columns, minCellWidth, gap, className, style, }: ChartGridProps): React.JSX.Element;
37
37
  export declare namespace ChartGrid {
38
38
  var displayName: string;
39
39
  }
@@ -32,7 +32,7 @@ export interface ContextLayoutProps {
32
32
  * </ContextLayout>
33
33
  * ```
34
34
  */
35
- export declare function ContextLayout({ children, context, position, contextSize, gap, className, style, }: ContextLayoutProps): import("react/jsx-runtime").JSX.Element;
35
+ export declare function ContextLayout({ children, context, position, contextSize, gap, className, style, }: ContextLayoutProps): React.JSX.Element;
36
36
  export declare namespace ContextLayout {
37
37
  var displayName: string;
38
38
  }
@@ -6,7 +6,7 @@ interface DataSummaryState {
6
6
  }
7
7
  export declare function DataSummaryProvider({ children }: {
8
8
  children: React.ReactNode;
9
- }): import("react/jsx-runtime").JSX.Element;
9
+ }): React.JSX.Element;
10
10
  export declare function useDataSummary(): DataSummaryState | null;
11
11
  export declare function useDataSummaryToggle(): (() => void) | null;
12
12
  export {};
@@ -32,7 +32,7 @@ export interface DetailsPanelProps {
32
32
  /** Inline style overrides */
33
33
  style?: React.CSSProperties;
34
34
  }
35
- export declare function DetailsPanel({ children, position, size, trigger, chartId, observation: directObservation, dismissOnEmpty, showClose, onToggle, className, style, }: DetailsPanelProps): import("react/jsx-runtime").JSX.Element | null;
35
+ export declare function DetailsPanel({ children, position, size, trigger, chartId, observation: directObservation, dismissOnEmpty, showClose, onToggle, className, style, }: DetailsPanelProps): React.JSX.Element | null;
36
36
  export declare namespace DetailsPanel {
37
37
  var displayName: string;
38
38
  }
@@ -1,8 +1,9 @@
1
+ import * as React from "react";
1
2
  import { LegendProps, GradientLegendConfig } from "./types/legendTypes";
2
3
  /** Gradient legend for continuous/sequential color scales */
3
4
  export declare function GradientLegend({ config, orientation, width, }: {
4
5
  config: GradientLegendConfig;
5
6
  orientation?: "vertical" | "horizontal";
6
7
  width?: number;
7
- }): import("react/jsx-runtime").JSX.Element;
8
- export default function Legend(props: LegendProps): import("react/jsx-runtime").JSX.Element;
8
+ }): React.JSX.Element;
9
+ export default function Legend(props: LegendProps): React.JSX.Element;
@@ -86,4 +86,4 @@ export declare function estimateLegendRowCount(labels: string[], width: number):
86
86
  * </LinkedCharts>
87
87
  * ```
88
88
  */
89
- export declare function LinkedCharts({ children, selections, showLegend, legendPosition, legendInteraction, legendSelectionName, legendField, }: LinkedChartsProps): import("react/jsx-runtime").JSX.Element;
89
+ export declare function LinkedCharts({ children, selections, showLegend, legendPosition, legendInteraction, legendSelectionName, legendField, }: LinkedChartsProps): React.JSX.Element;
@@ -7,7 +7,7 @@ interface ThemeProviderProps {
7
7
  theme?: ThemePresetName | SemioticThemeUpdate;
8
8
  children: React.ReactNode;
9
9
  }
10
- declare function ThemeProviderWrapper({ theme, children }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
10
+ declare function ThemeProviderWrapper({ theme, children }: ThemeProviderProps): React.JSX.Element;
11
11
  declare function useTheme(): SemioticTheme;
12
12
  export { ThemeProviderWrapper as ThemeProvider, useTheme };
13
13
  export { LIGHT_THEME, DARK_THEME, HIGH_CONTRAST_THEME };
@@ -45,5 +45,5 @@ interface FlippingTooltipProps {
45
45
  * guard, React throws `'NaN' is an invalid value for the 'top' css
46
46
  * style property` and the entire frame stops rendering.
47
47
  */
48
- export declare function FlippingTooltip({ x, y, containerWidth, containerHeight, margin, children, className, zIndex }: FlippingTooltipProps): import("react/jsx-runtime").JSX.Element | null;
48
+ export declare function FlippingTooltip({ x, y, containerWidth, containerHeight, margin, children, className, zIndex }: FlippingTooltipProps): React.JSX.Element | null;
49
49
  export {};
@@ -88,7 +88,7 @@ export declare const defaultTooltipStyle: React.CSSProperties;
88
88
  * />
89
89
  * ```
90
90
  */
91
- export declare function Tooltip(config?: TooltipConfig): (data: Record<string, unknown>) => import("react/jsx-runtime").JSX.Element | null;
91
+ export declare function Tooltip(config?: TooltipConfig): (data: Record<string, unknown>) => React.JSX.Element | null;
92
92
  /**
93
93
  * Create a multi-line tooltip that displays multiple fields
94
94
  *
@@ -131,7 +131,7 @@ export declare function Tooltip(config?: TooltipConfig): (data: Record<string, u
131
131
  * />
132
132
  * ```
133
133
  */
134
- export declare function MultiLineTooltip(config?: MultiLineTooltipConfig): (data: Record<string, unknown>) => import("react/jsx-runtime").JSX.Element | null;
134
+ export declare function MultiLineTooltip(config?: MultiLineTooltipConfig): (data: Record<string, unknown>) => React.JSX.Element | null;
135
135
  /**
136
136
  * Type for tooltip prop that chart components accept
137
137
  */
@@ -30,6 +30,8 @@ export interface PerCapabilityScore {
30
30
  rejectedOn: number;
31
31
  /** Number of fixtures where this capability appeared in the top-3 ranked suggestions. */
32
32
  inTopThreeOn: number;
33
+ /** Number of fixtures where this capability was the #1 ranked suggestion. */
34
+ topPickOn: number;
33
35
  /** Fixtures where the human expert picked this chart AND it was in top-3 ranking. */
34
36
  expertAgreementCount: number;
35
37
  /** Mean composite score across fixtures where it fit. */
@@ -58,6 +60,10 @@ export interface PerFixtureScore {
58
60
  rejectedCount: number;
59
61
  /** True if the top-3 ranking contained at least one expected component (when expected is provided). */
60
62
  expertAgreement: boolean | null;
63
+ /** True if the #1 ranked suggestion was an expected component — the strict
64
+ * form of agreement. Reported alongside the lenient top-3 form so the
65
+ * scorecard can't flatter itself with close-second behavior. */
66
+ topPickAgreement: boolean | null;
61
67
  /** Did the engine honor `expectsNoFit`? */
62
68
  noFitHonored: boolean | null;
63
69
  }
@@ -69,6 +75,11 @@ export interface ScorecardReport {
69
75
  capabilityCount: number;
70
76
  /** Fraction of expectation-bearing fixtures where the engine agreed with the expert. */
71
77
  expertAgreementRate: number;
78
+ /** Strict agreement: fraction of expectation-bearing fixtures where the
79
+ * engine's #1 pick was an expert pick. Always reported next to the
80
+ * lenient top-3 rate — the gap between the two is the honest measure of
81
+ * how often the engine is merely "not completely wrong." */
82
+ top1AgreementRate: number;
72
83
  /** Average caveat coverage across all suggestions. */
73
84
  overallCaveatCoverage: number;
74
85
  /** Average variant utilization across all suggestions. */
@@ -1,4 +1,5 @@
1
1
  import type { Datum } from "../shared/datumTypes";
2
+ import * as React from "react";
2
3
  import type { StreamGeoFrameProps, ProjectionProp } from "../../stream/geoTypes";
3
4
  import type { BaseChartProps, ChartAccessor } from "../shared/types";
4
5
  import { type TooltipProp } from "../../Tooltip/Tooltip";
@@ -138,7 +139,7 @@ export interface ChoroplethMapProps<TDatum extends Datum = Datum> extends BaseCh
138
139
  * `colorScheme`. For diverging data (positive/negative around zero), use
139
140
  * a diverging scheme name and pass `frameProps={{ colorDomain: [-max, max] }}`.
140
141
  */
141
- export declare function ChoroplethMap<TDatum extends Datum = Datum>(props: ChoroplethMapProps<TDatum>): import("react/jsx-runtime").JSX.Element;
142
+ export declare function ChoroplethMap<TDatum extends Datum = Datum>(props: ChoroplethMapProps<TDatum>): React.JSX.Element;
142
143
  export declare namespace ChoroplethMap {
143
144
  var displayName: string;
144
145
  }
@@ -1,4 +1,5 @@
1
1
  import type { Datum } from "../shared/datumTypes";
2
+ import * as React from "react";
2
3
  import type { StreamNetworkFrameProps } from "../../stream/networkTypes";
3
4
  import type { BaseChartProps, ChartAccessor } from "../shared/types";
4
5
  import { type TooltipProp } from "../../Tooltip/Tooltip";
@@ -63,7 +64,7 @@ export interface CirclePackProps<TNode extends Datum = Datum> extends BaseChartP
63
64
  * />
64
65
  * ```
65
66
  */
66
- export declare function CirclePack<TNode extends Datum = Datum>(props: CirclePackProps<TNode>): import("react/jsx-runtime").JSX.Element;
67
+ export declare function CirclePack<TNode extends Datum = Datum>(props: CirclePackProps<TNode>): React.JSX.Element;
67
68
  export declare namespace CirclePack {
68
69
  var displayName: string;
69
70
  }
@@ -110,7 +110,7 @@ export interface OrbitDiagramProps<TDatum extends Datum = Datum> extends BaseCha
110
110
  * />
111
111
  * ```
112
112
  */
113
- export declare function OrbitDiagram<TDatum extends Datum = Datum>(props: OrbitDiagramProps<TDatum>): import("react/jsx-runtime").JSX.Element;
113
+ export declare function OrbitDiagram<TDatum extends Datum = Datum>(props: OrbitDiagramProps<TDatum>): React.JSX.Element;
114
114
  export declare namespace OrbitDiagram {
115
115
  var displayName: string;
116
116
  }
@@ -1,4 +1,5 @@
1
1
  import type { Datum } from "../shared/datumTypes";
2
+ import * as React from "react";
2
3
  import type { StreamNetworkFrameProps } from "../../stream/networkTypes";
3
4
  import type { BaseChartProps, ChartAccessor } from "../shared/types";
4
5
  import { type TooltipProp } from "../../Tooltip/Tooltip";
@@ -65,7 +66,7 @@ export interface TreeDiagramProps<TNode extends Datum = Datum> extends BaseChart
65
66
  * />
66
67
  * ```
67
68
  */
68
- export declare function TreeDiagram<TNode extends Datum = Datum>(props: TreeDiagramProps<TNode>): import("react/jsx-runtime").JSX.Element;
69
+ export declare function TreeDiagram<TNode extends Datum = Datum>(props: TreeDiagramProps<TNode>): React.JSX.Element;
69
70
  export declare namespace TreeDiagram {
70
71
  var displayName: string;
71
72
  }
@@ -1,4 +1,5 @@
1
1
  import type { Datum } from "../shared/datumTypes";
2
+ import * as React from "react";
2
3
  import type { StreamNetworkFrameProps } from "../../stream/networkTypes";
3
4
  import type { BaseChartProps, ChartAccessor } from "../shared/types";
4
5
  import { type TooltipProp } from "../../Tooltip/Tooltip";
@@ -71,7 +72,7 @@ export interface TreemapProps<TNode extends Datum = Datum> extends BaseChartProp
71
72
  * />
72
73
  * ```
73
74
  */
74
- export declare function Treemap<TNode extends Datum = Datum>(props: TreemapProps<TNode>): import("react/jsx-runtime").JSX.Element;
75
+ export declare function Treemap<TNode extends Datum = Datum>(props: TreemapProps<TNode>): React.JSX.Element;
75
76
  export declare namespace Treemap {
76
77
  var displayName: string;
77
78
  }
@@ -196,7 +196,7 @@ export interface TemporalHistogramProps<TDatum extends Datum = Datum> extends Om
196
196
  * bounded array rather than a ref-driven stream; the realtime push API is not
197
197
  * part of this public surface.
198
198
  */
199
- export declare function TemporalHistogram<TDatum extends Datum = Datum>(props: TemporalHistogramProps<TDatum>): import("react/jsx-runtime").JSX.Element;
199
+ export declare function TemporalHistogram<TDatum extends Datum = Datum>(props: TemporalHistogramProps<TDatum>): React.JSX.Element;
200
200
  export declare namespace TemporalHistogram {
201
201
  var displayName: string;
202
202
  }
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  export interface ChartErrorProps {
2
3
  /** Component name for the error message */
3
4
  componentName: string;
@@ -17,4 +18,4 @@ export interface ChartErrorProps {
17
18
  * Designed to be obvious in development but not alarming in production —
18
19
  * uses muted colors that adapt to light/dark backgrounds.
19
20
  */
20
- export default function ChartError({ componentName, message, diagnosticHint, width, height, }: ChartErrorProps): import("react/jsx-runtime").JSX.Element;
21
+ export default function ChartError({ componentName, message, diagnosticHint, width, height, }: ChartErrorProps): React.JSX.Element;
@@ -20,7 +20,7 @@ interface SafeRenderProps {
20
20
  * map into every subpath import — it would add ~7KB gz to xy/ordinal/
21
21
  * network just to power a fallback that only fires when render throws.
22
22
  */
23
- export declare function SafeRender({ componentName, width, height, children }: SafeRenderProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function SafeRender({ componentName, width, height, children }: SafeRenderProps): React.JSX.Element;
24
24
  /**
25
25
  * Renders a "No data available" placeholder when data is empty.
26
26
  * Returns null when data is present or emptyContent is `false`.
@@ -1,4 +1,5 @@
1
1
  import type { Datum } from "../shared/datumTypes";
2
+ import * as React from "react";
2
3
  import type { StreamXYFrameProps } from "../../stream/types";
3
4
  import type { LegendPosition } from "../shared/hooks";
4
5
  import type { BaseChartProps, AxisConfig, ChartAccessor } from "../shared/types";
@@ -128,7 +129,7 @@ export interface MinimapChartProps<TDatum extends Datum = Datum> extends Omit<Ba
128
129
  * />
129
130
  * ```
130
131
  */
131
- export declare function MinimapChart<TDatum extends Datum = Datum>(props: MinimapChartProps<TDatum>): import("react/jsx-runtime").JSX.Element;
132
+ export declare function MinimapChart<TDatum extends Datum = Datum>(props: MinimapChartProps<TDatum>): React.JSX.Element;
132
133
  export declare namespace MinimapChart {
133
134
  var displayName: string;
134
135
  }
@@ -1,4 +1,5 @@
1
1
  import type { Datum } from "../shared/datumTypes";
2
+ import * as React from "react";
2
3
  import type { BaseChartProps, ChartAccessor } from "../shared/types";
3
4
  import { type TooltipProp } from "../../Tooltip/Tooltip";
4
5
  export interface ScatterplotMatrixProps<TDatum extends Datum = Datum> extends BaseChartProps {
@@ -81,7 +82,7 @@ export interface ScatterplotMatrixProps<TDatum extends Datum = Datum> extends Ba
81
82
  * />
82
83
  * ```
83
84
  */
84
- export declare function ScatterplotMatrix<TDatum extends Datum = Datum>(props: ScatterplotMatrixProps<TDatum>): import("react/jsx-runtime").JSX.Element;
85
+ export declare function ScatterplotMatrix<TDatum extends Datum = Datum>(props: ScatterplotMatrixProps<TDatum>): React.JSX.Element;
85
86
  export declare namespace ScatterplotMatrix {
86
87
  var displayName: string;
87
88
  }
@@ -1,4 +1,5 @@
1
- export { renderToStaticSVG, renderXYToStaticSVG, renderOrdinalToStaticSVG, renderNetworkToStaticSVG, renderGeoToStaticSVG, renderChart, renderToImage, renderDashboard, } from "./server/renderToStaticSVG";
1
+ export { renderToStaticSVG, renderXYToStaticSVG, renderOrdinalToStaticSVG, renderNetworkToStaticSVG, renderGeoToStaticSVG, renderChart, renderChartWithEvidence, renderToImage, renderDashboard, } from "./server/renderToStaticSVG";
2
+ export type { RenderEvidence } from "./server/renderEvidence";
2
3
  export type { RenderToImageOptions, DashboardChart, DashboardLayout, RenderDashboardOptions, } from "./server/renderToStaticSVG";
3
4
  export type { LegendLayout } from "./types/legendTypes";
4
5
  export { renderToAnimatedGif, generateFrameSVGs, generateFrameSequence } from "./server/animatedGif";
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Render evidence — machine-readable ground truth about what a server render
3
+ * actually produced, emitted from the same scene the SVG converter walks.
4
+ *
5
+ * The chart-reading literature's consistent failure mode is models
6
+ * hallucinating about what a chart contains — worst of all about what is
7
+ * *absent* from it. Render evidence is the artifact an agent can quote
8
+ * instead of trusting its eyes: did marks render, how many, of what kind,
9
+ * over what domains. It is computed during `renderChartWithEvidence`
10
+ * (`semiotic/server`) and returned alongside the SVG through the MCP
11
+ * `renderChart` tool, so repair loops can react to "this rendered zero data
12
+ * marks" without pixel inspection.
13
+ *
14
+ * Evidence reflects the *rendered scene*, never the input props — that is
15
+ * the point. A config can be valid and still render empty; evidence is how
16
+ * that difference becomes visible to a non-visual caller.
17
+ */
18
+ export interface RenderEvidence {
19
+ /** HOC component name as passed to renderChart. */
20
+ component: string;
21
+ frameType: "xy" | "ordinal" | "network" | "geo";
22
+ /** "ok" when the scene produced data marks; "empty" when it did not. */
23
+ status: "ok" | "empty";
24
+ /** True when zero data marks rendered. */
25
+ empty: boolean;
26
+ /** Total data-mark scene nodes (grid/axes/legend chrome never counts). */
27
+ markCount: number;
28
+ /** Tally of scene nodes by their scene `type` (point, line, rect, …). */
29
+ markCountByType: Record<string, number>;
30
+ /** Outer SVG dimensions. */
31
+ width: number;
32
+ height: number;
33
+ /** Resolved numeric x-domain (XY frames; time domains in epoch ms). */
34
+ xDomain?: [number, number];
35
+ /** Resolved numeric y/value domain (XY + ordinal frames). */
36
+ yDomain?: [number, number];
37
+ /** Ordinal category domain, in render order. */
38
+ categories?: string[];
39
+ /** Network node / edge counts. */
40
+ nodeCount?: number;
41
+ edgeCount?: number;
42
+ /** Number of legend entries rendered (when a legend rendered). */
43
+ legendItems?: number;
44
+ /** Number of annotations supplied to the render. */
45
+ annotationCount: number;
46
+ /** The accessible name the SVG carries (description ?? title ?? generated). */
47
+ ariaLabel: string;
48
+ /** Stable warning codes (EMPTY_SCENE, NO_SCALES). */
49
+ warnings: string[];
50
+ }
51
+ /**
52
+ * Internal mutable slot threaded through the frame renderers. Only
53
+ * `renderChartWithEvidence` allocates one; the public string-returning
54
+ * render APIs pass nothing and pay nothing.
55
+ */
56
+ export interface EvidenceSink {
57
+ evidence?: RenderEvidence;
58
+ }
59
+ /** Tally scene nodes by their `type` field. */
60
+ export declare function tallyByType(nodes: ReadonlyArray<{
61
+ type?: string;
62
+ }>): {
63
+ count: number;
64
+ byType: Record<string, number>;
65
+ };
66
+ /** Convert a d3 scale domain to a serializable [number, number], or undefined. */
67
+ export declare function numericDomain(domain: ReadonlyArray<unknown> | undefined): [number, number] | undefined;
68
+ interface BuildEvidenceInput {
69
+ frameType: RenderEvidence["frameType"];
70
+ width: number;
71
+ height: number;
72
+ marks: ReadonlyArray<{
73
+ type?: string;
74
+ }>;
75
+ /** Frame props type title/description as ReactNode; only string values
76
+ * contribute to the accessible name (matching what wrapSVG emits as
77
+ * <title>/<desc> text). */
78
+ title?: unknown;
79
+ description?: unknown;
80
+ annotations?: unknown;
81
+ xDomain?: [number, number];
82
+ yDomain?: [number, number];
83
+ categories?: string[];
84
+ nodeCount?: number;
85
+ edgeCount?: number;
86
+ legendItems?: number;
87
+ extraWarnings?: string[];
88
+ }
89
+ /** Assemble evidence from a computed scene. Component name is stamped later
90
+ * by `renderChartWithEvidence`, which knows the HOC-level name. */
91
+ export declare function buildEvidence(input: BuildEvidenceInput): RenderEvidence;
92
+ export {};
@@ -20,6 +20,7 @@ import type { StreamXYFrameProps } from "../stream/types";
20
20
  import type { StreamNetworkFrameProps } from "../stream/networkTypes";
21
21
  import type { StreamOrdinalFrameProps } from "../stream/ordinalTypes";
22
22
  import type { StreamGeoFrameProps } from "../stream/geoTypes";
23
+ import { type RenderEvidence } from "./renderEvidence";
23
24
  import { type ThemeInput } from "./themeResolver";
24
25
  import { CHART_CONFIGS } from "./serverChartConfigs";
25
26
  type FrameType = "xy" | "ordinal" | "network" | "geo";
@@ -60,7 +61,19 @@ interface RenderChartOptions {
60
61
  *
61
62
  * This is the primary API for AI/MCP workflows.
62
63
  */
63
- export declare function renderChart(component: ChartName, props: Datum, _options?: RenderChartOptions): string;
64
+ export declare function renderChart(component: ChartName, props: Datum, options?: RenderChartOptions): string;
65
+ /**
66
+ * Render a chart and return machine-readable evidence about what actually
67
+ * rendered — mark counts by scene type, resolved axis domains, emptiness,
68
+ * legend/annotation counts, and the accessible name. The evidence is computed
69
+ * from the same scene graph the SVG converter walks, so it is ground truth a
70
+ * non-visual caller (an agent repair loop, a CI assertion) can quote without
71
+ * pixel inspection. Exposed through the MCP `renderChart` tool response.
72
+ */
73
+ export declare function renderChartWithEvidence(component: ChartName, props: Datum, options?: RenderChartOptions): {
74
+ svg: string;
75
+ evidence: RenderEvidence;
76
+ };
64
77
  export interface RenderToImageOptions {
65
78
  /** Output format */
66
79
  format?: "png" | "jpeg";
@@ -35,7 +35,7 @@ interface AccessibleDataTableProps {
35
35
  * computes a statistical summary (.describe()-style) and shows a sample of rows
36
36
  * (5 to start), pageable to the full dataset via "Show more".
37
37
  */
38
- export declare function AccessibleDataTable({ scene, chartType, tableId, chartTitle }: AccessibleDataTableProps): import("react/jsx-runtime").JSX.Element | null;
38
+ export declare function AccessibleDataTable({ scene, chartType, tableId, chartTitle }: AccessibleDataTableProps): React.JSX.Element | null;
39
39
  interface NetworkAccessibleDataTableProps {
40
40
  nodes: Array<{
41
41
  datum?: any;
@@ -57,25 +57,25 @@ interface NetworkAccessibleDataTableProps {
57
57
  /**
58
58
  * JIT accessible data summary for network charts.
59
59
  */
60
- export declare function NetworkAccessibleDataTable({ nodes, edges, chartType, tableId, chartTitle }: NetworkAccessibleDataTableProps): import("react/jsx-runtime").JSX.Element | null;
60
+ export declare function NetworkAccessibleDataTable({ nodes, edges, chartType, tableId, chartTitle }: NetworkAccessibleDataTableProps): React.JSX.Element | null;
61
61
  /**
62
62
  * Screen-reader-only summary note for the chart.
63
63
  * Rendered as role="note" so assistive technology can discover it.
64
64
  */
65
65
  export declare function ScreenReaderSummary({ summary }: {
66
66
  summary?: string;
67
- }): import("react/jsx-runtime").JSX.Element | null;
67
+ }): React.JSX.Element | null;
68
68
  /**
69
69
  * Screen-reader-only skip link to jump past chart canvas to the data table.
70
70
  * Only rendered when accessibleTable is enabled.
71
71
  */
72
72
  export declare function SkipToTableLink({ tableId }: {
73
73
  tableId: string;
74
- }): import("react/jsx-runtime").JSX.Element;
74
+ }): React.JSX.Element;
75
75
  /**
76
76
  * Visually-hidden aria-live region that mirrors tooltip text for screen readers.
77
77
  */
78
78
  export declare function AriaLiveTooltip({ hoverPoint }: {
79
79
  hoverPoint: any;
80
- }): import("react/jsx-runtime").JSX.Element;
80
+ }): React.JSX.Element;
81
81
  export { SR_ONLY_STYLE };
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  /**
2
3
  * Shape-appropriate keyboard focus indicator for canvas-based charts.
3
4
  *
@@ -29,4 +30,4 @@ export interface FocusRingProps {
29
30
  /** Height of rect-shaped focus target */
30
31
  height?: number;
31
32
  }
32
- export declare function FocusRing({ active, hoverPoint, margin, size, shape, width, height }: FocusRingProps): import("react/jsx-runtime").JSX.Element | null;
33
+ export declare function FocusRing({ active, hoverPoint, margin, size, shape, width, height }: FocusRingProps): React.JSX.Element | null;
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  import type { ScaleLinear } from "d3-scale";
2
3
  import type { MarginalConfig, MarginalType } from "./types";
3
4
  export type MarginalOrient = "top" | "bottom" | "left" | "right";
@@ -15,4 +16,4 @@ export interface MarginalGraphicsProps {
15
16
  }
16
17
  /** Resolve a string shorthand or full config into a MarginalConfig */
17
18
  export declare function normalizeMarginalConfig(input: MarginalConfig | MarginalType): MarginalConfig;
18
- export declare function MarginalGraphics({ orient, config: rawConfig, values, scale, size, length }: MarginalGraphicsProps): import("react/jsx-runtime").JSX.Element | null;
19
+ export declare function MarginalGraphics({ orient, config: rawConfig, values, scale, size, length }: MarginalGraphicsProps): React.JSX.Element | null;
@@ -1,4 +1,5 @@
1
- import type { NetworkSceneNode, NetworkSceneEdge } from "./networkTypes";
1
+ import type { NetworkSceneNode, NetworkSceneEdge, NetworkCircleNode } from "./networkTypes";
2
+ import type { Quadtree } from "d3-quadtree";
2
3
  export interface NetworkHitResult {
3
4
  type: "node" | "edge";
4
5
  datum: any;
@@ -11,4 +12,4 @@ export interface NetworkHitResult {
11
12
  *
12
13
  * Checks nodes first (they're on top), then edges.
13
14
  */
14
- export declare function findNearestNetworkNode(sceneNodes: NetworkSceneNode[], sceneEdges: NetworkSceneEdge[], px: number, py: number, maxDistance?: number): NetworkHitResult | null;
15
+ export declare function findNearestNetworkNode(sceneNodes: NetworkSceneNode[], sceneEdges: NetworkSceneEdge[], px: number, py: number, maxDistance?: number, nodeQuadtree?: Quadtree<NetworkCircleNode> | null, maxNodeRadius?: number): NetworkHitResult | null;
@@ -1,6 +1,7 @@
1
1
  import { ParticlePool } from "./ParticlePool";
2
2
  import type { ActiveTransition } from "./pipelineTransitionUtils";
3
- import type { NetworkPipelineConfig, NetworkSceneNode, NetworkSceneEdge, NetworkLabel, RealtimeNode, RealtimeEdge, EdgePush } from "./networkTypes";
3
+ import { type Quadtree } from "d3-quadtree";
4
+ import type { NetworkPipelineConfig, NetworkSceneNode, NetworkSceneEdge, NetworkCircleNode, NetworkLabel, RealtimeNode, RealtimeEdge, EdgePush } from "./networkTypes";
4
5
  import type { Datum } from "../charts/shared/datumTypes";
5
6
  /**
6
7
  * NetworkPipelineStore — stateful store for the StreamNetworkFrame.
@@ -15,12 +16,28 @@ export declare class NetworkPipelineStore {
15
16
  nodes: Map<string, RealtimeNode>;
16
17
  edges: Map<string, RealtimeEdge>;
17
18
  tension: number;
19
+ /**
20
+ * Monotonic scene/layout-rebuild counter — Network's equivalent of the
21
+ * `version` field on the XY/Ordinal/Geo stores. Shared cross-store
22
+ * convention: bumps on every layout rebuild and on clear(); never resets to
23
+ * a prior value, so a consumer comparing against a last-seen value can
24
+ * always detect "something changed."
25
+ */
18
26
  layoutVersion: number;
19
27
  sceneNodes: NetworkSceneNode[];
20
28
  sceneEdges: NetworkSceneEdge[];
21
29
  labels: NetworkLabel[];
22
30
  /** Overlays returned from customNetworkLayout (consumed by StreamNetworkFrame). */
23
31
  customLayoutOverlays: import("react").ReactNode;
32
+ private _nodeQuadtree;
33
+ private _maxNodeRadius;
34
+ /** Bumped whenever sceneNodes is rebuilt; keys the quadtree cache. */
35
+ private _sceneNodesRevision;
36
+ private _nodeQuadtreeRevision;
37
+ private static readonly QUADTREE_THRESHOLD;
38
+ private _nodesArrCache;
39
+ private _edgesArrCache;
40
+ private _arrCacheVersion;
24
41
  particlePool: ParticlePool | null;
25
42
  private config;
26
43
  private tensionConfig;
@@ -35,6 +52,8 @@ export declare class NetworkPipelineStore {
35
52
  private edgeTimestamps;
36
53
  /** Cached sorted node-timestamp entries for applyDecay(); null = needs rebuild */
37
54
  private _decaySortedNodes;
55
+ /** id→age-index map derived from _decaySortedNodes; rebuilt with it, not per frame. */
56
+ private _decayAgeMap;
38
57
  /** Node IDs added in the most recent layout */
39
58
  addedNodes: Set<string>;
40
59
  /** Node IDs removed in the most recent layout */
@@ -90,6 +109,32 @@ export declare class NetworkPipelineStore {
90
109
  * Build the scene graph from current layout positions.
91
110
  */
92
111
  buildScene(size: [number, number]): void;
112
+ /**
113
+ * Lazily (re)build the circle-node spatial index. Only built when the scene
114
+ * holds more than QUADTREE_THRESHOLD circle nodes (force/orbit graphs); for
115
+ * rect (sankey/treemap) and arc (chord) scenes — which carry far fewer marks
116
+ * and need area/angular hit logic — it stays null and the hit tester scans
117
+ * linearly. Always tracks `_maxNodeRadius` so the hit query can widen its
118
+ * search to cover the largest node.
119
+ */
120
+ private rebuildNodeQuadtree;
121
+ /**
122
+ * Circle-node spatial index for hit testing, or null when the scene is small
123
+ * or not circle-based. Rebuilt on demand only after the scene changed, so a
124
+ * settled graph indexes once and animation frames without a hover pay nothing.
125
+ */
126
+ get nodeQuadtree(): Quadtree<NetworkCircleNode> | null;
127
+ /** Largest circle-node radius in the current scene (widens the hit query). */
128
+ get maxNodeRadius(): number;
129
+ /**
130
+ * Per-frame-stable node/edge arrays (see field docs). Rebuilt only when
131
+ * layoutVersion changes — i.e. on a Map mutation, never on an animation tick.
132
+ */
133
+ private _ensureArrays;
134
+ /** Cached node array — safe only for read / position-mutate consumers. */
135
+ get nodesArray(): RealtimeNode[];
136
+ /** Cached edge array — safe only for read / position-mutate consumers. */
137
+ get edgesArray(): RealtimeEdge[];
93
138
  /** Whether the current layout plugin drives continuous animation (respects orbitAnimated config) */
94
139
  get isAnimating(): boolean;
95
140
  /**