@eventcatalog/core 2.45.1 → 2.45.3
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-DDM6QEBV.js → chunk-KLNIUFPG.js} +1 -1
- package/dist/{chunk-P23CLNWF.js → chunk-YIR6C2W3.js} +1 -1
- package/dist/{chunk-77HCL77S.js → chunk-ZOCINDXG.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +3 -3
- package/eventcatalog/astro.config.mjs +13 -1
- package/eventcatalog/src/components/MDX/SchemaViewer/SchemaProperty.astro +8 -5
- package/eventcatalog/src/components/MDX/SchemaViewer/SchemaViewer.astro +383 -10
- package/eventcatalog/src/components/MDX/SchemaViewer/SchemaViewerPortal.tsx +12 -1
- package/eventcatalog/src/components/MDX/SchemaViewer/SchemaViewerRoot.astro +30 -4
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +33 -0
- package/package.json +2 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-YIR6C2W3.js";
|
|
4
|
+
import "../chunk-ZOCINDXG.js";
|
|
5
|
+
import "../chunk-KLNIUFPG.js";
|
|
6
6
|
import "../chunk-E7TXTI7G.js";
|
|
7
7
|
export {
|
|
8
8
|
log_build_default as default
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
package/dist/eventcatalog.cjs
CHANGED
package/dist/eventcatalog.js
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "./chunk-DCLTVJDP.js";
|
|
7
7
|
import {
|
|
8
8
|
log_build_default
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-YIR6C2W3.js";
|
|
10
|
+
import "./chunk-ZOCINDXG.js";
|
|
11
11
|
import {
|
|
12
12
|
catalogToAstro,
|
|
13
13
|
checkAndConvertMdToMdx
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import "./chunk-EXAALOQA.js";
|
|
16
16
|
import {
|
|
17
17
|
VERSION
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-KLNIUFPG.js";
|
|
19
19
|
import {
|
|
20
20
|
isAuthEnabled,
|
|
21
21
|
isBackstagePluginEnabled,
|
|
@@ -9,7 +9,8 @@ import remarkDirective from 'remark-directive';
|
|
|
9
9
|
import { remarkDirectives } from "./src/remark-plugins/directives"
|
|
10
10
|
import node from '@astrojs/node';
|
|
11
11
|
import remarkComment from 'remark-comment'
|
|
12
|
-
import
|
|
12
|
+
import rehypeSlug from 'rehype-slug';
|
|
13
|
+
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
|
|
13
14
|
|
|
14
15
|
/** @type {import('bin/eventcatalog.config').Config} */
|
|
15
16
|
import config from './eventcatalog.config';
|
|
@@ -60,6 +61,17 @@ export default defineConfig({
|
|
|
60
61
|
// https://docs.astro.build/en/guides/integrations-guide/mdx/#optimize
|
|
61
62
|
optimize: config.mdxOptimize || false,
|
|
62
63
|
remarkPlugins: [remarkDirective, remarkDirectives, remarkComment, mermaid],
|
|
64
|
+
rehypePlugins: [
|
|
65
|
+
rehypeSlug,
|
|
66
|
+
[
|
|
67
|
+
rehypeAutolinkHeadings,
|
|
68
|
+
{
|
|
69
|
+
behavior: 'append',
|
|
70
|
+
properties: { className: ['anchor-link'] },
|
|
71
|
+
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
],
|
|
63
75
|
gfm: true,
|
|
64
76
|
}),
|
|
65
77
|
config.output !== 'server' && pagefind(),
|
|
@@ -7,9 +7,10 @@ interface Props {
|
|
|
7
7
|
isRequired: boolean;
|
|
8
8
|
level: number;
|
|
9
9
|
isListItem?: boolean;
|
|
10
|
+
expand?: boolean;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const { name, details, isRequired, level, isListItem = false } = Astro.props;
|
|
13
|
+
const { name, details, isRequired, level, isListItem = false, expand = false } = Astro.props;
|
|
13
14
|
|
|
14
15
|
const hasNestedProperties = details.type === 'object' && details.properties && Object.keys(details.properties).length > 0;
|
|
15
16
|
const hasArrayItems = details.type === 'array' && details.items;
|
|
@@ -34,12 +35,12 @@ const contentId = `prop-${name}-${level}-${Math.random().toString(36).substring(
|
|
|
34
35
|
isCollapsible && (
|
|
35
36
|
<button
|
|
36
37
|
type="button"
|
|
37
|
-
aria-expanded=
|
|
38
|
+
aria-expanded={expand ? 'true' : 'false'}
|
|
38
39
|
aria-controls={contentId}
|
|
39
40
|
class="property-toggle text-gray-500 hover:text-gray-700 pt-0.5 focus:outline-none w-3 text-center flex-shrink-0"
|
|
40
41
|
>
|
|
41
|
-
<span class=
|
|
42
|
-
<span class=
|
|
42
|
+
<span class:list={['icon-collapsed font-mono text-xs', { hidden: expand }]}>></span>
|
|
43
|
+
<span class:list={['icon-expanded font-mono text-xs', { hidden: !expand }]}>v</span>
|
|
43
44
|
</button>
|
|
44
45
|
)
|
|
45
46
|
}
|
|
@@ -124,7 +125,7 @@ const contentId = `prop-${name}-${level}-${Math.random().toString(36).substring(
|
|
|
124
125
|
{
|
|
125
126
|
(hasNestedProperties || hasArrayItems) && (
|
|
126
127
|
// class:list with conditional object is standard and should be safe
|
|
127
|
-
<div id={contentId} class:list={['nested-content mt-1', { hidden: isCollapsible }]}>
|
|
128
|
+
<div id={contentId} class:list={['nested-content mt-1', { hidden: isCollapsible && !expand }]}>
|
|
128
129
|
{/* Recursive component calls */}
|
|
129
130
|
{hasNestedProperties &&
|
|
130
131
|
details.properties &&
|
|
@@ -134,6 +135,7 @@ const contentId = `prop-${name}-${level}-${Math.random().toString(36).substring(
|
|
|
134
135
|
details={nestedDetails}
|
|
135
136
|
isRequired={details.required?.includes(nestedName) ?? false}
|
|
136
137
|
level={level + 1}
|
|
138
|
+
expand={expand}
|
|
137
139
|
/>
|
|
138
140
|
))}
|
|
139
141
|
|
|
@@ -148,6 +150,7 @@ const contentId = `prop-${name}-${level}-${Math.random().toString(36).substring(
|
|
|
148
150
|
isRequired={details.items.required?.includes(itemPropName) ?? false}
|
|
149
151
|
level={level + 1}
|
|
150
152
|
isListItem={true}
|
|
153
|
+
expand={expand}
|
|
151
154
|
/>
|
|
152
155
|
))}
|
|
153
156
|
{(details.items.allOf || details.items.oneOf || details.items.$ref) && !details.items.properties && (
|
|
@@ -9,9 +9,36 @@ interface Props {
|
|
|
9
9
|
maxHeight: string;
|
|
10
10
|
file: string;
|
|
11
11
|
id: string;
|
|
12
|
+
expand?: boolean | string;
|
|
13
|
+
search?: boolean | string;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
const { id, file, title, maxHeight, schema } = Astro.props;
|
|
16
|
+
const { id, file, title, maxHeight, schema, expand = false, search = true } = Astro.props;
|
|
17
|
+
|
|
18
|
+
// Convert string props to booleans (MDX passes strings)
|
|
19
|
+
const expandBool = expand === true || expand === 'true';
|
|
20
|
+
const searchBool = search !== false && search !== 'false';
|
|
21
|
+
|
|
22
|
+
// This will be used to pass expand state via data attribute
|
|
23
|
+
const expandData = expandBool ? 'true' : 'false';
|
|
24
|
+
const searchData = searchBool ? 'true' : 'false';
|
|
25
|
+
|
|
26
|
+
// Count total properties recursively
|
|
27
|
+
function countProperties(obj: any): number {
|
|
28
|
+
if (!obj || typeof obj !== 'object') return 0;
|
|
29
|
+
|
|
30
|
+
let count = 0;
|
|
31
|
+
if (obj.properties) {
|
|
32
|
+
count += Object.keys(obj.properties).length;
|
|
33
|
+
Object.values(obj.properties).forEach((prop: any) => {
|
|
34
|
+
count += countProperties(prop);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (obj.items) {
|
|
38
|
+
count += countProperties(obj.items);
|
|
39
|
+
}
|
|
40
|
+
return count;
|
|
41
|
+
}
|
|
15
42
|
|
|
16
43
|
// Function to merge allOf schemas
|
|
17
44
|
function mergeAllOfSchemas(schemaWithProcessor: any): any {
|
|
@@ -188,18 +215,84 @@ function processSchema(schema: any, rootSchema?: any): any {
|
|
|
188
215
|
const processedSchema = processSchema(schema);
|
|
189
216
|
const { description, properties, required = [], variants } = processedSchema;
|
|
190
217
|
|
|
218
|
+
// Count total properties after processing
|
|
219
|
+
const totalProperties = countProperties(processedSchema);
|
|
220
|
+
|
|
191
221
|
// Generate a unique ID for this instance
|
|
192
|
-
const instanceId = `${id}-${
|
|
222
|
+
const instanceId = `${id}-${Math.random().toString(36).substring(2, 9)}`;
|
|
193
223
|
---
|
|
194
224
|
|
|
195
|
-
<div id={
|
|
225
|
+
<div id={id} class="not-prose my-4" data-expand={expandData} data-search={searchData}>
|
|
196
226
|
{title && <h2 class="text-3xl font-bold mb-2 !mt-0">{title}</h2>}
|
|
197
227
|
<div
|
|
198
|
-
class="schema-viewer p-4 bg-white overflow-y-auto rounded-lg border border-gray-100 shadow-sm font-sans"
|
|
228
|
+
class="schema-viewer p-4 pt-0 bg-white overflow-y-auto rounded-lg border border-gray-100 shadow-sm font-sans"
|
|
199
229
|
style={{
|
|
200
|
-
maxHeight: maxHeight ? `${maxHeight}
|
|
230
|
+
maxHeight: maxHeight ? `${maxHeight}px` : `30em`,
|
|
231
|
+
minHeight: '15em',
|
|
201
232
|
}}
|
|
202
233
|
>
|
|
234
|
+
{
|
|
235
|
+
searchBool && (
|
|
236
|
+
<div
|
|
237
|
+
class="schema-toolbar sticky top-0 z-10 bg-white pt-4 px-4 -mx-4 mb-4 pb-3 border-b border-gray-100 shadow-sm"
|
|
238
|
+
id={`${instanceId}-toolbar`}
|
|
239
|
+
>
|
|
240
|
+
<div class="flex flex-col sm:flex-row gap-3">
|
|
241
|
+
<div class="flex-1 relative">
|
|
242
|
+
<input
|
|
243
|
+
type="text"
|
|
244
|
+
id={`${instanceId}-search`}
|
|
245
|
+
placeholder="Search properties..."
|
|
246
|
+
class="w-full px-3 py-1.5 pr-20 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
247
|
+
/>
|
|
248
|
+
<div
|
|
249
|
+
class="absolute right-2 top-1/2 transform -translate-y-1/2 flex items-center gap-1"
|
|
250
|
+
id={`${instanceId}-nav-buttons`}
|
|
251
|
+
>
|
|
252
|
+
<button
|
|
253
|
+
id={`${instanceId}-prev-match`}
|
|
254
|
+
class="p-1 text-gray-400 hover:text-gray-600 disabled:opacity-30 disabled:cursor-not-allowed"
|
|
255
|
+
disabled
|
|
256
|
+
title="Previous match"
|
|
257
|
+
>
|
|
258
|
+
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
259
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
|
260
|
+
</svg>
|
|
261
|
+
</button>
|
|
262
|
+
<button
|
|
263
|
+
id={`${instanceId}-next-match`}
|
|
264
|
+
class="p-1 text-gray-400 hover:text-gray-600 disabled:opacity-30 disabled:cursor-not-allowed"
|
|
265
|
+
disabled
|
|
266
|
+
title="Next match"
|
|
267
|
+
>
|
|
268
|
+
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
269
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
270
|
+
</svg>
|
|
271
|
+
</button>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
<div class="flex items-center gap-2">
|
|
275
|
+
<button
|
|
276
|
+
id={`${instanceId}-expand-all`}
|
|
277
|
+
class="px-3 py-1.5 text-xs font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-500"
|
|
278
|
+
>
|
|
279
|
+
Expand All
|
|
280
|
+
</button>
|
|
281
|
+
<button
|
|
282
|
+
id={`${instanceId}-collapse-all`}
|
|
283
|
+
class="px-3 py-1.5 text-xs font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-500"
|
|
284
|
+
>
|
|
285
|
+
Collapse All
|
|
286
|
+
</button>
|
|
287
|
+
<div class="text-xs text-gray-500">
|
|
288
|
+
{totalProperties} {totalProperties === 1 ? 'property' : 'properties'}
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
<div id={`${instanceId}-search-results`} class="mt-2 text-xs text-gray-600 hidden" />
|
|
293
|
+
</div>
|
|
294
|
+
)
|
|
295
|
+
}
|
|
203
296
|
{description && <p class="text-gray-600 text-xs mb-5">{description}</p>}
|
|
204
297
|
|
|
205
298
|
{
|
|
@@ -222,10 +315,32 @@ const instanceId = `${id}-${file}-${Math.random().toString(36).substring(2, 9)}`
|
|
|
222
315
|
|
|
223
316
|
{
|
|
224
317
|
properties && (
|
|
225
|
-
<div
|
|
226
|
-
{
|
|
227
|
-
|
|
228
|
-
|
|
318
|
+
<div>
|
|
319
|
+
<div id={`${instanceId}-properties`}>
|
|
320
|
+
{Object.entries(properties).map(([name, details]) => (
|
|
321
|
+
<SchemaProperty
|
|
322
|
+
name={name}
|
|
323
|
+
details={details}
|
|
324
|
+
isRequired={variants ? false : required.includes(name)}
|
|
325
|
+
level={0}
|
|
326
|
+
expand={expandBool}
|
|
327
|
+
/>
|
|
328
|
+
))}
|
|
329
|
+
</div>
|
|
330
|
+
<div id={`${instanceId}-no-results`} class="hidden text-center py-8">
|
|
331
|
+
<div class="text-gray-400 text-sm">
|
|
332
|
+
<svg class="mx-auto h-12 w-12 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
333
|
+
<path
|
|
334
|
+
stroke-linecap="round"
|
|
335
|
+
stroke-linejoin="round"
|
|
336
|
+
stroke-width="2"
|
|
337
|
+
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
338
|
+
/>
|
|
339
|
+
</svg>
|
|
340
|
+
<p>No properties match your search</p>
|
|
341
|
+
<p class="text-xs mt-1">Try a different search term or clear the search to see all properties</p>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
229
344
|
</div>
|
|
230
345
|
)
|
|
231
346
|
}
|
|
@@ -234,7 +349,233 @@ const instanceId = `${id}-${file}-${Math.random().toString(36).substring(2, 9)}`
|
|
|
234
349
|
</div>
|
|
235
350
|
</div>
|
|
236
351
|
|
|
237
|
-
<script define:vars={{ instanceId, variants }}>
|
|
352
|
+
<script define:vars={{ instanceId, variants, id, file }}>
|
|
353
|
+
// Check if expand is set via data attribute (from portal movement)
|
|
354
|
+
function checkAndExpandAll() {
|
|
355
|
+
const schemaViewerClient = document.getElementById(`${id}-${file}-SchemaViewer-client`);
|
|
356
|
+
if (schemaViewerClient && schemaViewerClient.getAttribute('data-expand') === 'true') {
|
|
357
|
+
// Find all toggle buttons within this schema viewer
|
|
358
|
+
const toggleButtons = schemaViewerClient.querySelectorAll('.property-toggle');
|
|
359
|
+
toggleButtons.forEach((button) => {
|
|
360
|
+
if (button.getAttribute('aria-expanded') === 'false') {
|
|
361
|
+
button.click(); // Trigger the existing toggle logic
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Setup search and utilities
|
|
368
|
+
function setupSchemaUtilities() {
|
|
369
|
+
const schemaViewerClient = document.getElementById(id);
|
|
370
|
+
if (!schemaViewerClient || schemaViewerClient.getAttribute('data-search') !== 'true') return;
|
|
371
|
+
|
|
372
|
+
const searchInput = document.getElementById(`${instanceId}-search`);
|
|
373
|
+
const expandAllBtn = document.getElementById(`${instanceId}-expand-all`);
|
|
374
|
+
const collapseAllBtn = document.getElementById(`${instanceId}-collapse-all`);
|
|
375
|
+
const searchResults = document.getElementById(`${instanceId}-search-results`);
|
|
376
|
+
const propertiesContainer = document.getElementById(`${instanceId}-properties`);
|
|
377
|
+
const noResultsMessage = document.getElementById(`${instanceId}-no-results`);
|
|
378
|
+
const prevMatchBtn = document.getElementById(`${instanceId}-prev-match`);
|
|
379
|
+
const nextMatchBtn = document.getElementById(`${instanceId}-next-match`);
|
|
380
|
+
|
|
381
|
+
let currentMatches = [];
|
|
382
|
+
let currentMatchIndex = -1;
|
|
383
|
+
|
|
384
|
+
if (!searchInput || !propertiesContainer) return;
|
|
385
|
+
|
|
386
|
+
// Expand All functionality
|
|
387
|
+
if (expandAllBtn) {
|
|
388
|
+
expandAllBtn.addEventListener('click', () => {
|
|
389
|
+
const toggleButtons = schemaViewerClient.querySelectorAll('.property-toggle');
|
|
390
|
+
toggleButtons.forEach((button) => {
|
|
391
|
+
if (button.getAttribute('aria-expanded') === 'false') {
|
|
392
|
+
button.click();
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Collapse All functionality
|
|
399
|
+
if (collapseAllBtn) {
|
|
400
|
+
collapseAllBtn.addEventListener('click', () => {
|
|
401
|
+
const toggleButtons = schemaViewerClient.querySelectorAll('.property-toggle');
|
|
402
|
+
toggleButtons.forEach((button) => {
|
|
403
|
+
if (button.getAttribute('aria-expanded') === 'true') {
|
|
404
|
+
button.click();
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Helper functions
|
|
411
|
+
function scrollToMatch(container) {
|
|
412
|
+
container.scrollIntoView({
|
|
413
|
+
behavior: 'smooth',
|
|
414
|
+
block: 'center',
|
|
415
|
+
inline: 'nearest',
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function updateMatchDisplay() {
|
|
420
|
+
// Remove previous current match highlighting
|
|
421
|
+
currentMatches.forEach((match, index) => {
|
|
422
|
+
match.classList.remove('search-current-match');
|
|
423
|
+
if (index === currentMatchIndex) {
|
|
424
|
+
match.classList.add('search-current-match');
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Update navigation buttons
|
|
429
|
+
if (prevMatchBtn && nextMatchBtn) {
|
|
430
|
+
prevMatchBtn.disabled = currentMatches.length === 0 || currentMatchIndex <= 0;
|
|
431
|
+
nextMatchBtn.disabled = currentMatches.length === 0 || currentMatchIndex >= currentMatches.length - 1;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Update search results with current position
|
|
435
|
+
if (searchResults && currentMatches.length > 0) {
|
|
436
|
+
searchResults.textContent = `${currentMatchIndex + 1} of ${currentMatches.length} ${currentMatches.length === 1 ? 'match' : 'matches'}`;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function performSearch(searchTerm) {
|
|
441
|
+
const propertyContainers = propertiesContainer.querySelectorAll('.property-container');
|
|
442
|
+
currentMatches = [];
|
|
443
|
+
currentMatchIndex = -1;
|
|
444
|
+
|
|
445
|
+
if (searchTerm === '') {
|
|
446
|
+
// Reset search
|
|
447
|
+
propertyContainers.forEach((container) => {
|
|
448
|
+
container.classList.remove('search-match', 'search-no-match', 'search-current-match', 'search-dimmed');
|
|
449
|
+
const nameEl = container.querySelector('.font-semibold');
|
|
450
|
+
if (nameEl) {
|
|
451
|
+
nameEl.innerHTML = nameEl.textContent;
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
searchResults.classList.add('hidden');
|
|
455
|
+
if (noResultsMessage) {
|
|
456
|
+
noResultsMessage.classList.add('hidden');
|
|
457
|
+
}
|
|
458
|
+
updateMatchDisplay();
|
|
459
|
+
|
|
460
|
+
// Scroll back to top when search is cleared
|
|
461
|
+
// Use the same container that we're already working with
|
|
462
|
+
const scrollableContainer = propertiesContainer.closest('.schema-viewer');
|
|
463
|
+
if (scrollableContainer) {
|
|
464
|
+
scrollableContainer.scrollTo({
|
|
465
|
+
top: 0,
|
|
466
|
+
behavior: 'smooth',
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Find all matches
|
|
473
|
+
propertyContainers.forEach((container) => {
|
|
474
|
+
const nameEl = container.querySelector('.font-semibold');
|
|
475
|
+
|
|
476
|
+
if (!nameEl) return;
|
|
477
|
+
|
|
478
|
+
const propName = nameEl.textContent.toLowerCase();
|
|
479
|
+
|
|
480
|
+
if (propName.includes(searchTerm)) {
|
|
481
|
+
container.classList.add('search-match');
|
|
482
|
+
container.classList.remove('search-dimmed');
|
|
483
|
+
currentMatches.push(container);
|
|
484
|
+
|
|
485
|
+
// Highlight the search term in the property name
|
|
486
|
+
const regex = new RegExp(`(${searchTerm})`, 'gi');
|
|
487
|
+
nameEl.innerHTML = nameEl.textContent.replace(regex, '<mark class="bg-yellow-200 rounded px-0.5">$1</mark>');
|
|
488
|
+
|
|
489
|
+
// Expand parent containers to show the match
|
|
490
|
+
let parent = container.parentElement;
|
|
491
|
+
while (parent && parent.id !== `${instanceId}-properties`) {
|
|
492
|
+
if (parent.classList.contains('nested-content') && parent.classList.contains('hidden')) {
|
|
493
|
+
const parentPropertyContainer = parent.closest('.property-container');
|
|
494
|
+
if (parentPropertyContainer) {
|
|
495
|
+
const toggleBtn = parentPropertyContainer.querySelector('.property-toggle');
|
|
496
|
+
if (toggleBtn && toggleBtn.getAttribute('aria-expanded') === 'false') {
|
|
497
|
+
toggleBtn.click();
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
parent = parent.parentElement;
|
|
502
|
+
}
|
|
503
|
+
} else {
|
|
504
|
+
container.classList.remove('search-match', 'search-current-match');
|
|
505
|
+
container.classList.add('search-dimmed');
|
|
506
|
+
nameEl.innerHTML = nameEl.textContent;
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// Show results
|
|
511
|
+
if (searchResults) {
|
|
512
|
+
searchResults.classList.remove('hidden');
|
|
513
|
+
if (currentMatches.length === 0) {
|
|
514
|
+
searchResults.textContent = 'No properties found';
|
|
515
|
+
searchResults.classList.add('text-red-600');
|
|
516
|
+
searchResults.classList.remove('text-gray-600');
|
|
517
|
+
if (noResultsMessage) {
|
|
518
|
+
noResultsMessage.classList.remove('hidden');
|
|
519
|
+
}
|
|
520
|
+
} else {
|
|
521
|
+
searchResults.classList.remove('text-red-600');
|
|
522
|
+
searchResults.classList.add('text-gray-600');
|
|
523
|
+
if (noResultsMessage) {
|
|
524
|
+
noResultsMessage.classList.add('hidden');
|
|
525
|
+
}
|
|
526
|
+
// Go to first match
|
|
527
|
+
currentMatchIndex = 0;
|
|
528
|
+
scrollToMatch(currentMatches[0]);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
updateMatchDisplay();
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Search functionality
|
|
536
|
+
let searchTimeout;
|
|
537
|
+
searchInput.addEventListener('input', (e) => {
|
|
538
|
+
clearTimeout(searchTimeout);
|
|
539
|
+
searchTimeout = setTimeout(() => {
|
|
540
|
+
const searchTerm = e.target.value.toLowerCase().trim();
|
|
541
|
+
performSearch(searchTerm);
|
|
542
|
+
}, 300);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// Navigation functionality
|
|
546
|
+
if (prevMatchBtn) {
|
|
547
|
+
prevMatchBtn.addEventListener('click', () => {
|
|
548
|
+
if (currentMatchIndex > 0) {
|
|
549
|
+
currentMatchIndex--;
|
|
550
|
+
scrollToMatch(currentMatches[currentMatchIndex]);
|
|
551
|
+
updateMatchDisplay();
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (nextMatchBtn) {
|
|
557
|
+
nextMatchBtn.addEventListener('click', () => {
|
|
558
|
+
if (currentMatchIndex < currentMatches.length - 1) {
|
|
559
|
+
currentMatchIndex++;
|
|
560
|
+
scrollToMatch(currentMatches[currentMatchIndex]);
|
|
561
|
+
updateMatchDisplay();
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Keyboard navigation
|
|
567
|
+
searchInput.addEventListener('keydown', (e) => {
|
|
568
|
+
if (e.key === 'Enter') {
|
|
569
|
+
e.preventDefault();
|
|
570
|
+
if (e.shiftKey && prevMatchBtn && !prevMatchBtn.disabled) {
|
|
571
|
+
prevMatchBtn.click();
|
|
572
|
+
} else if (!e.shiftKey && nextMatchBtn && !nextMatchBtn.disabled) {
|
|
573
|
+
nextMatchBtn.click();
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
|
|
238
579
|
if (variants) {
|
|
239
580
|
const selector = document.getElementById(`${instanceId}-variant-selector`);
|
|
240
581
|
const propertiesContainer = document.getElementById(`${instanceId}-properties`);
|
|
@@ -267,10 +608,42 @@ const instanceId = `${id}-${file}-${Math.random().toString(36).substring(2, 9)}`
|
|
|
267
608
|
// Initialize with first variant
|
|
268
609
|
updateRequiredFields();
|
|
269
610
|
}
|
|
611
|
+
|
|
612
|
+
// Check expand state after page loads and after portal movement
|
|
613
|
+
document.addEventListener('astro:page-load', () => {
|
|
614
|
+
// Small delay to ensure portal movement has completed
|
|
615
|
+
setTimeout(() => {
|
|
616
|
+
checkAndExpandAll();
|
|
617
|
+
setupSchemaUtilities();
|
|
618
|
+
}, 100);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// Also check immediately in case the component is already in place
|
|
622
|
+
checkAndExpandAll();
|
|
623
|
+
setupSchemaUtilities();
|
|
270
624
|
</script>
|
|
271
625
|
|
|
272
626
|
<style>
|
|
273
627
|
.schema-viewer code {
|
|
274
628
|
font-family: 'Courier New', Courier, monospace;
|
|
275
629
|
}
|
|
630
|
+
|
|
631
|
+
/* Search highlighting styles */
|
|
632
|
+
.search-dimmed {
|
|
633
|
+
opacity: 0.4;
|
|
634
|
+
transition: opacity 0.2s ease;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
.search-match {
|
|
638
|
+
opacity: 1;
|
|
639
|
+
transition: opacity 0.2s ease;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.search-current-match {
|
|
643
|
+
background-color: rgba(59, 130, 246, 0.1);
|
|
644
|
+
border-left: 3px solid #3b82f6;
|
|
645
|
+
padding-left: 8px;
|
|
646
|
+
margin-left: -11px;
|
|
647
|
+
transition: all 0.2s ease;
|
|
648
|
+
}
|
|
276
649
|
</style>
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
const SchemaViewerPortal = (props: any) => {
|
|
2
|
-
|
|
2
|
+
// Convert string props to booleans (MDX passes strings)
|
|
3
|
+
const expandBool = props.expand === true || props.expand === 'true';
|
|
4
|
+
const searchBool = props.search !== false && props.search !== 'false';
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
id={`${props.id}-${props.file}-SchemaViewer-portal`}
|
|
9
|
+
data-expand={expandBool ? 'true' : 'false'}
|
|
10
|
+
data-max-height={props.maxHeight}
|
|
11
|
+
data-search={searchBool ? 'true' : 'false'}
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
3
14
|
};
|
|
4
15
|
|
|
5
16
|
export default SchemaViewerPortal;
|
|
@@ -15,7 +15,7 @@ try {
|
|
|
15
15
|
const schemaViewers = getMDXComponentsByName(file, 'SchemaViewer');
|
|
16
16
|
|
|
17
17
|
// Loop around all the possible SchemaViewers in the file.
|
|
18
|
-
const getAllComponents = schemaViewers.map(async (schemaViewerProps: any) => {
|
|
18
|
+
const getAllComponents = schemaViewers.map(async (schemaViewerProps: any, index: number) => {
|
|
19
19
|
const schemaPath = path.join(path.dirname(filePath), schemaViewerProps.file);
|
|
20
20
|
const exists = existsSync(schemaPath);
|
|
21
21
|
let schema;
|
|
@@ -42,6 +42,7 @@ try {
|
|
|
42
42
|
schemaPath,
|
|
43
43
|
...schemaViewerProps,
|
|
44
44
|
render,
|
|
45
|
+
index,
|
|
45
46
|
};
|
|
46
47
|
});
|
|
47
48
|
|
|
@@ -59,7 +60,7 @@ try {
|
|
|
59
60
|
if (!schema.render) return null;
|
|
60
61
|
return (
|
|
61
62
|
<div>
|
|
62
|
-
{schema.exists && <SchemaViewerClient {...schema} />}
|
|
63
|
+
{schema.exists && <SchemaViewerClient {...schema} id={`${schema.id}-${schema.file}-SchemaViewer-client`} />}
|
|
63
64
|
|
|
64
65
|
{/* User has tried to load the schema, but it was not found on file system */}
|
|
65
66
|
{!schema.exists && (
|
|
@@ -83,8 +84,33 @@ try {
|
|
|
83
84
|
function moveSchemaViewerToPortal(schema) {
|
|
84
85
|
const portalId = `${schema.id}-${schema.file}-SchemaViewer-portal`;
|
|
85
86
|
const schemaViewerContainer = document.getElementById(portalId);
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
const schemaViewerClient = document.getElementById(`${schema.id}-${schema.file}-SchemaViewer-client`);
|
|
88
|
+
|
|
89
|
+
if (schemaViewerContainer && schemaViewerClient) {
|
|
90
|
+
// Get attributes from the portal
|
|
91
|
+
const expand = schemaViewerContainer.getAttribute('data-expand') === 'true';
|
|
92
|
+
const maxHeight = schemaViewerContainer.getAttribute('data-max-height');
|
|
93
|
+
const search = schemaViewerContainer.getAttribute('data-search');
|
|
94
|
+
|
|
95
|
+
// Set the expand attribute on the schema viewer client
|
|
96
|
+
if (expand) {
|
|
97
|
+
schemaViewerClient.setAttribute('data-expand', 'true');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Set the search attribute on the schema viewer client
|
|
101
|
+
if (search) {
|
|
102
|
+
schemaViewerClient.setAttribute('data-search', search);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Set the maxHeight on the schema viewer element
|
|
106
|
+
if (maxHeight) {
|
|
107
|
+
const schemaViewerElement = schemaViewerClient.querySelector('.schema-viewer');
|
|
108
|
+
if (schemaViewerElement) {
|
|
109
|
+
schemaViewerElement.style.maxHeight = `${maxHeight}px`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
schemaViewerContainer.appendChild(schemaViewerClient);
|
|
88
114
|
}
|
|
89
115
|
}
|
|
90
116
|
|
|
@@ -189,6 +189,39 @@ const canPageBeEmbedded = process.env.ENABLE_EMBED === 'true';
|
|
|
189
189
|
visibility: visible;
|
|
190
190
|
z-index: 100;
|
|
191
191
|
}
|
|
192
|
+
|
|
193
|
+
/* Hide anchor link by default */
|
|
194
|
+
.anchor-link {
|
|
195
|
+
display: inline-block;
|
|
196
|
+
width: 1em;
|
|
197
|
+
height: 1em;
|
|
198
|
+
margin-left: 0.5rem;
|
|
199
|
+
margin-top: 0.25rem;
|
|
200
|
+
background-image: url('data:image/svg+xml,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20fill%3D%22currentColor%22%20d%3D%22m12.11%2015.39-3.88%203.88a2.52%202.52%200%200%201-3.5%200%202.47%202.47%200%200%201%200-3.5l3.88-3.88a1%201%200%200%200-1.42-1.42l-3.88%203.89a4.48%204.48%200%200%200%206.33%206.33l3.89-3.88a1%201%200%201%200-1.42-1.42Zm8.58-12.08a4.49%204.49%200%200%200-6.33%200l-3.89%203.88a1%201%200%200%200%201.42%201.42l3.88-3.88a2.52%202.52%200%200%201%203.5%200%202.47%202.47%200%200%201%200%203.5l-3.88%203.88a1%201%200%201%200%201.42%201.42l3.88-3.89a4.49%204.49%200%200%200%200-6.33ZM8.83%2015.17a1%201%200%200%200%201.1.22%201%201%200%200%200%20.32-.22l4.92-4.92a1%201%200%200%200-1.42-1.42l-4.92%204.92a1%201%200%200%200%200%201.42Z%22/%3E%3C/svg%3E');
|
|
201
|
+
background-repeat: no-repeat;
|
|
202
|
+
background-position: center;
|
|
203
|
+
background-size: 1em 1em;
|
|
204
|
+
opacity: 0;
|
|
205
|
+
transition: opacity 0.2s ease-in-out;
|
|
206
|
+
text-decoration: none;
|
|
207
|
+
vertical-align: -2px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* Show icon on heading hover */
|
|
211
|
+
h1:hover .anchor-link,
|
|
212
|
+
h2:hover .anchor-link,
|
|
213
|
+
h3:hover .anchor-link,
|
|
214
|
+
h4:hover .anchor-link,
|
|
215
|
+
h5:hover .anchor-link,
|
|
216
|
+
h6:hover .anchor-link {
|
|
217
|
+
opacity: 1;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* Show on keyboard focus */
|
|
221
|
+
.anchor-link:focus {
|
|
222
|
+
opacity: 1;
|
|
223
|
+
outline: none;
|
|
224
|
+
}
|
|
192
225
|
</style>
|
|
193
226
|
</head>
|
|
194
227
|
<body>
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/event-catalog/eventcatalog.git"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
|
-
"version": "2.45.
|
|
9
|
+
"version": "2.45.3",
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
"react-dom": "^18.3.1",
|
|
86
86
|
"react-markdown": "^10.1.0",
|
|
87
87
|
"react-syntax-highlighter": "^15.6.1",
|
|
88
|
+
"rehype-autolink-headings": "^7.1.0",
|
|
88
89
|
"rehype-slug": "^6.0.0",
|
|
89
90
|
"remark-comment": "^1.0.0",
|
|
90
91
|
"remark-directive": "^3.0.0",
|