feat: better unlock (#9546)
* change lock label * feat: add unlock logic for single units on pointer up * feat: add unlock popup * fix: linting errors * style: padding tweaks * style: remove redundant line * feat: lock multiple units together * style: tweak color & position * feat: add highlight for locked elements * feat: select groups correctly after unlocking * test: update snapshots * fix: lasso from selecting locked elements * fix: should prevent selecting unlocked elements and setting locked id at the same time * fix: reset hit locked id immediately when appropriate * feat: capture locked units in delta * test: update locking test * feat: show lock highlight when locking (including undo/redo) * feat: make locked highlighting consistent * feat: show correct cursor type when moving over locked elements * fix history * remove `lockedUnits.singleUnits` * tweak button * do not render UnlockPopup if not locked element selected * tweak actions * refactor: simplify type * refactor: rename type * refactor: simplify hit element setting & checking * fix: prefer locked over link * rename to `activeLockedId` * refactor: getElementAtPosition takes an optional hitelments array * fix: avoid setting active locked id after resizing --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
41a7613dff
commit
712f267519
@ -187,10 +187,12 @@ export class Delta<T> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof deleted[property] === "object" ||
|
||||
typeof inserted[property] === "object"
|
||||
) {
|
||||
const isDeletedObject =
|
||||
deleted[property] !== null && typeof deleted[property] === "object";
|
||||
const isInsertedObject =
|
||||
inserted[property] !== null && typeof inserted[property] === "object";
|
||||
|
||||
if (isDeletedObject || isInsertedObject) {
|
||||
type RecordLike = Record<string, V | undefined>;
|
||||
|
||||
const deletedObject: RecordLike = deleted[property] ?? {};
|
||||
@ -222,6 +224,9 @@ export class Delta<T> {
|
||||
Reflect.deleteProperty(deleted, property);
|
||||
Reflect.deleteProperty(inserted, property);
|
||||
}
|
||||
} else if (deleted[property] === inserted[property]) {
|
||||
Reflect.deleteProperty(deleted, property);
|
||||
Reflect.deleteProperty(inserted, property);
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,6 +663,24 @@ export class AppStateDelta implements DeltaContainer<AppState> {
|
||||
}
|
||||
|
||||
break;
|
||||
case "lockedMultiSelections": {
|
||||
const prevLockedUnits = prevAppState[key] || {};
|
||||
const nextLockedUnits = nextAppState[key] || {};
|
||||
|
||||
if (!isShallowEqual(prevLockedUnits, nextLockedUnits)) {
|
||||
visibleDifferenceFlag.value = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "activeLockedId": {
|
||||
const prevHitLockedId = prevAppState[key] || null;
|
||||
const nextHitLockedId = nextAppState[key] || null;
|
||||
|
||||
if (prevHitLockedId !== nextHitLockedId) {
|
||||
visibleDifferenceFlag.value = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertNever(
|
||||
key,
|
||||
@ -753,6 +776,8 @@ export class AppStateDelta implements DeltaContainer<AppState> {
|
||||
editingLinearElementId,
|
||||
selectedLinearElementId,
|
||||
croppingElementId,
|
||||
lockedMultiSelections,
|
||||
activeLockedId,
|
||||
...standaloneProps
|
||||
} = delta as ObservedAppState;
|
||||
|
||||
@ -797,6 +822,18 @@ export class AppStateDelta implements DeltaContainer<AppState> {
|
||||
"selectedGroupIds",
|
||||
(prevValue) => (prevValue ?? false) as ValueOf<T["selectedGroupIds"]>,
|
||||
);
|
||||
Delta.diffObjects(
|
||||
deleted,
|
||||
inserted,
|
||||
"lockedMultiSelections",
|
||||
(prevValue) => (prevValue ?? {}) as ValueOf<T["lockedMultiSelections"]>,
|
||||
);
|
||||
Delta.diffObjects(
|
||||
deleted,
|
||||
inserted,
|
||||
"activeLockedId",
|
||||
(prevValue) => (prevValue ?? null) as ValueOf<T["activeLockedId"]>,
|
||||
);
|
||||
} catch (e) {
|
||||
// if postprocessing fails it does not make sense to bubble up, but let's make sure we know about it
|
||||
console.error(`Couldn't postprocess appstate change deltas.`);
|
||||
|
@ -939,6 +939,8 @@ const getDefaultObservedAppState = (): ObservedAppState => {
|
||||
editingLinearElementId: null,
|
||||
selectedLinearElementId: null,
|
||||
croppingElementId: null,
|
||||
activeLockedId: null,
|
||||
lockedMultiSelections: {},
|
||||
};
|
||||
};
|
||||
|
||||
@ -952,6 +954,8 @@ export const getObservedAppState = (appState: AppState): ObservedAppState => {
|
||||
editingLinearElementId: appState.editingLinearElement?.elementId || null,
|
||||
selectedLinearElementId: appState.selectedLinearElement?.elementId || null,
|
||||
croppingElementId: appState.croppingElementId,
|
||||
activeLockedId: appState.activeLockedId,
|
||||
lockedMultiSelections: appState.lockedMultiSelections,
|
||||
};
|
||||
|
||||
Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
|
||||
|
@ -16,6 +16,8 @@ describe("AppStateDelta", () => {
|
||||
editingGroupId: null,
|
||||
croppingElementId: null,
|
||||
editingLinearElementId: null,
|
||||
lockedMultiSelections: {},
|
||||
activeLockedId: null,
|
||||
};
|
||||
|
||||
const prevAppState1: ObservedAppState = {
|
||||
@ -57,6 +59,8 @@ describe("AppStateDelta", () => {
|
||||
croppingElementId: null,
|
||||
selectedLinearElementId: null,
|
||||
editingLinearElementId: null,
|
||||
activeLockedId: null,
|
||||
lockedMultiSelections: {},
|
||||
};
|
||||
|
||||
const prevAppState1: ObservedAppState = {
|
||||
@ -102,6 +106,8 @@ describe("AppStateDelta", () => {
|
||||
croppingElementId: null,
|
||||
selectedLinearElementId: null,
|
||||
editingLinearElementId: null,
|
||||
activeLockedId: null,
|
||||
lockedMultiSelections: {},
|
||||
};
|
||||
|
||||
const prevAppState1: ObservedAppState = {
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { KEYS, arrayToMap } from "@excalidraw/common";
|
||||
import { KEYS, arrayToMap, randomId } from "@excalidraw/common";
|
||||
|
||||
import { newElementWith } from "@excalidraw/element";
|
||||
|
||||
import { isFrameLikeElement } from "@excalidraw/element";
|
||||
import {
|
||||
elementsAreInSameGroup,
|
||||
newElementWith,
|
||||
selectGroupsFromGivenElements,
|
||||
} from "@excalidraw/element";
|
||||
|
||||
import { CaptureUpdateAction } from "@excalidraw/element";
|
||||
|
||||
@ -14,6 +16,8 @@ import { getSelectedElements } from "../scene";
|
||||
|
||||
import { register } from "./register";
|
||||
|
||||
import type { AppState } from "../types";
|
||||
|
||||
const shouldLock = (elements: readonly ExcalidrawElement[]) =>
|
||||
elements.every((el) => !el.locked);
|
||||
|
||||
@ -24,15 +28,10 @@ export const actionToggleElementLock = register({
|
||||
selectedElementIds: appState.selectedElementIds,
|
||||
includeBoundTextElement: false,
|
||||
});
|
||||
if (selected.length === 1 && !isFrameLikeElement(selected[0])) {
|
||||
return selected[0].locked
|
||||
? "labels.elementLock.unlock"
|
||||
: "labels.elementLock.lock";
|
||||
}
|
||||
|
||||
return shouldLock(selected)
|
||||
? "labels.elementLock.lockAll"
|
||||
: "labels.elementLock.unlockAll";
|
||||
? "labels.elementLock.lock"
|
||||
: "labels.elementLock.unlock";
|
||||
},
|
||||
icon: (appState, elements) => {
|
||||
const selectedElements = getSelectedElements(elements, appState);
|
||||
@ -59,19 +58,84 @@ export const actionToggleElementLock = register({
|
||||
|
||||
const nextLockState = shouldLock(selectedElements);
|
||||
const selectedElementsMap = arrayToMap(selectedElements);
|
||||
return {
|
||||
elements: elements.map((element) => {
|
||||
if (!selectedElementsMap.has(element.id)) {
|
||||
return element;
|
||||
}
|
||||
|
||||
return newElementWith(element, { locked: nextLockState });
|
||||
}),
|
||||
const isAGroup =
|
||||
selectedElements.length > 1 && elementsAreInSameGroup(selectedElements);
|
||||
const isASingleUnit = selectedElements.length === 1 || isAGroup;
|
||||
const newGroupId = isASingleUnit ? null : randomId();
|
||||
|
||||
let nextLockedMultiSelections = { ...appState.lockedMultiSelections };
|
||||
|
||||
if (nextLockState) {
|
||||
nextLockedMultiSelections = {
|
||||
...appState.lockedMultiSelections,
|
||||
...(newGroupId ? { [newGroupId]: true } : {}),
|
||||
};
|
||||
} else if (isAGroup) {
|
||||
const groupId = selectedElements[0].groupIds.at(-1)!;
|
||||
delete nextLockedMultiSelections[groupId];
|
||||
}
|
||||
|
||||
const nextElements = elements.map((element) => {
|
||||
if (!selectedElementsMap.has(element.id)) {
|
||||
return element;
|
||||
}
|
||||
|
||||
let nextGroupIds = element.groupIds;
|
||||
|
||||
// if locking together, add to group
|
||||
// if unlocking, remove the temporary group
|
||||
if (nextLockState) {
|
||||
if (newGroupId) {
|
||||
nextGroupIds = [...nextGroupIds, newGroupId];
|
||||
}
|
||||
} else {
|
||||
nextGroupIds = nextGroupIds.filter(
|
||||
(groupId) => !appState.lockedMultiSelections[groupId],
|
||||
);
|
||||
}
|
||||
|
||||
return newElementWith(element, {
|
||||
locked: nextLockState,
|
||||
// do not recreate the array unncessarily
|
||||
groupIds:
|
||||
nextGroupIds.length !== element.groupIds.length
|
||||
? nextGroupIds
|
||||
: element.groupIds,
|
||||
});
|
||||
});
|
||||
|
||||
const nextElementsMap = arrayToMap(nextElements);
|
||||
const nextSelectedElementIds: AppState["selectedElementIds"] = nextLockState
|
||||
? {}
|
||||
: Object.fromEntries(selectedElements.map((el) => [el.id, true]));
|
||||
const unlockedSelectedElements = selectedElements.map(
|
||||
(el) => nextElementsMap.get(el.id) || el,
|
||||
);
|
||||
const nextSelectedGroupIds = nextLockState
|
||||
? {}
|
||||
: selectGroupsFromGivenElements(unlockedSelectedElements, appState);
|
||||
|
||||
const activeLockedId = nextLockState
|
||||
? newGroupId
|
||||
? newGroupId
|
||||
: isAGroup
|
||||
? selectedElements[0].groupIds.at(-1)!
|
||||
: selectedElements[0].id
|
||||
: null;
|
||||
|
||||
return {
|
||||
elements: nextElements,
|
||||
|
||||
appState: {
|
||||
...appState,
|
||||
selectedElementIds: nextSelectedElementIds,
|
||||
selectedGroupIds: nextSelectedGroupIds,
|
||||
selectedLinearElement: nextLockState
|
||||
? null
|
||||
: appState.selectedLinearElement,
|
||||
lockedMultiSelections: nextLockedMultiSelections,
|
||||
activeLockedId,
|
||||
},
|
||||
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
|
||||
};
|
||||
@ -104,18 +168,44 @@ export const actionUnlockAllElements = register({
|
||||
perform: (elements, appState) => {
|
||||
const lockedElements = elements.filter((el) => el.locked);
|
||||
|
||||
const nextElements = elements.map((element) => {
|
||||
if (element.locked) {
|
||||
// remove the temporary groupId if it exists
|
||||
const nextGroupIds = element.groupIds.filter(
|
||||
(gid) => !appState.lockedMultiSelections[gid],
|
||||
);
|
||||
|
||||
return newElementWith(element, {
|
||||
locked: false,
|
||||
groupIds:
|
||||
// do not recreate the array unncessarily
|
||||
element.groupIds.length !== nextGroupIds.length
|
||||
? nextGroupIds
|
||||
: element.groupIds,
|
||||
});
|
||||
}
|
||||
return element;
|
||||
});
|
||||
|
||||
const nextElementsMap = arrayToMap(nextElements);
|
||||
|
||||
const unlockedElements = lockedElements.map(
|
||||
(el) => nextElementsMap.get(el.id) || el,
|
||||
);
|
||||
|
||||
return {
|
||||
elements: elements.map((element) => {
|
||||
if (element.locked) {
|
||||
return newElementWith(element, { locked: false });
|
||||
}
|
||||
return element;
|
||||
}),
|
||||
elements: nextElements,
|
||||
appState: {
|
||||
...appState,
|
||||
selectedElementIds: Object.fromEntries(
|
||||
lockedElements.map((el) => [el.id, true]),
|
||||
),
|
||||
selectedGroupIds: selectGroupsFromGivenElements(
|
||||
unlockedElements,
|
||||
appState,
|
||||
),
|
||||
lockedMultiSelections: {},
|
||||
activeLockedId: null,
|
||||
},
|
||||
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
|
||||
};
|
||||
|
@ -122,6 +122,8 @@ export const getDefaultAppState = (): Omit<
|
||||
isCropping: false,
|
||||
croppingElementId: null,
|
||||
searchMatches: null,
|
||||
lockedMultiSelections: {},
|
||||
activeLockedId: null,
|
||||
};
|
||||
};
|
||||
|
||||
@ -246,6 +248,8 @@ const APP_STATE_STORAGE_CONF = (<
|
||||
isCropping: { browser: false, export: false, server: false },
|
||||
croppingElementId: { browser: false, export: false, server: false },
|
||||
searchMatches: { browser: false, export: false, server: false },
|
||||
lockedMultiSelections: { browser: true, export: true, server: true },
|
||||
activeLockedId: { browser: false, export: false, server: false },
|
||||
});
|
||||
|
||||
const _clearAppStateForStorage = <
|
||||
|
@ -485,6 +485,8 @@ import { Toast } from "./Toast";
|
||||
|
||||
import { findShapeByKey } from "./shapes";
|
||||
|
||||
import UnlockPopup from "./UnlockPopup";
|
||||
|
||||
import type {
|
||||
RenderInteractiveSceneCallback,
|
||||
ScrollBars,
|
||||
@ -1876,6 +1878,12 @@ class App extends React.Component<AppProps, AppState> {
|
||||
/>
|
||||
)}
|
||||
{this.renderFrameNames()}
|
||||
{this.state.activeLockedId && (
|
||||
<UnlockPopup
|
||||
app={this}
|
||||
activeLockedId={this.state.activeLockedId}
|
||||
/>
|
||||
)}
|
||||
{showShapeSwitchPanel && (
|
||||
<ConvertElementTypePopup app={this} />
|
||||
)}
|
||||
@ -5114,18 +5122,27 @@ class App extends React.Component<AppProps, AppState> {
|
||||
private getElementAtPosition(
|
||||
x: number,
|
||||
y: number,
|
||||
opts?: {
|
||||
opts?: (
|
||||
| {
|
||||
includeBoundTextElement?: boolean;
|
||||
includeLockedElements?: boolean;
|
||||
}
|
||||
| {
|
||||
allHitElements: NonDeleted<ExcalidrawElement>[];
|
||||
}
|
||||
) & {
|
||||
preferSelected?: boolean;
|
||||
includeBoundTextElement?: boolean;
|
||||
includeLockedElements?: boolean;
|
||||
},
|
||||
): NonDeleted<ExcalidrawElement> | null {
|
||||
const allHitElements = this.getElementsAtPosition(
|
||||
x,
|
||||
y,
|
||||
opts?.includeBoundTextElement,
|
||||
opts?.includeLockedElements,
|
||||
);
|
||||
let allHitElements: NonDeleted<ExcalidrawElement>[] = [];
|
||||
if (opts && "allHitElements" in opts) {
|
||||
allHitElements = opts?.allHitElements || [];
|
||||
} else {
|
||||
allHitElements = this.getElementsAtPosition(x, y, {
|
||||
includeBoundTextElement: opts?.includeBoundTextElement,
|
||||
includeLockedElements: opts?.includeLockedElements,
|
||||
});
|
||||
}
|
||||
|
||||
if (allHitElements.length > 1) {
|
||||
if (opts?.preferSelected) {
|
||||
@ -5168,22 +5185,24 @@ class App extends React.Component<AppProps, AppState> {
|
||||
private getElementsAtPosition(
|
||||
x: number,
|
||||
y: number,
|
||||
includeBoundTextElement: boolean = false,
|
||||
includeLockedElements: boolean = false,
|
||||
opts?: {
|
||||
includeBoundTextElement?: boolean;
|
||||
includeLockedElements?: boolean;
|
||||
},
|
||||
): NonDeleted<ExcalidrawElement>[] {
|
||||
const iframeLikes: Ordered<ExcalidrawIframeElement>[] = [];
|
||||
|
||||
const elementsMap = this.scene.getNonDeletedElementsMap();
|
||||
|
||||
const elements = (
|
||||
includeBoundTextElement && includeLockedElements
|
||||
opts?.includeBoundTextElement && opts?.includeLockedElements
|
||||
? this.scene.getNonDeletedElements()
|
||||
: this.scene
|
||||
.getNonDeletedElements()
|
||||
.filter(
|
||||
(element) =>
|
||||
(includeLockedElements || !element.locked) &&
|
||||
(includeBoundTextElement ||
|
||||
(opts?.includeLockedElements || !element.locked) &&
|
||||
(opts?.includeBoundTextElement ||
|
||||
!(isTextElement(element) && element.containerId)),
|
||||
)
|
||||
)
|
||||
@ -5669,14 +5688,21 @@ class App extends React.Component<AppProps, AppState> {
|
||||
|
||||
private getElementLinkAtPosition = (
|
||||
scenePointer: Readonly<{ x: number; y: number }>,
|
||||
hitElement: NonDeletedExcalidrawElement | null,
|
||||
hitElementMightBeLocked: NonDeletedExcalidrawElement | null,
|
||||
): ExcalidrawElement | undefined => {
|
||||
if (hitElementMightBeLocked && hitElementMightBeLocked.locked) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const elements = this.scene.getNonDeletedElements();
|
||||
let hitElementIndex = -1;
|
||||
|
||||
for (let index = elements.length - 1; index >= 0; index--) {
|
||||
const element = elements[index];
|
||||
if (hitElement && element.id === hitElement.id) {
|
||||
if (
|
||||
hitElementMightBeLocked &&
|
||||
element.id === hitElementMightBeLocked.id
|
||||
) {
|
||||
hitElementIndex = index;
|
||||
}
|
||||
if (
|
||||
@ -6158,14 +6184,25 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
}
|
||||
|
||||
const hitElement = this.getElementAtPosition(
|
||||
scenePointer.x,
|
||||
scenePointer.y,
|
||||
const hitElementMightBeLocked = this.getElementAtPosition(
|
||||
scenePointerX,
|
||||
scenePointerY,
|
||||
{
|
||||
preferSelected: true,
|
||||
includeLockedElements: true,
|
||||
},
|
||||
);
|
||||
|
||||
let hitElement: ExcalidrawElement | null = null;
|
||||
if (hitElementMightBeLocked && hitElementMightBeLocked.locked) {
|
||||
hitElement = null;
|
||||
} else {
|
||||
hitElement = hitElementMightBeLocked;
|
||||
}
|
||||
|
||||
this.hitLinkElement = this.getElementLinkAtPosition(
|
||||
scenePointer,
|
||||
hitElement,
|
||||
hitElementMightBeLocked,
|
||||
);
|
||||
if (isEraserActive(this.state)) {
|
||||
return;
|
||||
@ -6258,7 +6295,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
selectGroupsForSelectedElements(
|
||||
{
|
||||
editingGroupId: prevState.editingGroupId,
|
||||
selectedElementIds: { [hitElement.id]: true },
|
||||
selectedElementIds: { [hitElement!.id]: true },
|
||||
},
|
||||
this.scene.getNonDeletedElements(),
|
||||
prevState,
|
||||
@ -6772,6 +6809,9 @@ class App extends React.Component<AppProps, AppState> {
|
||||
const hitElement = this.getElementAtPosition(
|
||||
scenePointer.x,
|
||||
scenePointer.y,
|
||||
{
|
||||
includeLockedElements: true,
|
||||
},
|
||||
);
|
||||
this.hitLinkElement = this.getElementLinkAtPosition(
|
||||
scenePointer,
|
||||
@ -7207,17 +7247,57 @@ class App extends React.Component<AppProps, AppState> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// hitElement may already be set above, so check first
|
||||
pointerDownState.hit.element =
|
||||
pointerDownState.hit.element ??
|
||||
this.getElementAtPosition(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
);
|
||||
|
||||
const allHitElements = this.getElementsAtPosition(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
{
|
||||
includeLockedElements: true,
|
||||
},
|
||||
);
|
||||
const unlockedHitElements = allHitElements.filter((e) => !e.locked);
|
||||
|
||||
// Cannot set preferSelected in getElementAtPosition as we do in pointer move; consider:
|
||||
// A & B: both unlocked, A selected, B on top, A & B overlaps in some way
|
||||
// we want to select B when clicking on the overlapping area
|
||||
const hitElementMightBeLocked = this.getElementAtPosition(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
{
|
||||
allHitElements,
|
||||
},
|
||||
);
|
||||
|
||||
if (
|
||||
!hitElementMightBeLocked ||
|
||||
hitElementMightBeLocked.id !== this.state.activeLockedId
|
||||
) {
|
||||
this.setState({
|
||||
activeLockedId: null,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
hitElementMightBeLocked &&
|
||||
hitElementMightBeLocked.locked &&
|
||||
!unlockedHitElements.some(
|
||||
(el) => this.state.selectedElementIds[el.id],
|
||||
)
|
||||
) {
|
||||
pointerDownState.hit.element = null;
|
||||
} else {
|
||||
// hitElement may already be set above, so check first
|
||||
pointerDownState.hit.element =
|
||||
pointerDownState.hit.element ??
|
||||
this.getElementAtPosition(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
);
|
||||
}
|
||||
|
||||
this.hitLinkElement = this.getElementLinkAtPosition(
|
||||
pointerDownState.origin,
|
||||
pointerDownState.hit.element,
|
||||
hitElementMightBeLocked,
|
||||
);
|
||||
|
||||
if (this.hitLinkElement) {
|
||||
@ -7247,10 +7327,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
|
||||
// For overlapped elements one position may hit
|
||||
// multiple elements
|
||||
pointerDownState.hit.allHitElements = this.getElementsAtPosition(
|
||||
pointerDownState.origin.x,
|
||||
pointerDownState.origin.y,
|
||||
);
|
||||
pointerDownState.hit.allHitElements = unlockedHitElements;
|
||||
|
||||
const hitElement = pointerDownState.hit.element;
|
||||
const someHitElementIsSelected =
|
||||
@ -8066,6 +8143,12 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
const pointerCoords = viewportCoordsToSceneCoords(event, this.state);
|
||||
|
||||
if (this.state.activeLockedId) {
|
||||
this.setState({
|
||||
activeLockedId: null,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.state.selectedLinearElement &&
|
||||
this.state.selectedLinearElement.elbowed &&
|
||||
@ -8947,6 +9030,49 @@ class App extends React.Component<AppProps, AppState> {
|
||||
|
||||
this.savePointer(childEvent.clientX, childEvent.clientY, "up");
|
||||
|
||||
// if current elements are still selected
|
||||
// and the pointer is just over a locked element
|
||||
// do not allow activeLockedId to be set
|
||||
|
||||
const hitElements = pointerDownState.hit.allHitElements;
|
||||
|
||||
if (
|
||||
this.state.activeTool.type === "selection" &&
|
||||
!pointerDownState.boxSelection.hasOccurred &&
|
||||
!pointerDownState.resize.isResizing &&
|
||||
!hitElements.some((el) => this.state.selectedElementIds[el.id])
|
||||
) {
|
||||
const sceneCoords = viewportCoordsToSceneCoords(
|
||||
{ clientX: childEvent.clientX, clientY: childEvent.clientY },
|
||||
this.state,
|
||||
);
|
||||
const hitLockedElement = this.getElementAtPosition(
|
||||
sceneCoords.x,
|
||||
sceneCoords.y,
|
||||
{
|
||||
includeLockedElements: true,
|
||||
},
|
||||
);
|
||||
|
||||
this.store.scheduleCapture();
|
||||
if (hitLockedElement?.locked) {
|
||||
this.setState({
|
||||
activeLockedId:
|
||||
hitLockedElement.groupIds.length > 0
|
||||
? hitLockedElement.groupIds.at(-1) || ""
|
||||
: hitLockedElement.id,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
activeLockedId: null,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
activeLockedId: null,
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedElementsAreBeingDragged: false,
|
||||
});
|
||||
|
40
packages/excalidraw/components/UnlockPopup.scss
Normal file
40
packages/excalidraw/components/UnlockPopup.scss
Normal file
@ -0,0 +1,40 @@
|
||||
@import "../css/variables.module.scss";
|
||||
|
||||
.excalidraw {
|
||||
.UnlockPopup {
|
||||
position: absolute;
|
||||
z-index: var(--zIndex-interactiveCanvas);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
background: var(--island-bg-color);
|
||||
box-shadow: var(--shadow-island);
|
||||
padding: 0.8rem;
|
||||
cursor: pointer;
|
||||
color: var(--color-gray-60);
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
color: var(--color-gray-60);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
svg {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
75
packages/excalidraw/components/UnlockPopup.tsx
Normal file
75
packages/excalidraw/components/UnlockPopup.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import {
|
||||
getCommonBounds,
|
||||
getElementsInGroup,
|
||||
selectGroupsFromGivenElements,
|
||||
} from "@excalidraw/element";
|
||||
import { sceneCoordsToViewportCoords } from "@excalidraw/common";
|
||||
|
||||
import { flushSync } from "react-dom";
|
||||
|
||||
import { actionToggleElementLock } from "../actions";
|
||||
import { t } from "../i18n";
|
||||
|
||||
import "./UnlockPopup.scss";
|
||||
|
||||
import { LockedIconFilled } from "./icons";
|
||||
|
||||
import type App from "./App";
|
||||
|
||||
import type { AppState } from "../types";
|
||||
|
||||
const UnlockPopup = ({
|
||||
app,
|
||||
activeLockedId,
|
||||
}: {
|
||||
app: App;
|
||||
activeLockedId: NonNullable<AppState["activeLockedId"]>;
|
||||
}) => {
|
||||
const element = app.scene.getElement(activeLockedId);
|
||||
|
||||
const elements = element
|
||||
? [element]
|
||||
: getElementsInGroup(app.scene.getNonDeletedElementsMap(), activeLockedId);
|
||||
|
||||
if (elements.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [x, y] = getCommonBounds(elements);
|
||||
const { x: viewX, y: viewY } = sceneCoordsToViewportCoords(
|
||||
{ sceneX: x, sceneY: y },
|
||||
app.state,
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="UnlockPopup"
|
||||
style={{
|
||||
bottom: `${app.state.height + 12 - viewY + app.state.offsetTop}px`,
|
||||
left: `${viewX - app.state.offsetLeft}px`,
|
||||
}}
|
||||
onClick={() => {
|
||||
flushSync(() => {
|
||||
const groupIds = selectGroupsFromGivenElements(elements, app.state);
|
||||
app.setState({
|
||||
selectedElementIds: elements.reduce(
|
||||
(acc, element) => ({
|
||||
...acc,
|
||||
[element.id]: true,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
selectedGroupIds: groupIds,
|
||||
activeLockedId: null,
|
||||
});
|
||||
});
|
||||
app.actionManager.executeAction(actionToggleElementLock);
|
||||
}}
|
||||
title={t("labels.elementLock.unlock")}
|
||||
>
|
||||
{LockedIconFilled}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UnlockPopup;
|
@ -215,6 +215,7 @@ const getRelevantAppStateProps = (
|
||||
isCropping: appState.isCropping,
|
||||
croppingElementId: appState.croppingElementId,
|
||||
searchMatches: appState.searchMatches,
|
||||
activeLockedId: appState.activeLockedId,
|
||||
});
|
||||
|
||||
const areEqual = (
|
||||
|
@ -178,6 +178,16 @@ export const LockedIcon = createIcon(
|
||||
modifiedTablerIconProps,
|
||||
);
|
||||
|
||||
export const LockedIconFilled = createIcon(
|
||||
<g fill="currentColor">
|
||||
<path d="M12 2a5 5 0 0 1 5 5v3a3 3 0 0 1 3 3v6a3 3 0 0 1 -3 3h-10a3 3 0 0 1 -3 -3v-6a3 3 0 0 1 3 -3v-3a5 5 0 0 1 5 -5m0 12a2 2 0 0 0 -1.995 1.85l-.005 .15a2 2 0 1 0 2 -2m0 -10a3 3 0 0 0 -3 3v3h6v-3a3 3 0 0 0 -3 -3" />
|
||||
</g>,
|
||||
{
|
||||
width: 24,
|
||||
height: 24,
|
||||
},
|
||||
);
|
||||
|
||||
// custom
|
||||
export const WelcomeScreenMenuArrow = createIcon(
|
||||
<>
|
||||
|
@ -37,9 +37,10 @@ export const getLassoSelectedElementIds = (input: {
|
||||
if (simplifyDistance) {
|
||||
path = simplify(lassoPath, simplifyDistance) as GlobalPoint[];
|
||||
}
|
||||
const unlockedElements = elements.filter((el) => !el.locked);
|
||||
// as the path might not enclose a shape anymore, clear before checking
|
||||
enclosedElements.clear();
|
||||
for (const element of elements) {
|
||||
for (const element of unlockedElements) {
|
||||
if (
|
||||
!intersectedElements.has(element.id) &&
|
||||
!enclosedElements.has(element.id)
|
||||
|
@ -377,7 +377,9 @@ const renderElementsBoxHighlight = (
|
||||
context: CanvasRenderingContext2D,
|
||||
appState: InteractiveCanvasAppState,
|
||||
elements: NonDeleted<ExcalidrawElement>[],
|
||||
config?: { colors?: string[]; dashed?: boolean },
|
||||
) => {
|
||||
const { colors = ["rgb(0,118,255)"], dashed = false } = config || {};
|
||||
const individualElements = elements.filter(
|
||||
(element) => element.groupIds.length === 0,
|
||||
);
|
||||
@ -394,8 +396,8 @@ const renderElementsBoxHighlight = (
|
||||
x2,
|
||||
y1,
|
||||
y2,
|
||||
selectionColors: ["rgb(0,118,255)"],
|
||||
dashed: false,
|
||||
selectionColors: colors,
|
||||
dashed,
|
||||
cx: x1 + (x2 - x1) / 2,
|
||||
cy: y1 + (y2 - y1) / 2,
|
||||
activeEmbeddable: false,
|
||||
@ -787,6 +789,17 @@ const _renderInteractiveScene = ({
|
||||
renderElementsBoxHighlight(context, appState, appState.elementsToHighlight);
|
||||
}
|
||||
|
||||
if (appState.activeLockedId) {
|
||||
const element = allElementsMap.get(appState.activeLockedId);
|
||||
const elements = element
|
||||
? [element]
|
||||
: getElementsInGroup(allElementsMap, appState.activeLockedId);
|
||||
renderElementsBoxHighlight(context, appState, elements, {
|
||||
colors: ["#ced4da"],
|
||||
dashed: true,
|
||||
});
|
||||
}
|
||||
|
||||
const isFrameSelected = selectedElements.some((element) =>
|
||||
isFrameLikeElement(element),
|
||||
);
|
||||
@ -901,8 +914,8 @@ const _renderInteractiveScene = ({
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
selectionColors,
|
||||
dashed: !!remoteClients,
|
||||
selectionColors: element.locked ? ["#ced4da"] : selectionColors,
|
||||
dashed: !!remoteClients || element.locked,
|
||||
cx,
|
||||
cy,
|
||||
activeEmbeddable:
|
||||
@ -926,7 +939,9 @@ const _renderInteractiveScene = ({
|
||||
x2,
|
||||
y1,
|
||||
y2,
|
||||
selectionColors: [oc.black],
|
||||
selectionColors: groupElements.some((el) => el.locked)
|
||||
? ["#ced4da"]
|
||||
: [oc.black],
|
||||
dashed: true,
|
||||
cx: x1 + (x2 - x1) / 2,
|
||||
cy: y1 + (y2 - y1) / 2,
|
||||
@ -990,7 +1005,11 @@ const _renderInteractiveScene = ({
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (selectedElements.length > 1 && !appState.isRotating) {
|
||||
} else if (
|
||||
selectedElements.length > 1 &&
|
||||
!appState.isRotating &&
|
||||
!selectedElements.some((el) => el.locked)
|
||||
) {
|
||||
const dashedLinePadding =
|
||||
(DEFAULT_TRANSFORM_HANDLE_SPACING * 2) / appState.zoom.value;
|
||||
context.fillStyle = oc.white;
|
||||
|
@ -3,6 +3,7 @@
|
||||
exports[`contextMenu element > right-clicking on a group should select whole group > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -935,6 +936,7 @@ exports[`contextMenu element > right-clicking on a group should select whole gro
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1078,6 +1080,7 @@ exports[`contextMenu element > right-clicking on a group should select whole gro
|
||||
exports[`contextMenu element > selecting 'Add to library' in context menu adds element to library > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1136,6 +1139,7 @@ exports[`contextMenu element > selecting 'Add to library' in context menu adds e
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1292,6 +1296,7 @@ exports[`contextMenu element > selecting 'Add to library' in context menu adds e
|
||||
exports[`contextMenu element > selecting 'Bring forward' in context menu brings element forward > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1350,6 +1355,7 @@ exports[`contextMenu element > selecting 'Bring forward' in context menu brings
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1623,6 +1629,7 @@ exports[`contextMenu element > selecting 'Bring forward' in context menu brings
|
||||
exports[`contextMenu element > selecting 'Bring to front' in context menu brings element to front > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1681,6 +1688,7 @@ exports[`contextMenu element > selecting 'Bring to front' in context menu brings
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1954,6 +1962,7 @@ exports[`contextMenu element > selecting 'Bring to front' in context menu brings
|
||||
exports[`contextMenu element > selecting 'Copy styles' in context menu copies styles > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2012,6 +2021,7 @@ exports[`contextMenu element > selecting 'Copy styles' in context menu copies st
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2168,6 +2178,7 @@ exports[`contextMenu element > selecting 'Copy styles' in context menu copies st
|
||||
exports[`contextMenu element > selecting 'Delete' in context menu deletes element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2226,6 +2237,7 @@ exports[`contextMenu element > selecting 'Delete' in context menu deletes elemen
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2407,6 +2419,7 @@ exports[`contextMenu element > selecting 'Delete' in context menu deletes elemen
|
||||
exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2465,6 +2478,7 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2707,6 +2721,7 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates
|
||||
exports[`contextMenu element > selecting 'Group selection' in context menu groups selected elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2765,6 +2780,7 @@ exports[`contextMenu element > selecting 'Group selection' in context menu group
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3077,6 +3093,7 @@ exports[`contextMenu element > selecting 'Group selection' in context menu group
|
||||
exports[`contextMenu element > selecting 'Paste styles' in context menu pastes styles > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3135,6 +3152,7 @@ exports[`contextMenu element > selecting 'Paste styles' in context menu pastes s
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3558,6 +3576,7 @@ exports[`contextMenu element > selecting 'Paste styles' in context menu pastes s
|
||||
exports[`contextMenu element > selecting 'Send backward' in context menu sends element backward > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3616,6 +3635,7 @@ exports[`contextMenu element > selecting 'Send backward' in context menu sends e
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3881,6 +3901,7 @@ exports[`contextMenu element > selecting 'Send backward' in context menu sends e
|
||||
exports[`contextMenu element > selecting 'Send to back' in context menu sends element to back > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3939,6 +3960,7 @@ exports[`contextMenu element > selecting 'Send to back' in context menu sends el
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -4204,6 +4226,7 @@ exports[`contextMenu element > selecting 'Send to back' in context menu sends el
|
||||
exports[`contextMenu element > selecting 'Ungroup selection' in context menu ungroups selected group > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4262,6 +4285,7 @@ exports[`contextMenu element > selecting 'Ungroup selection' in context menu ung
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -4609,6 +4633,7 @@ exports[`contextMenu element > selecting 'Ungroup selection' in context menu ung
|
||||
exports[`contextMenu element > shows 'Group selection' in context menu for multiple selected elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5541,6 +5566,7 @@ exports[`contextMenu element > shows 'Group selection' in context menu for multi
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -5828,6 +5854,7 @@ exports[`contextMenu element > shows 'Group selection' in context menu for multi
|
||||
exports[`contextMenu element > shows 'Ungroup selection' in context menu for group inside selected elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -6760,6 +6787,7 @@ exports[`contextMenu element > shows 'Ungroup selection' in context menu for gro
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -7094,6 +7122,7 @@ exports[`contextMenu element > shows 'Ungroup selection' in context menu for gro
|
||||
exports[`contextMenu element > shows context menu for canvas > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7693,6 +7722,7 @@ exports[`contextMenu element > shows context menu for canvas > [end of test] app
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -7759,6 +7789,7 @@ exports[`contextMenu element > shows context menu for canvas > [end of test] und
|
||||
exports[`contextMenu element > shows context menu for element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8691,6 +8722,7 @@ exports[`contextMenu element > shows context menu for element > [end of test] ap
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -8748,6 +8780,7 @@ exports[`contextMenu element > shows context menu for element > [end of test] ap
|
||||
exports[`contextMenu element > shows context menu for element > [end of test] appState 2`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9680,6 +9713,7 @@ exports[`contextMenu element > shows context menu for element > [end of test] ap
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`export > export svg-embedded scene > svg-embdedded scene export output 1`] = `
|
||||
"<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" width="36" height="36"><!-- svg-source:excalidraw --><metadata><!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nHVTTU/jMFx1MDAxML33V0TmulrSXCL20Fx1MDAxYrtcdTAwMGKCw+5hi8RcdTAwMDFxMPE0XHUwMDE51bUte0JbUCV+xt72L/JcdTAwMTNcdTAwMTi7JW5SNpFcIvnN15vnl5dRUVxi2jhcdTAwMTDTQsC6klx1MDAxYZWXK/El4k/gXHUwMDAzWsOhSTpcdTAwMDfb+iplNkRuenqqLVx1MDAxNzQ20PSsLMtdXHUwMDExaFiCocBp93wuipf05Vxiqlh6kdJcdTAwMTLwMZdgTVx1MDAxOV0zVHanTe+0QkVcciPjb1x1MDAxZNRcdTAwMDDWXHL1MWlqXHK9wkDeLuCH1dbHiSdjiG9cdTAwMWX6KKtF7W1rVJdDXprgpOdlct5cdTAwMWO1ntEmdWc9WC0xmHG3pzhcdTAwMTng/6vioXVjIETBxlx1MDAxZGqdrJDi8uMyb1x1MDAxMVx1MDAxObpcdTAwMWKVtH3InLxcXMJNXHUwMDE017RadzBcdTAwMWFcdTAwMDXrIZhW3E/7uJh8XHUwMDEzZ3tkm7lcdTAwMDOoXHUwMDFlseyJI+y3NVVfdVxmP9lcdTAwMGWUWsylXHUwMDBlkPWOPC6zVXokW6ckXHLmajSLYVx1MDAxZdtv8UnvZCdcdTAwMTb67d/f14Obs4Zm+Fx1MDAxY1x0TspcdTAwMWV6JZeoo9TnvVx1MDAxNlx1MDAxN1x1MDAxYeu4p9AwP3BcdTAwMDAvS8i278JkXY5W3E+iXHUwMDAxf3xcdTAwMWbWY41G6ttP6cmW7Fx1MDAxZlxiO4LkWzjcXHUwMDFjrjuTf52cp8CWv8lcdTAwMDJCOjcj1qu7UbZcdKrBqjuMwOU1XHUwMDEz9MsquDTyUVx1MDAwZnVcdTAwMTRPXGKr78d/xck8PWK0d0n8IyC5aTvavlx1MDAwM9lcdTAwMDIhXHUwMDFjIn0=<!-- payload-end --></metadata><defs><style class="style-fonts">
|
||||
"<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" width="36" height="36"><!-- svg-source:excalidraw --><metadata><!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nHVTTW/TQFx1MDAxML3zKyz3iqiTqlx1MDAxY3IrUERcdTAwMGblQJA4IFx1MDAwZVvvxFx1MDAxZWWyu9pcdTAwMWQ3XHRVJH5cdTAwMDY3/lwiP4HZjeuNnWJLlvbtfLx58/z0qihK3jsoXHUwMDE3RVx0u1pcdTAwMTFqr7bl64g/glx1MDAwZmiNXFzN0znYztcpsmV2i8tLspLQ2sCLq6qqjklAsFx1MDAwMcNBwr7LuSie0lduUMfUm1x1MDAxNJaA575cZjvO6E6gajjtR6ctam5cdTAwMDWZvVx1MDAxZKBcdTAwMTawaXmMKdNcdTAwMTCMXHUwMDEyXHUwMDAze7uG95asj1x1MDAxZC9mXHUwMDEw39z0QdXrxtvO6CGGvTLBKS/D5LhcdTAwMTVcdTAwMTIteZ+qi1x1MDAxZaJWOenxrac4n+D/y5KmTWsgRMFmXHUwMDAzap2qkePwsypPXHUwMDExXHUwMDE5ujudtP2ROXm1gbsorumIXHUwMDA2XHUwMDE4jYbdXHUwMDE0TCP23Z5cdTAwMTeTN3HVI4fMXHUwMDFkQI+IZU+cYZ+tqceqY/ggduBUYqUoQNY78rjNVlx1MDAxOZHsnFY86Uto1tM4sd/6hdrJTlwi9N8/v3+dbM5cdTAwMWFe4s9IcF6N0I9qg1x1MDAxNKW+XHUwMDFllbghbOKcJcHqxFx1MDAwMTIso9h+uGbr8m0t9Vx1MDAxNFx1MDAxYfDn+7BcdTAwMWVcdTAwMWI0ir6+SE91bL9AOFx1MDAxMmTfwenk8Gkw+Zv5dbo4yDdZoFTOLVn0XHUwMDFhNio2QT1cdTAwMTn1iDG4PGaC7q2GW6NcdTAwMWVoqmP5iLB9d/5XXFys0tNcdTAwMTPvV3DfXHUwMDEx41JWXbP4IHkr8ks2ir9cZvTQ4Vx1MDAxZvRzK/4ifQ==<!-- payload-end --></metadata><defs><style class="style-fonts">
|
||||
</style></defs><rect x="0" y="0" width="36" height="36" fill="#ffffff"></rect><g transform="translate(10 10) rotate(0 8 8)" data-id="A"><text x="0" y="17.619999999999997" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">😀</text></g></svg>"
|
||||
`;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and the arrow got bound to a different element in the meantime > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -61,6 +62,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -592,6 +594,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind bindings when both are updated through the history and there are no conflicting updates in the meantime > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -650,6 +653,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -1099,6 +1103,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added arrow when it's bindable elements are added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1157,6 +1162,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -1465,6 +1471,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should rebind remotely added bindable elements when it's arrow is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1523,6 +1530,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -1832,6 +1840,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should unbind remotely deleted bindable elements from arrow when the arrow is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1890,6 +1899,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -2097,6 +2107,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
exports[`history > multiplayer undo/redo > conflicts in arrows and their bindable elements > should update bound element points when rectangle was remotely moved and arrow is added back through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2155,6 +2166,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -2532,6 +2544,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the container is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2590,6 +2603,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -2829,6 +2843,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should preserve latest remotely added binding and unbind previous one when the text is added through history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2887,6 +2902,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -3111,6 +3127,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the container got bound to a different text in the meantime > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3169,6 +3186,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -3403,6 +3421,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and the text got bound to a different container in the meantime > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3461,6 +3480,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -3687,6 +3707,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind bindings when both are updated through the history and there no conflicting updates in the meantime > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3745,6 +3766,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -3920,6 +3942,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added bound text when it's container is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3978,6 +4001,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -4177,6 +4201,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should rebind remotely added container when it's bound text is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4235,6 +4260,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -4448,6 +4474,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw bound text to match container dimensions when the bound text is updated through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4506,6 +4533,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -4677,6 +4705,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should redraw remotely added bound text when it's container is updated through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4735,6 +4764,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -4906,6 +4936,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted bound text from container when the container is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4964,6 +4995,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -5133,6 +5165,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in bound text elements and their containers > should unbind remotely deleted container from bound text when the text is added through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5191,6 +5224,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -5360,6 +5394,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and
|
||||
exports[`history > multiplayer undo/redo > conflicts in frames and their children > should not rebind frame child with frame when frame was remotely deleted and frame child is added back through the history > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5418,6 +5453,7 @@ exports[`history > multiplayer undo/redo > conflicts in frames and their childre
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -5618,6 +5654,7 @@ exports[`history > multiplayer undo/redo > conflicts in frames and their childre
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when editing group contains only remotely deleted elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5676,6 +5713,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -5949,6 +5987,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when element changes relate only to remotely deleted elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -6007,6 +6046,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -6376,6 +6416,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when selected elements relate only to remotely deleted elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -6434,6 +6475,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -6754,6 +6796,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when selected groups contain only remotely deleted elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -6812,6 +6855,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -7072,6 +7116,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when selected or editing linear element was remotely deleted > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7130,6 +7175,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -7371,6 +7417,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when when element change relates to remotely deleted element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7429,6 +7476,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -7599,6 +7647,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced all indices > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7657,6 +7706,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -7953,6 +8003,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should iterate through the history when z-index changes do not produce visible change and we synced changed indices > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8011,6 +8062,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -8307,6 +8359,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh
|
||||
exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress dragging > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8365,6 +8418,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -8713,6 +8767,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte
|
||||
exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress freedraw > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8771,6 +8826,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -8998,6 +9054,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte
|
||||
exports[`history > multiplayer undo/redo > should not let remote changes to interfere with in progress resizing > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9056,6 +9113,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -9262,6 +9320,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte
|
||||
exports[`history > multiplayer undo/redo > should not override remote changes on different elements > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9320,6 +9379,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -9527,6 +9587,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on
|
||||
exports[`history > multiplayer undo/redo > should not override remote changes on different properties > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9585,6 +9646,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -9757,6 +9819,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on
|
||||
exports[`history > multiplayer undo/redo > should override remotely added groups on undo, but restore them on redo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9815,6 +9878,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -10056,6 +10120,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups
|
||||
exports[`history > multiplayer undo/redo > should override remotely added points on undo, but restore them on redo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -10114,6 +10179,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -10396,6 +10462,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points
|
||||
exports[`history > multiplayer undo/redo > should redistribute deltas when element gets removed locally but is restored remotely > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -10454,6 +10521,7 @@ exports[`history > multiplayer undo/redo > should redistribute deltas when eleme
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -10630,6 +10698,7 @@ exports[`history > multiplayer undo/redo > should redistribute deltas when eleme
|
||||
exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -10688,6 +10757,7 @@ exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end o
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -11078,6 +11148,7 @@ exports[`history > multiplayer undo/redo > should redraw arrows on undo > [end o
|
||||
exports[`history > multiplayer undo/redo > should update history entries after remote changes on the same properties > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11136,6 +11207,7 @@ exports[`history > multiplayer undo/redo > should update history entries after r
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -11334,6 +11406,7 @@ exports[`history > multiplayer undo/redo > should update history entries after r
|
||||
exports[`history > singleplayer undo/redo > remounting undo/redo buttons should initialize undo/redo state correctly > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11392,6 +11465,7 @@ exports[`history > singleplayer undo/redo > remounting undo/redo buttons should
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -11571,6 +11645,7 @@ exports[`history > singleplayer undo/redo > remounting undo/redo buttons should
|
||||
exports[`history > singleplayer undo/redo > should clear the redo stack on elements change > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11629,6 +11704,7 @@ exports[`history > singleplayer undo/redo > should clear the redo stack on eleme
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -11810,6 +11886,7 @@ exports[`history > singleplayer undo/redo > should clear the redo stack on eleme
|
||||
exports[`history > singleplayer undo/redo > should create entry when selecting freedraw > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11868,6 +11945,7 @@ exports[`history > singleplayer undo/redo > should create entry when selecting f
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -12211,6 +12289,7 @@ exports[`history > singleplayer undo/redo > should create entry when selecting f
|
||||
exports[`history > singleplayer undo/redo > should create new history entry on scene import via drag&drop > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12269,6 +12348,7 @@ exports[`history > singleplayer undo/redo > should create new history entry on s
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -12456,6 +12536,7 @@ exports[`history > singleplayer undo/redo > should create new history entry on s
|
||||
exports[`history > singleplayer undo/redo > should disable undo/redo buttons when stacks empty > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12514,6 +12595,7 @@ exports[`history > singleplayer undo/redo > should disable undo/redo buttons whe
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -12695,6 +12777,7 @@ exports[`history > singleplayer undo/redo > should disable undo/redo buttons whe
|
||||
exports[`history > singleplayer undo/redo > should end up with no history entry after initializing scene > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12753,6 +12836,7 @@ exports[`history > singleplayer undo/redo > should end up with no history entry
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -12934,6 +13018,7 @@ exports[`history > singleplayer undo/redo > should end up with no history entry
|
||||
exports[`history > singleplayer undo/redo > should iterate through the history when selection changes do not produce visible change > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12992,6 +13077,7 @@ exports[`history > singleplayer undo/redo > should iterate through the history w
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -13181,6 +13267,7 @@ exports[`history > singleplayer undo/redo > should iterate through the history w
|
||||
exports[`history > singleplayer undo/redo > should not clear the redo stack on standalone appstate change > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -13239,6 +13326,7 @@ exports[`history > singleplayer undo/redo > should not clear the redo stack on s
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -13514,6 +13602,7 @@ exports[`history > singleplayer undo/redo > should not clear the redo stack on s
|
||||
exports[`history > singleplayer undo/redo > should not collapse when applying corrupted history entry > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -13572,6 +13661,7 @@ exports[`history > singleplayer undo/redo > should not collapse when applying co
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -13684,6 +13774,7 @@ exports[`history > singleplayer undo/redo > should not collapse when applying co
|
||||
exports[`history > singleplayer undo/redo > should not end up with history entry when there are no appstate changes > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -13742,6 +13833,7 @@ exports[`history > singleplayer undo/redo > should not end up with history entry
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -13970,6 +14062,7 @@ exports[`history > singleplayer undo/redo > should not end up with history entry
|
||||
exports[`history > singleplayer undo/redo > should not end up with history entry when there are no elements changes > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14028,6 +14121,7 @@ exports[`history > singleplayer undo/redo > should not end up with history entry
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -14235,6 +14329,7 @@ exports[`history > singleplayer undo/redo > should not end up with history entry
|
||||
exports[`history > singleplayer undo/redo > should not override appstate changes when redo stack is not cleared > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14293,6 +14388,7 @@ exports[`history > singleplayer undo/redo > should not override appstate changes
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -14513,6 +14609,7 @@ exports[`history > singleplayer undo/redo > should not override appstate changes
|
||||
exports[`history > singleplayer undo/redo > should support appstate name or viewBackgroundColor change > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14571,6 +14668,7 @@ exports[`history > singleplayer undo/redo > should support appstate name or view
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -14673,6 +14771,7 @@ exports[`history > singleplayer undo/redo > should support appstate name or view
|
||||
exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14731,6 +14830,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -15372,6 +15472,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -15430,6 +15531,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -15990,6 +16092,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -16048,6 +16151,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -16608,6 +16712,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -16666,6 +16771,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -17321,6 +17427,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -17379,6 +17486,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -18072,6 +18180,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding
|
||||
exports[`history > singleplayer undo/redo > should support changes in elements' order > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -18130,6 +18239,7 @@ exports[`history > singleplayer undo/redo > should support changes in elements'
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -18550,6 +18660,7 @@ exports[`history > singleplayer undo/redo > should support changes in elements'
|
||||
exports[`history > singleplayer undo/redo > should support duplication of groups, appstate group selection and editing group > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -18608,6 +18719,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -19071,6 +19183,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups
|
||||
exports[`history > singleplayer undo/redo > should support element creation, deletion and appstate element selection change > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -19129,6 +19242,7 @@ exports[`history > singleplayer undo/redo > should support element creation, del
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
@ -19530,6 +19644,7 @@ exports[`history > singleplayer undo/redo > should support element creation, del
|
||||
exports[`history > singleplayer undo/redo > should support linear element creation and points manipulation through the editor > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -19588,6 +19703,7 @@ exports[`history > singleplayer undo/redo > should support linear element creati
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"newElement": null,
|
||||
"objectsSnapModeEnabled": false,
|
||||
|
@ -3,6 +3,7 @@
|
||||
exports[`given element A and group of elements B and given both are selected when user clicks on B, on pointer up only elements from B should be selected > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -61,6 +62,7 @@ exports[`given element A and group of elements B and given both are selected whe
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -423,6 +425,7 @@ exports[`given element A and group of elements B and given both are selected whe
|
||||
exports[`given element A and group of elements B and given both are selected when user shift-clicks on B, on pointer up only element A should be selected > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -481,6 +484,7 @@ exports[`given element A and group of elements B and given both are selected whe
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -833,6 +837,7 @@ exports[`given element A and group of elements B and given both are selected whe
|
||||
exports[`regression tests > Cmd/Ctrl-click exclusively select element under pointer > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -891,6 +896,7 @@ exports[`regression tests > Cmd/Ctrl-click exclusively select element under poin
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1387,6 +1393,7 @@ exports[`regression tests > Cmd/Ctrl-click exclusively select element under poin
|
||||
exports[`regression tests > Drags selected element when hitting only bounding box and keeps element selected > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1445,6 +1452,7 @@ exports[`regression tests > Drags selected element when hitting only bounding bo
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1590,6 +1598,7 @@ exports[`regression tests > Drags selected element when hitting only bounding bo
|
||||
exports[`regression tests > adjusts z order when grouping > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -1648,6 +1657,7 @@ exports[`regression tests > adjusts z order when grouping > [end of test] appSta
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -1968,6 +1978,7 @@ exports[`regression tests > adjusts z order when grouping > [end of test] undo s
|
||||
exports[`regression tests > alt-drag duplicates an element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2026,6 +2037,7 @@ exports[`regression tests > alt-drag duplicates an element > [end of test] appSt
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2202,6 +2214,7 @@ exports[`regression tests > alt-drag duplicates an element > [end of test] undo
|
||||
exports[`regression tests > arrow keys > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2260,6 +2273,7 @@ exports[`regression tests > arrow keys > [end of test] appState 1`] = `
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2380,6 +2394,7 @@ exports[`regression tests > arrow keys > [end of test] undo stack 1`] = `
|
||||
exports[`regression tests > can drag element that covers another element, while another elem is selected > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2438,6 +2453,7 @@ exports[`regression tests > can drag element that covers another element, while
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2701,6 +2717,7 @@ exports[`regression tests > can drag element that covers another element, while
|
||||
exports[`regression tests > change the properties of a shape > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -2759,6 +2776,7 @@ exports[`regression tests > change the properties of a shape > [end of test] app
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -2948,6 +2966,7 @@ exports[`regression tests > change the properties of a shape > [end of test] und
|
||||
exports[`regression tests > click on an element and drag it > [dragged] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3006,6 +3025,7 @@ exports[`regression tests > click on an element and drag it > [dragged] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3187,6 +3207,7 @@ exports[`regression tests > click on an element and drag it > [dragged] undo sta
|
||||
exports[`regression tests > click on an element and drag it > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3245,6 +3266,7 @@ exports[`regression tests > click on an element and drag it > [end of test] appS
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3417,6 +3439,7 @@ exports[`regression tests > click on an element and drag it > [end of test] undo
|
||||
exports[`regression tests > click to select a shape > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3475,6 +3498,7 @@ exports[`regression tests > click to select a shape > [end of test] appState 1`]
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3673,6 +3697,7 @@ exports[`regression tests > click to select a shape > [end of test] undo stack 1
|
||||
exports[`regression tests > click-drag to select a group > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -3731,6 +3756,7 @@ exports[`regression tests > click-drag to select a group > [end of test] appStat
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -3985,6 +4011,7 @@ exports[`regression tests > click-drag to select a group > [end of test] undo st
|
||||
exports[`regression tests > deleting last but one element in editing group should unselect the group > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4043,6 +4070,7 @@ exports[`regression tests > deleting last but one element in editing group shoul
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -4413,6 +4441,7 @@ exports[`regression tests > deleting last but one element in editing group shoul
|
||||
exports[`regression tests > deselects group of selected elements on pointer down when pointer doesn't hit any element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4471,6 +4500,7 @@ exports[`regression tests > deselects group of selected elements on pointer down
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -4696,6 +4726,7 @@ exports[`regression tests > deselects group of selected elements on pointer down
|
||||
exports[`regression tests > deselects group of selected elements on pointer up when pointer hits common bounding box without hitting any element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -4754,6 +4785,7 @@ exports[`regression tests > deselects group of selected elements on pointer up w
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -4943,12 +4975,34 @@ exports[`regression tests > deselects group of selected elements on pointer up w
|
||||
},
|
||||
"id": "id8",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
"delta": Delta {
|
||||
"deleted": {
|
||||
"selectedElementIds": {},
|
||||
},
|
||||
"inserted": {
|
||||
"selectedElementIds": {
|
||||
"id0": true,
|
||||
"id3": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"elements": {
|
||||
"added": {},
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id11",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`regression tests > deselects selected element on pointer down when pointer doesn't hit any element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5007,6 +5061,7 @@ exports[`regression tests > deselects selected element on pointer down when poin
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -5157,6 +5212,7 @@ exports[`regression tests > deselects selected element on pointer down when poin
|
||||
exports[`regression tests > deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5215,6 +5271,7 @@ exports[`regression tests > deselects selected element, on pointer up, when clic
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -5355,6 +5412,7 @@ exports[`regression tests > deselects selected element, on pointer up, when clic
|
||||
exports[`regression tests > double click to edit a group > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5413,6 +5471,7 @@ exports[`regression tests > double click to edit a group > [end of test] appStat
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -5740,6 +5799,7 @@ exports[`regression tests > double click to edit a group > [end of test] undo st
|
||||
exports[`regression tests > drags selected elements from point inside common bounding box that doesn't hit any element and keeps elements selected after dragging > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -5798,6 +5858,7 @@ exports[`regression tests > drags selected elements from point inside common bou
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -6031,6 +6092,7 @@ exports[`regression tests > drags selected elements from point inside common bou
|
||||
exports[`regression tests > draw every type of shape > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -6089,6 +6151,7 @@ exports[`regression tests > draw every type of shape > [end of test] appState 1`
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -6849,6 +6912,7 @@ exports[`regression tests > draw every type of shape > [end of test] undo stack
|
||||
exports[`regression tests > given a group of selected elements with an element that is not selected inside the group common bounding box when element that is not selected is clicked should switch selection to not selected element on pointer up > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -6907,6 +6971,7 @@ exports[`regression tests > given a group of selected elements with an element t
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -7181,6 +7246,7 @@ exports[`regression tests > given a group of selected elements with an element t
|
||||
exports[`regression tests > given a selected element A and a not selected element B with higher z-index than A and given B partially overlaps A when there's a shift-click on the overlapped section B is added to the selection > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7239,6 +7305,7 @@ exports[`regression tests > given a selected element A and a not selected elemen
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -7458,6 +7525,7 @@ exports[`regression tests > given a selected element A and a not selected elemen
|
||||
exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when clicking intersection between A and B B should be selected on pointer up > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7516,6 +7584,7 @@ exports[`regression tests > given selected element A with lower z-index than uns
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -7691,6 +7760,7 @@ exports[`regression tests > given selected element A with lower z-index than uns
|
||||
exports[`regression tests > given selected element A with lower z-index than unselected element B and given B is partially over A when dragging on intersection between A and B A should be dragged and keep being selected > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7749,6 +7819,7 @@ exports[`regression tests > given selected element A with lower z-index than uns
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -7927,6 +7998,7 @@ exports[`regression tests > given selected element A with lower z-index than uns
|
||||
exports[`regression tests > key 2 selects rectangle tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -7985,6 +8057,7 @@ exports[`regression tests > key 2 selects rectangle tool > [end of test] appStat
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -8105,6 +8178,7 @@ exports[`regression tests > key 2 selects rectangle tool > [end of test] undo st
|
||||
exports[`regression tests > key 3 selects diamond tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8163,6 +8237,7 @@ exports[`regression tests > key 3 selects diamond tool > [end of test] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -8283,6 +8358,7 @@ exports[`regression tests > key 3 selects diamond tool > [end of test] undo stac
|
||||
exports[`regression tests > key 4 selects ellipse tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8341,6 +8417,7 @@ exports[`regression tests > key 4 selects ellipse tool > [end of test] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -8461,6 +8538,7 @@ exports[`regression tests > key 4 selects ellipse tool > [end of test] undo stac
|
||||
exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8519,6 +8597,7 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1`
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -8682,6 +8761,7 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] undo stack
|
||||
exports[`regression tests > key 6 selects line tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8740,6 +8820,7 @@ exports[`regression tests > key 6 selects line tool > [end of test] appState 1`]
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -8902,6 +8983,7 @@ exports[`regression tests > key 6 selects line tool > [end of test] undo stack 1
|
||||
exports[`regression tests > key 7 selects freedraw tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -8960,6 +9042,7 @@ exports[`regression tests > key 7 selects freedraw tool > [end of test] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -9094,6 +9177,7 @@ exports[`regression tests > key 7 selects freedraw tool > [end of test] undo sta
|
||||
exports[`regression tests > key a selects arrow tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9152,6 +9236,7 @@ exports[`regression tests > key a selects arrow tool > [end of test] appState 1`
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -9315,6 +9400,7 @@ exports[`regression tests > key a selects arrow tool > [end of test] undo stack
|
||||
exports[`regression tests > key d selects diamond tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9373,6 +9459,7 @@ exports[`regression tests > key d selects diamond tool > [end of test] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -9493,6 +9580,7 @@ exports[`regression tests > key d selects diamond tool > [end of test] undo stac
|
||||
exports[`regression tests > key l selects line tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9551,6 +9639,7 @@ exports[`regression tests > key l selects line tool > [end of test] appState 1`]
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -9713,6 +9802,7 @@ exports[`regression tests > key l selects line tool > [end of test] undo stack 1
|
||||
exports[`regression tests > key o selects ellipse tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9771,6 +9861,7 @@ exports[`regression tests > key o selects ellipse tool > [end of test] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -9891,6 +9982,7 @@ exports[`regression tests > key o selects ellipse tool > [end of test] undo stac
|
||||
exports[`regression tests > key p selects freedraw tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -9949,6 +10041,7 @@ exports[`regression tests > key p selects freedraw tool > [end of test] appState
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -10083,6 +10176,7 @@ exports[`regression tests > key p selects freedraw tool > [end of test] undo sta
|
||||
exports[`regression tests > key r selects rectangle tool > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -10141,6 +10235,7 @@ exports[`regression tests > key r selects rectangle tool > [end of test] appStat
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -10261,6 +10356,7 @@ exports[`regression tests > key r selects rectangle tool > [end of test] undo st
|
||||
exports[`regression tests > make a group and duplicate it > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -10319,6 +10415,7 @@ exports[`regression tests > make a group and duplicate it > [end of test] appSta
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -10759,6 +10856,7 @@ exports[`regression tests > make a group and duplicate it > [end of test] undo s
|
||||
exports[`regression tests > noop interaction after undo shouldn't create history entry > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -10817,6 +10915,7 @@ exports[`regression tests > noop interaction after undo shouldn't create history
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -11037,6 +11136,7 @@ exports[`regression tests > noop interaction after undo shouldn't create history
|
||||
exports[`regression tests > pinch-to-zoom works > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11095,6 +11195,7 @@ exports[`regression tests > pinch-to-zoom works > [end of test] appState 1`] = `
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "touch",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -11158,6 +11259,7 @@ exports[`regression tests > pinch-to-zoom works > [end of test] undo stack 1`] =
|
||||
exports[`regression tests > shift click on selected element should deselect it on pointer up > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11216,6 +11318,7 @@ exports[`regression tests > shift click on selected element should deselect it o
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -11356,6 +11459,7 @@ exports[`regression tests > shift click on selected element should deselect it o
|
||||
exports[`regression tests > shift-click to multiselect, then drag > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11414,6 +11518,7 @@ exports[`regression tests > shift-click to multiselect, then drag > [end of test
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -11669,6 +11774,7 @@ exports[`regression tests > shift-click to multiselect, then drag > [end of test
|
||||
exports[`regression tests > should group elements and ungroup them > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -11727,6 +11833,7 @@ exports[`regression tests > should group elements and ungroup them > [end of tes
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -12084,6 +12191,7 @@ exports[`regression tests > should group elements and ungroup them > [end of tes
|
||||
exports[`regression tests > single-clicking on a subgroup of a selected group should not alter selection > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12142,6 +12250,7 @@ exports[`regression tests > single-clicking on a subgroup of a selected group sh
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -12706,6 +12815,7 @@ exports[`regression tests > single-clicking on a subgroup of a selected group sh
|
||||
exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12764,6 +12874,7 @@ exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] a
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -12830,6 +12941,7 @@ exports[`regression tests > spacebar + drag scrolls the canvas > [end of test] u
|
||||
exports[`regression tests > supports nested groups > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -12888,6 +13000,7 @@ exports[`regression tests > supports nested groups > [end of test] appState 1`]
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -13287,16 +13400,15 @@ exports[`regression tests > supports nested groups > [end of test] undo stack 1`
|
||||
"delta": Delta {
|
||||
"deleted": {
|
||||
"editingGroupId": null,
|
||||
"selectedElementIds": {
|
||||
"id3": true,
|
||||
},
|
||||
"selectedGroupIds": {
|
||||
"id11": true,
|
||||
},
|
||||
"selectedElementIds": {},
|
||||
"selectedGroupIds": {},
|
||||
},
|
||||
"inserted": {
|
||||
"editingGroupId": "id11",
|
||||
"selectedElementIds": {},
|
||||
"selectedElementIds": {
|
||||
"id0": true,
|
||||
"id6": true,
|
||||
},
|
||||
"selectedGroupIds": {
|
||||
"id19": true,
|
||||
},
|
||||
@ -13308,7 +13420,33 @@ exports[`regression tests > supports nested groups > [end of test] undo stack 1`
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id25",
|
||||
"id": "id24",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
"delta": Delta {
|
||||
"deleted": {
|
||||
"selectedElementIds": {
|
||||
"id0": true,
|
||||
"id3": true,
|
||||
"id6": true,
|
||||
},
|
||||
"selectedGroupIds": {
|
||||
"id11": true,
|
||||
},
|
||||
},
|
||||
"inserted": {
|
||||
"selectedElementIds": {},
|
||||
"selectedGroupIds": {},
|
||||
},
|
||||
},
|
||||
},
|
||||
"elements": {
|
||||
"added": {},
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id27",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
@ -13336,34 +13474,34 @@ exports[`regression tests > supports nested groups > [end of test] undo stack 1`
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id27",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
"delta": Delta {
|
||||
"deleted": {
|
||||
"editingGroupId": "id19",
|
||||
"selectedElementIds": {},
|
||||
"selectedGroupIds": {},
|
||||
},
|
||||
"inserted": {
|
||||
"editingGroupId": "id11",
|
||||
"selectedElementIds": {
|
||||
"id6": true,
|
||||
},
|
||||
"selectedGroupIds": {
|
||||
"id19": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"elements": {
|
||||
"added": {},
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id29",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
"delta": Delta {
|
||||
"deleted": {
|
||||
"editingGroupId": "id19",
|
||||
"selectedElementIds": {},
|
||||
"selectedGroupIds": {},
|
||||
},
|
||||
"inserted": {
|
||||
"editingGroupId": "id11",
|
||||
"selectedElementIds": {
|
||||
"id6": true,
|
||||
},
|
||||
"selectedGroupIds": {
|
||||
"id19": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"elements": {
|
||||
"added": {},
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id31",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
"delta": Delta {
|
||||
@ -13389,7 +13527,7 @@ exports[`regression tests > supports nested groups > [end of test] undo stack 1`
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id32",
|
||||
"id": "id34",
|
||||
},
|
||||
{
|
||||
"appState": AppStateDelta {
|
||||
@ -13416,7 +13554,7 @@ exports[`regression tests > supports nested groups > [end of test] undo stack 1`
|
||||
"removed": {},
|
||||
"updated": {},
|
||||
},
|
||||
"id": "id34",
|
||||
"id": "id36",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@ -13424,6 +13562,7 @@ exports[`regression tests > supports nested groups > [end of test] undo stack 1`
|
||||
exports[`regression tests > switches from group of selected elements to another element on pointer down > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -13482,6 +13621,7 @@ exports[`regression tests > switches from group of selected elements to another
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -13763,6 +13903,7 @@ exports[`regression tests > switches from group of selected elements to another
|
||||
exports[`regression tests > switches selected element on pointer down > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -13821,6 +13962,7 @@ exports[`regression tests > switches selected element on pointer down > [end of
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -14027,6 +14169,7 @@ exports[`regression tests > switches selected element on pointer down > [end of
|
||||
exports[`regression tests > two-finger scroll works > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14085,6 +14228,7 @@ exports[`regression tests > two-finger scroll works > [end of test] appState 1`]
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "touch",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -14148,6 +14292,7 @@ exports[`regression tests > two-finger scroll works > [end of test] undo stack 1
|
||||
exports[`regression tests > undo/redo drawing an element > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14206,6 +14351,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] appStat
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -14531,6 +14677,7 @@ exports[`regression tests > undo/redo drawing an element > [end of test] undo st
|
||||
exports[`regression tests > updates fontSize & fontFamily appState > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14589,6 +14736,7 @@ exports[`regression tests > updates fontSize & fontFamily appState > [end of tes
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
@ -14652,6 +14800,7 @@ exports[`regression tests > updates fontSize & fontFamily appState > [end of tes
|
||||
exports[`regression tests > zoom hotkeys > [end of test] appState 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -14710,6 +14859,7 @@ exports[`regression tests > zoom hotkeys > [end of test] appState 1`] = `
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "Untitled-201933152653",
|
||||
"newElement": null,
|
||||
|
@ -72,7 +72,7 @@ describe("element locking", () => {
|
||||
expect(lockedRectangle).toEqual(expect.objectContaining({ x: 0, y: 0 }));
|
||||
});
|
||||
|
||||
it("you can drag element that's below a locked element", () => {
|
||||
it("dragging element that's below a locked element", () => {
|
||||
const rectangle = API.createElement({
|
||||
type: "rectangle",
|
||||
width: 100,
|
||||
@ -89,6 +89,14 @@ describe("element locking", () => {
|
||||
|
||||
API.setElements([rectangle, lockedRectangle]);
|
||||
|
||||
mouse.downAt(50, 50);
|
||||
mouse.moveTo(100, 100);
|
||||
mouse.upAt(100, 100);
|
||||
expect(lockedRectangle).toEqual(expect.objectContaining({ x: 0, y: 0 }));
|
||||
expect(rectangle).toEqual(expect.objectContaining({ x: 0, y: 0 }));
|
||||
|
||||
// once selected, the locked element above should be ignored
|
||||
API.setSelectedElements([rectangle]);
|
||||
mouse.downAt(50, 50);
|
||||
mouse.moveTo(100, 100);
|
||||
mouse.upAt(100, 100);
|
||||
@ -107,7 +115,7 @@ describe("element locking", () => {
|
||||
expect(API.getSelectedElements().length).toBe(1);
|
||||
});
|
||||
|
||||
it("clicking on a locked element should select the unlocked element beneath it", () => {
|
||||
it("clicking on a locked element should not select the unlocked element beneath it", () => {
|
||||
const rectangle = API.createElement({
|
||||
type: "rectangle",
|
||||
width: 100,
|
||||
@ -125,8 +133,8 @@ describe("element locking", () => {
|
||||
API.setElements([rectangle, lockedRectangle]);
|
||||
expect(API.getSelectedElements().length).toBe(0);
|
||||
mouse.clickAt(50, 50);
|
||||
expect(API.getSelectedElements().length).toBe(1);
|
||||
expect(API.getSelectedElement().id).toBe(rectangle.id);
|
||||
expect(API.getSelectedElements().length).toBe(0);
|
||||
expect(h.state.activeLockedId).toBe(lockedRectangle.id);
|
||||
});
|
||||
|
||||
it("right-clicking on a locked element should select it & open its contextMenu", () => {
|
||||
|
@ -235,6 +235,7 @@ export type InteractiveCanvasAppState = Readonly<
|
||||
croppingElementId: AppState["croppingElementId"];
|
||||
// Search matches
|
||||
searchMatches: AppState["searchMatches"];
|
||||
activeLockedId: AppState["activeLockedId"];
|
||||
}
|
||||
>;
|
||||
|
||||
@ -255,6 +256,8 @@ export type ObservedElementsAppState = {
|
||||
// Right now it's coupled to `editingLinearElement`, ideally it should not be really needed as we already have selectedElementIds & editingLinearElementId
|
||||
selectedLinearElementId: LinearElementEditor["elementId"] | null;
|
||||
croppingElementId: AppState["croppingElementId"];
|
||||
lockedMultiSelections: AppState["lockedMultiSelections"];
|
||||
activeLockedId: AppState["activeLockedId"];
|
||||
};
|
||||
|
||||
export interface AppState {
|
||||
@ -437,6 +440,14 @@ export interface AppState {
|
||||
focusedId: ExcalidrawElement["id"] | null;
|
||||
matches: readonly SearchMatch[];
|
||||
}> | null;
|
||||
|
||||
/** the locked element/group that's active and shows unlock popup */
|
||||
activeLockedId: string | null;
|
||||
// when locking multiple units of elements together, we assign a temporary
|
||||
// groupId to them so we can unlock them together;
|
||||
// as elements are unlocked, we remove the groupId from the elements
|
||||
// and also remove groupId from this map
|
||||
lockedMultiSelections: { [groupId: string]: true };
|
||||
}
|
||||
|
||||
export type SearchMatch = {
|
||||
|
@ -3,6 +3,7 @@
|
||||
exports[`exportToSvg > with default arguments 1`] = `
|
||||
{
|
||||
"activeEmbeddable": null,
|
||||
"activeLockedId": null,
|
||||
"activeTool": {
|
||||
"customType": null,
|
||||
"fromSelection": false,
|
||||
@ -61,6 +62,7 @@ exports[`exportToSvg > with default arguments 1`] = `
|
||||
"isResizing": false,
|
||||
"isRotating": false,
|
||||
"lastPointerDownWith": "mouse",
|
||||
"lockedMultiSelections": {},
|
||||
"multiElement": null,
|
||||
"name": "name",
|
||||
"newElement": null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user