@gravity-ui/chartkit 0.13.0 → 1.0.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.
- package/CHANGELOG.md +16 -0
- package/build/plugins/yagr/__stories__/mocks/line10.js +8 -9
- package/build/plugins/yagr/renderer/YagrWidget.js +35 -169
- package/build/plugins/yagr/renderer/tooltip/index.d.ts +1 -0
- package/build/plugins/yagr/renderer/tooltip/index.js +1 -0
- package/build/plugins/yagr/renderer/tooltip/renderTooltip.d.ts +2 -0
- package/build/plugins/yagr/renderer/tooltip/renderTooltip.js +55 -0
- package/build/plugins/yagr/renderer/tooltip/tooltip.d.ts +2 -140
- package/build/plugins/yagr/renderer/tooltip/tooltip.js +10 -9
- package/build/plugins/yagr/renderer/tooltip/types.d.ts +74 -0
- package/build/plugins/yagr/renderer/tooltip/types.js +1 -0
- package/build/plugins/yagr/renderer/useWidgetData.d.ts +9 -0
- package/build/plugins/yagr/renderer/useWidgetData.js +43 -0
- package/build/plugins/yagr/renderer/utils.d.ts +15 -0
- package/build/plugins/yagr/renderer/utils.js +80 -0
- package/package.json +2 -2
- package/build/plugins/yagr/renderer/synchronizeTooltipTablesCellsWidth.d.ts +0 -1
- package/build/plugins/yagr/renderer/synchronizeTooltipTablesCellsWidth.js +0 -43
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.0](https://github.com/gravity-ui/chartkit/compare/v0.13.0...v1.0.0) (2022-12-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* update yagr to v2 ([#82](https://github.com/gravity-ui/chartkit/issues/82))
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* update yagr to v2 ([#82](https://github.com/gravity-ui/chartkit/issues/82)) ([ae3c347](https://github.com/gravity-ui/chartkit/commit/ae3c3471bc7bb0d4a2d5af850bac1ecb4eb8e3bb))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### chore
|
|
16
|
+
|
|
17
|
+
* bump major ([966c40b](https://github.com/gravity-ui/chartkit/commit/966c40b89d4795acbadb798fcd1e2031481d76a2))
|
|
18
|
+
|
|
3
19
|
## [0.13.0](https://github.com/gravity-ui/chartkit/compare/v0.12.3...v0.13.0) (2022-12-05)
|
|
4
20
|
|
|
5
21
|
|
|
@@ -9,28 +9,30 @@ export const line10 = {
|
|
|
9
9
|
id: '0',
|
|
10
10
|
name: 'Serie 1',
|
|
11
11
|
color: '#6c59c2',
|
|
12
|
-
|
|
13
|
-
data: [25, 52, 89, 72, 39, 49, 82, 59, 36, 5],
|
|
12
|
+
data: [45, 52, 89, 72, 39, 49, 82, 59, 36, 5],
|
|
14
13
|
},
|
|
15
14
|
{
|
|
16
15
|
id: '1',
|
|
17
16
|
name: 'Serie 2',
|
|
18
17
|
color: '#6e8188',
|
|
19
|
-
visible: true,
|
|
20
18
|
data: [37, 6, 51, 10, 65, 35, 72, 0, 94, 54],
|
|
21
19
|
},
|
|
22
20
|
{
|
|
23
21
|
id: '2',
|
|
24
22
|
name: 'Serie 3',
|
|
25
23
|
color: '#e21576',
|
|
26
|
-
visible: true,
|
|
27
24
|
data: [26, 54, 15, 40, 43, 18, 65, 46, 51, 33],
|
|
28
25
|
},
|
|
29
26
|
],
|
|
30
27
|
},
|
|
31
28
|
libraryConfig: {
|
|
32
29
|
chart: {
|
|
33
|
-
|
|
30
|
+
series: {
|
|
31
|
+
type: 'line',
|
|
32
|
+
},
|
|
33
|
+
select: {
|
|
34
|
+
zoom: false,
|
|
35
|
+
},
|
|
34
36
|
},
|
|
35
37
|
title: {
|
|
36
38
|
text: 'line: random 10 pts',
|
|
@@ -51,11 +53,8 @@ export const line10 = {
|
|
|
51
53
|
style: 'solid 2px rgba(230, 2, 7, 0.3)',
|
|
52
54
|
},
|
|
53
55
|
},
|
|
54
|
-
settings: {
|
|
55
|
-
adaptive: true,
|
|
56
|
-
},
|
|
57
56
|
tooltip: {
|
|
58
|
-
|
|
57
|
+
show: true,
|
|
59
58
|
boundClassName: '.wrapper',
|
|
60
59
|
tracking: 'sticky',
|
|
61
60
|
className: 'chartkit-theme_common',
|
|
@@ -1,179 +1,22 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import moment from 'moment';
|
|
3
|
-
import debounce from 'lodash/debounce';
|
|
4
2
|
import isEmpty from 'lodash/isEmpty';
|
|
5
|
-
import { useThemeType } from '@gravity-ui/uikit';
|
|
6
3
|
import YagrComponent from 'yagr/dist/react';
|
|
7
|
-
import { defaults, } from 'yagr';
|
|
8
4
|
import { i18n } from '../../../i18n';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { synchronizeTooltipTablesCellsWidth } from './
|
|
5
|
+
import { CHARTKIT_ERROR_CODE, ChartKitError } from '../../../libs';
|
|
6
|
+
import { useWidgetData } from './useWidgetData';
|
|
7
|
+
import { checkFocus, detectClickOutside, synchronizeTooltipTablesCellsWidth } from './utils';
|
|
12
8
|
import './polyfills';
|
|
13
9
|
import './YagrWidget.css';
|
|
14
|
-
const calcOption = (d) => {
|
|
15
|
-
return typeof d === 'object'
|
|
16
|
-
? Object.values(d).reduce((_, t) => {
|
|
17
|
-
return t;
|
|
18
|
-
})
|
|
19
|
-
: d;
|
|
20
|
-
};
|
|
21
|
-
/*
|
|
22
|
-
* Default tooltip renderer.
|
|
23
|
-
* Adapter between native Yagr tooltip config and ChartKit
|
|
24
|
-
* tooltip renderer.
|
|
25
|
-
*/
|
|
26
|
-
const renderTooltip = (data) => {
|
|
27
|
-
var _a, _b;
|
|
28
|
-
const cfg = data.yagr.config;
|
|
29
|
-
const timeMultiplier = ((_a = cfg.settings) === null || _a === void 0 ? void 0 : _a.timeMultiplier) || 1;
|
|
30
|
-
const locale = (_b = cfg.settings) === null || _b === void 0 ? void 0 : _b.locale;
|
|
31
|
-
const opts = data.options;
|
|
32
|
-
const { x, pinned } = data;
|
|
33
|
-
let sumTotal = 0;
|
|
34
|
-
const rows = Object.values(data.scales).reduce((acc, scale) => {
|
|
35
|
-
sumTotal += scale.sum || 0;
|
|
36
|
-
return acc.concat(scale.rows);
|
|
37
|
-
}, []);
|
|
38
|
-
const lines = rows.length;
|
|
39
|
-
const sum = calcOption(opts.sum);
|
|
40
|
-
const maxLines = calcOption(opts.maxLines);
|
|
41
|
-
const valueFormatter = calcOption(opts.value);
|
|
42
|
-
// eslint-disable-next-line no-nested-ternary
|
|
43
|
-
const hiddenRowsNumber = pinned
|
|
44
|
-
? undefined
|
|
45
|
-
: lines > maxLines
|
|
46
|
-
? Math.abs(maxLines - lines)
|
|
47
|
-
: undefined;
|
|
48
|
-
const hiddenRowsSum = hiddenRowsNumber
|
|
49
|
-
? valueFormatter(rows
|
|
50
|
-
.slice(-hiddenRowsNumber)
|
|
51
|
-
.reduce((sum, { originalValue }) => sum + (originalValue || 0), 0))
|
|
52
|
-
: undefined;
|
|
53
|
-
const tooltipFormatOptions = {
|
|
54
|
-
activeRowAlwaysFirstInTooltip: rows.length > 1,
|
|
55
|
-
tooltipHeader: moment(x / timeMultiplier).format('DD MMMM YYYY HH:mm:ss'),
|
|
56
|
-
shared: true,
|
|
57
|
-
lines: rows.map((row, i) => (Object.assign(Object.assign({}, row), { seriesName: row.name || 'Serie ' + (i + 1), seriesColor: row.color, selectedSeries: row.active, seriesIdx: row.seriesIdx, percentValue: typeof row.transformed === 'number' ? row.transformed.toFixed(1) : '' }))),
|
|
58
|
-
withPercent: calcOption(opts.percent),
|
|
59
|
-
hiddenRowsNumber: hiddenRowsNumber,
|
|
60
|
-
hiddenRowsSum,
|
|
61
|
-
};
|
|
62
|
-
if (sum) {
|
|
63
|
-
tooltipFormatOptions.sum = valueFormatter(sumTotal);
|
|
64
|
-
}
|
|
65
|
-
return formatTooltip(tooltipFormatOptions, {
|
|
66
|
-
options: { locale },
|
|
67
|
-
lastVisibleRowIndex: pinned ? rows.length - 1 : maxLines - 1,
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
const getXAxisFormatter = (msm = 1) => (_, ticks) => {
|
|
71
|
-
const range = (ticks[ticks.length - 1] - ticks[0]) / msm;
|
|
72
|
-
return ticks.map((rawValue) => {
|
|
73
|
-
const d = moment(rawValue / msm);
|
|
74
|
-
if (d.hour() === 0 && d.minutes() === 0 && d.seconds() === 0) {
|
|
75
|
-
return d.format('DD.MM.YY');
|
|
76
|
-
}
|
|
77
|
-
return d.format(range < 300 ? 'HH:mm:ss' : 'HH:mm');
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
10
|
const YagrWidget = React.forwardRef((props, forwardedRef) => {
|
|
81
|
-
|
|
11
|
+
const { id, data: { data }, onLoad, } = props;
|
|
82
12
|
const yagrRef = React.useRef(null);
|
|
83
|
-
const { data, libraryConfig } = props.data;
|
|
84
|
-
const { id, onLoad } = props;
|
|
85
|
-
const theme = useThemeType();
|
|
86
13
|
if (!data || isEmpty(data)) {
|
|
87
14
|
throw new ChartKitError({
|
|
88
15
|
code: CHARTKIT_ERROR_CODE.NO_DATA,
|
|
89
16
|
message: i18n('error', 'label_no-data'),
|
|
90
17
|
});
|
|
91
18
|
}
|
|
92
|
-
const
|
|
93
|
-
mouseMove: null,
|
|
94
|
-
mouseDown: null,
|
|
95
|
-
};
|
|
96
|
-
const checkFocus = (tooltip) => (event) => {
|
|
97
|
-
var _a, _b;
|
|
98
|
-
const yagr = (_a = yagrRef === null || yagrRef === void 0 ? void 0 : yagrRef.current) === null || _a === void 0 ? void 0 : _a.chart;
|
|
99
|
-
if (!yagr) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const target = event.target;
|
|
103
|
-
const seriesIdx = target && tooltip.contains(target) && target.tagName === 'TD'
|
|
104
|
-
? (_b = target.parentElement) === null || _b === void 0 ? void 0 : _b.dataset['seriesIdx']
|
|
105
|
-
: undefined;
|
|
106
|
-
const serie = seriesIdx ? yagr.uplot.series[Number(seriesIdx)] : null;
|
|
107
|
-
yagr.focus(serie ? serie.id : null, true);
|
|
108
|
-
};
|
|
109
|
-
const detectClickOutside = (tooltip, actions) => (event) => {
|
|
110
|
-
var _a, _b;
|
|
111
|
-
const yagr = (_a = yagrRef === null || yagrRef === void 0 ? void 0 : yagrRef.current) === null || _a === void 0 ? void 0 : _a.chart;
|
|
112
|
-
if (!yagr) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const target = event.target;
|
|
116
|
-
if (target instanceof Element) {
|
|
117
|
-
const isClickInsideTooltip = target && tooltip.contains(target);
|
|
118
|
-
const isClickOnUplotOver = target && ((_b = yagr.root.querySelector('.u-over')) === null || _b === void 0 ? void 0 : _b.contains(target));
|
|
119
|
-
if (!isClickInsideTooltip && !isClickOnUplotOver) {
|
|
120
|
-
actions.pin(false);
|
|
121
|
-
actions.hide();
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
const config = Object.assign(Object.assign({}, libraryConfig), { timeline: data.timeline, series: data.graphs });
|
|
126
|
-
config.settings = Object.assign({ locale: settings.get('lang'), theme }, (config.settings || {}));
|
|
127
|
-
if (((_a = config.tooltip) === null || _a === void 0 ? void 0 : _a.enabled) !== false) {
|
|
128
|
-
config.tooltip = config.tooltip || {};
|
|
129
|
-
config.tooltip.render = ((_b = config.tooltip) === null || _b === void 0 ? void 0 : _b.render) || renderTooltip;
|
|
130
|
-
// "className" property prevent default yagr styles adding
|
|
131
|
-
config.tooltip.className = 'chartkit-yagr-tooltip';
|
|
132
|
-
config.tooltip.onStateChange = (tooltip, { action, actions }) => {
|
|
133
|
-
switch (action) {
|
|
134
|
-
case 'pin': {
|
|
135
|
-
handlers.mouseMove = checkFocus(tooltip);
|
|
136
|
-
handlers.mouseDown = detectClickOutside(tooltip, actions);
|
|
137
|
-
document.addEventListener('mousemove', handlers.mouseMove);
|
|
138
|
-
document.addEventListener('mousedown', handlers.mouseDown);
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
case 'unpin': {
|
|
142
|
-
if (handlers.mouseMove) {
|
|
143
|
-
document.removeEventListener('mousemove', handlers.mouseMove);
|
|
144
|
-
handlers.mouseMove = null;
|
|
145
|
-
}
|
|
146
|
-
if (handlers.mouseDown) {
|
|
147
|
-
document.removeEventListener('mousedown', handlers.mouseDown);
|
|
148
|
-
handlers.mouseDown = null;
|
|
149
|
-
}
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
case 'render': {
|
|
153
|
-
synchronizeTooltipTablesCellsWidth(tooltip);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
config.axes = config.axes || {};
|
|
159
|
-
const xAxis = config.axes[defaults.DEFAULT_X_SCALE];
|
|
160
|
-
if (xAxis && !xAxis.values) {
|
|
161
|
-
xAxis.values = getXAxisFormatter(config.settings.timeMultiplier);
|
|
162
|
-
}
|
|
163
|
-
if (!xAxis) {
|
|
164
|
-
config.axes[defaults.DEFAULT_X_SCALE] = {
|
|
165
|
-
values: getXAxisFormatter(config.settings.timeMultiplier),
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
const debugFileName = props.data.sources
|
|
169
|
-
? Object.values(props.data.sources)
|
|
170
|
-
.map((source) => {
|
|
171
|
-
var _a;
|
|
172
|
-
return (_a = source === null || source === void 0 ? void 0 : source.data) === null || _a === void 0 ? void 0 : _a.program;
|
|
173
|
-
})
|
|
174
|
-
.filter(Boolean)
|
|
175
|
-
.join(', ') || id
|
|
176
|
-
: id;
|
|
19
|
+
const { config, debug } = useWidgetData(Object.assign(Object.assign({}, props.data), { id }));
|
|
177
20
|
const handleChartLoading = React.useCallback((chart, { renderTime }) => {
|
|
178
21
|
onLoad === null || onLoad === void 0 ? void 0 : onLoad(Object.assign(Object.assign({}, data), { widget: chart, widgetRendering: renderTime }));
|
|
179
22
|
}, [onLoad, data]);
|
|
@@ -193,13 +36,36 @@ const YagrWidget = React.forwardRef((props, forwardedRef) => {
|
|
|
193
36
|
onWindowResize();
|
|
194
37
|
},
|
|
195
38
|
}), [onWindowResize]);
|
|
196
|
-
React.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
39
|
+
React.useLayoutEffect(() => {
|
|
40
|
+
var _a, _b, _c, _d;
|
|
41
|
+
const yagr = (_a = yagrRef.current) === null || _a === void 0 ? void 0 : _a.chart;
|
|
42
|
+
if (!yagr) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const handlers = {
|
|
46
|
+
mouseMove: null,
|
|
47
|
+
mouseDown: null,
|
|
201
48
|
};
|
|
202
|
-
|
|
203
|
-
|
|
49
|
+
(_b = yagr.plugins.tooltip) === null || _b === void 0 ? void 0 : _b.on('render', (tooltip) => {
|
|
50
|
+
synchronizeTooltipTablesCellsWidth(tooltip);
|
|
51
|
+
});
|
|
52
|
+
(_c = yagr.plugins.tooltip) === null || _c === void 0 ? void 0 : _c.on('pin', (tooltip, { actions }) => {
|
|
53
|
+
handlers.mouseMove = checkFocus({ tooltip, yagr });
|
|
54
|
+
handlers.mouseDown = detectClickOutside({ tooltip, actions, yagr });
|
|
55
|
+
document.addEventListener('mousemove', handlers.mouseMove);
|
|
56
|
+
document.addEventListener('mousedown', handlers.mouseDown);
|
|
57
|
+
});
|
|
58
|
+
(_d = yagr.plugins.tooltip) === null || _d === void 0 ? void 0 : _d.on('unpin', () => {
|
|
59
|
+
if (handlers.mouseMove) {
|
|
60
|
+
document.removeEventListener('mousemove', handlers.mouseMove);
|
|
61
|
+
handlers.mouseMove = null;
|
|
62
|
+
}
|
|
63
|
+
if (handlers.mouseDown) {
|
|
64
|
+
document.removeEventListener('mousedown', handlers.mouseDown);
|
|
65
|
+
handlers.mouseDown = null;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
return (React.createElement(YagrComponent, { ref: yagrRef, id: id, config: config, debug: debug, onChartLoad: handleChartLoading }));
|
|
204
70
|
});
|
|
205
71
|
export default YagrWidget;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { renderTooltip } from './renderTooltip';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { renderTooltip } from './renderTooltip';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import moment from 'moment';
|
|
2
|
+
import { formatTooltip } from './tooltip';
|
|
3
|
+
const calcOption = (d) => {
|
|
4
|
+
return typeof d === 'object'
|
|
5
|
+
? Object.values(d).reduce((_, t) => {
|
|
6
|
+
return t;
|
|
7
|
+
})
|
|
8
|
+
: d;
|
|
9
|
+
};
|
|
10
|
+
/*
|
|
11
|
+
* Default tooltip renderer.
|
|
12
|
+
* Adapter between native Yagr tooltip config and ChartKit
|
|
13
|
+
* tooltip renderer.
|
|
14
|
+
*/
|
|
15
|
+
export const renderTooltip = (data) => {
|
|
16
|
+
const cfg = data.yagr.config;
|
|
17
|
+
const timeMultiplier = cfg.chart.timeMultiplier || 1;
|
|
18
|
+
const opts = data.options;
|
|
19
|
+
const { x, pinned } = data;
|
|
20
|
+
let sumTotal = 0;
|
|
21
|
+
const rows = Object.values(data.scales).reduce((acc, scale) => {
|
|
22
|
+
sumTotal += scale.sum || 0;
|
|
23
|
+
return acc.concat(scale.rows);
|
|
24
|
+
}, []);
|
|
25
|
+
const lines = rows.length;
|
|
26
|
+
const sum = calcOption(opts.sum);
|
|
27
|
+
const maxLines = calcOption(opts.maxLines);
|
|
28
|
+
const valueFormatter = calcOption(opts.value);
|
|
29
|
+
// eslint-disable-next-line no-nested-ternary
|
|
30
|
+
const hiddenRowsNumber = pinned
|
|
31
|
+
? undefined
|
|
32
|
+
: lines > maxLines
|
|
33
|
+
? Math.abs(maxLines - lines)
|
|
34
|
+
: undefined;
|
|
35
|
+
const hiddenRowsSum = hiddenRowsNumber
|
|
36
|
+
? valueFormatter(rows
|
|
37
|
+
.slice(-hiddenRowsNumber)
|
|
38
|
+
.reduce((acc, { originalValue }) => acc + (originalValue || 0), 0))
|
|
39
|
+
: undefined;
|
|
40
|
+
const tooltipFormatOptions = {
|
|
41
|
+
activeRowAlwaysFirstInTooltip: rows.length > 1,
|
|
42
|
+
tooltipHeader: moment(x / timeMultiplier).format('DD MMMM YYYY HH:mm:ss'),
|
|
43
|
+
shared: true,
|
|
44
|
+
lines: rows.map((row, i) => (Object.assign(Object.assign({}, row), { seriesName: row.name || 'Serie ' + (i + 1), seriesColor: row.color, selectedSeries: row.active, seriesIdx: row.seriesIdx, percentValue: typeof row.transformed === 'number' ? row.transformed.toFixed(1) : '' }))),
|
|
45
|
+
withPercent: calcOption(opts.percent),
|
|
46
|
+
hiddenRowsNumber: hiddenRowsNumber,
|
|
47
|
+
hiddenRowsSum,
|
|
48
|
+
};
|
|
49
|
+
if (sum) {
|
|
50
|
+
tooltipFormatOptions.sum = valueFormatter(sumTotal);
|
|
51
|
+
}
|
|
52
|
+
return formatTooltip(tooltipFormatOptions, {
|
|
53
|
+
lastVisibleRowIndex: pinned ? rows.length - 1 : maxLines - 1,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
@@ -1,141 +1,3 @@
|
|
|
1
|
+
import type { TooltipData, TooltipExtraData } from './types';
|
|
1
2
|
import './tooltip.css';
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const SERIES_IDX_DATA_ATTRIBUTE = "data-series-idx";
|
|
4
|
-
export declare const TOOLTIP_CONTAINER_CLASS_NAME = "_tooltip";
|
|
5
|
-
export declare const TOOLTIP_ROW_NAME_CLASS_NANE = "_tooltip-rows__name-td";
|
|
6
|
-
export declare const TOOLTIP_ROW_CLASS_NAME = "_tooltip-row";
|
|
7
|
-
export declare const TOOLTIP_HEADER_CLASS_NAME = "_tooltip-header";
|
|
8
|
-
export declare const TOOLTIP_LIST_CLASS_NAME = "_tooltip-list";
|
|
9
|
-
export declare const TOOLTIP_FOOTER_CLASS_NAME = "_tooltip-footer";
|
|
10
|
-
declare type Tooltip = any;
|
|
11
|
-
export interface TooltipData {
|
|
12
|
-
/**
|
|
13
|
-
* Массив строк выводящихся в тултипе (см. TooltipLine)
|
|
14
|
-
*/
|
|
15
|
-
lines: Array<TooltipLine>;
|
|
16
|
-
/**
|
|
17
|
-
* массив комментариев (задаются в диалоге комментариев)
|
|
18
|
-
*/
|
|
19
|
-
xComments?: Array<{
|
|
20
|
-
/**
|
|
21
|
-
* текст комментария
|
|
22
|
-
*/
|
|
23
|
-
text: string;
|
|
24
|
-
/**
|
|
25
|
-
* цвет отображающийся над комментарием
|
|
26
|
-
*/
|
|
27
|
-
color: string;
|
|
28
|
-
}>;
|
|
29
|
-
/**
|
|
30
|
-
* текст комментария (задаётся через manageTooltipConfig)
|
|
31
|
-
*/
|
|
32
|
-
commentDateText?: string;
|
|
33
|
-
/**
|
|
34
|
-
* флаг, указывающий что нужно всегда дублировать активную строку выводя её поверх основного списка (дефолтное
|
|
35
|
-
* поведение - активная строка выводится поверх основного списка только если "не поместилась" в тултип)
|
|
36
|
-
*/
|
|
37
|
-
activeRowAlwaysFirstInTooltip?: boolean;
|
|
38
|
-
/**
|
|
39
|
-
* флаг, указыващий что чарт отображается в режиме split tooltip
|
|
40
|
-
*/
|
|
41
|
-
splitTooltip?: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* текст хедера тултипа
|
|
44
|
-
*/
|
|
45
|
-
tooltipHeader?: string;
|
|
46
|
-
/**
|
|
47
|
-
* флаг, указывающий, что в тултипе выводится колонка с названием строки
|
|
48
|
-
*/
|
|
49
|
-
shared?: boolean;
|
|
50
|
-
/**
|
|
51
|
-
* флаг, указывающий, что в тултипе выводится колонка с процентным значением
|
|
52
|
-
*/
|
|
53
|
-
withPercent?: boolean;
|
|
54
|
-
/**
|
|
55
|
-
* флаг, указывающий, что в тултипе выводится колонка с diff-ом
|
|
56
|
-
*/
|
|
57
|
-
useCompareFrom?: boolean;
|
|
58
|
-
/**
|
|
59
|
-
* флаг, указывающий, что в тултипе выводится блок с информацией о праздничном дне
|
|
60
|
-
*/
|
|
61
|
-
holiday?: boolean;
|
|
62
|
-
/**
|
|
63
|
-
* название праздничного дня
|
|
64
|
-
*/
|
|
65
|
-
holidayText?: string;
|
|
66
|
-
/**
|
|
67
|
-
* регион для которого актуален праздничный день
|
|
68
|
-
*/
|
|
69
|
-
region?: string;
|
|
70
|
-
/**
|
|
71
|
-
* сумма значений выводящихся в тултипе строк
|
|
72
|
-
*/
|
|
73
|
-
sum?: number | string;
|
|
74
|
-
/**
|
|
75
|
-
* количество скрытых строк "не поместившихся" в тултип
|
|
76
|
-
*/
|
|
77
|
-
hiddenRowsNumber: number;
|
|
78
|
-
/**
|
|
79
|
-
* сумма значений скрытых ("не поместившихся" в тултип) строк
|
|
80
|
-
*/
|
|
81
|
-
hiddenRowsSum?: number | string;
|
|
82
|
-
}
|
|
83
|
-
export interface TooltipLine {
|
|
84
|
-
/**
|
|
85
|
-
* цвет выводящийся в соответсвующей ячейке
|
|
86
|
-
*/
|
|
87
|
-
seriesColor: string;
|
|
88
|
-
/**
|
|
89
|
-
* название измерения выводящееся в соответсвующей ячейке
|
|
90
|
-
*/
|
|
91
|
-
seriesName: string;
|
|
92
|
-
/**
|
|
93
|
-
* индекс линии
|
|
94
|
-
*/
|
|
95
|
-
seriesIdx?: number;
|
|
96
|
-
/**
|
|
97
|
-
* флаг, указывающий, должно ли отображаться название строки
|
|
98
|
-
*/
|
|
99
|
-
hideSeriesName?: boolean;
|
|
100
|
-
/**
|
|
101
|
-
* процентное значение выводящееся в соответвующей ячейке
|
|
102
|
-
*/
|
|
103
|
-
percentValue?: number | string;
|
|
104
|
-
/**
|
|
105
|
-
* значение diff-а выводящееся в соответвующей ячейке
|
|
106
|
-
*/
|
|
107
|
-
diff?: string;
|
|
108
|
-
/**
|
|
109
|
-
* отформатированное числовое значение для текущего измерения выводящееся в соответствующей ячейке
|
|
110
|
-
*/
|
|
111
|
-
value: string;
|
|
112
|
-
/**
|
|
113
|
-
* Комментарий к строке (отображается под соответствующей строкой), задаётся через manageTooltipConfig
|
|
114
|
-
*/
|
|
115
|
-
commentText?: string;
|
|
116
|
-
/**
|
|
117
|
-
* Комментарий к строке (отображается под соответствующей строкой), задаётся через диалог комментариев
|
|
118
|
-
*/
|
|
119
|
-
xyCommentText?: string;
|
|
120
|
-
/**
|
|
121
|
-
* флаг, указывающий, что данная строка активна
|
|
122
|
-
*/
|
|
123
|
-
selectedSeries?: boolean;
|
|
124
|
-
/**
|
|
125
|
-
* кастомный рендер соответсвующей строки (строка с текстом либо html разметкой)
|
|
126
|
-
*/
|
|
127
|
-
customRender?: string;
|
|
128
|
-
/**
|
|
129
|
-
* объект, где ключи - индексы ячеек, контент которых должен быть заменён, значения - функции возвращающие
|
|
130
|
-
* строку (с текстом либо html разметкой) которая будет вставлена в ячейку на соответствующем индексе
|
|
131
|
-
*/
|
|
132
|
-
replaceCellAt?: Record<number, (line: TooltipLine) => string>;
|
|
133
|
-
/**
|
|
134
|
-
* объект, где ключи - индексы на которые будут вставлены новые ячейки (ячейка ранее располагавшаяся на этом
|
|
135
|
-
* индексе и последующие за ней будут сдвинуты), значения - функции возвращающие строку (с текстом либо html
|
|
136
|
-
* разметкой) которая будет вставлена в добавившуюся ячейку
|
|
137
|
-
*/
|
|
138
|
-
insertCellAt?: Record<number, (line: TooltipLine) => string>;
|
|
139
|
-
}
|
|
140
|
-
export declare const formatTooltip: (data: TooltipData, tooltip: Tooltip) => string;
|
|
141
|
-
export {};
|
|
3
|
+
export declare const formatTooltip: (data: TooltipData, tooltip: TooltipExtraData) => string;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
/* eslint complexity: 0 */
|
|
1
2
|
import { i18n } from '../../../../i18n';
|
|
2
3
|
import { escapeHTML } from './helpers/escapeHTML';
|
|
3
4
|
import './tooltip.css';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
const SERIES_NAME_DATA_ATTRIBUTE = 'data-series-name';
|
|
6
|
+
const SERIES_IDX_DATA_ATTRIBUTE = 'data-series-idx';
|
|
7
|
+
const TOOLTIP_CONTAINER_CLASS_NAME = '_tooltip';
|
|
8
|
+
const TOOLTIP_ROW_NAME_CLASS_NANE = '_tooltip-rows__name-td';
|
|
9
|
+
const TOOLTIP_ROW_CLASS_NAME = '_tooltip-row';
|
|
10
|
+
const TOOLTIP_HEADER_CLASS_NAME = '_tooltip-header';
|
|
11
|
+
const TOOLTIP_LIST_CLASS_NAME = '_tooltip-list';
|
|
12
|
+
const TOOLTIP_FOOTER_CLASS_NAME = '_tooltip-footer';
|
|
12
13
|
const renderEmptyCell = () => '<td />';
|
|
13
14
|
const renderColorCell = (line) => `<td class="_tooltip-rows__bubble-td">
|
|
14
15
|
<div class="_tooltip-rows__bubble-div" style="background-color:${line.seriesColor};"></div>
|
|
@@ -154,7 +155,7 @@ export const formatTooltip = (data, tooltip) => {
|
|
|
154
155
|
tooltipContainerClassNames += ` ${TOOLTIP_CONTAINER_CLASS_NAME}_split-tooltip`;
|
|
155
156
|
}
|
|
156
157
|
return `
|
|
157
|
-
<div class="${tooltipContainerClassNames}" style="
|
|
158
|
+
<div class="${tooltipContainerClassNames}" style="max-height: ${splitTooltip ? 'auto' : `${windowHeight}px`}">
|
|
158
159
|
${data.tooltipHeader
|
|
159
160
|
? `<div title="${(document.createRange().createContextualFragment(data.tooltipHeader).textContent ||
|
|
160
161
|
'').trim()}" class="_tooltip-date">
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export declare type TooltipData = {
|
|
2
|
+
/** Tooltip lines data */
|
|
3
|
+
lines: Array<TooltipLine>;
|
|
4
|
+
/** Tooltip comments */
|
|
5
|
+
xComments?: Array<{
|
|
6
|
+
text: string;
|
|
7
|
+
color: string;
|
|
8
|
+
}>;
|
|
9
|
+
commentDateText?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Indicating that active line duplicated by displaying it on top of the main list
|
|
12
|
+
* default behavior - the active line is displayed on top of the main list only if it"does not fit" in the tooltip
|
|
13
|
+
*/
|
|
14
|
+
activeRowAlwaysFirstInTooltip?: boolean;
|
|
15
|
+
/** Indicating that the chart is displayed in "split tooltip" mode */
|
|
16
|
+
splitTooltip?: boolean;
|
|
17
|
+
/** Text of the header of the tooltip */
|
|
18
|
+
tooltipHeader?: string;
|
|
19
|
+
/** Indicating that a column with the line name is displayed in the tooltip */
|
|
20
|
+
shared?: boolean;
|
|
21
|
+
/** Indicating that a column with a percentage value is displayed in the tooltip */
|
|
22
|
+
withPercent?: boolean;
|
|
23
|
+
/** Indicating that a column with a diff is displayed in the tooltip */
|
|
24
|
+
useCompareFrom?: boolean;
|
|
25
|
+
/** Indicating that the tooltip displays a block with information about the holiday */
|
|
26
|
+
holiday?: boolean;
|
|
27
|
+
/** Name of the holiday */
|
|
28
|
+
holidayText?: string;
|
|
29
|
+
/** Region for which the holiday is relevant */
|
|
30
|
+
region?: string;
|
|
31
|
+
/** Sum of the values of the rows displayed in the tooltip */
|
|
32
|
+
sum?: number | string;
|
|
33
|
+
/** Number of hidden lines "not fit" in the tooltip */
|
|
34
|
+
hiddenRowsNumber: number;
|
|
35
|
+
/** Sum of the values of the hidden ("not fit" in the tooltip) rows */
|
|
36
|
+
hiddenRowsSum?: number | string;
|
|
37
|
+
};
|
|
38
|
+
export declare type TooltipExtraData = {
|
|
39
|
+
lastVisibleRowIndex: number;
|
|
40
|
+
};
|
|
41
|
+
export declare type TooltipLine = {
|
|
42
|
+
/** Color displayed in a separate cell */
|
|
43
|
+
seriesColor: string;
|
|
44
|
+
/** Series name */
|
|
45
|
+
seriesName: string;
|
|
46
|
+
/** Series index */
|
|
47
|
+
seriesIdx?: number;
|
|
48
|
+
/** Indicating whether the series name should be displayed */
|
|
49
|
+
hideSeriesName?: boolean;
|
|
50
|
+
/** Percentage value displayed in a separate cell */
|
|
51
|
+
percentValue?: number | string;
|
|
52
|
+
/** Diff value displayed in the separate cell */
|
|
53
|
+
diff?: string;
|
|
54
|
+
/** Formatted numeric value for the current series displayed in a separate cell */
|
|
55
|
+
value: string;
|
|
56
|
+
/** Comment to the line (displayed under the corresponding line), set via manageTooltipConfig */
|
|
57
|
+
commentText?: string;
|
|
58
|
+
/** Comment to the line (displayed under the corresponding line) */
|
|
59
|
+
xyCommentText?: string;
|
|
60
|
+
/** Indicating that line is active */
|
|
61
|
+
selectedSeries?: boolean;
|
|
62
|
+
/** Custom renderer of the line (a string with text or html markup) */
|
|
63
|
+
customRender?: string;
|
|
64
|
+
replaceCellAt?: Record<number, (line: TooltipLine) => string>;
|
|
65
|
+
insertCellAt?: Record<number, (line: TooltipLine) => string>;
|
|
66
|
+
};
|
|
67
|
+
export declare type RowRenderingConfig = {
|
|
68
|
+
cellsRenderers: Array<(line: TooltipLine) => string>;
|
|
69
|
+
isSelectedLine?: boolean;
|
|
70
|
+
allowComment?: boolean;
|
|
71
|
+
withDarkBackground?: boolean;
|
|
72
|
+
isSingleLine?: boolean;
|
|
73
|
+
rowIndex?: number;
|
|
74
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MinimalValidConfig } from 'yagr';
|
|
2
|
+
import type { YagrChartProps } from 'yagr/dist/react';
|
|
3
|
+
import type { YagrWidgetData } from '../types';
|
|
4
|
+
export declare const useWidgetData: (args: YagrWidgetData & {
|
|
5
|
+
id: string;
|
|
6
|
+
}) => {
|
|
7
|
+
config: MinimalValidConfig;
|
|
8
|
+
debug: YagrChartProps['debug'];
|
|
9
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useThemeType } from '@gravity-ui/uikit';
|
|
3
|
+
import { defaults } from 'yagr';
|
|
4
|
+
import { settings } from '../../../libs';
|
|
5
|
+
import { renderTooltip } from './tooltip';
|
|
6
|
+
import { getXAxisFormatter } from './utils';
|
|
7
|
+
export const useWidgetData = (args) => {
|
|
8
|
+
const { id, data, sources, libraryConfig } = args;
|
|
9
|
+
const theme = useThemeType();
|
|
10
|
+
const config = React.useMemo(() => {
|
|
11
|
+
var _a, _b, _c;
|
|
12
|
+
const result = Object.assign(Object.assign({}, libraryConfig), { timeline: data.timeline, series: data.graphs });
|
|
13
|
+
result.chart = Object.assign({ appereance: Object.assign({ locale: settings.get('lang'), theme }, (_a = result.chart) === null || _a === void 0 ? void 0 : _a.appereance) }, result.chart);
|
|
14
|
+
if (((_b = result.tooltip) === null || _b === void 0 ? void 0 : _b.show) !== false) {
|
|
15
|
+
result.tooltip = result.tooltip || {};
|
|
16
|
+
result.tooltip.render = ((_c = result.tooltip) === null || _c === void 0 ? void 0 : _c.render) || renderTooltip;
|
|
17
|
+
}
|
|
18
|
+
result.axes = result.axes || {};
|
|
19
|
+
const xAxis = result.axes[defaults.DEFAULT_X_SCALE];
|
|
20
|
+
if (xAxis && !xAxis.values) {
|
|
21
|
+
xAxis.values = getXAxisFormatter(result.chart.timeMultiplier);
|
|
22
|
+
}
|
|
23
|
+
if (!xAxis) {
|
|
24
|
+
result.axes[defaults.DEFAULT_X_SCALE] = {
|
|
25
|
+
values: getXAxisFormatter(result.chart.timeMultiplier),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}, [data, libraryConfig, theme]);
|
|
30
|
+
const debug = React.useMemo(() => {
|
|
31
|
+
const filename = sources
|
|
32
|
+
? Object.values(sources)
|
|
33
|
+
.map((source) => {
|
|
34
|
+
var _a;
|
|
35
|
+
return (_a = source === null || source === void 0 ? void 0 : source.data) === null || _a === void 0 ? void 0 : _a.program;
|
|
36
|
+
})
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.join(', ') || id
|
|
39
|
+
: id;
|
|
40
|
+
return { filename };
|
|
41
|
+
}, [id, sources]);
|
|
42
|
+
return { config, debug };
|
|
43
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { default as Yagr } from 'yagr';
|
|
2
|
+
export declare const synchronizeTooltipTablesCellsWidth: (tooltipContainer: HTMLElement) => void;
|
|
3
|
+
export declare const checkFocus: (args: {
|
|
4
|
+
tooltip: HTMLElement;
|
|
5
|
+
yagr?: Yagr;
|
|
6
|
+
}) => (event: MouseEvent) => void;
|
|
7
|
+
export declare const detectClickOutside: (args: {
|
|
8
|
+
tooltip: HTMLElement;
|
|
9
|
+
actions: {
|
|
10
|
+
pin: (state: boolean) => void;
|
|
11
|
+
hide: () => void;
|
|
12
|
+
};
|
|
13
|
+
yagr?: Yagr<import("yagr").MinimalValidConfig> | undefined;
|
|
14
|
+
}) => (event: MouseEvent) => void;
|
|
15
|
+
export declare const getXAxisFormatter: (msm?: number) => (_: unknown, ticks: number[]) => string[];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import moment from 'moment';
|
|
2
|
+
const TOOLTIP_HEADER_CLASS_NAME = '_tooltip-header';
|
|
3
|
+
const TOOLTIP_LIST_CLASS_NAME = '_tooltip-list';
|
|
4
|
+
export const synchronizeTooltipTablesCellsWidth = (tooltipContainer) => {
|
|
5
|
+
const tHeadNode = tooltipContainer.querySelector(`.${TOOLTIP_HEADER_CLASS_NAME}`);
|
|
6
|
+
const tBodyNode = tooltipContainer.querySelector(`.${TOOLTIP_LIST_CLASS_NAME}`);
|
|
7
|
+
if (!tHeadNode || !tBodyNode || !tHeadNode.children.length) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const tHeadNodeFirstRow = tHeadNode.children[0];
|
|
11
|
+
for (let j = 0; j < tHeadNodeFirstRow.children.length; j++) {
|
|
12
|
+
const cell = tHeadNodeFirstRow.children[j];
|
|
13
|
+
cell.removeAttribute('style');
|
|
14
|
+
if ((tBodyNode === null || tBodyNode === void 0 ? void 0 : tBodyNode.children.length) === 1) {
|
|
15
|
+
cell.innerHTML = ' ';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const tBodyNodeFirstRow = tBodyNode.children[0];
|
|
19
|
+
for (let j = 0; j < tBodyNodeFirstRow.children.length; j++) {
|
|
20
|
+
const cell = tBodyNodeFirstRow.children[j];
|
|
21
|
+
cell.removeAttribute('style');
|
|
22
|
+
}
|
|
23
|
+
const tHeadRowsWidth = tHeadNode.children[0].getBoundingClientRect().width;
|
|
24
|
+
const tBodyRowsWidth = tBodyNode.children[0].getBoundingClientRect().width;
|
|
25
|
+
const nodeWithWidesRows = tHeadRowsWidth > tBodyRowsWidth ? tHeadNode : tBodyNode;
|
|
26
|
+
const nodeWithWidesRowsCellsWidth = Array.prototype.reduce.call(nodeWithWidesRows.children[0].children, (accum, cellNode) => {
|
|
27
|
+
accum.push(cellNode.getBoundingClientRect().width);
|
|
28
|
+
return accum;
|
|
29
|
+
}, []);
|
|
30
|
+
const nodeToSetCellsWidth = nodeWithWidesRows === tHeadNode ? tBodyNode : tHeadNode;
|
|
31
|
+
const nodeToSetCellsWidthFirstRow = nodeToSetCellsWidth.children[0];
|
|
32
|
+
for (let j = 0; j < nodeToSetCellsWidthFirstRow.children.length; j++) {
|
|
33
|
+
const cell = nodeToSetCellsWidthFirstRow.children[j];
|
|
34
|
+
cell.setAttribute('style', `width: ${nodeWithWidesRowsCellsWidth[j]}px`);
|
|
35
|
+
}
|
|
36
|
+
if (tBodyNode.children.length === 1) {
|
|
37
|
+
for (const cell of tHeadNodeFirstRow.children) {
|
|
38
|
+
cell.innerHTML = '';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
export const checkFocus = (args) => (event) => {
|
|
43
|
+
var _a;
|
|
44
|
+
const { tooltip, yagr } = args;
|
|
45
|
+
if (!yagr) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const target = event.target;
|
|
49
|
+
const seriesIdx = target && tooltip.contains(target) && target.tagName === 'TD'
|
|
50
|
+
? (_a = target.parentElement) === null || _a === void 0 ? void 0 : _a.dataset['seriesIdx']
|
|
51
|
+
: undefined;
|
|
52
|
+
const serie = seriesIdx ? yagr.uplot.series[Number(seriesIdx)] : null;
|
|
53
|
+
yagr.setFocus(serie ? serie.id : null, true);
|
|
54
|
+
};
|
|
55
|
+
export const detectClickOutside = (args) => (event) => {
|
|
56
|
+
var _a;
|
|
57
|
+
const { tooltip, actions, yagr } = args;
|
|
58
|
+
if (!yagr) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const target = event.target;
|
|
62
|
+
if (target instanceof Element) {
|
|
63
|
+
const isClickInsideTooltip = target && tooltip.contains(target);
|
|
64
|
+
const isClickOnUplotOver = target && ((_a = yagr.root.querySelector('.u-over')) === null || _a === void 0 ? void 0 : _a.contains(target));
|
|
65
|
+
if (!isClickInsideTooltip && !isClickOnUplotOver) {
|
|
66
|
+
actions.pin(false);
|
|
67
|
+
actions.hide();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
export const getXAxisFormatter = (msm = 1) => (_, ticks) => {
|
|
72
|
+
const range = (ticks[ticks.length - 1] - ticks[0]) / msm;
|
|
73
|
+
return ticks.map((rawValue) => {
|
|
74
|
+
const d = moment(rawValue / msm);
|
|
75
|
+
if (d.hour() === 0 && d.minutes() === 0 && d.seconds() === 0) {
|
|
76
|
+
return d.format('DD.MM.YY');
|
|
77
|
+
}
|
|
78
|
+
return d.format(range < 300 ? 'HH:mm:ss' : 'HH:mm');
|
|
79
|
+
});
|
|
80
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/chartkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "React component used to render charts based on any sources you need",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "git@github.com:gravity-ui/ChartKit.git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"highcharts-react-official": "^3.0.0",
|
|
19
19
|
"lodash": "^4.17.21",
|
|
20
20
|
"react-split-pane": "^0.1.92",
|
|
21
|
-
"yagr": "
|
|
21
|
+
"yagr": "^2.0.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@gravity-ui/eslint-config": "^1.0.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function synchronizeTooltipTablesCellsWidth(tooltipContainer: any): false | undefined;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
const TOOLTIP_HEADER_CLASS_NAME = '_tooltip-header';
|
|
2
|
-
const TOOLTIP_LIST_CLASS_NAME = '_tooltip-list';
|
|
3
|
-
// @ts-ignore
|
|
4
|
-
export function synchronizeTooltipTablesCellsWidth(tooltipContainer) {
|
|
5
|
-
const tHeadNode = tooltipContainer.querySelector(`.${TOOLTIP_HEADER_CLASS_NAME}`);
|
|
6
|
-
const tBodyNode = tooltipContainer.querySelector(`.${TOOLTIP_LIST_CLASS_NAME}`);
|
|
7
|
-
if (!tHeadNode || !tHeadNode.children.length) {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
const tHeadNodeFirstRow = tHeadNode.children[0];
|
|
11
|
-
for (let j = 0; j < tHeadNodeFirstRow.children.length; j++) {
|
|
12
|
-
const cell = tHeadNodeFirstRow.children[j];
|
|
13
|
-
cell.removeAttribute('style');
|
|
14
|
-
if (tBodyNode.children.length === 1) {
|
|
15
|
-
cell.innerHTML = ' ';
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
const tBodyNodeFirstRow = tBodyNode.children[0];
|
|
19
|
-
for (let j = 0; j < tBodyNodeFirstRow.children.length; j++) {
|
|
20
|
-
const cell = tBodyNodeFirstRow.children[j];
|
|
21
|
-
cell.removeAttribute('style');
|
|
22
|
-
}
|
|
23
|
-
const tHeadRowsWidth = tHeadNode.children[0].getBoundingClientRect().width;
|
|
24
|
-
const tBodyRowsWidth = tBodyNode.children[0].getBoundingClientRect().width;
|
|
25
|
-
const nodeWithWidesRows = tHeadRowsWidth > tBodyRowsWidth ? tHeadNode : tBodyNode;
|
|
26
|
-
const nodeWithWidesRowsCellsWidth = Array.prototype.reduce.call(nodeWithWidesRows.children[0].children, (accum, cellNode) => {
|
|
27
|
-
// @ts-ignore
|
|
28
|
-
accum.push(cellNode.getBoundingClientRect().width);
|
|
29
|
-
return accum;
|
|
30
|
-
}, []);
|
|
31
|
-
const nodeToSetCellsWidth = nodeWithWidesRows === tHeadNode ? tBodyNode : tHeadNode;
|
|
32
|
-
const nodeToSetCellsWidthFirstRow = nodeToSetCellsWidth.children[0];
|
|
33
|
-
for (let j = 0; j < nodeToSetCellsWidthFirstRow.children.length; j++) {
|
|
34
|
-
const cell = nodeToSetCellsWidthFirstRow.children[j];
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
cell.setAttribute('style', `width: ${nodeWithWidesRowsCellsWidth[j]}px`);
|
|
37
|
-
}
|
|
38
|
-
if (tBodyNode.children.length === 1) {
|
|
39
|
-
for (const cell of tHeadNodeFirstRow.children) {
|
|
40
|
-
cell.innerHTML = '';
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|