mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: Element locking (#4964)
Co-authored-by: dwelle <luzar.david@gmail.com> Co-authored-by: Zsolt Viczian <viczian.zsolt@gmail.com>
This commit is contained in:
parent
c2fce6d8c4
commit
327ed0e2d1
31 changed files with 1066 additions and 53 deletions
|
@ -255,7 +255,8 @@ export const getHoveredElementForBinding = (
|
|||
const hoveredElement = getElementAtPosition(
|
||||
scene.getElements(),
|
||||
(element) =>
|
||||
isBindableElement(element) && bindingBorderTest(element, pointerCoords),
|
||||
isBindableElement(element, false) &&
|
||||
bindingBorderTest(element, pointerCoords),
|
||||
);
|
||||
return hoveredElement as NonDeleted<ExcalidrawBindableElement> | null;
|
||||
};
|
||||
|
@ -456,13 +457,13 @@ export const getEligibleElementsForBinding = (
|
|||
): SuggestedBinding[] => {
|
||||
const includedElementIds = new Set(elements.map(({ id }) => id));
|
||||
return elements.flatMap((element) =>
|
||||
isBindingElement(element)
|
||||
isBindingElement(element, false)
|
||||
? (getElligibleElementsForBindingElement(
|
||||
element as NonDeleted<ExcalidrawLinearElement>,
|
||||
).filter(
|
||||
(element) => !includedElementIds.has(element.id),
|
||||
) as SuggestedBinding[])
|
||||
: isBindableElement(element)
|
||||
: isBindableElement(element, false)
|
||||
? getElligibleElementsForBindableElementAndWhere(element).filter(
|
||||
(binding) => !includedElementIds.has(binding[0].id),
|
||||
)
|
||||
|
@ -508,7 +509,7 @@ const getElligibleElementsForBindableElementAndWhere = (
|
|||
return Scene.getScene(bindableElement)!
|
||||
.getElements()
|
||||
.map((element) => {
|
||||
if (!isBindingElement(element)) {
|
||||
if (!isBindingElement(element, false)) {
|
||||
return null;
|
||||
}
|
||||
const canBindStart = isLinearElementEligibleForNewBindingByBindable(
|
||||
|
|
|
@ -205,7 +205,7 @@ export class LinearElementEditor {
|
|||
);
|
||||
|
||||
// suggest bindings for first and last point if selected
|
||||
if (isBindingElement(element)) {
|
||||
if (isBindingElement(element, false)) {
|
||||
const coords: { x: number; y: number }[] = [];
|
||||
|
||||
const firstSelectedIndex = selectedPointsIndices[0];
|
||||
|
|
|
@ -56,6 +56,7 @@ const _newElementBase = <T extends ExcalidrawElement>(
|
|||
strokeSharpness,
|
||||
boundElements = null,
|
||||
link = null,
|
||||
locked,
|
||||
...rest
|
||||
}: ElementConstructorOpts & Omit<Partial<ExcalidrawGenericElement>, "type">,
|
||||
) => {
|
||||
|
@ -83,6 +84,7 @@ const _newElementBase = <T extends ExcalidrawElement>(
|
|||
boundElements,
|
||||
updated: getUpdatedTimestamp(),
|
||||
link,
|
||||
locked,
|
||||
};
|
||||
return element;
|
||||
};
|
||||
|
|
|
@ -222,6 +222,13 @@ export const getTransformHandles = (
|
|||
zoom: Zoom,
|
||||
pointerType: PointerType = "mouse",
|
||||
): TransformHandles => {
|
||||
// so that when locked element is selected (especially when you toggle lock
|
||||
// via keyboard) the locked element is visually distinct, indicating
|
||||
// you can't move/resize
|
||||
if (element.locked) {
|
||||
return {};
|
||||
}
|
||||
|
||||
let omitSides: { [T in TransformHandleType]?: boolean } = {};
|
||||
if (
|
||||
element.type === "arrow" ||
|
||||
|
|
|
@ -70,8 +70,13 @@ export const isLinearElementType = (
|
|||
|
||||
export const isBindingElement = (
|
||||
element?: ExcalidrawElement | null,
|
||||
includeLocked = true,
|
||||
): element is ExcalidrawLinearElement => {
|
||||
return element != null && isBindingElementType(element.type);
|
||||
return (
|
||||
element != null &&
|
||||
(!element.locked || includeLocked === true) &&
|
||||
isBindingElementType(element.type)
|
||||
);
|
||||
};
|
||||
|
||||
export const isBindingElementType = (
|
||||
|
@ -82,9 +87,11 @@ export const isBindingElementType = (
|
|||
|
||||
export const isBindableElement = (
|
||||
element: ExcalidrawElement | null,
|
||||
includeLocked = true,
|
||||
): element is ExcalidrawBindableElement => {
|
||||
return (
|
||||
element != null &&
|
||||
(!element.locked || includeLocked === true) &&
|
||||
(element.type === "rectangle" ||
|
||||
element.type === "diamond" ||
|
||||
element.type === "ellipse" ||
|
||||
|
@ -95,9 +102,11 @@ export const isBindableElement = (
|
|||
|
||||
export const isTextBindableContainer = (
|
||||
element: ExcalidrawElement | null,
|
||||
includeLocked = true,
|
||||
): element is ExcalidrawTextContainer => {
|
||||
return (
|
||||
element != null &&
|
||||
(!element.locked || includeLocked === true) &&
|
||||
(element.type === "rectangle" ||
|
||||
element.type === "diamond" ||
|
||||
element.type === "ellipse" ||
|
||||
|
|
|
@ -55,6 +55,7 @@ type _ExcalidrawElementBase = Readonly<{
|
|||
/** epoch (ms) timestamp of last element update */
|
||||
updated: number;
|
||||
link: string | null;
|
||||
locked: boolean;
|
||||
}>;
|
||||
|
||||
export type ExcalidrawSelectionElement = _ExcalidrawElementBase & {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue