github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/components/popover-menu.js (about)

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