@gravity-ui/chartkit 0.7.2
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 +127 -0
- package/LICENSE +21 -0
- package/README.md +64 -0
- package/build/components/ChartKit.css +4 -0
- package/build/components/ChartKit.d.ts +19 -0
- package/build/components/ChartKit.js +42 -0
- package/build/components/ErrorBoundary/ErrorBoundary.d.ts +18 -0
- package/build/components/ErrorBoundary/ErrorBoundary.js +27 -0
- package/build/components/ErrorView/ErrorView.d.ts +7 -0
- package/build/components/ErrorView/ErrorView.js +6 -0
- package/build/components/Loader/Loader.css +7 -0
- package/build/components/Loader/Loader.d.ts +6 -0
- package/build/components/Loader/Loader.js +9 -0
- package/build/constants/common.d.ts +1 -0
- package/build/constants/common.js +2 -0
- package/build/constants/index.d.ts +1 -0
- package/build/constants/index.js +1 -0
- package/build/i18n/index.d.ts +7 -0
- package/build/i18n/index.js +10 -0
- package/build/i18n/keysets/en.json +11 -0
- package/build/i18n/keysets/ru.json +11 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +4 -0
- package/build/libs/chartkit-error/__tests__/chartkit-error.d.ts +1 -0
- package/build/libs/chartkit-error/__tests__/chartkit-error.js +27 -0
- package/build/libs/chartkit-error/chartkit-error.d.ts +16 -0
- package/build/libs/chartkit-error/chartkit-error.js +19 -0
- package/build/libs/index.d.ts +3 -0
- package/build/libs/index.js +2 -0
- package/build/libs/settings/__tests__/settings.test.d.ts +1 -0
- package/build/libs/settings/__tests__/settings.test.js +7 -0
- package/build/libs/settings/settings.d.ts +16 -0
- package/build/libs/settings/settings.js +43 -0
- package/build/plugins/index.d.ts +4 -0
- package/build/plugins/index.js +2 -0
- package/build/plugins/indicator/__stories__/Indicator.stories.d.ts +4 -0
- package/build/plugins/indicator/__stories__/Indicator.stories.js +45 -0
- package/build/plugins/indicator/index.d.ts +2 -0
- package/build/plugins/indicator/index.js +5 -0
- package/build/plugins/indicator/renderer/IndicatorItem.d.ts +6 -0
- package/build/plugins/indicator/renderer/IndicatorItem.js +15 -0
- package/build/plugins/indicator/renderer/IndicatorWidget.css +62 -0
- package/build/plugins/indicator/renderer/IndicatorWidget.d.ts +6 -0
- package/build/plugins/indicator/renderer/IndicatorWidget.js +28 -0
- package/build/plugins/indicator/types.d.ts +21 -0
- package/build/plugins/indicator/types.js +1 -0
- package/build/plugins/yagr/__stories__/Yagr.stories.d.ts +4 -0
- package/build/plugins/yagr/__stories__/Yagr.stories.js +21 -0
- package/build/plugins/yagr/__stories__/mocks/line10.d.ts +2 -0
- package/build/plugins/yagr/__stories__/mocks/line10.js +66 -0
- package/build/plugins/yagr/index.d.ts +2 -0
- package/build/plugins/yagr/index.js +5 -0
- package/build/plugins/yagr/renderer/YagrWidget.css +4 -0
- package/build/plugins/yagr/renderer/YagrWidget.d.ts +7 -0
- package/build/plugins/yagr/renderer/YagrWidget.js +196 -0
- package/build/plugins/yagr/renderer/polyfills.d.ts +1 -0
- package/build/plugins/yagr/renderer/polyfills.js +17 -0
- package/build/plugins/yagr/renderer/synchronizeTooltipTablesCellsWidth.d.ts +1 -0
- package/build/plugins/yagr/renderer/synchronizeTooltipTablesCellsWidth.js +43 -0
- package/build/plugins/yagr/renderer/tooltip/helpers/escapeHTML.d.ts +1 -0
- package/build/plugins/yagr/renderer/tooltip/helpers/escapeHTML.js +5 -0
- package/build/plugins/yagr/renderer/tooltip/tooltip.css +368 -0
- package/build/plugins/yagr/renderer/tooltip/tooltip.d.ts +141 -0
- package/build/plugins/yagr/renderer/tooltip/tooltip.js +229 -0
- package/build/plugins/yagr/types.d.ts +21 -0
- package/build/plugins/yagr/types.js +1 -0
- package/build/types/index.d.ts +33 -0
- package/build/types/index.js +1 -0
- package/build/types/widget.d.ts +13 -0
- package/build/types/widget.js +1 -0
- package/build/utils/__tests__/common.test.d.ts +1 -0
- package/build/utils/__tests__/common.test.js +9 -0
- package/build/utils/common.d.ts +1 -0
- package/build/utils/common.js +8 -0
- package/build/utils/index.d.ts +2 -0
- package/build/utils/index.js +2 -0
- package/build/utils/react.d.ts +1 -0
- package/build/utils/react.js +4 -0
- package/package.json +93 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { withKnobs, boolean, color as colorKnob, radios, text } from '@storybook/addon-knobs';
|
|
3
|
+
import { cloneDeep } from 'lodash';
|
|
4
|
+
import { Button } from '@gravity-ui/uikit';
|
|
5
|
+
import { settings } from '../../../libs';
|
|
6
|
+
import { ChartKit } from '../../../components/ChartKit';
|
|
7
|
+
import { IndicatorPlugin } from '../';
|
|
8
|
+
const data = {
|
|
9
|
+
data: [
|
|
10
|
+
{
|
|
11
|
+
content: {
|
|
12
|
+
current: {
|
|
13
|
+
value: 1539577973,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
const Template = () => {
|
|
20
|
+
const [shown, setShown] = React.useState(false);
|
|
21
|
+
const chartkitRef = React.useRef();
|
|
22
|
+
const color = colorKnob('color', '#4da2f1');
|
|
23
|
+
const size = radios('size', { s: 's', m: 'm', l: 'l', xl: 'xl' }, 'm');
|
|
24
|
+
const title = text('title', 'Value title');
|
|
25
|
+
const nowrap = boolean('nowrap', false);
|
|
26
|
+
const resultData = cloneDeep(data);
|
|
27
|
+
if (resultData.data) {
|
|
28
|
+
resultData.data[0].size = size;
|
|
29
|
+
resultData.data[0].color = color;
|
|
30
|
+
resultData.data[0].title = title;
|
|
31
|
+
resultData.data[0].nowrap = nowrap;
|
|
32
|
+
}
|
|
33
|
+
if (!shown) {
|
|
34
|
+
settings.set({ plugins: [IndicatorPlugin] });
|
|
35
|
+
return React.createElement(Button, { onClick: () => setShown(true) }, "Show chart");
|
|
36
|
+
}
|
|
37
|
+
return (React.createElement("div", { style: { height: 300, width: '100%' } },
|
|
38
|
+
React.createElement(ChartKit, { ref: chartkitRef, id: "1", type: "indicator", data: resultData })));
|
|
39
|
+
};
|
|
40
|
+
export const Showcase = Template.bind({});
|
|
41
|
+
const meta = {
|
|
42
|
+
title: 'Plugins/Indicator',
|
|
43
|
+
decorators: [withKnobs],
|
|
44
|
+
};
|
|
45
|
+
export default meta;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { IndicatorWidgetProps, IndicatorWidgetDataItem } from '../types';
|
|
3
|
+
export declare const IndicatorItem: (props: IndicatorWidgetDataItem & {
|
|
4
|
+
defaultColor?: string;
|
|
5
|
+
formatNumber?: IndicatorWidgetProps['formatNumber'];
|
|
6
|
+
}) => JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import block from 'bem-cn-lite';
|
|
3
|
+
const b = block('chartkit-indicator');
|
|
4
|
+
export const IndicatorItem = (props) => {
|
|
5
|
+
const { formatNumber, content, color, defaultColor, size, title, nowrap } = props;
|
|
6
|
+
const mods = { size, nowrap };
|
|
7
|
+
const style = { color: color || defaultColor };
|
|
8
|
+
let value = content.current.value;
|
|
9
|
+
if (formatNumber && typeof value === 'number') {
|
|
10
|
+
value = formatNumber(value, content.current);
|
|
11
|
+
}
|
|
12
|
+
return (React.createElement("div", { className: b('item', mods) },
|
|
13
|
+
title && (React.createElement("div", { className: b('item-title'), title: nowrap ? title : '' }, title)),
|
|
14
|
+
React.createElement("div", { className: b('item-value'), style: style }, value)));
|
|
15
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
.chartkit-indicator {
|
|
2
|
+
width: 100%;
|
|
3
|
+
height: 100%;
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.chartkit-indicator__content {
|
|
9
|
+
width: 100%;
|
|
10
|
+
overflow: auto;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.chartkit-indicator__item {
|
|
14
|
+
padding: 15px;
|
|
15
|
+
font-size: inherit;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.chartkit-indicator__item_nowrap .chartkit-indicator__item-title {
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
text-overflow: ellipsis;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.chartkit-indicator__item_size_s .chartkit-indicator__item-title {
|
|
26
|
+
font-size: 13px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.chartkit-indicator__item_size_s .chartkit-indicator__item-value {
|
|
30
|
+
font-size: 24px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.chartkit-indicator__item_size_l .chartkit-indicator__item-title {
|
|
34
|
+
font-size: 20px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.chartkit-indicator__item_size_l .chartkit-indicator__item-value {
|
|
38
|
+
font-size: 64px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.chartkit-indicator__item_size_xl .chartkit-indicator__item-title {
|
|
42
|
+
font-size: 24px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.chartkit-indicator__item_size_xl .chartkit-indicator__item-value {
|
|
46
|
+
font-size: 80px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.chartkit-indicator__item-title {
|
|
50
|
+
font-weight: 500;
|
|
51
|
+
line-height: 1.2;
|
|
52
|
+
color: var(--yc-color-text-primary);
|
|
53
|
+
font-size: 16px;
|
|
54
|
+
padding-bottom: 0.125em;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.chartkit-indicator__item-value {
|
|
58
|
+
font-weight: 500;
|
|
59
|
+
line-height: 1.2;
|
|
60
|
+
font-size: 48px;
|
|
61
|
+
white-space: nowrap;
|
|
62
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ChartKitWidgetRef } from '../../../types';
|
|
3
|
+
import type { IndicatorWidgetProps } from '../types';
|
|
4
|
+
import './IndicatorWidget.css';
|
|
5
|
+
declare const IndicatorWidget: React.ForwardRefExoticComponent<IndicatorWidgetProps & React.RefAttributes<ChartKitWidgetRef | undefined>>;
|
|
6
|
+
export default IndicatorWidget;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import block from 'bem-cn-lite';
|
|
3
|
+
import { isEmpty } from 'lodash';
|
|
4
|
+
import { i18n } from '../../../i18n';
|
|
5
|
+
import { CHARTKIT_ERROR_CODE, ChartKitError } from '../../../libs';
|
|
6
|
+
import { CHARTKIT_SCROLLABLE_NODE_CLASSNAME } from '../../../constants';
|
|
7
|
+
import { IndicatorItem } from './IndicatorItem';
|
|
8
|
+
import './IndicatorWidget.css';
|
|
9
|
+
const b = block('chartkit-indicator');
|
|
10
|
+
const IndicatorWidget = React.forwardRef(
|
|
11
|
+
// _ref needs to avoid this React warning:
|
|
12
|
+
// "forwardRef render functions accept exactly two parameters: props and ref"
|
|
13
|
+
(props, _ref) => {
|
|
14
|
+
const { onLoad, formatNumber, data: { data = [], defaultColor }, } = props;
|
|
15
|
+
React.useLayoutEffect(() => {
|
|
16
|
+
// TODO: swap to onRender after https://github.com/gravity-ui/chartkit/issues/33
|
|
17
|
+
onLoad === null || onLoad === void 0 ? void 0 : onLoad();
|
|
18
|
+
});
|
|
19
|
+
if (isEmpty(data)) {
|
|
20
|
+
throw new ChartKitError({
|
|
21
|
+
code: CHARTKIT_ERROR_CODE.NO_DATA,
|
|
22
|
+
message: i18n('error', 'label_no-data'),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return (React.createElement("div", { className: b() },
|
|
26
|
+
React.createElement("div", { className: b('content', CHARTKIT_SCROLLABLE_NODE_CLASSNAME) }, data.map((item, index) => (React.createElement(IndicatorItem, Object.assign({}, item, { key: `${index}-ck-indicator-item`, defaultColor: defaultColor, formatNumber: formatNumber })))))));
|
|
27
|
+
});
|
|
28
|
+
export default IndicatorWidget;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ChartKitFormatNumber } from '../../types';
|
|
2
|
+
export declare type IndicatorWidgetDataItem = {
|
|
3
|
+
content: {
|
|
4
|
+
current: {
|
|
5
|
+
value: string | number;
|
|
6
|
+
} & Record<string, unknown>;
|
|
7
|
+
};
|
|
8
|
+
color?: string;
|
|
9
|
+
size?: 's' | 'm' | 'l' | 'xl';
|
|
10
|
+
title?: string;
|
|
11
|
+
nowrap?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare type IndicatorWidgetData = {
|
|
14
|
+
data?: IndicatorWidgetDataItem[];
|
|
15
|
+
defaultColor?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare type IndicatorWidgetProps = {
|
|
18
|
+
data: IndicatorWidgetData;
|
|
19
|
+
onLoad?: () => void;
|
|
20
|
+
formatNumber?: ChartKitFormatNumber;
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button } from '@gravity-ui/uikit';
|
|
3
|
+
import { settings } from '../../../libs';
|
|
4
|
+
import { YagrPlugin } from '../../../plugins';
|
|
5
|
+
import { ChartKit } from '../../../components/ChartKit';
|
|
6
|
+
import { line10 } from './mocks/line10';
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Plugins/Yagr',
|
|
9
|
+
component: ChartKit,
|
|
10
|
+
};
|
|
11
|
+
const Template = () => {
|
|
12
|
+
const [shown, setShown] = React.useState(false);
|
|
13
|
+
const chartkitRef = React.useRef();
|
|
14
|
+
if (!shown) {
|
|
15
|
+
settings.set({ plugins: [YagrPlugin] });
|
|
16
|
+
return React.createElement(Button, { onClick: () => setShown(true) }, "Show chart");
|
|
17
|
+
}
|
|
18
|
+
return (React.createElement("div", { style: { height: 300, width: '100%' } },
|
|
19
|
+
React.createElement(ChartKit, { ref: chartkitRef, id: "1", type: "yagr", data: line10 })));
|
|
20
|
+
};
|
|
21
|
+
export const Line = Template.bind({});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export const line10 = {
|
|
2
|
+
data: {
|
|
3
|
+
timeline: [
|
|
4
|
+
1636838612441, 1636925012441, 1637011412441, 1637097812441, 1637184212441,
|
|
5
|
+
1637270612441, 1637357012441, 1637443412441, 1637529812441, 1637616212441,
|
|
6
|
+
],
|
|
7
|
+
graphs: [
|
|
8
|
+
{
|
|
9
|
+
id: '0',
|
|
10
|
+
name: 'Serie 1',
|
|
11
|
+
color: '#6c59c2',
|
|
12
|
+
visible: true,
|
|
13
|
+
data: [25, 52, 89, 72, 39, 49, 82, 59, 36, 5],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: '1',
|
|
17
|
+
name: 'Serie 2',
|
|
18
|
+
color: '#6e8188',
|
|
19
|
+
visible: true,
|
|
20
|
+
data: [37, 6, 51, 10, 65, 35, 72, 0, 94, 54],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: '2',
|
|
24
|
+
name: 'Serie 3',
|
|
25
|
+
color: '#e21576',
|
|
26
|
+
visible: true,
|
|
27
|
+
data: [26, 54, 15, 40, 43, 18, 65, 46, 51, 33],
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
libraryConfig: {
|
|
32
|
+
chart: {
|
|
33
|
+
type: 'line',
|
|
34
|
+
},
|
|
35
|
+
title: {
|
|
36
|
+
text: 'line: random 10 pts',
|
|
37
|
+
},
|
|
38
|
+
axes: {
|
|
39
|
+
x: {},
|
|
40
|
+
},
|
|
41
|
+
scales: {
|
|
42
|
+
x: {},
|
|
43
|
+
y: {
|
|
44
|
+
type: 'linear',
|
|
45
|
+
range: 'nice',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
cursor: {
|
|
49
|
+
x: {
|
|
50
|
+
visible: true,
|
|
51
|
+
style: 'solid 2px rgba(230, 2, 7, 0.3)',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
settings: {
|
|
55
|
+
adaptive: true,
|
|
56
|
+
},
|
|
57
|
+
tooltip: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
boundClassName: '.wrapper',
|
|
60
|
+
tracking: 'sticky',
|
|
61
|
+
className: 'chartkit-theme_common',
|
|
62
|
+
},
|
|
63
|
+
legend: {},
|
|
64
|
+
processing: {},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ChartKitWidgetRef } from '../../../types';
|
|
3
|
+
import type { YagrWidgetProps } from '../types';
|
|
4
|
+
import './polyfills';
|
|
5
|
+
import './YagrWidget.css';
|
|
6
|
+
declare const YagrWidget: React.ForwardRefExoticComponent<YagrWidgetProps & React.RefAttributes<ChartKitWidgetRef | undefined>>;
|
|
7
|
+
export default YagrWidget;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import moment from 'moment';
|
|
3
|
+
import debounce from 'lodash/debounce';
|
|
4
|
+
import { useThemeValue } from '@gravity-ui/uikit';
|
|
5
|
+
import YagrComponent from 'yagr/dist/react';
|
|
6
|
+
import { defaults, } from 'yagr';
|
|
7
|
+
import { formatTooltip } from './tooltip/tooltip';
|
|
8
|
+
import { synchronizeTooltipTablesCellsWidth } from './synchronizeTooltipTablesCellsWidth';
|
|
9
|
+
import './polyfills';
|
|
10
|
+
import './YagrWidget.css';
|
|
11
|
+
const calcOption = (d) => {
|
|
12
|
+
return typeof d === 'object'
|
|
13
|
+
? Object.values(d).reduce((_, t) => {
|
|
14
|
+
return t;
|
|
15
|
+
})
|
|
16
|
+
: d;
|
|
17
|
+
};
|
|
18
|
+
/*
|
|
19
|
+
* Default tooltip renderer.
|
|
20
|
+
* Adapter between native Yagr tooltip config and ChartKit
|
|
21
|
+
* tooltip renderer.
|
|
22
|
+
*/
|
|
23
|
+
const renderTooltip = (data) => {
|
|
24
|
+
var _a, _b;
|
|
25
|
+
const cfg = data.yagr.config;
|
|
26
|
+
const timeMultiplier = ((_a = cfg.settings) === null || _a === void 0 ? void 0 : _a.timeMultiplier) || 1;
|
|
27
|
+
const locale = (_b = cfg.settings) === null || _b === void 0 ? void 0 : _b.locale;
|
|
28
|
+
const opts = data.options;
|
|
29
|
+
const { x, pinned } = data;
|
|
30
|
+
let sumTotal = 0;
|
|
31
|
+
const rows = Object.values(data.scales).reduce((acc, scale) => {
|
|
32
|
+
sumTotal += scale.sum || 0;
|
|
33
|
+
return acc.concat(scale.rows);
|
|
34
|
+
}, []);
|
|
35
|
+
const lines = rows.length;
|
|
36
|
+
const sum = calcOption(opts.sum);
|
|
37
|
+
const maxLines = calcOption(opts.maxLines);
|
|
38
|
+
const valueFormatter = calcOption(opts.value);
|
|
39
|
+
// eslint-disable-next-line no-nested-ternary
|
|
40
|
+
const hiddenRowsNumber = pinned
|
|
41
|
+
? undefined
|
|
42
|
+
: lines > maxLines
|
|
43
|
+
? Math.abs(maxLines - lines)
|
|
44
|
+
: undefined;
|
|
45
|
+
const hiddenRowsSum = hiddenRowsNumber
|
|
46
|
+
? valueFormatter(rows
|
|
47
|
+
.slice(-hiddenRowsNumber)
|
|
48
|
+
.reduce((sum, { originalValue }) => sum + (originalValue || 0), 0))
|
|
49
|
+
: undefined;
|
|
50
|
+
const tooltipFormatOptions = {
|
|
51
|
+
activeRowAlwaysFirstInTooltip: rows.length > 1,
|
|
52
|
+
tooltipHeader: moment(x / timeMultiplier).format('DD MMMM YYYY HH:mm:ss'),
|
|
53
|
+
shared: true,
|
|
54
|
+
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) : '' }))),
|
|
55
|
+
withPercent: calcOption(opts.percent),
|
|
56
|
+
hiddenRowsNumber: hiddenRowsNumber,
|
|
57
|
+
hiddenRowsSum,
|
|
58
|
+
};
|
|
59
|
+
if (sum) {
|
|
60
|
+
tooltipFormatOptions.sum = valueFormatter(sumTotal);
|
|
61
|
+
}
|
|
62
|
+
return formatTooltip(tooltipFormatOptions, {
|
|
63
|
+
options: { locale },
|
|
64
|
+
lastVisibleRowIndex: pinned ? rows.length - 1 : maxLines - 1,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const getXAxisFormatter = (msm = 1) => (_, ticks) => {
|
|
68
|
+
const range = (ticks[ticks.length - 1] - ticks[0]) / msm;
|
|
69
|
+
return ticks.map((rawValue) => {
|
|
70
|
+
const d = moment(rawValue / msm);
|
|
71
|
+
if (d.hour() === 0 && d.minutes() === 0 && d.seconds() === 0) {
|
|
72
|
+
return d.format('DD.MM.YY');
|
|
73
|
+
}
|
|
74
|
+
return d.format(range < 300 ? 'HH:mm:ss' : 'HH:mm');
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const YagrWidget = React.forwardRef((props, forwardedRef) => {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const yagrRef = React.useRef(null);
|
|
80
|
+
const { data, libraryConfig } = props.data;
|
|
81
|
+
const { id, onLoad } = props;
|
|
82
|
+
const theme = useThemeValue();
|
|
83
|
+
const handlers = {
|
|
84
|
+
mouseMove: null,
|
|
85
|
+
mouseDown: null,
|
|
86
|
+
};
|
|
87
|
+
const checkFocus = (tooltip) => (event) => {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
const yagr = (_a = yagrRef === null || yagrRef === void 0 ? void 0 : yagrRef.current) === null || _a === void 0 ? void 0 : _a.chart;
|
|
90
|
+
if (!yagr) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const target = event.target;
|
|
94
|
+
const seriesIdx = target && tooltip.contains(target) && target.tagName === 'TD'
|
|
95
|
+
? (_b = target.parentElement) === null || _b === void 0 ? void 0 : _b.dataset['seriesIdx']
|
|
96
|
+
: undefined;
|
|
97
|
+
const serie = seriesIdx ? yagr.uplot.series[Number(seriesIdx)] : null;
|
|
98
|
+
yagr.focus(serie ? serie.id : null, true);
|
|
99
|
+
};
|
|
100
|
+
const detectClickOutside = (tooltip, actions) => (event) => {
|
|
101
|
+
var _a, _b;
|
|
102
|
+
const yagr = (_a = yagrRef === null || yagrRef === void 0 ? void 0 : yagrRef.current) === null || _a === void 0 ? void 0 : _a.chart;
|
|
103
|
+
if (!yagr) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const target = event.target;
|
|
107
|
+
if (target instanceof Element) {
|
|
108
|
+
const isClickInsideTooltip = target && tooltip.contains(target);
|
|
109
|
+
const isClickOnUplotOver = target && ((_b = yagr.root.querySelector('.u-over')) === null || _b === void 0 ? void 0 : _b.contains(target));
|
|
110
|
+
if (!isClickInsideTooltip && !isClickOnUplotOver) {
|
|
111
|
+
actions.pin(false);
|
|
112
|
+
actions.hide();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const config = Object.assign(Object.assign({}, libraryConfig), { timeline: data.timeline, series: data.graphs });
|
|
117
|
+
config.settings = Object.assign({ locale: props.lang, theme }, (config.settings || {}));
|
|
118
|
+
if (((_a = config.tooltip) === null || _a === void 0 ? void 0 : _a.enabled) !== false) {
|
|
119
|
+
config.tooltip = config.tooltip || {};
|
|
120
|
+
config.tooltip.render = ((_b = config.tooltip) === null || _b === void 0 ? void 0 : _b.render) || renderTooltip;
|
|
121
|
+
// "className" property prevent default yagr styles adding
|
|
122
|
+
config.tooltip.className = 'chartkit-yagr-tooltip';
|
|
123
|
+
config.tooltip.onStateChange = (tooltip, { action, actions }) => {
|
|
124
|
+
switch (action) {
|
|
125
|
+
case 'pin': {
|
|
126
|
+
handlers.mouseMove = checkFocus(tooltip);
|
|
127
|
+
handlers.mouseDown = detectClickOutside(tooltip, actions);
|
|
128
|
+
document.addEventListener('mousemove', handlers.mouseMove);
|
|
129
|
+
document.addEventListener('mousedown', handlers.mouseDown);
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case 'unpin': {
|
|
133
|
+
if (handlers.mouseMove) {
|
|
134
|
+
document.removeEventListener('mousemove', handlers.mouseMove);
|
|
135
|
+
handlers.mouseMove = null;
|
|
136
|
+
}
|
|
137
|
+
if (handlers.mouseDown) {
|
|
138
|
+
document.removeEventListener('mousedown', handlers.mouseDown);
|
|
139
|
+
handlers.mouseDown = null;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case 'render': {
|
|
144
|
+
synchronizeTooltipTablesCellsWidth(tooltip);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
config.axes = config.axes || {};
|
|
150
|
+
const xAxis = config.axes[defaults.DEFAULT_X_SCALE];
|
|
151
|
+
if (xAxis && !xAxis.values) {
|
|
152
|
+
xAxis.values = getXAxisFormatter(config.settings.timeMultiplier);
|
|
153
|
+
}
|
|
154
|
+
if (!xAxis) {
|
|
155
|
+
config.axes[defaults.DEFAULT_X_SCALE] = {
|
|
156
|
+
values: getXAxisFormatter(config.settings.timeMultiplier),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const debugFileName = props.data.sources
|
|
160
|
+
? Object.values(props.data.sources)
|
|
161
|
+
.map((source) => {
|
|
162
|
+
var _a;
|
|
163
|
+
return (_a = source === null || source === void 0 ? void 0 : source.data) === null || _a === void 0 ? void 0 : _a.program;
|
|
164
|
+
})
|
|
165
|
+
.filter(Boolean)
|
|
166
|
+
.join(', ') || id
|
|
167
|
+
: id;
|
|
168
|
+
const handleChartLoading = React.useCallback((chart, { renderTime }) => {
|
|
169
|
+
onLoad === null || onLoad === void 0 ? void 0 : onLoad(Object.assign(Object.assign({}, data), { widget: chart, widgetRendering: renderTime }));
|
|
170
|
+
}, [onLoad, data]);
|
|
171
|
+
const onWindowResize = React.useCallback(() => {
|
|
172
|
+
var _a;
|
|
173
|
+
if ((_a = yagrRef.current) === null || _a === void 0 ? void 0 : _a.chart) {
|
|
174
|
+
const chart = yagrRef.current.chart;
|
|
175
|
+
const root = chart.root;
|
|
176
|
+
const height = root.offsetHeight;
|
|
177
|
+
const width = root.offsetWidth;
|
|
178
|
+
chart.uplot.setSize({ width, height });
|
|
179
|
+
chart.uplot.redraw();
|
|
180
|
+
}
|
|
181
|
+
}, []);
|
|
182
|
+
React.useImperativeHandle(forwardedRef, () => ({
|
|
183
|
+
reflow() {
|
|
184
|
+
onWindowResize();
|
|
185
|
+
},
|
|
186
|
+
}), [onWindowResize]);
|
|
187
|
+
React.useEffect(() => {
|
|
188
|
+
const debouncedOnWindowResize = debounce(onWindowResize, 50);
|
|
189
|
+
window.addEventListener('resize', debouncedOnWindowResize);
|
|
190
|
+
return () => {
|
|
191
|
+
window.removeEventListener('resize', debouncedOnWindowResize);
|
|
192
|
+
};
|
|
193
|
+
}, [onWindowResize]);
|
|
194
|
+
return (React.createElement(YagrComponent, { ref: yagrRef, id: id, config: config, onChartLoad: handleChartLoading, debug: { filename: debugFileName } }));
|
|
195
|
+
});
|
|
196
|
+
export default YagrWidget;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare const oMatchMedia: ((query: string) => MediaQueryList) & typeof matchMedia;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* @see https://github.com/leeoniya/uPlot/issues/538#issuecomment-870711531 */
|
|
3
|
+
// eslint-disable-next-line
|
|
4
|
+
const oMatchMedia = window.matchMedia;
|
|
5
|
+
// eslint-disable-next-line
|
|
6
|
+
window.matchMedia = (query) => {
|
|
7
|
+
const mql = oMatchMedia(query);
|
|
8
|
+
if (!mql.addEventListener) {
|
|
9
|
+
mql.addEventListener = (_, handler) => {
|
|
10
|
+
mql.addListener(handler);
|
|
11
|
+
};
|
|
12
|
+
mql.removeEventListener = (_, handler) => {
|
|
13
|
+
mql.removeListener(handler);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return mql;
|
|
17
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function synchronizeTooltipTablesCellsWidth(tooltipContainer: any): false | undefined;
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function escapeHTML(html: string): string;
|