import { type FileContents, FileDiff, type DiffLineAnnotation, FileDiffOptions } from "@pierre/precision-diffs" import { PreloadMultiFileDiffResult } from "@pierre/precision-diffs/ssr" import { ComponentProps, createEffect, onCleanup, onMount, Show, splitProps } from "solid-js" import { isServer } from "solid-js/web" import { createDefaultOptions, styleVariables } from "./pierre" export type DiffProps = FileDiffOptions & { preloadedDiff?: PreloadMultiFileDiffResult before: FileContents after: FileContents annotations?: DiffLineAnnotation[] class?: string classList?: ComponentProps<"div">["classList"] } // interface ThreadMetadata { // threadId: string // } // // export function Diff(props: DiffProps) { let container!: HTMLDivElement let fileDiffRef!: HTMLElement const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations"]) let fileDiffInstance: FileDiff | undefined const cleanupFunctions: Array<() => void> = [] createEffect(() => { if (props.preloadedDiff) return container.innerHTML = "" if (!fileDiffInstance) { fileDiffInstance = new FileDiff({ ...createDefaultOptions(props.diffStyle), ...others, ...(props.preloadedDiff ?? {}), }) } fileDiffInstance.render({ oldFile: local.before, newFile: local.after, lineAnnotations: local.annotations, containerWrapper: container, }) }) onMount(() => { if (isServer) return fileDiffInstance = new FileDiff({ ...createDefaultOptions(props.diffStyle), ...others, ...(props.preloadedDiff ?? {}), }) // @ts-expect-error - fileContainer is private but needed for SSR hydration fileDiffInstance.fileContainer = fileDiffRef fileDiffInstance.hydrate({ oldFile: local.before, newFile: local.after, lineAnnotations: local.annotations, fileContainer: fileDiffRef, containerWrapper: container, }) // Hydrate annotation slots with interactive SolidJS components // if (props.annotations.length > 0 && props.renderAnnotation != null) { // for (const annotation of props.annotations) { // const slotName = `annotation-${annotation.side}-${annotation.lineNumber}`; // const slotElement = fileDiffRef.querySelector( // `[slot="${slotName}"]` // ) as HTMLElement; // // if (slotElement != null) { // // Clear the static server-rendered content from the slot // slotElement.innerHTML = ''; // // // Mount a fresh SolidJS component into this slot using render(). // // This enables full SolidJS reactivity (signals, effects, etc.) // const dispose = render( // () => props.renderAnnotation!(annotation), // slotElement // ); // cleanupFunctions.push(dispose); // } // } // } }) onCleanup(() => { // Clean up FileDiff event handlers and dispose SolidJS components fileDiffInstance?.cleanUp() cleanupFunctions.forEach((dispose) => dispose()) }) return (
{(preloadedDiff) =>