Skip to content
Snippets Groups Projects
site-search.tsx 5.05 KiB
Newer Older
  • Learn to ignore specific revisions
  • druid's avatar
    druid committed
    export interface SearchSpecialTools {
      url: string;
      label: string;
    }
    
    import {Component, Prop, h, Watch, State, Listen, Host, Event, EventEmitter, Element} from '@stencil/core';
    
    import {ComponentLabels} from '../site-header';
    
    import {ColorVariant} from '../../../utils/utils';
    
    
    @Component({
      tag: 'hy-site-search',
      styleUrl: 'site-search.scss',
    
    })
    export class SiteSearch {
    
    druid's avatar
    druid committed
      @Element() el: HTMLElement;
    
    
      @Prop() color: ColorVariant = ColorVariant.black;
    
      @Prop() isAlternative: boolean = false;
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
      @Prop() labels?: ComponentLabels[] | string;
    
      @Prop() showLabel: boolean = false;
    
    druid's avatar
    druid committed
      @Prop() dataSearchSpecialTools: string;
      private _dataSearchSpecialTools: SearchSpecialTools[];
    
      @State() isSearchPanelOpen: boolean = false;
      @Event() searchPanelToggled: EventEmitter;
    
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
      private _labels: ComponentLabels[];
    
      @Watch('labels') labelsWatcher(data: ComponentLabels[] | string) {
        this._labels = typeof data === 'string' ? JSON.parse(data) : data;
      }
    
    
    druid's avatar
    druid committed
      componentWillLoad() {
        if (this.dataSearchSpecialTools) {
          this._dataSearchSpecialTools = JSON.parse(this.dataSearchSpecialTools);
        }
      }
    
    
    Markus Kalijärvi's avatar
    Markus Kalijärvi committed
      componentWillRender() {
        this.labelsWatcher(this.labels);
      }
    
    druid's avatar
    druid committed
      // CLose the search panel if user opens the desktop menu panel.
      @Listen('menuDesktopToggled', {target: 'document'})
      desktopMenuToggled() {
        this.isSearchPanelOpen = false;
      }
    
      // CLose the search panel if user opens the language menu.
      @Listen('menuLanguageToggled', {target: 'document'})
      menuLanguageToggled() {
        this.isSearchPanelOpen = false;
      }
    
      // Close the search panel if user clicks anywhere outside the Search component.
      @Listen('click', {target: 'window'})
      handleWindowClick(event) {
        if (event.target.tagName.toLowerCase() !== 'hy-site-search') {
          this.isSearchPanelOpen = false;
        }
        event.stopPropagation();
      }
    
      handleSearchPanelToggle() {
        this.isSearchPanelOpen = !this.isSearchPanelOpen;
    
        if (this.isSearchPanelOpen) {
          //const searchPanelSelector = this.el as HTMLElement;
    
          // Close desktop menu panel and lang menu panel if they are open.
          this.searchPanelToggled.emit();
    
          let hyHeader = this.el.closest('.hy-site-header') as HTMLElement;
          let rectHeader = hyHeader.getBoundingClientRect();
    
          const headerHeight = `${rectHeader.bottom}px`;
          const searchPanel = this.el.shadowRoot.querySelectorAll(`.site-search__panel`)[0] as HTMLElement;
          searchPanel.style.top = headerHeight;
        }
        //event.stopPropagation();
      }
    
      handleSearchPanelClose() {
        this.isSearchPanelOpen = false;
      }
    
    
      render() {
        return (
    
    druid's avatar
    druid committed
          <Host
    
    druid's avatar
    druid committed
              'site-search': true,
              'site-search__is-open': this.isSearchPanelOpen,
    
    druid's avatar
    druid committed
            <button
              aria-label={this._labels['open']}
              class={{
                'button--search': true,
                'is-open--menu': this.isAlternative,
                'is-open': this.isSearchPanelOpen,
              }}
              onClick={() => this.handleSearchPanelToggle()}
            >
              {this.showLabel ? <span class={'button--search__label'}>{this._labels['label']}</span> : ''}
              <hy-icon icon={'hy-icon-search'} size={this.size} fill={this.color} />
            </button>
            <div
              class={{
                'site-search__panel': true,
                'site-search__panel__is-open': this.isSearchPanelOpen,
              }}
            >
              <div class="site-search__panel__title">
                <div class="site-search__panel__title__label">
                  <h1>Search</h1>
                  <div>web pages, study options, people, research groups, etc…</div>
                </div>
                <button
                  onClick={() => this.handleSearchPanelClose()}
                  class={{
                    'site-search__panel__panel-toggle': true,
                  }}
                  aria-label="Exit Search"
                >
                  <span class="site-search__panel__panel-toggle__label">
                    <span class="site-search__panel__panel-toggle__label__title">Exit Search</span>
                    <hy-icon icon={'hy-icon-remove'} size={20} fill={ColorVariant.black} />
                  </span>
                </button>
              </div>
              <div class="site-search__panel__input">
                <hy-search-field input-id="search" label="Search degree programmes" />
              </div>
              <div class="site-search__panel__results">
                <div class="filters"></div>
                <div class="results"></div>
              </div>
              {this.dataSearchSpecialTools && this._dataSearchSpecialTools.length > 0 && (
                <div class="site-search__panel__tools">
                  <div>Special Search tools</div>
                  {this._dataSearchSpecialTools.map((i) => {
                    return (
                      <a class={'search-special-tool'} href={i.url}>
                        <hy-icon icon={'hy-icon-arrow-to-right'} size={14} fill={ColorVariant.black} />
                        <span class={'search-special-tool__label'}>{i.label}</span>
                      </a>
                    );
                  })}
                </div>
              )}
            </div>
          </Host>