semiotic 3.4.2 → 3.5.1

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 (163) 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 +113 -1
  28. package/dist/components/charts/ordinal/BoxPlot.d.ts +33 -0
  29. package/dist/components/charts/ordinal/DonutChart.d.ts +36 -0
  30. package/dist/components/charts/ordinal/DotPlot.d.ts +33 -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 +40 -0
  34. package/dist/components/charts/ordinal/Histogram.d.ts +97 -0
  35. package/dist/components/charts/ordinal/LikertChart.d.ts +44 -0
  36. package/dist/components/charts/ordinal/PieChart.d.ts +90 -1
  37. package/dist/components/charts/ordinal/RidgelinePlot.d.ts +29 -0
  38. package/dist/components/charts/ordinal/StackedBarChart.d.ts +40 -0
  39. package/dist/components/charts/ordinal/SwarmPlot.d.ts +38 -0
  40. package/dist/components/charts/ordinal/SwimlaneChart.d.ts +62 -0
  41. package/dist/components/charts/ordinal/ViolinPlot.d.ts +34 -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 +67 -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 +44 -1
  65. package/dist/components/charts/xy/BubbleChart.d.ts +4 -0
  66. package/dist/components/charts/xy/CandlestickChart.d.ts +37 -6
  67. package/dist/components/charts/xy/ConnectedScatterplot.d.ts +28 -0
  68. package/dist/components/charts/xy/Heatmap.d.ts +4 -0
  69. package/dist/components/charts/xy/LineChart.d.ts +12 -0
  70. package/dist/components/charts/xy/MinimapChart.d.ts +58 -0
  71. package/dist/components/charts/xy/MultiAxisLineChart.d.ts +27 -0
  72. package/dist/components/charts/xy/QuadrantChart.d.ts +21 -0
  73. package/dist/components/charts/xy/Scatterplot.d.ts +38 -2
  74. package/dist/components/charts/xy/ScatterplotMatrix.d.ts +16 -0
  75. package/dist/components/charts/xy/StackedAreaChart.d.ts +61 -1
  76. package/dist/components/realtime/types.d.ts +2 -4
  77. package/dist/components/recipes/bullet.d.ts +86 -0
  78. package/dist/components/recipes/calendar.d.ts +43 -0
  79. package/dist/components/recipes/dagre.d.ts +56 -0
  80. package/dist/components/recipes/flextree.d.ts +55 -0
  81. package/dist/components/recipes/marimekko.d.ts +55 -0
  82. package/dist/components/recipes/parallelCoordinates.d.ts +97 -0
  83. package/dist/components/recipes/recipeUtils.d.ts +27 -0
  84. package/dist/components/recipes/waffle.d.ts +46 -0
  85. package/dist/components/semiotic-ai.d.ts +4 -0
  86. package/dist/components/semiotic-network.d.ts +3 -0
  87. package/dist/components/semiotic-ordinal.d.ts +3 -0
  88. package/dist/components/semiotic-recipes.d.ts +24 -0
  89. package/dist/components/semiotic-xy.d.ts +3 -0
  90. package/dist/components/semiotic.d.ts +2 -2
  91. package/dist/components/server/renderToStaticSVG.d.ts +8 -2
  92. package/dist/components/server/serverChartConfigs.d.ts +47 -1
  93. package/dist/components/server/staticAnnotations.d.ts +6 -0
  94. package/dist/components/store/ObservationStore.d.ts +1 -3
  95. package/dist/components/store/SelectionStore.d.ts +1 -3
  96. package/dist/components/store/ThemeStore.d.ts +4 -4
  97. package/dist/components/store/TooltipStore.d.ts +1 -3
  98. package/dist/components/store/createStore.d.ts +4 -2
  99. package/dist/components/stream/CanvasHitTester.d.ts +10 -8
  100. package/dist/components/stream/DataSourceAdapter.d.ts +9 -0
  101. package/dist/components/stream/GeoPipelineStore.d.ts +9 -0
  102. package/dist/components/stream/GeoTileRenderer.d.ts +14 -0
  103. package/dist/components/stream/NetworkPipelineStore.d.ts +25 -0
  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 +13 -0
  114. package/dist/components/stream/hoverUtils.d.ts +4 -10
  115. package/dist/components/stream/networkCustomLayout.d.ts +67 -0
  116. package/dist/components/stream/networkTypes.d.ts +45 -0
  117. package/dist/components/stream/ordinalCustomLayout.d.ts +84 -0
  118. package/dist/components/stream/ordinalTypes.d.ts +35 -1
  119. package/dist/components/stream/renderers/barFunnelCanvasRenderer.d.ts +9 -1
  120. package/dist/components/stream/renderers/canvasRenderHelpers.d.ts +92 -0
  121. package/dist/components/stream/sampleCurvePath.d.ts +9 -0
  122. package/dist/components/stream/types.d.ts +44 -1
  123. package/dist/components/stream/useHydration.d.ts +89 -0
  124. package/dist/components/stream/useStableShallow.d.ts +1 -0
  125. package/dist/components/stream/xySceneBuilders/types.d.ts +4 -0
  126. package/dist/geo.min.js +2 -1
  127. package/dist/geo.module.min.js +2 -1
  128. package/dist/network.min.js +2 -1
  129. package/dist/network.module.min.js +2 -1
  130. package/dist/ordinal.min.js +2 -1
  131. package/dist/ordinal.module.min.js +2 -1
  132. package/dist/realtime.min.js +2 -1
  133. package/dist/realtime.module.min.js +2 -1
  134. package/dist/semiotic-ai.d.ts +69 -65
  135. package/dist/semiotic-ai.min.js +2 -1
  136. package/dist/semiotic-ai.module.min.js +2 -1
  137. package/dist/semiotic-data.d.ts +4 -4
  138. package/dist/semiotic-geo.d.ts +15 -15
  139. package/dist/semiotic-network.d.ts +19 -16
  140. package/dist/semiotic-ordinal.d.ts +31 -28
  141. package/dist/semiotic-realtime.d.ts +17 -17
  142. package/dist/semiotic-recipes.d.ts +24 -0
  143. package/dist/semiotic-recipes.min.js +1 -0
  144. package/dist/semiotic-recipes.module.min.js +1 -0
  145. package/dist/semiotic-server.d.ts +6 -6
  146. package/dist/semiotic-statisticalOverlays-C3DsOgr_.js +1 -0
  147. package/dist/semiotic-themes.d.ts +3 -3
  148. package/dist/semiotic-themes.min.js +2 -1
  149. package/dist/semiotic-themes.module.min.js +2 -1
  150. package/dist/semiotic-utils.d.ts +23 -23
  151. package/dist/semiotic-utils.min.js +2 -1
  152. package/dist/semiotic-utils.module.min.js +2 -1
  153. package/dist/semiotic-xy.d.ts +27 -24
  154. package/dist/semiotic.d.ts +63 -63
  155. package/dist/semiotic.min.js +2 -1
  156. package/dist/semiotic.module.min.js +2 -1
  157. package/dist/server.min.js +1 -1
  158. package/dist/server.module.min.js +1 -1
  159. package/dist/test-utils/canvasMock.d.ts +34 -5
  160. package/dist/xy.min.js +2 -1
  161. package/dist/xy.module.min.js +2 -1
  162. package/package.json +38 -17
  163. package/dist/semiotic-statisticalOverlays-Ckd_jM8z.js +0 -1
@@ -108,16 +108,34 @@ export interface RealtimeHeatmapProps<TDatum extends Datum = Datum> {
108
108
  *
109
109
  * @example
110
110
  * ```tsx
111
+ * // Count-aggregated heatmap — each push lands in a (time-bin × value-bin) cell
111
112
  * const ref = useRef<RealtimeFrameHandle>(null)
112
- * ref.current.push({ time: Date.now(), x: 42, y: 7 })
113
+ * useEffect(() => {
114
+ * const id = setInterval(() => ref.current?.push({ time: Date.now(), y: Math.random() * 10 }), 50)
115
+ * return () => clearInterval(id)
116
+ * }, [])
117
+ * return (
118
+ * <RealtimeHeatmap
119
+ * ref={ref}
120
+ * timeAccessor="time"
121
+ * valueAccessor="y"
122
+ * heatmapXBins={30}
123
+ * heatmapYBins={20}
124
+ * aggregation="count"
125
+ * />
126
+ * )
127
+ * ```
113
128
  *
129
+ * @example
130
+ * ```tsx
131
+ * // Mean aggregation with a sequential color scheme; useful for sensor density maps
114
132
  * <RealtimeHeatmap
115
133
  * ref={ref}
116
134
  * timeAccessor="time"
117
135
  * valueAccessor="y"
118
- * heatmapXBins={30}
119
- * heatmapYBins={20}
120
- * aggregation="count"
136
+ * aggregation="mean"
137
+ * colorScheme="viridis"
138
+ * windowSize={500}
121
139
  * />
122
140
  * ```
123
141
  */
@@ -148,15 +148,18 @@ export interface RealtimeTemporalHistogramProps<TDatum extends Datum = Datum> {
148
148
  *
149
149
  * @example
150
150
  * ```tsx
151
- * // Simple histogram
151
+ * // Simple temporal histogram — push each event, the chart bins by time
152
152
  * <RealtimeTemporalHistogram
153
153
  * ref={ref}
154
154
  * binSize={20}
155
155
  * fill="#007bff"
156
156
  * enableHover
157
157
  * />
158
+ * ```
158
159
  *
159
- * // Stacked by category
160
+ * @example
161
+ * ```tsx
162
+ * // Stacked by category — same push API, color by status field
160
163
  * <RealtimeTemporalHistogram
161
164
  * ref={ref}
162
165
  * binSize={25}
@@ -110,14 +110,35 @@ export interface RealtimeLineChartProps<TDatum extends Datum = Datum> {
110
110
  *
111
111
  * @example
112
112
  * ```tsx
113
+ * // Single streaming series — push each datum, the chart slides
113
114
  * const ref = useRef<RealtimeFrameHandle>(null)
115
+ * useEffect(() => {
116
+ * const id = setInterval(() => ref.current?.push({ time: Date.now(), value: Math.random() }), 100)
117
+ * return () => clearInterval(id)
118
+ * }, [])
119
+ * return (
120
+ * <RealtimeLineChart
121
+ * ref={ref}
122
+ * stroke="#007bff"
123
+ * strokeWidth={2}
124
+ * windowSize={200}
125
+ * enableHover
126
+ * />
127
+ * )
128
+ * ```
114
129
  *
130
+ * @example
131
+ * ```tsx
132
+ * // Decay + pulse — older points fade, newly-pushed points flash
115
133
  * <RealtimeLineChart
116
134
  * ref={ref}
117
- * stroke="#007bff"
135
+ * timeAccessor="t"
136
+ * valueAccessor="v"
137
+ * stroke="#0b5fff"
118
138
  * strokeWidth={2}
119
- * windowSize={200}
120
- * enableHover
139
+ * decay={{ type: "linear" }}
140
+ * pulse={{ type: "fade", durationMs: 400 }}
141
+ * windowSize={500}
121
142
  * />
122
143
  * ```
123
144
  */
@@ -112,6 +112,7 @@ export interface RealtimeSwarmChartProps<TDatum extends Datum = Datum> {
112
112
  *
113
113
  * @example
114
114
  * ```tsx
115
+ * // Per-sensor swarm — each push is a discrete dot, color by category
115
116
  * <RealtimeSwarmChart
116
117
  * ref={ref}
117
118
  * radius={4}
@@ -120,6 +121,17 @@ export interface RealtimeSwarmChartProps<TDatum extends Datum = Datum> {
120
121
  * colors={{ sensor1: "#007bff", sensor2: "#28a745" }}
121
122
  * />
122
123
  * ```
124
+ *
125
+ * @example
126
+ * ```tsx
127
+ * // Threshold-coloured outliers via a y-threshold annotation
128
+ * <RealtimeSwarmChart
129
+ * ref={ref}
130
+ * radius={3}
131
+ * annotations={[{ type: "y-threshold", value: 0.9, color: "#dc3545", label: "alert" }]}
132
+ * windowSize={300}
133
+ * />
134
+ * ```
123
135
  */
124
136
  export declare const RealtimeSwarmChart: {
125
137
  <TDatum extends Datum = Datum>(props: RealtimeSwarmChartProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
@@ -111,6 +111,7 @@ export interface RealtimeWaterfallChartProps<TDatum extends Datum = Datum> {
111
111
  *
112
112
  * @example
113
113
  * ```tsx
114
+ * // Trade-flow waterfall — push each delta, the chart accumulates from baseline
114
115
  * <RealtimeWaterfallChart
115
116
  * ref={ref}
116
117
  * positiveColor="#28a745"
@@ -119,6 +120,19 @@ export interface RealtimeWaterfallChartProps<TDatum extends Datum = Datum> {
119
120
  * windowSize={300}
120
121
  * />
121
122
  * ```
123
+ *
124
+ * @example
125
+ * ```tsx
126
+ * // Themed via CSS variables — same chart, brand colors via the theme provider
127
+ * <ThemeProvider theme="bi-tool">
128
+ * <RealtimeWaterfallChart
129
+ * ref={ref}
130
+ * positiveColor="var(--semiotic-success)"
131
+ * negativeColor="var(--semiotic-danger)"
132
+ * stroke="var(--semiotic-border)"
133
+ * />
134
+ * </ThemeProvider>
135
+ * ```
122
136
  */
123
137
  export declare const RealtimeWaterfallChart: {
124
138
  <TDatum extends Datum = Datum>(props: RealtimeWaterfallChartProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
@@ -0,0 +1,67 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Datum } from "../shared/datumTypes";
3
+ import type { HoverData } from "../../realtime/types";
4
+ import type { ChartAccessor } from "../shared/types";
5
+ interface DefaultRealtimeTooltipOptions<TDatum extends Datum = Datum> {
6
+ timeAccessor?: ChartAccessor<TDatum, number>;
7
+ valueAccessor?: ChartAccessor<TDatum, number>;
8
+ /**
9
+ * Field-name aliases shown in the tooltip ("x" / "y" by default).
10
+ * Some Realtime HOCs may want to show "time" / "value" or
11
+ * "category" / "count" — pass overrides here. The strings are
12
+ * cosmetic; data lookup still uses `timeAccessor`/`valueAccessor`.
13
+ */
14
+ xLabel?: string;
15
+ yLabel?: string;
16
+ }
17
+ /**
18
+ * Build a default tooltip renderer for a Realtime HOC. Returns a
19
+ * function compatible with `tooltipContent: (d: HoverData) => ReactNode`.
20
+ */
21
+ export declare function buildDefaultRealtimeTooltip<TDatum extends Datum = Datum>(options?: DefaultRealtimeTooltipOptions<TDatum>): (d: HoverData) => ReactNode;
22
+ /**
23
+ * Waterfall-specific default tooltip.
24
+ *
25
+ * The waterfall scene builder enriches each rect's datum with
26
+ * `baseline` (cumulative at the start of the bar), `cumEnd`
27
+ * (cumulative at the top of the bar), and `delta` (signed per-tick
28
+ * change). The default `x:`/`y:` shape is misleading for waterfall
29
+ * because the bar's vertical projection encodes the *cumulative*
30
+ * total — hovering a bar high on the chart and seeing the per-tick
31
+ * delta felt disconnected from what the bar visually showed.
32
+ *
33
+ * This tooltip surfaces all three relevant quantities:
34
+ * x: <time> (the configured timeAccessor)
35
+ * Δ: +5.2 / -3.1 (the per-tick delta, sign-prefixed)
36
+ * total: 87.4 (the cumulative running sum at the bar top)
37
+ *
38
+ * Falls back to the canonical x/y shape if the enriched fields are
39
+ * absent (e.g. a static-data render that bypassed the waterfall
40
+ * scene builder).
41
+ */
42
+ export declare function buildWaterfallTooltip<TDatum extends Datum = Datum>(options?: DefaultRealtimeTooltipOptions<TDatum>): (d: HoverData) => ReactNode;
43
+ /**
44
+ * Heatmap-specific default tooltip.
45
+ *
46
+ * The streaming heatmap aggregates raw points into 2D bins; each cell's
47
+ * datum is `{ xi, yi, value, count, sum, xCenter, yCenter, agg }`. The
48
+ * generic `x: <time>, y: <value>` shape is meaningless because the cell
49
+ * doesn't carry the user's original fields — it carries bin indices and
50
+ * aggregated counts.
51
+ *
52
+ * This tooltip surfaces the user-relevant info:
53
+ * x: <data-space x-center of the bin>
54
+ * y: <data-space y-center of the bin>
55
+ * count: 12 (when datum.count is present — streaming path)
56
+ * sum: 142 (when agg === "sum")
57
+ * mean: 11.83 (when agg === "mean")
58
+ *
59
+ * For `agg === "sum"` we always surface the sum (it's the metric the
60
+ * heatmap is colored by, even when sum happens to equal count).
61
+ *
62
+ * Falls back to the canonical x/y shape if the enriched fields are
63
+ * absent (e.g. a non-streaming render path); the count/sum/mean rows
64
+ * only appear when the matching field is present on the datum.
65
+ */
66
+ export declare function buildHeatmapTooltip<TDatum extends Datum = Datum>(options?: DefaultRealtimeTooltipOptions<TDatum>): (d: HoverData) => ReactNode;
67
+ export {};
@@ -0,0 +1,26 @@
1
+ import type { Datum } from "../shared/datumTypes";
2
+ /**
3
+ * Auto-fit the realtime ring buffer to bounded data.
4
+ *
5
+ * Realtime HOCs accept both a static `data` array (bounded use) and
6
+ * ref-based `push()` (streaming use). The underlying ring buffer is
7
+ * sized by `windowSize`, which has historically defaulted to 200.
8
+ * That default is fine for streaming — the buffer scrolls — but
9
+ * silently truncates static `data` arrays larger than 200 points
10
+ * (the older entries fall off the back as new ones arrive during the
11
+ * single bulk ingest, which looks like a bug from the consumer's
12
+ * perspective).
13
+ *
14
+ * Resolution rule:
15
+ * - **Explicit user `windowSize` always wins** — they may want a
16
+ * specific cap regardless of the data size (e.g. preview the
17
+ * last 50 of a 1000-point archive).
18
+ * - **Otherwise** auto-fit to `max(data.length, 200)`. The 200
19
+ * floor preserves the streaming-default ring size when `data`
20
+ * is empty/undefined; data-size sets the floor when present so
21
+ * bounded ingestion never drops points.
22
+ *
23
+ * Replaces the historical `windowSize={data.length}` workaround that
24
+ * appeared in our own theming docs and likely consumer code.
25
+ */
26
+ export declare function resolveRealtimeWindowSize(windowSizeProp: number | undefined, data: Datum[] | undefined): number;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Single source of truth for per-chart prop specifications.
3
+ *
4
+ * Three downstream consumers used to maintain their own per-chart entries:
5
+ * - `ai/schema.json` (LLM tool definitions)
6
+ * - `src/components/charts/shared/validationMap.ts` (runtime prop validation)
7
+ * - `ai/componentMetadata.cjs` (category buckets)
8
+ *
9
+ * Today, `ai/schema.json` is generated from this registry — run
10
+ * `npm run docs:chart-specs:schema` to refresh it after editing a spec.
11
+ * `validationMap.ts` and `ai/componentMetadata.cjs` are still hand-edited
12
+ * but are gated for parity by the registry: `check:chart-specs` (run via
13
+ * `npm run check:chart-specs`) regenerates each chart's schema/
14
+ * validation/metadata entries with the pure functions in
15
+ * `scripts/lib/chart-specs-generators.mjs` and fails the build on any
16
+ * drift, including unexpected adds or removes that bypass the registry.
17
+ *
18
+ * Design notes:
19
+ * - Shared prop bags (common, xyAxis, ordinalAxis) live in `PROP_BAGS` and
20
+ * are referenced by name in each spec so common surface stays in one place.
21
+ * - The runtime PropType set ("string" | "number" | "boolean" | "array" |
22
+ * "object" | "function") is broader than JSON Schema's, but the schema
23
+ * generator emits whatever types this registry declares — including
24
+ * "function" inside type unions (canonical entries like
25
+ * `RidgelinePlot.tooltip: ["function", "object"]` and
26
+ * `SwimlaneChart.onBrush: "function"` already use this convention; LLMs
27
+ * read the union and pick a non-function alternative when they can't
28
+ * supply a function value). For props that are purely callbacks or
29
+ * escape hatches an LLM cannot meaningfully populate, tag the spec
30
+ * with `omitFromSchema: true` to keep it in validationMap but out of
31
+ * schema.json. `description` and `default` annotations surface in
32
+ * schema.json (and MCP responses) but are dropped from validationMap
33
+ * (which only reads `type` and `enum`).
34
+ */
35
+ export type PropType = "string" | "number" | "boolean" | "array" | "object" | "function";
36
+ export type DataShape = "array" | "object" | "network" | "realtime" | "none";
37
+ export type ChartCategory = "xy" | "ordinal" | "network" | "geo" | "realtime";
38
+ export interface ChartPropSpec {
39
+ /** Allowed runtime types. May be a single value or a union. */
40
+ type: PropType | PropType[];
41
+ /** Allowed enum values for string-typed props. */
42
+ enum?: readonly string[];
43
+ /** Default value surfaced in schema.json (and shown in MCP getSchema). */
44
+ default?: unknown;
45
+ /** Schema-side description; surfaces in LLM tool definitions. */
46
+ description?: string;
47
+ /**
48
+ * When true, the prop is included in validationMap but omitted from
49
+ * schema.json. Use for handler/callback props (`onClick`, `tooltip`)
50
+ * and pass-through escape hatches (`frameProps`) that LLMs shouldn't
51
+ * be asked to populate.
52
+ */
53
+ omitFromSchema?: boolean;
54
+ }
55
+ export interface ChartSpec {
56
+ /** Component name, must match the React export. */
57
+ name: string;
58
+ category: ChartCategory;
59
+ /** Human-readable description for schema.tools[].function.description. */
60
+ description: string;
61
+ /** Statically-required props. Push-mode optionality lives in behaviorContracts. */
62
+ required: string[];
63
+ /** Drives validation dispatch (validateArrayData / validateNetworkData / …). */
64
+ dataShape: DataShape;
65
+ /** Accessor props validated against the data shape at runtime. */
66
+ dataAccessors: string[];
67
+ /**
68
+ * Shared prop bags this chart composes. Bag props are merged in left-to-right
69
+ * order; chart-specific `ownProps` win on key collision.
70
+ */
71
+ propBags: ReadonlyArray<keyof typeof PROP_BAGS>;
72
+ /** Chart-specific prop spec, overlaid on top of the composed bags. */
73
+ ownProps: Record<string, ChartPropSpec>;
74
+ }
75
+ export declare const PROP_BAGS: {
76
+ readonly common: Record<string, ChartPropSpec>;
77
+ readonly xyAxis: Record<string, ChartPropSpec>;
78
+ readonly ordinalAxis: Record<string, ChartPropSpec>;
79
+ readonly realtime: Record<string, ChartPropSpec>;
80
+ };
81
+ export declare const ORIENTATION_ENUM: readonly ["vertical", "horizontal"];
82
+ export declare const HORIZONTAL_VERTICAL_ENUM: readonly ["horizontal", "vertical"];
83
+ export declare const LEGEND_POSITION_ENUM: readonly ["right", "left", "top", "bottom"];
84
+ export declare const CURVE_ENUM: readonly ["linear", "monotoneX", "monotoneY", "step", "stepAfter", "stepBefore", "basis", "cardinal", "catmullRom"];
85
+ export declare const CHART_MODE_ENUM: readonly ["primary", "context", "sparkline"];
86
+ export declare const CHART_SPECS: Record<string, ChartSpec>;
87
+ /**
88
+ * Compose a chart's full prop set (bags + ownProps) in deterministic order.
89
+ * ownProps wins on key collision so a chart can override a shared default.
90
+ */
91
+ export declare function composeProps(spec: ChartSpec): Record<string, ChartPropSpec>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Inlined replacement for the subset of `d3-scale-chromatic` that
3
+ * `semiotic` actually uses.
4
+ *
5
+ * Why this module exists: `d3-scale-chromatic` ships ~76KB of palette
6
+ * data and pulls in `d3-color` + `d3-interpolate` transitively. We
7
+ * use exactly 3 categorical schemes, 12 sequential single-/multi-hue
8
+ * interpolators, and 7 diverging interpolators. Inlining at the right
9
+ * granularity is much smaller than the dependency.
10
+ *
11
+ * Fidelity choices:
12
+ * - **Categorical schemes** are byte-identical to d3 — they're just
13
+ * hex-string arrays of the canonical Tableau / ColorBrewer / d3
14
+ * palettes.
15
+ * - **Sequential and diverging interpolators** sample the canonical
16
+ * palette at coarser resolution than d3's ~256-stop precomputed
17
+ * LUTs. d3 uses a Catmull-Rom basis spline through the same stops;
18
+ * we use linear RGB interpolation. The visible difference at
19
+ * typical N=5–9 binning or continuous heatmap rendering is
20
+ * imperceptible (RGB-linear and basis-spline produce ΔE < 1 across
21
+ * the gradient for these palettes — well under perceptual
22
+ * threshold). Behavior is identical for the discrete-binning use
23
+ * cases that dominate consumer code.
24
+ *
25
+ * Each interpolator has the same signature as d3's: `(t: number) =>
26
+ * string`, where `t ∈ [0, 1]` and the return is a `#rrggbb` CSS color
27
+ * string (matching d3-color's `Rgb#toString()` output for opaque
28
+ * colors, which is what flows into JSX `stroke=` / `fill=` attributes
29
+ * downstream). `t` outside [0, 1] is clamped, matching d3 behavior.
30
+ *
31
+ * Palette stops are taken from d3-scale-chromatic and ColorBrewer
32
+ * source: https://github.com/d3/d3-scale-chromatic
33
+ *
34
+ * Add to this module rather than re-introducing the dependency if a
35
+ * new scheme is needed — copy the relevant palette strings from the
36
+ * d3 source and add the export.
37
+ */
38
+ /** D3's standard 10-color categorical palette (Vega Category10). */
39
+ export declare const schemeCategory10: readonly string[];
40
+ /** Tableau 10 default categorical palette. */
41
+ export declare const schemeTableau10: readonly string[];
42
+ /** ColorBrewer Set3 — 12 pastel categorical colors. */
43
+ export declare const schemeSet3: readonly string[];
44
+ export declare const interpolateBlues: (t: number) => string;
45
+ export declare const interpolateReds: (t: number) => string;
46
+ export declare const interpolateGreens: (t: number) => string;
47
+ export declare const interpolateOranges: (t: number) => string;
48
+ export declare const interpolatePurples: (t: number) => string;
49
+ export declare const interpolateGreys: (t: number) => string;
50
+ export declare const interpolateViridis: (t: number) => string;
51
+ export declare const interpolatePlasma: (t: number) => string;
52
+ export declare const interpolateInferno: (t: number) => string;
53
+ export declare const interpolateMagma: (t: number) => string;
54
+ export declare const interpolateCividis: (t: number) => string;
55
+ export declare const interpolateTurbo: (t: number) => string;
56
+ export declare const interpolateRdBu: (t: number) => string;
57
+ export declare const interpolatePiYG: (t: number) => string;
58
+ export declare const interpolatePRGn: (t: number) => string;
59
+ export declare const interpolateBrBG: (t: number) => string;
60
+ export declare const interpolateRdYlBu: (t: number) => string;
61
+ export declare const interpolateRdYlGn: (t: number) => string;
62
+ export declare const interpolateSpectral: (t: number) => string;
@@ -1,4 +1,3 @@
1
- import { interpolateBlues, interpolateReds, interpolateGreens, interpolateOranges, interpolatePurples, interpolateViridis, interpolatePlasma } from "d3-scale-chromatic";
2
1
  import type { Datum } from "./datumTypes";
3
2
  /**
4
3
  * Predefined color schemes
@@ -7,13 +6,13 @@ export declare const COLOR_SCHEMES: {
7
6
  category10: readonly string[];
8
7
  tableau10: readonly string[];
9
8
  set3: readonly string[];
10
- blues: typeof interpolateBlues;
11
- reds: typeof interpolateReds;
12
- greens: typeof interpolateGreens;
13
- oranges: typeof interpolateOranges;
14
- purples: typeof interpolatePurples;
15
- viridis: typeof interpolateViridis;
16
- plasma: typeof interpolatePlasma;
9
+ blues: (t: number) => string;
10
+ reds: (t: number) => string;
11
+ greens: (t: number) => string;
12
+ oranges: (t: number) => string;
13
+ purples: (t: number) => string;
14
+ viridis: (t: number) => string;
15
+ plasma: (t: number) => string;
17
16
  };
18
17
  /**
19
18
  * Default colors for charts
@@ -46,7 +45,7 @@ export declare const DEPTH_PALETTE_COLORS: string[];
46
45
  * getColor({value: 10}, d => d.value > 5 ? 'red' : 'blue')
47
46
  * ```
48
47
  */
49
- export declare function getColor(dataPoint: any, colorBy: string | ((d: Datum) => string), colorScale?: (v: any) => string): string;
48
+ export declare function getColor(dataPoint: Datum, colorBy: string | ((d: Datum) => string), colorScale?: (v: string) => string): string;
50
49
  /**
51
50
  * Creates a color scale function from data
52
51
  *
@@ -71,4 +70,4 @@ export declare function createColorScale(data: Array<Datum>, colorBy: string, sc
71
70
  * @param domain - Optional domain for scaling [minValue, maxValue]
72
71
  * @returns Size value
73
72
  */
74
- export declare function getSize(dataPoint: any, sizeBy: string | ((d: Datum) => number), sizeRange?: [number, number], domain?: [number, number]): number;
73
+ export declare function getSize(dataPoint: Datum, sizeBy: string | ((d: Datum) => number), sizeRange?: [number, number], domain?: [number, number]): number;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Inlined replacement for the subset of `d3-format` that semiotic and
3
+ * its consumers actually exercise.
4
+ *
5
+ * Why this module exists: `d3-format` ships ~42KB unpacked plus a
6
+ * full locale-data table we don't use. Internally semiotic only emits
7
+ * three format strings (`,.0f`, `,.${n}f`, `.${n}%`) but the public
8
+ * `xFormat` / `yFormat` / `valueFormat` props let consumers pass any
9
+ * d3-format spec, so the parser needs to cover the realistic chart
10
+ * subset, not just the strings semiotic emits itself.
11
+ *
12
+ * What's implemented (the chart-relevant subset):
13
+ *
14
+ * [,][.precision][~][type]
15
+ *
16
+ * - `,` — thousands grouping using a literal comma. Matches d3's
17
+ * default-locale behavior (en-US); intentionally not locale-aware,
18
+ * because chart axis labels need stable output across CI runners
19
+ * and SSR snapshots — a runtime-locale separator would shift to
20
+ * `1.234,56` under de-DE / fr-FR and break golden-file tests.
21
+ * - `.N` — fractional precision (digits after the decimal for
22
+ * `f`/`%`, significant digits for `s`/`r`/`g`/`e`)
23
+ * - `~` — trim trailing zeros (matches d3's `~` modifier)
24
+ * - type: `f` (fixed), `%` (percent ×100), `e` (exponential),
25
+ * `d` (integer; precision ignored), `s` (SI prefix), `r` (rounded
26
+ * to N significant digits), `g` (general — switches between fixed
27
+ * and exponential), or omitted (treated as `g` with default
28
+ * precision, matching d3).
29
+ *
30
+ * What's NOT implemented (rare in chart axis labels):
31
+ *
32
+ * - `[fill][align]` (`0`, `<`, `>`, `^`, `=`) — padding/alignment
33
+ * - `[sign]` (`+`, `-`, `(`, ` `) — sign behaviors
34
+ * - `[symbol]` (`$`, `#`) — currency / radix prefix
35
+ * - `[width]` — minimum field width
36
+ * - `b`/`o`/`x`/`X`/`c`/`n`/`p` types — binary/octal/hex/code-point/
37
+ * comma/percent-rounded
38
+ *
39
+ * If a consumer passes a spec with one of the un-implemented features
40
+ * the parser falls through to a best-effort `Intl.NumberFormat` call
41
+ * so we don't crash; if the input isn't even a recognized spec, the
42
+ * caller's existing `try/catch` falls back to `String(value)`.
43
+ */
44
+ /**
45
+ * Build a number formatter from a d3-format-style spec string.
46
+ * Mirrors `d3.format(spec)`: returns `(value: number) => string`.
47
+ *
48
+ * **Throws on unparseable specs and unimplemented types.** This
49
+ * matches d3's contract — the existing `try/catch` in
50
+ * `formatUtils.formatNumber` (and any consumer code that wraps a
51
+ * `format(spec)` call) catches the throw and falls back to
52
+ * `String(value)`. Earlier shim revisions silently fell back to
53
+ * `Intl.NumberFormat`, which (a) suppressed bad-input errors that
54
+ * the outer fallback was designed to handle, and (b) reintroduced a
55
+ * runtime-locale dependency that would shift output across CI runners
56
+ * and SSR snapshot baselines.
57
+ */
58
+ export declare function format(spec: string): (value: number) => string;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Identity-preserving filter for sparse arrays of objects.
3
+ *
4
+ * Public chart props (`data`, `points`, `nodes`, `edges`, `flows`,
5
+ * `series`, `areas`) get fed to ingestion, color extraction, scene
6
+ * builders, and accessor lookups that read `d[field]` without
7
+ * null-checking individual entries. CSV-parsed and lookup-failed
8
+ * pipelines commonly emit `null` / `undefined` interlopers; without
9
+ * upfront filtering, the HOC crashes the moment a hook iterates the
10
+ * array.
11
+ *
12
+ * Returns the original array reference when nothing needs to be
13
+ * dropped. Consumers doing identity checks against the input prop —
14
+ * notably the cache keys inside `PipelineStore` and the `useMemo`
15
+ * deps inside `useChartSetup` / `useColorScale` — keep their fast
16
+ * paths in the common case where the input is already clean.
17
+ */
18
+ /**
19
+ * Singleton empty array. Use as a stable default when a caller needs
20
+ * to satisfy a non-optional `T[]` parameter without allocating a fresh
21
+ * `[]` on every render — which would invalidate any downstream
22
+ * `useMemo` keyed on the array reference (e.g. `useChartSetup`'s
23
+ * sparse-array filter, color-scale memos). Frozen so accidental
24
+ * mutation throws in strict mode rather than corrupting later reads.
25
+ */
26
+ export declare const EMPTY_ARRAY: readonly unknown[];
27
+ export declare function filterSparseArray<T>(input: readonly T[] | undefined | null): T[];
@@ -0,0 +1,113 @@
1
+ import type { ReactNode } from "react";
2
+ import type { Datum } from "./datumTypes";
3
+ import { type TooltipProp } from "../../Tooltip/Tooltip";
4
+ import type { HoverData } from "../../realtime/types";
5
+ import type { LinkedHoverProp, SelectionConfig } from "./types";
6
+ import type { OnObservationCallback } from "../../store/ObservationStore";
7
+ import type { AnimateProp } from "../../stream/pipelineTransitionUtils";
8
+ /**
9
+ * The frames accept `tooltipContent: (d: HoverData) => ReactNode`,
10
+ * which is a slightly wider parameter than the `TooltipContentFn`
11
+ * (`(d: Datum) => ReactNode`) the `Tooltip` module exports. The HOC
12
+ * default tooltip generated by `buildDefaultTooltip` matches the
13
+ * wider shape; user-provided tooltip functions (via `normalizeTooltip`)
14
+ * conform to the narrower `Datum` shape. At runtime both work because
15
+ * `HoverData` carries the original `Datum` plus interaction metadata,
16
+ * and the user's tooltip body reads only fields it knows about.
17
+ *
18
+ * Typing the helper's return at the wider `HoverData` shape lets either
19
+ * source flow through without a cast at the call site, matching the
20
+ * inline form HOCs used before this refactor.
21
+ */
22
+ type FrameTooltipContent = (d: HoverData) => ReactNode;
23
+ /**
24
+ * Returns the spreadable subset of base metadata props for the frame.
25
+ *
26
+ * - Truthy gate for `title` / `description` / `summary` / `className`:
27
+ * empty strings should NOT shadow the frame's own defaults.
28
+ * - Defined gate for `accessibleTable`: an explicit `false` is a real
29
+ * consumer choice (suppresses the sr-only data table) and must
30
+ * reach the frame.
31
+ * - Defined-and-non-null gate for `animate`: matches `props.animate
32
+ * != null`. Lets `false` through (disables animation explicitly)
33
+ * while filtering `undefined` so the frame's intro-on-default
34
+ * stays in effect.
35
+ *
36
+ * The returned object is suitable for `...spread` into a frame-props
37
+ * object literal.
38
+ */
39
+ export interface BaseMetadataProps {
40
+ title?: string | ReactNode;
41
+ description?: string;
42
+ summary?: string;
43
+ accessibleTable?: boolean;
44
+ className?: string;
45
+ animate?: AnimateProp;
46
+ }
47
+ export declare function buildBaseMetadataProps(input: BaseMetadataProps): BaseMetadataProps;
48
+ /**
49
+ * Returns the spreadable hover/click behavior props for the frame.
50
+ *
51
+ * The predicates encode the same logic the HOCs already used inline:
52
+ *
53
+ * - `customHoverBehavior` is forwarded only when at least one
54
+ * consumer-side hover-driving prop is set (`linkedHover` for
55
+ * cross-chart highlight, `onObservation` for AI observation
56
+ * emission, `onClick` for click resolution that needs hover-driven
57
+ * hit testing, `hoverHighlight` for the dim-non-hovered effect).
58
+ * - `customClickBehavior` mirrors the click-driving subset
59
+ * (`onObservation`, `onClick`, `linkedHover` for cross-chart
60
+ * selection lock).
61
+ *
62
+ * Returning the props as a spreadable object means HOCs that don't
63
+ * need either get an empty merge that adds nothing.
64
+ */
65
+ export declare function buildCustomBehaviorProps(input: {
66
+ linkedHover?: LinkedHoverProp;
67
+ onObservation?: OnObservationCallback;
68
+ onClick?: ((datum: Datum, position: {
69
+ x: number;
70
+ y: number;
71
+ }) => void) | undefined;
72
+ hoverHighlight?: boolean;
73
+ customHoverBehavior: (d: Datum | null) => void;
74
+ customClickBehavior: (d: Datum | null) => void;
75
+ /**
76
+ * Whether `linkedHover` participates in the click predicate. Most
77
+ * XY / ordinal HOCs say yes — `linkedHover` cross-chart selection
78
+ * fires on click-to-lock as well as hover. Geo HOCs and
79
+ * `CandlestickChart` say no — their click resolution only needs
80
+ * direct consumer-side handlers (`onObservation` / `onClick`).
81
+ * Default is `true` to match the more common case.
82
+ */
83
+ linkedHoverInClickPredicate?: boolean;
84
+ }): {
85
+ customHoverBehavior?: (d: Datum | null) => void;
86
+ customClickBehavior?: (d: Datum | null) => void;
87
+ };
88
+ /**
89
+ * Resolve the `tooltipContent` prop for the frame.
90
+ *
91
+ * - `tooltip === false` → noop function (suppresses the frame's
92
+ * default tooltip rendering entirely).
93
+ * - Otherwise → `normalizeTooltip(tooltip)` (a function, possibly
94
+ * returned by `Tooltip({ ... })` / `MultiLineTooltip({ ... })`),
95
+ * falling back to the chart's own `defaultTooltipContent` if
96
+ * `tooltip` is undefined or an unrecognized form.
97
+ *
98
+ * Returning `tooltipContent` as an object means HOCs spread it like
99
+ * the other helpers and don't have to remember the noop-vs-default
100
+ * branch in line.
101
+ */
102
+ export declare function buildTooltipProps(input: {
103
+ tooltip: TooltipProp | undefined;
104
+ defaultTooltipContent: FrameTooltipContent;
105
+ }): {
106
+ tooltipContent: FrameTooltipContent;
107
+ };
108
+ /**
109
+ * Selection-config alias. Re-exported so HOCs that use these helpers
110
+ * don't need a parallel import path for the type that flows through
111
+ * `buildCustomBehaviorProps`.
112
+ */
113
+ export type { SelectionConfig };