@wordpress/components
Version:
UI components for WordPress.
157 lines (156 loc) • 5.01 kB
JavaScript
// packages/components/src/color-picker/component.tsx
import { colord, extend, getFormat } from "colord";
import namesPlugin from "colord/plugins/names";
import { useCallback, useEffect, useRef, useState, useMemo } from "@wordpress/element";
import { useDebounce } from "@wordpress/compose";
import { __ } from "@wordpress/i18n";
import { useContextSystem, contextConnect } from "../context/index.mjs";
import { ColorfulWrapper, SelectControl, AuxiliaryColorArtefactWrapper, AuxiliaryColorArtefactHStackHeader, ColorInputWrapper } from "./styles.mjs";
import { ColorCopyButton } from "./color-copy-button.mjs";
import { ColorInput } from "./color-input.mjs";
import { Picker } from "./picker.mjs";
import { useControlledValue } from "../utils/hooks/index.mjs";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
extend([namesPlugin]);
function mergeHSLA(nextHSLA, prevHSLA) {
if (nextHSLA.s === 0) {
if (nextHSLA.l === 0 || nextHSLA.l === 100) {
return {
...nextHSLA,
h: prevHSLA.h,
s: prevHSLA.s
};
}
return {
...nextHSLA,
h: prevHSLA.h
};
}
return nextHSLA;
}
var options = [{
label: "RGB",
value: "rgb"
}, {
label: "HSL",
value: "hsl"
}, {
label: "Hex",
value: "hex"
}];
var UnconnectedColorPicker = (props, forwardedRef) => {
const {
enableAlpha = false,
color: colorProp,
onChange,
defaultValue = "#fff",
copyFormat,
...divProps
} = useContextSystem(props, "ColorPicker");
const [color, setColor] = useControlledValue({
onChange,
value: colorProp,
defaultValue
});
const safeColordColor = useMemo(() => {
return colord(color || "");
}, [color]);
const debouncedSetColor = useDebounce(setColor);
const [internalHSLA, setInternalHSLA] = useState(() => ({
...safeColordColor.toHsl()
}));
const lastProducedHexRef = useRef(safeColordColor.toHex());
useEffect(() => {
const incomingHex = safeColordColor.toHex();
if (incomingHex === lastProducedHexRef.current) {
return;
}
lastProducedHexRef.current = incomingHex;
const externalHSLA = safeColordColor.toHsl();
setInternalHSLA((prev) => mergeHSLA(externalHSLA, prev));
}, [safeColordColor]);
const handleHSLAChange = useCallback((nextHSLA) => {
setInternalHSLA(nextHSLA);
const previousHex = lastProducedHexRef.current;
const nextHex = colord(nextHSLA).toHex();
if (nextHex !== previousHex) {
lastProducedHexRef.current = nextHex;
setColor(nextHex);
}
}, [setColor]);
const handleChange = useCallback((nextValue) => {
const nextHSLA = nextValue.toHsl();
setInternalHSLA((prev) => mergeHSLA(nextHSLA, prev));
const nextHex = nextValue.toHex();
lastProducedHexRef.current = nextHex;
debouncedSetColor(nextHex);
}, [debouncedSetColor]);
const [colorType, setColorType] = useState(copyFormat || "hex");
const maybeHandlePaste = useCallback((event) => {
const pastedText = event.clipboardData?.getData("text")?.trim();
if (!pastedText) {
return;
}
const parsedColor = colord(pastedText);
if (!parsedColor.isValid()) {
return;
}
handleChange(parsedColor);
const supportedFormats = {
hex: "hex",
rgb: "rgb",
hsl: "hsl"
};
const detectedFormat = String(getFormat(pastedText));
const newColorType = supportedFormats[detectedFormat];
if (newColorType) {
setColorType(newColorType);
}
event.stopPropagation();
event.preventDefault();
}, [handleChange, setColorType]);
return /* @__PURE__ */ _jsxs(ColorfulWrapper, {
ref: forwardedRef,
...divProps,
onPasteCapture: maybeHandlePaste,
children: [/* @__PURE__ */ _jsx(Picker, {
onChange: handleHSLAChange,
hsla: internalHSLA,
enableAlpha
}), /* @__PURE__ */ _jsxs(AuxiliaryColorArtefactWrapper, {
children: [/* @__PURE__ */ _jsxs(AuxiliaryColorArtefactHStackHeader, {
justify: "space-between",
children: [/* @__PURE__ */ _jsx(SelectControl, {
size: "compact",
options,
value: colorType,
onChange: (nextColorType) => setColorType(nextColorType),
label: __("Color format"),
hideLabelFromVision: true,
variant: "minimal"
}), /* @__PURE__ */ _jsx(ColorCopyButton, {
color: safeColordColor,
colorType: copyFormat || colorType
})]
}), /* @__PURE__ */ _jsx(ColorInputWrapper, {
direction: "column",
gap: 2,
children: /* @__PURE__ */ _jsx(ColorInput, {
colorType,
color: safeColordColor,
hsla: internalHSLA,
onChange: handleChange,
onHSLChange: handleHSLAChange,
enableAlpha
})
})]
})]
});
};
var ColorPicker = contextConnect(UnconnectedColorPicker, "ColorPicker");
var component_default = ColorPicker;
export {
ColorPicker,
component_default as default
};
//# sourceMappingURL=component.mjs.map