All files / color-swatch/src index.tsx

100% Statements 23/23
100% Branches 34/34
100% Functions 5/5
100% Lines 23/23

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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119                                            1x                         7x 7x                         7x 2x   7x                               20x 20x 20x 12x 12x   20x 8x 8x   20x   20x           1x   20x 4x     16x           16x         1x                       1x      
import React, { Fragment } from 'react';
import { HsvaColor, hexToHsva, color as handleColor, ColorResult } from '@uiw/color-convert';
 
export type SwatchPresetColor = { color: string; title?: string } | string;
export interface SwatchRectRenderProps extends React.HTMLAttributes<HTMLDivElement> {
  title: string;
  color: string;
  checked: boolean;
  style: React.CSSProperties;
  onClick: (evn: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
}
export interface SwatchProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'> {
  prefixCls?: string;
  color?: string;
  colors?: SwatchPresetColor[];
  rectProps?: React.HTMLAttributes<HTMLDivElement>;
  rectRender?: (props: SwatchRectRenderProps) => JSX.Element | undefined;
  onChange?: (hsva: HsvaColor, color: ColorResult, evn: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
  addonAfter?: React.ReactNode;
  addonBefore?: React.ReactNode;
}
 
const Swatch = React.forwardRef<HTMLDivElement, SwatchProps>((props, ref) => {
  const {
    prefixCls = 'w-color-swatch',
    className,
    color,
    colors = [],
    style,
    rectProps = {},
    onChange,
    addonAfter,
    addonBefore,
    rectRender,
    ...other
  } = props;
  const rectStyle = {
    '--swatch-background-color': 'rgb(144, 19, 254)',
    background: 'var(--swatch-background-color)',
    height: 15,
    width: 15,
    marginRight: 5,
    marginBottom: 5,
    cursor: 'pointer',
    position: 'relative',
    outline: 'none',
    borderRadius: 2,
    ...rectProps.style,
  } as React.CSSProperties;
  const handleClick = (hex: string, evn: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    onChange && onChange(hexToHsva(hex), handleColor(hexToHsva(hex)), evn);
  };
  return (
    <div
      ref={ref}
      {...other}
      className={[prefixCls, className || ''].filter(Boolean).join(' ')}
      style={{
        display: 'flex',
        flexWrap: 'wrap',
        position: 'relative',
        ...style,
      }}
    >
      {addonBefore && React.isValidElement(addonBefore) && addonBefore}
      {colors &&
        Array.isArray(colors) &&
        colors.map((item, idx) => {
          let title = '';
          let background = '';
          if (typeof item === 'string') {
            title = item;
            background = item;
          }
          if (typeof item === 'object' && item.color) {
            title = item.title || item.color;
            background = item.color;
          }
          const checked = color && color.toLocaleLowerCase() === background.toLocaleLowerCase();
          const render =
            rectRender &&
            rectRender({
              title,
              color: background,
              checked: !!checked,
              style: { ...rectStyle, background },
              onClick: (evn) => handleClick(background, evn),
            });
          if (render) {
            return <Fragment key={idx}>{render}</Fragment>;
          }
          const child =
            rectProps.children && React.isValidElement(rectProps.children)
              ? React.cloneElement<any>(rectProps.children, {
                  color: background,
                  checked,
                })
              : null;
          return (
            <div
              tabIndex={0}
              key={idx}
              title={title}
              onClick={(evn) => handleClick(background, evn)}
              {...rectProps}
              children={child}
              style={{ ...rectStyle, background }}
            />
          );
        })}
      {addonAfter && React.isValidElement(addonAfter) && addonAfter}
    </div>
  );
});
 
Swatch.displayName = 'Swatch';
 
export default Swatch;