From f3da73553c45f17e04b1e77cb13eb0fca714d1bd Mon Sep 17 00:00:00 2001
From: Dax Raad <d@ironbay.co>
Date: Fri, 30 May 2025 20:47:56 -0400
Subject: sync

---
 packages/web/src/components/DiffView.tsx | 73 ++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 packages/web/src/components/DiffView.tsx

(limited to 'packages/web/src/components/DiffView.tsx')

diff --git a/packages/web/src/components/DiffView.tsx b/packages/web/src/components/DiffView.tsx
new file mode 100644
index 000000000..44feef140
--- /dev/null
+++ b/packages/web/src/components/DiffView.tsx
@@ -0,0 +1,73 @@
+import { type Component, createSignal, onMount } from "solid-js"
+import { diffLines } from "diff"
+import CodeBlock from "./CodeBlock"
+import styles from "./diffview.module.css"
+
+type DiffRow = {
+  left: string
+  right: string
+  type: "added" | "removed" | "unchanged"
+}
+
+interface DiffViewProps {
+  oldCode: string
+  newCode: string
+  lang?: string
+  class?: string
+}
+
+const DiffView: Component<DiffViewProps> = (props) => {
+  const [rows, setRows] = createSignal<DiffRow[]>([])
+
+  onMount(() => {
+    const chunks = diffLines(props.oldCode, props.newCode)
+    const diffRows: DiffRow[] = []
+
+    for (const chunk of chunks) {
+      const lines = chunk.value.split(/\r?\n/)
+      if (lines.at(-1) === "") lines.pop()
+
+      for (const line of lines) {
+        diffRows.push({
+          left: chunk.removed ? line : chunk.added ? "" : line,
+          right: chunk.added ? line : chunk.removed ? "" : line,
+          type: chunk.added
+            ? "added"
+            : chunk.removed
+              ? "removed"
+              : "unchanged",
+        })
+      }
+    }
+
+    setRows(diffRows)
+  })
+
+  return (
+    <div class={`${styles.diff} ${props.class ?? ""}`}>
+      <div class={styles.column}>
+        {rows().map((r) => (
+          <CodeBlock
+            code={r.left}
+            lang={props.lang}
+            data-section="cell"
+            data-diff-type={r.type === "removed" ? "removed" : ""}
+          />
+        ))}
+      </div>
+
+      <div class={styles.column}>
+        {rows().map((r) => (
+          <CodeBlock
+            code={r.right}
+            lang={props.lang}
+            data-section="cell"
+            data-diff-type={r.type === "added" ? "added" : ""}
+          />
+        ))}
+      </div>
+    </div>
+  )
+}
+
+export default DiffView
-- 
cgit v1.2.3

