Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| import { AnimationFrames } from "runed"; | |
| import type { Attachment } from "svelte/attachments"; | |
| export enum ObservedElements { | |
| BottomActions = "bottom-actions", | |
| TokenCountEnd = "token-count-end", | |
| TokenCountStart = "token-count-start", | |
| // Add other elements here as needed | |
| } | |
| type ObservedData = { | |
| rect: { | |
| width: number; | |
| height: number; | |
| top: number; | |
| left: number; | |
| right: number; | |
| bottom: number; | |
| }; | |
| offset: { | |
| width: number; | |
| height: number; | |
| top: number; | |
| left: number; | |
| right: number; | |
| bottom: number; | |
| }; | |
| }; | |
| export const observed: Record<ObservedElements, ObservedData> = $state( | |
| Object.values(ObservedElements).reduce( | |
| (acc, key) => { | |
| acc[key] = { | |
| rect: { | |
| width: 0, | |
| height: 0, | |
| top: 0, | |
| left: 0, | |
| right: 0, | |
| bottom: 0, | |
| }, | |
| offset: { | |
| width: 0, | |
| height: 0, | |
| top: 0, | |
| left: 0, | |
| right: 0, | |
| bottom: 0, | |
| }, | |
| }; | |
| return acc; | |
| }, | |
| {} as Record<ObservedElements, ObservedData>, | |
| ), | |
| ); | |
| type ObserveArgs = { | |
| name: ObservedElements; | |
| useRaf?: boolean; | |
| }; | |
| function getOffsetPosition(el: HTMLElement) { | |
| let top = 0; | |
| let left = 0; | |
| const width = el.offsetWidth; | |
| const height = el.offsetHeight; | |
| while (el) { | |
| top += el.offsetTop; | |
| left += el.offsetLeft; | |
| el = el.offsetParent as HTMLElement; | |
| } | |
| return { top, left, width, height, right: left + width, bottom: top + height }; | |
| } | |
| export function observe(args: ObserveArgs): Attachment<HTMLElement> { | |
| return node => { | |
| function setVars(name: ObservedElements) { | |
| // 1. Standard rect (includes transforms) | |
| const rect = node.getBoundingClientRect(); | |
| document.documentElement.style.setProperty(`--${name}-width`, `${rect.width}px`); | |
| document.documentElement.style.setProperty(`--${name}-height`, `${rect.height}px`); | |
| document.documentElement.style.setProperty(`--${name}-top`, `${rect.top}px`); | |
| document.documentElement.style.setProperty(`--${name}-left`, `${rect.left}px`); | |
| document.documentElement.style.setProperty(`--${name}-right`, `${rect.right}px`); | |
| document.documentElement.style.setProperty(`--${name}-bottom`, `${rect.bottom}px`); | |
| // 2. Offset position (ignores transforms) | |
| const offset = getOffsetPosition(node); | |
| document.documentElement.style.setProperty(`--${name}-width-offset`, `${offset.width}px`); | |
| document.documentElement.style.setProperty(`--${name}-height-offset`, `${offset.height}px`); | |
| document.documentElement.style.setProperty(`--${name}-top-offset`, `${offset.top}px`); | |
| document.documentElement.style.setProperty(`--${name}-left-offset`, `${offset.left}px`); | |
| document.documentElement.style.setProperty(`--${name}-right-offset`, `${offset.right}px`); | |
| document.documentElement.style.setProperty(`--${name}-bottom-offset`, `${offset.bottom}px`); | |
| observed[name] = { | |
| rect, | |
| offset, | |
| }; | |
| } | |
| function onWindowChange() { | |
| setVars(args.name); | |
| } | |
| /** Initialize */ | |
| const resizeObserver = new ResizeObserver(() => { | |
| setVars(args.name); | |
| }); | |
| resizeObserver.observe(node); | |
| // Listen for scroll and resize events | |
| window.addEventListener("scroll", onWindowChange, true); | |
| window.addEventListener("resize", onWindowChange, true); | |
| setVars(args.name); // Initial set after observing | |
| if (args.useRaf) { | |
| new AnimationFrames(() => { | |
| setVars(args.name); | |
| }); | |
| } | |
| return function destroy() { | |
| resizeObserver.disconnect(); | |
| window.removeEventListener("scroll", onWindowChange, true); | |
| window.removeEventListener("resize", onWindowChange, true); | |
| }; | |
| }; | |
| } | |