Spaces:
Running
Running
| class ProgressRing extends HTMLElement { | |
| constructor() { | |
| super(); | |
| this.attachShadow({ mode: 'open' }); | |
| } | |
| static get observedAttributes() { | |
| return ['value', 'color', 'size']; | |
| } | |
| connectedCallback() { | |
| this.animateValue(); | |
| } | |
| attributeChangedCallback(name, oldValue, newValue) { | |
| if (oldValue !== newValue && this.shadowRoot) { | |
| this.render(); | |
| this.animateValue(); | |
| } | |
| } | |
| render() { | |
| const value = this.getAttribute('value') || 0; | |
| const color = this.getAttribute('color') || '#10b981'; | |
| const size = this.getAttribute('size') || 150; | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: inline-block; | |
| } | |
| .progress-ring { | |
| transform: rotate(-90deg); | |
| } | |
| .progress-ring__circle { | |
| transition: stroke-dashoffset 0.5s ease-in-out; | |
| transform-origin: 50% 50%; | |
| } | |
| </style> | |
| <svg class="progress-ring" width="${size}" height="${size}"> | |
| <circle | |
| class="progress-ring__circle-bg" | |
| stroke="#1e293b" | |
| stroke-width="12" | |
| fill="transparent" | |
| r="${size/2 - 12}" | |
| cx="${size/2}" | |
| cy="${size/2}" | |
| /> | |
| <circle | |
| class="progress-ring__circle" | |
| stroke="${color}" | |
| stroke-width="12" | |
| stroke-linecap="round" | |
| fill="transparent" | |
| r="${size/2 - 12}" | |
| cx="${size/2}" | |
| cy="${size/2}" | |
| style="stroke-dasharray: ${2 * Math.PI * (size/2 - 12)}; stroke-dashoffset: ${2 * Math.PI * (size/2 - 12)}" | |
| /> | |
| </svg> | |
| `; | |
| } | |
| animateValue() { | |
| const circle = this.shadowRoot.querySelector('.progress-ring__circle'); | |
| const value = parseInt(this.getAttribute('value') || 0); | |
| const radius = circle.r.baseVal.value; | |
| const circumference = radius * 2 * Math.PI; | |
| circle.style.strokeDasharray = `${circumference} ${circumference}`; | |
| const offset = circumference - (value / 100) * circumference; | |
| setTimeout(() => { | |
| circle.style.strokeDashoffset = offset; | |
| }, 100); | |
| } | |
| } | |
| customElements.define('progress-ring', ProgressRing); |