64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { X } from 'lucide-react';
|
|
import { getIcon } from 'material-file-icons';
|
|
import type { OpenFile } from './useEditorState';
|
|
|
|
type EditorTabsProps = {
|
|
files: OpenFile[];
|
|
activePath: string | null;
|
|
onSelect: (path: string) => void;
|
|
onClose: (path: string) => void;
|
|
theme?: string;
|
|
};
|
|
|
|
const FileIcon = ({ name }: { name: string }) => {
|
|
const svg = useMemo(() => getIcon(name).svg, [name]);
|
|
return <span className="inline-flex h-4 w-4 shrink-0" dangerouslySetInnerHTML={{ __html: svg }} />;
|
|
};
|
|
|
|
export const EditorTabs = ({ files, activePath, onSelect, onClose, theme }: EditorTabsProps) => {
|
|
if (files.length === 0) return null;
|
|
|
|
const isDark = theme !== 'vs';
|
|
const borderColor = isDark ? '#333' : '#e0e0e0';
|
|
const activeBg = isDark ? '#1e1e1e' : '#ffffff';
|
|
const inactiveBg = isDark ? '#181818' : '#f3f3f3';
|
|
const activeColor = isDark ? '#ccc' : '#333';
|
|
const inactiveColor = isDark ? '#888' : '#666';
|
|
|
|
return (
|
|
<div className="flex items-center overflow-x-auto shrink-0 code-editor-scrollable" style={{ borderBottom: `1px solid ${borderColor}` }}>
|
|
{files.map((file) => {
|
|
const isActive = file.path === activePath;
|
|
return (
|
|
<button
|
|
key={file.path}
|
|
onClick={() => onSelect(file.path)}
|
|
className="flex items-center gap-1.5 px-3 py-1.5 text-sm cursor-pointer whitespace-nowrap transition-colors"
|
|
style={{
|
|
background: isActive ? activeBg : inactiveBg,
|
|
color: isActive ? activeColor : inactiveColor,
|
|
borderRight: `1px solid ${borderColor}`,
|
|
}}
|
|
>
|
|
<FileIcon name={file.name} />
|
|
<span>{file.name}</span>
|
|
{file.isDirty && <span className="w-2 h-2 rounded-full bg-blue-400 shrink-0" />}
|
|
<span
|
|
role="button"
|
|
className="ml-1 p-0.5 rounded transition-colors"
|
|
style={{ color: inactiveColor }}
|
|
onClick={(ev) => {
|
|
ev.stopPropagation();
|
|
onClose(file.path);
|
|
}}
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
};
|