mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
support ids, clean up code and move the api related stuff to transform.ts
This commit is contained in:
parent
da8e97ad14
commit
985318e960
11 changed files with 337 additions and 250 deletions
|
@ -130,7 +130,6 @@ import {
|
||||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||||
import { mutateElement, newElementWith } from "../element/mutateElement";
|
import { mutateElement, newElementWith } from "../element/mutateElement";
|
||||||
import {
|
import {
|
||||||
convertToExcalidrawElements,
|
|
||||||
deepCopyElement,
|
deepCopyElement,
|
||||||
duplicateElements,
|
duplicateElements,
|
||||||
newFreeDrawElement,
|
newFreeDrawElement,
|
||||||
|
@ -305,6 +304,7 @@ import { jotaiStore } from "../jotai";
|
||||||
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
|
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
|
||||||
import { actionWrapTextInContainer } from "../actions/actionBoundText";
|
import { actionWrapTextInContainer } from "../actions/actionBoundText";
|
||||||
import BraveMeasureTextError from "./BraveMeasureTextError";
|
import BraveMeasureTextError from "./BraveMeasureTextError";
|
||||||
|
import { convertToExcalidrawElements } from "../data/transform";
|
||||||
|
|
||||||
const AppContext = React.createContext<AppClassProperties>(null!);
|
const AppContext = React.createContext<AppClassProperties>(null!);
|
||||||
const AppPropsContext = React.createContext<AppProps>(null!);
|
const AppPropsContext = React.createContext<AppProps>(null!);
|
||||||
|
@ -2044,6 +2044,8 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sceneData.elements) {
|
if (sceneData.elements) {
|
||||||
|
console.log("HEYYYYYYYY", sceneData.elements);
|
||||||
|
|
||||||
this.scene.replaceAllElements(
|
this.scene.replaceAllElements(
|
||||||
convertToExcalidrawElements(sceneData.elements),
|
convertToExcalidrawElements(sceneData.elements),
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { FileSystemHandle, nativeFileSystemSupported } from "./filesystem";
|
||||||
import { isValidExcalidrawData, isValidLibrary } from "./json";
|
import { isValidExcalidrawData, isValidLibrary } from "./json";
|
||||||
import { restore, restoreLibraryItems } from "./restore";
|
import { restore, restoreLibraryItems } from "./restore";
|
||||||
import { ImportedLibraryData } from "./types";
|
import { ImportedLibraryData } from "./types";
|
||||||
import { convertToExcalidrawElements } from "../element/newElement";
|
import { convertToExcalidrawElements } from "../data/transform";
|
||||||
|
|
||||||
const parseFileContents = async (blob: Blob | File) => {
|
const parseFileContents = async (blob: Blob | File) => {
|
||||||
let contents: string;
|
let contents: string;
|
||||||
|
|
|
@ -41,7 +41,7 @@ import {
|
||||||
getDefaultLineHeight,
|
getDefaultLineHeight,
|
||||||
measureBaseline,
|
measureBaseline,
|
||||||
} from "../element/textElement";
|
} from "../element/textElement";
|
||||||
import { convertToExcalidrawElements } from "../element/newElement";
|
import { convertToExcalidrawElements } from "../data/transform";
|
||||||
|
|
||||||
type RestoredAppState = Omit<
|
type RestoredAppState = Omit<
|
||||||
AppState,
|
AppState,
|
||||||
|
|
310
src/data/transform.ts
Normal file
310
src/data/transform.ts
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
import { TEXT_ALIGN, VERTICAL_ALIGN } from "../constants";
|
||||||
|
import {
|
||||||
|
newElement,
|
||||||
|
newLinearElement,
|
||||||
|
redrawTextBoundingBox,
|
||||||
|
} from "../element";
|
||||||
|
import { bindLinearElement } from "../element/binding";
|
||||||
|
import { mutateElement } from "../element/mutateElement";
|
||||||
|
import { ElementConstructorOpts, newTextElement } from "../element/newElement";
|
||||||
|
import { VALID_CONTAINER_TYPES } from "../element/textElement";
|
||||||
|
import {
|
||||||
|
ExcalidrawBindableElement,
|
||||||
|
ExcalidrawElement,
|
||||||
|
ExcalidrawGenericElement,
|
||||||
|
ExcalidrawLinearElement,
|
||||||
|
ExcalidrawTextElement,
|
||||||
|
FontFamilyValues,
|
||||||
|
TextAlign,
|
||||||
|
VerticalAlign,
|
||||||
|
} from "../element/types";
|
||||||
|
import { MarkOptional } from "../utility-types";
|
||||||
|
import { ImportedDataState } from "./types";
|
||||||
|
|
||||||
|
export const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
|
||||||
|
"rectangle",
|
||||||
|
"ellipse",
|
||||||
|
"diamond",
|
||||||
|
"text",
|
||||||
|
"arrow",
|
||||||
|
"line",
|
||||||
|
];
|
||||||
|
|
||||||
|
const bindTextToContainer = (
|
||||||
|
containerProps:
|
||||||
|
| {
|
||||||
|
type:
|
||||||
|
| Exclude<ExcalidrawGenericElement["type"], "selection">
|
||||||
|
| ExcalidrawLinearElement["type"];
|
||||||
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">,
|
||||||
|
textProps: { text: string } & MarkOptional<ElementConstructorOpts, "x" | "y">,
|
||||||
|
) => {
|
||||||
|
let container;
|
||||||
|
if (containerProps.type === "arrow") {
|
||||||
|
container = newLinearElement({
|
||||||
|
width: containerProps.width || 300,
|
||||||
|
height: containerProps.height || 24,
|
||||||
|
//@ts-ignore
|
||||||
|
type: containerProps.type,
|
||||||
|
//@ts-ignore,
|
||||||
|
endArrowhead: containerProps.type === "arrow" ? "arrow" : null,
|
||||||
|
//@ts-ignore
|
||||||
|
points: [
|
||||||
|
[0, 0],
|
||||||
|
[300, 0],
|
||||||
|
],
|
||||||
|
...containerProps,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
|
container = newElement({
|
||||||
|
...containerProps,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const textElement: ExcalidrawTextElement = newTextElement({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
textAlign: TEXT_ALIGN.CENTER,
|
||||||
|
verticalAlign: VERTICAL_ALIGN.MIDDLE,
|
||||||
|
...textProps,
|
||||||
|
containerId: container.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
mutateElement(container, {
|
||||||
|
boundElements: (container.boundElements || []).concat({
|
||||||
|
type: "text",
|
||||||
|
id: textElement.id,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
redrawTextBoundingBox(textElement, container);
|
||||||
|
|
||||||
|
return [container, textElement];
|
||||||
|
};
|
||||||
|
|
||||||
|
const bindLinearElementToElement = (
|
||||||
|
linearElement: {
|
||||||
|
type: ExcalidrawLinearElement["type"];
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
label?: {
|
||||||
|
text: string;
|
||||||
|
fontSize?: number;
|
||||||
|
fontFamily?: FontFamilyValues;
|
||||||
|
textAlign?: TextAlign;
|
||||||
|
verticalAlign?: VerticalAlign;
|
||||||
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
|
start?: {
|
||||||
|
type: Exclude<
|
||||||
|
ExcalidrawBindableElement["type"],
|
||||||
|
"image" | "selection" | "text"
|
||||||
|
>;
|
||||||
|
id?: ExcalidrawGenericElement["id"];
|
||||||
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
|
end?: {
|
||||||
|
type: ExcalidrawGenericElement["type"];
|
||||||
|
id?: ExcalidrawGenericElement["id"];
|
||||||
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
|
} & Partial<ExcalidrawLinearElement>,
|
||||||
|
elements: ImportedDataState["elements"],
|
||||||
|
): {
|
||||||
|
linearElement: ExcalidrawLinearElement;
|
||||||
|
startBoundElement?: ExcalidrawElement;
|
||||||
|
endBoundElement?: ExcalidrawElement;
|
||||||
|
} => {
|
||||||
|
const {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
type,
|
||||||
|
endArrowhead = linearElement.type === "arrow" ? "arrow" : null,
|
||||||
|
...rest
|
||||||
|
} = linearElement;
|
||||||
|
|
||||||
|
const excliadrawLinearElement = newLinearElement({
|
||||||
|
type,
|
||||||
|
width: 200,
|
||||||
|
height: 24,
|
||||||
|
points: [
|
||||||
|
[0, 0],
|
||||||
|
[200, 0],
|
||||||
|
],
|
||||||
|
endArrowhead,
|
||||||
|
...rest,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!elements || !elements.length) {
|
||||||
|
return { linearElement: excliadrawLinearElement };
|
||||||
|
}
|
||||||
|
|
||||||
|
let startBoundElement;
|
||||||
|
let endBoundElement;
|
||||||
|
|
||||||
|
mutateElement(excliadrawLinearElement, {
|
||||||
|
startBinding: linearElement?.startBinding || null,
|
||||||
|
endBinding: linearElement.endBinding || null,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
const width = start?.width ?? 100;
|
||||||
|
const height = start?.height ?? 100;
|
||||||
|
const existingElement = start.id
|
||||||
|
? elements.find((ele) => ele?.id === start.id)
|
||||||
|
: undefined;
|
||||||
|
startBoundElement = newElement({
|
||||||
|
x: start.x || excliadrawLinearElement.x - width,
|
||||||
|
y: start.y || excliadrawLinearElement.y - height / 2,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
...existingElement,
|
||||||
|
...start,
|
||||||
|
});
|
||||||
|
|
||||||
|
bindLinearElement(
|
||||||
|
excliadrawLinearElement,
|
||||||
|
startBoundElement as ExcalidrawBindableElement,
|
||||||
|
"start",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (end) {
|
||||||
|
const height = end?.height ?? 100;
|
||||||
|
const existingElement = end.id
|
||||||
|
? elements.find((ele) => ele?.id === end.id)
|
||||||
|
: undefined;
|
||||||
|
endBoundElement = newElement({
|
||||||
|
x: end.x || excliadrawLinearElement.x + excliadrawLinearElement.width,
|
||||||
|
y: end.y || excliadrawLinearElement.y - height / 2,
|
||||||
|
width: end?.width ?? 100,
|
||||||
|
height,
|
||||||
|
...existingElement,
|
||||||
|
...end,
|
||||||
|
}) as ExcalidrawBindableElement;
|
||||||
|
|
||||||
|
bindLinearElement(
|
||||||
|
excliadrawLinearElement,
|
||||||
|
endBoundElement as ExcalidrawBindableElement,
|
||||||
|
"end",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
linearElement: excliadrawLinearElement,
|
||||||
|
//@ts-ignore
|
||||||
|
startBoundElement,
|
||||||
|
//@ts-ignore
|
||||||
|
endBoundElement,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const excalidrawElements = (() => {
|
||||||
|
const res: ExcalidrawElement[] = [];
|
||||||
|
const elementMap = new Map<string, number>();
|
||||||
|
|
||||||
|
const push = (ele?: ExcalidrawElement) => {
|
||||||
|
if (!ele) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const index = elementMap.get(ele.id);
|
||||||
|
if (index !== undefined && index >= 0) {
|
||||||
|
res[index] = ele;
|
||||||
|
} else {
|
||||||
|
res.push(ele);
|
||||||
|
const index = res.length - 1;
|
||||||
|
elementMap.set(ele.id, index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const clear = () => {
|
||||||
|
res.length = 0;
|
||||||
|
};
|
||||||
|
const get = () => {
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
push,
|
||||||
|
clear,
|
||||||
|
get,
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
export const convertToExcalidrawElements = (
|
||||||
|
elements: ImportedDataState["elements"],
|
||||||
|
): ExcalidrawElement[] => {
|
||||||
|
excalidrawElements.clear();
|
||||||
|
if (!elements) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
elements.forEach((element) => {
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)) {
|
||||||
|
excalidrawElements.push(element as ExcalidrawElement);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//@ts-ignore
|
||||||
|
if (VALID_CONTAINER_TYPES.has(element.type) && element?.label?.text) {
|
||||||
|
//@ts-ignore
|
||||||
|
let [container, text] = bindTextToContainer(element, element.label);
|
||||||
|
excalidrawElements.push(container);
|
||||||
|
excalidrawElements.push(text);
|
||||||
|
|
||||||
|
if (container.type === "arrow") {
|
||||||
|
const { linearElement, startBoundElement, endBoundElement } =
|
||||||
|
bindLinearElementToElement(
|
||||||
|
{
|
||||||
|
...container,
|
||||||
|
//@ts-ignore
|
||||||
|
start: element?.start,
|
||||||
|
//@ts-ignore
|
||||||
|
end: element?.end,
|
||||||
|
},
|
||||||
|
elements,
|
||||||
|
);
|
||||||
|
container = linearElement;
|
||||||
|
excalidrawElements.push(linearElement);
|
||||||
|
excalidrawElements.push(startBoundElement);
|
||||||
|
excalidrawElements.push(endBoundElement);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let excalidrawElement;
|
||||||
|
if (element.type === "text") {
|
||||||
|
excalidrawElement = {
|
||||||
|
...element,
|
||||||
|
} as ExcalidrawTextElement;
|
||||||
|
excalidrawElements.push(excalidrawElement);
|
||||||
|
} else if (element.type === "arrow" || element.type === "line") {
|
||||||
|
const { linearElement, startBoundElement, endBoundElement } =
|
||||||
|
//@ts-ignore
|
||||||
|
bindLinearElementToElement(element, elements);
|
||||||
|
excalidrawElements.push(linearElement);
|
||||||
|
excalidrawElements.push(startBoundElement);
|
||||||
|
excalidrawElements.push(endBoundElement);
|
||||||
|
//@ts-ignore
|
||||||
|
if (startBoundElement && !element.start.id) {
|
||||||
|
//@ts-ignore
|
||||||
|
excalidrawElements.push(startBoundElement);
|
||||||
|
}
|
||||||
|
//@ts-ignore
|
||||||
|
if (endBoundElement && !element.end.id) {
|
||||||
|
//@ts-ignore
|
||||||
|
excalidrawElements.push(endBoundElement);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
excalidrawElement = {
|
||||||
|
...element,
|
||||||
|
width:
|
||||||
|
element?.width ||
|
||||||
|
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
||||||
|
? 100
|
||||||
|
: 0),
|
||||||
|
height:
|
||||||
|
element?.height ||
|
||||||
|
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
||||||
|
? 100
|
||||||
|
: 0),
|
||||||
|
} as ExcalidrawGenericElement;
|
||||||
|
excalidrawElements.push(excalidrawElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return excalidrawElements.get();
|
||||||
|
};
|
|
@ -1,7 +1,8 @@
|
||||||
import {
|
import {
|
||||||
Arrowhead,
|
|
||||||
ExcalidrawBindableElement,
|
ExcalidrawBindableElement,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
|
ExcalidrawGenericElement,
|
||||||
|
ExcalidrawLinearElement,
|
||||||
FontFamilyValues,
|
FontFamilyValues,
|
||||||
TextAlign,
|
TextAlign,
|
||||||
VerticalAlign,
|
VerticalAlign,
|
||||||
|
@ -15,10 +16,8 @@ import {
|
||||||
import type { cleanAppStateForExport } from "../appState";
|
import type { cleanAppStateForExport } from "../appState";
|
||||||
import { VERSIONS } from "../constants";
|
import { VERSIONS } from "../constants";
|
||||||
import { MarkOptional } from "../utility-types";
|
import { MarkOptional } from "../utility-types";
|
||||||
import {
|
import { ElementConstructorOpts } from "../element/newElement";
|
||||||
ElementConstructorOpts,
|
import { ELEMENTS_SUPPORTING_PROGRAMMATIC_API } from "./transform";
|
||||||
ELEMENTS_SUPPORTING_PROGRAMMATIC_API,
|
|
||||||
} from "../element/newElement";
|
|
||||||
|
|
||||||
export interface ExportedDataState {
|
export interface ExportedDataState {
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -74,9 +73,12 @@ export interface ImportedDataState {
|
||||||
| ({
|
| ({
|
||||||
type: "text";
|
type: "text";
|
||||||
text: string;
|
text: string;
|
||||||
|
id?: ExcalidrawBindableElement["id"];
|
||||||
} & ElementConstructorOpts)
|
} & ElementConstructorOpts)
|
||||||
| ({
|
| ({
|
||||||
type: "arrow";
|
type: ExcalidrawLinearElement["type"];
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
label?: {
|
label?: {
|
||||||
text: string;
|
text: string;
|
||||||
fontSize?: number;
|
fontSize?: number;
|
||||||
|
@ -85,13 +87,17 @@ export interface ImportedDataState {
|
||||||
verticalAlign?: VerticalAlign;
|
verticalAlign?: VerticalAlign;
|
||||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
start?: {
|
start?: {
|
||||||
type: ExcalidrawBindableElement["type"];
|
type: Exclude<
|
||||||
|
ExcalidrawBindableElement["type"],
|
||||||
|
"image" | "selection" | "text"
|
||||||
|
>;
|
||||||
|
id?: ExcalidrawGenericElement["id"];
|
||||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
end?: {
|
end?: {
|
||||||
type: ExcalidrawBindableElement["type"];
|
type: ExcalidrawGenericElement["type"];
|
||||||
|
id?: ExcalidrawGenericElement["id"];
|
||||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
endArrowhead?: Arrowhead | null;
|
} & Partial<ExcalidrawLinearElement>)
|
||||||
} & ElementConstructorOpts)
|
|
||||||
)[]
|
)[]
|
||||||
| null;
|
| null;
|
||||||
appState?: Readonly<
|
appState?: Readonly<
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
ExcalidrawFreeDrawElement,
|
ExcalidrawFreeDrawElement,
|
||||||
FontFamilyValues,
|
FontFamilyValues,
|
||||||
ExcalidrawTextContainer,
|
ExcalidrawTextContainer,
|
||||||
ExcalidrawBindableElement,
|
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import {
|
import {
|
||||||
arrayToMap,
|
arrayToMap,
|
||||||
|
@ -36,8 +35,6 @@ import {
|
||||||
wrapText,
|
wrapText,
|
||||||
getBoundTextMaxWidth,
|
getBoundTextMaxWidth,
|
||||||
getDefaultLineHeight,
|
getDefaultLineHeight,
|
||||||
bindTextToContainer,
|
|
||||||
VALID_CONTAINER_TYPES,
|
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
import {
|
import {
|
||||||
DEFAULT_ELEMENT_PROPS,
|
DEFAULT_ELEMENT_PROPS,
|
||||||
|
@ -49,17 +46,7 @@ import {
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
import { isArrowElement } from "./typeChecks";
|
import { isArrowElement } from "./typeChecks";
|
||||||
import { MarkOptional, Merge, Mutable } from "../utility-types";
|
import { MarkOptional, Merge, Mutable } from "../utility-types";
|
||||||
import { ImportedDataState } from "../data/types";
|
|
||||||
import { bindLinearElement } from "./binding";
|
|
||||||
|
|
||||||
export const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
|
|
||||||
"rectangle",
|
|
||||||
"ellipse",
|
|
||||||
"diamond",
|
|
||||||
"text",
|
|
||||||
"arrow",
|
|
||||||
"line",
|
|
||||||
];
|
|
||||||
export type ElementConstructorOpts = MarkOptional<
|
export type ElementConstructorOpts = MarkOptional<
|
||||||
Omit<ExcalidrawGenericElement, "id" | "type" | "isDeleted" | "updated">,
|
Omit<ExcalidrawGenericElement, "id" | "type" | "isDeleted" | "updated">,
|
||||||
| "width"
|
| "width"
|
||||||
|
@ -656,169 +643,3 @@ export const duplicateElements = (
|
||||||
|
|
||||||
return clonedElements;
|
return clonedElements;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertToExcalidrawElements = (
|
|
||||||
elements: ImportedDataState["elements"],
|
|
||||||
) => {
|
|
||||||
const res: ExcalidrawElement[] = [];
|
|
||||||
if (!elements) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
elements.forEach((element) => {
|
|
||||||
if (!element) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)) {
|
|
||||||
res.push(element as ExcalidrawElement);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let startBoundElement;
|
|
||||||
let endBoundElement;
|
|
||||||
//@ts-ignore
|
|
||||||
if (VALID_CONTAINER_TYPES.has(element.type) && element?.label?.text) {
|
|
||||||
//@ts-ignore
|
|
||||||
const elements = bindTextToContainer(element, element.label);
|
|
||||||
const [container, text] = elements;
|
|
||||||
|
|
||||||
if (container.type === "arrow") {
|
|
||||||
//@ts-ignore
|
|
||||||
const { start, end } = element;
|
|
||||||
mutateElement(container, {
|
|
||||||
//@ts-ignore
|
|
||||||
startBinding: element?.startBinding || null,
|
|
||||||
//@ts-ignore
|
|
||||||
endBinding: element.endBinding || null,
|
|
||||||
});
|
|
||||||
if (start) {
|
|
||||||
const width = start?.width ?? 100;
|
|
||||||
const height = start?.height ?? 100;
|
|
||||||
|
|
||||||
startBoundElement = newElement({
|
|
||||||
x: start.x || container.x - width,
|
|
||||||
y: start.y || container.y - height / 2,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
...start,
|
|
||||||
}) as ExcalidrawBindableElement;
|
|
||||||
bindLinearElement(
|
|
||||||
container as ExcalidrawLinearElement,
|
|
||||||
startBoundElement,
|
|
||||||
"start",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (end) {
|
|
||||||
const height = end?.height ?? 100;
|
|
||||||
|
|
||||||
endBoundElement = newElement({
|
|
||||||
x: end.x || container.x + container.width,
|
|
||||||
y: end.y || container.y - height / 2,
|
|
||||||
width: end?.width ?? 100,
|
|
||||||
height,
|
|
||||||
...end,
|
|
||||||
}) as ExcalidrawBindableElement;
|
|
||||||
bindLinearElement(
|
|
||||||
container as ExcalidrawLinearElement,
|
|
||||||
endBoundElement,
|
|
||||||
"end",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.push(container);
|
|
||||||
res.push(text);
|
|
||||||
if (startBoundElement) {
|
|
||||||
res.push(startBoundElement);
|
|
||||||
}
|
|
||||||
if (endBoundElement) {
|
|
||||||
res.push(endBoundElement);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let excalidrawElement;
|
|
||||||
if (element.type === "text") {
|
|
||||||
excalidrawElement = {
|
|
||||||
...element,
|
|
||||||
} as ExcalidrawTextElement;
|
|
||||||
res.push(excalidrawElement);
|
|
||||||
} else if (element.type === "arrow" || element.type === "line") {
|
|
||||||
const {
|
|
||||||
//@ts-ignore
|
|
||||||
start,
|
|
||||||
//@ts-ignore
|
|
||||||
end,
|
|
||||||
type,
|
|
||||||
//@ts-ignore
|
|
||||||
endArrowhead = element.type === "arrow" ? "arrow" : null,
|
|
||||||
...rest
|
|
||||||
} = element;
|
|
||||||
|
|
||||||
excalidrawElement = newLinearElement({
|
|
||||||
type,
|
|
||||||
width: 200,
|
|
||||||
height: 24,
|
|
||||||
points: [
|
|
||||||
[0, 0],
|
|
||||||
[200, 0],
|
|
||||||
],
|
|
||||||
endArrowhead,
|
|
||||||
...rest,
|
|
||||||
});
|
|
||||||
|
|
||||||
mutateElement(excalidrawElement, {
|
|
||||||
//@ts-ignore
|
|
||||||
startBinding: element?.startBinding || null,
|
|
||||||
//@ts-ignore
|
|
||||||
endBinding: element.endBinding || null,
|
|
||||||
});
|
|
||||||
let startBoundElement;
|
|
||||||
let endBoundElement;
|
|
||||||
if (start) {
|
|
||||||
const width = start?.width ?? 100;
|
|
||||||
const height = start?.height ?? 100;
|
|
||||||
startBoundElement = newElement({
|
|
||||||
x: start.x || excalidrawElement.x - width,
|
|
||||||
y: start.y || excalidrawElement.y - height / 2,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
...start,
|
|
||||||
}) as ExcalidrawBindableElement;
|
|
||||||
bindLinearElement(excalidrawElement, startBoundElement, "start");
|
|
||||||
}
|
|
||||||
if (end) {
|
|
||||||
const height = end?.height ?? 100;
|
|
||||||
|
|
||||||
endBoundElement = newElement({
|
|
||||||
x: end.x || excalidrawElement.x + excalidrawElement.width,
|
|
||||||
y: end.y || excalidrawElement.y - height / 2,
|
|
||||||
width: end?.width ?? 100,
|
|
||||||
height,
|
|
||||||
...end,
|
|
||||||
}) as ExcalidrawBindableElement;
|
|
||||||
bindLinearElement(excalidrawElement, endBoundElement, "end");
|
|
||||||
}
|
|
||||||
|
|
||||||
res.push(excalidrawElement);
|
|
||||||
if (startBoundElement) {
|
|
||||||
res.push(startBoundElement);
|
|
||||||
}
|
|
||||||
if (endBoundElement) {
|
|
||||||
res.push(endBoundElement);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
excalidrawElement = {
|
|
||||||
...element,
|
|
||||||
width:
|
|
||||||
element?.width ||
|
|
||||||
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
|
||||||
? 100
|
|
||||||
: 0),
|
|
||||||
height:
|
|
||||||
element?.height ||
|
|
||||||
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
|
||||||
? 100
|
|
||||||
: 0),
|
|
||||||
} as ExcalidrawGenericElement;
|
|
||||||
res.push(excalidrawElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
|
@ -980,55 +980,3 @@ export const getDefaultLineHeight = (fontFamily: FontFamilyValues) => {
|
||||||
}
|
}
|
||||||
return DEFAULT_LINE_HEIGHT[DEFAULT_FONT_FAMILY];
|
return DEFAULT_LINE_HEIGHT[DEFAULT_FONT_FAMILY];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bindTextToContainer = (
|
|
||||||
containerProps:
|
|
||||||
| {
|
|
||||||
type:
|
|
||||||
| Exclude<ExcalidrawGenericElement["type"], "selection">
|
|
||||||
| ExcalidrawLinearElement["type"];
|
|
||||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">,
|
|
||||||
textProps: { text: string } & MarkOptional<ElementConstructorOpts, "x" | "y">,
|
|
||||||
) => {
|
|
||||||
let container;
|
|
||||||
if (containerProps.type === "arrow") {
|
|
||||||
container = newLinearElement({
|
|
||||||
width: containerProps.width || 300,
|
|
||||||
height: containerProps.height || 24,
|
|
||||||
//@ts-ignore
|
|
||||||
type: containerProps.type,
|
|
||||||
//@ts-ignore,
|
|
||||||
endArrowhead: containerProps.type === "arrow" ? "arrow" : null,
|
|
||||||
//@ts-ignore
|
|
||||||
points: [
|
|
||||||
[0, 0],
|
|
||||||
[300, 0],
|
|
||||||
],
|
|
||||||
...containerProps,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
//@ts-ignore
|
|
||||||
container = newElement({
|
|
||||||
...containerProps,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const textElement: ExcalidrawTextElement = newTextElement({
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
textAlign: TEXT_ALIGN.CENTER,
|
|
||||||
verticalAlign: VERTICAL_ALIGN.MIDDLE,
|
|
||||||
...textProps,
|
|
||||||
containerId: container.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
mutateElement(container, {
|
|
||||||
boundElements: (container.boundElements || []).concat({
|
|
||||||
type: "text",
|
|
||||||
id: textElement.id,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
redrawTextBoundingBox(textElement, container);
|
|
||||||
|
|
||||||
return [container, textElement];
|
|
||||||
};
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
import { serializeAsJSON } from "../../data/json";
|
import { serializeAsJSON } from "../../data/json";
|
||||||
import { restore } from "../../data/restore";
|
import { restore } from "../../data/restore";
|
||||||
import { ImportedDataState } from "../../data/types";
|
import { ImportedDataState } from "../../data/types";
|
||||||
import { convertToExcalidrawElements } from "../../element/newElement";
|
import { convertToExcalidrawElements } from "../../data/transform";
|
||||||
import { isInvisiblySmallElement } from "../../element/sizeHelpers";
|
import { isInvisiblySmallElement } from "../../element/sizeHelpers";
|
||||||
import { isInitializedImageElement } from "../../element/typeChecks";
|
import { isInitializedImageElement } from "../../element/typeChecks";
|
||||||
import { ExcalidrawElement, FileId } from "../../element/types";
|
import { ExcalidrawElement, FileId } from "../../element/types";
|
||||||
|
|
|
@ -87,7 +87,7 @@ import { appJotaiStore } from "./app-jotai";
|
||||||
|
|
||||||
import "./index.scss";
|
import "./index.scss";
|
||||||
import { ResolutionType } from "../utility-types";
|
import { ResolutionType } from "../utility-types";
|
||||||
import { convertToExcalidrawElements } from "../element/newElement";
|
import { convertToExcalidrawElements } from "../data/transform";
|
||||||
|
|
||||||
polyfill();
|
polyfill();
|
||||||
|
|
||||||
|
|
|
@ -207,9 +207,9 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
|
||||||
|
|
||||||
{
|
{
|
||||||
type: "arrow",
|
type: "arrow",
|
||||||
x: -160,
|
x: 300,
|
||||||
y: 300,
|
y: 150,
|
||||||
start: { type: "rectangle", width: 300, height: 300 },
|
start: { type: "rectangle", id: "rect-1" },
|
||||||
end: { type: "ellipse" },
|
end: { type: "ellipse" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { decodePngMetadata, decodeSvgMetadata } from "../../data/image";
|
import { decodePngMetadata, decodeSvgMetadata } from "../../data/image";
|
||||||
import { ImportedDataState } from "../../data/types";
|
import { ImportedDataState } from "../../data/types";
|
||||||
import { convertToExcalidrawElements } from "../../element/newElement";
|
import { convertToExcalidrawElements } from "../../data/transform";
|
||||||
import * as utils from "../../packages/utils";
|
import * as utils from "../../packages/utils";
|
||||||
import { API } from "../helpers/api";
|
import { API } from "../helpers/api";
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue