/** * Custom-template craft kit — CodeBlock. * * A themed, SAFE code panel for the "code" content archetype. Renders ONLY the * lines passed in `lines` (from props.codeLines) — it never invents sample code, * and there is no place for `process.env` / `eval` / other forbidden APIs to leak * in, which is exactly the failure mode hand-rolled code scenes hit. Lines reveal * line-by-line with a mono font, accent gutter, and a small window chrome. */ import React from "react"; import { useCurrentFrame } from "remotion"; import { useKit } from "./context"; import { withAlpha } from "./theme"; import { staggerEntrance } from "./motion"; export interface CodeBlockProps { /** The code lines to display — pass props.codeLines. Empty → renders nothing. */ lines?: string[]; /** Optional language label shown in the window chrome (e.g. props.codeLanguage). */ language?: string; start?: number; maxLines?: number; style?: React.CSSProperties; } export const CodeBlock: React.FC = ({ lines, language, start = 6, maxLines = 12, style, }) => { const frame = useCurrentFrame(); const { palette, isPortrait } = useKit(); const rows = (lines ?? []).filter((l) => typeof l === "string").slice(0, maxLines); if (!rows.length) return null; const mono = "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace"; const fontSize = isPortrait ? 22 : 24; return (
{/* window chrome */}
{["#FF5F56", "#FFBD2E", "#27C93F"].map((dot) => ( ))} {language && ( {language} )}
{/* lines */}
{rows.map((line, i) => { const enter = staggerEntrance(frame, i, { start, stagger: 4 }); return (
{i + 1} {line}
); })}
); };