UNPKG

device-navigation

Version:

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

64 lines (63 loc) 2.07 kB
/** * Walk each node in the tree with a depth-first traversal. Walking stops if the callback returns * true. * * @category Internal * @returns The nav tree node that the callback returned `true` on, if any. Otherwise, `undefined`. */ export function walkNavTree( /** The tree to walk. */ tree, /** The callback to call on each node. If this returns `true`, the walking stops. */ callback) { return walkRecursively([ { ancestorChain: [], node: tree, nodeCoords: { x: 0, y: 0, }, }, ], tree.children, callback); } function walkRecursively(ancestorChain, children, callback) { // eslint-disable-next-line unicorn/no-for-loop for (let y = 0; y < children.length; y++) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const row = children[y]; // eslint-disable-next-line unicorn/no-for-loop for (let x = 0; x < row.length; x++) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const node = row[x]; const walkResult = { ancestorChain, nodeCoords: { x, y }, node, }; if (callback(walkResult)) { return walkResult; } const result = walkRecursively(ancestorChain.concat(walkResult), node.children, callback); if (result) { return result; } } } return undefined; } /** * Finds the given {@link NavEntry} in the given {@link NavTree}. If it does not exist, error out. * * @category Internal * @throws Error if the {@link NavEntry} is not found in the {@link NavTree}. */ export function findNavTreeNodeByNavEntry(navTree, navEntry) { const walkResult = walkNavTree(navTree, ({ node }) => { return !node.root && node.navEntry === navEntry; }); if (!walkResult) { throw new Error(`Failed to find NavEntry in NavTree.`); } return walkResult; }