|
|
|
@ -2,6 +2,7 @@ import React from "react"; |
|
|
|
import ReactDOM from "react-dom"; |
|
|
|
import ReactDOM from "react-dom"; |
|
|
|
import rough from "roughjs/bin/wrappers/rough"; |
|
|
|
import rough from "roughjs/bin/wrappers/rough"; |
|
|
|
import { RoughCanvas } from "roughjs/bin/canvas"; |
|
|
|
import { RoughCanvas } from "roughjs/bin/canvas"; |
|
|
|
|
|
|
|
import { SketchPicker } from "react-color"; |
|
|
|
|
|
|
|
|
|
|
|
import { moveOneLeft, moveAllLeft, moveOneRight, moveAllRight } from "./zindex"; |
|
|
|
import { moveOneLeft, moveAllLeft, moveOneRight, moveAllRight } from "./zindex"; |
|
|
|
|
|
|
|
|
|
|
|
@ -816,9 +817,16 @@ function restore( |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum ColorPicker { |
|
|
|
|
|
|
|
CANVAS_BACKGROUND, |
|
|
|
|
|
|
|
SHAPE_STROKE, |
|
|
|
|
|
|
|
SHAPE_BACKGROUND |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type AppState = { |
|
|
|
type AppState = { |
|
|
|
draggingElement: ExcalidrawElement | null; |
|
|
|
draggingElement: ExcalidrawElement | null; |
|
|
|
resizingElement: ExcalidrawElement | null; |
|
|
|
resizingElement: ExcalidrawElement | null; |
|
|
|
|
|
|
|
currentColorPicker: ColorPicker | null; |
|
|
|
elementType: string; |
|
|
|
elementType: string; |
|
|
|
exportBackground: boolean; |
|
|
|
exportBackground: boolean; |
|
|
|
currentItemStrokeColor: string; |
|
|
|
currentItemStrokeColor: string; |
|
|
|
@ -889,7 +897,6 @@ const SHAPES = [ |
|
|
|
|
|
|
|
|
|
|
|
const shapesShortcutKeys = SHAPES.map(shape => shape.value[0]); |
|
|
|
const shapesShortcutKeys = SHAPES.map(shape => shape.value[0]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function capitalize(str: string) { |
|
|
|
function capitalize(str: string) { |
|
|
|
return str.charAt(0).toUpperCase() + str.slice(1); |
|
|
|
return str.charAt(0).toUpperCase() + str.slice(1); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -953,6 +960,7 @@ class App extends React.Component<{}, AppState> { |
|
|
|
draggingElement: null, |
|
|
|
draggingElement: null, |
|
|
|
resizingElement: null, |
|
|
|
resizingElement: null, |
|
|
|
elementType: "selection", |
|
|
|
elementType: "selection", |
|
|
|
|
|
|
|
currentColorPicker: null, |
|
|
|
exportBackground: true, |
|
|
|
exportBackground: true, |
|
|
|
currentItemStrokeColor: "#000000", |
|
|
|
currentItemStrokeColor: "#000000", |
|
|
|
currentItemBackgroundColor: "#ffffff", |
|
|
|
currentItemBackgroundColor: "#ffffff", |
|
|
|
@ -1134,7 +1142,11 @@ class App extends React.Component<{}, AppState> { |
|
|
|
<h4>Shapes</h4> |
|
|
|
<h4>Shapes</h4> |
|
|
|
<div className="panelTools"> |
|
|
|
<div className="panelTools"> |
|
|
|
{SHAPES.map(({ value, icon }) => ( |
|
|
|
{SHAPES.map(({ value, icon }) => ( |
|
|
|
<label key={value} className="tool" title={`${capitalize(value)} - ${capitalize(value)[0]}`}> |
|
|
|
<label |
|
|
|
|
|
|
|
key={value} |
|
|
|
|
|
|
|
className="tool" |
|
|
|
|
|
|
|
title={`${capitalize(value)} - ${capitalize(value)[0]}`} |
|
|
|
|
|
|
|
> |
|
|
|
<input |
|
|
|
<input |
|
|
|
type="radio" |
|
|
|
type="radio" |
|
|
|
checked={this.state.elementType === value} |
|
|
|
checked={this.state.elementType === value} |
|
|
|
@ -1152,36 +1164,123 @@ class App extends React.Component<{}, AppState> { |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<h4>Colors</h4> |
|
|
|
<h4>Colors</h4> |
|
|
|
<div className="panelColumn"> |
|
|
|
<div className="panelColumn"> |
|
|
|
<label> |
|
|
|
<h5>Canvas Background</h5> |
|
|
|
|
|
|
|
<div> |
|
|
|
|
|
|
|
<button |
|
|
|
|
|
|
|
className="swatch" |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
backgroundColor: this.state.viewBackgroundColor |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
onClick={() => |
|
|
|
|
|
|
|
this.setState(s => ({ |
|
|
|
|
|
|
|
currentColorPicker: |
|
|
|
|
|
|
|
s.currentColorPicker === ColorPicker.CANVAS_BACKGROUND |
|
|
|
|
|
|
|
? null |
|
|
|
|
|
|
|
: ColorPicker.CANVAS_BACKGROUND |
|
|
|
|
|
|
|
})) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
></button> |
|
|
|
|
|
|
|
{this.state.currentColorPicker === ColorPicker.CANVAS_BACKGROUND ? ( |
|
|
|
|
|
|
|
<div className="popover"> |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
className="cover" |
|
|
|
|
|
|
|
onClick={() => this.setState({ currentColorPicker: null })} |
|
|
|
|
|
|
|
></div> |
|
|
|
|
|
|
|
<SketchPicker |
|
|
|
|
|
|
|
color={this.state.viewBackgroundColor} |
|
|
|
|
|
|
|
onChange={color => { |
|
|
|
|
|
|
|
this.setState({ viewBackgroundColor: color.hex }); |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
) : null} |
|
|
|
<input |
|
|
|
<input |
|
|
|
type="color" |
|
|
|
type="text" |
|
|
|
|
|
|
|
className="swatch-input" |
|
|
|
value={this.state.viewBackgroundColor} |
|
|
|
value={this.state.viewBackgroundColor} |
|
|
|
onChange={e => { |
|
|
|
onChange={e => |
|
|
|
this.setState({ viewBackgroundColor: e.target.value }); |
|
|
|
this.setState({ viewBackgroundColor: e.target.value }) |
|
|
|
}} |
|
|
|
} |
|
|
|
/> |
|
|
|
/> |
|
|
|
Background |
|
|
|
</div> |
|
|
|
</label> |
|
|
|
<h5>Shape Stroke</h5> |
|
|
|
<label> |
|
|
|
<div> |
|
|
|
|
|
|
|
<button |
|
|
|
|
|
|
|
className="swatch" |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
backgroundColor: this.state.currentItemStrokeColor |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
onClick={() => |
|
|
|
|
|
|
|
this.setState(s => ({ |
|
|
|
|
|
|
|
currentColorPicker: |
|
|
|
|
|
|
|
s.currentColorPicker === ColorPicker.SHAPE_STROKE |
|
|
|
|
|
|
|
? null |
|
|
|
|
|
|
|
: ColorPicker.SHAPE_STROKE |
|
|
|
|
|
|
|
})) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
></button> |
|
|
|
|
|
|
|
{this.state.currentColorPicker === ColorPicker.SHAPE_STROKE ? ( |
|
|
|
|
|
|
|
<div className="popover"> |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
className="cover" |
|
|
|
|
|
|
|
onClick={() => this.setState({ currentColorPicker: null })} |
|
|
|
|
|
|
|
></div> |
|
|
|
|
|
|
|
<SketchPicker |
|
|
|
|
|
|
|
color={this.state.currentItemStrokeColor} |
|
|
|
|
|
|
|
onChange={color => { |
|
|
|
|
|
|
|
this.setState({ currentItemStrokeColor: color.hex }); |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
) : null} |
|
|
|
<input |
|
|
|
<input |
|
|
|
type="color" |
|
|
|
type="text" |
|
|
|
|
|
|
|
className="swatch-input" |
|
|
|
value={this.state.currentItemStrokeColor} |
|
|
|
value={this.state.currentItemStrokeColor} |
|
|
|
onChange={e => { |
|
|
|
onChange={e => { |
|
|
|
this.setState({ currentItemStrokeColor: e.target.value }); |
|
|
|
this.setState({ currentItemStrokeColor: e.target.value }); |
|
|
|
}} |
|
|
|
}} |
|
|
|
/> |
|
|
|
/> |
|
|
|
Shape Stroke |
|
|
|
</div> |
|
|
|
</label> |
|
|
|
<h5>Shape Background</h5> |
|
|
|
<label> |
|
|
|
<div> |
|
|
|
|
|
|
|
<button |
|
|
|
|
|
|
|
className="swatch" |
|
|
|
|
|
|
|
style={{ |
|
|
|
|
|
|
|
backgroundColor: this.state.currentItemBackgroundColor |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
onClick={() => |
|
|
|
|
|
|
|
this.setState(s => ({ |
|
|
|
|
|
|
|
currentColorPicker: |
|
|
|
|
|
|
|
s.currentColorPicker === ColorPicker.SHAPE_BACKGROUND |
|
|
|
|
|
|
|
? null |
|
|
|
|
|
|
|
: ColorPicker.SHAPE_BACKGROUND |
|
|
|
|
|
|
|
})) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
></button> |
|
|
|
|
|
|
|
{this.state.currentColorPicker === ColorPicker.SHAPE_BACKGROUND ? ( |
|
|
|
|
|
|
|
<div className="popover"> |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
className="cover" |
|
|
|
|
|
|
|
onClick={() => this.setState({ currentColorPicker: null })} |
|
|
|
|
|
|
|
></div> |
|
|
|
|
|
|
|
<SketchPicker |
|
|
|
|
|
|
|
color={this.state.currentItemBackgroundColor} |
|
|
|
|
|
|
|
onChange={color => { |
|
|
|
|
|
|
|
this.setState({ currentItemBackgroundColor: color.hex }); |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
) : null} |
|
|
|
<input |
|
|
|
<input |
|
|
|
type="color" |
|
|
|
type="text" |
|
|
|
value={this.state.currentItemBackgroundColor} |
|
|
|
className="swatch-input" |
|
|
|
|
|
|
|
value={this.state.currentItemStrokeColor} |
|
|
|
onChange={e => { |
|
|
|
onChange={e => { |
|
|
|
this.setState({ currentItemBackgroundColor: e.target.value }); |
|
|
|
this.setState({ currentItemStrokeColor: e.target.value }); |
|
|
|
}} |
|
|
|
}} |
|
|
|
/> |
|
|
|
/> |
|
|
|
Shape Background |
|
|
|
</div> |
|
|
|
</label> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<h4>Canvas</h4> |
|
|
|
<h4>Canvas</h4> |
|
|
|
<div className="panelColumn"> |
|
|
|
<div className="panelColumn"> |
|
|
|
|