Переглянути джерело

feat: change `boundElementIds` → `boundElements` (#4404)

David Luzar 3 роки тому
батько
коміт
390da3fd0f

+ 7 - 2
src/data/restore.ts

@@ -64,7 +64,10 @@ const restoreElementWithProperties = <
   T extends ExcalidrawElement,
   K extends Pick<T, keyof Omit<Required<T>, keyof ExcalidrawElement>>,
 >(
-  element: Required<T>,
+  element: Required<T> & {
+    /** @deprecated */
+    boundElementIds?: readonly ExcalidrawElement["id"][];
+  },
   extra: Pick<
     T,
     // This extra Pick<T, keyof K> ensure no excess properties are passed.
@@ -98,7 +101,9 @@ const restoreElementWithProperties = <
     strokeSharpness:
       element.strokeSharpness ??
       (isLinearElementType(element.type) ? "round" : "sharp"),
-    boundElementIds: element.boundElementIds ?? [],
+    boundElements: element.boundElementIds
+      ? element.boundElementIds.map((id) => ({ type: "arrow", id }))
+      : element.boundElements ?? [],
     updated: element.updated ?? getUpdatedTimestamp(),
   };
 

+ 80 - 62
src/element/binding.ts

@@ -8,7 +8,11 @@ import {
 } from "./types";
 import { getElementAtPosition } from "../scene";
 import { AppState } from "../types";
-import { isBindableElement, isBindingElement } from "./typeChecks";
+import {
+  isBindableElement,
+  isBindingElement,
+  isLinearElement,
+} from "./typeChecks";
 import {
   bindingBorderTest,
   distanceToBindableElement,
@@ -20,7 +24,7 @@ import {
 import { mutateElement } from "./mutateElement";
 import Scene from "../scene/Scene";
 import { LinearElementEditor } from "./linearElementEditor";
-import { tupleToCoors } from "../utils";
+import { arrayToMap, tupleToCoors } from "../utils";
 import { KEYS } from "../keys";
 
 export type SuggestedBinding =
@@ -74,8 +78,9 @@ export const bindOrUnbindLinearElement = (
     .getNonDeletedElements(onlyUnbound)
     .forEach((element) => {
       mutateElement(element, {
-        boundElementIds: element.boundElementIds?.filter(
-          (id) => id !== linearElement.id,
+        boundElements: element.boundElements?.filter(
+          (element) =>
+            element.type !== "arrow" || element.id !== linearElement.id,
         ),
       });
     });
@@ -180,11 +185,16 @@ const bindLinearElement = (
       ...calculateFocusAndGap(linearElement, hoveredElement, startOrEnd),
     } as PointBinding,
   });
-  mutateElement(hoveredElement, {
-    boundElementIds: Array.from(
-      new Set([...(hoveredElement.boundElementIds ?? []), linearElement.id]),
-    ),
-  });
+
+  const boundElementsMap = arrayToMap(hoveredElement.boundElements || []);
+  if (!boundElementsMap.has(linearElement.id)) {
+    mutateElement(hoveredElement, {
+      boundElements: (hoveredElement.boundElements || []).concat({
+        id: linearElement.id,
+        type: "arrow",
+      }),
+    });
+  }
 };
 
 // Don't bind both ends of a simple segment
@@ -284,52 +294,56 @@ export const updateBoundElements = (
     newSize?: { width: number; height: number };
   },
 ) => {
-  const boundElementIds = changedElement.boundElementIds ?? [];
-  if (boundElementIds.length === 0) {
+  const boundLinearElements = (changedElement.boundElements ?? []).filter(
+    (el) => el.type === "arrow",
+  );
+  if (boundLinearElements.length === 0) {
     return;
   }
   const { newSize, simultaneouslyUpdated } = options ?? {};
   const simultaneouslyUpdatedElementIds = getSimultaneouslyUpdatedElementIds(
     simultaneouslyUpdated,
   );
-  (
-    Scene.getScene(changedElement)!.getNonDeletedElements(
-      boundElementIds,
-    ) as NonDeleted<ExcalidrawLinearElement>[]
-  ).forEach((linearElement) => {
-    const bindableElement = changedElement as ExcalidrawBindableElement;
-    // In case the boundElementIds are stale
-    if (!doesNeedUpdate(linearElement, bindableElement)) {
-      return;
-    }
-    const startBinding = maybeCalculateNewGapWhenScaling(
-      bindableElement,
-      linearElement.startBinding,
-      newSize,
-    );
-    const endBinding = maybeCalculateNewGapWhenScaling(
-      bindableElement,
-      linearElement.endBinding,
-      newSize,
-    );
-    // `linearElement` is being moved/scaled already, just update the binding
-    if (simultaneouslyUpdatedElementIds.has(linearElement.id)) {
-      mutateElement(linearElement, { startBinding, endBinding });
-      return;
-    }
-    updateBoundPoint(
-      linearElement,
-      "start",
-      startBinding,
-      changedElement as ExcalidrawBindableElement,
-    );
-    updateBoundPoint(
-      linearElement,
-      "end",
-      endBinding,
-      changedElement as ExcalidrawBindableElement,
-    );
-  });
+  Scene.getScene(changedElement)!
+    .getNonDeletedElements(boundLinearElements.map((el) => el.id))
+    .forEach((element) => {
+      if (!isLinearElement(element)) {
+        return;
+      }
+
+      const bindableElement = changedElement as ExcalidrawBindableElement;
+      // In case the boundElements are stale
+      if (!doesNeedUpdate(element, bindableElement)) {
+        return;
+      }
+      const startBinding = maybeCalculateNewGapWhenScaling(
+        bindableElement,
+        element.startBinding,
+        newSize,
+      );
+      const endBinding = maybeCalculateNewGapWhenScaling(
+        bindableElement,
+        element.endBinding,
+        newSize,
+      );
+      // `linearElement` is being moved/scaled already, just update the binding
+      if (simultaneouslyUpdatedElementIds.has(element.id)) {
+        mutateElement(element, { startBinding, endBinding });
+        return;
+      }
+      updateBoundPoint(
+        element,
+        "start",
+        startBinding,
+        changedElement as ExcalidrawBindableElement,
+      );
+      updateBoundPoint(
+        element,
+        "end",
+        endBinding,
+        changedElement as ExcalidrawBindableElement,
+      );
+    });
 };
 
 const doesNeedUpdate = (
@@ -559,11 +573,11 @@ export const fixBindingsAfterDuplication = (
   const allBindableElementIds: Set<ExcalidrawElement["id"]> = new Set();
   const shouldReverseRoles = duplicatesServeAsOld === "duplicatesServeAsOld";
   oldElements.forEach((oldElement) => {
-    const { boundElementIds } = oldElement;
-    if (boundElementIds != null && boundElementIds.length > 0) {
-      boundElementIds.forEach((boundElementId) => {
-        if (shouldReverseRoles && !oldIdToDuplicatedId.has(boundElementId)) {
-          allBoundElementIds.add(boundElementId);
+    const { boundElements } = oldElement;
+    if (boundElements != null && boundElements.length > 0) {
+      boundElements.forEach((boundElement) => {
+        if (shouldReverseRoles && !oldIdToDuplicatedId.has(boundElement.id)) {
+          allBoundElementIds.add(boundElement.id);
         }
       });
       allBindableElementIds.add(oldIdToDuplicatedId.get(oldElement.id)!);
@@ -607,12 +621,16 @@ export const fixBindingsAfterDuplication = (
   sceneElements
     .filter(({ id }) => allBindableElementIds.has(id))
     .forEach((bindableElement) => {
-      const { boundElementIds } = bindableElement;
-      if (boundElementIds != null && boundElementIds.length > 0) {
+      const { boundElements } = bindableElement;
+      if (boundElements != null && boundElements.length > 0) {
         mutateElement(bindableElement, {
-          boundElementIds: boundElementIds.map(
-            (boundElementId) =>
-              oldIdToDuplicatedId.get(boundElementId) ?? boundElementId,
+          boundElements: boundElements.map((boundElement) =>
+            oldIdToDuplicatedId.has(boundElement.id)
+              ? {
+                  id: oldIdToDuplicatedId.get(boundElement.id)!,
+                  type: boundElement.type,
+                }
+              : boundElement,
           ),
         });
       }
@@ -645,9 +663,9 @@ export const fixBindingsAfterDeletion = (
   const boundElementIds: Set<ExcalidrawElement["id"]> = new Set();
   deletedElements.forEach((deletedElement) => {
     if (isBindableElement(deletedElement)) {
-      deletedElement.boundElementIds?.forEach((id) => {
-        if (!deletedElementIds.has(id)) {
-          boundElementIds.add(id);
+      deletedElement.boundElements?.forEach((element) => {
+        if (!deletedElementIds.has(element.id)) {
+          boundElementIds.add(element.id);
         }
       });
     }

+ 3 - 3
src/element/newElement.ts

@@ -27,7 +27,7 @@ type ElementConstructorOpts = MarkOptional<
   | "height"
   | "angle"
   | "groupIds"
-  | "boundElementIds"
+  | "boundElements"
   | "seed"
   | "version"
   | "versionNonce"
@@ -50,7 +50,7 @@ const _newElementBase = <T extends ExcalidrawElement>(
     angle = 0,
     groupIds = [],
     strokeSharpness,
-    boundElementIds = null,
+    boundElements = null,
     ...rest
   }: ElementConstructorOpts & Omit<Partial<ExcalidrawGenericElement>, "type">,
 ) => ({
@@ -74,7 +74,7 @@ const _newElementBase = <T extends ExcalidrawElement>(
   version: rest.version || 1,
   versionNonce: rest.versionNonce ?? 0,
   isDeleted: false as false,
-  boundElementIds,
+  boundElements,
   updated: getUpdatedTimestamp(),
 });
 

+ 7 - 2
src/element/types.ts

@@ -43,8 +43,13 @@ type _ExcalidrawElementBase = Readonly<{
   /** List of groups the element belongs to.
       Ordered from deepest to shallowest. */
   groupIds: readonly GroupId[];
-  /** Ids of (linear) elements that are bound to this element. */
-  boundElementIds: readonly ExcalidrawLinearElement["id"][] | null;
+  /** other elements that are bound to this element */
+  boundElements:
+    | readonly Readonly<{
+        id: ExcalidrawLinearElement["id"];
+        type: "arrow" | "text";
+      }>[]
+    | null;
   /** epoch (ms) timestamp of last element update */
   updated: number;
 }>;

+ 93 - 93
src/tests/__snapshots__/contextmenu.test.tsx.snap

@@ -85,7 +85,7 @@ exports[`contextMenu element selecting 'Add to library' in context menu adds ele
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -139,7 +139,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -255,7 +255,7 @@ exports[`contextMenu element selecting 'Bring forward' in context menu brings el
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -282,7 +282,7 @@ exports[`contextMenu element selecting 'Bring forward' in context menu brings el
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -336,7 +336,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -374,7 +374,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -398,7 +398,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -436,7 +436,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -460,7 +460,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -576,7 +576,7 @@ exports[`contextMenu element selecting 'Bring to front' in context menu brings e
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -603,7 +603,7 @@ exports[`contextMenu element selecting 'Bring to front' in context menu brings e
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -657,7 +657,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -695,7 +695,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -719,7 +719,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -757,7 +757,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -781,7 +781,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -897,7 +897,7 @@ exports[`contextMenu element selecting 'Copy styles' in context menu copies styl
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -951,7 +951,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1065,7 +1065,7 @@ exports[`contextMenu element selecting 'Delete' in context menu deletes element:
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -1119,7 +1119,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1155,7 +1155,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1271,7 +1271,7 @@ exports[`contextMenu element selecting 'Duplicate' in context menu duplicates el
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -1298,7 +1298,7 @@ exports[`contextMenu element selecting 'Duplicate' in context menu duplicates el
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -1352,7 +1352,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1390,7 +1390,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1414,7 +1414,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1536,7 +1536,7 @@ exports[`contextMenu element selecting 'Group selection' in context menu groups
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [
     "id3",
@@ -1565,7 +1565,7 @@ exports[`contextMenu element selecting 'Group selection' in context menu groups
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [
     "id3",
@@ -1621,7 +1621,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1659,7 +1659,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1683,7 +1683,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1725,7 +1725,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [
             "id3",
@@ -1751,7 +1751,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [
             "id3",
@@ -1869,7 +1869,7 @@ exports[`contextMenu element selecting 'Paste styles' in context menu pastes sty
 Object {
   "angle": 0,
   "backgroundColor": "#e64980",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "cross-hatch",
   "groupIds": Array [],
   "height": 20,
@@ -1896,7 +1896,7 @@ exports[`contextMenu element selecting 'Paste styles' in context menu pastes sty
 Object {
   "angle": 0,
   "backgroundColor": "#e64980",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "cross-hatch",
   "groupIds": Array [],
   "height": 20,
@@ -1950,7 +1950,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -1988,7 +1988,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2012,7 +2012,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2050,7 +2050,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2074,7 +2074,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2112,7 +2112,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2136,7 +2136,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2174,7 +2174,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2198,7 +2198,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2236,7 +2236,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2260,7 +2260,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2298,7 +2298,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2322,7 +2322,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2360,7 +2360,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2384,7 +2384,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2422,7 +2422,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2446,7 +2446,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2484,7 +2484,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2508,7 +2508,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "#e64980",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "cross-hatch",
           "groupIds": Array [],
           "height": 20,
@@ -2624,7 +2624,7 @@ exports[`contextMenu element selecting 'Send backward' in context menu sends ele
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -2651,7 +2651,7 @@ exports[`contextMenu element selecting 'Send backward' in context menu sends ele
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -2705,7 +2705,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2743,7 +2743,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2767,7 +2767,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2805,7 +2805,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2829,7 +2829,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -2945,7 +2945,7 @@ exports[`contextMenu element selecting 'Send to back' in context menu sends elem
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -2972,7 +2972,7 @@ exports[`contextMenu element selecting 'Send to back' in context menu sends elem
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -3026,7 +3026,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3064,7 +3064,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3088,7 +3088,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3126,7 +3126,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3150,7 +3150,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3270,7 +3270,7 @@ exports[`contextMenu element selecting 'Ungroup selection' in context menu ungro
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -3297,7 +3297,7 @@ exports[`contextMenu element selecting 'Ungroup selection' in context menu ungro
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -3351,7 +3351,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3389,7 +3389,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3413,7 +3413,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3455,7 +3455,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [
             "id3",
@@ -3481,7 +3481,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [
             "id3",
@@ -3523,7 +3523,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3547,7 +3547,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,
@@ -3669,7 +3669,7 @@ exports[`contextMenu element shows 'Group selection' in context menu for multipl
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 10,
@@ -3696,7 +3696,7 @@ exports[`contextMenu element shows 'Group selection' in context menu for multipl
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 10,
@@ -3750,7 +3750,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 10,
@@ -3788,7 +3788,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 10,
@@ -3812,7 +3812,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 10,
@@ -3936,7 +3936,7 @@ exports[`contextMenu element shows 'Ungroup selection' in context menu for group
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [
     "id4",
@@ -3965,7 +3965,7 @@ exports[`contextMenu element shows 'Ungroup selection' in context menu for group
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [
     "id4",
@@ -4021,7 +4021,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 10,
@@ -4059,7 +4059,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 10,
@@ -4083,7 +4083,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 10,
@@ -4126,7 +4126,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [
             "id4",
@@ -4152,7 +4152,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [
             "id4",
@@ -4454,7 +4454,7 @@ exports[`contextMenu element shows context menu for element: [end of test] eleme
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 20,
@@ -4481,7 +4481,7 @@ exports[`contextMenu element shows context menu for element: [end of test] eleme
 Object {
   "angle": 0,
   "backgroundColor": "red",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 200,
@@ -4508,7 +4508,7 @@ exports[`contextMenu element shows context menu for element: [end of test] eleme
 Object {
   "angle": 0,
   "backgroundColor": "red",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 200,
@@ -4562,7 +4562,7 @@ Object {
         Object {
           "angle": 0,
           "backgroundColor": "transparent",
-          "boundElementIds": null,
+          "boundElements": null,
           "fillStyle": "hachure",
           "groupIds": Array [],
           "height": 20,

+ 5 - 5
src/tests/__snapshots__/dragCreate.test.tsx.snap

@@ -6,7 +6,7 @@ exports[`Test dragCreate add element to the scene when pointer dragging long eno
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": "arrow",
   "endBinding": null,
   "fillStyle": "hachure",
@@ -50,7 +50,7 @@ exports[`Test dragCreate add element to the scene when pointer dragging long eno
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -79,7 +79,7 @@ exports[`Test dragCreate add element to the scene when pointer dragging long eno
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -106,7 +106,7 @@ exports[`Test dragCreate add element to the scene when pointer dragging long eno
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": null,
   "endBinding": null,
   "fillStyle": "hachure",
@@ -150,7 +150,7 @@ exports[`Test dragCreate add element to the scene when pointer dragging long eno
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,

+ 14 - 8
src/tests/__snapshots__/move.test.tsx.snap

@@ -4,7 +4,7 @@ exports[`duplicate element on move when ALT is clicked rectangle 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -31,7 +31,7 @@ exports[`duplicate element on move when ALT is clicked rectangle 2`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -58,7 +58,7 @@ exports[`move element rectangle 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -85,8 +85,11 @@ exports[`move element rectangles with binding arrow 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": Array [
-    "id2",
+  "boundElements": Array [
+    Object {
+      "id": "id2",
+      "type": "arrow",
+    },
   ],
   "fillStyle": "hachure",
   "groupIds": Array [],
@@ -114,8 +117,11 @@ exports[`move element rectangles with binding arrow 2`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": Array [
-    "id2",
+  "boundElements": Array [
+    Object {
+      "id": "id2",
+      "type": "arrow",
+    },
   ],
   "fillStyle": "hachure",
   "groupIds": Array [],
@@ -143,7 +149,7 @@ exports[`move element rectangles with binding arrow 3`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": null,
   "endBinding": Object {
     "elementId": "id1",

+ 2 - 2
src/tests/__snapshots__/multiPointCreate.test.tsx.snap

@@ -4,7 +4,7 @@ exports[`multi point mode in linear elements arrow 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": "arrow",
   "endBinding": null,
   "fillStyle": "hachure",
@@ -53,7 +53,7 @@ exports[`multi point mode in linear elements line 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": null,
   "endBinding": null,
   "fillStyle": "hachure",

Різницю між файлами не показано, бо вона завелика
+ 112 - 112
src/tests/__snapshots__/regressionTests.test.tsx.snap


+ 5 - 5
src/tests/__snapshots__/selection.test.tsx.snap

@@ -4,7 +4,7 @@ exports[`select single element on the scene arrow 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": "arrow",
   "endBinding": null,
   "fillStyle": "hachure",
@@ -46,7 +46,7 @@ exports[`select single element on the scene arrow escape 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "endArrowhead": null,
   "endBinding": null,
   "fillStyle": "hachure",
@@ -88,7 +88,7 @@ exports[`select single element on the scene diamond 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -115,7 +115,7 @@ exports[`select single element on the scene ellipse 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,
@@ -142,7 +142,7 @@ exports[`select single element on the scene rectangle 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": null,
+  "boundElements": null,
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 50,

+ 9 - 9
src/tests/data/__snapshots__/restore.test.ts.snap

@@ -4,7 +4,7 @@ exports[`restoreElements should restore arrow element correctly 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "endArrowhead": null,
   "endBinding": null,
   "fillStyle": "hachure",
@@ -46,7 +46,7 @@ exports[`restoreElements should restore correctly with rectangle, ellipse and di
 Object {
   "angle": 0,
   "backgroundColor": "blue",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "fillStyle": "cross-hatch",
   "groupIds": Array [
     "1",
@@ -77,7 +77,7 @@ exports[`restoreElements should restore correctly with rectangle, ellipse and di
 Object {
   "angle": 0,
   "backgroundColor": "blue",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "fillStyle": "cross-hatch",
   "groupIds": Array [
     "1",
@@ -108,7 +108,7 @@ exports[`restoreElements should restore correctly with rectangle, ellipse and di
 Object {
   "angle": 0,
   "backgroundColor": "blue",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "fillStyle": "cross-hatch",
   "groupIds": Array [
     "1",
@@ -139,7 +139,7 @@ exports[`restoreElements should restore freedraw element correctly 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "fillStyle": "hachure",
   "groupIds": Array [],
   "height": 0,
@@ -170,7 +170,7 @@ exports[`restoreElements should restore line and draw elements correctly 1`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "endArrowhead": null,
   "endBinding": null,
   "fillStyle": "hachure",
@@ -212,7 +212,7 @@ exports[`restoreElements should restore line and draw elements correctly 2`] = `
 Object {
   "angle": 0,
   "backgroundColor": "transparent",
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "endArrowhead": null,
   "endBinding": null,
   "fillStyle": "hachure",
@@ -255,7 +255,7 @@ Object {
   "angle": 0,
   "backgroundColor": "transparent",
   "baseline": 0,
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "fillStyle": "hachure",
   "fontFamily": 1,
   "fontSize": 14,
@@ -288,7 +288,7 @@ Object {
   "angle": 0,
   "backgroundColor": "transparent",
   "baseline": 0,
-  "boundElementIds": Array [],
+  "boundElements": Array [],
   "fillStyle": "hachure",
   "fontFamily": 1,
   "fontSize": 10,

+ 1 - 1
src/tests/fixtures/elementFixture.ts

@@ -20,7 +20,7 @@ const elementBase: Omit<ExcalidrawElement, "type"> = {
   version: 120,
   versionNonce: 1188004276,
   isDeleted: false,
-  boundElementIds: null,
+  boundElements: null,
   updated: 1,
 };
 

+ 1 - 1
src/tests/scene/__snapshots__/export.test.ts.snap

@@ -74,7 +74,7 @@ exports[`exportToSvg with default arguments 1`] = `
 exports[`exportToSvg with exportEmbedScene 1`] = `
 "
   <!-- svg-source:excalidraw -->
-  <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1SsW7CMFx1MDAxMN35ishdkUjSQChcdTAwMWItVVWpalx1MDAwN1x1MDAwNqRWXHUwMDFkTHxJLIxtbFx1MDAwN4hcdTAwMTD/XtuBpI26dK9cdTAwMDdL9/ze3fnunVx1MDAwNkGATC1cdTAwMDHNXHUwMDAyXHUwMDA0x1xmM0pcdTAwMTQ+oKHD96A0XHUwMDE13D7FPtaiUplnlsbI2WjEhFx1MDAxNZRCm4ZcdTAwMGZcZrbAjbaMXHUwMDBmXHUwMDFiXHUwMDA3wcnf9oVcdTAwMTKn2q/U7m2ebygn8S7bpi+L+dO7l3rS0XKSKGnj2lx1MDAxNb5N2/hAiSktXHUwMDE2hWGLlUCL0vRAzFx1MDAwYuba7Fx1MDAxMG2U2MCDYEK5Rm5Cf7rSa5xtXG4lKk46TjTGeJ13nJwytjQ1a1x1MDAwNoCzslKAelx1MDAxNVbXXHUwMDE2e3ir08JcdTAwMGW4U9mSRclB61x1MDAxZlx1MDAxYSFxRk3d+5XrTz5cdTAwMTM/3c9+/lx1MDAxMit5yYO0XHUwMDBivnVcdTAwMDZAfKokmozTu3DavnT7jeKwj75cbu53XHUwMDFkRdNpXHUwMDE4JnE6aVx1MDAxOVQv7KqNT5tjpqGbo1x1MDAxYuFjY4OmVV4x1j5XkuBG1n32aj5C8VZwgjx+XHUwMDFl/vvn3z9/8lx1MDAwZjBGpYaLf+zt/4iwlEtjRZbSuFx07SlcdTAwMWPuf9lX7o/Te/e5fYHr4HRcdTAwMWWcv1x1MDAwMKlcdFItIn0=<!-- payload-end -->
+  <!-- payload-type:application/vnd.excalidraw+json --><!-- payload-version:2 --><!-- payload-start -->eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO1STU9cdTAwMDMhXHUwMDEwvfdXbPDapLtrv+ytWmNMjFx1MDAxZXpoovFAl9mFlFx1MDAwMlx1MDAwNbZcdTAwMWZp+t9cdTAwMDXaLrrx4l1cdTAwMGUk83hvZph5x06SIHtQgCZcdIJ9gTkjXHUwMDFh71DX41vQhknhnvJcdTAwMTBcdTAwMWJZ61wiMKm1atLrcelcdTAwMDRUXHUwMDFhe+ZcdTAwMDOHNVxia1x1MDAxY+PDxUlyXGa3e2HEq7ZcdTAwMGK9eZuWKyZIvinWo5fZ9Ok9SFx1MDAwM2nvOP2s38RcdTAwMDdf+HbUxDtGLHVYlqZcckaBVdS2QCwq7tuMiLFaruBBcql9IzdpOLH0XHUwMDEyXHUwMDE3q0rLWpDIyVx1MDAwNlx1MDAxOC/LyClcdTAwMTnnc3vg51x1MDAwMeCC1lx1MDAxYVCrwuLaYlx1MDAwYm90RrpcdTAwMDFHlStZUVx1MDAwMcb80EiFXHUwMDBiZlx1MDAwZq1f+f7UM1x00/1s56dYq0tcdTAwMWVkfPCtM1x1MDAwMFx1MDAxMlL1s+FgdJeOm5e43yxP2+irXHUwMDE0YddZNlx1MDAxZadpP1x1MDAxZlxyXHUwMDFiXHUwMDA2MzO3alx1MDAxYtKWmFx1MDAxYohz9CN8jDZcdTAwMTA1581jrVxiPoviV6/WI1xmr6UgKOCn7r97/t3zXHUwMDA391x1MDAwMOdMXHUwMDE5uLjH3eGHXGIrNbdO5ChnL6Etg939L9sqw/H64D2/LfBcdTAwMWRcdTAwMWNPndNcdTAwMTfZZ1DTIn0=<!-- payload-end -->
   <defs>
     <style>
       @font-face {

Деякі файли не було показано, через те що забагато файлів було змінено