@czi-sds/data-viz 0.5.0 → 0.7.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.
- package/README.md +18 -13
- package/dist/index.cjs.d.ts +64 -2
- package/dist/index.cjs.js +282 -83
- package/dist/index.esm.d.ts +64 -2
- package/dist/index.esm.js +283 -84
- package/dist/tailwind.json +211 -80
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The Science Design System (SDS) brings consistency and universal standards to CZ
|
|
|
4
4
|
|
|
5
5
|
## Design System Documentation
|
|
6
6
|
|
|
7
|
-
`@czi-sds/components` implements the Science Design System as documented in [Zeroheight](https://sds.czi.design/). As a result, it's very useful to get familiar with the available **theme variables**, such as `colors`, `
|
|
7
|
+
`@czi-sds/components` implements the Science Design System as documented in [Zeroheight](https://sds.czi.design/). As a result, it's very useful to get familiar with the available **theme variables**, such as `colors`, `spaces`, `typography`, etc., so you can leverage the theme properly in your application.
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
@@ -93,24 +93,24 @@ export const Title - styled(Typography)`
|
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
95
|
import { css, SerializedStyles } from "@emotion/react";
|
|
96
|
-
import { styled } from
|
|
96
|
+
import { styled } from "@mui/material/styles";
|
|
97
97
|
import { getColors, getCorners } from "@czi-sds/components";
|
|
98
98
|
|
|
99
99
|
export const Tag = styled("div")`
|
|
100
100
|
// This is a callback function that returns more CSS rules, but the only way
|
|
101
101
|
// to access the custom theme object
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
${(props) => {
|
|
103
|
+
// getColors() is a selector that picks out colors from the theme object
|
|
104
|
+
const colors = getColors(props);
|
|
105
|
+
// getSpaces() is a selector that picks out spaces from the theme object
|
|
106
|
+
const spaces = getSpaces(props);
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
return `
|
|
109
109
|
background-color: ${colors?.gray[500]};
|
|
110
|
-
padding-bottom: ${
|
|
111
|
-
margin-bottom: ${
|
|
110
|
+
padding-bottom: ${spaces?.m}px;
|
|
111
|
+
margin-bottom: ${spaces?.xxl}px;
|
|
112
112
|
`;
|
|
113
|
-
|
|
113
|
+
}}
|
|
114
114
|
`;
|
|
115
115
|
```
|
|
116
116
|
|
|
@@ -199,9 +199,14 @@ To use the default theme in your React application, complete the following:
|
|
|
199
199
|
|
|
200
200
|
```html
|
|
201
201
|
// installs the sds font from google fonts
|
|
202
|
-
<link rel="preconnect" href="https://fonts.
|
|
202
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
203
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
204
|
+
<link
|
|
205
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"
|
|
206
|
+
rel="stylesheet"
|
|
207
|
+
/>
|
|
203
208
|
<link
|
|
204
|
-
href="https://fonts.googleapis.com/css2?family=
|
|
209
|
+
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap"
|
|
205
210
|
rel="stylesheet"
|
|
206
211
|
/>
|
|
207
212
|
```
|
package/dist/index.cjs.d.ts
CHANGED
|
@@ -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,86 +62,172 @@ var DEFAULT_ITEM_STYLE = {
|
|
|
62
62
|
return "rgb(0, 0, 0)";
|
|
63
63
|
},
|
|
64
64
|
};
|
|
65
|
-
function createChartOptions(
|
|
66
|
-
var
|
|
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,
|
|
70
132
|
top: 0,
|
|
71
133
|
// (atarashansky): this is the key change to align x and y axis
|
|
72
|
-
// labels to fixed
|
|
134
|
+
// labels to fixed spaces
|
|
73
135
|
width: "".concat(width, "px"),
|
|
74
136
|
};
|
|
75
|
-
var
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
88
|
-
|
|
147
|
+
axisTick: {
|
|
148
|
+
show: false,
|
|
89
149
|
},
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
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
|
-
|
|
209
|
-
|
|
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
|
-
|
|
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
|
-
|
|
217
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
});
|
|
384
|
+
// Bind events if provided
|
|
385
|
+
if (onEventsCurrent) {
|
|
386
|
+
bindEvents(rawChart, onEventsCurrent);
|
|
235
387
|
}
|
|
236
388
|
setChart(rawChart);
|
|
237
|
-
|
|
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(
|
|
462
|
+
});
|
|
463
|
+
var index = react.memo(HeatmapChart);
|
|
265
464
|
|
|
266
465
|
exports.HeatmapChart = index;
|