@statewalker/fsm-charts 0.0.6 → 0.1.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.
@@ -40,6 +40,15 @@ type Position = {
40
40
  y: number;
41
41
  };
42
42
 
43
+ /**
44
+ * Information about a state node in the graph.
45
+ */
46
+ type StateGraphNode = Dimensions & Position & {
47
+ id: string;
48
+ key: string;
49
+ state: string;
50
+ } & Record<string, any>;
51
+
43
52
  /**
44
53
  * Information about a state graph edge.
45
54
  */
@@ -51,15 +60,6 @@ type StateGraphEdge = Dimensions & Position & {
51
60
  points: Position[];
52
61
  } & Record<string, any>;
53
62
 
54
- /**
55
- * Information about a state node in the graph.
56
- */
57
- type StateGraphNode = Dimensions & Position & {
58
- id: string;
59
- key: string;
60
- state: string;
61
- } & Record<string, any>;
62
-
63
63
  /**
64
64
  * Coordinates for state nodes and endges corresponding to state transitions.
65
65
  */
@@ -68,9 +68,7 @@ type TransitionsGraph = Position & Dimensions & {
68
68
  edges: StateGraphEdge[];
69
69
  };
70
70
 
71
- type StateChart = TransitionsGraph & {
72
- id: string;
73
- key: string;
71
+ type StateChart = TransitionsGraph & StateGraphNode & {
74
72
  children?: StateChart[];
75
73
  } & Record<string, any>;
76
74
 
@@ -0,0 +1,163 @@
1
+ import { __publicField } from './chunk-XEO3YXBM.js';
2
+
3
+ // src/runtime/StateChartIndex.ts
4
+ var StateChartIndex = class {
5
+ constructor({ statechart }) {
6
+ __publicField(this, "statechart");
7
+ __publicField(this, "_chartsIndex", {});
8
+ __publicField(this, "_nodesIndex", {});
9
+ __publicField(this, "_nodesParentsIndex", {});
10
+ __publicField(this, "_edgeIndex", {});
11
+ __publicField(this, "_edgesParentsIndex", {});
12
+ this.statechart = statechart;
13
+ this._buildIndexes();
14
+ }
15
+ /**
16
+ * Transforms a stack of state keys to the corresponding identifiers.
17
+ * If a key in the stack was not found then this method returns
18
+ * an empty stack.
19
+ * @param stack a stack of state keys
20
+ * @returns a stack of state identifiers for the given states
21
+ */
22
+ getStatesIds(...stack) {
23
+ let result = [];
24
+ let list = [this.statechart];
25
+ for (let i = 0; list?.length > 0 && i < stack.length; i++) {
26
+ const key = stack[i];
27
+ const node = list.find((node2) => node2.key === key);
28
+ if (!node)
29
+ break;
30
+ result.push(node.id);
31
+ list = node.children;
32
+ if (!list?.length)
33
+ list = node.nodes;
34
+ }
35
+ return result.length === stack.length ? result : [];
36
+ }
37
+ /**
38
+ * Returns graph nodes for the specified identifier.
39
+ * @param id the id of a node
40
+ * @returns a stack of nodes
41
+ */
42
+ getStackByStateId(id) {
43
+ if (!id)
44
+ return [];
45
+ const node = this._chartsIndex[id] || this._nodesIndex[id];
46
+ if (!node)
47
+ return [];
48
+ const parentId = this._nodesParentsIndex[id];
49
+ if (parentId) {
50
+ const parentStack = this.getStackByStateId(parentId);
51
+ if (!parentStack.length)
52
+ return [];
53
+ parentStack.push(node);
54
+ return parentStack;
55
+ } else {
56
+ return [node];
57
+ }
58
+ }
59
+ /**
60
+ * Returns an edge object corresponding to the transition from the state
61
+ * @param stateId identifier of the source state
62
+ * @param event an event triggering the transition
63
+ * @returns graph edge
64
+ */
65
+ getTransition(stateId, event) {
66
+ const stack = this.getStackByStateId(stateId);
67
+ const state = stack.pop();
68
+ if (!state || !stack.length)
69
+ return;
70
+ const parent = stack[stack.length - 1];
71
+ const t = parent.edges.find(
72
+ (t2) => t2.from === state.key && t2.event === event
73
+ );
74
+ return t;
75
+ }
76
+ /**
77
+ * Returns a list of edge objects corresponding to all transitions from the state
78
+ * @param stateId identifier of the source state
79
+ * @returns a list of graph edges
80
+ */
81
+ getTransitions(stateId) {
82
+ const stack = this.getStackByStateId(stateId);
83
+ const state = stack.pop();
84
+ if (!state || !stack.length)
85
+ return [];
86
+ const parent = stack[stack.length - 1];
87
+ return parent.edges.filter((t) => t.from === state.key);
88
+ }
89
+ /**
90
+ * Returns a graph node corresponding to the specified state id.
91
+ * @param stateId identifier of the state
92
+ * @returns graph node
93
+ * @see getStateChart
94
+ */
95
+ getStateNode(stateId) {
96
+ return stateId ? this._nodesIndex[stateId] : void 0;
97
+ }
98
+ /**
99
+ * Returns a chart corresponding to the specified state id.
100
+ * @param stateId identifier of the state
101
+ * @returns graph node
102
+ * @see getStateNode
103
+ */
104
+ getStateChart(stateId) {
105
+ return stateId ? this._chartsIndex[stateId] : void 0;
106
+ }
107
+ /**
108
+ * Returns ids of the previous and next state for the specified transition
109
+ * @param transition a graph edge instance defining transition
110
+ * @returns an array with two identifiers - [sourceStateId, targetStateId] - the source state id and target state id
111
+ */
112
+ getTransitionStateIds(transition) {
113
+ const result = [
114
+ void 0,
115
+ void 0
116
+ ];
117
+ if (!transition)
118
+ return result;
119
+ const parentId = this._edgesParentsIndex[transition.id];
120
+ if (!parentId)
121
+ return result;
122
+ const parent = this._chartsIndex[parentId];
123
+ if (!parent)
124
+ return result;
125
+ parent.nodes.forEach((node) => {
126
+ if (node.key === transition.from) {
127
+ result[0] = node.id;
128
+ }
129
+ if (node.key === transition.to) {
130
+ result[1] = node.id;
131
+ }
132
+ });
133
+ return result;
134
+ }
135
+ // ----------------------------------------------------------
136
+ // Internal methods
137
+ _buildIndexes() {
138
+ const addToIndex = (chart) => {
139
+ const chartId = chart.id;
140
+ this._chartsIndex[chartId] = chart;
141
+ if (!(chartId in this._nodesIndex)) {
142
+ this._nodesIndex[chartId] = chart;
143
+ }
144
+ chart.nodes.forEach((node) => {
145
+ const nodeId = node.id;
146
+ this._nodesIndex[nodeId] = node;
147
+ this._nodesParentsIndex[nodeId] = chartId;
148
+ });
149
+ chart.edges.forEach((edge) => {
150
+ const edgeId = edge.id;
151
+ this._edgeIndex[edgeId] = edge;
152
+ this._edgesParentsIndex[edgeId] = chartId;
153
+ });
154
+ (chart.children || []).forEach((child) => {
155
+ this._nodesParentsIndex[child.id] = chartId;
156
+ addToIndex(child);
157
+ });
158
+ };
159
+ addToIndex(this.statechart);
160
+ }
161
+ };
162
+
163
+ export { StateChartIndex };
@@ -47,7 +47,7 @@ function serializeCss(obj) {
47
47
  }
48
48
  }
49
49
 
50
- // src/svg/buildStatechartStyles.ts
50
+ // src/html/buildStatechartStyles.ts
51
51
  function buildStateDetailsStyle() {
52
52
  return {
53
53
  ".state-details": {
@@ -214,7 +214,7 @@ function buildStatechartStyles({
214
214
  };
215
215
  }
216
216
 
217
- // src/svg/buildStatechartCss.ts
217
+ // src/html/buildStatechartCss.ts
218
218
  function buildStatechartCss({ prefix = "" } = {}) {
219
219
  const cssObject = buildStatechartStyles({ root: prefix || ":root" });
220
220
  return serializeCss(cssObject);
@@ -310,7 +310,7 @@ var BasisCurve = class {
310
310
  }
311
311
  };
312
312
 
313
- // src/svg/buildStatechartSvg.ts
313
+ // src/html/buildStatechartSvg.ts
314
314
  function getBoxParams({
315
315
  x,
316
316
  y,
@@ -500,7 +500,7 @@ function buildStatechartSvg({
500
500
  println("</svg>");
501
501
  }
502
502
 
503
- // src/svg/buildStatechartsPanel.ts
503
+ // src/html/buildStatechartsPanel.ts
504
504
  function buildStatechartsPanel({
505
505
  statechart,
506
506
  newId,
@@ -2589,6 +2589,7 @@ function buildCharts({
2589
2589
  return {
2590
2590
  id,
2591
2591
  key: config2.key,
2592
+ state: config2.key,
2592
2593
  ...graph,
2593
2594
  children
2594
2595
  };
@@ -1,4 +1,4 @@
1
- import { S as StateChart, d as TransitionsGraph } from './StateChart-pFSQIvtE.js';
1
+ import { S as StateChart, d as TransitionsGraph } from './StateChart-PdtJDEPy.js';
2
2
 
3
3
  declare function buildStatechartCss({ prefix }?: {
4
4
  prefix?: string | undefined;
@@ -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-pFSQIvtE.js';
2
- export { b as buildStatechartCss, c as buildStatechartStyles, d as buildStatechartSvg, a as buildStatechartsPanel } from './index-svg-DCwEyX8X.js';
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-PdtJDEPy.js';
2
+ export { b as buildStatechartCss, c as buildStatechartStyles, d as buildStatechartSvg, a as buildStatechartsPanel } from './index-html-CbDZzk2n.js';
@@ -1,3 +1,3 @@
1
- export { buildStatechartCss, buildStatechartStyles, buildStatechartSvg, buildStatechartsPanel } from './chunk-FYTJYHEQ.js';
1
+ export { buildStatechartCss, buildStatechartStyles, buildStatechartSvg, buildStatechartsPanel } from './chunk-YYNW6Q2T.js';
2
2
  import './chunk-NXWOFQMO.js';
3
3
  import './chunk-XEO3YXBM.js';
@@ -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-pFSQIvtE.js';
2
- export { D as Dimensions, a as Position, b as StateGraphEdge, c as StateGraphNode } from './StateChart-pFSQIvtE.js';
1
+ import { T as Transition, P as Padding, G as GraphParamsProvider, d as TransitionsGraph, F as FsmStateConfig, S as StateChart } from './StateChart-PdtJDEPy.js';
2
+ export { D as Dimensions, a as Position, b as StateGraphEdge, c as StateGraphNode } from './StateChart-PdtJDEPy.js';
3
3
 
4
4
  /**
5
5
  * Build graphs corresponding to the specified transitions.
@@ -1,3 +1,3 @@
1
- export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-IT7GBMYV.js';
1
+ export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-ZSGS37QH.js';
2
2
  import './chunk-NXWOFQMO.js';
3
3
  import './chunk-XEO3YXBM.js';
@@ -1,5 +1,64 @@
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-pFSQIvtE.js';
1
+ import { S as StateChart, c as StateGraphNode, b as StateGraphEdge } from './StateChart-PdtJDEPy.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-PdtJDEPy.js';
2
3
 
3
- declare const a = "a";
4
+ declare class StateChartIndex {
5
+ statechart: StateChart;
6
+ _chartsIndex: Record<string, StateChart>;
7
+ _nodesIndex: Record<string, StateGraphNode>;
8
+ _nodesParentsIndex: Record<string, string>;
9
+ _edgeIndex: Record<string, StateGraphEdge>;
10
+ _edgesParentsIndex: Record<string, string>;
11
+ constructor({ statechart }: {
12
+ statechart: StateChart;
13
+ });
14
+ /**
15
+ * Transforms a stack of state keys to the corresponding identifiers.
16
+ * If a key in the stack was not found then this method returns
17
+ * an empty stack.
18
+ * @param stack a stack of state keys
19
+ * @returns a stack of state identifiers for the given states
20
+ */
21
+ getStatesIds(...stack: string[]): string[];
22
+ /**
23
+ * Returns graph nodes for the specified identifier.
24
+ * @param id the id of a node
25
+ * @returns a stack of nodes
26
+ */
27
+ getStackByStateId(id?: string): StateGraphNode[];
28
+ /**
29
+ * Returns an edge object corresponding to the transition from the state
30
+ * @param stateId identifier of the source state
31
+ * @param event an event triggering the transition
32
+ * @returns graph edge
33
+ */
34
+ getTransition(stateId?: string, event?: string): StateGraphEdge | undefined;
35
+ /**
36
+ * Returns a list of edge objects corresponding to all transitions from the state
37
+ * @param stateId identifier of the source state
38
+ * @returns a list of graph edges
39
+ */
40
+ getTransitions(stateId?: string): StateGraphEdge[];
41
+ /**
42
+ * Returns a graph node corresponding to the specified state id.
43
+ * @param stateId identifier of the state
44
+ * @returns graph node
45
+ * @see getStateChart
46
+ */
47
+ getStateNode(stateId?: string): StateGraphNode | undefined;
48
+ /**
49
+ * Returns a chart corresponding to the specified state id.
50
+ * @param stateId identifier of the state
51
+ * @returns graph node
52
+ * @see getStateNode
53
+ */
54
+ getStateChart(stateId?: string): StateChart | undefined;
55
+ /**
56
+ * Returns ids of the previous and next state for the specified transition
57
+ * @param transition a graph edge instance defining transition
58
+ * @returns an array with two identifiers - [sourceStateId, targetStateId] - the source state id and target state id
59
+ */
60
+ getTransitionStateIds(transition?: StateGraphEdge): [string | undefined, string | undefined];
61
+ _buildIndexes(): void;
62
+ }
4
63
 
5
- export { a };
64
+ export { StateChart, StateChartIndex, StateGraphEdge, StateGraphNode };
@@ -1,2 +1,2 @@
1
- export { a } from './chunk-X2UPWZLX.js';
1
+ export { StateChartIndex } from './chunk-EU64L34M.js';
2
2
  import './chunk-XEO3YXBM.js';
package/dist/index.d.ts CHANGED
@@ -1,7 +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-pFSQIvtE.js';
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-PdtJDEPy.js';
2
2
  export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './index-layout.js';
3
- export { C as CssTree, b as buildStatechartCss, c as buildStatechartStyles, d as buildStatechartSvg, a as buildStatechartsPanel, s as serializeCss } from './index-svg-DCwEyX8X.js';
4
- export { a } from './index-runtime.js';
3
+ export { C as CssTree, b as buildStatechartCss, c as buildStatechartStyles, d as buildStatechartSvg, a as buildStatechartsPanel, s as serializeCss } from './index-html-CbDZzk2n.js';
4
+ export { StateChartIndex } from './index-runtime.js';
5
5
 
6
6
  declare function toKebabCase(str: string): string;
7
7
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-IT7GBMYV.js';
2
- export { buildStatechartCss, buildStatechartStyles, buildStatechartSvg, buildStatechartsPanel, serializeCss, toKebabCase } from './chunk-FYTJYHEQ.js';
1
+ export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-ZSGS37QH.js';
2
+ export { buildStatechartCss, buildStatechartStyles, buildStatechartSvg, buildStatechartsPanel, serializeCss, toKebabCase } from './chunk-YYNW6Q2T.js';
3
3
  import './chunk-NXWOFQMO.js';
4
- export { a } from './chunk-X2UPWZLX.js';
4
+ export { StateChartIndex } from './chunk-EU64L34M.js';
5
5
  import './chunk-XEO3YXBM.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statewalker/fsm-charts",
3
- "version": "0.0.6",
3
+ "version": "0.1.1",
4
4
  "description": "HFSM Implementation",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/statewalker/statewalker-fsm-charts",
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "devDependencies": {
28
28
  "@statewalker/typescript-config": "*",
29
+ "@types/jsdom": "^21.1.7",
29
30
  "@types/lodash-es": "^4.17.12",
30
31
  "@typescript-eslint/eslint-plugin": "^6.4.0",
31
32
  "eslint": "^8.0.1",
@@ -33,6 +34,7 @@
33
34
  "eslint-plugin-import": "^2.25.2",
34
35
  "eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
35
36
  "eslint-plugin-promise": "^6.0.0",
37
+ "jsdom": "^24.1.0",
36
38
  "lodash": "^4.17.21",
37
39
  "lodash-es": "^4.17.21",
38
40
  "tsup": "^8.0.2",
@@ -1,4 +1,4 @@
1
- import { CssTree } from "../utils/serializeCss";
1
+ import type { CssTree } from "../utils/serializeCss";
2
2
 
3
3
  function buildStateDetailsStyle() {
4
4
  return {
@@ -1,2 +1,2 @@
1
1
  export * from "./types/index.ts";
2
- export * from "./svg/index.ts";
2
+ export * from "./html/index.ts";
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "./types/index.ts";
2
2
  export * from "./layout/index.ts";
3
- export * from "./svg/index.ts";
3
+ export * from "./html/index.ts";
4
4
  export * from "./runtime/index.ts";
5
5
  export * from "./utils/toKebabCase.ts";
6
6
  export * from "./utils/serializeCss.ts";
@@ -33,7 +33,10 @@ export function buildCharts({
33
33
  } & GraphParamsProvider): StateChart {
34
34
  return buildChart(config);
35
35
 
36
- function buildChart(config: FsmStateConfig, id: string = newId("s")) {
36
+ function buildChart(
37
+ config: FsmStateConfig,
38
+ id: string = newId("s")
39
+ ): StateChart {
37
40
  const graph = buildFlatCharts({
38
41
  lodash,
39
42
  transitions: config.transitions,
@@ -59,6 +62,7 @@ export function buildCharts({
59
62
  return {
60
63
  id,
61
64
  key: config.key,
65
+ state: config.key,
62
66
  ...graph,
63
67
  children,
64
68
  };
@@ -0,0 +1,165 @@
1
+ import type {
2
+ StateChart,
3
+ StateGraphNode,
4
+ StateGraphEdge,
5
+ } from "../types/index.ts";
6
+
7
+ export class StateChartIndex {
8
+ statechart: StateChart;
9
+ _chartsIndex: Record<string, StateChart> = {};
10
+ _nodesIndex: Record<string, StateGraphNode> = {};
11
+ _nodesParentsIndex: Record<string, string> = {};
12
+ _edgeIndex: Record<string, StateGraphEdge> = {};
13
+ _edgesParentsIndex: Record<string, string> = {};
14
+
15
+ constructor({ statechart }: { statechart: StateChart }) {
16
+ this.statechart = statechart;
17
+ this._buildIndexes();
18
+ }
19
+
20
+ /**
21
+ * Transforms a stack of state keys to the corresponding identifiers.
22
+ * If a key in the stack was not found then this method returns
23
+ * an empty stack.
24
+ * @param stack a stack of state keys
25
+ * @returns a stack of state identifiers for the given states
26
+ */
27
+ getStatesIds(...stack: string[]): string[] {
28
+ let result = [];
29
+ let list = [this.statechart] as (StateChart | StateGraphNode)[];
30
+ for (let i = 0; list?.length > 0 && i < stack.length; i++) {
31
+ const key = stack[i];
32
+ const node = list.find((node) => node.key === key);
33
+ if (!node) break;
34
+ result.push(node.id);
35
+ list = node.children;
36
+ if (!list?.length) list = node.nodes;
37
+ }
38
+ return result.length === stack.length ? result : [];
39
+ }
40
+
41
+ /**
42
+ * Returns graph nodes for the specified identifier.
43
+ * @param id the id of a node
44
+ * @returns a stack of nodes
45
+ */
46
+ getStackByStateId(id?: string): StateGraphNode[] {
47
+ if (!id) return [];
48
+ const node = this._chartsIndex[id] || this._nodesIndex[id];
49
+ if (!node) return [];
50
+ const parentId = this._nodesParentsIndex[id];
51
+ if (parentId) {
52
+ const parentStack = this.getStackByStateId(parentId);
53
+ if (!parentStack.length) return [];
54
+ parentStack.push(node);
55
+ return parentStack;
56
+ } else {
57
+ return [node];
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Returns an edge object corresponding to the transition from the state
63
+ * @param stateId identifier of the source state
64
+ * @param event an event triggering the transition
65
+ * @returns graph edge
66
+ */
67
+ getTransition(stateId?: string, event?: string): StateGraphEdge | undefined {
68
+ const stack = this.getStackByStateId(stateId);
69
+ const state = stack.pop();
70
+ if (!state || !stack.length) return;
71
+ const parent = stack[stack.length - 1];
72
+ const t = parent.edges.find(
73
+ (t: StateGraphEdge) => t.from === state.key && t.event === event
74
+ );
75
+ return t;
76
+ }
77
+
78
+ /**
79
+ * Returns a list of edge objects corresponding to all transitions from the state
80
+ * @param stateId identifier of the source state
81
+ * @returns a list of graph edges
82
+ */
83
+ getTransitions(stateId?: string): StateGraphEdge[] {
84
+ const stack = this.getStackByStateId(stateId);
85
+ const state = stack.pop();
86
+ if (!state || !stack.length) return [];
87
+ const parent = stack[stack.length - 1];
88
+ return parent.edges.filter((t: StateGraphEdge) => t.from === state.key);
89
+ }
90
+
91
+ /**
92
+ * Returns a graph node corresponding to the specified state id.
93
+ * @param stateId identifier of the state
94
+ * @returns graph node
95
+ * @see getStateChart
96
+ */
97
+ getStateNode(stateId?: string): StateGraphNode | undefined {
98
+ return stateId ? this._nodesIndex[stateId] : undefined;
99
+ }
100
+
101
+ /**
102
+ * Returns a chart corresponding to the specified state id.
103
+ * @param stateId identifier of the state
104
+ * @returns graph node
105
+ * @see getStateNode
106
+ */
107
+ getStateChart(stateId?: string): StateChart | undefined {
108
+ return stateId ? this._chartsIndex[stateId] : undefined;
109
+ }
110
+
111
+ /**
112
+ * Returns ids of the previous and next state for the specified transition
113
+ * @param transition a graph edge instance defining transition
114
+ * @returns an array with two identifiers - [sourceStateId, targetStateId] - the source state id and target state id
115
+ */
116
+ getTransitionStateIds(
117
+ transition?: StateGraphEdge
118
+ ): [string | undefined, string | undefined] {
119
+ const result: [string | undefined, string | undefined] = [
120
+ undefined,
121
+ undefined,
122
+ ];
123
+ if (!transition) return result;
124
+ const parentId = this._edgesParentsIndex[transition.id];
125
+ if (!parentId) return result;
126
+ const parent = this._chartsIndex[parentId];
127
+ if (!parent) return result;
128
+ parent.nodes.forEach((node: StateGraphNode) => {
129
+ if (node.key === transition.from) {
130
+ result[0] = node.id;
131
+ }
132
+ if (node.key === transition.to) {
133
+ result[1] = node.id;
134
+ }
135
+ });
136
+ return result;
137
+ }
138
+
139
+ // ----------------------------------------------------------
140
+ // Internal methods
141
+ _buildIndexes() {
142
+ const addToIndex = (chart: StateChart) => {
143
+ const chartId = chart.id;
144
+ this._chartsIndex[chartId] = chart;
145
+ if (!(chartId in this._nodesIndex)) {
146
+ this._nodesIndex[chartId] = chart;
147
+ }
148
+ chart.nodes.forEach((node) => {
149
+ const nodeId = node.id;
150
+ this._nodesIndex[nodeId] = node;
151
+ this._nodesParentsIndex[nodeId] = chartId;
152
+ });
153
+ chart.edges.forEach((edge) => {
154
+ const edgeId = edge.id;
155
+ this._edgeIndex[edgeId] = edge;
156
+ this._edgesParentsIndex[edgeId] = chartId;
157
+ });
158
+ (chart.children || []).forEach((child) => {
159
+ this._nodesParentsIndex[child.id] = chartId;
160
+ addToIndex(child);
161
+ });
162
+ };
163
+ addToIndex(this.statechart);
164
+ }
165
+ }
@@ -1,211 +1 @@
1
- export const a = "a";
2
-
3
- // class RuntimeStatechartsApi {
4
- // constructor({ element, statechart }) {
5
- // this.element = element;
6
- // this.statechart = statechart;
7
- // // this._statesIndex = {};
8
- // // this._transitionsIndex = {};
9
- // // this._buildIndexes(this.statechart);
10
- // }
11
-
12
- // _applyStateModifier(cssSelector, modifier = "selected", apply) {
13
- // const detailsModifier = `state-details--${modifier}`;
14
- // const stateLabelsModifier = `state-details__label--${modifier}`;
15
- // const stateModifier = `state--${modifier}`;
16
- // [...this.element.querySelectorAll(cssSelector)].forEach((elm) => {
17
- // if (elm.tagName.toLowerCase() === "details") {
18
- // apply(elm, detailsModifier);
19
- // const labelElm = elm.querySelector(".state-details__label");
20
- // if (labelElm) apply(labelElm, stateLabelsModifier);
21
- // } else {
22
- // apply(elm, stateModifier);
23
- // }
24
- // });
25
- // }
26
-
27
- // _applyTransitionsModifier(cssSelector, modifier = "selected", action) {}
28
-
29
- // deselectAllTransitions() {
30
- // const removeClass = (elm, cls) => elm.classList.remove(cls);
31
- // this._applyTransitionsModifier(
32
- // "[data-transition-id]",
33
- // "selected",
34
- // removeClass
35
- // );
36
- // }
37
- // deselectTransitions(...ids) {
38
- // const removeClass = (elm, cls) => elm.classList.remove(cls);
39
- // for (const id of ids) {
40
- // this._applyTransitionsModifier(
41
- // `[data-transition-id="${id}"]`,
42
- // "selected",
43
- // removeClass
44
- // );
45
- // }
46
- // }
47
- // selectTransitions(...ids) {
48
- // const addClass = (elm, cls) => elm.classList.add(cls);
49
- // for (const id of ids) {
50
- // this._applyTransitionsModifier(
51
- // `[data-transition-id="${id}"]`,
52
- // "selected",
53
- // addClass
54
- // );
55
- // }
56
- // }
57
-
58
- // deselectAllStates() {
59
- // const removeClass = (elm, cls) => elm.classList.remove(cls);
60
- // this._applyStateModifier("[data-state-id]", "selected", removeClass);
61
- // }
62
- // deselectStates(...ids) {
63
- // const removeClass = (elm, cls) => elm.classList.remove(cls);
64
- // for (const id of ids) {
65
- // this._applyStateModifier(
66
- // `[data-state-id="${id}"]`,
67
- // "selected",
68
- // removeClass
69
- // );
70
- // }
71
- // }
72
- // selectStates(...ids) {
73
- // const addClass = (elm, cls) => elm.classList.add(cls);
74
- // for (const id of ids) {
75
- // this._applyStateModifier(`[data-state-id="${id}"]`, "selected", addClass);
76
- // }
77
- // }
78
-
79
- // // -----------------------------------------------
80
- // // Access to charts data
81
- // // - get state ids by stack of state keys
82
- // // - get stack of states by state id
83
- // // - get transitionId by stateId + event
84
- // // - get targetId, sourceId, event by transitionId
85
- // getStatesIds(...stack) {
86
- // let statechart = this.statechart;
87
- // let result = [];
88
- // if (statechart.key === stack[0]) {
89
- // result.push(statechart.id);
90
- // for (let i = 1; i < stack.length; i++) {
91
- // const key = stack[i];
92
- // let id = statechart.graph.nodes.find((node) => node.key === key)?.id;
93
- // if (!id) break;
94
- // result.push(id);
95
- // statechart = (statechart.children || []).find(
96
- // (child) => child.key === key
97
- // );
98
- // }
99
- // }
100
- // return result.length === stack.length ? result : [];
101
- // }
102
-
103
- // getStackByStateId(id) {
104
- // return this._getStack(id, ({ id, key }) => key);
105
- // }
106
-
107
- // getTransition(stateId, event) {
108
- // const stack = this._getStack(stateId);
109
- // const state = stack.pop();
110
- // if (!state || !stack.length) return;
111
- // const parent = stack[stack.length - 1];
112
- // const t = parent.graph.edges.find(
113
- // (t) => t.from === state.key && t.event === event
114
- // );
115
- // if (!t) return;
116
- // const to = parent.graph.nodes.find((n) => n.key === t.to);
117
- // return to && { id: t.id, fromId: state.id, event: t.event, toId: to.id };
118
- // }
119
-
120
- // _getStack(id, get = (d) => d) {
121
- // return findById(this.statechart, id, get);
122
-
123
- // function findById(statechart, id, get, stack = []) {
124
- // try {
125
- // stack.push(get(statechart));
126
- // if (statechart.id === id) {
127
- // return [...stack];
128
- // } else {
129
- // let node = statechart.graph.nodes.find((node) => node.id === id);
130
- // if (node) {
131
- // return [...stack, get(node)];
132
- // } else {
133
- // let result;
134
- // if (statechart.children) {
135
- // for (const child of statechart.children) {
136
- // result = findById(child, id, get, stack);
137
- // if (result) break;
138
- // }
139
- // }
140
- // return result;
141
- // }
142
- // }
143
- // } finally {
144
- // stack.pop();
145
- // }
146
- // }
147
- // }
148
-
149
- // // getTransitionId(stateId, event) {
150
- // // }
151
-
152
- // // const stateInfo = this._statesIndex[stateId];
153
- // // if (!stateInfo) return;
154
- // // if (stateInfo.parent) return ;
155
- // // const targetState = stateInfo.parent.
156
- // // const fromId = stateIds.pop();
157
- // // const parentId = stateIds.pop();
158
- // // const parent = parentId ? this._statesIndex[parentId] : null;
159
- // // return parent
160
- // // ? parent.graph?.edges.find(
161
- // // (edge) => edge.from === fromId && edge.event === event
162
- // // )
163
- // // : undefined;
164
- // // }
165
-
166
- // // _getInfo(index, id, create) {
167
- // // let info = index[id];
168
- // // if (!info && create) {
169
- // // info = index[id] = { id };
170
- // // }
171
- // // return info;
172
- // // }
173
- // // _getStateInfo(id, create) {
174
- // // return this._getInfo(this._statesIndex, id, create);
175
- // // }
176
- // // _getTransitionInfo(id, create) {
177
- // // return this._getInfo(this._transitionsIndex, id, create);
178
- // // }
179
- // // _buildIndexes(statechart) {
180
- // // const { id, key } = statechart;
181
- // // const stateInfo = this._getStateInfo(id, true);
182
- // // stateInfo.key = key;
183
- // // stateInfo.detailsElement = this.element.querySelector(
184
- // // `details[data-state-id="${id}"]`
185
- // // );
186
- // // for (const node of statechart.graph?.nodes || []) {
187
- // // const info = this._getStateInfo(node.id, true);
188
- // // info.parent = stateInfo;
189
- // // // info.parentId = id;
190
- // // info.node = node;
191
- // // info.key = node.key;
192
- // // info.svgGroupElement = this.element.querySelector(
193
- // // `g[data-state-id="${info.id}"]`
194
- // // );
195
- // // }
196
- // // for (const edge of statechart.graph?.edges || []) {
197
- // // const info = this._getTransitionInfo(edge.id, true);
198
- // // info.transition = edge;
199
- // // info.from = edge.from;
200
- // // info.event = edge.event;
201
- // // info.to = edge.to;
202
- // // info.svgGroupElement = this.element.querySelector(
203
- // // `g[data-transition-id="${info.id}"]`
204
- // // );
205
- // // }
206
-
207
- // // for (const child of statechart.children) {
208
- // // this._buildIndexes(child);
209
- // // }
210
- // // }
211
- // }
1
+ export * from "./StateChartIndex.ts";
@@ -1,7 +1,7 @@
1
+ import type { StateGraphNode } from "./StateGraphNode.ts";
1
2
  import type { TransitionsGraph } from "./TransitionsGraph.ts";
2
3
 
3
- export type StateChart = TransitionsGraph & {
4
- id: string;
5
- key: string;
6
- children?: StateChart[];
7
- } & Record<string, any>;
4
+ export type StateChart = TransitionsGraph &
5
+ StateGraphNode & {
6
+ children?: StateChart[];
7
+ } & Record<string, any>;
@@ -1,4 +0,0 @@
1
- // src/runtime/index.ts
2
- var a = "a";
3
-
4
- export { a };
File without changes
File without changes
@@ -1,5 +1,5 @@
1
- import { buildStatechartSvg } from "./buildStatechartSvg.ts";
2
1
  import type { StateChart } from "../types/StateChart.ts";
2
+ import { buildStatechartSvg } from "./buildStatechartSvg.ts";
3
3
 
4
4
  export function buildStatechartsPanel({
5
5
  statechart,
File without changes