From 85365e5bcb866e76b7d26daeb9d5ff945d57a4b1 Mon Sep 17 00:00:00 2001 From: Gasim Gasimzada Date: Tue, 7 Jan 2020 15:06:22 +0400 Subject: [PATCH] Extract Sidebar panels into separate components (#230) * Extract Sidebar panels into separate components * Add Jest TS types --- package-lock.json | 8 ++ package.json | 1 + src/components/panels/PanelCanvas.tsx | 35 ++++++ src/components/panels/PanelColor.tsx | 24 ++++ src/components/panels/PanelExport.tsx | 52 ++++++++ src/components/panels/PanelSelection.tsx | 35 ++++++ src/components/panels/PanelTools.tsx | 38 ++++++ src/index.tsx | 154 ++++++++--------------- 8 files changed, 246 insertions(+), 101 deletions(-) create mode 100644 src/components/panels/PanelCanvas.tsx create mode 100644 src/components/panels/PanelColor.tsx create mode 100644 src/components/panels/PanelExport.tsx create mode 100644 src/components/panels/PanelSelection.tsx create mode 100644 src/components/panels/PanelTools.tsx diff --git a/package-lock.json b/package-lock.json index 79f18d86..6243dba9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1469,6 +1469,14 @@ "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "24.0.25", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.25.tgz", + "integrity": "sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g==", + "requires": { + "jest-diff": "^24.3.0" + } + }, "@types/json-schema": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", diff --git a/package.json b/package.json index 1be5d6df..cfd2ee8e 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "roughjs": "3.1.0" }, "devDependencies": { + "@types/jest": "^24.0.25", "@types/react": "16.9.17", "@types/react-color": "^3.0.1", "@types/react-dom": "16.9.4", diff --git a/src/components/panels/PanelCanvas.tsx b/src/components/panels/PanelCanvas.tsx new file mode 100644 index 00000000..f647e63c --- /dev/null +++ b/src/components/panels/PanelCanvas.tsx @@ -0,0 +1,35 @@ +import React from "react"; + +import { ColorPicker } from "../ColorPicker"; + +interface PanelCanvasProps { + viewBackgroundColor: string; + onViewBackgroundColorChange: (val: string) => void; + onClearCanvas: React.MouseEventHandler; +} + +export const PanelCanvas: React.FC = ({ + viewBackgroundColor, + onViewBackgroundColorChange, + onClearCanvas +}) => { + return ( + <> +

Canvas

+
+
Canvas Background Color
+ onViewBackgroundColorChange(color)} + /> + +
+ + ); +}; diff --git a/src/components/panels/PanelColor.tsx b/src/components/panels/PanelColor.tsx new file mode 100644 index 00000000..c61bf2a1 --- /dev/null +++ b/src/components/panels/PanelColor.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { ColorPicker } from "../ColorPicker"; + +interface PanelColorProps { + title: string; + colorValue: string | null; + onColorChange: (value: string) => void; +} + +export const PanelColor: React.FC = ({ + title, + onColorChange, + colorValue +}) => { + return ( + <> +
{title}
+ onColorChange(color)} + /> + + ); +}; diff --git a/src/components/panels/PanelExport.tsx b/src/components/panels/PanelExport.tsx new file mode 100644 index 00000000..9c36aba2 --- /dev/null +++ b/src/components/panels/PanelExport.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { EditableText } from "../EditableText"; + +interface PanelExportProps { + projectName: string; + onProjectNameChange: (name: string) => void; + onExportAsPNG: React.MouseEventHandler; + exportBackground: boolean; + onExportBackgroundChange: (val: boolean) => void; + onSaveScene: React.MouseEventHandler; + onLoadScene: React.MouseEventHandler; +} + +export const PanelExport: React.FC = ({ + projectName, + exportBackground, + onProjectNameChange, + onExportBackgroundChange, + onSaveScene, + onLoadScene, + onExportAsPNG +}) => { + return ( + <> +

Export

+
+
Name
+ {projectName && ( + onProjectNameChange(name)} + /> + )} +
Image
+ + +
Scene
+ + +
+ + ); +}; diff --git a/src/components/panels/PanelSelection.tsx b/src/components/panels/PanelSelection.tsx new file mode 100644 index 00000000..57eb3e56 --- /dev/null +++ b/src/components/panels/PanelSelection.tsx @@ -0,0 +1,35 @@ +import React from "react"; + +interface PanelSelectionProps { + onBringForward: React.MouseEventHandler; + onBringToFront: React.MouseEventHandler; + onSendBackward: React.MouseEventHandler; + onSendToBack: React.MouseEventHandler; +} + +export const PanelSelection: React.FC = ({ + onBringForward, + onBringToFront, + onSendBackward, + onSendToBack +}) => { + return ( + <> +

Selection

+
+ + + + +
+ + ); +}; diff --git a/src/components/panels/PanelTools.tsx b/src/components/panels/PanelTools.tsx new file mode 100644 index 00000000..b6345a08 --- /dev/null +++ b/src/components/panels/PanelTools.tsx @@ -0,0 +1,38 @@ +import React from "react"; + +import { SHAPES } from "../../shapes"; +import { capitalizeString } from "../../utils"; + +interface PanelToolsProps { + activeTool: string; + onToolChange: (value: string) => void; +} + +export const PanelTools: React.FC = ({ + activeTool, + onToolChange +}) => { + return ( + <> +

Shapes

+
+ {SHAPES.map(({ value, icon }) => ( + + ))} +
+ + ); +}; diff --git a/src/index.tsx b/src/index.tsx index 2af36f01..25bd55e2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -29,16 +29,19 @@ import { import { AppState } from "./types"; import { ExcalidrawElement, ExcalidrawTextElement } from "./element/types"; -import { getDateTime, capitalizeString, isInputLike } from "./utils"; +import { getDateTime, isInputLike } from "./utils"; -import { EditableText } from "./components/EditableText"; import { ButtonSelect } from "./components/ButtonSelect"; -import { ColorPicker } from "./components/ColorPicker"; -import { SHAPES, findShapeByKey, shapesShortcutKeys } from "./shapes"; +import { findShapeByKey, shapesShortcutKeys } from "./shapes"; import { createHistory } from "./history"; import "./styles.scss"; import ContextMenu from "./components/ContextMenu"; +import { PanelTools } from "./components/panels/PanelTools"; +import { PanelSelection } from "./components/panels/PanelSelection"; +import { PanelColor } from "./components/panels/PanelColor"; +import { PanelExport } from "./components/panels/PanelExport"; +import { PanelCanvas } from "./components/panels/PanelCanvas"; const { elements } = createScene(); const { history } = createHistory(); @@ -368,59 +371,45 @@ class App extends React.Component<{}, AppState> { }} >
-

Shapes

-
- {SHAPES.map(({ value, icon }) => ( - - ))} -
+ { + this.setState({ elementType: value }); + clearSelection(elements); + document.documentElement.style.cursor = + value === "text" ? "text" : "crosshair"; + this.forceUpdate(); + }} + /> {someElementIsSelected(elements) && (
-

Selection

-
- - - - -
-
Stroke Color
- + + element.strokeColor )} - onChange={color => this.changeStrokeColor(color)} /> {hasBackground(elements) && ( <> -
Background Color
- element.backgroundColor )} - onChange={color => this.changeBackgroundColor(color)} /> +
Fill
{
)} -

Canvas

-
-
Canvas Background Color
- this.setState({ viewBackgroundColor: color })} - /> - -
-

Export

-
-
Name
- {this.state.name && ( - this.updateProjectName(name)} - /> - )} -
Image
- - -
Scene
- - -
+ + this.setState({ viewBackgroundColor: val }) + } + viewBackgroundColor={this.state.viewBackgroundColor} + /> + exportAsPNG(elements, canvas, this.state)} + exportBackground={this.state.exportBackground} + onExportBackgroundChange={val => + this.setState({ exportBackground: val }) + } + onSaveScene={() => saveAsJSON(elements, this.state.name)} + onLoadScene={() => + loadFromJSON(elements).then(() => this.forceUpdate()) + } + />