@jmbarzee/force-graph 0.0.1
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/LICENSE +21 -0
- package/README.md +424 -0
- package/dist-lib/components/FilterBar.d.ts +90 -0
- package/dist-lib/components/GraphView.d.ts +213 -0
- package/dist-lib/components/GroupLegend.d.ts +25 -0
- package/dist-lib/components/graph-view/focus.d.ts +16 -0
- package/dist-lib/components/graph-view/useFocusRequest.d.ts +9 -0
- package/dist-lib/components/graph-view/useLinkedViews.d.ts +85 -0
- package/dist-lib/components/graph-view/useRecentlyChanged.d.ts +5 -0
- package/dist-lib/components/graph-view/useTaxonomy.d.ts +11 -0
- package/dist-lib/components/graph-view/useTheme.d.ts +26 -0
- package/dist-lib/filter/linked.d.ts +26 -0
- package/dist-lib/filter/reconcile.d.ts +38 -0
- package/dist-lib/filter/toggle.d.ts +12 -0
- package/dist-lib/filter/types.d.ts +162 -0
- package/dist-lib/graph/axis.d.ts +290 -0
- package/dist-lib/graph/groups.d.ts +31 -0
- package/dist-lib/graph/layout.d.ts +104 -0
- package/dist-lib/graph/model.d.ts +149 -0
- package/dist-lib/graph/scalar.d.ts +88 -0
- package/dist-lib/graph/scheme.d.ts +68 -0
- package/dist-lib/graph/shapes.d.ts +227 -0
- package/dist-lib/graph/taxonomy.d.ts +207 -0
- package/dist-lib/graph/validate.d.ts +47 -0
- package/dist-lib/index.d.ts +35 -0
- package/dist-lib/index.js +4895 -0
- package/dist-lib/index.js.map +1 -0
- package/dist-lib/styles.css +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { AxisValue } from './axis';
|
|
2
|
+
import { Taxonomy } from './taxonomy';
|
|
3
|
+
/** The two themes every colour is declared in. */
|
|
4
|
+
export type Theme = 'light' | 'dark';
|
|
5
|
+
/** Both themes, in order. */
|
|
6
|
+
export declare const THEMES: readonly Theme[];
|
|
7
|
+
/** A fill and a border. */
|
|
8
|
+
export interface ColorPair {
|
|
9
|
+
/** Canvas fill colour. */
|
|
10
|
+
readonly fill: string;
|
|
11
|
+
/** Canvas border colour, a few stops darker than the fill. */
|
|
12
|
+
readonly border: string;
|
|
13
|
+
}
|
|
14
|
+
/** A value's colour in both themes — declared together, so no half can go missing. */
|
|
15
|
+
export interface ThemedColor {
|
|
16
|
+
readonly light: ColorPair;
|
|
17
|
+
readonly dark: ColorPair;
|
|
18
|
+
}
|
|
19
|
+
/** How an edge type is stroked: its colour per theme, base alpha, dash pattern and width. */
|
|
20
|
+
export interface EdgeStroke {
|
|
21
|
+
readonly color: {
|
|
22
|
+
readonly light: string;
|
|
23
|
+
readonly dark: string;
|
|
24
|
+
};
|
|
25
|
+
readonly alpha: number;
|
|
26
|
+
readonly dash: readonly number[];
|
|
27
|
+
readonly width: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The stem of a value's custom-property name: the value id in kebab case
|
|
31
|
+
* (`twoWords` → `two-words`). Derived, never stored.
|
|
32
|
+
*/
|
|
33
|
+
export declare function cssSuffix(value: AxisValue): string;
|
|
34
|
+
/**
|
|
35
|
+
* The inline custom properties a pane carries for one theme: every style
|
|
36
|
+
* value's fill and border. Set on the pane's root, they are what tokens, chip
|
|
37
|
+
* tints and typed rows read, and they follow the resolved theme by being
|
|
38
|
+
* recomputed, not overridden.
|
|
39
|
+
*/
|
|
40
|
+
export declare function schemeVars(taxonomy: Taxonomy, theme: Theme): Record<string, string>;
|
|
41
|
+
/**
|
|
42
|
+
* The red, green and blue of a scheme colour, or undefined. A scheme colour
|
|
43
|
+
* is hex of either length, `rgb()`/`rgba()` or `hsl()`/`hsla()` — a form
|
|
44
|
+
* every reader can parse without a browser, so the taxonomy can refuse
|
|
45
|
+
* anything else at construction (`isSchemeColor`) and no reader meets a
|
|
46
|
+
* colour it cannot read.
|
|
47
|
+
*/
|
|
48
|
+
export declare function rgbOf(color: string): readonly [number, number, number] | undefined;
|
|
49
|
+
/** Whether a colour is one every reader parses: hex, `rgb()` or `hsl()`. */
|
|
50
|
+
export declare const isSchemeColor: (color: string) => boolean;
|
|
51
|
+
/**
|
|
52
|
+
* A colour at an alpha, as `rgba()`, for a canvas gradient or fill. A colour
|
|
53
|
+
* outside the scheme's forms becomes a neutral grey, said once per colour on
|
|
54
|
+
* the console — never a throw, because this runs inside the draw loop.
|
|
55
|
+
* Unreachable for a taxonomy's colours, which are refused at
|
|
56
|
+
* construction; it guards the library's own group palette and any caller
|
|
57
|
+
* that bypasses the taxonomy.
|
|
58
|
+
*/
|
|
59
|
+
export declare function withAlpha(color: string, alpha: number): string;
|
|
60
|
+
/**
|
|
61
|
+
* A stylesheet for a host's own CSS: every style value's fill and border on
|
|
62
|
+
* `:root`, and the dark values that differ under `darkSelector` — by default
|
|
63
|
+
* `[data-theme="dark"]`, the attribute the pane carries on its own root; a
|
|
64
|
+
* host that marks its theme another way names its own selector. The pane
|
|
65
|
+
* does not read this — it carries `schemeVars` inline — so a host that
|
|
66
|
+
* styles nothing of its own by node value never needs it.
|
|
67
|
+
*/
|
|
68
|
+
export declare function schemeStylesheet(taxonomy: Taxonomy, darkSelector?: string): string;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { AxisId, AxisValue } from './axis';
|
|
2
|
+
import { EdgeStroke, ThemedColor } from './scheme';
|
|
3
|
+
/** A rest band on one layout axis: the range inside which a value feels no gravity. */
|
|
4
|
+
export interface Band {
|
|
5
|
+
min: number;
|
|
6
|
+
max: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* How one value on the style axis is drawn, sized, and physically weighted,
|
|
10
|
+
* as a host declares it. Only the id, the label and the colour are required;
|
|
11
|
+
* the rest is derived from them and from the value's position in the
|
|
12
|
+
* declaration order (top of the hierarchy first):
|
|
13
|
+
*
|
|
14
|
+
* - `abbreviation`: the first two characters of the label.
|
|
15
|
+
* - `icon`: none.
|
|
16
|
+
* - `size.r`: 12; `size.iconSize`: nine tenths of the radius, rounded, at least 9.
|
|
17
|
+
* - `physics.charge`: −40 × r; `physics.coreRadius`: 4 × r.
|
|
18
|
+
* - `physics.band.y`: the value's slice of the stack, by position — the
|
|
19
|
+
* first value's band at the top of the canvas, the last at the bottom,
|
|
20
|
+
* neighbours overlapping a fifth; `physics.band.x`: 0 to 380.
|
|
21
|
+
* - `whenHidden`: `ascend`; `summaryKind`: `degree`.
|
|
22
|
+
*
|
|
23
|
+
* A field given overrides its default, field by field — a band's `x` may be
|
|
24
|
+
* declared and its `y` left to the stack.
|
|
25
|
+
*/
|
|
26
|
+
export interface NodeStyle {
|
|
27
|
+
/** The value on the style axis this style is for. */
|
|
28
|
+
id: AxisValue;
|
|
29
|
+
/** Display name, e.g. "Service". */
|
|
30
|
+
label: string;
|
|
31
|
+
/**
|
|
32
|
+
* One or two characters for a control token: a control surface renders a
|
|
33
|
+
* token per value and has no room for a name.
|
|
34
|
+
*/
|
|
35
|
+
abbreviation?: string;
|
|
36
|
+
/** Single glyph drawn inside the canvas node. */
|
|
37
|
+
icon?: string;
|
|
38
|
+
/** Fill and border in both themes; the canvas reads `color[theme]`. */
|
|
39
|
+
color: ThemedColor;
|
|
40
|
+
size?: {
|
|
41
|
+
/** Circle radius in world units. Hit-test radius = r + 4. */
|
|
42
|
+
r?: number;
|
|
43
|
+
/** Font size for the icon glyph (px). */
|
|
44
|
+
iconSize?: number;
|
|
45
|
+
};
|
|
46
|
+
physics?: {
|
|
47
|
+
/**
|
|
48
|
+
* Repulsion charge. Negative = repulsion. The starting point for the
|
|
49
|
+
* value the user tunes at runtime via the control panel.
|
|
50
|
+
*/
|
|
51
|
+
charge?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Core radius (charge softening, as a length). A pair of nodes softens
|
|
54
|
+
* its charge by the squared average of the two endpoints' effective core
|
|
55
|
+
* radii (`coreRadiusMultiplier × coreRadius`), added to d². Larger =
|
|
56
|
+
* gentler, wider plateau.
|
|
57
|
+
*/
|
|
58
|
+
coreRadius?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Rest bands, one per layout axis, inside which this value feels no
|
|
61
|
+
* gravity. `y` is the hierarchy (negative = top of canvas); `x` bounds
|
|
62
|
+
* the horizontal spread. The simulation seeds nodes inside their bands on
|
|
63
|
+
* creation, so the structure is visible before the first tick — which
|
|
64
|
+
* also makes this the seeding function, not only the gravity target.
|
|
65
|
+
*/
|
|
66
|
+
band?: {
|
|
67
|
+
x?: Band;
|
|
68
|
+
y?: Band;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* What a dependency edge touching a HIDDEN node of this value does:
|
|
73
|
+
* `ascend` re-points the endpoint to the node's nearest visible ancestor;
|
|
74
|
+
* `splice` follows the node's own dependency edges through to the far
|
|
75
|
+
* side, so caller → hidden → callee draws as caller → callee.
|
|
76
|
+
*/
|
|
77
|
+
whenHidden?: 'ascend' | 'splice';
|
|
78
|
+
/**
|
|
79
|
+
* The glanceable summary for a node of this value: the children it contains,
|
|
80
|
+
* counted per style value and named by that value's abbreviation
|
|
81
|
+
* (`2 Sv · 1 Pd`); its dependency degree (`→3 ←2`); or nothing.
|
|
82
|
+
*/
|
|
83
|
+
summaryKind?: 'children' | 'degree' | 'none';
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A node style with every default filled in — what `Taxonomy.styleOf` answers.
|
|
87
|
+
*
|
|
88
|
+
* Reached through `Taxonomy.nodeStyleOf`, never by key lookup from the
|
|
89
|
+
* engine — a miss has to resolve to the fallback rather than throw, because
|
|
90
|
+
* the resolution happens per node per frame inside the draw loop where an
|
|
91
|
+
* exception stops the canvas repainting for good.
|
|
92
|
+
*/
|
|
93
|
+
export interface ResolvedNodeStyle {
|
|
94
|
+
id: AxisValue;
|
|
95
|
+
label: string;
|
|
96
|
+
abbreviation: string;
|
|
97
|
+
/** Empty when the style declares none: nothing is drawn. */
|
|
98
|
+
icon: string;
|
|
99
|
+
color: ThemedColor;
|
|
100
|
+
size: {
|
|
101
|
+
r: number;
|
|
102
|
+
iconSize: number;
|
|
103
|
+
};
|
|
104
|
+
physics: {
|
|
105
|
+
charge: number;
|
|
106
|
+
coreRadius: number;
|
|
107
|
+
band: {
|
|
108
|
+
x: Band;
|
|
109
|
+
y: Band;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
whenHidden: 'ascend' | 'splice';
|
|
113
|
+
summaryKind: 'children' | 'degree' | 'none';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Stable id for one edge type.
|
|
117
|
+
*
|
|
118
|
+
* A string, not a union, and that is the library's whole position on edge
|
|
119
|
+
* vocabulary: it is the override key in the spring tuning and the hover-link
|
|
120
|
+
* key across the spring map, curves, and canvas, so it has to be something a
|
|
121
|
+
* host can extend. A host narrows it to its own union.
|
|
122
|
+
*/
|
|
123
|
+
export type EdgeTypeId = string;
|
|
124
|
+
/** One spring: stiffness (k) and rest length. */
|
|
125
|
+
export interface SpringPhysics {
|
|
126
|
+
strength: number;
|
|
127
|
+
distance: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* One kind of edge, as a host declares it: which values it runs between and
|
|
131
|
+
* which relation it expresses, optionally which values the edge itself must
|
|
132
|
+
* carry (`match`), and — optionally — how it is stroked, its spring and its
|
|
133
|
+
* hover text. An edge is classified as the declared type of its relation
|
|
134
|
+
* that runs between its endpoints' values, in either orientation, and whose
|
|
135
|
+
* `match` (if any) its own values satisfy; a satisfied `match` beats a type
|
|
136
|
+
* without one, the declared orientation beats the reverse, and declaration
|
|
137
|
+
* order settles the rest — unless the taxonomy's `classifyEdge` says
|
|
138
|
+
* otherwise. A label left out is the id; a stroke left out is the neutral
|
|
139
|
+
* stroke (the containment stroke for a containment type), field by field; a
|
|
140
|
+
* spring left out is the middling spring; a tooltip left out is the label.
|
|
141
|
+
*/
|
|
142
|
+
export interface EdgeType {
|
|
143
|
+
/** Stable id — also the override key in the spring tuning. */
|
|
144
|
+
id: EdgeTypeId;
|
|
145
|
+
/** Short control-panel label. Default: the id. */
|
|
146
|
+
label?: string;
|
|
147
|
+
/**
|
|
148
|
+
* The endpoint values on the style axis this type runs between — one
|
|
149
|
+
* value or several at each end: the type runs between every source value
|
|
150
|
+
* and every target value, in either orientation. Read off the edge's
|
|
151
|
+
* original endpoint nodes when an edge is classified; the first of each
|
|
152
|
+
* is the split-colour token's two halves. Values, not types: the engine
|
|
153
|
+
* resolves an edge's type from where its nodes sit.
|
|
154
|
+
*/
|
|
155
|
+
sourceValue: AxisValue | readonly AxisValue[];
|
|
156
|
+
targetValue: AxisValue | readonly AxisValue[];
|
|
157
|
+
/** Which relation an edge of this type expresses; an edge is classified only as a type of its own relation. */
|
|
158
|
+
relation: 'containment' | 'dependency';
|
|
159
|
+
/**
|
|
160
|
+
* Values the edge itself must carry on the host's edge axes to be this
|
|
161
|
+
* type — how two types on one pair are told apart (a call and a signal
|
|
162
|
+
* between the same two values, by the edge's `dispatch`). An edge lacking
|
|
163
|
+
* one of these values is not this type. Absent, the pair alone decides,
|
|
164
|
+
* and this type is the fallback for a pair other types `match` on.
|
|
165
|
+
*/
|
|
166
|
+
match?: Readonly<Record<AxisId, AxisValue>>;
|
|
167
|
+
/** Declared stiffness / rest length — what the type resolves to until tuned. */
|
|
168
|
+
physics?: SpringPhysics;
|
|
169
|
+
/** How the canvas strokes an edge of this type, in both themes; any field left out is its relation's default stroke's (`NEUTRAL_STROKE`, or `CONTAINMENT_STROKE` for a containment type). */
|
|
170
|
+
style?: Partial<EdgeStroke>;
|
|
171
|
+
/** The hover text for the type. Default: the label. */
|
|
172
|
+
tooltip?: string;
|
|
173
|
+
}
|
|
174
|
+
/** An edge type with its defaults filled in — what `Taxonomy.edgeTypes` carries. */
|
|
175
|
+
export interface ResolvedEdgeType extends EdgeType {
|
|
176
|
+
label: string;
|
|
177
|
+
/** The first declared source value — one half of the split-colour token. */
|
|
178
|
+
sourceValue: AxisValue;
|
|
179
|
+
/** The first declared target value — the other half. */
|
|
180
|
+
targetValue: AxisValue;
|
|
181
|
+
/** Every (source, target) pair the type runs between: each source value with each target value, in declaration order. */
|
|
182
|
+
pairs: readonly (readonly [AxisValue, AxisValue])[];
|
|
183
|
+
physics: SpringPhysics;
|
|
184
|
+
style: EdgeStroke;
|
|
185
|
+
tooltip: string;
|
|
186
|
+
}
|
|
187
|
+
/** The stroke a dependency type starts from, and the stroke of a dependency edge no type claims: a quiet, solid grey. */
|
|
188
|
+
export declare const NEUTRAL_STROKE: EdgeStroke;
|
|
189
|
+
/** The stroke a containment type starts from, and the stroke of a containment edge no type claims: the same grey, faint and dashed. */
|
|
190
|
+
export declare const CONTAINMENT_STROKE: EdgeStroke;
|
|
191
|
+
/** The values declared at one end of an edge type, as a list. */
|
|
192
|
+
export declare function endpointValues(declared: AxisValue | readonly AxisValue[]): readonly AxisValue[];
|
|
193
|
+
/** Every (source, target) pair a type runs between: each source value with each target value, in declaration order. */
|
|
194
|
+
export declare function edgePairs(type: Pick<EdgeType, 'sourceValue' | 'targetValue'>): readonly (readonly [AxisValue, AxisValue])[];
|
|
195
|
+
/**
|
|
196
|
+
* The frame the default rest bands are laid in, in world units: the
|
|
197
|
+
* hierarchy axis runs from `top` (the first declared value) to `bottom` (the
|
|
198
|
+
* last), and every value spreads across `x`. A host that declares a band of
|
|
199
|
+
* its own writes it in these units.
|
|
200
|
+
*/
|
|
201
|
+
export declare const BAND_FRAME: {
|
|
202
|
+
readonly top: -300;
|
|
203
|
+
readonly bottom: 400;
|
|
204
|
+
readonly x: Band;
|
|
205
|
+
};
|
|
206
|
+
/** The spring a type starts from when it declares none. */
|
|
207
|
+
export declare const MIDDLING_SPRING: SpringPhysics;
|
|
208
|
+
/**
|
|
209
|
+
* The rest band on the hierarchy axis for the value at position `i` of `n`:
|
|
210
|
+
* centres spread evenly down the stack, each band wide enough to overlap its
|
|
211
|
+
* neighbours by a fifth, so the structure reads as tiers without a gap a node
|
|
212
|
+
* could never rest in. One value alone takes the whole stack.
|
|
213
|
+
*/
|
|
214
|
+
export declare function stackBand(i: number, n: number): Band;
|
|
215
|
+
/**
|
|
216
|
+
* A declared style with every default filled in, given its position in the
|
|
217
|
+
* declaration order. Pure: the same inputs give the same object, so the
|
|
218
|
+
* taxonomy resolves each value once and hands out that one object.
|
|
219
|
+
*/
|
|
220
|
+
export declare function resolveNodeStyle(style: NodeStyle, i: number, n: number): ResolvedNodeStyle;
|
|
221
|
+
/**
|
|
222
|
+
* A declared edge type with its defaults filled in: the id as label, the
|
|
223
|
+
* first declared value at each end beside every pair, the middling spring,
|
|
224
|
+
* its relation's stroke field by field, the label as tooltip. The taxonomy
|
|
225
|
+
* has refused an end that names no value before this runs.
|
|
226
|
+
*/
|
|
227
|
+
export declare function resolveEdgeType(type: EdgeType): ResolvedEdgeType;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { AxisDescriptor, AxisId, AxisValues, AxisValue, ResolvedAxisDescriptor } from './axis';
|
|
3
|
+
import { GraphEdge, GraphNode } from './model';
|
|
4
|
+
import { EdgeType, EdgeTypeId, NodeStyle, ResolvedEdgeType, ResolvedNodeStyle } from './shapes';
|
|
5
|
+
import { ResolvedScalarAxis, ScalarAxis } from './scalar';
|
|
6
|
+
import { EdgeStroke } from './scheme';
|
|
7
|
+
/** A highlight: the node ids lit and the edge ids lit. Edges absent means "every visible edge between lit nodes". */
|
|
8
|
+
export interface Highlight {
|
|
9
|
+
readonly nodes: ReadonlySet<string>;
|
|
10
|
+
readonly edges?: ReadonlySet<string>;
|
|
11
|
+
}
|
|
12
|
+
/** What a highlight rule may read: the visible graph, and a lookup for any node. */
|
|
13
|
+
export interface HighlightGraph {
|
|
14
|
+
readonly visibleNodes: readonly GraphNode[];
|
|
15
|
+
readonly visibleEdges: readonly GraphEdge[];
|
|
16
|
+
readonly visibleIds: ReadonlySet<string>;
|
|
17
|
+
getNode(id: string): GraphNode | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Which way a highlight walks from its node: what it depends on, or what depends on it. */
|
|
20
|
+
export type HighlightDirection = 'downstream' | 'upstream';
|
|
21
|
+
/** The minimum a consumer needs of a node in order to resolve its style. */
|
|
22
|
+
export type StyleSubject = {
|
|
23
|
+
values: AxisValues;
|
|
24
|
+
};
|
|
25
|
+
/** What the hover box shows under a node's name: one line, or several — text or a host's own elements. */
|
|
26
|
+
export type ContextLine = ReactNode | readonly ReactNode[];
|
|
27
|
+
/**
|
|
28
|
+
* The built taxonomy: what the view resolves every style, edge type, axis
|
|
29
|
+
* policy and host hook through. Built once by `createTaxonomy`; derive a
|
|
30
|
+
* variant from the spec, never by spreading this object.
|
|
31
|
+
*
|
|
32
|
+
* What a host reads: `filterAxes`, `axisFor` and `valueOn` to filter its own
|
|
33
|
+
* records the way the view does; `styleOf`, `styleValues` and `colorVar` for
|
|
34
|
+
* chrome of its own in the scheme's colours; `edgeTypes` for a legend;
|
|
35
|
+
* `searchText` to match as the view matches. The rest is the engine's
|
|
36
|
+
* interface — resolution for the draw loop — and a host has no call to read
|
|
37
|
+
* it.
|
|
38
|
+
*/
|
|
39
|
+
export interface Taxonomy {
|
|
40
|
+
/**
|
|
41
|
+
* The axis this taxonomy resolves style on.
|
|
42
|
+
*
|
|
43
|
+
* One axis, named once. Every other feature elects its own — the physics reads
|
|
44
|
+
* its axis off the force params, filters read theirs off the filter — and no
|
|
45
|
+
* feature composes two.
|
|
46
|
+
*
|
|
47
|
+
* A method, not a field, and that is a correctness property rather than a
|
|
48
|
+
* style choice: a container derived by spreading (`{ ...taxonomy,
|
|
49
|
+
* styleAxis: 'other' }`) would rewrite a field and leave the closures
|
|
50
|
+
* answering on the old axis — an object that disagrees with itself, the
|
|
51
|
+
* draw loop reading one half and the physics the other. With one source
|
|
52
|
+
* there is nothing to override out of step.
|
|
53
|
+
*/
|
|
54
|
+
styleAxis(): AxisId;
|
|
55
|
+
/** The style axis's display name, for a control that names axes. */
|
|
56
|
+
styleLabel(): string;
|
|
57
|
+
/**
|
|
58
|
+
* The axes a filter may operate on, with their per-axis policies,
|
|
59
|
+
* every default filled in. Host-declared, like the entries: which axes
|
|
60
|
+
* exist is a domain fact. The engine reads only the policies and never
|
|
61
|
+
* enumerates the ids.
|
|
62
|
+
*/
|
|
63
|
+
readonly filterAxes: readonly ResolvedAxisDescriptor[];
|
|
64
|
+
/** One axis's policies, or undefined if the host does not declare it. */
|
|
65
|
+
axisFor(axis: AxisId): ResolvedAxisDescriptor | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* The value a subject presents on one axis — read off its values, for
|
|
68
|
+
* every axis alike. An axis that is a projection of another is materialized
|
|
69
|
+
* by the host when it builds the node, so nothing here knows which axes are
|
|
70
|
+
* derived.
|
|
71
|
+
*/
|
|
72
|
+
valueOn(subject: StyleSubject, axis: AxisId): AxisValue | undefined;
|
|
73
|
+
/** Every style value, in declaration order (top of the hierarchy first). */
|
|
74
|
+
readonly styleValues: readonly AxisValue[];
|
|
75
|
+
/** Every edge type, in control-panel order, its defaults filled in. */
|
|
76
|
+
readonly edgeTypes: readonly ResolvedEdgeType[];
|
|
77
|
+
/** Every computed scalar a layout axis may key on, its words filled in: the built-ins, then the host's. */
|
|
78
|
+
readonly scalars: readonly ResolvedScalarAxis[];
|
|
79
|
+
/** How the canvas strokes an edge of this type; the neutral stroke, said once, for an id the taxonomy does not declare. */
|
|
80
|
+
edgeStrokeFor(id: EdgeTypeId): EdgeStroke;
|
|
81
|
+
/**
|
|
82
|
+
* The custom property a value's fill is published under (`-border` for its
|
|
83
|
+
* border): `--gv-node-` and the value id in kebab case, or a numbered name
|
|
84
|
+
* when the id kebab-cases to nothing or to another value's name. The one
|
|
85
|
+
* way to learn the name; a host's CSS reads it through `schemeVars` or
|
|
86
|
+
* `schemeStylesheet`.
|
|
87
|
+
*/
|
|
88
|
+
colorVar(value: AxisValue): string;
|
|
89
|
+
/** The hover box's context line(s) for a node — the host's, or its parent's name. */
|
|
90
|
+
contextLine(node: GraphNode, parent: GraphNode | undefined): ContextLine;
|
|
91
|
+
/** What the search control matches against for a node — the host's text, or the name. */
|
|
92
|
+
searchText(node: GraphNode): string;
|
|
93
|
+
/** The highlight for an active node — the host's refinement of the library's transitive walk in the given direction. */
|
|
94
|
+
highlight(active: GraphNode, base: Highlight, graph: HighlightGraph, direction: HighlightDirection): Highlight;
|
|
95
|
+
/**
|
|
96
|
+
* Style, size, physics and summary metadata for a value. Never throws — a
|
|
97
|
+
* value the taxonomy does not declare, and an ABSENT value, both resolve to
|
|
98
|
+
* the fallback.
|
|
99
|
+
*/
|
|
100
|
+
styleOf(value: AxisValue | undefined): ResolvedNodeStyle;
|
|
101
|
+
/** Where a node sits on the style axis, or undefined if it sits nowhere. */
|
|
102
|
+
styleValueOf(subject: StyleSubject): AxisValue | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Short label for a value — one or two characters. Control surfaces render a
|
|
105
|
+
* token per value and have no room for a full name. A value the taxonomy
|
|
106
|
+
* does not declare abbreviates to its own first two characters.
|
|
107
|
+
*/
|
|
108
|
+
abbreviationFor(value: AxisValue): string;
|
|
109
|
+
/** The same as `styleOf`, addressed by a node. The hot-path entry point. */
|
|
110
|
+
nodeStyleOf(subject: StyleSubject): ResolvedNodeStyle;
|
|
111
|
+
/**
|
|
112
|
+
* Which declared edge type an edge is, given the style values of its two
|
|
113
|
+
* ORIGINAL endpoints: the declared type of the edge's relation that runs
|
|
114
|
+
* between those values in either orientation and whose `match` the edge's
|
|
115
|
+
* own values satisfy (a satisfied `match` over none, the declared
|
|
116
|
+
* orientation over the reverse, then declaration order), handed to the
|
|
117
|
+
* spec's `classifyEdge`, which may keep it, replace it, or supply one where
|
|
118
|
+
* there is none; undefined when neither names one. Classified once, on
|
|
119
|
+
* the original endpoints; the type is carried through graduation, so a
|
|
120
|
+
* re-pointed edge keeps its stroke and its spring.
|
|
121
|
+
*/
|
|
122
|
+
edgeTypeOf(edge: GraphEdge, src: AxisValue | undefined, tgt: AxisValue | undefined): EdgeTypeId | undefined;
|
|
123
|
+
/** Which of two graduated edges on one visible pair survives: the host's choice, or the one kept so far. */
|
|
124
|
+
collapse(kept: GraphEdge, candidate: GraphEdge): GraphEdge;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* What a host declares in order to build an `Taxonomy`: the style axis and
|
|
128
|
+
* its values, the edge types and the rule that classifies an edge, the filter
|
|
129
|
+
* axes. Everything with a sensible default is optional.
|
|
130
|
+
*/
|
|
131
|
+
export interface TaxonomySpec {
|
|
132
|
+
/** The axis every node's style is read on. */
|
|
133
|
+
styleAxis: AxisId;
|
|
134
|
+
/** The style axis's display name. Absent, the axis id. */
|
|
135
|
+
styleLabel?: string;
|
|
136
|
+
/**
|
|
137
|
+
* The style values, top of the hierarchy first. The order places each
|
|
138
|
+
* value's rest band down the stack when it declares none, and orders the
|
|
139
|
+
* control surfaces and the hover box's child counts.
|
|
140
|
+
*/
|
|
141
|
+
styles: readonly NodeStyle[];
|
|
142
|
+
/**
|
|
143
|
+
* Drawn for a value the taxonomy does not declare, and for a node with no
|
|
144
|
+
* value on the style axis. Absent, a grey disc with a question mark that
|
|
145
|
+
* rests anywhere in the stack.
|
|
146
|
+
*/
|
|
147
|
+
fallbackStyle?: Omit<NodeStyle, 'id'>;
|
|
148
|
+
/** The edge types, in control-panel order. Absent, none: every edge draws untyped in its relation's stroke, and `validateGraph` says so. */
|
|
149
|
+
edgeTypes?: readonly EdgeType[];
|
|
150
|
+
/**
|
|
151
|
+
* The host's say in classifying an edge, given the style values of its
|
|
152
|
+
* original endpoints and `declared` — the type the declarations answer (by
|
|
153
|
+
* relation, endpoint pair, `match` and orientation), or undefined: an id
|
|
154
|
+
* to use, or undefined to keep the declared answer. For the exceptions the
|
|
155
|
+
* declarations cannot express — a type that also runs between pairs it
|
|
156
|
+
* does not declare, say: `(edge, src, tgt, declared) => declared ?? …`.
|
|
157
|
+
* Required only when two declared types on one pair share an orientation
|
|
158
|
+
* and a `match`.
|
|
159
|
+
*/
|
|
160
|
+
classifyEdge?: (edge: GraphEdge, src: AxisValue | undefined, tgt: AxisValue | undefined, declared: EdgeTypeId | undefined) => EdgeTypeId | undefined;
|
|
161
|
+
/** The axes the filter bar offers. Absent, the style axis alone, as an allow-list. */
|
|
162
|
+
filterAxes?: readonly AxisDescriptor[];
|
|
163
|
+
/**
|
|
164
|
+
* Computed scalars this host adds to the built-ins: each reads node
|
|
165
|
+
* metadata — its own payload included — and the graph's structure, and
|
|
166
|
+
* answers a number per node, which the frame maps onto [0, 1] the way the
|
|
167
|
+
* scalar's `normalize` says. Absent, the built-ins alone.
|
|
168
|
+
*/
|
|
169
|
+
scalars?: readonly ScalarAxis[];
|
|
170
|
+
/**
|
|
171
|
+
* The hover box's context under the name: what a host wants said there —
|
|
172
|
+
* addressing metadata from its own payload, a parent by another name, an
|
|
173
|
+
* origin — as one line or several. Absent, the line is the parent's name.
|
|
174
|
+
*/
|
|
175
|
+
contextLine?: (node: GraphNode, parent: GraphNode | undefined) => ContextLine;
|
|
176
|
+
/**
|
|
177
|
+
* What the search control matches a node on, case-insensitively: a code
|
|
178
|
+
* from the payload beside the name, say. Absent, the name.
|
|
179
|
+
*/
|
|
180
|
+
searchText?: (node: GraphNode) => string;
|
|
181
|
+
/**
|
|
182
|
+
* The highlight for an active node: given the library's transitive walk
|
|
183
|
+
* from it in `direction`, the host may widen it (members it relates by
|
|
184
|
+
* metadata) or replace it. Absent, the walk is the highlight.
|
|
185
|
+
*/
|
|
186
|
+
highlight?: (active: GraphNode, base: Highlight, graph: HighlightGraph, direction: HighlightDirection) => Highlight;
|
|
187
|
+
/**
|
|
188
|
+
* When two dependency edges each lose an end to a hidden node and come to
|
|
189
|
+
* run between the same two visible nodes, which of the two originals the
|
|
190
|
+
* drawn edge stands for. Both arguments are the host's own edges, so
|
|
191
|
+
* a host whose edges carry routing metadata may prefer the one that does.
|
|
192
|
+
* Absent, the one met first in the host's edge order is kept. Two edges
|
|
193
|
+
* whose ends are both visible are never collapsed.
|
|
194
|
+
*/
|
|
195
|
+
collapse?: (kept: GraphEdge, candidate: GraphEdge) => GraphEdge;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Build the container, refusing an incoherent spec: a value declared twice, an
|
|
199
|
+
* edge type declared twice, running between values nobody declared or naming
|
|
200
|
+
* no value at an end, a filter axis declared twice, a colour no reader can
|
|
201
|
+
* parse, a band whose ends cross, a policy outside its vocabulary, a scalar
|
|
202
|
+
* id already taken. Every problem is named at once, by its path in the spec.
|
|
203
|
+
* To derive a variant, build one from a spec (`createTaxonomy({ ...spec, … })`);
|
|
204
|
+
* spreading the built object copies closures that still read the original's
|
|
205
|
+
* fields.
|
|
206
|
+
*/
|
|
207
|
+
export declare function createTaxonomy(spec: TaxonomySpec): Taxonomy;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Graph } from './model';
|
|
2
|
+
import { Taxonomy } from './taxonomy';
|
|
3
|
+
/**
|
|
4
|
+
* The defects `validateGraph` names. Errors: a node or edge id used twice,
|
|
5
|
+
* an edge whose endpoint is not in the graph, an unknown relation, a type
|
|
6
|
+
* whose relation is not the edge's, a rule that threw, a parent not in the
|
|
7
|
+
* graph. Warnings: an edge no type claims, a style value the taxonomy does
|
|
8
|
+
* not declare, containment edges that contradict `parentId`, derived
|
|
9
|
+
* containment edges no type claims (`containment-untyped`, from
|
|
10
|
+
* `derivedContainmentDiagnostics`).
|
|
11
|
+
*/
|
|
12
|
+
export type GraphDiagnosticCode = 'edge-id-duplicate' | 'edge-endpoint-missing' | 'edge-relation-unknown' | 'edge-type-rule-threw' | 'edge-type-unclassified' | 'edge-type-relation-mismatch' | 'parent-missing' | 'containment-parent-mismatch' | 'node-value-undeclared' | 'node-id-duplicate' | 'containment-untyped';
|
|
13
|
+
/** One defect in a host's graph, as data: its severity, its code, a message, and the node or edge it names. */
|
|
14
|
+
export interface GraphDiagnostic {
|
|
15
|
+
/** An error names something the view cannot draw as given; a warning, something it draws but the host should know. */
|
|
16
|
+
severity: 'error' | 'warning';
|
|
17
|
+
code: GraphDiagnosticCode;
|
|
18
|
+
message: string;
|
|
19
|
+
nodeId?: string;
|
|
20
|
+
edgeId?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Every defect in a host's graph, as data: errors for what the view cannot
|
|
24
|
+
* draw as given (a duplicated node id, a dangling endpoint, an unknown
|
|
25
|
+
* relation, a type whose relation is not the edge's, a parent not in the
|
|
26
|
+
* graph) and warnings for what it draws but the host should know (an
|
|
27
|
+
* unclassified edge, an undeclared style value, containment edges that
|
|
28
|
+
* contradict `parentId`). Pure; the same graph and taxonomy give the same
|
|
29
|
+
* list, in graph order.
|
|
30
|
+
*/
|
|
31
|
+
export declare function validateGraph(graph: Graph, taxonomy: Taxonomy): GraphDiagnostic[];
|
|
32
|
+
/**
|
|
33
|
+
* The graph with every node and edge an error names removed and every parent
|
|
34
|
+
* an error names cleared — what the view draws when the host's graph has
|
|
35
|
+
* defects. A duplicated id keeps its first node and its first edge. The
|
|
36
|
+
* host's objects are not mutated; a graph with no errors is returned as is.
|
|
37
|
+
*/
|
|
38
|
+
export declare function dropInvalid(graph: Graph, diagnostics: readonly GraphDiagnostic[]): Graph;
|
|
39
|
+
/**
|
|
40
|
+
* The one warning the drawn graph adds to the host's: the containment edges
|
|
41
|
+
* the view derived from `parentId` that no declared containment type claims
|
|
42
|
+
* (a dependency type the host's rule answers does not count). They draw in
|
|
43
|
+
* the containment stroke and pull nothing while push and pull key on the
|
|
44
|
+
* style axis; a host that wants them typed declares a containment type
|
|
45
|
+
* between the child's value and the parent's.
|
|
46
|
+
*/
|
|
47
|
+
export declare function derivedContainmentDiagnostics(drawn: Graph, host: Graph, taxonomy: Taxonomy): GraphDiagnostic[];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export { FilterBar } from './components/FilterBar';
|
|
2
|
+
export type { FilterBarChrome, FilterBarProps } from './components/FilterBar';
|
|
3
|
+
export { GraphView } from './components/GraphView';
|
|
4
|
+
export type { GraphViewChrome, GraphViewHandle, GraphViewProps, GroupsControl, NodeAction, Position, SearchState } from './components/GraphView';
|
|
5
|
+
export { GroupLegend } from './components/GroupLegend';
|
|
6
|
+
export type { GroupLegendProps } from './components/GroupLegend';
|
|
7
|
+
export { useLinkedViews } from './components/graph-view/useLinkedViews';
|
|
8
|
+
export type { LinkedViewProps, LinkedViewState, LinkedViews, LinkedViewsOptions } from './components/graph-view/useLinkedViews';
|
|
9
|
+
export type { FocusRequest } from './components/graph-view/focus';
|
|
10
|
+
export { useFocusRequest } from './components/graph-view/useFocusRequest';
|
|
11
|
+
export type { RecentlyChanged } from './components/graph-view/useRecentlyChanged';
|
|
12
|
+
export { TaxonomyContext, useTaxonomy } from './components/graph-view/useTaxonomy';
|
|
13
|
+
export { themeChoiceOf, useHostTheme } from './components/graph-view/useTheme';
|
|
14
|
+
export type { ThemeChoice } from './components/graph-view/useTheme';
|
|
15
|
+
export { reconcileFilter } from './filter/reconcile';
|
|
16
|
+
export type { ReconcileInput } from './filter/reconcile';
|
|
17
|
+
export { toggleGroup, toggleValue } from './filter/toggle';
|
|
18
|
+
export { initialFilter, filterFromJSON, filterStatesEqual, filterToJSON, hiddenMatchesOf, locksFromJSON, locksToJSON, matchesFocus, passesSelection, reseedFilter, lockedFor, selectionFor, withLock, withSelection } from './filter/types';
|
|
19
|
+
export type { FilterState, FocusTarget, HiddenMatches, HiddenMatchesInput, AxisLocks, PassesSelectionInput, ReconcileResult, AxisSelection, ViewTransition } from './filter/types';
|
|
20
|
+
export { countsOn, valuesOn } from './graph/axis';
|
|
21
|
+
export type { AxisDescriptor, AxisId, AxisNamer, AxisValues, AxisValue, FilterChip, Relation, ResolvedAxisDescriptor } from './graph/axis';
|
|
22
|
+
export type { ActiveGroup, NodeGroup } from './graph/groups';
|
|
23
|
+
export { copyGroups, isContainment, nodesById, payloadNumber, payloadString } from './graph/model';
|
|
24
|
+
export type { Graph, GraphEdge, GraphNode, ReadableGraph } from './graph/model';
|
|
25
|
+
export { createTaxonomy } from './graph/taxonomy';
|
|
26
|
+
export type { ContextLine, Highlight, HighlightDirection, HighlightGraph, StyleSubject, Taxonomy, TaxonomySpec } from './graph/taxonomy';
|
|
27
|
+
export { schemeStylesheet, schemeVars } from './graph/scheme';
|
|
28
|
+
export type { ColorPair, EdgeStroke, Theme, ThemedColor } from './graph/scheme';
|
|
29
|
+
export type { ResolvedScalarAxis, ScalarAxis } from './graph/scalar';
|
|
30
|
+
export { layoutFromJSON, layoutToJSON } from './graph/layout';
|
|
31
|
+
export type { LayoutJSON, LayoutState, LayoutTuningJSON } from './graph/layout';
|
|
32
|
+
export { validateGraph } from './graph/validate';
|
|
33
|
+
export type { GraphDiagnostic, GraphDiagnosticCode } from './graph/validate';
|
|
34
|
+
export { BAND_FRAME, CONTAINMENT_STROKE, NEUTRAL_STROKE } from './graph/shapes';
|
|
35
|
+
export type { Band, EdgeType, EdgeTypeId, NodeStyle, ResolvedEdgeType, ResolvedNodeStyle, SpringPhysics } from './graph/shapes';
|