diff options
| author | Adam <[email protected]> | 2026-01-04 15:40:25 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-22 22:12:12 -0600 |
| commit | 640d1f1ecc7a2b46fb2bafed760c7348c70579a8 (patch) | |
| tree | 090f22b0e98053e7089133f164b17cff0367daa6 /packages/ui/src/components/diff.tsx | |
| parent | 2e53697da01d1417845567296774166350e786f1 (diff) | |
| download | opencode-640d1f1ecc7a2b46fb2bafed760c7348c70579a8.tar.gz opencode-640d1f1ecc7a2b46fb2bafed760c7348c70579a8.zip | |
wip(app): line selection
Diffstat (limited to 'packages/ui/src/components/diff.tsx')
| -rw-r--r-- | packages/ui/src/components/diff.tsx | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/packages/ui/src/components/diff.tsx b/packages/ui/src/components/diff.tsx index 33925592c..46b6709b6 100644 --- a/packages/ui/src/components/diff.tsx +++ b/packages/ui/src/components/diff.tsx @@ -7,7 +7,10 @@ import { getWorkerPool } from "../pierre/worker" export function Diff<T>(props: DiffProps<T>) { let container!: HTMLDivElement - const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations"]) + let observer: MutationObserver | undefined + let renderToken = 0 + + const [local, others] = splitProps(props, ["before", "after", "class", "classList", "annotations", "onRendered"]) const mobile = createMediaQuery("(max-width: 640px)") @@ -25,6 +28,95 @@ export function Diff<T>(props: DiffProps<T>) { let instance: FileDiff<T> | undefined + const getRoot = () => { + const host = container.querySelector("diffs-container") + if (!(host instanceof HTMLElement)) return + + const root = host.shadowRoot + if (!root) return + + return root + } + + const notifyRendered = () => { + if (!local.onRendered) return + + observer?.disconnect() + observer = undefined + renderToken++ + + const token = renderToken + let settle = 0 + + const isReady = (root: ShadowRoot) => root.querySelector("[data-line]") != null + + const notify = () => { + if (token !== renderToken) return + + observer?.disconnect() + observer = undefined + requestAnimationFrame(() => { + if (token !== renderToken) return + local.onRendered?.() + }) + } + + const schedule = () => { + settle++ + const current = settle + + requestAnimationFrame(() => { + if (token !== renderToken) return + if (current !== settle) return + + requestAnimationFrame(() => { + if (token !== renderToken) return + if (current !== settle) return + + notify() + }) + }) + } + + const observeRoot = (root: ShadowRoot) => { + observer?.disconnect() + observer = new MutationObserver(() => { + if (token !== renderToken) return + if (!isReady(root)) return + + schedule() + }) + + observer.observe(root, { childList: true, subtree: true }) + + if (!isReady(root)) return + schedule() + } + + const root = getRoot() + if (typeof MutationObserver === "undefined") { + if (!root || !isReady(root)) return + local.onRendered() + return + } + + if (root) { + observeRoot(root) + return + } + + observer = new MutationObserver(() => { + if (token !== renderToken) return + + const root = getRoot() + if (!root) return + + observeRoot(root) + }) + + observer.observe(container, { childList: true, subtree: true }) + } + createEffect(() => { const opts = options() const workerPool = getWorkerPool(props.diffStyle) @@ -50,9 +142,12 @@ export function Diff<T>(props: DiffProps<T>) { lineAnnotations: annotations, containerWrapper: container, }) + + notifyRendered() }) onCleanup(() => { + observer?.disconnect() instance?.cleanUp() }) |
