'use client'; import {Markdown} from '@astryxdesign/core/Markdown'; import {Text} from '@astryxdesign/core/Text'; import {VStack} from '@astryxdesign/core/Layout'; import {ResponseRenderer} from './response/ResponseRenderer'; import type {MessagePart} from '@/features/loyaly-ai/types/chat'; /** * The renderer registry: one message part in, one block out. * * THIS is the extension point the brief asks for. Charts, interactive tables, * business dashboards, file previews and image responses each become a case * below plus a variant in types/chat — and nothing else in the module moves, * because the transport already yields parts and the message list already maps * over them. * * The unimplemented cases are not silently dropped. A part the UI cannot draw * yet says so, which is the difference between "this version cannot render a * chart" and "the answer arrived empty". */ export function MessageContent({ part, isStreaming, }: { part: MessagePart; isStreaming?: boolean; }) { switch (part.type) { case 'report': return ; case 'text': return ( // `isStreaming` lets Markdown tolerate half-finished syntax — a table // that is three rows in, a code fence with no closing backticks — and // draws the caret. Without it, every chunk boundary would flash raw // markup on screen. {part.text} ); // ── Not yet rendered. Each is a component away, not a refactor away. ── case 'chart': case 'table': case 'file': case 'image': return ( {`This answer includes a ${part.type} that this version cannot display yet.`} ); } }