@ts-graphviz/react 0.9.0 → 0.10.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 +76 -0
- package/LICENSE +1 -1
- package/README.md +25 -61
- package/example/example.tsx +14 -12
- package/lib/react.cjs +457 -0
- package/lib/react.d.ts +230 -0
- package/lib/react.js +457 -0
- package/package.json +55 -65
- package/src/components/Digraph.spec.tsx +18 -0
- package/src/components/Digraph.tsx +41 -0
- package/src/components/Edge.tsx +17 -0
- package/src/components/Graph.spec.tsx +18 -0
- package/src/components/Graph.tsx +36 -0
- package/src/components/GraphPortal.tsx +22 -0
- package/src/components/Node.spec.tsx +101 -0
- package/src/components/Node.tsx +21 -0
- package/src/components/Subgraph.tsx +30 -0
- package/src/contexts/CurrentGraph.ts +5 -0
- package/src/contexts/GraphContainer.ts +5 -0
- package/src/contexts/GraphMap.ts +5 -0
- package/src/contexts/GraphvizContext.ts +11 -0
- package/src/hooks/__tests__/wrapper.tsx +58 -0
- package/src/hooks/useCurrentGraph.spec.ts +56 -0
- package/src/hooks/useCurrentGraph.ts +18 -0
- package/src/hooks/useDigraph.spec.ts +15 -0
- package/src/hooks/useDigraph.ts +33 -0
- package/src/hooks/useEdge.spec.ts +46 -0
- package/src/hooks/useEdge.ts +35 -0
- package/src/hooks/useGraph.spec.ts +15 -0
- package/src/hooks/useGraph.ts +33 -0
- package/src/hooks/useGraphAttributes.ts +32 -0
- package/src/hooks/useGraphContainer.spec.ts +45 -0
- package/src/hooks/useGraphContainer.ts +10 -0
- package/src/hooks/useGraphMap.ts +7 -0
- package/src/hooks/useGraphvizContext.spec.ts +26 -0
- package/src/hooks/useGraphvizContext.ts +16 -0
- package/src/hooks/useHasAttributes.ts +16 -0
- package/src/hooks/useHasComment.ts +8 -0
- package/src/hooks/useNode.spec.ts +16 -0
- package/src/hooks/useNode.ts +29 -0
- package/src/hooks/useRenderedID.spec.tsx +28 -0
- package/src/hooks/useRenderedID.ts +6 -0
- package/src/hooks/useSubgraph.spec.ts +41 -0
- package/src/hooks/useSubgraph.ts +39 -0
- package/src/react.ts +16 -0
- package/src/reconciler.ts +272 -0
- package/src/render.test.tsx +71 -0
- package/src/render.ts +142 -0
- package/src/renderHTMLLike.ts +9 -0
- package/src/renderId.ts +9 -0
- package/src/types.ts +107 -0
- package/tsconfig.json +8 -0
- package/typedoc.json +5 -0
- package/vite.config.ts +31 -0
- package/.all-contributorsrc +0 -47
- package/.eslintignore +0 -2
- package/lib/index.d.ts +0 -368
- package/lib/index.js +0 -1
- package/lib/index.mjs +0 -1
- package/rollup.config.js +0 -55
package/src/render.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { type ReactElement, createElement } from 'react';
|
|
2
|
+
import { type GraphBaseModel, type RootGraphModel, toDot } from 'ts-graphviz';
|
|
3
|
+
|
|
4
|
+
import { CurrentGraph } from './contexts/CurrentGraph.js';
|
|
5
|
+
import { GraphContainer } from './contexts/GraphContainer.js';
|
|
6
|
+
import { GraphMap } from './contexts/GraphMap.js';
|
|
7
|
+
import { type Context, GraphvizContext } from './contexts/GraphvizContext.js';
|
|
8
|
+
import { reconciler } from './reconciler.js';
|
|
9
|
+
|
|
10
|
+
const noop = (): void => undefined;
|
|
11
|
+
|
|
12
|
+
function clusterMap(
|
|
13
|
+
graph?: GraphBaseModel,
|
|
14
|
+
map: Map<string, GraphBaseModel> = new Map(),
|
|
15
|
+
): Map<string, GraphBaseModel> {
|
|
16
|
+
if (graph) {
|
|
17
|
+
if (graph.id) {
|
|
18
|
+
map.set(graph.id, graph);
|
|
19
|
+
}
|
|
20
|
+
for (const s of graph.subgraphs) {
|
|
21
|
+
clusterMap(s, map);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return map;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Convert the given element to Graphviz model.
|
|
29
|
+
*
|
|
30
|
+
* @example Example of giving a cluster as a container with the second argument.
|
|
31
|
+
*
|
|
32
|
+
* ```tsx
|
|
33
|
+
* import React, { FC } from 'react';
|
|
34
|
+
* import { digraph, toDot } from 'ts-graphviz';
|
|
35
|
+
* import { Node, Subgraph, render, Edge } from '@ts-graphviz/react';
|
|
36
|
+
*
|
|
37
|
+
* const Example: FC = () => (
|
|
38
|
+
* <>
|
|
39
|
+
* <Node id="a" />
|
|
40
|
+
*
|
|
41
|
+
* <Subgraph id="my_cluster">
|
|
42
|
+
* <Node id="b" />
|
|
43
|
+
* </Subgraph>
|
|
44
|
+
* <Edge targets={['b', 'a']} />
|
|
45
|
+
* </>
|
|
46
|
+
* );
|
|
47
|
+
*
|
|
48
|
+
* const G = digraph((g) => render(<Example />, g));
|
|
49
|
+
* console.log(toDot(G));
|
|
50
|
+
* // digraph {
|
|
51
|
+
* // "a";
|
|
52
|
+
* // subgraph "my_cluster" {
|
|
53
|
+
* // "b";
|
|
54
|
+
* // }
|
|
55
|
+
* // "b" -> "a";
|
|
56
|
+
* // }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function render<T extends GraphBaseModel>(
|
|
60
|
+
element: ReactElement,
|
|
61
|
+
container?: T,
|
|
62
|
+
): T {
|
|
63
|
+
const context: Context<T> = { container };
|
|
64
|
+
reconciler.updateContainer(
|
|
65
|
+
createElement(
|
|
66
|
+
GraphvizContext.Provider,
|
|
67
|
+
{ value: context },
|
|
68
|
+
createElement(
|
|
69
|
+
GraphMap.Provider,
|
|
70
|
+
{ value: clusterMap(container) },
|
|
71
|
+
createElement(
|
|
72
|
+
GraphContainer.Provider,
|
|
73
|
+
{ value: container ?? null },
|
|
74
|
+
container
|
|
75
|
+
? createElement(
|
|
76
|
+
CurrentGraph.Provider,
|
|
77
|
+
{ value: container },
|
|
78
|
+
element,
|
|
79
|
+
)
|
|
80
|
+
: element,
|
|
81
|
+
),
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
reconciler.createContainer(
|
|
85
|
+
{},
|
|
86
|
+
0,
|
|
87
|
+
null,
|
|
88
|
+
true,
|
|
89
|
+
null,
|
|
90
|
+
'@ts-graphviz/react',
|
|
91
|
+
noop,
|
|
92
|
+
null,
|
|
93
|
+
),
|
|
94
|
+
null,
|
|
95
|
+
noop,
|
|
96
|
+
);
|
|
97
|
+
if (!context.container) {
|
|
98
|
+
throw Error(
|
|
99
|
+
'There are no clusters of container(Subgraph, Digraph, Graph).',
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
return context.container;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Converts the given element to DOT language and returns it.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
*
|
|
110
|
+
* ```tsx
|
|
111
|
+
* import React, { FC } from 'react';
|
|
112
|
+
* import { Digraph, Node, Subgraph, renderToDot, Edge } from '@ts-graphviz/react';
|
|
113
|
+
*
|
|
114
|
+
* const Example: FC = () => (
|
|
115
|
+
* <Digraph>
|
|
116
|
+
* <Node id="a" />
|
|
117
|
+
* <Subgraph id="my_cluster">
|
|
118
|
+
* <Node id="b" />
|
|
119
|
+
* </Subgraph>
|
|
120
|
+
* <Edge targets={['b', 'a']} />
|
|
121
|
+
* </Digraph>
|
|
122
|
+
* );
|
|
123
|
+
*
|
|
124
|
+
* const dot = renderToDot(<Example />);
|
|
125
|
+
* console.log(dot);
|
|
126
|
+
* // digraph {
|
|
127
|
+
* // "a";
|
|
128
|
+
* // subgraph "my_cluster" {
|
|
129
|
+
* // "b";
|
|
130
|
+
* // }
|
|
131
|
+
* // "b" -> "a";
|
|
132
|
+
* // }
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @returns Rendered dot string
|
|
136
|
+
*/
|
|
137
|
+
export function renderToDot(
|
|
138
|
+
element: ReactElement,
|
|
139
|
+
container?: RootGraphModel,
|
|
140
|
+
): string {
|
|
141
|
+
return toDot(render(element, container));
|
|
142
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import { renderToStaticMarkup } from 'react-dom/server';
|
|
3
|
+
|
|
4
|
+
export function renderHTMLLike(label?: ReactElement): string {
|
|
5
|
+
const htmlLike = renderToStaticMarkup(label)
|
|
6
|
+
.replace(/<dot:port>(.+?)<\/dot:port>/gi, '<$1>')
|
|
7
|
+
.replace(/<(\/?)dot:([a-z-]+)/gi, (_, $1, $2) => `<${$1}${$2}`);
|
|
8
|
+
return `<${htmlLike}>`;
|
|
9
|
+
}
|
package/src/renderId.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ReactElement, isValidElement } from 'react';
|
|
2
|
+
import { renderHTMLLike } from './renderHTMLLike.js';
|
|
3
|
+
|
|
4
|
+
export function renderId<T>(id?: ReactElement<T> | string): string | undefined {
|
|
5
|
+
if (isValidElement(id)) {
|
|
6
|
+
return renderHTMLLike(id);
|
|
7
|
+
}
|
|
8
|
+
return id;
|
|
9
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
EdgeAttributesObject,
|
|
3
|
+
EdgeTargetLikeTuple,
|
|
4
|
+
GraphAttributesObject,
|
|
5
|
+
HTMLLikeLabel,
|
|
6
|
+
HasComment,
|
|
7
|
+
NodeAttributesObject,
|
|
8
|
+
SubgraphAttributesObject,
|
|
9
|
+
} from '@ts-graphviz/common';
|
|
10
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
11
|
+
|
|
12
|
+
/** Common attribute values of objects under cluster */
|
|
13
|
+
export interface GraphBaseAttributesProps {
|
|
14
|
+
/** Attribute value for Edges */
|
|
15
|
+
edge?: EdgeAttributesObject;
|
|
16
|
+
/** Attribute value for Nodes */
|
|
17
|
+
node?: NodeAttributesObject;
|
|
18
|
+
/** Attribute value for Graphs */
|
|
19
|
+
graph?: SubgraphAttributesObject;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Options for RootGraph */
|
|
23
|
+
export interface RootGraphOptions
|
|
24
|
+
extends GraphAttributesObject,
|
|
25
|
+
GraphBaseAttributesProps {
|
|
26
|
+
/** Cluster id */
|
|
27
|
+
id?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Options for Subgraph */
|
|
31
|
+
export interface SubgraphOptions
|
|
32
|
+
extends SubgraphAttributesObject,
|
|
33
|
+
GraphBaseAttributesProps,
|
|
34
|
+
HasComment {
|
|
35
|
+
/** Cluster id */
|
|
36
|
+
id?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Options for Edge */
|
|
40
|
+
export interface EdgeOptions extends EdgeAttributesObject {}
|
|
41
|
+
|
|
42
|
+
/** Options for Node */
|
|
43
|
+
export interface NodeOptions extends NodeAttributesObject {}
|
|
44
|
+
|
|
45
|
+
/** Props for RootGraph component */
|
|
46
|
+
export interface RootGraphProps extends Omit<RootGraphOptions, 'label'> {
|
|
47
|
+
label?: ReactElement | string;
|
|
48
|
+
children?: ReactNode;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Props for Edge component */
|
|
52
|
+
export interface EdgeProps extends Omit<EdgeOptions, 'label'> {
|
|
53
|
+
/** Edge targets */
|
|
54
|
+
targets: EdgeTargetLikeTuple;
|
|
55
|
+
/** Edge label */
|
|
56
|
+
label?: ReactElement | string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Props for Node component */
|
|
60
|
+
export interface NodeProps extends Omit<NodeOptions, 'label' | 'xlabel'> {
|
|
61
|
+
/** Node id */
|
|
62
|
+
id: string;
|
|
63
|
+
/** Node label */
|
|
64
|
+
label?: ReactElement | string;
|
|
65
|
+
/** Node xlabel */
|
|
66
|
+
xlabel?: ReactElement | string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Props for Subgraph component */
|
|
70
|
+
export interface SubgraphProps extends Omit<SubgraphOptions, 'label'> {
|
|
71
|
+
/** Subgraph label */
|
|
72
|
+
label?: ReactElement | string;
|
|
73
|
+
children?: ReactNode;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Props for GraphPortal component */
|
|
77
|
+
export interface GraphPortalProps {
|
|
78
|
+
/**
|
|
79
|
+
* id of the cluster you want to target for the portal.
|
|
80
|
+
* If not specified, target the cluster that is the container to the portal.
|
|
81
|
+
*/
|
|
82
|
+
id?: string;
|
|
83
|
+
children?: ReactNode;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
declare global {
|
|
87
|
+
namespace JSX {
|
|
88
|
+
interface IntrinsicElements {
|
|
89
|
+
'dot:port': { children: string };
|
|
90
|
+
'dot:table': HTMLLikeLabel.TableAttributes & { children?: ReactNode };
|
|
91
|
+
'dot:tr': HTMLLikeLabel.TrAttributes & { children?: ReactNode };
|
|
92
|
+
'dot:td': HTMLLikeLabel.TdAttributes & { children?: ReactNode };
|
|
93
|
+
'dot:font': HTMLLikeLabel.FontAttributes & { children?: ReactNode };
|
|
94
|
+
'dot:br': HTMLLikeLabel.BrAttributes;
|
|
95
|
+
'dot:img': HTMLLikeLabel.ImgAttributes;
|
|
96
|
+
'dot:i': HTMLLikeLabel.IAttributes & { children?: ReactNode };
|
|
97
|
+
'dot:b': HTMLLikeLabel.BAttributes & { children?: ReactNode };
|
|
98
|
+
'dot:u': HTMLLikeLabel.UAttributes & { children?: ReactNode };
|
|
99
|
+
'dot:o': HTMLLikeLabel.OAttributes & { children?: ReactNode };
|
|
100
|
+
'dot:sub': HTMLLikeLabel.SubAttributes & { children?: ReactNode };
|
|
101
|
+
'dot:sup': HTMLLikeLabel.SupAttributes & { children?: ReactNode };
|
|
102
|
+
'dot:s': HTMLLikeLabel.SAttributes & { children?: ReactNode };
|
|
103
|
+
'dot:hr': HTMLLikeLabel.HrAttributes;
|
|
104
|
+
'dot:vr': HTMLLikeLabel.VrAttributes;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
package/tsconfig.json
ADDED
package/typedoc.json
ADDED
package/vite.config.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import dts from 'vite-plugin-dts';
|
|
2
|
+
import { defineConfig } from 'vitest/config';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
build: {
|
|
6
|
+
target: 'ES2022',
|
|
7
|
+
outDir: './lib',
|
|
8
|
+
minify: false,
|
|
9
|
+
lib: {
|
|
10
|
+
entry: {
|
|
11
|
+
react: './src/react.ts',
|
|
12
|
+
},
|
|
13
|
+
formats: ['es', 'cjs'],
|
|
14
|
+
},
|
|
15
|
+
rollupOptions: {
|
|
16
|
+
external: [
|
|
17
|
+
'react',
|
|
18
|
+
'react/jsx-runtime',
|
|
19
|
+
'react-dom',
|
|
20
|
+
'react-dom/server',
|
|
21
|
+
'react-reconciler',
|
|
22
|
+
'ts-graphviz',
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
plugins: [
|
|
27
|
+
dts({
|
|
28
|
+
rollupTypes: true,
|
|
29
|
+
}),
|
|
30
|
+
],
|
|
31
|
+
});
|
package/.all-contributorsrc
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"files": [
|
|
3
|
-
"README.md"
|
|
4
|
-
],
|
|
5
|
-
"imageSize": 100,
|
|
6
|
-
"commit": false,
|
|
7
|
-
"contributors": [
|
|
8
|
-
{
|
|
9
|
-
"login": "kamiazya",
|
|
10
|
-
"name": "Yuki Yamazaki",
|
|
11
|
-
"avatar_url": "https://avatars0.githubusercontent.com/u/35218186?v=4",
|
|
12
|
-
"profile": "http://blog.kamiazya.tech/",
|
|
13
|
-
"contributions": [
|
|
14
|
-
"code",
|
|
15
|
-
"test",
|
|
16
|
-
"ideas",
|
|
17
|
-
"doc"
|
|
18
|
-
]
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"login": "nagasawaryoya",
|
|
22
|
-
"name": "nagasawaryoya",
|
|
23
|
-
"avatar_url": "https://avatars.githubusercontent.com/u/53528726?v=4",
|
|
24
|
-
"profile": "https://github.com/nagasawaryoya",
|
|
25
|
-
"contributions": [
|
|
26
|
-
"code",
|
|
27
|
-
"test"
|
|
28
|
-
]
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"login": "tokidrill",
|
|
32
|
-
"name": "YukiSasaki",
|
|
33
|
-
"avatar_url": "https://avatars.githubusercontent.com/u/42460318?v=4",
|
|
34
|
-
"profile": "https://github.com/tokidrill",
|
|
35
|
-
"contributions": [
|
|
36
|
-
"code",
|
|
37
|
-
"test"
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
],
|
|
41
|
-
"contributorsPerLine": 7,
|
|
42
|
-
"projectName": "react",
|
|
43
|
-
"projectOwner": "ts-graphviz",
|
|
44
|
-
"repoType": "github",
|
|
45
|
-
"repoHost": "https://github.com",
|
|
46
|
-
"skipCi": true
|
|
47
|
-
}
|
package/.eslintignore
DELETED