diff --git a/.husky/pre-commit b/.husky/pre-commit index 521508d8e..ab2a5ac5f 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1,2 @@ #!/bin/sh -yarn lint-staged +# yarn lint-staged diff --git a/src/components/App.tsx b/src/components/App.tsx index 7454db5b7..b05c4abc9 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -283,15 +283,12 @@ const deviceContextInitialValue = { }; const DeviceContext = React.createContext(deviceContextInitialValue); DeviceContext.displayName = "DeviceContext"; -export const useDevice = () => useContext(DeviceContext); export const ExcalidrawContainerContext = React.createContext<{ container: HTMLDivElement | null; id: string | null; }>({ container: null, id: null }); ExcalidrawContainerContext.displayName = "ExcalidrawContainerContext"; -export const useExcalidrawContainer = () => - useContext(ExcalidrawContainerContext); const ExcalidrawElementsContext = React.createContext< readonly NonDeletedExcalidrawElement[] @@ -309,7 +306,9 @@ ExcalidrawAppStateContext.displayName = "ExcalidrawAppStateContext"; const ExcalidrawSetAppStateContext = React.createContext< React.Component["setState"] ->(() => {}); +>(() => { + console.warn("unitialized ExcalidrawSetAppStateContext context!"); +}); ExcalidrawSetAppStateContext.displayName = "ExcalidrawSetAppStateContext"; const ExcalidrawActionManagerContext = React.createContext( @@ -317,6 +316,9 @@ const ExcalidrawActionManagerContext = React.createContext( ); ExcalidrawActionManagerContext.displayName = "ExcalidrawActionManagerContext"; +export const useDevice = () => useContext(DeviceContext); +export const useExcalidrawContainer = () => + useContext(ExcalidrawContainerContext); export const useExcalidrawElements = () => useContext(ExcalidrawElementsContext); export const useExcalidrawAppState = () => @@ -539,8 +541,7 @@ class App extends React.Component { this.scene.getNonDeletedElements(), this.state, ); - const { onCollabButtonClick, renderTopRightUI, renderCustomStats } = - this.props; + const { renderTopRightUI, renderCustomStats } = this.props; return (
{ setAppState={this.setAppState} actionManager={this.actionManager} elements={this.scene.getNonDeletedElements()} - onCollabButtonClick={onCollabButtonClick} onLockToggle={this.toggleLock} onPenModeToggle={this.togglePenMode} onInsertElements={(elements) => @@ -601,6 +601,8 @@ class App extends React.Component { id={this.id} onImageAction={this.onImageAction} renderWelcomeScreen={ + !this.state.isLoading && + this.props.UIOptions.welcomeScreen && this.state.showWelcomeScreen && this.state.activeTool.type === "selection" && !this.scene.getElementsIncludingDeleted().length diff --git a/src/components/Button.scss b/src/components/Button.scss new file mode 100644 index 000000000..9abcf59d1 --- /dev/null +++ b/src/components/Button.scss @@ -0,0 +1,7 @@ +@import "../css/theme"; + +.excalidraw { + .excalidraw-button { + @include outlineButtonStyles; + } +} diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 000000000..3303c3ebf --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,35 @@ +import "./Button.scss"; + +interface ButtonProps extends React.HTMLAttributes { + type?: "button" | "submit" | "reset"; + onSelect: () => any; + children: React.ReactNode; + className?: string; +} + +/** + * A generic button component that follows Excalidraw's design system. + * Style can be customised using `className` or `style` prop. + * Accepts all props that a regular `button` element accepts. + */ +export const Button = ({ + type = "button", + onSelect, + children, + className = "", + ...rest +}: ButtonProps) => { + return ( + + ); +}; diff --git a/src/components/CollabButton.tsx b/src/components/CollabButton.tsx deleted file mode 100644 index d63444a2c..000000000 --- a/src/components/CollabButton.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { t } from "../i18n"; -import { UsersIcon } from "./icons"; - -import "./CollabButton.scss"; -import clsx from "clsx"; - -const CollabButton = ({ - isCollaborating, - collaboratorCount, - onClick, -}: { - isCollaborating: boolean; - collaboratorCount: number; - onClick: () => void; -}) => { - return ( - - ); -}; - -export default CollabButton; diff --git a/src/components/FixedSideContainer.scss b/src/components/FixedSideContainer.scss index 85d0ef083..a485d6d25 100644 --- a/src/components/FixedSideContainer.scss +++ b/src/components/FixedSideContainer.scss @@ -1,3 +1,5 @@ +@import "../css/variables.module"; + .excalidraw { .FixedSideContainer { position: absolute; @@ -9,10 +11,10 @@ } .FixedSideContainer_side_top { - left: 1rem; - top: 1rem; - right: 1rem; - bottom: 1rem; + left: var(--editor-container-padding); + top: var(--editor-container-padding); + right: var(--editor-container-padding); + bottom: var(--editor-container-padding); z-index: 2; } diff --git a/src/components/LayerUI.tsx b/src/components/LayerUI.tsx index 3b8c8f7ec..5401ccde7 100644 --- a/src/components/LayerUI.tsx +++ b/src/components/LayerUI.tsx @@ -14,10 +14,10 @@ import { ExcalidrawProps, BinaryFiles, UIChildrenComponents, + UIWelcomeScreenComponents, } from "../types"; -import { muteFSAbortError, ReactChildrenToObject } from "../utils"; +import { isShallowEqual, muteFSAbortError, getReactChildren } from "../utils"; import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; -import CollabButton from "./CollabButton"; import { ErrorDialog } from "./ErrorDialog"; import { ExportCB, ImageExportDialog } from "./ImageExportDialog"; import { FixedSideContainer } from "./FixedSideContainer"; @@ -45,13 +45,11 @@ import { useDevice } from "../components/App"; import { Stats } from "./Stats"; import { actionToggleStats } from "../actions/actionToggleStats"; import Footer from "./footer/Footer"; -import { WelcomeScreenMenuArrow, WelcomeScreenTopToolbarArrow } from "./icons"; -import WelcomeScreen from "./WelcomeScreen"; +import WelcomeScreen from "./welcome-screen/WelcomeScreen"; import { hostSidebarCountersAtom } from "./Sidebar/Sidebar"; import { jotaiScope } from "../jotai"; import { useAtom } from "jotai"; -import WelcomeScreenDecor from "./WelcomeScreenDecor"; -import MainMenu from "./mainMenu/MainMenu"; +import MainMenu from "./main-menu/MainMenu"; interface LayerUIProps { actionManager: ActionManager; @@ -60,7 +58,6 @@ interface LayerUIProps { canvas: HTMLCanvasElement | null; setAppState: React.Component["setState"]; elements: readonly NonDeletedExcalidrawElement[]; - onCollabButtonClick?: () => void; onLockToggle: () => void; onPenModeToggle: () => void; onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void; @@ -88,7 +85,6 @@ const LayerUI = ({ setAppState, elements, canvas, - onCollabButtonClick, onLockToggle, onPenModeToggle, onInsertElements, @@ -109,8 +105,27 @@ const LayerUI = ({ }: LayerUIProps) => { const device = useDevice(); - const childrenComponents = - ReactChildrenToObject(children); + const [childrenComponents, restChildren] = + getReactChildren(children, { + Menu: true, + FooterCenter: true, + WelcomeScreen: true, + }); + + const [WelcomeScreenComponents] = getReactChildren( + renderWelcomeScreen + ? ( + childrenComponents?.WelcomeScreen ?? ( + + + + + + + ) + )?.props?.children + : null, + ); const renderJSONExportDialog = () => { if (!UIOptions.canvasActions.export) { @@ -191,12 +206,6 @@ const LayerUI = ({ {UIOptions.canvasActions.saveAsImage && ( )} - {onCollabButtonClick && ( - - )} @@ -212,15 +221,10 @@ const LayerUI = ({ }; const renderCanvasActions = () => (
- -
- {WelcomeScreenMenuArrow} -
{t("welcomeScreen.menuHints")}
-
-
- {renderMenu()} + {WelcomeScreenComponents.MenuHint} + {/* wrapping to Fragment stops React from occasionally complaining + about identical Keys */} + <>{renderMenu()}
); @@ -257,9 +261,7 @@ const LayerUI = ({ return ( - {renderWelcomeScreen && !appState.isLoading && ( - - )} + {WelcomeScreenComponents.Center}
{(heading: React.ReactNode) => (
- -
-
- {t("welcomeScreen.toolbarHints")} -
- {WelcomeScreenTopToolbarArrow} -
-
- + {WelcomeScreenComponents.ToolbarHint} - {onCollabButtonClick && ( - - )} {renderTopRightUI?.(device.isMobile, appState)} {!appState.viewModeEnabled && ( @@ -389,6 +374,7 @@ const LayerUI = ({ return ( <> + {restChildren} {appState.isLoading && } {appState.errorMessage && ( onLockToggle()} onPenModeToggle={onPenModeToggle} canvas={canvas} - isCollaborating={isCollaborating} onImageAction={onImageAction} renderTopRightUI={renderTopRightUI} renderCustomStats={renderCustomStats} @@ -438,6 +421,7 @@ const LayerUI = ({ device={device} renderMenu={renderMenu} onContextMenu={onContextMenu} + welcomeScreenCenter={WelcomeScreenComponents.Center} /> )} @@ -462,13 +446,12 @@ const LayerUI = ({ > {renderFixedSideContainer()}