Grafana-UI: replace react-color with react-colorful (#33267)

* Grafana-UI: replace react-color with react-colorful

* Throttle onChange from SpectrumPalette
This commit is contained in:
Giordano Ricci 2021-04-23 15:03:48 +01:00 committed by GitHub
parent d76c056656
commit ec1c85acca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 218 deletions

View File

@ -66,7 +66,7 @@
"react": "17.0.1",
"react-beautiful-dnd": "13.0.0",
"react-calendar": "2.19.2",
"react-color": "2.18.0",
"react-colorful": "5.1.2",
"react-custom-scrollbars": "4.2.1",
"react-dom": "17.0.1",
"react-highlight-words": "0.16.0",

View File

@ -3,7 +3,10 @@ import tinycolor from 'tinycolor2';
import { debounce } from 'lodash';
import { ColorPickerProps } from './ColorPickerPopover';
import { Input } from '../Forms/Legacy/Input/Input';
import { Input } from '../Input/Input';
import { useStyles } from '../../themes';
import { GrafanaTheme } from '@grafana/data';
import { cx, css } from '@emotion/css';
interface ColorInputState {
previousColor: string;
@ -12,6 +15,7 @@ interface ColorInputState {
interface ColorInputProps extends ColorPickerProps {
style?: React.CSSProperties;
className?: string;
}
class ColorInput extends React.PureComponent<ColorInputProps, ColorInputState> {
@ -66,31 +70,41 @@ class ColorInput extends React.PureComponent<ColorInputProps, ColorInputState> {
render() {
const { value } = this.state;
return (
<div
style={{
display: 'flex',
...this.props.style,
}}
>
<div
style={{
background: this.props.color,
width: '35px',
height: '35px',
flexGrow: 0,
borderRadius: '3px 0 0 3px',
}}
/>
<div
style={{
flexGrow: 1,
}}
>
<Input className="gf-form-input" value={value} onChange={this.onChange} onBlur={this.onBlur} />
</div>
</div>
<Input
className={this.props.className}
value={value}
onChange={this.onChange}
onBlur={this.onBlur}
addonBefore={<ColorPreview color={this.props.color} />}
/>
);
}
}
export default ColorInput;
interface ColorPreviewProps {
color: string;
}
const ColorPreview = ({ color }: ColorPreviewProps) => {
const styles = useStyles(getColorPreviewStyles);
return (
<div
className={cx(
styles,
css`
background-color: ${color};
`
)}
/>
);
};
const getColorPreviewStyles = (theme: GrafanaTheme) => css`
height: 100%;
width: ${theme.spacing.formInputHeight}px;
border-radius: ${theme.border.radius.sm} 0 0 ${theme.border.radius.sm};
border: 1px solid ${theme.colors.formInputBorder};
`;

View File

@ -72,7 +72,7 @@ class UnThemedColorPickerPopover<T extends CustomPickersDescriptor> extends Reac
switch (activePicker) {
case 'spectrum':
return <SpectrumPalette color={color} onChange={this.handleChange} theme={theme} />;
return <SpectrumPalette color={color} onChange={this.handleChange} />;
case 'palette':
return <NamedColorsPalette color={color} onChange={this.handleChange} theme={theme} />;
default:

View File

@ -1,101 +1,67 @@
import React from 'react';
import { CustomPicker, ColorResult } from 'react-color';
import React, { useMemo, useState } from 'react';
import { Saturation, Hue, Alpha } from 'react-color/lib/components/common';
import { RgbaStringColorPicker } from 'react-colorful';
import tinycolor from 'tinycolor2';
import ColorInput from './ColorInput';
import { Themeable } from '../../types';
import SpectrumPalettePointer, { SpectrumPalettePointerProps } from './SpectrumPalettePointer';
import { GrafanaTheme, getColorForTheme } from '@grafana/data';
import { css, cx } from '@emotion/css';
import { useStyles, useTheme } from '../../themes';
import { useThrottleFn } from 'react-use';
export interface SpectrumPaletteProps extends Themeable {
export interface SpectrumPaletteProps {
color: string;
onChange: (color: string) => void;
}
// eslint-disable-next-line react/display-name
const renderPointer = (theme: GrafanaTheme) => (props: SpectrumPalettePointerProps) => (
<SpectrumPalettePointer {...props} theme={theme} />
);
const SpectrumPalette: React.FunctionComponent<SpectrumPaletteProps> = ({ color, onChange }) => {
const [currentColor, setColor] = useState(color);
useThrottleFn(onChange, 500, [currentColor]);
const theme = useTheme();
const styles = useStyles(getStyles);
const rgbaString = useMemo(() => {
return currentColor.startsWith('rgba')
? currentColor
: tinycolor(getColorForTheme(currentColor, theme)).toRgbString();
}, [currentColor, theme]);
// @ts-ignore
const SpectrumPicker = CustomPicker<Themeable>(({ rgb, hsl, onChange, theme }) => {
return (
<div
style={{
display: 'flex',
width: '100%',
flexDirection: 'column',
}}
>
<div
style={{
display: 'flex',
}}
>
<div
style={{
display: 'flex',
flexGrow: 1,
flexDirection: 'column',
}}
>
<div
style={{
position: 'relative',
height: '100px',
width: '100%',
}}
>
{/*
// @ts-ignore */}
<Saturation onChange={onChange} hsl={hsl} hsv={tinycolor(hsl).toHsv()} />
</div>
<div
style={{
width: '100%',
height: '16px',
marginTop: '16px',
position: 'relative',
background: 'white',
}}
>
{/*
// @ts-ignore */}
<Alpha rgb={rgb} hsl={hsl} a={rgb.a} onChange={onChange} pointer={renderPointer(theme)} />
</div>
</div>
<>
<RgbaStringColorPicker className={cx(styles.root)} color={rgbaString} onChange={setColor} />
<div
style={{
position: 'relative',
width: '16px',
height: '100px',
marginLeft: '16px',
}}
>
{/*
// @ts-ignore */}
<Hue onChange={onChange} hsl={hsl} direction="vertical" pointer={renderPointer(theme)} />
</div>
</div>
</div>
);
});
const SpectrumPalette: React.FunctionComponent<SpectrumPaletteProps> = ({ color, onChange, theme }) => {
return (
<div>
<SpectrumPicker
color={tinycolor(getColorForTheme(color, theme)).toRgb()}
onChange={(a: ColorResult) => {
onChange(tinycolor(a.rgb).toString());
}}
theme={theme}
/>
<ColorInput theme={theme} color={color} onChange={onChange} style={{ marginTop: '16px' }} />
</div>
<ColorInput theme={theme} color={currentColor} onChange={setColor} className={styles.colorInput} />
</>
);
};
const getStyles = (theme: GrafanaTheme) => ({
root: css`
&.react-colorful {
width: auto;
}
.react-colorful {
&__saturation {
border-radius: ${theme.border.radius.sm} ${theme.border.radius.sm} 0 0;
}
&__alpha {
border-radius: 0 0 ${theme.border.radius.sm} ${theme.border.radius.sm};
}
&__alpha,
&__hue {
height: ${theme.spacing.md};
position: relative;
}
&__pointer {
height: ${theme.spacing.md};
width: ${theme.spacing.md};
}
}
`,
colorInput: css`
margin-top: ${theme.spacing.md};
`,
});
export default SpectrumPalette;

View File

@ -1,77 +0,0 @@
import React from 'react';
import { Themeable } from '../../types';
export interface SpectrumPalettePointerProps extends Themeable {
direction?: string;
}
const SpectrumPalettePointer: React.FunctionComponent<SpectrumPalettePointerProps> = ({ theme, direction }) => {
const styles = {
picker: {
width: '16px',
height: '16px',
transform: direction === 'vertical' ? 'translate(0, -8px)' : 'translate(-8px, 0)',
},
};
const pointerColor = theme.colors.text;
let pointerStyles: React.CSSProperties = {
position: 'absolute',
left: '6px',
width: '0',
height: '0',
borderStyle: 'solid',
background: 'none',
};
let topArrowStyles: React.CSSProperties = {
top: '-7px',
borderWidth: '6px 3px 0px 3px',
borderColor: `${pointerColor} transparent transparent transparent`,
};
let bottomArrowStyles: React.CSSProperties = {
bottom: '-7px',
borderWidth: '0px 3px 6px 3px',
borderColor: ` transparent transparent ${pointerColor} transparent`,
};
if (direction === 'vertical') {
pointerStyles = {
...pointerStyles,
left: 'auto',
};
topArrowStyles = {
borderWidth: '3px 0px 3px 6px',
borderColor: `transparent transparent transparent ${pointerColor}`,
left: '-7px',
top: '7px',
};
bottomArrowStyles = {
borderWidth: '3px 6px 3px 0px',
borderColor: `transparent ${pointerColor} transparent transparent`,
right: '-7px',
top: '7px',
};
}
return (
<div style={styles.picker}>
<div
style={{
...pointerStyles,
...topArrowStyles,
}}
/>
<div
style={{
...pointerStyles,
...bottomArrowStyles,
}}
/>
</div>
);
};
export default SpectrumPalettePointer;

View File

@ -2609,11 +2609,6 @@
resolved "https://registry.yarnpkg.com/@grafana/tsconfig/-/tsconfig-1.0.0-rc1.tgz#d07ea16755a50cae21000113f30546b61647a200"
integrity sha512-nucKPGyzlSKYSiJk5RA8GzMdVWhdYNdF+Hh65AXxjD9PlY69JKr5wANj8bVdQboag6dgg0BFKqgKPyY+YtV4Iw==
"@icons/material@^0.2.4":
version "0.2.4"
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"
integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -16557,7 +16552,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@4.17.21, lodash@>=4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.1.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.10, lodash@~4.17.15:
lodash@4.17.21, lodash@>=4, lodash@^4, lodash@^4.0.0, lodash@^4.1.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.10, lodash@~4.17.15:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@ -16842,11 +16837,6 @@ marked@2.0.1:
resolved "https://registry.yarnpkg.com/marked/-/marked-2.0.1.tgz#5e7ed7009bfa5c95182e4eb696f85e948cefcee3"
integrity sha512-5+/fKgMv2hARmMW7DOpykr2iLhl0NgjyELk5yn92iE7z8Se1IS9n3UsFm86hFXIkvMBmVxki8+ckcpjBeyo/hw==
material-colors@^1.2.1:
version "1.2.6"
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
md5-file@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-4.0.0.tgz#f3f7ba1e2dd1144d5bf1de698d0e5f44a4409584"
@ -20536,17 +20526,10 @@ react-calendar@2.19.2:
prop-types "^15.6.0"
react-lifecycles-compat "^3.0.4"
react-color@2.18.0:
version "2.18.0"
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.18.0.tgz#34956f0bac394f6c3bc01692fd695644cc775ffd"
integrity sha512-FyVeU1kQiSokWc8NPz22azl1ezLpJdUyTbWL0LPUpcuuYDrZ/Y1veOk9rRK5B3pMlyDGvTk4f4KJhlkIQNRjEA==
dependencies:
"@icons/material" "^0.2.4"
lodash "^4.17.11"
material-colors "^1.2.1"
prop-types "^15.5.10"
reactcss "^1.2.0"
tinycolor2 "^1.4.1"
react-colorful@5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.1.2.tgz#5cb1506b8f9104b88d02d34984a36c2d1e477e9e"
integrity sha512-FRt9jz6xjiPqQ6bIAQ26kd0oJhHbGBwsA4BDz/F8FDCFuQJDiEl0wVUARNiqRyvQjwfKuhM42P/bMYI0l92hRw==
react-colorful@^5.0.1:
version "5.1.0"
@ -21135,13 +21118,6 @@ react@17.0.1:
loose-envify "^1.1.0"
object-assign "^4.1.1"
reactcss@^1.2.0:
version "1.2.3"
resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd"
integrity sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==
dependencies:
lodash "^4.0.1"
read-cmd-shim@^1.0.1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"
@ -24042,7 +24018,7 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3:
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tinycolor2@1.4.1, tinycolor2@^1.4.1:
tinycolor2@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=