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