@statewalker/fsm-charts 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/StateChart-DNGQd1XG.d.ts +53 -0
- package/dist/chunk-3GGM3ZWL.js +2685 -0
- package/dist/chunk-NXWOFQMO.js +10 -0
- package/dist/chunk-TPNWHU7Y.js +437 -0
- package/dist/index-layout.d.ts +96 -0
- package/dist/index-layout.js +2 -0
- package/dist/index-svg.d.ts +25 -0
- package/dist/index-svg.js +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +60 -0
- package/src/FsmStateConfig.ts +5 -0
- package/src/dagre/acyclic.d.ts +2 -0
- package/src/dagre/acyclic.js +60 -0
- package/src/dagre/add-border-segments.d.ts +1 -0
- package/src/dagre/add-border-segments.js +36 -0
- package/src/dagre/coordinate-system.d.ts +2 -0
- package/src/dagre/coordinate-system.js +75 -0
- package/src/dagre/data/list.d.ts +12 -0
- package/src/dagre/data/list.js +55 -0
- package/src/dagre/debug.d.ts +2 -0
- package/src/dagre/debug.js +32 -0
- package/src/dagre/greedy-fas.d.ts +1 -0
- package/src/dagre/greedy-fas.js +126 -0
- package/src/dagre/index.d.ts +5 -0
- package/src/dagre/index.js +6 -0
- package/src/dagre/layout.d.ts +1 -0
- package/src/dagre/layout.js +466 -0
- package/src/dagre/nesting-graph.d.ts +2 -0
- package/src/dagre/nesting-graph.js +137 -0
- package/src/dagre/normalize.d.ts +2 -0
- package/src/dagre/normalize.js +91 -0
- package/src/dagre/order/add-subgraph-constraints.d.ts +1 -0
- package/src/dagre/order/add-subgraph-constraints.js +53 -0
- package/src/dagre/order/barycenter.d.ts +15 -0
- package/src/dagre/order/barycenter.js +31 -0
- package/src/dagre/order/build-layer-graph.d.ts +2 -0
- package/src/dagre/order/build-layer-graph.js +76 -0
- package/src/dagre/order/cross-count.d.ts +1 -0
- package/src/dagre/order/cross-count.js +82 -0
- package/src/dagre/order/index.d.ts +1 -0
- package/src/dagre/order/index.js +77 -0
- package/src/dagre/order/init-order.d.ts +1 -0
- package/src/dagre/order/init-order.js +44 -0
- package/src/dagre/order/resolve-conflicts.d.ts +1 -0
- package/src/dagre/order/resolve-conflicts.js +128 -0
- package/src/dagre/order/sort-subgraph.d.ts +8 -0
- package/src/dagre/order/sort-subgraph.js +78 -0
- package/src/dagre/order/sort.d.ts +6 -0
- package/src/dagre/order/sort.js +59 -0
- package/src/dagre/parent-dummy-chains.d.ts +1 -0
- package/src/dagre/parent-dummy-chains.js +86 -0
- package/src/dagre/position/bk.d.ts +31 -0
- package/src/dagre/position/bk.js +423 -0
- package/src/dagre/position/index.d.ts +1 -0
- package/src/dagre/position/index.js +31 -0
- package/src/dagre/rank/feasible-tree.d.ts +2 -0
- package/src/dagre/rank/feasible-tree.js +87 -0
- package/src/dagre/rank/index.d.ts +1 -0
- package/src/dagre/rank/index.js +52 -0
- package/src/dagre/rank/network-simplex.d.ts +16 -0
- package/src/dagre/rank/network-simplex.js +236 -0
- package/src/dagre/rank/util.d.ts +2 -0
- package/src/dagre/rank/util.js +63 -0
- package/src/dagre/util.d.ts +27 -0
- package/src/dagre/util.js +250 -0
- package/src/graphlib/alg/components.d.ts +1 -0
- package/src/graphlib/alg/components.js +27 -0
- package/src/graphlib/alg/dfs.d.ts +1 -0
- package/src/graphlib/alg/dfs.js +46 -0
- package/src/graphlib/alg/dijkstra-all.d.ts +1 -0
- package/src/graphlib/alg/dijkstra-all.js +14 -0
- package/src/graphlib/alg/dijkstra.d.ts +1 -0
- package/src/graphlib/alg/dijkstra.js +65 -0
- package/src/graphlib/alg/find-cycles.d.ts +1 -0
- package/src/graphlib/alg/find-cycles.js +10 -0
- package/src/graphlib/alg/floyd-warshall.d.ts +1 -0
- package/src/graphlib/alg/floyd-warshall.js +55 -0
- package/src/graphlib/alg/index.d.ts +24 -0
- package/src/graphlib/alg/index.js +25 -0
- package/src/graphlib/alg/is-acyclic.d.ts +1 -0
- package/src/graphlib/alg/is-acyclic.js +15 -0
- package/src/graphlib/alg/postorder.d.ts +1 -0
- package/src/graphlib/alg/postorder.js +7 -0
- package/src/graphlib/alg/preorder.d.ts +1 -0
- package/src/graphlib/alg/preorder.js +7 -0
- package/src/graphlib/alg/prim.d.ts +2 -0
- package/src/graphlib/alg/prim.js +52 -0
- package/src/graphlib/alg/tarjan.d.ts +1 -0
- package/src/graphlib/alg/tarjan.js +47 -0
- package/src/graphlib/alg/topsort.d.ts +5 -0
- package/src/graphlib/alg/topsort.js +36 -0
- package/src/graphlib/data/priority-queue.d.ts +59 -0
- package/src/graphlib/data/priority-queue.js +152 -0
- package/src/graphlib/graph.d.ts +55 -0
- package/src/graphlib/graph.js +510 -0
- package/src/graphlib/index.d.ts +3 -0
- package/src/graphlib/index.js +7 -0
- package/src/graphlib/json.d.ts +16 -0
- package/src/graphlib/json.js +63 -0
- package/src/index-layout.ts +1 -0
- package/src/index-svg.ts +1 -0
- package/src/index.ts +2 -0
- package/src/layout/Dimensions.ts +8 -0
- package/src/layout/GraphParamsProvider.ts +17 -0
- package/src/layout/Padding.ts +10 -0
- package/src/layout/Position.ts +4 -0
- package/src/layout/StateChart.ts +8 -0
- package/src/layout/StateGraphEdge.ts +14 -0
- package/src/layout/StateGraphNode.ts +12 -0
- package/src/layout/Transition.ts +5 -0
- package/src/layout/TransitionsGraph.ts +13 -0
- package/src/layout/buildCharts.ts +74 -0
- package/src/layout/buildFlatCharts.ts +142 -0
- package/src/layout/getGraphParamsProvider.ts +63 -0
- package/src/layout/getLabelDimensions.ts +59 -0
- package/src/layout/index.ts +15 -0
- package/src/lodash-es/_deleteme.js +291 -0
- package/src/lodash-es/index.ts +9 -0
- package/src/lodash-es/types.ts +35 -0
- package/src/svg/buildStatechartCss.ts +120 -0
- package/src/svg/buildStatechartSvg.ts +256 -0
- package/src/svg/buildStatechartsPanel.ts +38 -0
- package/src/svg/index.ts +3 -0
- package/src/utils/BasisCurve.ts +89 -0
- package/src/utils/getPadding.ts +13 -0
- package/src/utils/serializeAttrs.ts +28 -0
- package/src/utils/serializeStyle.ts +11 -0
- package/src/utils/toKebabCase.ts +18 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Dimensions } from "./Dimensions.ts";
|
|
2
|
+
import { Position } from "./Position.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Information about a state graph edge.
|
|
6
|
+
*/
|
|
7
|
+
export type StateGraphEdge = Dimensions &
|
|
8
|
+
Position & {
|
|
9
|
+
id: string;
|
|
10
|
+
from: string;
|
|
11
|
+
event: string;
|
|
12
|
+
to: string;
|
|
13
|
+
points: Position[];
|
|
14
|
+
} & Record<string, any>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Dimensions } from "./Dimensions";
|
|
2
|
+
import { Position } from "./Position";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Information about a state node in the graph.
|
|
6
|
+
*/
|
|
7
|
+
export type StateGraphNode = Dimensions &
|
|
8
|
+
Position & {
|
|
9
|
+
id: string;
|
|
10
|
+
key: string;
|
|
11
|
+
state: string;
|
|
12
|
+
} & Record<string, any>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Dimensions } from "./Dimensions.ts";
|
|
2
|
+
import { Position } from "./Position.ts";
|
|
3
|
+
import { StateGraphEdge } from "./StateGraphEdge.ts";
|
|
4
|
+
import { StateGraphNode } from "./StateGraphNode.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Coordinates for state nodes and endges corresponding to state transitions.
|
|
8
|
+
*/
|
|
9
|
+
export type TransitionsGraph = Position &
|
|
10
|
+
Dimensions & {
|
|
11
|
+
nodes: StateGraphNode[];
|
|
12
|
+
edges: StateGraphEdge[];
|
|
13
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { GraphParamsProvider } from "./GraphParamsProvider.ts";
|
|
2
|
+
import type { StateGraphNode } from "./StateGraphNode.ts";
|
|
3
|
+
import type { StateGraphEdge } from "./StateGraphEdge.ts";
|
|
4
|
+
import type { Padding } from "./Padding.ts";
|
|
5
|
+
import type { Position } from "./Position.ts";
|
|
6
|
+
import type { Dimensions } from "./Dimensions.ts";
|
|
7
|
+
import type { FsmStateConfig } from "../FsmStateConfig.ts";
|
|
8
|
+
import type { StateChart } from "./StateChart.ts";
|
|
9
|
+
|
|
10
|
+
import { layout } from "../dagre/layout.js";
|
|
11
|
+
import { Graph } from "../graphlib/graph.js";
|
|
12
|
+
import { getPadding } from "../utils/getPadding.ts";
|
|
13
|
+
import { getLodash, setLodash } from "../lodash-es/index.ts";
|
|
14
|
+
import { buildFlatCharts } from "./buildFlatCharts.ts";
|
|
15
|
+
/**
|
|
16
|
+
* Build graphs corresponding to the specified transitions.
|
|
17
|
+
* @param config - State configuration with transitions and sub-states.
|
|
18
|
+
* @param newId - A function that generates unique ids for nodes and edges.
|
|
19
|
+
* @param getStateParams - A function that returns the dimensions of a state node.
|
|
20
|
+
* @param getTransitionParams - A function that returns the dimensions of a transition edge.
|
|
21
|
+
* @param initialStateKey - The key for the initial state.
|
|
22
|
+
* @param finalStateKey - The key for the final state.
|
|
23
|
+
* @returns {StateChart} - The graph with nodes and edges.
|
|
24
|
+
*/
|
|
25
|
+
export function buildCharts({
|
|
26
|
+
lodash,
|
|
27
|
+
config,
|
|
28
|
+
newId,
|
|
29
|
+
getStateParams,
|
|
30
|
+
getTransitionParams,
|
|
31
|
+
padding = [5, 5],
|
|
32
|
+
initialStateKey = "<initial>",
|
|
33
|
+
finalStateKey = "<final>",
|
|
34
|
+
}: {
|
|
35
|
+
config: FsmStateConfig;
|
|
36
|
+
lodash: any;
|
|
37
|
+
newId: (prefix: string) => string;
|
|
38
|
+
initialStateKey?: string;
|
|
39
|
+
finalStateKey?: string;
|
|
40
|
+
padding?: Padding;
|
|
41
|
+
} & GraphParamsProvider): StateChart {
|
|
42
|
+
return buildChart(config);
|
|
43
|
+
|
|
44
|
+
function buildChart(config: FsmStateConfig, id: string = newId("state")) {
|
|
45
|
+
const graph = buildFlatCharts({
|
|
46
|
+
lodash,
|
|
47
|
+
transitions: config.transitions,
|
|
48
|
+
newId,
|
|
49
|
+
getStateParams,
|
|
50
|
+
getTransitionParams,
|
|
51
|
+
padding,
|
|
52
|
+
initialStateKey,
|
|
53
|
+
finalStateKey,
|
|
54
|
+
});
|
|
55
|
+
const index = graph.nodes.reduce((index, node) => {
|
|
56
|
+
index[node.key as string] = node.id as string;
|
|
57
|
+
return index;
|
|
58
|
+
}, {} as Record<string, string>);
|
|
59
|
+
|
|
60
|
+
const children: StateChart[] = [];
|
|
61
|
+
if (config.states) {
|
|
62
|
+
for (const child of config.states) {
|
|
63
|
+
const childId = index[child.key];
|
|
64
|
+
children.push(buildChart(child, childId));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
id,
|
|
69
|
+
key: config.key,
|
|
70
|
+
graph,
|
|
71
|
+
children,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { layout } from "../dagre/layout.js";
|
|
2
|
+
import { Graph } from "../graphlib/graph.js";
|
|
3
|
+
|
|
4
|
+
import type { GraphParamsProvider } from "./GraphParamsProvider.ts";
|
|
5
|
+
import type { Transition } from "./Transition.ts";
|
|
6
|
+
import type { TransitionsGraph } from "./TransitionsGraph.ts";
|
|
7
|
+
import type { StateGraphNode } from "./StateGraphNode.ts";
|
|
8
|
+
import type { StateGraphEdge } from "./StateGraphEdge.ts";
|
|
9
|
+
import { Padding } from "./Padding.ts";
|
|
10
|
+
import { getPadding } from "../utils/getPadding.ts";
|
|
11
|
+
import { Position } from "./Position.ts";
|
|
12
|
+
import { Dimensions } from "./Dimensions.ts";
|
|
13
|
+
import { getLodash, setLodash } from "../lodash-es/index.ts";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Build graphs corresponding to the specified transitions.
|
|
17
|
+
* @param transitions - The transitions between states.
|
|
18
|
+
* @param newId - A function that generates unique ids for nodes and edges.
|
|
19
|
+
* @param getStateParams - A function that returns the dimensions of a state node.
|
|
20
|
+
* @param getTransitionParams - A function that returns the dimensions of a transition edge.
|
|
21
|
+
* @param initialStateKey - The key for the initial state.
|
|
22
|
+
* @param finalStateKey - The key for the final state.
|
|
23
|
+
* @param vertical - Whether the graph should be vertical.
|
|
24
|
+
* @returns {TransitionsGraph} - The graph with nodes and edges.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export function buildFlatCharts({
|
|
28
|
+
lodash,
|
|
29
|
+
transitions,
|
|
30
|
+
newId,
|
|
31
|
+
getStateParams,
|
|
32
|
+
getTransitionParams,
|
|
33
|
+
padding = [5, 5],
|
|
34
|
+
initialStateKey = "<initial>",
|
|
35
|
+
finalStateKey = "<final>",
|
|
36
|
+
vertical = false,
|
|
37
|
+
}: {
|
|
38
|
+
transitions: Transition[];
|
|
39
|
+
lodash: any;
|
|
40
|
+
newId: (prefix: string) => string;
|
|
41
|
+
initialStateKey?: string;
|
|
42
|
+
finalStateKey?: string;
|
|
43
|
+
vertical?: boolean;
|
|
44
|
+
padding?: Padding;
|
|
45
|
+
} & GraphParamsProvider): TransitionsGraph {
|
|
46
|
+
let prevLodash = getLodash();
|
|
47
|
+
try {
|
|
48
|
+
setLodash(lodash);
|
|
49
|
+
const graph = new Graph({
|
|
50
|
+
directed: true,
|
|
51
|
+
})
|
|
52
|
+
.setGraph({ rankdir: vertical ? "tb" : "lr" })
|
|
53
|
+
.setDefaultEdgeLabel(() => ({}));
|
|
54
|
+
|
|
55
|
+
const nodesIndex: Record<string, string> = {};
|
|
56
|
+
|
|
57
|
+
const getStateNodeId = (key: string, state: string = key) => {
|
|
58
|
+
let id = nodesIndex[key];
|
|
59
|
+
if (!id) {
|
|
60
|
+
id = nodesIndex[key] = newId("s");
|
|
61
|
+
const params = getStateParams(key, state);
|
|
62
|
+
graph.setNode(id, { id, ...params });
|
|
63
|
+
}
|
|
64
|
+
return id;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
for (const [fromState, event, toState] of transitions) {
|
|
68
|
+
const fromStateKey = fromState || initialStateKey;
|
|
69
|
+
const from = getStateNodeId(fromStateKey, fromState);
|
|
70
|
+
const toStateKey = toState || finalStateKey;
|
|
71
|
+
const to = getStateNodeId(toStateKey, toState);
|
|
72
|
+
const params = getTransitionParams(fromStateKey, event, toStateKey);
|
|
73
|
+
graph.setEdge(from, to, {
|
|
74
|
+
id: newId("t"),
|
|
75
|
+
...params,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
layout(graph, { rankdir: vertical ? "tb" : "lr" });
|
|
79
|
+
|
|
80
|
+
const [top, right, bottom, left] = getPadding(padding);
|
|
81
|
+
|
|
82
|
+
const nodes = graph.nodes().map((id: string) => {
|
|
83
|
+
const n = graph.node(id) as StateGraphNode;
|
|
84
|
+
n.x += -n.width / 2;
|
|
85
|
+
n.y += -n.height / 2;
|
|
86
|
+
return n;
|
|
87
|
+
});
|
|
88
|
+
const edges = graph
|
|
89
|
+
.edges()
|
|
90
|
+
.map(({ v, w, name }: { v: string; w: string; name: string }) => {
|
|
91
|
+
const e = graph.edge(v, w, name) as StateGraphEdge;
|
|
92
|
+
e.x += -e.width / 2;
|
|
93
|
+
e.y += -e.height / 2;
|
|
94
|
+
return e;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Get the bounding box of the graph
|
|
98
|
+
let x = 0;
|
|
99
|
+
let y = 0;
|
|
100
|
+
let width = 0;
|
|
101
|
+
let height = 0;
|
|
102
|
+
const addCoords = (node: StateGraphNode | StateGraphEdge) => {
|
|
103
|
+
x = Math.min(x, node.x);
|
|
104
|
+
y = Math.min(y, node.y);
|
|
105
|
+
width = Math.max(width, node.x + node.width);
|
|
106
|
+
height = Math.max(height, node.y + node.height);
|
|
107
|
+
};
|
|
108
|
+
nodes.forEach(addCoords);
|
|
109
|
+
edges.forEach(addCoords);
|
|
110
|
+
edges.forEach((edge) => {
|
|
111
|
+
for (const point of edge.points) {
|
|
112
|
+
x = Math.min(x, edge.x);
|
|
113
|
+
y = Math.min(y, edge.y);
|
|
114
|
+
width = Math.max(width, point.x);
|
|
115
|
+
height = Math.max(height, point.y);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Shift the graph to the origin taking into account the padding
|
|
120
|
+
// Invert coordinates.
|
|
121
|
+
width += left + right;
|
|
122
|
+
height += bottom + top;
|
|
123
|
+
const updateCoords = (node: Position) => {
|
|
124
|
+
node.x = Math.round(node.x + left);
|
|
125
|
+
node.y = Math.round(node.y + bottom);
|
|
126
|
+
// node.y = node.y + bottom;
|
|
127
|
+
};
|
|
128
|
+
const updateBox = (node: Position & Dimensions) => {
|
|
129
|
+
updateCoords(node);
|
|
130
|
+
node.y = Math.round(node.y + node.height);
|
|
131
|
+
};
|
|
132
|
+
nodes.forEach(updateBox);
|
|
133
|
+
edges.forEach(updateBox);
|
|
134
|
+
edges.forEach((edge) => {
|
|
135
|
+
edge.points.forEach(updateCoords);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return { x, y, width, height, nodes, edges };
|
|
139
|
+
} finally {
|
|
140
|
+
setLodash(prevLodash);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Dimensions } from "./Dimensions.ts";
|
|
2
|
+
import { getLabelDimensions } from "./getLabelDimensions.ts";
|
|
3
|
+
import { getPadding } from "../utils/getPadding.ts";
|
|
4
|
+
import type { GraphParamsProvider } from "./GraphParamsProvider.ts";
|
|
5
|
+
import type { Padding } from "./Padding.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Provides default functions measuring dimensions for state nodes and transition edges in the graph.
|
|
9
|
+
* @param fontSize - The font size for the state and transition labels.
|
|
10
|
+
* @param stateFontSize - The font size for the state labels.
|
|
11
|
+
* @param stateTextPadding - The padding around the state labels.
|
|
12
|
+
* @param transitionsFontSize - The font size for the transition labels.
|
|
13
|
+
* @param transitionsTextPadding - The padding around the transition labels.
|
|
14
|
+
*/
|
|
15
|
+
export function getGraphParamsProvider({
|
|
16
|
+
fontSize = 14,
|
|
17
|
+
stateFontSize = fontSize,
|
|
18
|
+
stateTextPadding = 0,
|
|
19
|
+
transitionsFontSize = fontSize,
|
|
20
|
+
transitionsTextPadding = 0,
|
|
21
|
+
}: {
|
|
22
|
+
fontSize?: number;
|
|
23
|
+
stateFontSize?: number;
|
|
24
|
+
stateTextPadding?: Padding;
|
|
25
|
+
transitionsFontSize?: number;
|
|
26
|
+
transitionsTextPadding?: Padding;
|
|
27
|
+
} = {}): GraphParamsProvider {
|
|
28
|
+
return {
|
|
29
|
+
getStateParams: (stateKey: string, state: string = stateKey) => {
|
|
30
|
+
const padding = getPadding(stateTextPadding);
|
|
31
|
+
const fontSize = stateFontSize;
|
|
32
|
+
return {
|
|
33
|
+
...getLabelDimensions(state, {
|
|
34
|
+
padding,
|
|
35
|
+
fontSize,
|
|
36
|
+
}),
|
|
37
|
+
state,
|
|
38
|
+
key: stateKey,
|
|
39
|
+
padding,
|
|
40
|
+
fontSize,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
getTransitionParams: (
|
|
44
|
+
fromStateKey: string,
|
|
45
|
+
event: string,
|
|
46
|
+
toStateKey: string
|
|
47
|
+
): Dimensions & Record<string, any> => {
|
|
48
|
+
const padding = getPadding(transitionsTextPadding);
|
|
49
|
+
const fontSize = transitionsFontSize;
|
|
50
|
+
return {
|
|
51
|
+
...getLabelDimensions(event, {
|
|
52
|
+
padding,
|
|
53
|
+
fontSize,
|
|
54
|
+
}),
|
|
55
|
+
from: fromStateKey,
|
|
56
|
+
event,
|
|
57
|
+
to: toStateKey,
|
|
58
|
+
padding,
|
|
59
|
+
fontSize,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Dimensions } from "./Dimensions.ts";
|
|
2
|
+
import type { Padding } from "./Padding.ts";
|
|
3
|
+
import { getPadding } from "../utils/getPadding.ts";
|
|
4
|
+
|
|
5
|
+
export function getLabelDimensions(
|
|
6
|
+
label: string,
|
|
7
|
+
{
|
|
8
|
+
padding = 0,
|
|
9
|
+
fontSize = 14,
|
|
10
|
+
getCharWidth = () => fontSize / 1.61, // Golden ratio and all that jazz :-)
|
|
11
|
+
lineGap = fontSize * 0.2,
|
|
12
|
+
}: {
|
|
13
|
+
padding?: Padding;
|
|
14
|
+
fontSize?: number;
|
|
15
|
+
getCharWidth?: (char: string) => number;
|
|
16
|
+
lineGap?: number;
|
|
17
|
+
} = {}
|
|
18
|
+
) {
|
|
19
|
+
const lines = [label]; // label.split("\n");
|
|
20
|
+
let dimensions: Dimensions = { width: 0, height: 0 };
|
|
21
|
+
let lineNumber = 0;
|
|
22
|
+
for (const line of lines) {
|
|
23
|
+
if (lineNumber++) dimensions.height += lineGap;
|
|
24
|
+
dimensions = expandBox(
|
|
25
|
+
dimensions,
|
|
26
|
+
getLineDimensions({
|
|
27
|
+
line,
|
|
28
|
+
fontSize,
|
|
29
|
+
getCharWidth,
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
const [top, right, bottom, left] = getPadding(padding);
|
|
34
|
+
return {
|
|
35
|
+
width: Math.round(dimensions.width + left + right),
|
|
36
|
+
height: Math.round(dimensions.height + top + bottom),
|
|
37
|
+
};
|
|
38
|
+
function expandBox(dim1: Dimensions, dim2: Dimensions) {
|
|
39
|
+
return {
|
|
40
|
+
width: Math.round(Math.max(dim1.width, dim2.width)),
|
|
41
|
+
height: Math.round(dim1.height + dim2.height),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getLineDimensions({
|
|
46
|
+
line,
|
|
47
|
+
fontSize = 14,
|
|
48
|
+
getCharWidth = () => fontSize,
|
|
49
|
+
}: {
|
|
50
|
+
line: string;
|
|
51
|
+
fontSize?: number;
|
|
52
|
+
getCharWidth?: (char: string[1]) => number;
|
|
53
|
+
}) {
|
|
54
|
+
return {
|
|
55
|
+
width: line.split("").reduce((w, c) => (w += getCharWidth(c)), 0),
|
|
56
|
+
height: fontSize,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Methods
|
|
2
|
+
export * from "./buildFlatCharts.ts";
|
|
3
|
+
export * from "./buildCharts.ts";
|
|
4
|
+
export * from "./getGraphParamsProvider.ts";
|
|
5
|
+
export * from "./getLabelDimensions.ts";
|
|
6
|
+
|
|
7
|
+
// Types
|
|
8
|
+
export * from "./Dimensions.ts";
|
|
9
|
+
export * from "./GraphParamsProvider.ts";
|
|
10
|
+
export * from "./Padding.ts";
|
|
11
|
+
export * from "./Position.ts";
|
|
12
|
+
export * from "./StateGraphEdge.ts";
|
|
13
|
+
export * from "./StateGraphNode.ts";
|
|
14
|
+
export * from "./Transition.ts";
|
|
15
|
+
export * from "./TransitionsGraph.ts";
|