'use client'; import React from 'react'; import { FileText, GitBranch, Loader2 } from 'lucide-react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { Badge } from '@/components/ui/badge'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import type { SkillFileContent, SkillFileInfo, SkillVersionRef } from '@/types'; type SkillDetailViewProps = { title: string; summary?: string | null; badges?: React.ReactNode; actions?: React.ReactNode; currentVersion: string; versions: SkillVersionRef[]; files: SkillFileInfo[]; content: string; selectedFile?: SkillFileContent | null; loadingFile?: boolean; loadingVersion?: boolean; onSelectVersion: (version: string) => void; onOpenFile: (filePath: string) => void; labels: { overview: string; files: string; versions: string; noReadme: string; noFiles: string; selectFile: string; binaryFile: string; current: string; size: string; }; }; export function SkillDetailView({ title, summary, badges, actions, currentVersion, versions, files, content, selectedFile, loadingFile, loadingVersion, onSelectVersion, onOpenFile, labels, }: SkillDetailViewProps) { const readme = stripFrontmatter(content || ''); return (
{badges} v{currentVersion || '-'} {loadingVersion && }

{title}

{summary &&

{summary}

}
{actions}
{labels.overview} {labels.files} {labels.versions} {readme.trim() ? ( ) : ( } text={labels.noReadme} /> )}
{files.length === 0 ? ( } text={labels.noFiles} /> ) : (
{files.map((file) => ( ))}
)}
{loadingFile ? (
) : selectedFile ? ( ) : ( } text={labels.selectFile} /> )}
{versions.map((version) => ( ))}
); } function FilePreview({ file, labels }: { file: SkillFileContent; labels: SkillDetailViewProps['labels'] }) { const content = file.content || ''; return (
{file.filePath}
{labels.size}: {formatBytes(file.fileSize)}
{file.isBinary ? ( } text={labels.binaryFile} /> ) : isMarkdown(file.filePath, file.contentType) ? ( ) : (
          {content}
        
)}
); } function MarkdownPreview({ content }: { content: string }) { return (
{content}
); } function EmptyPanel({ icon, text }: { icon: React.ReactNode; text: string }) { return (
{icon}

{text}

); } function stripFrontmatter(value: string): string { if (!value.startsWith('---')) return value; const marker = value.indexOf('\n---', 3); if (marker < 0) return value; const after = value.indexOf('\n', marker + 4); return after >= 0 ? value.slice(after + 1) : ''; } function isMarkdown(filePath: string, contentType?: string | null): boolean { return filePath.toLowerCase().endsWith('.md') || (contentType || '').includes('markdown'); } function formatBytes(value: number | undefined): string { const size = Number(value || 0); if (size < 1024) return `${size} B`; if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`; return `${(size / 1024 / 1024).toFixed(1)} MB`; }