@almadar/ui 4.54.6 → 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.
@@ -57854,6 +57854,11 @@ function orbitalToTraitGraph(schema, orbitalName, _mockData) {
57854
57854
  transitions,
57855
57855
  emits,
57856
57856
  listens,
57857
+ // `_fullSchema` carries the parsed schema to `TraitCardNode` so it
57858
+ // can run `parseTraitLevel(...)` and render the ELK-laid-out
57859
+ // state-machine flow chart inside the card. Mirrors the same
57860
+ // convention `OrbPreviewNode` uses for its embedded UI preview.
57861
+ _fullSchema: schema,
57857
57862
  // Required fields on PreviewNodeData — keep empty for trait cards.
57858
57863
  patterns: [],
57859
57864
  eventSources: []
@@ -61920,14 +61925,133 @@ init_Typography();
61920
61925
  init_Box();
61921
61926
  init_Stack();
61922
61927
  init_Typography();
61923
- init_Button();
61924
61928
  init_Badge();
61929
+
61930
+ // components/organisms/avl/AvlTraitScene.tsx
61931
+ init_AvlState();
61932
+ init_AvlTransitionLane();
61933
+ init_AvlSwimLane();
61934
+ init_types();
61935
+ init_avl_elk_layout();
61936
+ var log19 = logger.createLogger("almadar:ui:avl:trait-scene");
61937
+ var SWIM_GUTTER2 = 120;
61938
+ var CENTER_W2 = 360;
61939
+ var AvlTraitScene = ({
61940
+ data,
61941
+ color = "var(--color-primary)",
61942
+ onTransitionClick
61943
+ }) => {
61944
+ const [layout, setLayout] = React96.useState(null);
61945
+ const dataKey = React96.useMemo(() => JSON.stringify(data), [data]);
61946
+ React96.useEffect(() => {
61947
+ computeTraitLayout(data).then(setLayout).catch((error) => {
61948
+ log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61949
+ });
61950
+ }, [dataKey]);
61951
+ if (!layout) {
61952
+ 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..." }) });
61953
+ }
61954
+ const hasExternal = data.listenedEvents.length > 0 || data.emittedEvents.length > 0;
61955
+ const machineOffsetX = hasExternal ? 0 : 30;
61956
+ const padding = 20;
61957
+ const availW = CENTER_W2 - padding * 2;
61958
+ const availH = 300;
61959
+ const scale = Math.min(1, availW / layout.width, availH / layout.height);
61960
+ const scaledW = layout.width * scale;
61961
+ const scaledH = layout.height * scale;
61962
+ const offsetX = padding + (availW - scaledW) / 2;
61963
+ const offsetY = 50 + (availH - scaledH) / 2;
61964
+ const machineHeight = scaledH + 100;
61965
+ const renderMachine = /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
61966
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: CENTER_W2 / 2, y: 20, textAnchor: "middle", fill: color, fontSize: 20, fontWeight: "700", fontFamily: "inherit", children: data.name }),
61967
+ /* @__PURE__ */ jsxRuntime.jsxs("text", { x: CENTER_W2 / 2, y: 38, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, fontFamily: "inherit", children: [
61968
+ "linked to ",
61969
+ data.linkedEntity
61970
+ ] }),
61971
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
61972
+ /* @__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: exports.CONNECTION_COLORS.forward.color, opacity: 0.7 }) }),
61973
+ /* @__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: exports.CONNECTION_COLORS.backward.color, opacity: 0.5 }) })
61974
+ ] }),
61975
+ /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${offsetX},${offsetY}) scale(${scale})`, children: [
61976
+ layout.edges.map((edge) => {
61977
+ const conn = edge.isSelf ? exports.CONNECTION_COLORS.selfLoop : edge.isBackward ? exports.CONNECTION_COLORS.backward : exports.CONNECTION_COLORS.forward;
61978
+ const marker = edge.isBackward || edge.isSelf ? "url(#traitArrowBack)" : "url(#traitArrowV2)";
61979
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
61980
+ /* @__PURE__ */ jsxRuntime.jsx(
61981
+ "path",
61982
+ {
61983
+ d: edgePath(edge.points),
61984
+ fill: "none",
61985
+ stroke: conn.color,
61986
+ strokeWidth: conn.width,
61987
+ strokeDasharray: conn.dash === "none" ? void 0 : conn.dash,
61988
+ opacity: 0.5,
61989
+ markerEnd: marker
61990
+ }
61991
+ ),
61992
+ /* @__PURE__ */ jsxRuntime.jsx(
61993
+ exports.AvlTransitionLane,
61994
+ {
61995
+ x: edge.labelX,
61996
+ y: edge.labelY,
61997
+ event: edge.event,
61998
+ guard: edge.guardExpr,
61999
+ effects: edge.effects.map((e) => ({ type: e.type })),
62000
+ width: edge.labelW,
62001
+ isBackward: edge.isBackward,
62002
+ isSelfLoop: edge.isSelf,
62003
+ color,
62004
+ onTransitionClick: onTransitionClick ? () => onTransitionClick(edge.index, {
62005
+ x: edge.labelX + offsetX + (hasExternal ? SWIM_GUTTER2 : machineOffsetX),
62006
+ y: edge.labelY + offsetY
62007
+ }) : void 0
62008
+ }
62009
+ )
62010
+ ] }, edge.id);
62011
+ }),
62012
+ layout.nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx("g", { children: /* @__PURE__ */ jsxRuntime.jsx(
62013
+ exports.AvlState,
62014
+ {
62015
+ x: node.x,
62016
+ y: node.y,
62017
+ width: node.width,
62018
+ height: node.height,
62019
+ name: node.id,
62020
+ isInitial: node.isInitial,
62021
+ isTerminal: node.isTerminal,
62022
+ role: node.role,
62023
+ transitionCount: node.transitionCount,
62024
+ color
62025
+ }
62026
+ ) }, node.id))
62027
+ ] })
62028
+ ] });
62029
+ if (!hasExternal) {
62030
+ return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${machineOffsetX}, 0)`, children: renderMachine });
62031
+ }
62032
+ return /* @__PURE__ */ jsxRuntime.jsx(
62033
+ exports.AvlSwimLane,
62034
+ {
62035
+ listenedEvents: data.listenedEvents,
62036
+ emittedEvents: data.emittedEvents,
62037
+ centerWidth: CENTER_W2,
62038
+ height: machineHeight,
62039
+ color,
62040
+ children: renderMachine
62041
+ }
62042
+ );
62043
+ };
62044
+ AvlTraitScene.displayName = "AvlTraitScene";
62045
+
62046
+ // components/molecules/avl/TraitCardNode.tsx
62047
+ init_avl_schema_parser();
61925
62048
  var TraitCardSelectionContext = React96.createContext({
61926
62049
  selectTransition: () => {
61927
62050
  }
61928
62051
  });
61929
- var CARD_WIDTH = 360;
61930
- var CARD_MIN_HEIGHT = 200;
62052
+ var CARD_WIDTH = 540;
62053
+ var SCENE_WIDTH = 600;
62054
+ var SCENE_HEIGHT = 400;
61931
62055
  var TraitCardNodeInner = (props) => {
61932
62056
  const data = props.data;
61933
62057
  const { selectTransition } = React96.useContext(TraitCardSelectionContext);
@@ -61937,11 +62061,16 @@ var TraitCardNodeInner = (props) => {
61937
62061
  const transitions = data.transitions ?? [];
61938
62062
  const emits = data.emits ?? [];
61939
62063
  const listens = data.listens ?? [];
62064
+ const fullSchema = data._fullSchema;
62065
+ const traitLevelData = React96.useMemo(() => {
62066
+ if (!fullSchema) return null;
62067
+ return parseTraitLevel(fullSchema, orbitalName, traitName);
62068
+ }, [fullSchema, orbitalName, traitName]);
61940
62069
  return /* @__PURE__ */ jsxRuntime.jsxs(
61941
62070
  Box,
61942
62071
  {
61943
62072
  className: "bg-card border-2 border-border rounded-lg shadow-md p-4",
61944
- style: { width: CARD_WIDTH, minHeight: CARD_MIN_HEIGHT, position: "relative" },
62073
+ style: { width: CARD_WIDTH, position: "relative" },
61945
62074
  children: [
61946
62075
  listens.map((event, i) => /* @__PURE__ */ jsxRuntime.jsx(
61947
62076
  react.Handle,
@@ -61970,34 +62099,31 @@ var TraitCardNodeInner = (props) => {
61970
62099
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h6", weight: "semibold", children: traitName }),
61971
62100
  linkedEntity ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", children: linkedEntity }) : null
61972
62101
  ] }),
61973
- /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "xs", children: transitions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "muted", children: "No transitions" }) : transitions.map((t, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
61974
- Button,
62102
+ traitLevelData ? /* @__PURE__ */ jsxRuntime.jsx(
62103
+ "svg",
61975
62104
  {
61976
- variant: "ghost",
61977
- size: "sm",
61978
- onClick: (e) => {
61979
- e.stopPropagation();
61980
- selectTransition({
61981
- orbitalName,
61982
- traitName,
61983
- transitionEvent: t.event,
61984
- fromState: t.fromState,
61985
- toState: t.toState,
61986
- index: idx
61987
- });
61988
- },
61989
- children: [
61990
- /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "semibold", children: t.event }),
61991
- /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", color: "muted", children: [
61992
- " \xB7 ",
61993
- t.fromState,
61994
- " \u2192 ",
61995
- t.toState
61996
- ] })
61997
- ]
61998
- },
61999
- `${t.event}-${t.fromState}-${t.toState}-${idx}`
62000
- )) })
62105
+ viewBox: `0 0 ${SCENE_WIDTH} ${SCENE_HEIGHT}`,
62106
+ style: { width: "100%", height: "auto", display: "block" },
62107
+ children: /* @__PURE__ */ jsxRuntime.jsx(
62108
+ AvlTraitScene,
62109
+ {
62110
+ data: traitLevelData,
62111
+ onTransitionClick: (idx) => {
62112
+ const t = transitions[idx];
62113
+ if (!t) return;
62114
+ selectTransition({
62115
+ orbitalName,
62116
+ traitName,
62117
+ transitionEvent: t.event,
62118
+ fromState: t.fromState,
62119
+ toState: t.toState,
62120
+ index: idx
62121
+ });
62122
+ }
62123
+ }
62124
+ )
62125
+ }
62126
+ ) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "muted", children: "No state machine" })
62001
62127
  ] })
62002
62128
  ]
62003
62129
  }
@@ -63425,122 +63551,6 @@ var AvlOrbitalsCosmicZoom = ({
63425
63551
  );
63426
63552
  };
63427
63553
  AvlOrbitalsCosmicZoom.displayName = "AvlOrbitalsCosmicZoom";
63428
-
63429
- // components/organisms/avl/AvlTraitScene.tsx
63430
- init_AvlState();
63431
- init_AvlTransitionLane();
63432
- init_AvlSwimLane();
63433
- init_types();
63434
- init_avl_elk_layout();
63435
- var log19 = logger.createLogger("almadar:ui:avl:trait-scene");
63436
- var SWIM_GUTTER2 = 120;
63437
- var CENTER_W2 = 360;
63438
- var AvlTraitScene = ({
63439
- data,
63440
- color = "var(--color-primary)",
63441
- onTransitionClick
63442
- }) => {
63443
- const [layout, setLayout] = React96.useState(null);
63444
- const dataKey = React96.useMemo(() => JSON.stringify(data), [data]);
63445
- React96.useEffect(() => {
63446
- computeTraitLayout(data).then(setLayout).catch((error) => {
63447
- log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
63448
- });
63449
- }, [dataKey]);
63450
- if (!layout) {
63451
- 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..." }) });
63452
- }
63453
- const hasExternal = data.listenedEvents.length > 0 || data.emittedEvents.length > 0;
63454
- const machineOffsetX = hasExternal ? 0 : 30;
63455
- const padding = 20;
63456
- const availW = CENTER_W2 - padding * 2;
63457
- const availH = 300;
63458
- const scale = Math.min(1, availW / layout.width, availH / layout.height);
63459
- const scaledW = layout.width * scale;
63460
- const scaledH = layout.height * scale;
63461
- const offsetX = padding + (availW - scaledW) / 2;
63462
- const offsetY = 50 + (availH - scaledH) / 2;
63463
- const machineHeight = scaledH + 100;
63464
- const renderMachine = /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
63465
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: CENTER_W2 / 2, y: 20, textAnchor: "middle", fill: color, fontSize: 20, fontWeight: "700", fontFamily: "inherit", children: data.name }),
63466
- /* @__PURE__ */ jsxRuntime.jsxs("text", { x: CENTER_W2 / 2, y: 38, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, fontFamily: "inherit", children: [
63467
- "linked to ",
63468
- data.linkedEntity
63469
- ] }),
63470
- /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
63471
- /* @__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: exports.CONNECTION_COLORS.forward.color, opacity: 0.7 }) }),
63472
- /* @__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: exports.CONNECTION_COLORS.backward.color, opacity: 0.5 }) })
63473
- ] }),
63474
- /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${offsetX},${offsetY}) scale(${scale})`, children: [
63475
- layout.edges.map((edge) => {
63476
- const conn = edge.isSelf ? exports.CONNECTION_COLORS.selfLoop : edge.isBackward ? exports.CONNECTION_COLORS.backward : exports.CONNECTION_COLORS.forward;
63477
- const marker = edge.isBackward || edge.isSelf ? "url(#traitArrowBack)" : "url(#traitArrowV2)";
63478
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
63479
- /* @__PURE__ */ jsxRuntime.jsx(
63480
- "path",
63481
- {
63482
- d: edgePath(edge.points),
63483
- fill: "none",
63484
- stroke: conn.color,
63485
- strokeWidth: conn.width,
63486
- strokeDasharray: conn.dash === "none" ? void 0 : conn.dash,
63487
- opacity: 0.5,
63488
- markerEnd: marker
63489
- }
63490
- ),
63491
- /* @__PURE__ */ jsxRuntime.jsx(
63492
- exports.AvlTransitionLane,
63493
- {
63494
- x: edge.labelX,
63495
- y: edge.labelY,
63496
- event: edge.event,
63497
- guard: edge.guardExpr,
63498
- effects: edge.effects.map((e) => ({ type: e.type })),
63499
- width: edge.labelW,
63500
- isBackward: edge.isBackward,
63501
- isSelfLoop: edge.isSelf,
63502
- color,
63503
- onTransitionClick: onTransitionClick ? () => onTransitionClick(edge.index, {
63504
- x: edge.labelX + offsetX + (hasExternal ? SWIM_GUTTER2 : machineOffsetX),
63505
- y: edge.labelY + offsetY
63506
- }) : void 0
63507
- }
63508
- )
63509
- ] }, edge.id);
63510
- }),
63511
- layout.nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx("g", { children: /* @__PURE__ */ jsxRuntime.jsx(
63512
- exports.AvlState,
63513
- {
63514
- x: node.x,
63515
- y: node.y,
63516
- width: node.width,
63517
- height: node.height,
63518
- name: node.id,
63519
- isInitial: node.isInitial,
63520
- isTerminal: node.isTerminal,
63521
- role: node.role,
63522
- transitionCount: node.transitionCount,
63523
- color
63524
- }
63525
- ) }, node.id))
63526
- ] })
63527
- ] });
63528
- if (!hasExternal) {
63529
- return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${machineOffsetX}, 0)`, children: renderMachine });
63530
- }
63531
- return /* @__PURE__ */ jsxRuntime.jsx(
63532
- exports.AvlSwimLane,
63533
- {
63534
- listenedEvents: data.listenedEvents,
63535
- emittedEvents: data.emittedEvents,
63536
- centerWidth: CENTER_W2,
63537
- height: machineHeight,
63538
- color,
63539
- children: renderMachine
63540
- }
63541
- );
63542
- };
63543
- AvlTraitScene.displayName = "AvlTraitScene";
63544
63554
  var AvlClickTarget = ({
63545
63555
  x,
63546
63556
  y,
package/dist/avl/index.js CHANGED
@@ -57808,6 +57808,11 @@ function orbitalToTraitGraph(schema, orbitalName, _mockData) {
57808
57808
  transitions,
57809
57809
  emits,
57810
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,
57811
57816
  // Required fields on PreviewNodeData — keep empty for trait cards.
57812
57817
  patterns: [],
57813
57818
  eventSources: []
@@ -61874,14 +61879,133 @@ init_Typography();
61874
61879
  init_Box();
61875
61880
  init_Stack();
61876
61881
  init_Typography();
61877
- init_Button();
61878
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();
61879
62002
  var TraitCardSelectionContext = createContext({
61880
62003
  selectTransition: () => {
61881
62004
  }
61882
62005
  });
61883
- var CARD_WIDTH = 360;
61884
- var CARD_MIN_HEIGHT = 200;
62006
+ var CARD_WIDTH = 540;
62007
+ var SCENE_WIDTH = 600;
62008
+ var SCENE_HEIGHT = 400;
61885
62009
  var TraitCardNodeInner = (props) => {
61886
62010
  const data = props.data;
61887
62011
  const { selectTransition } = useContext(TraitCardSelectionContext);
@@ -61891,11 +62015,16 @@ var TraitCardNodeInner = (props) => {
61891
62015
  const transitions = data.transitions ?? [];
61892
62016
  const emits = data.emits ?? [];
61893
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]);
61894
62023
  return /* @__PURE__ */ jsxs(
61895
62024
  Box,
61896
62025
  {
61897
62026
  className: "bg-card border-2 border-border rounded-lg shadow-md p-4",
61898
- style: { width: CARD_WIDTH, minHeight: CARD_MIN_HEIGHT, position: "relative" },
62027
+ style: { width: CARD_WIDTH, position: "relative" },
61899
62028
  children: [
61900
62029
  listens.map((event, i) => /* @__PURE__ */ jsx(
61901
62030
  Handle,
@@ -61924,34 +62053,31 @@ var TraitCardNodeInner = (props) => {
61924
62053
  /* @__PURE__ */ jsx(Typography, { variant: "h6", weight: "semibold", children: traitName }),
61925
62054
  linkedEntity ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: linkedEntity }) : null
61926
62055
  ] }),
61927
- /* @__PURE__ */ jsx(VStack, { gap: "xs", children: transitions.length === 0 ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "No transitions" }) : transitions.map((t, idx) => /* @__PURE__ */ jsxs(
61928
- Button,
62056
+ traitLevelData ? /* @__PURE__ */ jsx(
62057
+ "svg",
61929
62058
  {
61930
- variant: "ghost",
61931
- size: "sm",
61932
- onClick: (e) => {
61933
- e.stopPropagation();
61934
- selectTransition({
61935
- orbitalName,
61936
- traitName,
61937
- transitionEvent: t.event,
61938
- fromState: t.fromState,
61939
- toState: t.toState,
61940
- index: idx
61941
- });
61942
- },
61943
- children: [
61944
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "semibold", children: t.event }),
61945
- /* @__PURE__ */ jsxs(Typography, { variant: "small", color: "muted", children: [
61946
- " \xB7 ",
61947
- t.fromState,
61948
- " \u2192 ",
61949
- t.toState
61950
- ] })
61951
- ]
61952
- },
61953
- `${t.event}-${t.fromState}-${t.toState}-${idx}`
61954
- )) })
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" })
61955
62081
  ] })
61956
62082
  ]
61957
62083
  }
@@ -63379,122 +63505,6 @@ var AvlOrbitalsCosmicZoom = ({
63379
63505
  );
63380
63506
  };
63381
63507
  AvlOrbitalsCosmicZoom.displayName = "AvlOrbitalsCosmicZoom";
63382
-
63383
- // components/organisms/avl/AvlTraitScene.tsx
63384
- init_AvlState();
63385
- init_AvlTransitionLane();
63386
- init_AvlSwimLane();
63387
- init_types();
63388
- init_avl_elk_layout();
63389
- var log19 = createLogger("almadar:ui:avl:trait-scene");
63390
- var SWIM_GUTTER2 = 120;
63391
- var CENTER_W2 = 360;
63392
- var AvlTraitScene = ({
63393
- data,
63394
- color = "var(--color-primary)",
63395
- onTransitionClick
63396
- }) => {
63397
- const [layout, setLayout] = useState(null);
63398
- const dataKey = useMemo(() => JSON.stringify(data), [data]);
63399
- useEffect(() => {
63400
- computeTraitLayout(data).then(setLayout).catch((error) => {
63401
- log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
63402
- });
63403
- }, [dataKey]);
63404
- if (!layout) {
63405
- return /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx("text", { x: 300, y: 200, textAnchor: "middle", fill: color, fontSize: 12, opacity: 0.5, children: "Computing layout..." }) });
63406
- }
63407
- const hasExternal = data.listenedEvents.length > 0 || data.emittedEvents.length > 0;
63408
- const machineOffsetX = hasExternal ? 0 : 30;
63409
- const padding = 20;
63410
- const availW = CENTER_W2 - padding * 2;
63411
- const availH = 300;
63412
- const scale = Math.min(1, availW / layout.width, availH / layout.height);
63413
- const scaledW = layout.width * scale;
63414
- const scaledH = layout.height * scale;
63415
- const offsetX = padding + (availW - scaledW) / 2;
63416
- const offsetY = 50 + (availH - scaledH) / 2;
63417
- const machineHeight = scaledH + 100;
63418
- const renderMachine = /* @__PURE__ */ jsxs("g", { children: [
63419
- /* @__PURE__ */ jsx("text", { x: CENTER_W2 / 2, y: 20, textAnchor: "middle", fill: color, fontSize: 20, fontWeight: "700", fontFamily: "inherit", children: data.name }),
63420
- /* @__PURE__ */ jsxs("text", { x: CENTER_W2 / 2, y: 38, textAnchor: "middle", fill: color, fontSize: 11, opacity: 0.5, fontFamily: "inherit", children: [
63421
- "linked to ",
63422
- data.linkedEntity
63423
- ] }),
63424
- /* @__PURE__ */ jsxs("defs", { children: [
63425
- /* @__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 }) }),
63426
- /* @__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 }) })
63427
- ] }),
63428
- /* @__PURE__ */ jsxs("g", { transform: `translate(${offsetX},${offsetY}) scale(${scale})`, children: [
63429
- layout.edges.map((edge) => {
63430
- const conn = edge.isSelf ? CONNECTION_COLORS.selfLoop : edge.isBackward ? CONNECTION_COLORS.backward : CONNECTION_COLORS.forward;
63431
- const marker = edge.isBackward || edge.isSelf ? "url(#traitArrowBack)" : "url(#traitArrowV2)";
63432
- return /* @__PURE__ */ jsxs("g", { children: [
63433
- /* @__PURE__ */ jsx(
63434
- "path",
63435
- {
63436
- d: edgePath(edge.points),
63437
- fill: "none",
63438
- stroke: conn.color,
63439
- strokeWidth: conn.width,
63440
- strokeDasharray: conn.dash === "none" ? void 0 : conn.dash,
63441
- opacity: 0.5,
63442
- markerEnd: marker
63443
- }
63444
- ),
63445
- /* @__PURE__ */ jsx(
63446
- AvlTransitionLane,
63447
- {
63448
- x: edge.labelX,
63449
- y: edge.labelY,
63450
- event: edge.event,
63451
- guard: edge.guardExpr,
63452
- effects: edge.effects.map((e) => ({ type: e.type })),
63453
- width: edge.labelW,
63454
- isBackward: edge.isBackward,
63455
- isSelfLoop: edge.isSelf,
63456
- color,
63457
- onTransitionClick: onTransitionClick ? () => onTransitionClick(edge.index, {
63458
- x: edge.labelX + offsetX + (hasExternal ? SWIM_GUTTER2 : machineOffsetX),
63459
- y: edge.labelY + offsetY
63460
- }) : void 0
63461
- }
63462
- )
63463
- ] }, edge.id);
63464
- }),
63465
- layout.nodes.map((node) => /* @__PURE__ */ jsx("g", { children: /* @__PURE__ */ jsx(
63466
- AvlState,
63467
- {
63468
- x: node.x,
63469
- y: node.y,
63470
- width: node.width,
63471
- height: node.height,
63472
- name: node.id,
63473
- isInitial: node.isInitial,
63474
- isTerminal: node.isTerminal,
63475
- role: node.role,
63476
- transitionCount: node.transitionCount,
63477
- color
63478
- }
63479
- ) }, node.id))
63480
- ] })
63481
- ] });
63482
- if (!hasExternal) {
63483
- return /* @__PURE__ */ jsx("g", { transform: `translate(${machineOffsetX}, 0)`, children: renderMachine });
63484
- }
63485
- return /* @__PURE__ */ jsx(
63486
- AvlSwimLane,
63487
- {
63488
- listenedEvents: data.listenedEvents,
63489
- emittedEvents: data.emittedEvents,
63490
- centerWidth: CENTER_W2,
63491
- height: machineHeight,
63492
- color,
63493
- children: renderMachine
63494
- }
63495
- );
63496
- };
63497
- AvlTraitScene.displayName = "AvlTraitScene";
63498
63508
  var AvlClickTarget = ({
63499
63509
  x,
63500
63510
  y,
@@ -1,15 +1,17 @@
1
1
  /**
2
2
  * TraitCardNode — React Flow node for the `trait-expanded` view level.
3
3
  *
4
- * Renders one card per trait of a single orbital. Header shows the trait
5
- * name + linked entity badge; body lists the trait's transitions as
6
- * clickable rows that drill into L4 transition detail; left edge has
7
- * one target handle per `listens[]` event; right edge has one source
8
- * handle per `emits[]` event. The edges produced by
4
+ * Renders one card per trait of a single orbital. The card body shows
5
+ * the trait's state-machine flow chart (states + transitions, laid out
6
+ * by ELK) via the existing `AvlTraitScene` organism. Clicking a
7
+ * transition arc drills into L4 transition detail.
8
+ *
9
+ * Left edge has one target handle per `listens[]` event; right edge
10
+ * has one source handle per `emits[]` event. Edges produced by
9
11
  * `orbitalToTraitGraph` connect emit handles to listen handles where
10
- * the event names match.
12
+ * the event names match within the same orbital.
11
13
  *
12
- * Transition-row clicks bubble through `TraitCardSelectionContext`
14
+ * Transition clicks bubble through `TraitCardSelectionContext`
13
15
  * (mirrors `PatternSelectionContext` in `OrbPreviewNode`). FlowCanvas
14
16
  * wraps the canvas in a provider that translates the context callback
15
17
  * into its `onNodeClick({ level: 'transition', ... })` prop.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.54.6",
3
+ "version": "4.54.7",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [