/** * @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; } }