1import {
2 cloneFileDiffMetadata,
3 type FileDiffContentsLoader,
4 type FileDiffMetadata,
5} from "@pierre/diffs";
6import { FileDiff } from "@pierre/diffs/react";
7import { useMemo } from "react";
8
9import { useTheme } from "~/hooks/useTheme";
10import { resolveDiffThemeName } from "~/lib/diffRendering";
11import { PREFERRED_HIGHLIGHTER } from "~/lib/syntaxHighlighting";
12
13import { DIFF_VIEW_UNSAFE_CSS } from "../../diffs/StyledDiffCodeView";
14
15/**
16 * A whole file's diff inside a stop, for a file the guide vouched for without excerpting. The row
17 * above it names the file, so the renderer's own header is left off. The bars between hunks load
18 * the unchanged lines, as in the Code tab.
19 */
20export function GuideFileDiff({
21 file,
22 loadDiffFiles,
23}: {
24 file: FileDiffMetadata;
25 loadDiffFiles: FileDiffContentsLoader;
26}) {
27 const { resolvedTheme } = useTheme();
28 // Loading the unchanged lines rewrites the diff it is given; the excerpts read the same file
29 // as a patch, so this view expands a copy of its own.
30 const expandable = useMemo(() => cloneFileDiffMetadata(file), [file]);
31 const options = useMemo(
32 () => ({
33 diffStyle: "unified" as const,
34 lineDiffType: "none" as const,
35 overflow: "scroll" as const,
36 disableFileHeader: true,
37 theme: resolveDiffThemeName(resolvedTheme),
38 themeType: resolvedTheme,
39 preferredHighlighter: PREFERRED_HIGHLIGHTER,
40 unsafeCSS: DIFF_VIEW_UNSAFE_CSS,
41 loadDiffFiles,
42 }),
43 [loadDiffFiles, resolvedTheme],
44 );
45 return (
46 <div className="border-t border-border/60">
47 <FileDiff fileDiff={expandable} options={options} />
48 </div>
49 );
50}