@eventcatalog/visualiser 4.1.0 → 4.1.1

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/index.d.mts CHANGED
@@ -733,10 +733,31 @@ declare const OwnerIndicator: react.NamedExoticComponent<{
733
733
  iconClass?: string;
734
734
  }>;
735
735
 
736
+ declare const ENTITY_TARGET_HANDLE_ID = "__eventcatalog-entity-target";
737
+ interface EntityProperty {
738
+ name: string;
739
+ type: string;
740
+ required?: boolean;
741
+ description?: string;
742
+ references?: string;
743
+ referencesIdentifier?: string;
744
+ referenceTarget?: "entity";
745
+ relationType?: string;
746
+ enum?: string[];
747
+ properties?: EntityProperty[];
748
+ items?: {
749
+ type: string;
750
+ properties?: EntityProperty[];
751
+ };
752
+ }
753
+ declare const getPropertyTypeLabel: (property: any) => any;
754
+ declare const getNestedEntityProperties: (property: EntityProperty) => EntityProperty[];
736
755
  declare const _default$c: react.NamedExoticComponent<any>;
737
756
 
738
757
  declare const _default$b: react.NamedExoticComponent<any>;
739
758
 
759
+ declare const _default$a: react.NamedExoticComponent<any>;
760
+
740
761
  /**
741
762
  * A system rendered on the System Diagram.
742
763
  *
@@ -745,7 +766,7 @@ declare const _default$b: react.NamedExoticComponent<any>;
745
766
  * Left-clicking the node navigates to the system's architecture map.
746
767
  * Right-click (handled by the NodeGraph context-menu wrapper) offers docs / map / context.
747
768
  */
748
- declare const _default$a: react.NamedExoticComponent<any>;
769
+ declare const _default$9: react.NamedExoticComponent<any>;
749
770
 
750
771
  /**
751
772
  * An actor (person/role) on the System Diagram.
@@ -754,11 +775,9 @@ declare const _default$a: react.NamedExoticComponent<any>;
754
775
  * card with the actor icon in a circular badge centered at the top and the actor
755
776
  * name centered below. This reads as "a person", not "a system", at a glance.
756
777
  */
757
- declare const _default$9: react.NamedExoticComponent<any>;
758
-
759
- declare const _default$8: react.NamedExoticComponent<NodeProps>;
778
+ declare const _default$8: react.NamedExoticComponent<any>;
760
779
 
761
- declare const _default$7: react.NamedExoticComponent<any>;
780
+ declare const _default$7: react.NamedExoticComponent<NodeProps>;
762
781
 
763
782
  declare const _default$6: react.NamedExoticComponent<any>;
764
783
 
@@ -907,4 +926,4 @@ declare function layoutGraph(nodes: GraphNode[], edges: GraphEdge[], options?: {
907
926
  edges: Edge[];
908
927
  };
909
928
 
910
- export { ACTOR, AGENT, AGENT_TOOL, _default$o as Actor, type ActorNode, type Agent$1 as Agent, _default$i as AgentNode, type AgentTool$1 as AgentTool, _default$j as AgentToolNode, type AgentToolNode as AgentToolNodeType, AnimatedMessageEdge, type BaseNodeData, CHANNEL, COMMAND, type Channel, type ChannelNode, _default$f as Command, type CommandNode, _default$9 as ContextActorNode, type ContextMenuItem, _default$c as CustomNode, DATA, type Data, type DataNode, _default$s as DataProductNode, _default$b as DomainNode, type DslGraph, EVENT, type EdgeType, _default$7 as EntityNode, _default$e as Event, type EventCatalogResource, type EventNode, type ExternalSystem, _default$2 as ExternalSystem2Node, type ExternalSystemNode, _default$q as Field, type FieldNode as FieldNodeType, _default$1 as FlowEdge, _default$r as FlowExpandedNode, _default$6 as FlowNode, FocusModeModal, type GraphEdge, type GraphEdgeType, type GraphNode, _default$5 as GroupNode, LabelledDefaultEdge, LabelledSmoothStepEdge, LabelledStepEdge, MESSAGE, type MermaidExportOptions, MermaidView, type Message, _default$t as MessageGroupExpandedNode, type MessageGroupExpandedNodeData, _default$u as MessageGroupNode, type MessageGroupNodeData, type MessageGroupNode as MessageGroupNodeType, _default as MultilineEdgeLabel, type NodeCategory, type NodeConfiguration, _default$v as NodeContextMenu, NodeGraph, type NodeGraphProps, type NodeType, _default$k as Note, type NoteNode, NotesIndicator, OwnerIndicator, QUERY, _default$g as Query, type QueryNode, type RegisteredNode, SERVICE, _default$h as Service, type ServiceNode, type Service as ServiceType, _default$4 as StepNode, _default$w as StepWalkthrough, _default$8 as SystemGroupNode, _default$a as SystemNode, _default$3 as UserNode, VIEW, type View, type ViewNode, VisualiserSearch, type VisualizerCallbacks, type VisualizerLink, type VisualizerMode, _default$n as actorConfig, buildNodeData, calculatedNodes, convertToMermaid, createDagreGraph, createEdge, createNode, _default$m as dataNodeConfig, edgeTypes, _default$d as eventConfig, exportNodeGraphForStudio, _default$l as externalSystemConfig, _default$p as fieldConfig, generateIdForNode, generateIdForNodes, generatedIdForEdge, getColorFromString, getEdgeLabelForMessageAsSource, getEdgeLabelForServiceAsTarget, getNodesAndEdgesFromDagre, layoutGraph, nodeComponents, nodeConfigs, normalizeOwners };
929
+ export { ACTOR, AGENT, AGENT_TOOL, _default$o as Actor, type ActorNode, type Agent$1 as Agent, _default$i as AgentNode, type AgentTool$1 as AgentTool, _default$j as AgentToolNode, type AgentToolNode as AgentToolNodeType, AnimatedMessageEdge, type BaseNodeData, CHANNEL, COMMAND, type Channel, type ChannelNode, _default$f as Command, type CommandNode, _default$8 as ContextActorNode, type ContextMenuItem, _default$b as CustomNode, DATA, type Data, type DataNode, _default$s as DataProductNode, _default$a as DomainNode, type DslGraph, ENTITY_TARGET_HANDLE_ID, EVENT, type EdgeType, _default$c as EntityNode, type EntityProperty, _default$e as Event, type EventCatalogResource, type EventNode, type ExternalSystem, _default$2 as ExternalSystem2Node, type ExternalSystemNode, _default$q as Field, type FieldNode as FieldNodeType, _default$1 as FlowEdge, _default$r as FlowExpandedNode, _default$6 as FlowNode, FocusModeModal, type GraphEdge, type GraphEdgeType, type GraphNode, _default$5 as GroupNode, LabelledDefaultEdge, LabelledSmoothStepEdge, LabelledStepEdge, MESSAGE, type MermaidExportOptions, MermaidView, type Message, _default$t as MessageGroupExpandedNode, type MessageGroupExpandedNodeData, _default$u as MessageGroupNode, type MessageGroupNodeData, type MessageGroupNode as MessageGroupNodeType, _default as MultilineEdgeLabel, type NodeCategory, type NodeConfiguration, _default$v as NodeContextMenu, NodeGraph, type NodeGraphProps, type NodeType, _default$k as Note, type NoteNode, NotesIndicator, OwnerIndicator, QUERY, _default$g as Query, type QueryNode, type RegisteredNode, SERVICE, _default$h as Service, type ServiceNode, type Service as ServiceType, _default$4 as StepNode, _default$w as StepWalkthrough, _default$7 as SystemGroupNode, _default$9 as SystemNode, _default$3 as UserNode, VIEW, type View, type ViewNode, VisualiserSearch, type VisualizerCallbacks, type VisualizerLink, type VisualizerMode, _default$n as actorConfig, buildNodeData, calculatedNodes, convertToMermaid, createDagreGraph, createEdge, createNode, _default$m as dataNodeConfig, edgeTypes, _default$d as eventConfig, exportNodeGraphForStudio, _default$l as externalSystemConfig, _default$p as fieldConfig, generateIdForNode, generateIdForNodes, generatedIdForEdge, getColorFromString, getEdgeLabelForMessageAsSource, getEdgeLabelForServiceAsTarget, getNestedEntityProperties, getNodesAndEdgesFromDagre, getPropertyTypeLabel, layoutGraph, nodeComponents, nodeConfigs, normalizeOwners };
package/dist/index.d.ts CHANGED
@@ -733,10 +733,31 @@ declare const OwnerIndicator: react.NamedExoticComponent<{
733
733
  iconClass?: string;
734
734
  }>;
735
735
 
736
+ declare const ENTITY_TARGET_HANDLE_ID = "__eventcatalog-entity-target";
737
+ interface EntityProperty {
738
+ name: string;
739
+ type: string;
740
+ required?: boolean;
741
+ description?: string;
742
+ references?: string;
743
+ referencesIdentifier?: string;
744
+ referenceTarget?: "entity";
745
+ relationType?: string;
746
+ enum?: string[];
747
+ properties?: EntityProperty[];
748
+ items?: {
749
+ type: string;
750
+ properties?: EntityProperty[];
751
+ };
752
+ }
753
+ declare const getPropertyTypeLabel: (property: any) => any;
754
+ declare const getNestedEntityProperties: (property: EntityProperty) => EntityProperty[];
736
755
  declare const _default$c: react.NamedExoticComponent<any>;
737
756
 
738
757
  declare const _default$b: react.NamedExoticComponent<any>;
739
758
 
759
+ declare const _default$a: react.NamedExoticComponent<any>;
760
+
740
761
  /**
741
762
  * A system rendered on the System Diagram.
742
763
  *
@@ -745,7 +766,7 @@ declare const _default$b: react.NamedExoticComponent<any>;
745
766
  * Left-clicking the node navigates to the system's architecture map.
746
767
  * Right-click (handled by the NodeGraph context-menu wrapper) offers docs / map / context.
747
768
  */
748
- declare const _default$a: react.NamedExoticComponent<any>;
769
+ declare const _default$9: react.NamedExoticComponent<any>;
749
770
 
750
771
  /**
751
772
  * An actor (person/role) on the System Diagram.
@@ -754,11 +775,9 @@ declare const _default$a: react.NamedExoticComponent<any>;
754
775
  * card with the actor icon in a circular badge centered at the top and the actor
755
776
  * name centered below. This reads as "a person", not "a system", at a glance.
756
777
  */
757
- declare const _default$9: react.NamedExoticComponent<any>;
758
-
759
- declare const _default$8: react.NamedExoticComponent<NodeProps>;
778
+ declare const _default$8: react.NamedExoticComponent<any>;
760
779
 
761
- declare const _default$7: react.NamedExoticComponent<any>;
780
+ declare const _default$7: react.NamedExoticComponent<NodeProps>;
762
781
 
763
782
  declare const _default$6: react.NamedExoticComponent<any>;
764
783
 
@@ -907,4 +926,4 @@ declare function layoutGraph(nodes: GraphNode[], edges: GraphEdge[], options?: {
907
926
  edges: Edge[];
908
927
  };
909
928
 
910
- export { ACTOR, AGENT, AGENT_TOOL, _default$o as Actor, type ActorNode, type Agent$1 as Agent, _default$i as AgentNode, type AgentTool$1 as AgentTool, _default$j as AgentToolNode, type AgentToolNode as AgentToolNodeType, AnimatedMessageEdge, type BaseNodeData, CHANNEL, COMMAND, type Channel, type ChannelNode, _default$f as Command, type CommandNode, _default$9 as ContextActorNode, type ContextMenuItem, _default$c as CustomNode, DATA, type Data, type DataNode, _default$s as DataProductNode, _default$b as DomainNode, type DslGraph, EVENT, type EdgeType, _default$7 as EntityNode, _default$e as Event, type EventCatalogResource, type EventNode, type ExternalSystem, _default$2 as ExternalSystem2Node, type ExternalSystemNode, _default$q as Field, type FieldNode as FieldNodeType, _default$1 as FlowEdge, _default$r as FlowExpandedNode, _default$6 as FlowNode, FocusModeModal, type GraphEdge, type GraphEdgeType, type GraphNode, _default$5 as GroupNode, LabelledDefaultEdge, LabelledSmoothStepEdge, LabelledStepEdge, MESSAGE, type MermaidExportOptions, MermaidView, type Message, _default$t as MessageGroupExpandedNode, type MessageGroupExpandedNodeData, _default$u as MessageGroupNode, type MessageGroupNodeData, type MessageGroupNode as MessageGroupNodeType, _default as MultilineEdgeLabel, type NodeCategory, type NodeConfiguration, _default$v as NodeContextMenu, NodeGraph, type NodeGraphProps, type NodeType, _default$k as Note, type NoteNode, NotesIndicator, OwnerIndicator, QUERY, _default$g as Query, type QueryNode, type RegisteredNode, SERVICE, _default$h as Service, type ServiceNode, type Service as ServiceType, _default$4 as StepNode, _default$w as StepWalkthrough, _default$8 as SystemGroupNode, _default$a as SystemNode, _default$3 as UserNode, VIEW, type View, type ViewNode, VisualiserSearch, type VisualizerCallbacks, type VisualizerLink, type VisualizerMode, _default$n as actorConfig, buildNodeData, calculatedNodes, convertToMermaid, createDagreGraph, createEdge, createNode, _default$m as dataNodeConfig, edgeTypes, _default$d as eventConfig, exportNodeGraphForStudio, _default$l as externalSystemConfig, _default$p as fieldConfig, generateIdForNode, generateIdForNodes, generatedIdForEdge, getColorFromString, getEdgeLabelForMessageAsSource, getEdgeLabelForServiceAsTarget, getNodesAndEdgesFromDagre, layoutGraph, nodeComponents, nodeConfigs, normalizeOwners };
929
+ export { ACTOR, AGENT, AGENT_TOOL, _default$o as Actor, type ActorNode, type Agent$1 as Agent, _default$i as AgentNode, type AgentTool$1 as AgentTool, _default$j as AgentToolNode, type AgentToolNode as AgentToolNodeType, AnimatedMessageEdge, type BaseNodeData, CHANNEL, COMMAND, type Channel, type ChannelNode, _default$f as Command, type CommandNode, _default$8 as ContextActorNode, type ContextMenuItem, _default$b as CustomNode, DATA, type Data, type DataNode, _default$s as DataProductNode, _default$a as DomainNode, type DslGraph, ENTITY_TARGET_HANDLE_ID, EVENT, type EdgeType, _default$c as EntityNode, type EntityProperty, _default$e as Event, type EventCatalogResource, type EventNode, type ExternalSystem, _default$2 as ExternalSystem2Node, type ExternalSystemNode, _default$q as Field, type FieldNode as FieldNodeType, _default$1 as FlowEdge, _default$r as FlowExpandedNode, _default$6 as FlowNode, FocusModeModal, type GraphEdge, type GraphEdgeType, type GraphNode, _default$5 as GroupNode, LabelledDefaultEdge, LabelledSmoothStepEdge, LabelledStepEdge, MESSAGE, type MermaidExportOptions, MermaidView, type Message, _default$t as MessageGroupExpandedNode, type MessageGroupExpandedNodeData, _default$u as MessageGroupNode, type MessageGroupNodeData, type MessageGroupNode as MessageGroupNodeType, _default as MultilineEdgeLabel, type NodeCategory, type NodeConfiguration, _default$v as NodeContextMenu, NodeGraph, type NodeGraphProps, type NodeType, _default$k as Note, type NoteNode, NotesIndicator, OwnerIndicator, QUERY, _default$g as Query, type QueryNode, type RegisteredNode, SERVICE, _default$h as Service, type ServiceNode, type Service as ServiceType, _default$4 as StepNode, _default$w as StepWalkthrough, _default$7 as SystemGroupNode, _default$9 as SystemNode, _default$3 as UserNode, VIEW, type View, type ViewNode, VisualiserSearch, type VisualizerCallbacks, type VisualizerLink, type VisualizerMode, _default$n as actorConfig, buildNodeData, calculatedNodes, convertToMermaid, createDagreGraph, createEdge, createNode, _default$m as dataNodeConfig, edgeTypes, _default$d as eventConfig, exportNodeGraphForStudio, _default$l as externalSystemConfig, _default$p as fieldConfig, generateIdForNode, generateIdForNodes, generatedIdForEdge, getColorFromString, getEdgeLabelForMessageAsSource, getEdgeLabelForServiceAsTarget, getNestedEntityProperties, getNodesAndEdgesFromDagre, getPropertyTypeLabel, layoutGraph, nodeComponents, nodeConfigs, normalizeOwners };
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ __export(index_exports, {
47
47
  Data: () => DataNode_default,
48
48
  DataProductNode: () => DataProduct_default,
49
49
  DomainNode: () => Domain_default,
50
+ ENTITY_TARGET_HANDLE_ID: () => ENTITY_TARGET_HANDLE_ID,
50
51
  EVENT: () => EVENT,
51
52
  EntityNode: () => Entity_default,
52
53
  Event: () => EventNode_default,
@@ -102,7 +103,9 @@ __export(index_exports, {
102
103
  getColorFromString: () => getColorFromString,
103
104
  getEdgeLabelForMessageAsSource: () => getEdgeLabelForMessageAsSource,
104
105
  getEdgeLabelForServiceAsTarget: () => getEdgeLabelForServiceAsTarget,
106
+ getNestedEntityProperties: () => getNestedEntityProperties,
105
107
  getNodesAndEdgesFromDagre: () => getNodesAndEdgesFromDagre,
108
+ getPropertyTypeLabel: () => getPropertyTypeLabel,
106
109
  layoutGraph: () => layoutGraph,
107
110
  nodeComponents: () => nodeComponents,
108
111
  nodeConfigs: () => nodeConfigs,
@@ -5280,7 +5283,9 @@ var FlowExpandedNode_default = (0, import_react44.memo)(function FlowExpandedNod
5280
5283
  var import_react45 = require("@xyflow/react");
5281
5284
  var ContextMenu2 = __toESM(require("@radix-ui/react-context-menu"));
5282
5285
  var import_react46 = require("react");
5286
+ var import_solid = require("@heroicons/react/20/solid");
5283
5287
  var import_jsx_runtime25 = require("react/jsx-runtime");
5288
+ var ENTITY_TARGET_HANDLE_ID = "__eventcatalog-entity-target";
5284
5289
  function classNames15(...classes) {
5285
5290
  return classes.filter(Boolean).join(" ");
5286
5291
  }
@@ -5290,12 +5295,27 @@ var getPropertyTypeLabel = (property) => {
5290
5295
  }
5291
5296
  return property.type;
5292
5297
  };
5298
+ var getNestedEntityProperties = (property) => {
5299
+ if (property.properties?.length) return property.properties;
5300
+ if (property.type === "array" && property.items?.properties?.length) {
5301
+ return property.items.properties;
5302
+ }
5303
+ return [];
5304
+ };
5293
5305
  var Entity_default = (0, import_react46.memo)(function EntityNode({
5306
+ id,
5294
5307
  data,
5295
5308
  sourcePosition,
5296
5309
  targetPosition
5297
5310
  }) {
5298
- const { mode, entity, externalToDomain, domainName } = data;
5311
+ const {
5312
+ mode,
5313
+ entity,
5314
+ externalToDomain,
5315
+ domainName,
5316
+ entityTargetHandle = ENTITY_TARGET_HANDLE_ID,
5317
+ referencePropertyNames = EMPTY_ARRAY
5318
+ } = data;
5299
5319
  const {
5300
5320
  name,
5301
5321
  version,
@@ -5310,7 +5330,123 @@ var Entity_default = (0, import_react46.memo)(function EntityNode({
5310
5330
  } = styles || {};
5311
5331
  const Icon = (0, import_react46.useMemo)(() => getIcon(icon), [icon]);
5312
5332
  const [hoveredProperty, setHoveredProperty] = (0, import_react46.useState)(null);
5333
+ const [expandedProperties, setExpandedProperties] = (0, import_react46.useState)(
5334
+ () => /* @__PURE__ */ new Set()
5335
+ );
5336
+ const previousExpandedProperties = (0, import_react46.useRef)(expandedProperties);
5337
+ const updateNodeInternals = (0, import_react45.useUpdateNodeInternals)();
5313
5338
  const portalContainer = usePortalContainer();
5339
+ const referenceProperties = (0, import_react46.useMemo)(
5340
+ () => new Set(referencePropertyNames),
5341
+ [referencePropertyNames]
5342
+ );
5343
+ const toggleProperty = (0, import_react46.useCallback)((propertyPath) => {
5344
+ setExpandedProperties((current) => {
5345
+ const next = new Set(current);
5346
+ if (next.has(propertyPath)) {
5347
+ next.delete(propertyPath);
5348
+ } else {
5349
+ next.add(propertyPath);
5350
+ }
5351
+ return next;
5352
+ });
5353
+ }, []);
5354
+ (0, import_react46.useEffect)(() => {
5355
+ if (previousExpandedProperties.current === expandedProperties) return;
5356
+ previousExpandedProperties.current = expandedProperties;
5357
+ updateNodeInternals(id);
5358
+ }, [expandedProperties, id, updateNodeInternals]);
5359
+ const renderPropertyRows = (entityProperties, depth = 0, parentPath = "") => entityProperties.map((property, index) => {
5360
+ const propertyPath = parentPath ? `${parentPath}.${property.name}` : property.name;
5361
+ const propertyKey = `${propertyPath}-${index}`;
5362
+ const isHovered = hoveredProperty === propertyKey;
5363
+ const nestedProperties = getNestedEntityProperties(property);
5364
+ const isExpandable = nestedProperties.length > 0;
5365
+ const isExpanded = expandedProperties.has(propertyPath);
5366
+ const isTopLevel = depth === 0;
5367
+ const referencedEntityId = property.references || (isTopLevel && referenceProperties.has(property.name) ? property.items?.type : void 0);
5368
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
5369
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5370
+ "div",
5371
+ {
5372
+ className: classNames15(
5373
+ "relative flex items-center justify-between py-2 pr-4 hover:bg-[rgb(var(--ec-page-border)/0.2)]",
5374
+ isExpandable && "nodrag nopan cursor-pointer"
5375
+ ),
5376
+ style: { paddingLeft: `${16 + depth * 16}px` },
5377
+ role: isExpandable ? "button" : void 0,
5378
+ tabIndex: isExpandable ? 0 : void 0,
5379
+ "aria-label": isExpandable ? `${isExpanded ? "Collapse" : "Expand"} ${property.name}` : void 0,
5380
+ "aria-expanded": isExpandable ? isExpanded : void 0,
5381
+ onClick: (event) => {
5382
+ if (!isExpandable) return;
5383
+ const target = event.target;
5384
+ if (target.closest(".react-flow__handle")) return;
5385
+ toggleProperty(propertyPath);
5386
+ },
5387
+ onKeyDown: (event) => {
5388
+ if (!isExpandable || event.key !== "Enter" && event.key !== " ")
5389
+ return;
5390
+ event.preventDefault();
5391
+ toggleProperty(propertyPath);
5392
+ },
5393
+ onMouseEnter: () => property.description && setHoveredProperty(propertyKey),
5394
+ onMouseLeave: () => setHoveredProperty(null),
5395
+ children: [
5396
+ isTopLevel && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5397
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5398
+ import_react45.Handle,
5399
+ {
5400
+ type: "target",
5401
+ position: import_react45.Position.Left,
5402
+ id: `${property.name}-target`,
5403
+ className: "!w-3 !h-3 !bg-[rgb(var(--ec-card-bg))] !border-2 !border-[rgb(var(--ec-page-border))] !rounded-full !left-[-0px]",
5404
+ style: HANDLE_LEFT_OFFSET_STYLE
5405
+ }
5406
+ ),
5407
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5408
+ import_react45.Handle,
5409
+ {
5410
+ type: "source",
5411
+ position: import_react45.Position.Right,
5412
+ id: `${property.name}-source`,
5413
+ className: "!w-3 !h-3 !bg-[rgb(var(--ec-card-bg))] !border-2 !border-[rgb(var(--ec-page-border))] !rounded-full !right-[-0px]",
5414
+ style: HANDLE_RIGHT_OFFSET_STYLE
5415
+ }
5416
+ )
5417
+ ] }),
5418
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 flex items-center justify-between gap-3 min-w-0", children: [
5419
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-1 min-w-0", children: [
5420
+ isExpandable && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5421
+ "span",
5422
+ {
5423
+ className: "shrink-0 text-[rgb(var(--ec-page-text-muted))]",
5424
+ "aria-hidden": "true",
5425
+ children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_solid.ChevronDownIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_solid.ChevronRightIcon, { className: "h-3.5 w-3.5" })
5426
+ }
5427
+ ),
5428
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm font-medium text-[rgb(var(--ec-page-text))] truncate", children: property.name }),
5429
+ property.required && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-red-500 text-xs", children: "*" })
5430
+ ] }),
5431
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm text-[rgb(var(--ec-page-text-muted))] font-mono shrink-0", children: getPropertyTypeLabel(property) })
5432
+ ] }),
5433
+ referencedEntityId && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "absolute right-2 top-1/2 transform -translate-y-1/2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5434
+ "div",
5435
+ {
5436
+ className: "w-2 h-2 bg-blue-500 rounded-full",
5437
+ title: `References ${referencedEntityId}`
5438
+ }
5439
+ ) }),
5440
+ isHovered && property.description && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "absolute left-full ml-2 top-1/2 transform -translate-y-1/2 z-[9999] w-[200px] bg-gray-900 text-white text-xs rounded-lg py-2 px-3 pointer-events-none shadow-xl max-w-xl opacity-100", children: [
5441
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-gray-200 whitespace-normal break-words", children: property.description }),
5442
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "absolute right-full top-1/2 transform -translate-y-1/2 border-4 border-transparent border-r-gray-900" })
5443
+ ] })
5444
+ ]
5445
+ }
5446
+ ),
5447
+ isExpandable && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "divide-y divide-[rgb(var(--ec-page-border))] border-t border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover)/0.18)]", children: renderPropertyRows(nestedProperties, depth + 1, propertyPath) })
5448
+ ] }, propertyKey);
5449
+ });
5314
5450
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ContextMenu2.Root, { children: [
5315
5451
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ContextMenu2.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5316
5452
  "div",
@@ -5324,10 +5460,20 @@ var Entity_default = (0, import_react46.memo)(function EntityNode({
5324
5460
  "div",
5325
5461
  {
5326
5462
  className: classNames15(
5327
- "px-4 py-2 rounded-t-lg border-b border-[rgb(var(--ec-page-border))]",
5463
+ "relative px-4 py-2 rounded-t-lg border-b border-[rgb(var(--ec-page-border))]",
5328
5464
  externalToDomain ? "bg-amber-500/20" : "bg-blue-500/15"
5329
5465
  ),
5330
5466
  children: [
5467
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5468
+ import_react45.Handle,
5469
+ {
5470
+ type: "target",
5471
+ position: import_react45.Position.Left,
5472
+ id: entityTargetHandle,
5473
+ className: "!w-3 !h-3 !bg-[rgb(var(--ec-card-bg))] !border-2 !border-[rgb(var(--ec-page-border))] !rounded-full !left-[-0px]",
5474
+ style: HANDLE_LEFT_OFFSET_STYLE
5475
+ }
5476
+ ),
5331
5477
  /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
5332
5478
  Icon && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Icon, { className: "w-4 h-4 text-[rgb(var(--ec-page-text-muted))]" }),
5333
5479
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
@@ -5353,59 +5499,7 @@ var Entity_default = (0, import_react46.memo)(function EntityNode({
5353
5499
  ]
5354
5500
  }
5355
5501
  ),
5356
- properties.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "divide-y divide-[rgb(var(--ec-page-border))] relative", children: properties.map((property, index) => {
5357
- const propertyKey = `${property.name}-${index}`;
5358
- const isHovered = hoveredProperty === propertyKey;
5359
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5360
- "div",
5361
- {
5362
- className: "relative flex items-center justify-between px-4 py-2 hover:bg-[rgb(var(--ec-page-border)/0.2)]",
5363
- onMouseEnter: () => property.description && setHoveredProperty(propertyKey),
5364
- onMouseLeave: () => setHoveredProperty(null),
5365
- children: [
5366
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5367
- import_react45.Handle,
5368
- {
5369
- type: "target",
5370
- position: import_react45.Position.Left,
5371
- id: `${property.name}-target`,
5372
- className: "!w-3 !h-3 !bg-[rgb(var(--ec-card-bg))] !border-2 !border-[rgb(var(--ec-page-border))] !rounded-full !left-[-0px]",
5373
- style: HANDLE_LEFT_OFFSET_STYLE
5374
- }
5375
- ),
5376
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5377
- import_react45.Handle,
5378
- {
5379
- type: "source",
5380
- position: import_react45.Position.Right,
5381
- id: `${property.name}-source`,
5382
- className: "!w-3 !h-3 !bg-[rgb(var(--ec-card-bg))] !border-2 !border-[rgb(var(--ec-page-border))] !rounded-full !right-[-0px]",
5383
- style: HANDLE_RIGHT_OFFSET_STYLE
5384
- }
5385
- ),
5386
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 flex items-center justify-between", children: [
5387
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-1", children: [
5388
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm font-medium text-[rgb(var(--ec-page-text))]", children: property.name }),
5389
- property.required && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-red-500 text-xs", children: "*" })
5390
- ] }),
5391
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-sm text-[rgb(var(--ec-page-text-muted))] font-mono", children: getPropertyTypeLabel(property) })
5392
- ] }),
5393
- (property.references || property.type === "array" && property.items?.type) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "absolute right-2 top-1/2 transform -translate-y-1/2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5394
- "div",
5395
- {
5396
- className: "w-2 h-2 bg-blue-500 rounded-full",
5397
- title: `References ${property.references || property.items.type}`
5398
- }
5399
- ) }),
5400
- isHovered && property.description && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "absolute left-full ml-2 top-1/2 transform -translate-y-1/2 z-[9999] w-[200px] bg-gray-900 text-white text-xs rounded-lg py-2 px-3 pointer-events-none shadow-xl max-w-xl opacity-100", children: [
5401
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-gray-200 whitespace-normal break-words", children: property.description }),
5402
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "absolute right-full top-1/2 transform -translate-y-1/2 border-4 border-transparent border-r-gray-900" })
5403
- ] })
5404
- ]
5405
- },
5406
- propertyKey
5407
- );
5408
- }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "px-4 py-3 text-sm text-[rgb(var(--ec-page-text-muted))] text-center", children: "No properties defined" }),
5502
+ properties.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "divide-y divide-[rgb(var(--ec-page-border))] relative", children: renderPropertyRows(properties) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "px-4 py-3 text-sm text-[rgb(var(--ec-page-text-muted))] text-center", children: "No properties defined" }),
5409
5503
  properties.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5410
5504
  targetPosition && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react45.Handle, { type: "target", position: targetPosition }),
5411
5505
  sourcePosition && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react45.Handle, { type: "source", position: sourcePosition })
@@ -5451,7 +5545,7 @@ var Entity_default = (0, import_react46.memo)(function EntityNode({
5451
5545
 
5452
5546
  // src/nodes/User.tsx
5453
5547
  var import_react47 = require("react");
5454
- var import_solid = require("@heroicons/react/20/solid");
5548
+ var import_solid2 = require("@heroicons/react/20/solid");
5455
5549
  var import_react48 = require("@xyflow/react");
5456
5550
  var import_jsx_runtime26 = require("react/jsx-runtime");
5457
5551
  function classNames16(...classes) {
@@ -5487,7 +5581,7 @@ var User_default = (0, import_react47.memo)(function UserNode({
5487
5581
  `border-r-[1px] border-yellow-500`
5488
5582
  ),
5489
5583
  children: [
5490
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_solid.UserIcon, { className: "w-4 h-4 opacity-90 text-white mt-1" }),
5584
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_solid2.UserIcon, { className: "w-4 h-4 opacity-90 text-white mt-1" }),
5491
5585
  mode === "full" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5492
5586
  "span",
5493
5587
  {
@@ -11458,6 +11552,7 @@ var import_jsx_runtime52 = require("react/jsx-runtime");
11458
11552
  var POSITION_CHANGE_THRESHOLD = 1;
11459
11553
  var LARGE_GRAPH_NODE_THRESHOLD = 30;
11460
11554
  var NODE_ORIGIN = [0.1, 0.1];
11555
+ var INITIAL_FIT_VIEW_OPTIONS = { padding: 0.2, duration: 0 };
11461
11556
  var MINIMAP_STYLE = {
11462
11557
  backgroundColor: "rgb(var(--ec-page-bg))",
11463
11558
  border: "1px solid rgb(var(--ec-page-border))",
@@ -11717,7 +11812,19 @@ var NodeGraphBuilder = ({
11717
11812
  const [edges, setEdges, onEdgesChange] = (0, import_react93.useEdgesState)(initialEdges);
11718
11813
  const { fitView, getNodes, getIntersectingNodes, getZoom, setCenter } = (0, import_react93.useReactFlow)();
11719
11814
  const storeApi = (0, import_react93.useStoreApi)();
11815
+ const previousGraphInputRef = (0, import_react92.useRef)({
11816
+ nodes: initialNodes,
11817
+ edges: initialEdges
11818
+ });
11720
11819
  (0, import_react92.useEffect)(() => {
11820
+ const previousGraphInput = previousGraphInputRef.current;
11821
+ previousGraphInputRef.current = {
11822
+ nodes: initialNodes,
11823
+ edges: initialEdges
11824
+ };
11825
+ if (previousGraphInput.nodes === initialNodes && previousGraphInput.edges === initialEdges) {
11826
+ return;
11827
+ }
11721
11828
  setNodes(initialNodes);
11722
11829
  setEdges(initialEdges);
11723
11830
  requestAnimationFrame(() => {
@@ -13099,6 +13206,7 @@ var NodeGraphBuilder = ({
13099
13206
  nodes,
13100
13207
  edges,
13101
13208
  fitView: true,
13209
+ fitViewOptions: INITIAL_FIT_VIEW_OPTIONS,
13102
13210
  onNodesChange: handleNodesChange,
13103
13211
  onEdgesChange,
13104
13212
  onEdgeMouseEnter: handleEdgeMouseEnter,
@@ -13577,6 +13685,7 @@ var edgeTypes = {
13577
13685
  Data,
13578
13686
  DataProductNode,
13579
13687
  DomainNode,
13688
+ ENTITY_TARGET_HANDLE_ID,
13580
13689
  EVENT,
13581
13690
  EntityNode,
13582
13691
  Event,
@@ -13632,7 +13741,9 @@ var edgeTypes = {
13632
13741
  getColorFromString,
13633
13742
  getEdgeLabelForMessageAsSource,
13634
13743
  getEdgeLabelForServiceAsTarget,
13744
+ getNestedEntityProperties,
13635
13745
  getNodesAndEdgesFromDagre,
13746
+ getPropertyTypeLabel,
13636
13747
  layoutGraph,
13637
13748
  nodeComponents,
13638
13749
  nodeConfigs,