Merge remote-tracking branch 'origin/master' into aakansha-custom-elements

Update customType
This commit is contained in:
ad1992 2022-03-25 22:32:28 +05:30
commit 3d459076fb
25 changed files with 381 additions and 229 deletions

View file

@ -332,7 +332,6 @@ class App extends React.Component<AppProps, AppState> {
lastPointerUp: React.PointerEvent<HTMLElement> | PointerEvent | null = null;
contextMenuOpen: boolean = false;
lastScenePointer: { x: number; y: number } | null = null;
customElementName: string | null = null;
constructor(props: AppProps) {
super(props);
@ -414,18 +413,17 @@ class App extends React.Component<AppProps, AppState> {
this.actionManager.registerAction(createRedoAction(this.history));
}
setCustomType = (name: string) => {
this.setState({ elementType: "custom" });
this.customElementName = name;
setCustomType = (customType: string) => {
this.setState({ activeTool: { type: "custom", customType } });
};
renderCustomElement = (
coords: { x: number; y: number },
customType: string = "",
) => {
renderCustomElement = (coords: { x: number; y: number }) => {
if (this.state.activeTool.type !== "custom") {
return;
}
const config = getCustomElementConfig(
this.props.customElementsConfig,
customType,
this.state.activeTool.customType,
);
if (!config) {
return;
@ -438,7 +436,7 @@ class App extends React.Component<AppProps, AppState> {
const width = config.width || 40;
const height = config.height || 40;
const customElement = newCustomElement(customType, {
const customElement = newCustomElement(this.state.activeTool.customType, {
type: "custom",
x: gridX - width / 2,
y: gridY - height / 2,
@ -864,10 +862,10 @@ class App extends React.Component<AppProps, AppState> {
scene.appState = {
...scene.appState,
elementType:
scene.appState.elementType === "image"
? "selection"
: scene.appState.elementType,
activeTool:
scene.appState.activeTool.type === "image"
? { type: "selection" }
: scene.appState.activeTool,
isLoading: false,
};
if (initialData?.scrollToContent) {
@ -1121,15 +1119,15 @@ class App extends React.Component<AppProps, AppState> {
Object.keys(this.state.selectedElementIds).length &&
isEraserActive(this.state)
) {
this.setState({ elementType: "selection" });
this.setState({ activeTool: { type: "selection" } });
}
if (prevState.theme !== this.state.theme) {
setEraserCursor(this.canvas, this.state.theme);
}
// Hide hyperlink popup if shown when element type is not selection
if (
prevState.elementType === "selection" &&
this.state.elementType !== "selection" &&
prevState.activeTool.type === "selection" &&
this.state.activeTool.type !== "selection" &&
this.state.showHyperlinkPopup
) {
this.setState({ showHyperlinkPopup: false });
@ -1183,7 +1181,7 @@ class App extends React.Component<AppProps, AppState> {
}
const { multiElement } = prevState;
if (
prevState.elementType !== this.state.elementType &&
prevState.activeTool !== this.state.activeTool &&
multiElement != null &&
isBindingEnabled(this.state) &&
isBindingElement(multiElement)
@ -1487,7 +1485,7 @@ class App extends React.Component<AppProps, AppState> {
} else if (data.text) {
this.addTextFromPaste(data.text);
}
this.selectShapeTool("selection");
this.setActiveTool({ type: "selection" });
event?.preventDefault();
},
);
@ -1575,7 +1573,7 @@ class App extends React.Component<AppProps, AppState> {
}
},
);
this.selectShapeTool("selection");
this.setActiveTool({ type: "selection" });
};
private addTextFromPaste(text: any) {
@ -1628,9 +1626,9 @@ class App extends React.Component<AppProps, AppState> {
this.setState((prevState) => {
return {
elementLocked: !prevState.elementLocked,
elementType: prevState.elementLocked
? "selection"
: prevState.elementType,
activeTool: prevState.elementLocked
? { type: "selection" }
: prevState.activeTool,
};
});
};
@ -1905,7 +1903,7 @@ class App extends React.Component<AppProps, AppState> {
) {
const shape = findShapeByKey(event.key);
if (shape) {
this.selectShapeTool(shape);
this.setActiveTool({ type: shape });
} else if (event.key === KEYS.Q) {
this.toggleLock();
}
@ -1922,7 +1920,7 @@ class App extends React.Component<AppProps, AppState> {
this.state,
);
if (
this.state.elementType === "selection" &&
this.state.activeTool.type === "selection" &&
!selectedElements.length
) {
return;
@ -1930,7 +1928,7 @@ class App extends React.Component<AppProps, AppState> {
if (
event.key === KEYS.G &&
(hasBackground(this.state.elementType) ||
(hasBackground(this.state.activeTool.type) ||
selectedElements.some((element) => hasBackground(element.type)))
) {
this.setState({ openPopup: "backgroundColorPicker" });
@ -1946,7 +1944,7 @@ class App extends React.Component<AppProps, AppState> {
if (event.key === KEYS.SPACE) {
if (this.state.viewModeEnabled) {
setCursor(this.canvas, CURSOR_TYPE.GRAB);
} else if (this.state.elementType === "selection") {
} else if (this.state.activeTool.type === "selection") {
resetCursor(this.canvas);
} else {
setCursorForShape(this.canvas, this.state);
@ -1973,28 +1971,28 @@ class App extends React.Component<AppProps, AppState> {
}
});
private selectShapeTool(elementType: AppState["elementType"]) {
private setActiveTool(tool: AppState["activeTool"]) {
if (!isHoldingSpace) {
setCursorForShape(this.canvas, this.state);
}
if (isToolIcon(document.activeElement)) {
this.focusContainer();
}
if (!isLinearElementType(elementType)) {
if (!isLinearElementType(tool.type)) {
this.setState({ suggestedBindings: [] });
}
if (elementType === "image") {
if (tool.type === "image") {
this.onImageAction();
}
if (elementType !== "selection") {
if (tool.type !== "selection") {
this.setState({
elementType,
activeTool: tool,
selectedElementIds: {},
selectedGroupIds: {},
editingGroupId: null,
});
} else {
this.setState({ elementType });
this.setState({ activeTool: tool });
}
}
@ -2368,7 +2366,7 @@ class App extends React.Component<AppProps, AppState> {
return;
}
// we should only be able to double click when mode is selection
if (this.state.elementType !== "selection") {
if (this.state.activeTool.type !== "selection") {
return;
}
@ -2558,7 +2556,7 @@ class App extends React.Component<AppProps, AppState> {
const distance = getDistance(Array.from(gesture.pointers.values()));
const scaleFactor =
this.state.elementType === "freedraw" && this.state.penMode
this.state.activeTool.type === "freedraw" && this.state.penMode
? 1
: distance / gesture.initialDistance;
@ -2633,7 +2631,7 @@ class App extends React.Component<AppProps, AppState> {
}
}
if (isBindingElementType(this.state.elementType)) {
if (isBindingElementType(this.state.activeTool.type)) {
// Hovering with a selected tool or creating new linear element via click
// and point
const { draggingElement } = this.state;
@ -2709,9 +2707,9 @@ class App extends React.Component<AppProps, AppState> {
const hasDeselectedButton = Boolean(event.buttons);
if (
hasDeselectedButton ||
(this.state.elementType !== "selection" &&
this.state.elementType !== "text" &&
this.state.elementType !== "eraser")
(this.state.activeTool.type !== "selection" &&
this.state.activeTool.type !== "text" &&
this.state.activeTool.type !== "eraser")
) {
return;
}
@ -2788,7 +2786,7 @@ class App extends React.Component<AppProps, AppState> {
!this.state.showHyperlinkPopup
) {
this.setState({ showHyperlinkPopup: "info" });
} else if (this.state.elementType === "text") {
} else if (this.state.activeTool.type === "text") {
setCursor(
this.canvas,
isTextElement(hitElement) ? CURSOR_TYPE.TEXT : CURSOR_TYPE.CROSSHAIR,
@ -3000,27 +2998,27 @@ class App extends React.Component<AppProps, AppState> {
const allowOnPointerDown =
!this.state.penMode ||
event.pointerType !== "touch" ||
this.state.elementType === "selection" ||
this.state.elementType === "text" ||
this.state.elementType === "image";
this.state.activeTool.type === "selection" ||
this.state.activeTool.type === "text" ||
this.state.activeTool.type === "image";
if (!allowOnPointerDown) {
return;
}
if (this.state.elementType === "text") {
if (this.state.activeTool.type === "text") {
this.handleTextOnPointerDown(event, pointerDownState);
return;
} else if (
this.state.elementType === "arrow" ||
this.state.elementType === "line"
this.state.activeTool.type === "arrow" ||
this.state.activeTool.type === "line"
) {
this.handleLinearElementOnPointerDown(
event,
this.state.elementType,
this.state.activeTool.type,
pointerDownState,
);
} else if (this.state.elementType === "image") {
} else if (this.state.activeTool.type === "image") {
// reset image preview on pointerdown
setCursor(this.canvas, CURSOR_TYPE.CROSSHAIR);
@ -3040,26 +3038,21 @@ class App extends React.Component<AppProps, AppState> {
x,
y,
});
} else if (this.state.elementType === "custom") {
if (this.customElementName) {
setCursor(this.canvas, CURSOR_TYPE.CROSSHAIR);
this.renderCustomElement(
{
x: pointerDownState.origin.x,
y: pointerDownState.origin.y,
},
this.customElementName,
);
}
} else if (this.state.elementType === "freedraw") {
} else if (this.state.activeTool.type === "custom") {
setCursor(this.canvas, CURSOR_TYPE.CROSSHAIR);
this.renderCustomElement({
x: pointerDownState.origin.x,
y: pointerDownState.origin.y,
});
} else if (this.state.activeTool.type === "freedraw") {
this.handleFreeDrawElementOnPointerDown(
event,
this.state.elementType,
this.state.activeTool.type,
pointerDownState,
);
} else if (this.state.elementType !== "eraser") {
} else if (this.state.activeTool.type !== "eraser") {
this.createGenericElementOnPointerDown(
this.state.elementType,
this.state.activeTool.type,
pointerDownState,
);
}
@ -3111,7 +3104,7 @@ class App extends React.Component<AppProps, AppState> {
}
if (
this.state.elementType === "selection" &&
this.state.activeTool.type === "selection" &&
this.props.onElementClick &&
hitElement
) {
@ -3392,7 +3385,7 @@ class App extends React.Component<AppProps, AppState> {
}
private clearSelectionIfNotUsingSelection = (): void => {
if (this.state.elementType !== "selection") {
if (this.state.activeTool.type !== "selection") {
this.setState({
selectedElementIds: {},
selectedGroupIds: {},
@ -3408,7 +3401,7 @@ class App extends React.Component<AppProps, AppState> {
event: React.PointerEvent<HTMLCanvasElement>,
pointerDownState: PointerDownState,
): boolean => {
if (this.state.elementType === "selection") {
if (this.state.activeTool.type === "selection") {
const elements = this.scene.getElements();
const selectedElements = getSelectedElements(elements, this.state);
if (selectedElements.length === 1 && !this.state.editingLinearElement) {
@ -3662,7 +3655,7 @@ class App extends React.Component<AppProps, AppState> {
resetCursor(this.canvas);
if (!this.state.elementLocked) {
this.setState({
elementType: "selection",
activeTool: { type: "selection" },
});
}
};
@ -3971,8 +3964,8 @@ class App extends React.Component<AppProps, AppState> {
// triggering pointermove)
if (
!pointerDownState.drag.hasOccurred &&
(this.state.elementType === "arrow" ||
this.state.elementType === "line")
(this.state.activeTool.type === "arrow" ||
this.state.activeTool.type === "line")
) {
if (
distance2d(
@ -4167,7 +4160,7 @@ class App extends React.Component<AppProps, AppState> {
if (shouldRotateWithDiscreteAngle(event) && points.length === 2) {
({ width: dx, height: dy } = getPerfectElementSize(
this.state.elementType,
this.state.activeTool.type,
dx,
dy,
));
@ -4195,7 +4188,7 @@ class App extends React.Component<AppProps, AppState> {
this.maybeDragNewGenericElement(pointerDownState, event);
}
if (this.state.elementType === "selection") {
if (this.state.activeTool.type === "selection") {
pointerDownState.boxSelection.hasOccurred = true;
const elements = this.scene.getElements();
@ -4307,7 +4300,7 @@ class App extends React.Component<AppProps, AppState> {
draggingElement,
resizingElement,
multiElement,
elementType,
activeTool,
elementLocked,
isResizing,
isRotating,
@ -4476,7 +4469,7 @@ class App extends React.Component<AppProps, AppState> {
resetCursor(this.canvas);
this.setState((prevState) => ({
draggingElement: null,
elementType: "selection",
activeTool: { type: "selection" },
selectedElementIds: {
...prevState.selectedElementIds,
[this.state.draggingElement!.id]: true,
@ -4496,7 +4489,7 @@ class App extends React.Component<AppProps, AppState> {
}
if (
elementType !== "selection" &&
activeTool.type !== "selection" &&
draggingElement &&
isInvisiblySmallElement(draggingElement)
) {
@ -4665,7 +4658,7 @@ class App extends React.Component<AppProps, AppState> {
return;
}
if (!elementLocked && elementType !== "freedraw" && draggingElement) {
if (!elementLocked && activeTool.type !== "freedraw" && draggingElement) {
this.setState((prevState) => ({
selectedElementIds: {
...prevState.selectedElementIds,
@ -4675,7 +4668,7 @@ class App extends React.Component<AppProps, AppState> {
}
if (
elementType !== "selection" ||
activeTool.type !== "selection" ||
isSomeElementSelected(this.scene.getElements(), this.state)
) {
this.history.resumeRecording();
@ -4689,12 +4682,12 @@ class App extends React.Component<AppProps, AppState> {
);
}
if (!elementLocked && elementType !== "freedraw") {
if (!elementLocked && activeTool.type !== "freedraw") {
resetCursor(this.canvas);
this.setState({
draggingElement: null,
suggestedBindings: [],
elementType: "selection",
activeTool: { type: "selection" },
});
} else {
this.setState({
@ -5000,7 +4993,7 @@ class App extends React.Component<AppProps, AppState> {
{
pendingImageElement: null,
editingElement: null,
elementType: "selection",
activeTool: { type: "selection" },
},
() => {
this.actionManager.executeAction(actionFinalize);
@ -5370,7 +5363,7 @@ class App extends React.Component<AppProps, AppState> {
(event.nativeEvent.pointerType === "pen" &&
// always allow if user uses a pen secondary button
event.button !== POINTER_BUTTON.SECONDARY)) &&
this.state.elementType !== "selection"
this.state.activeTool.type !== "selection"
) {
return;
}
@ -5404,10 +5397,13 @@ class App extends React.Component<AppProps, AppState> {
if (!draggingElement) {
return;
}
if (draggingElement.type === "selection") {
if (
draggingElement.type === "selection" &&
this.state.activeTool.type !== "eraser"
) {
dragNewElement(
draggingElement,
this.state.elementType,
this.state.activeTool.type,
pointerDownState.origin.x,
pointerDownState.origin.y,
pointerCoords.x,
@ -5434,7 +5430,7 @@ class App extends React.Component<AppProps, AppState> {
dragNewElement(
draggingElement,
this.state.elementType,
this.state.activeTool.type,
pointerDownState.originInGrid.x,
pointerDownState.originInGrid.y,
gridX,