@gravity-ui/charts 1.24.2 → 1.26.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/useChartInnerProps.d.ts +3 -3
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +34 -16
- package/dist/cjs/components/Legend/index.js +50 -28
- package/dist/cjs/hooks/useAxis/index.js +0 -1
- package/dist/cjs/hooks/useAxis/x-axis.d.ts +1 -3
- package/dist/cjs/hooks/useAxis/x-axis.js +3 -4
- package/dist/cjs/hooks/useAxisScales/index.d.ts +1 -3
- package/dist/cjs/hooks/useAxisScales/index.js +6 -35
- package/dist/cjs/hooks/useChartDimensions/index.js +16 -1
- package/dist/cjs/hooks/useRangeSlider/index.js +0 -1
- package/dist/cjs/hooks/useSeries/index.js +8 -8
- package/dist/cjs/hooks/useSeries/prepare-area.js +7 -5
- package/dist/cjs/hooks/useSeries/prepare-bar-x.js +8 -6
- package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +2 -0
- package/dist/cjs/hooks/useSeries/prepare-bar-y.js +7 -5
- package/dist/cjs/hooks/useSeries/prepare-funnel.js +14 -10
- package/dist/cjs/hooks/useSeries/prepare-heatmap.js +9 -7
- package/dist/cjs/hooks/useSeries/prepare-legend.js +75 -15
- package/dist/cjs/hooks/useSeries/prepare-line.js +6 -4
- package/dist/cjs/hooks/useSeries/prepare-pie.js +10 -6
- package/dist/cjs/hooks/useSeries/prepare-radar.js +7 -5
- package/dist/cjs/hooks/useSeries/prepare-sankey.js +3 -1
- package/dist/cjs/hooks/useSeries/prepare-scatter.js +4 -1
- package/dist/cjs/hooks/useSeries/prepare-treemap.js +4 -2
- package/dist/cjs/hooks/useSeries/prepare-waterfall.js +13 -8
- package/dist/cjs/hooks/useSeries/types.d.ts +5 -0
- package/dist/cjs/hooks/useSeries/utils.d.ts +7 -3
- package/dist/cjs/hooks/useSeries/utils.js +2 -2
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +3 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +24 -46
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +0 -3
- package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +4 -1
- package/dist/cjs/hooks/utils/bar-x.d.ts +3 -2
- package/dist/cjs/hooks/utils/bar-x.js +8 -6
- package/dist/cjs/hooks/utils/bar-y.d.ts +0 -1
- package/dist/cjs/hooks/utils/bar-y.js +3 -3
- package/dist/cjs/types/chart/area.d.ts +3 -3
- package/dist/cjs/types/chart/axis.d.ts +1 -0
- package/dist/cjs/types/chart/bar-x.d.ts +3 -3
- package/dist/cjs/types/chart/bar-y.d.ts +3 -3
- package/dist/cjs/types/chart/base.d.ts +9 -0
- package/dist/cjs/types/chart/funnel.d.ts +10 -6
- package/dist/cjs/types/chart/heatmap.d.ts +3 -3
- package/dist/cjs/types/chart/legend.d.ts +12 -10
- package/dist/cjs/types/chart/line.d.ts +3 -3
- package/dist/cjs/types/chart/pie.d.ts +10 -6
- package/dist/cjs/types/chart/radar.d.ts +3 -3
- package/dist/cjs/types/chart/sankey.d.ts +3 -3
- package/dist/cjs/types/chart/scatter.d.ts +3 -3
- package/dist/cjs/types/chart/treemap.d.ts +3 -3
- package/dist/cjs/types/chart/waterfall.d.ts +2 -2
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -3
- package/dist/esm/components/ChartInner/useChartInnerProps.js +34 -16
- package/dist/esm/components/Legend/index.js +50 -28
- package/dist/esm/hooks/useAxis/index.js +0 -1
- package/dist/esm/hooks/useAxis/x-axis.d.ts +1 -3
- package/dist/esm/hooks/useAxis/x-axis.js +3 -4
- package/dist/esm/hooks/useAxisScales/index.d.ts +1 -3
- package/dist/esm/hooks/useAxisScales/index.js +6 -35
- package/dist/esm/hooks/useChartDimensions/index.js +16 -1
- package/dist/esm/hooks/useRangeSlider/index.js +0 -1
- package/dist/esm/hooks/useSeries/index.js +8 -8
- package/dist/esm/hooks/useSeries/prepare-area.js +7 -5
- package/dist/esm/hooks/useSeries/prepare-bar-x.js +8 -6
- package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +2 -0
- package/dist/esm/hooks/useSeries/prepare-bar-y.js +7 -5
- package/dist/esm/hooks/useSeries/prepare-funnel.js +14 -10
- package/dist/esm/hooks/useSeries/prepare-heatmap.js +9 -7
- package/dist/esm/hooks/useSeries/prepare-legend.js +75 -15
- package/dist/esm/hooks/useSeries/prepare-line.js +6 -4
- package/dist/esm/hooks/useSeries/prepare-pie.js +10 -6
- package/dist/esm/hooks/useSeries/prepare-radar.js +7 -5
- package/dist/esm/hooks/useSeries/prepare-sankey.js +3 -1
- package/dist/esm/hooks/useSeries/prepare-scatter.js +4 -1
- package/dist/esm/hooks/useSeries/prepare-treemap.js +4 -2
- package/dist/esm/hooks/useSeries/prepare-waterfall.js +13 -8
- package/dist/esm/hooks/useSeries/types.d.ts +5 -0
- package/dist/esm/hooks/useSeries/utils.d.ts +7 -3
- package/dist/esm/hooks/useSeries/utils.js +2 -2
- package/dist/esm/hooks/useShapes/area/prepare-data.js +3 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +24 -46
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +0 -3
- package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +4 -1
- package/dist/esm/hooks/utils/bar-x.d.ts +3 -2
- package/dist/esm/hooks/utils/bar-x.js +8 -6
- package/dist/esm/hooks/utils/bar-y.d.ts +0 -1
- package/dist/esm/hooks/utils/bar-y.js +3 -3
- package/dist/esm/types/chart/area.d.ts +3 -3
- package/dist/esm/types/chart/axis.d.ts +1 -0
- package/dist/esm/types/chart/bar-x.d.ts +3 -3
- package/dist/esm/types/chart/bar-y.d.ts +3 -3
- package/dist/esm/types/chart/base.d.ts +9 -0
- package/dist/esm/types/chart/funnel.d.ts +10 -6
- package/dist/esm/types/chart/heatmap.d.ts +3 -3
- package/dist/esm/types/chart/legend.d.ts +12 -10
- package/dist/esm/types/chart/line.d.ts +3 -3
- package/dist/esm/types/chart/pie.d.ts +10 -6
- package/dist/esm/types/chart/radar.d.ts +3 -3
- package/dist/esm/types/chart/sankey.d.ts +3 -3
- package/dist/esm/types/chart/scatter.d.ts +3 -3
- package/dist/esm/types/chart/treemap.d.ts +3 -3
- package/dist/esm/types/chart/waterfall.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Dispatch } from 'd3';
|
|
3
|
-
import type { RangeSliderState, ZoomState } from '../../hooks';
|
|
3
|
+
import type { PreparedLegend, RangeSliderState, ZoomState } from '../../hooks';
|
|
4
4
|
import type { ChartInnerProps } from './types';
|
|
5
5
|
type Props = ChartInnerProps & {
|
|
6
6
|
clipPathId: string;
|
|
@@ -35,7 +35,7 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
35
35
|
} | undefined;
|
|
36
36
|
legendItems: never[] | import("../../hooks").LegendItem[][];
|
|
37
37
|
preparedChart: import("../../hooks").PreparedChart;
|
|
38
|
-
preparedLegend:
|
|
38
|
+
preparedLegend: PreparedLegend | null;
|
|
39
39
|
preparedSeries: import("../../hooks").PreparedSeries[];
|
|
40
40
|
preparedSeriesOptions: import("../../constants").SeriesOptionsDefaults;
|
|
41
41
|
preparedSplit: import("../../hooks").PreparedSplit;
|
|
@@ -52,7 +52,7 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
52
52
|
xScale: import("../../hooks").ChartScale | undefined;
|
|
53
53
|
yAxis: (Omit<import("../..").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
|
|
54
54
|
type: import("../..").ChartAxisType;
|
|
55
|
-
labels: Omit<import("../..").ChartAxisLabels, "enabled" | "style" | "padding" | "autoRotation"> & Required<Pick<import("../..").ChartAxisLabels, "
|
|
55
|
+
labels: Omit<import("../..").ChartAxisLabels, "enabled" | "style" | "padding" | "autoRotation"> & Required<Pick<import("../..").ChartAxisLabels, "margin" | "html" | "enabled" | "padding" | "rotation">> & {
|
|
56
56
|
style: import("../..").BaseTextStyle;
|
|
57
57
|
rotation: number;
|
|
58
58
|
height: number;
|
|
@@ -9,6 +9,30 @@ import { hasAtLeastOneSeriesDataPerPlot } from './utils';
|
|
|
9
9
|
const CLIP_PATH_BY_SERIES_TYPE = {
|
|
10
10
|
[SERIES_TYPE.Scatter]: false,
|
|
11
11
|
};
|
|
12
|
+
function getBoundsOffsetTop(args) {
|
|
13
|
+
const { chartMarginTop, preparedLegend } = args;
|
|
14
|
+
return (chartMarginTop +
|
|
15
|
+
((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'top'
|
|
16
|
+
? preparedLegend.height + preparedLegend.margin
|
|
17
|
+
: 0));
|
|
18
|
+
}
|
|
19
|
+
function getBoundsOffsetLeft(args) {
|
|
20
|
+
const { chartMarginLeft, preparedLegend, yAxis, getYAxisWidth: getAxisWidth } = args;
|
|
21
|
+
const legendOffset = (preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'left'
|
|
22
|
+
? preparedLegend.width + preparedLegend.margin
|
|
23
|
+
: 0;
|
|
24
|
+
const leftAxisWidth = yAxis.reduce((acc, axis) => {
|
|
25
|
+
if (axis.position !== 'left') {
|
|
26
|
+
return acc;
|
|
27
|
+
}
|
|
28
|
+
const axisWidth = getAxisWidth(axis);
|
|
29
|
+
if (acc < axisWidth) {
|
|
30
|
+
acc = axisWidth;
|
|
31
|
+
}
|
|
32
|
+
return acc;
|
|
33
|
+
}, 0);
|
|
34
|
+
return chartMarginLeft + legendOffset + leftAxisWidth;
|
|
35
|
+
}
|
|
12
36
|
export function useChartInnerProps(props) {
|
|
13
37
|
var _a;
|
|
14
38
|
const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, rangeSliderState, svgContainer, width, updateZoomState, zoomState, } = props;
|
|
@@ -81,7 +105,6 @@ export function useChartInnerProps(props) {
|
|
|
81
105
|
boundsHeight,
|
|
82
106
|
rangeSliderState,
|
|
83
107
|
series: preparedSeries,
|
|
84
|
-
seriesOptions: preparedSeriesOptions,
|
|
85
108
|
split: preparedSplit,
|
|
86
109
|
xAxis,
|
|
87
110
|
yAxis,
|
|
@@ -130,22 +153,17 @@ export function useChartInnerProps(props) {
|
|
|
130
153
|
yAxis,
|
|
131
154
|
yScale,
|
|
132
155
|
});
|
|
133
|
-
const boundsOffsetTop =
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
156
|
+
const boundsOffsetTop = getBoundsOffsetTop({
|
|
157
|
+
chartMarginTop: chart.margin.top,
|
|
158
|
+
preparedLegend,
|
|
159
|
+
});
|
|
137
160
|
// We need to calculate the width of each left axis because the first axis can be hidden
|
|
138
|
-
const boundsOffsetLeft =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (acc < axisWidth) {
|
|
145
|
-
acc = axisWidth;
|
|
146
|
-
}
|
|
147
|
-
return acc;
|
|
148
|
-
}, 0);
|
|
161
|
+
const boundsOffsetLeft = getBoundsOffsetLeft({
|
|
162
|
+
chartMarginLeft: chart.margin.left,
|
|
163
|
+
preparedLegend,
|
|
164
|
+
yAxis,
|
|
165
|
+
getYAxisWidth,
|
|
166
|
+
});
|
|
149
167
|
const { x } = (_a = svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) !== null && _a !== void 0 ? _a : {};
|
|
150
168
|
return {
|
|
151
169
|
allPreparedSeries,
|
|
@@ -6,16 +6,21 @@ import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getLineD
|
|
|
6
6
|
import { axisBottom } from '../../utils/chart/axis-generators';
|
|
7
7
|
import './styles.css';
|
|
8
8
|
const b = block('legend');
|
|
9
|
-
const
|
|
10
|
-
const { align,
|
|
11
|
-
const top = 0;
|
|
12
|
-
if (align === 'left') {
|
|
13
|
-
return { top, left: offsetLeft };
|
|
14
|
-
}
|
|
9
|
+
const getLegendItemPosition = (args) => {
|
|
10
|
+
const { align, width, contentWidth } = args;
|
|
15
11
|
if (align === 'right') {
|
|
16
|
-
return {
|
|
12
|
+
return { left: width - contentWidth };
|
|
13
|
+
}
|
|
14
|
+
else if (align === 'left') {
|
|
15
|
+
return { left: 0 };
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return { left: width / 2 - contentWidth / 2 };
|
|
17
19
|
}
|
|
18
|
-
|
|
20
|
+
};
|
|
21
|
+
const getLegendPosition = (args) => {
|
|
22
|
+
const { offsetLeft, offsetTop, contentWidth, width } = args;
|
|
23
|
+
return { top: offsetTop, left: offsetLeft + width / 2 - contentWidth / 2 };
|
|
19
24
|
};
|
|
20
25
|
const appendPaginator = (args) => {
|
|
21
26
|
const { container, pageIndex, legend, transform, pages, onArrowClick } = args;
|
|
@@ -115,7 +120,6 @@ function renderLegendSymbol(args) {
|
|
|
115
120
|
}
|
|
116
121
|
case 'symbol': {
|
|
117
122
|
const y = legendLineHeight / 2;
|
|
118
|
-
const translateX = x + d.symbol.width / 2;
|
|
119
123
|
element
|
|
120
124
|
.append('svg:path')
|
|
121
125
|
.attr('d', () => {
|
|
@@ -124,7 +128,9 @@ function renderLegendSymbol(args) {
|
|
|
124
128
|
// https://d3js.org/d3-shape/symbol#symbol
|
|
125
129
|
return symbol(scatterSymbol, d.symbol.width * d.symbol.width)();
|
|
126
130
|
})
|
|
127
|
-
.attr('transform', () => {
|
|
131
|
+
.attr('transform', (_d, _index, elements) => {
|
|
132
|
+
var _a, _b;
|
|
133
|
+
const translateX = x + ((_b = (_a = elements[0]) === null || _a === void 0 ? void 0 : _a.getBBox()) === null || _b === void 0 ? void 0 : _b.width) / 2;
|
|
128
134
|
return 'translate(' + translateX + ',' + y + ')';
|
|
129
135
|
})
|
|
130
136
|
.attr('class', className)
|
|
@@ -143,7 +149,7 @@ export const Legend = (props) => {
|
|
|
143
149
|
}, [config.maxWidth]);
|
|
144
150
|
React.useEffect(() => {
|
|
145
151
|
async function prepareLegend() {
|
|
146
|
-
var _a, _b, _c,
|
|
152
|
+
var _a, _b, _c, _e, _f, _g, _h, _j;
|
|
147
153
|
if (!ref.current || !htmlLayout) {
|
|
148
154
|
return;
|
|
149
155
|
}
|
|
@@ -156,9 +162,11 @@ export const Legend = (props) => {
|
|
|
156
162
|
? htmlElement.append('div').attr('data-legend', 1).style('position', 'absolute')
|
|
157
163
|
: null;
|
|
158
164
|
let legendWidth = 0;
|
|
165
|
+
let legendLeft = 0;
|
|
166
|
+
let legendTop = 0;
|
|
159
167
|
if (legend.type === 'discrete') {
|
|
160
168
|
const start = (_b = (_a = config.pagination) === null || _a === void 0 ? void 0 : _a.pages[pageIndex]) === null || _b === void 0 ? void 0 : _b.start;
|
|
161
|
-
const end = (
|
|
169
|
+
const end = (_e = (_c = config.pagination) === null || _c === void 0 ? void 0 : _c.pages[pageIndex]) === null || _e === void 0 ? void 0 : _e.end;
|
|
162
170
|
const pageItems = typeof start === 'number' && typeof end === 'number'
|
|
163
171
|
? items.slice(start, end)
|
|
164
172
|
: items;
|
|
@@ -174,7 +182,7 @@ export const Legend = (props) => {
|
|
|
174
182
|
.append('g')
|
|
175
183
|
.attr('class', b('item'))
|
|
176
184
|
.on('click', function (e, d) {
|
|
177
|
-
onItemClick({ name: d.name, metaKey: e.metaKey });
|
|
185
|
+
onItemClick({ id: d.id, name: d.name, metaKey: e.metaKey });
|
|
178
186
|
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate();
|
|
179
187
|
});
|
|
180
188
|
const getXPosition = (i) => {
|
|
@@ -213,7 +221,7 @@ export const Legend = (props) => {
|
|
|
213
221
|
return '0px';
|
|
214
222
|
})
|
|
215
223
|
.on('click', function (e, d) {
|
|
216
|
-
onItemClick({ name: d.name, metaKey: e.metaKey });
|
|
224
|
+
onItemClick({ id: d.id, name: d.name, metaKey: e.metaKey });
|
|
217
225
|
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate();
|
|
218
226
|
})[legend.html ? 'html' : 'text'](function (d) {
|
|
219
227
|
return d.name;
|
|
@@ -248,11 +256,10 @@ export const Legend = (props) => {
|
|
|
248
256
|
let left = 0;
|
|
249
257
|
switch (legend.justifyContent) {
|
|
250
258
|
case 'center': {
|
|
251
|
-
const legendLinePostion =
|
|
259
|
+
const legendLinePostion = getLegendItemPosition({
|
|
252
260
|
align: legend.align,
|
|
253
261
|
width: config.maxWidth,
|
|
254
262
|
contentWidth,
|
|
255
|
-
offsetLeft: config.offset.left,
|
|
256
263
|
});
|
|
257
264
|
left = legendLinePostion.left;
|
|
258
265
|
legendWidth = config.maxWidth;
|
|
@@ -279,10 +286,31 @@ export const Legend = (props) => {
|
|
|
279
286
|
onArrowClick: setPageIndex,
|
|
280
287
|
});
|
|
281
288
|
}
|
|
289
|
+
const { left, top } = getLegendPosition({
|
|
290
|
+
width: config.maxWidth,
|
|
291
|
+
contentWidth: legendWidth,
|
|
292
|
+
offsetLeft: config.offset.left,
|
|
293
|
+
offsetTop: config.offset.top,
|
|
294
|
+
});
|
|
295
|
+
legendLeft = left;
|
|
296
|
+
legendTop = top;
|
|
282
297
|
}
|
|
283
298
|
else {
|
|
299
|
+
const { left } = getLegendItemPosition({
|
|
300
|
+
align: legend.align,
|
|
301
|
+
width: config.maxWidth,
|
|
302
|
+
contentWidth: legend.width,
|
|
303
|
+
});
|
|
304
|
+
const { top } = getLegendPosition({
|
|
305
|
+
width: config.maxWidth,
|
|
306
|
+
contentWidth: legendWidth,
|
|
307
|
+
offsetLeft: config.offset.left,
|
|
308
|
+
offsetTop: config.offset.top,
|
|
309
|
+
});
|
|
310
|
+
legendLeft = left;
|
|
311
|
+
legendTop = top;
|
|
284
312
|
// gradient rect
|
|
285
|
-
const domain = (
|
|
313
|
+
const domain = (_f = legend.colorScale.domain) !== null && _f !== void 0 ? _f : [];
|
|
286
314
|
const rectHeight = CONTINUOUS_LEGEND_SIZE.height;
|
|
287
315
|
svgElement.call(createGradientRect, {
|
|
288
316
|
y: legend.title.height + legend.title.margin,
|
|
@@ -351,25 +379,19 @@ export const Legend = (props) => {
|
|
|
351
379
|
.attr('class', legendTitleClassname)
|
|
352
380
|
.append('text')
|
|
353
381
|
.attr('dx', dx)
|
|
354
|
-
.attr('font-weight', (
|
|
355
|
-
.attr('font-size', (
|
|
356
|
-
.attr('fill', (
|
|
382
|
+
.attr('font-weight', (_g = legend.title.style.fontWeight) !== null && _g !== void 0 ? _g : null)
|
|
383
|
+
.attr('font-size', (_h = legend.title.style.fontSize) !== null && _h !== void 0 ? _h : null)
|
|
384
|
+
.attr('fill', (_j = legend.title.style.fontColor) !== null && _j !== void 0 ? _j : null)
|
|
357
385
|
.style('dominant-baseline', 'text-before-edge')
|
|
358
386
|
.html(legend.title.text);
|
|
359
387
|
}
|
|
360
388
|
else {
|
|
361
389
|
svgElement.selectAll(`.${legendTitleClassname}`).remove();
|
|
362
390
|
}
|
|
363
|
-
const { left } = getLegendPosition({
|
|
364
|
-
align: legend.align,
|
|
365
|
-
width: config.maxWidth,
|
|
366
|
-
contentWidth: legendWidth,
|
|
367
|
-
offsetLeft: config.offset.left,
|
|
368
|
-
});
|
|
369
391
|
svgElement
|
|
370
|
-
.attr('transform', `translate(${[
|
|
392
|
+
.attr('transform', `translate(${[legendLeft, legendTop].join(',')})`)
|
|
371
393
|
.style('opacity', 1);
|
|
372
|
-
htmlContainer === null || htmlContainer === void 0 ? void 0 : htmlContainer.style('transform', `translate(${
|
|
394
|
+
htmlContainer === null || htmlContainer === void 0 ? void 0 : htmlContainer.style('transform', `translate(${legendLeft}px, ${legendTop}px)`);
|
|
373
395
|
}
|
|
374
396
|
prepareLegend();
|
|
375
397
|
}, [chartSeries, onItemClick, onUpdate, legend, items, config, pageIndex, htmlLayout]);
|
|
@@ -18,7 +18,6 @@ export function useAxis(props) {
|
|
|
18
18
|
xAxis,
|
|
19
19
|
width,
|
|
20
20
|
seriesData,
|
|
21
|
-
seriesOptions: preparedSeriesOptions,
|
|
22
21
|
});
|
|
23
22
|
let estimatedBoundsHeight = boundsHeight !== null && boundsHeight !== void 0 ? boundsHeight : height;
|
|
24
23
|
if (preparedXAxis && typeof boundsHeight !== 'number') {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { ChartSeries, ChartXAxis } from '../../types';
|
|
2
|
-
import type { PreparedSeriesOptions } from '../useSeries/types';
|
|
3
2
|
import type { PreparedXAxis } from './types';
|
|
4
|
-
export declare const getPreparedXAxis: ({ xAxis, seriesData,
|
|
3
|
+
export declare const getPreparedXAxis: ({ xAxis, seriesData, width, }: {
|
|
5
4
|
xAxis?: ChartXAxis;
|
|
6
5
|
seriesData: ChartSeries[];
|
|
7
|
-
seriesOptions: PreparedSeriesOptions;
|
|
8
6
|
width: number;
|
|
9
7
|
}) => Promise<PreparedXAxis | null>;
|
|
@@ -4,8 +4,8 @@ import { calculateCos, calculateNumericProperty, formatAxisTickLabel, getAxisIte
|
|
|
4
4
|
import { createXScale } from '../useAxisScales';
|
|
5
5
|
import { getPreparedRangeSlider } from './range-slider';
|
|
6
6
|
import { prepareAxisPlotLabel } from './utils';
|
|
7
|
-
async function setLabelSettings({ axis, seriesData,
|
|
8
|
-
const scale = createXScale({ axis, series: seriesData,
|
|
7
|
+
async function setLabelSettings({ axis, seriesData, width, autoRotation = true, }) {
|
|
8
|
+
const scale = createXScale({ axis, series: seriesData, boundsWidth: width });
|
|
9
9
|
if (!scale) {
|
|
10
10
|
axis.labels.height = 0;
|
|
11
11
|
axis.labels.rotation = 0;
|
|
@@ -56,7 +56,7 @@ function getMaxPaddingBySeries({ series }) {
|
|
|
56
56
|
}
|
|
57
57
|
return 0.01;
|
|
58
58
|
}
|
|
59
|
-
export const getPreparedXAxis = async ({ xAxis, seriesData,
|
|
59
|
+
export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
|
|
60
60
|
var _a, _b, _c, _d, _e;
|
|
61
61
|
const hasAxisRelatedSeries = seriesData.some(isAxisRelatedSeries);
|
|
62
62
|
if (!hasAxisRelatedSeries) {
|
|
@@ -159,7 +159,6 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width
|
|
|
159
159
|
await setLabelSettings({
|
|
160
160
|
axis: preparedXAxis,
|
|
161
161
|
seriesData,
|
|
162
|
-
seriesOptions,
|
|
163
162
|
width,
|
|
164
163
|
autoRotation: (_e = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _e === void 0 ? void 0 : _e.autoRotation,
|
|
165
164
|
});
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
|
-
import type { PreparedAxis, PreparedSeries,
|
|
2
|
+
import type { PreparedAxis, PreparedSeries, PreparedSplit, RangeSliderState, ZoomState } from '../../hooks';
|
|
3
3
|
import type { ChartAxis, ChartSeries } from '../../types';
|
|
4
4
|
export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
|
|
5
5
|
type Args = {
|
|
6
6
|
boundsWidth: number;
|
|
7
7
|
boundsHeight: number;
|
|
8
8
|
series: PreparedSeries[];
|
|
9
|
-
seriesOptions: PreparedSeriesOptions;
|
|
10
9
|
xAxis: PreparedAxis | null;
|
|
11
10
|
yAxis: PreparedAxis[];
|
|
12
11
|
split: PreparedSplit;
|
|
@@ -27,7 +26,6 @@ export declare function createXScale(args: {
|
|
|
27
26
|
axis: PreparedAxis | ChartAxis;
|
|
28
27
|
boundsWidth: number;
|
|
29
28
|
series: (PreparedSeries | ChartSeries)[];
|
|
30
|
-
seriesOptions: PreparedSeriesOptions;
|
|
31
29
|
rangeSliderState?: RangeSliderState;
|
|
32
30
|
zoomStateX?: [number, number];
|
|
33
31
|
}): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never> | undefined;
|
|
@@ -3,7 +3,6 @@ import { extent, scaleBand, scaleLinear, scaleLog, scaleUtc } from 'd3';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { DEFAULT_AXIS_TYPE, SERIES_TYPE } from '../../constants';
|
|
5
5
|
import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, getAxisCategories, getAxisHeight, getDataCategoryValue, getDefaultMaxXAxisValue, getDefaultMinXAxisValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
|
|
6
|
-
import { getBarXLayoutForNumericScale, groupBarXDataByXValue } from '../utils/bar-x';
|
|
7
6
|
import { getBandSize } from '../utils/get-band-size';
|
|
8
7
|
import { checkIsPointDomain, getMinMaxPropsOrState, hasOnlyMarkerSeries } from './utils';
|
|
9
8
|
const X_AXIS_ZOOM_PADDING = 0.02;
|
|
@@ -214,32 +213,19 @@ function calculateXAxisPadding(series) {
|
|
|
214
213
|
return result;
|
|
215
214
|
}
|
|
216
215
|
function isSeriesWithXAxisOffset(series) {
|
|
217
|
-
const types = [SERIES_TYPE.Heatmap];
|
|
216
|
+
const types = [SERIES_TYPE.Heatmap, SERIES_TYPE.BarX];
|
|
218
217
|
return series.some((s) => types.includes(s.type));
|
|
219
218
|
}
|
|
220
|
-
function getXScaleRange({ boundsWidth,
|
|
219
|
+
function getXScaleRange({ boundsWidth, hasZoomX }) {
|
|
221
220
|
const xAxisZoomPadding = boundsWidth * X_AXIS_ZOOM_PADDING;
|
|
222
221
|
const xRange = [0, boundsWidth];
|
|
223
222
|
const xRangeZoom = [0 + xAxisZoomPadding, boundsWidth - xAxisZoomPadding];
|
|
224
223
|
const range = hasZoomX ? xRangeZoom : xRange;
|
|
225
|
-
const barXSeries = series.filter((s) => s.type === SERIES_TYPE.BarX);
|
|
226
|
-
if (barXSeries.length) {
|
|
227
|
-
const groupedData = groupBarXDataByXValue(barXSeries, axis);
|
|
228
|
-
if (Object.keys(groupedData).length > 1) {
|
|
229
|
-
const { bandSize } = getBarXLayoutForNumericScale({
|
|
230
|
-
plotWidth: boundsWidth,
|
|
231
|
-
groupedData,
|
|
232
|
-
seriesOptions,
|
|
233
|
-
});
|
|
234
|
-
const offset = bandSize / 2;
|
|
235
|
-
return [range[0] + offset, range[1] - offset];
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
224
|
return range;
|
|
239
225
|
}
|
|
240
226
|
// eslint-disable-next-line complexity
|
|
241
227
|
export function createXScale(args) {
|
|
242
|
-
const { axis, boundsWidth, series,
|
|
228
|
+
const { axis, boundsWidth, series, rangeSliderState, zoomStateX } = args;
|
|
243
229
|
const [xMinPropsOrState, xMaxPropsOrState] = getMinMaxPropsOrState({
|
|
244
230
|
axis,
|
|
245
231
|
maxValues: [zoomStateX === null || zoomStateX === void 0 ? void 0 : zoomStateX[1], rangeSliderState === null || rangeSliderState === void 0 ? void 0 : rangeSliderState.max],
|
|
@@ -260,10 +246,7 @@ export function createXScale(args) {
|
|
|
260
246
|
const xAxisMaxPadding = boundsWidth * maxPadding + calculateXAxisPadding(series);
|
|
261
247
|
const range = getXScaleRange({
|
|
262
248
|
boundsWidth,
|
|
263
|
-
series,
|
|
264
|
-
seriesOptions,
|
|
265
249
|
hasZoomX,
|
|
266
|
-
axis,
|
|
267
250
|
});
|
|
268
251
|
switch (axis.order) {
|
|
269
252
|
case 'sortDesc':
|
|
@@ -407,7 +390,7 @@ export function createXScale(args) {
|
|
|
407
390
|
throw new Error('Failed to create xScale');
|
|
408
391
|
}
|
|
409
392
|
const createScales = (args) => {
|
|
410
|
-
const { boundsWidth, boundsHeight, rangeSliderState, series,
|
|
393
|
+
const { boundsWidth, boundsHeight, rangeSliderState, series, split, xAxis, yAxis, zoomState } = args;
|
|
411
394
|
let visibleSeries = getOnlyVisibleSeries(series);
|
|
412
395
|
// Reassign to all series in case of all series unselected,
|
|
413
396
|
// otherwise we will get an empty space without grid
|
|
@@ -419,7 +402,6 @@ const createScales = (args) => {
|
|
|
419
402
|
boundsWidth,
|
|
420
403
|
rangeSliderState,
|
|
421
404
|
series: visibleSeries,
|
|
422
|
-
seriesOptions,
|
|
423
405
|
zoomStateX: zoomState === null || zoomState === void 0 ? void 0 : zoomState.x,
|
|
424
406
|
})
|
|
425
407
|
: undefined,
|
|
@@ -445,7 +427,7 @@ const createScales = (args) => {
|
|
|
445
427
|
* Uses to create scales for axis related series
|
|
446
428
|
*/
|
|
447
429
|
export const useAxisScales = (args) => {
|
|
448
|
-
const { boundsWidth, boundsHeight, rangeSliderState, series,
|
|
430
|
+
const { boundsWidth, boundsHeight, rangeSliderState, series, split, xAxis, yAxis, zoomState } = args;
|
|
449
431
|
return React.useMemo(() => {
|
|
450
432
|
let xScale;
|
|
451
433
|
let yScale;
|
|
@@ -456,7 +438,6 @@ export const useAxisScales = (args) => {
|
|
|
456
438
|
boundsHeight,
|
|
457
439
|
rangeSliderState,
|
|
458
440
|
series,
|
|
459
|
-
seriesOptions,
|
|
460
441
|
split,
|
|
461
442
|
xAxis,
|
|
462
443
|
yAxis,
|
|
@@ -464,15 +445,5 @@ export const useAxisScales = (args) => {
|
|
|
464
445
|
}));
|
|
465
446
|
}
|
|
466
447
|
return { xScale, yScale };
|
|
467
|
-
}, [
|
|
468
|
-
boundsWidth,
|
|
469
|
-
boundsHeight,
|
|
470
|
-
rangeSliderState,
|
|
471
|
-
series,
|
|
472
|
-
seriesOptions,
|
|
473
|
-
split,
|
|
474
|
-
xAxis,
|
|
475
|
-
yAxis,
|
|
476
|
-
zoomState,
|
|
477
|
-
]);
|
|
448
|
+
}, [boundsWidth, boundsHeight, rangeSliderState, series, split, xAxis, yAxis, zoomState]);
|
|
478
449
|
};
|
|
@@ -30,6 +30,18 @@ const getTopOffset = ({ preparedLegend }) => {
|
|
|
30
30
|
}
|
|
31
31
|
return 0;
|
|
32
32
|
};
|
|
33
|
+
const getRightOffset = ({ preparedLegend }) => {
|
|
34
|
+
if ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'right') {
|
|
35
|
+
return preparedLegend.width + preparedLegend.margin;
|
|
36
|
+
}
|
|
37
|
+
return 0;
|
|
38
|
+
};
|
|
39
|
+
const getLeftOffset = ({ preparedLegend }) => {
|
|
40
|
+
if ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'left') {
|
|
41
|
+
return preparedLegend.width + preparedLegend.margin;
|
|
42
|
+
}
|
|
43
|
+
return 0;
|
|
44
|
+
};
|
|
33
45
|
export const useChartDimensions = (args) => {
|
|
34
46
|
const { height, margin, preparedLegend, preparedSeries, preparedXAxis, preparedYAxis, width } = args;
|
|
35
47
|
return React.useMemo(() => {
|
|
@@ -41,7 +53,10 @@ export const useChartDimensions = (args) => {
|
|
|
41
53
|
preparedXAxis,
|
|
42
54
|
});
|
|
43
55
|
const topOffset = getTopOffset({ preparedLegend });
|
|
56
|
+
const rightOffset = getRightOffset({ preparedLegend });
|
|
57
|
+
const leftOffset = getLeftOffset({ preparedLegend });
|
|
44
58
|
const boundsHeight = height - margin.top - margin.bottom - bottomOffset - topOffset;
|
|
45
|
-
|
|
59
|
+
const adjustedBoundsWidth = boundsWidth - rightOffset - leftOffset;
|
|
60
|
+
return { boundsWidth: adjustedBoundsWidth, boundsHeight };
|
|
46
61
|
}, [height, margin, preparedLegend, preparedSeries, preparedXAxis, preparedYAxis, width]);
|
|
47
62
|
};
|
|
@@ -9,7 +9,7 @@ const useVisibleSeries = ({ preparedSeries, activeLegendItems, }) => {
|
|
|
9
9
|
return React.useMemo(() => {
|
|
10
10
|
return preparedSeries.map((singleSeries) => {
|
|
11
11
|
if (singleSeries.legend.enabled) {
|
|
12
|
-
return Object.assign(Object.assign({}, singleSeries), { visible: activeLegendItems.includes(singleSeries.
|
|
12
|
+
return Object.assign(Object.assign({}, singleSeries), { visible: activeLegendItems.includes(singleSeries.legend.groupId) });
|
|
13
13
|
}
|
|
14
14
|
return singleSeries;
|
|
15
15
|
});
|
|
@@ -61,15 +61,15 @@ export const useSeries = (args) => {
|
|
|
61
61
|
}, [seriesData, seriesOptions, preparedLegend, colors]);
|
|
62
62
|
const prevOriginalSeriesData = usePrevious(originalSeriesData);
|
|
63
63
|
const chartSeries = useVisibleSeries({ preparedSeries, activeLegendItems });
|
|
64
|
-
const handleLegendItemClick = React.useCallback(({
|
|
64
|
+
const handleLegendItemClick = React.useCallback(({ id, metaKey }) => {
|
|
65
65
|
const allItems = getAllLegendItems(preparedSeries);
|
|
66
|
-
const onlyItemSelected = activeLegendItems.length === 1 && activeLegendItems.includes(
|
|
66
|
+
const onlyItemSelected = activeLegendItems.length === 1 && activeLegendItems.includes(id);
|
|
67
67
|
let nextActiveLegendItems;
|
|
68
|
-
if (metaKey && activeLegendItems.includes(
|
|
69
|
-
nextActiveLegendItems = activeLegendItems.filter((item) => item !==
|
|
68
|
+
if (metaKey && activeLegendItems.includes(id)) {
|
|
69
|
+
nextActiveLegendItems = activeLegendItems.filter((item) => item !== id);
|
|
70
70
|
}
|
|
71
|
-
else if (metaKey && !activeLegendItems.includes(
|
|
72
|
-
nextActiveLegendItems = activeLegendItems.concat(
|
|
71
|
+
else if (metaKey && !activeLegendItems.includes(id)) {
|
|
72
|
+
nextActiveLegendItems = activeLegendItems.concat(id);
|
|
73
73
|
}
|
|
74
74
|
else if (onlyItemSelected && allItems.length === 1) {
|
|
75
75
|
nextActiveLegendItems = [];
|
|
@@ -78,7 +78,7 @@ export const useSeries = (args) => {
|
|
|
78
78
|
nextActiveLegendItems = allItems;
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
nextActiveLegendItems = [
|
|
81
|
+
nextActiveLegendItems = [id];
|
|
82
82
|
}
|
|
83
83
|
setActiveLegendItems(nextActiveLegendItems);
|
|
84
84
|
}, [preparedSeries, activeLegendItems]);
|
|
@@ -32,7 +32,6 @@ function prepareSeriesData(series) {
|
|
|
32
32
|
case 'zero':
|
|
33
33
|
return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { y: (_a = p.y) !== null && _a !== void 0 ? _a : 0 })); });
|
|
34
34
|
case 'connect':
|
|
35
|
-
return data.filter((p) => p.y !== null);
|
|
36
35
|
case 'skip':
|
|
37
36
|
default:
|
|
38
37
|
return data;
|
|
@@ -43,7 +42,7 @@ export function prepareArea(args) {
|
|
|
43
42
|
const defaultAreaWidth = get(seriesOptions, 'area.lineWidth', DEFAULT_LINE_WIDTH);
|
|
44
43
|
const defaultOpacity = get(seriesOptions, 'area.opacity', 0.75);
|
|
45
44
|
return seriesList.map((series) => {
|
|
46
|
-
var _a, _b, _c;
|
|
45
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
47
46
|
const id = getUniqId();
|
|
48
47
|
const name = series.name || '';
|
|
49
48
|
const color = series.color || colorScale(name);
|
|
@@ -58,23 +57,26 @@ export function prepareArea(args) {
|
|
|
58
57
|
legend: {
|
|
59
58
|
enabled: get(series, 'legend.enabled', legend.enabled),
|
|
60
59
|
symbol: prepareLegendSymbol(series),
|
|
60
|
+
groupId: (_b = (_a = series.legend) === null || _a === void 0 ? void 0 : _a.groupId) !== null && _b !== void 0 ? _b : getUniqId(),
|
|
61
|
+
itemText: (_d = (_c = series.legend) === null || _c === void 0 ? void 0 : _c.itemText) !== null && _d !== void 0 ? _d : name,
|
|
61
62
|
},
|
|
62
63
|
data: prepareSeriesData(series),
|
|
63
64
|
stacking: series.stacking,
|
|
64
65
|
stackId: getSeriesStackId(series),
|
|
65
66
|
dataLabels: {
|
|
66
|
-
enabled: ((
|
|
67
|
-
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (
|
|
67
|
+
enabled: ((_e = series.dataLabels) === null || _e === void 0 ? void 0 : _e.enabled) || false,
|
|
68
|
+
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_f = series.dataLabels) === null || _f === void 0 ? void 0 : _f.style),
|
|
68
69
|
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
|
|
69
70
|
allowOverlap: get(series, 'dataLabels.allowOverlap', false),
|
|
70
71
|
html: get(series, 'dataLabels.html', false),
|
|
71
|
-
format: (
|
|
72
|
+
format: (_g = series.dataLabels) === null || _g === void 0 ? void 0 : _g.format,
|
|
72
73
|
},
|
|
73
74
|
marker: prepareMarker(series, seriesOptions),
|
|
74
75
|
cursor: get(series, 'cursor', null),
|
|
75
76
|
yAxis: get(series, 'yAxis', 0),
|
|
76
77
|
tooltip: series.tooltip,
|
|
77
78
|
rangeSlider: Object.assign({}, seriesRangeSliderOptionsDefaults, series.rangeSlider),
|
|
79
|
+
nullMode: series.nullMode,
|
|
78
80
|
};
|
|
79
81
|
return prepared;
|
|
80
82
|
}, []);
|
|
@@ -12,13 +12,13 @@ function prepareSeriesData(series) {
|
|
|
12
12
|
return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { y: (_a = p.y) !== null && _a !== void 0 ? _a : 0 })); });
|
|
13
13
|
case 'skip':
|
|
14
14
|
default:
|
|
15
|
-
return data
|
|
15
|
+
return data;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
export function prepareBarXSeries(args) {
|
|
19
19
|
const { colorScale, series: seriesList, seriesOptions, legend } = args;
|
|
20
20
|
return seriesList.map((series) => {
|
|
21
|
-
var _a, _b, _c, _d;
|
|
21
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
22
22
|
const name = series.name || '';
|
|
23
23
|
const color = series.color || colorScale(name);
|
|
24
24
|
const dataLabelsInside = series.stacking === 'percent' ? true : get(series, 'dataLabels.inside', false);
|
|
@@ -31,18 +31,20 @@ export function prepareBarXSeries(args) {
|
|
|
31
31
|
legend: {
|
|
32
32
|
enabled: get(series, 'legend.enabled', legend.enabled),
|
|
33
33
|
symbol: prepareLegendSymbol(series),
|
|
34
|
+
groupId: (_b = (_a = series.legend) === null || _a === void 0 ? void 0 : _a.groupId) !== null && _b !== void 0 ? _b : getUniqId(),
|
|
35
|
+
itemText: (_d = (_c = series.legend) === null || _c === void 0 ? void 0 : _c.itemText) !== null && _d !== void 0 ? _d : name,
|
|
34
36
|
},
|
|
35
37
|
data: prepareSeriesData(series),
|
|
36
38
|
stacking: series.stacking,
|
|
37
39
|
stackId: getSeriesStackId(series),
|
|
38
40
|
dataLabels: {
|
|
39
|
-
enabled: ((
|
|
41
|
+
enabled: ((_e = series.dataLabels) === null || _e === void 0 ? void 0 : _e.enabled) || false,
|
|
40
42
|
inside: dataLabelsInside,
|
|
41
|
-
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (
|
|
42
|
-
allowOverlap: ((
|
|
43
|
+
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_f = series.dataLabels) === null || _f === void 0 ? void 0 : _f.style),
|
|
44
|
+
allowOverlap: ((_g = series.dataLabels) === null || _g === void 0 ? void 0 : _g.allowOverlap) || false,
|
|
43
45
|
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
|
|
44
46
|
html: get(series, 'dataLabels.html', false),
|
|
45
|
-
format: (
|
|
47
|
+
format: (_h = series.dataLabels) === null || _h === void 0 ? void 0 : _h.format,
|
|
46
48
|
},
|
|
47
49
|
cursor: get(series, 'cursor', null),
|
|
48
50
|
yAxis: get(series, 'yAxis', 0),
|