import { Check, Copy, DownloadSimple, FileText, Info, Warning, X } from "@phosphor-icons/react"; import { useState, type ReactNode } from "react"; import { cn } from "../../lib/cn"; import { IconButton } from "../actions/icon-button"; export type AdvancedBlockTone = "info" | "success" | "warning" | "error"; function useCopy(value: string, onCopy?: (value: string) => void) { const [copied, setCopied] = useState(false); async function copy() { onCopy?.(value); if (typeof navigator !== "undefined" && navigator.clipboard) { await navigator.clipboard.writeText(value); } setCopied(true); window.setTimeout(() => setCopied(false), 1400); } return { copied, copy }; } function CopyControl({ value, onCopy }: { value: string; onCopy?: (value: string) => void }) { const { copied, copy } = useCopy(value, onCopy); return ( : } label={copied ? "Copied" : "Copy content"} onClick={copy} title={copied ? "Copied" : "Copy content"} /> ); } function BlockFrame({ actions, children, className, eyebrow, title, }: { actions?: ReactNode; children: ReactNode; className?: string; eyebrow?: string; title?: ReactNode; }) { return (
{eyebrow || title || actions ? (
{eyebrow ?

{eyebrow}

: null} {title ?

{title}

: null}
{actions ?
{actions}
: null}
) : null} {children}
); } export function CodeBlock({ code, language, onCopy, title, }: { code: string; language?: string; onCopy?: (value: string) => void; title?: ReactNode; }) { return ( } eyebrow={language || "Code"} title={title}>
{code}
); } export function MathBlock({ display = true, formula, onCopy, title = "Formula", }: { display?: boolean; formula: string; onCopy?: (value: string) => void; title?: ReactNode; }) { return ( } eyebrow="Math" title={title}>
{formula}
); } export function DiagramBlock({ language = "diagram", onCopy, source, title = "Diagram", }: { language?: string; onCopy?: (value: string) => void; source: string; title?: ReactNode; }) { return ( } eyebrow={language} title={title}>
{source}
); } export function CalloutBlock({ children, title, tone = "info", }: { children: ReactNode; title?: ReactNode; tone?: AdvancedBlockTone; }) { const icons = { error: , info: , success: , warning: }; return (
{icons[tone]}
{title ?

{title}

: null}
{children}
); } export function QuoteBlock({ children, cite }: { children: ReactNode; cite?: ReactNode }) { return
{children}
{cite ?
{cite}
: null}
; } export function TableBlock({ headers, rows, }: { headers: ReactNode[]; rows: ReactNode[][]; }) { return (
{headers.map((header, index) => )}{rows.map((row, rowIndex) => {row.map((cell, cellIndex) => )})}
{header}
{cell}
); } export function StepsBlock({ steps }: { steps: Array<{ description?: ReactNode; title: ReactNode }> }) { return
    {steps.map((step, index) =>
  1. {index + 1}

    {step.title}

    {step.description ?

    {step.description}

    : null}
  2. )}
; } export function ChecklistBlock({ items }: { items: Array<{ checked?: boolean; label: ReactNode }> }) { return
    {items.map((item, index) =>
  • {item.checked ? : null}{item.label}
  • )}
; } export function KeyValueBlock({ items }: { items: Array<{ label: ReactNode; value: ReactNode }> }) { return
{items.map((item, index) =>
{item.label}
{item.value}
)}
; } export function TimelineBlock({ items }: { items: Array<{ description?: ReactNode; title: ReactNode; time?: ReactNode }> }) { return
    {items.map((item, index) =>
  1. {index < items.length - 1 ? : null}

    {item.title}

    {item.time ? : null}
    {item.description ?

    {item.description}

    : null}
  2. )}
; } export function FileBlock({ download, meta, name, onDownload, }: { download?: string; meta?: ReactNode; name: ReactNode; onDownload?: () => void; }) { return

{name}

{meta ?

{meta}

: null}
{download || onDownload ? : null}
; } export function MediaBlock({ alt, src, type = "image" }: { alt?: string; src: string; type?: "audio" | "image" | "video" }) { if (type === "video") return ; if (type === "audio") return