import { customElement, property, type TemplateResult, } from '@design.estate/dees-element'; import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js'; import { demoFunc } from './demo.js'; import { gaugeStyles } from './styles.js'; import { renderChartGauge } from './template.js'; import { getEchartsSeriesColors } from '../dees-chart-echarts-theme.js'; export interface IGaugeThreshold { value: number; color: string; } declare global { interface HTMLElementTagNameMap { 'dees-chart-gauge': DeesChartGauge; } } @customElement('dees-chart-gauge') export class DeesChartGauge extends DeesChartEchartsBase { public static demo = demoFunc; public static demoGroups = ['Chart']; @property({ type: Number }) accessor value: number = 0; @property({ type: Number }) accessor min: number = 0; @property({ type: Number }) accessor max: number = 100; @property({ type: String }) accessor unit: string = '%'; @property({ type: Array }) accessor thresholds: IGaugeThreshold[] = []; @property({ type: Boolean }) accessor showTicks: boolean = true; public static styles = gaugeStyles; public render(): TemplateResult { return renderChartGauge(this); } public async updated(changedProperties: Map) { super.updated(changedProperties); if ( this.chartInstance && (changedProperties.has('value') || changedProperties.has('min') || changedProperties.has('max') || changedProperties.has('unit') || changedProperties.has('thresholds') || changedProperties.has('showTicks')) ) { this.updateChart(); } } protected buildOption(): Record { const isDark = !this.goBright; const seriesColors = getEchartsSeriesColors(this.goBright); const primaryColor = seriesColors[0]; // Build axis line color stops from thresholds let axisLineColors: Array<[number, string]>; if (this.thresholds.length > 0) { const sorted = [...this.thresholds].sort((a, b) => a.value - b.value); axisLineColors = sorted.map((t) => [ (t.value - this.min) / (this.max - this.min), t.color, ]); // Ensure we end at 1 if (axisLineColors[axisLineColors.length - 1][0] < 1) { axisLineColors.push([1, sorted[sorted.length - 1].color]); } } else { axisLineColors = [[1, primaryColor]]; } return { series: [ { type: 'gauge', min: this.min, max: this.max, startAngle: 220, endAngle: -40, progress: { show: true, width: 14, roundCap: true, }, pointer: { show: true, length: '60%', width: 5, itemStyle: { color: 'auto', }, }, axisLine: { lineStyle: { width: 14, color: axisLineColors, opacity: 0.3, }, }, axisTick: { show: this.showTicks, distance: -20, length: 6, lineStyle: { color: isDark ? 'hsl(0 0% 30%)' : 'hsl(0 0% 75%)', width: 1, }, }, splitLine: { show: this.showTicks, distance: -24, length: 10, lineStyle: { color: isDark ? 'hsl(0 0% 40%)' : 'hsl(0 0% 60%)', width: 2, }, }, axisLabel: { show: this.showTicks, distance: 30, color: isDark ? 'hsl(0 0% 50%)' : 'hsl(0 0% 45%)', fontSize: 11, }, detail: { valueAnimation: true, fontSize: 28, fontWeight: 600, offsetCenter: [0, '65%'], color: isDark ? 'hsl(0 0% 90%)' : 'hsl(0 0% 15%)', formatter: `{value}${this.unit}`, }, title: { show: false, }, data: [ { value: this.value, }, ], }, ], }; } }