import { onKeydown } from '$lib/actions/input'; import type { Action } from 'svelte/action'; /** * Enables keyboard navigation (up and down arrows) for a list of elements. * @param node Element which listens for keyboard events * @param container Element containing the list of elements */ export const listNavigation: Action = ( node: HTMLElement, container?: HTMLElement, ) => { const moveFocus = (direction: 'up' | 'down') => { if (!container) { return; } const children = Array.from(container?.children); if (children.length === 0) { return; } const currentIndex = document.activeElement === null ? -1 : children.indexOf(document.activeElement); const directionFactor = (direction === 'up' ? -1 : 1) + (direction === 'up' && currentIndex === -1 ? 1 : 0); const newIndex = (currentIndex + directionFactor + children.length) % children.length; const element = children.at(newIndex); if (element instanceof HTMLElement) { element.focus(); } }; const unregisterUp = onKeydown('ArrowUp', (event) => (event.preventDefault(), moveFocus('up')), { ignoreInputFields: false, })(node); const unregisterDown = onKeydown('ArrowDown', (event) => (event.preventDefault(), moveFocus('down')), { ignoreInputFields: false, })(node); let destroy = () => { unregisterUp(); unregisterDown(); destroy = () => void 0; }; return { update(newContainer) { container = newContainer; }, destroy, }; };