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; }