fix: copy bound text style when copying element having bound text (#5305)
* fix: copy bound text style when copying element having bound text * fix * fix tests
This commit is contained in:
parent
6196fba286
commit
84b47a2ed5
@ -48,7 +48,7 @@ describe("actionStyles", () => {
|
|||||||
Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
|
Keyboard.withModifierKeys({ ctrl: true, alt: true }, () => {
|
||||||
Keyboard.codeDown(CODES.C);
|
Keyboard.codeDown(CODES.C);
|
||||||
});
|
});
|
||||||
const secondRect = JSON.parse(copiedStyles);
|
const secondRect = JSON.parse(copiedStyles)[0];
|
||||||
expect(secondRect.id).toBe(h.elements[1].id);
|
expect(secondRect.id).toBe(h.elements[1].id);
|
||||||
|
|
||||||
mouse.reset();
|
mouse.reset();
|
||||||
|
@ -12,7 +12,9 @@ import {
|
|||||||
DEFAULT_FONT_FAMILY,
|
DEFAULT_FONT_FAMILY,
|
||||||
DEFAULT_TEXT_ALIGN,
|
DEFAULT_TEXT_ALIGN,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
import { getContainerElement } from "../element/textElement";
|
import { getBoundTextElement } from "../element/textElement";
|
||||||
|
import { hasBoundTextElement } from "../element/typeChecks";
|
||||||
|
import { getSelectedElements } from "../scene";
|
||||||
|
|
||||||
// `copiedStyles` is exported only for tests.
|
// `copiedStyles` is exported only for tests.
|
||||||
export let copiedStyles: string = "{}";
|
export let copiedStyles: string = "{}";
|
||||||
@ -21,9 +23,15 @@ export const actionCopyStyles = register({
|
|||||||
name: "copyStyles",
|
name: "copyStyles",
|
||||||
trackEvent: { category: "element" },
|
trackEvent: { category: "element" },
|
||||||
perform: (elements, appState) => {
|
perform: (elements, appState) => {
|
||||||
|
const elementsCopied = [];
|
||||||
const element = elements.find((el) => appState.selectedElementIds[el.id]);
|
const element = elements.find((el) => appState.selectedElementIds[el.id]);
|
||||||
|
elementsCopied.push(element);
|
||||||
|
if (element && hasBoundTextElement(element)) {
|
||||||
|
const boundTextElement = getBoundTextElement(element);
|
||||||
|
elementsCopied.push(boundTextElement);
|
||||||
|
}
|
||||||
if (element) {
|
if (element) {
|
||||||
copiedStyles = JSON.stringify(element);
|
copiedStyles = JSON.stringify(elementsCopied);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
appState: {
|
appState: {
|
||||||
@ -42,37 +50,59 @@ export const actionPasteStyles = register({
|
|||||||
name: "pasteStyles",
|
name: "pasteStyles",
|
||||||
trackEvent: { category: "element" },
|
trackEvent: { category: "element" },
|
||||||
perform: (elements, appState) => {
|
perform: (elements, appState) => {
|
||||||
const pastedElement = JSON.parse(copiedStyles);
|
const elementsCopied = JSON.parse(copiedStyles);
|
||||||
|
const pastedElement = elementsCopied[0];
|
||||||
|
const boundTextElement = elementsCopied[1];
|
||||||
if (!isExcalidrawElement(pastedElement)) {
|
if (!isExcalidrawElement(pastedElement)) {
|
||||||
return { elements, commitToHistory: false };
|
return { elements, commitToHistory: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectedElements = getSelectedElements(elements, appState, true);
|
||||||
|
const selectedElementIds = selectedElements.map((element) => element.id);
|
||||||
return {
|
return {
|
||||||
elements: elements.map((element) => {
|
elements: elements.map((element) => {
|
||||||
if (appState.selectedElementIds[element.id]) {
|
if (selectedElementIds.includes(element.id)) {
|
||||||
|
let elementStylesToCopyFrom = pastedElement;
|
||||||
|
if (isTextElement(element) && element.containerId) {
|
||||||
|
elementStylesToCopyFrom = boundTextElement;
|
||||||
|
}
|
||||||
|
if (!elementStylesToCopyFrom) {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
let newElement = newElementWith(element, {
|
let newElement = newElementWith(element, {
|
||||||
backgroundColor: pastedElement?.backgroundColor,
|
backgroundColor: elementStylesToCopyFrom?.backgroundColor,
|
||||||
strokeWidth: pastedElement?.strokeWidth,
|
strokeWidth: elementStylesToCopyFrom?.strokeWidth,
|
||||||
strokeColor: pastedElement?.strokeColor,
|
strokeColor: elementStylesToCopyFrom?.strokeColor,
|
||||||
strokeStyle: pastedElement?.strokeStyle,
|
strokeStyle: elementStylesToCopyFrom?.strokeStyle,
|
||||||
fillStyle: pastedElement?.fillStyle,
|
fillStyle: elementStylesToCopyFrom?.fillStyle,
|
||||||
opacity: pastedElement?.opacity,
|
opacity: elementStylesToCopyFrom?.opacity,
|
||||||
roughness: pastedElement?.roughness,
|
roughness: elementStylesToCopyFrom?.roughness,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isTextElement(newElement)) {
|
if (isTextElement(newElement)) {
|
||||||
newElement = newElementWith(newElement, {
|
newElement = newElementWith(newElement, {
|
||||||
fontSize: pastedElement?.fontSize || DEFAULT_FONT_SIZE,
|
fontSize: elementStylesToCopyFrom?.fontSize || DEFAULT_FONT_SIZE,
|
||||||
fontFamily: pastedElement?.fontFamily || DEFAULT_FONT_FAMILY,
|
fontFamily:
|
||||||
textAlign: pastedElement?.textAlign || DEFAULT_TEXT_ALIGN,
|
elementStylesToCopyFrom?.fontFamily || DEFAULT_FONT_FAMILY,
|
||||||
|
textAlign:
|
||||||
|
elementStylesToCopyFrom?.textAlign || DEFAULT_TEXT_ALIGN,
|
||||||
});
|
});
|
||||||
|
let container = null;
|
||||||
redrawTextBoundingBox(newElement, getContainerElement(newElement));
|
if (newElement.containerId) {
|
||||||
|
container =
|
||||||
|
selectedElements.find(
|
||||||
|
(element) =>
|
||||||
|
isTextElement(newElement) &&
|
||||||
|
element.id === newElement.containerId,
|
||||||
|
) || null;
|
||||||
|
}
|
||||||
|
redrawTextBoundingBox(newElement, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newElement.type === "arrow") {
|
if (newElement.type === "arrow") {
|
||||||
newElement = newElementWith(newElement, {
|
newElement = newElementWith(newElement, {
|
||||||
startArrowhead: pastedElement.startArrowhead,
|
startArrowhead: elementStylesToCopyFrom.startArrowhead,
|
||||||
endArrowhead: pastedElement.endArrowhead,
|
endArrowhead: elementStylesToCopyFrom.endArrowhead,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ describe("contextMenu element", () => {
|
|||||||
expect(copiedStyles).toBe("{}");
|
expect(copiedStyles).toBe("{}");
|
||||||
fireEvent.click(queryByText(contextMenu as HTMLElement, "Copy styles")!);
|
fireEvent.click(queryByText(contextMenu as HTMLElement, "Copy styles")!);
|
||||||
expect(copiedStyles).not.toBe("{}");
|
expect(copiedStyles).not.toBe("{}");
|
||||||
const element = JSON.parse(copiedStyles);
|
const element = JSON.parse(copiedStyles)[0];
|
||||||
expect(element).toEqual(API.getSelectedElement());
|
expect(element).toEqual(API.getSelectedElement());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ describe("contextMenu element", () => {
|
|||||||
});
|
});
|
||||||
let contextMenu = UI.queryContextMenu();
|
let contextMenu = UI.queryContextMenu();
|
||||||
fireEvent.click(queryByText(contextMenu as HTMLElement, "Copy styles")!);
|
fireEvent.click(queryByText(contextMenu as HTMLElement, "Copy styles")!);
|
||||||
const secondRect = JSON.parse(copiedStyles);
|
const secondRect = JSON.parse(copiedStyles)[0];
|
||||||
expect(secondRect.id).toBe(h.elements[1].id);
|
expect(secondRect.id).toBe(h.elements[1].id);
|
||||||
|
|
||||||
mouse.reset();
|
mouse.reset();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user