@cardenelabs/dragon 0.36.4 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/export.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var fs = require('fs');
4
- var path = require('path');
4
+ var path$1 = require('path');
5
5
  var module$1 = require('module');
6
6
  var promises = require('fs/promises');
7
7
 
@@ -279,13 +279,46 @@ var LOOK = {
279
279
  region: { pad: 18, gap: 10, radius: 14, inset: 14, icon: 24, iconRadius: 7, iconScale: 0.68, nameY: 58, line: 16, minH: 108 },
280
280
  architecture: { columns: 4, columnGap: 56, maxColumnGap: 160, rowGap: 44, labelRoom: 16 },
281
281
  sequence: { columnGap: 40, labelRoom: 16, firstRow: 22, rowGap: 14, stepGap: 8, minPitch: 40, tail: 18, selfW: 34, selfH: 18 },
282
- edge: { inset: 3, arrow: 6, arrowHalf: 3.5, parallel: 5, ghostDash: 5, flowDash: 9 },
282
+ /**
283
+ * 状態遷移図 (#3163)。状態は `columns` つずつ並べて次の段へ折り返し、段の間 (`rowGap`) の真ん中を、段をまたぐ線が通る。
284
+ * `start` と `end` は始まりと終わりの印の半径と、印の中の丸の半径。`drop` は最初の状態の上端から始まりの印の中心まで、
285
+ * `below` は状態の下端から終わりの印の中心まで、`beside` は状態の右端から右に置く終わりの印の中心まで、`text` は印の中心から字の左端まで。
286
+ * `loop` は同じ状態へ戻る輪の幅と深さ。`side` は脇道の囲みの内側の余白、1 段目の上端との間、脇道へ入る線が横に通る所の囲みの下端からの離れ、
287
+ * 点線の線が箱へ入る所を箱の端から離す幅。
288
+ * `ghost` は脇道の点線の札で、絵柄を左に、名前と下の字を右に並べる (#3171)。`h` は札の高さ、`pad` は左右の余白、`gap` は絵柄と字の間、
289
+ * `nameY` と `subY` は札の真ん中から名前と下の字の基準線まで。
290
+ * `done` は出た状態の右上の済んだ印の半径と、箱の右上の角からの離れ。
291
+ * `loop` の `samples` は同じ状態へ戻る弧を区切る点の数、`badgeAt` は弧の段の番号を弧の上端から深さのどこに置くかの割合。
292
+ * `pastLabel` は段が終わった後に薄く残す線の名前の濃さ (#3171)
293
+ */
294
+ state: {
295
+ columns: 4,
296
+ columnGap: 64,
297
+ rowGap: 108,
298
+ labelRoom: 16,
299
+ start: 7,
300
+ end: { r: 9, inner: 5 },
301
+ drop: 56,
302
+ below: 64,
303
+ beside: 38,
304
+ text: 16,
305
+ loop: { w: 24, h: 34, samples: 12, badgeAt: 0.6 },
306
+ side: { pad: 16, gap: 76, lane: 30, entry: 28 },
307
+ ghost: { h: 52, pad: 12, gap: 10, nameY: -2, subY: 14 },
308
+ done: { r: 6.5, inset: 13 },
309
+ pastLabel: 0.85
310
+ },
311
+ /** `bend` は線の曲がりを丸める半径 (#3171) */
312
+ edge: { inset: 3, arrow: 6, arrowHalf: 3.5, parallel: 5, ghostDash: 5, flowDash: 9, bend: 12 },
283
313
  label: { h: 20, padX: 9, radius: 10, offset: 22, side: 14, search: 4, searchMax: 400, soft: 6 },
284
314
  action: { h: 22, padX: 10, radius: 11 },
285
315
  badge: { r: 9.5, ring: 9, inset: 4, along: 14, short: 44 },
286
316
  carrier: { envW: 24, envH: 17, coinR: 6.5, coinIn: 3.8, tagH: 18, tagPadX: 8, samples: 16 },
287
- strip: { h: 72, line: 44, pad: 12, icon: 24, titleX: 44, fieldGap: 22, sepInset: 14, tagGap: 6, tagH: 15, tagPadX: 7, nameY: 22, valueY: 43 },
288
- stroke: { hair: 1, edge: 1.7, edgeOn: 2.25, arrow: 1.5, flow: 1.3, halo: 7, on: 1.75, glyph: 2, lifeline: 1.2, envelope: 1.5, badgeRing: 1.5 },
317
+ /**
318
+ * `trail` は状態遷移図の帯の最後の、通った状態の点 (#3171)。`r` は点の半径、`step` は点の中心どうしの間、`now` は変わった値の欄の名前の横の点の半径と、名前からの離れ
319
+ */
320
+ strip: { h: 72, line: 44, pad: 12, icon: 24, titleX: 44, fieldGap: 22, sepInset: 14, tagGap: 6, tagH: 15, tagPadX: 7, nameY: 22, valueY: 43, trail: { r: 5.4, step: 16 }, now: { r: 3, gap: 7 } },
321
+ stroke: { hair: 1, edge: 1.7, edgeOn: 2.25, arrow: 1.5, flow: 1.3, halo: 7, on: 1.75, glyph: 2, lifeline: 1.2, envelope: 1.5, badgeRing: 1.5, path: 1.6, end: 1.6, done: 1.2, trail: 1.2 },
289
322
  shadow: { near: 0.8, far: 4, nearY: 1, farY: 3 },
290
323
  mini: { w: 168, pad: 8, title: 14, inset: 12, radius: 10 },
291
324
  /**
@@ -299,9 +332,9 @@ var LOOK = {
299
332
  */
300
333
  follow: { aspect: 0.75, minH: 320, fitMinH: 160, ease: 0.6, narrow: 440, badgeRoom: 8, headRoom: 10, head: { pad: 8, h: 40, nameY: 17, subY: 31 } },
301
334
  /** 色を混ぜる割合 (%) */
302
- mix: { icon: 14, regionIcon: 16, regionIconEdge: 34, cap: 12, capEdge: 42, badgePast: 14, badgePastEdge: 70, mini: 62, miniBand: 16, miniBandEdge: 36, view: 6 },
335
+ mix: { icon: 14, regionIcon: 16, regionIconEdge: 34, cap: 12, capEdge: 42, badgePast: 14, badgePastEdge: 70, mini: 62, miniBand: 16, miniBandEdge: 36, view: 6, side: 4, sideEdge: 36, ghostEdge: 60, path: 55, past: 72 },
303
336
  /** 字の並びの基準線を、置きたい高さの真ん中からどれだけ下げるか */
304
- baseline: { label: 3.8, badge: 3.5, carrier: 3.7, stripTitle: 4.5, tag: 3.6, action: 3.8 },
337
+ baseline: { label: 3.8, badge: 3.5, carrier: 3.7, stripTitle: 4.5, tag: 3.6, action: 3.8, mark: 4 },
305
338
  /** 浮いて出る物が下から上がる長さと、弾んで出る物の始まりの大きさ */
306
339
  rise: 5,
307
340
  popFrom: 0.4};
@@ -335,7 +368,9 @@ var MOTION = {
335
368
  popFade: 0.4,
336
369
  untilFade: 0.2,
337
370
  /** 段の止め絵を撮る時刻を、段の終わりからどれだけ前にするか */
338
- still: 0.45
371
+ still: 0.45,
372
+ /** 状態遷移図で、札が状態を出てから済んだ印が出るまで */
373
+ done: 0.3
339
374
  };
340
375
  var READABLE_PX = 10.5;
341
376
  var EASE = {
@@ -353,7 +388,13 @@ var FIGURE_TEXT = {
353
388
  pause: "\u6B62\u3081\u308B",
354
389
  play: "\u52D5\u304B\u3059",
355
390
  next: "\u6B21\u306E\u6BB5",
356
- steps: (title) => `${title} \u306E\u6BB5`
391
+ steps: (title) => `${title} \u306E\u6BB5`,
392
+ side: "\u8107\u9053",
393
+ sideNote: "\u4ECA\u56DE\u306F\u901A\u3089\u306A\u3044",
394
+ sideFrom: (count) => `${count} \u3064\u306E\u72B6\u614B\u304B\u3089\u5165\u308C\u308B`,
395
+ trail: "\u901A\u3063\u305F\u72B6\u614B",
396
+ start: "\u59CB\u307E\u308A",
397
+ end: "\u7D42\u308F\u308A"
357
398
  },
358
399
  en: {
359
400
  cannotDraw: (detail) => `Cannot draw the diagram: ${detail}`,
@@ -362,7 +403,13 @@ var FIGURE_TEXT = {
362
403
  pause: "Pause",
363
404
  play: "Play",
364
405
  next: "Next step",
365
- steps: (title) => `Steps of ${title}`
406
+ steps: (title) => `Steps of ${title}`,
407
+ side: "Side path",
408
+ sideNote: "Not taken this time",
409
+ sideFrom: (count) => `Enterable from ${count} ${count === 1 ? "state" : "states"}`,
410
+ trail: "States passed",
411
+ start: "Start",
412
+ end: "End"
366
413
  }
367
414
  };
368
415
 
@@ -457,12 +504,12 @@ function placeLabel(request, obstacles) {
457
504
  const segment = longest(request.points);
458
505
  const mx = (segment.a[0] + segment.b[0]) / 2;
459
506
  const my = (segment.a[1] + segment.b[1]) / 2;
460
- const side = request.side ?? (segment.vertical ? "right" : "above");
507
+ const side2 = request.side ?? (segment.vertical ? "right" : "above");
461
508
  const { offset, side: sideGap } = LOOK.label;
462
- const base = side === "above" ? { x: mx - w / 2, y: my - offset - h / 2, w, h } : side === "below" ? { x: mx - w / 2, y: my + offset - h / 2, w, h } : side === "left" ? { x: mx - sideGap - w, y: my - h / 2, w, h } : { x: mx + sideGap, y: my - h / 2, w, h };
463
- const away = side === "above" ? [0, -1] : side === "below" ? [0, 1] : side === "left" ? [-1, 0] : [1, 0];
509
+ const base = side2 === "above" ? { x: mx - w / 2, y: my - offset - h / 2, w, h } : side2 === "below" ? { x: mx - w / 2, y: my + offset - h / 2, w, h } : side2 === "left" ? { x: mx - sideGap - w, y: my - h / 2, w, h } : { x: mx + sideGap, y: my - h / 2, w, h };
510
+ const away = side2 === "above" ? [0, -1] : side2 === "below" ? [0, 1] : side2 === "left" ? [-1, 0] : [1, 0];
464
511
  const slideAxis = [Math.abs(away[1]), Math.abs(away[0])];
465
- const slideMax = side === "above" || side === "below" ? w : h * 4;
512
+ const slideMax = side2 === "above" || side2 === "below" ? w : h * 4;
466
513
  const clear = (rect) => obstacles.hard.every((box) => gapBetween(rect, box) >= LOOK.gap) && obstacles.soft.every((other) => gapBetween(rect, other) >= LOOK.label.soft);
467
514
  const { search, searchMax } = LOOK.label;
468
515
  for (let d = 0; d <= searchMax; d += search) {
@@ -488,29 +535,36 @@ function fieldWidth(diagram, name) {
488
535
  const both = value + (tag > 0 ? (value > 0 ? LOOK.strip.tagGap : 0) + tag : 0);
489
536
  return Math.max(textWidth(name, TYPE.fieldName), both);
490
537
  }
491
- function stripNeed(diagram) {
538
+ var trailWidth = (trail) => Math.max(textWidth(trail.title, TYPE.fieldName), trail.states.length * LOOK.strip.trail.step);
539
+ function stripNeed(diagram, trail) {
492
540
  if (!diagram.strip) return 0;
493
541
  const { titleX, fieldGap, pad: pad2 } = LOOK.strip;
494
542
  const start = titleX + textWidth(diagram.strip.title, TYPE.stripTitle) + fieldGap;
495
- return start + diagram.strip.fields.reduce((sum, name) => sum + fieldWidth(diagram, name) + fieldGap, 0) - fieldGap + pad2;
543
+ const widths = [...diagram.strip.fields.map((name) => fieldWidth(diagram, name)), ...trail ? [trailWidth(trail)] : []];
544
+ return start + widths.reduce((sum, w) => sum + w + fieldGap, 0) - fieldGap + pad2;
496
545
  }
497
- function layoutStrip(diagram, x, y, width) {
546
+ function layoutStrip(diagram, x, y, width, trail) {
498
547
  if (!diagram.strip) return void 0;
499
548
  const { titleX, fieldGap, pad: pad2, line, h } = LOOK.strip;
500
549
  const start = titleX + textWidth(diagram.strip.title, TYPE.stripTitle) + fieldGap;
501
550
  const fields = [];
502
551
  let cx = start;
503
552
  let row = 0;
504
- for (const name of diagram.strip.fields) {
505
- const w = fieldWidth(diagram, name);
553
+ const place = (w) => {
506
554
  if (cx > start && cx + w > width - pad2) {
507
555
  cx = start;
508
556
  row++;
509
557
  }
510
- fields.push({ name, x: x + cx, y: y + row * line, w });
558
+ const at2 = { x: x + cx, y: y + row * line };
511
559
  cx += w + fieldGap;
560
+ return at2;
561
+ };
562
+ for (const name of diagram.strip.fields) {
563
+ const w = fieldWidth(diagram, name);
564
+ fields.push({ name, ...place(w), w });
512
565
  }
513
- return { x, y, w: width, h: h + row * line, title: diagram.strip.title, fields };
566
+ const laidTrail = trail ? { ...trail, ...place(trailWidth(trail)), w: trailWidth(trail) } : void 0;
567
+ return { x, y, w: width, h: h + row * line, title: diagram.strip.title, fields, ...laidTrail ? { trail: laidTrail } : {} };
514
568
  }
515
569
  function shiftContent(layout, dx, dy) {
516
570
  const move = (rect) => {
@@ -536,6 +590,15 @@ function shiftContent(layout, dx, dy) {
536
590
  if (edge2.settle) edge2.settle = [edge2.settle[0] + dx, edge2.settle[1] + dy];
537
591
  }
538
592
  for (const label2 of layout.labels) move(label2);
593
+ for (const path2 of layout.paths) {
594
+ path2.points = path2.points.map(([px, py]) => [px + dx, py + dy]);
595
+ if (path2.label) move(path2.label);
596
+ }
597
+ for (const end of layout.ends) {
598
+ end.x += dx;
599
+ end.y += dy;
600
+ }
601
+ if (layout.side) move(layout.side);
539
602
  for (const action2 of layout.actions) move(action2);
540
603
  for (const badge2 of layout.badges) {
541
604
  badge2.x += dx;
@@ -547,6 +610,10 @@ function shiftContent(layout, dx, dy) {
547
610
  field.x += dx;
548
611
  field.y += dy;
549
612
  }
613
+ if (layout.strip.trail) {
614
+ layout.strip.trail.x += dx;
615
+ layout.strip.trail.y += dy;
616
+ }
550
617
  }
551
618
  }
552
619
  function cornerBadge(events, step, layout) {
@@ -578,7 +645,7 @@ function groupsOf(diagram) {
578
645
  if (loose.length > 0) groups.push({ members: loose });
579
646
  return groups;
580
647
  }
581
- var vertical = (side) => side === "left" || side === "right";
648
+ var vertical = (side2) => side2 === "left" || side2 === "right";
582
649
  function placeBoxes(diagram, groups) {
583
650
  const columns = LOOK.architecture.columns;
584
651
  const edges = edgesOf(diagram).map((e) => e.edge);
@@ -825,7 +892,7 @@ function arrange(diagram, groups, slots, rooms) {
825
892
  )
826
893
  );
827
894
  }
828
- const layout = { kind: "architecture", width: 0, height: 0, regions, boxes, lifelines: [], edges: sceneEdges, labels, actions: [], badges: [] };
895
+ const layout = { kind: "architecture", width: 0, height: 0, regions, boxes, lifelines: [], edges: sceneEdges, labels, actions: [], badges: [], paths: [], ends: [] };
829
896
  const shift = labels.length > 0 ? Math.max(0, margin + LOOK.label.soft - Math.min(...labels.map((l) => l.x))) : 0;
830
897
  if (shift > 0) shiftContent(layout, shift, 0);
831
898
  const contentRight = Math.max(...boxes.map((b) => b.x + b.w + R.pad), ...labels.map((l) => l.x + l.w + LOOK.label.soft), ...sceneEdges.flatMap((e) => e.points.map((p) => p[0] + R.pad)));
@@ -932,11 +999,11 @@ function layoutSequence(diagram) {
932
999
  let above;
933
1000
  let under;
934
1001
  if (event.type === "edge") {
935
- const side = event.labelSide ?? "above";
1002
+ const side2 = event.labelSide ?? "above";
936
1003
  const self = event.from === event.to;
937
1004
  const named = event.label !== void 0;
938
- above = named && side === "above" ? L.offset + L.h / 2 : gap;
939
- under = self ? Q.selfH + gap : named && side === "below" ? L.offset + L.h / 2 : gap;
1005
+ above = named && side2 === "above" ? L.offset + L.h / 2 : gap;
1006
+ under = self ? Q.selfH + gap : named && side2 === "below" ? L.offset + L.h / 2 : gap;
940
1007
  } else {
941
1008
  above = LOOK.action.h / 2;
942
1009
  under = LOOK.action.h / 2;
@@ -983,7 +1050,7 @@ function layoutSequence(diagram) {
983
1050
  const soft = [...labels.filter((l) => l.step === request.step), ...actions];
984
1051
  labels.push(placeLabel(request, { hard: boxes, soft }));
985
1052
  }
986
- const layout = { kind: "sequence", width: 0, height: 0, regions: [], boxes, lifelines, edges, labels, actions, badges: [] };
1053
+ const layout = { kind: "sequence", width: 0, height: 0, regions: [], boxes, lifelines, edges, labels, actions, badges: [], paths: [], ends: [] };
987
1054
  const lefts = [...boxes.map((b) => b.x), ...labels.map((l) => l.x), ...actions.map((a) => a.x)];
988
1055
  const shift = Math.max(0, margin - Math.min(...lefts));
989
1056
  if (shift > 0) shiftContent(layout, shift, 0);
@@ -1009,6 +1076,302 @@ function badges(diagram, layout) {
1009
1076
  return cornerBadge(step.events, s, layout);
1010
1077
  });
1011
1078
  }
1079
+ var STATE_ENDS = ["start", "finish"];
1080
+
1081
+ // src/layout/state.ts
1082
+ var isEnd = (id) => STATE_ENDS.includes(id);
1083
+ function visitOrder(diagram) {
1084
+ const order = [];
1085
+ const add = (id) => {
1086
+ if (!isEnd(id) && !order.includes(id)) order.push(id);
1087
+ };
1088
+ for (const { edge: edge2 } of edgesOf(diagram)) {
1089
+ add(edge2.from);
1090
+ add(edge2.to);
1091
+ }
1092
+ return order;
1093
+ }
1094
+ function carrierHalf(carry) {
1095
+ const C = LOOK.carrier;
1096
+ if (carry.kind === "tag") return (textWidth(carry.text, hasWide(carry.text) ? TYPE.carrierJa : TYPE.carrier) + C.tagPadX * 2) / 2;
1097
+ if (carry.kind === "coin") return C.coinR;
1098
+ return C.envW / 2;
1099
+ }
1100
+ var same = (a, b) => a.from === b.from && a.to === b.to;
1101
+ function layoutState(diagram, lang) {
1102
+ const { box: B, state: T, margin, gap } = LOOK;
1103
+ const inset = LOOK.edge.inset;
1104
+ const words = FIGURE_TEXT[lang];
1105
+ const colors = boxColors(diagram);
1106
+ const steps = edgesOf(diagram);
1107
+ const walked = visitOrder(diagram);
1108
+ const ghosts = diagram.boxes.map((b) => b.id).filter((id) => !walked.includes(id));
1109
+ const notTaken = (diagram.state?.paths ?? []).filter((p) => !steps.some(({ edge: edge2 }) => same(edge2, p)));
1110
+ const lines = [...steps.map(({ edge: edge2 }) => edge2), ...notTaken];
1111
+ const G = T.ghost;
1112
+ const ghostWidth = (id) => {
1113
+ const source = diagram.boxes.find((b) => b.id === id);
1114
+ return G.pad * 2 + B.icon + G.gap + Math.max(textWidth(source?.name ?? id, TYPE.boxName), textWidth(source?.sub ?? "", TYPE.boxSub));
1115
+ };
1116
+ const widths = new Map(diagram.boxes.map((b) => [b.id, ghosts.includes(b.id) ? ghostWidth(b.id) : boxWidth(diagram, b.id, true)]));
1117
+ const columnCount = Math.max(1, Math.min(T.columns, walked.length));
1118
+ const rowCount = Math.max(1, Math.ceil(walked.length / T.columns));
1119
+ const slot = new Map(
1120
+ walked.map((id, k) => {
1121
+ const row = Math.floor(k / T.columns);
1122
+ const at2 = k % T.columns;
1123
+ return [id, { row, col: row % 2 === 0 ? at2 : columnCount - 1 - at2 }];
1124
+ })
1125
+ );
1126
+ const colW = Array.from({ length: columnCount }, (_, c) => Math.max(B.minW, ...walked.filter((id) => slot.get(id)?.col === c).map((id) => widths.get(id) ?? B.minW)));
1127
+ const between = Array.from({ length: Math.max(0, columnCount - 1) }, () => T.columnGap);
1128
+ for (const line of lines) {
1129
+ const a = slot.get(line.from);
1130
+ const b = slot.get(line.to);
1131
+ if (!a || !b || line.label === void 0 || a.row !== b.row || Math.abs(a.col - b.col) !== 1) continue;
1132
+ const i = Math.min(a.col, b.col);
1133
+ between[i] = Math.max(between[i] ?? 0, textWidth(line.label, labelStyle(line.label)) + LOOK.label.padX * 2 + T.labelRoom * 2);
1134
+ }
1135
+ const colLeft = [];
1136
+ for (let c = 0; c < columnCount; c++) colLeft.push(c === 0 ? margin : colLeft[c - 1] + colW[c - 1] + between[c - 1]);
1137
+ const center = (c) => colLeft[c] + colW[c] / 2;
1138
+ const isGhost = (id) => ghosts.includes(id);
1139
+ const enteringFrom = new Set(notTaken.filter((p) => isGhost(p.to) && !isGhost(p.from) && !isEnd(p.from)).map((p) => p.from));
1140
+ const notes = [words.sideNote, ...enteringFrom.size > 0 ? [words.sideFrom(enteringFrom.size)] : []];
1141
+ const titleW = Math.max(textWidth(words.side, TYPE.regionName), ...notes.map((note) => textWidth(note, TYPE.regionNote)));
1142
+ const sideH = T.side.pad * 2 + Math.max(G.h, TYPE.regionName.size + LOOK.region.line * notes.length + T.side.pad / 4);
1143
+ const starts = lines.some((line) => line.from === "start");
1144
+ const top0 = margin + (ghosts.length > 0 ? sideH + T.side.gap : starts ? T.start + T.drop : 0);
1145
+ const rowY = (row) => top0 + row * (B.h + T.rowGap);
1146
+ const boxOf = (id, cx, y, ghost) => {
1147
+ const source = diagram.boxes.find((b) => b.id === id);
1148
+ const w = widths.get(id) ?? B.minW;
1149
+ const h = ghost ? G.h : B.h;
1150
+ return {
1151
+ id,
1152
+ name: source?.name ?? id,
1153
+ ...source?.sub !== void 0 ? { sub: source.sub } : {},
1154
+ ...source?.icon !== void 0 ? { icon: source.icon } : {},
1155
+ color: colors.get(id) ?? "slate",
1156
+ x: cx - w / 2,
1157
+ y,
1158
+ w,
1159
+ h,
1160
+ cx,
1161
+ cy: y + h / 2,
1162
+ ...ghost ? { ghost: true } : {}
1163
+ };
1164
+ };
1165
+ const boxes = walked.map((id) => {
1166
+ const s = slot.get(id);
1167
+ return boxOf(id, center(s.col), rowY(s.row), false);
1168
+ });
1169
+ const byId = new Map(boxes.map((b) => [b.id, b]));
1170
+ const below = (box) => boxes.some((other) => other !== box && Math.abs(other.cx - box.cx) < 0.5 && other.y > box.y);
1171
+ const ends = [];
1172
+ const first = boxes[0];
1173
+ const contentRight = Math.max(...boxes.map((b) => b.x + b.w));
1174
+ let side2;
1175
+ const lane = margin + sideH + T.side.lane;
1176
+ if (ghosts.length > 0) {
1177
+ const sourcesOf = (id) => notTaken.filter((p) => p.to === id).flatMap((p) => byId.get(p.from) ?? []);
1178
+ const all = ghosts.flatMap(sourcesOf);
1179
+ const x = Math.max(margin, Math.min(...all.length > 0 ? all.map((b) => b.x) : [margin + T.side.pad]) - T.side.pad);
1180
+ let cursor = x + T.side.pad + titleW + gap * 2;
1181
+ const wanted = ghosts.map((id) => {
1182
+ const from = sourcesOf(id);
1183
+ return { id, cx: from.length > 0 ? from.reduce((sum, b) => sum + b.cx, 0) / from.length : cursor };
1184
+ });
1185
+ wanted.sort((a, b) => a.cx - b.cx);
1186
+ let right = x;
1187
+ for (const { id, cx } of wanted) {
1188
+ const w = widths.get(id) ?? B.minW;
1189
+ const left = Math.max(cx - w / 2, cursor);
1190
+ const ghost = boxOf(id, left + w / 2, margin + (sideH - G.h) / 2, true);
1191
+ boxes.push(ghost);
1192
+ byId.set(id, ghost);
1193
+ const finishes = notTaken.some((p) => p.from === id && p.to === "finish");
1194
+ if (finishes) ends.push({ kind: "finish", x: ghost.x + ghost.w + T.beside, y: ghost.cy, r: T.end.r, ghost: true, text: "", box: id });
1195
+ right = finishes ? ghost.x + ghost.w + T.beside + T.end.r : ghost.x + ghost.w;
1196
+ cursor = right + gap * 2;
1197
+ }
1198
+ const rightmost = Math.max(right + T.side.pad, contentRight);
1199
+ side2 = { x, y: margin, w: rightmost - x, h: sideH, title: words.side, notes };
1200
+ }
1201
+ if (first && starts) {
1202
+ const reach = first.cx + T.start + T.text + textWidth(words.start, TYPE.regionNote) + gap;
1203
+ const y = side2 && reach < side2.x ? side2.y + T.side.pad + T.start : first.y - T.drop;
1204
+ ends.unshift({ kind: "start", x: first.cx, y, r: T.start, ghost: false, text: words.start });
1205
+ }
1206
+ for (const box of boxes.filter((b) => !b.ghost && lines.some((line) => line.from === b.id && line.to === "finish"))) {
1207
+ ends.push(
1208
+ below(box) ? { kind: "finish", x: box.x + box.w + T.beside, y: box.cy, r: T.end.r, ghost: false, text: words.end, box: box.id } : { kind: "finish", x: box.cx, y: box.y + box.h + T.below, r: T.end.r, ghost: false, text: words.end, box: box.id }
1209
+ );
1210
+ }
1211
+ const between2 = (a, b) => {
1212
+ const sa = slot.get(a.id);
1213
+ const sb = slot.get(b.id);
1214
+ if (!sa || !sb) return [[a.cx, a.y + a.h], [b.cx, b.y - inset]];
1215
+ if (sa.row === sb.row && Math.abs(sa.col - sb.col) === 1) {
1216
+ return b.cx > a.cx ? [[a.x + a.w, a.cy], [b.x - inset, b.cy]] : [[a.x, a.cy], [b.x + b.w + inset, b.cy]];
1217
+ }
1218
+ if (sa.row === sb.row) {
1219
+ const y2 = a.y + a.h + T.rowGap / 4;
1220
+ return [[a.cx, a.y + a.h], [a.cx, y2], [b.cx, y2], [b.cx, b.y + b.h + inset]];
1221
+ }
1222
+ if (sb.row > sa.row) {
1223
+ if (Math.abs(a.cx - b.cx) < 0.5) return [[a.cx, a.y + a.h], [b.cx, b.y - inset]];
1224
+ const y2 = a.y + a.h + T.rowGap / 2;
1225
+ return [[a.cx, a.y + a.h], [a.cx, y2], [b.cx, y2], [b.cx, b.y - inset]];
1226
+ }
1227
+ if (Math.abs(a.cx - b.cx) < 0.5) return [[a.cx, a.y], [b.cx, b.y + b.h + inset]];
1228
+ const y = b.y + b.h + T.rowGap / 2;
1229
+ return [[a.cx, a.y], [a.cx, y], [b.cx, y], [b.cx, b.y + b.h + inset]];
1230
+ };
1231
+ const entryOf = (from, to) => {
1232
+ const sources = notTaken.filter((p) => p.to === to.id).flatMap((p) => byId.get(p.from) ?? []).sort((a, b) => a.cx - b.cx);
1233
+ const k = sources.findIndex((b) => b.id === from);
1234
+ if (sources.length <= 1) return Math.min(Math.max(sources[0]?.cx ?? to.cx, to.x + T.side.entry), to.x + to.w - T.side.entry);
1235
+ return to.x + T.side.entry + (to.w - T.side.entry * 2) * Math.max(0, k) / (sources.length - 1);
1236
+ };
1237
+ const exitX = (box) => starts && box === first ? box.cx + T.side.entry : box.cx;
1238
+ const finishOf = (id) => ends.find((e) => e.kind === "finish" && e.box === id);
1239
+ const loopOf = (box) => {
1240
+ const { w, h, samples } = T.loop;
1241
+ const bottom2 = box.y + box.h;
1242
+ const p0 = [box.cx + w / 2, bottom2];
1243
+ const c1 = [box.cx + w * 3 / 4, bottom2 + h * 4 / 3];
1244
+ const c2 = [box.cx - w * 3 / 4, bottom2 + h * 4 / 3];
1245
+ const p3 = [box.cx - w / 2, bottom2 + inset];
1246
+ return Array.from({ length: samples + 1 }, (_, k) => {
1247
+ const t = k / samples;
1248
+ const u = 1 - t;
1249
+ const at2 = (i) => u * u * u * p0[i] + 3 * u * u * t * c1[i] + 3 * u * t * t * c2[i] + t * t * t * p3[i];
1250
+ return [at2(0), at2(1)];
1251
+ });
1252
+ };
1253
+ const route = (from, to) => {
1254
+ if (from === "start") {
1255
+ const start = ends.find((e) => e.kind === "start");
1256
+ const target = byId.get(to);
1257
+ if (!start || !target) return [];
1258
+ return [[start.x, start.y + start.r], [target.cx, target.y - inset]];
1259
+ }
1260
+ const a = byId.get(from);
1261
+ if (!a) return [];
1262
+ if (to === "finish") {
1263
+ const end = finishOf(from);
1264
+ if (!end) return [];
1265
+ return Math.abs(end.x - a.cx) < 0.5 ? [[a.cx, a.y + a.h], [a.cx, end.y - end.r - inset]] : [[a.x + a.w, a.cy], [end.x - end.r - inset, a.cy]];
1266
+ }
1267
+ const b = byId.get(to);
1268
+ if (!b) return [];
1269
+ if (from === to) return loopOf(a);
1270
+ if (b.ghost && !a.ghost) {
1271
+ const sx = exitX(a);
1272
+ const ex = entryOf(from, b);
1273
+ return Math.abs(sx - ex) < 0.5 ? [[sx, a.y], [ex, b.y + b.h + inset]] : [[sx, a.y], [sx, lane], [ex, lane], [ex, b.y + b.h + inset]];
1274
+ }
1275
+ if (a.ghost && b.ghost) return [[a.x + a.w, a.cy], [b.x - inset, b.cy]];
1276
+ if (a.ghost) return [[a.cx, a.y + a.h], [a.cx, lane], [b.cx, lane], [b.cx, b.y - inset]];
1277
+ return between2(a, b);
1278
+ };
1279
+ const settleOf = (edge2) => {
1280
+ const target = byId.get(edge2.to);
1281
+ if (target) return [target.cx, target.cy + B.iconY];
1282
+ const end = edge2.to === "finish" ? finishOf(edge2.from) : void 0;
1283
+ if (!end) return void 0;
1284
+ const from = byId.get(edge2.from);
1285
+ return from && Math.abs(end.x - from.cx) < 0.5 ? [end.x - end.r - gap - carrierHalf(edge2.carry), end.y] : [end.x, end.y + end.r + gap + LOOK.carrier.tagH / 2];
1286
+ };
1287
+ const sceneEdges = steps.map(({ step, event, edge: edge2 }) => {
1288
+ const settle = settleOf(edge2);
1289
+ return {
1290
+ step,
1291
+ event,
1292
+ from: edge2.from,
1293
+ to: edge2.to,
1294
+ points: route(edge2.from, edge2.to),
1295
+ color: colorOf(edge2, colors),
1296
+ carry: edge2.carry,
1297
+ ...settle ? { settle } : {}
1298
+ };
1299
+ });
1300
+ for (const e of sceneEdges) {
1301
+ if (e.points.length !== 2 || !sceneEdges.some((o) => o.from === e.to && o.to === e.from && o.points.length === 2)) continue;
1302
+ const [p, q] = e.points;
1303
+ const flat = Math.abs(q[1] - p[1]) < Math.abs(q[0] - p[0]);
1304
+ const d = (e.from < e.to ? 1 : -1) * LOOK.edge.parallel;
1305
+ e.points = e.points.map(([x, y]) => flat ? [x, y + d] : [x + d, y]);
1306
+ }
1307
+ const paths = notTaken.map((p) => ({ from: p.from, to: p.to, points: route(p.from, p.to) }));
1308
+ const labels = [];
1309
+ const soft = side2 ? [{ x: side2.x, y: side2.y, w: T.side.pad + titleW, h: side2.h }] : [];
1310
+ for (const e of sceneEdges) {
1311
+ const source = diagram.steps[e.step]?.events[e.event];
1312
+ if (source?.type !== "edge" || source.label === void 0) continue;
1313
+ const style = labelStyle(source.label);
1314
+ if (e.from === e.to) {
1315
+ const w = textWidth(source.label, style) + LOOK.label.padX * 2;
1316
+ const bottom2 = Math.max(...e.points.map(([, y]) => y));
1317
+ labels.push({ step: e.step, event: e.event, text: source.label, family: style.family, color: e.color, x: (e.points[0]?.[0] ?? 0) - T.loop.w / 2 - w / 2, y: bottom2 + LOOK.label.soft, w, h: LOOK.label.h });
1318
+ continue;
1319
+ }
1320
+ const side22 = source.labelSide ?? (e.to === "finish" ? "left" : void 0);
1321
+ labels.push(
1322
+ placeLabel(
1323
+ { step: e.step, event: e.event, text: source.label, points: e.points, color: e.color, ...side22 ? { side: side22 } : {} },
1324
+ { hard: boxes, soft: [...soft, ...labels.filter((l) => l.step === e.step)] }
1325
+ )
1326
+ );
1327
+ }
1328
+ notTaken.forEach((p, i) => {
1329
+ const path2 = paths[i];
1330
+ if (p.label === void 0 || path2.points.length === 0) return;
1331
+ const style = labelStyle(p.label);
1332
+ const into = byId.get(p.to)?.ghost === true && byId.get(p.from)?.ghost !== true;
1333
+ const rect = into ? { x: path2.points[0][0] + LOOK.label.soft, y: lane + LOOK.label.soft, w: textWidth(p.label, style) + LOOK.label.padX * 2, h: LOOK.label.h } : placeLabel({ step: -1, event: i, text: p.label, points: path2.points, color: "slate" }, { hard: boxes, soft });
1334
+ path2.label = { x: rect.x, y: rect.y, w: rect.w, h: rect.h, text: p.label, family: style.family };
1335
+ });
1336
+ const layout = { kind: "state", width: 0, height: 0, regions: [], boxes, lifelines: [], edges: sceneEdges, labels, actions: [], badges: [], paths, ends, ...side2 ? { side: side2 } : {} };
1337
+ const lefts = [...boxes.map((b) => b.x), ...labels.map((l) => l.x), ...paths.flatMap((p) => p.label ? [p.label.x] : [])];
1338
+ const shift = Math.max(0, margin - Math.min(...lefts));
1339
+ if (shift > 0) shiftContent(layout, shift, 0);
1340
+ const endRight = (e) => e.x + (e.text === "" ? e.r : T.text + textWidth(e.text, TYPE.regionNote));
1341
+ const rights = [
1342
+ ...boxes.map((b) => b.x + b.w),
1343
+ ...labels.map((l) => l.x + l.w),
1344
+ ...ends.map(endRight),
1345
+ ...sceneEdges.flatMap((e) => e.points.map((p) => p[0])),
1346
+ ...paths.flatMap((p) => [...p.points.map((q) => q[0]), ...p.label ? [p.label.x + p.label.w] : []]),
1347
+ ...side2 ? [side2.x + side2.w] : []
1348
+ ];
1349
+ const bottoms = [...boxes.map((b) => b.y + b.h), ...labels.map((l) => l.y + l.h), ...ends.map((e) => e.y + e.r), ...sceneEdges.flatMap((e) => e.points.map((p) => p[1]))];
1350
+ const trail = { title: words.trail, states: walked.map((id) => ({ box: id, color: colors.get(id) ?? "slate" })) };
1351
+ const width = Math.max(Math.max(...rights) + margin, stripNeed(diagram, trail) + margin * 2);
1352
+ const bottom = Math.max(...bottoms, rowY(rowCount - 1) + B.h);
1353
+ const strip2 = layoutStrip(diagram, margin, bottom + gap, width - margin * 2, trail);
1354
+ layout.width = width;
1355
+ layout.height = (strip2 ? strip2.y + strip2.h : bottom) + margin;
1356
+ if (strip2) layout.strip = strip2;
1357
+ layout.badges = diagram.steps.map((step, s) => {
1358
+ const edge2 = sceneEdges.find((e) => e.step === s && e.points.length > 0);
1359
+ if (!edge2) return cornerBadge(step.events, s, layout);
1360
+ if (edge2.from === edge2.to) {
1361
+ const right = Math.max(...edge2.points.map(([px]) => px));
1362
+ const top = edge2.points[0][1];
1363
+ const deep = Math.max(...edge2.points.map(([, py]) => py));
1364
+ return { step: s, x: right + LOOK.badge.r + LOOK.badge.inset, y: top + (deep - top) * T.loop.badgeAt, color: edge2.color };
1365
+ }
1366
+ const [x, y] = badgeOnPath(edge2.points);
1367
+ return { step: s, x, y, color: edge2.color };
1368
+ });
1369
+ return layout;
1370
+ }
1371
+ function colorOf(edge2, colors) {
1372
+ if (edge2.carry.kind === "coin") return edgeColor(edge2, colors);
1373
+ return colors.get(edge2.to === "finish" ? edge2.from : edge2.to) ?? "slate";
1374
+ }
1012
1375
 
1013
1376
  // src/field-messages.ts
1014
1377
  var TYPES_JA = {
@@ -1041,6 +1404,7 @@ var ja = {
1041
1404
  minimum: (limit) => `${limit} \u4EE5\u4E0A\u306B\u3059\u308B`,
1042
1405
  const: (value) => `${value} \u306B\u3059\u308B`,
1043
1406
  not: (allowed) => allowed ? `${allowed.field} \u306E\u6B04\u306F kind \u304C ${allowed.kind} \u306E\u6642\u3060\u3051\u66F8\u3051\u308B` : "\u3053\u306E\u6B04\u306E\u7D44\u307F\u5408\u308F\u305B\u306F\u66F8\u3051\u306A\u3044",
1407
+ reserved: (names) => `${names.join(" \u3068 ")} \u306F\u72B6\u614B\u9077\u79FB\u56F3\u306E\u59CB\u307E\u308A\u3068\u7D42\u308F\u308A\u306E\u5370\u306E\u540D\u524D\u3067\u3001\u7BB1\u306E\u540D\u672D\u306B\u4F7F\u3048\u306A\u3044`,
1044
1408
  anyOf: (fields) => fields.length > 0 ? `${fields.join(" \u304B ")} \u306E${fields.length === 2 ? "\u3069\u3061\u3089\u304B" : "\u3069\u308C\u304B"}\u306E\u6B04\u304C\u8981\u308B` : "\u66F8\u3051\u308B\u5F62\u306E\u3069\u308C\u306B\u3082\u5408\u308F\u306A\u3044",
1045
1409
  oneOf: "\u66F8\u3051\u308B\u5F62\u306E\u3069\u308C\u304B 1 \u3064\u3060\u3051\u306B\u5408\u308F\u305B\u308B",
1046
1410
  discriminator: (tag, values) => `${tag} \u306F ${values.join(" / ")} \u306E\u3069\u308C\u304B\u306B\u3059\u308B`,
@@ -1057,6 +1421,7 @@ var en = {
1057
1421
  minimum: (limit) => `Use ${limit} or greater`,
1058
1422
  const: (value) => `Use ${value}`,
1059
1423
  not: (allowed) => allowed ? `The ${allowed.field} field is allowed only when kind is ${allowed.kind}` : "This combination of fields is not allowed",
1424
+ reserved: (names) => `${names.join(" and ")} name the start and end marks of a state diagram and cannot be box ids`,
1060
1425
  anyOf: (fields) => fields.length > 0 ? `Write one of the ${fields.join(" or ")} fields` : "Does not match any of the allowed shapes",
1061
1426
  oneOf: "Match exactly one of the allowed shapes",
1062
1427
  discriminator: (tag, values) => `${tag} is one of ${values.join(" / ")}`,
@@ -1071,7 +1436,7 @@ function ucs2length(str) {
1071
1436
  return length;
1072
1437
  }
1073
1438
  var validate_diagram_default = validate10;
1074
- var schema11 = { "properties": { "version": { "description": "\u5F62\u5F0F\u306E\u7248", "type": "integer", "minimum": 1 }, "kind": { "description": "\u56F3\u306E\u7A2E\u985E", "enum": ["sequence", "architecture"] }, "title": { "$ref": "#/definitions/text" }, "view": { "description": "\u898B\u305B\u65B9\u3002\u66F8\u304B\u306A\u3051\u308C\u3070\u5B57\u306E\u5927\u304D\u3055\u3067\u9078\u3076\u3002fixed \u306F\u5168\u4F53\u3092\u6B62\u3081\u3066\u4E2D\u3060\u3051\u52D5\u304B\u3057\u3001follow \u306F\u5BC4\u3063\u3066\u52D5\u304B\u3057\u5168\u4F53\u56F3\u3067\u4ECA\u3069\u3053\u304B\u3092\u793A\u3059", "enum": ["fixed", "follow"] }, "regions": { "type": "array", "items": { "$ref": "#/definitions/region" } }, "boxes": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/box" } }, "strip": { "$ref": "#/definitions/strip" }, "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/step" } }, "sequence": { "$ref": "#/definitions/sequence" } }};
1439
+ var schema11 = { "properties": { "version": { "description": "\u5F62\u5F0F\u306E\u7248", "type": "integer", "minimum": 1 }, "kind": { "description": "\u56F3\u306E\u7A2E\u985E", "enum": ["sequence", "architecture", "state"] }, "title": { "$ref": "#/definitions/text" }, "view": { "description": "\u898B\u305B\u65B9\u3002\u66F8\u304B\u306A\u3051\u308C\u3070\u5B57\u306E\u5927\u304D\u3055\u3067\u9078\u3076\u3002fixed \u306F\u5168\u4F53\u3092\u6B62\u3081\u3066\u4E2D\u3060\u3051\u52D5\u304B\u3057\u3001follow \u306F\u5BC4\u3063\u3066\u52D5\u304B\u3057\u5168\u4F53\u56F3\u3067\u4ECA\u3069\u3053\u304B\u3092\u793A\u3059", "enum": ["fixed", "follow"] }, "regions": { "type": "array", "items": { "$ref": "#/definitions/region" } }, "boxes": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/box" } }, "strip": { "$ref": "#/definitions/strip" }, "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/step" } }, "sequence": { "$ref": "#/definitions/sequence" }, "state": { "$ref": "#/definitions/state" } }};
1075
1440
  var func2 = Object.prototype.hasOwnProperty;
1076
1441
  var func3 = ucs2length;
1077
1442
  var schema17 = { "enum": ["blue", "amber", "green", "violet", "rose", "slate", "coin"] };
@@ -2465,6 +2830,182 @@ function validate23(data, { instancePath = "", parentData, parentDataProperty, r
2465
2830
  validate23.errors = vErrors;
2466
2831
  return errors === 0;
2467
2832
  }
2833
+ function validate26(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2834
+ let vErrors = null;
2835
+ let errors = 0;
2836
+ if (data && typeof data == "object" && !Array.isArray(data)) {
2837
+ if (data.from === void 0) {
2838
+ const err0 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "from" }, message: "must have required property 'from'" };
2839
+ if (vErrors === null) {
2840
+ vErrors = [err0];
2841
+ } else {
2842
+ vErrors.push(err0);
2843
+ }
2844
+ errors++;
2845
+ }
2846
+ if (data.to === void 0) {
2847
+ const err1 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "to" }, message: "must have required property 'to'" };
2848
+ if (vErrors === null) {
2849
+ vErrors = [err1];
2850
+ } else {
2851
+ vErrors.push(err1);
2852
+ }
2853
+ errors++;
2854
+ }
2855
+ for (const key0 in data) {
2856
+ if (!(key0 === "from" || key0 === "to" || key0 === "label")) {
2857
+ const err2 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
2858
+ if (vErrors === null) {
2859
+ vErrors = [err2];
2860
+ } else {
2861
+ vErrors.push(err2);
2862
+ }
2863
+ errors++;
2864
+ }
2865
+ }
2866
+ if (data.from !== void 0) {
2867
+ let data0 = data.from;
2868
+ if (typeof data0 === "string") {
2869
+ if (!pattern0.test(data0)) {
2870
+ const err3 = { instancePath: instancePath + "/from", schemaPath: "#/definitions/id/pattern", keyword: "pattern", params: { pattern: "^[^\\s\\[\\]\u300C\u300D=:]+$" }, message: 'must match pattern "^[^\\s\\[\\]\u300C\u300D=:]+$"' };
2871
+ if (vErrors === null) {
2872
+ vErrors = [err3];
2873
+ } else {
2874
+ vErrors.push(err3);
2875
+ }
2876
+ errors++;
2877
+ }
2878
+ } else {
2879
+ const err4 = { instancePath: instancePath + "/from", schemaPath: "#/definitions/id/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2880
+ if (vErrors === null) {
2881
+ vErrors = [err4];
2882
+ } else {
2883
+ vErrors.push(err4);
2884
+ }
2885
+ errors++;
2886
+ }
2887
+ }
2888
+ if (data.to !== void 0) {
2889
+ let data1 = data.to;
2890
+ if (typeof data1 === "string") {
2891
+ if (!pattern0.test(data1)) {
2892
+ const err5 = { instancePath: instancePath + "/to", schemaPath: "#/definitions/id/pattern", keyword: "pattern", params: { pattern: "^[^\\s\\[\\]\u300C\u300D=:]+$" }, message: 'must match pattern "^[^\\s\\[\\]\u300C\u300D=:]+$"' };
2893
+ if (vErrors === null) {
2894
+ vErrors = [err5];
2895
+ } else {
2896
+ vErrors.push(err5);
2897
+ }
2898
+ errors++;
2899
+ }
2900
+ } else {
2901
+ const err6 = { instancePath: instancePath + "/to", schemaPath: "#/definitions/id/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2902
+ if (vErrors === null) {
2903
+ vErrors = [err6];
2904
+ } else {
2905
+ vErrors.push(err6);
2906
+ }
2907
+ errors++;
2908
+ }
2909
+ }
2910
+ if (data.label !== void 0) {
2911
+ let data2 = data.label;
2912
+ if (typeof data2 === "string") {
2913
+ if (func3(data2) < 1) {
2914
+ const err7 = { instancePath: instancePath + "/label", schemaPath: "#/definitions/text/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" };
2915
+ if (vErrors === null) {
2916
+ vErrors = [err7];
2917
+ } else {
2918
+ vErrors.push(err7);
2919
+ }
2920
+ errors++;
2921
+ }
2922
+ } else {
2923
+ const err8 = { instancePath: instancePath + "/label", schemaPath: "#/definitions/text/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2924
+ if (vErrors === null) {
2925
+ vErrors = [err8];
2926
+ } else {
2927
+ vErrors.push(err8);
2928
+ }
2929
+ errors++;
2930
+ }
2931
+ }
2932
+ } else {
2933
+ const err9 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
2934
+ if (vErrors === null) {
2935
+ vErrors = [err9];
2936
+ } else {
2937
+ vErrors.push(err9);
2938
+ }
2939
+ errors++;
2940
+ }
2941
+ validate26.errors = vErrors;
2942
+ return errors === 0;
2943
+ }
2944
+ function validate25(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2945
+ let vErrors = null;
2946
+ let errors = 0;
2947
+ if (data && typeof data == "object" && !Array.isArray(data)) {
2948
+ if (data.paths === void 0) {
2949
+ const err0 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "paths" }, message: "must have required property 'paths'" };
2950
+ if (vErrors === null) {
2951
+ vErrors = [err0];
2952
+ } else {
2953
+ vErrors.push(err0);
2954
+ }
2955
+ errors++;
2956
+ }
2957
+ for (const key0 in data) {
2958
+ if (!(key0 === "paths")) {
2959
+ const err1 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
2960
+ if (vErrors === null) {
2961
+ vErrors = [err1];
2962
+ } else {
2963
+ vErrors.push(err1);
2964
+ }
2965
+ errors++;
2966
+ }
2967
+ }
2968
+ if (data.paths !== void 0) {
2969
+ let data0 = data.paths;
2970
+ if (Array.isArray(data0)) {
2971
+ if (data0.length < 1) {
2972
+ const err2 = { instancePath: instancePath + "/paths", schemaPath: "#/properties/paths/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
2973
+ if (vErrors === null) {
2974
+ vErrors = [err2];
2975
+ } else {
2976
+ vErrors.push(err2);
2977
+ }
2978
+ errors++;
2979
+ }
2980
+ const len0 = data0.length;
2981
+ for (let i0 = 0; i0 < len0; i0++) {
2982
+ if (!validate26(data0[i0], { instancePath: instancePath + "/paths/" + i0, parentData: data0, parentDataProperty: i0, rootData })) {
2983
+ vErrors = vErrors === null ? validate26.errors : vErrors.concat(validate26.errors);
2984
+ errors = vErrors.length;
2985
+ }
2986
+ }
2987
+ } else {
2988
+ const err3 = { instancePath: instancePath + "/paths", schemaPath: "#/properties/paths/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2989
+ if (vErrors === null) {
2990
+ vErrors = [err3];
2991
+ } else {
2992
+ vErrors.push(err3);
2993
+ }
2994
+ errors++;
2995
+ }
2996
+ }
2997
+ } else {
2998
+ const err4 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
2999
+ if (vErrors === null) {
3000
+ vErrors = [err4];
3001
+ } else {
3002
+ vErrors.push(err4);
3003
+ }
3004
+ errors++;
3005
+ }
3006
+ validate25.errors = vErrors;
3007
+ return errors === 0;
3008
+ }
2468
3009
  function validate10(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2469
3010
  let vErrors = null;
2470
3011
  let errors = 0;
@@ -2506,9 +3047,11 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2506
3047
  let ifClause0;
2507
3048
  if (_valid0) {
2508
3049
  const _errs4 = errors;
3050
+ const _errs5 = errors;
3051
+ const _errs6 = errors;
2509
3052
  if (data && typeof data == "object" && !Array.isArray(data)) {
2510
- if (data.sequence === void 0) {
2511
- const err2 = { instancePath, schemaPath: "#/then/required", keyword: "required", params: { missingProperty: "sequence" }, message: "must have required property 'sequence'" };
3053
+ if (data.state === void 0 && ("state")) {
3054
+ const err2 = {};
2512
3055
  if (vErrors === null) {
2513
3056
  vErrors = [err2];
2514
3057
  } else {
@@ -2517,227 +3060,391 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2517
3060
  errors++;
2518
3061
  }
2519
3062
  }
3063
+ var valid2 = _errs6 === errors;
3064
+ if (valid2) {
3065
+ const err3 = { instancePath, schemaPath: "#/then/not", keyword: "not", params: {}, message: "must NOT be valid" };
3066
+ if (vErrors === null) {
3067
+ vErrors = [err3];
3068
+ } else {
3069
+ vErrors.push(err3);
3070
+ }
3071
+ errors++;
3072
+ } else {
3073
+ errors = _errs5;
3074
+ if (vErrors !== null) {
3075
+ if (_errs5) {
3076
+ vErrors.length = _errs5;
3077
+ } else {
3078
+ vErrors = null;
3079
+ }
3080
+ }
3081
+ }
3082
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3083
+ if (data.sequence === void 0) {
3084
+ const err4 = { instancePath, schemaPath: "#/then/required", keyword: "required", params: { missingProperty: "sequence" }, message: "must have required property 'sequence'" };
3085
+ if (vErrors === null) {
3086
+ vErrors = [err4];
3087
+ } else {
3088
+ vErrors.push(err4);
3089
+ }
3090
+ errors++;
3091
+ }
3092
+ }
2520
3093
  var _valid0 = _errs4 === errors;
2521
3094
  valid0 = _valid0;
2522
3095
  ifClause0 = "then";
2523
3096
  } else {
2524
- const _errs5 = errors;
2525
- const _errs6 = errors;
2526
3097
  const _errs7 = errors;
3098
+ const _errs8 = errors;
3099
+ const _errs9 = errors;
2527
3100
  if (data && typeof data == "object" && !Array.isArray(data)) {
2528
3101
  if (data.sequence === void 0 && ("sequence")) {
2529
- const err3 = {};
3102
+ const err5 = {};
2530
3103
  if (vErrors === null) {
2531
- vErrors = [err3];
3104
+ vErrors = [err5];
2532
3105
  } else {
2533
- vErrors.push(err3);
3106
+ vErrors.push(err5);
2534
3107
  }
2535
3108
  errors++;
2536
3109
  }
2537
3110
  }
2538
- var valid2 = _errs7 === errors;
2539
- if (valid2) {
2540
- const err4 = { instancePath, schemaPath: "#/else/not", keyword: "not", params: {}, message: "must NOT be valid" };
3111
+ var valid3 = _errs9 === errors;
3112
+ if (valid3) {
3113
+ const err6 = { instancePath, schemaPath: "#/else/not", keyword: "not", params: {}, message: "must NOT be valid" };
2541
3114
  if (vErrors === null) {
2542
- vErrors = [err4];
3115
+ vErrors = [err6];
2543
3116
  } else {
2544
- vErrors.push(err4);
3117
+ vErrors.push(err6);
2545
3118
  }
2546
3119
  errors++;
2547
3120
  } else {
2548
- errors = _errs6;
3121
+ errors = _errs8;
2549
3122
  if (vErrors !== null) {
2550
- if (_errs6) {
2551
- vErrors.length = _errs6;
3123
+ if (_errs8) {
3124
+ vErrors.length = _errs8;
2552
3125
  } else {
2553
3126
  vErrors = null;
2554
3127
  }
2555
3128
  }
2556
3129
  }
2557
- var _valid0 = _errs5 === errors;
3130
+ const _errs10 = errors;
3131
+ let valid4 = true;
3132
+ const _errs11 = errors;
3133
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3134
+ if (data.kind === void 0 && ("kind")) {
3135
+ const err7 = {};
3136
+ if (vErrors === null) {
3137
+ vErrors = [err7];
3138
+ } else {
3139
+ vErrors.push(err7);
3140
+ }
3141
+ errors++;
3142
+ } else {
3143
+ if (data.kind !== void 0) {
3144
+ if ("state" !== data.kind) {
3145
+ const err8 = {};
3146
+ if (vErrors === null) {
3147
+ vErrors = [err8];
3148
+ } else {
3149
+ vErrors.push(err8);
3150
+ }
3151
+ errors++;
3152
+ }
3153
+ }
3154
+ }
3155
+ }
3156
+ var _valid1 = _errs11 === errors;
3157
+ errors = _errs10;
3158
+ if (vErrors !== null) {
3159
+ if (_errs10) {
3160
+ vErrors.length = _errs10;
3161
+ } else {
3162
+ vErrors = null;
3163
+ }
3164
+ }
3165
+ let ifClause1;
3166
+ if (_valid1) {
3167
+ const _errs13 = errors;
3168
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3169
+ if (data.boxes !== void 0) {
3170
+ let data2 = data.boxes;
3171
+ if (Array.isArray(data2)) {
3172
+ const len0 = data2.length;
3173
+ for (let i0 = 0; i0 < len0; i0++) {
3174
+ let data3 = data2[i0];
3175
+ if (data3 && typeof data3 == "object" && !Array.isArray(data3)) {
3176
+ if (data3.id !== void 0) {
3177
+ let data4 = data3.id;
3178
+ const _errs17 = errors;
3179
+ const _errs18 = errors;
3180
+ if (!(data4 === "start" || data4 === "finish")) {
3181
+ const err9 = {};
3182
+ if (vErrors === null) {
3183
+ vErrors = [err9];
3184
+ } else {
3185
+ vErrors.push(err9);
3186
+ }
3187
+ errors++;
3188
+ }
3189
+ var valid10 = _errs18 === errors;
3190
+ if (valid10) {
3191
+ const err10 = { instancePath: instancePath + "/boxes/" + i0 + "/id", schemaPath: "#/else/then/properties/boxes/items/properties/id/not", keyword: "not", params: {}, message: "must NOT be valid" };
3192
+ if (vErrors === null) {
3193
+ vErrors = [err10];
3194
+ } else {
3195
+ vErrors.push(err10);
3196
+ }
3197
+ errors++;
3198
+ } else {
3199
+ errors = _errs17;
3200
+ if (vErrors !== null) {
3201
+ if (_errs17) {
3202
+ vErrors.length = _errs17;
3203
+ } else {
3204
+ vErrors = null;
3205
+ }
3206
+ }
3207
+ }
3208
+ }
3209
+ }
3210
+ }
3211
+ }
3212
+ }
3213
+ }
3214
+ var _valid1 = _errs13 === errors;
3215
+ valid4 = _valid1;
3216
+ ifClause1 = "then";
3217
+ } else {
3218
+ const _errs19 = errors;
3219
+ const _errs20 = errors;
3220
+ const _errs21 = errors;
3221
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3222
+ if (data.state === void 0 && ("state")) {
3223
+ const err11 = {};
3224
+ if (vErrors === null) {
3225
+ vErrors = [err11];
3226
+ } else {
3227
+ vErrors.push(err11);
3228
+ }
3229
+ errors++;
3230
+ }
3231
+ }
3232
+ var valid11 = _errs21 === errors;
3233
+ if (valid11) {
3234
+ const err12 = { instancePath, schemaPath: "#/else/else/not", keyword: "not", params: {}, message: "must NOT be valid" };
3235
+ if (vErrors === null) {
3236
+ vErrors = [err12];
3237
+ } else {
3238
+ vErrors.push(err12);
3239
+ }
3240
+ errors++;
3241
+ } else {
3242
+ errors = _errs20;
3243
+ if (vErrors !== null) {
3244
+ if (_errs20) {
3245
+ vErrors.length = _errs20;
3246
+ } else {
3247
+ vErrors = null;
3248
+ }
3249
+ }
3250
+ }
3251
+ var _valid1 = _errs19 === errors;
3252
+ valid4 = _valid1;
3253
+ ifClause1 = "else";
3254
+ }
3255
+ if (!valid4) {
3256
+ const err13 = { instancePath, schemaPath: "#/else/if", keyword: "if", params: { failingKeyword: ifClause1 }, message: 'must match "' + ifClause1 + '" schema' };
3257
+ if (vErrors === null) {
3258
+ vErrors = [err13];
3259
+ } else {
3260
+ vErrors.push(err13);
3261
+ }
3262
+ errors++;
3263
+ }
3264
+ var _valid0 = _errs7 === errors;
2558
3265
  valid0 = _valid0;
2559
3266
  ifClause0 = "else";
2560
3267
  }
2561
3268
  if (!valid0) {
2562
- const err5 = { instancePath, schemaPath: "#/if", keyword: "if", params: { failingKeyword: ifClause0 }, message: 'must match "' + ifClause0 + '" schema' };
3269
+ const err14 = { instancePath, schemaPath: "#/if", keyword: "if", params: { failingKeyword: ifClause0 }, message: 'must match "' + ifClause0 + '" schema' };
2563
3270
  if (vErrors === null) {
2564
- vErrors = [err5];
3271
+ vErrors = [err14];
2565
3272
  } else {
2566
- vErrors.push(err5);
3273
+ vErrors.push(err14);
2567
3274
  }
2568
3275
  errors++;
2569
3276
  }
2570
3277
  if (data && typeof data == "object" && !Array.isArray(data)) {
2571
3278
  if (data.version === void 0) {
2572
- const err6 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "version" }, message: "must have required property 'version'" };
3279
+ const err15 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "version" }, message: "must have required property 'version'" };
2573
3280
  if (vErrors === null) {
2574
- vErrors = [err6];
3281
+ vErrors = [err15];
2575
3282
  } else {
2576
- vErrors.push(err6);
3283
+ vErrors.push(err15);
2577
3284
  }
2578
3285
  errors++;
2579
3286
  }
2580
3287
  if (data.kind === void 0) {
2581
- const err7 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "kind" }, message: "must have required property 'kind'" };
3288
+ const err16 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "kind" }, message: "must have required property 'kind'" };
2582
3289
  if (vErrors === null) {
2583
- vErrors = [err7];
3290
+ vErrors = [err16];
2584
3291
  } else {
2585
- vErrors.push(err7);
3292
+ vErrors.push(err16);
2586
3293
  }
2587
3294
  errors++;
2588
3295
  }
2589
3296
  if (data.title === void 0) {
2590
- const err8 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "title" }, message: "must have required property 'title'" };
3297
+ const err17 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "title" }, message: "must have required property 'title'" };
2591
3298
  if (vErrors === null) {
2592
- vErrors = [err8];
3299
+ vErrors = [err17];
2593
3300
  } else {
2594
- vErrors.push(err8);
3301
+ vErrors.push(err17);
2595
3302
  }
2596
3303
  errors++;
2597
3304
  }
2598
3305
  if (data.boxes === void 0) {
2599
- const err9 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "boxes" }, message: "must have required property 'boxes'" };
3306
+ const err18 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "boxes" }, message: "must have required property 'boxes'" };
2600
3307
  if (vErrors === null) {
2601
- vErrors = [err9];
3308
+ vErrors = [err18];
2602
3309
  } else {
2603
- vErrors.push(err9);
3310
+ vErrors.push(err18);
2604
3311
  }
2605
3312
  errors++;
2606
3313
  }
2607
3314
  if (data.steps === void 0) {
2608
- const err10 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "steps" }, message: "must have required property 'steps'" };
3315
+ const err19 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "steps" }, message: "must have required property 'steps'" };
2609
3316
  if (vErrors === null) {
2610
- vErrors = [err10];
3317
+ vErrors = [err19];
2611
3318
  } else {
2612
- vErrors.push(err10);
3319
+ vErrors.push(err19);
2613
3320
  }
2614
3321
  errors++;
2615
3322
  }
2616
3323
  for (const key0 in data) {
2617
3324
  if (!func2.call(schema11.properties, key0)) {
2618
- const err11 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
3325
+ const err20 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
2619
3326
  if (vErrors === null) {
2620
- vErrors = [err11];
3327
+ vErrors = [err20];
2621
3328
  } else {
2622
- vErrors.push(err11);
3329
+ vErrors.push(err20);
2623
3330
  }
2624
3331
  errors++;
2625
3332
  }
2626
3333
  }
2627
3334
  if (data.version !== void 0) {
2628
- let data1 = data.version;
2629
- if (!(typeof data1 == "number" && (!(data1 % 1) && !isNaN(data1)) && isFinite(data1))) {
2630
- const err12 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/type", keyword: "type", params: { type: "integer" }, message: "must be integer" };
3335
+ let data5 = data.version;
3336
+ if (!(typeof data5 == "number" && (!(data5 % 1) && !isNaN(data5)) && isFinite(data5))) {
3337
+ const err21 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/type", keyword: "type", params: { type: "integer" }, message: "must be integer" };
2631
3338
  if (vErrors === null) {
2632
- vErrors = [err12];
3339
+ vErrors = [err21];
2633
3340
  } else {
2634
- vErrors.push(err12);
3341
+ vErrors.push(err21);
2635
3342
  }
2636
3343
  errors++;
2637
3344
  }
2638
- if (typeof data1 == "number" && isFinite(data1)) {
2639
- if (data1 < 1 || isNaN(data1)) {
2640
- const err13 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/minimum", keyword: "minimum", params: { comparison: ">=", limit: 1 }, message: "must be >= 1" };
3345
+ if (typeof data5 == "number" && isFinite(data5)) {
3346
+ if (data5 < 1 || isNaN(data5)) {
3347
+ const err22 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/minimum", keyword: "minimum", params: { comparison: ">=", limit: 1 }, message: "must be >= 1" };
2641
3348
  if (vErrors === null) {
2642
- vErrors = [err13];
3349
+ vErrors = [err22];
2643
3350
  } else {
2644
- vErrors.push(err13);
3351
+ vErrors.push(err22);
2645
3352
  }
2646
3353
  errors++;
2647
3354
  }
2648
3355
  }
2649
3356
  }
2650
3357
  if (data.kind !== void 0) {
2651
- let data2 = data.kind;
2652
- if (!(data2 === "sequence" || data2 === "architecture")) {
2653
- const err14 = { instancePath: instancePath + "/kind", schemaPath: "#/properties/kind/enum", keyword: "enum", params: { allowedValues: schema11.properties.kind.enum }, message: "must be equal to one of the allowed values" };
3358
+ let data6 = data.kind;
3359
+ if (!(data6 === "sequence" || data6 === "architecture" || data6 === "state")) {
3360
+ const err23 = { instancePath: instancePath + "/kind", schemaPath: "#/properties/kind/enum", keyword: "enum", params: { allowedValues: schema11.properties.kind.enum }, message: "must be equal to one of the allowed values" };
2654
3361
  if (vErrors === null) {
2655
- vErrors = [err14];
3362
+ vErrors = [err23];
2656
3363
  } else {
2657
- vErrors.push(err14);
3364
+ vErrors.push(err23);
2658
3365
  }
2659
3366
  errors++;
2660
3367
  }
2661
3368
  }
2662
3369
  if (data.title !== void 0) {
2663
- let data3 = data.title;
2664
- if (typeof data3 === "string") {
2665
- if (func3(data3) < 1) {
2666
- const err15 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" };
3370
+ let data7 = data.title;
3371
+ if (typeof data7 === "string") {
3372
+ if (func3(data7) < 1) {
3373
+ const err24 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" };
2667
3374
  if (vErrors === null) {
2668
- vErrors = [err15];
3375
+ vErrors = [err24];
2669
3376
  } else {
2670
- vErrors.push(err15);
3377
+ vErrors.push(err24);
2671
3378
  }
2672
3379
  errors++;
2673
3380
  }
2674
3381
  } else {
2675
- const err16 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/type", keyword: "type", params: { type: "string" }, message: "must be string" };
3382
+ const err25 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2676
3383
  if (vErrors === null) {
2677
- vErrors = [err16];
3384
+ vErrors = [err25];
2678
3385
  } else {
2679
- vErrors.push(err16);
3386
+ vErrors.push(err25);
2680
3387
  }
2681
3388
  errors++;
2682
3389
  }
2683
3390
  }
2684
3391
  if (data.view !== void 0) {
2685
- let data4 = data.view;
2686
- if (!(data4 === "fixed" || data4 === "follow")) {
2687
- const err17 = { instancePath: instancePath + "/view", schemaPath: "#/properties/view/enum", keyword: "enum", params: { allowedValues: schema11.properties.view.enum }, message: "must be equal to one of the allowed values" };
3392
+ let data8 = data.view;
3393
+ if (!(data8 === "fixed" || data8 === "follow")) {
3394
+ const err26 = { instancePath: instancePath + "/view", schemaPath: "#/properties/view/enum", keyword: "enum", params: { allowedValues: schema11.properties.view.enum }, message: "must be equal to one of the allowed values" };
2688
3395
  if (vErrors === null) {
2689
- vErrors = [err17];
3396
+ vErrors = [err26];
2690
3397
  } else {
2691
- vErrors.push(err17);
3398
+ vErrors.push(err26);
2692
3399
  }
2693
3400
  errors++;
2694
3401
  }
2695
3402
  }
2696
3403
  if (data.regions !== void 0) {
2697
- let data5 = data.regions;
2698
- if (Array.isArray(data5)) {
2699
- const len0 = data5.length;
2700
- for (let i0 = 0; i0 < len0; i0++) {
2701
- if (!validate11(data5[i0], { instancePath: instancePath + "/regions/" + i0, parentData: data5, parentDataProperty: i0, rootData })) {
3404
+ let data9 = data.regions;
3405
+ if (Array.isArray(data9)) {
3406
+ const len1 = data9.length;
3407
+ for (let i1 = 0; i1 < len1; i1++) {
3408
+ if (!validate11(data9[i1], { instancePath: instancePath + "/regions/" + i1, parentData: data9, parentDataProperty: i1, rootData })) {
2702
3409
  vErrors = vErrors === null ? validate11.errors : vErrors.concat(validate11.errors);
2703
3410
  errors = vErrors.length;
2704
3411
  }
2705
3412
  }
2706
3413
  } else {
2707
- const err18 = { instancePath: instancePath + "/regions", schemaPath: "#/properties/regions/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3414
+ const err27 = { instancePath: instancePath + "/regions", schemaPath: "#/properties/regions/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2708
3415
  if (vErrors === null) {
2709
- vErrors = [err18];
3416
+ vErrors = [err27];
2710
3417
  } else {
2711
- vErrors.push(err18);
3418
+ vErrors.push(err27);
2712
3419
  }
2713
3420
  errors++;
2714
3421
  }
2715
3422
  }
2716
3423
  if (data.boxes !== void 0) {
2717
- let data7 = data.boxes;
2718
- if (Array.isArray(data7)) {
2719
- if (data7.length < 1) {
2720
- const err19 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
3424
+ let data11 = data.boxes;
3425
+ if (Array.isArray(data11)) {
3426
+ if (data11.length < 1) {
3427
+ const err28 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
2721
3428
  if (vErrors === null) {
2722
- vErrors = [err19];
3429
+ vErrors = [err28];
2723
3430
  } else {
2724
- vErrors.push(err19);
3431
+ vErrors.push(err28);
2725
3432
  }
2726
3433
  errors++;
2727
3434
  }
2728
- const len1 = data7.length;
2729
- for (let i1 = 0; i1 < len1; i1++) {
2730
- if (!validate13(data7[i1], { instancePath: instancePath + "/boxes/" + i1, parentData: data7, parentDataProperty: i1, rootData })) {
3435
+ const len2 = data11.length;
3436
+ for (let i2 = 0; i2 < len2; i2++) {
3437
+ if (!validate13(data11[i2], { instancePath: instancePath + "/boxes/" + i2, parentData: data11, parentDataProperty: i2, rootData })) {
2731
3438
  vErrors = vErrors === null ? validate13.errors : vErrors.concat(validate13.errors);
2732
3439
  errors = vErrors.length;
2733
3440
  }
2734
3441
  }
2735
3442
  } else {
2736
- const err20 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3443
+ const err29 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2737
3444
  if (vErrors === null) {
2738
- vErrors = [err20];
3445
+ vErrors = [err29];
2739
3446
  } else {
2740
- vErrors.push(err20);
3447
+ vErrors.push(err29);
2741
3448
  }
2742
3449
  errors++;
2743
3450
  }
@@ -2749,30 +3456,30 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2749
3456
  }
2750
3457
  }
2751
3458
  if (data.steps !== void 0) {
2752
- let data10 = data.steps;
2753
- if (Array.isArray(data10)) {
2754
- if (data10.length < 1) {
2755
- const err21 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
3459
+ let data14 = data.steps;
3460
+ if (Array.isArray(data14)) {
3461
+ if (data14.length < 1) {
3462
+ const err30 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
2756
3463
  if (vErrors === null) {
2757
- vErrors = [err21];
3464
+ vErrors = [err30];
2758
3465
  } else {
2759
- vErrors.push(err21);
3466
+ vErrors.push(err30);
2760
3467
  }
2761
3468
  errors++;
2762
3469
  }
2763
- const len2 = data10.length;
2764
- for (let i2 = 0; i2 < len2; i2++) {
2765
- if (!validate17(data10[i2], { instancePath: instancePath + "/steps/" + i2, parentData: data10, parentDataProperty: i2, rootData })) {
3470
+ const len3 = data14.length;
3471
+ for (let i3 = 0; i3 < len3; i3++) {
3472
+ if (!validate17(data14[i3], { instancePath: instancePath + "/steps/" + i3, parentData: data14, parentDataProperty: i3, rootData })) {
2766
3473
  vErrors = vErrors === null ? validate17.errors : vErrors.concat(validate17.errors);
2767
3474
  errors = vErrors.length;
2768
3475
  }
2769
3476
  }
2770
3477
  } else {
2771
- const err22 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3478
+ const err31 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2772
3479
  if (vErrors === null) {
2773
- vErrors = [err22];
3480
+ vErrors = [err31];
2774
3481
  } else {
2775
- vErrors.push(err22);
3482
+ vErrors.push(err31);
2776
3483
  }
2777
3484
  errors++;
2778
3485
  }
@@ -2783,12 +3490,18 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2783
3490
  errors = vErrors.length;
2784
3491
  }
2785
3492
  }
3493
+ if (data.state !== void 0) {
3494
+ if (!validate25(data.state, { instancePath: instancePath + "/state", parentData: data, parentDataProperty: "state", rootData })) {
3495
+ vErrors = vErrors === null ? validate25.errors : vErrors.concat(validate25.errors);
3496
+ errors = vErrors.length;
3497
+ }
3498
+ }
2786
3499
  } else {
2787
- const err23 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
3500
+ const err32 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
2788
3501
  if (vErrors === null) {
2789
- vErrors = [err23];
3502
+ vErrors = [err32];
2790
3503
  } else {
2791
- vErrors.push(err23);
3504
+ vErrors.push(err32);
2792
3505
  }
2793
3506
  errors++;
2794
3507
  }
@@ -2798,10 +3511,15 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2798
3511
 
2799
3512
  // src/schema.ts
2800
3513
  var EVENT_TYPES = ["edge", "action", "swap", "strip"];
3514
+ var ROOT_NOT_ALLOWED = {
3515
+ "#/else/not": { field: "sequence", kind: "sequence" },
3516
+ "#/then/not": { field: "state", kind: "state" },
3517
+ "#/else/else/not": { field: "state", kind: "state" }
3518
+ };
2801
3519
  var NOT_ALLOWED = {
2802
- "": { field: "sequence", kind: "sequence" },
2803
3520
  carry: { field: "text", kind: "tag" }
2804
3521
  };
3522
+ var RESERVED_ID = /\/boxes\/items\/properties\/id\/not$/u;
2805
3523
  var escape = (key) => key.replaceAll("~", "~0").replaceAll("/", "~1");
2806
3524
  function forbiddenOf(pattern) {
2807
3525
  const inside = /^\^\[\^(.+)\]\+\$$/u.exec(pattern)?.[1];
@@ -2825,7 +3543,8 @@ function toFieldError(error, errors, m) {
2825
3543
  return { pointer: `${at2}/${escape(key)}`, message: m.required(key) };
2826
3544
  }
2827
3545
  case "not": {
2828
- const allowed = NOT_ALLOWED[at2.slice(at2.lastIndexOf("/") + 1)];
3546
+ if (RESERVED_ID.test(error.schemaPath)) return { pointer: at2, message: m.reserved(STATE_ENDS) };
3547
+ const allowed = at2 === "" ? ROOT_NOT_ALLOWED[error.schemaPath] : NOT_ALLOWED[at2.slice(at2.lastIndexOf("/") + 1)];
2829
3548
  return { pointer: allowed ? `${at2}/${allowed.field}` : at2, message: m.not(allowed) };
2830
3549
  }
2831
3550
  case "anyOf": {
@@ -2944,6 +3663,7 @@ function buildTimeline(diagram) {
2944
3663
  const later = named[k + 2];
2945
3664
  if (later) label2.end = Math.min(label2.end, later.start);
2946
3665
  });
3666
+ if (diagram.kind === "state") for (const label2 of named) label2.after = { start: label2.end, end: last };
2947
3667
  labels.push(...named);
2948
3668
  for (const event of p.events) events.push({ step: s, event: event.event, at: span.start + event.at });
2949
3669
  });
@@ -2967,6 +3687,7 @@ function buildTimeline(diagram) {
2967
3687
  });
2968
3688
  }
2969
3689
  carriers.sort((x, y) => x.depart - y.depart);
3690
+ const states = diagram.kind === "state" ? stateTimes(diagram, edges, last) : void 0;
2970
3691
  return {
2971
3692
  total,
2972
3693
  last,
@@ -2976,8 +3697,32 @@ function buildTimeline(diagram) {
2976
3697
  labels,
2977
3698
  badges: steps.map((span, s) => ({ step: s, appears: span.start })),
2978
3699
  events,
2979
- stills: steps.map((span) => span.end - MOTION.still)
3700
+ stills: steps.map((span) => span.end - MOTION.still),
3701
+ ...states ? { states } : {}
3702
+ };
3703
+ }
3704
+ var isEnd2 = (id) => STATE_ENDS.includes(id);
3705
+ function stateTimes(diagram, edges, last) {
3706
+ const times = /* @__PURE__ */ new Map();
3707
+ const of = (box) => {
3708
+ const found = times.get(box) ?? { box, lit: [] };
3709
+ times.set(box, found);
3710
+ return found;
2980
3711
  };
3712
+ let on;
3713
+ for (const edge2 of edges) {
3714
+ const event = diagram.steps[edge2.step]?.events[edge2.event];
3715
+ if (event?.type !== "edge" || event.from === event.to) continue;
3716
+ if (on) {
3717
+ const left = of(on.box);
3718
+ left.lit.push({ start: on.since, end: edge2.start });
3719
+ if (on.box === event.from && left.done === void 0) left.done = edge2.start + MOTION.done;
3720
+ on = void 0;
3721
+ }
3722
+ if (!isEnd2(event.to)) on = { box: event.to, since: edge2.drawn };
3723
+ }
3724
+ if (on) of(on.box).lit.push({ start: on.since, end: last });
3725
+ return [...times.values()];
2981
3726
  }
2982
3727
 
2983
3728
  // src/render/icons.ts
@@ -3012,6 +3757,8 @@ var ICONS = {
3012
3757
  branch: "M -4 -4.5 v9 M 5 0.5 c0 4 -9 3 -9 6.5 M -6.2 -7 a2.2 2.2 0 1 0 4.4 0 a2.2 2.2 0 1 0 -4.4 0 M -6.2 7 a2.2 2.2 0 1 0 4.4 0 a2.2 2.2 0 1 0 -4.4 0 M 2.8 -2 a2.2 2.2 0 1 0 4.4 0 a2.2 2.2 0 1 0 -4.4 0",
3013
3758
  cloud: "M -7 6 h13 a4.5 4.5 0 0 0 0.5 -9 a6 6 0 0 0 -11.5 -1 a4.5 4.5 0 0 0 -2 10 z",
3014
3759
  refresh: "M 7 -3 a7.5 7.5 0 1 0 0.5 5 M 7.5 -8 v5 h-5",
3760
+ undo: "M -7 -2 h10 a5 5 0 0 1 0 10 h-6 M -3 -6 l-4 4 l4 4",
3761
+ yen: "M -6 -8 l6 7 l6 -7 M 0 -1 v9 M -5 1.5 h10 M -5 5 h10",
3015
3762
  layers: "M 0 -8 l9 4.5 l-9 4.5 l-9 -4.5 z M -9 2.5 l9 4.5 l9 -4.5",
3016
3763
  code: "M -4 -6 l-5 6 l5 6 M 4 -6 l5 6 l-5 6",
3017
3764
  paint: "M -8 8 c 0 -3 2 -5 4.5 -5 l 9 -9 l 3.5 3.5 l -9 9 c 0 2.5 -2 4.5 -5 4.5 z",
@@ -3026,7 +3773,25 @@ function glyph(name, x, y, scale, cls = "dg-gl") {
3026
3773
  const d = name === void 0 ? void 0 : ICONS[name];
3027
3774
  return d ? `<path class="${cls}" transform="translate(${r1(x)} ${r1(y)}) scale(${scale})" d="${d}"/>` : "";
3028
3775
  }
3029
- var pathOf = (points) => points.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${r1(x)} ${r1(y)}`).join(" ");
3776
+ function pathOf(points) {
3777
+ const pts = points.filter((p, i) => i === 0 || p[0] !== points[i - 1][0] || p[1] !== points[i - 1][1]);
3778
+ const [x0, y0] = pts[0];
3779
+ let d = `M ${r1(x0)} ${r1(y0)}`;
3780
+ for (let i = 1; i < pts.length - 1; i++) {
3781
+ const [ax, ay] = pts[i - 1];
3782
+ const [bx, by] = pts[i];
3783
+ const [cx, cy] = pts[i + 1];
3784
+ const l1 = Math.hypot(bx - ax, by - ay);
3785
+ const l2 = Math.hypot(cx - bx, cy - by);
3786
+ const a = Math.min(LOOK.edge.bend, l1 / 2, l2 / 2);
3787
+ d += ` L ${r1(bx - (bx - ax) / l1 * a)} ${r1(by - (by - ay) / l1 * a)} Q ${r1(bx)} ${r1(by)} ${r1(bx + (cx - bx) / l2 * a)} ${r1(by + (cy - by) / l2 * a)}`;
3788
+ }
3789
+ if (pts.length > 1) {
3790
+ const [lx, ly] = pts[pts.length - 1];
3791
+ d += ` L ${r1(lx)} ${r1(ly)}`;
3792
+ }
3793
+ return d;
3794
+ }
3030
3795
  function arrowHead(points) {
3031
3796
  const [ex, ey] = points[points.length - 1];
3032
3797
  const [px, py] = points[points.length - 2];
@@ -3073,10 +3838,10 @@ function cardFrame(box, ctx, act, y, h) {
3073
3838
  const rect = (cls, extra = "") => `<rect class="${cls}" x="${r1(box.x)}" y="${r1(y)}" width="${r1(box.w)}" height="${h}" rx="${LOOK.box.radius}"${extra}/>`;
3074
3839
  return `${act ? `<g class="dg-a" style="${act}">${rect("dg-halo")}</g>` : ""}${rect("dg-st", ` ${ctx.sh}`)}${act ? `<g class="dg-a" style="${act}">${rect("dg-on")}</g>` : ""}`;
3075
3840
  }
3076
- function card(box, ctx, on, changes) {
3841
+ function card(box, ctx, on, changes, lit) {
3077
3842
  const { icon, iconRadius, iconScale, iconY, nameY, subY } = LOOK.box;
3078
3843
  const subs = subLines(box, ctx.m, changes, box.cy + subY);
3079
- const act = on.length > 0 ? activeKf(ctx, on) : void 0;
3844
+ const act = lit ? lit.length > 0 ? rangeKf(ctx.m, lit.map((s) => [s.start, s.end])) : void 0 : on.length > 0 ? activeKf(ctx, on) : void 0;
3080
3845
  const mark = box.icon && ICONS[box.icon] ? `<rect class="dg-ic" x="${r1(box.cx - icon / 2)}" y="${r1(box.cy + iconY - icon / 2)}" width="${icon}" height="${icon}" rx="${iconRadius}"/>${glyph(box.icon, box.cx, box.cy + iconY, iconScale)}` : "";
3081
3846
  return `<g style="${cs(box.color)}">${cardFrame(box, ctx, act, box.y, box.h)}${mark}<text class="dg-sn" x="${r1(box.cx)}" y="${r1(box.cy + nameY)}" text-anchor="middle">${esc(box.name)}</text>${subs}</g>`;
3082
3847
  }
@@ -3086,15 +3851,54 @@ function headCard(box, ctx, on, changes) {
3086
3851
  const act = on.length > 0 ? activeKf(ctx, on) : void 0;
3087
3852
  return `<g style="${cs(box.color)}">${cardFrame(box, ctx, act, pad2, h)}<text class="dg-sn" x="${r1(box.cx)}" y="${r1(pad2 + nameY)}" text-anchor="middle">${esc(box.name)}</text>${subs}</g>`;
3088
3853
  }
3854
+ function ghostCard(box) {
3855
+ const { icon, iconRadius, iconScale, radius } = LOOK.box;
3856
+ const G = LOOK.state.ghost;
3857
+ const ix = box.x + G.pad + icon / 2;
3858
+ const tx = box.x + G.pad + icon + G.gap;
3859
+ const mark = box.icon && ICONS[box.icon] ? `<rect class="dg-ic" x="${r1(ix - icon / 2)}" y="${r1(box.cy - icon / 2)}" width="${icon}" height="${icon}" rx="${iconRadius}"/>${glyph(box.icon, ix, box.cy, iconScale)}` : "";
3860
+ const nameY = box.sub ? G.nameY : LOOK.baseline.mark;
3861
+ const sub = box.sub ? `<text class="dg-ss" x="${r1(tx)}" y="${r1(box.cy + G.subY)}" text-anchor="start">${esc(box.sub)}</text>` : "";
3862
+ return `<g data-ghost="${esc(box.id)}" style="${cs(box.color)}"><rect class="dg-ghost" x="${r1(box.x)}" y="${r1(box.y)}" width="${r1(box.w)}" height="${box.h}" rx="${radius}"/>${mark}<text class="dg-sn" x="${r1(tx)}" y="${r1(box.cy + nameY)}" text-anchor="start">${esc(box.name)}</text>${sub}</g>`;
3863
+ }
3864
+ function doneMark(box, at2, ctx) {
3865
+ const { r, inset } = LOOK.state.done;
3866
+ const x = box.x + box.w - inset;
3867
+ const y = box.y + inset;
3868
+ return `<g class="dg-popc dg-a" data-done="${esc(box.id)}" style="${cs(box.color)};${ctx.m.pop(at2)}"><circle class="dg-done" cx="${r1(x)}" cy="${r1(y)}" r="${r}"/>${glyph("check", x, y, 0.5, "dg-done-ck")}</g>`;
3869
+ }
3870
+ function path(p, color) {
3871
+ const label2 = p.label ? `<text class="dg-path-t${p.label.family === "sans" ? " dg-path-tj" : ""}" x="${r1(p.label.x + LOOK.label.padX)}" y="${r1(p.label.y + p.label.h / 2 + LOOK.baseline.label)}">${esc(p.label.text)}</text>` : "";
3872
+ return `<g data-path="${esc(`${p.from}->${p.to}`)}" style="${cs(color)}"><path class="dg-path" d="${pathOf(p.points)}"/><path class="dg-path-h" d="${arrowHead(p.points)}"/>${label2}</g>`;
3873
+ }
3874
+ function side(s, color) {
3875
+ const { pad: pad2 } = LOOK.state.side;
3876
+ const title = s.y + pad2 + TYPE.regionName.size;
3877
+ const notes = s.notes.map((note, k) => `<text class="dg-side-n" x="${r1(s.x + pad2)}" y="${r1(title + LOOK.region.line * (k + 1))}">${esc(note)}</text>`).join("");
3878
+ return `<g style="${cs(color)}"><rect class="dg-side" x="${r1(s.x + 0.5)}" y="${r1(s.y + 0.5)}" width="${r1(s.w - 1)}" height="${r1(s.h - 1)}" rx="${LOOK.region.radius}"/><text class="dg-side-t" x="${r1(s.x + pad2)}" y="${r1(title)}">${esc(s.title)}</text>${notes}</g>`;
3879
+ }
3880
+ function endMark(e, color) {
3881
+ const { end } = LOOK.state;
3882
+ const text2 = e.text === "" ? "" : `<text class="dg-mark" x="${r1(e.x + LOOK.state.text)}" y="${r1(e.y + LOOK.baseline.mark)}">${esc(e.text)}</text>`;
3883
+ const x = r1(e.x);
3884
+ const y = r1(e.y);
3885
+ if (e.kind === "start") return `<g data-end="start"><circle class="dg-start" cx="${x}" cy="${y}" r="${e.r}"/>${text2}</g>`;
3886
+ if (e.ghost) return `<g data-end="finish" style="${cs(color)}"><circle class="dg-end-x" cx="${x}" cy="${y}" r="${e.r}"/><circle class="dg-end-xi" cx="${x}" cy="${y}" r="${end.inner}"/>${text2}</g>`;
3887
+ return `<g data-end="finish"><circle class="dg-end" cx="${x}" cy="${y}" r="${e.r}"/><circle class="dg-end-in" cx="${x}" cy="${y}" r="${end.inner}"/>${text2}</g>`;
3888
+ }
3089
3889
  function lifeline(x, y1, y2) {
3090
3890
  return `<line class="dg-ll" x1="${r1(x)}" y1="${r1(y1)}" x2="${r1(x)}" y2="${r1(y2)}"/>`;
3091
3891
  }
3092
- function edge(e, time, ctx) {
3892
+ function edge(e, time, ctx, past = false) {
3093
3893
  const { m } = ctx;
3094
3894
  const d = pathOf(e.points);
3095
3895
  const head = arrowHead(e.points);
3096
3896
  const { start: a, drawn: b, end } = time;
3097
- const tail = [
3897
+ const tail = past ? [
3898
+ [end, { opacity: 1 }, EASE.inOut],
3899
+ [end + 0.4, { opacity: 0 }],
3900
+ [m.total, { opacity: 0 }]
3901
+ ] : [
3098
3902
  [end, { opacity: 1 }, EASE.inOut],
3099
3903
  [end + 0.4, { opacity: 0.45 }],
3100
3904
  [ctx.end + 0.3, { opacity: 0.45 }, EASE.inOut],
@@ -3121,15 +3925,19 @@ function edge(e, time, ctx) {
3121
3925
  [end + 0.2, { opacity: 0, "stroke-dashoffset": run }],
3122
3926
  [m.total, { opacity: 0, "stroke-dashoffset": run }]
3123
3927
  ]);
3928
+ const grey = past ? m.kf([[0, { opacity: 0 }], [end, { opacity: 0 }, EASE.inOut], [end + 0.4, { opacity: 1 }], [m.last, { opacity: 1 }, EASE.inOut], [m.total, { opacity: 0 }]]) : "";
3124
3929
  return {
3125
- base: `<path class="dg-e" d="${d}"/><path class="dg-eh" d="${head}"/>`,
3930
+ base: `<path class="dg-e" d="${d}"/><path class="dg-eh" d="${head}"/>${past ? `<path class="dg-e-past dg-a" d="${d}" style="${grey}"/><path class="dg-eh-past dg-a" d="${head}" style="${grey}"/>` : ""}`,
3126
3931
  lit: `<g style="${cs(e.color)}"><path class="dg-e-on dg-a" pathLength="1" d="${d}" style="${line}"/><path class="dg-eh-on dg-a" d="${head}" style="${hk}"/><path class="dg-flow dg-a" d="${d}" style="${flow}"/></g>`
3127
3932
  };
3128
3933
  }
3129
3934
  function label(l, time, ctx) {
3130
3935
  const ja2 = l.family === "sans" ? " dg-capj" : "";
3131
3936
  const { radius } = LOOK.label;
3132
- return `<g class="dg-cap${ja2} dg-a" style="${cs(l.color)};${ctx.m.rise(time.start, time.end, true)}"><rect x="${r1(l.x)}" y="${r1(l.y)}" width="${r1(l.w)}" height="${l.h}" rx="${radius}"/><text x="${r1(l.x + l.w / 2)}" y="${r1(l.y + l.h / 2 + LOOK.baseline.label)}" text-anchor="middle">${esc(l.text)}</text></g>`;
3937
+ const x = r1(l.x + l.w / 2);
3938
+ const y = r1(l.y + l.h / 2 + LOOK.baseline.label);
3939
+ const past = time.after ? `<g class="dg-cap-past${l.family === "sans" ? " dg-cap-pastj" : ""} dg-a" style="${ctx.m.vis(time.after.start, time.after.end)}"><text x="${x}" y="${y}" text-anchor="middle">${esc(l.text)}</text></g>` : "";
3940
+ return `${past}<g class="dg-cap${ja2} dg-a" style="${cs(l.color)};${ctx.m.rise(time.start, time.end, true)}"><rect x="${r1(l.x)}" y="${r1(l.y)}" width="${r1(l.w)}" height="${l.h}" rx="${radius}"/><text x="${x}" y="${y}" text-anchor="middle">${esc(l.text)}</text></g>`;
3133
3941
  }
3134
3942
  function action(a, at2, until, ctx) {
3135
3943
  return `<g class="dg-act dg-a" style="${cs(a.color)};${ctx.m.rise(at2, until, true)}"><rect x="${r1(a.x)}" y="${r1(a.y)}" width="${r1(a.w)}" height="${a.h}" rx="${LOOK.action.radius}"/><text x="${r1(a.x + a.w / 2)}" y="${r1(a.y + a.h / 2 + LOOK.baseline.action)}" text-anchor="middle">${esc(a.text)}</text></g>`;
@@ -3151,21 +3959,21 @@ function carrier(e, time, ctx) {
3151
3959
  const n = LOOK.carrier.samples;
3152
3960
  const length = pathLength(e.points);
3153
3961
  const { depart: a, arrive: b, start: from, end: gone } = time;
3154
- const path = [];
3962
+ const path2 = [];
3155
3963
  for (let k = 0; k <= n; k++) {
3156
3964
  const [x, y] = along(e.points, easeInOut(k / n) * length);
3157
- path.push([a + (b - a) * k / n, x, y]);
3965
+ path2.push([a + (b - a) * k / n, x, y]);
3158
3966
  }
3159
- const first = path[0];
3160
- const lastPoint = path[path.length - 1];
3967
+ const first = path2[0];
3968
+ const lastPoint = path2[path2.length - 1];
3161
3969
  const rest = e.settle ?? [lastPoint[1], lastPoint[2]];
3162
- const pts = [[0, first[1], first[2]], ...path];
3970
+ const pts = [[0, first[1], first[2]], ...path2];
3163
3971
  if (e.settle) pts.push([Math.min(b + 0.3, Math.max(gone, b + 0.01)), rest[0], rest[1]]);
3164
3972
  pts.push([gone, rest[0], rest[1]], [m.total, rest[0], rest[1]]);
3165
3973
  const fade = gone < m.last ? 0.05 : 0.18;
3166
3974
  return `<g class="dg-a" style="${m.move(pts, m.blink(from + 0.02, gone, fade))}">${carrierShape(e, ctx.sh)}</g>`;
3167
3975
  }
3168
- function badge(b, ctx) {
3976
+ function badge(b, ctx, grey = false) {
3169
3977
  const { m } = ctx;
3170
3978
  const span = ctx.t.steps[b.step];
3171
3979
  const a = span.start;
@@ -3191,9 +3999,9 @@ function badge(b, ctx) {
3191
3999
  const y = r1(b.y);
3192
4000
  const ty = r1(b.y + LOOK.baseline.badge);
3193
4001
  const no = b.step + 1;
3194
- return `<g class="dg-bd" data-step="${b.step}" style="${cs(b.color)}"><circle class="dg-bdr dg-popc dg-a" cx="${x}" cy="${y}" r="${rr}" style="${ring}"/><g class="dg-a" style="${past}"><circle class="dg-bdp" cx="${x}" cy="${y}" r="${rr}"/><text class="dg-bdpt" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g><g class="dg-popc dg-a" style="${fill}"><circle class="dg-bdf" cx="${x}" cy="${y}" r="${r}"/><text class="dg-bdft" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g></g>`;
4002
+ return `<g class="dg-bd" data-step="${b.step}" style="${cs(b.color)}"><circle class="dg-bdr dg-popc dg-a" cx="${x}" cy="${y}" r="${rr}" style="${ring}"/><g class="dg-a" style="${past}"><circle class="${grey ? "dg-bdp-g" : "dg-bdp"}" cx="${x}" cy="${y}" r="${rr}"/><text class="${grey ? "dg-bdpt-g" : "dg-bdpt"}" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g><g class="dg-popc dg-a" style="${fill}"><circle class="dg-bdf" cx="${x}" cy="${y}" r="${r}"/><text class="dg-bdft" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g></g>`;
3195
4003
  }
3196
- function strip(s, changes, ctx) {
4004
+ function strip(s, changes, ctx, now = false, arrivals = /* @__PURE__ */ new Map()) {
3197
4005
  const { m, sh } = ctx;
3198
4006
  const S2 = LOOK.strip;
3199
4007
  const my = s.y + S2.h / 2;
@@ -3215,8 +4023,18 @@ function strip(s, changes, ctx) {
3215
4023
  values.forEach((c, k) => {
3216
4024
  const next = values[k + 1]?.at;
3217
4025
  const value = c.value;
3218
- const anim = next === void 0 ? m.rise(c.at) : m.rise(c.at, next - MOTION.untilFade);
3219
- parts.push(`<g class="dg-a" style="${anim}"><text class="${hasWide(value) ? "dg-fvj" : "dg-fv"}" x="${r1(field.x)}" y="${r1(field.y + S2.valueY)}">${esc(value)}</text></g>`);
4026
+ const cls = hasWide(value) ? "dg-fvj" : "dg-fv";
4027
+ const textOf = (c2) => `<text class="${c2}" x="${r1(field.x)}" y="${r1(field.y + S2.valueY)}">${esc(value)}</text>`;
4028
+ const text2 = textOf(cls);
4029
+ if (!now) {
4030
+ const anim = next === void 0 ? m.rise(c.at) : m.rise(c.at, next - MOTION.untilFade);
4031
+ parts.push(`<g class="dg-a" style="${anim}">${text2}</g>`);
4032
+ return;
4033
+ }
4034
+ const until = Math.min(c.until, next ?? c.until);
4035
+ const dot = `<circle class="dg-fl-now" cx="${r1(field.x + textWidth(field.name, TYPE.fieldName) + S2.now.gap)}" cy="${r1(field.y + S2.nameY - TYPE.fieldName.size / 3)}" r="${S2.now.r}"/>`;
4036
+ parts.push(`<g class="dg-fv-now dg-a" data-step="${c.step}" style="${cs(c.color)};${m.rise(c.at, until - MOTION.untilFade)}">${textOf(`${cls} dg-fv-c`)}${dot}</g>`);
4037
+ if (next === void 0 || next > until) parts.push(`<g class="dg-a" style="${m.vis(until - MOTION.untilFade, next === void 0 ? m.last : next - MOTION.untilFade)}">${text2}</g>`);
3220
4038
  });
3221
4039
  tags.forEach((c, k) => {
3222
4040
  const next = tags[k + 1]?.at;
@@ -3230,6 +4048,22 @@ function strip(s, changes, ctx) {
3230
4048
  );
3231
4049
  });
3232
4050
  });
4051
+ if (s.trail) {
4052
+ const t = s.trail;
4053
+ const last = s.fields[s.fields.length - 1];
4054
+ if (last && last.y === t.y) {
4055
+ const sx = t.x - S2.fieldGap / 2;
4056
+ parts.push(`<line class="dg-sep" x1="${r1(sx)}" y1="${r1(t.y + S2.sepInset)}" x2="${r1(sx)}" y2="${r1(t.y + S2.h - S2.sepInset)}"/>`);
4057
+ }
4058
+ parts.push(`<text class="dg-fl" x="${r1(t.x)}" y="${r1(t.y + S2.nameY)}">${esc(t.title)}</text>`);
4059
+ const dy = t.y + S2.valueY - TYPE.fieldValue.size / 3;
4060
+ t.states.forEach((state, k) => {
4061
+ const cx = r1(t.x + S2.trail.r + k * S2.trail.step);
4062
+ const at2 = arrivals.get(state.box);
4063
+ const fill = at2 === void 0 ? "" : `<circle class="dg-tr-fill dg-a" cx="${cx}" cy="${r1(dy)}" r="${S2.trail.r}" style="${m.pop(at2)}"/>`;
4064
+ parts.push(`<g data-trail="${esc(state.box)}" style="${cs(state.color)}"><circle class="dg-tr-ring" cx="${cx}" cy="${r1(dy)}" r="${S2.trail.r}"/>${fill}</g>`);
4065
+ });
4066
+ }
3233
4067
  return parts.join("");
3234
4068
  }
3235
4069
 
@@ -3326,6 +4160,7 @@ var font = (t) => `font:${t.weight} ${t.size}px var(--${t.family})`;
3326
4160
  var mix = (pct, base = "var(--surf)") => `color-mix(in srgb,var(--c) ${pct}%,${base})`;
3327
4161
  var S = LOOK.stroke;
3328
4162
  var X = LOOK.mix;
4163
+ var PAST = `color-mix(in srgb,var(--mute) ${X.past}%,var(--bg))`;
3329
4164
  var PART_CSS = [
3330
4165
  ".dg{display:block;width:100%;height:auto;overflow:visible}",
3331
4166
  ".dg .dg-a{animation-duration:var(--T);animation-timing-function:linear;animation-iteration-count:infinite;animation-fill-mode:both;animation-delay:calc(var(--at,0) * -1s);animation-play-state:var(--play,running)}",
@@ -3350,15 +4185,21 @@ var PART_CSS = [
3350
4185
  `.dg-e-on{fill:none;stroke:var(--c);stroke-width:${S.edgeOn};stroke-linecap:round;stroke-dasharray:1 2}`,
3351
4186
  `.dg-eh-on{fill:none;stroke:var(--c);stroke-width:${S.edgeOn};stroke-linecap:round;stroke-linejoin:round}`,
3352
4187
  `.dg-flow{fill:none;stroke:var(--surf);stroke-width:${S.flow};stroke-linecap:round;stroke-dasharray:1.5 ${LOOK.edge.flowDash}}`,
4188
+ `.dg-e-past{fill:none;stroke:${PAST};stroke-width:${S.edge};stroke-linecap:round}`,
4189
+ `.dg-eh-past{fill:none;stroke:${PAST};stroke-width:${S.arrow};stroke-linecap:round;stroke-linejoin:round}`,
3353
4190
  ".dg-bd{cursor:pointer}",
3354
4191
  ".dg-bdf{fill:var(--c)}",
3355
4192
  `.dg-bdft{${font(TYPE.badge)};fill:var(--on-c)}`,
3356
4193
  `.dg-bdr{fill:none;stroke:var(--c);stroke-width:${S.badgeRing}}`,
3357
4194
  `.dg-bdp{fill:${mix(X.badgePast)};stroke:${mix(X.badgePastEdge, "transparent")};stroke-width:${S.hair}}`,
3358
4195
  `.dg-bdpt{${font(TYPE.badge)};fill:var(--ct)}`,
4196
+ `.dg-bdp-g{fill:var(--surf);stroke:${PAST};stroke-width:${S.hair}}`,
4197
+ `.dg-bdpt-g{${font(TYPE.badge)};fill:var(--mute)}`,
3359
4198
  `.dg-cap rect,.dg-act rect{fill:${mix(X.cap)};stroke:${mix(X.capEdge, "transparent")}}`,
3360
4199
  `.dg-cap text{${font(TYPE.label)};fill:var(--ct)}`,
3361
4200
  `.dg-capj text{${font(TYPE.labelJa)}}`,
4201
+ `.dg-cap-past text{${font(TYPE.label)};fill:var(--mute);fill-opacity:${LOOK.state.pastLabel}}`,
4202
+ `.dg-cap-pastj text{${font(TYPE.labelJa)}}`,
3362
4203
  `.dg-act text{${font(TYPE.action)};fill:var(--ct)}`,
3363
4204
  ".dg-car{fill:var(--carry,var(--ink))}",
3364
4205
  `.dg-car-t{${font(TYPE.carrier)};fill:var(--bg)}`,
@@ -3373,8 +4214,28 @@ var PART_CSS = [
3373
4214
  `.dg-fl{${font(TYPE.fieldName)};fill:var(--mute)}`,
3374
4215
  `.dg-fv{${font(TYPE.fieldValue)};fill:var(--ink)}`,
3375
4216
  `.dg-fvj{${font(TYPE.fieldValueJa)};fill:var(--ink)}`,
4217
+ ".dg-fv-c{fill:var(--ct)}",
4218
+ ".dg-fl-now{fill:var(--c)}",
4219
+ `.dg-tr-ring{fill:none;stroke:var(--line);stroke-width:${S.trail}}`,
4220
+ ".dg-tr-fill{fill:var(--c)}",
3376
4221
  ".dg-tg rect{fill:var(--c)}",
3377
4222
  `.dg-tg text{${font(TYPE.tag)};fill:var(--on-c)}`,
4223
+ `.dg-side{fill:color-mix(in srgb,var(--c) ${X.side}%,var(--bg));stroke:${mix(X.sideEdge, "transparent")};stroke-dasharray:4 4}`,
4224
+ `.dg-side-t{${font(TYPE.regionName)};fill:var(--ct)}`,
4225
+ `.dg-side-n{${font(TYPE.regionNote)};fill:var(--mute)}`,
4226
+ `.dg-ghost{fill:var(--surf);stroke:${mix(X.ghostEdge, "transparent")};stroke-dasharray:4 3}`,
4227
+ `.dg-path{fill:none;stroke:${mix(X.path, "transparent")};stroke-width:${S.path};stroke-linecap:round;stroke-dasharray:0 ${LOOK.edge.ghostDash}}`,
4228
+ `.dg-path-h{fill:none;stroke:${mix(X.path, "transparent")};stroke-width:${S.arrow};stroke-linecap:round;stroke-linejoin:round}`,
4229
+ `.dg-path-t{${font(TYPE.label)};fill:var(--ct)}`,
4230
+ `.dg-path-tj{${font(TYPE.labelJa)}}`,
4231
+ ".dg-start{fill:var(--ink)}",
4232
+ `.dg-end{fill:var(--bg);stroke:var(--ink);stroke-width:${S.end}}`,
4233
+ ".dg-end-in{fill:var(--ink)}",
4234
+ `.dg-end-x{fill:var(--bg);stroke:${mix(X.path, "transparent")};stroke-width:${S.arrow};stroke-dasharray:2 2.5}`,
4235
+ `.dg-end-xi{fill:${mix(X.path, "transparent")}}`,
4236
+ `.dg-mark{${font(TYPE.regionNote)};fill:var(--mute)}`,
4237
+ `.dg-done{fill:var(--ink);stroke:var(--surf);stroke-width:${S.done}}`,
4238
+ `.dg-done-ck{fill:none;stroke:var(--surf);stroke-width:${S.glyph};stroke-linecap:round;stroke-linejoin:round}`,
3378
4239
  ".dg-vp-bg{fill:var(--bg)}",
3379
4240
  ".dg-vp-frame{fill:none;stroke:var(--hair)}",
3380
4241
  ".dg-hd-bg{fill:var(--bg)}",
@@ -3452,7 +4313,8 @@ function fieldChanges(diagram, timeline, layout) {
3452
4313
  if (event?.type !== "strip") continue;
3453
4314
  const color = layout.badges[time.step]?.color ?? "slate";
3454
4315
  const list = out.get(event.field) ?? [];
3455
- list.push({ at: time.at, color, ...event.value !== void 0 ? { value: event.value } : {}, ...event.tag !== void 0 ? { tag: event.tag } : {} });
4316
+ const until = timeline.steps[time.step].end;
4317
+ list.push({ at: time.at, color, step: time.step, until, ...event.value !== void 0 ? { value: event.value } : {}, ...event.tag !== void 0 ? { tag: event.tag } : {} });
3456
4318
  out.set(event.field, list);
3457
4319
  }
3458
4320
  return out;
@@ -3462,20 +4324,36 @@ function drawSvg(diagram, layout, timeline, palette, theme, follow) {
3462
4324
  const m = new Motion(`dg${id}`, timeline.total, timeline.last);
3463
4325
  const ctx = { m, t: timeline, sh: `filter="url(#dg-sh-${id})"`, end: timeline.steps[timeline.steps.length - 1].end };
3464
4326
  const on = involved(diagram);
3465
- const subs = subChanges(diagram, timeline, layout.kind === "architecture");
4327
+ const subs = subChanges(diagram, timeline, layout.kind !== "sequence");
3466
4328
  const L = { band: [], base: [], lit: [], node: [], badge: [], top: [] };
3467
4329
  for (const region of layout.regions) L.band.push(band(region));
3468
- if (layout.strip) L.band.push(strip(layout.strip, fieldChanges(diagram, timeline, layout), ctx));
4330
+ const ghostColor = layout.boxes.find((b) => b.ghost)?.color ?? "slate";
4331
+ if (layout.side) L.band.push(side(layout.side, ghostColor));
4332
+ const boxColor = (id2, ghost) => layout.boxes.find((b) => b.id === id2 && (ghost === void 0 || b.ghost === ghost))?.color;
4333
+ for (const p of layout.paths) L.base.push(path(p, boxColor(p.to, true) ?? boxColor(p.from) ?? ghostColor));
4334
+ for (const e of layout.ends) L.node.push(endMark(e, ghostColor));
4335
+ const isState = layout.kind === "state";
4336
+ const arrivals = new Map((timeline.states ?? []).flatMap((s) => s.lit[0] ? [[s.box, s.lit[0].start]] : []));
4337
+ if (layout.strip) L.band.push(strip(layout.strip, fieldChanges(diagram, timeline, layout), ctx, isState, arrivals));
3469
4338
  for (const line of layout.lifelines) L.base.push(lifeline(line.x, line.y1, line.y2));
3470
4339
  for (const e of layout.edges) {
3471
4340
  const time = timeline.edges.find((t) => t.step === e.step && t.event === e.event);
3472
4341
  if (!time) continue;
3473
- const drawn = edge(e, time, ctx);
4342
+ const drawn = edge(e, time, ctx, isState);
3474
4343
  L.base.push(drawn.base);
3475
4344
  L.lit.push(drawn.lit);
3476
4345
  }
3477
- for (const box of layout.boxes) L.node.push(card(box, ctx, on.get(box.id) ?? [], subs.get(box.id) ?? []));
3478
- for (const b of layout.badges) L.badge.push(badge(b, ctx));
4346
+ const states = new Map((timeline.states ?? []).map((s) => [s.box, s]));
4347
+ for (const box of layout.boxes) {
4348
+ if (box.ghost) {
4349
+ L.node.push(ghostCard(box));
4350
+ continue;
4351
+ }
4352
+ const state = states.get(box.id);
4353
+ L.node.push(card(box, ctx, on.get(box.id) ?? [], subs.get(box.id) ?? [], isState ? state?.lit ?? [] : void 0));
4354
+ if (state?.done !== void 0) L.node.push(doneMark(box, state.done, ctx));
4355
+ }
4356
+ for (const b of layout.badges) L.badge.push(badge(b, ctx, isState));
3479
4357
  for (const l of layout.labels) {
3480
4358
  const time = timeline.labels.find((t) => t.step === l.step && t.event === l.event);
3481
4359
  if (time) L.top.push(label(l, time, ctx));
@@ -3611,7 +4489,7 @@ function renderDiagram(input, options = {}) {
3611
4489
  const diagram = read.diagram;
3612
4490
  const palette = resolvePalette(options.palette);
3613
4491
  const theme = options.theme === "dark" ? "dark" : "light";
3614
- const layout = diagram.kind === "sequence" ? layoutSequence(diagram) : layoutArchitecture(diagram);
4492
+ const layout = diagram.kind === "sequence" ? layoutSequence(diagram) : diagram.kind === "state" ? layoutState(diagram, lang) : layoutArchitecture(diagram);
3615
4493
  const timeline = buildTimeline(diagram);
3616
4494
  return {
3617
4495
  svg: drawSvg(diagram, layout, timeline, palette, theme),
@@ -3640,7 +4518,7 @@ var pad = (n) => String(n).padStart(2, "0");
3640
4518
  var stepNo = (step, count) => `${pad(step + 1)}/${pad(count)}`;
3641
4519
  var require_ = module$1.createRequire(importMetaUrl);
3642
4520
  var SCRIPTS = {
3643
- "/mediabunny.js": path.join(path.dirname(require_.resolve("mediabunny")), "mediabunny.min.mjs"),
4521
+ "/mediabunny.js": path$1.join(path$1.dirname(require_.resolve("mediabunny")), "mediabunny.min.mjs"),
3644
4522
  "/gifenc.js": require_.resolve("gifenc/dist/gifenc.esm.js")
3645
4523
  };
3646
4524
  var SCALE = 2;
@@ -3682,9 +4560,9 @@ async function stage(browser, svg, fontCss, body) {
3682
4560
  const paused = svg.replace(/^<svg\b/, '<svg style="--play:paused;--at:0"');
3683
4561
  const html = `<!doctype html><html><head><meta charset="utf-8"><style>${fontCss}html,body{margin:0}body{${body}}svg{display:block}</style><script type="module">import * as mb from "/mediabunny.js";import * as gif from "/gifenc.js";window.__tools={mb,gif};</script></head><body>${paused}</body></html>`;
3684
4562
  await page.route("http://localhost/**", async (route) => {
3685
- const path = new URL(route.request().url()).pathname;
3686
- if (path === "/") return route.fulfill({ contentType: "text/html; charset=utf-8", body: html });
3687
- const script = SCRIPTS[path];
4563
+ const path2 = new URL(route.request().url()).pathname;
4564
+ if (path2 === "/") return route.fulfill({ contentType: "text/html; charset=utf-8", body: html });
4565
+ const script = SCRIPTS[path2];
3688
4566
  return script ? route.fulfill({ contentType: "text/javascript", body: fs.readFileSync(script) }) : route.fulfill({ status: 404 });
3689
4567
  });
3690
4568
  await page.goto("http://localhost/");
@@ -3861,8 +4739,8 @@ function charsOf(texts) {
3861
4739
  async function fontFaces(chars) {
3862
4740
  const faces = await Promise.all(
3863
4741
  PACKAGES.flatMap(({ family, name }) => {
3864
- const base = path.dirname(require_2.resolve(`@fontsource-variable/${name}/unicode.json`));
3865
- const table = JSON.parse(fs.readFileSync(path.join(base, "unicode.json"), "utf8"));
4742
+ const base = path$1.dirname(require_2.resolve(`@fontsource-variable/${name}/unicode.json`));
4743
+ const table = JSON.parse(fs.readFileSync(path$1.join(base, "unicode.json"), "utf8"));
3866
4744
  return Object.entries(table).map(async ([key, list]) => {
3867
4745
  const span = ranges(list);
3868
4746
  const own = chars.filter((char) => {
@@ -3870,7 +4748,7 @@ async function fontFaces(chars) {
3870
4748
  return span.some(([from, to]) => code >= from && code <= to);
3871
4749
  });
3872
4750
  if (!own.length) return "";
3873
- const file = path.join(base, "files", `${name}-${key.replace(/[[\]]/g, "")}-wght-normal.woff2`);
4751
+ const file = path$1.join(base, "files", `${name}-${key.replace(/[[\]]/g, "")}-wght-normal.woff2`);
3874
4752
  const woff2 = await subsetFont(await promises.readFile(file), own.join(""), { targetFormat: "woff2", variationAxes: { wght: WEIGHT } });
3875
4753
  const unicode = own.map((char) => hex(char.codePointAt(0) ?? 0)).join(",");
3876
4754
  return `@font-face{font-family:"${family}";font-style:normal;font-display:block;font-weight:${WEIGHT.min} ${WEIGHT.max};src:url(data:font/woff2;base64,${woff2.toString("base64")}) format("woff2");unicode-range:${unicode}}`;
@@ -3962,9 +4840,9 @@ function writeOutputs(outDir, name, outputs) {
3962
4840
  const files = {};
3963
4841
  try {
3964
4842
  for (const [format, data] of outputs) {
3965
- const path$1 = path.join(outDir, `${name}.${format}`);
3966
- fs.writeFileSync(path$1, data);
3967
- files[format] = path$1;
4843
+ const path2 = path$1.join(outDir, `${name}.${format}`);
4844
+ fs.writeFileSync(path2, data);
4845
+ files[format] = path2;
3968
4846
  }
3969
4847
  } catch (error) {
3970
4848
  if (created !== void 0) fs.rmSync(created, { recursive: true, force: true });