@almadar/ui 2.22.2 → 2.24.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.
Files changed (36) hide show
  1. package/dist/avl/index.cjs +699 -343
  2. package/dist/avl/index.d.cts +47 -10
  3. package/dist/avl/index.d.ts +2 -0
  4. package/dist/avl/index.js +696 -345
  5. package/dist/components/atoms/PatternTile.d.ts +41 -0
  6. package/dist/components/atoms/avl/AvlEffect.d.ts +2 -0
  7. package/dist/components/atoms/avl/AvlState.d.ts +5 -0
  8. package/dist/components/atoms/avl/index.d.ts +2 -0
  9. package/dist/components/atoms/avl/types.d.ts +34 -0
  10. package/dist/components/atoms/index.d.ts +1 -0
  11. package/dist/components/index.cjs +2136 -1124
  12. package/dist/components/index.js +1272 -264
  13. package/dist/components/molecules/EdgeDecoration.d.ts +35 -0
  14. package/dist/components/molecules/GeometricPattern.d.ts +33 -0
  15. package/dist/components/molecules/avl/AvlSwimLane.d.ts +10 -0
  16. package/dist/components/molecules/avl/AvlTransitionLane.d.ts +18 -0
  17. package/dist/components/molecules/avl/index.d.ts +2 -0
  18. package/dist/components/molecules/index.d.ts +2 -0
  19. package/dist/components/organisms/avl/AvlTraitScene.d.ts +3 -3
  20. package/dist/components/organisms/avl/AvlTransitionScene.d.ts +3 -6
  21. package/dist/docs/index.cjs +3 -3
  22. package/dist/docs/index.js +3 -3
  23. package/dist/illustrations/index.cjs +65 -12
  24. package/dist/illustrations/index.d.cts +7 -0
  25. package/dist/illustrations/index.js +65 -12
  26. package/dist/marketing/index.cjs +1035 -23
  27. package/dist/marketing/index.d.cts +112 -1
  28. package/dist/marketing/index.d.ts +6 -0
  29. package/dist/marketing/index.js +1034 -26
  30. package/dist/providers/index.cjs +125 -125
  31. package/dist/providers/index.js +37 -37
  32. package/dist/runtime/enrichFromResponse.d.ts +1 -1
  33. package/dist/runtime/index.cjs +1006 -998
  34. package/dist/runtime/index.js +247 -239
  35. package/package.json +1 -1
  36. package/themes/almadar-website.css +36 -34
@@ -32,6 +32,48 @@ var AVL_FIELD_TYPE_SHAPES = {
32
32
  object: "hexagon",
33
33
  array: "bars"
34
34
  };
35
+ var STATE_COLORS = {
36
+ initial: { fill: "#22C55E1F", border: "#16A34A" },
37
+ terminal: { fill: "#EF44441F", border: "#DC2626" },
38
+ hub: { fill: "#3B82F61F", border: "#2563EB" },
39
+ error: { fill: "#F59E0B1F", border: "#D97706" },
40
+ default: { fill: "#6B72801F", border: "#4B5563" }
41
+ };
42
+ var EFFECT_CATEGORY_COLORS = {
43
+ ui: { color: "#8B5CF6", bg: "#8B5CF614" },
44
+ data: { color: "#3B82F6", bg: "#3B82F614" },
45
+ communication: { color: "#F97316", bg: "#F9731614" },
46
+ lifecycle: { color: "#10B981", bg: "#10B98114" },
47
+ control: { color: "#6B7280", bg: "#6B728014" }
48
+ };
49
+ var EFFECT_TYPE_TO_CATEGORY = {
50
+ "render-ui": "ui",
51
+ "navigate": "ui",
52
+ "set": "data",
53
+ "persist": "data",
54
+ "fetch": "data",
55
+ "emit": "communication",
56
+ "notify": "communication",
57
+ "call-service": "communication",
58
+ "spawn": "lifecycle",
59
+ "despawn": "lifecycle",
60
+ "do": "control",
61
+ "if": "control",
62
+ "log": "control"
63
+ };
64
+ var CONNECTION_COLORS = {
65
+ forward: { color: "#1E293B", width: 2, dash: "none" },
66
+ backward: { color: "#94A3B8", width: 1.5, dash: "6 3" },
67
+ selfLoop: { color: "#CBD5E1", width: 1, dash: "3 2" },
68
+ emitListen: { color: "#F97316", width: 1.5, dash: "4 3" }
69
+ };
70
+ function getStateRole(name, isInitial, isTerminal, transitionCount, maxTransitionCount) {
71
+ if (isInitial) return "initial";
72
+ if (isTerminal) return "terminal";
73
+ if (/error|fail|invalid/i.test(name)) return "error";
74
+ if (transitionCount != null && maxTransitionCount != null && transitionCount === maxTransitionCount && transitionCount >= 3) return "hub";
75
+ return "default";
76
+ }
35
77
  var AvlOrbital = ({
36
78
  cx = 0,
37
79
  cy = 0,
@@ -303,19 +345,33 @@ var AvlApplication = ({
303
345
  ] });
304
346
  };
305
347
  AvlApplication.displayName = "AvlApplication";
348
+ function computeWidth(explicit, transitionCount) {
349
+ if (explicit != null) return explicit;
350
+ if (transitionCount == null) return 100;
351
+ if (transitionCount >= 5) return 160;
352
+ if (transitionCount >= 3) return 130;
353
+ return 100;
354
+ }
306
355
  var AvlState = ({
307
356
  x = 0,
308
357
  y = 0,
309
358
  name,
310
359
  isInitial = false,
311
360
  isTerminal = false,
312
- width = 100,
361
+ width: explicitWidth,
313
362
  height = 40,
314
363
  color = "var(--color-primary)",
315
364
  opacity = 1,
316
- className
365
+ className,
366
+ role,
367
+ transitionCount
317
368
  }) => {
369
+ const width = computeWidth(explicitWidth, transitionCount);
318
370
  const rx = height / 2;
371
+ const roleColors = role ? STATE_COLORS[role] : null;
372
+ const fillColor = roleColors ? roleColors.fill : "none";
373
+ const strokeColor = roleColors ? roleColors.border : color;
374
+ const textColor = roleColors ? roleColors.border : color;
319
375
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { className, opacity, transform: `translate(${x},${y})`, children: [
320
376
  isInitial && /* @__PURE__ */ jsxRuntime.jsx(
321
377
  "circle",
@@ -323,7 +379,7 @@ var AvlState = ({
323
379
  cx: -16,
324
380
  cy: height / 2,
325
381
  r: 6,
326
- fill: color
382
+ fill: strokeColor
327
383
  }
328
384
  ),
329
385
  isTerminal && /* @__PURE__ */ jsxRuntime.jsx(
@@ -336,7 +392,7 @@ var AvlState = ({
336
392
  rx: rx + 4,
337
393
  ry: rx + 4,
338
394
  fill: "none",
339
- stroke: color,
395
+ stroke: strokeColor,
340
396
  strokeWidth: 1,
341
397
  opacity: 0.5
342
398
  }
@@ -350,8 +406,8 @@ var AvlState = ({
350
406
  height,
351
407
  rx,
352
408
  ry: rx,
353
- fill: "none",
354
- stroke: color,
409
+ fill: fillColor,
410
+ stroke: strokeColor,
355
411
  strokeWidth: 2
356
412
  }
357
413
  ),
@@ -362,8 +418,9 @@ var AvlState = ({
362
418
  y: height / 2,
363
419
  textAnchor: "middle",
364
420
  dominantBaseline: "central",
365
- fill: color,
366
- fontSize: 11,
421
+ fill: textColor,
422
+ fontSize: role ? 14 : 11,
423
+ fontWeight: role ? 600 : 400,
367
424
  fontFamily: "inherit",
368
425
  children: name
369
426
  }
@@ -632,18 +689,27 @@ var AvlEffect = ({
632
689
  label,
633
690
  color = "var(--color-primary)",
634
691
  opacity = 1,
635
- className
692
+ className,
693
+ showBackground = false
636
694
  }) => {
695
+ const category = EFFECT_TYPE_TO_CATEGORY[effectType];
696
+ const catColors = EFFECT_CATEGORY_COLORS[category];
697
+ const iconColor = showBackground ? catColors.color : color;
637
698
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { className, opacity, children: [
638
- effectIcon(effectType, x, y, size, color),
699
+ showBackground && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
700
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x, cy: y, r: size * 1.2, fill: catColors.bg }),
701
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x, cy: y, r: size * 1.2, fill: "none", stroke: catColors.color, strokeWidth: 0.5, opacity: 0.3 })
702
+ ] }),
703
+ effectIcon(effectType, x, y, size, iconColor),
639
704
  label && /* @__PURE__ */ jsxRuntime.jsx(
640
705
  "text",
641
706
  {
642
707
  x,
643
708
  y: y + size + 10,
644
709
  textAnchor: "middle",
645
- fill: color,
646
- fontSize: 8,
710
+ fill: iconColor,
711
+ fontSize: 11,
712
+ fontWeight: 500,
647
713
  fontFamily: "inherit",
648
714
  opacity: 0.7,
649
715
  children: label
@@ -4071,7 +4137,7 @@ var AvlStateMachine = ({
4071
4137
  const cx = 300;
4072
4138
  const cy = 200;
4073
4139
  const r2 = 150;
4074
- const stateWidth = 90;
4140
+ const stateWidth2 = 90;
4075
4141
  const stateHeight = 36;
4076
4142
  const positions = ringPositions(cx, cy, r2, states.length);
4077
4143
  const stateIndex = new Map(states.map((s, i) => [s.name, i]));
@@ -4152,9 +4218,9 @@ var AvlStateMachine = ({
4152
4218
  const seenIdx = pairSeen.get(pairKey) ?? 0;
4153
4219
  pairSeen.set(pairKey, seenIdx + 1);
4154
4220
  const pairOffset = totalForPair > 1 ? (seenIdx - (totalForPair - 1) / 2) * 24 : 0;
4155
- const x1 = fp.x + nx * (stateWidth / 2 + 4);
4221
+ const x1 = fp.x + nx * (stateWidth2 / 2 + 4);
4156
4222
  const y1 = fp.y + ny * (stateHeight / 2 + 4);
4157
- const x2 = tp.x - nx * (stateWidth / 2 + 8);
4223
+ const x2 = tp.x - nx * (stateWidth2 / 2 + 8);
4158
4224
  const y2 = tp.y - ny * (stateHeight / 2 + 8);
4159
4225
  const t = 0.3;
4160
4226
  const labelX = x1 * (1 - t) + x2 * t;
@@ -4232,9 +4298,9 @@ var AvlStateMachine = ({
4232
4298
  return /* @__PURE__ */ jsxRuntime.jsx(
4233
4299
  AvlState,
4234
4300
  {
4235
- x: pos.x - stateWidth / 2,
4301
+ x: pos.x - stateWidth2 / 2,
4236
4302
  y: pos.y - stateHeight / 2,
4237
- width: stateWidth,
4303
+ width: stateWidth2,
4238
4304
  height: stateHeight,
4239
4305
  name: state.name,
4240
4306
  isInitial: state.isInitial,
@@ -4850,6 +4916,288 @@ var AvlExprTree = ({
4850
4916
  ] });
4851
4917
  };
4852
4918
  AvlExprTree.displayName = "AvlExprTree";
4919
+ var MAX_VISIBLE_EFFECTS = 6;
4920
+ var AvlTransitionLane = ({
4921
+ event,
4922
+ guard,
4923
+ effects,
4924
+ width,
4925
+ x = 0,
4926
+ y = 0,
4927
+ isBackward = false,
4928
+ isSelfLoop = false,
4929
+ color = "var(--color-primary)",
4930
+ onTransitionClick
4931
+ }) => {
4932
+ const rowHeight = 22;
4933
+ const padding = 8;
4934
+ const eventRow = padding;
4935
+ const guardRow = guard ? eventRow + rowHeight : eventRow;
4936
+ const effectsRow = guard ? guardRow + rowHeight : eventRow + rowHeight;
4937
+ const totalHeight = effectsRow + (effects.length > 0 ? rowHeight + padding : padding);
4938
+ const connStyle = isSelfLoop ? CONNECTION_COLORS.selfLoop : isBackward ? CONNECTION_COLORS.backward : CONNECTION_COLORS.forward;
4939
+ const visibleEffects = effects.slice(0, MAX_VISIBLE_EFFECTS);
4940
+ const overflow = effects.length - MAX_VISIBLE_EFFECTS;
4941
+ const effectSpacing = 28;
4942
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4943
+ "g",
4944
+ {
4945
+ transform: `translate(${x},${y})`,
4946
+ style: { cursor: onTransitionClick ? "pointer" : "default" },
4947
+ onClick: onTransitionClick,
4948
+ role: onTransitionClick ? "button" : void 0,
4949
+ children: [
4950
+ /* @__PURE__ */ jsxRuntime.jsx(
4951
+ "rect",
4952
+ {
4953
+ x: 0,
4954
+ y: 0,
4955
+ width,
4956
+ height: totalHeight,
4957
+ rx: 6,
4958
+ fill: connStyle.color,
4959
+ fillOpacity: 0.03,
4960
+ stroke: connStyle.color,
4961
+ strokeWidth: 0.5,
4962
+ strokeOpacity: 0.15,
4963
+ strokeDasharray: connStyle.dash === "none" ? void 0 : connStyle.dash
4964
+ }
4965
+ ),
4966
+ /* @__PURE__ */ jsxRuntime.jsx(
4967
+ "text",
4968
+ {
4969
+ x: padding + 14,
4970
+ y: eventRow + rowHeight * 0.65,
4971
+ fontSize: 14,
4972
+ fontWeight: 600,
4973
+ fill: color,
4974
+ fontFamily: "inherit",
4975
+ children: event
4976
+ }
4977
+ ),
4978
+ /* @__PURE__ */ jsxRuntime.jsx(
4979
+ "text",
4980
+ {
4981
+ x: padding + 4,
4982
+ y: eventRow + rowHeight * 0.65,
4983
+ fontSize: 10,
4984
+ fill: color,
4985
+ opacity: 0.5,
4986
+ children: "\u26A1"
4987
+ }
4988
+ ),
4989
+ guard && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
4990
+ /* @__PURE__ */ jsxRuntime.jsx(
4991
+ "polygon",
4992
+ {
4993
+ points: `${padding + 6},${guardRow + rowHeight * 0.35} ${padding + 10},${guardRow + rowHeight * 0.15} ${padding + 14},${guardRow + rowHeight * 0.35} ${padding + 10},${guardRow + rowHeight * 0.55}`,
4994
+ fill: "none",
4995
+ stroke: color,
4996
+ strokeWidth: 1,
4997
+ opacity: 0.5
4998
+ }
4999
+ ),
5000
+ /* @__PURE__ */ jsxRuntime.jsx(
5001
+ "text",
5002
+ {
5003
+ x: padding + 20,
5004
+ y: guardRow + rowHeight * 0.6,
5005
+ fontSize: 12,
5006
+ fontWeight: 400,
5007
+ fill: color,
5008
+ opacity: 0.6,
5009
+ fontFamily: "inherit",
5010
+ children: guard
5011
+ }
5012
+ )
5013
+ ] }),
5014
+ visibleEffects.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5015
+ visibleEffects.map((eff, i) => /* @__PURE__ */ jsxRuntime.jsx(
5016
+ AvlEffect,
5017
+ {
5018
+ x: padding + 12 + i * effectSpacing,
5019
+ y: effectsRow + rowHeight * 0.5,
5020
+ effectType: eff.type,
5021
+ size: 10,
5022
+ showBackground: true
5023
+ },
5024
+ i
5025
+ )),
5026
+ overflow > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
5027
+ "text",
5028
+ {
5029
+ x: padding + 12 + visibleEffects.length * effectSpacing,
5030
+ y: effectsRow + rowHeight * 0.6,
5031
+ fontSize: 10,
5032
+ fill: color,
5033
+ opacity: 0.5,
5034
+ fontFamily: "inherit",
5035
+ children: [
5036
+ "+",
5037
+ overflow
5038
+ ]
5039
+ }
5040
+ )
5041
+ ] })
5042
+ ]
5043
+ }
5044
+ );
5045
+ };
5046
+ AvlTransitionLane.displayName = "AvlTransitionLane";
5047
+ var GUTTER_WIDTH = 120;
5048
+ var EVENT_SPACING = 24;
5049
+ var HEADER_Y = 16;
5050
+ var EVENT_START_Y = 36;
5051
+ var AvlSwimLane = ({
5052
+ listenedEvents,
5053
+ emittedEvents,
5054
+ centerWidth,
5055
+ height,
5056
+ color = "var(--color-primary)",
5057
+ children
5058
+ }) => {
5059
+ const rightX = GUTTER_WIDTH + centerWidth;
5060
+ const totalWidth = rightX + GUTTER_WIDTH;
5061
+ const emitColor = CONNECTION_COLORS.emitListen.color;
5062
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5063
+ listenedEvents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5064
+ /* @__PURE__ */ jsxRuntime.jsx(
5065
+ "text",
5066
+ {
5067
+ x: 8,
5068
+ y: HEADER_Y,
5069
+ fontSize: 10,
5070
+ fontWeight: 600,
5071
+ fill: color,
5072
+ opacity: 0.4,
5073
+ fontFamily: "inherit",
5074
+ children: "LISTENS"
5075
+ }
5076
+ ),
5077
+ listenedEvents.map((evt, i) => {
5078
+ const ey = EVENT_START_Y + i * EVENT_SPACING;
5079
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5080
+ /* @__PURE__ */ jsxRuntime.jsx(
5081
+ "polygon",
5082
+ {
5083
+ points: `${4},${ey} ${12},${ey - 5} ${12},${ey + 5}`,
5084
+ fill: emitColor,
5085
+ opacity: 0.6
5086
+ }
5087
+ ),
5088
+ /* @__PURE__ */ jsxRuntime.jsx(
5089
+ "text",
5090
+ {
5091
+ x: 16,
5092
+ y: ey + 4,
5093
+ fontSize: 11,
5094
+ fontWeight: 500,
5095
+ fill: color,
5096
+ opacity: 0.6,
5097
+ fontFamily: "inherit",
5098
+ children: evt
5099
+ }
5100
+ ),
5101
+ /* @__PURE__ */ jsxRuntime.jsx(
5102
+ "line",
5103
+ {
5104
+ x1: GUTTER_WIDTH - 4,
5105
+ y1: ey,
5106
+ x2: GUTTER_WIDTH,
5107
+ y2: ey,
5108
+ stroke: emitColor,
5109
+ strokeWidth: 1,
5110
+ strokeDasharray: "3 2",
5111
+ opacity: 0.4
5112
+ }
5113
+ )
5114
+ ] }, evt + i);
5115
+ })
5116
+ ] }),
5117
+ /* @__PURE__ */ jsxRuntime.jsx(
5118
+ "line",
5119
+ {
5120
+ x1: GUTTER_WIDTH,
5121
+ y1: 0,
5122
+ x2: GUTTER_WIDTH,
5123
+ y2: height,
5124
+ stroke: color,
5125
+ strokeWidth: 0.5,
5126
+ strokeDasharray: "4 3",
5127
+ opacity: 0.12
5128
+ }
5129
+ ),
5130
+ /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${GUTTER_WIDTH}, 0)`, children }),
5131
+ /* @__PURE__ */ jsxRuntime.jsx(
5132
+ "line",
5133
+ {
5134
+ x1: rightX,
5135
+ y1: 0,
5136
+ x2: rightX,
5137
+ y2: height,
5138
+ stroke: color,
5139
+ strokeWidth: 0.5,
5140
+ strokeDasharray: "4 3",
5141
+ opacity: 0.12
5142
+ }
5143
+ ),
5144
+ emittedEvents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5145
+ /* @__PURE__ */ jsxRuntime.jsx(
5146
+ "text",
5147
+ {
5148
+ x: rightX + 8,
5149
+ y: HEADER_Y,
5150
+ fontSize: 10,
5151
+ fontWeight: 600,
5152
+ fill: color,
5153
+ opacity: 0.4,
5154
+ fontFamily: "inherit",
5155
+ children: "EMITS"
5156
+ }
5157
+ ),
5158
+ emittedEvents.map((evt, i) => {
5159
+ const ey = EVENT_START_Y + i * EVENT_SPACING;
5160
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5161
+ /* @__PURE__ */ jsxRuntime.jsx(
5162
+ "text",
5163
+ {
5164
+ x: rightX + 8,
5165
+ y: ey + 4,
5166
+ fontSize: 11,
5167
+ fontWeight: 500,
5168
+ fill: color,
5169
+ opacity: 0.6,
5170
+ fontFamily: "inherit",
5171
+ children: evt
5172
+ }
5173
+ ),
5174
+ /* @__PURE__ */ jsxRuntime.jsx(
5175
+ "polygon",
5176
+ {
5177
+ points: `${totalWidth - 4},${ey} ${totalWidth - 12},${ey - 5} ${totalWidth - 12},${ey + 5}`,
5178
+ fill: emitColor,
5179
+ opacity: 0.6
5180
+ }
5181
+ ),
5182
+ /* @__PURE__ */ jsxRuntime.jsx(
5183
+ "line",
5184
+ {
5185
+ x1: rightX,
5186
+ y1: ey,
5187
+ x2: rightX + 4,
5188
+ y2: ey,
5189
+ stroke: emitColor,
5190
+ strokeWidth: 1,
5191
+ strokeDasharray: "3 2",
5192
+ opacity: 0.4
5193
+ }
5194
+ )
5195
+ ] }, evt + i);
5196
+ })
5197
+ ] })
5198
+ ] });
5199
+ };
5200
+ AvlSwimLane.displayName = "AvlSwimLane";
4853
5201
 
4854
5202
  // components/organisms/avl/avl-schema-parser.ts
4855
5203
  function getEntity(orbital) {
@@ -5604,39 +5952,52 @@ var AvlOrbitalScene = ({
5604
5952
  ] });
5605
5953
  };
5606
5954
  AvlOrbitalScene.displayName = "AvlOrbitalScene";
5607
- var STATE_W = 110;
5608
- var STATE_H = 38;
5609
- var LABEL_W = 90;
5610
- var LABEL_H = 20;
5955
+ function stateWidth(transitionCount) {
5956
+ if (transitionCount >= 5) return 160;
5957
+ if (transitionCount >= 3) return 130;
5958
+ return 110;
5959
+ }
5960
+ var STATE_H = 40;
5611
5961
  var elk = new ELK__default.default();
5612
5962
  async function computeLayout(data) {
5963
+ const transitionCounts = {};
5964
+ for (const s of data.states) transitionCounts[s.name] = 0;
5965
+ for (const t of data.transitions) {
5966
+ transitionCounts[t.from] = (transitionCounts[t.from] ?? 0) + 1;
5967
+ transitionCounts[t.to] = (transitionCounts[t.to] ?? 0) + 1;
5968
+ }
5969
+ const maxTC = Math.max(...Object.values(transitionCounts), 0);
5970
+ const LABEL_BASE_W = 100;
5971
+ const LABEL_H = 44;
5613
5972
  const elkGraph = {
5614
5973
  id: "root",
5615
5974
  layoutOptions: {
5616
5975
  "elk.algorithm": "layered",
5617
- "elk.direction": "DOWN",
5618
- "elk.spacing.nodeNode": "50",
5976
+ "elk.direction": "RIGHT",
5977
+ "elk.spacing.nodeNode": "80",
5619
5978
  "elk.spacing.edgeNode": "30",
5620
- "elk.spacing.edgeEdge": "20",
5621
- "elk.spacing.edgeLabel": "8",
5622
- "elk.spacing.labelLabel": "6",
5623
- "elk.layered.spacing.nodeNodeBetweenLayers": "60",
5979
+ "elk.spacing.edgeEdge": "24",
5980
+ "elk.spacing.edgeLabel": "10",
5981
+ "elk.spacing.labelLabel": "8",
5982
+ "elk.layered.spacing.nodeNodeBetweenLayers": "100",
5624
5983
  "elk.edgeLabels.placement": "CENTER",
5625
5984
  "elk.layered.mergeEdges": "false",
5626
5985
  "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX"
5627
5986
  },
5628
- children: data.states.map((s) => ({
5629
- id: s.name,
5630
- width: STATE_W,
5631
- height: STATE_H,
5632
- labels: [{ text: s.name, width: STATE_W - 10, height: 14 }]
5633
- })),
5987
+ children: data.states.map((s) => {
5988
+ const tc = transitionCounts[s.name] ?? 0;
5989
+ const w = stateWidth(tc);
5990
+ return {
5991
+ id: s.name,
5992
+ width: w,
5993
+ height: STATE_H,
5994
+ labels: [{ text: s.name, width: w - 10, height: 14 }]
5995
+ };
5996
+ }),
5634
5997
  edges: data.transitions.map((t, i) => {
5635
- const hasEffects = t.effects.length > 0;
5636
- const labelH = hasEffects ? 38 : LABEL_H;
5637
- const textW = Math.max(t.event.length * 7, 40);
5638
- const iconsW = Math.min(t.effects.length, 4) * 14;
5639
- const labelW = Math.max(textW, iconsW, LABEL_W) + 20;
5998
+ const textW = Math.max(t.event.length * 8, 60);
5999
+ const iconsW = Math.min(t.effects.length, 6) * 28 + 20;
6000
+ const labelW = Math.max(textW, iconsW, LABEL_BASE_W);
5640
6001
  return {
5641
6002
  id: `e${i}`,
5642
6003
  sources: [t.from],
@@ -5644,7 +6005,7 @@ async function computeLayout(data) {
5644
6005
  labels: [{
5645
6006
  text: t.event,
5646
6007
  width: labelW,
5647
- height: labelH
6008
+ height: LABEL_H
5648
6009
  }]
5649
6010
  };
5650
6011
  })
@@ -5652,15 +6013,26 @@ async function computeLayout(data) {
5652
6013
  const layout = await elk.layout(elkGraph);
5653
6014
  const layoutChildren = layout.children ?? [];
5654
6015
  const layoutEdges = layout.edges ?? [];
5655
- const nodes = layoutChildren.map((n) => ({
5656
- id: n.id,
5657
- x: n.x ?? 0,
5658
- y: n.y ?? 0,
5659
- width: n.width ?? STATE_W,
5660
- height: n.height ?? STATE_H,
5661
- isInitial: data.states.find((s) => s.name === n.id)?.isInitial,
5662
- isTerminal: data.states.find((s) => s.name === n.id)?.isTerminal
5663
- }));
6016
+ const nodeXMap = {};
6017
+ for (const n of layoutChildren) {
6018
+ nodeXMap[n.id] = n.x ?? 0;
6019
+ }
6020
+ const nodes = layoutChildren.map((n) => {
6021
+ const name = n.id;
6022
+ const stateInfo = data.states.find((s) => s.name === name);
6023
+ const tc = transitionCounts[name] ?? 0;
6024
+ return {
6025
+ id: name,
6026
+ x: n.x ?? 0,
6027
+ y: n.y ?? 0,
6028
+ width: n.width ?? 110,
6029
+ height: n.height ?? STATE_H,
6030
+ isInitial: stateInfo?.isInitial,
6031
+ isTerminal: stateInfo?.isTerminal,
6032
+ role: getStateRole(name, stateInfo?.isInitial, stateInfo?.isTerminal, tc, maxTC),
6033
+ transitionCount: tc
6034
+ };
6035
+ });
5664
6036
  const edges = layoutEdges.map((e, i) => {
5665
6037
  const t = data.transitions[i];
5666
6038
  const labels = e.labels ?? [];
@@ -5672,11 +6044,13 @@ async function computeLayout(data) {
5672
6044
  const endPoint = section.endPoint;
5673
6045
  const bendPoints = section.bendPoints ?? [];
5674
6046
  points.push({ x: startPoint.x, y: startPoint.y });
5675
- for (const bp of bendPoints) {
5676
- points.push({ x: bp.x, y: bp.y });
5677
- }
6047
+ for (const bp of bendPoints) points.push({ x: bp.x, y: bp.y });
5678
6048
  points.push({ x: endPoint.x, y: endPoint.y });
5679
6049
  }
6050
+ const isSelf = t.from === t.to;
6051
+ const isBackward = !isSelf && (nodeXMap[t.to] ?? 0) <= (nodeXMap[t.from] ?? 0);
6052
+ const lw = label?.width ?? LABEL_BASE_W;
6053
+ const lh = label?.height ?? LABEL_H;
5680
6054
  return {
5681
6055
  id: e.id,
5682
6056
  from: t.from,
@@ -5684,11 +6058,15 @@ async function computeLayout(data) {
5684
6058
  event: t.event,
5685
6059
  effects: t.effects,
5686
6060
  guard: !!t.guard,
6061
+ guardExpr: typeof t.guard === "string" ? t.guard : void 0,
5687
6062
  index: t.index,
5688
- labelX: (label?.x ?? 0) + (label?.width ?? 0) / 2,
5689
- labelY: (label?.y ?? 0) + (label?.height ?? 0) / 2,
6063
+ labelX: label?.x ?? 0,
6064
+ labelY: label?.y ?? 0,
6065
+ labelW: lw,
6066
+ labelH: lh,
5690
6067
  points,
5691
- isSelf: t.from === t.to
6068
+ isSelf,
6069
+ isBackward
5692
6070
  };
5693
6071
  });
5694
6072
  return {
@@ -5701,25 +6079,11 @@ async function computeLayout(data) {
5701
6079
  function edgePath(points) {
5702
6080
  if (points.length === 0) return "";
5703
6081
  let d = `M ${points[0].x},${points[0].y}`;
5704
- for (let i = 1; i < points.length; i++) {
5705
- d += ` L ${points[i].x},${points[i].y}`;
5706
- }
6082
+ for (let i = 1; i < points.length; i++) d += ` L ${points[i].x},${points[i].y}`;
5707
6083
  return d;
5708
6084
  }
5709
- function mapEffectType(label) {
5710
- const map = {
5711
- "render-ui": "render-ui",
5712
- set: "set",
5713
- persist: "persist",
5714
- fetch: "fetch",
5715
- emit: "emit",
5716
- navigate: "navigate",
5717
- notify: "notify",
5718
- "call-service": "call-service",
5719
- log: "log"
5720
- };
5721
- return map[label] ?? "log";
5722
- }
6085
+ var SWIM_GUTTER = 120;
6086
+ var CENTER_W = 360;
5723
6087
  var AvlTraitScene = ({
5724
6088
  data,
5725
6089
  color = "var(--color-primary)",
@@ -5733,113 +6097,60 @@ var AvlTraitScene = ({
5733
6097
  if (!layout) {
5734
6098
  return /* @__PURE__ */ jsxRuntime.jsx("g", { children: /* @__PURE__ */ jsxRuntime.jsx("text", { x: 300, y: 200, textAnchor: "middle", fill: color, fontSize: 12, opacity: 0.5, children: "Computing layout..." }) });
5735
6099
  }
5736
- const padding = 30;
5737
- const availW = 600 - padding * 2;
5738
- const availH = 340;
6100
+ const hasExternal = data.listenedEvents.length > 0 || data.emittedEvents.length > 0;
6101
+ const machineOffsetX = hasExternal ? 0 : 30;
6102
+ const padding = 20;
6103
+ const availW = CENTER_W - padding * 2;
6104
+ const availH = 300;
5739
6105
  const scale = Math.min(1, availW / layout.width, availH / layout.height);
5740
6106
  const scaledW = layout.width * scale;
5741
6107
  const scaledH = layout.height * scale;
5742
6108
  const offsetX = padding + (availW - scaledW) / 2;
5743
- const offsetY = 60 + (availH - scaledH) / 2;
5744
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5745
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: 300, y: 24, textAnchor: "middle", fill: color, fontSize: 16, fontWeight: "bold", children: data.name }),
5746
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: 300, y: 42, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, children: [
6109
+ const offsetY = 50 + (availH - scaledH) / 2;
6110
+ const machineHeight = scaledH + 100;
6111
+ const renderMachine = /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6112
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: CENTER_W / 2, y: 20, textAnchor: "middle", fill: color, fontSize: 20, fontWeight: "700", fontFamily: "inherit", children: data.name }),
6113
+ /* @__PURE__ */ jsxRuntime.jsxs("text", { x: CENTER_W / 2, y: 38, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, fontFamily: "inherit", children: [
5747
6114
  "linked to ",
5748
6115
  data.linkedEntity
5749
6116
  ] }),
5750
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "traitArrow", viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "6", markerHeight: "6", orient: "auto-start-reverse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: color, opacity: 0.6 }) }) }),
6117
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
6118
+ /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "traitArrowV2", viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "6", markerHeight: "6", orient: "auto-start-reverse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: CONNECTION_COLORS.forward.color, opacity: 0.7 }) }),
6119
+ /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "traitArrowBack", viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "6", markerHeight: "6", orient: "auto-start-reverse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: CONNECTION_COLORS.backward.color, opacity: 0.5 }) })
6120
+ ] }),
5751
6121
  /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${offsetX},${offsetY}) scale(${scale})`, children: [
5752
6122
  layout.edges.map((edge) => {
5753
- const hasEmit = edge.effects.some((e) => e.type === "emit");
6123
+ const conn = edge.isSelf ? CONNECTION_COLORS.selfLoop : edge.isBackward ? CONNECTION_COLORS.backward : CONNECTION_COLORS.forward;
6124
+ const marker = edge.isBackward || edge.isSelf ? "url(#traitArrowBack)" : "url(#traitArrowV2)";
5754
6125
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5755
6126
  /* @__PURE__ */ jsxRuntime.jsx(
5756
6127
  "path",
5757
6128
  {
5758
6129
  d: edgePath(edge.points),
5759
6130
  fill: "none",
5760
- stroke: color,
5761
- strokeWidth: 1.5,
5762
- opacity: 0.4,
5763
- markerEnd: "url(#traitArrow)"
6131
+ stroke: conn.color,
6132
+ strokeWidth: conn.width,
6133
+ strokeDasharray: conn.dash === "none" ? void 0 : conn.dash,
6134
+ opacity: 0.5,
6135
+ markerEnd: marker
5764
6136
  }
5765
6137
  ),
5766
- (() => {
5767
- const visibleEffects = edge.effects.slice(0, 4);
5768
- const textW = Math.max(edge.event.length * 7, 40);
5769
- const iconsW = visibleEffects.length * 14;
5770
- const cardW = Math.max(textW, iconsW) + 20;
5771
- const hasEffects = visibleEffects.length > 0;
5772
- const cardH = hasEffects ? 34 : 20;
5773
- const cardX = edge.labelX - cardW / 2;
5774
- const cardY = edge.labelY - 10;
5775
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5776
- /* @__PURE__ */ jsxRuntime.jsx(
5777
- "rect",
5778
- {
5779
- x: cardX,
5780
- y: cardY,
5781
- width: cardW,
5782
- height: cardH,
5783
- rx: 5,
5784
- fill: "var(--color-surface, white)",
5785
- stroke: color,
5786
- strokeWidth: 0.8,
5787
- opacity: 0.95
5788
- }
5789
- ),
5790
- /* @__PURE__ */ jsxRuntime.jsx(
5791
- "text",
5792
- {
5793
- x: edge.labelX,
5794
- y: cardY + 13,
5795
- textAnchor: "middle",
5796
- fill: color,
5797
- fontSize: 11,
5798
- fontWeight: "600",
5799
- children: edge.event
5800
- }
5801
- ),
5802
- hasEffects && /* @__PURE__ */ jsxRuntime.jsx("g", { children: visibleEffects.map((eff, ei) => {
5803
- const iconX = edge.labelX - (visibleEffects.length - 1) * 7 + ei * 14;
5804
- return /* @__PURE__ */ jsxRuntime.jsx(
5805
- AvlEffect,
5806
- {
5807
- x: iconX,
5808
- y: cardY + 25,
5809
- effectType: mapEffectType(eff.type),
5810
- size: 9,
5811
- color
5812
- },
5813
- `${edge.id}-eff-${ei}`
5814
- );
5815
- }) }),
5816
- edge.guard && /* @__PURE__ */ jsxRuntime.jsx(
5817
- AvlGuard,
5818
- {
5819
- x: cardX + cardW - 10,
5820
- y: cardY + 10,
5821
- label: "",
5822
- color,
5823
- size: 6
5824
- }
5825
- ),
5826
- hasEmit && /* @__PURE__ */ jsxRuntime.jsxs("circle", { cx: cardX - 8, cy: cardY + cardH / 2, r: 3, fill: color, opacity: 0.5, children: [
5827
- /* @__PURE__ */ jsxRuntime.jsx("animate", { attributeName: "r", values: "2;5;2", dur: "1.5s", repeatCount: "indefinite" }),
5828
- /* @__PURE__ */ jsxRuntime.jsx("animate", { attributeName: "opacity", values: "0.5;0.15;0.5", dur: "1.5s", repeatCount: "indefinite" })
5829
- ] })
5830
- ] });
5831
- })(),
5832
- onTransitionClick && /* @__PURE__ */ jsxRuntime.jsx(
5833
- AvlClickTarget,
6138
+ /* @__PURE__ */ jsxRuntime.jsx(
6139
+ AvlTransitionLane,
5834
6140
  {
5835
- x: edge.labelX - 50,
5836
- y: edge.labelY - 15,
5837
- width: 100,
5838
- height: 30,
5839
- onClick: () => onTransitionClick(edge.index, { x: edge.labelX + offsetX, y: edge.labelY + offsetY }),
5840
- label: `${edge.event}: ${edge.from} -> ${edge.to}`,
5841
- glowColor: color,
5842
- children: /* @__PURE__ */ jsxRuntime.jsx("rect", { x: 0, y: 0, width: 0, height: 0, fill: "transparent" })
6141
+ x: edge.labelX,
6142
+ y: edge.labelY,
6143
+ event: edge.event,
6144
+ guard: edge.guardExpr,
6145
+ effects: edge.effects.map((e) => ({ type: e.type })),
6146
+ width: edge.labelW,
6147
+ isBackward: edge.isBackward,
6148
+ isSelfLoop: edge.isSelf,
6149
+ color,
6150
+ onTransitionClick: onTransitionClick ? () => onTransitionClick(edge.index, {
6151
+ x: edge.labelX + offsetX + (hasExternal ? SWIM_GUTTER : machineOffsetX),
6152
+ y: edge.labelY + offsetY
6153
+ }) : void 0
5843
6154
  }
5844
6155
  )
5845
6156
  ] }, edge.id);
@@ -5854,223 +6165,263 @@ var AvlTraitScene = ({
5854
6165
  name: node.id,
5855
6166
  isInitial: node.isInitial,
5856
6167
  isTerminal: node.isTerminal,
6168
+ role: node.role,
6169
+ transitionCount: node.transitionCount,
5857
6170
  color
5858
6171
  }
5859
6172
  ) }, node.id))
5860
- ] }),
5861
- data.emittedEvents.map((evt, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5862
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: 450, y1: 55 + i * 22, x2: 585, y2: 55 + i * 22, stroke: color, strokeWidth: 1, strokeDasharray: "4 3", opacity: 0.3 }),
5863
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: 588, y: 59 + i * 22, fill: color, fontSize: 10, opacity: 0.5, children: [
5864
- "emit: ",
5865
- evt
5866
- ] })
5867
- ] }, `emit-${i}`)),
5868
- data.listenedEvents.map((evt, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5869
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: 15, y1: 55 + i * 22, x2: 150, y2: 55 + i * 22, stroke: color, strokeWidth: 1, strokeDasharray: "4 3", opacity: 0.3 }),
5870
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: 5, y: 59 + i * 22, fill: color, fontSize: 10, opacity: 0.5, children: [
5871
- "listen: ",
5872
- evt
5873
- ] })
5874
- ] }, `listen-${i}`))
6173
+ ] })
5875
6174
  ] });
6175
+ if (!hasExternal) {
6176
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${machineOffsetX}, 0)`, children: renderMachine });
6177
+ }
6178
+ return /* @__PURE__ */ jsxRuntime.jsx(
6179
+ AvlSwimLane,
6180
+ {
6181
+ listenedEvents: data.listenedEvents,
6182
+ emittedEvents: data.emittedEvents,
6183
+ centerWidth: CENTER_W,
6184
+ height: machineHeight,
6185
+ color,
6186
+ children: renderMachine
6187
+ }
6188
+ );
5876
6189
  };
5877
6190
  AvlTraitScene.displayName = "AvlTraitScene";
5878
6191
  var CX2 = 300;
5879
- var STATE_W2 = 120;
5880
- var STATE_H2 = 40;
5881
- var CARD_W = 140;
5882
- function mapEffectType2(label) {
5883
- const map = {
5884
- "render-ui": "render-ui",
5885
- set: "set",
5886
- persist: "persist",
5887
- fetch: "fetch",
5888
- emit: "emit",
5889
- navigate: "navigate",
5890
- notify: "notify",
5891
- "call-service": "call-service",
5892
- log: "log"
5893
- };
5894
- return map[label] ?? "log";
5895
- }
5896
- function EffectNode({ node, x, y, color, id }) {
5897
- if (node.type === "operator") {
5898
- const children = node.children ?? [];
5899
- const maxLabelLen = Math.max(...children.map((c) => c.label.length), 4);
5900
- const childSpacing = Math.max(90, maxLabelLen * 8 + 20);
5901
- const totalW = (children.length - 1) * childSpacing;
5902
- const startX = x - totalW / 2;
5903
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5904
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: x - 30, y: y - 10, width: 60, height: 20, rx: 4, fill: "var(--color-surface, white)", stroke: color, strokeWidth: 0.8 }),
5905
- /* @__PURE__ */ jsxRuntime.jsx(AvlEffect, { x: x - 16, y, effectType: mapEffectType2(node.label), size: 10, color }),
5906
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: x + 2, y: y + 4, fill: color, fontSize: 9, fontWeight: "500", children: node.label }),
5907
- children.map((child, i) => {
5908
- const cx = startX + i * childSpacing;
5909
- const cy = y + 40;
5910
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5911
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: x, y1: y + 10, x2: cx, y2: cy - 10, stroke: color, strokeWidth: 0.8, opacity: 0.3 }),
5912
- /* @__PURE__ */ jsxRuntime.jsx(EffectNode, { node: child, x: cx, y: cy, color, id: `${id}-${i}` })
5913
- ] }, `${id}-${i}`);
5914
- })
5915
- ] });
6192
+ var CARD_W = 440;
6193
+ var CARD_X = CX2 - CARD_W / 2;
6194
+ var SECTION_LEFT = CARD_X + 16;
6195
+ var CONTENT_LEFT = CARD_X + 24;
6196
+ function flattenEffect(node) {
6197
+ const args = [];
6198
+ for (const child of node.children ?? []) {
6199
+ args.push(child.label);
5916
6200
  }
5917
- const isBinding = node.type === "binding";
5918
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5919
- /* @__PURE__ */ jsxRuntime.jsx(
5920
- "circle",
5921
- {
5922
- cx: x,
5923
- cy: y,
5924
- r: isBinding ? 6 : 5,
5925
- fill: isBinding ? "none" : color,
5926
- opacity: isBinding ? 1 : 0.15,
5927
- stroke: color,
5928
- strokeWidth: 1,
5929
- strokeDasharray: isBinding ? "2 1.5" : "none"
5930
- }
5931
- ),
5932
- /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: y + 16, textAnchor: "middle", fill: color, fontSize: 8, opacity: 0.7, children: node.label })
5933
- ] });
6201
+ return { type: node.label, args };
6202
+ }
6203
+ function mapEffectType(label) {
6204
+ const valid = [
6205
+ "render-ui",
6206
+ "set",
6207
+ "persist",
6208
+ "fetch",
6209
+ "emit",
6210
+ "navigate",
6211
+ "notify",
6212
+ "call-service",
6213
+ "spawn",
6214
+ "despawn",
6215
+ "do",
6216
+ "if",
6217
+ "log"
6218
+ ];
6219
+ return valid.includes(label) ? label : "log";
5934
6220
  }
5935
6221
  var AvlTransitionScene = ({
5936
6222
  data,
5937
6223
  color = "var(--color-primary)"
5938
6224
  }) => {
5939
- let curY = 30;
5940
- const fromY = curY;
5941
- curY += STATE_H2;
5942
- curY += 15;
5943
- const eventY = curY;
5944
- const eventH = 24;
5945
- curY += eventH + 8;
5946
- const guardY = curY;
6225
+ const fromRole = getStateRole(data.from, true);
6226
+ const toRole = getStateRole(data.to, false, false);
6227
+ const fromColors = STATE_COLORS[fromRole];
6228
+ const toColors = STATE_COLORS[toRole];
5947
6229
  const hasGuard = !!data.guard;
5948
- if (hasGuard) {
5949
- curY += 24 + 8;
5950
- }
5951
- curY += 15;
5952
- const effectsY = curY;
5953
6230
  const hasEffects = data.effects.length > 0;
5954
- const effectsH = hasEffects ? 80 : 0;
5955
- if (hasEffects) curY += effectsH + 8;
5956
- const slotsY = curY;
5957
6231
  const hasSlots = data.slotTargets.length > 0;
5958
- const slotsH = hasSlots ? 30 : 0;
5959
- if (hasSlots) curY += slotsH + 8;
5960
- curY += 15;
5961
- const toY = curY;
5962
- curY += STATE_H2;
5963
- const totalH = curY;
5964
- const offsetY = Math.max(0, (400 - totalH) / 2);
5965
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(0,${offsetY})`, children: [
5966
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "transArrow", viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "5", markerHeight: "5", orient: "auto-start-reverse", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: color, opacity: 0.5 }) }) }),
5967
- /* @__PURE__ */ jsxRuntime.jsx(AvlState, { x: CX2 - STATE_W2 / 2, y: fromY, width: STATE_W2, height: STATE_H2, name: data.from, isInitial: true, color }),
5968
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: CX2, y1: fromY + STATE_H2, x2: CX2, y2: eventY - 2, stroke: color, strokeWidth: 1.5, opacity: 0.4, markerEnd: "url(#transArrow)" }),
6232
+ const effects = data.effects.map(flattenEffect);
6233
+ const headerH = 52;
6234
+ const sectionGap = 8;
6235
+ const triggerH = 34;
6236
+ const guardH = hasGuard ? 30 + sectionGap : 0;
6237
+ const effectRowH = 28;
6238
+ const effectsH = hasEffects ? 24 + effects.length * effectRowH + sectionGap : 0;
6239
+ const slotsH = hasSlots ? 24 + data.slotTargets.length * 22 + sectionGap : 0;
6240
+ const cardH = headerH + triggerH + guardH + effectsH + slotsH + 16;
6241
+ const cardY = Math.max(20, (400 - cardH) / 2);
6242
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5969
6243
  /* @__PURE__ */ jsxRuntime.jsx(
5970
6244
  "rect",
5971
6245
  {
5972
- x: CX2 - CARD_W / 2,
5973
- y: eventY,
6246
+ x: CARD_X,
6247
+ y: cardY,
5974
6248
  width: CARD_W,
5975
- height: eventH,
5976
- rx: 5,
6249
+ height: cardH,
6250
+ rx: 12,
5977
6251
  fill: "var(--color-surface, white)",
6252
+ fillOpacity: 0.97,
5978
6253
  stroke: color,
5979
- strokeWidth: 1
6254
+ strokeWidth: 0.8,
6255
+ strokeOpacity: 0.2
5980
6256
  }
5981
6257
  ),
5982
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: CX2, y: eventY + 15, textAnchor: "middle", fill: color, fontSize: 13, fontWeight: "700", children: data.event }),
5983
- hasGuard && data.guard && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
5984
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: CX2, y1: eventY + eventH, x2: CX2, y2: guardY - 2, stroke: color, strokeWidth: 1, opacity: 0.3 }),
5985
- /* @__PURE__ */ jsxRuntime.jsx(
5986
- "rect",
5987
- {
5988
- x: CX2 - 50,
5989
- y: guardY,
5990
- width: 100,
5991
- height: 20,
5992
- rx: 4,
5993
- fill: "var(--color-surface, white)",
5994
- stroke: color,
5995
- strokeWidth: 0.8,
5996
- opacity: 0.9
5997
- }
5998
- ),
5999
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: CX2 - 6, y: guardY + 14, textAnchor: "middle", fill: color, fontSize: 10, children: data.guard.label }),
6000
- /* @__PURE__ */ jsxRuntime.jsx(
6001
- "polygon",
6002
- {
6003
- points: `${CX2 - 40},${guardY + 10} ${CX2 - 46},${guardY + 10 - 5} ${CX2 - 40},${guardY + 10 - 10} ${CX2 - 34},${guardY + 10 - 5}`,
6004
- fill: color,
6005
- opacity: 0.2,
6006
- stroke: color,
6007
- strokeWidth: 0.8
6008
- }
6009
- )
6010
- ] }),
6011
6258
  /* @__PURE__ */ jsxRuntime.jsx(
6012
- "line",
6259
+ "rect",
6013
6260
  {
6014
- x1: CX2,
6015
- y1: hasGuard ? guardY + 20 : eventY + eventH,
6016
- x2: CX2,
6017
- y2: hasEffects ? effectsY - 8 : hasSlots ? slotsY - 8 : toY - 2,
6018
- stroke: color,
6019
- strokeWidth: 1.5,
6261
+ x: CARD_X,
6262
+ y: cardY,
6263
+ width: CARD_W,
6264
+ height: headerH,
6265
+ rx: 12,
6266
+ fill: color,
6267
+ fillOpacity: 0.03
6268
+ }
6269
+ ),
6270
+ /* @__PURE__ */ jsxRuntime.jsx(
6271
+ "rect",
6272
+ {
6273
+ x: CARD_X,
6274
+ y: cardY + headerH - 12,
6275
+ width: CARD_W,
6276
+ height: 12,
6277
+ fill: color,
6278
+ fillOpacity: 0.03
6279
+ }
6280
+ ),
6281
+ /* @__PURE__ */ jsxRuntime.jsx(
6282
+ "rect",
6283
+ {
6284
+ x: CARD_X + 20,
6285
+ y: cardY + 12,
6286
+ width: 140,
6287
+ height: 30,
6288
+ rx: 15,
6289
+ fill: fromColors.fill,
6290
+ stroke: fromColors.border,
6291
+ strokeWidth: 1.5
6292
+ }
6293
+ ),
6294
+ /* @__PURE__ */ jsxRuntime.jsx(
6295
+ "text",
6296
+ {
6297
+ x: CARD_X + 90,
6298
+ y: cardY + 31,
6299
+ textAnchor: "middle",
6300
+ fill: fromColors.border,
6301
+ fontSize: 14,
6302
+ fontWeight: 600,
6303
+ fontFamily: "inherit",
6304
+ children: data.from
6305
+ }
6306
+ ),
6307
+ /* @__PURE__ */ jsxRuntime.jsx(
6308
+ "text",
6309
+ {
6310
+ x: CX2,
6311
+ y: cardY + 32,
6312
+ textAnchor: "middle",
6313
+ fill: color,
6314
+ fontSize: 16,
6020
6315
  opacity: 0.4,
6021
- markerEnd: "url(#transArrow)"
6316
+ fontFamily: "inherit",
6317
+ children: "\u2192"
6022
6318
  }
6023
6319
  ),
6024
- hasEffects && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6025
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: CX2, y: effectsY - 2, textAnchor: "middle", fill: color, fontSize: 9, fontWeight: "600", opacity: 0.5, children: "EFFECTS" }),
6026
- data.effects.map((effect, i) => {
6027
- const effectSpacing = 130;
6028
- const effectX = CX2 - (data.effects.length - 1) * effectSpacing / 2 + i * effectSpacing;
6029
- return /* @__PURE__ */ jsxRuntime.jsx(EffectNode, { node: effect, x: effectX, y: effectsY + 20, color, id: `eff-${i}` }, `eff-${i}`);
6030
- })
6031
- ] }),
6032
- hasSlots && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6033
- hasEffects && /* @__PURE__ */ jsxRuntime.jsx("line", { x1: CX2, y1: effectsY + effectsH - 10, x2: CX2, y2: slotsY - 4, stroke: color, strokeWidth: 1, opacity: 0.3 }),
6034
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: CX2, y: slotsY - 2, textAnchor: "middle", fill: color, fontSize: 9, fontWeight: "600", opacity: 0.5, children: "SLOTS" }),
6035
- data.slotTargets.map((slot, i) => {
6036
- const sx = CX2 - (data.slotTargets.length - 1) * 90 / 2 + i * 90;
6037
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6038
- /* @__PURE__ */ jsxRuntime.jsx(
6039
- "rect",
6040
- {
6041
- x: sx - 35,
6042
- y: slotsY + 4,
6043
- width: 70,
6044
- height: 20,
6045
- rx: 4,
6046
- fill: color,
6047
- opacity: 0.08,
6048
- stroke: color,
6049
- strokeWidth: 0.8
6050
- }
6051
- ),
6052
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: sx, y: slotsY + 17, textAnchor: "middle", fill: color, fontSize: 9, children: [
6053
- slot.name,
6054
- ": ",
6055
- slot.pattern
6056
- ] })
6057
- ] }, `slot-${i}`);
6058
- })
6059
- ] }),
6060
- (hasEffects || hasSlots) && /* @__PURE__ */ jsxRuntime.jsx(
6320
+ /* @__PURE__ */ jsxRuntime.jsx(
6321
+ "rect",
6322
+ {
6323
+ x: CARD_X + CARD_W - 160,
6324
+ y: cardY + 12,
6325
+ width: 140,
6326
+ height: 30,
6327
+ rx: 15,
6328
+ fill: toColors.fill,
6329
+ stroke: toColors.border,
6330
+ strokeWidth: 1.5
6331
+ }
6332
+ ),
6333
+ /* @__PURE__ */ jsxRuntime.jsx(
6334
+ "text",
6335
+ {
6336
+ x: CARD_X + CARD_W - 90,
6337
+ y: cardY + 31,
6338
+ textAnchor: "middle",
6339
+ fill: toColors.border,
6340
+ fontSize: 14,
6341
+ fontWeight: 600,
6342
+ fontFamily: "inherit",
6343
+ children: data.to
6344
+ }
6345
+ ),
6346
+ /* @__PURE__ */ jsxRuntime.jsx(
6061
6347
  "line",
6062
6348
  {
6063
- x1: CX2,
6064
- y1: hasSlots ? slotsY + slotsH : effectsY + effectsH - 10,
6065
- x2: CX2,
6066
- y2: toY - 2,
6349
+ x1: CARD_X + 12,
6350
+ y1: cardY + headerH,
6351
+ x2: CARD_X + CARD_W - 12,
6352
+ y2: cardY + headerH,
6067
6353
  stroke: color,
6068
- strokeWidth: 1.5,
6069
- opacity: 0.4,
6070
- markerEnd: "url(#transArrow)"
6354
+ strokeWidth: 0.5,
6355
+ opacity: 0.1
6071
6356
  }
6072
6357
  ),
6073
- /* @__PURE__ */ jsxRuntime.jsx(AvlState, { x: CX2 - STATE_W2 / 2, y: toY, width: STATE_W2, height: STATE_H2, name: data.to, color })
6358
+ (() => {
6359
+ const secY = cardY + headerH + sectionGap;
6360
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6361
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: SECTION_LEFT, y: secY + 12, fill: color, fontSize: 10, fontWeight: 600, opacity: 0.4, fontFamily: "inherit", children: "TRIGGER" }),
6362
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: CONTENT_LEFT + 14, y: secY + 28, fill: color, fontSize: 14, fontWeight: 600, fontFamily: "inherit", children: data.event }),
6363
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: CONTENT_LEFT + 4, y: secY + 28, fill: color, fontSize: 10, opacity: 0.5, children: "\u26A1" })
6364
+ ] });
6365
+ })(),
6366
+ hasGuard && data.guard && (() => {
6367
+ const secY = cardY + headerH + sectionGap + triggerH;
6368
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6369
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: SECTION_LEFT, y: secY + 12, fill: color, fontSize: 10, fontWeight: 600, opacity: 0.4, fontFamily: "inherit", children: "GUARD" }),
6370
+ /* @__PURE__ */ jsxRuntime.jsx(
6371
+ "polygon",
6372
+ {
6373
+ points: `${CONTENT_LEFT + 6},${secY + 22} ${CONTENT_LEFT + 2},${secY + 26} ${CONTENT_LEFT + 6},${secY + 30} ${CONTENT_LEFT + 10},${secY + 26}`,
6374
+ fill: "none",
6375
+ stroke: color,
6376
+ strokeWidth: 1,
6377
+ opacity: 0.5
6378
+ }
6379
+ ),
6380
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: CONTENT_LEFT + 18, y: secY + 29, fill: color, fontSize: 12, fontWeight: 400, opacity: 0.6, fontFamily: "inherit", children: data.guard.label })
6381
+ ] });
6382
+ })(),
6383
+ hasEffects && (() => {
6384
+ const secY = cardY + headerH + sectionGap + triggerH + guardH;
6385
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6386
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: SECTION_LEFT, y: secY + 12, fill: color, fontSize: 10, fontWeight: 600, opacity: 0.4, fontFamily: "inherit", children: "EFFECTS" }),
6387
+ effects.map((eff, i) => {
6388
+ const rowY = secY + 22 + i * effectRowH;
6389
+ const effectType = mapEffectType(eff.type);
6390
+ const argsText = eff.args.length > 0 ? eff.args.join(" \xB7 ") : "";
6391
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6392
+ /* @__PURE__ */ jsxRuntime.jsx(
6393
+ AvlEffect,
6394
+ {
6395
+ x: CONTENT_LEFT + 10,
6396
+ y: rowY + 6,
6397
+ effectType,
6398
+ size: 10,
6399
+ showBackground: true
6400
+ }
6401
+ ),
6402
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: CONTENT_LEFT + 28, y: rowY + 10, fill: color, fontSize: 12, fontWeight: 500, opacity: 0.8, fontFamily: "inherit", children: eff.type }),
6403
+ argsText && /* @__PURE__ */ jsxRuntime.jsx("text", { x: CONTENT_LEFT + 28 + eff.type.length * 7 + 8, y: rowY + 10, fill: color, fontSize: 10, fontWeight: 400, opacity: 0.5, fontFamily: "monospace", children: argsText })
6404
+ ] }, `eff-${i}`);
6405
+ })
6406
+ ] });
6407
+ })(),
6408
+ hasSlots && (() => {
6409
+ const secY = cardY + headerH + sectionGap + triggerH + guardH + effectsH;
6410
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6411
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: SECTION_LEFT, y: secY + 12, fill: color, fontSize: 10, fontWeight: 600, opacity: 0.4, fontFamily: "inherit", children: "SLOTS" }),
6412
+ data.slotTargets.map((slot, i) => {
6413
+ const rowY = secY + 22 + i * 22;
6414
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
6415
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: CONTENT_LEFT, y: rowY - 4, width: CARD_W - 56, height: 18, rx: 4, fill: color, fillOpacity: 0.04 }),
6416
+ /* @__PURE__ */ jsxRuntime.jsxs("text", { x: CONTENT_LEFT + 8, y: rowY + 8, fill: color, fontSize: 11, fontFamily: "inherit", children: [
6417
+ slot.name,
6418
+ ": ",
6419
+ slot.pattern
6420
+ ] })
6421
+ ] }, `slot-${i}`);
6422
+ })
6423
+ ] });
6424
+ })()
6074
6425
  ] });
6075
6426
  };
6076
6427
  AvlTransitionScene.displayName = "AvlTransitionScene";
@@ -6499,8 +6850,13 @@ exports.AvlTrait = AvlTrait;
6499
6850
  exports.AvlTraitScene = AvlTraitScene;
6500
6851
  exports.AvlTransition = AvlTransition;
6501
6852
  exports.AvlTransitionScene = AvlTransitionScene;
6853
+ exports.CONNECTION_COLORS = CONNECTION_COLORS;
6854
+ exports.EFFECT_CATEGORY_COLORS = EFFECT_CATEGORY_COLORS;
6855
+ exports.EFFECT_TYPE_TO_CATEGORY = EFFECT_TYPE_TO_CATEGORY;
6856
+ exports.STATE_COLORS = STATE_COLORS;
6502
6857
  exports.arcPath = arcPath;
6503
6858
  exports.curveControlPoint = curveControlPoint;
6859
+ exports.getStateRole = getStateRole;
6504
6860
  exports.gridPositions = gridPositions;
6505
6861
  exports.parseApplicationLevel = parseApplicationLevel;
6506
6862
  exports.parseOrbitalLevel = parseOrbitalLevel;