mirror of
https://github.com/grafana/grafana.git
synced 2025-01-10 08:03:58 -06:00
Update dependency rc-slider to v10 (#49242)
* Update dependency rc-slider to v10 * start migrating to rc-slider 10 * rc-slider 10 changes * fix Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
parent
d7f9093ccd
commit
9e25cf7e12
@ -351,7 +351,7 @@
|
||||
"pseudoizer": "^0.1.0",
|
||||
"rc-cascader": "3.7.0",
|
||||
"rc-drawer": "4.4.3",
|
||||
"rc-slider": "9.7.5",
|
||||
"rc-slider": "10.0.1",
|
||||
"rc-time-picker": "3.7.3",
|
||||
"rc-tree": "5.7.0",
|
||||
"re-resizable": "6.9.9",
|
||||
|
@ -80,8 +80,9 @@
|
||||
"prismjs": "1.29.0",
|
||||
"rc-cascader": "3.7.0",
|
||||
"rc-drawer": "4.4.3",
|
||||
"rc-slider": "9.7.5",
|
||||
"rc-slider": "10.0.1",
|
||||
"rc-time-picker": "^3.7.3",
|
||||
"rc-tooltip": "5.2.2",
|
||||
"react-beautiful-dnd": "13.1.0",
|
||||
"react-calendar": "3.9.0",
|
||||
"react-colorful": "5.6.1",
|
||||
|
78
packages/grafana-ui/src/components/Slider/HandleTooltip.tsx
Normal file
78
packages/grafana-ui/src/components/Slider/HandleTooltip.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import { css } from '@emotion/css';
|
||||
import Tooltip from 'rc-tooltip';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { useStyles2 } from '../../themes/ThemeContext';
|
||||
|
||||
interface RCTooltipRef {
|
||||
// rc-tooltip's ref is essentially untyped, so we be cautious by saying the function is
|
||||
// potentially undefined which, given rc's track record, seems likely :)
|
||||
forcePopupAlign?: () => {};
|
||||
}
|
||||
|
||||
const HandleTooltip = (props: {
|
||||
value: number;
|
||||
children: React.ReactElement;
|
||||
visible: boolean;
|
||||
placement: 'top' | 'right';
|
||||
tipFormatter?: (value: number) => React.ReactNode;
|
||||
}) => {
|
||||
const { value, children, visible, placement, tipFormatter, ...restProps } = props;
|
||||
|
||||
const tooltipRef = useRef<RCTooltipRef>();
|
||||
const rafRef = useRef<number | null>(null);
|
||||
const styles = useStyles2(tooltipStyles);
|
||||
|
||||
function cancelKeepAlign() {
|
||||
if (rafRef.current !== null) {
|
||||
cancelAnimationFrame(rafRef.current);
|
||||
}
|
||||
}
|
||||
|
||||
function keepAlign() {
|
||||
rafRef.current = requestAnimationFrame(() => {
|
||||
tooltipRef.current?.forcePopupAlign?.();
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
keepAlign();
|
||||
} else {
|
||||
cancelKeepAlign();
|
||||
}
|
||||
|
||||
return cancelKeepAlign;
|
||||
}, [value, visible]);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
overlayClassName={styles.tooltip}
|
||||
placement={placement}
|
||||
overlay={tipFormatter ?? value}
|
||||
overlayInnerStyle={{ minHeight: 'auto' }}
|
||||
ref={tooltipRef}
|
||||
visible={visible}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const tooltipStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
tooltip: css({
|
||||
position: 'absolute',
|
||||
display: 'block',
|
||||
visibility: 'visible',
|
||||
fontSize: theme.typography.bodySmall.fontSize,
|
||||
opacity: 0.9,
|
||||
padding: 3,
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export default HandleTooltip;
|
@ -27,7 +27,15 @@ const meta: ComponentMeta<typeof RangeSlider> = {
|
||||
export const Basic: ComponentStory<typeof RangeSlider> = (args) => {
|
||||
return (
|
||||
<div style={{ width: '200px', height: '200px' }}>
|
||||
<RangeSlider value={[10, 20]} {...args} />
|
||||
<RangeSlider {...args} value={[10, 62]} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Vertical: ComponentStory<typeof RangeSlider> = (args) => {
|
||||
return (
|
||||
<div style={{ width: '200px', height: '200px' }}>
|
||||
<RangeSlider {...args} value={[10, 62]} orientation="vertical" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { cx } from '@emotion/css';
|
||||
import { Global } from '@emotion/react';
|
||||
import { Range as RangeComponent, createSliderWithTooltip } from 'rc-slider';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import Slider, { SliderProps } from 'rc-slider';
|
||||
import React, { FunctionComponent, useCallback } from 'react';
|
||||
|
||||
import { useTheme2 } from '../../themes/ThemeContext';
|
||||
|
||||
import HandleTooltip from './HandleTooltip';
|
||||
import { getStyles } from './styles';
|
||||
import { RangeSliderProps } from './types';
|
||||
|
||||
@ -25,33 +26,59 @@ export const RangeSlider: FunctionComponent<RangeSliderProps> = ({
|
||||
value,
|
||||
tooltipAlwaysVisible = true,
|
||||
}) => {
|
||||
const handleChange = useCallback(
|
||||
(v: number | number[]) => {
|
||||
const value = typeof v === 'number' ? [v, v] : v;
|
||||
onChange?.(value);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const handleAfterChange = useCallback(
|
||||
(v: number | number[]) => {
|
||||
const value = typeof v === 'number' ? [v, v] : v;
|
||||
onAfterChange?.(value);
|
||||
},
|
||||
[onAfterChange]
|
||||
);
|
||||
|
||||
const isHorizontal = orientation === 'horizontal';
|
||||
const theme = useTheme2();
|
||||
const styles = getStyles(theme, isHorizontal);
|
||||
const RangeWithTooltip = createSliderWithTooltip(RangeComponent);
|
||||
|
||||
const tipHandleRender: SliderProps['handleRender'] = (node, handleProps) => {
|
||||
return (
|
||||
<HandleTooltip
|
||||
value={handleProps.value}
|
||||
visible={tooltipAlwaysVisible || handleProps.dragging}
|
||||
tipFormatter={formatTooltipResult}
|
||||
placement={isHorizontal ? 'top' : 'right'}
|
||||
>
|
||||
{node}
|
||||
</HandleTooltip>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cx(styles.container, styles.slider)}>
|
||||
{/** Slider tooltip's parent component is body and therefore we need Global component to do css overrides for it. */}
|
||||
<Global styles={styles.tooltip} />
|
||||
<RangeWithTooltip
|
||||
tipProps={{
|
||||
visible: tooltipAlwaysVisible,
|
||||
placement: isHorizontal ? 'top' : 'right',
|
||||
}}
|
||||
<Slider
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
defaultValue={value}
|
||||
tipFormatter={(value: number) => (formatTooltipResult ? formatTooltipResult(value) : value)}
|
||||
onChange={onChange}
|
||||
onAfterChange={onAfterChange}
|
||||
range={true}
|
||||
onChange={handleChange}
|
||||
onAfterChange={handleAfterChange}
|
||||
vertical={!isHorizontal}
|
||||
reverse={reverse}
|
||||
// TODO: The following is a temporary work around for making content after the slider accessible and it will be removed when fixing the slider in public/app/features/explore/RichHistory/RichHistoryQueriesTab.tsx.
|
||||
tabIndex={[0, 1]}
|
||||
handleRender={tipHandleRender}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
RangeSlider.displayName = 'Range';
|
||||
RangeSlider.displayName = 'RangeSlider';
|
||||
|
@ -32,12 +32,11 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
||||
const [sliderValue, setSliderValue] = useState<number>(value ?? min);
|
||||
|
||||
const onSliderChange = useCallback(
|
||||
(v: number) => {
|
||||
setSliderValue(v);
|
||||
(v: number | number[]) => {
|
||||
const value = typeof v === 'number' ? v : v[0];
|
||||
|
||||
if (onChange) {
|
||||
onChange(v);
|
||||
}
|
||||
setSliderValue(value);
|
||||
onChange?.(value);
|
||||
},
|
||||
[setSliderValue, onChange]
|
||||
);
|
||||
@ -78,6 +77,14 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
||||
[max, min]
|
||||
);
|
||||
|
||||
const handleAfterChange = useCallback(
|
||||
(v: number | number[]) => {
|
||||
const value = typeof v === 'number' ? v : v[0];
|
||||
onAfterChange?.(value);
|
||||
},
|
||||
[onAfterChange]
|
||||
);
|
||||
|
||||
const sliderInputClassNames = !isHorizontal ? [styles.sliderInputVertical] : [];
|
||||
const sliderInputFieldClassNames = !isHorizontal ? [styles.sliderInputFieldVertical] : [];
|
||||
|
||||
@ -85,7 +92,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
||||
<div className={cx(styles.container, styles.slider)}>
|
||||
{/** Slider tooltip's parent component is body and therefore we need Global component to do css overrides for it. */}
|
||||
<Global styles={styles.tooltip} />
|
||||
<label className={cx(styles.sliderInput, ...sliderInputClassNames)}>
|
||||
<div className={cx(styles.sliderInput, ...sliderInputClassNames)}>
|
||||
<SliderWithTooltip
|
||||
min={min}
|
||||
max={max}
|
||||
@ -93,24 +100,24 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
||||
defaultValue={value}
|
||||
value={sliderValue}
|
||||
onChange={onSliderChange}
|
||||
onAfterChange={onAfterChange}
|
||||
onAfterChange={handleAfterChange}
|
||||
vertical={!isHorizontal}
|
||||
reverse={reverse}
|
||||
ariaLabelForHandle={ariaLabelForHandle}
|
||||
marks={marks}
|
||||
included={included}
|
||||
/>
|
||||
{/* Uses text input so that the number spinners are not shown */}
|
||||
|
||||
<Input
|
||||
type="text"
|
||||
className={cx(styles.sliderInputField, ...sliderInputFieldClassNames)}
|
||||
value={`${sliderValue}`} // to fix the react leading zero issue
|
||||
value={sliderValue}
|
||||
onChange={onSliderInputChange}
|
||||
onBlur={onSliderInputBlur}
|
||||
min={min}
|
||||
max={max}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -44,14 +44,21 @@ export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: bool
|
||||
background-color: ${handleColor};
|
||||
box-shadow: ${theme.shadows.z1};
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.rc-slider-handle:hover,
|
||||
.rc-slider-handle:active,
|
||||
.rc-slider-handle:focus,
|
||||
.rc-slider-handle-click-focused:focus {
|
||||
${hoverSyle};
|
||||
}
|
||||
|
||||
// The triple class names is needed because that's the specificity used in the source css :(
|
||||
.rc-slider-handle-dragging.rc-slider-handle-dragging.rc-slider-handle-dragging,
|
||||
.rc-slider-handle:focus-visible {
|
||||
box-shadow: 0 0 0 5px ${theme.colors.text.primary};
|
||||
}
|
||||
|
||||
.rc-slider-dot,
|
||||
.rc-slider-dot-active {
|
||||
background-color: ${theme.colors.text.primary};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { Global } from '@emotion/react';
|
||||
import SliderComponent from 'rc-slider';
|
||||
import Slider from 'rc-slider';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { FieldConfigEditorProps, GrafanaTheme2, SliderFieldConfigSettings } from '@grafana/data';
|
||||
@ -30,7 +30,6 @@ export const SliderValueEditor: React.FC<FieldConfigEditorProps<number, SliderFi
|
||||
const inputWidthDefault = 75;
|
||||
const isHorizontal = true;
|
||||
const theme = useTheme2();
|
||||
const SliderWithTooltip = SliderComponent;
|
||||
const [sliderValue, setSliderValue] = useState<number>(value ?? min);
|
||||
const [inputWidth, setInputWidth] = useState<number>(inputWidthDefault);
|
||||
|
||||
@ -60,11 +59,12 @@ export const SliderValueEditor: React.FC<FieldConfigEditorProps<number, SliderFi
|
||||
}, [max, step]);
|
||||
|
||||
const onSliderChange = useCallback(
|
||||
(v: number) => {
|
||||
setSliderValue(v);
|
||||
(v: number | number[]) => {
|
||||
const value = typeof v === 'number' ? v : v[0];
|
||||
setSliderValue(value);
|
||||
|
||||
if (onChange) {
|
||||
onChange(v);
|
||||
onChange(value);
|
||||
}
|
||||
},
|
||||
[setSliderValue, onChange]
|
||||
@ -97,7 +97,7 @@ export const SliderValueEditor: React.FC<FieldConfigEditorProps<number, SliderFi
|
||||
{/** Slider tooltip's parent component is body and therefore we need Global component to do css overrides for it. */}
|
||||
<Global styles={styles.slider} />
|
||||
<div className={cx(styles.sliderInput, ...sliderInputClassNames)}>
|
||||
<SliderWithTooltip
|
||||
<Slider
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
|
57
yarn.lock
57
yarn.lock
@ -4837,8 +4837,9 @@ __metadata:
|
||||
process: ^0.11.10
|
||||
rc-cascader: 3.7.0
|
||||
rc-drawer: 4.4.3
|
||||
rc-slider: 9.7.5
|
||||
rc-slider: 10.0.1
|
||||
rc-time-picker: ^3.7.3
|
||||
rc-tooltip: 5.2.2
|
||||
react: 17.0.2
|
||||
react-beautiful-dnd: 13.1.0
|
||||
react-calendar: 3.9.0
|
||||
@ -21894,7 +21895,7 @@ __metadata:
|
||||
pseudoizer: ^0.1.0
|
||||
rc-cascader: 3.7.0
|
||||
rc-drawer: 4.4.3
|
||||
rc-slider: 9.7.5
|
||||
rc-slider: 10.0.1
|
||||
rc-time-picker: 3.7.3
|
||||
rc-tree: 5.7.0
|
||||
re-resizable: 6.9.9
|
||||
@ -31854,19 +31855,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-slider@npm:9.7.5":
|
||||
version: 9.7.5
|
||||
resolution: "rc-slider@npm:9.7.5"
|
||||
"rc-slider@npm:10.0.1":
|
||||
version: 10.0.1
|
||||
resolution: "rc-slider@npm:10.0.1"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.10.1
|
||||
classnames: ^2.2.5
|
||||
rc-tooltip: ^5.0.1
|
||||
rc-util: ^5.16.1
|
||||
rc-util: ^5.18.1
|
||||
shallowequal: ^1.1.0
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: e5b7b8e6036ea51d88e40c11c46e9c1639f5133fd1a6b5353c87547b1bc92393a291f9d0772a0465d1d139c9dbd14a349838861df86d33b1abb6a94593e7b17e
|
||||
checksum: 803f0cc39d43897c0b24549e87232a668d26ff5b0e14b528fd454aa455cdf96ebc60654832c51bb1a6c7b7594ca39017d6c96b3237662471efb863f1723e3d9c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -31884,16 +31884,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-tooltip@npm:^5.0.1":
|
||||
version: 5.1.1
|
||||
resolution: "rc-tooltip@npm:5.1.1"
|
||||
"rc-tooltip@npm:5.2.2":
|
||||
version: 5.2.2
|
||||
resolution: "rc-tooltip@npm:5.2.2"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.11.2
|
||||
classnames: ^2.3.1
|
||||
rc-trigger: ^5.0.0
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: e65b175c28356cee101db56217d02a1eb1d96e727620bb1f6551f98e3ab49d3ec4381f1d408d19054b46349cba0e89056a4b4f09eeebbe70a1013733ad0e1fc9
|
||||
checksum: df6a59096876becf930df0347cfe6379cde9647f338a333dd0aae99039bf45e72db866f03ab6b5fd5ce616b074ec888f50e61ebe0f8d2a135c2617595dbf0583
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -31944,7 +31945,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-trigger@npm:^5.0.0, rc-trigger@npm:^5.0.4":
|
||||
"rc-trigger@npm:^5.0.0":
|
||||
version: 5.3.1
|
||||
resolution: "rc-trigger@npm:5.3.1"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.18.3
|
||||
classnames: ^2.2.6
|
||||
rc-align: ^4.0.0
|
||||
rc-motion: ^2.0.0
|
||||
rc-util: ^5.19.2
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 29302e9a0a66eb26cef5ce0b291ada9bb3e284f19980bf02da6863a5306d5de863aa87fbbf30c176a4453c13db160b69789ac50aae09af8e5c53942ac0368a3b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-trigger@npm:^5.0.4":
|
||||
version: 5.2.10
|
||||
resolution: "rc-trigger@npm:5.2.10"
|
||||
dependencies:
|
||||
@ -31987,6 +32004,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-util@npm:^5.18.1, rc-util@npm:^5.19.2":
|
||||
version: 5.24.4
|
||||
resolution: "rc-util@npm:5.24.4"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.18.3
|
||||
react-is: ^16.12.0
|
||||
shallowequal: ^1.1.0
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: efda306dcf9eeb0df6d3a8d315d18ec73c653d463174355bd91d34f4d42acc092b2d6ffee47993312841ea4d13b4fe036c764a3a46fa935f307d51a8807e2c10
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-util@npm:^5.2.1, rc-util@npm:^5.3.0, rc-util@npm:^5.5.0, rc-util@npm:^5.7.0":
|
||||
version: 5.14.0
|
||||
resolution: "rc-util@npm:5.14.0"
|
||||
|
Loading…
Reference in New Issue
Block a user