import React from "react"; import { PanelTools } from "./panels/PanelTools"; import { Panel } from "./Panel"; import { PanelSelection } from "./panels/PanelSelection"; import { PanelColor } from "./panels/PanelColor"; import { hasBackground, someElementIsSelected, getSelectedAttribute, hasStroke, hasText, loadFromJSON, saveAsJSON, exportCanvas, deleteSelectedElements } from "../scene"; import { ButtonSelect } from "./ButtonSelect"; import { ExcalidrawElement } from "../element/types"; import { redrawTextBoundingBox, isTextElement } from "../element"; import { PanelCanvas } from "./panels/PanelCanvas"; import { PanelExport } from "./panels/PanelExport"; import { ExportType } from "../scene/types"; import { AppState } from "../types"; interface SidePanelProps { elements: readonly ExcalidrawElement[]; onToolChange: (elementType: string) => void; changeProperty: ( callback: (element: ExcalidrawElement) => ExcalidrawElement ) => void; moveAllLeft: () => void; moveOneLeft: () => void; moveAllRight: () => void; moveOneRight: () => void; onClearCanvas: React.MouseEventHandler; onUpdateAppState: (name: string, value: any) => void; appState: AppState; onUpdateElements: (elements: readonly ExcalidrawElement[]) => void; canvas: HTMLCanvasElement; } export const SidePanel: React.FC = ({ elements, onToolChange, changeProperty, moveAllLeft, moveOneLeft, moveAllRight, moveOneRight, onClearCanvas, onUpdateAppState, appState, onUpdateElements, canvas }) => { return (
{ onToolChange(value); }} /> { changeProperty(element => ({ ...element, strokeColor: color })); onUpdateAppState("currentItemStrokeColor", color); }} colorValue={getSelectedAttribute( elements, element => element.strokeColor )} /> {hasBackground(elements) && ( <> { changeProperty(element => ({ ...element, backgroundColor: color })); onUpdateAppState("currentItemBackgroundColor", color); }} colorValue={getSelectedAttribute( elements, element => element.backgroundColor )} />
Fill
element.fillStyle )} onChange={value => { changeProperty(element => ({ ...element, fillStyle: value })); }} /> )} {hasStroke(elements) && ( <>
Stroke Width
element.strokeWidth )} onChange={value => { changeProperty(element => ({ ...element, strokeWidth: value })); }} />
Sloppiness
element.roughness )} onChange={value => changeProperty(element => ({ ...element, roughness: value })) } /> )} {hasText(elements) && ( <>
Font size
isTextElement(element) && +element.font.split("px ")[0] )} onChange={value => changeProperty(element => { if (isTextElement(element)) { element.font = `${value}px ${element.font.split("px ")[1]}`; redrawTextBoundingBox(element); } return element; }) } />
Font familly
isTextElement(element) && element.font.split("px ")[1] )} onChange={value => changeProperty(element => { if (isTextElement(element)) { element.font = `${element.font.split("px ")[0]}px ${value}`; redrawTextBoundingBox(element); } return element; }) } /> )}
Opacity
{ changeProperty(element => ({ ...element, opacity: +event.target.value })); }} value={ getSelectedAttribute(elements, element => element.opacity) || 0 /* Put the opacity at 0 if there are two conflicting ones */ } />
{ onUpdateAppState("viewBackgroundColor", value); }} viewBackgroundColor={appState.viewBackgroundColor} /> { onUpdateAppState("name", name); }} onExportCanvas={(type: ExportType) => exportCanvas(type, elements, canvas, appState) } exportBackground={appState.exportBackground} onExportBackgroundChange={value => { onUpdateAppState("exportBackground", value); }} onSaveScene={() => saveAsJSON(elements, appState.name)} onLoadScene={() => loadFromJSON().then(({ elements }) => { onUpdateElements(elements); }) } />
); };