semiotic 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +16 -7
- package/README.md +1 -1
- package/ai/dist/mcp-server.js +104 -9
- package/ai/schema.json +97 -1
- package/dist/components/LinkedCharts.d.ts +8 -0
- package/dist/components/charts/index.d.ts +1 -1
- package/dist/components/charts/ordinal/BarChart.d.ts +9 -1
- package/dist/components/charts/ordinal/DonutChart.d.ts +2 -0
- package/dist/components/charts/ordinal/DotPlot.d.ts +9 -1
- package/dist/components/charts/ordinal/GroupedBarChart.d.ts +4 -0
- package/dist/components/charts/ordinal/LikertChart.d.ts +5 -2
- package/dist/components/charts/ordinal/PieChart.d.ts +2 -0
- package/dist/components/charts/ordinal/StackedBarChart.d.ts +4 -0
- package/dist/components/charts/shared/hooks.d.ts +15 -2
- package/dist/components/charts/shared/selectionUtils.d.ts +9 -7
- package/dist/components/charts/shared/tooltipUtils.d.ts +13 -1
- package/dist/components/charts/shared/types.d.ts +5 -6
- package/dist/components/charts/shared/useChartSetup.d.ts +8 -0
- package/dist/components/charts/shared/useResolvedSelection.d.ts +2 -0
- package/dist/components/realtime/types.d.ts +54 -3
- package/dist/components/semiotic-geo.d.ts +4 -0
- package/dist/components/semiotic-network.d.ts +7 -0
- package/dist/components/semiotic-ordinal.d.ts +8 -0
- package/dist/components/semiotic-xy.d.ts +9 -0
- package/dist/components/server/renderToStaticSVG.d.ts +2 -1
- package/dist/components/server/serverChartConfigs.d.ts +17 -0
- package/dist/components/server/themeResolver.d.ts +4 -0
- package/dist/components/store/ThemeStore.d.ts +16 -0
- package/dist/components/stream/CanvasHitTester.d.ts +8 -3
- package/dist/components/stream/DataSourceAdapter.d.ts +17 -0
- package/dist/components/stream/GeoCanvasHitTester.d.ts +1 -1
- package/dist/components/stream/GeoPipelineStore.d.ts +19 -1
- package/dist/components/stream/NetworkPipelineStore.d.ts +12 -1
- package/dist/components/stream/OrdinalCanvasHitTester.d.ts +3 -1
- package/dist/components/stream/OrdinalPipelineStore.d.ts +38 -1
- package/dist/components/stream/ParticlePool.d.ts +4 -0
- package/dist/components/stream/PipelineStore.d.ts +17 -2
- package/dist/components/stream/StreamXYFrame.d.ts +17 -0
- package/dist/components/stream/geoTypes.d.ts +11 -4
- package/dist/components/stream/hoverUtils.d.ts +34 -0
- package/dist/components/stream/networkTypes.d.ts +33 -23
- package/dist/components/stream/ordinalTypes.d.ts +63 -12
- package/dist/components/stream/pipelineDecay.d.ts +6 -5
- package/dist/components/stream/pipelineTransitionUtils.d.ts +21 -0
- package/dist/components/stream/quadtreeHitTest.d.ts +22 -0
- package/dist/components/stream/renderers/resolveCSSColor.d.ts +23 -6
- package/dist/components/stream/types.d.ts +22 -0
- package/dist/components/stream/useFrame.d.ts +122 -0
- package/dist/geo.min.js +1 -1
- package/dist/geo.module.min.js +1 -1
- package/dist/network.min.js +1 -1
- package/dist/network.module.min.js +1 -1
- package/dist/ordinal.min.js +1 -1
- package/dist/ordinal.module.min.js +1 -1
- package/dist/realtime.min.js +1 -1
- package/dist/realtime.module.min.js +1 -1
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-geo.d.ts +4 -0
- package/dist/semiotic-network.d.ts +7 -0
- package/dist/semiotic-ordinal.d.ts +8 -0
- package/dist/semiotic-themes.min.js +1 -1
- package/dist/semiotic-themes.module.min.js +1 -1
- package/dist/semiotic-utils.min.js +1 -1
- package/dist/semiotic-utils.module.min.js +1 -1
- package/dist/semiotic-xy.d.ts +9 -0
- package/dist/semiotic.min.js +1 -1
- package/dist/semiotic.module.min.js +1 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/test-utils/canvasMock.d.ts +26 -0
- package/dist/test-utils/ordinalFixtures.d.ts +48 -0
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +15 -14
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
2
|
import type { MarginType } from "../../types/generalTypes";
|
|
3
3
|
import type { OnObservationCallback } from "../../store/ObservationStore";
|
|
4
|
+
import type { AnimateProp } from "../../stream/pipelineTransitionUtils";
|
|
4
5
|
/**
|
|
5
6
|
* Selection consumption config — makes this chart react to a named selection
|
|
6
7
|
*/
|
|
@@ -103,12 +104,10 @@ export interface BaseChartProps {
|
|
|
103
104
|
dataIdAccessor?: string | ((d: any) => string);
|
|
104
105
|
/** Visual emphasis level for dashboard hierarchy. "primary" spans two columns in ChartGrid. */
|
|
105
106
|
emphasis?: "primary" | "secondary";
|
|
106
|
-
/** Enable declarative bounded animation (enter/exit/update transitions).
|
|
107
|
-
* `true` uses defaults (300ms ease-out). Object form allows customization.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
easing?: "linear" | "ease-out";
|
|
111
|
-
};
|
|
107
|
+
/** Enable declarative bounded animation (enter/exit/update transitions + intro).
|
|
108
|
+
* `true` uses defaults (300ms ease-out, intro enabled). Object form allows customization.
|
|
109
|
+
* Set `{ intro: false }` to disable the animated intro on first render. */
|
|
110
|
+
animate?: AnimateProp;
|
|
112
111
|
}
|
|
113
112
|
/**
|
|
114
113
|
* Axis configuration props
|
|
@@ -104,6 +104,14 @@ export interface ChartSetupResult {
|
|
|
104
104
|
linkedCrosshairName: string;
|
|
105
105
|
linkedCrosshairSourceId: string;
|
|
106
106
|
} | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Selection config merged with theme-level defaults. HOCs should pass this
|
|
109
|
+
* to `wrapStyleWithSelection` instead of the raw `selection` prop so that
|
|
110
|
+
* the current theme's `colors.selectionOpacity` becomes the effective
|
|
111
|
+
* unselected-opacity fallback. Per-chart `selection.unselectedOpacity`
|
|
112
|
+
* still takes priority over the theme value.
|
|
113
|
+
*/
|
|
114
|
+
resolvedSelection: SelectionConfig | undefined;
|
|
107
115
|
}
|
|
108
116
|
/**
|
|
109
117
|
* Hook that consolidates the shared boilerplate across all HOC charts:
|
|
@@ -64,11 +64,50 @@ export interface HoverAnnotationConfig {
|
|
|
64
64
|
pointColor?: string;
|
|
65
65
|
}
|
|
66
66
|
export interface HoverData {
|
|
67
|
-
data
|
|
68
|
-
|
|
69
|
-
|
|
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;
|
|
@@ -137,6 +176,18 @@ export interface RealtimeFrameHandle {
|
|
|
137
176
|
update(id: string | string[], updater: (d: Record<string, any>) => Record<string, any>): Record<string, any>[];
|
|
138
177
|
clear(): void;
|
|
139
178
|
getData(): Record<string, any>[];
|
|
179
|
+
/** Returns the frame's resolved scales, or null if unavailable.
|
|
180
|
+
*
|
|
181
|
+
* The concrete scales object differs by frame type — XY charts
|
|
182
|
+
* expose `{ x, y }`, ordinal charts expose `{ o, r, projection }`,
|
|
183
|
+
* network/geo don't have a meaningful scale concept and may not
|
|
184
|
+
* implement this method at all.
|
|
185
|
+
*
|
|
186
|
+
* Typed as `unknown` so the shared handle stays compatible across
|
|
187
|
+
* chart families. HOCs that want a narrower return type should
|
|
188
|
+
* export a chart-specific handle (e.g. `LikertChartHandle`) that
|
|
189
|
+
* extends this interface and narrows `getScales()`. */
|
|
190
|
+
getScales?(): unknown | null;
|
|
140
191
|
}
|
|
141
192
|
export interface RealtimeScales {
|
|
142
193
|
time: ScaleLinear<number, number>;
|
|
@@ -14,3 +14,7 @@ export { mergeData } from "./geo/mergeData";
|
|
|
14
14
|
export { resolveReferenceGeography } from "./geo/referenceGeography";
|
|
15
15
|
export type { ReferenceGeography } from "./geo/referenceGeography";
|
|
16
16
|
export type { AreasProp } from "./geo/useReferenceAreas";
|
|
17
|
+
export type { ChoroplethMapProps } from "./charts/geo/ChoroplethMap";
|
|
18
|
+
export type { ProportionalSymbolMapProps } from "./charts/geo/ProportionalSymbolMap";
|
|
19
|
+
export type { FlowMapProps } from "./charts/geo/FlowMap";
|
|
20
|
+
export type { DistanceCartogramProps } from "./charts/geo/DistanceCartogram";
|
|
@@ -12,3 +12,10 @@ export { Treemap } from "./charts/network/Treemap";
|
|
|
12
12
|
export { CirclePack } from "./charts/network/CirclePack";
|
|
13
13
|
export { OrbitDiagram } from "./charts/network/OrbitDiagram";
|
|
14
14
|
export type { StreamNetworkFrameProps, StreamNetworkFrameHandle, NetworkChartType, NetworkSceneNode, NetworkSceneEdge, NetworkLabel, ThresholdAlertConfig } from "./stream/networkTypes";
|
|
15
|
+
export type { ForceDirectedGraphProps } from "./charts/network/ForceDirectedGraph";
|
|
16
|
+
export type { SankeyDiagramProps } from "./charts/network/SankeyDiagram";
|
|
17
|
+
export type { ChordDiagramProps } from "./charts/network/ChordDiagram";
|
|
18
|
+
export type { TreeDiagramProps } from "./charts/network/TreeDiagram";
|
|
19
|
+
export type { TreemapProps } from "./charts/network/Treemap";
|
|
20
|
+
export type { CirclePackProps } from "./charts/network/CirclePack";
|
|
21
|
+
export type { OrbitDiagramProps } from "./charts/network/OrbitDiagram";
|
|
@@ -23,3 +23,11 @@ export { LikertChart } from "./charts/ordinal/LikertChart";
|
|
|
23
23
|
export { createHatchPattern } from "./charts/shared/hatchPattern";
|
|
24
24
|
export type { HatchPatternOptions } from "./charts/shared/hatchPattern";
|
|
25
25
|
export type { StreamOrdinalFrameProps, StreamOrdinalFrameHandle, OrdinalChartType, OrdinalScales, OrdinalSceneNode } from "./stream/ordinalTypes";
|
|
26
|
+
export type { BarChartProps } from "./charts/ordinal/BarChart";
|
|
27
|
+
export type { StackedBarChartProps } from "./charts/ordinal/StackedBarChart";
|
|
28
|
+
export type { GroupedBarChartProps } from "./charts/ordinal/GroupedBarChart";
|
|
29
|
+
export type { SwimlaneChartProps } from "./charts/ordinal/SwimlaneChart";
|
|
30
|
+
export type { PieChartProps } from "./charts/ordinal/PieChart";
|
|
31
|
+
export type { DonutChartProps } from "./charts/ordinal/DonutChart";
|
|
32
|
+
export type { FunnelChartProps } from "./charts/ordinal/FunnelChart";
|
|
33
|
+
export type { LikertChartProps } from "./charts/ordinal/LikertChart";
|
|
@@ -16,3 +16,12 @@ export { MinimapChart } from "./charts/xy/MinimapChart";
|
|
|
16
16
|
export { QuadrantChart } from "./charts/xy/QuadrantChart";
|
|
17
17
|
export { MultiAxisLineChart } from "./charts/xy/MultiAxisLineChart";
|
|
18
18
|
export type { StreamXYFrameProps, StreamXYFrameHandle } from "./stream/types";
|
|
19
|
+
export type { LineChartProps } from "./charts/xy/LineChart";
|
|
20
|
+
export type { AreaChartProps } from "./charts/xy/AreaChart";
|
|
21
|
+
export type { StackedAreaChartProps } from "./charts/xy/StackedAreaChart";
|
|
22
|
+
export type { ScatterplotProps } from "./charts/xy/Scatterplot";
|
|
23
|
+
export type { ConnectedScatterplotProps } from "./charts/xy/ConnectedScatterplot";
|
|
24
|
+
export type { BubbleChartProps } from "./charts/xy/BubbleChart";
|
|
25
|
+
export type { HeatmapProps } from "./charts/xy/Heatmap";
|
|
26
|
+
export type { QuadrantChartProps } from "./charts/xy/QuadrantChart";
|
|
27
|
+
export type { MultiAxisLineChartProps } from "./charts/xy/MultiAxisLineChart";
|
|
@@ -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
|
}
|
|
@@ -38,7 +39,7 @@ export declare function renderOrdinalToStaticSVG(props: StreamOrdinalFrameProps
|
|
|
38
39
|
export declare function renderNetworkToStaticSVG(props: StreamNetworkFrameProps & ThemeAwareProps): string;
|
|
39
40
|
export declare function renderGeoToStaticSVG(props: StreamGeoFrameProps & ThemeAwareProps): string;
|
|
40
41
|
/** Chart component name to frame type + props mapping */
|
|
41
|
-
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";
|
|
42
|
+
type ChartName = "LineChart" | "AreaChart" | "StackedAreaChart" | "Scatterplot" | "BubbleChart" | "ConnectedScatterplot" | "Heatmap" | "Sparkline" | "BarChart" | "StackedBarChart" | "GroupedBarChart" | "PieChart" | "DonutChart" | "SwimlaneChart" | "Histogram" | "BoxPlot" | "ViolinPlot" | "SwarmPlot" | "DotPlot" | "RidgelinePlot" | "LikertChart" | "FunnelChart" | "GaugeChart" | "ForceDirectedGraph" | "SankeyDiagram" | "ChordDiagram" | "TreeDiagram" | "Treemap" | "CirclePack" | "ChoroplethMap" | "ProportionalSymbolMap" | "FlowMap";
|
|
42
43
|
interface RenderChartOptions {
|
|
43
44
|
/** Output format — currently only "svg" is synchronous */
|
|
44
45
|
format?: "svg";
|
|
@@ -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 {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Apply accessibility flags to a resolved theme. Shared by ThemeStore and server themeResolver. */
|
|
2
|
+
export declare function applyThemeAccessibility(theme: SemioticTheme): SemioticTheme;
|
|
1
3
|
export interface SemioticTheme {
|
|
2
4
|
mode: "light" | "dark" | "auto";
|
|
3
5
|
colors: {
|
|
@@ -16,12 +18,20 @@ export interface SemioticTheme {
|
|
|
16
18
|
selection?: string;
|
|
17
19
|
/** Opacity for non-selected (dimmed) elements, 0–1 */
|
|
18
20
|
selectionOpacity?: number;
|
|
21
|
+
/** Default annotation text/marker color. Falls back to `text` if unset. */
|
|
22
|
+
annotation?: string;
|
|
19
23
|
};
|
|
20
24
|
typography: {
|
|
21
25
|
fontFamily: string;
|
|
22
26
|
titleSize: number;
|
|
23
27
|
labelSize: number;
|
|
24
28
|
tickSize: number;
|
|
29
|
+
/** Font size for legend text. Falls back to `labelSize` if unset. */
|
|
30
|
+
legendSize?: number;
|
|
31
|
+
/** Font family for axis tick labels. Use monospace for aligned numerics. Falls back to `fontFamily`. */
|
|
32
|
+
tickFontFamily?: string;
|
|
33
|
+
/** Font size for chart title. Falls back to `titleSize` if unset. */
|
|
34
|
+
titleFontSize?: number;
|
|
25
35
|
};
|
|
26
36
|
tooltip?: {
|
|
27
37
|
background?: string;
|
|
@@ -31,6 +41,12 @@ export interface SemioticTheme {
|
|
|
31
41
|
shadow?: string;
|
|
32
42
|
};
|
|
33
43
|
borderRadius?: string;
|
|
44
|
+
accessibility?: {
|
|
45
|
+
/** Auto-swap to color-blind safe palette when true */
|
|
46
|
+
colorBlindSafe?: boolean;
|
|
47
|
+
/** Enforce minimum 3:1 contrast ratios */
|
|
48
|
+
highContrast?: boolean;
|
|
49
|
+
};
|
|
34
50
|
}
|
|
35
51
|
/** Color-blind safe categorical palette (8 colors).
|
|
36
52
|
* Derived from Wong (2011) "Points of view: Color blindness" — safe for
|
|
@@ -13,11 +13,16 @@ export interface HitResult {
|
|
|
13
13
|
* Dispatches to type-specific hit testers for optimal performance.
|
|
14
14
|
*
|
|
15
15
|
* When a quadtree spatial index is provided (for scatter/bubble charts with
|
|
16
|
-
* many points), point hit testing
|
|
17
|
-
*
|
|
16
|
+
* many points), point hit testing routes through `findHitPointInQuadtree`,
|
|
17
|
+
* which visits every candidate within the widened search radius (using
|
|
18
|
+
* `maxPointRadius` so variable-size points like BubbleChart can't hide
|
|
19
|
+
* behind a nearer non-hit). The visit is authoritative — when it returns
|
|
20
|
+
* null, no point hit exists and the linear point loop is skipped.
|
|
21
|
+
*
|
|
22
|
+
* Non-point node types (line, rect, area, heatcell, candlestick) still
|
|
18
23
|
* use the linear scan.
|
|
19
24
|
*/
|
|
20
|
-
export declare function findNearestNode(scene: SceneNode[], px: number, py: number, maxDistance?: number, pointQuadtree?: Quadtree<PointSceneNode> | null): HitResult | null;
|
|
25
|
+
export declare function findNearestNode(scene: SceneNode[], px: number, py: number, maxDistance?: number, pointQuadtree?: Quadtree<PointSceneNode> | null, maxPointRadius?: number): HitResult | null;
|
|
21
26
|
/**
|
|
22
27
|
* Find all line/area nodes at a given X pixel coordinate.
|
|
23
28
|
* For each node, interpolates the Y value at px using the path data.
|
|
@@ -32,6 +32,23 @@ export declare class DataSourceAdapter<T = Record<string, any>> {
|
|
|
32
32
|
* animation frames (bounded: false so they append without clearing).
|
|
33
33
|
*/
|
|
34
34
|
setBoundedData(data: T[]): void;
|
|
35
|
+
/**
|
|
36
|
+
* Replace the buffer contents without clearing category insertion-order
|
|
37
|
+
* memory. Intended for aggregator HOCs (e.g. LikertChart) that re-derive
|
|
38
|
+
* a full dataset from streaming input on every push — the transport is
|
|
39
|
+
* wholesale replacement, but the user perceives it as a live stream
|
|
40
|
+
* where categories should stay put across updates.
|
|
41
|
+
*
|
|
42
|
+
* Small datasets (≤ chunkThreshold) emit a single synchronous
|
|
43
|
+
* changeset — the common aggregator case. Larger datasets fall
|
|
44
|
+
* through to progressive chunking so an unexpectedly-huge replacement
|
|
45
|
+
* doesn't block the main thread. Only the first chunk carries
|
|
46
|
+
* `preserveCategoryOrder: true` (it's the one that resets the
|
|
47
|
+
* buffer and seeds the category Set); subsequent chunks are plain
|
|
48
|
+
* append-only streaming changesets, which preserve order anyway via
|
|
49
|
+
* the streaming-mode branch.
|
|
50
|
+
*/
|
|
51
|
+
setReplacementData(data: T[]): void;
|
|
35
52
|
/**
|
|
36
53
|
* Flush all buffered push data as a single changeset.
|
|
37
54
|
* Called automatically via microtask after push()/pushMany().
|
|
@@ -16,4 +16,4 @@ export interface GeoHitResult {
|
|
|
16
16
|
* The `hitCtx` parameter is a shared offscreen canvas context used for
|
|
17
17
|
* isPointInPath checks without polluting the visible canvas.
|
|
18
18
|
*/
|
|
19
|
-
export declare function findNearestGeoNode(nodes: GeoSceneNode[], mouseX: number, mouseY: number, maxDistance: number, hitCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, pointQuadtree?: Quadtree<PointSceneNode>): GeoHitResult | null;
|
|
19
|
+
export declare function findNearestGeoNode(nodes: GeoSceneNode[], mouseX: number, mouseY: number, maxDistance: number, hitCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, pointQuadtree?: Quadtree<PointSceneNode> | null, maxPointRadius?: number): GeoHitResult | null;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { ZoomTransform } from "d3-zoom";
|
|
2
|
+
import { type Quadtree } from "d3-quadtree";
|
|
2
3
|
import type { GeoPipelineConfig, GeoScales, GeoSceneNode } from "./geoTypes";
|
|
3
|
-
import type { StreamLayout } from "./types";
|
|
4
|
+
import type { PointSceneNode, StreamLayout } from "./types";
|
|
4
5
|
import type { ActiveTransition } from "./pipelineTransitionUtils";
|
|
5
6
|
export declare class GeoPipelineStore {
|
|
6
7
|
config: GeoPipelineConfig;
|
|
7
8
|
scene: GeoSceneNode[];
|
|
8
9
|
scales: GeoScales | null;
|
|
9
10
|
version: number;
|
|
11
|
+
private static readonly QUADTREE_THRESHOLD;
|
|
12
|
+
private _quadtree;
|
|
13
|
+
/** Largest visual point radius in the current scene; used to widen quadtree
|
|
14
|
+
* hit-test radius when points are larger than the default maxDistance. */
|
|
15
|
+
private _maxPointRadius;
|
|
10
16
|
private projection;
|
|
11
17
|
private geoPath;
|
|
12
18
|
private baseScale;
|
|
@@ -28,6 +34,7 @@ export declare class GeoPipelineStore {
|
|
|
28
34
|
private timestampBuffer;
|
|
29
35
|
activeTransition: ActiveTransition | null;
|
|
30
36
|
private prevPositions;
|
|
37
|
+
private _hasRenderedOnce;
|
|
31
38
|
constructor(config: GeoPipelineConfig);
|
|
32
39
|
updateConfig(config: Partial<GeoPipelineConfig>): void;
|
|
33
40
|
setAreas(features: GeoJSON.Feature[]): void;
|
|
@@ -76,6 +83,17 @@ export declare class GeoPipelineStore {
|
|
|
76
83
|
translate: [number, number];
|
|
77
84
|
};
|
|
78
85
|
getPoints(): Record<string, any>[];
|
|
86
|
+
/**
|
|
87
|
+
* Build (or clear) the quadtree spatial index for point scene nodes.
|
|
88
|
+
* Only built when the point count exceeds QUADTREE_THRESHOLD; below that
|
|
89
|
+
* a linear scan is faster than indexing overhead. Also tracks the largest
|
|
90
|
+
* point radius so the hit tester can widen its query when symbols are big.
|
|
91
|
+
*/
|
|
92
|
+
private rebuildQuadtree;
|
|
93
|
+
/** Quadtree spatial index for point hit testing, or null when below threshold. */
|
|
94
|
+
get quadtree(): Quadtree<PointSceneNode> | null;
|
|
95
|
+
/** Largest visual point radius in the current scene. */
|
|
96
|
+
get maxPointRadius(): number;
|
|
79
97
|
private buildSceneNodes;
|
|
80
98
|
private applyCartogramTransform;
|
|
81
99
|
private applyDecay;
|
|
@@ -22,6 +22,11 @@ export declare class NetworkPipelineStore {
|
|
|
22
22
|
private config;
|
|
23
23
|
private tensionConfig;
|
|
24
24
|
transition: ActiveTransition | null;
|
|
25
|
+
private _hasRenderedOnce;
|
|
26
|
+
/** Snapshot of node positions from before bounded re-ingestion cleared the maps */
|
|
27
|
+
private _boundedPrevSnapshot;
|
|
28
|
+
/** Snapshot of edge positions from before bounded re-ingestion cleared the maps */
|
|
29
|
+
private _boundedEdgeSnapshot;
|
|
25
30
|
lastIngestTime: number;
|
|
26
31
|
private nodeTimestamps;
|
|
27
32
|
private edgeTimestamps;
|
|
@@ -145,6 +150,12 @@ export declare class NetworkPipelineStore {
|
|
|
145
150
|
* Handles parallel edges (multiple edges between the same pair).
|
|
146
151
|
* Returns true if at least one edge was removed.
|
|
147
152
|
*/
|
|
148
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Remove edges by source+target IDs, or by edge ID when edgeIdAccessor is configured.
|
|
155
|
+
*
|
|
156
|
+
* - `removeEdge(sourceId, targetId)` — removes all parallel edges between endpoints
|
|
157
|
+
* - `removeEdge(edgeId)` — removes the edge matching edgeIdAccessor (requires config.edgeIdAccessor)
|
|
158
|
+
*/
|
|
159
|
+
removeEdge(sourceIdOrEdgeId: string, targetId?: string): boolean;
|
|
149
160
|
clear(): void;
|
|
150
161
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { OrdinalSceneNode } from "./ordinalTypes";
|
|
2
|
+
import type { PointSceneNode } from "./types";
|
|
3
|
+
import type { Quadtree } from "d3-quadtree";
|
|
2
4
|
export interface OrdinalHitResult {
|
|
3
5
|
datum: any;
|
|
4
6
|
x: number;
|
|
@@ -7,4 +9,4 @@ export interface OrdinalHitResult {
|
|
|
7
9
|
category?: string;
|
|
8
10
|
stats?: import("./ordinalTypes").DistributionStats;
|
|
9
11
|
}
|
|
10
|
-
export declare function findNearestOrdinalNode(scene: OrdinalSceneNode[], px: number, py: number, maxDistance?: number): OrdinalHitResult | null;
|
|
12
|
+
export declare function findNearestOrdinalNode(scene: OrdinalSceneNode[], px: number, py: number, maxDistance?: number, pointQuadtree?: Quadtree<PointSceneNode> | null, maxPointRadius?: number): OrdinalHitResult | null;
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* Consumed by: StreamOrdinalFrame (sole consumer).
|
|
16
16
|
*/
|
|
17
17
|
import { type ScaleLinear } from "d3-scale";
|
|
18
|
+
import { type Quadtree } from "d3-quadtree";
|
|
18
19
|
import type { OrdinalPipelineConfig, OrdinalScales, OrdinalSceneNode, OrdinalColumn, OrdinalLayout } from "./ordinalTypes";
|
|
19
|
-
import type { Changeset } from "./types";
|
|
20
|
+
import type { Changeset, PointSceneNode } from "./types";
|
|
20
21
|
import type { ActiveTransition } from "./pipelineTransitionUtils";
|
|
21
22
|
export declare class OrdinalPipelineStore {
|
|
22
23
|
private buffer;
|
|
@@ -52,6 +53,17 @@ export declare class OrdinalPipelineStore {
|
|
|
52
53
|
scene: OrdinalSceneNode[];
|
|
53
54
|
columns: Record<string, OrdinalColumn>;
|
|
54
55
|
version: number;
|
|
56
|
+
/** Bumped whenever the buffer is mutated. Used to invalidate per-frame caches. */
|
|
57
|
+
private _dataVersion;
|
|
58
|
+
private static readonly QUADTREE_THRESHOLD;
|
|
59
|
+
private _pointQuadtree;
|
|
60
|
+
/** Largest visual point radius in the current scene. */
|
|
61
|
+
private _maxPointRadius;
|
|
62
|
+
/** Cached datum→index map for applyDecay/applyPulse. Keyed by `_dataVersion`. */
|
|
63
|
+
private _datumIndexCache;
|
|
64
|
+
/** Cached category→indices map for applyPulse wedge path. Keyed by `_dataVersion`. */
|
|
65
|
+
private _categoryIndexCache;
|
|
66
|
+
private _hasRenderedOnce;
|
|
55
67
|
constructor(config: OrdinalPipelineConfig);
|
|
56
68
|
ingest(changeset: Changeset): boolean;
|
|
57
69
|
private pushValueExtent;
|
|
@@ -69,9 +81,34 @@ export declare class OrdinalPipelineStore {
|
|
|
69
81
|
private getColorFromScheme;
|
|
70
82
|
private resolveSummaryStyle;
|
|
71
83
|
computeDecayOpacity(bufferIndex: number, bufferSize: number): number;
|
|
84
|
+
/**
|
|
85
|
+
* Build (or return cached) datum→buffer-index map. Cached against
|
|
86
|
+
* `_dataVersion` so the per-frame applyDecay/applyPulse calls don't
|
|
87
|
+
* rebuild it during animation when the buffer hasn't changed.
|
|
88
|
+
*/
|
|
89
|
+
private getDatumIndexMap;
|
|
90
|
+
/**
|
|
91
|
+
* Build (or return cached) category→[indices] map used by applyPulse for
|
|
92
|
+
* wedge nodes. Cached against `_dataVersion` so the per-wedge inner loop
|
|
93
|
+
* collapses from O(data) to O(matches-for-this-category).
|
|
94
|
+
*/
|
|
95
|
+
private getCategoryIndexMap;
|
|
96
|
+
/**
|
|
97
|
+
* Build (or clear) a quadtree spatial index for point scene nodes.
|
|
98
|
+
* Useful for swarm plots — other ordinal types (bar/wedge/box/violin) are
|
|
99
|
+
* not indexed because they're typically few in number or already O(1) hit
|
|
100
|
+
* tests via bbox checks.
|
|
101
|
+
*/
|
|
102
|
+
private rebuildPointQuadtree;
|
|
103
|
+
/** Quadtree spatial index for point hit testing, or null when below threshold. */
|
|
104
|
+
get pointQuadtree(): Quadtree<PointSceneNode> | null;
|
|
105
|
+
/** Largest visual point radius in the current scene. */
|
|
106
|
+
get maxPointRadius(): number;
|
|
72
107
|
private applyDecay;
|
|
73
108
|
private applyPulse;
|
|
74
109
|
get hasActivePulses(): boolean;
|
|
110
|
+
/** Synthesize a zero-state prevPositionMap for animated intro (first render). */
|
|
111
|
+
private synthesizeIntroPositions;
|
|
75
112
|
/** Build a stable identity key for a scene node based on its content, not array index */
|
|
76
113
|
private getNodeKey;
|
|
77
114
|
private snapshotPositions;
|
|
@@ -4,10 +4,14 @@ import type { Particle, RealtimeEdge } from "./networkTypes";
|
|
|
4
4
|
*
|
|
5
5
|
* Pre-allocates a fixed-size array to avoid GC pressure.
|
|
6
6
|
* Particles travel along bezier paths within link bands.
|
|
7
|
+
*
|
|
8
|
+
* `_freeIndices` is a stack of currently-free slot indices. Spawn pops; step
|
|
9
|
+
* pushes when a particle expires. This makes spawn O(1) instead of O(capacity).
|
|
7
10
|
*/
|
|
8
11
|
export declare class ParticlePool {
|
|
9
12
|
particles: Particle[];
|
|
10
13
|
private capacity;
|
|
14
|
+
private _freeIndices;
|
|
11
15
|
constructor(capacity: number);
|
|
12
16
|
/**
|
|
13
17
|
* Spawn a new particle on the given edge.
|
|
@@ -76,11 +76,15 @@ export interface PipelineConfig {
|
|
|
76
76
|
strokeWidth?: number;
|
|
77
77
|
};
|
|
78
78
|
colorScheme?: string | string[];
|
|
79
|
+
/** Theme categorical palette — used as fallback when colorScheme is not an explicit array */
|
|
80
|
+
themeCategorical?: string[];
|
|
79
81
|
barColors?: Record<string, string>;
|
|
80
82
|
annotations?: Record<string, any>[];
|
|
81
83
|
decay?: DecayConfig;
|
|
82
84
|
pulse?: PulseConfig;
|
|
83
85
|
transition?: TransitionConfig;
|
|
86
|
+
/** Whether to animate elements on first render (points scale up, lines/areas clip from left, rects grow from baseline) */
|
|
87
|
+
introAnimation?: boolean;
|
|
84
88
|
staleness?: StalenessConfig;
|
|
85
89
|
heatmapAggregation?: "count" | "sum" | "mean";
|
|
86
90
|
heatmapXBins?: number;
|
|
@@ -111,6 +115,7 @@ export declare class PipelineStore {
|
|
|
111
115
|
private getPointId;
|
|
112
116
|
private timestampBuffer;
|
|
113
117
|
activeTransition: ActiveTransition | null;
|
|
118
|
+
private _hasRenderedOnce;
|
|
114
119
|
private prevPositionMap;
|
|
115
120
|
/** Previous line/area path arrays for path interpolation */
|
|
116
121
|
private prevPathMap;
|
|
@@ -140,6 +145,10 @@ export declare class PipelineStore {
|
|
|
140
145
|
/** True when the x accessor returns Date objects (auto-detected on first data ingestion) */
|
|
141
146
|
xIsDate: boolean;
|
|
142
147
|
private _quadtree;
|
|
148
|
+
/** Largest visual point radius in the current scene. The hit tester uses
|
|
149
|
+
* this to widen its quadtree query so points with big radii (bubble) don't
|
|
150
|
+
* fall outside the search region. */
|
|
151
|
+
private _maxPointRadius;
|
|
143
152
|
private static readonly QUADTREE_THRESHOLD;
|
|
144
153
|
constructor(config: PipelineConfig);
|
|
145
154
|
/**
|
|
@@ -161,6 +170,8 @@ export declare class PipelineStore {
|
|
|
161
170
|
* Returns null when chart type is not scatter/bubble or point count is below threshold.
|
|
162
171
|
*/
|
|
163
172
|
get quadtree(): Quadtree<PointSceneNode> | null;
|
|
173
|
+
/** Largest visual point radius in the current scene. */
|
|
174
|
+
get maxPointRadius(): number;
|
|
164
175
|
/**
|
|
165
176
|
* Remap existing scene node coordinates for a new layout size.
|
|
166
177
|
* Proportionally scales all pixel coordinates without rebuilding from data.
|
|
@@ -174,13 +185,17 @@ export declare class PipelineStore {
|
|
|
174
185
|
get hasActivePulses(): boolean;
|
|
175
186
|
private get transitionContext();
|
|
176
187
|
private snapshotPositions;
|
|
188
|
+
/** Synthesize a zero-state prevPositionMap/prevPathMap for animated intro (first render). */
|
|
189
|
+
private synthesizeIntroPositions;
|
|
177
190
|
private startTransition;
|
|
178
191
|
advanceTransition(now: number): boolean;
|
|
179
192
|
private groupData;
|
|
180
193
|
/**
|
|
181
194
|
* Resolve a category→color map from data using the colorAccessor.
|
|
182
|
-
* Caches the result in _colorMapCache keyed by
|
|
183
|
-
*
|
|
195
|
+
* Caches the result in _colorMapCache keyed by `_ingestVersion` (fast path)
|
|
196
|
+
* and a sorted-category fingerprint (so palette/scheme changes still
|
|
197
|
+
* invalidate). Multiple scene builders within one frame skip the data scan
|
|
198
|
+
* entirely after the first call.
|
|
184
199
|
*/
|
|
185
200
|
private resolveColorMap;
|
|
186
201
|
private resolveLineStyle;
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { StreamXYFrameProps, StreamXYFrameHandle } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Append a 2-char hex alpha to an existing CSS color, returning a valid
|
|
5
|
+
* CSS color string. The naive `${color}${alpha}` concatenation only works
|
|
6
|
+
* when `color` is a 6-char `#rrggbb`; shorthand `#rgb` produces the
|
|
7
|
+
* invalid 5-char `#rgbXX`, which `ctx.strokeStyle`/`fillStyle` silently
|
|
8
|
+
* rejects (falling back to `#000000` — black, invisible on dark themes).
|
|
9
|
+
* The /cookbook/marginal-graphics crosshair invisibility was caused
|
|
10
|
+
* precisely by `--semiotic-text-secondary: "#aaa"` hitting this path.
|
|
11
|
+
*
|
|
12
|
+
* Handles:
|
|
13
|
+
* • 3-char hex (`#abc`) → expanded to 6-char then concatenated
|
|
14
|
+
* • 6-char hex (`#aabbcc`) → concatenated directly
|
|
15
|
+
* • `rgb(...)` → repacked as `rgba(..., a)` with numeric alpha
|
|
16
|
+
* Any other form (named colors, hsl(), oklch(), etc.) falls back to the
|
|
17
|
+
* raw color without alpha — degrades gracefully.
|
|
18
|
+
*/
|
|
19
|
+
export declare function withAlpha(color: string, alphaHex: string): string;
|
|
3
20
|
declare const StreamXYFrame: React.ForwardRefExoticComponent<StreamXYFrameProps<Record<string, any>> & React.RefAttributes<StreamXYFrameHandle<Record<string, any>>>>;
|
|
4
21
|
export default StreamXYFrame;
|
|
@@ -1,7 +1,8 @@
|
|
|
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 {
|
|
4
|
+
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
5
|
+
import type { HoverAnnotationConfig, HoverData } from "../realtime/types";
|
|
5
6
|
import type { GeoParticleStyle } from "./GeoParticlePool";
|
|
6
7
|
export type ProjectionProp = GeoProjection | ProjectionName | ProjectionConfig;
|
|
7
8
|
export type ProjectionName = "mercator" | "equalEarth" | "albersUsa" | "orthographic" | "naturalEarth" | "equirectangular";
|
|
@@ -75,6 +76,8 @@ export interface GeoPipelineConfig {
|
|
|
75
76
|
decay?: DecayConfig;
|
|
76
77
|
pulse?: PulseConfig;
|
|
77
78
|
transition?: TransitionConfig;
|
|
79
|
+
/** Whether to animate elements on first render */
|
|
80
|
+
introAnimation?: boolean;
|
|
78
81
|
annotations?: Record<string, any>[];
|
|
79
82
|
pointIdAccessor?: string | ((d: any) => string);
|
|
80
83
|
}
|
|
@@ -139,13 +142,17 @@ export interface StreamGeoFrameProps<T = Record<string, any>> {
|
|
|
139
142
|
colorScheme?: string | string[];
|
|
140
143
|
enableHover?: boolean;
|
|
141
144
|
hoverAnnotation?: boolean | HoverAnnotationConfig;
|
|
142
|
-
tooltipContent?: (d:
|
|
143
|
-
customClickBehavior?: (d:
|
|
144
|
-
customHoverBehavior?: (d:
|
|
145
|
+
tooltipContent?: (d: HoverData) => ReactNode;
|
|
146
|
+
customClickBehavior?: (d: HoverData | null) => void;
|
|
147
|
+
customHoverBehavior?: (d: HoverData | null) => void;
|
|
145
148
|
annotations?: Record<string, any>[];
|
|
146
149
|
decay?: DecayConfig;
|
|
147
150
|
pulse?: PulseConfig;
|
|
148
151
|
transition?: TransitionConfig;
|
|
152
|
+
/** Declarative animation: `true` for defaults (300ms ease-out), or config object.
|
|
153
|
+
* When enabled, charts animate on first render (intro) and on data change.
|
|
154
|
+
* Set `{ intro: false }` to disable the intro animation. */
|
|
155
|
+
animate?: AnimateProp;
|
|
149
156
|
staleness?: StalenessConfig;
|
|
150
157
|
backgroundGraphics?: ReactNode;
|
|
151
158
|
foregroundGraphics?: ReactNode;
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
* Minimal shape a Stream Frame's internal hover handler needs from a pointer
|
|
12
|
+
* event. React.MouseEvent satisfies this structurally, as does the plain
|
|
13
|
+
* `{clientX, clientY}` object the rAF-coalescing path synthesizes. Using this
|
|
14
|
+
* narrower type on `hoverHandlerRef` (instead of `React.MouseEvent`) prevents
|
|
15
|
+
* downstream code from reading event fields — `currentTarget`, `target`,
|
|
16
|
+
* `preventDefault` — that wouldn't survive the coalescing cast.
|
|
17
|
+
*/
|
|
18
|
+
export interface HoverPointerCoords {
|
|
19
|
+
clientX: number;
|
|
20
|
+
clientY: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Spread raw datum properties onto HoverData if it's a non-null,
|
|
24
|
+
* non-array object. Class instances (Date, etc.) are included —
|
|
25
|
+
* this matches the historical behavior where all datum fields are
|
|
26
|
+
* accessible directly on the hover object (d.fieldName).
|
|
27
|
+
*/
|
|
28
|
+
export declare function spreadDatum(rawDatum: any): Record<string, any>;
|
|
29
|
+
/**
|
|
30
|
+
* Build a HoverData object from a raw datum and pixel coordinates.
|
|
31
|
+
* Spreads plain-object datum properties for backwards compatibility
|
|
32
|
+
* (consumers can access d.fieldName directly in addition to d.data.fieldName).
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildHoverData(rawDatum: any, x: number, y: number, extra?: Partial<HoverData>): HoverData;
|