summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src/components/diff-ssr.tsx
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-01-21 06:17:55 -0600
committerAdam <[email protected]>2026-01-22 22:12:12 -0600
commitcb481d9ac861813d4ff091ed33bcac9e882da1a1 (patch)
treec08be4b96815b74ac6dc1e3bab6359cd5dbb27b3 /packages/ui/src/components/diff-ssr.tsx
parent0ce0cacb282c47943348a2af21ea00e721bcb9d9 (diff)
downloadopencode-cb481d9ac861813d4ff091ed33bcac9e882da1a1.tar.gz
opencode-cb481d9ac861813d4ff091ed33bcac9e882da1a1.zip
wip(app): line selection
Diffstat (limited to 'packages/ui/src/components/diff-ssr.tsx')
-rw-r--r--packages/ui/src/components/diff-ssr.tsx45
1 files changed, 44 insertions, 1 deletions
diff --git a/packages/ui/src/components/diff-ssr.tsx b/packages/ui/src/components/diff-ssr.tsx
index da99ba3b7..ac98a6d24 100644
--- a/packages/ui/src/components/diff-ssr.tsx
+++ b/packages/ui/src/components/diff-ssr.tsx
@@ -1,4 +1,4 @@
-import { DIFFS_TAG_NAME, FileDiff } from "@pierre/diffs"
+import { DIFFS_TAG_NAME, FileDiff, type SelectedLineRange } from "@pierre/diffs"
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
import { createEffect, onCleanup, onMount, Show, splitProps } from "solid-js"
import { Dynamic, isServer } from "solid-js/web"
@@ -19,12 +19,50 @@ export function Diff<T>(props: SSRDiffProps<T>) {
"classList",
"annotations",
"selectedLines",
+ "commentedLines",
])
const workerPool = useWorkerPool(props.diffStyle)
let fileDiffInstance: FileDiff<T> | undefined
const cleanupFunctions: Array<() => void> = []
+ const getRoot = () => fileDiffRef?.shadowRoot ?? undefined
+
+ const findSide = (element: HTMLElement): "additions" | "deletions" => {
+ const code = element.closest("[data-code]")
+ if (!(code instanceof HTMLElement)) return "additions"
+ if (code.hasAttribute("data-deletions")) return "deletions"
+ return "additions"
+ }
+
+ const applyCommentedLines = (ranges: SelectedLineRange[]) => {
+ const root = getRoot()
+ if (!root) return
+
+ const existing = Array.from(root.querySelectorAll("[data-comment-selected]"))
+ for (const node of existing) {
+ if (!(node instanceof HTMLElement)) continue
+ node.removeAttribute("data-comment-selected")
+ }
+
+ for (const range of ranges) {
+ const start = Math.max(1, Math.min(range.start, range.end))
+ const end = Math.max(range.start, range.end)
+
+ for (let line = start; line <= end; line++) {
+ const expectedSide =
+ line === end ? (range.endSide ?? range.side) : line === start ? range.side : (range.side ?? range.endSide)
+
+ const nodes = Array.from(root.querySelectorAll(`[data-line="${line}"], [data-alt-line="${line}"]`))
+ for (const node of nodes) {
+ if (!(node instanceof HTMLElement)) continue
+ if (expectedSide && findSide(node) !== expectedSide) continue
+ node.setAttribute("data-comment-selected", "")
+ }
+ }
+ }
+ }
+
onMount(() => {
if (isServer || !props.preloadedDiff) return
fileDiffInstance = new FileDiff<T>(
@@ -55,6 +93,11 @@ export function Diff<T>(props: SSRDiffProps<T>) {
fileDiffInstance?.setSelectedLines(local.selectedLines ?? null)
})
+ createEffect(() => {
+ const ranges = local.commentedLines ?? []
+ requestAnimationFrame(() => applyCommentedLines(ranges))
+ })
+
// Hydrate annotation slots with interactive SolidJS components
// if (props.annotations.length > 0 && props.renderAnnotation != null) {
// for (const annotation of props.annotations) {