~james/core

core/web/src/lib/components/ui/menuItems.ts -rw-r--r-- 975 bytes
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 15 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
export function menuItems() {
	let items: HTMLElement[] = [];

	const focus = (index: number) => {
		if (items.length === 0) return;
		const wrapped = ((index % items.length) + items.length) % items.length;
		items[wrapped]?.focus({ preventScroll: true });
	};

	return {
		register(el: HTMLElement) {
			const index = items.findIndex(
				(item) => item.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING
			);
			if (index === -1) {
				items.push(el);
			} else {
				items.splice(index, 0, el);
			}
			return () => {
				items = items.filter((item) => item !== el);
			};
		},
		focus,
		navigate(event: KeyboardEvent) {
			const current = items.indexOf(event.target as HTMLElement);
			const targets: Record<string, number> = {
				ArrowDown: current + 1,
				ArrowUp: current - 1,
				Home: 0,
				End: items.length - 1
			};
			if (!(event.key in targets)) return false;
			event.preventDefault();
			focus(targets[event.key]!);
			return true;
		}
	};
}