@trackunit/react-chart-components 1.3.86 → 1.3.88

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.
package/index.esm.js CHANGED
@@ -1,61 +1,170 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { Spinner, Text } from '@trackunit/react-components';
2
3
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
3
- import { Spinner, Text, useHover } from '@trackunit/react-components';
4
- import EChart from 'echarts-for-react';
5
- import { useRef, useEffect } from 'react';
4
+ import { objectKeys } from '@trackunit/shared-utils';
5
+ import * as echarts from 'echarts';
6
+ import { useRef, useCallback, useEffect, useMemo, useState } from 'react';
7
+ import { DEFAULT_CHART_COLORS, CHART_STATUS_COLORS, DEFAULT_CHART_OTHER } from '@trackunit/ui-design-tokens';
6
8
 
9
+ function isECElementEvent(value) {
10
+ return (typeof value === "object" &&
11
+ value !== null &&
12
+ "type" in value &&
13
+ "componentType" in value &&
14
+ "componentSubType" in value &&
15
+ "componentIndex" in value &&
16
+ "seriesIndex" in value);
17
+ }
7
18
  /**
8
- * The Chart component is a wrapper component for ECharts.
9
- *
10
- * Handles events and click functionality.
11
- *
12
- * For more information see the [eCharts documentation](https://github.com/hustcc/echarts-for-react).
13
- *
14
- * @param {ChartProps} props - The props for the Chart component
15
- * @returns {ReactElement} Chart component
19
+ * A React wrapper for ECharts that handles initialization, events, and cleanup.
16
20
  */
17
- const Chart = ({ options, unsafeOptions, showLoading, className, style, onChartReady, onClick, onEvents, merge = true, loadingOption, timezoneLabel, renderer = "canvas", dataTestId, }) => {
18
- const echartsRef = useRef(null);
21
+ const EChart = ({ option, style, className, onChartReady, onClick, onEvents, notMerge = false, renderer = "canvas", dataTestId, }) => {
22
+ const containerRef = useRef(null);
23
+ const internalChartRef = useRef(undefined);
24
+ const isInitialRender = useRef(true);
25
+ const setupEventHandlers = useCallback((chart) => {
26
+ // Handle click events
27
+ if (onClick) {
28
+ chart.on("click", function (event) {
29
+ if (isECElementEvent(event)) {
30
+ onClick(event);
31
+ }
32
+ });
33
+ const zr = chart.getZr();
34
+ zr.setCursorStyle("pointer");
35
+ }
36
+ // Handle other events
37
+ if (onEvents) {
38
+ Object.entries(onEvents).forEach(([eventName, handler]) => {
39
+ if (eventName !== "click" || !onClick) {
40
+ // Don't double-register click if onClick is provided
41
+ chart.on(eventName, function (event) {
42
+ if (isECElementEvent(event)) {
43
+ handler(event);
44
+ }
45
+ });
46
+ }
47
+ });
48
+ }
49
+ }, [onClick, onEvents]);
50
+ const initChart = useCallback(() => {
51
+ const container = containerRef.current;
52
+ if (!container) {
53
+ return;
54
+ }
55
+ // Dispose existing instance if any
56
+ if (internalChartRef.current) {
57
+ internalChartRef.current.dispose();
58
+ internalChartRef.current = undefined;
59
+ }
60
+ // Create new chart instance
61
+ const newChart = echarts.init(container, undefined, {
62
+ renderer,
63
+ width: "auto",
64
+ height: "auto",
65
+ });
66
+ // Store reference and notify ready
67
+ internalChartRef.current = newChart;
68
+ if (onChartReady) {
69
+ onChartReady(newChart);
70
+ }
71
+ }, [renderer, onChartReady]);
72
+ // Initialize chart and handle cleanup
19
73
  useEffect(() => {
20
- const instance = echartsRef.current?.getEchartsInstance();
21
- if (instance) {
22
- if (onClick) {
23
- instance.on("click", onClick);
74
+ initChart();
75
+ isInitialRender.current = true;
76
+ const resizeObserver = new ResizeObserver(() => {
77
+ const chart = internalChartRef.current;
78
+ if (!chart) {
79
+ return;
24
80
  }
25
- else {
26
- instance.getZr().setCursorStyle("default");
81
+ if (!chart.isDisposed()) {
82
+ chart.resize();
27
83
  }
84
+ });
85
+ const container = containerRef.current;
86
+ if (container) {
87
+ resizeObserver.observe(container);
88
+ }
89
+ return () => {
90
+ resizeObserver.disconnect();
91
+ const chart = internalChartRef.current;
92
+ if (!chart) {
93
+ return;
94
+ }
95
+ if (!chart.isDisposed()) {
96
+ const zr = chart.getZr();
97
+ zr.setCursorStyle("default");
98
+ chart.dispose();
99
+ internalChartRef.current = undefined;
100
+ }
101
+ };
102
+ }, [initChart]);
103
+ // Setup event handlers
104
+ useEffect(() => {
105
+ const chart = internalChartRef.current;
106
+ if (chart && !chart.isDisposed()) {
107
+ // Setup handlers
108
+ setupEventHandlers(chart);
28
109
  }
29
110
  return () => {
30
- if (instance && !instance.isDisposed()) {
31
- instance.off("click", onClick);
111
+ if (chart && !chart.isDisposed()) {
112
+ // Clean up all event handlers
113
+ chart.off("click");
114
+ if (onEvents) {
115
+ objectKeys(onEvents).forEach(eventName => {
116
+ chart.off(eventName);
117
+ });
118
+ }
32
119
  }
33
120
  };
34
- }, [onClick, echartsRef]);
35
- return (jsx("div", { className: cvaChartContainer(), "data-testid": dataTestId, style: { height: style?.height ?? "300px", width: style?.width ?? "100%" }, children: showLoading ? (jsxs("div", { className: cvaChartSpinnerContainer(), "data-testid": `${dataTestId}-loading`, children: [jsx(Spinner, { centering: "centered" }), loadingOption?.text ? (jsx(Text, { align: "center", subtle: true, children: loadingOption.text })) : null] })) : (jsxs(Fragment, { children: [jsx(EChart, { className: className, notMerge: !merge, onChartReady: onChartReady, onEvents: onEvents, option: options ?? unsafeOptions, opts: { width: "auto", height: "auto", renderer: renderer }, ref: echartsRef, style: style }), timezoneLabel] })) }));
121
+ }, [onEvents, setupEventHandlers]);
122
+ // Handle options updates
123
+ useEffect(() => {
124
+ const chart = internalChartRef.current;
125
+ if (!chart) {
126
+ return;
127
+ }
128
+ if (!chart.isDisposed()) {
129
+ // Force notMerge on initial render, respect prop afterwards
130
+ chart.setOption(option, isInitialRender.current || notMerge);
131
+ isInitialRender.current = false;
132
+ }
133
+ }, [option, notMerge]);
134
+ return jsx("div", { className: cvaEChart({ className }), "data-testid": dataTestId, ref: containerRef, style: style });
135
+ };
136
+ const cvaEChart = cvaMerge(["w-full", "h-full"]);
137
+
138
+ /**
139
+ * The Chart component is a wrapper component for ECharts.
140
+ * Handles events and click functionality.
141
+ */
142
+ const Chart = ({ options, unsafeOptions, showLoading, className, style, onChartReady, onClick, onEvents, merge = true, loadingOption, timezoneLabel, renderer = "canvas", dataTestId, }) => {
143
+ const containerStyle = {
144
+ height: style?.height ?? "300px",
145
+ width: style?.width ?? "100%",
146
+ ...style,
147
+ };
148
+ return (jsx("div", { className: "grid h-full w-full grid-cols-1 grid-rows-1 items-center gap-1", "data-testid": dataTestId, style: containerStyle, children: showLoading ? (jsxs("div", { className: "grid place-items-center overflow-y-auto", "data-testid": `${dataTestId}-loading`, children: [jsx(Spinner, { centering: "centered" }), loadingOption?.text ? (jsx(Text, { align: "center", subtle: true, children: loadingOption.text })) : null] })) : (jsxs(Fragment, { children: [jsx(EChart, { className: className, dataTestId: `${dataTestId}-chart`, notMerge: !merge, onChartReady: onChartReady, onClick: onClick, onEvents: onEvents, option: options ?? unsafeOptions, renderer: renderer, style: style }), timezoneLabel] })) }));
36
149
  };
37
- const cvaChartContainer = cvaMerge(["grid", "gap-1", "grid-rows-1", "grid-cols-1", "h-full", "w-full", "items-center"]);
38
- const cvaChartSpinnerContainer = cvaMerge(["grid", "place-items-center", "overflow-y-auto"]);
39
150
 
40
151
  const cvaLegendItem = cvaMerge([
41
- "inline-flex",
152
+ "flex",
42
153
  "items-center",
43
154
  "transition-all",
44
155
  "ease-in-out",
45
156
  "duration-200",
46
- "text-neutral-500",
47
- "hover:text-neutral-700",
48
- "text-sm",
49
- "gap-2",
157
+ "text-secondary-600",
158
+ "hover:text-secondary-900",
50
159
  ], {
51
160
  variants: {
52
161
  selected: {
53
162
  false: "",
54
- true: "font-medium text-black",
163
+ true: ["font-semibold", "text-secondary-900"],
55
164
  },
56
165
  disabled: {
57
166
  false: "",
58
- true: "text-neutral-300",
167
+ true: ["text-secondary-400", "hover:text-secondary-400"],
59
168
  },
60
169
  isClickable: {
61
170
  false: "cursor-default",
@@ -68,11 +177,11 @@ const cvaLegendItem = cvaMerge([
68
177
  isClickable: false,
69
178
  },
70
179
  });
71
- const cvaLegendItemIndicator = cvaMerge(["w-3", "h-3", "rounded-[50%]"], {
180
+ const cvaLegendItemIndicator = cvaMerge(["w-3", "mr-1", "h-3", "rounded-[50%]", "flex-none"], {
72
181
  variants: {
73
182
  selected: {
74
183
  false: "",
75
- true: "border border-black border-opacity-50",
184
+ true: "",
76
185
  },
77
186
  },
78
187
  defaultVariants: {
@@ -86,77 +195,232 @@ const cvaLegendItemIndicator = cvaMerge(["w-3", "h-3", "rounded-[50%]"], {
86
195
  * @param {LegendItem} props - The props for the LegendItem component
87
196
  * @returns {ReactElement} LegendItem component
88
197
  */
89
- const LegendItem = ({ className, label, disabled, selected, onClick, color, dataTestId }) => {
198
+ const LegendItem = ({ className, count, label, disabled, selected, onClick, color, dataTestId, onMouseEnter, onMouseLeave, }) => {
90
199
  const handleOnClick = onClick && !disabled ? () => onClick() : undefined;
91
- return (jsxs("div", { className: cvaLegendItem({ disabled, selected, isClickable: Boolean(onClick), className }), "data-testid": dataTestId, onClick: handleOnClick, children: [jsx("div", { className: cvaLegendItemIndicator({ selected }), "data-testid": dataTestId ? `${dataTestId}-indicator` : null, style: { backgroundColor: color } }), label ? jsx("p", { children: label }) : null] }));
200
+ return (jsxs("div", { className: cvaLegendItem({ disabled, selected, isClickable: !disabled && Boolean(onClick), className }), "data-testid": dataTestId, onClick: handleOnClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: [jsx("div", { className: cvaLegendItemIndicator({ selected }), "data-testid": dataTestId ? `${dataTestId}-indicator` : null, style: { backgroundColor: color } }), jsxs("p", { className: "truncate text-xs", children: [label, "\u00A0"] }), jsxs("p", { className: "text-xs", children: ["(", count || 0, ")"] })] }));
201
+ };
202
+
203
+ /**
204
+ * Re-ordered chart colors to ensure that adjacent colors are visually different.
205
+ *
206
+ * @returns {string[]} The reordered chart colors.
207
+ */
208
+ const useChartColor = () => {
209
+ const chartColor = useCallback((index) => {
210
+ return DEFAULT_CHART_COLORS[index % DEFAULT_CHART_COLORS.length] ?? "#000000";
211
+ }, []);
212
+ const chartColorArray = useCallback((total) => {
213
+ return Array.from({ length: total }, (_, index) => chartColor(index));
214
+ }, [chartColor]);
215
+ const chartStatusColor = useCallback((status) => {
216
+ return CHART_STATUS_COLORS[status];
217
+ }, []);
218
+ return {
219
+ chartColor,
220
+ chartColorArray,
221
+ chartStatusColor,
222
+ };
223
+ };
224
+
225
+ /**
226
+ * Limits the data set to the given limit.
227
+ * If the data set is larger than the limit, the data set is limited to the limit and the rest of the data is added to the "Others" group.
228
+ *
229
+ * @param data - The data set to limit.
230
+ * @param limit - The limit to apply to the data set.
231
+ * @returns {object} The limited data set with and without the "others" category.
232
+ */
233
+ const useLimitDataSet = (data, limit) => {
234
+ const limitedData = useMemo(() => {
235
+ const sortedData = data.sort((a, b) => (b.count ?? 0) - (a.count ?? 0));
236
+ if (sortedData.length > limit) {
237
+ const result = sortedData.slice(0, limit);
238
+ result.push({
239
+ id: "defaultOther",
240
+ name: "Others",
241
+ selected: false,
242
+ count: sortedData.slice(limit).reduce((acc, curr) => acc + (curr.count ?? 0), 0),
243
+ color: DEFAULT_CHART_OTHER,
244
+ original: { defaultOther: true },
245
+ });
246
+ return result;
247
+ }
248
+ return sortedData;
249
+ }, [data, limit]);
250
+ const limitedDataWithoutOthers = useMemo(() => limitedData.filter(item => !item.original?.defaultOther), [limitedData]);
251
+ return { limitedData, limitedDataWithoutOthers };
92
252
  };
93
253
 
94
254
  /**
95
- * Create a PieChart with legends based on our current Chart component
255
+ * Create a DonutChart with legends based on our current Chart component
96
256
  *
97
- * @param {PieChartProps} props - The props for the Chart component
257
+ * @param {DonutChartProps} props - The props for the Chart component
98
258
  * @returns {ReactElement} Chart component
99
259
  */
100
- const PieChart = ({ data, size = "full", loading, onClick, className, dataTestId, }) => {
101
- const totalCount = data?.map(item => item.count ?? 0).reduce((a, b) => a + b, 0) ?? 0;
102
- const { hovering, onMouseEnter, onMouseLeave } = useHover({ debounced: true });
103
- return (jsxs("div", { className: cvaChartRoot({ className }), "data-testid": dataTestId, children: [jsx("div", { children: size === "full" && (jsx("div", { className: "flex flex-col", "data-testid": "legend", children: data?.map(item => (jsx(LegendItem, { color: item.color, dataTestId: `legend-${item.id}`, label: item.count !== undefined ? `${item.name} (${item.count})` : item.name, onClick: onClick ? () => onClick(item) : undefined, selected: item.selected }, item.id))) })) }), jsx("div", { onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: jsx(Chart, { dataTestId: "pie-chart", onClick: evt => {
104
- const clickedEntry = data?.find(x => x.id === evt.data.id);
105
- if (onClick && clickedEntry) {
106
- onClick(clickedEntry);
107
- }
108
- }, options: {
109
- legend: {
110
- show: false,
111
- },
112
- tooltip: {
113
- show: false,
260
+ const DonutChart = ({ data, size = "full", loading, onClick, className, dataTestId, legendPosition = "Right", maxDataPoints = 6, showOthers = true, }) => {
261
+ const containerRef = useRef(null);
262
+ const chartRef = useRef(null);
263
+ const totalCount = useMemo(() => data?.map(item => item.count ?? 0).reduce((a, b) => a + b, 0) ?? 0, [data]);
264
+ const [hoveringItem, setHoveringItem] = useState(null);
265
+ const currentCount = useMemo(() => hoveringItem?.count ?? totalCount, [hoveringItem, totalCount]);
266
+ const { limitedData, limitedDataWithoutOthers } = useLimitDataSet(data ?? [], maxDataPoints);
267
+ const { chartColor } = useChartColor();
268
+ const handleChartReady = useCallback((chart) => {
269
+ chartRef.current = chart;
270
+ }, []);
271
+ const handleChartClick = useCallback((evt) => {
272
+ if (onClick && data) {
273
+ const clickedEntry = data.find(x => {
274
+ if (!evt.data || typeof evt.data !== "object" || !("id" in evt.data)) {
275
+ return false;
276
+ }
277
+ return x.id === evt.data.id;
278
+ });
279
+ if (clickedEntry) {
280
+ onClick(clickedEntry);
281
+ }
282
+ }
283
+ }, [onClick, data]);
284
+ const handleChartEvents = useMemo(() => ({
285
+ mouseover: (evt) => {
286
+ const hoveredItem = data?.[evt.dataIndex];
287
+ if (hoveredItem) {
288
+ setHoveringItem(hoveredItem);
289
+ }
290
+ },
291
+ mouseout: () => {
292
+ setHoveringItem(null);
293
+ },
294
+ }), [data, setHoveringItem]);
295
+ const handleLegendMouseEnter = useCallback((item) => {
296
+ setHoveringItem(item);
297
+ const chart = chartRef.current;
298
+ if (!chart) {
299
+ return;
300
+ }
301
+ // Find the index in the current chart data
302
+ const index = (showOthers ? limitedData : limitedDataWithoutOthers).findIndex(d => d.id === item.id);
303
+ if (index !== -1) {
304
+ chart.dispatchAction({
305
+ type: "highlight",
306
+ seriesIndex: 0,
307
+ dataIndex: index,
308
+ });
309
+ }
310
+ }, [limitedData, limitedDataWithoutOthers, showOthers]);
311
+ const handleLegendMouseLeave = useCallback(() => {
312
+ setHoveringItem(null);
313
+ const chart = chartRef.current;
314
+ if (!chart) {
315
+ return;
316
+ }
317
+ chart.dispatchAction({
318
+ type: "downplay",
319
+ seriesIndex: 0,
320
+ });
321
+ }, []);
322
+ const chartOptions = useMemo(() => {
323
+ return {
324
+ legend: {
325
+ show: false,
326
+ },
327
+ tooltip: {
328
+ show: false,
329
+ },
330
+ series: [
331
+ {
332
+ type: "pie",
333
+ radius: ["50%", "75%"],
334
+ center: ["50%", "50%"],
335
+ minAngle: 5,
336
+ selectedOffset: 8,
337
+ itemStyle: {
338
+ borderColor: "#ffffff",
339
+ borderWidth: 2,
340
+ },
341
+ avoidLabelOverlap: false,
342
+ label: {
343
+ show: true,
344
+ position: "center",
345
+ fontSize: size === "full" ? 18 : 12,
346
+ fontWeight: "bold",
347
+ formatter: currentCount.toString(),
348
+ },
349
+ emphasis: {
350
+ label: {
351
+ show: true,
352
+ formatter: "{c}",
114
353
  },
115
- series: [
116
- {
117
- type: "pie",
118
- radius: ["50%", "75%"], //can't be 100 since it'll be cut off when hovering
119
- center: ["50%", "50%"],
120
- minAngle: 10,
121
- selectedOffset: 8,
122
- itemStyle: {
123
- borderColor: "#ffffff",
124
- borderWidth: 2,
125
- },
126
- avoidLabelOverlap: false,
127
- label: {
128
- show: !hovering,
129
- position: "center",
130
- fontSize: size === "full" ? 18 : 12,
131
- fontWeight: "bold",
132
- formatter: totalCount.toString(),
133
- },
134
- emphasis: {
135
- label: {
136
- show: hovering,
137
- formatter: "{c}",
138
- },
139
- },
140
- labelLine: {
141
- show: false,
142
- },
143
- data: data?.map(item => ({
144
- id: item.id,
145
- name: item.name,
146
- value: item.count ?? 0,
147
- itemStyle: { color: item.color },
148
- })),
354
+ },
355
+ labelLine: {
356
+ show: false,
357
+ },
358
+ data: (showOthers ? limitedData : limitedDataWithoutOthers)
359
+ .map((item, index) => {
360
+ const itemColor = item.color ?? chartColor(index);
361
+ return {
362
+ id: item.id,
363
+ name: item.name,
364
+ value: item.count ?? 0,
365
+ itemStyle: {
366
+ color: itemColor,
149
367
  },
150
- ],
151
- }, showLoading: loading, style: size === "full" ? { height: 110, width: 110 } : { height: 60, width: 60 } }) })] }));
368
+ emphasis: {
369
+ disabled: false,
370
+ scale: true,
371
+ scaleSize: 5,
372
+ },
373
+ selected: hoveringItem?.id === item.id,
374
+ };
375
+ })
376
+ .filter(item => item.value),
377
+ },
378
+ ],
379
+ };
380
+ }, [size, currentCount, showOthers, limitedData, limitedDataWithoutOthers, chartColor, hoveringItem?.id]);
381
+ return (jsxs("div", { className: cvaChartRoot({ className, legendPosition }), "data-testid": dataTestId, ref: containerRef, children: [jsx("div", { className: cvaChartContainer({ legendPosition }), children: jsx(Chart, { className: cvaChart({ legendPosition, size }), dataTestId: "pie-chart", onChartReady: handleChartReady, onClick: handleChartClick, onEvents: handleChartEvents, options: chartOptions, showLoading: loading, style: { width: "100%", height: "100%" } }) }), size === "full" && (jsx("div", { className: cvaLegend({ legendPosition }), "data-testid": "legend", children: limitedData.map((item, index) => (jsx(LegendItem, { className: "p-1.5 py-0.5", color: item.color ?? chartColor(index), count: item.count, dataTestId: `legend-${item.id}`, disabled: item.count === 0, label: item.name, onClick: onClick ? () => onClick(item) : undefined, onMouseEnter: () => handleLegendMouseEnter(item), onMouseLeave: handleLegendMouseLeave, selected: item.selected }, item.id))) }))] }));
152
382
  };
153
- const cvaChartRoot = cvaMerge([
154
- "flex",
155
- "flex-direction-col",
156
- "flex-wrap-reverse",
157
- "justify-between",
158
- "items-center",
159
- "h-full",
160
- ]);
383
+ const cvaChartRoot = cvaMerge(["flex", "w-full", "h-full", "gap-4"], {
384
+ variants: {
385
+ legendPosition: {
386
+ Right: ["items-center", "justify-items-stretch", "flex-row"],
387
+ Bottom: ["items-center", "flex-col"],
388
+ },
389
+ },
390
+ });
391
+ const cvaChartContainer = cvaMerge(["flex-1", "h-full"], {
392
+ variants: {
393
+ legendPosition: {
394
+ Right: ["justify-end"],
395
+ Bottom: ["flex", "items-center", "w-full"],
396
+ },
397
+ },
398
+ });
399
+ const cvaChart = cvaMerge(["flex-0", "max-w-[200px]", "max-h-[200px]", "place-self-center"], {
400
+ variants: {
401
+ legendPosition: {
402
+ Right: [],
403
+ Bottom: ["max-h-[230px]"],
404
+ },
405
+ size: {
406
+ full: ["min-h-[140px]"],
407
+ compact: ["w-[60px]", "h-[60px]"],
408
+ },
409
+ },
410
+ defaultVariants: {
411
+ size: "full",
412
+ },
413
+ });
414
+ const cvaLegend = cvaMerge(["flex", "overflow-auto"], {
415
+ variants: {
416
+ legendPosition: {
417
+ Right: ["justify-start", "flex-col", "flex-1"],
418
+ Bottom: ["flex-wrap", "justify-end", "flex-row"],
419
+ },
420
+ },
421
+ defaultVariants: {
422
+ legendPosition: "Right",
423
+ },
424
+ });
161
425
 
162
- export { Chart, LegendItem, PieChart };
426
+ export { Chart, DonutChart, LegendItem, useChartColor };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-chart-components",
3
- "version": "1.3.86",
3
+ "version": "1.3.88",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -8,10 +8,11 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "echarts": "5.6.0",
11
- "echarts-for-react": "^3.0.2",
12
11
  "react": "19.0.0",
13
- "@trackunit/css-class-variance-utilities": "1.3.71",
14
- "@trackunit/react-components": "1.4.86"
12
+ "@trackunit/ui-design-tokens": "1.3.73",
13
+ "@trackunit/shared-utils": "1.5.73",
14
+ "@trackunit/css-class-variance-utilities": "1.3.73",
15
+ "@trackunit/react-components": "1.4.88"
15
16
  },
16
17
  "module": "./index.esm.js",
17
18
  "main": "./index.cjs.js",
@@ -1,6 +1,7 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
- import { EChartsOption } from "echarts";
2
+ import type { ECElementEvent, ECharts, EChartsOption } from "echarts";
3
3
  import { CSSProperties, ReactElement, ReactNode } from "react";
4
+ import { type EventName } from "../EChart/EChart";
4
5
  interface UnsafeOptions {
5
6
  [key: string]: any;
6
7
  }
@@ -12,7 +13,7 @@ type UnsafeOptionsCondition = {
12
13
  /**
13
14
  * Option values for EChart. Not typed.
14
15
  *
15
- * @deprecated Use options instead.
16
+ * @deprecated Use options instead. Will be removed in next major version.
16
17
  */
17
18
  unsafeOptions: UnsafeOptions;
18
19
  };
@@ -24,38 +25,37 @@ type SafeOptionsCondition = {
24
25
  /**
25
26
  * Option values for EChart. Not typed.
26
27
  *
27
- * @deprecated Use options instead.
28
+ * @deprecated Use options instead. Will be removed in next major version.
28
29
  */
29
30
  unsafeOptions?: never;
30
31
  };
31
32
  type ConditionalChartOptions = UnsafeOptionsCondition | SafeOptionsCondition;
32
- /**
33
- * https://echarts.apache.org/en/api.html#events
34
- */
35
- type EventName = "datazoom" | "brush" | "brushselected" | "globalout" | "mouseover" | "mousedown" | "mouseup" | "mouseOut" | "click" | "dblclick" | "contextmenu";
36
33
  export type ChartProps = CommonProps & ConditionalChartOptions & {
37
34
  /**
38
- * Whether or not to low the preloader.
35
+ * Whether or not to show the preloader.
39
36
  */
40
37
  showLoading?: boolean;
41
38
  /**
42
- * onClick event.
39
+ * onClick event handler.
43
40
  */
44
- onClick?: (event: any) => void;
41
+ onClick?: (event: ECElementEvent) => void;
45
42
  /**
46
43
  * CSS styles for the chart.
47
44
  */
48
45
  style?: CSSProperties;
49
46
  /**
50
- * To denote of chart is ready or not.
47
+ * Called when the chart instance is ready.
51
48
  */
52
- onChartReady?: (chart: any) => void;
49
+ onChartReady?: (chart: ECharts) => void;
53
50
  /**
54
51
  * Event handlers for the chart.
55
52
  */
56
- onEvents?: Partial<Record<EventName, (event: any) => void>>;
53
+ onEvents?: Partial<Record<EventName, (event: ECElementEvent) => void>>;
57
54
  /**
58
55
  * Whether to merge with previous option.
56
+ *
57
+ * @deprecated Use notMerge in EChart directly. Will be removed in next major version.
58
+ * @default true
59
59
  */
60
60
  merge?: boolean;
61
61
  /**
@@ -69,7 +69,9 @@ export type ChartProps = CommonProps & ConditionalChartOptions & {
69
69
  */
70
70
  timezoneLabel?: ReactNode;
71
71
  /**
72
- * Type of rendered used. Either "svg" or "canvas".
72
+ * Type of renderer used. Either "svg" or "canvas".
73
+ *
74
+ * @default "canvas"
73
75
  */
74
76
  renderer?: "svg" | "canvas";
75
77
  /**
@@ -79,13 +81,7 @@ export type ChartProps = CommonProps & ConditionalChartOptions & {
79
81
  };
80
82
  /**
81
83
  * The Chart component is a wrapper component for ECharts.
82
- *
83
84
  * Handles events and click functionality.
84
- *
85
- * For more information see the [eCharts documentation](https://github.com/hustcc/echarts-for-react).
86
- *
87
- * @param {ChartProps} props - The props for the Chart component
88
- * @returns {ReactElement} Chart component
89
85
  */
90
86
  export declare const Chart: ({ options, unsafeOptions, showLoading, className, style, onChartReady, onClick, onEvents, merge, loadingOption, timezoneLabel, renderer, dataTestId, }: ChartProps) => ReactElement;
91
87
  export {};