import type { GitFileDiff } from "@opengeni/sdk"; import { type ComponentType, type CSSProperties, type ReactNode, lazy, Suspense, useEffect, useState, useSyncExternalStore, } from "react"; import { cn } from "../lib/cn"; import { gitFileDiffToPatch } from "../lib/git-patch"; import { loadPierreDiffs, pierreDiffsRevision, subscribePierreDiffs, } from "../lib/pierre-diffs-loader"; import { useOpenGeniText } from "../messages/runtime"; /** Pierre `PatchDiff` props subset we drive. */ type PatchDiffComponent = ComponentType<{ patch: string; options?: { theme?: string | { dark: string; light: string }; themeType?: "dark" | "light"; diffStyle?: "unified" | "split"; overflow?: "scroll" | "wrap"; stickyHeader?: boolean; }; disableWorkerPool?: boolean; className?: string; }>; export type PierreDiffProps = { diff: GitFileDiff[]; layout?: "unified" | "split" | undefined; themeType?: "dark" | "light" | undefined; /** Shiki bundled theme names (dark/light) — derived from the host palette. */ theme?: { dark: string; light: string } | undefined; /** Disable Pierre's worker pool if its worker bundling fights the host bundler. */ disableWorkerPool?: boolean | undefined; /** Rendered while the (lazy) Pierre bundle loads. */ loading?: ReactNode | undefined; /** Rendered if `@pierre/diffs/react` is not installed / fails to import. */ fallback?: ReactNode | undefined; /** Skip the Shiki renderer entirely and show the plain-text degrade (the old * `usePierre={false}` path — one renderer, opted out of highlighting). */ plain?: boolean | undefined; /** Long-line handling: `"wrap"` soft-wraps (the default — a diff in a narrow * dock pane should be readable without a horizontal-scroll tax), `"scroll"` * keeps lines on one row behind a horizontal scrollbar (better for a wide * viewport or pathological minified lines). */ overflow?: "wrap" | "scroll" | undefined; className?: string | undefined; }; // Lazy-load `@pierre/diffs/react` so Shiki + the worker pool stay off the // critical path (and out of an SSR bundle) until a diff is actually shown. The // peer is loaded only through the host-registered loader (see // `enablePierreDiffs`); without one the load rejects and we render `fallback`. const LazyPatchDiff = lazy(async () => { const mod = (await loadPierreDiffs()) as { PatchDiff: PatchDiffComponent; }; return { default: mod.PatchDiff }; }); /** * The Pierre-backed diff: Shiki-highlighted, virtualized, unified/split. Renders * one `PatchDiff` per changed file (a reconstructed unified patch from the * `GitFileDiff` hunks). The ONE workbench diff renderer; a host without * `@pierre/diffs` gets the built-in plain-text degrade (`PlainPatch`). */ export function PierreDiff({ diff, layout = "unified", themeType, theme, disableWorkerPool, loading, fallback, plain, overflow = "wrap", className, }: PierreDiffProps) { const [failed, setFailed] = useState(false); const [ready, setReady] = useState(false); const [forcedColors, setForcedColors] = useState(false); // Pierre's rich renderer distinguishes additions/deletions primarily through // foreground and background colors inside a shadow root. In Windows forced- // colors mode those paints intentionally collapse, so expose the literal // unified patch (+/- markers) instead of leaving changed lines ambiguous. useEffect(() => { if (typeof window === "undefined" || typeof window.matchMedia !== "function") return; const query = window.matchMedia("(forced-colors: active)"); const update = () => setForcedColors(query.matches); update(); query.addEventListener?.("change", update); return () => query.removeEventListener?.("change", update); }, []); // Probe the import once so a hard failure (peer missing) shows `fallback` // rather than a Suspense boundary that never resolves. Skipped when `plain`. const loaderRevision = useSyncExternalStore( subscribePierreDiffs, pierreDiffsRevision, pierreDiffsRevision, ); useEffect(() => { if (plain) return; let cancelled = false; setFailed(false); // Mount the lazy renderer only after the peer loaded, so a missing peer // never poisons React.lazy's cached result for the rest of the page. loadPierreDiffs().then( () => { if (!cancelled) setReady(true); }, () => { if (!cancelled) setFailed(true); }, ); return () => { cancelled = true; }; }, [plain, loaderRevision]); if (plain || failed || forcedColors) { // `plain` opts out of highlighting; `failed` = `@pierre/diffs` not installed. // Render the caller's fallback, or a plain (unhighlighted) patch dump — NOT a // second hunk renderer. One highlighted renderer (Pierre) + a text degrade. return (
{gitFileDiffToPatch(file)
.split("\n")
.map((line, index) => (
{line || " "}
))}
))}