lint & format
This commit is contained in:
@@ -1,10 +1,21 @@
|
||||
{
|
||||
"name": "@excalidraw/element",
|
||||
"version": "0.18.0",
|
||||
"description": "Excalidraw elements-related logic",
|
||||
"keywords": [
|
||||
"excalidraw",
|
||||
"excalidraw-utils"
|
||||
],
|
||||
"bugs": "https://github.com/excalidraw/excalidraw/issues",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/excalidraw/excalidraw",
|
||||
"files": [
|
||||
"dist/*"
|
||||
],
|
||||
"type": "module",
|
||||
"types": "./dist/types/element/src/index.d.ts",
|
||||
"main": "./dist/prod/index.js",
|
||||
"module": "./dist/prod/index.js",
|
||||
"types": "./dist/types/element/src/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/types/element/src/index.d.ts",
|
||||
@@ -25,18 +36,17 @@
|
||||
"default": "./dist/prod/visualdebug.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist/*"
|
||||
],
|
||||
"description": "Excalidraw elements-related logic",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"excalidraw",
|
||||
"excalidraw-utils"
|
||||
],
|
||||
"scripts": {
|
||||
"gen:types": "rimraf types && tsc",
|
||||
"build:esm": "rimraf dist && node ../../scripts/buildBase.js && yarn gen:types"
|
||||
},
|
||||
"dependencies": {
|
||||
"@excalidraw/common": "0.18.0",
|
||||
"@excalidraw/math": "0.18.0"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
@@ -55,15 +65,5 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"bugs": "https://github.com/excalidraw/excalidraw/issues",
|
||||
"repository": "https://github.com/excalidraw/excalidraw",
|
||||
"scripts": {
|
||||
"gen:types": "rimraf types && tsc",
|
||||
"build:esm": "rimraf dist && node ../../scripts/buildBase.js && yarn gen:types"
|
||||
},
|
||||
"dependencies": {
|
||||
"@excalidraw/common": "0.18.0",
|
||||
"@excalidraw/math": "0.18.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ const hashSelectionOpts = (
|
||||
type _ = Assert<
|
||||
SameType<
|
||||
Required<HashableKeys>,
|
||||
Pick<Required<HashableKeys>, typeof keys[number]>
|
||||
Pick<Required<HashableKeys>, (typeof keys)[number]>
|
||||
>
|
||||
>;
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ const bindingStrategyForElbowArrowEndpointDragging = (
|
||||
globalPoint,
|
||||
elements,
|
||||
elementsMap,
|
||||
(element) => maxBindingDistance_simple(zoom),
|
||||
() => maxBindingDistance_simple(zoom),
|
||||
);
|
||||
|
||||
const current = hit
|
||||
@@ -391,7 +391,7 @@ const bindingStrategyForNewSimpleArrowEndpointDragging = (
|
||||
element: otherElement,
|
||||
focusPoint: shiftKey
|
||||
? elementCenterPoint(otherElement, elementsMap)
|
||||
: origin ?? pointFrom<GlobalPoint>(arrow.x, arrow.y),
|
||||
: (origin ?? pointFrom<GlobalPoint>(arrow.x, arrow.y)),
|
||||
};
|
||||
|
||||
// We are hovering another element with the end point
|
||||
@@ -522,41 +522,35 @@ const bindingStrategyForSimpleArrowEndpointDragging_complex = (
|
||||
}
|
||||
// The opposite binding is inside the same element
|
||||
// eslint-disable-next-line no-else-return
|
||||
else {
|
||||
current = { element: hit, mode: "inside", focusPoint: point };
|
||||
|
||||
return { current, other: isMultiPoint ? { mode: undefined } : other };
|
||||
}
|
||||
}
|
||||
// The opposite binding is on a different element (or nested)
|
||||
// eslint-disable-next-line no-else-return
|
||||
else {
|
||||
// Handle the nested element case
|
||||
if (isOverlapping && oppositeElement && !otherIsTransparent) {
|
||||
current = {
|
||||
element: oppositeElement,
|
||||
mode: "inside",
|
||||
focusPoint: point,
|
||||
};
|
||||
} else {
|
||||
current = {
|
||||
element: hit,
|
||||
mode: "orbit",
|
||||
focusPoint: isNested ? point : point,
|
||||
};
|
||||
}
|
||||
current = { element: hit, mode: "inside", focusPoint: point };
|
||||
|
||||
return { current, other: isMultiPoint ? { mode: undefined } : other };
|
||||
}
|
||||
// The opposite binding is on a different element (or nested)
|
||||
// eslint-disable-next-line no-else-return
|
||||
// Handle the nested element case
|
||||
if (isOverlapping && oppositeElement && !otherIsTransparent) {
|
||||
current = {
|
||||
element: oppositeElement,
|
||||
mode: "inside",
|
||||
focusPoint: point,
|
||||
};
|
||||
} else {
|
||||
current = {
|
||||
element: hit,
|
||||
mode: "orbit",
|
||||
focusPoint: isNested ? point : point,
|
||||
};
|
||||
}
|
||||
|
||||
return { current, other: isMultiPoint ? { mode: undefined } : other };
|
||||
}
|
||||
// The opposite binding is on a different element or no binding
|
||||
else {
|
||||
current = {
|
||||
element: hit,
|
||||
mode: "orbit",
|
||||
focusPoint: point,
|
||||
};
|
||||
}
|
||||
current = {
|
||||
element: hit,
|
||||
mode: "orbit",
|
||||
focusPoint: point,
|
||||
};
|
||||
|
||||
// Must return as only one endpoint is dragged, therefore
|
||||
// the end binding strategy might accidentally gets overriden
|
||||
@@ -683,7 +677,7 @@ const getBindingStrategyForDraggingBindingElementEndpoints_simple = (
|
||||
globalPoint,
|
||||
elements,
|
||||
elementsMap,
|
||||
(e) => maxBindingDistance_simple(appState.zoom),
|
||||
() => maxBindingDistance_simple(appState.zoom),
|
||||
);
|
||||
const pointInElement =
|
||||
hit &&
|
||||
@@ -726,13 +720,13 @@ const getBindingStrategyForDraggingBindingElementEndpoints_simple = (
|
||||
focusPoint: startDragged
|
||||
? globalPoint
|
||||
: // NOTE: Can only affect the start point because new arrows always drag the end point
|
||||
opts?.newArrow
|
||||
? appState.selectedLinearElement!.initialState.origin!
|
||||
: LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
arrow,
|
||||
0,
|
||||
elementsMap,
|
||||
), // startFixedPoint,
|
||||
opts?.newArrow
|
||||
? appState.selectedLinearElement!.initialState.origin!
|
||||
: LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
arrow,
|
||||
0,
|
||||
elementsMap,
|
||||
), // startFixedPoint,
|
||||
},
|
||||
end: {
|
||||
mode: "inside",
|
||||
@@ -810,19 +804,19 @@ const getBindingStrategyForDraggingBindingElementEndpoints_simple = (
|
||||
focusPoint: appState.selectedLinearElement.initialState.altFocusPoint,
|
||||
}
|
||||
: opts?.angleLocked && otherBindableElement
|
||||
? {
|
||||
mode: "orbit",
|
||||
element: otherBindableElement,
|
||||
focusPoint:
|
||||
projectFixedPointOntoDiagonal(
|
||||
arrow,
|
||||
otherEndpoint,
|
||||
otherBindableElement,
|
||||
startDragged ? "end" : "start",
|
||||
elementsMap,
|
||||
) || otherEndpoint,
|
||||
}
|
||||
: { mode: undefined };
|
||||
? {
|
||||
mode: "orbit",
|
||||
element: otherBindableElement,
|
||||
focusPoint:
|
||||
projectFixedPointOntoDiagonal(
|
||||
arrow,
|
||||
otherEndpoint,
|
||||
otherBindableElement,
|
||||
startDragged ? "end" : "start",
|
||||
elementsMap,
|
||||
) || otherEndpoint,
|
||||
}
|
||||
: { mode: undefined };
|
||||
|
||||
return {
|
||||
start: startDragged ? current : other,
|
||||
@@ -1944,9 +1938,9 @@ const newBoundElements = (
|
||||
nextBoundElements.push(
|
||||
...elementsToAdd.map(
|
||||
(x) =>
|
||||
({ id: x.id, type: x.type } as
|
||||
({ id: x.id, type: x.type }) as
|
||||
| ExcalidrawArrowElement
|
||||
| ExcalidrawTextElement),
|
||||
| ExcalidrawTextElement,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2414,7 +2408,7 @@ const SHAPE_CONFIGS: Record<ShapeType, SectorConfig[]> = {
|
||||
const getSectorBoundaries = (
|
||||
config: SectorConfig[],
|
||||
): Array<{ start: number; end: number; side: Side }> => {
|
||||
return config.map((sector, index) => {
|
||||
return config.map((sector) => {
|
||||
const halfWidth = sector.sectorWidth / 2;
|
||||
let start = sector.centerAngle - halfWidth;
|
||||
let end = sector.centerAngle + halfWidth;
|
||||
|
||||
@@ -974,7 +974,7 @@ export class AppStateDelta implements DeltaContainer<AppState> {
|
||||
inserted,
|
||||
"selectedElementIds",
|
||||
// ts language server has a bit trouble resolving this, so we are giving it a little push
|
||||
(_) => true as ValueOf<T["selectedElementIds"]>,
|
||||
() => true as ValueOf<T["selectedElementIds"]>,
|
||||
);
|
||||
Delta.diffObjects(
|
||||
deleted,
|
||||
@@ -995,9 +995,8 @@ export class AppStateDelta implements DeltaContainer<AppState> {
|
||||
if (isTestEnv() || isDevEnv()) {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
return [deleted, inserted];
|
||||
}
|
||||
return [deleted, inserted];
|
||||
}
|
||||
|
||||
private static orderAppStateKeys(partial: Partial<ObservedAppState>) {
|
||||
@@ -1459,9 +1458,8 @@ export class ElementsDelta implements DeltaContainer<SceneElementsMap> {
|
||||
if (isTestEnv() || isDevEnv()) {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
return [nextElements, flags.containsVisibleDifference];
|
||||
}
|
||||
return [nextElements, flags.containsVisibleDifference];
|
||||
}
|
||||
|
||||
public squash(delta: ElementsDelta): this {
|
||||
@@ -1802,7 +1800,7 @@ export class ElementsDelta implements DeltaContainer<SceneElementsMap> {
|
||||
|
||||
// updated delta is affecting the binding only in case it contains changed binding or bindable property
|
||||
for (const [id] of Array.from(Object.entries(this.updated)).filter(
|
||||
([_, delta]) =>
|
||||
([, delta]) =>
|
||||
Object.keys({ ...delta.deleted, ...delta.inserted }).find((prop) =>
|
||||
bindingProperties.has(prop as BindingProp | BindableProp),
|
||||
),
|
||||
@@ -1908,9 +1906,8 @@ export class ElementsDelta implements DeltaContainer<SceneElementsMap> {
|
||||
if (isTestEnv() || isDevEnv()) {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
return nextElements;
|
||||
}
|
||||
return nextElements;
|
||||
}
|
||||
|
||||
private static redrawTextBoundingBoxes(
|
||||
@@ -2051,9 +2048,9 @@ export class ElementsDelta implements DeltaContainer<SceneElementsMap> {
|
||||
if (isTestEnv() || isDevEnv()) {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
return [deleted, inserted];
|
||||
}
|
||||
|
||||
return [deleted, inserted];
|
||||
}
|
||||
|
||||
private static stripIrrelevantProps(
|
||||
|
||||
@@ -255,11 +255,12 @@ const handleSegmentRenormalization = (
|
||||
);
|
||||
}
|
||||
|
||||
isDevEnv() &&
|
||||
if (isDevEnv()) {
|
||||
invariant(
|
||||
validateElbowPoints(nextPoints),
|
||||
"Invalid elbow points with fixed segments",
|
||||
);
|
||||
}
|
||||
|
||||
return normalizeArrowElementUpdate(
|
||||
nextPoints,
|
||||
@@ -521,8 +522,8 @@ const handleSegmentMove = (
|
||||
? segmentLength / 2
|
||||
: BASE_PADDING
|
||||
: segmentIsTooShort
|
||||
? -segmentLength / 2
|
||||
: -BASE_PADDING;
|
||||
? -segmentLength / 2
|
||||
: -BASE_PADDING;
|
||||
fixedSegments[activelyModifiedSegmentIdx].start = pointFrom<LocalPoint>(
|
||||
fixedSegments[activelyModifiedSegmentIdx].start[0] +
|
||||
(startIsHorizontal ? padding : 0),
|
||||
@@ -547,8 +548,8 @@ const handleSegmentMove = (
|
||||
? segmentLength / 2
|
||||
: BASE_PADDING
|
||||
: segmentIsTooShort
|
||||
? -segmentLength / 2
|
||||
: -BASE_PADDING;
|
||||
? -segmentLength / 2
|
||||
: -BASE_PADDING;
|
||||
fixedSegments[activelyModifiedSegmentIdx].end = pointFrom<LocalPoint>(
|
||||
fixedSegments[activelyModifiedSegmentIdx].end[0] +
|
||||
(endIsHorizontal ? padding : 0),
|
||||
@@ -571,7 +572,7 @@ const handleSegmentMove = (
|
||||
}));
|
||||
|
||||
// For start, clone old arrow points
|
||||
const newPoints: GlobalPoint[] = arrow.points.map((p, i) =>
|
||||
const newPoints: GlobalPoint[] = arrow.points.map((p) =>
|
||||
pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),
|
||||
);
|
||||
|
||||
@@ -720,11 +721,11 @@ const handleEndpointDrag = (
|
||||
i === 0
|
||||
? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])
|
||||
: i === updatedPoints.length - 1
|
||||
? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])
|
||||
: pointFrom<GlobalPoint>(
|
||||
arrow.x + arrow.points[i][0],
|
||||
arrow.y + arrow.points[i][1],
|
||||
),
|
||||
? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])
|
||||
: pointFrom<GlobalPoint>(
|
||||
arrow.x + arrow.points[i][0],
|
||||
arrow.y + arrow.points[i][1],
|
||||
),
|
||||
);
|
||||
const nextFixedSegments = fixedSegments.map((segment) => ({
|
||||
...segment,
|
||||
@@ -982,8 +983,8 @@ export const updateElbowArrowPoints = (
|
||||
idx === 0
|
||||
? updates.points![0]
|
||||
: idx === arrow.points.length - 1
|
||||
? updates.points![1]
|
||||
: p,
|
||||
? updates.points![1]
|
||||
: p,
|
||||
)
|
||||
: updates.points.slice()
|
||||
: arrow.points.slice();
|
||||
@@ -1489,8 +1490,12 @@ const routeElbowArrow = (
|
||||
node.pos[0],
|
||||
node.pos[1],
|
||||
]) as GlobalPoint[];
|
||||
startDongle && points.unshift(startGlobalPoint);
|
||||
endDongle && points.push(endGlobalPoint);
|
||||
if (startDongle) {
|
||||
points.unshift(startGlobalPoint);
|
||||
}
|
||||
if (endDongle) {
|
||||
points.push(endGlobalPoint);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
@@ -1680,29 +1685,29 @@ const generateDynamicAABBs = (
|
||||
? Math.min((startEl[0] + endEl[2]) / 2, a[0] - startLeft)
|
||||
: (startEl[0] + endEl[2]) / 2
|
||||
: a[0] > b[0]
|
||||
? a[0] - startLeft
|
||||
: common[0] - startLeft,
|
||||
? a[0] - startLeft
|
||||
: common[0] - startLeft,
|
||||
a[1] > b[3]
|
||||
? a[0] > b[2] || a[2] < b[0]
|
||||
? Math.min((startEl[1] + endEl[3]) / 2, a[1] - startUp)
|
||||
: (startEl[1] + endEl[3]) / 2
|
||||
: a[1] > b[1]
|
||||
? a[1] - startUp
|
||||
: common[1] - startUp,
|
||||
? a[1] - startUp
|
||||
: common[1] - startUp,
|
||||
a[2] < b[0]
|
||||
? a[1] > b[3] || a[3] < b[1]
|
||||
? Math.max((startEl[2] + endEl[0]) / 2, a[2] + startRight)
|
||||
: (startEl[2] + endEl[0]) / 2
|
||||
: a[2] < b[2]
|
||||
? a[2] + startRight
|
||||
: common[2] + startRight,
|
||||
? a[2] + startRight
|
||||
: common[2] + startRight,
|
||||
a[3] < b[1]
|
||||
? a[0] > b[2] || a[2] < b[0]
|
||||
? Math.max((startEl[3] + endEl[1]) / 2, a[3] + startDown)
|
||||
: (startEl[3] + endEl[1]) / 2
|
||||
: a[3] < b[3]
|
||||
? a[3] + startDown
|
||||
: common[3] + startDown,
|
||||
? a[3] + startDown
|
||||
: common[3] + startDown,
|
||||
] as Bounds;
|
||||
const second = [
|
||||
b[0] > a[2]
|
||||
@@ -1710,29 +1715,29 @@ const generateDynamicAABBs = (
|
||||
? Math.min((endEl[0] + startEl[2]) / 2, b[0] - endLeft)
|
||||
: (endEl[0] + startEl[2]) / 2
|
||||
: b[0] > a[0]
|
||||
? b[0] - endLeft
|
||||
: common[0] - endLeft,
|
||||
? b[0] - endLeft
|
||||
: common[0] - endLeft,
|
||||
b[1] > a[3]
|
||||
? b[0] > a[2] || b[2] < a[0]
|
||||
? Math.min((endEl[1] + startEl[3]) / 2, b[1] - endUp)
|
||||
: (endEl[1] + startEl[3]) / 2
|
||||
: b[1] > a[1]
|
||||
? b[1] - endUp
|
||||
: common[1] - endUp,
|
||||
? b[1] - endUp
|
||||
: common[1] - endUp,
|
||||
b[2] < a[0]
|
||||
? b[1] > a[3] || b[3] < a[1]
|
||||
? Math.max((endEl[2] + startEl[0]) / 2, b[2] + endRight)
|
||||
: (endEl[2] + startEl[0]) / 2
|
||||
: b[2] < a[2]
|
||||
? b[2] + endRight
|
||||
: common[2] + endRight,
|
||||
? b[2] + endRight
|
||||
: common[2] + endRight,
|
||||
b[3] < a[1]
|
||||
? b[0] > a[2] || b[2] < a[0]
|
||||
? Math.max((endEl[3] + startEl[1]) / 2, b[3] + endDown)
|
||||
: (endEl[3] + startEl[1]) / 2
|
||||
: b[3] < a[3]
|
||||
? b[3] + endDown
|
||||
: common[3] + endDown,
|
||||
? b[3] + endDown
|
||||
: common[3] + endDown,
|
||||
] as Bounds;
|
||||
|
||||
const c = commonAABB([first, second]);
|
||||
@@ -2272,11 +2277,8 @@ const getHoveredElement = (
|
||||
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
||||
zoom?: AppState["zoom"],
|
||||
) => {
|
||||
return getHoveredElementForBinding(
|
||||
origPoint,
|
||||
elements,
|
||||
elementsMap,
|
||||
(element) => maxBindingDistance_simple(zoom),
|
||||
return getHoveredElementForBinding(origPoint, elements, elementsMap, () =>
|
||||
maxBindingDistance_simple(zoom),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { ExcalidrawElement } from "./types";
|
||||
export const defaultGetElementLinkFromSelection: Exclude<
|
||||
AppProps["generateLinkForSelection"],
|
||||
undefined
|
||||
> = (id, type) => {
|
||||
> = (id) => {
|
||||
const url = window.location.href;
|
||||
|
||||
try {
|
||||
@@ -86,7 +86,7 @@ export const isElementLink = (url: string) => {
|
||||
_url.searchParams.has(ELEMENT_LINK_KEY) &&
|
||||
_url.host === window.location.host
|
||||
);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ const parseYouTubeTimestamp = (url: string): number => {
|
||||
const urlObj = new URL(url.startsWith("http") ? url : `https://${url}`);
|
||||
timeParam =
|
||||
urlObj.searchParams.get("t") || urlObj.searchParams.get("start");
|
||||
} catch (error) {
|
||||
} catch {
|
||||
const timeMatch = url.match(/[?&#](?:t|start)=([^&#\s]+)/);
|
||||
timeParam = timeMatch?.[1];
|
||||
}
|
||||
@@ -388,7 +388,7 @@ const matchHostname = (
|
||||
if (bareDomain === bareAllowedHostname) {
|
||||
return bareAllowedHostname;
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -198,8 +198,8 @@ const getOffsets = (
|
||||
linkedNodes.length === 0
|
||||
? 0
|
||||
: (linkedNodes.length + 1) % 2 === 0
|
||||
? ((linkedNodes.length + 1) / 2) * _HORIZONTAL_OFFSET
|
||||
: (linkedNodes.length / 2) * _HORIZONTAL_OFFSET * -1;
|
||||
? ((linkedNodes.length + 1) / 2) * _HORIZONTAL_OFFSET
|
||||
: (linkedNodes.length / 2) * _HORIZONTAL_OFFSET * -1;
|
||||
|
||||
if (direction === "up") {
|
||||
return {
|
||||
@@ -222,8 +222,8 @@ const getOffsets = (
|
||||
linkedNodes.length === 0
|
||||
? 0
|
||||
: (linkedNodes.length + 1) % 2 === 0
|
||||
? ((linkedNodes.length + 1) / 2) * _VERTICAL_OFFSET
|
||||
: (linkedNodes.length / 2) * _VERTICAL_OFFSET * -1;
|
||||
? ((linkedNodes.length + 1) / 2) * _VERTICAL_OFFSET
|
||||
: (linkedNodes.length / 2) * _VERTICAL_OFFSET * -1;
|
||||
|
||||
if (direction === "left") {
|
||||
return {
|
||||
|
||||
@@ -187,7 +187,7 @@ export const syncMovedIndices = (
|
||||
for (const [element, { index }] of elementsUpdates) {
|
||||
mutateElement(element, elementsMap, { index });
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// fallback to default sync
|
||||
syncInvalidIndices(elements);
|
||||
}
|
||||
|
||||
@@ -797,7 +797,7 @@ export const isElementInFrame = (
|
||||
|
||||
for (const gid of _element.groupIds) {
|
||||
if (opts?.checkedGroups?.has(gid)) {
|
||||
return opts.checkedGroups.get(gid)!!;
|
||||
return opts.checkedGroups.get(gid)!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -231,8 +231,8 @@ export const getSelectedGroupIds = (
|
||||
appState: InteractiveCanvasAppState,
|
||||
): GroupId[] =>
|
||||
Object.entries(appState.selectedGroupIds)
|
||||
.filter(([groupId, isSelected]) => isSelected)
|
||||
.map(([groupId, isSelected]) => groupId);
|
||||
.filter(([, isSelected]) => isSelected)
|
||||
.map(([groupId]) => groupId);
|
||||
|
||||
// given a list of elements, return the the actual group ids that should be selected
|
||||
// or used to update the elements
|
||||
@@ -325,8 +325,8 @@ export const getMaximumGroups = (
|
||||
elements: ExcalidrawElement[],
|
||||
elementsMap: ElementsMap,
|
||||
): ExcalidrawElement[][] => {
|
||||
const groups: Map<String, ExcalidrawElement[]> = new Map<
|
||||
String,
|
||||
const groups: Map<string, ExcalidrawElement[]> = new Map<
|
||||
string,
|
||||
ExcalidrawElement[]
|
||||
>();
|
||||
elements.forEach((element: ExcalidrawElement) => {
|
||||
|
||||
@@ -268,16 +268,16 @@ export const headingForPointFromElement = <Point extends GlobalPoint>(
|
||||
)
|
||||
? HEADING_UP
|
||||
: triangleIncludesPoint<Point>(
|
||||
[topRight, bottomRight, midPoint] as Triangle<Point>,
|
||||
p,
|
||||
)
|
||||
? HEADING_RIGHT
|
||||
: triangleIncludesPoint<Point>(
|
||||
[bottomRight, bottomLeft, midPoint] as Triangle<Point>,
|
||||
p,
|
||||
)
|
||||
? HEADING_DOWN
|
||||
: HEADING_LEFT;
|
||||
[topRight, bottomRight, midPoint] as Triangle<Point>,
|
||||
p,
|
||||
)
|
||||
? HEADING_RIGHT
|
||||
: triangleIncludesPoint<Point>(
|
||||
[bottomRight, bottomLeft, midPoint] as Triangle<Point>,
|
||||
p,
|
||||
)
|
||||
? HEADING_DOWN
|
||||
: HEADING_LEFT;
|
||||
};
|
||||
|
||||
export const flipHeading = (h: Heading): Heading =>
|
||||
|
||||
@@ -69,7 +69,7 @@ export const updateImageCache = async ({
|
||||
const image = await imagePromise;
|
||||
|
||||
imageCache.set(fileId, { ...data, image });
|
||||
} catch (error: any) {
|
||||
} catch {
|
||||
erroredFiles.set(fileId, true);
|
||||
}
|
||||
})(),
|
||||
|
||||
@@ -606,10 +606,10 @@ export class LinearElementEditor {
|
||||
updates?.suggestedBinding?.id !== startBindingElement.id // The end point is not hovering the start bindable + it's binding gap
|
||||
? startBindingElement
|
||||
: startIsSelected && // The "other" end (i.e. "start") is dragged
|
||||
endBindingElement &&
|
||||
updates?.suggestedBinding?.id !== endBindingElement.id // The start point is not hovering the end bindable + it's binding gap
|
||||
? endBindingElement
|
||||
: null;
|
||||
endBindingElement &&
|
||||
updates?.suggestedBinding?.id !== endBindingElement.id // The start point is not hovering the end bindable + it's binding gap
|
||||
? endBindingElement
|
||||
: null;
|
||||
|
||||
const newLinearElementEditor: LinearElementEditor = {
|
||||
...linearElementEditor,
|
||||
@@ -721,8 +721,8 @@ export class LinearElementEditor {
|
||||
)
|
||||
: selectedPointsIndices
|
||||
: selectedPointsIndices?.includes(pointerDownState.lastClickedPoint)
|
||||
? [pointerDownState.lastClickedPoint]
|
||||
: selectedPointsIndices,
|
||||
? [pointerDownState.lastClickedPoint]
|
||||
: selectedPointsIndices,
|
||||
isDragging: false,
|
||||
pointerOffset: { x: 0, y: 0 },
|
||||
customLineAngle: null,
|
||||
@@ -976,7 +976,7 @@ export class LinearElementEditor {
|
||||
const appState = app.state;
|
||||
const elementsMap = scene.getNonDeletedElementsMap();
|
||||
|
||||
const ret: ReturnType<typeof LinearElementEditor["handlePointerDown"]> = {
|
||||
const ret: ReturnType<(typeof LinearElementEditor)["handlePointerDown"]> = {
|
||||
didAddPoint: false,
|
||||
hitElement: null,
|
||||
linearElementEditor: null,
|
||||
@@ -2130,8 +2130,8 @@ const pointDraggingUpdates = (
|
||||
suggestedBinding: startIsDragged
|
||||
? start.element
|
||||
: endIsDragged
|
||||
? end.element
|
||||
: null,
|
||||
? end.element
|
||||
: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -2222,14 +2222,14 @@ const pointDraggingUpdates = (
|
||||
updates.startBinding === undefined
|
||||
? element.startBinding
|
||||
: updates.startBinding === null
|
||||
? null
|
||||
: updates.startBinding,
|
||||
? null
|
||||
: updates.startBinding,
|
||||
endBinding:
|
||||
updates.endBinding === undefined
|
||||
? element.endBinding
|
||||
: updates.endBinding === null
|
||||
? null
|
||||
: updates.endBinding,
|
||||
? null
|
||||
: updates.endBinding,
|
||||
};
|
||||
|
||||
// We need to use a custom intersector to ensure that if there is a big "jump"
|
||||
@@ -2261,28 +2261,28 @@ const pointDraggingUpdates = (
|
||||
// We need to update the non-dragged point too if bound,
|
||||
// so we look up the old binding to trigger updateBoundPoint
|
||||
const endBindable = nextArrow.endBinding
|
||||
? end.element ??
|
||||
? (end.element ??
|
||||
(elementsMap.get(
|
||||
nextArrow.endBinding.elementId,
|
||||
)! as ExcalidrawBindableElement)
|
||||
)! as ExcalidrawBindableElement))
|
||||
: null;
|
||||
|
||||
const endLocalPoint = startIsDraggingOverEndElement
|
||||
? nextArrow.points[nextArrow.points.length - 1]
|
||||
: endIsDraggingOverStartElement &&
|
||||
app.state.bindMode !== "inside" &&
|
||||
getFeatureFlag("COMPLEX_BINDINGS")
|
||||
? nextArrow.points[0]
|
||||
: endBindable
|
||||
? updateBoundPoint(
|
||||
element,
|
||||
"endBinding",
|
||||
nextArrow.endBinding,
|
||||
endBindable,
|
||||
elementsMap,
|
||||
endCustomIntersector,
|
||||
) || nextArrow.points[nextArrow.points.length - 1]
|
||||
: nextArrow.points[nextArrow.points.length - 1];
|
||||
app.state.bindMode !== "inside" &&
|
||||
getFeatureFlag("COMPLEX_BINDINGS")
|
||||
? nextArrow.points[0]
|
||||
: endBindable
|
||||
? updateBoundPoint(
|
||||
element,
|
||||
"endBinding",
|
||||
nextArrow.endBinding,
|
||||
endBindable,
|
||||
elementsMap,
|
||||
endCustomIntersector,
|
||||
) || nextArrow.points[nextArrow.points.length - 1]
|
||||
: nextArrow.points[nextArrow.points.length - 1];
|
||||
|
||||
// We need to keep the simulated next arrow up-to-date, because
|
||||
// updateBoundPoint looks at the opposite point
|
||||
@@ -2291,29 +2291,29 @@ const pointDraggingUpdates = (
|
||||
// We need to update the non-dragged point too if bound,
|
||||
// so we look up the old binding to trigger updateBoundPoint
|
||||
const startBindable = nextArrow.startBinding
|
||||
? start.element ??
|
||||
? (start.element ??
|
||||
(elementsMap.get(
|
||||
nextArrow.startBinding.elementId,
|
||||
)! as ExcalidrawBindableElement)
|
||||
)! as ExcalidrawBindableElement))
|
||||
: null;
|
||||
|
||||
const startLocalPoint =
|
||||
endIsDraggingOverStartElement && getFeatureFlag("COMPLEX_BINDINGS")
|
||||
? nextArrow.points[0]
|
||||
: startIsDraggingOverEndElement &&
|
||||
app.state.bindMode !== "inside" &&
|
||||
getFeatureFlag("COMPLEX_BINDINGS")
|
||||
? nextArrow.points[nextArrow.points.length - 1]
|
||||
: startBindable
|
||||
? updateBoundPoint(
|
||||
element,
|
||||
"startBinding",
|
||||
nextArrow.startBinding,
|
||||
startBindable,
|
||||
elementsMap,
|
||||
startCustomIntersector,
|
||||
) || nextArrow.points[0]
|
||||
: nextArrow.points[0];
|
||||
app.state.bindMode !== "inside" &&
|
||||
getFeatureFlag("COMPLEX_BINDINGS")
|
||||
? nextArrow.points[nextArrow.points.length - 1]
|
||||
: startBindable
|
||||
? updateBoundPoint(
|
||||
element,
|
||||
"startBinding",
|
||||
nextArrow.startBinding,
|
||||
startBindable,
|
||||
elementsMap,
|
||||
startCustomIntersector,
|
||||
) || nextArrow.points[0]
|
||||
: nextArrow.points[0];
|
||||
|
||||
const endChanged =
|
||||
pointDistance(
|
||||
@@ -2350,11 +2350,11 @@ const pointDraggingUpdates = (
|
||||
isDragging: true,
|
||||
}
|
||||
: idx === element.points.length - 1
|
||||
? {
|
||||
point: endLocalPoint,
|
||||
isDragging: true,
|
||||
}
|
||||
: naiveDraggingPoints.get(idx)!,
|
||||
? {
|
||||
point: endLocalPoint,
|
||||
isDragging: true,
|
||||
}
|
||||
: naiveDraggingPoints.get(idx)!,
|
||||
];
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -230,8 +230,8 @@ const getTextElementPositionOffsets = (
|
||||
opts.textAlign === "center"
|
||||
? metrics.width / 2
|
||||
: opts.textAlign === "right"
|
||||
? metrics.width
|
||||
: 0,
|
||||
? metrics.width
|
||||
: 0,
|
||||
y: opts.verticalAlign === "middle" ? metrics.height / 2 : 0,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -514,8 +514,8 @@ const drawElementOnCanvas = (
|
||||
element.textAlign === "center"
|
||||
? element.width / 2
|
||||
: element.textAlign === "right"
|
||||
? element.width
|
||||
: 0;
|
||||
? element.width
|
||||
: 0;
|
||||
|
||||
const lineHeightPx = getLineHeightInPx(
|
||||
element.fontSize,
|
||||
|
||||
@@ -819,8 +819,8 @@ export const resizeSingleElement = (
|
||||
nextHeight,
|
||||
origElement.angle,
|
||||
handleDirection,
|
||||
shouldMaintainAspectRatio!!,
|
||||
shouldResizeFromCenter!!,
|
||||
shouldMaintainAspectRatio,
|
||||
shouldResizeFromCenter,
|
||||
);
|
||||
|
||||
if (isLinearElement(origElement) && rescaledPoints.points) {
|
||||
@@ -1370,7 +1370,7 @@ export const resizeMultipleElements = (
|
||||
false,
|
||||
);
|
||||
|
||||
const update: typeof elementsAndUpdates[0]["update"] = {
|
||||
const update: (typeof elementsAndUpdates)[0]["update"] = {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
|
||||
@@ -137,22 +137,28 @@ export const getElementWithTransformHandleType = (
|
||||
elementsMap: ElementsMap,
|
||||
editorInterface: EditorInterface,
|
||||
) => {
|
||||
return elements.reduce((result, element) => {
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
const transformHandleType = resizeTest(
|
||||
element,
|
||||
elementsMap,
|
||||
appState,
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
zoom,
|
||||
pointerType,
|
||||
editorInterface,
|
||||
);
|
||||
return transformHandleType ? { element, transformHandleType } : null;
|
||||
}, null as { element: NonDeletedExcalidrawElement; transformHandleType: MaybeTransformHandleType } | null);
|
||||
return elements.reduce(
|
||||
(result, element) => {
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
const transformHandleType = resizeTest(
|
||||
element,
|
||||
elementsMap,
|
||||
appState,
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
zoom,
|
||||
pointerType,
|
||||
editorInterface,
|
||||
);
|
||||
return transformHandleType ? { element, transformHandleType } : null;
|
||||
},
|
||||
null as {
|
||||
element: NonDeletedExcalidrawElement;
|
||||
transformHandleType: MaybeTransformHandleType;
|
||||
} | null,
|
||||
);
|
||||
};
|
||||
|
||||
export const getTransformHandleTypeFromCoords = <
|
||||
|
||||
@@ -223,10 +223,10 @@ export const getTargetElements = (
|
||||
appState.editingTextElement
|
||||
? [appState.editingTextElement]
|
||||
: appState.newElement
|
||||
? [appState.newElement]
|
||||
: getSelectedElements(elements, appState, {
|
||||
includeBoundTextElement: true,
|
||||
});
|
||||
? [appState.newElement]
|
||||
: getSelectedElements(elements, appState, {
|
||||
includeBoundTextElement: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* returns prevState's selectedElementids if no change from previous, so as to
|
||||
|
||||
@@ -201,8 +201,8 @@ export const generateRoughOptions = (
|
||||
element.strokeStyle === "dashed"
|
||||
? getDashArrayDashed(element.strokeWidth)
|
||||
: element.strokeStyle === "dotted"
|
||||
? getDashArrayDotted(element.strokeWidth)
|
||||
: undefined,
|
||||
? getDashArrayDotted(element.strokeWidth)
|
||||
: undefined,
|
||||
// for non-solid strokes, disable multiStroke because it tends to make
|
||||
// dashes/dots overlay each other
|
||||
disableMultiStroke: element.strokeStyle !== "solid",
|
||||
@@ -235,8 +235,8 @@ export const generateRoughOptions = (
|
||||
options.fill = isTransparent(element.backgroundColor)
|
||||
? undefined
|
||||
: isDarkMode
|
||||
? applyDarkModeFilter(element.backgroundColor)
|
||||
: element.backgroundColor;
|
||||
? applyDarkModeFilter(element.backgroundColor)
|
||||
: element.backgroundColor;
|
||||
if (element.type === "ellipse") {
|
||||
options.curveFitting = 1;
|
||||
}
|
||||
@@ -250,8 +250,8 @@ export const generateRoughOptions = (
|
||||
element.backgroundColor === "transparent"
|
||||
? undefined
|
||||
: isDarkMode
|
||||
? applyDarkModeFilter(element.backgroundColor)
|
||||
: element.backgroundColor;
|
||||
? applyDarkModeFilter(element.backgroundColor)
|
||||
: element.backgroundColor;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
@@ -708,20 +708,20 @@ const _generateElementShape = (
|
||||
rightX - verticalRadius
|
||||
} ${rightY - horizontalRadius}
|
||||
C ${rightX} ${rightY}, ${rightX} ${rightY}, ${
|
||||
rightX - verticalRadius
|
||||
} ${rightY + horizontalRadius}
|
||||
rightX - verticalRadius
|
||||
} ${rightY + horizontalRadius}
|
||||
L ${bottomX + verticalRadius} ${bottomY - horizontalRadius}
|
||||
C ${bottomX} ${bottomY}, ${bottomX} ${bottomY}, ${
|
||||
bottomX - verticalRadius
|
||||
} ${bottomY - horizontalRadius}
|
||||
bottomX - verticalRadius
|
||||
} ${bottomY - horizontalRadius}
|
||||
L ${leftX + verticalRadius} ${leftY + horizontalRadius}
|
||||
C ${leftX} ${leftY}, ${leftX} ${leftY}, ${leftX + verticalRadius} ${
|
||||
leftY - horizontalRadius
|
||||
}
|
||||
leftY - horizontalRadius
|
||||
}
|
||||
L ${topX - verticalRadius} ${topY + horizontalRadius}
|
||||
C ${topX} ${topY}, ${topX} ${topY}, ${topX + verticalRadius} ${
|
||||
topY + horizontalRadius
|
||||
}`,
|
||||
topY + horizontalRadius
|
||||
}`,
|
||||
generateRoughOptions(element, true, isDarkMode),
|
||||
);
|
||||
} else {
|
||||
@@ -1057,8 +1057,8 @@ export const getFreedrawOutlinePoints = (
|
||||
const inputPoints = element.simulatePressure
|
||||
? element.points
|
||||
: element.points.length
|
||||
? element.points.map(([x, y], i) => [x, y, element.pressures[i]])
|
||||
: [[0, 0, 0.5]];
|
||||
? element.points.map(([x, y], i) => [x, y, element.pressures[i]])
|
||||
: [[0, 0, 0.5]];
|
||||
|
||||
return getStroke(inputPoints as number[][], {
|
||||
simulatePressure: element.simulatePressure,
|
||||
|
||||
@@ -10,13 +10,13 @@ export const showSelectedShapeActions = (
|
||||
) =>
|
||||
Boolean(
|
||||
!appState.viewModeEnabled &&
|
||||
appState.openDialog?.name !== "elementLinkSelector" &&
|
||||
((appState.activeTool.type !== "custom" &&
|
||||
(appState.editingTextElement ||
|
||||
(appState.activeTool.type !== "selection" &&
|
||||
appState.activeTool.type !== "lasso" &&
|
||||
appState.activeTool.type !== "eraser" &&
|
||||
appState.activeTool.type !== "hand" &&
|
||||
appState.activeTool.type !== "laser"))) ||
|
||||
getSelectedElements(elements, appState).length),
|
||||
appState.openDialog?.name !== "elementLinkSelector" &&
|
||||
((appState.activeTool.type !== "custom" &&
|
||||
(appState.editingTextElement ||
|
||||
(appState.activeTool.type !== "selection" &&
|
||||
appState.activeTool.type !== "lasso" &&
|
||||
appState.activeTool.type !== "eraser" &&
|
||||
appState.activeTool.type !== "hand" &&
|
||||
appState.activeTool.type !== "laser"))) ||
|
||||
getSelectedElements(elements, appState).length),
|
||||
);
|
||||
|
||||
@@ -89,7 +89,7 @@ const CJK = {
|
||||
* ↑ BREAK BEFORE "「"
|
||||
* ↑ BREAK AFTER "」"
|
||||
*/
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
// prettier-ignore
|
||||
OPENING:/([{〈《⦅「「『【〖〔〘〚<〝/u,
|
||||
CLOSING: /)]}〉》⦆」」』】〗〕〙〛>。.,、〟‥?!:;・〜〞/u,
|
||||
/**
|
||||
|
||||
@@ -73,104 +73,101 @@ export type ValidLinearElement = {
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
end?:
|
||||
end?: (
|
||||
| (
|
||||
| (
|
||||
| {
|
||||
type: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
id?: ExcalidrawGenericElement["id"];
|
||||
}
|
||||
| {
|
||||
id: ExcalidrawGenericElement["id"];
|
||||
type?: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
}
|
||||
)
|
||||
| ((
|
||||
| {
|
||||
type: "text";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type?: "text";
|
||||
id: ExcalidrawTextElement["id"];
|
||||
text: string;
|
||||
}
|
||||
) &
|
||||
Partial<ExcalidrawTextElement>)
|
||||
| {
|
||||
type: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
id?: ExcalidrawGenericElement["id"];
|
||||
}
|
||||
| {
|
||||
id: ExcalidrawGenericElement["id"];
|
||||
type?: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
}
|
||||
)
|
||||
| ((
|
||||
| {
|
||||
type: "text";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type?: "text";
|
||||
id: ExcalidrawTextElement["id"];
|
||||
text: string;
|
||||
}
|
||||
) &
|
||||
MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
start?:
|
||||
Partial<ExcalidrawTextElement>)
|
||||
) &
|
||||
MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
start?: (
|
||||
| (
|
||||
| (
|
||||
| {
|
||||
type: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
id?: ExcalidrawGenericElement["id"];
|
||||
}
|
||||
| {
|
||||
id: ExcalidrawGenericElement["id"];
|
||||
type?: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
}
|
||||
)
|
||||
| ((
|
||||
| {
|
||||
type: "text";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type?: "text";
|
||||
id: ExcalidrawTextElement["id"];
|
||||
text: string;
|
||||
}
|
||||
) &
|
||||
Partial<ExcalidrawTextElement>)
|
||||
| {
|
||||
type: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
id?: ExcalidrawGenericElement["id"];
|
||||
}
|
||||
| {
|
||||
id: ExcalidrawGenericElement["id"];
|
||||
type?: Exclude<
|
||||
ExcalidrawBindableElement["type"],
|
||||
| "image"
|
||||
| "text"
|
||||
| "frame"
|
||||
| "magicframe"
|
||||
| "embeddable"
|
||||
| "iframe"
|
||||
>;
|
||||
}
|
||||
)
|
||||
| ((
|
||||
| {
|
||||
type: "text";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type?: "text";
|
||||
id: ExcalidrawTextElement["id"];
|
||||
text: string;
|
||||
}
|
||||
) &
|
||||
MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
Partial<ExcalidrawTextElement>)
|
||||
) &
|
||||
MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
} & Partial<ExcalidrawLinearElement>;
|
||||
|
||||
export type ValidContainer =
|
||||
| {
|
||||
type: Exclude<ExcalidrawGenericElement["type"], "selection">;
|
||||
id?: ExcalidrawGenericElement["id"];
|
||||
label?: {
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: FontFamilyValues;
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
} & ElementConstructorOpts;
|
||||
export type ValidContainer = {
|
||||
type: Exclude<ExcalidrawGenericElement["type"], "selection">;
|
||||
id?: ExcalidrawGenericElement["id"];
|
||||
label?: {
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: FontFamilyValues;
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
} & ElementConstructorOpts;
|
||||
|
||||
export type ExcalidrawElementSkeleton =
|
||||
| Extract<
|
||||
|
||||
@@ -312,8 +312,8 @@ export const getTransformHandles = (
|
||||
const margin = isLinearElement(element)
|
||||
? DEFAULT_TRANSFORM_HANDLE_SPACING + 8
|
||||
: isImageElement(element)
|
||||
? 0
|
||||
: DEFAULT_TRANSFORM_HANDLE_SPACING;
|
||||
? 0
|
||||
: DEFAULT_TRANSFORM_HANDLE_SPACING;
|
||||
return getTransformHandlesFromCoords(
|
||||
getElementAbsoluteCoords(element, elementsMap, true),
|
||||
element.angle,
|
||||
|
||||
@@ -18,18 +18,18 @@ import type {
|
||||
export type ChartType = "bar" | "line";
|
||||
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
||||
export type FontFamilyKeys = keyof typeof FONT_FAMILY;
|
||||
export type FontFamilyValues = typeof FONT_FAMILY[FontFamilyKeys];
|
||||
export type Theme = typeof THEME[keyof typeof THEME];
|
||||
export type FontFamilyValues = (typeof FONT_FAMILY)[FontFamilyKeys];
|
||||
export type Theme = (typeof THEME)[keyof typeof THEME];
|
||||
export type FontString = string & { _brand: "fontString" };
|
||||
export type GroupId = string;
|
||||
export type PointerType = "mouse" | "pen" | "touch";
|
||||
export type StrokeRoundness = "round" | "sharp";
|
||||
export type RoundnessType = ValueOf<typeof ROUNDNESS>;
|
||||
export type StrokeStyle = "solid" | "dashed" | "dotted";
|
||||
export type TextAlign = typeof TEXT_ALIGN[keyof typeof TEXT_ALIGN];
|
||||
export type TextAlign = (typeof TEXT_ALIGN)[keyof typeof TEXT_ALIGN];
|
||||
|
||||
type VerticalAlignKeys = keyof typeof VERTICAL_ALIGN;
|
||||
export type VerticalAlign = typeof VERTICAL_ALIGN[VerticalAlignKeys];
|
||||
export type VerticalAlign = (typeof VERTICAL_ALIGN)[VerticalAlignKeys];
|
||||
export type FractionalIndex = string & { _brand: "franctionalIndex" };
|
||||
|
||||
export type BoundElement = Readonly<{
|
||||
@@ -124,15 +124,14 @@ export type ExcalidrawIframeLikeElement =
|
||||
| ExcalidrawIframeElement
|
||||
| ExcalidrawEmbeddableElement;
|
||||
|
||||
export type IframeData =
|
||||
| {
|
||||
intrinsicSize: { w: number; h: number };
|
||||
error?: Error;
|
||||
sandbox?: { allowSameOrigin?: boolean };
|
||||
} & (
|
||||
| { type: "video" | "generic"; link: string }
|
||||
| { type: "document"; srcdoc: (theme: Theme) => string }
|
||||
);
|
||||
export type IframeData = {
|
||||
intrinsicSize: { w: number; h: number };
|
||||
error?: Error;
|
||||
sandbox?: { allowSameOrigin?: boolean };
|
||||
} & (
|
||||
| { type: "video" | "generic"; link: string }
|
||||
| { type: "document"; srcdoc: (theme: Theme) => string }
|
||||
);
|
||||
|
||||
export type ImageCrop = {
|
||||
x: number;
|
||||
|
||||
@@ -252,6 +252,7 @@ const addToCurrentFrame = (element: DebugElement) => {
|
||||
if (window.visualDebug?.data && window.visualDebug.data.length === 0) {
|
||||
window.visualDebug.data[0] = [];
|
||||
}
|
||||
window.visualDebug?.data &&
|
||||
if (window.visualDebug?.data) {
|
||||
window.visualDebug.data[window.visualDebug.data.length - 1].push(element);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -335,7 +335,7 @@ const shiftElementsByOne = (
|
||||
.map((idx) => elements[idx].id),
|
||||
);
|
||||
|
||||
groupedIndices.forEach((indices, i) => {
|
||||
groupedIndices.forEach((indices) => {
|
||||
const leadingIndex = indices[0];
|
||||
const trailingIndex = indices[indices.length - 1];
|
||||
const boundaryIndex = direction === "left" ? leadingIndex : trailingIndex;
|
||||
|
||||
@@ -37,7 +37,7 @@ const _ce = ({
|
||||
width: w,
|
||||
height: h,
|
||||
angle: a,
|
||||
} as ExcalidrawElement);
|
||||
}) as ExcalidrawElement;
|
||||
|
||||
describe("getElementAbsoluteCoords", () => {
|
||||
it("test x1 coordinate", () => {
|
||||
|
||||
@@ -24,7 +24,7 @@ describe("Test measureText", () => {
|
||||
...params,
|
||||
});
|
||||
expect(getContainerCoords(element)).toEqual({
|
||||
x: 44.2893218813452455,
|
||||
x: 44.289321881345245,
|
||||
y: 39.64466094067262,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user