"use client"; import { evaluate } from "@mdx-js/mdx"; import { MDXProvider, useMDXComponents } from "@mdx-js/react"; import type { MDXComponents } from "mdx/types"; import { useEffect, useState, type ComponentType, type ReactNode } from "react"; import * as runtime from "react/jsx-runtime"; import rehypeHighlight from "rehype-highlight"; import remarkGfm from "remark-gfm"; import { mdxComponents } from "~/components/mdx-components"; type MdxModule = { default: ComponentType<{ components?: MDXComponents }>; }; type ClientMdxProps = { source: string; components?: MDXComponents; format?: "md" | "mdx"; fallback?: ReactNode; errorFallback?: (error: Error) => ReactNode; }; export function ClientMdx({ source, components = mdxComponents, format = "md", fallback = null, errorFallback, }: ClientMdxProps) { const [Content, setContent] = useState(null); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; const trimmed = source.trim(); if (!trimmed) { setContent(null); setError(null); return; } void evaluate(trimmed, { ...runtime, baseUrl: import.meta.url, format, useMDXComponents, rehypePlugins: [rehypeHighlight], remarkPlugins: [remarkGfm], }) .then((mod) => { if (cancelled) return; setContent(() => (mod as MdxModule).default); setError(null); }) .catch((nextError: unknown) => { if (cancelled) return; setContent(null); setError(nextError instanceof Error ? nextError : new Error("Failed to render MDX")); }); return () => { cancelled = true; }; }, [format, source]); if (error) { return errorFallback ? errorFallback(error) :

{source}

; } if (!Content) return <>{fallback}; return ( ); }