@sis-cc/dotstatsuite-components 17.8.0 → 17.9.0

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.
@@ -59,17 +59,13 @@ var Chart = function Chart(_ref) {
59
59
  var ChartWrapper = function ChartWrapper() {
60
60
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
61
61
 
62
- var options = R.over( // adjust svg height regarding header and footer height
63
- R.lensPath(['base', 'height']), R.pipe(function (h) {
64
- return h - props.heightOffsets.header - props.heightOffsets.footer - 2;
65
- }, R.when(R.gt(0), R.always(300))), // 2 = borders
66
- props.options);
67
-
68
- if ((0, _utils.isChartNoData)((0, _extends3.default)({}, props, { options: options }))) {
69
- if (R.isNil(props.fixedHeight)) return _react2.default.createElement(_dotstatsuiteVisions.NoData, { message: props.noData || 'No Data' });
62
+ var options = R.over(R.lensPath(['base', 'height']), R.when(function (h) {
63
+ return h < 0;
64
+ }, R.always(300)))(props.options);
70
65
 
66
+ if ((0, _utils.isChartNoData)(props)) {
71
67
  var height = R.path(['base', 'height'], options);
72
- var style = R.equals(0, height) ? { height: 'auto' } : { height: height };
68
+ var style = { height: height };
73
69
  return _react2.default.createElement(
74
70
  'div',
75
71
  { style: style },
@@ -4,10 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
8
-
9
- var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
10
-
11
7
  var _react = require('react');
12
8
 
13
9
  var _react2 = _interopRequireDefault(_react);
@@ -16,10 +12,6 @@ var _ramda = require('ramda');
16
12
 
17
13
  var R = _interopRequireWildcard(_ramda);
18
14
 
19
- var _size = require('@react-hook/size');
20
-
21
- var _size2 = _interopRequireDefault(_size);
22
-
23
15
  var _dotstatsuiteVisions = require('@sis-cc/dotstatsuite-visions');
24
16
 
25
17
  var _ChartLegends = require('./legends/ChartLegends');
@@ -38,27 +30,17 @@ var Footer = function Footer(_ref) {
38
30
  source = _ref.source,
39
31
  logo = _ref.logo,
40
32
  copyright = _ref.copyright,
41
- onSize = _ref.onSize,
42
33
  chartOptions = _ref.chartOptions,
43
- isSticky = _ref.isSticky;
44
-
45
- var target = _react2.default.useRef(null);
46
-
47
- var _useSize = (0, _size2.default)(target),
48
- _useSize2 = (0, _slicedToArray3.default)(_useSize, 2),
49
- width = _useSize2[0],
50
- height = _useSize2[1];
51
-
52
- _react2.default.useEffect(function () {
53
- if (R.is(Function, onSize)) onSize({ width: width, height: height });
54
- }, [height]);
34
+ isSticky = _ref.isSticky,
35
+ target = _ref.target,
36
+ width = _ref.width;
55
37
 
56
38
  var hasNoLegend = type === 'table' || (0, _utils.isChartNoData)({ data: chartData, type: type });
57
39
  var legend = hasNoLegend ? null : _react2.default.createElement(_ChartLegends2.default, { data: chartData, options: chartOptions, type: type, width: width });
58
40
 
59
41
  return _react2.default.createElement(
60
42
  'div',
61
- { ref: target },
43
+ target ? { ref: target } : {},
62
44
  _react2.default.createElement(_dotstatsuiteVisions.DataFooter, {
63
45
  source: source,
64
46
  logo: logo,
@@ -4,28 +4,26 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- var _react = require('react');
7
+ var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
8
8
 
9
- var _react2 = _interopRequireDefault(_react);
9
+ var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
10
10
 
11
- var _reactSizeme = require('react-sizeme');
11
+ var _react = require('react');
12
12
 
13
- var _reactSizeme2 = _interopRequireDefault(_reactSizeme);
13
+ var _react2 = _interopRequireDefault(_react);
14
14
 
15
15
  var _dotstatsuiteVisions = require('@sis-cc/dotstatsuite-visions');
16
16
 
17
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
18
 
19
- var Header = function Header(props) {
19
+ var Header = function Header(_ref) {
20
+ var target = _ref.target,
21
+ props = (0, _objectWithoutProperties3.default)(_ref, ['target']);
20
22
  return _react2.default.createElement(
21
23
  'div',
22
- null,
24
+ target ? { ref: target } : {},
23
25
  _react2.default.createElement(_dotstatsuiteVisions.DataHeader, props)
24
26
  );
25
27
  };
26
- /*
27
- putting DataHeader under a div is necessary because sizeMe add a hidden DOM element that
28
- mess up the Header layout
29
- */
30
28
 
31
- exports.default = (0, _reactSizeme2.default)({ noPlaceholder: true, monitorHeight: true, monitorWidth: false })(Header);
29
+ exports.default = Header;
@@ -32,9 +32,9 @@ var _classnames = require('classnames');
32
32
 
33
33
  var _classnames2 = _interopRequireDefault(_classnames);
34
34
 
35
- var _reactSizeme = require('react-sizeme');
35
+ var _size = require('@react-hook/size');
36
36
 
37
- var _reactSizeme2 = _interopRequireDefault(_reactSizeme);
37
+ var _size2 = _interopRequireDefault(_size);
38
38
 
39
39
  var _dotstatsuiteVisions = require('@sis-cc/dotstatsuite-visions');
40
40
 
@@ -56,6 +56,8 @@ var _footer = require('./footer');
56
56
 
57
57
  var _footer2 = _interopRequireDefault(_footer);
58
58
 
59
+ var _utils = require('./utils');
60
+
59
61
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
60
62
 
61
63
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -86,7 +88,8 @@ var useStyles = (0, _styles.makeStyles)(function () {
86
88
  var fixedHeight = _ref2.fixedHeight;
87
89
  return fixedHeight || '100%';
88
90
  },
89
- overflow: 'hidden'
91
+ overflow: 'hidden',
92
+ position: 'relative'
90
93
  }
91
94
  };
92
95
  });
@@ -101,7 +104,6 @@ var ViewContent = function ViewContent(_ref3) {
101
104
  rest = (0, _objectWithoutProperties3.default)(_ref3, ['loading', 'loadingProps', 'type', 'width', 'errorMessage']);
102
105
 
103
106
  if (loading) return _react2.default.createElement(_dotstatsuiteVisions.Loading, (0, _extends3.default)({ message: loading }, loadingProps));
104
- if (!width) return _react2.default.createElement(_dotstatsuiteVisions.Loading, (0, _extends3.default)({ message: loading }, loadingProps));
105
107
  if (errorMessage) return _react2.default.createElement(_dotstatsuiteVisions.NoData, { message: errorMessage });
106
108
 
107
109
  if (type === 'table') {
@@ -111,9 +113,11 @@ var ViewContent = function ViewContent(_ref3) {
111
113
 
112
114
  return _react2.default.createElement(_dotstatsuiteVisions.TableHtml5, (0, _extends3.default)({ isRtl: R.prop('isRtl', rest) }, tableProps));
113
115
  }
116
+ if ((0, _utils.isChartDataNotReady)({ data: R.prop('chartData', rest) }) || !width) {
117
+ return _react2.default.createElement(_dotstatsuiteVisions.Loading, null);
118
+ }
114
119
  return _react2.default.createElement(_chart2.default, {
115
120
  data: R.prop('chartData', rest),
116
- fixedHeight: R.prop('fixedHeight', rest),
117
121
  getAxisOptions: R.prop('getAxisOptions', rest),
118
122
  heightOffsets: R.prop('heightOffsets', rest),
119
123
  options: R.prop('chartOptions', rest),
@@ -125,41 +129,29 @@ var ViewContent = function ViewContent(_ref3) {
125
129
  var Viewer = function Viewer(_ref4) {
126
130
  var _cx;
127
131
 
128
- var getResponsiveSize = _ref4.getResponsiveSize,
129
- setFooterOffset = _ref4.setFooterOffset,
130
- setHeaderOffset = _ref4.setHeaderOffset,
131
- size = _ref4.size,
132
- type = _ref4.type,
133
- rest = (0, _objectWithoutProperties3.default)(_ref4, ['getResponsiveSize', 'setFooterOffset', 'setHeaderOffset', 'size', 'type']);
132
+ var type = _ref4.type,
133
+ _ref4$targets = _ref4.targets,
134
+ targets = _ref4$targets === undefined ? {} : _ref4$targets,
135
+ width = _ref4.width,
136
+ rest = (0, _objectWithoutProperties3.default)(_ref4, ['type', 'targets', 'width']);
134
137
 
135
138
  var classes = useStyles({
136
139
  fixedWidth: rest.fixedWidth,
137
140
  fixedHeight: rest.fixedHeight
138
141
  });
139
- (0, _react.useEffect)(function () {
140
- if (R.is(Function, getResponsiveSize)) {
141
- getResponsiveSize({
142
- responsiveWidth: size.width,
143
- responsiveHeight: size.height
144
- });
145
- }
146
- });
147
142
 
148
143
  return _react2.default.createElement(
149
144
  'div',
150
- {
145
+ (0, _extends3.default)({}, targets.viewer ? { ref: targets.viewer } : {}, {
151
146
  className: (0, _classnames2.default)(classes.container, (_cx = {}, (0, _defineProperty3.default)(_cx, classes.tableContainer, type === 'table'), (0, _defineProperty3.default)(_cx, classes.chartContainer, type !== 'table'), _cx))
152
- },
147
+ }),
153
148
  _react2.default.createElement(_header2.default, (0, _extends3.default)({
154
- onSize: function onSize(size) {
155
- return setHeaderOffset(size.height);
156
- }
149
+ target: targets.header
157
150
  }, R.propOr({}, 'headerProps', rest))),
158
- _react2.default.createElement(ViewContent, (0, _extends3.default)({ type: type, width: size.width }, rest)),
151
+ _react2.default.createElement(ViewContent, (0, _extends3.default)({ type: type, width: width }, rest)),
159
152
  _react2.default.createElement(_footer2.default, (0, _extends3.default)({
160
- onSize: function onSize(size) {
161
- return setFooterOffset(size.height);
162
- },
153
+ width: width,
154
+ target: targets.footer,
163
155
  type: type,
164
156
  chartData: R.prop('chartData', rest),
165
157
  chartOptions: R.prop('chartOptions', rest)
@@ -167,38 +159,84 @@ var Viewer = function Viewer(_ref4) {
167
159
  );
168
160
  };
169
161
 
162
+ var defaultChartHeight = function defaultChartHeight(chartOptions) {
163
+ return R.pipe(R.path(['base', 'height']), function (h) {
164
+ return R.isNil(h) || isNaN(h) ? 0 : h;
165
+ })(chartOptions);
166
+ };
167
+
170
168
  var ViewerWrapper = function ViewerWrapper(_ref5) {
171
169
  var chartOptions = _ref5.chartOptions,
172
170
  type = _ref5.type,
173
- props = (0, _objectWithoutProperties3.default)(_ref5, ['chartOptions', 'type']);
171
+ getResponsiveSize = _ref5.getResponsiveSize,
172
+ props = (0, _objectWithoutProperties3.default)(_ref5, ['chartOptions', 'type', 'getResponsiveSize']);
174
173
 
175
174
  var theme = (0, _styles.useTheme)();
176
-
177
- var _useState = (0, _react.useState)({ footer: 0, header: 0 }),
175
+ var viewerTarget = _react2.default.useRef(null);
176
+ var headerTarget = _react2.default.useRef(null);
177
+ var footerTarget = _react2.default.useRef(null);
178
+
179
+ var _useSize = (0, _size2.default)(viewerTarget),
180
+ _useSize2 = (0, _slicedToArray3.default)(_useSize, 2),
181
+ viewerWidth = _useSize2[0],
182
+ viewerHeight = _useSize2[1];
183
+
184
+ var _useSize3 = (0, _size2.default)(headerTarget, { initialHeight: -1 }),
185
+ _useSize4 = (0, _slicedToArray3.default)(_useSize3, 2),
186
+ _ = _useSize4[0],
187
+ headerHeight = _useSize4[1];
188
+
189
+ var _useSize5 = (0, _size2.default)(footerTarget, { initialHeight: -1 }),
190
+ _useSize6 = (0, _slicedToArray3.default)(_useSize5, 2),
191
+ ___ = _useSize6[0],
192
+ footerHeight = _useSize6[1];
193
+
194
+ var _useState = (0, _react.useState)(0),
178
195
  _useState2 = (0, _slicedToArray3.default)(_useState, 2),
179
- heightOffsets = _useState2[0],
180
- setHeightOffsets = _useState2[1];
196
+ chartSvgHeight = _useState2[0],
197
+ setChartSvgHeight = _useState2[1];
181
198
 
182
- var extendedProps = (0, _extends3.default)({}, props, {
183
- type: type,
184
- setFooterOffset: function setFooterOffset(offset) {
185
- return setHeightOffsets(R.assoc('footer', offset));
186
- },
187
- setHeaderOffset: function setHeaderOffset(offset) {
188
- return setHeightOffsets(R.assoc('header', offset));
189
- },
190
- heightOffsets: heightOffsets,
191
- fixedWidth: R.path(['base', 'width'], chartOptions),
192
- fixedHeight: R.path(['base', 'height'], chartOptions)
193
- });
199
+ var defChartHeight = defaultChartHeight(chartOptions);
200
+
201
+ (0, _react.useEffect)(function () {
202
+ if (R.is(Function, getResponsiveSize) && viewerWidth && headerHeight !== -1 && footerHeight !== -1) {
203
+ getResponsiveSize({
204
+ responsiveWidth: viewerWidth,
205
+ responsiveHeight: viewerHeight
206
+ });
207
+ }
208
+ }, [viewerWidth, viewerHeight]);
194
209
 
195
- if (type === 'table') return _react2.default.createElement(Viewer, (0, _extends3.default)({}, extendedProps, { chartOptions: chartOptions }));
210
+ (0, _react.useEffect)(function () {
211
+ if (headerHeight !== -1 && footerHeight !== -1 && !isNaN(headerHeight) && !isNaN(footerHeight)) {
212
+ var nextHeight = defChartHeight - headerHeight - footerHeight - 2;
213
+ setChartSvgHeight(nextHeight);
214
+ }
215
+ }, [headerHeight, footerHeight, defChartHeight]);
216
+
217
+ if (type === 'table') {
218
+ return _react2.default.createElement(Viewer, (0, _extends3.default)({}, props, {
219
+ width: viewerWidth,
220
+ type: type
221
+ }));
222
+ }
196
223
 
197
- var preparedChartOptions = R.pipe(R.over(R.lensPath(['base', 'width']), R.when(R.anyPass([R.isNil, isNaN]), R.always(props.size.width || 0))), R.over(R.lensPath(['base', 'height']), R.when(R.anyPass([R.isNil, isNaN]), R.always(0))), function (chartOptions) {
224
+ var preparedChartOptions = R.pipe(R.over(R.lensPath(['base', 'width']), R.when(R.anyPass([R.isNil, isNaN]), R.always(viewerWidth || 0))), R.set(R.lensPath(['base', 'height']), chartSvgHeight), function (chartOptions) {
198
225
  return (0, _options2.default)(chartOptions, props.chartData, type, theme, props.timeFormats, props.locale);
199
226
  })(chartOptions);
200
227
 
201
- return _react2.default.createElement(Viewer, (0, _extends3.default)({}, extendedProps, { chartOptions: preparedChartOptions }));
228
+ return _react2.default.createElement(Viewer, (0, _extends3.default)({}, props, {
229
+ type: type,
230
+ chartOptions: preparedChartOptions,
231
+ fixedWidth: R.path(['base', 'width'], chartOptions),
232
+ fixedHeight: defChartHeight,
233
+ targets: {
234
+ viewer: viewerTarget,
235
+ header: headerTarget,
236
+ footer: footerTarget
237
+ },
238
+ width: viewerWidth
239
+ }));
202
240
  };
203
241
 
204
- exports.default = (0, _reactSizeme2.default)({ noPlaceholder: true, monitorWidth: true, monitorHeight: true })(ViewerWrapper);
242
+ exports.default = ViewerWrapper;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getOptionsFromFont = exports.getFontFromTheme = exports.isChartNoData = undefined;
6
+ exports.getOptionsFromFont = exports.getFontFromTheme = exports.isChartDataNotReady = exports.isChartNoData = undefined;
7
7
 
8
8
  var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
9
9
 
@@ -17,7 +17,9 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
17
17
 
18
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
19
 
20
- var isChartNoData = exports.isChartNoData = R.anyPass([R.pipe(R.path(['data', 'series']), R.anyPass([R.isNil, R.isEmpty])), R.allPass([R.pipe(R.prop('type'), R.equals('ChoroplethChart'), R.not), R.pipe(R.path(['data', 'series', 0, 'datapoints']), R.anyPass([R.isNil, R.isEmpty]))])]);
20
+ var isChartNoData = exports.isChartNoData = R.anyPass([R.pipe(R.path(['data', 'series']), R.isEmpty), R.allPass([R.pipe(R.prop('type'), R.equals('ChoroplethChart'), R.not), R.pipe(R.path(['data', 'series', 0, 'datapoints']), R.anyPass([R.isNil, R.isEmpty]))])]);
21
+
22
+ var isChartDataNotReady = exports.isChartDataNotReady = R.pipe(R.path(['data', 'series']), R.isNil);
21
23
 
22
24
  var getFontFromTheme = exports.getFontFromTheme = function getFontFromTheme(customPath) {
23
25
  return R.converge(R.mergeRight, [R.pathOr({}, ['mixins', 'chart', 'main']), R.pathOr({}, R.concat(['mixins', 'chart'], customPath))]);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sis-cc/dotstatsuite-components",
3
3
  "description": "Set components based on React.",
4
- "version": "17.8.0",
4
+ "version": "17.9.0",
5
5
  "main": "lib/index.js",
6
6
  "author": "OECD",
7
7
  "license": "MIT",
@@ -31,8 +31,7 @@
31
31
  "memoizee": "^0.4.4",
32
32
  "numeral": "^2.0.6",
33
33
  "prop-types": "^15.6.2",
34
- "ramda": "^0.26.1",
35
- "react-sizeme": "^2.3.6"
34
+ "ramda": "^0.26.1"
36
35
  },
37
36
  "peerDependencies": {
38
37
  "@material-ui/core": "^4",
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import * as R from 'ramda';
3
- import { NoData } from '@sis-cc/dotstatsuite-visions';
3
+ import { NoData, Loading } from '@sis-cc/dotstatsuite-visions';
4
4
  import * as charts from '../../bridge-d3-react/src';
5
5
  import filterSeriesRegardingDimensions from './chartUtils/series';
6
6
  import AxisLegend from './legends/AxisLegend';
@@ -25,17 +25,14 @@ const Chart = ({ options, series, type, width, getAxisOptions }) => {
25
25
  };
26
26
 
27
27
  const ChartWrapper = (props = {}) => {
28
- const options = R.over( // adjust svg height regarding header and footer height
28
+ const options = R.over(
29
29
  R.lensPath(['base', 'height']),
30
- R.pipe(h => h - props.heightOffsets.header - props.heightOffsets.footer - 2, R.when(R.gt(0), R.always(300))), // 2 = borders
31
- props.options
32
- );
33
-
34
- if (isChartNoData({...props, options })) {
35
- if (R.isNil(props.fixedHeight)) return <NoData message={props.noData || 'No Data'} />;
30
+ R.when(h => h < 0, R.always(300))
31
+ )(props.options);
36
32
 
33
+ if (isChartNoData(props)) {
37
34
  const height = R.path(['base', 'height'], options);
38
- const style = R.equals(0, height) ? { height: 'auto' } : { height };
35
+ const style = { height };
39
36
  return (
40
37
  <div style={style}>
41
38
  <NoData message={props.noData || 'No Data'} />
@@ -1,23 +1,15 @@
1
1
  import React from 'react';
2
2
  import * as R from 'ramda';
3
- import useSize from '@react-hook/size';
4
3
  import { DataFooter } from '@sis-cc/dotstatsuite-visions';
5
4
  import ChartLegends from './legends/ChartLegends';
6
5
  import { isChartNoData } from './utils';
7
6
 
8
- const Footer = ({ type, chartData, source, logo, copyright, onSize, chartOptions, isSticky }) => {
9
- const target = React.useRef(null);
10
- const [width, height] = useSize(target);
11
-
12
- React.useEffect(() => {
13
- if (R.is(Function, onSize)) onSize({width, height});
14
- }, [height]);
15
-
7
+ const Footer = ({ type, chartData, source, logo, copyright, chartOptions, isSticky, target, width }) => {
16
8
  const hasNoLegend = type === 'table' || isChartNoData({ data: chartData, type });
17
9
  const legend = hasNoLegend ? null : <ChartLegends data={chartData} options={chartOptions} type={type} width={width} />;
18
10
 
19
11
  return (
20
- <div ref={target}>
12
+ <div {...(target ? { ref: target } : {})}>
21
13
  <DataFooter
22
14
  source={source}
23
15
  logo={logo}
@@ -1,15 +1,10 @@
1
1
  import React from 'react';
2
- import sizeMe from 'react-sizeme';
3
2
  import { DataHeader } from '@sis-cc/dotstatsuite-visions';
4
3
 
5
- const Header = (props) => (
6
- <div>
4
+ const Header = ({ target, ...props }) => (
5
+ <div {...(target ? { ref: target } : {})}>
7
6
  <DataHeader {...props} />
8
7
  </div>
9
8
  );
10
- /*
11
- putting DataHeader under a div is necessary because sizeMe add a hidden DOM element that
12
- mess up the Header layout
13
- */
14
9
 
15
- export default sizeMe({ noPlaceholder: true, monitorHeight: true, monitorWidth: false })(Header);
10
+ export default Header;
@@ -1,13 +1,14 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import * as R from 'ramda';
3
3
  import cx from 'classnames';
4
- import sizeMe from 'react-sizeme';
4
+ import useSize from '@react-hook/size';
5
5
  import { Loading, NoData, TableHtml5 } from '@sis-cc/dotstatsuite-visions';
6
6
  import { useTheme, makeStyles } from '@material-ui/core/styles';
7
7
  import getChartOptions from './chartUtils/options';
8
8
  import Header from './header';
9
9
  import Chart from './chart';
10
10
  import Footer from './footer';
11
+ import { isChartDataNotReady } from './utils';
11
12
 
12
13
  const useStyles = makeStyles(() => ({
13
14
  container: {
@@ -28,14 +29,16 @@ const useStyles = makeStyles(() => ({
28
29
  chartContainer: {
29
30
  width: ({ fixedWidth }) => fixedWidth || '100%',
30
31
  height: ({ fixedHeight }) => fixedHeight || '100%',
31
- overflow: 'hidden'
32
+ overflow: 'hidden',
33
+ position: 'relative'
32
34
  }
33
35
  }));
34
36
 
35
37
  const ViewContent = ({ loading, loadingProps={}, type, width, errorMessage, ...rest }) => {
36
- if (loading) return <Loading message={loading} {...loadingProps} />;
37
- if (!width) return <Loading message={loading} {...loadingProps} />;
38
- if (errorMessage) return <NoData message={errorMessage} />;
38
+ if (loading)
39
+ return <Loading message={loading} {...loadingProps} />;
40
+ if (errorMessage)
41
+ return <NoData message={errorMessage} />;
39
42
 
40
43
  if (type === 'table') {
41
44
  const tableProps = R.propOr({}, 'tableProps', rest);
@@ -44,10 +47,12 @@ const ViewContent = ({ loading, loadingProps={}, type, width, errorMessage, ...r
44
47
 
45
48
  return <TableHtml5 isRtl={R.prop('isRtl', rest)} {...tableProps} />;
46
49
  }
50
+ if (isChartDataNotReady({ data: R.prop('chartData', rest) }) || !width) {
51
+ return <Loading />;
52
+ }
47
53
  return (
48
54
  <Chart
49
55
  data={R.prop('chartData', rest)}
50
- fixedHeight={R.prop('fixedHeight', rest)}
51
56
  getAxisOptions={R.prop('getAxisOptions', rest)}
52
57
  heightOffsets={R.prop('heightOffsets', rest)}
53
58
  options={R.prop('chartOptions', rest)}
@@ -57,34 +62,28 @@ const ViewContent = ({ loading, loadingProps={}, type, width, errorMessage, ...r
57
62
  );
58
63
  };
59
64
 
60
- const Viewer = ({ getResponsiveSize, setFooterOffset, setHeaderOffset, size, type, ...rest }) => {
65
+ const Viewer = ({ type, targets={}, width, ...rest }) => {
61
66
  const classes = useStyles({
62
67
  fixedWidth: rest.fixedWidth,
63
68
  fixedHeight: rest.fixedHeight
64
69
  });
65
- useEffect(() => {
66
- if (R.is(Function, getResponsiveSize)) {
67
- getResponsiveSize({
68
- responsiveWidth: size.width,
69
- responsiveHeight: size.height
70
- });
71
- }
72
- });
73
70
 
74
71
  return (
75
72
  <div
73
+ {...(targets.viewer ? { ref: targets.viewer } : {})}
76
74
  className={cx(classes.container, {
77
75
  [classes.tableContainer]: type === 'table',
78
76
  [classes.chartContainer]: type !== 'table'
79
77
  })}
80
78
  >
81
79
  <Header
82
- onSize={size => setHeaderOffset(size.height)}
80
+ target={targets.header}
83
81
  {...R.propOr({}, 'headerProps', rest)}
84
82
  />
85
- <ViewContent type={type} width={size.width} {...rest} />
83
+ <ViewContent type={type} width={width} {...rest} />
86
84
  <Footer
87
- onSize={size => setFooterOffset(size.height)}
85
+ width={width}
86
+ target={targets.footer}
88
87
  type={type}
89
88
  chartData={R.prop('chartData', rest)}
90
89
  chartOptions={R.prop('chartOptions', rest)}
@@ -94,29 +93,66 @@ const Viewer = ({ getResponsiveSize, setFooterOffset, setHeaderOffset, size, typ
94
93
  );
95
94
  };
96
95
 
97
- const ViewerWrapper = ({ chartOptions, type, ...props }) => {
96
+ const defaultChartHeight = chartOptions => R.pipe(
97
+ R.path(['base', 'height']),
98
+ h => (R.isNil(h) || isNaN(h)) ? 0 : h
99
+ )(chartOptions);
100
+
101
+ const ViewerWrapper = ({ chartOptions, type, getResponsiveSize, ...props }) => {
98
102
  const theme = useTheme();
99
- const [heightOffsets, setHeightOffsets] = useState({ footer: 0, header: 0 });
103
+ const viewerTarget = React.useRef(null);
104
+ const headerTarget = React.useRef(null);
105
+ const footerTarget = React.useRef(null);
106
+ const [viewerWidth, viewerHeight] = useSize(viewerTarget);
107
+ const [_, headerHeight] = useSize(headerTarget, { initialHeight: -1 });
108
+ const [___, footerHeight] = useSize(footerTarget, { initialHeight: -1 });
109
+ const [chartSvgHeight, setChartSvgHeight] = useState(0);
110
+ const defChartHeight = defaultChartHeight(chartOptions);
111
+
112
+ useEffect(() => {
113
+ if (R.is(Function, getResponsiveSize) && viewerWidth && headerHeight !== -1 && footerHeight !== -1) {
114
+ getResponsiveSize({
115
+ responsiveWidth: viewerWidth,
116
+ responsiveHeight: viewerHeight
117
+ });
118
+ }
119
+ }, [viewerWidth, viewerHeight]);
100
120
 
101
- const extendedProps = {
102
- ...props,
103
- type,
104
- setFooterOffset: offset => setHeightOffsets(R.assoc('footer', offset)),
105
- setHeaderOffset: offset => setHeightOffsets(R.assoc('header', offset)),
106
- heightOffsets,
107
- fixedWidth: R.path(['base', 'width'], chartOptions),
108
- fixedHeight: R.path(['base', 'height'], chartOptions),
109
- };
121
+ useEffect(() => {
122
+ if (headerHeight !== -1 && footerHeight !== -1 && !isNaN(headerHeight) && !isNaN(footerHeight)) {
123
+ const nextHeight = defChartHeight - headerHeight - footerHeight - 2;
124
+ setChartSvgHeight(nextHeight);
125
+ }
126
+ }, [headerHeight, footerHeight, defChartHeight]);
110
127
 
111
- if (type === 'table') return <Viewer {...extendedProps} chartOptions={chartOptions} />;
128
+
129
+ if (type === 'table') {
130
+ return <Viewer
131
+ {...props}
132
+ width={viewerWidth}
133
+ type={type}
134
+ />;
135
+ }
112
136
 
113
137
  const preparedChartOptions = R.pipe(
114
- R.over(R.lensPath(['base', 'width']), R.when(R.anyPass([R.isNil, isNaN]), R.always(props.size.width || 0))),
115
- R.over(R.lensPath(['base', 'height']), R.when(R.anyPass([R.isNil, isNaN]), R.always(0))),
138
+ R.over(R.lensPath(['base', 'width']), R.when(R.anyPass([R.isNil, isNaN]), R.always(viewerWidth || 0))),
139
+ R.set(R.lensPath(['base', 'height']), chartSvgHeight),
116
140
  chartOptions => getChartOptions(chartOptions, props.chartData, type, theme, props.timeFormats, props.locale),
117
141
  )(chartOptions);
118
142
 
119
- return <Viewer {...extendedProps} chartOptions={preparedChartOptions} />;
143
+ return <Viewer
144
+ {...props}
145
+ type={type}
146
+ chartOptions={preparedChartOptions}
147
+ fixedWidth={R.path(['base', 'width'], chartOptions)}
148
+ fixedHeight={defChartHeight}
149
+ targets={{
150
+ viewer: viewerTarget,
151
+ header: headerTarget,
152
+ footer: footerTarget
153
+ }}
154
+ width={viewerWidth}
155
+ />;
120
156
  };
121
157
 
122
- export default sizeMe({ noPlaceholder: true, monitorWidth: true, monitorHeight: true })(ViewerWrapper);
158
+ export default ViewerWrapper;
@@ -1,13 +1,15 @@
1
1
  import * as R from 'ramda';
2
2
 
3
3
  export const isChartNoData = R.anyPass([
4
- R.pipe(R.path(['data', 'series']), R.anyPass([R.isNil, R.isEmpty])),
4
+ R.pipe(R.path(['data', 'series']), R.isEmpty),
5
5
  R.allPass([
6
6
  R.pipe(R.prop('type'), R.equals('ChoroplethChart'), R.not),
7
7
  R.pipe(R.path(['data', 'series', 0, 'datapoints']), R.anyPass([R.isNil, R.isEmpty]))
8
8
  ])
9
9
  ]);
10
10
 
11
+ export const isChartDataNotReady = R.pipe(R.path(['data', 'series']), R.isNil);
12
+
11
13
  export const getFontFromTheme = customPath => R.converge(
12
14
  R.mergeRight,
13
15
  [R.pathOr({}, ['mixins', 'chart', 'main']), R.pathOr({}, R.concat(['mixins', 'chart'], customPath))]