62 lines
2.5 KiB
TypeScript
62 lines
2.5 KiB
TypeScript
import { motion } from 'framer-motion';
|
|
import type { CanvasComponent } from '../../types/canvas';
|
|
import { RendererWrapper, type ComponentRenderContext } from './RendererWrapper';
|
|
import { AlertTriangle, AlertCircle, Info, CheckCircle2 } from 'lucide-react';
|
|
|
|
interface Props { component: CanvasComponent; ctx: ComponentRenderContext }
|
|
|
|
const SEVERITY_MAP = {
|
|
error: { icon: AlertTriangle, bg: 'rgba(239,68,68,0.08)', border: 'rgba(239,68,68,0.25)', text: '#f87171', accent: '#ef4444' },
|
|
warning: { icon: AlertCircle, bg: 'rgba(251,191,36,0.08)', border: 'rgba(251,191,36,0.25)', text: '#fbbf24', accent: '#f59e0b' },
|
|
info: { icon: Info, bg: 'rgba(59,130,246,0.08)', border: 'rgba(59,130,246,0.2)', text: '#60a5fa', accent: '#3b82f6' },
|
|
success: { icon: CheckCircle2, bg: 'rgba(52,211,153,0.08)', border: 'rgba(52,211,153,0.25)', text: '#34d399', accent: '#10b981' },
|
|
};
|
|
|
|
export function ErrorNoticeRenderer({ component, ctx }: Props) {
|
|
const params = component.visualizationParameters as {
|
|
errorCode?: string;
|
|
message?: string;
|
|
severity?: 'error' | 'warning' | 'info' | 'success';
|
|
retryable?: boolean;
|
|
};
|
|
|
|
const severity = params.severity ?? 'warning';
|
|
const { icon: Icon, bg, border, text, accent } = SEVERITY_MAP[severity] ?? SEVERITY_MAP.warning;
|
|
|
|
return (
|
|
<RendererWrapper component={component} ctx={ctx} minHeight={120}>
|
|
<motion.div
|
|
className="flex items-start gap-4 p-4 rounded-xl h-full"
|
|
style={{ background: bg, border: `1px solid ${border}` }}
|
|
initial={{ opacity: 0, scale: 0.98 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
>
|
|
<div
|
|
className="w-9 h-9 rounded-xl flex items-center justify-center flex-shrink-0 mt-0.5"
|
|
style={{ background: `${accent}20` }}
|
|
>
|
|
<Icon className="w-5 h-5" style={{ color: text }} />
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
{params.errorCode && (
|
|
<p className="text-[10px] font-mono uppercase tracking-widest mb-1" style={{ color: `${text}80` }}>
|
|
{params.errorCode}
|
|
</p>
|
|
)}
|
|
<p className="text-sm font-medium" style={{ color: text }}>
|
|
{params.message ?? 'An error occurred rendering this component.'}
|
|
</p>
|
|
{params.retryable && (
|
|
<button
|
|
className="text-xs mt-2 underline underline-offset-2 hover:opacity-80 transition-opacity"
|
|
style={{ color: text }}
|
|
>
|
|
Retry
|
|
</button>
|
|
)}
|
|
</div>
|
|
</motion.div>
|
|
</RendererWrapper>
|
|
);
|
|
}
|