@almadar/ui 4.54.5 → 4.54.7

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
@@ -50994,6 +50994,22 @@ function zoomReducer(state, action) {
50994
50994
  selectedTransition: action.transitionIndex
50995
50995
  };
50996
50996
  }
50997
+ case "JUMP_TO_TRAIT_CIRCUIT": {
50998
+ if (state.level !== "application" || state.animating) return state;
50999
+ return {
51000
+ ...state,
51001
+ level: "trait",
51002
+ selectedOrbital: action.orbital,
51003
+ selectedTrait: null,
51004
+ selectedTransition: null,
51005
+ animating: false,
51006
+ animationDirection: "in",
51007
+ animationTarget: null
51008
+ };
51009
+ }
51010
+ case "SELECT_TRAIT": {
51011
+ return { ...state, selectedTrait: action.trait };
51012
+ }
50997
51013
  case "ZOOM_OUT": {
50998
51014
  if (state.level === "application" || state.animating) return state;
50999
51015
  return {
@@ -51026,7 +51042,8 @@ function zoomReducer(state, action) {
51026
51042
  if (state.level === "trait") {
51027
51043
  return {
51028
51044
  ...state,
51029
- level: "orbital",
51045
+ level: "application",
51046
+ selectedOrbital: null,
51030
51047
  selectedTrait: null,
51031
51048
  animating: false,
51032
51049
  animationTarget: null
@@ -57418,8 +57435,8 @@ function isBackwardTransition(from, to, states) {
57418
57435
  if (fromIdx === -1 || toIdx === -1) return false;
57419
57436
  return toIdx < fromIdx;
57420
57437
  }
57421
- function findCrossLinks(orbitals) {
57422
- const links = [];
57438
+ function extractTraitWires(orbitals, scope) {
57439
+ const wires = [];
57423
57440
  const emitters = [];
57424
57441
  const listeners6 = [];
57425
57442
  for (const orb of orbitals) {
@@ -57435,11 +57452,14 @@ function findCrossLinks(orbitals) {
57435
57452
  const seen = /* @__PURE__ */ new Set();
57436
57453
  for (const em of emitters) {
57437
57454
  for (const li of listeners6) {
57438
- if (em.event !== li.event || em.orbital === li.orbital) continue;
57439
- const key = `${em.orbital}\u241F${li.orbital}\u241F${em.event}`;
57455
+ if (em.event !== li.event) continue;
57456
+ if (scope === "cross-orbital" && em.orbital === li.orbital) continue;
57457
+ if (scope === "intra-orbital" && em.orbital !== li.orbital) continue;
57458
+ if (scope === "intra-orbital" && em.trait === li.trait) continue;
57459
+ const key = scope === "cross-orbital" ? `${em.orbital}\u241F${li.orbital}\u241F${em.event}` : `${em.orbital}\u241F${em.trait}\u241F${li.trait}\u241F${em.event}`;
57440
57460
  if (seen.has(key)) continue;
57441
57461
  seen.add(key);
57442
- links.push({
57462
+ wires.push({
57443
57463
  emitterOrbital: em.orbital,
57444
57464
  listenerOrbital: li.orbital,
57445
57465
  event: em.event,
@@ -57448,7 +57468,10 @@ function findCrossLinks(orbitals) {
57448
57468
  });
57449
57469
  }
57450
57470
  }
57451
- return links;
57471
+ return wires;
57472
+ }
57473
+ function findCrossLinks(orbitals) {
57474
+ return extractTraitWires(orbitals, "cross-orbital");
57452
57475
  }
57453
57476
  function schemaToOverviewGraph(schema, mockData, behaviorMeta, layoutHint, orbitalStatus) {
57454
57477
  const orbitals = getOrbitals(schema);
@@ -57748,6 +57771,71 @@ function orbitalAliasToExpandedGraph(schema, orbitalName, alias, mockData) {
57748
57771
  mockData
57749
57772
  );
57750
57773
  }
57774
+ var TRAIT_CARD_SPACING_X = 480;
57775
+ var TRAIT_CARD_SPACING_Y = 380;
57776
+ function orbitalToTraitGraph(schema, orbitalName, _mockData) {
57777
+ const orbital = getOrbitals(schema).find((o) => o.name === orbitalName);
57778
+ if (!orbital) return { nodes: [], edges: [] };
57779
+ const traits2 = getTraits2(orbital);
57780
+ const nodes = [];
57781
+ const count = traits2.length;
57782
+ const cols = Math.max(1, Math.ceil(Math.sqrt(count)));
57783
+ for (let i = 0; i < traits2.length; i++) {
57784
+ const trait = traits2[i];
57785
+ const sm = getStateMachine2(trait);
57786
+ const transitions = (sm?.transitions ?? []).map((t) => ({
57787
+ event: t.event,
57788
+ fromState: Array.isArray(t.from) ? t.from.join("|") : t.from,
57789
+ toState: t.to
57790
+ }));
57791
+ const emits = getEmits2(trait);
57792
+ const listens = getListens2(trait);
57793
+ const linkedEntity = trait.linkedEntity ?? "";
57794
+ const row = Math.floor(i / cols);
57795
+ const col = i % cols;
57796
+ nodes.push({
57797
+ id: `trait-${orbitalName}-${trait.name}`,
57798
+ type: "traitCard",
57799
+ position: {
57800
+ x: col * TRAIT_CARD_SPACING_X,
57801
+ y: row * TRAIT_CARD_SPACING_Y
57802
+ },
57803
+ data: {
57804
+ kind: "trait-card",
57805
+ orbitalName,
57806
+ traitName: trait.name,
57807
+ linkedEntity,
57808
+ transitions,
57809
+ emits,
57810
+ listens,
57811
+ // `_fullSchema` carries the parsed schema to `TraitCardNode` so it
57812
+ // can run `parseTraitLevel(...)` and render the ELK-laid-out
57813
+ // state-machine flow chart inside the card. Mirrors the same
57814
+ // convention `OrbPreviewNode` uses for its embedded UI preview.
57815
+ _fullSchema: schema,
57816
+ // Required fields on PreviewNodeData — keep empty for trait cards.
57817
+ patterns: [],
57818
+ eventSources: []
57819
+ }
57820
+ });
57821
+ }
57822
+ const wires = extractTraitWires([orbital], "intra-orbital");
57823
+ const edges = wires.map((w) => ({
57824
+ id: `wire-${orbitalName}-${w.emitterTrait}-${w.listenerTrait}-${w.event}`,
57825
+ source: `trait-${orbitalName}-${w.emitterTrait}`,
57826
+ target: `trait-${orbitalName}-${w.listenerTrait}`,
57827
+ sourceHandle: `emit-${w.event}`,
57828
+ targetHandle: `listen-${w.event}`,
57829
+ type: "eventFlow",
57830
+ data: {
57831
+ event: w.event,
57832
+ isCrossOrbital: false,
57833
+ fromTrait: w.emitterTrait,
57834
+ toTrait: w.listenerTrait
57835
+ }
57836
+ }));
57837
+ return { nodes, edges };
57838
+ }
57751
57839
 
57752
57840
  // components/molecules/avl/OrbPreviewNode.tsx
57753
57841
  init_Box();
@@ -61786,11 +61874,225 @@ function TokenRow({ group, tokenKey, value, isColor, onPropChange }) {
61786
61874
  // components/organisms/avl/FlowCanvas.tsx
61787
61875
  init_Box();
61788
61876
  init_Typography();
61877
+
61878
+ // components/molecules/avl/TraitCardNode.tsx
61879
+ init_Box();
61880
+ init_Stack();
61881
+ init_Typography();
61882
+ init_Badge();
61883
+
61884
+ // components/organisms/avl/AvlTraitScene.tsx
61885
+ init_AvlState();
61886
+ init_AvlTransitionLane();
61887
+ init_AvlSwimLane();
61888
+ init_types();
61889
+ init_avl_elk_layout();
61890
+ var log19 = createLogger("almadar:ui:avl:trait-scene");
61891
+ var SWIM_GUTTER2 = 120;
61892
+ var CENTER_W2 = 360;
61893
+ var AvlTraitScene = ({
61894
+ data,
61895
+ color = "var(--color-primary)",
61896
+ onTransitionClick
61897
+ }) => {
61898
+ const [layout, setLayout] = useState(null);
61899
+ const dataKey = useMemo(() => JSON.stringify(data), [data]);
61900
+ useEffect(() => {
61901
+ computeTraitLayout(data).then(setLayout).catch((error) => {
61902
+ log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61903
+ });
61904
+ }, [dataKey]);
61905
+ if (!layout) {
61906
+ return /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx("text", { x: 300, y: 200, textAnchor: "middle", fill: color, fontSize: 12, opacity: 0.5, children: "Computing layout..." }) });
61907
+ }
61908
+ const hasExternal = data.listenedEvents.length > 0 || data.emittedEvents.length > 0;
61909
+ const machineOffsetX = hasExternal ? 0 : 30;
61910
+ const padding = 20;
61911
+ const availW = CENTER_W2 - padding * 2;
61912
+ const availH = 300;
61913
+ const scale = Math.min(1, availW / layout.width, availH / layout.height);
61914
+ const scaledW = layout.width * scale;
61915
+ const scaledH = layout.height * scale;
61916
+ const offsetX = padding + (availW - scaledW) / 2;
61917
+ const offsetY = 50 + (availH - scaledH) / 2;
61918
+ const machineHeight = scaledH + 100;
61919
+ const renderMachine = /* @__PURE__ */ jsxs("g", { children: [
61920
+ /* @__PURE__ */ jsx("text", { x: CENTER_W2 / 2, y: 20, textAnchor: "middle", fill: color, fontSize: 20, fontWeight: "700", fontFamily: "inherit", children: data.name }),
61921
+ /* @__PURE__ */ jsxs("text", { x: CENTER_W2 / 2, y: 38, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, fontFamily: "inherit", children: [
61922
+ "linked to ",
61923
+ data.linkedEntity
61924
+ ] }),
61925
+ /* @__PURE__ */ jsxs("defs", { children: [
61926
+ /* @__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 }) }),
61927
+ /* @__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 }) })
61928
+ ] }),
61929
+ /* @__PURE__ */ jsxs("g", { transform: `translate(${offsetX},${offsetY}) scale(${scale})`, children: [
61930
+ layout.edges.map((edge) => {
61931
+ const conn = edge.isSelf ? CONNECTION_COLORS.selfLoop : edge.isBackward ? CONNECTION_COLORS.backward : CONNECTION_COLORS.forward;
61932
+ const marker = edge.isBackward || edge.isSelf ? "url(#traitArrowBack)" : "url(#traitArrowV2)";
61933
+ return /* @__PURE__ */ jsxs("g", { children: [
61934
+ /* @__PURE__ */ jsx(
61935
+ "path",
61936
+ {
61937
+ d: edgePath(edge.points),
61938
+ fill: "none",
61939
+ stroke: conn.color,
61940
+ strokeWidth: conn.width,
61941
+ strokeDasharray: conn.dash === "none" ? void 0 : conn.dash,
61942
+ opacity: 0.5,
61943
+ markerEnd: marker
61944
+ }
61945
+ ),
61946
+ /* @__PURE__ */ jsx(
61947
+ AvlTransitionLane,
61948
+ {
61949
+ x: edge.labelX,
61950
+ y: edge.labelY,
61951
+ event: edge.event,
61952
+ guard: edge.guardExpr,
61953
+ effects: edge.effects.map((e) => ({ type: e.type })),
61954
+ width: edge.labelW,
61955
+ isBackward: edge.isBackward,
61956
+ isSelfLoop: edge.isSelf,
61957
+ color,
61958
+ onTransitionClick: onTransitionClick ? () => onTransitionClick(edge.index, {
61959
+ x: edge.labelX + offsetX + (hasExternal ? SWIM_GUTTER2 : machineOffsetX),
61960
+ y: edge.labelY + offsetY
61961
+ }) : void 0
61962
+ }
61963
+ )
61964
+ ] }, edge.id);
61965
+ }),
61966
+ layout.nodes.map((node) => /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx(
61967
+ AvlState,
61968
+ {
61969
+ x: node.x,
61970
+ y: node.y,
61971
+ width: node.width,
61972
+ height: node.height,
61973
+ name: node.id,
61974
+ isInitial: node.isInitial,
61975
+ isTerminal: node.isTerminal,
61976
+ role: node.role,
61977
+ transitionCount: node.transitionCount,
61978
+ color
61979
+ }
61980
+ ) }, node.id))
61981
+ ] })
61982
+ ] });
61983
+ if (!hasExternal) {
61984
+ return /* @__PURE__ */ jsx("g", { transform: `translate(${machineOffsetX}, 0)`, children: renderMachine });
61985
+ }
61986
+ return /* @__PURE__ */ jsx(
61987
+ AvlSwimLane,
61988
+ {
61989
+ listenedEvents: data.listenedEvents,
61990
+ emittedEvents: data.emittedEvents,
61991
+ centerWidth: CENTER_W2,
61992
+ height: machineHeight,
61993
+ color,
61994
+ children: renderMachine
61995
+ }
61996
+ );
61997
+ };
61998
+ AvlTraitScene.displayName = "AvlTraitScene";
61999
+
62000
+ // components/molecules/avl/TraitCardNode.tsx
62001
+ init_avl_schema_parser();
62002
+ var TraitCardSelectionContext = createContext({
62003
+ selectTransition: () => {
62004
+ }
62005
+ });
62006
+ var CARD_WIDTH = 540;
62007
+ var SCENE_WIDTH = 600;
62008
+ var SCENE_HEIGHT = 400;
62009
+ var TraitCardNodeInner = (props) => {
62010
+ const data = props.data;
62011
+ const { selectTransition } = useContext(TraitCardSelectionContext);
62012
+ const orbitalName = data.orbitalName;
62013
+ const traitName = data.traitName ?? "";
62014
+ const linkedEntity = data.linkedEntity ?? "";
62015
+ const transitions = data.transitions ?? [];
62016
+ const emits = data.emits ?? [];
62017
+ const listens = data.listens ?? [];
62018
+ const fullSchema = data._fullSchema;
62019
+ const traitLevelData = useMemo(() => {
62020
+ if (!fullSchema) return null;
62021
+ return parseTraitLevel(fullSchema, orbitalName, traitName);
62022
+ }, [fullSchema, orbitalName, traitName]);
62023
+ return /* @__PURE__ */ jsxs(
62024
+ Box,
62025
+ {
62026
+ className: "bg-card border-2 border-border rounded-lg shadow-md p-4",
62027
+ style: { width: CARD_WIDTH, position: "relative" },
62028
+ children: [
62029
+ listens.map((event, i) => /* @__PURE__ */ jsx(
62030
+ Handle,
62031
+ {
62032
+ type: "target",
62033
+ position: Position.Left,
62034
+ id: `listen-${event}`,
62035
+ style: { top: `${(i + 1) / (listens.length + 1) * 100}%` },
62036
+ "aria-label": `listens for ${event}`
62037
+ },
62038
+ `listen-${event}`
62039
+ )),
62040
+ emits.map((event, i) => /* @__PURE__ */ jsx(
62041
+ Handle,
62042
+ {
62043
+ type: "source",
62044
+ position: Position.Right,
62045
+ id: `emit-${event}`,
62046
+ style: { top: `${(i + 1) / (emits.length + 1) * 100}%` },
62047
+ "aria-label": `emits ${event}`
62048
+ },
62049
+ `emit-${event}`
62050
+ )),
62051
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
62052
+ /* @__PURE__ */ jsxs(HStack, { gap: "xs", justify: "between", align: "center", children: [
62053
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", weight: "semibold", children: traitName }),
62054
+ linkedEntity ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: linkedEntity }) : null
62055
+ ] }),
62056
+ traitLevelData ? /* @__PURE__ */ jsx(
62057
+ "svg",
62058
+ {
62059
+ viewBox: `0 0 ${SCENE_WIDTH} ${SCENE_HEIGHT}`,
62060
+ style: { width: "100%", height: "auto", display: "block" },
62061
+ children: /* @__PURE__ */ jsx(
62062
+ AvlTraitScene,
62063
+ {
62064
+ data: traitLevelData,
62065
+ onTransitionClick: (idx) => {
62066
+ const t = transitions[idx];
62067
+ if (!t) return;
62068
+ selectTransition({
62069
+ orbitalName,
62070
+ traitName,
62071
+ transitionEvent: t.event,
62072
+ fromState: t.fromState,
62073
+ toState: t.toState,
62074
+ index: idx
62075
+ });
62076
+ }
62077
+ }
62078
+ )
62079
+ }
62080
+ ) : /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "No state machine" })
62081
+ ] })
62082
+ ]
62083
+ }
62084
+ );
62085
+ };
62086
+ var TraitCardNode = React96__default.memo(TraitCardNodeInner);
62087
+ TraitCardNode.displayName = "TraitCardNode";
62088
+
62089
+ // components/organisms/avl/FlowCanvas.tsx
61789
62090
  init_useEventBus();
61790
62091
  var flowCanvasLog = createLogger("almadar:ui:flow-canvas");
61791
62092
  var NODE_TYPES = {
61792
62093
  preview: OrbPreviewNode,
61793
- behaviorCompose: BehaviorComposeNode
62094
+ behaviorCompose: BehaviorComposeNode,
62095
+ traitCard: TraitCardNode
61794
62096
  };
61795
62097
  flowCanvasLog.debug("node-type-registry", () => ({
61796
62098
  registered: Object.keys(NODE_TYPES),
@@ -61831,7 +62133,8 @@ function FlowCanvasInner({
61831
62133
  }) {
61832
62134
  const NODE_TYPES2 = useMemo(() => ({
61833
62135
  preview: OrbPreviewNode,
61834
- behaviorCompose: BehaviorComposeNode
62136
+ behaviorCompose: BehaviorComposeNode,
62137
+ traitCard: TraitCardNode
61835
62138
  }), []);
61836
62139
  const EDGE_TYPES_LOCAL = useMemo(() => ({
61837
62140
  eventFlow: EventFlowEdge
@@ -61879,17 +62182,19 @@ function FlowCanvasInner({
61879
62182
  }
61880
62183
  }), [selectedPattern]);
61881
62184
  const [atBehaviorLevel, setAtBehaviorLevel] = useState(composeLevel === "behavior");
61882
- const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges, behaviorExpandedNodes, behaviorExpandedEdges } = useMemo(() => {
62185
+ const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges, behaviorExpandedNodes, behaviorExpandedEdges, traitExpandedNodes, traitExpandedEdges } = useMemo(() => {
61883
62186
  const t = perfStart("compose-graph");
61884
62187
  const compose = composeLevel === "behavior" && behaviorEntries?.length ? behaviorsToComposeGraph(behaviorEntries, behaviorWires ?? [], layoutHint) : { nodes: [], edges: [] };
61885
62188
  const overview = schemaToOverviewGraph(parsedSchema, mockData, behaviorMeta, layoutHint, orbitalStatus);
61886
62189
  const expanded = expandedOrbital ? orbitalToExpandedGraph(parsedSchema, expandedOrbital, mockData) : { nodes: [], edges: [] };
61887
62190
  const behaviorExpanded = expandedOrbital && expandedBehaviorAlias ? orbitalAliasToExpandedGraph(parsedSchema, expandedOrbital, expandedBehaviorAlias, mockData) : { nodes: [], edges: [] };
62191
+ const traitExpanded = expandedOrbital ? orbitalToTraitGraph(parsedSchema, expandedOrbital) : { nodes: [], edges: [] };
61888
62192
  perfEnd("compose-graph", t, {
61889
62193
  composeNodes: compose.nodes.length,
61890
62194
  overviewNodes: overview.nodes.length,
61891
62195
  expandedNodes: expanded.nodes.length,
61892
62196
  behaviorExpandedNodes: behaviorExpanded.nodes.length,
62197
+ traitExpandedNodes: traitExpanded.nodes.length,
61893
62198
  orbitalCount: parsedSchema.orbitals?.length ?? 0
61894
62199
  });
61895
62200
  return {
@@ -61900,11 +62205,13 @@ function FlowCanvasInner({
61900
62205
  expandedNodes: expanded.nodes,
61901
62206
  expandedEdges: expanded.edges,
61902
62207
  behaviorExpandedNodes: behaviorExpanded.nodes,
61903
- behaviorExpandedEdges: behaviorExpanded.edges
62208
+ behaviorExpandedEdges: behaviorExpanded.edges,
62209
+ traitExpandedNodes: traitExpanded.nodes,
62210
+ traitExpandedEdges: traitExpanded.edges
61904
62211
  };
61905
62212
  }, [parsedSchema, expandedOrbital, expandedBehaviorAlias, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires, mockData, orbitalStatus]);
61906
- const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : level === "behavior-expanded" ? behaviorExpandedNodes : expandedNodes;
61907
- const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : level === "behavior-expanded" ? behaviorExpandedEdges : expandedEdges;
62213
+ const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : level === "behavior-expanded" ? behaviorExpandedNodes : level === "trait-expanded" ? traitExpandedNodes : expandedNodes;
62214
+ const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : level === "behavior-expanded" ? behaviorExpandedEdges : level === "trait-expanded" ? traitExpandedEdges : expandedEdges;
61908
62215
  const [nodes, setNodes, onNodesChange] = useNodesState(activeNodes);
61909
62216
  const [edges, setEdges, onEdgesChange] = useEdgesState(activeEdges);
61910
62217
  const reactFlow = useReactFlow();
@@ -62061,7 +62368,17 @@ function FlowCanvasInner({
62061
62368
  });
62062
62369
  }, [nodes, onEventWire, eventBus]);
62063
62370
  const screenSizeKeys = ["mobile", "tablet", "laptop", "wide"];
62064
- return /* @__PURE__ */ jsx(ScreenSizeContext.Provider, { value: screenSize, children: /* @__PURE__ */ jsx(PatternSelectionContext.Provider, { value: patternSelectionValue, children: /* @__PURE__ */ jsxs(
62371
+ const traitCardSelectionValue = useMemo(() => ({
62372
+ selectTransition: (sel) => {
62373
+ onNodeClick?.({
62374
+ level: "transition",
62375
+ orbital: sel.orbitalName,
62376
+ trait: sel.traitName,
62377
+ transition: sel.transitionEvent
62378
+ });
62379
+ }
62380
+ }), [onNodeClick]);
62381
+ return /* @__PURE__ */ jsx(ScreenSizeContext.Provider, { value: screenSize, children: /* @__PURE__ */ jsx(PatternSelectionContext.Provider, { value: patternSelectionValue, children: /* @__PURE__ */ jsx(TraitCardSelectionContext.Provider, { value: traitCardSelectionValue, children: /* @__PURE__ */ jsxs(
62065
62382
  Box,
62066
62383
  {
62067
62384
  className: `flex h-full ${className ?? ""}`,
@@ -62179,7 +62496,7 @@ function FlowCanvasInner({
62179
62496
  ] })
62180
62497
  ]
62181
62498
  }
62182
- ) }) });
62499
+ ) }) }) });
62183
62500
  }
62184
62501
  var FlowCanvas = (props) => {
62185
62502
  return /* @__PURE__ */ jsx(Profiler, { id: "flow-canvas", onRender: profilerOnRender, children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(FlowCanvasInner, { ...props }) }) });
@@ -62303,122 +62620,6 @@ AvlCosmicZoom.displayName = "AvlCosmicZoom";
62303
62620
  init_avl_schema_parser();
62304
62621
  init_avl_zoom_state();
62305
62622
 
62306
- // components/organisms/avl/AvlTraitScene.tsx
62307
- init_AvlState();
62308
- init_AvlTransitionLane();
62309
- init_AvlSwimLane();
62310
- init_types();
62311
- init_avl_elk_layout();
62312
- var log19 = createLogger("almadar:ui:avl:trait-scene");
62313
- var SWIM_GUTTER2 = 120;
62314
- var CENTER_W2 = 360;
62315
- var AvlTraitScene = ({
62316
- data,
62317
- color = "var(--color-primary)",
62318
- onTransitionClick
62319
- }) => {
62320
- const [layout, setLayout] = useState(null);
62321
- const dataKey = useMemo(() => JSON.stringify(data), [data]);
62322
- useEffect(() => {
62323
- computeTraitLayout(data).then(setLayout).catch((error) => {
62324
- log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
62325
- });
62326
- }, [dataKey]);
62327
- if (!layout) {
62328
- return /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx("text", { x: 300, y: 200, textAnchor: "middle", fill: color, fontSize: 12, opacity: 0.5, children: "Computing layout..." }) });
62329
- }
62330
- const hasExternal = data.listenedEvents.length > 0 || data.emittedEvents.length > 0;
62331
- const machineOffsetX = hasExternal ? 0 : 30;
62332
- const padding = 20;
62333
- const availW = CENTER_W2 - padding * 2;
62334
- const availH = 300;
62335
- const scale = Math.min(1, availW / layout.width, availH / layout.height);
62336
- const scaledW = layout.width * scale;
62337
- const scaledH = layout.height * scale;
62338
- const offsetX = padding + (availW - scaledW) / 2;
62339
- const offsetY = 50 + (availH - scaledH) / 2;
62340
- const machineHeight = scaledH + 100;
62341
- const renderMachine = /* @__PURE__ */ jsxs("g", { children: [
62342
- /* @__PURE__ */ jsx("text", { x: CENTER_W2 / 2, y: 20, textAnchor: "middle", fill: color, fontSize: 20, fontWeight: "700", fontFamily: "inherit", children: data.name }),
62343
- /* @__PURE__ */ jsxs("text", { x: CENTER_W2 / 2, y: 38, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, fontFamily: "inherit", children: [
62344
- "linked to ",
62345
- data.linkedEntity
62346
- ] }),
62347
- /* @__PURE__ */ jsxs("defs", { children: [
62348
- /* @__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 }) }),
62349
- /* @__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 }) })
62350
- ] }),
62351
- /* @__PURE__ */ jsxs("g", { transform: `translate(${offsetX},${offsetY}) scale(${scale})`, children: [
62352
- layout.edges.map((edge) => {
62353
- const conn = edge.isSelf ? CONNECTION_COLORS.selfLoop : edge.isBackward ? CONNECTION_COLORS.backward : CONNECTION_COLORS.forward;
62354
- const marker = edge.isBackward || edge.isSelf ? "url(#traitArrowBack)" : "url(#traitArrowV2)";
62355
- return /* @__PURE__ */ jsxs("g", { children: [
62356
- /* @__PURE__ */ jsx(
62357
- "path",
62358
- {
62359
- d: edgePath(edge.points),
62360
- fill: "none",
62361
- stroke: conn.color,
62362
- strokeWidth: conn.width,
62363
- strokeDasharray: conn.dash === "none" ? void 0 : conn.dash,
62364
- opacity: 0.5,
62365
- markerEnd: marker
62366
- }
62367
- ),
62368
- /* @__PURE__ */ jsx(
62369
- AvlTransitionLane,
62370
- {
62371
- x: edge.labelX,
62372
- y: edge.labelY,
62373
- event: edge.event,
62374
- guard: edge.guardExpr,
62375
- effects: edge.effects.map((e) => ({ type: e.type })),
62376
- width: edge.labelW,
62377
- isBackward: edge.isBackward,
62378
- isSelfLoop: edge.isSelf,
62379
- color,
62380
- onTransitionClick: onTransitionClick ? () => onTransitionClick(edge.index, {
62381
- x: edge.labelX + offsetX + (hasExternal ? SWIM_GUTTER2 : machineOffsetX),
62382
- y: edge.labelY + offsetY
62383
- }) : void 0
62384
- }
62385
- )
62386
- ] }, edge.id);
62387
- }),
62388
- layout.nodes.map((node) => /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx(
62389
- AvlState,
62390
- {
62391
- x: node.x,
62392
- y: node.y,
62393
- width: node.width,
62394
- height: node.height,
62395
- name: node.id,
62396
- isInitial: node.isInitial,
62397
- isTerminal: node.isTerminal,
62398
- role: node.role,
62399
- transitionCount: node.transitionCount,
62400
- color
62401
- }
62402
- ) }, node.id))
62403
- ] })
62404
- ] });
62405
- if (!hasExternal) {
62406
- return /* @__PURE__ */ jsx("g", { transform: `translate(${machineOffsetX}, 0)`, children: renderMachine });
62407
- }
62408
- return /* @__PURE__ */ jsx(
62409
- AvlSwimLane,
62410
- {
62411
- listenedEvents: data.listenedEvents,
62412
- emittedEvents: data.emittedEvents,
62413
- centerWidth: CENTER_W2,
62414
- height: machineHeight,
62415
- color,
62416
- children: renderMachine
62417
- }
62418
- );
62419
- };
62420
- AvlTraitScene.displayName = "AvlTraitScene";
62421
-
62422
62623
  // components/organisms/avl/AvlTransitionScene.tsx
62423
62624
  init_AvlEffect();
62424
62625
  init_types();
@@ -62905,26 +63106,34 @@ var AvlOrbitalsCosmicZoom = ({
62905
63106
  if (!highlightedOrbital) return;
62906
63107
  if (drilledForHighlightRef.current) return;
62907
63108
  drilledForHighlightRef.current = true;
62908
- dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: highlightedOrbital, targetPosition: { x: 0, y: 0 } });
62909
- Promise.resolve().then(() => dispatch({ type: "ANIMATION_COMPLETE" }));
63109
+ dispatch({ type: "JUMP_TO_TRAIT_CIRCUIT", orbital: highlightedOrbital });
62910
63110
  }, [highlightedOrbital]);
62911
63111
  const breadcrumbs = useMemo(() => getBreadcrumbs(state), [state]);
62912
63112
  const handleSelect = useCallback(
62913
63113
  (name) => {
62914
- dispatch({ type: "ZOOM_INTO_ORBITAL", orbital: name, targetPosition: { x: 0, y: 0 } });
62915
- Promise.resolve().then(() => dispatch({ type: "ANIMATION_COMPLETE" }));
63114
+ dispatch({ type: "JUMP_TO_TRAIT_CIRCUIT", orbital: name });
62916
63115
  onOrbitalSelect?.(name);
62917
63116
  },
62918
63117
  [onOrbitalSelect]
62919
63118
  );
62920
- const handleTraitSelect = useCallback((traitName) => {
62921
- dispatch({ type: "ZOOM_INTO_TRAIT", trait: traitName, targetPosition: { x: 0, y: 0 } });
62922
- Promise.resolve().then(() => dispatch({ type: "ANIMATION_COMPLETE" }));
62923
- }, []);
62924
- const handleTransitionSelect = useCallback((transitionIndex) => {
63119
+ useCallback((transitionIndex) => {
62925
63120
  dispatch({ type: "ZOOM_INTO_TRANSITION", transitionIndex, targetPosition: { x: 0, y: 0 } });
62926
63121
  Promise.resolve().then(() => dispatch({ type: "ANIMATION_COMPLETE" }));
62927
63122
  }, []);
63123
+ const handleCanvasNodeClick = useCallback(
63124
+ (ctx) => {
63125
+ if (ctx.level !== "transition" || !ctx.trait || !ctx.transition) return;
63126
+ const orbital = parsedSchema.orbitals?.find((o) => o.name === ctx.orbital);
63127
+ const traitRef = orbital?.traits?.find((t) => isInlineTrait(t) && t.name === ctx.trait);
63128
+ if (!traitRef || !isInlineTrait(traitRef)) return;
63129
+ const idx = traitRef.stateMachine?.transitions?.findIndex((t) => t.event === ctx.transition) ?? -1;
63130
+ if (idx < 0) return;
63131
+ dispatch({ type: "SELECT_TRAIT", trait: ctx.trait });
63132
+ dispatch({ type: "ZOOM_INTO_TRANSITION", transitionIndex: idx, targetPosition: { x: 0, y: 0 } });
63133
+ Promise.resolve().then(() => dispatch({ type: "ANIMATION_COMPLETE" }));
63134
+ },
63135
+ [parsedSchema]
63136
+ );
62928
63137
  const handleZoomOut = useCallback(() => {
62929
63138
  dispatch({ type: "ZOOM_OUT" });
62930
63139
  Promise.resolve().then(() => dispatch({ type: "ANIMATION_COMPLETE" }));
@@ -62947,14 +63156,6 @@ var AvlOrbitalsCosmicZoom = ({
62947
63156
  window.addEventListener("keydown", onKey);
62948
63157
  return () => window.removeEventListener("keydown", onKey);
62949
63158
  }, [handleZoomOut, state.level]);
62950
- const orbitalLevelData = useMemo(() => {
62951
- if (!state.selectedOrbital) return null;
62952
- return parseOrbitalLevel(parsedSchema, state.selectedOrbital);
62953
- }, [parsedSchema, state.selectedOrbital]);
62954
- const traitLevelData = useMemo(() => {
62955
- if (!state.selectedOrbital || !state.selectedTrait) return null;
62956
- return parseTraitLevel(parsedSchema, state.selectedOrbital, state.selectedTrait);
62957
- }, [parsedSchema, state.selectedOrbital, state.selectedTrait]);
62958
63159
  const transitionLevelData = useMemo(() => {
62959
63160
  if (!state.selectedOrbital || !state.selectedTrait || state.selectedTransition === null) return null;
62960
63161
  return parseTransitionLevel(
@@ -62964,6 +63165,12 @@ var AvlOrbitalsCosmicZoom = ({
62964
63165
  state.selectedTransition
62965
63166
  );
62966
63167
  }, [parsedSchema, state.selectedOrbital, state.selectedTrait, state.selectedTransition]);
63168
+ const scopedSchema = useMemo(() => {
63169
+ if (!state.selectedOrbital) return null;
63170
+ const orbital = parsedSchema.orbitals?.find((o) => o.name === state.selectedOrbital);
63171
+ if (!orbital) return null;
63172
+ return { ...parsedSchema, orbitals: [orbital] };
63173
+ }, [parsedSchema, state.selectedOrbital]);
62967
63174
  const [zoom, setZoom] = useState(1);
62968
63175
  const [pan, setPan] = useState({ x: 0, y: 0 });
62969
63176
  const dragStateRef = useRef(null);
@@ -63011,6 +63218,7 @@ var AvlOrbitalsCosmicZoom = ({
63011
63218
  zoomRef.current = zoom;
63012
63219
  }, [zoom]);
63013
63220
  useEffect(() => {
63221
+ if (state.level !== "application") return;
63014
63222
  const wrapper = transformWrapperRef.current;
63015
63223
  if (!wrapper) return;
63016
63224
  const wheelListener = (e) => {
@@ -63201,81 +63409,7 @@ var AvlOrbitalsCosmicZoom = ({
63201
63409
  }
63202
63410
  )
63203
63411
  ] }),
63204
- state.level === "orbital" && orbitalLevelData && /* @__PURE__ */ jsxs(
63205
- Box,
63206
- {
63207
- position: "absolute",
63208
- style: {
63209
- inset: 0,
63210
- paddingTop: 56,
63211
- paddingBottom: 24,
63212
- paddingLeft: 24,
63213
- paddingRight: 24,
63214
- display: "flex",
63215
- alignItems: "stretch",
63216
- justifyContent: "center",
63217
- gap: 24
63218
- },
63219
- children: [
63220
- /* @__PURE__ */ jsx(Box, { style: { flex: 1, maxWidth: 720, display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx(
63221
- AvlOrbitalUnit,
63222
- {
63223
- entityName: orbitalLevelData.entity.name,
63224
- fields: orbitalLevelData.entity.fields.length,
63225
- persistence: orbitalLevelData.entity.persistence || "persistent",
63226
- traits: orbitalLevelData.traits.map((t) => ({ name: t.name })),
63227
- pages: orbitalLevelData.pages.map((p2) => ({ name: p2.name })),
63228
- color,
63229
- animated
63230
- }
63231
- ) }),
63232
- /* @__PURE__ */ jsxs(
63233
- Box,
63234
- {
63235
- style: {
63236
- width: 220,
63237
- padding: 12,
63238
- display: "flex",
63239
- flexDirection: "column",
63240
- gap: 8,
63241
- borderLeft: `1px solid ${color}`,
63242
- opacity: 0.95,
63243
- overflowY: "auto",
63244
- minHeight: 0
63245
- },
63246
- children: [
63247
- /* @__PURE__ */ jsxs(Typography, { variant: "small", weight: "semibold", style: { color, marginBottom: 4 }, children: [
63248
- "Traits (",
63249
- orbitalLevelData.traits.length,
63250
- ")"
63251
- ] }),
63252
- orbitalLevelData.traits.length === 0 && /* @__PURE__ */ jsx(Text, { variant: "small", style: { opacity: 0.6, color }, children: "No traits" }),
63253
- orbitalLevelData.traits.map((trait) => /* @__PURE__ */ jsx(
63254
- Button,
63255
- {
63256
- variant: "ghost",
63257
- size: "sm",
63258
- onClick: () => handleTraitSelect(trait.name),
63259
- action: "COSMIC_DRILL_TRAIT",
63260
- children: trait.name
63261
- },
63262
- trait.name
63263
- )),
63264
- orbitalLevelData.pages.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
63265
- /* @__PURE__ */ jsxs(Typography, { variant: "small", weight: "semibold", style: { color, marginTop: 12 }, children: [
63266
- "Pages (",
63267
- orbitalLevelData.pages.length,
63268
- ")"
63269
- ] }),
63270
- orbitalLevelData.pages.map((page) => /* @__PURE__ */ jsx(Text, { variant: "small", style: { opacity: 0.7, color }, children: page.name }, page.name))
63271
- ] })
63272
- ]
63273
- }
63274
- )
63275
- ]
63276
- }
63277
- ),
63278
- state.level === "trait" && traitLevelData && /* @__PURE__ */ jsx(
63412
+ state.level === "trait" && scopedSchema && state.selectedOrbital && /* @__PURE__ */ jsx(
63279
63413
  Box,
63280
63414
  {
63281
63415
  position: "absolute",
@@ -63287,39 +63421,14 @@ var AvlOrbitalsCosmicZoom = ({
63287
63421
  paddingRight: 24
63288
63422
  },
63289
63423
  children: /* @__PURE__ */ jsx(
63290
- Box,
63424
+ FlowCanvas,
63291
63425
  {
63292
- ref: transformWrapperRef,
63293
- position: "relative",
63294
- onPointerDown: handlePointerDown,
63295
- onPointerMove: handlePointerMove,
63296
- onPointerUp: handlePointerUp,
63297
- onPointerCancel: handlePointerUp,
63298
- style: {
63299
- width: "100%",
63300
- height: "100%",
63301
- cursor: dragStateRef.current ? "grabbing" : "grab",
63302
- overflow: "hidden"
63303
- },
63304
- children: /* @__PURE__ */ jsx(
63305
- Box,
63306
- {
63307
- position: "absolute",
63308
- style: {
63309
- inset: 0,
63310
- transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
63311
- transformOrigin: "0 0"
63312
- },
63313
- children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 600 400", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
63314
- AvlTraitScene,
63315
- {
63316
- data: traitLevelData,
63317
- color,
63318
- onTransitionClick: (idx) => handleTransitionSelect(idx)
63319
- }
63320
- ) })
63321
- }
63322
- )
63426
+ schema: scopedSchema,
63427
+ initialLevel: "trait-expanded",
63428
+ initialOrbital: state.selectedOrbital,
63429
+ onNodeClick: handleCanvasNodeClick,
63430
+ width: "100%",
63431
+ height: "100%"
63323
63432
  }
63324
63433
  )
63325
63434
  }
@@ -63372,7 +63481,7 @@ var AvlOrbitalsCosmicZoom = ({
63372
63481
  )
63373
63482
  }
63374
63483
  ),
63375
- (state.level === "trait" || state.level === "transition") && /* @__PURE__ */ jsxs(
63484
+ state.level === "transition" && /* @__PURE__ */ jsxs(
63376
63485
  Box,
63377
63486
  {
63378
63487
  position: "absolute",