device-navigation
Version:
Navigate HTML elements in two dimensions with non-pointer devices.
60 lines (59 loc) • 1.95 kB
JavaScript
import { assert } from '@augment-vir/assert';
import { stringify } from '@augment-vir/common';
import { applyAttributes } from '../util/attributes.js';
import { modifyElement } from './modify-element.directive.js';
import { extractNavEntry, hasNavEntry, navAttribute, NavEntry, navEntryPropertyKey, NavValue, } from './nav-entry.js';
/**
* Used to determine an element's initial {@link navAttribute} value.
*
* @category Internal
*/
export function determineNavValue(params) {
if ('group' in params) {
return NavValue.Group;
}
else if (params.disabled) {
return NavValue.Disabled;
}
else {
return '';
}
}
/**
* Mark an element for navigation.
*
* This automatically applies the `tabindex` attribute and all keyboard and mouse listeners needed
* to enable `NavController` functionality.
*
* @category Main
*/
export function nav(navController, params = {}) {
return modifyElement(stringify(params), (element) => {
navController.needsUpdate = true;
const isNavigable =
/** Groups are not directly navigable. */
!params.group &&
/** Disabled entries are not navigable. */
!params.disabled;
assert.instanceOf(element, HTMLElement);
const allAttributes = {
[navAttribute.name]: determineNavValue(params),
tabindex: isNavigable ? 0 : -1,
};
applyAttributes(element, allAttributes);
const navEntry = extractNavEntry(element) || new NavEntry(element, navController, params);
if (hasNavEntry(element)) {
navEntry.navParams = params;
navEntry.navController = navController;
}
else {
element[navEntryPropertyKey] = navEntry;
}
if (isNavigable) {
element.style.setProperty('cursor', 'pointer');
}
else {
element.style.removeProperty('cursor');
}
});
}