shopper
Version:
plug shopify into any website
101 lines (81 loc) • 2.22 kB
text/typescript
import {property} from "lit/decorators.js"
import {html, css, CSSResultArray} from "lit"
import {ShopperComponent} from "./shopper-component.js"
import loaderSvg from "../icons/feather/loader.svg.js"
import alertTriangleSvg from "../icons/feather/alert-triangle.svg.js"
export enum LoadableState {
Loading,
Error,
Ready,
}
const _state = Symbol()
const _renderError = Symbol()
const _renderLoading = Symbol()
export class LoadableComponent extends ShopperComponent {
({type: String}) errorMessage: string = "error"
({type: String}) loadingMessage: string = "loading..."
({type: Number}) private [_state]: LoadableState = LoadableState.Loading
set loadableState(value: LoadableState) { this[_state] = value }
get loadableState(): LoadableState { return this[_state] }
()
loadingIcon = loaderSvg
()
errorIcon = alertTriangleSvg
static get styles(): CSSResultArray {return [css`
.loadable {
display: flex;
align-items: center;
justify-content: center;
font-family: monospace;
color: var(--shopper-loading-color, currentColor);
}
.loadable svg {
width: 2em;
height: 2em;
margin-right: 1em;
}
@keyframes loadable-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes loadable-fade {
from { opacity: 0.8; }
to { opacity: 0.4; }
}
.loadable.loading svg {
opacity: 0.5;
animation:
loadable-spin 10s linear infinite,
loadable-fade 500ms linear infinite alternate;
}
.loadable.error {
color: var(--shopper-loading-error, maroon);
}
`]}
renderReady() {
throw new Error("loadable: renderReady must be implemented")
}
render() {
switch (this[_state]) {
case LoadableState.Loading: return this[_renderLoading]()
case LoadableState.Error: return this[_renderError]()
case LoadableState.Ready: return this.renderReady()
}
}
private [_renderLoading]() {
return html`
<div class="loadable loading">
${this.loadingIcon}
<p>${this.loadingMessage}</p>
</div>
`
}
private [_renderError]() {
return html`
<div class="loadable error">
${this.errorIcon}
<p>${this.errorMessage}</p>
</div>
`
}
}