@statewalker/fsm-charts 0.2.5 → 0.2.6
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/README.md +206 -1
- package/dist/StateChart-cXyVRcs-.d.ts +94 -0
- package/dist/StateChart-cXyVRcs-.d.ts.map +1 -0
- package/dist/StateChartIndex-BK2315qj.d.ts +142 -0
- package/dist/StateChartIndex-BK2315qj.d.ts.map +1 -0
- package/dist/StateChartIndex-BOIrc_nq.js +355 -0
- package/dist/StateChartIndex-BOIrc_nq.js.map +1 -0
- package/dist/buildStatechartsPanel-CxQlIwTh.js +494 -0
- package/dist/buildStatechartsPanel-CxQlIwTh.js.map +1 -0
- package/dist/buildStatechartsPanel-hCtZbdiF.d.ts +79 -0
- package/dist/buildStatechartsPanel-hCtZbdiF.d.ts.map +1 -0
- package/dist/defineProperty-C0rC37pP.js +39 -0
- package/dist/description-panels-DI2MNlbK.js +184 -0
- package/dist/description-panels-DI2MNlbK.js.map +1 -0
- package/dist/getLabelDimensions-BY0q7j3D.d.ts +79 -0
- package/dist/getLabelDimensions-BY0q7j3D.d.ts.map +1 -0
- package/dist/getPadding-Cw0e7G2v.js +25 -0
- package/dist/getPadding-Cw0e7G2v.js.map +1 -0
- package/dist/index-config.d.ts +3 -12
- package/dist/index-config.js +2 -2
- package/dist/index-dom.d.ts +2 -49
- package/dist/index-dom.js +2 -2
- package/dist/index-html.d.ts +3 -2
- package/dist/index-html.js +2 -3
- package/dist/index-layout.d.ts +3 -77
- package/dist/index-layout.js +2 -3
- package/dist/index-runtime.d.ts +3 -141
- package/dist/index-runtime.js +2 -2
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -7
- package/dist/layout-Dp671N6q.js +2465 -0
- package/dist/layout-Dp671N6q.js.map +1 -0
- package/dist/newTreeBuilder-CvtLDjGj.d.ts +54 -0
- package/dist/newTreeBuilder-CvtLDjGj.d.ts.map +1 -0
- package/dist/toFsmStateConfig-DlJkyZni.js +135 -0
- package/dist/toFsmStateConfig-DlJkyZni.js.map +1 -0
- package/dist/toFsmStateConfig-DmOlTRjv.d.ts +15 -0
- package/dist/toFsmStateConfig-DmOlTRjv.d.ts.map +1 -0
- package/package.json +53 -25
- package/src/config/concatTransitionsToString.ts +2 -2
- package/src/config/splitTransitionString.ts +1 -3
- package/src/config/toFsmStateConfig.ts +2 -9
- package/src/dom/buildSections.ts +3 -11
- package/src/dom/description-panels.ts +2 -4
- package/src/dom/getStatesDescriptions.ts +3 -9
- package/src/full/toFsmStateCharts.ts +1 -1
- package/src/html/buildStatechartStyles.ts +4 -14
- package/src/html/buildStatechartSvg.ts +2 -14
- package/src/html/buildStatechartsPanel.ts +1 -3
- package/src/layout/buildCharts.ts +1 -2
- package/src/layout/buildFlatCharts.ts +6 -8
- package/src/layout/getGraphParamsProvider.ts +3 -12
- package/src/runtime/RuntimeStatechartApi.ts +10 -32
- package/src/runtime/StateChartIndex.ts +6 -23
- package/src/types/GraphParamsProvider.ts +1 -4
- package/src/utils/BasisCurve.ts +5 -14
- package/src/utils/domToText.ts +2 -6
- package/src/utils/getPadding.ts +1 -2
- package/src/utils/newId.ts +2 -1
- package/src/utils/newRegistry.ts +12 -12
- package/src/utils/serializeAttrs.ts +3 -11
- package/src/utils/serializeCss.ts +1 -5
- package/src/utils/serializeStyle.ts +1 -4
- package/src/utils/toKebabCase.ts +1 -4
- package/dist/StateChart-BYBjTmC2.d.ts +0 -82
- package/dist/chunk-2LFUT2C6.js +0 -2691
- package/dist/chunk-ARZYBFNA.js +0 -133
- package/dist/chunk-CR2M4445.js +0 -608
- package/dist/chunk-FIQDLBWD.js +0 -9
- package/dist/chunk-GW2Z65BN.js +0 -429
- package/dist/chunk-PKBMQBKP.js +0 -5
- package/dist/chunk-RZ4FP6JB.js +0 -233
- package/dist/index-html-BBQqYoST.d.ts +0 -75
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { l as FsmStateConfig, u as Transition } from "./StateChart-cXyVRcs-.js";
|
|
2
|
+
//#region src/config/concatTransitionsToString.d.ts
|
|
3
|
+
declare function concatTransitionsToString(transitions: Transition[]): string[];
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/config/serializeProcessConfig.d.ts
|
|
6
|
+
declare function serializeProcessConfig(config: FsmStateConfig | undefined): string;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/config/splitTransitionString.d.ts
|
|
9
|
+
declare function splitTransitionString(str: string): Transition[];
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/config/toFsmStateConfig.d.ts
|
|
12
|
+
declare function toFsmStateConfig(json: any): FsmStateConfig | undefined;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { concatTransitionsToString as i, splitTransitionString as n, serializeProcessConfig as r, toFsmStateConfig as t };
|
|
15
|
+
//# sourceMappingURL=toFsmStateConfig-DmOlTRjv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toFsmStateConfig-DmOlTRjv.d.ts","names":[],"sources":["../src/config/concatTransitionsToString.ts","../src/config/serializeProcessConfig.ts","../src/config/splitTransitionString.ts","../src/config/toFsmStateConfig.ts"],"mappings":";;iBAEgB,0BAA0B,aAAa;;;iBCAvC,uBAAuB,QAAQ;;;iBCA/B,sBAAsB,cAAc;;;iBCCpC,iBAAiB,YAAY"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statewalker/fsm-charts",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "Statechart layout, SVG rendering and runtime binding for hierarchical finite state machines",
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/statewalker/statewalker-fsm/issues"
|
|
7
|
+
},
|
|
5
8
|
"keywords": [],
|
|
6
|
-
"homepage": "https://github.com/statewalker/statewalker-fsm-charts",
|
|
9
|
+
"homepage": "https://github.com/statewalker/statewalker-fsm/tree/main/packages/fsm-charts#readme",
|
|
7
10
|
"author": {
|
|
8
11
|
"name": "Mikhail Kotelnikov",
|
|
9
12
|
"email": "mikhail.kotelnikov@gmail.com"
|
|
@@ -26,40 +29,65 @@
|
|
|
26
29
|
"types": "./dist/index.d.ts",
|
|
27
30
|
"import": "./dist/index.js",
|
|
28
31
|
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./config": {
|
|
34
|
+
"source": "./src/index-config.ts",
|
|
35
|
+
"types": "./dist/index-config.d.ts",
|
|
36
|
+
"import": "./dist/index-config.js",
|
|
37
|
+
"default": "./dist/index-config.js"
|
|
38
|
+
},
|
|
39
|
+
"./dom": {
|
|
40
|
+
"source": "./src/index-dom.ts",
|
|
41
|
+
"types": "./dist/index-dom.d.ts",
|
|
42
|
+
"import": "./dist/index-dom.js",
|
|
43
|
+
"default": "./dist/index-dom.js"
|
|
44
|
+
},
|
|
45
|
+
"./html": {
|
|
46
|
+
"source": "./src/index-html.ts",
|
|
47
|
+
"types": "./dist/index-html.d.ts",
|
|
48
|
+
"import": "./dist/index-html.js",
|
|
49
|
+
"default": "./dist/index-html.js"
|
|
50
|
+
},
|
|
51
|
+
"./layout": {
|
|
52
|
+
"source": "./src/index-layout.ts",
|
|
53
|
+
"types": "./dist/index-layout.d.ts",
|
|
54
|
+
"import": "./dist/index-layout.js",
|
|
55
|
+
"default": "./dist/index-layout.js"
|
|
56
|
+
},
|
|
57
|
+
"./runtime": {
|
|
58
|
+
"source": "./src/index-runtime.ts",
|
|
59
|
+
"types": "./dist/index-runtime.d.ts",
|
|
60
|
+
"import": "./dist/index-runtime.js",
|
|
61
|
+
"default": "./dist/index-runtime.js"
|
|
29
62
|
}
|
|
30
63
|
},
|
|
31
64
|
"devDependencies": {
|
|
32
|
-
"@types/jsdom": "
|
|
33
|
-
"@types/lodash-es": "
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"lodash": "catalog:",
|
|
42
|
-
"lodash-es": "catalog:",
|
|
43
|
-
"tsup": "catalog:",
|
|
44
|
-
"typescript": "*",
|
|
45
|
-
"vitest": "catalog:"
|
|
65
|
+
"@types/jsdom": "^30.0.0",
|
|
66
|
+
"@types/lodash-es": "^4.17.12",
|
|
67
|
+
"eslint": "^10.12.0",
|
|
68
|
+
"jsdom": "^30.1.1",
|
|
69
|
+
"lodash": "^4.18.1",
|
|
70
|
+
"lodash-es": "^4.18.1",
|
|
71
|
+
"tsdown": "^0.23.0",
|
|
72
|
+
"typescript": "^7.0.2",
|
|
73
|
+
"vitest": "^5.0.3"
|
|
46
74
|
},
|
|
47
75
|
"repository": {
|
|
48
76
|
"type": "git",
|
|
49
|
-
"url": "git
|
|
77
|
+
"url": "git+https://github.com/statewalker/statewalker-fsm.git",
|
|
78
|
+
"directory": "packages/fsm-charts"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
50
82
|
},
|
|
51
83
|
"scripts": {
|
|
52
|
-
"build": "rm -fr ./dist && pnpm test &&
|
|
53
|
-
"watch": "
|
|
54
|
-
"watch-for-viewer": "tsup --watch --outDir=../statewalker-fsm-viewer/src/.observablehq/cache/_node/@statewalker/fsm-charts@0.2.1",
|
|
84
|
+
"build": "rm -fr ./dist && pnpm test && tsdown",
|
|
85
|
+
"watch": "tsdown --watch",
|
|
55
86
|
"clean": "rm -rf dist",
|
|
56
87
|
"lint": "eslint",
|
|
57
88
|
"lint:fix": "pnpm lint --fix",
|
|
58
89
|
"test": "vitest --run",
|
|
59
90
|
"test:watch": "vitest",
|
|
60
91
|
"prepublish": "pnpm build"
|
|
61
|
-
},
|
|
62
|
-
"publishConfig": {
|
|
63
|
-
"access": "public"
|
|
64
92
|
}
|
|
65
|
-
}
|
|
93
|
+
}
|
|
@@ -9,13 +9,13 @@ export function concatTransitionsToString(transitions: Transition[]) {
|
|
|
9
9
|
if (str) list.push(str);
|
|
10
10
|
str = from;
|
|
11
11
|
}
|
|
12
|
-
str += ` -${
|
|
12
|
+
str += ` -${escapeLabel(event)}-> ${escapeLabel(to)}`;
|
|
13
13
|
prev = to;
|
|
14
14
|
}
|
|
15
15
|
if (str) list.push(str);
|
|
16
16
|
return list;
|
|
17
17
|
|
|
18
|
-
function
|
|
18
|
+
function escapeLabel(str: string): string {
|
|
19
19
|
return str;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -3,9 +3,7 @@ import type { Transition } from "../types/index.js";
|
|
|
3
3
|
export function splitTransitionString(str: string): Transition[] {
|
|
4
4
|
let list: string[] = [];
|
|
5
5
|
let pos = 0;
|
|
6
|
-
const matches = Array.from(
|
|
7
|
-
str.matchAll(/-\s*("[^"]*?"|'[^']*?'|[^-]*?)\s*->/g),
|
|
8
|
-
);
|
|
6
|
+
const matches = Array.from(str.matchAll(/-\s*("[^"]*?"|'[^']*?'|[^-]*?)\s*->/g));
|
|
9
7
|
for (const match of matches) {
|
|
10
8
|
list.push(str.substring(pos, match.index));
|
|
11
9
|
list.push(match[1]);
|
|
@@ -22,9 +22,7 @@ export function toFsmStateConfig(json: any): FsmStateConfig | undefined {
|
|
|
22
22
|
const array = toArray(json);
|
|
23
23
|
for (const line of array) {
|
|
24
24
|
const lineTransitions =
|
|
25
|
-
typeof line === "string"
|
|
26
|
-
? splitTransitionString(line)
|
|
27
|
-
: [toArray(line)];
|
|
25
|
+
typeof line === "string" ? splitTransitionString(line) : [toArray(line)];
|
|
28
26
|
for (const transition of lineTransitions.map(validateTransition)) {
|
|
29
27
|
if (!transition) continue;
|
|
30
28
|
const key = transition.join("|");
|
|
@@ -40,12 +38,7 @@ export function toFsmStateConfig(json: any): FsmStateConfig | undefined {
|
|
|
40
38
|
const array = toArray(value);
|
|
41
39
|
if (array.length !== 3) return;
|
|
42
40
|
const [from, event, to] = array;
|
|
43
|
-
if (
|
|
44
|
-
typeof from !== "string" ||
|
|
45
|
-
typeof event !== "string" ||
|
|
46
|
-
typeof to !== "string"
|
|
47
|
-
)
|
|
48
|
-
return;
|
|
41
|
+
if (typeof from !== "string" || typeof event !== "string" || typeof to !== "string") return;
|
|
49
42
|
return [from, event, to];
|
|
50
43
|
}
|
|
51
44
|
|
package/src/dom/buildSections.ts
CHANGED
|
@@ -38,10 +38,7 @@ export function buildSections(root: HTMLElement | Iterable<Node>): DomSection {
|
|
|
38
38
|
if (isDomElement(node)) {
|
|
39
39
|
if (/^H[1-6]$/i.test(node.tagName)) {
|
|
40
40
|
const headerLevel = +node.tagName.replace(/^H/, "");
|
|
41
|
-
while (
|
|
42
|
-
headerLevels.length > 0 &&
|
|
43
|
-
headerLevels[headerLevels.length - 1] >= headerLevel
|
|
44
|
-
) {
|
|
41
|
+
while (headerLevels.length > 0 && headerLevels[headerLevels.length - 1] >= headerLevel) {
|
|
45
42
|
headerLevels.pop();
|
|
46
43
|
}
|
|
47
44
|
headerLevels.push(headerLevel);
|
|
@@ -76,10 +73,7 @@ export function* vistSections(
|
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
75
|
|
|
79
|
-
export function findSection(
|
|
80
|
-
section: DomSection,
|
|
81
|
-
accept: (section: DomSection) => boolean,
|
|
82
|
-
) {
|
|
76
|
+
export function findSection(section: DomSection, accept: (section: DomSection) => boolean) {
|
|
83
77
|
for (const s of vistSections(section)) {
|
|
84
78
|
if (accept(s) === true) return s;
|
|
85
79
|
}
|
|
@@ -93,9 +87,7 @@ export function isDomElement(node: Node): node is HTMLElement {
|
|
|
93
87
|
return node.nodeType === Node.ELEMENT_NODE;
|
|
94
88
|
}
|
|
95
89
|
|
|
96
|
-
export function* toDomNodesIterator(
|
|
97
|
-
root: Node | Iterable<Node>,
|
|
98
|
-
): Iterable<Node> {
|
|
90
|
+
export function* toDomNodesIterator(root: Node | Iterable<Node>): Iterable<Node> {
|
|
99
91
|
yield* root instanceof Node ? visitDom(root) : root;
|
|
100
92
|
}
|
|
101
93
|
|
|
@@ -4,9 +4,7 @@ import { getStatesDescriptions } from "./getStatesDescriptions.js";
|
|
|
4
4
|
export function getStateDescriptionRenderer(options: {
|
|
5
5
|
element: HTMLElement;
|
|
6
6
|
rootStateKey: string;
|
|
7
|
-
splitHeader?: (
|
|
8
|
-
header?: HTMLElement,
|
|
9
|
-
) => [stateKey: undefined | string, label: string];
|
|
7
|
+
splitHeader?: (header?: HTMLElement) => [stateKey: undefined | string, label: string];
|
|
10
8
|
}) {
|
|
11
9
|
const descriptionsIndex = getStatesDescriptions(options);
|
|
12
10
|
|
|
@@ -28,7 +26,7 @@ export function getStateDescriptionRenderer(options: {
|
|
|
28
26
|
},
|
|
29
27
|
});
|
|
30
28
|
const details = elm?.querySelector("details");
|
|
31
|
-
|
|
29
|
+
if (details) details.open = true;
|
|
32
30
|
return elm;
|
|
33
31
|
};
|
|
34
32
|
}
|
|
@@ -14,9 +14,7 @@ export function* visitStateDescriptions({
|
|
|
14
14
|
element,
|
|
15
15
|
rootStateKey,
|
|
16
16
|
removeFromDom = true,
|
|
17
|
-
splitHeader = (
|
|
18
|
-
header?: HTMLElement,
|
|
19
|
-
): [stateKey: undefined | string, label: string] => {
|
|
17
|
+
splitHeader = (header?: HTMLElement): [stateKey: undefined | string, label: string] => {
|
|
20
18
|
if (!header) return [undefined, ""];
|
|
21
19
|
const text = header.innerText.trim();
|
|
22
20
|
let key: string | undefined;
|
|
@@ -32,9 +30,7 @@ export function* visitStateDescriptions({
|
|
|
32
30
|
element: HTMLElement;
|
|
33
31
|
rootStateKey: string;
|
|
34
32
|
removeFromDom?: boolean; // If true - removes state description nodes from the DOM
|
|
35
|
-
splitHeader?: (
|
|
36
|
-
header?: HTMLElement,
|
|
37
|
-
) => [stateKey: undefined | string, label: string];
|
|
33
|
+
splitHeader?: (header?: HTMLElement) => [stateKey: undefined | string, label: string];
|
|
38
34
|
}): Generator<StateDescriptionSection> {
|
|
39
35
|
const docSections = buildSections(element);
|
|
40
36
|
const rootDescription = findSection(docSections, (section: DomSection) => {
|
|
@@ -68,9 +64,7 @@ export function getStatesDescriptions(options: {
|
|
|
68
64
|
element: HTMLElement;
|
|
69
65
|
rootStateKey: string;
|
|
70
66
|
removeFromDom?: boolean; // If true - removes state description nodes from the DOM
|
|
71
|
-
splitHeader?: (
|
|
72
|
-
header?: HTMLElement,
|
|
73
|
-
) => [stateKey: undefined | string, label: string];
|
|
67
|
+
splitHeader?: (header?: HTMLElement) => [stateKey: undefined | string, label: string];
|
|
74
68
|
}): { [state: string]: StateDescriptionSection } {
|
|
75
69
|
const index: { [state: string]: StateDescriptionSection } = {};
|
|
76
70
|
for (const description of visitStateDescriptions(options)) {
|
|
@@ -92,7 +92,7 @@ ${css}
|
|
|
92
92
|
const stateId = node.id;
|
|
93
93
|
if (i < nodes.length - 1 || selected) {
|
|
94
94
|
const transitions = index.getTransitions(stateId);
|
|
95
|
-
|
|
95
|
+
for (const t of transitions) api.selectTransition(t.id);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
// api.focusStates(...nodeIds);
|
|
@@ -30,11 +30,7 @@ export const selectedTransitionsStyle = {
|
|
|
30
30
|
labelColor: "navy",
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export function buildStateDetailsStyle({
|
|
34
|
-
root = ":root",
|
|
35
|
-
}: {
|
|
36
|
-
root?: string;
|
|
37
|
-
}): CssTree {
|
|
33
|
+
export function buildStateDetailsStyle({ root = ":root" }: { root?: string }): CssTree {
|
|
38
34
|
return {
|
|
39
35
|
[root]: {
|
|
40
36
|
// --------------------------
|
|
@@ -42,8 +38,7 @@ export function buildStateDetailsStyle({
|
|
|
42
38
|
|
|
43
39
|
".state-details": {
|
|
44
40
|
backgroundColor: "var(--state-background-color, white)",
|
|
45
|
-
border:
|
|
46
|
-
"var(--state-border-width, 1px) solid var(--state-border-color, currentColor)",
|
|
41
|
+
border: "var(--state-border-width, 1px) solid var(--state-border-color, currentColor)",
|
|
47
42
|
borderRadius: "0.5em",
|
|
48
43
|
padding: "0.5em",
|
|
49
44
|
},
|
|
@@ -109,8 +104,7 @@ export function buildStatechartStylesWithModifier({
|
|
|
109
104
|
[root]: {
|
|
110
105
|
// --------------------------------------
|
|
111
106
|
// Default values for transitions
|
|
112
|
-
[`--transition-${modifier}-background-color`]:
|
|
113
|
-
transitions.backgroundColor,
|
|
107
|
+
[`--transition-${modifier}-background-color`]: transitions.backgroundColor,
|
|
114
108
|
[`--transition-${modifier}-border-color`]: transitions.borderColor,
|
|
115
109
|
[`--transition-${modifier}-border-width`]: transitions.borderWidth,
|
|
116
110
|
[`--transition-${modifier}-line-color`]: transitions.lineColor,
|
|
@@ -147,11 +141,7 @@ export function buildStatechartStylesWithModifier({
|
|
|
147
141
|
};
|
|
148
142
|
}
|
|
149
143
|
|
|
150
|
-
export function buildStatechartStyles({
|
|
151
|
-
root = ":root",
|
|
152
|
-
}: {
|
|
153
|
-
root?: string;
|
|
154
|
-
}): CssTree {
|
|
144
|
+
export function buildStatechartStyles({ root = ":root" }: { root?: string }): CssTree {
|
|
155
145
|
return {
|
|
156
146
|
[root]: {
|
|
157
147
|
// --------------------------------------
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Dimensions,
|
|
3
|
-
Padding,
|
|
4
|
-
Position,
|
|
5
|
-
TransitionsGraph,
|
|
6
|
-
} from "../types/index.js";
|
|
1
|
+
import type { Dimensions, Padding, Position, TransitionsGraph } from "../types/index.js";
|
|
7
2
|
import { BasisCurve } from "../utils/BasisCurve.js";
|
|
8
3
|
import { getPadding } from "../utils/getPadding.js";
|
|
9
4
|
import { serializeAttrs } from "../utils/serializeAttrs.js";
|
|
@@ -93,14 +88,7 @@ export function buildStatechartSvg({
|
|
|
93
88
|
const path: string[] = [];
|
|
94
89
|
const round = (...n: number[]) => n.map(Math.round);
|
|
95
90
|
const base = new BasisCurve({
|
|
96
|
-
bezierCurveTo(
|
|
97
|
-
x0: number,
|
|
98
|
-
y0: number,
|
|
99
|
-
x1: number,
|
|
100
|
-
y1: number,
|
|
101
|
-
x2: number,
|
|
102
|
-
y2: number,
|
|
103
|
-
) {
|
|
91
|
+
bezierCurveTo(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number) {
|
|
104
92
|
path.push(`C${round(x0, y0, x1, y1, x2, y2).join(",")}`);
|
|
105
93
|
},
|
|
106
94
|
moveTo(x: number, y: number) {
|
|
@@ -17,9 +17,7 @@ export function buildStatechartsPanel({
|
|
|
17
17
|
render(statechart, println);
|
|
18
18
|
|
|
19
19
|
function render(statechart: StateChart, println: (str: string) => void) {
|
|
20
|
-
println(
|
|
21
|
-
` <details class="state-details" data-state-id="${statechart.id}">`,
|
|
22
|
-
);
|
|
20
|
+
println(` <details class="state-details" data-state-id="${statechart.id}">`);
|
|
23
21
|
println(
|
|
24
22
|
` <summary class="state-details__label">${statechart.text ?? statechart.state}</summary>`,
|
|
25
23
|
);
|
|
@@ -19,8 +19,7 @@ export function buildCharts({
|
|
|
19
19
|
config,
|
|
20
20
|
newId,
|
|
21
21
|
getStateParams,
|
|
22
|
-
getStateLabel = (stateKey: string) =>
|
|
23
|
-
stateKey.replace(/([a-z])([A-Z])/g, "$1 $2"),
|
|
22
|
+
getStateLabel = (stateKey: string) => stateKey.replace(/([a-z])([A-Z])/g, "$1 $2"),
|
|
24
23
|
getTransitionParams,
|
|
25
24
|
padding = [5, 5],
|
|
26
25
|
vertical = false,
|
|
@@ -92,14 +92,12 @@ export function buildFlatCharts({
|
|
|
92
92
|
n.y += -n.height / 2;
|
|
93
93
|
return n;
|
|
94
94
|
});
|
|
95
|
-
const edges = graph
|
|
96
|
-
.
|
|
97
|
-
.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return e;
|
|
102
|
-
});
|
|
95
|
+
const edges = graph.edges().map(({ v, w, name }: { v: string; w: string; name: string }) => {
|
|
96
|
+
const e = graph.edge(v, w, name) as StateGraphEdge;
|
|
97
|
+
e.x += -e.width / 2;
|
|
98
|
+
e.y += -e.height / 2;
|
|
99
|
+
return e;
|
|
100
|
+
});
|
|
103
101
|
|
|
104
102
|
// Get the bounding box of the graph
|
|
105
103
|
let x = 0;
|
|
@@ -18,8 +18,7 @@ export function getGraphParamsProvider({
|
|
|
18
18
|
transitionsFontSize = fontSize,
|
|
19
19
|
transitionsTextPadding = 0,
|
|
20
20
|
getStateLabel = (state: string) => state,
|
|
21
|
-
getTransitionLabel = (_fromState: string, event: string, _toState: string) =>
|
|
22
|
-
event,
|
|
21
|
+
getTransitionLabel = (_fromState: string, event: string, _toState: string) => event,
|
|
23
22
|
}: {
|
|
24
23
|
fontSize?: number;
|
|
25
24
|
stateFontSize?: number;
|
|
@@ -27,11 +26,7 @@ export function getGraphParamsProvider({
|
|
|
27
26
|
transitionsFontSize?: number;
|
|
28
27
|
transitionsTextPadding?: Padding;
|
|
29
28
|
getStateLabel?: (state: string) => string;
|
|
30
|
-
getTransitionLabel?: (
|
|
31
|
-
fromState: string,
|
|
32
|
-
event: string,
|
|
33
|
-
toState: string,
|
|
34
|
-
) => string;
|
|
29
|
+
getTransitionLabel?: (fromState: string, event: string, toState: string) => string;
|
|
35
30
|
} = {}): GraphParamsProvider {
|
|
36
31
|
return {
|
|
37
32
|
getStateParams: (stateKey: string, state: string = stateKey) => {
|
|
@@ -50,11 +45,7 @@ export function getGraphParamsProvider({
|
|
|
50
45
|
fontSize,
|
|
51
46
|
};
|
|
52
47
|
},
|
|
53
|
-
getTransitionParams: (
|
|
54
|
-
fromStateKey: string,
|
|
55
|
-
event: string,
|
|
56
|
-
toStateKey: string,
|
|
57
|
-
) => {
|
|
48
|
+
getTransitionParams: (fromStateKey: string, event: string, toStateKey: string) => {
|
|
58
49
|
const padding = getPadding(transitionsTextPadding);
|
|
59
50
|
const fontSize = transitionsFontSize;
|
|
60
51
|
const eventLabel = getTransitionLabel(fromStateKey, event, toStateKey);
|
|
@@ -22,7 +22,7 @@ export class RuntimeStatechartApi {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
close() {
|
|
25
|
-
Object.values(this._registry)
|
|
25
|
+
for (const r of Object.values(this._registry)) r?.();
|
|
26
26
|
this._registry = {};
|
|
27
27
|
this._transitionsClickListeners = {};
|
|
28
28
|
this._statesClickListeners = {};
|
|
@@ -73,9 +73,7 @@ export class RuntimeStatechartApi {
|
|
|
73
73
|
for (let i = 0; i < stateIds.length; i++) {
|
|
74
74
|
const stateId = stateIds[i];
|
|
75
75
|
for (const tagName of ["details", "g"]) {
|
|
76
|
-
const elm = this.element.querySelector(
|
|
77
|
-
`${tagName}[data-state-id="${stateId}"]`,
|
|
78
|
-
);
|
|
76
|
+
const elm = this.element.querySelector(`${tagName}[data-state-id="${stateId}"]`);
|
|
79
77
|
elm?.scrollIntoView();
|
|
80
78
|
}
|
|
81
79
|
}
|
|
@@ -153,10 +151,7 @@ export class RuntimeStatechartApi {
|
|
|
153
151
|
dataField: string,
|
|
154
152
|
eventType: string,
|
|
155
153
|
) => {
|
|
156
|
-
function newEventListener(
|
|
157
|
-
index: Record<string, RuntimeListener>,
|
|
158
|
-
elm: Element,
|
|
159
|
-
) {
|
|
154
|
+
function newEventListener(index: Record<string, RuntimeListener>, elm: Element) {
|
|
160
155
|
return (ev: Event) => {
|
|
161
156
|
ev.preventDefault();
|
|
162
157
|
ev.stopPropagation();
|
|
@@ -174,17 +169,11 @@ export class RuntimeStatechartApi {
|
|
|
174
169
|
[...this.element.querySelectorAll(`[${dataField}]`)].forEach((elm) => {
|
|
175
170
|
const eventListener = newEventListener(index, elm);
|
|
176
171
|
elm.addEventListener(eventType, eventListener);
|
|
177
|
-
this._addListener(this._registry, () =>
|
|
178
|
-
elm.removeEventListener(eventType, eventListener),
|
|
179
|
-
);
|
|
172
|
+
this._addListener(this._registry, () => elm.removeEventListener(eventType, eventListener));
|
|
180
173
|
});
|
|
181
174
|
};
|
|
182
175
|
bindListeners(this._statesClickListeners, "data-state-id", "click");
|
|
183
|
-
bindListeners(
|
|
184
|
-
this._transitionsClickListeners,
|
|
185
|
-
"data-transition-id",
|
|
186
|
-
"click",
|
|
187
|
-
);
|
|
176
|
+
bindListeners(this._transitionsClickListeners, "data-transition-id", "click");
|
|
188
177
|
}
|
|
189
178
|
|
|
190
179
|
_setStatePanelStatus(selector: string, open: boolean) {
|
|
@@ -195,14 +184,10 @@ export class RuntimeStatechartApi {
|
|
|
195
184
|
}
|
|
196
185
|
|
|
197
186
|
_addStateModifier(cssSelector: string, modifier: string = "selected") {
|
|
198
|
-
this._applyStateModifier(cssSelector, modifier, (elm, cls) =>
|
|
199
|
-
elm?.classList.add(cls),
|
|
200
|
-
);
|
|
187
|
+
this._applyStateModifier(cssSelector, modifier, (elm, cls) => elm?.classList.add(cls));
|
|
201
188
|
}
|
|
202
189
|
_removeStateModifier(cssSelector: string, modifier: string = "selected") {
|
|
203
|
-
this._applyStateModifier(cssSelector, modifier, (elm, cls) =>
|
|
204
|
-
elm?.classList.remove(cls),
|
|
205
|
-
);
|
|
190
|
+
this._applyStateModifier(cssSelector, modifier, (elm, cls) => elm?.classList.remove(cls));
|
|
206
191
|
}
|
|
207
192
|
_applyStateModifier(
|
|
208
193
|
cssSelector: string,
|
|
@@ -224,17 +209,10 @@ export class RuntimeStatechartApi {
|
|
|
224
209
|
}
|
|
225
210
|
|
|
226
211
|
_addTransitionsModifier(cssSelector: string, modifier: string = "selected") {
|
|
227
|
-
this._applyTransitionsModifier(cssSelector, modifier, (elm, cls) =>
|
|
228
|
-
elm?.classList.add(cls),
|
|
229
|
-
);
|
|
212
|
+
this._applyTransitionsModifier(cssSelector, modifier, (elm, cls) => elm?.classList.add(cls));
|
|
230
213
|
}
|
|
231
|
-
_removeTransitionsModifier(
|
|
232
|
-
cssSelector
|
|
233
|
-
modifier: string = "selected",
|
|
234
|
-
) {
|
|
235
|
-
this._applyTransitionsModifier(cssSelector, modifier, (elm, cls) =>
|
|
236
|
-
elm?.classList.remove(cls),
|
|
237
|
-
);
|
|
214
|
+
_removeTransitionsModifier(cssSelector: string, modifier: string = "selected") {
|
|
215
|
+
this._applyTransitionsModifier(cssSelector, modifier, (elm, cls) => elm?.classList.remove(cls));
|
|
238
216
|
}
|
|
239
217
|
_applyTransitionsModifier(
|
|
240
218
|
cssSelector: string,
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
StateChart,
|
|
3
|
-
StateGraphEdge,
|
|
4
|
-
StateGraphNode,
|
|
5
|
-
} from "../types/index.js";
|
|
1
|
+
import type { StateChart, StateGraphEdge, StateGraphNode } from "../types/index.js";
|
|
6
2
|
|
|
7
3
|
export class StateChartIndex {
|
|
8
4
|
statechart: StateChart;
|
|
@@ -62,12 +58,7 @@ export class StateChartIndex {
|
|
|
62
58
|
* @return a list of all nodes
|
|
63
59
|
*/
|
|
64
60
|
getAllNodes(): StateGraphNode[] {
|
|
65
|
-
return [
|
|
66
|
-
...new Set([
|
|
67
|
-
...Object.values(this._chartsIndex),
|
|
68
|
-
...Object.values(this._nodesIndex),
|
|
69
|
-
]),
|
|
70
|
-
];
|
|
61
|
+
return [...new Set([...Object.values(this._chartsIndex), ...Object.values(this._nodesIndex)])];
|
|
71
62
|
}
|
|
72
63
|
|
|
73
64
|
/**
|
|
@@ -77,8 +68,7 @@ export class StateChartIndex {
|
|
|
77
68
|
*/
|
|
78
69
|
getStateNodes(): StateGraphNode[] {
|
|
79
70
|
return this.getAllNodes().filter(
|
|
80
|
-
(node) =>
|
|
81
|
-
node.key !== this.initialStateKey && node.key !== this.finalStateKey,
|
|
71
|
+
(node) => node.key !== this.initialStateKey && node.key !== this.finalStateKey,
|
|
82
72
|
);
|
|
83
73
|
}
|
|
84
74
|
|
|
@@ -133,9 +123,7 @@ export class StateChartIndex {
|
|
|
133
123
|
const state = stack.pop();
|
|
134
124
|
if (!state || !stack.length) return;
|
|
135
125
|
const parent = stack[stack.length - 1];
|
|
136
|
-
const t = parent.edges.find(
|
|
137
|
-
(t: StateGraphEdge) => t.from === state.key && t.event === event,
|
|
138
|
-
);
|
|
126
|
+
const t = parent.edges.find((t: StateGraphEdge) => t.from === state.key && t.event === event);
|
|
139
127
|
return t;
|
|
140
128
|
}
|
|
141
129
|
|
|
@@ -177,13 +165,8 @@ export class StateChartIndex {
|
|
|
177
165
|
* @param transition a graph edge instance defining transition
|
|
178
166
|
* @returns an array with two identifiers - [sourceStateId, targetStateId] - the source state id and target state id
|
|
179
167
|
*/
|
|
180
|
-
getTransitionStateIds(
|
|
181
|
-
|
|
182
|
-
): [string | undefined, string | undefined] {
|
|
183
|
-
const result: [string | undefined, string | undefined] = [
|
|
184
|
-
undefined,
|
|
185
|
-
undefined,
|
|
186
|
-
];
|
|
168
|
+
getTransitionStateIds(transition?: StateGraphEdge): [string | undefined, string | undefined] {
|
|
169
|
+
const result: [string | undefined, string | undefined] = [undefined, undefined];
|
|
187
170
|
if (!transition) return result;
|
|
188
171
|
const parentId = this._edgesParentsIndex[transition.id];
|
|
189
172
|
if (!parentId) return result;
|
|
@@ -5,10 +5,7 @@ import type { Label } from "./Label.js";
|
|
|
5
5
|
* Provides default functions measuring dimensions for state nodes and transition edges in the graph.
|
|
6
6
|
*/
|
|
7
7
|
export type GraphParamsProvider = {
|
|
8
|
-
getStateParams: (
|
|
9
|
-
stateKey: string,
|
|
10
|
-
state?: string,
|
|
11
|
-
) => Dimensions & Label & Record<string, any>;
|
|
8
|
+
getStateParams: (stateKey: string, state?: string) => Dimensions & Label & Record<string, any>;
|
|
12
9
|
getTransitionParams: (
|
|
13
10
|
fromStateKey: string,
|
|
14
11
|
event: string,
|
package/src/utils/BasisCurve.ts
CHANGED
|
@@ -2,14 +2,7 @@
|
|
|
2
2
|
// copied from d3-shape/src/curve/basis.ts (Mike Bostock, MIT License)
|
|
3
3
|
|
|
4
4
|
export type DrawContext = {
|
|
5
|
-
bezierCurveTo(
|
|
6
|
-
x0: number,
|
|
7
|
-
y0: number,
|
|
8
|
-
x1: number,
|
|
9
|
-
y1: number,
|
|
10
|
-
x2: number,
|
|
11
|
-
y2: number,
|
|
12
|
-
): void;
|
|
5
|
+
bezierCurveTo(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number): void;
|
|
13
6
|
moveTo(x: number, y: number): void;
|
|
14
7
|
lineTo(x: number, y: number): void;
|
|
15
8
|
closePath(): void;
|
|
@@ -52,14 +45,14 @@ export class BasisCurve {
|
|
|
52
45
|
|
|
53
46
|
lineEnd() {
|
|
54
47
|
switch (this._point) {
|
|
48
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: deliberate fall-through, as in the d3-shape basis curve this ports
|
|
55
49
|
case 3:
|
|
56
50
|
this.$point(this._x1, this._y1); // falls through
|
|
57
51
|
case 2:
|
|
58
52
|
this._context.lineTo(this._x1, this._y1);
|
|
59
53
|
break;
|
|
60
54
|
}
|
|
61
|
-
if (this._line || (this._line !== 0 && this._point === 1))
|
|
62
|
-
this._context.closePath();
|
|
55
|
+
if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
|
|
63
56
|
this._line = 1 - this._line;
|
|
64
57
|
}
|
|
65
58
|
|
|
@@ -73,12 +66,10 @@ export class BasisCurve {
|
|
|
73
66
|
case 1:
|
|
74
67
|
this._point = 2;
|
|
75
68
|
break;
|
|
69
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: deliberate fall-through, as in the d3-shape basis curve this ports
|
|
76
70
|
case 2:
|
|
77
71
|
this._point = 3;
|
|
78
|
-
this._context.lineTo(
|
|
79
|
-
(5 * this._x0 + this._x1) / 6,
|
|
80
|
-
(5 * this._y0 + this._y1) / 6,
|
|
81
|
-
); // falls through
|
|
72
|
+
this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // falls through
|
|
82
73
|
default:
|
|
83
74
|
this.$point(x, y);
|
|
84
75
|
break;
|
package/src/utils/domToText.ts
CHANGED
|
@@ -4,11 +4,7 @@ export function domToText(elm: HTMLElement) {
|
|
|
4
4
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
5
5
|
lines.push(node.textContent || "");
|
|
6
6
|
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
7
|
-
if (
|
|
8
|
-
node.nodeName === "BR" ||
|
|
9
|
-
node.nodeName === "P" ||
|
|
10
|
-
node.nodeName === "DIV"
|
|
11
|
-
) {
|
|
7
|
+
if (node.nodeName === "BR" || node.nodeName === "P" || node.nodeName === "DIV") {
|
|
12
8
|
lines.push("\n");
|
|
13
9
|
}
|
|
14
10
|
}
|
|
@@ -16,7 +12,7 @@ export function domToText(elm: HTMLElement) {
|
|
|
16
12
|
return lines.join("");
|
|
17
13
|
|
|
18
14
|
function visit(el: HTMLElement, visitor: (node: Node) => void) {
|
|
19
|
-
for (
|
|
15
|
+
for (let i = 0; i < el.childNodes.length; i++) {
|
|
20
16
|
const child = el.childNodes[i];
|
|
21
17
|
const result = visitor(el.childNodes[i]);
|
|
22
18
|
if (child.nodeType !== Node.ELEMENT_NODE) continue;
|