2020-03-07 10:20:38 -05:00
|
|
|
import React from "react";
|
|
|
|
import { ExcalidrawElement } from "../element/types";
|
|
|
|
import { ActionManager } from "../actions/manager";
|
2020-03-08 10:20:55 -07:00
|
|
|
import { hasBackground, hasStroke, hasText } from "../scene";
|
2020-03-07 10:20:38 -05:00
|
|
|
import { t } from "../i18n";
|
|
|
|
import { SHAPES } from "../shapes";
|
|
|
|
import { ToolButton } from "./ToolButton";
|
2020-03-09 15:06:35 +02:00
|
|
|
import { capitalizeString, getShortcutKey } from "../utils";
|
2020-03-07 10:20:38 -05:00
|
|
|
import { CURSOR_TYPE } from "../constants";
|
|
|
|
import Stack from "./Stack";
|
|
|
|
|
|
|
|
export function SelectedShapeActions({
|
|
|
|
targetElements,
|
|
|
|
renderAction,
|
|
|
|
elementType,
|
|
|
|
}: {
|
|
|
|
targetElements: readonly ExcalidrawElement[];
|
|
|
|
renderAction: ActionManager["renderAction"];
|
|
|
|
elementType: ExcalidrawElement["type"];
|
|
|
|
}) {
|
|
|
|
return (
|
|
|
|
<div className="panelColumn">
|
|
|
|
{renderAction("changeStrokeColor")}
|
|
|
|
{(hasBackground(elementType) ||
|
2020-03-23 13:05:07 +02:00
|
|
|
targetElements.some((element) => hasBackground(element.type))) && (
|
2020-03-07 10:20:38 -05:00
|
|
|
<>
|
|
|
|
{renderAction("changeBackgroundColor")}
|
|
|
|
|
|
|
|
{renderAction("changeFillStyle")}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{(hasStroke(elementType) ||
|
2020-03-23 13:05:07 +02:00
|
|
|
targetElements.some((element) => hasStroke(element.type))) && (
|
2020-03-07 10:20:38 -05:00
|
|
|
<>
|
|
|
|
{renderAction("changeStrokeWidth")}
|
|
|
|
|
|
|
|
{renderAction("changeSloppiness")}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{(hasText(elementType) ||
|
2020-03-23 13:05:07 +02:00
|
|
|
targetElements.some((element) => hasText(element.type))) && (
|
2020-03-07 10:20:38 -05:00
|
|
|
<>
|
|
|
|
{renderAction("changeFontSize")}
|
|
|
|
|
|
|
|
{renderAction("changeFontFamily")}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{renderAction("changeOpacity")}
|
|
|
|
|
|
|
|
<fieldset>
|
|
|
|
<legend>{t("labels.layers")}</legend>
|
|
|
|
<div className="buttonList">
|
|
|
|
{renderAction("sendToBack")}
|
|
|
|
{renderAction("sendBackward")}
|
|
|
|
{renderAction("bringToFront")}
|
|
|
|
{renderAction("bringForward")}
|
|
|
|
</div>
|
|
|
|
</fieldset>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function ShapesSwitcher({
|
|
|
|
elementType,
|
|
|
|
setAppState,
|
|
|
|
setElements,
|
|
|
|
elements,
|
|
|
|
}: {
|
|
|
|
elementType: ExcalidrawElement["type"];
|
|
|
|
setAppState: any;
|
|
|
|
setElements: any;
|
|
|
|
elements: readonly ExcalidrawElement[];
|
|
|
|
}) {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{SHAPES.map(({ value, icon }, index) => {
|
|
|
|
const label = t(`toolBar.${value}`);
|
2020-03-09 15:06:35 +02:00
|
|
|
const shortcut = getShortcutKey(
|
|
|
|
`${capitalizeString(value)[0]}, ${index + 1}`,
|
|
|
|
);
|
2020-03-07 10:20:38 -05:00
|
|
|
return (
|
|
|
|
<ToolButton
|
|
|
|
key={value}
|
|
|
|
type="radio"
|
|
|
|
icon={icon}
|
|
|
|
checked={elementType === value}
|
|
|
|
name="editor-current-shape"
|
2020-03-09 15:06:35 +02:00
|
|
|
title={`${capitalizeString(label)} ${shortcut}`}
|
2020-03-07 10:20:38 -05:00
|
|
|
keyBindingLabel={`${index + 1}`}
|
|
|
|
aria-label={capitalizeString(label)}
|
|
|
|
aria-keyshortcuts={`${label[0]} ${index + 1}`}
|
|
|
|
onChange={() => {
|
2020-03-08 10:20:55 -07:00
|
|
|
setAppState({
|
|
|
|
elementType: value,
|
|
|
|
multiElement: null,
|
|
|
|
selectedElementIds: {},
|
|
|
|
});
|
2020-03-07 10:20:38 -05:00
|
|
|
document.documentElement.style.cursor =
|
|
|
|
value === "text" ? CURSOR_TYPE.TEXT : CURSOR_TYPE.CROSSHAIR;
|
|
|
|
setAppState({});
|
|
|
|
}}
|
|
|
|
></ToolButton>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function ZoomActions({
|
|
|
|
renderAction,
|
|
|
|
zoom,
|
|
|
|
}: {
|
|
|
|
renderAction: ActionManager["renderAction"];
|
|
|
|
zoom: number;
|
|
|
|
}) {
|
|
|
|
return (
|
|
|
|
<Stack.Col gap={1}>
|
|
|
|
<Stack.Row gap={1} align="center">
|
|
|
|
{renderAction("zoomIn")}
|
|
|
|
{renderAction("zoomOut")}
|
|
|
|
{renderAction("resetZoom")}
|
|
|
|
<div style={{ marginLeft: 4 }}>{(zoom * 100).toFixed(0)}%</div>
|
|
|
|
</Stack.Row>
|
|
|
|
</Stack.Col>
|
|
|
|
);
|
|
|
|
}
|