CodeBox
uses window
A definition's or file's code in a box: a head, the line count, then its lines, numbered (CodeLines). A file with
a view of its own (Markdown rendered, an image) shows that first, with a switch to its code; an address naming
lines shows the code.
import { CodeLines } from "#codebase/tcmts/share"; import { useEffect, useState } from "react"; import type { ReactNode } from "react"; import { ToggleButton, ToggleButtonGroup } from "react-aria-components"; export function CodeBox({ head, lines, preview, }: { head: ReactNode; lines: string[]; preview?: ReactNode; }) { const viewable = preview !== undefined && preview !== null; const [code, setCode] = useState(!viewable); useEffect(() => { if (!viewable) return; const read = () => /^#L\d/.test(window.location.hash) && setCode(true); read(); window.addEventListener("hashchange", read); return () => window.removeEventListener("hashchange", read); }, [viewable]); return ( <div className="box"> <div className="boxhead"> {viewable && ( <ToggleButtonGroup aria-label="Show" className="seg" selectionMode="single" disallowEmptySelection selectedKeys={[code ? "code" : "preview"]} onSelectionChange={(keys) => setCode(keys.has("code"))} > <ToggleButton id="preview" className="btn small"> Preview </ToggleButton> <ToggleButton id="code" className="btn small"> Code </ToggleButton> </ToggleButtonGroup> )} {head} <span className="right muted" style={{ fontSize: 12 }}> {lines.length.toLocaleString("en")} line{lines.length === 1 ? "" : "s"} </span> </div> {code ? <CodeLines lines={lines} /> : preview} </div> ); }