@gravity-ui/charts 1.46.1 → 1.47.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/dist/cjs/components/ChartInner/index.js +1 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +1 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +12 -5
- package/dist/cjs/core/brush/index.d.ts +2 -0
- package/dist/cjs/core/brush/index.js +2 -0
- package/dist/cjs/{hooks/useBrush → core/brush}/types.d.ts +2 -2
- package/dist/{esm/hooks/useBrush → cjs/core/brush}/utils.d.ts +1 -1
- package/dist/cjs/core/chart/index.d.ts +1 -0
- package/dist/cjs/core/chart/index.js +1 -0
- package/dist/cjs/core/chart/types.d.ts +8 -0
- package/dist/cjs/core/index.d.ts +3 -0
- package/dist/cjs/core/index.js +3 -0
- package/dist/cjs/core/layout/chart-dimensions.d.ts +1 -1
- package/dist/cjs/core/range-slider/index.d.ts +2 -0
- package/dist/cjs/core/range-slider/index.js +2 -0
- package/dist/cjs/core/range-slider/types.d.ts +4 -0
- package/dist/cjs/{hooks/useRangeSlider → core/range-slider}/utils.d.ts +5 -5
- package/dist/cjs/{hooks/useRangeSlider → core/range-slider}/utils.js +1 -1
- package/dist/cjs/core/scales/x-scale.d.ts +2 -2
- package/dist/cjs/core/scales/y-scale.js +21 -0
- package/dist/cjs/core/series/prepare-legend.d.ts +1 -1
- package/dist/cjs/core/shapes/area/prepare-data.js +6 -1
- package/dist/cjs/core/shapes/area/renderer.js +8 -14
- package/dist/cjs/core/shapes/area/types.d.ts +6 -5
- package/dist/cjs/core/shapes/bar-x/renderer.js +6 -12
- package/dist/cjs/core/shapes/bar-y/renderer.js +6 -12
- package/dist/cjs/core/shapes/data-labels.d.ts +15 -0
- package/dist/cjs/core/shapes/data-labels.js +15 -0
- package/dist/cjs/core/shapes/funnel/renderer.js +6 -11
- package/dist/cjs/core/shapes/heatmap/prepare-data.js +1 -0
- package/dist/cjs/core/shapes/heatmap/renderer.js +6 -11
- package/dist/cjs/core/shapes/heatmap/types.d.ts +1 -0
- package/dist/cjs/core/shapes/line/prepare-data.js +9 -1
- package/dist/cjs/core/shapes/line/renderer.js +7 -13
- package/dist/cjs/core/shapes/line/types.d.ts +5 -4
- package/dist/cjs/core/shapes/radar/renderer.js +8 -12
- package/dist/cjs/core/shapes/sankey/renderer.js +6 -12
- package/dist/cjs/core/shapes/utils.d.ts +24 -0
- package/dist/cjs/core/shapes/utils.js +48 -0
- package/dist/cjs/core/shapes/waterfall/renderer.js +6 -12
- package/dist/cjs/core/shapes/x-range/renderer.js +7 -13
- package/dist/cjs/core/types/chart/base.d.ts +17 -3
- package/dist/cjs/core/types/chart/tooltip.d.ts +3 -3
- package/dist/cjs/core/types/formatter.d.ts +1 -40
- package/dist/cjs/core/utils/format.d.ts +2 -2
- package/dist/cjs/core/utils/get-closest-data.js +13 -8
- package/dist/cjs/core/zoom/index.d.ts +2 -0
- package/dist/cjs/core/zoom/index.js +2 -0
- package/dist/{esm/hooks/useZoom → cjs/core/zoom}/utils.d.ts +3 -3
- package/dist/{esm/hooks/useZoom → cjs/core/zoom}/utils.js +1 -1
- package/dist/cjs/core/zoom/zoom.d.ts +3 -3
- package/dist/cjs/hooks/index.d.ts +2 -2
- package/dist/cjs/hooks/index.js +2 -2
- package/dist/cjs/hooks/types.d.ts +2 -8
- package/dist/cjs/hooks/useBrush/index.d.ts +1 -1
- package/dist/cjs/hooks/useBrush/index.js +1 -1
- package/dist/cjs/hooks/useRangeSlider/index.js +3 -3
- package/dist/cjs/hooks/useRangeSlider/types.d.ts +5 -7
- package/dist/cjs/hooks/useShapes/index.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/utils.d.ts +1 -1
- package/dist/cjs/hooks/useZoom/index.d.ts +1 -1
- package/dist/cjs/hooks/useZoom/index.js +1 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/libs/format-number/index.js +82 -14
- package/dist/cjs/libs/format-number/presets.d.ts +40 -0
- package/dist/cjs/libs/format-number/presets.js +66 -0
- package/dist/cjs/libs/format-number/types.d.ts +82 -3
- package/dist/esm/components/ChartInner/index.js +1 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +1 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.js +12 -5
- package/dist/esm/core/brush/index.d.ts +2 -0
- package/dist/esm/core/brush/index.js +2 -0
- package/dist/esm/{hooks/useBrush → core/brush}/types.d.ts +2 -2
- package/dist/esm/core/brush/types.js +1 -0
- package/dist/{cjs/hooks/useBrush → esm/core/brush}/utils.d.ts +1 -1
- package/dist/esm/core/chart/index.d.ts +1 -0
- package/dist/esm/core/chart/index.js +1 -0
- package/dist/esm/core/chart/types.d.ts +8 -0
- package/dist/esm/core/chart/types.js +1 -0
- package/dist/esm/core/index.d.ts +3 -0
- package/dist/esm/core/index.js +3 -0
- package/dist/esm/core/layout/chart-dimensions.d.ts +1 -1
- package/dist/esm/core/range-slider/index.d.ts +2 -0
- package/dist/esm/core/range-slider/index.js +2 -0
- package/dist/esm/core/range-slider/types.d.ts +4 -0
- package/dist/esm/core/range-slider/types.js +1 -0
- package/dist/esm/{hooks/useRangeSlider → core/range-slider}/utils.d.ts +5 -5
- package/dist/esm/{hooks/useRangeSlider → core/range-slider}/utils.js +1 -1
- package/dist/esm/core/scales/x-scale.d.ts +2 -2
- package/dist/esm/core/scales/y-scale.js +21 -0
- package/dist/esm/core/series/prepare-legend.d.ts +1 -1
- package/dist/esm/core/shapes/area/prepare-data.js +6 -1
- package/dist/esm/core/shapes/area/renderer.js +8 -14
- package/dist/esm/core/shapes/area/types.d.ts +6 -5
- package/dist/esm/core/shapes/bar-x/renderer.js +6 -12
- package/dist/esm/core/shapes/bar-y/renderer.js +6 -12
- package/dist/esm/core/shapes/data-labels.d.ts +15 -0
- package/dist/esm/core/shapes/data-labels.js +15 -0
- package/dist/esm/core/shapes/funnel/renderer.js +6 -11
- package/dist/esm/core/shapes/heatmap/prepare-data.js +1 -0
- package/dist/esm/core/shapes/heatmap/renderer.js +6 -11
- package/dist/esm/core/shapes/heatmap/types.d.ts +1 -0
- package/dist/esm/core/shapes/line/prepare-data.js +9 -1
- package/dist/esm/core/shapes/line/renderer.js +7 -13
- package/dist/esm/core/shapes/line/types.d.ts +5 -4
- package/dist/esm/core/shapes/radar/renderer.js +8 -12
- package/dist/esm/core/shapes/sankey/renderer.js +6 -12
- package/dist/esm/core/shapes/utils.d.ts +24 -0
- package/dist/esm/core/shapes/utils.js +48 -0
- package/dist/esm/core/shapes/waterfall/renderer.js +6 -12
- package/dist/esm/core/shapes/x-range/renderer.js +7 -13
- package/dist/esm/core/types/chart/base.d.ts +17 -3
- package/dist/esm/core/types/chart/tooltip.d.ts +3 -3
- package/dist/esm/core/types/formatter.d.ts +1 -40
- package/dist/esm/core/utils/format.d.ts +2 -2
- package/dist/esm/core/utils/get-closest-data.js +13 -8
- package/dist/esm/core/zoom/index.d.ts +2 -0
- package/dist/esm/core/zoom/index.js +2 -0
- package/dist/esm/core/zoom/types.js +1 -0
- package/dist/{cjs/hooks/useZoom → esm/core/zoom}/utils.d.ts +3 -3
- package/dist/{cjs/hooks/useZoom → esm/core/zoom}/utils.js +1 -1
- package/dist/esm/core/zoom/zoom.d.ts +3 -3
- package/dist/esm/hooks/index.d.ts +2 -2
- package/dist/esm/hooks/index.js +2 -2
- package/dist/esm/hooks/types.d.ts +2 -8
- package/dist/esm/hooks/useBrush/index.d.ts +1 -1
- package/dist/esm/hooks/useBrush/index.js +1 -1
- package/dist/esm/hooks/useRangeSlider/index.js +3 -3
- package/dist/esm/hooks/useRangeSlider/types.d.ts +5 -7
- package/dist/esm/hooks/useShapes/index.d.ts +1 -1
- package/dist/esm/hooks/useShapes/utils.d.ts +1 -1
- package/dist/esm/hooks/useZoom/index.d.ts +1 -1
- package/dist/esm/hooks/useZoom/index.js +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/libs/format-number/index.js +82 -14
- package/dist/esm/libs/format-number/presets.d.ts +40 -0
- package/dist/esm/libs/format-number/presets.js +66 -0
- package/dist/esm/libs/format-number/types.d.ts +82 -3
- package/package.json +1 -1
- /package/dist/cjs/{hooks/useBrush → core/brush}/types.js +0 -0
- /package/dist/cjs/{hooks/useBrush → core/brush}/utils.js +0 -0
- /package/dist/cjs/{hooks/useZoom → core/chart}/types.js +0 -0
- /package/dist/{esm/hooks/useBrush → cjs/core/range-slider}/types.js +0 -0
- /package/dist/cjs/{hooks/useZoom → core/zoom}/types.d.ts +0 -0
- /package/dist/{esm/hooks/useZoom → cjs/core/zoom}/types.js +0 -0
- /package/dist/esm/{hooks/useBrush → core/brush}/utils.js +0 -0
- /package/dist/esm/{hooks/useZoom → core/zoom}/types.d.ts +0 -0
|
@@ -55,6 +55,7 @@ export const ChartInner = (props) => {
|
|
|
55
55
|
const { activeLegendItems, allPreparedSeries, boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, legendConfig, legendItems, preparedLegend, preparedSeries, preparedSeriesOptions, preparedSplit, shapes, shapesData, shapesReady, xAxis, xScale, yAxis, yScale, preparedTitle, preparedChart, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
|
|
56
56
|
dispatcher,
|
|
57
57
|
htmlLayout, plotNode: plotRef.current, rangeSliderState,
|
|
58
|
+
updateRangeSliderState,
|
|
58
59
|
updateZoomState,
|
|
59
60
|
zoomState }));
|
|
60
61
|
const prevWidth = usePrevious(width);
|
|
@@ -9,6 +9,7 @@ type Props = ChartInnerProps & {
|
|
|
9
9
|
dispatcher: Dispatch<object>;
|
|
10
10
|
htmlLayout: HTMLElement | null;
|
|
11
11
|
plotNode: SVGGElement | null;
|
|
12
|
+
updateRangeSliderState: (nextState?: RangeSliderState) => void;
|
|
12
13
|
updateZoomState: (nextZoomState: Partial<ZoomState>) => void;
|
|
13
14
|
zoomState: Partial<ZoomState>;
|
|
14
15
|
rangeSliderState?: RangeSliderState;
|
|
@@ -38,7 +38,7 @@ function getBoundsOffsetLeft(args) {
|
|
|
38
38
|
}
|
|
39
39
|
export function useChartInnerProps(props) {
|
|
40
40
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
41
|
-
const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, rangeSliderState, width, updateZoomState, zoomState, } = props;
|
|
41
|
+
const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, rangeSliderState, width, updateRangeSliderState, updateZoomState, zoomState, } = props;
|
|
42
42
|
const [selectedLegendItems, setSelectedLegendItems] = React.useState(null);
|
|
43
43
|
const [chartState, setState] = React.useState(null);
|
|
44
44
|
const prevStateValue = React.useRef(chartState);
|
|
@@ -48,20 +48,26 @@ export function useChartInnerProps(props) {
|
|
|
48
48
|
currentRunRef.current++;
|
|
49
49
|
const currentRun = currentRunRef.current;
|
|
50
50
|
(async function () {
|
|
51
|
-
var _a, _b, _c, _d;
|
|
51
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
52
52
|
const chartDataChanged = !(previousChartData.current && isEqual(previousChartData.current, data));
|
|
53
|
+
const axisTypeChanged = ((_b = (_a = previousChartData.current) === null || _a === void 0 ? void 0 : _a.xAxis) === null || _b === void 0 ? void 0 : _b.type) !== undefined &&
|
|
54
|
+
previousChartData.current.xAxis.type !== ((_c = data.xAxis) === null || _c === void 0 ? void 0 : _c.type);
|
|
55
|
+
if (axisTypeChanged && rangeSliderState !== undefined) {
|
|
56
|
+
updateRangeSliderState(undefined);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
53
59
|
const preparedTitle = await getPreparedTitle({
|
|
54
60
|
title: data.title,
|
|
55
61
|
chartWidth: width,
|
|
56
62
|
chartHeight: height,
|
|
57
|
-
chartMargin: (
|
|
63
|
+
chartMargin: (_d = data.chart) === null || _d === void 0 ? void 0 : _d.margin,
|
|
58
64
|
});
|
|
59
65
|
const preparedChart = getPreparedChart({
|
|
60
66
|
chart: data.chart,
|
|
61
67
|
seriesData: data.series.data,
|
|
62
68
|
preparedTitle,
|
|
63
69
|
});
|
|
64
|
-
const colors = (
|
|
70
|
+
const colors = (_e = data.colors) !== null && _e !== void 0 ? _e : DEFAULT_PALETTE;
|
|
65
71
|
const normalizedSeriesData = getSortedSeriesData({
|
|
66
72
|
seriesData: data.series.data,
|
|
67
73
|
xAxis: data.xAxis,
|
|
@@ -84,7 +90,7 @@ export function useChartInnerProps(props) {
|
|
|
84
90
|
});
|
|
85
91
|
}
|
|
86
92
|
else {
|
|
87
|
-
allPreparedSeries = (
|
|
93
|
+
allPreparedSeries = (_g = (_f = prevStateValue.current) === null || _f === void 0 ? void 0 : _f.allPreparedSeries) !== null && _g !== void 0 ? _g : [];
|
|
88
94
|
}
|
|
89
95
|
const activeLegendItems = selectedLegendItems !== null && selectedLegendItems !== void 0 ? selectedLegendItems : getActiveLegendItems(allPreparedSeries);
|
|
90
96
|
const visiblePreparedSeries = getVisibleSeries({
|
|
@@ -243,6 +249,7 @@ export function useChartInnerProps(props) {
|
|
|
243
249
|
rangeSliderState,
|
|
244
250
|
dispatcher,
|
|
245
251
|
htmlLayout,
|
|
252
|
+
updateRangeSliderState,
|
|
246
253
|
clipPathId,
|
|
247
254
|
]);
|
|
248
255
|
// additional start
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BrushBehavior } from 'd3-brush';
|
|
2
|
-
import type { ZoomType } from '
|
|
3
|
-
import type { ChartBrush, DeepRequired } from '
|
|
2
|
+
import type { ZoomType } from '../constants';
|
|
3
|
+
import type { ChartBrush, DeepRequired } from '../types';
|
|
4
4
|
export type BrushSelection = [number, number] | [[number, number], [number, number]];
|
|
5
5
|
export interface BrushArea {
|
|
6
6
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BrushBehavior } from 'd3-brush';
|
|
2
|
-
import type { ChartBrush, DeepRequired } from '
|
|
2
|
+
import type { ChartBrush, DeepRequired } from '../types';
|
|
3
3
|
import type { BrushSelection } from './types';
|
|
4
4
|
export declare function isOneDimensionalSelection(selection?: BrushSelection | null): selection is [number, number];
|
|
5
5
|
export declare function setBrushBorder(this: SVGGElement, _brushInstance: BrushBehavior<unknown>, selection: BrushSelection | null, options: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ChartBrush, ChartMargin, ChartZoom, DeepRequired } from '../types';
|
|
2
|
+
export type PreparedZoom = DeepRequired<Omit<ChartZoom, 'enabled' | 'brush'>> & DeepRequired<{
|
|
3
|
+
brush: ChartBrush;
|
|
4
|
+
}>;
|
|
5
|
+
export type PreparedChart = {
|
|
6
|
+
margin: ChartMargin;
|
|
7
|
+
zoom: PreparedZoom | null;
|
|
8
|
+
};
|
package/dist/cjs/core/index.d.ts
CHANGED
package/dist/cjs/core/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { PreparedChart } from '../../hooks/types';
|
|
2
1
|
import type { ChartMargin, LegendConfig } from '../../types';
|
|
3
2
|
import type { PreparedXAxis, PreparedYAxis } from '../axes/types';
|
|
3
|
+
import type { PreparedChart } from '../chart/types';
|
|
4
4
|
import type { PreparedLegend, PreparedSeries } from '../series';
|
|
5
5
|
export declare const getBoundsWidth: (args: {
|
|
6
6
|
chartWidth: number;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type { PreparedChart } from '../types';
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
1
|
+
import type { PreparedRangeSlider } from '../axes/types';
|
|
2
|
+
import type { BrushSelection } from '../brush/types';
|
|
3
|
+
import type { PreparedChart } from '../chart/types';
|
|
4
|
+
import type { ChartScale } from '../scales/types';
|
|
5
|
+
import type { PreparedLegend } from '../series/types';
|
|
6
6
|
import type { RangeSliderState } from './types';
|
|
7
7
|
export declare function getRangeSliderOffsetTop(args: {
|
|
8
8
|
height: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { RangeSliderState } from '../../hooks';
|
|
2
|
-
import type { ChartAxis, ChartSeries } from '../../types';
|
|
3
1
|
import type { PreparedAxis } from '../axes/types';
|
|
2
|
+
import type { RangeSliderState } from '../range-slider/types';
|
|
4
3
|
import type { PreparedSeries } from '../series';
|
|
4
|
+
import type { ChartAxis, ChartSeries } from '../types';
|
|
5
5
|
export declare function createXScale(args: {
|
|
6
6
|
axis: PreparedAxis | ChartAxis;
|
|
7
7
|
boundsWidth: number;
|
|
@@ -218,6 +218,27 @@ export function createYScale(args) {
|
|
|
218
218
|
else {
|
|
219
219
|
yMax = hasSeriesWithVolumeOnYAxis ? Math.max(yMaxDomain, 0) : yMaxDomain;
|
|
220
220
|
}
|
|
221
|
+
// When the user pins only one of min/max on the wrong side of all data,
|
|
222
|
+
// d3 produces either an inverted scale (yMax<yMin, silently flips the
|
|
223
|
+
// axis) or a degenerate one (yMax===yMin, maps everything to the range
|
|
224
|
+
// midpoint); both leave phantom hover targets inside an empty plot.
|
|
225
|
+
// Expand the auto-computed side so the scale stays sane. Only applies
|
|
226
|
+
// when the opposite bound is auto-derived — if the user supplied both
|
|
227
|
+
// bounds, trust the explicit range and let point filtering hide the
|
|
228
|
+
// rest. Comparison uses the raw data extent because upstream coercions
|
|
229
|
+
// like volume-series `yMax = Math.max(yMaxDomain, 0)` can make the
|
|
230
|
+
// post-coerced yMin/yMax lie about where data actually sits.
|
|
231
|
+
// Logarithmic has its own guard.
|
|
232
|
+
if (axis.type === 'linear') {
|
|
233
|
+
const minIsUserSet = typeof yMinPropsOrState === 'number';
|
|
234
|
+
const maxIsUserSet = typeof yMaxPropsOrState === 'number';
|
|
235
|
+
if (minIsUserSet && !maxIsUserSet && yMaxDomain < yMin) {
|
|
236
|
+
yMax = yMin + Math.max(Math.abs(yMin), 1);
|
|
237
|
+
}
|
|
238
|
+
else if (maxIsUserSet && !minIsUserSet && yMinDomain > yMax) {
|
|
239
|
+
yMin = yMax - Math.max(Math.abs(yMax), 1);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
221
242
|
const scaleFn = axis.type === 'logarithmic' ? scaleLog : scaleLinear;
|
|
222
243
|
let scale = scaleFn().domain([yMin, yMax]).range(range);
|
|
223
244
|
let offsetMin = 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { PreparedChart } from '../../hooks/types';
|
|
2
1
|
import type { ChartData } from '../../types';
|
|
2
|
+
import type { PreparedChart } from '../chart/types';
|
|
3
3
|
import type { LegendItem, PreparedLegend, PreparedSeries } from './types';
|
|
4
4
|
export declare function getPreparedLegend(args: {
|
|
5
5
|
legend: ChartData['legend'];
|
|
@@ -2,7 +2,7 @@ import { group, min, sort } from 'd3-array';
|
|
|
2
2
|
import isNil from 'lodash/isNil';
|
|
3
3
|
import round from 'lodash/round';
|
|
4
4
|
import { prepareAnnotation } from '../../series/prepare-annotation';
|
|
5
|
-
import { getXValue, getYValue } from '../../shapes/utils';
|
|
5
|
+
import { getXValue, getYValue, markHiddenPointsOutOfYRange } from '../../shapes/utils';
|
|
6
6
|
import { getDataCategoryValue, getLabelsSize, getTextSizeFn } from '../../utils';
|
|
7
7
|
import { getFormattedValue } from '../../utils/format';
|
|
8
8
|
function getXValues(series, xAxis, xScale) {
|
|
@@ -315,6 +315,11 @@ export const prepareAreaData = async (args) => {
|
|
|
315
315
|
}
|
|
316
316
|
return result;
|
|
317
317
|
}, []);
|
|
318
|
+
markHiddenPointsOutOfYRange({
|
|
319
|
+
points,
|
|
320
|
+
yScale: seriesYScale,
|
|
321
|
+
yAxisTop,
|
|
322
|
+
});
|
|
318
323
|
seriesStackData.push({
|
|
319
324
|
annotations,
|
|
320
325
|
points,
|
|
@@ -5,6 +5,7 @@ import get from 'lodash/get';
|
|
|
5
5
|
import { block } from '../../../utils';
|
|
6
6
|
import { filterOverlappingLabels } from '../../utils';
|
|
7
7
|
import { renderAnnotations } from '../annotation';
|
|
8
|
+
import { renderDataLabels } from '../data-labels';
|
|
8
9
|
import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../marker';
|
|
9
10
|
import { setActiveState } from '../utils';
|
|
10
11
|
const b = block('area');
|
|
@@ -17,7 +18,7 @@ export function renderArea(elements, preparedData, seriesOptions, allowOverlapDa
|
|
|
17
18
|
const inactiveOptions = get(seriesOptions, 'area.states.inactive');
|
|
18
19
|
const line = lineGenerator()
|
|
19
20
|
.x((d) => d.x)
|
|
20
|
-
.defined((d) => d.y !== null)
|
|
21
|
+
.defined((d) => d.y !== null && !d.hiddenInLine)
|
|
21
22
|
.y((d) => d.y);
|
|
22
23
|
plotSvgElement.selectAll('*').remove();
|
|
23
24
|
markersSvgElement.selectAll('*').remove();
|
|
@@ -37,7 +38,7 @@ export function renderArea(elements, preparedData, seriesOptions, allowOverlapDa
|
|
|
37
38
|
.attr('stroke-linejoin', 'round')
|
|
38
39
|
.attr('stroke-linecap', 'round');
|
|
39
40
|
const area = areaGenerator()
|
|
40
|
-
.defined((d) => d.y !== null)
|
|
41
|
+
.defined((d) => d.y !== null && !d.hiddenInLine)
|
|
41
42
|
.x((d) => d.x)
|
|
42
43
|
.y0((d) => d.y0)
|
|
43
44
|
.y1((d) => d.y);
|
|
@@ -53,18 +54,11 @@ export function renderArea(elements, preparedData, seriesOptions, allowOverlapDa
|
|
|
53
54
|
if (!allowOverlapDataLabels) {
|
|
54
55
|
dataLabels = filterOverlappingLabels(dataLabels);
|
|
55
56
|
}
|
|
56
|
-
const labelsSelection =
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.attr('class', b('label'))
|
|
62
|
-
.attr('x', (d) => d.x)
|
|
63
|
-
.attr('y', (d) => d.y)
|
|
64
|
-
.attr('text-anchor', (d) => d.textAnchor)
|
|
65
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
66
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
67
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
57
|
+
const labelsSelection = renderDataLabels({
|
|
58
|
+
container: plotSvgElement,
|
|
59
|
+
data: dataLabels,
|
|
60
|
+
className: b('label'),
|
|
61
|
+
});
|
|
68
62
|
const markers = preparedData.reduce((acc, d) => acc.concat(d.markers), []);
|
|
69
63
|
const markerSelection = markersSvgElement
|
|
70
64
|
.selectAll('marker')
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { AreaSeriesData, HtmlItem, LabelData } from '../../../types';
|
|
2
2
|
import type { AnnotationAnchor, PreparedAnnotation, PreparedAreaSeries } from '../../series/types';
|
|
3
3
|
export type PointData = {
|
|
4
|
-
y0: number;
|
|
5
|
-
x: number;
|
|
6
|
-
y: number | null;
|
|
7
|
-
data: AreaSeriesData;
|
|
8
|
-
series: PreparedAreaSeries;
|
|
9
4
|
annotation?: PreparedAnnotation;
|
|
10
5
|
color?: string;
|
|
6
|
+
data: AreaSeriesData;
|
|
7
|
+
hiddenInLine?: boolean;
|
|
8
|
+
series: PreparedAreaSeries;
|
|
9
|
+
x: number;
|
|
10
|
+
y: number | null;
|
|
11
|
+
y0: number;
|
|
11
12
|
};
|
|
12
13
|
export type MarkerPointData = PointData & {
|
|
13
14
|
y: number;
|
|
@@ -4,6 +4,7 @@ import get from 'lodash/get';
|
|
|
4
4
|
import { block } from '../../../utils';
|
|
5
5
|
import { filterOverlappingLabels } from '../../utils';
|
|
6
6
|
import { renderAnnotations } from '../annotation';
|
|
7
|
+
import { renderDataLabels } from '../data-labels';
|
|
7
8
|
import { getRectPath } from '../utils';
|
|
8
9
|
const b = block('bar-x');
|
|
9
10
|
export function renderBarX(elements, preparedData, seriesOptions, allowOverlapDataLabels, dispatcher) {
|
|
@@ -37,18 +38,11 @@ export function renderBarX(elements, preparedData, seriesOptions, allowOverlapDa
|
|
|
37
38
|
if (!allowOverlapDataLabels) {
|
|
38
39
|
dataLabels = filterOverlappingLabels(dataLabels);
|
|
39
40
|
}
|
|
40
|
-
const labelSelection =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
.attr('class', b('label'))
|
|
46
|
-
.attr('x', (d) => d.x)
|
|
47
|
-
.attr('y', (d) => d.y)
|
|
48
|
-
.attr('text-anchor', (d) => d.textAnchor)
|
|
49
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
50
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
51
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
41
|
+
const labelSelection = renderDataLabels({
|
|
42
|
+
container: svgElement,
|
|
43
|
+
data: dataLabels,
|
|
44
|
+
className: b('label'),
|
|
45
|
+
});
|
|
52
46
|
const annotationAnchors = [];
|
|
53
47
|
for (const d of preparedData) {
|
|
54
48
|
if (d.annotation) {
|
|
@@ -2,6 +2,7 @@ import { color } from 'd3-color';
|
|
|
2
2
|
import { select } from 'd3-selection';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../utils';
|
|
5
|
+
import { renderDataLabels } from '../data-labels';
|
|
5
6
|
import { getAdjustedRectBorderPath, getAdjustedRectPath } from './utils';
|
|
6
7
|
const b = block('bar-y');
|
|
7
8
|
export function renderBarY(elements, preparedData, seriesOptions, dispatcher) {
|
|
@@ -31,18 +32,11 @@ export function renderBarY(elements, preparedData, seriesOptions, dispatcher) {
|
|
|
31
32
|
.attr('fill-rule', 'evenodd')
|
|
32
33
|
.attr('opacity', (d) => d.data.opacity || null)
|
|
33
34
|
.attr('pointer-events', 'none');
|
|
34
|
-
const labelSelection =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
.attr('class', b('label'))
|
|
40
|
-
.attr('x', (d) => d.x)
|
|
41
|
-
.attr('y', (d) => d.y)
|
|
42
|
-
.attr('text-anchor', (d) => d.textAnchor)
|
|
43
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
44
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
45
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
35
|
+
const labelSelection = renderDataLabels({
|
|
36
|
+
container: svgElement,
|
|
37
|
+
data: dataLabels,
|
|
38
|
+
className: b('label'),
|
|
39
|
+
});
|
|
46
40
|
const hoverOptions = get(seriesOptions, 'bar-y.states.hover');
|
|
47
41
|
const inactiveOptions = get(seriesOptions, 'bar-y.states.inactive');
|
|
48
42
|
function handleShapeHover(data) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Selection } from 'd3-selection';
|
|
2
|
+
import type { BaseTextStyle } from '../types/chart/base';
|
|
3
|
+
type RenderableLabelData = {
|
|
4
|
+
text: string;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
textAnchor: 'start' | 'end' | 'middle';
|
|
8
|
+
style: BaseTextStyle;
|
|
9
|
+
};
|
|
10
|
+
export declare function renderDataLabels<T extends RenderableLabelData>(args: {
|
|
11
|
+
container: Selection<SVGGElement, unknown, null, undefined>;
|
|
12
|
+
data: T[];
|
|
13
|
+
className: string;
|
|
14
|
+
}): Selection<SVGTextElement, T, SVGGElement, unknown>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function renderDataLabels(args) {
|
|
2
|
+
const { container, data, className } = args;
|
|
3
|
+
return container
|
|
4
|
+
.selectAll('text')
|
|
5
|
+
.data(data)
|
|
6
|
+
.join('text')
|
|
7
|
+
.html((d) => d.text)
|
|
8
|
+
.attr('class', className)
|
|
9
|
+
.attr('x', (d) => d.x)
|
|
10
|
+
.attr('y', (d) => d.y)
|
|
11
|
+
.attr('text-anchor', (d) => d.textAnchor)
|
|
12
|
+
.style('font-size', (d) => d.style.fontSize)
|
|
13
|
+
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
14
|
+
.style('fill', (d) => d.style.fontColor || null);
|
|
15
|
+
}
|
|
@@ -2,6 +2,7 @@ import { color } from 'd3-color';
|
|
|
2
2
|
import { select } from 'd3-selection';
|
|
3
3
|
import { block } from '../../../utils';
|
|
4
4
|
import { getLineDashArray } from '../../utils';
|
|
5
|
+
import { renderDataLabels } from '../data-labels';
|
|
5
6
|
const b = block('funnel');
|
|
6
7
|
export function renderFunnel(elements, preparedData, seriesOptions, dispatcher) {
|
|
7
8
|
var _a, _b;
|
|
@@ -44,17 +45,11 @@ export function renderFunnel(elements, preparedData, seriesOptions, dispatcher)
|
|
|
44
45
|
connectorLines.append('path').attr('d', (d) => d.linePath[0].toString());
|
|
45
46
|
connectorLines.append('path').attr('d', (d) => d.linePath[1].toString());
|
|
46
47
|
// dataLabels
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.attr('class', b('label'))
|
|
53
|
-
.attr('x', (d) => d.x)
|
|
54
|
-
.attr('y', (d) => d.y)
|
|
55
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
56
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
57
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
48
|
+
renderDataLabels({
|
|
49
|
+
container: svgElement,
|
|
50
|
+
data: preparedData.svgLabels,
|
|
51
|
+
className: b('label'),
|
|
52
|
+
});
|
|
58
53
|
function handleShapeHover(data) {
|
|
59
54
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
60
55
|
if (hoverEnabled) {
|
|
@@ -84,6 +84,7 @@ export async function prepareHeatmapData({ series, xAxis, xScale, yAxis, yScale,
|
|
|
84
84
|
x: item.x + item.width / 2 - size.width / 2,
|
|
85
85
|
y: item.y + item.height / 2 - size.height / 2 + size.hangingOffset,
|
|
86
86
|
text,
|
|
87
|
+
textAnchor: 'start',
|
|
87
88
|
style: series.dataLabels.style,
|
|
88
89
|
});
|
|
89
90
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { color } from 'd3-color';
|
|
2
2
|
import { select } from 'd3-selection';
|
|
3
3
|
import { block } from '../../../utils';
|
|
4
|
+
import { renderDataLabels } from '../data-labels';
|
|
4
5
|
const b = block('heatmap');
|
|
5
6
|
export function renderHeatmap(elements, preparedData, seriesOptions, dispatcher) {
|
|
6
7
|
var _a, _b;
|
|
@@ -20,17 +21,11 @@ export function renderHeatmap(elements, preparedData, seriesOptions, dispatcher)
|
|
|
20
21
|
.attr('stroke', (d) => d.borderColor)
|
|
21
22
|
.attr('stroke-width', (d) => d.borderWidth);
|
|
22
23
|
// dataLabels
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
.attr('class', b('label'))
|
|
29
|
-
.attr('x', (d) => d.x)
|
|
30
|
-
.attr('y', (d) => d.y)
|
|
31
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
32
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
33
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
24
|
+
renderDataLabels({
|
|
25
|
+
container: svgElement,
|
|
26
|
+
data: preparedData.labels,
|
|
27
|
+
className: b('label'),
|
|
28
|
+
});
|
|
34
29
|
function handleShapeHover(data) {
|
|
35
30
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
36
31
|
if (hoverEnabled) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { prepareAnnotation } from '../../series/prepare-annotation';
|
|
2
2
|
import { filterOverlappingLabels, getLabelsSize, getTextSizeFn } from '../../utils';
|
|
3
3
|
import { getFormattedValue } from '../../utils/format';
|
|
4
|
-
import { getXValue, getYValue } from '../utils';
|
|
4
|
+
import { getXValue, getYValue, markHiddenPointsOutOfYRange } from '../utils';
|
|
5
5
|
async function getHtmlLabel(point, series, xMax) {
|
|
6
6
|
var _a;
|
|
7
7
|
const content = String((_a = point.data.label) !== null && _a !== void 0 ? _a : point.data.y);
|
|
@@ -129,6 +129,14 @@ export const prepareLineData = async (args) => {
|
|
|
129
129
|
}
|
|
130
130
|
return result;
|
|
131
131
|
}, []);
|
|
132
|
+
markHiddenPointsOutOfYRange({
|
|
133
|
+
points,
|
|
134
|
+
yScale: seriesYScale,
|
|
135
|
+
yAxisTop,
|
|
136
|
+
axisMin: seriesYAxis.min,
|
|
137
|
+
axisMax: seriesYAxis.max,
|
|
138
|
+
getDataY: (p) => p.data.y,
|
|
139
|
+
});
|
|
132
140
|
const result = {
|
|
133
141
|
annotations,
|
|
134
142
|
points,
|
|
@@ -5,6 +5,7 @@ import get from 'lodash/get';
|
|
|
5
5
|
import { block } from '../../../utils';
|
|
6
6
|
import { getLineDashArray } from '../../utils';
|
|
7
7
|
import { renderAnnotations } from '../annotation';
|
|
8
|
+
import { renderDataLabels } from '../data-labels';
|
|
8
9
|
import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../marker';
|
|
9
10
|
import { setActiveState } from '../utils';
|
|
10
11
|
const b = block('line');
|
|
@@ -17,7 +18,7 @@ export function renderLine(elements, preparedData, seriesOptions, dispatcher) {
|
|
|
17
18
|
const hoverOptions = get(seriesOptions, 'line.states.hover');
|
|
18
19
|
const inactiveOptions = get(seriesOptions, 'line.states.inactive');
|
|
19
20
|
const line = lineGenerator()
|
|
20
|
-
.defined((d) => d.y !== null && d.x !== null)
|
|
21
|
+
.defined((d) => d.y !== null && d.x !== null && !d.hiddenInLine)
|
|
21
22
|
.x((d) => d.x)
|
|
22
23
|
.y((d) => d.y);
|
|
23
24
|
plotSvgElement.selectAll('*').remove();
|
|
@@ -38,18 +39,11 @@ export function renderLine(elements, preparedData, seriesOptions, dispatcher) {
|
|
|
38
39
|
const dataLabels = preparedData.reduce((acc, d) => {
|
|
39
40
|
return acc.concat(d.svgLabels);
|
|
40
41
|
}, []);
|
|
41
|
-
const labelsSelection =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.attr('class', b('label'))
|
|
47
|
-
.attr('x', (d) => d.x)
|
|
48
|
-
.attr('y', (d) => d.y)
|
|
49
|
-
.attr('text-anchor', (d) => d.textAnchor)
|
|
50
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
51
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
52
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
42
|
+
const labelsSelection = renderDataLabels({
|
|
43
|
+
container: plotSvgElement,
|
|
44
|
+
data: dataLabels,
|
|
45
|
+
className: b('label'),
|
|
46
|
+
});
|
|
53
47
|
const markers = preparedData.reduce((acc, d) => acc.concat(d.markers), []);
|
|
54
48
|
const markerSelection = markersSvgElement
|
|
55
49
|
.selectAll('marker')
|
|
@@ -2,12 +2,13 @@ import type { HtmlItem, LabelData, LineSeriesData, LineSeriesLineBaseStyle } fro
|
|
|
2
2
|
import type { DashStyle, LineCap, LineJoin } from '../../constants';
|
|
3
3
|
import type { AnnotationAnchor, PreparedAnnotation, PreparedLineSeries } from '../../series/types';
|
|
4
4
|
export type PointData = {
|
|
5
|
-
x: number | null;
|
|
6
|
-
y: number | null;
|
|
7
|
-
data: LineSeriesData;
|
|
8
|
-
series: PreparedLineSeries;
|
|
9
5
|
annotation?: PreparedAnnotation;
|
|
10
6
|
color?: string;
|
|
7
|
+
data: LineSeriesData;
|
|
8
|
+
hiddenInLine?: boolean;
|
|
9
|
+
series: PreparedLineSeries;
|
|
10
|
+
x: number | null;
|
|
11
|
+
y: number | null;
|
|
11
12
|
};
|
|
12
13
|
export type MarkerPointData = PointData & {
|
|
13
14
|
y: number;
|
|
@@ -3,6 +3,7 @@ import { select } from 'd3-selection';
|
|
|
3
3
|
import { line } from 'd3-shape';
|
|
4
4
|
import get from 'lodash/get';
|
|
5
5
|
import { block } from '../../../utils';
|
|
6
|
+
import { renderDataLabels } from '../../shapes/data-labels';
|
|
6
7
|
import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../../shapes/marker';
|
|
7
8
|
import { setActiveState } from '../../shapes/utils';
|
|
8
9
|
const b = block('radar');
|
|
@@ -59,18 +60,13 @@ export function renderRadar(elements, preparedData, seriesOptions, dispatcher) {
|
|
|
59
60
|
.join('g')
|
|
60
61
|
.call(renderMarker);
|
|
61
62
|
// Render labels
|
|
62
|
-
radarSelection
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.attr('y', (d) => d.y)
|
|
70
|
-
.attr('text-anchor', (d) => d.textAnchor)
|
|
71
|
-
.style('font-size', (d) => d.style.fontSize)
|
|
72
|
-
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
73
|
-
.style('fill', (d) => d.style.fontColor || null);
|
|
63
|
+
radarSelection.each(function (radarData) {
|
|
64
|
+
renderDataLabels({
|
|
65
|
+
container: select(this),
|
|
66
|
+
data: radarData.labels,
|
|
67
|
+
className: b('label'),
|
|
68
|
+
});
|
|
69
|
+
});
|
|
74
70
|
// Handle hover events
|
|
75
71
|
const eventName = `hover-shape.radar`;
|
|
76
72
|
const hoverOptions = get(seriesOptions, 'radar.states.hover');
|