@gravity-ui/charts 0.1.1 → 0.3.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/README.md +3 -0
- package/dist/cjs/components/ChartInner/index.js +18 -10
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/types/chart/chart.d.ts +8 -4
- package/dist/esm/components/ChartInner/index.js +18 -10
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/types/chart/chart.d.ts +8 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# @gravity-ui/charts · [](https://www.npmjs.com/package/@gravity-ui/charts) [](https://github.com/gravity-ui/charts/actions/workflows/ci.yml?query=branch:main) [](https://preview.gravity-ui.com/charts/)
|
|
2
2
|
|
|
3
|
+
> [!WARNING]
|
|
4
|
+
> The library may have major changes in minor releases while it is on version `0.*.*`.
|
|
5
|
+
|
|
3
6
|
## Install
|
|
4
7
|
|
|
5
8
|
```shell
|
|
@@ -17,7 +17,7 @@ import './styles.css';
|
|
|
17
17
|
const b = block('d3');
|
|
18
18
|
const THROTTLE_DELAY = 50;
|
|
19
19
|
export const ChartInner = (props) => {
|
|
20
|
-
var _a, _b;
|
|
20
|
+
var _a, _b, _c, _d;
|
|
21
21
|
const { width, height, data } = props;
|
|
22
22
|
const svgRef = React.useRef(null);
|
|
23
23
|
const htmlLayerRef = React.useRef(null);
|
|
@@ -73,38 +73,46 @@ export const ChartInner = (props) => {
|
|
|
73
73
|
htmlLayout: htmlLayerRef.current,
|
|
74
74
|
});
|
|
75
75
|
const clickHandler = (_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click;
|
|
76
|
+
const pointerMoveHandler = (_d = (_c = data.chart) === null || _c === void 0 ? void 0 : _c.events) === null || _d === void 0 ? void 0 : _d.pointermove;
|
|
76
77
|
React.useEffect(() => {
|
|
77
78
|
if (clickHandler) {
|
|
78
79
|
dispatcher.on('click-chart', clickHandler);
|
|
79
80
|
}
|
|
81
|
+
if (pointerMoveHandler) {
|
|
82
|
+
dispatcher.on('hover-shape.chart', (...args) => {
|
|
83
|
+
const [hoverData, _position, event] = args;
|
|
84
|
+
pointerMoveHandler(hoverData, event);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
80
87
|
return () => {
|
|
81
88
|
dispatcher.on('click-chart', null);
|
|
89
|
+
dispatcher.on('hover-shape.chart', null);
|
|
82
90
|
};
|
|
83
|
-
}, [dispatcher, clickHandler]);
|
|
91
|
+
}, [dispatcher, clickHandler, pointerMoveHandler]);
|
|
84
92
|
const boundsOffsetTop = chart.margin.top;
|
|
85
93
|
// We only need to consider the width of the first left axis
|
|
86
94
|
const boundsOffsetLeft = chart.margin.left + getYAxisWidth(yAxis[0]);
|
|
87
95
|
const isOutsideBounds = React.useCallback((x, y) => {
|
|
88
96
|
return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
|
|
89
97
|
}, [boundsHeight, boundsWidth]);
|
|
90
|
-
const
|
|
98
|
+
const handlePointerMove = (event) => {
|
|
91
99
|
const [pointerX, pointerY] = pointer(event, svgRef.current);
|
|
92
100
|
const x = pointerX - boundsOffsetLeft;
|
|
93
101
|
const y = pointerY - boundsOffsetTop;
|
|
94
102
|
if (isOutsideBounds(x, y)) {
|
|
95
|
-
dispatcher.call('hover-shape', {}, undefined);
|
|
103
|
+
dispatcher.call('hover-shape', {}, undefined, undefined, event);
|
|
96
104
|
return;
|
|
97
105
|
}
|
|
98
106
|
const closest = getClosestPoints({
|
|
99
107
|
position: [x, y],
|
|
100
108
|
shapesData,
|
|
101
109
|
});
|
|
102
|
-
dispatcher.call('hover-shape', event.target, closest, [pointerX, pointerY]);
|
|
110
|
+
dispatcher.call('hover-shape', event.target, closest, [pointerX, pointerY], event);
|
|
103
111
|
};
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
dispatcher.call('hover-shape', {}, undefined);
|
|
112
|
+
const throttledHandlePointerMove = throttle(handlePointerMove, THROTTLE_DELAY);
|
|
113
|
+
const handlePointerLeave = (event) => {
|
|
114
|
+
throttledHandlePointerMove.cancel();
|
|
115
|
+
dispatcher.call('hover-shape', {}, undefined, undefined, event);
|
|
108
116
|
};
|
|
109
117
|
const handleChartClick = React.useCallback((event) => {
|
|
110
118
|
const [pointerX, pointerY] = pointer(event, svgRef.current);
|
|
@@ -124,7 +132,7 @@ export const ChartInner = (props) => {
|
|
|
124
132
|
dispatcher.call('click-chart', undefined, { point: selected.data, series: selected.series }, event);
|
|
125
133
|
}, [boundsOffsetLeft, boundsOffsetTop, dispatcher, isOutsideBounds, shapesData]);
|
|
126
134
|
return (React.createElement(React.Fragment, null,
|
|
127
|
-
React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height,
|
|
135
|
+
React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height, onPointerMove: throttledHandlePointerMove, onPointerLeave: handlePointerLeave, onClick: handleChartClick },
|
|
128
136
|
title && React.createElement(Title, Object.assign({}, title, { chartWidth: width })),
|
|
129
137
|
React.createElement("g", { transform: `translate(0, ${boundsOffsetTop})` }, preparedSplit.plots.map((plot, index) => {
|
|
130
138
|
return React.createElement(PlotTitle, { key: `plot-${index}`, title: plot.title });
|
package/dist/cjs/index.d.ts
CHANGED
package/dist/cjs/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import type { MeaningfulAny } from '../misc';
|
|
1
2
|
export type ChartMargin = {
|
|
2
3
|
top: number;
|
|
3
4
|
right: number;
|
|
4
5
|
bottom: number;
|
|
5
6
|
left: number;
|
|
6
7
|
};
|
|
8
|
+
type ChartEventData = {
|
|
9
|
+
point: MeaningfulAny;
|
|
10
|
+
series: MeaningfulAny;
|
|
11
|
+
};
|
|
7
12
|
export type ChartOptions = {
|
|
8
13
|
margin?: Partial<ChartMargin>;
|
|
9
14
|
events?: {
|
|
10
|
-
click?: (data:
|
|
11
|
-
|
|
12
|
-
series: unknown;
|
|
13
|
-
}, event: PointerEvent) => void;
|
|
15
|
+
click?: (data: ChartEventData, event: PointerEvent) => void;
|
|
16
|
+
pointermove?: (data: ChartEventData | undefined, event: PointerEvent) => void;
|
|
14
17
|
};
|
|
15
18
|
};
|
|
19
|
+
export {};
|
|
@@ -17,7 +17,7 @@ import './styles.css';
|
|
|
17
17
|
const b = block('d3');
|
|
18
18
|
const THROTTLE_DELAY = 50;
|
|
19
19
|
export const ChartInner = (props) => {
|
|
20
|
-
var _a, _b;
|
|
20
|
+
var _a, _b, _c, _d;
|
|
21
21
|
const { width, height, data } = props;
|
|
22
22
|
const svgRef = React.useRef(null);
|
|
23
23
|
const htmlLayerRef = React.useRef(null);
|
|
@@ -73,38 +73,46 @@ export const ChartInner = (props) => {
|
|
|
73
73
|
htmlLayout: htmlLayerRef.current,
|
|
74
74
|
});
|
|
75
75
|
const clickHandler = (_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click;
|
|
76
|
+
const pointerMoveHandler = (_d = (_c = data.chart) === null || _c === void 0 ? void 0 : _c.events) === null || _d === void 0 ? void 0 : _d.pointermove;
|
|
76
77
|
React.useEffect(() => {
|
|
77
78
|
if (clickHandler) {
|
|
78
79
|
dispatcher.on('click-chart', clickHandler);
|
|
79
80
|
}
|
|
81
|
+
if (pointerMoveHandler) {
|
|
82
|
+
dispatcher.on('hover-shape.chart', (...args) => {
|
|
83
|
+
const [hoverData, _position, event] = args;
|
|
84
|
+
pointerMoveHandler(hoverData, event);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
80
87
|
return () => {
|
|
81
88
|
dispatcher.on('click-chart', null);
|
|
89
|
+
dispatcher.on('hover-shape.chart', null);
|
|
82
90
|
};
|
|
83
|
-
}, [dispatcher, clickHandler]);
|
|
91
|
+
}, [dispatcher, clickHandler, pointerMoveHandler]);
|
|
84
92
|
const boundsOffsetTop = chart.margin.top;
|
|
85
93
|
// We only need to consider the width of the first left axis
|
|
86
94
|
const boundsOffsetLeft = chart.margin.left + getYAxisWidth(yAxis[0]);
|
|
87
95
|
const isOutsideBounds = React.useCallback((x, y) => {
|
|
88
96
|
return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
|
|
89
97
|
}, [boundsHeight, boundsWidth]);
|
|
90
|
-
const
|
|
98
|
+
const handlePointerMove = (event) => {
|
|
91
99
|
const [pointerX, pointerY] = pointer(event, svgRef.current);
|
|
92
100
|
const x = pointerX - boundsOffsetLeft;
|
|
93
101
|
const y = pointerY - boundsOffsetTop;
|
|
94
102
|
if (isOutsideBounds(x, y)) {
|
|
95
|
-
dispatcher.call('hover-shape', {}, undefined);
|
|
103
|
+
dispatcher.call('hover-shape', {}, undefined, undefined, event);
|
|
96
104
|
return;
|
|
97
105
|
}
|
|
98
106
|
const closest = getClosestPoints({
|
|
99
107
|
position: [x, y],
|
|
100
108
|
shapesData,
|
|
101
109
|
});
|
|
102
|
-
dispatcher.call('hover-shape', event.target, closest, [pointerX, pointerY]);
|
|
110
|
+
dispatcher.call('hover-shape', event.target, closest, [pointerX, pointerY], event);
|
|
103
111
|
};
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
dispatcher.call('hover-shape', {}, undefined);
|
|
112
|
+
const throttledHandlePointerMove = throttle(handlePointerMove, THROTTLE_DELAY);
|
|
113
|
+
const handlePointerLeave = (event) => {
|
|
114
|
+
throttledHandlePointerMove.cancel();
|
|
115
|
+
dispatcher.call('hover-shape', {}, undefined, undefined, event);
|
|
108
116
|
};
|
|
109
117
|
const handleChartClick = React.useCallback((event) => {
|
|
110
118
|
const [pointerX, pointerY] = pointer(event, svgRef.current);
|
|
@@ -124,7 +132,7 @@ export const ChartInner = (props) => {
|
|
|
124
132
|
dispatcher.call('click-chart', undefined, { point: selected.data, series: selected.series }, event);
|
|
125
133
|
}, [boundsOffsetLeft, boundsOffsetTop, dispatcher, isOutsideBounds, shapesData]);
|
|
126
134
|
return (React.createElement(React.Fragment, null,
|
|
127
|
-
React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height,
|
|
135
|
+
React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height, onPointerMove: throttledHandlePointerMove, onPointerLeave: handlePointerLeave, onClick: handleChartClick },
|
|
128
136
|
title && React.createElement(Title, Object.assign({}, title, { chartWidth: width })),
|
|
129
137
|
React.createElement("g", { transform: `translate(0, ${boundsOffsetTop})` }, preparedSplit.plots.map((plot, index) => {
|
|
130
138
|
return React.createElement(PlotTitle, { key: `plot-${index}`, title: plot.title });
|
package/dist/esm/index.d.ts
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import type { MeaningfulAny } from '../misc';
|
|
1
2
|
export type ChartMargin = {
|
|
2
3
|
top: number;
|
|
3
4
|
right: number;
|
|
4
5
|
bottom: number;
|
|
5
6
|
left: number;
|
|
6
7
|
};
|
|
8
|
+
type ChartEventData = {
|
|
9
|
+
point: MeaningfulAny;
|
|
10
|
+
series: MeaningfulAny;
|
|
11
|
+
};
|
|
7
12
|
export type ChartOptions = {
|
|
8
13
|
margin?: Partial<ChartMargin>;
|
|
9
14
|
events?: {
|
|
10
|
-
click?: (data:
|
|
11
|
-
|
|
12
|
-
series: unknown;
|
|
13
|
-
}, event: PointerEvent) => void;
|
|
15
|
+
click?: (data: ChartEventData, event: PointerEvent) => void;
|
|
16
|
+
pointermove?: (data: ChartEventData | undefined, event: PointerEvent) => void;
|
|
14
17
|
};
|
|
15
18
|
};
|
|
19
|
+
export {};
|