editing single element

This commit is contained in:
Ryan Di 2023-03-27 17:51:31 +08:00
parent 30743ec726
commit 3fc89b716a
2 changed files with 139 additions and 69 deletions

View File

@ -9,8 +9,33 @@
z-index: 10; z-index: 10;
pointer-events: all; pointer-events: all;
.section { .sectionContent {
padding: 12px; display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.elementType {
font-size: 12px;
font-weight: 700;
margin-bottom: 8px;
}
.statsItem {
margin-bottom: 4px;
display: flex;
align-items: center;
// margin-right: 8px;
.label {
margin-right: 4px;
width: 10px;
}
.input {
width: 55px;
}
} }
h3 { h3 {

View File

@ -1,7 +1,12 @@
import React from "react"; import React from "react";
import { getCommonBounds } from "../element/bounds"; import { getCommonBounds } from "../element/bounds";
import { NonDeletedExcalidrawElement } from "../element/types"; import { mutateElement } from "../element/mutateElement";
import {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "../element/types";
import { t } from "../i18n"; import { t } from "../i18n";
import { KEYS } from "../keys";
import { getTargetElements } from "../scene"; import { getTargetElements } from "../scene";
import { AppState, ExcalidrawProps } from "../types"; import { AppState, ExcalidrawProps } from "../types";
import { CloseIcon } from "./icons"; import { CloseIcon } from "./icons";
@ -19,9 +24,45 @@ export const Stats = (props: {
const selectedElements = getTargetElements(props.elements, props.appState); const selectedElements = getTargetElements(props.elements, props.appState);
const selectedBoundingBox = getCommonBounds(selectedElements); const selectedBoundingBox = getCommonBounds(selectedElements);
const stats =
selectedElements.length === 1
? [
{
label: "X",
value: Math.round(selectedBoundingBox[0]),
element: selectedElements[0],
property: "x",
},
{
label: "Y",
value: Math.round(selectedBoundingBox[1]),
element: selectedElements[0],
property: "y",
},
{
label: "W",
value: Math.round(selectedBoundingBox[2] - selectedBoundingBox[0]),
element: selectedElements[0],
property: "width",
},
{
label: "H",
value: Math.round(selectedBoundingBox[3] - selectedBoundingBox[1]),
element: selectedElements[0],
property: "height",
},
{
label: "A",
value: selectedElements[0].angle,
element: selectedElements[0],
property: "angle",
},
]
: [];
return ( return (
<div className="Stats"> <div className="Stats">
<Island> <Island padding={3}>
<div className="section"> <div className="section">
<div className="close" onClick={props.onClose}> <div className="close" onClick={props.onClose}>
{CloseIcon} {CloseIcon}
@ -54,75 +95,79 @@ export const Stats = (props: {
</div> </div>
{selectedElements.length > 0 && ( {selectedElements.length > 0 && (
<> <div className="section">
<div className="divider"></div> <h3>{t("stats.elementStats")}</h3>
<div className="section"> <div className="sectionContent">
<h3>{t("stats.elementStats")}</h3> {selectedElements.length === 1 && (
<div className="elementType">
{t(`element.${selectedElements[0].type}`)}
</div>
)}
<table> <div
<tbody> style={{
{selectedElements.length === 1 && ( display: "grid",
<tr> gridTemplateColumns: "repeat(2, 1fr)",
<th colSpan={2}> gap: "4px 8px",
{t(`element.${selectedElements[0].type}`)} }}
</th> >
</tr> {stats.map((statsItem) => (
)} <label
className="color-input-container"
key={statsItem.property}
>
<div
className="color-picker-hash"
style={{
width: "30px",
}}
>
{statsItem.label}
</div>
<input
id={statsItem.label}
defaultValue={statsItem.value}
className="color-picker-input"
style={{
width: "55px",
}}
autoComplete="off"
spellCheck="false"
onKeyDown={(event) => {
const value = Number(event.target.value);
{selectedElements.length > 1 && ( if (event.key === KEYS.ENTER) {
<> if (!isNaN(value)) {
<tr> mutateElement(statsItem.element, {
<th colSpan={2}>{t("stats.selected")}</th> [statsItem.property]: value,
</tr> });
<tr> }
<td>{t("stats.elements")}</td>
<td>{selectedElements.length}</td> event.target.value = statsItem.element[
</tr> statsItem.property as keyof ExcalidrawElement
</> ] as string;
)} }
{selectedElements.length > 0 && ( }}
<> onBlur={(event) => {
<tr> const value = Number(event.target.value);
<td>{"x"}</td>
<td>{Math.round(selectedBoundingBox[0])}</td> if (!isNaN(value)) {
</tr> mutateElement(statsItem.element, {
<tr> [statsItem.property]: value,
<td>{"y"}</td> });
<td>{Math.round(selectedBoundingBox[1])}</td> }
</tr>
<tr> event.target.value = statsItem.element[
<td>{t("stats.width")}</td> statsItem.property as keyof ExcalidrawElement
<td> ] as string;
{Math.round( }}
selectedBoundingBox[2] - selectedBoundingBox[0], ></input>
)} </label>
</td> ))}
</tr> </div>
<tr>
<td>{t("stats.height")}</td>
<td>
{Math.round(
selectedBoundingBox[3] - selectedBoundingBox[1],
)}
</td>
</tr>
</>
)}
{selectedElements.length === 1 && (
<tr>
<td>{t("stats.angle")}</td>
<td>
{`${Math.round(
(selectedElements[0].angle * 180) / Math.PI,
)}°`}
</td>
</tr>
)}
</tbody>
</table>
</div> </div>
</> </div>
)} )}
</Island> </Island>
</div> </div>