Слияние кода завершено, страница обновится автоматически
/**
* @license
* Copyright 2018 Google Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import {MDCFoundation} from '@material/base/foundation';
import {cssClasses as listCssClasses} from '@material/list/constants';
import {MDCMenuAdapter} from './adapter';
import {cssClasses, DefaultFocusState, numbers, strings} from './constants';
/** MDC Menu Foundation */
export class MDCMenuFoundation extends MDCFoundation<MDCMenuAdapter> {
static override get cssClasses() {
return cssClasses;
}
static override get strings() {
return strings;
}
static override get numbers() {
return numbers;
}
private defaultFocusState = DefaultFocusState.LIST_ROOT;
private selectedIndex = -1;
/**
* @see {@link MDCMenuAdapter} for typing information on parameters and return types.
*/
static override get defaultAdapter(): MDCMenuAdapter {
// tslint:disable:object-literal-sort-keys Methods should be in the same order as the adapter interface.
return {
addClassToElementAtIndex: () => undefined,
removeClassFromElementAtIndex: () => undefined,
addAttributeToElementAtIndex: () => undefined,
removeAttributeFromElementAtIndex: () => undefined,
getAttributeFromElementAtIndex: () => null,
elementContainsClass: () => false,
closeSurface: () => undefined,
getElementIndex: () => -1,
notifySelected: () => undefined,
getMenuItemCount: () => 0,
focusItemAtIndex: () => undefined,
focusListRoot: () => undefined,
getSelectedSiblingOfItemAtIndex: () => -1,
isSelectableItemAtIndex: () => false,
};
// tslint:enable:object-literal-sort-keys
}
constructor(adapter?: Partial<MDCMenuAdapter>) {
super({...MDCMenuFoundation.defaultAdapter, ...adapter});
}
override destroy() {
this.adapter.closeSurface();
}
handleKeydown(event: KeyboardEvent) {
const {key, keyCode} = event;
const isTab = key === 'Tab' || keyCode === 9;
if (isTab) {
this.adapter.closeSurface(/** skipRestoreFocus */ true);
}
}
handleItemAction(listItem: HTMLElement) {
const index = this.adapter.getElementIndex(listItem);
if (index < 0) {
return;
}
this.adapter.notifySelected({index});
const skipRestoreFocus = this.adapter.getAttributeFromElementAtIndex(
index, strings.SKIP_RESTORE_FOCUS) === 'true';
this.adapter.closeSurface(skipRestoreFocus);
if (this.adapter.isSelectableItemAtIndex(index)) {
this.setSelectedIndex(index);
}
}
handleMenuSurfaceOpened() {
switch (this.defaultFocusState) {
case DefaultFocusState.FIRST_ITEM:
this.adapter.focusItemAtIndex(0);
break;
case DefaultFocusState.LAST_ITEM:
this.adapter.focusItemAtIndex(this.adapter.getMenuItemCount() - 1);
break;
case DefaultFocusState.NONE:
// Do nothing.
break;
default:
this.adapter.focusListRoot();
break;
}
}
/**
* Sets default focus state where the menu should focus every time when menu
* is opened. Focuses the list root (`DefaultFocusState.LIST_ROOT`) element by
* default.
*/
setDefaultFocusState(focusState: DefaultFocusState) {
this.defaultFocusState = focusState;
}
/** @return Index of the currently selected list item within the menu. */
getSelectedIndex() {
return this.selectedIndex;
}
/**
* Selects the list item at `index` within the menu.
* @param index Index of list item within the menu.
*/
setSelectedIndex(index: number) {
this.validatedIndex(index);
if (!this.adapter.isSelectableItemAtIndex(index)) {
throw new Error(
'MDCMenuFoundation: No selection group at specified index.');
}
const prevSelectedIndex =
this.adapter.getSelectedSiblingOfItemAtIndex(index);
if (prevSelectedIndex >= 0) {
this.adapter.removeAttributeFromElementAtIndex(
prevSelectedIndex, strings.ARIA_CHECKED_ATTR);
this.adapter.removeClassFromElementAtIndex(
prevSelectedIndex, cssClasses.MENU_SELECTED_LIST_ITEM);
}
this.adapter.addClassToElementAtIndex(
index, cssClasses.MENU_SELECTED_LIST_ITEM);
this.adapter.addAttributeToElementAtIndex(
index, strings.ARIA_CHECKED_ATTR, 'true');
this.selectedIndex = index;
}
/**
* Sets the enabled state to isEnabled for the menu item at the given index.
* @param index Index of the menu item
* @param isEnabled The desired enabled state of the menu item.
*/
setEnabled(index: number, isEnabled: boolean): void {
this.validatedIndex(index);
if (isEnabled) {
this.adapter.removeClassFromElementAtIndex(
index, listCssClasses.LIST_ITEM_DISABLED_CLASS);
this.adapter.addAttributeToElementAtIndex(
index, strings.ARIA_DISABLED_ATTR, 'false');
} else {
this.adapter.addClassToElementAtIndex(
index, listCssClasses.LIST_ITEM_DISABLED_CLASS);
this.adapter.addAttributeToElementAtIndex(
index, strings.ARIA_DISABLED_ATTR, 'true');
}
}
private validatedIndex(index: number): void {
const menuSize = this.adapter.getMenuItemCount();
const isIndexInRange = index >= 0 && index < menuSize;
if (!isIndexInRange) {
throw new Error('MDCMenuFoundation: No list item at specified index.');
}
}
}
// tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.
export default MDCMenuFoundation;
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )