meatloaf-config/src/app/components/DirectoryListing.tsx

98 lines
3.2 KiB
TypeScript

import { useState } from 'react';
import { Type } from 'lucide-react';
export type DirectoryFont = 'C64_Pro_Mono' | 'CbmShift';
const FONTS: { id: DirectoryFont; label: string }[] = [
{ id: 'C64_Pro_Mono', label: 'C64 Pro' },
{ id: 'CbmShift', label: 'CBM Shift' },
];
export interface DirectoryEntry {
blocks: number;
name: string;
type: string;
}
interface DirectoryListingProps {
entries: DirectoryEntry[];
footerNote?: string;
}
const TYPE_BADGE: Record<string, string> = {
PRG: 'bg-blue-100 text-blue-700',
SEQ: 'bg-green-100 text-green-700',
DEL: 'bg-neutral-200 text-neutral-500',
REL: 'bg-purple-100 text-purple-700',
USR: 'bg-orange-100 text-orange-700',
};
export default function DirectoryListing({ entries, footerNote }: DirectoryListingProps) {
const [font, setFont] = useState<DirectoryFont>('C64_Pro_Mono');
return (
<div className="flex flex-col h-full" style={{ fontFamily: `'${font}', monospace` }}>
{/* Font toggle bar */}
<div className="flex items-center justify-end gap-2 px-4 py-2 border-b border-neutral-200 bg-neutral-50">
<Type className="w-4 h-4 text-neutral-500" />
<span className="text-xs text-neutral-500">Font:</span>
<div className="inline-flex rounded-md border border-neutral-300 bg-white overflow-hidden">
{FONTS.map((f, idx) => (
<button
key={f.id}
onClick={() => setFont(f.id)}
className={`px-3 py-1 text-xs ${
font === f.id
? 'bg-blue-600 text-white'
: 'bg-white text-neutral-700 hover:bg-neutral-100'
} ${idx > 0 ? 'border-l border-neutral-300' : ''}`}
aria-pressed={font === f.id}
>
{f.label}
</button>
))}
</div>
</div>
{/* Listing */}
<div className="flex-1 overflow-auto text-sm">
{entries.length === 0 ? (
<div className="p-8 text-center text-neutral-500">
Empty directory
</div>
) : (
entries.map((entry, idx) => (
<div
key={idx}
className="px-4 py-2 border-b border-neutral-100 flex items-center hover:bg-neutral-50"
>
<span className="inline-block w-16 text-neutral-700 flex-shrink-0">
{String(entry.blocks).padStart(3, ' ')}
</span>
<span className="inline-block w-40 truncate text-neutral-900 flex-shrink-0">
{entry.name}
</span>
<span className="inline-block w-16 flex-shrink-0">
<span
className={`px-1.5 py-0.5 rounded text-xs font-medium ${
TYPE_BADGE[entry.type] || 'bg-neutral-200 text-neutral-700'
}`}
style={{ fontFamily: 'system-ui, sans-serif' }}
>
{entry.type}
</span>
</span>
</div>
))
)}
</div>
{footerNote && (
<div className="px-4 py-3 text-xs text-neutral-500 border-t border-neutral-200">
{footerNote}
</div>
)}
</div>
);
}