/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ import {LitElement, html, css } from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; import { breakpoints } from '../../breakpoints'; @customElement('iu-nav-card') export class NavCard extends LitElement { @query('.title p') private titleElement!: HTMLParagraphElement static override styles = css` :host{ display: block; } .nav-card{ background: var(--iu-color-grey-100); display: block; aspect-ratio: 1/1; display: flex; flex-direction: column; justify-content: end; padding: var(--iu-grid-gutter); color: var(--iu-color-black); text-decoration: none; font-size: var(--iu-fs-lg); &:hover{ background: var(--iu-color-black); color: var(--iu-color-white); } p{ justify-self: end; margin: 0; } } .excerpt{ font-size: var(--iu-fs-1); margin-bottom: var(--iu-spacing-5); flex-grow: 1; } .subtitle{ font-size: var(--iu-fs-1); color: var(--iu-color-grey-300); margin-bottom: var(--iu-spacing-5); flex-grow: 1; } .title{ display: flex; align-items: end; overflow: hidden; flex-shrink: 1; } svg{ width: 27px; height: 20px; flex-shrink: 0; margin-bottom: 10px; margin-left: 20px; } `; @property() href : string = ''; @property() text : string = ''; @property() excerpt? : string; @property() subtitle? : string; private isExternalLink(url: string): boolean { try { const link = new URL(url, window.location.href); return link.hostname !== window.location.hostname; } catch (e) { return false; } } private renderIntIcon() { return html`<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 20"> <path fill-rule="evenodd" clip-rule="evenodd" d="m22.711 9-6.778-7.32L17.4.32 26.363 10 17.4 19.68l-1.467-1.36L22.71 11H0V9h22.711Z" fill="currentColor"/></svg>`; } private renderExtIcon() { return html`<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 20"> <path fill-rule="evenodd" clip-rule="evenodd" d="m23.06 2.526-9.97-.383.077-1.998 13.182.507.506 13.181-1.998.077-.383-9.97L8.414 20 7 18.586l16.06-16.06Z" fill="currentColor"/></svg>`; } private applyMultilineEllipsis(maxLines: number) { if (!this.titleElement) return; const lineHeight = parseFloat(getComputedStyle(this.titleElement).lineHeight); const maxHeight = lineHeight * maxLines; if (this.titleElement.scrollHeight > maxHeight) { let words = this.titleElement.textContent!.split(' '); this.titleElement.textContent = ''; for (let i = 0; i < words.length; i++) { this.titleElement.textContent += words[i] + ' '; if (this.titleElement.scrollHeight > maxHeight) { this.titleElement.textContent = this.titleElement.textContent.trim() + '...'; break; } } } } override firstUpdated() { // this.applyMultilineEllipsis(2); // Limit to 3 lines // window.addEventListener('resize', () => this.applyMultilineEllipsis(3)); // Reapply on resize } override render() { const external = this.isExternalLink(this.href); return html` <a href="${this.href}" class="nav-card"> ${this.subtitle ? html`<span class="subtitle">${this.subtitle}</span>` : ''} ${this.excerpt && !this.subtitle ? html`<span class="excerpt">${this.excerpt}</span>` : ''} <div class="title"> <p>${this.text}</p> ${external ? this.renderExtIcon() : this.renderIntIcon()} </div> </a> `; } } declare global { interface HTMLElementTagNameMap { 'iu-nav-card': NavCard; } }