Sync panel props to editing element (#470)

* ensure panel props are sync to editing elem

* ensure we don't create empty-text elements (fixes #468)

* remove dead code

Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
This commit is contained in:
David Luzar 2020-01-21 00:16:22 +01:00 committed by Christopher Chedeau
parent ff7a340d2f
commit 2340dddaad
7 changed files with 159 additions and 100 deletions

View file

@ -1,10 +1,11 @@
import React from "react";
import { Action } from "./types";
import { ExcalidrawElement, ExcalidrawTextElement } from "../element/types";
import { getSelectedAttribute } from "../scene";
import { getCommonAttributeOfSelectedElements } from "../scene";
import { ButtonSelect } from "../components/ButtonSelect";
import { isTextElement, redrawTextBoundingBox } from "../element";
import { ColorPicker } from "../components/ColorPicker";
import { AppState } from "../../src/types";
const changeProperty = (
elements: readonly ExcalidrawElement[],
@ -18,6 +19,20 @@ const changeProperty = (
});
};
const getFormValue = function<T>(
editingElement: AppState["editingElement"],
elements: readonly ExcalidrawElement[],
getAttribute: (element: ExcalidrawElement) => T,
defaultValue?: T
): T | null {
return (
(editingElement && getAttribute(editingElement)) ||
getCommonAttributeOfSelectedElements(elements, getAttribute) ||
defaultValue ||
null
);
};
export const actionChangeStrokeColor: Action = {
name: "changeStrokeColor",
perform: (elements, appState, value) => {
@ -30,21 +45,21 @@ export const actionChangeStrokeColor: Action = {
appState: { ...appState, currentItemStrokeColor: value }
};
},
PanelComponent: ({ elements, appState, updateData, t }) => {
return (
<>
<h5>{t("labels.stroke")}</h5>
<ColorPicker
type="elementStroke"
color={
getSelectedAttribute(elements, element => element.strokeColor) ||
appState.currentItemStrokeColor
}
onChange={updateData}
/>
</>
);
}
PanelComponent: ({ elements, appState, updateData, t }) => (
<>
<h5>{t("labels.stroke")}</h5>
<ColorPicker
type="elementStroke"
color={getFormValue(
appState.editingElement,
elements,
element => element.strokeColor,
appState.currentItemStrokeColor
)}
onChange={updateData}
/>
</>
)
};
export const actionChangeBackgroundColor: Action = {
@ -64,10 +79,12 @@ export const actionChangeBackgroundColor: Action = {
<h5>{t("labels.background")}</h5>
<ColorPicker
type="elementBackground"
color={
getSelectedAttribute(elements, element => element.backgroundColor) ||
color={getFormValue(
appState.editingElement,
elements,
element => element.backgroundColor,
appState.currentItemBackgroundColor
}
)}
onChange={updateData}
/>
</>
@ -85,7 +102,7 @@ export const actionChangeFillStyle: Action = {
}))
};
},
PanelComponent: ({ elements, updateData, t }) => (
PanelComponent: ({ elements, appState, updateData, t }) => (
<>
<h5>{t("labels.fill")}</h5>
<ButtonSelect
@ -94,7 +111,11 @@ export const actionChangeFillStyle: Action = {
{ value: "hachure", text: "Hachure" },
{ value: "cross-hatch", text: "Cross-hatch" }
]}
value={getSelectedAttribute(elements, element => element.fillStyle)}
value={getFormValue(
appState.editingElement,
elements,
element => element.fillStyle
)}
onChange={value => {
updateData(value);
}}
@ -123,7 +144,11 @@ export const actionChangeStrokeWidth: Action = {
{ value: 2, text: "Bold" },
{ value: 4, text: "Extra Bold" }
]}
value={getSelectedAttribute(elements, element => element.strokeWidth)}
value={getFormValue(
appState.editingElement,
elements,
element => element.strokeWidth
)}
onChange={value => updateData(value)}
/>
</>
@ -150,7 +175,11 @@ export const actionChangeSloppiness: Action = {
{ value: 1, text: "Artist" },
{ value: 3, text: "Cartoonist" }
]}
value={getSelectedAttribute(elements, element => element.roughness)}
value={getFormValue(
appState.editingElement,
elements,
element => element.roughness
)}
onChange={value => updateData(value)}
/>
</>
@ -168,7 +197,7 @@ export const actionChangeOpacity: Action = {
}))
};
},
PanelComponent: ({ elements, updateData, t }) => (
PanelComponent: ({ elements, appState, updateData, t }) => (
<>
<h5>{t("labels.oppacity")}</h5>
<input
@ -177,8 +206,12 @@ export const actionChangeOpacity: Action = {
max="100"
onChange={e => updateData(+e.target.value)}
value={
getSelectedAttribute(elements, element => element.opacity) ||
0 /* Put the opacity at 0 if there are two conflicting ones */
getFormValue(
appState.editingElement,
elements,
element => element.opacity,
100 /* default opacity */
) || undefined
}
/>
</>
@ -204,7 +237,7 @@ export const actionChangeFontSize: Action = {
})
};
},
PanelComponent: ({ elements, updateData, t }) => (
PanelComponent: ({ elements, appState, updateData, t }) => (
<>
<h5>{t("labels.fontSize")}</h5>
<ButtonSelect
@ -214,7 +247,8 @@ export const actionChangeFontSize: Action = {
{ value: 28, text: "Large" },
{ value: 36, text: "Very Large" }
]}
value={getSelectedAttribute(
value={getFormValue(
appState.editingElement,
elements,
element => isTextElement(element) && +element.font.split("px ")[0]
)}
@ -243,7 +277,7 @@ export const actionChangeFontFamily: Action = {
})
};
},
PanelComponent: ({ elements, updateData, t }) => (
PanelComponent: ({ elements, appState, updateData, t }) => (
<>
<h5>{t("labels.fontFamily")}</h5>
<ButtonSelect
@ -252,7 +286,8 @@ export const actionChangeFontFamily: Action = {
{ value: "Helvetica", text: t("labels.normal") },
{ value: "Cascadia", text: t("labels.code") }
]}
value={getSelectedAttribute(
value={getFormValue(
appState.editingElement,
elements,
element => isTextElement(element) && element.font.split("px ")[1]
)}