github.com/hernad/nomad@v1.6.112/ui/app/components/popover-menu.js (about)

     1  /**
     2   * Copyright (c) HashiCorp, Inc.
     3   * SPDX-License-Identifier: MPL-2.0
     4   */
     5  
     6  import Component from '@ember/component';
     7  import { action } from '@ember/object';
     8  import { scheduleOnce } from '@ember/runloop';
     9  import { classNames } from '@ember-decorators/component';
    10  import classic from 'ember-classic-decorator';
    11  
    12  const TAB = 9;
    13  const ARROW_DOWN = 40;
    14  const FOCUSABLE = [
    15    'a:not([disabled])',
    16    'button:not([disabled])',
    17    'input:not([disabled]):not([type="hidden"])',
    18    'textarea:not([disabled])',
    19    '[tabindex]:not([disabled]):not([tabindex="-1"])',
    20  ].join(', ');
    21  
    22  @classic
    23  @classNames('popover')
    24  export default class PopoverMenu extends Component {
    25    triggerClass = '';
    26    isOpen = false;
    27    isDisabled = false;
    28    label = '';
    29  
    30    dropdown = null;
    31  
    32    capture(dropdown) {
    33      // It's not a good idea to grab a dropdown reference like this, but it's necessary
    34      // in order to invoke dropdown.actions.close in traverseList as well as
    35      // dropdown.actions.reposition when the label or selection length changes.
    36      this.set('dropdown', dropdown);
    37    }
    38  
    39    didReceiveAttrs() {
    40      super.didReceiveAttrs();
    41      const dropdown = this.dropdown;
    42      if (this.isOpen && dropdown) {
    43        scheduleOnce('afterRender', this, this.repositionDropdown);
    44      }
    45    }
    46  
    47    repositionDropdown() {
    48      this.dropdown.actions.reposition();
    49    }
    50  
    51    @action
    52    openOnArrowDown(dropdown, e) {
    53      if (!this.isOpen && e.keyCode === ARROW_DOWN) {
    54        dropdown.actions.open(e);
    55        e.preventDefault();
    56      } else if (this.isOpen && (e.keyCode === TAB || e.keyCode === ARROW_DOWN)) {
    57        const optionsId = this.element
    58          .querySelector('.popover-trigger')
    59          .getAttribute('aria-owns');
    60        const popoverContentEl = document.querySelector(`#${optionsId}`);
    61        const firstFocusableElement = popoverContentEl.querySelector(FOCUSABLE);
    62  
    63        if (firstFocusableElement) {
    64          firstFocusableElement.focus();
    65          e.preventDefault();
    66        }
    67      }
    68    }
    69  }