@gravity-ui/charts 1.32.1 → 1.33.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/hooks/index.d.ts +1 -0
- package/dist/cjs/hooks/index.js +1 -0
- package/dist/cjs/hooks/useAxis/x-axis.js +2 -0
- package/dist/cjs/hooks/useAxis/y-axis.js +2 -0
- package/dist/cjs/hooks/useAxisScales/index.d.ts +6 -8
- package/dist/cjs/hooks/useAxisScales/index.js +145 -47
- package/dist/cjs/hooks/useAxisScales/types.d.ts +6 -0
- package/dist/cjs/hooks/useAxisScales/types.js +1 -0
- package/dist/cjs/hooks/useAxisScales/utils.d.ts +9 -1
- package/dist/cjs/hooks/useAxisScales/utils.js +74 -0
- package/dist/cjs/hooks/useNormalizedOriginalData/index.d.ts +2 -0
- package/dist/cjs/hooks/useRangeSlider/index.js +1 -0
- package/dist/cjs/hooks/useRangeSlider/types.d.ts +1 -1
- package/dist/cjs/hooks/useRangeSlider/utils.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +25 -11
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/heatmap/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/index.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/line/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/scatter/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/utils.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
- package/dist/cjs/hooks/useZoom/index.d.ts +1 -1
- package/dist/cjs/hooks/useZoom/utils.d.ts +1 -1
- package/dist/cjs/hooks/utils/bar-x.d.ts +1 -1
- package/dist/cjs/hooks/utils/bar-y.d.ts +1 -1
- package/dist/cjs/i18n/keysets/en.json +2 -1
- package/dist/cjs/i18n/keysets/ru.json +2 -1
- package/dist/cjs/types/chart/axis.d.ts +25 -0
- package/dist/cjs/validation/validate-axes.js +35 -0
- package/dist/esm/hooks/index.d.ts +1 -0
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/useAxis/x-axis.js +2 -0
- package/dist/esm/hooks/useAxis/y-axis.js +2 -0
- package/dist/esm/hooks/useAxisScales/index.d.ts +6 -8
- package/dist/esm/hooks/useAxisScales/index.js +145 -47
- package/dist/esm/hooks/useAxisScales/types.d.ts +6 -0
- package/dist/esm/hooks/useAxisScales/types.js +1 -0
- package/dist/esm/hooks/useAxisScales/utils.d.ts +9 -1
- package/dist/esm/hooks/useAxisScales/utils.js +74 -0
- package/dist/esm/hooks/useNormalizedOriginalData/index.d.ts +2 -0
- package/dist/esm/hooks/useRangeSlider/index.js +1 -0
- package/dist/esm/hooks/useRangeSlider/types.d.ts +1 -1
- package/dist/esm/hooks/useRangeSlider/utils.d.ts +1 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.js +25 -11
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useShapes/heatmap/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useShapes/index.d.ts +1 -1
- package/dist/esm/hooks/useShapes/line/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useShapes/scatter/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useShapes/utils.d.ts +1 -1
- package/dist/esm/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
- package/dist/esm/hooks/useZoom/index.d.ts +1 -1
- package/dist/esm/hooks/useZoom/utils.d.ts +1 -1
- package/dist/esm/hooks/utils/bar-x.d.ts +1 -1
- package/dist/esm/hooks/utils/bar-y.d.ts +1 -1
- package/dist/esm/i18n/keysets/en.json +2 -1
- package/dist/esm/i18n/keysets/ru.json +2 -1
- package/dist/esm/types/chart/axis.d.ts +25 -0
- package/dist/esm/validation/validate-axes.js +35 -0
- package/package.json +1 -1
package/dist/cjs/hooks/index.js
CHANGED
|
@@ -127,6 +127,8 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
|
|
|
127
127
|
},
|
|
128
128
|
min: get(xAxis, 'min'),
|
|
129
129
|
max: get(xAxis, 'max'),
|
|
130
|
+
startOnTick: get(xAxis, 'startOnTick'),
|
|
131
|
+
endOnTick: get(xAxis, 'endOnTick'),
|
|
130
132
|
maxPadding,
|
|
131
133
|
grid: {
|
|
132
134
|
enabled: shouldHideGrid ? false : get(xAxis, 'grid.enabled', true),
|
|
@@ -139,6 +139,8 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
139
139
|
},
|
|
140
140
|
min: (_l = get(axisItem, 'min')) !== null && _l !== void 0 ? _l : getDefaultMinYAxisValue(axisSeriesData),
|
|
141
141
|
max: get(axisItem, 'max'),
|
|
142
|
+
startOnTick: get(axisItem, 'startOnTick'),
|
|
143
|
+
endOnTick: get(axisItem, 'endOnTick'),
|
|
142
144
|
maxPadding: get(axisItem, 'maxPadding', getMaxPaddingBySeries({ series: axisSeriesData })),
|
|
143
145
|
grid: {
|
|
144
146
|
enabled: shouldHideGrid
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
1
|
import type { PreparedAxis, PreparedSeries, PreparedSplit, RangeSliderState, ZoomState } from '../../hooks';
|
|
3
2
|
import type { ChartAxis, ChartSeries } from '../../types';
|
|
4
|
-
type
|
|
5
|
-
export type ChartScaleLinear = ScaleLinear<number, number>;
|
|
6
|
-
export type ChartScaleTime = ScaleTime<number, number>;
|
|
7
|
-
export type ChartScale = ChartScaleBand | ChartScaleLinear | ChartScaleTime;
|
|
3
|
+
import type { ChartScale } from './types';
|
|
8
4
|
type Args = {
|
|
9
5
|
boundsWidth: number;
|
|
10
6
|
boundsHeight: number;
|
|
@@ -12,6 +8,7 @@ type Args = {
|
|
|
12
8
|
xAxis: PreparedAxis | null;
|
|
13
9
|
yAxis: PreparedAxis[];
|
|
14
10
|
split: PreparedSplit;
|
|
11
|
+
isRangeSlider?: boolean;
|
|
15
12
|
rangeSliderState?: RangeSliderState;
|
|
16
13
|
zoomState?: Partial<ZoomState>;
|
|
17
14
|
};
|
|
@@ -22,16 +19,17 @@ type ReturnValue = {
|
|
|
22
19
|
export declare function createYScale(args: {
|
|
23
20
|
axis: PreparedAxis;
|
|
24
21
|
boundsHeight: number;
|
|
25
|
-
series:
|
|
22
|
+
series: PreparedSeries[] | ChartSeries[];
|
|
23
|
+
primaryTickPositions?: number[];
|
|
26
24
|
zoomStateY?: [number, number];
|
|
27
|
-
}): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never> | undefined;
|
|
25
|
+
}): import("d3-scale").ScaleBand<string> | import("d3-scale").ScaleLinear<number, number, never> | import("d3-scale").ScaleTime<number, number, never> | undefined;
|
|
28
26
|
export declare function createXScale(args: {
|
|
29
27
|
axis: PreparedAxis | ChartAxis;
|
|
30
28
|
boundsWidth: number;
|
|
31
29
|
series: (PreparedSeries | ChartSeries)[];
|
|
32
30
|
rangeSliderState?: RangeSliderState;
|
|
33
31
|
zoomStateX?: [number, number];
|
|
34
|
-
}): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never> | undefined;
|
|
32
|
+
}): import("d3-scale").ScaleBand<string> | import("d3-scale").ScaleLinear<number, number, never> | import("d3-scale").ScaleTime<number, number, never> | undefined;
|
|
35
33
|
/**
|
|
36
34
|
* Uses to create scales for axis related series
|
|
37
35
|
*/
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { extent, scaleBand, scaleLinear, scaleLog, scaleUtc } from 'd3';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
|
+
import { getTickValues } from '../../components/AxisY/utils';
|
|
4
5
|
import { DEFAULT_AXIS_TYPE, SERIES_TYPE } from '../../constants';
|
|
5
6
|
import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, getAxisCategories, getAxisHeight, getDataCategoryValue, getDefaultMaxXAxisValue, getDefaultMinXAxisValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
|
|
6
7
|
import { getBandSize } from '../utils/get-band-size';
|
|
7
|
-
import { checkIsPointDomain, getMinMaxPropsOrState, getXMaxDomainResult, hasOnlyMarkerSeries, } from './utils';
|
|
8
|
+
import { checkIsPointDomain, clusterYAxes, getDomainSyncedToPrimaryTicks, getMinMaxPropsOrState, getXMaxDomainResult, hasOnlyMarkerSeries, } from './utils';
|
|
8
9
|
const X_AXIS_ZOOM_PADDING = 0.02;
|
|
9
10
|
function validateArrayData(data) {
|
|
10
11
|
let hasNumberAndNullValues;
|
|
@@ -65,7 +66,7 @@ function isSeriesWithYAxisOffset(series) {
|
|
|
65
66
|
}
|
|
66
67
|
// eslint-disable-next-line complexity
|
|
67
68
|
export function createYScale(args) {
|
|
68
|
-
const { axis, boundsHeight, series, zoomStateY } = args;
|
|
69
|
+
const { axis, boundsHeight, series, primaryTickPositions, zoomStateY } = args;
|
|
69
70
|
const [yMinPropsOrState, yMaxPropsOrState] = getMinMaxPropsOrState({
|
|
70
71
|
axis,
|
|
71
72
|
maxValues: [zoomStateY === null || zoomStateY === void 0 ? void 0 : zoomStateY[1]],
|
|
@@ -102,29 +103,57 @@ export function createYScale(args) {
|
|
|
102
103
|
yMax = hasSeriesWithVolumeOnYAxis ? Math.max(yMaxDomain, 0) : yMaxDomain;
|
|
103
104
|
}
|
|
104
105
|
const scaleFn = axis.type === 'logarithmic' ? scaleLog : scaleLinear;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
let scale = scaleFn().domain([yMin, yMax]).range(range);
|
|
107
|
+
if (primaryTickPositions) {
|
|
108
|
+
const syncedDomain = getDomainSyncedToPrimaryTicks({
|
|
109
|
+
primaryTickPositions,
|
|
110
|
+
range,
|
|
111
|
+
scaleFn,
|
|
112
|
+
secondaryDomain: scale.domain(),
|
|
113
|
+
});
|
|
114
|
+
scale.domain(syncedDomain);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
let offsetMin = 0;
|
|
118
|
+
// We should ignore padding if we are drawing only one point on the plot.
|
|
119
|
+
let offsetMax = yMin === yMax ? 0 : boundsHeight * axis.maxPadding;
|
|
120
|
+
if (isSeriesWithYAxisOffset(series)) {
|
|
121
|
+
if (domain.length > 1) {
|
|
122
|
+
const bandWidth = getBandSize({
|
|
123
|
+
scale: scale,
|
|
124
|
+
domain: domain,
|
|
125
|
+
});
|
|
126
|
+
offsetMin += bandWidth / 2;
|
|
127
|
+
offsetMax += bandWidth / 2;
|
|
128
|
+
}
|
|
117
129
|
}
|
|
130
|
+
const isMinSpecified = typeof get(axis, 'min') === 'number' && !zoomStateY;
|
|
131
|
+
const isMaxSpecified = typeof get(axis, 'max') === 'number' && !zoomStateY;
|
|
132
|
+
const domainOffsetMin = isMinSpecified
|
|
133
|
+
? 0
|
|
134
|
+
: Math.abs(scale.invert(offsetMin) - scale.invert(0));
|
|
135
|
+
const domainOffsetMax = isMaxSpecified
|
|
136
|
+
? 0
|
|
137
|
+
: Math.abs(scale.invert(offsetMax) - scale.invert(0));
|
|
138
|
+
scale = scale.domain([yMin - domainOffsetMin, yMax + domainOffsetMax]);
|
|
118
139
|
}
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
// 10 is the default value for the number of ticks. Here, to preserve the appearance of a series with a small number of points
|
|
141
|
+
const nicedDomain = scale.copy().nice(Math.max(10, domain.length)).domain();
|
|
142
|
+
const startOnTick = get(axis, 'startOnTick', false);
|
|
143
|
+
const endOnTick = get(axis, 'endOnTick', false);
|
|
144
|
+
const hasOffset = isSeriesWithYAxisOffset(series);
|
|
145
|
+
if (!zoomStateY && !hasOffset && nicedDomain.length === 2) {
|
|
146
|
+
const domainWithOffset = scale.domain();
|
|
147
|
+
scale.domain([
|
|
148
|
+
startOnTick
|
|
149
|
+
? Math.min(nicedDomain[0], domainWithOffset[0])
|
|
150
|
+
: domainWithOffset[0],
|
|
151
|
+
endOnTick
|
|
152
|
+
? Math.max(nicedDomain[1], domainWithOffset[1])
|
|
153
|
+
: domainWithOffset[1],
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
return scale;
|
|
128
157
|
}
|
|
129
158
|
break;
|
|
130
159
|
}
|
|
@@ -155,7 +184,17 @@ export function createYScale(args) {
|
|
|
155
184
|
yMaxPropsOrState < yMaxTimestamp
|
|
156
185
|
? yMaxPropsOrState
|
|
157
186
|
: yMaxTimestamp;
|
|
158
|
-
|
|
187
|
+
const scale = scaleUtc().domain([yMin, yMax]).range(range);
|
|
188
|
+
const startOnTick = get(axis, 'startOnTick', true);
|
|
189
|
+
const endOnTick = get(axis, 'endOnTick', true);
|
|
190
|
+
if (startOnTick || endOnTick) {
|
|
191
|
+
const nicedDomain = scale.copy().nice().domain();
|
|
192
|
+
return scale.domain([
|
|
193
|
+
startOnTick ? Number(nicedDomain[0]) : yMin,
|
|
194
|
+
endOnTick ? Number(nicedDomain[1]) : yMax,
|
|
195
|
+
]);
|
|
196
|
+
}
|
|
197
|
+
return scale;
|
|
159
198
|
}
|
|
160
199
|
else {
|
|
161
200
|
const domain = getDomainDataYBySeries(series);
|
|
@@ -330,11 +369,17 @@ export function createXScale(args) {
|
|
|
330
369
|
// 10 is the default value for the number of ticks. Here, to preserve the appearance of a series with a small number of points
|
|
331
370
|
const nicedDomain = scale.copy().nice(Math.max(10, domainData.length)).domain();
|
|
332
371
|
scale.domain([xMin - domainOffsetMin, xMax + domainOffsetMax]);
|
|
372
|
+
const startOnTick = get(axis, 'startOnTick', true);
|
|
373
|
+
const endOnTick = get(axis, 'endOnTick', true);
|
|
333
374
|
if (!hasZoomX && !hasOffset && nicedDomain.length === 2) {
|
|
334
375
|
const domainWithOffset = scale.domain();
|
|
335
376
|
scale.domain([
|
|
336
|
-
|
|
337
|
-
|
|
377
|
+
startOnTick
|
|
378
|
+
? Math.min(nicedDomain[0], domainWithOffset[0])
|
|
379
|
+
: domainWithOffset[0],
|
|
380
|
+
endOnTick
|
|
381
|
+
? Math.max(nicedDomain[1], domainWithOffset[1])
|
|
382
|
+
: domainWithOffset[1],
|
|
338
383
|
]);
|
|
339
384
|
}
|
|
340
385
|
return scale;
|
|
@@ -403,11 +448,17 @@ export function createXScale(args) {
|
|
|
403
448
|
// 10 is the default value for the number of ticks. Here, to preserve the appearance of a series with a small number of points
|
|
404
449
|
const nicedDomain = scale.copy().nice(Math.max(10, domainData.length)).domain();
|
|
405
450
|
scale.domain([xMin - domainOffsetMin, xMax + domainOffsetMax]);
|
|
451
|
+
const startOnTick = get(axis, 'startOnTick', true);
|
|
452
|
+
const endOnTick = get(axis, 'endOnTick', true);
|
|
406
453
|
if (!hasZoomX && !hasOffset && nicedDomain.length === 2) {
|
|
407
454
|
const domainWithOffset = scale.domain();
|
|
408
455
|
scale.domain([
|
|
409
|
-
|
|
410
|
-
|
|
456
|
+
startOnTick
|
|
457
|
+
? Math.min(Number(nicedDomain[0]), Number(domainWithOffset[0]))
|
|
458
|
+
: Number(domainWithOffset[0]),
|
|
459
|
+
endOnTick
|
|
460
|
+
? Math.max(Number(nicedDomain[1]), Number(domainWithOffset[1]))
|
|
461
|
+
: Number(domainWithOffset[1]),
|
|
411
462
|
]);
|
|
412
463
|
}
|
|
413
464
|
return scale;
|
|
@@ -418,11 +469,62 @@ export function createXScale(args) {
|
|
|
418
469
|
throw new Error('Failed to create xScale');
|
|
419
470
|
}
|
|
420
471
|
const createScales = (args) => {
|
|
421
|
-
const { boundsWidth, boundsHeight, rangeSliderState, series, split, xAxis, yAxis, zoomState } = args;
|
|
472
|
+
const { boundsWidth, boundsHeight, isRangeSlider, rangeSliderState, series, split, xAxis, yAxis, zoomState, } = args;
|
|
422
473
|
let visibleSeries = getOnlyVisibleSeries(series);
|
|
423
474
|
// Reassign to all series in case of all series unselected,
|
|
424
475
|
// otherwise we will get an empty space without grid
|
|
425
476
|
visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
|
|
477
|
+
const axisHeight = getAxisHeight({ boundsHeight, split });
|
|
478
|
+
let index = 0;
|
|
479
|
+
const yScale = clusterYAxes(yAxis).reduce((acc, cluster) => {
|
|
480
|
+
var _a, _b;
|
|
481
|
+
const [primaryAxis, secondaryAxis] = cluster;
|
|
482
|
+
const mainAxisSeries = series.filter((s) => {
|
|
483
|
+
const seriesAxisIndex = get(s, 'yAxis', 0);
|
|
484
|
+
return seriesAxisIndex === index;
|
|
485
|
+
});
|
|
486
|
+
const visiblePrimaryAxisSeries = getOnlyVisibleSeries(mainAxisSeries);
|
|
487
|
+
const primaryAxisScale = createYScale({
|
|
488
|
+
axis: primaryAxis,
|
|
489
|
+
boundsHeight: axisHeight,
|
|
490
|
+
series: visiblePrimaryAxisSeries.length ? visiblePrimaryAxisSeries : mainAxisSeries,
|
|
491
|
+
zoomStateY: (_a = zoomState === null || zoomState === void 0 ? void 0 : zoomState.y) === null || _a === void 0 ? void 0 : _a[index],
|
|
492
|
+
});
|
|
493
|
+
acc.push(primaryAxisScale);
|
|
494
|
+
index += 1;
|
|
495
|
+
let primaryTickPositions;
|
|
496
|
+
if (primaryAxisScale && secondaryAxis && !isRangeSlider) {
|
|
497
|
+
primaryTickPositions = getTickValues({
|
|
498
|
+
axis: primaryAxis,
|
|
499
|
+
scale: primaryAxisScale,
|
|
500
|
+
labelLineHeight: primaryAxis.labels.lineHeight,
|
|
501
|
+
series: visiblePrimaryAxisSeries.length
|
|
502
|
+
? visiblePrimaryAxisSeries
|
|
503
|
+
: mainAxisSeries,
|
|
504
|
+
}).map((t) => t.y);
|
|
505
|
+
}
|
|
506
|
+
const secondAxisSeries = series.filter((s) => {
|
|
507
|
+
const seriesAxisIndex = get(s, 'yAxis', 0);
|
|
508
|
+
return seriesAxisIndex === index;
|
|
509
|
+
});
|
|
510
|
+
const visibleSecondAxisSeries = getOnlyVisibleSeries(secondAxisSeries);
|
|
511
|
+
const secondaryAxisScale = secondaryAxis
|
|
512
|
+
? createYScale({
|
|
513
|
+
axis: secondaryAxis,
|
|
514
|
+
boundsHeight: axisHeight,
|
|
515
|
+
primaryTickPositions,
|
|
516
|
+
series: visibleSecondAxisSeries.length
|
|
517
|
+
? visibleSecondAxisSeries
|
|
518
|
+
: secondAxisSeries,
|
|
519
|
+
zoomStateY: (_b = zoomState === null || zoomState === void 0 ? void 0 : zoomState.y) === null || _b === void 0 ? void 0 : _b[index],
|
|
520
|
+
})
|
|
521
|
+
: undefined;
|
|
522
|
+
if (secondaryAxisScale) {
|
|
523
|
+
acc.push(secondaryAxisScale);
|
|
524
|
+
index += 1;
|
|
525
|
+
}
|
|
526
|
+
return acc;
|
|
527
|
+
}, []);
|
|
426
528
|
return {
|
|
427
529
|
xScale: xAxis
|
|
428
530
|
? createXScale({
|
|
@@ -433,29 +535,14 @@ const createScales = (args) => {
|
|
|
433
535
|
zoomStateX: zoomState === null || zoomState === void 0 ? void 0 : zoomState.x,
|
|
434
536
|
})
|
|
435
537
|
: undefined,
|
|
436
|
-
yScale
|
|
437
|
-
var _a;
|
|
438
|
-
const axisSeries = series.filter((s) => {
|
|
439
|
-
const seriesAxisIndex = get(s, 'yAxis', 0);
|
|
440
|
-
return seriesAxisIndex === index;
|
|
441
|
-
});
|
|
442
|
-
const visibleAxisSeries = getOnlyVisibleSeries(axisSeries);
|
|
443
|
-
const axisHeight = getAxisHeight({ boundsHeight, split });
|
|
444
|
-
const zoomStateY = (_a = zoomState === null || zoomState === void 0 ? void 0 : zoomState.y) === null || _a === void 0 ? void 0 : _a[index];
|
|
445
|
-
return createYScale({
|
|
446
|
-
axis,
|
|
447
|
-
boundsHeight: axisHeight,
|
|
448
|
-
series: visibleAxisSeries.length ? visibleAxisSeries : axisSeries,
|
|
449
|
-
zoomStateY,
|
|
450
|
-
});
|
|
451
|
-
}),
|
|
538
|
+
yScale,
|
|
452
539
|
};
|
|
453
540
|
};
|
|
454
541
|
/**
|
|
455
542
|
* Uses to create scales for axis related series
|
|
456
543
|
*/
|
|
457
544
|
export const useAxisScales = (args) => {
|
|
458
|
-
const { boundsWidth, boundsHeight, rangeSliderState, series, split, xAxis, yAxis, zoomState } = args;
|
|
545
|
+
const { boundsWidth, boundsHeight, isRangeSlider, rangeSliderState, series, split, xAxis, yAxis, zoomState, } = args;
|
|
459
546
|
return React.useMemo(() => {
|
|
460
547
|
let xScale;
|
|
461
548
|
let yScale;
|
|
@@ -464,6 +551,7 @@ export const useAxisScales = (args) => {
|
|
|
464
551
|
({ xScale, yScale } = createScales({
|
|
465
552
|
boundsWidth,
|
|
466
553
|
boundsHeight,
|
|
554
|
+
isRangeSlider,
|
|
467
555
|
rangeSliderState,
|
|
468
556
|
series,
|
|
469
557
|
split,
|
|
@@ -473,5 +561,15 @@ export const useAxisScales = (args) => {
|
|
|
473
561
|
}));
|
|
474
562
|
}
|
|
475
563
|
return { xScale, yScale };
|
|
476
|
-
}, [
|
|
564
|
+
}, [
|
|
565
|
+
boundsWidth,
|
|
566
|
+
boundsHeight,
|
|
567
|
+
isRangeSlider,
|
|
568
|
+
rangeSliderState,
|
|
569
|
+
series,
|
|
570
|
+
split,
|
|
571
|
+
xAxis,
|
|
572
|
+
yAxis,
|
|
573
|
+
zoomState,
|
|
574
|
+
]);
|
|
477
575
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
|
+
type ChartScaleBand = ScaleBand<string>;
|
|
3
|
+
export type ChartScaleLinear = ScaleLinear<number, number>;
|
|
4
|
+
export type ChartScaleTime = ScaleTime<number, number>;
|
|
5
|
+
export type ChartScale = ChartScaleBand | ChartScaleLinear | ChartScaleTime;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { scaleLinear } from 'd3';
|
|
2
|
+
import type { PreparedAxis, PreparedSeries, PreparedYAxis } from '../../hooks';
|
|
2
3
|
import type { ChartAxis, ChartSeries } from '../../types';
|
|
3
4
|
type OptionalNumber = number | undefined;
|
|
4
5
|
export declare function getMinMaxPropsOrState(args: {
|
|
@@ -22,4 +23,11 @@ export declare function getXMaxDomainResult(args: {
|
|
|
22
23
|
xMaxRangeSlider?: number;
|
|
23
24
|
xMaxZoom?: number;
|
|
24
25
|
}): number;
|
|
26
|
+
export declare function clusterYAxes(yAxes: PreparedYAxis[]): [PreparedYAxis, PreparedYAxis?][];
|
|
27
|
+
export declare function getDomainSyncedToPrimaryTicks(args: {
|
|
28
|
+
primaryTickPositions: number[];
|
|
29
|
+
range: [number, number];
|
|
30
|
+
scaleFn: typeof scaleLinear;
|
|
31
|
+
secondaryDomain: number[];
|
|
32
|
+
}): [number, number];
|
|
25
33
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ticks } from 'd3';
|
|
1
2
|
import get from 'lodash/get';
|
|
2
3
|
import { SERIES_TYPE } from '../../constants';
|
|
3
4
|
const MARKER_SERIES_TYPES = [SERIES_TYPE.Area, SERIES_TYPE.Line, SERIES_TYPE.Scatter];
|
|
@@ -49,3 +50,76 @@ export function getXMaxDomainResult(args) {
|
|
|
49
50
|
}
|
|
50
51
|
return xMaxDomainResult;
|
|
51
52
|
}
|
|
53
|
+
export function clusterYAxes(yAxes) {
|
|
54
|
+
if (yAxes.length <= 1) {
|
|
55
|
+
return yAxes.map((axis) => [axis]);
|
|
56
|
+
}
|
|
57
|
+
const clusters = {};
|
|
58
|
+
yAxes.forEach((axis) => {
|
|
59
|
+
var _a;
|
|
60
|
+
const plotIndex = (_a = axis.plotIndex) !== null && _a !== void 0 ? _a : 0;
|
|
61
|
+
if (!clusters[plotIndex]) {
|
|
62
|
+
clusters[plotIndex] = [];
|
|
63
|
+
}
|
|
64
|
+
clusters[plotIndex].push(axis);
|
|
65
|
+
});
|
|
66
|
+
return Object.values(clusters).map((cluster) => {
|
|
67
|
+
if (cluster.length <= 1) {
|
|
68
|
+
return [cluster[0]];
|
|
69
|
+
}
|
|
70
|
+
const leftAxis = cluster.find((a) => a.position === 'left');
|
|
71
|
+
const secondaryAxis = cluster.find((a) => a !== leftAxis);
|
|
72
|
+
if (leftAxis) {
|
|
73
|
+
return [leftAxis, secondaryAxis];
|
|
74
|
+
}
|
|
75
|
+
return [cluster[0], cluster[1]];
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
export function getDomainSyncedToPrimaryTicks(args) {
|
|
79
|
+
const { primaryTickPositions, range, scaleFn, secondaryDomain } = args;
|
|
80
|
+
const [dMin, dMax] = secondaryDomain;
|
|
81
|
+
const primaryPosBottom = primaryTickPositions[0];
|
|
82
|
+
const primaryPosTop = primaryTickPositions[primaryTickPositions.length - 1];
|
|
83
|
+
let secondaryTicks = ticks(dMin, dMax, primaryTickPositions.length);
|
|
84
|
+
let originalStep = 0;
|
|
85
|
+
if (typeof secondaryTicks[0] === 'number' && typeof secondaryTicks[1] === 'number') {
|
|
86
|
+
originalStep = secondaryTicks[1] - secondaryTicks[0];
|
|
87
|
+
}
|
|
88
|
+
let i = 1;
|
|
89
|
+
while (secondaryTicks.length > primaryTickPositions.length) {
|
|
90
|
+
secondaryTicks = ticks(dMin, dMax, primaryTickPositions.length - i);
|
|
91
|
+
i += 1;
|
|
92
|
+
}
|
|
93
|
+
let step = originalStep;
|
|
94
|
+
if (typeof secondaryTicks[0] === 'number' && typeof secondaryTicks[1] === 'number') {
|
|
95
|
+
step = secondaryTicks[1] - secondaryTicks[0];
|
|
96
|
+
}
|
|
97
|
+
let ticksCountDiff = primaryTickPositions.length - secondaryTicks.length;
|
|
98
|
+
let deltaMin = Math.abs(dMin - secondaryTicks[0]);
|
|
99
|
+
let deltaMax = Math.abs(dMax - secondaryTicks[secondaryTicks.length - 1]);
|
|
100
|
+
while (ticksCountDiff > 0) {
|
|
101
|
+
if (deltaMin > deltaMax) {
|
|
102
|
+
secondaryTicks.unshift(secondaryTicks[0] - step);
|
|
103
|
+
deltaMin -= step;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
secondaryTicks.push(secondaryTicks[secondaryTicks.length - 1] + step);
|
|
107
|
+
deltaMax -= step;
|
|
108
|
+
}
|
|
109
|
+
ticksCountDiff -= 1;
|
|
110
|
+
}
|
|
111
|
+
let tmpScale = scaleFn()
|
|
112
|
+
.domain([secondaryTicks[0], secondaryTicks[secondaryTicks.length - 1]])
|
|
113
|
+
.range([primaryPosBottom, primaryPosTop]);
|
|
114
|
+
let dNewMin = tmpScale.invert(range[0]);
|
|
115
|
+
let dNewMax = tmpScale.invert(range[1]);
|
|
116
|
+
if (dNewMin < dMin) {
|
|
117
|
+
secondaryTicks = secondaryTicks.map((st) => st + step);
|
|
118
|
+
tmpScale = scaleFn()
|
|
119
|
+
.domain([secondaryTicks[0], secondaryTicks[secondaryTicks.length - 1]])
|
|
120
|
+
.range([primaryPosBottom, primaryPosTop]);
|
|
121
|
+
dNewMin = tmpScale.invert(range[0]);
|
|
122
|
+
dNewMax = tmpScale.invert(range[1]);
|
|
123
|
+
}
|
|
124
|
+
return [dNewMin, dNewMax];
|
|
125
|
+
}
|
|
@@ -29,6 +29,8 @@ export declare function useNormalizedOriginalData(props: UseOriginalDataProps):
|
|
|
29
29
|
plotBands?: import("../../types").AxisPlotBand[];
|
|
30
30
|
visible?: boolean;
|
|
31
31
|
order?: "sortAsc" | "sortDesc" | "reverse";
|
|
32
|
+
startOnTick?: boolean;
|
|
33
|
+
endOnTick?: boolean;
|
|
32
34
|
};
|
|
33
35
|
normalizedYAxis: import("../../types").ChartYAxis[] | undefined;
|
|
34
36
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChartXAxis, ChartYAxis } from '../../types';
|
|
2
2
|
import type { PreparedRangeSlider, PreparedXAxis, PreparedYAxis } from '../useAxis/types';
|
|
3
|
-
import type { ChartScale } from '../useAxisScales';
|
|
3
|
+
import type { ChartScale } from '../useAxisScales/types';
|
|
4
4
|
import type { BrushSelection, UseBrushProps } from '../useBrush/types';
|
|
5
5
|
import type { PreparedChart } from '../useChartOptions/types';
|
|
6
6
|
import type { PreparedLegend, PreparedSeries, PreparedSeriesOptions } from '../useSeries/types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedRangeSlider } from '../useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../useAxisScales/types';
|
|
3
3
|
import type { BrushSelection } from '../useBrush/types';
|
|
4
4
|
import type { PreparedChart } from '../useChartOptions/types';
|
|
5
5
|
import type { PreparedLegend } from '../useSeries/types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../../useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../../useAxisScales/types';
|
|
3
3
|
import type { PreparedAreaSeries } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedSplit } from '../../useSplit/types';
|
|
5
5
|
import type { PreparedAreaData } from './types';
|
|
@@ -91,9 +91,11 @@ export const prepareAreaData = async (args) => {
|
|
|
91
91
|
for (let i = 0; i < list.length; i++) {
|
|
92
92
|
const [_stackId, seriesStack] = list[i];
|
|
93
93
|
const xValues = getXValues(seriesStack, xAxis, xScale);
|
|
94
|
-
const
|
|
94
|
+
const positiveStackValues = new Map();
|
|
95
|
+
const negativeStackValues = new Map();
|
|
95
96
|
xValues.forEach(([key]) => {
|
|
96
|
-
|
|
97
|
+
positiveStackValues.set(key, 0);
|
|
98
|
+
negativeStackValues.set(key, 0);
|
|
97
99
|
});
|
|
98
100
|
const seriesStackData = [];
|
|
99
101
|
for (let j = 0; j < seriesStack.length; j++) {
|
|
@@ -122,24 +124,36 @@ export const prepareAreaData = async (args) => {
|
|
|
122
124
|
return m.set(key, d);
|
|
123
125
|
}, new Map());
|
|
124
126
|
const points = xValues.reduce((pointsAcc, [x, xValue]) => {
|
|
125
|
-
var _a;
|
|
126
|
-
const accumulatedYValue = accumulatedYValues.get(x) || 0;
|
|
127
|
+
var _a, _b;
|
|
127
128
|
const d = (_a = seriesData.get(x)) !== null && _a !== void 0 ? _a : {
|
|
128
129
|
x,
|
|
129
130
|
y: 0,
|
|
130
131
|
};
|
|
132
|
+
const yDataValue = (_b = d.y) !== null && _b !== void 0 ? _b : null;
|
|
131
133
|
const yValue = getYValue({ point: d, yAxis: seriesYAxis, yScale: seriesYScale });
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
let y = null;
|
|
135
|
+
let y0 = yAxisTop + yMin;
|
|
136
|
+
if (typeof yDataValue === 'number' && yValue !== null) {
|
|
137
|
+
if (yDataValue >= 0) {
|
|
138
|
+
const positiveStackHeight = positiveStackValues.get(x) || 0;
|
|
139
|
+
y = yAxisTop + yValue - positiveStackHeight;
|
|
140
|
+
y0 -= positiveStackHeight;
|
|
141
|
+
positiveStackValues.set(x, positiveStackHeight + (yMin - yValue));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
const negativeStackHeight = negativeStackValues.get(x) || 0;
|
|
145
|
+
y = yAxisTop + yValue + negativeStackHeight;
|
|
146
|
+
y0 += negativeStackHeight;
|
|
147
|
+
negativeStackValues.set(x, negativeStackHeight + (yValue - yMin));
|
|
148
|
+
}
|
|
135
149
|
}
|
|
136
|
-
if (s.nullMode === 'connect' &&
|
|
150
|
+
if (s.nullMode === 'connect' && yDataValue === null) {
|
|
137
151
|
return pointsAcc;
|
|
138
152
|
}
|
|
139
153
|
pointsAcc.push({
|
|
140
|
-
y0
|
|
154
|
+
y0,
|
|
141
155
|
x: xValue,
|
|
142
|
-
y
|
|
156
|
+
y,
|
|
143
157
|
data: d,
|
|
144
158
|
series: s,
|
|
145
159
|
});
|
|
@@ -183,7 +197,7 @@ export const prepareAreaData = async (args) => {
|
|
|
183
197
|
}
|
|
184
198
|
if (series.some((s) => s.stacking === 'percent')) {
|
|
185
199
|
xValues.forEach(([x], index) => {
|
|
186
|
-
const stackHeight =
|
|
200
|
+
const stackHeight = positiveStackValues.get(x) || 0;
|
|
187
201
|
let acc = 0;
|
|
188
202
|
const ratio = plotHeight / stackHeight;
|
|
189
203
|
seriesStackData.forEach((item) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../../useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../../useAxisScales/types';
|
|
3
3
|
import type { PreparedBarXSeries, PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedSplit } from '../../useSplit/types';
|
|
5
5
|
import type { PreparedBarXData } from './types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../../useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../../useAxisScales/types';
|
|
3
3
|
import type { PreparedBarYSeries, PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
4
|
import type { BarYShapesArgs } from './types';
|
|
5
5
|
export declare function prepareBarYData(args: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../../hooks/useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../../../hooks/useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../../../hooks/useAxisScales/types';
|
|
3
3
|
import type { PreparedHeatmapSeries } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedHeatmapData } from './types';
|
|
5
5
|
type PrepareHeatmapDataArgs = {
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { Dispatch } from 'd3';
|
|
3
3
|
import type { SeriesType } from '../../constants';
|
|
4
4
|
import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
|
|
5
|
-
import type { ChartScale } from '../useAxisScales';
|
|
5
|
+
import type { ChartScale } from '../useAxisScales/types';
|
|
6
6
|
import type { PreparedSeries, PreparedSeriesOptions } from '../useSeries/types';
|
|
7
7
|
import type { PreparedSplit } from '../useSplit/types';
|
|
8
8
|
import type { PreparedAreaData } from './area/types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../../useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../../useAxisScales/types';
|
|
3
3
|
import type { PreparedLineSeries } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedSplit } from '../../useSplit/types';
|
|
5
5
|
import type { PreparedLineData } from './types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
2
|
-
import type { ChartScale } from '../../useAxisScales';
|
|
2
|
+
import type { ChartScale } from '../../useAxisScales/types';
|
|
3
3
|
import type { PreparedScatterSeries } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedScatterData } from './types';
|
|
5
5
|
export declare function prepareScatterData(args: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BaseType } from 'd3';
|
|
2
2
|
import type { BasicInactiveState } from '../../types';
|
|
3
3
|
import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
|
|
4
|
-
import type { ChartScale } from '../useAxisScales';
|
|
4
|
+
import type { ChartScale } from '../useAxisScales/types';
|
|
5
5
|
export declare function getXValue(args: {
|
|
6
6
|
point: {
|
|
7
7
|
x?: number | string | null;
|