UNPKG

@roots/bud-client

Version:

Client scripts for @roots/bud

198 lines (168 loc) 4.08 kB
import {pulse} from './indicator.pulse.js' /** * Indicator web component */ export class Component extends HTMLElement { public static get observedAttributes() { return [`has-errors`, `has-warnings`, `action`] } /** * Status indicator colors */ public colors: Record<string, [number, number, number, number]> = { error: [220, 38, 38, 1], pending: [59, 130, 246, 1], success: [4, 120, 87, 1], warn: [252, 211, 77, 1], } /** * Timer */ public timeout?: NodeJS.Timeout /** * Component name */ public name: string = `bud-activity-indicator` /** * Has component rendered */ public rendered: boolean = false /** * Class constructor */ public constructor() { super() this.renderShadow() } /** * Status is error */ public onError() { this.show() this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`warning`, `success`, `pending`) this.shadowRoot?.querySelector(this.selector)?.classList.add(`error`) this.hide() } /** * Status is pending */ public onPending() { this.show() this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`error`, `warning`, `success`) this.shadowRoot?.querySelector(this.selector)?.classList.add(`pending`) this.hide() } /** * Status is success */ public onSuccess() { this.show() this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`error`, `warning`, `pending`) this.shadowRoot?.querySelector(this.selector)?.classList.add(`success`) this.hide() } /** * Status is warning */ public onWarning() { this.show() this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`error`, `success`, `pending`) this.shadowRoot?.querySelector(this.selector)?.classList.add(`warning`) this.hide() } public attributeChangedCallback() { if (this.hasAttribute(`has-errors`)) return this.onError() if (this.hasAttribute(`has-warnings`)) return this.onWarning() if ( this.getAttribute(`action`) == `building` || this.getAttribute(`action`) == `sync` ) return this.onSuccess() this.onPending() } /** * Get accessor: has errors */ public get hasErrors(): boolean { return this.getAttribute(`has-errors`) == `true` } /** * Get accessor: has warnings */ public get hasWarnings(): boolean { return this.getAttribute(`has-warnings`) == `true` } /** * Hide status indicator */ public hide() { this.timeout = setTimeout(() => { this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`show`) }, 2000) } /** * Render status indicator */ public renderShadow() { const container = document.createElement(`div`) container.classList.add(this.name) container.innerHTML = ` <style> .bud-activity-indicator { position: fixed; width: 10px; height: 10px; left: 10px; bottom: 10px; z-index: 9999; margin: 5px; padding: 5px; -webkit-transition: all .6s ease-in-out, transition: all .6s ease-in-out; animation-fill-mode: forwards; pointer-events: none; border-radius: 50%; transform: scale(0); opacity: 0; } .show { opacity: 1; background-color: rgba(255, 255, 255, 1); transform: scale(1); transition: all .6s ease-in-out; } ${pulse(`success`, this.colors.success)} ${pulse(`error`, this.colors.error)} ${pulse(`warning`, this.colors.warn)} ${pulse(`pending`, this.colors.pending)} </style> ` this.attachShadow({mode: `open`}).appendChild(container) } /** * Root div querySelector selector */ public get selector() { return `.${this.name}` } /** * Show status indicator */ public show() { this.timeout && clearTimeout(this.timeout) this.shadowRoot?.querySelector(this.selector)?.classList.add(`show`) } }