import React, { FC, useEffect, useState } from 'react' import styled from 'styled-components' import { Channel, TColor } from 'shared/types' import { ControlGroup, Input } from '../inputs' import { useStore } from '@nanostores/react' import { colorSpaceStore } from 'store/palette' import { clamp } from 'shared/utils' type ColorEditorProps = { color: TColor onChange: (color: TColor) => void } export const ColorEditor: FC = ({ color, onChange }) => { const { lch2color, hex2color, ranges } = useStore(colorSpaceStore) const { l, c, h, hex, within_sRGB } = color const [isFocused, setIsFocused] = useState(false) const [colorInput, setColorInput] = useState(hex) useEffect(() => { if (!isFocused) setColorInput(hex) }, [hex, isFocused]) const setColor = (channel: Channel, value: number) => { value = clamp(value, ranges[channel].min, ranges[channel].max) if (channel === 'l') onChange(lch2color([value, c, h])) if (channel === 'c') onChange(lch2color([l, value, h])) if (channel === 'h') onChange(lch2color([l, c, value])) } return ( L setColor('l', +e.target.value)} /> C setColor('c', +e.target.value)} /> H setColor('h', +e.target.value)} /> setIsFocused(true)} onBlur={() => { setIsFocused(false) setColorInput(hex) }} onChange={e => { const value = e.target.value setColorInput(value) let color = hex2color(value) if (color) onChange(color) }} /> ) } const ChannelInputWrapper = styled.label` position: relative; isolation: isolate; ` const ChannelLabel = styled.span` position: absolute; top: 50%; left: 0; transform: translateY(-50%); padding: 4px 0 4px 8px; color: var(--c-text-hint); ` const ChannelInput = styled(Input)` width: 80px; padding-left: 24px; border-radius: inherit; height: 100%; -moz-appearance: textfield; ::-webkit-outer-spin-button, ::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } ` const HexInput = styled(Input)` width: 80px; `