Files
Netcatty/components/keychain/KeyCard.tsx
T
LAPTOP-O016UC3M\Qi Chen b8c221d112 Organize and normalize imports across project
Reorder and normalize import statements, group icon imports, and add
missing utility imports (cn). Fix export/newline formatting and minor
type import tweaks. Add ESLint scripts to package.json and update the
lockfile.
2025-12-11 16:01:03 +08:00

112 lines
4.2 KiB
TypeScript

/**
* Key Card component for displaying SSH keys in grid/list view
*/
import { Copy,ExternalLink,Pencil,Trash2 } from 'lucide-react';
import React from 'react';
import { cn } from '../../lib/utils';
import { SSHKey } from '../../types';
import { Button } from '../ui/button';
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from '../ui/context-menu';
import { getKeyIcon,getKeyTypeDisplay } from './utils';
interface KeyCardProps {
keyItem: SSHKey;
viewMode: 'grid' | 'list';
isSelected: boolean;
isMac: boolean;
onClick: () => void;
onEdit: () => void;
onExport: () => void;
onCopyPublicKey: () => void;
onDelete: () => void;
}
export const KeyCard: React.FC<KeyCardProps> = ({
keyItem,
viewMode,
isSelected,
isMac,
onClick,
onEdit,
onExport,
onCopyPublicKey,
onDelete,
}) => {
return (
<ContextMenu>
<ContextMenuTrigger asChild>
<div
className={cn(
"group cursor-pointer",
viewMode === 'grid'
? "soft-card elevate rounded-xl h-[68px] px-3 py-2"
: "h-14 px-3 py-2 hover:bg-secondary/60 rounded-lg transition-colors",
isSelected && "ring-2 ring-primary"
)}
onClick={onClick}
>
<div className="flex items-center gap-3 h-full">
<div className={cn(
"h-11 w-11 rounded-xl flex items-center justify-center",
keyItem.source === 'biometric'
? "bg-blue-500/15 text-blue-500"
: keyItem.source === 'fido2'
? "bg-amber-500/15 text-amber-500"
: "bg-primary/15 text-primary"
)}>
{getKeyIcon(keyItem)}
</div>
<div className="min-w-0 flex-1">
<div className="text-sm font-semibold truncate">{keyItem.label}</div>
<div className="text-[11px] font-mono text-muted-foreground truncate">
Type {getKeyTypeDisplay(keyItem, isMac)}
</div>
</div>
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
{viewMode === 'list' && (
<Button
size="icon"
variant="ghost"
className="h-8 w-8"
onClick={(e) => {
e.stopPropagation();
onEdit();
}}
>
<Pencil size={14} />
</Button>
)}
</div>
</div>
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem onClick={onCopyPublicKey} disabled={!keyItem.publicKey}>
<Copy size={14} className="mr-2" />
Copy Public Key
</ContextMenuItem>
<ContextMenuItem onClick={onExport}>
<ExternalLink size={14} className="mr-2" />
Key Export
</ContextMenuItem>
<ContextMenuItem onClick={onEdit}>
<Pencil size={14} className="mr-2" />
Edit
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem onClick={onDelete} className="text-destructive focus:text-destructive">
<Trash2 size={14} className="mr-2" />
Delete
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
);
};