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,381 @@
1
+ import { ChartPropertyView } from "@/components/ChartPropertyView";
2
+ import { getEchartsLocale, trans } from "@/i18n/comps";
3
+ import { formatAllStyles } from "@/utils/chartStyle.util";
4
+ import { ChartSize, echartProps, getEChartConfig } from "@/utils/echarts.util";
5
+ import { getSelectedPoints } from "@/utils/selection.util";
6
+ import { registerMap } from "echarts";
7
+ import ReactECharts from "echarts-for-react";
8
+ import EChartsReactCore from "echarts-for-react/lib/core";
9
+ import {
10
+ changeChildAction,
11
+ chartColorPalette,
12
+ childrenToProps,
13
+ CompAction,
14
+ CompActionTypes,
15
+ depsConfig,
16
+ genRandomKey,
17
+ getPromiseAfterDispatch,
18
+ NameConfig,
19
+ Theme,
20
+ ThemeContext,
21
+ UICompBuilder,
22
+ valueComp,
23
+ withDefault,
24
+ withExposingConfigs,
25
+ withViewFn,
26
+ } from "lowcoder-sdk";
27
+ import { useContext, useEffect, useMemo, useRef, useState } from "react";
28
+ import { useResizeDetector } from "react-resize-detector";
29
+ import { chartUiProps } from "./constants";
30
+
31
+ let clickEventCallback = () => {};
32
+
33
+ let MapChartTmpComp = (function () {
34
+ return new UICompBuilder(
35
+ {
36
+ ...echartProps,
37
+ ...chartUiProps,
38
+ },
39
+ () => null
40
+ )
41
+ .setPropertyViewFn(ChartPropertyView)
42
+ .build();
43
+ })();
44
+
45
+ MapChartTmpComp = withViewFn(MapChartTmpComp, (comp) => {
46
+ const onUIEvent = comp.children.onUIEvent.getView();
47
+ const onEvent = comp.children.onEvent.getView();
48
+ const { mapType, mapUrl } = comp.children.chartConfig.getView();
49
+ const echartsCompRef = useRef<EChartsReactCore | null>();
50
+ const containerRef = useRef<HTMLDivElement>(null);
51
+ const [chartSize, setChartSize] = useState<ChartSize>();
52
+ const firstResize = useRef(true);
53
+ const theme: Theme = useContext(ThemeContext);
54
+ const [mapsRegistered, setMapsRegistered] = useState(false);
55
+ const [customMapLoaded, setCustomMapLoaded] = useState(false);
56
+ const prevMapUrlRef = useRef(null);
57
+ const prevMapType = useRef<any>(null);
58
+
59
+ const defaultChartTheme = {
60
+ color: chartColorPalette,
61
+ backgroundColor: "#fff",
62
+ };
63
+
64
+ let themeConfig = defaultChartTheme;
65
+ try {
66
+ themeConfig = theme?.theme?.chart
67
+ ? JSON.parse(theme.theme.chart)
68
+ : defaultChartTheme;
69
+ } catch (error) {
70
+ console.error("theme chart error: ", error);
71
+ }
72
+
73
+ useEffect(() => {
74
+ const loadMaps = async () => {
75
+ try {
76
+ try {
77
+ const worldMapModule = await import("@/geo/world.geo.json");
78
+ registerMap("world", worldMapModule.default as any);
79
+ } catch (e) {
80
+ console.warn("Failed to load world.json");
81
+ }
82
+ try {
83
+ const worldMapModule = await import("@/geo/vn.geo.json");
84
+ registerMap("vietnam", worldMapModule.default as any);
85
+ } catch (e) {
86
+ console.warn("Failed to load vietnam.json");
87
+ }
88
+
89
+ setMapsRegistered(true);
90
+ } catch (error) {
91
+ console.error("Failed to load maps:", error);
92
+ setMapsRegistered(true);
93
+ }
94
+ };
95
+
96
+ loadMaps();
97
+ }, []);
98
+
99
+ useEffect(() => {
100
+ const loadCustomMap = async () => {
101
+ if (
102
+ mapType !== "custom" ||
103
+ !mapUrl ||
104
+ !mapsRegistered ||
105
+ prevMapUrlRef.current === mapUrl
106
+ ) {
107
+ return;
108
+ }
109
+
110
+ try {
111
+ const response = await fetch(mapUrl);
112
+
113
+ prevMapUrlRef.current = mapUrl;
114
+ if (!response.ok) {
115
+ throw new Error(`Failed to fetch map: ${response.statusText}`);
116
+ }
117
+
118
+ const geoData = await response.json();
119
+
120
+ if (!geoData) throw new Error("Data not found");
121
+
122
+ registerMap("custom", geoData);
123
+ console.log("Custom map loaded and registered successfully");
124
+ setCustomMapLoaded(true);
125
+ } catch (error) {
126
+ console.error("Failed to load custom map:", error);
127
+
128
+ setCustomMapLoaded(false);
129
+ }
130
+ };
131
+ loadCustomMap();
132
+ }, [mapType, mapUrl, mapsRegistered]);
133
+
134
+ const triggerClickEvent = async (dispatch: any, action: CompAction) => {
135
+ await getPromiseAfterDispatch(dispatch, action, {
136
+ autoHandleAfterReduce: true,
137
+ });
138
+ onEvent("click");
139
+ };
140
+
141
+ useEffect(() => {
142
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
143
+ if (!echartsCompInstance) {
144
+ return undefined;
145
+ }
146
+ echartsCompInstance?.on("click", (param: any) => {
147
+ document.dispatchEvent(
148
+ new CustomEvent("clickEvent", {
149
+ bubbles: true,
150
+ detail: {
151
+ action: "click",
152
+ data: param.data,
153
+ },
154
+ })
155
+ );
156
+ triggerClickEvent(
157
+ comp.dispatch,
158
+ changeChildAction("lastInteractionData", param.data, false)
159
+ );
160
+ });
161
+ return () => {
162
+ echartsCompInstance?.off("click");
163
+ document.removeEventListener("clickEvent", clickEventCallback);
164
+ };
165
+ }, []);
166
+
167
+ useEffect(() => {
168
+ const echartsCompInstance = echartsCompRef?.current?.getEchartsInstance();
169
+ if (!echartsCompInstance) {
170
+ return;
171
+ }
172
+ echartsCompInstance?.on("selectchanged", (param: any) => {
173
+ const option: any = echartsCompInstance?.getOption();
174
+ document.dispatchEvent(
175
+ new CustomEvent("clickEvent", {
176
+ bubbles: true,
177
+ detail: {
178
+ action: param.fromAction,
179
+ data: getSelectedPoints(param, option),
180
+ },
181
+ })
182
+ );
183
+
184
+ if (param.fromAction === "select") {
185
+ comp.dispatch(
186
+ changeChildAction(
187
+ "selectedPoints",
188
+ getSelectedPoints(param, option),
189
+ false
190
+ )
191
+ );
192
+ onUIEvent("select");
193
+ } else if (param.fromAction === "unselect") {
194
+ comp.dispatch(
195
+ changeChildAction(
196
+ "selectedPoints",
197
+ getSelectedPoints(param, option),
198
+ false
199
+ )
200
+ );
201
+ onUIEvent("unselect");
202
+ }
203
+
204
+ triggerClickEvent(
205
+ comp.dispatch,
206
+ changeChildAction(
207
+ "lastInteractionData",
208
+ getSelectedPoints(param, option),
209
+ false
210
+ )
211
+ );
212
+ });
213
+ return () => {
214
+ echartsCompInstance?.off("selectchanged");
215
+ document.removeEventListener("clickEvent", clickEventCallback);
216
+ };
217
+ }, [onUIEvent]);
218
+
219
+ const childrenProps = formatAllStyles(childrenToProps(comp.children));
220
+
221
+ const updateSeriesMap = (
222
+ data: any,
223
+ newMapType: string,
224
+ index: number = 0
225
+ ): any => {
226
+ if (!data || !Array.isArray(data.series)) {
227
+ throw new Error("Invalid data format: missing series array");
228
+ }
229
+
230
+ const updatedData = { ...data };
231
+ updatedData.series = [...data.series];
232
+
233
+ if (!updatedData.series[index]) {
234
+ throw new Error(`Series index ${index} does not exist`);
235
+ }
236
+
237
+ updatedData.series[index] = {
238
+ ...updatedData.series[index],
239
+ mapType: newMapType,
240
+ map: newMapType,
241
+ };
242
+
243
+ return updatedData;
244
+ };
245
+
246
+ const option = useMemo(() => {
247
+ if (!mapsRegistered) {
248
+ return {
249
+ title: {
250
+ text: "Loading map...",
251
+ left: "center",
252
+ top: "center",
253
+ },
254
+ };
255
+ }
256
+
257
+ const defaultOption = getEChartConfig(
258
+ childrenProps,
259
+ chartSize,
260
+ themeConfig
261
+ );
262
+ const isFinished = mapType === "custom" && !customMapLoaded;
263
+
264
+ const newOption = updateSeriesMap(
265
+ defaultOption,
266
+ isFinished ? prevMapType.current : mapType
267
+ );
268
+
269
+ if (!isFinished) prevMapType.current = mapType;
270
+
271
+ return newOption;
272
+ }, [
273
+ themeConfig,
274
+ childrenProps,
275
+ chartSize,
276
+ mapsRegistered,
277
+ mapType,
278
+ customMapLoaded,
279
+ ]);
280
+
281
+ useResizeDetector({
282
+ targetRef: containerRef,
283
+ onResize: ({ width, height }) => {
284
+ if (width && height) {
285
+ setChartSize({ w: width, h: height });
286
+ }
287
+ if (!firstResize.current) {
288
+ echartsCompRef.current?.getEchartsInstance().resize();
289
+ } else {
290
+ firstResize.current = false;
291
+ }
292
+ },
293
+ });
294
+
295
+ return (
296
+ <div ref={containerRef} style={{ height: "100%" }}>
297
+ <ReactECharts
298
+ ref={(e) => (echartsCompRef.current = e)}
299
+ style={{ height: "100%" }}
300
+ notMerge
301
+ lazyUpdate
302
+ opts={{
303
+ locale: getEchartsLocale(),
304
+ renderer: "canvas",
305
+ }}
306
+ option={option}
307
+ />
308
+ </div>
309
+ );
310
+ });
311
+
312
+ MapChartTmpComp = class extends MapChartTmpComp {
313
+ updateContext(comp: any) {
314
+ return comp;
315
+ }
316
+
317
+ reduce(action: CompAction): this {
318
+ const comp = super.reduce(action);
319
+ if (action.type === CompActionTypes.UPDATE_NODES_V2) {
320
+ const newData = comp.children.data.getView();
321
+ if (comp.children.data !== this.children.data) {
322
+ setTimeout(() => {
323
+ comp.children.series.dispatchDataChanged(newData);
324
+ }, 0);
325
+ }
326
+ return this.updateContext(comp);
327
+ }
328
+ return comp;
329
+ }
330
+
331
+ autoHeight(): boolean {
332
+ return false;
333
+ }
334
+ };
335
+
336
+ let MapChartComp = withExposingConfigs(MapChartTmpComp, [
337
+ depsConfig({
338
+ name: "selectedPoints",
339
+ desc: trans("chart.selectedPointsDesc"),
340
+ depKeys: ["selectedPoints"],
341
+ func: (input) => {
342
+ return input.selectedPoints;
343
+ },
344
+ }),
345
+ depsConfig({
346
+ name: "lastInteractionData",
347
+ desc: trans("chart.lastInteractionDataDesc"),
348
+ depKeys: ["lastInteractionData"],
349
+ func: (input) => {
350
+ return input.lastInteractionData;
351
+ },
352
+ }),
353
+ depsConfig({
354
+ name: "data",
355
+ desc: trans("chart.dataDesc"),
356
+ depKeys: ["data", "mode"],
357
+ func: (input) => [],
358
+ }),
359
+ new NameConfig("title", trans("chart.titleDesc")),
360
+ ]);
361
+
362
+ export const MapChartCompWithDefault = withDefault(MapChartComp, {
363
+ xAxisKey: valueComp<string>("time"),
364
+ series: [
365
+ {
366
+ dataIndex: genRandomKey(),
367
+ seriesName: "Value",
368
+ columnName: "value",
369
+ },
370
+ {
371
+ dataIndex: genRandomKey(),
372
+ seriesName: "Population",
373
+ columnName: "population",
374
+ },
375
+ {
376
+ dataIndex: genRandomKey(),
377
+ seriesName: "Gdp",
378
+ columnName: "gdp",
379
+ },
380
+ ],
381
+ });
@@ -0,0 +1,312 @@
1
+ import { createSeriesListComp } from "@/components/SeriesComp";
2
+ import { RegionMapTypeOptions } from "@/configs/mapChartConfig";
3
+ import {
4
+ ChartOptionMap,
5
+ EndTimeControl,
6
+ RowLimitConfig,
7
+ StartTimeControl,
8
+ TimeGranularityControl,
9
+ TimeRangeControl,
10
+ } from "@/controls";
11
+ import { trans } from "@/i18n/comps";
12
+ import {
13
+ dropdownControl,
14
+ EchartDefaultTextStyle,
15
+ jsonControl,
16
+ RecordConstructorToView,
17
+ StringControl,
18
+ styleControl,
19
+ toJSONObjectArray,
20
+ uiChildren,
21
+ withDefault,
22
+ withType,
23
+ } from "lowcoder-sdk";
24
+
25
+ const defaultChartData = [
26
+ {
27
+ name: "Thành phố Hà Nội",
28
+ value: 120,
29
+ population: 8000,
30
+ gdp: 200,
31
+ time: "2025-09-01",
32
+ },
33
+ {
34
+ name: "Thành phố Hồ Chí Minh",
35
+ value: 150,
36
+ population: 9000,
37
+ gdp: 250,
38
+ time: "2025-09-02",
39
+ },
40
+ {
41
+ name: "Thành phố Đà Nẵng",
42
+ value: 95,
43
+ population: 1200,
44
+ gdp: 80,
45
+ time: "2025-09-03",
46
+ },
47
+ {
48
+ name: "Thành phố Hải Phòng",
49
+ value: 110,
50
+ population: 2200,
51
+ gdp: 90,
52
+ time: "2025-09-04",
53
+ },
54
+ {
55
+ name: "Thành phố Cần Thơ",
56
+ value: 88,
57
+ population: 1600,
58
+ gdp: 70,
59
+ time: "2025-09-05",
60
+ },
61
+
62
+ {
63
+ name: "Tỉnh Bắc Ninh",
64
+ value: 77,
65
+ population: 1200,
66
+ gdp: 65,
67
+ time: "2025-09-06",
68
+ },
69
+ {
70
+ name: "Tỉnh Quảng Ninh",
71
+ value: 99,
72
+ population: 1300,
73
+ gdp: 85,
74
+ time: "2025-09-07",
75
+ },
76
+ {
77
+ name: "Tỉnh Thanh Hóa",
78
+ value: 66,
79
+ population: 3000,
80
+ gdp: 60,
81
+ time: "2025-09-08",
82
+ },
83
+ {
84
+ name: "Tỉnh Nghệ An",
85
+ value: 70,
86
+ population: 3200,
87
+ gdp: 62,
88
+ time: "2025-09-09",
89
+ },
90
+ {
91
+ name: "Tỉnh Thừa Thiên Huế",
92
+ value: 55,
93
+ population: 1100,
94
+ gdp: 45,
95
+ time: "2025-09-10",
96
+ },
97
+
98
+ {
99
+ name: "Tỉnh Khánh Hòa",
100
+ value: 85,
101
+ population: 1500,
102
+ gdp: 72,
103
+ time: "2025-09-11",
104
+ },
105
+ {
106
+ name: "Tỉnh Bình Dương",
107
+ value: 140,
108
+ population: 2500,
109
+ gdp: 190,
110
+ time: "2025-09-12",
111
+ },
112
+ {
113
+ name: "Tỉnh Đồng Nai",
114
+ value: 130,
115
+ population: 2800,
116
+ gdp: 175,
117
+ time: "2025-09-13",
118
+ },
119
+ {
120
+ name: "Tỉnh Long An",
121
+ value: 74,
122
+ population: 1400,
123
+ gdp: 60,
124
+ time: "2025-09-14",
125
+ },
126
+ {
127
+ name: "Tỉnh Tiền Giang",
128
+ value: 60,
129
+ population: 1350,
130
+ gdp: 55,
131
+ time: "2025-09-15",
132
+ },
133
+
134
+ {
135
+ name: "Tỉnh Vĩnh Long",
136
+ value: 58,
137
+ population: 1000,
138
+ gdp: 48,
139
+ time: "2025-09-16",
140
+ },
141
+ {
142
+ name: "Tỉnh An Giang",
143
+ value: 65,
144
+ population: 1900,
145
+ gdp: 52,
146
+ time: "2025-09-17",
147
+ },
148
+ {
149
+ name: "Tỉnh Kiên Giang",
150
+ value: 72,
151
+ population: 1800,
152
+ gdp: 58,
153
+ time: "2025-09-18",
154
+ },
155
+ {
156
+ name: "Tỉnh Sóc Trăng",
157
+ value: 54,
158
+ population: 1300,
159
+ gdp: 42,
160
+ time: "2025-09-19",
161
+ },
162
+ {
163
+ name: "Tỉnh Bạc Liêu",
164
+ value: 49,
165
+ population: 900,
166
+ gdp: 38,
167
+ time: "2025-09-20",
168
+ },
169
+
170
+ {
171
+ name: "Tỉnh Cà Mau",
172
+ value: 62,
173
+ population: 1200,
174
+ gdp: 50,
175
+ time: "2025-09-21",
176
+ },
177
+ {
178
+ name: "Tỉnh Tây Ninh",
179
+ value: 80,
180
+ population: 1500,
181
+ gdp: 68,
182
+ time: "2025-09-22",
183
+ },
184
+ {
185
+ name: "Tỉnh Bình Phước",
186
+ value: 78,
187
+ population: 1300,
188
+ gdp: 66,
189
+ time: "2025-09-23",
190
+ },
191
+ {
192
+ name: "Tỉnh Lâm Đồng",
193
+ value: 83,
194
+ population: 1400,
195
+ gdp: 70,
196
+ time: "2025-09-24",
197
+ },
198
+ {
199
+ name: "Tỉnh Gia Lai",
200
+ value: 59,
201
+ population: 1600,
202
+ gdp: 47,
203
+ time: "2025-09-25",
204
+ },
205
+
206
+ {
207
+ name: "Tỉnh Kon Tum",
208
+ value: 40,
209
+ population: 600,
210
+ gdp: 30,
211
+ time: "2025-09-26",
212
+ },
213
+ {
214
+ name: "Tỉnh Đắk Lắk",
215
+ value: 73,
216
+ population: 1700,
217
+ gdp: 60,
218
+ time: "2025-09-27",
219
+ },
220
+ {
221
+ name: "Tỉnh Đắk Nông",
222
+ value: 50,
223
+ population: 700,
224
+ gdp: 35,
225
+ time: "2025-09-28",
226
+ },
227
+ {
228
+ name: "Tỉnh Phú Yên",
229
+ value: 56,
230
+ population: 900,
231
+ gdp: 44,
232
+ time: "2025-09-29",
233
+ },
234
+ {
235
+ name: "Tỉnh Bình Thuận",
236
+ value: 68,
237
+ population: 1200,
238
+ gdp: 55,
239
+ time: "2025-09-30",
240
+ },
241
+
242
+ {
243
+ name: "Tỉnh Ninh Thuận",
244
+ value: 45,
245
+ population: 600,
246
+ gdp: 33,
247
+ time: "2025-09-12",
248
+ },
249
+ {
250
+ name: "Tỉnh Quảng Nam",
251
+ value: 76,
252
+ population: 1500,
253
+ gdp: 64,
254
+ time: "2025-09-13",
255
+ },
256
+ {
257
+ name: "Tỉnh Quảng Ngãi",
258
+ value: 63,
259
+ population: 1100,
260
+ gdp: 50,
261
+ time: "2025-09-14",
262
+ },
263
+ {
264
+ name: "Tỉnh Bình Định",
265
+ value: 82,
266
+ population: 1600,
267
+ gdp: 69,
268
+ time: "2025-09-15",
269
+ },
270
+ ];
271
+ export const chartUiProps = {
272
+ chartConfig: withType(ChartOptionMap, "map"),
273
+ chartType: withDefault(StringControl, "map"),
274
+ defaultData: jsonControl(toJSONObjectArray, defaultChartData),
275
+ endTime: EndTimeControl,
276
+ mapStyle: styleControl(EchartDefaultTextStyle, "mapStyle"),
277
+ regionMapType: dropdownControl(RegionMapTypeOptions, "choropleth"),
278
+ regionName: withDefault(StringControl, "name"),
279
+ regionValue: withDefault(StringControl, "value"),
280
+ rowLimitConfig: RowLimitConfig,
281
+ series: createSeriesListComp(),
282
+ sortBy: withDefault(StringControl, "value"),
283
+ sortOrder: dropdownControl(
284
+ [
285
+ { label: "Ascending", value: "asc" },
286
+ { label: "Descending", value: "desc" },
287
+ ],
288
+ "desc"
289
+ ),
290
+ startTime: StartTimeControl,
291
+ timeColumn: withDefault(StringControl, "time"),
292
+ timeGranularity: TimeGranularityControl,
293
+ timeRange: TimeRangeControl,
294
+ title: withDefault(StringControl, trans("mapChart.defaultTitle")),
295
+ value: withDefault(StringControl, "value"),
296
+ };
297
+
298
+ const chartUiChildrenMap = uiChildren(chartUiProps);
299
+ export type ChartUiPropsType = RecordConstructorToView<
300
+ typeof chartUiChildrenMap
301
+ >;
302
+
303
+ export type UIChartDataType = {
304
+ seriesName: string;
305
+ name: string;
306
+ value: any;
307
+ };
308
+
309
+ export type NonUIChartDataType = {
310
+ name: string;
311
+ value: any;
312
+ };