diff --git a/packages/common/src/colors.ts b/packages/common/src/colors.ts index 567093c7d9..f6bced8b67 100644 --- a/packages/common/src/colors.ts +++ b/packages/common/src/colors.ts @@ -80,7 +80,11 @@ const cssInvert = ( return { r: invertedR, g: invertedG, b: invertedB }; }; -export const applyDarkModeFilter = (color: string): string => { +export const applyDarkModeFilter = (color: string, enable = true): string => { + if (!enable) { + return color; + } + const cached = DARK_MODE_COLORS_CACHE?.get(color); if (cached) { return cached; diff --git a/packages/element/src/renderElement.ts b/packages/element/src/renderElement.ts index f84bba09c7..980b3b1fae 100644 --- a/packages/element/src/renderElement.ts +++ b/packages/element/src/renderElement.ts @@ -554,10 +554,10 @@ const drawElementOnCanvas = ( context.canvas.setAttribute("dir", rtl ? "rtl" : "ltr"); context.save(); context.font = getFontString(element); - context.fillStyle = - renderConfig.theme === THEME.DARK - ? applyDarkModeFilter(element.strokeColor) - : element.strokeColor; + context.fillStyle = applyDarkModeFilter( + element.strokeColor, + renderConfig.theme === THEME.DARK, + ); context.textAlign = element.textAlign as CanvasTextAlign; // Canvas does not support multiline text by default @@ -851,10 +851,10 @@ export const renderElement = ( context.fillStyle = "rgba(0, 0, 200, 0.04)"; context.lineWidth = FRAME_STYLE.strokeWidth / appState.zoom.value; - context.strokeStyle = - appState.theme === THEME.DARK - ? applyDarkModeFilter(FRAME_STYLE.strokeColor) - : FRAME_STYLE.strokeColor; + context.strokeStyle = applyDarkModeFilter( + FRAME_STYLE.strokeColor, + appState.theme === THEME.DARK, + ); // TODO change later to only affect AI frames if (isMagicFrameElement(element)) { diff --git a/packages/element/src/renderFreedraw.ts b/packages/element/src/renderFreedraw.ts index 2fa69ff950..a61a644f87 100644 --- a/packages/element/src/renderFreedraw.ts +++ b/packages/element/src/renderFreedraw.ts @@ -163,7 +163,10 @@ export const drawFreeDrawSegments = ( ? applyDarkModeFilter(element.strokeColor) : element.strokeColor; - context.fillStyle = strokeColor; + context.fillStyle = applyDarkModeFilter( + strokeColor, + renderConfig.theme === THEME.DARK, + ); const baseRadius = (element.strokeWidth * 1.25) / 2; diff --git a/packages/element/src/shape.ts b/packages/element/src/shape.ts index e3f0cc28c8..41d8977296 100644 --- a/packages/element/src/shape.ts +++ b/packages/element/src/shape.ts @@ -218,9 +218,7 @@ export const generateRoughOptions = ( fillWeight: element.strokeWidth / 2, hachureGap: element.strokeWidth * 4, roughness: adjustRoughness(element), - stroke: isDarkMode - ? applyDarkModeFilter(element.strokeColor) - : element.strokeColor, + stroke: applyDarkModeFilter(element.strokeColor, isDarkMode), preserveVertices: continuousPath || element.roughness < ROUGHNESS.cartoonist, }; @@ -234,9 +232,7 @@ export const generateRoughOptions = ( options.fillStyle = element.fillStyle; options.fill = isTransparent(element.backgroundColor) ? undefined - : isDarkMode - ? applyDarkModeFilter(element.backgroundColor) - : element.backgroundColor; + : applyDarkModeFilter(element.backgroundColor, isDarkMode); if (element.type === "ellipse") { options.curveFitting = 1; } @@ -249,9 +245,7 @@ export const generateRoughOptions = ( options.fill = element.backgroundColor === "transparent" ? undefined - : isDarkMode - ? applyDarkModeFilter(element.backgroundColor) - : element.backgroundColor; + : applyDarkModeFilter(element.backgroundColor, isDarkMode); } return options; } @@ -386,12 +380,11 @@ const getArrowheadShapes = ( return []; } - const strokeColor = isDarkMode - ? applyDarkModeFilter(element.strokeColor) - : element.strokeColor; - const backgroundFillColor = isDarkMode - ? applyDarkModeFilter(canvasBackgroundColor) - : canvasBackgroundColor; + const strokeColor = applyDarkModeFilter(element.strokeColor, isDarkMode); + const backgroundFillColor = applyDarkModeFilter( + canvasBackgroundColor, + isDarkMode, + ); const cardinalityOneOrManyOffset = -0.25; const cardinalityZeroCircleScale = 0.8; diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 2a1d922c01..9442692c80 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -1995,9 +1995,10 @@ class App extends React.Component { } }} style={{ - background: isDarkTheme - ? applyDarkModeFilter(this.state.viewBackgroundColor) - : this.state.viewBackgroundColor, + background: applyDarkModeFilter( + this.state.viewBackgroundColor, + isDarkTheme, + ), zIndex: 2, border: "none", display: "block", diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index 64cedb3a8e..b56e568b60 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -7,6 +7,7 @@ import React, { } from "react"; import { + applyDarkModeFilter, DEFAULT_IMAGE_OPTIONS, DEFAULT_UI_OPTIONS, isShallowEqual, @@ -450,3 +451,5 @@ export function useExcalidrawStateValue( // ----------------------------------------------------------------------------- export { _useOnAppStateChange as useOnExcalidrawStateChange }; + +export { applyDarkModeFilter }; diff --git a/packages/excalidraw/renderer/helpers.ts b/packages/excalidraw/renderer/helpers.ts index 8fd70428f0..e5025dcd09 100644 --- a/packages/excalidraw/renderer/helpers.ts +++ b/packages/excalidraw/renderer/helpers.ts @@ -62,10 +62,10 @@ export const bootstrapCanvas = ({ context.clearRect(0, 0, normalizedWidth, normalizedHeight); } context.save(); - context.fillStyle = - theme === THEME.DARK - ? applyDarkModeFilter(viewBackgroundColor) - : viewBackgroundColor; + context.fillStyle = applyDarkModeFilter( + viewBackgroundColor, + theme === THEME.DARK, + ); context.fillRect(0, 0, normalizedWidth, normalizedHeight); context.restore(); } else { diff --git a/packages/excalidraw/renderer/staticSvgScene.ts b/packages/excalidraw/renderer/staticSvgScene.ts index 2cc632411c..9cc63e74c8 100644 --- a/packages/excalidraw/renderer/staticSvgScene.ts +++ b/packages/excalidraw/renderer/staticSvgScene.ts @@ -392,6 +392,13 @@ const renderElementToSvg = ( if (typeof shape === "string") { // stroke (SVGPathString) — fill inherited from wrapper const path = svgRoot.ownerDocument.createElementNS(SVG_NS, "path"); + path.setAttribute( + "fill", + applyDarkModeFilter( + element.strokeColor, + renderConfig.theme === THEME.DARK, + ), + ); path.setAttribute("d", shape); wrapper.appendChild(path); } else { @@ -623,9 +630,10 @@ const renderElementToSvg = ( rect.setAttribute("fill", "none"); rect.setAttribute( "stroke", - renderConfig.theme === THEME.DARK - ? applyDarkModeFilter(FRAME_STYLE.strokeColor) - : FRAME_STYLE.strokeColor, + applyDarkModeFilter( + FRAME_STYLE.strokeColor, + renderConfig.theme === THEME.DARK, + ), ); rect.setAttribute("stroke-width", FRAME_STYLE.strokeWidth.toString()); @@ -679,9 +687,10 @@ const renderElementToSvg = ( text.setAttribute("font-size", `${element.fontSize}px`); text.setAttribute( "fill", - renderConfig.theme === THEME.DARK - ? applyDarkModeFilter(element.strokeColor) - : element.strokeColor, + applyDarkModeFilter( + element.strokeColor, + renderConfig.theme === THEME.DARK, + ), ); text.setAttribute("text-anchor", textAnchor); text.setAttribute("style", "white-space: pre;"); diff --git a/packages/excalidraw/scene/export.ts b/packages/excalidraw/scene/export.ts index 8d8c405e82..eef553d4c7 100644 --- a/packages/excalidraw/scene/export.ts +++ b/packages/excalidraw/scene/export.ts @@ -459,9 +459,7 @@ export const exportToSvg = async ( rect.setAttribute("height", `${height}`); rect.setAttribute( "fill", - exportWithDarkMode - ? applyDarkModeFilter(viewBackgroundColor) - : viewBackgroundColor, + applyDarkModeFilter(viewBackgroundColor, exportWithDarkMode), ); svgRoot.appendChild(rect); } diff --git a/packages/excalidraw/wysiwyg/textWysiwyg.tsx b/packages/excalidraw/wysiwyg/textWysiwyg.tsx index 262558727c..eeee206fa7 100644 --- a/packages/excalidraw/wysiwyg/textWysiwyg.tsx +++ b/packages/excalidraw/wysiwyg/textWysiwyg.tsx @@ -392,10 +392,10 @@ export const textWysiwyg = ({ ), textAlign, verticalAlign, - color: - appState.theme === THEME.DARK - ? applyDarkModeFilter(updatedTextElement.strokeColor) - : updatedTextElement.strokeColor, + color: applyDarkModeFilter( + updatedTextElement.strokeColor, + appState.theme === THEME.DARK, + ), opacity: updatedTextElement.opacity / 100, maxHeight: `${editorMaxHeight}px`, });