@roots/bud-client
Version:
Client scripts for @roots/bud
168 lines (164 loc) • 4.32 kB
JavaScript
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`);
}
}