UNPKG

@roots/bud-client

Version:

Client scripts for @roots/bud

168 lines (164 loc) 4.32 kB
import { pulse } from './indicator.pulse.js'; /** * Indicator web component */ export class Component extends HTMLElement { static get observedAttributes() { return [`has-errors`, `has-warnings`, `action`]; } /** * Class constructor */ constructor() { super(); /** * Status indicator colors */ this.colors = { error: [220, 38, 38, 1], pending: [59, 130, 246, 1], success: [4, 120, 87, 1], warn: [252, 211, 77, 1], }; /** * Component name */ this.name = `bud-activity-indicator`; /** * Has component rendered */ this.rendered = false; this.renderShadow(); } /** * Status is error */ 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 */ 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 */ 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 */ onWarning() { this.show(); this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`error`, `success`, `pending`); this.shadowRoot?.querySelector(this.selector)?.classList.add(`warning`); this.hide(); } 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 */ get hasErrors() { return this.getAttribute(`has-errors`) == `true`; } /** * Get accessor: has warnings */ get hasWarnings() { return this.getAttribute(`has-warnings`) == `true`; } /** * Hide status indicator */ hide() { this.timeout = setTimeout(() => { this.shadowRoot ?.querySelector(this.selector) ?.classList.remove(`show`); }, 2000); } /** * Render status indicator */ 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 */ get selector() { return `.${this.name}`; } /** * Show status indicator */ show() { this.timeout && clearTimeout(this.timeout); this.shadowRoot?.querySelector(this.selector)?.classList.add(`show`); } }