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
|
@@ -2,7 +2,8 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
import type { OnObservationCallback } from "../store/ObservationStore";
|
|
3
3
|
import type { HoverData, AnnotationContext } from "../realtime/types";
|
|
4
4
|
import type { LegendGroup } from "../types/legendTypes";
|
|
5
|
-
import type { Style, DecayConfig, PulseConfig, StalenessConfig } from "./types";
|
|
5
|
+
import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig } from "./types";
|
|
6
|
+
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
6
7
|
export interface TensionConfig {
|
|
7
8
|
weightChange: number;
|
|
8
9
|
newEdge: number;
|
|
@@ -52,6 +53,8 @@ export interface RealtimeEdge {
|
|
|
52
53
|
_targetY0?: number;
|
|
53
54
|
_targetY1?: number;
|
|
54
55
|
_targetSankeyWidth?: number;
|
|
56
|
+
/** Set during intro animation to allow edge interpolation from width 0 */
|
|
57
|
+
_introFromZero?: boolean;
|
|
55
58
|
direction?: string;
|
|
56
59
|
circular?: boolean;
|
|
57
60
|
circularPathData?: any;
|
|
@@ -168,13 +171,16 @@ export interface NetworkRectNode {
|
|
|
168
171
|
_pulseGlowRadius?: number;
|
|
169
172
|
}
|
|
170
173
|
/** Arc node — used by chord */
|
|
174
|
+
/** Arc node — used by chord. Angles in canvas convention (0 = 3 o'clock). */
|
|
171
175
|
export interface NetworkArcNode {
|
|
172
176
|
type: "arc";
|
|
173
177
|
cx: number;
|
|
174
178
|
cy: number;
|
|
175
179
|
innerR: number;
|
|
176
180
|
outerR: number;
|
|
181
|
+
/** Start angle in radians, canvas convention (0 = 3 o'clock, positive = clockwise) */
|
|
177
182
|
startAngle: number;
|
|
183
|
+
/** End angle in radians, canvas convention */
|
|
178
184
|
endAngle: number;
|
|
179
185
|
style: Style;
|
|
180
186
|
datum: any;
|
|
@@ -205,6 +211,9 @@ export interface NetworkBezierEdge {
|
|
|
205
211
|
datum: any;
|
|
206
212
|
_pulseIntensity?: number;
|
|
207
213
|
_pulseColor?: string;
|
|
214
|
+
/** Lazily-built Path2D for hit testing; invalidated when pathD changes. */
|
|
215
|
+
_cachedPath2D?: Path2D;
|
|
216
|
+
_cachedPath2DSource?: string;
|
|
208
217
|
}
|
|
209
218
|
/** Ribbon edge — used by chord */
|
|
210
219
|
export interface NetworkRibbonEdge {
|
|
@@ -214,6 +223,8 @@ export interface NetworkRibbonEdge {
|
|
|
214
223
|
datum: any;
|
|
215
224
|
_pulseIntensity?: number;
|
|
216
225
|
_pulseColor?: string;
|
|
226
|
+
_cachedPath2D?: Path2D;
|
|
227
|
+
_cachedPath2DSource?: string;
|
|
217
228
|
}
|
|
218
229
|
/** Curved edge — used by tree, cluster */
|
|
219
230
|
export interface NetworkCurvedEdge {
|
|
@@ -223,6 +234,8 @@ export interface NetworkCurvedEdge {
|
|
|
223
234
|
datum: any;
|
|
224
235
|
_pulseIntensity?: number;
|
|
225
236
|
_pulseColor?: string;
|
|
237
|
+
_cachedPath2D?: Path2D;
|
|
238
|
+
_cachedPath2DSource?: string;
|
|
226
239
|
}
|
|
227
240
|
export type NetworkSceneNode = NetworkCircleNode | NetworkRectNode | NetworkArcNode;
|
|
228
241
|
export type NetworkSceneEdge = NetworkLineEdge | NetworkBezierEdge | NetworkRibbonEdge | NetworkCurvedEdge;
|
|
@@ -290,8 +303,10 @@ export interface NetworkPipelineConfig {
|
|
|
290
303
|
sourceAccessor?: string | ((d: any) => string);
|
|
291
304
|
targetAccessor?: string | ((d: any) => string);
|
|
292
305
|
valueAccessor?: string | ((d: any) => number);
|
|
306
|
+
/** Edge ID accessor for removeEdge(edgeId) — enables single-ID edge removal */
|
|
307
|
+
edgeIdAccessor?: string | ((d: any) => string);
|
|
293
308
|
childrenAccessor?: string | ((d: any) => any[]);
|
|
294
|
-
hierarchySum?: (d: any) => number;
|
|
309
|
+
hierarchySum?: string | ((d: any) => number);
|
|
295
310
|
orientation?: "horizontal" | "vertical";
|
|
296
311
|
nodeAlign?: "justify" | "left" | "right" | "center";
|
|
297
312
|
nodePaddingRatio?: number;
|
|
@@ -323,6 +338,9 @@ export interface NetworkPipelineConfig {
|
|
|
323
338
|
nodeSizeRange?: [number, number];
|
|
324
339
|
decay?: DecayConfig;
|
|
325
340
|
pulse?: PulseConfig;
|
|
341
|
+
transition?: TransitionConfig;
|
|
342
|
+
/** Whether to animate elements on first render (nodes scale up, edges fade in) */
|
|
343
|
+
introAnimation?: boolean;
|
|
326
344
|
staleness?: StalenessConfig;
|
|
327
345
|
thresholds?: ThresholdAlertConfig;
|
|
328
346
|
/** Ring arrangement mode: "flat" (all children in one ring), "solar" (one per ring),
|
|
@@ -370,8 +388,10 @@ export interface StreamNetworkFrameProps<T = Record<string, any>> {
|
|
|
370
388
|
sourceAccessor?: string | ((d: T) => string);
|
|
371
389
|
targetAccessor?: string | ((d: T) => string);
|
|
372
390
|
valueAccessor?: string | ((d: T) => number);
|
|
391
|
+
/** Edge ID accessor for removeEdge(edgeId) single-ID removal */
|
|
392
|
+
edgeIdAccessor?: string | ((d: any) => string);
|
|
373
393
|
childrenAccessor?: string | ((d: T) => T[]);
|
|
374
|
-
hierarchySum?: (d: T) => number;
|
|
394
|
+
hierarchySum?: string | ((d: T) => number);
|
|
375
395
|
orientation?: "horizontal" | "vertical";
|
|
376
396
|
nodeAlign?: "justify" | "left" | "right" | "center";
|
|
377
397
|
nodePaddingRatio?: number;
|
|
@@ -413,24 +433,9 @@ export interface StreamNetworkFrameProps<T = Record<string, any>> {
|
|
|
413
433
|
className?: string;
|
|
414
434
|
background?: string;
|
|
415
435
|
enableHover?: boolean;
|
|
416
|
-
tooltipContent?: (d:
|
|
417
|
-
|
|
418
|
-
|
|
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;
|
|
436
|
+
tooltipContent?: (d: HoverData) => ReactNode;
|
|
437
|
+
customHoverBehavior?: (d: HoverData | null) => void;
|
|
438
|
+
customClickBehavior?: (d: HoverData | null) => void;
|
|
434
439
|
/** Observation callback — emits hover/click events to the ObservationStore and this callback */
|
|
435
440
|
onObservation?: OnObservationCallback;
|
|
436
441
|
/** Chart instance identifier for observation filtering */
|
|
@@ -455,6 +460,11 @@ export interface StreamNetworkFrameProps<T = Record<string, any>> {
|
|
|
455
460
|
backgroundGraphics?: ReactNode;
|
|
456
461
|
decay?: DecayConfig;
|
|
457
462
|
pulse?: PulseConfig;
|
|
463
|
+
transition?: TransitionConfig;
|
|
464
|
+
/** Declarative animation: `true` for defaults (300ms ease-out), or config object.
|
|
465
|
+
* When enabled, charts animate on first render (intro) and on data change.
|
|
466
|
+
* Set `{ intro: false }` to disable the intro animation. */
|
|
467
|
+
animate?: AnimateProp;
|
|
458
468
|
staleness?: StalenessConfig;
|
|
459
469
|
thresholds?: ThresholdAlertConfig;
|
|
460
470
|
orbitMode?: "flat" | "solar" | "atomic" | number[];
|
|
@@ -477,8 +487,8 @@ export interface StreamNetworkFrameHandle {
|
|
|
477
487
|
pushMany(edges: EdgePush[]): void;
|
|
478
488
|
/** Remove a node by ID. Also removes connected edges. */
|
|
479
489
|
removeNode(id: string): boolean;
|
|
480
|
-
/** Remove
|
|
481
|
-
removeEdge(
|
|
490
|
+
/** Remove edges by source+target, or by edge ID when edgeIdAccessor is configured. */
|
|
491
|
+
removeEdge(sourceIdOrEdgeId: string, targetId?: string): boolean;
|
|
482
492
|
/** Update a node's data by ID. Returns previous data. */
|
|
483
493
|
updateNode(id: string, updater: (data: Record<string, any>) => Record<string, any>): Record<string, any> | null;
|
|
484
494
|
/** Update all edges between source+target. Returns array of previous data. */
|
|
@@ -2,6 +2,7 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
import type { ScaleLinear, ScaleBand } from "d3-scale";
|
|
3
3
|
import type { ArrowOfTime, WindowMode, HoverAnnotationConfig, HoverData, AnnotationContext } from "../realtime/types";
|
|
4
4
|
import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig } from "./types";
|
|
5
|
+
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
5
6
|
import type { LegendGroup } from "../types/legendTypes";
|
|
6
7
|
export type OrdinalChartType = "bar" | "clusterbar" | "point" | "swarm" | "pie" | "donut" | "boxplot" | "violin" | "histogram" | "ridgeline" | "timeline" | "funnel" | "bar-funnel" | "swimlane";
|
|
7
8
|
export interface OrdinalScales {
|
|
@@ -15,8 +16,12 @@ export interface WedgeSceneNode {
|
|
|
15
16
|
cy: number;
|
|
16
17
|
innerRadius: number;
|
|
17
18
|
outerRadius: number;
|
|
19
|
+
/** Start angle in radians, canvas convention (0 = 3 o'clock, positive = clockwise) */
|
|
18
20
|
startAngle: number;
|
|
21
|
+
/** End angle in radians, canvas convention */
|
|
19
22
|
endAngle: number;
|
|
23
|
+
/** Corner radius for rounded wedge arcs (d3-shape arc.cornerRadius) */
|
|
24
|
+
cornerRadius?: number;
|
|
20
25
|
style: Style;
|
|
21
26
|
datum: any;
|
|
22
27
|
category?: string;
|
|
@@ -24,6 +29,8 @@ export interface WedgeSceneNode {
|
|
|
24
29
|
_pulseColor?: string;
|
|
25
30
|
_pulseGlowRadius?: number;
|
|
26
31
|
_targetOpacity?: number;
|
|
32
|
+
_targetStartAngle?: number;
|
|
33
|
+
_targetEndAngle?: number;
|
|
27
34
|
_transitionKey?: string;
|
|
28
35
|
}
|
|
29
36
|
export interface BoxplotSceneNode {
|
|
@@ -149,21 +156,27 @@ export interface OrdinalPipelineConfig {
|
|
|
149
156
|
windowMode: WindowMode;
|
|
150
157
|
extentPadding: number;
|
|
151
158
|
projection: "vertical" | "horizontal" | "radial";
|
|
152
|
-
|
|
153
|
-
|
|
159
|
+
categoryAccessor?: string | ((d: any) => string);
|
|
160
|
+
valueAccessor?: string | ((d: any) => number) | Array<string | ((d: any) => number)>;
|
|
154
161
|
colorAccessor?: string | ((d: any) => string);
|
|
155
162
|
stackBy?: string | ((d: any) => string);
|
|
156
163
|
groupBy?: string | ((d: any) => string);
|
|
157
|
-
multiAxis?: boolean;
|
|
158
164
|
timeAccessor?: string | ((d: any) => number);
|
|
159
|
-
|
|
160
|
-
|
|
165
|
+
/** @deprecated Use categoryAccessor */
|
|
166
|
+
oAccessor?: string | ((d: any) => string);
|
|
167
|
+
/** @deprecated Use valueAccessor */
|
|
168
|
+
rAccessor?: string | ((d: any) => number) | Array<string | ((d: any) => number)>;
|
|
169
|
+
multiAxis?: boolean;
|
|
161
170
|
rExtent?: [number?, number?];
|
|
162
171
|
oExtent?: string[];
|
|
163
172
|
barPadding?: number;
|
|
173
|
+
/** 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. */
|
|
174
|
+
roundedTop?: number;
|
|
164
175
|
/** When true, adds padding below the 0 baseline. When false (default), bars are flush with the axis line. */
|
|
165
176
|
baselinePadding?: boolean;
|
|
166
177
|
innerRadius?: number;
|
|
178
|
+
/** Corner radius for rounded wedge arcs (pie/donut) */
|
|
179
|
+
cornerRadius?: number;
|
|
167
180
|
normalize?: boolean;
|
|
168
181
|
startAngle?: number;
|
|
169
182
|
/** Total arc sweep in degrees (default 360 = full circle). Used by GaugeChart for partial arcs. */
|
|
@@ -174,34 +187,41 @@ export interface OrdinalPipelineConfig {
|
|
|
174
187
|
amplitude?: number;
|
|
175
188
|
connectorOpacity?: number;
|
|
176
189
|
showLabels?: boolean;
|
|
177
|
-
oSort?: ((a:
|
|
190
|
+
oSort?: ((a: string, b: string) => number) | boolean | "asc" | "desc" | "auto";
|
|
178
191
|
connectorAccessor?: string | ((d: any) => string);
|
|
179
192
|
connectorStyle?: Style | ((d: any) => Style);
|
|
180
193
|
dynamicColumnWidth?: string | ((data: any[]) => number);
|
|
181
194
|
pieceStyle?: (d: any, category?: string) => Style;
|
|
182
195
|
summaryStyle?: (d: any, category?: string) => Style;
|
|
183
196
|
colorScheme?: string | string[];
|
|
197
|
+
themeCategorical?: string[];
|
|
184
198
|
barColors?: Record<string, string>;
|
|
185
199
|
/** ID accessor for remove() — extracts a unique identifier from each datum */
|
|
186
200
|
dataIdAccessor?: string | ((d: any) => string);
|
|
187
201
|
decay?: DecayConfig;
|
|
188
202
|
pulse?: PulseConfig;
|
|
189
203
|
transition?: TransitionConfig;
|
|
204
|
+
/** Whether to animate elements on first render (bars grow from baseline, wedges sweep in) */
|
|
205
|
+
introAnimation?: boolean;
|
|
190
206
|
staleness?: StalenessConfig;
|
|
191
207
|
}
|
|
192
208
|
export interface StreamOrdinalFrameProps<T = Record<string, any>> {
|
|
193
209
|
chartType: OrdinalChartType;
|
|
194
210
|
runtimeMode?: "bounded" | "streaming";
|
|
195
211
|
data?: T[];
|
|
196
|
-
|
|
197
|
-
|
|
212
|
+
/** Category field — the ordinal dimension (replaces oAccessor) */
|
|
213
|
+
categoryAccessor?: string | ((d: T) => string);
|
|
214
|
+
/** Value field — the quantitative dimension (replaces rAccessor). Can be array for multiAxis. */
|
|
215
|
+
valueAccessor?: string | ((d: T) => number) | Array<string | ((d: T) => number)>;
|
|
198
216
|
colorAccessor?: string | ((d: T) => string);
|
|
199
217
|
stackBy?: string | ((d: T) => string);
|
|
200
218
|
groupBy?: string | ((d: T) => string);
|
|
201
|
-
multiAxis?: boolean;
|
|
202
219
|
timeAccessor?: string | ((d: T) => number);
|
|
203
|
-
|
|
204
|
-
|
|
220
|
+
/** @deprecated Use categoryAccessor instead */
|
|
221
|
+
oAccessor?: string | ((d: T) => string);
|
|
222
|
+
/** @deprecated Use valueAccessor instead */
|
|
223
|
+
rAccessor?: string | ((d: T) => number) | Array<string | ((d: T) => number)>;
|
|
224
|
+
multiAxis?: boolean;
|
|
205
225
|
projection?: "vertical" | "horizontal" | "radial";
|
|
206
226
|
size?: [number, number];
|
|
207
227
|
responsiveWidth?: boolean;
|
|
@@ -213,8 +233,10 @@ export interface StreamOrdinalFrameProps<T = Record<string, any>> {
|
|
|
213
233
|
left?: number;
|
|
214
234
|
};
|
|
215
235
|
barPadding?: number;
|
|
236
|
+
roundedTop?: number;
|
|
216
237
|
baselinePadding?: boolean;
|
|
217
238
|
innerRadius?: number;
|
|
239
|
+
cornerRadius?: number;
|
|
218
240
|
normalize?: boolean;
|
|
219
241
|
startAngle?: number;
|
|
220
242
|
sweepAngle?: number;
|
|
@@ -228,7 +250,7 @@ export interface StreamOrdinalFrameProps<T = Record<string, any>> {
|
|
|
228
250
|
rExtent?: [number?, number?];
|
|
229
251
|
oExtent?: string[];
|
|
230
252
|
extentPadding?: number;
|
|
231
|
-
oSort?: ((a:
|
|
253
|
+
oSort?: ((a: string, b: string) => number) | boolean | "asc" | "desc" | "auto";
|
|
232
254
|
arrowOfTime?: ArrowOfTime;
|
|
233
255
|
windowMode?: WindowMode;
|
|
234
256
|
windowSize?: number;
|
|
@@ -246,9 +268,21 @@ export interface StreamOrdinalFrameProps<T = Record<string, any>> {
|
|
|
246
268
|
barColors?: Record<string, string>;
|
|
247
269
|
showAxes?: boolean;
|
|
248
270
|
showCategoryTicks?: boolean;
|
|
271
|
+
/** Category axis label */
|
|
272
|
+
categoryLabel?: string;
|
|
273
|
+
/** Value axis label */
|
|
274
|
+
valueLabel?: string;
|
|
275
|
+
/** Category tick formatter */
|
|
276
|
+
categoryFormat?: (d: string, index?: number) => string | ReactNode;
|
|
277
|
+
/** Value tick formatter */
|
|
278
|
+
valueFormat?: (d: number | string) => string;
|
|
279
|
+
/** @deprecated Use categoryLabel */
|
|
249
280
|
oLabel?: string;
|
|
281
|
+
/** @deprecated Use valueLabel */
|
|
250
282
|
rLabel?: string;
|
|
283
|
+
/** @deprecated Use categoryFormat */
|
|
251
284
|
oFormat?: (d: string, index?: number) => string | ReactNode;
|
|
285
|
+
/** @deprecated Use valueFormat */
|
|
252
286
|
rFormat?: (d: number | string) => string;
|
|
253
287
|
enableHover?: boolean;
|
|
254
288
|
hoverAnnotation?: boolean | HoverAnnotationConfig;
|
|
@@ -288,6 +322,10 @@ export interface StreamOrdinalFrameProps<T = Record<string, any>> {
|
|
|
288
322
|
decay?: DecayConfig;
|
|
289
323
|
pulse?: PulseConfig;
|
|
290
324
|
transition?: TransitionConfig;
|
|
325
|
+
/** Declarative animation: `true` for defaults (300ms ease-out), or config object.
|
|
326
|
+
* When enabled, charts animate on first render (intro) and on data change.
|
|
327
|
+
* Set `{ intro: false }` to disable the intro animation. */
|
|
328
|
+
animate?: AnimateProp;
|
|
291
329
|
staleness?: StalenessConfig;
|
|
292
330
|
/** Render a visually-hidden data table from the scene graph for screen readers */
|
|
293
331
|
accessibleTable?: boolean;
|
|
@@ -299,6 +337,19 @@ export interface StreamOrdinalFrameProps<T = Record<string, any>> {
|
|
|
299
337
|
export interface StreamOrdinalFrameHandle<T = Record<string, any>> {
|
|
300
338
|
push(datum: T): void;
|
|
301
339
|
pushMany(data: T[]): void;
|
|
340
|
+
/** Replace all data. Unlike `clear() + pushMany()`, `replace()` preserves
|
|
341
|
+
* the previous scene's position snapshot so data-change transitions fire.
|
|
342
|
+
* Use when you need to swap in a full new dataset (e.g. re-aggregated
|
|
343
|
+
* values from streaming input) and want the bars/points/etc. to animate
|
|
344
|
+
* between the old and new positions.
|
|
345
|
+
*
|
|
346
|
+
* Note: for datasets within the DataSourceAdapter chunk threshold (the
|
|
347
|
+
* common case for aggregator HOCs like LikertChart) the replacement
|
|
348
|
+
* lands in a single changeset. Larger datasets fall through to the
|
|
349
|
+
* progressive-chunked path used by the `data` prop — the first chunk
|
|
350
|
+
* resets + seeds the buffer, subsequent chunks append on successive
|
|
351
|
+
* animation frames, so replacement is not instantaneous for large N. */
|
|
352
|
+
replace(data: T[]): void;
|
|
302
353
|
/** Remove data items by ID. Requires dataIdAccessor. */
|
|
303
354
|
remove(id: string | string[]): T[];
|
|
304
355
|
/** Update data items by ID in place. Requires dataIdAccessor. Returns previous values. */
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared decay encoding utilities for all pipeline stores.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* `computeDecayOpacity()` — core algorithm used by all four pipeline stores
|
|
5
|
+
* (XY, Ordinal, Network, Geo) to compute age-based opacity.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
/**
|
|
@@ -40,3 +40,24 @@ export declare function lerp(from: number, to: number, t: number): number;
|
|
|
40
40
|
* Get the current timestamp in a way that works both in browser and Node.
|
|
41
41
|
*/
|
|
42
42
|
export declare function now(): number;
|
|
43
|
+
/** The animate prop type accepted by all HOCs and Stream Frames.
|
|
44
|
+
* Single source of truth — re-exported by types.ts, ordinalTypes.ts, networkTypes.ts, geoTypes.ts. */
|
|
45
|
+
export type AnimateProp = boolean | {
|
|
46
|
+
duration?: number;
|
|
47
|
+
easing?: "linear" | "ease-out";
|
|
48
|
+
intro?: boolean;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the declarative `animate` prop into a concrete TransitionConfig.
|
|
52
|
+
* Used by all 4 Stream Frames. `animate` takes precedence over `transitionProp`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveAnimateConfig(animate: AnimateProp | undefined, transitionProp: {
|
|
55
|
+
duration?: number;
|
|
56
|
+
easing?: "ease-out" | "linear";
|
|
57
|
+
} | undefined): {
|
|
58
|
+
transition: {
|
|
59
|
+
duration?: number;
|
|
60
|
+
easing?: "ease-out" | "linear";
|
|
61
|
+
} | undefined;
|
|
62
|
+
introEnabled: boolean;
|
|
63
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Quadtree } from "d3-quadtree";
|
|
2
|
+
export interface QuadtreeHit<T> {
|
|
3
|
+
node: T;
|
|
4
|
+
distance: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Find the closest point whose own hit radius contains the cursor.
|
|
8
|
+
*
|
|
9
|
+
* Uses `quadtree.visit()` to enumerate every candidate within the widened
|
|
10
|
+
* search radius (maxDistance extended by the largest point radius in the
|
|
11
|
+
* scene). `quadtree.find()` alone is insufficient because it returns the
|
|
12
|
+
* nearest candidate by center-to-center distance — a farther point with a
|
|
13
|
+
* much larger visual radius can still be a valid hit that `find()` would
|
|
14
|
+
* hide.
|
|
15
|
+
*
|
|
16
|
+
* `T` must expose `x`, `y`, and `r` — the standard `PointSceneNode` shape.
|
|
17
|
+
*/
|
|
18
|
+
export declare function findHitPointInQuadtree<T extends {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
r: number;
|
|
22
|
+
}>(qt: Quadtree<T>, px: number, py: number, maxDistance: number, maxPointRadius: number): QuadtreeHit<T> | null;
|
|
@@ -5,13 +5,30 @@
|
|
|
5
5
|
* reads the computed value from the canvas element. Otherwise returns
|
|
6
6
|
* the input unchanged.
|
|
7
7
|
*
|
|
8
|
-
* Per-canvas cache avoids repeated getComputedStyle calls
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Per-canvas cache avoids repeated `getComputedStyle` calls. Cached entries
|
|
9
|
+
* are tagged with a global version counter that's bumped whenever a theme
|
|
10
|
+
* change is detected — either through `clearCSSColorCache()` (called by
|
|
11
|
+
* Stream Frames on `currentTheme` change) or via the global observer below
|
|
12
|
+
* (catches external class toggles on `<html>` and `prefers-color-scheme`
|
|
13
|
+
* media-query changes that bypass React).
|
|
11
14
|
*/
|
|
12
15
|
export declare function resolveCSSColor(ctx: CanvasRenderingContext2D, value: string | undefined): string | undefined;
|
|
13
16
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
17
|
+
* Invalidate the CSS variable cache. Stream Frames call this from their
|
|
18
|
+
* `currentTheme` `useEffect` so the next paint reads fresh computed values.
|
|
19
|
+
*
|
|
20
|
+
* The `canvas` argument is accepted for backward compatibility but ignored —
|
|
21
|
+
* invalidation is global because theme changes are global.
|
|
22
|
+
*/
|
|
23
|
+
export declare function clearCSSColorCache(_canvas?: HTMLCanvasElement): void;
|
|
24
|
+
/**
|
|
25
|
+
* Test-only: reset all cache state, including disconnecting any installed
|
|
26
|
+
* observer/matchMedia listeners. Required for test isolation — without it,
|
|
27
|
+
* observers accumulate across files and bump `currentVersion` more than once
|
|
28
|
+
* per real DOM mutation.
|
|
29
|
+
*
|
|
30
|
+
* `currentVersion` is *incremented* (not reset to zero) so any WeakMap entries
|
|
31
|
+
* that survive from a previous test can't accidentally be re-validated by a
|
|
32
|
+
* version collision.
|
|
16
33
|
*/
|
|
17
|
-
export declare function
|
|
34
|
+
export declare function _resetCSSColorCacheForTest(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { ScaleLinear } from "d3-scale";
|
|
3
|
+
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
3
4
|
import type { ArrowOfTime, WindowMode, LineStyle, BarStyle, WaterfallStyle, SwarmStyle, HoverAnnotationConfig, HoverData, AnnotationContext, AnnotationAnchorMode } from "../realtime/types";
|
|
4
5
|
export interface DecayConfig {
|
|
5
6
|
type: "linear" | "exponential" | "step";
|
|
@@ -107,6 +108,8 @@ export interface LineSceneNode {
|
|
|
107
108
|
_prevPath?: [number, number][];
|
|
108
109
|
/** Target path coordinates for interpolation during transitions */
|
|
109
110
|
_targetPath?: [number, number][];
|
|
111
|
+
/** Intro clip fraction (0→1): reveals line from left to right via canvas clip */
|
|
112
|
+
_introClipFraction?: number;
|
|
110
113
|
}
|
|
111
114
|
export interface AreaSceneNode {
|
|
112
115
|
type: "area";
|
|
@@ -156,6 +159,8 @@ export interface AreaSceneNode {
|
|
|
156
159
|
_prevBottomPath?: [number, number][];
|
|
157
160
|
/** Target bottom path coordinates for interpolation during transitions */
|
|
158
161
|
_targetBottomPath?: [number, number][];
|
|
162
|
+
/** Intro clip fraction (0→1): reveals area from left to right via canvas clip */
|
|
163
|
+
_introClipFraction?: number;
|
|
159
164
|
}
|
|
160
165
|
export interface PointSceneNode {
|
|
161
166
|
type: "point";
|
|
@@ -187,6 +192,10 @@ export interface RectSceneNode {
|
|
|
187
192
|
y: number;
|
|
188
193
|
w: number;
|
|
189
194
|
h: number;
|
|
195
|
+
/** Rounded corner radius on the end away from the baseline */
|
|
196
|
+
roundedTop?: number;
|
|
197
|
+
/** Which edge to round: "top"/"bottom" (vertical), "right"/"left" (horizontal) */
|
|
198
|
+
roundedEdge?: "top" | "bottom" | "right" | "left";
|
|
190
199
|
style: Style;
|
|
191
200
|
datum: any;
|
|
192
201
|
group?: string;
|
|
@@ -274,6 +283,15 @@ export interface Changeset<T = Record<string, any>> {
|
|
|
274
283
|
bounded: boolean;
|
|
275
284
|
/** Hint: total dataset size when progressively chunking bounded data */
|
|
276
285
|
totalSize?: number;
|
|
286
|
+
/** When true on a bounded changeset, the store replaces the buffer
|
|
287
|
+
* contents but does NOT clear its category insertion-order memory
|
|
288
|
+
* and marks itself as having received streaming-sourced data. Used
|
|
289
|
+
* by aggregator HOCs (LikertChart, future density/bin charts) that
|
|
290
|
+
* re-derive their full dataset from streaming input on every push —
|
|
291
|
+
* the user perceives it as a stream even though the transport is
|
|
292
|
+
* a wholesale replacement. Without this, re-aggregation would wipe
|
|
293
|
+
* the category order and categories would shuffle on every tick. */
|
|
294
|
+
preserveCategoryOrder?: boolean;
|
|
277
295
|
}
|
|
278
296
|
/**
|
|
279
297
|
* Note: when xScaleType="time", the x scale is a d3.scaleTime at runtime
|
|
@@ -463,6 +481,10 @@ export interface StreamXYFrameProps<T = Record<string, any>> {
|
|
|
463
481
|
pulse?: PulseConfig;
|
|
464
482
|
/** Smooth position transitions on data change */
|
|
465
483
|
transition?: TransitionConfig;
|
|
484
|
+
/** Declarative animation: `true` for defaults (300ms ease-out), or config object.
|
|
485
|
+
* When enabled, charts animate on first render (intro) and on data change.
|
|
486
|
+
* Set `{ intro: false }` to disable the intro animation. */
|
|
487
|
+
animate?: AnimateProp;
|
|
466
488
|
/** Frame-level data liveness indicator */
|
|
467
489
|
staleness?: StalenessConfig;
|
|
468
490
|
/** Marginal distribution plots in axis margins (histogram, violin, ridgeline, boxplot) */
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { SemioticTheme } from "../store/ThemeStore";
|
|
4
|
+
import { useResponsiveSize } from "./useResponsiveSize";
|
|
5
|
+
import { resolveAnimateConfig } from "./pipelineTransitionUtils";
|
|
6
|
+
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
7
|
+
import type { TransitionConfig } from "./types";
|
|
8
|
+
import type { HoverPointerCoords } from "./hoverUtils";
|
|
9
|
+
/**
|
|
10
|
+
* Frame-supplied margin defaults. Each Stream Frame has its own — XY's
|
|
11
|
+
* differs from Ordinal's, Network has both a default and a CENTERED variant
|
|
12
|
+
* for radial chart types. The hook accepts the resolved default and
|
|
13
|
+
* shallow-merges user margin on top.
|
|
14
|
+
*/
|
|
15
|
+
export interface FrameMargin {
|
|
16
|
+
top: number;
|
|
17
|
+
right: number;
|
|
18
|
+
bottom: number;
|
|
19
|
+
left: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Foreground/background graphics can be a ReactNode (rendered as-is) or a
|
|
23
|
+
* function that receives the current `{ size, margin }` and returns one.
|
|
24
|
+
* The function form lets users place chrome relative to the chart area.
|
|
25
|
+
*/
|
|
26
|
+
export type FrameGraphicsProp = ReactNode | ((ctx: {
|
|
27
|
+
size: number[];
|
|
28
|
+
margin: FrameMargin;
|
|
29
|
+
}) => ReactNode);
|
|
30
|
+
export interface UseFrameInput {
|
|
31
|
+
/** Resolved size `[width, height]`. Each frame defaults its `size` prop
|
|
32
|
+
* before calling, so this is never undefined. */
|
|
33
|
+
sizeProp: [number, number];
|
|
34
|
+
/** Frame's `responsiveWidth` prop. */
|
|
35
|
+
responsiveWidth: boolean | undefined;
|
|
36
|
+
/** Frame's `responsiveHeight` prop. */
|
|
37
|
+
responsiveHeight: boolean | undefined;
|
|
38
|
+
/** Frame's user-supplied margin (always partial — each side optional).
|
|
39
|
+
* Matches the `margin?:` prop type on every Stream Frame. */
|
|
40
|
+
userMargin: Partial<FrameMargin> | undefined;
|
|
41
|
+
/** Frame's family-default margin. Shallow-merged with `userMargin`. */
|
|
42
|
+
marginDefault: FrameMargin;
|
|
43
|
+
/** Frame's `foregroundGraphics` prop. */
|
|
44
|
+
foregroundGraphics?: FrameGraphicsProp;
|
|
45
|
+
/** Frame's `backgroundGraphics` prop. */
|
|
46
|
+
backgroundGraphics?: FrameGraphicsProp;
|
|
47
|
+
/** Frame's `animate` prop. */
|
|
48
|
+
animate?: AnimateProp;
|
|
49
|
+
/** Frame's `transition` prop (legacy / explicit form). */
|
|
50
|
+
transitionProp?: TransitionConfig;
|
|
51
|
+
/**
|
|
52
|
+
* Frame's `dirtyRef` (the flag that forces a full canvas redraw on the
|
|
53
|
+
* next paint). When provided, useFrame installs a theme-change effect
|
|
54
|
+
* that bumps it to `true`, clears the CSS-var cache, and queues a
|
|
55
|
+
* render — the pattern that all four frames duplicated.
|
|
56
|
+
*
|
|
57
|
+
* Optional because this is a Tier B add-on; before the migration the
|
|
58
|
+
* frames installed this themselves. The hook keeps the input optional
|
|
59
|
+
* so a frame can opt in independently, but in practice all four pass
|
|
60
|
+
* it.
|
|
61
|
+
*
|
|
62
|
+
* `dirtyRef` is owned by the frame (not the hook) because its initial
|
|
63
|
+
* value differs — only `StreamXYFrame` inits to `false`; Ordinal,
|
|
64
|
+
* Network, and Geo all init to `true` (load-bearing for first-paint
|
|
65
|
+
* timing on those three).
|
|
66
|
+
*/
|
|
67
|
+
themeDirtyRef?: React.MutableRefObject<boolean>;
|
|
68
|
+
}
|
|
69
|
+
export interface UseFrameResult {
|
|
70
|
+
/** Reduced-motion preference at last render (for re-render gating). */
|
|
71
|
+
reducedMotion: boolean;
|
|
72
|
+
/** Reduced-motion ref-mirror so render closures see the latest value
|
|
73
|
+
* without depending on it. */
|
|
74
|
+
reducedMotionRef: React.MutableRefObject<boolean>;
|
|
75
|
+
/** Ref to attach to the responsive container. */
|
|
76
|
+
responsiveRef: ReturnType<typeof useResponsiveSize>[0];
|
|
77
|
+
/** Resolved size `[width, height]` accounting for `responsiveWidth/Height`. */
|
|
78
|
+
size: [number, number];
|
|
79
|
+
/** Effective margin (`marginDefault` ⊕ `userMargin`). */
|
|
80
|
+
margin: FrameMargin;
|
|
81
|
+
/** `size[0] - margin.left - margin.right`. */
|
|
82
|
+
adjustedWidth: number;
|
|
83
|
+
/** `size[1] - margin.top - margin.bottom`. */
|
|
84
|
+
adjustedHeight: number;
|
|
85
|
+
/** Resolved foreground (function-or-node, evaluated). */
|
|
86
|
+
resolvedForeground: ReactNode;
|
|
87
|
+
/** Resolved background (function-or-node, evaluated). */
|
|
88
|
+
resolvedBackground: ReactNode;
|
|
89
|
+
/** Current theme from the ThemeStore — re-renders on theme change. */
|
|
90
|
+
currentTheme: SemioticTheme;
|
|
91
|
+
/** Resolved transition config from `animate`/`transition` props. */
|
|
92
|
+
transition: ReturnType<typeof resolveAnimateConfig>["transition"];
|
|
93
|
+
/** Whether the intro animation should run on first render. */
|
|
94
|
+
introEnabled: boolean;
|
|
95
|
+
/** Stable id for the AccessibleDataTable region (hash-suffixed). */
|
|
96
|
+
tableId: string;
|
|
97
|
+
/** Token of the pending rAF, or 0 if none. */
|
|
98
|
+
rafRef: React.MutableRefObject<number>;
|
|
99
|
+
/** Frame assigns its render closure here. */
|
|
100
|
+
renderFnRef: React.MutableRefObject<() => void>;
|
|
101
|
+
/** Queue a render on the next animation frame. Coalesces. */
|
|
102
|
+
scheduleRender: () => void;
|
|
103
|
+
/** Frame assigns its hover handler closure here. */
|
|
104
|
+
hoverHandlerRef: React.MutableRefObject<(coords: HoverPointerCoords) => void>;
|
|
105
|
+
/** Frame assigns its pointer-leave closure here. */
|
|
106
|
+
hoverLeaveRef: React.MutableRefObject<() => void>;
|
|
107
|
+
/** Stable callback to attach to canvas's onPointerMove (or onMouseMove).
|
|
108
|
+
* Captures the coords and queues a single rAF to drain into hoverHandlerRef. */
|
|
109
|
+
onPointerMove: (e: {
|
|
110
|
+
clientX: number;
|
|
111
|
+
clientY: number;
|
|
112
|
+
}) => void;
|
|
113
|
+
/** Stable callback to attach to canvas's onPointerLeave (or onMouseLeave).
|
|
114
|
+
* Cancels any pending hover rAF and invokes hoverLeaveRef. */
|
|
115
|
+
onPointerLeave: () => void;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Bundles the universally-shared setup boilerplate that opens every
|
|
119
|
+
* Stream Frame. See `FRAME_COMPOSITION_LOG.md` for which concerns are
|
|
120
|
+
* inside this hook vs. left frame-specific.
|
|
121
|
+
*/
|
|
122
|
+
export declare function useFrame(input: UseFrameInput): UseFrameResult;
|