@eventcatalog/core 2.31.4 → 2.31.5

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 (25) 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-W5HUNIMM.js → chunk-45XUM7UR.js} +1 -1
  6. package/dist/{chunk-C3M26NRD.js → chunk-NPIJWM72.js} +1 -1
  7. package/dist/{chunk-H5QIDJHP.js → chunk-VCKSLDEL.js} +1 -1
  8. package/dist/constants.cjs +1 -1
  9. package/dist/constants.js +1 -1
  10. package/dist/eventcatalog.cjs +1 -1
  11. package/dist/eventcatalog.js +3 -3
  12. package/eventcatalog/src/components/SideNav/CustomDocsNav.astro +1 -1
  13. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro +9 -0
  14. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/components/NestedItem.tsx +26 -96
  15. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +19 -16
  16. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/types.ts +1 -0
  17. package/eventcatalog/src/enterprise/custom-documentation/pages/{index.astro → docs/custom/index.astro} +10 -5
  18. package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +6 -3
  19. package/eventcatalog/src/pages/docs/custom/[...path]/index.astro +4 -4
  20. package/package.json +1 -1
  21. package/eventcatalog/src/components/SideNav/CustomDocsNav/CustomDocsNavWrapper.tsx +0 -11
  22. package/eventcatalog/src/components/SideNav/CustomDocsNav/components/NestedItem.tsx +0 -183
  23. package/eventcatalog/src/components/SideNav/CustomDocsNav/components/NoResultsFound.tsx +0 -21
  24. package/eventcatalog/src/components/SideNav/CustomDocsNav/index.tsx +0 -250
  25. package/eventcatalog/src/components/SideNav/CustomDocsNav/types.ts +0 -29
@@ -37,7 +37,7 @@ var import_axios = __toESM(require("axios"), 1);
37
37
  var import_os = __toESM(require("os"), 1);
38
38
 
39
39
  // package.json
40
- var version = "2.31.4";
40
+ var version = "2.31.5";
41
41
 
42
42
  // src/constants.ts
43
43
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-W5HUNIMM.js";
4
- import "../chunk-H5QIDJHP.js";
3
+ } from "../chunk-45XUM7UR.js";
4
+ import "../chunk-VCKSLDEL.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -106,7 +106,7 @@ var import_axios = __toESM(require("axios"), 1);
106
106
  var import_os = __toESM(require("os"), 1);
107
107
 
108
108
  // package.json
109
- var version = "2.31.4";
109
+ var version = "2.31.5";
110
110
 
111
111
  // src/constants.ts
112
112
  var VERSION = version;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-C3M26NRD.js";
4
- import "../chunk-W5HUNIMM.js";
5
- import "../chunk-H5QIDJHP.js";
3
+ } from "../chunk-NPIJWM72.js";
4
+ import "../chunk-45XUM7UR.js";
5
+ import "../chunk-VCKSLDEL.js";
6
6
  import "../chunk-E7TXTI7G.js";
7
7
  export {
8
8
  log_build_default as default
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-H5QIDJHP.js";
3
+ } from "./chunk-VCKSLDEL.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-W5HUNIMM.js";
3
+ } from "./chunk-45XUM7UR.js";
4
4
  import {
5
5
  getEventCatalogConfigFile,
6
6
  verifyRequiredFieldsAreInCatalogConfigFile
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "2.31.4";
2
+ var version = "2.31.5";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "2.31.4";
28
+ var version = "2.31.5";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-H5QIDJHP.js";
3
+ } from "./chunk-VCKSLDEL.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -157,7 +157,7 @@ var import_axios = __toESM(require("axios"), 1);
157
157
  var import_os = __toESM(require("os"), 1);
158
158
 
159
159
  // package.json
160
- var version = "2.31.4";
160
+ var version = "2.31.5";
161
161
 
162
162
  // src/constants.ts
163
163
  var VERSION = version;
@@ -6,15 +6,15 @@ import {
6
6
  } from "./chunk-UKJ7F5WR.js";
7
7
  import {
8
8
  log_build_default
9
- } from "./chunk-C3M26NRD.js";
10
- import "./chunk-W5HUNIMM.js";
9
+ } from "./chunk-NPIJWM72.js";
10
+ import "./chunk-45XUM7UR.js";
11
11
  import {
12
12
  catalogToAstro,
13
13
  checkAndConvertMdToMdx
14
14
  } from "./chunk-7SI5EVOX.js";
15
15
  import {
16
16
  VERSION
17
- } from "./chunk-H5QIDJHP.js";
17
+ } from "./chunk-VCKSLDEL.js";
18
18
  import {
19
19
  isBackstagePluginEnabled,
20
20
  isEventCatalogProEnabled
@@ -6,4 +6,4 @@ const currentPath = Astro.url.pathname;
6
6
  const sidebarItems = await getNavigationItems();
7
7
  ---
8
8
 
9
- <CustomDocsNavWrapper client:load sidebarItems={sidebarItems} currentPath={currentPath} />
9
+ <CustomDocsNavWrapper client:only sidebarItems={sidebarItems} currentPath={currentPath} />
@@ -0,0 +1,9 @@
1
+ ---
2
+ import { getNavigationItems } from '@enterprise/custom-documentation/utils/custom-docs';
3
+ import CustomDocsNavWrapper from '@enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNavWrapper';
4
+
5
+ const currentPath = Astro.url.pathname;
6
+ const sidebarItems = await getNavigationItems();
7
+ ---
8
+
9
+ <CustomDocsNavWrapper client:only sidebarItems={sidebarItems} currentPath={currentPath} />
@@ -27,7 +27,7 @@ const NestedItem: React.FC<NestedItemProps> = ({
27
27
  <div className="py-1">
28
28
  <div className="flex items-center">
29
29
  <button
30
- className="p-1 hover:bg-gray-100 rounded-md"
30
+ className="p-1 hover:bg-gray-100 rounded-md flex-shrink-0"
31
31
  onClick={(e) => {
32
32
  e.stopPropagation();
33
33
  toggleGroupCollapse(`nested-${itemId}`);
@@ -35,29 +35,34 @@ const NestedItem: React.FC<NestedItemProps> = ({
35
35
  >
36
36
  <div className={`transition-transform duration-150 ${collapsedGroups[`nested-${itemId}`] ? '' : 'rotate-180'}`}>
37
37
  <svg
38
- className="h-3 w-3 text-gray-500"
39
38
  xmlns="http://www.w3.org/2000/svg"
40
- width="16"
41
- height="16"
42
- viewBox="0 0 24 24"
43
39
  fill="none"
40
+ viewBox="0 0 24 24"
41
+ strokeWidth="1.5"
44
42
  stroke="currentColor"
45
- strokeWidth="2"
46
- strokeLinecap="round"
47
- strokeLinejoin="round"
43
+ aria-hidden="true"
44
+ data-slot="icon"
45
+ className="h-3 w-3 text-gray-500"
48
46
  >
49
- <polyline points="6 9 12 15 18 9" />
47
+ <path strokeLinecap="round" strokeLinejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"></path>
50
48
  </svg>
51
49
  </div>
52
50
  </button>
53
51
  <button
54
- className="flex-grow flex items-center px-2 py-1 text-xs font-medium text-gray-700 rounded-md hover:bg-purple-50"
52
+ className="flex items-center px-2 py-1 text-xs font-medium text-gray-700 rounded-md hover:bg-purple-50 min-w-0 flex-1"
55
53
  onClick={(e) => {
56
54
  e.stopPropagation();
57
55
  toggleGroupCollapse(`nested-${itemId}`);
58
56
  }}
59
57
  >
60
58
  <span className="truncate">{item.label}</span>
59
+ {item.badge && item?.badge?.text && (
60
+ <span
61
+ className={`text-${item.badge.color || 'purple'}-600 ml-2 text-[10px] font-medium bg-${item.badge.color || 'purple'}-50 px-2 py-0.5 rounded uppercase`}
62
+ >
63
+ {item.badge.text}
64
+ </span>
65
+ )}
61
66
  </button>
62
67
  </div>
63
68
 
@@ -67,92 +72,17 @@ const NestedItem: React.FC<NestedItemProps> = ({
67
72
  }`}
68
73
  >
69
74
  <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
70
- {item.items.map((nestedItem: SidebarItem, nestedIndex: number) => {
71
- if (nestedItem.items && nestedItem.items.length > 0) {
72
- // Recursively render deeper nested items
73
- const nestedItemId = `${itemId}-${nestedIndex}`;
74
- return (
75
- <div className="py-1" key={`nested-${nestedItemId}`}>
76
- <div className="flex items-center">
77
- <button
78
- className="p-1 hover:bg-gray-100 rounded-md"
79
- onClick={(e) => {
80
- e.stopPropagation();
81
- toggleGroupCollapse(`nested-${nestedItemId}`);
82
- }}
83
- >
84
- <div
85
- className={`transition-transform duration-150 ${collapsedGroups[`nested-${nestedItemId}`] ? '' : 'rotate-180'}`}
86
- >
87
- <svg
88
- className="h-3 w-3 text-gray-500"
89
- xmlns="http://www.w3.org/2000/svg"
90
- width="16"
91
- height="16"
92
- viewBox="0 0 24 24"
93
- fill="none"
94
- stroke="currentColor"
95
- strokeWidth="2"
96
- strokeLinecap="round"
97
- strokeLinejoin="round"
98
- >
99
- <polyline points="6 9 12 15 18 9" />
100
- </svg>
101
- </div>
102
- </button>
103
- <button
104
- className="flex-grow flex items-center px-2 py-1 text-xs font-medium text-gray-700 rounded-md hover:bg-purple-50"
105
- onClick={(e) => {
106
- e.stopPropagation();
107
- toggleGroupCollapse(`nested-${nestedItemId}`);
108
- }}
109
- >
110
- <span className="truncate">{nestedItem.label}</span>
111
- </button>
112
- </div>
113
-
114
- <div
115
- className={`overflow-hidden transition-[height] duration-150 ease-out ${
116
- collapsedGroups[`nested-${nestedItemId}`] ? 'h-0' : 'h-auto'
117
- }`}
118
- >
119
- <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
120
- {nestedItem.items.map((deepNestedItem: SidebarItem, deepIndex: number) => {
121
- const deepNestedItemPath = deepNestedItem.slug ? buildUrl(`/docs/custom/${deepNestedItem.slug}`) : '#';
122
- const isDeepActive =
123
- currentPath === deepNestedItemPath || currentPath.endsWith(`/${deepNestedItem.slug}`);
124
-
125
- return (
126
- <a
127
- key={`deep-${nestedItemId}-${deepIndex}`}
128
- href={deepNestedItemPath}
129
- className={`flex items-center px-2 py-1.5 text-xs ${isDeepActive ? 'bg-purple-100 text-purple-900 font-medium' : 'text-gray-600 hover:bg-purple-100'} rounded-md`}
130
- data-active={isDeepActive}
131
- >
132
- <span className="truncate">{deepNestedItem.label}</span>
133
- </a>
134
- );
135
- })}
136
- </div>
137
- </div>
138
- </div>
139
- );
140
- }
141
-
142
- const nestedItemPath = nestedItem.slug ? buildUrl(`/docs/custom/${nestedItem.slug}`) : '#';
143
- const isActive = currentPath === nestedItemPath || currentPath.endsWith(`/${nestedItem.slug}`);
144
-
145
- return (
146
- <a
147
- key={`nested-link-${itemId}-${nestedIndex}`}
148
- href={nestedItemPath}
149
- className={`flex items-center px-2 py-1.5 text-xs ${isActive ? 'bg-purple-100 text-purple-900 font-medium' : 'text-gray-600 hover:bg-purple-100'} rounded-md`}
150
- data-active={isActive}
151
- >
152
- <span className="truncate">{nestedItem.label}</span>
153
- </a>
154
- );
155
- })}
75
+ {item.items.map((nestedItem: SidebarItem, nestedIndex: number) => (
76
+ <NestedItem
77
+ key={`nested-${itemId}-${nestedIndex}`}
78
+ item={nestedItem}
79
+ currentPath={currentPath}
80
+ parentId={itemId}
81
+ itemIndex={nestedIndex}
82
+ collapsedGroups={collapsedGroups}
83
+ toggleGroupCollapse={toggleGroupCollapse}
84
+ />
85
+ ))}
156
86
  </div>
157
87
  </div>
158
88
  </div>
@@ -7,7 +7,7 @@ import NoResultsFound from './components/NoResultsFound';
7
7
  const STORAGE_KEY = 'EventCatalog:customDocsSidebarCollapsedGroups';
8
8
  const DEBOUNCE_DELAY = 300; // 300ms debounce delay
9
9
 
10
- const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems, currentPath }) => {
10
+ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems }) => {
11
11
  const navRef = useRef<HTMLElement>(null);
12
12
  const [searchTerm, setSearchTerm] = useState('');
13
13
  const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
@@ -21,6 +21,8 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems, currentPath
21
21
  return {};
22
22
  });
23
23
 
24
+ const currentPath = window.location.pathname;
25
+
24
26
  // Set up debounced search
25
27
  useEffect(() => {
26
28
  const timer = setTimeout(() => {
@@ -128,29 +130,32 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems, currentPath
128
130
 
129
131
  const hasNoResults = debouncedSearchTerm && filteredSidebarItems.length === 0;
130
132
 
133
+ console.log('filteredSidebarItems', filteredSidebarItems);
134
+ console.log('currentPath', currentPath);
135
+
131
136
  return (
132
- <nav ref={navRef} className="h-full text-gray-800 pt-2">
133
- <div className="mb-2 px-4">
137
+ <nav ref={navRef} className="h-full text-gray-800 pt-4 overflow-y-auto">
138
+ <div className="mb-2 px-3 bg-white z-10">
134
139
  <input
135
140
  type="text"
136
141
  value={searchTerm}
137
142
  onChange={handleSearchChange}
138
143
  placeholder="Quick search..."
139
- className="w-full p-2 text-sm rounded-md border border-gray-200 h-[30px]"
144
+ className="w-full p-2 px-2 text-sm rounded-md border border-gray-200 h-[30px]"
140
145
  />
141
146
  </div>
142
147
 
143
- <div className="space-y-2 divide-y divide-gray-100/40">
148
+ <div className="space-y-2 divide-y divide-gray-100/40 pb-4">
144
149
  {hasNoResults ? (
145
150
  <NoResultsFound searchTerm={debouncedSearchTerm} />
146
151
  ) : (
147
152
  filteredSidebarItems.map((section: SidebarSection, index: number) => (
148
- <div className="pt-2 pb-2 px-4" key={`section-${index}`}>
153
+ <div className="pt-2 pb-2 px-3" key={`section-${index}`}>
149
154
  <div className="space-y-0" data-section={`section-${index}`}>
150
155
  {section.items ? (
151
156
  <div className="flex items-center">
152
157
  <button
153
- className="p-1 hover:bg-gray-100 rounded-md"
158
+ className="p-1 hover:bg-gray-100 rounded-md flex-shrink-0"
154
159
  onClick={(e) => {
155
160
  e.stopPropagation();
156
161
  toggleGroupCollapse(`section-${index}`);
@@ -160,23 +165,21 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems, currentPath
160
165
  className={`transition-transform duration-150 ${collapsedGroups[`section-${index}`] ? '' : 'rotate-180'}`}
161
166
  >
162
167
  <svg
163
- className="h-3 w-3 text-gray-500"
164
168
  xmlns="http://www.w3.org/2000/svg"
165
- width="16"
166
- height="16"
167
- viewBox="0 0 24 24"
168
169
  fill="none"
170
+ viewBox="0 0 24 24"
171
+ strokeWidth="1.5"
169
172
  stroke="currentColor"
170
- strokeWidth="2"
171
- strokeLinecap="round"
172
- strokeLinejoin="round"
173
+ aria-hidden="true"
174
+ data-slot="icon"
175
+ className="h-3 w-3 text-gray-500"
173
176
  >
174
- <polyline points="6 9 12 15 18 9" />
177
+ <path strokeLinecap="round" strokeLinejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"></path>
175
178
  </svg>
176
179
  </div>
177
180
  </button>
178
181
  <button
179
- className="flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md hover:bg-purple-50"
182
+ className="flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md hover:bg-purple-50 min-w-0 flex-1"
180
183
  onClick={(e) => {
181
184
  e.stopPropagation();
182
185
  toggleGroupCollapse(`section-${index}`);
@@ -15,6 +15,7 @@ export interface SidebarSection {
15
15
  slug?: string;
16
16
  autogenerated?: {
17
17
  directory: string;
18
+ collapsed?: boolean;
18
19
  };
19
20
  badge?: {
20
21
  text: string;
@@ -1,14 +1,17 @@
1
1
  ---
2
2
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
3
3
  import { render } from 'astro:content';
4
- import { buildUrl } from '@utils/url-builder';
5
4
  import config from '@config';
6
5
  import { AlignLeftIcon } from 'lucide-react';
6
+
7
7
  import mdxComponents from '@components/MDX/components';
8
8
  import OwnersList from '@components/Lists/OwnersList';
9
+
9
10
  import { getOwner } from '@utils/collections/owners';
10
- import CustomDocsNav from '@components/SideNav/CustomDocsNav.astro';
11
- import { getAdjacentPages } from '../utils/custom-docs';
11
+ import { buildUrl } from '@utils/url-builder';
12
+
13
+ import CustomDocsNav from '@enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro';
14
+ import { getAdjacentPages } from '@enterprise/custom-documentation/utils/custom-docs';
12
15
 
13
16
  const props = Astro.props;
14
17
  const doc = props.data;
@@ -72,14 +75,16 @@ const badges = doc?.badges || [];
72
75
  ---
73
76
 
74
77
  <VerticalSideBarLayout title={doc.title || 'Documentation'}>
75
- <div class="flex w-full">
78
+ <div class="flex w-full" data-pagefind-body data-pagefind-meta={`title:${doc.title}`}>
76
79
  <!-- Left Sidebar Navigation -->
77
80
  <aside class="sidebar-transition overflow-y-auto bg-white border-r border-gray-100 w-80 fixed top-16 bottom-0 z-10">
78
81
  <CustomDocsNav />
79
82
  </aside>
80
83
 
81
84
  <!-- Main Content Area - Independent scrolling -->
82
- <main class="sidebar-transition w-full max-h-content ml-[22em] 2xl:ml-[24em] mr-80 lg:mr-[20em] max-w-5xl mx-auto">
85
+ <main
86
+ class="sidebar-transition w-full max-h-content ml-[22em] md:ml-[21em] lg:mr-[21em] 2xl:mr-[26em] 2xl:ml-[22em] mr-80 max-w-5xl mx-auto"
87
+ >
83
88
  <div class="max-w-7xl mx-auto px-6 py-10">
84
89
  <div class="border-b border-gray-200 flex justify-between items-start md:pb-6">
85
90
  <div>
@@ -20,10 +20,11 @@ type SidebarItem = {
20
20
 
21
21
  type SideBarConfigurationItem = {
22
22
  label: string;
23
- items?: SidebarItem[];
23
+ items?: SideBarConfigurationItem[];
24
24
  slug?: string;
25
25
  autogenerated?: {
26
26
  directory: string;
27
+ collapsed?: boolean;
27
28
  };
28
29
  badge?: Badge;
29
30
  collapsed?: boolean;
@@ -78,6 +79,8 @@ const processAutoGeneratedDirectory = async (
78
79
 
79
80
  return {
80
81
  label,
82
+ badge,
83
+ collapsed,
81
84
  items: filteredEntries.map((entry) => ({
82
85
  label: entry?.data?.title,
83
86
  slug: entry?.data?.slug || entry?.id.replace(DOCS_DIR, ''),
@@ -98,13 +101,13 @@ const processSidebarItems = async (items: SideBarConfigurationItem[]): Promise<S
98
101
  item.autogenerated.directory,
99
102
  item.label,
100
103
  item.badge,
101
- item.collapsed
104
+ item.autogenerated.collapsed !== undefined ? item.autogenerated.collapsed : item.collapsed
102
105
  );
103
106
  processedItems.push(processedItem);
104
107
  }
105
108
  // If item has nested items, process them recursively
106
109
  else if (item.items && item.items.length > 0) {
107
- const processedNestedItems = await processSidebarItems(item.items as SideBarConfigurationItem[]);
110
+ const processedNestedItems = await processSidebarItems(item.items);
108
111
  processedItems.push({
109
112
  label: item.label,
110
113
  slug: item.slug,
@@ -1,6 +1,7 @@
1
1
  ---
2
- import CustomDocumentationPage from '@enterprise/custom-documentation/pages/index.astro';
2
+ import CustomDocumentationPage from '@enterprise/custom-documentation/pages/docs/custom/index.astro';
3
3
  import { getCollection } from 'astro:content';
4
+ import { buildUrl } from '@utils/url-builder';
4
5
  import type { GetStaticPaths } from 'astro';
5
6
  import { isEventCatalogProEnabled } from '@utils/feature';
6
7
  import path from 'node:path';
@@ -21,9 +22,8 @@ export const getStaticPaths = (async () => {
21
22
 
22
23
  const props = Astro.props;
23
24
 
24
- // Redirect
25
- if (!directoryExists || !isEventCatalogProEnabled()) {
26
- Astro.redirect('/docs/custom');
25
+ if (!isEventCatalogProEnabled()) {
26
+ return Astro.redirect('/docs/custom');
27
27
  }
28
28
  ---
29
29
 
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.31.4",
9
+ "version": "2.31.5",
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
@@ -1,11 +0,0 @@
1
- import CustomDocsNav from './';
2
- import type { SidebarSection } from './types';
3
-
4
- interface CustomDocsNavWrapperProps {
5
- sidebarItems: SidebarSection[];
6
- currentPath: string;
7
- }
8
-
9
- export default function CustomDocsNavWrapper(props: CustomDocsNavWrapperProps) {
10
- return <CustomDocsNav {...props} />;
11
- }
@@ -1,183 +0,0 @@
1
- import React from 'react';
2
- import { buildUrl } from '@utils/url-builder';
3
- import type { SidebarItem } from '../types';
4
-
5
- interface NestedItemProps {
6
- item: SidebarItem;
7
- currentPath: string;
8
- parentId: string;
9
- itemIndex: number;
10
- collapsedGroups: { [key: string]: boolean };
11
- toggleGroupCollapse: (group: string) => void;
12
- }
13
-
14
- const NestedItem: React.FC<NestedItemProps> = ({
15
- item,
16
- currentPath,
17
- parentId,
18
- itemIndex,
19
- collapsedGroups,
20
- toggleGroupCollapse,
21
- }) => {
22
- const hasNestedItems = item.items && item.items.length > 0;
23
- const itemId = `${parentId}-${itemIndex}`;
24
-
25
- if (hasNestedItems && item.items) {
26
- return (
27
- <div className="py-1">
28
- <div className="flex items-center">
29
- <button
30
- className="p-1 hover:bg-gray-100 rounded-md"
31
- onClick={(e) => {
32
- e.stopPropagation();
33
- toggleGroupCollapse(`nested-${itemId}`);
34
- }}
35
- >
36
- <div className={`transition-transform duration-150 ${collapsedGroups[`nested-${itemId}`] ? '' : 'rotate-180'}`}>
37
- <svg
38
- className="h-3 w-3 text-gray-500"
39
- xmlns="http://www.w3.org/2000/svg"
40
- width="16"
41
- height="16"
42
- viewBox="0 0 24 24"
43
- fill="none"
44
- stroke="currentColor"
45
- strokeWidth="2"
46
- strokeLinecap="round"
47
- strokeLinejoin="round"
48
- >
49
- <polyline points="6 9 12 15 18 9" />
50
- </svg>
51
- </div>
52
- </button>
53
- <button
54
- className="flex-grow flex items-center px-2 py-1 text-xs font-medium text-gray-700 rounded-md hover:bg-purple-50"
55
- onClick={(e) => {
56
- e.stopPropagation();
57
- toggleGroupCollapse(`nested-${itemId}`);
58
- }}
59
- >
60
- <span className="truncate">{item.label}</span>
61
- </button>
62
- </div>
63
-
64
- <div
65
- className={`overflow-hidden transition-[height] duration-150 ease-out ${
66
- collapsedGroups[`nested-${itemId}`] ? 'h-0' : 'h-auto'
67
- }`}
68
- >
69
- <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
70
- {item.items.map((nestedItem: SidebarItem, nestedIndex: number) => {
71
- if (nestedItem.items && nestedItem.items.length > 0) {
72
- // Recursively render deeper nested items
73
- const nestedItemId = `${itemId}-${nestedIndex}`;
74
- return (
75
- <div className="py-1" key={`nested-${nestedItemId}`}>
76
- <div className="flex items-center">
77
- <button
78
- className="p-1 hover:bg-gray-100 rounded-md"
79
- onClick={(e) => {
80
- e.stopPropagation();
81
- toggleGroupCollapse(`nested-${nestedItemId}`);
82
- }}
83
- >
84
- <div
85
- className={`transition-transform duration-150 ${collapsedGroups[`nested-${nestedItemId}`] ? '' : 'rotate-180'}`}
86
- >
87
- <svg
88
- className="h-3 w-3 text-gray-500"
89
- xmlns="http://www.w3.org/2000/svg"
90
- width="16"
91
- height="16"
92
- viewBox="0 0 24 24"
93
- fill="none"
94
- stroke="currentColor"
95
- strokeWidth="2"
96
- strokeLinecap="round"
97
- strokeLinejoin="round"
98
- >
99
- <polyline points="6 9 12 15 18 9" />
100
- </svg>
101
- </div>
102
- </button>
103
- <button
104
- className="flex-grow flex items-center px-2 py-1 text-xs font-medium text-gray-700 rounded-md hover:bg-purple-50"
105
- onClick={(e) => {
106
- e.stopPropagation();
107
- toggleGroupCollapse(`nested-${nestedItemId}`);
108
- }}
109
- >
110
- <span className="truncate">{nestedItem.label}</span>
111
- </button>
112
- </div>
113
-
114
- <div
115
- className={`overflow-hidden transition-[height] duration-150 ease-out ${
116
- collapsedGroups[`nested-${nestedItemId}`] ? 'h-0' : 'h-auto'
117
- }`}
118
- >
119
- <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
120
- {nestedItem.items.map((deepNestedItem: SidebarItem, deepIndex: number) => {
121
- const deepNestedItemPath = deepNestedItem.slug ? buildUrl(`/docs/custom/${deepNestedItem.slug}`) : '#';
122
- const isDeepActive =
123
- currentPath === deepNestedItemPath || currentPath.endsWith(`/${deepNestedItem.slug}`);
124
-
125
- return (
126
- <a
127
- key={`deep-${nestedItemId}-${deepIndex}`}
128
- href={deepNestedItemPath}
129
- className={`flex items-center px-2 py-1.5 text-xs ${isDeepActive ? 'bg-purple-100 text-purple-900 font-medium' : 'text-gray-600 hover:bg-purple-100'} rounded-md`}
130
- data-active={isDeepActive}
131
- >
132
- <span className="truncate">{deepNestedItem.label}</span>
133
- </a>
134
- );
135
- })}
136
- </div>
137
- </div>
138
- </div>
139
- );
140
- }
141
-
142
- const nestedItemPath = nestedItem.slug ? buildUrl(`/docs/custom/${nestedItem.slug}`) : '#';
143
- const isActive = currentPath === nestedItemPath || currentPath.endsWith(`/${nestedItem.slug}`);
144
-
145
- return (
146
- <a
147
- key={`nested-link-${itemId}-${nestedIndex}`}
148
- href={nestedItemPath}
149
- className={`flex items-center px-2 py-1.5 text-xs ${isActive ? 'bg-purple-100 text-purple-900 font-medium' : 'text-gray-600 hover:bg-purple-100'} rounded-md`}
150
- data-active={isActive}
151
- >
152
- <span className="truncate">{nestedItem.label}</span>
153
- </a>
154
- );
155
- })}
156
- </div>
157
- </div>
158
- </div>
159
- );
160
- }
161
-
162
- const itemPath = item.slug ? buildUrl(`/docs/custom/${item.slug}`) : '#';
163
- const isActive = currentPath === itemPath || currentPath.endsWith(`/${item.slug}`);
164
-
165
- return (
166
- <a
167
- href={itemPath}
168
- className={`flex items-center px-2 py-1.5 text-xs ${isActive ? 'bg-purple-100 text-purple-900 font-medium' : 'text-gray-600 hover:bg-purple-100'} rounded-md`}
169
- data-active={isActive}
170
- >
171
- <span className="truncate">{item.label}</span>
172
- {item.badge && item?.badge?.text && (
173
- <span
174
- className={`text-${item.badge.color || 'purple'}-600 ml-2 text-[10px] font-medium bg-${item.badge.color || 'purple'}-50 px-2 py-0.5 rounded uppercase`}
175
- >
176
- {item.badge.text}
177
- </span>
178
- )}
179
- </a>
180
- );
181
- };
182
-
183
- export default React.memo(NestedItem);
@@ -1,21 +0,0 @@
1
- import React from 'react';
2
-
3
- interface NoResultsFoundProps {
4
- searchTerm: string;
5
- }
6
-
7
- const NoResultsFound: React.FC<NoResultsFoundProps> = ({ searchTerm }) => (
8
- <div className="px-4 py-6 text-center">
9
- <div className="text-gray-400 text-sm mb-2">No results found for "{searchTerm}"</div>
10
- <div className="text-gray-400 text-xs">
11
- Try:
12
- <ul className="mt-2 space-y-1 text-left list-disc pl-4">
13
- <li>Checking for typos</li>
14
- <li>Using fewer keywords</li>
15
- <li>Using more general terms</li>
16
- </ul>
17
- </div>
18
- </div>
19
- );
20
-
21
- export default React.memo(NoResultsFound);
@@ -1,250 +0,0 @@
1
- import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
2
- import { buildUrl } from '@utils/url-builder';
3
- import type { CustomDocsNavProps, SidebarSection, SidebarItem } from './types';
4
- import NestedItem from './components/NestedItem';
5
- import NoResultsFound from './components/NoResultsFound';
6
-
7
- const STORAGE_KEY = 'EventCatalog:customDocsSidebarCollapsedGroups';
8
- const DEBOUNCE_DELAY = 300; // 300ms debounce delay
9
-
10
- const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems, currentPath }) => {
11
- const navRef = useRef<HTMLElement>(null);
12
- const [searchTerm, setSearchTerm] = useState('');
13
- const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
14
- const [isInitialized, setIsInitialized] = useState(false);
15
- const [collapsedGroups, setCollapsedGroups] = useState<{ [key: string]: boolean }>(() => {
16
- if (typeof window !== 'undefined') {
17
- const saved = window.localStorage.getItem(STORAGE_KEY);
18
- setIsInitialized(true);
19
- return saved ? JSON.parse(saved) : {};
20
- }
21
- return {};
22
- });
23
-
24
- // Set up debounced search
25
- useEffect(() => {
26
- const timer = setTimeout(() => {
27
- setDebouncedSearchTerm(searchTerm.toLowerCase());
28
- }, DEBOUNCE_DELAY);
29
-
30
- return () => clearTimeout(timer);
31
- }, [searchTerm]);
32
-
33
- // Filter sidebar items based on search term
34
- const filteredSidebarItems = useMemo(() => {
35
- if (!debouncedSearchTerm) return sidebarItems;
36
-
37
- const matchesSearchTerm = (text: string) => text.toLowerCase().includes(debouncedSearchTerm);
38
-
39
- // Helper function to check if an item or any of its nested items match the search term
40
- const itemContainsSearchTerm = (item: SidebarItem): boolean => {
41
- if (matchesSearchTerm(item.label)) return true;
42
-
43
- if (item.items && item.items.length > 0) {
44
- return item.items.some(itemContainsSearchTerm);
45
- }
46
-
47
- return false;
48
- };
49
-
50
- return sidebarItems
51
- .map((section) => {
52
- if (!section.items) {
53
- return matchesSearchTerm(section.label) ? section : null;
54
- }
55
-
56
- const filteredItems = section.items.filter(itemContainsSearchTerm);
57
-
58
- if (filteredItems.length > 0 || matchesSearchTerm(section.label)) {
59
- return {
60
- ...section,
61
- items: filteredItems,
62
- };
63
- }
64
-
65
- return null;
66
- })
67
- .filter(Boolean) as SidebarSection[];
68
- }, [sidebarItems, debouncedSearchTerm]);
69
-
70
- // Auto-expand groups when searching
71
- useEffect(() => {
72
- if (debouncedSearchTerm) {
73
- // Expand all groups when searching
74
- const newCollapsedState = { ...collapsedGroups };
75
- Object.keys(newCollapsedState).forEach((key) => {
76
- newCollapsedState[key] = false;
77
- });
78
- setCollapsedGroups(newCollapsedState);
79
- }
80
- }, [debouncedSearchTerm]);
81
-
82
- // Store collapsed groups in local storage
83
- useEffect(() => {
84
- if (typeof window !== 'undefined' && isInitialized) {
85
- window.localStorage.setItem(STORAGE_KEY, JSON.stringify(collapsedGroups));
86
- }
87
- }, [collapsedGroups, isInitialized]);
88
-
89
- // Initialize collapsed state from section config
90
- useEffect(() => {
91
- if (isInitialized && sidebarItems && sidebarItems.length > 0) {
92
- const initialState = { ...collapsedGroups };
93
-
94
- sidebarItems.forEach((section, index) => {
95
- const sectionKey = `section-${index}`;
96
- if (section.collapsed !== undefined && initialState[sectionKey] === undefined) {
97
- initialState[sectionKey] = section.collapsed;
98
- }
99
- });
100
-
101
- setCollapsedGroups(initialState);
102
- }
103
- }, [sidebarItems, isInitialized]);
104
-
105
- // If we find a data-active element, scroll to it on mount
106
- useEffect(() => {
107
- const activeElement = document.querySelector('[data-active="true"]');
108
- if (activeElement) {
109
- // Add y offset to the scroll position
110
- setTimeout(() => {
111
- activeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
112
- }, 300);
113
- }
114
- }, []);
115
-
116
- const toggleGroupCollapse = useCallback((group: string) => {
117
- setCollapsedGroups((prev) => ({
118
- ...prev,
119
- [group]: !prev[group],
120
- }));
121
- }, []);
122
-
123
- const handleSearchChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
124
- setSearchTerm(e.target.value);
125
- }, []);
126
-
127
- if (!isInitialized) return null;
128
-
129
- const hasNoResults = debouncedSearchTerm && filteredSidebarItems.length === 0;
130
-
131
- return (
132
- <nav ref={navRef} className="h-full text-gray-800 pt-2">
133
- <div className="mb-2 px-4">
134
- <input
135
- type="text"
136
- value={searchTerm}
137
- onChange={handleSearchChange}
138
- placeholder="Quick search..."
139
- className="w-full p-2 text-sm rounded-md border border-gray-200 h-[30px]"
140
- />
141
- </div>
142
-
143
- <div className="space-y-2 divide-y divide-gray-100/40">
144
- {hasNoResults ? (
145
- <NoResultsFound searchTerm={debouncedSearchTerm} />
146
- ) : (
147
- filteredSidebarItems.map((section: SidebarSection, index: number) => (
148
- <div className="pt-2 pb-2 px-4" key={`section-${index}`}>
149
- <div className="space-y-0" data-section={`section-${index}`}>
150
- {section.items ? (
151
- <div className="flex items-center">
152
- <button
153
- className="p-1 hover:bg-gray-100 rounded-md"
154
- onClick={(e) => {
155
- e.stopPropagation();
156
- toggleGroupCollapse(`section-${index}`);
157
- }}
158
- >
159
- <div
160
- className={`transition-transform duration-150 ${collapsedGroups[`section-${index}`] ? '' : 'rotate-180'}`}
161
- >
162
- <svg
163
- className="h-3 w-3 text-gray-500"
164
- xmlns="http://www.w3.org/2000/svg"
165
- width="16"
166
- height="16"
167
- viewBox="0 0 24 24"
168
- fill="none"
169
- stroke="currentColor"
170
- strokeWidth="2"
171
- strokeLinecap="round"
172
- strokeLinejoin="round"
173
- >
174
- <polyline points="6 9 12 15 18 9" />
175
- </svg>
176
- </div>
177
- </button>
178
- <button
179
- className="flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md hover:bg-purple-50"
180
- onClick={(e) => {
181
- e.stopPropagation();
182
- toggleGroupCollapse(`section-${index}`);
183
- }}
184
- >
185
- <span className="truncate">{section.label}</span>
186
- {section.badge && section?.badge?.text && (
187
- <span
188
- className={`text-${section.badge.color || 'purple'}-600 ml-2 text-[10px] font-medium bg-${section.badge.color || 'purple'}-50 px-2 py-0.5 rounded uppercase`}
189
- >
190
- {section.badge.text}
191
- </span>
192
- )}
193
- </button>
194
- </div>
195
- ) : (
196
- <div className="flex items-center">
197
- <span className="flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md">
198
- <span className="truncate">{section.label}</span>
199
- <span className="text-purple-600 ml-2 text-[10px] font-medium bg-purple-50 px-2 py-0.5 rounded uppercase">
200
- Section
201
- </span>
202
- </span>
203
- </div>
204
- )}
205
-
206
- {section.items && (
207
- <div
208
- className={`overflow-hidden transition-[height] duration-150 ease-out ${
209
- collapsedGroups[`section-${index}`] ? 'h-0' : 'h-auto'
210
- }`}
211
- >
212
- <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
213
- {section.items.map((item: SidebarItem, itemIndex: number) => (
214
- <NestedItem
215
- key={`item-${index}-${itemIndex}`}
216
- item={item}
217
- currentPath={currentPath}
218
- parentId={`${index}`}
219
- itemIndex={itemIndex}
220
- collapsedGroups={collapsedGroups}
221
- toggleGroupCollapse={toggleGroupCollapse}
222
- />
223
- ))}
224
- </div>
225
- </div>
226
- )}
227
-
228
- {section.slug && !section.items && (
229
- <a
230
- href={buildUrl(`/docs/custom/${section.slug}`)}
231
- className={`flex items-center px-2 py-1.5 text-xs ${
232
- currentPath.endsWith(`/${section.slug}`)
233
- ? 'bg-purple-100 text-purple-900 font-medium'
234
- : 'text-gray-600 hover:bg-purple-100'
235
- } rounded-md ml-6`}
236
- data-active={currentPath.endsWith(`/${section.slug}`)}
237
- >
238
- <span className="truncate">{section.label}</span>
239
- </a>
240
- )}
241
- </div>
242
- </div>
243
- ))
244
- )}
245
- </div>
246
- </nav>
247
- );
248
- };
249
-
250
- export default React.memo(CustomDocsNav);
@@ -1,29 +0,0 @@
1
- export interface SidebarItem {
2
- label: string;
3
- slug?: string;
4
- items?: SidebarItem[];
5
- badge?: {
6
- text: string;
7
- color: string;
8
- };
9
- collapsed?: boolean;
10
- }
11
-
12
- export interface SidebarSection {
13
- label: string;
14
- items?: SidebarItem[];
15
- slug?: string;
16
- autogenerated?: {
17
- directory: string;
18
- };
19
- badge?: {
20
- text: string;
21
- color: string;
22
- };
23
- collapsed?: boolean;
24
- }
25
-
26
- export interface CustomDocsNavProps {
27
- sidebarItems: SidebarSection[];
28
- currentPath: string;
29
- }