11<template >
2- <div ref =" chart" ></div >
2+ <div class = " -mb-2 " ref =" chart" ></div >
33</template >
44
55<script setup lang="ts">
@@ -10,122 +10,132 @@ const chart: Ref<HTMLDivElement | null> = ref(null);
1010
1111const props = defineProps <{
1212 data: {
13- x: string ,
13+ label: string ,
14+ amount: number ,
15+ color? : string ,
1416 [key : string ]: any ,
1517 }[],
16- series: {
17- name: string ,
18- fieldName: string ,
19- color: string ,
20- }[],
21- options: ApexOptions ,
18+ options? : ApexOptions ,
2219}>();
2320
21+ const SUGGESTED_COLORS = [
22+ " #4E79A7" , " #F28E2B" , " #E15759" , " #76B7B2" , " #59A14F" , " #EDC949" , " #B07AA1" , " #FF9DA6" , " #9C755F" , " #BAB0AC" ,
23+ " #2B8A86" , " #CC4D58" , " #F7941D" , " #F9C232" , " #729B33" , " #497288" , " #16578D" , " #5F4D99" , " #F9F871" , " #F9F871" ,
24+ ];
25+
26+
27+ // [ "#2B8A86", "#CC4D58", "#F7941D", "#F9C232", "#729B33", "#497288", "#16578D", "#5F4D99",]
28+ // ["#4E79A7", "#F28E2B", "#E15759", "#76B7B2", "#59A14F"], // Professional Cool Tones
29+ // ["#1F77B4", "#FF7F0E", "#2CA02C", "#D62728", "#9467BD"], // Balanced Vibrant Colors
30+ // ["#6A4C93", "#1982C4", "#8AC926", "#FF595E", "#FFCA3A"], // Bold and Distinct
31+ // ["#0077B6", "#0096C7", "#00B4D8", "#90E0EF", "#CAF0F8"], // Ocean Blues
32+ // ["#3A0CA3", "#7209B7", "#F72585", "#4361EE", "#4CC9F0"], // Vivid Purples and Blues
33+ // ["#FF9F1C", "#FFBF69", "#CBF3F0", "#2EC4B6", "#011627"], // Warm and Cool Mix
34+ // ["#8338EC", "#3A86FF", "#FB5607", "#FF006E", "#FFBE0B"], // Fun and Playful
35+ // ["#F94144", "#F3722C", "#F8961E", "#F9844A", "#F9C74F"], // Warm Gradient
2436
2537
2638const optionsBase = {
27- chart: {
28- sparkline: {
29- enabled: false ,
39+ series: [],
40+ colors: [],
41+ labels: [],
42+ chart: {
43+ height: 400 ,
44+ width: " 100%" ,
45+ type: " donut" ,
3046 },
31- type: " bar" ,
32- width: " 100%" ,
33- height: 150 ,
34- toolbar: {
35- show: false ,
36- }
37- },
38- fill: {
39- opacity: 1 ,
40- },
41- plotOptions: {
42- bar: {
43- horizontal: false ,
44- columnWidth: " 80%" ,
45- borderRadiusApplication: " end" ,
46- borderRadius: 8 ,
47- dataLabels: {
48- position: " top" ,
49- },
47+ stroke: {
48+ colors: [" transparent" ],
49+ lineCap: " " ,
5050 },
51- },
52- legend: {
53- show: false ,
54- position: " bottom" ,
55- },
56- dataLabels: {
57- enabled: false ,
58- },
59- tooltip: {
60- shared: true ,
61- intersect: false ,
62- formatter : function (value ) {
63- return value
51+ plotOptions: {
52+ pie: {
53+ donut: {
54+ labels: {
55+ show: true ,
56+ name: {
57+ show: true ,
58+ fontFamily: " Inter, sans-serif" ,
59+ offsetY: 20 ,
60+ },
61+ total: {
62+ showAlways: true ,
63+ show: false ,
64+ fontFamily: " Inter, sans-serif" ,
65+ label: " " ,
66+ formatter : function (w ) {
67+ const sum = w .globals .seriesTotals .reduce ((a , b ) => {
68+ return a + b
69+ }, 0 )
70+ return sum
71+ },
72+ },
73+ value: {
74+ show: true ,
75+ fontFamily: " Inter, sans-serif" ,
76+ offsetY: - 20 ,
77+ formatter : function (value ) {
78+ return value + " k"
79+ },
80+ },
81+ },
82+ size: " 80%" ,
83+ },
84+ },
6485 },
65- },
66- xaxis: {
67- labels: {
68- show: false ,
69- style: {
70- fontFamily: " Inter, sans-serif" ,
71- cssClass: ' text-xs font-normal fill-gray-500 dark:fill-gray-400'
86+ grid: {
87+ padding: {
88+ top: 3 ,
89+ left: 3 ,
90+ right: 3 ,
91+ bottom: 3 ,
7292 },
73- formatter : function (value ) {
74- return value
75- }
7693 },
77- categories: [],
78- axisTicks: {
79- show: false ,
94+ dataLabels: {
95+ enabled: false ,
8096 },
81- axisBorder: {
82- show: false ,
97+ legend: {
98+ position: " bottom" ,
99+ fontFamily: " Inter, sans-serif" ,
83100 },
84- },
85- yaxis: {
86- labels: {
87- show: false ,
88- style: {
89- fontFamily: " Inter, sans-serif" ,
90- cssClass: ' text-xs font-normal fill-gray-500 dark:fill-gray-400'
91- }
92- }
93- },
94- grid: {
95- show: false ,
96- strokeDashArray: 4 ,
97- padding: {
98- left: 2 ,
99- right: 2 ,
100- // top: -20
101+ yaxis: {
102+ labels: {
103+ formatter : function (value ) {
104+ return value ;
105+ },
106+ },
107+ },
108+ xaxis: {
109+ labels: {
110+ formatter : function (value ) {
111+ return value ;
112+ },
113+ },
114+ axisTicks: {
115+ show: false ,
116+ },
117+ axisBorder: {
118+ show: false ,
119+ },
101120 },
102- },
103121};
104122
105123const options = computed (() => {
106- if (props .data ?.length > 0 ) {
107- props .series .forEach ((s ) => {
108- if (props .data [0 ][s .fieldName ] === undefined ) {
109- throw new Error (` Field ${s .fieldName } not found even in first data point ${JSON .stringify (props .data [0 ])}, something is wrong ` );
110- }
111- });
112- }
124+
113125 const options = {
114126 ... optionsBase ,
115127
116128 // shade and gradient take from first series
117- series: props .series .map ((s ) => ({
118- data: props .data ?.map ((item ) => item [s .fieldName ]) ?? [],
119- ... s ,
120- })),
121- xaxis: {
122- ... optionsBase .xaxis ,
123- categories: props .data ?.map ((item ) => item .x ) ?? [],
124- },
129+ series: props .data ?.map ((item ) => item .amount ) ?? [],
130+ colors: props .data ?.map ((item , index ) => item .color ?? SUGGESTED_COLORS [index ]) ?? [],
131+ labels: props .data ?.map ((item ) => item .label ) ?? [],
125132 };
126133
127134 // for each of ...props.options merge on lowest level. so if { chart: {height : 2} }, it should not replace chart level, only height level
128135 function mergeOptions(options : any , newOptions : any ) {
136+ if (! newOptions ) {
137+ return ;
138+ }
129139 for (const key in newOptions ) {
130140 if (typeof newOptions [key ] === ' object' ) {
131141 if (! options [key ]) {
0 commit comments