summaryrefslogtreecommitdiffstats
path: root/src/scripts/lib/dom.ts
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2026-07-22 19:40:59 +0200
committerVolpeon <git@volpeon.ink>2026-07-22 19:40:59 +0200
commitc1e28224aa2e1450031669d9a7e359b63e04687d (patch)
tree68f3d8905c763a91f68001d868197effa92adafa /src/scripts/lib/dom.ts
downloadcorvos-website-c1e28224aa2e1450031669d9a7e359b63e04687d.tar.gz
corvos-website-c1e28224aa2e1450031669d9a7e359b63e04687d.tar.bz2
corvos-website-c1e28224aa2e1450031669d9a7e359b63e04687d.zip
Init
Diffstat (limited to 'src/scripts/lib/dom.ts')
-rw-r--r--src/scripts/lib/dom.ts59
1 files changed, 59 insertions, 0 deletions
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 @@
1function isAbove(a: HTMLElement, b: HTMLElement) {
2 return a.offsetTop + a.clientHeight < b.offsetTop;
3}
4
5export function getVerticalNeighbor(
6 dir: -1 | 1,
7 items: Iterable<HTMLElement>,
8 current: HTMLElement,
9) {
10 let candidates: HTMLElement[] = [];
11
12 if (dir === -1) {
13 let adjacentY = Number.MIN_SAFE_INTEGER;
14
15 for (const item of items) {
16 if (!isAbove(item, current)) {
17 continue;
18 }
19
20 if (item.offsetTop > adjacentY) {
21 adjacentY = item.offsetTop;
22 candidates = [item];
23 } else if (item.offsetTop === adjacentY) {
24 candidates.push(item);
25 }
26 }
27 } else {
28 let adjacentY = Number.MAX_SAFE_INTEGER;
29
30 for (const item of items) {
31 if (!isAbove(current, item)) {
32 continue;
33 }
34
35 if (item.offsetTop < adjacentY) {
36 adjacentY = item.offsetTop;
37 candidates = [item];
38 } else if (item.offsetTop === adjacentY) {
39 candidates.push(item);
40 }
41 }
42 }
43
44 const currentX = current.offsetLeft + 0.5 * current.clientWidth;
45 let match = candidates[0];
46 let bestDist = Number.MAX_SAFE_INTEGER;
47
48 for (const candidate of candidates) {
49 const candidateX = candidate.offsetLeft + 0.5 * candidate.clientWidth;
50 const dist = Math.abs(currentX - candidateX);
51
52 if (dist < bestDist) {
53 bestDist = dist;
54 match = candidate;
55 }
56 }
57
58 return match;
59}