@brainfish-ai/devdoc 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +33 -0
- package/README.md +415 -0
- package/bin/devdoc.js +13 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +87 -0
- package/dist/cli/commands/check.d.ts +1 -0
- package/dist/cli/commands/check.js +143 -0
- package/dist/cli/commands/create.d.ts +24 -0
- package/dist/cli/commands/create.js +387 -0
- package/dist/cli/commands/deploy.d.ts +9 -0
- package/dist/cli/commands/deploy.js +433 -0
- package/dist/cli/commands/dev.d.ts +6 -0
- package/dist/cli/commands/dev.js +139 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.js +238 -0
- package/dist/cli/commands/keys.d.ts +12 -0
- package/dist/cli/commands/keys.js +165 -0
- package/dist/cli/commands/start.d.ts +5 -0
- package/dist/cli/commands/start.js +56 -0
- package/dist/cli/commands/upload.d.ts +13 -0
- package/dist/cli/commands/upload.js +238 -0
- package/dist/cli/commands/whoami.d.ts +8 -0
- package/dist/cli/commands/whoami.js +91 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +106 -0
- package/dist/config/index.d.ts +80 -0
- package/dist/config/index.js +133 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.js +50 -0
- package/package.json +51 -0
- package/renderer/app/api/assets/[...path]/route.ts +123 -0
- package/renderer/app/api/assets/route.ts +124 -0
- package/renderer/app/api/assets/upload/route.ts +177 -0
- package/renderer/app/api/auth-schemes/route.ts +77 -0
- package/renderer/app/api/chat/route.ts +858 -0
- package/renderer/app/api/codegen/route.ts +72 -0
- package/renderer/app/api/collections/route.ts +1016 -0
- package/renderer/app/api/debug/route.ts +53 -0
- package/renderer/app/api/deploy/route.ts +234 -0
- package/renderer/app/api/device/route.ts +42 -0
- package/renderer/app/api/docs/route.ts +187 -0
- package/renderer/app/api/keys/regenerate/route.ts +80 -0
- package/renderer/app/api/openapi-spec/route.ts +151 -0
- package/renderer/app/api/projects/[slug]/route.ts +153 -0
- package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
- package/renderer/app/api/projects/register/route.ts +152 -0
- package/renderer/app/api/proxy/route.ts +149 -0
- package/renderer/app/api/proxy-stream/route.ts +168 -0
- package/renderer/app/api/redirects/route.ts +47 -0
- package/renderer/app/api/schema/route.ts +65 -0
- package/renderer/app/api/subdomains/check/route.ts +172 -0
- package/renderer/app/api/suggestions/route.ts +144 -0
- package/renderer/app/favicon.ico +0 -0
- package/renderer/app/globals.css +1103 -0
- package/renderer/app/layout.tsx +47 -0
- package/renderer/app/llms-full.txt/route.ts +346 -0
- package/renderer/app/llms.txt/route.ts +279 -0
- package/renderer/app/page.tsx +14 -0
- package/renderer/app/robots.txt/route.ts +84 -0
- package/renderer/app/sitemap.xml/route.ts +199 -0
- package/renderer/components/docs/index.ts +12 -0
- package/renderer/components/docs/mdx/accordion.tsx +169 -0
- package/renderer/components/docs/mdx/badge.tsx +132 -0
- package/renderer/components/docs/mdx/callouts.tsx +154 -0
- package/renderer/components/docs/mdx/cards.tsx +213 -0
- package/renderer/components/docs/mdx/changelog.tsx +120 -0
- package/renderer/components/docs/mdx/code-block.tsx +186 -0
- package/renderer/components/docs/mdx/code-group.tsx +421 -0
- package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
- package/renderer/components/docs/mdx/frame.tsx +112 -0
- package/renderer/components/docs/mdx/highlight.tsx +151 -0
- package/renderer/components/docs/mdx/iframe.tsx +134 -0
- package/renderer/components/docs/mdx/image.tsx +235 -0
- package/renderer/components/docs/mdx/index.ts +204 -0
- package/renderer/components/docs/mdx/mermaid.tsx +240 -0
- package/renderer/components/docs/mdx/param-field.tsx +200 -0
- package/renderer/components/docs/mdx/steps.tsx +113 -0
- package/renderer/components/docs/mdx/tabs.tsx +86 -0
- package/renderer/components/docs/mdx-renderer.tsx +100 -0
- package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
- package/renderer/components/docs/navigation/index.ts +8 -0
- package/renderer/components/docs/navigation/page-nav.tsx +64 -0
- package/renderer/components/docs/navigation/sidebar.tsx +515 -0
- package/renderer/components/docs/navigation/toc.tsx +113 -0
- package/renderer/components/docs/notice.tsx +105 -0
- package/renderer/components/docs-header.tsx +274 -0
- package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
- package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
- package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
- package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
- package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
- package/renderer/components/docs-viewer/agent/index.tsx +6 -0
- package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
- package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
- package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
- package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
- package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
- package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
- package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
- package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
- package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
- package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
- package/renderer/components/docs-viewer/content/index.tsx +29 -0
- package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
- package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
- package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
- package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
- package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
- package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
- package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
- package/renderer/components/docs-viewer/index.tsx +1466 -0
- package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
- package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
- package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
- package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
- package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
- package/renderer/components/docs-viewer/playground/index.tsx +671 -0
- package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
- package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
- package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
- package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
- package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
- package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
- package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
- package/renderer/components/docs-viewer/search/index.ts +2 -0
- package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
- package/renderer/components/docs-viewer/search/use-search.ts +117 -0
- package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
- package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
- package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
- package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
- package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
- package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
- package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
- package/renderer/components/theme-provider.tsx +11 -0
- package/renderer/components/theme-toggle.tsx +76 -0
- package/renderer/components/ui/badge.tsx +46 -0
- package/renderer/components/ui/button.tsx +59 -0
- package/renderer/components/ui/dialog.tsx +118 -0
- package/renderer/components/ui/dropdown-menu.tsx +257 -0
- package/renderer/components/ui/input.tsx +21 -0
- package/renderer/components/ui/label.tsx +24 -0
- package/renderer/components/ui/navigation-menu.tsx +168 -0
- package/renderer/components/ui/select.tsx +190 -0
- package/renderer/components/ui/spinner.tsx +114 -0
- package/renderer/components/ui/tabs.tsx +66 -0
- package/renderer/components/ui/tooltip.tsx +61 -0
- package/renderer/hooks/use-code-copy.ts +88 -0
- package/renderer/hooks/use-openapi-title.ts +44 -0
- package/renderer/lib/api-docs/agent/index.ts +6 -0
- package/renderer/lib/api-docs/agent/indexer.ts +323 -0
- package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
- package/renderer/lib/api-docs/agent/types.ts +116 -0
- package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
- package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
- package/renderer/lib/api-docs/auth/crypto.ts +89 -0
- package/renderer/lib/api-docs/auth/index.ts +4 -0
- package/renderer/lib/api-docs/code-editor/db.ts +164 -0
- package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
- package/renderer/lib/api-docs/code-editor/index.ts +6 -0
- package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
- package/renderer/lib/api-docs/code-editor/types.ts +105 -0
- package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
- package/renderer/lib/api-docs/codegen/har.ts +251 -0
- package/renderer/lib/api-docs/codegen/index.ts +159 -0
- package/renderer/lib/api-docs/factories.ts +151 -0
- package/renderer/lib/api-docs/index.ts +17 -0
- package/renderer/lib/api-docs/mobile-context.tsx +112 -0
- package/renderer/lib/api-docs/navigation-context.tsx +88 -0
- package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
- package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
- package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
- package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
- package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
- package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
- package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
- package/renderer/lib/api-docs/playground/context.tsx +107 -0
- package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
- package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
- package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
- package/renderer/lib/api-docs/playground/types.ts +35 -0
- package/renderer/lib/api-docs/types.ts +269 -0
- package/renderer/lib/api-docs/utils.ts +311 -0
- package/renderer/lib/cache.ts +193 -0
- package/renderer/lib/docs/config/index.ts +29 -0
- package/renderer/lib/docs/config/loader.ts +142 -0
- package/renderer/lib/docs/config/schema.ts +298 -0
- package/renderer/lib/docs/index.ts +12 -0
- package/renderer/lib/docs/mdx/compiler.ts +176 -0
- package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
- package/renderer/lib/docs/mdx/index.ts +26 -0
- package/renderer/lib/docs/navigation/generator.ts +348 -0
- package/renderer/lib/docs/navigation/index.ts +12 -0
- package/renderer/lib/docs/navigation/types.ts +123 -0
- package/renderer/lib/docs-navigation-context.tsx +80 -0
- package/renderer/lib/multi-tenant/context.ts +105 -0
- package/renderer/lib/storage/blob.ts +845 -0
- package/renderer/lib/utils.ts +6 -0
- package/renderer/next.config.ts +76 -0
- package/renderer/package.json +66 -0
- package/renderer/postcss.config.mjs +5 -0
- package/renderer/public/assets/images/screenshot.png +0 -0
- package/renderer/public/assets/logo/dark.svg +9 -0
- package/renderer/public/assets/logo/light.svg +9 -0
- package/renderer/public/assets/logo.svg +9 -0
- package/renderer/public/file.svg +1 -0
- package/renderer/public/globe.svg +1 -0
- package/renderer/public/icon.png +0 -0
- package/renderer/public/logo.svg +9 -0
- package/renderer/public/window.svg +1 -0
- package/renderer/tsconfig.json +28 -0
- package/templates/basic/README.md +139 -0
- package/templates/basic/assets/favicon.svg +4 -0
- package/templates/basic/assets/logo.svg +9 -0
- package/templates/basic/docs.json +47 -0
- package/templates/basic/guides/configuration.mdx +149 -0
- package/templates/basic/guides/overview.mdx +96 -0
- package/templates/basic/index.mdx +39 -0
- package/templates/basic/package.json +14 -0
- package/templates/basic/quickstart.mdx +92 -0
- package/templates/basic/vercel.json +6 -0
- package/templates/graphql/README.md +139 -0
- package/templates/graphql/api-reference/schema.graphql +305 -0
- package/templates/graphql/assets/favicon.svg +4 -0
- package/templates/graphql/assets/logo.svg +9 -0
- package/templates/graphql/docs.json +54 -0
- package/templates/graphql/guides/configuration.mdx +149 -0
- package/templates/graphql/guides/overview.mdx +96 -0
- package/templates/graphql/index.mdx +39 -0
- package/templates/graphql/package.json +14 -0
- package/templates/graphql/quickstart.mdx +92 -0
- package/templates/graphql/vercel.json +6 -0
- package/templates/openapi/README.md +139 -0
- package/templates/openapi/api-reference/openapi.json +419 -0
- package/templates/openapi/assets/favicon.svg +4 -0
- package/templates/openapi/assets/logo.svg +9 -0
- package/templates/openapi/docs.json +61 -0
- package/templates/openapi/guides/configuration.mdx +149 -0
- package/templates/openapi/guides/overview.mdx +96 -0
- package/templates/openapi/index.mdx +39 -0
- package/templates/openapi/package.json +14 -0
- package/templates/openapi/quickstart.mdx +92 -0
- package/templates/openapi/vercel.json +6 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useState, useEffect } from 'react'
|
|
4
|
+
import { X } from '@phosphor-icons/react'
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
6
|
+
import ReactMarkdown from 'react-markdown'
|
|
7
|
+
|
|
8
|
+
export interface NoticeConfig {
|
|
9
|
+
content: string
|
|
10
|
+
dismissible?: boolean
|
|
11
|
+
background?: string // Custom background color (hex, rgb, or Tailwind class)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface NoticeProps {
|
|
15
|
+
config: NoticeConfig
|
|
16
|
+
storageKey?: string
|
|
17
|
+
className?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const STORAGE_PREFIX = 'docs-notice-dismissed-'
|
|
21
|
+
|
|
22
|
+
export function Notice({ config, storageKey = 'default', className }: NoticeProps) {
|
|
23
|
+
// For non-dismissible notices, show immediately
|
|
24
|
+
// For dismissible notices, start hidden until we check storage
|
|
25
|
+
const [isDismissed, setIsDismissed] = useState(config.dismissible ? true : false)
|
|
26
|
+
const [isLoaded, setIsLoaded] = useState(!config.dismissible)
|
|
27
|
+
|
|
28
|
+
const fullStorageKey = `${STORAGE_PREFIX}${storageKey}`
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (!config.dismissible) return
|
|
32
|
+
|
|
33
|
+
// Check if notice was previously dismissed
|
|
34
|
+
const dismissed = sessionStorage.getItem(fullStorageKey)
|
|
35
|
+
setIsDismissed(dismissed === 'true')
|
|
36
|
+
setIsLoaded(true)
|
|
37
|
+
}, [fullStorageKey, config.dismissible])
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const handleDismiss = () => {
|
|
41
|
+
sessionStorage.setItem(fullStorageKey, 'true')
|
|
42
|
+
setIsDismissed(true)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Don't render until we've checked storage (for dismissible notices)
|
|
46
|
+
if (!isLoaded) return null
|
|
47
|
+
|
|
48
|
+
// Don't render if dismissed
|
|
49
|
+
if (isDismissed && config.dismissible) return null
|
|
50
|
+
|
|
51
|
+
// Don't render if no content
|
|
52
|
+
if (!config.content) return null
|
|
53
|
+
|
|
54
|
+
// Default to a neutral dark color that works with any theme
|
|
55
|
+
const defaultBackground = '#1e293b' // slate-800
|
|
56
|
+
const backgroundStyle = {
|
|
57
|
+
backgroundColor: config.background || defaultBackground
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
className={cn(
|
|
63
|
+
'docs-notice sticky top-0 z-[100] w-full text-white',
|
|
64
|
+
'px-4 py-2.5 text-sm text-center',
|
|
65
|
+
'shadow-[0_4px_6px_-1px_rgba(0,0,0,0.3)]',
|
|
66
|
+
className
|
|
67
|
+
)}
|
|
68
|
+
style={backgroundStyle}
|
|
69
|
+
>
|
|
70
|
+
<div className="docs-notice-content max-w-screen-xl mx-auto flex items-center justify-center gap-2">
|
|
71
|
+
<div className="docs-notice-text flex-1 [&_a]:underline [&_a]:font-medium [&_a]:hover:opacity-80 [&_p]:m-0 [&_p]:inline">
|
|
72
|
+
<ReactMarkdown
|
|
73
|
+
components={{
|
|
74
|
+
// Render links properly
|
|
75
|
+
a: ({ href, children }) => (
|
|
76
|
+
<a href={href} className="underline font-medium hover:opacity-80">
|
|
77
|
+
{children}
|
|
78
|
+
</a>
|
|
79
|
+
),
|
|
80
|
+
// Render paragraphs inline
|
|
81
|
+
p: ({ children }) => <span>{children}</span>,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
{config.content}
|
|
85
|
+
</ReactMarkdown>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
{config.dismissible && (
|
|
89
|
+
<button
|
|
90
|
+
type="button"
|
|
91
|
+
onClick={handleDismiss}
|
|
92
|
+
className={cn(
|
|
93
|
+
'docs-notice-dismiss flex-shrink-0 p-1 rounded-sm',
|
|
94
|
+
'hover:bg-white/20 transition-colors',
|
|
95
|
+
'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/50'
|
|
96
|
+
)}
|
|
97
|
+
aria-label="Dismiss notice"
|
|
98
|
+
>
|
|
99
|
+
<X className="h-4 w-4" weight="bold" />
|
|
100
|
+
</button>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import Link from "next/link"
|
|
4
|
+
import Image from "next/image"
|
|
5
|
+
import { ArrowSquareOut, List, ChatCircle, X, MagnifyingGlass } from "@phosphor-icons/react"
|
|
6
|
+
import { ThemeToggle } from "@/components/theme-toggle"
|
|
7
|
+
import { useMobile } from "@/lib/api-docs/mobile-context"
|
|
8
|
+
import { Button } from "@/components/ui/button"
|
|
9
|
+
import { cn } from "@/lib/utils"
|
|
10
|
+
|
|
11
|
+
// Navigation tab from config
|
|
12
|
+
interface NavigationTab {
|
|
13
|
+
id: string
|
|
14
|
+
tab: string // Tab name (used for both navigation and page header)
|
|
15
|
+
type?: 'docs' | 'openapi' | 'changelog' | 'graphql'
|
|
16
|
+
path?: string
|
|
17
|
+
order: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Logo config from docs.json
|
|
21
|
+
interface DocsLogo {
|
|
22
|
+
url?: string
|
|
23
|
+
alt?: string
|
|
24
|
+
width?: number
|
|
25
|
+
height?: number
|
|
26
|
+
light?: string
|
|
27
|
+
dark?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Header config from docs.json
|
|
31
|
+
interface DocsHeaderConfig {
|
|
32
|
+
showSearch?: boolean
|
|
33
|
+
showThemeToggle?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Navbar config from docs.json
|
|
37
|
+
interface DocsNavbarLink {
|
|
38
|
+
label: string
|
|
39
|
+
href: string
|
|
40
|
+
external?: boolean
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface DocsNavbarPrimary {
|
|
44
|
+
label: string
|
|
45
|
+
href: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface DocsNavbar {
|
|
49
|
+
links?: DocsNavbarLink[]
|
|
50
|
+
primary?: DocsNavbarPrimary
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface DocsHeaderProps {
|
|
54
|
+
navigationTabs?: NavigationTab[]
|
|
55
|
+
activeTab: string
|
|
56
|
+
onTabChange: (tabId: string) => void
|
|
57
|
+
hasEndpoints?: boolean
|
|
58
|
+
docsName?: string | null
|
|
59
|
+
docsLogo?: DocsLogo | null
|
|
60
|
+
docsHeader?: DocsHeaderConfig | null
|
|
61
|
+
docsNavbar?: DocsNavbar | null
|
|
62
|
+
docGroups?: unknown[] // Keep for backward compatibility but not used
|
|
63
|
+
onSearchClick?: () => void
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Default logo fallback
|
|
67
|
+
const DEFAULT_LOGO = {
|
|
68
|
+
url: 'https://cdn.prod.website-files.com/639181964f4fe88697a20a0a/67af64a5ba42bb659b8560c9_Logo%20(3).svg',
|
|
69
|
+
alt: 'Logo',
|
|
70
|
+
width: 80,
|
|
71
|
+
height: 24,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function DocsHeader({
|
|
75
|
+
navigationTabs = [],
|
|
76
|
+
activeTab,
|
|
77
|
+
onTabChange,
|
|
78
|
+
docsName,
|
|
79
|
+
docsLogo,
|
|
80
|
+
docsHeader,
|
|
81
|
+
docsNavbar,
|
|
82
|
+
onSearchClick,
|
|
83
|
+
}: DocsHeaderProps) {
|
|
84
|
+
const {
|
|
85
|
+
isMobile,
|
|
86
|
+
isLeftSidebarOpen,
|
|
87
|
+
isRightSidebarOpen,
|
|
88
|
+
toggleLeftSidebar,
|
|
89
|
+
toggleRightSidebar
|
|
90
|
+
} = useMobile()
|
|
91
|
+
|
|
92
|
+
// Use config values with defaults
|
|
93
|
+
// Support both single URL and separate light/dark logos
|
|
94
|
+
const hasLightDarkLogos = docsLogo?.light && docsLogo?.dark
|
|
95
|
+
const logo = {
|
|
96
|
+
url: docsLogo?.url || DEFAULT_LOGO.url,
|
|
97
|
+
light: docsLogo?.light,
|
|
98
|
+
dark: docsLogo?.dark,
|
|
99
|
+
alt: docsLogo?.alt || DEFAULT_LOGO.alt,
|
|
100
|
+
width: docsLogo?.width || DEFAULT_LOGO.width,
|
|
101
|
+
height: docsLogo?.height || DEFAULT_LOGO.height,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const showSearch = docsHeader?.showSearch !== false // Default true
|
|
105
|
+
const showThemeToggle = docsHeader?.showThemeToggle !== false // Default true
|
|
106
|
+
|
|
107
|
+
const navbarLinks = docsNavbar?.links || []
|
|
108
|
+
const navbarPrimary = docsNavbar?.primary
|
|
109
|
+
|
|
110
|
+
// Use navigation tabs directly from config (already ordered)
|
|
111
|
+
const tabs = navigationTabs.sort((a, b) => a.order - b.order)
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<header className="docs-header sticky top-0 z-50 bg-background border-b border-border">
|
|
115
|
+
{/* Main header row */}
|
|
116
|
+
<div className="flex h-14 w-full items-center justify-between px-3 sm:px-6">
|
|
117
|
+
{/* Left side: Menu button (mobile) + Logo */}
|
|
118
|
+
<div className="flex items-center gap-2">
|
|
119
|
+
{/* Mobile menu button */}
|
|
120
|
+
{isMobile && (
|
|
121
|
+
<Button
|
|
122
|
+
variant="ghost"
|
|
123
|
+
size="icon"
|
|
124
|
+
onClick={toggleLeftSidebar}
|
|
125
|
+
className="docs-header-menu-button lg:hidden h-9 w-9"
|
|
126
|
+
aria-label={isLeftSidebarOpen ? "Close menu" : "Open menu"}
|
|
127
|
+
>
|
|
128
|
+
{isLeftSidebarOpen ? (
|
|
129
|
+
<X className="h-5 w-5" weight="bold" />
|
|
130
|
+
) : (
|
|
131
|
+
<List className="h-5 w-5" weight="bold" />
|
|
132
|
+
)}
|
|
133
|
+
</Button>
|
|
134
|
+
)}
|
|
135
|
+
|
|
136
|
+
<Link href="/" className="docs-header-logo flex items-center gap-2 sm:gap-3">
|
|
137
|
+
{hasLightDarkLogos ? (
|
|
138
|
+
<>
|
|
139
|
+
{/* Light mode logo */}
|
|
140
|
+
<Image
|
|
141
|
+
src={logo.light!}
|
|
142
|
+
alt={logo.alt}
|
|
143
|
+
width={logo.width}
|
|
144
|
+
height={logo.height}
|
|
145
|
+
className="w-auto dark:hidden"
|
|
146
|
+
style={{ height: logo.height }}
|
|
147
|
+
priority
|
|
148
|
+
/>
|
|
149
|
+
{/* Dark mode logo */}
|
|
150
|
+
<Image
|
|
151
|
+
src={logo.dark!}
|
|
152
|
+
alt={logo.alt}
|
|
153
|
+
width={logo.width}
|
|
154
|
+
height={logo.height}
|
|
155
|
+
className="w-auto hidden dark:block"
|
|
156
|
+
style={{ height: logo.height }}
|
|
157
|
+
priority
|
|
158
|
+
/>
|
|
159
|
+
</>
|
|
160
|
+
) : (
|
|
161
|
+
<Image
|
|
162
|
+
src={logo.url}
|
|
163
|
+
alt={logo.alt}
|
|
164
|
+
width={logo.width}
|
|
165
|
+
height={logo.height}
|
|
166
|
+
className="w-auto dark:invert"
|
|
167
|
+
style={{ height: logo.height }}
|
|
168
|
+
priority
|
|
169
|
+
/>
|
|
170
|
+
)}
|
|
171
|
+
{docsName && (
|
|
172
|
+
<>
|
|
173
|
+
<div className="hidden sm:block h-5 w-px bg-border" />
|
|
174
|
+
<span className="docs-header-title hidden sm:inline text-sm font-medium text-muted-foreground">
|
|
175
|
+
{docsName}
|
|
176
|
+
</span>
|
|
177
|
+
</>
|
|
178
|
+
)}
|
|
179
|
+
</Link>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
{/* Center: Search bar */}
|
|
183
|
+
{showSearch && (
|
|
184
|
+
<div className="docs-header-search hidden md:flex flex-1 max-w-md mx-6">
|
|
185
|
+
<button
|
|
186
|
+
onClick={onSearchClick}
|
|
187
|
+
className="relative w-full flex items-center gap-2 px-3 h-9 bg-muted/50 border border-border rounded-md text-sm text-muted-foreground hover:bg-muted/70 transition-colors"
|
|
188
|
+
>
|
|
189
|
+
<MagnifyingGlass className="h-4 w-4" />
|
|
190
|
+
<span className="flex-1 text-left">Search...</span>
|
|
191
|
+
<kbd className="pointer-events-none hidden sm:inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium">
|
|
192
|
+
⌘K
|
|
193
|
+
</kbd>
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
)}
|
|
197
|
+
|
|
198
|
+
{/* Right side: Nav items + Primary button + Theme toggle */}
|
|
199
|
+
<div className="flex items-center gap-1 sm:gap-2">
|
|
200
|
+
{/* Navbar links from config */}
|
|
201
|
+
{navbarLinks.length > 0 && (
|
|
202
|
+
<nav className="docs-header-nav hidden lg:flex items-center gap-1">
|
|
203
|
+
{navbarLinks.map((link) => (
|
|
204
|
+
<Link
|
|
205
|
+
key={link.href}
|
|
206
|
+
href={link.href}
|
|
207
|
+
className="docs-header-nav-link flex items-center gap-1.5 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-muted/50 rounded-sm transition-colors"
|
|
208
|
+
{...(link.external && { target: "_blank", rel: "noopener noreferrer" })}
|
|
209
|
+
>
|
|
210
|
+
<span>{link.label}</span>
|
|
211
|
+
{link.external && <ArrowSquareOut className="h-3.5 w-3.5" weight="bold" />}
|
|
212
|
+
</Link>
|
|
213
|
+
))}
|
|
214
|
+
</nav>
|
|
215
|
+
)}
|
|
216
|
+
|
|
217
|
+
{/* Primary button from config */}
|
|
218
|
+
{navbarPrimary && (
|
|
219
|
+
<Button asChild size="sm" className="docs-header-button docs-button-primary hidden sm:flex">
|
|
220
|
+
<Link href={navbarPrimary.href}>
|
|
221
|
+
{navbarPrimary.label}
|
|
222
|
+
</Link>
|
|
223
|
+
</Button>
|
|
224
|
+
)}
|
|
225
|
+
|
|
226
|
+
{showThemeToggle && <ThemeToggle />}
|
|
227
|
+
|
|
228
|
+
{/* Mobile agent button */}
|
|
229
|
+
{isMobile && (
|
|
230
|
+
<Button
|
|
231
|
+
variant="ghost"
|
|
232
|
+
size="icon"
|
|
233
|
+
onClick={toggleRightSidebar}
|
|
234
|
+
className="docs-header-button lg:hidden h-9 w-9"
|
|
235
|
+
aria-label={isRightSidebarOpen ? "Close assistant" : "Open assistant"}
|
|
236
|
+
>
|
|
237
|
+
{isRightSidebarOpen ? (
|
|
238
|
+
<X className="h-5 w-5" weight="bold" />
|
|
239
|
+
) : (
|
|
240
|
+
<ChatCircle className="h-5 w-5" weight="fill" />
|
|
241
|
+
)}
|
|
242
|
+
</Button>
|
|
243
|
+
)}
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
{/* Sub-header with tabs */}
|
|
248
|
+
{tabs.length > 0 && (
|
|
249
|
+
<div className="docs-tabs flex items-center px-3 sm:px-6 border-y border-border overflow-x-auto overflow-y-visible bg-muted/50 dark:bg-muted/20">
|
|
250
|
+
{tabs.map((t) => (
|
|
251
|
+
<button
|
|
252
|
+
key={t.id}
|
|
253
|
+
onClick={() => onTabChange(t.id)}
|
|
254
|
+
className={cn(
|
|
255
|
+
'docs-tab relative px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-colors',
|
|
256
|
+
activeTab === t.id
|
|
257
|
+
? 'docs-tab-active text-foreground font-semibold'
|
|
258
|
+
: 'text-muted-foreground hover:text-foreground'
|
|
259
|
+
)}
|
|
260
|
+
>
|
|
261
|
+
{t.tab}
|
|
262
|
+
{/* Active indicator line */}
|
|
263
|
+
{activeTab === t.id && (
|
|
264
|
+
<span
|
|
265
|
+
className="absolute bottom-0 left-0 right-0 h-[2px] rounded-full bg-primary z-10"
|
|
266
|
+
/>
|
|
267
|
+
)}
|
|
268
|
+
</button>
|
|
269
|
+
))}
|
|
270
|
+
</div>
|
|
271
|
+
)}
|
|
272
|
+
</header>
|
|
273
|
+
)
|
|
274
|
+
}
|