ant-design/ant-design

View on GitHub
.dumi/theme/common/Color/Palette.tsx

Summary

Maintainability
B
4 hrs
Test Coverage
import React, { useEffect } from 'react';
import { presetDarkPalettes } from '@ant-design/colors';
import { message } from 'antd';
import CopyToClipboard from 'react-copy-to-clipboard';

const rgbToHex = (rgbString: string): string => {
  const rgb = rgbString.match(/\d+/g);
  let r = parseInt(rgb[0], 10).toString(16);
  let g = parseInt(rgb[1], 10).toString(16);
  let b = parseInt(rgb[2], 10).toString(16);
  r = r.length === 1 ? `0${r}` : r;
  g = g.length === 1 ? `0${g}` : g;
  b = b.length === 1 ? `0${b}` : b;
  return `#${r}${g}${b}`;
};

interface PaletteProps {
  showTitle?: boolean;
  direction?: 'horizontal' | 'vertical';
  dark?: boolean;
  color?: {
    name: string;
    count?: number;
    description?: string;
    english?: string;
    chinese?: string;
  };
}

const Palette: React.FC<PaletteProps> = (props) => {
  const {
    showTitle,
    direction,
    dark,
    color: { name, count = 10, description, english, chinese } = { name: 'gray', count: 13 },
  } = props;
  const [hexColors, setHexColors] = React.useState<Record<PropertyKey, string>>({});
  const colorNodesRef = React.useRef<Record<PropertyKey, HTMLDivElement>>({});

  useEffect(() => {
    const colors = {};
    Object.keys(colorNodesRef.current || {}).forEach((key) => {
      const computedColor = getComputedStyle(colorNodesRef.current[key])['background-color'];
      if (computedColor.includes('rgba')) {
        colors[key] = computedColor;
      } else {
        colors[key] = rgbToHex(computedColor);
      }
    });
    setHexColors(colors);
  }, []);

  const className = direction === 'horizontal' ? 'color-palette-horizontal' : 'color-palette';
  const colors: React.ReactNode[] = [];
  const colorName = `${english} / ${chinese}`;
  const colorPaletteMap = {
    dark: ['#fff', 'unset'],
    default: ['rgba(0, 0, 0, 0.85)', '#fff'],
  };
  const [lastColor, firstColor] = dark ? colorPaletteMap.dark : colorPaletteMap.default;
  for (let i = 1; i <= count; i += 1) {
    const colorText = `${name}-${i}`;
    const defaultBgStyle = dark ? presetDarkPalettes[name][i - 1] : '';
    colors.push(
      <CopyToClipboard
        text={hexColors[colorText]}
        onCopy={() => message.success(`@${colorText} copied: ${hexColors[colorText]}`)}
        key={colorText}
      >
        <div
          key={i}
          ref={(node) => {
            colorNodesRef.current[`${name}-${i}`] = node;
          }}
          className={`main-color-item palette-${name}-${i}`}
          style={{
            color: (name === 'yellow' ? i > 6 : i > 5) ? firstColor : lastColor,
            fontWeight: i === 6 ? 'bold' : 'normal',
            backgroundColor: defaultBgStyle,
          }}
          title="click to copy color"
        >
          <span className="main-color-text">{colorText}</span>
          <span className="main-color-value">{hexColors[colorText]}</span>
        </div>
      </CopyToClipboard>,
    );
  }
  return (
    <div className={className}>
      {showTitle && (
        <div className="color-title">
          {colorName}
          <span className="color-description">{description}</span>
        </div>
      )}
      <div className="main-color">{colors}</div>
    </div>
  );
};

export default Palette;