@eventcatalog/core 3.8.2 → 3.9.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.
Files changed (33) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-OCD75GFW.js → chunk-CZG5RQXY.js} +1 -1
  6. package/dist/{chunk-I7HRERRK.js → chunk-FM44RPBS.js} +1 -1
  7. package/dist/{chunk-MOBOWLEW.js → chunk-HJOMVPCL.js} +1 -1
  8. package/dist/{chunk-275AT7XV.js → chunk-OQYLI4YJ.js} +1 -1
  9. package/dist/{chunk-KBMXUUXX.js → chunk-UYBPI4UO.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/eventcatalog.cjs +1 -1
  13. package/dist/eventcatalog.js +5 -5
  14. package/dist/generate.cjs +1 -1
  15. package/dist/generate.js +3 -3
  16. package/dist/utils/cli-logger.cjs +1 -1
  17. package/dist/utils/cli-logger.js +2 -2
  18. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +50 -0
  19. package/eventcatalog/src/components/MDX/Design/Design.astro +4 -1
  20. package/eventcatalog/src/components/MDX/EntityMap/EntityMap.astro +4 -0
  21. package/eventcatalog/src/components/MDX/Flow/Flow.astro +4 -1
  22. package/eventcatalog/src/components/MDX/NodeGraph/MermaidView.tsx +240 -0
  23. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +4 -0
  24. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.tsx +333 -189
  25. package/eventcatalog/src/components/MDX/NodeGraph/VisualizerDropdownContent.tsx +224 -0
  26. package/eventcatalog/src/content.config.ts +1 -1
  27. package/eventcatalog/src/enterprise/ai/chat-api.ts +23 -0
  28. package/eventcatalog/src/enterprise/tools/catalog-tools.ts +96 -0
  29. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version].mermaid.ts +128 -0
  30. package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +4 -0
  31. package/eventcatalog/src/utils/clipboard.ts +22 -0
  32. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +299 -0
  33. package/package.json +1 -1
@@ -37,7 +37,7 @@ var import_axios = __toESM(require("axios"), 1);
37
37
  var import_os = __toESM(require("os"), 1);
38
38
 
39
39
  // package.json
40
- var version = "3.8.2";
40
+ var version = "3.9.0";
41
41
 
42
42
  // src/constants.ts
43
43
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-MOBOWLEW.js";
4
- import "../chunk-KBMXUUXX.js";
3
+ } from "../chunk-HJOMVPCL.js";
4
+ import "../chunk-UYBPI4UO.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -106,7 +106,7 @@ var import_axios = __toESM(require("axios"), 1);
106
106
  var import_os = __toESM(require("os"), 1);
107
107
 
108
108
  // package.json
109
- var version = "3.8.2";
109
+ var version = "3.9.0";
110
110
 
111
111
  // src/constants.ts
112
112
  var VERSION = version;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-I7HRERRK.js";
4
- import "../chunk-MOBOWLEW.js";
5
- import "../chunk-KBMXUUXX.js";
3
+ } from "../chunk-FM44RPBS.js";
4
+ import "../chunk-HJOMVPCL.js";
5
+ import "../chunk-UYBPI4UO.js";
6
6
  import "../chunk-UPONRQSN.js";
7
7
  export {
8
8
  log_build_default as default
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-275AT7XV.js";
3
+ } from "./chunk-OQYLI4YJ.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-MOBOWLEW.js";
3
+ } from "./chunk-HJOMVPCL.js";
4
4
  import {
5
5
  getEventCatalogConfigFile,
6
6
  verifyRequiredFieldsAreInCatalogConfigFile
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-KBMXUUXX.js";
3
+ } from "./chunk-UYBPI4UO.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-KBMXUUXX.js";
3
+ } from "./chunk-UYBPI4UO.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "3.8.2";
2
+ var version = "3.9.0";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "3.8.2";
28
+ var version = "3.9.0";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-KBMXUUXX.js";
3
+ } from "./chunk-UYBPI4UO.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -109,7 +109,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
109
109
  var import_picocolors = __toESM(require("picocolors"), 1);
110
110
 
111
111
  // package.json
112
- var version = "3.8.2";
112
+ var version = "3.9.0";
113
113
 
114
114
  // src/constants.ts
115
115
  var VERSION = version;
@@ -6,8 +6,8 @@ import {
6
6
  } from "./chunk-PLNJC7NZ.js";
7
7
  import {
8
8
  log_build_default
9
- } from "./chunk-I7HRERRK.js";
10
- import "./chunk-MOBOWLEW.js";
9
+ } from "./chunk-FM44RPBS.js";
10
+ import "./chunk-HJOMVPCL.js";
11
11
  import {
12
12
  runMigrations
13
13
  } from "./chunk-BH3JMNAV.js";
@@ -21,13 +21,13 @@ import {
21
21
  } from "./chunk-5VBIXL6C.js";
22
22
  import {
23
23
  generate
24
- } from "./chunk-OCD75GFW.js";
24
+ } from "./chunk-CZG5RQXY.js";
25
25
  import {
26
26
  logger
27
- } from "./chunk-275AT7XV.js";
27
+ } from "./chunk-OQYLI4YJ.js";
28
28
  import {
29
29
  VERSION
30
- } from "./chunk-KBMXUUXX.js";
30
+ } from "./chunk-UYBPI4UO.js";
31
31
  import "./chunk-UPONRQSN.js";
32
32
 
33
33
  // src/eventcatalog.ts
package/dist/generate.cjs CHANGED
@@ -73,7 +73,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
73
73
  var import_picocolors = __toESM(require("picocolors"), 1);
74
74
 
75
75
  // package.json
76
- var version = "3.8.2";
76
+ var version = "3.9.0";
77
77
 
78
78
  // src/constants.ts
79
79
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-OCD75GFW.js";
4
- import "./chunk-275AT7XV.js";
5
- import "./chunk-KBMXUUXX.js";
3
+ } from "./chunk-CZG5RQXY.js";
4
+ import "./chunk-OQYLI4YJ.js";
5
+ import "./chunk-UYBPI4UO.js";
6
6
  import "./chunk-UPONRQSN.js";
7
7
  export {
8
8
  generate
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(cli_logger_exports);
36
36
  var import_picocolors = __toESM(require("picocolors"), 1);
37
37
 
38
38
  // package.json
39
- var version = "3.8.2";
39
+ var version = "3.9.0";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-275AT7XV.js";
4
- import "../chunk-KBMXUUXX.js";
3
+ } from "../chunk-OQYLI4YJ.js";
4
+ import "../chunk-UYBPI4UO.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -171,6 +171,55 @@ const suggestedQuestionsConfig: QuestionConfig[] = [
171
171
  { label: 'Who owns this domain?', prompt: 'Who owns this domain and how do I contact them?' },
172
172
  ],
173
173
  },
174
+ // Business Flows / Workflows (must be before general visualiser pattern)
175
+ {
176
+ pattern: /^\/(docs|visualiser)\/flows\/.+/,
177
+ questions: [
178
+ {
179
+ label: 'Walk me through this workflow',
180
+ prompt:
181
+ 'Get the architecture diagram for this flow and walk me through each step of this business workflow. Explain what happens at each stage.',
182
+ },
183
+ {
184
+ label: 'What services are involved?',
185
+ prompt:
186
+ 'Using the architecture diagram, list all the services involved in this workflow and explain their role in the process.',
187
+ },
188
+ {
189
+ label: 'What events does this trigger?',
190
+ prompt: 'What events are produced during this workflow? When are they triggered and who consumes them?',
191
+ },
192
+ {
193
+ label: 'What can go wrong?',
194
+ prompt:
195
+ 'Analyze this workflow and identify potential failure points. What happens if a step fails? Are there retry mechanisms or compensating actions?',
196
+ },
197
+ ],
198
+ },
199
+ // Visualizer page (/visualiser/*) - general fallback for other visualiser pages
200
+ {
201
+ pattern: /^\/visualiser\/.+/,
202
+ questions: [
203
+ {
204
+ label: 'Explain this architecture',
205
+ prompt:
206
+ 'Get the architecture diagram for this resource and explain what I am looking at. Describe the key components and how they connect.',
207
+ },
208
+ {
209
+ label: 'What are the dependencies?',
210
+ prompt: 'Using the architecture diagram, show me what this resource depends on and what depends on it.',
211
+ },
212
+ {
213
+ label: 'How does data flow here?',
214
+ prompt: 'Get the architecture diagram and explain how data flows through this part of the system.',
215
+ },
216
+ {
217
+ label: 'What would break if this changes?',
218
+ prompt:
219
+ 'Analyze the architecture diagram to identify what services or components would be affected if this resource changes.',
220
+ },
221
+ ],
222
+ },
174
223
  // Data Products page
175
224
  {
176
225
  pattern: /^\/(docs|visualiser)\/data-products\/.+/,
@@ -182,6 +231,7 @@ const suggestedQuestionsConfig: QuestionConfig[] = [
182
231
  { label: 'Who owns this data product?', prompt: 'Who owns this data product and how do I contact them?' },
183
232
  ],
184
233
  },
234
+
185
235
  // Designs page
186
236
  {
187
237
  pattern: /^\/diagrams\/.+/,
@@ -5,7 +5,9 @@ import { getAbsoluteFilePathForAstroFile } from '@utils/files';
5
5
  import Admonition from '@components/MDX/Admonition';
6
6
  import NodeGraph from '../NodeGraph/NodeGraph';
7
7
 
8
- import { isVisualiserEnabled } from '@utils/feature';
8
+ import { isVisualiserEnabled, isEventCatalogChatEnabled } from '@utils/feature';
9
+
10
+ const isChatEnabled = isEventCatalogChatEnabled();
9
11
 
10
12
  let design: any;
11
13
  let id = 'design';
@@ -57,6 +59,7 @@ try {
57
59
  designId={design.id || id}
58
60
  client:only="react"
59
61
  showSearch={search}
62
+ isChatEnabled={isChatEnabled}
60
63
  />
61
64
  </div>
62
65
  </div>
@@ -5,6 +5,9 @@ import Admonition from '@components/MDX/Admonition';
5
5
  import NodeGraph from '../NodeGraph/NodeGraph';
6
6
  import { getVersionFromCollection } from '@utils/collections/versions';
7
7
  import { getServices } from '@utils/collections/services';
8
+ import { isEventCatalogChatEnabled } from '@utils/feature';
9
+
10
+ const isChatEnabled = isEventCatalogChatEnabled();
8
11
 
9
12
  const { id, version = 'latest', maxHeight, includeKey = true, entities, collection = 'domains', ...rest } = Astro.props;
10
13
  let resource = null;
@@ -71,6 +74,7 @@ const { nodes, edges } = await getNodesAndEdges({
71
74
  footerLabel={`Entity Map - ${resource?.data?.name} - v(${resource?.data?.version})`}
72
75
  client:only="react"
73
76
  portalId={`${id}-entity-map-portal`}
77
+ isChatEnabled={isChatEnabled}
74
78
  />
75
79
  </div>
76
80
 
@@ -4,7 +4,9 @@ import { getNodesAndEdges } from '@utils/node-graphs/flows-node-graph';
4
4
  import Admonition from '@components/MDX/Admonition';
5
5
  import NodeGraph from '../NodeGraph/NodeGraph';
6
6
  import { getVersionFromCollection } from '@utils/collections/versions';
7
- import { isVisualiserEnabled } from '@utils/feature';
7
+ import { isVisualiserEnabled, isEventCatalogChatEnabled } from '@utils/feature';
8
+
9
+ const isChatEnabled = isEventCatalogChatEnabled();
8
10
 
9
11
  const { id, version = 'latest', maxHeight, includeKey = true, mode = 'simple', walkthrough = true, search = true } = Astro.props;
10
12
 
@@ -57,6 +59,7 @@ const { nodes, edges } = await getNodesAndEdges({
57
59
  client:only="react"
58
60
  showFlowWalkthrough={walkthrough}
59
61
  showSearch={search}
62
+ isChatEnabled={isChatEnabled}
60
63
  />
61
64
  </div>
62
65
 
@@ -0,0 +1,240 @@
1
+ import React, { useState, useEffect, useRef, useCallback } from 'react';
2
+ import { CheckIcon, ClipboardIcon } from 'lucide-react';
3
+ import type { Node, Edge } from '@xyflow/react';
4
+ import { convertToMermaid } from '@utils/node-graphs/export-mermaid';
5
+ import { copyToClipboard } from '@utils/clipboard';
6
+
7
+ interface MermaidViewProps {
8
+ nodes: Node[];
9
+ edges: Edge[];
10
+ }
11
+
12
+ const MermaidView = ({ nodes, edges }: MermaidViewProps) => {
13
+ const [copySuccess, setCopySuccess] = useState(false);
14
+ const [mermaidCode, setMermaidCode] = useState('');
15
+ const [previewSvg, setPreviewSvg] = useState<string | null>(null);
16
+ const [previewError, setPreviewError] = useState<string | null>(null);
17
+ const [isRendering, setIsRendering] = useState(true);
18
+ const containerRef = useRef<HTMLDivElement>(null);
19
+ const svgContainerRef = useRef<HTMLDivElement>(null);
20
+ const panZoomInstanceRef = useRef<any>(null);
21
+
22
+ // Generate mermaid code
23
+ useEffect(() => {
24
+ const code = convertToMermaid(nodes, edges, { includeStyles: true, direction: 'LR' });
25
+ setMermaidCode(code);
26
+ }, [nodes, edges]);
27
+
28
+ // Render mermaid preview
29
+ useEffect(() => {
30
+ if (!mermaidCode) return;
31
+
32
+ let cancelled = false;
33
+ setIsRendering(true);
34
+ setPreviewError(null);
35
+
36
+ const renderMermaid = async () => {
37
+ try {
38
+ const { default: mermaid } = await import('mermaid');
39
+
40
+ // Detect current theme
41
+ const isDarkMode = document.documentElement.getAttribute('data-theme') === 'dark';
42
+ const currentTheme = isDarkMode ? 'dark' : 'default';
43
+
44
+ mermaid.initialize({
45
+ startOnLoad: false,
46
+ theme: currentTheme,
47
+ flowchart: {
48
+ curve: 'basis',
49
+ padding: 20,
50
+ },
51
+ securityLevel: 'loose',
52
+ });
53
+
54
+ const id = 'mermaid-view-' + Math.random().toString(36).substring(2, 9);
55
+ const { svg } = await mermaid.render(id, mermaidCode);
56
+
57
+ if (!cancelled) {
58
+ setPreviewSvg(svg);
59
+ setPreviewError(null);
60
+ }
61
+ } catch (error) {
62
+ if (!cancelled) {
63
+ console.error('Mermaid render error:', error);
64
+ setPreviewError(error instanceof Error ? error.message : 'Failed to render diagram');
65
+ setPreviewSvg(null);
66
+ }
67
+ } finally {
68
+ if (!cancelled) {
69
+ setIsRendering(false);
70
+ }
71
+ }
72
+ };
73
+
74
+ renderMermaid();
75
+
76
+ return () => {
77
+ cancelled = true;
78
+ };
79
+ }, [mermaidCode]);
80
+
81
+ // Initialize pan/zoom after SVG is rendered
82
+ useEffect(() => {
83
+ if (!previewSvg || !svgContainerRef.current) return;
84
+
85
+ const initZoom = async () => {
86
+ const svgElement = svgContainerRef.current?.querySelector('svg');
87
+ if (!svgElement) return;
88
+
89
+ try {
90
+ const { default: svgPanZoom } = await import('svg-pan-zoom');
91
+
92
+ // Set SVG to fill container
93
+ svgElement.style.width = '100%';
94
+ svgElement.style.height = '100%';
95
+ svgElement.removeAttribute('height');
96
+ svgElement.removeAttribute('width');
97
+
98
+ const instance = svgPanZoom(svgElement, {
99
+ zoomEnabled: true,
100
+ controlIconsEnabled: false,
101
+ fit: true,
102
+ center: true,
103
+ minZoom: 0.1,
104
+ maxZoom: 10,
105
+ zoomScaleSensitivity: 0.15,
106
+ dblClickZoomEnabled: true,
107
+ mouseWheelZoomEnabled: true,
108
+ panEnabled: true,
109
+ });
110
+
111
+ panZoomInstanceRef.current = instance;
112
+ } catch (e) {
113
+ console.warn('Failed to initialize zoom:', e);
114
+ }
115
+ };
116
+
117
+ initZoom();
118
+
119
+ return () => {
120
+ if (panZoomInstanceRef.current) {
121
+ try {
122
+ panZoomInstanceRef.current.destroy();
123
+ } catch (e) {
124
+ // Ignore
125
+ }
126
+ panZoomInstanceRef.current = null;
127
+ }
128
+ };
129
+ }, [previewSvg]);
130
+
131
+ const handleCopyToClipboard = useCallback(async () => {
132
+ await copyToClipboard(mermaidCode);
133
+ setCopySuccess(true);
134
+ setTimeout(() => setCopySuccess(false), 2000);
135
+ }, [mermaidCode]);
136
+
137
+ return (
138
+ <div
139
+ ref={containerRef}
140
+ className="w-full h-full bg-[rgb(var(--ec-page-bg))] relative flex flex-col"
141
+ style={{ animation: 'fadeIn 200ms ease-out' }}
142
+ >
143
+ <style>{`
144
+ @keyframes fadeIn {
145
+ from { opacity: 0; }
146
+ to { opacity: 1; }
147
+ }
148
+ `}</style>
149
+
150
+ {/* Copy button - top right */}
151
+ <div className="absolute top-[10px] right-4 z-20">
152
+ <div className="relative group">
153
+ <button
154
+ onClick={handleCopyToClipboard}
155
+ className={`p-2.5 rounded-md shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[rgb(var(--ec-accent))] transition-all duration-150 ${
156
+ copySuccess
157
+ ? 'bg-green-500 text-white scale-110'
158
+ : 'bg-[rgb(var(--ec-card-bg))] hover:bg-[rgb(var(--ec-page-border))/0.5] text-[rgb(var(--ec-icon-color))] hover:scale-105'
159
+ }`}
160
+ aria-label={copySuccess ? 'Copied!' : 'Copy Mermaid code'}
161
+ >
162
+ {copySuccess ? <CheckIcon className="h-5 w-5" /> : <ClipboardIcon className="h-5 w-5" />}
163
+ </button>
164
+ <div className="absolute top-full right-0 mt-2 px-2 py-1 bg-[rgb(var(--ec-page-text))] text-[rgb(var(--ec-page-bg))] text-xs rounded shadow-lg opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-50">
165
+ {copySuccess ? 'Copied!' : 'Copy Mermaid code'}
166
+ </div>
167
+ </div>
168
+ </div>
169
+
170
+ {/* Mermaid diagram container */}
171
+ <div className="flex-1 overflow-hidden">
172
+ {isRendering && (
173
+ <div className="w-full h-full flex items-center justify-center">
174
+ <div className="relative">
175
+ <div className="flex items-center gap-4 opacity-40">
176
+ <div className="w-24 h-10 bg-[rgb(var(--ec-page-border))] rounded animate-pulse" />
177
+ <div className="w-12 h-0.5 bg-[rgb(var(--ec-page-border))] animate-pulse" />
178
+ <div
179
+ className="w-20 h-10 bg-[rgb(var(--ec-page-border))] rounded-full animate-pulse"
180
+ style={{ animationDelay: '75ms' }}
181
+ />
182
+ <div className="w-12 h-0.5 bg-[rgb(var(--ec-page-border))] animate-pulse" style={{ animationDelay: '150ms' }} />
183
+ <div
184
+ className="w-24 h-10 bg-[rgb(var(--ec-page-border))] rounded animate-pulse"
185
+ style={{ animationDelay: '225ms' }}
186
+ />
187
+ </div>
188
+ <p className="text-center text-sm text-[rgb(var(--ec-page-text-muted))] mt-4">Rendering diagram...</p>
189
+ </div>
190
+ </div>
191
+ )}
192
+
193
+ {previewError && !isRendering && (
194
+ <div className="w-full h-full flex flex-col items-center justify-center p-4">
195
+ <div className="text-red-500 text-sm mb-2">Failed to render diagram</div>
196
+ <div className="text-[rgb(var(--ec-page-text-muted))] text-xs font-mono bg-[rgb(var(--ec-code-bg))] p-2 rounded max-w-lg overflow-auto">
197
+ {previewError}
198
+ </div>
199
+ <div className="mt-4 text-sm text-[rgb(var(--ec-page-text-muted))]">
200
+ <p>You can still copy the Mermaid code and paste it into</p>
201
+ <a
202
+ href="https://mermaid.live"
203
+ target="_blank"
204
+ rel="noopener noreferrer"
205
+ className="text-[rgb(var(--ec-accent))] hover:underline"
206
+ >
207
+ mermaid.live
208
+ </a>
209
+ </div>
210
+ </div>
211
+ )}
212
+
213
+ {previewSvg && !isRendering && !previewError && (
214
+ <div
215
+ ref={svgContainerRef}
216
+ className="w-full h-full cursor-grab active:cursor-grabbing [&_svg]:w-full [&_svg]:h-full"
217
+ dangerouslySetInnerHTML={{ __html: previewSvg }}
218
+ />
219
+ )}
220
+ </div>
221
+
222
+ {/* Footer hint */}
223
+ <div className="absolute bottom-4 left-4 z-20">
224
+ <div className="flex items-center gap-2 bg-[rgb(var(--ec-card-bg))]/90 backdrop-blur-sm px-3 py-1.5 rounded-md shadow-sm border border-[rgb(var(--ec-page-border))]">
225
+ <svg className="w-3.5 h-3.5 text-[rgb(var(--ec-icon-color))]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
226
+ <path
227
+ strokeLinecap="round"
228
+ strokeLinejoin="round"
229
+ strokeWidth={2}
230
+ d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
231
+ />
232
+ </svg>
233
+ <span className="text-xs text-[rgb(var(--ec-page-text-muted))]">Scroll to zoom · Drag to pan</span>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ );
238
+ };
239
+
240
+ export default MermaidView;
@@ -19,6 +19,9 @@ import { getVersionFromCollection } from '@utils/collections/versions';
19
19
  import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
20
20
  import { getNodesAndEdges as getNodesAndEdgesForContainer } from '@utils/node-graphs/container-node-graph';
21
21
  import config from '@config';
22
+ import { isEventCatalogChatEnabled } from '@utils/feature';
23
+
24
+ const isChatEnabled = isEventCatalogChatEnabled();
22
25
 
23
26
  interface Props {
24
27
  id: string;
@@ -154,6 +157,7 @@ if (collection === 'services-containers') {
154
157
  showSearch={showSearch}
155
158
  includeKey={showLegend}
156
159
  zoomOnScroll={zoomOnScroll}
160
+ isChatEnabled={isChatEnabled}
157
161
  />
158
162
  </div>
159
163