@zsviczian/excalidraw 0.17.1-obsidian-28 → 0.17.1-obsidian-29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -760,7 +760,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
760
760
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
761
761
|
|
|
762
762
|
"use strict";
|
|
763
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"trackEvent\": () => (/* binding */ trackEvent)\n/* harmony export */ });\n// place here categories that you want to track. We want to track just a\n// small subset of categories at a given time.\nconst ALLOWED_CATEGORIES_TO_TRACK = [\"ai\", \"command_palette\"];\nconst trackEvent = (category, action, label, value) => {\n try {\n // prettier-ignore\n if (typeof window === \"undefined\" || ({\"VITE_APP_BACKEND_V2_GET_URL\":\"https://json-dev.excalidraw.com/api/v2/\",\"VITE_APP_BACKEND_V2_POST_URL\":\"https://json-dev.excalidraw.com/api/v2/post/\",\"VITE_APP_LIBRARY_URL\":\"https://libraries.excalidraw.com\",\"VITE_APP_LIBRARY_BACKEND\":\"https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries\",\"VITE_APP_WS_SERVER_URL\":\"http://localhost:3002\",\"VITE_APP_PLUS_LP\":\"https://plus.excalidraw.com\",\"VITE_APP_PLUS_APP\":\"https://app.excalidraw.com\",\"VITE_APP_AI_BACKEND\":\"http://localhost:3015\",\"VITE_APP_FIREBASE_CONFIG\":\"{\\\"apiKey\\\":\\\"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8\\\",\\\"authDomain\\\":\\\"excalidraw-oss-dev.firebaseapp.com\\\",\\\"projectId\\\":\\\"excalidraw-oss-dev\\\",\\\"storageBucket\\\":\\\"excalidraw-oss-dev.appspot.com\\\",\\\"messagingSenderId\\\":\\\"664559512677\\\",\\\"appId\\\":\\\"1:664559512677:web:a385181f2928d328a7aa8c\\\"}\",\"VITE_APP_DEV_ENABLE_SW\":\"\",\"VITE_APP_DEV_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_DISABLE_TRACKING\":\"true\",\"FAST_REFRESH\":\"false\",\"VITE_APP_PORT\":\"3000\",\"VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX\":\"\",\"VITE_APP_COLLAPSE_OVERLAY\":\"true\",\"VITE_APP_ENABLE_ESLINT\":\"true\",\"VITE_PKG_NAME\":\"@zsviczian/excalidraw\",\"VITE_PKG_VERSION\":\"0.17.1-obsidian-
|
|
763
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"trackEvent\": () => (/* binding */ trackEvent)\n/* harmony export */ });\n// place here categories that you want to track. We want to track just a\n// small subset of categories at a given time.\nconst ALLOWED_CATEGORIES_TO_TRACK = [\"ai\", \"command_palette\"];\nconst trackEvent = (category, action, label, value) => {\n try {\n // prettier-ignore\n if (typeof window === \"undefined\" || ({\"VITE_APP_BACKEND_V2_GET_URL\":\"https://json-dev.excalidraw.com/api/v2/\",\"VITE_APP_BACKEND_V2_POST_URL\":\"https://json-dev.excalidraw.com/api/v2/post/\",\"VITE_APP_LIBRARY_URL\":\"https://libraries.excalidraw.com\",\"VITE_APP_LIBRARY_BACKEND\":\"https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries\",\"VITE_APP_WS_SERVER_URL\":\"http://localhost:3002\",\"VITE_APP_PLUS_LP\":\"https://plus.excalidraw.com\",\"VITE_APP_PLUS_APP\":\"https://app.excalidraw.com\",\"VITE_APP_AI_BACKEND\":\"http://localhost:3015\",\"VITE_APP_FIREBASE_CONFIG\":\"{\\\"apiKey\\\":\\\"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8\\\",\\\"authDomain\\\":\\\"excalidraw-oss-dev.firebaseapp.com\\\",\\\"projectId\\\":\\\"excalidraw-oss-dev\\\",\\\"storageBucket\\\":\\\"excalidraw-oss-dev.appspot.com\\\",\\\"messagingSenderId\\\":\\\"664559512677\\\",\\\"appId\\\":\\\"1:664559512677:web:a385181f2928d328a7aa8c\\\"}\",\"VITE_APP_DEV_ENABLE_SW\":\"\",\"VITE_APP_DEV_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_DISABLE_TRACKING\":\"true\",\"FAST_REFRESH\":\"false\",\"VITE_APP_PORT\":\"3000\",\"VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX\":\"\",\"VITE_APP_COLLAPSE_OVERLAY\":\"true\",\"VITE_APP_ENABLE_ESLINT\":\"true\",\"VITE_PKG_NAME\":\"@zsviczian/excalidraw\",\"VITE_PKG_VERSION\":\"0.17.1-obsidian-28\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).VITE_WORKER_ID // comment out to debug locally\n || \"development\" === \"production\") {\n return;\n }\n\n if (!ALLOWED_CATEGORIES_TO_TRACK.includes(category)) {\n return;\n }\n\n if (true) {\n console.info(\"trackEvent\", {\n category,\n action,\n label,\n value\n });\n }\n\n if (window.sa_event) {\n window.sa_event(action, {\n category,\n label,\n value\n });\n }\n } catch (error) {\n console.error(\"error during analytics\", error);\n }\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./analytics.ts?");
|
|
764
764
|
|
|
765
765
|
/***/ }),
|
|
766
766
|
|
|
@@ -2575,7 +2575,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2575
2575
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2576
2576
|
|
|
2577
2577
|
"use strict";
|
|
2578
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"AllowedExcalidrawActiveTools\": () => (/* binding */ AllowedExcalidrawActiveTools),\n/* harmony export */ \"restore\": () => (/* binding */ restore),\n/* harmony export */ \"restoreAppState\": () => (/* binding */ restoreAppState),\n/* harmony export */ \"restoreElements\": () => (/* binding */ restoreElements),\n/* harmony export */ \"restoreLibraryItems\": () => (/* binding */ restoreLibraryItems)\n/* harmony export */ });\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element/typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _random__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../random */ \"./random.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../element/linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../element/mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _url__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./url */ \"./data/url.ts\");\n/* harmony import */ var _fractionalIndex__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../fractionalIndex */ \"./fractionalIndex.ts\");\n/* harmony import */ var _points__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../points */ \"./points.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst AllowedExcalidrawActiveTools = {\n selection: true,\n text: true,\n rectangle: true,\n diamond: true,\n ellipse: true,\n line: true,\n image: true,\n arrow: true,\n freedraw: true,\n eraser: false,\n custom: true,\n frame: true,\n embeddable: true,\n hand: true,\n mermaid: true,\n laser: false,\n magicframe: false\n};\n\nconst getFontFamilyByName = fontFamilyName => {\n if (Object.keys(_constants__WEBPACK_IMPORTED_MODULE_3__.FONT_FAMILY).includes(fontFamilyName)) {\n return _constants__WEBPACK_IMPORTED_MODULE_3__.FONT_FAMILY[fontFamilyName];\n }\n\n return _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_FONT_FAMILY;\n};\n\nconst repairBinding = binding => {\n if (!binding) {\n return null;\n }\n\n return Object.assign(Object.assign({}, binding), {\n focus: binding.focus || 0\n });\n};\n\nconst restoreElementWithProperties = (element, extra) => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;\n\n const base = {\n type: extra.type || element.type,\n // all elements must have version > 0 so getSceneVersion() will pick up\n // newly added elements\n version: element.version || 1,\n versionNonce: (_a = element.versionNonce) !== null && _a !== void 0 ? _a : 0,\n index: (_b = element.index) !== null && _b !== void 0 ? _b : null,\n isDeleted: (_c = element.isDeleted) !== null && _c !== void 0 ? _c : false,\n id: element.id || (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)(),\n fillStyle: element.fillStyle || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.fillStyle,\n strokeWidth: element.strokeWidth || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.strokeWidth,\n strokeStyle: (_d = element.strokeStyle) !== null && _d !== void 0 ? _d : _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.strokeStyle,\n roughness: (_e = element.roughness) !== null && _e !== void 0 ? _e : _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.roughness,\n opacity: element.opacity == null ? _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.opacity : element.opacity,\n angle: element.angle || 0,\n x: (_g = (_f = extra.x) !== null && _f !== void 0 ? _f : element.x) !== null && _g !== void 0 ? _g : 0,\n y: (_j = (_h = extra.y) !== null && _h !== void 0 ? _h : element.y) !== null && _j !== void 0 ? _j : 0,\n strokeColor: element.strokeColor || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.strokeColor,\n backgroundColor: element.backgroundColor || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.backgroundColor,\n width: element.width || 0,\n height: element.height || 0,\n seed: (_k = element.seed) !== null && _k !== void 0 ? _k : 1,\n groupIds: (_l = element.groupIds) !== null && _l !== void 0 ? _l : [],\n frameId: (_m = element.frameId) !== null && _m !== void 0 ? _m : null,\n roundness: element.roundness ? element.roundness : element.strokeSharpness === \"round\" && element.type !== \"image\" ? {\n // for old elements that would now use adaptive radius algo,\n // use legacy algo instead\n type: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isUsingAdaptiveRadius)(element.type) ? _constants__WEBPACK_IMPORTED_MODULE_3__.ROUNDNESS.LEGACY : _constants__WEBPACK_IMPORTED_MODULE_3__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null,\n boundElements: element.boundElementIds ? element.boundElementIds.map(id => ({\n type: \"arrow\",\n id\n })) : (_o = element.boundElements) !== null && _o !== void 0 ? _o : [],\n updated: (_p = element.updated) !== null && _p !== void 0 ? _p : (0,_utils__WEBPACK_IMPORTED_MODULE_7__.getUpdatedTimestamp)(),\n link: element.link ? (0,_url__WEBPACK_IMPORTED_MODULE_9__.normalizeLink)(element.link) : null,\n locked: (_q = element.locked) !== null && _q !== void 0 ? _q : false\n };\n\n if (\"customData\" in element || \"customData\" in extra) {\n base.customData = \"customData\" in extra ? extra.customData : element.customData;\n }\n\n return Object.assign(Object.assign(Object.assign({}, base), (0,_element__WEBPACK_IMPORTED_MODULE_0__.getNormalizedDimensions)(base)), extra);\n};\n\nconst restoreElement = element => {\n var _a, _b, _c, _d, _e;\n\n switch (element.type) {\n case \"text\":\n let fontSize = element.fontSize;\n let fontFamily = element.fontFamily;\n\n if (\"font\" in element) {\n const [fontPx, _fontFamily] = element.font.split(\" \");\n fontSize = parseFloat(fontPx);\n fontFamily = getFontFamilyByName(_fontFamily);\n }\n\n const text = typeof element.text === \"string\" && element.text || \"\"; // line-height might not be specified either when creating elements\n // programmatically, or when importing old diagrams.\n // For the latter we want to detect the original line height which\n // will likely differ from our per-font fixed line height we now use,\n // to maintain backward compatibility.\n\n const lineHeight = element.lineHeight || (element.height ? // detect line-height from current element height and font-size\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_8__.detectLineHeight)(element) : // no element height likely means programmatic use, so default\n // to a fixed line height\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_8__.getDefaultLineHeight)(element.fontFamily));\n element = restoreElementWithProperties(element, {\n fontSize,\n fontFamily,\n text,\n rawText: (_a = element.rawText) !== null && _a !== void 0 ? _a : \"\",\n textAlign: element.textAlign || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_TEXT_ALIGN,\n verticalAlign: element.verticalAlign || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_VERTICAL_ALIGN,\n containerId: (_b = element.containerId) !== null && _b !== void 0 ? _b : null,\n originalText: element.originalText || text,\n autoResize: (_c = element.autoResize) !== null && _c !== void 0 ? _c : true,\n lineHeight\n }); // if empty text, mark as deleted. We keep in array\n // for data integrity purposes (collab etc.)\n\n if (!text && !element.isDeleted) {\n element = Object.assign(Object.assign({}, element), {\n originalText: text,\n isDeleted: true\n });\n element = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_6__.bumpVersion)(element);\n }\n\n return element;\n\n case \"freedraw\":\n {\n return restoreElementWithProperties(element, {\n points: element.points,\n lastCommittedPoint: null,\n simulatePressure: element.simulatePressure,\n pressures: element.pressures\n });\n }\n\n case \"image\":\n return restoreElementWithProperties(element, {\n status: element.status || \"pending\",\n fileId: element.fileId,\n scale: element.scale || [1, 1]\n });\n\n case \"line\": // @ts-ignore LEGACY type\n // eslint-disable-next-line no-fallthrough\n\n case \"draw\":\n case \"arrow\":\n {\n const {\n startArrowhead = null,\n endArrowhead = element.type === \"arrow\" ? \"arrow\" : null\n } = element;\n let x = element.x;\n let y = element.y;\n let points = // migrate old arrow model to new one\n !Array.isArray(element.points) || element.points.length < 2 ? [[0, 0], [element.width, element.height]] : element.points;\n\n if (points[0][0] !== 0 || points[0][1] !== 0) {\n ({\n points,\n x,\n y\n } = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getNormalizedPoints(element));\n }\n\n return restoreElementWithProperties(element, Object.assign({\n type: element.type === \"draw\" ? \"line\" : element.type,\n startBinding: repairBinding(element.startBinding),\n endBinding: repairBinding(element.endBinding),\n lastCommittedPoint: null,\n startArrowhead,\n endArrowhead,\n points,\n x,\n y\n }, (0,_points__WEBPACK_IMPORTED_MODULE_11__.getSizeFromPoints)(points)));\n }\n // generic elements\n\n case \"ellipse\":\n case \"rectangle\":\n case \"diamond\":\n return restoreElementWithProperties(element, {});\n\n case \"iframe\": //zsviczian\n\n case \"embeddable\":\n return restoreElementWithProperties(element, {\n scale: (_d = element.scale) !== null && _d !== void 0 ? _d : [1, 1] //zsviczian\n\n });\n\n case \"magicframe\":\n case \"frame\":\n return restoreElementWithProperties(element, {\n name: (_e = element.name) !== null && _e !== void 0 ? _e : null\n });\n // Don't use default case so as to catch a missing an element type case.\n // We also don't want to throw, but instead return void so we filter\n // out these unsupported elements from the restored array.\n }\n\n return null;\n};\n/**\r\n * Repairs container element's boundElements array by removing duplicates and\r\n * fixing containerId of bound elements if not present. Also removes any\r\n * bound elements that do not exist in the elements array.\r\n *\r\n * NOTE mutates elements.\r\n */\n\n\nconst repairContainerElement = (container, elementsMap) => {\n if (container.boundElements) {\n // copy because we're not cloning on restore, and we don't want to mutate upstream\n const boundElements = container.boundElements.slice(); // dedupe bindings & fix boundElement.containerId if not set already\n\n const boundIds = new Set();\n container.boundElements = boundElements.reduce((acc, binding) => {\n const boundElement = elementsMap.get(binding.id);\n\n if (boundElement && !boundIds.has(binding.id)) {\n boundIds.add(binding.id);\n\n if (boundElement.isDeleted) {\n return acc;\n }\n\n acc.push(binding);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(boundElement) && // being slightly conservative here, preserving existing containerId\n // if defined, lest boundElements is stale\n !boundElement.containerId) {\n boundElement.containerId = container.id;\n }\n }\n\n return acc;\n }, []);\n }\n};\n/**\r\n * Repairs target bound element's container's boundElements array,\r\n * or removes contaienrId if container does not exist.\r\n *\r\n * NOTE mutates elements.\r\n */\n\n\nconst repairBoundElement = (boundElement, elementsMap) => {\n const container = boundElement.containerId ? elementsMap.get(boundElement.containerId) : null;\n\n if (!container) {\n boundElement.containerId = null;\n return;\n }\n\n if (boundElement.isDeleted) {\n return;\n }\n\n if (container.boundElements && !container.boundElements.find(binding => binding.id === boundElement.id)) {\n // copy because we're not cloning on restore, and we don't want to mutate upstream\n const boundElements = (container.boundElements || (container.boundElements = [])).slice();\n boundElements.push({\n type: \"text\",\n id: boundElement.id\n });\n container.boundElements = boundElements;\n }\n};\n/**\r\n * Remove an element's frameId if its containing frame is non-existent\r\n *\r\n * NOTE mutates elements.\r\n */\n\n\nconst repairFrameMembership = (element, elementsMap) => {\n if (element.frameId) {\n const containingFrame = elementsMap.get(element.frameId);\n\n if (!containingFrame) {\n element.frameId = null;\n }\n }\n};\n\nconst restoreElements = (elements,\n/** NOTE doesn't serve for reconciliation */\nlocalElements, opts) => {\n // used to detect duplicate top-level element ids\n const existingIds = new Set();\n const localElementsMap = localElements ? (0,_utils__WEBPACK_IMPORTED_MODULE_7__.arrayToMap)(localElements) : null;\n const restoredElements = (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_10__.syncInvalidIndices)((elements || []).reduce((elements, element) => {\n // filtering out selection, which is legacy, no longer kept in elements,\n // and causing issues if retained\n if (element.type !== \"selection\" && !(0,_element__WEBPACK_IMPORTED_MODULE_0__.isInvisiblySmallElement)(element)) {\n let migratedElement = restoreElement(element);\n\n if (migratedElement) {\n const localElement = localElementsMap === null || localElementsMap === void 0 ? void 0 : localElementsMap.get(element.id);\n\n if (localElement && localElement.version > migratedElement.version) {\n migratedElement = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_6__.bumpVersion)(migratedElement, localElement.version);\n }\n\n if (existingIds.has(migratedElement.id)) {\n migratedElement = Object.assign(Object.assign({}, migratedElement), {\n id: (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)()\n });\n }\n\n existingIds.add(migratedElement.id);\n elements.push(migratedElement);\n }\n }\n\n return elements;\n }, []));\n\n if (!(opts === null || opts === void 0 ? void 0 : opts.repairBindings)) {\n return restoredElements;\n } // repair binding. Mutates elements.\n\n\n const restoredElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_7__.arrayToMap)(restoredElements);\n\n for (const element of restoredElements) {\n if (element.frameId) {\n repairFrameMembership(element, restoredElementsMap);\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element) && element.containerId) {\n repairBoundElement(element, restoredElementsMap);\n } else if (element.boundElements) {\n repairContainerElement(element, restoredElementsMap);\n }\n\n if (opts.refreshDimensions && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n Object.assign(element, (0,_element__WEBPACK_IMPORTED_MODULE_0__.refreshTextDimensions)(element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_8__.getContainerElement)(element, restoredElementsMap), restoredElementsMap));\n }\n }\n\n return restoredElements;\n};\n\nconst coalesceAppStateValue = (key, appState, defaultAppState) => {\n const value = appState[key]; // NOTE the value! assertion is needed in TS 4.5.5 (fixed in newer versions)\n\n return value !== undefined ? value : defaultAppState[key];\n};\n\nconst LegacyAppStateMigrations = {\n isSidebarDocked: (appState, defaultAppState) => {\n var _a;\n\n return [\"defaultSidebarDockedPreference\", (_a = appState.isSidebarDocked) !== null && _a !== void 0 ? _a : coalesceAppStateValue(\"defaultSidebarDockedPreference\", appState, defaultAppState)];\n }\n};\nconst restoreAppState = (appState, localAppState) => {\n var _a, _b, _c, _d;\n\n appState = appState || {};\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_4__.getDefaultAppState)();\n const nextAppState = {}; // first, migrate all legacy AppState properties to new ones. We do it\n // in one go before migrate the rest of the properties in case the new ones\n // depend on checking any other key (i.e. they are coupled)\n\n for (const legacyKey of Object.keys(LegacyAppStateMigrations)) {\n if (legacyKey in appState) {\n const [nextKey, nextValue] = LegacyAppStateMigrations[legacyKey](appState, defaultAppState);\n nextAppState[nextKey] = nextValue;\n }\n }\n\n for (const [key, defaultValue] of Object.entries(defaultAppState)) {\n // if AppState contains a legacy key, prefer that one and migrate its\n // value to the new one\n const suppliedValue = appState[key];\n const localValue = localAppState ? localAppState[key] : undefined;\n nextAppState[key] = suppliedValue !== undefined ? suppliedValue : localValue !== undefined ? localValue : defaultValue;\n }\n\n return Object.assign(Object.assign({}, nextAppState), {\n cursorButton: (localAppState === null || localAppState === void 0 ? void 0 : localAppState.cursorButton) || \"up\",\n // reset on fresh restore so as to hide the UI button if penMode not active\n penDetected: (_a = localAppState === null || localAppState === void 0 ? void 0 : localAppState.penDetected) !== null && _a !== void 0 ? _a : appState.penMode ? (_b = appState.penDetected) !== null && _b !== void 0 ? _b : false : false,\n activeTool: Object.assign(Object.assign({}, (0,_utils__WEBPACK_IMPORTED_MODULE_7__.updateActiveTool)(defaultAppState, nextAppState.activeTool.type && AllowedExcalidrawActiveTools[nextAppState.activeTool.type] ? nextAppState.activeTool : {\n type: \"selection\"\n })), {\n lastActiveTool: null,\n locked: (_c = nextAppState.activeTool.locked) !== null && _c !== void 0 ? _c : false\n }),\n // Migrates from previous version where appState.zoom was a number\n zoom: typeof appState.zoom === \"number\" ? {\n value: appState.zoom\n } : ((_d = appState.zoom) === null || _d === void 0 ? void 0 : _d.value) ? appState.zoom : defaultAppState.zoom,\n openSidebar: // string (legacy)\n typeof appState.openSidebar === \"string\" ? {\n name: _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.name\n } : nextAppState.openSidebar\n });\n};\nconst restore = (data,\n/**\r\n * Local AppState (`this.state` or initial state from localStorage) so that we\r\n * don't overwrite local state with default values (when values not\r\n * explicitly specified).\r\n * Supply `null` if you can't get access to it.\r\n */\nlocalAppState, localElements, elementsConfig) => {\n return {\n elements: restoreElements(data === null || data === void 0 ? void 0 : data.elements, localElements, elementsConfig),\n appState: restoreAppState(data === null || data === void 0 ? void 0 : data.appState, localAppState || null),\n files: (data === null || data === void 0 ? void 0 : data.files) || {}\n };\n};\n\nconst restoreLibraryItem = libraryItem => {\n const elements = restoreElements((0,_element__WEBPACK_IMPORTED_MODULE_0__.getNonDeletedElements)(libraryItem.elements), null);\n return elements.length ? Object.assign(Object.assign({}, libraryItem), {\n elements\n }) : null;\n};\n\nconst restoreLibraryItems = (libraryItems = [], defaultStatus) => {\n const restoredItems = [];\n\n for (const item of libraryItems) {\n // migrate older libraries\n if (Array.isArray(item)) {\n const restoredItem = restoreLibraryItem({\n status: defaultStatus,\n elements: item,\n id: (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)(),\n created: Date.now()\n });\n\n if (restoredItem) {\n restoredItems.push(restoredItem);\n }\n } else {\n const _item = item;\n const restoredItem = restoreLibraryItem(Object.assign(Object.assign({}, _item), {\n id: _item.id || (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)(),\n status: _item.status || defaultStatus,\n created: _item.created || Date.now()\n }));\n\n if (restoredItem) {\n restoredItems.push(restoredItem);\n }\n }\n }\n\n return restoredItems;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./data/restore.ts?");
|
|
2578
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"AllowedExcalidrawActiveTools\": () => (/* binding */ AllowedExcalidrawActiveTools),\n/* harmony export */ \"restore\": () => (/* binding */ restore),\n/* harmony export */ \"restoreAppState\": () => (/* binding */ restoreAppState),\n/* harmony export */ \"restoreElements\": () => (/* binding */ restoreElements),\n/* harmony export */ \"restoreLibraryItems\": () => (/* binding */ restoreLibraryItems)\n/* harmony export */ });\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element/typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _random__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../random */ \"./random.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../element/linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../element/mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _url__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./url */ \"./data/url.ts\");\n/* harmony import */ var _fractionalIndex__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../fractionalIndex */ \"./fractionalIndex.ts\");\n/* harmony import */ var _points__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../points */ \"./points.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst AllowedExcalidrawActiveTools = {\n selection: true,\n text: true,\n rectangle: true,\n diamond: true,\n ellipse: true,\n line: true,\n image: true,\n arrow: true,\n freedraw: true,\n eraser: false,\n custom: true,\n frame: true,\n embeddable: true,\n hand: true,\n mermaid: true,\n laser: false,\n magicframe: false\n};\n\nconst getFontFamilyByName = fontFamilyName => {\n if (Object.keys(_constants__WEBPACK_IMPORTED_MODULE_3__.FONT_FAMILY).includes(fontFamilyName)) {\n return _constants__WEBPACK_IMPORTED_MODULE_3__.FONT_FAMILY[fontFamilyName];\n }\n\n return _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_FONT_FAMILY;\n};\n\nconst repairBinding = binding => {\n if (!binding) {\n return null;\n }\n\n return Object.assign(Object.assign({}, binding), {\n focus: binding.focus || 0\n });\n};\n\nconst restoreElementWithProperties = (element, extra) => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;\n\n const base = {\n type: extra.type || element.type,\n // all elements must have version > 0 so getSceneVersion() will pick up\n // newly added elements\n version: element.version || 1,\n versionNonce: (_a = element.versionNonce) !== null && _a !== void 0 ? _a : 0,\n index: (_b = element.index) !== null && _b !== void 0 ? _b : null,\n isDeleted: (_c = element.isDeleted) !== null && _c !== void 0 ? _c : false,\n id: element.id || (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)(),\n fillStyle: element.fillStyle || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.fillStyle,\n strokeWidth: element.strokeWidth || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.strokeWidth,\n strokeStyle: (_d = element.strokeStyle) !== null && _d !== void 0 ? _d : _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.strokeStyle,\n roughness: (_e = element.roughness) !== null && _e !== void 0 ? _e : _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.roughness,\n opacity: element.opacity == null ? _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.opacity : element.opacity,\n angle: element.angle || 0,\n x: (_g = (_f = extra.x) !== null && _f !== void 0 ? _f : element.x) !== null && _g !== void 0 ? _g : 0,\n y: (_j = (_h = extra.y) !== null && _h !== void 0 ? _h : element.y) !== null && _j !== void 0 ? _j : 0,\n strokeColor: element.strokeColor || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.strokeColor,\n backgroundColor: element.backgroundColor || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_ELEMENT_PROPS.backgroundColor,\n width: element.width || 0,\n height: element.height || 0,\n seed: (_k = element.seed) !== null && _k !== void 0 ? _k : 1,\n groupIds: (_l = element.groupIds) !== null && _l !== void 0 ? _l : [],\n frameId: (_m = element.frameId) !== null && _m !== void 0 ? _m : null,\n roundness: element.roundness ? element.roundness : element.strokeSharpness === \"round\" && element.type !== \"image\" ? {\n // for old elements that would now use adaptive radius algo,\n // use legacy algo instead\n type: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isUsingAdaptiveRadius)(element.type) ? _constants__WEBPACK_IMPORTED_MODULE_3__.ROUNDNESS.LEGACY : _constants__WEBPACK_IMPORTED_MODULE_3__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null,\n boundElements: element.boundElementIds ? element.boundElementIds.map(id => ({\n type: \"arrow\",\n id\n })) : (_o = element.boundElements) !== null && _o !== void 0 ? _o : [],\n updated: (_p = element.updated) !== null && _p !== void 0 ? _p : (0,_utils__WEBPACK_IMPORTED_MODULE_7__.getUpdatedTimestamp)(),\n link: element.link ? (0,_url__WEBPACK_IMPORTED_MODULE_9__.normalizeLink)(element.link) : null,\n locked: (_q = element.locked) !== null && _q !== void 0 ? _q : false\n };\n\n if (\"customData\" in element || \"customData\" in extra) {\n base.customData = \"customData\" in extra ? extra.customData : element.customData;\n }\n\n return Object.assign(Object.assign(Object.assign({}, base), (0,_element__WEBPACK_IMPORTED_MODULE_0__.getNormalizedDimensions)(base)), extra);\n};\n\nconst restoreElement = element => {\n var _a, _b, _c, _d, _e;\n\n switch (element.type) {\n case \"text\":\n let fontSize = element.fontSize;\n let fontFamily = element.fontFamily;\n\n if (\"font\" in element) {\n const [fontPx, _fontFamily] = element.font.split(\" \");\n fontSize = parseFloat(fontPx);\n fontFamily = getFontFamilyByName(_fontFamily);\n }\n\n const text = typeof element.text === \"string\" && element.text || \"\"; // line-height might not be specified either when creating elements\n // programmatically, or when importing old diagrams.\n // For the latter we want to detect the original line height which\n // will likely differ from our per-font fixed line height we now use,\n // to maintain backward compatibility.\n\n const lineHeight = element.lineHeight || (element.height ? // detect line-height from current element height and font-size\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_8__.detectLineHeight)(element) : // no element height likely means programmatic use, so default\n // to a fixed line height\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_8__.getDefaultLineHeight)(element.fontFamily));\n element = restoreElementWithProperties(element, {\n fontSize,\n fontFamily,\n text,\n rawText: (_a = element.rawText) !== null && _a !== void 0 ? _a : \"\",\n textAlign: element.textAlign || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_TEXT_ALIGN,\n verticalAlign: element.verticalAlign || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_VERTICAL_ALIGN,\n containerId: (_b = element.containerId) !== null && _b !== void 0 ? _b : null,\n originalText: element.originalText || text,\n autoResize: (_c = element.autoResize) !== null && _c !== void 0 ? _c : true,\n lineHeight\n }); // if empty text, mark as deleted. We keep in array\n // for data integrity purposes (collab etc.)\n\n if (!text && !element.isDeleted) {\n element = Object.assign(Object.assign({}, element), {\n originalText: text,\n isDeleted: true\n });\n element = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_6__.bumpVersion)(element);\n }\n\n return element;\n\n case \"freedraw\":\n {\n return restoreElementWithProperties(element, {\n points: element.points,\n lastCommittedPoint: null,\n simulatePressure: element.simulatePressure,\n pressures: element.pressures\n });\n }\n\n case \"image\":\n return restoreElementWithProperties(element, {\n status: element.status || \"pending\",\n fileId: element.fileId,\n scale: element.scale || [1, 1]\n });\n\n case \"line\": // @ts-ignore LEGACY type\n // eslint-disable-next-line no-fallthrough\n\n case \"draw\":\n case \"arrow\":\n {\n const {\n startArrowhead = null,\n endArrowhead = element.type === \"arrow\" ? \"arrow\" : null\n } = element;\n let x = element.x;\n let y = element.y;\n let points = // migrate old arrow model to new one\n !Array.isArray(element.points) || element.points.length < 2 ? [[0, 0], [element.width, element.height]] : element.points;\n\n if (points[0][0] !== 0 || points[0][1] !== 0) {\n ({\n points,\n x,\n y\n } = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getNormalizedPoints(element));\n }\n\n return restoreElementWithProperties(element, Object.assign({\n type: element.type === \"draw\" ? \"line\" : element.type,\n startBinding: repairBinding(element.startBinding),\n endBinding: repairBinding(element.endBinding),\n lastCommittedPoint: null,\n startArrowhead,\n endArrowhead,\n points,\n x,\n y\n }, (0,_points__WEBPACK_IMPORTED_MODULE_11__.getSizeFromPoints)(points)));\n }\n // generic elements\n\n case \"ellipse\":\n case \"rectangle\":\n case \"diamond\":\n return restoreElementWithProperties(element, {});\n\n case \"iframe\": //zsviczian\n\n case \"embeddable\":\n return restoreElementWithProperties(element, {\n scale: (_d = element.scale) !== null && _d !== void 0 ? _d : [1, 1] //zsviczian\n\n });\n\n case \"magicframe\":\n case \"frame\":\n return restoreElementWithProperties(element, {\n name: (_e = element.name) !== null && _e !== void 0 ? _e : null\n });\n // Don't use default case so as to catch a missing an element type case.\n // We also don't want to throw, but instead return void so we filter\n // out these unsupported elements from the restored array.\n }\n\n return null;\n};\n/**\r\n * Repairs container element's boundElements array by removing duplicates and\r\n * fixing containerId of bound elements if not present. Also removes any\r\n * bound elements that do not exist in the elements array.\r\n *\r\n * NOTE mutates elements.\r\n */\n\n\nconst repairContainerElement = (container, elementsMap) => {\n if (container.boundElements) {\n // copy because we're not cloning on restore, and we don't want to mutate upstream\n const boundElements = container.boundElements.slice(); // dedupe bindings & fix boundElement.containerId if not set already\n\n const boundIds = new Set();\n container.boundElements = boundElements.reduce((acc, binding) => {\n const boundElement = elementsMap.get(binding.id);\n\n if (boundElement && !boundIds.has(binding.id)) {\n boundIds.add(binding.id);\n\n if (boundElement.isDeleted) {\n return acc;\n }\n\n acc.push(binding);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(boundElement) && // being slightly conservative here, preserving existing containerId\n // if defined, lest boundElements is stale\n !boundElement.containerId) {\n boundElement.containerId = container.id;\n }\n }\n\n return acc;\n }, []);\n }\n};\n/**\r\n * Repairs target bound element's container's boundElements array,\r\n * or removes contaienrId if container does not exist.\r\n *\r\n * NOTE mutates elements.\r\n */\n\n\nconst repairBoundElement = (boundElement, elementsMap) => {\n const container = boundElement.containerId ? elementsMap.get(boundElement.containerId) : null;\n\n if (!container) {\n boundElement.containerId = null;\n return;\n }\n\n if (boundElement.isDeleted) {\n return;\n }\n\n if (container.boundElements && !container.boundElements.find(binding => binding.id === boundElement.id)) {\n // copy because we're not cloning on restore, and we don't want to mutate upstream\n const boundElements = (container.boundElements || (container.boundElements = [])).slice();\n boundElements.push({\n type: \"text\",\n id: boundElement.id\n });\n container.boundElements = boundElements;\n }\n};\n/**\r\n * Remove an element's frameId if its containing frame is non-existent\r\n *\r\n * NOTE mutates elements.\r\n */\n\n\nconst repairFrameMembership = (element, elementsMap) => {\n if (element.frameId) {\n const containingFrame = elementsMap.get(element.frameId);\n\n if (!containingFrame) {\n element.frameId = null;\n }\n }\n};\n\nconst restoreElements = (elements,\n/** NOTE doesn't serve for reconciliation */\nlocalElements, opts) => {\n // used to detect duplicate top-level element ids\n const existingIds = new Set();\n const localElementsMap = localElements ? (0,_utils__WEBPACK_IMPORTED_MODULE_7__.arrayToMap)(localElements) : null;\n const restoredElements = (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_10__.syncInvalidIndices)((elements || []).reduce((elements, element) => {\n // filtering out selection, which is legacy, no longer kept in elements,\n // and causing issues if retained\n if (element.type !== \"selection\" && !(0,_element__WEBPACK_IMPORTED_MODULE_0__.isInvisiblySmallElement)(element)) {\n let migratedElement = restoreElement(element);\n\n if (migratedElement) {\n const localElement = localElementsMap === null || localElementsMap === void 0 ? void 0 : localElementsMap.get(element.id);\n\n if (localElement && localElement.version > migratedElement.version) {\n migratedElement = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_6__.bumpVersion)(migratedElement, localElement.version);\n }\n\n if (existingIds.has(migratedElement.id)) {\n migratedElement = Object.assign(Object.assign({}, migratedElement), {\n id: (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)()\n });\n }\n\n existingIds.add(migratedElement.id);\n elements.push(migratedElement);\n }\n }\n\n return elements;\n }, []));\n\n if (!(opts === null || opts === void 0 ? void 0 : opts.repairBindings)) {\n return restoredElements;\n } // repair binding. Mutates elements.\n\n\n const restoredElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_7__.arrayToMap)(restoredElements);\n\n for (const element of restoredElements) {\n if (element.frameId) {\n repairFrameMembership(element, restoredElementsMap);\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element) && element.containerId) {\n repairBoundElement(element, restoredElementsMap);\n } else if (element.boundElements) {\n repairContainerElement(element, restoredElementsMap);\n }\n\n if (opts.refreshDimensions && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n Object.assign(element, (0,_element__WEBPACK_IMPORTED_MODULE_0__.refreshTextDimensions)(element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_8__.getContainerElement)(element, restoredElementsMap), restoredElementsMap));\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isLinearElement)(element)) {\n if (element.startBinding && (!restoredElementsMap.has(element.startBinding.elementId) || !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isArrowElement)(element))) {\n element.startBinding = null;\n }\n\n if (element.endBinding && (!restoredElementsMap.has(element.endBinding.elementId) || !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isArrowElement)(element))) {\n element.endBinding = null;\n }\n }\n }\n\n return restoredElements;\n};\n\nconst coalesceAppStateValue = (key, appState, defaultAppState) => {\n const value = appState[key]; // NOTE the value! assertion is needed in TS 4.5.5 (fixed in newer versions)\n\n return value !== undefined ? value : defaultAppState[key];\n};\n\nconst LegacyAppStateMigrations = {\n isSidebarDocked: (appState, defaultAppState) => {\n var _a;\n\n return [\"defaultSidebarDockedPreference\", (_a = appState.isSidebarDocked) !== null && _a !== void 0 ? _a : coalesceAppStateValue(\"defaultSidebarDockedPreference\", appState, defaultAppState)];\n }\n};\nconst restoreAppState = (appState, localAppState) => {\n var _a, _b, _c, _d;\n\n appState = appState || {};\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_4__.getDefaultAppState)();\n const nextAppState = {}; // first, migrate all legacy AppState properties to new ones. We do it\n // in one go before migrate the rest of the properties in case the new ones\n // depend on checking any other key (i.e. they are coupled)\n\n for (const legacyKey of Object.keys(LegacyAppStateMigrations)) {\n if (legacyKey in appState) {\n const [nextKey, nextValue] = LegacyAppStateMigrations[legacyKey](appState, defaultAppState);\n nextAppState[nextKey] = nextValue;\n }\n }\n\n for (const [key, defaultValue] of Object.entries(defaultAppState)) {\n // if AppState contains a legacy key, prefer that one and migrate its\n // value to the new one\n const suppliedValue = appState[key];\n const localValue = localAppState ? localAppState[key] : undefined;\n nextAppState[key] = suppliedValue !== undefined ? suppliedValue : localValue !== undefined ? localValue : defaultValue;\n }\n\n return Object.assign(Object.assign({}, nextAppState), {\n cursorButton: (localAppState === null || localAppState === void 0 ? void 0 : localAppState.cursorButton) || \"up\",\n // reset on fresh restore so as to hide the UI button if penMode not active\n penDetected: (_a = localAppState === null || localAppState === void 0 ? void 0 : localAppState.penDetected) !== null && _a !== void 0 ? _a : appState.penMode ? (_b = appState.penDetected) !== null && _b !== void 0 ? _b : false : false,\n activeTool: Object.assign(Object.assign({}, (0,_utils__WEBPACK_IMPORTED_MODULE_7__.updateActiveTool)(defaultAppState, nextAppState.activeTool.type && AllowedExcalidrawActiveTools[nextAppState.activeTool.type] ? nextAppState.activeTool : {\n type: \"selection\"\n })), {\n lastActiveTool: null,\n locked: (_c = nextAppState.activeTool.locked) !== null && _c !== void 0 ? _c : false\n }),\n // Migrates from previous version where appState.zoom was a number\n zoom: typeof appState.zoom === \"number\" ? {\n value: appState.zoom\n } : ((_d = appState.zoom) === null || _d === void 0 ? void 0 : _d.value) ? appState.zoom : defaultAppState.zoom,\n openSidebar: // string (legacy)\n typeof appState.openSidebar === \"string\" ? {\n name: _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_SIDEBAR.name\n } : nextAppState.openSidebar\n });\n};\nconst restore = (data,\n/**\r\n * Local AppState (`this.state` or initial state from localStorage) so that we\r\n * don't overwrite local state with default values (when values not\r\n * explicitly specified).\r\n * Supply `null` if you can't get access to it.\r\n */\nlocalAppState, localElements, elementsConfig) => {\n return {\n elements: restoreElements(data === null || data === void 0 ? void 0 : data.elements, localElements, elementsConfig),\n appState: restoreAppState(data === null || data === void 0 ? void 0 : data.appState, localAppState || null),\n files: (data === null || data === void 0 ? void 0 : data.files) || {}\n };\n};\n\nconst restoreLibraryItem = libraryItem => {\n const elements = restoreElements((0,_element__WEBPACK_IMPORTED_MODULE_0__.getNonDeletedElements)(libraryItem.elements), null);\n return elements.length ? Object.assign(Object.assign({}, libraryItem), {\n elements\n }) : null;\n};\n\nconst restoreLibraryItems = (libraryItems = [], defaultStatus) => {\n const restoredItems = [];\n\n for (const item of libraryItems) {\n // migrate older libraries\n if (Array.isArray(item)) {\n const restoredItem = restoreLibraryItem({\n status: defaultStatus,\n elements: item,\n id: (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)(),\n created: Date.now()\n });\n\n if (restoredItem) {\n restoredItems.push(restoredItem);\n }\n } else {\n const _item = item;\n const restoredItem = restoreLibraryItem(Object.assign(Object.assign({}, _item), {\n id: _item.id || (0,_random__WEBPACK_IMPORTED_MODULE_2__.randomId)(),\n status: _item.status || defaultStatus,\n created: _item.created || Date.now()\n }));\n\n if (restoredItem) {\n restoredItems.push(restoredItem);\n }\n }\n }\n\n return restoredItems;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./data/restore.ts?");
|
|
2579
2579
|
|
|
2580
2580
|
/***/ }),
|
|
2581
2581
|
|
|
@@ -2641,7 +2641,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2641
2641
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2642
2642
|
|
|
2643
2643
|
"use strict";
|
|
2644
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BindableElement\": () => (/* binding */ BindableElement),\n/* harmony export */ \"BoundElement\": () => (/* binding */ BoundElement),\n/* harmony export */ \"bindLinearElement\": () => (/* binding */ bindLinearElement),\n/* harmony export */ \"bindOrUnbindLinearElement\": () => (/* binding */ bindOrUnbindLinearElement),\n/* harmony export */ \"bindOrUnbindLinearElements\": () => (/* binding */ bindOrUnbindLinearElements),\n/* harmony export */ \"bindingProperties\": () => (/* binding */ bindingProperties),\n/* harmony export */ \"determineFocusDistance\": () => (/* binding */ determineFocusDistance),\n/* harmony export */ \"fixBindingsAfterDeletion\": () => (/* binding */ fixBindingsAfterDeletion),\n/* harmony export */ \"fixBindingsAfterDuplication\": () => (/* binding */ fixBindingsAfterDuplication),\n/* harmony export */ \"getHoveredElementForBinding\": () => (/* binding */ getHoveredElementForBinding),\n/* harmony export */ \"getSuggestedBindingsForArrows\": () => (/* binding */ getSuggestedBindingsForArrows),\n/* harmony export */ \"intersectElementWithLine\": () => (/* binding */ intersectElementWithLine),\n/* harmony export */ \"isBindingEnabled\": () => (/* binding */ isBindingEnabled),\n/* harmony export */ \"isLinearElementSimpleAndAlreadyBound\": () => (/* binding */ isLinearElementSimpleAndAlreadyBound),\n/* harmony export */ \"maxBindingGap\": () => (/* binding */ maxBindingGap),\n/* harmony export */ \"maybeBindLinearElement\": () => (/* binding */ maybeBindLinearElement),\n/* harmony export */ \"shouldEnableBindingForPointerEvent\": () => (/* binding */ shouldEnableBindingForPointerEvent),\n/* harmony export */ \"updateBoundElements\": () => (/* binding */ updateBoundElements)\n/* harmony export */ });\n/* harmony import */ var _ga__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../ga */ \"./ga.ts\");\n/* harmony import */ var _gapoints__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../gapoints */ \"./gapoints.ts\");\n/* harmony import */ var _gadirections__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../gadirections */ \"./gadirections.ts\");\n/* harmony import */ var _galines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../galines */ \"./galines.ts\");\n/* harmony import */ var _gatransforms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../gatransforms */ \"./gatransforms.ts\");\n/* harmony import */ var _bounds__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _utils_collision__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../utils/collision */ \"../utils/collision.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../scene */ \"./scene/index.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../keys */ \"./keys.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst shouldEnableBindingForPointerEvent = event => {\n return !event[_keys__WEBPACK_IMPORTED_MODULE_13__.KEYS.CTRL_OR_CMD];\n};\nconst isBindingEnabled = appState => {\n return appState.invertBindingBehaviour //zsviczian\n ? !appState.isBindingEnabled : appState.isBindingEnabled;\n};\n\nconst getNonDeletedElements = (scene, ids) => {\n const result = [];\n ids.forEach(id => {\n const element = scene.getNonDeletedElement(id);\n\n if (element != null) {\n result.push(element);\n }\n });\n return result;\n};\n\nconst bindOrUnbindLinearElement = (linearElement, startBindingElement, endBindingElement, elementsMap) => {\n const boundToElementIds = new Set();\n const unboundFromElementIds = new Set();\n bindOrUnbindLinearElementEdge(linearElement, startBindingElement, endBindingElement, \"start\", boundToElementIds, unboundFromElementIds, elementsMap);\n bindOrUnbindLinearElementEdge(linearElement, endBindingElement, startBindingElement, \"end\", boundToElementIds, unboundFromElementIds, elementsMap);\n const onlyUnbound = Array.from(unboundFromElementIds).filter(id => !boundToElementIds.has(id));\n getNonDeletedElements(_scene_Scene__WEBPACK_IMPORTED_MODULE_10__[\"default\"].getScene(linearElement), onlyUnbound).forEach(element => {\n var _a;\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(element, {\n boundElements: (_a = element.boundElements) === null || _a === void 0 ? void 0 : _a.filter(element => element.type !== \"arrow\" || element.id !== linearElement.id)\n });\n });\n};\n\nconst bindOrUnbindLinearElementEdge = (linearElement, bindableElement, otherEdgeBindableElement, startOrEnd, // Is mutated\nboundToElementIds, // Is mutated\nunboundFromElementIds, elementsMap) => {\n // \"keep\" is for method chaining convenience, a \"no-op\", so just bail out\n if (bindableElement === \"keep\") {\n return;\n } // null means break the bind, so nothing to consider here\n\n\n if (bindableElement === null) {\n const unbound = unbindLinearElement(linearElement, startOrEnd);\n\n if (unbound != null) {\n unboundFromElementIds.add(unbound);\n }\n\n return;\n } // While complext arrows can do anything, simple arrow with both ends trying\n // to bind to the same bindable should not be allowed, start binding takes\n // precedence\n\n\n if (isLinearElementSimple(linearElement)) {\n if (otherEdgeBindableElement == null || (otherEdgeBindableElement === \"keep\" ? // TODO: Refactor - Needlessly complex\n !isLinearElementSimpleAndAlreadyBoundOnOppositeEdge(linearElement, bindableElement, startOrEnd) : startOrEnd === \"start\" || otherEdgeBindableElement.id !== bindableElement.id)) {\n bindLinearElement(linearElement, bindableElement, startOrEnd, elementsMap);\n boundToElementIds.add(bindableElement.id);\n }\n } else {\n bindLinearElement(linearElement, bindableElement, startOrEnd, elementsMap);\n boundToElementIds.add(bindableElement.id);\n }\n};\n\nconst getOriginalBindingIfStillCloseOfLinearElementEdge = (linearElement, edge, app) => {\n var _a, _b;\n\n const elementsMap = app.scene.getNonDeletedElementsMap();\n const coors = getLinearElementEdgeCoors(linearElement, edge, elementsMap);\n const elementId = edge === \"start\" ? (_a = linearElement.startBinding) === null || _a === void 0 ? void 0 : _a.elementId : (_b = linearElement.endBinding) === null || _b === void 0 ? void 0 : _b.elementId;\n\n if (elementId) {\n const element = elementsMap.get(elementId);\n\n if (bindingBorderTest(element, coors, app)) {\n return element;\n }\n }\n\n return null;\n};\n\nconst getOriginalBindingsIfStillCloseToArrowEnds = (linearElement, app) => [\"start\", \"end\"].map(edge => getOriginalBindingIfStillCloseOfLinearElementEdge(linearElement, edge, app));\n\nconst getBindingStrategyForDraggingArrowEndpoints = (selectedElement, isBindingEnabled, draggingPoints, app) => {\n const startIdx = 0;\n const endIdx = selectedElement.points.length - 1;\n const startDragged = draggingPoints.findIndex(i => i === startIdx) > -1;\n const endDragged = draggingPoints.findIndex(i => i === endIdx) > -1;\n const start = startDragged ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"start\", app) : null // If binding is disabled and start is dragged, break all binds\n : // We have to update the focus and gap of the binding, so let's rebind\n getElligibleElementForBindingElement(selectedElement, \"start\", app);\n const end = endDragged ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"end\", app) : null // If binding is disabled and end is dragged, break all binds\n : // We have to update the focus and gap of the binding, so let's rebind\n getElligibleElementForBindingElement(selectedElement, \"end\", app);\n return [start, end];\n};\n\nconst getBindingStrategyForDraggingArrowOrJoints = (selectedElement, app, isBindingEnabled) => {\n const [startIsClose, endIsClose] = getOriginalBindingsIfStillCloseToArrowEnds(selectedElement, app);\n const start = startIsClose ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"start\", app) : null : null;\n const end = endIsClose ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"end\", app) : null : null;\n return [start, end];\n};\n\nconst bindOrUnbindLinearElements = (selectedElements, app, isBindingEnabled, draggingPoints) => {\n selectedElements.forEach(selectedElement => {\n const [start, end] = (draggingPoints === null || draggingPoints === void 0 ? void 0 : draggingPoints.length) ? // The arrow edge points are dragged (i.e. start, end)\n getBindingStrategyForDraggingArrowEndpoints(selectedElement, isBindingEnabled, draggingPoints !== null && draggingPoints !== void 0 ? draggingPoints : [], app) : // The arrow itself (the shaft) or the inner joins are dragged\n getBindingStrategyForDraggingArrowOrJoints(selectedElement, app, isBindingEnabled);\n bindOrUnbindLinearElement(selectedElement, start, end, app.scene.getNonDeletedElementsMap());\n });\n};\nconst getSuggestedBindingsForArrows = (selectedElements, app) => {\n // HOT PATH: Bail out if selected elements list is too large\n if (selectedElements.length > 50) {\n return [];\n }\n\n return selectedElements.filter(_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isLinearElement).flatMap(element => getOriginalBindingsIfStillCloseToArrowEnds(element, app)).filter(element => element !== null) // Filter out bind candidates which are in the\n // same selection / group with the arrow\n //\n // TODO: Is it worth turning the list into a set to avoid dupes?\n .filter(element => selectedElements.filter(selected => selected.id === (element === null || element === void 0 ? void 0 : element.id)).length === 0);\n};\nconst maybeBindLinearElement = (linearElement, appState, pointerCoords, app) => {\n if (appState.startBoundElement != null) {\n bindLinearElement(linearElement, appState.startBoundElement, \"start\", app.scene.getNonDeletedElementsMap());\n }\n\n const hoveredElement = getHoveredElementForBinding(pointerCoords, app);\n\n if (hoveredElement != null && !isLinearElementSimpleAndAlreadyBoundOnOppositeEdge(linearElement, hoveredElement, \"end\")) {\n bindLinearElement(linearElement, hoveredElement, \"end\", app.scene.getNonDeletedElementsMap());\n }\n};\nconst bindLinearElement = (linearElement, hoveredElement, startOrEnd, elementsMap) => {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(linearElement, {\n [startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\"]: Object.assign({\n elementId: hoveredElement.id\n }, calculateFocusAndGap(linearElement, hoveredElement, startOrEnd, elementsMap))\n });\n const boundElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_12__.arrayToMap)(hoveredElement.boundElements || []);\n\n if (!boundElementsMap.has(linearElement.id)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(hoveredElement, {\n boundElements: (hoveredElement.boundElements || []).concat({\n id: linearElement.id,\n type: \"arrow\"\n })\n });\n }\n}; // Don't bind both ends of a simple segment\n\nconst isLinearElementSimpleAndAlreadyBoundOnOppositeEdge = (linearElement, bindableElement, startOrEnd) => {\n const otherBinding = linearElement[startOrEnd === \"start\" ? \"endBinding\" : \"startBinding\"];\n return isLinearElementSimpleAndAlreadyBound(linearElement, otherBinding === null || otherBinding === void 0 ? void 0 : otherBinding.elementId, bindableElement);\n};\n\nconst isLinearElementSimpleAndAlreadyBound = (linearElement, alreadyBoundToId, bindableElement) => {\n return alreadyBoundToId === bindableElement.id && isLinearElementSimple(linearElement);\n};\n\nconst isLinearElementSimple = linearElement => linearElement.points.length < 3;\n\nconst unbindLinearElement = (linearElement, startOrEnd) => {\n const field = startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\";\n const binding = linearElement[field];\n\n if (binding == null) {\n return null;\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(linearElement, {\n [field]: null\n });\n return binding.elementId;\n};\n\nconst getHoveredElementForBinding = (pointerCoords, app) => {\n const hoveredElement = (0,_scene__WEBPACK_IMPORTED_MODULE_7__.getElementAtPosition)(app.scene.getNonDeletedElements(), element => (0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(element, false) && bindingBorderTest(element, pointerCoords, app));\n return hoveredElement;\n};\n\nconst calculateFocusAndGap = (linearElement, hoveredElement, startOrEnd, elementsMap) => {\n const direction = startOrEnd === \"start\" ? -1 : 1;\n const edgePointIndex = direction === -1 ? 0 : linearElement.points.length - 1;\n const adjacentPointIndex = edgePointIndex - direction;\n const edgePoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, edgePointIndex, elementsMap);\n const adjacentPoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, adjacentPointIndex, elementsMap);\n return {\n focus: determineFocusDistance(hoveredElement, adjacentPoint, edgePoint, elementsMap),\n gap: Math.max(1, distanceToBindableElement(hoveredElement, edgePoint, elementsMap))\n };\n}; // Supports translating, rotating and scaling `changedElement` with bound\n// linear elements.\n// Because scaling involves moving the focus points as well, it is\n// done before the `changedElement` is updated, and the `newSize` is passed\n// in explicitly.\n\n\nconst updateBoundElements = (changedElement, elementsMap, options) => {\n const {\n newSize,\n simultaneouslyUpdated\n } = options !== null && options !== void 0 ? options : {};\n const simultaneouslyUpdatedElementIds = getSimultaneouslyUpdatedElementIds(simultaneouslyUpdated);\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(changedElement)) {\n return;\n }\n\n boundElementsVisitor(elementsMap, changedElement, element => {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isLinearElement)(element) || element.isDeleted) {\n return;\n } // In case the boundElements are stale\n\n\n if (!doesNeedUpdate(element, changedElement)) {\n return;\n }\n\n const bindings = {\n startBinding: maybeCalculateNewGapWhenScaling(changedElement, element.startBinding, newSize),\n endBinding: maybeCalculateNewGapWhenScaling(changedElement, element.endBinding, newSize)\n }; // `linearElement` is being moved/scaled already, just update the binding\n\n if (simultaneouslyUpdatedElementIds.has(element.id)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(element, bindings);\n return;\n }\n\n bindableElementsVisitor(elementsMap, element, (bindableElement, bindingProp) => {\n if (bindableElement && (0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(bindableElement) && (bindingProp === \"startBinding\" || bindingProp === \"endBinding\")) {\n updateBoundPoint(element, bindingProp, bindings[bindingProp], bindableElement, elementsMap);\n }\n });\n const boundText = (0,_textElement__WEBPACK_IMPORTED_MODULE_14__.getBoundTextElement)(element, elementsMap);\n\n if (boundText && !boundText.isDeleted) {\n (0,_textElement__WEBPACK_IMPORTED_MODULE_14__.handleBindTextResize)(element, elementsMap, false);\n }\n });\n};\n\nconst doesNeedUpdate = (boundElement, changedElement) => {\n var _a, _b;\n\n return ((_a = boundElement.startBinding) === null || _a === void 0 ? void 0 : _a.elementId) === changedElement.id || ((_b = boundElement.endBinding) === null || _b === void 0 ? void 0 : _b.elementId) === changedElement.id;\n};\n\nconst getSimultaneouslyUpdatedElementIds = simultaneouslyUpdated => {\n return new Set((simultaneouslyUpdated || []).map(element => element.id));\n};\n\nconst updateBoundPoint = (linearElement, startOrEnd, binding, bindableElement, elementsMap) => {\n if (binding == null || // We only need to update the other end if this is a 2 point line element\n binding.elementId !== bindableElement.id && linearElement.points.length > 2) {\n return;\n }\n\n const direction = startOrEnd === \"startBinding\" ? -1 : 1;\n const edgePointIndex = direction === -1 ? 0 : linearElement.points.length - 1;\n const adjacentPointIndex = edgePointIndex - direction;\n const adjacentPoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, adjacentPointIndex, elementsMap);\n const focusPointAbsolute = determineFocusPoint(bindableElement, binding.focus, adjacentPoint, elementsMap);\n let newEdgePoint; // The linear element was not originally pointing inside the bound shape,\n // we can point directly at the focus point\n\n if (binding.gap === 0) {\n newEdgePoint = focusPointAbsolute;\n } else {\n const intersections = intersectElementWithLine(bindableElement, adjacentPoint, focusPointAbsolute, binding.gap, elementsMap);\n\n if (intersections.length === 0) {\n // This should never happen, since focusPoint should always be\n // inside the element, but just in case, bail out\n newEdgePoint = focusPointAbsolute;\n } else {\n // Guaranteed to intersect because focusPoint is always inside the shape\n newEdgePoint = intersections[0];\n }\n }\n\n _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.movePoints(linearElement, [{\n index: edgePointIndex,\n point: _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.pointFromAbsoluteCoords(linearElement, newEdgePoint, elementsMap)\n }], {\n [startOrEnd]: binding\n });\n};\n\nconst maybeCalculateNewGapWhenScaling = (changedElement, currentBinding, newSize) => {\n if (currentBinding == null || newSize == null) {\n return currentBinding;\n }\n\n const {\n gap,\n focus,\n elementId\n } = currentBinding;\n const {\n width: newWidth,\n height: newHeight\n } = newSize;\n const {\n width,\n height\n } = changedElement;\n const newGap = Math.max(1, Math.min(maxBindingGap(changedElement, newWidth, newHeight), gap * (newWidth < newHeight ? newWidth / width : newHeight / height)));\n return {\n elementId,\n gap: newGap,\n focus\n };\n};\n\nconst getElligibleElementForBindingElement = (linearElement, startOrEnd, app) => {\n return getHoveredElementForBinding(getLinearElementEdgeCoors(linearElement, startOrEnd, app.scene.getNonDeletedElementsMap()), app);\n};\n\nconst getLinearElementEdgeCoors = (linearElement, startOrEnd, elementsMap) => {\n const index = startOrEnd === \"start\" ? 0 : -1;\n return (0,_utils__WEBPACK_IMPORTED_MODULE_12__.tupleToCoors)(_linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, index, elementsMap));\n}; // We need to:\n// 1: Update elements not selected to point to duplicated elements\n// 2: Update duplicated elements to point to other duplicated elements\n\n\nconst fixBindingsAfterDuplication = (sceneElements, oldElements, oldIdToDuplicatedId, // There are three copying mechanisms: Copy-paste, duplication and alt-drag.\n// Only when alt-dragging the new \"duplicates\" act as the \"old\", while\n// the \"old\" elements act as the \"new copy\" - essentially working reverse\n// to the other two.\nduplicatesServeAsOld) => {\n // First collect all the binding/bindable elements, so we only update\n // each once, regardless of whether they were duplicated or not.\n const allBoundElementIds = new Set();\n const allBindableElementIds = new Set();\n const shouldReverseRoles = duplicatesServeAsOld === \"duplicatesServeAsOld\";\n oldElements.forEach(oldElement => {\n const {\n boundElements\n } = oldElement;\n\n if (boundElements != null && boundElements.length > 0) {\n boundElements.forEach(boundElement => {\n if (shouldReverseRoles && !oldIdToDuplicatedId.has(boundElement.id)) {\n allBoundElementIds.add(boundElement.id);\n }\n });\n allBindableElementIds.add(oldIdToDuplicatedId.get(oldElement.id));\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindingElement)(oldElement)) {\n if (oldElement.startBinding != null) {\n const {\n elementId\n } = oldElement.startBinding;\n\n if (shouldReverseRoles && !oldIdToDuplicatedId.has(elementId)) {\n allBindableElementIds.add(elementId);\n }\n }\n\n if (oldElement.endBinding != null) {\n const {\n elementId\n } = oldElement.endBinding;\n\n if (shouldReverseRoles && !oldIdToDuplicatedId.has(elementId)) {\n allBindableElementIds.add(elementId);\n }\n }\n\n if (oldElement.startBinding != null || oldElement.endBinding != null) {\n allBoundElementIds.add(oldIdToDuplicatedId.get(oldElement.id));\n }\n }\n }); // Update the linear elements\n\n sceneElements.filter(({\n id\n }) => allBoundElementIds.has(id)).forEach(element => {\n const {\n startBinding,\n endBinding\n } = element;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(element, {\n startBinding: newBindingAfterDuplication(startBinding, oldIdToDuplicatedId),\n endBinding: newBindingAfterDuplication(endBinding, oldIdToDuplicatedId)\n });\n }); // Update the bindable shapes\n\n sceneElements.filter(({\n id\n }) => allBindableElementIds.has(id)).forEach(bindableElement => {\n const {\n boundElements\n } = bindableElement;\n\n if (boundElements != null && boundElements.length > 0) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(bindableElement, {\n boundElements: boundElements.map(boundElement => oldIdToDuplicatedId.has(boundElement.id) ? {\n id: oldIdToDuplicatedId.get(boundElement.id),\n type: boundElement.type\n } : boundElement)\n });\n }\n });\n};\n\nconst newBindingAfterDuplication = (binding, oldIdToDuplicatedId) => {\n var _a;\n\n if (binding == null) {\n return null;\n }\n\n const {\n elementId,\n focus,\n gap\n } = binding;\n return {\n focus,\n gap,\n elementId: (_a = oldIdToDuplicatedId.get(elementId)) !== null && _a !== void 0 ? _a : elementId\n };\n};\n\nconst fixBindingsAfterDeletion = (sceneElements, deletedElements) => {\n const elements = (0,_utils__WEBPACK_IMPORTED_MODULE_12__.arrayToMap)(sceneElements);\n\n for (const element of deletedElements) {\n BoundElement.unbindAffected(elements, element, _mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement);\n BindableElement.unbindAffected(elements, element, _mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement);\n }\n};\n\nconst newBoundElements = (boundElements, idsToRemove, elementsToAdd = []) => {\n if (!boundElements) {\n return null;\n }\n\n const nextBoundElements = boundElements.filter(boundElement => !idsToRemove.has(boundElement.id));\n nextBoundElements.push(...elementsToAdd.map(x => ({\n id: x.id,\n type: x.type\n })));\n return nextBoundElements;\n};\n\nconst bindingBorderTest = (element, {\n x,\n y\n}, app) => {\n const threshold = maxBindingGap(element, element.width, element.height);\n const shape = app.getElementShape(element);\n return (0,_utils_collision__WEBPACK_IMPORTED_MODULE_6__.isPointOnShape)([x, y], shape, threshold);\n};\n\nconst maxBindingGap = (element, elementWidth, elementHeight) => {\n // Aligns diamonds with rectangles\n const shapeRatio = element.type === \"diamond\" ? 1 / Math.sqrt(2) : 1;\n const smallerDimension = shapeRatio * Math.min(elementWidth, elementHeight); // We make the bindable boundary bigger for bigger elements\n\n return Math.max(16, Math.min(0.25 * smallerDimension, 32));\n};\n\nconst distanceToBindableElement = (element, point, elementsMap) => {\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n return distanceToRectangle(element, point, elementsMap);\n\n case \"diamond\":\n return distanceToDiamond(element, point, elementsMap);\n\n case \"ellipse\":\n return distanceToEllipse(element, point, elementsMap);\n }\n};\n\nconst distanceToRectangle = (element, point, elementsMap) => {\n const [, pointRel, hwidth, hheight] = pointRelativeToElement(element, point, elementsMap);\n return Math.max(_gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, _galines__WEBPACK_IMPORTED_MODULE_3__.equation(0, 1, -hheight)), _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, _galines__WEBPACK_IMPORTED_MODULE_3__.equation(1, 0, -hwidth)));\n};\n\nconst distanceToDiamond = (element, point, elementsMap) => {\n const [, pointRel, hwidth, hheight] = pointRelativeToElement(element, point, elementsMap);\n const side = _galines__WEBPACK_IMPORTED_MODULE_3__.equation(hheight, hwidth, -hheight * hwidth);\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, side);\n};\n\nconst distanceToEllipse = (element, point, elementsMap) => {\n const [pointRel, tangent] = ellipseParamsForTest(element, point, elementsMap);\n return -_galines__WEBPACK_IMPORTED_MODULE_3__.sign(tangent) * _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, tangent);\n};\n\nconst ellipseParamsForTest = (element, point, elementsMap) => {\n const [, pointRel, hwidth, hheight] = pointRelativeToElement(element, point, elementsMap);\n const [px, py] = _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(pointRel); // We're working in positive quadrant, so start with `t = 45deg`, `tx=cos(t)`\n\n let tx = 0.707;\n let ty = 0.707;\n const a = hwidth;\n const b = hheight; // This is a numerical method to find the params tx, ty at which\n // the ellipse has the closest point to the given point\n\n [0, 1, 2, 3].forEach(_ => {\n const xx = a * tx;\n const yy = b * ty;\n const ex = (a * a - b * b) * tx ** 3 / a;\n const ey = (b * b - a * a) * ty ** 3 / b;\n const rx = xx - ex;\n const ry = yy - ey;\n const qx = px - ex;\n const qy = py - ey;\n const r = Math.hypot(ry, rx);\n const q = Math.hypot(qy, qx);\n tx = Math.min(1, Math.max(0, (qx * r / q + ex) / a));\n ty = Math.min(1, Math.max(0, (qy * r / q + ey) / b));\n const t = Math.hypot(ty, tx);\n tx /= t;\n ty /= t;\n });\n const closestPoint = _ga__WEBPACK_IMPORTED_MODULE_0__.point(a * tx, b * ty);\n const tangent = _galines__WEBPACK_IMPORTED_MODULE_3__.orthogonalThrough(pointRel, closestPoint);\n return [pointRel, tangent];\n}; // Returns:\n// 1. the point relative to the elements (x, y) position\n// 2. the point relative to the element's center with positive (x, y)\n// 3. half element width\n// 4. half element height\n//\n// Note that for linear elements the (x, y) position is not at the\n// top right corner of their boundary.\n//\n// Rectangles, diamonds and ellipses are symmetrical over axes,\n// and other elements have a rectangular boundary,\n// so we only need to perform hit tests for the positive quadrant.\n\n\nconst pointRelativeToElement = (element, pointTuple, elementsMap) => {\n const point = _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(pointTuple);\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getElementAbsoluteCoords)(element, elementsMap);\n const center = coordsCenter(x1, y1, x2, y2); // GA has angle orientation opposite to `rotate`\n\n const rotate = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.rotation(center, element.angle);\n const pointRotated = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(rotate, point);\n const pointRelToCenter = _ga__WEBPACK_IMPORTED_MODULE_0__.sub(pointRotated, _gadirections__WEBPACK_IMPORTED_MODULE_2__.from(center));\n const pointRelToCenterAbs = _gapoints__WEBPACK_IMPORTED_MODULE_1__.abs(pointRelToCenter);\n const elementPos = _ga__WEBPACK_IMPORTED_MODULE_0__.offset(element.x, element.y);\n const pointRelToPos = _ga__WEBPACK_IMPORTED_MODULE_0__.sub(pointRotated, elementPos);\n const halfWidth = (x2 - x1) / 2;\n const halfHeight = (y2 - y1) / 2;\n return [pointRelToPos, pointRelToCenterAbs, halfWidth, halfHeight];\n};\n\nconst relativizationToElementCenter = (element, elementsMap) => {\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getElementAbsoluteCoords)(element, elementsMap);\n const center = coordsCenter(x1, y1, x2, y2); // GA has angle orientation opposite to `rotate`\n\n const rotate = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.rotation(center, element.angle);\n const translate = _ga__WEBPACK_IMPORTED_MODULE_0__.reverse(_gatransforms__WEBPACK_IMPORTED_MODULE_4__.translation(_gadirections__WEBPACK_IMPORTED_MODULE_2__.from(center)));\n return _gatransforms__WEBPACK_IMPORTED_MODULE_4__.compose(rotate, translate);\n};\n\nconst coordsCenter = (x1, y1, x2, y2) => {\n return _ga__WEBPACK_IMPORTED_MODULE_0__.point((x1 + x2) / 2, (y1 + y2) / 2);\n}; // The focus distance is the oriented ratio between the size of\n// the `element` and the \"focus image\" of the element on which\n// all focus points lie, so it's a number between -1 and 1.\n// The line going through `a` and `b` is a tangent to the \"focus image\"\n// of the element.\n\n\nconst determineFocusDistance = ( //zsviczian added export\nelement, // Point on the line, in absolute coordinates\na, // Another point on the line, in absolute coordinates (closer to element)\nb, elementsMap) => {\n const relateToCenter = relativizationToElementCenter(element, elementsMap);\n const aRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(a));\n const bRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(b));\n const line = _galines__WEBPACK_IMPORTED_MODULE_3__.through(aRel, bRel);\n const q = element.height / element.width;\n const hwidth = element.width / 2;\n const hheight = element.height / 2;\n const n = line[2];\n const m = line[3];\n const c = line[1];\n const mabs = Math.abs(m);\n const nabs = Math.abs(n);\n let ret;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n ret = c / (hwidth * (nabs + q * mabs));\n break;\n\n case \"diamond\":\n ret = mabs < nabs ? c / (nabs * hwidth) : c / (mabs * hheight);\n break;\n\n case \"ellipse\":\n ret = c / (hwidth * Math.sqrt(n ** 2 + q ** 2 * m ** 2));\n break;\n }\n\n return ret || 0;\n};\n\nconst determineFocusPoint = (element, // The oriented, relative distance from the center of `element` of the\n// returned focusPoint\nfocus, adjecentPoint, elementsMap) => {\n if (focus === 0) {\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getElementAbsoluteCoords)(element, elementsMap);\n const center = coordsCenter(x1, y1, x2, y2);\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(center);\n }\n\n const relateToCenter = relativizationToElementCenter(element, elementsMap);\n const adjecentPointRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(adjecentPoint));\n const reverseRelateToCenter = _ga__WEBPACK_IMPORTED_MODULE_0__.reverse(relateToCenter);\n let point;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"diamond\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n point = findFocusPointForRectangulars(element, focus, adjecentPointRel);\n break;\n\n case \"ellipse\":\n point = findFocusPointForEllipse(element, focus, adjecentPointRel);\n break;\n }\n\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(_gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(reverseRelateToCenter, point));\n}; // Returns 2 or 0 intersection points between line going through `a` and `b`\n// and the `element`, in ascending order of distance from `a`.\n\n\nconst intersectElementWithLine = ( //zsviczian added export\nelement, // Point on the line, in absolute coordinates\na, // Another point on the line, in absolute coordinates\nb, // If given, the element is inflated by this value\ngap = 0, elementsMap) => {\n const relateToCenter = relativizationToElementCenter(element, elementsMap);\n const aRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(a));\n const bRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(b));\n const line = _galines__WEBPACK_IMPORTED_MODULE_3__.through(aRel, bRel);\n const reverseRelateToCenter = _ga__WEBPACK_IMPORTED_MODULE_0__.reverse(relateToCenter);\n const intersections = getSortedElementLineIntersections(element, line, aRel, gap);\n return intersections.map(point => _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(_gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(reverseRelateToCenter, point)));\n};\n\nconst getSortedElementLineIntersections = (element, // Relative to element center\nline, // Relative to element center\nnearPoint, gap = 0) => {\n let intersections;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"diamond\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n const corners = getCorners(element);\n intersections = corners.flatMap((point, i) => {\n const edge = [point, corners[(i + 1) % 4]];\n return intersectSegment(line, offsetSegment(edge, gap));\n }).concat(corners.flatMap(point => getCircleIntersections(point, gap, line)));\n break;\n\n case \"ellipse\":\n intersections = getEllipseIntersections(element, gap, line);\n break;\n }\n\n if (intersections.length < 2) {\n // Ignore the \"edge\" case of only intersecting with a single corner\n return [];\n }\n\n const sortedIntersections = intersections.sort((i1, i2) => _gapoints__WEBPACK_IMPORTED_MODULE_1__.distance(i1, nearPoint) - _gapoints__WEBPACK_IMPORTED_MODULE_1__.distance(i2, nearPoint));\n return [sortedIntersections[0], sortedIntersections[sortedIntersections.length - 1]];\n};\n\nconst getCorners = (element, scale = 1) => {\n const hx = scale * element.width / 2;\n const hy = scale * element.height / 2;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point(hx, hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(hx, -hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(-hx, -hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(-hx, hy)];\n\n case \"diamond\":\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point(0, hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(hx, 0), _ga__WEBPACK_IMPORTED_MODULE_0__.point(0, -hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(-hx, 0)];\n }\n}; // Returns intersection of `line` with `segment`, with `segment` moved by\n// `gap` in its polar direction.\n// If intersection coincides with second segment point returns empty array.\n\n\nconst intersectSegment = (line, segment) => {\n const [a, b] = segment;\n const aDist = _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(a, line);\n const bDist = _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(b, line);\n\n if (aDist * bDist >= 0) {\n // The intersection is outside segment `(a, b)`\n return [];\n }\n\n return [_gapoints__WEBPACK_IMPORTED_MODULE_1__.intersect(line, _galines__WEBPACK_IMPORTED_MODULE_3__.through(a, b))];\n};\n\nconst offsetSegment = (segment, distance) => {\n const [a, b] = segment;\n const offset = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.translationOrthogonal(_gadirections__WEBPACK_IMPORTED_MODULE_2__.fromTo(a, b), distance);\n return [_gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(offset, a), _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(offset, b)];\n};\n\nconst getEllipseIntersections = (element, gap, line) => {\n const a = element.width / 2 + gap;\n const b = element.height / 2 + gap;\n const m = line[2];\n const n = line[3];\n const c = line[1];\n const squares = a * a * m * m + b * b * n * n;\n const discr = squares - c * c;\n\n if (squares === 0 || discr <= 0) {\n return [];\n }\n\n const discrRoot = Math.sqrt(discr);\n const xn = -a * a * m * c;\n const yn = -b * b * n * c;\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point((xn + a * b * n * discrRoot) / squares, (yn - a * b * m * discrRoot) / squares), _ga__WEBPACK_IMPORTED_MODULE_0__.point((xn - a * b * n * discrRoot) / squares, (yn + a * b * m * discrRoot) / squares)];\n};\n\nconst getCircleIntersections = (center, radius, line) => {\n if (radius === 0) {\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(line, center) === 0 ? [center] : [];\n }\n\n const m = line[2];\n const n = line[3];\n const c = line[1];\n const [a, b] = _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(center);\n const r = radius;\n const squares = m * m + n * n;\n const discr = r * r * squares - (m * a + n * b + c) ** 2;\n\n if (squares === 0 || discr <= 0) {\n return [];\n }\n\n const discrRoot = Math.sqrt(discr);\n const xn = a * n * n - b * m * n - m * c;\n const yn = b * m * m - a * m * n - n * c;\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point((xn + n * discrRoot) / squares, (yn - m * discrRoot) / squares), _ga__WEBPACK_IMPORTED_MODULE_0__.point((xn - n * discrRoot) / squares, (yn + m * discrRoot) / squares)];\n}; // The focus point is the tangent point of the \"focus image\" of the\n// `element`, where the tangent goes through `point`.\n\n\nconst findFocusPointForEllipse = (ellipse, // Between -1 and 1 (not 0) the relative size of the \"focus image\" of\n// the element on which the focus point lies\nrelativeDistance, // The point for which we're trying to find the focus point, relative\n// to the ellipse center.\npoint) => {\n const relativeDistanceAbs = Math.abs(relativeDistance);\n const a = ellipse.width * relativeDistanceAbs / 2;\n const b = ellipse.height * relativeDistanceAbs / 2;\n const orientation = Math.sign(relativeDistance);\n const [px, pyo] = _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(point); // The calculation below can't handle py = 0\n\n const py = pyo === 0 ? 0.0001 : pyo;\n const squares = px ** 2 * b ** 2 + py ** 2 * a ** 2; // Tangent mx + ny + 1 = 0\n\n const m = (-px * b ** 2 + orientation * py * Math.sqrt(Math.max(0, squares - a ** 2 * b ** 2))) / squares;\n let n = (-m * px - 1) / py;\n\n if (n === 0) {\n // if zero {-0, 0}, fall back to a same-sign value in the similar range\n n = (Object.is(n, -0) ? -1 : 1) * 0.01;\n }\n\n const x = -(a ** 2 * m) / (n ** 2 * b ** 2 + m ** 2 * a ** 2);\n return _ga__WEBPACK_IMPORTED_MODULE_0__.point(x, (-m * x - 1) / (n === 0 ? 0.0001 : n)); //zsviczian https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1054\n};\n\nconst findFocusPointForRectangulars = (element, // Between -1 and 1 for how far away should the focus point be relative\n// to the size of the element. Sign determines orientation.\nrelativeDistance, // The point for which we're trying to find the focus point, relative\n// to the element center.\npoint) => {\n const relativeDistanceAbs = Math.abs(relativeDistance);\n const orientation = Math.sign(relativeDistance);\n const corners = getCorners(element, relativeDistanceAbs);\n let maxDistance = 0;\n let tangentPoint = null;\n corners.forEach(corner => {\n const distance = orientation * _galines__WEBPACK_IMPORTED_MODULE_3__.through(point, corner)[1];\n\n if (distance > maxDistance) {\n maxDistance = distance;\n tangentPoint = corner;\n }\n });\n return tangentPoint;\n};\n\nconst bindingProperties = new Set([\"boundElements\", \"frameId\", \"containerId\", \"startBinding\", \"endBinding\"]);\n/**\r\n * Tries to visit each bound element (does not have to be found).\r\n */\n\nconst boundElementsVisitor = (elements, element, visit) => {\n var _a, _b;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(element)) {\n // create new instance so that possible mutations won't play a role in visiting order\n const boundElements = (_b = (_a = element.boundElements) === null || _a === void 0 ? void 0 : _a.slice()) !== null && _b !== void 0 ? _b : []; // last added text should be the one we keep (~previous are duplicates)\n\n boundElements.forEach(({\n id\n }) => {\n visit(elements.get(id), \"boundElements\", id);\n });\n }\n};\n/**\r\n * Tries to visit each bindable element (does not have to be found).\r\n */\n\n\nconst bindableElementsVisitor = (elements, element, visit) => {\n if (element.frameId) {\n const id = element.frameId;\n visit(elements.get(id), \"frameId\", id);\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBoundToContainer)(element)) {\n const id = element.containerId;\n visit(elements.get(id), \"containerId\", id);\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isArrowElement)(element)) {\n if (element.startBinding) {\n const id = element.startBinding.elementId;\n visit(elements.get(id), \"startBinding\", id);\n }\n\n if (element.endBinding) {\n const id = element.endBinding.elementId;\n visit(elements.get(id), \"endBinding\", id);\n }\n }\n};\n/**\r\n * Bound element containing bindings to `frameId`, `containerId`, `startBinding` or `endBinding`.\r\n */\n\n\nclass BoundElement {\n /**\r\n * Unbind the affected non deleted bindable elements (removing element from `boundElements`).\r\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\r\n * - prepares updates to unbind each bindable element's `boundElements` from the current element\r\n */\n static unbindAffected(elements, boundElement, updateElementWith) {\n if (!boundElement) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, bindableElement => {\n // bindable element is deleted, this is fine\n if (!bindableElement || bindableElement.isDeleted) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, (_, __, boundElementId) => {\n if (boundElementId === boundElement.id) {\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set([boundElementId]))\n });\n }\n });\n });\n }\n\n}\n/**\r\n * Rebind the next affected non deleted bindable elements (adding element to `boundElements`).\r\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\r\n * - prepares updates to rebind each bindable element's `boundElements` to the current element\r\n *\r\n * NOTE: rebind expects that affected elements were previously unbound with `BoundElement.unbindAffected`\r\n */\n\nBoundElement.rebindAffected = (elements, boundElement, updateElementWith) => {\n // don't try to rebind element that is deleted\n if (!boundElement || boundElement.isDeleted) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, (bindableElement, bindingProp) => {\n var _a, _b; // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\n\n\n if (!bindableElement || bindableElement.isDeleted) {\n updateElementWith(boundElement, {\n [bindingProp]: null\n });\n return;\n } // frame bindings are unidirectional, there is nothing to rebind\n\n\n if (bindingProp === \"frameId\") {\n return;\n }\n\n if ((_a = bindableElement.boundElements) === null || _a === void 0 ? void 0 : _a.find(x => x.id === boundElement.id)) {\n return;\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isArrowElement)(boundElement)) {\n // rebind if not found!\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set(), new Array(boundElement))\n });\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isTextElement)(boundElement)) {\n if (!((_b = bindableElement.boundElements) === null || _b === void 0 ? void 0 : _b.find(x => x.type === \"text\"))) {\n // rebind only if there is no other text bound already\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set(), new Array(boundElement))\n });\n } else {\n // unbind otherwise\n updateElementWith(boundElement, {\n [bindingProp]: null\n });\n }\n }\n });\n};\n/**\r\n * Bindable element containing bindings to `boundElements`.\r\n */\n\n\nclass BindableElement {\n /**\r\n * Unbind the affected non deleted bound elements (resetting `containerId`, `startBinding`, `endBinding` to `null`).\r\n * - iterates through non deleted `boundElements` of the current element\r\n * - prepares updates to unbind each bound element from the current element\r\n */\n static unbindAffected(elements, bindableElement, updateElementWith) {\n if (!bindableElement) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, boundElement => {\n // bound element is deleted, this is fine\n if (!boundElement || boundElement.isDeleted) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, (_, bindingProp, bindableElementId) => {\n // making sure there is an element to be unbound\n if (bindableElementId === bindableElement.id) {\n updateElementWith(boundElement, {\n [bindingProp]: null\n });\n }\n });\n });\n }\n\n}\n/**\r\n * Rebind the affected non deleted bound elements (for now setting only `containerId`, as we cannot rebind arrows atm).\r\n * - iterates through non deleted `boundElements` of the current element\r\n * - prepares updates to rebind each bound element to the current element or unbind it from `boundElements` in case of conflicts\r\n *\r\n * NOTE: rebind expects that affected elements were previously unbound with `BindaleElement.unbindAffected`\r\n */\n\nBindableElement.rebindAffected = (elements, bindableElement, updateElementWith) => {\n // don't try to rebind element that is deleted (i.e. updated as deleted)\n if (!bindableElement || bindableElement.isDeleted) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, (boundElement, _, boundElementId) => {\n var _a, _b, _c; // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\n\n\n if (!boundElement || boundElement.isDeleted) {\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set([boundElementId]))\n });\n return;\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isTextElement)(boundElement)) {\n const boundElements = (_b = (_a = bindableElement.boundElements) === null || _a === void 0 ? void 0 : _a.slice()) !== null && _b !== void 0 ? _b : []; // check if this is the last element in the array, if not, there is an previously bound text which should be unbound\n\n if (((_c = boundElements.reverse().find(x => x.type === \"text\")) === null || _c === void 0 ? void 0 : _c.id) === boundElement.id) {\n if (boundElement.containerId !== bindableElement.id) {\n // rebind if not bound already!\n updateElementWith(boundElement, {\n containerId: bindableElement.id\n });\n }\n } else {\n if (boundElement.containerId !== null) {\n // unbind if not unbound already\n updateElementWith(boundElement, {\n containerId: null\n });\n } // unbind from boundElements as the element got bound to some other element in the meantime\n\n\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set([boundElement.id]))\n });\n }\n }\n });\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/binding.ts?");
|
|
2644
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"BindableElement\": () => (/* binding */ BindableElement),\n/* harmony export */ \"BoundElement\": () => (/* binding */ BoundElement),\n/* harmony export */ \"bindLinearElement\": () => (/* binding */ bindLinearElement),\n/* harmony export */ \"bindOrUnbindLinearElement\": () => (/* binding */ bindOrUnbindLinearElement),\n/* harmony export */ \"bindOrUnbindLinearElements\": () => (/* binding */ bindOrUnbindLinearElements),\n/* harmony export */ \"bindingProperties\": () => (/* binding */ bindingProperties),\n/* harmony export */ \"determineFocusDistance\": () => (/* binding */ determineFocusDistance),\n/* harmony export */ \"fixBindingsAfterDeletion\": () => (/* binding */ fixBindingsAfterDeletion),\n/* harmony export */ \"fixBindingsAfterDuplication\": () => (/* binding */ fixBindingsAfterDuplication),\n/* harmony export */ \"getHoveredElementForBinding\": () => (/* binding */ getHoveredElementForBinding),\n/* harmony export */ \"getSuggestedBindingsForArrows\": () => (/* binding */ getSuggestedBindingsForArrows),\n/* harmony export */ \"intersectElementWithLine\": () => (/* binding */ intersectElementWithLine),\n/* harmony export */ \"isBindingEnabled\": () => (/* binding */ isBindingEnabled),\n/* harmony export */ \"isLinearElementSimpleAndAlreadyBound\": () => (/* binding */ isLinearElementSimpleAndAlreadyBound),\n/* harmony export */ \"maxBindingGap\": () => (/* binding */ maxBindingGap),\n/* harmony export */ \"maybeBindLinearElement\": () => (/* binding */ maybeBindLinearElement),\n/* harmony export */ \"shouldEnableBindingForPointerEvent\": () => (/* binding */ shouldEnableBindingForPointerEvent),\n/* harmony export */ \"updateBoundElements\": () => (/* binding */ updateBoundElements)\n/* harmony export */ });\n/* harmony import */ var _ga__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../ga */ \"./ga.ts\");\n/* harmony import */ var _gapoints__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../gapoints */ \"./gapoints.ts\");\n/* harmony import */ var _gadirections__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../gadirections */ \"./gadirections.ts\");\n/* harmony import */ var _galines__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../galines */ \"./galines.ts\");\n/* harmony import */ var _gatransforms__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../gatransforms */ \"./gatransforms.ts\");\n/* harmony import */ var _bounds__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _utils_collision__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../utils/collision */ \"../utils/collision.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../scene */ \"./scene/index.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../keys */ \"./keys.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst shouldEnableBindingForPointerEvent = event => {\n return !event[_keys__WEBPACK_IMPORTED_MODULE_13__.KEYS.CTRL_OR_CMD];\n};\nconst isBindingEnabled = appState => {\n return appState.invertBindingBehaviour //zsviczian\n ? !appState.isBindingEnabled : appState.isBindingEnabled;\n};\n\nconst getNonDeletedElements = (scene, ids) => {\n const result = [];\n ids.forEach(id => {\n const element = scene.getNonDeletedElement(id);\n\n if (element != null) {\n result.push(element);\n }\n });\n return result;\n};\n\nconst bindOrUnbindLinearElement = (linearElement, startBindingElement, endBindingElement, elementsMap) => {\n const boundToElementIds = new Set();\n const unboundFromElementIds = new Set();\n bindOrUnbindLinearElementEdge(linearElement, startBindingElement, endBindingElement, \"start\", boundToElementIds, unboundFromElementIds, elementsMap);\n bindOrUnbindLinearElementEdge(linearElement, endBindingElement, startBindingElement, \"end\", boundToElementIds, unboundFromElementIds, elementsMap);\n const onlyUnbound = Array.from(unboundFromElementIds).filter(id => !boundToElementIds.has(id));\n getNonDeletedElements(_scene_Scene__WEBPACK_IMPORTED_MODULE_10__[\"default\"].getScene(linearElement), onlyUnbound).forEach(element => {\n var _a;\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(element, {\n boundElements: (_a = element.boundElements) === null || _a === void 0 ? void 0 : _a.filter(element => element.type !== \"arrow\" || element.id !== linearElement.id)\n });\n });\n};\n\nconst bindOrUnbindLinearElementEdge = (linearElement, bindableElement, otherEdgeBindableElement, startOrEnd, // Is mutated\nboundToElementIds, // Is mutated\nunboundFromElementIds, elementsMap) => {\n // \"keep\" is for method chaining convenience, a \"no-op\", so just bail out\n if (bindableElement === \"keep\") {\n return;\n } // null means break the bind, so nothing to consider here\n\n\n if (bindableElement === null) {\n const unbound = unbindLinearElement(linearElement, startOrEnd);\n\n if (unbound != null) {\n unboundFromElementIds.add(unbound);\n }\n\n return;\n } // While complext arrows can do anything, simple arrow with both ends trying\n // to bind to the same bindable should not be allowed, start binding takes\n // precedence\n\n\n if (isLinearElementSimple(linearElement)) {\n if (otherEdgeBindableElement == null || (otherEdgeBindableElement === \"keep\" ? // TODO: Refactor - Needlessly complex\n !isLinearElementSimpleAndAlreadyBoundOnOppositeEdge(linearElement, bindableElement, startOrEnd) : startOrEnd === \"start\" || otherEdgeBindableElement.id !== bindableElement.id)) {\n bindLinearElement(linearElement, bindableElement, startOrEnd, elementsMap);\n boundToElementIds.add(bindableElement.id);\n }\n } else {\n bindLinearElement(linearElement, bindableElement, startOrEnd, elementsMap);\n boundToElementIds.add(bindableElement.id);\n }\n};\n\nconst getOriginalBindingIfStillCloseOfLinearElementEdge = (linearElement, edge, app) => {\n var _a, _b;\n\n const elementsMap = app.scene.getNonDeletedElementsMap();\n const coors = getLinearElementEdgeCoors(linearElement, edge, elementsMap);\n const elementId = edge === \"start\" ? (_a = linearElement.startBinding) === null || _a === void 0 ? void 0 : _a.elementId : (_b = linearElement.endBinding) === null || _b === void 0 ? void 0 : _b.elementId;\n\n if (elementId) {\n const element = elementsMap.get(elementId);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(element) && bindingBorderTest(element, coors, app)) {\n return element;\n }\n }\n\n return null;\n};\n\nconst getOriginalBindingsIfStillCloseToArrowEnds = (linearElement, app) => [\"start\", \"end\"].map(edge => getOriginalBindingIfStillCloseOfLinearElementEdge(linearElement, edge, app));\n\nconst getBindingStrategyForDraggingArrowEndpoints = (selectedElement, isBindingEnabled, draggingPoints, app) => {\n const startIdx = 0;\n const endIdx = selectedElement.points.length - 1;\n const startDragged = draggingPoints.findIndex(i => i === startIdx) > -1;\n const endDragged = draggingPoints.findIndex(i => i === endIdx) > -1;\n const start = startDragged ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"start\", app) : null // If binding is disabled and start is dragged, break all binds\n : // We have to update the focus and gap of the binding, so let's rebind\n getElligibleElementForBindingElement(selectedElement, \"start\", app);\n const end = endDragged ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"end\", app) : null // If binding is disabled and end is dragged, break all binds\n : // We have to update the focus and gap of the binding, so let's rebind\n getElligibleElementForBindingElement(selectedElement, \"end\", app);\n return [start, end];\n};\n\nconst getBindingStrategyForDraggingArrowOrJoints = (selectedElement, app, isBindingEnabled) => {\n const [startIsClose, endIsClose] = getOriginalBindingsIfStillCloseToArrowEnds(selectedElement, app);\n const start = startIsClose ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"start\", app) : null : null;\n const end = endIsClose ? isBindingEnabled ? getElligibleElementForBindingElement(selectedElement, \"end\", app) : null : null;\n return [start, end];\n};\n\nconst bindOrUnbindLinearElements = (selectedElements, app, isBindingEnabled, draggingPoints) => {\n selectedElements.forEach(selectedElement => {\n const [start, end] = (draggingPoints === null || draggingPoints === void 0 ? void 0 : draggingPoints.length) ? // The arrow edge points are dragged (i.e. start, end)\n getBindingStrategyForDraggingArrowEndpoints(selectedElement, isBindingEnabled, draggingPoints !== null && draggingPoints !== void 0 ? draggingPoints : [], app) : // The arrow itself (the shaft) or the inner joins are dragged\n getBindingStrategyForDraggingArrowOrJoints(selectedElement, app, isBindingEnabled);\n bindOrUnbindLinearElement(selectedElement, start, end, app.scene.getNonDeletedElementsMap());\n });\n};\nconst getSuggestedBindingsForArrows = (selectedElements, app) => {\n // HOT PATH: Bail out if selected elements list is too large\n if (selectedElements.length > 50) {\n return [];\n }\n\n return selectedElements.filter(_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isLinearElement).flatMap(element => getOriginalBindingsIfStillCloseToArrowEnds(element, app)).filter(element => element !== null) // Filter out bind candidates which are in the\n // same selection / group with the arrow\n //\n // TODO: Is it worth turning the list into a set to avoid dupes?\n .filter(element => selectedElements.filter(selected => selected.id === (element === null || element === void 0 ? void 0 : element.id)).length === 0);\n};\nconst maybeBindLinearElement = (linearElement, appState, pointerCoords, app) => {\n if (appState.startBoundElement != null) {\n bindLinearElement(linearElement, appState.startBoundElement, \"start\", app.scene.getNonDeletedElementsMap());\n }\n\n const hoveredElement = getHoveredElementForBinding(pointerCoords, app);\n\n if (hoveredElement != null && !isLinearElementSimpleAndAlreadyBoundOnOppositeEdge(linearElement, hoveredElement, \"end\")) {\n bindLinearElement(linearElement, hoveredElement, \"end\", app.scene.getNonDeletedElementsMap());\n }\n};\nconst bindLinearElement = (linearElement, hoveredElement, startOrEnd, elementsMap) => {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isArrowElement)(linearElement)) {\n return;\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(linearElement, {\n [startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\"]: Object.assign({\n elementId: hoveredElement.id\n }, calculateFocusAndGap(linearElement, hoveredElement, startOrEnd, elementsMap))\n });\n const boundElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_12__.arrayToMap)(hoveredElement.boundElements || []);\n\n if (!boundElementsMap.has(linearElement.id)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(hoveredElement, {\n boundElements: (hoveredElement.boundElements || []).concat({\n id: linearElement.id,\n type: \"arrow\"\n })\n });\n }\n}; // Don't bind both ends of a simple segment\n\nconst isLinearElementSimpleAndAlreadyBoundOnOppositeEdge = (linearElement, bindableElement, startOrEnd) => {\n const otherBinding = linearElement[startOrEnd === \"start\" ? \"endBinding\" : \"startBinding\"];\n return isLinearElementSimpleAndAlreadyBound(linearElement, otherBinding === null || otherBinding === void 0 ? void 0 : otherBinding.elementId, bindableElement);\n};\n\nconst isLinearElementSimpleAndAlreadyBound = (linearElement, alreadyBoundToId, bindableElement) => {\n return alreadyBoundToId === bindableElement.id && isLinearElementSimple(linearElement);\n};\n\nconst isLinearElementSimple = linearElement => linearElement.points.length < 3;\n\nconst unbindLinearElement = (linearElement, startOrEnd) => {\n const field = startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\";\n const binding = linearElement[field];\n\n if (binding == null) {\n return null;\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(linearElement, {\n [field]: null\n });\n return binding.elementId;\n};\n\nconst getHoveredElementForBinding = (pointerCoords, app) => {\n const hoveredElement = (0,_scene__WEBPACK_IMPORTED_MODULE_7__.getElementAtPosition)(app.scene.getNonDeletedElements(), element => (0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(element, false) && bindingBorderTest(element, pointerCoords, app));\n return hoveredElement;\n};\n\nconst calculateFocusAndGap = (linearElement, hoveredElement, startOrEnd, elementsMap) => {\n const direction = startOrEnd === \"start\" ? -1 : 1;\n const edgePointIndex = direction === -1 ? 0 : linearElement.points.length - 1;\n const adjacentPointIndex = edgePointIndex - direction;\n const edgePoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, edgePointIndex, elementsMap);\n const adjacentPoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, adjacentPointIndex, elementsMap);\n return {\n focus: determineFocusDistance(hoveredElement, adjacentPoint, edgePoint, elementsMap),\n gap: Math.max(1, distanceToBindableElement(hoveredElement, edgePoint, elementsMap))\n };\n}; // Supports translating, rotating and scaling `changedElement` with bound\n// linear elements.\n// Because scaling involves moving the focus points as well, it is\n// done before the `changedElement` is updated, and the `newSize` is passed\n// in explicitly.\n\n\nconst updateBoundElements = (changedElement, elementsMap, options) => {\n const {\n newSize,\n simultaneouslyUpdated\n } = options !== null && options !== void 0 ? options : {};\n const simultaneouslyUpdatedElementIds = getSimultaneouslyUpdatedElementIds(simultaneouslyUpdated);\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(changedElement)) {\n return;\n }\n\n boundElementsVisitor(elementsMap, changedElement, element => {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isLinearElement)(element) || element.isDeleted) {\n return;\n } // In case the boundElements are stale\n\n\n if (!doesNeedUpdate(element, changedElement)) {\n return;\n }\n\n const bindings = {\n startBinding: maybeCalculateNewGapWhenScaling(changedElement, element.startBinding, newSize),\n endBinding: maybeCalculateNewGapWhenScaling(changedElement, element.endBinding, newSize)\n }; // `linearElement` is being moved/scaled already, just update the binding\n\n if (simultaneouslyUpdatedElementIds.has(element.id)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(element, bindings);\n return;\n }\n\n bindableElementsVisitor(elementsMap, element, (bindableElement, bindingProp) => {\n if (bindableElement && (0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(bindableElement) && (bindingProp === \"startBinding\" || bindingProp === \"endBinding\")) {\n updateBoundPoint(element, bindingProp, bindings[bindingProp], bindableElement, elementsMap);\n }\n });\n const boundText = (0,_textElement__WEBPACK_IMPORTED_MODULE_14__.getBoundTextElement)(element, elementsMap);\n\n if (boundText && !boundText.isDeleted) {\n (0,_textElement__WEBPACK_IMPORTED_MODULE_14__.handleBindTextResize)(element, elementsMap, false);\n }\n });\n};\n\nconst doesNeedUpdate = (boundElement, changedElement) => {\n var _a, _b;\n\n return ((_a = boundElement.startBinding) === null || _a === void 0 ? void 0 : _a.elementId) === changedElement.id || ((_b = boundElement.endBinding) === null || _b === void 0 ? void 0 : _b.elementId) === changedElement.id;\n};\n\nconst getSimultaneouslyUpdatedElementIds = simultaneouslyUpdated => {\n return new Set((simultaneouslyUpdated || []).map(element => element.id));\n};\n\nconst updateBoundPoint = (linearElement, startOrEnd, binding, bindableElement, elementsMap) => {\n if (binding == null || // We only need to update the other end if this is a 2 point line element\n binding.elementId !== bindableElement.id && linearElement.points.length > 2) {\n return;\n }\n\n const direction = startOrEnd === \"startBinding\" ? -1 : 1;\n const edgePointIndex = direction === -1 ? 0 : linearElement.points.length - 1;\n const adjacentPointIndex = edgePointIndex - direction;\n const adjacentPoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, adjacentPointIndex, elementsMap);\n const focusPointAbsolute = determineFocusPoint(bindableElement, binding.focus, adjacentPoint, elementsMap);\n let newEdgePoint; // The linear element was not originally pointing inside the bound shape,\n // we can point directly at the focus point\n\n if (binding.gap === 0) {\n newEdgePoint = focusPointAbsolute;\n } else {\n const intersections = intersectElementWithLine(bindableElement, adjacentPoint, focusPointAbsolute, binding.gap, elementsMap);\n\n if (intersections.length === 0) {\n // This should never happen, since focusPoint should always be\n // inside the element, but just in case, bail out\n newEdgePoint = focusPointAbsolute;\n } else {\n // Guaranteed to intersect because focusPoint is always inside the shape\n newEdgePoint = intersections[0];\n }\n }\n\n _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.movePoints(linearElement, [{\n index: edgePointIndex,\n point: _linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.pointFromAbsoluteCoords(linearElement, newEdgePoint, elementsMap)\n }], {\n [startOrEnd]: binding\n });\n};\n\nconst maybeCalculateNewGapWhenScaling = (changedElement, currentBinding, newSize) => {\n if (currentBinding == null || newSize == null) {\n return currentBinding;\n }\n\n const {\n gap,\n focus,\n elementId\n } = currentBinding;\n const {\n width: newWidth,\n height: newHeight\n } = newSize;\n const {\n width,\n height\n } = changedElement;\n const newGap = Math.max(1, Math.min(maxBindingGap(changedElement, newWidth, newHeight), gap * (newWidth < newHeight ? newWidth / width : newHeight / height)));\n return {\n elementId,\n gap: newGap,\n focus\n };\n};\n\nconst getElligibleElementForBindingElement = (linearElement, startOrEnd, app) => {\n return getHoveredElementForBinding(getLinearElementEdgeCoors(linearElement, startOrEnd, app.scene.getNonDeletedElementsMap()), app);\n};\n\nconst getLinearElementEdgeCoors = (linearElement, startOrEnd, elementsMap) => {\n const index = startOrEnd === \"start\" ? 0 : -1;\n return (0,_utils__WEBPACK_IMPORTED_MODULE_12__.tupleToCoors)(_linearElementEditor__WEBPACK_IMPORTED_MODULE_11__.LinearElementEditor.getPointAtIndexGlobalCoordinates(linearElement, index, elementsMap));\n}; // We need to:\n// 1: Update elements not selected to point to duplicated elements\n// 2: Update duplicated elements to point to other duplicated elements\n\n\nconst fixBindingsAfterDuplication = (sceneElements, oldElements, oldIdToDuplicatedId, // There are three copying mechanisms: Copy-paste, duplication and alt-drag.\n// Only when alt-dragging the new \"duplicates\" act as the \"old\", while\n// the \"old\" elements act as the \"new copy\" - essentially working reverse\n// to the other two.\nduplicatesServeAsOld) => {\n // First collect all the binding/bindable elements, so we only update\n // each once, regardless of whether they were duplicated or not.\n const allBoundElementIds = new Set();\n const allBindableElementIds = new Set();\n const shouldReverseRoles = duplicatesServeAsOld === \"duplicatesServeAsOld\";\n oldElements.forEach(oldElement => {\n const {\n boundElements\n } = oldElement;\n\n if (boundElements != null && boundElements.length > 0) {\n boundElements.forEach(boundElement => {\n if (shouldReverseRoles && !oldIdToDuplicatedId.has(boundElement.id)) {\n allBoundElementIds.add(boundElement.id);\n }\n });\n allBindableElementIds.add(oldIdToDuplicatedId.get(oldElement.id));\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindingElement)(oldElement)) {\n if (oldElement.startBinding != null) {\n const {\n elementId\n } = oldElement.startBinding;\n\n if (shouldReverseRoles && !oldIdToDuplicatedId.has(elementId)) {\n allBindableElementIds.add(elementId);\n }\n }\n\n if (oldElement.endBinding != null) {\n const {\n elementId\n } = oldElement.endBinding;\n\n if (shouldReverseRoles && !oldIdToDuplicatedId.has(elementId)) {\n allBindableElementIds.add(elementId);\n }\n }\n\n if (oldElement.startBinding != null || oldElement.endBinding != null) {\n allBoundElementIds.add(oldIdToDuplicatedId.get(oldElement.id));\n }\n }\n }); // Update the linear elements\n\n sceneElements.filter(({\n id\n }) => allBoundElementIds.has(id)).forEach(element => {\n const {\n startBinding,\n endBinding\n } = element;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(element, {\n startBinding: newBindingAfterDuplication(startBinding, oldIdToDuplicatedId),\n endBinding: newBindingAfterDuplication(endBinding, oldIdToDuplicatedId)\n });\n }); // Update the bindable shapes\n\n sceneElements.filter(({\n id\n }) => allBindableElementIds.has(id)).forEach(bindableElement => {\n const {\n boundElements\n } = bindableElement;\n\n if (boundElements != null && boundElements.length > 0) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement)(bindableElement, {\n boundElements: boundElements.map(boundElement => oldIdToDuplicatedId.has(boundElement.id) ? {\n id: oldIdToDuplicatedId.get(boundElement.id),\n type: boundElement.type\n } : boundElement)\n });\n }\n });\n};\n\nconst newBindingAfterDuplication = (binding, oldIdToDuplicatedId) => {\n var _a;\n\n if (binding == null) {\n return null;\n }\n\n const {\n elementId,\n focus,\n gap\n } = binding;\n return {\n focus,\n gap,\n elementId: (_a = oldIdToDuplicatedId.get(elementId)) !== null && _a !== void 0 ? _a : elementId\n };\n};\n\nconst fixBindingsAfterDeletion = (sceneElements, deletedElements) => {\n const elements = (0,_utils__WEBPACK_IMPORTED_MODULE_12__.arrayToMap)(sceneElements);\n\n for (const element of deletedElements) {\n BoundElement.unbindAffected(elements, element, _mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement);\n BindableElement.unbindAffected(elements, element, _mutateElement__WEBPACK_IMPORTED_MODULE_9__.mutateElement);\n }\n};\n\nconst newBoundElements = (boundElements, idsToRemove, elementsToAdd = []) => {\n if (!boundElements) {\n return null;\n }\n\n const nextBoundElements = boundElements.filter(boundElement => !idsToRemove.has(boundElement.id));\n nextBoundElements.push(...elementsToAdd.map(x => ({\n id: x.id,\n type: x.type\n })));\n return nextBoundElements;\n};\n\nconst bindingBorderTest = (element, {\n x,\n y\n}, app) => {\n const threshold = maxBindingGap(element, element.width, element.height);\n const shape = app.getElementShape(element);\n return (0,_utils_collision__WEBPACK_IMPORTED_MODULE_6__.isPointOnShape)([x, y], shape, threshold);\n};\n\nconst maxBindingGap = (element, elementWidth, elementHeight) => {\n // Aligns diamonds with rectangles\n const shapeRatio = element.type === \"diamond\" ? 1 / Math.sqrt(2) : 1;\n const smallerDimension = shapeRatio * Math.min(elementWidth, elementHeight); // We make the bindable boundary bigger for bigger elements\n\n return Math.max(16, Math.min(0.25 * smallerDimension, 32));\n};\n\nconst distanceToBindableElement = (element, point, elementsMap) => {\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n return distanceToRectangle(element, point, elementsMap);\n\n case \"diamond\":\n return distanceToDiamond(element, point, elementsMap);\n\n case \"ellipse\":\n return distanceToEllipse(element, point, elementsMap);\n }\n};\n\nconst distanceToRectangle = (element, point, elementsMap) => {\n const [, pointRel, hwidth, hheight] = pointRelativeToElement(element, point, elementsMap);\n return Math.max(_gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, _galines__WEBPACK_IMPORTED_MODULE_3__.equation(0, 1, -hheight)), _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, _galines__WEBPACK_IMPORTED_MODULE_3__.equation(1, 0, -hwidth)));\n};\n\nconst distanceToDiamond = (element, point, elementsMap) => {\n const [, pointRel, hwidth, hheight] = pointRelativeToElement(element, point, elementsMap);\n const side = _galines__WEBPACK_IMPORTED_MODULE_3__.equation(hheight, hwidth, -hheight * hwidth);\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, side);\n};\n\nconst distanceToEllipse = (element, point, elementsMap) => {\n const [pointRel, tangent] = ellipseParamsForTest(element, point, elementsMap);\n return -_galines__WEBPACK_IMPORTED_MODULE_3__.sign(tangent) * _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(pointRel, tangent);\n};\n\nconst ellipseParamsForTest = (element, point, elementsMap) => {\n const [, pointRel, hwidth, hheight] = pointRelativeToElement(element, point, elementsMap);\n const [px, py] = _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(pointRel); // We're working in positive quadrant, so start with `t = 45deg`, `tx=cos(t)`\n\n let tx = 0.707;\n let ty = 0.707;\n const a = hwidth;\n const b = hheight; // This is a numerical method to find the params tx, ty at which\n // the ellipse has the closest point to the given point\n\n [0, 1, 2, 3].forEach(_ => {\n const xx = a * tx;\n const yy = b * ty;\n const ex = (a * a - b * b) * tx ** 3 / a;\n const ey = (b * b - a * a) * ty ** 3 / b;\n const rx = xx - ex;\n const ry = yy - ey;\n const qx = px - ex;\n const qy = py - ey;\n const r = Math.hypot(ry, rx);\n const q = Math.hypot(qy, qx);\n tx = Math.min(1, Math.max(0, (qx * r / q + ex) / a));\n ty = Math.min(1, Math.max(0, (qy * r / q + ey) / b));\n const t = Math.hypot(ty, tx);\n tx /= t;\n ty /= t;\n });\n const closestPoint = _ga__WEBPACK_IMPORTED_MODULE_0__.point(a * tx, b * ty);\n const tangent = _galines__WEBPACK_IMPORTED_MODULE_3__.orthogonalThrough(pointRel, closestPoint);\n return [pointRel, tangent];\n}; // Returns:\n// 1. the point relative to the elements (x, y) position\n// 2. the point relative to the element's center with positive (x, y)\n// 3. half element width\n// 4. half element height\n//\n// Note that for linear elements the (x, y) position is not at the\n// top right corner of their boundary.\n//\n// Rectangles, diamonds and ellipses are symmetrical over axes,\n// and other elements have a rectangular boundary,\n// so we only need to perform hit tests for the positive quadrant.\n\n\nconst pointRelativeToElement = (element, pointTuple, elementsMap) => {\n const point = _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(pointTuple);\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getElementAbsoluteCoords)(element, elementsMap);\n const center = coordsCenter(x1, y1, x2, y2); // GA has angle orientation opposite to `rotate`\n\n const rotate = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.rotation(center, element.angle);\n const pointRotated = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(rotate, point);\n const pointRelToCenter = _ga__WEBPACK_IMPORTED_MODULE_0__.sub(pointRotated, _gadirections__WEBPACK_IMPORTED_MODULE_2__.from(center));\n const pointRelToCenterAbs = _gapoints__WEBPACK_IMPORTED_MODULE_1__.abs(pointRelToCenter);\n const elementPos = _ga__WEBPACK_IMPORTED_MODULE_0__.offset(element.x, element.y);\n const pointRelToPos = _ga__WEBPACK_IMPORTED_MODULE_0__.sub(pointRotated, elementPos);\n const halfWidth = (x2 - x1) / 2;\n const halfHeight = (y2 - y1) / 2;\n return [pointRelToPos, pointRelToCenterAbs, halfWidth, halfHeight];\n};\n\nconst relativizationToElementCenter = (element, elementsMap) => {\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getElementAbsoluteCoords)(element, elementsMap);\n const center = coordsCenter(x1, y1, x2, y2); // GA has angle orientation opposite to `rotate`\n\n const rotate = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.rotation(center, element.angle);\n const translate = _ga__WEBPACK_IMPORTED_MODULE_0__.reverse(_gatransforms__WEBPACK_IMPORTED_MODULE_4__.translation(_gadirections__WEBPACK_IMPORTED_MODULE_2__.from(center)));\n return _gatransforms__WEBPACK_IMPORTED_MODULE_4__.compose(rotate, translate);\n};\n\nconst coordsCenter = (x1, y1, x2, y2) => {\n return _ga__WEBPACK_IMPORTED_MODULE_0__.point((x1 + x2) / 2, (y1 + y2) / 2);\n}; // The focus distance is the oriented ratio between the size of\n// the `element` and the \"focus image\" of the element on which\n// all focus points lie, so it's a number between -1 and 1.\n// The line going through `a` and `b` is a tangent to the \"focus image\"\n// of the element.\n\n\nconst determineFocusDistance = ( //zsviczian added export\nelement, // Point on the line, in absolute coordinates\na, // Another point on the line, in absolute coordinates (closer to element)\nb, elementsMap) => {\n const relateToCenter = relativizationToElementCenter(element, elementsMap);\n const aRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(a));\n const bRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(b));\n const line = _galines__WEBPACK_IMPORTED_MODULE_3__.through(aRel, bRel);\n const q = element.height / element.width;\n const hwidth = element.width / 2;\n const hheight = element.height / 2;\n const n = line[2];\n const m = line[3];\n const c = line[1];\n const mabs = Math.abs(m);\n const nabs = Math.abs(n);\n let ret;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n ret = c / (hwidth * (nabs + q * mabs));\n break;\n\n case \"diamond\":\n ret = mabs < nabs ? c / (nabs * hwidth) : c / (mabs * hheight);\n break;\n\n case \"ellipse\":\n ret = c / (hwidth * Math.sqrt(n ** 2 + q ** 2 * m ** 2));\n break;\n }\n\n return ret || 0;\n};\n\nconst determineFocusPoint = (element, // The oriented, relative distance from the center of `element` of the\n// returned focusPoint\nfocus, adjecentPoint, elementsMap) => {\n if (focus === 0) {\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getElementAbsoluteCoords)(element, elementsMap);\n const center = coordsCenter(x1, y1, x2, y2);\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(center);\n }\n\n const relateToCenter = relativizationToElementCenter(element, elementsMap);\n const adjecentPointRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(adjecentPoint));\n const reverseRelateToCenter = _ga__WEBPACK_IMPORTED_MODULE_0__.reverse(relateToCenter);\n let point;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"diamond\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n point = findFocusPointForRectangulars(element, focus, adjecentPointRel);\n break;\n\n case \"ellipse\":\n point = findFocusPointForEllipse(element, focus, adjecentPointRel);\n break;\n }\n\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(_gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(reverseRelateToCenter, point));\n}; // Returns 2 or 0 intersection points between line going through `a` and `b`\n// and the `element`, in ascending order of distance from `a`.\n\n\nconst intersectElementWithLine = ( //zsviczian added export\nelement, // Point on the line, in absolute coordinates\na, // Another point on the line, in absolute coordinates\nb, // If given, the element is inflated by this value\ngap = 0, elementsMap) => {\n const relateToCenter = relativizationToElementCenter(element, elementsMap);\n const aRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(a));\n const bRel = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(relateToCenter, _gapoints__WEBPACK_IMPORTED_MODULE_1__.from(b));\n const line = _galines__WEBPACK_IMPORTED_MODULE_3__.through(aRel, bRel);\n const reverseRelateToCenter = _ga__WEBPACK_IMPORTED_MODULE_0__.reverse(relateToCenter);\n const intersections = getSortedElementLineIntersections(element, line, aRel, gap);\n return intersections.map(point => _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(_gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(reverseRelateToCenter, point)));\n};\n\nconst getSortedElementLineIntersections = (element, // Relative to element center\nline, // Relative to element center\nnearPoint, gap = 0) => {\n let intersections;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"diamond\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n const corners = getCorners(element);\n intersections = corners.flatMap((point, i) => {\n const edge = [point, corners[(i + 1) % 4]];\n return intersectSegment(line, offsetSegment(edge, gap));\n }).concat(corners.flatMap(point => getCircleIntersections(point, gap, line)));\n break;\n\n case \"ellipse\":\n intersections = getEllipseIntersections(element, gap, line);\n break;\n }\n\n if (intersections.length < 2) {\n // Ignore the \"edge\" case of only intersecting with a single corner\n return [];\n }\n\n const sortedIntersections = intersections.sort((i1, i2) => _gapoints__WEBPACK_IMPORTED_MODULE_1__.distance(i1, nearPoint) - _gapoints__WEBPACK_IMPORTED_MODULE_1__.distance(i2, nearPoint));\n return [sortedIntersections[0], sortedIntersections[sortedIntersections.length - 1]];\n};\n\nconst getCorners = (element, scale = 1) => {\n const hx = scale * element.width / 2;\n const hy = scale * element.height / 2;\n\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point(hx, hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(hx, -hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(-hx, -hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(-hx, hy)];\n\n case \"diamond\":\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point(0, hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(hx, 0), _ga__WEBPACK_IMPORTED_MODULE_0__.point(0, -hy), _ga__WEBPACK_IMPORTED_MODULE_0__.point(-hx, 0)];\n }\n}; // Returns intersection of `line` with `segment`, with `segment` moved by\n// `gap` in its polar direction.\n// If intersection coincides with second segment point returns empty array.\n\n\nconst intersectSegment = (line, segment) => {\n const [a, b] = segment;\n const aDist = _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(a, line);\n const bDist = _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(b, line);\n\n if (aDist * bDist >= 0) {\n // The intersection is outside segment `(a, b)`\n return [];\n }\n\n return [_gapoints__WEBPACK_IMPORTED_MODULE_1__.intersect(line, _galines__WEBPACK_IMPORTED_MODULE_3__.through(a, b))];\n};\n\nconst offsetSegment = (segment, distance) => {\n const [a, b] = segment;\n const offset = _gatransforms__WEBPACK_IMPORTED_MODULE_4__.translationOrthogonal(_gadirections__WEBPACK_IMPORTED_MODULE_2__.fromTo(a, b), distance);\n return [_gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(offset, a), _gatransforms__WEBPACK_IMPORTED_MODULE_4__.apply(offset, b)];\n};\n\nconst getEllipseIntersections = (element, gap, line) => {\n const a = element.width / 2 + gap;\n const b = element.height / 2 + gap;\n const m = line[2];\n const n = line[3];\n const c = line[1];\n const squares = a * a * m * m + b * b * n * n;\n const discr = squares - c * c;\n\n if (squares === 0 || discr <= 0) {\n return [];\n }\n\n const discrRoot = Math.sqrt(discr);\n const xn = -a * a * m * c;\n const yn = -b * b * n * c;\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point((xn + a * b * n * discrRoot) / squares, (yn - a * b * m * discrRoot) / squares), _ga__WEBPACK_IMPORTED_MODULE_0__.point((xn - a * b * n * discrRoot) / squares, (yn + a * b * m * discrRoot) / squares)];\n};\n\nconst getCircleIntersections = (center, radius, line) => {\n if (radius === 0) {\n return _gapoints__WEBPACK_IMPORTED_MODULE_1__.distanceToLine(line, center) === 0 ? [center] : [];\n }\n\n const m = line[2];\n const n = line[3];\n const c = line[1];\n const [a, b] = _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(center);\n const r = radius;\n const squares = m * m + n * n;\n const discr = r * r * squares - (m * a + n * b + c) ** 2;\n\n if (squares === 0 || discr <= 0) {\n return [];\n }\n\n const discrRoot = Math.sqrt(discr);\n const xn = a * n * n - b * m * n - m * c;\n const yn = b * m * m - a * m * n - n * c;\n return [_ga__WEBPACK_IMPORTED_MODULE_0__.point((xn + n * discrRoot) / squares, (yn - m * discrRoot) / squares), _ga__WEBPACK_IMPORTED_MODULE_0__.point((xn - n * discrRoot) / squares, (yn + m * discrRoot) / squares)];\n}; // The focus point is the tangent point of the \"focus image\" of the\n// `element`, where the tangent goes through `point`.\n\n\nconst findFocusPointForEllipse = (ellipse, // Between -1 and 1 (not 0) the relative size of the \"focus image\" of\n// the element on which the focus point lies\nrelativeDistance, // The point for which we're trying to find the focus point, relative\n// to the ellipse center.\npoint) => {\n const relativeDistanceAbs = Math.abs(relativeDistance);\n const a = ellipse.width * relativeDistanceAbs / 2;\n const b = ellipse.height * relativeDistanceAbs / 2;\n const orientation = Math.sign(relativeDistance);\n const [px, pyo] = _gapoints__WEBPACK_IMPORTED_MODULE_1__.toTuple(point); // The calculation below can't handle py = 0\n\n const py = pyo === 0 ? 0.0001 : pyo;\n const squares = px ** 2 * b ** 2 + py ** 2 * a ** 2; // Tangent mx + ny + 1 = 0\n\n const m = (-px * b ** 2 + orientation * py * Math.sqrt(Math.max(0, squares - a ** 2 * b ** 2))) / squares;\n let n = (-m * px - 1) / py;\n\n if (n === 0) {\n // if zero {-0, 0}, fall back to a same-sign value in the similar range\n n = (Object.is(n, -0) ? -1 : 1) * 0.01;\n }\n\n const x = -(a ** 2 * m) / (n ** 2 * b ** 2 + m ** 2 * a ** 2);\n return _ga__WEBPACK_IMPORTED_MODULE_0__.point(x, (-m * x - 1) / (n === 0 ? 0.0001 : n)); //zsviczian https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1054\n};\n\nconst findFocusPointForRectangulars = (element, // Between -1 and 1 for how far away should the focus point be relative\n// to the size of the element. Sign determines orientation.\nrelativeDistance, // The point for which we're trying to find the focus point, relative\n// to the element center.\npoint) => {\n const relativeDistanceAbs = Math.abs(relativeDistance);\n const orientation = Math.sign(relativeDistance);\n const corners = getCorners(element, relativeDistanceAbs);\n let maxDistance = 0;\n let tangentPoint = null;\n corners.forEach(corner => {\n const distance = orientation * _galines__WEBPACK_IMPORTED_MODULE_3__.through(point, corner)[1];\n\n if (distance > maxDistance) {\n maxDistance = distance;\n tangentPoint = corner;\n }\n });\n return tangentPoint;\n};\n\nconst bindingProperties = new Set([\"boundElements\", \"frameId\", \"containerId\", \"startBinding\", \"endBinding\"]);\n/**\r\n * Tries to visit each bound element (does not have to be found).\r\n */\n\nconst boundElementsVisitor = (elements, element, visit) => {\n var _a, _b;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBindableElement)(element)) {\n // create new instance so that possible mutations won't play a role in visiting order\n const boundElements = (_b = (_a = element.boundElements) === null || _a === void 0 ? void 0 : _a.slice()) !== null && _b !== void 0 ? _b : []; // last added text should be the one we keep (~previous are duplicates)\n\n boundElements.forEach(({\n id\n }) => {\n visit(elements.get(id), \"boundElements\", id);\n });\n }\n};\n/**\r\n * Tries to visit each bindable element (does not have to be found).\r\n */\n\n\nconst bindableElementsVisitor = (elements, element, visit) => {\n if (element.frameId) {\n const id = element.frameId;\n visit(elements.get(id), \"frameId\", id);\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isBoundToContainer)(element)) {\n const id = element.containerId;\n visit(elements.get(id), \"containerId\", id);\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isArrowElement)(element)) {\n if (element.startBinding) {\n const id = element.startBinding.elementId;\n visit(elements.get(id), \"startBinding\", id);\n }\n\n if (element.endBinding) {\n const id = element.endBinding.elementId;\n visit(elements.get(id), \"endBinding\", id);\n }\n }\n};\n/**\r\n * Bound element containing bindings to `frameId`, `containerId`, `startBinding` or `endBinding`.\r\n */\n\n\nclass BoundElement {\n /**\r\n * Unbind the affected non deleted bindable elements (removing element from `boundElements`).\r\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\r\n * - prepares updates to unbind each bindable element's `boundElements` from the current element\r\n */\n static unbindAffected(elements, boundElement, updateElementWith) {\n if (!boundElement) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, bindableElement => {\n // bindable element is deleted, this is fine\n if (!bindableElement || bindableElement.isDeleted) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, (_, __, boundElementId) => {\n if (boundElementId === boundElement.id) {\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set([boundElementId]))\n });\n }\n });\n });\n }\n\n}\n/**\r\n * Rebind the next affected non deleted bindable elements (adding element to `boundElements`).\r\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\r\n * - prepares updates to rebind each bindable element's `boundElements` to the current element\r\n *\r\n * NOTE: rebind expects that affected elements were previously unbound with `BoundElement.unbindAffected`\r\n */\n\nBoundElement.rebindAffected = (elements, boundElement, updateElementWith) => {\n // don't try to rebind element that is deleted\n if (!boundElement || boundElement.isDeleted) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, (bindableElement, bindingProp) => {\n var _a, _b; // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\n\n\n if (!bindableElement || bindableElement.isDeleted) {\n updateElementWith(boundElement, {\n [bindingProp]: null\n });\n return;\n } // frame bindings are unidirectional, there is nothing to rebind\n\n\n if (bindingProp === \"frameId\") {\n return;\n }\n\n if ((_a = bindableElement.boundElements) === null || _a === void 0 ? void 0 : _a.find(x => x.id === boundElement.id)) {\n return;\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isArrowElement)(boundElement)) {\n // rebind if not found!\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set(), new Array(boundElement))\n });\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isTextElement)(boundElement)) {\n if (!((_b = bindableElement.boundElements) === null || _b === void 0 ? void 0 : _b.find(x => x.type === \"text\"))) {\n // rebind only if there is no other text bound already\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set(), new Array(boundElement))\n });\n } else {\n // unbind otherwise\n updateElementWith(boundElement, {\n [bindingProp]: null\n });\n }\n }\n });\n};\n/**\r\n * Bindable element containing bindings to `boundElements`.\r\n */\n\n\nclass BindableElement {\n /**\r\n * Unbind the affected non deleted bound elements (resetting `containerId`, `startBinding`, `endBinding` to `null`).\r\n * - iterates through non deleted `boundElements` of the current element\r\n * - prepares updates to unbind each bound element from the current element\r\n */\n static unbindAffected(elements, bindableElement, updateElementWith) {\n if (!bindableElement) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, boundElement => {\n // bound element is deleted, this is fine\n if (!boundElement || boundElement.isDeleted) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, (_, bindingProp, bindableElementId) => {\n // making sure there is an element to be unbound\n if (bindableElementId === bindableElement.id) {\n updateElementWith(boundElement, {\n [bindingProp]: null\n });\n }\n });\n });\n }\n\n}\n/**\r\n * Rebind the affected non deleted bound elements (for now setting only `containerId`, as we cannot rebind arrows atm).\r\n * - iterates through non deleted `boundElements` of the current element\r\n * - prepares updates to rebind each bound element to the current element or unbind it from `boundElements` in case of conflicts\r\n *\r\n * NOTE: rebind expects that affected elements were previously unbound with `BindaleElement.unbindAffected`\r\n */\n\nBindableElement.rebindAffected = (elements, bindableElement, updateElementWith) => {\n // don't try to rebind element that is deleted (i.e. updated as deleted)\n if (!bindableElement || bindableElement.isDeleted) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, (boundElement, _, boundElementId) => {\n var _a, _b, _c; // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\n\n\n if (!boundElement || boundElement.isDeleted) {\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set([boundElementId]))\n });\n return;\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_8__.isTextElement)(boundElement)) {\n const boundElements = (_b = (_a = bindableElement.boundElements) === null || _a === void 0 ? void 0 : _a.slice()) !== null && _b !== void 0 ? _b : []; // check if this is the last element in the array, if not, there is an previously bound text which should be unbound\n\n if (((_c = boundElements.reverse().find(x => x.type === \"text\")) === null || _c === void 0 ? void 0 : _c.id) === boundElement.id) {\n if (boundElement.containerId !== bindableElement.id) {\n // rebind if not bound already!\n updateElementWith(boundElement, {\n containerId: bindableElement.id\n });\n }\n } else {\n if (boundElement.containerId !== null) {\n // unbind if not unbound already\n updateElementWith(boundElement, {\n containerId: null\n });\n } // unbind from boundElements as the element got bound to some other element in the meantime\n\n\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(bindableElement.boundElements, new Set([boundElement.id]))\n });\n }\n }\n });\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/binding.ts?");
|
|
2645
2645
|
|
|
2646
2646
|
/***/ }),
|
|
2647
2647
|
|
|
@@ -3213,7 +3213,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
3213
3213
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
3214
3214
|
|
|
3215
3215
|
"use strict";
|
|
3216
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ \"./constants.ts\");\n\n\nif (\"development\" !== _constants__WEBPACK_IMPORTED_MODULE_0__.ENV.TEST) {\n /* eslint-disable */\n\n /* global __webpack_public_path__:writable */\n __webpack_require__.p = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${\"@zsviczian/excalidraw\"}@${\"0.17.1-obsidian-
|
|
3216
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ \"./constants.ts\");\n\n\nif (\"development\" !== _constants__WEBPACK_IMPORTED_MODULE_0__.ENV.TEST) {\n /* eslint-disable */\n\n /* global __webpack_public_path__:writable */\n __webpack_require__.p = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${\"@zsviczian/excalidraw\"}@${\"0.17.1-obsidian-28\"}/dist/`;\n}\n\n//# sourceURL=webpack://ExcalidrawLib/./publicPath.js?");
|
|
3217
3217
|
|
|
3218
3218
|
/***/ }),
|
|
3219
3219
|
|