65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
'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 <ResponseRenderer report={part} isStreaming={isStreaming} />;
|
|
|
|
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.
|
|
<Markdown
|
|
density="compact"
|
|
isStreaming={isStreaming}
|
|
// The panel is 380px wide and lives inside a page that already has
|
|
// an h1. Starting at h3 keeps an assistant heading from
|
|
// out-ranking the page it is advising on.
|
|
headingLevelStart={3}
|
|
>
|
|
{part.text}
|
|
</Markdown>
|
|
);
|
|
|
|
// ── Not yet rendered. Each is a component away, not a refactor away. ──
|
|
case 'chart':
|
|
case 'table':
|
|
case 'file':
|
|
case 'image':
|
|
return (
|
|
<VStack gap={1}>
|
|
<Text size="sm" type="supporting">
|
|
{`This answer includes a ${part.type} that this version cannot display yet.`}
|
|
</Text>
|
|
</VStack>
|
|
);
|
|
}
|
|
}
|