sanity-plugin-simpler-color-input
Version:
274 lines (273 loc) • 10.9 kB
JavaScript
import { set, unset, defineType, definePlugin } from "sanity";
import { jsx, jsxs } from "react/jsx-runtime";
import { ChevronDownIcon, CloseIcon, SearchIcon } from "@sanity/icons";
import { Container, Popover, Flex, Button, Box, Card, Text, Inline, TextInput, Stack } from "@sanity/ui";
import { useState, useCallback, useRef, useEffect } from "react";
import { BiHighlight, BiFontColor } from "react-icons/bi";
import styled from "styled-components";
const SimplerColorInput = (props) => {
const [isOpen, setIsOpen] = useState(!1), [pickerIsOpen, setPickerIsOpen] = useState(!1), [searchValue, setSearchValue] = useState(""), { onChange } = props, value = props.value, type = props.schemaType, showColorValue = !!(type.options?.showColorValue ?? !0), [selectedColor, setSelectedColor] = useState(value), handleChange = useCallback(
(color) => {
setSelectedColor(color), setIsOpen(!1), onChange(set({ ...props.value, ...color }));
},
[onChange, props.value]
), colorList = type.options?.colorList || type.type?.options?.defaultColorList, colorFormat = type.options?.colorFormat ?? type.type?.options?.defaultColorFormat, enableSearch = !!(type.options?.enableSearch ?? type.type?.options?.enableSearch), filteredColorList = searchValue.length ? colorList?.filter((color) => color.label.toLowerCase().includes(searchValue.toLowerCase())) : colorList, handlePickerChange = (color) => {
let colorValue;
switch (colorFormat) {
case "hexa":
colorValue = color.hexa;
break;
case "rgb":
colorValue = `rgb(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b})`;
break;
case "rgba":
colorValue = `rgba(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b}, ${color.rgba.a.toFixed(2)})`;
break;
case "hsl":
colorValue = `hsl(${color.hsl.h.toFixed(0)}, ${color.hsl.s.toFixed(
0
)}%, ${color.hsl.l.toFixed(0)}%)`;
break;
case "hsla":
colorValue = `hsla(${color.hsla.h.toFixed(0)}, ${color.hsla.s.toFixed(
0
)}%, ${color.hsla.l.toFixed(0)}%, ${color.hsla.a.toFixed(2)})`;
break;
default:
colorValue = color.hex;
break;
}
const formattedColor = {
label: "Custom",
value: colorValue
};
setSelectedColor(formattedColor), onChange(set({ ...props.value, ...formattedColor }));
}, ref = useRef(null);
useEffect(() => {
isOpen || setSearchValue("");
const handleClickOutside = (event) => {
ref.current && !ref.current.contains(event.target) && (setPickerIsOpen(!1), setIsOpen(!1));
};
return document.addEventListener("click", handleClickOutside, !0), () => {
document.removeEventListener("click", handleClickOutside, !0);
};
}, [isOpen, pickerIsOpen, ref]);
const isRequired = type.validation[0]._required === "required", [Component, setComponent] = useState(/* @__PURE__ */ jsx("div", { children: "Loading..." }));
return useEffect(() => {
import("@uiw/react-color").then((module) => {
const { Chrome, rgbStringToHsva, hslStringToHsva } = module;
let pickerColor = selectedColor?.value || "#ffffff";
pickerColor.startsWith("rgb") ? pickerColor = rgbStringToHsva(pickerColor) : pickerColor.startsWith("hsl") && (pickerColor = hslStringToHsva(pickerColor)), setComponent(
/* @__PURE__ */ jsxs(Container, { children: [
/* @__PURE__ */ jsx(
Popover,
{
ref,
content: /* @__PURE__ */ jsx(
Chrome,
{
onChange: handlePickerChange,
color: pickerColor,
showAlpha: colorFormat ? colorFormat.slice(-1) === "a" : !1
}
),
portal: !0,
open: pickerIsOpen,
children: /* @__PURE__ */ jsxs(Flex, { children: [
/* @__PURE__ */ jsx(
Button,
{
style: {
width: "100%",
textAlign: "center",
borderTopRightRadius: isRequired ? "" : "0",
borderBottomRightRadius: isRequired ? "" : "0",
flexShrink: 1,
overflow: "hidden"
},
mode: "ghost",
padding: 2,
onClick: () => colorList && colorList.length > 0 ? setIsOpen(!isOpen) : setPickerIsOpen(!pickerIsOpen),
children: /* @__PURE__ */ jsxs(Flex, { justify: "center", gap: 4, children: [
/* @__PURE__ */ jsxs(Flex, { align: "center", gap: 1, overflow: "hidden", children: [
/* @__PURE__ */ jsx(Box, { style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx(
Card,
{
style: { backgroundColor: selectedColor?.value || "#ffffff" },
radius: 2,
shadow: 1,
padding: 2,
margin: 1
}
) }),
/* @__PURE__ */ jsx(Box, { style: { ...showColorValue && { flexShrink: 0 } }, children: /* @__PURE__ */ jsxs(Text, { weight: "semibold", textOverflow: "ellipsis", children: [
selectedColor?.label || "Select a color...",
" "
] }) }),
showColorValue && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { textOverflow: "ellipsis", children: selectedColor?.value }) })
] }),
/* @__PURE__ */ jsx(ChevronDownIcon, { style: { flexShrink: 0 }, width: 32, height: 32 })
] })
}
),
!isRequired && /* @__PURE__ */ jsx(
Button,
{
mode: "ghost",
onClick: () => {
if (value !== void 0 && value._key) {
const annotationValue = { _type: value._type, _key: value._key };
setSelectedColor(annotationValue), onChange(set(annotationValue));
} else
setSelectedColor(void 0), onChange(unset());
},
style: { borderTopLeftRadius: "0", borderBottomLeftRadius: "0" },
children: /* @__PURE__ */ jsxs(Inline, { space: 1, children: [
/* @__PURE__ */ jsx(CloseIcon, { width: 24, height: 24 }),
/* @__PURE__ */ jsx(Text, { weight: "semibold", children: "Clear" })
] })
}
)
] })
}
),
isOpen && colorList && /* @__PURE__ */ jsxs(Card, { radius: 2, shadow: 3, marginTop: 1, overflow: "hidden", children: [
enableSearch && /* @__PURE__ */ jsx(
Box,
{
padding: 3,
style: {
borderBottom: "1px solid var(--card-border-color)"
},
children: /* @__PURE__ */ jsx(
TextInput,
{
icon: SearchIcon,
radius: 2,
placeholder: "Search",
onChange: (event) => {
setSearchValue(event.currentTarget.value);
},
autoFocus: !0
}
)
}
),
/* @__PURE__ */ jsx(Stack, { children: filteredColorList?.map(
(color) => color.value === "custom" ? /* @__PURE__ */ jsx(
Button,
{
radius: 0,
mode: "bleed",
onClick: () => {
setIsOpen(!1), setPickerIsOpen(!0);
},
children: /* @__PURE__ */ jsx(Text, { children: color.label })
},
color.label
) : /* @__PURE__ */ jsx(
Button,
{
radius: 0,
mode: "bleed",
onClick: () => handleChange(color),
children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Inline, { space: 3, children: [
/* @__PURE__ */ jsx(
Card,
{
style: { backgroundColor: color.value, width: "16px", height: "16px" },
radius: 2,
shadow: 1
}
),
/* @__PURE__ */ jsx(Text, { children: color.label })
] }) })
},
color.label
)
) })
] })
] })
);
});
}, [isOpen, selectedColor, searchValue, pickerIsOpen]), Component;
}, ColorSpan$1 = styled.span`
& > span {
background-color: ${({ color }) => color};
border-bottom: unset;
color: inherit;
}
`, HighlightColorAnnotation = (props) => /* @__PURE__ */ jsx(ColorSpan$1, { color: props.value?.value || "", children: props.renderDefault(props) }), highlightColor = defineType({
title: "Highlight color",
type: "object",
name: "highlightColor",
icon: BiHighlight,
components: {
annotation: HighlightColorAnnotation,
input: SimplerColorInput
},
fields: [
{
name: "label",
type: "string"
},
{
name: "value",
type: "string"
}
]
}), simplerColor = defineType({
title: "Simpler Color",
type: "object",
name: "simplerColor",
components: { input: SimplerColorInput },
fields: [
{
name: "label",
type: "string"
},
{
name: "value",
type: "string"
}
]
}), ColorSpan = styled.span`
& > span {
background-color: inherit;
border-bottom: unset;
color: ${({ color }) => color};
}
`, TextColorAnnotation = (props) => /* @__PURE__ */ jsx(ColorSpan, { color: props.value?.value || "", children: props.renderDefault(props) }), textColor = defineType({
title: "Text color",
type: "object",
name: "textColor",
icon: BiFontColor,
components: {
annotation: TextColorAnnotation,
input: SimplerColorInput
},
fields: [
{
name: "label",
type: "string"
},
{
name: "value",
type: "string"
}
]
}), simplerColorInput = definePlugin((options) => ({
name: "sanity-plugin-simpler-color-input",
schema: {
types: [
{ ...simplerColor, options },
{ ...textColor, options },
{ ...highlightColor, options }
]
}
}));
export {
SimplerColorInput,
simplerColorInput
};
//# sourceMappingURL=index.mjs.map