'use client' /** * Shared utilities and small presentational components for StepWordRecognition. */ /** Render text with \n as line breaks */ export function MultilineText({ text }: { text: string }) { if (!text) return const lines = text.split('\n') if (lines.length === 1) return <>{text} return <>{lines.map((line, i) => ( {line}{i < lines.length - 1 &&
}
))} } /** Column type to human-readable header */ export function colTypeLabel(colType: string): string { const labels: Record = { column_en: 'English', column_de: 'Deutsch', column_example: 'Example', column_text: 'Text', column_marker: 'Marker', page_ref: 'Seite', } return labels[colType] || colType.replace('column_', '') } /** Column type to color class */ export function colTypeColor(colType: string): string { const colors: Record = { column_en: 'text-blue-600 dark:text-blue-400', column_de: 'text-green-600 dark:text-green-400', column_example: 'text-orange-600 dark:text-orange-400', column_text: 'text-purple-600 dark:text-purple-400', column_marker: 'text-gray-500 dark:text-gray-400', } return colors[colType] || 'text-gray-600 dark:text-gray-400' } /** Confidence score to color class */ export function confColor(conf: number): string { if (conf >= 70) return 'text-green-600 dark:text-green-400' if (conf >= 50) return 'text-yellow-600 dark:text-yellow-400' return 'text-red-600 dark:text-red-400' } /** Status to badge color class */ export function statusBadge(status?: string): string { const map: Record = { pending: 'bg-gray-100 dark:bg-gray-700 text-gray-500', confirmed: 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400', edited: 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400', skipped: 'bg-orange-100 dark:bg-orange-900/30 text-orange-700 dark:text-orange-400', } return map[status || 'pending'] || map.pending } /** * CellCrop: Shows a cropped portion of the dewarped image based on percent bbox. * Uses CSS background-image + background-position for efficient cropping. */ export function CellCrop({ imageUrl, bbox }: { imageUrl: string; bbox: { x: number; y: number; w: number; h: number } }) { // Scale factor: how much to zoom into the cell const scaleX = 100 / bbox.w const scaleY = 100 / bbox.h const scale = Math.min(scaleX, scaleY, 8) // Cap zoom at 8x return (
) }