CodeBox

tcmts.share.CodeBox · #2akxjpc6 · term · runs in the browser

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>
  );
}

uses

used by