import React from 'react'; import type * as CSS from 'csstype'; import { HsvaColor, type ColorResult, validHex, hexToHsva, hsvaToHex, color as handleColor } from '@uiw/color-convert'; import Interactive, { type Interaction } from '@uiw/react-drag-event-interactive'; import { Pointer, type PointerProps } from './Pointer'; import { getWheelHandlePosition, getWheelValueFromInput } from './utils'; export interface WheelProps extends Omit, 'onChange' | 'color'> { prefixCls?: string; color?: string | HsvaColor; width?: number; height?: number; radius?: CSS.Properties['borderRadius']; /** Direction of the oval: 'x' or 'y'. */ oval?: string; /** Starting angle of the color wheel's hue gradient, measured in degrees. */ angle?: number; /** Direction of the color wheel's hue gradient; either clockwise or anticlockwise. Default: `anticlockwise` */ direction?: 'clockwise' | 'anticlockwise'; pointer?: ({ prefixCls, left, top, color }: PointerProps) => JSX.Element; onChange?: (color: ColorResult) => void; } const HUE_GRADIENT_CLOCKWISE = 'conic-gradient(red, yellow, lime, aqua, blue, magenta, red)'; const HUE_GRADIENT_ANTICLOCKWISE = 'conic-gradient(red, magenta, blue, aqua, lime, yellow, red)'; const Wheel = React.forwardRef((props, ref) => { const { prefixCls = 'w-color-wheel', radius = 0, pointer, className, style, width = 200, height = 200, oval, direction = 'anticlockwise', angle = 180, color, onChange, ...other } = props; const hsva = (typeof color === 'string' && validHex(color) ? hexToHsva(color) : color || {}) as HsvaColor; const hex = color ? hsvaToHex(hsva) : ''; const wheelProps = { width, direction, angle }; const positions = getWheelHandlePosition(wheelProps, hsva); const comProps = { top: '0', left: '0', color: hex, }; const handleChange = (interaction: Interaction, event: MouseEvent | TouchEvent) => { const result = getWheelValueFromInput(wheelProps, interaction.x, interaction.y); const handleHsva = { h: result.h, s: result.s, v: hsva.v, a: hsva.a, }; onChange && onChange(handleColor(handleHsva)); }; const pointerStyle: CSS.Properties = { zIndex: 1, position: 'absolute', transform: `translate(${positions.x}px, ${positions.y}px) ${ oval === 'x' || oval === 'X' ? 'scaleY(2)' : oval === 'y' || oval === 'Y' ? 'scaleX(2)' : '' }`, }; const pointerElement = pointer && typeof pointer === 'function' ? ( pointer({ prefixCls, style: pointerStyle, ...comProps }) ) : ( ); return ( {pointerElement}
); }); Wheel.displayName = 'Wheel'; export default Wheel;