@statewalker/fsm-charts 0.1.7 → 0.1.9

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.
@@ -15,7 +15,7 @@ type Transition = [string, string, string];
15
15
 
16
16
  type FsmStateConfig = {
17
17
  key: string;
18
- transitions: Transition[];
18
+ transitions?: Transition[];
19
19
  states?: FsmStateConfig[];
20
20
  } & Record<string, any>;
21
21
 
@@ -1,5 +1,4 @@
1
- import { getPadding } from './chunk-NXWOFQMO.js';
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
- __publicField(this, "_context");
312
- __publicField(this, "_x0", 0);
313
- __publicField(this, "_y0", 0);
314
- __publicField(this, "_x1", 0);
315
- __publicField(this, "_y1", 0);
316
- __publicField(this, "_point", 0);
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
- __publicField(this, "element");
10
- __publicField(this, "statechart");
11
- __publicField(this, "_listenersCounter", 0);
12
- __publicField(this, "_transitionsClickListeners", {});
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
- elm.setAttribute("open", "open");
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
- __publicField(this, "statechart");
221
- __publicField(this, "_chartsIndex", {});
222
- __publicField(this, "_nodesIndex", {});
223
- __publicField(this, "_nodesParentsIndex", {});
224
- __publicField(this, "_edgeIndex", {});
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;
@@ -5,15 +5,13 @@ function concatTransitionsToString(transitions) {
5
5
  let prev;
6
6
  for (const [from, event, to] of transitions) {
7
7
  if (prev !== from) {
8
- if (str)
9
- list.push(str);
8
+ if (str) list.push(str);
10
9
  str = from;
11
10
  }
12
11
  str += ` -${escape(event)}-> ${escape(to)}`;
13
12
  prev = to;
14
13
  }
15
- if (str)
16
- list.push(str);
14
+ if (str) list.push(str);
17
15
  return list;
18
16
  function escape(str2) {
19
17
  return str2;
@@ -22,12 +20,11 @@ function concatTransitionsToString(transitions) {
22
20
 
23
21
  // src/config/serializeProcessConfig.ts
24
22
  function serializeProcessConfig(config) {
25
- if (!config)
26
- return "";
23
+ if (!config) return "";
27
24
  let lines = [];
28
25
  visit(config, lines);
29
26
  return lines.join("\n");
30
- function visit(config2, lines2, shift = " ") {
27
+ function visit(config2, lines2, shift = "") {
31
28
  lines2.push(`${shift}{`);
32
29
  const { key, states, transitions, ...params } = config2;
33
30
  lines2.push(`${shift} "key": ${JSON.stringify(key)}`);
@@ -91,19 +88,16 @@ function splitTransitionString(str) {
91
88
 
92
89
  // src/config/toFsmStateConfig.ts
93
90
  function toFsmStateConfig(json) {
94
- if (!json || typeof json !== "object")
95
- return;
91
+ if (!json || typeof json !== "object") return;
96
92
  const { key, transitions, states, ...options } = json;
97
- if (typeof key !== "string")
98
- return;
93
+ if (typeof key !== "string") return;
99
94
  const stateTransitions = toFsmTransitions(transitions);
100
95
  const substates = toArray(states).map(toFsmStateConfig).filter((v) => !!v);
101
96
  const state = {
102
97
  key,
103
98
  transitions: stateTransitions
104
99
  };
105
- if (substates && substates.length > 0)
106
- state.states = substates;
100
+ if (substates && substates.length > 0) state.states = substates;
107
101
  return Object.assign(state, options);
108
102
  function toFsmTransitions(json2) {
109
103
  const transitions2 = [];
@@ -112,11 +106,9 @@ function toFsmStateConfig(json) {
112
106
  for (let line of array) {
113
107
  const lineTransitions = typeof line === "string" ? splitTransitionString(line) : [toArray(line)];
114
108
  for (const transition of lineTransitions.map(validateTransition)) {
115
- if (!transition)
116
- continue;
109
+ if (!transition) continue;
117
110
  const key2 = transition.join("|");
118
- if (key2 in index)
119
- continue;
111
+ if (key2 in index) continue;
120
112
  index[key2] = true;
121
113
  transitions2.push(transition);
122
114
  }
@@ -125,18 +117,15 @@ function toFsmStateConfig(json) {
125
117
  }
126
118
  function validateTransition(value) {
127
119
  const array = toArray(value);
128
- if (array.length !== 3)
129
- return;
120
+ if (array.length !== 3) return;
130
121
  const [from, event, to] = array;
131
122
  if (typeof from !== "string" || typeof event !== "string" || typeof to !== "string")
132
123
  return;
133
124
  return [from, event, to];
134
125
  }
135
126
  function toArray(value) {
136
- if (value === void 0)
137
- return [];
138
- if (Array.isArray(value))
139
- return value;
127
+ if (value === void 0) return [];
128
+ if (Array.isArray(value)) return value;
140
129
  return [value];
141
130
  }
142
131
  }
@@ -0,0 +1,207 @@
1
+ // src/dom/index.ts
2
+ function getStateDescriptionRenderer({
3
+ element,
4
+ rootStateKey,
5
+ splitHeader = (header) => {
6
+ if (!header) return [void 0, ""];
7
+ const text = header.innerText.trim();
8
+ let key;
9
+ let label = text;
10
+ text.replace(/^\s*\[(.*)\]\s*(.*)$/, (_, k, l) => {
11
+ key = k.trim();
12
+ label = l.trim() || key;
13
+ return "";
14
+ });
15
+ return [key, label];
16
+ }
17
+ }) {
18
+ const docSections = buildSections(element);
19
+ const rootStateFilter = getStateDescriptionFilter(splitHeader, rootStateKey);
20
+ const rootDescription = findSection(docSections, rootStateFilter);
21
+ if (!rootDescription) {
22
+ return () => {
23
+ };
24
+ }
25
+ for (const node of visitSectionNodes(rootDescription)) {
26
+ if (node.nodeName[0] === "#") continue;
27
+ node.parentElement?.removeChild(node);
28
+ }
29
+ return (statesStack) => {
30
+ const stateKey = [...statesStack].pop();
31
+ const filter = getStateDescriptionFilter(splitHeader, stateKey);
32
+ const description = findSection(rootDescription, filter);
33
+ if (!description) return;
34
+ const elm = renderSections({
35
+ section: description,
36
+ deep: (s) => !rootStateFilter(s),
37
+ header: (header) => {
38
+ const [key, label] = splitHeader(header);
39
+ if (key === stateKey) {
40
+ return label || key;
41
+ }
42
+ return;
43
+ }
44
+ });
45
+ const details = elm?.querySelector("details");
46
+ details && (details.open = true);
47
+ return elm;
48
+ };
49
+ function getStateDescriptionFilter(splitHeader2, stateKey) {
50
+ if (!stateKey) return () => false;
51
+ return (section) => {
52
+ if (!section.header) return false;
53
+ const [key] = splitHeader2(section.header);
54
+ return key === stateKey;
55
+ };
56
+ }
57
+ }
58
+ function* visitDom(elm) {
59
+ for (let node = elm.firstChild; node; node = node.nextSibling) {
60
+ if (isDomElement(node)) {
61
+ if (node.tagName === "DIV") {
62
+ yield* visitDom(node);
63
+ } else {
64
+ yield node;
65
+ }
66
+ } else {
67
+ yield node;
68
+ }
69
+ }
70
+ }
71
+ function* visitSectionNodes(section) {
72
+ if (section.header) yield section.header;
73
+ yield* section.content;
74
+ for (const s of vistSections(section, true)) {
75
+ yield* visitSectionNodes(s);
76
+ }
77
+ }
78
+ function* vistSections(root, ignoreRoot = false) {
79
+ !ignoreRoot && (yield root);
80
+ for (const child of root.children) {
81
+ yield* vistSections(child, false);
82
+ }
83
+ }
84
+ function findSection(section, accept) {
85
+ for (const s of vistSections(section)) {
86
+ if (accept(s) === true) return s;
87
+ }
88
+ }
89
+ function isDomElement(node) {
90
+ return node.nodeType === Node.ELEMENT_NODE;
91
+ }
92
+ function newAligner(context) {
93
+ let level = -1;
94
+ return (newLevel, ...params) => {
95
+ while (level >= 0 && level >= newLevel) {
96
+ context.exit(level--, ...params);
97
+ }
98
+ while (level < newLevel) {
99
+ context.enter(++level, ...params);
100
+ }
101
+ };
102
+ }
103
+ function* toDomNodesIterator(root) {
104
+ yield* root instanceof Node ? visitDom(root) : root;
105
+ }
106
+ function buildSections(root) {
107
+ const nodes = toDomNodesIterator(root);
108
+ let top = null;
109
+ let peek = null;
110
+ const stack = [];
111
+ const aligner = newAligner({
112
+ enter(level, header) {
113
+ const section = {
114
+ header,
115
+ content: [],
116
+ children: []
117
+ };
118
+ top = top || section;
119
+ peek && peek.children.push(section);
120
+ peek = section;
121
+ stack.push(section);
122
+ },
123
+ exit() {
124
+ stack.pop();
125
+ peek = stack[stack.length - 1];
126
+ }
127
+ });
128
+ aligner(0);
129
+ let currentHeaderLevel = 0;
130
+ let currentLevel = 0;
131
+ for (const node of nodes) {
132
+ if (isDomElement(node)) {
133
+ if (/^H[1-6]$/i.test(node.tagName)) {
134
+ const headerLevel = +node.tagName.replace(/^H/, "");
135
+ currentLevel = headerLevel > currentHeaderLevel ? currentLevel + 1 : headerLevel < currentHeaderLevel ? currentLevel - 1 : currentLevel;
136
+ currentHeaderLevel = headerLevel;
137
+ aligner(currentLevel, node);
138
+ } else {
139
+ peek.content.push(node);
140
+ }
141
+ } else {
142
+ peek.content.push(node);
143
+ }
144
+ }
145
+ return top.content.length === 0 && top.children.length === 1 && !top.header ? top.children[0] : top;
146
+ }
147
+ function renderSections({
148
+ section,
149
+ deep = (s) => true,
150
+ header = (headerElm) => headerElm
151
+ }) {
152
+ const container = document.createElement("div");
153
+ const id = `id-${String(Math.random()).split(".")[1]}-${Date.now()}`;
154
+ container.setAttribute("id", id);
155
+ if (!section) return container;
156
+ const sectionView = renderSection(section);
157
+ container.append(sectionView);
158
+ const style = renderSectionStyles(id);
159
+ container.append(style);
160
+ return container;
161
+ function renderSectionStyles(id2) {
162
+ const prefix = id2 ? `#${id2}` : "";
163
+ const style2 = document.createElement("style");
164
+ container.appendChild(style2);
165
+ style2.innerHTML = `
166
+ ${prefix} details {
167
+ border: 1px solid #aaa;
168
+ border-radius: 4px;
169
+ padding: 0.5em 0.5em 0;
170
+ margin-bottom: 0.5em;
171
+ }
172
+
173
+ ${prefix} details > summary {
174
+ font-weight: bold;
175
+ margin: -0.5em -0.5em 0;
176
+ padding: 0.5em;
177
+ cursor: pointer;
178
+ }
179
+
180
+ ${prefix} details[open] {
181
+ padding: 0.5em;
182
+ }
183
+ `;
184
+ return style2;
185
+ }
186
+ function renderSection(section2) {
187
+ const details = document.createElement("details");
188
+ const summary = document.createElement("summary");
189
+ details.appendChild(summary);
190
+ const content = document.createElement("div");
191
+ details.appendChild(content);
192
+ const headerElm = header(section2.header);
193
+ headerElm && summary.append(headerElm);
194
+ for (const node of section2.content) {
195
+ if (node.nodeName[0] === "#") continue;
196
+ content.append(node.cloneNode(true));
197
+ }
198
+ if (deep(section2)) {
199
+ for (const child of section2.children) {
200
+ content.append(renderSection(child));
201
+ }
202
+ }
203
+ return details;
204
+ }
205
+ }
206
+
207
+ export { buildSections, findSection, getStateDescriptionRenderer, renderSections, visitDom, visitSectionNodes, vistSections };
@@ -1,4 +1,4 @@
1
- import { getPadding } from './chunk-NXWOFQMO.js';
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: vertical ? "tb" : "lr", multigraph: true });
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: "lr" });
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({
@@ -1,5 +1,5 @@
1
- import { T as Transition, F as FsmStateConfig } from './StateChart-4_Yew7nT.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-4_Yew7nT.js';
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
3
 
4
4
  declare function concatTransitionsToString(transitions: Transition[]): string[];
5
5
 
@@ -1,2 +1 @@
1
- export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './chunk-SHSJVXEB.js';
2
- import './chunk-XEO3YXBM.js';
1
+ export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './chunk-SLWDNGWK.js';
@@ -0,0 +1,22 @@
1
+ type DomSection = {
2
+ header?: HTMLElement;
3
+ content: Node[];
4
+ children: DomSection[];
5
+ };
6
+ declare function getStateDescriptionRenderer({ element, rootStateKey, splitHeader, }: {
7
+ element: HTMLElement;
8
+ rootStateKey: string;
9
+ splitHeader: (header?: HTMLElement) => [stateKey: undefined | string, label: string];
10
+ }): (() => void) | ((statesStack: string[]) => HTMLDivElement | undefined);
11
+ declare function visitDom(elm: Node): Iterable<Node>;
12
+ declare function visitSectionNodes(section: DomSection): Iterable<Node>;
13
+ declare function vistSections(root: DomSection, ignoreRoot?: boolean): Generator<DomSection>;
14
+ declare function findSection(section: DomSection, accept: (section: DomSection) => boolean): DomSection | undefined;
15
+ declare function buildSections(root: HTMLElement | Iterable<Node>): DomSection;
16
+ declare function renderSections({ section, deep, header, }: {
17
+ section: DomSection;
18
+ deep?: (s: DomSection) => boolean;
19
+ header?: (header: HTMLElement) => undefined | string | HTMLElement;
20
+ }): HTMLDivElement;
21
+
22
+ export { type DomSection, buildSections, findSection, getStateDescriptionRenderer, renderSections, visitDom, visitSectionNodes, vistSections };
@@ -0,0 +1 @@
1
+ export { buildSections, findSection, getStateDescriptionRenderer, renderSections, visitDom, visitSectionNodes, vistSections } from './chunk-TZRPE2VD.js';
@@ -1,4 +1,4 @@
1
- import { S as StateChart, d as TransitionsGraph } from './StateChart-4_Yew7nT.js';
1
+ import { S as StateChart, d as TransitionsGraph } from './StateChart-DlcWaRml.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-4_Yew7nT.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-C3JXXoPE.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-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';
@@ -1,3 +1,2 @@
1
- export { activeStatesStyle, activeTransitionsStyle, buildStateDetailsStyle, buildStateDetailsStyleWithModifier, buildStatechartCss, buildStatechartStyles, buildStatechartStylesWithModifier, buildStatechartSvg, buildStatechartsPanel, selectedStatesStyle, selectedTransitionsStyle } from './chunk-2BBNBZQI.js';
2
- import './chunk-NXWOFQMO.js';
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';
@@ -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-4_Yew7nT.js';
2
- export { D as Dimensions, a as Position, b as StateGraphEdge, c as StateGraphNode } from './StateChart-4_Yew7nT.js';
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: Transition[];
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
  /**
@@ -1,3 +1,2 @@
1
- export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-OTGN3OYG.js';
2
- import './chunk-NXWOFQMO.js';
3
- import './chunk-XEO3YXBM.js';
1
+ export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-U5LUJ7JS.js';
2
+ import './chunk-FIQDLBWD.js';
@@ -1,5 +1,5 @@
1
- import { S as StateChart, c as StateGraphNode, b as StateGraphEdge } from './StateChart-4_Yew7nT.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-4_Yew7nT.js';
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 {
@@ -1,2 +1 @@
1
- export { RuntimeStatechartApi, StateChartIndex } from './chunk-NXS24DZQ.js';
2
- import './chunk-XEO3YXBM.js';
1
+ export { RuntimeStatechartApi, StateChartIndex } from './chunk-FS3L6FBI.js';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
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-4_Yew7nT.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-DlcWaRml.js';
2
+ export { DomSection, buildSections, findSection, getStateDescriptionRenderer, renderSections, visitDom, visitSectionNodes, vistSections } from './index-dom.js';
2
3
  export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './index-config.js';
3
4
  export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './index-layout.js';
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-C3JXXoPE.js';
5
+ 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';
5
6
  export { RuntimeListener, RuntimeStatechartApi, StateChartIndex } from './index-runtime.js';
6
7
 
7
8
  declare function toKebabCase(str?: string): string;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './chunk-SHSJVXEB.js';
2
- export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-OTGN3OYG.js';
3
- export { activeStatesStyle, activeTransitionsStyle, buildStateDetailsStyle, buildStateDetailsStyleWithModifier, buildStatechartCss, buildStatechartStyles, buildStatechartStylesWithModifier, buildStatechartSvg, buildStatechartsPanel, selectedStatesStyle, selectedTransitionsStyle, serializeCss, toKebabCase } from './chunk-2BBNBZQI.js';
4
- import './chunk-NXWOFQMO.js';
5
- export { RuntimeStatechartApi, StateChartIndex } from './chunk-NXS24DZQ.js';
6
- import './chunk-XEO3YXBM.js';
1
+ export { buildSections, findSection, getStateDescriptionRenderer, renderSections, visitDom, visitSectionNodes, vistSections } from './chunk-TZRPE2VD.js';
2
+ export { concatTransitionsToString, serializeProcessConfig, splitTransitionString, toFsmStateConfig } from './chunk-SLWDNGWK.js';
3
+ export { buildCharts, buildFlatCharts, getGraphParamsProvider, getLabelDimensions } from './chunk-U5LUJ7JS.js';
4
+ export { activeStatesStyle, activeTransitionsStyle, buildStateDetailsStyle, buildStateDetailsStyleWithModifier, buildStatechartCss, buildStatechartStyles, buildStatechartStylesWithModifier, buildStatechartSvg, buildStatechartsPanel, selectedStatesStyle, selectedTransitionsStyle, serializeCss, toKebabCase } from './chunk-2XPO6T2M.js';
5
+ import './chunk-FIQDLBWD.js';
6
+ export { RuntimeStatechartApi, StateChartIndex } from './chunk-FS3L6FBI.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statewalker/fsm-charts",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "HFSM Implementation",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/statewalker/statewalker-fsm-charts",
@@ -6,7 +6,7 @@ export function serializeProcessConfig(config: FsmStateConfig | undefined) {
6
6
  visit(config, lines);
7
7
  return lines.join("\n");
8
8
 
9
- function visit(config: FsmStateConfig, lines: string[], shift = " ") {
9
+ function visit(config: FsmStateConfig, lines: string[], shift = "") {
10
10
  lines.push(`${shift}{`);
11
11
  const { key, states, transitions, ...params } = config;
12
12
  lines.push(`${shift} "key": ${JSON.stringify(key)}`);
@@ -0,0 +1,267 @@
1
+ export type DomSection = {
2
+ header?: HTMLElement;
3
+ content: Node[];
4
+ children: DomSection[];
5
+ };
6
+
7
+ export function getStateDescriptionRenderer({
8
+ element,
9
+ rootStateKey,
10
+ splitHeader = (
11
+ header?: HTMLElement,
12
+ ): [stateKey: undefined | string, label: string] => {
13
+ if (!header) return [undefined, ""];
14
+ const text = header.innerText.trim();
15
+ let key: string | undefined;
16
+ let label: string = text;
17
+ text.replace(/^\s*\[(.*)\]\s*(.*)$/, (_, k, l) => {
18
+ key = k.trim();
19
+ label = l.trim() || key;
20
+ return "";
21
+ });
22
+ return [key, label];
23
+ },
24
+ }: {
25
+ element: HTMLElement;
26
+ rootStateKey: string;
27
+ splitHeader: (
28
+ header?: HTMLElement,
29
+ ) => [stateKey: undefined | string, label: string];
30
+ }) {
31
+ const docSections = buildSections(element);
32
+ const rootStateFilter = getStateDescriptionFilter(splitHeader, rootStateKey);
33
+ const rootDescription = findSection(docSections, rootStateFilter);
34
+
35
+ if (!rootDescription) {
36
+ return () => {};
37
+ }
38
+
39
+ // Remove description nodes from DOM
40
+ for (const node of visitSectionNodes(rootDescription)) {
41
+ if (node.nodeName[0] === "#") continue;
42
+ node.parentElement?.removeChild(node);
43
+ }
44
+ // for (const section of vistSections(rootDescription)) {
45
+ // const [key, label] = splitHeader(section.header);
46
+ // console.log("??????", section.header?.innerText, key);
47
+ // if (!key) continue;
48
+
49
+ // section.header?.remove();
50
+ // for (const node of section.content) {
51
+ // if (node.nodeName[0] === "#") continue;
52
+ // node.parentElement?.removeChild(node);
53
+ // }
54
+ // }
55
+
56
+ return (statesStack: string[]) => {
57
+ const stateKey = [...statesStack].pop();
58
+ const filter = getStateDescriptionFilter(splitHeader, stateKey);
59
+ const description = findSection(rootDescription, filter);
60
+ if (!description) return;
61
+ const elm = renderSections({
62
+ section: description,
63
+ deep: (s) => !rootStateFilter(s),
64
+ header: (header) => {
65
+ const [key, label] = splitHeader(header);
66
+ if (key === stateKey) {
67
+ return label || key;
68
+ }
69
+ return;
70
+ },
71
+ });
72
+ const details = elm?.querySelector("details");
73
+ details && (details.open = true);
74
+ return elm;
75
+ };
76
+
77
+ function getStateDescriptionFilter(
78
+ splitHeader: (header: HTMLElement) => [stateKey?: string, label?: string],
79
+ stateKey?: string,
80
+ ) {
81
+ if (!stateKey) return () => false;
82
+ return (section: DomSection) => {
83
+ if (!section.header) return false;
84
+ const [key] = splitHeader(section.header);
85
+ return key === stateKey;
86
+ };
87
+ }
88
+ }
89
+
90
+ export function* visitDom(elm: Node): Iterable<Node> {
91
+ for (let node = elm.firstChild; node; node = node.nextSibling) {
92
+ if (isDomElement(node)) {
93
+ if (node.tagName === "DIV") {
94
+ yield* visitDom(node);
95
+ } else {
96
+ yield node;
97
+ }
98
+ } else {
99
+ yield node;
100
+ }
101
+ }
102
+ }
103
+
104
+ export function* visitSectionNodes(section: DomSection): Iterable<Node> {
105
+ if (section.header) yield section.header;
106
+ yield* section.content;
107
+ for (const s of vistSections(section, true)) {
108
+ yield* visitSectionNodes(s);
109
+ }
110
+ }
111
+
112
+ export function* vistSections(
113
+ root: DomSection,
114
+ ignoreRoot: boolean = false,
115
+ ): Generator<DomSection> {
116
+ !ignoreRoot && (yield root);
117
+ for (const child of root.children) {
118
+ yield* vistSections(child, false);
119
+ }
120
+ }
121
+
122
+ export function findSection(
123
+ section: DomSection,
124
+ accept: (section: DomSection) => boolean,
125
+ ) {
126
+ for (const s of vistSections(section)) {
127
+ if (accept(s) === true) return s;
128
+ }
129
+ }
130
+
131
+ function isDomElement(node: Node): node is HTMLElement {
132
+ return node.nodeType === Node.ELEMENT_NODE;
133
+ }
134
+
135
+ function newAligner<T extends unknown[] = []>(context: {
136
+ enter: (level: number, ...params: T) => void;
137
+ exit: (level: number, ...params: T) => void;
138
+ }) {
139
+ let level = -1;
140
+ return (newLevel: number, ...params: T) => {
141
+ while (level >= 0 && level >= newLevel) {
142
+ context.exit(level--, ...params);
143
+ }
144
+ while (level < newLevel) {
145
+ context.enter(++level, ...params);
146
+ }
147
+ };
148
+ }
149
+
150
+ function* toDomNodesIterator(root: Node | Iterable<Node>): Iterable<Node> {
151
+ yield* root instanceof Node ? visitDom(root) : root;
152
+ }
153
+
154
+ export function buildSections(root: HTMLElement | Iterable<Node>): DomSection {
155
+ const nodes = toDomNodesIterator(root);
156
+ let top: DomSection = null!;
157
+ let peek: DomSection = null!;
158
+ const stack: DomSection[] = [];
159
+ const aligner = newAligner<[HTMLElement?]>({
160
+ enter(level, header) {
161
+ const section: DomSection = {
162
+ header,
163
+ content: [],
164
+ children: [],
165
+ };
166
+ top = top || section;
167
+ peek && peek.children.push(section);
168
+ peek = section;
169
+ stack.push(section);
170
+ },
171
+ exit() {
172
+ stack.pop();
173
+ peek = stack[stack.length - 1];
174
+ },
175
+ });
176
+ aligner(0);
177
+ let currentHeaderLevel = 0;
178
+ let currentLevel = 0;
179
+ for (const node of nodes) {
180
+ if (isDomElement(node)) {
181
+ if (/^H[1-6]$/i.test(node.tagName)) {
182
+ const headerLevel = +node.tagName.replace(/^H/, "");
183
+ currentLevel =
184
+ headerLevel > currentHeaderLevel
185
+ ? currentLevel + 1
186
+ : headerLevel < currentHeaderLevel
187
+ ? currentLevel - 1
188
+ : currentLevel;
189
+ currentHeaderLevel = headerLevel;
190
+ aligner(currentLevel, node);
191
+ } else {
192
+ peek.content.push(node);
193
+ }
194
+ } else {
195
+ peek.content.push(node);
196
+ }
197
+ }
198
+ return top.content.length === 0 && top.children.length === 1 && !top.header
199
+ ? top.children[0]
200
+ : top;
201
+ }
202
+
203
+ export function renderSections({
204
+ section,
205
+ deep = (s) => true,
206
+ header = (headerElm) => headerElm,
207
+ }: {
208
+ section: DomSection;
209
+ deep?: (s: DomSection) => boolean;
210
+ header?: (header: HTMLElement) => undefined | string | HTMLElement;
211
+ }) {
212
+ const container = document.createElement("div");
213
+ const id = `id-${String(Math.random()).split(".")[1]}-${Date.now()}`;
214
+ container.setAttribute("id", id);
215
+ if (!section) return container;
216
+
217
+ const sectionView = renderSection(section);
218
+ container.append(sectionView);
219
+ const style = renderSectionStyles(id);
220
+ container.append(style);
221
+ return container;
222
+
223
+ function renderSectionStyles(id?: string) {
224
+ const prefix = id ? `#${id}` : "";
225
+ const style = document.createElement("style");
226
+ container.appendChild(style);
227
+ style.innerHTML = `
228
+ ${prefix} details {
229
+ border: 1px solid #aaa;
230
+ border-radius: 4px;
231
+ padding: 0.5em 0.5em 0;
232
+ margin-bottom: 0.5em;
233
+ }
234
+
235
+ ${prefix} details > summary {
236
+ font-weight: bold;
237
+ margin: -0.5em -0.5em 0;
238
+ padding: 0.5em;
239
+ cursor: pointer;
240
+ }
241
+
242
+ ${prefix} details[open] {
243
+ padding: 0.5em;
244
+ }
245
+ `;
246
+ return style;
247
+ }
248
+ function renderSection(section: DomSection) {
249
+ const details = document.createElement("details");
250
+ const summary = document.createElement("summary");
251
+ details.appendChild(summary);
252
+ const content = document.createElement("div");
253
+ details.appendChild(content);
254
+ const headerElm = header(section.header!);
255
+ headerElm && summary.append(headerElm);
256
+ for (const node of section.content) {
257
+ if (node.nodeName[0] === "#") continue;
258
+ content.append(node.cloneNode(true));
259
+ }
260
+ if (deep(section)) {
261
+ for (const child of section.children) {
262
+ content.append(renderSection(child));
263
+ }
264
+ }
265
+ return details;
266
+ }
267
+ }
@@ -0,0 +1 @@
1
+ export * from "./dom/index.ts";
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type * from "./types/index.ts";
2
+ export * from "./dom/index.ts";
2
3
  export * from "./config/index.ts";
3
4
  export * from "./layout/index.ts";
4
5
  export * from "./html/index.ts";
@@ -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: Transition[];
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: vertical ? "tb" : "lr", multigraph: true });
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: "lr" });
87
+ layout(graph, { rankdir });
85
88
 
86
89
  const [top, right, bottom, left] = getPadding(padding);
87
90
 
@@ -11,6 +11,6 @@ import type { Transition } from "./Transition.ts";
11
11
 
12
12
  export type FsmStateConfig = {
13
13
  key: string;
14
- transitions: Transition[];
14
+ transitions?: Transition[];
15
15
  states?: FsmStateConfig[];
16
16
  } & Record<string, any>;
@@ -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 };