diff options
| author | Adam <[email protected]> | 2026-01-21 06:17:55 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-22 22:12:12 -0600 |
| commit | cb481d9ac861813d4ff091ed33bcac9e882da1a1 (patch) | |
| tree | c08be4b96815b74ac6dc1e3bab6359cd5dbb27b3 /packages/ui/src/components/diff-ssr.tsx | |
| parent | 0ce0cacb282c47943348a2af21ea00e721bcb9d9 (diff) | |
| download | opencode-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.tsx | 45 |
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) { |
