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.
@@ -0,0 +1,400 @@
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 d3 = _interopRequireWildcard(require("d3"));
14
+ var _constants = require("../../constants");
15
+ var _intl = _interopRequireDefault(require("../../intl"));
16
+ var _utils = require("../../utils");
17
+ var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
18
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
19
+ class Area 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
+ let {
46
+ result: data,
47
+ customRender
48
+ } = this.props;
49
+ data = _utils.BaseUtils.formatEmptyName(data, '', _intl.default.get('Empty'));
50
+ if (!Array.isArray(data)) return;
51
+ this.draw(data);
52
+ (0, _utils.isFunction)(customRender) && customRender(this.chart);
53
+ this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
54
+ };
55
+ this.draw = data => {
56
+ const {
57
+ chart,
58
+ globalTheme,
59
+ tables
60
+ } = this.props;
61
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
62
+ const {
63
+ display_goal_line,
64
+ goal_label,
65
+ goal_value
66
+ } = chart.style_config || {};
67
+ const {
68
+ y_axis_summary_type,
69
+ y_axis_column_key,
70
+ y_axis_summary_column_key,
71
+ line_type,
72
+ y_axis_show_value,
73
+ label_font_size,
74
+ table_id,
75
+ y_axis_auto_range,
76
+ y_axis_min,
77
+ y_axis_max
78
+ } = chart.config;
79
+ const {
80
+ width: chartWidth,
81
+ height: chartHeight,
82
+ insertPadding,
83
+ marginTop
84
+ } = this.chartBoundingClientRect;
85
+ const tooltipTitle = this.getTitle(tables, table_id, y_axis_summary_type, y_axis_column_key || y_axis_summary_column_key);
86
+
87
+ // Y axis
88
+ const niceEnd = d3.nice(0, d3.max(data, d => d.value), 5)[1];
89
+ const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, niceEnd] : [y_axis_min || 0, y_axis_max || niceEnd]).range([chartHeight - insertPadding, insertPadding + marginTop]);
90
+ 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));
91
+
92
+ // X axis
93
+ const xDomain = data.map(item => item.name);
94
+ const x = d3.scaleBand().domain(xDomain).range([insertPadding + this.horizontalOverflowOffset, chartWidth - insertPadding]).paddingInner(0.4).paddingOuter(0.1);
95
+ this.ticksWrapper = this.chart.append('g').attr('transform', "translate(0, ".concat(chartHeight - insertPadding, ")")).call(d3.axisBottom(x).tickSizeOuter(0).tickSizeInner(5)).call(g => {
96
+ this.ticksAddName(g);
97
+ g.selectAll('.domain').attr('stroke', theme.XAxisColor);
98
+ g.selectAll('.tick line').attr('stroke', theme.XAxisColor);
99
+ g.selectAll('text').attr('font-size', theme.fontSize);
100
+ g.selectAll('text').attr('fill', theme.textColor);
101
+ this.checkTickOverlap(g);
102
+ });
103
+ const rectsWrapper = this.chart.append('g').attr('class', "rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id));
104
+
105
+ // Line
106
+ const circleData = xDomain.map(() => ({}));
107
+ const line = d3.line().x((d, index) => {
108
+ const xVal = x(d.name) + x.bandwidth() / 2;
109
+ circleData[index]['x'] = xVal;
110
+ circleData[index]['name'] = d.name;
111
+ return xVal;
112
+ }).y((d, index) => {
113
+ const yVal = y(d.value);
114
+ circleData[index]['y'] = yVal;
115
+ circleData[index]['value'] = d.value;
116
+ return yVal;
117
+ }).curve(line_type === _constants.CHART_LINE_TYPES[1] ? d3.curveBumpX : d3.curveLinear);
118
+ this.Line = rectsWrapper.append('path').attr('fill', 'none').attr('stroke', this.getAreaColor()).attr('stroke-width', 2).attr('d', () => line(data));
119
+
120
+ // Area
121
+ const area = d3.area().x(d => {
122
+ const xVal = x(d.name) + x.bandwidth() / 2;
123
+ return xVal;
124
+ }).y0(y(0)).y1(d => y(d.value)).curve(line_type === _constants.CHART_LINE_TYPES[1] ? d3.curveBumpX : d3.curveLinear);
125
+ this.Area = rectsWrapper.append('path').attr('fill', this.getAreaColor()).attr('d', () => area(data)).attr('opacity', '0.3');
126
+
127
+ // circle
128
+ circleData.forEach(item => {
129
+ rectsWrapper.append('circle').attr('cx', item.x).attr('cy', item.y).attr('r', 3).attr('fill', this.getAreaColor()).attr('opacity', y_axis_show_value ? 1 : 0).attr('data-text', item.value).attr('data-name', item.name).call(g => {
130
+ // circle label
131
+ if (y_axis_show_value) {
132
+ const curCircleEl = g.node();
133
+ rectsWrapper.append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(curCircleEl.getAttribute('data-text')).call(g => {
134
+ const {
135
+ width
136
+ } = g.node().getBoundingClientRect();
137
+ const translateX = Number(curCircleEl.getAttribute('cx')) - width / 2;
138
+ const translateY = Number(curCircleEl.getAttribute('cy')) - 10;
139
+ g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
140
+ });
141
+ }
142
+ }).on('click', (event, data) => {
143
+ this.props.toggleRecords(data);
144
+ });
145
+ });
146
+ this.chart.on('mouseover', event => {
147
+ this.updateCircleAndTickStyle({
148
+ event,
149
+ state: 'zoomIn',
150
+ circleData,
151
+ rectsWrapper,
152
+ eventState: 'over',
153
+ tooltipTitle
154
+ });
155
+ }).on('mousemove', event => {
156
+ this.updateCircleAndTickStyle({
157
+ event,
158
+ state: 'zoomIn',
159
+ circleData,
160
+ rectsWrapper,
161
+ eventState: 'move',
162
+ tooltipTitle
163
+ });
164
+ }).on('mouseleave', event => {
165
+ this.updateCircleAndTickStyle({
166
+ event,
167
+ state: 'zoomOut',
168
+ circleData,
169
+ rectsWrapper,
170
+ eventState: 'leave',
171
+ tooltipTitle
172
+ });
173
+ });
174
+ if (display_goal_line && goal_label && goal_value) {
175
+ this.setDispalyGoalLine(goal_label, goal_value, insertPadding, y);
176
+ }
177
+ };
178
+ this.updateCircleAndTickStyle = _ref => {
179
+ var _rectsWrapper$selectA, _this$ticksWrapper$se;
180
+ let {
181
+ event,
182
+ state,
183
+ circleData,
184
+ rectsWrapper,
185
+ eventState,
186
+ tooltipTitle
187
+ } = _ref;
188
+ const {
189
+ y_axis_show_value
190
+ } = this.props.chart.config;
191
+ const {
192
+ height: chartHeight,
193
+ insertPadding,
194
+ marginTop
195
+ } = this.chartBoundingClientRect;
196
+ const {
197
+ offsetX
198
+ } = event;
199
+ const minDistanceItem = this.getMinDistanceItem(offsetX, circleData);
200
+ const circleList = (_rectsWrapper$selectA = rectsWrapper.selectAll('circle')) === null || _rectsWrapper$selectA === void 0 ? void 0 : _rectsWrapper$selectA.nodes();
201
+ if (circleList.length !== 0) {
202
+ if (state === 'zoomIn') {
203
+ circleList.forEach(circle => {
204
+ const name = circle.getAttribute('data-name');
205
+ if (name === minDistanceItem.name) {
206
+ d3.select(circle).attr('opacity', 1);
207
+ d3.select(circle).attr('r', 5);
208
+ } else {
209
+ d3.select(circle).attr('opacity', 0.3);
210
+ d3.select(circle).attr('r', 3);
211
+ }
212
+ });
213
+ this.Area.attr('opacity', 0.1);
214
+ this.Line.attr('opacity', 0.3);
215
+ } else {
216
+ circleList.forEach(circle => {
217
+ if (!y_axis_show_value) {
218
+ d3.select(circle).attr('opacity', 0);
219
+ } else {
220
+ d3.select(circle).attr('opacity', 1);
221
+ }
222
+ d3.select(circle).attr('r', 3);
223
+ });
224
+ this.Area.attr('opacity', 0.3);
225
+ this.Line.attr('opacity', 1);
226
+ }
227
+ }
228
+ const ticks = (_this$ticksWrapper$se = this.ticksWrapper.selectAll('.tick line')) === null || _this$ticksWrapper$se === void 0 ? void 0 : _this$ticksWrapper$se.nodes();
229
+ if (ticks.length !== 0) {
230
+ if (state === 'zoomIn') {
231
+ ticks.forEach(tick => {
232
+ const name = tick.getAttribute('data-name');
233
+ if (name === minDistanceItem.name) {
234
+ d3.select(tick).attr('y2', -(chartHeight - insertPadding * 2 - marginTop));
235
+ } else {
236
+ d3.select(tick).attr('y2', 0);
237
+ }
238
+ });
239
+ } else {
240
+ ticks.forEach(tick => {
241
+ d3.select(tick).attr('y2', 0);
242
+ });
243
+ }
244
+ }
245
+
246
+ // tooltip
247
+ if (eventState === 'over') {
248
+ this.showTooltip(event, minDistanceItem, tooltipTitle);
249
+ }
250
+ if (eventState === 'move') {
251
+ this.moveTooltip(event, minDistanceItem, tooltipTitle);
252
+ }
253
+ if (eventState === 'leave') {
254
+ this.hiddenTooltip();
255
+ }
256
+ };
257
+ this.showTooltip = (event, data, title) => {
258
+ const {
259
+ offsetX,
260
+ offsetY
261
+ } = event;
262
+ const {
263
+ chart,
264
+ summaryColumn
265
+ } = this.props;
266
+ const {
267
+ y_axis_summary_method
268
+ } = chart.config;
269
+ const newTooltipData = {
270
+ title: title,
271
+ items: [{
272
+ color: this.getAreaColor(),
273
+ name: data.name,
274
+ value: _utils.BaseUtils.getSummaryValueDisplayString(summaryColumn, data.value, y_axis_summary_method)
275
+ }]
276
+ };
277
+ this.setState({
278
+ tooltipData: newTooltipData
279
+ });
280
+ this.setState({
281
+ toolTipPosition: {
282
+ offsetX,
283
+ offsetY
284
+ }
285
+ });
286
+ };
287
+ this.moveTooltip = (event, data, title) => {
288
+ const {
289
+ offsetX,
290
+ offsetY
291
+ } = event;
292
+ const {
293
+ chart,
294
+ summaryColumn
295
+ } = this.props;
296
+ const {
297
+ y_axis_summary_method
298
+ } = chart.config;
299
+ const newTooltipData = {
300
+ title: title,
301
+ items: [{
302
+ color: this.getAreaColor(),
303
+ name: data.name,
304
+ value: _utils.BaseUtils.getSummaryValueDisplayString(summaryColumn, data.value, y_axis_summary_method)
305
+ }]
306
+ };
307
+ this.setState({
308
+ tooltipData: newTooltipData
309
+ });
310
+ this.setState({
311
+ toolTipPosition: {
312
+ offsetX,
313
+ offsetY
314
+ }
315
+ });
316
+ };
317
+ this.hiddenTooltip = event => {
318
+ this.setState({
319
+ toolTipPosition: null
320
+ });
321
+ };
322
+ this.getAreaColor = () => {
323
+ const {
324
+ chart,
325
+ chartColorTheme
326
+ } = this.props;
327
+ const {
328
+ y_axis_label_color,
329
+ color_option
330
+ } = chart.config;
331
+ let chartBarColor = _constants.CHART_STYLE_COLORS[0];
332
+ if (chartColorTheme) {
333
+ chartBarColor = _utils.BaseUtils.getCurrentTheme(chartColorTheme).colors[0];
334
+ }
335
+ if (color_option === _constants.TYPE_COLOR_USING.USE_SPECIFIC_COLORS && y_axis_label_color) {
336
+ chartBarColor = y_axis_label_color;
337
+ }
338
+ return chartBarColor;
339
+ };
340
+ this.chart = null;
341
+ this.state = {
342
+ tooltipData: null,
343
+ toolTipPosition: null
344
+ };
345
+ }
346
+ componentDidMount() {
347
+ this.createChart();
348
+ this.drawChart();
349
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
350
+ window.addEventListener('resize', this.debouncedHandleResize);
351
+ super.componentDidMount();
352
+ }
353
+ componentDidUpdate(prevProps) {
354
+ super.componentDidUpdate(prevProps);
355
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
356
+ this.chart.node() && this.chart.node().remove();
357
+ this.createChart();
358
+ this.drawChart();
359
+ }
360
+ }
361
+ componentWillUnmount() {
362
+ this.chart.node() && this.chart.node().remove();
363
+ window.removeEventListener('resize', this.debouncedHandleResize);
364
+ super.componentWillUnmount();
365
+ }
366
+ render() {
367
+ const {
368
+ chart
369
+ } = this.props;
370
+ const {
371
+ tooltipData,
372
+ toolTipPosition
373
+ } = this.state;
374
+ return /*#__PURE__*/_react.default.createElement("div", {
375
+ ref: ref => this.container = ref,
376
+ className: (0, _classnames.default)('sea-chart-container', {
377
+ 'show-x-axis-label': this.isShowXAxisLabel(chart),
378
+ 'show-y-axis-label': this.isShowYAxisLabel(chart)
379
+ })
380
+ }, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
381
+ tooltipData: tooltipData,
382
+ toolTipPosition: toolTipPosition,
383
+ chart: this.chart
384
+ }));
385
+ }
386
+ }
387
+ Area.propTypes = {
388
+ canvasStyle: _propTypes.default.object,
389
+ chart: _propTypes.default.object,
390
+ groupbyColumn: _propTypes.default.object,
391
+ columnGroupbyColumn: _propTypes.default.object,
392
+ summaryColumn: _propTypes.default.object,
393
+ result: _propTypes.default.array,
394
+ tables: _propTypes.default.array,
395
+ globalTheme: _propTypes.default.string,
396
+ chartColorTheme: _propTypes.default.string,
397
+ toggleRecords: _propTypes.default.func,
398
+ customRender: _propTypes.default.func
399
+ };
400
+ var _default = exports.default = Area;
@@ -605,6 +605,7 @@ class ChartComponent extends _react.Component {
605
605
  legendItemMargin: 20,
606
606
  legendRecTextGap: 8,
607
607
  legendPageNavWrapperWidth: 100,
608
+ legendPageNavWrapperHeight: 18,
608
609
  legendPosition,
609
610
  legendName,
610
611
  theme
@@ -616,7 +617,8 @@ class ChartComponent extends _react.Component {
616
617
  }
617
618
  const {
618
619
  width: chartWidth,
619
- insertPadding
620
+ insertPadding,
621
+ rightLegendSpace
620
622
  } = this.chartBoundingClientRect;
621
623
  const groupsData = this.getLegendDataGroups(legendData);
622
624
  const legendWrapper = this.chart.append('g').attr('class', "legend-wrapper-".concat((_this$chart$node = this.chart.node()) === null || _this$chart$node === void 0 ? void 0 : _this$chart$node.id));
@@ -632,7 +634,8 @@ class ChartComponent extends _react.Component {
632
634
  // Render Page navigator
633
635
  if (groupsData.length > 1) {
634
636
  const {
635
- legendPageNavWrapperWidth
637
+ legendPageNavWrapperWidth,
638
+ legendItemMargin
636
639
  } = this.legendConfig;
637
640
  let curCount = 0;
638
641
  const pageNavigator = legendWrapper.append('g').attr('class', 'legend-flip-page');
@@ -671,6 +674,7 @@ class ChartComponent extends _react.Component {
671
674
  // update pageNavigator transform
672
675
  pageNavigator.call(g => {
673
676
  let groupTranslateX = 0;
677
+ let groupTranslateY = 0;
674
678
  if (legendPosition === 'top-right') {
675
679
  groupTranslateX = insertPadding;
676
680
  } else if (legendPosition === 'top-left') {
@@ -680,8 +684,14 @@ class ChartComponent extends _react.Component {
680
684
  } = g.node().getBoundingClientRect();
681
685
  const offset = legendPageNavWrapperWidth - width;
682
686
  groupTranslateX = groupTranslateX + offset;
687
+ } else if (legendPosition === 'center-right') {
688
+ groupTranslateX = chartWidth - insertPadding - rightLegendSpace;
689
+ const {
690
+ height
691
+ } = g.node().parentNode.getBoundingClientRect();
692
+ groupTranslateY = groupTranslateY + height + legendItemMargin;
683
693
  }
684
- g.attr('transform', "translate(".concat(groupTranslateX, ", 0)"));
694
+ g.attr('transform', "translate(".concat(groupTranslateX, ", ").concat(groupTranslateY, ")"));
685
695
  });
686
696
  }
687
697
  };
@@ -733,35 +743,53 @@ class ChartComponent extends _react.Component {
733
743
  const parentNode = rect.parentNode;
734
744
  d3.select(parentNode).append('text').attr('x', legendRectWidth + legendRecTextGap).attr('fill', theme.legendTextColor).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(rect.dataset.text)).attr('data-text', rect.dataset.text).attr('dominant-baseline', 'hanging');
735
745
  });
736
- // update g translateX
737
746
  const legendItems = Array.from(legendWrapper.node().children).filter(item => item.getAttribute('class') !== 'legend-flip-page');
738
747
  const {
739
748
  start,
740
- end
749
+ end,
750
+ top,
751
+ bottom
741
752
  } = this.getLegendBoundary(legendPosition);
742
- legendItems.forEach((item, index) => {
743
- let translateX = start;
744
- const prevItem = legendItems[index - 1];
745
- if (index > 0) {
746
- const {
747
- width
748
- } = prevItem.getBoundingClientRect();
749
- const prevTranslateX = Number(prevItem.getAttribute('data-translateX'));
750
- translateX = prevTranslateX + width + legendItemMargin;
751
- }
752
- d3.select(item).attr('transform', "translate(".concat(translateX, ",0)")).attr('data-translateX', translateX);
753
+ if (top && bottom) {
754
+ // update g translateY
755
+ legendItems.forEach((item, index) => {
756
+ let translateY = top;
757
+ const prevItem = legendItems[index - 1];
758
+ if (index > 0) {
759
+ const {
760
+ height
761
+ } = prevItem.getBoundingClientRect();
762
+ const prevTranslateY = Number(prevItem.getAttribute('data-translateY'));
763
+ translateY = prevTranslateY + height + legendItemMargin;
764
+ }
765
+ d3.select(item).attr('transform', "translate(".concat(start, ",").concat(translateY, ")")).attr('data-translateY', translateY);
766
+ });
767
+ } else {
768
+ // update g translateX
769
+ legendItems.forEach((item, index) => {
770
+ let translateX = start;
771
+ const prevItem = legendItems[index - 1];
772
+ if (index > 0) {
773
+ const {
774
+ width
775
+ } = prevItem.getBoundingClientRect();
776
+ const prevTranslateX = Number(prevItem.getAttribute('data-translateX'));
777
+ translateX = prevTranslateX + width + legendItemMargin;
778
+ }
779
+ d3.select(item).attr('transform', "translate(".concat(translateX, ",0)")).attr('data-translateX', translateX);
753
780
 
754
- // legend items add offset
755
- if (legendPosition === 'top-right') {
756
- d3.select(item).attr('opacity', 0);
757
- // Execute only once
758
- if (index === legendItems.length - 1) {
759
- queueMicrotask(() => {
760
- this.setLegendItemOffset(legendItems, end);
761
- });
781
+ // legend items add offset
782
+ if (legendPosition === 'top-right') {
783
+ d3.select(item).attr('opacity', 0);
784
+ // Execute only once
785
+ if (index === legendItems.length - 1) {
786
+ queueMicrotask(() => {
787
+ this.setLegendItemOffset(legendItems, end);
788
+ });
789
+ }
762
790
  }
763
- }
764
- });
791
+ });
792
+ }
765
793
  });
766
794
  };
767
795
  this.getLegendDataGroups = legendData => {
@@ -780,43 +808,77 @@ class ChartComponent extends _react.Component {
780
808
  } = this.legendConfig;
781
809
  const {
782
810
  start,
783
- end
811
+ end,
812
+ top,
813
+ bottom
784
814
  } = this.getLegendBoundary(legendPosition);
785
- let allWidth = start;
786
- const groupsData = [];
787
- const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
788
- let lastIndex = 0;
789
- legendData.forEach((item, index) => {
790
- const virtualLegend = this.chart.append('g').attr('opacity', 0);
791
- virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
792
- virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
793
- const {
794
- width
795
- } = virtualLegend.node().getBoundingClientRect();
796
- const itemWidth = index === legendData.length - 1 ? width : width + legendItemMargin; // last item no used margin
797
- allWidth = allWidth + itemWidth;
798
- if (allWidth > end) {
799
- groupsData.push(newLegendData.slice(0, index - lastIndex));
800
- newLegendData.splice(0, index - lastIndex);
801
- lastIndex = index;
802
- allWidth = start + itemWidth;
803
- }
804
- virtualLegend.remove();
805
- });
806
- const restLegendItems = newLegendData.slice(0);
807
- restLegendItems.length !== 0 && groupsData.push(restLegendItems);
808
- return groupsData;
815
+ if (top && bottom) {
816
+ let allHeight = top;
817
+ const groupsData = [];
818
+ const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
819
+ let lastIndex = 0;
820
+ legendData.forEach((item, index) => {
821
+ const virtualLegend = this.chart.append('g').attr('opacity', 0);
822
+ virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
823
+ virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
824
+ const {
825
+ height
826
+ } = virtualLegend.node().getBoundingClientRect();
827
+ const itemHeight = index === legendData.length - 1 ? height : height + legendItemMargin; // last item no used margin
828
+ allHeight = allHeight + itemHeight;
829
+ if (allHeight > bottom) {
830
+ groupsData.push(newLegendData.slice(0, index - lastIndex));
831
+ newLegendData.splice(0, index - lastIndex);
832
+ lastIndex = index;
833
+ allHeight = top + itemHeight;
834
+ }
835
+ virtualLegend.remove();
836
+ });
837
+ const restLegendItems = newLegendData.slice(0);
838
+ restLegendItems.length !== 0 && groupsData.push(restLegendItems);
839
+ return groupsData;
840
+ } else {
841
+ let allWidth = start;
842
+ const groupsData = [];
843
+ const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
844
+ let lastIndex = 0;
845
+ legendData.forEach((item, index) => {
846
+ const virtualLegend = this.chart.append('g').attr('opacity', 0);
847
+ virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
848
+ virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
849
+ const {
850
+ width
851
+ } = virtualLegend.node().getBoundingClientRect();
852
+ const itemWidth = index === legendData.length - 1 ? width : width + legendItemMargin; // last item no used margin
853
+ allWidth = allWidth + itemWidth;
854
+ if (allWidth > end) {
855
+ groupsData.push(newLegendData.slice(0, index - lastIndex));
856
+ newLegendData.splice(0, index - lastIndex);
857
+ lastIndex = index;
858
+ allWidth = start + itemWidth;
859
+ }
860
+ virtualLegend.remove();
861
+ });
862
+ const restLegendItems = newLegendData.slice(0);
863
+ restLegendItems.length !== 0 && groupsData.push(restLegendItems);
864
+ return groupsData;
865
+ }
809
866
  };
810
867
  this.getLegendBoundary = legendPosition => {
811
868
  const {
812
- legendPageNavWrapperWidth
869
+ legendPageNavWrapperWidth,
870
+ legendPageNavWrapperHeight
813
871
  } = this.legendConfig;
814
872
  const {
815
873
  width: chartWidth,
816
- insertPadding
874
+ height: chartHeight,
875
+ insertPadding,
876
+ rightLegendSpace
817
877
  } = this.chartBoundingClientRect;
818
878
  let start = 0;
819
879
  let end = 0;
880
+ let top = 0;
881
+ let bottom = 0;
820
882
  if (legendPosition === 'top-left') {
821
883
  start = insertPadding;
822
884
  end = chartWidth - insertPadding - legendPageNavWrapperWidth;
@@ -825,9 +887,17 @@ class ChartComponent extends _react.Component {
825
887
  start = insertPadding + legendPageNavWrapperWidth;
826
888
  end = chartWidth - insertPadding;
827
889
  }
890
+ if (legendPosition === 'center-right') {
891
+ start = chartWidth - insertPadding - rightLegendSpace;
892
+ end = chartWidth - insertPadding;
893
+ top = insertPadding;
894
+ bottom = chartHeight - insertPadding - legendPageNavWrapperHeight;
895
+ }
828
896
  return {
829
897
  start,
830
- end
898
+ end,
899
+ top,
900
+ bottom
831
901
  };
832
902
  };
833
903
  this.handleNavigatorOpacity = (navigator, text) => {