@eventcatalog/core 5.7.1 → 5.7.2

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.
@@ -94,6 +94,7 @@ import {
94
94
  isGroupType,
95
95
  type Hotspot,
96
96
  type HotspotDraft,
97
+ type HotspotPlace,
97
98
  type HotspotFields,
98
99
  type HotspotSeverity,
99
100
  type HotspotSpot,
@@ -699,6 +700,8 @@ function Canvas({
699
700
  const [lastCopied, setLastCopied] = useState<ClipboardContent | null>(null);
700
701
  // Nodes to copy instead of the selection (copying from the context menu)
701
702
  const copyOnly = useRef<string[] | null>(null);
703
+ // Whether the menu's copy got onto the clipboard (Cut only deletes once it has)
704
+ const copiedFromMenu = useRef(false);
702
705
 
703
706
  /** Adds copies (as one change, so one undo takes them back) and selects them instead of what was selected */
704
707
  const paste = useStableCallback((content: ClipboardContent, place: { at: XYPosition } | { offset: XYPosition }) => {
@@ -731,6 +734,7 @@ function Canvas({
731
734
  event.clipboardData.setData('text/plain', content.nodes.map((node) => getNodeName(node.type, node.data)).join('\n'));
732
735
  pastes.current = 0;
733
736
  setLastCopied(content);
737
+ if (fromMenu) copiedFromMenu.current = true;
734
738
  if (event.type === 'cut') flow.deleteNodes(ids);
735
739
  };
736
740
  const onPaste = (event: ClipboardEvent) => {
@@ -1192,6 +1196,10 @@ function Canvas({
1192
1196
  setHotspotDraft(null);
1193
1197
  });
1194
1198
  const cancelHotspot = useCallback(() => setHotspotDraft(null), []);
1199
+ // The hotspot being added, dragged somewhere else before it's added: onto a node, or a place on the level shown
1200
+ const moveHotspotDraft = useStableCallback((to: HotspotPlace) =>
1201
+ setHotspotDraft((draft) => draft && { ...(to.nodeId ? { nodeId: to.nodeId } : placeLevel()), position: to.position })
1202
+ );
1195
1203
  const deleteHotspot = useStableCallback((id: string) => flow.deleteHotspot(id));
1196
1204
  // Dragged onto a node (they move with it), or to a place; open where it lands if it was open
1197
1205
  const moveHotspots = useStableCallback((ids: string[], to: { nodeId?: string; position: XYPosition }) => {
@@ -1213,8 +1221,8 @@ function Canvas({
1213
1221
  const width = node ? (node.measured?.width ?? node.width ?? 0) : 0;
1214
1222
  void setCenter(at.x + width / 2 + 120, at.y + 80, { zoom: Math.max(getZoom(), 0.8), duration: 300 });
1215
1223
  setHotspotDraft(null);
1224
+ // (the list stays open, so they can go through them one by one)
1216
1225
  setOpenHotspot(node ? `node:${node.id}` : `place:${hotspot.id}`);
1217
- setListingHotspots(false);
1218
1226
  });
1219
1227
  const nameOfNode = useStableCallback((id: string) => {
1220
1228
  const node = nodesRef.current.find((candidate) => candidate.id === id);
@@ -1725,6 +1733,13 @@ function Canvas({
1725
1733
  flow.deleteNodes(menuTargets());
1726
1734
  setContextMenu(null);
1727
1735
  });
1736
+ // Copies, then deletes, as ⌘X does: only on L3, where copying works (so it's not offered on L1 and L2)
1737
+ const cutFromMenu = useStableCallback(() => {
1738
+ copiedFromMenu.current = false;
1739
+ copyFromMenu();
1740
+ // Not copied (the browser refused, or there was nothing to copy): nothing's deleted, as with ⌘X
1741
+ if (copiedFromMenu.current) deleteFromMenu();
1742
+ });
1728
1743
 
1729
1744
  const openThread = useStableCallback((thread: Thread) => {
1730
1745
  setListingComments(false);
@@ -1841,7 +1856,7 @@ function Canvas({
1841
1856
  ref={canvasRef}
1842
1857
  className={`eventcatalog-visualizer studio-canvas relative flex-1 min-w-0 ${commentMode ? 'comment-mode' : ''} ${
1843
1858
  transitioning ? 'is-layout-transition' : ''
1844
- } ${placing || tool === 'comment' || tool === 'hotspot' ? 'is-placing' : ''} ${tool === 'hand' ? 'is-panning' : ''}`}
1859
+ } ${placing || tool === 'comment' || tool === 'hotspot' ? 'is-placing' : ''} ${tool === 'hotspot' ? 'is-placing-hotspot' : ''} ${tool === 'hand' ? 'is-panning' : ''}`}
1845
1860
  onPointerMove={trackPointer}
1846
1861
  onPointerLeave={clearPointer}
1847
1862
  onDoubleClick={onCanvasDoubleClick}
@@ -1938,6 +1953,7 @@ function Canvas({
1938
1953
  onUpdate={flow.updateHotspot}
1939
1954
  onDelete={deleteHotspot}
1940
1955
  onGo={goToHotspot}
1956
+ onMoveDraft={moveHotspotDraft}
1941
1957
  />
1942
1958
  </ReactFlow>
1943
1959
 
@@ -2051,7 +2067,12 @@ function Canvas({
2051
2067
  </button>
2052
2068
  </div>
2053
2069
  <div className="min-h-0 flex-1 overflow-y-auto">
2054
- <HotspotList hotspots={flow.hotspots} nameOf={nameOfNode} onOpen={goToHotspot} />
2070
+ <HotspotList
2071
+ hotspots={flow.hotspots}
2072
+ nameOf={nameOfNode}
2073
+ onOpen={goToHotspot}
2074
+ goOnHover={!hotspotDraft}
2075
+ />
2055
2076
  </div>
2056
2077
  </div>
2057
2078
  )}
@@ -2081,6 +2102,7 @@ function Canvas({
2081
2102
  onAddNote={noteFromMenu}
2082
2103
  onEditDetails={editFromMenu}
2083
2104
  onCopy={copyFromMenu}
2105
+ onCut={level === 3 ? cutFromMenu : undefined}
2084
2106
  onDuplicate={duplicateFromMenu}
2085
2107
  onPaste={lastCopied ? pasteFromMenu : undefined}
2086
2108
  onReorder={reorderFromMenu}
@@ -277,7 +277,7 @@ const createCanvasTools = (get: () => CanvasWebMcpOptions, getStage: () => Agent
277
277
  defineTool({
278
278
  name: 'remove_from_canvas',
279
279
  title: 'Remove from the canvas',
280
- description: 'Removes nodes (and their connections) or connections. Only remove what the user asked for.',
280
+ description: 'Removes nodes (and their connections and hotspots) or connections. Only remove what the user asked for.',
281
281
  input: z.object({ nodeIds: z.array(z.string()).optional(), connectionIds: z.array(z.string()).optional() }),
282
282
  annotations: { consequentialHint: true },
283
283
  execute: async ({ nodeIds = [], connectionIds = [] }) => {
@@ -372,7 +372,7 @@ export function registerCanvasTools(server: McpServer, { catalogUrl, userAgent }
372
372
  {
373
373
  title: 'Remove from a canvas',
374
374
  description:
375
- 'Removes nodes (and their connections) or connections from a canvas. Comments on removed nodes stay on the canvas. Only remove what the user asked for or what you added.',
375
+ 'Removes nodes (and their connections and hotspots) or connections from a canvas. Comments on removed nodes stay on the canvas. Only remove what the user asked for or what you added.',
376
376
  inputSchema: z.object({
377
377
  canvasId,
378
378
  nodeIds: z.array(z.string()).optional(),
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "BUSL-1.1",
9
9
  "type": "module",
10
- "version": "5.7.1",
10
+ "version": "5.7.2",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -142,10 +142,10 @@
142
142
  "yjs": "^13.6.33",
143
143
  "zod": "^4.6.6",
144
144
  "@eventcatalog/exporters": "0.1.4",
145
- "@eventcatalog/linter": "1.3.1",
146
145
  "@eventcatalog/fitness": "0.1.1",
146
+ "@eventcatalog/linter": "1.3.1",
147
147
  "@eventcatalog/sdk": "2.32.0",
148
- "@eventcatalog/visualiser": "^5.2.1"
148
+ "@eventcatalog/visualiser": "^5.2.2"
149
149
  },
150
150
  "devDependencies": {
151
151
  "@astrojs/check": "^0.9.10",