@gravity-ui/charts 1.26.0 → 1.27.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/AxisX/AxisX.d.ts +5 -20
- package/dist/cjs/components/AxisX/AxisX.js +167 -212
- package/dist/cjs/components/AxisX/prepare-axis-data.d.ts +10 -0
- package/dist/cjs/components/AxisX/prepare-axis-data.js +267 -0
- package/dist/cjs/components/AxisX/styles.css +7 -10
- package/dist/cjs/components/AxisX/types.d.ts +85 -0
- package/dist/cjs/components/AxisX/types.js +1 -0
- package/dist/cjs/components/AxisY/AxisY.js +9 -3
- package/dist/cjs/components/AxisY/prepare-axis-data.d.ts +1 -1
- package/dist/cjs/components/AxisY/prepare-axis-data.js +17 -81
- package/dist/cjs/components/AxisY/prepare-axis-title.d.ts +16 -0
- package/dist/cjs/components/AxisY/prepare-axis-title.js +149 -0
- package/dist/cjs/components/AxisY/types.d.ts +16 -4
- package/dist/cjs/components/AxisY/utils.js +1 -8
- package/dist/cjs/components/ChartInner/index.js +62 -50
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +7 -7
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +15 -20
- package/dist/cjs/components/ChartInner/useChartInnerState.d.ts +3 -2
- package/dist/cjs/components/ChartInner/useChartInnerState.js +23 -4
- package/dist/cjs/components/Legend/index.js +21 -14
- package/dist/cjs/components/RangeSlider/index.d.ts +5 -3
- package/dist/cjs/components/RangeSlider/index.js +36 -4
- package/dist/cjs/components/Title/index.js +2 -2
- package/dist/cjs/components/utils.d.ts +9 -0
- package/dist/cjs/components/utils.js +34 -0
- package/dist/cjs/constants/defaults/axis.js +1 -1
- package/dist/cjs/hooks/index.d.ts +0 -1
- package/dist/cjs/hooks/index.js +0 -1
- package/dist/cjs/hooks/useAxis/index.js +10 -0
- package/dist/cjs/hooks/useAxis/types.d.ts +3 -0
- package/dist/cjs/hooks/useAxis/x-axis.d.ts +2 -1
- package/dist/cjs/hooks/useAxis/x-axis.js +36 -28
- package/dist/cjs/hooks/useAxis/y-axis.js +38 -11
- package/dist/cjs/hooks/useAxisScales/index.d.ts +4 -1
- package/dist/cjs/hooks/useAxisScales/index.js +8 -7
- package/dist/cjs/hooks/useAxisScales/utils.d.ts +6 -0
- package/dist/cjs/hooks/useAxisScales/utils.js +17 -0
- package/dist/cjs/hooks/useChartDimensions/utils.js +7 -1
- package/dist/cjs/hooks/useNormalizedOriginalData/index.d.ts +1 -7
- package/dist/cjs/hooks/useRangeSlider/index.js +1 -2
- package/dist/cjs/hooks/useRangeSlider/types.d.ts +1 -3
- package/dist/cjs/hooks/useZoom/index.d.ts +1 -0
- package/dist/cjs/hooks/useZoom/index.js +12 -2
- package/dist/cjs/types/chart/axis.d.ts +45 -17
- package/dist/cjs/types/chart/title.d.ts +3 -0
- package/dist/{esm/utils/chart/axis.d.ts → cjs/utils/chart/axis/common.d.ts} +4 -16
- package/dist/{esm/utils/chart/axis.js → cjs/utils/chart/axis/common.js} +7 -40
- package/dist/cjs/utils/chart/axis/x-axis.d.ts +12 -0
- package/dist/cjs/utils/chart/axis/x-axis.js +78 -0
- package/dist/cjs/utils/chart/axis-generators/bottom.js +1 -1
- package/dist/cjs/utils/chart/index.d.ts +1 -1
- package/dist/cjs/utils/chart/index.js +1 -1
- package/dist/cjs/utils/chart/text.d.ts +0 -6
- package/dist/cjs/utils/chart/text.js +7 -19
- package/dist/esm/components/AxisX/AxisX.d.ts +5 -20
- package/dist/esm/components/AxisX/AxisX.js +167 -212
- package/dist/esm/components/AxisX/prepare-axis-data.d.ts +10 -0
- package/dist/esm/components/AxisX/prepare-axis-data.js +267 -0
- package/dist/esm/components/AxisX/styles.css +7 -10
- package/dist/esm/components/AxisX/types.d.ts +85 -0
- package/dist/esm/components/AxisX/types.js +1 -0
- package/dist/esm/components/AxisY/AxisY.js +9 -3
- package/dist/esm/components/AxisY/prepare-axis-data.d.ts +1 -1
- package/dist/esm/components/AxisY/prepare-axis-data.js +17 -81
- package/dist/esm/components/AxisY/prepare-axis-title.d.ts +16 -0
- package/dist/esm/components/AxisY/prepare-axis-title.js +149 -0
- package/dist/esm/components/AxisY/types.d.ts +16 -4
- package/dist/esm/components/AxisY/utils.js +1 -8
- package/dist/esm/components/ChartInner/index.js +62 -50
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +7 -7
- package/dist/esm/components/ChartInner/useChartInnerProps.js +15 -20
- package/dist/esm/components/ChartInner/useChartInnerState.d.ts +3 -2
- package/dist/esm/components/ChartInner/useChartInnerState.js +23 -4
- package/dist/esm/components/Legend/index.js +21 -14
- package/dist/esm/components/RangeSlider/index.d.ts +5 -3
- package/dist/esm/components/RangeSlider/index.js +36 -4
- package/dist/esm/components/Title/index.js +2 -2
- package/dist/esm/components/utils.d.ts +9 -0
- package/dist/esm/components/utils.js +34 -0
- package/dist/esm/constants/defaults/axis.js +1 -1
- package/dist/esm/hooks/index.d.ts +0 -1
- package/dist/esm/hooks/index.js +0 -1
- package/dist/esm/hooks/useAxis/index.js +10 -0
- package/dist/esm/hooks/useAxis/types.d.ts +3 -0
- package/dist/esm/hooks/useAxis/x-axis.d.ts +2 -1
- package/dist/esm/hooks/useAxis/x-axis.js +36 -28
- package/dist/esm/hooks/useAxis/y-axis.js +38 -11
- package/dist/esm/hooks/useAxisScales/index.d.ts +4 -1
- package/dist/esm/hooks/useAxisScales/index.js +8 -7
- package/dist/esm/hooks/useAxisScales/utils.d.ts +6 -0
- package/dist/esm/hooks/useAxisScales/utils.js +17 -0
- package/dist/esm/hooks/useChartDimensions/utils.js +7 -1
- package/dist/esm/hooks/useNormalizedOriginalData/index.d.ts +1 -7
- package/dist/esm/hooks/useRangeSlider/index.js +1 -2
- package/dist/esm/hooks/useRangeSlider/types.d.ts +1 -3
- package/dist/esm/hooks/useZoom/index.d.ts +1 -0
- package/dist/esm/hooks/useZoom/index.js +12 -2
- package/dist/esm/types/chart/axis.d.ts +45 -17
- package/dist/esm/types/chart/title.d.ts +3 -0
- package/dist/{cjs/utils/chart/axis.d.ts → esm/utils/chart/axis/common.d.ts} +4 -16
- package/dist/{cjs/utils/chart/axis.js → esm/utils/chart/axis/common.js} +7 -40
- package/dist/esm/utils/chart/axis/x-axis.d.ts +12 -0
- package/dist/esm/utils/chart/axis/x-axis.js +78 -0
- package/dist/esm/utils/chart/axis-generators/bottom.js +1 -1
- package/dist/esm/utils/chart/index.d.ts +1 -1
- package/dist/esm/utils/chart/index.js +1 -1
- package/dist/esm/utils/chart/text.d.ts +0 -6
- package/dist/esm/utils/chart/text.js +7 -19
- package/package.json +1 -1
- package/dist/cjs/hooks/useChartOptions/index.d.ts +0 -16
- package/dist/cjs/hooks/useChartOptions/index.js +0 -21
- package/dist/esm/hooks/useChartOptions/index.d.ts +0 -16
- package/dist/esm/hooks/useChartOptions/index.js +0 -21
|
@@ -6,17 +6,15 @@ 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
|
|
9
|
+
const getLegendItemLeftPosition = (args) => {
|
|
10
10
|
const { align, width, contentWidth } = args;
|
|
11
11
|
if (align === 'right') {
|
|
12
|
-
return
|
|
12
|
+
return width - contentWidth;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
return { left: width / 2 - contentWidth / 2 };
|
|
14
|
+
if (align === 'left') {
|
|
15
|
+
return 0;
|
|
19
16
|
}
|
|
17
|
+
return width / 2 - contentWidth / 2;
|
|
20
18
|
};
|
|
21
19
|
const getLegendPosition = (args) => {
|
|
22
20
|
const { offsetLeft, offsetTop, contentWidth, width } = args;
|
|
@@ -256,12 +254,11 @@ export const Legend = (props) => {
|
|
|
256
254
|
let left = 0;
|
|
257
255
|
switch (legend.justifyContent) {
|
|
258
256
|
case 'center': {
|
|
259
|
-
|
|
257
|
+
left = getLegendItemLeftPosition({
|
|
260
258
|
align: legend.align,
|
|
261
259
|
width: config.maxWidth,
|
|
262
260
|
contentWidth,
|
|
263
261
|
});
|
|
264
|
-
left = legendLinePostion.left;
|
|
265
262
|
legendWidth = config.maxWidth;
|
|
266
263
|
break;
|
|
267
264
|
}
|
|
@@ -296,11 +293,21 @@ export const Legend = (props) => {
|
|
|
296
293
|
legendTop = top;
|
|
297
294
|
}
|
|
298
295
|
else {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
296
|
+
let left = 0;
|
|
297
|
+
switch (legend.align) {
|
|
298
|
+
case 'right': {
|
|
299
|
+
left = config.offset.left + config.maxWidth - legend.width;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case 'left': {
|
|
303
|
+
left = config.offset.left;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case 'center': {
|
|
307
|
+
left = config.offset.left + config.maxWidth / 2 - legend.width / 2;
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
304
311
|
const { top } = getLegendPosition({
|
|
305
312
|
width: config.maxWidth,
|
|
306
313
|
contentWidth: legendWidth,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { RangeSliderProps } from '../../hooks';
|
|
3
3
|
import './styles.css';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export interface RangeSliderHandle {
|
|
5
|
+
getDomain: () => [number, number] | undefined;
|
|
6
|
+
resetState: () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const RangeSlider: React.MemoExoticComponent<React.ForwardRefExoticComponent<RangeSliderProps & React.RefAttributes<RangeSliderHandle>>>;
|
|
@@ -1,14 +1,46 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useUniqId } from '@gravity-ui/uikit';
|
|
3
3
|
import { useBrush, useRangeSlider } from '../../hooks';
|
|
4
|
-
import { block } from '../../utils';
|
|
4
|
+
import { block, isBandScale } from '../../utils';
|
|
5
|
+
import { getInitialRangeSliderState } from '../utils';
|
|
5
6
|
import { getFramedPath } from './utils';
|
|
6
7
|
import './styles.css';
|
|
7
8
|
const b = block('range-slider');
|
|
8
|
-
function RangeSliderComponent(props) {
|
|
9
|
+
function RangeSliderComponent(props, forwardedRef) {
|
|
10
|
+
const { onUpdate } = props;
|
|
9
11
|
const clipPathId = useUniqId();
|
|
10
|
-
const { brush, height, onBrushEnd, onOverlayClick, offsetLeft, offsetTop, preparedXAxis, preparedYAxis, selection, shapes, width, } = useRangeSlider(Object.assign(Object.assign({}, props), { clipPathId }));
|
|
12
|
+
const { brush, defaultRange, height, onBrushEnd, onOverlayClick, offsetLeft, offsetTop, preparedXAxis, preparedYAxis, selection, shapes, width, xScale, } = useRangeSlider(Object.assign(Object.assign({}, props), { clipPathId }));
|
|
11
13
|
const ref = React.useRef(null);
|
|
14
|
+
/*
|
|
15
|
+
* We use useImperativeHandle to expose methods to the parent component.
|
|
16
|
+
*
|
|
17
|
+
* This is necessary due to an architectural decision: all calculations for all data series
|
|
18
|
+
* (without zoom) are performed only within the RangeSlider component. This approach
|
|
19
|
+
* was chosen to avoid degrading performance for charts that don't use the slider —
|
|
20
|
+
* in that case, the extra computations simply don't happen.
|
|
21
|
+
*
|
|
22
|
+
* Methods:
|
|
23
|
+
* - getDomain: returns the current X-axis domain (for synchronization with zoom)
|
|
24
|
+
* - resetState: resets the slider state to its initial value (these calculations
|
|
25
|
+
* are only possible within the component since it has access to the prepared series data)
|
|
26
|
+
*/
|
|
27
|
+
React.useImperativeHandle(forwardedRef, () => ({
|
|
28
|
+
getDomain: () => {
|
|
29
|
+
if (!xScale || isBandScale(xScale)) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
return xScale.domain().map(Number);
|
|
33
|
+
},
|
|
34
|
+
resetState: () => {
|
|
35
|
+
if (xScale && !isBandScale(xScale)) {
|
|
36
|
+
const initialRangeSliderState = getInitialRangeSliderState({
|
|
37
|
+
xScale,
|
|
38
|
+
defaultRange,
|
|
39
|
+
});
|
|
40
|
+
onUpdate(initialRangeSliderState, false);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
}), [defaultRange, onUpdate, xScale]);
|
|
12
44
|
const areas = React.useMemo(() => {
|
|
13
45
|
if (!preparedXAxis || !(preparedYAxis === null || preparedYAxis === void 0 ? void 0 : preparedYAxis.length)) {
|
|
14
46
|
return [];
|
|
@@ -38,4 +70,4 @@ function RangeSliderComponent(props) {
|
|
|
38
70
|
React.createElement("g", { className: b('shapes') }, shapes),
|
|
39
71
|
React.createElement("rect", { height: height, className: b('clickable-overlay'), onClick: onOverlayClick, width: width, x: 0, y: 0 })));
|
|
40
72
|
}
|
|
41
|
-
export const RangeSlider = React.memo(RangeSliderComponent);
|
|
73
|
+
export const RangeSlider = React.memo(React.forwardRef(RangeSliderComponent));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export const Title = (props) => {
|
|
3
|
-
const { chartWidth, text, height, style } = props;
|
|
3
|
+
const { chartWidth, text, height, style, qa } = props;
|
|
4
4
|
return (React.createElement("text", { dx: chartWidth / 2, dy: height / 2, dominantBaseline: "middle", textAnchor: "middle", style: {
|
|
5
5
|
fill: style === null || style === void 0 ? void 0 : style.fontColor,
|
|
6
6
|
fontSize: style === null || style === void 0 ? void 0 : style.fontSize,
|
|
7
7
|
fontWeight: style === null || style === void 0 ? void 0 : style.fontWeight,
|
|
8
8
|
lineHeight: `${height}px`,
|
|
9
|
-
} },
|
|
9
|
+
}, "data-qa": qa },
|
|
10
10
|
React.createElement("tspan", { dangerouslySetInnerHTML: { __html: text } })));
|
|
11
11
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ChartScaleLinear, ChartScaleTime } from '../hooks';
|
|
2
|
+
import type { ChartAxisRangeSlider } from '../types';
|
|
3
|
+
export declare function getInitialRangeSliderState(args: {
|
|
4
|
+
xScale: ChartScaleLinear | ChartScaleTime;
|
|
5
|
+
defaultRange?: ChartAxisRangeSlider['defaultRange'];
|
|
6
|
+
}): {
|
|
7
|
+
min: number;
|
|
8
|
+
max: number;
|
|
9
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { duration } from '@gravity-ui/date-utils';
|
|
2
|
+
import { isTimeScale } from '../utils';
|
|
3
|
+
export function getInitialRangeSliderState(args) {
|
|
4
|
+
const { defaultRange, xScale } = args;
|
|
5
|
+
let minRange;
|
|
6
|
+
let maxRange;
|
|
7
|
+
if (isTimeScale(xScale)) {
|
|
8
|
+
const [minDomainMs, maxDomainMs] = xScale.domain().map(Number);
|
|
9
|
+
minRange = minDomainMs;
|
|
10
|
+
maxRange = maxDomainMs;
|
|
11
|
+
try {
|
|
12
|
+
if (defaultRange === null || defaultRange === void 0 ? void 0 : defaultRange.size) {
|
|
13
|
+
const durationMs = duration(defaultRange.size).asMilliseconds();
|
|
14
|
+
const minDefaultRangeMs = maxDomainMs - durationMs;
|
|
15
|
+
if (minDefaultRangeMs < maxDomainMs) {
|
|
16
|
+
minRange = minDefaultRangeMs;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (_a) { }
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const [minDomain, maxDomain] = xScale.domain();
|
|
24
|
+
minRange = minDomain;
|
|
25
|
+
maxRange = maxDomain;
|
|
26
|
+
if (typeof (defaultRange === null || defaultRange === void 0 ? void 0 : defaultRange.size) === 'number') {
|
|
27
|
+
const minDefaultRange = maxDomain - defaultRange.size;
|
|
28
|
+
if (minDefaultRange < maxDomain) {
|
|
29
|
+
minRange = minDefaultRange;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { min: minRange, max: maxRange };
|
|
34
|
+
}
|
|
@@ -4,7 +4,6 @@ export * from './useAxisScales';
|
|
|
4
4
|
export * from './useBrush';
|
|
5
5
|
export * from './useBrush/types';
|
|
6
6
|
export * from './useChartDimensions';
|
|
7
|
-
export * from './useChartOptions';
|
|
8
7
|
export * from './useChartOptions/types';
|
|
9
8
|
export * from './useCrosshair';
|
|
10
9
|
export * from './useNormalizedOriginalData';
|
package/dist/esm/hooks/index.js
CHANGED
|
@@ -4,7 +4,6 @@ export * from './useAxisScales';
|
|
|
4
4
|
export * from './useBrush';
|
|
5
5
|
export * from './useBrush/types';
|
|
6
6
|
export * from './useChartDimensions';
|
|
7
|
-
export * from './useChartOptions';
|
|
8
7
|
export * from './useChartOptions/types';
|
|
9
8
|
export * from './useCrosshair';
|
|
10
9
|
export * from './useNormalizedOriginalData';
|
|
@@ -14,9 +14,19 @@ export function useAxis(props) {
|
|
|
14
14
|
(async function () {
|
|
15
15
|
const currentRun = axesStateRunRef.current;
|
|
16
16
|
const seriesData = preparedSeries.filter((s) => s.visible);
|
|
17
|
+
const estimatedPreparedYAxis = await getPreparedYAxis({
|
|
18
|
+
height,
|
|
19
|
+
boundsHeight: height,
|
|
20
|
+
width,
|
|
21
|
+
seriesData,
|
|
22
|
+
yAxis,
|
|
23
|
+
});
|
|
24
|
+
const axesWidth = estimatedPreparedYAxis.reduce((acc, a) => acc + a.title.height + a.title.margin + a.labels.margin + a.labels.width, 0);
|
|
25
|
+
const estimatedBoundsWidth = width - (axesWidth + preparedChart.margin.left + preparedChart.margin.right);
|
|
17
26
|
const preparedXAxis = await getPreparedXAxis({
|
|
18
27
|
xAxis,
|
|
19
28
|
width,
|
|
29
|
+
boundsWidth: estimatedBoundsWidth,
|
|
20
30
|
seriesData,
|
|
21
31
|
});
|
|
22
32
|
let estimatedBoundsHeight = boundsHeight !== null && boundsHeight !== void 0 ? boundsHeight : height;
|
|
@@ -43,6 +43,9 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
|
|
|
43
43
|
style: BaseTextStyle;
|
|
44
44
|
align: ChartAxisTitleAlignment;
|
|
45
45
|
maxRowCount: number;
|
|
46
|
+
rotation: number;
|
|
47
|
+
maxWidth: number;
|
|
48
|
+
html: boolean;
|
|
46
49
|
};
|
|
47
50
|
min?: number;
|
|
48
51
|
grid: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ChartSeries, ChartXAxis } from '../../types';
|
|
2
2
|
import type { PreparedXAxis } from './types';
|
|
3
|
-
export declare const getPreparedXAxis: ({ xAxis, seriesData, width, }: {
|
|
3
|
+
export declare const getPreparedXAxis: ({ xAxis, seriesData, width, boundsWidth, }: {
|
|
4
4
|
xAxis?: ChartXAxis;
|
|
5
5
|
seriesData: ChartSeries[];
|
|
6
6
|
width: number;
|
|
7
|
+
boundsWidth: number;
|
|
7
8
|
}) => Promise<PreparedXAxis | null>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
2
|
import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
|
|
3
|
-
import { calculateCos, calculateNumericProperty, formatAxisTickLabel,
|
|
3
|
+
import { calculateCos, calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../../utils';
|
|
4
|
+
import { getXAxisTickValues } from '../../utils/chart/axis/x-axis';
|
|
4
5
|
import { createXScale } from '../useAxisScales';
|
|
5
6
|
import { getPreparedRangeSlider } from './range-slider';
|
|
6
7
|
import { prepareAxisPlotLabel } from './utils';
|
|
@@ -11,31 +12,31 @@ async function setLabelSettings({ axis, seriesData, width, autoRotation = true,
|
|
|
11
12
|
axis.labels.rotation = 0;
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
maxCount: getMaxTickCount({ width, axis }),
|
|
19
|
-
});
|
|
20
|
-
const step = getClosestPointsRange(axis, ticks);
|
|
15
|
+
const getTextSize = getTextSizeFn({ style: axis.labels.style });
|
|
16
|
+
const labelLineHeight = (await getTextSize('Tmp')).height;
|
|
17
|
+
const tickValues = getXAxisTickValues({ axis, scale, labelLineHeight });
|
|
18
|
+
const tickStep = getMinSpaceBetween(tickValues, (d) => Number(d.value));
|
|
21
19
|
if (axis.type === 'datetime' && !axis.labels.dateFormat) {
|
|
22
|
-
axis.labels.dateFormat = getDefaultDateFormat(
|
|
20
|
+
axis.labels.dateFormat = getDefaultDateFormat(tickStep);
|
|
23
21
|
}
|
|
24
|
-
const labels =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
22
|
+
const labels = tickValues.map((tick) => formatAxisTickLabel({
|
|
23
|
+
axis,
|
|
24
|
+
value: tick.value,
|
|
25
|
+
step: tickStep,
|
|
26
|
+
}));
|
|
27
|
+
const labelMaxWidth = tickValues.length > 1
|
|
28
|
+
? getMinSpaceBetween(tickValues, (d) => d.x) - axis.labels.padding * 2
|
|
29
|
+
: width;
|
|
30
|
+
const hasOverlappingLabels = async () => {
|
|
31
|
+
for (let i = 0; i < labels.length; i++) {
|
|
32
|
+
const size = await getTextSize(labels[i]);
|
|
33
|
+
if (size.width > labelMaxWidth) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
};
|
|
39
|
+
const overlapping = axis.labels.html ? false : await hasOverlappingLabels();
|
|
39
40
|
const defaultRotation = overlapping && autoRotation ? -45 : 0;
|
|
40
41
|
const rotation = axis.labels.html ? 0 : axis.labels.rotation || defaultRotation;
|
|
41
42
|
const labelsHeight = rotation || axis.labels.html
|
|
@@ -56,7 +57,7 @@ function getMaxPaddingBySeries({ series }) {
|
|
|
56
57
|
}
|
|
57
58
|
return 0.01;
|
|
58
59
|
}
|
|
59
|
-
export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
|
|
60
|
+
export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth, }) => {
|
|
60
61
|
var _a, _b, _c, _d, _e;
|
|
61
62
|
const hasAxisRelatedSeries = seriesData.some(isAxisRelatedSeries);
|
|
62
63
|
if (!hasAxisRelatedSeries) {
|
|
@@ -82,6 +83,10 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
|
|
|
82
83
|
? getHorizontalHtmlTextHeight({ text: 'Tmp', style: labelsStyle })
|
|
83
84
|
: getHorizontalSvgTextHeight({ text: 'Tmp', style: labelsStyle });
|
|
84
85
|
const shouldHideGrid = seriesData.some((s) => s.type === SERIES_TYPE.Heatmap);
|
|
86
|
+
const preparedRangeSlider = getPreparedRangeSlider({ xAxis });
|
|
87
|
+
const maxPadding = preparedRangeSlider.enabled
|
|
88
|
+
? 0
|
|
89
|
+
: get(xAxis, 'maxPadding', getMaxPaddingBySeries({ series: seriesData }));
|
|
85
90
|
const preparedXAxis = {
|
|
86
91
|
type: get(xAxis, 'type', 'linear'),
|
|
87
92
|
labels: {
|
|
@@ -109,10 +114,13 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
|
|
|
109
114
|
width: titleSize.maxWidth,
|
|
110
115
|
align: get(xAxis, 'title.align', xAxisTitleDefaults.align),
|
|
111
116
|
maxRowCount: get(xAxis, 'title.maxRowCount', xAxisTitleDefaults.maxRowCount),
|
|
117
|
+
rotation: 0,
|
|
118
|
+
maxWidth: Infinity,
|
|
119
|
+
html: false,
|
|
112
120
|
},
|
|
113
121
|
min: get(xAxis, 'min'),
|
|
114
122
|
max: get(xAxis, 'max'),
|
|
115
|
-
maxPadding
|
|
123
|
+
maxPadding,
|
|
116
124
|
grid: {
|
|
117
125
|
enabled: shouldHideGrid ? false : get(xAxis, 'grid.enabled', true),
|
|
118
126
|
},
|
|
@@ -154,12 +162,12 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
|
|
|
154
162
|
},
|
|
155
163
|
visible: get(xAxis, 'visible', true),
|
|
156
164
|
order: xAxis === null || xAxis === void 0 ? void 0 : xAxis.order,
|
|
157
|
-
rangeSlider:
|
|
165
|
+
rangeSlider: preparedRangeSlider,
|
|
158
166
|
};
|
|
159
167
|
await setLabelSettings({
|
|
160
168
|
axis: preparedXAxis,
|
|
161
169
|
seriesData,
|
|
162
|
-
width,
|
|
170
|
+
width: boundsWidth,
|
|
163
171
|
autoRotation: (_e = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _e === void 0 ? void 0 : _e.autoRotation,
|
|
164
172
|
});
|
|
165
173
|
return preparedXAxis;
|
|
@@ -43,6 +43,13 @@ function getMaxPaddingBySeries({ series }) {
|
|
|
43
43
|
}
|
|
44
44
|
return 0.05;
|
|
45
45
|
}
|
|
46
|
+
const VALID_Y_AXIS_TITLE_ROTATION = [0, -90, 90];
|
|
47
|
+
function getAxisTitleRotation(value, axisPosition) {
|
|
48
|
+
if (typeof value !== 'undefined' && VALID_Y_AXIS_TITLE_ROTATION.includes(value)) {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
return axisPosition === 'left' ? -90 : 90;
|
|
52
|
+
}
|
|
46
53
|
export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxis, }) => {
|
|
47
54
|
const axisByPlot = [];
|
|
48
55
|
const axisItems = yAxis || [{}];
|
|
@@ -50,8 +57,10 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
50
57
|
if (!hasAxisRelatedSeries) {
|
|
51
58
|
return Promise.resolve([]);
|
|
52
59
|
}
|
|
53
|
-
return Promise.all(
|
|
54
|
-
|
|
60
|
+
return Promise.all(
|
|
61
|
+
// eslint-disable-next-line complexity
|
|
62
|
+
axisItems.map(async (axisItem, axisIndex) => {
|
|
63
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
55
64
|
const plotIndex = get(axisItem, 'plotIndex', 0);
|
|
56
65
|
const firstPlotAxis = !axisByPlot[plotIndex];
|
|
57
66
|
if (firstPlotAxis) {
|
|
@@ -59,6 +68,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
59
68
|
}
|
|
60
69
|
axisByPlot[plotIndex].push(axisItem);
|
|
61
70
|
const defaultAxisPosition = firstPlotAxis ? 'left' : 'right';
|
|
71
|
+
const axisPosition = get(axisItem, 'position', defaultAxisPosition);
|
|
62
72
|
const axisSeriesData = seriesData.filter((s) => get(s, 'yAxis', 0) === axisIndex);
|
|
63
73
|
const labelsEnabled = get(axisItem, 'labels.enabled', true);
|
|
64
74
|
const labelsStyle = {
|
|
@@ -76,7 +86,21 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
76
86
|
style: titleStyle,
|
|
77
87
|
width: height,
|
|
78
88
|
})).slice(0, titleMaxRowsCount);
|
|
79
|
-
const
|
|
89
|
+
const titleRotation = getAxisTitleRotation((_a = axisItem.title) === null || _a === void 0 ? void 0 : _a.rotation, axisPosition);
|
|
90
|
+
const titleMaxWidth = titleRotation === 0
|
|
91
|
+
? calculateNumericProperty({
|
|
92
|
+
value: (_c = (_b = axisItem.title) === null || _b === void 0 ? void 0 : _b.maxWidth) !== null && _c !== void 0 ? _c : '20%',
|
|
93
|
+
base: width,
|
|
94
|
+
})
|
|
95
|
+
: calculateNumericProperty({
|
|
96
|
+
value: (_e = (_d = axisItem.title) === null || _d === void 0 ? void 0 : _d.maxWidth) !== null && _e !== void 0 ? _e : '100%',
|
|
97
|
+
base: height,
|
|
98
|
+
});
|
|
99
|
+
const titleSize = await getLabelsSize({
|
|
100
|
+
labels: [titleText],
|
|
101
|
+
style: titleStyle,
|
|
102
|
+
html: (_f = axisItem.title) === null || _f === void 0 ? void 0 : _f.html,
|
|
103
|
+
});
|
|
80
104
|
const axisType = get(axisItem, 'type', DEFAULT_AXIS_TYPE);
|
|
81
105
|
const shouldHideGrid = axisItem.visible === false ||
|
|
82
106
|
axisSeriesData.some((s) => s.type === SERIES_TYPE.Heatmap);
|
|
@@ -95,7 +119,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
95
119
|
width: 0,
|
|
96
120
|
height: 0,
|
|
97
121
|
lineHeight: labelsLineHeight,
|
|
98
|
-
maxWidth: (
|
|
122
|
+
maxWidth: (_h = calculateNumericProperty({ base: width, value: (_g = axisItem.labels) === null || _g === void 0 ? void 0 : _g.maxWidth })) !== null && _h !== void 0 ? _h : axisLabelsDefaults.maxWidth,
|
|
99
123
|
html: labelsHtml,
|
|
100
124
|
},
|
|
101
125
|
lineColor: get(axisItem, 'lineColor'),
|
|
@@ -105,29 +129,32 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
105
129
|
text: titleText,
|
|
106
130
|
margin: get(axisItem, 'title.margin', yAxisTitleDefaults.margin),
|
|
107
131
|
style: titleStyle,
|
|
108
|
-
width: titleSize.maxWidth,
|
|
132
|
+
width: Math.min(titleSize.maxWidth, titleMaxWidth !== null && titleMaxWidth !== void 0 ? titleMaxWidth : Infinity),
|
|
109
133
|
height: titleSize.maxHeight * estimatedTitleRows.length,
|
|
110
134
|
align: get(axisItem, 'title.align', yAxisTitleDefaults.align),
|
|
111
135
|
maxRowCount: titleMaxRowsCount,
|
|
136
|
+
html: (_k = (_j = axisItem.title) === null || _j === void 0 ? void 0 : _j.html) !== null && _k !== void 0 ? _k : false,
|
|
137
|
+
maxWidth: titleMaxWidth !== null && titleMaxWidth !== void 0 ? titleMaxWidth : Infinity,
|
|
138
|
+
rotation: titleRotation,
|
|
112
139
|
},
|
|
113
|
-
min: (
|
|
140
|
+
min: (_l = get(axisItem, 'min')) !== null && _l !== void 0 ? _l : getDefaultMinYAxisValue(axisSeriesData),
|
|
114
141
|
max: get(axisItem, 'max'),
|
|
115
142
|
maxPadding: get(axisItem, 'maxPadding', getMaxPaddingBySeries({ series: axisSeriesData })),
|
|
116
143
|
grid: {
|
|
117
144
|
enabled: shouldHideGrid
|
|
118
145
|
? false
|
|
119
146
|
: get(axisItem, 'grid.enabled', firstPlotAxis ||
|
|
120
|
-
(!firstPlotAxis && !((
|
|
147
|
+
(!firstPlotAxis && !((_m = axisByPlot[plotIndex][0].visible) !== null && _m !== void 0 ? _m : true))),
|
|
121
148
|
},
|
|
122
149
|
ticks: {
|
|
123
|
-
pixelInterval: ((
|
|
150
|
+
pixelInterval: ((_o = axisItem.ticks) === null || _o === void 0 ? void 0 : _o.interval)
|
|
124
151
|
? calculateNumericProperty({
|
|
125
152
|
base: height,
|
|
126
|
-
value: (
|
|
153
|
+
value: (_p = axisItem.ticks) === null || _p === void 0 ? void 0 : _p.interval,
|
|
127
154
|
})
|
|
128
|
-
: (
|
|
155
|
+
: (_q = axisItem.ticks) === null || _q === void 0 ? void 0 : _q.pixelInterval,
|
|
129
156
|
},
|
|
130
|
-
position:
|
|
157
|
+
position: axisPosition,
|
|
131
158
|
plotIndex: get(axisItem, 'plotIndex', 0),
|
|
132
159
|
plotLines: get(axisItem, 'plotLines', []).map((d) => ({
|
|
133
160
|
value: get(d, 'value', 0),
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
2
|
import type { PreparedAxis, PreparedSeries, PreparedSplit, RangeSliderState, ZoomState } from '../../hooks';
|
|
3
3
|
import type { ChartAxis, ChartSeries } from '../../types';
|
|
4
|
-
|
|
4
|
+
type ChartScaleBand = ScaleBand<string>;
|
|
5
|
+
export type ChartScaleLinear = ScaleLinear<number, number>;
|
|
6
|
+
export type ChartScaleTime = ScaleTime<number, number>;
|
|
7
|
+
export type ChartScale = ChartScaleBand | ChartScaleLinear | ChartScaleTime;
|
|
5
8
|
type Args = {
|
|
6
9
|
boundsWidth: number;
|
|
7
10
|
boundsHeight: number;
|
|
@@ -4,7 +4,7 @@ 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
6
|
import { getBandSize } from '../utils/get-band-size';
|
|
7
|
-
import { checkIsPointDomain, getMinMaxPropsOrState, hasOnlyMarkerSeries } from './utils';
|
|
7
|
+
import { checkIsPointDomain, getMinMaxPropsOrState, getXMaxDomainResult, hasOnlyMarkerSeries, } from './utils';
|
|
8
8
|
const X_AXIS_ZOOM_PADDING = 0.02;
|
|
9
9
|
function validateArrayData(data) {
|
|
10
10
|
let hasNumberAndNullValues;
|
|
@@ -242,7 +242,7 @@ export function createXScale(args) {
|
|
|
242
242
|
order: axis.order,
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
|
-
const maxPadding =
|
|
245
|
+
const maxPadding = get(axis, 'maxPadding', 0);
|
|
246
246
|
const xAxisMaxPadding = boundsWidth * maxPadding + calculateXAxisPadding(series);
|
|
247
247
|
const range = getXScaleRange({
|
|
248
248
|
boundsWidth,
|
|
@@ -350,11 +350,12 @@ export function createXScale(args) {
|
|
|
350
350
|
!isPointDomain
|
|
351
351
|
? xMinPropsOrState
|
|
352
352
|
: xMinTimestamp;
|
|
353
|
-
const xMax =
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
?
|
|
357
|
-
:
|
|
353
|
+
const xMax = getXMaxDomainResult({
|
|
354
|
+
xMaxDomain: xMaxTimestamp,
|
|
355
|
+
xMaxProps: get(axis, 'max'),
|
|
356
|
+
xMaxRangeSlider: rangeSliderState === null || rangeSliderState === void 0 ? void 0 : rangeSliderState.max,
|
|
357
|
+
xMaxZoom: zoomStateX === null || zoomStateX === void 0 ? void 0 : zoomStateX[1],
|
|
358
|
+
});
|
|
358
359
|
domain = [xMin, xMax];
|
|
359
360
|
const scale = scaleUtc().domain(domain).range(range);
|
|
360
361
|
let offsetMin = 0;
|
|
@@ -16,4 +16,10 @@ export declare function getMinMaxPropsOrState(args: {
|
|
|
16
16
|
*/
|
|
17
17
|
export declare function checkIsPointDomain(domain: [number, number]): boolean;
|
|
18
18
|
export declare function hasOnlyMarkerSeries(series: (PreparedSeries | ChartSeries)[]): boolean;
|
|
19
|
+
export declare function getXMaxDomainResult(args: {
|
|
20
|
+
xMaxDomain: number;
|
|
21
|
+
xMaxProps?: number;
|
|
22
|
+
xMaxRangeSlider?: number;
|
|
23
|
+
xMaxZoom?: number;
|
|
24
|
+
}): number;
|
|
19
25
|
export {};
|
|
@@ -32,3 +32,20 @@ export function checkIsPointDomain(domain) {
|
|
|
32
32
|
export function hasOnlyMarkerSeries(series) {
|
|
33
33
|
return series.every((s) => MARKER_SERIES_TYPES.includes(s.type));
|
|
34
34
|
}
|
|
35
|
+
export function getXMaxDomainResult(args) {
|
|
36
|
+
const { xMaxDomain, xMaxProps, xMaxRangeSlider, xMaxZoom } = args;
|
|
37
|
+
let xMaxDomainResult = xMaxDomain;
|
|
38
|
+
// When xMaxRangeSlider is provided, we use it directly without considering xMaxDomain.
|
|
39
|
+
// This is intentional: the range slider needs to display the chart's maxPadding area,
|
|
40
|
+
// which would be clipped if we constrained it to xMaxDomain.
|
|
41
|
+
if (typeof xMaxRangeSlider === 'number') {
|
|
42
|
+
xMaxDomainResult = xMaxRangeSlider;
|
|
43
|
+
}
|
|
44
|
+
else if (typeof xMaxZoom === 'number' && xMaxZoom < xMaxDomain) {
|
|
45
|
+
xMaxDomainResult = xMaxZoom;
|
|
46
|
+
}
|
|
47
|
+
else if (typeof xMaxProps === 'number' && xMaxProps < xMaxDomain) {
|
|
48
|
+
xMaxDomainResult = xMaxProps;
|
|
49
|
+
}
|
|
50
|
+
return xMaxDomainResult;
|
|
51
|
+
}
|
|
@@ -11,7 +11,13 @@ export function getYAxisWidth(axis) {
|
|
|
11
11
|
}
|
|
12
12
|
let result = 0;
|
|
13
13
|
if (axis === null || axis === void 0 ? void 0 : axis.title.text) {
|
|
14
|
-
result += axis.title.
|
|
14
|
+
result += axis.title.margin;
|
|
15
|
+
if (axis.title.rotation === 0) {
|
|
16
|
+
result += axis.title.width;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
result += axis.title.height;
|
|
20
|
+
}
|
|
15
21
|
}
|
|
16
22
|
if (axis === null || axis === void 0 ? void 0 : axis.labels.enabled) {
|
|
17
23
|
result += axis.labels.margin + axis.labels.width;
|
|
@@ -14,13 +14,7 @@ export declare function useNormalizedOriginalData(props: UseOriginalDataProps):
|
|
|
14
14
|
type?: import("../..").ChartAxisType;
|
|
15
15
|
labels?: import("../..").ChartAxisLabels;
|
|
16
16
|
lineColor?: string;
|
|
17
|
-
title?:
|
|
18
|
-
text?: string;
|
|
19
|
-
style?: Partial<import("../..").BaseTextStyle>;
|
|
20
|
-
margin?: number;
|
|
21
|
-
align?: import("../..").ChartAxisTitleAlignment;
|
|
22
|
-
maxRowCount?: number;
|
|
23
|
-
};
|
|
17
|
+
title?: import("../..").ChartAxisTitle;
|
|
24
18
|
min?: number;
|
|
25
19
|
max?: number;
|
|
26
20
|
grid?: {
|
|
@@ -17,7 +17,7 @@ const CLIP_PATH_BY_SERIES_TYPE = {
|
|
|
17
17
|
[SERIES_TYPE.Scatter]: true,
|
|
18
18
|
};
|
|
19
19
|
export function useRangeSlider(props) {
|
|
20
|
-
const { boundsWidth, boundsOffsetLeft, clipPathId, height, htmlLayout, onUpdate, preparedChart, preparedLegend, preparedSeries, preparedSeriesOptions, preparedRangeSlider, rangeSliderState, width, xAxis, yAxis,
|
|
20
|
+
const { boundsWidth, boundsOffsetLeft, clipPathId, height, htmlLayout, onUpdate, preparedChart, preparedLegend, preparedSeries, preparedSeriesOptions, preparedRangeSlider, rangeSliderState, width, xAxis, yAxis, } = props;
|
|
21
21
|
const filteredPreparedSeries = React.useMemo(() => {
|
|
22
22
|
return preparedSeries.filter((s) => {
|
|
23
23
|
if ('rangeSlider' in s && !s.rangeSlider.visible) {
|
|
@@ -44,7 +44,6 @@ export function useRangeSlider(props) {
|
|
|
44
44
|
split: EMPTY_PREPARED_SPLIT,
|
|
45
45
|
xAxis: preparedXAxis,
|
|
46
46
|
yAxis: preparedYAxis,
|
|
47
|
-
zoomState,
|
|
48
47
|
});
|
|
49
48
|
const { shapes } = useShapes({
|
|
50
49
|
boundsHeight: preparedRangeSlider.height,
|
|
@@ -4,7 +4,6 @@ import type { ChartScale } from '../useAxisScales';
|
|
|
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';
|
|
7
|
-
import type { ZoomState } from '../useZoom/types';
|
|
8
7
|
export type RangeSliderState = {
|
|
9
8
|
max: number;
|
|
10
9
|
min: number;
|
|
@@ -14,7 +13,7 @@ export interface RangeSliderProps {
|
|
|
14
13
|
boundsWidth: number;
|
|
15
14
|
height: number;
|
|
16
15
|
htmlLayout: HTMLElement | null;
|
|
17
|
-
onUpdate: (nextRangeSliderState?: RangeSliderState) => void;
|
|
16
|
+
onUpdate: (nextRangeSliderState?: RangeSliderState, syncZoom?: boolean) => void;
|
|
18
17
|
preparedChart: PreparedChart;
|
|
19
18
|
preparedLegend: PreparedLegend | null;
|
|
20
19
|
preparedRangeSlider: PreparedRangeSlider;
|
|
@@ -24,7 +23,6 @@ export interface RangeSliderProps {
|
|
|
24
23
|
rangeSliderState?: RangeSliderState;
|
|
25
24
|
xAxis?: ChartXAxis;
|
|
26
25
|
yAxis?: ChartYAxis[];
|
|
27
|
-
zoomState?: Partial<ZoomState>;
|
|
28
26
|
}
|
|
29
27
|
export interface UseRangeSliderProps extends RangeSliderProps {
|
|
30
28
|
clipPathId: string;
|