Files
XCSDD/src/components/ApiDocViewer.tsx

81 lines
2.4 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react'
import { DocTree } from './DocTree'
import { DocContent } from './DocContent'
import { parseMarkdown, buildFileTree } from '@/lib/parser'
import type { DocFile, ParsedDoc } from '@/lib/types'
import { config } from '@/config'
const modules = import.meta.glob('../docs/**/*.md', { as: 'raw', eager: true })
const DOCS_FILES: Record<string, string> = Object.fromEntries(
Object.entries(modules).map(([path, content]) => {
const relativePath = path.replace('../docs/', '')
return [relativePath, content as string]
})
)
export const ApiDocViewer = () => {
const [fileTree, setFileTree] = useState<DocFile[]>([])
const [selectedPath, setSelectedPath] = useState<string | undefined>()
const [currentDoc, setCurrentDoc] = useState<ParsedDoc | null>(null)
useEffect(() => {
const files = Object.keys(DOCS_FILES)
const tree = buildFileTree(files, '/')
setFileTree(tree)
if (files.length > 0) {
setSelectedPath(files[0])
}
}, [])
useEffect(() => {
if (selectedPath) {
const content = DOCS_FILES[selectedPath]
if (content) {
const parsed = parseMarkdown(content)
setCurrentDoc(parsed)
}
}
}, [selectedPath])
const handleSelect = useCallback((file: DocFile) => {
if (!file.isDir) {
setSelectedPath(file.relativePath)
}
}, [])
const handleReferenceClick = useCallback((ref: string) => {
const normalizedRef = ref.replace('.md', '').replace(/^\.\.\//, '')
const allFiles = Object.keys(DOCS_FILES)
const match = allFiles.find(f => f.replace('.md', '') === normalizedRef)
if (match) {
setSelectedPath(match)
}
}, [])
return (
<div className="flex h-screen bg-[#1e1e1e]">
<aside className="w-64 bg-[#252526] border-r border-[#3c3c3c] flex flex-col">
<div className="p-3 border-b border-[#3c3c3c]">
<h2 className="text-sm font-semibold text-gray-200">{config.sidebarTitle}</h2>
</div>
<div className="flex-1 overflow-hidden">
<DocTree
files={fileTree}
selectedPath={selectedPath}
onSelect={handleSelect}
/>
</div>
</aside>
<main className="flex-1 overflow-hidden">
<DocContent
doc={currentDoc}
onReferenceClick={handleReferenceClick}
/>
</main>
</div>
)
}