@eventcatalog/core 3.29.1 → 3.30.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.
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-H5UC2A5F.js → chunk-6UG4JMUV.js} +1 -1
- package/dist/{chunk-4MSAPCV3.js → chunk-ATRBVTJ6.js} +1 -1
- package/dist/{chunk-PLNJC7NZ.js → chunk-K3ZVEX2Y.js} +13 -2
- package/dist/{chunk-V4OTI3PF.js → chunk-MVZKHUX2.js} +1 -1
- package/dist/{chunk-FVKDNLZK.js → chunk-RRBDF4MM.js} +1 -1
- package/dist/{chunk-24NGK43A.js → chunk-Z26P4PCB.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +14 -3
- package/dist/eventcatalog.js +6 -6
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/dist/watcher.cjs +13 -2
- package/dist/watcher.js +1 -1
- package/eventcatalog/astro.config.mjs +1 -1
- package/eventcatalog/public/logo.png +0 -0
- package/eventcatalog/src/components/CopyAsMarkdown.tsx +2 -2
- package/eventcatalog/src/components/EnvironmentDropdown.tsx +33 -21
- package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +3 -53
- package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +144 -91
- package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +112 -109
- package/eventcatalog/src/components/Header.astro +9 -19
- package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +12 -14
- package/eventcatalog/src/components/MDX/Accordion/AccordionGroup.astro +11 -3
- package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +15 -5
- package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +164 -53
- package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +1 -1
- package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +4 -4
- package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +12 -10
- package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +48 -77
- package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +238 -169
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +189 -230
- package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +39 -36
- package/eventcatalog/src/components/Search/Search.astro +1 -1
- package/eventcatalog/src/components/Seo.astro +1 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -3
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +229 -256
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +78 -59
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +130 -197
- package/eventcatalog/src/components/Tables/Table.tsx +21 -18
- package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +79 -131
- package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +104 -175
- package/eventcatalog/src/enterprise/auth/error.astro +1 -1
- package/eventcatalog/src/enterprise/auth/login.astro +1 -1
- package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +95 -93
- package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +174 -136
- package/eventcatalog/src/enterprise/fields/pages/fields.astro +10 -8
- package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +0 -8
- package/eventcatalog/src/layouts/DirectoryLayout.astro +17 -88
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +528 -146
- package/eventcatalog/src/layouts/VisualiserLayout.astro +7 -2
- package/eventcatalog/src/pages/_index.astro +5 -3
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -3
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +223 -73
- package/eventcatalog/src/pages/discover/[type]/index.astro +22 -141
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +129 -29
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +129 -29
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +6 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +2 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +21 -18
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +33 -32
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +5 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +2 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +4 -6
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +11 -4
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +11 -4
- package/eventcatalog/src/pages/schemas/explorer/index.astro +10 -8
- package/eventcatalog/src/pages/studio.astro +1 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +2 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +2 -7
- package/eventcatalog/src/styles/theme.css +68 -12
- package/eventcatalog/src/types/react-syntax-highlighter.d.ts +13 -0
- package/package.json +1 -1
- package/eventcatalog/public/logo.svg +0 -14
- package/eventcatalog/src/enterprise/plans/index.astro +0 -319
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
<div
|
|
5
|
+
<div
|
|
6
|
+
class="accordion-group border border-[rgb(var(--ec-page-border))] rounded-lg overflow-hidden bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] my-3"
|
|
7
|
+
>
|
|
6
8
|
<slot />
|
|
7
9
|
</div>
|
|
8
10
|
|
|
9
11
|
<style is:global>
|
|
10
|
-
.
|
|
12
|
+
.accordion-group .accordion {
|
|
11
13
|
border: none;
|
|
12
|
-
border-
|
|
14
|
+
border-radius: 0;
|
|
15
|
+
box-shadow: none;
|
|
16
|
+
margin: 0;
|
|
17
|
+
background: transparent;
|
|
18
|
+
}
|
|
19
|
+
.accordion-group .accordion + .accordion {
|
|
20
|
+
border-top: 1px solid rgb(var(--ec-page-border));
|
|
13
21
|
}
|
|
14
22
|
</style>
|
|
@@ -248,15 +248,25 @@ const tooltipId = `ref-tooltip-${Math.random().toString(36).slice(2, 9)}`;
|
|
|
248
248
|
<a
|
|
249
249
|
href={href}
|
|
250
250
|
class:list={[
|
|
251
|
-
'resource-ref-trigger underline decoration-dotted
|
|
251
|
+
'resource-ref-trigger inline-flex items-center gap-1 px-1 -mx-1 rounded font-medium underline decoration-dotted decoration-2 underline-offset-[3px] transition-colors',
|
|
252
252
|
isDeprecated
|
|
253
|
-
? 'text-amber-
|
|
254
|
-
: 'text-[rgb(var(--ec-accent))] hover:
|
|
253
|
+
? 'text-amber-700 dark:text-amber-400 decoration-amber-500/60'
|
|
254
|
+
: 'text-[rgb(var(--ec-accent-text))] decoration-[rgb(var(--ec-primary))] hover:bg-[rgb(var(--ec-accent-subtle))]',
|
|
255
255
|
]}
|
|
256
256
|
data-tooltip-id={tooltipId}
|
|
257
257
|
>
|
|
258
|
-
|
|
259
|
-
|
|
258
|
+
<svg
|
|
259
|
+
class="w-3.5 h-3.5 flex-shrink-0 text-[rgb(var(--ec-primary))]"
|
|
260
|
+
fill="none"
|
|
261
|
+
viewBox="0 0 24 24"
|
|
262
|
+
stroke="currentColor"
|
|
263
|
+
stroke-width="1.75"
|
|
264
|
+
set:html={iconPath}
|
|
265
|
+
/>
|
|
266
|
+
<span>
|
|
267
|
+
{resource?.data?.name || resourceId}
|
|
268
|
+
{isDeprecated && ' (deprecated)'}
|
|
269
|
+
</span>
|
|
260
270
|
</a>
|
|
261
271
|
<span
|
|
262
272
|
id={tooltipId}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { ClipboardDocumentIcon, CheckIcon } from '@heroicons/react/24/outline';
|
|
1
|
+
import { ClipboardDocumentIcon, CheckIcon, GlobeAltIcon, DocumentTextIcon } from '@heroicons/react/24/outline';
|
|
2
2
|
import { LockClosedIcon } from '@heroicons/react/24/solid';
|
|
3
|
+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
4
|
+
import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
5
|
+
import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
6
|
+
import { getLanguageForHighlight, getSchemaTypeLabel } from './utils';
|
|
7
|
+
import { useDarkMode } from './useDarkMode';
|
|
3
8
|
import type { SchemaItem } from './types';
|
|
4
9
|
|
|
5
10
|
interface ApiContentViewerProps {
|
|
@@ -10,7 +15,14 @@ interface ApiContentViewerProps {
|
|
|
10
15
|
}
|
|
11
16
|
|
|
12
17
|
export default function ApiContentViewer({ message, onCopy, copiedId, apiAccessEnabled = false }: ApiContentViewerProps) {
|
|
13
|
-
|
|
18
|
+
const isDarkMode = useDarkMode();
|
|
19
|
+
const dividerColor = isDarkMode ? 'rgb(var(--ec-page-text-muted) / 0.13)' : 'rgb(var(--ec-page-border))';
|
|
20
|
+
const boxBorderColor = isDarkMode ? 'rgb(var(--ec-page-text-muted) / 0.17)' : 'rgb(var(--ec-page-border))';
|
|
21
|
+
const insetDividerColor = isDarkMode ? 'rgb(var(--ec-page-text-muted) / 0.11)' : 'rgb(var(--ec-page-border) / 0.8)';
|
|
22
|
+
const headingClass = 'text-sm font-semibold text-[rgb(var(--ec-page-text))]';
|
|
23
|
+
const labelClass = 'text-sm text-[rgb(var(--ec-page-text-muted))]';
|
|
24
|
+
const valueClass = 'text-sm text-[rgb(var(--ec-page-text-muted))]';
|
|
25
|
+
|
|
14
26
|
let apiPath = '';
|
|
15
27
|
if (message.collection === 'services') {
|
|
16
28
|
const specType = message.specType || 'openapi';
|
|
@@ -20,17 +32,20 @@ export default function ApiContentViewer({ message, onCopy, copiedId, apiAccessE
|
|
|
20
32
|
}
|
|
21
33
|
|
|
22
34
|
const fullUrl = typeof window !== 'undefined' ? `${window.location.origin}${apiPath}` : apiPath;
|
|
23
|
-
const
|
|
35
|
+
const exampleResponse = message.schemaContent || '{}';
|
|
36
|
+
const schemaTypeLabel = getSchemaTypeLabel(message.schemaExtension);
|
|
37
|
+
const lineCount = exampleResponse.split('\n').length;
|
|
38
|
+
const byteSize = new TextEncoder().encode(exampleResponse).length;
|
|
24
39
|
|
|
25
40
|
if (!apiAccessEnabled) {
|
|
26
41
|
return (
|
|
27
|
-
<div className="h-full
|
|
42
|
+
<div className="flex h-full items-center justify-center p-8">
|
|
28
43
|
<div className="max-w-md text-center">
|
|
29
|
-
<div className="
|
|
44
|
+
<div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-2xl border border-[rgb(var(--ec-accent)/0.3)] bg-[rgb(var(--ec-accent-subtle))]">
|
|
30
45
|
<LockClosedIcon className="h-8 w-8 text-[rgb(var(--ec-accent))]" />
|
|
31
46
|
</div>
|
|
32
|
-
<h3 className="text-lg font-semibold text-[rgb(var(--ec-page-text))]
|
|
33
|
-
<p className="text-sm text-[rgb(var(--ec-page-text-muted))]
|
|
47
|
+
<h3 className="mb-2 text-lg font-semibold text-[rgb(var(--ec-page-text))]">API Access</h3>
|
|
48
|
+
<p className="mb-6 text-sm text-[rgb(var(--ec-page-text-muted))]">
|
|
34
49
|
Access your schemas programmatically via REST API. Perfect for CI/CD pipelines, automation, and integrations with your
|
|
35
50
|
development workflow.
|
|
36
51
|
</p>
|
|
@@ -38,94 +53,190 @@ export default function ApiContentViewer({ message, onCopy, copiedId, apiAccessE
|
|
|
38
53
|
href="https://eventcatalog.cloud"
|
|
39
54
|
target="_blank"
|
|
40
55
|
rel="noopener noreferrer"
|
|
41
|
-
className="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white
|
|
56
|
+
className="inline-flex items-center gap-2 rounded-lg bg-[rgb(var(--ec-accent))] px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-[rgb(var(--ec-accent-hover))]"
|
|
42
57
|
>
|
|
43
58
|
Upgrade to Scale
|
|
44
59
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
45
60
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
46
61
|
</svg>
|
|
47
62
|
</a>
|
|
48
|
-
<p className="text-xs text-[rgb(var(--ec-page-text-muted))]
|
|
63
|
+
<p className="mt-3 text-xs text-[rgb(var(--ec-page-text-muted))]">Start your 14-day free trial</p>
|
|
49
64
|
</div>
|
|
50
65
|
</div>
|
|
51
66
|
);
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
return (
|
|
55
|
-
<div className="h-full overflow-auto">
|
|
56
|
-
<div className="space-y-4">
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
<div className="h-full overflow-auto pr-1">
|
|
71
|
+
<div className="space-y-4 pb-3">
|
|
72
|
+
<section className="overflow-hidden rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
|
|
73
|
+
<div className="flex items-start justify-between gap-4 px-4 py-4">
|
|
74
|
+
<div className="min-w-0">
|
|
75
|
+
<div className="flex items-center gap-2">
|
|
76
|
+
<div className="flex h-6 w-6 items-center justify-center rounded-md bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))]">
|
|
77
|
+
<GlobeAltIcon className="h-3.5 w-3.5" />
|
|
78
|
+
</div>
|
|
79
|
+
<h3 className={headingClass}>HTTP Endpoint</h3>
|
|
80
|
+
</div>
|
|
81
|
+
<p className={`mt-2 ${labelClass}`}>
|
|
82
|
+
Use this endpoint to interact with the{' '}
|
|
83
|
+
<span className="text-[rgb(var(--ec-page-text))]">{message.data.name}</span>.
|
|
84
|
+
</p>
|
|
65
85
|
</div>
|
|
66
86
|
<CopyButton
|
|
67
|
-
label="Copy
|
|
87
|
+
label="Copy"
|
|
68
88
|
isCopied={copiedId === `${message.data.id}-url`}
|
|
69
89
|
onClick={() => onCopy(fullUrl, `${message.data.id}-url`)}
|
|
90
|
+
borderColor={boxBorderColor}
|
|
91
|
+
variant="ghost"
|
|
70
92
|
/>
|
|
71
93
|
</div>
|
|
72
|
-
|
|
73
|
-
|
|
94
|
+
|
|
95
|
+
<div className="px-4 pb-4">
|
|
96
|
+
<div
|
|
97
|
+
className="flex items-center gap-2 rounded-lg border bg-[rgb(var(--ec-content-hover)/0.45)] p-2"
|
|
98
|
+
style={{ borderColor: boxBorderColor }}
|
|
99
|
+
>
|
|
100
|
+
<span className="rounded-md bg-emerald-500/15 px-3 py-2 text-xs font-bold uppercase tracking-wide text-emerald-400">
|
|
101
|
+
GET
|
|
102
|
+
</span>
|
|
103
|
+
<code className="min-w-0 flex-1 truncate text-[13px] text-[rgb(var(--ec-page-text-muted))]">{apiPath}</code>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<div className="mt-4 pt-4">
|
|
107
|
+
<div className="mb-2 flex items-center gap-3">
|
|
108
|
+
<span className={labelClass}>Full URL</span>
|
|
109
|
+
<div className="h-px flex-1" style={{ backgroundColor: insetDividerColor }} />
|
|
110
|
+
</div>
|
|
111
|
+
<div className="flex items-center gap-4">
|
|
112
|
+
<code className="min-w-0 flex-1 break-all text-[13px] leading-relaxed text-[rgb(var(--ec-page-text-muted))]">
|
|
113
|
+
{fullUrl}
|
|
114
|
+
</code>
|
|
115
|
+
<CopyButton
|
|
116
|
+
label="Copy"
|
|
117
|
+
isCopied={copiedId === `${message.data.id}-full-url`}
|
|
118
|
+
onClick={() => onCopy(fullUrl, `${message.data.id}-full-url`)}
|
|
119
|
+
borderColor={boxBorderColor}
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
74
123
|
</div>
|
|
75
|
-
</
|
|
124
|
+
</section>
|
|
125
|
+
|
|
126
|
+
<section className="overflow-hidden rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
|
|
127
|
+
<div className="px-4 py-4">
|
|
128
|
+
<h3 className={headingClass}>Response</h3>
|
|
129
|
+
</div>
|
|
130
|
+
<div className="border-t" style={{ borderColor: dividerColor }}>
|
|
131
|
+
<div className="flex items-center justify-between gap-4 px-4 py-3">
|
|
132
|
+
<span className={labelClass}>Content-Type</span>
|
|
133
|
+
<code
|
|
134
|
+
className="rounded-md border bg-[rgb(var(--ec-content-hover)/0.45)] px-2.5 py-1 text-xs font-medium text-[rgb(var(--ec-page-text-muted))]"
|
|
135
|
+
style={{ borderColor: boxBorderColor }}
|
|
136
|
+
>
|
|
137
|
+
application/json
|
|
138
|
+
</code>
|
|
139
|
+
</div>
|
|
140
|
+
<div className="flex items-center justify-between gap-4 border-t px-4 py-3" style={{ borderColor: dividerColor }}>
|
|
141
|
+
<span className={labelClass}>Returns</span>
|
|
142
|
+
<span className={valueClass}>Raw schema content</span>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</section>
|
|
76
146
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
147
|
+
<section className="overflow-hidden rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
|
|
148
|
+
<div className="flex items-center justify-between gap-4 px-4 py-4">
|
|
149
|
+
<div className="flex items-center gap-2">
|
|
150
|
+
<div
|
|
151
|
+
className="flex h-6 w-6 items-center justify-center rounded-md border bg-[rgb(var(--ec-content-hover)/0.45)] text-[rgb(var(--ec-page-text-muted))]"
|
|
152
|
+
style={{ borderColor: boxBorderColor }}
|
|
153
|
+
>
|
|
154
|
+
<DocumentTextIcon className="h-3.5 w-3.5" />
|
|
155
|
+
</div>
|
|
156
|
+
<h3 className={headingClass}>Example Response</h3>
|
|
157
|
+
</div>
|
|
81
158
|
<CopyButton
|
|
82
159
|
label="Copy"
|
|
83
|
-
isCopied={copiedId === `${message.data.id}-
|
|
84
|
-
onClick={() => onCopy(
|
|
160
|
+
isCopied={copiedId === `${message.data.id}-response`}
|
|
161
|
+
onClick={() => onCopy(exampleResponse, `${message.data.id}-response`)}
|
|
162
|
+
borderColor={boxBorderColor}
|
|
163
|
+
variant="ghost"
|
|
85
164
|
/>
|
|
86
165
|
</div>
|
|
87
|
-
<div className="px-4 py-3">
|
|
88
|
-
<code className="text-[13px] text-[rgb(var(--ec-page-text))] font-mono break-all leading-relaxed">
|
|
89
|
-
<span className="text-[rgb(var(--ec-accent))]">curl</span> {fullUrl}
|
|
90
|
-
</code>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
166
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
167
|
+
<div className="border-t" style={{ borderColor: dividerColor }}>
|
|
168
|
+
<SyntaxHighlighter
|
|
169
|
+
language={getLanguageForHighlight(message.schemaExtension)}
|
|
170
|
+
style={isDarkMode ? oneDark : oneLight}
|
|
171
|
+
customStyle={{
|
|
172
|
+
margin: 0,
|
|
173
|
+
padding: '1rem 1.25rem',
|
|
174
|
+
borderRadius: 0,
|
|
175
|
+
fontSize: '0.8125rem',
|
|
176
|
+
lineHeight: '1.625',
|
|
177
|
+
background: 'transparent',
|
|
178
|
+
}}
|
|
179
|
+
showLineNumbers={true}
|
|
180
|
+
wrapLines={true}
|
|
181
|
+
wrapLongLines={true}
|
|
182
|
+
>
|
|
183
|
+
{exampleResponse}
|
|
184
|
+
</SyntaxHighlighter>
|
|
98
185
|
</div>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
</code>
|
|
186
|
+
|
|
187
|
+
<div className="flex items-center justify-between gap-4 border-t px-4 py-3" style={{ borderColor: dividerColor }}>
|
|
188
|
+
<div className="inline-flex items-center gap-2 rounded-md bg-emerald-500/10 px-3 py-1.5 text-xs font-medium text-emerald-400">
|
|
189
|
+
<span className="h-2 w-2 rounded-full bg-emerald-400" />
|
|
190
|
+
Valid {schemaTypeLabel}
|
|
105
191
|
</div>
|
|
106
|
-
<div className="flex items-center
|
|
107
|
-
<span
|
|
108
|
-
<span
|
|
192
|
+
<div className="flex items-center gap-4 text-xs text-[rgb(var(--ec-page-text-muted))]">
|
|
193
|
+
<span>{lineCount} lines</span>
|
|
194
|
+
<span>{formatBytes(byteSize)}</span>
|
|
109
195
|
</div>
|
|
110
196
|
</div>
|
|
111
|
-
</
|
|
197
|
+
</section>
|
|
112
198
|
</div>
|
|
113
199
|
</div>
|
|
114
200
|
);
|
|
115
201
|
}
|
|
116
202
|
|
|
117
|
-
function CopyButton({
|
|
203
|
+
function CopyButton({
|
|
204
|
+
label,
|
|
205
|
+
isCopied,
|
|
206
|
+
onClick,
|
|
207
|
+
borderColor,
|
|
208
|
+
variant = 'outline',
|
|
209
|
+
}: {
|
|
210
|
+
label: string;
|
|
211
|
+
isCopied: boolean;
|
|
212
|
+
onClick: () => void;
|
|
213
|
+
borderColor: string;
|
|
214
|
+
variant?: 'outline' | 'ghost';
|
|
215
|
+
}) {
|
|
216
|
+
const classes =
|
|
217
|
+
variant === 'ghost'
|
|
218
|
+
? 'inline-flex items-center gap-2 rounded-md px-1 py-1 text-xs font-medium transition-colors'
|
|
219
|
+
: 'inline-flex items-center gap-2 rounded-md border px-3 py-2 text-xs font-medium transition-colors';
|
|
220
|
+
|
|
118
221
|
return (
|
|
119
222
|
<button
|
|
120
223
|
onClick={onClick}
|
|
121
|
-
|
|
224
|
+
style={variant === 'outline' ? { borderColor } : undefined}
|
|
225
|
+
className={`${classes} ${
|
|
122
226
|
isCopied
|
|
123
227
|
? 'text-emerald-400'
|
|
124
|
-
: 'text-[rgb(var(--ec-page-text-muted))] hover:
|
|
228
|
+
: 'text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-content-hover)/0.45)] hover:text-[rgb(var(--ec-page-text))]'
|
|
125
229
|
}`}
|
|
126
230
|
>
|
|
127
|
-
{isCopied ? <CheckIcon className="h-3 w-3" /> : <ClipboardDocumentIcon className="h-3 w-3" />}
|
|
231
|
+
{isCopied ? <CheckIcon className="h-3.5 w-3.5" /> : <ClipboardDocumentIcon className="h-3.5 w-3.5" />}
|
|
128
232
|
{isCopied ? 'Copied' : label}
|
|
129
233
|
</button>
|
|
130
234
|
);
|
|
131
235
|
}
|
|
236
|
+
|
|
237
|
+
function formatBytes(bytes: number) {
|
|
238
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
239
|
+
const kb = bytes / 1024;
|
|
240
|
+
if (kb < 1024) return `${kb.toFixed(1)} KB`;
|
|
241
|
+
return `${(kb / 1024).toFixed(1)} MB`;
|
|
242
|
+
}
|
|
@@ -118,7 +118,7 @@ export default function DiffViewer({ diffs, onOpenFullscreen, apiAccessEnabled =
|
|
|
118
118
|
if (diffs.length === 0) return null;
|
|
119
119
|
|
|
120
120
|
return (
|
|
121
|
-
<div className="h-full overflow-auto p-
|
|
121
|
+
<div className="h-full overflow-auto p-2">
|
|
122
122
|
{isDark && <style dangerouslySetInnerHTML={{ __html: DIFF_DARK_STYLES }} />}
|
|
123
123
|
<div className="mb-5 flex items-start justify-between">
|
|
124
124
|
<div className="flex-1">
|
|
@@ -73,9 +73,9 @@ export default function ExamplesViewer({ examples }: ExamplesViewerProps) {
|
|
|
73
73
|
{/* Right: code + usage */}
|
|
74
74
|
<div className="flex-1 flex flex-col min-w-0 overflow-auto">
|
|
75
75
|
{/* Code window */}
|
|
76
|
-
<div className="flex flex-col rounded-lg border border-[rgb(var(--ec-page-border))] overflow-hidden bg-[rgb(var(--ec-
|
|
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
77
|
{/* Window title bar */}
|
|
78
|
-
<div className="flex items-center justify-between
|
|
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
79
|
<div className="flex items-center gap-3">
|
|
80
80
|
<div className="flex items-center gap-1.5">
|
|
81
81
|
<div className="w-3 h-3 rounded-full bg-[#FF5F56]" />
|
|
@@ -121,8 +121,8 @@ export default function ExamplesViewer({ examples }: ExamplesViewerProps) {
|
|
|
121
121
|
{/* Usage section */}
|
|
122
122
|
{selected.usage && (
|
|
123
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-
|
|
125
|
-
<div className="flex items-center justify-between
|
|
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
126
|
<span className="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Usage</span>
|
|
127
127
|
<button
|
|
128
128
|
onClick={() => handleCopy(selected.usage!, `usage-${selected.fileName}`)}
|
|
@@ -10,26 +10,28 @@ export default function Pagination({ currentPage, totalPages, onPageChange }: Pa
|
|
|
10
10
|
if (totalPages <= 1) return null;
|
|
11
11
|
|
|
12
12
|
return (
|
|
13
|
-
<div className="flex-shrink-0 border-t border-[rgb(var(--ec-page-border))] px-
|
|
14
|
-
<div className="flex items-center justify-
|
|
13
|
+
<div className="flex-shrink-0 border-t border-[rgb(var(--ec-page-border))] px-5 py-4">
|
|
14
|
+
<div className="flex items-center justify-center gap-4">
|
|
15
15
|
<button
|
|
16
16
|
onClick={() => onPageChange(Math.max(1, currentPage - 1))}
|
|
17
17
|
disabled={currentPage === 1}
|
|
18
|
-
className="inline-flex
|
|
18
|
+
className="inline-flex h-9 w-9 items-center justify-center rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-page-text-muted))] transition-colors hover:text-[rgb(var(--ec-page-text))] disabled:cursor-not-allowed disabled:opacity-30"
|
|
19
|
+
aria-label="Previous page"
|
|
19
20
|
>
|
|
20
|
-
<ChevronLeftIcon className="h-
|
|
21
|
-
Prev
|
|
21
|
+
<ChevronLeftIcon className="h-4 w-4" />
|
|
22
22
|
</button>
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
<span className="min-w-[5.5rem] text-center text-[12px] font-medium tabular-nums text-[rgb(var(--ec-page-text-muted))]">
|
|
25
|
+
{currentPage} of {totalPages}
|
|
25
26
|
</span>
|
|
27
|
+
|
|
26
28
|
<button
|
|
27
29
|
onClick={() => onPageChange(Math.min(totalPages, currentPage + 1))}
|
|
28
30
|
disabled={currentPage === totalPages}
|
|
29
|
-
className="inline-flex
|
|
31
|
+
className="inline-flex h-9 w-9 items-center justify-center rounded-xl border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-page-text-muted))] transition-colors hover:text-[rgb(var(--ec-page-text))] disabled:cursor-not-allowed disabled:opacity-30"
|
|
32
|
+
aria-label="Next page"
|
|
30
33
|
>
|
|
31
|
-
|
|
32
|
-
<ChevronRightIcon className="h-3.5 w-3.5" />
|
|
34
|
+
<ChevronRightIcon className="h-4 w-4" />
|
|
33
35
|
</button>
|
|
34
36
|
</div>
|
|
35
37
|
</div>
|
|
@@ -5,7 +5,7 @@ import { oneLight } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
|
|
5
5
|
import { buildUrl } from '@utils/url-builder';
|
|
6
6
|
import JSONSchemaViewer from './JSONSchemaViewer';
|
|
7
7
|
import AvroSchemaViewer from './AvroSchemaViewer';
|
|
8
|
-
import { getLanguageForHighlight
|
|
8
|
+
import { getLanguageForHighlight } from './utils';
|
|
9
9
|
import type { SchemaItem } from './types';
|
|
10
10
|
import { useDarkMode } from './useDarkMode';
|
|
11
11
|
|
|
@@ -50,96 +50,67 @@ export default function SchemaContentViewer({
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const ext = message.schemaExtension?.toLowerCase() || '';
|
|
54
|
-
const iconSpec = ICON_SPECS[ext];
|
|
55
|
-
const filename = message.data.schemaPath
|
|
56
|
-
? message.data.schemaPath.split('/').pop() || `${message.data.id}.${ext || 'json'}`
|
|
57
|
-
: `${message.data.id}.${ext || 'json'}`;
|
|
58
|
-
|
|
59
53
|
return (
|
|
60
|
-
<div className="h-full
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<div className="w-3 h-3 rounded-full bg-[#FF5F56]" />
|
|
67
|
-
<div className="w-3 h-3 rounded-full bg-[#FFBD2E]" />
|
|
68
|
-
<div className="w-3 h-3 rounded-full bg-[#27C93F]" />
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
{/* Filename */}
|
|
72
|
-
<span className="text-xs font-mono text-[rgb(var(--ec-page-text-muted))]">{filename}</span>
|
|
73
|
-
</div>
|
|
54
|
+
<div className="relative flex h-full min-h-0 flex-col overflow-hidden rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-code-bg))]">
|
|
55
|
+
<div className="pointer-events-none absolute right-4 top-4 z-10 flex items-center gap-1.5">
|
|
56
|
+
{message.collection === 'services' &&
|
|
57
|
+
(() => {
|
|
58
|
+
const specType = message.specType || 'openapi';
|
|
59
|
+
const specFilename = message.specFilenameWithoutExtension || 'schema';
|
|
74
60
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
(
|
|
79
|
-
|
|
80
|
-
|
|
61
|
+
let urlSegment = 'spec';
|
|
62
|
+
if (specType === 'asyncapi') {
|
|
63
|
+
urlSegment = 'asyncapi';
|
|
64
|
+
} else if (specType === 'graphql') {
|
|
65
|
+
urlSegment = 'graphql';
|
|
66
|
+
}
|
|
81
67
|
|
|
82
|
-
|
|
83
|
-
if (specType === 'asyncapi') {
|
|
84
|
-
urlSegment = 'asyncapi';
|
|
85
|
-
} else if (specType === 'graphql') {
|
|
86
|
-
urlSegment = 'graphql';
|
|
87
|
-
}
|
|
68
|
+
const specUrl = buildUrl(`/docs/services/${message.data.id}/${message.data.version}/${urlSegment}/${specFilename}`);
|
|
88
69
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
109
|
-
/>
|
|
110
|
-
</svg>
|
|
111
|
-
View Spec
|
|
112
|
-
</a>
|
|
113
|
-
);
|
|
114
|
-
})()}
|
|
115
|
-
{onOpenFullscreen && (
|
|
116
|
-
<button
|
|
117
|
-
onClick={onOpenFullscreen}
|
|
118
|
-
className="inline-flex items-center p-1 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"
|
|
119
|
-
title="Open in fullscreen"
|
|
120
|
-
>
|
|
121
|
-
<ArrowsPointingOutIcon className="h-3.5 w-3.5" />
|
|
122
|
-
</button>
|
|
123
|
-
)}
|
|
70
|
+
return (
|
|
71
|
+
<a
|
|
72
|
+
href={specUrl}
|
|
73
|
+
className="pointer-events-auto inline-flex items-center gap-1 rounded-md bg-[rgb(var(--ec-content-hover)/0.9)] px-2 py-1 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] backdrop-blur-xs transition-colors hover:bg-[rgb(var(--ec-page-bg)/0.75)] hover:text-[rgb(var(--ec-page-text))]"
|
|
74
|
+
title="View full specification"
|
|
75
|
+
>
|
|
76
|
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
77
|
+
<path
|
|
78
|
+
strokeLinecap="round"
|
|
79
|
+
strokeLinejoin="round"
|
|
80
|
+
strokeWidth={2}
|
|
81
|
+
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
82
|
+
/>
|
|
83
|
+
</svg>
|
|
84
|
+
View Spec
|
|
85
|
+
</a>
|
|
86
|
+
);
|
|
87
|
+
})()}
|
|
88
|
+
{onOpenFullscreen && (
|
|
124
89
|
<button
|
|
125
|
-
onClick={
|
|
126
|
-
className="inline-flex items-center
|
|
127
|
-
title="
|
|
90
|
+
onClick={onOpenFullscreen}
|
|
91
|
+
className="pointer-events-auto inline-flex items-center rounded-md bg-[rgb(var(--ec-content-hover)/0.9)] p-1.5 text-[rgb(var(--ec-page-text-muted))] backdrop-blur-xs transition-colors hover:bg-[rgb(var(--ec-page-bg)/0.75)] hover:text-[rgb(var(--ec-page-text))]"
|
|
92
|
+
title="Open in fullscreen"
|
|
128
93
|
>
|
|
129
|
-
<
|
|
130
|
-
{isCopied ? 'Copied!' : 'Copy'}
|
|
94
|
+
<ArrowsPointingOutIcon className="h-3.5 w-3.5" />
|
|
131
95
|
</button>
|
|
132
|
-
|
|
96
|
+
)}
|
|
97
|
+
<button
|
|
98
|
+
onClick={onCopy}
|
|
99
|
+
className="pointer-events-auto inline-flex items-center gap-1 rounded-md bg-[rgb(var(--ec-content-hover)/0.9)] px-2 py-1.5 text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] backdrop-blur-xs transition-colors hover:bg-[rgb(var(--ec-page-bg)/0.75)] hover:text-[rgb(var(--ec-page-text))]"
|
|
100
|
+
title="Copy code"
|
|
101
|
+
>
|
|
102
|
+
<ClipboardDocumentIcon className="h-3 w-3" />
|
|
103
|
+
{isCopied ? 'Copied!' : 'Copy'}
|
|
104
|
+
</button>
|
|
133
105
|
</div>
|
|
134
106
|
|
|
135
|
-
|
|
136
|
-
<div className="flex-1 overflow-auto">
|
|
107
|
+
<div className="min-h-0 flex-1 overflow-auto">
|
|
137
108
|
<SyntaxHighlighter
|
|
138
109
|
language={getLanguageForHighlight(message.schemaExtension)}
|
|
139
110
|
style={isDarkMode ? oneDark : oneLight}
|
|
140
111
|
customStyle={{
|
|
141
112
|
margin: 0,
|
|
142
|
-
padding: '
|
|
113
|
+
padding: '1.25rem',
|
|
143
114
|
borderRadius: 0,
|
|
144
115
|
fontSize: '0.8125rem',
|
|
145
116
|
lineHeight: '1.625',
|