"use client"; import { INTERNAL, useMessagePartText } from "@assistant-ui/react"; import { type ComponentRef, type ElementType, type FC, forwardRef, type ForwardRefExoticComponent, type RefAttributes, useMemo, type ComponentPropsWithoutRef, type ComponentType, } from "react"; import ReactMarkdown, { type Options } from "react-markdown"; import type { SyntaxHighlighterProps, CodeHeaderProps, } from "../overrides/types"; import { PreOverride } from "../overrides/PreOverride"; import { DefaultPre, DefaultCode, DefaultCodeBlockContent, DefaultCodeHeader, } from "../overrides/defaultComponents"; import { useCallbackRef } from "@radix-ui/react-use-callback-ref"; import { CodeOverride } from "../overrides/CodeOverride"; import type { Primitive } from "@radix-ui/react-primitive"; import classNames from "classnames"; const { useSmooth, useSmoothStatus, withSmoothContextProvider } = INTERNAL; type MarkdownTextPrimitiveElement = ComponentRef; type PrimitiveDivProps = ComponentPropsWithoutRef; export type MarkdownTextPrimitiveProps = Omit< Options, "components" | "children" > & { className?: string | undefined; containerProps?: Omit | undefined; containerComponent?: ElementType | undefined; components?: | (NonNullable & { SyntaxHighlighter?: ComponentType | undefined; CodeHeader?: ComponentType | undefined; }) | undefined; /** * Language-specific component overrides. * @example { mermaid: { SyntaxHighlighter: MermaidDiagram } } */ componentsByLanguage?: | Record< string, { CodeHeader?: ComponentType | undefined; SyntaxHighlighter?: ComponentType | undefined; } > | undefined; smooth?: boolean | undefined; /** * Function to transform text before markdown processing. */ preprocess?: (text: string) => string; }; const MarkdownTextInner: FC = ({ components: userComponents, componentsByLanguage, smooth = true, preprocess, ...rest }) => { const messagePartText = useMessagePartText(); const processedMessagePart = useMemo(() => { if (!preprocess) return messagePartText; return { ...messagePartText, text: preprocess(messagePartText.text), }; }, [messagePartText, preprocess]); const { text } = useSmooth(processedMessagePart, smooth); const { pre = DefaultPre, code = DefaultCode, SyntaxHighlighter = DefaultCodeBlockContent, CodeHeader = DefaultCodeHeader, } = userComponents ?? {}; const useCodeOverrideComponents = useMemo(() => { return { Pre: pre, Code: code, SyntaxHighlighter, CodeHeader, }; }, [pre, code, SyntaxHighlighter, CodeHeader]); const CodeComponent = useCallbackRef((props) => ( )); const components: Options["components"] = useMemo(() => { const { pre, code, SyntaxHighlighter, CodeHeader, ...componentsRest } = userComponents ?? {}; return { ...componentsRest, pre: PreOverride, code: CodeComponent, }; }, [CodeComponent, userComponents]); return ( {text} ); }; const MarkdownTextPrimitiveImpl: ForwardRefExoticComponent & RefAttributes = forwardRef< MarkdownTextPrimitiveElement, MarkdownTextPrimitiveProps >( ( { className, containerProps, containerComponent: Container = "div", ...rest }, forwardedRef, ) => { const status = useSmoothStatus(); return ( ); }, ); MarkdownTextPrimitiveImpl.displayName = "MarkdownTextPrimitive"; export const MarkdownTextPrimitive = withSmoothContextProvider( MarkdownTextPrimitiveImpl, );