import React, { FC, useContext, useState } from 'react'; import { SketchPicker } from 'react-color'; import { Box } from '@chakra-ui/react'; import Popover from '../popover'; import Input, { InputProps } from '../input'; import { ConfigContext } from '../config-provider'; export interface ColorPickerInputProps extends Omit { defaultValue?: string; value?: string; /** 输入的颜色符合颜色正确值才触发 */ onChange?: (value: string) => void; /** 模式,色值模式或 rgb 模式,不设置时两种都支持 */ mode?: 'hex' | 'rgb'; } const hexReg = /(^#[\da-f]{6}$)|(^#[\da-f]{4}$)|(^#[\da-f]{3}$)/i; const rgbReg = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/; const rgbaReg = /^rgba\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/; const ColorPickerInput: FC = ({ mode, value, defaultValue, onChange, onBlur, ...props }) => { const { getPrefixCls } = useContext(ConfigContext); const [inputValue, setInputValue] = useState(() => defaultValue); // 外部设置 value 时,内部要同步 React.useEffect(() => { if (value !== inputValue) { setInputValue(value); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); return ( { const val = e.target.value; setInputValue(val); if (onChange) { if (!val) { onChange(val); return; } if (mode === 'hex') { if (hexReg.test(val)) { onChange(val); } } else if (mode === 'rgb') { if (rgbReg.test(val) || rgbaReg.test(val)) { onChange(val); } } else if (hexReg.test(val) || rgbReg.test(val) || rgbaReg.test(val)) { onChange(val); } } }} onBlur={e => { const val = e.target.value; // 失焦时如果值不正确,设置成外部的 value if (val) { if (mode === 'hex') { if (!hexReg.test(val)) { setInputValue(value); } } else if (mode === 'rgb') { if (!rgbReg.test(val) && !rgbaReg.test(val)) { setInputValue(value); } } else if (!hexReg.test(val) && !rgbReg.test(val) && !rgbaReg.test(val)) { setInputValue(value); } } onBlur?.(e); }} suffix={ { if (onChange) { if (mode === 'hex') { onChange(colorState.hex); setInputValue(colorState.hex); } else if (mode === 'rgb') { const color = `rgba(${colorState.rgb.r},${colorState.rgb.g},${colorState.rgb.b},${colorState.rgb.a})`; onChange(color); setInputValue(color); } else if ( colorState.source === 'hex' || colorState.source === 'hsv' || colorState.source === 'hsl' ) { onChange(colorState.hex); setInputValue(colorState.hex); } else if (colorState.source === 'rgb') { const color = `rgba(${colorState.rgb.r},${colorState.rgb.g},${colorState.rgb.b},${colorState.rgb.a})`; onChange(color); setInputValue(color); } } }} /> } > } /> ); }; export default ColorPickerInput;