sea-chart 2.0.30 → 2.0.31

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', 'Line_chart', 'Area', 'Pie_chart', 'Scatter_chart', 'Combination_chart', 'Map'].includes(item.name));
72
+ const newChartTypes = _constants.CHART_TYPES.filter(item => ['Histogram', 'Bar_chart', 'Line_chart', 'Area', 'Pie_chart', 'Scatter_chart', 'Combination_chart', 'Map', 'Heat_map', 'Facet_chart'].includes(item.name));
73
73
  return newChartTypes;
74
74
  }
75
75
  return _constants.CHART_TYPES;
@@ -12,6 +12,7 @@ var _lodashEs = require("lodash-es");
12
12
  var _dtableUtils = require("dtable-utils");
13
13
  var _utils = require("../../utils");
14
14
  var _constants = require("../../constants");
15
+ var _style = require("../../constants/style");
15
16
  var _intl = _interopRequireDefault(require("../../intl"));
16
17
  require("../../assets/css/sea-chart-d3-tooltip.css");
17
18
  class ChartComponent extends _react.Component {
@@ -59,10 +60,12 @@ class ChartComponent extends _react.Component {
59
60
  const {
60
61
  marginLeft = 0,
61
62
  marginRight = 0,
62
- marginBottom = 0
63
+ marginBottom = 0,
64
+ customWidth,
65
+ customHeight
63
66
  } = initConfig;
64
- const width = containerWidth - marginLeft - marginRight;
65
- const height = containerHeight - marginBottom;
67
+ const width = customWidth ? customWidth : containerWidth - marginLeft - marginRight;
68
+ const height = customHeight ? customHeight : containerHeight - marginBottom;
66
69
  _this.chart = d3.create('svg').attr('id', id).attr('width', width).attr('height', height).attr('viewBox', [0, 0, width, height]);
67
70
  _this.container.appendChild(_this.chart.node());
68
71
  _this.chartBoundingClientRect = {
@@ -647,8 +650,31 @@ class ChartComponent extends _react.Component {
647
650
  return _intl.default.get(name) || name;
648
651
  }
649
652
  };
653
+ // set legend for heat map
654
+ this.setLegendForHeatMap = _ref => {
655
+ let {
656
+ exampleColors,
657
+ themeColors
658
+ } = _ref;
659
+ const legendOffsetY = 3;
660
+ const legendItemTextWidth = 32;
661
+ const legendItemWidth = 12;
662
+ const legendItemHeight = 12;
663
+ const legendItemGap = 3;
664
+ const legendItemRadius = 2;
665
+ const legendWrapper = this.chart.append('g').attr('class', 'legend-heat-map-wrapper').attr('transform', "translate(0, ".concat(legendOffsetY, ")"));
666
+
667
+ // less
668
+ legendWrapper.append('text').attr('y', 10).attr('fill', themeColors.textColor).attr('font-size', 12).attr('font-weight', 'bold').text(_intl.default.get('Less'));
669
+ // rect
670
+ exampleColors.forEach((color, index) => {
671
+ legendWrapper.append('rect').attr('x', legendItemTextWidth + index * legendItemWidth + index * legendItemGap).attr('width', legendItemWidth).attr('height', legendItemHeight).attr('rx', legendItemRadius).attr('fill', color).attr('stroke', _style.FILL_BORDER_COLOR_MAP[color]).attr('stroke-width', 1);
672
+ });
673
+ // more
674
+ legendWrapper.append('text').attr('x', 182).attr('y', 10).attr('fill', themeColors.textColor).attr('font-size', 12).attr('font-weight', 'bold').text(_intl.default.get('More'));
675
+ };
650
676
  // set continuous legend
651
- this.setContinuousLegend = _ref => {
677
+ this.setContinuousLegend = _ref2 => {
652
678
  var _this$chart$node2;
653
679
  let {
654
680
  previewType,
@@ -659,7 +685,7 @@ class ChartComponent extends _react.Component {
659
685
  legendTextRange,
660
686
  bubbleColor,
661
687
  type
662
- } = _ref;
688
+ } = _ref2;
663
689
  const {
664
690
  width: chartWidth,
665
691
  height: chartHeight,
@@ -702,8 +728,8 @@ class ChartComponent extends _react.Component {
702
728
  });
703
729
  };
704
730
  // set legend
705
- this.setLegend = _ref2 => {
706
- var _chart$config, _chart$config2, _chart$config3;
731
+ this.setLegend = _ref3 => {
732
+ var _chart$config, _chart$config2;
707
733
  let {
708
734
  legendName,
709
735
  theme = _constants.CHART_THEME_COLOR['light'],
@@ -712,12 +738,12 @@ class ChartComponent extends _react.Component {
712
738
  colorScale,
713
739
  groupColumn,
714
740
  chart
715
- } = _ref2;
741
+ } = _ref3;
716
742
  if (!this.chart) return;
717
743
  this.legendConfig = {
718
- legendRectWidth: (chart === null || chart === void 0 ? void 0 : (_chart$config = chart.config) === null || _chart$config === void 0 ? void 0 : _chart$config.type) === _constants.CHART_TYPE.SCATTER ? 8 : 20,
719
- legendRectHeight: (chart === null || chart === void 0 ? void 0 : (_chart$config2 = chart.config) === null || _chart$config2 === void 0 ? void 0 : _chart$config2.type) === _constants.CHART_TYPE.SCATTER ? 8 : 6,
720
- r: (chart === null || chart === void 0 ? void 0 : (_chart$config3 = chart.config) === null || _chart$config3 === void 0 ? void 0 : _chart$config3.type) === _constants.CHART_TYPE.SCATTER ? 4 : 3,
744
+ legendRectWidth: [_constants.CHART_TYPE.SCATTER, _constants.CHART_TYPE.MIRROR].includes(chart === null || chart === void 0 ? void 0 : (_chart$config = chart.config) === null || _chart$config === void 0 ? void 0 : _chart$config.type) ? 8 : 20,
745
+ legendRectHeight: [_constants.CHART_TYPE.SCATTER, _constants.CHART_TYPE.MIRROR].includes(chart === null || chart === void 0 ? void 0 : (_chart$config2 = chart.config) === null || _chart$config2 === void 0 ? void 0 : _chart$config2.type) ? 8 : 6,
746
+ r: this.getLegendR(chart),
721
747
  legendItemPaddingTop: 5,
722
748
  legendItemTextPaddingTop: 13,
723
749
  legendItemMargin: 20,
@@ -746,12 +772,13 @@ class ChartComponent extends _react.Component {
746
772
  // legend offset bottom and When there is only one line of legend, it is displayed in the center (for scatter chart)
747
773
  if (bottomLegendSpace) {
748
774
  queueMicrotask(() => {
775
+ const {
776
+ width,
777
+ height
778
+ } = legendWrapper.node().getBoundingClientRect();
749
779
  let curTranslateX = 0;
750
- const curTranslateY = bottomLegendSpace ? chartHeight - bottomLegendSpace : 0;
780
+ const curTranslateY = bottomLegendSpace ? chartHeight - height : 0;
751
781
  if (groupsData.length === 1) {
752
- const {
753
- width
754
- } = legendWrapper.node().getBoundingClientRect();
755
782
  curTranslateX = (chartWidth - width - insertPadding * 2) / 2;
756
783
  }
757
784
  legendWrapper.attr('transform', "translate(".concat(curTranslateX, ",").concat(curTranslateY, ")"));
@@ -831,14 +858,14 @@ class ChartComponent extends _react.Component {
831
858
  });
832
859
  }
833
860
  };
834
- this.renderLegend = _ref3 => {
861
+ this.renderLegend = _ref4 => {
835
862
  let {
836
863
  legendWrapper,
837
864
  groupData,
838
865
  colorScale,
839
866
  theme,
840
867
  text
841
- } = _ref3;
868
+ } = _ref4;
842
869
  const {
843
870
  legendItemPaddingTop,
844
871
  legendItemTextPaddingTop,
@@ -864,15 +891,15 @@ class ChartComponent extends _react.Component {
864
891
  d3.select(item).remove();
865
892
  });
866
893
  }
867
- legendWrapper.selectAll().data(groupData).join('g').attr('data-groupName', _ref4 => {
868
- let [groupName] = _ref4;
869
- return groupName;
870
- }).append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('y', legendItemPaddingTop).attr('rx', r).attr('fill', _ref5 => {
894
+ legendWrapper.selectAll().data(groupData).join('g').attr('data-groupName', _ref5 => {
871
895
  let [groupName] = _ref5;
896
+ return groupName;
897
+ }).append('rect').attr('width', legendRectWidth).attr('height', legendRectHeight).attr('y', legendItemPaddingTop).attr('rx', r).attr('fill', _ref6 => {
898
+ let [groupName] = _ref6;
872
899
  if (colorScale) return colorScale(groupName);
873
900
  return this.colorMap[groupName] || _constants.CHART_STYLE_COLORS[0];
874
- }).attr('data-text', _ref6 => {
875
- let [groupName] = _ref6;
901
+ }).attr('data-text', _ref7 => {
902
+ let [groupName] = _ref7;
876
903
  return groupName;
877
904
  }).call(g => {
878
905
  // Add text
@@ -1078,6 +1105,17 @@ class ChartComponent extends _react.Component {
1078
1105
  item.name = item['oldName'];
1079
1106
  });
1080
1107
  };
1108
+ this.getLegendR = chart => {
1109
+ const {
1110
+ config
1111
+ } = chart;
1112
+ const {
1113
+ type
1114
+ } = config;
1115
+ if (type === _constants.CHART_TYPE.SCATTER) return 4;
1116
+ if (type === _constants.CHART_TYPE.MIRROR) return 0;
1117
+ return 3;
1118
+ };
1081
1119
  // theta is pie or ring chart
1082
1120
  this.setLegendForTheta = function (legendName) {
1083
1121
  let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
@@ -1372,7 +1410,7 @@ class ChartComponent extends _react.Component {
1372
1410
  annotationWrapper.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', yScale(goal_value) - 10).attr('fill', '#666').text(goal_label);
1373
1411
  });
1374
1412
  };
1375
- this.addLabelToRectTop = _ref7 => {
1413
+ this.addLabelToRectTop = _ref8 => {
1376
1414
  let {
1377
1415
  container,
1378
1416
  x,
@@ -1381,7 +1419,7 @@ class ChartComponent extends _react.Component {
1381
1419
  theme,
1382
1420
  label_font_size,
1383
1421
  text
1384
- } = _ref7;
1422
+ } = _ref8;
1385
1423
  d3.select(container).append('text').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('y', Number(y) - 10).attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
1386
1424
  const {
1387
1425
  width
@@ -1389,7 +1427,7 @@ class ChartComponent extends _react.Component {
1389
1427
  g.attr('x', Number(x) + Number(xWidth) / 2 - width / 2);
1390
1428
  });
1391
1429
  };
1392
- this.addLabelToRectRight = _ref8 => {
1430
+ this.addLabelToRectRight = _ref9 => {
1393
1431
  let {
1394
1432
  container,
1395
1433
  x,
@@ -1399,7 +1437,7 @@ class ChartComponent extends _react.Component {
1399
1437
  theme,
1400
1438
  label_font_size,
1401
1439
  text
1402
- } = _ref8;
1440
+ } = _ref9;
1403
1441
  d3.select(container).append('text').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('x', Number(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 => {
1404
1442
  if (g.node()) {
1405
1443
  var _g$node;
@@ -1410,7 +1448,7 @@ class ChartComponent extends _react.Component {
1410
1448
  }
1411
1449
  });
1412
1450
  };
1413
- this.addLabelToRectCenter = _ref9 => {
1451
+ this.addLabelToRectCenter = _ref10 => {
1414
1452
  let {
1415
1453
  chartType,
1416
1454
  container,
@@ -1421,7 +1459,7 @@ class ChartComponent extends _react.Component {
1421
1459
  theme,
1422
1460
  label_font_size,
1423
1461
  text
1424
- } = _ref9;
1462
+ } = _ref10;
1425
1463
  d3.select(container).append('text').attr('stroke', '#fff').attr('stroke-width', 1).attr('paint-order', 'stroke').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
1426
1464
  const {
1427
1465
  width,
@@ -1463,13 +1501,13 @@ class ChartComponent extends _react.Component {
1463
1501
  }
1464
1502
  };
1465
1503
  // Use clipPath to make rectangle rounded corners
1466
- this.addClipPath = _ref10 => {
1504
+ this.addClipPath = _ref11 => {
1467
1505
  let {
1468
1506
  rect,
1469
1507
  parentNode,
1470
1508
  attr,
1471
1509
  rectId
1472
- } = _ref10;
1510
+ } = _ref11;
1473
1511
  const {
1474
1512
  borderRadius
1475
1513
  } = this.chartBoundingClientRect;
@@ -0,0 +1,323 @@
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 _dayjs = _interopRequireDefault(require("dayjs"));
15
+ var _dtableUtils = require("dtable-utils");
16
+ var _dayOfYear = _interopRequireDefault(require("dayjs/plugin/dayOfYear"));
17
+ var _style = require("../../constants/style");
18
+ var _constants = require("../../constants");
19
+ var _utils = require("../../utils");
20
+ var _intl = _interopRequireDefault(require("../../intl"));
21
+ var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
22
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
23
+ _dayjs.default.extend(_dayOfYear.default);
24
+ class HeatMap extends _chartComponent.default {
25
+ constructor(props) {
26
+ super(props);
27
+ this.handleResize = () => {
28
+ this.destroyChart();
29
+ this.createChart();
30
+ this.drawChart();
31
+ };
32
+ this.createChart = () => {
33
+ const {
34
+ chart,
35
+ result
36
+ } = this.props;
37
+ const initConfig = {
38
+ insertPadding: 30,
39
+ borderRadius: 0.06,
40
+ monthAxisHeight: 30
41
+ };
42
+ const {
43
+ width,
44
+ height
45
+ } = this.getCustomWidthAndHeight(result, chart.config, initConfig);
46
+ initConfig['customWidth'] = width;
47
+ initConfig['customHeight'] = height;
48
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
49
+ };
50
+ this.drawChart = () => {
51
+ const {
52
+ result = {}
53
+ } = this.props;
54
+ if (Object.keys(result).length === 0) return;
55
+ this.draw(result);
56
+ this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
57
+ };
58
+ this.getCustomWidthAndHeight = (result, chartConfig, initConfig) => {
59
+ const {
60
+ insertPadding,
61
+ monthAxisHeight
62
+ } = initConfig;
63
+ const count = result.years.length;
64
+ let {
65
+ grid_size,
66
+ grid_distance
67
+ } = chartConfig;
68
+ grid_size = grid_size || _constants.DEFAULT_GRID_SIZE;
69
+ grid_distance = grid_distance || _constants.DEFAULT_GRID_DISTANCE;
70
+ const yearHeight = grid_size * 7 + grid_distance * 6; // height for 1 year
71
+ const height = (yearHeight + monthAxisHeight) * count + (insertPadding + insertPadding); // monthAxisHeight is axis height, insertPadding is top and bottm height
72
+ const width = grid_size * 53 + grid_distance * 52 + (insertPadding + insertPadding); // insertPadding is left and right width
73
+ return {
74
+ width,
75
+ height
76
+ };
77
+ };
78
+ this.showTooltip = (event, data, columnData) => {
79
+ const {
80
+ offsetX,
81
+ offsetY
82
+ } = event;
83
+ const newTooltipData = {
84
+ title: data.name,
85
+ items: [{
86
+ color: '',
87
+ name: _intl.default.get(_constants.TITLE_AMOUNT),
88
+ value: (0, _dtableUtils.getNumberDisplayString)(data.value, columnData)
89
+ }]
90
+ };
91
+ this.setState({
92
+ tooltipData: newTooltipData
93
+ });
94
+ this.setState({
95
+ toolTipPosition: {
96
+ offsetX,
97
+ offsetY
98
+ }
99
+ });
100
+ };
101
+ this.moveTooltip = event => {
102
+ const {
103
+ offsetX,
104
+ offsetY
105
+ } = event;
106
+ this.setState({
107
+ toolTipPosition: {
108
+ offsetX,
109
+ offsetY
110
+ }
111
+ });
112
+ };
113
+ this.hiddenTooltip = event => {
114
+ this.setState({
115
+ toolTipPosition: null
116
+ });
117
+ };
118
+ this.draw = resultData => {
119
+ const {
120
+ data,
121
+ years
122
+ } = resultData;
123
+ const {
124
+ chart,
125
+ tables
126
+ } = this.props;
127
+ const {
128
+ width: chartWidth,
129
+ height: chartHeight,
130
+ insertPadding,
131
+ borderRadius,
132
+ monthAxisHeight
133
+ } = this.chartBoundingClientRect;
134
+ let {
135
+ data_color,
136
+ grid_size,
137
+ table_id,
138
+ summary_type,
139
+ summary_column
140
+ } = chart.config;
141
+ grid_size = grid_size ? grid_size : _constants.DEFAULT_GRID_SIZE;
142
+ const currentColorOption = _style.COLOR_OPTIONS.filter(item => item.name === data_color)[0] || _style.COLOR_OPTIONS[0];
143
+ const {
144
+ exampleColors
145
+ } = currentColorOption;
146
+ const themeColors = this.getThemeColors();
147
+ let columnData = _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
148
+ if (summary_type === _constants.CHART_SUMMARY_TYPE.ADVANCED) {
149
+ const table = (0, _dtableUtils.getTableById)(tables, table_id);
150
+ const summaryColumn = (0, _dtableUtils.getTableColumnByKey)(table, summary_column) || {};
151
+ columnData = summaryColumn.data || _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
152
+ }
153
+ const yAxisWrapper = this.chart.append('g').attr('class', 'y-axis-wrapper');
154
+ const xAxisWrapper = this.chart.append('g').attr('class', 'x-axis-wrapper');
155
+ const contentWrapper = this.chart.append('g').attr('class', 'content-wrapper');
156
+ const titleWrapper = this.chart.append('g').attr('class', 'title-wrapper');
157
+
158
+ // Fy scale
159
+ const fyDomain = new Set(years.map(d => d));
160
+ const fy = d3.scaleBand().domain(fyDomain).range([insertPadding, chartHeight - insertPadding]).paddingInner(0).paddingOuter(0);
161
+ Array.from(fyDomain).forEach((year, index) => {
162
+ // Y axis
163
+ const y = d3.scaleBand().domain(this.weeks).range([fy(year), fy(year) + (fy.bandwidth() - monthAxisHeight)]).paddingInner(0).paddingOuter(0);
164
+ yAxisWrapper.append('g').attr('class', "y-axis-".concat(year)).attr('transform', "translate(".concat(insertPadding, ", 0)")).call(d3.axisLeft(y).tickSizeInner(0).tickSizeOuter(0).tickFormat(d => _intl.default.get(d))).call(g => {
165
+ g.select('.domain').remove();
166
+ g.selectAll('text').attr('font-size', 12);
167
+ g.selectAll('text').attr('fill', themeColors.textColor);
168
+ });
169
+
170
+ // Content
171
+ const [dates, weekCount] = this.generateYearDates(year);
172
+ const monthTranslateX = [];
173
+ const weekDomain = Array.from({
174
+ length: weekCount
175
+ }, (_, i) => i + 1);
176
+ const weekScale = d3.scaleBand().domain(weekDomain).range([insertPadding, chartWidth - insertPadding]).paddingInner(0).paddingOuter(0);
177
+
178
+ // year
179
+ const yearWrapper = contentWrapper.append('g').attr('class', "year-wrapper-".concat(year));
180
+ dates.forEach(_ref => {
181
+ let [monthIndex, days] = _ref;
182
+ // month
183
+ const monthWrapper = yearWrapper.append('g').attr('class', "month-".concat(this.months[monthIndex]));
184
+ // day
185
+ days.forEach((d, index) => {
186
+ monthWrapper.append('rect').attr('class', () => "day-".concat((0, _dayjs.default)(d).dayOfYear())).attr('x', () => {
187
+ let curWeek = (0, _dayjs.default)(d).week();
188
+ // The last few days are the first week of the next year
189
+ if (monthIndex === 11 && curWeek === 1) {
190
+ curWeek = weekCount;
191
+ }
192
+ if (index === 0) {
193
+ monthTranslateX.push(weekScale(curWeek));
194
+ } // Record the x position of the first day of each month
195
+ return weekScale(curWeek);
196
+ }).attr('y', () => {
197
+ const curWeek = this.weeks[(0, _dayjs.default)(d).day()];
198
+ return y(curWeek);
199
+ }).attr('width', grid_size).attr('height', grid_size).attr('rx', grid_size * borderRadius).attr('fill', () => this.getRectColor(d, data, 'fill', exampleColors)).attr('stroke', () => this.getRectColor(d, data, 'stroke', exampleColors)).attr('stroke-width', 1).on('click', () => {
200
+ const curDate = data.find(item => item.name === (0, _dayjs.default)(d).format('YYYY-MM-DD'));
201
+ if (curDate) {
202
+ this.props.toggleRecords(curDate);
203
+ }
204
+ }).on('mouseover', event => {
205
+ const curDate = data.find(item => item.name === (0, _dayjs.default)(d).format('YYYY-MM-DD'));
206
+ if (curDate) {
207
+ this.showTooltip(event, curDate, columnData);
208
+ }
209
+ }).on('mousemove', event => {
210
+ const curDate = data.find(item => item.name === (0, _dayjs.default)(d).format('YYYY-MM-DD'));
211
+ if (curDate) {
212
+ this.moveTooltip(event);
213
+ }
214
+ }).on('mouseleave', () => {
215
+ this.hiddenTooltip();
216
+ });
217
+ });
218
+ });
219
+
220
+ // X axis
221
+ const x = d3.scalePoint().domain(this.months).range([insertPadding, chartWidth - insertPadding]);
222
+ xAxisWrapper.append('g').attr('class', "x-axis-".concat(year)).attr('transform', "translate(0, ".concat(fy(year) + fy.bandwidth() - monthAxisHeight, ")")).call(d3.axisBottom(x).tickSizeInner(0).tickSizeOuter(0).tickFormat(d => _intl.default.get(d))).call(g => {
223
+ g.select('.domain').remove();
224
+ g.selectAll('.tick').nodes().forEach((item, index) => {
225
+ const curTranslateX = monthTranslateX[index] + weekScale.bandwidth() / 2;
226
+ d3.select(item).attr('transform', "translate(".concat(curTranslateX, ", 0)"));
227
+ });
228
+ g.selectAll('text').attr('font-size', 12);
229
+ g.selectAll('text').attr('fill', themeColors.textColor);
230
+ });
231
+
232
+ // Title
233
+ titleWrapper.append('text').attr('class', "text-".concat(year)).attr('x', 0).attr('y', fy(year) + fy.bandwidth()).attr('fill', '#000').attr('font-size', 12).attr('font-weight', 500).text(year);
234
+ });
235
+ this.setLegendForHeatMap({
236
+ exampleColors: ['#EBEDF0', ...exampleColors],
237
+ themeColors
238
+ });
239
+ };
240
+ this.generateYearDates = year => {
241
+ const dates = [];
242
+ let current = (0, _dayjs.default)("".concat(year, "-01-01"));
243
+ while (current.year() === year) {
244
+ dates.push(current);
245
+ current = current.add(1, 'day');
246
+ }
247
+ const weekCount = Math.ceil(dates.length / 7);
248
+ return [d3.groups(dates, d => (0, _dayjs.default)(d).month()), weekCount];
249
+ };
250
+ this.getRectColor = (d, data, type, exampleColors) => {
251
+ const maxVal = d3.max(data, d => d.value);
252
+ const defaultColor = type === 'stroke' ? '#E1E3E6' : '#EBEDF0';
253
+ const curDate = data.find(item => item.name === (0, _dayjs.default)(d).format('YYYY-MM-DD'));
254
+ if (curDate) {
255
+ if (curDate.value <= 0) return defaultColor;
256
+ if (curDate.value === maxVal) return type === 'stroke' ? _style.FILL_BORDER_COLOR_MAP[exampleColors[8]] : exampleColors[8];
257
+ const curColor = Math.floor(curDate.value / (maxVal / 9));
258
+ return type === 'stroke' ? _style.FILL_BORDER_COLOR_MAP[exampleColors[curColor]] : exampleColors[curColor];
259
+ }
260
+ return defaultColor;
261
+ };
262
+ _dayjs.default.locale('en');
263
+ this.weeks = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
264
+ this.months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
265
+ this.chart = null;
266
+ this.state = {
267
+ tooltipData: null,
268
+ toolTipPosition: null
269
+ };
270
+ }
271
+ componentDidMount() {
272
+ this.createChart();
273
+ this.drawChart();
274
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
275
+ window.addEventListener('resize', this.debouncedHandleResize);
276
+ }
277
+ componentDidUpdate(prevProps) {
278
+ super.componentDidUpdate(prevProps);
279
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
280
+ this.destroyChart();
281
+ this.createChart();
282
+ this.drawChart();
283
+ }
284
+ }
285
+ componentWillUnmount() {
286
+ this.destroyChart();
287
+ window.removeEventListener('resize', this.debouncedHandleResize);
288
+ }
289
+ render() {
290
+ const {
291
+ chart
292
+ } = this.props;
293
+ const {
294
+ tooltipData,
295
+ toolTipPosition
296
+ } = this.state;
297
+ return /*#__PURE__*/_react.default.createElement("div", {
298
+ ref: ref => this.container = ref,
299
+ className: (0, _classnames.default)('sea-chart-container', {
300
+ 'show-x-axis-label': this.isShowXAxisLabel(chart),
301
+ 'show-y-axis-label': this.isShowYAxisLabel(chart)
302
+ })
303
+ }, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
304
+ tooltipData: tooltipData,
305
+ toolTipPosition: toolTipPosition,
306
+ chart: this.chart
307
+ }));
308
+ }
309
+ }
310
+ HeatMap.propTypes = {
311
+ canvasStyle: _propTypes.default.object,
312
+ chart: _propTypes.default.object,
313
+ groupbyColumn: _propTypes.default.object,
314
+ columnGroupbyColumn: _propTypes.default.object,
315
+ summaryColumn: _propTypes.default.object,
316
+ result: _propTypes.default.object,
317
+ tables: _propTypes.default.array,
318
+ globalTheme: _propTypes.default.string,
319
+ chartColorTheme: _propTypes.default.string,
320
+ toggleRecords: _propTypes.default.func,
321
+ customRender: _propTypes.default.func
322
+ };
323
+ var _default = exports.default = HeatMap;
@@ -34,6 +34,8 @@ var _map = _interopRequireDefault(require("./map"));
34
34
  var _mapBubble = _interopRequireDefault(require("./map-bubble"));
35
35
  var _mapWorld = _interopRequireDefault(require("./map-world"));
36
36
  var _mapWorldBubble = _interopRequireDefault(require("./map-world-bubble"));
37
+ var _heatMap = _interopRequireDefault(require("./heat-map"));
38
+ var _mirror = _interopRequireDefault(require("./mirror"));
37
39
  var _trend = _interopRequireDefault(require("./trend"));
38
40
  var _tableElement = _interopRequireDefault(require("./table-element"));
39
41
  const Wrapper = _ref => {
@@ -281,6 +283,18 @@ const Wrapper = _ref => {
281
283
  canvasStyle: canvasStyle
282
284
  }));
283
285
  }
286
+ case _constants.CHART_TYPE.HEAT_MAP:
287
+ {
288
+ return /*#__PURE__*/_react.default.createElement(_heatMap.default, Object.assign({}, baseProps, {
289
+ canvasStyle: canvasStyle
290
+ }));
291
+ }
292
+ case _constants.CHART_TYPE.MIRROR:
293
+ {
294
+ return /*#__PURE__*/_react.default.createElement(_mirror.default, Object.assign({}, baseProps, {
295
+ canvasStyle: canvasStyle
296
+ }));
297
+ }
284
298
  case _constants.CHART_TYPE.BASIC_NUMBER_CARD:
285
299
  {
286
300
  return /*#__PURE__*/_react.default.createElement(_basicNumberCard.default, Object.assign({}, baseProps, {
@@ -0,0 +1,320 @@
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 _utils = require("../../utils");
17
+ var _intl = _interopRequireDefault(require("../../intl"));
18
+ var _tooltip = _interopRequireDefault(require("../../components/tooltip"));
19
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
20
+ class Mirror extends _chartComponent.default {
21
+ constructor(props) {
22
+ super(props);
23
+ this.handleResize = () => {
24
+ this.destroyChart();
25
+ this.createChart();
26
+ this.drawChart();
27
+ };
28
+ this.createChart = () => {
29
+ const {
30
+ chart
31
+ } = this.props;
32
+ const initConfig = {
33
+ insertPadding: 30,
34
+ bottomLegendSpace: 20
35
+ };
36
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
37
+ };
38
+ this.drawChart = () => {
39
+ let {
40
+ result
41
+ } = this.props;
42
+ const data = _utils.BaseUtils.formatEmptyName(result.data, '', _intl.default.get('Empty'));
43
+ if (!Array.isArray(data)) return;
44
+ this.draw({
45
+ data,
46
+ colorSet: result.colorSet
47
+ });
48
+ this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
49
+ };
50
+ this.showTooltip = (event, data) => {
51
+ const {
52
+ chart
53
+ } = this.props;
54
+ const {
55
+ summary_type,
56
+ summary_method
57
+ } = chart.config;
58
+ const {
59
+ offsetX,
60
+ offsetY
61
+ } = event;
62
+ const newTooltipData = {
63
+ title: summary_type === 'count' ? _intl.default.get(_constants.TITLE_AMOUNT) : _intl.default.get(_constants.CHART_SUMMARY_SHOW[summary_method]),
64
+ items: [{
65
+ color: '',
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 => {
81
+ const {
82
+ offsetX,
83
+ offsetY
84
+ } = event;
85
+ this.setState({
86
+ toolTipPosition: {
87
+ offsetX,
88
+ offsetY
89
+ }
90
+ });
91
+ };
92
+ this.hiddenTooltip = event => {
93
+ this.setState({
94
+ toolTipPosition: null
95
+ });
96
+ };
97
+ this.draw = _ref => {
98
+ let {
99
+ data,
100
+ colorSet
101
+ } = _ref;
102
+ const {
103
+ chart,
104
+ tables
105
+ } = this.props;
106
+ const {
107
+ table_id,
108
+ summary_type,
109
+ summary_column,
110
+ is_transpose
111
+ } = chart.config;
112
+ const {
113
+ width: chartWidth,
114
+ height: chartHeight,
115
+ insertPadding,
116
+ bottomLegendSpace
117
+ } = this.chartBoundingClientRect;
118
+ const themeColors = this.getThemeColors();
119
+ let columnData = _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
120
+ if (summary_type === _constants.CHART_SUMMARY_TYPE.ADVANCED) {
121
+ const table = (0, _dtableUtils.getTableById)(tables, table_id);
122
+ const summaryColumn = (0, _dtableUtils.getTableColumnByKey)(table, summary_column) || {};
123
+ columnData = summaryColumn.data || _constants.DEFAULT_NUMBER_FORMAT_OBJECT;
124
+ }
125
+ const scaleBandDomain = Array.from(new Set(data.map(d => d.group_name)));
126
+ const scaleBand = d3.scaleBand().domain(scaleBandDomain).range(is_transpose ? [insertPadding, chartWidth - insertPadding] : [insertPadding, chartHeight - insertPadding - bottomLegendSpace]).paddingInner(0.1).paddingOuter(0);
127
+
128
+ // ScaleLinear axis
129
+ const maxDomain = d3.max(data, d => d.value);
130
+ const scaleLinear1 = d3.scaleLinear().domain([maxDomain, 0]).range([scaleBand(scaleBandDomain[0]), scaleBand.bandwidth()]);
131
+ const scaleLinear2 = d3.scaleLinear().domain([0, maxDomain]).range([scaleBand(scaleBandDomain[1]), scaleBand(scaleBandDomain[1]) + scaleBand.bandwidth()]);
132
+ const scaleLinearWrapper = this.chart.append('g').attr('class', 'scale-linear-axis-wrapper');
133
+ scaleLinearWrapper.append('g').attr('class', 'scale-linear-1').attr('transform', is_transpose ? "translate(0, ".concat(chartHeight - insertPadding - bottomLegendSpace, ")") : "translate(".concat(insertPadding, ", 0)")).call(is_transpose ? d3.axisBottom(scaleLinear1).tickSizeInner(0).tickSizeOuter(0).ticks(5) : d3.axisLeft(scaleLinear1).tickSizeInner(0).tickSizeOuter(0).ticks(5)).call(g => {
134
+ g.select('.domain').remove();
135
+ g.selectAll('text').attr('font-size', themeColors.fontSize).attr('fill', themeColors.textColor);
136
+ g.selectAll('.tick line').attr('stroke', themeColors.gridColor);
137
+ is_transpose ? g.selectAll('.tick line').attr('y2', -(chartHeight - insertPadding - insertPadding - bottomLegendSpace)) : g.selectAll('.tick line').attr('x2', chartWidth - insertPadding - insertPadding);
138
+ });
139
+ scaleLinearWrapper.append('g').attr('class', 'scale-linear-2').attr('transform', is_transpose ? "translate(0, ".concat(chartHeight - insertPadding - bottomLegendSpace, ")") : "translate(".concat(insertPadding, ", 0)")).call(is_transpose ? d3.axisBottom(scaleLinear2).tickSizeInner(0).tickSizeOuter(0).ticks(5).tickFormat(t => (0, _dtableUtils.getNumberDisplayString)(t, columnData)) : d3.axisLeft(scaleLinear2).tickSizeInner(0).tickSizeOuter(0).ticks(5).tickFormat(t => (0, _dtableUtils.getNumberDisplayString)(t, columnData))).call(g => {
140
+ g.select('.domain').remove();
141
+ g.selectAll('text').attr('font-size', themeColors.fontSize).attr('fill', themeColors.textColor);
142
+ g.selectAll('.tick line').attr('stroke', themeColors.gridColor);
143
+ is_transpose ? g.selectAll('.tick line').attr('y2', -(chartHeight - insertPadding - insertPadding - bottomLegendSpace)) : g.selectAll('.tick line').attr('x2', chartWidth - insertPadding - insertPadding);
144
+ });
145
+
146
+ // ScaleBand Center axis
147
+ const scaleBandCenter = d3.scaleBand().domain(new Set(data.map(d => d.name))).range(is_transpose ? [insertPadding, chartHeight - insertPadding - bottomLegendSpace] : [insertPadding, chartWidth - insertPadding]).paddingInner(0.5).paddingOuter(0.1);
148
+ this.chart.append('g').attr('class', 'scale-band-center-axis-wrapper').attr('transform', is_transpose ? "translate(".concat(scaleLinear1(0), ", 0)") : "translate(0, ".concat(scaleLinear1(0), ")")).call(is_transpose ? d3.axisRight(scaleBandCenter).tickSizeInner(4).tickSizeOuter(0).tickFormat(t => {
149
+ const name = String(t);
150
+ return name.length > 5 ? "".concat(name.slice(0, 5), "...") : name;
151
+ }) : d3.axisBottom(scaleBandCenter).tickSizeInner(4).tickSizeOuter(0).tickFormat(t => {
152
+ const name = String(t);
153
+ return name.length > 5 ? "".concat(name.slice(0, 5), "...") : name;
154
+ })).call(g => {
155
+ g.select('.domain').remove();
156
+ g.selectAll('.tick line').attr('stroke', themeColors.XAxisColor);
157
+ g.selectAll('text').attr('font-size', 12).attr('fill', themeColors.textColor);
158
+ });
159
+
160
+ // Content
161
+ const contentWrapper = this.chart.append('g').attr('class', 'content-wrapper');
162
+ contentWrapper.selectAll().data(d3.group(data, d => d.group_name)).join('g').call(g => {
163
+ // Add title
164
+ const titleWrapper = this.chart.append('g').attr('class', 'title-wrapper');
165
+ g.nodes().forEach((item, index) => {
166
+ const title = item === null || item === void 0 ? void 0 : item.__data__[0];
167
+ titleWrapper.append('text').text(title || '').attr('dominant-baseline', 'hanging').attr('fill', themeColors.textColor).attr('font-size', 14).attr('font-weight', 500).call(text => {
168
+ if (text.node()) {
169
+ var _text$node;
170
+ const {
171
+ width
172
+ } = (_text$node = text.node()) === null || _text$node === void 0 ? void 0 : _text$node.getBoundingClientRect();
173
+ const endPosition = index === 0 ? scaleLinear1(0) : scaleLinear2(maxDomain);
174
+ if (is_transpose) {
175
+ text.attr('x', endPosition - scaleBand.bandwidth() / 2 + width / 2);
176
+ text.attr('y', 0);
177
+ } else {
178
+ text.attr('x', chartWidth - width);
179
+ text.attr('y', endPosition - scaleBand.bandwidth() / 2);
180
+ }
181
+ }
182
+ });
183
+ });
184
+ }).selectAll().data(_ref2 => {
185
+ let [groupName, d] = _ref2;
186
+ const newData = d.filter(item => item.value !== 0);
187
+ newData.groupName = groupName;
188
+ return newData;
189
+ }).join('rect').attr('opacity', 1).attr('x', d => {
190
+ const {
191
+ group_name,
192
+ value,
193
+ name
194
+ } = d;
195
+ if (group_name === scaleBandDomain[0]) {
196
+ return is_transpose ? scaleLinear1(value) : scaleBandCenter(name);
197
+ }
198
+ if (group_name === scaleBandDomain[1]) {
199
+ return is_transpose ? scaleLinear2(0) : scaleBandCenter(name);
200
+ }
201
+ }).attr('y', d => {
202
+ const {
203
+ group_name,
204
+ name,
205
+ value
206
+ } = d;
207
+ if (group_name === scaleBandDomain[0]) {
208
+ return is_transpose ? scaleBandCenter(name) : scaleLinear1(value);
209
+ }
210
+ if (group_name === scaleBandDomain[1]) {
211
+ return is_transpose ? scaleBandCenter(name) : scaleLinear2(0);
212
+ }
213
+ }).attr('width', d => {
214
+ const {
215
+ group_name,
216
+ value
217
+ } = d;
218
+ if (group_name === scaleBandDomain[0]) {
219
+ return is_transpose ? scaleLinear1(0) - scaleLinear1(value) : scaleBandCenter.bandwidth();
220
+ }
221
+ if (group_name === scaleBandDomain[1]) {
222
+ return is_transpose ? scaleLinear2(value) - scaleLinear2(0) : scaleBandCenter.bandwidth();
223
+ }
224
+ }).attr('height', d => {
225
+ const {
226
+ group_name,
227
+ value
228
+ } = d;
229
+ if (group_name === scaleBandDomain[0]) {
230
+ return is_transpose ? scaleBandCenter.bandwidth() : scaleLinear1(0) - scaleLinear1(value);
231
+ }
232
+ if (group_name === scaleBandDomain[1]) {
233
+ return is_transpose ? scaleBandCenter.bandwidth() : scaleLinear2(value) - scaleLinear2(0);
234
+ }
235
+ }).attr('fill', d => {
236
+ const {
237
+ color
238
+ } = d;
239
+ return color;
240
+ }).on('click', (event, data) => {
241
+ this.props.toggleRecords(data);
242
+ }).on('mouseover', (event, data) => {
243
+ this.showTooltip(event, data);
244
+ }).on('mousemove', event => {
245
+ this.moveTooltip(event);
246
+ }).on('mouseleave', event => {
247
+ this.hiddenTooltip(event);
248
+ });
249
+ this.setLegend({
250
+ legendName: 'group_name',
251
+ theme: themeColors,
252
+ legendPosition: 'top-left',
253
+ data,
254
+ groupColumn: this.props.columnGroupbyColumn,
255
+ chart,
256
+ colorScale: key => {
257
+ const curD = data.find(item => item.group_name === key);
258
+ return curD.color || '';
259
+ }
260
+ });
261
+ };
262
+ this.chart = null;
263
+ this.state = {
264
+ tooltipData: null,
265
+ toolTipPosition: null
266
+ };
267
+ }
268
+ componentDidMount() {
269
+ this.createChart();
270
+ this.drawChart();
271
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
272
+ window.addEventListener('resize', this.debouncedHandleResize);
273
+ }
274
+ componentDidUpdate(prevProps) {
275
+ super.componentDidUpdate(prevProps);
276
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
277
+ this.destroyChart();
278
+ this.createChart();
279
+ this.drawChart();
280
+ }
281
+ }
282
+ componentWillUnmount() {
283
+ this.destroyChart();
284
+ window.removeEventListener('resize', this.debouncedHandleResize);
285
+ }
286
+ render() {
287
+ const {
288
+ chart
289
+ } = this.props;
290
+ const {
291
+ tooltipData,
292
+ toolTipPosition
293
+ } = this.state;
294
+ return /*#__PURE__*/_react.default.createElement("div", {
295
+ ref: ref => this.container = ref,
296
+ className: (0, _classnames.default)('sea-chart-container', {
297
+ 'show-x-axis-label': this.isShowXAxisLabel(chart),
298
+ 'show-y-axis-label': this.isShowYAxisLabel(chart)
299
+ })
300
+ }, /*#__PURE__*/_react.default.createElement(_tooltip.default, {
301
+ tooltipData: tooltipData,
302
+ toolTipPosition: toolTipPosition,
303
+ chart: this.chart
304
+ }));
305
+ }
306
+ }
307
+ Mirror.propTypes = {
308
+ canvasStyle: _propTypes.default.object,
309
+ chart: _propTypes.default.object,
310
+ groupbyColumn: _propTypes.default.object,
311
+ columnGroupbyColumn: _propTypes.default.object,
312
+ summaryColumn: _propTypes.default.object,
313
+ result: _propTypes.default.object,
314
+ tables: _propTypes.default.array,
315
+ globalTheme: _propTypes.default.string,
316
+ chartColorTheme: _propTypes.default.string,
317
+ toggleRecords: _propTypes.default.func,
318
+ customRender: _propTypes.default.func
319
+ };
320
+ var _default = exports.default = Mirror;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sea-chart",
3
- "version": "2.0.30",
3
+ "version": "2.0.31",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "@dnd-kit/core": "^6.1.0",