semiotic 3.4.2 → 3.5.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 +114 -9
- package/README.md +45 -4
- package/ai/behaviorContracts.cjs +311 -0
- package/ai/chartSuggestions.cjs +291 -0
- package/ai/cli.js +255 -30
- package/ai/componentMetadata.cjs +107 -0
- package/ai/dist/mcp-server.js +907 -227
- package/ai/schema.json +3954 -2537
- package/ai/system-prompt.md +23 -4
- package/dist/components/LinkedCharts.d.ts +5 -1
- package/dist/components/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/charts/custom/NetworkCustomChart.d.ts +64 -0
- package/dist/components/charts/custom/OrdinalCustomChart.d.ts +71 -0
- package/dist/components/charts/custom/XYCustomChart.d.ts +59 -0
- package/dist/components/charts/geo/ChoroplethMap.d.ts +93 -2
- package/dist/components/charts/geo/DistanceCartogram.d.ts +51 -4
- package/dist/components/charts/geo/FlowMap.d.ts +55 -0
- package/dist/components/charts/geo/ProportionalSymbolMap.d.ts +53 -0
- package/dist/components/charts/index.d.ts +6 -0
- package/dist/components/charts/network/ChordDiagram.d.ts +34 -2
- package/dist/components/charts/network/CirclePack.d.ts +36 -1
- package/dist/components/charts/network/ForceDirectedGraph.d.ts +130 -2
- package/dist/components/charts/network/OrbitDiagram.d.ts +37 -0
- package/dist/components/charts/network/SankeyDiagram.d.ts +51 -2
- package/dist/components/charts/network/TreeDiagram.d.ts +37 -2
- package/dist/components/charts/network/Treemap.d.ts +36 -2
- package/dist/components/charts/ordinal/BarChart.d.ts +111 -1
- package/dist/components/charts/ordinal/BoxPlot.d.ts +31 -0
- package/dist/components/charts/ordinal/DonutChart.d.ts +36 -0
- package/dist/components/charts/ordinal/DotPlot.d.ts +31 -0
- package/dist/components/charts/ordinal/FunnelChart.d.ts +40 -0
- package/dist/components/charts/ordinal/GaugeChart.d.ts +45 -0
- package/dist/components/charts/ordinal/GroupedBarChart.d.ts +38 -0
- package/dist/components/charts/ordinal/Histogram.d.ts +95 -0
- package/dist/components/charts/ordinal/LikertChart.d.ts +42 -0
- package/dist/components/charts/ordinal/PieChart.d.ts +90 -1
- package/dist/components/charts/ordinal/RidgelinePlot.d.ts +27 -0
- package/dist/components/charts/ordinal/StackedBarChart.d.ts +38 -0
- package/dist/components/charts/ordinal/SwarmPlot.d.ts +36 -0
- package/dist/components/charts/ordinal/SwimlaneChart.d.ts +60 -0
- package/dist/components/charts/ordinal/ViolinPlot.d.ts +32 -0
- package/dist/components/charts/realtime/RealtimeHeatmap.d.ts +22 -4
- package/dist/components/charts/realtime/RealtimeHistogram.d.ts +5 -2
- package/dist/components/charts/realtime/RealtimeLineChart.d.ts +24 -3
- package/dist/components/charts/realtime/RealtimeSwarmChart.d.ts +12 -0
- package/dist/components/charts/realtime/RealtimeWaterfallChart.d.ts +14 -0
- package/dist/components/charts/realtime/defaultRealtimeTooltip.d.ts +43 -0
- package/dist/components/charts/realtime/resolveWindowSize.d.ts +26 -0
- package/dist/components/charts/shared/chartSpecs.d.ts +91 -0
- package/dist/components/charts/shared/colorPalettes.d.ts +62 -0
- package/dist/components/charts/shared/colorUtils.d.ts +9 -10
- package/dist/components/charts/shared/numberFormat.d.ts +58 -0
- package/dist/components/charts/shared/sparseArray.d.ts +27 -0
- package/dist/components/charts/shared/streamPropsHelpers.d.ts +113 -0
- package/dist/components/charts/shared/timeFormat.d.ts +60 -0
- package/dist/components/charts/shared/useChartSetup.d.ts +8 -0
- package/dist/components/charts/shared/useCustomChartSetup.d.ts +84 -0
- package/dist/components/charts/shared/useFrameImperativeHandle.d.ts +28 -0
- package/dist/components/charts/shared/useOrdinalStreaming.d.ts +6 -19
- package/dist/components/charts/shared/useStreamingLegend.d.ts +27 -11
- package/dist/components/charts/shared/validateProps.d.ts +2 -2
- package/dist/components/charts/shared/validationMap.d.ts +2 -1
- package/dist/components/charts/shared/withChartWrapper.d.ts +13 -4
- package/dist/components/charts/xy/AreaChart.d.ts +30 -1
- package/dist/components/charts/xy/CandlestickChart.d.ts +33 -6
- package/dist/components/charts/xy/ConnectedScatterplot.d.ts +24 -0
- package/dist/components/charts/xy/MinimapChart.d.ts +51 -0
- package/dist/components/charts/xy/MultiAxisLineChart.d.ts +27 -0
- package/dist/components/charts/xy/QuadrantChart.d.ts +21 -0
- package/dist/components/charts/xy/Scatterplot.d.ts +34 -2
- package/dist/components/charts/xy/ScatterplotMatrix.d.ts +16 -0
- package/dist/components/charts/xy/StackedAreaChart.d.ts +49 -1
- package/dist/components/realtime/types.d.ts +2 -4
- package/dist/components/recipes/bullet.d.ts +86 -0
- package/dist/components/recipes/calendar.d.ts +43 -0
- package/dist/components/recipes/dagre.d.ts +56 -0
- package/dist/components/recipes/flextree.d.ts +55 -0
- package/dist/components/recipes/marimekko.d.ts +55 -0
- package/dist/components/recipes/parallelCoordinates.d.ts +97 -0
- package/dist/components/recipes/recipeUtils.d.ts +27 -0
- package/dist/components/recipes/waffle.d.ts +46 -0
- package/dist/components/semiotic-ai.d.ts +4 -0
- package/dist/components/semiotic-network.d.ts +3 -0
- package/dist/components/semiotic-ordinal.d.ts +3 -0
- package/dist/components/semiotic-recipes.d.ts +24 -0
- package/dist/components/semiotic-xy.d.ts +3 -0
- package/dist/components/semiotic.d.ts +2 -2
- package/dist/components/server/renderToStaticSVG.d.ts +8 -2
- package/dist/components/server/serverChartConfigs.d.ts +47 -1
- package/dist/components/server/staticAnnotations.d.ts +6 -0
- package/dist/components/store/ObservationStore.d.ts +1 -3
- package/dist/components/store/SelectionStore.d.ts +1 -3
- package/dist/components/store/ThemeStore.d.ts +4 -4
- package/dist/components/store/TooltipStore.d.ts +1 -3
- package/dist/components/store/createStore.d.ts +4 -2
- package/dist/components/stream/CanvasHitTester.d.ts +10 -8
- package/dist/components/stream/DataSourceAdapter.d.ts +9 -0
- package/dist/components/stream/GeoPipelineStore.d.ts +9 -0
- package/dist/components/stream/GeoTileRenderer.d.ts +14 -0
- package/dist/components/stream/NetworkPipelineStore.d.ts +25 -0
- package/dist/components/stream/OrdinalPipelineStore.d.ts +12 -0
- package/dist/components/stream/PipelineStore.d.ts +51 -0
- package/dist/components/stream/SVGOverlay.d.ts +12 -0
- package/dist/components/stream/SceneGraph.d.ts +15 -1
- package/dist/components/stream/SceneToSVG.d.ts +1 -1
- package/dist/components/stream/categoryDomain.d.ts +4 -0
- package/dist/components/stream/composeOverlays.d.ts +15 -0
- package/dist/components/stream/customLayout.d.ts +76 -0
- package/dist/components/stream/customLayoutPalette.d.ts +29 -0
- package/dist/components/stream/geoTypes.d.ts +13 -0
- package/dist/components/stream/hoverUtils.d.ts +4 -10
- package/dist/components/stream/networkCustomLayout.d.ts +67 -0
- package/dist/components/stream/networkTypes.d.ts +45 -0
- package/dist/components/stream/ordinalCustomLayout.d.ts +84 -0
- package/dist/components/stream/ordinalTypes.d.ts +35 -1
- package/dist/components/stream/renderers/barFunnelCanvasRenderer.d.ts +9 -1
- package/dist/components/stream/renderers/canvasRenderHelpers.d.ts +92 -0
- package/dist/components/stream/sampleCurvePath.d.ts +9 -0
- package/dist/components/stream/types.d.ts +44 -1
- package/dist/components/stream/useHydration.d.ts +89 -0
- package/dist/components/stream/useStableShallow.d.ts +1 -0
- package/dist/components/stream/xySceneBuilders/types.d.ts +4 -0
- package/dist/geo.min.js +2 -1
- package/dist/geo.module.min.js +2 -1
- package/dist/network.min.js +2 -1
- package/dist/network.module.min.js +2 -1
- package/dist/ordinal.min.js +2 -1
- package/dist/ordinal.module.min.js +2 -1
- package/dist/realtime.min.js +2 -1
- package/dist/realtime.module.min.js +2 -1
- package/dist/semiotic-ai.d.ts +69 -65
- package/dist/semiotic-ai.min.js +2 -1
- package/dist/semiotic-ai.module.min.js +2 -1
- package/dist/semiotic-data.d.ts +4 -4
- package/dist/semiotic-geo.d.ts +15 -15
- package/dist/semiotic-network.d.ts +19 -16
- package/dist/semiotic-ordinal.d.ts +31 -28
- package/dist/semiotic-realtime.d.ts +17 -17
- package/dist/semiotic-recipes.d.ts +24 -0
- package/dist/semiotic-recipes.min.js +1 -0
- package/dist/semiotic-recipes.module.min.js +1 -0
- package/dist/semiotic-server.d.ts +6 -6
- package/dist/semiotic-statisticalOverlays-C3DsOgr_.js +1 -0
- package/dist/semiotic-themes.d.ts +3 -3
- package/dist/semiotic-themes.min.js +2 -1
- package/dist/semiotic-themes.module.min.js +2 -1
- package/dist/semiotic-utils.d.ts +23 -23
- package/dist/semiotic-utils.min.js +2 -1
- package/dist/semiotic-utils.module.min.js +2 -1
- package/dist/semiotic-xy.d.ts +27 -24
- package/dist/semiotic.d.ts +63 -63
- package/dist/semiotic.min.js +2 -1
- package/dist/semiotic.module.min.js +2 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/test-utils/canvasMock.d.ts +34 -5
- package/dist/xy.min.js +2 -1
- package/dist/xy.module.min.js +2 -1
- package/package.json +38 -17
- package/dist/semiotic-statisticalOverlays-Ckd_jM8z.js +0 -1
|
@@ -155,6 +155,15 @@ export interface StreamGeoFrameProps<T = Datum> {
|
|
|
155
155
|
};
|
|
156
156
|
lineStyle?: Style | ((d: Datum, group?: string) => Style);
|
|
157
157
|
colorScheme?: string | string[];
|
|
158
|
+
/**
|
|
159
|
+
* Categorical color field. For ChoroplethMap reads from area `properties`
|
|
160
|
+
* (or top-level fallback); for ProportionalSymbolMap reads from each point.
|
|
161
|
+
* Server-side legend auto-build groups by this field when `showLegend` is
|
|
162
|
+
* set and no explicit `legend` prop is provided. The function form accepts
|
|
163
|
+
* either the point datum `T` or a GeoJSON Feature so choropleth callers can
|
|
164
|
+
* write `(f) => f.properties.region` without a cast.
|
|
165
|
+
*/
|
|
166
|
+
colorBy?: string | ((d: T | GeoJSON.Feature) => string);
|
|
158
167
|
enableHover?: boolean;
|
|
159
168
|
hoverAnnotation?: boolean | HoverAnnotationConfig;
|
|
160
169
|
tooltipContent?: (d: HoverData) => ReactNode;
|
|
@@ -186,6 +195,10 @@ export interface StreamGeoFrameProps<T = Datum> {
|
|
|
186
195
|
}) => void;
|
|
187
196
|
legendHighlightedCategory?: string | null;
|
|
188
197
|
legendIsolatedCategories?: Set<string>;
|
|
198
|
+
/** Accessor used to report the current legend category domain in push mode. */
|
|
199
|
+
legendCategoryAccessor?: string | ((d: T) => string);
|
|
200
|
+
/** Fires when the current legend category domain changes after scene rebuilds. */
|
|
201
|
+
onCategoriesChange?: (categories: string[]) => void;
|
|
189
202
|
showAxes?: boolean;
|
|
190
203
|
/** Render a visually-hidden data table from the scene graph for screen readers */
|
|
191
204
|
accessibleTable?: boolean;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
1
|
/**
|
|
3
2
|
* Shared hover data utilities for stream frames.
|
|
4
3
|
*
|
|
@@ -20,16 +19,11 @@ export interface HoverPointerCoords {
|
|
|
20
19
|
clientX: number;
|
|
21
20
|
clientY: number;
|
|
22
21
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Spread raw datum properties onto HoverData if it's a non-null,
|
|
25
|
-
* non-array object. Class instances (Date, etc.) are included —
|
|
26
|
-
* this matches the historical behavior where all datum fields are
|
|
27
|
-
* accessible directly on the hover object (d.fieldName).
|
|
28
|
-
*/
|
|
29
|
-
export declare function spreadDatum(rawDatum: any): Datum;
|
|
30
22
|
/**
|
|
31
23
|
* Build a HoverData object from a raw datum and pixel coordinates.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
24
|
+
* The raw datum is preserved as `hover.data` for tooltip / callback
|
|
25
|
+
* consumers; pixel coordinates land on `x` / `y`. Anything else
|
|
26
|
+
* relevant to a specific frame family — `category`, `stats`,
|
|
27
|
+
* `nodeOrEdge`, `xValue`, etc. — is layered in via `extra`.
|
|
34
28
|
*/
|
|
35
29
|
export declare function buildHoverData(rawDatum: any, x: number, y: number, extra?: Partial<HoverData>): HoverData;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { NetworkSceneNode, NetworkSceneEdge, NetworkLabel, RealtimeNode, RealtimeEdge } from "./networkTypes";
|
|
3
|
+
import type { ThemeSemanticColors } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* customLayout escape hatch for `StreamNetworkFrame`.
|
|
6
|
+
*
|
|
7
|
+
* A network layout is a pure function: given raw nodes/edges plus the
|
|
8
|
+
* frame's dimensions/theme, return positioned scene primitives — circles,
|
|
9
|
+
* rects, lines, beziers — and optional labels/overlays. The frame still
|
|
10
|
+
* owns hit testing, decay, accessibility, and SSR.
|
|
11
|
+
*
|
|
12
|
+
* Mirrors the XY `CustomLayout` pattern. Reach for it when the catalog
|
|
13
|
+
* (force, sankey, chord, tree, treemap, circle-pack, orbit) doesn't fit
|
|
14
|
+
* — e.g. `d3-flextree`, `dagre`, custom radial layouts.
|
|
15
|
+
*/
|
|
16
|
+
export type NetworkCustomLayout<C extends object = Record<string, unknown>> = (ctx: NetworkLayoutContext<C>) => NetworkLayoutResult;
|
|
17
|
+
export interface NetworkLayoutContext<C extends object = Record<string, unknown>> {
|
|
18
|
+
/** Raw nodes from the data prop / push API. May or may not have positions. */
|
|
19
|
+
nodes: RealtimeNode[];
|
|
20
|
+
/** Raw edges. Source/target may be id strings or node references. */
|
|
21
|
+
edges: RealtimeEdge[];
|
|
22
|
+
/**
|
|
23
|
+
* Plot-area geometry. All scene-node coordinates are plot-relative —
|
|
24
|
+
* the canvas/SVG group already lives inside `margin.left`/`margin.top`.
|
|
25
|
+
*/
|
|
26
|
+
dimensions: {
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
plot: {
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
/** Theme-resolved semantic + categorical colors. */
|
|
37
|
+
theme: {
|
|
38
|
+
semantic: ThemeSemanticColors;
|
|
39
|
+
categorical: string[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Resolves a stable color for a given key (typically a node id or
|
|
43
|
+
* category) by hashing into the frame-resolved categorical palette.
|
|
44
|
+
* The palette comes from `colorScheme` (array or named d3 scheme like
|
|
45
|
+
* `"tableau10"` / `"set3"`), then the active theme's `categorical`,
|
|
46
|
+
* then a fallback. The same key always returns the same color for the
|
|
47
|
+
* lifetime of this store.
|
|
48
|
+
*
|
|
49
|
+
* Note: this does *not* honor `CategoryColorProvider` — network charts
|
|
50
|
+
* don't currently thread that into the pipeline. If you need
|
|
51
|
+
* cross-chart category color sync, pass a matching `colorScheme` to
|
|
52
|
+
* each chart instead.
|
|
53
|
+
*/
|
|
54
|
+
resolveColor: (key: string) => string;
|
|
55
|
+
/** User-supplied config blob threaded through `layoutConfig`. */
|
|
56
|
+
config: C;
|
|
57
|
+
}
|
|
58
|
+
export interface NetworkLayoutResult {
|
|
59
|
+
/** Positioned scene primitives. Circles, rects, or arcs. */
|
|
60
|
+
sceneNodes?: NetworkSceneNode[];
|
|
61
|
+
/** Positioned edges. Lines, beziers, ribbons, or curved. */
|
|
62
|
+
sceneEdges?: NetworkSceneEdge[];
|
|
63
|
+
/** Optional labels placed at arbitrary plot-relative positions. */
|
|
64
|
+
labels?: NetworkLabel[];
|
|
65
|
+
/** SVG overlays composited above the canvas. */
|
|
66
|
+
overlays?: ReactNode;
|
|
67
|
+
}
|
|
@@ -40,6 +40,29 @@ export interface RealtimeNode {
|
|
|
40
40
|
_pulseIntensity?: number;
|
|
41
41
|
_pulseColor?: string;
|
|
42
42
|
_pulseGlowRadius?: number;
|
|
43
|
+
/**
|
|
44
|
+
* @internal Hierarchy-layout-only extension fields. Set by
|
|
45
|
+
* `hierarchyLayoutPlugin` / `orbitLayoutPlugin` during layout and
|
|
46
|
+
* read by `hierarchySceneBuilders`. Typed `unknown` because the d3
|
|
47
|
+
* `HierarchyNode` shape is layout-specific (rectangular, circular,
|
|
48
|
+
* point) — consumers narrow with the structural fields they need.
|
|
49
|
+
*/
|
|
50
|
+
__hierarchyNode?: unknown;
|
|
51
|
+
/** @internal Circle-pack layout radius. Set by `hierarchyLayoutPlugin`. */
|
|
52
|
+
__radius?: number;
|
|
53
|
+
/**
|
|
54
|
+
* @internal Chord-layout extension. Carries the start/end angles
|
|
55
|
+
* for the arc segment representing this node, computed by
|
|
56
|
+
* `chordLayoutPlugin` and read by its `buildScene`. Concretely
|
|
57
|
+
* typed (unlike `__hierarchyNode`) because chord is the only
|
|
58
|
+
* layout that writes this field, so the shape is fixed — no
|
|
59
|
+
* narrowing-at-read needed. `__` prefix matches the convention
|
|
60
|
+
* used by `__hierarchyNode` / `__radius` on this same interface.
|
|
61
|
+
*/
|
|
62
|
+
__arcData?: {
|
|
63
|
+
startAngle: number;
|
|
64
|
+
endAngle: number;
|
|
65
|
+
};
|
|
43
66
|
}
|
|
44
67
|
export interface RealtimeEdge {
|
|
45
68
|
source: RealtimeNode | string;
|
|
@@ -69,6 +92,17 @@ export interface RealtimeEdge {
|
|
|
69
92
|
/** @internal Circular sankey layout fields */
|
|
70
93
|
_circularWidth?: number;
|
|
71
94
|
_circularStub?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* @internal Chord-layout extension. Carries the d3-chord-generated
|
|
97
|
+
* source/target arc spans for this edge, set by `chordLayoutPlugin`
|
|
98
|
+
* during `computeLayout` and read by its `buildScene`. Typed
|
|
99
|
+
* `unknown` because the d3 `Chord` interface lives in `d3-chord`
|
|
100
|
+
* and importing the type here would couple `networkTypes` to that
|
|
101
|
+
* dep — consumers narrow at the read site. `__` prefix matches the
|
|
102
|
+
* `_circularWidth` / `_circularStub` internal-field convention on
|
|
103
|
+
* this same interface.
|
|
104
|
+
*/
|
|
105
|
+
__chordData?: unknown;
|
|
72
106
|
}
|
|
73
107
|
export interface BezierPoint {
|
|
74
108
|
x: number;
|
|
@@ -402,6 +436,11 @@ export interface NetworkPipelineConfig {
|
|
|
402
436
|
x: number;
|
|
403
437
|
y: number;
|
|
404
438
|
}>;
|
|
439
|
+
/** When provided, replaces both layout dispatch and scene building.
|
|
440
|
+
* Receives raw nodes/edges and returns positioned scene primitives. */
|
|
441
|
+
customNetworkLayout?: import("./networkCustomLayout").NetworkCustomLayout;
|
|
442
|
+
/** User-supplied config blob threaded through to NetworkLayoutContext.config. */
|
|
443
|
+
layoutConfig?: object;
|
|
405
444
|
}
|
|
406
445
|
export interface StreamNetworkFrameProps<T = Datum> {
|
|
407
446
|
chartType: NetworkChartType;
|
|
@@ -507,6 +546,12 @@ export interface StreamNetworkFrameProps<T = Datum> {
|
|
|
507
546
|
description?: string;
|
|
508
547
|
/** Accessible summary rendered as a screen-reader-only note */
|
|
509
548
|
summary?: string;
|
|
549
|
+
/** Replaces network layout + scene dispatch with a user-supplied function.
|
|
550
|
+
* Receives raw nodes/edges + dimensions/theme, returns positioned scene
|
|
551
|
+
* primitives. See `semiotic/recipes` for reference layouts (flextree, dagre). */
|
|
552
|
+
customNetworkLayout?: import("./networkCustomLayout").NetworkCustomLayout;
|
|
553
|
+
/** User-supplied config blob threaded through to NetworkLayoutContext.config. */
|
|
554
|
+
layoutConfig?: object;
|
|
510
555
|
}
|
|
511
556
|
export interface StreamNetworkFrameHandle {
|
|
512
557
|
push(edge: EdgePush): void;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ScaleBand, ScaleLinear } from "d3-scale";
|
|
3
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
4
|
+
import type { MarginType } from "../types/marginType";
|
|
5
|
+
import type { OrdinalSceneNode, OrdinalScales } from "./ordinalTypes";
|
|
6
|
+
import type { ThemeSemanticColors } from "./types";
|
|
7
|
+
/**
|
|
8
|
+
* customLayout escape hatch for `StreamOrdinalFrame`.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the XY `CustomLayout` and network `NetworkCustomLayout` patterns.
|
|
11
|
+
* Reach for it when the catalog (bar, swarm, pie, box, ...) doesn't fit:
|
|
12
|
+
* marimekko, parallel coordinates, bullet charts, fan charts, slope graphs
|
|
13
|
+
* and similar are all natural ordinal customLayouts.
|
|
14
|
+
*
|
|
15
|
+
* The frame still owns hit testing, transitions, decay, theme cascade,
|
|
16
|
+
* and SSR — the layout owns geometry only. Emit standard scene nodes
|
|
17
|
+
* (`rect`, `point`, `wedge`, `boxplot`, `violin`, `connector`, `trapezoid`)
|
|
18
|
+
* and the frame handles the rest.
|
|
19
|
+
*/
|
|
20
|
+
export type OrdinalCustomLayout<C extends object = Record<string, unknown>> = (ctx: OrdinalLayoutContext<C>) => OrdinalLayoutResult;
|
|
21
|
+
export interface OrdinalLayoutContext<C extends object = Record<string, unknown>> {
|
|
22
|
+
/** Buffered, post-filter data the frame is currently drawing. */
|
|
23
|
+
data: Datum[];
|
|
24
|
+
/**
|
|
25
|
+
* Frame-built scales. `o` is the band scale over categories
|
|
26
|
+
* (insertion-ordered by default; flip via `oSort`). `r` is the linear
|
|
27
|
+
* value scale. Their domains/ranges respect `oExtent`/`rExtent` if you
|
|
28
|
+
* passed them on the chart.
|
|
29
|
+
*/
|
|
30
|
+
scales: {
|
|
31
|
+
o: ScaleBand<string>;
|
|
32
|
+
r: ScaleLinear<number, number>;
|
|
33
|
+
projection: OrdinalScales["projection"];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Plot-area geometry. The canvas/SVG group is already translated by
|
|
37
|
+
* the frame, so scene-node coordinates are *plot-local* — but the
|
|
38
|
+
* origin depends on `scales.projection`:
|
|
39
|
+
*
|
|
40
|
+
* - `vertical` / `horizontal`: origin is the **top-left** of the
|
|
41
|
+
* plot rect. `plot = { x: 0, y: 0, width, height }`.
|
|
42
|
+
* - `radial`: origin is the **center** of the plot rect. The frame
|
|
43
|
+
* translates the context to `(margin.left + width/2, margin.top
|
|
44
|
+
* + height/2)` so radial layouts emit coordinates around 0,0.
|
|
45
|
+
* `plot = { x: -width/2, y: -height/2, width, height }` — the
|
|
46
|
+
* top-left of the visible plot rect lives at `(plot.x, plot.y)`
|
|
47
|
+
* in your coord space.
|
|
48
|
+
*
|
|
49
|
+
* In both cases `plot.width` and `plot.height` describe the plot rect.
|
|
50
|
+
* Read `margin` if you need the outer canvas size.
|
|
51
|
+
*/
|
|
52
|
+
dimensions: {
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
margin: MarginType;
|
|
56
|
+
plot: {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/** Theme-resolved semantic + categorical colors. */
|
|
64
|
+
theme: {
|
|
65
|
+
semantic: ThemeSemanticColors;
|
|
66
|
+
categorical: string[];
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Resolves a stable color for a given key (typically a category
|
|
70
|
+
* label) from the frame's categorical palette. Palette precedence:
|
|
71
|
+
* explicit `colorScheme` (array or named d3 scheme like `"tableau10"`)
|
|
72
|
+
* → theme categorical → fallback. The same key always returns the
|
|
73
|
+
* same color for the lifetime of this store.
|
|
74
|
+
*/
|
|
75
|
+
resolveColor: (key: string) => string;
|
|
76
|
+
/** User-supplied config blob threaded through `layoutConfig`. */
|
|
77
|
+
config: C;
|
|
78
|
+
}
|
|
79
|
+
export interface OrdinalLayoutResult {
|
|
80
|
+
/** Scene nodes to render. Get hit testing, transitions, decay, SSR for free. */
|
|
81
|
+
nodes?: OrdinalSceneNode[];
|
|
82
|
+
/** SVG overlays composited above the canvas (labels, axis lines, annotations). */
|
|
83
|
+
overlays?: ReactNode;
|
|
84
|
+
}
|
|
@@ -5,7 +5,7 @@ import type { Style, SceneDatum, DecayConfig, PulseConfig, TransitionConfig, Sta
|
|
|
5
5
|
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
6
6
|
import type { LegendGroup } from "../types/legendTypes";
|
|
7
7
|
import type { Datum } from "../charts/shared/datumTypes";
|
|
8
|
-
export type OrdinalChartType = "bar" | "clusterbar" | "point" | "swarm" | "pie" | "donut" | "boxplot" | "violin" | "histogram" | "ridgeline" | "timeline" | "funnel" | "bar-funnel" | "swimlane";
|
|
8
|
+
export type OrdinalChartType = "bar" | "clusterbar" | "point" | "swarm" | "pie" | "donut" | "boxplot" | "violin" | "histogram" | "ridgeline" | "timeline" | "funnel" | "bar-funnel" | "swimlane" | "custom";
|
|
9
9
|
export interface OrdinalScales {
|
|
10
10
|
o: ScaleBand<string>;
|
|
11
11
|
r: ScaleLinear<number, number>;
|
|
@@ -187,6 +187,14 @@ export interface OrdinalPipelineConfig {
|
|
|
187
187
|
color: string;
|
|
188
188
|
}>;
|
|
189
189
|
};
|
|
190
|
+
/** Swimlane "track" fill — a rect drawn behind each lane spanning the
|
|
191
|
+
* full value-axis range, sized to the lane's bandwidth. Used to make
|
|
192
|
+
* budget/progress lanes read as filled vs. empty. Pass a color (CSS
|
|
193
|
+
* var supported) or `{ color, opacity }`. Honored by `chartType="swimlane"` only. */
|
|
194
|
+
trackFill?: string | {
|
|
195
|
+
color: string;
|
|
196
|
+
opacity?: number;
|
|
197
|
+
};
|
|
190
198
|
/** When true, adds padding below the 0 baseline. When false (default), bars are flush with the axis line. */
|
|
191
199
|
baselinePadding?: boolean;
|
|
192
200
|
innerRadius?: number;
|
|
@@ -225,6 +233,15 @@ export interface OrdinalPipelineConfig {
|
|
|
225
233
|
/** Whether to animate elements on first render (bars grow from baseline, wedges sweep in) */
|
|
226
234
|
introAnimation?: boolean;
|
|
227
235
|
staleness?: StalenessConfig;
|
|
236
|
+
/** When provided, replaces chart-type dispatch in scene building.
|
|
237
|
+
* Receives an OrdinalLayoutContext (scales, dimensions, theme,
|
|
238
|
+
* resolveColor) and returns scene nodes plus optional overlays. */
|
|
239
|
+
customLayout?: import("./ordinalCustomLayout").OrdinalCustomLayout;
|
|
240
|
+
/** User-supplied config blob threaded through to OrdinalLayoutContext.config. */
|
|
241
|
+
layoutConfig?: object;
|
|
242
|
+
/** Resolved margin — passed through so OrdinalLayoutContext.dimensions.margin
|
|
243
|
+
* reflects what the frame actually used. */
|
|
244
|
+
layoutMargin?: import("../types/marginType").MarginType;
|
|
228
245
|
}
|
|
229
246
|
export interface StreamOrdinalFrameProps<T = Datum> {
|
|
230
247
|
chartType: OrdinalChartType;
|
|
@@ -266,6 +283,11 @@ export interface StreamOrdinalFrameProps<T = Datum> {
|
|
|
266
283
|
color: string;
|
|
267
284
|
}>;
|
|
268
285
|
};
|
|
286
|
+
/** Swimlane "track" fill — see OrdinalPipelineConfig.trackFill */
|
|
287
|
+
trackFill?: string | {
|
|
288
|
+
color: string;
|
|
289
|
+
opacity?: number;
|
|
290
|
+
};
|
|
269
291
|
baselinePadding?: boolean;
|
|
270
292
|
innerRadius?: number;
|
|
271
293
|
cornerRadius?: number;
|
|
@@ -336,6 +358,10 @@ export interface StreamOrdinalFrameProps<T = Datum> {
|
|
|
336
358
|
legendHighlightedCategory?: string | null;
|
|
337
359
|
legendIsolatedCategories?: Set<string>;
|
|
338
360
|
legendPosition?: "right" | "left" | "top" | "bottom";
|
|
361
|
+
/** Accessor used to report the current legend category domain in push mode. */
|
|
362
|
+
legendCategoryAccessor?: string | ((d: T) => string);
|
|
363
|
+
/** Fires when the current legend category domain changes after scene rebuilds. */
|
|
364
|
+
onCategoriesChange?: (categories: string[]) => void;
|
|
339
365
|
backgroundGraphics?: ReactNode;
|
|
340
366
|
foregroundGraphics?: ReactNode;
|
|
341
367
|
title?: string | ReactNode;
|
|
@@ -364,6 +390,14 @@ export interface StreamOrdinalFrameProps<T = Datum> {
|
|
|
364
390
|
description?: string;
|
|
365
391
|
/** Accessible summary rendered as a screen-reader-only note */
|
|
366
392
|
summary?: string;
|
|
393
|
+
/** Replaces ordinal scene dispatch with a user-supplied function.
|
|
394
|
+
* Receives an OrdinalLayoutContext (scales, dimensions, theme,
|
|
395
|
+
* resolveColor), returns scene nodes + optional overlays. See
|
|
396
|
+
* `semiotic/recipes` for reference layouts (marimekko, parallel
|
|
397
|
+
* coordinates, bullet). */
|
|
398
|
+
customLayout?: import("./ordinalCustomLayout").OrdinalCustomLayout;
|
|
399
|
+
/** User-supplied config blob threaded through to OrdinalLayoutContext.config. */
|
|
400
|
+
layoutConfig?: object;
|
|
367
401
|
}
|
|
368
402
|
export interface StreamOrdinalFrameHandle<T = Datum> {
|
|
369
403
|
push(datum: T): void;
|
|
@@ -7,6 +7,14 @@ export declare const barFunnelHatchRenderer: (ctx: CanvasRenderingContext2D, nod
|
|
|
7
7
|
* - Bold percentage (of first step)
|
|
8
8
|
* - Raw value below it
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Light/dark mode is decided per-frame from the luminance of the
|
|
11
|
+
* resolved `--semiotic-text` value: if body text is light, we're in
|
|
12
|
+
* dark mode and pair a dark surface with light text; otherwise light
|
|
13
|
+
* mode (white surface, dark text). Pairing the background to whatever
|
|
14
|
+
* text color the consumer's theme actually emits is more robust than
|
|
15
|
+
* sourcing both from independent CSS variables — many sites set
|
|
16
|
+
* `--semiotic-text` and `--semiotic-bg` without setting
|
|
17
|
+
* `--semiotic-tooltip-bg`, which would otherwise leave the label box
|
|
18
|
+
* stuck on its fallback regardless of theme.
|
|
11
19
|
*/
|
|
12
20
|
export declare const barFunnelLabelRenderer: (ctx: CanvasRenderingContext2D, nodes: OrdinalSceneNode[], _scales: OrdinalScales, _layout: OrdinalLayout) => void;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared canvas-rendering primitives used by `bar`/`area`/`line`/`point`
|
|
3
|
+
* renderers (and any future mark renderer that paints a fill, a stroke,
|
|
4
|
+
* or a linear gradient).
|
|
5
|
+
*
|
|
6
|
+
* These are extractions, not abstractions: every function in this module
|
|
7
|
+
* was inline-duplicated across two or more renderers in byte-identical
|
|
8
|
+
* (or near-identical) form. Centralizing them eliminates drift at the
|
|
9
|
+
* "what does the canvas seam look like for a stream renderer" boundary
|
|
10
|
+
* and keeps each renderer focused on its mark-specific path tracing.
|
|
11
|
+
*
|
|
12
|
+
* Anything genuinely chart-shape-specific — `buildBarGradient`'s
|
|
13
|
+
* tip-vs-base coordinate computation from `node.roundedEdge`, the
|
|
14
|
+
* area's strip-decay path, the line's threshold-color crossing logic —
|
|
15
|
+
* stays in the renderer that owns the mark. The helpers here are the
|
|
16
|
+
* mechanical bits that recur regardless of the shape being painted.
|
|
17
|
+
*/
|
|
18
|
+
import type { CurveType } from "../types";
|
|
19
|
+
import type { CurveFactory } from "d3-shape";
|
|
20
|
+
/**
|
|
21
|
+
* Structural shapes for the gradient configs the helpers accept. Kept
|
|
22
|
+
* local rather than exported from `types.ts` because today's scene-node
|
|
23
|
+
* interfaces (`AreaSceneNode`, `RectSceneNode`, `LineSceneNode`) declare
|
|
24
|
+
* the same shapes inline. TS structural typing means a caller passing
|
|
25
|
+
* `node.fillGradient` satisfies these types without an explicit cast.
|
|
26
|
+
*/
|
|
27
|
+
type ColorStop = {
|
|
28
|
+
offset: number;
|
|
29
|
+
color: string;
|
|
30
|
+
};
|
|
31
|
+
export type ColorStopGradient = {
|
|
32
|
+
colorStops: ColorStop[];
|
|
33
|
+
};
|
|
34
|
+
export type OpacityGradient = {
|
|
35
|
+
topOpacity: number;
|
|
36
|
+
bottomOpacity: number;
|
|
37
|
+
};
|
|
38
|
+
export type FillGradient = ColorStopGradient | OpacityGradient;
|
|
39
|
+
/**
|
|
40
|
+
* Map a `CurveType` string to a d3-shape curve factory. Returns `null`
|
|
41
|
+
* for `"linear"` and `undefined` so callers can branch on a single
|
|
42
|
+
* "use linear fallback" sentinel instead of a separate has-curve check.
|
|
43
|
+
*
|
|
44
|
+
* Identical implementations previously lived in `areaCanvasRenderer.ts`
|
|
45
|
+
* and `lineCanvasRenderer.ts` — every new curve token had to be added
|
|
46
|
+
* to both switches in lockstep.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveCurveFactory(curve: CurveType | undefined): CurveFactory | null;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve a node's `style.fill` (or `style.stroke`) to something the
|
|
51
|
+
* canvas can accept as `fillStyle` / `strokeStyle`:
|
|
52
|
+
*
|
|
53
|
+
* - Strings go through `resolveCSSColor` so `var(...)` references
|
|
54
|
+
* resolve via the canvas DOM ancestor's computed style. Without
|
|
55
|
+
* this, canvas silently rejects CSS-variable strings and falls
|
|
56
|
+
* back to `#000000`.
|
|
57
|
+
* - `CanvasPattern` values pass through untouched.
|
|
58
|
+
* - `null` / `undefined` returns the caller-provided fallback.
|
|
59
|
+
*
|
|
60
|
+
* The previous inline form was
|
|
61
|
+
* `(typeof X === "string" ? resolveCSSColor(ctx, X) : X) || fallback`,
|
|
62
|
+
* repeated once per renderer per fill/stroke site.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveCanvasFill(ctx: CanvasRenderingContext2D, fill: string | CanvasPattern | null | undefined, fallback: string): string | CanvasPattern;
|
|
65
|
+
/**
|
|
66
|
+
* Build a linear gradient from a `FillGradient` config. Returns `null`
|
|
67
|
+
* when the gradient cannot be constructed (fewer than two valid color
|
|
68
|
+
* stops in the `colorStops` form, or a non-finite opacity in the
|
|
69
|
+
* `topOpacity` form).
|
|
70
|
+
*
|
|
71
|
+
* The renderer is responsible for choosing the gradient axis (a bar
|
|
72
|
+
* runs tip→base along its value axis; an area runs minTop→maxBottom
|
|
73
|
+
* vertically). The opacity-form path color-normalizes through the
|
|
74
|
+
* canvas via `parseCanvasColor` so named colors (`steelblue`), hsl(),
|
|
75
|
+
* etc. all produce gradients that match the mark's actual fill.
|
|
76
|
+
*
|
|
77
|
+
* Replaces `buildBarGradient` (bar) and the inline gradient block in
|
|
78
|
+
* `areaCanvasRenderer` — both implemented the same two-shape switch
|
|
79
|
+
* with the same offset-clamping and the same parseCanvasColor flow.
|
|
80
|
+
*/
|
|
81
|
+
export declare function buildLinearFillGradient(ctx: CanvasRenderingContext2D, fillGradient: FillGradient, baseFill: string, x0: number, y0: number, x1: number, y1: number): CanvasGradient | null;
|
|
82
|
+
/**
|
|
83
|
+
* Build a linear gradient from a `ColorStopGradient` (the stroke-side
|
|
84
|
+
* shape — only the `colorStops` form, no opacity variant). Returns
|
|
85
|
+
* `null` when there aren't enough valid stops to render a gradient.
|
|
86
|
+
*
|
|
87
|
+
* Caller picks the axis. Identical patterns previously lived inline in
|
|
88
|
+
* `areaCanvasRenderer`'s top-stroke branch and `lineCanvasRenderer`'s
|
|
89
|
+
* stroke branch.
|
|
90
|
+
*/
|
|
91
|
+
export declare function buildColorStopGradient(ctx: CanvasRenderingContext2D, strokeGradient: ColorStopGradient, x0: number, y0: number, x1: number, y1: number): CanvasGradient | null;
|
|
92
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CurveFactory } from "d3-shape";
|
|
2
|
+
/**
|
|
3
|
+
* Sample a d3-shape curve through `points` into a dense polyline.
|
|
4
|
+
*
|
|
5
|
+
* Returns the same `points` array unchanged when `curveFactory` is
|
|
6
|
+
* null — caller should treat that as the linear case (no resampling
|
|
7
|
+
* needed).
|
|
8
|
+
*/
|
|
9
|
+
export declare function sampleCurvePath(points: ReadonlyArray<readonly [number, number]>, curveFactory: CurveFactory | null, samplesPerSegment?: number): [number, number][];
|
|
@@ -74,7 +74,7 @@ export interface MarginalGraphicsConfig {
|
|
|
74
74
|
left?: MarginalConfig | MarginalType;
|
|
75
75
|
right?: MarginalConfig | MarginalType;
|
|
76
76
|
}
|
|
77
|
-
export type StreamChartType = "line" | "area" | "stackedarea" | "mixed" | "scatter" | "bubble" | "heatmap" | "bar" | "swarm" | "waterfall" | "candlestick";
|
|
77
|
+
export type StreamChartType = "line" | "area" | "stackedarea" | "mixed" | "scatter" | "bubble" | "heatmap" | "bar" | "swarm" | "waterfall" | "candlestick" | "custom";
|
|
78
78
|
export type RuntimeMode = "bounded" | "streaming";
|
|
79
79
|
export interface Style {
|
|
80
80
|
stroke?: string;
|
|
@@ -137,6 +137,14 @@ export interface AreaSceneNode {
|
|
|
137
137
|
style: Style;
|
|
138
138
|
datum: SeriesDatum;
|
|
139
139
|
group?: string;
|
|
140
|
+
/** Clip the area to this rect (in plot-relative pixels). Used by horizon
|
|
141
|
+
* charts to band a single series into N slices. */
|
|
142
|
+
clipRect?: {
|
|
143
|
+
x: number;
|
|
144
|
+
y: number;
|
|
145
|
+
width: number;
|
|
146
|
+
height: number;
|
|
147
|
+
};
|
|
140
148
|
/** Gradient fill: opacity-based (topOpacity/bottomOpacity) or multi-color (colorStops) */
|
|
141
149
|
fillGradient?: {
|
|
142
150
|
topOpacity: number;
|
|
@@ -364,6 +372,27 @@ export interface StreamXYFrameProps<T = Datum> {
|
|
|
364
372
|
lineDataAccessor?: string;
|
|
365
373
|
curve?: CurveType;
|
|
366
374
|
normalize?: boolean;
|
|
375
|
+
/**
|
|
376
|
+
* Stacked area baseline. Only consulted by stackedarea chartType.
|
|
377
|
+
* - "zero" (default): standard stack from y=0
|
|
378
|
+
* - "wiggle": Byron–Wattenberg streamgraph offset (minimizes wiggle)
|
|
379
|
+
* - "silhouette": center the stack symmetrically around y=0
|
|
380
|
+
*
|
|
381
|
+
* Mutually exclusive with `normalize`: when `normalize` is `true`, the
|
|
382
|
+
* stack is forced to a `"zero"` baseline (any other value is ignored)
|
|
383
|
+
* because normalization assumes a fixed `[0, 1]` y-domain.
|
|
384
|
+
*/
|
|
385
|
+
baseline?: "zero" | "wiggle" | "silhouette";
|
|
386
|
+
/**
|
|
387
|
+
* Stack order — controls which series sits at the top, middle, or bottom.
|
|
388
|
+
* - "key" (default): alphabetical by group key
|
|
389
|
+
* - "insideOut": largest-total series in the middle, smaller alternating
|
|
390
|
+
* above/below. Combined with `baseline: "wiggle"` or `"silhouette"`,
|
|
391
|
+
* produces the canonical streamgraph look where a "central anchor"
|
|
392
|
+
* layer sits across y=0 and other layers stack outward.
|
|
393
|
+
* - "asc" / "desc": by total ascending / descending
|
|
394
|
+
*/
|
|
395
|
+
stackOrder?: "key" | "insideOut" | "asc" | "desc";
|
|
367
396
|
/**
|
|
368
397
|
* Accessor returning a symmetric uncertainty offset per datum.
|
|
369
398
|
* When set, an uncertainty band is drawn ± this offset from the line.
|
|
@@ -506,6 +535,10 @@ export interface StreamXYFrameProps<T = Datum> {
|
|
|
506
535
|
legendHighlightedCategory?: string | null;
|
|
507
536
|
legendIsolatedCategories?: Set<string>;
|
|
508
537
|
legendPosition?: "right" | "left" | "top" | "bottom";
|
|
538
|
+
/** Accessor used to report the current legend category domain in push mode. */
|
|
539
|
+
legendCategoryAccessor?: string | ((d: T) => string);
|
|
540
|
+
/** Fires when the current legend category domain changes after scene rebuilds. */
|
|
541
|
+
onCategoriesChange?: (categories: string[]) => void;
|
|
509
542
|
/** SVG elements rendered behind the canvas (in pixel space) */
|
|
510
543
|
backgroundGraphics?: ReactNode;
|
|
511
544
|
/** SVG elements rendered on top of everything (in SVG overlay) */
|
|
@@ -550,6 +583,16 @@ export interface StreamXYFrameProps<T = Datum> {
|
|
|
550
583
|
linkedCrosshairName?: string;
|
|
551
584
|
/** Source chart ID — crosshair is suppressed on the source chart to avoid double rendering */
|
|
552
585
|
linkedCrosshairSourceId?: string;
|
|
586
|
+
/** Replaces chart-type scene dispatch with a user-supplied layout function.
|
|
587
|
+
* Receives a LayoutContext (scales, dimensions, theme, resolveColor) and
|
|
588
|
+
* returns SceneNode[] + optional overlays. See `semiotic/recipes` for
|
|
589
|
+
* reference layouts (waffle, calendar, horizon). */
|
|
590
|
+
customLayout?: import("./customLayout").CustomLayout;
|
|
591
|
+
/** User-supplied config blob threaded through to LayoutContext.config.
|
|
592
|
+
* Typed as `object` so caller-defined interfaces (without an index
|
|
593
|
+
* signature) flow through without casts; layouts narrow via their
|
|
594
|
+
* own `CustomLayout<TConfig>` parameterization. */
|
|
595
|
+
layoutConfig?: object;
|
|
553
596
|
}
|
|
554
597
|
export interface StreamXYFrameHandle<T = Datum> {
|
|
555
598
|
push(datum: T): void;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { MutableRefObject, RefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Returns `false` on the server (no effect fires there) and during the
|
|
4
|
+
* first client render after hydration; `true` from the first
|
|
5
|
+
* post-commit re-render onward.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useHydration(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Returns `true` when this component instance was mounted via SSR
|
|
10
|
+
* hydration (i.e. there was server-rendered HTML to hydrate from), and
|
|
11
|
+
* `false` when it was mounted via pure client-side rendering (no SSR).
|
|
12
|
+
*
|
|
13
|
+
* The trick: `useSyncExternalStore`'s `getServerSnapshot` callback is
|
|
14
|
+
* called *only* during hydration of server-rendered content — never
|
|
15
|
+
* during a fresh CSR mount. Returning different values from the two
|
|
16
|
+
* snapshots lets us read the hydration mode on the very first render,
|
|
17
|
+
* then we capture it into a ref so it survives later renders.
|
|
18
|
+
*
|
|
19
|
+
* Stream Frames use this to decide whether to skip the intro animation
|
|
20
|
+
* on the canvas's first paint: when SSR has already shown the chart in
|
|
21
|
+
* its final state, re-animating from blank when the canvas takes over
|
|
22
|
+
* looks like a regression. CSR mounts keep their intro animation
|
|
23
|
+
* because the SVG branch's output never actually paints (it's
|
|
24
|
+
* overwritten by the canvas branch within the same paint frame, before
|
|
25
|
+
* the browser commits a frame).
|
|
26
|
+
*/
|
|
27
|
+
export declare function useWasHydratingFromSSR(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Shared post-hydration lifecycle for every Stream Frame.
|
|
30
|
+
*
|
|
31
|
+
* Three things happen on every commit-after-hydration:
|
|
32
|
+
*
|
|
33
|
+
* 1. If we just rehydrated from SSR, cancel the intro animation that
|
|
34
|
+
* the SVG-branch's `computeScene` installed (the server already
|
|
35
|
+
* painted the chart in its final state — re-animating from blank
|
|
36
|
+
* on the canvas takeover is a visual regression).
|
|
37
|
+
* 2. Mark the scene dirty so the canvas-paint pipeline rebuilds.
|
|
38
|
+
* 3. **Paint the canvas synchronously** via `renderFnRef.current()`.
|
|
39
|
+
*
|
|
40
|
+
* Step 3 is the timing-critical bit. The hook fires inside an
|
|
41
|
+
* isomorphic layout effect — `useLayoutEffect` on the client (runs
|
|
42
|
+
* synchronously after commit but before the browser paints),
|
|
43
|
+
* `useEffect` on the server (no-op, since SSR doesn't paint). If we
|
|
44
|
+
* deferred the paint to a `requestAnimationFrame` (the standard
|
|
45
|
+
* `scheduleRender()` route), the rAF callback wouldn't fire until
|
|
46
|
+
* the *next* frame — meaning the browser would paint *frame N* with
|
|
47
|
+
* the canvas in DOM but blank, then *frame N+1* with the canvas
|
|
48
|
+
* actually drawn. Synchronous paint inside the layout effect makes
|
|
49
|
+
* frame N's paint already include the canvas content; no flash.
|
|
50
|
+
*
|
|
51
|
+
* Each frame supplies its own `cleanup` for unmount work that's
|
|
52
|
+
* frame-specific (XY/Ordinal clear the streaming adapter; Geo clears
|
|
53
|
+
* its tile cache; Network has no extra cleanup).
|
|
54
|
+
*/
|
|
55
|
+
export interface HydrationLifecycleOptions {
|
|
56
|
+
hydrated: boolean;
|
|
57
|
+
wasHydratingFromSSR: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Ref to the frame's pipeline store. The store optionally implements
|
|
60
|
+
* `cancelIntroAnimation()`; the hook calls it when the SVG → canvas
|
|
61
|
+
* swap fires after SSR rehydration. (Currently every shipped store
|
|
62
|
+
* implements the method, but the optional shape lets a custom store
|
|
63
|
+
* opt out.)
|
|
64
|
+
*/
|
|
65
|
+
storeRef: RefObject<{
|
|
66
|
+
cancelIntroAnimation?: () => void;
|
|
67
|
+
} | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Mutable dirty flag the renderer reads on its next paint. The hook
|
|
70
|
+
* sets it to true on every commit so the post-hydration paint
|
|
71
|
+
* rebuilds the scene from scratch.
|
|
72
|
+
*/
|
|
73
|
+
dirtyRef: MutableRefObject<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Ref to the frame's render closure (assigned by `useFrame` /
|
|
76
|
+
* the frame body). The hook calls this synchronously to paint
|
|
77
|
+
* within the same frame as the SVG → canvas swap commit, avoiding
|
|
78
|
+
* the one-frame blank-canvas flicker that an rAF-deferred paint
|
|
79
|
+
* would produce.
|
|
80
|
+
*/
|
|
81
|
+
renderFnRef: MutableRefObject<() => void>;
|
|
82
|
+
/**
|
|
83
|
+
* Optional unmount cleanup. Frame-specific work the hook can't
|
|
84
|
+
* generalize — e.g. clearing the streaming `DataSourceAdapter`
|
|
85
|
+
* (XY/Ordinal) or the geo tile cache.
|
|
86
|
+
*/
|
|
87
|
+
cleanup?: () => void;
|
|
88
|
+
}
|
|
89
|
+
export declare function useHydrationLifecycle(opts: HydrationLifecycleOptions): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useStableShallow<T>(value: T): T;
|
|
@@ -46,6 +46,10 @@ export interface XYSceneConfig {
|
|
|
46
46
|
curve?: CurveType;
|
|
47
47
|
colorScheme?: string | string[];
|
|
48
48
|
normalize?: boolean;
|
|
49
|
+
/** Stacked area baseline. "zero" (default), "wiggle" (streamgraph), "silhouette" (centered). */
|
|
50
|
+
baseline?: "zero" | "wiggle" | "silhouette";
|
|
51
|
+
/** Stack order — see PipelineConfig.stackOrder. */
|
|
52
|
+
stackOrder?: "key" | "insideOut" | "asc" | "desc";
|
|
49
53
|
gradientFill?: boolean | {
|
|
50
54
|
topOpacity?: number;
|
|
51
55
|
bottomOpacity?: number;
|