66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
import type * as React from "react"
|
|
|
|
import type { SlateElement, SlateText } from "@/types"
|
|
|
|
function SlateRenderer({ nodes }: { nodes: SlateElement[] }) {
|
|
return (
|
|
<div className="space-y-1">
|
|
{nodes.map((node, index) => (
|
|
<SlateNode key={index} node={node} />
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function SlateNode({ node }: { node: SlateElement }) {
|
|
const alignClass = node.align === "center" ? "text-center" : node.align === "right" ? "text-right" : "text-left"
|
|
|
|
switch (node.type) {
|
|
case "heading":
|
|
return (
|
|
<h4 className={`text-xs md:text-sm font-mono font-medium tracking-tight ${alignClass} mb-1.5`}>
|
|
{node.children.map((child, idx) => (
|
|
<SlateLeaf key={idx} leaf={child} />
|
|
))}
|
|
</h4>
|
|
)
|
|
case "bullet-list":
|
|
return (
|
|
<ul className="list-disc pl-5 mb-1.5 font-sans text-xs md:text-sm">
|
|
{node.children.map((child, idx) => (
|
|
<li key={idx} className={alignClass}>
|
|
{child.text}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)
|
|
case "paragraph":
|
|
default:
|
|
return (
|
|
<div className={`text-xs md:text-sm leading-relaxed ${alignClass} font-sans`}>
|
|
{node.children.map((child, idx) => (
|
|
<SlateLeaf key={idx} leaf={child} />
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
}
|
|
|
|
function SlateLeaf({ leaf }: { leaf: SlateText }) {
|
|
let children: React.ReactNode = leaf.text
|
|
|
|
if (leaf.bold) {
|
|
children = <strong className="font-bold">{children}</strong>
|
|
}
|
|
if (leaf.italic) {
|
|
children = <em className="italic">{children}</em>
|
|
}
|
|
if (leaf.code) {
|
|
children = <code className="bg-primary/10 px-1.5 py-0.5 rounded-lg font-mono text-xs text-primary font-bold">{children}</code>
|
|
}
|
|
|
|
return <span>{children}</span>
|
|
}
|
|
|
|
export { SlateRenderer }
|