Try adding deferred prop in the ColorPicker. With deferred set to true, change handler only fires when you click the SET button to commit the change:
<ColorPicker value={color} onChange={handleChange} deferred />
EDIT: If you really really want to listen to the mouseup event, you need to do some dirty work using plain JS:
function MyColorPicker({ onChange }) {
const [open, setOpen] = useState(false);
const [, forceRender] = useReducer((x) => ++x, 0);
const colorRef = useRef<Color>();
const handleChange = (newValue: Color) => {
colorRef.current = newValue;
forceRender();
};
React.useEffect(() => {
let colorGradientEl = null;
let hueSliderEl = null;
let alphaSliderEl = null;
let inputEls = [];
const handleMouseUp = () => onChange(colorRef.current);
if (open) {
setTimeout(() => {
colorGradientEl = document.querySelector(
'[data-testid="hsvgradient-color"]'
);
hueSliderEl = document.querySelector('[data-testid="hueslider"]');
alphaSliderEl = document.querySelector('[data-testid="alphaslider"]');
inputEls = [...document.querySelectorAll("input")];
const colorPickerPopoverEl = document.querySelector(
".ColorPicker-MuiPopover-root"
);
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.removedNodes) {
setOpen(false);
}
observer.disconnect();
});
});
observer.observe(colorPickerPopoverEl!, { childList: true });
colorGradientEl?.addEventListener("mouseup", handleMouseUp);
hueSliderEl?.addEventListener("mouseup", handleMouseUp);
alphaSliderEl?.addEventListener("mouseup", handleMouseUp);
inputEls.forEach((el) => {
el.addEventListener("change", handleMouseUp);
});
}, 10);
}
return () => {
colorGradientEl?.removeEventListener("mouseup", handleMouseUp);
hueSliderEl?.removeEventListener("mouseup", handleMouseUp);
alphaSliderEl?.removeEventListener("mouseup", handleMouseUp);
inputEls.forEach((el) => {
el.removeEventListener("change", handleMouseUp);
});
};
}, [open]);
return (
<ColorPicker
onOpen={() => setOpen(true)}
value={colorRef.current}
onChange={handleChange}
/>
);
}
Usage
MyColorPicker now only fires change handler when the user stops dragging the mouse:
<MyColorPicker onChange={handleChange} />
