feat: Support customising canvas actions 🎉 (#3364)

* feat: Support hiding save, save as, clear & export

* Remove canvasActions from state & minor changes

* Rename prop to UIOptions & pass default value

* Make requested changes

* better type checking so that optional check not needed at every point

* remove optional checks

* Add few tests

* Add describe block for canvasActions & use snapshot tests

* Add support for hiding canvas background picker

* Take snapshot of canvasActions instead of the whole app

* Add support for hiding dark mode toggle

* Update README.md

* Rename table heading

* Update changelog

* Make requested changes

* Update test name

* tweaks

Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
Arun 2021-04-04 15:57:14 +05:30 committed by GitHub
parent c54a099010
commit 233576628c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 637 additions and 15 deletions

View file

@ -44,6 +44,7 @@ import {
import {
APP_NAME,
CURSOR_TYPE,
DEFAULT_UI_OPTIONS,
DEFAULT_VERTICAL_ALIGN,
DRAGGING_THRESHOLD,
ELEMENT_SHIFT_TRANSLATE_AMOUNT,
@ -160,13 +161,7 @@ import Scene from "../scene/Scene";
import { SceneState, ScrollBars } from "../scene/types";
import { getNewZoom } from "../scene/zoom";
import { findShapeByKey } from "../shapes";
import {
AppState,
ExcalidrawProps,
Gesture,
GestureEvent,
SceneData,
} from "../types";
import { AppProps, AppState, Gesture, GestureEvent, SceneData } from "../types";
import {
debounce,
distance,
@ -286,16 +281,21 @@ export type ExcalidrawImperativeAPI = {
ready: true;
};
class App extends React.Component<ExcalidrawProps, AppState> {
class App extends React.Component<AppProps, AppState> {
canvas: HTMLCanvasElement | null = null;
rc: RoughCanvas | null = null;
unmounted: boolean = false;
actionManager: ActionManager;
private excalidrawContainerRef = React.createRef<HTMLDivElement>();
public static defaultProps: Partial<AppProps> = {
// needed for tests to pass since we directly render App in many tests
UIOptions: DEFAULT_UI_OPTIONS,
};
private scene: Scene;
private resizeObserver: ResizeObserver | undefined;
constructor(props: ExcalidrawProps) {
constructor(props: AppProps) {
super(props);
const defaultAppState = getDefaultAppState();
const {
@ -466,8 +466,12 @@ class App extends React.Component<ExcalidrawProps, AppState> {
showExitZenModeBtn={
typeof this.props?.zenModeEnabled === "undefined" && zenModeEnabled
}
showThemeBtn={typeof this.props?.theme === "undefined"}
showThemeBtn={
typeof this.props?.theme === "undefined" &&
this.props.UIOptions.canvasActions.theme
}
libraryReturnUrl={this.props.libraryReturnUrl}
UIOptions={this.props.UIOptions}
/>
<div className="excalidraw-textEditorContainer" />
{this.state.showStats && (
@ -878,7 +882,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
window.addEventListener(EVENT.DROP, this.disableEvent, false);
}
componentDidUpdate(prevProps: ExcalidrawProps, prevState: AppState) {
componentDidUpdate(prevProps: AppProps, prevState: AppState) {
if (prevProps.langCode !== this.props.langCode) {
this.updateLanguage();
}

View file

@ -17,7 +17,13 @@ import { Language, t } from "../i18n";
import { useIsMobile } from "../is-mobile";
import { calculateScrollCenter, getSelectedElements } from "../scene";
import { ExportType } from "../scene/types";
import { AppState, ExcalidrawProps, LibraryItem, LibraryItems } from "../types";
import {
AppProps,
AppState,
ExcalidrawProps,
LibraryItem,
LibraryItems,
} from "../types";
import { muteFSAbortError } from "../utils";
import { SelectedShapeActions, ShapesSwitcher, ZoomActions } from "./Actions";
import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle";
@ -65,6 +71,7 @@ interface LayerUIProps {
renderCustomFooter?: (isMobile: boolean) => JSX.Element;
viewModeEnabled: boolean;
libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
UIOptions: AppProps["UIOptions"];
}
const useOnClickOutside = (
@ -339,6 +346,7 @@ const LayerUI = ({
renderCustomFooter,
viewModeEnabled,
libraryReturnUrl,
UIOptions,
}: LayerUIProps) => {
const isMobile = useIsMobile();
@ -359,6 +367,10 @@ const LayerUI = ({
);
const renderExportDialog = () => {
if (!UIOptions.canvasActions.export) {
return null;
}
const createExporter = (type: ExportType): ExportCB => async (
exportedElements,
scale,