UNPKG

@hashicorp/design-system-components

Version:
124 lines (121 loc) 5.1 kB
import Component from '@glimmer/component'; import { guidFor } from '@ember/object/internals'; import { tracked } from '@glimmer/tracking'; import { registerDestructor } from '@ember/destroyable'; import { hash } from '@ember/helper'; import { not, and } from 'ember-truth-helpers'; import { NavigationNarrator } from 'ember-a11y-refocus'; import focusTrap from 'ember-focus-trap/modifiers/focus-trap'; import { hdsBreakpoints } from '../../../utils/hds-breakpoints.js'; import HdsAppHeaderMenuButton from './menu-button.js'; import { precompileTemplate } from '@ember/template-compilation'; import { setComponentTemplate } from '@ember/component'; import { g, i } from 'decorator-transforms/runtime'; /** * Copyright IBM Corp. 2021, 2025 * SPDX-License-Identifier: MPL-2.0 */ class HdsAppHeader extends Component { static { g(this.prototype, "_isOpen", [tracked], function () { return false; }); } #_isOpen = (i(this, "_isOpen"), void 0); static { g(this.prototype, "_isDesktop", [tracked], function () { return true; }); } #_isDesktop = (i(this, "_isDesktop"), void 0); static { g(this.prototype, "_hasOverflowContent", [tracked], function () { return false; }); } #_hasOverflowContent = (i(this, "_hasOverflowContent"), void 0); _desktopMQ; hasA11yRefocus = this.args.hasA11yRefocus ?? true; a11yRefocusSkipTo = '#' + (this.args.a11yRefocusSkipTo ?? 'hds-main'); // Generates a unique ID for the Menu Content _menuContentId = 'hds-menu-content-' + guidFor(this); // we use the `md` breakpoint for `desktop` viewports, but consumers can override its value _desktopMQVal = this.args.breakpoint ?? hdsBreakpoints['md'].px; constructor(owner, args) { super(owner, args); this._desktopMQ = window.matchMedia(`(min-width: ${this._desktopMQVal})`); this.addEventListeners(); registerDestructor(this, () => { this.removeEventListeners(); }); } addEventListeners() { document.addEventListener('keydown', this.escapePress, true); this._desktopMQ.addEventListener('change', this.updateDesktopVariable, true); // set initial state based on viewport using a "synthetic" event const syntheticEvent = new MediaQueryListEvent('change', { matches: this._desktopMQ.matches, media: this._desktopMQ.media }); this.updateDesktopVariable(syntheticEvent); } removeEventListeners() { document.removeEventListener('keydown', this.escapePress, true); this._desktopMQ.removeEventListener('change', this.updateDesktopVariable, true); } // In mobile view when the menu is open, trap focus within the AppHeader get shouldTrapFocus() { return !this._isDesktop && this._isOpen; } get classNames() { const classes = ['hds-app-header']; if (this._isDesktop) { classes.push('hds-app-header--is-desktop'); } else { classes.push('hds-app-header--is-mobile'); // open and closed menu states are only relevant on mobile if (this._isOpen) { classes.push('hds-app-header--menu-is-open'); } else { classes.push('hds-app-header--menu-is-closed'); } } return classes.join(' '); } escapePress = event => { if (event.key === 'Escape' && this._isOpen && !this._isDesktop) { this._isOpen = false; } }; onClickToggle = () => { this._isOpen = !this._isOpen; }; close = () => { if (this._isOpen && !this._isDesktop) { this._isOpen = false; } }; updateDesktopVariable = event => { this._isDesktop = event.matches; // Close the menu when switching to desktop view // (prevents menu from being open when resizing which causes Skip button to not render) if (this._isDesktop) { this._isOpen = false; } }; static { setComponentTemplate(precompileTemplate("<div class={{this.classNames}} {{focusTrap isActive=this.shouldTrapFocus}} ...attributes>\n {{#if (and this.hasA11yRefocus (not this._isOpen))}}\n <NavigationNarrator @routeChangeValidator={{@a11yRefocusRouteChangeValidator}} @skipTo={{this.a11yRefocusSkipTo}} @skipText={{@a11yRefocusSkipText}} @navigationText={{@a11yRefocusNavigationText}} @excludeAllQueryParams={{@a11yRefocusExcludeAllQueryParams}} />\n {{/if}}\n\n {{yield (hash close=this.close) to=\"logo\"}}\n\n {{#if (not this._isDesktop)}}\n <HdsAppHeaderMenuButton @onClickToggle={{this.onClickToggle}} @isOpen={{this._isOpen}} @menuContentId={{this._menuContentId}} />\n {{/if}}\n\n <div class=\"hds-app-header__actions\" id={{this._menuContentId}}>\n <div class=\"hds-app-header__global-actions\">\n {{yield (hash close=this.close) to=\"globalActions\"}}\n </div>\n\n <div class=\"hds-app-header__utility-actions\">\n {{yield (hash close=this.close) to=\"utilityActions\"}}\n </div>\n </div>\n</div>", { strictMode: true, scope: () => ({ focusTrap, and, not, NavigationNarrator, hash, HdsAppHeaderMenuButton }) }), this); } } export { HdsAppHeader as default }; //# sourceMappingURL=index.js.map