Files
vercel-labs--zerolang/docs/components/code-editor.tsx
T
wehub-resource-sync e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:29:30 +08:00

59 lines
1.7 KiB
TypeScript

"use client";
import type { UIEvent } from "react";
import { useMemo, useRef } from "react";
import { highlight } from "@/lib/highlight";
type CodeEditorProps = {
value: string;
onChange: (value: string) => void;
language?: string;
ariaLabel: string;
className?: string;
};
export function CodeEditor({
value,
onChange,
language = "zero",
ariaLabel,
className = "",
}: CodeEditorProps) {
const preRef = useRef<HTMLPreElement | null>(null);
const html = useMemo(() => {
const trailingNewline = value.endsWith("\n") ? " " : "";
return highlight(value + trailingNewline, language);
}, [value, language]);
function handleScroll(event: UIEvent<HTMLTextAreaElement>) {
const pre = preRef.current;
if (!pre) return;
pre.scrollTop = event.currentTarget.scrollTop;
pre.scrollLeft = event.currentTarget.scrollLeft;
}
return (
<div className={`relative h-full w-full ${className}`}>
<pre
ref={preRef}
aria-hidden="true"
className="pointer-events-none absolute inset-0 m-0 overflow-hidden whitespace-pre p-6 font-mono text-[0.9375rem] leading-[1.7] text-code-fg"
>
<code dangerouslySetInnerHTML={{ __html: html }} />
</pre>
<textarea
value={value}
onChange={(event) => onChange(event.target.value)}
onScroll={handleScroll}
spellCheck={false}
autoCorrect="off"
autoCapitalize="off"
autoComplete="off"
aria-label={ariaLabel}
className="relative block h-full w-full resize-none whitespace-pre border-0 bg-transparent p-6 font-mono text-[0.9375rem] leading-[1.7] text-transparent caret-fg outline-none"
/>
</div>
);
}