sea-chart 2.0.14 → 2.0.15

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