mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-07-07 06:02:43 +08:00
163 lines
5.7 KiB
TypeScript
163 lines
5.7 KiB
TypeScript
import { Code2, Download, Eye, Maximize2, Minimize2, Save, Settings as SettingsIcon, X } from 'lucide-react';
|
|
|
|
import type { CodeEditorFile } from '../../types/types';
|
|
|
|
type CodeEditorHeaderProps = {
|
|
file: CodeEditorFile;
|
|
isSidebar: boolean;
|
|
isFullscreen: boolean;
|
|
isMarkdownFile: boolean;
|
|
isHtmlPreviewFile: boolean;
|
|
markdownPreview: boolean;
|
|
saving: boolean;
|
|
saveSuccess: boolean;
|
|
onToggleMarkdownPreview: () => void;
|
|
onOpenHtmlPreview: () => void;
|
|
onOpenSettings: () => void;
|
|
onDownload: () => void;
|
|
onSave: () => void;
|
|
onToggleFullscreen: () => void;
|
|
onClose: () => void;
|
|
labels: {
|
|
showingChanges: string;
|
|
editMarkdown: string;
|
|
previewMarkdown: string;
|
|
previewHtml: string;
|
|
settings: string;
|
|
download: string;
|
|
save: string;
|
|
saving: string;
|
|
saved: string;
|
|
fullscreen: string;
|
|
exitFullscreen: string;
|
|
close: string;
|
|
};
|
|
};
|
|
|
|
export default function CodeEditorHeader({
|
|
file,
|
|
isSidebar,
|
|
isFullscreen,
|
|
isMarkdownFile,
|
|
isHtmlPreviewFile,
|
|
markdownPreview,
|
|
saving,
|
|
saveSuccess,
|
|
onToggleMarkdownPreview,
|
|
onOpenHtmlPreview,
|
|
onOpenSettings,
|
|
onDownload,
|
|
onSave,
|
|
onToggleFullscreen,
|
|
onClose,
|
|
labels,
|
|
}: CodeEditorHeaderProps) {
|
|
const saveTitle = saveSuccess ? labels.saved : saving ? labels.saving : labels.save;
|
|
|
|
return (
|
|
<div className="flex min-w-0 flex-shrink-0 items-center justify-between gap-2 border-b border-border px-3 py-1.5">
|
|
{/* File info - can shrink */}
|
|
<div className="flex min-w-0 flex-1 shrink items-center gap-2">
|
|
<div className="min-w-0 shrink">
|
|
<div className="flex min-w-0 items-center gap-2">
|
|
<h3 className="truncate text-sm font-medium text-gray-900 dark:text-white">{file.name}</h3>
|
|
{file.diffInfo && (
|
|
<span className="shrink-0 whitespace-nowrap rounded bg-blue-100 px-1.5 py-0.5 text-[10px] text-blue-600 dark:bg-blue-900 dark:text-blue-300">
|
|
{labels.showingChanges}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<p className="truncate text-xs text-gray-500 dark:text-gray-400">{file.path}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Buttons - don't shrink, always visible */}
|
|
<div className="flex shrink-0 items-center gap-0.5">
|
|
{isMarkdownFile && (
|
|
<button
|
|
type="button"
|
|
onClick={onToggleMarkdownPreview}
|
|
className={`flex items-center justify-center rounded-md p-1.5 transition-colors ${
|
|
markdownPreview
|
|
? 'bg-blue-50 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400'
|
|
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white'
|
|
}`}
|
|
title={markdownPreview ? labels.editMarkdown : labels.previewMarkdown}
|
|
>
|
|
{markdownPreview ? <Code2 className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
|
|
</button>
|
|
)}
|
|
|
|
{isHtmlPreviewFile && (
|
|
<button
|
|
type="button"
|
|
onClick={onOpenHtmlPreview}
|
|
className="flex items-center justify-center rounded-md p-1.5 text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white"
|
|
title={labels.previewHtml}
|
|
>
|
|
<Eye className="h-4 w-4" />
|
|
</button>
|
|
)}
|
|
|
|
<button
|
|
type="button"
|
|
onClick={onOpenSettings}
|
|
className="flex items-center justify-center rounded-md p-1.5 text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white"
|
|
title={labels.settings}
|
|
>
|
|
<SettingsIcon className="h-4 w-4" />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
onClick={onDownload}
|
|
className="flex items-center justify-center rounded-md p-1.5 text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white"
|
|
title={labels.download}
|
|
>
|
|
<Download className="h-4 w-4" />
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
onClick={onSave}
|
|
disabled={saving}
|
|
className={`flex items-center justify-center rounded-md p-1.5 transition-colors disabled:opacity-50 ${
|
|
saveSuccess
|
|
? 'bg-green-50 text-green-600 dark:bg-green-900/30 dark:text-green-400'
|
|
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white'
|
|
}`}
|
|
title={saveTitle}
|
|
>
|
|
{saveSuccess ? (
|
|
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
</svg>
|
|
) : (
|
|
<Save className="h-4 w-4" />
|
|
)}
|
|
</button>
|
|
|
|
{!isSidebar && (
|
|
<button
|
|
type="button"
|
|
onClick={onToggleFullscreen}
|
|
className="flex items-center justify-center rounded-md p-1.5 text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white"
|
|
title={isFullscreen ? labels.exitFullscreen : labels.fullscreen}
|
|
>
|
|
{isFullscreen ? <Minimize2 className="h-4 w-4" /> : <Maximize2 className="h-4 w-4" />}
|
|
</button>
|
|
)}
|
|
|
|
<button
|
|
type="button"
|
|
onClick={onClose}
|
|
className="flex items-center justify-center rounded-md p-1.5 text-gray-600 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-white"
|
|
title={labels.close}
|
|
>
|
|
<X className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|