@czi-sds/data-viz 0.4.2 → 0.6.0

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.
@@ -1,7 +1,12 @@
1
1
  /// <reference types="react" />
2
- import { ECharts, ElementEvent, DatasetComponentOption, EChartsOption, ScatterSeriesOption } from "echarts";
3
2
  import { HTMLAttributes } from "react";
3
+ import { DatasetComponentOption, ECharts, EChartsOption, ScatterSeriesOption } from "echarts";
4
4
  interface CreateChartOptionsProps {
5
+ /**
6
+ * Display reference line and axis value under mouse pointer
7
+ * https://echarts.apache.org/en/option.html#axisPointer
8
+ */
9
+ axisPointer?: EChartsOption["axisPointer"];
5
10
  /**
6
11
  * The data array to be visualized
7
12
  * The data point object shape can be whatever you like, but it must be consistent with the `encode` option
@@ -18,6 +23,44 @@ interface CreateChartOptionsProps {
18
23
  * }
19
24
  */
20
25
  data: DatasetComponentOption["source"];
26
+ /**
27
+ * The `dataZoom` prop is utilized for implementing zoom functionality within a
28
+ * specific area of the chart. This feature empowers users to inspect data in
29
+ * granular detail, obtain an overview of the entire dataset, or eliminate
30
+ * outlier points.
31
+ * By applying the `dataZoom` prop while locking the zoom level, the chart
32
+ * efficiently renders a confined portion of the heatmap. This selective
33
+ * rendering strategy becomes especially advantageous when dealing with
34
+ * extensive datasets. Instead of rendering the entire heatmap at once,
35
+ * the chart dynamically loads and renders specific segments as the user
36
+ * scrolls through the data. This approach optimizes performance and enables
37
+ * the creation of heatmaps with large amounts of data.
38
+ * https://echarts.apache.org/en/option.html#dataZoom
39
+ */
40
+ dataZoom?: EChartsOption["dataZoom"];
41
+ /**
42
+ * The `camera` prop is utilized for implementing camera view port functionality
43
+ * within a specific area of the chart. This feature empowers users to render
44
+ * a confined portion of the heatmap. This selective rendering strategy becomes
45
+ * especially advantageous when dealing with extensive datasets. Instead of
46
+ * rendering the entire heatmap at once, the chart dynamically loads and renders
47
+ * specific segments as the user scrolls through the data. This approach optimizes
48
+ * performance and enables the creation of heatmaps with large amounts of data.
49
+ *
50
+ * The `height` and `width` properties are used to specify the dimensions of the
51
+ * camera view port. The `active` property is used to enable or disable the camera
52
+ * view port functionality.
53
+ */
54
+ camera?: {
55
+ active: boolean;
56
+ height: number;
57
+ width: number;
58
+ };
59
+ /**
60
+ * Customize the style of each cell item when mouse hovers on it, such as color, border, opacity, etc.
61
+ * https://echarts.apache.org/en/option.html#series-scatter.emphasis
62
+ */
63
+ emphasis?: ScatterSeriesOption["emphasis"];
21
64
  /**
22
65
  * The data for the x axis
23
66
  * For example:
@@ -30,7 +73,13 @@ interface CreateChartOptionsProps {
30
73
  * [{ value: "cellType1", textStyle: { color: "red" } }, "cellType2", "cellType3"]
31
74
  */
32
75
  yAxisData: CategoryAxisData;
76
+ /**
77
+ * The width of the chart in pixels
78
+ */
33
79
  width: number;
80
+ /**
81
+ * The height of the chart in pixels
82
+ */
34
83
  height: number;
35
84
  /**
36
85
  * Provide a mapping of data key to x/y axis encoding
@@ -56,6 +105,10 @@ interface CreateChartOptionsProps {
56
105
  * https://echarts.apache.org/en/option.html#series-scatter.itemStyle
57
106
  */
58
107
  itemStyle?: ScatterSeriesOption["itemStyle"];
108
+ /**
109
+ * The shape of the symbol.
110
+ */
111
+ symbol?: "circle" | "rect" | "roundRect";
59
112
  /**
60
113
  * `symbolSize` can be set to single numbers like 10, or use an array to represent width and height. For example, [20, 10] means symbol width is 20, and height is 10.
61
114
  *
@@ -71,6 +124,16 @@ interface CreateChartOptionsProps {
71
124
  * https://echarts.apache.org/en/option.html#grid
72
125
  */
73
126
  grid?: EChartsOption["grid"] | ((defaultOption: EChartsOption["grid"]) => EChartsOption["grid"]);
127
+ /**
128
+ * The options object to be passed to echarts.setOption()
129
+ * https://echarts.apache.org/en/option.html
130
+ */
131
+ options?: EChartsOption;
132
+ /**
133
+ * Event listeners for the chart
134
+ * https://echarts.apache.org/en/api.html#events
135
+ */
136
+ onEvents?: Record<string, (event: unknown, chart: ECharts) => void>;
74
137
  }
75
138
  type OrdinalRawValue = string | number;
76
139
  /**
@@ -85,7 +148,6 @@ type CategoryAxisData = (OrdinalRawValue | {
85
148
  })[];
86
149
  interface HeatmapChartProps extends HTMLAttributes<HTMLDivElement>, CreateChartOptionsProps {
87
150
  echartsRendererMode?: "svg" | "canvas";
88
- onChartMouseMove?: (event: ElementEvent, chart: ECharts) => void;
89
151
  }
90
152
  declare const _default: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<HeatmapChartProps & import("react").RefAttributes<HTMLDivElement>>>;
91
153
  export { HeatmapChartProps, _default, _default as HeatmapChart };
package/dist/index.cjs.js CHANGED
@@ -62,8 +62,70 @@ var DEFAULT_ITEM_STYLE = {
62
62
  return "rgb(0, 0, 0)";
63
63
  },
64
64
  };
65
- function createChartOptions(_a) {
66
- var data = _a.data, xAxisData = _a.xAxisData, yAxisData = _a.yAxisData, width = _a.width, height = _a.height, encode = _a.encode, _b = _a.itemStyle, itemStyle = _b === void 0 ? DEFAULT_ITEM_STYLE : _b, symbolSize = _a.symbolSize, gridProp = _a.grid;
65
+ function createChartOptions(props) {
66
+ var axisPointer = props.axisPointer, camera = props.camera, data = props.data, dataZoom = props.dataZoom, emphasis = props.emphasis, encode = props.encode, gridProp = props.grid, _a = props.itemStyle, itemStyle = _a === void 0 ? DEFAULT_ITEM_STYLE : _a, options = props.options, symbolSize = props.symbolSize, _b = props.symbol, symbol = _b === void 0 ? "rect" : _b;
67
+ var _c = generateDefaultValues(props), defaultAxisPointer = _c.defaultAxisPointer, defaultDataZoom = _c.defaultDataZoom, defaultEmphasis = _c.defaultEmphasis, defaultGrid = _c.defaultGrid, defaultXAxis = _c.defaultXAxis, defaultYAxis = _c.defaultYAxis;
68
+ var customGrid = typeof gridProp === "function" ? gridProp(defaultGrid) : gridProp;
69
+ var _d = options || {}, optionsAxisPointer = _d.axisPointer, optionsDataZoom = _d.dataZoom, optionsSeries = _d.series, optionsXAxis = _d.xAxis, optionsYAxis = _d.yAxis, optionsRest = __rest(_d, ["axisPointer", "dataZoom", "series", "xAxis", "yAxis"]);
70
+ return __assign({ animation: false, axisPointer: mergeAxisPointer(defaultAxisPointer, axisPointer, optionsAxisPointer), dataZoom: (camera === null || camera === void 0 ? void 0 : camera.active)
71
+ ? mergeDataZoom(defaultDataZoom, dataZoom, optionsDataZoom)
72
+ : [], dataset: {
73
+ source: data,
74
+ }, grid: customGrid || defaultGrid, series: [
75
+ Object.assign({
76
+ emphasis: Object.assign(defaultEmphasis, emphasis),
77
+ encode: encode,
78
+ itemStyle: itemStyle,
79
+ legendHoverLink: false,
80
+ symbol: symbol,
81
+ symbolSize: symbolSize,
82
+ }, optionsSeries
83
+ ? Array.isArray(optionsSeries)
84
+ ? optionsSeries[0]
85
+ : optionsSeries
86
+ : [], { symbol: symbol, type: "scatter" }),
87
+ ], xAxis: [
88
+ Object.assign(defaultXAxis, optionsXAxis
89
+ ? Array.isArray(optionsXAxis)
90
+ ? optionsXAxis[0]
91
+ : optionsXAxis
92
+ : {}),
93
+ ], yAxis: [
94
+ Object.assign(defaultYAxis, optionsYAxis
95
+ ? Array.isArray(optionsYAxis)
96
+ ? optionsYAxis[0]
97
+ : optionsYAxis
98
+ : {}),
99
+ ] }, optionsRest);
100
+ }
101
+ function mergeAxisPointer(defaultAxisPointer, axisPointer, optionsAxisPointer) {
102
+ var finalAxisPointer = Array.isArray(axisPointer)
103
+ ? axisPointer // if it's an array, assume that the user has [{...propsToChangeOnX}] OR [ , {...propsToChangeOnY}] OR [{...propsToChangeOnX}, {...propsToChangeOnY}]
104
+ : [axisPointer, axisPointer]; // else if the user only supplies one AxisPointer object, we assume they want the props to apply to both x and y axisPointer objects
105
+ var finalOptionsAxisPointer = Array.isArray(optionsAxisPointer)
106
+ ? optionsAxisPointer
107
+ : [optionsAxisPointer, optionsAxisPointer];
108
+ // merge x axisPointer options
109
+ var x = __assign(__assign(__assign({}, defaultAxisPointer), finalAxisPointer[0]), finalOptionsAxisPointer === null || finalOptionsAxisPointer === void 0 ? void 0 : finalOptionsAxisPointer[0]);
110
+ // merge y axisPointer options
111
+ var y = __assign(__assign(__assign({}, defaultAxisPointer), finalAxisPointer[1]), finalOptionsAxisPointer[1]);
112
+ return [x, y];
113
+ }
114
+ function mergeDataZoom(defaultDataZoom, dataZoom, optionsDataZoom) {
115
+ var finalDataZoom = Array.isArray(dataZoom)
116
+ ? dataZoom // if it's an array, assume that the user has [{...propsToChangeOnX}] OR [ , {...propsToChangeOnY}] OR [{...propsToChangeOnX}, {...propsToChangeOnY}]
117
+ : [dataZoom, dataZoom]; // else if the user only supplies one dataZoom object, we assume they want the props to apply to both x and y zoom objects
118
+ var finalOptionsDataZoom = Array.isArray(optionsDataZoom)
119
+ ? optionsDataZoom
120
+ : [optionsDataZoom, optionsDataZoom];
121
+ // merge x dataZoom options
122
+ var x = __assign(__assign(__assign({}, defaultDataZoom[0]), finalDataZoom[0]), finalOptionsDataZoom === null || finalOptionsDataZoom === void 0 ? void 0 : finalOptionsDataZoom[0]);
123
+ // merge y dataZoom options
124
+ var y = __assign(__assign(__assign({}, defaultDataZoom[1]), finalDataZoom[1]), finalOptionsDataZoom[1]);
125
+ return [x, y];
126
+ }
127
+ function generateDefaultValues(props) {
128
+ var camera = props.camera, height = props.height, symbol = props.symbol, width = props.width, xAxisData = props.xAxisData, yAxisData = props.yAxisData;
67
129
  var defaultGrid = {
68
130
  height: "".concat(height, "px"),
69
131
  left: 0,
@@ -72,76 +134,100 @@ function createChartOptions(_a) {
72
134
  // labels to fixed spacings
73
135
  width: "".concat(width, "px"),
74
136
  };
75
- var customGrid = typeof gridProp === "function" ? gridProp(defaultGrid) : gridProp;
76
- return {
77
- animation: false,
78
- /**
79
- * Display reference line and axis value under mouse pointer
80
- * https://echarts.apache.org/en/option.html#axisPointer
81
- */
82
- axisPointer: {
83
- label: { show: false },
84
- show: true,
85
- triggerOn: "mousemove",
137
+ var defaultAxisPointer = {
138
+ label: { show: false },
139
+ show: false,
140
+ triggerOn: "mousemove",
141
+ };
142
+ var defaultXAxis = {
143
+ axisLabel: { fontSize: 0, rotate: 90 },
144
+ axisLine: {
145
+ show: false,
86
146
  },
87
- dataset: {
88
- source: data,
147
+ axisTick: {
148
+ show: false,
89
149
  },
90
- grid: customGrid || defaultGrid,
91
- series: [
92
- {
93
- emphasis: {
94
- itemStyle: {
95
- color: "inherit",
96
- },
97
- scale: false,
98
- },
99
- encode: encode,
100
- itemStyle: itemStyle,
101
- legendHoverLink: false,
102
- symbolSize: symbolSize,
103
- type: "scatter",
104
- },
105
- ],
106
- xAxis: [
107
- {
108
- axisLabel: { fontSize: 0, rotate: 90 },
109
- axisLine: {
110
- show: false,
111
- },
112
- axisTick: {
113
- show: false,
114
- },
115
- boundaryGap: true,
116
- data: xAxisData,
117
- splitLine: {
118
- show: false,
119
- },
120
- type: "category",
121
- },
122
- ],
123
- yAxis: [
124
- {
125
- axisLabel: { fontSize: 0 },
126
- axisLine: {
127
- show: false,
128
- },
129
- axisTick: {
130
- show: false,
131
- },
132
- boundaryGap: true,
133
- data: yAxisData,
134
- splitLine: {
135
- show: false,
136
- },
137
- },
138
- ],
150
+ boundaryGap: true,
151
+ data: xAxisData,
152
+ splitLine: {
153
+ show: false,
154
+ },
155
+ type: "category",
156
+ };
157
+ var defaultYAxis = {
158
+ axisLabel: { fontSize: 0 },
159
+ axisLine: {
160
+ show: false,
161
+ },
162
+ axisTick: {
163
+ show: false,
164
+ },
165
+ boundaryGap: true,
166
+ data: yAxisData,
167
+ splitLine: {
168
+ show: false,
169
+ },
170
+ };
171
+ var defaultEmphasis = {
172
+ itemStyle: {
173
+ borderColor: symbol === "circle" ? "black" : "white",
174
+ borderType: "solid",
175
+ borderWidth: symbol === "circle" ? 2 : 4,
176
+ opacity: 1,
177
+ },
178
+ scale: false,
179
+ };
180
+ var defaultCamera = {
181
+ height: camera && camera.height ? camera.height : 20,
182
+ width: camera && camera.width ? camera.width : 40,
183
+ };
184
+ var defaultDataZoom = [
185
+ {
186
+ // end index of the x axis window
187
+ endValue: defaultCamera.width - 1,
188
+ filterMode: "filter",
189
+ moveOnMouseMove: true,
190
+ // There's a PR to allow touchpad panning
191
+ // https://github.com/apache/echarts/pull/19352
192
+ moveOnMouseWheel: false,
193
+ orient: "horizontal",
194
+ preventDefaultMouseMove: true,
195
+ // start index of the x axis window
196
+ startValue: 0,
197
+ throttle: 0,
198
+ type: "inside",
199
+ xAxisIndex: 0,
200
+ zoomOnMouseWheel: false,
201
+ },
202
+ {
203
+ // end index of the y axis window
204
+ endValue: defaultCamera.height - 1,
205
+ filterMode: "filter",
206
+ moveOnMouseMove: true,
207
+ moveOnMouseWheel: true,
208
+ orient: "vertical",
209
+ preventDefaultMouseMove: true,
210
+ // start index of the y axis window
211
+ startValue: 0,
212
+ throttle: 0,
213
+ type: "inside",
214
+ yAxisIndex: 0,
215
+ zoomOnMouseWheel: false,
216
+ },
217
+ ];
218
+ return {
219
+ defaultAxisPointer: defaultAxisPointer,
220
+ defaultDataZoom: defaultDataZoom,
221
+ defaultEmphasis: defaultEmphasis,
222
+ defaultGrid: defaultGrid,
223
+ defaultXAxis: defaultXAxis,
224
+ defaultYAxis: defaultYAxis,
139
225
  };
140
226
  }
141
227
 
142
228
  var UPDATE_THROTTLE_MS = 1 * 100;
143
229
  function useUpdateChart(_a) {
144
- var chart = _a.chart, data = _a.data, xAxisData = _a.xAxisData, yAxisData = _a.yAxisData, width = _a.width, height = _a.height, encode = _a.encode, itemStyle = _a.itemStyle, symbolSize = _a.symbolSize, grid = _a.grid;
230
+ var axisPointer = _a.axisPointer, camera = _a.camera, chart = _a.chart, data = _a.data, emphasis = _a.emphasis, xAxisData = _a.xAxisData, yAxisData = _a.yAxisData, width = _a.width, height = _a.height, encode = _a.encode, itemStyle = _a.itemStyle, symbol = _a.symbol, symbolSize = _a.symbolSize, grid = _a.grid, options = _a.options, onEvents = _a.onEvents;
145
231
  var throttledUpdateChart = react.useMemo(function () {
146
232
  return lodash.throttle(function () {
147
233
  if (!chart || !data || !xAxisData || !yAxisData) {
@@ -150,32 +236,67 @@ function useUpdateChart(_a) {
150
236
  // (thuang): resize() needs to be called before setOption() to prevent
151
237
  // TypeError: Cannot read properties of undefined (reading 'shouldBePainted')
152
238
  chart.resize();
153
- chart.setOption(createChartOptions({
239
+ var chartOptions = createChartOptions({
240
+ axisPointer: axisPointer,
241
+ camera: camera,
154
242
  data: data,
243
+ emphasis: emphasis,
155
244
  encode: encode,
156
245
  grid: grid,
157
246
  height: height,
158
247
  itemStyle: itemStyle,
248
+ options: options,
249
+ symbol: symbol,
159
250
  symbolSize: symbolSize,
160
251
  width: width,
161
252
  xAxisData: xAxisData,
162
253
  yAxisData: yAxisData,
163
- }));
254
+ });
255
+ chart.setOption(chartOptions, {
256
+ replaceMerge: ["dataZoom", "tooltip"],
257
+ });
258
+ /**
259
+ * We need to remove old event listeners and bind new ones to
260
+ * make sure that the event listeners are updated when the props change.
261
+ */
262
+ if (onEvents) {
263
+ var _loop_1 = function (eventName) {
264
+ if (Object.prototype.hasOwnProperty.call(onEvents, eventName) &&
265
+ typeof eventName === "string" &&
266
+ typeof onEvents[eventName] === "function") {
267
+ // Remove old event listener
268
+ chart.off(eventName);
269
+ // Add new event listener
270
+ chart.on(eventName, function (event) {
271
+ onEvents[eventName](event, chart);
272
+ });
273
+ }
274
+ };
275
+ for (var eventName in onEvents) {
276
+ _loop_1(eventName);
277
+ }
278
+ }
164
279
  }, UPDATE_THROTTLE_MS,
165
280
  // (thuang): Trailing guarantees that the last call to the function will
166
281
  // be executed
167
282
  { trailing: true });
168
283
  }, [
284
+ axisPointer,
285
+ camera,
169
286
  chart,
170
287
  data,
288
+ emphasis,
171
289
  xAxisData,
172
290
  yAxisData,
173
291
  width,
174
292
  height,
175
293
  encode,
176
294
  itemStyle,
295
+ symbol,
177
296
  symbolSize,
178
297
  grid,
298
+ options,
299
+ onEvents,
179
300
  ]);
180
301
  react.useEffect(function () {
181
302
  return function () { return throttledUpdateChart.cancel(); };
@@ -184,8 +305,11 @@ function useUpdateChart(_a) {
184
305
  react.useEffect(function () {
185
306
  throttledUpdateChart();
186
307
  }, [
308
+ axisPointer,
309
+ camera,
187
310
  chart,
188
311
  data,
312
+ emphasis,
189
313
  xAxisData,
190
314
  yAxisData,
191
315
  throttledUpdateChart,
@@ -193,8 +317,11 @@ function useUpdateChart(_a) {
193
317
  height,
194
318
  encode,
195
319
  itemStyle,
320
+ symbol,
196
321
  symbolSize,
197
322
  grid,
323
+ options,
324
+ onEvents,
198
325
  ]);
199
326
  }
200
327
 
@@ -205,49 +332,121 @@ function getWidthAndHeight(_a) {
205
332
  }
206
333
  var templateObject_1;
207
334
 
208
- function HeatmapChart(props, ref) {
209
- var width = props.width, height = props.height, _a = props.echartsRendererMode, echartsRendererMode = _a === void 0 ? "canvas" : _a, onChartMouseMove = props.onChartMouseMove, xAxisData = props.xAxisData, yAxisData = props.yAxisData, data = props.data, encode = props.encode, itemStyle = props.itemStyle, _b = props.symbolSize, symbolSize = _b === void 0 ? 5 : _b, grid = props.grid, rest = __rest(props, ["width", "height", "echartsRendererMode", "onChartMouseMove", "xAxisData", "yAxisData", "data", "encode", "itemStyle", "symbolSize", "grid"]);
335
+ var HeatmapChart = react.forwardRef(function (props, ref
336
+ // eslint-disable-next-line sonarjs/cognitive-complexity
337
+ ) {
338
+ var axisPointer = props.axisPointer, width = props.width, height = props.height, _a = props.echartsRendererMode, echartsRendererMode = _a === void 0 ? "svg" : _a, camera = props.camera, onEvents = props.onEvents, xAxisData = props.xAxisData, yAxisData = props.yAxisData, data = props.data, encode = props.encode, emphasis = props.emphasis, itemStyle = props.itemStyle, symbol = props.symbol, _b = props.symbolSize, symbolSize = _b === void 0 ? 5 : _b, grid = props.grid, options = props.options, rest = __rest(props, ["axisPointer", "width", "height", "echartsRendererMode", "camera", "onEvents", "xAxisData", "yAxisData", "data", "encode", "emphasis", "itemStyle", "symbol", "symbolSize", "grid", "options"]);
339
+ // Validate width and height
210
340
  if (!width || !height) {
211
341
  throw Error("Chart must have width and height > 0");
212
342
  }
213
- var _c = react.useState(false), isChartInitialized = _c[0], setIsChartInitialized = _c[1];
214
- var _d = react.useState(null), chart = _d[0], setChart = _d[1];
343
+ // Ref for the chart container
215
344
  var innerRef = react.useRef(null);
216
- // Initialize charts
217
- react.useEffect(function () {
345
+ /**
346
+ * (thuang): We need both a state and a ref to store the chart instance, so
347
+ * some hooks can opt out of re-rendering when the chart instance changes.
348
+ */
349
+ var _c = react.useState(null), chart = _c[0], setChart = _c[1];
350
+ var chartRef = react.useRef(chart);
351
+ /**
352
+ * (thuang): Use this ref to store the onEvents prop to prevent
353
+ * unnecessary re-renders when the onEvents prop changes.
354
+ * NOTE: This implies that `onEvents` prop changes alone from the parent
355
+ * won't re-render the chart
356
+ */
357
+ var onEventsRef = react.useRef(onEvents);
358
+ /**
359
+ * (thuang): Use this function to dispose the chart instance for both
360
+ * the state and the ref. This is to prevent memory leaks.
361
+ */
362
+ var disposeChart = react.useCallback(function () {
363
+ var _a;
364
+ (_a = chartRef.current) === null || _a === void 0 ? void 0 : _a.dispose();
365
+ chartRef.current = null;
366
+ setChart(null);
367
+ }, []);
368
+ // Function to initialize the chart
369
+ var initChart = react.useCallback(function () {
370
+ var onEventsCurrent = onEventsRef.current;
218
371
  var current = innerRef.current;
219
372
  if (!current ||
220
- isChartInitialized ||
373
+ chartRef.current ||
221
374
  // (thuang): echart's `init()` will throw error if the container has 0 width or height
222
375
  (current === null || current === void 0 ? void 0 : current.getAttribute("height")) === "0" ||
223
376
  (current === null || current === void 0 ? void 0 : current.getAttribute("width")) === "0") {
224
377
  return;
225
378
  }
226
- setIsChartInitialized(true);
379
+ // Initialize ECharts instance
227
380
  var rawChart = echarts.init(current, EMPTY_OBJECT, {
228
381
  renderer: echartsRendererMode,
229
382
  useDirtyRect: true,
230
383
  });
231
- if (onChartMouseMove) {
232
- rawChart.getZr().on("mousemove", function (event) {
233
- onChartMouseMove(event, rawChart);
234
- });
384
+ // Bind events if provided
385
+ if (onEventsCurrent) {
386
+ bindEvents(rawChart, onEventsCurrent);
235
387
  }
236
388
  setChart(rawChart);
237
- }, [innerRef, isChartInitialized, echartsRendererMode, onChartMouseMove]);
389
+ chartRef.current = rawChart;
390
+ // Cleanup function
391
+ return function () {
392
+ disposeChart();
393
+ // Unbind events if provided
394
+ if (onEventsCurrent) {
395
+ for (var eventName in onEventsCurrent) {
396
+ if (Object.prototype.hasOwnProperty.call(onEventsCurrent, eventName) &&
397
+ typeof eventName === "string" &&
398
+ typeof onEventsCurrent[eventName] === "function") {
399
+ rawChart.off(eventName, onEventsCurrent[eventName]);
400
+ }
401
+ }
402
+ }
403
+ };
404
+ }, [echartsRendererMode, disposeChart]);
405
+ // Initialize charts on component mount
406
+ react.useEffect(function () {
407
+ disposeChart();
408
+ initChart();
409
+ }, [initChart, disposeChart]);
410
+ // Hook to update chart data and options
238
411
  useUpdateChart({
412
+ axisPointer: axisPointer,
413
+ camera: camera,
239
414
  chart: chart,
240
415
  data: data,
416
+ emphasis: emphasis,
241
417
  encode: encode,
242
418
  grid: grid,
243
419
  height: height,
244
420
  itemStyle: itemStyle,
421
+ onEvents: onEvents,
422
+ options: options,
423
+ symbol: symbol,
245
424
  symbolSize: symbolSize,
246
425
  width: width,
247
426
  xAxisData: xAxisData,
248
427
  yAxisData: yAxisData,
249
428
  });
429
+ // Render the chart container
250
430
  return (jsxRuntime.jsx(ChartContainer, __assign({ height: height, width: width, ref: handleRef }, rest)));
431
+ // Function to bind events to the ECharts instance
432
+ function bindEvents(instance, events) {
433
+ function innerBindEvent(eventName, func) {
434
+ // Ignore invalid event configurations
435
+ if (typeof eventName === "string" && typeof func === "function") {
436
+ // Bind event
437
+ instance.on(eventName, function (param) {
438
+ func(param, instance);
439
+ });
440
+ }
441
+ }
442
+ // Loop through events and bind them
443
+ for (var eventName in events) {
444
+ if (Object.prototype.hasOwnProperty.call(events, eventName)) {
445
+ innerBindEvent(eventName, events[eventName]);
446
+ }
447
+ }
448
+ }
449
+ // Function to handle the ref of the chart container
251
450
  function handleRef(element) {
252
451
  innerRef.current = element;
253
452
  if (!ref)
@@ -260,7 +459,7 @@ function HeatmapChart(props, ref) {
260
459
  ref.current = element;
261
460
  }
262
461
  }
263
- }
264
- var index = react.memo(react.forwardRef(HeatmapChart));
462
+ });
463
+ var index = react.memo(HeatmapChart);
265
464
 
266
465
  exports.HeatmapChart = index;