UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

118 lines (117 loc) • 9.17 kB
/*! All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://github.com/Esri/calcite-design-system/blob/dev/LICENSE.md for details. v3.2.1 */ import { c as customElement } from "../../chunks/runtime.js"; import { html, nothing, svg } from "lit"; import { LitElement, setAttribute, safeClassMap, safeStyleMap } from "@arcgis/lumina"; import { g as guid } from "../../chunks/guid.js"; import { u as useT9n } from "../../chunks/useT9n.js"; import { css } from "@lit/reactive-element/css-tag.js"; const CSS = { percentage: "percentage", progressRing: "ring--progress", ring: "ring", rings: "rings", text: "text", trackRing: "ring--track" }; const styles = css`:host{position:relative;margin-inline:auto;display:flex;align-items:center;justify-content:center;opacity:1;flex-direction:column;min-block-size:var(--calcite-loader-size);font-size:var(--calcite-loader-font-size);stroke-width:var(--calcite-internal-stroke-width);fill:none;transform:scale(1);padding-block:var(--calcite-loader-spacing, 4rem)}:host([scale=s]){--calcite-internal-stroke-width: 3;--calcite-internal-text-offset: var(--calcite-spacing-xxs);--calcite-internal-loader-font-size: var(--calcite-font-size--3);--calcite-internal-loader-size: 2rem;--calcite-internal-loader-size-inline: .75rem;--calcite-internal-loader-value-line-height: .625rem}:host([scale=m]){--calcite-internal-stroke-width: 6;--calcite-internal-text-offset: var(--calcite-spacing-sm);--calcite-internal-loader-font-size: var(--calcite-font-size-0);--calcite-internal-loader-size: 4rem;--calcite-internal-loader-size-inline: 1rem;--calcite-internal-loader-value-line-height: 1.375rem}:host([scale=l]){--calcite-internal-stroke-width: 8;--calcite-internal-text-offset: var(--calcite-spacing-md);--calcite-internal-loader-font-size: var(--calcite-font-size-2);--calcite-internal-loader-size: 6rem;--calcite-internal-loader-size-inline: 1.5rem;--calcite-internal-loader-value-line-height: 1.71875rem}.text{display:block;text-align:center;font-size:var(--calcite-font-size--2);line-height:1rem;margin-block-start:var(--calcite-loader-text-spacing, var(--calcite-internal-text-offset));font-weight:var(--calcite-loader-text-weight, var(--calcite-font-weight-normal));color:var(--calcite-loader-text-color, var(--calcite-color-text-1))}.percentage{display:block;text-align:center;font-size:var(--calcite-loader-font-size);inline-size:var(--calcite-loader-size, var(--calcite-internal-loader-size));line-height:var(--calcite-internal-loader-value-line-height);align-self:center;color:var(--calcite-loader-text-color, var(--calcite-color-text-1))}.rings{position:relative;display:flex;overflow:visible;opacity:1;inline-size:var(--calcite-loader-size, var(--calcite-internal-loader-size));block-size:var(--calcite-loader-size, var(--calcite-internal-loader-size))}.ring{position:absolute;inset-block-start:0px;transform-origin:center;overflow:visible;inset-inline-start:0;inline-size:var(--calcite-loader-size, var(--calcite-internal-loader-size));block-size:var(--calcite-loader-size, var(--calcite-internal-loader-size))}.ring--track{stroke:var(--calcite-loader-track-color, var(--calcite-color-transparent-press))}.ring--progress{stroke:var(--calcite-loader-progress-color, var(--calcite-color-brand));transform:rotate(-90deg);transition:all var(--calcite-internal-animation-timing-fast) linear}:host([type=indeterminate]) .ring--progress{animation:loader-clockwise calc(var(--calcite-internal-animation-timing-slow) / var(--calcite-internal-duration-factor) * 2 / var(--calcite-internal-duration-factor)) linear infinite}:host([inline]){--calcite-internal-stroke-width: 2;position:relative;margin:0;stroke:currentColor;stroke-width:2;padding-block:0px;block-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)));min-block-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)));inline-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)));vertical-align:calc(var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline))) * -1 * .2)}:host([inline]) .rings{inset-block-start:0px;margin:0;inset-inline-start:0;inline-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)));block-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)))}:host([inline]) .ring{inline-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)));block-size:var(--calcite-loader-size, var(--calcite-loader-size-inline, var(--calcite-internal-loader-size-inline)))}:host([inline]) .ring--progress{stroke:var(--calcite-loader-progress-color-inline, currentColor)}:host([complete]){opacity:0;transform:scale(.75);transform-origin:center;transition:opacity var(--calcite-internal-animation-timing-medium) linear 1s,transform var(--calcite-internal-animation-timing-medium) linear 1s}:host([complete]) .rings{opacity:0;transform:scale(.75);transform-origin:center;transition:opacity calc(.18s * var(--calcite-internal-duration-factor)) linear .8s,transform calc(.18s * var(--calcite-internal-duration-factor)) linear .8s}:host([complete]) .percentage{color:var(--calcite-color-brand);transform:scale(1.05);transform-origin:center;transition:color var(--calcite-internal-animation-timing-medium) linear,transform var(--calcite-internal-animation-timing-medium) linear}@keyframes loader-clockwise{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host([hidden]){display:none}[hidden]{display:none}`; class Loader extends LitElement { constructor() { super(...arguments); this.messages = useT9n({ name: null }); this.complete = false; this.inline = false; this.scale = "m"; this.text = ""; this.type = "indeterminate"; this.value = 0; } static { this.properties = { complete: [7, {}, { reflect: true, type: Boolean }], inline: [7, {}, { reflect: true, type: Boolean }], label: 1, scale: [3, {}, { reflect: true }], text: 1, type: [3, {}, { reflect: true }], value: [9, {}, { type: Number }] }; } static { this.styles = styles; } connectedCallback() { super.connectedCallback(); this.updateFormatter(); } load() { requestAnimationFrame(() => this.valueChangeHandler()); } willUpdate(changes) { if (changes.has("value") && (this.hasUpdated || this.value !== 0)) { this.valueChangeHandler(); } if (changes.has("type") && (this.hasUpdated || this.type !== "indeterminate") || changes.has("messages")) { this.updateFormatter(); } } valueChangeHandler() { this.complete = this.type.startsWith("determinate") && this.value === 100; } formatValue() { if (this.type !== "determinate-value") { return `${this.value}`; } return this.formatter.format(this.value / 100); } getSize(scale) { return { s: 32, m: 64, l: 96 }[scale]; } getInlineSize(scale) { return { s: 12, m: 16, l: 24 }[scale]; } updateFormatter() { if (this.type !== "determinate-value" || this.formatter?.resolvedOptions().locale === this.messages._lang) { return; } this.formatter = new Intl.NumberFormat(this.messages._lang, { style: "percent" }); } render() { const { el, inline, label, text, type, value } = this; const id = el.id || guid(); const isDeterminate = type !== "indeterminate"; const valueNow = Math.floor(value); this.el.ariaLabel = label; this.el.ariaValueMax = isDeterminate ? "100" : void 0; this.el.ariaValueMin = isDeterminate ? "0" : void 0; this.el.ariaValueNow = isDeterminate ? valueNow.toString() : void 0; setAttribute(this.el, "id", id); this.el.role = "progressbar"; return html`<div class=${safeClassMap(CSS.rings)}>${this.renderRing("track")}${this.renderRing("progress")}${!inline && isDeterminate && html`<div class=${safeClassMap(CSS.percentage)}>${this.formatValue()}</div>` || ""}</div>${!inline && text && html`<div class=${safeClassMap(CSS.text)}>${text}</div>` || ""}`; } renderRing(type) { const { inline, scale, value } = this; const size = inline ? this.getInlineSize(scale) : this.getSize(scale); const radiusRatio = 0.45; const radius = size * radiusRatio; let style; if (type === "progress") { const circumference = 2 * radius * Math.PI; const progress = (this.type.startsWith("determinate") ? value : 24) / 100 * circumference; const remaining = circumference - progress; style = { "stroke-dasharray": `${progress} ${remaining}` }; } return html`<svg aria-hidden=true class=${safeClassMap({ [CSS.ring]: true, [CSS.trackRing]: type === "track", [CSS.progressRing]: type === "progress" })} style=${safeStyleMap(style)} viewBox=${`0 0 ${size} ${size}`}>${svg`<circle cx=${size / 2} cy=${size / 2} r=${radius ?? nothing} />`}</svg>`; } } customElement("calcite-loader", Loader); export { Loader };