sea-chart 2.0.6 → 2.0.8

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.
@@ -23,7 +23,8 @@ const TypesDialog = _ref => {
23
23
  lang,
24
24
  onToggle: propsOnToggle,
25
25
  onChange,
26
- dataSources
26
+ dataSources,
27
+ hideTypeToggle
27
28
  } = _ref;
28
29
  const [currentCatIndex, setCurrentCatIndex] = (0, _react.useState)(0);
29
30
  const [selectedType, setType] = (0, _react.useState)(type);
@@ -66,11 +67,20 @@ const TypesDialog = _ref => {
66
67
  onChange(selectedType);
67
68
  onToggle();
68
69
  }, [onChange, selectedType, onToggle]);
70
+ const handleFilterTypes = (0, _react.useCallback)(() => {
71
+ if (hideTypeToggle) {
72
+ const newChartTypes = _constants.CHART_TYPES.filter(item => ['Histogram'].includes(item.name));
73
+ newChartTypes.forEach(item => {
74
+ item.children = item.children.slice(0, 3);
75
+ });
76
+ return newChartTypes;
77
+ }
78
+ return _constants.CHART_TYPES;
79
+ }, [hideTypeToggle]);
69
80
  return /*#__PURE__*/_react.default.createElement(_reactstrap.Modal, {
70
81
  isOpen: true,
71
82
  toggle: onToggle,
72
- className: "sea-chart-types-dialog",
73
- zIndex: 1048
83
+ className: "sea-chart-types-dialog"
74
84
  }, /*#__PURE__*/_react.default.createElement(_DTableModalHeader2.default, {
75
85
  toggle: onToggle
76
86
  }, type ? _intl.default.get('Edit_type') : _intl.default.get('All_charts')), /*#__PURE__*/_react.default.createElement(_reactstrap.ModalBody, {
@@ -79,7 +89,7 @@ const TypesDialog = _ref => {
79
89
  className: "sea-chart-types-container d-flex flex-column h-100"
80
90
  }, /*#__PURE__*/_react.default.createElement("ul", {
81
91
  className: "sea-chart-chart-categories-nav flex-shrink-0 d-flex flex-wrap align-items-center list-unstyled"
82
- }, _constants.CHART_TYPES.map((item, index) => {
92
+ }, handleFilterTypes().map((item, index) => {
83
93
  return /*#__PURE__*/_react.default.createElement("li", {
84
94
  key: index,
85
95
  className: "px-4 py-2 sea-chart-chart-cat-nav-item"
@@ -101,7 +111,7 @@ const TypesDialog = _ref => {
101
111
  })), /*#__PURE__*/_react.default.createElement("div", {
102
112
  className: "flex-fill o-auto sea-chart-type-container",
103
113
  ref: seaChartTypeContainerRef
104
- }, _constants.CHART_TYPES.map((item, index) => {
114
+ }, handleFilterTypes().map((item, index) => {
105
115
  return /*#__PURE__*/_react.default.createElement("div", {
106
116
  key: "sea-chart-type-".concat(index),
107
117
  className: "mb-7"
@@ -11,11 +11,11 @@ var _DTableRadioGroup2 = _interopRequireDefault(require("dtable-ui-component/lib
11
11
  var _DTableSwitch2 = _interopRequireDefault(require("dtable-ui-component/lib/DTableSwitch"));
12
12
  var _react = _interopRequireWildcard(require("react"));
13
13
  var _reactstrap = require("reactstrap");
14
- var _constants = require("dtable-ui-component/lib/constants");
14
+ var _dtableUtils = require("dtable-utils");
15
15
  var _divider = _interopRequireDefault(require("../widgets/divider"));
16
16
  var _minMaxSetting = _interopRequireDefault(require("../widgets/min-max-setting"));
17
17
  var _displayValuesSettings = _interopRequireDefault(require("../widgets/display-values-settings"));
18
- var _constants2 = require("../../constants");
18
+ var _constants = require("../../constants");
19
19
  var _intl = _interopRequireDefault(require("../../intl"));
20
20
  var _selectLineType = _interopRequireDefault(require("../widgets/select-line-type"));
21
21
  var _colorSelector = _interopRequireDefault(require("../../components/chart-color-selector/color-selector"));
@@ -60,20 +60,20 @@ const StyleSettings = _ref => {
60
60
  } = style_config || {};
61
61
  const table = tables.find(table => table._id === table_id);
62
62
  const column = (0, _utils.getColumnByKey)(column_groupby_column_key, table.columns);
63
- const isGroupBySingleSelectColumn = (column === null || column === void 0 ? void 0 : column.type) === _constants.CellType.SINGLE_SELECT;
63
+ const isGroupBySingleSelectColumn = (column === null || column === void 0 ? void 0 : column.type) === _dtableUtils.CellType.SINGLE_SELECT;
64
64
  const defaultColorTheme = _colorRules.SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.DEFAULT;
65
65
  const [currYaxisTitle, setCurrYaxisTitle] = (0, _react.useState)(title_name || '');
66
66
  const xAxisLabelOptions = (0, _react.useMemo)(() => {
67
67
  if (xLabel === 'Vertical_axis') {
68
- return _constants2.Y_LABEL_POSITIONS;
68
+ return _constants.Y_LABEL_POSITIONS;
69
69
  }
70
- return _constants2.X_LABEL_POSITIONS;
70
+ return _constants.X_LABEL_POSITIONS;
71
71
  }, [xLabel]);
72
72
  const yAxisLabelOptions = (0, _react.useMemo)(() => {
73
73
  if (yLabel === 'Horizontal_axis') {
74
- return _constants2.X_LABEL_POSITIONS;
74
+ return _constants.X_LABEL_POSITIONS;
75
75
  }
76
- return _constants2.Y_LABEL_POSITIONS;
76
+ return _constants.Y_LABEL_POSITIONS;
77
77
  }, [yLabel]);
78
78
  const onAxisLabelShowChange = (0, _react.useCallback)(labelKey => {
79
79
  const {
@@ -162,12 +162,12 @@ const StyleSettings = _ref => {
162
162
  }, []);
163
163
  const xAxisLabelPosition = x_axis_label_position || xAxisLabelOptions[0];
164
164
  const yAxisLabelPosition = y_axis_label_position || yAxisLabelOptions[0];
165
- const isLineChart = [_constants2.CHART_TYPE.LINE, _constants2.CHART_TYPE.LINE_GROUP, _constants2.CHART_TYPE.AREA, _constants2.CHART_TYPE.AREA_GROUP].includes(type);
165
+ const isLineChart = [_constants.CHART_TYPE.LINE, _constants.CHART_TYPE.LINE_GROUP, _constants.CHART_TYPE.AREA, _constants.CHART_TYPE.AREA_GROUP].includes(type);
166
166
  const getLabelOptionsDisplay = options => {
167
167
  return options.reduce((optionDisplayMap, position) => {
168
168
  return {
169
169
  ...optionDisplayMap,
170
- [position]: _intl.default.get(_constants2.LABEL_POSITION_TYPE_SHOW[position])
170
+ [position]: _intl.default.get(_constants.LABEL_POSITION_TYPE_SHOW[position])
171
171
  };
172
172
  }, {});
173
173
  };
@@ -196,7 +196,7 @@ const StyleSettings = _ref => {
196
196
  checked: y_axis_show_label || false,
197
197
  placeholder: _intl.default.get('Display_title'),
198
198
  onChange: () => onAxisLabelShowChange('y_axis_show_label')
199
- }), y_axis_show_label && [_constants2.CHART_TYPE.BAR_STACK].includes(type) && /*#__PURE__*/_react.default.createElement("div", {
199
+ }), y_axis_show_label && [_constants.CHART_TYPE.BAR_STACK].includes(type) && /*#__PURE__*/_react.default.createElement("div", {
200
200
  className: "mt-3"
201
201
  }, /*#__PURE__*/_react.default.createElement(_reactstrap.Label, {
202
202
  for: "y-axis-custom-title-input"
@@ -218,7 +218,7 @@ const StyleSettings = _ref => {
218
218
  options: yAxisLabelOptions,
219
219
  optionsDisplay: getLabelOptionsDisplay(yAxisLabelOptions),
220
220
  onSelectChanged: position => onAxisLabelPositionChange(position, 'y_axis_label_position')
221
- })), ![_constants2.CHART_TYPE.BAR_CUSTOM].includes(type) && /*#__PURE__*/_react.default.createElement(_DTableSwitch2.default, {
221
+ })), ![_constants.CHART_TYPE.BAR_CUSTOM].includes(type) && /*#__PURE__*/_react.default.createElement(_DTableSwitch2.default, {
222
222
  key: "y_axis_auto_range",
223
223
  switchClassName: "mt-3",
224
224
  checked: y_axis_auto_range,
@@ -235,18 +235,18 @@ const StyleSettings = _ref => {
235
235
  }), isGroupBySingleSelectColumn && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_divider.default, null), /*#__PURE__*/_react.default.createElement(_colorSelector.default, {
236
236
  colorTheme: color_theme || defaultColorTheme,
237
237
  onChange: onChartColorChange
238
- })), /*#__PURE__*/_react.default.createElement(_divider.default, null), _constants2.SUPPORT_GOAL_LINE_CHART_TYPES.includes(type) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_goalLineSetting.default, {
238
+ })), /*#__PURE__*/_react.default.createElement(_divider.default, null), _constants.SUPPORT_GOAL_LINE_CHART_TYPES.includes(type) && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_goalLineSetting.default, {
239
239
  displayGoalLine: display_goal_line,
240
240
  goalLabel: goal_label,
241
241
  goalValue: goal_value,
242
242
  onChange: onStyleChange
243
- }), /*#__PURE__*/_react.default.createElement(_divider.default, null)), ![_constants2.CHART_TYPE.BAR_CUSTOM].includes(type) && /*#__PURE__*/_react.default.createElement(_displayValuesSettings.default, {
243
+ }), /*#__PURE__*/_react.default.createElement(_divider.default, null)), ![_constants.CHART_TYPE.BAR_CUSTOM].includes(type) && /*#__PURE__*/_react.default.createElement(_displayValuesSettings.default, {
244
244
  isShowValueKey: "y_axis_show_value",
245
245
  isShowValue: y_axis_show_value,
246
246
  fontSizeKey: "label_font_size",
247
247
  fontSize: label_font_size,
248
248
  onChange: onDisplayValueChange
249
- }), _constants2.SUPPORT_STACK_VALUE_CHART_TYPES.includes(type) && /*#__PURE__*/_react.default.createElement(_DTableSwitch2.default, {
249
+ }), _constants.SUPPORT_STACK_VALUE_CHART_TYPES.includes(type) && /*#__PURE__*/_react.default.createElement(_DTableSwitch2.default, {
250
250
  switchClassName: "display-value-settings",
251
251
  checked: display_each_block_data,
252
252
  disabled: false,
@@ -11,12 +11,12 @@ var _DTableSelect2 = _interopRequireDefault(require("dtable-ui-component/lib/DTa
11
11
  var _DTableSwitch2 = _interopRequireDefault(require("dtable-ui-component/lib/DTableSwitch"));
12
12
  var _react = _interopRequireWildcard(require("react"));
13
13
  var _reactstrap = require("reactstrap");
14
- var _constants = require("dtable-ui-component/lib/constants");
14
+ var _dtableUtils = require("dtable-utils");
15
15
  var _divider = _interopRequireDefault(require("../widgets/divider"));
16
16
  var _mininumSlicePercent = _interopRequireDefault(require("../widgets/mininum-slice-percent"));
17
17
  var _fontSettings = require("../widgets/font-settings");
18
18
  var _utils = require("../../utils");
19
- var _constants2 = require("../../constants");
19
+ var _constants = require("../../constants");
20
20
  var _intl = _interopRequireDefault(require("../../intl"));
21
21
  var _colorRules = require("../../constants/color-rules");
22
22
  var _colorSelector = _interopRequireDefault(require("../../components/chart-color-selector/color-selector"));
@@ -27,18 +27,18 @@ const StyleSettings = _ref => {
27
27
  tables
28
28
  } = _ref;
29
29
  const labelPositionOptions = (0, _react.useMemo)(() => {
30
- return _constants2.CHART_LABEL_POSITIONS.map(item => {
30
+ return _constants.CHART_LABEL_POSITIONS.map(item => {
31
31
  return {
32
32
  value: item,
33
- label: _intl.default.get(_constants2.CHART_LABEL_POSITION_SHOW[item])
33
+ label: _intl.default.get(_constants.CHART_LABEL_POSITION_SHOW[item])
34
34
  };
35
35
  });
36
36
  }, []);
37
37
  const labelFormatOptions = (0, _react.useMemo)(() => {
38
- return _constants2.CHART_LABEL_FORMATS.map(item => {
38
+ return _constants.CHART_LABEL_FORMATS.map(item => {
39
39
  return {
40
40
  value: item,
41
- label: _intl.default.get(_constants2.CHART_LABEL_FORMAT_SHOW[item])
41
+ label: _intl.default.get(_constants.CHART_LABEL_FORMAT_SHOW[item])
42
42
  };
43
43
  });
44
44
  }, []);
@@ -122,7 +122,7 @@ const StyleSettings = _ref => {
122
122
  } = config;
123
123
  const table = tables.find(table => table._id === table_id);
124
124
  const column = (0, _utils.getColumnByKey)(groupby_column_key, table.columns);
125
- const isGroupBySingleSelectColumn = (column === null || column === void 0 ? void 0 : column.type) === _constants.CellType.SINGLE_SELECT;
125
+ const isGroupBySingleSelectColumn = (column === null || column === void 0 ? void 0 : column.type) === _dtableUtils.CellType.SINGLE_SELECT;
126
126
  const defaultColorTheme = _colorRules.SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.DEFAULT;
127
127
  const selectedLabelOption = labelPositionOptions.find(item => item.value === label_position);
128
128
  const selectedLabelFormat = labelFormatOptions.find(item => item.value === label_format) || labelFormatOptions[0];
@@ -42,10 +42,13 @@ const ChartType = _ref => {
42
42
  if (type === oldType) return;
43
43
 
44
44
  // reset these two configs to preventing new type getting into the wrong calculator
45
- config.column_groupby_column_key = null;
46
- config.column_groupby_multiple_numeric_column = null;
47
- const convertedChart = generateChartConfig({
45
+ const newConfig = {
48
46
  ...config,
47
+ column_groupby_column_key: null,
48
+ column_groupby_multiple_numeric_column: null
49
+ };
50
+ const convertedChart = generateChartConfig({
51
+ ...newConfig,
49
52
  type
50
53
  });
51
54
  onChange && onChange(convertedChart);
@@ -60,11 +63,8 @@ const ChartType = _ref => {
60
63
  className: "sea-chart-parameter-item",
61
64
  id: "sea-chart-type-container"
62
65
  }, /*#__PURE__*/_react.default.createElement(_reactstrap.Label, null, _intl.default.get('Chart_type')), /*#__PURE__*/_react.default.createElement("div", {
63
- className: "sea-chart-selected-type-container d-flex align-items-center",
64
- style: {
65
- backgroundColor: hideTypeToggle ? '#f5f5f5' : '#fff'
66
- }
67
- }, /*#__PURE__*/_react.default.createElement("span", null, _intl.default.get(_constants.CHART_TYPE_SHOW[type])), !hideTypeToggle && /*#__PURE__*/_react.default.createElement("div", {
66
+ className: "sea-chart-selected-type-container d-flex align-items-center"
67
+ }, /*#__PURE__*/_react.default.createElement("span", null, _intl.default.get(_constants.CHART_TYPE_SHOW[type])), /*#__PURE__*/_react.default.createElement("div", {
68
68
  className: "sea-chart-type-icon-container",
69
69
  onClick: openTypesDialog
70
70
  }, /*#__PURE__*/_react.default.createElement(_components.Icon, {
@@ -74,7 +74,8 @@ const ChartType = _ref => {
74
74
  dataSources: dataSources,
75
75
  type: type,
76
76
  onToggle: closeTypesDialog,
77
- onChange: onTypeChange
77
+ onChange: onTypeChange,
78
+ hideTypeToggle: hideTypeToggle
78
79
  }));
79
80
  };
80
81
  var _default = exports.default = ChartType;
@@ -0,0 +1,292 @@
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 _dtableUtils = require("dtable-utils");
12
+ var _lodashEs = require("lodash-es");
13
+ var d3 = _interopRequireWildcard(require("d3"));
14
+ var _intl = _interopRequireDefault(require("../../intl"));
15
+ var _columnUtils = require("../../utils/column-utils");
16
+ var _constants = require("../../constants");
17
+ var _utils = require("../../utils");
18
+ var _colorRules = require("../../constants/color-rules");
19
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
20
+ class BarGroup extends _chartComponent.default {
21
+ constructor(props) {
22
+ super(props);
23
+ this.handleResize = () => {
24
+ this.chart.node() && this.chart.node().remove();
25
+ this.createChart();
26
+ this.drawChart();
27
+ };
28
+ this.createChart = () => {
29
+ const {
30
+ chart
31
+ } = this.props;
32
+ const initConfig = {
33
+ insertPadding: 30,
34
+ borderRadius: 10,
35
+ overflowHeight: 20 // Fillet the bottom corner beyond the axis and then cover it with a mask
36
+ };
37
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
38
+ this.initDefs();
39
+ };
40
+ this.drawChart = () => {
41
+ const {
42
+ customRender
43
+ } = this.props;
44
+ let {
45
+ result: data
46
+ } = this.props;
47
+ data = _utils.BaseUtils.formatEmptyName(data, '', _intl.default.get('Empty'));
48
+ if (!Array.isArray(data)) return;
49
+ const {
50
+ chart
51
+ } = this.props;
52
+ const {
53
+ sort_type,
54
+ type
55
+ } = chart.config;
56
+ if (type === _constants.CHART_TYPE.BAR_STACK && sort_type) {
57
+ data = (0, _columnUtils.sortDataByGroupSum)(data, sort_type);
58
+ }
59
+ this.draw(data);
60
+ this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
61
+ (0, _utils.isFunction)(customRender) && customRender(this.chart);
62
+ };
63
+ this.draw = data => {
64
+ const {
65
+ chart,
66
+ globalTheme,
67
+ chartColorTheme,
68
+ tables,
69
+ canvasStyle
70
+ } = this.props;
71
+ const {
72
+ display_goal_line,
73
+ goal_value,
74
+ goal_label
75
+ } = chart.style_config || {};
76
+ const {
77
+ previewType
78
+ } = canvasStyle || {};
79
+ const {
80
+ width: chartWidth,
81
+ height: chartHeight,
82
+ insertPadding,
83
+ borderRadius,
84
+ overflowHeight
85
+ } = this.chartBoundingClientRect;
86
+ const {
87
+ type,
88
+ y_axis_show_value,
89
+ label_font_size,
90
+ table_id,
91
+ column_groupby_column_key,
92
+ color_theme,
93
+ y_axis_max,
94
+ y_axis_min,
95
+ y_axis_auto_range,
96
+ display_each_block_data
97
+ } = chart.config;
98
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
99
+ const column_groupby_column = this.getColumn(tables, table_id, column_groupby_column_key);
100
+ const useSingleSelectColumnColor = (column_groupby_column === null || column_groupby_column === void 0 ? void 0 : column_groupby_column.type) === _dtableUtils.CellType.SINGLE_SELECT && color_theme === _colorRules.SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
101
+ useSingleSelectColumnColor ? this.setSingleSelectColorMap(data) : this.setColorMap(data, chartColorTheme); // use single select column color
102
+
103
+ const fx = d3.scaleBand().domain(new Set(data.map(d => d.name))).range([insertPadding, chartWidth - insertPadding]).paddingInner(0.1);
104
+ const x = d3.scaleBand().domain(new Set(data.map(d => d.group_name))).range([0, fx.bandwidth()]);
105
+ const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, d3.max(data, d => d.value)] : [y_axis_min, y_axis_max]).range([chartHeight - insertPadding, insertPadding]);
106
+
107
+ // X axis
108
+ this.chart.append('g').attr('transform', "translate(0,".concat(chartHeight - insertPadding, ")")).call(d3.axisBottom(fx).tickSizeOuter(0).tickSizeInner(5)).call(g => {
109
+ g.selectAll('.domain').attr('stroke', theme.XAxisColor);
110
+ g.selectAll('.tick line').attr('stroke', theme.XAxisColor);
111
+ g.selectAll('text').attr('font-size', theme.fontSize);
112
+ g.selectAll('text').attr('fill', theme.textColor);
113
+ });
114
+
115
+ // Y axis
116
+ this.chart.append('g').attr('transform', "translate(".concat(insertPadding, ",0)")).call(d3.axisLeft(y).tickSizeInner(0).ticks(5).tickFormat(d => d)).call(g => {
117
+ g.select('.domain').remove();
118
+ g.selectAll('line').node() && g.selectAll('line').node().remove(); // delete the first line
119
+ g.selectAll('.tick line').clone().attr('x2', chartWidth - insertPadding * 2).attr('stroke', theme.gridColor).attr('stroke-dasharray', '8,3');
120
+ g.selectAll('text').attr('font-size', theme.fontSize);
121
+ g.selectAll('text').attr('fill', theme.textColor);
122
+ });
123
+
124
+ // Rect group
125
+ this.chart.append('g').attr('mask', "url(#mask-wrapper-".concat(previewType, "-").concat(chart === null || chart === void 0 ? void 0 : chart.id, ")")).selectAll().data(d3.group(data, d => d.name)).join('g').attr('transform', _ref => {
126
+ let [name, dum] = _ref;
127
+ // Each group is horizontally centered
128
+ const offset = (fx.bandwidth() - dum.length * x.bandwidth()) / 2;
129
+ return "translate(".concat(fx(name) + offset, ",0)");
130
+ })
131
+ // rect item
132
+ .selectAll().data(_ref2 => {
133
+ let [_, d] = _ref2;
134
+ return d;
135
+ }).join('rect').attr('x', (d, index) => index * x.bandwidth()).attr('y', d => y(d.value)).attr('width', x.bandwidth()).attr('height', d => y(0) - y(d.value) + overflowHeight).attr('rx', borderRadius).attr('fill', d => this.colorMap[d.group_name] || _constants.CHART_STYLE_COLORS[0]).attr('data-value', d => d.value).attr('data-groupName', d => d.name).call(g => {
136
+ g.nodes().forEach(rect => {
137
+ const parentNode = rect.parentNode;
138
+ // Add label
139
+ if (type === _constants.CHART_TYPE.BAR_STACK) {
140
+ if (y_axis_show_value) {
141
+ this.addLabelToRectCenter({
142
+ chartType: _constants.CHART_TYPE.BAR_STACK,
143
+ container: parentNode,
144
+ x: Number(rect.getAttribute('x')),
145
+ y: Number(rect.getAttribute('y')),
146
+ xWidth: x.bandwidth(),
147
+ yheight: Number(rect.getAttribute('height')),
148
+ theme,
149
+ label_font_size,
150
+ text: rect.getAttribute('data-value'),
151
+ overflowHeight
152
+ });
153
+ }
154
+ if (display_each_block_data) {
155
+ this.addLabelToRectTop({
156
+ container: parentNode,
157
+ xWidth: Number(x.bandwidth()),
158
+ x: Number(rect.getAttribute('x')),
159
+ y: Number(rect.getAttribute('y')),
160
+ theme,
161
+ label_font_size,
162
+ text: rect.dataset.value
163
+ });
164
+ }
165
+ return;
166
+ }
167
+ if (y_axis_show_value) {
168
+ this.addLabelToRectTop({
169
+ container: parentNode,
170
+ xWidth: Number(x.bandwidth()),
171
+ x: Number(rect.getAttribute('x')),
172
+ y: Number(rect.getAttribute('y')),
173
+ theme,
174
+ label_font_size,
175
+ text: rect.dataset.value
176
+ });
177
+ }
178
+ });
179
+ }).on('click', (event, data) => {
180
+ this.props.toggleRecords(data);
181
+ }).on('mouseover', event => {
182
+ this.showTooltip(event);
183
+ this.handleAcitveAndInActiveState('inActive', event);
184
+ }).on('mousemove', event => {
185
+ this.moveTooltip(event);
186
+ }).on('mouseleave', (event, data) => {
187
+ this.hiddenTooltip();
188
+ this.handleAcitveAndInActiveState('active', event);
189
+ });
190
+ if (display_goal_line && goal_label && goal_value) {
191
+ this.setDispalyGoalLine(goal_label, goal_value, insertPadding, y);
192
+ }
193
+ this.setLegend('group_name', theme, 'top-right', data);
194
+ };
195
+ this.showTooltip = event => {
196
+ const {
197
+ offsetX,
198
+ offsetY
199
+ } = event;
200
+ const curGroup = event.target.parentNode;
201
+ const [curGroupName, data] = curGroup.__data__;
202
+ const newTooltipData = {
203
+ title: !curGroupName && typeof curGroupName !== 'number' ? _intl.default.get(_constants.EMPTY_NAME) : curGroupName,
204
+ items: data.map(item => {
205
+ return {
206
+ color: this.colorMap[item.group_name],
207
+ name: item.group_name,
208
+ value: item.value
209
+ };
210
+ })
211
+ };
212
+ this.setState({
213
+ tooltipData: newTooltipData
214
+ });
215
+ this.setState({
216
+ toolTipPosition: {
217
+ offsetX,
218
+ offsetY
219
+ }
220
+ });
221
+ };
222
+ this.moveTooltip = event => {
223
+ const {
224
+ offsetX,
225
+ offsetY
226
+ } = event;
227
+ this.setState({
228
+ toolTipPosition: {
229
+ offsetX,
230
+ offsetY
231
+ }
232
+ });
233
+ };
234
+ this.hiddenTooltip = event => {
235
+ this.setState({
236
+ toolTipPosition: null
237
+ });
238
+ };
239
+ this.handleAcitveAndInActiveState = (state, event) => {
240
+ const curGroup = event.target.parentNode;
241
+ const allGroup = Array.from(curGroup.parentNode.children);
242
+ const [curGroupName] = curGroup.__data__;
243
+ this.setActiveAndInActiveState(state, allGroup, curGroupName);
244
+ };
245
+ this.chart = null;
246
+ this.state = {
247
+ tooltipData: null,
248
+ toolTipPosition: null
249
+ };
250
+ }
251
+ componentDidMount() {
252
+ this.createChart();
253
+ this.drawChart();
254
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
255
+ window.addEventListener('resize', this.debouncedHandleResize);
256
+ }
257
+ componentDidUpdate(prevProps) {
258
+ super.componentDidUpdate(prevProps);
259
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
260
+ this.createChart();
261
+ this.drawChart();
262
+ }
263
+ }
264
+ componentWillUnmount() {
265
+ this.chart.node() && this.chart.node().remove();
266
+ window.removeEventListener('resize', this.debouncedHandleResize);
267
+ }
268
+ render() {
269
+ const {
270
+ tooltipData,
271
+ toolTipPosition
272
+ } = this.state;
273
+ return /*#__PURE__*/_react.default.createElement("div", {
274
+ className: "sea-chart-container",
275
+ ref: ref => this.container = ref
276
+ }, this.getToolTipContainer(tooltipData, toolTipPosition));
277
+ }
278
+ }
279
+ BarGroup.propTypes = {
280
+ canvasStyle: _propTypes.default.object,
281
+ chart: _propTypes.default.object,
282
+ groupbyColumn: _propTypes.default.object,
283
+ columnGroupbyColumn: _propTypes.default.object,
284
+ summaryColumn: _propTypes.default.object,
285
+ result: _propTypes.default.array,
286
+ tables: _propTypes.default.array,
287
+ globalTheme: _propTypes.default.string,
288
+ chartColorTheme: _propTypes.default.string,
289
+ toggleRecords: _propTypes.default.func,
290
+ customRender: _propTypes.default.func
291
+ };
292
+ var _default = exports.default = BarGroup;
@@ -0,0 +1,332 @@
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 _dtableUtils = require("dtable-utils");
12
+ var _lodashEs = require("lodash-es");
13
+ var d3 = _interopRequireWildcard(require("d3"));
14
+ var _intl = _interopRequireDefault(require("../../intl"));
15
+ var _columnUtils = require("../../utils/column-utils");
16
+ var _constants = require("../../constants");
17
+ var _utils = require("../../utils");
18
+ var _colorRules = require("../../constants/color-rules");
19
+ var _chartComponent = _interopRequireDefault(require("./chart-component"));
20
+ class BarStack extends _chartComponent.default {
21
+ constructor(props) {
22
+ super(props);
23
+ this.handleResize = () => {
24
+ this.chart.node() && this.chart.node().remove();
25
+ this.createChart();
26
+ this.drawChart();
27
+ };
28
+ this.createChart = () => {
29
+ const {
30
+ chart
31
+ } = this.props;
32
+ const initConfig = {
33
+ insertPadding: 30,
34
+ borderRadius: 10
35
+ };
36
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
37
+ };
38
+ this.drawChart = () => {
39
+ const {
40
+ customRender
41
+ } = this.props;
42
+ let {
43
+ result: data
44
+ } = this.props;
45
+ data = _utils.BaseUtils.formatEmptyName(data, '', _intl.default.get('Empty'));
46
+ if (!Array.isArray(data)) return;
47
+ const {
48
+ chart
49
+ } = this.props;
50
+ const {
51
+ sort_type,
52
+ type
53
+ } = chart.config;
54
+ if (type === _constants.CHART_TYPE.BAR_STACK && sort_type) {
55
+ data = (0, _columnUtils.sortDataByGroupSum)(data, sort_type);
56
+ }
57
+ this.draw(data);
58
+ this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
59
+ (0, _utils.isFunction)(customRender) && customRender(this.chart);
60
+ };
61
+ this.draw = data => {
62
+ const {
63
+ chart,
64
+ globalTheme,
65
+ chartColorTheme,
66
+ tables
67
+ } = this.props;
68
+ const {
69
+ display_goal_line,
70
+ goal_value,
71
+ goal_label
72
+ } = chart.style_config || {};
73
+ const {
74
+ y_axis_show_value,
75
+ display_each_block_data,
76
+ table_id,
77
+ column_groupby_column_key,
78
+ color_theme,
79
+ y_axis_max,
80
+ y_axis_min,
81
+ y_axis_auto_range
82
+ } = chart.config;
83
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
84
+ const column_groupby_column = this.getColumn(tables, table_id, column_groupby_column_key);
85
+ const useSingleSelectColumnColor = (column_groupby_column === null || column_groupby_column === void 0 ? void 0 : column_groupby_column.type) === _dtableUtils.CellType.SINGLE_SELECT && color_theme === _colorRules.SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
86
+ // use single select column color
87
+ useSingleSelectColumnColor ? this.setSingleSelectColorMap(data) : this.setColorMap(data, chartColorTheme);
88
+ const {
89
+ width: chartWidth,
90
+ height: chartHeight,
91
+ insertPadding
92
+ } = this.chartBoundingClientRect;
93
+ const series = d3.stack().keys(d3.union(data.map(d => d.group_name))).value((_ref, key) => {
94
+ var _group$get;
95
+ let [_, group] = _ref;
96
+ return (_group$get = group.get(String(key))) === null || _group$get === void 0 ? void 0 : _group$get.value;
97
+ })(d3.index(data, d => d.name, d => d.group_name));
98
+ const x = d3.scaleBand().domain(d3.group(data, d => d.name).keys()).range([insertPadding, chartWidth - insertPadding]).paddingInner(0.1).paddingOuter(0.1);
99
+ const niceEnd = d3.nice(0, d3.max(series, d => d3.max(d, d => d[1])), 5)[1];
100
+ const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, niceEnd] : [y_axis_min, y_axis_max]).range([chartHeight - insertPadding, insertPadding]);
101
+
102
+ // X axis
103
+ this.chart.append('g').attr('transform', "translate(0,".concat(chartHeight - insertPadding, ")")).call(d3.axisBottom(x).tickSizeOuter(0).tickSizeInner(5)).call(g => {
104
+ g.selectAll('.domain').attr('stroke', theme.XAxisColor);
105
+ g.selectAll('.tick line').attr('stroke', theme.XAxisColor);
106
+ g.selectAll('text').attr('font-size', theme.fontSize);
107
+ g.selectAll('text').attr('fill', theme.textColor);
108
+ });
109
+
110
+ // Y axis
111
+ this.chart.append('g').attr('transform', "translate(".concat(insertPadding, ",0)")).call(d3.axisLeft(y).tickSizeInner(0).ticks(5).tickFormat(d => d)).call(g => {
112
+ g.select('.domain').remove();
113
+ g.selectAll('line').node() && g.selectAll('line').node().remove(); // delete the first line
114
+ g.selectAll('.tick line').clone().attr('x2', chartWidth - insertPadding * 2).attr('stroke', theme.gridColor).attr('stroke-dasharray', '8,3');
115
+ g.selectAll('text').attr('font-size', theme.fontSize);
116
+ g.selectAll('text').attr('fill', theme.textColor);
117
+ });
118
+
119
+ // Rect group
120
+ this.chart.append('g').attr('class', "rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id)).selectAll().data(series).join('g').attr('data-key', d => d.key).selectAll('rect').data(D => {
121
+ const data = D.map(d => {
122
+ d.key = D.key;
123
+ return d;
124
+ });
125
+ return data;
126
+ }).join('rect').attr('x', d => x(d.data[0])).attr('y', d => y(d[1])).attr('height', d => {
127
+ const height = y(d[0]) - y(d[1]);
128
+ return (0, _lodashEs.isNaN)(height) ? 0 : height;
129
+ }).attr('width', x.bandwidth()).attr('fill', d => this.colorMap[d.key] || _constants.CHART_STYLE_COLORS[0]).attr('data-value', d => {
130
+ const {
131
+ data,
132
+ key
133
+ } = d;
134
+ const rowData = data[1].get(key);
135
+ return rowData ? rowData.value : 0;
136
+ }).attr('data-groupName', d => {
137
+ const {
138
+ data
139
+ } = d;
140
+ return data[0];
141
+ }).call(g => {
142
+ const [topG] = g._parents.slice(-1);
143
+ Array.from(topG.children).forEach(rect => {
144
+ // Add label (get the total value of each stack)
145
+ if (display_each_block_data) {
146
+ this.addLabelByEachStack(data, topG, rect, x);
147
+ }
148
+ // Add mask rect
149
+ this.addMaskRect(topG, rect, x.bandwidth());
150
+ });
151
+ // Add label
152
+ if (y_axis_show_value) {
153
+ this.handleLabelToRectCenter(g, x.bandwidth());
154
+ }
155
+ }).on('click', (event, data) => {
156
+ this.props.toggleRecords(data);
157
+ }).on('mouseover', event => {
158
+ this.showTooltip(event);
159
+ this.handleAcitveAndInActiveState('inActive', event);
160
+ }).on('mousemove', event => {
161
+ this.moveTooltip(event);
162
+ }).on('mouseleave', (event, data) => {
163
+ this.hiddenTooltip();
164
+ this.handleAcitveAndInActiveState('active', event);
165
+ });
166
+ if (display_goal_line && goal_label && goal_value) {
167
+ this.setDispalyGoalLine(goal_label, goal_value, insertPadding, y);
168
+ }
169
+ this.setLegend('group_name', theme, 'top-right', data);
170
+ };
171
+ this.showTooltip = event => {
172
+ const offsetX = d3.pointer(event)[0];
173
+ const offsetY = d3.pointer(event)[1];
174
+ const curRect = event.currentTarget;
175
+ const curGroup = curRect.parentNode;
176
+ const curGroupName = event.currentTarget.getAttribute('data-groupName');
177
+ const newTooltipData = {
178
+ title: !curGroupName && typeof curGroupName !== 'number' ? _intl.default.get(_constants.EMPTY_NAME) : curGroupName,
179
+ items: [{
180
+ color: this.colorMap[curGroup.getAttribute('data-key')],
181
+ name: curGroup.getAttribute('data-key'),
182
+ value: curRect.getAttribute('data-value')
183
+ }]
184
+ };
185
+ this.setState({
186
+ tooltipData: newTooltipData
187
+ });
188
+ this.setState({
189
+ toolTipPosition: {
190
+ offsetX,
191
+ offsetY
192
+ }
193
+ });
194
+ };
195
+ this.moveTooltip = event => {
196
+ const offsetX = d3.pointer(event)[0];
197
+ const offsetY = d3.pointer(event)[1];
198
+ this.setState({
199
+ toolTipPosition: {
200
+ offsetX,
201
+ offsetY
202
+ }
203
+ });
204
+ };
205
+ this.hiddenTooltip = event => {
206
+ this.setState({
207
+ toolTipPosition: null
208
+ });
209
+ };
210
+ this.handleAcitveAndInActiveState = (state, event) => {
211
+ const {
212
+ chart
213
+ } = this.props;
214
+ const rectsWrapper = d3.selectAll(".rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id));
215
+ const allGroup = Array.from(rectsWrapper.node().children);
216
+ const curGroupName = event.currentTarget.getAttribute('data-groupName');
217
+ this.setActiveAndInActiveState(state, allGroup, curGroupName);
218
+ };
219
+ this.addMaskRect = (topG, rect, xWidth) => {
220
+ const {
221
+ borderRadius
222
+ } = this.chartBoundingClientRect;
223
+ // Add mask rect
224
+ d3.select(topG).append('foreignObject').attr('x', rect.getAttribute('x')).attr('y', rect.getAttribute('y')).attr('width', xWidth).attr('height', rect.getAttribute('height')).attr('data-groupName', rect.getAttribute('data-groupName')).attr('data-value', rect.getAttribute('data-value')).on('click', (event, data) => {
225
+ this.props.toggleRecords(data);
226
+ }).on('mouseover', event => {
227
+ this.showTooltip(event);
228
+ this.handleAcitveAndInActiveState('inActive', event);
229
+ }).on('mousemove', event => {
230
+ this.moveTooltip(event);
231
+ }).on('mouseleave', (event, data) => {
232
+ this.hiddenTooltip();
233
+ this.handleAcitveAndInActiveState('active', event);
234
+ }).append('xhtml:div').attr('style', "width: 100%; height: 100%; background-color: ".concat(rect.getAttribute('fill'), "; border-radius: ").concat(borderRadius, "px ").concat(borderRadius, "px 0px 0px"));
235
+
236
+ // Remove old rect
237
+ d3.select(rect).remove();
238
+ };
239
+ this.addLabelByEachStack = (data, topG, rect, x) => {
240
+ const {
241
+ globalTheme,
242
+ chart
243
+ } = this.props;
244
+ const {
245
+ label_font_size
246
+ } = chart.config;
247
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
248
+ const groupData = d3.group(data, d => d.name);
249
+ const group_name = rect.getAttribute('data-groupName');
250
+ const stackSum = groupData.get(group_name).reduce((p, n) => p.value + n.value);
251
+ this.addLabelToRectTop({
252
+ container: topG,
253
+ xWidth: Number(x.bandwidth()),
254
+ x: Number(rect.getAttribute('x')),
255
+ y: Number(rect.getAttribute('y')),
256
+ theme,
257
+ label_font_size,
258
+ text: stackSum
259
+ });
260
+ };
261
+ this.handleLabelToRectCenter = (g, xWidth) => {
262
+ const {
263
+ globalTheme,
264
+ chart
265
+ } = this.props;
266
+ const {
267
+ label_font_size
268
+ } = chart.config;
269
+ const theme = _constants.CHART_THEME_COLOR[globalTheme];
270
+ g._parents.forEach(group => {
271
+ Array.from(group.children).forEach(rect => {
272
+ this.addLabelToRectCenter({
273
+ container: group,
274
+ x: Number(rect.getAttribute('x')),
275
+ y: Number(rect.getAttribute('y')),
276
+ xWidth,
277
+ yheight: Number(rect.getAttribute('height')),
278
+ theme,
279
+ label_font_size,
280
+ text: rect.getAttribute('data-value')
281
+ });
282
+ });
283
+ });
284
+ };
285
+ this.chart = null;
286
+ this.state = {
287
+ tooltipData: null,
288
+ toolTipPosition: null
289
+ };
290
+ }
291
+ componentDidMount() {
292
+ this.createChart();
293
+ this.drawChart();
294
+ this.debouncedHandleResize = (0, _lodashEs.debounce)(this.handleResize, 300);
295
+ window.addEventListener('resize', this.debouncedHandleResize);
296
+ }
297
+ componentDidUpdate(prevProps) {
298
+ super.componentDidUpdate(prevProps);
299
+ if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
300
+ this.createChart();
301
+ this.drawChart();
302
+ }
303
+ }
304
+ componentWillUnmount() {
305
+ this.chart.node() && this.chart.node().remove();
306
+ window.removeEventListener('resize', this.debouncedHandleResize);
307
+ }
308
+ render() {
309
+ const {
310
+ tooltipData,
311
+ toolTipPosition
312
+ } = this.state;
313
+ return /*#__PURE__*/_react.default.createElement("div", {
314
+ className: "sea-chart-container",
315
+ ref: ref => this.container = ref
316
+ }, this.getToolTipContainer(tooltipData, toolTipPosition));
317
+ }
318
+ }
319
+ BarStack.propTypes = {
320
+ canvasStyle: _propTypes.default.object,
321
+ chart: _propTypes.default.object,
322
+ groupbyColumn: _propTypes.default.object,
323
+ columnGroupbyColumn: _propTypes.default.object,
324
+ summaryColumn: _propTypes.default.object,
325
+ result: _propTypes.default.array,
326
+ tables: _propTypes.default.array,
327
+ globalTheme: _propTypes.default.string,
328
+ chartColorTheme: _propTypes.default.string,
329
+ toggleRecords: _propTypes.default.func,
330
+ customRender: _propTypes.default.func
331
+ };
332
+ var _default = exports.default = BarStack;
@@ -24,7 +24,14 @@ class Bar extends _chartComponent.default {
24
24
  this.drawChart();
25
25
  };
26
26
  this.createChart = () => {
27
- this.initChart(this.container);
27
+ const {
28
+ chart
29
+ } = this.props;
30
+ const initConfig = {
31
+ insertPadding: 30,
32
+ borderRadius: 10
33
+ };
34
+ this.initChart(this.container, chart === null || chart === void 0 ? void 0 : chart.id, initConfig);
28
35
  };
29
36
  this.drawChart = () => {
30
37
  const {
@@ -101,22 +108,10 @@ class Bar extends _chartComponent.default {
101
108
  toolTipPosition: null
102
109
  });
103
110
  };
104
- this.setActiveAndInActiveState = (state, data) => {
105
- const {
106
- chart
107
- } = this.props;
108
- const paths = d3.selectAll(".rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id, " path"));
109
- if (state === 'active') {
110
- paths.nodes().forEach(path => {
111
- d3.select(path).attr('opacity', 1);
112
- });
113
- return;
114
- }
115
- paths.nodes().forEach(path => {
116
- if (path.id !== data.slugId) {
117
- d3.select(path).attr('opacity', 0.3);
118
- }
119
- });
111
+ this.handleAcitveAndInActiveState = (state, event) => {
112
+ const allGroup = [event.currentTarget.parentNode];
113
+ const curGroupName = event.currentTarget.getAttribute('data-groupName');
114
+ this.setActiveAndInActiveState(state, allGroup, curGroupName);
120
115
  };
121
116
  this.draw = data => {
122
117
  const {
@@ -144,10 +139,10 @@ class Bar extends _chartComponent.default {
144
139
  const tooltipTitle = this.getTitle(tables, table_id, y_axis_summary_type, y_axis_column_key || y_axis_summary_column_key);
145
140
  const {
146
141
  width: chartWidth,
147
- height: chartHeight
142
+ height: chartHeight,
143
+ insertPadding,
144
+ borderRadius
148
145
  } = this.chartBoundingClientRect;
149
- const insertPadding = 30;
150
- const borderRadius = 10;
151
146
  const x = d3.scaleBand().domain(data.map(item => item.name)).range([insertPadding, chartWidth - insertPadding]).paddingInner(0.4).paddingOuter(0.1);
152
147
  const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, d3.max(data, d => d.value)] : [y_axis_min, y_axis_max]).range([chartHeight - insertPadding, insertPadding]);
153
148
  this.chart.append('g').attr('transform', "translate(0, ".concat(chartHeight - insertPadding, ")")).call(d3.axisBottom(x).tickSizeOuter(0).tickSizeInner(5)).call(g => {
@@ -163,7 +158,7 @@ class Bar extends _chartComponent.default {
163
158
  g.selectAll('text').attr('font-size', theme.fontSize);
164
159
  g.selectAll('text').attr('fill', theme.textColor);
165
160
  });
166
- this.chart.append('g').attr('class', "rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id)).selectAll().data(data).join('path').attr('fill', d => d3.color(this.getFillColor(d))).attr('data-x', d => x(d.name)).attr('data-y', d => y(d.value)).attr('data-width', x.bandwidth()).attr('data-value', d => d.value).attr('id', (d, index) => d.slugId).attr('d', d => {
161
+ this.chart.append('g').attr('class', "rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id)).selectAll().data(data).join('path').attr('fill', d => d3.color(this.getFillColor(d))).attr('data-x', d => x(d.name)).attr('data-y', d => y(d.value)).attr('data-width', x.bandwidth()).attr('data-value', d => d.value).attr('data-groupName', d => d.name).attr('id', (d, index) => d.slugId).attr('d', d => {
167
162
  // Do not draw if the range is smaller than the minimum
168
163
  if (!y_axis_auto_range && d.value <= y_axis_min) {
169
164
  return '';
@@ -180,15 +175,18 @@ class Bar extends _chartComponent.default {
180
175
  path.closePath();
181
176
  return path.toString();
182
177
  }).call(g => {
183
- const parentNode = d3.select('.rects-wrapper');
178
+ const parentNode = d3.select(".rects-wrapper-".concat(chart === null || chart === void 0 ? void 0 : chart.id));
184
179
  g.nodes().forEach(path => {
185
180
  // Add label
186
181
  if (y_axis_show_value) {
187
- parentNode.append('text').attr('y', Number(path.dataset.y) - 10).attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(path.dataset.value).call(g => {
188
- const {
189
- width
190
- } = g.node().getBoundingClientRect();
191
- g.attr('x', Number(path.dataset.x) + Number(path.dataset.width) / 2 - width);
182
+ this.addLabelToRectTop({
183
+ container: parentNode.node(),
184
+ xWidth: Number(path.dataset.width),
185
+ x: Number(path.dataset.x),
186
+ y: Number(path.dataset.y),
187
+ theme,
188
+ label_font_size,
189
+ text: path.dataset.value
192
190
  });
193
191
  }
194
192
  });
@@ -196,18 +194,15 @@ class Bar extends _chartComponent.default {
196
194
  this.props.toggleRecords(data);
197
195
  }).on('mouseover', (event, data) => {
198
196
  this.showTooltip(event, data, tooltipTitle);
199
- this.setActiveAndInActiveState('inActive', data);
197
+ this.handleAcitveAndInActiveState('inActive', event);
200
198
  }).on('mousemove', event => {
201
199
  this.moveTooltip(event);
202
200
  }).on('mouseleave', (event, data) => {
203
201
  this.hiddenTooltip();
204
- this.setActiveAndInActiveState('active', data);
202
+ this.handleAcitveAndInActiveState('active', event);
205
203
  });
206
- if (display_goal_line) {
207
- this.chart.append('g').attr('class', 'annotation-wrapper').append('line').attr('stroke', '#aaa').attr('x1', insertPadding).attr('y1', y(goal_value)).attr('x2', chartWidth - insertPadding).attr('y2', y(goal_value)).call(g => {
208
- const parentNode = d3.select('.annotation-wrapper');
209
- parentNode.append('text').attr('x', chartWidth - insertPadding - 30).attr('y', y(goal_value) - 10).attr('fill', '#666').text(goal_label);
210
- });
204
+ if (display_goal_line && goal_label && goal_value) {
205
+ this.setDispalyGoalLine(goal_label, goal_value, insertPadding, y);
211
206
  }
212
207
  };
213
208
  this.chart = null;
@@ -225,8 +220,6 @@ class Bar extends _chartComponent.default {
225
220
  componentDidUpdate(prevProps) {
226
221
  super.componentDidUpdate(prevProps);
227
222
  if (_utils.BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
228
- var _this$chart;
229
- ((_this$chart = this.chart) === null || _this$chart === void 0 ? void 0 : _this$chart.autoPadding) && this.chart.destroy();
230
223
  this.createChart();
231
224
  this.drawChart();
232
225
  }
@@ -48,14 +48,31 @@ class ChartComponent extends _react.Component {
48
48
  const column = this.getColumn(tables, tableId, columnKey);
49
49
  return column.name || '';
50
50
  };
51
- this.initChart = container => {
51
+ this.initChart = function (container, id) {
52
+ let initConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
52
53
  const {
53
54
  width,
54
55
  height
55
56
  } = container.getBoundingClientRect();
56
- this.chart = d3.create('svg').attr('width', width).attr('height', height).attr('viewBox', [0, 0, width, height]);
57
- this.container.appendChild(this.chart.node());
58
- this.chartBoundingClientRect = this.chart.node().getBoundingClientRect();
57
+ _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
+ _this.container.appendChild(_this.chart.node());
59
+ _this.chartBoundingClientRect = {
60
+ ...JSON.parse(JSON.stringify(_this.chart.node().getBoundingClientRect())),
61
+ ...initConfig
62
+ };
63
+ };
64
+ this.initDefs = () => {
65
+ if (this.container) {
66
+ // add Mask
67
+ const {
68
+ previewType
69
+ } = this.props.canvasStyle || {};
70
+ const {
71
+ width,
72
+ height
73
+ } = this.container.getBoundingClientRect();
74
+ 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
+ }
59
76
  };
60
77
  this.getChartDisplayLabels = (containerWidth, minItemWidth, charts) => {
61
78
  let labels = [];
@@ -198,7 +215,7 @@ class ChartComponent extends _react.Component {
198
215
  });
199
216
  }
200
217
  };
201
- this.renderAxisLabel = (chart, tables, container) => {
218
+ this.renderAxisLabel = (chart, tables, chartContainer) => {
202
219
  var _this$chart2;
203
220
  if (!this.chart || !chart) return;
204
221
  let {
@@ -226,7 +243,6 @@ class ChartComponent extends _react.Component {
226
243
  let textColor;
227
244
  this.globalTheme === _constants.THEME_NAME_MAP.DARK ? textColor = '#fff' : textColor = '#999';
228
245
  const xAxisID = "chart-x-axis-label_".concat(chart.id);
229
- const chartContainer = container || this.chart.getCanvas().get('container');
230
246
  const xLabel = chartContainer === null || chartContainer === void 0 ? void 0 : chartContainer.querySelector("#".concat(xAxisID));
231
247
  if (!xLabel && x_axis_show_label) {
232
248
  const div = document.createElement('div');
@@ -456,13 +472,100 @@ class ChartComponent extends _react.Component {
456
472
  }
457
473
  };
458
474
  };
475
+ this.formatterLegendName = name => {
476
+ if (!name && typeof name !== 'number' || name.trim() === 'undefined' || name.trim() === 'null') {
477
+ return _intl.default.get(_constants.EMPTY_NAME);
478
+ } else if (name === '_Others') {
479
+ return _intl.default.get('Others');
480
+ } else {
481
+ return _intl.default.get(name) || name;
482
+ }
483
+ };
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;
498
+ });
499
+ return width;
500
+ };
459
501
  // set legend
460
502
  this.setLegend = function (legendName) {
503
+ var _this$chart$node;
461
504
  let theme = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.CHART_THEME_COLOR['light'];
462
- let legendPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'bottom';
505
+ let legendPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'top-left';
506
+ let data = arguments.length > 3 ? arguments[3] : undefined;
463
507
  if (!_this.chart) return;
464
- const basicLegendConfig = _this.getLegendConfig(theme, legendPosition);
465
- _this.chart.legend(legendName, basicLegendConfig);
508
+ const {
509
+ width: chartWidth,
510
+ 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;
524
+ }
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;
535
+ return groupName;
536
+ }).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
+ // Add text
543
+ g.nodes().forEach(rect => {
544
+ 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
549
+ const {
550
+ height,
551
+ width
552
+ } = g.node().getBoundingClientRect();
553
+ textHeight = height;
554
+ textWidth = width;
555
+ g.attr('y', textHeight / 2);
556
+ });
557
+ });
558
+
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
+ });
567
+ });
568
+ });
466
569
  };
467
570
  // theta is pie or ring chart
468
571
  this.setLegendForTheta = function (legendName) {
@@ -693,30 +796,82 @@ class ChartComponent extends _react.Component {
693
796
  }
694
797
  return themeColors || _constants.CHART_THEME_COLOR[_constants.THEME_NAME_MAP.LIGHT];
695
798
  };
696
- this.setDispalyGoalLine = (goalLabel, goalValue, chartWidth) => {
697
- this.chart.annotation().line({
698
- // start of the annotation line start
699
- // x start is -0.5
700
- start: [-0.5, goalValue],
701
- // x end is infinite
702
- end: [99999, goalValue],
703
- style: {
704
- stroke: '#aaa',
705
- // dash color
706
- lineDash: [8, 3] // dash style
707
- },
708
- text: {
709
- content: goalLabel,
710
- offsetX: chartWidth - 70,
711
- offsetY: -5,
712
- style: {
713
- fill: '#666'
714
- }
799
+ this.setDispalyGoalLine = (goal_label, goal_value, insertPadding, yScale) => {
800
+ var _this$chart$node3;
801
+ const {
802
+ width: chartWidth
803
+ } = 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);
808
+ });
809
+ };
810
+ this.addLabelToRectTop = _ref3 => {
811
+ let {
812
+ container,
813
+ x,
814
+ y,
815
+ xWidth,
816
+ theme,
817
+ label_font_size,
818
+ text
819
+ } = _ref3;
820
+ 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
+ const {
822
+ width
823
+ } = g.node().getBoundingClientRect();
824
+ g.attr('x', Number(x) + Number(xWidth) / 2 - width / 2);
825
+ });
826
+ };
827
+ this.addLabelToRectCenter = _ref4 => {
828
+ let {
829
+ chartType,
830
+ container,
831
+ x,
832
+ y,
833
+ xWidth,
834
+ yheight,
835
+ overflowHeight,
836
+ theme,
837
+ label_font_size,
838
+ text
839
+ } = _ref4;
840
+ d3.select(container).append('text').attr('fill', theme.labelColor).attr('font-size', _utils.BaseUtils.getLabelFontSize(label_font_size)).text(text).call(g => {
841
+ const {
842
+ width,
843
+ height
844
+ } = g.node().getBoundingClientRect();
845
+ const translateX = Number(x) + xWidth / 2 - width / 2;
846
+ let translateY = Number(y) + Number(yheight / 2) + height / 2;
847
+ if (chartType === _constants.CHART_TYPE.BAR_STACK) {
848
+ translateY = translateY - overflowHeight / 2;
715
849
  }
850
+ g.attr('transform', "translate(".concat(translateX, ", ").concat(translateY, ")"));
716
851
  });
717
852
  };
853
+ this.setActiveAndInActiveState = (state, allGroup, curGroupName) => {
854
+ if (state === 'active') {
855
+ allGroup.forEach(g => {
856
+ const rects = Array.from(g.children);
857
+ rects.forEach(item => {
858
+ d3.select(item).attr('opacity', 1);
859
+ });
860
+ });
861
+ }
862
+ if (state === 'inActive') {
863
+ allGroup.forEach(g => {
864
+ const rects = Array.from(g.children);
865
+ rects.forEach(item => {
866
+ if (item.getAttribute('data-groupName') !== curGroupName) {
867
+ d3.select(item).attr('opacity', 0.3);
868
+ }
869
+ });
870
+ });
871
+ }
872
+ };
718
873
  this.initLabelStroke(props === null || props === void 0 ? void 0 : props.globalTheme);
719
- this.chartBoundingClientRect = null;
874
+ this.chartBoundingClientRect = {};
720
875
  }
721
876
  componentDidUpdate(prevProps) {
722
877
  if (prevProps.globalTheme !== this.props.globalTheme) {
@@ -11,6 +11,8 @@ var _constants = require("../../constants");
11
11
  var _statisticRecordDialog = _interopRequireDefault(require("../../components/statistic-record-dialog"));
12
12
  var _table = _interopRequireDefault(require("./table"));
13
13
  var _bar = _interopRequireDefault(require("./bar"));
14
+ var _barGroup = _interopRequireDefault(require("./bar-group"));
15
+ var _barStack = _interopRequireDefault(require("./bar-stack"));
14
16
  var _basicNumberCard = _interopRequireDefault(require("./basic-number-card"));
15
17
  var _trend = _interopRequireDefault(require("./trend"));
16
18
  var _tableElement = _interopRequireDefault(require("./table-element"));
@@ -94,6 +96,25 @@ const Wrapper = _ref => {
94
96
  canvasStyle: canvasStyle
95
97
  }));
96
98
  }
99
+ case _constants.CHART_TYPE.BAR_GROUP:
100
+ {
101
+ return /*#__PURE__*/_react.default.createElement(_barGroup.default, Object.assign({}, baseProps, {
102
+ canvasStyle: canvasStyle
103
+ }));
104
+ }
105
+ case _constants.CHART_TYPE.BAR_STACK:
106
+ {
107
+ const {
108
+ config
109
+ } = chart;
110
+ const {
111
+ column_groupby_multiple_numeric_column
112
+ } = config;
113
+ const BarGroupComponent = column_groupby_multiple_numeric_column ? _barStack.default : _barGroup.default;
114
+ return /*#__PURE__*/_react.default.createElement(BarGroupComponent, Object.assign({}, baseProps, {
115
+ canvasStyle: canvasStyle
116
+ }));
117
+ }
97
118
  case _constants.CHART_TYPE.BASIC_NUMBER_CARD:
98
119
  {
99
120
  return /*#__PURE__*/_react.default.createElement(_basicNumberCard.default, Object.assign({}, baseProps, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sea-chart",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "@dnd-kit/core": "^6.1.0",
@@ -20,7 +20,7 @@
20
20
  "slugid": "~5.0.1"
21
21
  },
22
22
  "peerDependencies": {
23
- "dtable-ui-component": "6.0.9",
23
+ "dtable-ui-component": "~6.0.15",
24
24
  "dtable-utils": "~5.0.*",
25
25
  "prop-types": "15.8.1",
26
26
  "react": "18.3.1",