UNPKG

@material/web

Version:
218 lines 7.49 kB
/** * @license * Copyright 2023 Google LLC * SPDX-License-Identifier: Apache-2.0 */ /** * Activates the first non-disabled item of a given array of items. * * @param items {Array<ListItem>} The items from which to activate the * first item. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. */ export function activateFirstItem(items, isActivatable = (isItemNotDisabled)) { // NOTE: These selector functions are static and not on the instance such // that multiple operations can be chained and we do not have to re-query // the DOM const firstItem = getFirstActivatableItem(items, isActivatable); if (firstItem) { firstItem.tabIndex = 0; firstItem.focus(); } return firstItem; } /** * Activates the last non-disabled item of a given array of items. * * @param items {Array<ListItem>} The items from which to activate the * last item. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @nocollapse */ export function activateLastItem(items, isActivatable = (isItemNotDisabled)) { const lastItem = getLastActivatableItem(items, isActivatable); if (lastItem) { lastItem.tabIndex = 0; lastItem.focus(); } return lastItem; } /** * Deactivates the currently active item of a given array of items. * * @param items {Array<ListItem>} The items from which to deactivate the * active item. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @return A record of the deleselcted activated item including the item and * the index of the item or `null` if none are deactivated. * @nocollapse */ export function deactivateActiveItem(items, isActivatable = (isItemNotDisabled)) { const activeItem = getActiveItem(items, isActivatable); if (activeItem) { activeItem.item.tabIndex = -1; } return activeItem; } /** * Retrieves the first activated item of a given array of items. * * @param items {Array<ListItem>} The items to search. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @return A record of the first activated item including the item and the * index of the item or `null` if none are activated. * @nocollapse */ export function getActiveItem(items, isActivatable = (isItemNotDisabled)) { for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.tabIndex === 0 && isActivatable(item)) { return { item, index: i, }; } } return null; } /** * Retrieves the first non-disabled item of a given array of items. This * the first item that is not disabled. * * @param items {Array<ListItem>} The items to search. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @return The first activatable item or `null` if none are activatable. * @nocollapse */ export function getFirstActivatableItem(items, isActivatable = (isItemNotDisabled)) { for (const item of items) { if (isActivatable(item)) { return item; } } return null; } /** * Retrieves the last non-disabled item of a given array of items. * * @param items {Array<ListItem>} The items to search. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @return The last activatable item or `null` if none are activatable. * @nocollapse */ export function getLastActivatableItem(items, isActivatable = (isItemNotDisabled)) { for (let i = items.length - 1; i >= 0; i--) { const item = items[i]; if (isActivatable(item)) { return item; } } return null; } /** * Retrieves the next non-disabled item of a given array of items. * * @param items {Array<ListItem>} The items to search. * @param index {{index: number}} The index to search from. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @return The next activatable item or `null` if none are activatable. */ export function getNextItem(items, index, isActivatable = (isItemNotDisabled)) { for (let i = 1; i < items.length; i++) { const nextIndex = (i + index) % items.length; const item = items[nextIndex]; if (isActivatable(item)) { return item; } } return items[index] ? items[index] : null; } /** * Retrieves the previous non-disabled item of a given array of items. * * @param items {Array<ListItem>} The items to search. * @param index {{index: number}} The index to search from. * @param isActivatable Function to determine if an item can be activated. * Defaults to non-disabled items. * @return The previous activatable item or `null` if none are activatable. */ export function getPrevItem(items, index, isActivatable = (isItemNotDisabled)) { for (let i = 1; i < items.length; i++) { const prevIndex = (index - i + items.length) % items.length; const item = items[prevIndex]; if (isActivatable(item)) { return item; } } return items[index] ? items[index] : null; } /** * Activates the next item and focuses it. If nothing is currently activated, * activates the first item. */ export function activateNextItem(items, activeItemRecord, isActivatable = (isItemNotDisabled)) { if (activeItemRecord) { const next = getNextItem(items, activeItemRecord.index, isActivatable); if (next) { next.tabIndex = 0; next.focus(); } return next; } else { return activateFirstItem(items, isActivatable); } } /** * Activates the previous item and focuses it. If nothing is currently * activated, activates the last item. */ export function activatePreviousItem(items, activeItemRecord, isActivatable = (isItemNotDisabled)) { if (activeItemRecord) { const prev = getPrevItem(items, activeItemRecord.index, isActivatable); if (prev) { prev.tabIndex = 0; prev.focus(); } return prev; } else { return activateLastItem(items, isActivatable); } } /** * Creates an event that requests the parent md-list to deactivate all other * items. */ export function createDeactivateItemsEvent() { return new Event('deactivate-items', { bubbles: true, composed: true }); } /** * Creates an event that requests the menu to set `tabindex=0` on the item and * focus it. We use this pattern because List keeps track of what element is * active in the List by maintaining tabindex. We do not want list items * to set tabindex on themselves or focus themselves so that we can organize all * that logic in the parent List and Menus, and list item stays as dumb as * possible. */ export function createRequestActivationEvent() { return new Event('request-activation', { bubbles: true, composed: true }); } /** * The default `isActivatable` function, which checks if an item is not * disabled. * * @param item The item to check. * @return true if `item.disabled` is `false. */ function isItemNotDisabled(item) { return !item.disabled; } //# sourceMappingURL=list-navigation-helpers.js.map