"use client"; import { useCallback, useMemo, useState } from "react"; import { Check, Copy } from "lucide-react"; import type { CopyFormat } from "@/lib/copy-formats"; import { formatSvg } from "@/lib/copy-formats"; import { generateSnippet, type SnippetFormat } from "@/lib/code-snippets"; import { colorizeSvgCode, colorizeSnippet } from "@/components/icons/shared/syntax-highlight"; import { cn } from "@/lib/utils"; interface CodeBlockProps { svgContent: string; slug: string; title: string; activeVariant: string; } type TabValue = CopyFormat | SnippetFormat; interface Tab { value: TabValue; label: string; iconSlug?: string; group: "use" | "copy"; } const TABS: Tab[] = [ { value: "react", label: "React", iconSlug: "react", group: "use" }, { value: "vue", label: "Vue", iconSlug: "vue", group: "use" }, { value: "html", label: "HTML", iconSlug: "html5", group: "use" }, { value: "nextjs", label: "Next.js", iconSlug: "nextdotjs", group: "use" }, { value: "css", label: "CSS", iconSlug: "css", group: "use" }, { value: "svg", label: "SVG", group: "copy" }, { value: "jsx", label: "JSX", group: "copy" }, { value: "cdn", label: "CDN", group: "copy" }, { value: "data-uri", label: "URI", group: "copy" }, ]; const SNIPPET_FORMATS = new Set(["react", "vue", "html", "nextjs", "css"]); const SVG_LIKE = new Set(["svg", "jsx", "vue"]); function formatSvgCode(raw: string): string { return raw .replace(/>\s*\n<") .replace(/\s{2,}/g, " ") .trim(); } export function CodeBlock({ svgContent, slug, title, activeVariant }: CodeBlockProps) { const [activeTab, setActiveTab] = useState("svg"); const [copied, setCopied] = useState(false); const output = useMemo(() => { if (!svgContent) return ""; if (SNIPPET_FORMATS.has(activeTab)) { return generateSnippet(slug, title, activeTab as SnippetFormat, activeVariant); } const raw = formatSvg(svgContent, activeTab as CopyFormat, slug, activeVariant); return activeTab === "svg" ? formatSvgCode(raw) : raw; }, [svgContent, activeTab, slug, title, activeVariant]); const handleCopy = useCallback(async () => { if (!output) return; let text = output; if (!SNIPPET_FORMATS.has(activeTab) && activeTab === "svg") { text = formatSvg(svgContent, "svg", slug, activeVariant); } await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 1500); }, [output, svgContent, activeTab, slug, activeVariant]); const renderCode = useMemo(() => { if (!output) return null; if (SNIPPET_FORMATS.has(activeTab)) { return colorizeSnippet(output, activeTab as SnippetFormat); } if (SVG_LIKE.has(activeTab)) { return colorizeSvgCode(output); } return output; }, [output, activeTab]); if (!svgContent) return null; const useTabs = TABS.filter((t) => t.group === "use"); const copyTabs = TABS.filter((t) => t.group === "copy"); return (
{/* Tab bar */}
{/* Usage tabs */}
{useTabs.map((tab) => ( ))}
{/* Divider */}
{/* Copy format tabs */}
{copyTabs.map((tab) => ( ))}
{/* Code output */}
            
              {renderCode}
            
          
); }