mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: support creating containers, linear elements, text containers, labelled arrows and arrow bindings programatically (#6546)
* feat: support creating text containers programatically
* fix
* fix
* fix
* fix
* update api to use label
* fix api and support individual shapes and text element
* update test case in package example
* support creating arrows and line
* support labelled arrows
* add in package example
* fix alignment
* better types
* fix
* keep element as is unless we support prog api
* fix tests
* fix lint
* ignore
* support arrow bindings via start and end in api
* fix lint
* fix coords
* support id as well for elements
* preserve bindings if present and fix testcases
* preserve bindings for labelled arrows
* support ids, clean up code and move the api related stuff to transform.ts
* allow multiple arrows to bind to single element
* fix singular elements
* fix single text element, unique id and tests
* fix lint
* fix
* support binding arrow to text element
* fix creation of regular text
* use same stroke color as parent for text containers and height 0 for linear element by default
* fix types
* fix
* remove more ts ignore
* remove ts ignore
* remove
* Add coverage script
* Add tests
* fix tests
* make type optional when id present
* remove type when id provided in tests
* Add more tests
* tweak
* let host call convertToExcalidrawElements when using programmatic API
* remove convertToExcalidrawElements call from restore
* lint
* update snaps
* Add new type excalidraw-api/clipboard for programmatic api
* cleanup
* rename tweak
* tweak
* make image attributes optional and better ts check
* support image via programmatic API
* fix lint
* more types
* make fileId mandatory for image and export convertToExcalidrawElements
* fix
* small tweaks
* update snaps
* fix
* use Object.assign instead of mutateElement
* lint
* preserve z-index by pushing all elements first and then add bindings
* instantiate instead of closure for storing elements
* use element API to create regular text, diamond, ellipse and rectangle
* fix snaps
* udpdate api
* ts fixes
* make `convertToExcalidrawElements` more typesafe
* update snaps
* refactor the approach so that order of elements doesn't matter
* Revert "update snaps"
This reverts commit 621dfadccf
.
* review fixes
* rename ExcalidrawProgrammaticElement -> ExcalidrawELementSkeleton
* Add tests
* give preference to first element when duplicate ids found
* use console.error
---------
Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
ded0222e8d
commit
3ea07076ad
15 changed files with 3440 additions and 454 deletions
|
@ -190,7 +190,7 @@ export const maybeBindLinearElement = (
|
|||
}
|
||||
};
|
||||
|
||||
const bindLinearElement = (
|
||||
export const bindLinearElement = (
|
||||
linearElement: NonDeleted<ExcalidrawLinearElement>,
|
||||
hoveredElement: ExcalidrawBindableElement,
|
||||
startOrEnd: "start" | "end",
|
||||
|
|
|
@ -46,7 +46,7 @@ import {
|
|||
} from "../constants";
|
||||
import { MarkOptional, Merge, Mutable } from "../utility-types";
|
||||
|
||||
type ElementConstructorOpts = MarkOptional<
|
||||
export type ElementConstructorOpts = MarkOptional<
|
||||
Omit<ExcalidrawGenericElement, "id" | "type" | "isDeleted" | "updated">,
|
||||
| "width"
|
||||
| "height"
|
||||
|
@ -187,7 +187,7 @@ export const newTextElement = (
|
|||
fontFamily?: FontFamilyValues;
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
containerId?: ExcalidrawTextContainer["id"];
|
||||
containerId?: ExcalidrawTextContainer["id"] | null;
|
||||
lineHeight?: ExcalidrawTextElement["lineHeight"];
|
||||
strokeWidth?: ExcalidrawTextElement["strokeWidth"];
|
||||
} & ElementConstructorOpts,
|
||||
|
@ -361,8 +361,8 @@ export const newFreeDrawElement = (
|
|||
export const newLinearElement = (
|
||||
opts: {
|
||||
type: ExcalidrawLinearElement["type"];
|
||||
startArrowhead: Arrowhead | null;
|
||||
endArrowhead: Arrowhead | null;
|
||||
startArrowhead?: Arrowhead | null;
|
||||
endArrowhead?: Arrowhead | null;
|
||||
points?: ExcalidrawLinearElement["points"];
|
||||
} & ElementConstructorOpts,
|
||||
): NonDeleted<ExcalidrawLinearElement> => {
|
||||
|
@ -372,8 +372,8 @@ export const newLinearElement = (
|
|||
lastCommittedPoint: null,
|
||||
startBinding: null,
|
||||
endBinding: null,
|
||||
startArrowhead: opts.startArrowhead,
|
||||
endArrowhead: opts.endArrowhead,
|
||||
startArrowhead: opts.startArrowhead || null,
|
||||
endArrowhead: opts.endArrowhead || null,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -477,7 +477,7 @@ export const deepCopyElement = <T extends ExcalidrawElement>(
|
|||
* utility wrapper to generate new id. In test env it reuses the old + postfix
|
||||
* for test assertions.
|
||||
*/
|
||||
const regenerateId = (
|
||||
export const regenerateId = (
|
||||
/** supply null if no previous id exists */
|
||||
previousId: string | null,
|
||||
) => {
|
||||
|
|
|
@ -89,16 +89,23 @@ export const redrawTextBoundingBox = (
|
|||
container,
|
||||
textElement as ExcalidrawTextElementWithContainer,
|
||||
);
|
||||
const maxContainerWidth = getBoundTextMaxWidth(container);
|
||||
|
||||
let nextHeight = container.height;
|
||||
if (metrics.height > maxContainerHeight) {
|
||||
nextHeight = computeContainerDimensionForBoundText(
|
||||
const nextHeight = computeContainerDimensionForBoundText(
|
||||
metrics.height,
|
||||
container.type,
|
||||
);
|
||||
mutateElement(container, { height: nextHeight });
|
||||
updateOriginalContainerCache(container.id, nextHeight);
|
||||
}
|
||||
if (metrics.width > maxContainerWidth) {
|
||||
const nextWidth = computeContainerDimensionForBoundText(
|
||||
metrics.width,
|
||||
container.type,
|
||||
);
|
||||
mutateElement(container, { width: nextWidth });
|
||||
}
|
||||
const updatedTextElement = {
|
||||
...textElement,
|
||||
...boundTextUpdates,
|
||||
|
@ -859,8 +866,9 @@ const VALID_CONTAINER_TYPES = new Set([
|
|||
"arrow",
|
||||
]);
|
||||
|
||||
export const isValidTextContainer = (element: ExcalidrawElement) =>
|
||||
VALID_CONTAINER_TYPES.has(element.type);
|
||||
export const isValidTextContainer = (element: {
|
||||
type: ExcalidrawElement["type"];
|
||||
}) => VALID_CONTAINER_TYPES.has(element.type);
|
||||
|
||||
export const computeContainerDimensionForBoundText = (
|
||||
dimension: number,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue