fix: default light theme splash 🔧 (#5660)
Co-authored-by: dwelle <luzar.david@gmail.com> Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
		
							parent
							
								
									ec4b3d913e
								
							
						
					
					
						commit
						7eaf47c9d4
					
				| 
						 | 
				
			
			@ -137,7 +137,6 @@ export class ActionManager {
 | 
			
		|||
   */
 | 
			
		||||
  renderAction = (name: ActionName, data?: PanelComponentProps["data"]) => {
 | 
			
		||||
    const canvasActions = this.app.props.UIOptions.canvasActions;
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      this.actions[name] &&
 | 
			
		||||
      "PanelComponent" in this.actions[name] &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -552,10 +552,6 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		|||
                    typeof this.props?.zenModeEnabled === "undefined" &&
 | 
			
		||||
                    this.state.zenModeEnabled
 | 
			
		||||
                  }
 | 
			
		||||
                  showThemeBtn={
 | 
			
		||||
                    typeof this.props?.theme === "undefined" &&
 | 
			
		||||
                    this.props.UIOptions.canvasActions.theme
 | 
			
		||||
                  }
 | 
			
		||||
                  libraryReturnUrl={this.props.libraryReturnUrl}
 | 
			
		||||
                  UIOptions={this.props.UIOptions}
 | 
			
		||||
                  focusContainer={this.focusContainer}
 | 
			
		||||
| 
						 | 
				
			
			@ -645,7 +641,8 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		|||
        let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
 | 
			
		||||
        let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
 | 
			
		||||
        let gridSize = actionResult?.appState?.gridSize || null;
 | 
			
		||||
        let theme = actionResult?.appState?.theme || THEME.LIGHT;
 | 
			
		||||
        const theme =
 | 
			
		||||
          actionResult?.appState?.theme || this.props.theme || THEME.LIGHT;
 | 
			
		||||
        let name = actionResult?.appState?.name ?? this.state.name;
 | 
			
		||||
        if (typeof this.props.viewModeEnabled !== "undefined") {
 | 
			
		||||
          viewModeEnabled = this.props.viewModeEnabled;
 | 
			
		||||
| 
						 | 
				
			
			@ -659,10 +656,6 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		|||
          gridSize = this.props.gridModeEnabled ? GRID_SIZE : null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (typeof this.props.theme !== "undefined") {
 | 
			
		||||
          theme = this.props.theme;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (typeof this.props.name !== "undefined") {
 | 
			
		||||
          name = this.props.name;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -755,6 +748,9 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		|||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.props.theme) {
 | 
			
		||||
      this.setState({ theme: this.props.theme });
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.state.isLoading) {
 | 
			
		||||
      this.setState({ isLoading: true });
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -784,6 +780,7 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		|||
    const scene = restore(initialData, null, null);
 | 
			
		||||
    scene.appState = {
 | 
			
		||||
      ...scene.appState,
 | 
			
		||||
      theme: this.props.theme || scene.appState.theme,
 | 
			
		||||
      // we're falling back to current (pre-init) state when deciding
 | 
			
		||||
      // whether to open the library, to handle a case where we
 | 
			
		||||
      // update the state outside of initialData (e.g. when loading the app
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,20 +1,12 @@
 | 
			
		|||
import React from "react";
 | 
			
		||||
import { ActionManager } from "../actions/manager";
 | 
			
		||||
import { AppState } from "../types";
 | 
			
		||||
 | 
			
		||||
export const BackgroundPickerAndDarkModeToggle = ({
 | 
			
		||||
  appState,
 | 
			
		||||
  setAppState,
 | 
			
		||||
  actionManager,
 | 
			
		||||
  showThemeBtn,
 | 
			
		||||
}: {
 | 
			
		||||
  actionManager: ActionManager;
 | 
			
		||||
  appState: AppState;
 | 
			
		||||
  setAppState: React.Component<any, AppState>["setState"];
 | 
			
		||||
  showThemeBtn: boolean;
 | 
			
		||||
}) => (
 | 
			
		||||
  <div style={{ display: "flex" }}>
 | 
			
		||||
    {actionManager.renderAction("changeViewBackgroundColor")}
 | 
			
		||||
    {showThemeBtn && actionManager.renderAction("toggleTheme")}
 | 
			
		||||
    {actionManager.renderAction("toggleTheme")}
 | 
			
		||||
  </div>
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,10 +2,12 @@ import React, { useEffect, useState } from "react";
 | 
			
		|||
 | 
			
		||||
import { LoadingMessage } from "./LoadingMessage";
 | 
			
		||||
import { defaultLang, Language, languages, setLanguage } from "../i18n";
 | 
			
		||||
import { Theme } from "../element/types";
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
  langCode: Language["code"];
 | 
			
		||||
  children: React.ReactElement;
 | 
			
		||||
  theme?: Theme;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const InitializeApp = (props: Props) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -21,5 +23,5 @@ export const InitializeApp = (props: Props) => {
 | 
			
		|||
    updateLang();
 | 
			
		||||
  }, [props.langCode]);
 | 
			
		||||
 | 
			
		||||
  return loading ? <LoadingMessage /> : props.children;
 | 
			
		||||
  return loading ? <LoadingMessage theme={props.theme} /> : props.children;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,6 @@ interface LayerUIProps {
 | 
			
		|||
  onPenModeToggle: () => void;
 | 
			
		||||
  onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void;
 | 
			
		||||
  showExitZenModeBtn: boolean;
 | 
			
		||||
  showThemeBtn: boolean;
 | 
			
		||||
  langCode: Language["code"];
 | 
			
		||||
  isCollaborating: boolean;
 | 
			
		||||
  renderTopRightUI?: ExcalidrawProps["renderTopRightUI"];
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +77,6 @@ const LayerUI = ({
 | 
			
		|||
  onPenModeToggle,
 | 
			
		||||
  onInsertElements,
 | 
			
		||||
  showExitZenModeBtn,
 | 
			
		||||
  showThemeBtn,
 | 
			
		||||
  isCollaborating,
 | 
			
		||||
  renderTopRightUI,
 | 
			
		||||
  renderCustomFooter,
 | 
			
		||||
| 
						 | 
				
			
			@ -209,12 +207,7 @@ const LayerUI = ({
 | 
			
		|||
              />
 | 
			
		||||
            )}
 | 
			
		||||
          </Stack.Row>
 | 
			
		||||
          <BackgroundPickerAndDarkModeToggle
 | 
			
		||||
            appState={appState}
 | 
			
		||||
            actionManager={actionManager}
 | 
			
		||||
            setAppState={setAppState}
 | 
			
		||||
            showThemeBtn={showThemeBtn}
 | 
			
		||||
          />
 | 
			
		||||
          <BackgroundPickerAndDarkModeToggle actionManager={actionManager} />
 | 
			
		||||
          {appState.fileHandle && (
 | 
			
		||||
            <>{actionManager.renderAction("saveToActiveFile")}</>
 | 
			
		||||
          )}
 | 
			
		||||
| 
						 | 
				
			
			@ -424,7 +417,6 @@ const LayerUI = ({
 | 
			
		|||
          canvas={canvas}
 | 
			
		||||
          isCollaborating={isCollaborating}
 | 
			
		||||
          renderCustomFooter={renderCustomFooter}
 | 
			
		||||
          showThemeBtn={showThemeBtn}
 | 
			
		||||
          onImageAction={onImageAction}
 | 
			
		||||
          renderTopRightUI={renderTopRightUI}
 | 
			
		||||
          renderCustomStats={renderCustomStats}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,14 @@
 | 
			
		|||
import { t } from "../i18n";
 | 
			
		||||
import { useState, useEffect } from "react";
 | 
			
		||||
import Spinner from "./Spinner";
 | 
			
		||||
import clsx from "clsx";
 | 
			
		||||
import { THEME } from "../constants";
 | 
			
		||||
import { Theme } from "../element/types";
 | 
			
		||||
 | 
			
		||||
export const LoadingMessage: React.FC<{ delay?: number }> = ({ delay }) => {
 | 
			
		||||
export const LoadingMessage: React.FC<{ delay?: number; theme?: Theme }> = ({
 | 
			
		||||
  delay,
 | 
			
		||||
  theme,
 | 
			
		||||
}) => {
 | 
			
		||||
  const [isWaiting, setIsWaiting] = useState(!!delay);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +26,11 @@ export const LoadingMessage: React.FC<{ delay?: number }> = ({ delay }) => {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="LoadingMessage">
 | 
			
		||||
    <div
 | 
			
		||||
      className={clsx("LoadingMessage", {
 | 
			
		||||
        "LoadingMessage--dark": theme === THEME.DARK,
 | 
			
		||||
      })}
 | 
			
		||||
    >
 | 
			
		||||
      <div>
 | 
			
		||||
        <Spinner />
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,6 @@ type MobileMenuProps = {
 | 
			
		|||
    isMobile: boolean,
 | 
			
		||||
    appState: AppState,
 | 
			
		||||
  ) => JSX.Element | null;
 | 
			
		||||
  showThemeBtn: boolean;
 | 
			
		||||
  onImageAction: (data: { insertOnCanvasDirectly: boolean }) => void;
 | 
			
		||||
  renderTopRightUI?: (
 | 
			
		||||
    isMobile: boolean,
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +60,6 @@ export const MobileMenu = ({
 | 
			
		|||
  canvas,
 | 
			
		||||
  isCollaborating,
 | 
			
		||||
  renderCustomFooter,
 | 
			
		||||
  showThemeBtn,
 | 
			
		||||
  onImageAction,
 | 
			
		||||
  renderTopRightUI,
 | 
			
		||||
  renderCustomStats,
 | 
			
		||||
| 
						 | 
				
			
			@ -171,14 +169,7 @@ export const MobileMenu = ({
 | 
			
		|||
            onClick={onCollabButtonClick}
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
        {
 | 
			
		||||
          <BackgroundPickerAndDarkModeToggle
 | 
			
		||||
            actionManager={actionManager}
 | 
			
		||||
            appState={appState}
 | 
			
		||||
            setAppState={setAppState}
 | 
			
		||||
            showThemeBtn={showThemeBtn}
 | 
			
		||||
          />
 | 
			
		||||
        }
 | 
			
		||||
        {<BackgroundPickerAndDarkModeToggle actionManager={actionManager} />}
 | 
			
		||||
      </>
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,7 +149,7 @@ export const DEFAULT_UI_OPTIONS: AppProps["UIOptions"] = {
 | 
			
		|||
    export: { saveFileToDisk: true },
 | 
			
		||||
    loadScene: true,
 | 
			
		||||
    saveToActiveFile: true,
 | 
			
		||||
    theme: true,
 | 
			
		||||
    toggleTheme: null,
 | 
			
		||||
    saveAsImage: true,
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
@import "open-color/open-color.scss";
 | 
			
		||||
 | 
			
		||||
.visually-hidden {
 | 
			
		||||
  position: absolute !important;
 | 
			
		||||
  height: 1px;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,3 +32,8 @@
 | 
			
		|||
    font-size: 0.8em;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.LoadingMessage--dark {
 | 
			
		||||
  background-color: $oc-black;
 | 
			
		||||
  color: $oc-white;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ export const STORAGE_KEYS = {
 | 
			
		|||
  LOCAL_STORAGE_APP_STATE: "excalidraw-state",
 | 
			
		||||
  LOCAL_STORAGE_COLLAB: "excalidraw-collab",
 | 
			
		||||
  LOCAL_STORAGE_LIBRARY: "excalidraw-library",
 | 
			
		||||
  LOCAL_STORAGE_THEME: "excalidraw-theme",
 | 
			
		||||
  VERSION_DATA_STATE: "version-dataState",
 | 
			
		||||
  VERSION_FILES: "version-files",
 | 
			
		||||
} as const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import {
 | 
			
		|||
  APP_NAME,
 | 
			
		||||
  COOKIES,
 | 
			
		||||
  EVENT,
 | 
			
		||||
  THEME,
 | 
			
		||||
  TITLE_TIMEOUT,
 | 
			
		||||
  VERSION_TIMEOUT,
 | 
			
		||||
} from "../constants";
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +18,7 @@ import {
 | 
			
		|||
  ExcalidrawElement,
 | 
			
		||||
  FileId,
 | 
			
		||||
  NonDeletedExcalidrawElement,
 | 
			
		||||
  Theme,
 | 
			
		||||
} from "../element/types";
 | 
			
		||||
import { useCallbackRefState } from "../hooks/useCallbackRefState";
 | 
			
		||||
import { t } from "../i18n";
 | 
			
		||||
| 
						 | 
				
			
			@ -512,6 +514,18 @@ const ExcalidrawWrapper = () => {
 | 
			
		|||
    languageDetector.cacheUserLanguage(langCode);
 | 
			
		||||
  }, [langCode]);
 | 
			
		||||
 | 
			
		||||
  const [theme, setTheme] = useState<Theme>(
 | 
			
		||||
    () =>
 | 
			
		||||
      localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_THEME) ||
 | 
			
		||||
      // FIXME migration from old LS scheme. Can be removed later. #5660
 | 
			
		||||
      importFromLocalStorage().appState?.theme ||
 | 
			
		||||
      THEME.LIGHT,
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    localStorage.setItem(STORAGE_KEYS.LOCAL_STORAGE_THEME, theme);
 | 
			
		||||
  }, [theme]);
 | 
			
		||||
 | 
			
		||||
  const onChange = (
 | 
			
		||||
    elements: readonly ExcalidrawElement[],
 | 
			
		||||
    appState: AppState,
 | 
			
		||||
| 
						 | 
				
			
			@ -521,6 +535,8 @@ const ExcalidrawWrapper = () => {
 | 
			
		|||
      collabAPI.syncElements(elements);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTheme(appState.theme);
 | 
			
		||||
 | 
			
		||||
    // this check is redundant, but since this is a hot path, it's best
 | 
			
		||||
    // not to evaludate the nested expression every time
 | 
			
		||||
    if (!LocalData.isSavePaused()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -710,6 +726,7 @@ const ExcalidrawWrapper = () => {
 | 
			
		|||
        onPointerUpdate={collabAPI?.onPointerUpdate}
 | 
			
		||||
        UIOptions={{
 | 
			
		||||
          canvasActions: {
 | 
			
		||||
            toggleTheme: true,
 | 
			
		||||
            export: {
 | 
			
		||||
              onExportToBackend,
 | 
			
		||||
              renderCustomUI: (elements, appState, files) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -739,6 +756,7 @@ const ExcalidrawWrapper = () => {
 | 
			
		|||
        handleKeyboardGlobally={true}
 | 
			
		||||
        onLibraryChange={onLibraryChange}
 | 
			
		||||
        autoFocus={true}
 | 
			
		||||
        theme={theme}
 | 
			
		||||
      />
 | 
			
		||||
      {excalidrawAPI && <Collab excalidrawAPI={excalidrawAPI} />}
 | 
			
		||||
      {errorMessage && (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,11 +17,13 @@ Please add the latest change on the top under the correct section.
 | 
			
		|||
 | 
			
		||||
#### Features
 | 
			
		||||
 | 
			
		||||
- Support [theme](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#theme) to be semi-controlled [#5660](https://github.com/excalidraw/excalidraw/pull/5660).
 | 
			
		||||
- Added support for storing [`customData`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#storing-custom-data-to-excalidraw-elements) on Excalidraw elements [#5592].
 | 
			
		||||
- Added `exportPadding?: number;` to [exportToCanvas](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exporttocanvas) and [exportToBlob](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#exporttoblob). The default value of the padding is 10.
 | 
			
		||||
 | 
			
		||||
#### Breaking Changes
 | 
			
		||||
 | 
			
		||||
- `props.UIOptions.canvasActions.theme` is now renamed to `props.UIOptions.canvasActions.toggleTheme` [#5660](https://github.com/excalidraw/excalidraw/pull/5660).
 | 
			
		||||
- `setToastMessage` API is now renamed to `setToast` API and the function signature is also updated [#5427](https://github.com/excalidraw/excalidraw/pull/5427). You can also pass `duration` and `closable` attributes along with `message`.
 | 
			
		||||
 | 
			
		||||
## 0.12.0 (2022-07-07)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -637,7 +637,9 @@ If supplied, this URL will be used when user tries to install a library from [li
 | 
			
		|||
 | 
			
		||||
#### `theme`
 | 
			
		||||
 | 
			
		||||
This prop controls Excalidraw's theme. When supplied, the value takes precedence over `intialData.appState.theme`, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app. You can use [`THEME`](#THEME-1) to specify the theme.
 | 
			
		||||
This prop controls Excalidraw's theme. When supplied, the value takes precedence over `intialData.appState.theme`, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app unless `UIOptions.canvasActions.toggleTheme` is set to `true`, in which case the `theme` prop will control Excalidraw's default theme with ability to allow theme switching (you must take care of updating the `theme` prop when you detect a change to `appState.theme` from the [onChange](#onChange) callback).
 | 
			
		||||
 | 
			
		||||
You can use [`THEME`](#THEME-1) to specify the theme.
 | 
			
		||||
 | 
			
		||||
#### `name`
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -660,7 +662,7 @@ This prop can be used to customise UI of Excalidraw. Currently we support custom
 | 
			
		|||
| `export` | false | [exportOpts](#exportOpts) | <pre>{ saveFileToDisk: true }</pre> | This prop allows to customize the UI inside the export dialog. By default it shows the "saveFileToDisk". If this prop is `false` the export button will not be rendered. For more details visit [`exportOpts`](#exportOpts). |
 | 
			
		||||
| `loadScene` | boolean | true | Implies whether to show `Load button` |
 | 
			
		||||
| `saveToActiveFile` | boolean | true | Implies whether to show `Save button` to save to current file |
 | 
			
		||||
| `theme` | boolean | true | Implies whether to show `Theme toggle` |
 | 
			
		||||
| `toggleTheme` | boolean | null | null | Implies whether to show `Theme toggle`. When defined as `boolean`, takes precedence over [`props.theme`](#theme) to show `Theme toggle` |
 | 
			
		||||
| `saveAsImage` | boolean | true | Implies whether to show `Save as image button` |
 | 
			
		||||
 | 
			
		||||
##### `dockedSidebarBreakpoint`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,13 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
 | 
			
		|||
      DEFAULT_UI_OPTIONS.canvasActions.export.saveFileToDisk;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (
 | 
			
		||||
    UIOptions.canvasActions.toggleTheme === null &&
 | 
			
		||||
    typeof theme === "undefined"
 | 
			
		||||
  ) {
 | 
			
		||||
    UIOptions.canvasActions.toggleTheme = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    // Block pinch-zooming on iOS outside of the content area
 | 
			
		||||
    const handleTouchMove = (event: TouchEvent) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +82,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
 | 
			
		|||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <InitializeApp langCode={langCode}>
 | 
			
		||||
    <InitializeApp langCode={langCode} theme={theme}>
 | 
			
		||||
      <Provider unstable_createStore={() => jotaiStore} scope={jotaiScope}>
 | 
			
		||||
        <App
 | 
			
		||||
          onChange={onChange}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,21 +88,42 @@ describe("<Excalidraw/>", () => {
 | 
			
		|||
  });
 | 
			
		||||
 | 
			
		||||
  describe("Test theme prop", () => {
 | 
			
		||||
    it('should show the dark mode toggle when the theme prop is "undefined"', async () => {
 | 
			
		||||
    it("should show the theme toggle by default", async () => {
 | 
			
		||||
      const { container } = await render(<Excalidraw />);
 | 
			
		||||
      expect(h.state.theme).toBe(THEME.LIGHT);
 | 
			
		||||
 | 
			
		||||
      const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
 | 
			
		||||
 | 
			
		||||
      expect(darkModeToggle).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should not show the dark mode toggle when the theme prop is not "undefined"', async () => {
 | 
			
		||||
    it("should not show theme toggle when the theme prop is defined", async () => {
 | 
			
		||||
      const { container } = await render(<Excalidraw theme="dark" />);
 | 
			
		||||
      expect(h.state.theme).toBe(THEME.DARK);
 | 
			
		||||
 | 
			
		||||
      expect(queryByTestId(container, "toggle-dark-mode")).toBe(null);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should show theme mode toggle when `UIOptions.canvasActions.toggleTheme` is true", async () => {
 | 
			
		||||
      const { container } = await render(
 | 
			
		||||
        <Excalidraw
 | 
			
		||||
          theme={THEME.DARK}
 | 
			
		||||
          UIOptions={{ canvasActions: { toggleTheme: true } }}
 | 
			
		||||
        />,
 | 
			
		||||
      );
 | 
			
		||||
      expect(h.state.theme).toBe(THEME.DARK);
 | 
			
		||||
      const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
 | 
			
		||||
      expect(darkModeToggle).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should not show theme toggle when `UIOptions.canvasActions.toggleTheme` is false", async () => {
 | 
			
		||||
      const { container } = await render(
 | 
			
		||||
        <Excalidraw
 | 
			
		||||
          UIOptions={{ canvasActions: { toggleTheme: false } }}
 | 
			
		||||
          theme={THEME.DARK}
 | 
			
		||||
        />,
 | 
			
		||||
      );
 | 
			
		||||
      expect(h.state.theme).toBe(THEME.DARK);
 | 
			
		||||
      const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
 | 
			
		||||
      expect(darkModeToggle).toBeFalsy();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe("Test name prop", () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +235,7 @@ describe("<Excalidraw/>", () => {
 | 
			
		|||
 | 
			
		||||
      it("should hide the theme toggle when theme is false", async () => {
 | 
			
		||||
        const { container } = await render(
 | 
			
		||||
          <Excalidraw UIOptions={{ canvasActions: { theme: false } }} />,
 | 
			
		||||
          <Excalidraw UIOptions={{ canvasActions: { toggleTheme: false } }} />,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        expect(queryByTestId(container, "toggle-dark-mode")).toBeNull();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -344,13 +344,17 @@ export type ExportOpts = {
 | 
			
		|||
  ) => JSX.Element;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// NOTE at the moment, if action name coressponds to canvasAction prop, its
 | 
			
		||||
// truthiness value will determine whether the action is rendered or not
 | 
			
		||||
// (see manager renderAction). We also override canvasAction values in
 | 
			
		||||
// excalidraw package index.tsx.
 | 
			
		||||
type CanvasActions = {
 | 
			
		||||
  changeViewBackgroundColor?: boolean;
 | 
			
		||||
  clearCanvas?: boolean;
 | 
			
		||||
  export?: false | ExportOpts;
 | 
			
		||||
  loadScene?: boolean;
 | 
			
		||||
  saveToActiveFile?: boolean;
 | 
			
		||||
  theme?: boolean;
 | 
			
		||||
  toggleTheme?: boolean | null;
 | 
			
		||||
  saveAsImage?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue