import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { toJsxRuntime } from "hast-util-to-jsx-runtime";
import { Check, Copy } from "lucide-react";
import { useEffect, useLayoutEffect, useState } from "react";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { Button } from "../cmp/button";
import { cn } from "../lib/utils";
import { highlightCode, highlightedLineClassNames, isSupportedLanguage, shikiLineClassNames, shikiPreClassName, } from "./shiki";
function CodeBlock({ code, filename, highlightedLines, language, showLineNumbers = true, }) {
    const [highlighted, setHighlighted] = useState(null);
    const [copied, setCopied] = useState(false);
    const supported = isSupportedLanguage(language);
    const highlightedLineKey = [...highlightedLines]
        .sort((left, right) => left - right)
        .join(",");
    useLayoutEffect(() => {
        let active = true;
        setHighlighted(null);
        if (!language || !supported)
            return () => void (active = false);
        const lines = new Set(highlightedLineKey.split(",").filter(Boolean).map(Number));
        void highlightCode(code, language, lines).then((tree) => {
            if (!active || !tree)
                return;
            const rendered = toJsxRuntime(tree, { Fragment, jsx, jsxs });
            setHighlighted(rendered);
        });
        return () => void (active = false);
    }, [code, highlightedLineKey, language, supported]);
    useEffect(() => {
        if (!copied)
            return;
        const timeout = window.setTimeout(() => setCopied(false), 2_000);
        return () => window.clearTimeout(timeout);
    }, [copied]);
    async function copyCode() {
        try {
            await navigator.clipboard.writeText(code);
            setCopied(true);
        }
        catch {
            setCopied(false);
        }
    }
    return (_jsxs("figure", { "data-slot": "code-block", "data-line-numbers": showLineNumbers || undefined, "data-language": language || undefined, className: "group/code-block overflow-hidden rounded-lg border-[length:var(--ui-border-width)] border-border bg-[var(--markdown-code-background,var(--markdown-code-background-default))] my-2!", children: [_jsxs("figcaption", { "data-slot": "code-block-header", className: "flex items-center gap-2 ps-[0.6rem] px-0.5 font-mono text-xs text-muted-foreground", children: [_jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap", children: filename ?? language ?? "Plain text" }), !supported && language ? (_jsx("span", { "data-slot": "code-block-language-note", className: "ms-auto font-sans", children: "Plain text" })) : null, _jsx(Button, { variant: "ghost", size: "icon-xs", className: cn("ms-auto h-[22.2px]!", !supported && language && "ms-0"), onClick: copyCode, children: copied ? (_jsx(Check, { className: "size-3", "aria-hidden": "true" })) : (_jsx(Copy, { className: "size-3", "aria-hidden": "true" })) }), _jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? "Code copied to clipboard" : "" })] }), _jsx("div", { "data-slot": "code-block-content", className: "max-w-full overflow-x-auto pb-2", children: highlighted ?? (_jsx("pre", { className: cn(shikiPreClassName, !supported && "is-plain-text"), tabIndex: 0, children: _jsx("code", { children: code.split("\n").map((line, index, lines) => (_jsxs(Fragment, { children: [_jsx("span", { className: cn(shikiLineClassNames, highlightedLines.has(index + 1) &&
                                        highlightedLineClassNames), "data-line": index + 1, children: line }), index < lines.length - 1 ? "\n" : null] }, index))) }) })) })] }));
}
export { CodeBlock };
