/* global React */ const { useState, useRef } = React; // Splits code into lines and flags which ones are comments (line // or block /* */) // so we can tint them without a full tokenizer. function classifyLines(code) { const lines = code.replace(/\s+$/, '').split('\n'); let inBlock = false; return lines.map((text) => { const trimmed = text.trim(); let comment = false; if (inBlock) { comment = true; if (trimmed.includes('*/')) inBlock = false; } else if (trimmed.startsWith('/*')) { comment = true; if (!trimmed.includes('*/')) inBlock = true; } else if (trimmed.startsWith('//')) { comment = true; } else if (trimmed.startsWith('*')) { comment = true; } return { text, comment }; }); } function CodeBlock({ code, filename = 'sketch.ino', lang = 'Arduino / C++', caption }) { const [expanded, setExpanded] = useState(false); const [copied, setCopied] = useState(false); const lines = classifyLines(code || ''); const copy = () => { try { navigator.clipboard.writeText(code); setCopied(true); setTimeout(() => setCopied(false), 1600); } catch (e) { /* clipboard blocked — ignore */ } }; const chip = { fontFamily: 'var(--font-mono)', fontSize: '10px', textTransform: 'uppercase', letterSpacing: '0.14em', color: 'var(--fg-4)', }; const btn = { display: 'inline-flex', alignItems: 'center', gap: '7px', cursor: 'pointer', fontFamily: 'var(--font-mono)', fontSize: '11px', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--fg-2)', background: 'transparent', border: '1px solid var(--line-strong)', borderRadius: 'var(--radius-pill, 999px)', padding: '7px 14px', transition: 'color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out)', }; return (
{/* Title bar */}
{filename} {lang} · {lines.length} lines
{/* Code body */}
              
                {lines.map((ln, i) => (
                  
{ln.text || ' '}
))}
{/* Fade + expand affordance when collapsed */} {!expanded && ( )}
{caption && (
{caption}
)}
); } window.CodeBlock = CodeBlock;