class Gauge extends HTMLElement { constructor(iconName, label) { super(); this.iconName = iconName; this.label = label; } connectedCallback() { this.role = "progressbar"; this.classList.add("icon", `icon-${this.iconName}`); this.full = this.appendChild(document.createElement("div")); this.full.classList.add("full", "icon", `icon-${this.iconName}-white`); } setValue(value, valueMax) { let clampedNormalized = Math.max(0, Math.min(1, value / valueMax)); this.style.setProperty("--progress", `${clampedNormalized * 100}%`); this.title = `${this.label}: ${value} / ${valueMax} (${Math.ceil(clampedNormalized * 100)}%)`; } } customElements.define("rkgk-brush-cost-gauge", Gauge); export class BrushCostGauges extends HTMLElement { constructor() { super(); } connectedCallback() { this.codeSizeGauge = this.appendChild( createGauge({ className: "code-size", iconName: "brackets", label: "Code size", }), ); this.fuelGauge = this.appendChild( createGauge({ className: "fuel", iconName: "droplet", label: "Fuel", }), ); this.objectsGauge = this.appendChild( createGauge({ className: "objects", iconName: "object", label: "Objects", }), ); this.memoryGauge = this.appendChild( createGauge({ className: "memory", iconName: "memory", label: "Bulk memory", }), ); this.codeSizeGauge.setValue(0); this.fuelGauge.setValue(0); this.objectsGauge.setValue(0); this.memoryGauge.setValue(0); } update(stats) { this.codeSizeGauge.setValue(stats.astSize, stats.astSizeMax); this.fuelGauge.setValue(stats.fuel, stats.fuelMax); this.objectsGauge.setValue(stats.numRefs, stats.numRefsMax); this.memoryGauge.setValue(stats.memory, stats.memoryMax); } } customElements.define("rkgk-brush-cost-gauges", BrushCostGauges); function createGauge({ className, iconName, label }) { let gauge = new Gauge(iconName, label); gauge.classList.add(className); return gauge; }