vizcraft 0.1.3 → 0.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # vizcraft
2
2
 
3
+ ## 0.1.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ecb5ade`](https://github.com/ChipiKaf/vizcraft/commit/ecb5adef774e30589a0714699ccdb7839530bd50) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - update docs with correct code snippets
8
+
9
+ ## 0.1.4
10
+
11
+ ### Patch Changes
12
+
13
+ - [`10926fc`](https://github.com/ChipiKaf/vizcraft/commit/10926fcce211d00dfba2697eaac62948ac0ef69d) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - update readme
14
+
3
15
  ## 0.1.3
4
16
 
5
17
  ### Patch Changes
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # VizCraft
2
+
3
+ **A declarative, builder-based library for creating animated SVG network visualizations and algorithm demos.**
4
+
5
+ VizCraft is designed to make creating beautiful, animated node-link diagrams and complex visualizations intuitive and powerful. Whether you are building an educational tool, explaining an algorithm, or just need a great looking graph, VizCraft provides the primitives you need.
6
+
7
+ ## ✨ Features
8
+
9
+ - **Fluent Builder API**: Define your visualization scene using a readable, chainable API.
10
+ - **Grid System**: Built-in 2D grid system for easy, structured layout of nodes.
11
+ - **Declarative Animations**: Animate layout changes, edge flow, and node states with a simple declarative config.
12
+ - **Framework Agnostic**: The core logic is pure TypeScript and can be used with any framework or Vanilla JS.
13
+ - **Custom Overlays**: Create complex, custom UI elements that float on top of your visualization.
14
+
15
+ ## 📦 Installation
16
+
17
+ ```bash
18
+ npm install vizcraft
19
+ # or
20
+ pnpm add vizcraft
21
+ # or
22
+ yarn add vizcraft
23
+ ```
24
+
25
+ ## 🚀 Getting Started
26
+
27
+ You can use the core library directly to generate SVG content or mount to a DOM element.
28
+
29
+ ```typescript
30
+ import { viz } from 'vizcraft';
31
+
32
+ const builder = viz().view(800, 600);
33
+
34
+ builder
35
+ .view(500, 500)
36
+ .node('a')
37
+ .at(100, 100)
38
+ .circle(15)
39
+ .label('A')
40
+ .node('b')
41
+ .at(400, 100)
42
+ .circle(15)
43
+ .label('B')
44
+ .edge('a', 'b')
45
+ .arrow();
46
+
47
+ const container = document.getElementById('viz-basic');
48
+ if (container) builder.mount(container);
49
+ ```
50
+
51
+ ## 📖 Core Concepts
52
+
53
+ ### The Builder (`VizBuilder`)
54
+
55
+ The heart of VizCraft is the `VizBuilder`. It allows you to construct a `VizScene` which acts as the blueprint for your visualization.
56
+
57
+ ```typescript
58
+ b.view(width, height) // Set the coordinate space
59
+ .grid(cols, rows) // (Optional) Define layout grid
60
+ .node(id) // Start defining a node
61
+ .edge(from, to); // Start defining an edge
62
+ ```
63
+
64
+ ### Nodes
65
+
66
+ Nodes are the primary entities in your graph. They can have shapes, labels, and styles.
67
+
68
+ ```typescript
69
+ b.node('n1')
70
+ .at(x, y) // Absolute position
71
+ // OR
72
+ .cell(col, row) // Grid position
73
+ .circle(radius) // Shape definition
74
+ .label('Text', { dy: 5 }) // Label with offset
75
+ .class('css-class') // Custom CSS class
76
+ .data({ ... }) // Attach custom data
77
+ ```
78
+
79
+ ### Edges
80
+
81
+ Edges connect nodes and can be styled, directed, or animated.
82
+
83
+ ```typescript
84
+ b.edge('n1', 'n2')
85
+ .arrow() // Add an arrowhead
86
+ .straight() // (Default) Straight line
87
+ .label('Connection')
88
+ .animate('flow'); // Add animation
89
+ ```
90
+
91
+ ### Animations
92
+
93
+ VizCraft supports declarative animations. You define _what_ happens, and the renderer handles the interpolation.
94
+
95
+ - **`stream`**: Particles flowing along an edge.
96
+ - **`pulse`**: Rhythmic scaling or opacity changes.
97
+ - **Transition**: Moving a node from one position to another.
98
+
99
+ ## 🎨 Styling
100
+
101
+ VizCraft generates standard SVG elements with predictable classes, making it easy to style with CSS.
102
+
103
+ ```css
104
+ /* Custom node style */
105
+ .viz-node-shape {
106
+ fill: #fff;
107
+ stroke: #333;
108
+ stroke-width: 2px;
109
+ }
110
+
111
+ /* Specific node class */
112
+ .my-node .viz-node-shape {
113
+ fill: #ff6b6b;
114
+ }
115
+
116
+ /* Edge styling */
117
+ .viz-edge {
118
+ stroke: #ccc;
119
+ stroke-width: 2;
120
+ }
121
+ ```
122
+
123
+ ## 🤝 Contributing
124
+
125
+ Contributions are welcome! This is a monorepo managed with Turbo.
126
+
127
+ 1. Clone the repo
128
+ 2. Install dependencies: `pnpm install`
129
+ 3. Run dev server: `pnpm dev`
130
+
131
+ ## 📄 License
132
+
133
+ MIT License © Chipili Kafwilo
package/dist/builder.d.ts CHANGED
@@ -24,6 +24,9 @@ interface NodeBuilder {
24
24
  rect(w: number, h: number, rx?: number): NodeBuilder;
25
25
  diamond(w: number, h: number): NodeBuilder;
26
26
  label(text: string, opts?: Partial<NodeLabel>): NodeBuilder;
27
+ fill(color: string): NodeBuilder;
28
+ stroke(color: string, width?: number): NodeBuilder;
29
+ opacity(value: number): NodeBuilder;
27
30
  class(name: string): NodeBuilder;
28
31
  animate(type: string, config?: AnimationConfig): NodeBuilder;
29
32
  data(payload: unknown): NodeBuilder;
@@ -39,6 +42,7 @@ interface EdgeBuilder {
39
42
  straight(): EdgeBuilder;
40
43
  label(text: string, opts?: Partial<EdgeLabel>): EdgeBuilder;
41
44
  arrow(enabled?: boolean): EdgeBuilder;
45
+ connect(anchor: 'center' | 'boundary'): EdgeBuilder;
42
46
  class(name: string): EdgeBuilder;
43
47
  hitArea(px: number): EdgeBuilder;
44
48
  animate(type: string, config?: AnimationConfig): EdgeBuilder;
package/dist/builder.js CHANGED
@@ -1,6 +1,63 @@
1
1
  import { DEFAULT_VIZ_CSS } from './styles';
2
2
  import { defaultCoreAnimationRegistry } from './animations';
3
3
  import { defaultCoreOverlayRegistry } from './overlays';
4
+ function setSvgAttributes(el, attrs) {
5
+ Object.entries(attrs).forEach(([key, value]) => {
6
+ if (value === undefined) {
7
+ el.removeAttribute(key);
8
+ }
9
+ else {
10
+ el.setAttribute(key, String(value));
11
+ }
12
+ });
13
+ }
14
+ function svgAttributeString(attrs) {
15
+ return Object.entries(attrs)
16
+ .filter(([, value]) => value !== undefined)
17
+ .map(([key, value]) => ` ${key}="${String(value)}"`)
18
+ .join('');
19
+ }
20
+ function computeNodeAnchor(node, target, anchor) {
21
+ if (anchor === 'center') {
22
+ return { x: node.pos.x, y: node.pos.y };
23
+ }
24
+ const dx = target.x - node.pos.x;
25
+ const dy = target.y - node.pos.y;
26
+ if (dx === 0 && dy === 0) {
27
+ return { x: node.pos.x, y: node.pos.y };
28
+ }
29
+ if (node.shape.kind === 'circle') {
30
+ const dist = Math.hypot(dx, dy) || 1;
31
+ const scale = node.shape.r / dist;
32
+ return {
33
+ x: node.pos.x + dx * scale,
34
+ y: node.pos.y + dy * scale,
35
+ };
36
+ }
37
+ if (node.shape.kind === 'rect') {
38
+ const hw = node.shape.w / 2;
39
+ const hh = node.shape.h / 2;
40
+ const scale = Math.min(hw / Math.abs(dx || 1e-6), hh / Math.abs(dy || 1e-6));
41
+ return {
42
+ x: node.pos.x + dx * scale,
43
+ y: node.pos.y + dy * scale,
44
+ };
45
+ }
46
+ const hw = node.shape.w / 2;
47
+ const hh = node.shape.h / 2;
48
+ const denom = Math.abs(dx) / hw + Math.abs(dy) / hh;
49
+ const scale = denom === 0 ? 0 : 1 / denom;
50
+ return {
51
+ x: node.pos.x + dx * scale,
52
+ y: node.pos.y + dy * scale,
53
+ };
54
+ }
55
+ function computeEdgeEndpoints(start, end, edge) {
56
+ const anchor = edge.anchor ?? 'boundary';
57
+ const startAnchor = computeNodeAnchor(start, end.pos, anchor);
58
+ const endAnchor = computeNodeAnchor(end, start.pos, anchor);
59
+ return { start: startAnchor, end: endAnchor };
60
+ }
4
61
  class VizBuilderImpl {
5
62
  _viewBox = { w: 800, h: 600 };
6
63
  _nodes = new Map();
@@ -217,12 +274,13 @@ class VizBuilderImpl {
217
274
  });
218
275
  }
219
276
  group.setAttribute('class', classes);
277
+ const endpoints = computeEdgeEndpoints(start, end, edge);
220
278
  // Update Line
221
279
  const line = group.querySelector('.viz-edge');
222
- line.setAttribute('x1', String(start.pos.x));
223
- line.setAttribute('y1', String(start.pos.y));
224
- line.setAttribute('x2', String(end.pos.x));
225
- line.setAttribute('y2', String(end.pos.y));
280
+ line.setAttribute('x1', String(endpoints.start.x));
281
+ line.setAttribute('y1', String(endpoints.start.y));
282
+ line.setAttribute('x2', String(endpoints.end.x));
283
+ line.setAttribute('y2', String(endpoints.end.y));
226
284
  line.setAttribute('stroke', 'currentColor');
227
285
  if (edge.markerEnd === 'arrow') {
228
286
  line.setAttribute('marker-end', 'url(#viz-arrow)');
@@ -236,10 +294,10 @@ class VizBuilderImpl {
236
294
  if (edge.hitArea || edge.onClick) {
237
295
  const hit = document.createElementNS(svgNS, 'line');
238
296
  hit.setAttribute('class', 'viz-edge-hit'); // Add class for selection
239
- hit.setAttribute('x1', String(start.pos.x));
240
- hit.setAttribute('y1', String(start.pos.y));
241
- hit.setAttribute('x2', String(end.pos.x));
242
- hit.setAttribute('y2', String(end.pos.y));
297
+ hit.setAttribute('x1', String(endpoints.start.x));
298
+ hit.setAttribute('y1', String(endpoints.start.y));
299
+ hit.setAttribute('x2', String(endpoints.end.x));
300
+ hit.setAttribute('y2', String(endpoints.end.y));
243
301
  hit.setAttribute('stroke', 'transparent');
244
302
  hit.setAttribute('stroke-width', String(edge.hitArea || 10));
245
303
  hit.style.cursor = edge.onClick ? 'pointer' : '';
@@ -257,8 +315,8 @@ class VizBuilderImpl {
257
315
  oldLabel.remove();
258
316
  if (edge.label) {
259
317
  const text = document.createElementNS(svgNS, 'text');
260
- const mx = (start.pos.x + end.pos.x) / 2 + (edge.label.dx || 0);
261
- const my = (start.pos.y + end.pos.y) / 2 + (edge.label.dy || 0);
318
+ const mx = (endpoints.start.x + endpoints.end.x) / 2 + (edge.label.dx || 0);
319
+ const my = (endpoints.start.y + endpoints.end.y) / 2 + (edge.label.dy || 0);
262
320
  text.setAttribute('x', String(mx));
263
321
  text.setAttribute('y', String(my));
264
322
  text.setAttribute('class', `viz-edge-label ${edge.label.className || ''}`);
@@ -375,13 +433,17 @@ class VizBuilderImpl {
375
433
  const pts = `${x},${y - hh} ${x + hw},${y} ${x},${y + hh} ${x - hw},${y}`;
376
434
  shape.setAttribute('points', pts);
377
435
  }
436
+ setSvgAttributes(shape, {
437
+ fill: node.style?.fill ?? 'none',
438
+ stroke: node.style?.stroke ?? '#111',
439
+ 'stroke-width': node.style?.strokeWidth ?? 2,
440
+ opacity: node.style?.opacity,
441
+ });
378
442
  // Label (Recreate for simplicity as usually just text/pos changes)
379
443
  let label = group.querySelector('.viz-node-label');
380
444
  if (!label && node.label) {
381
445
  label = document.createElementNS(svgNS, 'text');
382
446
  label.setAttribute('class', 'viz-node-label');
383
- label.setAttribute('text-anchor', 'middle');
384
- label.setAttribute('dominant-baseline', 'middle');
385
447
  group.appendChild(label);
386
448
  }
387
449
  if (node.label) {
@@ -389,8 +451,15 @@ class VizBuilderImpl {
389
451
  const ly = y + (node.label.dy || 0);
390
452
  label.setAttribute('x', String(lx));
391
453
  label.setAttribute('y', String(ly));
454
+ label.setAttribute('text-anchor', node.label.textAnchor || 'middle');
455
+ label.setAttribute('dominant-baseline', node.label.dominantBaseline || 'middle');
392
456
  // Update class carefully to preserve 'viz-node-label'
393
457
  label.setAttribute('class', `viz-node-label ${node.label.className || ''}`);
458
+ setSvgAttributes(label, {
459
+ fill: node.label.fill,
460
+ 'font-size': node.label.fontSize,
461
+ 'font-weight': node.label.fontWeight,
462
+ });
394
463
  label.textContent = node.label.text;
395
464
  }
396
465
  else if (label) {
@@ -498,12 +567,13 @@ class VizBuilderImpl {
498
567
  });
499
568
  }
500
569
  const markerEnd = edge.markerEnd === 'arrow' ? 'marker-end="url(#viz-arrow)"' : '';
570
+ const endpoints = computeEdgeEndpoints(start, end, edge);
501
571
  svgContent += `<g class="viz-edge-group ${edge.className || ''} ${animClasses}" style="${animStyleStr}">`;
502
- svgContent += `<line x1="${start.pos.x}" y1="${start.pos.y}" x2="${end.pos.x}" y2="${end.pos.y}" class="viz-edge" ${markerEnd} stroke="currentColor" />`;
572
+ svgContent += `<line x1="${endpoints.start.x}" y1="${endpoints.start.y}" x2="${endpoints.end.x}" y2="${endpoints.end.y}" class="viz-edge" ${markerEnd} stroke="currentColor" />`;
503
573
  // Edge Label
504
574
  if (edge.label) {
505
- const mx = (start.pos.x + end.pos.x) / 2 + (edge.label.dx || 0);
506
- const my = (start.pos.y + end.pos.y) / 2 + (edge.label.dy || 0);
575
+ const mx = (endpoints.start.x + endpoints.end.x) / 2 + (edge.label.dx || 0);
576
+ const my = (endpoints.start.y + endpoints.end.y) / 2 + (edge.label.dy || 0);
507
577
  const labelClass = `viz-edge-label ${edge.label.className || ''}`;
508
578
  svgContent += `<text x="${mx}" y="${my}" class="${labelClass}" text-anchor="middle" dominant-baseline="middle">${edge.label.text}</text>`;
509
579
  }
@@ -536,25 +606,38 @@ class VizBuilderImpl {
536
606
  }
537
607
  const className = `viz-node-group ${node.className || ''} ${animClasses}`;
538
608
  svgContent += `<g class="${className}" style="${animStyleStr}">`;
609
+ const shapeStyleAttrs = svgAttributeString({
610
+ fill: node.style?.fill ?? 'none',
611
+ stroke: node.style?.stroke ?? '#111',
612
+ 'stroke-width': node.style?.strokeWidth ?? 2,
613
+ opacity: node.style?.opacity,
614
+ });
539
615
  // Shape
540
616
  if (shape.kind === 'circle') {
541
- svgContent += `<circle cx="${x}" cy="${y}" r="${shape.r}" class="viz-node-shape" />`;
617
+ svgContent += `<circle cx="${x}" cy="${y}" r="${shape.r}" class="viz-node-shape"${shapeStyleAttrs} />`;
542
618
  }
543
619
  else if (shape.kind === 'rect') {
544
- svgContent += `<rect x="${x - shape.w / 2}" y="${y - shape.h / 2}" width="${shape.w}" height="${shape.h}" rx="${shape.rx || 0}" class="viz-node-shape" />`;
620
+ svgContent += `<rect x="${x - shape.w / 2}" y="${y - shape.h / 2}" width="${shape.w}" height="${shape.h}" rx="${shape.rx || 0}" class="viz-node-shape"${shapeStyleAttrs} />`;
545
621
  }
546
622
  else if (shape.kind === 'diamond') {
547
623
  const hw = shape.w / 2;
548
624
  const hh = shape.h / 2;
549
625
  const pts = `${x},${y - hh} ${x + hw},${y} ${x},${y + hh} ${x - hw},${y}`;
550
- svgContent += `<polygon points="${pts}" class="viz-node-shape" />`;
626
+ svgContent += `<polygon points="${pts}" class="viz-node-shape"${shapeStyleAttrs} />`;
551
627
  }
552
628
  // Label
553
629
  if (node.label) {
554
630
  const lx = x + (node.label.dx || 0);
555
631
  const ly = y + (node.label.dy || 0);
556
632
  const labelClass = `viz-node-label ${node.label.className || ''}`;
557
- svgContent += `<text x="${lx}" y="${ly}" class="${labelClass}" text-anchor="middle" dominant-baseline="middle">${node.label.text}</text>`;
633
+ const labelAttrs = svgAttributeString({
634
+ fill: node.label.fill,
635
+ 'font-size': node.label.fontSize,
636
+ 'font-weight': node.label.fontWeight,
637
+ 'text-anchor': node.label.textAnchor || 'middle',
638
+ 'dominant-baseline': node.label.dominantBaseline || 'middle',
639
+ });
640
+ svgContent += `<text x="${lx}" y="${ly}" class="${labelClass}"${labelAttrs}>${node.label.text}</text>`;
558
641
  }
559
642
  svgContent += '</g>';
560
643
  });
@@ -626,6 +709,28 @@ class NodeBuilderImpl {
626
709
  this.nodeDef.label = { text, ...opts };
627
710
  return this;
628
711
  }
712
+ fill(color) {
713
+ this.nodeDef.style = {
714
+ ...(this.nodeDef.style || {}),
715
+ fill: color,
716
+ };
717
+ return this;
718
+ }
719
+ stroke(color, width) {
720
+ this.nodeDef.style = {
721
+ ...(this.nodeDef.style || {}),
722
+ stroke: color,
723
+ strokeWidth: width ?? this.nodeDef.style?.strokeWidth,
724
+ };
725
+ return this;
726
+ }
727
+ opacity(value) {
728
+ this.nodeDef.style = {
729
+ ...(this.nodeDef.style || {}),
730
+ opacity: value,
731
+ };
732
+ return this;
733
+ }
629
734
  class(name) {
630
735
  if (this.nodeDef.className) {
631
736
  this.nodeDef.className += ` ${name}`;
@@ -682,13 +787,17 @@ class EdgeBuilderImpl {
682
787
  return this;
683
788
  }
684
789
  label(text, opts) {
685
- this.edgeDef.label = { position: 'mid', text, ...opts };
790
+ this.edgeDef.label = { position: 'mid', text, dy: -10, ...opts };
686
791
  return this;
687
792
  }
688
793
  arrow(enabled = true) {
689
794
  this.edgeDef.markerEnd = enabled ? 'arrow' : 'none';
690
795
  return this;
691
796
  }
797
+ connect(anchor) {
798
+ this.edgeDef.anchor = anchor;
799
+ return this;
800
+ }
692
801
  class(name) {
693
802
  if (this.edgeDef.className) {
694
803
  this.edgeDef.className += ` ${name}`;
package/dist/types.d.ts CHANGED
@@ -20,6 +20,11 @@ export type NodeLabel = {
20
20
  dx?: number;
21
21
  dy?: number;
22
22
  className?: string;
23
+ fill?: string;
24
+ fontSize?: number | string;
25
+ fontWeight?: number | string;
26
+ textAnchor?: 'start' | 'middle' | 'end';
27
+ dominantBaseline?: string;
23
28
  };
24
29
  export type AnimationDuration = `${number}s`;
25
30
  export interface AnimationConfig {
@@ -36,6 +41,12 @@ export interface VizNode {
36
41
  pos: Vec2;
37
42
  shape: NodeShape;
38
43
  label?: NodeLabel;
44
+ style?: {
45
+ fill?: string;
46
+ stroke?: string;
47
+ strokeWidth?: number;
48
+ opacity?: number;
49
+ };
39
50
  className?: string;
40
51
  data?: unknown;
41
52
  onClick?: (id: string, node: VizNode) => void;
@@ -54,6 +65,7 @@ export interface VizEdge {
54
65
  to: string;
55
66
  label?: EdgeLabel;
56
67
  markerEnd?: 'arrow' | 'none';
68
+ anchor?: 'center' | 'boundary';
57
69
  className?: string;
58
70
  hitArea?: number;
59
71
  data?: unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vizcraft",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "A fluent, type-safe SVG scene builder for composing nodes, edges, animations, and overlays with incremental DOM updates and no framework dependency.",
5
5
  "keywords": [
6
6
  "visualization",
@@ -28,6 +28,11 @@
28
28
  "module": "./dist/index.mjs",
29
29
  "types": "./dist/index.d.ts",
30
30
  "license": "MIT",
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "CHANGELOG.md"
35
+ ],
31
36
  "devDependencies": {
32
37
  "typescript": "^5.9.3"
33
38
  },
@@ -1,4 +0,0 @@
1
-
2
- > vizcraft@0.1.3 build /home/runner/work/vizcraft/vizcraft/packages/core
3
- > tsc
4
-
package/src/animations.ts DELETED
@@ -1,53 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import type { VizNode, VizEdge, VizAnimSpec } from './types';
3
-
4
- export interface CoreAnimRendererContext<T = any> {
5
- spec: VizAnimSpec<T>;
6
- element: VizNode | VizEdge;
7
- }
8
-
9
- export interface CoreAnimRenderer<T = any> {
10
- getClass?: (ctx: CoreAnimRendererContext<T>) => string;
11
- getStyle?: (
12
- ctx: CoreAnimRendererContext<T>
13
- ) => Record<string, string | number>;
14
- }
15
-
16
- export class CoreAnimationRegistry {
17
- private nodeAnims = new Map<string, CoreAnimRenderer>();
18
- private edgeAnims = new Map<string, CoreAnimRenderer>();
19
-
20
- constructor() {}
21
-
22
- registerNode(id: string, renderer: CoreAnimRenderer) {
23
- this.nodeAnims.set(id, renderer);
24
- return this;
25
- }
26
-
27
- registerEdge(id: string, renderer: CoreAnimRenderer) {
28
- this.edgeAnims.set(id, renderer);
29
- return this;
30
- }
31
-
32
- getNodeRenderer(id: string): CoreAnimRenderer | undefined {
33
- return this.nodeAnims.get(id);
34
- }
35
-
36
- getEdgeRenderer(id: string): CoreAnimRenderer | undefined {
37
- return this.edgeAnims.get(id);
38
- }
39
- }
40
-
41
- // Default Implementations
42
- export const coreFlowAnimation: CoreAnimRenderer<{ duration?: string }> = {
43
- getClass: () => 'viz-anim-flow',
44
- getStyle: ({ spec }) => {
45
- const duration = spec.params?.duration ?? '2s';
46
- return {
47
- '--viz-anim-duration': duration,
48
- };
49
- },
50
- };
51
-
52
- export const defaultCoreAnimationRegistry =
53
- new CoreAnimationRegistry().registerEdge('flow', coreFlowAnimation);