Allow multiple selected text + Add font familly option

Refactor change and update ElementOption composant for enable type select
This commit is contained in:
David Bonan 2020-01-06 12:09:12 +01:00
parent 91896c3c11
commit cb423cff29
2 changed files with 91 additions and 46 deletions

View file

@ -2,6 +2,8 @@ import React from "react";
type PropsElementOption = { type PropsElementOption = {
label: string; label: string;
type?: string;
options?: Array<string|number>;
value: string; value: string;
onChange: Function; onChange: Function;
}; };
@ -9,17 +11,24 @@ function ElementOption(props: PropsElementOption) {
const handleChangeInput = (e: React.FormEvent<HTMLInputElement>) => { const handleChangeInput = (e: React.FormEvent<HTMLInputElement>) => {
props.onChange(e.currentTarget.value); props.onChange(e.currentTarget.value);
}; };
const handleChangeSelect = (e: React.FormEvent<HTMLSelectElement>) => {
props.onChange(e.currentTarget.value);
};
return ( return (
<> <>
<label style={{ display: "flex", flexDirection: "row" }}> <label style={{ display: 'flex', flexDirection: 'row' }}>
<span style={{ marginRight: 5, fontSize: 14, minWidth: 40 }}> <span style={{ marginRight: 5, fontSize: 14, minWidth: 40 }}>{props.label}:</span>
{props.label}: {props.type === 'select' ? (
</span> <select onChange={handleChangeSelect} value={props.value} style={{ flex: 1 }}>
<input {props.options?.map(option => (
onChange={handleChangeInput} <option key={option} value={option}>
value={props.value} {option}
style={{ flex: 1 }} </option>
/> ))}
</select>
) : (
<input type={props.type || 'text'} onChange={handleChangeInput} value={props.value} style={{ flex: 1 }} />
)}
</label> </label>
</> </>
); );

View file

@ -25,6 +25,8 @@ type ExcalidrawTextElement = ExcalidrawElement & {
const LOCAL_STORAGE_KEY = "excalidraw"; const LOCAL_STORAGE_KEY = "excalidraw";
const LOCAL_STORAGE_KEY_STATE = "excalidraw-state"; const LOCAL_STORAGE_KEY_STATE = "excalidraw-state";
const listFonts = ["Virgil", "Arial", "Times New Roman", "Georgia", "Arial", "Helvetica", "Tahoma", "Courier"]
const elements = Array.of<ExcalidrawElement>(); const elements = Array.of<ExcalidrawElement>();
const DEFAULT_PROJECT_NAME = `excalidraw-${getDateTime()}`; const DEFAULT_PROJECT_NAME = `excalidraw-${getDateTime()}`;
@ -1393,33 +1395,52 @@ class App extends React.Component<{}, AppState> {
this.setState({ currentItemBackgroundColor: color }); this.setState({ currentItemBackgroundColor: color });
}; };
private updateElement = (element: any, values: any) => { /**
* Method for change a text element
* Change property and recompute bound
*/
private changeTextElement = (values: any) => {
/** Use of Object.assign instead spread because we want to keep ref to element for update is value in initial object */ /** Use of Object.assign instead spread because we want to keep ref to element for update is value in initial object */
Object.assign(element, values); console.log(values)
this.changeProperty(element => isTextElement(element) && Object.assign(element, values));
if (values.text || values.font) { if (values.text || values.font) {
const fontSize = values.font elements.forEach(elm => {
? values.font.split("px")[0] if (elm.isSelected && isTextElement(elm)) {
: element.font.split("px")[0]; const fontSize = values.font ? values.font.split('px')[0] : elm.font.split('px')[0];
context.font = `${fontSize}px Virgil`; const fontFamilly = values.font ? values.font.split('px ')[1] : elm.font.split('px ')[1];
const textMeasure = context.measureText(values.text || element.text); context.font = `${fontSize}px ${fontFamilly}`;
const width = textMeasure.width; const textMeasure = context.measureText(values.text || elm.text);
const actualBoundingBoxAscent = const width = textMeasure.width;
textMeasure.actualBoundingBoxAscent || fontSize; const actualBoundingBoxAscent = textMeasure.actualBoundingBoxAscent || fontSize;
const actualBoundingBoxDescent = const actualBoundingBoxDescent = textMeasure.actualBoundingBoxDescent || 0;
textMeasure.actualBoundingBoxDescent || 0; elm.actualBoundingBoxAscent = actualBoundingBoxAscent;
element.actualBoundingBoxAscent = actualBoundingBoxAscent; const height = actualBoundingBoxAscent + actualBoundingBoxDescent;
const height = actualBoundingBoxAscent + actualBoundingBoxDescent; elm.width = width;
element.width = width; elm.height = height;
element.height = height; }
});
} }
this.forceUpdate(); this.forceUpdate();
}; };
private updateFontSizeElement = (element: any, size: string) => { private updateFontSizeElement = (element: ExcalidrawElement, size: string) => {
if (size.match(/[^0-9.]/g)) { if (size.match(/[^0-9.]/g)) {
return; return;
} }
this.updateElement(element, { font: `${size}px Virgil` }); if(isTextElement(element)) {
const fontFamilly = element.font.split('px ')[1];
this.changeTextElement({ font: `${size}px ${fontFamilly}` });
}
};
private updateFontFamillyElement = (element: ExcalidrawElement, fontFamilly: string) => {
console.log("element", element)
console.log("isTextElement", isTextElement(element))
if(isTextElement(element)) {
const size = element.font.split('px')[0];
console.log("size", size)
this.changeTextElement({ font: `${size}px ${fontFamilly}` });
}
}; };
public render() { public render() {
@ -1433,24 +1454,39 @@ class App extends React.Component<{}, AppState> {
/** If the selected item is a Text so : */ /** If the selected item is a Text so : */
if (isTextElement(selectedElement)) { if (isTextElement(selectedElement)) {
// Text value option // Text value option
elementSelectedOptions.push( if(elements.filter(element => element.isSelected).length === 1) {
<ElementOption elementSelectedOptions.push(
key="value" <ElementOption
label="Value" key="value"
value={selectedElement.text} label="Value"
onChange={(text: string) => value={selectedElement.text}
this.updateElement(selectedElement, { text }) onChange={(text: string) =>
} this.changeTextElement({ text })
/> }
); />
);
}
// Font size option // Font size option
elementSelectedOptions.push( elementSelectedOptions.push(
<ElementOption <ElementOption
key="size" key="size"
label="Size" label="Size"
value={selectedElement.font.split("px")[0]} type="select"
onChange={(size: string) => options={['6', '8', '10', '12', '14', '16', '18', '20', '22', '26', '30', '34', '38', '40', '50', '60', '70']}
this.updateFontSizeElement(selectedElement, size) value={selectedElement.font.split('px')[0]}
onChange={(size: string) => this.updateFontSizeElement(selectedElement, size)}
/>
);
// Font familly option
elementSelectedOptions.push(
<ElementOption
key="fontFamilly"
label="Font"
type="select"
options={listFonts}
value={selectedElement.font.split("px ")[1]}
onChange={(fontFamilly: string) =>
this.updateFontFamillyElement(selectedElement, fontFamilly)
} }
/> />
); );
@ -1527,12 +1563,12 @@ class App extends React.Component<{}, AppState> {
</div> </div>
{someElementIsSelected() && ( {someElementIsSelected() && (
<> <>
<h4>Element's options</h4> {elementSelectedOptions.length > 0 && (
<div className="panelColumn"> <>
{elementSelectedOptions.length > 0 <h4>Element's options</h4>
? elementSelectedOptions <div className="panelColumn">{elementSelectedOptions}</div>
: "No options available"} </>
</div> )}
<div className="panelColumn"> <div className="panelColumn">
<h4>Selection</h4> <h4>Selection</h4>
<div className="buttonList"> <div className="buttonList">