UNPKG

device-navigation

Version:

Navigate HTML elements in two dimensions with non-pointer devices.

84 lines (83 loc) 2.33 kB
import { check } from '@augment-vir/assert'; import { getOrSet } from '@augment-vir/common'; import { extractNavEntry } from '../directives/nav-entry.js'; /** * Maps an `ElementTree` to a {@link NavTree}. * * @category Internal */ export function mapTree(elementTree) { const children = mapTreeRecursively(elementTree)?.children || []; return { root: true, children, }; } function mapTreeRecursively(elementTree) { const element = elementTree.element; if (!(element instanceof HTMLElement)) { return undefined; } const navEntry = extractNavEntry(element); const children = expandChildren(elementTree); const isValidGroup = navEntry?.navParams.group ? !!children.length : false; if (isValidGroup || !!children.length || !!navEntry) { return { root: false, element, navEntry, children, }; } else { return undefined; } } function expandChildren(elementTreeNode) { const rawChildren = []; function pushNode(node) { if (node.navEntry?.navParams.group && !node.children.length) { return; } else if (!node.navEntry) { node.children.forEach((row) => row.forEach((child) => pushNode(child))); return; } const x = node.navEntry.navParams.x; const y = node.navEntry.navParams.y || 0; const row = getOrSet(rawChildren, y, () => { return { noX: [], withX: [], y, }; }); if (x == undefined) { row.noX.push(node); } else { row.withX.push({ x, node }); } } elementTreeNode.children.forEach((child) => { const newNode = mapTreeRecursively(child); if (newNode) { pushNode(newNode); } }); // eslint-disable-next-line sonarjs/no-misleading-array-reverse return rawChildren .sort((rowA, rowB) => { return rowA.y - rowB.y; }) .map((row) => { row.withX.sort((a, b) => { return a.x - b.x; }); row.withX.forEach(({ x, node }) => { row.noX.splice(x, 0, node); }); return row.noX; }) .filter(check.isTruthy); }