specra 0.1.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 (142) hide show
  1. package/LICENSE.MD +21 -0
  2. package/README.md +157 -0
  3. package/dist/app/api/mdx-watch/route.d.mts +12 -0
  4. package/dist/app/api/mdx-watch/route.d.ts +12 -0
  5. package/dist/app/api/mdx-watch/route.js +98 -0
  6. package/dist/app/api/mdx-watch/route.js.map +1 -0
  7. package/dist/app/api/mdx-watch/route.mjs +71 -0
  8. package/dist/app/api/mdx-watch/route.mjs.map +1 -0
  9. package/dist/app/docs-page.d.mts +32 -0
  10. package/dist/app/docs-page.d.ts +32 -0
  11. package/dist/app/docs-page.js +4072 -0
  12. package/dist/app/docs-page.js.map +1 -0
  13. package/dist/app/docs-page.mjs +14 -0
  14. package/dist/app/docs-page.mjs.map +1 -0
  15. package/dist/app/layout.css +297 -0
  16. package/dist/app/layout.css.map +1 -0
  17. package/dist/app/layout.d.mts +19 -0
  18. package/dist/app/layout.d.ts +19 -0
  19. package/dist/app/layout.js +112 -0
  20. package/dist/app/layout.js.map +1 -0
  21. package/dist/app/layout.mjs +13 -0
  22. package/dist/app/layout.mjs.map +1 -0
  23. package/dist/chunk-DR4EPLMT.mjs +1013 -0
  24. package/dist/chunk-DR4EPLMT.mjs.map +1 -0
  25. package/dist/chunk-INL2EC72.mjs +170 -0
  26. package/dist/chunk-INL2EC72.mjs.map +1 -0
  27. package/dist/chunk-IZFGEAD6.mjs +61 -0
  28. package/dist/chunk-IZFGEAD6.mjs.map +1 -0
  29. package/dist/chunk-KTRWWAGL.mjs +50 -0
  30. package/dist/chunk-KTRWWAGL.mjs.map +1 -0
  31. package/dist/chunk-MZJHJ6BV.mjs +21 -0
  32. package/dist/chunk-MZJHJ6BV.mjs.map +1 -0
  33. package/dist/chunk-NXRIAL7T.mjs +3119 -0
  34. package/dist/chunk-NXRIAL7T.mjs.map +1 -0
  35. package/dist/components/index.d.mts +822 -0
  36. package/dist/components/index.d.ts +822 -0
  37. package/dist/components/index.js +3738 -0
  38. package/dist/components/index.js.map +1 -0
  39. package/dist/components/index.mjs +3627 -0
  40. package/dist/components/index.mjs.map +1 -0
  41. package/dist/index.css +297 -0
  42. package/dist/index.css.map +1 -0
  43. package/dist/index.d.mts +545 -0
  44. package/dist/index.d.ts +545 -0
  45. package/dist/index.js +4648 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/index.mjs +347 -0
  48. package/dist/index.mjs.map +1 -0
  49. package/dist/lib/index.d.mts +798 -0
  50. package/dist/lib/index.d.ts +798 -0
  51. package/dist/lib/index.js +1301 -0
  52. package/dist/lib/index.js.map +1 -0
  53. package/dist/lib/index.mjs +89 -0
  54. package/dist/lib/index.mjs.map +1 -0
  55. package/package.json +119 -0
  56. package/src/app/api/mdx-watch/route.ts +86 -0
  57. package/src/app/docs-page.tsx +212 -0
  58. package/src/app/layout.tsx +74 -0
  59. package/src/components/docs/accordion.tsx +53 -0
  60. package/src/components/docs/api/api-endpoint.tsx +59 -0
  61. package/src/components/docs/api/api-params.tsx +43 -0
  62. package/src/components/docs/api/api-playground.tsx +233 -0
  63. package/src/components/docs/api/api-reference.tsx +291 -0
  64. package/src/components/docs/api/api-response.tsx +48 -0
  65. package/src/components/docs/api/index.ts +5 -0
  66. package/src/components/docs/badge.tsx +22 -0
  67. package/src/components/docs/breadcrumb.tsx +51 -0
  68. package/src/components/docs/callout.tsx +109 -0
  69. package/src/components/docs/card.tsx +84 -0
  70. package/src/components/docs/category-index.tsx +112 -0
  71. package/src/components/docs/code-block.tsx +129 -0
  72. package/src/components/docs/columns.tsx +45 -0
  73. package/src/components/docs/componentTextProps.ts +85 -0
  74. package/src/components/docs/dev-mode-badge.tsx +35 -0
  75. package/src/components/docs/doc-layout-wrapper.tsx +54 -0
  76. package/src/components/docs/doc-layout.tsx +111 -0
  77. package/src/components/docs/doc-loading.tsx +15 -0
  78. package/src/components/docs/doc-metadata.tsx +55 -0
  79. package/src/components/docs/doc-navigation.tsx +62 -0
  80. package/src/components/docs/doc-tags.tsx +25 -0
  81. package/src/components/docs/draft-badge.tsx +10 -0
  82. package/src/components/docs/footer.tsx +47 -0
  83. package/src/components/docs/frame.tsx +22 -0
  84. package/src/components/docs/header.tsx +122 -0
  85. package/src/components/docs/hot-reload-indicator.tsx +77 -0
  86. package/src/components/docs/icon.tsx +70 -0
  87. package/src/components/docs/image-card.tsx +95 -0
  88. package/src/components/docs/image.tsx +73 -0
  89. package/src/components/docs/index.ts +48 -0
  90. package/src/components/docs/math.tsx +46 -0
  91. package/src/components/docs/mdx-components.tsx +166 -0
  92. package/src/components/docs/mdx-hot-reload.tsx +37 -0
  93. package/src/components/docs/mermaid.tsx +77 -0
  94. package/src/components/docs/mobile-doc-layout.tsx +115 -0
  95. package/src/components/docs/not-found-content.tsx +55 -0
  96. package/src/components/docs/search-highlight.tsx +127 -0
  97. package/src/components/docs/search-modal.tsx +223 -0
  98. package/src/components/docs/sidebar-skeleton.tsx +39 -0
  99. package/src/components/docs/sidebar.tsx +323 -0
  100. package/src/components/docs/site-banner.tsx +92 -0
  101. package/src/components/docs/steps.tsx +29 -0
  102. package/src/components/docs/tab-context.tsx +28 -0
  103. package/src/components/docs/tab-groups.tsx +50 -0
  104. package/src/components/docs/table-of-contents.tsx +104 -0
  105. package/src/components/docs/tabs.tsx +63 -0
  106. package/src/components/docs/theme-toggle.tsx +39 -0
  107. package/src/components/docs/tooltip.tsx +37 -0
  108. package/src/components/docs/version-switcher.tsx +52 -0
  109. package/src/components/docs/video.tsx +80 -0
  110. package/src/components/global/index.ts +3 -0
  111. package/src/components/global/version-not-found.tsx +26 -0
  112. package/src/components/index.ts +8 -0
  113. package/src/components/theme-provider.tsx +11 -0
  114. package/src/components/ui/badge.tsx +46 -0
  115. package/src/components/ui/button.tsx +60 -0
  116. package/src/components/ui/dialog.tsx +143 -0
  117. package/src/components/ui/index.ts +6 -0
  118. package/src/components/ui/input.tsx +21 -0
  119. package/src/components/ui/textarea.tsx +18 -0
  120. package/src/index.ts +41 -0
  121. package/src/lib/api-parser.types.ts +78 -0
  122. package/src/lib/api.types.ts +202 -0
  123. package/src/lib/category.ts +71 -0
  124. package/src/lib/config.server.ts +170 -0
  125. package/src/lib/config.ts +20 -0
  126. package/src/lib/config.types.ts +295 -0
  127. package/src/lib/dev-utils.ts +75 -0
  128. package/src/lib/index.ts +27 -0
  129. package/src/lib/mdx-cache.ts +200 -0
  130. package/src/lib/mdx.ts +402 -0
  131. package/src/lib/parsers/base-parser.ts +16 -0
  132. package/src/lib/parsers/index.ts +69 -0
  133. package/src/lib/parsers/openapi-parser.ts +251 -0
  134. package/src/lib/parsers/postman-parser.ts +301 -0
  135. package/src/lib/parsers/specra-parser.ts +24 -0
  136. package/src/lib/redirects.ts +40 -0
  137. package/src/lib/remark-code-meta.ts +23 -0
  138. package/src/lib/sidebar-utils.ts +188 -0
  139. package/src/lib/toc.ts +24 -0
  140. package/src/lib/utils.ts +36 -0
  141. package/src/specra.config.json +124 -0
  142. package/src/styles/globals.css +427 -0
package/dist/index.js ADDED
@@ -0,0 +1,4648 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Accordion: () => Accordion,
34
+ AccordionItem: () => AccordionItem,
35
+ ApiEndpoint: () => ApiEndpoint,
36
+ ApiParams: () => ApiParams,
37
+ ApiPlayground: () => ApiPlayground,
38
+ ApiReference: () => ApiReference,
39
+ ApiResponse: () => ApiResponse,
40
+ ApiResponseDisplay: () => ApiResponse,
41
+ Badge: () => Badge2,
42
+ Breadcrumb: () => Breadcrumb,
43
+ Button: () => Button,
44
+ COMPONENT_TEXT_PROPS: () => COMPONENT_TEXT_PROPS,
45
+ Callout: () => Callout,
46
+ Card: () => Card,
47
+ CardGrid: () => CardGrid,
48
+ CategoryIndex: () => CategoryIndex,
49
+ CodeBlock: () => CodeBlock,
50
+ Column: () => Column,
51
+ Columns: () => Columns,
52
+ DevModeBadge: () => DevModeBadge,
53
+ Dialog: () => Dialog,
54
+ DialogClose: () => DialogClose,
55
+ DialogContent: () => DialogContent,
56
+ DialogDescription: () => DialogDescription,
57
+ DialogFooter: () => DialogFooter,
58
+ DialogHeader: () => DialogHeader,
59
+ DialogOverlay: () => DialogOverlay,
60
+ DialogPortal: () => DialogPortal,
61
+ DialogTitle: () => DialogTitle,
62
+ DialogTrigger: () => DialogTrigger,
63
+ DocBadge: () => Badge,
64
+ DocLayout: () => DocLayout,
65
+ DocLayoutWrapper: () => DocLayoutWrapper,
66
+ DocLoading: () => DocLoading,
67
+ DocMetadata: () => DocMetadata,
68
+ DocNavigation: () => DocNavigation,
69
+ DocTags: () => DocTags,
70
+ DocsPage: () => DocPage,
71
+ DraftBadge: () => DraftBadge,
72
+ Footer: () => Footer,
73
+ Frame: () => Frame,
74
+ Header: () => Header,
75
+ HotReloadIndicator: () => HotReloadIndicator,
76
+ Icon: () => Icon,
77
+ Image: () => Image,
78
+ ImageCard: () => ImageCard,
79
+ ImageCardGrid: () => ImageCardGrid,
80
+ Input: () => Input,
81
+ Math: () => Math2,
82
+ MdxHotReload: () => MdxHotReload,
83
+ Mermaid: () => Mermaid,
84
+ MobileDocLayout: () => MobileDocLayout,
85
+ NotFoundContent: () => NotFoundContent,
86
+ OpenApiParser: () => OpenApiParser,
87
+ PerfTimer: () => PerfTimer,
88
+ PostmanParser: () => PostmanParser,
89
+ RootLayout: () => RootLayout,
90
+ SearchHighlight: () => SearchHighlight,
91
+ SearchModal: () => SearchModal,
92
+ Sidebar: () => Sidebar,
93
+ SidebarSkeleton: () => SidebarSkeleton,
94
+ SiteBanner: () => SiteBanner,
95
+ SpecraParser: () => SpecraParser,
96
+ Step: () => Step,
97
+ Steps: () => Steps,
98
+ Tab: () => Tab,
99
+ TabGroups: () => TabGroups,
100
+ TabProvider: () => TabProvider,
101
+ TableOfContents: () => TableOfContents,
102
+ Tabs: () => Tabs,
103
+ Textarea: () => Textarea,
104
+ ThemeToggle: () => ThemeToggle,
105
+ Tooltip: () => Tooltip,
106
+ VersionNotFound: () => VersionNotFound,
107
+ VersionSwitcher: () => VersionSwitcher,
108
+ Video: () => Video,
109
+ badgeVariants: () => badgeVariants,
110
+ buildRedirectMappings: () => buildRedirectMappings,
111
+ buildSidebarStructure: () => buildSidebarStructure,
112
+ buttonVariants: () => buttonVariants,
113
+ clearAllCaches: () => clearAllCaches,
114
+ cn: () => cn,
115
+ debugLog: () => debugLog,
116
+ defaultConfig: () => defaultConfig,
117
+ detectParserType: () => detectParserType,
118
+ extractComponentPropsText: () => extractComponentPropsText,
119
+ extractHeadings: () => extractHeadings,
120
+ extractSearchText: () => extractSearchText,
121
+ extractTableOfContents: () => extractTableOfContents,
122
+ findRedirect: () => findRedirect,
123
+ generateDocsMetadata: () => generateMetadata2,
124
+ generateDocsStaticParams: () => generateStaticParams,
125
+ generateRootMetadata: () => generateMetadata,
126
+ getAdjacentDocs: () => getAdjacentDocs,
127
+ getAllCategoryConfigs: () => getAllCategoryConfigs,
128
+ getAllDocs: () => getAllDocs,
129
+ getAssetPath: () => getAssetPath,
130
+ getCacheStats: () => getCacheStats,
131
+ getCachedAllDocs: () => getCachedAllDocs,
132
+ getCachedDocBySlug: () => getCachedDocBySlug,
133
+ getCachedVersions: () => getCachedVersions,
134
+ getCategoryConfig: () => getCategoryConfig,
135
+ getConfig: () => getConfig,
136
+ getConfigValue: () => getConfigValue,
137
+ getDocBySlug: () => getDocBySlug,
138
+ getVersions: () => getVersions,
139
+ initConfig: () => initConfig,
140
+ isCategoryPage: () => isCategoryPage,
141
+ loadConfig: () => loadConfig,
142
+ logCacheOperation: () => logCacheOperation,
143
+ logFsOperation: () => logFsOperation,
144
+ logMemoryUsage: () => logMemoryUsage,
145
+ mdxComponents: () => mdxComponents,
146
+ parseApiSpec: () => parseApiSpec,
147
+ processContentWithEnv: () => processContentWithEnv,
148
+ reloadConfig: () => reloadConfig,
149
+ replaceEnvVariables: () => replaceEnvVariables,
150
+ sortSidebarGroups: () => sortSidebarGroups,
151
+ sortSidebarItems: () => sortSidebarItems,
152
+ useTabContext: () => useTabContext,
153
+ validateConfig: () => validateConfig
154
+ });
155
+ module.exports = __toCommonJS(src_exports);
156
+
157
+ // src/lib/mdx.ts
158
+ var import_fs2 = __toESM(require("fs"));
159
+ var import_path2 = __toESM(require("path"));
160
+ var import_gray_matter = __toESM(require("gray-matter"));
161
+
162
+ // src/lib/category.ts
163
+ var import_fs = __toESM(require("fs"));
164
+ var import_path = __toESM(require("path"));
165
+ var DOCS_DIR = import_path.default.join(process.cwd(), "docs");
166
+ function getCategoryConfig(folderPath) {
167
+ try {
168
+ const categoryPath = import_path.default.join(folderPath, "_category_.json");
169
+ if (!import_fs.default.existsSync(categoryPath)) {
170
+ return null;
171
+ }
172
+ const content = import_fs.default.readFileSync(categoryPath, "utf8");
173
+ return JSON.parse(content);
174
+ } catch (error) {
175
+ console.error(`Error reading category config from ${folderPath}:`, error);
176
+ return null;
177
+ }
178
+ }
179
+ function getAllCategoryConfigs(version) {
180
+ const configs = /* @__PURE__ */ new Map();
181
+ const versionDir = import_path.default.join(DOCS_DIR, version);
182
+ if (!import_fs.default.existsSync(versionDir)) {
183
+ return configs;
184
+ }
185
+ function scanDirectory(dir, relativePath = "") {
186
+ const entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
187
+ for (const entry of entries) {
188
+ if (entry.isDirectory()) {
189
+ const fullPath = import_path.default.join(dir, entry.name);
190
+ const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
191
+ const config = getCategoryConfig(fullPath);
192
+ if (config) {
193
+ configs.set(relPath, config);
194
+ }
195
+ scanDirectory(fullPath, relPath);
196
+ }
197
+ }
198
+ }
199
+ scanDirectory(versionDir);
200
+ return configs;
201
+ }
202
+
203
+ // src/lib/sidebar-utils.ts
204
+ function sortSidebarItems(items) {
205
+ return [...items].sort((a, b) => {
206
+ const posA = a.sidebar_position ?? a.meta?.sidebar_position ?? a.meta?.order ?? 999;
207
+ const posB = b.sidebar_position ?? b.meta?.sidebar_position ?? b.meta?.order ?? 999;
208
+ return posA - posB;
209
+ });
210
+ }
211
+ function sortSidebarGroups(groups) {
212
+ return Object.entries(groups).sort(([, a], [, b]) => {
213
+ const posA = a.position ?? 999;
214
+ const posB = b.position ?? 999;
215
+ return posA - posB;
216
+ });
217
+ }
218
+ function buildSidebarStructure(docs) {
219
+ const rootGroups = {};
220
+ const standalone = [];
221
+ const categoryMetadata = /* @__PURE__ */ new Map();
222
+ docs.forEach((doc) => {
223
+ const pathParts = doc.filePath.split("/");
224
+ const folderPath = pathParts.length > 1 ? pathParts.slice(0, -1).join("/") : "";
225
+ if (folderPath && doc.categoryLabel) {
226
+ categoryMetadata.set(folderPath, {
227
+ label: doc.categoryLabel,
228
+ position: doc.categoryPosition,
229
+ icon: doc.categoryIcon,
230
+ collapsible: doc.categoryCollapsible,
231
+ collapsed: doc.categoryCollapsed
232
+ });
233
+ }
234
+ });
235
+ docs.forEach((doc) => {
236
+ const pathParts = doc.filePath.split("/");
237
+ const isIndexFile = doc.filePath.endsWith("/index") || doc.filePath === "index" || pathParts.length > 1 && doc.slug === pathParts.slice(0, -1).join("/");
238
+ const customGroup = doc.meta.sidebar || doc.meta.group;
239
+ if (customGroup) {
240
+ const groupName = customGroup.charAt(0).toUpperCase() + customGroup.slice(1);
241
+ if (!rootGroups[groupName]) {
242
+ rootGroups[groupName] = {
243
+ label: groupName,
244
+ path: customGroup,
245
+ items: [],
246
+ position: 999,
247
+ collapsible: doc.categoryCollapsible ?? true,
248
+ defaultCollapsed: doc.categoryCollapsed ?? false,
249
+ children: {}
250
+ };
251
+ }
252
+ if (isIndexFile) {
253
+ rootGroups[groupName].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? 999;
254
+ rootGroups[groupName].icon = doc.categoryIcon;
255
+ } else {
256
+ rootGroups[groupName].items.push(doc);
257
+ }
258
+ return;
259
+ }
260
+ if (pathParts.length > 1) {
261
+ const folderParts = pathParts.slice(0, -1);
262
+ let currentLevel = rootGroups;
263
+ let currentPath = "";
264
+ for (let i = 0; i < folderParts.length; i++) {
265
+ const folder = folderParts[i];
266
+ currentPath = currentPath ? `${currentPath}/${folder}` : folder;
267
+ const folderLabel = folder.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
268
+ const metadata2 = categoryMetadata.get(currentPath);
269
+ if (!currentLevel[folder]) {
270
+ currentLevel[folder] = {
271
+ label: metadata2?.label ?? folderLabel,
272
+ path: currentPath,
273
+ icon: metadata2?.icon,
274
+ items: [],
275
+ position: metadata2?.position ?? 999,
276
+ collapsible: metadata2?.collapsible ?? true,
277
+ defaultCollapsed: metadata2?.collapsed ?? false,
278
+ children: {}
279
+ };
280
+ }
281
+ if (i === folderParts.length - 1) {
282
+ if (isIndexFile) {
283
+ currentLevel[folder].position = doc.categoryPosition ?? doc.meta.sidebar_position ?? currentLevel[folder].position;
284
+ if (doc.categoryLabel) {
285
+ currentLevel[folder].label = doc.categoryLabel;
286
+ }
287
+ if (doc.categoryIcon) {
288
+ currentLevel[folder].icon = doc.categoryIcon;
289
+ }
290
+ if (doc.categoryCollapsible !== void 0) {
291
+ currentLevel[folder].collapsible = doc.categoryCollapsible;
292
+ }
293
+ if (doc.categoryCollapsed !== void 0) {
294
+ currentLevel[folder].defaultCollapsed = doc.categoryCollapsed;
295
+ }
296
+ } else {
297
+ currentLevel[folder].items.push(doc);
298
+ }
299
+ }
300
+ currentLevel = currentLevel[folder].children;
301
+ }
302
+ } else {
303
+ if (!isIndexFile) {
304
+ standalone.push(doc);
305
+ }
306
+ }
307
+ });
308
+ return { rootGroups, standalone };
309
+ }
310
+
311
+ // src/lib/mdx.ts
312
+ var DOCS_DIR2 = import_path2.default.join(process.cwd(), "docs");
313
+ function calculateReadingTime(content) {
314
+ const words = content.trim().split(/\s+/).length;
315
+ const minutes = Math.ceil(words / 200);
316
+ return { minutes, words };
317
+ }
318
+ function getVersions() {
319
+ try {
320
+ const versions = import_fs2.default.readdirSync(DOCS_DIR2);
321
+ return versions.filter((v) => import_fs2.default.statSync(import_path2.default.join(DOCS_DIR2, v)).isDirectory());
322
+ } catch (error) {
323
+ return ["v1.0.0"];
324
+ }
325
+ }
326
+ function findMdxFiles(dir, baseDir = dir) {
327
+ const files = [];
328
+ try {
329
+ const entries = import_fs2.default.readdirSync(dir, { withFileTypes: true });
330
+ for (const entry of entries) {
331
+ const fullPath = import_path2.default.join(dir, entry.name);
332
+ if (entry.isDirectory()) {
333
+ files.push(...findMdxFiles(fullPath, baseDir));
334
+ } else if (entry.isFile() && entry.name.endsWith(".mdx")) {
335
+ const relativePath = import_path2.default.relative(baseDir, fullPath).replace(/\\/g, "/");
336
+ files.push(relativePath);
337
+ }
338
+ }
339
+ } catch (error) {
340
+ console.error(`Error reading directory ${dir}:`, error);
341
+ }
342
+ return files;
343
+ }
344
+ function readDocFromFile(filePath, originalSlug) {
345
+ try {
346
+ if (!import_fs2.default.existsSync(filePath)) {
347
+ return null;
348
+ }
349
+ const fileContents = import_fs2.default.readFileSync(filePath, "utf8");
350
+ const { data, content } = (0, import_gray_matter.default)(fileContents);
351
+ const { minutes, words } = calculateReadingTime(content);
352
+ let finalSlug = originalSlug;
353
+ if (data.slug) {
354
+ const customSlug = data.slug.replace(/^\//, "");
355
+ const parts = originalSlug.split("/");
356
+ if (parts.length > 1) {
357
+ parts[parts.length - 1] = customSlug;
358
+ finalSlug = parts.join("/");
359
+ } else {
360
+ finalSlug = customSlug;
361
+ }
362
+ }
363
+ return {
364
+ slug: finalSlug,
365
+ filePath: originalSlug,
366
+ // Keep original file path for sidebar
367
+ title: data.title || originalSlug,
368
+ meta: {
369
+ ...data,
370
+ content,
371
+ reading_time: minutes,
372
+ word_count: words
373
+ },
374
+ content
375
+ };
376
+ } catch (error) {
377
+ console.error(`Error reading file ${filePath}:`, error);
378
+ return null;
379
+ }
380
+ }
381
+ async function getDocBySlug(slug, version = "v1.0.0") {
382
+ try {
383
+ let filePath = import_path2.default.join(DOCS_DIR2, version, `${slug}.mdx`);
384
+ let doc = readDocFromFile(filePath, slug);
385
+ if (doc) return doc;
386
+ filePath = import_path2.default.join(DOCS_DIR2, version, slug, "index.mdx");
387
+ doc = readDocFromFile(filePath, slug);
388
+ if (doc) return doc;
389
+ const versionDir = import_path2.default.join(DOCS_DIR2, version);
390
+ if (!import_fs2.default.existsSync(versionDir)) {
391
+ return null;
392
+ }
393
+ const mdxFiles = findMdxFiles(versionDir);
394
+ for (const file of mdxFiles) {
395
+ const fileSlug = file.replace(/\.mdx$/, "");
396
+ const testPath = import_path2.default.join(versionDir, file.endsWith("index.mdx") ? file : `${fileSlug}.mdx`);
397
+ const testDoc = readDocFromFile(testPath, fileSlug);
398
+ if (testDoc && testDoc.slug === slug) {
399
+ return testDoc;
400
+ }
401
+ }
402
+ return null;
403
+ } catch (error) {
404
+ console.error(`Error reading doc ${slug}:`, error);
405
+ return null;
406
+ }
407
+ }
408
+ async function getAllDocs(version = "v1.0.0") {
409
+ try {
410
+ const versionDir = import_path2.default.join(DOCS_DIR2, version);
411
+ if (!import_fs2.default.existsSync(versionDir)) {
412
+ return [];
413
+ }
414
+ const mdxFiles = findMdxFiles(versionDir);
415
+ const categoryConfigs = getAllCategoryConfigs(version);
416
+ const docs = await Promise.all(
417
+ mdxFiles.map(async (file) => {
418
+ const originalFilePath = file.replace(/\.mdx$/, "");
419
+ let slug = originalFilePath;
420
+ if (file.endsWith("/index.mdx") || file === "index.mdx") {
421
+ slug = import_path2.default.dirname(file).replace(/\\/g, "/");
422
+ if (slug === ".") slug = "";
423
+ }
424
+ const doc = await getDocBySlug(slug, version);
425
+ if (doc) {
426
+ doc.filePath = originalFilePath;
427
+ const folderPath = import_path2.default.dirname(originalFilePath).replace(/\\/g, "/");
428
+ if (folderPath !== ".") {
429
+ const categoryConfig = categoryConfigs.get(folderPath);
430
+ if (categoryConfig) {
431
+ doc.categoryLabel = categoryConfig.label;
432
+ doc.categoryPosition = categoryConfig.position ?? categoryConfig.sidebar_position;
433
+ doc.categoryCollapsible = categoryConfig.collapsible;
434
+ doc.categoryCollapsed = categoryConfig.collapsed;
435
+ doc.categoryIcon = categoryConfig.icon;
436
+ doc.categoryTabGroup = categoryConfig.tab_group;
437
+ }
438
+ }
439
+ }
440
+ return doc;
441
+ })
442
+ );
443
+ const isDevelopment3 = process.env.NODE_ENV === "development";
444
+ const uniqueDocs = /* @__PURE__ */ new Map();
445
+ docs.filter((doc) => doc !== null).filter((doc) => isDevelopment3 || !doc.meta.draft).forEach((doc) => {
446
+ uniqueDocs.set(doc.slug, doc);
447
+ });
448
+ return Array.from(uniqueDocs.values()).sort((a, b) => {
449
+ const orderA = a.meta.sidebar_position ?? a.meta.order ?? 999;
450
+ const orderB = b.meta.sidebar_position ?? b.meta.order ?? 999;
451
+ return orderA - orderB;
452
+ });
453
+ } catch (error) {
454
+ console.error(`Error getting all docs for version ${version}:`, error);
455
+ return [];
456
+ }
457
+ }
458
+ function flattenSidebarOrder(rootGroups, standalone) {
459
+ const flatDocs = [];
460
+ const flattenGroup = (group) => {
461
+ const sortedChildren = sortSidebarGroups(group.children);
462
+ const sortedItems = sortSidebarItems(group.items);
463
+ const merged = [
464
+ ...sortedChildren.map(([, childGroup]) => ({
465
+ type: "group",
466
+ group: childGroup,
467
+ position: childGroup.position
468
+ })),
469
+ ...sortedItems.map((doc) => ({
470
+ type: "item",
471
+ doc,
472
+ position: doc.meta.sidebar_position ?? doc.meta.order ?? 999
473
+ }))
474
+ ];
475
+ merged.sort((a, b) => a.position - b.position);
476
+ merged.forEach((item) => {
477
+ if (item.type === "group") {
478
+ flattenGroup(item.group);
479
+ } else {
480
+ flatDocs.push(item.doc);
481
+ }
482
+ });
483
+ };
484
+ sortSidebarItems(standalone).forEach((doc) => {
485
+ flatDocs.push(doc);
486
+ });
487
+ const sortedRootGroups = sortSidebarGroups(rootGroups);
488
+ sortedRootGroups.forEach(([, group]) => {
489
+ flattenGroup(group);
490
+ });
491
+ return flatDocs;
492
+ }
493
+ function getAdjacentDocs(currentSlug, allDocs) {
494
+ const { rootGroups, standalone } = buildSidebarStructure(allDocs);
495
+ const orderedDocs = flattenSidebarOrder(rootGroups, standalone);
496
+ const currentIndex = orderedDocs.findIndex((doc) => doc.slug === currentSlug);
497
+ if (currentIndex === -1) {
498
+ return {};
499
+ }
500
+ const currentDoc = orderedDocs[currentIndex];
501
+ const currentTabGroup = currentDoc.meta?.tab_group || currentDoc.categoryTabGroup;
502
+ const filteredDocs = orderedDocs.filter((doc) => {
503
+ const docTabGroup = doc.meta?.tab_group || doc.categoryTabGroup;
504
+ if (currentTabGroup) {
505
+ return docTabGroup === currentTabGroup;
506
+ }
507
+ return !docTabGroup;
508
+ });
509
+ const filteredIndex = filteredDocs.findIndex((doc) => doc.slug === currentSlug);
510
+ if (filteredIndex === -1) {
511
+ return {};
512
+ }
513
+ return {
514
+ previous: filteredIndex > 0 ? filteredDocs[filteredIndex - 1] : void 0,
515
+ next: filteredIndex < filteredDocs.length - 1 ? filteredDocs[filteredIndex + 1] : void 0
516
+ };
517
+ }
518
+ function extractTableOfContents(content) {
519
+ const headingRegex = /^(#{2,3})\s+(.+)$/gm;
520
+ const toc = [];
521
+ let match;
522
+ while ((match = headingRegex.exec(content)) !== null) {
523
+ const level = match[1].length;
524
+ const text = match[2];
525
+ const id = text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-|-$/g, "");
526
+ toc.push({ id, title: text, level });
527
+ }
528
+ return toc;
529
+ }
530
+ function isCategoryPage(slug, allDocs) {
531
+ return allDocs.some((doc) => {
532
+ const parts = doc.slug.split("/");
533
+ const docParent = parts.slice(0, -1).join("/");
534
+ return docParent === slug && doc.slug !== slug;
535
+ });
536
+ }
537
+
538
+ // src/lib/mdx-cache.ts
539
+ var import_fs3 = require("fs");
540
+ var import_path3 = require("path");
541
+
542
+ // src/lib/dev-utils.ts
543
+ var isDevelopment = process.env.NODE_ENV === "development";
544
+ var PerfTimer = class {
545
+ constructor(label) {
546
+ this.label = label;
547
+ this.startTime = isDevelopment ? performance.now() : 0;
548
+ }
549
+ end() {
550
+ if (!isDevelopment) return;
551
+ const duration = performance.now() - this.startTime;
552
+ const color = duration > 1e3 ? "\x1B[31m" : duration > 500 ? "\x1B[33m" : "\x1B[32m";
553
+ const reset = "\x1B[0m";
554
+ console.log(`${color}\u23F1\uFE0F ${this.label}: ${duration.toFixed(2)}ms${reset}`);
555
+ }
556
+ };
557
+ function logFsOperation(operation, path3, details) {
558
+ if (!isDevelopment) return;
559
+ console.log(`\u{1F4C1} [FS] ${operation}: ${path3}`, details || "");
560
+ }
561
+ function logCacheOperation(operation, key) {
562
+ if (!isDevelopment) return;
563
+ const emoji = operation === "hit" ? "\u2705" : operation === "miss" ? "\u274C" : "\u{1F504}";
564
+ console.log(`${emoji} [Cache] ${operation}: ${key}`);
565
+ }
566
+ function logMemoryUsage(label) {
567
+ if (!isDevelopment) return;
568
+ const used = process.memoryUsage();
569
+ const prefix = label ? `[${label}] ` : "";
570
+ console.log(`\u{1F4BE} ${prefix}Memory Usage:`, {
571
+ rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
572
+ heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
573
+ heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`
574
+ });
575
+ }
576
+ function debugLog(label, data) {
577
+ if (!isDevelopment) return;
578
+ console.log(`
579
+ \u{1F50D} ${label}:`);
580
+ console.dir(data, { depth: null, colors: true });
581
+ console.log("");
582
+ }
583
+
584
+ // src/lib/mdx-cache.ts
585
+ var isDevelopment2 = process.env.NODE_ENV === "development";
586
+ var versionsCache = {
587
+ data: null,
588
+ timestamp: 0
589
+ };
590
+ var allDocsCache = /* @__PURE__ */ new Map();
591
+ var docBySlugCache = /* @__PURE__ */ new Map();
592
+ var CACHE_TTL = isDevelopment2 ? 5e3 : 6e4;
593
+ var watchersInitialized = false;
594
+ function initializeWatchers() {
595
+ if (!isDevelopment2 || watchersInitialized) return;
596
+ watchersInitialized = true;
597
+ const docsPath = (0, import_path3.join)(process.cwd(), "docs");
598
+ try {
599
+ (0, import_fs3.watch)(docsPath, { recursive: true }, (eventType, filename) => {
600
+ if (!filename) return;
601
+ if (filename.endsWith(".mdx") || filename.endsWith(".json")) {
602
+ const parts = filename.split(/[/\\]/);
603
+ const version = parts[0];
604
+ allDocsCache.delete(version);
605
+ const cacheKeysToDelete = [];
606
+ docBySlugCache.forEach((_, key) => {
607
+ if (key.startsWith(`${version}:`)) {
608
+ cacheKeysToDelete.push(key);
609
+ }
610
+ });
611
+ cacheKeysToDelete.forEach((key) => docBySlugCache.delete(key));
612
+ if (eventType === "rename") {
613
+ versionsCache.data = null;
614
+ }
615
+ console.log(`[MDX Cache] Invalidated cache for: ${filename}`);
616
+ }
617
+ });
618
+ console.log("[MDX Cache] File watchers initialized");
619
+ } catch (error) {
620
+ console.error("[MDX Cache] Failed to initialize watchers:", error);
621
+ }
622
+ }
623
+ function isCacheValid(timestamp) {
624
+ return Date.now() - timestamp < CACHE_TTL;
625
+ }
626
+ function getCachedVersions() {
627
+ initializeWatchers();
628
+ if (versionsCache.data && isCacheValid(versionsCache.timestamp)) {
629
+ logCacheOperation("hit", "versions");
630
+ return versionsCache.data;
631
+ }
632
+ logCacheOperation("miss", "versions");
633
+ const timer = new PerfTimer("getVersions");
634
+ const versions = getVersions();
635
+ timer.end();
636
+ versionsCache.data = versions;
637
+ versionsCache.timestamp = Date.now();
638
+ return versions;
639
+ }
640
+ async function getCachedAllDocs(version = "v1.0.0") {
641
+ initializeWatchers();
642
+ const cached = allDocsCache.get(version);
643
+ if (cached && isCacheValid(cached.timestamp)) {
644
+ logCacheOperation("hit", `getAllDocs:${version}`);
645
+ return cached.data;
646
+ }
647
+ logCacheOperation("miss", `getAllDocs:${version}`);
648
+ const timer = new PerfTimer(`getAllDocs(${version})`);
649
+ const docs = await getAllDocs(version);
650
+ timer.end();
651
+ allDocsCache.set(version, {
652
+ data: docs,
653
+ timestamp: Date.now()
654
+ });
655
+ return docs;
656
+ }
657
+ async function getCachedDocBySlug(slug, version = "v1.0.0") {
658
+ initializeWatchers();
659
+ const cacheKey = `${version}:${slug}`;
660
+ const cached = docBySlugCache.get(cacheKey);
661
+ if (cached && isCacheValid(cached.timestamp)) {
662
+ logCacheOperation("hit", `getDocBySlug:${cacheKey}`);
663
+ return cached.data;
664
+ }
665
+ logCacheOperation("miss", `getDocBySlug:${cacheKey}`);
666
+ const timer = new PerfTimer(`getDocBySlug(${slug})`);
667
+ const doc = await getDocBySlug(slug, version);
668
+ timer.end();
669
+ docBySlugCache.set(cacheKey, {
670
+ data: doc,
671
+ timestamp: Date.now()
672
+ });
673
+ return doc;
674
+ }
675
+ function clearAllCaches() {
676
+ versionsCache.data = null;
677
+ allDocsCache.clear();
678
+ docBySlugCache.clear();
679
+ console.log("[MDX Cache] All caches cleared");
680
+ }
681
+ function getCacheStats() {
682
+ return {
683
+ versions: {
684
+ cached: versionsCache.data !== null,
685
+ age: versionsCache.timestamp ? Date.now() - versionsCache.timestamp : 0
686
+ },
687
+ allDocs: {
688
+ entries: allDocsCache.size,
689
+ versions: Array.from(allDocsCache.keys())
690
+ },
691
+ docBySlug: {
692
+ entries: docBySlugCache.size
693
+ }
694
+ };
695
+ }
696
+
697
+ // src/lib/toc.ts
698
+ function extractHeadings(html) {
699
+ const headingRegex = /<h([2-3])[^>]*id="([^"]*)"[^>]*>(.*?)<\/h\1>/g;
700
+ const toc = [];
701
+ let match;
702
+ while ((match = headingRegex.exec(html)) !== null) {
703
+ const level = Number.parseInt(match[1]);
704
+ const id = match[2];
705
+ const title = match[3].replace(/<[^>]*>/g, "");
706
+ toc.push({ id, title, level });
707
+ }
708
+ return toc;
709
+ }
710
+
711
+ // src/lib/config.types.ts
712
+ var defaultConfig = {
713
+ site: {
714
+ title: "Documentation",
715
+ description: "Project documentation",
716
+ baseUrl: "/",
717
+ language: "en"
718
+ },
719
+ theme: {
720
+ defaultMode: "system",
721
+ respectPrefersColorScheme: true
722
+ },
723
+ navigation: {
724
+ showSidebar: true,
725
+ collapsibleSidebar: true,
726
+ showBreadcrumbs: true,
727
+ showTableOfContents: true,
728
+ tocPosition: "right",
729
+ tocMaxDepth: 3
730
+ },
731
+ search: {
732
+ enabled: true,
733
+ provider: "local",
734
+ placeholder: "Search documentation..."
735
+ },
736
+ features: {
737
+ showLastUpdated: true,
738
+ showReadingTime: true,
739
+ showAuthors: false,
740
+ showTags: true,
741
+ versioning: true,
742
+ i18n: false
743
+ }
744
+ };
745
+
746
+ // src/lib/config.server.ts
747
+ function deepMerge(target, source) {
748
+ const result = { ...target };
749
+ for (const key in source) {
750
+ const sourceValue = source[key];
751
+ const targetValue = result[key];
752
+ if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
753
+ result[key] = deepMerge(
754
+ targetValue && typeof targetValue === "object" ? targetValue : {},
755
+ sourceValue
756
+ );
757
+ } else if (sourceValue !== void 0) {
758
+ result[key] = sourceValue;
759
+ }
760
+ }
761
+ return result;
762
+ }
763
+ function loadConfig(userConfig) {
764
+ try {
765
+ const config = deepMerge(defaultConfig, userConfig);
766
+ return config;
767
+ } catch (error) {
768
+ console.error(`\u274C Error loading configuration:`, error);
769
+ console.warn("Using default configuration.");
770
+ return defaultConfig;
771
+ }
772
+ }
773
+ function getConfigValue(path3, config) {
774
+ const cfg = config || loadConfig({});
775
+ const keys = path3.split(".");
776
+ let value = cfg;
777
+ for (const key of keys) {
778
+ if (value && typeof value === "object" && key in value) {
779
+ value = value[key];
780
+ } else {
781
+ return void 0;
782
+ }
783
+ }
784
+ return value;
785
+ }
786
+ function replaceEnvVariables(text, config) {
787
+ const cfg = config || loadConfig({});
788
+ const envVars = cfg.env || {};
789
+ let result = text;
790
+ result = result.replace(/\$\{([^}]+)\}/g, (match, varName) => {
791
+ return envVars[varName] || match;
792
+ });
793
+ result = result.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
794
+ return envVars[varName] || match;
795
+ });
796
+ return result;
797
+ }
798
+ function processContentWithEnv(content, config) {
799
+ return replaceEnvVariables(content, config);
800
+ }
801
+ function validateConfig(config) {
802
+ const errors = [];
803
+ if (!config.site?.title) {
804
+ errors.push("site.title is required");
805
+ }
806
+ if (config.site?.url) {
807
+ try {
808
+ new URL(config.site.url);
809
+ } catch {
810
+ errors.push("site.url must be a valid URL");
811
+ }
812
+ }
813
+ if (config.social) {
814
+ const socialKeys = ["github", "twitter", "discord", "linkedin", "youtube"];
815
+ for (const key of socialKeys) {
816
+ const url = config.social[key];
817
+ if (url) {
818
+ try {
819
+ new URL(url);
820
+ } catch {
821
+ errors.push(`social.${key} must be a valid URL`);
822
+ }
823
+ }
824
+ }
825
+ }
826
+ return {
827
+ valid: errors.length === 0,
828
+ errors
829
+ };
830
+ }
831
+ var configInstance = null;
832
+ function initConfig(userConfig) {
833
+ if (configInstance) {
834
+ throw new Error("Specra config has already been initialized");
835
+ }
836
+ configInstance = loadConfig(userConfig);
837
+ return configInstance;
838
+ }
839
+ function getConfig() {
840
+ if (!configInstance) {
841
+ throw new Error("Specra config has not been initialized");
842
+ }
843
+ return configInstance;
844
+ }
845
+ function reloadConfig(userConfig) {
846
+ configInstance = loadConfig(userConfig);
847
+ return configInstance;
848
+ }
849
+
850
+ // src/lib/parsers/specra-parser.ts
851
+ var SpecraParser = class {
852
+ validate(input) {
853
+ return typeof input === "object" && input !== null && "endpoints" in input && Array.isArray(input.endpoints);
854
+ }
855
+ parse(input) {
856
+ if (!this.validate(input)) {
857
+ throw new Error("Invalid Specra API spec format");
858
+ }
859
+ return input;
860
+ }
861
+ };
862
+
863
+ // src/lib/parsers/openapi-parser.ts
864
+ var OpenApiParser = class {
865
+ validate(input) {
866
+ return typeof input === "object" && input !== null && ("openapi" in input || "swagger" in input) && "paths" in input;
867
+ }
868
+ parse(input) {
869
+ if (!this.validate(input)) {
870
+ throw new Error("Invalid OpenAPI spec format");
871
+ }
872
+ const baseUrl = this.extractBaseUrl(input);
873
+ const endpoints = [];
874
+ for (const [path3, pathItem] of Object.entries(input.paths || {})) {
875
+ const methods = ["get", "post", "put", "patch", "delete"];
876
+ for (const method of methods) {
877
+ const operation = pathItem[method];
878
+ if (!operation) continue;
879
+ const endpoint = this.parseOperation(path3, method.toUpperCase(), operation, input);
880
+ endpoints.push(endpoint);
881
+ }
882
+ }
883
+ return {
884
+ version: input.info?.version,
885
+ title: input.info?.title,
886
+ description: input.info?.description,
887
+ baseUrl,
888
+ auth: this.extractAuth(input),
889
+ endpoints
890
+ };
891
+ }
892
+ extractBaseUrl(spec) {
893
+ if (spec.servers && spec.servers.length > 0) {
894
+ return spec.servers[0].url;
895
+ }
896
+ if (spec.host) {
897
+ const scheme = spec.schemes?.[0] || "https";
898
+ const basePath = spec.basePath || "";
899
+ return `${scheme}://${spec.host}${basePath}`;
900
+ }
901
+ return "";
902
+ }
903
+ extractAuth(spec) {
904
+ const securitySchemes = spec.components?.securitySchemes || spec.securityDefinitions;
905
+ if (!securitySchemes) return void 0;
906
+ const firstScheme = Object.values(securitySchemes)[0];
907
+ if (!firstScheme) return void 0;
908
+ if (firstScheme.type === "http" && firstScheme.scheme === "bearer") {
909
+ return {
910
+ type: "bearer",
911
+ description: firstScheme.description,
912
+ tokenPrefix: "Bearer"
913
+ };
914
+ }
915
+ if (firstScheme.type === "apiKey") {
916
+ return {
917
+ type: "apiKey",
918
+ description: firstScheme.description,
919
+ headerName: firstScheme.name || "X-API-Key"
920
+ };
921
+ }
922
+ if (firstScheme.type === "http" && firstScheme.scheme === "basic") {
923
+ return {
924
+ type: "basic",
925
+ description: firstScheme.description
926
+ };
927
+ }
928
+ return void 0;
929
+ }
930
+ parseOperation(path3, method, operation, spec) {
931
+ const endpoint = {
932
+ title: operation.summary || operation.operationId || `${method} ${path3}`,
933
+ method,
934
+ path: this.convertPathParams(path3),
935
+ description: operation.description
936
+ };
937
+ const params = this.parseParameters(operation.parameters || [], spec);
938
+ if (params.path.length > 0) endpoint.pathParams = params.path;
939
+ if (params.query.length > 0) endpoint.queryParams = params.query;
940
+ if (params.header.length > 0) {
941
+ endpoint.headers = params.header.map((p) => ({
942
+ name: p.name,
943
+ value: p.example || "",
944
+ description: p.description
945
+ }));
946
+ }
947
+ if (operation.requestBody) {
948
+ endpoint.body = this.parseRequestBody(operation.requestBody, spec);
949
+ }
950
+ const responses = this.parseResponses(operation.responses || {}, spec);
951
+ if (responses.success) endpoint.successResponse = responses.success;
952
+ if (responses.errors.length > 0) endpoint.errorResponses = responses.errors;
953
+ return endpoint;
954
+ }
955
+ convertPathParams(path3) {
956
+ return path3.replace(/\{([^}]+)\}/g, ":$1");
957
+ }
958
+ parseParameters(parameters, spec) {
959
+ const result = { path: [], query: [], header: [] };
960
+ for (const param of parameters) {
961
+ const resolved = param.$ref ? this.resolveRef(param.$ref, spec) : param;
962
+ const apiParam = {
963
+ name: resolved.name,
964
+ type: resolved.schema?.type || resolved.type || "string",
965
+ required: resolved.required,
966
+ description: resolved.description,
967
+ example: resolved.example || resolved.schema?.example
968
+ };
969
+ if (resolved.in === "path") result.path.push(apiParam);
970
+ else if (resolved.in === "query") result.query.push(apiParam);
971
+ else if (resolved.in === "header") result.header.push(apiParam);
972
+ }
973
+ return result;
974
+ }
975
+ parseRequestBody(requestBody, spec) {
976
+ const content = requestBody.content?.["application/json"];
977
+ if (!content) return void 0;
978
+ return {
979
+ description: requestBody.description,
980
+ example: content.example || this.generateExample(content.schema, spec),
981
+ schema: content.schema
982
+ };
983
+ }
984
+ parseResponses(responses, spec) {
985
+ const result = { errors: [] };
986
+ for (const [statusCode, response] of Object.entries(responses)) {
987
+ const status = parseInt(statusCode);
988
+ if (isNaN(status)) continue;
989
+ const resolved = response.$ref ? this.resolveRef(response.$ref, spec) : response;
990
+ const content = resolved.content?.["application/json"];
991
+ const apiResponse = {
992
+ status,
993
+ description: resolved.description,
994
+ example: content?.example || this.generateExample(content?.schema, spec),
995
+ schema: content?.schema
996
+ };
997
+ if (status >= 200 && status < 300) {
998
+ result.success = apiResponse;
999
+ } else {
1000
+ result.errors.push(apiResponse);
1001
+ }
1002
+ }
1003
+ return result;
1004
+ }
1005
+ generateExample(schema, spec) {
1006
+ if (!schema) return void 0;
1007
+ if (schema.$ref) schema = this.resolveRef(schema.$ref, spec);
1008
+ if (schema.example) return schema.example;
1009
+ if (schema.type === "object" && schema.properties) {
1010
+ const example = {};
1011
+ for (const [key, prop] of Object.entries(schema.properties)) {
1012
+ example[key] = this.generateExample(prop, spec);
1013
+ }
1014
+ return example;
1015
+ }
1016
+ if (schema.type === "array" && schema.items) {
1017
+ return [this.generateExample(schema.items, spec)];
1018
+ }
1019
+ const defaults = {
1020
+ string: "string",
1021
+ number: 0,
1022
+ integer: 0,
1023
+ boolean: false,
1024
+ object: {},
1025
+ array: []
1026
+ };
1027
+ return defaults[schema.type] || null;
1028
+ }
1029
+ resolveRef(ref, spec) {
1030
+ const path3 = ref.replace(/^#\//, "").split("/");
1031
+ let current = spec;
1032
+ for (const segment of path3) {
1033
+ current = current[segment];
1034
+ if (!current) return {};
1035
+ }
1036
+ return current;
1037
+ }
1038
+ };
1039
+
1040
+ // src/lib/parsers/postman-parser.ts
1041
+ var PostmanParser = class {
1042
+ validate(input) {
1043
+ return typeof input === "object" && input !== null && "info" in input && input.info?.schema?.includes("v2");
1044
+ }
1045
+ parse(input) {
1046
+ if (!this.validate(input)) {
1047
+ throw new Error("Invalid Postman Collection format (requires v2.0 or v2.1)");
1048
+ }
1049
+ const baseUrl = this.extractBaseUrl(input);
1050
+ const endpoints = [];
1051
+ this.parseItems(input.item || [], endpoints, baseUrl, input);
1052
+ return {
1053
+ version: input.info?.version,
1054
+ title: input.info?.name,
1055
+ description: input.info?.description,
1056
+ baseUrl,
1057
+ auth: this.extractAuth(input.auth),
1058
+ globalHeaders: this.extractGlobalHeaders(input),
1059
+ endpoints
1060
+ };
1061
+ }
1062
+ extractBaseUrl(collection) {
1063
+ const baseUrlVar = collection.variable?.find(
1064
+ (v) => v.key === "baseUrl" || v.key === "base_url" || v.key === "url"
1065
+ );
1066
+ if (baseUrlVar) return baseUrlVar.value;
1067
+ if (collection.item && collection.item.length > 0) {
1068
+ const firstRequest = this.findFirstRequest(collection.item);
1069
+ if (firstRequest?.request?.url) {
1070
+ const url = this.parseUrl(firstRequest.request.url);
1071
+ if (url.host) {
1072
+ return `${url.protocol}://${url.host.join(".")}`;
1073
+ }
1074
+ }
1075
+ }
1076
+ return "";
1077
+ }
1078
+ findFirstRequest(items) {
1079
+ for (const item of items) {
1080
+ if (item.request) return item;
1081
+ if (item.item) {
1082
+ const found = this.findFirstRequest(item.item);
1083
+ if (found) return found;
1084
+ }
1085
+ }
1086
+ return null;
1087
+ }
1088
+ extractAuth(auth) {
1089
+ if (!auth) return void 0;
1090
+ if (auth.type === "bearer") {
1091
+ return {
1092
+ type: "bearer",
1093
+ tokenPrefix: "Bearer"
1094
+ };
1095
+ }
1096
+ if (auth.type === "apikey") {
1097
+ const keyData = auth.apikey?.find((a) => a.key === "key");
1098
+ const keyName = keyData?.value || "X-API-Key";
1099
+ return {
1100
+ type: "apiKey",
1101
+ headerName: keyName
1102
+ };
1103
+ }
1104
+ if (auth.type === "basic") {
1105
+ return {
1106
+ type: "basic"
1107
+ };
1108
+ }
1109
+ return void 0;
1110
+ }
1111
+ extractGlobalHeaders(collection) {
1112
+ return [];
1113
+ }
1114
+ parseItems(items, endpoints, baseUrl, collection) {
1115
+ for (const item of items) {
1116
+ if (item.item && Array.isArray(item.item)) {
1117
+ this.parseItems(item.item, endpoints, baseUrl, collection);
1118
+ } else if (item.request) {
1119
+ const endpoint = this.parseRequest(item, baseUrl, collection);
1120
+ endpoints.push(endpoint);
1121
+ }
1122
+ }
1123
+ }
1124
+ parseRequest(item, baseUrl, collection) {
1125
+ const request = item.request;
1126
+ const url = this.parseUrl(request.url);
1127
+ const endpoint = {
1128
+ title: item.name,
1129
+ method: request.method.toUpperCase(),
1130
+ path: this.buildPath(url, baseUrl),
1131
+ description: item.request.description || item.description
1132
+ };
1133
+ const params = this.parseUrlParams(url);
1134
+ if (params.path.length > 0) endpoint.pathParams = params.path;
1135
+ if (params.query.length > 0) endpoint.queryParams = params.query;
1136
+ if (request.header && request.header.length > 0) {
1137
+ endpoint.headers = request.header.filter((h) => !h.disabled).map((h) => ({
1138
+ name: h.key,
1139
+ value: h.value || "",
1140
+ description: h.description
1141
+ }));
1142
+ }
1143
+ if (request.body) {
1144
+ endpoint.body = this.parseBody(request.body);
1145
+ }
1146
+ const responses = this.parseResponses(item.response || []);
1147
+ if (responses.success) endpoint.successResponse = responses.success;
1148
+ if (responses.errors.length > 0) endpoint.errorResponses = responses.errors;
1149
+ return endpoint;
1150
+ }
1151
+ parseUrl(url) {
1152
+ if (typeof url === "string") {
1153
+ const urlObj = new URL(url);
1154
+ return {
1155
+ protocol: urlObj.protocol.replace(":", ""),
1156
+ host: urlObj.hostname.split("."),
1157
+ path: urlObj.pathname.split("/").filter(Boolean),
1158
+ query: [],
1159
+ variable: []
1160
+ };
1161
+ }
1162
+ return {
1163
+ protocol: url.protocol || "https",
1164
+ host: url.host || [],
1165
+ path: url.path || [],
1166
+ query: url.query || [],
1167
+ variable: url.variable || []
1168
+ };
1169
+ }
1170
+ buildPath(url, baseUrl) {
1171
+ let path3 = "/";
1172
+ if (url.path && url.path.length > 0) {
1173
+ path3 += url.path.join("/");
1174
+ }
1175
+ path3 = path3.replace(/\{\{([^}]+)\}\}/g, ":$1");
1176
+ return path3;
1177
+ }
1178
+ parseUrlParams(url) {
1179
+ const result = { path: [], query: [] };
1180
+ if (url.variable && url.variable.length > 0) {
1181
+ for (const v of url.variable) {
1182
+ result.path.push({
1183
+ name: v.key,
1184
+ type: v.type || "string",
1185
+ description: v.description,
1186
+ example: v.value
1187
+ });
1188
+ }
1189
+ }
1190
+ if (url.path && url.path.length > 0) {
1191
+ for (const segment of url.path) {
1192
+ if (segment.startsWith(":")) {
1193
+ const paramName = segment.slice(1);
1194
+ if (!result.path.find((p) => p.name === paramName)) {
1195
+ result.path.push({
1196
+ name: paramName,
1197
+ type: "string"
1198
+ });
1199
+ }
1200
+ }
1201
+ }
1202
+ }
1203
+ if (url.query && url.query.length > 0) {
1204
+ for (const q of url.query) {
1205
+ if (q.disabled) continue;
1206
+ result.query.push({
1207
+ name: q.key,
1208
+ type: "string",
1209
+ description: q.description,
1210
+ example: q.value
1211
+ });
1212
+ }
1213
+ }
1214
+ return result;
1215
+ }
1216
+ parseBody(body) {
1217
+ if (!body) return void 0;
1218
+ let example;
1219
+ let description = body.description;
1220
+ if (body.mode === "raw") {
1221
+ try {
1222
+ example = JSON.parse(body.raw);
1223
+ } catch {
1224
+ example = body.raw;
1225
+ }
1226
+ } else if (body.mode === "formdata" || body.mode === "urlencoded") {
1227
+ example = {};
1228
+ for (const item of body[body.mode] || []) {
1229
+ if (!item.disabled) {
1230
+ example[item.key] = item.value;
1231
+ }
1232
+ }
1233
+ }
1234
+ return {
1235
+ description,
1236
+ example
1237
+ };
1238
+ }
1239
+ parseResponses(responses) {
1240
+ const result = { errors: [] };
1241
+ for (const response of responses) {
1242
+ let example;
1243
+ try {
1244
+ example = JSON.parse(response.body);
1245
+ } catch {
1246
+ example = response.body;
1247
+ }
1248
+ const apiResponse = {
1249
+ status: response.code || 200,
1250
+ description: response.name,
1251
+ example
1252
+ };
1253
+ if (apiResponse.status >= 200 && apiResponse.status < 300) {
1254
+ if (!result.success) result.success = apiResponse;
1255
+ } else {
1256
+ result.errors.push(apiResponse);
1257
+ }
1258
+ }
1259
+ return result;
1260
+ }
1261
+ };
1262
+
1263
+ // src/lib/parsers/index.ts
1264
+ var parsers = /* @__PURE__ */ new Map([
1265
+ ["specra", new SpecraParser()],
1266
+ ["openapi", new OpenApiParser()],
1267
+ ["postman", new PostmanParser()]
1268
+ ]);
1269
+ function detectParserType(input) {
1270
+ if (!input || typeof input !== "object") {
1271
+ throw new Error("Invalid API spec: input must be an object");
1272
+ }
1273
+ if (input.info?.schema?.includes("v2")) {
1274
+ return "postman";
1275
+ }
1276
+ if (input.openapi || input.swagger) {
1277
+ return "openapi";
1278
+ }
1279
+ if (input.endpoints && Array.isArray(input.endpoints)) {
1280
+ return "specra";
1281
+ }
1282
+ throw new Error(
1283
+ "Unable to auto-detect API spec format. Supported formats: Specra, OpenAPI 3.x, Postman Collection v2.x"
1284
+ );
1285
+ }
1286
+ function parseApiSpec(input, parserType = "auto") {
1287
+ const actualType = parserType === "auto" ? detectParserType(input) : parserType;
1288
+ const parser = parsers.get(actualType);
1289
+ if (!parser) {
1290
+ throw new Error(`Unknown parser type: ${actualType}`);
1291
+ }
1292
+ if (!parser.validate(input)) {
1293
+ throw new Error(`Input does not match ${actualType} format`);
1294
+ }
1295
+ return parser.parse(input);
1296
+ }
1297
+
1298
+ // src/lib/utils.ts
1299
+ var import_clsx = require("clsx");
1300
+ var import_tailwind_merge = require("tailwind-merge");
1301
+ function cn(...inputs) {
1302
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
1303
+ }
1304
+ function getAssetPath(path3) {
1305
+ const basePath = process.env.NEXT_PUBLIC_BASE_PATH || process.env.__NEXT_ROUTER_BASEPATH || "";
1306
+ const normalizedPath = path3.startsWith("/") ? path3 : `/${path3}`;
1307
+ if (basePath) {
1308
+ const normalizedBase = basePath.startsWith("/") ? basePath : `/${basePath}`;
1309
+ const cleanBase = normalizedBase.replace(/\/$/, "");
1310
+ return `${cleanBase}${normalizedPath}`;
1311
+ }
1312
+ return normalizedPath;
1313
+ }
1314
+
1315
+ // src/lib/redirects.ts
1316
+ async function buildRedirectMappings() {
1317
+ const versions = getVersions();
1318
+ const redirects = [];
1319
+ for (const version of versions) {
1320
+ const docs = await getAllDocs(version);
1321
+ for (const doc of docs) {
1322
+ if (doc.meta.redirect_from && Array.isArray(doc.meta.redirect_from)) {
1323
+ for (const oldPath of doc.meta.redirect_from) {
1324
+ redirects.push({
1325
+ from: oldPath,
1326
+ to: `/docs/${version}/${doc.slug}`
1327
+ });
1328
+ }
1329
+ }
1330
+ }
1331
+ }
1332
+ return redirects;
1333
+ }
1334
+ async function findRedirect(path3) {
1335
+ const redirects = await buildRedirectMappings();
1336
+ const redirect = redirects.find((r) => r.from === path3);
1337
+ return redirect ? redirect.to : null;
1338
+ }
1339
+
1340
+ // src/components/docs/accordion.tsx
1341
+ var import_lucide_react = require("lucide-react");
1342
+ var import_react = require("react");
1343
+ var import_jsx_runtime = require("react/jsx-runtime");
1344
+ function AccordionItem({ title, children, defaultOpen = false }) {
1345
+ const [isOpen, setIsOpen] = (0, import_react.useState)(defaultOpen);
1346
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "border border-border rounded-xl overflow-hidden mb-2", children: [
1347
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1348
+ "button",
1349
+ {
1350
+ onClick: () => setIsOpen(!isOpen),
1351
+ className: "w-full flex items-center justify-between p-4 text-left bg-muted/30 hover:bg-muted/50 transition-colors",
1352
+ children: [
1353
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-medium text-foreground", children: title }),
1354
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1355
+ import_lucide_react.ChevronDown,
1356
+ {
1357
+ className: `h-5 w-5 text-muted-foreground transition-transform ${isOpen ? "rotate-180" : ""}`
1358
+ }
1359
+ )
1360
+ ]
1361
+ }
1362
+ ),
1363
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "p-4 border-t border-border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "prose prose-sm dark:prose-invert max-w-none [&>*:last-child]:mb-0", children }) })
1364
+ ] });
1365
+ }
1366
+ function Accordion({ children, type = "multiple", className }) {
1367
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: className || "my-6 space-y-2", children });
1368
+ }
1369
+
1370
+ // src/components/docs/badge.tsx
1371
+ var import_jsx_runtime2 = require("react/jsx-runtime");
1372
+ function Badge({ children, variant = "default" }) {
1373
+ const variants = {
1374
+ default: "bg-muted text-foreground border-border",
1375
+ success: "bg-green-500/10 text-green-600 dark:text-green-400 border-green-500/20",
1376
+ warning: "bg-yellow-500/10 text-yellow-600 dark:text-yellow-400 border-yellow-500/20",
1377
+ error: "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20",
1378
+ info: "bg-blue-500/10 text-blue-600 dark:text-blue-400 border-blue-500/20"
1379
+ };
1380
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1381
+ "span",
1382
+ {
1383
+ className: `inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium border ${variants[variant]}`,
1384
+ children
1385
+ }
1386
+ );
1387
+ }
1388
+
1389
+ // src/components/docs/breadcrumb.tsx
1390
+ var import_link = __toESM(require("next/link"));
1391
+ var import_lucide_react2 = require("lucide-react");
1392
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1393
+ function Breadcrumb({ version, slug, title }) {
1394
+ const parts = slug.split("/");
1395
+ const breadcrumbs = [
1396
+ { label: "Docs", href: `/docs/${version}` }
1397
+ ];
1398
+ let currentPath = "";
1399
+ for (let i = 0; i < parts.length - 1; i++) {
1400
+ currentPath += (currentPath ? "/" : "") + parts[i];
1401
+ breadcrumbs.push({
1402
+ label: parts[i].replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
1403
+ href: `/docs/${version}/${currentPath}`
1404
+ });
1405
+ }
1406
+ breadcrumbs.push({
1407
+ label: title,
1408
+ href: `/docs/${version}/${slug}`
1409
+ });
1410
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("nav", { className: "flex items-center gap-2 text-sm text-muted-foreground mb-4", "aria-label": "Breadcrumb", children: breadcrumbs.map((crumb, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
1411
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.ChevronRight, { className: "h-4 w-4" }),
1412
+ index === breadcrumbs.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-foreground font-medium", children: crumb.label }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1413
+ import_link.default,
1414
+ {
1415
+ href: crumb.href,
1416
+ className: "hover:text-foreground transition-colors",
1417
+ children: crumb.label
1418
+ }
1419
+ )
1420
+ ] }, crumb.href)) });
1421
+ }
1422
+
1423
+ // src/components/docs/callout.tsx
1424
+ var import_lucide_react3 = require("lucide-react");
1425
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1426
+ function Callout({ children, type = "info", title }) {
1427
+ const configs = {
1428
+ info: {
1429
+ icon: import_lucide_react3.Info,
1430
+ className: "bg-blue-500/10 border-blue-500/30 text-blue-900 dark:bg-blue-400/5 dark:border-blue-500/20 dark:text-blue-400",
1431
+ iconClassName: "text-blue-600 dark:text-blue-400",
1432
+ titleClassName: "text-blue-700 dark:text-blue-300",
1433
+ defaultTitle: "Info"
1434
+ },
1435
+ note: {
1436
+ icon: import_lucide_react3.Info,
1437
+ className: "bg-blue-500/10 border-blue-500/30 text-blue-900 dark:bg-blue-400/5 dark:border-blue-500/20 dark:text-blue-400",
1438
+ iconClassName: "text-blue-600 dark:text-blue-400",
1439
+ titleClassName: "text-blue-700 dark:text-blue-300",
1440
+ defaultTitle: "Note"
1441
+ },
1442
+ warning: {
1443
+ icon: import_lucide_react3.AlertTriangle,
1444
+ className: "bg-yellow-500/10 border-yellow-500/30 text-yellow-900 dark:bg-yellow-400/5 dark:border-yellow-500/20 dark:text-yellow-400",
1445
+ iconClassName: "text-yellow-600 dark:text-yellow-400",
1446
+ titleClassName: "text-yellow-700 dark:text-yellow-300",
1447
+ defaultTitle: "Warning"
1448
+ },
1449
+ success: {
1450
+ icon: import_lucide_react3.CheckCircle2,
1451
+ className: "bg-green-500/10 border-green-500/30 text-green-900 dark:bg-green-400/5 dark:border-green-500/20 dark:text-green-400",
1452
+ iconClassName: "text-green-600 dark:text-green-400",
1453
+ titleClassName: "text-green-700 dark:text-green-300",
1454
+ defaultTitle: "Success"
1455
+ },
1456
+ error: {
1457
+ icon: import_lucide_react3.XCircle,
1458
+ className: "bg-red-500/10 border-red-500/30 text-red-900 dark:bg-red-400/5 dark:border-red-500/20 dark:text-red-400",
1459
+ iconClassName: "text-red-600 dark:text-red-400",
1460
+ titleClassName: "text-red-700 dark:text-red-300",
1461
+ defaultTitle: "Error"
1462
+ },
1463
+ danger: {
1464
+ icon: import_lucide_react3.XCircle,
1465
+ className: "bg-red-500/10 border-red-500/30 text-red-900 dark:bg-red-400/5 dark:border-red-500/20 dark:text-red-400",
1466
+ iconClassName: "text-red-600 dark:text-red-400",
1467
+ titleClassName: "text-red-700 dark:text-red-300",
1468
+ defaultTitle: "Danger"
1469
+ },
1470
+ tip: {
1471
+ icon: import_lucide_react3.Lightbulb,
1472
+ className: "bg-purple-500/10 border-purple-500/30 text-purple-900 dark:bg-purple-400/5 dark:border-purple-500/20 dark:text-purple-400",
1473
+ iconClassName: "text-purple-600 dark:text-purple-400",
1474
+ titleClassName: "text-purple-700 dark:text-purple-300",
1475
+ defaultTitle: "Tip"
1476
+ }
1477
+ };
1478
+ const config = configs[type];
1479
+ const Icon2 = config.icon;
1480
+ let _title = title || config.defaultTitle;
1481
+ let content = children;
1482
+ if (!title && children && typeof children === "object") {
1483
+ const childArray = Array.isArray(children) ? children : [children];
1484
+ const firstElement = childArray[0];
1485
+ if (firstElement && typeof firstElement === "object" && "props" in firstElement) {
1486
+ const props = firstElement.props;
1487
+ if (props.children && Array.isArray(props.children)) {
1488
+ const strongChild = props.children.find(
1489
+ (child) => child && typeof child === "object" && child.type === "strong"
1490
+ );
1491
+ if (strongChild) {
1492
+ _title = strongChild.props.children;
1493
+ content = childArray.map((child, idx) => {
1494
+ if (idx === 0 && typeof child === "object" && "props" in child) {
1495
+ const newChildren = child.props.children.filter((c) => c !== strongChild);
1496
+ return { ...child, props: { ...child.props, children: newChildren } };
1497
+ }
1498
+ return child;
1499
+ });
1500
+ }
1501
+ }
1502
+ }
1503
+ }
1504
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `flex gap-3 p-4 rounded-xl border my-2 ${config.className}`, children: [
1505
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex-shrink-0 mt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon2, { className: `h-5 w-5 ${config.iconClassName}` }) }),
1506
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex-1 space-y-0", children: [
1507
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `font-semibold text-sm ${config.titleClassName}`, children: _title }),
1508
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-sm leading-relaxed [&>p]:mb-0 [&>p]:text-current", children: content })
1509
+ ] })
1510
+ ] });
1511
+ }
1512
+
1513
+ // src/components/docs/card.tsx
1514
+ var import_lucide_react4 = require("lucide-react");
1515
+ var import_link2 = __toESM(require("next/link"));
1516
+
1517
+ // src/components/docs/icon.tsx
1518
+ var LucideIcons = __toESM(require("lucide-react"));
1519
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1520
+ function Icon({ icon, iconType = "regular", color, size = 20, className = "" }) {
1521
+ if (typeof icon !== "string") {
1522
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `inline-flex items-center ${className}`, style: { color }, children: icon });
1523
+ }
1524
+ if (icon.startsWith("http") || icon.startsWith("/")) {
1525
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1526
+ "img",
1527
+ {
1528
+ src: icon,
1529
+ alt: "",
1530
+ width: size,
1531
+ height: size,
1532
+ className: `inline-block ${className}`,
1533
+ style: { color }
1534
+ }
1535
+ );
1536
+ }
1537
+ if (icon.startsWith("fa-")) {
1538
+ const faClass = `fa-${iconType} ${icon}`;
1539
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1540
+ "i",
1541
+ {
1542
+ className: `${faClass} ${className}`,
1543
+ style: { fontSize: size, color },
1544
+ "aria-hidden": "true"
1545
+ }
1546
+ );
1547
+ }
1548
+ const iconName = icon.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
1549
+ const LucideIcon = LucideIcons[iconName];
1550
+ if (LucideIcon) {
1551
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1552
+ LucideIcon,
1553
+ {
1554
+ size,
1555
+ className: `inline-block ${className}`,
1556
+ style: { color },
1557
+ "aria-hidden": "true"
1558
+ }
1559
+ );
1560
+ }
1561
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: `inline-flex items-center font-mono text-xs ${className}`, style: { color }, children: [
1562
+ "[",
1563
+ icon,
1564
+ "]"
1565
+ ] });
1566
+ }
1567
+
1568
+ // src/components/docs/card.tsx
1569
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1570
+ function Card({ title, description, href, icon, children, external = false }) {
1571
+ const content = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-3", children: [
1572
+ icon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "shrink-0 w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center text-primary", children: typeof icon === "string" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { icon, size: 20 }) : icon }),
1573
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex-1 min-w-0", children: [
1574
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: `font-semibold text-foreground mb-1 no-underline ${href ? "group-hover:text-primary transition-colors" : ""}`, children: title }),
1575
+ description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-sm text-muted-foreground line-clamp-2 no-underline", children: description }),
1576
+ children && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mt-2 text-sm text-muted-foreground no-underline", children })
1577
+ ] }),
1578
+ href && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "shrink-0 self-start mt-1", children: external ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.ExternalLink, { className: "h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.ArrowRight, { className: "h-4 w-4 text-muted-foreground group-hover:text-primary group-hover:translate-x-1 transition-all" }) })
1579
+ ] }) });
1580
+ if (href) {
1581
+ const Component = external ? "a" : import_link2.default;
1582
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1583
+ Component,
1584
+ {
1585
+ href,
1586
+ className: "card-link group block p-4 rounded-xl border border-border hover:border-primary/50 hover:bg-muted/50 transition-all",
1587
+ ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
1588
+ children: content
1589
+ }
1590
+ );
1591
+ }
1592
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-4 rounded-xl border border-border bg-muted/30 no-underline", children: content });
1593
+ }
1594
+ function CardGrid({ children, cols = 2 }) {
1595
+ const gridCols = {
1596
+ 1: "grid-cols-1",
1597
+ 2: "grid-cols-1 md:grid-cols-2",
1598
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
1599
+ };
1600
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `grid ${gridCols[cols]} gap-4 my-6`, children });
1601
+ }
1602
+
1603
+ // src/components/docs/category-index.tsx
1604
+ var import_link4 = __toESM(require("next/link"));
1605
+ var import_lucide_react10 = require("lucide-react");
1606
+ var import_rsc = require("next-mdx-remote/rsc");
1607
+ var import_remark_gfm = __toESM(require("remark-gfm"));
1608
+
1609
+ // src/lib/remark-code-meta.ts
1610
+ function remarkCodeMeta() {
1611
+ return (tree) => {
1612
+ const visit = (node) => {
1613
+ if (node.type === "code" && node.meta) {
1614
+ node.data = node.data || {};
1615
+ node.data.hProperties = node.data.hProperties || {};
1616
+ node.data.hProperties.meta = node.meta;
1617
+ }
1618
+ if (node.children) {
1619
+ node.children.forEach(visit);
1620
+ }
1621
+ };
1622
+ visit(tree);
1623
+ };
1624
+ }
1625
+
1626
+ // src/components/docs/category-index.tsx
1627
+ var import_rehype_slug = __toESM(require("rehype-slug"));
1628
+
1629
+ // src/components/docs/code-block.tsx
1630
+ var import_react2 = require("react");
1631
+ var import_lucide_react5 = require("lucide-react");
1632
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1633
+ function CodeBlock({ code, language, filename }) {
1634
+ const [copied, setCopied] = (0, import_react2.useState)(false);
1635
+ const handleCopy = async () => {
1636
+ await navigator.clipboard.writeText(code);
1637
+ setCopied(true);
1638
+ setTimeout(() => setCopied(false), 2e3);
1639
+ };
1640
+ const highlightCode = (code2, lang) => {
1641
+ const lines = code2.split("\n");
1642
+ return lines.map((line, i) => {
1643
+ const tokens = [];
1644
+ let currentPos = 0;
1645
+ const patterns = [
1646
+ { type: "comment", regex: /(\/\/.*$|\/\*[\s\S]*?\*\/|#.*$)/ },
1647
+ { type: "string", regex: /("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)/ },
1648
+ {
1649
+ type: "keyword",
1650
+ regex: /\b(const|let|var|function|return|if|else|for|while|do|break|continue|switch|case|default|import|export|from|as|class|extends|implements|interface|type|enum|namespace|async|await|try|catch|finally|throw|new|this|super|static|public|private|protected|readonly|abstract|void|null|undefined|true|false|typeof|instanceof|delete|in|of)\b/
1651
+ },
1652
+ { type: "operator", regex: /([+\-*/%=<>!&|^~?:]+)/ },
1653
+ { type: "number", regex: /\b(0x[a-fA-F0-9]+|0b[01]+|\d+\.?\d*(?:e[+-]?\d+)?)\b/ },
1654
+ { type: "function", regex: /\b([a-zA-Z_$][\w$]*)\s*(?=\()/ },
1655
+ { type: "property", regex: /\.([a-zA-Z_$][\w$]*)/ },
1656
+ { type: "punctuation", regex: /([{}[\]();,])/ }
1657
+ ];
1658
+ while (currentPos < line.length) {
1659
+ let matched = false;
1660
+ for (const { type, regex } of patterns) {
1661
+ const match = line.slice(currentPos).match(regex);
1662
+ if (match && match.index === 0) {
1663
+ tokens.push({ type, value: match[0] });
1664
+ currentPos += match[0].length;
1665
+ matched = true;
1666
+ break;
1667
+ }
1668
+ }
1669
+ if (!matched) {
1670
+ const nextSpecialChar = line.slice(currentPos).search(/["'`/\w.+\-*/%=<>!&|^~?:;,()[\]{}#]/);
1671
+ if (nextSpecialChar === -1) {
1672
+ tokens.push({ type: "text", value: line.slice(currentPos) });
1673
+ break;
1674
+ } else if (nextSpecialChar > 0) {
1675
+ tokens.push({ type: "text", value: line.slice(currentPos, currentPos + nextSpecialChar) });
1676
+ currentPos += nextSpecialChar;
1677
+ } else {
1678
+ tokens.push({ type: "text", value: line[currentPos] });
1679
+ currentPos++;
1680
+ }
1681
+ }
1682
+ }
1683
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "table-row", children: [
1684
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "table-cell pr-4 text-right select-none text-muted-foreground/40 w-8 align-top", children: i + 1 }),
1685
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "table-cell align-top", children: tokens.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "\xA0" }) : tokens.map((token, j) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `token-${token.type}`, children: token.value }, j)) })
1686
+ ] }, i);
1687
+ });
1688
+ };
1689
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative group my-2", children: [
1690
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "bg-muted/50 dark:bg-muted/30 px-4 py-2 rounded-t-xl border border-b-0 border-border/50 flex items-center justify-between", children: [
1691
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-3", children: [
1692
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1693
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-3 h-3 rounded-full bg-red-500/80 dark:bg-red-500/60" }),
1694
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-3 h-3 rounded-full bg-yellow-500/80 dark:bg-yellow-500/60" }),
1695
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-3 h-3 rounded-full bg-green-500/80 dark:bg-green-500/60" })
1696
+ ] }),
1697
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-xs font-mono text-foreground", children: filename || "Code" })
1698
+ ] }),
1699
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1700
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-xs text-muted-foreground/60 font-mono uppercase tracking-wide", children: language }),
1701
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1702
+ "button",
1703
+ {
1704
+ onClick: handleCopy,
1705
+ className: "p-1.5 rounded-md hover:bg-muted/50 transition-colors",
1706
+ "aria-label": "Copy code",
1707
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Check, { className: "h-4 w-4 text-green-400" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Copy, { className: "h-4 w-4 text-muted-foreground" })
1708
+ }
1709
+ )
1710
+ ] })
1711
+ ] }),
1712
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-gray-200/50 dark:bg-[#0d1117] rounded-b-xl overflow-x-auto border border-border/50", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { className: "p-2 text-[13px] font-mono leading-relaxed text-gray-800 dark:text-gray-200", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: "table w-full", children: highlightCode(code, language) }) }) })
1713
+ ] });
1714
+ }
1715
+
1716
+ // src/components/docs/tabs.tsx
1717
+ var import_react3 = require("react");
1718
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1719
+ function Tab({ children }) {
1720
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children });
1721
+ }
1722
+ function Tabs({ children, defaultValue }) {
1723
+ const tabs = import_react3.Children.toArray(children).filter(import_react3.isValidElement);
1724
+ const firstTabLabel = tabs[0]?.props.label || "";
1725
+ const [activeTab, setActiveTab] = (0, import_react3.useState)(defaultValue || firstTabLabel);
1726
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "my-6", children: [
1727
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex items-center gap-1 border-b border-border mb-4", children: tabs.map((tab) => {
1728
+ const label = tab.props.label;
1729
+ const isActive = activeTab === label;
1730
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1731
+ "button",
1732
+ {
1733
+ onClick: () => setActiveTab(label),
1734
+ className: `px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px ${isActive ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground hover:border-border"}`,
1735
+ children: label
1736
+ },
1737
+ label
1738
+ );
1739
+ }) }),
1740
+ tabs.map((tab) => {
1741
+ const label = tab.props.label;
1742
+ if (activeTab !== label) return null;
1743
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "prose prose-slate dark:prose-invert max-w-none [&>*:first-child]:mt-0", children: tab.props.children }, label);
1744
+ })
1745
+ ] });
1746
+ }
1747
+
1748
+ // src/components/docs/image.tsx
1749
+ var import_image = __toESM(require("next/image"));
1750
+ var import_react4 = require("react");
1751
+ var import_lucide_react6 = require("lucide-react");
1752
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1753
+ function Image({ src, alt, caption, width, height, zoom = true }) {
1754
+ const [isZoomed, setIsZoomed] = (0, import_react4.useState)(false);
1755
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1756
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("figure", { className: "my-6", children: [
1757
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "relative group rounded-xl border border-border overflow-hidden bg-muted/30", children: [
1758
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1759
+ import_image.default,
1760
+ {
1761
+ src,
1762
+ alt,
1763
+ width: width || 1200,
1764
+ height: height || 675,
1765
+ className: "w-full h-auto"
1766
+ }
1767
+ ),
1768
+ zoom && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1769
+ "button",
1770
+ {
1771
+ onClick: () => setIsZoomed(true),
1772
+ className: "absolute top-3 right-3 p-2 rounded-md bg-background/80 backdrop-blur-sm border border-border opacity-0 group-hover:opacity-100 transition-opacity hover:bg-background",
1773
+ "aria-label": "Zoom image",
1774
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react6.ZoomIn, { className: "h-4 w-4 text-foreground" })
1775
+ }
1776
+ )
1777
+ ] }),
1778
+ caption && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("figcaption", { className: "mt-2 text-center text-sm text-muted-foreground italic", children: caption })
1779
+ ] }),
1780
+ isZoomed && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1781
+ "div",
1782
+ {
1783
+ className: "fixed inset-0 z-50 bg-background/95 backdrop-blur-sm flex items-center justify-center p-4",
1784
+ onClick: () => setIsZoomed(false),
1785
+ children: [
1786
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1787
+ "button",
1788
+ {
1789
+ onClick: () => setIsZoomed(false),
1790
+ className: "absolute top-4 right-4 p-2 rounded-md bg-muted hover:bg-muted/80 transition-colors",
1791
+ "aria-label": "Close",
1792
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react6.X, { className: "h-5 w-5 text-foreground" })
1793
+ }
1794
+ ),
1795
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-w-7xl max-h-[90vh] overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1796
+ import_image.default,
1797
+ {
1798
+ src,
1799
+ alt,
1800
+ width: width || 1920,
1801
+ height: height || 1080,
1802
+ className: "w-full h-auto"
1803
+ }
1804
+ ) })
1805
+ ]
1806
+ }
1807
+ )
1808
+ ] });
1809
+ }
1810
+
1811
+ // src/components/docs/video.tsx
1812
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1813
+ function Video({
1814
+ src,
1815
+ caption,
1816
+ autoplay = false,
1817
+ loop = false,
1818
+ muted = false,
1819
+ controls = true,
1820
+ poster
1821
+ }) {
1822
+ const isYouTube = src.includes("youtube.com") || src.includes("youtu.be");
1823
+ const isVimeo = src.includes("vimeo.com");
1824
+ const getYouTubeId = (url) => {
1825
+ const match = url.match(/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/);
1826
+ return match ? match[1] : null;
1827
+ };
1828
+ const getVimeoId = (url) => {
1829
+ const match = url.match(/vimeo\.com\/(\d+)/);
1830
+ return match ? match[1] : null;
1831
+ };
1832
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("figure", { className: "my-6", children: [
1833
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative rounded-xl border border-border overflow-hidden bg-muted/30", children: isYouTube ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative w-full", style: { paddingBottom: "56.25%" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1834
+ "iframe",
1835
+ {
1836
+ className: "absolute top-0 left-0 w-full h-full",
1837
+ src: `https://www.youtube.com/embed/${getYouTubeId(src)}${autoplay ? "?autoplay=1" : ""}`,
1838
+ title: "YouTube video",
1839
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
1840
+ allowFullScreen: true
1841
+ }
1842
+ ) }) : isVimeo ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative w-full", style: { paddingBottom: "56.25%" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1843
+ "iframe",
1844
+ {
1845
+ className: "absolute top-0 left-0 w-full h-full",
1846
+ src: `https://player.vimeo.com/video/${getVimeoId(src)}${autoplay ? "?autoplay=1" : ""}`,
1847
+ title: "Vimeo video",
1848
+ allow: "autoplay; fullscreen; picture-in-picture",
1849
+ allowFullScreen: true
1850
+ }
1851
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1852
+ "video",
1853
+ {
1854
+ src,
1855
+ controls,
1856
+ autoPlay: autoplay,
1857
+ loop,
1858
+ muted,
1859
+ poster,
1860
+ className: "w-full h-auto",
1861
+ children: "Your browser does not support the video tag."
1862
+ }
1863
+ ) }),
1864
+ caption && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("figcaption", { className: "mt-2 text-center text-sm text-muted-foreground italic", children: caption })
1865
+ ] });
1866
+ }
1867
+
1868
+ // src/components/docs/image-card.tsx
1869
+ var import_image2 = __toESM(require("next/image"));
1870
+ var import_link3 = __toESM(require("next/link"));
1871
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1872
+ function ImageCard({
1873
+ src,
1874
+ alt,
1875
+ title,
1876
+ description,
1877
+ href,
1878
+ external = false,
1879
+ aspectRatio = "video"
1880
+ }) {
1881
+ const aspectRatios = {
1882
+ square: "aspect-square",
1883
+ video: "aspect-video",
1884
+ portrait: "aspect-[3/4]"
1885
+ };
1886
+ const content = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-0 p-0", children: [
1887
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `w-full ${aspectRatios[aspectRatio]} overflow-hidden ${title || description ? "rounded-t-xl" : "rounded-xl"} bg-muted relative`, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1888
+ import_image2.default,
1889
+ {
1890
+ src,
1891
+ alt,
1892
+ fill: true,
1893
+ sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
1894
+ className: "object-cover transition-transform duration-300 group-hover:scale-105"
1895
+ }
1896
+ ) }),
1897
+ (title || description) && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "p-3 flex flex-col gap-1", children: [
1898
+ title && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { className: `font-semibold text-foreground mb-0 no-underline ${href ? "group-hover:text-primary transition-colors" : ""}`, children: title }),
1899
+ description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-sm text-muted-foreground line-clamp-2 no-underline mb-0", children: description })
1900
+ ] })
1901
+ ] });
1902
+ if (href) {
1903
+ const Component = external ? "a" : import_link3.default;
1904
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1905
+ Component,
1906
+ {
1907
+ href,
1908
+ className: "image-card-link group block rounded-xl border border-border hover:border-primary/50 hover:shadow-lg transition-all overflow-hidden p-0",
1909
+ ...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
1910
+ children: content
1911
+ }
1912
+ );
1913
+ }
1914
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "block rounded-xl border border-border overflow-hidden bg-card p-0", children: content });
1915
+ }
1916
+ function ImageCardGrid({ children, cols = 3 }) {
1917
+ const gridCols = {
1918
+ 1: "grid-cols-1",
1919
+ 2: "grid-cols-1 md:grid-cols-2",
1920
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
1921
+ 4: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4"
1922
+ };
1923
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: `grid ${gridCols[cols]} gap-4 my-6`, children });
1924
+ }
1925
+
1926
+ // src/components/docs/steps.tsx
1927
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1928
+ function Steps({ children }) {
1929
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "my-6 ml-4 space-y-6 [counter-reset:step]", children });
1930
+ }
1931
+ function Step({ title, children }) {
1932
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "relative pl-8 pb-6 border-l-2 border-border last:border-l-0 last:pb-0 [counter-increment:step] before:content-[counter(step)] before:absolute before:left-0 before:-translate-x-1/2 before:w-8 before:h-8 before:rounded-full before:bg-primary before:text-primary-foreground before:flex before:items-center before:justify-center before:text-sm before:font-semibold before:z-10", children: [
1933
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold text-foreground", children: title }) }),
1934
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "prose prose-sm dark:prose-invert max-w-none [&>*:last-child]:mb-0", children })
1935
+ ] });
1936
+ }
1937
+
1938
+ // src/components/docs/mermaid.tsx
1939
+ var import_react5 = require("react");
1940
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1941
+ function Mermaid({ chart, caption }) {
1942
+ const containerRef = (0, import_react5.useRef)(null);
1943
+ const [error, setError] = (0, import_react5.useState)(null);
1944
+ (0, import_react5.useEffect)(() => {
1945
+ const renderChart = async () => {
1946
+ try {
1947
+ const mermaid = (await import("mermaid")).default;
1948
+ mermaid.initialize({
1949
+ startOnLoad: false,
1950
+ theme: document.documentElement.classList.contains("dark") ? "dark" : "default",
1951
+ securityLevel: "loose",
1952
+ fontFamily: "inherit"
1953
+ });
1954
+ if (containerRef.current) {
1955
+ const id = `mermaid-${Math.random().toString(36).substr(2, 9)}`;
1956
+ const { svg } = await mermaid.render(id, chart);
1957
+ containerRef.current.innerHTML = svg;
1958
+ }
1959
+ } catch (err) {
1960
+ console.error("Mermaid rendering error:", err);
1961
+ setError(err instanceof Error ? err.message : "Failed to render diagram");
1962
+ }
1963
+ };
1964
+ renderChart();
1965
+ const observer = new MutationObserver((mutations) => {
1966
+ mutations.forEach((mutation) => {
1967
+ if (mutation.attributeName === "class") {
1968
+ renderChart();
1969
+ }
1970
+ });
1971
+ });
1972
+ observer.observe(document.documentElement, { attributes: true });
1973
+ return () => observer.disconnect();
1974
+ }, [chart]);
1975
+ if (error) {
1976
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "my-6 p-4 rounded-xl border border-red-500/50 bg-red-500/10", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "text-sm text-red-600 dark:text-red-400 font-mono", children: [
1977
+ "Mermaid Error: ",
1978
+ error
1979
+ ] }) });
1980
+ }
1981
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-6", children: [
1982
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1983
+ "div",
1984
+ {
1985
+ ref: containerRef,
1986
+ className: "flex justify-center items-center p-6 rounded-xl border border-border bg-muted/30 overflow-x-auto"
1987
+ }
1988
+ ),
1989
+ caption && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("figcaption", { className: "mt-2 text-center text-sm text-muted-foreground italic", children: caption })
1990
+ ] });
1991
+ }
1992
+
1993
+ // src/components/docs/math.tsx
1994
+ var import_react6 = require("react");
1995
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1996
+ function Math2({ children, block = false }) {
1997
+ const containerRef = (0, import_react6.useRef)(null);
1998
+ (0, import_react6.useEffect)(() => {
1999
+ const renderMath = async () => {
2000
+ try {
2001
+ const katex = (await import("katex")).default;
2002
+ if (containerRef.current) {
2003
+ katex.render(children, containerRef.current, {
2004
+ throwOnError: false,
2005
+ displayMode: block
2006
+ });
2007
+ }
2008
+ } catch (err) {
2009
+ console.error("KaTeX rendering error:", err);
2010
+ if (containerRef.current) {
2011
+ containerRef.current.textContent = children;
2012
+ }
2013
+ }
2014
+ };
2015
+ renderMath();
2016
+ }, [children, block]);
2017
+ if (block) {
2018
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2019
+ "div",
2020
+ {
2021
+ ref: containerRef,
2022
+ className: "my-6 overflow-x-auto text-center"
2023
+ }
2024
+ );
2025
+ }
2026
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { ref: containerRef, className: "inline-block" });
2027
+ }
2028
+
2029
+ // src/components/docs/columns.tsx
2030
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2031
+ function Columns({ children, cols = { sm: 1, md: 2, lg: 3 } }) {
2032
+ const colClasses = {
2033
+ 1: "grid-cols-1",
2034
+ 2: "grid-cols-2",
2035
+ 3: "grid-cols-3",
2036
+ 4: "grid-cols-4"
2037
+ };
2038
+ const smClass = cols.sm ? colClasses[cols.sm] : "grid-cols-1";
2039
+ const mdClass = cols.md ? `md:${colClasses[cols.md]}` : "";
2040
+ const lgClass = cols.lg ? `lg:${colClasses[cols.lg]}` : "";
2041
+ const xlClass = cols.xl ? `xl:${colClasses[cols.xl]}` : "";
2042
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: `grid ${smClass} ${mdClass} ${lgClass} ${xlClass} gap-4 my-6`, children });
2043
+ }
2044
+ function Column({ children, span = 1 }) {
2045
+ const spanClass = {
2046
+ 1: "col-span-1",
2047
+ 2: "col-span-2",
2048
+ 3: "col-span-3",
2049
+ 4: "col-span-4"
2050
+ };
2051
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: spanClass[span], children });
2052
+ }
2053
+
2054
+ // src/components/docs/tooltip.tsx
2055
+ var import_react7 = require("react");
2056
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2057
+ function Tooltip({ children, content, position = "top" }) {
2058
+ const [isVisible, setIsVisible] = (0, import_react7.useState)(false);
2059
+ const positions = {
2060
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
2061
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
2062
+ left: "right-full top-1/2 -translate-y-1/2 mr-2",
2063
+ right: "left-full top-1/2 -translate-y-1/2 ml-2"
2064
+ };
2065
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2066
+ "span",
2067
+ {
2068
+ className: "relative inline-flex underline decoration-dotted cursor-help",
2069
+ onMouseEnter: () => setIsVisible(true),
2070
+ onMouseLeave: () => setIsVisible(false),
2071
+ children: [
2072
+ children,
2073
+ isVisible && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2074
+ "span",
2075
+ {
2076
+ className: `absolute ${positions[position]} z-50 px-2 py-1 text-xs text-white bg-gray-900 dark:bg-gray-700 rounded whitespace-nowrap pointer-events-none`,
2077
+ children: content
2078
+ }
2079
+ )
2080
+ ]
2081
+ }
2082
+ );
2083
+ }
2084
+
2085
+ // src/components/docs/frame.tsx
2086
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2087
+ function Frame({ src, title = "Embedded content", height = 500, width = "100%" }) {
2088
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "my-6 rounded-xl border border-border overflow-hidden bg-muted/30", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2089
+ "iframe",
2090
+ {
2091
+ src,
2092
+ title,
2093
+ width,
2094
+ height,
2095
+ className: "w-full",
2096
+ loading: "lazy",
2097
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups"
2098
+ }
2099
+ ) });
2100
+ }
2101
+
2102
+ // src/components/docs/api/api-endpoint.tsx
2103
+ var import_react8 = require("react");
2104
+ var import_lucide_react7 = require("lucide-react");
2105
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2106
+ var methodColors = {
2107
+ GET: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
2108
+ POST: "bg-green-500/10 text-green-600 dark:text-green-400",
2109
+ PUT: "bg-orange-500/10 text-orange-600 dark:text-orange-400",
2110
+ PATCH: "bg-purple-500/10 text-purple-600 dark:text-purple-400",
2111
+ DELETE: "bg-red-500/10 text-red-600 dark:text-red-400"
2112
+ };
2113
+ function ApiEndpoint({ method, path: path3, summary, children, defaultOpen = false }) {
2114
+ const [isOpen, setIsOpen] = (0, import_react8.useState)(defaultOpen);
2115
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "not-prose mb-4 rounded-xl border border-border overflow-hidden", children: [
2116
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2117
+ "button",
2118
+ {
2119
+ onClick: () => setIsOpen(!isOpen),
2120
+ className: "w-full flex items-center gap-3 px-4 py-3 text-left bg-muted/30 hover:bg-muted/50 transition-colors",
2121
+ children: [
2122
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2123
+ "span",
2124
+ {
2125
+ className: cn(
2126
+ "text-xs font-semibold px-2 py-0.5 rounded",
2127
+ methodColors[method]
2128
+ ),
2129
+ children: method
2130
+ }
2131
+ ),
2132
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("code", { className: "text-sm font-mono", children: path3 }),
2133
+ summary && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-sm text-muted-foreground ml-auto mr-2", children: summary }),
2134
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2135
+ import_lucide_react7.ChevronDown,
2136
+ {
2137
+ className: cn(
2138
+ "h-5 w-5 text-muted-foreground transition-transform flex-shrink-0",
2139
+ isOpen ? "rotate-180" : ""
2140
+ )
2141
+ }
2142
+ )
2143
+ ]
2144
+ }
2145
+ ),
2146
+ isOpen && children && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "border-t border-border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "px-4 py-4 space-y-6", children }) })
2147
+ ] });
2148
+ }
2149
+
2150
+ // src/components/docs/api/api-params.tsx
2151
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2152
+ function ApiParams({ title = "Parameters", params }) {
2153
+ if (!params || params.length === 0) return null;
2154
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "mb-6", children: [
2155
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h4", { className: "text-sm font-semibold text-foreground mb-3", children: title }),
2156
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-3", children: params.map((param) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col gap-1", children: [
2157
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
2158
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { className: "text-sm font-mono text-foreground", children: param.name }),
2159
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-xs text-muted-foreground", children: param.type }),
2160
+ param.required && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-xs text-red-600 dark:text-red-400", children: "required" }),
2161
+ param.default && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
2162
+ "default: ",
2163
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("code", { className: "text-xs", children: param.default })
2164
+ ] })
2165
+ ] }),
2166
+ param.description && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-muted-foreground", children: param.description })
2167
+ ] }, param.name)) })
2168
+ ] });
2169
+ }
2170
+
2171
+ // src/components/docs/api/api-response.tsx
2172
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2173
+ var statusColors = {
2174
+ "2": "text-green-600 dark:text-green-400",
2175
+ "3": "text-blue-600 dark:text-blue-400",
2176
+ "4": "text-orange-600 dark:text-orange-400",
2177
+ "5": "text-red-600 dark:text-red-400"
2178
+ };
2179
+ function ApiResponse({ status, description, example, schema }) {
2180
+ const statusClass = statusColors[String(status)[0]] || "text-muted-foreground";
2181
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mb-4", children: [
2182
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [
2183
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: `text-sm font-semibold ${statusClass}`, children: status }),
2184
+ description && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-sm text-muted-foreground", children: description })
2185
+ ] }),
2186
+ example && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mb-3", children: [
2187
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs font-semibold text-muted-foreground mb-2", children: "Example Response" }),
2188
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2189
+ CodeBlock,
2190
+ {
2191
+ code: typeof example === "string" ? example : JSON.stringify(example, null, 2),
2192
+ language: "json"
2193
+ }
2194
+ )
2195
+ ] }),
2196
+ schema && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
2197
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs font-semibold text-muted-foreground mb-2", children: "Schema" }),
2198
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2199
+ CodeBlock,
2200
+ {
2201
+ code: typeof schema === "string" ? schema : JSON.stringify(schema, null, 2),
2202
+ language: "json"
2203
+ }
2204
+ )
2205
+ ] })
2206
+ ] });
2207
+ }
2208
+
2209
+ // src/components/docs/api/api-playground.tsx
2210
+ var import_react9 = require("react");
2211
+
2212
+ // src/components/ui/button.tsx
2213
+ var import_react_slot = require("@radix-ui/react-slot");
2214
+ var import_class_variance_authority = require("class-variance-authority");
2215
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2216
+ var buttonVariants = (0, import_class_variance_authority.cva)(
2217
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
2218
+ {
2219
+ variants: {
2220
+ variant: {
2221
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
2222
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
2223
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
2224
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
2225
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
2226
+ link: "text-primary underline-offset-4 hover:underline"
2227
+ },
2228
+ size: {
2229
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
2230
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
2231
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
2232
+ icon: "size-9",
2233
+ "icon-sm": "size-8",
2234
+ "icon-lg": "size-10"
2235
+ }
2236
+ },
2237
+ defaultVariants: {
2238
+ variant: "default",
2239
+ size: "default"
2240
+ }
2241
+ }
2242
+ );
2243
+ function Button({
2244
+ className,
2245
+ variant,
2246
+ size,
2247
+ asChild = false,
2248
+ ...props
2249
+ }) {
2250
+ const Comp = asChild ? import_react_slot.Slot : "button";
2251
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2252
+ Comp,
2253
+ {
2254
+ "data-slot": "button",
2255
+ className: cn(buttonVariants({ variant, size, className })),
2256
+ ...props
2257
+ }
2258
+ );
2259
+ }
2260
+
2261
+ // src/components/ui/input.tsx
2262
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2263
+ function Input({ className, type, ...props }) {
2264
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2265
+ "input",
2266
+ {
2267
+ type,
2268
+ "data-slot": "input",
2269
+ className: cn(
2270
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
2271
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
2272
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
2273
+ className
2274
+ ),
2275
+ ...props
2276
+ }
2277
+ );
2278
+ }
2279
+
2280
+ // src/components/ui/textarea.tsx
2281
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2282
+ function Textarea({ className, ...props }) {
2283
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2284
+ "textarea",
2285
+ {
2286
+ "data-slot": "textarea",
2287
+ className: cn(
2288
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
2289
+ className
2290
+ ),
2291
+ ...props
2292
+ }
2293
+ );
2294
+ }
2295
+
2296
+ // src/components/ui/badge.tsx
2297
+ var import_react_slot2 = require("@radix-ui/react-slot");
2298
+ var import_class_variance_authority2 = require("class-variance-authority");
2299
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2300
+ var badgeVariants = (0, import_class_variance_authority2.cva)(
2301
+ "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
2302
+ {
2303
+ variants: {
2304
+ variant: {
2305
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
2306
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
2307
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
2308
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
2309
+ }
2310
+ },
2311
+ defaultVariants: {
2312
+ variant: "default"
2313
+ }
2314
+ }
2315
+ );
2316
+ function Badge2({
2317
+ className,
2318
+ variant,
2319
+ asChild = false,
2320
+ ...props
2321
+ }) {
2322
+ const Comp = asChild ? import_react_slot2.Slot : "span";
2323
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2324
+ Comp,
2325
+ {
2326
+ "data-slot": "badge",
2327
+ className: cn(badgeVariants({ variant }), className),
2328
+ ...props
2329
+ }
2330
+ );
2331
+ }
2332
+
2333
+ // src/components/docs/api/api-playground.tsx
2334
+ var import_lucide_react8 = require("lucide-react");
2335
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2336
+ function ApiPlayground({
2337
+ method,
2338
+ path: path3,
2339
+ baseUrl = "",
2340
+ headers = {},
2341
+ defaultBody,
2342
+ pathParams = []
2343
+ }) {
2344
+ const [loading, setLoading] = (0, import_react9.useState)(false);
2345
+ const [response, setResponse] = (0, import_react9.useState)(null);
2346
+ const [error, setError] = (0, import_react9.useState)(null);
2347
+ const [requestBody, setRequestBody] = (0, import_react9.useState)(defaultBody || "");
2348
+ const initialHeaders = (0, import_react9.useMemo)(() => {
2349
+ const cleanHeaders = {};
2350
+ Object.entries(headers).forEach(([key, value]) => {
2351
+ cleanHeaders[key] = value || "";
2352
+ });
2353
+ return cleanHeaders;
2354
+ }, [headers]);
2355
+ const [requestHeaders, setRequestHeaders] = (0, import_react9.useState)(JSON.stringify(initialHeaders, null, 2));
2356
+ const extractedParams = (0, import_react9.useMemo)(() => {
2357
+ const params = {};
2358
+ const pathParamPattern = /:(\w+)/g;
2359
+ let match;
2360
+ while ((match = pathParamPattern.exec(path3)) !== null) {
2361
+ const paramName = match[1];
2362
+ const paramConfig = pathParams.find((p) => p.name === paramName);
2363
+ if (paramConfig?.example !== void 0) {
2364
+ params[paramName] = String(paramConfig.example);
2365
+ } else if (paramConfig?.type === "number") {
2366
+ params[paramName] = "1";
2367
+ } else {
2368
+ params[paramName] = "";
2369
+ }
2370
+ }
2371
+ return params;
2372
+ }, [path3, pathParams]);
2373
+ const [pathParamValues, setPathParamValues] = (0, import_react9.useState)(extractedParams);
2374
+ const buildUrl = () => {
2375
+ let finalPath = path3;
2376
+ Object.entries(pathParamValues).forEach(([key, value]) => {
2377
+ finalPath = finalPath.replace(`:${key}`, value);
2378
+ });
2379
+ return `${baseUrl}${finalPath}`;
2380
+ };
2381
+ const handleSend = async () => {
2382
+ setLoading(true);
2383
+ setError(null);
2384
+ setResponse(null);
2385
+ try {
2386
+ const url = buildUrl();
2387
+ const parsedHeaders = JSON.parse(requestHeaders);
2388
+ const options = {
2389
+ method,
2390
+ headers: {
2391
+ "Content-Type": "application/json",
2392
+ ...parsedHeaders
2393
+ }
2394
+ };
2395
+ if (method !== "GET" && method !== "DELETE" && requestBody) {
2396
+ options.body = requestBody;
2397
+ }
2398
+ const res = await fetch(url, options);
2399
+ const data = await res.json();
2400
+ setResponse({
2401
+ status: res.status,
2402
+ statusText: res.statusText,
2403
+ headers: Object.fromEntries(res.headers.entries()),
2404
+ body: data
2405
+ });
2406
+ } catch (err) {
2407
+ setError(err instanceof Error ? err.message : "An error occurred");
2408
+ } finally {
2409
+ setLoading(false);
2410
+ }
2411
+ };
2412
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "not-prose border border-border rounded-lg overflow-hidden bg-card/30", children: [
2413
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "bg-muted/50 px-4 py-2 border-b border-border", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h4", { className: "text-sm font-semibold text-foreground", children: "API Playground" }) }),
2414
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "p-4 space-y-4", children: [
2415
+ Object.keys(pathParamValues).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
2416
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-xs font-semibold text-muted-foreground mb-2 block", children: "Path Parameters" }),
2417
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "space-y-2", children: Object.entries(pathParamValues).map(([paramName, paramValue]) => {
2418
+ const paramConfig = pathParams.find((p) => p.name === paramName);
2419
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2", children: [
2420
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "text-xs text-muted-foreground min-w-[80px]", children: [
2421
+ ":",
2422
+ paramName
2423
+ ] }),
2424
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2425
+ Input,
2426
+ {
2427
+ value: paramValue,
2428
+ onChange: (e) => setPathParamValues((prev) => ({ ...prev, [paramName]: e.target.value })),
2429
+ placeholder: paramConfig?.example || paramConfig?.type || "value",
2430
+ className: "font-mono text-sm"
2431
+ }
2432
+ )
2433
+ ] }, paramName);
2434
+ }) })
2435
+ ] }),
2436
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
2437
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-xs font-semibold text-muted-foreground mb-2 block", children: "Request URL" }),
2438
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2", children: [
2439
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge2, { variant: "outline", className: "font-mono", children: method }),
2440
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Input, { value: buildUrl(), readOnly: true, className: "font-mono text-sm" })
2441
+ ] })
2442
+ ] }),
2443
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
2444
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-xs font-semibold text-muted-foreground mb-2 block", children: "Headers (JSON)" }),
2445
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2446
+ Textarea,
2447
+ {
2448
+ value: requestHeaders,
2449
+ onChange: (e) => setRequestHeaders(e.target.value),
2450
+ className: "font-mono text-sm",
2451
+ rows: 4
2452
+ }
2453
+ )
2454
+ ] }),
2455
+ method !== "GET" && method !== "DELETE" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
2456
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-xs font-semibold text-muted-foreground mb-2 block", children: "Request Body (JSON)" }),
2457
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2458
+ Textarea,
2459
+ {
2460
+ value: requestBody,
2461
+ onChange: (e) => setRequestBody(e.target.value),
2462
+ className: "font-mono text-sm",
2463
+ rows: 6,
2464
+ placeholder: '{\\n "key": "value"\\n}'
2465
+ }
2466
+ )
2467
+ ] }),
2468
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { onClick: handleSend, disabled: loading, className: "w-full", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
2469
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react8.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
2470
+ "Sending..."
2471
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
2472
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react8.Play, { className: "mr-2 h-4 w-4" }),
2473
+ "Send Request"
2474
+ ] }) }),
2475
+ response && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "mt-4", children: [
2476
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "text-xs font-semibold text-muted-foreground mb-2 block", children: [
2477
+ "Response (",
2478
+ response.status,
2479
+ " ",
2480
+ response.statusText,
2481
+ ")"
2482
+ ] }),
2483
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CodeBlock, { code: JSON.stringify(response.body, null, 2), language: "json" })
2484
+ ] }),
2485
+ error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "mt-4 p-3 bg-red-500/10 border border-red-500/20 rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: error }) })
2486
+ ] })
2487
+ ] });
2488
+ }
2489
+
2490
+ // src/components/docs/api/api-reference.tsx
2491
+ var import_react10 = require("react");
2492
+ var import_lucide_react9 = require("lucide-react");
2493
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2494
+ function ApiReference({ spec, parser = "auto", showPlayground = true }) {
2495
+ const [apiSpec, setApiSpec] = (0, import_react10.useState)(null);
2496
+ const [loading, setLoading] = (0, import_react10.useState)(true);
2497
+ const [error, setError] = (0, import_react10.useState)(null);
2498
+ (0, import_react10.useEffect)(() => {
2499
+ async function loadSpec() {
2500
+ try {
2501
+ const response = await fetch(spec);
2502
+ if (!response.ok) {
2503
+ throw new Error(`Failed to load API spec: ${response.statusText}`);
2504
+ }
2505
+ const data = await response.json();
2506
+ const parsedSpec = parseApiSpec(data, parser);
2507
+ setApiSpec(parsedSpec);
2508
+ } catch (err) {
2509
+ setError(err instanceof Error ? err.message : "Failed to load API spec");
2510
+ } finally {
2511
+ setLoading(false);
2512
+ }
2513
+ }
2514
+ loadSpec();
2515
+ }, [spec, parser]);
2516
+ const interpolateEnv = (text, env) => {
2517
+ if (!env) return text;
2518
+ return text.replace(/\{(\w+)\}/g, (match, key) => {
2519
+ return env[key] || match;
2520
+ });
2521
+ };
2522
+ if (loading) {
2523
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-center py-12", children: [
2524
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }),
2525
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "ml-2 text-muted-foreground", children: "Loading API specification..." })
2526
+ ] });
2527
+ }
2528
+ if (error) {
2529
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "rounded-lg border border-red-500/20 bg-red-500/10 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { className: "text-sm text-red-600 dark:text-red-400", children: [
2530
+ "Error: ",
2531
+ error
2532
+ ] }) });
2533
+ }
2534
+ if (!apiSpec) {
2535
+ return null;
2536
+ }
2537
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-6", children: [
2538
+ (apiSpec.title || apiSpec.description) && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mb-8", children: [
2539
+ apiSpec.title && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { className: "text-2xl font-semibold mb-2 text-foreground", children: apiSpec.title }),
2540
+ apiSpec.description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-muted-foreground", children: apiSpec.description }),
2541
+ apiSpec.baseUrl && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mt-4", children: [
2542
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm font-semibold text-muted-foreground mb-1", children: "Base URL" }),
2543
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("code", { className: "text-sm px-2 py-1 bg-muted rounded", children: apiSpec.baseUrl })
2544
+ ] })
2545
+ ] }),
2546
+ apiSpec.auth && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "rounded-lg border border-border bg-card/30 p-4 mb-6", children: [
2547
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "text-lg font-semibold mb-2 text-foreground", children: "Authentication" }),
2548
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground mb-2", children: apiSpec.auth.description || `This API uses ${apiSpec.auth.type} authentication.` }),
2549
+ apiSpec.auth.type === "bearer" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2550
+ CodeBlock,
2551
+ {
2552
+ code: `Authorization: ${apiSpec.auth.tokenPrefix || "Bearer"} {YOUR_TOKEN}`,
2553
+ language: "bash"
2554
+ }
2555
+ ),
2556
+ apiSpec.auth.type === "apiKey" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2557
+ CodeBlock,
2558
+ {
2559
+ code: `${apiSpec.auth.headerName || "X-API-Key"}: {YOUR_API_KEY}`,
2560
+ language: "bash"
2561
+ }
2562
+ )
2563
+ ] }),
2564
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Accordion, { type: "single", collapsible: true, className: "space-y-4", children: apiSpec.endpoints.map((endpoint, index) => {
2565
+ const allHeaders = [
2566
+ ...apiSpec.globalHeaders || [],
2567
+ ...endpoint.headers || []
2568
+ ].map((header) => ({
2569
+ ...header,
2570
+ value: interpolateEnv(header.value, apiSpec.env)
2571
+ }));
2572
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2573
+ AccordionItem,
2574
+ {
2575
+ value: `endpoint-${index}`,
2576
+ title: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-3", children: [
2577
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2578
+ "span",
2579
+ {
2580
+ className: `text-xs font-semibold px-2 py-0.5 rounded ${endpoint.method === "GET" ? "bg-blue-500/10 text-blue-600 dark:text-blue-400" : endpoint.method === "POST" ? "bg-green-500/10 text-green-600 dark:text-green-400" : endpoint.method === "PUT" ? "bg-orange-500/10 text-orange-600 dark:text-orange-400" : endpoint.method === "PATCH" ? "bg-purple-500/10 text-purple-600 dark:text-purple-400" : "bg-red-500/10 text-red-600 dark:text-red-400"}`,
2581
+ children: endpoint.method
2582
+ }
2583
+ ),
2584
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("code", { className: "text-sm font-mono", children: endpoint.path }),
2585
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-sm text-muted-foreground ml-auto", children: endpoint.title })
2586
+ ] }),
2587
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-6 pt-4", children: [
2588
+ endpoint.description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground", children: endpoint.description }),
2589
+ endpoint.pathParams && endpoint.pathParams.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ApiParams, { title: "Path Parameters", params: endpoint.pathParams }),
2590
+ endpoint.queryParams && endpoint.queryParams.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ApiParams, { title: "Query Parameters", params: endpoint.queryParams }),
2591
+ allHeaders.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
2592
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "text-sm font-semibold text-foreground mb-3", children: "Headers" }),
2593
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "space-y-2", children: allHeaders.map((header, idx) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-1", children: [
2594
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
2595
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("code", { className: "text-sm font-mono text-foreground", children: header.name }),
2596
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: header.value })
2597
+ ] }),
2598
+ header.description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground", children: header.description })
2599
+ ] }, idx)) })
2600
+ ] }),
2601
+ endpoint.body && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
2602
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "text-sm font-semibold text-foreground mb-3", children: "Request Body" }),
2603
+ endpoint.body.description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-sm text-muted-foreground mb-2", children: endpoint.body.description }),
2604
+ endpoint.body.example && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2605
+ CodeBlock,
2606
+ {
2607
+ code: typeof endpoint.body.example === "string" ? endpoint.body.example : JSON.stringify(endpoint.body.example, null, 2),
2608
+ language: "json"
2609
+ }
2610
+ )
2611
+ ] }),
2612
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
2613
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "text-sm font-semibold text-foreground mb-3", children: "Responses" }),
2614
+ endpoint.successResponse && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2615
+ ApiResponse,
2616
+ {
2617
+ status: endpoint.successResponse.status,
2618
+ description: endpoint.successResponse.description,
2619
+ example: endpoint.successResponse.example,
2620
+ schema: endpoint.successResponse.schema
2621
+ }
2622
+ ),
2623
+ endpoint.errorResponses?.map((response, idx) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2624
+ ApiResponse,
2625
+ {
2626
+ status: response.status,
2627
+ description: response.description,
2628
+ example: response.example,
2629
+ schema: response.schema
2630
+ },
2631
+ idx
2632
+ ))
2633
+ ] }),
2634
+ endpoint.examples && endpoint.examples.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
2635
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h4", { className: "text-sm font-semibold text-foreground mb-3", children: "Examples" }),
2636
+ endpoint.examples.map((example, idx) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mb-3", children: [
2637
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-xs font-semibold text-muted-foreground mb-2", children: example.title }),
2638
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CodeBlock, { code: example.code, language: example.language })
2639
+ ] }, idx))
2640
+ ] }),
2641
+ showPlayground && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2642
+ ApiPlayground,
2643
+ {
2644
+ method: endpoint.method,
2645
+ path: endpoint.path,
2646
+ baseUrl: apiSpec.baseUrl,
2647
+ headers: Object.fromEntries(allHeaders.map((h) => [h.name, h.value])),
2648
+ pathParams: endpoint.pathParams,
2649
+ defaultBody: endpoint.body?.example ? typeof endpoint.body.example === "string" ? endpoint.body.example : JSON.stringify(endpoint.body.example, null, 2) : void 0
2650
+ }
2651
+ )
2652
+ ] })
2653
+ },
2654
+ index
2655
+ );
2656
+ }) })
2657
+ ] });
2658
+ }
2659
+
2660
+ // src/components/docs/mdx-components.tsx
2661
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2662
+ var mdxComponents = {
2663
+ h1: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h1", { className: "text-3xl font-semibold tracking-tight mb-6 text-foreground", children }),
2664
+ h2: ({ children, id }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { id, className: "text-2xl font-semibold tracking-tight mt-10 mb-4 text-foreground scroll-mt-24", children }),
2665
+ h3: ({ children, id }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h3", { id, className: "text-xl font-medium tracking-tight mt-8 mb-3 text-foreground scroll-mt-24", children }),
2666
+ p: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-base leading-7 text-muted-foreground mb-4", children }),
2667
+ code: ({ children, className, meta, ...props }) => {
2668
+ const isInline = !className;
2669
+ if (isInline) {
2670
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("code", { className: "px-1.5 py-0.5 rounded-md bg-muted/50 text-primary font-mono text-[13px] border border-border/50", children });
2671
+ }
2672
+ const language = className?.replace("language-", "") || "text";
2673
+ const filename = meta || void 0;
2674
+ const code = String(children).replace(/\n$/, "");
2675
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CodeBlock, { code, language, filename });
2676
+ },
2677
+ pre: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children }),
2678
+ ul: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("ul", { className: "list-disc list-outside pl-5 space-y-2 mb-4 text-muted-foreground [&_p]:mb-0 [&_p]:inline [&_ul]:ml-6 [&_ol]:ml-6", children }),
2679
+ ol: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("ol", { className: "list-decimal list-outside pl-5 space-y-2 mb-4 text-muted-foreground [&_p]:mb-0 [&_p]:inline [&_ul]:ml-6 [&_ol]:ml-6", children }),
2680
+ li: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { className: "leading-7 [&>p]:mb-0 [&>p]:inline", children }),
2681
+ a: ({ children, href }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2682
+ "a",
2683
+ {
2684
+ href,
2685
+ className: "text-primary hover:underline font-medium",
2686
+ target: href?.startsWith("http") ? "_blank" : void 0,
2687
+ rel: href?.startsWith("http") ? "noopener noreferrer" : void 0,
2688
+ children
2689
+ }
2690
+ ),
2691
+ blockquote: ({ children }) => {
2692
+ const childrenArray = Array.isArray(children) ? children : [children];
2693
+ const firstChild = childrenArray[0];
2694
+ let textContent = "";
2695
+ if (firstChild && typeof firstChild === "object" && "props" in firstChild) {
2696
+ const props = firstChild.props;
2697
+ if (props.children) {
2698
+ const text = Array.isArray(props.children) ? props.children.join("") : String(props.children);
2699
+ textContent = text;
2700
+ }
2701
+ }
2702
+ const alertMatch = textContent.match(/^\[!(INFO|TIP|WARNING|SUCCESS|ERROR)\]/);
2703
+ if (alertMatch) {
2704
+ const type = alertMatch[1].toLowerCase();
2705
+ const processChildren = (node) => {
2706
+ if (typeof node === "string") {
2707
+ return node.replace(/^\[!(INFO|TIP|WARNING|SUCCESS|ERROR)\]\s*\n?/, "");
2708
+ }
2709
+ if (node && typeof node === "object" && "props" in node) {
2710
+ return {
2711
+ ...node,
2712
+ props: {
2713
+ ...node.props,
2714
+ children: Array.isArray(node.props.children) ? node.props.children.map(processChildren) : processChildren(node.props.children)
2715
+ }
2716
+ };
2717
+ }
2718
+ return node;
2719
+ };
2720
+ const cleanedChildren = Array.isArray(children) ? children.map(processChildren) : processChildren(children);
2721
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Callout, { type, children: cleanedChildren });
2722
+ }
2723
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("blockquote", { className: "border-l-4 border-primary/50 bg-muted/30 pl-4 pr-4 py-3 my-6 rounded-r-lg", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "text-muted-foreground italic [&>p]:mb-0", children }) });
2724
+ },
2725
+ table: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "overflow-x-auto mb-6 rounded-xl border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("table", { className: "min-w-full border-collapse", children }) }),
2726
+ th: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("th", { className: "border-b border-r border-border bg-muted px-4 py-2 text-left font-semibold text-foreground last:border-r-0", children }),
2727
+ td: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("td", { className: "border-b border-r border-border px-4 py-2 text-muted-foreground last:border-r-0", children }),
2728
+ // Custom components
2729
+ Callout,
2730
+ Accordion,
2731
+ AccordionItem,
2732
+ Tabs,
2733
+ Tab,
2734
+ Image,
2735
+ Video,
2736
+ Card,
2737
+ CardGrid,
2738
+ ImageCard,
2739
+ ImageCardGrid,
2740
+ Steps,
2741
+ Step,
2742
+ Icon,
2743
+ Mermaid,
2744
+ Math: Math2,
2745
+ Columns,
2746
+ Column,
2747
+ Badge,
2748
+ Tooltip,
2749
+ Frame,
2750
+ // API Documentation components
2751
+ ApiEndpoint,
2752
+ ApiParams,
2753
+ ApiResponse,
2754
+ ApiPlayground,
2755
+ ApiReference
2756
+ };
2757
+
2758
+ // src/components/docs/category-index.tsx
2759
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2760
+ function CategoryIndex({ categoryPath, version, allDocs, title, description, content, config }) {
2761
+ const childDocs = allDocs.filter((doc) => {
2762
+ const parts = doc.slug.split("/");
2763
+ const docParent = parts.slice(0, -1).join("/");
2764
+ return docParent === categoryPath && doc.slug !== categoryPath;
2765
+ });
2766
+ const processedContent = () => {
2767
+ if (content) {
2768
+ return processContentWithEnv(content, config);
2769
+ }
2770
+ return "";
2771
+ };
2772
+ const sortedDocs = sortSidebarItems(childDocs);
2773
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex-1 min-w-0", children: [
2774
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "mb-8", children: [
2775
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h1", { className: "text-4xl font-bold tracking-tight mb-3 text-foreground", children: title }),
2776
+ description && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-lg text-muted-foreground leading-relaxed", children: description }),
2777
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "prose prose-slate dark:prose-invert max-w-none prose-headings:scroll-mt-24 prose-headings:font-semibold prose-h1:text-4xl prose-h2:text-3xl prose-h2:mt-12 prose-h2:mb-4 prose-h3:text-2xl prose-h3:mt-8 prose-h3:mb-3 prose-p:text-base prose-p:leading-7 prose-p:text-muted-foreground prose-p:mb-4 prose-a:font-normal prose-a:transition-all prose-code:text-primary prose-code:bg-muted/50 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded-md prose-code:text-[13px] prose-code:font-mono prose-code:border prose-code:border-border/50 prose-code:before:content-none prose-code:after:content-none prose-pre:bg-transparent prose-pre:p-0 prose-ul:list-disc prose-ul:list-inside prose-ul:space-y-2 prose-ul:mb-4 prose-ol:list-decimal prose-ol:list-inside prose-ol:space-y-2 prose-ol:mb-4 prose-li:leading-7 prose-li:text-muted-foreground prose-strong:text-foreground prose-strong:font-semibold", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2778
+ import_rsc.MDXRemote,
2779
+ {
2780
+ source: processedContent(),
2781
+ options: {
2782
+ parseFrontmatter: false,
2783
+ mdxOptions: {
2784
+ remarkPlugins: [import_remark_gfm.default, remarkCodeMeta],
2785
+ rehypePlugins: [import_rehype_slug.default],
2786
+ development: false
2787
+ }
2788
+ },
2789
+ components: mdxComponents
2790
+ }
2791
+ ) })
2792
+ ] }),
2793
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-4", children: sortedDocs.map((doc) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2794
+ import_link4.default,
2795
+ {
2796
+ href: `/docs/${version}/${doc.slug}`,
2797
+ className: "group block p-5 rounded-xl border border-border bg-card hover:bg-accent hover:border-primary/50 transition-all duration-200",
2798
+ style: {
2799
+ textDecoration: "none !important"
2800
+ },
2801
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
2802
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex-1 min-w-0", children: [
2803
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [
2804
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react10.FileText, { className: "h-6 w-6 text-primary shrink-0" }),
2805
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h3", { className: "text-lg font-semibold text-foreground group-hover:text-primary transition-colors", children: doc.meta.title || doc.title })
2806
+ ] }),
2807
+ doc.meta.description && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm text-muted-foreground line-clamp-2", children: doc.meta.description }),
2808
+ doc.meta.reading_time && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("p", { className: "text-xs text-muted-foreground mt-2", children: [
2809
+ doc.meta.reading_time,
2810
+ " min read"
2811
+ ] })
2812
+ ] }),
2813
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react10.ChevronRight, { className: "h-5 w-5 text-muted-foreground group-hover:text-primary group-hover:translate-x-1 transition-all flex-shrink-0 mt-1" })
2814
+ ] })
2815
+ },
2816
+ doc.slug
2817
+ )) }),
2818
+ sortedDocs.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "text-center py-12 text-muted-foreground", children: [
2819
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react10.FileText, { className: "h-12 w-12 mx-auto mb-3 opacity-50" }),
2820
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { children: "No documents found in this category." })
2821
+ ] })
2822
+ ] });
2823
+ }
2824
+
2825
+ // src/components/docs/componentTextProps.ts
2826
+ var COMPONENT_TEXT_PROPS = {
2827
+ // Accordion components
2828
+ Accordion: ["title"],
2829
+ AccordionItem: ["title"],
2830
+ // Alert/Callout components
2831
+ Alert: ["title", "description"],
2832
+ Banner: ["title"],
2833
+ Callout: ["title", "content"],
2834
+ Note: ["title"],
2835
+ Warning: ["title", "text"],
2836
+ // Navigation components
2837
+ BreadCrumb: ["title", "slug", "version"],
2838
+ // Card components
2839
+ Card: ["title", "description"],
2840
+ ImageCard: ["title", "description", "alt"],
2841
+ // Media components
2842
+ Image: ["alt", "caption"],
2843
+ Video: ["caption"],
2844
+ Frame: ["title"],
2845
+ Mermaid: ["caption"],
2846
+ // Interactive components
2847
+ Tooltip: ["content"],
2848
+ // Code components
2849
+ CodeBlock: ["filename"],
2850
+ // Step components
2851
+ Step: ["title"]
2852
+ };
2853
+ function extractComponentPropsText(mdx) {
2854
+ return mdx.replace(
2855
+ /<([A-Z][\w]*)\b([^/>]*)\/>/g,
2856
+ (_, component, props) => {
2857
+ const searchableProps = COMPONENT_TEXT_PROPS[component];
2858
+ if (!searchableProps) return " ";
2859
+ let extracted = "";
2860
+ for (const prop of searchableProps) {
2861
+ const match = props.match(
2862
+ new RegExp(`${prop}="([^"]+)"`, "i")
2863
+ );
2864
+ if (match) {
2865
+ extracted += " " + match[1];
2866
+ }
2867
+ }
2868
+ return extracted || " ";
2869
+ }
2870
+ );
2871
+ }
2872
+ function extractSearchText(mdx) {
2873
+ return extractComponentPropsText(mdx).replace(/```[\s\S]*?```/g, " ").replace(/<([A-Z][\w]*)\b[^>]*>[\s\S]*?<\/\1>/g, " ").replace(/<\/?[A-Za-z][^>]*>/g, " ").replace(/`[^`]+`/g, " ").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[#>*_~=-]+/g, " ").replace(/\s+/g, " ").trim().slice(0, 1e3);
2874
+ }
2875
+
2876
+ // src/components/docs/dev-mode-badge.tsx
2877
+ var import_react11 = require("react");
2878
+ var import_lucide_react11 = require("lucide-react");
2879
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2880
+ function DevModeBadge() {
2881
+ const [isConnected, setIsConnected] = (0, import_react11.useState)(true);
2882
+ (0, import_react11.useEffect)(() => {
2883
+ if (process.env.NODE_ENV !== "development") return;
2884
+ const checkConnection = () => {
2885
+ setIsConnected(navigator.onLine);
2886
+ };
2887
+ window.addEventListener("online", checkConnection);
2888
+ window.addEventListener("offline", checkConnection);
2889
+ return () => {
2890
+ window.removeEventListener("online", checkConnection);
2891
+ window.removeEventListener("offline", checkConnection);
2892
+ };
2893
+ }, []);
2894
+ if (process.env.NODE_ENV !== "development") return null;
2895
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "fixed top-20 left-4 z-40 flex items-center gap-2 px-3 py-1.5 bg-orange-500/10 text-orange-600 dark:text-orange-400 border border-orange-500/20 rounded-full text-xs font-medium", children: [
2896
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react11.Code2, { className: "h-3 w-3" }),
2897
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Dev Mode" }),
2898
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: `h-2 w-2 rounded-full ${isConnected ? "bg-green-500" : "bg-red-500"} animate-pulse` })
2899
+ ] });
2900
+ }
2901
+
2902
+ // src/components/docs/doc-layout.tsx
2903
+ var import_lucide_react16 = require("lucide-react");
2904
+ var import_rsc2 = require("next-mdx-remote/rsc");
2905
+ var import_remark_gfm2 = __toESM(require("remark-gfm"));
2906
+ var import_rehype_slug2 = __toESM(require("rehype-slug"));
2907
+
2908
+ // src/components/docs/doc-navigation.tsx
2909
+ var import_link5 = __toESM(require("next/link"));
2910
+ var import_lucide_react12 = require("lucide-react");
2911
+ var import_jsx_runtime30 = require("react/jsx-runtime");
2912
+ function DocNavigation({ previousDoc, nextDoc, version }) {
2913
+ if (!previousDoc && !nextDoc) return null;
2914
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "mt-12 pt-8 border-t border-border grid grid-cols-2 gap-4", children: [
2915
+ previousDoc ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
2916
+ import_link5.default,
2917
+ {
2918
+ href: `/docs/${version}/${previousDoc.slug}`,
2919
+ className: "group flex flex-col gap-2 p-4 rounded-xl border border-border hover:border-primary/50 hover:bg-muted/50 transition-all",
2920
+ style: {
2921
+ textDecoration: "none !important"
2922
+ },
2923
+ children: [
2924
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
2925
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react12.ChevronLeft, { className: "h-4 w-4" }),
2926
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Previous" })
2927
+ ] }),
2928
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "text-base font-medium text-foreground group-hover:text-primary transition-colors", children: previousDoc.title })
2929
+ ]
2930
+ }
2931
+ ) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", {}),
2932
+ nextDoc ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
2933
+ import_link5.default,
2934
+ {
2935
+ href: `/docs/${version}/${nextDoc.slug}`,
2936
+ className: "group flex flex-col gap-2 p-4 rounded-xl border border-border hover:border-primary/50 hover:bg-muted/50 transition-all text-right",
2937
+ style: {
2938
+ textDecoration: "none !important"
2939
+ },
2940
+ children: [
2941
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-end gap-2 text-sm text-muted-foreground", children: [
2942
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Next" }),
2943
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react12.ChevronRight, { className: "h-4 w-4" })
2944
+ ] }),
2945
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "text-base font-medium text-foreground group-hover:text-primary transition-colors", children: nextDoc.title })
2946
+ ]
2947
+ }
2948
+ ) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", {})
2949
+ ] });
2950
+ }
2951
+
2952
+ // src/components/docs/doc-metadata.tsx
2953
+ var import_lucide_react13 = require("lucide-react");
2954
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2955
+ function DocMetadata({ meta, config }) {
2956
+ const showReadingTime = config.features?.showReadingTime && meta.reading_time;
2957
+ const showLastUpdated = config.features?.showLastUpdated && meta.last_updated;
2958
+ const showAuthors = config.features?.showAuthors && meta.authors?.length;
2959
+ const hasMetadata = showReadingTime || showLastUpdated || showAuthors;
2960
+ if (!hasMetadata) {
2961
+ return null;
2962
+ }
2963
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-wrap items-center gap-4 text-sm text-muted-foreground border-b border-border pb-4 mb-6", children: [
2964
+ showReadingTime && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2965
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react13.Clock, { className: "h-4 w-4" }),
2966
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { children: [
2967
+ meta.reading_time,
2968
+ " min read"
2969
+ ] })
2970
+ ] }),
2971
+ showLastUpdated && meta.last_updated && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2972
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react13.Calendar, { className: "h-4 w-4" }),
2973
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { children: [
2974
+ "Updated ",
2975
+ new Date(meta.last_updated).toLocaleDateString()
2976
+ ] })
2977
+ ] }),
2978
+ showAuthors && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2979
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react13.User, { className: "h-4 w-4" }),
2980
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: meta.authors.map((author, idx) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { children: [
2981
+ author.name || author.id,
2982
+ idx < meta.authors.length - 1 && ", "
2983
+ ] }, author.id)) })
2984
+ ] })
2985
+ ] });
2986
+ }
2987
+
2988
+ // src/components/docs/draft-badge.tsx
2989
+ var import_lucide_react14 = require("lucide-react");
2990
+ var import_jsx_runtime32 = require("react/jsx-runtime");
2991
+ function DraftBadge() {
2992
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "inline-flex items-center gap-2 px-3 py-1.5 rounded-md bg-yellow-500/10 border border-yellow-500/20 text-yellow-600 dark:text-yellow-400 text-sm font-medium mb-4", children: [
2993
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react14.FileWarning, { className: "h-4 w-4" }),
2994
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Draft - Not visible in production" })
2995
+ ] });
2996
+ }
2997
+
2998
+ // src/components/docs/doc-tags.tsx
2999
+ var import_lucide_react15 = require("lucide-react");
3000
+ var import_jsx_runtime33 = require("react/jsx-runtime");
3001
+ function DocTags({ tags }) {
3002
+ if (!tags || tags.length === 0) {
3003
+ return null;
3004
+ }
3005
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-wrap items-center gap-2 mt-6 pt-6 border-t border-border", children: [
3006
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react15.Tag, { className: "h-4 w-4 text-muted-foreground" }),
3007
+ tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3008
+ "span",
3009
+ {
3010
+ className: "inline-flex items-center px-2.5 py-0.5 rounded-md text-xs font-medium bg-primary/10 text-primary border border-primary/20",
3011
+ children: tag
3012
+ },
3013
+ tag
3014
+ ))
3015
+ ] });
3016
+ }
3017
+
3018
+ // src/components/docs/search-highlight.tsx
3019
+ var import_react12 = require("react");
3020
+ var import_navigation = require("next/navigation");
3021
+ function SearchHighlight() {
3022
+ const searchParams = (0, import_navigation.useSearchParams)();
3023
+ const query = searchParams.get("q");
3024
+ (0, import_react12.useEffect)(() => {
3025
+ if (!query) {
3026
+ document.querySelectorAll("mark.search-highlight").forEach((mark) => {
3027
+ const parent = mark.parentNode;
3028
+ if (parent) {
3029
+ parent.replaceChild(document.createTextNode(mark.textContent || ""), mark);
3030
+ parent.normalize();
3031
+ }
3032
+ });
3033
+ return;
3034
+ }
3035
+ const timeout = setTimeout(() => {
3036
+ highlightSearchTerm(query);
3037
+ }, 100);
3038
+ return () => {
3039
+ clearTimeout(timeout);
3040
+ document.querySelectorAll("mark.search-highlight").forEach((mark) => {
3041
+ const parent = mark.parentNode;
3042
+ if (parent) {
3043
+ parent.replaceChild(document.createTextNode(mark.textContent || ""), mark);
3044
+ parent.normalize();
3045
+ }
3046
+ });
3047
+ };
3048
+ }, [query]);
3049
+ return null;
3050
+ }
3051
+ function highlightSearchTerm(searchTerm) {
3052
+ document.querySelectorAll("mark.search-highlight").forEach((mark) => {
3053
+ const parent = mark.parentNode;
3054
+ if (parent) {
3055
+ parent.replaceChild(document.createTextNode(mark.textContent || ""), mark);
3056
+ parent.normalize();
3057
+ }
3058
+ });
3059
+ const contentArea = document.querySelector("main") || document.body;
3060
+ const walker = document.createTreeWalker(
3061
+ contentArea,
3062
+ NodeFilter.SHOW_TEXT,
3063
+ {
3064
+ acceptNode: (node) => {
3065
+ const parent = node.parentElement;
3066
+ if (!parent) return NodeFilter.FILTER_REJECT;
3067
+ const tagName = parent.tagName.toLowerCase();
3068
+ if (["mark", "script", "style", "code", "pre"].includes(tagName)) {
3069
+ return NodeFilter.FILTER_REJECT;
3070
+ }
3071
+ if (node.textContent && node.textContent.toLowerCase().includes(searchTerm.toLowerCase())) {
3072
+ return NodeFilter.FILTER_ACCEPT;
3073
+ }
3074
+ return NodeFilter.FILTER_REJECT;
3075
+ }
3076
+ }
3077
+ );
3078
+ const nodesToHighlight = [];
3079
+ let currentNode;
3080
+ while (currentNode = walker.nextNode()) {
3081
+ if (currentNode.textContent) {
3082
+ nodesToHighlight.push({
3083
+ node: currentNode,
3084
+ text: currentNode.textContent
3085
+ });
3086
+ }
3087
+ }
3088
+ nodesToHighlight.forEach(({ node, text }) => {
3089
+ const regex = new RegExp(`(${escapeRegex(searchTerm)})`, "gi");
3090
+ const parts = text.split(regex);
3091
+ if (parts.length > 1) {
3092
+ const fragment = document.createDocumentFragment();
3093
+ parts.forEach((part) => {
3094
+ if (part.toLowerCase() === searchTerm.toLowerCase()) {
3095
+ const mark = document.createElement("mark");
3096
+ mark.className = "search-highlight bg-yellow-200 dark:bg-yellow-900/50 text-foreground px-1 rounded";
3097
+ mark.textContent = part;
3098
+ fragment.appendChild(mark);
3099
+ } else if (part) {
3100
+ fragment.appendChild(document.createTextNode(part));
3101
+ }
3102
+ });
3103
+ node.parentNode?.replaceChild(fragment, node);
3104
+ }
3105
+ });
3106
+ const firstHighlight = document.querySelector("mark.search-highlight");
3107
+ if (firstHighlight) {
3108
+ setTimeout(() => {
3109
+ firstHighlight.scrollIntoView({ behavior: "smooth", block: "center" });
3110
+ }, 200);
3111
+ }
3112
+ }
3113
+ function escapeRegex(string) {
3114
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3115
+ }
3116
+
3117
+ // src/components/docs/doc-layout.tsx
3118
+ var import_jsx_runtime34 = require("react/jsx-runtime");
3119
+ async function DocLayout({ content, meta, previousDoc, nextDoc, version, slug, config }) {
3120
+ const isDevelopment3 = process.env.NODE_ENV === "development";
3121
+ const processedContent = processContentWithEnv(content, config);
3122
+ const editUrl = config.features?.editUrl && typeof config.features.editUrl === "string" ? `${config.features.editUrl}/${version}/${slug}.mdx` : null;
3123
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("article", { className: "flex-1 min-w-0", children: [
3124
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(SearchHighlight, {}),
3125
+ config.navigation?.showBreadcrumbs && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Breadcrumb, { version, slug, title: meta.title }),
3126
+ isDevelopment3 && meta.draft && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DraftBadge, {}),
3127
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "mb-8", children: [
3128
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h1", { className: "text-4xl font-bold tracking-tight mb-3 text-foreground", children: meta.title }),
3129
+ meta.description && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "text-lg text-muted-foreground leading-relaxed", children: meta.description })
3130
+ ] }),
3131
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DocMetadata, { meta, config }),
3132
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "prose prose-slate dark:prose-invert max-w-none prose-headings:scroll-mt-24 prose-headings:font-semibold prose-h1:text-4xl prose-h2:text-3xl prose-h2:mt-12 prose-h2:mb-4 prose-h3:text-2xl prose-h3:mt-8 prose-h3:mb-3 prose-p:text-base prose-p:leading-7 prose-p:text-muted-foreground prose-p:mb-4 prose-a:font-normal prose-a:transition-all prose-code:text-primary prose-code:bg-muted/50 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded-md prose-code:text-[13px] prose-code:font-mono prose-code:border prose-code:border-border/50 prose-code:before:content-none prose-code:after:content-none prose-pre:bg-transparent prose-pre:p-0 prose-ul:list-disc prose-ul:list-inside prose-ul:space-y-2 prose-ul:mb-4 prose-ol:list-decimal prose-ol:list-inside prose-ol:space-y-2 prose-ol:mb-4 prose-li:leading-7 prose-li:text-muted-foreground prose-strong:text-foreground prose-strong:font-semibold", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3133
+ import_rsc2.MDXRemote,
3134
+ {
3135
+ source: processedContent,
3136
+ options: {
3137
+ parseFrontmatter: false,
3138
+ mdxOptions: {
3139
+ remarkPlugins: [import_remark_gfm2.default, remarkCodeMeta],
3140
+ rehypePlugins: [import_rehype_slug2.default],
3141
+ development: false
3142
+ }
3143
+ },
3144
+ components: mdxComponents
3145
+ }
3146
+ ) }),
3147
+ config.features?.showTags && meta.tags && meta.tags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DocTags, { tags: meta.tags }),
3148
+ (editUrl || config.social?.github) && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "mt-12 pt-6 border-t border-border flex items-center justify-between", children: [
3149
+ editUrl ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
3150
+ "a",
3151
+ {
3152
+ href: editUrl,
3153
+ target: "_blank",
3154
+ rel: "noopener noreferrer",
3155
+ className: "flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors",
3156
+ children: [
3157
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react16.FileEdit, { className: "h-4 w-4" }),
3158
+ "Edit this page"
3159
+ ]
3160
+ }
3161
+ ) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", {}),
3162
+ config.social?.github && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
3163
+ "a",
3164
+ {
3165
+ href: `${config.social.github}/issues/new`,
3166
+ target: "_blank",
3167
+ rel: "noopener noreferrer",
3168
+ className: "flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors",
3169
+ children: [
3170
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react16.ExternalLink, { className: "h-4 w-4" }),
3171
+ "Report an issue"
3172
+ ]
3173
+ }
3174
+ )
3175
+ ] }),
3176
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DocNavigation, { previousDoc, nextDoc, version })
3177
+ ] });
3178
+ }
3179
+
3180
+ // src/components/docs/doc-layout-wrapper.tsx
3181
+ var import_react17 = require("react");
3182
+
3183
+ // src/components/docs/mobile-doc-layout.tsx
3184
+ var import_react15 = require("react");
3185
+
3186
+ // src/components/docs/footer.tsx
3187
+ var import_link6 = __toESM(require("next/link"));
3188
+ var import_jsx_runtime35 = require("react/jsx-runtime");
3189
+ function Footer({ config }) {
3190
+ if (!config.footer) {
3191
+ return null;
3192
+ }
3193
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("footer", { className: "bg-muted/30 dark:bg-muted/10 rounded-2xl mt-24", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "px-6 py-12", children: [
3194
+ config.footer.links && config.footer.links.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "grid grid-cols-2 md:grid-cols-4 gap-8 mb-8", children: config.footer.links.map((column, idx) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
3195
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h3", { className: "font-semibold text-foreground mb-4", children: column.title }),
3196
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "space-y-2", children: column.items.map((item, itemIdx) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3197
+ import_link6.default,
3198
+ {
3199
+ href: item.href,
3200
+ className: "text-sm text-muted-foreground hover:text-foreground transition-colors",
3201
+ children: item.label
3202
+ }
3203
+ ) }, itemIdx)) })
3204
+ ] }, idx)) }),
3205
+ config.footer.copyright && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "pt-8", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-sm text-muted-foreground text-center", children: config.footer.copyright }) })
3206
+ ] }) });
3207
+ }
3208
+
3209
+ // src/components/docs/site-banner.tsx
3210
+ var import_lucide_react17 = require("lucide-react");
3211
+ var import_react13 = require("react");
3212
+ var import_jsx_runtime36 = require("react/jsx-runtime");
3213
+ function SiteBanner({ config }) {
3214
+ const [dismissed, setDismissed] = (0, import_react13.useState)(false);
3215
+ const [mounted, setMounted] = (0, import_react13.useState)(false);
3216
+ const banner = config.banner;
3217
+ const storageKey = "site-banner-dismissed";
3218
+ (0, import_react13.useEffect)(() => {
3219
+ setMounted(true);
3220
+ const isDismissed = localStorage.getItem(storageKey) === "true";
3221
+ setDismissed(isDismissed);
3222
+ }, []);
3223
+ const handleDismiss = () => {
3224
+ setDismissed(true);
3225
+ localStorage.setItem(storageKey, "true");
3226
+ };
3227
+ if (!mounted || !banner || !banner.enabled || dismissed) {
3228
+ return null;
3229
+ }
3230
+ const typeConfig = {
3231
+ info: {
3232
+ icon: import_lucide_react17.Info,
3233
+ bg: "bg-blue-500/10 dark:bg-blue-400/5",
3234
+ border: "border-blue-500/30 dark:border-blue-500/20",
3235
+ iconColor: "text-blue-600 dark:text-blue-400",
3236
+ textColor: "text-blue-900 dark:text-blue-300"
3237
+ },
3238
+ success: {
3239
+ icon: import_lucide_react17.CheckCircle,
3240
+ bg: "bg-green-500/10 dark:bg-green-400/5",
3241
+ border: "border-green-500/30 dark:border-green-500/20",
3242
+ iconColor: "text-green-600 dark:text-green-400",
3243
+ textColor: "text-green-900 dark:text-green-300"
3244
+ },
3245
+ warning: {
3246
+ icon: import_lucide_react17.AlertCircle,
3247
+ bg: "bg-yellow-500/10 dark:bg-yellow-400/5",
3248
+ border: "border-yellow-500/30 dark:border-yellow-500/20",
3249
+ iconColor: "text-yellow-600 dark:text-yellow-400",
3250
+ textColor: "text-yellow-900 dark:text-yellow-300"
3251
+ },
3252
+ error: {
3253
+ icon: import_lucide_react17.XCircle,
3254
+ bg: "bg-red-500/10 dark:bg-red-400/5",
3255
+ border: "border-red-500/30 dark:border-red-500/20",
3256
+ iconColor: "text-red-600 dark:text-red-400",
3257
+ textColor: "text-red-900 dark:text-red-300"
3258
+ }
3259
+ };
3260
+ const type = banner.type || "info";
3261
+ const { icon: IconComponent, bg, border, iconColor, textColor } = typeConfig[type];
3262
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: `w-full border-b ${border} ${bg}`, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "container mx-auto px-6 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-3", children: [
3263
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(IconComponent, { className: `h-5 w-5 shrink-0 ${iconColor}` }),
3264
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: `text-sm font-medium ${textColor}`, children: banner.message }) }),
3265
+ banner.dismissible && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3266
+ "button",
3267
+ {
3268
+ onClick: handleDismiss,
3269
+ className: `shrink-0 p-1 rounded-md hover:bg-black/5 dark:hover:bg-white/5 transition-colors ${iconColor}`,
3270
+ "aria-label": "Dismiss banner",
3271
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react17.X, { className: "h-4 w-4" })
3272
+ }
3273
+ )
3274
+ ] }) }) });
3275
+ }
3276
+
3277
+ // src/components/docs/tab-groups.tsx
3278
+ var import_jsx_runtime37 = require("react/jsx-runtime");
3279
+ function TabGroups({ tabGroups, activeTabId, onTabChange }) {
3280
+ const activeTab = activeTabId || tabGroups[0]?.id || "";
3281
+ const handleTabChange = (tabId) => {
3282
+ onTabChange?.(tabId);
3283
+ };
3284
+ if (!tabGroups || tabGroups.length === 0) {
3285
+ return null;
3286
+ }
3287
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "container mx-auto px-6", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("nav", { className: "flex gap-1 overflow-x-auto no-scrollbar", "aria-label": "Documentation tabs", children: tabGroups.map((tab) => {
3288
+ const isActive = tab.id === activeTab;
3289
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
3290
+ "button",
3291
+ {
3292
+ onClick: () => handleTabChange(tab.id),
3293
+ className: `flex items-center gap-2 px-4 py-3 text-sm font-medium whitespace-nowrap transition-all border-b-2 ${isActive ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground hover:border-border"}`,
3294
+ "aria-current": isActive ? "page" : void 0,
3295
+ children: [
3296
+ tab.icon && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Icon, { icon: tab.icon, size: 16, className: "shrink-0" }),
3297
+ tab.label
3298
+ ]
3299
+ },
3300
+ tab.id
3301
+ );
3302
+ }) }) }) });
3303
+ }
3304
+
3305
+ // src/components/docs/sidebar.tsx
3306
+ var import_link7 = __toESM(require("next/link"));
3307
+ var import_navigation2 = require("next/navigation");
3308
+ var import_lucide_react18 = require("lucide-react");
3309
+ var import_react14 = require("react");
3310
+ var import_jsx_runtime38 = require("react/jsx-runtime");
3311
+ function Sidebar({ docs, version, onLinkClick, config, activeTabGroup }) {
3312
+ const pathname = (0, import_navigation2.usePathname)();
3313
+ const [collapsed, setCollapsed] = (0, import_react14.useState)(() => {
3314
+ const initial = {};
3315
+ return initial;
3316
+ });
3317
+ if (!config.navigation?.showSidebar) {
3318
+ return null;
3319
+ }
3320
+ const hasTabGroups = config.navigation?.tabGroups && config.navigation.tabGroups.length > 0;
3321
+ const filteredDocs = hasTabGroups && activeTabGroup ? docs.filter((doc) => {
3322
+ const docTabGroup = doc.meta?.tab_group || doc.categoryTabGroup;
3323
+ if (!docTabGroup) {
3324
+ return activeTabGroup === config.navigation?.tabGroups?.[0]?.id;
3325
+ }
3326
+ return docTabGroup === activeTabGroup;
3327
+ }) : docs;
3328
+ const rootGroups = {};
3329
+ const standalone = [];
3330
+ filteredDocs.forEach((doc) => {
3331
+ const pathParts = doc.filePath.split("/");
3332
+ const isIndexFile = doc.filePath.endsWith("/index") || doc.filePath === "index" || pathParts.length > 1 && doc.slug === pathParts.slice(0, -1).join("/");
3333
+ const customGroup = doc.sidebar || doc.group;
3334
+ if (customGroup) {
3335
+ const groupName = customGroup.charAt(0).toUpperCase() + customGroup.slice(1);
3336
+ if (!rootGroups[groupName]) {
3337
+ rootGroups[groupName] = {
3338
+ label: groupName,
3339
+ path: customGroup,
3340
+ items: [],
3341
+ position: 999,
3342
+ collapsible: doc.categoryCollapsible ?? true,
3343
+ defaultCollapsed: doc.categoryCollapsed ?? false,
3344
+ children: {}
3345
+ };
3346
+ }
3347
+ if (isIndexFile) {
3348
+ rootGroups[groupName].position = doc.sidebar_position ?? 999;
3349
+ rootGroups[groupName].icon = doc.categoryIcon;
3350
+ } else {
3351
+ rootGroups[groupName].items.push(doc);
3352
+ }
3353
+ return;
3354
+ }
3355
+ if (pathParts.length > 1) {
3356
+ const folderParts = pathParts.slice(0, -1);
3357
+ let currentLevel = rootGroups;
3358
+ let currentPath = "";
3359
+ for (let i = 0; i < folderParts.length; i++) {
3360
+ const folder = folderParts[i];
3361
+ currentPath = currentPath ? `${currentPath}/${folder}` : folder;
3362
+ const folderLabel = folder.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
3363
+ if (!currentLevel[folder]) {
3364
+ currentLevel[folder] = {
3365
+ label: doc.categoryLabel && i === folderParts.length - 1 ? doc.categoryLabel : folderLabel,
3366
+ path: currentPath,
3367
+ icon: doc.categoryIcon,
3368
+ items: [],
3369
+ position: doc.categoryPosition ?? 999,
3370
+ collapsible: doc.categoryCollapsible ?? true,
3371
+ defaultCollapsed: doc.categoryCollapsed ?? false,
3372
+ children: {}
3373
+ };
3374
+ }
3375
+ if (i === folderParts.length - 1) {
3376
+ if (isIndexFile) {
3377
+ currentLevel[folder].position = doc.categoryPosition ?? doc.sidebar_position ?? 999;
3378
+ if (doc.categoryLabel) {
3379
+ currentLevel[folder].label = doc.categoryLabel;
3380
+ }
3381
+ if (doc.categoryIcon) {
3382
+ currentLevel[folder].icon = doc.categoryIcon;
3383
+ }
3384
+ } else {
3385
+ currentLevel[folder].items.push(doc);
3386
+ }
3387
+ }
3388
+ currentLevel = currentLevel[folder].children;
3389
+ }
3390
+ } else {
3391
+ if (!isIndexFile) {
3392
+ standalone.push(doc);
3393
+ }
3394
+ }
3395
+ });
3396
+ const toggleSection = (section) => {
3397
+ setCollapsed((prev) => ({ ...prev, [section]: !prev[section] }));
3398
+ };
3399
+ const renderGroup = (groupKey, group, depth = 0) => {
3400
+ const sortedItems = sortSidebarItems(group.items);
3401
+ const sortedChildren = sortSidebarGroups(group.children);
3402
+ const hasChildren = sortedChildren.length > 0;
3403
+ const hasItems = sortedItems.length > 0;
3404
+ const hasContent = hasChildren || hasItems;
3405
+ const isActiveInGroup = (g) => {
3406
+ const hasActiveItem2 = g.items.some((doc) => pathname === `/docs/${version}/${doc.slug}`);
3407
+ if (hasActiveItem2) return true;
3408
+ return Object.values(g.children).some((child) => isActiveInGroup(child));
3409
+ };
3410
+ const hasActiveItem = isActiveInGroup(group);
3411
+ const isGroupActive = pathname === `/docs/${version}/${group.path}`;
3412
+ const isCollapsed = hasActiveItem || isGroupActive ? false : collapsed[groupKey] ?? group.defaultCollapsed;
3413
+ const marginLeft = depth > 0 ? "ml-4" : "";
3414
+ const groupHref = `/docs/${version}/${group.path}`;
3415
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: `space-y-1 ${marginLeft}`, children: [
3416
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center group", children: [
3417
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3418
+ import_link7.default,
3419
+ {
3420
+ href: groupHref,
3421
+ onClick: onLinkClick,
3422
+ className: `flex items-center gap-2 flex-1 px-3 py-2 text-sm font-semibold rounded-l-xl transition-all ${isGroupActive ? "bg-primary/10 text-primary" : "text-foreground hover:bg-accent/50"}`,
3423
+ children: [
3424
+ group.icon ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { icon: group.icon, size: 16, className: "shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react18.FolderOpen, { size: 16, className: "shrink-0" }),
3425
+ group.label
3426
+ ]
3427
+ }
3428
+ ),
3429
+ hasContent && group.collapsible && config.navigation?.collapsibleSidebar && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
3430
+ "button",
3431
+ {
3432
+ onClick: (e) => {
3433
+ e.preventDefault();
3434
+ e.stopPropagation();
3435
+ toggleSection(groupKey);
3436
+ },
3437
+ className: `p-2 rounded-r-xl transition-all ${isGroupActive ? "hover:bg-primary/20" : "hover:bg-accent/50"}`,
3438
+ "aria-label": isCollapsed ? "Expand section" : "Collapse section",
3439
+ children: isCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react18.ChevronRight, { className: `h-4 w-4 ${isGroupActive ? "text-primary" : "text-muted-foreground"}` }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react18.ChevronDown, { className: `h-4 w-4 ${isGroupActive ? "text-primary" : "text-muted-foreground"}` })
3440
+ }
3441
+ )
3442
+ ] }),
3443
+ !isCollapsed && hasContent && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ml-4 space-y-1", children: (() => {
3444
+ const merged = [
3445
+ ...sortedChildren.map(([childKey, childGroup]) => ({
3446
+ type: "group",
3447
+ key: childKey,
3448
+ group: childGroup,
3449
+ position: childGroup.position
3450
+ })),
3451
+ ...sortedItems.map((doc) => ({
3452
+ type: "item",
3453
+ doc,
3454
+ position: doc.sidebar_position ?? doc.meta?.sidebar_position ?? doc.meta?.order ?? 999
3455
+ }))
3456
+ ];
3457
+ merged.sort((a, b) => a.position - b.position);
3458
+ return merged.map((item) => {
3459
+ if (item.type === "group") {
3460
+ return renderGroup(`${groupKey}/${item.key}`, item.group, depth + 1);
3461
+ } else {
3462
+ const href = `/docs/${version}/${item.doc.slug}`;
3463
+ const isActive = pathname === href;
3464
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3465
+ import_link7.default,
3466
+ {
3467
+ href,
3468
+ onClick: onLinkClick,
3469
+ className: `flex items-center gap-2 px-3 py-2 text-sm rounded-xl transition-all ${isActive ? "bg-primary/10 text-primary font-medium" : "text-foreground hover:text-foreground hover:bg-accent/50"}`,
3470
+ children: [
3471
+ item.doc.meta?.icon && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { icon: item.doc.meta.icon, size: 16, className: "shrink-0" }),
3472
+ item.doc.title
3473
+ ]
3474
+ },
3475
+ `grouped-${item.doc.slug}`
3476
+ );
3477
+ }
3478
+ });
3479
+ })() })
3480
+ ] }, `group-${groupKey}`);
3481
+ };
3482
+ const sortedRootGroups = sortSidebarGroups(rootGroups);
3483
+ const sortedStandalone = sortSidebarItems(standalone);
3484
+ const stickyTop = hasTabGroups ? "top-[7.5rem]" : "top-24";
3485
+ const maxHeight = hasTabGroups ? "max-h-[calc(100vh-10rem)]" : "max-h-[calc(100vh-7rem)]";
3486
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("aside", { className: `w-64 shrink-0 sticky ${stickyTop} self-start`, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: `${maxHeight} overflow-y-auto bg-muted/30 dark:bg-muted/10 rounded-2xl p-4 border border-border/50`, children: [
3487
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h2", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-4 px-2", children: "Documentation" }),
3488
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("nav", { className: "space-y-1", children: [
3489
+ sortedStandalone.length > 0 && sortedStandalone.map((doc) => {
3490
+ const href = `/docs/${version}/${doc.slug}`;
3491
+ const isActive = pathname === href;
3492
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
3493
+ import_link7.default,
3494
+ {
3495
+ href,
3496
+ onClick: onLinkClick,
3497
+ className: `flex items-center gap-2 px-3 py-2 text-sm rounded-xl transition-all ${isActive ? "bg-primary/10 text-primary font-medium" : "text-foreground hover:text-foreground hover:bg-accent/50"}`,
3498
+ children: [
3499
+ doc.meta?.icon && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { icon: doc.meta.icon, size: 16, className: "shrink-0" }),
3500
+ doc.title
3501
+ ]
3502
+ },
3503
+ `standalone-${doc.slug}`
3504
+ );
3505
+ }),
3506
+ sortedRootGroups.map(([groupKey, group]) => renderGroup(groupKey, group, 0))
3507
+ ] })
3508
+ ] }) });
3509
+ }
3510
+
3511
+ // src/components/docs/mobile-doc-layout.tsx
3512
+ var import_jsx_runtime39 = require("react/jsx-runtime");
3513
+ function MobileDocLayout({ header, docs, version, content, toc, config, activeTabGroup, onTabChange }) {
3514
+ const [sidebarOpen, setSidebarOpen] = (0, import_react15.useState)(false);
3515
+ const handleTabChange = (tabId) => {
3516
+ onTabChange?.(tabId);
3517
+ };
3518
+ const closeSidebar = () => setSidebarOpen(false);
3519
+ const toggleSidebar = () => setSidebarOpen(!sidebarOpen);
3520
+ const headerWithProps = (0, import_react15.isValidElement)(header) ? (0, import_react15.cloneElement)(header, {
3521
+ onMenuClick: toggleSidebar
3522
+ }) : header;
3523
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "min-h-screen bg-background", children: [
3524
+ headerWithProps,
3525
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SiteBanner, { config }),
3526
+ config.navigation?.tabGroups && config.navigation.tabGroups.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3527
+ TabGroups,
3528
+ {
3529
+ tabGroups: config.navigation.tabGroups,
3530
+ activeTabId: activeTabGroup,
3531
+ onTabChange: handleTabChange
3532
+ }
3533
+ ),
3534
+ sidebarOpen && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3535
+ "div",
3536
+ {
3537
+ className: "lg:hidden fixed inset-0 bg-background/80 backdrop-blur-sm z-40",
3538
+ onClick: () => setSidebarOpen(false)
3539
+ }
3540
+ ),
3541
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3542
+ "div",
3543
+ {
3544
+ className: `lg:hidden fixed top-0 left-0 h-full w-64 bg-background border-r border-border z-40 transform transition-transform duration-300 ease-in-out overflow-y-auto ${sidebarOpen ? "translate-x-0" : "-translate-x-full"}`,
3545
+ children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "pt-20 px-4", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3546
+ Sidebar,
3547
+ {
3548
+ docs,
3549
+ version,
3550
+ config,
3551
+ onLinkClick: closeSidebar,
3552
+ activeTabGroup
3553
+ }
3554
+ ) })
3555
+ }
3556
+ ),
3557
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("main", { className: "container mx-auto px-6 py-8", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex", children: [
3558
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "hidden lg:block", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
3559
+ Sidebar,
3560
+ {
3561
+ docs,
3562
+ version,
3563
+ config,
3564
+ activeTabGroup
3565
+ }
3566
+ ) }),
3567
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-2 px-2 md:px-8", children: [
3568
+ content,
3569
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Footer, { config })
3570
+ ] }) }),
3571
+ toc
3572
+ ] }) })
3573
+ ] });
3574
+ }
3575
+
3576
+ // src/components/docs/tab-context.tsx
3577
+ var import_react16 = require("react");
3578
+ var import_jsx_runtime40 = require("react/jsx-runtime");
3579
+ var TabContext = (0, import_react16.createContext)(void 0);
3580
+ function TabProvider({ children, defaultTab }) {
3581
+ const [activeTabGroup, setActiveTabGroup] = (0, import_react16.useState)(defaultTab);
3582
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(TabContext.Provider, { value: { activeTabGroup, setActiveTabGroup }, children });
3583
+ }
3584
+ function useTabContext() {
3585
+ const context = (0, import_react16.useContext)(TabContext);
3586
+ if (!context) {
3587
+ throw new Error("useTabContext must be used within TabProvider");
3588
+ }
3589
+ return context;
3590
+ }
3591
+
3592
+ // src/components/docs/doc-layout-wrapper.tsx
3593
+ var import_jsx_runtime41 = require("react/jsx-runtime");
3594
+ function DocLayoutWrapper({ header, docs, version, content, toc, config, currentPageTabGroup }) {
3595
+ const { activeTabGroup, setActiveTabGroup } = useTabContext();
3596
+ const lastPageTabGroupRef = (0, import_react17.useRef)(void 0);
3597
+ const isInitialMount = (0, import_react17.useRef)(true);
3598
+ (0, import_react17.useEffect)(() => {
3599
+ if (isInitialMount.current && currentPageTabGroup) {
3600
+ setActiveTabGroup(currentPageTabGroup);
3601
+ lastPageTabGroupRef.current = currentPageTabGroup;
3602
+ isInitialMount.current = false;
3603
+ return;
3604
+ }
3605
+ if (currentPageTabGroup && lastPageTabGroupRef.current !== currentPageTabGroup) {
3606
+ setActiveTabGroup(currentPageTabGroup);
3607
+ lastPageTabGroupRef.current = currentPageTabGroup;
3608
+ }
3609
+ }, [currentPageTabGroup, setActiveTabGroup]);
3610
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
3611
+ MobileDocLayout,
3612
+ {
3613
+ header,
3614
+ docs,
3615
+ version,
3616
+ content,
3617
+ toc,
3618
+ config,
3619
+ activeTabGroup,
3620
+ onTabChange: setActiveTabGroup
3621
+ }
3622
+ );
3623
+ }
3624
+
3625
+ // src/components/docs/doc-loading.tsx
3626
+ var import_jsx_runtime42 = require("react/jsx-runtime");
3627
+ function DocLoading() {
3628
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "max-w-4xl mx-auto px-6 py-8", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "animate-pulse space-y-4", children: [
3629
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "h-8 bg-gray-200 rounded w-3/4" }),
3630
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "h-4 bg-gray-200 rounded w-1/2" }),
3631
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-3 mt-8", children: [
3632
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "h-4 bg-gray-200 rounded" }),
3633
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "h-4 bg-gray-200 rounded w-5/6" }),
3634
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "h-4 bg-gray-200 rounded w-4/6" })
3635
+ ] })
3636
+ ] }) });
3637
+ }
3638
+
3639
+ // src/components/docs/header.tsx
3640
+ var import_link8 = __toESM(require("next/link"));
3641
+ var import_lucide_react23 = require("lucide-react");
3642
+
3643
+ // src/components/docs/version-switcher.tsx
3644
+ var import_react18 = require("react");
3645
+ var import_lucide_react19 = require("lucide-react");
3646
+ var import_navigation3 = require("next/navigation");
3647
+ var import_jsx_runtime43 = require("react/jsx-runtime");
3648
+ function VersionSwitcher({ currentVersion, versions }) {
3649
+ const [open, setOpen] = (0, import_react18.useState)(false);
3650
+ const router = (0, import_navigation3.useRouter)();
3651
+ const handleVersionChange = (version) => {
3652
+ router.push(`/docs/${version}`);
3653
+ setOpen(false);
3654
+ };
3655
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "relative", children: [
3656
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
3657
+ "button",
3658
+ {
3659
+ onClick: () => setOpen(!open),
3660
+ className: "flex items-center gap-2 px-3 py-2 text-sm text-foreground bg-muted rounded-md hover:bg-muted/80 transition-colors",
3661
+ children: [
3662
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium", children: currentVersion }),
3663
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react19.ChevronDown, { className: "h-4 w-4" })
3664
+ ]
3665
+ }
3666
+ ),
3667
+ open && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
3668
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "fixed inset-0 z-40", onClick: () => setOpen(false) }),
3669
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "absolute right-0 mt-2 w-48 bg-background border border-border rounded-md shadow-lg z-50", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "p-2", children: versions.map((version) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
3670
+ "button",
3671
+ {
3672
+ onClick: () => handleVersionChange(version),
3673
+ className: "flex items-center justify-between w-full px-3 py-2 text-sm text-foreground hover:bg-muted rounded-md transition-colors",
3674
+ children: [
3675
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: version }),
3676
+ version === currentVersion && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react19.Check, { className: "h-4 w-4 text-primary" })
3677
+ ]
3678
+ },
3679
+ version
3680
+ )) }) })
3681
+ ] })
3682
+ ] });
3683
+ }
3684
+
3685
+ // src/components/docs/theme-toggle.tsx
3686
+ var import_lucide_react20 = require("lucide-react");
3687
+ var import_react19 = require("react");
3688
+ var import_jsx_runtime44 = require("react/jsx-runtime");
3689
+ function ThemeToggle() {
3690
+ const [theme, setTheme] = (0, import_react19.useState)("dark");
3691
+ (0, import_react19.useEffect)(() => {
3692
+ const savedTheme = localStorage.getItem("theme");
3693
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
3694
+ const initialTheme = savedTheme || (prefersDark ? "dark" : "light");
3695
+ setTheme(initialTheme);
3696
+ document.documentElement.classList.toggle("dark", initialTheme === "dark");
3697
+ }, []);
3698
+ const toggleTheme = () => {
3699
+ const newTheme = theme === "dark" ? "light" : "dark";
3700
+ setTheme(newTheme);
3701
+ localStorage.setItem("theme", newTheme);
3702
+ document.documentElement.classList.toggle("dark", newTheme === "dark");
3703
+ };
3704
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3705
+ "button",
3706
+ {
3707
+ onClick: toggleTheme,
3708
+ className: "flex items-center justify-center w-9 h-9 rounded-md border border-border bg-background hover:bg-accent transition-colors",
3709
+ "aria-label": "Toggle theme",
3710
+ children: theme === "dark" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react20.Sun, { className: "h-4 w-4 text-foreground" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react20.Moon, { className: "h-4 w-4 text-foreground" })
3711
+ }
3712
+ );
3713
+ }
3714
+
3715
+ // src/components/docs/search-modal.tsx
3716
+ var import_react20 = require("react");
3717
+ var import_lucide_react22 = require("lucide-react");
3718
+ var import_navigation4 = require("next/navigation");
3719
+
3720
+ // src/components/ui/dialog.tsx
3721
+ var DialogPrimitive = __toESM(require("@radix-ui/react-dialog"));
3722
+ var import_lucide_react21 = require("lucide-react");
3723
+ var import_jsx_runtime45 = require("react/jsx-runtime");
3724
+ function Dialog({
3725
+ ...props
3726
+ }) {
3727
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
3728
+ }
3729
+ function DialogTrigger({
3730
+ ...props
3731
+ }) {
3732
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(DialogPrimitive.Trigger, { "data-slot": "dialog-trigger", ...props });
3733
+ }
3734
+ function DialogPortal({
3735
+ ...props
3736
+ }) {
3737
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
3738
+ }
3739
+ function DialogClose({
3740
+ ...props
3741
+ }) {
3742
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
3743
+ }
3744
+ function DialogOverlay({
3745
+ className,
3746
+ ...props
3747
+ }) {
3748
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3749
+ DialogPrimitive.Overlay,
3750
+ {
3751
+ "data-slot": "dialog-overlay",
3752
+ className: cn(
3753
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 dark:bg-black/70 backdrop-blur-md",
3754
+ className
3755
+ ),
3756
+ ...props
3757
+ }
3758
+ );
3759
+ }
3760
+ function DialogContent({
3761
+ className,
3762
+ children,
3763
+ showCloseButton = true,
3764
+ ...props
3765
+ }) {
3766
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(DialogPortal, { "data-slot": "dialog-portal", children: [
3767
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(DialogOverlay, {}),
3768
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3769
+ DialogPrimitive.Content,
3770
+ {
3771
+ "data-slot": "dialog-content",
3772
+ className: cn(
3773
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
3774
+ className
3775
+ ),
3776
+ ...props,
3777
+ children: [
3778
+ children,
3779
+ showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3780
+ DialogPrimitive.Close,
3781
+ {
3782
+ "data-slot": "dialog-close",
3783
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
3784
+ children: [
3785
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react21.XIcon, {}),
3786
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "sr-only", children: "Close" })
3787
+ ]
3788
+ }
3789
+ )
3790
+ ]
3791
+ }
3792
+ )
3793
+ ] });
3794
+ }
3795
+ function DialogHeader({ className, ...props }) {
3796
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3797
+ "div",
3798
+ {
3799
+ "data-slot": "dialog-header",
3800
+ className: cn("flex flex-col gap-2 text-center sm:text-left", className),
3801
+ ...props
3802
+ }
3803
+ );
3804
+ }
3805
+ function DialogFooter({ className, ...props }) {
3806
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3807
+ "div",
3808
+ {
3809
+ "data-slot": "dialog-footer",
3810
+ className: cn(
3811
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
3812
+ className
3813
+ ),
3814
+ ...props
3815
+ }
3816
+ );
3817
+ }
3818
+ function DialogTitle({
3819
+ className,
3820
+ ...props
3821
+ }) {
3822
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3823
+ DialogPrimitive.Title,
3824
+ {
3825
+ "data-slot": "dialog-title",
3826
+ className: cn("text-lg leading-none font-semibold", className),
3827
+ ...props
3828
+ }
3829
+ );
3830
+ }
3831
+ function DialogDescription({
3832
+ className,
3833
+ ...props
3834
+ }) {
3835
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3836
+ DialogPrimitive.Description,
3837
+ {
3838
+ "data-slot": "dialog-description",
3839
+ className: cn("text-muted-foreground text-sm", className),
3840
+ ...props
3841
+ }
3842
+ );
3843
+ }
3844
+
3845
+ // src/components/docs/search-modal.tsx
3846
+ var import_jsx_runtime46 = require("react/jsx-runtime");
3847
+ function SearchModal({ isOpen, onClose, config }) {
3848
+ const [query, setQuery] = (0, import_react20.useState)("");
3849
+ const [results, setResults] = (0, import_react20.useState)([]);
3850
+ const [isLoading, setIsLoading] = (0, import_react20.useState)(false);
3851
+ const [selectedIndex, setSelectedIndex] = (0, import_react20.useState)(0);
3852
+ const router = (0, import_navigation4.useRouter)();
3853
+ const searchConfig = config.search;
3854
+ const performSearch = (0, import_react20.useCallback)(async (searchQuery) => {
3855
+ if (!searchQuery.trim() || !searchConfig?.enabled) {
3856
+ setResults([]);
3857
+ return;
3858
+ }
3859
+ setIsLoading(true);
3860
+ try {
3861
+ const response = await fetch("/api/search", {
3862
+ method: "POST",
3863
+ headers: { "Content-Type": "application/json" },
3864
+ body: JSON.stringify({
3865
+ query: searchQuery,
3866
+ // filter: 'version = "v1.0.0"',
3867
+ distinct: "version",
3868
+ limit: 2
3869
+ })
3870
+ });
3871
+ if (response.ok) {
3872
+ const data = await response.json();
3873
+ console.log("Search response:", data);
3874
+ setResults(data.hits || []);
3875
+ } else {
3876
+ console.error("Search failed:", response.status, await response.text());
3877
+ }
3878
+ } catch (error) {
3879
+ console.error("Search error:", error);
3880
+ setResults([]);
3881
+ } finally {
3882
+ setIsLoading(false);
3883
+ }
3884
+ }, [searchConfig]);
3885
+ (0, import_react20.useEffect)(() => {
3886
+ const timer = setTimeout(() => {
3887
+ performSearch(query);
3888
+ }, 300);
3889
+ return () => clearTimeout(timer);
3890
+ }, [query, performSearch]);
3891
+ (0, import_react20.useEffect)(() => {
3892
+ const handleKeyDown = (e) => {
3893
+ if (!isOpen) return;
3894
+ switch (e.key) {
3895
+ case "Escape":
3896
+ onClose();
3897
+ break;
3898
+ case "ArrowDown":
3899
+ e.preventDefault();
3900
+ setSelectedIndex((prev) => Math.min(prev + 1, results.length - 1));
3901
+ break;
3902
+ case "ArrowUp":
3903
+ e.preventDefault();
3904
+ setSelectedIndex((prev) => Math.max(prev - 1, 0));
3905
+ break;
3906
+ case "Enter":
3907
+ e.preventDefault();
3908
+ if (results[selectedIndex]) {
3909
+ handleResultClick(results[selectedIndex]);
3910
+ }
3911
+ break;
3912
+ }
3913
+ };
3914
+ window.addEventListener("keydown", handleKeyDown);
3915
+ return () => window.removeEventListener("keydown", handleKeyDown);
3916
+ }, [isOpen, results, selectedIndex, onClose]);
3917
+ (0, import_react20.useEffect)(() => {
3918
+ if (isOpen) {
3919
+ setQuery("");
3920
+ setResults([]);
3921
+ setSelectedIndex(0);
3922
+ }
3923
+ }, [isOpen]);
3924
+ const handleResultClick = (result) => {
3925
+ const url = `/docs/${result.version}/${result.slug}?q=${encodeURIComponent(query)}`;
3926
+ router.push(url);
3927
+ onClose();
3928
+ };
3929
+ const highlightText = (text, query2) => {
3930
+ if (!query2.trim()) return text;
3931
+ const parts = text.split(new RegExp(`(${query2})`, "gi"));
3932
+ return parts.map(
3933
+ (part, i) => part.toLowerCase() === query2.toLowerCase() ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("mark", { className: "bg-yellow-200 dark:bg-yellow-900/50 text-foreground", children: part }, i) : part
3934
+ );
3935
+ };
3936
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Dialog, { open: isOpen, onOpenChange: onClose, modal: true, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3937
+ DialogContent,
3938
+ {
3939
+ className: "max-w-2xl p-0 gap-0 top-[10vh] translate-y-0",
3940
+ showCloseButton: false,
3941
+ onOpenAutoFocus: (e) => e.preventDefault(),
3942
+ children: [
3943
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-3 px-4 py-3 border-b border-border", children: [
3944
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react22.Search, { className: "h-5 w-5 text-muted-foreground shrink-0" }),
3945
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3946
+ "input",
3947
+ {
3948
+ type: "text",
3949
+ value: query,
3950
+ onChange: (e) => setQuery(e.target.value),
3951
+ placeholder: searchConfig?.placeholder || "Search documentation...",
3952
+ className: "flex-1 bg-transparent border-none outline-none text-foreground placeholder:text-muted-foreground",
3953
+ autoFocus: true
3954
+ }
3955
+ ),
3956
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react22.Loader2, { className: "h-5 w-5 text-muted-foreground animate-spin" })
3957
+ ] }),
3958
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "max-h-[60vh] overflow-y-auto", children: [
3959
+ query.trim() && results.length === 0 && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "px-4 py-8 text-center text-muted-foreground", children: [
3960
+ 'No results found for "',
3961
+ query,
3962
+ '"'
3963
+ ] }),
3964
+ results.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "py-2", children: results.map((result, index) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3965
+ "button",
3966
+ {
3967
+ onClick: () => handleResultClick(result),
3968
+ className: `w-full px-4 py-3 text-left hover:bg-muted/50 transition-colors border-l-2 ${index === selectedIndex ? "bg-muted/50 border-primary" : "border-transparent"}`,
3969
+ onMouseEnter: () => setSelectedIndex(index),
3970
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-start gap-3", children: [
3971
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react22.FileText, { className: "h-5 w-5 text-muted-foreground shrink-0 mt-0.5" }),
3972
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex-1 min-w-0", children: [
3973
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "font-medium text-foreground mb-1", children: highlightText(result.title, query) }),
3974
+ result.content && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "text-sm text-muted-foreground line-clamp-2", children: highlightText(result.content, query) }),
3975
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2 mt-1 text-xs text-muted-foreground", children: [
3976
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: result.version }),
3977
+ result.category && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
3978
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: "\u2022" }),
3979
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: result.category })
3980
+ ] })
3981
+ ] })
3982
+ ] })
3983
+ ] })
3984
+ },
3985
+ result.id
3986
+ )) }),
3987
+ !query.trim() && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "px-4 py-8 text-center text-muted-foreground text-sm", children: [
3988
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { children: "Start typing to search documentation..." }),
3989
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "mt-4 flex items-center justify-center gap-4 text-xs", children: [
3990
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("kbd", { className: "px-2 py-1 bg-muted rounded border border-border", children: "\u2191\u2193" }),
3991
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: "Navigate" }),
3992
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("kbd", { className: "px-2 py-1 bg-muted rounded border border-border", children: "Enter" }),
3993
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: "Select" }),
3994
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("kbd", { className: "px-2 py-1 bg-muted rounded border border-border", children: "Esc" }),
3995
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { children: "Close" })
3996
+ ] })
3997
+ ] })
3998
+ ] })
3999
+ ]
4000
+ }
4001
+ ) });
4002
+ }
4003
+
4004
+ // src/components/docs/header.tsx
4005
+ var import_react21 = require("react");
4006
+ var import_jsx_runtime47 = require("react/jsx-runtime");
4007
+ function Header({ currentVersion, versions, onMenuClick, config }) {
4008
+ const [searchOpen, setSearchOpen] = (0, import_react21.useState)(false);
4009
+ (0, import_react21.useEffect)(() => {
4010
+ const handleKeyDown = (e) => {
4011
+ if ((e.metaKey || e.ctrlKey) && e.key === "k") {
4012
+ e.preventDefault();
4013
+ setSearchOpen(true);
4014
+ }
4015
+ };
4016
+ window.addEventListener("keydown", handleKeyDown);
4017
+ return () => window.removeEventListener("keydown", handleKeyDown);
4018
+ }, []);
4019
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("header", { className: "sticky top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60", children: [
4020
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "container flex h-16 items-center justify-between px-6 mx-auto", children: [
4021
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
4022
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
4023
+ "button",
4024
+ {
4025
+ onClick: onMenuClick,
4026
+ className: "lg:hidden hover:bg-muted p-2 rounded-md transition-colors",
4027
+ "aria-label": "Toggle menu",
4028
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react23.Menu, { className: "h-5 w-5" })
4029
+ }
4030
+ ),
4031
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_link8.default, { href: "/", className: "flex items-center gap-2", children: [
4032
+ config.site.logo ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("img", { src: getAssetPath(config.site.logo), alt: config.site.title, className: "h-8 w-auto" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "h-8 w-8 rounded-xl bg-primary flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-primary-foreground font-bold text-lg", children: config.site.title.charAt(0).toUpperCase() }) }),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-semibold text-lg text-foreground", children: "Specra" })
4034
+ ] })
4035
+ ] }),
4036
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
4037
+ config.search?.enabled && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
4038
+ "button",
4039
+ {
4040
+ onClick: () => setSearchOpen(true),
4041
+ className: "flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground bg-muted rounded-md transition-colors",
4042
+ children: [
4043
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react23.Search, { className: "h-4 w-4" }),
4044
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "hidden sm:inline", children: config.search.placeholder || "Search" }),
4045
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("kbd", { className: "hidden sm:inline-flex h-5 select-none items-center gap-1 rounded border border-border bg-background px-1.5 font-mono text-xs font-medium", children: "\u2318K" })
4046
+ ]
4047
+ }
4048
+ ),
4049
+ config.features?.versioning && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(VersionSwitcher, { currentVersion, versions }),
4050
+ config.social?.github && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
4051
+ "a",
4052
+ {
4053
+ href: config.social.github,
4054
+ target: "_blank",
4055
+ rel: "noopener noreferrer",
4056
+ className: "hidden md:flex items-center justify-center h-9 w-9 rounded-md hover:bg-muted transition-colors",
4057
+ "aria-label": "GitHub",
4058
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react23.Github, { className: "h-4 w-4" })
4059
+ }
4060
+ ),
4061
+ config.social?.twitter && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
4062
+ "a",
4063
+ {
4064
+ href: config.social.twitter,
4065
+ target: "_blank",
4066
+ rel: "noopener noreferrer",
4067
+ className: "hidden md:flex items-center justify-center h-9 w-9 rounded-md hover:bg-muted transition-colors",
4068
+ "aria-label": "Twitter",
4069
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react23.Twitter, { className: "h-4 w-4" })
4070
+ }
4071
+ ),
4072
+ config.social?.discord && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
4073
+ "a",
4074
+ {
4075
+ href: config.social.discord,
4076
+ target: "_blank",
4077
+ rel: "noopener noreferrer",
4078
+ className: "hidden md:flex items-center justify-center h-9 w-9 rounded-md hover:bg-muted transition-colors",
4079
+ "aria-label": "Discord",
4080
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react23.MessageCircle, { className: "h-4 w-4" })
4081
+ }
4082
+ ),
4083
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ThemeToggle, {})
4084
+ ] })
4085
+ ] }),
4086
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SearchModal, { isOpen: searchOpen, onClose: () => setSearchOpen(false), config })
4087
+ ] });
4088
+ }
4089
+
4090
+ // src/components/docs/hot-reload-indicator.tsx
4091
+ var import_react22 = require("react");
4092
+ var import_navigation5 = require("next/navigation");
4093
+ var import_lucide_react24 = require("lucide-react");
4094
+ var import_jsx_runtime48 = require("react/jsx-runtime");
4095
+ function HotReloadIndicator() {
4096
+ const [isReloading, setIsReloading] = (0, import_react22.useState)(false);
4097
+ const [lastReload, setLastReload] = (0, import_react22.useState)(null);
4098
+ const pathname = (0, import_navigation5.usePathname)();
4099
+ (0, import_react22.useEffect)(() => {
4100
+ if (process.env.NODE_ENV !== "development") return;
4101
+ setIsReloading(true);
4102
+ const timer = setTimeout(() => {
4103
+ setIsReloading(false);
4104
+ setLastReload(/* @__PURE__ */ new Date());
4105
+ setTimeout(() => {
4106
+ setLastReload(null);
4107
+ }, 3e3);
4108
+ }, 500);
4109
+ return () => clearTimeout(timer);
4110
+ }, [pathname]);
4111
+ (0, import_react22.useEffect)(() => {
4112
+ if (process.env.NODE_ENV !== "development") return;
4113
+ const handleBeforeRefresh = () => {
4114
+ setIsReloading(true);
4115
+ };
4116
+ const handleAfterRefresh = () => {
4117
+ setIsReloading(false);
4118
+ setLastReload(/* @__PURE__ */ new Date());
4119
+ setTimeout(() => setLastReload(null), 3e3);
4120
+ };
4121
+ if (typeof window !== "undefined" && window.__NEXT_DATA__) {
4122
+ window.addEventListener("beforeunload", handleBeforeRefresh);
4123
+ }
4124
+ return () => {
4125
+ window.removeEventListener("beforeunload", handleBeforeRefresh);
4126
+ };
4127
+ }, []);
4128
+ if (process.env.NODE_ENV !== "development") return null;
4129
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
4130
+ isReloading && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fixed bottom-4 right-4 z-50 flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-xl shadow-lg animate-in slide-in-from-bottom-2", children: [
4131
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react24.RefreshCw, { className: "h-4 w-4 animate-spin" }),
4132
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-sm font-medium", children: "Reloading..." })
4133
+ ] }),
4134
+ lastReload && !isReloading && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "fixed bottom-4 right-4 z-50 flex items-center gap-2 px-4 py-2 bg-green-500 text-white rounded-xl shadow-lg animate-in slide-in-from-bottom-2", children: [
4135
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react24.RefreshCw, { className: "h-4 w-4" }),
4136
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "text-sm font-medium", children: [
4137
+ "Updated at ",
4138
+ lastReload.toLocaleTimeString()
4139
+ ] })
4140
+ ] })
4141
+ ] });
4142
+ }
4143
+
4144
+ // src/components/docs/mdx-hot-reload.tsx
4145
+ var import_react23 = require("react");
4146
+ var import_navigation6 = require("next/navigation");
4147
+ function MdxHotReload() {
4148
+ const router = (0, import_navigation6.useRouter)();
4149
+ (0, import_react23.useEffect)(() => {
4150
+ if (process.env.NODE_ENV !== "development") return;
4151
+ const eventSource = new EventSource("/api/mdx-watch");
4152
+ eventSource.onmessage = (event) => {
4153
+ const data = JSON.parse(event.data);
4154
+ if (data.type === "change") {
4155
+ console.log("[MDX Hot Reload] File changed:", data.file);
4156
+ router.refresh();
4157
+ } else if (data.type === "connected") {
4158
+ console.log("[MDX Hot Reload] Watching for changes...");
4159
+ }
4160
+ };
4161
+ eventSource.onerror = (error) => {
4162
+ console.error("[MDX Hot Reload] Connection error:", error);
4163
+ eventSource.close();
4164
+ };
4165
+ return () => {
4166
+ eventSource.close();
4167
+ };
4168
+ }, [router]);
4169
+ return null;
4170
+ }
4171
+
4172
+ // src/components/docs/not-found-content.tsx
4173
+ var import_link9 = __toESM(require("next/link"));
4174
+ var import_lucide_react25 = require("lucide-react");
4175
+ var import_jsx_runtime49 = require("react/jsx-runtime");
4176
+ function NotFoundContent({ version }) {
4177
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex min-h-[calc(100vh-12rem)] items-center justify-center px-4 py-12", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "w-full max-w-2xl text-center", children: [
4178
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "mb-6 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "rounded-full bg-yellow-500/10 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react25.AlertTriangle, { className: "h-16 w-16 text-yellow-500" }) }) }),
4179
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h1", { className: "mb-3 text-5xl font-bold tracking-tight", children: "404" }),
4180
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h2", { className: "mb-4 text-2xl font-semibold", children: "Page Not Found" }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "mb-8 text-base text-muted-foreground", children: [
4182
+ "The documentation page you're looking for doesn't exist or may have been moved.",
4183
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("br", {}),
4184
+ "Try using the sidebar to find what you're looking for, or return to the documentation home."
4185
+ ] }),
4186
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col items-center justify-center gap-3 sm:flex-row", children: [
4187
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
4188
+ import_link9.default,
4189
+ {
4190
+ href: `/docs/${version}`,
4191
+ className: "inline-flex items-center gap-2 rounded-lg bg-primary px-6 py-3 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
4192
+ children: [
4193
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react25.ArrowLeft, { className: "h-4 w-4" }),
4194
+ "Back to Documentation"
4195
+ ]
4196
+ }
4197
+ ),
4198
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
4199
+ import_link9.default,
4200
+ {
4201
+ href: "/",
4202
+ className: "inline-flex items-center gap-2 rounded-lg border border-border bg-background px-6 py-3 text-sm font-medium hover:bg-muted transition-colors",
4203
+ children: [
4204
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react25.Home, { className: "h-4 w-4" }),
4205
+ "Go to Homepage"
4206
+ ]
4207
+ }
4208
+ )
4209
+ ] }),
4210
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "mt-12 rounded-lg border border-border bg-muted/30 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { className: "text-sm text-muted-foreground", children: [
4211
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("strong", { className: "font-medium text-foreground", children: "Tip:" }),
4212
+ " Use the sidebar navigation on the left to browse all available documentation pages."
4213
+ ] }) })
4214
+ ] }) });
4215
+ }
4216
+
4217
+ // src/components/docs/sidebar-skeleton.tsx
4218
+ var import_jsx_runtime50 = require("react/jsx-runtime");
4219
+ function SidebarSkeleton() {
4220
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("aside", { className: "w-64 pr-8 py-6", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "space-y-6", children: [
4221
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "h-5 w-32 bg-muted/50 rounded animate-pulse" }) }),
4222
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "space-y-1", children: [...Array(8)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4223
+ "div",
4224
+ {
4225
+ className: "h-4 bg-muted/50 rounded animate-pulse",
4226
+ style: { width: `${60 + Math.random() * 40}%` }
4227
+ }
4228
+ ) }, i)) }),
4229
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "space-y-1", children: [
4230
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "px-2 mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "h-4 w-24 bg-muted/50 rounded animate-pulse" }) }),
4231
+ [...Array(5)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
4232
+ "div",
4233
+ {
4234
+ className: "h-4 bg-muted/50 rounded animate-pulse",
4235
+ style: { width: `${50 + Math.random() * 50}%` }
4236
+ }
4237
+ ) }, i))
4238
+ ] })
4239
+ ] }) });
4240
+ }
4241
+
4242
+ // src/components/docs/table-of-contents.tsx
4243
+ var import_react24 = require("react");
4244
+ var import_jsx_runtime51 = require("react/jsx-runtime");
4245
+ function TableOfContents({ items, config }) {
4246
+ const [activeId, setActiveId] = (0, import_react24.useState)("");
4247
+ if (!config.navigation?.showTableOfContents) {
4248
+ return null;
4249
+ }
4250
+ const maxDepth = config.navigation?.tocMaxDepth || 3;
4251
+ const filteredItems = items.filter((item) => item.level <= maxDepth);
4252
+ const hasTabGroups = config.navigation?.tabGroups && config.navigation.tabGroups.length > 0;
4253
+ (0, import_react24.useEffect)(() => {
4254
+ const observer = new IntersectionObserver(
4255
+ (entries) => {
4256
+ entries.forEach((entry) => {
4257
+ if (entry.isIntersecting) {
4258
+ setActiveId(entry.target.id);
4259
+ }
4260
+ });
4261
+ },
4262
+ { rootMargin: "-80px 0px -80% 0px" }
4263
+ );
4264
+ filteredItems.forEach((item) => {
4265
+ const element = document.getElementById(item.id);
4266
+ if (element) {
4267
+ observer.observe(element);
4268
+ }
4269
+ });
4270
+ return () => observer.disconnect();
4271
+ }, [filteredItems]);
4272
+ const handleClick = (e, id) => {
4273
+ e.preventDefault();
4274
+ const element = document.getElementById(id);
4275
+ if (element) {
4276
+ const offset = 100;
4277
+ const elementPosition = element.getBoundingClientRect().top;
4278
+ const offsetPosition = elementPosition + window.scrollY - offset;
4279
+ window.scrollTo({
4280
+ top: offsetPosition,
4281
+ behavior: "smooth"
4282
+ });
4283
+ window.history.replaceState(null, "", `#${id}`);
4284
+ setActiveId(id);
4285
+ }
4286
+ };
4287
+ const stickyTop = hasTabGroups ? "top-[7.5rem]" : "top-24";
4288
+ const maxHeight = hasTabGroups ? "max-h-[calc(100vh-10rem)]" : "max-h-[calc(100vh-7rem)]";
4289
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("aside", { className: `w-64 hidden xl:block shrink-0 sticky ${stickyTop} self-start`, children: filteredItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: `${maxHeight} overflow-y-auto bg-muted/30 dark:bg-muted/10 rounded-2xl p-4 border border-border/50`, children: [
4290
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("h3", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-4 px-2", children: "On this page" }),
4291
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("nav", { className: "space-y-1", children: filteredItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
4292
+ "a",
4293
+ {
4294
+ href: `#${item.id}`,
4295
+ onClick: (e) => handleClick(e, item.id),
4296
+ className: `block text-sm transition-all cursor-pointer rounded-xl px-3 py-2 ${item.level === 3 ? "ml-3" : ""} ${activeId === item.id ? "text-primary font-medium" : "text-foreground hover:bg-accent/50"}`,
4297
+ children: item.title
4298
+ },
4299
+ item.id
4300
+ )) })
4301
+ ] }) });
4302
+ }
4303
+
4304
+ // src/components/global/version-not-found.tsx
4305
+ var import_lucide_react26 = require("lucide-react");
4306
+ var import_link10 = __toESM(require("next/link"));
4307
+ var import_jsx_runtime52 = require("react/jsx-runtime");
4308
+ function VersionNotFound() {
4309
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_jsx_runtime52.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "flex min-h-screen items-center justify-center px-4", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "text-center", children: [
4310
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "mb-4 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react26.AlertTriangle, { className: "h-16 w-16 text-yellow-500" }) }),
4311
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("h1", { className: "mb-2 text-4xl font-bold", children: "Version Not Found" }),
4312
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "mb-6 text-muted-foreground", children: "The documentation version you're looking for doesn't exist." }),
4313
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
4314
+ import_link10.default,
4315
+ {
4316
+ href: "/docs/v1.0.0",
4317
+ className: "inline-flex items-center rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90",
4318
+ children: "Go to Latest Version"
4319
+ }
4320
+ )
4321
+ ] }) }) });
4322
+ }
4323
+
4324
+ // src/app/layout.tsx
4325
+ var import_google = require("next/font/google");
4326
+ var import_jsx_runtime53 = require("react/jsx-runtime");
4327
+ var geist = (0, import_google.Geist)({ subsets: ["latin"] });
4328
+ var geistMono = (0, import_google.Geist_Mono)({ subsets: ["latin"] });
4329
+ function generateMetadata() {
4330
+ const config = getConfig();
4331
+ return {
4332
+ title: {
4333
+ default: config.site.title,
4334
+ template: `%s | ${config.site.title}`
4335
+ },
4336
+ description: config.site.description || "Modern documentation platform",
4337
+ generator: "Specra Documentation",
4338
+ metadataBase: config.site.url ? new URL(config.site.url) : void 0,
4339
+ icons: {
4340
+ icon: getAssetPath(config.site.favicon ?? "") ? [
4341
+ {
4342
+ url: getAssetPath(config.site.favicon ?? "")
4343
+ }
4344
+ ] : [],
4345
+ apple: getAssetPath("/apple-icon.png")
4346
+ },
4347
+ openGraph: {
4348
+ title: config.site.title,
4349
+ description: config.site.description,
4350
+ url: config.site.url,
4351
+ siteName: config.site.title,
4352
+ locale: config.site.language || "en",
4353
+ type: "website"
4354
+ },
4355
+ twitter: {
4356
+ card: "summary_large_image",
4357
+ title: config.site.title,
4358
+ description: config.site.description
4359
+ }
4360
+ };
4361
+ }
4362
+ var metadata = generateMetadata();
4363
+ function RootLayout({
4364
+ children
4365
+ }) {
4366
+ const config = getConfig();
4367
+ const defaultTab = config.navigation?.tabGroups?.[0]?.id || "";
4368
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("html", { lang: config.site.language || "en", suppressHydrationWarning: true, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("body", { className: `${geist.className} font-sans antialiased`, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(TabProvider, { defaultTab, children }) }) });
4369
+ }
4370
+
4371
+ // src/app/docs-page.tsx
4372
+ var import_react25 = require("react");
4373
+ var import_jsx_runtime54 = require("react/jsx-runtime");
4374
+ async function generateMetadata2({ params }) {
4375
+ const { version, slug: slugArray } = await params;
4376
+ const slug = slugArray.join("/");
4377
+ const doc = await getCachedDocBySlug(slug, version);
4378
+ if (!doc) {
4379
+ return {
4380
+ title: "Page Not Found",
4381
+ description: "The requested documentation page could not be found."
4382
+ };
4383
+ }
4384
+ const title = doc.meta.title || doc.title;
4385
+ const description = doc.meta.description || `Documentation for ${title}`;
4386
+ const url = `/docs/${version}/${slug}`;
4387
+ return {
4388
+ title: `${title}`,
4389
+ description,
4390
+ openGraph: {
4391
+ title,
4392
+ description,
4393
+ url,
4394
+ siteName: "Documentation Platform",
4395
+ type: "article",
4396
+ locale: "en_US"
4397
+ },
4398
+ twitter: {
4399
+ card: "summary_large_image",
4400
+ title,
4401
+ description
4402
+ },
4403
+ alternates: {
4404
+ canonical: url
4405
+ }
4406
+ };
4407
+ }
4408
+ async function generateStaticParams() {
4409
+ const versions = getCachedVersions();
4410
+ const params = [];
4411
+ for (const version of versions) {
4412
+ const docs = await getCachedAllDocs(version);
4413
+ for (const doc of docs) {
4414
+ params.push({
4415
+ version,
4416
+ slug: doc.slug.split("/").filter(Boolean)
4417
+ });
4418
+ }
4419
+ }
4420
+ return params;
4421
+ }
4422
+ async function DocPage({ params }) {
4423
+ const { version, slug: slugArray } = await params;
4424
+ const slug = slugArray.join("/");
4425
+ const allDocs = await getCachedAllDocs(version);
4426
+ const versions = getCachedVersions();
4427
+ const config = getConfig();
4428
+ const isCategory = isCategoryPage(slug, allDocs);
4429
+ const doc = await getCachedDocBySlug(slug, version);
4430
+ if (!doc && isCategory) {
4431
+ const categoryDoc = allDocs.find((d) => d.slug.startsWith(slug + "/"));
4432
+ const categoryTabGroup = categoryDoc?.meta?.tab_group || categoryDoc?.categoryTabGroup;
4433
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
4434
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4435
+ DocLayoutWrapper,
4436
+ {
4437
+ header: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Header, { currentVersion: version, versions, config }),
4438
+ docs: allDocs,
4439
+ version,
4440
+ content: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4441
+ CategoryIndex,
4442
+ {
4443
+ categoryPath: slug,
4444
+ version,
4445
+ allDocs,
4446
+ title: slug.split("/").pop()?.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) || "Category",
4447
+ description: "Browse the documentation in this section.",
4448
+ config
4449
+ }
4450
+ ),
4451
+ toc: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", {}),
4452
+ config,
4453
+ currentPageTabGroup: categoryTabGroup
4454
+ }
4455
+ ),
4456
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(MdxHotReload, {}),
4457
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(HotReloadIndicator, {}),
4458
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DevModeBadge, {})
4459
+ ] });
4460
+ }
4461
+ if (!doc) {
4462
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react25.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DocLoading, {}), children: [
4463
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4464
+ DocLayoutWrapper,
4465
+ {
4466
+ header: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Header, { currentVersion: version, versions, config }),
4467
+ docs: allDocs,
4468
+ version,
4469
+ content: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(NotFoundContent, { version }),
4470
+ toc: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", {}),
4471
+ config,
4472
+ currentPageTabGroup: void 0
4473
+ }
4474
+ ),
4475
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(MdxHotReload, {}),
4476
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(HotReloadIndicator, {}),
4477
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DevModeBadge, {})
4478
+ ] }) });
4479
+ }
4480
+ const toc = extractTableOfContents(doc.content);
4481
+ const { previous, next } = getAdjacentDocs(slug, allDocs);
4482
+ const showCategoryIndex = isCategory && doc;
4483
+ const currentPageTabGroup = doc.meta?.tab_group || doc.categoryTabGroup;
4484
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_jsx_runtime54.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_react25.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DocLoading, {}), children: [
4485
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4486
+ DocLayoutWrapper,
4487
+ {
4488
+ header: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Header, { currentVersion: version, versions, config }),
4489
+ docs: allDocs,
4490
+ version,
4491
+ content: showCategoryIndex ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4492
+ CategoryIndex,
4493
+ {
4494
+ categoryPath: slug,
4495
+ version,
4496
+ allDocs,
4497
+ title: doc.meta.title,
4498
+ description: doc.meta.description,
4499
+ content: doc.content,
4500
+ config
4501
+ }
4502
+ ) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
4503
+ DocLayout,
4504
+ {
4505
+ meta: doc.meta,
4506
+ content: doc.content,
4507
+ previousDoc: previous ? { title: previous.meta.title, slug: previous.slug } : void 0,
4508
+ nextDoc: next ? { title: next.meta.title, slug: next.slug } : void 0,
4509
+ version,
4510
+ slug,
4511
+ config
4512
+ }
4513
+ ),
4514
+ toc: showCategoryIndex ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", {}) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(TableOfContents, { items: toc, config }),
4515
+ config,
4516
+ currentPageTabGroup
4517
+ }
4518
+ ),
4519
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(MdxHotReload, {}),
4520
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(HotReloadIndicator, {}),
4521
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(DevModeBadge, {})
4522
+ ] }) });
4523
+ }
4524
+ // Annotate the CommonJS export names for ESM import in node:
4525
+ 0 && (module.exports = {
4526
+ Accordion,
4527
+ AccordionItem,
4528
+ ApiEndpoint,
4529
+ ApiParams,
4530
+ ApiPlayground,
4531
+ ApiReference,
4532
+ ApiResponse,
4533
+ ApiResponseDisplay,
4534
+ Badge,
4535
+ Breadcrumb,
4536
+ Button,
4537
+ COMPONENT_TEXT_PROPS,
4538
+ Callout,
4539
+ Card,
4540
+ CardGrid,
4541
+ CategoryIndex,
4542
+ CodeBlock,
4543
+ Column,
4544
+ Columns,
4545
+ DevModeBadge,
4546
+ Dialog,
4547
+ DialogClose,
4548
+ DialogContent,
4549
+ DialogDescription,
4550
+ DialogFooter,
4551
+ DialogHeader,
4552
+ DialogOverlay,
4553
+ DialogPortal,
4554
+ DialogTitle,
4555
+ DialogTrigger,
4556
+ DocBadge,
4557
+ DocLayout,
4558
+ DocLayoutWrapper,
4559
+ DocLoading,
4560
+ DocMetadata,
4561
+ DocNavigation,
4562
+ DocTags,
4563
+ DocsPage,
4564
+ DraftBadge,
4565
+ Footer,
4566
+ Frame,
4567
+ Header,
4568
+ HotReloadIndicator,
4569
+ Icon,
4570
+ Image,
4571
+ ImageCard,
4572
+ ImageCardGrid,
4573
+ Input,
4574
+ Math,
4575
+ MdxHotReload,
4576
+ Mermaid,
4577
+ MobileDocLayout,
4578
+ NotFoundContent,
4579
+ OpenApiParser,
4580
+ PerfTimer,
4581
+ PostmanParser,
4582
+ RootLayout,
4583
+ SearchHighlight,
4584
+ SearchModal,
4585
+ Sidebar,
4586
+ SidebarSkeleton,
4587
+ SiteBanner,
4588
+ SpecraParser,
4589
+ Step,
4590
+ Steps,
4591
+ Tab,
4592
+ TabGroups,
4593
+ TabProvider,
4594
+ TableOfContents,
4595
+ Tabs,
4596
+ Textarea,
4597
+ ThemeToggle,
4598
+ Tooltip,
4599
+ VersionNotFound,
4600
+ VersionSwitcher,
4601
+ Video,
4602
+ badgeVariants,
4603
+ buildRedirectMappings,
4604
+ buildSidebarStructure,
4605
+ buttonVariants,
4606
+ clearAllCaches,
4607
+ cn,
4608
+ debugLog,
4609
+ defaultConfig,
4610
+ detectParserType,
4611
+ extractComponentPropsText,
4612
+ extractHeadings,
4613
+ extractSearchText,
4614
+ extractTableOfContents,
4615
+ findRedirect,
4616
+ generateDocsMetadata,
4617
+ generateDocsStaticParams,
4618
+ generateRootMetadata,
4619
+ getAdjacentDocs,
4620
+ getAllCategoryConfigs,
4621
+ getAllDocs,
4622
+ getAssetPath,
4623
+ getCacheStats,
4624
+ getCachedAllDocs,
4625
+ getCachedDocBySlug,
4626
+ getCachedVersions,
4627
+ getCategoryConfig,
4628
+ getConfig,
4629
+ getConfigValue,
4630
+ getDocBySlug,
4631
+ getVersions,
4632
+ initConfig,
4633
+ isCategoryPage,
4634
+ loadConfig,
4635
+ logCacheOperation,
4636
+ logFsOperation,
4637
+ logMemoryUsage,
4638
+ mdxComponents,
4639
+ parseApiSpec,
4640
+ processContentWithEnv,
4641
+ reloadConfig,
4642
+ replaceEnvVariables,
4643
+ sortSidebarGroups,
4644
+ sortSidebarItems,
4645
+ useTabContext,
4646
+ validateConfig
4647
+ });
4648
+ //# sourceMappingURL=index.js.map