summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src/components/diff-ssr.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/ui/src/components/diff-ssr.tsx')
-rw-r--r--packages/ui/src/components/diff-ssr.tsx75
1 files changed, 75 insertions, 0 deletions
diff --git a/packages/ui/src/components/diff-ssr.tsx b/packages/ui/src/components/diff-ssr.tsx
new file mode 100644
index 000000000..800aa3730
--- /dev/null
+++ b/packages/ui/src/components/diff-ssr.tsx
@@ -0,0 +1,75 @@
+import { FileDiff } from "@pierre/precision-diffs"
+import { PreloadMultiFileDiffResult } from "@pierre/precision-diffs/ssr"
+import { onCleanup, onMount, Show, splitProps } from "solid-js"
+import { isServer } from "solid-js/web"
+import { createDefaultOptions, styleVariables, type DiffProps } from "../pierre"
+
+export type SSRDiffProps<T = {}> = DiffProps<T> & {
+ preloadedDiff: PreloadMultiFileDiffResult<T>
+}
+
+export function Diff<T>(props: SSRDiffProps<T>) {
+ let container!: HTMLDivElement
+ let fileDiffRef!: HTMLElement
+ const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations"])
+
+ let fileDiffInstance: FileDiff<T> | undefined
+ const cleanupFunctions: Array<() => void> = []
+
+ onMount(() => {
+ if (isServer || !props.preloadedDiff) return
+ fileDiffInstance = new FileDiff<T>({
+ ...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 (
+ <div data-component="diff" style={styleVariables} ref={container}>
+ <file-diff ref={fileDiffRef} id="ssr-diff">
+ <Show when={isServer}>
+ <template shadowrootmode="open" innerHTML={props.preloadedDiff.prerenderedHTML} />
+ </Show>
+ </file-diff>
+ </div>
+ )
+}