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:
Tom Sherman 2022-04-07 12:43:29 +01:00 committed by GitHub
parent c2fce6d8c4
commit 327ed0e2d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 1066 additions and 53 deletions

View file

@ -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(

View file

@ -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];

View file

@ -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;
};

View file

@ -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" ||

View file

@ -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" ||

View file

@ -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 & {