aboutsummaryrefslogtreecommitdiffstats
path: root/packages/excalidraw/components/ColorPicker/ShadeList.tsx
blob: 8d3d4cc2a47b61ed043d4363da903eddd2e1e9cf (plain) (blame)
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
import clsx from "clsx";
import { useAtom } from "../../editor-jotai";
import { useEffect, useRef } from "react";
import {
  activeColorPickerSectionAtom,
  getColorNameAndShadeFromColor,
} from "./colorPickerUtils";
import HotkeyLabel from "./HotkeyLabel";
import { t } from "../../i18n";
import type { ColorPaletteCustom } from "../../colors";

interface ShadeListProps {
  hex: string;
  onChange: (color: string) => void;
  palette: ColorPaletteCustom;
}

export const ShadeList = ({ hex, onChange, palette }: ShadeListProps) => {
  const colorObj = getColorNameAndShadeFromColor({
    color: hex || "transparent",
    palette,
  });

  const [activeColorPickerSection, setActiveColorPickerSection] = useAtom(
    activeColorPickerSectionAtom,
  );

  const btnRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    if (btnRef.current && activeColorPickerSection === "shades") {
      btnRef.current.focus();
    }
  }, [colorObj, activeColorPickerSection]);

  if (colorObj) {
    const { colorName, shade } = colorObj;

    const shades = palette[colorName];

    if (Array.isArray(shades)) {
      return (
        <div className="color-picker-content--default shades">
          {shades.map((color, i) => (
            <button
              ref={
                i === shade && activeColorPickerSection === "shades"
                  ? btnRef
                  : undefined
              }
              tabIndex={-1}
              key={i}
              type="button"
              className={clsx(
                "color-picker__button color-picker__button--large",
                { active: i === shade },
              )}
              aria-label="Shade"
              title={`${colorName} - ${i + 1}`}
              style={color ? { "--swatch-color": color } : undefined}
              onClick={() => {
                onChange(color);
                setActiveColorPickerSection("shades");
              }}
            >
              <div className="color-picker__button-outline" />
              <HotkeyLabel color={color} keyLabel={i + 1} isShade />
            </button>
          ))}
        </div>
      );
    }
  }

  return (
    <div
      className="color-picker-content--default"
      style={{ position: "relative" }}
      tabIndex={-1}
    >
      <button
        type="button"
        tabIndex={-1}
        className="color-picker__button color-picker__button--large color-picker__button--no-focus-visible"
      />
      <div
        tabIndex={-1}
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          textAlign: "center",
          fontSize: "0.75rem",
        }}
      >
        {t("colorPicker.noShades")}
      </div>
    </div>
  );
};