@eventcatalog/core 5.0.0-beta.12 → 5.0.0-beta.14

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.
Files changed (90) hide show
  1. package/LICENSE +13 -12
  2. package/dist/analytics/analytics.cjs +1 -1
  3. package/dist/analytics/analytics.js +2 -2
  4. package/dist/analytics/log-build.cjs +1 -1
  5. package/dist/analytics/log-build.js +3 -3
  6. package/dist/catalog-runtime.cjs +1 -1
  7. package/dist/{chunk-TSY5CC27.js → chunk-4KE3EUDJ.js} +1 -1
  8. package/dist/{chunk-FY6MSP6J.js → chunk-I3XDOICA.js} +1 -1
  9. package/dist/{chunk-QB7X34OD.js → chunk-OFK7U7BX.js} +1 -1
  10. package/dist/{chunk-CX2VB7AI.js → chunk-PI5YNZZZ.js} +1 -1
  11. package/dist/{chunk-BWC4YKW3.js → chunk-WY6M3RPT.js} +1 -1
  12. package/dist/constants.cjs +1 -1
  13. package/dist/constants.js +1 -1
  14. package/dist/eventcatalog.cjs +11 -6
  15. package/dist/eventcatalog.js +14 -9
  16. package/dist/generate.cjs +1 -1
  17. package/dist/generate.js +3 -3
  18. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio-fonts.css.mjs +3 -0
  19. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.css.mjs +3 -0
  20. package/dist/runtime-dependencies/@eventcatalog__visualiser__studio.mjs +3 -0
  21. package/dist/runtime-dependencies/manifest.json +3 -0
  22. package/dist/utils/cli-logger.cjs +1 -1
  23. package/dist/utils/cli-logger.js +2 -2
  24. package/eventcatalog/astro.config.mjs +13 -1
  25. package/eventcatalog/integrations/skip-startup-reload.mjs +31 -0
  26. package/eventcatalog/integrations/stable-dependency-order.mjs +29 -0
  27. package/eventcatalog/src/components/CatalogGraph/CatalogForceGraph.tsx +39 -0
  28. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +11 -3
  29. package/eventcatalog/src/components/Search/SearchDataLoader.astro +16 -28
  30. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +37 -76
  31. package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +2 -0
  32. package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +122 -1
  33. package/eventcatalog/src/components/SideNav/SideNav.astro +9 -1
  34. package/eventcatalog/src/features/mcp/apps/canvas/shared.ts +3 -3
  35. package/eventcatalog/src/features/mcp/apps/canvas/styles.css +3 -1
  36. package/eventcatalog/src/features/mcp/apps/canvas/view.tsx +7 -5
  37. package/eventcatalog/src/features/mcp/apps/generated/canvas.html +133 -71
  38. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +66 -66
  39. package/eventcatalog/src/features/studio/agent-choreography.ts +5 -4
  40. package/eventcatalog/src/features/studio/agents.ts +28 -0
  41. package/eventcatalog/src/features/studio/api/canvases-api.ts +1 -1
  42. package/eventcatalog/src/features/studio/canvas-actions.ts +22 -14
  43. package/eventcatalog/src/features/studio/canvas-preview.ts +1 -2
  44. package/eventcatalog/src/features/studio/catalog.ts +1 -4
  45. package/eventcatalog/src/features/studio/components/CanvasHeader.tsx +246 -115
  46. package/eventcatalog/src/features/studio/components/CanvasStatusMenu.tsx +7 -3
  47. package/eventcatalog/src/features/studio/components/ConnectAgentDialog.tsx +272 -119
  48. package/eventcatalog/src/features/studio/components/ConnectionsChooser.tsx +1 -2
  49. package/eventcatalog/src/features/studio/components/DeleteCanvasDialog.tsx +1 -1
  50. package/eventcatalog/src/features/studio/components/JoinForm.tsx +101 -26
  51. package/eventcatalog/src/features/studio/components/LeftPanel.tsx +102 -241
  52. package/eventcatalog/src/features/studio/components/NodeDetails.tsx +183 -0
  53. package/eventcatalog/src/features/studio/components/OpenInStudioDialog.tsx +1 -1
  54. package/eventcatalog/src/features/studio/components/Presence.tsx +6 -8
  55. package/eventcatalog/src/features/studio/components/ShareDialog.tsx +277 -141
  56. package/eventcatalog/src/features/studio/components/ShortcutsDialog.tsx +41 -0
  57. package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +1005 -354
  58. package/eventcatalog/src/features/studio/document-name.ts +7 -0
  59. package/eventcatalog/src/features/studio/from-visualiser.ts +1 -1
  60. package/eventcatalog/src/features/studio/hooks/presence-sender.ts +19 -2
  61. package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +9 -3
  62. package/eventcatalog/src/features/studio/hooks/use-comments.ts +2 -2
  63. package/eventcatalog/src/features/studio/hooks/use-studio-flow.ts +162 -23
  64. package/eventcatalog/src/features/studio/identity.ts +23 -1
  65. package/eventcatalog/src/features/studio/pages/[id].astro +2 -1
  66. package/eventcatalog/src/features/studio/pages/index.astro +1 -2
  67. package/eventcatalog/src/features/studio/server/canvas-mcp.ts +7 -22
  68. package/eventcatalog/src/features/studio/server/runtime.ts +4 -5
  69. package/package.json +3 -3
  70. package/eventcatalog/src/features/studio/canvas-doc.ts +0 -569
  71. package/eventcatalog/src/features/studio/clipboard.ts +0 -97
  72. package/eventcatalog/src/features/studio/components/CanvasControls.tsx +0 -119
  73. package/eventcatalog/src/features/studio/components/Comments.tsx +0 -777
  74. package/eventcatalog/src/features/studio/components/ContainerChooser.tsx +0 -145
  75. package/eventcatalog/src/features/studio/components/DragGhost.tsx +0 -115
  76. package/eventcatalog/src/features/studio/components/Picture.tsx +0 -21
  77. package/eventcatalog/src/features/studio/components/PropertiesPanel.tsx +0 -212
  78. package/eventcatalog/src/features/studio/components/canvas-nodes.tsx +0 -271
  79. package/eventcatalog/src/features/studio/components/icons.ts +0 -53
  80. package/eventcatalog/src/features/studio/components/status.ts +0 -53
  81. package/eventcatalog/src/features/studio/edges.ts +0 -56
  82. package/eventcatalog/src/features/studio/flow-state.ts +0 -121
  83. package/eventcatalog/src/features/studio/grouping.ts +0 -230
  84. package/eventcatalog/src/features/studio/hooks/use-counter-scale.ts +0 -20
  85. package/eventcatalog/src/features/studio/layout.ts +0 -56
  86. package/eventcatalog/src/features/studio/level-layout.ts +0 -145
  87. package/eventcatalog/src/features/studio/levels.ts +0 -337
  88. package/eventcatalog/src/features/studio/node-types.ts +0 -245
  89. package/eventcatalog/src/features/studio/placement.ts +0 -197
  90. package/eventcatalog/src/features/studio/studio.css +0 -273
@@ -0,0 +1,183 @@
1
+ import { memo, type RefObject } from 'react';
2
+ import type { Node } from '@xyflow/react';
3
+ import { Box, ExternalLink, Library } from 'lucide-react';
4
+ import { getCatalogLink } from '../catalog';
5
+ import {
6
+ EditableText,
7
+ EditStatus,
8
+ Field,
9
+ NodeCard,
10
+ getNodeLabel,
11
+ getResource,
12
+ isVersioned,
13
+ updateResource,
14
+ useSavedFlash,
15
+ type UpdateNodeData,
16
+ NODE_ICONS,
17
+ } from '@eventcatalog/visualiser/studio';
18
+
19
+ /** Something it's connected to: the node at the other end, and the connection's label */
20
+ export type NodeConnection = { id: string; name: string; type?: string; label?: string; outgoing: boolean };
21
+
22
+ /**
23
+ * A node's details, in a card next to it (as Studio on the web's): its type and where it is, and its name, version
24
+ * and summary, saved as they're typed, and what it's connected to (click one to go to it). Catalog resources are read only (they're changed in the catalog), as is
25
+ * everything on a locked canvas. Notes and text are edited on the canvas.
26
+ */
27
+ export default memo(function NodeDetails({
28
+ node,
29
+ parentName,
30
+ connections,
31
+ onOpenNode,
32
+ containerRef,
33
+ locked,
34
+ onChange,
35
+ onClose,
36
+ }: {
37
+ /** What's shown of the node (not its position: the card follows the node on screen by itself) */
38
+ node: Pick<Node, 'id' | 'type' | 'data'>;
39
+ /** The domain or system it's in, if it's in one */
40
+ parentName?: string;
41
+ connections: NodeConnection[];
42
+ /** Goes to a node it's connected to (and shows its card) */
43
+ onOpenNode: (id: string) => void;
44
+ /** The canvas, to put the card next to the node */
45
+ containerRef: RefObject<HTMLElement | null>;
46
+ locked: boolean;
47
+ onChange: UpdateNodeData;
48
+ onClose: () => void;
49
+ }) {
50
+ const { saved, showSaved } = useSavedFlash();
51
+ const resource = getResource(node.type, node.data);
52
+ const link = getCatalogLink(node);
53
+ const label = getNodeLabel(node.type);
54
+ const { icon: Icon, className: iconClassName } = NODE_ICONS[node.type ?? ''] ?? { icon: Box, className: '' };
55
+ const versioned = isVersioned(node.type);
56
+ const name = String(resource.name ?? '');
57
+ const version = String(link?.version ?? resource.version ?? '');
58
+ const summary = String(resource.summary ?? '');
59
+ const save = (fields: Record<string, string>) => onChange(node.id, (data) => updateResource(node.type, data, fields));
60
+
61
+ return (
62
+ <NodeCard
63
+ nodeId={node.id}
64
+ containerRef={containerRef}
65
+ label={name || label}
66
+ onClose={onClose}
67
+ kicker={
68
+ <>
69
+ {/* Its type, in its colour (as the web's type pill) */}
70
+ <span className={`flex-none ${iconClassName}`}>
71
+ <span className="inline-flex items-center gap-1 rounded bg-current px-1.5 text-[9px] font-bold uppercase leading-4 tracking-wider">
72
+ <Icon aria-hidden size={10} className="text-white" />
73
+ <span className="text-white">{label}</span>
74
+ </span>
75
+ </span>
76
+ {parentName && <span className="ec-doc-card-breadcrumb">in {parentName}</span>}
77
+ </>
78
+ }
79
+ header={
80
+ link || locked ? (
81
+ <>
82
+ <h2 className="ec-doc-card-title">
83
+ {name}
84
+ {version && <span className="ec-doc-card-version">v{version}</span>}
85
+ </h2>
86
+ {summary && <p className="ec-doc-card-summary">{summary}</p>}
87
+ {link && (
88
+ <div className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-1.5 text-xs text-[rgb(var(--ec-page-text-muted))]">
89
+ <span className="inline-flex items-center gap-1.5">
90
+ <Library aria-hidden size={13} className="text-[rgb(var(--ec-accent))]" />
91
+ From your catalog: change it there
92
+ </span>
93
+ <a
94
+ href={link.url}
95
+ target="_blank"
96
+ rel="noreferrer"
97
+ className="inline-flex items-center gap-1 font-medium text-[rgb(var(--ec-accent))] hover:underline"
98
+ >
99
+ Open in EventCatalog <ExternalLink aria-hidden size={12} />
100
+ </a>
101
+ </div>
102
+ )}
103
+ </>
104
+ ) : (
105
+ // A small form: what's typed is saved as it's typed (there's nothing to press), and shown on the node
106
+ <div className="ec-edit-form" key={node.id}>
107
+ <Field label="Name">
108
+ <EditableText
109
+ label="Name"
110
+ value={name}
111
+ onSave={(next) => save({ name: next })}
112
+ onSaved={showSaved}
113
+ placeholder={`Name this ${label.toLowerCase()}`}
114
+ className="ec-editable-title"
115
+ required
116
+ />
117
+ </Field>
118
+ {versioned && (
119
+ <Field label="Version" className="ec-field-version">
120
+ <EditableText
121
+ label="Version"
122
+ value={version || '0.0.1'}
123
+ onSave={(next) => save({ version: next })}
124
+ onSaved={showSaved}
125
+ placeholder="0.0.1"
126
+ required
127
+ />
128
+ </Field>
129
+ )}
130
+ <Field label="Summary">
131
+ <EditableText
132
+ label="Summary"
133
+ value={summary}
134
+ onSave={(next) => save({ summary: next })}
135
+ onSaved={showSaved}
136
+ placeholder="What it does, in a sentence or two"
137
+ className="ec-editable-summary"
138
+ multiline
139
+ />
140
+ </Field>
141
+ <EditStatus saved={saved} />
142
+ </div>
143
+ )
144
+ }
145
+ >
146
+ <div className="ec-doc-card-body px-4 pb-3.5 pt-1 empty:hidden">
147
+ {(['Connects to', 'Connected from'] as const).map((heading) => {
148
+ const items = connections.filter((connection) => connection.outgoing === (heading === 'Connects to'));
149
+ if (!items.length) return null;
150
+ return (
151
+ <section key={heading} className="mt-3">
152
+ <h3 className="mb-1.5 text-xs font-semibold text-[rgb(var(--ec-page-text-muted))]">{heading}</h3>
153
+ <ul className="space-y-0.5">
154
+ {items.map((item) => {
155
+ const { icon: ItemIcon, className: itemIconClassName } = NODE_ICONS[item.type ?? ''] ?? {
156
+ icon: Box,
157
+ className: '',
158
+ };
159
+ return (
160
+ <li key={`${item.id}-${item.label}`}>
161
+ <button
162
+ type="button"
163
+ title={`Go to ${item.name}`}
164
+ onClick={() => onOpenNode(item.id)}
165
+ className="flex w-full items-center gap-2 rounded-md px-1.5 py-1 text-left text-sm hover:bg-[rgb(var(--ec-content-hover))]"
166
+ >
167
+ <ItemIcon aria-hidden size={15} className={`flex-none ${itemIconClassName}`} />
168
+ <span className="min-w-0 flex-1 truncate">{item.name}</span>
169
+ {item.label && (
170
+ <span className="flex-none text-[11px] text-[rgb(var(--ec-page-text-muted))]">{item.label}</span>
171
+ )}
172
+ </button>
173
+ </li>
174
+ );
175
+ })}
176
+ </ul>
177
+ </section>
178
+ );
179
+ })}
180
+ </div>
181
+ </NodeCard>
182
+ );
183
+ });
@@ -1,7 +1,7 @@
1
1
  import { useState, type FormEvent } from 'react';
2
2
  import { MAX_TITLE_LENGTH } from '../limits';
3
3
  import Dialog, { PRIMARY_BUTTON, SECONDARY_BUTTON } from './Dialog';
4
- import { STATUS } from './status';
4
+ import { STATUS } from '@eventcatalog/visualiser/studio';
5
5
 
6
6
  /**
7
7
  * Naming the canvas a diagram is opened in (the visualiser's "Open in Studio"), named after the diagram to start
@@ -1,11 +1,9 @@
1
1
  import { Fragment, memo, useEffect, useLayoutEffect, useRef, useSyncExternalStore, type MutableRefObject } from 'react';
2
- import { useInternalNode, useStore, useStoreApi, ViewportPortal, type XYPosition } from '@xyflow/react';
3
- import { Bot, Eye, EyeOff } from 'lucide-react';
4
- import { sizeOf } from '../grouping';
2
+ import { useInternalNode, useStore, useStoreApi, type XYPosition } from '@xyflow/react';
3
+ import { Eye, EyeOff } from 'lucide-react';
4
+ import { CanvasPortal, sizeOf, COUNTER_SCALE, useCounterScale, Picture, AgentMark } from '@eventcatalog/visualiser/studio';
5
5
  import { usePeople, type Peer, type PresenceStore } from '../hooks/presence-store';
6
- import { COUNTER_SCALE, useCounterScale } from '../hooks/use-counter-scale';
7
6
  import { useFollowCamera } from '../hooks/use-follow-camera';
8
- import Picture from './Picture';
9
7
 
10
8
  /**
11
9
  * Other people on the canvas: their pointers, selections and the connections they're dragging. Drawn in the
@@ -26,7 +24,7 @@ export const RemotePresence = memo(function RemotePresence({
26
24
  const others = store ? people.filter((peer) => peer.clientId !== clientId) : [];
27
25
 
28
26
  return (
29
- <ViewportPortal>
27
+ <CanvasPortal>
30
28
  {/* Above nodes (selected ones are raised to 1000) */}
31
29
  <div ref={layer} className="pointer-events-none absolute left-0 top-0" style={{ zIndex: 2000 }}>
32
30
  {others.map((peer) => (
@@ -36,7 +34,7 @@ export const RemotePresence = memo(function RemotePresence({
36
34
  </Fragment>
37
35
  ))}
38
36
  </div>
39
- </ViewportPortal>
37
+ </CanvasPortal>
40
38
  );
41
39
  });
42
40
 
@@ -151,7 +149,7 @@ const PeerPointer = memo(function PeerPointer({ store, peer }: { store: Presence
151
149
  className="absolute left-4 top-4 flex items-center gap-1 whitespace-nowrap rounded px-1.5 py-0.5 text-[11px] font-medium text-white"
152
150
  style={{ backgroundColor: peer.color }}
153
151
  >
154
- {peer.agent && <Bot size={12} />}
152
+ {peer.agent && <AgentMark name={peer.name} size={12} />}
155
153
  <Picture src={peer.picture} className="-ml-0.5 h-4 w-4 shrink-0" />
156
154
  {peer.name}
157
155
  {peer.activity && <span className="font-normal opacity-90">· {peer.activity}</span>}