Files
platform/src/workspaces/plugins/FileBrowser/client/Screen/Toolbar.tsx
T
2026-02-16 19:34:35 +00:00

198 lines
5.8 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
import { FolderPlus, Upload, FolderUp, Scissors, Copy, ClipboardPaste, Trash2, X, Check } from 'lucide-react';
type ToolbarProps = {
onCreateDir: (name: string) => void;
onUpload: (files: FileList) => void;
selectionCount: number;
hasClipboard: boolean;
onCut: () => void;
onCopy: () => void;
onPaste: () => void;
onDeleteSelected: () => void;
onClearSelection: () => void;
};
export const Toolbar = ({
onCreateDir,
onUpload,
selectionCount,
hasClipboard,
onCut,
onCopy,
onPaste,
onDeleteSelected,
onClearSelection,
}: ToolbarProps) => {
const [showInput, setShowInput] = useState(false);
const [folderName, setFolderName] = useState('');
const fileInputRef = useRef<HTMLInputElement | null>(null);
const folderInputRef = useRef<HTMLInputElement | null>(null);
useEffect(() => {
const input = folderInputRef.current;
if (!input) return;
input.setAttribute('webkitdirectory', '');
}, []);
const handleCreate = () => {
const name = folderName.trim();
if (!name) return;
onCreateDir(name);
setFolderName('');
setShowInput(false);
};
if (selectionCount > 0) {
return (
<div className="flex items-center gap-1">
<span className="text-sm font-medium text-duck-dark/70 mr-1">
{selectionCount}
<span className="hidden md:inline"> selected</span>
</span>
<button
onClick={onCut}
title="Cut"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<Scissors className="h-4 w-4" />
</button>
<button
onClick={onCopy}
title="Copy"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<Copy className="h-4 w-4" />
</button>
{hasClipboard && (
<button
onClick={onPaste}
title="Paste"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<ClipboardPaste className="h-4 w-4" />
</button>
)}
<button
onClick={onDeleteSelected}
title="Delete"
className="p-1.5 rounded-md text-red-500 hover:bg-red-50 cursor-pointer transition-colors"
>
<Trash2 className="h-4 w-4" />
</button>
<button
onClick={onClearSelection}
title="Clear selection"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<X className="h-4 w-4" />
</button>
</div>
);
}
return (
<div className="flex items-center gap-1">
{showInput ? (
<form
onSubmit={(ev) => {
ev.preventDefault();
handleCreate();
}}
className="flex items-center gap-2"
>
<input
autoFocus
value={folderName}
onChange={(ev) => setFolderName(ev.target.value)}
placeholder="Folder name"
className="h-8 w-40 text-sm rounded-md border border-duck-dark/20 bg-white/60 text-duck-dark placeholder:text-duck-dark/40 outline-none focus:border-duck-teal/50 px-2"
onKeyDown={(ev) => {
if (ev.key === 'Escape') {
setShowInput(false);
setFolderName('');
}
}}
/>
<button
type="submit"
className="p-1.5 rounded-md text-duck-teal hover:bg-duck-dark/5 cursor-pointer transition-colors"
title="Create"
>
<Check className="h-4 w-4" />
</button>
<button
type="button"
onClick={() => {
setShowInput(false);
setFolderName('');
}}
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
title="Cancel"
>
<X className="h-4 w-4" />
</button>
</form>
) : (
<button
onClick={() => setShowInput(true)}
title="New folder"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<FolderPlus className="h-4 w-4" />
</button>
)}
<button
onClick={() => fileInputRef.current?.click()}
title="Upload files"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<Upload className="h-4 w-4" />
</button>
<button
onClick={() => folderInputRef.current?.click()}
title="Upload folder"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<FolderUp className="h-4 w-4" />
</button>
{hasClipboard && (
<button
onClick={onPaste}
title="Paste"
className="p-1.5 rounded-md text-duck-dark/50 hover:bg-duck-dark/5 cursor-pointer transition-colors"
>
<ClipboardPaste className="h-4 w-4" />
</button>
)}
<input
ref={fileInputRef}
type="file"
multiple
className="hidden"
onChange={(ev) => {
if (ev.target.files?.length) {
onUpload(ev.target.files);
ev.target.value = '';
}
}}
/>
<input
ref={folderInputRef}
type="file"
className="hidden"
onChange={(ev) => {
if (ev.target.files?.length) {
onUpload(ev.target.files);
ev.target.value = '';
}
}}
/>
</div>
);
};