85 lines
2.2 KiB
TypeScript
85 lines
2.2 KiB
TypeScript
/**
|
|
* FileManager — pluggable file browser for S3/MinIO files.
|
|
*
|
|
* Handles both input file selection and output file listing.
|
|
* Used by timeline (assets + output), chunker (assets + chunk output),
|
|
* and future tools.
|
|
*/
|
|
|
|
import type { ReactNode } from "react";
|
|
import { formatSize } from "../utils/format";
|
|
import "./FileManager.css";
|
|
|
|
export interface FileEntry {
|
|
key: string;
|
|
name: string;
|
|
size?: number;
|
|
meta?: string;
|
|
}
|
|
|
|
interface FileManagerProps {
|
|
title: string;
|
|
files: FileEntry[];
|
|
selectedKey?: string | null;
|
|
onSelect?: (file: FileEntry) => void;
|
|
onScan?: () => void;
|
|
scanning?: boolean;
|
|
emptyMessage?: string;
|
|
renderActions?: (file: FileEntry) => ReactNode;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
export function FileManager({
|
|
title,
|
|
files,
|
|
selectedKey,
|
|
onSelect,
|
|
onScan,
|
|
scanning = false,
|
|
emptyMessage = "No files",
|
|
renderActions,
|
|
disabled = false,
|
|
}: FileManagerProps) {
|
|
return (
|
|
<div className="file-manager">
|
|
<div className="fm-header">
|
|
<h2>{title}</h2>
|
|
{onScan && (
|
|
<button
|
|
className="fm-scan-btn"
|
|
onClick={onScan}
|
|
disabled={scanning || disabled}
|
|
>
|
|
{scanning ? "Scanning..." : "Scan Folder"}
|
|
</button>
|
|
)}
|
|
</div>
|
|
<ul className="fm-list">
|
|
{files.length === 0 ? (
|
|
<li className="fm-empty">{emptyMessage}</li>
|
|
) : (
|
|
files.map((file) => (
|
|
<li
|
|
key={file.key}
|
|
className={`fm-item ${selectedKey === file.key ? "fm-selected" : ""} ${onSelect && !disabled ? "fm-clickable" : ""}`}
|
|
onClick={() => onSelect && !disabled && onSelect(file)}
|
|
title={file.name}
|
|
>
|
|
<div className="fm-item-info">
|
|
<span className="fm-filename">{file.name}</span>
|
|
<span className="fm-meta">
|
|
{file.size != null && formatSize(file.size)}
|
|
{file.meta && (file.size != null ? ` · ${file.meta}` : file.meta)}
|
|
</span>
|
|
</div>
|
|
{renderActions && (
|
|
<div className="fm-actions">{renderActions(file)}</div>
|
|
)}
|
|
</li>
|
|
))
|
|
)}
|
|
</ul>
|
|
</div>
|
|
);
|
|
}
|