// Minimal Lexical → React renderer. Only handles the node kinds our CMS // emits today (heading h1-h4, paragraph, list/listitem, link, text, // linebreak). Add cases as new node kinds appear. import type { JSX } from "react"; import type { LexNode, LexRoot } from "@/lib/cms"; function renderNodes(nodes: LexNode[] | undefined): JSX.Element[] { return (nodes ?? []).map((n, i) => renderNode(n, i)); } function renderNode(n: LexNode, key: number): JSX.Element { switch (n.type) { case "text": { const format = (n as { format?: number }).format ?? 0; let el: JSX.Element = <>{n.text}; if (format & 1) el = {el}; if (format & 2) el = {el}; if (format & 8) el = {el}; if (format & 16) el = {el}; return {el}; } case "linebreak": return
; case "paragraph": return

{renderNodes(n.children)}

; case "heading": { const Tag = (n.tag ?? "h2") as keyof JSX.IntrinsicElements; return {renderNodes(n.children)}; } case "list": { const Tag = (n.tag === "ol" ? "ol" : "ul") as "ol" | "ul"; return {renderNodes(n.children)}; } case "listitem": return
  • {renderNodes(n.children)}
  • ; case "link": { const url = n.fields?.url ?? "#"; const newTab = Boolean(n.fields?.newTab); return ( {renderNodes(n.children)} ); } default: return ; } } export default function RichText({ data }: { data: LexRoot | null | undefined }) { if (!data?.root) return null; return <>{renderNodes(data.root.children)}; }