sea-chart 2.0.8 → 2.0.10

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.
@@ -13,6 +13,7 @@ var _dtableUtils = require("dtable-utils");
13
13
  var _utils = require("../../utils");
14
14
  var _constants = require("../../constants");
15
15
  var _intl = _interopRequireDefault(require("../../intl"));
16
+ var _columnUtils = require("../../utils/column-utils");
16
17
  require("../../assets/css/sea-chart-d3-tooltip.css");
17
18
  class ChartComponent extends _react.Component {
18
19
  constructor(props) {
@@ -51,14 +52,22 @@ class ChartComponent extends _react.Component {
51
52
  this.initChart = function (container, id) {
52
53
  let initConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
53
54
  const {
54
- width,
55
- height
55
+ width: containerWidth,
56
+ height: containerHeight
56
57
  } = container.getBoundingClientRect();
58
+ const {
59
+ marginLeft = 0,
60
+ marginBottom = 0
61
+ } = initConfig;
62
+ const width = containerWidth - marginLeft;
63
+ const height = containerHeight - marginBottom;
57
64
  _this.chart = d3.create('svg').attr('id', id).attr('class', "svg-wrapper-".concat(id)).attr('width', width).attr('height', height).attr('viewBox', [0, 0, width, height]);
58
65
  _this.container.appendChild(_this.chart.node());
59
66
  _this.chartBoundingClientRect = {
60
67
  ...JSON.parse(JSON.stringify(_this.chart.node().getBoundingClientRect())),
61
- ...initConfig
68
+ ...initConfig,
69
+ width,
70
+ height
62
71
  };
63
72
  };
64
73
  this.initDefs = () => {
@@ -70,7 +79,7 @@ class ChartComponent extends _react.Component {
70
79
  const {
71
80
  width,
72
81
  height
73
- } = this.container.getBoundingClientRect();
82
+ } = this.chartBoundingClientRect;
74
83
  this.chart.append('defs').append('mask').attr('id', "mask-wrapper-".concat(previewType, "-").concat(this.chart.node().id)).append('rect').attr('x', 0).attr('y', 0).attr('width', width).attr('height', height - 30).attr('fill', 'white');
75
84
  }
76
85
  };
@@ -216,7 +225,6 @@ class ChartComponent extends _react.Component {
216
225
  }
217
226
  };
218
227
  this.renderAxisLabel = (chart, tables, chartContainer) => {
219
- var _this$chart2;
220
228
  if (!this.chart || !chart) return;
221
229
  let {
222
230
  table_id,
@@ -237,30 +245,31 @@ class ChartComponent extends _react.Component {
237
245
  y_axis_column_key = y_axis_summary_column_key;
238
246
  }
239
247
  const table = (0, _dtableUtils.getTableById)(tables, table_id);
240
- const autoPadding = ((_this$chart2 = this.chart) === null || _this$chart2 === void 0 ? void 0 : _this$chart2.autoPadding) || {
241
- bottom: 0
242
- };
243
248
  let textColor;
244
249
  this.globalTheme === _constants.THEME_NAME_MAP.DARK ? textColor = '#fff' : textColor = '#999';
245
250
  const xAxisID = "chart-x-axis-label_".concat(chart.id);
246
251
  const xLabel = chartContainer === null || chartContainer === void 0 ? void 0 : chartContainer.querySelector("#".concat(xAxisID));
252
+ const {
253
+ width: containerWidth
254
+ } = this.chartBoundingClientRect;
247
255
  if (!xLabel && x_axis_show_label) {
248
256
  const div = document.createElement('div');
249
257
  div.id = xAxisID;
250
258
  div.className = 'chart-axis-label';
251
259
  const column = (0, _dtableUtils.getTableColumnByKey)(table, x_axis_column_key);
252
260
  div.innerHTML = "".concat(column ? column.name : '');
253
- div.setAttribute('style', "color:".concat(textColor, "; width: 100%; text-align: ").concat(x_axis_label_position, "; bottom: -20px; position: absolute"));
261
+ div.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(x_axis_label_position, "; position: absolute"));
254
262
  chartContainer.appendChild(div);
255
263
  }
256
264
  if (xLabel && x_axis_show_label) {
257
- xLabel.setAttribute('style', "color:".concat(textColor, "; width: 100%; text-align: ").concat(x_axis_label_position, "; bottom: -20px; position: absolute"));
265
+ xLabel.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(x_axis_label_position, "; position: absolute"));
258
266
  }
259
267
  if (xLabel && !x_axis_show_label) {
260
268
  xLabel.parentNode.removeChild(xLabel);
261
269
  }
262
270
  const yAxisID = "chart-y-axis-label_".concat(chart.id);
263
271
  const yLabel = chartContainer.querySelector("#".concat(yAxisID));
272
+ const divHeight = 20;
264
273
  if (!yLabel && y_axis_show_label) {
265
274
  const div = document.createElement('div');
266
275
  div.id = yAxisID;
@@ -274,24 +283,103 @@ class ChartComponent extends _react.Component {
274
283
  div.innerHTML = title_name || '';
275
284
  }
276
285
  }
277
- const containerHeight = chartContainer.offsetHeight;
286
+ const {
287
+ height: containerHeight
288
+ } = this.chartBoundingClientRect;
278
289
  let textAlign = 'center';
279
290
  if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
280
291
  if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
281
- div.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 + 12, "px, ").concat((containerHeight - autoPadding.bottom) / 2 + autoPadding.bottom / 4, "px) rotate(-90deg)"));
292
+ div.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
282
293
  chartContainer.appendChild(div);
283
294
  }
284
295
  if (yLabel && y_axis_show_label) {
285
- const containerHeight = chartContainer.offsetHeight;
296
+ const {
297
+ height: containerHeight
298
+ } = this.chartBoundingClientRect;
286
299
  let textAlign = 'center';
287
300
  if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
288
301
  if (y_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
289
- yLabel.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 + 12, "px, ").concat((containerHeight - autoPadding.bottom) / 2 + autoPadding.bottom / 4, "px) rotate(-90deg)"));
302
+ yLabel.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
290
303
  }
291
304
  if (yLabel && !y_axis_show_label) {
292
305
  yLabel.parentNode.removeChild(yLabel);
293
306
  }
294
307
  };
308
+ this.renderHorizontalLabel = (chart, tables, chartContainer) => {
309
+ if (!this.chart || !chart) return;
310
+ const {
311
+ table_id,
312
+ vertical_axis_column_key,
313
+ horizontal_axis_column_key,
314
+ horizontal_axis_summary_type,
315
+ horizontal_axis_label_position,
316
+ vertical_axis_label_position,
317
+ show_vertical_axis_label,
318
+ show_horizontal_axis_label
319
+ } = chart.config;
320
+ const table = (0, _dtableUtils.getTableById)(tables, table_id);
321
+ const textColor = '#999999';
322
+ const xAxisID = "chart-x-axis-label_".concat(chart.id);
323
+ const xLabel = chartContainer.querySelector("#".concat(xAxisID));
324
+ const {
325
+ width: containerWidth
326
+ } = this.chartBoundingClientRect;
327
+ if (!xLabel && show_horizontal_axis_label) {
328
+ const div = document.createElement('div');
329
+ div.id = xAxisID;
330
+ div.className = 'chart-axis-label';
331
+ if (horizontal_axis_summary_type === _constants.CHART_SUMMARY_TYPE.COUNT) {
332
+ div.innerHTML = _intl.default.get('Amount');
333
+ } else {
334
+ const column = (0, _dtableUtils.getTableColumnByKey)(table, horizontal_axis_column_key);
335
+ div.innerHTML = "".concat(column ? column.name : '');
336
+ }
337
+ div.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(horizontal_axis_label_position, "; position: absolute"));
338
+ chartContainer.appendChild(div);
339
+ }
340
+ if (xLabel && show_horizontal_axis_label) {
341
+ xLabel.setAttribute('style', "color:".concat(textColor, "; width: ").concat(containerWidth, "px; text-align: ").concat(horizontal_axis_label_position, "; position: absolute"));
342
+ }
343
+ if (xLabel && !show_horizontal_axis_label) {
344
+ xLabel.parentNode.removeChild(xLabel);
345
+ }
346
+ const yAxisID = "chart-y-axis-label_".concat(chart.id);
347
+ const yLabel = chartContainer.querySelector("#".concat(yAxisID));
348
+ const divHeight = 20;
349
+ if (!yLabel && show_vertical_axis_label) {
350
+ const div = document.createElement('div');
351
+ div.id = yAxisID;
352
+ div.className = 'chart-axis-label';
353
+ const column = (0, _dtableUtils.getTableColumnByKey)(table, vertical_axis_column_key) || {};
354
+ div.innerHTML = column.name || '';
355
+ const {
356
+ height: containerHeight
357
+ } = this.chartBoundingClientRect;
358
+ let textAlign = 'center';
359
+ if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
360
+ if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
361
+ div.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
362
+ chartContainer.appendChild(div);
363
+ }
364
+ if (yLabel && show_horizontal_axis_label) {
365
+ const {
366
+ height: containerHeight
367
+ } = this.chartBoundingClientRect;
368
+ let textAlign = 'center';
369
+ if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.BOTTOM) textAlign = 'left';
370
+ if (vertical_axis_label_position === _constants.LABEL_POSITION_TYPE.TOP) textAlign = 'right';
371
+ yLabel.setAttribute('style', "color:".concat(textColor, "; position: absolute; width: ").concat(containerHeight, "px; height: ").concat(divHeight, "px; text-align: ").concat(textAlign, "; top: 0; left: 0; transform: translate(-").concat(containerHeight / 2 - divHeight / 2, "px, ").concat(containerHeight / 2 - divHeight / 2, "px) rotate(-90deg)"));
372
+ }
373
+ if (yLabel && !show_horizontal_axis_label) {
374
+ yLabel.parentNode.removeChild(yLabel);
375
+ }
376
+ };
377
+ this.isShowVerticalAxisLabel = chart => {
378
+ return !!(chart && chart.config && chart.config.show_vertical_axis_label);
379
+ };
380
+ this.isShowHorizontalAxisLabel = chart => {
381
+ return !!(chart && chart.config && chart.config.show_horizontal_axis_label);
382
+ };
295
383
  // Automatic adjustment of maximum and minimum values
296
384
  this.autoAdjustDataOptions = function (chart) {
297
385
  let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
@@ -481,92 +569,290 @@ class ChartComponent extends _react.Component {
481
569
  return _intl.default.get(name) || name;
482
570
  }
483
571
  };
484
- this.getOthersLegendItemWidth = (curIndex, allLegendItems, direction) => {
485
- let width = 0;
486
- let otherItems = [];
487
- if (direction === 1) {
488
- otherItems = allLegendItems.slice(0, curIndex);
489
- }
490
- if (direction === -1) {
491
- otherItems = allLegendItems.slice(curIndex);
492
- }
493
- otherItems.forEach(item => {
494
- const {
495
- width: legendItemWidth
496
- } = item.getBoundingClientRect();
497
- width = width + legendItemWidth;
572
+ this.sortLegend = (result, groupColumn, legendName) => {
573
+ result.forEach(item => {
574
+ const option = groupColumn.data.options.find(option => option.name === item[legendName]);
575
+ if (option !== null && option !== void 0 && option.id) {
576
+ item['group_name_id'] = option.id;
577
+ item['oldName'] = item.name;
578
+ item.name = item['group_name_id'];
579
+ }
580
+ });
581
+ _utils.BaseUtils.sortCharts(result, groupColumn, 'name');
582
+ result.forEach(item => {
583
+ item.name = item['oldName'];
498
584
  });
499
- return width;
500
585
  };
501
586
  // set legend
502
- this.setLegend = function (legendName) {
587
+ this.setLegend = _ref => {
503
588
  var _this$chart$node;
504
- let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
505
- let legendPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'top-left';
506
- let data = arguments.length > 3 ? arguments[3] : undefined;
507
- if (!_this.chart) return;
589
+ let {
590
+ legendName,
591
+ theme = _constants.CHART_THEME_COLOR['light'],
592
+ legendPosition = 'top-left',
593
+ data,
594
+ colorScale,
595
+ groupColumn
596
+ } = _ref;
597
+ if (!this.chart) return;
598
+ const legendData = (0, _lodashEs.cloneDeep)(data);
599
+ this.legendConfig = {
600
+ legendRectWidth: 20,
601
+ legendRectHeight: 6,
602
+ r: 3,
603
+ legendItemPaddingTop: 3,
604
+ legendItemMargin: 20,
605
+ legendRecTextGap: 8,
606
+ legendPageNavWrapperWidth: 100,
607
+ legendPosition,
608
+ legendName,
609
+ theme
610
+ };
611
+
612
+ // sort legend data
613
+ if (groupColumn && [_dtableUtils.CellType.SINGLE_SELECT].includes(groupColumn.type)) {
614
+ this.sortLegend(legendData, groupColumn, legendName);
615
+ }
508
616
  const {
509
617
  width: chartWidth,
510
618
  insertPadding
511
- } = _this.chartBoundingClientRect;
512
- const legendItemPaddingTop = 8;
513
- const legendItemSpacing = 30;
514
- const legendRectWidth = 18;
515
- const legendRectHeight = 6;
516
- const r = 3;
517
- let translateX = 0;
518
- let legendData = [];
519
- let direction = 0; // 1 means left, -1 means right
520
- if (legendPosition === 'top-left') {
521
- translateX = insertPadding;
522
- legendData = d3.group(data, d => d[legendName]);
523
- direction = 1;
619
+ } = this.chartBoundingClientRect;
620
+ const groupsData = this.getLegendDataGroups(legendData);
621
+ 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));
622
+
623
+ // Render first group legend
624
+ this.renderLegend({
625
+ legendWrapper,
626
+ groupData: groupsData[0],
627
+ colorScale,
628
+ theme
629
+ });
630
+
631
+ // Render Page navigator
632
+ if (groupsData.length > 1) {
633
+ const {
634
+ legendPageNavWrapperWidth
635
+ } = this.legendConfig;
636
+ let curCount = 0;
637
+ const pageNavigator = legendWrapper.append('g').attr('class', 'legend-flip-page');
638
+
639
+ // count
640
+ pageNavigator.append('text').attr('class', 'legend-count').attr('dominant-baseline', 'hanging').attr('x', 15).attr('fill', theme.legendTextColor).attr('font-size', theme.legendFontSize).text("".concat(curCount + 1, "/").concat(groupsData.length));
641
+
642
+ // prev page
643
+ pageNavigator.append('polygon').attr('class', 'legend-prev-page').attr('points', this.calcEquilateralTriangle(5, 5, 12)).attr('fill', theme.legendPageNavigatorMarkerColor).attr('opacity', curCount === 0 ? 0.45 : 1).attr('style', 'cursor: pointer;').on('click', event => {
644
+ if (curCount > 0) {
645
+ curCount--;
646
+ this.renderLegend({
647
+ legendWrapper,
648
+ groupData: groupsData[curCount],
649
+ colorScale,
650
+ theme,
651
+ text: "".concat(curCount + 1, "/").concat(groupsData.length)
652
+ });
653
+ }
654
+ });
655
+
656
+ // next page
657
+ pageNavigator.append('polygon').attr('class', 'legend-next-page').attr('points', this.calcEquilateralTriangle(45, 5, 12, 'bottom')).attr('fill', theme.legendPageNavigatorMarkerColor).attr('opacity', curCount === groupsData.length - 1 ? 0.45 : 1).attr('style', 'cursor: pointer;').on('click', event => {
658
+ if (curCount < groupsData.length - 1) {
659
+ curCount++;
660
+ this.renderLegend({
661
+ legendWrapper,
662
+ groupData: groupsData[curCount],
663
+ colorScale,
664
+ theme,
665
+ text: "".concat(curCount + 1, "/").concat(groupsData.length)
666
+ });
667
+ }
668
+ });
669
+
670
+ // update pageNavigator transform
671
+ pageNavigator.call(g => {
672
+ let groupTranslateX = 0;
673
+ if (legendPosition === 'top-right') {
674
+ groupTranslateX = insertPadding;
675
+ } else if (legendPosition === 'top-left') {
676
+ groupTranslateX = chartWidth - insertPadding - legendPageNavWrapperWidth;
677
+ const {
678
+ width
679
+ } = g.node().getBoundingClientRect();
680
+ const offset = legendPageNavWrapperWidth - width;
681
+ groupTranslateX = groupTranslateX + offset;
682
+ }
683
+ g.attr('transform', "translate(".concat(groupTranslateX, ", 0)"));
684
+ });
524
685
  }
525
- if (legendPosition === 'top-right') {
526
- translateX = chartWidth;
527
- legendData = d3.group(data, d => d[legendName]);
528
- direction = -1;
529
- }
530
- _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)).attr('transform', "translate(".concat(translateX, ", 0)")).selectAll().data(legendData).join('g').append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r).attr('fill', _ref => {
531
- let [groupName] = _ref;
532
- return _this.colorMap[groupName] || _constants.CHART_STYLE_COLORS[0];
533
- }).attr('data-text', _ref2 => {
534
- let [groupName] = _ref2;
686
+ };
687
+ this.renderLegend = _ref2 => {
688
+ let {
689
+ legendWrapper,
690
+ groupData,
691
+ colorScale,
692
+ theme,
693
+ text
694
+ } = _ref2;
695
+ const {
696
+ legendItemPaddingTop,
697
+ legendRectWidth,
698
+ legendRectHeight,
699
+ r,
700
+ legendRecTextGap,
701
+ legendItemMargin,
702
+ legendPosition
703
+ } = this.legendConfig;
704
+
705
+ // clear old legends
706
+ const oldChildren = Array.from(legendWrapper.node().children);
707
+ if (oldChildren.length !== 0) {
708
+ oldChildren.forEach(item => {
709
+ // update navigator button opacity and text
710
+ if (item.getAttribute('class') == 'legend-flip-page') {
711
+ this.handleNavigatorOpacity(item, text);
712
+ d3.select(item).selectAll('text').text(text);
713
+ return;
714
+ }
715
+ // remove old legend item
716
+ d3.select(item).remove();
717
+ });
718
+ }
719
+ legendWrapper.selectAll().data(groupData).join('g').attr('data-groupName', _ref3 => {
720
+ let [groupName] = _ref3;
721
+ return groupName;
722
+ }).append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('y', legendItemPaddingTop).attr('rx', r).attr('fill', _ref4 => {
723
+ let [groupName] = _ref4;
724
+ if (colorScale) return colorScale(groupName);
725
+ return this.colorMap[groupName] || _constants.CHART_STYLE_COLORS[0];
726
+ }).attr('data-text', _ref5 => {
727
+ let [groupName] = _ref5;
535
728
  return groupName;
536
729
  }).call(g => {
537
- var _this$chart$node2;
538
- const legendWrapper = d3.selectAll(".legend-wrapper-".concat((_this$chart$node2 = _this.chart.node()) === null || _this$chart$node2 === void 0 ? void 0 : _this$chart$node2.id)).node();
539
- const legendItems = Array.from(legendWrapper.children);
540
- const legendItemCount = legendItems.length;
541
-
542
730
  // Add text
543
731
  g.nodes().forEach(rect => {
544
732
  const parentNode = rect.parentNode;
545
- let textHeight = 0;
546
- let textWidth = 0;
547
- d3.select(parentNode).append('text').attr('x', legendRectWidth).attr('width', 30).attr('fill', theme.legendTextColor).attr('font-size', theme.legendFontSize).text(_this.formatterLegendName(rect.dataset.text)).attr('data-text', rect.dataset.text).call(g => {
548
- // set text y position
733
+ 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');
734
+ });
735
+ // update g translateX
736
+ const legendItems = Array.from(legendWrapper.node().children).filter(item => item.getAttribute('class') !== 'legend-flip-page');
737
+ const {
738
+ start,
739
+ end
740
+ } = this.getLegendBoundary(legendPosition);
741
+ legendItems.forEach((item, index) => {
742
+ let translateX = start;
743
+ const lastItem = legendItems[index - 1];
744
+ if (index > 0) {
549
745
  const {
550
- height,
551
746
  width
552
- } = g.node().getBoundingClientRect();
553
- textHeight = height;
554
- textWidth = width;
555
- g.attr('y', textHeight / 2);
556
- });
557
- });
747
+ } = lastItem.getBoundingClientRect();
748
+ const prevTranslateX = Number(lastItem.getAttribute('data-translateX'));
749
+ translateX = prevTranslateX + width + legendItemMargin;
750
+ }
558
751
 
559
- // set g position
560
- legendItems.forEach((item, index) => {
561
- const otherslegendItemWidth = _this.getOthersLegendItemWidth(index, legendItems, direction);
562
- d3.select(item).attr('transform', () => {
563
- const gaps = direction === 1 ? index : legendItemCount - index;
564
- const translateX = direction * (otherslegendItemWidth + gaps * legendItemSpacing);
565
- return "translate(".concat(translateX, ", ").concat(legendItemPaddingTop, ")");
566
- });
752
+ // legend items add offset
753
+ if (legendPosition === 'top-right') {
754
+ d3.select(item).attr('opacity', 0);
755
+ if (index === legendItems.length - 1) {
756
+ queueMicrotask(() => {
757
+ this.setLegendItemOffset(legendItems, end);
758
+ });
759
+ }
760
+ }
761
+ d3.select(item).attr('transform', "translate(".concat(translateX, ",0)")).attr('data-translateX', translateX);
567
762
  });
568
763
  });
569
764
  };
765
+ this.getLegendDataGroups = legendData => {
766
+ const {
767
+ legendName,
768
+ theme,
769
+ legendPosition
770
+ } = this.legendConfig;
771
+ legendData = d3.groups(legendData, d => d[legendName]);
772
+ const {
773
+ legendItemMargin,
774
+ legendRectWidth,
775
+ legendRectHeight,
776
+ r,
777
+ legendRecTextGap
778
+ } = this.legendConfig;
779
+ const {
780
+ start,
781
+ end
782
+ } = this.getLegendBoundary(legendPosition);
783
+ let allWidth = start;
784
+ const groupsData = [];
785
+ const newLegendData = (0, _lodashEs.cloneDeep)(legendData);
786
+ legendData.forEach((item, index) => {
787
+ const virtualLegend = this.chart.append('g').attr('opacity', 0);
788
+ virtualLegend.append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('rx', r);
789
+ virtualLegend.append('text').attr('x', legendRectWidth + legendRecTextGap).attr('font-size', theme.legendFontSize).text(this.formatterLegendName(item[0]));
790
+ const {
791
+ width
792
+ } = virtualLegend.node().getBoundingClientRect();
793
+ const itemWidth = index === legendData.length - 1 ? width : width + legendItemMargin; // last item no used margin
794
+ allWidth = allWidth + itemWidth;
795
+ if (allWidth >= end) {
796
+ groupsData.push(newLegendData.slice(0, index));
797
+ newLegendData.splice(0, index);
798
+ allWidth = 0;
799
+ }
800
+ virtualLegend.remove();
801
+ });
802
+ const restLegendItems = newLegendData.slice(0);
803
+ groupsData.push(restLegendItems);
804
+ return groupsData;
805
+ };
806
+ this.getLegendBoundary = legendPosition => {
807
+ const {
808
+ legendPageNavWrapperWidth
809
+ } = this.legendConfig;
810
+ const {
811
+ width: chartWidth,
812
+ insertPadding
813
+ } = this.chartBoundingClientRect;
814
+ let start = 0;
815
+ let end = 0;
816
+ if (legendPosition === 'top-left') {
817
+ start = insertPadding;
818
+ end = chartWidth - insertPadding - legendPageNavWrapperWidth;
819
+ }
820
+ if (legendPosition === 'top-right') {
821
+ start = insertPadding + legendPageNavWrapperWidth;
822
+ end = chartWidth - insertPadding;
823
+ }
824
+ return {
825
+ start,
826
+ end
827
+ };
828
+ };
829
+ this.handleNavigatorOpacity = (navigator, text) => {
830
+ const curCount = text.split('/')[0];
831
+ const allCount = text.split('/')[1];
832
+ if (Number(curCount) === 0) {
833
+ d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 0.45);
834
+ d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 1);
835
+ } else if (Number(curCount) === Number(allCount)) {
836
+ d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 1);
837
+ d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 0.45);
838
+ } else {
839
+ d3.select(navigator).selectAll('.legend-prev-page').attr('opacity', 1);
840
+ d3.select(navigator).selectAll('.legend-next-page').attr('opacity', 1);
841
+ }
842
+ };
843
+ this.setLegendItemOffset = (legendItems, end) => {
844
+ const endItem = legendItems[legendItems.length - 1];
845
+ const endTranslateX = Number(endItem.getAttribute('data-translateX'));
846
+ const {
847
+ width: endWidth
848
+ } = endItem.getBoundingClientRect();
849
+ const offset = end - (endTranslateX + endWidth);
850
+ legendItems.forEach(legendItem => {
851
+ const curTranslateX = Number(legendItem.getAttribute('data-translateX')) + offset;
852
+ d3.select(legendItem).attr('transform', "translate(".concat(curTranslateX, ",0)")).attr('data-translateX', curTranslateX);
853
+ d3.select(legendItem).attr('opacity', 1);
854
+ });
855
+ };
570
856
  // theta is pie or ring chart
571
857
  this.setLegendForTheta = function (legendName) {
572
858
  let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
@@ -580,6 +866,13 @@ class ChartComponent extends _react.Component {
580
866
  basicLegendConfig.itemName.style.fontSize = theme.fontSize;
581
867
  _this.chart.legend(legendName, basicLegendConfig);
582
868
  };
869
+ this.calcEquilateralTriangle = (cx, cy, size, direction) => {
870
+ const height = size * Math.sqrt(3) / 2;
871
+ if (direction === 'bottom') {
872
+ return [[cx, cy + height / 2], [cx - size / 2, cy - height / 2], [cx + size / 2, cy - height / 2]];
873
+ }
874
+ return [[cx, cy - height / 2], [cx - size / 2, cy + height / 2], [cx + size / 2, cy + height / 2]];
875
+ };
583
876
  this.setColorMap = (data, chartColorTheme) => {
584
877
  let currentIdx = 0;
585
878
  const defaultColors = _constants.CHART_STYLE_COLORS;
@@ -689,47 +982,6 @@ class ChartComponent extends _react.Component {
689
982
  const settings = this.getToolTipSettings(isGroup, summaryColumn, y_axis_summary_method, useSingleSelectColumnColor);
690
983
  this.chart.tooltip(settings);
691
984
  };
692
- this.getToolTipContainer = (tooltipData, position) => {
693
- const {
694
- offsetX,
695
- offsetY
696
- } = position || {
697
- offsetX: -9999,
698
- offsetY: -9999
699
- };
700
- const {
701
- title,
702
- items
703
- } = tooltipData || {
704
- title: '',
705
- items: []
706
- };
707
- const dom = /*#__PURE__*/_react.default.createElement("div", {
708
- className: "sea-chart-d3-tooltip-container",
709
- style: {
710
- transform: "translate(".concat(offsetX + 50, "px, ").concat(offsetY, "px)")
711
- }
712
- }, /*#__PURE__*/_react.default.createElement("div", {
713
- className: "sea-chart-d3-tooltip-title"
714
- }, title), /*#__PURE__*/_react.default.createElement("ul", {
715
- className: "sea-chart-d3-tooltip-list"
716
- }, items.map((item, index) => {
717
- return /*#__PURE__*/_react.default.createElement("li", {
718
- className: "sea-chart-d3-tooltip-list-item",
719
- key: index
720
- }, /*#__PURE__*/_react.default.createElement("span", {
721
- className: "sea-chart-d3-tooltip-marker",
722
- style: {
723
- backgroundColor: item.color
724
- }
725
- }), /*#__PURE__*/_react.default.createElement("span", {
726
- className: "sea-chart-d3-tooltip-name"
727
- }, item.name), /*#__PURE__*/_react.default.createElement("span", {
728
- className: "sea-chart-d3-tooltip-value"
729
- }, item.value));
730
- })));
731
- return dom;
732
- };
733
985
  this.setToolTipForLine = () => {
734
986
  const settings = this.getToolTipSettings();
735
987
  const lineToolTipSettings = {
@@ -797,17 +1049,16 @@ class ChartComponent extends _react.Component {
797
1049
  return themeColors || _constants.CHART_THEME_COLOR[_constants.THEME_NAME_MAP.LIGHT];
798
1050
  };
799
1051
  this.setDispalyGoalLine = (goal_label, goal_value, insertPadding, yScale) => {
800
- var _this$chart$node3;
1052
+ var _this$chart$node2;
801
1053
  const {
802
1054
  width: chartWidth
803
1055
  } = this.chartBoundingClientRect;
804
- this.chart.append('g').attr('class', "annotation-wrapper-".concat((_this$chart$node3 = this.chart.node()) === null || _this$chart$node3 === void 0 ? void 0 : _this$chart$node3.id)).append('line').attr('stroke', '#aaa').attr('x1', insertPadding).attr('y1', yScale(goal_value)).attr('x2', chartWidth - insertPadding).attr('y2', yScale(goal_value)).call(g => {
805
- var _this$chart$node4;
806
- const parentNode = d3.select(".annotation-wrapper-".concat((_this$chart$node4 = this.chart.node()) === null || _this$chart$node4 === void 0 ? void 0 : _this$chart$node4.id));
807
- parentNode.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', yScale(goal_value) - 10).attr('fill', '#666').text(goal_label);
1056
+ const annotationWrapper = this.chart.append('g').attr('class', "annotation-wrapper-".concat((_this$chart$node2 = this.chart.node()) === null || _this$chart$node2 === void 0 ? void 0 : _this$chart$node2.id));
1057
+ annotationWrapper.append('line').attr('stroke', '#aaa').attr('x1', insertPadding).attr('y1', yScale(goal_value)).attr('x2', chartWidth - insertPadding).attr('y2', yScale(goal_value)).attr('stroke-dasharray', '8,3').call(g => {
1058
+ annotationWrapper.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', yScale(goal_value) - 10).attr('fill', '#666').text(goal_label);
808
1059
  });
809
1060
  };
810
- this.addLabelToRectTop = _ref3 => {
1061
+ this.addLabelToRectTop = _ref6 => {
811
1062
  let {
812
1063
  container,
813
1064
  x,
@@ -816,7 +1067,7 @@ class ChartComponent extends _react.Component {
816
1067
  theme,
817
1068
  label_font_size,
818
1069
  text
819
- } = _ref3;
1070
+ } = _ref6;
820
1071
  d3.select(container).append('text').attr('y', Number(y) - 10).attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
821
1072
  const {
822
1073
  width
@@ -824,7 +1075,24 @@ class ChartComponent extends _react.Component {
824
1075
  g.attr('x', Number(x) + Number(xWidth) / 2 - width / 2);
825
1076
  });
826
1077
  };
827
- this.addLabelToRectCenter = _ref4 => {
1078
+ this.addLabelToRectRight = _ref7 => {
1079
+ let {
1080
+ container,
1081
+ y,
1082
+ xWidth,
1083
+ yHeight,
1084
+ theme,
1085
+ label_font_size,
1086
+ text
1087
+ } = _ref7;
1088
+ d3.select(container).append('text').attr('x', Number(xWidth) + 10).attr('y', Number(y)).attr('fill', theme.labelColor).attr('dominant-baseline', 'hanging').attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
1089
+ const {
1090
+ height
1091
+ } = g.node().getBoundingClientRect();
1092
+ g.attr('y', Number(y) + Number(yHeight) / 2 - height / 2);
1093
+ });
1094
+ };
1095
+ this.addLabelToRectCenter = _ref8 => {
828
1096
  let {
829
1097
  chartType,
830
1098
  container,
@@ -832,11 +1100,10 @@ class ChartComponent extends _react.Component {
832
1100
  y,
833
1101
  xWidth,
834
1102
  yheight,
835
- overflowHeight,
836
1103
  theme,
837
1104
  label_font_size,
838
1105
  text
839
- } = _ref4;
1106
+ } = _ref8;
840
1107
  d3.select(container).append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
841
1108
  const {
842
1109
  width,
@@ -845,7 +1112,7 @@ class ChartComponent extends _react.Component {
845
1112
  const translateX = Number(x) + xWidth / 2 - width / 2;
846
1113
  let translateY = Number(y) + Number(yheight / 2) + height / 2;
847
1114
  if (chartType === _constants.CHART_TYPE.BAR_STACK) {
848
- translateY = translateY - overflowHeight / 2;
1115
+ translateY = translateY;
849
1116
  }
850
1117
  g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
851
1118
  });
@@ -870,6 +1137,31 @@ class ChartComponent extends _react.Component {
870
1137
  });
871
1138
  }
872
1139
  };
1140
+ // Use clipPath to make rectangle rounded corners
1141
+ this.addClipPath = _ref9 => {
1142
+ let {
1143
+ rect,
1144
+ parentNode,
1145
+ attr,
1146
+ rectId
1147
+ } = _ref9;
1148
+ const {
1149
+ borderRadius
1150
+ } = this.chartBoundingClientRect;
1151
+ const clipRect = d3.select(rect.cloneNode());
1152
+ if (attr === 'x') {
1153
+ const borderRadiusVal = Number(rect.getAttribute('height')) * borderRadius;
1154
+ clipRect.attr('rx', borderRadiusVal);
1155
+ clipRect.attr('x', Number(rect.getAttribute('x')) - borderRadiusVal).attr('width', Number(rect.getAttribute('width')) + borderRadiusVal);
1156
+ } else {
1157
+ const borderRadiusVal = Number(rect.getAttribute('width')) * borderRadius;
1158
+ clipRect.attr('rx', borderRadiusVal);
1159
+ clipRect.attr('height', Number(rect.getAttribute('height')) + borderRadiusVal);
1160
+ }
1161
+ const clipPath = d3.select(parentNode).append('clipPath').attr('id', rectId);
1162
+ clipPath.node().appendChild(clipRect.node());
1163
+ d3.select(rect).attr('clip-path', "url(#".concat(rectId, ")"));
1164
+ };
873
1165
  this.initLabelStroke(props === null || props === void 0 ? void 0 : props.globalTheme);
874
1166
  this.chartBoundingClientRect = {};
875
1167
  }