import { customElement, property, type TemplateResult, } from '@design.estate/dees-element'; import { DeesChartEchartsBase } from '../dees-chart-echarts-base.js'; import { demoFunc } from './demo.js'; import { donutStyles } from './styles.js'; import { renderChartDonut } from './template.js'; import { getEchartsSeriesColors, getThemeColors } from '../dees-chart-echarts-theme.js'; export interface IDonutDataItem { name: string; value: number; color?: string; } declare global { interface HTMLElementTagNameMap { 'dees-chart-donut': DeesChartDonut; } } @customElement('dees-chart-donut') export class DeesChartDonut extends DeesChartEchartsBase { public static demo = demoFunc; public static demoGroups = ['Chart']; @property({ type: Array }) accessor data: IDonutDataItem[] = []; @property({ type: Boolean }) accessor showLegend: boolean = true; @property({ type: Boolean }) accessor showLabels: boolean = true; @property({ type: String }) accessor innerRadiusPercent: string = '55%'; @property({ attribute: false }) accessor valueFormatter: (value: number) => string = (val) => `${val}`; public static styles = donutStyles; public render(): TemplateResult { return renderChartDonut(this); } public async updated(changedProperties: Map) { super.updated(changedProperties); if ( this.chartInstance && (changedProperties.has('data') || changedProperties.has('showLegend') || changedProperties.has('showLabels') || changedProperties.has('innerRadiusPercent')) ) { this.updateChart(); } } protected buildOption(): Record { const colors = getThemeColors(this.goBright); const seriesColors = getEchartsSeriesColors(this.goBright); const data = this.data.map((item, index) => ({ name: item.name, value: item.value, itemStyle: item.color ? { color: item.color } : { color: seriesColors[index % seriesColors.length] }, })); const formatter = this.valueFormatter; return { tooltip: { trigger: 'item', formatter: (params: any) => { return `${params.marker} ${params.name}: ${formatter(params.value)} (${params.percent}%)`; }, }, legend: this.showLegend ? { orient: 'vertical', right: 16, top: 'center', itemWidth: 10, itemHeight: 10, itemGap: 12, formatter: (name: string) => { const item = this.data.find((d) => d.name === name); return item ? `${name} ${formatter(item.value)}` : name; }, } : { show: false }, series: [ { type: 'pie', radius: [this.innerRadiusPercent, '85%'], center: this.showLegend ? ['35%', '50%'] : ['50%', '50%'], avoidLabelOverlap: true, itemStyle: { borderRadius: 4, borderColor: 'transparent', borderWidth: 2, }, label: this.showLabels ? { show: true, formatter: '{b}: {d}%', fontSize: 11, color: colors.textSecondary, textBorderColor: 'transparent', } : { show: false }, emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.2)', }, label: { show: true, fontWeight: 'bold', }, }, data, }, ], }; } }