Download packages/app/src/pages/session/timeline/observe-element-offset.ts from SaylorTwift/opencode: direct link, hf CLI and curl.
- Browser
- Download file 2.66 kB
-
https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/app/src/pages/session/timeline/observe-element-offset.ts
- Command line
-
hf download hf://SaylorTwift/opencode/packages/app/src/pages/session/timeline/observe-element-offset.ts
-
curl -L -o observe-element-offset.ts https://huggingface.co/SaylorTwift/opencode/resolve/main/packages/app/src/pages/session/timeline/observe-element-offset.ts
2.66 kB
| import { observeElementOffset, type Virtualizer } from "@tanstack/solid-virtual" | |
| export function observeElementOffsetReconnectAware<TScrollElement extends Element, TItemElement extends Element>( | |
| instance: Virtualizer<TScrollElement, TItemElement>, | |
| callback: (offset: number, isScrolling: boolean) => void, | |
| ) { | |
| let active = true | |
| const deliver = (offset: number, isScrolling: boolean) => { | |
| if (!active) return | |
| callback(offset, isScrolling) | |
| } | |
| const cleanupOffset = observeElementOffset(instance, deliver) | |
| const element = instance.scrollElement | |
| const targetWindow = instance.targetWindow | |
| const root = element?.closest("main") ?? element?.ownerDocument.body | |
| if (!element || !targetWindow || !root) | |
| return () => { | |
| active = false | |
| cleanupOffset?.() | |
| } | |
| let removed = false | |
| let frame: number | undefined | |
| const clearCheck = () => { | |
| if (frame === undefined) return | |
| targetWindow.cancelAnimationFrame(frame) | |
| frame = undefined | |
| } | |
| const startCheck = () => { | |
| clearCheck() | |
| const deadline = targetWindow.performance.now() + instance.options.isScrollingResetDelay | |
| let framesAfterDeadline = 0 | |
| const check = (time: number) => { | |
| frame = undefined | |
| if (element.isConnected) { | |
| const offset = instance.options.horizontal | |
| ? element.scrollLeft * (instance.options.isRtl ? -1 : 1) | |
| : element.scrollTop | |
| if (instance.scrollOffset === null || Math.abs(offset - instance.scrollOffset) > 1) deliver(offset, false) | |
| } | |
| if (time >= deadline) framesAfterDeadline += 1 | |
| if (framesAfterDeadline >= 2) return | |
| frame = targetWindow.requestAnimationFrame(check) | |
| } | |
| frame = targetWindow.requestAnimationFrame(check) | |
| } | |
| const observer = new targetWindow.MutationObserver((records) => { | |
| if (!active) return | |
| records.forEach((record) => { | |
| if (record.target === element || element.contains(record.target)) return | |
| if (mutationNodesContainElement(record.removedNodes, element)) { | |
| removed = true | |
| clearCheck() | |
| } | |
| if (!removed || !element.isConnected || !mutationNodesContainElement(record.addedNodes, element)) return | |
| removed = false | |
| startCheck() | |
| }) | |
| }) | |
| // Session routes are replaced below persistent main; body is the fallback for isolated hosts. | |
| observer.observe(root, { childList: true, subtree: true }) | |
| return () => { | |
| active = false | |
| observer.disconnect() | |
| clearCheck() | |
| cleanupOffset?.() | |
| } | |
| } | |
| export function mutationNodesContainElement(nodes: Iterable<Node>, element: Element) { | |
| return [...nodes].some((node) => node === element || node.contains(element)) | |
| } | |