From 342205e40325855fd5f2f2aae0645cc167c76632 Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Fri, 31 Oct 2025 18:16:50 +0100 Subject: [PATCH] feat: Settings menu --- excalidraw-app/components/AppMainMenu.tsx | 1 + packages/common/src/utils.ts | 2 +- packages/excalidraw/components/LayerUI.tsx | 2 + .../components/Settings/Settings.scss | 59 + .../components/Settings/Settings.tsx | 130 ++ .../excalidraw/components/Settings/index.tsx | 1 + packages/excalidraw/components/icons.tsx | 10 + .../components/main-menu/DefaultItems.tsx | 21 + packages/excalidraw/locales/en.json | 5 + .../tests/__snapshots__/history.test.tsx.snap | 1724 +++++++---------- .../tests/__snapshots__/move.test.tsx.snap | 138 -- packages/excalidraw/types.ts | 1 + 12 files changed, 915 insertions(+), 1179 deletions(-) create mode 100644 packages/excalidraw/components/Settings/Settings.scss create mode 100644 packages/excalidraw/components/Settings/Settings.tsx create mode 100644 packages/excalidraw/components/Settings/index.tsx diff --git a/excalidraw-app/components/AppMainMenu.tsx b/excalidraw-app/components/AppMainMenu.tsx index cd0aca2683..7db2f47811 100644 --- a/excalidraw-app/components/AppMainMenu.tsx +++ b/excalidraw-app/components/AppMainMenu.tsx @@ -37,6 +37,7 @@ export const AppMainMenu: React.FC<{ )} + diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index ef62da2c0e..4803e0b58d 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -1326,7 +1326,7 @@ type FEATURE_FLAGS = { COMPLEX_BINDINGS: boolean; }; -const FEATURE_FLAGS_STORAGE_KEY = "feature-flags"; +const FEATURE_FLAGS_STORAGE_KEY = "excalidraw-feature-flags"; const DEFAULT_FEATURE_FLAGS: FEATURE_FLAGS = { COMPLEX_BINDINGS: false, }; diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index a5f64e344d..57d0900c3e 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -63,6 +63,7 @@ import { ImageExportDialog } from "./ImageExportDialog"; import { Island } from "./Island"; import { JSONExportDialog } from "./JSONExportDialog"; import { LaserPointerButton } from "./LaserPointerButton"; +import { Settings } from "./Settings"; import "./LayerUI.scss"; import "./Toolbar.scss"; @@ -548,6 +549,7 @@ const LayerUI = ({ /> )} + {appState.openDialog?.name === "elementLinkSelector" && ( { + switch (category) { + case DEFAULT_SETTINGS_CATEGORIES.experimental: + return 1; + default: + return 10; + } +}; + +type SettingItem = { + label: string; + category: string; + flagKey: "COMPLEX_BINDINGS"; + getValue: () => boolean; + setValue: (value: boolean) => void; +}; + +export const Settings = () => { + const uiAppState = useUIAppState(); + const setAppState = useExcalidrawSetAppState(); + + const settings: SettingItem[] = [ + { + label: t("settings.binding"), + category: DEFAULT_SETTINGS_CATEGORIES.experimental, + flagKey: "COMPLEX_BINDINGS", + getValue: () => getFeatureFlag("COMPLEX_BINDINGS"), + setValue: (value: boolean) => setFeatureFlag("COMPLEX_BINDINGS", value), + }, + ]; + + const [settingStates, setSettingStates] = useState>( + () => { + const initialStates: Record = {}; + settings.forEach((setting) => { + initialStates[setting.flagKey] = setting.getValue(); + }); + return initialStates; + }, + ); + + if (uiAppState.openDialog?.name !== "settings") { + return null; + } + + const closeSettings = () => { + setAppState({ + openDialog: null, + }); + }; + + const handleToggle = (setting: SettingItem, checked: boolean) => { + setting.setValue(checked); + setSettingStates((prev) => ({ + ...prev, + [setting.flagKey]: checked, + })); + }; + + const settingsByCategory = settings + .sort( + (a, b) => + getCategoryOrder(a.category) - getCategoryOrder(b.category) || + a.label.localeCompare(b.label), + ) + .reduce((acc, setting) => { + if (!acc[setting.category]) { + acc[setting.category] = []; + } + acc[setting.category].push(setting); + return acc; + }, {} as Record); + + return ( + + +
+ {Object.entries(settingsByCategory).map(([category, items]) => ( +
+
{category}
+
+ {items.map((setting) => ( +
+ handleToggle(setting, checked)} + > + {setting.label} + +
+ ))} +
+
+ ))} +
+
+ ); +}; diff --git a/packages/excalidraw/components/Settings/index.tsx b/packages/excalidraw/components/Settings/index.tsx new file mode 100644 index 0000000000..7d229fa5f4 --- /dev/null +++ b/packages/excalidraw/components/Settings/index.tsx @@ -0,0 +1 @@ +export { Settings } from "./Settings"; diff --git a/packages/excalidraw/components/icons.tsx b/packages/excalidraw/components/icons.tsx index 3f6c4d1bb1..f53162dbe2 100644 --- a/packages/excalidraw/components/icons.tsx +++ b/packages/excalidraw/components/icons.tsx @@ -522,6 +522,16 @@ export const ExportIcon = createIcon( modifiedTablerIconProps, ); +// tabler-icons: settings +export const settingsIcon = createIcon( + + + + + , + tablerIconProps, +); + export const HelpIcon = createIcon( diff --git a/packages/excalidraw/components/main-menu/DefaultItems.tsx b/packages/excalidraw/components/main-menu/DefaultItems.tsx index 29a2761a10..173e3d7ff2 100644 --- a/packages/excalidraw/components/main-menu/DefaultItems.tsx +++ b/packages/excalidraw/components/main-menu/DefaultItems.tsx @@ -40,6 +40,7 @@ import { MoonIcon, save, searchIcon, + settingsIcon, SunIcon, TrashIcon, usersIcon, @@ -170,6 +171,26 @@ export const SearchMenu = (opts?: { className?: string }) => { }; SearchMenu.displayName = "SearchMenu"; +export const SettingsMenu = (opts?: { className?: string }) => { + const { t } = useI18n(); + const setAppState = useExcalidrawSetAppState(); + + return ( + { + setAppState({ openDialog: { name: "settings" } }); + }} + aria-label={t("settings.title")} + className={opts?.className} + > + {t("settings.title")} + + ); +}; +SettingsMenu.displayName = "SettingsMenu"; + export const Help = () => { const { t } = useI18n(); diff --git a/packages/excalidraw/locales/en.json b/packages/excalidraw/locales/en.json index d6fd2654bf..963a57d0aa 100644 --- a/packages/excalidraw/locales/en.json +++ b/packages/excalidraw/locales/en.json @@ -198,6 +198,11 @@ "frames": "Frames", "texts": "Texts" }, + "settings": { + "title": "Settings", + "experimental": "Experimental", + "binding": "Complex bindings" + }, "buttons": { "clearReset": "Reset the canvas", "exportJSON": "Export to file", diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 6e7aa01ce7..50b6990e65 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -124,7 +124,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [], + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -143,7 +148,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 13, + "version": 7, "width": 100, "x": -100, "y": -50, @@ -154,7 +159,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [], + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -173,7 +183,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 9, + "version": 6, "width": 100, "x": 100, "y": -50, @@ -189,17 +199,17 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "elbowed": false, "endArrowhead": "arrow", "endBinding": { - "elementId": "id15", + "elementId": "id1", "fixedPoint": [ - "0.50000", - 1, + "-0.06000", + "0.59962", ], "mode": "orbit", }, "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "112.79549", + "height": "0.56170", "id": "id4", "index": "a2", "isDeleted": false, @@ -213,8 +223,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - "94.00000", - "112.79549", + "88.00000", + "0.56170", ], ], "roughness": 1, @@ -222,16 +232,23 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 34, - "width": "94.00000", - "x": 0, - "y": 0, + "version": 17, + "width": "88.00000", + "x": 6, + "y": "9.40000", } `; @@ -239,12 +256,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], + "boundElements": [], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -263,7 +275,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 10, + "version": 4, "width": 50, "x": 100, "y": 100, @@ -272,214 +284,9 @@ 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 the arrow got bound to a different element in the meantime > [end of test] number of elements 1`] = `4`; -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] number of renders 1`] = `22`; +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] number of renders 1`] = `16`; -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] redo stack 1`] = ` -[ - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id0": { - "deleted": { - "version": 12, - }, - "inserted": { - "version": 11, - }, - }, - "id1": { - "deleted": { - "boundElements": [], - "version": 9, - }, - "inserted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 8, - }, - }, - "id15": { - "deleted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 9, - }, - "inserted": { - "boundElements": [], - "version": 8, - }, - }, - "id4": { - "deleted": { - "endBinding": { - "elementId": "id15", - "fixedPoint": [ - "0.50000", - 1, - ], - "mode": "orbit", - }, - "height": "98.55605", - "points": [ - [ - 0, - 0, - ], - [ - 88, - "98.55605", - ], - ], - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.60000", - ], - "mode": "orbit", - }, - "version": 33, - "width": 88, - "y": "16.71973", - }, - "inserted": { - "endBinding": { - "elementId": "id1", - "fixedPoint": [ - 0, - "0.60000", - ], - "mode": "orbit", - }, - "height": "0.00000", - "points": [ - [ - 0, - 0, - ], - [ - 88, - "0.00000", - ], - ], - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.60000", - ], - "mode": "orbit", - }, - "version": 30, - "width": 88, - "y": "10.00000", - }, - }, - }, - }, - "id": "id22", - }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id0": { - "deleted": { - "boundElements": [], - "version": 13, - }, - "inserted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 12, - }, - }, - "id15": { - "deleted": { - "version": 10, - }, - "inserted": { - "version": 9, - }, - }, - "id4": { - "deleted": { - "height": "112.79549", - "points": [ - [ - 0, - 0, - ], - [ - "94.00000", - "112.79549", - ], - ], - "startBinding": null, - "version": 34, - "width": "94.00000", - "x": 0, - "y": 0, - }, - "inserted": { - "height": "98.55605", - "points": [ - [ - 0, - 0, - ], - [ - 88, - "98.55605", - ], - ], - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.60000", - ], - "mode": "orbit", - }, - "version": 33, - "width": 88, - "x": 6, - "y": "16.71973", - }, - }, - }, - }, - "id": "id23", - }, -] -`; +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] redo stack 1`] = `[]`; 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] undo stack 1`] = ` [ @@ -634,6 +441,206 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "id": "id6", }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 6, + }, + "inserted": { + "boundElements": [], + "version": 5, + }, + }, + "id15": { + "deleted": { + "version": 3, + }, + "inserted": { + "version": 2, + }, + }, + "id4": { + "deleted": { + "height": "103.96874", + "points": [ + [ + 0, + 0, + ], + [ + "88.00000", + "103.96874", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, + "version": 16, + "width": "88.00000", + "x": 6, + "y": "9.40000", + }, + "inserted": { + "height": 0, + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + "startBinding": null, + "version": 14, + "width": 100, + "x": 0, + "y": 0, + }, + }, + }, + }, + "id": "id16", + }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "version": 7, + }, + "inserted": { + "version": 6, + }, + }, + "id1": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 6, + }, + "inserted": { + "boundElements": [], + "version": 5, + }, + }, + "id15": { + "deleted": { + "boundElements": [], + "version": 4, + }, + "inserted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 3, + }, + }, + "id4": { + "deleted": { + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + "-0.06000", + "0.59962", + ], + "mode": "orbit", + }, + "height": "0.56170", + "points": [ + [ + 0, + 0, + ], + [ + "88.00000", + "0.56170", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, + "version": 17, + "width": "88.00000", + }, + "inserted": { + "endBinding": { + "elementId": "id15", + "fixedPoint": [ + "0.50000", + 1, + ], + "mode": "orbit", + }, + "height": "103.96874", + "points": [ + [ + 0, + 0, + ], + [ + "88.00000", + "103.96874", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, + "version": 16, + "width": "88.00000", + }, + }, + }, + }, + "id": "id17", + }, ] `; @@ -761,7 +768,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [], + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -780,7 +792,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 14, + "version": 8, "width": 100, "x": 150, "y": -50, @@ -791,7 +803,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [], + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -810,7 +827,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 9, + "version": 6, "width": 100, "x": 150, "y": -50, @@ -825,7 +842,14 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "customData": undefined, "elbowed": false, "endArrowhead": "arrow", - "endBinding": null, + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + "-0.06000", + "0.59962", + ], + "mode": "orbit", + }, "fillStyle": "solid", "frameId": null, "groupIds": [], @@ -843,7 +867,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 100, + 0, 0, ], ], @@ -852,199 +876,31 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": 2, }, "startArrowhead": null, - "startBinding": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, "strokeColor": "#1e1e1e", "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 30, - "width": 100, - "x": 150, - "y": 0, + "version": 20, + "width": 0, + "x": 144, + "y": "9.96170", } `; 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] number of elements 1`] = `3`; -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] number of renders 1`] = `24`; +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] number of renders 1`] = `17`; -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] redo stack 1`] = ` -[ - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id0": { - "deleted": { - "version": 13, - }, - "inserted": { - "version": 12, - }, - }, - "id1": { - "deleted": { - "boundElements": [], - "version": 9, - }, - "inserted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 8, - }, - }, - "id4": { - "deleted": { - "endBinding": null, - "height": "2.93333", - "points": [ - [ - 0, - 0, - ], - [ - "-44.00000", - "-2.93333", - ], - ], - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.60000", - ], - "mode": "orbit", - }, - "version": 29, - "width": "44.00000", - "y": "2.93333", - }, - "inserted": { - "endBinding": { - "elementId": "id1", - "fixedPoint": [ - 0, - "0.60000", - ], - "mode": "orbit", - }, - "height": 0, - "points": [ - [ - 0, - 0, - ], - [ - "6.00000", - 0, - ], - ], - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.60000", - ], - "mode": "orbit", - }, - "version": 27, - "width": "6.00000", - "y": 10, - }, - }, - }, - }, - "id": "id21", - }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": { - "id0": { - "deleted": { - "boundElements": [], - "version": 14, - }, - "inserted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 13, - }, - }, - "id4": { - "deleted": { - "height": 0, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "startBinding": null, - "version": 30, - "width": 100, - "x": 150, - "y": 0, - }, - "inserted": { - "height": "2.93333", - "points": [ - [ - 0, - 0, - ], - [ - "-44.00000", - "-2.93333", - ], - ], - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.60000", - ], - "mode": "orbit", - }, - "version": 29, - "width": "44.00000", - "x": 144, - "y": "2.93333", - }, - }, - }, - }, - "id": "id22", - }, -] -`; +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] redo stack 1`] = `[]`; 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] undo stack 1`] = ` [ @@ -1199,6 +1055,176 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "id": "id6", }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 7, + }, + "inserted": { + "boundElements": [], + "version": 6, + }, + }, + "id4": { + "deleted": { + "height": "2.65128", + "points": [ + [ + 0, + 0, + ], + [ + -44, + "-2.65128", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, + "version": 17, + "width": 44, + "x": 144, + "y": "2.65128", + }, + "inserted": { + "height": 0, + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + "startBinding": null, + "version": 15, + "width": 100, + "x": 150, + "y": 0, + }, + }, + }, + }, + "id": "id15", + }, + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elements": { + "added": {}, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "version": 8, + }, + "inserted": { + "version": 7, + }, + }, + "id1": { + "deleted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 6, + }, + "inserted": { + "boundElements": [], + "version": 5, + }, + }, + "id4": { + "deleted": { + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + "-0.06000", + "0.59962", + ], + "mode": "orbit", + }, + "height": 0, + "points": [ + [ + 0, + 0, + ], + [ + 0, + 0, + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, + "version": 20, + "width": 0, + }, + "inserted": { + "endBinding": null, + "height": "2.65128", + "points": [ + [ + 0, + 0, + ], + [ + -44, + "-2.65128", + ], + ], + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + "1.06000", + "0.59400", + ], + "mode": "orbit", + }, + "version": 17, + "width": 44, + }, + }, + }, + }, + "id": "id16", + }, ] `; @@ -2287,9 +2313,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "scrollX": 0, "scrollY": 0, "searchMatches": null, - "selectedElementIds": { - "id4": true, - }, + "selectedElementIds": {}, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, "selectionElement": null, @@ -2321,12 +2345,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], + "boundElements": [], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -2345,7 +2364,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 5, + "version": 4, "width": 100, "x": -100, "y": -50, @@ -2356,12 +2375,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl { "angle": 0, "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], + "boundElements": [], "customData": undefined, "fillStyle": "solid", "frameId": null, @@ -2380,10 +2394,10 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 4, "width": 100, - "x": 500, - "y": -500, + "x": 100, + "y": -50, } `; @@ -2398,7 +2412,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "endBinding": { "elementId": "id1", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -2406,13 +2420,12 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "439.13521", + "height": 0, "id": "id4", "index": "a2", - "isDeleted": false, + "isDeleted": true, "link": null, "locked": false, - "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -2420,8 +2433,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 488, - "-439.13521", + 88, + 0, ], ], "roughness": 1, @@ -2442,18 +2455,140 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 13, - "width": 488, + "version": 8, + "width": 88, "x": 6, - "y": "-5.38920", + "y": "0.01000", } `; 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] number of elements 1`] = `3`; -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] number of renders 1`] = `10`; +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] number of renders 1`] = `8`; -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] redo stack 1`] = `[]`; +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] redo stack 1`] = ` +[ + { + "appState": AppStateDelta { + "delta": Delta { + "deleted": { + "selectedElementIds": {}, + "selectedLinearElement": null, + }, + "inserted": { + "selectedElementIds": { + "id4": true, + }, + "selectedLinearElement": { + "elementId": "id4", + "isEditing": false, + }, + }, + }, + }, + "elements": { + "added": { + "id4": { + "deleted": { + "isDeleted": true, + "version": 8, + }, + "inserted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id1", + "fixedPoint": [ + "-0.06000", + "0.50010", + ], + "mode": "orbit", + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 0, + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + 88, + 0, + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "startArrowhead": null, + "startBinding": { + "elementId": "id0", + "fixedPoint": [ + 1, + "0.50010", + ], + "mode": "orbit", + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "version": 7, + "width": 88, + "x": 6, + "y": "0.01000", + }, + }, + }, + "removed": {}, + "updated": { + "id0": { + "deleted": { + "boundElements": [], + "version": 4, + }, + "inserted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 3, + }, + }, + "id1": { + "deleted": { + "boundElements": [], + "version": 4, + }, + "inserted": { + "boundElements": [ + { + "id": "id4", + "type": "arrow", + }, + ], + "version": 3, + }, + }, + }, + }, + "id": "id7", + }, +] +`; 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] undo stack 1`] = ` [ @@ -2534,125 +2669,6 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "id": "id3", }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id4": true, - }, - "selectedLinearElement": { - "elementId": "id4", - "isEditing": false, - }, - }, - "inserted": { - "selectedElementIds": {}, - "selectedLinearElement": null, - }, - }, - }, - "elements": { - "added": {}, - "removed": { - "id4": { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": { - "elementId": "id1", - "fixedPoint": [ - 0, - "0.50010", - ], - "mode": "orbit", - }, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": "439.13521", - "index": "a2", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - 488, - "-439.13521", - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "startArrowhead": null, - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.50010", - ], - "mode": "orbit", - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "version": 13, - "width": 488, - "x": 6, - "y": "-5.38920", - }, - "inserted": { - "isDeleted": true, - "version": 10, - }, - }, - }, - "updated": { - "id0": { - "deleted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 5, - }, - "inserted": { - "boundElements": [], - "version": 4, - }, - }, - "id1": { - "deleted": { - "boundElements": [ - { - "id": "id4", - "type": "arrow", - }, - ], - "version": 6, - }, - "inserted": { - "boundElements": [], - "version": 5, - }, - }, - }, - }, - "id": "id8", - }, ] `; @@ -16340,7 +16356,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 4, "width": 100, "x": -100, "y": -50, @@ -16378,7 +16394,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 5, + "version": 4, "verticalAlign": "middle", "width": 30, "x": -65, @@ -16414,7 +16430,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 5, + "version": 3, "width": 100, "x": 100, "y": -50, @@ -16432,7 +16448,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -16446,7 +16462,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isDeleted": false, "link": null, "locked": false, - "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -16454,7 +16469,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -16476,8 +16491,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 13, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", } @@ -16485,119 +16500,9 @@ 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 deletion and rebind on undo > [end of test] number of elements 1`] = `4`; -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] number of renders 1`] = `13`; +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] number of renders 1`] = `11`; -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] redo stack 1`] = ` -[ - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id13": true, - }, - "selectedLinearElement": { - "elementId": "id13", - "isEditing": false, - }, - }, - "inserted": { - "selectedElementIds": {}, - "selectedLinearElement": null, - }, - }, - }, - "elements": { - "added": {}, - "removed": { - "id13": { - "deleted": { - "endBinding": { - "elementId": "id2", - "fixedPoint": [ - 0, - "0.50010", - ], - "mode": "orbit", - }, - "isDeleted": false, - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.50010", - ], - "mode": "orbit", - }, - "version": 13, - }, - "inserted": { - "endBinding": { - "elementId": "id2", - "fixedPoint": [ - 0, - "0.50010", - ], - "mode": "orbit", - }, - "isDeleted": true, - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.50010", - ], - "mode": "orbit", - }, - "version": 10, - }, - }, - }, - "updated": { - "id0": { - "deleted": { - "boundElements": [ - { - "id": "id13", - "type": "arrow", - }, - ], - "version": 6, - }, - "inserted": { - "boundElements": [], - "version": 5, - }, - }, - "id1": { - "deleted": { - "version": 5, - }, - "inserted": { - "version": 4, - }, - }, - "id2": { - "deleted": { - "boundElements": [ - { - "id": "id13", - "type": "arrow", - }, - ], - "version": 5, - }, - "inserted": { - "boundElements": [], - "version": 4, - }, - }, - }, - }, - "id": "id18", - }, -] -`; +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] redo stack 1`] = `[]`; 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] undo stack 1`] = ` [ @@ -16850,7 +16755,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -16891,14 +16796,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 9, + "version": 7, "width": 88, "x": 6, - "y": "0.00936", + "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 8, + "version": 6, }, }, }, @@ -17092,7 +16997,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 4, "width": 100, "x": -100, "y": -50, @@ -17130,7 +17035,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 6, + "version": 4, "verticalAlign": "middle", "width": 30, "x": -65, @@ -17166,7 +17071,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 5, + "version": 3, "width": 100, "x": 100, "y": -50, @@ -17184,7 +17089,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -17198,7 +17103,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isDeleted": false, "link": null, "locked": false, - "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -17206,7 +17110,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -17228,8 +17132,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 13, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", } @@ -17237,7 +17141,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] number of elements 1`] = `4`; -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] number of renders 1`] = `13`; +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] number of renders 1`] = `11`; 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] redo stack 1`] = `[]`; @@ -17492,7 +17396,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -17512,7 +17416,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -17533,14 +17437,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 13, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 10, + "version": 6, }, }, }, @@ -17553,19 +17457,11 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", }, ], - "version": 6, + "version": 4, }, "inserted": { "boundElements": [], - "version": 5, - }, - }, - "id1": { - "deleted": { - "version": 6, - }, - "inserted": { - "version": 5, + "version": 3, }, }, "id2": { @@ -17576,16 +17472,16 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", }, ], - "version": 5, + "version": 3, }, "inserted": { "boundElements": [], - "version": 4, + "version": 2, }, }, }, }, - "id": "id17", + "id": "id15", }, ] `; @@ -17742,7 +17638,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 10, + "version": 4, "width": 100, "x": -100, "y": -50, @@ -17780,7 +17676,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 10, + "version": 4, "verticalAlign": "middle", "width": 30, "x": -65, @@ -17816,7 +17712,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 7, + "version": 3, "width": 100, "x": 100, "y": -50, @@ -17834,7 +17730,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -17848,7 +17744,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isDeleted": false, "link": null, "locked": false, - "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -17856,7 +17751,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -17878,8 +17773,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 13, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", } @@ -17887,7 +17782,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] number of elements 1`] = `4`; -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] number of renders 1`] = `21`; +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] number of renders 1`] = `11`; 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] redo stack 1`] = `[]`; @@ -17924,14 +17819,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "rectangle", - "version": 8, + "version": 2, "width": 100, "x": -100, "y": -50, }, "inserted": { "isDeleted": true, - "version": 7, + "version": 1, }, }, "id1": { @@ -17963,7 +17858,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "text": "ola", "textAlign": "left", "type": "text", - "version": 8, + "version": 2, "verticalAlign": "top", "width": 100, "x": -200, @@ -17971,7 +17866,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, "inserted": { "isDeleted": true, - "version": 7, + "version": 1, }, }, "id2": { @@ -17995,20 +17890,20 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "rectangle", - "version": 6, + "version": 2, "width": 100, "x": 100, "y": -50, }, "inserted": { "isDeleted": true, - "version": 5, + "version": 1, }, }, }, "updated": {}, }, - "id": "id21", + "id": "id4", }, { "appState": AppStateDelta { @@ -18028,7 +17923,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "removed": {}, "updated": {}, }, - "id": "id22", + "id": "id7", }, { "appState": AppStateDelta { @@ -18048,7 +17943,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "removed": {}, "updated": {}, }, - "id": "id23", + "id": "id10", }, { "appState": AppStateDelta { @@ -18075,11 +17970,11 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "text", }, ], - "version": 9, + "version": 3, }, "inserted": { "boundElements": [], - "version": 8, + "version": 2, }, }, "id1": { @@ -18087,7 +17982,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "containerId": "id0", "height": 25, "textAlign": "center", - "version": 9, + "version": 4, "verticalAlign": "middle", "width": 30, "x": -65, @@ -18097,7 +17992,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "containerId": null, "height": 100, "textAlign": "left", - "version": 8, + "version": 2, "verticalAlign": "top", "width": 100, "x": -200, @@ -18106,7 +18001,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, }, }, - "id": "id24", + "id": "id12", }, { "appState": AppStateDelta { @@ -18142,7 +18037,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -18162,7 +18057,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -18183,14 +18078,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 13, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 10, + "version": 6, }, }, }, @@ -18203,19 +18098,11 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", }, ], - "version": 10, + "version": 4, }, "inserted": { "boundElements": [], - "version": 9, - }, - }, - "id1": { - "deleted": { - "version": 10, - }, - "inserted": { - "version": 9, + "version": 3, }, }, "id2": { @@ -18226,16 +18113,16 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", }, ], - "version": 7, + "version": 3, }, "inserted": { "boundElements": [], - "version": 6, + "version": 2, }, }, }, }, - "id": "id25", + "id": "id15", }, ] `; @@ -18323,13 +18210,15 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "initialized": true, "type": "selection", }, - "previousSelectedElementIds": {}, + "previousSelectedElementIds": { + "id0": true, + }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": null, "selectedElementIds": { - "id0": true, + "id13": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -18363,14 +18252,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "angle": 0, "backgroundColor": "transparent", "boundElements": [ - { - "id": "id13", - "type": "arrow", - }, { "id": "id1", "type": "text", }, + { + "id": "id13", + "type": "arrow", + }, ], "customData": undefined, "fillStyle": "solid", @@ -18390,7 +18279,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 4, "width": 100, "x": -100, "y": -50, @@ -18428,7 +18317,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 6, + "version": 4, "verticalAlign": "middle", "width": 30, "x": -65, @@ -18464,7 +18353,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 4, + "version": 3, "width": 100, "x": 100, "y": -50, @@ -18482,7 +18371,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -18496,7 +18385,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isDeleted": false, "link": null, "locked": false, - "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -18504,7 +18392,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -18526,8 +18414,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 13, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", } @@ -18535,95 +18423,9 @@ 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] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `15`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `11`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = ` -[ - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id0": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elements": { - "added": {}, - "removed": { - "id0": { - "deleted": { - "isDeleted": false, - "version": 6, - }, - "inserted": { - "isDeleted": true, - "version": 5, - }, - }, - "id1": { - "deleted": { - "isDeleted": false, - "version": 6, - }, - "inserted": { - "isDeleted": true, - "version": 5, - }, - }, - }, - "updated": { - "id13": { - "deleted": { - "endBinding": { - "elementId": "id2", - "fixedPoint": [ - 0, - "0.50010", - ], - "mode": "orbit", - }, - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.50010", - ], - "mode": "orbit", - }, - "version": 13, - }, - "inserted": { - "endBinding": { - "elementId": "id2", - "fixedPoint": [ - 0, - "0.50010", - ], - "mode": "orbit", - }, - "startBinding": null, - "version": 10, - }, - }, - "id2": { - "deleted": { - "version": 4, - }, - "inserted": { - "version": 3, - }, - }, - }, - }, - "id": "id21", - }, -] -`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = `[]`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] undo stack 1`] = ` [ @@ -18876,7 +18678,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -18917,14 +18719,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 9, + "version": 7, "width": 88, "x": 6, - "y": "0.00936", + "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 8, + "version": 6, }, }, }, @@ -18963,33 +18765,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, "id": "id15", }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id0": true, - }, - "selectedLinearElement": null, - }, - "inserted": { - "selectedElementIds": { - "id13": true, - }, - "selectedLinearElement": { - "elementId": "id13", - "isEditing": false, - }, - }, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": {}, - }, - "id": "id18", - }, ] `; @@ -19084,8 +18859,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "scrollY": 0, "searchMatches": null, "selectedElementIds": { - "id0": true, - "id2": true, + "id13": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -19119,14 +18893,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "angle": 0, "backgroundColor": "transparent", "boundElements": [ - { - "id": "id13", - "type": "arrow", - }, { "id": "id1", "type": "text", }, + { + "id": "id13", + "type": "arrow", + }, ], "customData": undefined, "fillStyle": "solid", @@ -19146,7 +18920,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 4, "width": 100, "x": -100, "y": -50, @@ -19184,7 +18958,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 6, + "version": 4, "verticalAlign": "middle", "width": 30, "x": -65, @@ -19220,7 +18994,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 5, + "version": 3, "width": 100, "x": 100, "y": -50, @@ -19238,7 +19012,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -19252,7 +19026,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "isDeleted": false, "link": null, "locked": false, - "moveMidPointsWithElement": false, "opacity": 100, "points": [ [ @@ -19260,7 +19033,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "88.00000", + 88, 0, ], ], @@ -19282,8 +19055,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "arrow", "updated": 1, - "version": 14, - "width": "88.00000", + "version": 7, + "width": 88, "x": 6, "y": "0.01000", } @@ -19291,91 +19064,9 @@ 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] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `16`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] number of renders 1`] = `11`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = ` -[ - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id0": true, - "id2": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elements": { - "added": {}, - "removed": { - "id0": { - "deleted": { - "isDeleted": false, - "version": 6, - }, - "inserted": { - "isDeleted": true, - "version": 5, - }, - }, - "id1": { - "deleted": { - "isDeleted": false, - "version": 6, - }, - "inserted": { - "isDeleted": true, - "version": 5, - }, - }, - "id2": { - "deleted": { - "isDeleted": false, - "version": 5, - }, - "inserted": { - "isDeleted": true, - "version": 4, - }, - }, - }, - "updated": { - "id13": { - "deleted": { - "endBinding": { - "elementId": "id2", - "fixedPoint": [ - 0, - "0.50010", - ], - "mode": "orbit", - }, - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - 1, - "0.50010", - ], - "mode": "orbit", - }, - "version": 14, - }, - "inserted": { - "endBinding": null, - "startBinding": null, - "version": 11, - }, - }, - }, - }, - "id": "id24", - }, -] -`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] redo stack 1`] = `[]`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangles from arrow on deletion and rebind on undo > [end of test] undo stack 1`] = ` [ @@ -19628,7 +19319,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endBinding": { "elementId": "id2", "fixedPoint": [ - 0, + "-0.06000", "0.50010", ], "mode": "orbit", @@ -19669,14 +19360,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "version": 9, + "version": 7, "width": 88, "x": 6, - "y": "0.00936", + "y": "0.01000", }, "inserted": { "isDeleted": true, - "version": 8, + "version": 6, }, }, }, @@ -19715,53 +19406,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, "id": "id15", }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id0": true, - }, - "selectedLinearElement": null, - }, - "inserted": { - "selectedElementIds": { - "id13": true, - }, - "selectedLinearElement": { - "elementId": "id13", - "isEditing": false, - }, - }, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": {}, - }, - "id": "id18", - }, - { - "appState": AppStateDelta { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id2": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elements": { - "added": {}, - "removed": {}, - "updated": {}, - }, - "id": "id21", - }, ] `; diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 2431240933..556a41c35b 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -95,141 +95,3 @@ exports[`move element > rectangle 5`] = ` "y": 40, } `; - -exports[`move element > rectangles with binding arrow 5`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id6", - "type": "arrow", - }, - ], - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "id": "id0", - "index": "a0", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": null, - "seed": 1278240551, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "updated": 1, - "version": 4, - "versionNonce": 640725609, - "width": 100, - "x": 0, - "y": 0, -} -`; - -exports[`move element > rectangles with binding arrow 6`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id6", - "type": "arrow", - }, - ], - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 300, - "id": "id3", - "index": "a1", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": null, - "seed": 1116226695, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "updated": 1, - "version": 7, - "versionNonce": 1051383431, - "width": 300, - "x": 201, - "y": 2, -} -`; - -exports[`move element > rectangles with binding arrow 7`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": { - "elementId": "id3", - "fixedPoint": [ - "-0.03333", - "0.43333", - ], - "mode": "orbit", - }, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": "90.03375", - "id": "id6", - "index": "a2", - "isDeleted": false, - "link": null, - "locked": false, - "moveMidPointsWithElement": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - 89, - "90.03375", - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "seed": 23633383, - "startArrowhead": null, - "startBinding": { - "elementId": "id0", - "fixedPoint": [ - "1.10000", - "0.50010", - ], - "mode": "orbit", - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "updated": 1, - "version": 9, - "versionNonce": 1996028265, - "width": 89, - "x": 106, - "y": "46.01049", -} -`; diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index bb57d075ca..1cb66b943c 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -373,6 +373,7 @@ export interface AppState { | { name: "imageExport" | "help" | "jsonExport" } | { name: "ttd"; tab: "text-to-diagram" | "mermaid" } | { name: "commandPalette" } + | { name: "settings" } | { name: "elementLinkSelector"; sourceElementId: ExcalidrawElement["id"] }; /** * Reflects user preference for whether the default sidebar should be docked.