@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.
Files changed (82) 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-H5UC2A5F.js → chunk-6UG4JMUV.js} +1 -1
  6. package/dist/{chunk-4MSAPCV3.js → chunk-ATRBVTJ6.js} +1 -1
  7. package/dist/{chunk-PLNJC7NZ.js → chunk-K3ZVEX2Y.js} +13 -2
  8. package/dist/{chunk-V4OTI3PF.js → chunk-MVZKHUX2.js} +1 -1
  9. package/dist/{chunk-FVKDNLZK.js → chunk-RRBDF4MM.js} +1 -1
  10. package/dist/{chunk-24NGK43A.js → chunk-Z26P4PCB.js} +1 -1
  11. package/dist/constants.cjs +1 -1
  12. package/dist/constants.js +1 -1
  13. package/dist/eventcatalog.cjs +14 -3
  14. package/dist/eventcatalog.js +6 -6
  15. package/dist/generate.cjs +1 -1
  16. package/dist/generate.js +3 -3
  17. package/dist/utils/cli-logger.cjs +1 -1
  18. package/dist/utils/cli-logger.js +2 -2
  19. package/dist/watcher.cjs +13 -2
  20. package/dist/watcher.js +1 -1
  21. package/eventcatalog/astro.config.mjs +1 -1
  22. package/eventcatalog/public/logo.png +0 -0
  23. package/eventcatalog/src/components/CopyAsMarkdown.tsx +2 -2
  24. package/eventcatalog/src/components/EnvironmentDropdown.tsx +33 -21
  25. package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +3 -53
  26. package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +144 -91
  27. package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +112 -109
  28. package/eventcatalog/src/components/Header.astro +9 -19
  29. package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +12 -14
  30. package/eventcatalog/src/components/MDX/Accordion/AccordionGroup.astro +11 -3
  31. package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +15 -5
  32. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +164 -53
  33. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +1 -1
  34. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +4 -4
  35. package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +12 -10
  36. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +48 -77
  37. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +238 -169
  38. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +189 -230
  39. package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +39 -36
  40. package/eventcatalog/src/components/Search/Search.astro +1 -1
  41. package/eventcatalog/src/components/Seo.astro +1 -1
  42. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -3
  43. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +229 -256
  44. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +78 -59
  45. package/eventcatalog/src/components/Tables/Discover/columns.tsx +130 -197
  46. package/eventcatalog/src/components/Tables/Table.tsx +21 -18
  47. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +79 -131
  48. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +104 -175
  49. package/eventcatalog/src/enterprise/auth/error.astro +1 -1
  50. package/eventcatalog/src/enterprise/auth/login.astro +1 -1
  51. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +95 -93
  52. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +174 -136
  53. package/eventcatalog/src/enterprise/fields/pages/fields.astro +10 -8
  54. package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +0 -8
  55. package/eventcatalog/src/layouts/DirectoryLayout.astro +17 -88
  56. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +528 -146
  57. package/eventcatalog/src/layouts/VisualiserLayout.astro +7 -2
  58. package/eventcatalog/src/pages/_index.astro +5 -3
  59. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -3
  60. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +223 -73
  61. package/eventcatalog/src/pages/discover/[type]/index.astro +22 -141
  62. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +129 -29
  63. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +129 -29
  64. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +6 -2
  65. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +2 -2
  66. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +21 -18
  67. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +33 -32
  68. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +5 -1
  69. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +2 -2
  70. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +4 -6
  71. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +11 -4
  72. package/eventcatalog/src/pages/docs/users/[id]/index.astro +11 -4
  73. package/eventcatalog/src/pages/schemas/explorer/index.astro +10 -8
  74. package/eventcatalog/src/pages/studio.astro +1 -1
  75. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +2 -7
  76. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
  77. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +2 -7
  78. package/eventcatalog/src/styles/theme.css +68 -12
  79. package/eventcatalog/src/types/react-syntax-highlighter.d.ts +13 -0
  80. package/package.json +1 -1
  81. package/eventcatalog/public/logo.svg +0 -14
  82. package/eventcatalog/src/enterprise/plans/index.astro +0 -319
@@ -4,17 +4,72 @@ import { filterByName, filterCollectionByName } from '../filters/custom-filters'
4
4
  import { buildUrl } from '@utils/url-builder';
5
5
  import type { TData } from '../Table';
6
6
  import type { CollectionUserTypes } from '@types';
7
- import { User, Users } from 'lucide-react';
8
- import type { CollectionEntry } from 'astro:content';
9
- import { ServerIcon, BoltIcon, ChatBubbleLeftIcon, MagnifyingGlassIcon } from '@heroicons/react/24/solid';
10
7
  import type { TableConfiguration } from '@types';
8
+ import { getColorAndIconForCollection } from '@utils/collections/icons';
11
9
  const columnHelper = createColumnHelper<TData<CollectionUserTypes>>();
12
10
 
13
- const getMessageIconAndColor = (collection: string) => {
14
- if (collection === 'events') return { Icon: BoltIcon, color: 'orange' };
15
- if (collection === 'commands') return { Icon: ChatBubbleLeftIcon, color: 'blue' };
16
- if (collection === 'queries') return { Icon: MagnifyingGlassIcon, color: 'green' };
17
- return { Icon: ChatBubbleLeftIcon, color: 'gray' };
11
+ const colorClasses: Record<string, string> = {
12
+ orange: 'text-orange-500',
13
+ blue: 'text-blue-500',
14
+ green: 'text-green-500',
15
+ pink: 'text-pink-500',
16
+ yellow: 'text-yellow-500',
17
+ teal: 'text-teal-500',
18
+ purple: 'text-purple-500',
19
+ red: 'text-red-500',
20
+ gray: 'text-gray-500',
21
+ cyan: 'text-cyan-500',
22
+ };
23
+
24
+ const CollectionListCell = ({
25
+ items,
26
+ emptyText,
27
+ }: {
28
+ items: Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined;
29
+ emptyText: string;
30
+ }) => {
31
+ const [isExpanded, setIsExpanded] = useState(false);
32
+
33
+ if (!items || items.length === 0) {
34
+ return <span className="text-xs text-[rgb(var(--ec-icon-color))]">{emptyText}</span>;
35
+ }
36
+
37
+ const visibleItems = isExpanded ? items : items.slice(0, 4);
38
+ const hiddenCount = items.length - 4;
39
+
40
+ return (
41
+ <div className="flex flex-col gap-1">
42
+ {visibleItems.map((item, index) => {
43
+ const { color, Icon } = getColorAndIconForCollection(item.collection);
44
+ const href =
45
+ item.collection === 'teams'
46
+ ? buildUrl(`/docs/teams/${item.data.id}`)
47
+ : buildUrl(`/docs/${item.collection}/${item.data.id}${item.data.version ? `/${item.data.version}` : ''}`);
48
+
49
+ return (
50
+ <a
51
+ key={`${item.data.id}-${index}`}
52
+ href={href}
53
+ className="group inline-flex items-center gap-1.5 text-[0.8rem] text-[rgb(var(--ec-icon-color))] transition-colors hover:text-[rgb(var(--ec-accent))]"
54
+ >
55
+ <Icon className={`h-3.5 w-3.5 flex-shrink-0 ${colorClasses[color] || 'text-[rgb(var(--ec-icon-color))]'}`} />
56
+ <span className="max-w-[140px] truncate" title={item.data.name}>
57
+ {item.data.name}
58
+ </span>
59
+ {item.data.version && <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{item.data.version}</span>}
60
+ </a>
61
+ );
62
+ })}
63
+ {hiddenCount > 0 && (
64
+ <button
65
+ onClick={() => setIsExpanded(!isExpanded)}
66
+ className="text-xs text-[rgb(var(--ec-accent))] hover:underline text-left"
67
+ >
68
+ {isExpanded ? 'Show less' : `+${hiddenCount} more`}
69
+ </button>
70
+ )}
71
+ </div>
72
+ );
18
73
  };
19
74
 
20
75
  export const columns = (tableConfiguration: TableConfiguration) => [
@@ -24,16 +79,11 @@ export const columns = (tableConfiguration: TableConfiguration) => [
24
79
  cell: (info) => {
25
80
  const user = info.row.original;
26
81
  return (
27
- <a href={buildUrl(`/docs/${user.collection}/${user.data.id}`)} className="group inline-flex items-center">
28
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-[rgb(var(--ec-accent))] hover:bg-[rgb(var(--ec-accent-subtle))] transition-colors">
29
- <span className="flex items-center justify-center w-6 h-6 bg-[rgb(var(--ec-accent))] rounded-l-md">
30
- <User className="h-3 w-3 text-white" />
31
- </span>
32
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
33
- {user.data.name}
34
- {user.data.role && <span className="text-[rgb(var(--ec-icon-color))] ml-1">({user.data.role})</span>}
35
- </span>
36
- </span>
82
+ <a
83
+ href={buildUrl(`/docs/${user.collection}/${user.data.id}`)}
84
+ className="group inline-flex items-center text-sm font-semibold text-[rgb(var(--ec-page-text))] transition-colors hover:text-[rgb(var(--ec-accent))]"
85
+ >
86
+ <span>{user.data.name}</span>
37
87
  </a>
38
88
  );
39
89
  },
@@ -44,6 +94,22 @@ export const columns = (tableConfiguration: TableConfiguration) => [
44
94
  filterFn: filterByName,
45
95
  }),
46
96
 
97
+ columnHelper.accessor('data.role', {
98
+ id: 'role',
99
+ header: () => <span>{tableConfiguration.columns?.role?.label || 'Role'}</span>,
100
+ cell: (info) => {
101
+ const role = info.getValue() as string | undefined;
102
+ return role ? (
103
+ <span className="text-[0.8rem] text-[rgb(var(--ec-icon-color))]">{role}</span>
104
+ ) : (
105
+ <span className="text-xs text-[rgb(var(--ec-icon-color))]">-</span>
106
+ );
107
+ },
108
+ meta: {
109
+ showFilter: false,
110
+ },
111
+ }),
112
+
47
113
  columnHelper.accessor(
48
114
  (row) => {
49
115
  const events = row.data.ownedEvents || [];
@@ -57,57 +123,14 @@ export const columns = (tableConfiguration: TableConfiguration) => [
57
123
  meta: {
58
124
  showFilter: false,
59
125
  },
60
- cell: (info) => {
61
- const messages = info.getValue() as Array<
62
- CollectionEntry<'events'> | CollectionEntry<'commands'> | CollectionEntry<'queries'>
63
- >;
64
- const [isExpanded, setIsExpanded] = useState(false);
65
-
66
- if (messages?.length === 0 || !messages)
67
- return (
68
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
69
- No messages
70
- </span>
71
- );
72
-
73
- const visibleItems = isExpanded ? messages : messages.slice(0, 4);
74
- const hiddenCount = messages.length - 4;
75
-
76
- return (
77
- <div className="flex flex-col gap-1.5">
78
- {visibleItems.map((message, index: number) => {
79
- const { Icon, color } = getMessageIconAndColor(message.collection);
80
- return (
81
- <a
82
- key={`${message.data.id}-${index}`}
83
- href={buildUrl(`/docs/${message.collection}/${message.data.id}/${message.data.version}`)}
84
- className="group inline-flex items-center"
85
- >
86
- <span
87
- className={`inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-${color}-400 dark:hover:border-${color}-500 hover:bg-${color}-50 dark:hover:bg-${color}-500/10 transition-colors`}
88
- >
89
- <span className={`flex items-center justify-center w-6 h-6 bg-${color}-500 rounded-l-md`}>
90
- <Icon className="h-3 w-3 text-white" />
91
- </span>
92
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
93
- {message.data.name}
94
- <span className="text-[rgb(var(--ec-icon-color))] ml-1">v{message.data.version}</span>
95
- </span>
96
- </span>
97
- </a>
98
- );
99
- })}
100
- {hiddenCount > 0 && (
101
- <button
102
- onClick={() => setIsExpanded(!isExpanded)}
103
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
104
- >
105
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
106
- </button>
107
- )}
108
- </div>
109
- );
110
- },
126
+ cell: (info) => (
127
+ <CollectionListCell
128
+ items={
129
+ info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined
130
+ }
131
+ emptyText="No messages"
132
+ />
133
+ ),
111
134
  }
112
135
  ),
113
136
 
@@ -118,50 +141,12 @@ export const columns = (tableConfiguration: TableConfiguration) => [
118
141
  filterVariant: 'collection',
119
142
  collectionFilterKey: 'ownedServices',
120
143
  },
121
- cell: (info) => {
122
- const services = info.getValue();
123
- const [isExpanded, setIsExpanded] = useState(false);
124
-
125
- if (services?.length === 0 || !services)
126
- return (
127
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
128
- No services
129
- </span>
130
- );
131
-
132
- const visibleItems = isExpanded ? services : services.slice(0, 4);
133
- const hiddenCount = services.length - 4;
134
-
135
- return (
136
- <div className="flex flex-col gap-1.5">
137
- {visibleItems.map((service: CollectionEntry<'services'>, index: number) => (
138
- <a
139
- key={`${service.data.id}-${index}`}
140
- href={buildUrl(`/docs/${service.collection}/${service.data.id}/${service.data.version}`)}
141
- className="group inline-flex items-center"
142
- >
143
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-pink-400 dark:hover:border-pink-500 hover:bg-pink-50 dark:hover:bg-pink-500/10 transition-colors">
144
- <span className="flex items-center justify-center w-6 h-6 bg-pink-500 rounded-l-md">
145
- <ServerIcon className="h-3 w-3 text-white" />
146
- </span>
147
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
148
- {service.data.name}
149
- <span className="text-[rgb(var(--ec-icon-color))] ml-1">v{service.data.version}</span>
150
- </span>
151
- </span>
152
- </a>
153
- ))}
154
- {hiddenCount > 0 && (
155
- <button
156
- onClick={() => setIsExpanded(!isExpanded)}
157
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
158
- >
159
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
160
- </button>
161
- )}
162
- </div>
163
- );
164
- },
144
+ cell: (info) => (
145
+ <CollectionListCell
146
+ items={info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined}
147
+ emptyText="No services"
148
+ />
149
+ ),
165
150
  footer: (info) => info.column.id,
166
151
  filterFn: filterCollectionByName('ownedServices'),
167
152
  }),
@@ -174,69 +159,13 @@ export const columns = (tableConfiguration: TableConfiguration) => [
174
159
  collectionFilterKey: 'associatedTeams',
175
160
  filteredItemHasVersion: false,
176
161
  },
177
- cell: (info) => {
178
- const teams = info.getValue();
179
- const [isExpanded, setIsExpanded] = useState(false);
180
-
181
- if (teams?.length === 0 || !teams)
182
- return (
183
- <span className="inline-flex items-center px-2 py-1 text-xs text-[rgb(var(--ec-icon-color))] bg-[rgb(var(--ec-content-hover))] rounded-md border border-[rgb(var(--ec-page-border))]">
184
- No teams
185
- </span>
186
- );
187
-
188
- const visibleItems = isExpanded ? teams : teams.slice(0, 4);
189
- const hiddenCount = teams.length - 4;
190
-
191
- return (
192
- <div className="flex flex-col gap-1.5">
193
- {visibleItems.map((team: CollectionEntry<'teams'>, index: number) => (
194
- <a
195
- key={`${team.data.id}-${index}`}
196
- href={buildUrl(`/docs/teams/${team.data.id}`)}
197
- className="group inline-flex items-center"
198
- >
199
- <span className="inline-flex items-center rounded-md border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] hover:border-pink-400 dark:hover:border-pink-500 hover:bg-pink-50 dark:hover:bg-pink-500/10 transition-colors">
200
- <span className="flex items-center justify-center w-6 h-6 bg-pink-500 rounded-l-md">
201
- <Users className="h-3 w-3 text-white" />
202
- </span>
203
- <span className="px-2 py-1 text-xs text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-page-text))]">
204
- {team.data.name}
205
- </span>
206
- </span>
207
- </a>
208
- ))}
209
- {hiddenCount > 0 && (
210
- <button
211
- onClick={() => setIsExpanded(!isExpanded)}
212
- className="text-xs text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] text-left"
213
- >
214
- {isExpanded ? 'Show less' : `+${hiddenCount} more`}
215
- </button>
216
- )}
217
- </div>
218
- );
219
- },
162
+ cell: (info) => (
163
+ <CollectionListCell
164
+ items={info.getValue() as Array<{ collection: string; data: { id: string; name: string; version?: string } }> | undefined}
165
+ emptyText="No teams"
166
+ />
167
+ ),
220
168
  footer: (info) => info.column.id,
221
169
  filterFn: filterCollectionByName('associatedTeams'),
222
170
  }),
223
-
224
- columnHelper.accessor('data.name', {
225
- header: () => <span>{tableConfiguration.columns?.actions?.label || 'Actions'}</span>,
226
- cell: (info) => {
227
- const item = info.row.original;
228
- return (
229
- <a
230
- className="inline-flex items-center px-2.5 py-1 text-xs font-medium text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-content-hover))] border border-[rgb(var(--ec-page-border))] rounded-md hover:bg-[rgb(var(--ec-content-hover))] hover:text-[rgb(var(--ec-page-text))] transition-colors whitespace-nowrap"
231
- href={buildUrl(`/docs/${item.collection}/${item.data.id}`)}
232
- >
233
- View profile
234
- </a>
235
- );
236
- },
237
- id: 'actions',
238
- meta: {
239
- showFilter: false,
240
- },
241
- }),
242
171
  ];
@@ -21,7 +21,7 @@ const errorMessage = errorMessages[error] || errorMessages.Default;
21
21
  <head>
22
22
  <meta charset="UTF-8" />
23
23
  <meta name="viewport" content="width=device-width" />
24
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
24
+ <link rel="icon" type="image/png" href="/logo.png" />
25
25
  <meta name="generator" content={Astro.generator} />
26
26
  <title>Authentication Error - EventCatalog</title>
27
27
  </head>
@@ -102,7 +102,7 @@ const providerConfig = {
102
102
  <head>
103
103
  <meta charset="UTF-8" />
104
104
  <meta name="viewport" content="width=device-width" />
105
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
105
+ <link rel="icon" type="image/png" href="/logo.png" />
106
106
  <meta name="generator" content={Astro.generator} />
107
107
  <title>Sign In | {title}</title>
108
108
  <link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -203,8 +203,8 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems }) => {
203
203
  const hasNoResults = debouncedSearchTerm && filteredSidebarItems.length === 0;
204
204
 
205
205
  return (
206
- <nav ref={navRef} className="h-full text-[rgb(var(--ec-page-text))] pt-4 overflow-y-auto">
207
- <div className="mb-2 px-3 bg-[rgb(var(--ec-page-bg))] z-10">
206
+ <nav ref={navRef} className="flex h-full min-h-0 flex-col text-[rgb(var(--ec-page-text))]">
207
+ <div className="flex-shrink-0 border-b border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-page-bg))] px-3 py-3.5">
208
208
  <div className="flex gap-2">
209
209
  <input
210
210
  type="text"
@@ -227,103 +227,105 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems }) => {
227
227
  </div>
228
228
  </div>
229
229
 
230
- <div className="space-y-2 divide-y divide-[rgb(var(--ec-page-border))] pb-4">
231
- {hasNoResults ? (
232
- <NoResultsFound searchTerm={debouncedSearchTerm} />
233
- ) : (
234
- filteredSidebarItems.map((section: SidebarSection, index: number) => {
235
- const sectionBadgeClassName = getCustomDocsSidebarBadgeClasses(section.badge?.color);
236
- return (
237
- <div className="pt-2 pb-2 px-3" key={`section-${index}`}>
238
- <div className="space-y-0" data-section={`section-${index}`}>
239
- {section.items ? (
240
- <div className="flex items-center">
241
- <button
242
- className="p-1 hover:bg-[rgb(var(--ec-content-hover))] rounded-md flex-shrink-0"
243
- onClick={(e) => {
244
- e.stopPropagation();
245
- toggleGroupCollapse(`section-${index}`);
246
- }}
247
- >
248
- <div
249
- className={`transition-transform duration-150 ${collapsedGroups[`section-${index}`] ? '' : 'rotate-180'}`}
230
+ <div className="min-h-0 flex-1 overflow-y-auto">
231
+ <div className="space-y-2 divide-y divide-[rgb(var(--ec-page-border))] pb-4 pt-2">
232
+ {hasNoResults ? (
233
+ <NoResultsFound searchTerm={debouncedSearchTerm} />
234
+ ) : (
235
+ filteredSidebarItems.map((section: SidebarSection, index: number) => {
236
+ const sectionBadgeClassName = getCustomDocsSidebarBadgeClasses(section.badge?.color);
237
+ return (
238
+ <div className="pt-2 pb-2 px-3" key={`section-${index}`}>
239
+ <div className="space-y-0" data-section={`section-${index}`}>
240
+ {section.items ? (
241
+ <div className="flex items-center">
242
+ <button
243
+ className="p-1 hover:bg-[rgb(var(--ec-content-hover))] rounded-md flex-shrink-0"
244
+ onClick={(e) => {
245
+ e.stopPropagation();
246
+ toggleGroupCollapse(`section-${index}`);
247
+ }}
250
248
  >
251
- <svg
252
- xmlns="http://www.w3.org/2000/svg"
253
- fill="none"
254
- viewBox="0 0 24 24"
255
- strokeWidth="1.5"
256
- stroke="currentColor"
257
- aria-hidden="true"
258
- data-slot="icon"
259
- className="h-3 w-3 text-[rgb(var(--ec-icon-color))]"
249
+ <div
250
+ className={`transition-transform duration-150 ${collapsedGroups[`section-${index}`] ? '' : 'rotate-180'}`}
260
251
  >
261
- <path strokeLinecap="round" strokeLinejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"></path>
262
- </svg>
252
+ <svg
253
+ xmlns="http://www.w3.org/2000/svg"
254
+ fill="none"
255
+ viewBox="0 0 24 24"
256
+ strokeWidth="1.5"
257
+ stroke="currentColor"
258
+ aria-hidden="true"
259
+ data-slot="icon"
260
+ className="h-3 w-3 text-[rgb(var(--ec-icon-color))]"
261
+ >
262
+ <path strokeLinecap="round" strokeLinejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"></path>
263
+ </svg>
264
+ </div>
265
+ </button>
266
+ <button
267
+ className="flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md hover:bg-[rgb(var(--ec-content-hover))] min-w-0 flex-1"
268
+ onClick={(e) => {
269
+ e.stopPropagation();
270
+ toggleGroupCollapse(`section-${index}`);
271
+ }}
272
+ >
273
+ <span className="truncate">{section.label}</span>
274
+ {section.badge && section?.badge?.text && (
275
+ <span className={sectionBadgeClassName}>{section.badge.text}</span>
276
+ )}
277
+ </button>
278
+ </div>
279
+ ) : (
280
+ <div className="flex items-center">
281
+ <span className="flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md">
282
+ <span className="truncate">{section.label}</span>
283
+ <span className={sectionBadgeClassName}>Section</span>
284
+ </span>
285
+ </div>
286
+ )}
287
+
288
+ {section.items && (
289
+ <div
290
+ className={`overflow-hidden transition-[height] duration-150 ease-out ${
291
+ collapsedGroups[`section-${index}`] ? 'h-0' : 'h-auto'
292
+ }`}
293
+ >
294
+ <div className="space-y-0.5 border-[rgb(var(--ec-page-border))] border-l pl-4 ml-[9px] mt-1">
295
+ {section.items.map((item: SidebarItem, itemIndex: number) => (
296
+ <NestedItem
297
+ key={`item-${index}-${itemIndex}`}
298
+ item={item}
299
+ currentPath={currentPath}
300
+ parentId={`${index}`}
301
+ itemIndex={itemIndex}
302
+ collapsedGroups={collapsedGroups}
303
+ toggleGroupCollapse={toggleGroupCollapse}
304
+ />
305
+ ))}
263
306
  </div>
264
- </button>
265
- <button
266
- className="flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md hover:bg-[rgb(var(--ec-content-hover))] min-w-0 flex-1"
267
- onClick={(e) => {
268
- e.stopPropagation();
269
- toggleGroupCollapse(`section-${index}`);
270
- }}
307
+ </div>
308
+ )}
309
+
310
+ {section.slug && !section.items && (
311
+ <a
312
+ href={buildUrl(`/docs/custom/${section.slug}`)}
313
+ className={`flex items-center px-2 py-1.5 text-xs ${
314
+ currentPath.endsWith(`/${section.slug}`)
315
+ ? 'bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-page-text))] font-semibold'
316
+ : 'text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-content-hover))]'
317
+ } rounded-md ml-6`}
318
+ data-active={currentPath.endsWith(`/${section.slug}`)}
271
319
  >
272
320
  <span className="truncate">{section.label}</span>
273
- {section.badge && section?.badge?.text && (
274
- <span className={sectionBadgeClassName}>{section.badge.text}</span>
275
- )}
276
- </button>
277
- </div>
278
- ) : (
279
- <div className="flex items-center">
280
- <span className="flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md">
281
- <span className="truncate">{section.label}</span>
282
- <span className={sectionBadgeClassName}>Section</span>
283
- </span>
284
- </div>
285
- )}
286
-
287
- {section.items && (
288
- <div
289
- className={`overflow-hidden transition-[height] duration-150 ease-out ${
290
- collapsedGroups[`section-${index}`] ? 'h-0' : 'h-auto'
291
- }`}
292
- >
293
- <div className="space-y-0.5 border-[rgb(var(--ec-page-border))] border-l pl-4 ml-[9px] mt-1">
294
- {section.items.map((item: SidebarItem, itemIndex: number) => (
295
- <NestedItem
296
- key={`item-${index}-${itemIndex}`}
297
- item={item}
298
- currentPath={currentPath}
299
- parentId={`${index}`}
300
- itemIndex={itemIndex}
301
- collapsedGroups={collapsedGroups}
302
- toggleGroupCollapse={toggleGroupCollapse}
303
- />
304
- ))}
305
- </div>
306
- </div>
307
- )}
308
-
309
- {section.slug && !section.items && (
310
- <a
311
- href={buildUrl(`/docs/custom/${section.slug}`)}
312
- className={`flex items-center px-2 py-1.5 text-xs ${
313
- currentPath.endsWith(`/${section.slug}`)
314
- ? 'bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-page-text))] font-semibold'
315
- : 'text-[rgb(var(--ec-page-text-muted))] hover:bg-[rgb(var(--ec-content-hover))]'
316
- } rounded-md ml-6`}
317
- data-active={currentPath.endsWith(`/${section.slug}`)}
318
- >
319
- <span className="truncate">{section.label}</span>
320
- </a>
321
- )}
321
+ </a>
322
+ )}
323
+ </div>
322
324
  </div>
323
- </div>
324
- );
325
- })
326
- )}
325
+ );
326
+ })
327
+ )}
328
+ </div>
327
329
  </div>
328
330
  </nav>
329
331
  );