diff --git a/src/components/ColorPicker/ColorInput.tsx b/src/components/ColorPicker/ColorInput.tsx index f179d415..968729cc 100644 --- a/src/components/ColorPicker/ColorInput.tsx +++ b/src/components/ColorPicker/ColorInput.tsx @@ -15,9 +15,15 @@ interface ColorInputProps { color: string; onChange: (color: string) => void; label: string; + eyeDropperType: "strokeColor" | "backgroundColor"; } -export const ColorInput = ({ color, onChange, label }: ColorInputProps) => { +export const ColorInput = ({ + color, + onChange, + label, + eyeDropperType, +}: ColorInputProps) => { const device = useDevice(); const [innerValue, setInnerValue] = useState(color); const [activeSection, setActiveColorPickerSection] = useAtom( @@ -110,6 +116,7 @@ export const ColorInput = ({ color, onChange, label }: ColorInputProps) => { : { keepOpenOnAlt: false, onSelect: (color) => onChange(color), + previewType: eyeDropperType, }, ) } diff --git a/src/components/ColorPicker/ColorPicker.tsx b/src/components/ColorPicker/ColorPicker.tsx index d2f89c81..4a378950 100644 --- a/src/components/ColorPicker/ColorPicker.tsx +++ b/src/components/ColorPicker/ColorPicker.tsx @@ -82,7 +82,14 @@ const ColorPickerPopupContent = ({ const { container } = useExcalidrawContainer(); const { isMobile, isLandscape } = useDevice(); - const colorInputJSX = ( + const eyeDropperType = + type === "canvasBackground" + ? undefined + : type === "elementBackground" + ? "backgroundColor" + : "strokeColor"; + + const colorInputJSX = eyeDropperType && (
{t("colorPicker.hexCode")} { onChange(color); }} + eyeDropperType={eyeDropperType} />
); @@ -140,7 +148,7 @@ const ColorPickerPopupContent = ({ alignOffset={-16} sideOffset={20} style={{ - zIndex: 9999, + zIndex: "var(--zIndex-layerUI)", backgroundColor: "var(--popup-bg-color)", maxWidth: "208px", maxHeight: window.innerHeight, @@ -152,7 +160,7 @@ const ColorPickerPopupContent = ({ "0px 7px 14px rgba(0, 0, 0, 0.05), 0px 0px 3.12708px rgba(0, 0, 0, 0.0798), 0px 0px 0.931014px rgba(0, 0, 0, 0.1702)", }} > - {palette ? ( + {palette && eyeDropperType ? ( void; - previewType?: "strokeColor" | "backgroundColor"; + onSelect: (color: string, event: PointerEvent) => void; + previewType: "strokeColor" | "backgroundColor"; }; export const activeEyeDropperAtom = atom(null); @@ -28,13 +28,8 @@ export const EyeDropper: React.FC<{ onCancel: () => void; onSelect: Required["onSelect"]; swapPreviewOnAlt?: EyeDropperProperties["swapPreviewOnAlt"]; - previewType?: EyeDropperProperties["previewType"]; -}> = ({ - onCancel, - onSelect, - swapPreviewOnAlt, - previewType = "backgroundColor", -}) => { + previewType: EyeDropperProperties["previewType"]; +}> = ({ onCancel, onSelect, swapPreviewOnAlt, previewType }) => { const eyeDropperContainer = useCreatePortalContainer({ className: "excalidraw-eye-dropper-backdrop", parentSelector: ".excalidraw-eye-dropper-container", @@ -58,11 +53,27 @@ export const EyeDropper: React.FC<{ return; } - let currentColor: string = COLOR_PALETTE.black; let isHoldingPointerDown = false; const ctx = app.canvas.getContext("2d")!; + const getCurrentColor = ({ + clientX, + clientY, + }: { + clientX: number; + clientY: number; + }) => { + const pixel = ctx.getImageData( + (clientX - appState.offsetLeft) * window.devicePixelRatio, + (clientY - appState.offsetTop) * window.devicePixelRatio, + 1, + 1, + ).data; + + return rgbToHex(pixel[0], pixel[1], pixel[2]); + }; + const mouseMoveListener = ({ clientX, clientY, @@ -76,14 +87,7 @@ export const EyeDropper: React.FC<{ colorPreviewDiv.style.top = `${clientY + 20}px`; colorPreviewDiv.style.left = `${clientX + 20}px`; - const pixel = ctx.getImageData( - (clientX - appState.offsetLeft) * window.devicePixelRatio, - (clientY - appState.offsetTop) * window.devicePixelRatio, - 1, - 1, - ).data; - - currentColor = rgbToHex(pixel[0], pixel[1], pixel[2]); + const currentColor = getCurrentColor({ clientX, clientY }); if (isHoldingPointerDown) { for (const element of metaStuffRef.current.selectedElements) { @@ -125,7 +129,7 @@ export const EyeDropper: React.FC<{ event.stopImmediatePropagation(); event.preventDefault(); - onSelect(currentColor, event); + onSelect(getCurrentColor(event), event); }; const keyDownListener = (event: KeyboardEvent) => { diff --git a/src/css/styles.scss b/src/css/styles.scss index f1d359d5..d46ab1bc 100644 --- a/src/css/styles.scss +++ b/src/css/styles.scss @@ -6,6 +6,8 @@ --zIndex-interactiveCanvas: 2; --zIndex-wysiwyg: 3; --zIndex-layerUI: 4; + --zIndex-eyeDropperBackdrop: 5; + --zIndex-eyeDropperPreview: 6; --zIndex-modal: 1000; --zIndex-popup: 1001; diff --git a/src/types.ts b/src/types.ts index bc777086..f07b1340 100644 --- a/src/types.ts +++ b/src/types.ts @@ -507,8 +507,9 @@ export type AppProps = Merge< * in the app, eg Manager. Factored out into a separate type to keep DRY. */ export type AppClassProperties = { props: AppProps; - canvas: HTMLCanvasElement; interactiveCanvas: HTMLCanvasElement | null; + /** static canvas */ + canvas: HTMLCanvasElement; focusContainer(): void; library: Library; imageCache: Map<