semiotic 3.2.3 → 3.3.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 (64) hide show
  1. package/CLAUDE.md +122 -265
  2. package/README.md +37 -17
  3. package/ai/schema.json +97 -1
  4. package/ai/system-prompt.md +3 -3
  5. package/dist/components/charts/ordinal/BarChart.d.ts +2 -0
  6. package/dist/components/charts/ordinal/DonutChart.d.ts +2 -0
  7. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +4 -0
  8. package/dist/components/charts/ordinal/PieChart.d.ts +2 -0
  9. package/dist/components/charts/ordinal/StackedBarChart.d.ts +4 -0
  10. package/dist/components/charts/ordinal/SwimlaneChart.d.ts +4 -0
  11. package/dist/components/charts/realtime/RealtimeHeatmap.d.ts +2 -0
  12. package/dist/components/charts/realtime/RealtimeHistogram.d.ts +2 -0
  13. package/dist/components/charts/realtime/RealtimeLineChart.d.ts +2 -0
  14. package/dist/components/charts/realtime/RealtimeSwarmChart.d.ts +2 -0
  15. package/dist/components/charts/realtime/RealtimeWaterfallChart.d.ts +2 -0
  16. package/dist/components/charts/shared/hooks.d.ts +2 -1
  17. package/dist/components/charts/shared/types.d.ts +6 -2
  18. package/dist/components/charts/shared/useChartSetup.d.ts +1 -1
  19. package/dist/components/realtime/RingBuffer.d.ts +11 -0
  20. package/dist/components/realtime/types.d.ts +46 -3
  21. package/dist/components/semiotic-server.d.ts +6 -1
  22. package/dist/components/server/animatedGif.d.ts +78 -0
  23. package/dist/components/server/renderToStaticSVG.d.ts +86 -5
  24. package/dist/components/server/serverChartConfigs.d.ts +17 -0
  25. package/dist/components/server/staticAnnotations.d.ts +40 -0
  26. package/dist/components/server/staticLegend.d.ts +39 -0
  27. package/dist/components/server/svgHatchPattern.d.ts +26 -0
  28. package/dist/components/server/themeResolver.d.ts +39 -0
  29. package/dist/components/store/ThemeStore.d.ts +14 -0
  30. package/dist/components/stream/GeoPipelineStore.d.ts +6 -1
  31. package/dist/components/stream/NetworkPipelineStore.d.ts +26 -0
  32. package/dist/components/stream/OrdinalPipelineStore.d.ts +11 -0
  33. package/dist/components/stream/OrdinalSVGOverlay.d.ts +5 -0
  34. package/dist/components/stream/PipelineStore.d.ts +11 -0
  35. package/dist/components/stream/accessorUtils.d.ts +3 -3
  36. package/dist/components/stream/geoTypes.d.ts +6 -4
  37. package/dist/components/stream/hoverUtils.d.ts +22 -0
  38. package/dist/components/stream/networkTypes.d.ts +45 -20
  39. package/dist/components/stream/ordinalTypes.d.ts +40 -3
  40. package/dist/components/stream/pipelineDecay.d.ts +6 -5
  41. package/dist/components/stream/renderers/resolveCSSColor.d.ts +17 -0
  42. package/dist/components/stream/types.d.ts +8 -0
  43. package/dist/geo.min.js +1 -1
  44. package/dist/geo.module.min.js +1 -1
  45. package/dist/network.min.js +1 -1
  46. package/dist/network.module.min.js +1 -1
  47. package/dist/ordinal.min.js +1 -1
  48. package/dist/ordinal.module.min.js +1 -1
  49. package/dist/realtime.min.js +1 -1
  50. package/dist/realtime.module.min.js +1 -1
  51. package/dist/semiotic-ai.min.js +1 -1
  52. package/dist/semiotic-ai.module.min.js +1 -1
  53. package/dist/semiotic-server.d.ts +6 -1
  54. package/dist/semiotic-themes.min.js +1 -1
  55. package/dist/semiotic-themes.module.min.js +1 -1
  56. package/dist/semiotic-utils.min.js +1 -1
  57. package/dist/semiotic-utils.module.min.js +1 -1
  58. package/dist/semiotic.min.js +1 -1
  59. package/dist/semiotic.module.min.js +1 -1
  60. package/dist/server.min.js +1 -1
  61. package/dist/server.module.min.js +1 -1
  62. package/dist/xy.min.js +1 -1
  63. package/dist/xy.module.min.js +1 -1
  64. package/package.json +14 -3
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.2.2",
4
+ "version": "3.3.1",
5
5
  "description": "React data visualization library for charts, networks, and beyond",
6
6
  "tools": [
7
7
  {
@@ -4793,6 +4793,102 @@
4793
4793
  ]
4794
4794
  }
4795
4795
  }
4796
+ },
4797
+ {
4798
+ "type": "function",
4799
+ "function": {
4800
+ "name": "ScatterplotMatrix",
4801
+ "description": "Multi-panel scatterplot grid with crossfilter brushing. Requires data array with numeric fields.",
4802
+ "parameters": {
4803
+ "type": "object",
4804
+ "properties": {
4805
+ "data": { "type": "array" },
4806
+ "fields": { "type": "array", "items": { "type": "string" } }
4807
+ },
4808
+ "required": ["data", "fields"]
4809
+ }
4810
+ }
4811
+ },
4812
+ {
4813
+ "type": "function",
4814
+ "function": {
4815
+ "name": "MinimapChart",
4816
+ "description": "Overview + detail chart with linked zoom. Wraps an XY chart with a minimap navigation pane.",
4817
+ "parameters": {
4818
+ "type": "object",
4819
+ "properties": {
4820
+ "data": { "type": "array" }
4821
+ },
4822
+ "required": ["data"]
4823
+ }
4824
+ }
4825
+ },
4826
+ {
4827
+ "type": "function",
4828
+ "function": {
4829
+ "name": "ChoroplethMap",
4830
+ "description": "Geographic choropleth map with colored regions based on data values.",
4831
+ "parameters": {
4832
+ "type": "object",
4833
+ "properties": {
4834
+ "areas": { "type": ["array", "string"], "description": "GeoJSON features or reference geography name" },
4835
+ "valueAccessor": { "type": "string" },
4836
+ "colorScheme": { "type": "string" },
4837
+ "projection": { "type": "string", "default": "equalEarth" }
4838
+ },
4839
+ "required": ["areas"]
4840
+ }
4841
+ }
4842
+ },
4843
+ {
4844
+ "type": "function",
4845
+ "function": {
4846
+ "name": "ProportionalSymbolMap",
4847
+ "description": "Geographic map with sized symbols at point locations.",
4848
+ "parameters": {
4849
+ "type": "object",
4850
+ "properties": {
4851
+ "points": { "type": "array" },
4852
+ "xAccessor": { "type": "string", "default": "lon" },
4853
+ "yAccessor": { "type": "string", "default": "lat" },
4854
+ "sizeBy": { "type": "string" },
4855
+ "areas": { "type": ["array", "string"] }
4856
+ },
4857
+ "required": ["points"]
4858
+ }
4859
+ }
4860
+ },
4861
+ {
4862
+ "type": "function",
4863
+ "function": {
4864
+ "name": "FlowMap",
4865
+ "description": "Geographic flow map showing movement between locations with animated particles.",
4866
+ "parameters": {
4867
+ "type": "object",
4868
+ "properties": {
4869
+ "flows": { "type": "array" },
4870
+ "nodes": { "type": "array" },
4871
+ "valueAccessor": { "type": "string" }
4872
+ },
4873
+ "required": ["flows"]
4874
+ }
4875
+ }
4876
+ },
4877
+ {
4878
+ "type": "function",
4879
+ "function": {
4880
+ "name": "DistanceCartogram",
4881
+ "description": "Cartogram distorting geographic positions based on travel time or cost from a center point.",
4882
+ "parameters": {
4883
+ "type": "object",
4884
+ "properties": {
4885
+ "points": { "type": "array" },
4886
+ "center": { "type": "array" },
4887
+ "costAccessor": { "type": "string" }
4888
+ },
4889
+ "required": ["points"]
4890
+ }
4891
+ }
4796
4892
  }
4797
4893
  ]
4798
4894
  }
@@ -1,6 +1,6 @@
1
1
  # Semiotic — React Data Visualization
2
2
 
3
- Use `import { ComponentName } from "semiotic/ai"` for all components below.
3
+ Use sub-path imports: `semiotic/xy` (143KB gz), `semiotic/ordinal` (109KB), `semiotic/network` (98KB), `semiotic/geo` (93KB), `semiotic/realtime` (145KB). Or `semiotic/ai` for all 38 HOCs in one import (269KB).
4
4
 
5
5
  ## Flat Array Data (`data: object[]`)
6
6
  - **LineChart** — `xAccessor`, `yAccessor`, `lineBy` (multi-line), `curve`
@@ -58,7 +58,7 @@ const chartRef = useRef()
58
58
  chartRef.current.push({ x: 1, y: 2 })
59
59
  <Scatterplot ref={chartRef} xAccessor="x" yAccessor="y" />
60
60
  ```
61
- Methods: `push(datum)`, `pushMany(data)`, `clear()`, `getData()`. Streaming-specific props (`windowSize`, `decay`, `pulse`) go in `frameProps`. Supported: XY charts, ordinal charts, network charts (ForceDirectedGraph, SankeyDiagram, ChordDiagram), ProportionalSymbolMap, DistanceCartogram. Not supported: hierarchy charts (TreeDiagram, Treemap, CirclePack, OrbitDiagram), ChoroplethMap, FlowMap, ScatterplotMatrix.
61
+ Methods: `push(datum)`, `pushMany(data)`, `remove(id)` (requires `pointIdAccessor`/`dataIdAccessor`), `update(id, updater)`, `clear()`, `getData()`. Network HOC refs use `remove()`/`update()` for node operations. Edge-level methods (`removeNode`, `removeEdge`, `updateNode`, `updateEdge`) are on `StreamNetworkFrameHandle`. Geo charts: `update()` is implemented as remove+push internally. Streaming-specific props (`windowSize`, `decay`, `pulse`) go in `frameProps`. Supported: XY charts, ordinal charts, network charts (ForceDirectedGraph, SankeyDiagram, ChordDiagram), ProportionalSymbolMap, DistanceCartogram. Not supported: hierarchy charts (TreeDiagram, Treemap, CirclePack, OrbitDiagram), ChoroplethMap, FlowMap, ScatterplotMatrix.
62
62
 
63
63
  For advanced streaming control, use Stream Frames (`StreamXYFrame`, `StreamOrdinalFrame`, `StreamNetworkFrame`) with `runtimeMode="streaming"` and ref-based push.
64
64
 
@@ -113,5 +113,5 @@ Or use ThemeProvider with 15 named presets: `<ThemeProvider theme="tufte">`, `"t
113
113
 
114
114
  ## Key Patterns
115
115
  - **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.
116
- - **SSR**: `renderToStaticSVG("ordinal", props)` or `renderOrdinalToStaticSVG(props)` from `semiotic/server`. Frame type is `"xy"` | `"ordinal"` | `"network"` (NOT component name).
116
+ - **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 `thresholds`.
117
117
  - **exportChart**: Pass the wrapper div, not the SVG element: `exportChart(wrapperDiv, { format: "png" })`. It finds canvas+SVG internally.
@@ -19,6 +19,8 @@ export interface BarChartProps<TDatum extends Record<string, any> = Record<strin
19
19
  colorScheme?: string | string[];
20
20
  sort?: boolean | "asc" | "desc" | ((a: Record<string, any>, b: Record<string, any>) => number);
21
21
  barPadding?: number;
22
+ /** Rounded top corner radius in pixels. Only the end away from the baseline is rounded. */
23
+ roundedTop?: number;
22
24
  /** When true, adds padding below the 0 baseline. Default false (bars flush with axis). */
23
25
  baselinePadding?: boolean;
24
26
  enableHover?: boolean;
@@ -13,6 +13,8 @@ export interface DonutChartProps<TDatum extends Record<string, any> = Record<str
13
13
  colorBy?: ChartAccessor<TDatum, string>;
14
14
  colorScheme?: string | string[];
15
15
  startAngle?: number;
16
+ /** Rounded corner radius on wedge arcs */
17
+ cornerRadius?: number;
16
18
  enableHover?: boolean;
17
19
  showCategoryTicks?: boolean;
18
20
  showLegend?: boolean;
@@ -15,7 +15,11 @@ export interface GroupedBarChartProps<TDatum extends Record<string, any> = Recor
15
15
  valueFormat?: (d: number | string) => string;
16
16
  colorBy?: ChartAccessor<TDatum, string>;
17
17
  colorScheme?: string | string[];
18
+ /** Category sort order. Default: false (data insertion order). "asc"/"desc" sorts by total grouped value. Custom comparators receive category keys. */
19
+ sort?: boolean | "asc" | "desc" | ((a: string, b: string) => number);
18
20
  barPadding?: number;
21
+ /** Rounded corner radius on bar ends (away from baseline). */
22
+ roundedTop?: number;
19
23
  baselinePadding?: boolean;
20
24
  enableHover?: boolean;
21
25
  showGrid?: boolean;
@@ -11,6 +11,8 @@ export interface PieChartProps<TDatum extends Record<string, any> = Record<strin
11
11
  colorBy?: ChartAccessor<TDatum, string>;
12
12
  colorScheme?: string | string[];
13
13
  startAngle?: number;
14
+ /** Rounded corner radius on wedge arcs */
15
+ cornerRadius?: number;
14
16
  enableHover?: boolean;
15
17
  showCategoryTicks?: boolean;
16
18
  showLegend?: boolean;
@@ -16,7 +16,11 @@ export interface StackedBarChartProps<TDatum extends Record<string, any> = Recor
16
16
  colorBy?: ChartAccessor<TDatum, string>;
17
17
  colorScheme?: string | string[];
18
18
  normalize?: boolean;
19
+ /** Category sort order. Default: false (data insertion order). "asc"/"desc" sorts by total stacked value. Custom comparators receive category keys. */
20
+ sort?: boolean | "asc" | "desc" | ((a: string, b: string) => number);
19
21
  barPadding?: number;
22
+ /** Rounded top corner radius. Only the topmost stacked segment gets rounded. */
23
+ roundedTop?: number;
20
24
  baselinePadding?: boolean;
21
25
  enableHover?: boolean;
22
26
  showGrid?: boolean;
@@ -56,6 +56,10 @@ export interface SwimlaneChartProps<TDatum extends Record<string, any> = Record<
56
56
  };
57
57
  /** Custom formatter for category tick labels */
58
58
  categoryFormat?: CategoryFormatFn;
59
+ /** Custom tick values for the value axis. Forces specific values instead of d3 auto-ticks. */
60
+ rTickValues?: number[];
61
+ /** Align first value tick label to start, last to end. Prevents clipping at chart edges. */
62
+ tickLabelEdgeAlign?: boolean;
59
63
  /** Pass-through props to StreamOrdinalFrame */
60
64
  frameProps?: Partial<Omit<StreamOrdinalFrameProps, "data" | "size">>;
61
65
  }
@@ -96,6 +96,8 @@ export interface RealtimeHeatmapProps<TDatum extends Record<string, any> = Recor
96
96
  legendPosition?: LegendPosition;
97
97
  /** Legend interaction mode */
98
98
  legendInteraction?: LegendInteractionMode;
99
+ /** ID accessor for remove()/update() on the push API */
100
+ pointIdAccessor?: string | ((d: any) => string);
99
101
  }
100
102
  /**
101
103
  * RealtimeHeatmap - Streaming heatmap with 2D grid binning.
@@ -130,6 +130,8 @@ export interface RealtimeTemporalHistogramProps<TDatum extends Record<string, an
130
130
  legendPosition?: LegendPosition;
131
131
  /** Legend interaction mode */
132
132
  legendInteraction?: LegendInteractionMode;
133
+ /** ID accessor for remove()/update() on the push API */
134
+ pointIdAccessor?: string | ((d: any) => string);
133
135
  }
134
136
  /**
135
137
  * RealtimeTemporalHistogram - Streaming temporal histogram.
@@ -96,6 +96,8 @@ export interface RealtimeLineChartProps<TDatum extends Record<string, any> = Rec
96
96
  legendPosition?: LegendPosition;
97
97
  /** Legend interaction mode */
98
98
  legendInteraction?: LegendInteractionMode;
99
+ /** ID accessor for remove()/update() on the push API */
100
+ pointIdAccessor?: string | ((d: any) => string);
99
101
  }
100
102
  /**
101
103
  * RealtimeLineChart - Simplified wrapper for streaming line charts.
@@ -96,6 +96,8 @@ export interface RealtimeSwarmChartProps<TDatum extends Record<string, any> = Re
96
96
  legendPosition?: LegendPosition;
97
97
  /** Legend interaction mode */
98
98
  legendInteraction?: LegendInteractionMode;
99
+ /** ID accessor for remove()/update() on the push API */
100
+ pointIdAccessor?: string | ((d: any) => string);
99
101
  }
100
102
  /**
101
103
  * RealtimeSwarmChart - Simplified wrapper for streaming dot/swarm charts.
@@ -96,6 +96,8 @@ export interface RealtimeWaterfallChartProps<TDatum extends Record<string, any>
96
96
  legendPosition?: LegendPosition;
97
97
  /** Legend interaction mode */
98
98
  legendInteraction?: LegendInteractionMode;
99
+ /** ID accessor for remove()/update() on the push API */
100
+ pointIdAccessor?: string | ((d: any) => string);
99
101
  }
100
102
  /**
101
103
  * RealtimeWaterfallChart - Simplified wrapper for streaming waterfall charts.
@@ -55,7 +55,7 @@ export declare function useChartSelection({ selection, linkedHover, fallbackFiel
55
55
  x: number;
56
56
  y: number;
57
57
  }) => void;
58
- hoverHighlight?: boolean | "series";
58
+ hoverHighlight?: boolean;
59
59
  colorByField?: string;
60
60
  }): {
61
61
  activeSelectionHook: SelectionHookResult | null;
@@ -128,6 +128,7 @@ export declare function useLegendInteraction(mode: LegendInteractionMode | undef
128
128
  interface ChartModeInput {
129
129
  width?: number;
130
130
  height?: number;
131
+ showAxes?: boolean;
131
132
  showGrid?: boolean;
132
133
  enableHover?: boolean;
133
134
  showLegend?: boolean;
@@ -93,10 +93,14 @@ export interface BaseChartProps {
93
93
  x: number;
94
94
  y: number;
95
95
  }) => void;
96
- /** Dim non-hovered series when hovering a data mark. "series" dims by the colorBy group key. */
97
- hoverHighlight?: boolean | "series";
96
+ /** Dim non-hovered series when hovering a data mark. Requires `colorBy`. */
97
+ hoverHighlight?: boolean;
98
98
  /** Max pixel distance for hover/click hit testing. Default 30. Increase for sparse charts, decrease for dense ones. */
99
99
  hoverRadius?: number;
100
+ /** ID accessor for remove()/update() on XY charts. Extracts a unique identifier from each datum. */
101
+ pointIdAccessor?: string | ((d: any) => string);
102
+ /** ID accessor for remove()/update() on ordinal charts. Extracts a unique identifier from each datum. */
103
+ dataIdAccessor?: string | ((d: any) => string);
100
104
  /** Visual emphasis level for dashboard hierarchy. "primary" spans two columns in ChartGrid. */
101
105
  emphasis?: "primary" | "secondary";
102
106
  /** Enable declarative bounded animation (enter/exit/update transitions).
@@ -56,7 +56,7 @@ export interface ChartSetupInput {
56
56
  y: number;
57
57
  }) => void;
58
58
  /** Dim non-hovered series on data mark hover */
59
- hoverHighlight?: boolean | "series";
59
+ hoverHighlight?: boolean;
60
60
  /** Loading state */
61
61
  loading: boolean | undefined;
62
62
  /** Empty content override */
@@ -13,6 +13,17 @@ export declare class RingBuffer<T> {
13
13
  forEach(callback: (value: T, index: number) => void): void;
14
14
  toArray(): T[];
15
15
  resize(newCapacity: number): T[];
16
+ /**
17
+ * Update items in place. The updater receives each matching item and returns
18
+ * the replacement. Returns the previous values of updated items.
19
+ * O(n) scan, no compaction needed — buffer positions stay stable.
20
+ */
21
+ update(predicate: (item: T) => boolean, updater: (item: T) => T): T[];
22
+ /**
23
+ * Remove items matching a predicate. Returns removed items.
24
+ * O(n) scan + compaction. Size decreases; capacity stays the same.
25
+ */
26
+ remove(predicate: (item: T) => boolean): T[];
16
27
  clear(): void;
17
28
  get size(): number;
18
29
  get capacity(): number;
@@ -64,11 +64,50 @@ export interface HoverAnnotationConfig {
64
64
  pointColor?: string;
65
65
  }
66
66
  export interface HoverData {
67
- data: Record<string, any>;
68
- time: number;
69
- value: number;
67
+ /** The raw datum from the user's data array (may be an object, array, or null for exit nodes) */
68
+ data: any;
69
+ /** Pixel X coordinate of the hovered element */
70
70
  x: number;
71
+ /** Pixel Y coordinate of the hovered element */
71
72
  y: number;
73
+ /** Pixel X coordinate, aliased as "time" for backwards compatibility with realtime charts */
74
+ time: number;
75
+ /** Pixel Y coordinate, aliased as "value" for backwards compatibility with realtime charts */
76
+ value: number;
77
+ /** All series values at hovered X (multi-point tooltip mode) */
78
+ allSeries?: Array<{
79
+ group: string;
80
+ value: number;
81
+ valuePx?: number;
82
+ color: string;
83
+ datum: any;
84
+ }>;
85
+ /** Pixel X of hover position (may differ from x for multi-point snap) */
86
+ xPx?: number;
87
+ /** Raw X domain value at hover position */
88
+ xValue?: any;
89
+ /** Distribution statistics for boxplot/violin/ridgeline */
90
+ stats?: {
91
+ n: number;
92
+ min: number;
93
+ q1: number;
94
+ median: number;
95
+ q3: number;
96
+ max: number;
97
+ mean: number;
98
+ };
99
+ /** Category label of hovered element */
100
+ category?: string;
101
+ /** @internal Category accessor name for tooltip rendering */
102
+ __oAccessor?: string;
103
+ /** @internal Value accessor name for tooltip rendering */
104
+ __rAccessor?: string;
105
+ /** @internal Chart type hint for tooltip rendering */
106
+ __chartType?: string;
107
+ /** Whether the hovered element is a node or edge */
108
+ nodeOrEdge?: "node" | "edge";
109
+ /** GeoJSON feature properties (flattened for convenience) */
110
+ properties?: Record<string, any>;
72
111
  }
73
112
  export interface BarStyle {
74
113
  fill?: string;
@@ -131,6 +170,10 @@ export interface RealtimeFrameProps {
131
170
  export interface RealtimeFrameHandle {
132
171
  push(point: Record<string, any>): void;
133
172
  pushMany(points: Record<string, any>[]): void;
173
+ /** Remove data by ID. Requires an ID accessor (pointIdAccessor or dataIdAccessor). */
174
+ remove(id: string | string[]): Record<string, any>[];
175
+ /** Update data by ID in place. Requires an ID accessor. Returns previous values. */
176
+ update(id: string | string[], updater: (d: Record<string, any>) => Record<string, any>): Record<string, any>[];
134
177
  clear(): void;
135
178
  getData(): Record<string, any>[];
136
179
  }
@@ -1 +1,6 @@
1
- export { renderToStaticSVG, renderXYToStaticSVG, renderOrdinalToStaticSVG, renderNetworkToStaticSVG, renderGeoToStaticSVG } from "./server/renderToStaticSVG";
1
+ export { renderToStaticSVG, renderXYToStaticSVG, renderOrdinalToStaticSVG, renderNetworkToStaticSVG, renderGeoToStaticSVG, renderChart, renderToImage, renderDashboard, } from "./server/renderToStaticSVG";
2
+ export type { RenderToImageOptions, DashboardChart, DashboardLayout, RenderDashboardOptions, } from "./server/renderToStaticSVG";
3
+ export { renderToAnimatedGif, generateFrameSVGs, generateFrameSequence } from "./server/animatedGif";
4
+ export type { AnimatedGifOptions } from "./server/animatedGif";
5
+ export { resolveTheme, themeStyles } from "./server/themeResolver";
6
+ export type { ThemeInput } from "./server/themeResolver";
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Animated GIF generation from semiotic chart data.
3
+ *
4
+ * Renders a sequence of chart frames by progressively feeding data into
5
+ * PipelineStore, optionally applying transition easing and decay effects,
6
+ * then encoding all frames as an animated GIF.
7
+ *
8
+ * Phases:
9
+ * 1. Sliding window — slice data into progressive windows, render each
10
+ * 2. Transition easing — interpolate enter/update between data windows
11
+ * 3. Decay/pulse — apply age-based opacity fading per frame
12
+ *
13
+ * Requires: sharp (SVG→PNG rasterization), gifenc (GIF encoding)
14
+ * Both are optional dependencies of semiotic.
15
+ */
16
+ import type { SemioticTheme } from "../store/ThemeStore";
17
+ export interface AnimatedGifOptions {
18
+ /** Frames per second (default 12) */
19
+ fps?: number;
20
+ /** Number of data points to advance per frame (default: auto-calculated) */
21
+ stepSize?: number;
22
+ /** Data points visible per frame (default: all data up to current step) */
23
+ windowSize?: number;
24
+ /** Total number of frames (default: auto from data length / stepSize) */
25
+ frameCount?: number;
26
+ /** Lock X axis domain to prevent shifting (default: auto from full data) */
27
+ xExtent?: [number, number];
28
+ /** Lock Y axis domain (default: auto from full data) */
29
+ yExtent?: [number, number];
30
+ /** Transition frames between data steps (0 = no easing, default 4). XY charts only — ordinal charts use instant transitions. */
31
+ transitionFrames?: number;
32
+ /** Easing for transitions (default "ease-out") */
33
+ easing?: "linear" | "ease-out";
34
+ /** Apply decay (age-based fade) to older data points */
35
+ decay?: {
36
+ type: "linear" | "exponential" | "step";
37
+ minOpacity?: number;
38
+ halfLife?: number;
39
+ };
40
+ /** Loop the GIF (default true) */
41
+ loop?: boolean;
42
+ /** Scale factor for resolution (default 1) */
43
+ scale?: number;
44
+ /** Background color */
45
+ background?: string;
46
+ }
47
+ export interface AnimatedGifFrameConfig {
48
+ /** Chart width */
49
+ width: number;
50
+ /** Chart height */
51
+ height: number;
52
+ /** Theme for styling */
53
+ theme: SemioticTheme;
54
+ }
55
+ /**
56
+ * Generate SVG strings for each animation frame.
57
+ * This is the core logic shared between GIF export and client-side preview.
58
+ */
59
+ export declare function generateFrameSVGs(chartType: string, data: Record<string, any>[], props: Record<string, any>, options?: AnimatedGifOptions): string[];
60
+ /**
61
+ * Generate SVG strings from an array of data snapshots.
62
+ *
63
+ * Unlike `generateFrameSVGs` which slices a single array progressively,
64
+ * this accepts pre-built snapshots — each entry is the complete props
65
+ * for one frame. Use for scenarios where data changes non-monotonically
66
+ * (edge deletion, network splits, failover paths).
67
+ *
68
+ * Each snapshot is passed directly to `renderChart()`.
69
+ */
70
+ export declare function generateFrameSequence(component: string, snapshots: Record<string, any>[], baseProps?: Record<string, any>): string[];
71
+ /**
72
+ * Render a chart as an animated GIF.
73
+ *
74
+ * Requires `sharp` (SVG→PNG) and `gifenc` (GIF encoding) as optional dependencies.
75
+ *
76
+ * @returns Buffer containing the animated GIF
77
+ */
78
+ export declare function renderToAnimatedGif(chartType: string, data: Record<string, any>[], props: Record<string, any>, options?: AnimatedGifOptions): Promise<Buffer>;
@@ -4,15 +4,96 @@
4
4
  * Uses the shared SceneToSVG converters (same code used by Stream Frames
5
5
  * for SSR) plus PipelineStore / OrdinalPipelineStore / NetworkPipelineStore
6
6
  * for scene graph computation.
7
+ *
8
+ * Features:
9
+ * - Theme inlining (resolve presets to concrete SVG styles)
10
+ * - Legend rendering (categorical color swatches)
11
+ * - Accessibility (title, desc, role="img")
12
+ * - Grid lines
13
+ * - Annotations (y-threshold, x-threshold, band, label, text, category-highlight)
14
+ * - renderChart HOC-level API
7
15
  */
16
+ import * as React from "react";
8
17
  import type { StreamXYFrameProps } from "../stream/types";
9
18
  import type { StreamNetworkFrameProps } from "../stream/networkTypes";
10
19
  import type { StreamOrdinalFrameProps } from "../stream/ordinalTypes";
11
20
  import type { StreamGeoFrameProps } from "../stream/geoTypes";
21
+ import { type ThemeInput } from "./themeResolver";
12
22
  type FrameType = "xy" | "ordinal" | "network" | "geo";
13
- export declare function renderToStaticSVG(frameType: FrameType, props: StreamXYFrameProps | StreamNetworkFrameProps | StreamOrdinalFrameProps | StreamGeoFrameProps): string;
14
- export declare function renderXYToStaticSVG(props: StreamXYFrameProps): string;
15
- export declare function renderOrdinalToStaticSVG(props: StreamOrdinalFrameProps): string;
16
- export declare function renderNetworkToStaticSVG(props: StreamNetworkFrameProps): string;
17
- export declare function renderGeoToStaticSVG(props: StreamGeoFrameProps): string;
23
+ interface ThemeAwareProps {
24
+ theme?: ThemeInput;
25
+ showLegend?: boolean;
26
+ showGrid?: boolean;
27
+ annotations?: Record<string, any>[];
28
+ title?: string | React.ReactNode;
29
+ description?: string;
30
+ background?: string;
31
+ className?: string;
32
+ legendPosition?: "right" | "left" | "top" | "bottom";
33
+ /** Prefix for SVG element IDs — used by renderDashboard to avoid collisions */
34
+ _idPrefix?: string;
35
+ }
36
+ export declare function renderToStaticSVG(frameType: FrameType, props: (StreamXYFrameProps | StreamNetworkFrameProps | StreamOrdinalFrameProps | StreamGeoFrameProps) & ThemeAwareProps): string;
37
+ export declare function renderXYToStaticSVG(props: StreamXYFrameProps & ThemeAwareProps): string;
38
+ export declare function renderOrdinalToStaticSVG(props: StreamOrdinalFrameProps & ThemeAwareProps): string;
39
+ export declare function renderNetworkToStaticSVG(props: StreamNetworkFrameProps & ThemeAwareProps): string;
40
+ export declare function renderGeoToStaticSVG(props: StreamGeoFrameProps & ThemeAwareProps): string;
41
+ /** Chart component name to frame type + props mapping */
42
+ type ChartName = "LineChart" | "AreaChart" | "StackedAreaChart" | "Scatterplot" | "BubbleChart" | "ConnectedScatterplot" | "Heatmap" | "Sparkline" | "BarChart" | "StackedBarChart" | "GroupedBarChart" | "PieChart" | "DonutChart" | "SwimlaneChart" | "Histogram" | "BoxPlot" | "ViolinPlot" | "SwarmPlot" | "DotPlot" | "RidgelinePlot" | "FunnelChart" | "GaugeChart" | "ForceDirectedGraph" | "SankeyDiagram" | "ChordDiagram" | "TreeDiagram" | "Treemap" | "CirclePack" | "ChoroplethMap" | "ProportionalSymbolMap";
43
+ interface RenderChartOptions {
44
+ /** Output format — currently only "svg" is synchronous */
45
+ format?: "svg";
46
+ }
47
+ /**
48
+ * Render a chart using HOC-level props (categoryAccessor, valueAccessor, etc.)
49
+ * instead of frame-level props (oAccessor, rAccessor, etc.).
50
+ *
51
+ * This is the primary API for AI/MCP workflows.
52
+ */
53
+ export declare function renderChart(component: ChartName, props: Record<string, any>, _options?: RenderChartOptions): string;
54
+ export interface RenderToImageOptions {
55
+ /** Output format */
56
+ format?: "png" | "jpeg";
57
+ /** Scale factor (e.g., 2 for retina) */
58
+ scale?: number;
59
+ /** Background color (overrides theme) */
60
+ background?: string;
61
+ }
62
+ /**
63
+ * Render a chart to a PNG or JPEG Buffer.
64
+ *
65
+ * Requires `sharp` as an optional peer dependency.
66
+ * Falls back to a descriptive error if sharp is not installed.
67
+ */
68
+ export declare function renderToImage(frameTypeOrComponent: FrameType | ChartName, props: Record<string, any>, options?: RenderToImageOptions): Promise<Buffer>;
69
+ export interface DashboardChart {
70
+ /** Frame type or HOC component name */
71
+ component?: ChartName;
72
+ frameType?: FrameType;
73
+ /** Chart props (data, accessors, etc.) */
74
+ props: Record<string, any>;
75
+ /** Span multiple columns (for emphasis="primary") */
76
+ colSpan?: number;
77
+ }
78
+ export interface DashboardLayout {
79
+ /** Number of columns */
80
+ columns?: number;
81
+ /** Gap between charts in pixels */
82
+ gap?: number;
83
+ }
84
+ export interface RenderDashboardOptions {
85
+ title?: string;
86
+ subtitle?: string;
87
+ theme?: ThemeInput;
88
+ width?: number;
89
+ height?: number;
90
+ layout?: DashboardLayout;
91
+ background?: string;
92
+ /** Output format */
93
+ format?: "svg";
94
+ }
95
+ /**
96
+ * Compose multiple charts into a single SVG.
97
+ */
98
+ export declare function renderDashboard(charts: DashboardChart[], options?: RenderDashboardOptions): string;
18
99
  export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Chart-specific prop mapping for renderChart().
3
+ *
4
+ * Each entry maps HOC-level props (categoryAccessor, valueAccessor, etc.)
5
+ * to frame-level props (oAccessor, rAccessor, etc.) for server rendering.
6
+ *
7
+ * Extracted from renderToStaticSVG.tsx's 400-line switch statement to make
8
+ * each chart type independently readable and testable.
9
+ */
10
+ type FrameType = "xy" | "ordinal" | "network" | "geo";
11
+ interface ChartConfig {
12
+ frameType: FrameType;
13
+ /** Build frame props from HOC-level props */
14
+ buildProps: (data: any, colorBy: any, colorScheme: any, common: Record<string, any>, rest: Record<string, any>) => Record<string, any>;
15
+ }
16
+ export declare const CHART_CONFIGS: Record<string, ChartConfig>;
17
+ export {};
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Static annotation rendering for server-side SVG.
3
+ *
4
+ * Supports common annotation types without DOM or React hooks.
5
+ * Converts data coordinates to pixels using provided scales.
6
+ */
7
+ import * as React from "react";
8
+ import type { SemioticTheme } from "../store/ThemeStore";
9
+ interface AnnotationScales {
10
+ x?: (v: any) => number;
11
+ y?: (v: any) => number;
12
+ /** For ordinal charts: band scale */
13
+ o?: {
14
+ (v: string): number | undefined;
15
+ bandwidth?: () => number;
16
+ };
17
+ /** For ordinal charts: value scale */
18
+ r?: (v: number) => number;
19
+ }
20
+ interface AnnotationLayout {
21
+ width: number;
22
+ height: number;
23
+ }
24
+ export interface StaticAnnotationConfig {
25
+ annotations: Record<string, any>[];
26
+ scales: AnnotationScales;
27
+ layout: AnnotationLayout;
28
+ theme: SemioticTheme;
29
+ /** ID prefix for multi-chart documents */
30
+ idPrefix?: string;
31
+ xAccessor?: string;
32
+ yAccessor?: string;
33
+ /** Ordinal projection — determines whether r maps to x or y */
34
+ projection?: "vertical" | "horizontal" | "radial";
35
+ }
36
+ /**
37
+ * Render annotations as static SVG elements.
38
+ */
39
+ export declare function renderStaticAnnotations(config: StaticAnnotationConfig): React.ReactNode;
40
+ export {};