semiotic 3.7.3 → 3.7.5
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 +13 -7
- package/README.md +36 -20
- package/ai/schema.json +221 -1
- package/ai/system-prompt.md +2 -1
- package/dist/components/Annotation.d.ts +4 -0
- package/dist/components/DataSummaryContext.d.ts +1 -0
- package/dist/components/LinkedCharts.d.ts +2 -2
- package/dist/components/ai/chartCapabilityTypes.d.ts +16 -0
- package/dist/components/ai/dataPitfallsBridge.d.ts +101 -0
- package/dist/components/ai/dataQualityBridge.d.ts +201 -0
- package/dist/components/ai/describeChart.d.ts +2 -0
- package/dist/components/ai/generativeChart.d.ts +145 -0
- package/dist/components/charts/custom/NetworkCustomChart.d.ts +15 -2
- package/dist/components/charts/ordinal/SwarmPlot.d.ts +7 -0
- package/dist/components/charts/realtime/RealtimeLineChart.d.ts +21 -0
- package/dist/components/charts/realtime/aggregate.d.ts +51 -0
- package/dist/components/charts/realtime/eventTime.d.ts +26 -0
- package/dist/components/charts/shared/colorPalettes.d.ts +2 -0
- package/dist/components/charts/shared/colorUtils.d.ts +1 -12
- package/dist/components/charts/shared/minMax.d.ts +3 -0
- package/dist/components/charts/shared/radialGeometry.d.ts +0 -18
- package/dist/components/charts/shared/smartTooltip.d.ts +27 -0
- package/dist/components/charts/shared/statisticalOverlays.d.ts +35 -0
- package/dist/components/charts/shared/tooltipUtils.d.ts +2 -0
- package/dist/components/charts/shared/useChartSetup.d.ts +1 -1
- package/dist/components/charts/shared/useCustomChartSetup.d.ts +1 -1
- package/dist/components/charts/shared/validateChartData.d.ts +1 -1
- package/dist/components/charts/xy/Scatterplot.d.ts +9 -0
- package/dist/components/data/fromArrow.d.ts +54 -0
- package/dist/components/data/fromMermaid.d.ts +47 -0
- package/dist/components/data/fromObservablePlot.d.ts +69 -0
- package/dist/components/data/portability/index.d.ts +14 -0
- package/dist/components/data/portability/spec.d.ts +129 -0
- package/dist/components/data/portability/vegaLite.d.ts +62 -0
- package/dist/components/realtime/ReorderBuffer.d.ts +54 -0
- package/dist/components/realtime/RunningStats.d.ts +66 -0
- package/dist/components/realtime/WindowAccumulator.d.ts +105 -0
- package/dist/components/realtime/parseWindowDuration.d.ts +12 -0
- package/dist/components/recipes/customTooltip.d.ts +31 -0
- package/dist/components/recipes/gofish.d.ts +207 -0
- package/dist/components/recipes/gofishBoba.d.ts +23 -0
- package/dist/components/recipes/gofishIR.d.ts +169 -0
- package/dist/components/recipes/gofishIRExamples.d.ts +89 -0
- package/dist/components/recipes/gofishInterpreter.d.ts +52 -0
- package/dist/components/recipes/gofishLambdas.d.ts +145 -0
- package/dist/components/recipes/lineageDag.d.ts +129 -0
- package/dist/components/recipes/mermaidDag.d.ts +44 -0
- package/dist/components/recipes/packedClusterMatrix.d.ts +166 -0
- package/dist/components/recipes/recipeChrome.d.ts +100 -0
- package/dist/components/recipes/recipeLegend.d.ts +57 -0
- package/dist/components/recipes/recipeUtils.d.ts +105 -0
- package/dist/components/semiotic-ai.d.ts +6 -0
- package/dist/components/semiotic-data.d.ts +2 -0
- package/dist/components/semiotic-experimental.d.ts +20 -0
- package/dist/components/semiotic-network.d.ts +3 -1
- package/dist/components/semiotic-ordinal.d.ts +2 -0
- package/dist/components/semiotic-realtime.d.ts +9 -1
- package/dist/components/semiotic-recipes.d.ts +20 -1
- package/dist/components/semiotic-themes.d.ts +2 -0
- package/dist/components/semiotic-xy.d.ts +2 -0
- package/dist/components/semiotic.d.ts +6 -2
- package/dist/components/store/ObservationStore.d.ts +21 -2
- package/dist/components/store/SelectionStore.d.ts +1 -1
- package/dist/components/store/ThemeStore.d.ts +1 -1
- package/dist/components/store/TooltipStore.d.ts +1 -1
- package/dist/components/store/createStore.d.ts +1 -1
- package/dist/components/store/designTokens.d.ts +15 -0
- package/dist/components/store/useSelection.d.ts +22 -0
- package/dist/components/stream/NetworkHtmlMarksLayer.d.ts +44 -0
- package/dist/components/stream/NetworkPipelineStore.d.ts +32 -0
- package/dist/components/stream/NetworkSVGOverlay.d.ts +12 -0
- package/dist/components/stream/OrdinalPipelineStore.d.ts +18 -0
- package/dist/components/stream/PipelineStore.d.ts +27 -0
- package/dist/components/stream/SceneGraph.d.ts +5 -1
- package/dist/components/stream/customLayout.d.ts +20 -0
- package/dist/components/stream/customLayoutDiagnostics.d.ts +11 -0
- package/dist/components/stream/customLayoutSelection.d.ts +52 -0
- package/dist/components/stream/networkCustomLayout.d.ts +101 -1
- package/dist/components/stream/networkTypes.d.ts +38 -1
- package/dist/components/stream/ordinalCustomLayout.d.ts +17 -1
- package/dist/components/stream/ordinalSceneBuilders/types.d.ts +2 -0
- package/dist/components/stream/ordinalTypes.d.ts +19 -3
- package/dist/components/stream/renderers/networkSymbolRenderer.d.ts +2 -0
- package/dist/components/stream/renderers/symbolCanvasRenderer.d.ts +2 -0
- package/dist/components/stream/stalenessBands.d.ts +28 -0
- package/dist/components/stream/symbolPath.d.ts +24 -0
- package/dist/components/stream/types.d.ts +72 -3
- package/dist/components/stream/useStalenessCheck.d.ts +6 -1
- package/dist/components/stream/xySceneBuilders/pointScene.d.ts +2 -2
- package/dist/components/stream/xySceneBuilders/types.d.ts +5 -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-semiotic-ai-u954ylUn.js +2 -0
- package/dist/semiotic-ai-statisticalOverlays-CU7jW05Q.js +1 -0
- package/dist/semiotic-ai.d.ts +6 -0
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-data.d.ts +2 -0
- package/dist/semiotic-data.min.js +1 -1
- package/dist/semiotic-data.module.min.js +1 -1
- package/dist/semiotic-experimental.d.ts +20 -0
- package/dist/semiotic-experimental.min.js +1 -0
- package/dist/semiotic-experimental.module.min.js +1 -0
- package/dist/semiotic-network.d.ts +3 -1
- package/dist/semiotic-ordinal.d.ts +2 -0
- package/dist/semiotic-realtime.d.ts +9 -1
- package/dist/semiotic-recipes.d.ts +20 -1
- package/dist/semiotic-recipes.min.js +1 -1
- package/dist/semiotic-recipes.module.min.js +1 -1
- package/dist/semiotic-semiotic-BmrYbi99.js +2 -0
- package/dist/semiotic-statisticalOverlays-IjZw8Lsu.js +1 -0
- package/dist/semiotic-themes.d.ts +2 -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-value.min.js +1 -1
- package/dist/semiotic-value.module.min.js +1 -1
- package/dist/semiotic-xy.d.ts +2 -0
- package/dist/semiotic.d.ts +6 -2
- 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-semiotic-xy-Dufu3D0-.js +2 -0
- package/dist/xy-statisticalOverlays-3Ni9bRph.js +1 -0
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +11 -3
- package/dist/semiotic-ai-statisticalOverlays-C2PPlmXv.js +0 -1
- package/dist/semiotic-statisticalOverlays-C3DsOgr_.js +0 -1
- package/dist/xy-statisticalOverlays-C2PPlmXv.js +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { CustomLayout } from "../stream/customLayout";
|
|
2
|
+
import type { OrdinalCustomLayout } from "../stream/ordinalCustomLayout";
|
|
3
|
+
import type { GofishGlyphMark } from "./gofish";
|
|
4
|
+
import type { GofishLambda } from "./gofishLambdas";
|
|
5
|
+
import type { GofishRootIR } from "./gofishIR";
|
|
6
|
+
/**
|
|
7
|
+
* GoFish IR interpreter.
|
|
8
|
+
*
|
|
9
|
+
* Walks a `data → operators → mark` tree and *executes* the grammar —
|
|
10
|
+
* `group`/`spread`/`stack`/`scatter`/`treemap`/`layer`, the `polar`/`unit`
|
|
11
|
+
* coordinate transforms, mark channels through scales, and `connect`/`ref`/
|
|
12
|
+
* `arrow` relations — emitting positioned primitives. This is a real
|
|
13
|
+
* translator, not a recognizer: any spec built from these constructs renders.
|
|
14
|
+
*
|
|
15
|
+
* It is NOT GoFish's full constraint solver. GoFish elaborates `spread` to
|
|
16
|
+
* `layer + distribute + align` over a linear-system bbox; we implement the
|
|
17
|
+
* deterministic allocation/accumulation model the common acyclic specs reduce
|
|
18
|
+
* to. Constructs outside it (`table`, `cut`, `mask`, `over`/`inside`/`xor`,
|
|
19
|
+
* free-form `.constrain`) record a warning and fall back, never silently
|
|
20
|
+
* mis-render. The two sanctioned non-grammar paths — `derive` and `mark-fn`
|
|
21
|
+
* lambdas — resolve through the lambda registry.
|
|
22
|
+
*/
|
|
23
|
+
export interface InterpretOptions {
|
|
24
|
+
/** Per-call lambda overrides for `derive`/`mark-fn` (merged over the registry). */
|
|
25
|
+
lambdas?: Record<string, GofishLambda>;
|
|
26
|
+
/** Collected warnings for unsupported constructs / unresolved lambdas. */
|
|
27
|
+
warnings?: string[];
|
|
28
|
+
}
|
|
29
|
+
/** XY binding — the default for free-coordinate GoFish charts. */
|
|
30
|
+
export declare function interpretToXYLayout(root: GofishRootIR, options?: InterpretOptions): CustomLayout;
|
|
31
|
+
/**
|
|
32
|
+
* Ordinal binding — the top-level categorical `spread`/`group` maps to the
|
|
33
|
+
* frame's o-scale (one band per category); each category's subtree is
|
|
34
|
+
* interpreted within its full band column. A pictorial glyph that declares a
|
|
35
|
+
* `unit` coord with `fit: "uniform"` then scales aspect-correctly to fill the
|
|
36
|
+
* column (e.g. boba cups). Emits one data-bearing hit rect per category + the
|
|
37
|
+
* interpreted glyph as overlays.
|
|
38
|
+
*
|
|
39
|
+
* `config.glyphWidthRatio` (alias `cupWidthRatio`) insets the glyph column
|
|
40
|
+
* horizontally so neighboring glyphs breathe; default 0.9.
|
|
41
|
+
*/
|
|
42
|
+
export declare function interpretToOrdinalLayout(root: GofishRootIR, categoryAccessor: string, options?: InterpretOptions): OrdinalCustomLayout;
|
|
43
|
+
/** Interpret a root to raw marks (for tests / custom hosts). */
|
|
44
|
+
export declare function interpretToMarks(root: GofishRootIR, frame: {
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
width: number;
|
|
48
|
+
height: number;
|
|
49
|
+
}, resolveColor?: (key: string) => string, options?: InterpretOptions): {
|
|
50
|
+
marks: GofishGlyphMark[];
|
|
51
|
+
warnings: string[];
|
|
52
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
2
|
+
/**
|
|
3
|
+
* GoFish escape-hatch lambda registry.
|
|
4
|
+
*
|
|
5
|
+
* GoFish's serialized IR cannot carry function bodies, so `derive` (a
|
|
6
|
+
* `(rows) => rows'` data transform) and `mark-fn` (a `(datum) => drawing`
|
|
7
|
+
* custom glyph) travel as a `lambdaId` that the host resolves through a
|
|
8
|
+
* bridge. This module is that bridge for the Semiotic interpreter: register a
|
|
9
|
+
* function under the id the IR references and `interpretGofishIR` will call it
|
|
10
|
+
* where the grammar genuinely can't reach.
|
|
11
|
+
*
|
|
12
|
+
* This is the *only* sanctioned non-grammar path. A spec that resolves to pure
|
|
13
|
+
* operators + marks needs no lambdas; one that reaches a `derive`/`mark-fn`
|
|
14
|
+
* names the computation here.
|
|
15
|
+
*/
|
|
16
|
+
export interface DeriveLambda {
|
|
17
|
+
kind: "derive";
|
|
18
|
+
/** Transform the in-scope rows — add columns, or emit new rows. */
|
|
19
|
+
fn: (rows: Datum[]) => Datum[];
|
|
20
|
+
}
|
|
21
|
+
export interface MarkFnLambda {
|
|
22
|
+
kind: "mark-fn";
|
|
23
|
+
/**
|
|
24
|
+
* Draw a bespoke glyph for one datum inside its allocated unit frame
|
|
25
|
+
* (coordinates in [0,1], mapped to pixels by the interpreter). Returns
|
|
26
|
+
* primitive marks the interpreter splices into the scene.
|
|
27
|
+
*/
|
|
28
|
+
fn: (datum: Datum, frame: {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
w: number;
|
|
32
|
+
h: number;
|
|
33
|
+
}) => GofishLambdaPrimitive[];
|
|
34
|
+
}
|
|
35
|
+
export type GofishLambda = DeriveLambda | MarkFnLambda;
|
|
36
|
+
/** A primitive a `mark-fn` may emit (unit coords). Mirrors the glyph vocabulary. */
|
|
37
|
+
export type GofishLambdaPrimitive = {
|
|
38
|
+
kind: "polygon";
|
|
39
|
+
points: Array<[number, number]>;
|
|
40
|
+
fill?: string;
|
|
41
|
+
stroke?: string;
|
|
42
|
+
strokeWidth?: number;
|
|
43
|
+
opacity?: number;
|
|
44
|
+
} | {
|
|
45
|
+
kind: "circle";
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
r: number;
|
|
49
|
+
fill?: string;
|
|
50
|
+
stroke?: string;
|
|
51
|
+
opacity?: number;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "rect";
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
w: number;
|
|
57
|
+
h: number;
|
|
58
|
+
fill?: string;
|
|
59
|
+
stroke?: string;
|
|
60
|
+
opacity?: number;
|
|
61
|
+
rotate?: number;
|
|
62
|
+
} | {
|
|
63
|
+
kind: "text";
|
|
64
|
+
x: number;
|
|
65
|
+
y: number;
|
|
66
|
+
text: string;
|
|
67
|
+
fill?: string;
|
|
68
|
+
fontSize?: number;
|
|
69
|
+
};
|
|
70
|
+
/** Register a `derive`/`mark-fn` implementation under the id the IR references. */
|
|
71
|
+
export declare function registerGofishLambda(id: string, lambda: GofishLambda): () => void;
|
|
72
|
+
export declare function unregisterGofishLambda(id: string): void;
|
|
73
|
+
export declare function getGofishLambda(id: string): GofishLambda | undefined;
|
|
74
|
+
/** Merge a per-call lambda map over the module registry (per-call wins). */
|
|
75
|
+
export declare function resolveLambda(id: string, perCall?: Record<string, GofishLambda>): GofishLambda | undefined;
|
|
76
|
+
export interface BobaCellGeometry {
|
|
77
|
+
cup: Array<[number, number]>;
|
|
78
|
+
tea: Array<[number, number]> | null;
|
|
79
|
+
straw: Array<[number, number]> | null;
|
|
80
|
+
/** Thick rim/lid bar across the cup top. */
|
|
81
|
+
lid: {
|
|
82
|
+
x1: number;
|
|
83
|
+
x2: number;
|
|
84
|
+
y: number;
|
|
85
|
+
};
|
|
86
|
+
pearls: Array<{
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
r: number;
|
|
90
|
+
fill: string;
|
|
91
|
+
}>;
|
|
92
|
+
ice: Array<{
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
w: number;
|
|
96
|
+
rot: number;
|
|
97
|
+
fill: string;
|
|
98
|
+
}>;
|
|
99
|
+
/** Content box `[bw, bh]` for the `uniform` unit fit; shared across the menu. */
|
|
100
|
+
box: [number, number];
|
|
101
|
+
numBobas: number;
|
|
102
|
+
numIce: number;
|
|
103
|
+
teaVolume: number;
|
|
104
|
+
bobaVolume: number;
|
|
105
|
+
iceVolume: number;
|
|
106
|
+
totalVolume: number;
|
|
107
|
+
cupStroke: string;
|
|
108
|
+
}
|
|
109
|
+
/** Single-cup convenience (normalizes against itself). */
|
|
110
|
+
export declare function computeBobaCellGeometry(row: Datum): BobaCellGeometry;
|
|
111
|
+
/**
|
|
112
|
+
* The built-in `bobaGeometry` derive: solve every cup, then attach `_g`
|
|
113
|
+
* (geometry against the shared menu-wide normalization) plus the fixed fills
|
|
114
|
+
* the marks read.
|
|
115
|
+
*/
|
|
116
|
+
export declare const bobaGeometryLambda: DeriveLambda;
|
|
117
|
+
export interface BottleCellGeometry {
|
|
118
|
+
silhouette: Array<[number, number]>;
|
|
119
|
+
imageHref: string;
|
|
120
|
+
fill: {
|
|
121
|
+
x: number;
|
|
122
|
+
y: number;
|
|
123
|
+
w: number;
|
|
124
|
+
h: number;
|
|
125
|
+
};
|
|
126
|
+
fillLine: {
|
|
127
|
+
x1: number;
|
|
128
|
+
x2: number;
|
|
129
|
+
y: number;
|
|
130
|
+
};
|
|
131
|
+
pct: {
|
|
132
|
+
x: number;
|
|
133
|
+
y: number;
|
|
134
|
+
text: string;
|
|
135
|
+
};
|
|
136
|
+
label: {
|
|
137
|
+
x: number;
|
|
138
|
+
y: number;
|
|
139
|
+
text: string;
|
|
140
|
+
};
|
|
141
|
+
fillFill: string;
|
|
142
|
+
}
|
|
143
|
+
export declare function computeBottleCellGeometry(row: Datum): BottleCellGeometry;
|
|
144
|
+
/** The built-in `bottleGeometry` derive: attach `_b` (normalized geometry) per bottle. */
|
|
145
|
+
export declare const bottleGeometryLambda: DeriveLambda;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { NetworkCustomLayout } from "../stream/networkCustomLayout";
|
|
3
|
+
import type { Datum } from "../charts/shared/datumTypes";
|
|
4
|
+
/**
|
|
5
|
+
* Level of detail for a node glyph.
|
|
6
|
+
* - `full` container + icon + type label + truncated name + store-slot chips
|
|
7
|
+
* - `compact` container + icon + truncated name
|
|
8
|
+
* - `icon` container + icon only
|
|
9
|
+
* - `dot` a single ~5px circle (minimap density)
|
|
10
|
+
*/
|
|
11
|
+
export type LineageLod = "full" | "compact" | "icon" | "dot";
|
|
12
|
+
export interface LineageStoreSlot {
|
|
13
|
+
storeName: string;
|
|
14
|
+
slotIndex: number;
|
|
15
|
+
}
|
|
16
|
+
export interface LineageDagConfig {
|
|
17
|
+
/** Number of layers (x domain). Computed from node `x` extents when omitted. */
|
|
18
|
+
layerCount?: number;
|
|
19
|
+
/** Largest layer's row count (y domain). Computed from the data when omitted. */
|
|
20
|
+
maxLayerSize?: number;
|
|
21
|
+
/** Target full-glyph width / height in px. Shrunk to fit the plot. @default 172 / 54 */
|
|
22
|
+
nodeWidth?: number;
|
|
23
|
+
nodeHeight?: number;
|
|
24
|
+
/** Minimum gap reserved between glyphs when fitting. @default 26 / 18 */
|
|
25
|
+
minGapX?: number;
|
|
26
|
+
minGapY?: number;
|
|
27
|
+
/** Force a level of detail; `"auto"` derives it from the fitted glyph size. @default "auto" */
|
|
28
|
+
lod?: LineageLod | "auto";
|
|
29
|
+
/**
|
|
30
|
+
* Caller-supplied "reachable" set. When present, nodes/edges **outside**
|
|
31
|
+
* it dim to `dimOpacity`. This is the controlled-dimming channel: the host
|
|
32
|
+
* computes the set (e.g. downstream BFS of the hovered node) and re-renders.
|
|
33
|
+
* Independent of, and composes with, `NetworkLayoutContext.selection`.
|
|
34
|
+
*/
|
|
35
|
+
reachableIds?: Iterable<string> | null;
|
|
36
|
+
/** Currently-selected node id — drawn with the selection ring. Host-owned. */
|
|
37
|
+
selectedId?: string | null;
|
|
38
|
+
/** Opacity for dimmed (out-of-reach / unselected) marks. @default 0.14 */
|
|
39
|
+
dimOpacity?: number;
|
|
40
|
+
/** Logical layer index (0 = leftmost). @default "x" */
|
|
41
|
+
layerAccessor?: string;
|
|
42
|
+
/** Logical row offset within the layer (centered on 0). @default "y" */
|
|
43
|
+
rowAccessor?: string;
|
|
44
|
+
/** Node partition → fill family. @default "partition" */
|
|
45
|
+
partitionAccessor?: string;
|
|
46
|
+
/** Node semantic → icon. @default "semantic" */
|
|
47
|
+
semanticAccessor?: string;
|
|
48
|
+
/** Human label. @default "label" */
|
|
49
|
+
labelAccessor?: string;
|
|
50
|
+
/** Store list — `string[]` or `{storeName,slotIndex}[]`. @default "stores" */
|
|
51
|
+
storesAccessor?: string;
|
|
52
|
+
/** Edge "closes a cycle" flag. @default "isBackEdge" */
|
|
53
|
+
backEdgeAccessor?: string;
|
|
54
|
+
/** Edge type, drives edge color. @default "edgeType" */
|
|
55
|
+
edgeTypeAccessor?: string;
|
|
56
|
+
/** Fill per partition. Overridable; recipe ships dark-theme-friendly defaults. */
|
|
57
|
+
partitionColors?: Partial<Record<string, string>>;
|
|
58
|
+
/** Edge stroke per edgeType, plus `back` for back-edges. */
|
|
59
|
+
edgeColors?: Partial<Record<string, string>>;
|
|
60
|
+
/** Selection-ring stroke. @default var(--semiotic-focus, #ffcc33) */
|
|
61
|
+
accentColor?: string;
|
|
62
|
+
/** Container border stroke. @default var(--semiotic-border, #555) */
|
|
63
|
+
borderColor?: string;
|
|
64
|
+
/** Draw the store-slot chips in `full` LOD. @default true */
|
|
65
|
+
showStoreChips?: boolean;
|
|
66
|
+
/** Chip fill. @default var(--semiotic-info, #6a8caf) */
|
|
67
|
+
storeChipColor?: string;
|
|
68
|
+
/** Base edge opacity (non-dimmed). @default 0.5 */
|
|
69
|
+
edgeOpacity?: number;
|
|
70
|
+
/** Forward-edge stroke width in px. @default 1.25 */
|
|
71
|
+
edgeWidth?: number;
|
|
72
|
+
/** Back-edge stroke width in px. @default `edgeWidth`, else 1.5 */
|
|
73
|
+
backEdgeWidth?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Render the per-node icon. Receives the resolved semantic/partition, the
|
|
76
|
+
* pixel size to draw within, and a color hint. Return any SVG node. When
|
|
77
|
+
* omitted a labelled fallback chip is drawn. The demo passes a KStreams
|
|
78
|
+
* icon set here — keeping the recipe domain-agnostic.
|
|
79
|
+
*/
|
|
80
|
+
renderIcon?: (info: {
|
|
81
|
+
semantic: string;
|
|
82
|
+
partition: string;
|
|
83
|
+
size: number;
|
|
84
|
+
color: string;
|
|
85
|
+
node: Datum;
|
|
86
|
+
}) => ReactNode;
|
|
87
|
+
/** Small type label shown above the name in `full` LOD. @default the semantic. */
|
|
88
|
+
typeLabel?: (info: {
|
|
89
|
+
semantic: string;
|
|
90
|
+
partition: string;
|
|
91
|
+
node: Datum;
|
|
92
|
+
}) => string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* `lineageDagLayout` — a reusable layout recipe for **pre-positioned layered
|
|
96
|
+
* lineage / DAG graphs** with rich, composite node glyphs. Used here for the
|
|
97
|
+
* Kafka Streams topology viewer, but domain-agnostic: it reads logical
|
|
98
|
+
* `x` (layer) / `y` (row) coordinates the caller already computed (e.g. from a
|
|
99
|
+
* `dagLayoutFromGraph` pipeline) and maps them into the plot — it never runs a
|
|
100
|
+
* force sim or re-lays-out, so output is deterministic.
|
|
101
|
+
*
|
|
102
|
+
* **Composite glyphs as one hit-testable unit.** Each node emits exactly one
|
|
103
|
+
* `rect` (or `circle` in `dot` LOD) scene node — that single mark owns the
|
|
104
|
+
* canvas hit area and carries the node datum/id. All glyph chrome (semantic
|
|
105
|
+
* icon, type label, truncated name, per-store chips, selection ring) is drawn
|
|
106
|
+
* in the returned `overlays` layer, which is `pointer-events: none`, so it
|
|
107
|
+
* decorates without ever intercepting a hover. Hover/click therefore always
|
|
108
|
+
* resolve to the underlying node as a unit — see §5.2(a) of the spec.
|
|
109
|
+
*
|
|
110
|
+
* **Controlled dimming + selection, from outside.** `config.reachableIds`
|
|
111
|
+
* (host-computed set) dims everything outside it; `config.selectedId` draws
|
|
112
|
+
* the selection ring; both are owned by the host, never by the frame. The
|
|
113
|
+
* shared `NetworkLayoutContext.selection` predicate (from `LinkedCharts`)
|
|
114
|
+
* composes on top — a node dims if excluded by *either* cue.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```tsx
|
|
118
|
+
* import { NetworkCustomChart } from "semiotic/network"
|
|
119
|
+
* import { lineageDagLayout } from "semiotic/recipes"
|
|
120
|
+
*
|
|
121
|
+
* <NetworkCustomChart
|
|
122
|
+
* nodes={dagNodes} // each: { id, x: layer, y: row, partition, semantic, stores, label }
|
|
123
|
+
* edges={dagEdges} // each: { source, target, edgeType, isBackEdge }
|
|
124
|
+
* layout={lineageDagLayout}
|
|
125
|
+
* layoutConfig={{ layerCount, maxLayerSize, reachableIds, selectedId }}
|
|
126
|
+
* />
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare const lineageDagLayout: NetworkCustomLayout<LineageDagConfig>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { NetworkCustomLayout } from "../stream/networkCustomLayout";
|
|
2
|
+
/**
|
|
3
|
+
* Layered flowchart layout for the Mermaid adapter (and any pre-layered DAG).
|
|
4
|
+
*
|
|
5
|
+
* A Mermaid flowchart is a directed acyclic graph, not a force graph — so it
|
|
6
|
+
* should render as a *layered diagram* with shape-appropriate node glyphs,
|
|
7
|
+
* directional arrows, and edge labels, the way Mermaid draws it. This recipe
|
|
8
|
+
* does exactly that from the `layer`/`row` coordinates `fromMermaid` already
|
|
9
|
+
* computes (longest-path layering), so it needs **no layout engine and no new
|
|
10
|
+
* dependency**. It ships in `semiotic/recipes`, so it tree-shakes — you only
|
|
11
|
+
* pull it in if you use it.
|
|
12
|
+
*
|
|
13
|
+
* For large or dense graphs where crossing-minimization matters, run a real
|
|
14
|
+
* Sugiyama layouter (the BYO `dagre` recipe, or `d3-dag`) to assign
|
|
15
|
+
* `layer`/`row`, then render with this layout — the rendering and the
|
|
16
|
+
* positioning are deliberately separate concerns.
|
|
17
|
+
*
|
|
18
|
+
* Pure, SSR-safe: hit-testable rects are emitted as scene nodes; all visual
|
|
19
|
+
* chrome (shape glyphs, labels, edges, arrowheads, edge labels) is an SVG
|
|
20
|
+
* `overlays` group painted on top, in plot-relative coordinates.
|
|
21
|
+
*/
|
|
22
|
+
export type MermaidDirection = "TD" | "TB" | "BT" | "LR" | "RL";
|
|
23
|
+
export interface MermaidDagConfig {
|
|
24
|
+
/** Flow direction. TD/TB top-down, BT bottom-up, LR left-right, RL right-left. @default "TD" */
|
|
25
|
+
direction?: MermaidDirection;
|
|
26
|
+
/** Glyph width / height in px (shrunk to fit). @default 150 / 46 */
|
|
27
|
+
nodeWidth?: number;
|
|
28
|
+
nodeHeight?: number;
|
|
29
|
+
/** Node field accessors. @default "layer" / "row" / "label" / "shape" */
|
|
30
|
+
layerAccessor?: string;
|
|
31
|
+
rowAccessor?: string;
|
|
32
|
+
labelAccessor?: string;
|
|
33
|
+
shapeAccessor?: string;
|
|
34
|
+
/** Edge label field. @default "label" */
|
|
35
|
+
edgeLabelAccessor?: string;
|
|
36
|
+
/** Colors (CSS vars by default so they follow the theme). */
|
|
37
|
+
nodeFill?: string;
|
|
38
|
+
nodeStroke?: string;
|
|
39
|
+
textColor?: string;
|
|
40
|
+
edgeColor?: string;
|
|
41
|
+
/** Stroke for decision (diamond) glyphs. */
|
|
42
|
+
accentColor?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare const mermaidDagLayout: NetworkCustomLayout<MermaidDagConfig>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { NetworkCustomLayout } from "../stream/networkCustomLayout";
|
|
2
|
+
import type { NetworkSymbolName } from "../stream/symbolPath";
|
|
3
|
+
/**
|
|
4
|
+
* Config for {@link packedClusterMatrix}. Accessors read `node.data.<field>`
|
|
5
|
+
* (the ingest wrapper) and fall back to the node itself.
|
|
6
|
+
*/
|
|
7
|
+
export interface PackedClusterMatrixConfig {
|
|
8
|
+
/** Categorical field → matrix column. @default "column" */
|
|
9
|
+
columnAccessor?: string;
|
|
10
|
+
/** Categorical field → matrix row (stacked within a column). @default "row" */
|
|
11
|
+
rowAccessor?: string;
|
|
12
|
+
/** Numeric field → glyph size (area-encoded). Constant size when omitted. */
|
|
13
|
+
sizeAccessor?: string;
|
|
14
|
+
/** Categorical field → glyph hue (via `ctx.resolveColor`). */
|
|
15
|
+
colorAccessor?: string;
|
|
16
|
+
/** Fixed hue per category value. Wins over `ctx.resolveColor` for mapped keys —
|
|
17
|
+
* the right choice for editorial graphics with a semantic palette. */
|
|
18
|
+
colorMap?: Record<string, string>;
|
|
19
|
+
/** Categorical field → glyph shape. Auto-assigned shapes when no `symbolMap`. */
|
|
20
|
+
symbolAccessor?: string;
|
|
21
|
+
/** Numeric/date field → lightness shade of the hue (the fourth channel). */
|
|
22
|
+
shadeAccessor?: string;
|
|
23
|
+
/** Boolean field → small center dot on the glyph (e.g. a flagged subset). */
|
|
24
|
+
markerAccessor?: string;
|
|
25
|
+
/** Explicit column order; otherwise columns sort by count, largest first. */
|
|
26
|
+
columnOrder?: string[];
|
|
27
|
+
/** Explicit row order **bottom→top**; otherwise rows sort by count, largest at bottom. */
|
|
28
|
+
rowOrder?: string[];
|
|
29
|
+
/** Map a class value to a named glyph (the base mark BECOMES that shape).
|
|
30
|
+
* Unmapped values get auto-assigned. Mutually exclusive with `iconAccessor`. */
|
|
31
|
+
symbolMap?: Record<string, NetworkSymbolName>;
|
|
32
|
+
/** Shape when no `symbolAccessor` is set. @default "circle" */
|
|
33
|
+
defaultSymbol?: NetworkSymbolName;
|
|
34
|
+
/** Categorical field whose value selects an OPTIONAL stroked icon drawn inside
|
|
35
|
+
* the (filled circle) base mark — the "most marks are plain circles, a few
|
|
36
|
+
* carry an icon" model. Only values present in `iconMap` get an icon. */
|
|
37
|
+
iconAccessor?: string;
|
|
38
|
+
/** Map an icon-field value to a glyph. Values omitted here render as a plain
|
|
39
|
+
* circle (no icon) — so a single dominant class stays unmarked. */
|
|
40
|
+
iconMap?: Record<string, NetworkSymbolName>;
|
|
41
|
+
/** Stroke color of the inner icon. @default "rgba(255,255,255,0.92)" */
|
|
42
|
+
iconColor?: string;
|
|
43
|
+
/** Inner-icon stroke width. @default 1 */
|
|
44
|
+
iconStrokeWidth?: number;
|
|
45
|
+
/** Inner-icon size as a fraction of the base circle radius. @default 0.72 */
|
|
46
|
+
iconScale?: number;
|
|
47
|
+
/** Glyph radius range in px (area = πr²). @default [2, 8] */
|
|
48
|
+
sizeRange?: [number, number];
|
|
49
|
+
/** Size value domain. @default data extent */
|
|
50
|
+
sizeDomain?: [number, number];
|
|
51
|
+
/** Cap total glyph area at this fraction of the plot; radii scale down to fit
|
|
52
|
+
* (keeps clusters packable / non-overlapping on smaller canvases). @default 0.4 */
|
|
53
|
+
maxAreaFraction?: number;
|
|
54
|
+
/** How far the shade travels from the base hue (0..1). @default 0.72 */
|
|
55
|
+
shadeStrength?: number;
|
|
56
|
+
/** Shade value domain. @default data extent (dates auto-parsed) */
|
|
57
|
+
shadeDomain?: [number, number];
|
|
58
|
+
/** Flip the shade ramp (default: low → light, high → dark). */
|
|
59
|
+
shadeReverse?: boolean;
|
|
60
|
+
/** Row layout. `"banded"`: orbit rows are aligned global bands (one y-range
|
|
61
|
+
* spanning all columns → row labels align, one enclosure per band spans the
|
|
62
|
+
* columns, a column is only as tall as its highest occupied band). `"stacked"`:
|
|
63
|
+
* each column stacks its own rows independently (cell height ∝ that column's
|
|
64
|
+
* count; rows do NOT align). @default "banded" */
|
|
65
|
+
rowMode?: "banded" | "stacked";
|
|
66
|
+
/** `"proportional"` (mosaic: cell area ∝ count) or `"uniform"` grid. @default "proportional" */
|
|
67
|
+
cellSizing?: "proportional" | "uniform";
|
|
68
|
+
/** Exponent applied to counts when sizing columns/cells. `1` = strict area ∝
|
|
69
|
+
* count; `<1` softens the range so small columns stay legible. @default 1 */
|
|
70
|
+
proportionExponent?: number;
|
|
71
|
+
/** Gap between columns in px. @default 16 */
|
|
72
|
+
columnGap?: number;
|
|
73
|
+
/** Gap between stacked cells in px. @default 12 */
|
|
74
|
+
rowGap?: number;
|
|
75
|
+
/** Collision padding between glyphs in px. @default 1 */
|
|
76
|
+
packPadding?: number;
|
|
77
|
+
/** Relaxation passes for the packing (capped at 14; a near-uniform seed needs
|
|
78
|
+
* few). Higher = tidier/slower. @default 12 */
|
|
79
|
+
iterations?: number;
|
|
80
|
+
/** Draw a rounded enclosure hugging each cluster. @default true */
|
|
81
|
+
showEnclosures?: boolean;
|
|
82
|
+
enclosureColor?: string;
|
|
83
|
+
enclosureRadius?: number;
|
|
84
|
+
enclosureOpacity?: number;
|
|
85
|
+
enclosureWidth?: number;
|
|
86
|
+
/** Column header labels across the top. @default true */
|
|
87
|
+
showColumnHeaders?: boolean;
|
|
88
|
+
/** Row labels down the left. @default true */
|
|
89
|
+
showRowLabels?: boolean;
|
|
90
|
+
columnLabel?: (col: string) => string;
|
|
91
|
+
rowLabel?: (row: string) => string;
|
|
92
|
+
headerColor?: string;
|
|
93
|
+
labelColor?: string;
|
|
94
|
+
headerFontSize?: number;
|
|
95
|
+
labelFontSize?: number;
|
|
96
|
+
/** Top space reserved for headers. @default 26 */
|
|
97
|
+
headerHeight?: number;
|
|
98
|
+
/** Left space reserved for row labels. @default 66 */
|
|
99
|
+
labelWidth?: number;
|
|
100
|
+
/** Bottom margin reserved for callout labels (only when `callouts` is set). @default 30 */
|
|
101
|
+
footerHeight?: number;
|
|
102
|
+
markStroke?: string;
|
|
103
|
+
markStrokeWidth?: number;
|
|
104
|
+
/** Center-dot color for `markerAccessor` hits. @default "#ffffff" */
|
|
105
|
+
markerColor?: string;
|
|
106
|
+
/** Dim every glyph that doesn't match the highlight. A single `{field,value}`
|
|
107
|
+
* or an array (AND — a glyph must match all to stay lit, e.g. a region×orbit
|
|
108
|
+
* cell). Drives legend / nav-tree highlighting. */
|
|
109
|
+
highlight?: {
|
|
110
|
+
field: string;
|
|
111
|
+
value: string;
|
|
112
|
+
} | {
|
|
113
|
+
field: string;
|
|
114
|
+
value: string;
|
|
115
|
+
}[] | null;
|
|
116
|
+
/** Opacity for dimmed glyphs. @default 0.16 */
|
|
117
|
+
dimOpacity?: number;
|
|
118
|
+
/** Editorial leader-line callouts to specific marks. Each picks the first mark
|
|
119
|
+
* whose `datum[field] === value` and draws a ring + connector + label. `at`
|
|
120
|
+
* places the label: a y in [0,1] of the plot ("1" = bottom) and the label
|
|
121
|
+
* tracks the mark's x, or an explicit `{x,y}` in plot px. */
|
|
122
|
+
callouts?: Array<{
|
|
123
|
+
field: string;
|
|
124
|
+
value: string;
|
|
125
|
+
label: string;
|
|
126
|
+
at?: number | {
|
|
127
|
+
x: number;
|
|
128
|
+
y: number;
|
|
129
|
+
};
|
|
130
|
+
connector?: "straight" | "elbow" | "curve";
|
|
131
|
+
}>;
|
|
132
|
+
calloutColor?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* `packedClusterMatrix` — a reusable network layout that arranges a flat set of
|
|
136
|
+
* records into a **matrix of densely-packed clusters**: one column per value of
|
|
137
|
+
* `columnAccessor`, cells stacked within a column per value of `rowAccessor`,
|
|
138
|
+
* each cell a beeswarm of variable-radius glyphs. In `"proportional"` sizing the
|
|
139
|
+
* column widths and cell heights track counts (a mosaic), so a cell's area is
|
|
140
|
+
* proportional to its record count and packing density stays roughly uniform.
|
|
141
|
+
*
|
|
142
|
+
* Each record renders as a **four-channel glyph**: shape (`symbolAccessor`),
|
|
143
|
+
* hue (`colorAccessor`), size (`sizeAccessor`, area-encoded), and lightness
|
|
144
|
+
* shade (`shadeAccessor`). Packing is deterministic (seeded `d3-force`) and the
|
|
145
|
+
* geometry is cached, so hover/selection/filter re-runs re-style without
|
|
146
|
+
* re-packing. Built to recreate small-multiples beeswarm graphics (e.g. Nadieh
|
|
147
|
+
* Bremer's "Satellites in Space").
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```tsx
|
|
151
|
+
* import { NetworkCustomChart } from "semiotic/network"
|
|
152
|
+
* import { packedClusterMatrix } from "semiotic/recipes"
|
|
153
|
+
*
|
|
154
|
+
* <NetworkCustomChart
|
|
155
|
+
* nodes={satellites} // each: { id, region, orbit, mass, category, klass, launch }
|
|
156
|
+
* layout={packedClusterMatrix}
|
|
157
|
+
* colorScheme={categoryColors}
|
|
158
|
+
* layoutConfig={{
|
|
159
|
+
* columnAccessor: "region", rowAccessor: "orbit",
|
|
160
|
+
* sizeAccessor: "mass", colorAccessor: "category",
|
|
161
|
+
* symbolAccessor: "klass", shadeAccessor: "launch",
|
|
162
|
+
* }}
|
|
163
|
+
* />
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export declare const packedClusterMatrix: NetworkCustomLayout<PackedClusterMatrixConfig>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Recipe chrome kit — small, framework-level building blocks for the decoration
|
|
4
|
+
* that custom-layout recipes draw in their `overlays` layer: group enclosures,
|
|
5
|
+
* band/axis labels, and leader-line callouts to a mark.
|
|
6
|
+
*
|
|
7
|
+
* These were each hand-rolled per recipe (packedClusterMatrix drew enclosures,
|
|
8
|
+
* marimekko/bullet/parallelCoordinates placed band labels, the satellites
|
|
9
|
+
* graphic needed callouts to specific marks). Centralizing them keeps chrome
|
|
10
|
+
* consistent and lets new recipes opt in instead of re-deriving the geometry.
|
|
11
|
+
*
|
|
12
|
+
* All return plain SVG React elements with `pointerEvents: "none"`, so they
|
|
13
|
+
* decorate without intercepting canvas hit-testing. Pure / SSR-safe.
|
|
14
|
+
*/
|
|
15
|
+
export interface RoundedEnclosureProps {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
/** Corner radius. @default 10 */
|
|
21
|
+
radius?: number;
|
|
22
|
+
stroke?: string;
|
|
23
|
+
/** @default 1.5 */
|
|
24
|
+
strokeWidth?: number;
|
|
25
|
+
/** @default 0.6 */
|
|
26
|
+
opacity?: number;
|
|
27
|
+
/** @default "none" */
|
|
28
|
+
fill?: string;
|
|
29
|
+
strokeDasharray?: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
keyId?: string | number;
|
|
32
|
+
}
|
|
33
|
+
/** A rounded rectangle around a group of marks (a cell, a row/column band, a cluster). */
|
|
34
|
+
export declare function roundedEnclosure(p: RoundedEnclosureProps): ReactElement;
|
|
35
|
+
/** Bounding box of a set of points (each optionally a circle of radius `r`), padded.
|
|
36
|
+
* The usual precursor to {@link roundedEnclosure}. Returns null for an empty set. */
|
|
37
|
+
export declare function boundsOf(points: ReadonlyArray<{
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
r?: number;
|
|
41
|
+
}>, pad?: number): {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
} | null;
|
|
47
|
+
export interface BandLabelProps {
|
|
48
|
+
text: string;
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
/** @default "middle" */
|
|
52
|
+
anchor?: "start" | "middle" | "end";
|
|
53
|
+
/** @default "middle" */
|
|
54
|
+
baseline?: "middle" | "hanging" | "auto";
|
|
55
|
+
/** Hide the label if its estimated width exceeds this (px). */
|
|
56
|
+
maxWidth?: number;
|
|
57
|
+
/** @default 12 */
|
|
58
|
+
fontSize?: number;
|
|
59
|
+
fontWeight?: number | string;
|
|
60
|
+
color?: string;
|
|
61
|
+
className?: string;
|
|
62
|
+
keyId?: string | number;
|
|
63
|
+
}
|
|
64
|
+
/** A label placed at a band/axis position, suppressed when it would overflow
|
|
65
|
+
* `maxWidth` (the dedup pattern marimekko/parallelCoordinates hand-roll). */
|
|
66
|
+
export declare function bandLabel(p: BandLabelProps): ReactElement | null;
|
|
67
|
+
export type CalloutConnector = "straight" | "elbow" | "curve";
|
|
68
|
+
export interface MarkCalloutProps {
|
|
69
|
+
/** The anchored mark (a position a custom layout emitted). */
|
|
70
|
+
markX: number;
|
|
71
|
+
markY: number;
|
|
72
|
+
/** Where the label text sits. */
|
|
73
|
+
labelX: number;
|
|
74
|
+
labelY: number;
|
|
75
|
+
label: ReactNode;
|
|
76
|
+
/** @default "straight" */
|
|
77
|
+
connector?: CalloutConnector;
|
|
78
|
+
/** Draw a ring of this radius around the mark (editorial highlight). */
|
|
79
|
+
markRadius?: number;
|
|
80
|
+
stroke?: string;
|
|
81
|
+
/** @default 1 */
|
|
82
|
+
strokeWidth?: number;
|
|
83
|
+
color?: string;
|
|
84
|
+
/** @default 11 */
|
|
85
|
+
fontSize?: number;
|
|
86
|
+
fontWeight?: number | string;
|
|
87
|
+
/** text-anchor for the label. @default "middle" */
|
|
88
|
+
labelAnchor?: "start" | "middle" | "end";
|
|
89
|
+
/** @default "hanging" */
|
|
90
|
+
labelBaseline?: "middle" | "hanging" | "auto";
|
|
91
|
+
className?: string;
|
|
92
|
+
keyId?: string | number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A leader line connecting a label to a mark, with an optional ring around the
|
|
96
|
+
* mark — the editorial-callout pattern. Custom-layout recipes use it because
|
|
97
|
+
* the annotation system can't anchor to a mark a layout emits at runtime; the
|
|
98
|
+
* recipe knows the packed position and can call this directly.
|
|
99
|
+
*/
|
|
100
|
+
export declare function markCallout(p: MarkCalloutProps): ReactElement;
|