mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-23 17:30:44 +02:00
support arrow bindings via start and end in api
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
|
ExcalidrawBindableElement,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
|
ExcalidrawLinearElement,
|
||||||
FontFamilyValues,
|
FontFamilyValues,
|
||||||
TextAlign,
|
TextAlign,
|
||||||
VerticalAlign,
|
VerticalAlign,
|
||||||
@@ -71,6 +73,22 @@ export interface ImportedDataState {
|
|||||||
type: "text";
|
type: "text";
|
||||||
text: string;
|
text: string;
|
||||||
} & ElementConstructorOpts)
|
} & ElementConstructorOpts)
|
||||||
|
| ({
|
||||||
|
type: "arrow";
|
||||||
|
label?: {
|
||||||
|
text: string;
|
||||||
|
fontSize?: number;
|
||||||
|
fontFamily?: FontFamilyValues;
|
||||||
|
textAlign?: TextAlign;
|
||||||
|
verticalAlign?: VerticalAlign;
|
||||||
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
|
start?: {
|
||||||
|
type: ExcalidrawBindableElement["type"] & ElementConstructorOpts;
|
||||||
|
};
|
||||||
|
end?: {
|
||||||
|
type: ExcalidrawBindableElement["type"] & ElementConstructorOpts;
|
||||||
|
};
|
||||||
|
} & ElementConstructorOpts)
|
||||||
)[]
|
)[]
|
||||||
| null;
|
| null;
|
||||||
appState?: Readonly<
|
appState?: Readonly<
|
||||||
|
@@ -190,7 +190,7 @@ export const maybeBindLinearElement = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const bindLinearElement = (
|
export const bindLinearElement = (
|
||||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||||
hoveredElement: ExcalidrawBindableElement,
|
hoveredElement: ExcalidrawBindableElement,
|
||||||
startOrEnd: "start" | "end",
|
startOrEnd: "start" | "end",
|
||||||
|
@@ -12,6 +12,7 @@ import {
|
|||||||
ExcalidrawFreeDrawElement,
|
ExcalidrawFreeDrawElement,
|
||||||
FontFamilyValues,
|
FontFamilyValues,
|
||||||
ExcalidrawTextContainer,
|
ExcalidrawTextContainer,
|
||||||
|
ExcalidrawBindableElement,
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import {
|
import {
|
||||||
arrayToMap,
|
arrayToMap,
|
||||||
@@ -49,6 +50,7 @@ import {
|
|||||||
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 { ImportedDataState } from "../data/types";
|
||||||
|
import { bindLinearElement } from "./binding";
|
||||||
|
|
||||||
export const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
|
export const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
|
||||||
"rectangle",
|
"rectangle",
|
||||||
@@ -670,30 +672,116 @@ export const convertToExcalidrawElements = (
|
|||||||
res.push(element as ExcalidrawElement);
|
res.push(element as ExcalidrawElement);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let startBoundElement;
|
||||||
|
let endBoundElement;
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
if (VALID_CONTAINER_TYPES.has(element.type) && element?.label?.text) {
|
if (VALID_CONTAINER_TYPES.has(element.type) && element?.label?.text) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const elements = bindTextToContainer(element, element.label);
|
const elements = bindTextToContainer(element, element.label);
|
||||||
res.push(...elements);
|
const [container, text] = elements;
|
||||||
|
|
||||||
|
if (container.type === "arrow") {
|
||||||
|
//@ts-ignore
|
||||||
|
const { start, end } = element;
|
||||||
|
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 {
|
} else {
|
||||||
let excalidrawElement;
|
let excalidrawElement;
|
||||||
const { type, ...rest } = element;
|
|
||||||
if (element.type === "text") {
|
if (element.type === "text") {
|
||||||
excalidrawElement = {
|
excalidrawElement = {
|
||||||
...element,
|
...element,
|
||||||
} as ExcalidrawTextElement;
|
} as ExcalidrawTextElement;
|
||||||
} else if (type === "arrow" || type === "line") {
|
res.push(excalidrawElement);
|
||||||
|
} else if (element.type === "arrow" || element.type === "line") {
|
||||||
|
//@ts-ignore
|
||||||
|
const { start, end, type, endArrowHead, ...rest } = element;
|
||||||
|
|
||||||
excalidrawElement = {
|
excalidrawElement = {
|
||||||
type,
|
type,
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 24,
|
height: 24,
|
||||||
endArrowhead: element.type === "arrow" ? "arrow" : null,
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[200, 0],
|
[200, 0],
|
||||||
],
|
],
|
||||||
|
endArrowhead: endArrowHead || type === "arrow" ? "arrow" : null,
|
||||||
...rest,
|
...rest,
|
||||||
} as ExcalidrawLinearElement;
|
} as ExcalidrawLinearElement;
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
excalidrawElement = {
|
excalidrawElement = {
|
||||||
...element,
|
...element,
|
||||||
@@ -708,9 +796,9 @@ export const convertToExcalidrawElements = (
|
|||||||
? 100
|
? 100
|
||||||
: 0),
|
: 0),
|
||||||
} as ExcalidrawGenericElement;
|
} as ExcalidrawGenericElement;
|
||||||
}
|
|
||||||
res.push(excalidrawElement);
|
res.push(excalidrawElement);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
@@ -993,10 +993,8 @@ export const bindTextToContainer = (
|
|||||||
let container;
|
let container;
|
||||||
if (containerProps.type === "arrow") {
|
if (containerProps.type === "arrow") {
|
||||||
container = newLinearElement({
|
container = newLinearElement({
|
||||||
//@ts-ignore
|
width: containerProps.width || 300,
|
||||||
x: 0,
|
height: containerProps.height || 24,
|
||||||
//@ts-ignore
|
|
||||||
y: 0,
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
type: containerProps.type,
|
type: containerProps.type,
|
||||||
//@ts-ignore,
|
//@ts-ignore,
|
||||||
@@ -1011,8 +1009,6 @@ export const bindTextToContainer = (
|
|||||||
} else {
|
} else {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
container = newElement({
|
container = newElement({
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
...containerProps,
|
...containerProps,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user