1+ <template >
2+ <div ref =" chart" ></div >
3+ </template >
4+
5+ <script setup lang="ts">
6+ import ApexCharts , { type ApexOptions } from ' apexcharts' ;
7+ import { ref , type Ref , watch , computed } from ' vue' ;
8+
9+ const chart: Ref <HTMLDivElement | null > = ref (null );
10+
11+ const props = defineProps <{
12+ data: {
13+ x: string ,
14+ [key : string ]: any ,
15+ }[],
16+ series: {
17+ name: string ,
18+ fieldName: string ,
19+ color: string ,
20+ }[],
21+ options: ApexOptions ,
22+ }>();
23+
24+
25+
26+ const optionsBase = {
27+ chart: {
28+ height: 150 ,
29+ type: " area" ,
30+ fontFamily: " Inter, sans-serif" ,
31+ dropShadow: {
32+ enabled: false ,
33+ },
34+ toolbar: {
35+ show: false ,
36+ },
37+ },
38+ tooltip: {
39+ enabled: true ,
40+ x: {
41+ show: false ,
42+ },
43+ },
44+ fill: {
45+ type: " gradient" ,
46+ gradient: {
47+ opacityFrom: 0.55 ,
48+ opacityTo: 0 ,
49+ shade: " #1C64F2" ,
50+ gradientToColors: [" #1C64F2" ],
51+ },
52+ },
53+ dataLabels: {
54+ enabled: false ,
55+ },
56+ stroke: {
57+ width: 6 ,
58+ },
59+ grid: {
60+ show: false ,
61+ strokeDashArray: 4 ,
62+ padding: {
63+ left: 2 ,
64+ right: 2 ,
65+ top: 0
66+ },
67+ },
68+ series: [],
69+ xaxis: {
70+ categories: [],
71+ labels: {
72+ show: false ,
73+ },
74+ axisBorder: {
75+ show: false ,
76+ },
77+ axisTicks: {
78+ show: false ,
79+ },
80+ },
81+ yaxis: {
82+ show: false ,
83+ },
84+ };
85+
86+ const options = computed (() => {
87+ if (props .data ?.length > 0 ) {
88+ props .series .forEach ((s ) => {
89+ if (props .data [0 ][s .fieldName ] === undefined ) {
90+ throw new Error (` Field ${s .fieldName } not found even in first data point ${JSON .stringify (props .data [0 ])}, something is wrong ` );
91+ }
92+ });
93+ }
94+ const options = {
95+ ... optionsBase ,
96+
97+ // shade and gradient take from first series
98+ fill: {
99+ ... optionsBase .fill ,
100+ gradient: {
101+ ... optionsBase .fill .gradient ,
102+ shade: props .series [0 ].color ,
103+ gradientToColors: [props .series [0 ].color ],
104+ },
105+ },
106+ series: props .series .map ((s ) => ({
107+ data: props .data ?.map ((item ) => item [s .fieldName ]) ?? [],
108+ ... s ,
109+ })),
110+ xaxis: {
111+ ... optionsBase .xaxis ,
112+ categories: props .data ?.map ((item ) => item .x ) ?? [],
113+ },
114+ };
115+
116+ // for each of ...props.options merge on lowest level. so if { chart: {height : 2} }, it should not replace chart level, only height level
117+ function mergeOptions(options : any , newOptions : any ) {
118+ for (const key in newOptions ) {
119+ if (typeof newOptions [key ] === ' object' ) {
120+ if (! options [key ]) {
121+ options [key ] = {};
122+ }
123+ mergeOptions (options [key ], newOptions [key ]);
124+ } else {
125+ options [key ] = newOptions [key ];
126+ }
127+ }
128+ }
129+ mergeOptions (options , props .options );
130+
131+ return options ;
132+ });
133+
134+ let apexChart: ApexCharts ;
135+
136+ watch (() => options .value , (value ) => {
137+ if (apexChart ) {
138+ apexChart .updateOptions (value );
139+ } else {
140+ console .log (' chart.value' , value );
141+ apexChart = new ApexCharts (chart .value , value );
142+ apexChart .render ();
143+ }
144+ });
145+
146+ </script >
0 commit comments