All files / color-saturation/src index.tsx

85.71% Statements 12/14
75% Branches 12/16
100% Functions 3/3
92.3% Lines 12/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                1x 2x 2x               2x 1x                     2x 2x 2x         2x     2x     2x                                           1x      
import React, { useMemo } from 'react';
import { HsvaColor, hsvaToHslaString } from '@uiw/color-convert';
import Interactive, { Interaction } from '@uiw/react-drag-event-interactive';
import { Pointer, PointerProps } from './Pointer';
 
export interface SaturationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
  prefixCls?: string;
  /** hsva => `{ h: 0, s: 75, v: 82, a: 1 }` */
  hsva?: HsvaColor;
  hue?: number;
  radius?: React.CSSProperties['borderRadius'];
  /** React Component, Custom pointer component */
  pointer?: ({ prefixCls, left, top, color }: PointerProps) => JSX.Element;
  onChange?: (newColor: HsvaColor) => void;
}
 
const Saturation = React.forwardRef<HTMLDivElement, SaturationProps>((props, ref) => {
  const { prefixCls = 'w-color-saturation', radius = 0, pointer, className, hue = 0, style, hsva, onChange, ...other } = props;
  const containerStyle: React.CSSProperties = {
    width: 200,
    height: 200,
    borderRadius: radius,
    ...style,
    position: 'relative',
  };
 
  const handleChange = (interaction: Interaction, event: MouseEvent | TouchEvent) => {
    onChange &&
      hsva &&
      onChange({
        h: hsva.h,
        s: interaction.left * 100,
        v: (1 - interaction.top) * 100,
        a: hsva.a,
        // source: 'hsv',
      });
  };
 
  const pointerElement = useMemo(() => {
    Iif (!hsva) return null;
    const comProps = {
      top: `${100 - hsva.v}%`,
      left: `${hsva.s}%`,
      color: hsvaToHslaString(hsva),
    };
    Iif (pointer && typeof pointer === 'function') {
      return pointer({ prefixCls, ...comProps });
    }
    return <Pointer prefixCls={prefixCls} {...comProps} />;
  }, [hsva, pointer, prefixCls]);
 
  return (
    <Interactive
      className={[prefixCls, className || ''].filter(Boolean).join(' ')}
      {...other}
      style={{
        position: 'absolute',
        inset: 0,
        cursor: 'crosshair',
        backgroundImage: `linear-gradient(0deg, #000, transparent), linear-gradient(90deg, #fff, hsl(${
          hsva?.h ?? hue
        }, 100%, 50%))`,
        ...containerStyle,
      }}
      ref={ref}
      onMove={handleChange}
      onDown={handleChange}
    >
      {pointerElement}
    </Interactive>
  );
});
 
Saturation.displayName = 'Saturation';
 
export default Saturation;