'use client'; import { useMemo, useState } from 'react'; import { ChevronDown, ChevronRight } from 'lucide-react'; import { Button } from '@spoon/ui'; import type { DiffMode } from './diff-file-view'; import type { DiffFileStatus, ParsedDiffFile } from './diff-utils'; import { DiffFileView, useDiffTheme } from './diff-file-view'; import { parseDiffFiles } from './diff-utils'; const statusBadge: Record< DiffFileStatus, { label: string; className: string } > = { added: { label: 'Added', className: 'bg-emerald-500/15 text-emerald-500' }, deleted: { label: 'Deleted', className: 'bg-red-500/15 text-red-500' }, modified: { label: 'Modified', className: 'bg-amber-500/15 text-amber-500' }, renamed: { label: 'Renamed', className: 'bg-sky-500/15 text-sky-500' }, }; const totals = (files: ParsedDiffFile[]) => files.reduce( (acc, file) => ({ additions: acc.additions + file.additions, deletions: acc.deletions + file.deletions, }), { additions: 0, deletions: 0 }, ); const FileCard = ({ file, mode, theme, defaultOpen, }: { file: ParsedDiffFile; mode: DiffMode; theme: 'light' | 'dark'; defaultOpen: boolean; }) => { const [open, setOpen] = useState(defaultOpen); const badge = statusBadge[file.status]; return (
{open ? (
) : null}
); }; export const DiffViewer = ({ diff, focusedPath, onRefresh, onClearFocusedPath, }: { diff: string; focusedPath?: string; onRefresh: () => Promise; onClearFocusedPath?: () => void; }) => { const [mode, setMode] = useState('unified'); const theme = useDiffTheme(); const files = useMemo(() => parseDiffFiles(diff), [diff]); const normalizedFocus = focusedPath?.replace(/^\.\/+/, ''); const visibleFiles = useMemo( () => normalizedFocus ? files.filter( (file) => file.displayPath === normalizedFocus || file.newPath === normalizedFocus || file.oldPath === normalizedFocus, ) : files, [files, normalizedFocus], ); const stats = totals(visibleFiles); return (

{focusedPath ? `Diff: ${focusedPath}` : 'Diff viewer'}

{visibleFiles.length > 0 ? `${visibleFiles.length} ${visibleFiles.length === 1 ? 'file' : 'files'}, ` : ''} +{stats.additions}{' '} −{stats.deletions}

{focusedPath ? ( ) : null}
{visibleFiles.length > 0 ? (
{visibleFiles.map((file, index) => ( ))}
) : (
{focusedPath ? 'No diff is recorded for this file yet.' : 'No workspace diff yet.'}
)}
); };