import type { RefObject } from 'preact'; import { Archive, ArrowUpDown, Check, CheckCheck, FolderInput, Plus, RefreshCw, RotateCcw, Trash2, X } from 'lucide-preact'; import type { Cipher } from '@/lib/types'; import { t } from '@/lib/i18n'; import { CREATE_TYPE_OPTIONS, CreateTypeIcon, VAULT_SORT_OPTIONS, VaultListIcon, type SidebarFilter, type VaultSortMode, } from '@/components/vault/vault-page-helpers'; interface VirtualRange { start: number; end: number; padTop: number; padBottom: number; } interface VaultListPanelProps { busy: boolean; loading: boolean; searchInput: string; sortMode: VaultSortMode; sortMenuOpen: boolean; selectedCount: number; totalCipherCount: number; filteredCiphers: Cipher[]; visibleCiphers: Cipher[]; virtualRange: VirtualRange; selectedCipherId: string; selectedMap: Record; sidebarFilter: SidebarFilter; createMenuOpen: boolean; createMenuRef: RefObject; sortMenuRef: RefObject; listPanelRef: RefObject; onSearchInput: (value: string) => void; onClearSearch: () => void; onSearchCompositionStart: () => void; onSearchCompositionEnd: (value: string) => void; onToggleSortMenu: () => void; onSelectSortMode: (value: VaultSortMode) => void; onSyncVault: () => void; onOpenBulkDelete: () => void; onSelectDuplicates: () => void; onSelectAll: () => void; onToggleCreateMenu: () => void; onStartCreate: (type: number) => void; onBulkRestore: () => void; onBulkArchive: () => void; onBulkUnarchive: () => void; onOpenMove: () => void; onClearSelection: () => void; onScroll: (top: number) => void; onToggleSelected: (cipherId: string, checked: boolean) => void; onSelectCipher: (cipherId: string) => void; listSubtitle: (cipher: Cipher) => string; } export default function VaultListPanel(props: VaultListPanelProps) { return (
props.onSearchInput((e.currentTarget as HTMLInputElement).value)} onCompositionStart={props.onSearchCompositionStart} onCompositionEnd={(e) => props.onSearchCompositionEnd((e.currentTarget as HTMLInputElement).value)} onKeyDown={(e) => { if (e.key !== 'Escape' || !props.searchInput) return; e.preventDefault(); props.onClearSearch(); }} /> {!!props.searchInput && ( )}
{props.sortMenuOpen && (
{VAULT_SORT_OPTIONS.map((option) => ( ))}
)}
{t('txt_total_items_count', { count: props.totalCipherCount })}
{props.sidebarFilter.kind === 'duplicates' && ( )} {props.selectedCount > 0 && props.sidebarFilter.kind === 'trash' && ( )} {props.selectedCount > 0 && props.sidebarFilter.kind === 'archive' && ( )} {props.selectedCount > 0 && props.sidebarFilter.kind !== 'trash' && props.sidebarFilter.kind !== 'archive' && props.sidebarFilter.kind !== 'duplicates' && ( )} {props.selectedCount > 0 && props.sidebarFilter.kind !== 'trash' && props.sidebarFilter.kind !== 'archive' && props.sidebarFilter.kind !== 'duplicates' && ( )} {props.selectedCount > 0 && ( )}
{props.createMenuOpen && (
{CREATE_TYPE_OPTIONS.map((option) => ( ))}
)}
props.onScroll((event.currentTarget as HTMLDivElement).scrollTop)}> {!!props.filteredCiphers.length && (
{props.visibleCiphers.map((cipher, index) => (
{ const target = event.target as HTMLElement; if (target.closest('.row-check')) return; props.onSelectCipher(cipher.id); }} > event.stopPropagation()} onInput={(e) => props.onToggleSelected(cipher.id, (e.currentTarget as HTMLInputElement).checked)} />
))}
)} {!props.filteredCiphers.length &&
{t('txt_no_items')}
}
); }