diff --git a/packages/react-components/react-color-picker-preview/stories/src/ColorPicker/ColorPickerDefault.stories.tsx b/packages/react-components/react-color-picker-preview/stories/src/ColorPicker/ColorPickerDefault.stories.tsx index 4ba93f4bbf939..4902f0cf02eb8 100644 --- a/packages/react-components/react-color-picker-preview/stories/src/ColorPicker/ColorPickerDefault.stories.tsx +++ b/packages/react-components/react-color-picker-preview/stories/src/ColorPicker/ColorPickerDefault.stories.tsx @@ -1,6 +1,16 @@ import * as React from 'react'; import { tinycolor } from '@ctrl/tinycolor'; -import { makeStyles, useId, Input, type InputProps, Label } from '@fluentui/react-components'; +import { + makeStyles, + useId, + Input, + type InputProps, + Label, + SpinButton, + type SpinButtonProps, + type SpinButtonOnChangeData, + type SpinButtonChangeEvent, +} from '@fluentui/react-components'; import { ColorPicker, ColorSlider, @@ -36,21 +46,46 @@ const useStyles = makeStyles({ input: { width: '80px', }, + spinButton: { + width: '50px', + }, }); const HEX_COLOR_REGEX = /^#?([0-9A-Fa-f]{0,6})$/; +const NUMBER_REGEX = /^\d+$/; const DEFAULT_COLOR_HSV = tinycolor('#2be700').toHsv(); +type RgbKey = 'r' | 'g' | 'b'; + export const Default = () => { const hexId = useId('hex-input'); const styles = useStyles(); const [color, setColor] = React.useState(DEFAULT_COLOR_HSV); const [hex, setHex] = React.useState(tinycolor(color).toHexString()); + const [rgb, setRgb] = React.useState(tinycolor(color).toRgb()); const handleChange: ColorPickerProps['onColorChange'] = (_, data) => { setColor({ ...data.color, a: data.color.a ?? 1 }); setHex(tinycolor(data.color).toHexString()); + setRgb(tinycolor(data.color).toRgb()); + }; + + const onRgbChange = (event: SpinButtonChangeEvent, data: SpinButtonOnChangeData) => { + const value = data.value ?? (data.displayValue !== undefined ? parseFloat(data.displayValue) : null); + + if (value === null || Number.isNaN(value) || !NUMBER_REGEX.test(value.toString())) { + return; + } + + const colorKey = (event.target as HTMLInputElement).name as RgbKey; + + const newColor = tinycolor({ ...rgb, [colorKey]: value }); + if (newColor.isValid) { + setColor(newColor.toHsv()); + setHex(newColor.toHex()); + setRgb(newColor.toRgb()); + } }; return ( @@ -74,7 +109,11 @@ export const Default = () => { setHex(oldValue => (HEX_COLOR_REGEX.test(value) ? value : oldValue)); }} /> + + + +
); }; @@ -99,6 +138,36 @@ const InputHexField = ({ ); }; +const InputRgbField = ({ + value, + onChange, + label, + name, +}: { + value: number; + label: string; + name: RgbKey; + onChange?: SpinButtonProps['onChange']; +}) => { + const id = useId(`${label.toLowerCase()}-input`); + const styles = useStyles(); + + return ( +
+ + +
+ ); +}; + const handleOnBlur = (e: React.FocusEvent) => { const value = tinycolor(e.target.value); if (!value.isValid) {