/** * Source with a copy button — the fence chrome, in one place. * * Reference architectures arrive as `mermaid`, both in a template's structured * `fields` and inside the markdown body a promoted artefact brings with it, and * neither is rendered as a picture. Bundling mermaid means roughly two * megabytes and evaluating author-supplied text, and the proxy allows exactly * one inline script by hash (AGENTS.md §5), so it would drag a CSP change onto * the deployment host too. Source with a copy button gets the reader into their * own diagram tool in two clicks; the picture is tracked as follow-up in * `docs/motion.md`. * * The copy button is here rather than in each caller because a diagram in a * body and a diagram in a field are the same thing to the person reading it, * and one of the two silently lacking the button is the sort of difference * nobody reports. */ import { useState } from 'react'; import { Check, Copy } from 'lucide-react'; import { toast } from 'sonner'; import { Button } from '@/components/ui'; export function CodeBlock({ source, language, label, }: { source: string; /** The fence's language, shown as the block's caption. Absent for a bare fence. */ language?: string | null; /** What the copy button says it copies, for a screen reader. */ label?: string; }) { const [copied, setCopied] = useState(false); const copy = async () => { // `navigator.clipboard` is absent outside a secure context, which the LAN // dev server is — so this branch is reached routinely, not exceptionally. if (!navigator.clipboard) { toast.error('The browser refused clipboard access. Select the source and copy it by hand.'); return; } try { await navigator.clipboard.writeText(source); setCopied(true); toast.success('Source copied.'); window.setTimeout(() => setCopied(false), 2000); } catch { toast.error('The browser refused clipboard access. Select the source and copy it by hand.'); } }; return (
{language ?? 'source'}
        {source}
      
); }