@statewalker/fsm-charts 0.1.6 → 0.1.8
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/dist/{StateChart-PdtJDEPy.d.ts → StateChart-DlcWaRml.d.ts} +2 -2
- package/dist/{chunk-2BBNBZQI.js → chunk-2XPO6T2M.js} +8 -11
- package/dist/{chunk-NXWOFQMO.js → chunk-FIQDLBWD.js} +1 -2
- package/dist/{chunk-NXS24DZQ.js → chunk-FS3L6FBI.js} +21 -38
- package/dist/chunk-SLWDNGWK.js +133 -0
- package/dist/{chunk-OTGN3OYG.js → chunk-U5LUJ7JS.js} +20 -20
- package/dist/index-config.d.ts +12 -0
- package/dist/index-config.js +1 -0
- package/dist/{index-html-D4UI0s_n.d.ts → index-html-De8e33ol.d.ts} +1 -1
- package/dist/index-html.d.ts +2 -2
- package/dist/index-html.js +2 -3
- package/dist/index-layout.d.ts +8 -5
- package/dist/index-layout.js +2 -3
- package/dist/index-runtime.d.ts +2 -2
- package/dist/index-runtime.js +1 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/src/config/concatTransitionsToString.ts +21 -0
- package/src/config/index.ts +4 -0
- package/src/config/serializeProcessConfig.ts +47 -0
- package/src/config/splitTransitionString.ts +24 -0
- package/src/config/toFsmStateConfig.ts +57 -0
- package/src/full/index.ts +1 -0
- package/src/full/toFsmStateCharts.ts +118 -0
- package/src/index-config.ts +2 -0
- package/src/index.ts +1 -0
- package/src/layout/buildCharts.ts +7 -1
- package/src/layout/buildFlatCharts.ts +8 -5
- package/src/types/FsmStateConfig.ts +11 -2
- package/src/utils/domToText.ts +27 -0
- package/src/utils/newId.ts +5 -0
- package/src/utils/newRegistry.ts +33 -0
- package/dist/chunk-XEO3YXBM.js +0 -8
|
@@ -15,9 +15,9 @@ type Transition = [string, string, string];
|
|
|
15
15
|
|
|
16
16
|
type FsmStateConfig = {
|
|
17
17
|
key: string;
|
|
18
|
-
transitions
|
|
18
|
+
transitions?: Transition[];
|
|
19
19
|
states?: FsmStateConfig[];
|
|
20
|
-
}
|
|
20
|
+
} & Record<string, any>;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Provides default functions measuring dimensions for state nodes and transition edges in the graph.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { getPadding } from './chunk-
|
|
2
|
-
import { __publicField } from './chunk-XEO3YXBM.js';
|
|
1
|
+
import { getPadding } from './chunk-FIQDLBWD.js';
|
|
3
2
|
|
|
4
3
|
// src/utils/toKebabCase.ts
|
|
5
4
|
function toKebabCase(str) {
|
|
@@ -291,8 +290,7 @@ function serializeAttrs(attrs = {}, {
|
|
|
291
290
|
for (const [key, value] of Object.entries(attrs || {}).sort(
|
|
292
291
|
([a], [b]) => a > b ? 1 : -1
|
|
293
292
|
)) {
|
|
294
|
-
if (value === void 0 || value === null || value === "")
|
|
295
|
-
continue;
|
|
293
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
296
294
|
result.push(
|
|
297
295
|
`${prefix}${escapeValue(key)}${"=" + JSON.stringify(
|
|
298
296
|
escapeValue(transform ? toKebabCase(String(value)) : value)
|
|
@@ -308,13 +306,12 @@ function serializeAttrs(attrs = {}, {
|
|
|
308
306
|
// src/utils/BasisCurve.ts
|
|
309
307
|
var BasisCurve = class {
|
|
310
308
|
constructor(context) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
__publicField(this, "_line", 0);
|
|
309
|
+
this._x0 = 0;
|
|
310
|
+
this._y0 = 0;
|
|
311
|
+
this._x1 = 0;
|
|
312
|
+
this._y1 = 0;
|
|
313
|
+
this._point = 0;
|
|
314
|
+
this._line = 0;
|
|
318
315
|
this._context = context;
|
|
319
316
|
}
|
|
320
317
|
$point(x, y) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/utils/getPadding.ts
|
|
2
2
|
function getPadding(padding) {
|
|
3
|
-
if (typeof padding === "number")
|
|
4
|
-
return [padding, padding, padding, padding];
|
|
3
|
+
if (typeof padding === "number") return [padding, padding, padding, padding];
|
|
5
4
|
if (padding.length === 2)
|
|
6
5
|
return [padding[0], padding[1], padding[0], padding[1]];
|
|
7
6
|
return padding;
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { __publicField } from './chunk-XEO3YXBM.js';
|
|
2
|
-
|
|
3
1
|
// src/runtime/RuntimeStatechartApi.ts
|
|
4
2
|
var RuntimeStatechartApi = class {
|
|
5
3
|
constructor({
|
|
6
4
|
element,
|
|
7
5
|
statechart
|
|
8
6
|
}) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
__publicField(this, "_statesClickListeners", {});
|
|
14
|
-
__publicField(this, "_registry", {});
|
|
7
|
+
this._listenersCounter = 0;
|
|
8
|
+
this._transitionsClickListeners = {};
|
|
9
|
+
this._statesClickListeners = {};
|
|
10
|
+
this._registry = {};
|
|
15
11
|
this.element = element;
|
|
16
12
|
this.statechart = statechart;
|
|
17
13
|
this._bindListeners();
|
|
@@ -151,10 +147,8 @@ var RuntimeStatechartApi = class {
|
|
|
151
147
|
}
|
|
152
148
|
_setStatePanelStatus(selector, open) {
|
|
153
149
|
[...this.element.querySelectorAll(selector)].forEach((elm) => {
|
|
154
|
-
if (open)
|
|
155
|
-
|
|
156
|
-
else
|
|
157
|
-
elm.removeAttribute("open");
|
|
150
|
+
if (open) elm.setAttribute("open", "open");
|
|
151
|
+
else elm.removeAttribute("open");
|
|
158
152
|
});
|
|
159
153
|
}
|
|
160
154
|
_addStateModifier(cssSelector, modifier = "selected") {
|
|
@@ -179,8 +173,7 @@ var RuntimeStatechartApi = class {
|
|
|
179
173
|
if (elm.tagName.toLowerCase() === "details") {
|
|
180
174
|
apply(elm, detailsModifier);
|
|
181
175
|
const labelElm = elm.querySelector(".state-details__label");
|
|
182
|
-
if (labelElm)
|
|
183
|
-
apply(labelElm, stateLabelsModifier);
|
|
176
|
+
if (labelElm) apply(labelElm, stateLabelsModifier);
|
|
184
177
|
} else {
|
|
185
178
|
apply(elm, stateModifier);
|
|
186
179
|
}
|
|
@@ -217,12 +210,11 @@ var RuntimeStatechartApi = class {
|
|
|
217
210
|
// src/runtime/StateChartIndex.ts
|
|
218
211
|
var StateChartIndex = class {
|
|
219
212
|
constructor({ statechart }) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
__publicField(this, "_edgesParentsIndex", {});
|
|
213
|
+
this._chartsIndex = {};
|
|
214
|
+
this._nodesIndex = {};
|
|
215
|
+
this._nodesParentsIndex = {};
|
|
216
|
+
this._edgeIndex = {};
|
|
217
|
+
this._edgesParentsIndex = {};
|
|
226
218
|
this.statechart = statechart;
|
|
227
219
|
this._buildIndexes();
|
|
228
220
|
}
|
|
@@ -263,8 +255,7 @@ var StateChartIndex = class {
|
|
|
263
255
|
for (let i = 0; list?.length > 0 && i < stack.length; i++) {
|
|
264
256
|
const key = stack[i];
|
|
265
257
|
const node = list.find((node2) => node2.key === key);
|
|
266
|
-
if (!node)
|
|
267
|
-
break;
|
|
258
|
+
if (!node) break;
|
|
268
259
|
result.push(node.id);
|
|
269
260
|
list = [...node.children || [], ...node.nodes || []];
|
|
270
261
|
}
|
|
@@ -276,16 +267,13 @@ var StateChartIndex = class {
|
|
|
276
267
|
* @returns a stack of nodes
|
|
277
268
|
*/
|
|
278
269
|
getStackByStateId(id) {
|
|
279
|
-
if (!id)
|
|
280
|
-
return [];
|
|
270
|
+
if (!id) return [];
|
|
281
271
|
const node = this._chartsIndex[id] || this._nodesIndex[id];
|
|
282
|
-
if (!node)
|
|
283
|
-
return [];
|
|
272
|
+
if (!node) return [];
|
|
284
273
|
const parentId = this._nodesParentsIndex[id];
|
|
285
274
|
if (parentId) {
|
|
286
275
|
const parentStack = this.getStackByStateId(parentId);
|
|
287
|
-
if (!parentStack.length)
|
|
288
|
-
return [];
|
|
276
|
+
if (!parentStack.length) return [];
|
|
289
277
|
parentStack.push(node);
|
|
290
278
|
return parentStack;
|
|
291
279
|
} else {
|
|
@@ -301,8 +289,7 @@ var StateChartIndex = class {
|
|
|
301
289
|
getTransition(stateId, event) {
|
|
302
290
|
const stack = this.getStackByStateId(stateId);
|
|
303
291
|
const state = stack.pop();
|
|
304
|
-
if (!state || !stack.length)
|
|
305
|
-
return;
|
|
292
|
+
if (!state || !stack.length) return;
|
|
306
293
|
const parent = stack[stack.length - 1];
|
|
307
294
|
const t = parent.edges.find(
|
|
308
295
|
(t2) => t2.from === state.key && t2.event === event
|
|
@@ -317,8 +304,7 @@ var StateChartIndex = class {
|
|
|
317
304
|
getTransitions(stateId) {
|
|
318
305
|
const stack = this.getStackByStateId(stateId);
|
|
319
306
|
const state = stack.pop();
|
|
320
|
-
if (!state || !stack.length)
|
|
321
|
-
return [];
|
|
307
|
+
if (!state || !stack.length) return [];
|
|
322
308
|
const parent = stack[stack.length - 1];
|
|
323
309
|
return parent.edges.filter((t) => t.from === state.key);
|
|
324
310
|
}
|
|
@@ -350,14 +336,11 @@ var StateChartIndex = class {
|
|
|
350
336
|
void 0,
|
|
351
337
|
void 0
|
|
352
338
|
];
|
|
353
|
-
if (!transition)
|
|
354
|
-
return result;
|
|
339
|
+
if (!transition) return result;
|
|
355
340
|
const parentId = this._edgesParentsIndex[transition.id];
|
|
356
|
-
if (!parentId)
|
|
357
|
-
return result;
|
|
341
|
+
if (!parentId) return result;
|
|
358
342
|
const parent = this._chartsIndex[parentId];
|
|
359
|
-
if (!parent)
|
|
360
|
-
return result;
|
|
343
|
+
if (!parent) return result;
|
|
361
344
|
parent.nodes.forEach((node) => {
|
|
362
345
|
if (node.key === transition.from) {
|
|
363
346
|
result[0] = node.id;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/config/concatTransitionsToString.ts
|
|
2
|
+
function concatTransitionsToString(transitions) {
|
|
3
|
+
let list = [];
|
|
4
|
+
let str = "";
|
|
5
|
+
let prev;
|
|
6
|
+
for (const [from, event, to] of transitions) {
|
|
7
|
+
if (prev !== from) {
|
|
8
|
+
if (str) list.push(str);
|
|
9
|
+
str = from;
|
|
10
|
+
}
|
|
11
|
+
str += ` -${escape(event)}-> ${escape(to)}`;
|
|
12
|
+
prev = to;
|
|
13
|
+
}
|
|
14
|
+
if (str) list.push(str);
|
|
15
|
+
return list;
|
|
16
|
+
function escape(str2) {
|
|
17
|
+
return str2;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/config/serializeProcessConfig.ts
|
|
22
|
+
function serializeProcessConfig(config) {
|
|
23
|
+
if (!config) return "";
|
|
24
|
+
let lines = [];
|
|
25
|
+
visit(config, lines);
|
|
26
|
+
return lines.join("\n");
|
|
27
|
+
function visit(config2, lines2, shift = "") {
|
|
28
|
+
lines2.push(`${shift}{`);
|
|
29
|
+
const { key, states, transitions, ...params } = config2;
|
|
30
|
+
lines2.push(`${shift} "key": ${JSON.stringify(key)}`);
|
|
31
|
+
if (transitions && transitions.length > 0) {
|
|
32
|
+
lines2[lines2.length - 1] += ",";
|
|
33
|
+
lines2.push(`${shift} "transitions": [`);
|
|
34
|
+
for (let i = 0; i < transitions.length; i++) {
|
|
35
|
+
if (i > 0) {
|
|
36
|
+
lines2[lines2.length - 1] += ",";
|
|
37
|
+
}
|
|
38
|
+
lines2.push(`${shift} ${JSON.stringify(transitions[i])}`);
|
|
39
|
+
}
|
|
40
|
+
lines2.push(`${shift} ]`);
|
|
41
|
+
}
|
|
42
|
+
if (states && states.length > 0) {
|
|
43
|
+
lines2[lines2.length - 1] += ",";
|
|
44
|
+
lines2.push(`${shift} "states": [`);
|
|
45
|
+
for (let i = 0; i < states.length; i++) {
|
|
46
|
+
if (i > 0) {
|
|
47
|
+
lines2[lines2.length - 1] += ",";
|
|
48
|
+
}
|
|
49
|
+
visit(states[i], lines2, shift + " ");
|
|
50
|
+
}
|
|
51
|
+
lines2.push(`${shift} ]`);
|
|
52
|
+
}
|
|
53
|
+
if (params && Object.keys(params).length > 0) {
|
|
54
|
+
lines2[lines2.length - 1] += ",";
|
|
55
|
+
const str = JSON.stringify(params, null, 2);
|
|
56
|
+
const paramsLines = str.split("\n");
|
|
57
|
+
paramsLines.shift();
|
|
58
|
+
paramsLines.pop();
|
|
59
|
+
lines2.push(...paramsLines.map((line) => shift + line));
|
|
60
|
+
}
|
|
61
|
+
lines2.push(`${shift}}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/config/splitTransitionString.ts
|
|
66
|
+
function splitTransitionString(str) {
|
|
67
|
+
let list = [];
|
|
68
|
+
let pos = 0;
|
|
69
|
+
const matches = Array.from(
|
|
70
|
+
str.matchAll(/-\s*("[^"]*?"|'[^']*?'|[^-]*?)\s*->/g)
|
|
71
|
+
);
|
|
72
|
+
for (const match of matches) {
|
|
73
|
+
list.push(str.substring(pos, match.index));
|
|
74
|
+
list.push(match[1]);
|
|
75
|
+
pos = match.index + match[0].length;
|
|
76
|
+
}
|
|
77
|
+
list.push(str.substring(pos));
|
|
78
|
+
list = list.map((str2) => str2.trim());
|
|
79
|
+
const transitions = [];
|
|
80
|
+
for (let i = 0; i < list.length - 2; ) {
|
|
81
|
+
const from = list[i++] || "";
|
|
82
|
+
const event = list[i++] || "";
|
|
83
|
+
const to = list[i] || "";
|
|
84
|
+
transitions.push([from, event, to]);
|
|
85
|
+
}
|
|
86
|
+
return transitions;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/config/toFsmStateConfig.ts
|
|
90
|
+
function toFsmStateConfig(json) {
|
|
91
|
+
if (!json || typeof json !== "object") return;
|
|
92
|
+
const { key, transitions, states, ...options } = json;
|
|
93
|
+
if (typeof key !== "string") return;
|
|
94
|
+
const stateTransitions = toFsmTransitions(transitions);
|
|
95
|
+
const substates = toArray(states).map(toFsmStateConfig).filter((v) => !!v);
|
|
96
|
+
const state = {
|
|
97
|
+
key,
|
|
98
|
+
transitions: stateTransitions
|
|
99
|
+
};
|
|
100
|
+
if (substates && substates.length > 0) state.states = substates;
|
|
101
|
+
return Object.assign(state, options);
|
|
102
|
+
function toFsmTransitions(json2) {
|
|
103
|
+
const transitions2 = [];
|
|
104
|
+
const index = {};
|
|
105
|
+
const array = toArray(json2);
|
|
106
|
+
for (let line of array) {
|
|
107
|
+
const lineTransitions = typeof line === "string" ? splitTransitionString(line) : [toArray(line)];
|
|
108
|
+
for (const transition of lineTransitions.map(validateTransition)) {
|
|
109
|
+
if (!transition) continue;
|
|
110
|
+
const key2 = transition.join("|");
|
|
111
|
+
if (key2 in index) continue;
|
|
112
|
+
index[key2] = true;
|
|
113
|
+
transitions2.push(transition);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return transitions2;
|
|
117
|
+
}
|
|
118
|
+
function validateTransition(value) {
|
|
119
|
+
const array = toArray(value);
|
|
120
|
+
if (array.length !== 3) return;
|
|
121
|
+
const [from, event, to] = array;
|
|
122
|
+
if (typeof from !== "string" || typeof event !== "string" || typeof to !== "string")
|
|
123
|
+
return;
|
|
124
|
+
return [from, event, to];
|
|
125
|
+
}
|
|
126
|
+
function toArray(value) {
|
|
127
|
+
if (value === void 0) return [];
|
|
128
|
+
if (Array.isArray(value)) return value;
|
|
129
|
+
return [value];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPadding } from './chunk-
|
|
1
|
+
import { getPadding } from './chunk-FIQDLBWD.js';
|
|
2
2
|
|
|
3
3
|
// src/lodash-es/index.ts
|
|
4
4
|
var _ = {
|
|
@@ -891,8 +891,7 @@ function normalizeEdge(g, e) {
|
|
|
891
891
|
var name = e.name;
|
|
892
892
|
var edgeLabel = g.edge(e);
|
|
893
893
|
var labelRank = edgeLabel.labelRank;
|
|
894
|
-
if (wRank === vRank + 1)
|
|
895
|
-
return;
|
|
894
|
+
if (wRank === vRank + 1) return;
|
|
896
895
|
g.removeEdge(e);
|
|
897
896
|
var dummy, attrs, i;
|
|
898
897
|
for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
|
|
@@ -1351,8 +1350,7 @@ function buildLayerGraph(g, rank2, relationship) {
|
|
|
1351
1350
|
}
|
|
1352
1351
|
function createRootNode(g) {
|
|
1353
1352
|
var v;
|
|
1354
|
-
while (g.hasNode(v = _.uniqueId("_root")))
|
|
1355
|
-
;
|
|
1353
|
+
while (g.hasNode(v = _.uniqueId("_root"))) ;
|
|
1356
1354
|
return v;
|
|
1357
1355
|
}
|
|
1358
1356
|
|
|
@@ -1382,8 +1380,7 @@ function twoLayerCrossCount(g, northLayer, southLayer) {
|
|
|
1382
1380
|
})
|
|
1383
1381
|
);
|
|
1384
1382
|
var firstIndex = 1;
|
|
1385
|
-
while (firstIndex < southLayer.length)
|
|
1386
|
-
firstIndex <<= 1;
|
|
1383
|
+
while (firstIndex < southLayer.length) firstIndex <<= 1;
|
|
1387
1384
|
var treeSize = 2 * firstIndex - 1;
|
|
1388
1385
|
firstIndex -= 1;
|
|
1389
1386
|
var tree = _.map(new Array(treeSize), function() {
|
|
@@ -1424,8 +1421,7 @@ function initOrder(g) {
|
|
|
1424
1421
|
return [];
|
|
1425
1422
|
});
|
|
1426
1423
|
function dfs3(v) {
|
|
1427
|
-
if (_.has(visited, v))
|
|
1428
|
-
return;
|
|
1424
|
+
if (_.has(visited, v)) return;
|
|
1429
1425
|
visited[v] = true;
|
|
1430
1426
|
var node = g.node(v);
|
|
1431
1427
|
layers[node.rank].push(v);
|
|
@@ -1947,8 +1943,7 @@ function alignCoordinates(xss, alignTo) {
|
|
|
1947
1943
|
_.forEach(["u", "d"], function(vert) {
|
|
1948
1944
|
_.forEach(["l", "r"], function(horiz) {
|
|
1949
1945
|
var alignment = vert + horiz, xs = xss[alignment], delta;
|
|
1950
|
-
if (xs === alignTo)
|
|
1951
|
-
return;
|
|
1946
|
+
if (xs === alignTo) return;
|
|
1952
1947
|
var xsVals = _.values(xs);
|
|
1953
1948
|
delta = horiz === "l" ? alignToMin - _.min(xsVals) : alignToMax - _.max(xsVals);
|
|
1954
1949
|
if (delta) {
|
|
@@ -2461,22 +2456,24 @@ function canonicalize(attrs) {
|
|
|
2461
2456
|
// src/layout/buildFlatCharts.ts
|
|
2462
2457
|
function buildFlatCharts({
|
|
2463
2458
|
lodash,
|
|
2464
|
-
transitions,
|
|
2459
|
+
transitions = [],
|
|
2465
2460
|
newId,
|
|
2466
2461
|
getStateParams,
|
|
2467
2462
|
getTransitionParams,
|
|
2468
2463
|
padding = [5, 5],
|
|
2469
2464
|
initialStateKey = "<initial>",
|
|
2470
2465
|
finalStateKey = "<final>",
|
|
2471
|
-
vertical = false
|
|
2466
|
+
vertical = false,
|
|
2467
|
+
direction
|
|
2472
2468
|
}) {
|
|
2473
2469
|
let prevLodash = getLodash();
|
|
2474
2470
|
try {
|
|
2475
2471
|
setLodash(lodash);
|
|
2472
|
+
const rankdir = direction || (vertical ? "tb" : "lr");
|
|
2476
2473
|
const graph = new Graph({
|
|
2477
2474
|
directed: true,
|
|
2478
2475
|
multigraph: true
|
|
2479
|
-
}).setGraph({ rankdir
|
|
2476
|
+
}).setGraph({ rankdir, multigraph: true });
|
|
2480
2477
|
const nodesIndex = {};
|
|
2481
2478
|
const getStateNodeId = (key, state = key) => {
|
|
2482
2479
|
let id = nodesIndex[key];
|
|
@@ -2504,7 +2501,7 @@ function buildFlatCharts({
|
|
|
2504
2501
|
edgeId
|
|
2505
2502
|
);
|
|
2506
2503
|
}
|
|
2507
|
-
layout(graph, { rankdir
|
|
2504
|
+
layout(graph, { rankdir });
|
|
2508
2505
|
const [top, right, bottom, left] = getPadding(padding);
|
|
2509
2506
|
const nodes = graph.nodes().map((id) => {
|
|
2510
2507
|
const n = graph.node(id);
|
|
@@ -2567,20 +2564,24 @@ function buildCharts({
|
|
|
2567
2564
|
getStateParams,
|
|
2568
2565
|
getTransitionParams,
|
|
2569
2566
|
padding = [5, 5],
|
|
2567
|
+
vertical = false,
|
|
2570
2568
|
initialStateKey = "<initial>",
|
|
2571
|
-
finalStateKey = "<final>"
|
|
2569
|
+
finalStateKey = "<final>",
|
|
2570
|
+
direction
|
|
2572
2571
|
}) {
|
|
2573
2572
|
return buildChart(config);
|
|
2574
2573
|
function buildChart(config2, id = newId("s")) {
|
|
2575
2574
|
const graph = buildFlatCharts({
|
|
2576
2575
|
lodash,
|
|
2577
|
-
transitions: config2.transitions,
|
|
2576
|
+
transitions: config2.transitions || [],
|
|
2578
2577
|
newId,
|
|
2579
2578
|
getStateParams,
|
|
2580
2579
|
getTransitionParams,
|
|
2581
2580
|
padding,
|
|
2582
2581
|
initialStateKey,
|
|
2583
|
-
finalStateKey
|
|
2582
|
+
finalStateKey,
|
|
2583
|
+
vertical,
|
|
2584
|
+
direction
|
|
2584
2585
|
});
|
|
2585
2586
|
const index = graph.nodes.reduce((index2, node) => {
|
|
2586
2587
|
index2[node.key] = node.id;
|
|
@@ -2615,8 +2616,7 @@ function getLabelDimensions(label, {
|
|
|
2615
2616
|
let dimensions = { width: 0, height: 0 };
|
|
2616
2617
|
let lineNumber = 0;
|
|
2617
2618
|
for (const line of lines) {
|
|
2618
|
-
if (lineNumber++)
|
|
2619
|
-
dimensions.height += lineGap;
|
|
2619
|
+
if (lineNumber++) dimensions.height += lineGap;
|
|
2620
2620
|
dimensions = expandBox(
|
|
2621
2621
|
dimensions,
|
|
2622
2622
|
getLineDimensions({
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { T as Transition, F as FsmStateConfig } from './StateChart-DlcWaRml.js';
|
|
2
|
+
export { D as Dimensions, G as GraphParamsProvider, P as Padding, a as Position, S as StateChart, b as StateGraphEdge, c as StateGraphNode, d as TransitionsGraph } from './StateChart-DlcWaRml.js';
|
|
3
|
+
|
|
4
|
+
declare function concatTransitionsToString(transitions: Transition[]): string[];
|
|
5
|
+
|
|
6
|
+
declare function serializeProcessConfig(config: FsmStateConfig | undefined): string;
|
|
7
|
+
|
|
8
|
+
declare function splitTransitionString(str: string): Transition[];
|
|
9
|
+
|
|
10
|
+
declare function toFsmStateConfig(json: any): FsmStateConfig | undefined;
|
|
11
|
+
|
|
12
|
+
export { FsmStateConfig, Transition, concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './chunk-SLWDNGWK.js';
|
package/dist/index-html.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { D as Dimensions, F as FsmStateConfig, G as GraphParamsProvider, P as Padding, a as Position, S as StateChart, b as StateGraphEdge, c as StateGraphNode, T as Transition, d as TransitionsGraph } from './StateChart-
|
|
2
|
-
export { c as activeStatesStyle, d as activeTransitionsStyle, f as buildStateDetailsStyle, g as buildStateDetailsStyleWithModifier, b as buildStatechartCss, i as buildStatechartStyles, h as buildStatechartStylesWithModifier, j as buildStatechartSvg, a as buildStatechartsPanel, s as selectedStatesStyle, e as selectedTransitionsStyle } from './index-html-
|
|
1
|
+
export { D as Dimensions, F as FsmStateConfig, G as GraphParamsProvider, P as Padding, a as Position, S as StateChart, b as StateGraphEdge, c as StateGraphNode, T as Transition, d as TransitionsGraph } from './StateChart-DlcWaRml.js';
|
|
2
|
+
export { c as activeStatesStyle, d as activeTransitionsStyle, f as buildStateDetailsStyle, g as buildStateDetailsStyleWithModifier, b as buildStatechartCss, i as buildStatechartStyles, h as buildStatechartStylesWithModifier, j as buildStatechartSvg, a as buildStatechartsPanel, s as selectedStatesStyle, e as selectedTransitionsStyle } from './index-html-De8e33ol.js';
|
package/dist/index-html.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export { activeStatesStyle, activeTransitionsStyle, buildStateDetailsStyle, buildStateDetailsStyleWithModifier, buildStatechartCss, buildStatechartStyles, buildStatechartStylesWithModifier, buildStatechartSvg, buildStatechartsPanel, selectedStatesStyle, selectedTransitionsStyle } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-XEO3YXBM.js';
|
|
1
|
+
export { activeStatesStyle, activeTransitionsStyle, buildStateDetailsStyle, buildStateDetailsStyleWithModifier, buildStatechartCss, buildStatechartStyles, buildStatechartStylesWithModifier, buildStatechartSvg, buildStatechartsPanel, selectedStatesStyle, selectedTransitionsStyle } from './chunk-2XPO6T2M.js';
|
|
2
|
+
import './chunk-FIQDLBWD.js';
|
package/dist/index-layout.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as Transition, P as Padding, G as GraphParamsProvider, d as TransitionsGraph, F as FsmStateConfig, S as StateChart } from './StateChart-
|
|
2
|
-
export { D as Dimensions, a as Position, b as StateGraphEdge, c as StateGraphNode } from './StateChart-
|
|
1
|
+
import { T as Transition, P as Padding, G as GraphParamsProvider, d as TransitionsGraph, F as FsmStateConfig, S as StateChart } from './StateChart-DlcWaRml.js';
|
|
2
|
+
export { D as Dimensions, a as Position, b as StateGraphEdge, c as StateGraphNode } from './StateChart-DlcWaRml.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Build graphs corresponding to the specified transitions.
|
|
@@ -12,14 +12,15 @@ export { D as Dimensions, a as Position, b as StateGraphEdge, c as StateGraphNod
|
|
|
12
12
|
* @param vertical - Whether the graph should be vertical.
|
|
13
13
|
* @returns {TransitionsGraph} - The graph with nodes and edges.
|
|
14
14
|
*/
|
|
15
|
-
declare function buildFlatCharts({ lodash, transitions, newId, getStateParams, getTransitionParams, padding, initialStateKey, finalStateKey, vertical, }: {
|
|
16
|
-
transitions
|
|
15
|
+
declare function buildFlatCharts({ lodash, transitions, newId, getStateParams, getTransitionParams, padding, initialStateKey, finalStateKey, vertical, direction, }: {
|
|
16
|
+
transitions?: Transition[];
|
|
17
17
|
lodash: any;
|
|
18
18
|
newId: (prefix: string) => string;
|
|
19
19
|
initialStateKey?: string;
|
|
20
20
|
finalStateKey?: string;
|
|
21
21
|
vertical?: boolean;
|
|
22
22
|
padding?: Padding;
|
|
23
|
+
direction?: "tb" | "bt" | "lr" | "rl";
|
|
23
24
|
} & GraphParamsProvider): TransitionsGraph;
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -32,13 +33,15 @@ declare function buildFlatCharts({ lodash, transitions, newId, getStateParams, g
|
|
|
32
33
|
* @param finalStateKey - The key for the final state.
|
|
33
34
|
* @returns {StateChart} - The graph with nodes and edges.
|
|
34
35
|
*/
|
|
35
|
-
declare function buildCharts({ lodash, config, newId, getStateParams, getTransitionParams, padding, initialStateKey, finalStateKey, }: {
|
|
36
|
+
declare function buildCharts({ lodash, config, newId, getStateParams, getTransitionParams, padding, vertical, initialStateKey, finalStateKey, direction, }: {
|
|
36
37
|
config: FsmStateConfig;
|
|
37
38
|
lodash: any;
|
|
38
39
|
newId: (prefix: string) => string;
|
|
39
40
|
initialStateKey?: string;
|
|
40
41
|
finalStateKey?: string;
|
|
41
42
|
padding?: Padding;
|
|
43
|
+
vertical?: boolean;
|
|
44
|
+
direction?: "tb" | "bt" | "lr" | "rl";
|
|
42
45
|
} & GraphParamsProvider): StateChart;
|
|
43
46
|
|
|
44
47
|
/**
|
package/dist/index-layout.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-XEO3YXBM.js';
|
|
1
|
+
export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-U5LUJ7JS.js';
|
|
2
|
+
import './chunk-FIQDLBWD.js';
|
package/dist/index-runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as StateChart, c as StateGraphNode, b as StateGraphEdge } from './StateChart-
|
|
2
|
-
export { D as Dimensions, F as FsmStateConfig, G as GraphParamsProvider, P as Padding, a as Position, T as Transition, d as TransitionsGraph } from './StateChart-
|
|
1
|
+
import { S as StateChart, c as StateGraphNode, b as StateGraphEdge } from './StateChart-DlcWaRml.js';
|
|
2
|
+
export { D as Dimensions, F as FsmStateConfig, G as GraphParamsProvider, P as Padding, a as Position, T as Transition, d as TransitionsGraph } from './StateChart-DlcWaRml.js';
|
|
3
3
|
|
|
4
4
|
type RuntimeListener = (id: string) => void;
|
|
5
5
|
declare class RuntimeStatechartApi {
|
package/dist/index-runtime.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export { RuntimeStatechartApi, StateChartIndex } from './chunk-
|
|
2
|
-
import './chunk-XEO3YXBM.js';
|
|
1
|
+
export { RuntimeStatechartApi, StateChartIndex } from './chunk-FS3L6FBI.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { D as Dimensions, F as FsmStateConfig, G as GraphParamsProvider, P as Padding, a as Position, S as StateChart, b as StateGraphEdge, c as StateGraphNode, T as Transition, d as TransitionsGraph } from './StateChart-
|
|
1
|
+
export { D as Dimensions, F as FsmStateConfig, G as GraphParamsProvider, P as Padding, a as Position, S as StateChart, b as StateGraphEdge, c as StateGraphNode, T as Transition, d as TransitionsGraph } from './StateChart-DlcWaRml.js';
|
|
2
|
+
export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './index-config.js';
|
|
2
3
|
export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './index-layout.js';
|
|
3
|
-
export { C as CssTree, c as activeStatesStyle, d as activeTransitionsStyle, f as buildStateDetailsStyle, g as buildStateDetailsStyleWithModifier, b as buildStatechartCss, i as buildStatechartStyles, h as buildStatechartStylesWithModifier, j as buildStatechartSvg, a as buildStatechartsPanel, s as selectedStatesStyle, e as selectedTransitionsStyle, k as serializeCss } from './index-html-
|
|
4
|
+
export { C as CssTree, c as activeStatesStyle, d as activeTransitionsStyle, f as buildStateDetailsStyle, g as buildStateDetailsStyleWithModifier, b as buildStatechartCss, i as buildStatechartStyles, h as buildStatechartStylesWithModifier, j as buildStatechartSvg, a as buildStatechartsPanel, s as selectedStatesStyle, e as selectedTransitionsStyle, k as serializeCss } from './index-html-De8e33ol.js';
|
|
4
5
|
export { RuntimeListener, RuntimeStatechartApi, StateChartIndex } from './index-runtime.js';
|
|
5
6
|
|
|
6
7
|
declare function toKebabCase(str?: string): string;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './chunk-SLWDNGWK.js';
|
|
2
|
+
export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-U5LUJ7JS.js';
|
|
3
|
+
export { activeStatesStyle, activeTransitionsStyle, buildStateDetailsStyle, buildStateDetailsStyleWithModifier, buildStatechartCss, buildStatechartStyles, buildStatechartStylesWithModifier, buildStatechartSvg, buildStatechartsPanel, selectedStatesStyle, selectedTransitionsStyle, serializeCss, toKebabCase } from './chunk-2XPO6T2M.js';
|
|
4
|
+
import './chunk-FIQDLBWD.js';
|
|
5
|
+
export { RuntimeStatechartApi, StateChartIndex } from './chunk-FS3L6FBI.js';
|
package/package.json
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Transition } from "../types/index.ts";
|
|
2
|
+
|
|
3
|
+
export function concatTransitionsToString(transitions: Transition[]) {
|
|
4
|
+
let list: string[] = [];
|
|
5
|
+
let str: string = "";
|
|
6
|
+
let prev: undefined | string;
|
|
7
|
+
for (const [from, event, to] of transitions) {
|
|
8
|
+
if (prev !== from) {
|
|
9
|
+
if (str) list.push(str);
|
|
10
|
+
str = from;
|
|
11
|
+
}
|
|
12
|
+
str += ` -${escape(event)}-> ${escape(to)}`;
|
|
13
|
+
prev = to;
|
|
14
|
+
}
|
|
15
|
+
if (str) list.push(str);
|
|
16
|
+
return list;
|
|
17
|
+
|
|
18
|
+
function escape(str: string): string {
|
|
19
|
+
return str;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { FsmStateConfig } from "../types/index.ts";
|
|
2
|
+
|
|
3
|
+
export function serializeProcessConfig(config: FsmStateConfig | undefined) {
|
|
4
|
+
if (!config) return "";
|
|
5
|
+
let lines: string[] = [];
|
|
6
|
+
visit(config, lines);
|
|
7
|
+
return lines.join("\n");
|
|
8
|
+
|
|
9
|
+
function visit(config: FsmStateConfig, lines: string[], shift = "") {
|
|
10
|
+
lines.push(`${shift}{`);
|
|
11
|
+
const { key, states, transitions, ...params } = config;
|
|
12
|
+
lines.push(`${shift} "key": ${JSON.stringify(key)}`);
|
|
13
|
+
if (transitions && transitions.length > 0) {
|
|
14
|
+
lines[lines.length - 1] += ",";
|
|
15
|
+
lines.push(`${shift} "transitions": [`);
|
|
16
|
+
for (let i = 0; i < transitions.length; i++) {
|
|
17
|
+
if (i > 0) {
|
|
18
|
+
lines[lines.length - 1] += ",";
|
|
19
|
+
}
|
|
20
|
+
lines.push(`${shift} ${JSON.stringify(transitions[i])}`);
|
|
21
|
+
}
|
|
22
|
+
lines.push(`${shift} ]`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (states && states.length > 0) {
|
|
26
|
+
lines[lines.length - 1] += ",";
|
|
27
|
+
lines.push(`${shift} "states": [`);
|
|
28
|
+
for (let i = 0; i < states.length; i++) {
|
|
29
|
+
if (i > 0) {
|
|
30
|
+
lines[lines.length - 1] += ",";
|
|
31
|
+
}
|
|
32
|
+
visit(states[i], lines, shift + " ");
|
|
33
|
+
}
|
|
34
|
+
lines.push(`${shift} ]`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (params && Object.keys(params).length > 0) {
|
|
38
|
+
lines[lines.length - 1] += ",";
|
|
39
|
+
const str = JSON.stringify(params, null, 2);
|
|
40
|
+
const paramsLines = str.split("\n");
|
|
41
|
+
paramsLines.shift();
|
|
42
|
+
paramsLines.pop();
|
|
43
|
+
lines.push(...paramsLines.map((line) => shift + line));
|
|
44
|
+
}
|
|
45
|
+
lines.push(`${shift}}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Transition } from "../types/index.ts";
|
|
2
|
+
|
|
3
|
+
export function splitTransitionString(str: string): Transition[] {
|
|
4
|
+
let list: string[] = [];
|
|
5
|
+
let pos = 0;
|
|
6
|
+
const matches = Array.from(
|
|
7
|
+
str.matchAll(/-\s*("[^"]*?"|'[^']*?'|[^-]*?)\s*->/g)
|
|
8
|
+
);
|
|
9
|
+
for (const match of matches) {
|
|
10
|
+
list.push(str.substring(pos, match.index));
|
|
11
|
+
list.push(match[1]);
|
|
12
|
+
pos = match.index + match[0].length;
|
|
13
|
+
}
|
|
14
|
+
list.push(str.substring(pos));
|
|
15
|
+
list = list.map((str) => str.trim());
|
|
16
|
+
const transitions: Transition[] = [];
|
|
17
|
+
for (let i = 0; i < list.length - 2; ) {
|
|
18
|
+
const from = list[i++] || "";
|
|
19
|
+
const event = list[i++] || "";
|
|
20
|
+
const to = list[i] || "";
|
|
21
|
+
transitions.push([from, event, to]);
|
|
22
|
+
}
|
|
23
|
+
return transitions;
|
|
24
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { splitTransitionString } from "./splitTransitionString.ts";
|
|
2
|
+
import type { FsmStateConfig, Transition } from "../types/index.ts";
|
|
3
|
+
|
|
4
|
+
export function toFsmStateConfig(json: any): FsmStateConfig | undefined {
|
|
5
|
+
if (!json || typeof json !== "object") return;
|
|
6
|
+
const { key, transitions, states, ...options } = json;
|
|
7
|
+
if (typeof key !== "string") return;
|
|
8
|
+
const stateTransitions = toFsmTransitions(transitions);
|
|
9
|
+
const substates = toArray(states)
|
|
10
|
+
.map(toFsmStateConfig)
|
|
11
|
+
.filter((v) => !!v) as FsmStateConfig[];
|
|
12
|
+
const state: FsmStateConfig = {
|
|
13
|
+
key,
|
|
14
|
+
transitions: stateTransitions,
|
|
15
|
+
};
|
|
16
|
+
if (substates && substates.length > 0) state.states = substates;
|
|
17
|
+
return Object.assign(state, options);
|
|
18
|
+
|
|
19
|
+
function toFsmTransitions(json: any): Transition[] {
|
|
20
|
+
const transitions: Transition[] = [];
|
|
21
|
+
const index: Record<string, boolean> = {};
|
|
22
|
+
const array = toArray(json);
|
|
23
|
+
for (let line of array) {
|
|
24
|
+
const lineTransitions =
|
|
25
|
+
typeof line === "string"
|
|
26
|
+
? splitTransitionString(line)
|
|
27
|
+
: [toArray(line)];
|
|
28
|
+
for (const transition of lineTransitions.map(validateTransition)) {
|
|
29
|
+
if (!transition) continue;
|
|
30
|
+
const key = transition.join("|");
|
|
31
|
+
if (key in index) continue;
|
|
32
|
+
index[key] = true;
|
|
33
|
+
transitions.push(transition);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return transitions;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function validateTransition(value: any): Transition | undefined {
|
|
40
|
+
const array = toArray(value);
|
|
41
|
+
if (array.length !== 3) return;
|
|
42
|
+
const [from, event, to] = array;
|
|
43
|
+
if (
|
|
44
|
+
typeof from !== "string" ||
|
|
45
|
+
typeof event !== "string" ||
|
|
46
|
+
typeof to !== "string"
|
|
47
|
+
)
|
|
48
|
+
return;
|
|
49
|
+
return [from, event, to];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function toArray(value: any) {
|
|
53
|
+
if (value === undefined) return [];
|
|
54
|
+
if (Array.isArray(value)) return value;
|
|
55
|
+
return [value];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./toFsmStateCharts.ts";
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { newId } from "../utils/newId.ts";
|
|
2
|
+
import { newRegistry } from "../utils/newRegistry.ts";
|
|
3
|
+
import { RuntimeStatechartApi, StateChartIndex } from "../runtime/index.ts";
|
|
4
|
+
import {
|
|
5
|
+
buildStatechartCss,
|
|
6
|
+
buildStatechartsPanel,
|
|
7
|
+
FsmStateConfig,
|
|
8
|
+
StateChart,
|
|
9
|
+
StateGraphEdge,
|
|
10
|
+
} from "../index-html.ts";
|
|
11
|
+
import { buildCharts, getGraphParamsProvider } from "../index-layout.ts";
|
|
12
|
+
|
|
13
|
+
export type FsmStateCharts = {
|
|
14
|
+
api: RuntimeStatechartApi;
|
|
15
|
+
index: StateChartIndex;
|
|
16
|
+
statechart: StateChart;
|
|
17
|
+
html: string;
|
|
18
|
+
element: HTMLElement;
|
|
19
|
+
|
|
20
|
+
register: (action: () => void) => () => void;
|
|
21
|
+
cleanup: () => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function toFsmStateCharts({
|
|
25
|
+
config,
|
|
26
|
+
lodash,
|
|
27
|
+
onTransitionClick,
|
|
28
|
+
}: {
|
|
29
|
+
onTransitionClick: (transition: StateGraphEdge) => unknown;
|
|
30
|
+
config: FsmStateConfig;
|
|
31
|
+
lodash: any;
|
|
32
|
+
}): FsmStateCharts {
|
|
33
|
+
const statechart = buildCharts({
|
|
34
|
+
lodash,
|
|
35
|
+
newId,
|
|
36
|
+
config,
|
|
37
|
+
padding: [15, 15],
|
|
38
|
+
...getGraphParamsProvider({
|
|
39
|
+
// fontSize: 14,
|
|
40
|
+
stateFontSize: 14,
|
|
41
|
+
stateTextPadding: [14, 16],
|
|
42
|
+
transitionsFontSize: 12,
|
|
43
|
+
transitionsTextPadding: 6,
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
const index = new StateChartIndex({ statechart });
|
|
47
|
+
|
|
48
|
+
const lines: string[] = [];
|
|
49
|
+
buildStatechartsPanel({
|
|
50
|
+
statechart,
|
|
51
|
+
newId,
|
|
52
|
+
println: (str) => lines.push(str),
|
|
53
|
+
});
|
|
54
|
+
const html = lines.join("\n");
|
|
55
|
+
const statechartId = newId("statechart");
|
|
56
|
+
const css = buildStatechartCss({
|
|
57
|
+
// prefix: `#${statechartId}`
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const container = document.createElement("div");
|
|
61
|
+
container.innerHTML = `${html}
|
|
62
|
+
<style>
|
|
63
|
+
${css}
|
|
64
|
+
#${statechartId} {
|
|
65
|
+
padding: 0.5em 0;
|
|
66
|
+
}
|
|
67
|
+
</style>`;
|
|
68
|
+
container.id = statechartId;
|
|
69
|
+
// const style = container.querySelector("style");
|
|
70
|
+
|
|
71
|
+
const [register, cleanup] = newRegistry();
|
|
72
|
+
register(() => {
|
|
73
|
+
container.remove();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const api = new RuntimeStatechartApi({
|
|
77
|
+
element: container,
|
|
78
|
+
statechart,
|
|
79
|
+
});
|
|
80
|
+
const topNodeId = index.getStackByStateId(statechart.id)[0].id;
|
|
81
|
+
// api.selectState(topNodeId);
|
|
82
|
+
api.openStatePanel(topNodeId);
|
|
83
|
+
|
|
84
|
+
register(
|
|
85
|
+
api.onStateClick((stateId) => {
|
|
86
|
+
const nodes = index.getStackByStateId(stateId);
|
|
87
|
+
const nodeIds = nodes.map((n) => n.id);
|
|
88
|
+
api.deselectTransitions();
|
|
89
|
+
const selected = api.toggleState(...nodeIds);
|
|
90
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
91
|
+
const node = nodes[i];
|
|
92
|
+
const stateId = node.id;
|
|
93
|
+
if (i < nodes.length - 1 || selected) {
|
|
94
|
+
const transitions = index.getTransitions(stateId);
|
|
95
|
+
transitions.forEach((t) => api.selectTransition(t.id));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
if (onTransitionClick) {
|
|
102
|
+
register(
|
|
103
|
+
api.onTransitionClick((transitionId) => {
|
|
104
|
+
const transition = index.getEdgeById(transitionId);
|
|
105
|
+
transition && onTransitionClick(transition);
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
register,
|
|
111
|
+
cleanup,
|
|
112
|
+
statechart,
|
|
113
|
+
api,
|
|
114
|
+
html,
|
|
115
|
+
element: container,
|
|
116
|
+
index,
|
|
117
|
+
};
|
|
118
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -21,8 +21,10 @@ export function buildCharts({
|
|
|
21
21
|
getStateParams,
|
|
22
22
|
getTransitionParams,
|
|
23
23
|
padding = [5, 5],
|
|
24
|
+
vertical = false,
|
|
24
25
|
initialStateKey = "<initial>",
|
|
25
26
|
finalStateKey = "<final>",
|
|
27
|
+
direction,
|
|
26
28
|
}: {
|
|
27
29
|
config: FsmStateConfig;
|
|
28
30
|
lodash: any;
|
|
@@ -30,6 +32,8 @@ export function buildCharts({
|
|
|
30
32
|
initialStateKey?: string;
|
|
31
33
|
finalStateKey?: string;
|
|
32
34
|
padding?: Padding;
|
|
35
|
+
vertical?: boolean;
|
|
36
|
+
direction?: "tb" | "bt" | "lr" | "rl";
|
|
33
37
|
} & GraphParamsProvider): StateChart {
|
|
34
38
|
return buildChart(config);
|
|
35
39
|
|
|
@@ -39,13 +43,15 @@ export function buildCharts({
|
|
|
39
43
|
): StateChart {
|
|
40
44
|
const graph = buildFlatCharts({
|
|
41
45
|
lodash,
|
|
42
|
-
transitions: config.transitions,
|
|
46
|
+
transitions: config.transitions || [],
|
|
43
47
|
newId,
|
|
44
48
|
getStateParams,
|
|
45
49
|
getTransitionParams,
|
|
46
50
|
padding,
|
|
47
51
|
initialStateKey,
|
|
48
52
|
finalStateKey,
|
|
53
|
+
vertical,
|
|
54
|
+
direction
|
|
49
55
|
});
|
|
50
56
|
const index = graph.nodes.reduce((index, node) => {
|
|
51
57
|
index[node.key as string] = node.id as string;
|
|
@@ -27,7 +27,7 @@ import { getLodash, setLodash } from "../lodash-es/index.ts";
|
|
|
27
27
|
|
|
28
28
|
export function buildFlatCharts({
|
|
29
29
|
lodash,
|
|
30
|
-
transitions,
|
|
30
|
+
transitions = [],
|
|
31
31
|
newId,
|
|
32
32
|
getStateParams,
|
|
33
33
|
getTransitionParams,
|
|
@@ -35,22 +35,25 @@ export function buildFlatCharts({
|
|
|
35
35
|
initialStateKey = "<initial>",
|
|
36
36
|
finalStateKey = "<final>",
|
|
37
37
|
vertical = false,
|
|
38
|
+
direction,
|
|
38
39
|
}: {
|
|
39
|
-
transitions
|
|
40
|
+
transitions?: Transition[];
|
|
40
41
|
lodash: any;
|
|
41
42
|
newId: (prefix: string) => string;
|
|
42
43
|
initialStateKey?: string;
|
|
43
44
|
finalStateKey?: string;
|
|
44
45
|
vertical?: boolean;
|
|
45
46
|
padding?: Padding;
|
|
47
|
+
direction?: "tb" | "bt" | "lr" | "rl";
|
|
46
48
|
} & GraphParamsProvider): TransitionsGraph {
|
|
47
49
|
let prevLodash = getLodash();
|
|
48
50
|
try {
|
|
49
51
|
setLodash(lodash);
|
|
52
|
+
const rankdir = direction || (vertical ? "tb" : "lr");
|
|
50
53
|
const graph = new Graph({
|
|
51
54
|
directed: true,
|
|
52
55
|
multigraph: true,
|
|
53
|
-
}).setGraph({ rankdir
|
|
56
|
+
}).setGraph({ rankdir, multigraph: true });
|
|
54
57
|
|
|
55
58
|
const nodesIndex: Record<string, string> = {};
|
|
56
59
|
|
|
@@ -78,10 +81,10 @@ export function buildFlatCharts({
|
|
|
78
81
|
id: edgeId,
|
|
79
82
|
...params,
|
|
80
83
|
},
|
|
81
|
-
edgeId
|
|
84
|
+
edgeId,
|
|
82
85
|
);
|
|
83
86
|
}
|
|
84
|
-
layout(graph, { rankdir
|
|
87
|
+
layout(graph, { rankdir });
|
|
85
88
|
|
|
86
89
|
const [top, right, bottom, left] = getPadding(padding);
|
|
87
90
|
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import type { Transition } from "./Transition.ts";
|
|
2
2
|
|
|
3
|
+
// export type FsmStateKey = string;
|
|
4
|
+
// export type FsmEventKey = string;
|
|
5
|
+
// export type FsmTransition = [FsmStateKey, FsmEventKey, FsmStateKey];
|
|
6
|
+
// export type FsmState = {
|
|
7
|
+
// key: string;
|
|
8
|
+
// transitions: FsmTransition[];
|
|
9
|
+
// states?: FsmState[];
|
|
10
|
+
// } & Record<string, any>;
|
|
11
|
+
|
|
3
12
|
export type FsmStateConfig = {
|
|
4
13
|
key: string;
|
|
5
|
-
transitions
|
|
14
|
+
transitions?: Transition[];
|
|
6
15
|
states?: FsmStateConfig[];
|
|
7
|
-
}
|
|
16
|
+
} & Record<string, any>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function domToText(elm: HTMLElement) {
|
|
2
|
+
const lines: string[] = [];
|
|
3
|
+
visit(elm, (node) => {
|
|
4
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
5
|
+
lines.push(node.textContent || "");
|
|
6
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
7
|
+
if (
|
|
8
|
+
node.nodeName === "BR" ||
|
|
9
|
+
node.nodeName === "P" ||
|
|
10
|
+
node.nodeName === "DIV"
|
|
11
|
+
) {
|
|
12
|
+
lines.push("\n");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
return lines.join("");
|
|
17
|
+
|
|
18
|
+
function visit(el: HTMLElement, visitor: (node: Node) => void) {
|
|
19
|
+
for (var i = 0; i < el.childNodes.length; i++) {
|
|
20
|
+
const child = el.childNodes[i];
|
|
21
|
+
const result = visitor(el.childNodes[i]);
|
|
22
|
+
if (child.nodeType !== Node.ELEMENT_NODE) continue;
|
|
23
|
+
if (result !== undefined && !Boolean(result)) continue;
|
|
24
|
+
visit(child as HTMLElement, visitor);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type Registry = [
|
|
2
|
+
register: (action: () => unknown) => (skipCall?: boolean) => void,
|
|
3
|
+
clear: () => void,
|
|
4
|
+
unregister: (action: () => unknown) => void,
|
|
5
|
+
];
|
|
6
|
+
|
|
7
|
+
export function newRegistry(
|
|
8
|
+
onError: (error: any) => unknown = console.error,
|
|
9
|
+
): Registry {
|
|
10
|
+
let counter = 0;
|
|
11
|
+
const registrations: Record<
|
|
12
|
+
number,
|
|
13
|
+
((skip?: boolean) => void) & { action: () => void }
|
|
14
|
+
> = {};
|
|
15
|
+
const register = (action: () => unknown) => {
|
|
16
|
+
const id = counter++;
|
|
17
|
+
return (registrations[id] = Object.assign(
|
|
18
|
+
function (skip?: boolean) {
|
|
19
|
+
try {
|
|
20
|
+
delete registrations[id];
|
|
21
|
+
return !skip && action && action();
|
|
22
|
+
} catch (error) {
|
|
23
|
+
onError(error);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{ action },
|
|
27
|
+
));
|
|
28
|
+
};
|
|
29
|
+
const unregister = (action: () => void) =>
|
|
30
|
+
Object.values(registrations).forEach((r) => r.action === action && r(true));
|
|
31
|
+
const clear = () => Object.values(registrations).forEach((r) => r());
|
|
32
|
+
return [register, clear, unregister];
|
|
33
|
+
}
|
package/dist/chunk-XEO3YXBM.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => {
|
|
4
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
return value;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export { __publicField };
|