@gravity-ui/charts 1.34.1 → 1.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/AxisX/prepare-axis-data.d.ts +6 -5
- package/dist/cjs/components/AxisX/prepare-axis-data.js +2 -2
- package/dist/cjs/components/AxisY/utils.js +3 -3
- package/dist/cjs/components/ChartInner/index.js +18 -8
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +1 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +2 -1
- package/dist/cjs/hooks/useAxis/x-axis.js +1 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +85 -25
- package/dist/cjs/hooks/useShapes/index.d.ts +1 -0
- package/dist/cjs/hooks/useShapes/index.js +32 -26
- package/dist/cjs/setup-jsdom.d.ts +0 -0
- package/dist/cjs/setup-jsdom.js +19 -0
- package/dist/cjs/utils/chart/axis/common.d.ts +2 -2
- package/dist/cjs/utils/chart/axis/common.js +2 -2
- package/dist/cjs/utils/chart/axis/x-axis.d.ts +11 -10
- package/dist/cjs/utils/chart/axis/x-axis.js +24 -3
- package/dist/cjs/utils/chart/index.d.ts +2 -29
- package/dist/cjs/utils/chart/index.js +2 -19
- package/dist/cjs/utils/chart/series-type-guards.d.ts +30 -0
- package/dist/cjs/utils/chart/series-type-guards.js +19 -0
- package/dist/esm/components/AxisX/prepare-axis-data.d.ts +6 -5
- package/dist/esm/components/AxisX/prepare-axis-data.js +2 -2
- package/dist/esm/components/AxisY/utils.js +3 -3
- package/dist/esm/components/ChartInner/index.js +18 -8
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +1 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.js +2 -1
- package/dist/esm/hooks/useAxis/x-axis.js +1 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.js +85 -25
- package/dist/esm/hooks/useShapes/index.d.ts +1 -0
- package/dist/esm/hooks/useShapes/index.js +32 -26
- package/dist/esm/setup-jsdom.d.ts +0 -0
- package/dist/esm/setup-jsdom.js +19 -0
- package/dist/esm/utils/chart/axis/common.d.ts +2 -2
- package/dist/esm/utils/chart/axis/common.js +2 -2
- package/dist/esm/utils/chart/axis/x-axis.d.ts +11 -10
- package/dist/esm/utils/chart/axis/x-axis.js +24 -3
- package/dist/esm/utils/chart/index.d.ts +2 -29
- package/dist/esm/utils/chart/index.js +2 -19
- package/dist/esm/utils/chart/series-type-guards.d.ts +30 -0
- package/dist/esm/utils/chart/series-type-guards.js +19 -0
- package/package.json +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type { ChartScale, PreparedAxis, PreparedSplit } from '../../hooks';
|
|
1
|
+
import type { ChartScale, PreparedAxis, PreparedSeries, PreparedSplit } from '../../hooks';
|
|
2
2
|
import type { AxisXData } from './types';
|
|
3
|
-
export declare function prepareXAxisData({ axis,
|
|
3
|
+
export declare function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRight, boundsWidth, height, scale, series, split, yAxis, }: {
|
|
4
4
|
axis: PreparedAxis;
|
|
5
|
-
yAxis: PreparedAxis[];
|
|
6
|
-
scale: ChartScale;
|
|
7
|
-
boundsWidth: number;
|
|
8
5
|
boundsOffsetLeft: number;
|
|
9
6
|
boundsOffsetRight: number;
|
|
7
|
+
boundsWidth: number;
|
|
10
8
|
height: number;
|
|
9
|
+
scale: ChartScale;
|
|
10
|
+
series: PreparedSeries[];
|
|
11
11
|
split: PreparedSplit;
|
|
12
|
+
yAxis: PreparedAxis[];
|
|
12
13
|
}): Promise<AxisXData[]>;
|
|
@@ -68,7 +68,7 @@ async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxWid
|
|
|
68
68
|
return svgLabel;
|
|
69
69
|
}
|
|
70
70
|
// eslint-disable-next-line complexity
|
|
71
|
-
export async function prepareXAxisData({ axis,
|
|
71
|
+
export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRight, boundsWidth, height, scale, series, split, yAxis, }) {
|
|
72
72
|
var _a, _b, _c, _d, _e, _f;
|
|
73
73
|
const xAxisItems = [];
|
|
74
74
|
for (let plotIndex = 0; plotIndex < split.plots.length; plotIndex++) {
|
|
@@ -95,7 +95,7 @@ export async function prepareXAxisData({ axis, yAxis, scale, boundsWidth, bounds
|
|
|
95
95
|
const ticks = [];
|
|
96
96
|
const getTextSize = getTextSizeFn({ style: axis.labels.style });
|
|
97
97
|
const labelLineHeight = (await getTextSize('Tmp')).height;
|
|
98
|
-
const values = getXAxisTickValues({ scale, axis, labelLineHeight });
|
|
98
|
+
const values = getXAxisTickValues({ scale, axis, labelLineHeight, series });
|
|
99
99
|
const tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
|
|
100
100
|
const labelMaxWidth = values.length > 1
|
|
101
101
|
? Math.abs(values[0].x - values[1].x) - axis.labels.padding * 2
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getDomainDataYBySeries, getMinSpaceBetween,
|
|
1
|
+
import { getDomainDataYBySeries, getMinSpaceBetween, getTicksCountByPixelInterval, isBandScale, thinOut, } from '../../utils';
|
|
2
2
|
export function getTickValues({ scale, axis, labelLineHeight, series, }) {
|
|
3
3
|
if ('ticks' in scale && typeof scale.ticks === 'function') {
|
|
4
4
|
const range = scale.range();
|
|
@@ -13,10 +13,10 @@ export function getTickValues({ scale, axis, labelLineHeight, series, }) {
|
|
|
13
13
|
if (domainData.length < 3) {
|
|
14
14
|
return domainData;
|
|
15
15
|
}
|
|
16
|
-
const ticksCount = (_a =
|
|
16
|
+
const ticksCount = (_a = getTicksCountByPixelInterval({ axis, axisWidth: height })) !== null && _a !== void 0 ? _a : domainData.length;
|
|
17
17
|
return scale.ticks(Math.min(ticksCount, domainData.length));
|
|
18
18
|
}
|
|
19
|
-
const ticksCount =
|
|
19
|
+
const ticksCount = getTicksCountByPixelInterval({ axis, axisWidth: height });
|
|
20
20
|
return scale.ticks(ticksCount);
|
|
21
21
|
};
|
|
22
22
|
const scaleTicks = getScaleTicks();
|
|
@@ -64,7 +64,7 @@ export const ChartInner = (props) => {
|
|
|
64
64
|
preparedRangeSlider,
|
|
65
65
|
tooltip: preparedTooltip,
|
|
66
66
|
});
|
|
67
|
-
const { allPreparedSeries, boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, isOutsideBounds, legendConfig, legendItems, preparedLegend, preparedSeries, preparedSeriesOptions, preparedSplit, prevHeight, prevWidth, shapes, shapesData, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
|
|
67
|
+
const { allPreparedSeries, boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, isOutsideBounds, legendConfig, legendItems, preparedLegend, preparedSeries, preparedSeriesOptions, preparedSplit, prevHeight, prevWidth, shapes, shapesData, shapesReady, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
|
|
68
68
|
dispatcher,
|
|
69
69
|
htmlLayout, plotNode: plotRef.current, preparedChart, rangeSliderDomain: (_a = rangeSliderRef.current) === null || _a === void 0 ? void 0 : _a.getDomain(), rangeSliderState, svgContainer: svgRef.current, updateZoomState,
|
|
70
70
|
zoomState }));
|
|
@@ -160,18 +160,29 @@ export const ChartInner = (props) => {
|
|
|
160
160
|
if (axis && scale) {
|
|
161
161
|
const axisData = await prepareXAxisData({
|
|
162
162
|
axis,
|
|
163
|
-
yAxis,
|
|
164
|
-
scale,
|
|
165
|
-
boundsWidth,
|
|
166
163
|
boundsOffsetLeft: boundsOffsetLeft,
|
|
167
164
|
boundsOffsetRight: width - boundsWidth - boundsOffsetLeft,
|
|
165
|
+
boundsWidth,
|
|
168
166
|
height: boundsHeight,
|
|
167
|
+
scale,
|
|
168
|
+
series: preparedSeries.filter((s) => s.visible),
|
|
169
169
|
split: preparedSplit,
|
|
170
|
+
yAxis,
|
|
170
171
|
});
|
|
171
172
|
items.push(...axisData);
|
|
172
173
|
}
|
|
173
174
|
return items;
|
|
174
|
-
}, [
|
|
175
|
+
}, [
|
|
176
|
+
boundsHeight,
|
|
177
|
+
boundsOffsetLeft,
|
|
178
|
+
boundsWidth,
|
|
179
|
+
preparedSeries,
|
|
180
|
+
preparedSplit,
|
|
181
|
+
width,
|
|
182
|
+
xAxis,
|
|
183
|
+
xScale,
|
|
184
|
+
yAxis,
|
|
185
|
+
]);
|
|
175
186
|
const xAxisDataItems = useAsyncState([], setXAxisDataItems);
|
|
176
187
|
React.useEffect(() => {
|
|
177
188
|
if (!initialized && xScale) {
|
|
@@ -207,12 +218,11 @@ export const ChartInner = (props) => {
|
|
|
207
218
|
updateRangeSliderState,
|
|
208
219
|
xScale,
|
|
209
220
|
]);
|
|
210
|
-
const areShapesReady = shapes.length > 0;
|
|
211
221
|
React.useEffect(() => {
|
|
212
|
-
if (
|
|
222
|
+
if (shapesReady) {
|
|
213
223
|
onReady === null || onReady === void 0 ? void 0 : onReady({ dimensions: { width, height } });
|
|
214
224
|
}
|
|
215
|
-
}, [height,
|
|
225
|
+
}, [height, shapesReady, onReady, width]);
|
|
216
226
|
const chartContent = (React.createElement(React.Fragment, null,
|
|
217
227
|
React.createElement("defs", null,
|
|
218
228
|
React.createElement("clipPath", { id: getClipPathIdByBounds({ clipPathId }) },
|
|
@@ -44,6 +44,7 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
44
44
|
prevWidth: number | undefined;
|
|
45
45
|
shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
|
|
46
46
|
shapesData: import("../../hooks").ShapeData[];
|
|
47
|
+
shapesReady: boolean;
|
|
47
48
|
svgXPos: number | undefined;
|
|
48
49
|
xAxis: import("../../hooks").PreparedXAxis | null;
|
|
49
50
|
xScale: import("../../hooks").ChartScale | undefined;
|
|
@@ -111,7 +111,7 @@ export function useChartInnerProps(props) {
|
|
|
111
111
|
const isOutsideBounds = React.useCallback((x, y) => {
|
|
112
112
|
return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
|
|
113
113
|
}, [boundsHeight, boundsWidth]);
|
|
114
|
-
const { shapes, shapesData } = useShapes({
|
|
114
|
+
const { shapes, shapesData, shapesReady } = useShapes({
|
|
115
115
|
boundsWidth,
|
|
116
116
|
boundsHeight,
|
|
117
117
|
clipPathBySeriesType: CLIP_PATH_BY_SERIES_TYPE,
|
|
@@ -183,6 +183,7 @@ export function useChartInnerProps(props) {
|
|
|
183
183
|
prevWidth,
|
|
184
184
|
shapes,
|
|
185
185
|
shapesData,
|
|
186
|
+
shapesReady,
|
|
186
187
|
svgXPos: x,
|
|
187
188
|
xAxis,
|
|
188
189
|
xScale,
|
|
@@ -15,7 +15,7 @@ async function setLabelSettings({ axis, seriesData, width, axisLabels, }) {
|
|
|
15
15
|
}
|
|
16
16
|
const getTextSize = getTextSizeFn({ style: axis.labels.style });
|
|
17
17
|
const labelLineHeight = (await getTextSize('Tmp')).height;
|
|
18
|
-
const tickValues = getXAxisTickValues({ axis, scale, labelLineHeight });
|
|
18
|
+
const tickValues = getXAxisTickValues({ axis, scale, labelLineHeight, series: seriesData });
|
|
19
19
|
const tickStep = getMinSpaceBetween(tickValues, (d) => Number(d.value));
|
|
20
20
|
if (axis.type === 'datetime' && !(axisLabels === null || axisLabels === void 0 ? void 0 : axisLabels.dateFormat)) {
|
|
21
21
|
axis.labels.dateFormat = getDefaultDateFormat(tickStep);
|
|
@@ -94,11 +94,13 @@ export const prepareAreaData = async (args) => {
|
|
|
94
94
|
const positiveStackValues = new Map();
|
|
95
95
|
const negativeStackValues = new Map();
|
|
96
96
|
xValues.forEach(([key]) => {
|
|
97
|
-
positiveStackValues.set(key, 0);
|
|
98
|
-
negativeStackValues.set(key, 0);
|
|
97
|
+
positiveStackValues.set(key, { prev: 0, next: 0 });
|
|
98
|
+
negativeStackValues.set(key, { prev: 0, next: 0 });
|
|
99
99
|
});
|
|
100
100
|
const seriesStackData = [];
|
|
101
|
-
|
|
101
|
+
// Process series in reverse order so that the first series in input
|
|
102
|
+
// appears at the top of the stack (furthest from baseline)
|
|
103
|
+
for (let j = seriesStack.length - 1; j >= 0; j--) {
|
|
102
104
|
const s = seriesStack[j];
|
|
103
105
|
const yAxisIndex = s.yAxis;
|
|
104
106
|
const seriesYAxis = yAxis[yAxisIndex];
|
|
@@ -123,40 +125,97 @@ export const prepareAreaData = async (args) => {
|
|
|
123
125
|
: d.x);
|
|
124
126
|
return m.set(key, d);
|
|
125
127
|
}, new Map());
|
|
126
|
-
const points = xValues.reduce((pointsAcc, [x, xValue]) => {
|
|
127
|
-
var _a, _b;
|
|
128
|
+
const points = xValues.reduce((pointsAcc, [x, xValue], index) => {
|
|
129
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
128
130
|
const d = (_a = seriesData.get(x)) !== null && _a !== void 0 ? _a : {
|
|
129
131
|
x,
|
|
130
132
|
y: 0,
|
|
131
133
|
};
|
|
132
134
|
const yDataValue = (_b = d.y) !== null && _b !== void 0 ? _b : null;
|
|
135
|
+
if (s.nullMode === 'connect' && yDataValue === null) {
|
|
136
|
+
return pointsAcc;
|
|
137
|
+
}
|
|
133
138
|
const yValue = getYValue({ point: d, yAxis: seriesYAxis, yScale: seriesYScale });
|
|
134
|
-
let y = null;
|
|
135
|
-
let y0 = yAxisTop + yMin;
|
|
136
139
|
if (typeof yDataValue === 'number' && yValue !== null) {
|
|
140
|
+
const prevPoint = seriesData.get((_c = xValues[index - 1]) === null || _c === void 0 ? void 0 : _c[0]);
|
|
141
|
+
const nextPoint = seriesData.get((_d = xValues[index + 1]) === null || _d === void 0 ? void 0 : _d[0]);
|
|
142
|
+
const currentPointStackHeight = Math.abs(yMin - yValue);
|
|
137
143
|
if (yDataValue >= 0) {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
const positiveStackHeights = positiveStackValues.get(x);
|
|
145
|
+
let prevSectionStackHeight = (_e = positiveStackHeights === null || positiveStackHeights === void 0 ? void 0 : positiveStackHeights.prev) !== null && _e !== void 0 ? _e : 0;
|
|
146
|
+
let nextSectionStackHeight = (_f = positiveStackHeights === null || positiveStackHeights === void 0 ? void 0 : positiveStackHeights.next) !== null && _f !== void 0 ? _f : 0;
|
|
147
|
+
pointsAcc.push({
|
|
148
|
+
y0: yAxisTop + yMin - prevSectionStackHeight,
|
|
149
|
+
x: xValue,
|
|
150
|
+
y: yAxisTop + yValue - prevSectionStackHeight,
|
|
151
|
+
data: d,
|
|
152
|
+
series: s,
|
|
153
|
+
});
|
|
154
|
+
if (prevSectionStackHeight !== nextSectionStackHeight) {
|
|
155
|
+
pointsAcc.push({
|
|
156
|
+
y0: yAxisTop + yMin - nextSectionStackHeight,
|
|
157
|
+
x: xValue,
|
|
158
|
+
y: yAxisTop + yValue - nextSectionStackHeight,
|
|
159
|
+
data: d,
|
|
160
|
+
series: s,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if ((prevPoint === null || prevPoint === void 0 ? void 0 : prevPoint.y) !== null) {
|
|
164
|
+
prevSectionStackHeight =
|
|
165
|
+
prevSectionStackHeight + currentPointStackHeight;
|
|
166
|
+
}
|
|
167
|
+
if ((nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.y) !== null) {
|
|
168
|
+
nextSectionStackHeight =
|
|
169
|
+
nextSectionStackHeight + currentPointStackHeight;
|
|
170
|
+
}
|
|
171
|
+
positiveStackValues.set(x, {
|
|
172
|
+
prev: prevSectionStackHeight,
|
|
173
|
+
next: nextSectionStackHeight,
|
|
174
|
+
});
|
|
142
175
|
}
|
|
143
176
|
else {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
177
|
+
const negativeStackHeights = negativeStackValues.get(x);
|
|
178
|
+
let prevSectionStackHeight = (_g = negativeStackHeights === null || negativeStackHeights === void 0 ? void 0 : negativeStackHeights.prev) !== null && _g !== void 0 ? _g : 0;
|
|
179
|
+
let nextSectionStackHeight = (_h = negativeStackHeights === null || negativeStackHeights === void 0 ? void 0 : negativeStackHeights.next) !== null && _h !== void 0 ? _h : 0;
|
|
180
|
+
pointsAcc.push({
|
|
181
|
+
y0: yAxisTop + yMin + prevSectionStackHeight,
|
|
182
|
+
x: xValue,
|
|
183
|
+
y: yAxisTop + yValue + prevSectionStackHeight,
|
|
184
|
+
data: d,
|
|
185
|
+
series: s,
|
|
186
|
+
});
|
|
187
|
+
if (prevSectionStackHeight !== nextSectionStackHeight) {
|
|
188
|
+
pointsAcc.push({
|
|
189
|
+
y0: yAxisTop + yMin + nextSectionStackHeight,
|
|
190
|
+
x: xValue,
|
|
191
|
+
y: yAxisTop + yValue + nextSectionStackHeight,
|
|
192
|
+
data: d,
|
|
193
|
+
series: s,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if ((prevPoint === null || prevPoint === void 0 ? void 0 : prevPoint.y) !== null) {
|
|
197
|
+
prevSectionStackHeight =
|
|
198
|
+
prevSectionStackHeight + currentPointStackHeight;
|
|
199
|
+
}
|
|
200
|
+
if ((nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.y) !== null) {
|
|
201
|
+
nextSectionStackHeight =
|
|
202
|
+
nextSectionStackHeight + currentPointStackHeight;
|
|
203
|
+
}
|
|
204
|
+
negativeStackValues.set(x, {
|
|
205
|
+
prev: prevSectionStackHeight,
|
|
206
|
+
next: nextSectionStackHeight,
|
|
207
|
+
});
|
|
148
208
|
}
|
|
149
209
|
}
|
|
150
|
-
|
|
151
|
-
|
|
210
|
+
else {
|
|
211
|
+
pointsAcc.push({
|
|
212
|
+
y0: yAxisTop + yMin,
|
|
213
|
+
x: xValue,
|
|
214
|
+
y: null,
|
|
215
|
+
data: d,
|
|
216
|
+
series: s,
|
|
217
|
+
});
|
|
152
218
|
}
|
|
153
|
-
pointsAcc.push({
|
|
154
|
-
y0,
|
|
155
|
-
x: xValue,
|
|
156
|
-
y,
|
|
157
|
-
data: d,
|
|
158
|
-
series: s,
|
|
159
|
-
});
|
|
160
219
|
return pointsAcc;
|
|
161
220
|
}, []);
|
|
162
221
|
const labels = [];
|
|
@@ -197,7 +256,8 @@ export const prepareAreaData = async (args) => {
|
|
|
197
256
|
}
|
|
198
257
|
if (series.some((s) => s.stacking === 'percent')) {
|
|
199
258
|
xValues.forEach(([x], index) => {
|
|
200
|
-
|
|
259
|
+
var _a;
|
|
260
|
+
const stackHeight = ((_a = positiveStackValues.get(x)) === null || _a === void 0 ? void 0 : _a.prev) || 0;
|
|
201
261
|
let acc = 0;
|
|
202
262
|
const ratio = plotHeight / stackHeight;
|
|
203
263
|
seriesStackData.forEach((item) => {
|
|
@@ -34,6 +34,7 @@ export const useShapes = (args) => {
|
|
|
34
34
|
const { boundsWidth, boundsHeight, clipPathId, clipPathBySeriesType, dispatcher, htmlLayout, isOutsideBounds = IS_OUTSIDE_BOUNDS, isRangeSlider, series, seriesOptions, split, xAxis, xScale, yAxis, yScale, zoomState, } = args;
|
|
35
35
|
const [shapesElemens, setShapesElements] = React.useState([]);
|
|
36
36
|
const [shapesElemensData, setShapesElemensData] = React.useState([]);
|
|
37
|
+
const shapesReadyRef = React.useRef(false);
|
|
37
38
|
const countedRef = React.useRef(0);
|
|
38
39
|
React.useEffect(() => {
|
|
39
40
|
countedRef.current++;
|
|
@@ -45,7 +46,7 @@ export const useShapes = (args) => {
|
|
|
45
46
|
const shapes = [];
|
|
46
47
|
await Promise.all(
|
|
47
48
|
// eslint-disable-next-line complexity
|
|
48
|
-
Array.from(groupedSeries).map(async (item) => {
|
|
49
|
+
Array.from(groupedSeries).map(async (item, index) => {
|
|
49
50
|
const [seriesType, chartSeries] = item;
|
|
50
51
|
switch (seriesType) {
|
|
51
52
|
case SERIES_TYPE.BarX: {
|
|
@@ -61,8 +62,8 @@ export const useShapes = (args) => {
|
|
|
61
62
|
split,
|
|
62
63
|
isRangeSlider,
|
|
63
64
|
});
|
|
64
|
-
shapes
|
|
65
|
-
shapesData.
|
|
65
|
+
shapes[index] = (React.createElement(BarXSeriesShapes, { key: SERIES_TYPE.BarX, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: clipPathId }));
|
|
66
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
66
67
|
}
|
|
67
68
|
break;
|
|
68
69
|
}
|
|
@@ -78,8 +79,8 @@ export const useShapes = (args) => {
|
|
|
78
79
|
yAxis,
|
|
79
80
|
yScale,
|
|
80
81
|
});
|
|
81
|
-
shapes
|
|
82
|
-
shapesData.
|
|
82
|
+
shapes[index] = (React.createElement(BarYSeriesShapes, { key: SERIES_TYPE.BarY, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: clipPathId }));
|
|
83
|
+
shapesData.splice(index, 0, ...preparedData.shapes);
|
|
83
84
|
}
|
|
84
85
|
break;
|
|
85
86
|
}
|
|
@@ -93,8 +94,8 @@ export const useShapes = (args) => {
|
|
|
93
94
|
yAxis,
|
|
94
95
|
yScale,
|
|
95
96
|
});
|
|
96
|
-
shapes
|
|
97
|
-
shapesData.
|
|
97
|
+
shapes[index] = (React.createElement(WaterfallSeriesShapes, { key: SERIES_TYPE.Waterfall, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: clipPathId }));
|
|
98
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
98
99
|
}
|
|
99
100
|
break;
|
|
100
101
|
}
|
|
@@ -115,8 +116,8 @@ export const useShapes = (args) => {
|
|
|
115
116
|
yAxis,
|
|
116
117
|
zoomState,
|
|
117
118
|
});
|
|
118
|
-
shapes
|
|
119
|
-
shapesData.
|
|
119
|
+
shapes[index] = (React.createElement(LineSeriesShapes, { key: SERIES_TYPE.Line, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: resultClipPathId }));
|
|
120
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
120
121
|
}
|
|
121
122
|
break;
|
|
122
123
|
}
|
|
@@ -133,8 +134,8 @@ export const useShapes = (args) => {
|
|
|
133
134
|
isOutsideBounds,
|
|
134
135
|
isRangeSlider,
|
|
135
136
|
});
|
|
136
|
-
shapes
|
|
137
|
-
shapesData.
|
|
137
|
+
shapes[index] = (React.createElement(AreaSeriesShapes, { key: SERIES_TYPE.Area, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: clipPathId }));
|
|
138
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
138
139
|
}
|
|
139
140
|
break;
|
|
140
141
|
}
|
|
@@ -148,10 +149,10 @@ export const useShapes = (args) => {
|
|
|
148
149
|
yScale,
|
|
149
150
|
isOutsideBounds,
|
|
150
151
|
});
|
|
151
|
-
shapes
|
|
152
|
+
shapes[index] = (React.createElement(ScatterSeriesShape, { key: SERIES_TYPE.Scatter, clipPathId: shouldUseClipPathId(SERIES_TYPE.Scatter, clipPathBySeriesType)
|
|
152
153
|
? clipPathId
|
|
153
154
|
: undefined, dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
154
|
-
shapesData.
|
|
155
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
155
156
|
}
|
|
156
157
|
break;
|
|
157
158
|
}
|
|
@@ -161,8 +162,8 @@ export const useShapes = (args) => {
|
|
|
161
162
|
boundsWidth,
|
|
162
163
|
boundsHeight,
|
|
163
164
|
});
|
|
164
|
-
shapes
|
|
165
|
-
shapesData.
|
|
165
|
+
shapes[index] = (React.createElement(PieSeriesShapes, { key: SERIES_TYPE.Pie, dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
166
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
166
167
|
break;
|
|
167
168
|
}
|
|
168
169
|
case SERIES_TYPE.Treemap: {
|
|
@@ -173,8 +174,8 @@ export const useShapes = (args) => {
|
|
|
173
174
|
width: boundsWidth,
|
|
174
175
|
height: boundsHeight,
|
|
175
176
|
});
|
|
176
|
-
shapes
|
|
177
|
-
shapesData.
|
|
177
|
+
shapes[index] = (React.createElement(TreemapSeriesShape, { key: SERIES_TYPE.Treemap, dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
178
|
+
shapesData.splice(index, 0, preparedData);
|
|
178
179
|
break;
|
|
179
180
|
}
|
|
180
181
|
case SERIES_TYPE.Sankey: {
|
|
@@ -183,8 +184,8 @@ export const useShapes = (args) => {
|
|
|
183
184
|
width: boundsWidth,
|
|
184
185
|
height: boundsHeight,
|
|
185
186
|
});
|
|
186
|
-
shapes
|
|
187
|
-
shapesData.
|
|
187
|
+
shapes[index] = (React.createElement(SankeySeriesShape, { key: SERIES_TYPE.Sankey, dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
188
|
+
shapesData.splice(index, 0, preparedData);
|
|
188
189
|
break;
|
|
189
190
|
}
|
|
190
191
|
case SERIES_TYPE.Radar: {
|
|
@@ -193,8 +194,8 @@ export const useShapes = (args) => {
|
|
|
193
194
|
boundsWidth,
|
|
194
195
|
boundsHeight,
|
|
195
196
|
});
|
|
196
|
-
shapes
|
|
197
|
-
shapesData.
|
|
197
|
+
shapes[index] = (React.createElement(RadarSeriesShapes, { key: SERIES_TYPE.Radar, dispatcher: dispatcher, series: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
198
|
+
shapesData.splice(index, 0, ...preparedData);
|
|
198
199
|
break;
|
|
199
200
|
}
|
|
200
201
|
case SERIES_TYPE.Heatmap: {
|
|
@@ -206,8 +207,8 @@ export const useShapes = (args) => {
|
|
|
206
207
|
yAxis: yAxis[0],
|
|
207
208
|
yScale: yScale[0],
|
|
208
209
|
});
|
|
209
|
-
shapes
|
|
210
|
-
shapesData.
|
|
210
|
+
shapes[index] = (React.createElement(HeatmapSeriesShapes, { key: SERIES_TYPE.Heatmap, dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
211
|
+
shapesData.splice(index, 0, preparedData);
|
|
211
212
|
}
|
|
212
213
|
break;
|
|
213
214
|
}
|
|
@@ -217,8 +218,8 @@ export const useShapes = (args) => {
|
|
|
217
218
|
boundsWidth,
|
|
218
219
|
boundsHeight,
|
|
219
220
|
});
|
|
220
|
-
shapes
|
|
221
|
-
shapesData.
|
|
221
|
+
shapes[index] = (React.createElement(FunnelSeriesShapes, { key: "funnel", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
222
|
+
shapesData.splice(index, 0, preparedData);
|
|
222
223
|
break;
|
|
223
224
|
}
|
|
224
225
|
default: {
|
|
@@ -229,6 +230,7 @@ export const useShapes = (args) => {
|
|
|
229
230
|
}
|
|
230
231
|
}));
|
|
231
232
|
if (countedRef.current === currentRun) {
|
|
233
|
+
shapesReadyRef.current = true;
|
|
232
234
|
setShapesElements(shapes);
|
|
233
235
|
setShapesElemensData(shapesData);
|
|
234
236
|
}
|
|
@@ -251,5 +253,9 @@ export const useShapes = (args) => {
|
|
|
251
253
|
yScale,
|
|
252
254
|
zoomState,
|
|
253
255
|
]);
|
|
254
|
-
return {
|
|
256
|
+
return {
|
|
257
|
+
shapes: shapesElemens,
|
|
258
|
+
shapesData: shapesElemensData,
|
|
259
|
+
shapesReady: shapesReadyRef.current,
|
|
260
|
+
};
|
|
255
261
|
};
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Global mocks for jsdom environment.
|
|
3
|
+
// Guarded by typeof checks so this file is safe to run in the `node` environment too.
|
|
4
|
+
if (typeof document !== 'undefined') {
|
|
5
|
+
// jsdom does not implement document.fonts
|
|
6
|
+
if (!document.fonts) {
|
|
7
|
+
Object.defineProperty(document, 'fonts', {
|
|
8
|
+
value: { ready: Promise.resolve() },
|
|
9
|
+
configurable: true,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (typeof HTMLCanvasElement !== 'undefined') {
|
|
14
|
+
// jsdom does not implement HTMLCanvasElement.prototype.getContext (used for text measurement)
|
|
15
|
+
HTMLCanvasElement.prototype.getContext = (() => ({
|
|
16
|
+
font: '',
|
|
17
|
+
measureText: () => ({ width: 0 }),
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
@@ -3,9 +3,9 @@ import type { ChartScale, PreparedAxis, PreparedAxisPlotBand, PreparedSplit } fr
|
|
|
3
3
|
import type { ChartAxis } from '../../../types';
|
|
4
4
|
import type { AxisDirection } from '../types';
|
|
5
5
|
type Ticks = number[] | string[] | Date[];
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function getTicksCountByPixelInterval({ axis, axisWidth, }: {
|
|
7
7
|
axis: PreparedAxis;
|
|
8
|
-
|
|
8
|
+
axisWidth: number;
|
|
9
9
|
}): number | undefined;
|
|
10
10
|
export declare function isBandScale(scale?: ChartScale | AxisScale<AxisDomain>): scale is ScaleBand<string>;
|
|
11
11
|
export declare function isTimeScale(scale?: ChartScale | AxisScale<AxisDomain>): scale is ScaleTime<number, number>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ascending, descending, reverse, sort } from 'd3';
|
|
2
2
|
import clamp from 'lodash/clamp';
|
|
3
|
-
export function
|
|
3
|
+
export function getTicksCountByPixelInterval({ axis, axisWidth, }) {
|
|
4
4
|
let ticksCount;
|
|
5
5
|
if (axis.ticks.pixelInterval) {
|
|
6
|
-
ticksCount = Math.ceil(
|
|
6
|
+
ticksCount = Math.ceil(axisWidth / axis.ticks.pixelInterval);
|
|
7
7
|
}
|
|
8
8
|
return ticksCount;
|
|
9
9
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type { ChartScale, PreparedAxis } from '../../../hooks';
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { ChartScale, PreparedAxis, PreparedSeries } from '../../../hooks';
|
|
2
|
+
import type { ChartSeries } from '../../../types';
|
|
3
|
+
type TickValue = {
|
|
4
|
+
x: number;
|
|
5
|
+
value: number | string | Date;
|
|
6
|
+
};
|
|
7
|
+
export declare function getXAxisTickValues({ axis, labelLineHeight, scale, series, }: {
|
|
4
8
|
axis: PreparedAxis;
|
|
5
9
|
labelLineHeight: number;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
x: number;
|
|
11
|
-
value: string;
|
|
12
|
-
}[];
|
|
10
|
+
scale: ChartScale;
|
|
11
|
+
series?: ChartSeries[] | PreparedSeries[];
|
|
12
|
+
}): TickValue[];
|
|
13
|
+
export {};
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
import { getMinSpaceBetween } from '../array';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { isSeriesWithNumericalXValues } from '../series-type-guards';
|
|
3
|
+
import { getTicksCountByPixelInterval, isBandScale, thinOut } from './common';
|
|
4
|
+
const DEFAULT_TICKS_COUNT = 10;
|
|
5
|
+
function getTicksCount(args) {
|
|
6
|
+
const { axis, axisWidth, series } = args;
|
|
7
|
+
const result = getTicksCountByPixelInterval({ axis, axisWidth });
|
|
8
|
+
if (typeof result === 'number') {
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
if (series) {
|
|
12
|
+
const xDataSet = new Set();
|
|
13
|
+
series === null || series === void 0 ? void 0 : series.forEach((item) => {
|
|
14
|
+
if (isSeriesWithNumericalXValues(item)) {
|
|
15
|
+
item.data.forEach((data) => {
|
|
16
|
+
xDataSet.add(data.x);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return xDataSet.size < DEFAULT_TICKS_COUNT ? xDataSet.size : DEFAULT_TICKS_COUNT;
|
|
21
|
+
}
|
|
22
|
+
return DEFAULT_TICKS_COUNT;
|
|
23
|
+
}
|
|
24
|
+
export function getXAxisTickValues({ axis, labelLineHeight, scale, series, }) {
|
|
4
25
|
if ('ticks' in scale && typeof scale.ticks === 'function') {
|
|
5
26
|
const range = scale.range();
|
|
6
27
|
const axisWidth = Math.abs(range[0] - range[1]);
|
|
7
28
|
if (!axisWidth) {
|
|
8
29
|
return [];
|
|
9
30
|
}
|
|
10
|
-
const scaleTicksCount = getTicksCount({ axis,
|
|
31
|
+
const scaleTicksCount = getTicksCount({ axis, axisWidth, series });
|
|
11
32
|
const scaleTicks = scale.ticks(scaleTicksCount);
|
|
12
33
|
const originalTickValues = scaleTicks.map((t) => ({
|
|
13
34
|
x: scale(t),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BaseTextStyle, ChartSeries, ChartSeriesData } from '../../types';
|
|
2
|
+
import type { UnknownSeries } from './series-type-guards';
|
|
2
3
|
import type { AxisDirection } from './types';
|
|
3
4
|
export * from './axis/common';
|
|
4
5
|
export * from './array';
|
|
@@ -8,41 +9,13 @@ export * from './labels';
|
|
|
8
9
|
export * from './legend';
|
|
9
10
|
export * from './math';
|
|
10
11
|
export * from './series';
|
|
12
|
+
export * from './series-type-guards';
|
|
11
13
|
export * from './symbol';
|
|
12
14
|
export * from './text';
|
|
13
15
|
export * from './time';
|
|
14
16
|
export * from './zoom';
|
|
15
17
|
export declare const CHART_SERIES_WITH_VOLUME_ON_Y_AXIS: ChartSeries['type'][];
|
|
16
18
|
export declare const CHART_SERIES_WITH_VOLUME_ON_X_AXIS: ChartSeries['type'][];
|
|
17
|
-
type UnknownSeries = {
|
|
18
|
-
type: ChartSeries['type'];
|
|
19
|
-
data: unknown;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Checks whether the series should be drawn with axes.
|
|
23
|
-
*
|
|
24
|
-
* @param series - The series object to check.
|
|
25
|
-
* @returns `true` if the series should be drawn with axes, `false` otherwise.
|
|
26
|
-
*/
|
|
27
|
-
export declare function isAxisRelatedSeries(series: UnknownSeries): boolean;
|
|
28
|
-
export declare function isSeriesWithNumericalXValues(series: UnknownSeries): series is {
|
|
29
|
-
type: ChartSeries['type'];
|
|
30
|
-
data: {
|
|
31
|
-
x: number;
|
|
32
|
-
}[];
|
|
33
|
-
};
|
|
34
|
-
export declare function isSeriesWithNumericalYValues(series: UnknownSeries): series is {
|
|
35
|
-
type: ChartSeries['type'];
|
|
36
|
-
data: {
|
|
37
|
-
y: number;
|
|
38
|
-
}[];
|
|
39
|
-
};
|
|
40
|
-
export declare function isSeriesWithCategoryValues(series: UnknownSeries): series is {
|
|
41
|
-
type: ChartSeries['type'];
|
|
42
|
-
data: {
|
|
43
|
-
category: string;
|
|
44
|
-
}[];
|
|
45
|
-
};
|
|
46
19
|
export declare const getDomainDataXBySeries: (series: UnknownSeries[]) => ({} | undefined)[];
|
|
47
20
|
export declare function getDefaultMaxXAxisValue(series: UnknownSeries[]): 0 | undefined;
|
|
48
21
|
export declare function getDefaultMinXAxisValue(series: UnknownSeries[]): number | undefined;
|