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