diff --git a/src/__tests__/__snapshots__/render.test.tsx.snap b/src/__tests__/__snapshots__/render.test.tsx.snap
new file mode 100644
index 0000000..472b466
--- /dev/null
+++ b/src/__tests__/__snapshots__/render.test.tsx.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renderToDot render to container subgraph test 1`] = `
+digraph {
+ subgraph "test" {
+ "a";
+ "b";
+ "a" -> "b";
+ }
+}
+`;
diff --git a/src/__tests__/render-to-dot.spec.tsx b/src/__tests__/render-to-dot.spec.tsx
index fb41ac5..9e439a9 100644
--- a/src/__tests__/render-to-dot.spec.tsx
+++ b/src/__tests__/render-to-dot.spec.tsx
@@ -45,9 +45,4 @@ describe('renderToDot', () => {
);
expect(dot).toBeValidDotAndMatchSnapshot();
});
-
- it('render to be blank string', () => {
- const dot = renderToDot(<>>);
- expect(dot).toBe('');
- });
});
diff --git a/src/__tests__/render.test.tsx b/src/__tests__/render.test.tsx
new file mode 100644
index 0000000..ea6eb7b
--- /dev/null
+++ b/src/__tests__/render.test.tsx
@@ -0,0 +1,41 @@
+/* eslint-disable jest/expect-expect */
+import React from 'react';
+import 'jest-graphviz';
+import { digraph, toDot } from 'ts-graphviz';
+import { Edge } from '../components/Edge';
+import { Node } from '../components/Node';
+import { renderExpectToThrow } from '../components/__tests__/utils/renderExpectToThrow';
+import { NoContainerErrorMessage } from '../errors';
+import { render } from '../render';
+
+describe('renderToDot', () => {
+ describe('no container error', () => {
+ test('Fragment', () => {
+ renderExpectToThrow(<>>, NoContainerErrorMessage);
+ });
+
+ test('Node', () => {
+ renderExpectToThrow(, NoContainerErrorMessage);
+ });
+
+ test('Edge', () => {
+ renderExpectToThrow(, NoContainerErrorMessage);
+ });
+ });
+
+ it('render to container subgraph test', () => {
+ const nodes = ['a', 'b'];
+ const G = digraph();
+ const subgraph = render(
+ <>
+ {nodes.map((id) => (
+
+ ))}
+
+ >,
+ G.subgraph('test'),
+ );
+ expect(G.subgraph('test')).toEqual(subgraph);
+ expect(toDot(G)).toBeValidDotAndMatchSnapshot();
+ });
+});
diff --git a/src/components/ClusterPortal.tsx b/src/components/ClusterPortal.tsx
index 6051f7a..16b2852 100644
--- a/src/components/ClusterPortal.tsx
+++ b/src/components/ClusterPortal.tsx
@@ -1,22 +1,25 @@
import React, { FC, useContext, useMemo } from 'react';
import PropTypes from 'prop-types';
-import { Cluster } from '../contexts/Cluster';
+import { CurrentCluster } from '../contexts/CurrentCluster';
import { ClusterMap } from '../contexts/ClusterMap';
-import { useRootCluster } from '../hooks/use-root-cluster';
-import { ClusterPortalComponentProps } from '../types';
+import { useContainerCluster } from '../hooks/use-container-cluster';
+import { ClusterPortalProps } from '../types';
-export const ClusterPortal: FC = ({ children, name }) => {
- const root = useRootCluster();
+/**
+ * ClusterPortal component.
+ */
+export const ClusterPortal: FC = ({ children, id }) => {
+ const container = useContainerCluster();
const map = useContext(ClusterMap);
- const cluster = useMemo(() => (name ? map.get(name) ?? root : root), [root, map, name]);
- return {children};
+ const cluster = useMemo(() => (id ? map.get(id) ?? container : container), [container, map, id]);
+ return {children};
};
ClusterPortal.displayName = 'ClusterPortal';
ClusterPortal.defaultProps = {
- name: undefined,
+ id: undefined,
};
ClusterPortal.propTypes = {
- name: PropTypes.string,
+ id: PropTypes.string,
};
diff --git a/src/components/Digraph.tsx b/src/components/Digraph.tsx
index fd3006b..b77c5d5 100644
--- a/src/components/Digraph.tsx
+++ b/src/components/Digraph.tsx
@@ -1,22 +1,25 @@
import React, { FC, useEffect } from 'react';
import PropTypes from 'prop-types';
-import { RootCluster } from '../contexts/RootCluster';
-import { Cluster } from '../contexts/Cluster';
+import { ContainerCluster } from '../contexts/ContainerCluster';
+import { CurrentCluster } from '../contexts/CurrentCluster';
import { useDigraph } from '../hooks/use-digraph';
import { useRenderedID } from '../hooks/use-rendered-id';
-import { useRootCluster } from '../hooks/use-root-cluster';
+import { useContainerCluster } from '../hooks/use-container-cluster';
import { DuplicatedRootClusterErrorMessage } from '../errors';
import { useClusterMap } from '../hooks/use-cluster-map';
-import { RootClusterComponentProps } from '../types';
+import { RootClusterProps } from '../types';
-export const Digraph: FC = ({ children, label, ...props }) => {
- const root = useRootCluster();
- if (root !== null) {
+/**
+ * `Digraph` component.
+ */
+export const Digraph: FC = ({ children, label, ...options }) => {
+ const container = useContainerCluster();
+ if (container !== null) {
throw Error(DuplicatedRootClusterErrorMessage);
}
const renderedLabel = useRenderedID(label);
- if (renderedLabel !== undefined) Object.assign(props, { label: renderedLabel });
- const digraph = useDigraph(props);
+ if (renderedLabel !== undefined) Object.assign(options, { label: renderedLabel });
+ const digraph = useDigraph(options);
const clusters = useClusterMap();
useEffect(() => {
if (digraph.id !== undefined) {
@@ -24,9 +27,9 @@ export const Digraph: FC = ({ children, label, ...pro
}
}, [clusters, digraph]);
return (
-
- {children}
-
+
+ {children}
+
);
};
diff --git a/src/components/Edge.tsx b/src/components/Edge.tsx
index 9db88a5..e75ce65 100644
--- a/src/components/Edge.tsx
+++ b/src/components/Edge.tsx
@@ -1,14 +1,17 @@
-import React, { FC } from 'react';
+import { VFC } from 'react';
import PropTypes from 'prop-types';
import { useEdge } from '../hooks/use-edge';
import { useRenderedID } from '../hooks/use-rendered-id';
-import { EdgeComponentProps } from '../types';
+import { EdgeProps } from '../types';
-export const Edge: FC = ({ children, label, ...props }) => {
+/**
+ * `Edge` component.
+ */
+export const Edge: VFC = ({ targets, label, ...options }) => {
const renderedLabel = useRenderedID(label);
- if (renderedLabel !== undefined) Object.assign(props, { label: renderedLabel });
- useEdge(props);
- return <>{children}>;
+ if (renderedLabel !== undefined) Object.assign(options, { label: renderedLabel });
+ useEdge(targets, options);
+ return null;
};
Edge.displayName = 'Edge';
diff --git a/src/components/Graph.tsx b/src/components/Graph.tsx
index 6c038bf..f102313 100644
--- a/src/components/Graph.tsx
+++ b/src/components/Graph.tsx
@@ -1,22 +1,24 @@
import React, { FC, useEffect } from 'react';
import PropTypes from 'prop-types';
-import { RootCluster } from '../contexts/RootCluster';
-import { Cluster } from '../contexts/Cluster';
+import { ContainerCluster } from '../contexts/ContainerCluster';
+import { CurrentCluster } from '../contexts/CurrentCluster';
import { useGraph } from '../hooks/use-graph';
import { useRenderedID } from '../hooks/use-rendered-id';
-import { useRootCluster } from '../hooks/use-root-cluster';
+import { useContainerCluster } from '../hooks/use-container-cluster';
import { DuplicatedRootClusterErrorMessage } from '../errors';
import { useClusterMap } from '../hooks/use-cluster-map';
-import { RootClusterComponentProps } from '../types';
-
-export const Graph: FC = ({ children, label, ...props }) => {
- const root = useRootCluster();
- if (root !== null) {
+import { RootClusterProps } from '../types';
+/**
+ * `Graph` component.
+ */
+export const Graph: FC = ({ children, label, ...options }) => {
+ const container = useContainerCluster();
+ if (container !== null) {
throw Error(DuplicatedRootClusterErrorMessage);
}
const renderedLabel = useRenderedID(label);
- if (renderedLabel !== undefined) Object.assign(props, { label: renderedLabel });
- const graph = useGraph(props);
+ if (renderedLabel !== undefined) Object.assign(options, { label: renderedLabel });
+ const graph = useGraph(options);
const clusters = useClusterMap();
useEffect(() => {
if (graph.id !== undefined) {
@@ -24,9 +26,9 @@ export const Graph: FC = ({ children, label, ...props
}
}, [clusters, graph]);
return (
-
- {children}
-
+
+ {children}
+
);
};
diff --git a/src/components/Node.tsx b/src/components/Node.tsx
index c664db0..5580dad 100644
--- a/src/components/Node.tsx
+++ b/src/components/Node.tsx
@@ -1,17 +1,20 @@
-import React, { FC } from 'react';
+import { VFC } from 'react';
import PropTypes from 'prop-types';
import { useNode } from '../hooks/use-node';
import { useRenderedID } from '../hooks/use-rendered-id';
-import { NodeComponentProps } from '../types';
+import { NodeProps } from '../types';
-export const Node: FC = ({ children, label, xlabel, ...props }) => {
+/**
+ * `Node` component.
+ */
+export const Node: VFC = ({ id, label, xlabel, ...options }) => {
const renderedLabel = useRenderedID(label);
const renderedXlabel = useRenderedID(xlabel);
- if (renderedLabel !== undefined) Object.assign(props, { label: renderedLabel });
- if (renderedXlabel !== undefined) Object.assign(props, { xlabel: renderedXlabel });
- useNode(props);
- return <>{children}>;
+ if (renderedLabel !== undefined) Object.assign(options, { label: renderedLabel });
+ if (renderedXlabel !== undefined) Object.assign(options, { xlabel: renderedXlabel });
+ useNode(id, options);
+ return null;
};
Node.displayName = 'Node';
diff --git a/src/components/Subgraph.tsx b/src/components/Subgraph.tsx
index ad3c7f5..f0f867e 100644
--- a/src/components/Subgraph.tsx
+++ b/src/components/Subgraph.tsx
@@ -1,22 +1,24 @@
import React, { FC, useEffect } from 'react';
import PropTypes from 'prop-types';
-import { Cluster } from '../contexts/Cluster';
+import { CurrentCluster } from '../contexts/CurrentCluster';
import { useSubgraph } from '../hooks/use-subgraph';
import { useRenderedID } from '../hooks/use-rendered-id';
import { useClusterMap } from '../hooks/use-cluster-map';
-import { SubgraphComponentProps } from '../types';
-
-export const Subgraph: FC = ({ children, label, ...props }) => {
+import { SubgraphProps } from '../types';
+/**
+ * `Subgraph` component.
+ */
+export const Subgraph: FC = ({ children, label, ...options }) => {
const renderedLabel = useRenderedID(label);
- if (renderedLabel !== undefined) Object.assign(props, { label: renderedLabel });
- const subgraph = useSubgraph(props);
+ if (renderedLabel !== undefined) Object.assign(options, { label: renderedLabel });
+ const subgraph = useSubgraph(options);
const clusters = useClusterMap();
useEffect(() => {
if (subgraph.id !== undefined) {
clusters.set(subgraph.id, subgraph);
}
}, [subgraph, clusters]);
- return {children};
+ return {children};
};
Subgraph.displayName = 'Subgraph';
diff --git a/src/components/__tests__/utils/renderExpectToThrow.tsx b/src/components/__tests__/utils/renderExpectToThrow.tsx
index 2a042ba..3c674e1 100644
--- a/src/components/__tests__/utils/renderExpectToThrow.tsx
+++ b/src/components/__tests__/utils/renderExpectToThrow.tsx
@@ -3,7 +3,7 @@
import React, { Component, ReactElement } from 'react';
import { render } from '../../../render';
-export function renderExpectToThrow(element: ReactElement, expectedError: string): void {
+export function renderExpectToThrow(element: ReactElement, ...expectedError: string[]): void {
const errors: Error[] = [];
class ErrorBoundary extends Component, { hasError: boolean }> {
constructor(props: Record) {
@@ -28,11 +28,11 @@ export function renderExpectToThrow(element: ReactElement, expectedError: string
}
try {
- render({element}, {});
+ render({element});
} catch (e) {
errors.push(e);
}
+ expect(errors.length).toBeGreaterThanOrEqual(expectedError.length);
- expect(errors.length).toBe(1);
- expect(errors[0].message).toContain(expectedError);
+ expect(errors.map((e) => e.message)).toEqual(expect.arrayContaining(expectedError));
}
diff --git a/src/contexts/Cluster.ts b/src/contexts/Cluster.ts
deleted file mode 100644
index f398b98..0000000
--- a/src/contexts/Cluster.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react';
-import { ICluster } from 'ts-graphviz';
-
-// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-export const Cluster = React.createContext(null!);
-Cluster.displayName = 'Cluster';
diff --git a/src/contexts/ContainerCluster.ts b/src/contexts/ContainerCluster.ts
new file mode 100644
index 0000000..45737b9
--- /dev/null
+++ b/src/contexts/ContainerCluster.ts
@@ -0,0 +1,5 @@
+import React from 'react';
+import { ICluster } from 'ts-graphviz';
+
+export const ContainerCluster = React.createContext(null);
+ContainerCluster.displayName = 'ContainerCluster';
diff --git a/src/contexts/CurrentCluster.ts b/src/contexts/CurrentCluster.ts
new file mode 100644
index 0000000..ca86503
--- /dev/null
+++ b/src/contexts/CurrentCluster.ts
@@ -0,0 +1,5 @@
+import React from 'react';
+import { ICluster } from 'ts-graphviz';
+
+export const CurrentCluster = React.createContext(null);
+CurrentCluster.displayName = 'CurrentCluster';
diff --git a/src/contexts/GraphvizContext.ts b/src/contexts/GraphvizContext.ts
index 6da9c0e..31507a2 100644
--- a/src/contexts/GraphvizContext.ts
+++ b/src/contexts/GraphvizContext.ts
@@ -1,5 +1,9 @@
import React from 'react';
-import { IContext } from '../types';
+import { ICluster } from 'ts-graphviz';
+
+export interface IContext {
+ container?: ICluster;
+}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
export const GraphvizContext = React.createContext(null!);
diff --git a/src/contexts/RootCluster.ts b/src/contexts/RootCluster.ts
deleted file mode 100644
index 82757eb..0000000
--- a/src/contexts/RootCluster.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react';
-import { IRootCluster } from 'ts-graphviz';
-
-// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-export const RootCluster = React.createContext(null!);
-RootCluster.displayName = 'RootCluster';
diff --git a/src/errors.ts b/src/errors.ts
index be6c29a..b3457de 100644
--- a/src/errors.ts
+++ b/src/errors.ts
@@ -3,3 +3,5 @@ export const NoGraphvizContextErrorMessage =
'Cannot call useGraphvizContext outside GraphvizContext.\nBasically, you need to use the render function provided by @ts-graphviz/react.';
export const NoClusterErrorMessage = 'useCluster must be called within a cluster such as Digraph, Graph, Subgraph.';
export const DuplicatedRootClusterErrorMessage = 'RootCluster is duplicated.\nUse only one of Digraph and Graph.';
+
+export const NoContainerErrorMessage = 'There are no clusters of container(Subgraph, Digraph, Graph).';
diff --git a/src/hooks/__tests__/use-root-cluster.spec.ts b/src/hooks/__tests__/use-container-cluster.spec.ts
similarity index 71%
rename from src/hooks/__tests__/use-root-cluster.spec.ts
rename to src/hooks/__tests__/use-container-cluster.spec.ts
index d7869d5..7ea8521 100644
--- a/src/hooks/__tests__/use-root-cluster.spec.ts
+++ b/src/hooks/__tests__/use-container-cluster.spec.ts
@@ -1,33 +1,33 @@
import { Digraph, Graph } from 'ts-graphviz';
import { renderHook } from '@testing-library/react-hooks';
import { digraph, graph, graphInSubgraph, digraphInSubgraph } from './utils/wrapper';
-import { useRootCluster } from '../use-root-cluster';
+import { useContainerCluster } from '../use-container-cluster';
-describe('useRootCluster', () => {
+describe('useContainerCluster', () => {
describe('get root cluster', () => {
test('returns Diagram instance in digraph wrapper', () => {
- const { result } = renderHook(() => useRootCluster(), {
+ const { result } = renderHook(() => useContainerCluster(), {
wrapper: digraph(),
});
expect(result.current).toBeInstanceOf(Digraph);
});
test('returns Graph instance in graph wrapper', () => {
- const { result } = renderHook(() => useRootCluster(), {
+ const { result } = renderHook(() => useContainerCluster(), {
wrapper: graph(),
});
expect(result.current).toBeInstanceOf(Graph);
});
test('returns Graph instance in graphInSubgraph wrapper', () => {
- const { result } = renderHook(() => useRootCluster(), {
+ const { result } = renderHook(() => useContainerCluster(), {
wrapper: graphInSubgraph(),
});
expect(result.current).toBeInstanceOf(Graph);
});
test('returns Digraph instance in digraphInSubgraph wrapper', () => {
- const { result } = renderHook(() => useRootCluster(), {
+ const { result } = renderHook(() => useContainerCluster(), {
wrapper: digraphInSubgraph(),
});
expect(result.current).toBeInstanceOf(Digraph);
diff --git a/src/hooks/__tests__/use-cluster.spec.ts b/src/hooks/__tests__/use-current-cluster.spec.ts
similarity index 73%
rename from src/hooks/__tests__/use-cluster.spec.ts
rename to src/hooks/__tests__/use-current-cluster.spec.ts
index f7e5e83..1618f39 100644
--- a/src/hooks/__tests__/use-cluster.spec.ts
+++ b/src/hooks/__tests__/use-current-cluster.spec.ts
@@ -1,34 +1,34 @@
import { Digraph, Graph, Subgraph } from 'ts-graphviz';
import { renderHook } from '@testing-library/react-hooks';
-import { useCluster } from '../use-cluster';
+import { useCurrentCluster } from '../use-current-cluster';
import { digraph, graph, graphInSubgraph, digraphInSubgraph } from './utils/wrapper';
import { NoClusterErrorMessage } from '../../errors';
-describe('useCluster', () => {
+describe('useCurrentCluster', () => {
describe('get parent cluster', () => {
test('returns Diagram instance in digraph wrapper', () => {
- const { result } = renderHook(() => useCluster(), {
+ const { result } = renderHook(() => useCurrentCluster(), {
wrapper: digraph(),
});
expect(result.current).toBeInstanceOf(Digraph);
});
test('returns Graph instance in graph wrapper', () => {
- const { result } = renderHook(() => useCluster(), {
+ const { result } = renderHook(() => useCurrentCluster(), {
wrapper: graph(),
});
expect(result.current).toBeInstanceOf(Graph);
});
test('returns Subgraph instance in graphInSubgraph wrapper', () => {
- const { result } = renderHook(() => useCluster(), {
+ const { result } = renderHook(() => useCurrentCluster(), {
wrapper: graphInSubgraph(),
});
expect(result.current).toBeInstanceOf(Subgraph);
});
test('returns Subgraph instance in digraphInSubgraph wrapper', () => {
- const { result } = renderHook(() => useCluster(), {
+ const { result } = renderHook(() => useCurrentCluster(), {
wrapper: digraphInSubgraph(),
});
expect(result.current).toBeInstanceOf(Subgraph);
@@ -36,7 +36,7 @@ describe('useCluster', () => {
});
test('An error occurs when called outside the cluster', () => {
- const { result } = renderHook(() => useCluster());
+ const { result } = renderHook(() => useCurrentCluster());
expect(result.error).toStrictEqual(Error(NoClusterErrorMessage));
});
});
diff --git a/src/hooks/__tests__/use-edge.spec.ts b/src/hooks/__tests__/use-edge.spec.ts
index ab3ff81..e8f3658 100644
--- a/src/hooks/__tests__/use-edge.spec.ts
+++ b/src/hooks/__tests__/use-edge.spec.ts
@@ -6,35 +6,35 @@ import { EdgeTargetLengthErrorMessage } from '../../errors';
describe('useEdge', () => {
it('returns Edge instance in digraph wrapper', () => {
- const { result } = renderHook(() => useEdge({ targets: ['a', 'b'] }), {
+ const { result } = renderHook(() => useEdge(['a', 'b']), {
wrapper: digraph(),
});
expect(result.current).toBeInstanceOf(Edge);
});
it('returns an Edge instance in a digraph wrapper for grouped edge targets', () => {
- const { result } = renderHook(() => useEdge({ targets: ['a', ['b1', 'b2'], 'c'] }), {
+ const { result } = renderHook(() => useEdge(['a', ['b1', 'b2'], 'c']), {
wrapper: digraph(),
});
expect(result.current).toBeInstanceOf(Edge);
});
it('returns Edge instance in graph wrapper', () => {
- const { result } = renderHook(() => useEdge({ targets: ['a', 'b'] }), {
+ const { result } = renderHook(() => useEdge(['a', 'b']), {
wrapper: graph(),
});
expect(result.current).toBeInstanceOf(Edge);
});
it('returns an Edge instance in a graph wrapper for grouped edge targets', () => {
- const { result } = renderHook(() => useEdge({ targets: ['a', ['b1', 'b2'], 'c'] }), {
+ const { result } = renderHook(() => useEdge(['a', ['b1', 'b2'], 'c']), {
wrapper: graph(),
});
expect(result.current).toBeInstanceOf(Edge);
});
test('throw error if the target is less than 2', () => {
- const { result } = renderHook(() => useEdge({ targets: ['a'] }), {
+ const { result } = renderHook(() => useEdge(['a']), {
wrapper: graph(),
});
expect(result.error).toStrictEqual(Error(EdgeTargetLengthErrorMessage));
diff --git a/src/hooks/__tests__/use-node.spec.ts b/src/hooks/__tests__/use-node.spec.ts
index 1424d5d..4c89934 100644
--- a/src/hooks/__tests__/use-node.spec.ts
+++ b/src/hooks/__tests__/use-node.spec.ts
@@ -6,7 +6,7 @@ import { digraph } from './utils/wrapper';
describe('useNode', () => {
it('returns Node instance', () => {
- const { result } = renderHook(() => useNode({ id: 'hoge' }), {
+ const { result } = renderHook(() => useNode('hoge'), {
wrapper: digraph(),
});
expect(result.current).toBeInstanceOf(Node);
diff --git a/src/hooks/use-cluster-attributes.ts b/src/hooks/use-cluster-attributes.ts
index be7b060..6327f52 100644
--- a/src/hooks/use-cluster-attributes.ts
+++ b/src/hooks/use-cluster-attributes.ts
@@ -1,11 +1,11 @@
import { ICluster, AttributesObject } from 'ts-graphviz';
import { useEffect } from 'react';
-import { ClusterAttributesProps } from '../types';
+import { ClusterCommonAttributesProps } from '../types';
export function useClusterAttributes(
cluster: ICluster,
attributes: AttributesObject,
- { edge, node, graph }: ClusterAttributesProps,
+ { edge, node, graph }: ClusterCommonAttributesProps,
): void {
useEffect(() => {
cluster.clear();
diff --git a/src/hooks/use-cluster.ts b/src/hooks/use-cluster.ts
deleted file mode 100644
index ba4afdb..0000000
--- a/src/hooks/use-cluster.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { useContext } from 'react';
-import { ICluster } from 'ts-graphviz';
-import { Cluster } from '../contexts/Cluster';
-import { NoClusterErrorMessage } from '../errors';
-
-export function useCluster(): ICluster {
- const cluster = useContext(Cluster);
- if (cluster === null) {
- throw Error(NoClusterErrorMessage);
- }
- return cluster;
-}
diff --git a/src/hooks/use-container-cluster.ts b/src/hooks/use-container-cluster.ts
new file mode 100644
index 0000000..6578a0f
--- /dev/null
+++ b/src/hooks/use-container-cluster.ts
@@ -0,0 +1,10 @@
+import { useContext } from 'react';
+import { ICluster } from 'ts-graphviz';
+import { ContainerCluster } from '../contexts/ContainerCluster';
+
+/**
+ * Return the cluster of container.
+ */
+export function useContainerCluster(): ICluster | null {
+ return useContext(ContainerCluster);
+}
diff --git a/src/hooks/use-current-cluster.ts b/src/hooks/use-current-cluster.ts
new file mode 100644
index 0000000..d1ab4e5
--- /dev/null
+++ b/src/hooks/use-current-cluster.ts
@@ -0,0 +1,17 @@
+import { useContext } from 'react';
+import { ICluster } from 'ts-graphviz';
+import { CurrentCluster } from '../contexts/CurrentCluster';
+import { NoClusterErrorMessage } from '../errors';
+
+/**
+ * Hook to get the current cluster(Digraph, Graph or Subgraph).
+ *
+ * @throws If it is out of the context of Cluster, it throws an exception.
+ */
+export function useCurrentCluster(): ICluster {
+ const cluster = useContext(CurrentCluster);
+ if (cluster === null) {
+ throw Error(NoClusterErrorMessage);
+ }
+ return cluster;
+}
diff --git a/src/hooks/use-digraph.ts b/src/hooks/use-digraph.ts
index 19fde4a..5715daa 100644
--- a/src/hooks/use-digraph.ts
+++ b/src/hooks/use-digraph.ts
@@ -3,13 +3,18 @@ import { Digraph, IRootCluster } from 'ts-graphviz';
import { useGraphvizContext } from './use-graphviz-context';
import { useClusterAttributes } from './use-cluster-attributes';
import { useHasComment } from './use-comment';
-import { RootClusterProps } from '../types';
+import { RootClusterOptions } from '../types';
-export function useDigraph({ id, comment, edge, node, graph, ...attributes }: RootClusterProps = {}): IRootCluster {
+/**
+ * `useDigraph` is a hook that creates an instance of Digraph
+ * according to the object given by props.
+ */
+export function useDigraph(options: RootClusterOptions = {}): IRootCluster {
+ const { id, comment, edge, node, graph, ...attributes } = options;
const context = useGraphvizContext();
const digraph = useMemo(() => {
const g = new Digraph(id);
- context.root = g;
+ context.container = g;
g.comment = comment;
g.apply(attributes);
g.attributes.node.apply(node ?? {});
@@ -21,7 +26,7 @@ export function useDigraph({ id, comment, edge, node, graph, ...attributes }: Ro
useClusterAttributes(digraph, attributes, { edge, node, graph });
useEffect(() => {
return (): void => {
- context.root = undefined;
+ context.container = undefined;
};
}, [context]);
return digraph;
diff --git a/src/hooks/use-edge.ts b/src/hooks/use-edge.ts
index c669283..43b55dd 100644
--- a/src/hooks/use-edge.ts
+++ b/src/hooks/use-edge.ts
@@ -1,13 +1,18 @@
import { useEffect, useMemo } from 'react';
-import { IEdge } from 'ts-graphviz';
-import { useCluster } from './use-cluster';
+import { EdgeTargetLike, EdgeTargetsLike, IEdge } from 'ts-graphviz';
+import { useCurrentCluster } from './use-current-cluster';
import { EdgeTargetLengthErrorMessage } from '../errors';
import { useHasComment } from './use-comment';
import { useHasAttributes } from './use-has-attributes';
-import { EdgeProps } from '../types';
+import { EdgeOptions } from '../types';
-export function useEdge({ targets, comment, ...attributes }: EdgeProps): IEdge {
- const cluster = useCluster();
+/**
+ * `useEdge` is a hook that creates an instance of Edge
+ * according to the object given by props.
+ */
+export function useEdge(targets: (EdgeTargetLike | EdgeTargetsLike)[], props: EdgeOptions = {}): IEdge {
+ const { comment, ...attributes } = props;
+ const cluster = useCurrentCluster();
if (targets.length < 2) {
throw Error(EdgeTargetLengthErrorMessage);
}
diff --git a/src/hooks/use-graph.ts b/src/hooks/use-graph.ts
index f84dcb4..4a2e969 100644
--- a/src/hooks/use-graph.ts
+++ b/src/hooks/use-graph.ts
@@ -3,13 +3,18 @@ import { Graph, IRootCluster } from 'ts-graphviz';
import { useGraphvizContext } from './use-graphviz-context';
import { useClusterAttributes } from './use-cluster-attributes';
import { useHasComment } from './use-comment';
-import { RootClusterProps } from '../types';
+import { RootClusterOptions } from '../types';
-export function useGraph({ id, comment, edge, node, graph, ...attributes }: RootClusterProps = {}): IRootCluster {
+/**
+ * `useGraph` is a hook that creates an instance of Graph
+ * according to the object given by props.
+ */
+export function useGraph(options: RootClusterOptions = {}): IRootCluster {
+ const { id, comment, edge, node, graph, ...attributes } = options;
const context = useGraphvizContext();
const memoGraph = useMemo(() => {
const g = new Graph(id);
- context.root = g;
+ context.container = g;
g.comment = comment;
g.apply(attributes);
g.attributes.node.apply(node ?? {});
@@ -21,7 +26,7 @@ export function useGraph({ id, comment, edge, node, graph, ...attributes }: Root
useClusterAttributes(memoGraph, attributes, { edge, node, graph });
useEffect(() => {
return (): void => {
- context.root = undefined;
+ context.container = undefined;
};
}, [context]);
return memoGraph;
diff --git a/src/hooks/use-graphviz-context.ts b/src/hooks/use-graphviz-context.ts
index 77db846..22bd15d 100644
--- a/src/hooks/use-graphviz-context.ts
+++ b/src/hooks/use-graphviz-context.ts
@@ -1,8 +1,12 @@
import { useContext } from 'react';
+import { ICluster } from 'ts-graphviz';
import { GraphvizContext } from '../contexts/GraphvizContext';
-import { IContext } from '../types';
import { NoGraphvizContextErrorMessage } from '../errors';
+export interface IContext {
+ container?: ICluster;
+}
+
export function useGraphvizContext(): IContext {
const context = useContext(GraphvizContext);
if (context === null) {
diff --git a/src/hooks/use-node.ts b/src/hooks/use-node.ts
index 5142870..646cf8f 100644
--- a/src/hooks/use-node.ts
+++ b/src/hooks/use-node.ts
@@ -1,12 +1,17 @@
import { useEffect, useMemo } from 'react';
import { INode } from 'ts-graphviz';
-import { NodeProps } from '../types';
-import { useCluster } from './use-cluster';
+import { NodeOptions } from '../types';
+import { useCurrentCluster } from './use-current-cluster';
import { useHasComment } from './use-comment';
import { useHasAttributes } from './use-has-attributes';
-export function useNode({ id, comment, ...attributes }: NodeProps): INode {
- const cluster = useCluster();
+/**
+ * `useNode` is a hook that creates an instance of Node
+ * according to the object given by props.
+ */
+export function useNode(id: string, options: NodeOptions = {}): INode {
+ const { comment, ...attributes } = options;
+ const cluster = useCurrentCluster();
const node = useMemo(() => {
const n = cluster.createNode(id);
n.attributes.apply(attributes);
diff --git a/src/hooks/use-root-cluster.ts b/src/hooks/use-root-cluster.ts
deleted file mode 100644
index 7398d3b..0000000
--- a/src/hooks/use-root-cluster.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { useContext } from 'react';
-import { IRootCluster } from 'ts-graphviz';
-import { RootCluster } from '../contexts/RootCluster';
-
-export function useRootCluster(): IRootCluster {
- return useContext(RootCluster);
-}
diff --git a/src/hooks/use-subgraph.ts b/src/hooks/use-subgraph.ts
index 67613e9..34a77ee 100644
--- a/src/hooks/use-subgraph.ts
+++ b/src/hooks/use-subgraph.ts
@@ -1,21 +1,33 @@
import { useMemo, useEffect } from 'react';
-import { ISubgraph } from 'ts-graphviz';
-import { SubgraphProps } from '../types';
-import { useCluster } from './use-cluster';
+import { Subgraph, ISubgraph } from 'ts-graphviz';
+import { SubgraphOptions } from '../types';
+import { useCurrentCluster } from './use-current-cluster';
import { useClusterAttributes } from './use-cluster-attributes';
import { useHasComment } from './use-comment';
+import { useGraphvizContext } from './use-graphviz-context';
-export function useSubgraph({ id, comment, edge, node, graph, ...attributes }: SubgraphProps = {}): ISubgraph {
- const cluster = useCluster();
+/**
+ * `useSubgraph` is a hook that creates an instance of Subgraph
+ * according to the object given by props.
+ */
+export function useSubgraph(props: SubgraphOptions = {}): ISubgraph {
+ const { id, comment, edge, node, graph, ...attributes } = props;
+ const context = useGraphvizContext();
+ const cluster = useCurrentCluster();
const subgraph = useMemo(() => {
- const g = cluster.createSubgraph(id);
+ const g = new Subgraph(id);
+ if (cluster !== null) {
+ cluster.addSubgraph(g);
+ } else if (!context.container) {
+ context.container = g;
+ }
g.comment = comment;
g.apply(attributes);
g.attributes.node.apply(node ?? {});
g.attributes.edge.apply(edge ?? {});
g.attributes.graph.apply(graph ?? {});
return g;
- }, [cluster, id, comment, edge, node, graph, attributes]);
+ }, [context, cluster, id, comment, edge, node, graph, attributes]);
useHasComment(subgraph, comment);
useClusterAttributes(subgraph, attributes, { edge, node, graph });
useEffect(() => {
diff --git a/src/index.ts b/src/index.ts
index 3e4c057..ca3ed08 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,15 +1,12 @@
export * from './types';
export * from './labels';
-export * from './hooks/use-cluster';
-export * from './hooks/use-cluster-map';
-export * from './hooks/use-graphviz-context';
+export * from './hooks/use-container-cluster';
+export * from './hooks/use-current-cluster';
export * from './hooks/use-digraph';
export * from './hooks/use-graph';
export * from './hooks/use-subgraph';
export * from './hooks/use-edge';
export * from './hooks/use-node';
-export * from './hooks/use-rendered-id';
-export * from './hooks/use-root-cluster';
export * from './components/Graph';
export * from './components/Digraph';
export * from './components/Subgraph';
diff --git a/src/labels.ts b/src/labels.ts
index ce52911..d16342f 100644
--- a/src/labels.ts
+++ b/src/labels.ts
@@ -3,88 +3,91 @@ import { AttributesValue } from 'ts-graphviz';
type ValueOf = T[keyof T];
-export type TableProps = {
- ALIGN?: 'CENTER' | 'LEFT' | 'RIGHT'; // "CENTER|LEFT|RIGHT"
- BGCOLOR?: AttributesValue; // "color"
- BORDER?: AttributesValue; // "value"
- CELLBORDER?: AttributesValue; // "value"
- CELLPADDING?: AttributesValue; // "value"
- CELLSPACING?: AttributesValue; // "value"
- COLOR?: AttributesValue; // "color"
- COLUMNS?: AttributesValue; // "value"
- FIXEDSIZE?: true; // "FALSE|TRUE"
- GRADIENTANGLE?: AttributesValue; // "value"
- HEIGHT?: AttributesValue; // "value"
- HREF?: AttributesValue; // "value"
- ID?: AttributesValue; // "value"
- PORT?: AttributesValue; // "portName"
- ROWS?: AttributesValue; // "value"
- SIDES?: AttributesValue; // "value"
- STYLE?: AttributesValue; // "value"
- TARGET?: AttributesValue; // "value"
- TITLE?: AttributesValue; // "value"
- TOOLTIP?: AttributesValue; // "value"
- VALIGN?: 'MIDDLE' | 'BOTTOM' | 'TOP'; // "MIDDLE|BOTTOM|TOP"
- WIDTH?: AttributesValue; // "value"
-};
-
-type NoAttributes = Record;
-
-export type TrProps = NoAttributes;
-
-export type TdProps = {
- ALIGN?: 'CENTER' | 'LEFT' | 'RIGHT' | 'TEXT'; // "CENTER|LEFT|RIGHT|TEXT"
- BALIGN?: 'CENTER' | 'LEFT' | 'RIGHT'; // "CENTER|LEFT|RIGHT"
- BGCOLOR?: AttributesValue; // "color"
- BORDER?: AttributesValue; // "value"
- CELLPADDING?: AttributesValue; // "value"
- CELLSPACING?: AttributesValue; // "value"
- COLOR?: AttributesValue; // "color"
- COLSPAN?: AttributesValue; // "value"
- FIXEDSIZE?: boolean; // "FALSE|TRUE"
- GRADIENTANGLE?: AttributesValue; // "value"
- HEIGHT?: AttributesValue; // "value"
- HREF?: AttributesValue; // "value"
- ID?: AttributesValue; // "value"
- PORT?: AttributesValue; // "portName"
- ROWSPAN?: AttributesValue; // "value"
- SIDES?: AttributesValue; // "value"
- STYLE?: AttributesValue; // "value"
- TARGET?: AttributesValue; // "value"
- TITLE?: AttributesValue; // "value"
- TOOLTIP?: AttributesValue; // "value"
- VALIGN?: 'MIDDLE' | 'BOTTOM' | 'TOP'; // "MIDDLE|BOTTOM|TOP"
- WIDTH?: AttributesValue; // "value"
-};
-
-export type FontProps = {
- COLOR?: AttributesValue; // "color"
- FACE?: AttributesValue; // "fontname"
- 'POINT-SIZE'?: AttributesValue; // "value"
-};
-
-export type BrProps = {
- ALIGN?: 'CENTER' | 'LEFT' | 'RIGHT'; // "CENTER|LEFT|RIGHT"
-};
-
-export type ImgProps = {
- SCALE?: boolean | 'WIDTH' | 'HEIGHT' | 'BOTH'; // "FALSE|TRUE|WIDTH|HEIGHT|BOTH"
- SRC?: AttributesValue; // "value"
-};
-
-export type IProps = NoAttributes;
-
-export type BProps = NoAttributes;
-
-export type UProps = NoAttributes;
-
-export type OProps = NoAttributes;
-export type SubProps = NoAttributes;
-
-export type SupProps = NoAttributes;
-export type SProps = NoAttributes;
-export type HrProps = NoAttributes;
-export type VrProps = NoAttributes;
+// eslint-disable-next-line @typescript-eslint/no-namespace
+export namespace labels {
+ export type TableProps = {
+ ALIGN?: 'CENTER' | 'LEFT' | 'RIGHT'; // "CENTER|LEFT|RIGHT"
+ BGCOLOR?: AttributesValue; // "color"
+ BORDER?: AttributesValue; // "value"
+ CELLBORDER?: AttributesValue; // "value"
+ CELLPADDING?: AttributesValue; // "value"
+ CELLSPACING?: AttributesValue; // "value"
+ COLOR?: AttributesValue; // "color"
+ COLUMNS?: AttributesValue; // "value"
+ FIXEDSIZE?: true; // "FALSE|TRUE"
+ GRADIENTANGLE?: AttributesValue; // "value"
+ HEIGHT?: AttributesValue; // "value"
+ HREF?: AttributesValue; // "value"
+ ID?: AttributesValue; // "value"
+ PORT?: AttributesValue; // "portName"
+ ROWS?: AttributesValue; // "value"
+ SIDES?: AttributesValue; // "value"
+ STYLE?: AttributesValue; // "value"
+ TARGET?: AttributesValue; // "value"
+ TITLE?: AttributesValue; // "value"
+ TOOLTIP?: AttributesValue; // "value"
+ VALIGN?: 'MIDDLE' | 'BOTTOM' | 'TOP'; // "MIDDLE|BOTTOM|TOP"
+ WIDTH?: AttributesValue; // "value"
+ };
+
+ type NoAttributes = Record;
+
+ export type TrProps = NoAttributes;
+
+ export type TdProps = {
+ ALIGN?: 'CENTER' | 'LEFT' | 'RIGHT' | 'TEXT'; // "CENTER|LEFT|RIGHT|TEXT"
+ BALIGN?: 'CENTER' | 'LEFT' | 'RIGHT'; // "CENTER|LEFT|RIGHT"
+ BGCOLOR?: AttributesValue; // "color"
+ BORDER?: AttributesValue; // "value"
+ CELLPADDING?: AttributesValue; // "value"
+ CELLSPACING?: AttributesValue; // "value"
+ COLOR?: AttributesValue; // "color"
+ COLSPAN?: AttributesValue; // "value"
+ FIXEDSIZE?: boolean; // "FALSE|TRUE"
+ GRADIENTANGLE?: AttributesValue; // "value"
+ HEIGHT?: AttributesValue; // "value"
+ HREF?: AttributesValue; // "value"
+ ID?: AttributesValue; // "value"
+ PORT?: AttributesValue; // "portName"
+ ROWSPAN?: AttributesValue; // "value"
+ SIDES?: AttributesValue; // "value"
+ STYLE?: AttributesValue; // "value"
+ TARGET?: AttributesValue; // "value"
+ TITLE?: AttributesValue; // "value"
+ TOOLTIP?: AttributesValue; // "value"
+ VALIGN?: 'MIDDLE' | 'BOTTOM' | 'TOP'; // "MIDDLE|BOTTOM|TOP"
+ WIDTH?: AttributesValue; // "value"
+ };
+
+ export type FontProps = {
+ COLOR?: AttributesValue; // "color"
+ FACE?: AttributesValue; // "fontname"
+ 'POINT-SIZE'?: AttributesValue; // "value"
+ };
+
+ export type BrProps = {
+ ALIGN?: 'CENTER' | 'LEFT' | 'RIGHT'; // "CENTER|LEFT|RIGHT"
+ };
+
+ export type ImgProps = {
+ SCALE?: boolean | 'WIDTH' | 'HEIGHT' | 'BOTH'; // "FALSE|TRUE|WIDTH|HEIGHT|BOTH"
+ SRC?: AttributesValue; // "value"
+ };
+
+ export type IProps = NoAttributes;
+
+ export type BProps = NoAttributes;
+
+ export type UProps = NoAttributes;
+
+ export type OProps = NoAttributes;
+ export type SubProps = NoAttributes;
+
+ export type SupProps = NoAttributes;
+ export type SProps = NoAttributes;
+ export type HrProps = NoAttributes;
+ export type VrProps = NoAttributes;
+}
export const DOT = Object.freeze({
PORT: 'dot-port',
@@ -112,21 +115,21 @@ declare global {
namespace JSX {
interface IntrinsicElements {
[DOT.PORT]: { children: string };
- [DOT.TABLE]: React.PropsWithChildren;
- [DOT.TR]: React.PropsWithChildren;
- [DOT.TD]: React.PropsWithChildren;
- [DOT.FONT]: React.PropsWithChildren;
- [DOT.BR]: BrProps;
- [DOT.IMG]: ImgProps;
- [DOT.I]: React.PropsWithChildren;
- [DOT.B]: React.PropsWithChildren;
- [DOT.U]: React.PropsWithChildren;
- [DOT.O]: React.PropsWithChildren;
- [DOT.SUB]: React.PropsWithChildren;
- [DOT.SUP]: React.PropsWithChildren;
- [DOT.S]: React.PropsWithChildren;
- [DOT.HR]: HrProps;
- [DOT.VR]: VrProps;
+ [DOT.TABLE]: React.PropsWithChildren;
+ [DOT.TR]: React.PropsWithChildren;
+ [DOT.TD]: React.PropsWithChildren;
+ [DOT.FONT]: React.PropsWithChildren;
+ [DOT.BR]: labels.BrProps;
+ [DOT.IMG]: labels.ImgProps;
+ [DOT.I]: React.PropsWithChildren;
+ [DOT.B]: React.PropsWithChildren;
+ [DOT.U]: React.PropsWithChildren;
+ [DOT.O]: React.PropsWithChildren;
+ [DOT.SUB]: React.PropsWithChildren;
+ [DOT.SUP]: React.PropsWithChildren;
+ [DOT.S]: React.PropsWithChildren;
+ [DOT.HR]: labels.HrProps;
+ [DOT.VR]: labels.VrProps;
}
}
}
diff --git a/src/render.ts b/src/render.ts
index 8a437d8..f6da35d 100644
--- a/src/render.ts
+++ b/src/render.ts
@@ -1,37 +1,116 @@
import { ReactElement, createElement } from 'react';
-import { toDot } from 'ts-graphviz';
-import { GraphvizContext } from './contexts/GraphvizContext';
+import { toDot, ICluster } from 'ts-graphviz';
+
import { reconciler } from './reconciler';
+import { IContext, GraphvizContext } from './contexts/GraphvizContext';
import { ClusterMap } from './contexts/ClusterMap';
-import { IContext } from './types';
+import { ContainerCluster } from './contexts/ContainerCluster';
+import { CurrentCluster } from './contexts/CurrentCluster';
+import { NoContainerErrorMessage } from './errors';
const noop = (): void => undefined;
-export function render(element: ReactElement, context: IContext): number {
- const container = reconciler.createContainer({}, 0, false, null);
- // Clusters
- return reconciler.updateContainer(
+function clusterMap(cluster?: ICluster, map: Map = new Map()): Map {
+ if (cluster) {
+ if (cluster.id) {
+ map.set(cluster.id, cluster);
+ }
+ cluster.subgraphs.forEach((s) => clusterMap(s, map));
+ }
+ return map;
+}
+
+/**
+ * Convert the given element to Graphviz model.
+ *
+ * @example Example of giving a cluster as a container with the second argument.
+ *
+ * ```tsx
+ * import React, { FC } from 'react';
+ * import { digraph, toDot } from 'ts-graphviz';
+ * import { Node, Subgraph, render, Edge } from '@ts-graphviz/react';
+ *
+ * const Example: FC = () => (
+ * <>
+ *
+ *
+ *
+ *
+ *
+ *
+ * >
+ * );
+ *
+ * const G = digraph((g) => render(, g));
+ * console.log(toDot(G));
+ * // digraph {
+ * // "a";
+ * // subgraph "my_cluster" {
+ * // "b";
+ * // }
+ * // "b" -> "a";
+ * // }
+ * ```
+ */
+export function render(element: ReactElement, container?: ICluster): ICluster {
+ const context: IContext = { container };
+ reconciler.updateContainer(
createElement(
- ClusterMap.Provider,
- {
- value: new Map(),
- },
+ GraphvizContext.Provider,
+ { value: context },
createElement(
- GraphvizContext.Provider,
- {
- value: context,
- },
- element,
+ ClusterMap.Provider,
+ { value: clusterMap(container) },
+ createElement(
+ ContainerCluster.Provider,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ { value: container ?? null! },
+ container ? createElement(CurrentCluster.Provider, { value: container }, element) : element,
+ ),
),
),
- container,
+ reconciler.createContainer({}, 0, false, null),
null,
noop,
);
+ if (!context.container) {
+ throw Error(NoContainerErrorMessage);
+ }
+ return context.container;
}
-export function renderToDot(element: ReactElement): string {
- const context: IContext = {};
- render(element, context);
- return context.root ? toDot(context.root) : '';
+/**
+ * Converts the given element to DOT language and returns it.
+ *
+ * @example
+ *
+ * ```tsx
+ * import React, { FC } from 'react';
+ * import { Digraph, Node, Subgraph, renderToDot, Edge } from '@ts-graphviz/react';
+ *
+ * const Example: FC = () => (
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * );
+ *
+ * const dot = renderToDot();
+ * console.log(dot);
+ * // digraph {
+ * // "a";
+ * // subgraph "my_cluster" {
+ * // "b";
+ * // }
+ * // "b" -> "a";
+ * // }
+ * ```
+ *
+ * @returns Rendered dot string
+ */
+export function renderToDot(element: ReactElement, container?: ICluster): string {
+ return toDot(render(element, container));
}
diff --git a/src/types.ts b/src/types.ts
index afaca32..dab0b35 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -3,7 +3,6 @@ import {
EdgeAttributes,
NodeAttributes,
ClusterSubgraphAttributes,
- IRootCluster,
RootClusterAttributes,
EdgeTargetLike,
EdgeTargetsLike,
@@ -11,55 +10,74 @@ import {
attribute,
} from 'ts-graphviz';
-export interface IContext {
- root?: IRootCluster;
-}
-
-export interface ClusterAttributesProps {
+/** Common attribute values of objects under cluster */
+export interface ClusterCommonAttributesProps {
+ /** Attribute value for Edges */
edge?: EdgeAttributes;
+ /** Attribute value for Nodes */
node?: NodeAttributes;
+ /** Attribute value for Graphs */
graph?: ClusterSubgraphAttributes;
}
-export interface RootClusterProps
+/** Options for RootCluster */
+export interface RootClusterOptions
extends Omit,
- ClusterAttributesProps,
+ ClusterCommonAttributesProps,
IHasComment {
+ /** Cluster id */
id?: string;
}
-export interface SubgraphProps
+/** Options for Subgraph */
+export interface SubgraphOptions
extends Omit,
- ClusterAttributesProps,
+ ClusterCommonAttributesProps,
IHasComment {
+ /** Cluster id */
id?: string;
}
-export interface EdgeProps extends Omit, IHasComment {
- targets: (EdgeTargetLike | EdgeTargetsLike)[];
-}
+/** Options for Edge */
+export interface EdgeOptions extends Omit, IHasComment {}
-export interface NodeProps extends Omit, IHasComment {
- id: string;
-}
+/** Options for Node */
+export interface NodeOptions extends Omit, IHasComment {}
-export interface RootClusterComponentProps extends Omit {
+/** Props for RootCluster component */
+export interface RootClusterProps extends Omit {
label?: ReactElement | string;
}
-export interface EdgeComponentProps extends Omit {
+/** Props for Edge component */
+export interface EdgeProps extends Omit {
+ /** Edge targets */
+ targets: (EdgeTargetLike | EdgeTargetsLike)[];
+ /** Edge label */
label?: ReactElement | string;
}
-export interface NodeComponentProps extends Omit {
+/** Props for Node component */
+export interface NodeProps extends Omit {
+ /** Node id */
+ id: string;
+ /** Node label */
label?: ReactElement | string;
+ /** Node xlabel */
xlabel?: ReactElement | string;
}
-export interface SubgraphComponentProps extends Omit {
+/** Props for Subgraph component */
+export interface SubgraphProps extends Omit {
+ /** Subgraph label */
label?: ReactElement | string;
}
-export interface ClusterPortalComponentProps {
- name?: string;
+/** Props for ClusterPortal component */
+export interface ClusterPortalProps {
+ /**
+ * id of the cluster you want to target for the portal.
+ * If not specified, target the cluster that is the container to the portal.
+ */
+ id?: string;
}