diff --git a/src/ColorPicker/index.jsx b/src/ColorPicker/index.jsx index 1cef1c336b8..e59f03d4e4f 100644 --- a/src/ColorPicker/index.jsx +++ b/src/ColorPicker/index.jsx @@ -10,29 +10,59 @@ import { OverlayTrigger } from '../Overlay'; import Tooltip from '../Tooltip'; import useToggle from '../hooks/useToggle'; +const colorIsValid = (colorToValidate) => { + const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; + return hexRegex.test(colorToValidate); +} + +const formatHexColorString = (colorString) => { + if (!colorString.startsWith('#')) { + colorString = `#${colorString}`; + } + return colorString.slice(0,7); +} + function ColorPicker({ color, setColor, className, size, }) { const [isOpen, open, close] = useToggle(false); const [target, setTarget] = React.useState(null); - const [hexValid, setHexValid] = React.useState(true); + const [hexValid, setHexValid] = React.useState(() => (color === '' || colorIsValid(formatHexColorString(color)))); + const [hexColorString, setHexColorString] = React.useState(() => formatHexColorString(color)); + const [colorToDisplay, setColorToDisplay] = React.useState(() => { + const formattedColor = formatHexColorString(color); + if (colorIsValid(formattedColor)) { + return formattedColor; + } - const validateHex = useCallback((input) => { - const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; - if (input.length > 1 && !input.startsWith('#')) { - setColor(`#${input}`); - } else { - setColor(input); + return '#fff'; + }); + + const setValidatedColor = (newColor) => { + if (newColor === '') { + setHexValid(true); + setColor(''); + setHexColorString(''); + setColorToDisplay('#fff'); + return; } - if (input === '' || hexRegex.test(input) === true) { + + newColor = formatHexColorString(newColor); + + if (colorIsValid(newColor)) { setHexValid(true); - } else { - setHexValid(false); + setColor(newColor); + setHexColorString(newColor); + setColorToDisplay(newColor); + return; } - }, [setColor]); - // this is needed for when a user changes the color through the sliders - useEffect(() => validateHex(color), [validateHex, color]); + setHexValid(false); + setHexColorString(newColor); + + // not sure if we want to do this, but if we don't then the value of the picker could be out of sync from what is in the textbox + setColor(newColor); + } return ( <> @@ -65,16 +95,17 @@ function ColorPicker({ className="pgn__color-modal rounded shadow" style={{ textAlign: 'start' }} > - +
Hex validateHex(e.target.value)} + value={hexColorString} + onChange={(e) => setValidatedColor(e.target.value)} data-testid="hex-input" + spellCheck="false" />
{!hexValid && (