@eventcatalog/core 4.10.15 → 4.11.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 (128) 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-HBVTU6ZP.js → chunk-DWC5GRFX.js} +1 -1
  6. package/dist/{chunk-A4JRWRCV.js → chunk-H3324DNT.js} +1 -1
  7. package/dist/{chunk-I6HUOX4R.js → chunk-SW7SJZIX.js} +1 -1
  8. package/dist/{chunk-7LWOCX4R.js → chunk-W4LDIMUI.js} +1 -1
  9. package/dist/{chunk-Q2ATWE7N.js → chunk-XJOKK5ZO.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/astro.config.mjs +2 -1
  19. package/eventcatalog/public/icons/languages/android.svg +1 -0
  20. package/eventcatalog/public/icons/languages/angular.svg +1 -0
  21. package/eventcatalog/public/icons/languages/apple.svg +1 -0
  22. package/eventcatalog/public/icons/languages/arduino.svg +1 -0
  23. package/eventcatalog/public/icons/languages/bash.svg +1 -0
  24. package/eventcatalog/public/icons/languages/bun.svg +1 -0
  25. package/eventcatalog/public/icons/languages/c.svg +1 -0
  26. package/eventcatalog/public/icons/languages/clojure.svg +1 -0
  27. package/eventcatalog/public/icons/languages/cpp.svg +1 -0
  28. package/eventcatalog/public/icons/languages/crystal.svg +1 -0
  29. package/eventcatalog/public/icons/languages/csharp.svg +1 -0
  30. package/eventcatalog/public/icons/languages/css.svg +1 -0
  31. package/eventcatalog/public/icons/languages/curl.svg +1 -0
  32. package/eventcatalog/public/icons/languages/dart.svg +1 -0
  33. package/eventcatalog/public/icons/languages/deno.svg +1 -0
  34. package/eventcatalog/public/icons/languages/docker.svg +1 -0
  35. package/eventcatalog/public/icons/languages/elm.svg +1 -0
  36. package/eventcatalog/public/icons/languages/erlang.svg +1 -0
  37. package/eventcatalog/public/icons/languages/flutter.svg +1 -0
  38. package/eventcatalog/public/icons/languages/fortran.svg +1 -0
  39. package/eventcatalog/public/icons/languages/fsharp.svg +1 -0
  40. package/eventcatalog/public/icons/languages/git.svg +1 -0
  41. package/eventcatalog/public/icons/languages/gradle.svg +1 -0
  42. package/eventcatalog/public/icons/languages/graphql.svg +1 -0
  43. package/eventcatalog/public/icons/languages/grpc.svg +1 -0
  44. package/eventcatalog/public/icons/languages/haskell.svg +1 -0
  45. package/eventcatalog/public/icons/languages/hasura.svg +1 -0
  46. package/eventcatalog/public/icons/languages/html.svg +1 -0
  47. package/eventcatalog/public/icons/languages/httpie.svg +1 -0
  48. package/eventcatalog/public/icons/languages/javascript.svg +1 -0
  49. package/eventcatalog/public/icons/languages/json-schema.svg +1 -0
  50. package/eventcatalog/public/icons/languages/json.svg +1 -0
  51. package/eventcatalog/public/icons/languages/julia.svg +1 -0
  52. package/eventcatalog/public/icons/languages/jupyter.svg +1 -0
  53. package/eventcatalog/public/icons/languages/kafka.svg +1 -0
  54. package/eventcatalog/public/icons/languages/kotlin.svg +1 -0
  55. package/eventcatalog/public/icons/languages/lua.svg +1 -0
  56. package/eventcatalog/public/icons/languages/markdown.svg +1 -0
  57. package/eventcatalog/public/icons/languages/maven.svg +1 -0
  58. package/eventcatalog/public/icons/languages/mongodb.svg +1 -0
  59. package/eventcatalog/public/icons/languages/mysql.svg +1 -0
  60. package/eventcatalog/public/icons/languages/nginx.svg +1 -0
  61. package/eventcatalog/public/icons/languages/nim.svg +1 -0
  62. package/eventcatalog/public/icons/languages/ocaml.svg +1 -0
  63. package/eventcatalog/public/icons/languages/perl.svg +1 -0
  64. package/eventcatalog/public/icons/languages/php.svg +1 -0
  65. package/eventcatalog/public/icons/languages/postgresql.svg +1 -0
  66. package/eventcatalog/public/icons/languages/prisma.svg +1 -0
  67. package/eventcatalog/public/icons/languages/purescript.svg +1 -0
  68. package/eventcatalog/public/icons/languages/python.svg +1 -0
  69. package/eventcatalog/public/icons/languages/r.svg +1 -0
  70. package/eventcatalog/public/icons/languages/react.svg +1 -0
  71. package/eventcatalog/public/icons/languages/reasonml.svg +1 -0
  72. package/eventcatalog/public/icons/languages/redis.svg +1 -0
  73. package/eventcatalog/public/icons/languages/ruby.svg +1 -0
  74. package/eventcatalog/public/icons/languages/rust.svg +1 -0
  75. package/eventcatalog/public/icons/languages/sass.svg +1 -0
  76. package/eventcatalog/public/icons/languages/scala.svg +1 -0
  77. package/eventcatalog/public/icons/languages/solidity.svg +1 -0
  78. package/eventcatalog/public/icons/languages/spring.svg +1 -0
  79. package/eventcatalog/public/icons/languages/sqlite.svg +1 -0
  80. package/eventcatalog/public/icons/languages/svelte.svg +1 -0
  81. package/eventcatalog/public/icons/languages/swagger.svg +1 -0
  82. package/eventcatalog/public/icons/languages/swift.svg +1 -0
  83. package/eventcatalog/public/icons/languages/tailwind.svg +1 -0
  84. package/eventcatalog/public/icons/languages/terraform.svg +1 -0
  85. package/eventcatalog/public/icons/languages/toml.svg +1 -0
  86. package/eventcatalog/public/icons/languages/typescript.svg +1 -0
  87. package/eventcatalog/public/icons/languages/unity.svg +1 -0
  88. package/eventcatalog/public/icons/languages/vim.svg +1 -0
  89. package/eventcatalog/public/icons/languages/vue.svg +1 -0
  90. package/eventcatalog/public/icons/languages/webassembly.svg +1 -0
  91. package/eventcatalog/public/icons/languages/yaml.svg +1 -0
  92. package/eventcatalog/public/icons/languages/zig.svg +1 -0
  93. package/eventcatalog/src/components/MDX/CodeGroup/CodeGroup.astro +12 -0
  94. package/eventcatalog/src/components/MDX/CodeGroup/CodeGroup.tsx +176 -0
  95. package/eventcatalog/src/components/MDX/CodeGroup/MarkdownCodeGroup.tsx +22 -0
  96. package/eventcatalog/src/components/MDX/CodeGroup/code-group-icons.ts +345 -0
  97. package/eventcatalog/src/components/MDX/CodeGroup/code-group.css +22 -0
  98. package/eventcatalog/src/components/MDX/CodeGroup/code-group.spec.tsx +89 -0
  99. package/eventcatalog/src/components/MDX/CodeGroup/parse-panels.ts +11 -0
  100. package/eventcatalog/src/components/MDX/Columns/Column.astro +10 -0
  101. package/eventcatalog/src/components/MDX/Columns/Columns.astro +14 -0
  102. package/eventcatalog/src/components/MDX/Columns/MarkdownColumns.tsx +37 -0
  103. package/eventcatalog/src/components/MDX/Columns/columns.spec.tsx +66 -0
  104. package/eventcatalog/src/components/MDX/Columns/layout.ts +16 -0
  105. package/eventcatalog/src/components/MDX/components.tsx +6 -0
  106. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +1 -1
  107. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +151 -114
  108. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +510 -248
  109. package/eventcatalog/src/components/SchemaExplorer/SchemaFlows.tsx +76 -0
  110. package/eventcatalog/src/components/SchemaExplorer/SchemaGraph.tsx +47 -0
  111. package/eventcatalog/src/components/SchemaExplorer/SchemaPageViewer.tsx +11 -0
  112. package/eventcatalog/src/components/SchemaExplorer/SchemaUsage.tsx +17 -0
  113. package/eventcatalog/src/components/SchemaExplorer/types.ts +48 -3
  114. package/eventcatalog/src/components/SchemaExplorer/utils.ts +28 -1
  115. package/eventcatalog/src/content.config.ts +28 -0
  116. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +38 -7
  117. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +144 -37
  118. package/eventcatalog/src/pages/schemas/explorer/index.astro +5 -0
  119. package/eventcatalog/src/remark-plugins/code-group.ts +39 -0
  120. package/eventcatalog/src/remark-plugins/markdown-code-group.ts +59 -0
  121. package/eventcatalog/src/remark-plugins/markdown-columns.ts +66 -0
  122. package/eventcatalog/src/utils/collections/examples.ts +133 -41
  123. package/eventcatalog/src/utils/collections/flows.ts +43 -0
  124. package/eventcatalog/src/utils/collections/messages.ts +2 -2
  125. package/eventcatalog/src/utils/collections/schemas.ts +15 -0
  126. package/eventcatalog/src/utils/schema-explorer.ts +73 -7
  127. package/eventcatalog/src/utils/schema-usage-graph.ts +92 -0
  128. package/package.json +4 -4
@@ -1,146 +1,183 @@
1
- import { useState, useEffect } from 'react';
2
- import { ClipboardDocumentIcon } from '@heroicons/react/24/outline';
1
+ import { createContext, useContext, useState, type ReactNode } from 'react';
2
+ import ReactMarkdown from 'react-markdown';
3
+ import remarkGfm from 'remark-gfm';
4
+ import { CheckIcon, ClipboardDocumentIcon } from '@heroicons/react/24/outline';
3
5
  import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
4
6
  import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
5
7
  import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
6
- import { getLanguageForHighlight } from './utils';
7
8
  import { copyToClipboard } from './utils';
8
9
  import type { MessageExample } from './types';
9
10
  import { useDarkMode } from './useDarkMode';
11
+ import { remarkMarkdownCodeGroup } from '../../remark-plugins/markdown-code-group';
12
+ import { MarkdownCodeGroup } from '../MDX/CodeGroup/MarkdownCodeGroup';
13
+ import { MarkdownColumns, MarkdownColumn } from '../MDX/Columns/MarkdownColumns';
14
+ import { remarkMarkdownColumns } from '../../remark-plugins/markdown-columns';
15
+ import { getLanguageForHighlight } from './utils';
10
16
 
11
17
  interface ExamplesViewerProps {
12
18
  examples: MessageExample[];
13
19
  }
14
20
 
15
- export default function ExamplesViewer({ examples }: ExamplesViewerProps) {
16
- const [selectedIndex, setSelectedIndex] = useState(0);
17
- const [copiedId, setCopiedId] = useState<string | null>(null);
18
- const isDarkMode = useDarkMode();
21
+ const PROSE_CLASS = [
22
+ 'prose prose-sm max-w-none',
23
+ 'prose-headings:text-[rgb(var(--ec-page-text))] prose-h1:mt-0 prose-h1:text-4xl prose-h1:font-bold prose-h1:tracking-tight',
24
+ 'prose-p:text-[rgb(var(--ec-page-text-muted))] prose-li:text-[rgb(var(--ec-page-text-muted))] prose-strong:text-[rgb(var(--ec-page-text))]',
25
+ 'prose-a:text-[rgb(var(--ec-accent))] prose-table:text-[rgb(var(--ec-page-text-muted))] prose-th:text-[rgb(var(--ec-page-text))]',
26
+ 'prose-blockquote:border-[rgb(var(--ec-page-border))] prose-blockquote:text-[rgb(var(--ec-page-text-muted))] prose-hr:border-[rgb(var(--ec-page-border))]',
27
+ ].join(' ');
19
28
 
20
- useEffect(() => {
21
- setSelectedIndex(0);
22
- }, [examples]);
29
+ const getCodeText = (children: ReactNode): string =>
30
+ Array.isArray(children) ? children.map(getCodeText).join('') : typeof children === 'string' ? children : '';
23
31
 
24
- if (examples.length === 0) {
32
+ /** True while rendering inside a CodeGroup panel, where the group supplies the header and copy button. */
33
+ const CodeGroupPanelContext = createContext(false);
34
+
35
+ /** Fenced code block rendered as the same themed code panel used across the schema page. */
36
+ function CodeBlock({ language, code }: { language?: string; code: string }) {
37
+ const isDarkMode = useDarkMode();
38
+ const [isCopied, setIsCopied] = useState(false);
39
+ const inCodeGroup = useContext(CodeGroupPanelContext);
40
+ const content = code.replace(/\s+$/, '');
41
+ const highlighter = (
42
+ <SyntaxHighlighter
43
+ language={language || 'text'}
44
+ style={isDarkMode ? oneDark : oneLight}
45
+ customStyle={{
46
+ margin: 0,
47
+ padding: '1rem 1.25rem',
48
+ borderRadius: 0,
49
+ fontSize: '0.8125rem',
50
+ lineHeight: '1.65',
51
+ background: 'transparent',
52
+ }}
53
+ showLineNumbers={content.includes('\n')}
54
+ wrapLines={true}
55
+ wrapLongLines={true}
56
+ >
57
+ {content}
58
+ </SyntaxHighlighter>
59
+ );
60
+
61
+ // Inside a group the panel chrome (file name, language picker, copy) belongs to the group.
62
+ // Keep the raw source on a data attribute so the group's copy button gets clean text.
63
+ if (inCodeGroup) {
25
64
  return (
26
- <div className="flex items-center justify-center h-full text-[rgb(var(--ec-page-text-muted))]">
27
- <p className="text-sm">No examples available</p>
65
+ <div data-code={content} className="not-prose max-h-[70vh] overflow-auto">
66
+ {highlighter}
28
67
  </div>
29
68
  );
30
69
  }
31
70
 
32
- const selected = examples[selectedIndex];
33
- const lang = getLanguageForHighlight(selected.extension);
34
-
35
- const handleCopy = async (content: string, id: string) => {
36
- const success = await copyToClipboard(content);
37
- if (success) {
38
- setCopiedId(id);
39
- setTimeout(() => setCopiedId(null), 2000);
71
+ const handleCopy = async () => {
72
+ if (await copyToClipboard(content)) {
73
+ setIsCopied(true);
74
+ setTimeout(() => setIsCopied(false), 2000);
40
75
  }
41
76
  };
42
77
 
43
78
  return (
44
- <div className="h-full flex gap-4 overflow-hidden">
45
- {/* Left: example list */}
46
- <div className="flex-shrink-0 w-56 overflow-y-auto space-y-1">
47
- {examples.map((ex, idx) => (
48
- <button
49
- key={ex.fileName}
50
- onClick={() => setSelectedIndex(idx)}
51
- className={`w-full text-left px-3 py-2.5 rounded-lg transition-colors ${
52
- idx === selectedIndex
53
- ? 'bg-[rgb(var(--ec-accent-subtle))] border border-[rgb(var(--ec-accent)/0.3)]'
54
- : 'hover:bg-[rgb(var(--ec-content-hover))] border border-transparent'
55
- }`}
56
- >
57
- <span
58
- className={`block text-xs font-medium truncate ${
59
- idx === selectedIndex ? 'text-[rgb(var(--ec-page-text))]' : 'text-[rgb(var(--ec-page-text-muted))]'
60
- }`}
61
- >
62
- {ex.title}
63
- </span>
64
- {ex.summary && (
65
- <span className="block text-[11px] text-[rgb(var(--ec-page-text-muted))] mt-0.5 line-clamp-2 leading-relaxed">
66
- {ex.summary}
67
- </span>
68
- )}
69
- </button>
70
- ))}
79
+ <div
80
+ data-example-code-block
81
+ className="not-prose my-4 overflow-hidden rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-code-bg))] shadow-sm"
82
+ >
83
+ <div className="flex items-center justify-between gap-3 border-b border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover)/0.45)] px-3 py-1.5">
84
+ <span className="rounded-md bg-[rgb(var(--ec-content-hover))] px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider text-[rgb(var(--ec-page-text-muted))]">
85
+ {language || 'text'}
86
+ </span>
87
+ <button
88
+ type="button"
89
+ onClick={handleCopy}
90
+ className={`inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-colors ${
91
+ isCopied
92
+ ? 'text-emerald-500'
93
+ : 'text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-page-text))]'
94
+ }`}
95
+ title="Copy code"
96
+ >
97
+ {isCopied ? <CheckIcon className="h-3.5 w-3.5" /> : <ClipboardDocumentIcon className="h-3.5 w-3.5" />}
98
+ {isCopied ? 'Copied' : 'Copy'}
99
+ </button>
71
100
  </div>
101
+ <div className="max-h-[70vh] overflow-auto">{highlighter}</div>
102
+ </div>
103
+ );
104
+ }
72
105
 
73
- {/* Right: code + usage */}
74
- <div className="flex-1 flex flex-col min-w-0 overflow-auto">
75
- {/* Code window */}
76
- <div className="flex flex-col rounded-lg border border-[rgb(var(--ec-page-border))] overflow-hidden bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
77
- {/* Window title bar */}
78
- <div className="flex items-center justify-between border-b border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover)/0.45)] px-4 py-2.5">
79
- <div className="flex items-center gap-3">
80
- <div className="flex items-center gap-1.5">
81
- <div className="w-3 h-3 rounded-full bg-[#FF5F56]" />
82
- <div className="w-3 h-3 rounded-full bg-[#FFBD2E]" />
83
- <div className="w-3 h-3 rounded-full bg-[#27C93F]" />
84
- </div>
85
- <span className="text-xs font-mono text-[rgb(var(--ec-page-text-muted))]">{selected.fileName}</span>
86
- </div>
87
-
88
- <button
89
- onClick={() => handleCopy(selected.content, selected.fileName)}
90
- className="inline-flex items-center gap-1 px-2 py-1 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-page-bg)/0.5)] hover:text-[rgb(var(--ec-page-text))] rounded transition-colors"
91
- title="Copy code"
92
- >
93
- <ClipboardDocumentIcon className="h-3 w-3" />
94
- {copiedId === selected.fileName ? 'Copied!' : 'Copy'}
95
- </button>
96
- </div>
106
+ const markdownComponents = {
107
+ div: ({ node: _node, children, ...props }: any) =>
108
+ props['data-columns'] ? (
109
+ <MarkdownColumns cols={Number(props['data-cols'])} ratio={props['data-ratio']} className={props.className}>
110
+ {children}
111
+ </MarkdownColumns>
112
+ ) : props['data-column'] ? (
113
+ <MarkdownColumn sticky={props['data-sticky'] === 'true'} className={props.className}>
114
+ {children}
115
+ </MarkdownColumn>
116
+ ) : props['data-code-group'] ? (
117
+ <MarkdownCodeGroup dropdown={props['data-dropdown'] === 'true'} className={props.className}>
118
+ {children}
119
+ </MarkdownCodeGroup>
120
+ ) : props['data-code-panel'] ? (
121
+ <div {...props}>
122
+ <CodeGroupPanelContext.Provider value={true}>{children}</CodeGroupPanelContext.Provider>
123
+ </div>
124
+ ) : (
125
+ <div {...props}>{children}</div>
126
+ ),
127
+ // Fenced blocks arrive as <pre><code class="language-x">. Render the panel from `code` and drop the <pre>.
128
+ pre: ({ children }: { children?: ReactNode }) => <>{children}</>,
129
+ code: ({ className, children }: { className?: string; children?: ReactNode }) => {
130
+ const language = /language-(\w+)/.exec(className || '')?.[1];
131
+ const text = getCodeText(children);
132
+ if (language || text.includes('\n')) return <CodeBlock language={language} code={text} />;
133
+ return (
134
+ <code className="rounded bg-[rgb(var(--ec-content-hover)/0.6)] px-1.5 py-0.5 font-mono text-[12px] font-normal text-[rgb(var(--ec-page-text))] before:content-none after:content-none">
135
+ {children}
136
+ </code>
137
+ );
138
+ },
139
+ };
97
140
 
98
- {/* Code content */}
99
- <div className="overflow-auto">
100
- <SyntaxHighlighter
101
- language={lang}
102
- style={isDarkMode ? oneDark : oneLight}
103
- customStyle={{
104
- margin: 0,
105
- padding: '1rem 1.25rem',
106
- borderRadius: 0,
107
- fontSize: '0.8125rem',
108
- lineHeight: '1.625',
109
- overflow: 'auto',
110
- background: 'transparent',
111
- }}
112
- showLineNumbers={true}
113
- wrapLines={true}
114
- wrapLongLines={true}
115
- >
116
- {selected.content}
117
- </SyntaxHighlighter>
118
- </div>
119
- </div>
141
+ /** Lists every usage example, rendering Markdown as prose and other formats as source. */
142
+ export default function ExamplesViewer({ examples }: ExamplesViewerProps) {
143
+ if (examples.length === 0) {
144
+ return (
145
+ <div className="flex h-full items-center justify-center text-[rgb(var(--ec-page-text-muted))]">
146
+ <p className="text-sm">No examples available</p>
147
+ </div>
148
+ );
149
+ }
120
150
 
121
- {/* Usage section */}
122
- {selected.usage && (
123
- <div className="flex-shrink-0 mt-3">
124
- <div className="rounded-lg border border-[rgb(var(--ec-page-border))] overflow-hidden bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
125
- <div className="flex items-center justify-between border-b border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-content-hover)/0.45)] px-4 py-2">
126
- <span className="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Usage</span>
127
- <button
128
- onClick={() => handleCopy(selected.usage!, `usage-${selected.fileName}`)}
129
- className="inline-flex items-center gap-1 px-2 py-1 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-page-bg)/0.5)] hover:text-[rgb(var(--ec-page-text))] rounded transition-colors"
130
- title="Copy usage"
151
+ return (
152
+ <div className="h-full overflow-auto pr-1">
153
+ <div className="divide-y divide-[rgb(var(--ec-page-border))]">
154
+ {examples.map((example) => (
155
+ <section
156
+ key={example.fileName}
157
+ id={`example-${example.fileName.replace(/[^a-zA-Z0-9]+/g, '-')}`}
158
+ className="w-full py-8 pr-8 first:pt-0 last:pb-0"
159
+ >
160
+ {example.summary && <p className="mb-4 text-sm text-[rgb(var(--ec-page-text-muted))]">{example.summary}</p>}
161
+ {example.renderMode === 'markdown' ? (
162
+ <div className={PROSE_CLASS}>
163
+ <ReactMarkdown
164
+ remarkPlugins={[remarkGfm, remarkMarkdownColumns, remarkMarkdownCodeGroup]}
165
+ components={markdownComponents}
131
166
  >
132
- <ClipboardDocumentIcon className="h-3 w-3" />
133
- {copiedId === `usage-${selected.fileName}` ? 'Copied!' : 'Copy'}
134
- </button>
167
+ {example.content}
168
+ </ReactMarkdown>
135
169
  </div>
136
- <div className="overflow-auto max-h-32">
137
- <pre className="m-0 px-5 py-3 text-[0.75rem] leading-[1.5] whitespace-pre-wrap break-words text-[rgb(var(--ec-page-text-muted))] bg-transparent font-mono">
138
- <code>{selected.usage}</code>
139
- </pre>
170
+ ) : (
171
+ <CodeBlock language={getLanguageForHighlight(example.extension)} code={example.content} />
172
+ )}
173
+ {example.usage && (
174
+ <div className="mt-5">
175
+ <h3 className="text-xs font-semibold uppercase tracking-wider text-[rgb(var(--ec-page-text-muted))]">Usage</h3>
176
+ <CodeBlock language="bash" code={example.usage} />
140
177
  </div>
141
- </div>
142
- </div>
143
- )}
178
+ )}
179
+ </section>
180
+ ))}
144
181
  </div>
145
182
  </div>
146
183
  );