import React from 'react'; import { ArrowUp } from 'lucide-react'; import type { Action } from '@/actions/types'; import { VfsContextMenuRow } from '@/modules/storage/VfsContextMenu'; import type { INode } from './types'; import { FOCUS_BG, FOCUS_BORDER, SELECTED_BG, SELECTED_BORDER } from './types'; import { getMimeCategory, CATEGORY_STYLE } from './helpers'; import { NodeIcon, ThumbPreview } from './ThumbPreview'; // ── Props ──────────────────────────────────────────────────────── interface FileGridViewProps { listRef: React.RefObject; sorted: INode[]; canGoUp: boolean; goUp: () => void; focusIdx: number; setFocusIdx: (idx: number) => void; selected: INode[]; onItemClick: (idx: number, e?: React.MouseEvent) => void; onItemDoubleClick: (idx: number) => void; thumbSize: number; mount: string; tokenParam: string; fontSize: number; isSearchMode?: boolean; vfsContextMenuActions?: Action[]; onVfsContextMenuOpen?: (idx: number) => void; } // ── Component ──────────────────────────────────────────────────── const FileGridView: React.FC = ({ listRef, sorted, canGoUp, goUp, focusIdx, setFocusIdx, selected, onItemClick, onItemDoubleClick, thumbSize, mount, tokenParam, fontSize, isSearchMode, vfsContextMenuActions, onVfsContextMenuOpen, }) => { const menuOn = Boolean(vfsContextMenuActions?.length && onVfsContextMenuOpen); const wrapRow = (stableKey: string, idx: number, row: React.ReactElement) => menuOn ? ( onVfsContextMenuOpen!(idx)} > {row} ) : ( React.cloneElement(row, { key: stableKey }) ); return (
{canGoUp && !isSearchMode && wrapRow('fb-up', 0, (
setFocusIdx(0)} onDoubleClick={goUp} className="fb-thumb" data-testid="file-grid-node-up" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 2, borderRadius: 2, cursor: 'pointer', gap: 2, aspectRatio: '1', borderWidth: 1, borderColor: 'transparent', borderStyle: 'solid', background: focusIdx === 0 ? FOCUS_BG : 'transparent', outline: focusIdx === 0 ? `2px solid ${FOCUS_BORDER}` : 'none', outlineOffset: '2px', }}> ..
))} {sorted.map((node, i) => { const idx = ((canGoUp && !isSearchMode) ? i + 1 : i); const isDir = getMimeCategory(node) === 'dir'; const isFocused = focusIdx === idx; const isSelected = selected.some(sel => sel.path === node.path); const { _uploading, _progress, _error } = node as any; return wrapRow(node.path || node.name, idx, (
onItemClick(idx, e)} onDoubleClick={() => !_uploading && onItemDoubleClick(idx)} className="fb-thumb" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 6, borderRadius: 6, cursor: _uploading ? 'default' : 'pointer', gap: 6, overflow: 'hidden', background: isSelected ? 'rgba(59, 130, 246, 0.05)' : 'transparent', opacity: (_uploading || _error) ? 0.7 : 1, }}>
{isDir ? : } {_uploading && (
)} {_error && (
{_error}
)}
{node.name} {isSearchMode && ( {node.parent || '/'} )}
)); })}
); }; export default FileGridView;