vizcraft 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +104 -0
- package/dist/builder.d.ts +162 -7
- package/dist/builder.js +1086 -123
- package/dist/edgePaths.d.ts +8 -0
- package/dist/edgePaths.js +86 -1
- package/dist/edgeStyles.d.ts +8 -0
- package/dist/edgeStyles.js +28 -0
- package/dist/hitTest.d.ts +66 -0
- package/dist/hitTest.js +339 -0
- package/dist/icons.d.ts +18 -0
- package/dist/icons.js +49 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/layouts.d.ts +33 -0
- package/dist/layouts.js +59 -0
- package/dist/panZoom.d.ts +2 -0
- package/dist/panZoom.js +197 -0
- package/dist/runtimePatcher.d.ts +9 -2
- package/dist/runtimePatcher.js +211 -12
- package/dist/serialization.d.ts +28 -0
- package/dist/serialization.js +98 -0
- package/dist/shapes.d.ts +3 -2
- package/dist/shapes.js +202 -2
- package/dist/textUtils.d.ts +38 -0
- package/dist/textUtils.js +213 -0
- package/dist/types.d.ts +464 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# vizcraft
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`f72dc04`](https://github.com/ChipiKaf/vizcraft/commit/f72dc0405ccd752ad13eb746349b6a5945448c79) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Added rich text labels to VizCraft with support for mixed formatting and line breaks. Introduced fluent .richLabel() APIs and declarative label.rich support. Improved runtime updates to keep animations stable, extended React rendering, and added test coverage. Docs and READMEs now include a live example.
|
|
8
|
+
|
|
9
|
+
## 1.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`86655bf`](https://github.com/ChipiKaf/vizcraft/commit/86655bf59c9641af18416b79d0775212a9ecd15e) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Added support for incremental scene updates, node resizing, JSON serialization/deserialization, viewport pan and zoom functionality, multi-line labels with text wrapping, declarative API options for nodes and edges, and custom dashed/dotted edge line styles.
|
|
14
|
+
|
|
3
15
|
## 1.0.0
|
|
4
16
|
|
|
5
17
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -85,6 +85,12 @@ pnpm -C packages/docs start
|
|
|
85
85
|
|
|
86
86
|
The heart of VizCraft is the `VizBuilder`. It allows you to construct a `VizScene` which acts as the blueprint for your visualization.
|
|
87
87
|
|
|
88
|
+
For exporting frame snapshots during data-only playback, you can export an SVG that includes runtime overrides:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const svg = builder.svg({ includeRuntime: true });
|
|
92
|
+
```
|
|
93
|
+
|
|
88
94
|
```typescript
|
|
89
95
|
b.view(width, height) // Set the coordinate space
|
|
90
96
|
.grid(cols, rows) // (Optional) Define layout grid
|
|
@@ -92,6 +98,71 @@ b.view(width, height) // Set the coordinate space
|
|
|
92
98
|
.edge(from, to); // Start defining an edge
|
|
93
99
|
```
|
|
94
100
|
|
|
101
|
+
### Plugins
|
|
102
|
+
|
|
103
|
+
Extend the builder's functionality seamlessly using `.use()`. Plugins are functions that take the builder instance and optional configuration, allowing you to encapsulate reusable behaviors, export utilities, or composite nodes.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { viz, VizPlugin } from 'vizcraft';
|
|
107
|
+
|
|
108
|
+
const watermarkPlugin: VizPlugin<{ text: string }> = (builder, opts) => {
|
|
109
|
+
builder.node('watermark', {
|
|
110
|
+
at: { x: 50, y: 20 },
|
|
111
|
+
rect: { w: 100, h: 20 },
|
|
112
|
+
label: opts?.text ?? 'Draft',
|
|
113
|
+
opacity: 0.5,
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
viz()
|
|
118
|
+
.view(800, 600)
|
|
119
|
+
.node('n1', { circle: { r: 20 } })
|
|
120
|
+
.use(watermarkPlugin, { text: 'Confidential' })
|
|
121
|
+
.build();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Event Hooks**
|
|
125
|
+
|
|
126
|
+
Plugins (or your own code) can also tap into the builder's lifecycle using `.on()`. This is particularly useful for interactive plugins that need to append HTML elements (like export buttons or tooltips) after VizCraft mounts the SVG to the DOM.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
const exportUiPlugin: VizPlugin = (builder) => {
|
|
130
|
+
// Listen for the 'mount' event to inject a button next to the SVG
|
|
131
|
+
builder.on('mount', ({ container }) => {
|
|
132
|
+
const btn = document.createElement('button');
|
|
133
|
+
btn.innerText = 'Download PNG';
|
|
134
|
+
btn.onclick = () => {
|
|
135
|
+
/* export logic */
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Position the button absolutely over the container
|
|
139
|
+
btn.style.position = 'absolute';
|
|
140
|
+
btn.style.top = '10px';
|
|
141
|
+
btn.style.right = '10px';
|
|
142
|
+
container.appendChild(btn);
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Declarative Options Overloads
|
|
148
|
+
|
|
149
|
+
You can also configure nodes and edges in a single declarative call by passing an options object:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Declarative — pass all options at once, returns VizBuilder
|
|
153
|
+
b.node('a', {
|
|
154
|
+
at: { x: 100, y: 100 },
|
|
155
|
+
rect: { w: 80, h: 40 },
|
|
156
|
+
fill: 'steelblue',
|
|
157
|
+
label: 'A',
|
|
158
|
+
})
|
|
159
|
+
.node('b', { circle: { r: 20 }, at: { x: 300, y: 100 }, label: 'B' })
|
|
160
|
+
.edge('a', 'b', { arrow: true, stroke: 'red', dash: 'dashed' })
|
|
161
|
+
.build();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Both `NodeOptions` and `EdgeOptions` types are exported for full type-safety. See the [Essentials docs](https://vizcraft.dev/docs/essentials) for the complete options reference.
|
|
165
|
+
|
|
95
166
|
### Nodes
|
|
96
167
|
|
|
97
168
|
Nodes are the primary entities in your graph. They can have shapes, labels, and styles.
|
|
@@ -121,6 +192,10 @@ b.node('n1')
|
|
|
121
192
|
.trapezoid(topW, bottomW, h) // Trapezoid
|
|
122
193
|
.triangle(w, h, [direction]) // Triangle
|
|
123
194
|
.label('Text', { dy: 5 }) // Label with offset
|
|
195
|
+
.richLabel((l) => l.text('Hello ').bold('World')) // Rich / mixed-format label
|
|
196
|
+
.image(href, w, h, opts?) // Embed an <image> inside the node
|
|
197
|
+
.icon(id, opts?) // Embed an icon from the icon registry (see registerIcon)
|
|
198
|
+
.svgContent(svg, opts) // Embed inline SVG content inside the node
|
|
124
199
|
.class('css-class') // Custom CSS class
|
|
125
200
|
.data({ ... }) // Attach custom data
|
|
126
201
|
.port('out', { x: 50, y: 0 }) // Named connection port
|
|
@@ -155,6 +230,7 @@ b.edge('n1', 'n2')
|
|
|
155
230
|
.arrow() // Add an arrowhead
|
|
156
231
|
.straight() // (Default) Straight line
|
|
157
232
|
.label('Connection')
|
|
233
|
+
.richLabel((l) => l.text('p').sup('95').text(' = ').bold('10ms'))
|
|
158
234
|
.animate('flow'); // Add animation
|
|
159
235
|
|
|
160
236
|
// Curved edge
|
|
@@ -166,21 +242,45 @@ b.edge('a', 'c').orthogonal().arrow();
|
|
|
166
242
|
// Waypoints — intermediate points the edge passes through
|
|
167
243
|
b.edge('x', 'y').curved().via(150, 50).via(200, 100).arrow();
|
|
168
244
|
|
|
245
|
+
// Arbitrary edge metadata (for routing flags, categories, etc.)
|
|
246
|
+
b.edge('a', 'b').meta({ customRouting: true, padding: 10 });
|
|
247
|
+
|
|
248
|
+
// Override edge path computation with a resolver hook
|
|
249
|
+
b.setEdgePathResolver((edge, scene, defaultResolver) => {
|
|
250
|
+
if (edge.meta?.customRouting) {
|
|
251
|
+
// Return an SVG path `d` string
|
|
252
|
+
return `M 0 0 L 10 10`;
|
|
253
|
+
}
|
|
254
|
+
return defaultResolver(edge, scene);
|
|
255
|
+
});
|
|
256
|
+
|
|
169
257
|
// Per-edge styling (overrides CSS defaults)
|
|
170
258
|
b.edge('a', 'b').stroke('#ff0000', 3).fill('none').opacity(0.8);
|
|
171
259
|
|
|
260
|
+
// Dashed, dotted, and custom dash patterns
|
|
261
|
+
b.edge('a', 'b').dashed().stroke('#6c7086'); // dashed line
|
|
262
|
+
b.edge('a', 'b').dotted(); // dotted line
|
|
263
|
+
b.edge('a', 'b').dash('12, 3, 3, 3').stroke('#cba6f7'); // custom pattern
|
|
264
|
+
|
|
172
265
|
// Multi-position edge labels (start / mid / end)
|
|
173
266
|
b.edge('a', 'b')
|
|
174
267
|
.label('1', { position: 'start' })
|
|
175
268
|
.label('*', { position: 'end' })
|
|
176
269
|
.arrow();
|
|
177
270
|
|
|
271
|
+
// Rich text labels (mixed formatting)
|
|
272
|
+
b.edge('a', 'b')
|
|
273
|
+
.richLabel((l) => l.text('p').sup('95').text(' ').bold('12ms'))
|
|
274
|
+
.arrow();
|
|
275
|
+
|
|
178
276
|
// Edge markers / arrowhead types
|
|
179
277
|
b.edge('a', 'b').markerEnd('arrowOpen'); // Open arrow (inheritance)
|
|
180
278
|
b.edge('a', 'b').markerStart('diamond').markerEnd('arrow'); // UML composition
|
|
181
279
|
b.edge('a', 'b').markerStart('diamondOpen').markerEnd('arrow'); // UML aggregation
|
|
182
280
|
b.edge('a', 'b').arrow('both'); // Bidirectional arrows
|
|
183
281
|
b.edge('a', 'b').markerStart('circleOpen').markerEnd('arrow'); // Association
|
|
282
|
+
// Self-loops (exits and enters the same node)
|
|
283
|
+
b.edge('n1', 'n1').loopSide('right').loopSize(40).arrow();
|
|
184
284
|
b.edge('a', 'b').markerEnd('bar'); // ER cardinality
|
|
185
285
|
|
|
186
286
|
// Connection ports — edges attach to specific points on nodes
|
|
@@ -204,6 +304,7 @@ b.edge('a', 'b').fromPort('right').toPort('left').arrow();
|
|
|
204
304
|
| `.routing(mode)` | Set mode programmatically. |
|
|
205
305
|
| `.via(x, y)` | Add an intermediate waypoint (chainable). |
|
|
206
306
|
| `.label(text, opts?)` | Add a text label. Chain multiple calls for multi-position labels. `opts.position` can be `'start'`, `'mid'` (default), or `'end'`. |
|
|
307
|
+
| `.richLabel(cb, opts?)` | Add a rich / mixed-format label (nested SVG `<tspan>`s). Use `.newline()` in the callback to control line breaks. |
|
|
207
308
|
| `.arrow([enabled])` | Shorthand for arrow markers. `true`/no-arg → markerEnd arrow. `'both'` → both ends. `'start'`/`'end'` → specific end. `false` → none. |
|
|
208
309
|
| `.markerEnd(type)` | Set marker type at the target end. See `EdgeMarkerType`. |
|
|
209
310
|
| `.markerStart(type)` | Set marker type at the source end. See `EdgeMarkerType`. |
|
|
@@ -212,6 +313,9 @@ b.edge('a', 'b').fromPort('right').toPort('left').arrow();
|
|
|
212
313
|
| `.stroke(color, width?)` | Set stroke color and optional width. |
|
|
213
314
|
| `.fill(color)` | Set fill color. |
|
|
214
315
|
| `.opacity(value)` | Set opacity (0–1). |
|
|
316
|
+
| `.dashed()` | Dashed stroke (`8, 4`). |
|
|
317
|
+
| `.dotted()` | Dotted stroke (`2, 4`). |
|
|
318
|
+
| `.dash(pattern)` | Custom SVG dasharray or preset (`'dashed'`, `'dotted'`, `'dash-dot'`, `'solid'`). |
|
|
215
319
|
|
|
216
320
|
**`EdgeMarkerType`** values: `'none'`, `'arrow'`, `'arrowOpen'`, `'diamond'`, `'diamondOpen'`, `'circle'`, `'circleOpen'`, `'square'`, `'bar'`, `'halfArrow'`.
|
|
217
321
|
|
package/dist/builder.d.ts
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
|
-
import type { VizScene, VizNode, VizEdge, NodeLabel, EdgeLabel, AnimationConfig, OverlayId, OverlayParams, VizGridConfig, ContainerConfig, EdgeRouting, EdgeMarkerType } from './types';
|
|
1
|
+
import type { VizScene, VizNode, VizEdge, NodeLabel, EdgeLabel, RichText, RichTextToken, AnimationConfig, OverlayId, OverlayParams, VizGridConfig, ContainerConfig, EdgeRouting, EdgeMarkerType, EdgePathResolver, NodeOptions, EdgeOptions, PanZoomOptions, PanZoomController, VizSceneMutator, VizPlugin, VizEventMap, LayoutAlgorithm, SvgExportOptions } from './types';
|
|
2
2
|
import { OverlayBuilder } from './overlayBuilder';
|
|
3
3
|
import type { AnimationSpec } from './anim/spec';
|
|
4
4
|
import { type AnimationBuilder, type AnimatableProps, type TweenOptions } from './anim/animationBuilder';
|
|
5
5
|
import { type PlaybackController } from './anim/playback';
|
|
6
|
-
interface VizBuilder {
|
|
6
|
+
export interface VizBuilder extends VizSceneMutator {
|
|
7
|
+
/**
|
|
8
|
+
* Applies a plugin to the builder fluently.
|
|
9
|
+
* @param plugin The plugin function to execute
|
|
10
|
+
* @param options Optional configuration for the plugin
|
|
11
|
+
* @returns The builder, for fluent chaining
|
|
12
|
+
*/
|
|
13
|
+
use<O>(plugin: VizPlugin<O>, options?: O): VizBuilder;
|
|
14
|
+
/**
|
|
15
|
+
* Applies a layout algorithm to the current nodes and edges.
|
|
16
|
+
* @param algorithm The layout function to execute
|
|
17
|
+
* @param options Optional configuration for the layout algorithm
|
|
18
|
+
* @returns The builder, for fluent chaining
|
|
19
|
+
*/
|
|
20
|
+
layout<O>(algorithm: LayoutAlgorithm<O>, options?: O): VizBuilder;
|
|
21
|
+
/**
|
|
22
|
+
* Listen for lifecycle events (e.g. 'build', 'mount').
|
|
23
|
+
* @param event The event name
|
|
24
|
+
* @param callback The callback to execute when the event fires
|
|
25
|
+
* @returns An unsubscribe function
|
|
26
|
+
*/
|
|
27
|
+
on<K extends keyof VizEventMap>(event: K, callback: (ev: VizEventMap[K]) => void): () => void;
|
|
28
|
+
/**
|
|
29
|
+
* Override edge SVG path computation.
|
|
30
|
+
*
|
|
31
|
+
* Intended to be installed before `mount()`. Applies to DOM reconciliation and
|
|
32
|
+
* `patchRuntime()`.
|
|
33
|
+
*/
|
|
34
|
+
setEdgePathResolver(resolver: EdgePathResolver | null): VizBuilder;
|
|
7
35
|
view(w: number, h: number): VizBuilder;
|
|
8
36
|
grid(cols: number, rows: number, padding?: {
|
|
9
37
|
x: number;
|
|
@@ -18,20 +46,28 @@ interface VizBuilder {
|
|
|
18
46
|
overlay(cb: (overlay: OverlayBuilder) => unknown): VizBuilder;
|
|
19
47
|
overlay<K extends OverlayId>(id: K, params: OverlayParams<K>, key?: string): VizBuilder;
|
|
20
48
|
overlay<T>(id: string, params: T, key?: string): VizBuilder;
|
|
49
|
+
/** Create a node and return the NodeBuilder for fluent chaining. */
|
|
21
50
|
node(id: string): NodeBuilder;
|
|
51
|
+
/** Create a fully-configured node declaratively and return the parent VizBuilder. */
|
|
52
|
+
node(id: string, opts: NodeOptions): VizBuilder;
|
|
53
|
+
/** Create an edge and return the EdgeBuilder for fluent chaining. */
|
|
22
54
|
edge(from: string, to: string, id?: string): EdgeBuilder;
|
|
55
|
+
/** Create a fully-configured edge declaratively and return the parent VizBuilder. */
|
|
56
|
+
edge(from: string, to: string, opts: EdgeOptions): VizBuilder;
|
|
57
|
+
/** Hydrates the builder from an existing VizScene. */
|
|
58
|
+
fromScene(scene: VizScene): VizBuilder;
|
|
23
59
|
build(): VizScene;
|
|
24
60
|
_getGridConfig(): VizGridConfig | null;
|
|
25
61
|
_getViewBox(): {
|
|
26
62
|
w: number;
|
|
27
63
|
h: number;
|
|
28
64
|
};
|
|
29
|
-
svg(): string;
|
|
30
|
-
mount(container: HTMLElement):
|
|
65
|
+
svg(opts?: SvgExportOptions): string;
|
|
66
|
+
mount(container: HTMLElement): PanZoomController | undefined;
|
|
31
67
|
mount(container: HTMLElement, opts: {
|
|
32
68
|
autoplay?: boolean;
|
|
33
69
|
css?: string | string[];
|
|
34
|
-
}):
|
|
70
|
+
} & PanZoomOptions): PanZoomController | undefined;
|
|
35
71
|
/**
|
|
36
72
|
* Plays animation specs against a mounted container.
|
|
37
73
|
*
|
|
@@ -45,11 +81,59 @@ interface VizBuilder {
|
|
|
45
81
|
play(container: HTMLElement): PlaybackController | null;
|
|
46
82
|
play(container: HTMLElement, spec: AnimationSpec): PlaybackController;
|
|
47
83
|
play(container: HTMLElement, spec: AnimationSpec[]): PlaybackController;
|
|
84
|
+
/**
|
|
85
|
+
* Resizes a node at runtime, overriding its initial shape dimensions.
|
|
86
|
+
*/
|
|
87
|
+
resizeNode(id: string, dims: {
|
|
88
|
+
w?: number;
|
|
89
|
+
h?: number;
|
|
90
|
+
r?: number;
|
|
91
|
+
}): VizBuilder;
|
|
48
92
|
/**
|
|
49
93
|
* Applies runtime-only patches (node.runtime / edge.runtime) to the mounted SVG.
|
|
50
94
|
* This avoids full DOM reconciliation and is intended for animation frame updates.
|
|
51
95
|
*/
|
|
52
96
|
patchRuntime(container: HTMLElement): void;
|
|
97
|
+
/**
|
|
98
|
+
* Tear down a previously mounted scene.
|
|
99
|
+
*
|
|
100
|
+
* - Removes the SVG tree from the container.
|
|
101
|
+
* - Destroys the PanZoomController (if created).
|
|
102
|
+
* - Cancels any pending requestAnimationFrame / animation loops.
|
|
103
|
+
* - Removes any internal event listeners (resize, mutation, etc.).
|
|
104
|
+
*
|
|
105
|
+
* Safe to call multiple times (no-op after first call).
|
|
106
|
+
* Safe to call even if `mount()` was never called.
|
|
107
|
+
*/
|
|
108
|
+
destroy(): void;
|
|
109
|
+
}
|
|
110
|
+
export interface RichLabelBuilder {
|
|
111
|
+
text(text: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
112
|
+
kind: 'span';
|
|
113
|
+
}>, 'kind' | 'text'>>): RichLabelBuilder;
|
|
114
|
+
bold(text: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
115
|
+
kind: 'span';
|
|
116
|
+
}>, 'kind' | 'text'>>): RichLabelBuilder;
|
|
117
|
+
italic(text: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
118
|
+
kind: 'span';
|
|
119
|
+
}>, 'kind' | 'text'>>): RichLabelBuilder;
|
|
120
|
+
code(text: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
121
|
+
kind: 'span';
|
|
122
|
+
}>, 'kind' | 'text'>>): RichLabelBuilder;
|
|
123
|
+
color(text: string, fill: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
124
|
+
kind: 'span';
|
|
125
|
+
}>, 'kind' | 'text' | 'fill'>>): RichLabelBuilder;
|
|
126
|
+
link(text: string, href: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
127
|
+
kind: 'span';
|
|
128
|
+
}>, 'kind' | 'text' | 'href'>>): RichLabelBuilder;
|
|
129
|
+
sup(text: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
130
|
+
kind: 'span';
|
|
131
|
+
}>, 'kind' | 'text' | 'baselineShift'>>): RichLabelBuilder;
|
|
132
|
+
sub(text: string, opts?: Partial<Omit<Extract<RichTextToken, {
|
|
133
|
+
kind: 'span';
|
|
134
|
+
}>, 'kind' | 'text' | 'baselineShift'>>): RichLabelBuilder;
|
|
135
|
+
newline(): RichLabelBuilder;
|
|
136
|
+
build(): RichText;
|
|
53
137
|
}
|
|
54
138
|
interface NodeBuilder {
|
|
55
139
|
at(x: number, y: number): NodeBuilder;
|
|
@@ -79,11 +163,54 @@ interface NodeBuilder {
|
|
|
79
163
|
star(points: number, outerR: number, innerR?: number): NodeBuilder;
|
|
80
164
|
trapezoid(topW: number, bottomW: number, h: number): NodeBuilder;
|
|
81
165
|
triangle(w: number, h: number, direction?: 'up' | 'down' | 'left' | 'right'): NodeBuilder;
|
|
166
|
+
/** Embed an SVG <image> inside/around the node. */
|
|
167
|
+
image(href: string, w: number, h: number, opts?: {
|
|
168
|
+
dx?: number;
|
|
169
|
+
dy?: number;
|
|
170
|
+
position?: 'center' | 'above' | 'below' | 'left' | 'right';
|
|
171
|
+
preserveAspectRatio?: string;
|
|
172
|
+
}): NodeBuilder;
|
|
173
|
+
image(href: string, opts: {
|
|
174
|
+
w: number;
|
|
175
|
+
h: number;
|
|
176
|
+
dx?: number;
|
|
177
|
+
dy?: number;
|
|
178
|
+
position?: 'center' | 'above' | 'below' | 'left' | 'right';
|
|
179
|
+
preserveAspectRatio?: string;
|
|
180
|
+
}): NodeBuilder;
|
|
181
|
+
/** Render a registered SVG icon inside/around the node. */
|
|
182
|
+
icon(id: string, opts: {
|
|
183
|
+
size: number;
|
|
184
|
+
color?: string;
|
|
185
|
+
dx?: number;
|
|
186
|
+
dy?: number;
|
|
187
|
+
position?: 'center' | 'above' | 'below' | 'left' | 'right';
|
|
188
|
+
}): NodeBuilder;
|
|
189
|
+
/** Render inline SVG content inside/around the node. */
|
|
190
|
+
svgContent(content: string, w: number, h: number, opts?: {
|
|
191
|
+
dx?: number;
|
|
192
|
+
dy?: number;
|
|
193
|
+
position?: 'center' | 'above' | 'below' | 'left' | 'right';
|
|
194
|
+
}): NodeBuilder;
|
|
195
|
+
svgContent(content: string, opts: {
|
|
196
|
+
w: number;
|
|
197
|
+
h: number;
|
|
198
|
+
dx?: number;
|
|
199
|
+
dy?: number;
|
|
200
|
+
position?: 'center' | 'above' | 'below' | 'left' | 'right';
|
|
201
|
+
}): NodeBuilder;
|
|
82
202
|
label(text: string, opts?: Partial<NodeLabel>): NodeBuilder;
|
|
203
|
+
/**
|
|
204
|
+
* Create a rich text label (mixed formatting) using nested SVG <tspan> spans.
|
|
205
|
+
*
|
|
206
|
+
* Note: Rich labels currently support explicit newlines via `l.newline()`.
|
|
207
|
+
*/
|
|
208
|
+
richLabel(cb: (l: RichLabelBuilder) => unknown, opts?: Partial<Omit<NodeLabel, 'text' | 'rich'>>): NodeBuilder;
|
|
83
209
|
fill(color: string): NodeBuilder;
|
|
84
210
|
stroke(color: string, width?: number): NodeBuilder;
|
|
85
211
|
opacity(value: number): NodeBuilder;
|
|
86
212
|
class(name: string): NodeBuilder;
|
|
213
|
+
zIndex(value: number): NodeBuilder;
|
|
87
214
|
animate(type: string, config?: AnimationConfig): NodeBuilder;
|
|
88
215
|
animate(cb: (anim: AnimationBuilder) => unknown): NodeBuilder;
|
|
89
216
|
/** Sugar for `animate(a => a.to(...))`. */
|
|
@@ -104,12 +231,14 @@ interface NodeBuilder {
|
|
|
104
231
|
parent(parentId: string): NodeBuilder;
|
|
105
232
|
done(): VizBuilder;
|
|
106
233
|
node(id: string): NodeBuilder;
|
|
234
|
+
node(id: string, opts: NodeOptions): VizBuilder;
|
|
107
235
|
edge(from: string, to: string, id?: string): EdgeBuilder;
|
|
236
|
+
edge(from: string, to: string, opts: EdgeOptions): VizBuilder;
|
|
108
237
|
overlay(cb: (overlay: OverlayBuilder) => unknown): VizBuilder;
|
|
109
238
|
overlay<K extends OverlayId>(id: K, params: OverlayParams<K>, key?: string): VizBuilder;
|
|
110
239
|
overlay<T>(id: string, params: T, key?: string): VizBuilder;
|
|
111
240
|
build(): VizScene;
|
|
112
|
-
svg(): string;
|
|
241
|
+
svg(opts?: SvgExportOptions): string;
|
|
113
242
|
}
|
|
114
243
|
interface EdgeBuilder {
|
|
115
244
|
straight(): EdgeBuilder;
|
|
@@ -118,6 +247,12 @@ interface EdgeBuilder {
|
|
|
118
247
|
routing(mode: EdgeRouting): EdgeBuilder;
|
|
119
248
|
via(x: number, y: number): EdgeBuilder;
|
|
120
249
|
label(text: string, opts?: Partial<EdgeLabel>): EdgeBuilder;
|
|
250
|
+
/**
|
|
251
|
+
* Create a rich text label (mixed formatting) using nested SVG <tspan> spans.
|
|
252
|
+
*
|
|
253
|
+
* Note: Rich labels currently support explicit newlines via `l.newline()`.
|
|
254
|
+
*/
|
|
255
|
+
richLabel(cb: (l: RichLabelBuilder) => unknown, opts?: Partial<Omit<EdgeLabel, 'text' | 'rich'>>): EdgeBuilder;
|
|
121
256
|
/**
|
|
122
257
|
* Set arrow markers. Convenience method.
|
|
123
258
|
* - `arrow(true)` or `arrow()` sets markerEnd to 'arrow'
|
|
@@ -142,22 +277,42 @@ interface EdgeBuilder {
|
|
|
142
277
|
stroke(color: string, width?: number): EdgeBuilder;
|
|
143
278
|
/** Sets the opacity of the edge. */
|
|
144
279
|
opacity(value: number): EdgeBuilder;
|
|
280
|
+
/** Apply a dashed stroke pattern (`8, 4`). */
|
|
281
|
+
dashed(): EdgeBuilder;
|
|
282
|
+
/** Apply a dotted stroke pattern (`2, 4`). */
|
|
283
|
+
dotted(): EdgeBuilder;
|
|
284
|
+
/** Apply a custom SVG `stroke-dasharray` value, or a preset name (`'dashed'`, `'dotted'`, `'dash-dot'`). */
|
|
285
|
+
dash(pattern: 'solid' | 'dashed' | 'dotted' | 'dash-dot' | string): EdgeBuilder;
|
|
145
286
|
class(name: string): EdgeBuilder;
|
|
146
287
|
hitArea(px: number): EdgeBuilder;
|
|
147
288
|
animate(type: string, config?: AnimationConfig): EdgeBuilder;
|
|
148
289
|
animate(cb: (anim: AnimationBuilder) => unknown): EdgeBuilder;
|
|
149
290
|
/** Sugar for `animate(a => a.to(...))`. */
|
|
150
291
|
animateTo(props: AnimatableProps, opts: TweenOptions): EdgeBuilder;
|
|
292
|
+
/** Attach arbitrary consumer-defined metadata to the edge. */
|
|
293
|
+
meta(meta: Record<string, unknown>): EdgeBuilder;
|
|
151
294
|
data(payload: unknown): EdgeBuilder;
|
|
152
295
|
onClick(handler: (id: string, edge: VizEdge) => void): EdgeBuilder;
|
|
296
|
+
/**
|
|
297
|
+
* For self-loops: which side the loop exits from.
|
|
298
|
+
* @default 'top'
|
|
299
|
+
*/
|
|
300
|
+
loopSide(side: 'top' | 'right' | 'bottom' | 'left'): EdgeBuilder;
|
|
301
|
+
/**
|
|
302
|
+
* For self-loops: how far the loop extends from the shape boundary.
|
|
303
|
+
* @default 30
|
|
304
|
+
*/
|
|
305
|
+
loopSize(size: number): EdgeBuilder;
|
|
153
306
|
done(): VizBuilder;
|
|
154
307
|
node(id: string): NodeBuilder;
|
|
308
|
+
node(id: string, opts: NodeOptions): VizBuilder;
|
|
155
309
|
edge(from: string, to: string, id?: string): EdgeBuilder;
|
|
310
|
+
edge(from: string, to: string, opts: EdgeOptions): VizBuilder;
|
|
156
311
|
overlay(cb: (overlay: OverlayBuilder) => unknown): VizBuilder;
|
|
157
312
|
overlay<K extends OverlayId>(id: K, params: OverlayParams<K>, key?: string): VizBuilder;
|
|
158
313
|
overlay<T>(id: string, params: T, key?: string): VizBuilder;
|
|
159
314
|
build(): VizScene;
|
|
160
|
-
svg(): string;
|
|
315
|
+
svg(opts?: SvgExportOptions): string;
|
|
161
316
|
}
|
|
162
317
|
export declare function viz(): VizBuilder;
|
|
163
318
|
export {};
|