semiotic 3.3.0 → 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 (40) hide show
  1. package/CLAUDE.md +7 -4
  2. package/ai/schema.json +97 -1
  3. package/dist/components/charts/ordinal/BarChart.d.ts +2 -0
  4. package/dist/components/charts/ordinal/DonutChart.d.ts +2 -0
  5. package/dist/components/charts/ordinal/GroupedBarChart.d.ts +4 -0
  6. package/dist/components/charts/ordinal/PieChart.d.ts +2 -0
  7. package/dist/components/charts/ordinal/StackedBarChart.d.ts +4 -0
  8. package/dist/components/realtime/types.d.ts +42 -3
  9. package/dist/components/server/renderToStaticSVG.d.ts +1 -0
  10. package/dist/components/server/serverChartConfigs.d.ts +17 -0
  11. package/dist/components/server/themeResolver.d.ts +4 -0
  12. package/dist/components/store/ThemeStore.d.ts +14 -0
  13. package/dist/components/stream/NetworkPipelineStore.d.ts +7 -1
  14. package/dist/components/stream/geoTypes.d.ts +4 -4
  15. package/dist/components/stream/hoverUtils.d.ts +22 -0
  16. package/dist/components/stream/networkTypes.d.ts +14 -22
  17. package/dist/components/stream/ordinalTypes.d.ts +10 -0
  18. package/dist/components/stream/pipelineDecay.d.ts +6 -5
  19. package/dist/components/stream/types.d.ts +4 -0
  20. package/dist/geo.min.js +1 -1
  21. package/dist/geo.module.min.js +1 -1
  22. package/dist/network.min.js +1 -1
  23. package/dist/network.module.min.js +1 -1
  24. package/dist/ordinal.min.js +1 -1
  25. package/dist/ordinal.module.min.js +1 -1
  26. package/dist/realtime.min.js +1 -1
  27. package/dist/realtime.module.min.js +1 -1
  28. package/dist/semiotic-ai.min.js +1 -1
  29. package/dist/semiotic-ai.module.min.js +1 -1
  30. package/dist/semiotic-themes.min.js +1 -1
  31. package/dist/semiotic-themes.module.min.js +1 -1
  32. package/dist/semiotic-utils.min.js +1 -1
  33. package/dist/semiotic-utils.module.min.js +1 -1
  34. package/dist/semiotic.min.js +1 -1
  35. package/dist/semiotic.module.min.js +1 -1
  36. package/dist/server.min.js +1 -1
  37. package/dist/server.module.min.js +1 -1
  38. package/dist/xy.min.js +1 -1
  39. package/dist/xy.module.min.js +1 -1
  40. package/package.json +1 -1
package/CLAUDE.md CHANGED
@@ -27,12 +27,14 @@
27
27
  **QuadrantChart** — Scatterplot + `quadrants` (required), `xCenter`, `yCenter`
28
28
  **MultiAxisLineChart** — Dual Y-axis. `series` (required: `[{ yAccessor, label?, color?, format?, extent? }]`). Falls back to multi-line if not 2 series.
29
29
  **Heatmap** — `data`, `xAccessor`, `yAccessor`, `valueAccessor`, `colorScheme`, `showValues`, `cellBorderColor`
30
+ **ScatterplotMatrix** — `data`, `fields` (array of numeric field names for grid)
31
+ **MinimapChart** — Overview + detail with linked zoom. Wraps an XY chart.
30
32
 
31
33
  ## Ordinal Charts (`semiotic/ordinal`)
32
34
 
33
35
  **BarChart** — `data`, `categoryAccessor`, `valueAccessor`, `orientation`, `colorBy`, `sort`, `barPadding` (40)
34
- **StackedBarChart** — + `stackBy` (required), `normalize`
35
- **GroupedBarChart** — + `groupBy` (required), `barPadding` (60)
36
+ **StackedBarChart** — + `stackBy` (required), `normalize`, `sort` (default false — insertion order)
37
+ **GroupedBarChart** — + `groupBy` (required), `barPadding` (60), `sort` (default false — insertion order)
36
38
  **SwarmPlot** — `colorBy`, `sizeBy`, `pointRadius`, `pointOpacity`
37
39
  **BoxPlot** — + `showOutliers`, `outlierRadius`
38
40
  **Histogram** — + `bins` (25), `relative`. Always horizontal.
@@ -91,7 +93,7 @@ ref.current.clear()
91
93
  ref.current.getData()
92
94
  <Scatterplot ref={ref} xAccessor="x" yAccessor="y" pointIdAccessor="id" />
93
95
  ```
94
- `remove()` and `update()` require an ID accessor: `pointIdAccessor` on XY/realtime charts, `dataIdAccessor` on ordinal charts. Network HOC refs also use `remove(id)`/`update(id, updater)` (operates on nodes). For edge-level operations, use `StreamNetworkFrameHandle` directly: `removeNode(id)`, `removeEdge(sourceId, targetId)`, `updateNode(id, updater)`, `updateEdge(sourceId, targetId, updater)`.
96
+ `remove()` and `update()` require an ID accessor: `pointIdAccessor` on XY/realtime charts, `dataIdAccessor` on ordinal charts. Network HOC refs also use `remove(id)`/`update(id, updater)` (operates on nodes). For edge-level operations, use `StreamNetworkFrameHandle` directly: `removeNode(id)`, `removeEdge(sourceId, targetId)` or `removeEdge(edgeId)` (requires `edgeIdAccessor`), `updateNode(id, updater)`, `updateEdge(sourceId, targetId, updater)`.
95
97
  Not supported: Tree, Treemap, CirclePack, Orbit, ChoroplethMap, FlowMap, ScatterplotMatrix.
96
98
 
97
99
  ## Coordinated Views
@@ -150,7 +152,7 @@ All HOCs accept `annotations` (array). Coordinates use data field names.
150
152
 
151
153
  ## Theming
152
154
 
153
- CSS custom properties: `--semiotic-bg`, `--semiotic-text`, `--semiotic-text-secondary`, `--semiotic-border`, `--semiotic-grid`, `--semiotic-primary`, `--semiotic-focus`, `--semiotic-font-family`, `--semiotic-tooltip-bg`/`text`/`radius`/`font-size`/`shadow`.
155
+ CSS custom properties: `--semiotic-bg`, `--semiotic-text`, `--semiotic-text-secondary`, `--semiotic-border`, `--semiotic-grid`, `--semiotic-primary`, `--semiotic-focus`, `--semiotic-font-family`, `--semiotic-annotation-color`, `--semiotic-legend-font-size`, `--semiotic-title-font-size`, `--semiotic-tick-font-family`, `--semiotic-tooltip-bg`/`text`/`radius`/`font-size`/`shadow`.
154
156
 
155
157
  ```jsx
156
158
  <ThemeProvider theme="tufte"> {/* Named preset */}
@@ -174,6 +176,7 @@ Serialization: `themeToCSS(theme, selector)`, `themeToTokens(theme)`, `resolveTh
174
176
  - **Legend**: "bottom" expands margin ~80px. MultiAxisLineChart: use `legendPosition="bottom"`.
175
177
  - **Log scale**: Domain min clamped to 1e-6.
176
178
  - **barPadding**: Pixel value (40/60 default). Reduce for small charts.
179
+ - **sort on StackedBarChart/GroupedBarChart**: Default `false` preserves insertion order. The underlying frame defaults to value-descending if `oSort` is undefined, so always pass `sort` explicitly if order matters.
177
180
  - **Horizontal bars**: Need wider left margin: `margin={{ left: 120 }}`.
178
181
  - **Push API**: Omit `data` entirely. `data={[]}` clears on every render.
179
182
  - **frameProps style functions**: Bypass HOC color resolution — use `colorBy` prop instead.
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.3.0",
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
  }
@@ -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;
@@ -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;
@@ -29,6 +29,7 @@ interface ThemeAwareProps {
29
29
  description?: string;
30
30
  background?: string;
31
31
  className?: string;
32
+ legendPosition?: "right" | "left" | "top" | "bottom";
32
33
  /** Prefix for SVG element IDs — used by renderDashboard to avoid collisions */
33
34
  _idPrefix?: string;
34
35
  }
@@ -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 {};
@@ -32,4 +32,8 @@ export declare function themeStyles(theme: SemioticTheme): {
32
32
  labelSize: number;
33
33
  tickSize: number;
34
34
  categorical: string[];
35
+ annotation: string;
36
+ legendSize: number;
37
+ titleFontSize: number;
38
+ tickFontFamily: string;
35
39
  };
@@ -16,12 +16,20 @@ export interface SemioticTheme {
16
16
  selection?: string;
17
17
  /** Opacity for non-selected (dimmed) elements, 0–1 */
18
18
  selectionOpacity?: number;
19
+ /** Default annotation text/marker color. Falls back to `text` if unset. */
20
+ annotation?: string;
19
21
  };
20
22
  typography: {
21
23
  fontFamily: string;
22
24
  titleSize: number;
23
25
  labelSize: number;
24
26
  tickSize: number;
27
+ /** Font size for legend text. Falls back to `labelSize` if unset. */
28
+ legendSize?: number;
29
+ /** Font family for axis tick labels. Use monospace for aligned numerics. Falls back to `fontFamily`. */
30
+ tickFontFamily?: string;
31
+ /** Font size for chart title. Falls back to `titleSize` if unset. */
32
+ titleFontSize?: number;
25
33
  };
26
34
  tooltip?: {
27
35
  background?: string;
@@ -31,6 +39,12 @@ export interface SemioticTheme {
31
39
  shadow?: string;
32
40
  };
33
41
  borderRadius?: string;
42
+ accessibility?: {
43
+ /** Auto-swap to color-blind safe palette when true */
44
+ colorBlindSafe?: boolean;
45
+ /** Enforce minimum 3:1 contrast ratios */
46
+ highContrast?: boolean;
47
+ };
34
48
  }
35
49
  /** Color-blind safe categorical palette (8 colors).
36
50
  * Derived from Wong (2011) "Points of view: Color blindness" — safe for
@@ -145,6 +145,12 @@ export declare class NetworkPipelineStore {
145
145
  * Handles parallel edges (multiple edges between the same pair).
146
146
  * Returns true if at least one edge was removed.
147
147
  */
148
- removeEdge(sourceId: string, targetId: string): boolean;
148
+ /**
149
+ * Remove edges by source+target IDs, or by edge ID when edgeIdAccessor is configured.
150
+ *
151
+ * - `removeEdge(sourceId, targetId)` — removes all parallel edges between endpoints
152
+ * - `removeEdge(edgeId)` — removes the edge matching edgeIdAccessor (requires config.edgeIdAccessor)
153
+ */
154
+ removeEdge(sourceIdOrEdgeId: string, targetId?: string): boolean;
149
155
  clear(): void;
150
156
  }
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { GeoProjection, GeoPath, GeoPermissibleObjects } from "d3-geo";
3
3
  import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, PointSceneNode, LineSceneNode } from "./types";
4
- import type { HoverAnnotationConfig } from "../realtime/types";
4
+ import type { HoverAnnotationConfig, HoverData } from "../realtime/types";
5
5
  import type { GeoParticleStyle } from "./GeoParticlePool";
6
6
  export type ProjectionProp = GeoProjection | ProjectionName | ProjectionConfig;
7
7
  export type ProjectionName = "mercator" | "equalEarth" | "albersUsa" | "orthographic" | "naturalEarth" | "equirectangular";
@@ -139,9 +139,9 @@ export interface StreamGeoFrameProps<T = Record<string, any>> {
139
139
  colorScheme?: string | string[];
140
140
  enableHover?: boolean;
141
141
  hoverAnnotation?: boolean | HoverAnnotationConfig;
142
- tooltipContent?: (d: any) => ReactNode;
143
- customClickBehavior?: (d: any) => void;
144
- customHoverBehavior?: (d: any) => void;
142
+ tooltipContent?: (d: HoverData) => ReactNode;
143
+ customClickBehavior?: (d: HoverData | null) => void;
144
+ customHoverBehavior?: (d: HoverData | null) => void;
145
145
  annotations?: Record<string, any>[];
146
146
  decay?: DecayConfig;
147
147
  pulse?: PulseConfig;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared hover data utilities for stream frames.
3
+ *
4
+ * Centralizes the common HoverData construction pattern used by
5
+ * XY, Ordinal, and Network stream frames for hover and click events.
6
+ * Geo frame and keyboard navigation use variants with additional
7
+ * property flattening that are handled at the call site.
8
+ */
9
+ import type { HoverData } from "../realtime/types";
10
+ /**
11
+ * Spread raw datum properties onto HoverData if it's a non-null,
12
+ * non-array object. Class instances (Date, etc.) are included —
13
+ * this matches the historical behavior where all datum fields are
14
+ * accessible directly on the hover object (d.fieldName).
15
+ */
16
+ export declare function spreadDatum(rawDatum: any): Record<string, any>;
17
+ /**
18
+ * Build a HoverData object from a raw datum and pixel coordinates.
19
+ * Spreads plain-object datum properties for backwards compatibility
20
+ * (consumers can access d.fieldName directly in addition to d.data.fieldName).
21
+ */
22
+ export declare function buildHoverData(rawDatum: any, x: number, y: number, extra?: Partial<HoverData>): HoverData;
@@ -168,13 +168,16 @@ export interface NetworkRectNode {
168
168
  _pulseGlowRadius?: number;
169
169
  }
170
170
  /** Arc node — used by chord */
171
+ /** Arc node — used by chord. Angles in canvas convention (0 = 3 o'clock). */
171
172
  export interface NetworkArcNode {
172
173
  type: "arc";
173
174
  cx: number;
174
175
  cy: number;
175
176
  innerR: number;
176
177
  outerR: number;
178
+ /** Start angle in radians, canvas convention (0 = 3 o'clock, positive = clockwise) */
177
179
  startAngle: number;
180
+ /** End angle in radians, canvas convention */
178
181
  endAngle: number;
179
182
  style: Style;
180
183
  datum: any;
@@ -290,8 +293,10 @@ export interface NetworkPipelineConfig {
290
293
  sourceAccessor?: string | ((d: any) => string);
291
294
  targetAccessor?: string | ((d: any) => string);
292
295
  valueAccessor?: string | ((d: any) => number);
296
+ /** Edge ID accessor for removeEdge(edgeId) — enables single-ID edge removal */
297
+ edgeIdAccessor?: string | ((d: any) => string);
293
298
  childrenAccessor?: string | ((d: any) => any[]);
294
- hierarchySum?: (d: any) => number;
299
+ hierarchySum?: string | ((d: any) => number);
295
300
  orientation?: "horizontal" | "vertical";
296
301
  nodeAlign?: "justify" | "left" | "right" | "center";
297
302
  nodePaddingRatio?: number;
@@ -370,8 +375,10 @@ export interface StreamNetworkFrameProps<T = Record<string, any>> {
370
375
  sourceAccessor?: string | ((d: T) => string);
371
376
  targetAccessor?: string | ((d: T) => string);
372
377
  valueAccessor?: string | ((d: T) => number);
378
+ /** Edge ID accessor for removeEdge(edgeId) single-ID removal */
379
+ edgeIdAccessor?: string | ((d: any) => string);
373
380
  childrenAccessor?: string | ((d: T) => T[]);
374
- hierarchySum?: (d: T) => number;
381
+ hierarchySum?: string | ((d: T) => number);
375
382
  orientation?: "horizontal" | "vertical";
376
383
  nodeAlign?: "justify" | "left" | "right" | "center";
377
384
  nodePaddingRatio?: number;
@@ -413,24 +420,9 @@ export interface StreamNetworkFrameProps<T = Record<string, any>> {
413
420
  className?: string;
414
421
  background?: string;
415
422
  enableHover?: boolean;
416
- tooltipContent?: (d: {
417
- type: "node" | "edge";
418
- data: any;
419
- x: number;
420
- y: number;
421
- }) => ReactNode;
422
- customHoverBehavior?: (d: {
423
- type: "node" | "edge";
424
- data: any;
425
- x: number;
426
- y: number;
427
- } | null) => void;
428
- customClickBehavior?: (d: {
429
- type: "node" | "edge";
430
- data: any;
431
- x: number;
432
- y: number;
433
- } | null) => void;
423
+ tooltipContent?: (d: HoverData) => ReactNode;
424
+ customHoverBehavior?: (d: HoverData | null) => void;
425
+ customClickBehavior?: (d: HoverData | null) => void;
434
426
  /** Observation callback — emits hover/click events to the ObservationStore and this callback */
435
427
  onObservation?: OnObservationCallback;
436
428
  /** Chart instance identifier for observation filtering */
@@ -477,8 +469,8 @@ export interface StreamNetworkFrameHandle {
477
469
  pushMany(edges: EdgePush[]): void;
478
470
  /** Remove a node by ID. Also removes connected edges. */
479
471
  removeNode(id: string): boolean;
480
- /** Remove all edges between source and target node IDs. */
481
- removeEdge(sourceId: string, targetId: string): boolean;
472
+ /** Remove edges by source+target, or by edge ID when edgeIdAccessor is configured. */
473
+ removeEdge(sourceIdOrEdgeId: string, targetId?: string): boolean;
482
474
  /** Update a node's data by ID. Returns previous data. */
483
475
  updateNode(id: string, updater: (data: Record<string, any>) => Record<string, any>): Record<string, any> | null;
484
476
  /** Update all edges between source+target. Returns array of previous data. */
@@ -15,8 +15,12 @@ export interface WedgeSceneNode {
15
15
  cy: number;
16
16
  innerRadius: number;
17
17
  outerRadius: number;
18
+ /** Start angle in radians, canvas convention (0 = 3 o'clock, positive = clockwise) */
18
19
  startAngle: number;
20
+ /** End angle in radians, canvas convention */
19
21
  endAngle: number;
22
+ /** Corner radius for rounded wedge arcs (d3-shape arc.cornerRadius) */
23
+ cornerRadius?: number;
20
24
  style: Style;
21
25
  datum: any;
22
26
  category?: string;
@@ -161,9 +165,13 @@ export interface OrdinalPipelineConfig {
161
165
  rExtent?: [number?, number?];
162
166
  oExtent?: string[];
163
167
  barPadding?: number;
168
+ /** Rounded top corner radius for bar charts. Only the end away from the baseline is rounded. For stacked bars, only the topmost segment gets rounded. */
169
+ roundedTop?: number;
164
170
  /** When true, adds padding below the 0 baseline. When false (default), bars are flush with the axis line. */
165
171
  baselinePadding?: boolean;
166
172
  innerRadius?: number;
173
+ /** Corner radius for rounded wedge arcs (pie/donut) */
174
+ cornerRadius?: number;
167
175
  normalize?: boolean;
168
176
  startAngle?: number;
169
177
  /** Total arc sweep in degrees (default 360 = full circle). Used by GaugeChart for partial arcs. */
@@ -213,8 +221,10 @@ export interface StreamOrdinalFrameProps<T = Record<string, any>> {
213
221
  left?: number;
214
222
  };
215
223
  barPadding?: number;
224
+ roundedTop?: number;
216
225
  baselinePadding?: boolean;
217
226
  innerRadius?: number;
227
+ cornerRadius?: number;
218
228
  normalize?: boolean;
219
229
  startAngle?: number;
220
230
  sweepAngle?: number;
@@ -1,11 +1,12 @@
1
1
  /**
2
- * Decay encoding for XY pipeline scene nodes.
2
+ * Shared decay encoding utilities for all pipeline stores.
3
3
  *
4
- * Applies age-based opacity fade to scene nodes linear, exponential, or step.
5
- * Per-vertex decay for line/area nodes, uniform for discrete nodes (point, rect, etc.).
4
+ * `computeDecayOpacity()` core algorithm used by all four pipeline stores
5
+ * (XY, Ordinal, Network, Geo) to compute age-based opacity.
6
6
  *
7
- * Dependencies: types (SceneNode, DecayConfig)
8
- * Consumed by: PipelineStore.computeScene (after scene build, before transitions)
7
+ * `applyDecay()` XY-specific application that handles per-vertex decay
8
+ * for line/area nodes. Other stores call `computeDecayOpacity()` directly
9
+ * with their own node iteration logic.
9
10
  */
10
11
  import type { SceneNode, DecayConfig } from "./types";
11
12
  /**
@@ -187,6 +187,10 @@ export interface RectSceneNode {
187
187
  y: number;
188
188
  w: number;
189
189
  h: number;
190
+ /** Rounded corner radius on the end away from the baseline */
191
+ roundedTop?: number;
192
+ /** Which edge to round: "top"/"bottom" (vertical), "right"/"left" (horizontal) */
193
+ roundedEdge?: "top" | "bottom" | "right" | "left";
190
194
  style: Style;
191
195
  datum: any;
192
196
  group?: string;