@almadar/ui 2.45.0 → 2.46.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.cjs +374 -14
- package/dist/avl/index.d.cts +192 -3
- package/dist/avl/index.d.ts +3 -0
- package/dist/avl/index.js +372 -15
- package/dist/components/molecules/avl/BehaviorComposeNode.d.ts +13 -0
- package/dist/components/molecules/avl/avl-behavior-compose-converter.d.ts +53 -0
- package/dist/components/molecules/avl/avl-behavior-compose-types.d.ts +100 -0
- package/dist/components/molecules/avl/avl-preview-converter.d.ts +3 -1
- package/dist/components/molecules/avl/avl-preview-types.d.ts +8 -0
- package/dist/components/molecules/avl/index.d.ts +3 -0
- package/dist/components/molecules/avl/wire-validation.d.ts +30 -0
- package/dist/components/organisms/avl/FlowCanvas.d.ts +15 -0
- package/package.json +1 -1
package/dist/avl/index.js
CHANGED
|
@@ -12830,12 +12830,12 @@ function findCrossLinks(orbitals) {
|
|
|
12830
12830
|
}
|
|
12831
12831
|
return links;
|
|
12832
12832
|
}
|
|
12833
|
-
function schemaToOverviewGraph(schema, mockData) {
|
|
12833
|
+
function schemaToOverviewGraph(schema, mockData, behaviorMeta, layoutHint) {
|
|
12834
12834
|
const orbitals = getOrbitals(schema);
|
|
12835
12835
|
const nodes = [];
|
|
12836
12836
|
const edges = [];
|
|
12837
12837
|
const count = orbitals.length;
|
|
12838
|
-
const cols = Math.ceil(Math.sqrt(count));
|
|
12838
|
+
const cols = layoutHint === "pipeline" ? count : Math.ceil(Math.sqrt(count));
|
|
12839
12839
|
for (let i = 0; i < orbitals.length; i++) {
|
|
12840
12840
|
const orb = orbitals[i];
|
|
12841
12841
|
const entityInfo = getEntityInfo(orb);
|
|
@@ -12874,6 +12874,22 @@ function schemaToOverviewGraph(schema, mockData) {
|
|
|
12874
12874
|
}
|
|
12875
12875
|
}
|
|
12876
12876
|
const eventSources = collectEventSources(initPatterns);
|
|
12877
|
+
for (const source of eventSources) {
|
|
12878
|
+
for (const trait of traits2) {
|
|
12879
|
+
const sm = getStateMachine2(trait);
|
|
12880
|
+
if (!sm) continue;
|
|
12881
|
+
const smEvents = trait.stateMachine?.events ?? [];
|
|
12882
|
+
const matchingEvent = smEvents.find((ev) => ev.key === source.event);
|
|
12883
|
+
if (matchingEvent?.payload && Array.isArray(matchingEvent.payload)) {
|
|
12884
|
+
source.payloadFields = matchingEvent.payload.map((p2) => ({
|
|
12885
|
+
name: String(p2.name ?? ""),
|
|
12886
|
+
type: String(p2.type ?? "string"),
|
|
12887
|
+
...p2.required ? { required: true } : {}
|
|
12888
|
+
}));
|
|
12889
|
+
break;
|
|
12890
|
+
}
|
|
12891
|
+
}
|
|
12892
|
+
}
|
|
12877
12893
|
const col = i % cols;
|
|
12878
12894
|
const row = Math.floor(i / cols);
|
|
12879
12895
|
nodes.push({
|
|
@@ -12885,6 +12901,7 @@ function schemaToOverviewGraph(schema, mockData) {
|
|
|
12885
12901
|
patterns: initPatterns,
|
|
12886
12902
|
eventSources,
|
|
12887
12903
|
effectTypes: initEffectTypes,
|
|
12904
|
+
layer: behaviorMeta?.[orb.name]?.layer,
|
|
12888
12905
|
stateRole: "initial",
|
|
12889
12906
|
entityName: entityInfo.name,
|
|
12890
12907
|
persistence: entityInfo.persistence,
|
|
@@ -47147,6 +47164,43 @@ OrbPreview.displayName = "OrbPreview";
|
|
|
47147
47164
|
|
|
47148
47165
|
// components/molecules/avl/OrbPreviewNode.tsx
|
|
47149
47166
|
init_useEventBus();
|
|
47167
|
+
|
|
47168
|
+
// components/molecules/avl/wire-validation.ts
|
|
47169
|
+
function validateWire(sourcePayload, targetPayload) {
|
|
47170
|
+
const warnings = [];
|
|
47171
|
+
if (!sourcePayload?.length && !targetPayload?.length) {
|
|
47172
|
+
return { valid: true, warnings };
|
|
47173
|
+
}
|
|
47174
|
+
if (sourcePayload?.length && !targetPayload?.length) {
|
|
47175
|
+
return { valid: true, warnings };
|
|
47176
|
+
}
|
|
47177
|
+
if (!sourcePayload?.length && targetPayload?.length) {
|
|
47178
|
+
const requiredFields = targetPayload.filter((f3) => f3.required);
|
|
47179
|
+
if (requiredFields.length > 0) {
|
|
47180
|
+
warnings.push(`Missing required fields: ${requiredFields.map((f3) => f3.name).join(", ")}`);
|
|
47181
|
+
}
|
|
47182
|
+
return { valid: warnings.length === 0, warnings };
|
|
47183
|
+
}
|
|
47184
|
+
const sourceFields = new Map(sourcePayload.map((f3) => [f3.name, f3]));
|
|
47185
|
+
for (const targetField of targetPayload) {
|
|
47186
|
+
const sourceField = sourceFields.get(targetField.name);
|
|
47187
|
+
if (!sourceField) {
|
|
47188
|
+
if (targetField.required) {
|
|
47189
|
+
warnings.push(`Missing required field: ${targetField.name} (${targetField.type})`);
|
|
47190
|
+
}
|
|
47191
|
+
} else if (sourceField.type !== targetField.type) {
|
|
47192
|
+
warnings.push(`Type mismatch: ${targetField.name} (source: ${sourceField.type}, target: ${targetField.type})`);
|
|
47193
|
+
}
|
|
47194
|
+
}
|
|
47195
|
+
return { valid: warnings.length === 0, warnings };
|
|
47196
|
+
}
|
|
47197
|
+
function formatPayloadTooltip(fields) {
|
|
47198
|
+
if (fields.length === 0) return "";
|
|
47199
|
+
const parts = fields.map(
|
|
47200
|
+
(f3) => `${f3.name}: ${f3.type}${f3.required ? " (req)" : ""}`
|
|
47201
|
+
);
|
|
47202
|
+
return `{ ${parts.join(", ")} }`;
|
|
47203
|
+
}
|
|
47150
47204
|
var ScreenSizeContext = createContext("tablet");
|
|
47151
47205
|
var PatternSelectionContext = createContext({ selected: null, select: () => {
|
|
47152
47206
|
} });
|
|
@@ -47157,6 +47211,15 @@ var ROLE_COLORS = {
|
|
|
47157
47211
|
error: { border: "#D97706", dot: "#F59E0B" },
|
|
47158
47212
|
default: { border: "var(--color-border)", dot: "#6B7280" }
|
|
47159
47213
|
};
|
|
47214
|
+
var LAYER_COLORS = {
|
|
47215
|
+
Infrastructure: "#3B82F6",
|
|
47216
|
+
Services: "#F59E0B",
|
|
47217
|
+
"UI Patterns": "#8B5CF6",
|
|
47218
|
+
Game: "#22C55E",
|
|
47219
|
+
ML: "#EC4899",
|
|
47220
|
+
Domain: "#6366F1",
|
|
47221
|
+
Community: "#6B7280"
|
|
47222
|
+
};
|
|
47160
47223
|
var TARGET_HANDLE_STYLE = {
|
|
47161
47224
|
background: "var(--color-primary)",
|
|
47162
47225
|
width: 8,
|
|
@@ -47259,6 +47322,7 @@ var OrbPreviewNodeInner = (props) => {
|
|
|
47259
47322
|
const role = data.stateRole ?? "default";
|
|
47260
47323
|
const colors = ROLE_COLORS[role] ?? ROLE_COLORS.default;
|
|
47261
47324
|
const eventSources = data.eventSources ?? [];
|
|
47325
|
+
const layerColor = data.layer ? LAYER_COLORS[data.layer] : void 0;
|
|
47262
47326
|
const isExpanded = Boolean(data.traitName);
|
|
47263
47327
|
const label = isExpanded ? `${data.transitionEvent ?? ""}` : data.orbitalName;
|
|
47264
47328
|
const sublabel = isExpanded ? `${data.fromState ?? ""} \u2192 ${data.toState ?? ""}` : data.entityName ?? "";
|
|
@@ -47400,6 +47464,13 @@ var OrbPreviewNodeInner = (props) => {
|
|
|
47400
47464
|
onMouseLeave: handleMouseLeave,
|
|
47401
47465
|
children: [
|
|
47402
47466
|
/* @__PURE__ */ jsx("style", { children: SELECTION_STYLES }),
|
|
47467
|
+
layerColor && /* @__PURE__ */ jsx(
|
|
47468
|
+
Box,
|
|
47469
|
+
{
|
|
47470
|
+
style: { height: 3, backgroundColor: layerColor },
|
|
47471
|
+
title: data.layer
|
|
47472
|
+
}
|
|
47473
|
+
),
|
|
47403
47474
|
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2 px-3 py-1.5 border-b border-border/40 drag-handle cursor-grab", children: [
|
|
47404
47475
|
/* @__PURE__ */ jsx(
|
|
47405
47476
|
Box,
|
|
@@ -47421,7 +47492,7 @@ var OrbPreviewNodeInner = (props) => {
|
|
|
47421
47492
|
color: "#F97316",
|
|
47422
47493
|
border: "1px solid #F9731630"
|
|
47423
47494
|
},
|
|
47424
|
-
title: `${src.label ?? src.patternType} \u2192 ${src.event}`,
|
|
47495
|
+
title: `${src.label ?? src.patternType} \u2192 ${src.event}${src.payloadFields?.length ? ` ${formatPayloadTooltip(src.payloadFields)}` : ""}`,
|
|
47425
47496
|
children: src.label ?? src.event
|
|
47426
47497
|
},
|
|
47427
47498
|
src.event
|
|
@@ -47455,7 +47526,7 @@ var OrbPreviewNodeInner = (props) => {
|
|
|
47455
47526
|
type: "source",
|
|
47456
47527
|
position: Position.Right,
|
|
47457
47528
|
style: eventHandleStyle(src),
|
|
47458
|
-
title: `${src.label ?? src.patternType}: ${src.event}`
|
|
47529
|
+
title: `${src.label ?? src.patternType}: ${src.event}${src.payloadFields?.length ? ` ${formatPayloadTooltip(src.payloadFields)}` : ""}`
|
|
47459
47530
|
},
|
|
47460
47531
|
`event-${src.event}`
|
|
47461
47532
|
))
|
|
@@ -47543,6 +47614,211 @@ var EventFlowEdgeInner = (props) => {
|
|
|
47543
47614
|
var EventFlowEdge = React125__default.memo(EventFlowEdgeInner);
|
|
47544
47615
|
EventFlowEdge.displayName = "EventFlowEdge";
|
|
47545
47616
|
|
|
47617
|
+
// components/molecules/avl/BehaviorComposeNode.tsx
|
|
47618
|
+
init_Box();
|
|
47619
|
+
init_Typography();
|
|
47620
|
+
var LAYER_COLORS2 = {
|
|
47621
|
+
Infrastructure: "#3B82F6",
|
|
47622
|
+
Services: "#F59E0B",
|
|
47623
|
+
"UI Patterns": "#8B5CF6",
|
|
47624
|
+
Game: "#22C55E",
|
|
47625
|
+
ML: "#EC4899",
|
|
47626
|
+
Domain: "#6366F1",
|
|
47627
|
+
Community: "#6B7280"
|
|
47628
|
+
};
|
|
47629
|
+
var NODE_WIDTH = 220;
|
|
47630
|
+
var TARGET_HANDLE_STYLE2 = {
|
|
47631
|
+
background: "var(--color-primary)",
|
|
47632
|
+
width: 8,
|
|
47633
|
+
height: 8,
|
|
47634
|
+
border: "2px solid var(--color-card)"
|
|
47635
|
+
};
|
|
47636
|
+
function eventHandleStyle2(source) {
|
|
47637
|
+
return {
|
|
47638
|
+
background: "#F97316",
|
|
47639
|
+
width: 10,
|
|
47640
|
+
height: 10,
|
|
47641
|
+
border: "2px solid var(--color-card)",
|
|
47642
|
+
top: `${source.positionHint * 100}%`,
|
|
47643
|
+
right: -5
|
|
47644
|
+
};
|
|
47645
|
+
}
|
|
47646
|
+
var BehaviorComposeNodeInner = (props) => {
|
|
47647
|
+
const data = props.data;
|
|
47648
|
+
const [hovered, setHovered] = useState(false);
|
|
47649
|
+
const handleMouseEnter = useCallback(() => setHovered(true), []);
|
|
47650
|
+
const handleMouseLeave = useCallback(() => setHovered(false), []);
|
|
47651
|
+
const layerColor = data.layer ? LAYER_COLORS2[data.layer] : void 0;
|
|
47652
|
+
const connectableEvents = data.connectableEvents ?? [];
|
|
47653
|
+
return /* @__PURE__ */ jsxs(
|
|
47654
|
+
Box,
|
|
47655
|
+
{
|
|
47656
|
+
className: "rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden",
|
|
47657
|
+
style: {
|
|
47658
|
+
borderColor: hovered ? "var(--color-primary)" : "var(--color-border)",
|
|
47659
|
+
borderWidth: "1.5px",
|
|
47660
|
+
width: NODE_WIDTH
|
|
47661
|
+
},
|
|
47662
|
+
onMouseEnter: handleMouseEnter,
|
|
47663
|
+
onMouseLeave: handleMouseLeave,
|
|
47664
|
+
children: [
|
|
47665
|
+
layerColor && /* @__PURE__ */ jsx(
|
|
47666
|
+
Box,
|
|
47667
|
+
{
|
|
47668
|
+
style: { height: 3, backgroundColor: layerColor },
|
|
47669
|
+
title: data.layer
|
|
47670
|
+
}
|
|
47671
|
+
),
|
|
47672
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2 px-3 py-1.5 border-b border-border/40 drag-handle cursor-grab", children: [
|
|
47673
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex flex-col min-w-0 flex-1", children: [
|
|
47674
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "font-semibold truncate leading-tight text-[12px]", children: data.behaviorName }),
|
|
47675
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground truncate text-[10px] leading-tight", children: data.entityName })
|
|
47676
|
+
] }),
|
|
47677
|
+
/* @__PURE__ */ jsx(Badge, { variant: "neutral", className: "shrink-0", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[9px] text-inherit", children: data.level }) })
|
|
47678
|
+
] }),
|
|
47679
|
+
/* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center py-3", children: /* @__PURE__ */ jsx(
|
|
47680
|
+
AvlBehaviorGlyph,
|
|
47681
|
+
{
|
|
47682
|
+
name: data.behaviorName,
|
|
47683
|
+
level: data.level,
|
|
47684
|
+
domain: data.domain,
|
|
47685
|
+
stateCount: data.stateCount,
|
|
47686
|
+
fieldCount: data.fieldCount,
|
|
47687
|
+
persistence: data.persistence,
|
|
47688
|
+
effectTypes: data.effectTypes,
|
|
47689
|
+
children: data.children,
|
|
47690
|
+
connections: data.connections,
|
|
47691
|
+
size: "sm",
|
|
47692
|
+
showLabels: false
|
|
47693
|
+
}
|
|
47694
|
+
) }),
|
|
47695
|
+
connectableEvents.length > 0 && /* @__PURE__ */ jsxs(Box, { className: "flex flex-wrap gap-0.5 px-2 pb-2", children: [
|
|
47696
|
+
connectableEvents.slice(0, 4).map((ev) => /* @__PURE__ */ jsx(
|
|
47697
|
+
Box,
|
|
47698
|
+
{
|
|
47699
|
+
className: "rounded-full px-1.5 py-0 text-[8px] font-medium leading-tight",
|
|
47700
|
+
style: {
|
|
47701
|
+
backgroundColor: "#F9731615",
|
|
47702
|
+
color: "#F97316",
|
|
47703
|
+
border: "1px solid #F9731630"
|
|
47704
|
+
},
|
|
47705
|
+
title: `${ev.event}${ev.payloadFields?.length ? ` ${formatPayloadTooltip(ev.payloadFields)}` : ""}`,
|
|
47706
|
+
children: ev.event
|
|
47707
|
+
},
|
|
47708
|
+
ev.event
|
|
47709
|
+
)),
|
|
47710
|
+
connectableEvents.length > 4 && /* @__PURE__ */ jsxs(
|
|
47711
|
+
Box,
|
|
47712
|
+
{
|
|
47713
|
+
className: "rounded-full px-1.5 py-0 text-[8px] font-medium leading-tight",
|
|
47714
|
+
style: { color: "var(--color-muted-foreground)" },
|
|
47715
|
+
children: [
|
|
47716
|
+
"+",
|
|
47717
|
+
connectableEvents.length - 4
|
|
47718
|
+
]
|
|
47719
|
+
}
|
|
47720
|
+
)
|
|
47721
|
+
] }),
|
|
47722
|
+
/* @__PURE__ */ jsxs(Box, { className: "flex items-center justify-between px-2 pb-1.5", children: [
|
|
47723
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "small", className: "text-muted-foreground text-[9px]", children: [
|
|
47724
|
+
data.stateCount,
|
|
47725
|
+
" states"
|
|
47726
|
+
] }),
|
|
47727
|
+
data.layer && /* @__PURE__ */ jsx(Badge, { variant: "neutral", className: "text-[8px]", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[8px] text-inherit", children: data.layer }) })
|
|
47728
|
+
] }),
|
|
47729
|
+
/* @__PURE__ */ jsx(
|
|
47730
|
+
Handle,
|
|
47731
|
+
{
|
|
47732
|
+
type: "target",
|
|
47733
|
+
position: Position.Left,
|
|
47734
|
+
style: TARGET_HANDLE_STYLE2
|
|
47735
|
+
}
|
|
47736
|
+
),
|
|
47737
|
+
connectableEvents.map((ev) => /* @__PURE__ */ jsx(
|
|
47738
|
+
Handle,
|
|
47739
|
+
{
|
|
47740
|
+
id: `event-${ev.event}`,
|
|
47741
|
+
type: "source",
|
|
47742
|
+
position: Position.Right,
|
|
47743
|
+
style: eventHandleStyle2(ev),
|
|
47744
|
+
title: `${ev.event}${ev.payloadFields?.length ? ` ${formatPayloadTooltip(ev.payloadFields)}` : ""}`
|
|
47745
|
+
},
|
|
47746
|
+
`event-${ev.event}`
|
|
47747
|
+
))
|
|
47748
|
+
]
|
|
47749
|
+
}
|
|
47750
|
+
);
|
|
47751
|
+
};
|
|
47752
|
+
var BehaviorComposeNode = React125__default.memo(BehaviorComposeNodeInner);
|
|
47753
|
+
BehaviorComposeNode.displayName = "BehaviorComposeNode";
|
|
47754
|
+
|
|
47755
|
+
// components/molecules/avl/avl-behavior-compose-converter.ts
|
|
47756
|
+
var COMPOSE_SPACING = 320;
|
|
47757
|
+
function behaviorsToComposeGraph(entries, wires, layoutHint) {
|
|
47758
|
+
const nodes = [];
|
|
47759
|
+
const edges = [];
|
|
47760
|
+
const count = entries.length;
|
|
47761
|
+
const cols = layoutHint === "pipeline" ? count : Math.ceil(Math.sqrt(count));
|
|
47762
|
+
for (let i = 0; i < entries.length; i++) {
|
|
47763
|
+
const entry = entries[i];
|
|
47764
|
+
const col = i % cols;
|
|
47765
|
+
const row = Math.floor(i / cols);
|
|
47766
|
+
nodes.push({
|
|
47767
|
+
id: entry.behaviorName,
|
|
47768
|
+
type: "behaviorCompose",
|
|
47769
|
+
position: { x: col * COMPOSE_SPACING, y: row * COMPOSE_SPACING },
|
|
47770
|
+
data: {
|
|
47771
|
+
behaviorName: entry.behaviorName,
|
|
47772
|
+
level: entry.level,
|
|
47773
|
+
domain: entry.domain,
|
|
47774
|
+
layer: entry.layer,
|
|
47775
|
+
entityName: entry.entityName,
|
|
47776
|
+
stateCount: entry.stateCount,
|
|
47777
|
+
fieldCount: entry.fieldCount,
|
|
47778
|
+
persistence: entry.persistence,
|
|
47779
|
+
effectTypes: entry.effectTypes,
|
|
47780
|
+
children: entry.children,
|
|
47781
|
+
connections: entry.connections,
|
|
47782
|
+
connectableEvents: entry.connectableEvents,
|
|
47783
|
+
composableWith: entry.composableWith,
|
|
47784
|
+
orbitalNames: entry.orbitalNames
|
|
47785
|
+
}
|
|
47786
|
+
});
|
|
47787
|
+
}
|
|
47788
|
+
for (const wire of wires) {
|
|
47789
|
+
edges.push({
|
|
47790
|
+
id: `bw-${wire.sourceBehavior}-${wire.targetBehavior}-${wire.event}`,
|
|
47791
|
+
source: wire.sourceBehavior,
|
|
47792
|
+
target: wire.targetBehavior,
|
|
47793
|
+
sourceHandle: `event-${wire.event}`,
|
|
47794
|
+
type: "eventFlow",
|
|
47795
|
+
data: wire
|
|
47796
|
+
});
|
|
47797
|
+
}
|
|
47798
|
+
return { nodes, edges };
|
|
47799
|
+
}
|
|
47800
|
+
function registryEntryToCanvasEntry(entry, orbitalNames) {
|
|
47801
|
+
const events2 = entry.connectableEvents;
|
|
47802
|
+
const connectableEvents = events2.map((eventName, i) => ({
|
|
47803
|
+
event: eventName,
|
|
47804
|
+
payloadFields: entry.eventPayloads[eventName],
|
|
47805
|
+
positionHint: events2.length > 1 ? 0.1 + i * 0.8 / (events2.length - 1) : 0.5
|
|
47806
|
+
}));
|
|
47807
|
+
return {
|
|
47808
|
+
behaviorName: entry.name,
|
|
47809
|
+
level: entry.level,
|
|
47810
|
+
domain: entry.family,
|
|
47811
|
+
layer: entry.layer,
|
|
47812
|
+
entityName: entry.defaultEntity.name,
|
|
47813
|
+
stateCount: entry.complexity.states,
|
|
47814
|
+
fieldCount: entry.defaultEntity.fields.length,
|
|
47815
|
+
persistence: entry.defaultEntity.persistence,
|
|
47816
|
+
connectableEvents,
|
|
47817
|
+
composableWith: entry.composableWith,
|
|
47818
|
+
orbitalNames
|
|
47819
|
+
};
|
|
47820
|
+
}
|
|
47821
|
+
|
|
47546
47822
|
// components/molecules/avl/index.ts
|
|
47547
47823
|
init_Avl3DOrbitalNode();
|
|
47548
47824
|
init_Avl3DCrossWire();
|
|
@@ -47655,6 +47931,7 @@ function OrbInspector({ node, schema, editable = false, onSchemaChange, onClose
|
|
|
47655
47931
|
const effectTypes = node.effectTypes ?? [];
|
|
47656
47932
|
const guard = node.guard;
|
|
47657
47933
|
const isExpanded = Boolean(traitName);
|
|
47934
|
+
const hasRenderUi = effectTypes.includes("render-ui");
|
|
47658
47935
|
const patternType = selectedPattern?.patternType;
|
|
47659
47936
|
const patternDef = useMemo(() => patternType ? getPatternDefinition(patternType) : null, [patternType]);
|
|
47660
47937
|
const isEntityPattern = patternType ? isEntityAwarePattern(patternType) : false;
|
|
@@ -47854,6 +48131,42 @@ function OrbInspector({ node, schema, editable = false, onSchemaChange, onClose
|
|
|
47854
48131
|
}
|
|
47855
48132
|
)
|
|
47856
48133
|
] }),
|
|
48134
|
+
editable && !selectedPattern && !isExpanded && node.layer === "Services" && /* @__PURE__ */ jsxs(Box, { className: "px-4 py-3 border-b border-border/40", children: [
|
|
48135
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] uppercase tracking-wider mb-2", children: t("Service Mode") }),
|
|
48136
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "items-center", children: [
|
|
48137
|
+
/* @__PURE__ */ jsxs(
|
|
48138
|
+
Button,
|
|
48139
|
+
{
|
|
48140
|
+
variant: hasRenderUi ? "primary" : "ghost",
|
|
48141
|
+
size: "sm",
|
|
48142
|
+
className: "flex-1 text-[11px]",
|
|
48143
|
+
onClick: () => {
|
|
48144
|
+
if (!hasRenderUi) eventBus.emit("UI:SERVICE_MODE_TOGGLE", { orbitalName: node.orbitalName, standalone: true });
|
|
48145
|
+
},
|
|
48146
|
+
children: [
|
|
48147
|
+
/* @__PURE__ */ jsx(Icon, { name: "monitor", size: "xs", className: "mr-1" }),
|
|
48148
|
+
t("Standalone")
|
|
48149
|
+
]
|
|
48150
|
+
}
|
|
48151
|
+
),
|
|
48152
|
+
/* @__PURE__ */ jsxs(
|
|
48153
|
+
Button,
|
|
48154
|
+
{
|
|
48155
|
+
variant: hasRenderUi ? "ghost" : "primary",
|
|
48156
|
+
size: "sm",
|
|
48157
|
+
className: "flex-1 text-[11px]",
|
|
48158
|
+
onClick: () => {
|
|
48159
|
+
if (hasRenderUi) eventBus.emit("UI:SERVICE_MODE_TOGGLE", { orbitalName: node.orbitalName, standalone: false });
|
|
48160
|
+
},
|
|
48161
|
+
children: [
|
|
48162
|
+
/* @__PURE__ */ jsx(Icon, { name: "cpu", size: "xs", className: "mr-1" }),
|
|
48163
|
+
t("Embedded")
|
|
48164
|
+
]
|
|
48165
|
+
}
|
|
48166
|
+
)
|
|
48167
|
+
] }),
|
|
48168
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] mt-1", children: hasRenderUi ? t("Renders its own UI") : t("Headless, wired to other behaviors") })
|
|
48169
|
+
] }),
|
|
47857
48170
|
!selectedPattern && !isExpanded && traits2.length > 0 && /* @__PURE__ */ jsxs(Box, { className: "px-4 py-3 border-b border-border/40", children: [
|
|
47858
48171
|
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] uppercase tracking-wider mb-2", children: "Traits" }),
|
|
47859
48172
|
/* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-1", children: traits2.map((t2) => /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2", children: [
|
|
@@ -48002,8 +48315,10 @@ OrbInspector.displayName = "OrbInspector";
|
|
|
48002
48315
|
// components/organisms/avl/FlowCanvas.tsx
|
|
48003
48316
|
init_Box();
|
|
48004
48317
|
init_Typography();
|
|
48318
|
+
init_useEventBus();
|
|
48005
48319
|
var NODE_TYPES = {
|
|
48006
|
-
preview: OrbPreviewNode
|
|
48320
|
+
preview: OrbPreviewNode,
|
|
48321
|
+
behaviorCompose: BehaviorComposeNode
|
|
48007
48322
|
};
|
|
48008
48323
|
var EDGE_TYPES = {
|
|
48009
48324
|
eventFlow: EventFlowEdge
|
|
@@ -48025,7 +48340,13 @@ function FlowCanvasInner({
|
|
|
48025
48340
|
editable,
|
|
48026
48341
|
onSchemaChange,
|
|
48027
48342
|
onPatternDelete,
|
|
48028
|
-
onEventWire
|
|
48343
|
+
onEventWire,
|
|
48344
|
+
behaviorMeta,
|
|
48345
|
+
layoutHint,
|
|
48346
|
+
onNodeSelect,
|
|
48347
|
+
composeLevel,
|
|
48348
|
+
behaviorEntries,
|
|
48349
|
+
behaviorWires
|
|
48029
48350
|
}) {
|
|
48030
48351
|
const parsedSchema = useMemo(() => {
|
|
48031
48352
|
if (typeof schemaProp === "string") return JSON.parse(schemaProp);
|
|
@@ -48047,18 +48368,22 @@ function FlowCanvasInner({
|
|
|
48047
48368
|
if (p2) setSelectedNode(p2.nodeData);
|
|
48048
48369
|
}
|
|
48049
48370
|
}), [selectedPattern]);
|
|
48050
|
-
const
|
|
48051
|
-
|
|
48371
|
+
const [atBehaviorLevel, setAtBehaviorLevel] = useState(composeLevel === "behavior");
|
|
48372
|
+
const { composeNodes, composeEdges, overviewNodes, overviewEdges, expandedNodes, expandedEdges } = useMemo(() => {
|
|
48373
|
+
const compose = composeLevel === "behavior" && behaviorEntries?.length ? behaviorsToComposeGraph(behaviorEntries, behaviorWires ?? [], layoutHint) : { nodes: [], edges: [] };
|
|
48374
|
+
const overview = schemaToOverviewGraph(parsedSchema, mockData, behaviorMeta, layoutHint);
|
|
48052
48375
|
const expanded = expandedOrbital ? orbitalToExpandedGraph(parsedSchema, expandedOrbital, mockData) : { nodes: [], edges: [] };
|
|
48053
48376
|
return {
|
|
48377
|
+
composeNodes: compose.nodes,
|
|
48378
|
+
composeEdges: compose.edges,
|
|
48054
48379
|
overviewNodes: overview.nodes,
|
|
48055
48380
|
overviewEdges: overview.edges,
|
|
48056
48381
|
expandedNodes: expanded.nodes,
|
|
48057
48382
|
expandedEdges: expanded.edges
|
|
48058
48383
|
};
|
|
48059
|
-
}, [parsedSchema, expandedOrbital]);
|
|
48060
|
-
const activeNodes = level === "overview" ? overviewNodes : expandedNodes;
|
|
48061
|
-
const activeEdges = level === "overview" ? overviewEdges : expandedEdges;
|
|
48384
|
+
}, [parsedSchema, expandedOrbital, behaviorMeta, layoutHint, composeLevel, behaviorEntries, behaviorWires]);
|
|
48385
|
+
const activeNodes = atBehaviorLevel && composeNodes.length > 0 ? composeNodes : level === "overview" ? overviewNodes : expandedNodes;
|
|
48386
|
+
const activeEdges = atBehaviorLevel && composeEdges.length > 0 ? composeEdges : level === "overview" ? overviewEdges : expandedEdges;
|
|
48062
48387
|
const [nodes, setNodes, onNodesChange] = useNodesState(activeNodes);
|
|
48063
48388
|
const [edges, setEdges, onEdgesChange] = useEdgesState(activeEdges);
|
|
48064
48389
|
const reactFlow = useReactFlow();
|
|
@@ -48070,13 +48395,23 @@ function FlowCanvasInner({
|
|
|
48070
48395
|
});
|
|
48071
48396
|
}, [activeNodes, activeEdges, setNodes, setEdges, reactFlow]);
|
|
48072
48397
|
const handleNodeDoubleClick = useCallback((_, node) => {
|
|
48398
|
+
if (atBehaviorLevel && composeLevel === "behavior") {
|
|
48399
|
+
const d = node.data;
|
|
48400
|
+
if (d.orbitalNames?.length) {
|
|
48401
|
+
setExpandedOrbital(d.orbitalNames[0]);
|
|
48402
|
+
}
|
|
48403
|
+
setAtBehaviorLevel(false);
|
|
48404
|
+
setLevel("overview");
|
|
48405
|
+
onLevelChange?.("overview", d.behaviorName);
|
|
48406
|
+
return;
|
|
48407
|
+
}
|
|
48073
48408
|
if (level === "overview") {
|
|
48074
48409
|
const d = node.data;
|
|
48075
48410
|
setExpandedOrbital(d.orbitalName ?? node.id);
|
|
48076
48411
|
setLevel("expanded");
|
|
48077
48412
|
onLevelChange?.("expanded", d.orbitalName ?? node.id);
|
|
48078
48413
|
}
|
|
48079
|
-
}, [level, onLevelChange]);
|
|
48414
|
+
}, [level, onLevelChange, atBehaviorLevel, composeLevel]);
|
|
48080
48415
|
const handleNodeClick = useCallback((_, node) => {
|
|
48081
48416
|
const nodeData = node.data;
|
|
48082
48417
|
if (level === "expanded") {
|
|
@@ -48092,6 +48427,7 @@ function FlowCanvasInner({
|
|
|
48092
48427
|
level: "overview",
|
|
48093
48428
|
orbital: nodeData.orbitalName ?? node.id
|
|
48094
48429
|
});
|
|
48430
|
+
onNodeSelect?.(nodeData.orbitalName ?? node.id);
|
|
48095
48431
|
}
|
|
48096
48432
|
}, [level, expandedOrbital, onNodeClick]);
|
|
48097
48433
|
const handleClosePanel = useCallback(() => {
|
|
@@ -48105,6 +48441,9 @@ function FlowCanvasInner({
|
|
|
48105
48441
|
setLevel("overview");
|
|
48106
48442
|
setExpandedOrbital(void 0);
|
|
48107
48443
|
onLevelChange?.("overview");
|
|
48444
|
+
} else if (level === "overview" && composeLevel === "behavior" && !atBehaviorLevel) {
|
|
48445
|
+
setAtBehaviorLevel(true);
|
|
48446
|
+
setExpandedOrbital(void 0);
|
|
48108
48447
|
}
|
|
48109
48448
|
} else if (e.key === "Delete" || e.key === "Backspace") {
|
|
48110
48449
|
const target = e.target;
|
|
@@ -48127,8 +48466,13 @@ function FlowCanvasInner({
|
|
|
48127
48466
|
setExpandedOrbital(void 0);
|
|
48128
48467
|
setSelectedNode(null);
|
|
48129
48468
|
onLevelChange?.("overview");
|
|
48469
|
+
} else if (level === "overview" && composeLevel === "behavior" && !atBehaviorLevel) {
|
|
48470
|
+
setAtBehaviorLevel(true);
|
|
48471
|
+
setExpandedOrbital(void 0);
|
|
48472
|
+
setSelectedNode(null);
|
|
48130
48473
|
}
|
|
48131
|
-
}, [level, onLevelChange, selectedNode]);
|
|
48474
|
+
}, [level, onLevelChange, selectedNode, composeLevel, atBehaviorLevel]);
|
|
48475
|
+
const eventBus = useEventBus();
|
|
48132
48476
|
const handleConnect = useCallback((connection) => {
|
|
48133
48477
|
if (!connection.sourceHandle?.startsWith("event-") || !onEventWire) return;
|
|
48134
48478
|
const eventName = connection.sourceHandle.replace("event-", "");
|
|
@@ -48137,6 +48481,19 @@ function FlowCanvasInner({
|
|
|
48137
48481
|
if (!sourceNode || !targetNode) return;
|
|
48138
48482
|
const srcData = sourceNode.data;
|
|
48139
48483
|
const tgtData = targetNode.data;
|
|
48484
|
+
const sourceEventSource = srcData.eventSources?.find((es) => es.event === eventName);
|
|
48485
|
+
const sourcePayload = sourceEventSource?.payloadFields;
|
|
48486
|
+
const targetEventSource = tgtData.eventSources?.find((es) => es.event === eventName);
|
|
48487
|
+
const targetPayload = targetEventSource?.payloadFields;
|
|
48488
|
+
const validation = validateWire(sourcePayload, targetPayload);
|
|
48489
|
+
if (validation.warnings.length > 0) {
|
|
48490
|
+
eventBus.emit("UI:WIRE_VALIDATION_WARNING", {
|
|
48491
|
+
eventName,
|
|
48492
|
+
sourceOrbital: srcData.orbitalName,
|
|
48493
|
+
targetOrbital: tgtData.orbitalName,
|
|
48494
|
+
warnings: validation.warnings
|
|
48495
|
+
});
|
|
48496
|
+
}
|
|
48140
48497
|
onEventWire({
|
|
48141
48498
|
eventName,
|
|
48142
48499
|
sourceOrbital: srcData.orbitalName ?? "",
|
|
@@ -48144,7 +48501,7 @@ function FlowCanvasInner({
|
|
|
48144
48501
|
sourceTraitName: srcData.traitName,
|
|
48145
48502
|
targetTraitName: tgtData.traitName
|
|
48146
48503
|
});
|
|
48147
|
-
}, [nodes, onEventWire]);
|
|
48504
|
+
}, [nodes, onEventWire, eventBus]);
|
|
48148
48505
|
const screenSizeKeys = ["mobile", "tablet", "desktop"];
|
|
48149
48506
|
return /* @__PURE__ */ jsx(ScreenSizeContext.Provider, { value: screenSize, children: /* @__PURE__ */ jsx(PatternSelectionContext.Provider, { value: patternSelectionValue, children: /* @__PURE__ */ jsxs(
|
|
48150
48507
|
Box,
|
|
@@ -48794,4 +49151,4 @@ AvlClickTarget.displayName = "AvlClickTarget";
|
|
|
48794
49151
|
init_avl_schema_parser();
|
|
48795
49152
|
init_avl_zoom_state();
|
|
48796
49153
|
|
|
48797
|
-
export { AVL_FIELD_TYPE_SHAPES, AVL_OPERATOR_COLORS, AvlApplication, AvlBackwardEdge, AvlBehaviorGlyph, AvlBinding, AvlBindingEdge, AvlBindingRef, AvlClickTarget, AvlClosedCircuit, AvlCosmicZoom, AvlEffect, AvlEmitListen, AvlEntity, AvlEvent, AvlEventWireEdge, AvlExprTree, AvlField, AvlFieldType, AvlGuard, AvlLiteral, AvlOperator, AvlOrbital, AvlOrbitalNode, AvlOrbitalUnit, AvlPage, AvlPageEdge, AvlPersistence, AvlSExpr, AvlSlotMap, AvlState, AvlStateMachine, AvlSwimLane, AvlTrait, AvlTraitScene, AvlTransition, AvlTransitionEdge, AvlTransitionLane, AvlTransitionScene, BehaviorView, CONNECTION_COLORS, DOMAIN_COLORS, DetailView, EFFECT_CATEGORY_COLORS, EFFECT_TYPE_TO_CATEGORY, EventFlowEdge, FlowCanvas, MiniStateMachine, ModuleCard, OrbInspector, OrbPreviewNode, STATE_COLORS, SystemNode, ZOOM_BAND_THRESHOLDS, ZoomBandContext, ZoomBreadcrumb, ZoomLegend, arcPath, computeTraitLayout, computeZoomBand, curveControlPoint, edgePath, getStateRole, gridPositions, orbitalToExpandedGraph, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, radialPositions, ringPositions, schemaToFlowGraph, schemaToOverviewGraph, useZoomBand, zoomProgress };
|
|
49154
|
+
export { AVL_FIELD_TYPE_SHAPES, AVL_OPERATOR_COLORS, AvlApplication, AvlBackwardEdge, AvlBehaviorGlyph, AvlBinding, AvlBindingEdge, AvlBindingRef, AvlClickTarget, AvlClosedCircuit, AvlCosmicZoom, AvlEffect, AvlEmitListen, AvlEntity, AvlEvent, AvlEventWireEdge, AvlExprTree, AvlField, AvlFieldType, AvlGuard, AvlLiteral, AvlOperator, AvlOrbital, AvlOrbitalNode, AvlOrbitalUnit, AvlPage, AvlPageEdge, AvlPersistence, AvlSExpr, AvlSlotMap, AvlState, AvlStateMachine, AvlSwimLane, AvlTrait, AvlTraitScene, AvlTransition, AvlTransitionEdge, AvlTransitionLane, AvlTransitionScene, BehaviorComposeNode, BehaviorView, CONNECTION_COLORS, DOMAIN_COLORS, DetailView, EFFECT_CATEGORY_COLORS, EFFECT_TYPE_TO_CATEGORY, EventFlowEdge, FlowCanvas, MiniStateMachine, ModuleCard, OrbInspector, OrbPreviewNode, STATE_COLORS, SystemNode, ZOOM_BAND_THRESHOLDS, ZoomBandContext, ZoomBreadcrumb, ZoomLegend, arcPath, behaviorsToComposeGraph, computeTraitLayout, computeZoomBand, curveControlPoint, edgePath, getStateRole, gridPositions, orbitalToExpandedGraph, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, radialPositions, registryEntryToCanvasEntry, ringPositions, schemaToFlowGraph, schemaToOverviewGraph, useZoomBand, zoomProgress };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BehaviorComposeNode
|
|
3
|
+
*
|
|
4
|
+
* React Flow custom node for behavior-level composition.
|
|
5
|
+
* Shows AvlBehaviorGlyph instead of live UI (OrbPreview).
|
|
6
|
+
* Each behavior is one compact node with event handles for wiring.
|
|
7
|
+
*
|
|
8
|
+
* This is the compose-level node. Double-clicking drills into
|
|
9
|
+
* the orbital-level view (OrbPreviewNode).
|
|
10
|
+
*/
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import { type NodeProps } from '@xyflow/react';
|
|
13
|
+
export declare const BehaviorComposeNode: React.NamedExoticComponent<NodeProps>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AVL Behavior Compose Converter
|
|
3
|
+
*
|
|
4
|
+
* Converts BehaviorCanvasEntry[] to React Flow nodes and edges
|
|
5
|
+
* for the behavior-level composition canvas.
|
|
6
|
+
*
|
|
7
|
+
* Parallel to avl-preview-converter.ts which works at the orbital level.
|
|
8
|
+
* This works one level higher: each node is a behavior (not an orbital).
|
|
9
|
+
*/
|
|
10
|
+
import type { Node, Edge } from '@xyflow/react';
|
|
11
|
+
import type { BehaviorCanvasEntry, BehaviorComposeNodeData, BehaviorWireEdgeData } from './avl-behavior-compose-types';
|
|
12
|
+
/**
|
|
13
|
+
* Build a React Flow graph for behavior-level composition.
|
|
14
|
+
* Each behavior entry becomes one BehaviorComposeNode.
|
|
15
|
+
*/
|
|
16
|
+
export declare function behaviorsToComposeGraph(entries: BehaviorCanvasEntry[], wires: BehaviorWireEdgeData[], layoutHint?: 'pipeline' | 'grid'): {
|
|
17
|
+
nodes: Node<BehaviorComposeNodeData>[];
|
|
18
|
+
edges: Edge<BehaviorWireEdgeData>[];
|
|
19
|
+
};
|
|
20
|
+
/** Registry record shape (matches behaviors-registry.json entries). */
|
|
21
|
+
export interface BehaviorRegistryRecord {
|
|
22
|
+
name: string;
|
|
23
|
+
level: 'atom' | 'molecule' | 'organism';
|
|
24
|
+
family: string;
|
|
25
|
+
layer: string;
|
|
26
|
+
description: string;
|
|
27
|
+
complexity: {
|
|
28
|
+
states: number;
|
|
29
|
+
events: number;
|
|
30
|
+
transitions: number;
|
|
31
|
+
};
|
|
32
|
+
defaultEntity: {
|
|
33
|
+
name: string;
|
|
34
|
+
persistence?: string;
|
|
35
|
+
fields: Array<{
|
|
36
|
+
name: string;
|
|
37
|
+
type: string;
|
|
38
|
+
required?: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
};
|
|
41
|
+
connectableEvents: string[];
|
|
42
|
+
eventPayloads: Record<string, Array<{
|
|
43
|
+
name: string;
|
|
44
|
+
type: string;
|
|
45
|
+
required?: boolean;
|
|
46
|
+
}>>;
|
|
47
|
+
composableWith: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Convert a registry entry to a BehaviorCanvasEntry.
|
|
51
|
+
* Maps connectableEvents + eventPayloads into typed ConnectableEvent[].
|
|
52
|
+
*/
|
|
53
|
+
export declare function registryEntryToCanvasEntry(entry: BehaviorRegistryRecord, orbitalNames: string[]): BehaviorCanvasEntry;
|