semiotic 3.5.1 → 3.5.2
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 +21 -19
- package/README.md +22 -16
- package/ai/chartSuggestions.cjs +191 -3
- package/ai/componentMetadata.cjs +3 -3
- package/ai/dist/mcp-server.js +266 -48
- package/ai/examples.md +68 -0
- package/ai/schema.json +900 -1
- package/ai/system-prompt.md +4 -1
- package/dist/components/Tooltip/FlippingTooltip.d.ts +16 -1
- package/dist/components/charts/geo/FlowMap.d.ts +13 -4
- package/dist/components/charts/index.d.ts +6 -0
- package/dist/components/charts/network/OrbitDiagram.d.ts +5 -5
- package/dist/components/charts/network/ProcessSankey.d.ts +141 -0
- package/dist/components/charts/network/processSankey/algorithm.d.ts +136 -0
- package/dist/components/charts/network/processSankey/buildScenes.d.ts +45 -0
- package/dist/components/charts/network/processSankey/ribbonInputs.d.ts +32 -0
- package/dist/components/charts/network/processSankey/streamingLayout.d.ts +58 -0
- package/dist/components/charts/network/processSankey/tooltipUtils.d.ts +41 -0
- package/dist/components/charts/ordinal/BarChart.d.ts +12 -0
- package/dist/components/charts/ordinal/DotPlot.d.ts +9 -0
- package/dist/components/charts/ordinal/GaugeChart.d.ts +20 -0
- package/dist/components/charts/ordinal/SwimlaneChart.d.ts +5 -0
- package/dist/components/charts/realtime/RealtimeHistogram.d.ts +14 -11
- package/dist/components/charts/realtime/defaultRealtimeTooltip.d.ts +19 -0
- package/dist/components/charts/shared/axisExtent.d.ts +59 -0
- package/dist/components/charts/shared/chartSpecs.d.ts +75 -0
- package/dist/components/charts/shared/colorUtils.d.ts +8 -2
- package/dist/components/charts/shared/networkUtils.d.ts +3 -5
- package/dist/components/charts/shared/radialGeometry.d.ts +99 -0
- package/dist/components/charts/shared/regressionUtils.d.ts +59 -0
- package/dist/components/charts/shared/selectionUtils.d.ts +8 -1
- package/dist/components/charts/shared/streamPropsHelpers.d.ts +5 -0
- package/dist/components/charts/shared/types.d.ts +13 -0
- package/dist/components/charts/shared/useAreaSeriesSetup.d.ts +75 -0
- package/dist/components/charts/shared/useEncodingDomain.d.ts +48 -0
- package/dist/components/charts/shared/useFrameImperativeHandle.d.ts +1 -1
- package/dist/components/charts/shared/useNetworkChartSetup.d.ts +148 -0
- package/dist/components/charts/shared/useOrdinalPieceStyle.d.ts +87 -0
- package/dist/components/charts/shared/useSeriesFeatures.d.ts +57 -0
- package/dist/components/charts/shared/useStreamStatus.d.ts +33 -0
- package/dist/components/charts/shared/useXYLineStyle.d.ts +69 -0
- package/dist/components/charts/shared/useXYPointStyle.d.ts +87 -0
- package/dist/components/charts/xy/AreaChart.d.ts +24 -0
- package/dist/components/charts/xy/BubbleChart.d.ts +9 -0
- package/dist/components/charts/xy/ConnectedScatterplot.d.ts +16 -0
- package/dist/components/charts/xy/DifferenceChart.d.ts +172 -0
- package/dist/components/charts/xy/Scatterplot.d.ts +34 -0
- package/dist/components/geometry/ribbonGeometry.d.ts +76 -0
- package/dist/components/semiotic-ai.d.ts +2 -0
- package/dist/components/semiotic-network.d.ts +4 -0
- package/dist/components/semiotic-realtime.d.ts +2 -0
- package/dist/components/semiotic-utils.d.ts +4 -0
- package/dist/components/semiotic-xy.d.ts +2 -0
- package/dist/components/semiotic.d.ts +3 -3
- package/dist/components/server/serverChartConfigs.d.ts +2 -0
- package/dist/components/stream/GeoPipelineStore.d.ts +21 -0
- package/dist/components/stream/OrdinalSVGOverlay.d.ts +8 -0
- package/dist/components/stream/PipelineStore.d.ts +5 -0
- package/dist/components/stream/SVGOverlay.d.ts +18 -0
- package/dist/components/stream/annotationAccessorResolver.d.ts +39 -0
- package/dist/components/stream/geoTypes.d.ts +12 -0
- package/dist/components/stream/ordinalTypes.d.ts +12 -0
- package/dist/components/stream/renderers/cornerRadii.d.ts +33 -0
- package/dist/components/stream/types.d.ts +23 -0
- package/dist/components/types/legendTypes.d.ts +1 -1
- 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.d.ts +2 -0
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-network.d.ts +4 -0
- package/dist/semiotic-realtime.d.ts +2 -0
- package/dist/semiotic-recipes.min.js +1 -1
- package/dist/semiotic-recipes.module.min.js +1 -1
- package/dist/semiotic-utils.d.ts +4 -0
- package/dist/semiotic-utils.min.js +1 -1
- package/dist/semiotic-utils.module.min.js +1 -1
- package/dist/semiotic-xy.d.ts +2 -0
- package/dist/semiotic.d.ts +3 -3
- 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/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +10 -5
package/ai/system-prompt.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Semiotic — React Data Visualization
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- semiotic-bundle-sizes:start -->
|
|
4
|
+
<!-- Auto-generated by scripts/sync-bundle-sizes.mjs — do not edit by hand. -->
|
|
5
|
+
**Use sub-path imports** — `semiotic/xy` (83KB gz), `semiotic/ordinal` (67KB gz), `semiotic/network` (62KB gz), `semiotic/geo` (50KB gz), `semiotic/realtime` (88KB gz), `semiotic/server` (114KB gz), `semiotic/utils` (22KB gz), `semiotic/recipes` (5KB gz), `semiotic/themes` (4KB gz), `semiotic/data` (3KB gz), `semiotic/ai` (184KB gz). Full `semiotic` is 183KB gz.
|
|
6
|
+
<!-- semiotic-bundle-sizes:end -->
|
|
4
7
|
|
|
5
8
|
## Flat Array Data (`data: object[]`)
|
|
6
9
|
- **LineChart** — `xAccessor`, `yAccessor`, `lineBy` (multi-line), `curve`
|
|
@@ -29,6 +29,21 @@ interface FlippingTooltipProps {
|
|
|
29
29
|
* On first render, uses a heuristic (similar to the old 70%/30% thresholds).
|
|
30
30
|
* After measuring the actual tooltip size via ref, repositions precisely to
|
|
31
31
|
* prevent clipping against container edges.
|
|
32
|
+
*
|
|
33
|
+
* Two defensive behaviors:
|
|
34
|
+
*
|
|
35
|
+
* - **Chrome guarantee.** If the rendered tooltip content lacks the
|
|
36
|
+
* `semiotic-tooltip` className on its root, the wrapper applies
|
|
37
|
+
* `defaultTooltipStyle` to itself so the tooltip always has a
|
|
38
|
+
* visible background, padding, and shadow. Shared tooltip helpers
|
|
39
|
+
* keep working unchanged (their `semiotic-tooltip` class causes the
|
|
40
|
+
* wrapper to stay transparent).
|
|
41
|
+
* - **Non-finite position guard.** Returns `null` when `x` or `y` is
|
|
42
|
+
* `NaN` / `Infinity`. The frame's hover plumbing can occasionally
|
|
43
|
+
* produce a non-finite hit-test result during a scale rebuild or
|
|
44
|
+
* when a custom layout emits a degenerate vertex; without the
|
|
45
|
+
* guard, React throws `'NaN' is an invalid value for the 'top' css
|
|
46
|
+
* style property` and the entire frame stops rendering.
|
|
32
47
|
*/
|
|
33
|
-
export declare function FlippingTooltip({ x, y, containerWidth, containerHeight, margin, children, className, zIndex }: FlippingTooltipProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
export declare function FlippingTooltip({ x, y, containerWidth, containerHeight, margin, children, className, zIndex }: FlippingTooltipProps): import("react/jsx-runtime").JSX.Element | null;
|
|
34
49
|
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Datum } from "../shared/datumTypes";
|
|
2
|
+
import * as React from "react";
|
|
2
3
|
import type { StreamGeoFrameProps, ProjectionProp } from "../../stream/geoTypes";
|
|
4
|
+
import type { RealtimeFrameHandle } from "../../realtime/types";
|
|
3
5
|
import type { BaseChartProps, ChartAccessor } from "../shared/types";
|
|
4
6
|
import { type TooltipProp } from "../../Tooltip/Tooltip";
|
|
5
7
|
import type { LegendInteractionMode, LegendPosition } from "../shared/hooks";
|
|
@@ -79,6 +81,13 @@ export interface FlowMapProps<TDatum extends Datum = Datum> extends BaseChartPro
|
|
|
79
81
|
tileCacheSize?: number;
|
|
80
82
|
/** Annotations */
|
|
81
83
|
annotations?: Datum[];
|
|
84
|
+
/**
|
|
85
|
+
* ID accessor on flow records — required for `ref.current.remove(id)`
|
|
86
|
+
* and `ref.current.update(id, …)`. The accessor reads the same field
|
|
87
|
+
* the user supplies on each flow; the field is preserved on the
|
|
88
|
+
* resolved line entry so the frame's `removeLine` can match by id.
|
|
89
|
+
*/
|
|
90
|
+
lineIdAccessor?: string | ((d: Datum) => string);
|
|
82
91
|
/** Passthrough */
|
|
83
92
|
frameProps?: Partial<Omit<StreamGeoFrameProps, "projection">>;
|
|
84
93
|
}
|
|
@@ -132,7 +141,7 @@ export interface FlowMapProps<TDatum extends Datum = Datum> extends BaseChartPro
|
|
|
132
141
|
* />
|
|
133
142
|
* ```
|
|
134
143
|
*/
|
|
135
|
-
export declare
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
144
|
+
export declare const FlowMap: {
|
|
145
|
+
<TDatum extends Datum = Datum>(props: FlowMapProps<TDatum> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
|
|
146
|
+
displayName?: string;
|
|
147
|
+
};
|
|
@@ -14,6 +14,8 @@ export { LineChart } from "./xy/LineChart";
|
|
|
14
14
|
export type { LineChartProps } from "./xy/LineChart";
|
|
15
15
|
export { AreaChart } from "./xy/AreaChart";
|
|
16
16
|
export type { AreaChartProps } from "./xy/AreaChart";
|
|
17
|
+
export { DifferenceChart } from "./xy/DifferenceChart";
|
|
18
|
+
export type { DifferenceChartProps } from "./xy/DifferenceChart";
|
|
17
19
|
export { StackedAreaChart } from "./xy/StackedAreaChart";
|
|
18
20
|
export type { StackedAreaChartProps } from "./xy/StackedAreaChart";
|
|
19
21
|
export { Heatmap } from "./xy/Heatmap";
|
|
@@ -72,6 +74,10 @@ export { ChordDiagram } from "./network/ChordDiagram";
|
|
|
72
74
|
export type { ChordDiagramProps } from "./network/ChordDiagram";
|
|
73
75
|
export { SankeyDiagram } from "./network/SankeyDiagram";
|
|
74
76
|
export type { SankeyDiagramProps } from "./network/SankeyDiagram";
|
|
77
|
+
export { ProcessSankey } from "./network/ProcessSankey";
|
|
78
|
+
export type { ProcessSankeyProps, ProcessSankeyTick } from "./network/ProcessSankey";
|
|
79
|
+
export { validateProcessSankey, formatProcessSankeyIssue, } from "./network/processSankey/algorithm";
|
|
80
|
+
export type { ProcessSankeyNode as ProcessSankeyValidatorNode, ProcessSankeyEdge as ProcessSankeyValidatorEdge, ProcessSankeyIssue, } from "./network/processSankey/algorithm";
|
|
75
81
|
export { TreeDiagram } from "./network/TreeDiagram";
|
|
76
82
|
export type { TreeDiagramProps } from "./network/TreeDiagram";
|
|
77
83
|
export { Treemap } from "./network/Treemap";
|
|
@@ -4,7 +4,7 @@ import type { StreamNetworkFrameProps } from "../../stream/networkTypes";
|
|
|
4
4
|
import type { BaseChartProps } from "../shared/types";
|
|
5
5
|
import { type TooltipProp } from "../../Tooltip/Tooltip";
|
|
6
6
|
export interface OrbitNode {
|
|
7
|
-
datum:
|
|
7
|
+
datum: Datum;
|
|
8
8
|
x: number;
|
|
9
9
|
y: number;
|
|
10
10
|
ring: number;
|
|
@@ -38,11 +38,11 @@ export interface OrbitDiagramProps<TDatum extends Datum = Datum> extends BaseCha
|
|
|
38
38
|
*/
|
|
39
39
|
orbitMode?: OrbitMode;
|
|
40
40
|
/** Ring size divisor per depth. Larger = tighter orbits. @default 2.95 */
|
|
41
|
-
orbitSize?: number | ((node:
|
|
41
|
+
orbitSize?: number | ((node: Datum) => number);
|
|
42
42
|
/** Orbit speed in degrees per frame @default 0.25 */
|
|
43
43
|
speed?: number;
|
|
44
44
|
/** Per-node speed modifier @default (node) => 1 / (node.depth + 1) */
|
|
45
|
-
revolution?: (node:
|
|
45
|
+
revolution?: (node: Datum) => number;
|
|
46
46
|
/**
|
|
47
47
|
* Built-in revolution style presets:
|
|
48
48
|
* - "locked": children rotate with parent at decreasing speed (default)
|
|
@@ -53,11 +53,11 @@ export interface OrbitDiagramProps<TDatum extends Datum = Datum> extends BaseCha
|
|
|
53
53
|
*/
|
|
54
54
|
revolutionStyle?: "locked" | "decay" | "alternate";
|
|
55
55
|
/** Vertical squash for elliptical orbits. 1 = circle, 0.5 = ellipse @default 1 */
|
|
56
|
-
eccentricity?: number | ((node:
|
|
56
|
+
eccentricity?: number | ((node: Datum) => number);
|
|
57
57
|
/** Show orbital ring paths @default true */
|
|
58
58
|
showRings?: boolean;
|
|
59
59
|
/** Node radius. Number or function of node. @default 6 */
|
|
60
|
-
nodeRadius?: number | ((node:
|
|
60
|
+
nodeRadius?: number | ((node: Datum) => number);
|
|
61
61
|
/** Show node labels @default false */
|
|
62
62
|
showLabels?: boolean;
|
|
63
63
|
/** Enable animation @default true */
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { Datum } from "../shared/datumTypes";
|
|
3
|
+
import type { BaseChartProps, ChartAccessor } from "../shared/types";
|
|
4
|
+
import type { RealtimeFrameHandle } from "../../realtime/types";
|
|
5
|
+
import type { StreamNetworkFrameProps, ParticleStyle } from "../../stream/networkTypes";
|
|
6
|
+
import { type TooltipProp } from "../../Tooltip/Tooltip";
|
|
7
|
+
type TimeLike = number | Date | string;
|
|
8
|
+
export interface ProcessSankeyTick {
|
|
9
|
+
date: TimeLike;
|
|
10
|
+
label: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ProcessSankeyProps<TNode extends Datum = Datum, TEdge extends Datum = Datum> extends BaseChartProps {
|
|
13
|
+
nodes?: TNode[];
|
|
14
|
+
edges?: TEdge[];
|
|
15
|
+
/** [tStart, tEnd] of the chart's x-axis. Required. */
|
|
16
|
+
domain: [TimeLike, TimeLike];
|
|
17
|
+
/** Optional axis ticks. Each tick: { date, label }. */
|
|
18
|
+
axisTicks?: ProcessSankeyTick[];
|
|
19
|
+
nodeIdAccessor?: ChartAccessor<TNode, string>;
|
|
20
|
+
sourceAccessor?: ChartAccessor<TEdge, string>;
|
|
21
|
+
targetAccessor?: ChartAccessor<TEdge, string>;
|
|
22
|
+
valueAccessor?: ChartAccessor<TEdge, number>;
|
|
23
|
+
startTimeAccessor?: ChartAccessor<TEdge, TimeLike>;
|
|
24
|
+
endTimeAccessor?: ChartAccessor<TEdge, TimeLike>;
|
|
25
|
+
/**
|
|
26
|
+
* Accessor for a node's explicit lifetime extent — a `[start, end]`
|
|
27
|
+
* tuple of time-likes. Lane spans
|
|
28
|
+
* `min(xExtent[0], earliestEdge)` to `max(xExtent[1], latestEdge)`.
|
|
29
|
+
*/
|
|
30
|
+
xExtentAccessor?: ChartAccessor<TNode, [TimeLike, TimeLike]>;
|
|
31
|
+
edgeIdAccessor?: ChartAccessor<TEdge, string>;
|
|
32
|
+
colorBy?: ChartAccessor<TNode, string>;
|
|
33
|
+
colorScheme?: string | string[];
|
|
34
|
+
/** Show a swatch + label legend. Defaults to `true` when `colorBy` is set. */
|
|
35
|
+
showLegend?: boolean;
|
|
36
|
+
/** Legend position. Default `"right"`. */
|
|
37
|
+
legendPosition?: "right" | "left" | "top" | "bottom";
|
|
38
|
+
/**
|
|
39
|
+
* Format function for time values — applied to axis tick labels and
|
|
40
|
+
* to time fields in the default tooltip. Same convention as
|
|
41
|
+
* `xFormat` on XY charts.
|
|
42
|
+
*/
|
|
43
|
+
timeFormat?: (d: number | Date) => string | React.ReactNode;
|
|
44
|
+
/** Format function for the `value` field. Mirrors `yFormat` on XY charts. */
|
|
45
|
+
valueFormat?: (d: number) => string | React.ReactNode;
|
|
46
|
+
pairing?: "value" | "temporal";
|
|
47
|
+
packing?: "off" | "reuse";
|
|
48
|
+
laneOrder?: "insertion" | "crossing-min" | "inside-out" | "crossing-min+inside-out";
|
|
49
|
+
ribbonLane?: "source" | "target" | "both";
|
|
50
|
+
lifetimeMode?: "full" | "half";
|
|
51
|
+
showLaneRails?: boolean;
|
|
52
|
+
showQualityReadout?: boolean;
|
|
53
|
+
edgeOpacity?: number;
|
|
54
|
+
/** Tooltip content. `false` disables, `true` uses the default,
|
|
55
|
+
* or pass a `Tooltip(...)` / custom function for full control. */
|
|
56
|
+
tooltip?: TooltipProp;
|
|
57
|
+
enableHover?: boolean;
|
|
58
|
+
onClick?: (datum: Datum, position?: {
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
}) => void;
|
|
62
|
+
showParticles?: boolean;
|
|
63
|
+
/** Style config for the particle overlay — same shape
|
|
64
|
+
* StreamNetworkFrame consumes from SankeyDiagram. Defaults
|
|
65
|
+
* (radius 3, opacity 0.7, spawnRate 0.1, maxPerEdge 50) live in
|
|
66
|
+
* `DEFAULT_PARTICLE_STYLE`. */
|
|
67
|
+
particleStyle?: ParticleStyle;
|
|
68
|
+
/** Pass-through to the underlying StreamNetworkFrame. */
|
|
69
|
+
frameProps?: Partial<Omit<StreamNetworkFrameProps, "nodes" | "edges" | "chartType" | "size" | "customNetworkLayout" | "layoutConfig">>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* ProcessSankey — temporal flow between nodes with an actual time x-axis.
|
|
73
|
+
*
|
|
74
|
+
* Built on top of `StreamNetworkFrame` via the `customNetworkLayout`
|
|
75
|
+
* escape hatch. Bands and ribbons emit as `bezier` scene-edges; the
|
|
76
|
+
* Frame handles canvas painting, hit testing, accessibility, theme
|
|
77
|
+
* cascade, and the push API.
|
|
78
|
+
*
|
|
79
|
+
* **Differs from SankeyDiagram in three ways:**
|
|
80
|
+
*
|
|
81
|
+
* 1. **Edges carry time.** Each edge has `startTime` / `endTime`.
|
|
82
|
+
* 2. **Nodes have lifetimes, not ranks.** A node's vertical lane spans
|
|
83
|
+
* `min(xExtent[0], earliestEdge)` to `max(xExtent[1], latestEdge)`.
|
|
84
|
+
* 3. **Static-graph cycles are valid** as long as edges move forward in time.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```tsx
|
|
88
|
+
* // Static fixture: pre-built nodes + timed edges, categorical colors.
|
|
89
|
+
* <ProcessSankey
|
|
90
|
+
* nodes={[
|
|
91
|
+
* { id: "Alice", category: "Person", xExtent: ["2026-01-06", "2026-01-06"] },
|
|
92
|
+
* { id: "Bob", category: "Person", xExtent: ["2026-02-01", "2026-02-01"] },
|
|
93
|
+
* { id: "Eng", category: "Team" },
|
|
94
|
+
* { id: "Release", category: "Milestone", xExtent: ["2026-04-15", "2026-05-30"] },
|
|
95
|
+
* ]}
|
|
96
|
+
* edges={[
|
|
97
|
+
* { id: "alice-eng", source: "Alice", target: "Eng", value: 8,
|
|
98
|
+
* startTime: "2026-01-20", endTime: "2026-02-10" },
|
|
99
|
+
* { id: "bob-eng", source: "Bob", target: "Eng", value: 5,
|
|
100
|
+
* startTime: "2026-02-15", endTime: "2026-03-15" },
|
|
101
|
+
* { id: "eng-rel", source: "Eng", target: "Release", value: 13,
|
|
102
|
+
* startTime: "2026-04-15", endTime: "2026-05-15" },
|
|
103
|
+
* ]}
|
|
104
|
+
* domain={["2026-01-01", "2026-05-31"]}
|
|
105
|
+
* colorBy="category"
|
|
106
|
+
* showLegend
|
|
107
|
+
* />
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```tsx
|
|
112
|
+
* // Push mode: omit `edges`, mutate via the ref. Same chart shape, but
|
|
113
|
+
* // edges arrive over time. Particles depict throughput.
|
|
114
|
+
* const ref = useRef<RealtimeFrameHandle>(null)
|
|
115
|
+
*
|
|
116
|
+
* useEffect(() => {
|
|
117
|
+
* const id = setInterval(() => {
|
|
118
|
+
* ref.current?.push({
|
|
119
|
+
* source: "API", target: "DB", value: Math.random() * 10,
|
|
120
|
+
* startTime: Date.now(), endTime: Date.now() + 1500,
|
|
121
|
+
* })
|
|
122
|
+
* }, 800)
|
|
123
|
+
* return () => clearInterval(id)
|
|
124
|
+
* }, [])
|
|
125
|
+
*
|
|
126
|
+
* return (
|
|
127
|
+
* <ProcessSankey
|
|
128
|
+
* ref={ref}
|
|
129
|
+
* domain={[t0, t0 + 60_000]}
|
|
130
|
+
* showParticles
|
|
131
|
+
* colorBy="category"
|
|
132
|
+
* showLegend
|
|
133
|
+
* />
|
|
134
|
+
* )
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export declare const ProcessSankey: {
|
|
138
|
+
<TNode extends Datum = Datum, TEdge extends Datum = Datum>(props: ProcessSankeyProps<TNode, TEdge> & React.RefAttributes<RealtimeFrameHandle>): React.ReactElement | null;
|
|
139
|
+
displayName?: string;
|
|
140
|
+
};
|
|
141
|
+
export default ProcessSankey;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export interface ProcessSankeyNode {
|
|
2
|
+
id: string;
|
|
3
|
+
/** Optional explicit lifetime bound [start, end]. Lifetime is
|
|
4
|
+
* `min(xExtent[0], earliestEdge)` to `max(xExtent[1], latestEdge)`. */
|
|
5
|
+
xExtent?: [number, number];
|
|
6
|
+
}
|
|
7
|
+
export interface ProcessSankeyEdge {
|
|
8
|
+
id: string;
|
|
9
|
+
source: string;
|
|
10
|
+
target: string;
|
|
11
|
+
value: number;
|
|
12
|
+
startTime: number;
|
|
13
|
+
endTime: number;
|
|
14
|
+
}
|
|
15
|
+
export interface ProcessSankeyIssue {
|
|
16
|
+
kind: string;
|
|
17
|
+
id?: string;
|
|
18
|
+
source?: string;
|
|
19
|
+
target?: string;
|
|
20
|
+
endpoint?: string;
|
|
21
|
+
nodeId?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ProcessSankeySample {
|
|
24
|
+
t: number;
|
|
25
|
+
topMass: number;
|
|
26
|
+
botMass: number;
|
|
27
|
+
}
|
|
28
|
+
export type AttachmentSide = "top" | "bot";
|
|
29
|
+
export type AttachmentKind = "in" | "out";
|
|
30
|
+
export interface ProcessSankeyAttachment {
|
|
31
|
+
side: AttachmentSide;
|
|
32
|
+
time: number;
|
|
33
|
+
sideMassBefore: number;
|
|
34
|
+
sideMassAfter: number;
|
|
35
|
+
kind: AttachmentKind;
|
|
36
|
+
value: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ProcessSankeyNodeData {
|
|
39
|
+
samples: ProcessSankeySample[];
|
|
40
|
+
peak: number;
|
|
41
|
+
topPeak: number;
|
|
42
|
+
botPeak: number;
|
|
43
|
+
localAttachments: Map<string, ProcessSankeyAttachment>;
|
|
44
|
+
}
|
|
45
|
+
export interface ProcessSankeySlotPeak {
|
|
46
|
+
topPeak: number;
|
|
47
|
+
botPeak: number;
|
|
48
|
+
}
|
|
49
|
+
export interface ProcessSankeySlotOccupant {
|
|
50
|
+
id: string;
|
|
51
|
+
end: number;
|
|
52
|
+
}
|
|
53
|
+
export interface ProcessSankeySlot {
|
|
54
|
+
peak: ProcessSankeySlotPeak;
|
|
55
|
+
occupants: ProcessSankeySlotOccupant[];
|
|
56
|
+
}
|
|
57
|
+
export interface ProcessSankeyLaneLifetime {
|
|
58
|
+
start: number | null;
|
|
59
|
+
end: number | null;
|
|
60
|
+
}
|
|
61
|
+
export interface ProcessSankeySideRecord {
|
|
62
|
+
sourceSide?: AttachmentSide;
|
|
63
|
+
targetSide?: AttachmentSide;
|
|
64
|
+
}
|
|
65
|
+
export interface ProcessSankeyLayout {
|
|
66
|
+
nodeData: Record<string, ProcessSankeyNodeData>;
|
|
67
|
+
sides: Map<string, ProcessSankeySideRecord>;
|
|
68
|
+
valueScale: number;
|
|
69
|
+
padding: number;
|
|
70
|
+
compressedPadding: boolean;
|
|
71
|
+
centerlines: Record<string, number>;
|
|
72
|
+
laneLifetime: Record<string, ProcessSankeyLaneLifetime>;
|
|
73
|
+
slots: ProcessSankeySlot[];
|
|
74
|
+
slotByNode: Record<string, number>;
|
|
75
|
+
crossingsBefore: number | null;
|
|
76
|
+
crossingsAfter: number | null;
|
|
77
|
+
lengthBefore: number | null;
|
|
78
|
+
lengthAfter: number | null;
|
|
79
|
+
}
|
|
80
|
+
export interface ProcessSankeyOptions {
|
|
81
|
+
plotH: number;
|
|
82
|
+
pairing?: "value" | "temporal";
|
|
83
|
+
packing?: "off" | "reuse";
|
|
84
|
+
laneOrder?: "insertion" | "crossing-min" | "inside-out" | "crossing-min+inside-out";
|
|
85
|
+
lifetimeMode?: "full" | "half";
|
|
86
|
+
}
|
|
87
|
+
export interface ProcessSankeyEdgeIndex {
|
|
88
|
+
incoming: Record<string, ProcessSankeyEdge[]>;
|
|
89
|
+
outgoing: Record<string, ProcessSankeyEdge[]>;
|
|
90
|
+
}
|
|
91
|
+
type Domain = [number, number] | null | undefined;
|
|
92
|
+
export declare function validateProcessSankey(nodes: ProcessSankeyNode[], edges: ProcessSankeyEdge[], domain: [number, number]): ProcessSankeyIssue[];
|
|
93
|
+
export declare function formatProcessSankeyIssue(issue: ProcessSankeyIssue): string;
|
|
94
|
+
export declare function buildEdgeIndex(nodes: ProcessSankeyNode[], edges: ProcessSankeyEdge[]): ProcessSankeyEdgeIndex;
|
|
95
|
+
export declare function assignSides(nodes: ProcessSankeyNode[], edges: ProcessSankeyEdge[], edgeIndex: ProcessSankeyEdgeIndex, pairing?: "value" | "temporal"): Map<string, ProcessSankeySideRecord>;
|
|
96
|
+
export declare function computeNode(node: ProcessSankeyNode, edgeIndex: ProcessSankeyEdgeIndex, sides: Map<string, ProcessSankeySideRecord>): ProcessSankeyNodeData;
|
|
97
|
+
export declare function clampTime(t: number, domain: Domain): number;
|
|
98
|
+
export declare function clampSamples(samples: ProcessSankeySample[], domain: Domain): ProcessSankeySample[];
|
|
99
|
+
export declare function attachmentYRange(att: ProcessSankeyAttachment, cl: number, S: number): [number, number];
|
|
100
|
+
export declare function buildBandPath(samples: ProcessSankeySample[], cl: number, S: number, xScale: (t: number) => number, domain: Domain): string | null;
|
|
101
|
+
type SlotByNode = Record<string, number>;
|
|
102
|
+
export declare function countCrossings(slotByNode: SlotByNode, edges: ProcessSankeyEdge[]): number;
|
|
103
|
+
export declare function totalEdgeLength(slotByNode: SlotByNode, edges: ProcessSankeyEdge[]): number;
|
|
104
|
+
interface LaneLayoutOptions {
|
|
105
|
+
plotH: number;
|
|
106
|
+
padding: number;
|
|
107
|
+
valueScale: number;
|
|
108
|
+
packing?: "off" | "reuse";
|
|
109
|
+
laneOrder?: "insertion" | "crossing-min" | "inside-out" | "crossing-min+inside-out";
|
|
110
|
+
lifetimeMode?: "full" | "half";
|
|
111
|
+
}
|
|
112
|
+
interface LaneLayoutResult {
|
|
113
|
+
effectiveSlotsHeight: number;
|
|
114
|
+
centerlines: Record<string, number>;
|
|
115
|
+
laneLifetime: Record<string, ProcessSankeyLaneLifetime>;
|
|
116
|
+
slots: ProcessSankeySlot[];
|
|
117
|
+
slotByNode: SlotByNode;
|
|
118
|
+
slotCenter: number[];
|
|
119
|
+
crossingsBefore: number | null;
|
|
120
|
+
crossingsAfter: number | null;
|
|
121
|
+
lengthBefore: number | null;
|
|
122
|
+
lengthAfter: number | null;
|
|
123
|
+
}
|
|
124
|
+
export declare function computeLaneLayout(nodes: ProcessSankeyNode[], edges: ProcessSankeyEdge[], nodeData: Record<string, ProcessSankeyNodeData>, edgeIndex: ProcessSankeyEdgeIndex, opts: LaneLayoutOptions): LaneLayoutResult;
|
|
125
|
+
/**
|
|
126
|
+
* Compute the full Process Sankey layout for a given dataset and
|
|
127
|
+
* configuration. Pure function, no side effects.
|
|
128
|
+
*
|
|
129
|
+
* The chart's time domain isn't a layout opt — domain handling lives
|
|
130
|
+
* in the geometry helpers (`buildBandPath`, `buildRibbonGeometry`,
|
|
131
|
+
* `clampSamples`) which receive an `xScale` and a domain pair from
|
|
132
|
+
* the caller. The layout itself is timeless apart from the per-node
|
|
133
|
+
* sample/event timestamps.
|
|
134
|
+
*/
|
|
135
|
+
export declare function computeProcessSankeyLayout(nodes: ProcessSankeyNode[], edges: ProcessSankeyEdge[], opts: ProcessSankeyOptions): ProcessSankeyLayout;
|
|
136
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { scaleTime } from "d3-scale";
|
|
2
|
+
import { type ProcessSankeyOptions, type ProcessSankeyLayout, type ProcessSankeyIssue } from "./algorithm";
|
|
3
|
+
import type { ProcessSankeyLayoutConfig } from "./streamingLayout";
|
|
4
|
+
import type { Datum } from "../../shared/datumTypes";
|
|
5
|
+
export interface ProcessSankeyNormalizedNode {
|
|
6
|
+
id: string;
|
|
7
|
+
xExtent?: [number, number];
|
|
8
|
+
__raw?: Datum;
|
|
9
|
+
}
|
|
10
|
+
export interface ProcessSankeyNormalizedEdge {
|
|
11
|
+
id: string;
|
|
12
|
+
source: string;
|
|
13
|
+
target: string;
|
|
14
|
+
value: number;
|
|
15
|
+
startTime: number;
|
|
16
|
+
endTime: number;
|
|
17
|
+
__raw?: Datum;
|
|
18
|
+
}
|
|
19
|
+
export interface BuildScenesInput {
|
|
20
|
+
nodes: ProcessSankeyNormalizedNode[];
|
|
21
|
+
edges: ProcessSankeyNormalizedEdge[];
|
|
22
|
+
domain: [number, number];
|
|
23
|
+
plotW: number;
|
|
24
|
+
plotH: number;
|
|
25
|
+
ribbonLane: "source" | "target" | "both";
|
|
26
|
+
edgeOpacity: number;
|
|
27
|
+
/** Resolves a node's color by id+index (lets the caller plug in
|
|
28
|
+
* the same theme/colorScheme/colorBy resolution the HOC uses). */
|
|
29
|
+
colorOf: (id: string, idx: number) => string;
|
|
30
|
+
layoutOpts: Pick<ProcessSankeyOptions, "pairing" | "packing" | "laneOrder" | "lifetimeMode">;
|
|
31
|
+
}
|
|
32
|
+
export interface BuildScenesResult {
|
|
33
|
+
layout: ProcessSankeyLayout | null;
|
|
34
|
+
layoutConfig: ProcessSankeyLayoutConfig;
|
|
35
|
+
issues: ProcessSankeyIssue[];
|
|
36
|
+
/** Used downstream for tooltips (mass-history) and overlays. */
|
|
37
|
+
xScale: ReturnType<typeof scaleTime>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run the full ProcessSankey layout pipeline. Returns the algorithm
|
|
41
|
+
* output, the bands/ribbons specs ready for `customNetworkLayout`, and
|
|
42
|
+
* the validation issues (caller decides whether to render an error
|
|
43
|
+
* gate or fall through). Pure: no DOM, no React, no rAF.
|
|
44
|
+
*/
|
|
45
|
+
export declare function buildProcessSankeyScenes(input: BuildScenesInput): BuildScenesResult;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the `RibbonGeometryInput` shape for a ProcessSankey ribbon
|
|
3
|
+
* from its source/target attachment data. Both the HOC (CSR) and the
|
|
4
|
+
* pure scene builder (SSR) call this so the coords feeding into the
|
|
5
|
+
* shared `buildRibbonGeometry` helper match between the two paths.
|
|
6
|
+
*
|
|
7
|
+
* Replaces `algorithm.js`'s `buildRibbonPath` — the path-D formula
|
|
8
|
+
* itself moved into `buildRibbonGeometry` so SankeyDiagram and
|
|
9
|
+
* ProcessSankey emit identical M-C-L-C-Z shapes.
|
|
10
|
+
*/
|
|
11
|
+
import type { RibbonGeometryInput } from "../../../geometry/ribbonGeometry";
|
|
12
|
+
type Side = "top" | "bot";
|
|
13
|
+
type Kind = "in" | "out";
|
|
14
|
+
interface AttachmentLike {
|
|
15
|
+
side: Side;
|
|
16
|
+
time: number;
|
|
17
|
+
sideMassBefore: number;
|
|
18
|
+
sideMassAfter: number;
|
|
19
|
+
kind: Kind;
|
|
20
|
+
value: number;
|
|
21
|
+
}
|
|
22
|
+
type RibbonLane = "source" | "target" | "both";
|
|
23
|
+
type XScale = (t: number) => number;
|
|
24
|
+
/**
|
|
25
|
+
* Build the geometry inputs for a single ProcessSankey ribbon. The
|
|
26
|
+
* source attachment is assumed to be `kind: "out"` (the value leaves
|
|
27
|
+
* the source on its outgoing side); the target attachment is
|
|
28
|
+
* `kind: "in"`. attachmentYRange's formula is inlined here to keep
|
|
29
|
+
* this module pure TS (the `algorithm.js` version is JS-only).
|
|
30
|
+
*/
|
|
31
|
+
export declare function computeProcessSankeyRibbonInputs(srcAtt: AttachmentLike, srcCenterline: number, tgtAtt: AttachmentLike, tgtCenterline: number, valueScale: number, xScale: XScale, lane: RibbonLane, domain: [number, number] | null): RibbonGeometryInput;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { NetworkCustomLayout } from "../../../stream/networkCustomLayout";
|
|
2
|
+
import type { BezierCache } from "../../../stream/networkTypes";
|
|
3
|
+
import type { Datum } from "../../shared/datumTypes";
|
|
4
|
+
export interface ProcessSankeyBandSpec {
|
|
5
|
+
id: string;
|
|
6
|
+
pathD: string;
|
|
7
|
+
fill: string;
|
|
8
|
+
stroke?: string;
|
|
9
|
+
strokeWidth?: number;
|
|
10
|
+
/** The user's raw node datum, surfaced as `data` in HoverData. */
|
|
11
|
+
rawDatum: Datum;
|
|
12
|
+
/** Pre-computed label x/y for the node band. */
|
|
13
|
+
labelX: number;
|
|
14
|
+
labelY: number;
|
|
15
|
+
labelText: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ProcessSankeyRibbonSpec {
|
|
18
|
+
id: string;
|
|
19
|
+
pathD: string;
|
|
20
|
+
fill: string;
|
|
21
|
+
opacity: number;
|
|
22
|
+
/** The user's raw edge datum, surfaced as `data` in HoverData. */
|
|
23
|
+
rawDatum: Datum;
|
|
24
|
+
/**
|
|
25
|
+
* Pre-computed cubic bezier control points + halfWidth for the
|
|
26
|
+
* shared particle pipeline. ProcessSankey writes these alongside
|
|
27
|
+
* the ribbon's path-D string so the frame's particle pool can
|
|
28
|
+
* spawn / step / render against them without re-deriving the
|
|
29
|
+
* ribbon geometry. Optional — when omitted the ribbon paints
|
|
30
|
+
* normally but no particles flow along it.
|
|
31
|
+
*/
|
|
32
|
+
bezier?: BezierCache;
|
|
33
|
+
}
|
|
34
|
+
export interface ProcessSankeyLayoutConfig {
|
|
35
|
+
bands: ProcessSankeyBandSpec[];
|
|
36
|
+
ribbons: ProcessSankeyRibbonSpec[];
|
|
37
|
+
/** Optional dim opacity for unselected bands/ribbons (linkedHover). */
|
|
38
|
+
showLabels?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Marker attached to scene-edge datums so the HOC's `tooltipContent`
|
|
42
|
+
* can route node bands vs. flow ribbons through different default
|
|
43
|
+
* bodies. `data` still carries the user's original node/edge datum.
|
|
44
|
+
*/
|
|
45
|
+
export interface SceneDatumPayload {
|
|
46
|
+
__kind: "band" | "ribbon";
|
|
47
|
+
/** Original node/edge record, as the user pushed it. */
|
|
48
|
+
data: Datum;
|
|
49
|
+
/** Stable id for hit-deduplication and ref operations. */
|
|
50
|
+
id: string;
|
|
51
|
+
}
|
|
52
|
+
export declare const emitProcessSankeyScenes: NetworkCustomLayout<ProcessSankeyLayoutConfig>;
|
|
53
|
+
/**
|
|
54
|
+
* Test whether an arbitrary HoverData/datum-shaped value carries the
|
|
55
|
+
* ProcessSankey scene marker. Lets the HOC's tooltipContent narrow to
|
|
56
|
+
* the band/ribbon variants without leaking the marker key everywhere.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isProcessSankeyScenePayload(d: unknown): d is SceneDatumPayload;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ProcessSankeyNodeData } from "./algorithm";
|
|
2
|
+
export interface MassHistoryRow {
|
|
3
|
+
t: number;
|
|
4
|
+
total: number;
|
|
5
|
+
}
|
|
6
|
+
export interface MassHistoryRowMarked extends MassHistoryRow {
|
|
7
|
+
/** "min" | "q25" | "median" | "q75" | "max" — present only when the
|
|
8
|
+
* full series was condensed via `pickMassQuantiles`. */
|
|
9
|
+
mark?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Distinct (time, total-mass) tuples drawn from a node's sample series.
|
|
13
|
+
* The same `(t, total)` pair never appears twice — the layout's
|
|
14
|
+
* same-time pre/post sample collapse is preserved here. Returns an
|
|
15
|
+
* empty array when `data` has no samples (or is undefined).
|
|
16
|
+
*/
|
|
17
|
+
export declare function massHistoryRows(data: ProcessSankeyNodeData | undefined): MassHistoryRow[];
|
|
18
|
+
/** Number of quantile picks emitted on truncation. Fixed at five —
|
|
19
|
+
* `min`, `q25`, `median`, `q75`, `max` — because the picks are
|
|
20
|
+
* semantic (named labels), not cap-driven. The `truncateAt` parameter
|
|
21
|
+
* on `pickMassQuantiles` controls *when* to truncate, not how many to
|
|
22
|
+
* return. */
|
|
23
|
+
export declare const QUANTILE_PICK_COUNT = 5;
|
|
24
|
+
/**
|
|
25
|
+
* Condense a row series down to the five mass-quantile picks —
|
|
26
|
+
* `min`, `q25`, `median`, `q75`, `max` — re-sorted by time so the
|
|
27
|
+
* tooltip table reads chronologically. Returns the input unchanged
|
|
28
|
+
* when its length is at or below `truncateAt` (default 5).
|
|
29
|
+
*
|
|
30
|
+
* Same-time collisions are deduplicated, so very small or very flat
|
|
31
|
+
* series may yield fewer than five output rows even when truncation
|
|
32
|
+
* fires; the marks attached are the first ones encountered for each
|
|
33
|
+
* surviving timestamp, which keeps `min` and `max` stable when ties
|
|
34
|
+
* are present.
|
|
35
|
+
*
|
|
36
|
+
* Note: `truncateAt` is the *trigger threshold*, not the output cap —
|
|
37
|
+
* once truncation fires, the output always emits the five quantile
|
|
38
|
+
* picks. To raise/lower the threshold without changing the picks,
|
|
39
|
+
* pass a different `truncateAt`; to vary the picks, fork this util.
|
|
40
|
+
*/
|
|
41
|
+
export declare function pickMassQuantiles(rows: MassHistoryRow[], truncateAt?: number): MassHistoryRowMarked[];
|
|
@@ -5,6 +5,7 @@ import type { LegendInteractionMode } from "../shared/hooks";
|
|
|
5
5
|
import type { BaseChartProps, ChartAccessor, CategoryFormatFn } from "../shared/types";
|
|
6
6
|
import { type TooltipProp } from "../../Tooltip/Tooltip";
|
|
7
7
|
import type { RealtimeFrameHandle } from "../../realtime/types";
|
|
8
|
+
import { type RegressionProp } from "../shared/regressionUtils";
|
|
8
9
|
/**
|
|
9
10
|
* BarChart component props
|
|
10
11
|
*/
|
|
@@ -90,6 +91,17 @@ export interface BarChartProps<TDatum extends Datum = Datum> extends BaseChartPr
|
|
|
90
91
|
legendPosition?: "right" | "left" | "top" | "bottom";
|
|
91
92
|
tooltip?: TooltipProp;
|
|
92
93
|
annotations?: Datum[];
|
|
94
|
+
/**
|
|
95
|
+
* Overlay a regression line through the bar tops. Accepts `true`
|
|
96
|
+
* (linear), a method name (`"linear"` | `"polynomial"` | `"loess"`),
|
|
97
|
+
* or a full `RegressionConfig`. The regression treats categories
|
|
98
|
+
* as a numeric category-index for fit input; pixel positions are
|
|
99
|
+
* resolved through the band scale, so the line passes through bar
|
|
100
|
+
* centers. Best for ordered categories (months, quarters, score
|
|
101
|
+
* buckets) where a slope reads as a meaningful trend. Sugar over
|
|
102
|
+
* the `trend` annotation.
|
|
103
|
+
*/
|
|
104
|
+
regression?: RegressionProp;
|
|
93
105
|
/** Custom formatter for category tick labels */
|
|
94
106
|
categoryFormat?: CategoryFormatFn;
|
|
95
107
|
/** Fixed value-axis domain `[min, max]`. Either bound may be `undefined` to leave that side data-derived. */
|
|
@@ -5,6 +5,7 @@ import type { LegendInteractionMode, LegendPosition } from "../shared/hooks";
|
|
|
5
5
|
import type { BaseChartProps, ChartAccessor, CategoryFormatFn } from "../shared/types";
|
|
6
6
|
import { type TooltipProp } from "../../Tooltip/Tooltip";
|
|
7
7
|
import type { RealtimeFrameHandle } from "../../realtime/types";
|
|
8
|
+
import { type RegressionProp } from "../shared/regressionUtils";
|
|
8
9
|
export interface DotPlotProps<TDatum extends Datum = Datum> extends BaseChartProps {
|
|
9
10
|
data?: TDatum[];
|
|
10
11
|
categoryAccessor?: ChartAccessor<TDatum, string>;
|
|
@@ -34,6 +35,14 @@ export interface DotPlotProps<TDatum extends Datum = Datum> extends BaseChartPro
|
|
|
34
35
|
legendPosition?: LegendPosition;
|
|
35
36
|
tooltip?: TooltipProp;
|
|
36
37
|
annotations?: Datum[];
|
|
38
|
+
/**
|
|
39
|
+
* Overlay a regression line through the dots. Same shape as
|
|
40
|
+
* Scatterplot's regression prop — accepts boolean, method-string,
|
|
41
|
+
* or full `RegressionConfig`. Pixel positions resolve through the
|
|
42
|
+
* band scale, so the line passes through dot centers. Sugar over
|
|
43
|
+
* the `trend` annotation.
|
|
44
|
+
*/
|
|
45
|
+
regression?: RegressionProp;
|
|
37
46
|
/** Custom formatter for category tick labels */
|
|
38
47
|
categoryFormat?: CategoryFormatFn;
|
|
39
48
|
/** Fixed value-axis domain `[min, max]`. Either bound may be `undefined` to leave that side data-derived. */
|