Newer
Older
iuav-ui / src / components / contacts / contact-card.ts
/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/

import {LitElement, html, css, unsafeCSS} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import { breakpoints } from '../../breakpoints';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';

@customElement('iu-contact-card')

export class ContactCard extends LitElement {
  static override styles = css`
    :host{
      display: flex;
      align-items: flex-end;
      aspect-ratio: 1/1;
      background: var(--iu-color-black);
      color: var(--iu-color-yellow-100);
      padding: var(--iu-grid-gutter);
    }
    :host(.external) a svg{
      transform: rotate(-45deg);
    }
    :host(.span-2){
      aspect-ratio: unset;
    }
    @media ${unsafeCSS(breakpoints.xl)} {
      :host(.span-2){
        aspect-ratio: 2/0.975;
      }
    }
    div{
      display: flex;
      flex-direction: column;
      width: 100%;
      height: 100%;
    }
    header{
      flex-grow: 1;
    }
    header span{
      display: block;
    }
    .title{
      font: var(--iu-f-lg);
    }
    .sub{
      margin-top: 1rem;
    }
    header a{
      display: flex;
      align-items: center;
      text-decoration: none;
      color: var(--iu-color-yellow-100);
    }
    header a span{
      flex-grow: 1;
    }
    header a svg{
      width: 40px;
    }
    @media ${unsafeCSS(breakpoints.lg)} {
      :host(.span-2) footer{
        display: grid;
        grid-template-columns: repeat(2,1fr);
      }
    }
    footer ul{
      list-style-type: none;
      margin: 0;
      padding: 0;
    }
    footer ul li a{
      color: var(--iu-color-yellow-100);
    }
    footer ul li a:hover{
      text-decoration: none;
    }
    .description{
      margin-top: var(--iu-spacing-6);
    }
    @media ${unsafeCSS(breakpoints.xl)} {
      .description{
        margin-top: 0;
      }
    }
    .description p{
      margin: 0;
    }
  `;
  
  @property() href? : string;
  @property() name : string = '#';
  @property() sub? : string;
  @property({ type: Array }) contacts?: Array<{ href: string; label: string }> = [];
  @property() description? : string;
  
  /**
  * Checks if a link is external or internal.
  * @param link The URL to check.
  * @returns true if the link is external, false otherwise.
  */
  private isExternalLink(link: string): boolean {
    const linkElement = document.createElement('a');
    linkElement.href = link;
    return linkElement.hostname !== window.location.hostname && !!linkElement.hostname;
  }

  /**
   * Applies the appropriate class to the component based on the link type.
   */
    private checkLinkType() {
      if (this.href) {
        const isExternal = this.isExternalLink(this.href);
        this.classList.toggle('external', isExternal);
        this.classList.toggle('internal', !isExternal);
      }
    }
  
  
  /**
   * If component has description, span for 2 columns
   */
  private checkCardSpan(){
    if (this.description != undefined) {
      this.classList.add('span-2')
    }
  }
  
  override firstUpdated(){
    super.firstUpdated();
    this.checkCardSpan();
    this.checkLinkType();
  }
  
  override render() {
    return html`
      <div>
        <header>
          ${this. href 
            ? html`<a href="${this.href}" class="title"><span>${this.name}</span><svg width="27" height="20" viewBox="0 0 27 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16.6667 1L25 10M25 10L16.6667 19M25 10H0" stroke="#FFCC00" stroke-width="2"/></svg></a>`
            : html`<span class="title">${this.name}</span>`
          }
          ${this.sub && html`<span class="sub">${this.sub}</span>`}
        </header>
        <footer>
          ${this.contacts && html`
            <ul>
              ${this.contacts.map(
                (contact) => html`
                  <li><a href="${contact.href}">${unsafeHTML(contact.label)}</a></li>
                `
              )}      
            </ul>
            ${this.description && html`
              <div class="description"><p>${this.description}</p></div>
            `}
          `}
        </footer>
      </div>
    `; 
  }
}
  
declare global {
  interface HTMLElementTagNameMap {
    'iu-contact-card': ContactCard;
  }
}