lowcoder-map-component 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +37 -0
  2. package/icons/demo-icon.svg +10 -0
  3. package/icons/hills.svg +17 -0
  4. package/index.css +27 -0
  5. package/index.html +35 -0
  6. package/index.tsx +20 -0
  7. package/loader.mjs +11 -0
  8. package/package.json +175 -0
  9. package/src/README.md +35 -0
  10. package/src/components/ChartPropertyView.tsx +961 -0
  11. package/src/components/SeriesComp.tsx +368 -0
  12. package/src/components/TabPropertyView.tsx +127 -0
  13. package/src/comps/Barcharts/comp.tsx +338 -0
  14. package/src/comps/Barcharts/constants.tsx +77 -0
  15. package/src/comps/Linecharts/comp.tsx +350 -0
  16. package/src/comps/Linecharts/constants.tsx +53 -0
  17. package/src/comps/Linechartsv2/comp.tsx +350 -0
  18. package/src/comps/Linechartsv2/constants.tsx +68 -0
  19. package/src/comps/Mapcharts/comp.tsx +381 -0
  20. package/src/comps/Mapcharts/constants.tsx +312 -0
  21. package/src/comps/Mapchartsv2/comp.tsx +393 -0
  22. package/src/comps/Mapchartsv2/constants.tsx +340 -0
  23. package/src/comps/MixedLineBarCharts/comp.tsx +353 -0
  24. package/src/comps/MixedLineBarCharts/constants.tsx +60 -0
  25. package/src/comps/MultiLineCharts/comp.tsx +362 -0
  26. package/src/comps/MultiLineCharts/constants.tsx +96 -0
  27. package/src/comps/PercentageCharts/comp.tsx +359 -0
  28. package/src/comps/PercentageCharts/constants.tsx +98 -0
  29. package/src/comps/Piecharts/comp.tsx +334 -0
  30. package/src/comps/Piecharts/constants.tsx +48 -0
  31. package/src/comps/Tablecharts/comp.tsx +429 -0
  32. package/src/comps/Tablecharts/constants.tsx +97 -0
  33. package/src/comps/Totalcharts/comp.tsx +463 -0
  34. package/src/comps/Totalcharts/constants.tsx +66 -0
  35. package/src/comps/TwoLineCharts/comp.tsx +350 -0
  36. package/src/comps/TwoLineCharts/constants.tsx +82 -0
  37. package/src/comps/mapComponent/comp.tsx +338 -0
  38. package/src/comps/mapComponent/constants.tsx +2149 -0
  39. package/src/comps/tab/comp.tsx +283 -0
  40. package/src/comps/tab/constants.tsx +79 -0
  41. package/src/configs/barChartConfig.tsx +153 -0
  42. package/src/configs/baseConfig.tsx +66 -0
  43. package/src/configs/candleStickChartConfig.tsx +35 -0
  44. package/src/configs/cartesianAxisConfig.tsx +314 -0
  45. package/src/configs/chartUrls.tsx +9 -0
  46. package/src/configs/echartConfig.tsx +260 -0
  47. package/src/configs/echartsLabelConfig.tsx +47 -0
  48. package/src/configs/echartsLegendConfig.tsx +29 -0
  49. package/src/configs/echartsTitleConfig.tsx +49 -0
  50. package/src/configs/echartsTitleVerticalConfig.tsx +50 -0
  51. package/src/configs/funnelChartConfig.tsx +35 -0
  52. package/src/configs/gaugeChartConfig.tsx +31 -0
  53. package/src/configs/graphChartConfig.tsx +31 -0
  54. package/src/configs/heatmapChartConfig.tsx +31 -0
  55. package/src/configs/legendConfig.tsx +55 -0
  56. package/src/configs/lineChartConfig.tsx +246 -0
  57. package/src/configs/lineChartConfigv2.tsx +246 -0
  58. package/src/configs/mapChartConfig.tsx +106 -0
  59. package/src/configs/mapChartConfigv2.tsx +106 -0
  60. package/src/configs/mixedChartConfig.tsx +21 -0
  61. package/src/configs/pieChartConfig.tsx +156 -0
  62. package/src/configs/radarChartConfig.tsx +31 -0
  63. package/src/configs/sankeyChartConfig.tsx +35 -0
  64. package/src/configs/scatterChartConfig.tsx +152 -0
  65. package/src/configs/sunburstChartConfig.tsx +31 -0
  66. package/src/configs/tabConfig.tsx +0 -0
  67. package/src/configs/tableChartConfig.tsx +81 -0
  68. package/src/configs/themeriverChartConfig.tsx +31 -0
  69. package/src/configs/totalChartConfig.tsx +670 -0
  70. package/src/configs/treeChartConfig.tsx +31 -0
  71. package/src/configs/treemapChartConfig.tsx +31 -0
  72. package/src/controls/AnimationsControls.tsx +3 -0
  73. package/src/controls/AutoHeightControl.tsx +2 -0
  74. package/src/controls/AxisControls.tsx +146 -0
  75. package/src/controls/AxisVisibilityControl.tsx +14 -0
  76. package/src/controls/ChartTypeControl.tsx +15 -0
  77. package/src/controls/ColorScaleControl.tsx +221 -0
  78. package/src/controls/ColumnControl.tsx +204 -0
  79. package/src/controls/ConfigControl.tsx +37 -0
  80. package/src/controls/DirectionControls.tsx +20 -0
  81. package/src/controls/IconControl.tsx +88 -0
  82. package/src/controls/LegendControl.tsx +8 -0
  83. package/src/controls/RowLimitControl.tsx +91 -0
  84. package/src/controls/StyleControls.tsx +22 -0
  85. package/src/controls/TimeControls.tsx +41 -0
  86. package/src/controls/TrendlineControl.tsx +89 -0
  87. package/src/controls/UIEventControl.tsx +21 -0
  88. package/src/controls/index.ts +16 -0
  89. package/src/controls/radioControl.tsx +88 -0
  90. package/src/exposing/index.ts +3 -0
  91. package/src/exposing/setPoint.ts +19 -0
  92. package/src/geo/vn.geo.json +369897 -0
  93. package/src/geo/world.geo.json +32127 -0
  94. package/src/i18n/comps/index.tsx +39 -0
  95. package/src/i18n/comps/locales/en.ts +558 -0
  96. package/src/i18n/comps/locales/enObj.tsx +7186 -0
  97. package/src/i18n/comps/locales/index.ts +7 -0
  98. package/src/i18n/comps/locales/pt.ts +37 -0
  99. package/src/i18n/comps/locales/ptObj.tsx +40 -0
  100. package/src/i18n/comps/locales/types.tsx +622 -0
  101. package/src/i18n/comps/locales/zh.ts +3 -0
  102. package/src/i18n/comps/locales/zhObj.tsx +4 -0
  103. package/src/index.ts +31 -0
  104. package/src/types/global.d.ts +9 -0
  105. package/src/types/lowcoder-sdk.d.ts +578 -0
  106. package/src/utils/chartStyle.util.ts +121 -0
  107. package/src/utils/columnExtractor.util.ts +41 -0
  108. package/src/utils/dataTransform.util.ts +37 -0
  109. package/src/utils/deepEqual.util.ts +29 -0
  110. package/src/utils/echarts.util.tsx +822 -0
  111. package/src/utils/getDataKey.util.ts +115 -0
  112. package/src/utils/getLinearRegression.util.ts +46 -0
  113. package/src/utils/googleMaps.util.ts +28 -0
  114. package/src/utils/isEmpty.util.ts +10 -0
  115. package/src/utils/move.util.ts +6 -0
  116. package/src/utils/selection.util.ts +73 -0
  117. package/src/utils/style.util.ts +315 -0
  118. package/src/utils/time.util.ts +221 -0
  119. package/src/utils/timeFormatter.util.ts +104 -0
  120. package/src/utils/timeProcessing.util.ts +38 -0
  121. package/src/utils/trendline.util.ts +342 -0
  122. package/tsconfig.json +25 -0
  123. package/vite.config.js +19 -0
@@ -0,0 +1,822 @@
1
+ import { createSeriesListComp } from "@/components/SeriesComp";
2
+ import {
3
+ NonUIChartDataType,
4
+ UIChartDataType,
5
+ } from "@/comps/Linecharts/constants";
6
+ import { calcXYConfig } from "@/configs/cartesianAxisConfig";
7
+ import {
8
+ calculateChartRealSize,
9
+ getPolarConfig,
10
+ getSeriesConfig,
11
+ } from "@/configs/echartConfig";
12
+ import { EchartsLabelConfig } from "@/configs/echartsLabelConfig";
13
+ import { EchartsLegendConfig } from "@/configs/echartsLegendConfig";
14
+ import { EchartsTitleConfig } from "@/configs/echartsTitleConfig";
15
+ import { EchartsTitleVerticalConfig } from "@/configs/echartsTitleVerticalConfig";
16
+ import { LegendConfig } from "@/configs/legendConfig";
17
+ import {
18
+ applyRowLimit,
19
+ CharOptionCompType,
20
+ EchartsOptionComp,
21
+ EndTimeControl,
22
+ RowLimitConfig,
23
+ ShowAxisControl,
24
+ ShowXAxisControl,
25
+ ShowYAxisControl,
26
+ StartTimeControl,
27
+ TimeGranularityControl,
28
+ TimeRangeControl,
29
+ UIEventOptions,
30
+ XAxisConfig,
31
+ XAxisDirectionOptions,
32
+ YAxisConfig,
33
+ } from "@/controls";
34
+ import { i18nObjs, trans } from "@/i18n/comps";
35
+ import { EChartsOption } from "echarts-for-react";
36
+ import {
37
+ BoolControl,
38
+ clickEvent,
39
+ ColorControl,
40
+ dropdownControl,
41
+ EchartDefaultChartStyle,
42
+ EchartDefaultTextStyle,
43
+ eventHandlerControl,
44
+ jsonControl,
45
+ list,
46
+ MultiCompBuilder,
47
+ NumberControl,
48
+ RecordConstructorToView,
49
+ stateComp,
50
+ StringControl,
51
+ styleControl,
52
+ toArray,
53
+ toJSONObject,
54
+ toJSONObjectArray,
55
+ toObject,
56
+ uiChildren,
57
+ withDefault,
58
+ } from "lowcoder-sdk";
59
+ import { getBaseConfig } from "../configs/baseConfig";
60
+ import { transformData } from "./dataTransform.util";
61
+ import { chartStyleWrapper } from "./style.util";
62
+ import { processTimeData } from "./timeProcessing.util";
63
+ import { calculateTrendline } from "./trendline.util";
64
+
65
+ // ============================================================================
66
+ // TYPES & INTERFACES
67
+ // ============================================================================
68
+ export type ChartSize = { w: number; h: number };
69
+
70
+ export type AvailableQueries = {
71
+ [queryName: string]: {
72
+ data: any;
73
+ run: (params?: any) => Promise<any>;
74
+ isLoading: boolean;
75
+ error?: any;
76
+ };
77
+ };
78
+
79
+ export type DataKeys = {
80
+ label: any;
81
+ value: any;
82
+ };
83
+
84
+ export type InitPropsType = RecordConstructorToView<
85
+ typeof chartUiChildrenMap
86
+ > & {
87
+ chartConfig?: any;
88
+ title?: string;
89
+ data?: ReturnType<typeof jsonControl>;
90
+ defaultData?: ReturnType<typeof jsonControl>;
91
+ series?: typeof createSeriesListComp;
92
+ chartType?: string;
93
+ type?: string;
94
+ type2?: string;
95
+ yAxisKey?: string;
96
+ yAxis2Key?: string;
97
+ yAxisName?: string;
98
+ yAxis2Name?: string;
99
+ xAxisStyle?: ReturnType<typeof styleControl>;
100
+ yAxisStyle?: ReturnType<typeof styleControl>;
101
+ yAxis2Style?: ReturnType<typeof styleControl>;
102
+ regionValue?: string;
103
+ regionName?: string;
104
+ value?: string;
105
+ regionMapType?: string;
106
+ borderColor?: string;
107
+ borderWidth?: string;
108
+ areaColor?: any;
109
+ hoverColor?: string;
110
+ sortBy?: string;
111
+ sortOrder?: string;
112
+ zoomLevel?: string;
113
+ width?: string;
114
+ height?: string;
115
+ tooltipItems?: any[];
116
+ columns?: any[];
117
+ showMaxPoint?: boolean;
118
+ dataZoom?: string;
119
+ };
120
+
121
+ export type EChartPropsType = RecordConstructorToView<
122
+ typeof chartUiChildrenMap & InitPropsType
123
+ >;
124
+
125
+ // ============================================================================
126
+ // CONSTANTS
127
+ // ============================================================================
128
+ export const chartModeOptions = [
129
+ {
130
+ label: "ECharts JSON",
131
+ value: "json",
132
+ },
133
+ ] as const;
134
+
135
+ const NOT_AXIS_CHART_SET: Set<CharOptionCompType> = new Set([
136
+ "pie",
137
+ "map",
138
+ "mapv2"
139
+ ] as const);
140
+ const notAxisChartSubtypeSet: Set<string> = new Set(["polar"] as const);
141
+
142
+ // ============================================================================
143
+ // NO DATA CONFIGURATIONS
144
+ // ============================================================================
145
+ export const noDataPieChartConfig: EChartsOption = {
146
+ animation: false,
147
+ tooltip: { show: false },
148
+ legend: {
149
+ formatter: trans("chart.unknown"),
150
+ top: "bottom",
151
+ selectedMode: false,
152
+ },
153
+ color: ["#B8BBCC", "#CED0D9", "#DCDEE6", "#E6E6EB"],
154
+ series: [
155
+ {
156
+ type: "pie",
157
+ radius: "35%",
158
+ center: ["25%", "50%"],
159
+ silent: true,
160
+ label: { show: false },
161
+ data: [
162
+ { name: "1", value: 70 },
163
+ { name: "2", value: 68 },
164
+ { name: "3", value: 48 },
165
+ { name: "4", value: 40 },
166
+ ],
167
+ },
168
+ {
169
+ type: "pie",
170
+ radius: "35%",
171
+ center: ["75%", "50%"],
172
+ silent: true,
173
+ label: { show: false },
174
+ data: [
175
+ { name: "1", value: 70 },
176
+ { name: "2", value: 68 },
177
+ { name: "3", value: 48 },
178
+ { name: "4", value: 40 },
179
+ ],
180
+ },
181
+ ],
182
+ };
183
+
184
+ export const noDataAxisConfig: EChartsOption = {
185
+ animation: false,
186
+ xAxis: {
187
+ type: "category",
188
+ name: trans("chart.noData"),
189
+ nameLocation: "middle",
190
+ data: [],
191
+ axisLine: { lineStyle: { color: "#8B8FA3" } },
192
+ },
193
+ yAxis: {
194
+ type: "value",
195
+ axisLabel: { color: "#8B8FA3" },
196
+ splitLine: { lineStyle: { color: "#F0F0F0" } },
197
+ },
198
+ tooltip: { show: false },
199
+ series: [
200
+ {
201
+ data: [700],
202
+ type: "line",
203
+ itemStyle: { opacity: 0 },
204
+ },
205
+ ],
206
+ };
207
+
208
+ // ============================================================================
209
+ // COMPONENT CONFIGURATIONS
210
+ // ============================================================================
211
+ const areaPiecesChildrenMap = {
212
+ color: ColorControl,
213
+ from: StringControl,
214
+ to: StringControl,
215
+ dataIndex: StringControl,
216
+ };
217
+
218
+ const AreaPiecesTmpComp = new MultiCompBuilder(
219
+ areaPiecesChildrenMap,
220
+ (props) => props
221
+ )
222
+ .setPropertyViewFn((children) => (
223
+ <>
224
+ {children.color.propertyView({ label: trans("lineChart.color") })}
225
+ {children.from.propertyView({ label: trans("lineChart.from") })}
226
+ {children.to.propertyView({ label: trans("lineChart.to") })}
227
+ </>
228
+ ))
229
+ .build();
230
+
231
+ export const chartUiModeChildren = {
232
+ animationDuration: withDefault(NumberControl, 1000),
233
+ areaPieces: list(AreaPiecesTmpComp),
234
+ availableQueries: stateComp<Array<AvailableQueries>>([]),
235
+ bottom: withDefault(NumberControl, trans("chart.defaultBottom")),
236
+ chartStyle: styleControl(EchartDefaultChartStyle, "chartStyle"),
237
+ data: jsonControl(toJSONObjectArray, []),
238
+ provinceData: jsonControl(toJSONObjectArray, []),
239
+ defaultStyle: jsonControl(toJSONObject, []),
240
+ dataQueryKey: withDefault(StringControl, "none"),
241
+ dataKeys: stateComp<Array<DataKeys[]>>([]),
242
+ eChartConfig: EchartsOptionComp,
243
+ echartsLabelConfig: EchartsLabelConfig,
244
+ echartsLegendConfig: EchartsLegendConfig,
245
+ echartsOption: jsonControl(toObject, i18nObjs.defaultEchartsJsonOption),
246
+ echartsTitle: withDefault(StringControl, trans("chart.defaultTitle")),
247
+ echartsTitleConfig: EchartsTitleConfig,
248
+ echartsTitleVerticalConfig: EchartsTitleVerticalConfig,
249
+ endTime: EndTimeControl,
250
+ left: withDefault(NumberControl, trans("chart.defaultLeft")),
251
+ legendConfig: LegendConfig,
252
+ legendStyle: styleControl(EchartDefaultTextStyle, "legendStyle"),
253
+ legendVisibility: withDefault(BoolControl, true),
254
+ mode: dropdownControl(chartModeOptions, "ui"),
255
+ onUIEvent: eventHandlerControl(UIEventOptions),
256
+ right: withDefault(NumberControl, trans("chart.defaultRight")),
257
+ rowLimitConfig: RowLimitConfig,
258
+ showAxis: ShowAxisControl,
259
+ showXAxis: ShowXAxisControl,
260
+ showYAxis: ShowYAxisControl,
261
+ startTime: StartTimeControl,
262
+ timeColumn: StringControl,
263
+ timeFormat: withDefault(StringControl, "DD-MM-YYYY HH:mm"),
264
+ timeGranularity: TimeGranularityControl,
265
+ timeRange: TimeRangeControl,
266
+ titleStyle: styleControl(EchartDefaultTextStyle, "titleStyle"),
267
+ tooltip: withDefault(BoolControl, true),
268
+ top: withDefault(NumberControl, trans("chart.defaultTop")),
269
+ xAxisData: jsonControl(toArray, []),
270
+ xAxisDirection: dropdownControl(XAxisDirectionOptions, "horizontal"),
271
+ xAxisKey: StringControl,
272
+ xConfig: XAxisConfig,
273
+ yConfig: YAxisConfig,
274
+ };
275
+
276
+ export const echartProps = {
277
+ lastInteractionData: stateComp<Array<UIChartDataType> | NonUIChartDataType>(
278
+ []
279
+ ),
280
+ selectedPoints: stateComp<Array<UIChartDataType>>([]),
281
+ onEvent: eventHandlerControl([clickEvent] as const),
282
+ ...chartUiModeChildren,
283
+ };
284
+
285
+ const chartUiChildrenMap = uiChildren(echartProps);
286
+
287
+ // ============================================================================
288
+ // UTILITY FUNCTIONS
289
+ // ============================================================================
290
+ export function isAxisChart(
291
+ type: CharOptionCompType,
292
+ subtype: string
293
+ ): boolean {
294
+ return !NOT_AXIS_CHART_SET.has(type) && !notAxisChartSubtypeSet.has(subtype);
295
+ }
296
+
297
+ // ============================================================================
298
+ // DATA PROCESSING FUNCTIONS
299
+ // ============================================================================
300
+ function extractValueKeys(data: any[]): string[] {
301
+ if (!data?.length) return [];
302
+ const keys = Object.keys(data[0]);
303
+ return keys.filter((key) => key !== "date");
304
+ }
305
+
306
+ function getSeriesColumnNames(
307
+ chartType: string,
308
+ series: any[],
309
+ valueKeys: string[]
310
+ ): string[] {
311
+ if (chartType === "total") return valueKeys;
312
+
313
+ return series
314
+ .filter((s: any) => !s.getView().hide)
315
+ .map((s: any) => s.getView().columnName);
316
+ }
317
+
318
+ function processChartData(
319
+ props: EChartPropsType,
320
+ data: any[],
321
+ seriesColumnNames: string[]
322
+ ): any[] {
323
+ const { timeColumn, xAxisKey, yConfig, rowLimitConfig, sortBy, sortOrder } =
324
+ props;
325
+
326
+ // Time processing
327
+ const hasValidTime =
328
+ timeColumn && data.some((d: any) => d[timeColumn] !== undefined);
329
+ let transformedData = hasValidTime
330
+ ? processTimeData(
331
+ { ...props, timeFormat: props.timeFormat },
332
+ data,
333
+ seriesColumnNames
334
+ )
335
+ : data;
336
+
337
+ // Data transformation
338
+ const shouldTransform = !["category", "time", "value"].includes(yConfig.type);
339
+ transformedData = shouldTransform
340
+ ? transformData(transformedData, xAxisKey, seriesColumnNames)
341
+ : applyRowLimit(transformedData, rowLimitConfig.rowLimit);
342
+
343
+ // Sorting
344
+ if (sortBy) {
345
+ transformedData = [...transformedData].sort((a, b) => {
346
+ const va = a[sortBy] ?? 0;
347
+ const vb = b[sortBy] ?? 0;
348
+ return sortOrder === "asc" ? va - vb : vb - va;
349
+ });
350
+ }
351
+
352
+ return transformedData;
353
+ }
354
+
355
+ // ============================================================================
356
+ // SERIES GENERATION
357
+ // ============================================================================
358
+ export function generateSeries(chartData: number[], props: EChartPropsType) {
359
+ const { chartConfig } = props;
360
+ if (!chartData?.length) return [];
361
+
362
+ const valueKeys = extractValueKeys(chartData);
363
+
364
+ return valueKeys.map((key) => ({
365
+ ...chartConfig,
366
+ type: "line",
367
+ columnName: key,
368
+ data: chartData.map((item: any) => item[key]),
369
+ }));
370
+ }
371
+
372
+ // ============================================================================
373
+ // MAP CHART CONFIGURATION
374
+ // ============================================================================
375
+ function configureMapChart(
376
+ config: EChartsOption,
377
+ props: EChartsOption,
378
+ transformedData: any[]
379
+ ): EChartsOption {
380
+ const { chartConfig, series, regionValue, zoomLevel } = props;
381
+ const { scaleType, minColor, midColor, maxColor, colorRanges } =
382
+ chartConfig.colorScale;
383
+ const { mapType } = chartConfig;
384
+
385
+ // Parse zoom level
386
+ let zoom = 1;
387
+ if (zoomLevel) {
388
+ if (String(zoomLevel).endsWith("%")) {
389
+ zoom = parseFloat(String(zoomLevel)) / 100;
390
+ } else {
391
+ zoom = parseFloat(String(zoomLevel));
392
+ }
393
+ }
394
+
395
+ const mapSeries = getSeriesConfig(props)
396
+ .filter((s: any) => s.columnName === regionValue)
397
+ .map((s: any) => ({
398
+ ...s,
399
+ type: "map",
400
+ mapType: mapType || "vietnam",
401
+ width: props.width || "auto",
402
+ height: props.height || "auto",
403
+ center: ["50%", "50%"],
404
+ zoom: isNaN(zoom) ? 1 : zoom,
405
+ roam: true, // Enable user interaction to zoom/pan
406
+ data: transformedData.map((item: any) => ({
407
+ ...item,
408
+ name: item.name || "",
409
+ value: item[regionValue] || 0,
410
+ })),
411
+ itemStyle: {
412
+ areaColor: "#eee",
413
+ borderColor: "#fff",
414
+ borderWidth: 1,
415
+ },
416
+ emphasis: {
417
+ itemStyle: { areaColor: "#ff7f50" },
418
+ },
419
+ }));
420
+
421
+ const color =
422
+ scaleType === "diverging"
423
+ ? [minColor, midColor, maxColor]
424
+ : scaleType === "categorical"
425
+ ? colorRanges.map((i: any) => i.getView().color)
426
+ : [minColor, maxColor];
427
+
428
+ const visualMapConfig =
429
+ transformedData.length > 0 && series.length > 0
430
+ ? {
431
+ show: true,
432
+ min: Math.min(...transformedData.map((v: any) => v[regionValue])),
433
+ max: Math.max(...transformedData.map((v: any) => v[regionValue])),
434
+ left: "left",
435
+ bottom: "bottom",
436
+ inRange: {
437
+ color: color.some((i: any) => i !== "")
438
+ ? color
439
+ : ["#C6EBFF", "#2875B8"],
440
+ },
441
+ }
442
+ : undefined;
443
+
444
+ const tooltipItems = props.tooltipItems?.length ? props.tooltipItems : [];
445
+
446
+ return {
447
+ ...config,
448
+ series: mapSeries,
449
+ tooltip: {
450
+ trigger: "item",
451
+ formatter: (params: any) => {
452
+ const d = params.data || {};
453
+ let content = `<p style="font-weight:bold; margin-bottom:5px">${params.name}</p>`;
454
+
455
+ if (tooltipItems.length > 0) {
456
+ tooltipItems.forEach((item: any) => {
457
+ const view = item.getView();
458
+ if (view.key) {
459
+ content += `${view.label || view.key}: <b>${d[view.key] ?? "-"}</b><br/>`;
460
+ }
461
+ });
462
+ } else {
463
+ content += `${regionValue}: <b>${d.value ?? 0}</b>`;
464
+ }
465
+ return content;
466
+ },
467
+ },
468
+ visualMap: visualMapConfig,
469
+ };
470
+ }
471
+
472
+ // ============================================================================
473
+ // AXIS CHART CONFIGURATION
474
+ // ============================================================================
475
+ function configureAxisChart(
476
+ config: EChartsOption,
477
+ props: EChartPropsType,
478
+ transformedData: any[],
479
+ chartSize?: ChartSize,
480
+ isPolar?: boolean
481
+ ): EChartsOption {
482
+ const {
483
+ xConfig,
484
+ yConfig,
485
+ xAxisDirection,
486
+ xAxisKey,
487
+ timeColumn,
488
+ showAxis,
489
+ showXAxis,
490
+ showYAxis,
491
+ } = props;
492
+
493
+ const chartRealSize = chartSize
494
+ ? calculateChartRealSize(chartSize, config.grid)
495
+ : undefined;
496
+
497
+ const finalXY = calcXYConfig(
498
+ xConfig,
499
+ yConfig,
500
+ xAxisDirection,
501
+ transformedData.map((d: any) => d[xAxisKey]),
502
+ chartRealSize
503
+ );
504
+
505
+ const isHide = isPolar ? false : showAxis !== "hide";
506
+ const xAxisType =
507
+ timeColumn && xAxisKey === timeColumn ? "category" : finalXY.xConfig.type;
508
+
509
+ return {
510
+ ...config,
511
+ xAxis: {
512
+ ...finalXY.xConfig,
513
+ type: xAxisType,
514
+ axisLabel: props?.xAxisStyle,
515
+ data:
516
+ xAxisType === "category" && props.xAxisData.length > 0
517
+ ? props.xAxisData
518
+ : transformedData.map((i: any) => i[xAxisKey]),
519
+ show: showXAxis ? !showXAxis : isHide,
520
+ },
521
+ yAxis: {
522
+ ...finalXY.yConfig,
523
+ axisLabel: props?.yAxisStyle,
524
+ show: showYAxis ? !showYAxis : isHide,
525
+ },
526
+ };
527
+ }
528
+ // ============================================================================
529
+ // MIXED CHART CONFIGURATION
530
+ // ============================================================================
531
+ function configureMixedChart(
532
+ config: EChartsOption,
533
+ props: EChartPropsType
534
+ ): EChartsOption {
535
+ const {
536
+ type,
537
+ type2,
538
+ yAxisKey,
539
+ yAxis2Key,
540
+ yAxisName,
541
+ yAxis2Name,
542
+ yAxisStyle,
543
+ yAxis2Style,
544
+ series,
545
+ } = props;
546
+
547
+ const yAxisConfig = [
548
+ {
549
+ type: "value",
550
+ name: yAxisName || "",
551
+ alignTicks: true,
552
+ axisLine: {
553
+ show: true,
554
+ lineStyle: yAxisStyle || {},
555
+ },
556
+ axisLabel: {
557
+ formatter: "{value}",
558
+ ...yAxisStyle,
559
+ },
560
+ },
561
+ {
562
+ type: "value",
563
+ name: yAxis2Name || "",
564
+ alignTicks: true,
565
+ axisLine: {
566
+ show: true,
567
+ lineStyle: yAxis2Style || {},
568
+ },
569
+ axisLabel: {
570
+ formatter: "{value}",
571
+ ...yAxis2Style,
572
+ },
573
+ },
574
+ ];
575
+
576
+ const updatedSeries = config.series?.map((seriesItem: any, index: number) => {
577
+ const seriesProps = series?.[index];
578
+
579
+ if (!seriesProps) return seriesItem;
580
+
581
+ const seriesView = seriesProps.getView();
582
+
583
+ const yAxisIndex =
584
+ seriesView?.yAxisIndex !== undefined
585
+ ? seriesView.yAxisIndex
586
+ : index === 0
587
+ ? 0
588
+ : 1;
589
+
590
+ const name =
591
+ seriesView?.seriesName ||
592
+ (index === 0 ? yAxisKey : yAxis2Key) ||
593
+ seriesItem.name;
594
+ const columnName =
595
+ seriesView?.columnName ||
596
+ (index === 0 ? yAxisKey : yAxis2Key) ||
597
+ seriesItem.columnName;
598
+
599
+ return {
600
+ ...seriesItem,
601
+ type: index === 0 ? type : type2 || seriesView?.chartType,
602
+ yAxisIndex: yAxisIndex,
603
+ name: name,
604
+ columnName: columnName,
605
+ smooth:
606
+ seriesView?.smooth !== undefined
607
+ ? seriesView.smooth
608
+ : seriesItem.smooth,
609
+ itemStyle: {
610
+ ...(seriesItem.itemStyle || {}),
611
+ ...(seriesProps.itemStyle || {}),
612
+ },
613
+ lineStyle: {
614
+ ...(seriesItem.lineStyle || {}),
615
+ ...(seriesProps.lineStyle || {}),
616
+ },
617
+ label: {
618
+ ...(seriesItem.label || {}),
619
+ ...(seriesProps.label || {}),
620
+ },
621
+ animation: true,
622
+ };
623
+ });
624
+
625
+ return {
626
+ ...config,
627
+ yAxis: yAxisConfig,
628
+ series: updatedSeries,
629
+ };
630
+ }
631
+ // ============================================================================
632
+ // TRENDLINE CONFIGURATION
633
+ // ============================================================================
634
+ function addTrendline(
635
+ config: EChartsOption,
636
+ props: EChartPropsType,
637
+ data: any[],
638
+ series: any[]
639
+ ): EChartsOption {
640
+ const { chartConfig } = props;
641
+
642
+ if (!chartConfig.showTrendline || series.length <= 1) return config;
643
+
644
+ const trendlineCf = chartConfig.trendlines;
645
+ const trendlineSeries = calculateTrendline(
646
+ data,
647
+ trendlineCf,
648
+ series?.[1]?.children?.columnName?.unevaledValue,
649
+ series?.[0]?.children?.columnName?.unevaledValue
650
+ );
651
+
652
+ if (!trendlineSeries.length) return config;
653
+
654
+ const trendlineConfig = {
655
+ ...config.series[0],
656
+ name: trendlineCf.name || "Trend",
657
+ columnName: trendlineCf.name || "Trend",
658
+ type: "line",
659
+ data: trendlineSeries,
660
+ smooth: false,
661
+ lineStyle: {
662
+ type: "dashed",
663
+ width: parseInt(config.lineWidth || "1"),
664
+ color: trendlineCf.color,
665
+ borderColor: "inherit",
666
+ },
667
+ silent: true,
668
+ symbolSize: chartConfig.symbolSize,
669
+ };
670
+
671
+ return {
672
+ ...config,
673
+ series: [...config.series, trendlineConfig],
674
+ };
675
+ }
676
+
677
+ // ============================================================================
678
+ // MAIN CONFIGURATION FUNCTION
679
+ // ============================================================================
680
+ export function getEChartConfig(
681
+ props: EChartsOption,
682
+ chartSize?: ChartSize,
683
+ theme?: any
684
+ ): EChartsOption | undefined {
685
+ const { chartConfig, chartType, data, series, chartStyle } = props;
686
+
687
+ // Early return for no data
688
+ const axisChart = isAxisChart(chartType, chartConfig?.polarData?.polar);
689
+ const defaultConfig = getBaseConfig(props, chartType);
690
+
691
+ if (!data?.length) {
692
+ return {
693
+ ...defaultConfig,
694
+ ...(["map", "mapv2"].includes(chartType)
695
+ ? noDataPieChartConfig
696
+ : noDataAxisConfig),
697
+ };
698
+ }
699
+
700
+ // Extract data keys
701
+ const valueKeys = extractValueKeys(data);
702
+ const seriesColumnNames = getSeriesColumnNames(chartType, series, valueKeys);
703
+
704
+ // Process data
705
+ const transformedData = processChartData(props, data, seriesColumnNames);
706
+
707
+ // Base configuration
708
+ const isPolar = chartConfig?.polarData?.polar;
709
+ let config: EChartsOption = {
710
+ ...defaultConfig,
711
+ ...(isPolar ? getPolarConfig(props) : {}),
712
+ backgroundColor: !chartStyle.background
713
+ ? defaultConfig.backgroundColor
714
+ : chartStyle.background,
715
+ };
716
+
717
+ if (["map", "mapv2"].includes(chartType)) {
718
+ config = configureMapChart(config, props, transformedData);
719
+ } else if (chartType === "pie") {
720
+ const { xAxisKey } = props;
721
+
722
+ config = {
723
+ ...config,
724
+ tooltip: {
725
+ trigger: "item",
726
+ },
727
+ series: getSeriesConfig(props).map((s: any) => ({
728
+ ...s,
729
+ data: transformedData.map((row: any) => ({
730
+ name: row[xAxisKey],
731
+ value: row[s.columnName],
732
+ })),
733
+ encode: {
734
+ itemName: xAxisKey,
735
+ value: s.columnName,
736
+ },
737
+ })),
738
+ };
739
+ } else if (chartType === "mixed") {
740
+ const seriesConfig = getSeriesConfig(props);
741
+
742
+ config = {
743
+ ...config,
744
+ dataset: [{ source: transformedData, sourceHeader: false }],
745
+ dataZoom: props.rowLimitConfig.dataZoom,
746
+ series: seriesConfig.map((s: any) => ({
747
+ ...s,
748
+ encode: { ...s.encode, y: s.columnName },
749
+ lineStyle: chartStyleWrapper(props?.chartStyle, theme?.chartStyle),
750
+ data: transformedData.map((row: any) => row[s.columnName]),
751
+ })),
752
+ };
753
+
754
+ // Add axis configuration
755
+ if (axisChart) {
756
+ config = configureAxisChart(
757
+ config,
758
+ props,
759
+ transformedData,
760
+ chartSize,
761
+ isPolar
762
+ );
763
+ }
764
+
765
+ config = configureMixedChart(config, props);
766
+ } else {
767
+ // Regular chart
768
+ const seriesConfig = getSeriesConfig(props);
769
+
770
+ config = {
771
+ ...config,
772
+ dataset: [{ source: transformedData, sourceHeader: false }],
773
+ dataZoom:
774
+ props.zoomLevel === "1"
775
+ ? [
776
+ {
777
+ type: "slider",
778
+ show: true,
779
+ xAxisIndex: [0],
780
+ start: 0,
781
+ end: 100,
782
+ bottom: 10,
783
+ },
784
+ {
785
+ type: "inside",
786
+ xAxisIndex: [0],
787
+ start: 0,
788
+ end: 100,
789
+ },
790
+ ]
791
+ : props.rowLimitConfig.dataZoom,
792
+ series: seriesConfig.map((s: any) => ({
793
+ ...s,
794
+ encode: { ...s.encode, y: s.columnName },
795
+ lineStyle: chartStyleWrapper(props?.chartStyle, theme?.chartStyle),
796
+ data: transformedData.map((row: any) => row[s.columnName]),
797
+ })),
798
+ };
799
+
800
+ // Add axis configuration for axis charts
801
+ if (axisChart) {
802
+ config = configureAxisChart(
803
+ config,
804
+ props,
805
+ transformedData,
806
+ chartSize,
807
+ isPolar
808
+ );
809
+ }
810
+
811
+ // Add trendline if enabled
812
+ config = addTrendline(config, props, data, series);
813
+
814
+ // Handle total chart type
815
+ if (chartType === "total") {
816
+ config.series = generateSeries(transformedData, props);
817
+ }
818
+ }
819
+ console.log({ series: config.series });
820
+
821
+ return config;
822
+ }