sea-chart 2.0.15 → 2.0.16

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.
@@ -69,7 +69,7 @@ const ToolTip = _ref => {
69
69
  style: {
70
70
  transform: "translate(".concat(position.offsetX, "px, ").concat(position.offsetY, "px)")
71
71
  }
72
- }, /*#__PURE__*/_react.default.createElement("div", {
72
+ }, title && /*#__PURE__*/_react.default.createElement("div", {
73
73
  className: "sea-chart-d3-tooltip-title"
74
74
  }, title), /*#__PURE__*/_react.default.createElement("ul", {
75
75
  className: "sea-chart-d3-tooltip-list"
@@ -69,7 +69,7 @@ const TypesDialog = _ref => {
69
69
  }, [onChange, selectedType, onToggle]);
70
70
  const handleFilterTypes = (0, _react.useCallback)(() => {
71
71
  if (hideTypeToggle) {
72
- const newChartTypes = _constants.CHART_TYPES.filter(item => ['Histogram', 'Bar_chart', 'Line_chart'].includes(item.name));
72
+ const newChartTypes = _constants.CHART_TYPES.filter(item => ['Histogram', 'Bar_chart', 'Line_chart', 'Area', 'Pie_chart'].includes(item.name));
73
73
  return newChartTypes;
74
74
  }
75
75
  return _constants.CHART_TYPES;
@@ -0,0 +1,423 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _propTypes = _interopRequireDefault(require("prop-types"));
10
+ var _react = _interopRequireDefault(require("react"));
11
+ var _classnames = _interopRequireDefault(require("classnames"));
12
+ var _lodashEs = require("lodash-es");
13
+ var _dtableUtils = require("dtable-utils");
14
+ var d3 = _interopRequireWildcard(require("d3"));
15
+ var _constants = require("../../constants");
16
+ var _colorRules = require("../../constants/color-rules");
17
+ var _intl = _interopRequireDefault(require("../../intl"));
18
+ var _utils = require("../../utils");
19
+ var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
20
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
21
+ class AreaGroup extends _chartComponent.default {
22
+ constructor(props) {
23
+ super(props);
24
+ this.handleResize = () => {
25
+ this.chart.node() && this.chart.node().remove();
26
+ this.createChart();
27
+ this.drawChart();
28
+ };
29
+ this.createChart = () => {
30
+ const {
31
+ chart
32
+ } = this.props;
33
+ const {
34
+ y_axis_show_label,
35
+ x_axis_show_label,
36
+ y_axis_show_value
37
+ } = chart.config;
38
+ const initConfig = {
39
+ insertPadding: 30,
40
+ marginLeft: y_axis_show_label ? 20 : 0,
41
+ marginBottom: x_axis_show_label ? 20 : 0,
42
+ marginTop: y_axis_show_value ? 15 : 0
43
+ };
44
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
45
+ };
46
+ this.drawChart = () => {
47
+ let {
48
+ result: data,
49
+ customRender
50
+ } = this.props;
51
+ data = _utils.BaseUtils.formatEmptyName(data, '', _intl.default.get('Empty'));
52
+ if (!Array.isArray(data)) return;
53
+ this.draw(data);
54
+ (0, _utils.isFunction)(customRender) && customRender(this.chart);
55
+ this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
56
+ };
57
+ this.draw = data => {
58
+ const {
59
+ chart,
60
+ globalTheme,
61
+ tables,
62
+ columnGroupbyColumn,
63
+ chartColorTheme
64
+ } = this.props;
65
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
66
+ const {
67
+ display_goal_line,
68
+ goal_label,
69
+ goal_value
70
+ } = chart.style_config || {};
71
+ const {
72
+ y_axis_summary_type,
73
+ y_axis_column_key,
74
+ y_axis_summary_column_key,
75
+ line_type,
76
+ y_axis_show_value,
77
+ label_font_size,
78
+ table_id,
79
+ y_axis_auto_range,
80
+ y_axis_min,
81
+ y_axis_max,
82
+ color_theme
83
+ } = chart.config;
84
+ const {
85
+ width: chartWidth,
86
+ height: chartHeight,
87
+ insertPadding,
88
+ marginTop
89
+ } = this.chartBoundingClientRect;
90
+ const useSingleSelectColumnColor = (columnGroupbyColumn === null || columnGroupbyColumn === void 0 ? void 0 : columnGroupbyColumn.type) === _dtableUtils.CellType.SINGLE_SELECT && color_theme === _colorRules.SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
91
+ useSingleSelectColumnColor ? this.setSingleSelectColorMap(data) : this.setColorMap(data, chartColorTheme);
92
+ const tooltipTitle = this.getTitle(tables, table_id, y_axis_summary_type, y_axis_column_key || y_axis_summary_column_key);
93
+
94
+ // Y axis
95
+ const niceEnd = d3.nice(0, d3.max(data, d => d.value), 5)[1];
96
+ const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, niceEnd] : [y_axis_min || 0, y_axis_max || niceEnd]).range([chartHeight - insertPadding, insertPadding + marginTop]);
97
+ this.chart.append('g').attr('transform', "translate(".concat(insertPadding, ", 0)")).call(d3.axisLeft(y).tickSizeInner(0).ticks(5).tickFormat(d => d)).call(g => this.drawYaxis(g, theme));
98
+
99
+ // X axis
100
+ const xDomain = data.map(item => item.name);
101
+ const x = d3.scaleBand().domain(xDomain).range([insertPadding + this.horizontalOverflowOffset, chartWidth - insertPadding]).paddingInner(0.4).paddingOuter(0.1);
102
+ this.ticksWrapper = this.chart.append('g').attr('transform', "translate(0, ".concat(chartHeight - insertPadding, ")")).call(d3.axisBottom(x).tickSizeOuter(0).tickSizeInner(5)).call(g => {
103
+ this.ticksAddName(g);
104
+ g.selectAll('.domain').attr('stroke', theme.XAxisColor);
105
+ g.selectAll('.tick line').attr('stroke', theme.XAxisColor);
106
+ g.selectAll('text').attr('font-size', theme.fontSize);
107
+ g.selectAll('text').attr('fill', theme.textColor);
108
+ this.checkTickOverlap(g);
109
+ });
110
+ const rectsWrapper = this.chart.append('g').attr('class', "rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id));
111
+ const circleDatas = [];
112
+ const groupData = d3.groups(data, d => d === null || d === void 0 ? void 0 : d.group_name);
113
+
114
+ // Line
115
+ groupData.forEach(_ref => {
116
+ let [group_name, data] = _ref;
117
+ const circleData = xDomain.map(() => ({}));
118
+ const line = d3.line().x((d, index) => {
119
+ const xVal = x(d.name) + x.bandwidth() / 2;
120
+ circleData[index]['x'] = xVal;
121
+ circleData[index]['name'] = d.name;
122
+ circleData[index]['group_name'] = group_name;
123
+ return xVal;
124
+ }).y((d, index) => {
125
+ const yVal = y(d.value);
126
+ circleData[index]['y'] = yVal;
127
+ circleData[index]['value'] = d.value;
128
+ return yVal;
129
+ }).curve(line_type === _constants.CHART_LINE_TYPES[1] ? d3.curveBumpX : d3.curveLinear);
130
+ rectsWrapper.append('path').attr('fill', 'none').attr('class', 'line').attr('stroke', this.colorMap[group_name]).attr('stroke-width', 2).attr('d', () => line(data));
131
+ circleDatas.push({
132
+ group_name,
133
+ circleData
134
+ });
135
+ });
136
+
137
+ // Area
138
+ groupData.forEach(_ref2 => {
139
+ let [group_name, data] = _ref2;
140
+ const area = d3.area().x(d => {
141
+ const xVal = x(d.name) + x.bandwidth() / 2;
142
+ return xVal;
143
+ }).y0(y(0)).y1(d => y(d.value)).curve(line_type === _constants.CHART_LINE_TYPES[1] ? d3.curveBumpX : d3.curveLinear);
144
+ rectsWrapper.append('path').attr('class', 'area').attr('fill', this.colorMap[group_name]).attr('d', () => area(data)).attr('opacity', '0.3');
145
+ });
146
+
147
+ // circle
148
+ circleDatas.forEach(_ref3 => {
149
+ let {
150
+ group_name,
151
+ circleData
152
+ } = _ref3;
153
+ circleData.forEach(item => {
154
+ rectsWrapper.append('circle').attr('cx', item.x).attr('cy', item.y).attr('r', 3).attr('fill', this.colorMap[group_name]).attr('opacity', y_axis_show_value ? 1 : 0).attr('data-text', item.value).attr('data-name', item.name).call(g => {
155
+ // circle label
156
+ if (y_axis_show_value) {
157
+ const curCircleEl = g.node();
158
+ rectsWrapper.append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(curCircleEl.getAttribute('data-text')).call(g => {
159
+ const {
160
+ width
161
+ } = g.node().getBoundingClientRect();
162
+ const translateX = Number(curCircleEl.getAttribute('cx')) - width / 2;
163
+ const translateY = Number(curCircleEl.getAttribute('cy')) - 10;
164
+ g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
165
+ });
166
+ }
167
+ }).on('click', (event, data) => {
168
+ this.props.toggleRecords(data);
169
+ });
170
+ });
171
+ });
172
+ this.chart.on('mouseover', event => {
173
+ this.updateCircleAndTickStyle({
174
+ event,
175
+ state: 'zoomIn',
176
+ circleDatas,
177
+ rectsWrapper,
178
+ eventState: 'over',
179
+ tooltipTitle
180
+ });
181
+ }).on('mousemove', event => {
182
+ this.updateCircleAndTickStyle({
183
+ event,
184
+ state: 'zoomIn',
185
+ circleDatas,
186
+ rectsWrapper,
187
+ eventState: 'move',
188
+ tooltipTitle
189
+ });
190
+ }).on('mouseleave', event => {
191
+ this.updateCircleAndTickStyle({
192
+ event,
193
+ state: 'zoomOut',
194
+ circleDatas,
195
+ rectsWrapper,
196
+ eventState: 'leave',
197
+ tooltipTitle
198
+ });
199
+ });
200
+ if (display_goal_line && goal_label && goal_value) {
201
+ this.setDispalyGoalLine(goal_label, goal_value, insertPadding, y);
202
+ }
203
+ this.setLegend({
204
+ legendName: 'group_name',
205
+ theme,
206
+ legendPosition: 'top-right',
207
+ data
208
+ });
209
+ };
210
+ this.updateCircleAndTickStyle = _ref4 => {
211
+ var _rectsWrapper$selectA, _this$ticksWrapper$se;
212
+ let {
213
+ event,
214
+ state,
215
+ circleDatas,
216
+ rectsWrapper,
217
+ eventState,
218
+ tooltipTitle
219
+ } = _ref4;
220
+ const {
221
+ y_axis_show_value
222
+ } = this.props.chart.config;
223
+ const {
224
+ height: chartHeight,
225
+ insertPadding,
226
+ marginTop
227
+ } = this.chartBoundingClientRect;
228
+ const {
229
+ offsetX
230
+ } = event;
231
+ const circleData = [];
232
+ circleDatas.forEach(item => {
233
+ circleData.push(...item.circleData);
234
+ });
235
+ const minDistanceItem = this.getMinDistanceItem(offsetX, circleData);
236
+ const tooltipItems = circleData.filter(item => item.name && item.name === minDistanceItem.name);
237
+ const circleList = (_rectsWrapper$selectA = rectsWrapper.selectAll('circle')) === null || _rectsWrapper$selectA === void 0 ? void 0 : _rectsWrapper$selectA.nodes();
238
+ if (circleList.length !== 0) {
239
+ if (state === 'zoomIn') {
240
+ circleList.forEach(circle => {
241
+ const name = circle.getAttribute('data-name');
242
+ if (name === minDistanceItem.name) {
243
+ d3.select(circle).attr('opacity', 1);
244
+ d3.select(circle).attr('r', 5);
245
+ } else {
246
+ d3.select(circle).attr('opacity', 0.3);
247
+ d3.select(circle).attr('r', 3);
248
+ }
249
+ });
250
+ rectsWrapper.selectAll('.area').attr('opacity', 0.1);
251
+ rectsWrapper.selectAll('.line').attr('opacity', 0.3);
252
+ } else {
253
+ circleList.forEach(circle => {
254
+ if (!y_axis_show_value) {
255
+ d3.select(circle).attr('opacity', 0);
256
+ } else {
257
+ d3.select(circle).attr('opacity', 1);
258
+ }
259
+ d3.select(circle).attr('r', 3);
260
+ });
261
+ rectsWrapper.selectAll('.area').attr('opacity', 0.3);
262
+ rectsWrapper.selectAll('.line').attr('opacity', 1);
263
+ }
264
+ }
265
+ const ticks = (_this$ticksWrapper$se = this.ticksWrapper.selectAll('.tick line')) === null || _this$ticksWrapper$se === void 0 ? void 0 : _this$ticksWrapper$se.nodes();
266
+ if (ticks.length !== 0) {
267
+ if (state === 'zoomIn') {
268
+ ticks.forEach(tick => {
269
+ const name = tick.getAttribute('data-name');
270
+ if (name === minDistanceItem.name) {
271
+ d3.select(tick).attr('y2', -(chartHeight - insertPadding * 2 - marginTop));
272
+ } else {
273
+ d3.select(tick).attr('y2', 0);
274
+ }
275
+ });
276
+ } else {
277
+ ticks.forEach(tick => {
278
+ d3.select(tick).attr('y2', 0);
279
+ });
280
+ }
281
+ }
282
+
283
+ // tooltip
284
+ if (eventState === 'over') {
285
+ this.showTooltip(event, tooltipItems, tooltipTitle);
286
+ }
287
+ if (eventState === 'move') {
288
+ this.moveTooltip(event, tooltipItems, tooltipTitle);
289
+ }
290
+ if (eventState === 'leave') {
291
+ this.hiddenTooltip();
292
+ }
293
+ };
294
+ this.showTooltip = (event, data, title) => {
295
+ const {
296
+ offsetX,
297
+ offsetY
298
+ } = event;
299
+ const {
300
+ chart,
301
+ summaryColumn
302
+ } = this.props;
303
+ const {
304
+ y_axis_summary_method
305
+ } = chart.config;
306
+ const newTooltipData = {
307
+ title: title,
308
+ items: data.map(item => {
309
+ return {
310
+ color: this.colorMap[item.group_name],
311
+ name: item.group_name,
312
+ value: _utils.BaseUtils.getSummaryValueDisplayString(summaryColumn, item.value, y_axis_summary_method)
313
+ };
314
+ })
315
+ };
316
+ this.setState({
317
+ tooltipData: newTooltipData
318
+ });
319
+ this.setState({
320
+ toolTipPosition: {
321
+ offsetX,
322
+ offsetY
323
+ }
324
+ });
325
+ };
326
+ this.moveTooltip = (event, data, title) => {
327
+ const {
328
+ offsetX,
329
+ offsetY
330
+ } = event;
331
+ const {
332
+ chart,
333
+ summaryColumn
334
+ } = this.props;
335
+ const {
336
+ y_axis_summary_method
337
+ } = chart.config;
338
+ const newTooltipData = {
339
+ title: title,
340
+ items: data.map(item => {
341
+ return {
342
+ color: this.colorMap[item.group_name],
343
+ name: item.group_name,
344
+ value: _utils.BaseUtils.getSummaryValueDisplayString(summaryColumn, item.value, y_axis_summary_method)
345
+ };
346
+ })
347
+ };
348
+ this.setState({
349
+ tooltipData: newTooltipData
350
+ });
351
+ this.setState({
352
+ toolTipPosition: {
353
+ offsetX,
354
+ offsetY
355
+ }
356
+ });
357
+ };
358
+ this.hiddenTooltip = event => {
359
+ this.setState({
360
+ toolTipPosition: null
361
+ });
362
+ };
363
+ this.chart = null;
364
+ this.state = {
365
+ tooltipData: null,
366
+ toolTipPosition: null
367
+ };
368
+ }
369
+ componentDidMount() {
370
+ this.createChart();
371
+ this.drawChart();
372
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
373
+ window.addEventListener('resize', this.debouncedHandleResize);
374
+ super.componentDidMount();
375
+ }
376
+ componentDidUpdate(prevProps) {
377
+ super.componentDidUpdate(prevProps);
378
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
379
+ this.chart.node() && this.chart.node().remove();
380
+ this.createChart();
381
+ this.drawChart();
382
+ }
383
+ }
384
+ componentWillUnmount() {
385
+ this.chart.node() && this.chart.node().remove();
386
+ window.removeEventListener('resize', this.debouncedHandleResize);
387
+ super.componentWillUnmount();
388
+ }
389
+ render() {
390
+ const {
391
+ chart
392
+ } = this.props;
393
+ const {
394
+ tooltipData,
395
+ toolTipPosition
396
+ } = this.state;
397
+ return /*#__PURE__*/_react.default.createElement("div", {
398
+ ref: ref => this.container = ref,
399
+ className: (0, _classnames.default)('sea-chart-container', {
400
+ 'show-x-axis-label': this.isShowXAxisLabel(chart),
401
+ 'show-y-axis-label': this.isShowYAxisLabel(chart)
402
+ })
403
+ }, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
404
+ tooltipData: tooltipData,
405
+ toolTipPosition: toolTipPosition,
406
+ chart: this.chart
407
+ }));
408
+ }
409
+ }
410
+ AreaGroup.propTypes = {
411
+ canvasStyle: _propTypes.default.object,
412
+ chart: _propTypes.default.object,
413
+ groupbyColumn: _propTypes.default.object,
414
+ columnGroupbyColumn: _propTypes.default.object,
415
+ summaryColumn: _propTypes.default.object,
416
+ result: _propTypes.default.array,
417
+ tables: _propTypes.default.array,
418
+ globalTheme: _propTypes.default.string,
419
+ chartColorTheme: _propTypes.default.string,
420
+ toggleRecords: _propTypes.default.func,
421
+ customRender: _propTypes.default.func
422
+ };
423
+ var _default = exports.default = AreaGroup;