From c1e28224aa2e1450031669d9a7e359b63e04687d Mon Sep 17 00:00:00 2001 From: Volpeon Date: Wed, 22 Jul 2026 19:40:59 +0200 Subject: Init --- src/scripts/lib/dom.ts | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/scripts/lib/dom.ts (limited to 'src/scripts/lib/dom.ts') diff --git a/src/scripts/lib/dom.ts b/src/scripts/lib/dom.ts new file mode 100644 index 0000000..a88686a --- /dev/null +++ b/src/scripts/lib/dom.ts @@ -0,0 +1,59 @@ +function isAbove(a: HTMLElement, b: HTMLElement) { + return a.offsetTop + a.clientHeight < b.offsetTop; +} + +export function getVerticalNeighbor( + dir: -1 | 1, + items: Iterable, + current: HTMLElement, +) { + let candidates: HTMLElement[] = []; + + if (dir === -1) { + let adjacentY = Number.MIN_SAFE_INTEGER; + + for (const item of items) { + if (!isAbove(item, current)) { + continue; + } + + if (item.offsetTop > adjacentY) { + adjacentY = item.offsetTop; + candidates = [item]; + } else if (item.offsetTop === adjacentY) { + candidates.push(item); + } + } + } else { + let adjacentY = Number.MAX_SAFE_INTEGER; + + for (const item of items) { + if (!isAbove(current, item)) { + continue; + } + + if (item.offsetTop < adjacentY) { + adjacentY = item.offsetTop; + candidates = [item]; + } else if (item.offsetTop === adjacentY) { + candidates.push(item); + } + } + } + + const currentX = current.offsetLeft + 0.5 * current.clientWidth; + let match = candidates[0]; + let bestDist = Number.MAX_SAFE_INTEGER; + + for (const candidate of candidates) { + const candidateX = candidate.offsetLeft + 0.5 * candidate.clientWidth; + const dist = Math.abs(currentX - candidateX); + + if (dist < bestDist) { + bestDist = dist; + match = candidate; + } + } + + return match; +} -- cgit v1.3.1