import { css as litCss, LitElement, PropertyValues } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { html, nothing } from 'lit/html.js'; import { css, theme } from 'twind/css'; import { Hideable } from './utils/CommonInterfaces'; import { spread } from './utils/LitHelper'; import { SpreadController } from './utils/SpreadController'; import { TailwindStylesController } from './utils/TailwindStylesController'; export type AlertType = | 'error' | 'error-with-icon' | 'success' | 'success-with-icon'; @customElement('mono-alert') export class MonoAlertComp extends LitElement implements Hideable { static styles = litCss` ::slotted(p:first-of-type) { margin: 0; } `; private __spreadController: SpreadController = new SpreadController(this); private __stylesController: TailwindStylesController = new TailwindStylesController( this, ); @property({ type: String, reflect: true, }) type: AlertType = 'error'; @property({ type: Boolean, reflect: true }) hidden: boolean = false; __computePrimaryColor() { if (this.type === 'error' || this.type === 'error-with-icon') { return 'alert'; } return 'success'; } __computeInsetPrimaryColor() { if (this.type === 'error' || this.type === 'error-with-icon') { return theme('colors.alert'); } return theme('colors.success'); } __getIcon() { switch (this.type) { case 'error-with-icon': return html``; case 'success-with-icon': return html``; default: return nothing; } } private __getSlotNamed(name: string) { return Array.from(this.children).find((child) => child.slot === name); } isHidden() { return this.hidden; } updated(changed: PropertyValues): void { if (changed.has('hidden')) { const event = new CustomEvent('mono-hideable', { detail: { hidden: this.hidden }, bubbles: true, composed: true, }); this.dispatchEvent(event); } } render() { const attributesToSpread = this.__spreadController.buildSpreadAttributesIgnoring( ['as', 'style', 'class', 'slot', 'type', 'hidden'], ); const alertBefore = css({ '&::before': { content: '""', display: 'flex', 'flex-shrink': 0, width: '4px', 'background-color': this.__computeInsetPrimaryColor(), }, }); const hasIcon = this.__getSlotNamed('icon') || this.type === 'error-with-icon' || this.type === 'success-with-icon'; return html` `; } /* eslint-enable lit/binding-positions,lit/no-invalid-html */ } declare global { interface HTMLElementTagNameMap { 'mono-alert': MonoAlertComp; } }