@zsviczian/excalidraw 0.17.6-8 → 0.17.6-9

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.
@@ -792,7 +792,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
792
792
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
793
793
 
794
794
  "use strict";
795
- 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 = new Set([\"command_palette\", \"export\"]);\nconst trackEvent = (category, action, label, value) => {\n try {\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_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_ENABLE_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.6-8\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).VITE_WORKER_ID || \"true\" !== \"true\") {\n return;\n }\n\n if (!ALLOWED_CATEGORIES_TO_TRACK.has(category)) {\n return;\n }\n\n if (true) {\n // comment out to debug in dev\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?");
795
+ 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 = new Set([\"command_palette\", \"export\"]);\nconst trackEvent = (category, action, label, value) => {\n try {\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_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_ENABLE_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.6-9\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).VITE_WORKER_ID || \"true\" !== \"true\") {\n return;\n }\n\n if (!ALLOWED_CATEGORIES_TO_TRACK.has(category)) {\n return;\n }\n\n if (true) {\n // comment out to debug in dev\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?");
796
796
 
797
797
  /***/ }),
798
798
 
@@ -924,7 +924,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
924
924
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
925
925
 
926
926
  "use strict";
927
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ExcalidrawContainerContext\": () => (/* binding */ ExcalidrawContainerContext),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ \"useApp\": () => (/* binding */ useApp),\n/* harmony export */ \"useAppProps\": () => (/* binding */ useAppProps),\n/* harmony export */ \"useDevice\": () => (/* binding */ useDevice),\n/* harmony export */ \"useExcalidrawActionManager\": () => (/* binding */ useExcalidrawActionManager),\n/* harmony export */ \"useExcalidrawAppState\": () => (/* binding */ useExcalidrawAppState),\n/* harmony export */ \"useExcalidrawContainer\": () => (/* binding */ useExcalidrawContainer),\n/* harmony export */ \"useExcalidrawElements\": () => (/* binding */ useExcalidrawElements),\n/* harmony export */ \"useExcalidrawSetAppState\": () => (/* binding */ useExcalidrawSetAppState)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! clsx */ \"../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var nanoid__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(/*! nanoid */ \"./node_modules/nanoid/index.browser.js\");\n/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../actions */ \"./actions/index.ts\");\n/* harmony import */ var _actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../actions/actionHistory */ \"./actions/actionHistory.tsx\");\n/* harmony import */ var _actions_manager__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../actions/manager */ \"./actions/manager.tsx\");\n/* harmony import */ var _actions_register__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../actions/register */ \"./actions/register.ts\");\n/* harmony import */ var _analytics__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../analytics */ \"./analytics.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../clipboard */ \"./clipboard.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../data */ \"./data/index.ts\");\n/* harmony import */ var _data_library__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../data/library */ \"./data/library.ts\");\n/* harmony import */ var _data_restore__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../data/restore */ \"./data/restore.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_binding__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../element/binding */ \"./element/binding.ts\");\n/* harmony import */ var _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../element/linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../element/mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _element_newElement__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../element/newElement */ \"./element/newElement.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../element/typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _gesture__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../gesture */ \"./gesture.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../groups */ \"./groups.ts\");\n/* harmony import */ var _history__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../history */ \"./history.ts\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../i18n */ \"./i18n.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../keys */ \"./keys.ts\");\n/* harmony import */ var _element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../element/sizeHelpers */ \"./element/sizeHelpers.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../scene */ \"./scene/index.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _scene_zoom__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../scene/zoom */ \"./scene/zoom.ts\");\n/* harmony import */ var _shapes__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../shapes */ \"./shapes.tsx\");\n/* harmony import */ var _utils_geometry_shape__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../../utils/geometry/shape */ \"../utils/geometry/shape.ts\");\n/* harmony import */ var _utils_collision__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../../utils/collision */ \"../utils/collision.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _element_embeddable__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ../element/embeddable */ \"./element/embeddable.ts\");\n/* harmony import */ var _ContextMenu__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./ContextMenu */ \"./components/ContextMenu.tsx\");\n/* harmony import */ var _LayerUI__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./LayerUI */ \"./components/LayerUI.tsx\");\n/* harmony import */ var _Toast__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./Toast */ \"./components/Toast.tsx\");\n/* harmony import */ var _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../actions/actionToggleViewMode */ \"./actions/actionToggleViewMode.tsx\");\n/* harmony import */ var _data_blob__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../data/blob */ \"./data/blob.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ../element/image */ \"./element/image.ts\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! lodash.throttle */ \"../../node_modules/lodash.throttle/index.js\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_42___default = /*#__PURE__*/__webpack_require__.n(lodash_throttle__WEBPACK_IMPORTED_MODULE_42__);\n/* harmony import */ var _data_filesystem__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ../data/filesystem */ \"./data/filesystem.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ../components/hyperlink/Hyperlink */ \"./components/hyperlink/Hyperlink.tsx\");\n/* harmony import */ var _data_url__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ../data/url */ \"./data/url.ts\");\n/* harmony import */ var _element_transformHandles__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ../element/transformHandles */ \"./element/transformHandles.ts\");\n/* harmony import */ var _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ../actions/actionElementLock */ \"./actions/actionElementLock.ts\");\n/* harmony import */ var _fonts__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ../fonts */ \"./fonts/index.ts\");\n/* harmony import */ var _frame__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ../frame */ \"./frame.ts\");\n/* harmony import */ var _scene_selection__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ../scene/selection */ \"./scene/selection.ts\");\n/* harmony import */ var _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ../actions/actionClipboard */ \"./actions/actionClipboard.tsx\");\n/* harmony import */ var _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ../actions/actionFrame */ \"./actions/actionFrame.ts\");\n/* harmony import */ var _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ../actions/actionCanvas */ \"./actions/actionCanvas.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ../jotai */ \"./jotai.ts\");\n/* harmony import */ var _ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./ActiveConfirmDialog */ \"./components/ActiveConfirmDialog.tsx\");\n/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ../errors */ \"./errors.ts\");\n/* harmony import */ var _snapping__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ../snapping */ \"./snapping.ts\");\n/* harmony import */ var _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ../actions/actionBoundText */ \"./actions/actionBoundText.tsx\");\n/* harmony import */ var _BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ./BraveMeasureTextError */ \"./components/BraveMeasureTextError.tsx\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./EyeDropper */ \"./components/EyeDropper.tsx\");\n/* harmony import */ var _data_transform__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ../data/transform */ \"./data/transform.ts\");\n/* harmony import */ var _Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ./Sidebar/Sidebar */ \"./components/Sidebar/Sidebar.tsx\");\n/* harmony import */ var _canvases__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ./canvases */ \"./components/canvases/index.tsx\");\n/* harmony import */ var _scene_Renderer__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! ../scene/Renderer */ \"./scene/Renderer.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(/*! ../scene/ShapeCache */ \"./scene/ShapeCache.ts\");\n/* harmony import */ var _SVGLayer__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(/*! ./SVGLayer */ \"./components/SVGLayer.tsx\");\n/* harmony import */ var _cursor__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(/*! ../cursor */ \"./cursor.ts\");\n/* harmony import */ var _emitter__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(/*! ../emitter */ \"./emitter.ts\");\n/* harmony import */ var _element_ElementCanvasButtons__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(/*! ../element/ElementCanvasButtons */ \"./element/ElementCanvasButtons.tsx\");\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(/*! ../colors */ \"./colors.ts\");\n/* harmony import */ var _MagicButton__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(/*! ./MagicButton */ \"./components/MagicButton.tsx\");\n/* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(/*! ./icons */ \"./components/icons.tsx\");\n/* harmony import */ var _FollowMode_FollowMode__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(/*! ./FollowMode/FollowMode */ \"./components/FollowMode/FollowMode.tsx\");\n/* harmony import */ var _actions_actionProperties__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(/*! ../actions/actionProperties */ \"./actions/actionProperties.tsx\");\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(/*! ../store */ \"./store.ts\");\n/* harmony import */ var _animation_frame_handler__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(/*! ../animation-frame-handler */ \"./animation-frame-handler.ts\");\n/* harmony import */ var _animated_trail__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(/*! ../animated-trail */ \"./animated-trail.ts\");\n/* harmony import */ var _laser_trails__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(/*! ../laser-trails */ \"./laser-trails.ts\");\n/* harmony import */ var _reactUtils__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(/*! ../reactUtils */ \"./reactUtils.ts\");\n/* harmony import */ var _renderer_renderElement__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(/*! ../renderer/renderElement */ \"./renderer/renderElement.ts\");\n/* harmony import */ var _obsidianUtils__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(/*! ../obsidianUtils */ \"./obsidianUtils.ts\");\n/* harmony import */ var _element_collision__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(/*! ../element/collision */ \"./element/collision.ts\");\n/* harmony import */ var _element_textWysiwyg__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(/*! ../element/textWysiwyg */ \"./element/textWysiwyg.tsx\");\n/* harmony import */ var _scene_scrollbars__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(/*! ../scene/scrollbars */ \"./scene/scrollbars.ts\");\n/* harmony import */ var _fractionalIndex__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(/*! ../fractionalIndex */ \"./fractionalIndex.ts\");\n/* harmony import */ var _hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(/*! ./hyperlink/helpers */ \"./components/hyperlink/helpers.ts\");\n/* harmony import */ var _actions_shortcuts__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(/*! ../actions/shortcuts */ \"./actions/shortcuts.ts\");\n/* harmony import */ var _element_resizeElements__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(/*! ../element/resizeElements */ \"./element/resizeElements.ts\");\n/* harmony import */ var _actions_actionTextAutoResize__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(/*! ../actions/actionTextAutoResize */ \"./actions/actionTextAutoResize.ts\");\n/* harmony import */ var _element_bounds__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(/*! ../element/bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _mermaid__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(/*! ../mermaid */ \"./mermaid.ts\");\n/* harmony import */ var _Tooltip__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(/*! ./Tooltip */ \"./components/Tooltip.tsx\");\n/* harmony import */ var _canvases_NewElementCanvas__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(/*! ./canvases/NewElementCanvas */ \"./components/canvases/NewElementCanvas.tsx\");\n/* harmony import */ var _element_routing__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(/*! ../element/routing */ \"./element/routing.ts\");\n/* harmony import */ var _element_flowchart__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(/*! ../element/flowchart */ \"./element/flowchart.ts\");\n/* harmony import */ var _SearchMenu__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(/*! ./SearchMenu */ \"./components/SearchMenu.tsx\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(/*! ../../math */ \"../math/index.ts\");\n/* harmony import */ var _element_cropElement__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(/*! ../element/cropElement */ \"./element/cropElement.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n //zsviczian\n\n\n\n\n\n\n\n\n\n\n\nconst AppContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst AppPropsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst deviceContextInitialValue = {\n viewport: {\n isMobile: false,\n isLandscape: false\n },\n editor: {\n isMobile: false,\n canFitSidebar: false\n },\n isTouchScreen: false\n};\nconst DeviceContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(deviceContextInitialValue);\nDeviceContext.displayName = \"DeviceContext\";\nconst ExcalidrawContainerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext({\n container: null,\n id: null\n});\nExcalidrawContainerContext.displayName = \"ExcalidrawContainerContext\";\nconst ExcalidrawElementsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext([]);\nExcalidrawElementsContext.displayName = \"ExcalidrawElementsContext\";\nconst ExcalidrawAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n width: 0,\n height: 0,\n offsetLeft: 0,\n offsetTop: 0\n}));\nExcalidrawAppStateContext.displayName = \"ExcalidrawAppStateContext\";\nconst ExcalidrawSetAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(() => {\n console.warn(\"Uninitialized ExcalidrawSetAppStateContext context!\");\n});\nExcalidrawSetAppStateContext.displayName = \"ExcalidrawSetAppStateContext\";\nconst ExcalidrawActionManagerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nExcalidrawActionManagerContext.displayName = \"ExcalidrawActionManagerContext\";\nconst useApp = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppContext);\nconst useAppProps = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppPropsContext);\nconst useDevice = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(DeviceContext);\nconst useExcalidrawContainer = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawContainerContext);\nconst useExcalidrawElements = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawElementsContext);\nconst useExcalidrawAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawAppStateContext);\nconst useExcalidrawSetAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawSetAppStateContext);\nconst useExcalidrawActionManager = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawActionManagerContext);\nlet didTapTwice = false;\nlet tappedTwiceTimer = 0;\nlet isHoldingSpace = false;\nlet isPanning = false;\nlet isDraggingScrollBar = false;\nlet currentScrollBars = {\n horizontal: null,\n vertical: null\n};\nlet touchTimeout = 0;\nlet invalidateContextMenu = false;\n/**\n * Map of youtube embed video states\n */\n\nconst YOUTUBE_VIDEO_STATES = new Map();\nlet IS_PLAIN_PASTE = false;\nlet IS_PLAIN_PASTE_TIMER = 0;\nlet PLAIN_PASTE_TOAST_SHOWN = false;\nlet lastPointerUp = null;\nconst gesture = {\n pointers: new Map(),\n lastCenter: null,\n initialDistance: null,\n initialScale: null\n};\n\nclass App extends (react__WEBPACK_IMPORTED_MODULE_1___default().Component) {\n constructor(props) {\n super(props);\n this.interactiveCanvas = null;\n this.unmounted = false;\n this.device = deviceContextInitialValue;\n this.excalidrawContainerRef = react__WEBPACK_IMPORTED_MODULE_1___default().createRef();\n this.files = {};\n this.imageCache = new Map();\n this.iFrameRefs = new Map();\n /**\n * Indicates whether the embeddable's url has been validated for rendering.\n * If value not set, indicates that the validation is pending.\n * Initially or on url change the flag is not reset so that we can guarantee\n * the validation came from a trusted source (the editor).\n **/\n\n this.embedsValidationStatus = new Map();\n /** embeds that have been inserted to DOM (as a perf optim, we don't want to\n * insert to DOM before user initially scrolls to them) */\n\n this.initializedEmbeds = new Set();\n this.elementsPendingErasure = new Set();\n this.flowChartCreator = new _element_flowchart__WEBPACK_IMPORTED_MODULE_96__.FlowChartCreator();\n this.flowChartNavigator = new _element_flowchart__WEBPACK_IMPORTED_MODULE_96__.FlowChartNavigator();\n this.lastPointerDownEvent = null;\n this.lastPointerUpEvent = null;\n this.lastPointerMoveEvent = null;\n this.lastPointerMoveCoords = null;\n this.lastViewportPosition = {\n x: 0,\n y: 0\n };\n this.allowMobileMode = true; //zsviczian\n\n this.animationFrameHandler = new _animation_frame_handler__WEBPACK_IMPORTED_MODULE_77__.AnimationFrameHandler();\n this.laserTrails = new _laser_trails__WEBPACK_IMPORTED_MODULE_79__.LaserTrails(this.animationFrameHandler, this);\n this.eraserTrail = new _animated_trail__WEBPACK_IMPORTED_MODULE_78__.AnimatedTrail(this.animationFrameHandler, this, {\n streamline: 0.2,\n size: 5,\n keepHead: true,\n sizeMapping: c => {\n const DECAY_TIME = 200;\n const DECAY_LENGTH = 10;\n const t = Math.max(0, 1 - (performance.now() - c.pressure) / DECAY_TIME);\n const l = (DECAY_LENGTH - Math.min(DECAY_LENGTH, c.totalLength - c.currentIndex)) / DECAY_LENGTH;\n return Math.min((0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeOut)(l), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeOut)(t));\n },\n fill: () => this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.LIGHT ? \"rgba(0, 0, 0, 0.2)\" : \"rgba(255, 255, 255, 0.2)\"\n });\n this.onChangeEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onPointerDownEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onPointerUpEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onUserFollowEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onScrollChangeEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.missingPointerEventCleanupEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onRemoveEventListenersEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n /**\n * Returns gridSize taking into account `gridModeEnabled`.\n * If disabled, returns null.\n */\n\n this.getEffectiveGridSize = () => {\n return (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isGridModeEnabled)(this) ? this.state.gridSize : null;\n };\n\n this.updateEmbedValidationStatus = (element, status) => {\n this.embedsValidationStatus.set(element.id, status);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element);\n };\n\n this.updateEmbeddables = () => {\n const iframeLikes = new Set();\n let updated = false;\n this.scene.getNonDeletedElements().filter(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(element)) {\n iframeLikes.add(element.id);\n\n if (!this.embedsValidationStatus.has(element.id)) {\n updated = true;\n const validated = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.embeddableURLValidator)(element.link, this.props.validateEmbeddable);\n this.updateEmbedValidationStatus(element, validated);\n }\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(element)) {\n iframeLikes.add(element.id);\n }\n\n return false;\n });\n\n if (updated) {\n this.scene.triggerUpdate();\n } // GC\n\n\n this.iFrameRefs.forEach((ref, id) => {\n if (!iframeLikes.has(id)) {\n this.iFrameRefs.delete(id);\n }\n });\n };\n\n this.getFrameNameDOMId = frameElement => {\n return `${this.id}-frame-name-${frameElement.id}`;\n };\n\n this.frameNameBoundsCache = {\n get: frameElement => {\n let bounds = this.frameNameBoundsCache._cache.get(frameElement.id);\n\n if (!bounds || bounds.zoom !== this.state.zoom.value || bounds.versionNonce !== frameElement.versionNonce) {\n const frameNameDiv = document.getElementById(this.getFrameNameDOMId(frameElement));\n\n if (frameNameDiv) {\n const box = frameNameDiv.getBoundingClientRect();\n const boxSceneTopLeft = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: box.x,\n clientY: box.y\n }, this.state);\n const boxSceneBottomRight = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: box.right,\n clientY: box.bottom\n }, this.state);\n bounds = {\n x: boxSceneTopLeft.x,\n y: boxSceneTopLeft.y,\n width: boxSceneBottomRight.x - boxSceneTopLeft.x,\n height: boxSceneBottomRight.y - boxSceneTopLeft.y,\n angle: 0,\n zoom: this.state.zoom.value,\n versionNonce: frameElement.versionNonce\n };\n\n this.frameNameBoundsCache._cache.set(frameElement.id, bounds);\n\n return bounds;\n }\n\n return null;\n }\n\n return bounds;\n },\n\n /**\n * @private\n */\n _cache: new Map()\n };\n\n this.renderFrameNames = () => {\n if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {\n return null;\n }\n\n const isDarkTheme = this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.DARK;\n return this.scene.getNonDeletedFramesLikes().map(f => {\n var _a, _b;\n\n if (!(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(f, this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap())) {\n // if frame not visible, don't render its name\n return null;\n }\n\n const {\n x: x1,\n y: y1\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: f.x,\n sceneY: f.y\n }, this.state);\n const FRAME_NAME_EDIT_PADDING = 6;\n\n const reset = () => {\n var _a;\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: ((_a = f.name) === null || _a === void 0 ? void 0 : _a.trim()) || null\n });\n this.setState({\n editingFrame: null\n });\n };\n\n let frameNameJSX;\n const frameName = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameLikeTitle)(f);\n\n if (f.id === this.state.editingFrame) {\n const frameNameInEdit = frameName;\n frameNameJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"input\", {\n autoFocus: true,\n value: frameNameInEdit,\n onChange: e => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: e.target.value\n });\n },\n onFocus: e => e.target.select(),\n onBlur: () => reset(),\n onKeyDown: event => {\n // for some inexplicable reason, `onBlur` triggered on ESC\n // does not reset `state.editingFrame` despite being called,\n // and we need to reset it here as well\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n reset();\n }\n },\n style: {\n background: this.state.viewBackgroundColor,\n filter: isDarkTheme ? _constants__WEBPACK_IMPORTED_MODULE_12__.THEME_FILTER : \"none\",\n zIndex: 2,\n border: \"none\",\n display: \"block\",\n padding: `${FRAME_NAME_EDIT_PADDING}px`,\n borderRadius: 4,\n boxShadow: \"inset 0 0 0 2px var(--color-on-primary-container)\",\n fontFamily: \"Assistant\",\n fontSize: \"14px\",\n transform: `translate(-${FRAME_NAME_EDIT_PADDING}px, ${FRAME_NAME_EDIT_PADDING}px)`,\n color: \"var(--color-gray-80)\",\n overflow: \"hidden\",\n maxWidth: `${(0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.getExcalidrawContentEl)().clientWidth - x1 - FRAME_NAME_EDIT_PADDING //zsviczian was document.body\n }px`\n },\n size: frameNameInEdit.length + 1 || 1,\n dir: \"auto\",\n autoComplete: \"off\",\n autoCapitalize: \"off\",\n autoCorrect: \"off\"\n });\n } else {\n frameNameJSX = frameName;\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n id: this.getFrameNameDOMId(f),\n style: {\n position: \"absolute\",\n // Positioning from bottom so that we don't to either\n // calculate text height or adjust using transform (which)\n // messes up input position when editing the frame name.\n // This makes the positioning deterministic and we can calculate\n // the same position when rendering to canvas / svg.\n bottom: `${this.state.height + _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameOffsetY - y1 + this.state.offsetTop}px`,\n left: `${x1 - this.state.offsetLeft}px`,\n zIndex: 2,\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameFontSize,\n color: (_b = (_a = this.state.frameColor) === null || _a === void 0 ? void 0 : _a.nameColor) !== null && _b !== void 0 ? _b : isDarkTheme //zsviczian\n ? _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameColorDarkTheme : _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameColorLightTheme,\n lineHeight: _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameLineHeight,\n width: \"max-content\",\n maxWidth: `${f.width}px`,\n overflow: f.id === this.state.editingFrame ? \"visible\" : \"hidden\",\n whiteSpace: \"nowrap\",\n textOverflow: \"ellipsis\",\n cursor: _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE,\n pointerEvents: this.state.viewModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled\n },\n onPointerDown: event => this.handleCanvasPointerDown(event),\n onWheel: event => this.handleWheel(event),\n onContextMenu: this.handleCanvasContextMenu,\n onDoubleClick: () => {\n this.setState({\n editingFrame: f.id\n });\n }\n }, {\n children: frameNameJSX\n }), f.id);\n });\n };\n\n this.focusContainer = () => {\n var _a;\n\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.focus();\n };\n\n this.getSceneElementsIncludingDeleted = () => {\n return this.scene.getElementsIncludingDeleted();\n };\n\n this.getSceneElements = () => {\n return this.scene.getNonDeletedElements();\n };\n\n this.onInsertElements = elements => {\n this.addElementsFromPasteOrLibrary({\n elements,\n position: \"center\",\n files: null\n });\n };\n\n this.onExportImage = async (type, elements, opts) => {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"export\", type, \"ui\");\n const fileHandle = await (0,_data__WEBPACK_IMPORTED_MODULE_13__.exportCanvas)(type, elements, this.state, this.files, {\n exportBackground: this.state.exportBackground,\n name: this.getName(),\n viewBackgroundColor: this.state.viewBackgroundColor,\n exportingFrame: opts.exportingFrame\n }).catch(_utils__WEBPACK_IMPORTED_MODULE_34__.muteFSAbortError).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: error.message\n });\n });\n\n if (this.state.exportEmbedScene && fileHandle && (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isImageFileHandle)(fileHandle)) {\n this.setState({\n fileHandle\n });\n }\n };\n\n this.magicGenerations = new Map();\n\n this.updateMagicGeneration = ({\n frameElement,\n data\n }) => {\n if (data.status === \"pending\") {\n // We don't wanna persist pending state to storage. It should be in-app\n // state only.\n // Thus reset so that we prefer local cache (if there was some\n // generationData set previously)\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(frameElement, {\n customData: {\n generationData: undefined\n }\n }, false);\n } else {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(frameElement, {\n customData: {\n generationData: data\n }\n }, false);\n }\n\n this.magicGenerations.set(frameElement.id, data);\n this.triggerRender();\n };\n\n this.plugins = {};\n\n this.onMagicframeToolSelect = () => {\n const selectedElements = this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds\n });\n\n if (selectedElements.length === 0) {\n this.setActiveTool({\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"tool-select (empty-selection)\", \"d2c\");\n } else {\n const selectedMagicFrame = selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isMagicFrameElement)(selectedElements[0]) && selectedElements[0]; // case: user selected elements containing frame-like(s) or are frame\n // members, we don't want to wrap into another magicframe\n // (unless the only selected element is a magic frame which we reuse)\n\n if (!selectedMagicFrame && selectedElements.some(el => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(el) || el.frameId)) {\n this.setActiveTool({\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe\n });\n return;\n }\n\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"tool-select (existing selection)\", \"d2c\");\n let frame;\n\n if (selectedMagicFrame) {\n // a single magicframe already selected -> use it\n frame = selectedMagicFrame;\n } else {\n // selected elements aren't wrapped in magic frame yet -> wrap now\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n const padding = 50;\n frame = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newMagicFrameElement)(Object.assign(Object.assign({}, _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE), {\n x: minX - padding,\n y: minY - padding,\n width: maxX - minX + padding * 2,\n height: maxY - minY + padding * 2,\n opacity: 100,\n locked: false\n }));\n this.scene.insertElement(frame);\n\n for (const child of selectedElements) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(child, {\n frameId: frame.id\n });\n }\n\n this.setState({\n selectedElementIds: {\n [frame.id]: true\n }\n });\n }\n\n this.onMagicFrameGenerate(frame, \"upstream\");\n }\n };\n\n this.openEyeDropper = ({\n type\n }) => {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_EyeDropper__WEBPACK_IMPORTED_MODULE_61__.activeEyeDropperAtom, {\n swapPreviewOnAlt: true,\n colorPickerType: type === \"stroke\" ? \"elementStroke\" : \"elementBackground\",\n onSelect: (color, event) => {\n const shouldUpdateStrokeColor = type === \"background\" && event.altKey || type === \"stroke\" && !event.altKey;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (!selectedElements.length || this.state.activeTool.type !== \"selection\") {\n if (shouldUpdateStrokeColor) {\n this.syncActionResult({\n appState: Object.assign(Object.assign({}, this.state), {\n currentItemStrokeColor: color\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n } else {\n this.syncActionResult({\n appState: Object.assign(Object.assign({}, this.state), {\n currentItemBackgroundColor: color\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n } else {\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().map(el => {\n if (this.state.selectedElementIds[el.id]) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(el, {\n [shouldUpdateStrokeColor ? \"strokeColor\" : \"backgroundColor\"]: color\n });\n }\n\n return el;\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n },\n keepOpenOnAlt: false\n });\n };\n\n this.dismissLinearEditor = () => {\n setTimeout(() => {\n this.setState({\n editingLinearElement: null\n });\n });\n };\n\n this.syncActionResult = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(actionResult => {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n\n if (this.unmounted || actionResult === false) {\n return;\n }\n\n if (actionResult.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE) {\n this.store.shouldUpdateSnapshot();\n } else if (actionResult.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE) {\n this.store.shouldCaptureIncrement();\n }\n\n let didUpdate = false;\n let editingTextElement = null;\n\n if (actionResult.elements) {\n this.scene.replaceAllElements(actionResult.elements);\n didUpdate = true;\n }\n\n if (actionResult.files) {\n this.files = actionResult.replaceFiles ? actionResult.files : Object.assign(Object.assign({}, this.files), actionResult.files);\n this.addNewImagesToImageCache();\n }\n\n if (actionResult.appState || editingTextElement || this.state.contextMenu) {\n let viewModeEnabled = ((_a = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _a === void 0 ? void 0 : _a.viewModeEnabled) || false;\n let zenModeEnabled = ((_b = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _b === void 0 ? void 0 : _b.zenModeEnabled) || false;\n const theme = ((_c = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _c === void 0 ? void 0 : _c.theme) || this.props.theme || _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.LIGHT;\n const name = (_e = (_d = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : this.state.name;\n const errorMessage = (_g = (_f = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _f === void 0 ? void 0 : _f.errorMessage) !== null && _g !== void 0 ? _g : this.state.errorMessage;\n\n if (typeof this.props.viewModeEnabled !== \"undefined\") {\n viewModeEnabled = this.props.viewModeEnabled;\n }\n\n if (typeof this.props.zenModeEnabled !== \"undefined\") {\n zenModeEnabled = this.props.zenModeEnabled;\n }\n\n editingTextElement = ((_h = actionResult.appState) === null || _h === void 0 ? void 0 : _h.editingTextElement) || null; // make sure editingTextElement points to latest element reference\n\n if (actionResult.elements && editingTextElement) {\n actionResult.elements.forEach(element => {\n if ((editingTextElement === null || editingTextElement === void 0 ? void 0 : editingTextElement.id) === element.id && editingTextElement !== element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element) && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element)) {\n editingTextElement = element;\n }\n });\n }\n\n if (editingTextElement === null || editingTextElement === void 0 ? void 0 : editingTextElement.isDeleted) {\n editingTextElement = null;\n }\n\n this.setState(prevAppState => {\n const actionAppState = actionResult.appState || {};\n return Object.assign(Object.assign(Object.assign({}, prevAppState), actionAppState), {\n // NOTE this will prevent opening context menu using an action\n // or programmatically from the host, so it will need to be\n // rewritten later\n contextMenu: null,\n editingTextElement,\n viewModeEnabled,\n zenModeEnabled,\n theme,\n name,\n errorMessage\n });\n });\n didUpdate = true;\n }\n\n if (!didUpdate && actionResult.storeAction !== _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.NONE) {\n this.scene.triggerUpdate();\n }\n }); // Lifecycle\n\n this.onBlur = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(() => {\n isHoldingSpace = false;\n this.setState({\n isBindingEnabled: true\n });\n });\n\n this.onUnload = () => {\n this.onBlur();\n };\n\n this.disableEvent = event => {\n event.preventDefault();\n };\n\n this.resetHistory = () => {\n this.history.clear();\n };\n\n this.resetStore = () => {\n this.store.clear();\n };\n /**\n * Resets scene & history.\n * ! Do not use to clear scene user action !\n */\n\n\n this.resetScene = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(opts => {\n this.scene.replaceAllElements([]);\n this.setState(state => Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n isLoading: (opts === null || opts === void 0 ? void 0 : opts.resetLoadingState) ? false : state.isLoading,\n theme: this.state.theme\n }));\n this.resetStore();\n this.resetHistory();\n });\n\n this.initializeScene = async () => {\n var _a;\n\n if (\"launchQueue\" in window && \"LaunchParams\" in window) {\n window.launchQueue.setConsumer(async launchParams => {\n if (!launchParams.files.length) {\n return;\n }\n\n const fileHandle = launchParams.files[0];\n const blob = await fileHandle.getFile();\n this.loadFileToCanvas(new File([blob], blob.name || \"\", {\n type: blob.type\n }), fileHandle);\n });\n }\n\n if (this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n if (!this.state.isLoading) {\n this.setState({\n isLoading: true\n });\n }\n\n let initialData = null;\n\n try {\n if (typeof this.props.initialData === \"function\") {\n initialData = (await this.props.initialData()) || null;\n } else {\n initialData = (await this.props.initialData) || null;\n }\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.libraryItems) {\n this.library.updateLibrary({\n libraryItems: initialData.libraryItems,\n merge: true\n }).catch(error => {\n console.error(error);\n });\n }\n } catch (error) {\n console.error(error);\n initialData = {\n appState: {\n errorMessage: error.message || \"Encountered an error during importing or restoring scene data\"\n }\n };\n }\n\n const scene = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restore)(initialData, null, null, {\n repairBindings: true\n });\n scene.appState = Object.assign(Object.assign({}, scene.appState), {\n theme: this.props.theme || scene.appState.theme,\n // we're falling back to current (pre-init) state when deciding\n // whether to open the library, to handle a case where we\n // update the state outside of initialData (e.g. when loading the app\n // with a library install link, which should auto-open the library)\n openSidebar: ((_a = scene.appState) === null || _a === void 0 ? void 0 : _a.openSidebar) || this.state.openSidebar,\n activeTool: scene.appState.activeTool.type === \"image\" ? Object.assign(Object.assign({}, scene.appState.activeTool), {\n type: \"selection\"\n }) : scene.appState.activeTool,\n isLoading: false,\n toast: this.state.toast\n });\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.scrollToContent) {\n scene.appState = Object.assign(Object.assign({}, scene.appState), (0,_scene__WEBPACK_IMPORTED_MODULE_28__.calculateScrollCenter)(scene.elements, Object.assign(Object.assign({}, scene.appState), {\n width: this.state.width,\n height: this.state.height,\n offsetTop: this.state.offsetTop,\n offsetLeft: this.state.offsetLeft\n })));\n }\n\n this.resetStore();\n this.resetHistory();\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n })); // clear the shape and image cache so that any images in initialData\n // can be loaded fresh\n\n this.clearImageShapeCache(); // FontFaceSet loadingdone event we listen on may not always\n // fire (looking at you Safari), so on init we manually load all\n // fonts and rerender scene text elements once done. This also\n // seems faster even in browsers that do fire the loadingdone event.\n\n this.fonts.loadSceneFonts();\n };\n\n this.isMobileBreakpoint = (width, height) => {\n return width !== 0 && //zsviczian changing tabs in Obsidian causes MobileMenu to be rendered\n this.allowMobileMode && ( //zsviczian\n width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_PORTRAIT || height < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_HEIGHT_LANDSCAPE && width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_LANDSCAPE);\n };\n\n this.refreshViewportBreakpoints = () => {\n const container = this.excalidrawContainerRef.current;\n\n if (!container) {\n return;\n }\n\n const {\n clientWidth: viewportWidth,\n clientHeight: viewportHeight\n } = (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.getExcalidrawContentEl)(); //zsviczian was document.body;\n\n const prevViewportState = this.device.viewport;\n const nextViewportState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevViewportState, {\n isLandscape: viewportWidth > viewportHeight,\n isMobile: this.isMobileBreakpoint(viewportWidth, viewportHeight)\n });\n\n if (prevViewportState !== nextViewportState) {\n this.device = Object.assign(Object.assign({}, this.device), {\n viewport: nextViewportState\n });\n return true;\n }\n\n return false;\n };\n\n this.refreshEditorBreakpoints = () => {\n const container = this.excalidrawContainerRef.current;\n\n if (!container) {\n return;\n }\n\n const {\n width: editorWidth,\n height: editorHeight\n } = container.getBoundingClientRect();\n const sidebarBreakpoint = this.props.UIOptions.dockedSidebarBreakpoint != null ? this.props.UIOptions.dockedSidebarBreakpoint : _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_RIGHT_SIDEBAR_MIN_WIDTH;\n const prevEditorState = this.device.editor;\n const nextEditorState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevEditorState, {\n isMobile: this.isMobileBreakpoint(editorWidth, editorHeight),\n canFitSidebar: editorWidth > sidebarBreakpoint\n });\n\n if (prevEditorState !== nextEditorState) {\n this.device = Object.assign(Object.assign({}, this.device), {\n editor: nextEditorState\n });\n return true;\n }\n\n return false;\n };\n\n this.onResize = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(() => {\n this.scene.getElementsIncludingDeleted().forEach(element => _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element));\n this.refreshViewportBreakpoints();\n this.updateDOMRect();\n\n if (!_constants__WEBPACK_IMPORTED_MODULE_12__.supportsResizeObserver) {\n this.refreshEditorBreakpoints();\n }\n\n this.setState({});\n });\n /** generally invoked only if fullscreen was invoked programmatically */\n\n this.onFullscreenChange = () => {\n var _a;\n\n if ( // points to the iframe element we fullscreened\n !document.fullscreenElement && ((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.state) === \"active\") {\n this.setState({\n activeEmbeddable: null\n });\n }\n };\n\n this.renderInteractiveSceneCallback = ({\n atLeastOneVisibleElement,\n scrollBars,\n elementsMap\n }) => {\n if (!document.querySelector(\".excalidraw\")) {\n return;\n } //zsviczian - address issue when moving excalidraw to a new window/document\n\n\n if (scrollBars) {\n currentScrollBars = scrollBars;\n }\n\n const scrolledOutside = // hide when editing text\n this.state.editingTextElement ? false : !atLeastOneVisibleElement && elementsMap.size > 0;\n\n if (this.state.scrolledOutside !== scrolledOutside) {\n this.setState({\n scrolledOutside\n });\n }\n\n this.scheduleImageRefresh();\n };\n\n this.onScroll = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.debounce)(() => {\n const {\n offsetTop,\n offsetLeft\n } = this.getCanvasOffsets();\n this.setState(state => {\n if (state.offsetLeft === offsetLeft && state.offsetTop === offsetTop) {\n return null;\n }\n\n return {\n offsetTop,\n offsetLeft\n };\n });\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.SCROLL_TIMEOUT); // Copy/paste\n\n this.onCut = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target)) {\n return;\n }\n\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, \"keyboard\", event);\n event.preventDefault();\n event.stopPropagation();\n });\n this.onCopy = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target)) {\n return;\n }\n\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, \"keyboard\", event);\n event.preventDefault();\n event.stopPropagation();\n });\n\n this.onTouchStart = event => {\n // fix for Apple Pencil Scribble (do not prevent for other devices)\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.isIOS) {\n event.preventDefault();\n }\n\n if (!didTapTwice) {\n didTapTwice = true;\n clearTimeout(tappedTwiceTimer);\n tappedTwiceTimer = window.setTimeout(App.resetTapTwice, _constants__WEBPACK_IMPORTED_MODULE_12__.TAP_TWICE_TIMEOUT);\n return;\n } // insert text only if we tapped twice with a single finger\n // event.touches.length === 1 will also prevent inserting text when user's zooming\n\n\n if (didTapTwice && event.touches.length === 1) {\n const touch = event.touches[0]; // @ts-ignore\n\n this.handleCanvasDoubleClick({\n clientX: touch.clientX,\n clientY: touch.clientY\n });\n didTapTwice = false;\n clearTimeout(tappedTwiceTimer);\n }\n\n if (event.touches.length === 2) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n };\n\n this.onTouchEnd = event => {\n this.resetContextMenuTimer();\n\n if (event.touches.length > 0) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n } else {\n gesture.pointers.clear();\n }\n };\n\n this.pasteFromClipboard = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(async event => {\n var _a, _b;\n\n const isPlainPaste = !!IS_PLAIN_PASTE; // #686\n\n const target = document.activeElement;\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(target);\n\n if (event && !isExcalidrawActive) {\n return;\n }\n\n const elementUnderCursor = document.elementFromPoint(this.lastViewportPosition.x, this.lastViewportPosition.y);\n\n if (event && (!(elementUnderCursor instanceof HTMLCanvasElement) || (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(target))) {\n return;\n }\n\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state); // must be called in the same frame (thus before any awaits) as the paste\n // event else some browsers (FF...) will clear the clipboardData\n // (something something security)\n\n let file = (_b = event === null || event === void 0 ? void 0 : event.clipboardData) === null || _b === void 0 ? void 0 : _b.files[0];\n const data = await (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.parseClipboard)(event, isPlainPaste);\n\n if (!file && !isPlainPaste) {\n if (data.mixedContent) {\n return this.addElementsFromMixedContentPaste(data.mixedContent, {\n isPlainPaste,\n sceneX,\n sceneY\n });\n } else if (data.text) {\n const string = data.text.trim();\n\n if (string.startsWith(\"<svg\") && string.endsWith(\"</svg>\")) {\n // ignore SVG validation/normalization which will be done during image\n // initialization\n file = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.SVGStringToFile)(string);\n }\n }\n } // prefer spreadsheet data over image file (MS Office/Libre Office)\n\n\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isSupportedImageFile)(file) && !data.spreadsheet) {\n if (!this.isToolSupported(\"image\")) {\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageToolNotSupported\")\n });\n return;\n }\n\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n\n if (this.props.onPaste) {\n try {\n if ((await this.props.onPaste(data, event)) === false) {\n return;\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n if (data.errorMessage) {\n this.setState({\n errorMessage: data.errorMessage\n });\n } else if (data.spreadsheet && !isPlainPaste) {\n this.setState({\n pasteDialog: {\n data: data.spreadsheet,\n shown: true\n }\n });\n } else if (data.elements) {\n const elements = data.programmaticAPI ? (0,_data_transform__WEBPACK_IMPORTED_MODULE_62__.convertToExcalidrawElements)(data.elements) : data.elements; // TODO remove formatting from elements if isPlainPaste\n\n this.addElementsFromPasteOrLibrary({\n elements,\n files: data.files || null,\n position: \"cursor\",\n retainSeed: isPlainPaste\n });\n } else if (data.text) {\n if (data.text && (0,_mermaid__WEBPACK_IMPORTED_MODULE_92__.isMaybeMermaidDefinition)(data.text)) {\n const api = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! @zsviczian/mermaid-to-excalidraw */ \"../../node_modules/@zsviczian/mermaid-to-excalidraw/dist/index.js\")); //zsviczian\n\n try {\n const {\n elements: skeletonElements,\n files\n } = await api.parseMermaidToExcalidraw(data.text, {\n //zsviczian reverting https://github.com/excalidraw/excalidraw/pull/8226\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_FONT_SIZE\n }); //await api.parseMermaidToExcalidraw(data.text);\n\n const elements = (0,_data_transform__WEBPACK_IMPORTED_MODULE_62__.convertToExcalidrawElements)(skeletonElements, {\n regenerateIds: true\n });\n this.addElementsFromPasteOrLibrary({\n elements,\n files,\n position: \"cursor\"\n });\n return;\n } catch (err) {\n console.warn(`parsing pasted text as mermaid definition failed: ${err.message}`);\n }\n }\n\n const nonEmptyLines = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.normalizeEOL)(data.text).split(/\\n+/).map(s => s.trim()).filter(Boolean);\n const embbeddableUrls = nonEmptyLines.map(str => (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.maybeParseEmbedSrc)(str)).filter(string => {\n var _a;\n\n return (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.embeddableURLValidator)(string, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(string) || ((_a = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)(string)) === null || _a === void 0 ? void 0 : _a.type) === \"video\");\n });\n\n if (!IS_PLAIN_PASTE && embbeddableUrls.length > 0 && // if there were non-embeddable text (lines) mixed in with embeddable\n // urls, ignore and paste as text\n embbeddableUrls.length === nonEmptyLines.length) {\n const embeddables = [];\n\n for (const url of embbeddableUrls) {\n const prevEmbeddable = embeddables[embeddables.length - 1];\n const embeddable = this.insertEmbeddableElement({\n sceneX: prevEmbeddable ? prevEmbeddable.x + prevEmbeddable.width + 20 : sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(url)\n });\n\n if (embeddable) {\n embeddables.push(embeddable);\n }\n }\n\n if (embeddables.length) {\n this.setState({\n selectedElementIds: Object.fromEntries(embeddables.map(embeddable => [embeddable.id, true]))\n });\n }\n\n return;\n }\n\n this.addTextFromPaste(data.text, isPlainPaste);\n }\n\n this.setActiveTool({\n type: \"selection\"\n });\n event === null || event === void 0 ? void 0 : event.preventDefault();\n });\n\n this.addElementsFromPasteOrLibrary = opts => {\n let elements = opts.elements.map((el, _, elements) => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(el)) {\n const startEndElements = [el.startBinding && elements.find(l => {\n var _a;\n\n return l.id === ((_a = el.startBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n }), el.endBinding && elements.find(l => {\n var _a;\n\n return l.id === ((_a = el.endBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n })];\n const startBinding = startEndElements[0] ? el.startBinding : null;\n const endBinding = startEndElements[1] ? el.endBinding : null;\n return Object.assign(Object.assign({}, el), (0,_element_routing__WEBPACK_IMPORTED_MODULE_95__.updateElbowArrow)(Object.assign(Object.assign({}, el), {\n startBinding,\n endBinding\n }), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.toBrandedType)(new Map(startEndElements.filter(x => x != null).map(el => [el.id, el]))), [el.points[0], el.points[el.points.length - 1]]));\n }\n\n return el;\n });\n elements = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restoreElements)(elements, null, undefined);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(elements);\n const elementsCenterX = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(minX, maxX) / 2;\n const elementsCenterY = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(minY, maxY) / 2;\n const clientX = typeof opts.position === \"object\" ? opts.position.clientX : opts.position === \"cursor\" ? this.lastViewportPosition.x : this.state.width / 2 + this.state.offsetLeft;\n const clientY = typeof opts.position === \"object\" ? opts.position.clientY : opts.position === \"cursor\" ? this.lastViewportPosition.y : this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const dx = x - elementsCenterX;\n const dy = y - elementsCenterY;\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(dx, dy, this.getEffectiveGridSize());\n const newElements = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.duplicateElements)(elements.map(element => {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n x: element.x + gridX - minX,\n y: element.y + gridY - minY\n });\n }), {\n randomizeSeed: !opts.retainSeed\n });\n const prevElements = this.scene.getElementsIncludingDeleted();\n const nextElements = [...prevElements, ...newElements];\n (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncMovedIndices)(nextElements, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(newElements));\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x,\n y\n });\n\n if (topLayerFrame) {\n const eligibleElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.filterElementsEligibleAsFrameChildren)(newElements, topLayerFrame);\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(nextElements, eligibleElements, topLayerFrame);\n }\n\n this.scene.replaceAllElements(nextElements);\n newElements.forEach(newElement => {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(newElement) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(newElement)) {\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(newElement, this.scene.getElementsMapIncludingDeleted());\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.redrawTextBoundingBox)(newElement, container, this.scene.getElementsMapIncludingDeleted());\n }\n });\n\n if (opts.files) {\n this.files = Object.assign(Object.assign({}, this.files), opts.files);\n }\n\n this.store.shouldCaptureIncrement();\n const nextElementsToSelect = (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.excludeElementsInFramesFromSelection)(newElements);\n this.setState(Object.assign(Object.assign(Object.assign({}, this.state), {\n // keep sidebar (presumably the library) open if it's docked and\n // can fit.\n //\n // Note, we should close the sidebar only if we're dropping items\n // from library, not when pasting from clipboard. Alas.\n openSidebar: this.state.openSidebar && this.device.editor.canFitSidebar && _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.get(_Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_63__.isSidebarDockedAtom) ? this.state.openSidebar : null\n }), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: null,\n selectedElementIds: nextElementsToSelect.reduce((acc, element) => {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(element)) {\n acc[element.id] = true;\n }\n\n return acc;\n }, {})\n }, this.scene.getNonDeletedElements(), this.state, this)), () => {\n if (opts.files) {\n this.addNewImagesToImageCache();\n }\n });\n this.setActiveTool({\n type: \"selection\"\n });\n\n if (opts.fitToContent) {\n this.scrollToContent(newElements, {\n fitToContent: true,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n };\n\n this.setAppState = (state, callback) => {\n this.setState(state, callback);\n };\n\n this.removePointer = event => {\n if (touchTimeout) {\n this.resetContextMenuTimer();\n }\n\n gesture.pointers.delete(event.pointerId);\n };\n\n this.toggleLock = (source = \"ui\") => {\n if (!this.state.activeTool.locked) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", \"toggleLock\", `${source} (${this.device.editor.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n this.setState(prevState => {\n return {\n activeTool: Object.assign(Object.assign(Object.assign({}, prevState.activeTool), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, prevState.activeTool.locked ? {\n type: \"selection\"\n } : prevState.activeTool)), {\n locked: !prevState.activeTool.locked\n })\n };\n });\n };\n\n this.updateFrameRendering = opts => {\n this.setState(prevState => {\n var _a, _b, _c, _d;\n\n const next = typeof opts === \"function\" ? opts(prevState.frameRendering) : opts;\n return {\n frameRendering: {\n enabled: (_a = next === null || next === void 0 ? void 0 : next.enabled) !== null && _a !== void 0 ? _a : prevState.frameRendering.enabled,\n clip: (_b = next === null || next === void 0 ? void 0 : next.clip) !== null && _b !== void 0 ? _b : prevState.frameRendering.clip,\n name: (_c = next === null || next === void 0 ? void 0 : next.name) !== null && _c !== void 0 ? _c : prevState.frameRendering.name,\n outline: (_d = next === null || next === void 0 ? void 0 : next.outline) !== null && _d !== void 0 ? _d : prevState.frameRendering.outline\n }\n };\n });\n };\n\n this.togglePenMode = force => {\n this.setState(prevState => {\n return {\n penMode: force !== null && force !== void 0 ? force : !prevState.penMode,\n penDetected: true\n };\n });\n };\n\n this.onHandToolToggle = () => {\n //zsviczian added timeout because button won't select otherwise\n setTimeout(() => this.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleHandTool));\n };\n /**\n * Zooms on canvas viewport center\n */\n\n\n this.zoomCanvas = (\n /**\n * Decimal fraction, auto-clamped between MIN_ZOOM and MAX_ZOOM.\n * 1 = 100% zoom, 2 = 200% zoom, 0.5 = 50% zoom\n */\n value) => {\n this.setState(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: this.state.width / 2 + this.state.offsetLeft,\n viewportY: this.state.height / 2 + this.state.offsetTop,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(value)\n }, this.state)));\n };\n\n this.cancelInProgressAnimation = null;\n\n this.scrollToContent = (target = this.scene.getNonDeletedElements(), opts) => {\n var _a, _b;\n\n (_a = this.cancelInProgressAnimation) === null || _a === void 0 ? void 0 : _a.call(this); // convert provided target into ExcalidrawElement[] if necessary\n\n const targetElements = Array.isArray(target) ? target : [target];\n let zoom = this.state.zoom;\n let scrollX = this.state.scrollX;\n let scrollY = this.state.scrollY;\n\n if ((opts === null || opts === void 0 ? void 0 : opts.fitToContent) || (opts === null || opts === void 0 ? void 0 : opts.fitToViewport)) {\n const {\n appState\n } = (0,_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.zoomToFit)({\n canvasOffsets: opts.canvasOffsets,\n targetElements,\n appState: this.state,\n fitToViewport: !!(opts === null || opts === void 0 ? void 0 : opts.fitToViewport),\n viewportZoomFactor: opts === null || opts === void 0 ? void 0 : opts.viewportZoomFactor,\n minZoom: opts === null || opts === void 0 ? void 0 : opts.minZoom,\n maxZoom: opts === null || opts === void 0 ? void 0 : opts.maxZoom\n });\n zoom = appState.zoom;\n scrollX = appState.scrollX;\n scrollY = appState.scrollY;\n } else {\n // compute only the viewport location, without any zoom adjustment\n const scroll = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.calculateScrollCenter)(targetElements, this.state);\n scrollX = scroll.scrollX;\n scrollY = scroll.scrollY;\n } // when animating, we use RequestAnimationFrame to prevent the animation\n // from slowing down other processes\n\n\n if (opts === null || opts === void 0 ? void 0 : opts.animate) {\n const origScrollX = this.state.scrollX;\n const origScrollY = this.state.scrollY;\n const origZoom = this.state.zoom.value;\n const cancel = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeToValuesRAF)({\n fromValues: {\n scrollX: origScrollX,\n scrollY: origScrollY,\n zoom: origZoom\n },\n toValues: {\n scrollX,\n scrollY,\n zoom: zoom.value\n },\n interpolateValue: (from, to, progress, key) => {\n // for zoom, use different easing\n if (key === \"zoom\") {\n return from * Math.pow(to / from, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeOut)(progress));\n } // handle using default\n\n\n return undefined;\n },\n onStep: ({\n scrollX,\n scrollY,\n zoom\n }) => {\n this.setState({\n scrollX,\n scrollY,\n zoom: {\n value: zoom\n }\n });\n },\n onStart: () => {\n this.setState({\n shouldCacheIgnoreZoom: true\n });\n },\n onEnd: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n onCancel: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n duration: (_b = opts === null || opts === void 0 ? void 0 : opts.duration) !== null && _b !== void 0 ? _b : 500\n });\n\n this.cancelInProgressAnimation = () => {\n cancel();\n this.cancelInProgressAnimation = null;\n };\n } else {\n this.setState({\n scrollX,\n scrollY,\n zoom\n });\n }\n };\n\n this.maybeUnfollowRemoteUser = () => {\n if (this.state.userToFollow) {\n this.setState({\n userToFollow: null\n });\n }\n };\n /** use when changing scrollX/scrollY/zoom based on user interaction */\n\n\n this.translateCanvas = state => {\n var _a;\n\n (_a = this.cancelInProgressAnimation) === null || _a === void 0 ? void 0 : _a.call(this);\n this.maybeUnfollowRemoteUser();\n this.setState(state);\n }; //zsviczian\n\n\n this.zoomToFit = (target = this.scene.getNonDeletedElements(), maxZoom, //null will zoom to max based on viewport\n margin = 0.03) => {\n if (typeof maxZoom === \"undefined\") {\n //zsviczian\n maxZoom = (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.getMaxZoom)();\n }\n\n if (!target) {\n target = this.scene.getNonDeletedElements();\n }\n\n if (target.length === 0) {\n maxZoom = 1;\n }\n\n this.setState((0,_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.zoomToFitElements)(target, this.state, false, this, maxZoom, margin).appState);\n }; //zsviczian\n\n\n this.startLineEditor = (el, selectedPointsIndices = null) => {\n if (!el || !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(el)) {\n return;\n }\n\n const editingLinearElement = new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(el);\n this.setState({\n selectedLinearElement: editingLinearElement,\n editingLinearElement: Object.assign(Object.assign({}, editingLinearElement), {\n selectedPointsIndices\n })\n });\n }; //zsviczian\n\n\n this.updateContainerSize = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(containers => {\n containers.forEach(el => {\n const [x, y] = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(el.x + el.width, el.y + el.height), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(el.x + el.width / 2, el.y + el.height / 2), el.angle);\n (0,_element_resizeElements__WEBPACK_IMPORTED_MODULE_89__.resizeSingleElement)(new Map().set(el.id, el), false, el, this.scene.getElementsMapIncludingDeleted(), \"se\", true, x, y);\n });\n });\n\n this.setToast = toast => {\n this.setState({\n toast\n });\n };\n\n this.restoreFileFromShare = async () => {\n try {\n const webShareTargetCache = await caches.open(\"web-share-target\");\n const response = await webShareTargetCache.match(\"shared-file\");\n\n if (response) {\n const blob = await response.blob();\n const file = new File([blob], blob.name || \"\", {\n type: blob.type\n });\n this.loadFileToCanvas(file, null);\n await webShareTargetCache.delete(\"shared-file\");\n window.history.replaceState(null, _constants__WEBPACK_IMPORTED_MODULE_12__.APP_NAME, window.location.pathname);\n }\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n };\n /** adds supplied files to existing files in the appState */\n\n\n this.addFiles = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(files => {\n const filesMap = files.reduce((acc, fileData) => {\n acc.set(fileData.id, fileData);\n return acc;\n }, new Map());\n this.files = Object.assign(Object.assign({}, this.files), Object.fromEntries(filesMap));\n this.clearImageShapeCache(Object.fromEntries(filesMap));\n this.scene.triggerUpdate();\n this.addNewImagesToImageCache();\n }); //zsviczian https://github.com/zsviczian/excalibrain/issues/9\n\n this.setMobileModeAllowed = allow => {\n const {\n width: editorWidth,\n height: editorHeight\n } = this.excalidrawContainerRef.current.getBoundingClientRect();\n this.allowMobileMode = allow;\n const prevEditorState = this.device.editor;\n let nextEditorState;\n\n if (allow) {\n nextEditorState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevEditorState, {\n isMobile: this.isMobileBreakpoint(editorWidth, editorHeight)\n });\n } else {\n nextEditorState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevEditorState, {\n isMobile: false //must test this\n\n });\n }\n\n if (prevEditorState !== nextEditorState) {\n this.device = Object.assign(Object.assign({}, this.device), {\n editor: nextEditorState\n });\n this.forceUpdate();\n }\n }; //zsviczian\n\n\n this.debounceClearHighlightSearchResults = false;\n\n this.selectElements = (elements, highlightSearchResult = false) => {\n //zsviczian\n if (highlightSearchResult) {\n this.debounceClearHighlightSearchResults = true;\n setTimeout(() => {\n this.debounceClearHighlightSearchResults = false;\n }, 500);\n }\n\n this.updateScene({\n appState: Object.assign(Object.assign({}, this.state), {\n editingGroupId: null,\n selectedElementIds: elements.reduce((map, element) => {\n map[element.id] = true;\n return map;\n }, {}),\n highlightSearchResult\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.NONE,\n forceFlushSync: true\n });\n };\n\n this.bringToFront = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionBringToFront.perform(this.scene.getNonDeletedElements(), this.state));\n };\n\n this.bringForward = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionBringForward.perform(this.scene.getNonDeletedElements(), this.state));\n };\n\n this.sendToBack = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionSendToBack.perform(this.scene.getNonDeletedElements(), this.state));\n };\n\n this.sendBackward = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionSendBackward.perform(this.scene.getNonDeletedElements(), this.state));\n };\n\n this.updateScene = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(sceneData => {\n var _a;\n\n const nextElements = (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncInvalidIndices)((_a = sceneData.elements) !== null && _a !== void 0 ? _a : []);\n\n if (sceneData.storeAction && sceneData.storeAction !== _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.NONE) {\n const prevCommittedAppState = this.store.snapshot.appState;\n const prevCommittedElements = this.store.snapshot.elements;\n const nextCommittedAppState = sceneData.appState ? Object.assign({}, prevCommittedAppState, sceneData.appState) // new instance, with partial appstate applied to previously captured one, including hidden prop inside `prevCommittedAppState`\n : prevCommittedAppState;\n const nextCommittedElements = sceneData.elements ? this.store.filterUncomittedElements(this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(nextElements)) : prevCommittedElements; // WARN: store action always performs deep clone of changed elements, for ephemeral remote updates (i.e. remote dragging, resizing, drawing) we might consider doing something smarter\n // do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well\n\n if (sceneData.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE) {\n this.store.captureIncrement(nextCommittedElements, nextCommittedAppState);\n } else if (sceneData.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE) {\n this.store.updateSnapshot(nextCommittedElements, nextCommittedAppState);\n }\n } //zsviczian forceFlushSync is set to true in ExcalidrawView.updateScene.\n //without this e.g. text search did not select the elements\n\n\n if (sceneData.forceFlushSync === true) {\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n if (sceneData.appState) {\n this.setState(sceneData.appState);\n }\n });\n } else if (sceneData.appState) {\n this.setState(sceneData.appState);\n }\n\n if (sceneData.elements) {\n this.scene.replaceAllElements(nextElements);\n }\n\n if (sceneData.collaborators) {\n this.setState({\n collaborators: sceneData.collaborators\n });\n }\n });\n\n this.triggerRender = (\n /** force always re-renders canvas even if no change */\n force) => {\n if (force === true) {\n this.scene.triggerUpdate();\n } else {\n this.setState({});\n }\n };\n /**\n * @returns whether the menu was toggled on or off\n */\n\n\n this.toggleSidebar = ({\n name,\n tab,\n force\n }) => {\n var _a, _b;\n\n let nextName;\n\n if (force === undefined) {\n nextName = ((_a = this.state.openSidebar) === null || _a === void 0 ? void 0 : _a.name) === name && ((_b = this.state.openSidebar) === null || _b === void 0 ? void 0 : _b.tab) === tab ? null : name;\n } else {\n nextName = force ? name : null;\n }\n\n const nextState = nextName ? {\n name: nextName\n } : null;\n\n if (nextState && tab) {\n nextState.tab = tab;\n }\n\n this.setState({\n openSidebar: nextState\n });\n return !!nextName;\n };\n\n this.updateCurrentCursorPosition = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n this.lastViewportPosition.x = event.clientX;\n this.lastViewportPosition.y = event.clientY;\n });\n\n this.getEditorUIOffsets = () => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;\n\n const toolbarBottom = ((_e = (_d = (_c = (_b = (_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.querySelector(\".App-toolbar\")) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect()) === null || _d === void 0 ? void 0 : _d.bottom) !== null && _e !== void 0 ? _e : 0) - this.state.offsetTop;\n const sidebarRect = (_h = (_g = (_f = this.excalidrawContainerRef) === null || _f === void 0 ? void 0 : _f.current) === null || _g === void 0 ? void 0 : _g.querySelector(\".sidebar\")) === null || _h === void 0 ? void 0 : _h.getBoundingClientRect();\n const propertiesPanelRect = (_l = (_k = (_j = this.excalidrawContainerRef) === null || _j === void 0 ? void 0 : _j.current) === null || _k === void 0 ? void 0 : _k.querySelector(\".App-menu__left\")) === null || _l === void 0 ? void 0 : _l.getBoundingClientRect();\n const PADDING = 16;\n\n const adjustRectValueForOffset = ( //zsviczian https://github.com/excalidraw/excalidraw/issues/8561\n value, fallback) => (value !== null && value !== void 0 ? value : fallback + this.state.offsetLeft) - this.state.offsetLeft;\n\n return (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.getLanguage)().rtl ? {\n top: toolbarBottom + PADDING,\n right: Math.max(this.state.width - adjustRectValueForOffset( //zsivczian\n propertiesPanelRect === null || propertiesPanelRect === void 0 ? void 0 : propertiesPanelRect.left, this.state.width), 0) + PADDING,\n bottom: PADDING,\n left: //zsivczian\n Math.max(adjustRectValueForOffset(sidebarRect === null || sidebarRect === void 0 ? void 0 : sidebarRect.right, 0), 0) + PADDING\n } : {\n top: toolbarBottom + PADDING,\n right: Math.max(this.state.width - adjustRectValueForOffset(sidebarRect === null || sidebarRect === void 0 ? void 0 : sidebarRect.left, this.state.width) + //zsivczian\n PADDING, 0),\n bottom: PADDING,\n left: //zsivczian\n Math.max(adjustRectValueForOffset(propertiesPanelRect === null || propertiesPanelRect === void 0 ? void 0 : propertiesPanelRect.right, 0), 0) + PADDING\n };\n }; // Input handling\n\n\n this.onKeyDown = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a;\n\n if (this.state.activeTool.type === \"selection\" && this.state.resizingElement && (event.shiftKey || event.altKey)) {\n event.stopPropagation(); //zsviczian shift fires repeatedly causing slowdown when resizing sticky notes\n\n return;\n } // normalize `event.key` when CapsLock is pressed #2372\n\n\n if (\"Proxy\" in window && (!event.shiftKey && /^[A-Z]$/.test(event.key) || event.shiftKey && /^[a-z]$/.test(event.key))) {\n event = new Proxy(event, {\n get(ev, prop) {\n const value = ev[prop];\n\n if (typeof value === \"function\") {\n // fix for Proxies hijacking `this`\n return value.bind(ev);\n }\n\n return prop === \"key\" ? // CapsLock inverts capitalization based on ShiftKey, so invert\n // it back\n event.shiftKey ? ev.key.toUpperCase() : ev.key.toLowerCase() : value;\n }\n\n });\n }\n\n if (!(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isInputLike)(event.target)) {\n if ((event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) && this.state.croppingElementId) {\n this.finishImageCropping();\n return;\n }\n\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElementsMap(), this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(selectedElements[0]) && event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n this.startImageCropping(selectedElements[0]);\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE && this.flowChartCreator.isCreatingChart) {\n this.flowChartCreator.clear();\n this.triggerRender(true);\n return;\n }\n\n const arrowKeyPressed = (0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key);\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && arrowKeyPressed && !event.shiftKey) {\n event.preventDefault();\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElementsMap(), this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFlowchartNodeElement)(selectedElements[0])) {\n this.flowChartCreator.createNodes(selectedElements[0], this.scene.getNonDeletedElementsMap(), this.state, (0,_element_flowchart__WEBPACK_IMPORTED_MODULE_96__.getLinkDirectionFromKey)(event.key));\n }\n\n if (((_a = this.flowChartCreator.pendingNodes) === null || _a === void 0 ? void 0 : _a.length) && !(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementCompletelyInViewport)(this.flowChartCreator.pendingNodes, this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap(), this.getEditorUIOffsets())) {\n this.scrollToContent(this.flowChartCreator.pendingNodes, {\n animate: true,\n duration: 300,\n fitToContent: true,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n\n return;\n }\n\n if (event.altKey) {\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElementsMap(), this.state);\n\n if (selectedElements.length === 1 && arrowKeyPressed) {\n event.preventDefault();\n const nextId = this.flowChartNavigator.exploreByDirection(selectedElements[0], this.scene.getNonDeletedElementsMap(), (0,_element_flowchart__WEBPACK_IMPORTED_MODULE_96__.getLinkDirectionFromKey)(event.key));\n\n if (nextId) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [nextId]: true\n }, prevState)\n }));\n const nextNode = this.scene.getNonDeletedElementsMap().get(nextId);\n\n if (nextNode && !(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementCompletelyInViewport)([nextNode], this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap(), this.getEditorUIOffsets())) {\n this.scrollToContent(nextNode, {\n animate: true,\n duration: 300,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n }\n\n return;\n }\n }\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.P && !event.shiftKey && !event.altKey) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"commandPalette.shortcutHint\", {\n shortcut: (0,_actions_shortcuts__WEBPACK_IMPORTED_MODULE_88__.getShortcutFromShortcutName)(\"commandPalette\")\n })\n });\n event.preventDefault();\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.V) {\n IS_PLAIN_PASTE = event.shiftKey;\n clearTimeout(IS_PLAIN_PASTE_TIMER); // reset (100ms to be safe that we it runs after the ensuing\n // paste event). Though, technically unnecessary to reset since we\n // (re)set the flag before each paste event.\n\n IS_PLAIN_PASTE_TIMER = window.setTimeout(() => {\n IS_PLAIN_PASTE = false;\n }, 100);\n } // prevent browser zoom in input fields\n\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target)) {\n if (event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.MINUS || event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.EQUAL) {\n event.preventDefault();\n return;\n }\n } // bail if\n\n\n if ( // inside an input\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target) && // unless pressing escape (finalize action)\n event.key !== _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || // or unless using arrows (to move between buttons)\n (0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key) && (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isInputLike)(event.target)) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.QUESTION_MARK) {\n this.setState({\n openDialog: {\n name: \"help\"\n }\n });\n return;\n } else if (event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.E && event.shiftKey && event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n this.setState({\n openDialog: {\n name: \"imageExport\"\n }\n });\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_UP || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n let offset = (event.shiftKey ? this.state.width : this.state.height) / this.state.zoom.value;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n offset = -offset;\n }\n\n if (event.shiftKey) {\n this.translateCanvas(state => ({\n scrollX: state.scrollX + offset\n }));\n } else {\n this.translateCanvas(state => ({\n scrollY: state.scrollY + offset\n }));\n }\n }\n\n if (this.actionManager.handleKeyDown(event)) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.K && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isLaserPointerActive)(this.state)) {\n this.setActiveTool({\n type: \"selection\"\n });\n } else {\n this.setActiveTool({\n type: \"laser\"\n });\n }\n\n return;\n }\n\n if (this.state.viewModeEnabled) {\n //revert to hand in case a key is pressed (K is handled above)\n if (event.key !== _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.K) {\n this.setActiveTool({\n type: \"selection\"\n });\n }\n\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: false\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n let selectedElements = this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n });\n const elbowArrow = selectedElements.find(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow);\n const arrowIdsToRemove = new Set();\n selectedElements.filter(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow).filter(arrow => {\n const startElementNotInSelection = arrow.startBinding && !selectedElements.some(el => {\n var _a;\n\n return el.id === ((_a = arrow.startBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n });\n const endElementNotInSelection = arrow.endBinding && !selectedElements.some(el => {\n var _a;\n\n return el.id === ((_a = arrow.endBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n });\n return startElementNotInSelection || endElementNotInSelection;\n }).forEach(arrow => arrowIdsToRemove.add(arrow.id));\n selectedElements = selectedElements.filter(el => !arrowIdsToRemove.has(el.id));\n const step = this.getEffectiveGridSize() && (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT : this.getEffectiveGridSize()) || (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_SHIFT_TRANSLATE_AMOUNT : _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT);\n let offsetX = 0;\n let offsetY = 0;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_LEFT) {\n offsetX = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_RIGHT) {\n offsetX = step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_UP) {\n offsetY = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_DOWN) {\n offsetY = step;\n }\n\n selectedElements.forEach(element => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: element.x + offsetX,\n y: element.y + offsetY\n });\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element, this.scene.getNonDeletedElementsMap(), {\n simultaneouslyUpdated: selectedElements\n });\n });\n this.setState({\n suggestedBindings: (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getSuggestedBindingsForArrows)(selectedElements.filter(element => element.id !== (elbowArrow === null || elbowArrow === void 0 ? void 0 : elbowArrow.id) || step !== 0), this.scene.getNonDeletedElementsMap())\n });\n event.preventDefault();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n const selectedElement = selectedElements[0];\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElement)) {\n if (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id) {\n this.store.shouldCaptureIncrement();\n\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElement)) {\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElement)\n });\n }\n }\n }\n } else if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.isValidTextContainer)(selectedElement)) {\n let container;\n\n if (!(0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement)) {\n container = selectedElement;\n }\n\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerCenter)(selectedElement, this.state, this.scene.getNonDeletedElementsMap());\n const sceneX = midPoint.x;\n const sceneY = midPoint.y;\n this.startTextEditing({\n sceneX,\n sceneY,\n container\n });\n event.preventDefault();\n return;\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(selectedElement)) {\n this.setState({\n editingFrame: selectedElement.id\n });\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(selectedElement)) {\n //zsviczian\n this.setState({\n activeEmbeddable: {\n element: selectedElement,\n state: \"active\"\n }\n });\n }\n }\n } else if (!event.ctrlKey && !event.altKey && !event.metaKey && !this.state.newElement && !this.state.selectionElement && !this.state.selectedElementsAreBeingDragged) {\n const shape = (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.findShapeByKey)(event.key);\n\n if (shape) {\n if (this.state.activeTool.type !== shape) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", shape, `keyboard (${this.device.editor.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n if (shape === \"arrow\" && this.state.activeTool.type === \"arrow\") {\n this.setState(prevState => ({\n currentItemArrowType: prevState.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.sharp ? _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.round : prevState.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.round ? _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.elbow : _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.sharp\n }));\n }\n\n this.setActiveTool({\n type: shape\n });\n event.stopPropagation();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.Q) {\n this.toggleLock(\"keyboard\");\n event.stopPropagation();\n }\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE && gesture.pointers.size === 0) {\n isHoldingSpace = true;\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n event.preventDefault();\n }\n\n if ((event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (this.state.activeTool.type === \"selection\" && !selectedElements.length) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && ((0,_scene__WEBPACK_IMPORTED_MODULE_28__.hasBackground)(this.state.activeTool.type) || selectedElements.some(element => (0,_scene__WEBPACK_IMPORTED_MODULE_28__.hasBackground)(element.type)))) {\n this.setState({\n openPopup: \"elementBackground\"\n });\n event.stopPropagation();\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) {\n this.setState({\n openPopup: \"elementStroke\"\n });\n event.stopPropagation();\n }\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.shiftKey && event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.F) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (this.state.activeTool.type === \"selection\" && !selectedElements.length) {\n return;\n }\n\n if (this.state.activeTool.type === \"text\" || selectedElements.find(element => (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getBoundTextElement)(element, this.scene.getNonDeletedElementsMap()))) {\n event.preventDefault();\n this.setState({\n openPopup: \"fontFamily\"\n });\n }\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.K && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (this.state.activeTool.type === \"laser\") {\n this.setActiveTool({\n type: \"selection\"\n });\n } else {\n this.setActiveTool({\n type: \"laser\"\n });\n }\n\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.BACKSPACE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.DELETE)) {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__.activeConfirmDialogAtom, \"clearCanvas\");\n } // eye dropper\n // -----------------------------------------------------------------------\n\n\n const lowerCased = event.key.toLocaleLowerCase();\n const isPickingStroke = lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S && event.shiftKey;\n const isPickingBackground = event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.I || lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && event.shiftKey;\n\n if (isPickingStroke || isPickingBackground) {\n this.openEyeDropper({\n type: isPickingStroke ? \"stroke\" : \"background\"\n });\n } // -----------------------------------------------------------------------\n\n });\n this.onKeyUp = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a, _b, _c, _d;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE) {\n if (this.state.viewModeEnabled) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (this.state.activeTool.type === \"selection\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n isHoldingSpace = false;\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: true\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElements)(this.scene.getSelectedElements(this.state).filter(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement), this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements(), this.scene, (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state), (_b = (_a = this.state.selectedLinearElement) === null || _a === void 0 ? void 0 : _a.selectedPointsIndices) !== null && _b !== void 0 ? _b : []);\n this.setState({\n suggestedBindings: []\n });\n }\n\n if (!event.altKey) {\n if (this.flowChartNavigator.isExploring) {\n this.flowChartNavigator.clear();\n this.syncActionResult({\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (this.flowChartCreator.isCreatingChart) {\n if ((_c = this.flowChartCreator.pendingNodes) === null || _c === void 0 ? void 0 : _c.length) {\n this.scene.insertElements(this.flowChartCreator.pendingNodes);\n }\n\n const firstNode = (_d = this.flowChartCreator.pendingNodes) === null || _d === void 0 ? void 0 : _d[0];\n\n if (firstNode) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [firstNode.id]: true\n }, prevState)\n }));\n\n if (!(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementCompletelyInViewport)([firstNode], this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap(), this.getEditorUIOffsets())) {\n this.scrollToContent(firstNode, {\n animate: true,\n duration: 300,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n }\n\n this.flowChartCreator.clear();\n this.syncActionResult({\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n }\n }); // We purposely widen the `tool` type so this helper can be called with\n // any tool without having to type check it\n\n this.isToolSupported = tool => {\n var _a;\n\n return ((_a = this.props.UIOptions.tools) === null || _a === void 0 ? void 0 : _a[tool]) !== false;\n };\n\n this.setActiveTool = tool => {\n var _a;\n\n if (!this.isToolSupported(tool.type)) {\n console.warn(`\"${tool.type}\" tool is disabled via \"UIOptions.canvasActions.tools.${tool.type}\"`);\n return;\n }\n\n const nextActiveTool = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, tool);\n\n if (nextActiveTool.type === \"hand\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (!isHoldingSpace) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_34__.isToolIcon)(document.activeElement)) {\n this.focusContainer();\n }\n\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElementType)(nextActiveTool.type)) {\n this.setState({\n suggestedBindings: []\n });\n }\n\n if (nextActiveTool.type === \"image\") {\n this.onImageAction({\n insertOnCanvasDirectly: (_a = tool.type === \"image\" && tool.insertOnCanvasDirectly) !== null && _a !== void 0 ? _a : false\n });\n }\n\n setTimeout(() => {\n this.setState(prevState => {\n const commonResets = {\n snapLines: prevState.snapLines.length ? [] : prevState.snapLines,\n originSnapOffset: null,\n activeEmbeddable: null\n };\n\n if (nextActiveTool.type === \"freedraw\") {\n this.store.shouldCaptureIncrement();\n }\n\n if (nextActiveTool.type !== \"selection\") {\n return Object.assign(Object.assign(Object.assign({}, prevState), {\n activeTool: nextActiveTool,\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextActiveTool.type === \"mermaid\" //zsviczian\n ? this.state.selectedElementIds : {}, prevState),\n selectedGroupIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, prevState),\n editingGroupId: null,\n multiElement: null\n }), commonResets);\n }\n\n return Object.assign(Object.assign(Object.assign({}, prevState), {\n activeTool: nextActiveTool\n }), commonResets);\n }); //zsviczian added timeout because button won't select otherwise\n });\n };\n\n this.setOpenDialog = dialogType => {\n this.setState({\n openDialog: dialogType\n });\n };\n\n this.setCursor = cursor => {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, cursor);\n };\n\n this.resetCursor = () => {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n };\n /**\n * returns whether user is making a gesture with >= 2 fingers (points)\n * on o touch screen (not on a trackpad). Currently only relates to Darwin\n * (iOS/iPadOS,MacOS), but may work on other devices in the future if\n * GestureEvent is standardized.\n */\n\n\n this.isTouchScreenMultiTouchGesture = () => {\n // we don't want to deselect when using trackpad, and multi-point gestures\n // only work on touch screens, so checking for >= pointers means we're on a\n // touchscreen\n return gesture.pointers.size >= 2;\n };\n\n this.getName = () => {\n return this.state.name || this.props.name || `${(0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.untitled\")}-${(0,_utils__WEBPACK_IMPORTED_MODULE_34__.getDateTime)()}`;\n }; // fires only on Safari\n\n\n this.onGestureStart = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n event.preventDefault(); // we only want to deselect on touch screens because user may have selected\n // elements by mistake while zooming\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n\n gesture.initialScale = this.state.zoom.value;\n }); // fires only on Safari\n\n this.onGestureChange = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n event.preventDefault(); // onGestureChange only has zoom factor but not the center.\n // If we're on iPad or iPhone, then we recognize multi-touch and will\n // zoom in at the right location in the touchmove handler\n // (handleCanvasPointerMove).\n //\n // On Macbook trackpad, we don't have those events so will zoom in at the\n // current location instead.\n //\n // As such, bail from this handler on touch devices.\n\n if (this.isTouchScreenMultiTouchGesture()) {\n return;\n }\n\n const initialScale = gesture.initialScale;\n\n if (initialScale) {\n this.setState(state => Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(initialScale * event.scale)\n }, state)));\n }\n }); // fires only on Safari\n\n this.onGestureEnd = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n event.preventDefault(); // reselect elements only on touch screens (see onGestureStart)\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n }\n\n gesture.initialScale = null;\n });\n\n this.startTextEditing = ({\n sceneX,\n sceneY,\n insertAtParentCenter = true,\n container,\n autoEdit = true\n }) => {\n var _a, _b;\n\n let shouldBindToContainer = false;\n let parentCenterPosition = insertAtParentCenter && this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n\n if (container && parentCenterPosition) {\n const boundTextElementToContainer = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getBoundTextElement)(container, this.scene.getNonDeletedElementsMap());\n\n if (!boundTextElementToContainer) {\n shouldBindToContainer = true;\n }\n }\n\n let existingTextElement = null;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElements[0])) {\n existingTextElement = selectedElements[0];\n } else if (container) {\n existingTextElement = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getBoundTextElement)(selectedElements[0], this.scene.getNonDeletedElementsMap());\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n\n const fontFamily = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.fontFamily) || this.state.currentItemFontFamily;\n const lineHeight = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.lineHeight) || (0,_fonts__WEBPACK_IMPORTED_MODULE_49__.getLineHeight)(fontFamily);\n const fontSize = (0,_actions_actionProperties__WEBPACK_IMPORTED_MODULE_75__.getFontSize)(this.state.currentItemFontSize, this.state.zoom.value); //zsviczian\n\n if (!existingTextElement && shouldBindToContainer && container && !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(container)) {\n const fontString = {\n fontSize,\n fontFamily\n };\n const minWidth = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getApproxMinLineWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_34__.getFontString)(fontString), lineHeight);\n const minHeight = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getApproxMinLineHeight)(fontSize, lineHeight);\n const newHeight = Math.max(container.height, minHeight);\n const newWidth = Math.max(container.width, minWidth);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n height: newHeight,\n width: newWidth\n });\n sceneX = container.x + newWidth / 2;\n sceneY = container.y + newHeight / 2;\n\n if (parentCenterPosition) {\n parentCenterPosition = this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n }\n }\n\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: sceneX,\n y: sceneY\n });\n /*const shouldWrapText = !shouldBindToContainer && //zsviczian\n this.lastPointerDownEvent?.pointerType === \"pen\";\n const [x1, , x2] = getVisibleSceneBounds(this.state); //zsviczian\n const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.85, 800), 200); //zsviczian*/\n\n const element = existingTextElement ? existingTextElement : (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)({\n x: parentCenterPosition ? parentCenterPosition.elementCenterX : sceneX,\n y: parentCenterPosition ? parentCenterPosition.elementCenterY : sceneY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text: \"\",\n rawText: \"\",\n fontSize,\n fontFamily,\n textAlign: parentCenterPosition ? \"center\" : this.state.currentItemTextAlign,\n verticalAlign: parentCenterPosition ? _constants__WEBPACK_IMPORTED_MODULE_12__.VERTICAL_ALIGN.MIDDLE : _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n containerId: shouldBindToContainer ? container === null || container === void 0 ? void 0 : container.id : undefined,\n groupIds: (_a = container === null || container === void 0 ? void 0 : container.groupIds) !== null && _a !== void 0 ? _a : [],\n lineHeight,\n angle: (_b = container === null || container === void 0 ? void 0 : container.angle) !== null && _b !== void 0 ? _b : 0,\n frameId: topLayerFrame ? topLayerFrame.id : null\n /*...shouldWrapText //zsviczian\n ? {\n width: maxTextWidth,\n autoResize: false,\n }\n : {},*/\n\n });\n\n if (!existingTextElement && shouldBindToContainer && container) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: element.id\n })\n });\n }\n\n this.setState({\n editingTextElement: element\n });\n\n if (!existingTextElement) {\n if (container && shouldBindToContainer) {\n const containerIndex = this.scene.getElementIndex(container.id);\n this.scene.insertElementAtIndex(element, containerIndex + 1);\n } else {\n this.scene.insertElement(element);\n }\n }\n\n if (autoEdit || existingTextElement || container) {\n this.handleTextWysiwyg(element, {\n isExistingElement: !!existingTextElement\n });\n } else {\n this.setState({\n newElement: element,\n multiElement: null\n });\n }\n };\n\n this.debounceDoubleClickTimestamp = 0; //zsviczian\n\n this.startImageCropping = image => {\n this.store.shouldCaptureIncrement();\n this.setState({\n croppingElementId: image.id\n });\n };\n\n this.finishImageCropping = () => {\n if (this.state.croppingElementId) {\n this.store.shouldCaptureIncrement();\n this.setState({\n croppingElementId: null\n });\n }\n };\n\n this.handleCanvasDoubleClick = event => {\n var _a; // case: double-clicking with arrow/line tool selected would both create\n // text and enter multiElement mode\n\n\n if (this.state.multiElement) {\n return;\n }\n\n if ( //zsviczian - double click eraser\n this.state.penMode && (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.allowDoubleTapEraser)() && ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a.pointerType) === \"touch\" && this.state.activeTool.type !== \"selection\") {\n const now = Date.now();\n\n if (now - this.debounceDoubleClickTimestamp < 200) {\n //handleCanvasDoubleClick click fires twice in case of touch.\n //Once from the onTouchStart event handler, once from the double click event handler\n return;\n }\n\n this.debounceDoubleClickTimestamp = now;\n this.updateScene(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleEraserTool.perform([], this.state));\n return;\n } // zsviczian - end\n // we should only be able to double click when mode is selection\n\n\n if (this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0])) {\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id) && !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0])) {\n this.store.shouldCaptureIncrement();\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElements[0])\n });\n return;\n }\n }\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(selectedElements[0])) {\n this.startImageCropping(selectedElements[0]);\n return;\n }\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n let {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedGroupIds = (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIds)(this.state);\n\n if (selectedGroupIds.length > 0) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n const selectedGroupId = hitElement && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIdForElement)(hitElement, this.state.selectedGroupIds);\n\n if (selectedGroupId) {\n this.store.shouldCaptureIncrement();\n this.setState(prevState => Object.assign(Object.assign({}, prevState), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: selectedGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)));\n return;\n }\n }\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.viewModeEnabled) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement)) {\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"active\"\n }\n });\n return;\n }\n\n const container = this.getTextBindableContainerAtPosition(sceneX, sceneY);\n\n if (container) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(container) || !(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isTransparent)(container.backgroundColor) || (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x: sceneX,\n y: sceneY,\n element: container,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(container, this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold()\n })) {\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerCenter)(container, this.state, this.scene.getNonDeletedElementsMap());\n sceneX = midPoint.x;\n sceneY = midPoint.y;\n }\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container\n });\n }\n };\n\n this.getElementLinkAtPosition = (scenePointer, hitElement) => {\n // Reversing so we traverse the elements in decreasing order\n // of z-index\n const elements = this.scene.getNonDeletedElements().slice().reverse();\n let hitElementIndex = Infinity;\n return elements.find((element, index) => {\n if (hitElement && element.id === hitElement.id) {\n hitElementIndex = index;\n }\n\n return element.link && index <= hitElementIndex && (0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLink)(element, this.scene.getNonDeletedElementsMap(), this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointer.x, scenePointer.y), this.device.editor.isMobile);\n });\n };\n\n this.redirectToLink = (event, isTouchScreen) => {\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(this.lastPointerDownEvent.clientX, this.lastPointerDownEvent.clientY), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(this.lastPointerUpEvent.clientX, this.lastPointerUpEvent.clientY));\n\n if (!this.hitLinkElement || // For touch screen allow dragging threshold else strict check\n isTouchScreen && draggedDistance > _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD || !isTouchScreen && draggedDistance !== 0) {\n return;\n }\n\n const lastPointerDownCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(this.lastPointerDownEvent, this.state);\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const lastPointerDownHittingLinkIcon = (0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLink)(this.hitLinkElement, elementsMap, this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastPointerDownCoords.x, lastPointerDownCoords.y), this.device.editor.isMobile);\n const lastPointerUpCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(this.lastPointerUpEvent, this.state);\n const lastPointerUpHittingLinkIcon = (0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLink)(this.hitLinkElement, elementsMap, this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastPointerUpCoords.x, lastPointerUpCoords.y), this.device.editor.isMobile);\n\n if (lastPointerDownHittingLinkIcon && lastPointerUpHittingLinkIcon) {\n let url = this.hitLinkElement.link;\n\n if (url) {\n url = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(url);\n let customEvent;\n\n if (this.props.onLinkOpen) {\n customEvent = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.wrapEvent)(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.EXCALIDRAW_LINK, event.nativeEvent);\n this.props.onLinkOpen(Object.assign(Object.assign({}, this.hitLinkElement), {\n link: url\n }), customEvent);\n }\n\n if (!(customEvent === null || customEvent === void 0 ? void 0 : customEvent.defaultPrevented)) {\n const target = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.isLocalLink)(url) ? \"_self\" : \"_blank\";\n const newWindow = window.open(undefined, target); // https://mathiasbynens.github.io/rel-noopener/\n\n if (newWindow) {\n newWindow.opener = null;\n newWindow.location = url;\n }\n }\n }\n }\n };\n\n this.getTopLayerFrameAtSceneCoords = sceneCoords => {\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const frames = this.scene.getNonDeletedFramesLikes().filter(frame => (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)(sceneCoords, frame, elementsMap));\n return frames.length ? frames[frames.length - 1] : null;\n };\n\n this.handleCanvasPointerMove = event => {\n var _a, _b;\n\n this.savePointer(event.clientX, event.clientY, this.state.cursorButton);\n this.lastPointerMoveEvent = event.nativeEvent;\n\n if (gesture.pointers.has(event.pointerId)) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n }\n\n const initialScale = gesture.initialScale;\n\n if (gesture.pointers.size === 2 && gesture.lastCenter && initialScale && gesture.initialDistance) {\n const center = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n const deltaX = center.x - gesture.lastCenter.x;\n const deltaY = center.y - gesture.lastCenter.y;\n gesture.lastCenter = center;\n const distance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n const scaleFactor = !this.state.allowPinchZoom && //zsviczian\n this.state.activeTool.type === \"freedraw\" && this.state.penMode ? 1 : distance / gesture.initialDistance;\n const nextZoom = scaleFactor ? (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(initialScale * scaleFactor) : this.state.zoom.value;\n this.setState(state => {\n const zoomState = (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: center.x,\n viewportY: center.y,\n nextZoom\n }, state);\n this.translateCanvas({\n zoom: zoomState.zoom,\n // 2x multiplier is just a magic number that makes this work correctly\n // on touchscreen devices (note: if we get report that panning is slower/faster\n // than actual movement, consider swapping with devicePixelRatio)\n scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),\n scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),\n shouldCacheIgnoreZoom: true\n });\n });\n this.resetShouldCacheIgnoreZoomDebounced();\n } else {\n gesture.lastCenter = gesture.initialDistance = gesture.initialScale = null;\n }\n\n if (isHoldingSpace || isPanning || isDraggingScrollBar || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state)) {\n return;\n }\n\n const isPointerOverScrollBars = (0,_scene_scrollbars__WEBPACK_IMPORTED_MODULE_85__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop);\n const isOverScrollBar = isPointerOverScrollBars.isOverEither;\n const isPenFreedraw = this.state.activeTool.type === \"freedraw\" && event.pointerType === \"pen\"; //zsviczian\n\n if (!this.state.newElement && !this.state.selectionElement && !this.state.selectedElementsAreBeingDragged && !this.state.multiElement) {\n if (isOverScrollBar) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n } else if (isPenFreedraw && this.interactiveCanvas && (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.hideFreedrawPenmodeCursor)()) {\n //zsviczian https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1659\n this.interactiveCanvas.style.cursor = \"none\";\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const {\n x: scenePointerX,\n y: scenePointerY\n } = scenePointer;\n\n if (!this.state.newElement && (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isActiveToolNonLinearSnappable)(this.state.activeTool.type)) {\n const {\n originOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getSnapLinesAtPointer)(this.scene.getNonDeletedElements(), this, {\n x: scenePointerX,\n y: scenePointerY\n }, event, this.scene.getNonDeletedElementsMap());\n this.setState(prevState => {\n const nextSnapLines = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateStable)(prevState.snapLines, snapLines);\n const nextOriginOffset = prevState.originSnapOffset ? (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateStable)(prevState.originSnapOffset, originOffset) : originOffset;\n\n if (prevState.snapLines === nextSnapLines && prevState.originSnapOffset === nextOriginOffset) {\n return null;\n }\n\n return {\n snapLines: nextSnapLines,\n originSnapOffset: nextOriginOffset\n };\n });\n } else if (!this.state.newElement && !this.state.selectedElementsAreBeingDragged && !this.state.selectionElement) {\n this.setState(prevState => {\n if (prevState.snapLines.length) {\n return {\n snapLines: []\n };\n }\n\n return null;\n });\n }\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerMove(event, scenePointerX, scenePointerY, this, this.scene.getNonDeletedElementsMap());\n\n if (editingLinearElement && editingLinearElement !== this.state.editingLinearElement) {\n // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n editingLinearElement\n });\n });\n }\n\n if ((editingLinearElement === null || editingLinearElement === void 0 ? void 0 : editingLinearElement.lastUncommittedPoint) != null) {\n this.maybeSuggestBindingAtCursor(scenePointer);\n } else {\n // causes stack overflow if not sync\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n suggestedBindings: []\n });\n });\n }\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElementType)(this.state.activeTool.type)) {\n // Hovering with a selected tool or creating new linear element via click\n // and point\n const {\n newElement\n } = this.state;\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(newElement, false)) {\n this.maybeSuggestBindingsForLinearElementAtCoords(newElement, [scenePointer], this.state.startBoundElement);\n } else {\n this.maybeSuggestBindingAtCursor(scenePointer);\n }\n }\n\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state;\n const {\n x: rx,\n y: ry\n } = multiElement;\n const {\n points,\n lastCommittedPoint\n } = multiElement;\n const lastPoint = points[points.length - 1];\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n\n if (lastPoint === lastCommittedPoint) {\n // if we haven't yet created a temp point and we're beyond commit-zone\n // threshold, add a point\n if ((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointerX - rx, scenePointerY - ry), lastPoint) >= _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointerX - rx, scenePointerY - ry)]\n }, false);\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER); // in this branch, we're inside the commit zone, and no uncommitted\n // point exists. Thus do nothing (don't add/remove points).\n }\n } else if (points.length > 2 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointerX - rx, scenePointerY - ry), lastCommittedPoint) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: points.slice(0, -1)\n }, false);\n } else {\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(scenePointerX, scenePointerY, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(multiElement) ? null : this.getEffectiveGridSize());\n const [lastCommittedX, lastCommittedY] = (_a = multiElement === null || multiElement === void 0 ? void 0 : multiElement.lastCommittedPoint) !== null && _a !== void 0 ? _a : [0, 0];\n let dxFromLastCommitted = gridX - rx - lastCommittedX;\n let dyFromLastCommitted = gridY - ry - lastCommittedY;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event)) {\n ({\n width: dxFromLastCommitted,\n height: dyFromLastCommitted\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)( // actual coordinate of the last committed point\n lastCommittedX + rx, lastCommittedY + ry, // cursor-grid coordinate\n gridX, gridY));\n }\n\n if ((0,_shapes__WEBPACK_IMPORTED_MODULE_31__.isPathALoop)(points, this.state.zoom.value)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(multiElement)) {\n (0,_element_routing__WEBPACK_IMPORTED_MODULE_95__.mutateElbowArrow)(multiElement, this.scene.getNonDeletedElementsMap(), [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastCommittedX + dxFromLastCommitted, lastCommittedY + dyFromLastCommitted)], undefined, undefined, {\n isDragging: true,\n informMutation: false\n });\n } else {\n // update last uncommitted point\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastCommittedX + dxFromLastCommitted, lastCommittedY + dyFromLastCommitted)]\n }, false);\n } // in this path, we're mutating multiElement to reflect\n // how it will be after adding pointer position as the next point\n // trigger update here so that new element canvas renders again to reflect this\n\n\n this.triggerRender(false);\n }\n\n return;\n }\n\n const hasDeselectedButton = Boolean(event.buttons);\n\n if (hasDeselectedButton || this.state.activeTool.type !== \"selection\" && this.state.activeTool.type !== \"text\" && this.state.activeTool.type !== \"eraser\") {\n return;\n }\n\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !isOverScrollBar && !this.state.editingLinearElement) {\n // for linear elements, we'd like to prioritize point dragging over edge resizing\n // therefore, we update and check hovered point index first\n if (this.state.selectedLinearElement) {\n this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);\n }\n\n if ((!this.state.selectedLinearElement || this.state.selectedLinearElement.hoverPointIndex === -1) && !(selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0]))) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);\n\n if (elementWithTransformHandleType && elementWithTransformHandleType.transformHandleType) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)(elementWithTransformHandleType));\n return;\n }\n }\n } else if (selectedElements.length > 1 && !isOverScrollBar) {\n const transformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.device);\n\n if (transformHandleType) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)({\n transformHandleType\n }));\n return;\n }\n }\n\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n return;\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.showHyperlinkTooltip)(this.hitLinkElement, this.state, this.scene.getNonDeletedElementsMap());\n\n if (this.props.onLinkHover) {\n this.props.onLinkHover(this.hitLinkElement, event);\n } //zsviczian\n\n } else {\n (0,_components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.hideHyperlinkToolip)();\n\n if (hitElement && (hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement)) && this.state.selectedElementIds[hitElement.id] && !this.state.contextMenu && !this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: \"info\"\n });\n } else if (this.state.activeTool.type === \"text\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(hitElement) ? _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.TEXT : _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR);\n } else if (this.state.viewModeEnabled) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (isOverScrollBar) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n } else if (this.state.selectedLinearElement) {\n this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);\n } else if ( // if using cmd/ctrl, we're not dragging\n !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((hitElement || this.isHittingCommonBoundingBoxOfSelectedElements(scenePointer, selectedElements)) && !(hitElement === null || hitElement === void 0 ? void 0 : hitElement.locked)) {\n if (hitElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement) && this.isIframeLikeElementCenter(hitElement, event, scenePointerX, scenePointerY)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"hover\"\n }\n });\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n\n if (((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\") {\n this.setState({\n activeEmbeddable: null\n });\n }\n }\n }\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n };\n\n this.handleEraser = (event, pointerDownState, scenePointer) => {\n this.eraserTrail.addPointToPath(scenePointer.x, scenePointer.y);\n let didChange = false;\n const processedGroups = new Set();\n const nonDeletedElements = this.scene.getNonDeletedElements();\n\n const processElements = elements => {\n var _a;\n\n for (const element of elements) {\n if (element.locked) {\n return;\n }\n\n if (event.altKey) {\n if (this.elementsPendingErasure.delete(element.id)) {\n didChange = true;\n }\n } else if (!this.elementsPendingErasure.has(element.id)) {\n didChange = true;\n this.elementsPendingErasure.add(element.id);\n } // (un)erase groups atomically\n\n\n if (didChange && ((_a = element.groupIds) === null || _a === void 0 ? void 0 : _a.length)) {\n const shallowestGroupId = element.groupIds.at(-1);\n\n if (!processedGroups.has(shallowestGroupId)) {\n processedGroups.add(shallowestGroupId);\n const elems = (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(nonDeletedElements, shallowestGroupId);\n\n for (const elem of elems) {\n if (event.altKey) {\n this.elementsPendingErasure.delete(elem.id);\n } else {\n this.elementsPendingErasure.add(elem.id);\n }\n }\n }\n }\n }\n };\n\n const distance = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointer.x, scenePointer.y));\n const threshold = this.getElementHitThreshold();\n const p = Object.assign({}, pointerDownState.lastCoords);\n let samplingInterval = 0;\n\n while (samplingInterval <= distance) {\n const hitElements = this.getElementsAtPosition(p.x, p.y);\n processElements(hitElements); // Exit since we reached current point\n\n if (samplingInterval === distance) {\n break;\n } // Calculate next point in the line at a distance of sampling interval\n\n\n samplingInterval = Math.min(samplingInterval + threshold, distance);\n const distanceRatio = samplingInterval / distance;\n const nextX = (1 - distanceRatio) * p.x + distanceRatio * scenePointer.x;\n const nextY = (1 - distanceRatio) * p.y + distanceRatio * scenePointer.y;\n p.x = nextX;\n p.y = nextY;\n }\n\n pointerDownState.lastCoords.x = scenePointer.x;\n pointerDownState.lastCoords.y = scenePointer.y;\n\n if (didChange) {\n for (const element of this.scene.getNonDeletedElements()) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(element) && (this.elementsPendingErasure.has(element.id) || this.elementsPendingErasure.has(element.containerId))) {\n if (event.altKey) {\n this.elementsPendingErasure.delete(element.id);\n this.elementsPendingErasure.delete(element.containerId);\n } else {\n this.elementsPendingErasure.add(element.id);\n this.elementsPendingErasure.add(element.containerId);\n }\n }\n }\n\n this.elementsPendingErasure = new Set(this.elementsPendingErasure);\n this.triggerRender();\n }\n }; // set touch moving for mobile context menu\n\n\n this.handleTouchMove = event => {\n invalidateContextMenu = true;\n };\n\n this.handleCanvasPointerDown = event => {\n var _a, _b;\n\n this.focusContainer(); //zsviczian\n\n this.maybeCleanupAfterMissingPointerUp(event.nativeEvent);\n this.maybeUnfollowRemoteUser();\n\n if (this.state.searchMatches) {\n this.setState(state => ({\n searchMatches: state.searchMatches.map(searchMatch => Object.assign(Object.assign({}, searchMatch), {\n focus: false\n }))\n }));\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_SearchMenu__WEBPACK_IMPORTED_MODULE_97__.searchItemInFocusAtom, null);\n } // since contextMenu options are potentially evaluated on each render,\n // and an contextMenu action may depend on selection state, we must\n // close the contextMenu before we update the selection on pointerDown\n // (e.g. resetting selection)\n\n\n if (this.state.contextMenu) {\n this.setState({\n contextMenu: null\n });\n }\n\n if (this.state.snapLines) {\n this.setAppState({\n snapLines: []\n });\n }\n\n this.updateGestureOnPointerDown(event); // if dragging element is freedraw and another pointerdown event occurs\n // a second finger is on the screen\n // discard the freedraw element if it is very short because it is likely\n // just a spike, otherwise finalize the freedraw element when the second\n // finger is lifted\n\n if (event.pointerType === \"touch\" && this.state.newElement && this.state.newElement.type === \"freedraw\") {\n const element = this.state.newElement;\n this.updateScene(Object.assign(Object.assign({}, element.points.length < 10 ? {\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== element.id)\n } : {}), {\n appState: {\n newElement: null,\n editingTextElement: null,\n startBoundElement: null,\n suggestedBindings: [],\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.keys(this.state.selectedElementIds).filter(key => key !== element.id).reduce((obj, key) => {\n obj[key] = this.state.selectedElementIds[key];\n return obj;\n }, {}), this.state)\n },\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n }));\n return;\n } // remove any active selection when we start to interact with canvas\n // (mainly, we care about removing selection outside the component which\n // would prevent our copy handling otherwise)\n\n\n const selection = document.getSelection();\n\n if (selection === null || selection === void 0 ? void 0 : selection.anchorNode) {\n selection.removeAllRanges();\n }\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices(event); //fires only once, if pen is detected, penMode is enabled\n //the user can disable this by toggling the penMode button\n\n if (!this.state.penDetected && event.pointerType === \"pen\") {\n this.setState(prevState => {\n return {\n penMode: true,\n penDetected: true\n };\n });\n }\n\n if (!this.device.isTouchScreen && [\"pen\", \"touch\"].includes(event.pointerType)) {\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(this.device, {\n isTouchScreen: true\n });\n }\n\n if (isPanning) {\n return;\n }\n\n this.lastPointerDownEvent = event; // we must exit before we set `cursorButton` state and `savePointer`\n // else it will send pointer state & laser pointer events in collab when\n // panning\n\n /*if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {\n return;\n }*/\n //zsviczian this broke on pointer down in onPointerUpdate\n\n this.setState({\n lastPointerDownWith: event.pointerType,\n cursorButton: \"down\"\n });\n this.savePointer(event.clientX, event.clientY, \"down\");\n\n if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {\n return;\n } //zsviczian moved it here, because else pointer down in onPointerUpdate did not work\n\n\n if (event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.ERASER && this.state.activeTool.type !== _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.eraser) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.eraser,\n lastActiveToolBeforeEraser: this.state.activeTool\n })\n }, () => {\n this.handleCanvasPointerDown(event);\n\n const onPointerUp = () => {\n unsubPointerUp();\n unsubCleanup === null || unsubCleanup === void 0 ? void 0 : unsubCleanup();\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, Object.assign(Object.assign({}, this.state.activeTool.lastActiveTool || {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.selection\n }), {\n lastActiveToolBeforeEraser: null\n }))\n });\n }\n };\n\n const unsubPointerUp = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp, {\n once: true\n });\n let unsubCleanup; // subscribe inside rAF lest it'd be triggered on the same pointerdown\n // if we start erasing while coming from blurred document since\n // we cleanup pointer events on focus\n\n requestAnimationFrame(() => {\n unsubCleanup = this.missingPointerEventCleanupEmitter.once(onPointerUp);\n });\n });\n return;\n } // only handle left mouse button or touch\n\n\n if (event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.TOUCH && event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.ERASER) {\n return;\n } // don't select while panning\n\n\n if (gesture.pointers.size > 1) {\n return;\n } // State for the duration of a pointer interaction, which starts with a\n // pointerDown event, ends with a pointerUp event (or another pointerDown)\n\n\n const pointerDownState = this.initialPointerDownState(event);\n this.setState({\n selectedElementsAreBeingDragged: false\n });\n\n if (this.handleDraggingScrollBar(event, pointerDownState)) {\n return;\n }\n\n this.clearSelectionIfNotUsingSelection();\n this.updateBindingEnabledOnPointerMove(event);\n\n if (this.handleSelectionOnPointerDown(event, pointerDownState)) {\n return;\n }\n\n const allowOnPointerDown = !this.state.penMode || event.pointerType !== \"touch\" || this.state.activeTool.type === \"selection\" || this.state.activeTool.type === \"text\" || this.state.activeTool.type === \"image\";\n\n if (!allowOnPointerDown) {\n return;\n }\n\n if (this.state.activeTool.type === \"text\") {\n this.handleTextOnPointerDown(event, pointerDownState);\n } else if (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\") {\n this.handleLinearElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"image\") {\n // reset image preview on pointerdown\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR); // retrieve the latest element as the state may be stale\n\n const pendingImageElement = this.state.pendingImageElementId && this.scene.getElement(this.state.pendingImageElementId);\n\n if (!pendingImageElement) {\n return;\n }\n\n this.setState({\n newElement: pendingImageElement,\n pendingImageElementId: null,\n multiElement: null\n });\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const frame = this.getTopLayerFrameAtSceneCoords({\n x,\n y\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(pendingImageElement, {\n x,\n y,\n frameId: frame ? frame.id : null\n });\n } else if (this.state.activeTool.type === \"freedraw\") {\n this.handleFreeDrawElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"custom\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n } else if (this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.frame || this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe) {\n this.createFrameElementOnPointerDown(pointerDownState, this.state.activeTool.type);\n } else if (this.state.activeTool.type === \"laser\") {\n this.laserTrails.startPath(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y);\n } else if (this.state.activeTool.type !== \"eraser\" && this.state.activeTool.type !== \"hand\" && this.state.activeTool.type !== \"mermaid\") {\n this.createGenericElementOnPointerDown(this.state.activeTool.type, pointerDownState);\n }\n\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onPointerDown) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.activeTool, pointerDownState);\n this.onPointerDownEmitter.trigger(this.state.activeTool, pointerDownState, event);\n\n if (this.state.activeTool.type === \"eraser\") {\n this.eraserTrail.startPath(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y);\n }\n\n const onPointerMove = this.onPointerMoveFromPointerDownHandler(pointerDownState);\n const onPointerUp = this.onPointerUpFromPointerDownHandler(pointerDownState);\n const onKeyDown = this.onKeyDownFromPointerDownHandler(pointerDownState);\n const onKeyUp = this.onKeyUpFromPointerDownHandler(pointerDownState);\n this.missingPointerEventCleanupEmitter.once(_event => onPointerUp(_event || event.nativeEvent));\n\n if (!this.state.viewModeEnabled || this.state.activeTool.type === \"laser\") {\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, onKeyDown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, onKeyUp);\n pointerDownState.eventListeners.onMove = onPointerMove;\n pointerDownState.eventListeners.onUp = onPointerUp;\n pointerDownState.eventListeners.onKeyUp = onKeyUp;\n pointerDownState.eventListeners.onKeyDown = onKeyDown;\n }\n };\n\n this.handleCanvasPointerUp = event => {\n var _a, _b;\n\n this.removePointer(event);\n this.lastPointerUpEvent = event;\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: event.clientX,\n clientY: event.clientY\n }, this.state);\n const clicklength = event.timeStamp - ((_b = (_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a.timeStamp) !== null && _b !== void 0 ? _b : 0);\n\n if (this.device.editor.isMobile && clicklength < 300) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement) && this.isIframeLikeElementCenter(hitElement, event, scenePointer.x, scenePointer.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n return;\n }\n }\n\n if (this.device.isTouchScreen) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n if (clicklength < 300 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(this.hitLinkElement) && !(0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLinkIcon)(this.hitLinkElement, this.scene.getNonDeletedElementsMap(), this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointer.x, scenePointer.y))) {\n this.handleEmbeddableCenterClick(this.hitLinkElement);\n } else {\n this.redirectToLink(event, this.device.isTouchScreen);\n }\n } else if (this.state.viewModeEnabled) {\n this.setState({\n activeEmbeddable: null,\n selectedElementIds: {}\n });\n }\n };\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices = event => {\n // deal with opening context menu on touch devices\n if (event.pointerType === \"touch\") {\n invalidateContextMenu = false;\n\n if (touchTimeout) {\n // If there's already a touchTimeout, this means that there's another\n // touch down and we are doing another touch, so we shouldn't open the\n // context menu.\n invalidateContextMenu = true;\n } else {\n // open the context menu with the first touch's clientX and clientY\n // if the touch is not moving\n touchTimeout = window.setTimeout(() => {\n touchTimeout = 0;\n\n if (!invalidateContextMenu) {\n this.handleCanvasContextMenu(event);\n }\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.TOUCH_CTX_MENU_TIMEOUT);\n }\n }\n };\n\n this.resetContextMenuTimer = () => {\n clearTimeout(touchTimeout);\n touchTimeout = 0;\n invalidateContextMenu = false;\n };\n /**\n * pointerup may not fire in certian cases (user tabs away...), so in order\n * to properly cleanup pointerdown state, we need to fire any hanging\n * pointerup handlers manually\n */\n\n\n this.maybeCleanupAfterMissingPointerUp = event => {\n lastPointerUp === null || lastPointerUp === void 0 ? void 0 : lastPointerUp();\n this.missingPointerEventCleanupEmitter.trigger(event).clear();\n }; // Returns whether the event is a panning\n\n\n this.handleCanvasPanUsingWheelOrSpaceDrag = event => {\n if (!(gesture.pointers.size <= 1 && (event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.WHEEL || event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && isHoldingSpace || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state) || (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.isTouchInPenMode)(this.state, event) || //!isLaserPointerActive added by zsviczian (but don't remember why....)\n this.state.viewModeEnabled && !(0,_appState__WEBPACK_IMPORTED_MODULE_10__.isLaserPointerActive)(this.state)))) {\n return false;\n }\n\n isPanning = true; // due to event.preventDefault below, container wouldn't get focus\n // automatically\n\n this.focusContainer(); // preventing defualt while text editing messes with cursor/focus\n\n if (!this.state.editingTextElement) {\n // necessary to prevent browser from scrolling the page if excalidraw\n // not full-page #4489\n //\n // as such, the above is broken when panning canvas while in wysiwyg\n event.preventDefault();\n }\n\n let nextPastePrevented = false;\n const isLinux = typeof window === undefined ? false : /Linux/.test(window.navigator.platform);\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRABBING);\n let {\n clientX: lastX,\n clientY: lastY\n } = event;\n const onPointerMove = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdatesThrottled)(event => {\n const deltaX = lastX - event.clientX;\n const deltaY = lastY - event.clientY;\n lastX = event.clientX;\n lastY = event.clientY;\n /*\n * Prevent paste event if we move while middle clicking on Linux.\n * See issue #1383.\n */\n\n if (isLinux && !nextPastePrevented && (Math.abs(deltaX) > 1 || Math.abs(deltaY) > 1)) {\n nextPastePrevented = true;\n /* Prevent the next paste event */\n\n const preventNextPaste = event => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n event.stopPropagation();\n };\n /*\n * Reenable next paste in case of disabled middle click paste for\n * any reason:\n * - right click paste\n * - empty clipboard\n */\n\n\n const enableNextPaste = () => {\n setTimeout(() => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }, 100);\n };\n\n document.body.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }\n\n this.translateCanvas({\n scrollX: this.state.scrollX - deltaX / this.state.zoom.value,\n scrollY: this.state.scrollY - deltaY / this.state.zoom.value\n });\n });\n const teardown = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(lastPointerUp = () => {\n lastPointerUp = null;\n isPanning = false;\n\n if (!isHoldingSpace) {\n if (this.state.viewModeEnabled) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n onPointerMove.flush();\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove, {\n passive: true\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n return true;\n };\n\n this.clearSelectionIfNotUsingSelection = () => {\n if (this.state.activeTool.type !== \"selection\") {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n };\n /**\n * @returns whether the pointer event has been completely handled\n */\n\n\n this.handleSelectionOnPointerDown = (event, pointerDownState) => {\n var _a, _b;\n\n if (this.state.activeTool.type === \"selection\") {\n const elements = this.scene.getNonDeletedElements();\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !this.state.editingLinearElement && !(this.state.selectedLinearElement && this.state.selectedLinearElement.hoverPointIndex !== -1)) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);\n\n if (elementWithTransformHandleType != null) {\n if (elementWithTransformHandleType.transformHandleType === \"rotation\") {\n this.setState({\n resizingElement: elementWithTransformHandleType.element\n });\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n } else if (this.state.croppingElementId) {\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n } else {\n this.setState({\n resizingElement: elementWithTransformHandleType.element\n });\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n }\n }\n } else if (selectedElements.length > 1) {\n pointerDownState.resize.handleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.device);\n }\n\n if (pointerDownState.resize.handleType) {\n pointerDownState.resize.isResizing = true;\n pointerDownState.resize.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeOffsetXY)(pointerDownState.resize.handleType, selectedElements, elementsMap, pointerDownState.origin.x, pointerDownState.origin.y));\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0]) && selectedElements[0].points.length === 2) {\n pointerDownState.resize.arrowDirection = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeArrowDirection)(pointerDownState.resize.handleType, selectedElements[0]);\n }\n } else {\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerDown(event, this, this.store, pointerDownState.origin, linearElementEditor, this.scene);\n\n if (ret.hitElement) {\n pointerDownState.hit.element = ret.hitElement;\n }\n\n if (ret.linearElementEditor) {\n this.setState({\n selectedLinearElement: ret.linearElementEditor\n });\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: ret.linearElementEditor\n });\n }\n }\n\n if (ret.didAddPoint) {\n return true;\n }\n } // hitElement may already be set above, so check first\n\n\n pointerDownState.hit.element = (_a = pointerDownState.hit.element) !== null && _a !== void 0 ? _a : this.getElementAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n\n if (this.state.croppingElementId && ((_b = pointerDownState.hit.element) === null || _b === void 0 ? void 0 : _b.id) !== this.state.croppingElementId) {\n this.finishImageCropping();\n }\n\n if (pointerDownState.hit.element) {\n // Early return if pointer is hitting link icon\n const hitLinkElement = this.getElementLinkAtPosition({\n x: pointerDownState.origin.x,\n y: pointerDownState.origin.y\n }, pointerDownState.hit.element);\n\n if (hitLinkElement) {\n return false;\n }\n } // For overlapped elements one position may hit\n // multiple elements\n\n\n pointerDownState.hit.allHitElements = this.getElementsAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n const hitElement = pointerDownState.hit.element;\n const someHitElementIsSelected = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n\n if ((hitElement === null || !someHitElementIsSelected) && !event.shiftKey && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.clearSelection(hitElement);\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [this.state.editingLinearElement.elementId]: true\n }, this.state)\n }); // If we click on something\n } else if (hitElement != null) {\n // on CMD/CTRL, drill down to hit element regardless of groups etc.\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (!this.state.selectedElementIds[hitElement.id]) {\n pointerDownState.hit.wasAddedToSelection = true;\n }\n\n this.setState(prevState => Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.editGroupForSelectedElement)(prevState, hitElement)), {\n previousSelectedElementIds: this.state.selectedElementIds\n })); // mark as not completely handled so as to allow dragging etc.\n\n return false;\n } // deselect if item is selected\n // if shift is not clicked, this will always return true\n // otherwise, it will trigger selection based on current\n // state of the box\n\n\n if (!this.state.selectedElementIds[hitElement.id]) {\n // if we are currently editing a group, exiting editing mode and deselect the group.\n if (this.state.editingGroupId && !(0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, this.state.editingGroupId)) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } // Add hit element to selection. At this point if we're not holding\n // SHIFT the previously selected element(s) were deselected above\n // (make sure you use setState updater to use latest state)\n // With shift-selection, we want to make sure that frames and their containing\n // elements are not selected at the same time.\n\n\n if (!someHitElementIsSelected && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n });\n const previouslySelectedElements = [];\n Object.keys(prevState.selectedElementIds).forEach(id => {\n const element = this.scene.getElement(id);\n element && previouslySelectedElements.push(element);\n }); // if hitElement is frame-like, deselect all of its elements\n // if they are selected\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(hitElement)) {\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameChildren)(previouslySelectedElements, hitElement.id).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n } else if (hitElement.frameId) {\n // if hitElement is in a frame and its frame has been selected\n // disable selection for the given element\n if (nextSelectedElementIds[hitElement.frameId]) {\n delete nextSelectedElementIds[hitElement.id];\n }\n } else {\n // hitElement is neither a frame nor an element in a frame\n // but since hitElement could be in a group with some frames\n // this means selecting hitElement will have the frames selected as well\n // because we want to keep the invariant:\n // - frames and their elements are not selected at the same time\n // we deselect elements in those frames that were previously selected\n const groupIds = hitElement.groupIds;\n const framesInGroups = new Set(groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element)).map(frame => frame.id));\n\n if (framesInGroups.size > 0) {\n previouslySelectedElements.forEach(element => {\n if (element.frameId && framesInGroups.has(element.frameId)) {\n // deselect element and groups containing the element\n delete nextSelectedElementIds[element.id];\n element.groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n }\n });\n }\n }\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n pointerDownState.hit.wasAddedToSelection = true;\n }\n }\n }\n\n this.setState({\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n }\n\n return false;\n };\n\n this.handleTextOnPointerDown = (event, pointerDownState) => {\n // if we're currently still editing text, clicking outside\n // should only finalize it, not create another (irrespective\n // of state.activeTool.locked)\n if (this.state.editingTextElement) {\n return;\n }\n\n let sceneX = pointerDownState.origin.x;\n let sceneY = pointerDownState.origin.y;\n const element = this.getElementAtPosition(sceneX, sceneY, {\n includeBoundTextElement: true\n }); // FIXME\n\n let container = this.getTextBindableContainerAtPosition(sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(element)) {\n container = element;\n sceneX = element.x + element.width / 2;\n sceneY = element.y + element.height / 2;\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container,\n autoEdit: false\n });\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n\n if (!this.state.activeTool.locked) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n };\n\n this.handleFreeDrawElementOnPointerDown = (event, elementType, pointerDownState) => {\n // Begin a mark capture. This does not have to update state yet.\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, null);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const strokeOptions = this.state.currentStrokeOptions; //zsviczian\n\n const simulatePressure = (strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.constantPressure //zsviczian\n ) ? false : event.pressure === 0.5;\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFreeDrawElement)(Object.assign(Object.assign({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: null,\n simulatePressure,\n locked: false\n }, strokeOptions //zsviczian\n ? {\n customData: {\n strokeOptions\n }\n } : {}), {\n frameId: topLayerFrame ? topLayerFrame.id : null,\n points: [(0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(0, 0)],\n pressures: simulatePressure ? [] : [(strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.constantPressure) ? 1 : event.pressure]\n })); //zsviczian\n\n if (strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.highlighter) {\n this.scene.insertElement(element, 0);\n } else {\n this.scene.insertElement(element);\n }\n\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());\n this.setState({\n newElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n };\n\n this.insertIframeElement = ({\n sceneX,\n sceneY,\n width,\n height\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newIframeElement)({\n type: \"iframe\",\n x: gridX,\n y: gridY,\n strokeColor: \"transparent\",\n backgroundColor: \"transparent\",\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: this.getCurrentItemRoundness(\"iframe\"),\n opacity: this.state.currentItemOpacity,\n locked: false,\n width,\n height\n });\n this.scene.insertElement(element);\n return element;\n }; //create rectangle element with youtube top left on nearest grid point width / hight 640/360\n\n\n this.insertEmbeddableElement = ({\n sceneX,\n sceneY,\n link\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)(link);\n\n if (!embedLink) {\n return;\n }\n\n if (embedLink.error instanceof URIError) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"toast.unrecognizedLinkFormat\"),\n closable: true\n });\n }\n\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)({\n type: \"embeddable\",\n x: gridX,\n y: gridY,\n strokeColor: \"transparent\",\n backgroundColor: \"transparent\",\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: this.getCurrentItemRoundness(\"embeddable\"),\n opacity: this.state.currentItemOpacity,\n locked: false,\n width: embedLink.intrinsicSize.w,\n height: embedLink.intrinsicSize.h,\n link\n });\n this.scene.insertElement(element);\n return element;\n };\n\n this.createImageElement = ({\n sceneX,\n sceneY,\n addToFrameUnderCursor = true\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const topLayerFrame = addToFrameUnderCursor ? this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n }) : null;\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newImageElement)({\n type: \"image\",\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: null,\n opacity: this.state.currentItemOpacity,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n return element;\n };\n\n this.handleLinearElementOnPointerDown = (event, elementType, pointerDownState) => {\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state; // finalize if completing a loop\n\n if (multiElement.type === \"line\" && (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.isPathALoop)(multiElement.points, this.state.zoom.value)) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n } // Elbow arrows cannot be created by putting down points\n // only the start and end points can be defined\n\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(multiElement) && multiElement.points.length > 1) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n const {\n x: rx,\n y: ry,\n lastCommittedPoint\n } = multiElement; // clicking inside commit zone → finalize arrow\n\n if (multiElement.points.length > 1 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerDownState.origin.x - rx, pointerDownState.origin.y - ry), lastCommittedPoint) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [multiElement.id]: true\n }), prevState)\n })); // clicking outside commit zone → update reference for last committed\n // point\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else {\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n /* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.\n If so, we want it to be null for start and \"arrow\" for end. If the linear item is not\n an arrow, we want it to be null for both. Otherwise, we want it to use the\n values from appState. */\n\n const {\n currentItemStartArrowhead,\n currentItemEndArrowhead\n } = this.state;\n const [startArrowhead, endArrowhead] = elementType === \"arrow\" ? [currentItemStartArrowhead, currentItemEndArrowhead] : [null, null];\n const element = elementType === \"arrow\" ? (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newArrowElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.state.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.round ? {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : // note, roundness doesn't have any effect for elbow arrows,\n // but it's best to set it to null as well\n null,\n startArrowhead,\n endArrowhead,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null,\n elbowed: this.state.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.elbow\n }) : (0,_element__WEBPACK_IMPORTED_MODULE_16__.newLinearElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.state.currentItemRoundness === \"round\" ? {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n points: [...element.points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(0, 0)]\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap(), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(element));\n this.scene.insertElement(element);\n this.setState({\n newElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n }\n };\n\n this.createGenericElementOnPointerDown = (elementType, pointerDownState) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const baseElementAttributes = {\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.getCurrentItemRoundness(elementType),\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n };\n let element;\n\n if (elementType === \"embeddable\") {\n element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)(Object.assign({\n type: \"embeddable\"\n }, baseElementAttributes));\n } else {\n element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newElement)(Object.assign({\n type: elementType\n }, baseElementAttributes));\n }\n\n if (element.type === \"selection\") {\n this.setState({\n selectionElement: element\n });\n } else {\n this.scene.insertElement(element);\n this.setState({\n multiElement: null,\n newElement: element\n });\n }\n };\n\n this.createFrameElementOnPointerDown = (pointerDownState, type) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const constructorOpts = Object.assign(Object.assign({\n x: gridX,\n y: gridY,\n opacity: this.state.currentItemOpacity,\n locked: false\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE), this.state.frameColor ? {\n //zsviczian\n customData: {\n frameColor: this.state.frameColor\n }\n } : {});\n const frame = type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe ? (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newMagicFrameElement)(constructorOpts) : (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFrameElement)(constructorOpts);\n this.scene.insertElement(frame);\n this.setState({\n multiElement: null,\n newElement: frame\n });\n };\n\n this.restoreReadyToEraseElements = () => {\n this.elementsPendingErasure = new Set();\n this.triggerRender();\n };\n\n this.eraseElements = () => {\n let didChange = false;\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n if (this.elementsPendingErasure.has(ele.id) || ele.frameId && this.elementsPendingErasure.has(ele.frameId) || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && this.elementsPendingErasure.has(ele.containerId)) {\n didChange = true;\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n }\n\n return ele;\n });\n this.elementsPendingErasure = new Set();\n\n if (didChange) {\n this.store.shouldCaptureIncrement();\n this.scene.replaceAllElements(elements);\n }\n };\n\n this.initializeImage = async ({\n imageFile,\n imageElement: _imageElement,\n showCursorImagePreview = false\n }) => {\n var _a, _b, _c, _d; // at this point this should be guaranteed image file, but we do this check\n // to satisfy TS down the line\n\n\n if (!(0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isSupportedImageFile)(imageFile)) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\"));\n }\n\n const mimeType = imageFile.type;\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, \"wait\");\n\n if (mimeType === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n imageFile = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.SVGStringToFile)(await (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.normalizeSVG)(await imageFile.text()), imageFile.name);\n } catch (error) {\n console.warn(error);\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.svgImageInsertError\"));\n }\n } // generate image id (by default the file digest) before any\n // resizing/compression takes place to keep it more portable\n\n\n const fileId = await (((_b = (_a = this.props).generateIdForFile) === null || _b === void 0 ? void 0 : _b.call(_a, imageFile)) || (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.generateIdFromFile)(imageFile));\n\n if (!fileId) {\n console.warn(\"Couldn't generate file id or the supplied `generateIdForFile` didn't resolve to one.\");\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\"));\n }\n\n const existingFileData = this.files[fileId];\n\n if (!(existingFileData === null || existingFileData === void 0 ? void 0 : existingFileData.dataURL)) {\n try {\n imageFile = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT\n });\n } catch (error) {\n console.error(\"Error trying to resizing image file on insertion\", error);\n }\n\n if (imageFile.size > _constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.fileTooBig\", {\n maxSize: `${Math.trunc(_constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES / 1024 / 1024)}MB`\n }));\n }\n }\n\n if (showCursorImagePreview) {\n const dataURL = (_c = this.files[fileId]) === null || _c === void 0 ? void 0 : _c.dataURL; // optimization so that we don't unnecessarily resize the original\n // full-size file for cursor preview\n // (it's much faster to convert the resized dataURL to File)\n\n const resizedFile = dataURL && (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.dataURLToFile)(dataURL);\n this.setImagePreviewCursor(resizedFile || imageFile);\n }\n\n const dataURL = ((_d = this.files[fileId]) === null || _d === void 0 ? void 0 : _d.dataURL) || (await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getDataURL)(imageFile));\n const imageElement = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(_imageElement, {\n fileId\n }, false);\n return new Promise(async (resolve, reject) => {\n var _a;\n\n try {\n this.files = Object.assign(Object.assign({}, this.files), {\n [fileId]: {\n mimeType,\n id: fileId,\n dataURL,\n created: Date.now(),\n lastRetrieved: Date.now(),\n //@ts-ignore\n name: (imageFile === null || imageFile === void 0 ? void 0 : imageFile.name) && imageFile.name !== \"image.png\" ? imageFile.name : undefined // zsviczian\n\n }\n });\n const cachedImageData = this.imageCache.get(fileId);\n\n if (!cachedImageData) {\n this.addNewImagesToImageCache();\n await this.updateImageCache([imageElement]);\n }\n\n if ((cachedImageData === null || cachedImageData === void 0 ? void 0 : cachedImageData.image) instanceof Promise) {\n await cachedImageData.image;\n }\n\n if (this.state.pendingImageElementId !== imageElement.id && ((_a = this.state.newElement) === null || _a === void 0 ? void 0 : _a.id) !== imageElement.id) {\n this.initializeImageDimensions(imageElement, true);\n }\n\n resolve(imageElement);\n } catch (error) {\n console.error(error);\n reject(new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")));\n } finally {\n if (!showCursorImagePreview) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n }\n }\n });\n };\n /**\n * inserts image into elements array and rerenders\n */\n\n\n this.insertImageElement = async (imageElement, imageFile, showCursorImagePreview) => {\n // we should be handling all cases upstream, but in case we forget to handle\n // a future case, let's throw here\n if (!this.isToolSupported(\"image\")) {\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageToolNotSupported\")\n });\n return;\n }\n\n this.scene.insertElement(imageElement);\n\n try {\n return await this.initializeImage({\n imageFile,\n imageElement,\n showCursorImagePreview\n });\n } catch (error) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n isDeleted: true\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n this.setState({\n errorMessage: error.message || (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")\n });\n return null;\n }\n };\n\n this.setImagePreviewCursor = async imageFile => {\n // mustn't be larger than 128 px\n // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Basic_User_Interface/Using_URL_values_for_the_cursor_property\n const cursorImageSizePx = 96;\n let imagePreview;\n\n try {\n imagePreview = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: cursorImageSizePx\n });\n } catch (e) {\n if (e.cause === \"UNSUPPORTED\") {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\"));\n }\n\n throw e;\n }\n\n let previewDataURL = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getDataURL)(imagePreview); // SVG cannot be resized via `resizeImageFile` so we resize by rendering to\n // a small canvas\n\n if (imageFile.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n const img = await (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.loadHTMLImageElement)(previewDataURL);\n let height = Math.min(img.height, cursorImageSizePx);\n let width = height * (img.width / img.height);\n\n if (width > cursorImageSizePx) {\n width = cursorImageSizePx;\n height = width * (img.height / img.width);\n }\n\n const canvas = document.createElement(\"canvas\");\n canvas.height = height;\n canvas.width = width;\n const context = canvas.getContext(\"2d\");\n context.drawImage(img, 0, 0, width, height);\n previewDataURL = canvas.toDataURL(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg);\n }\n\n if (this.state.pendingImageElementId) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, `url(${previewDataURL}) 4 4, auto`);\n }\n };\n\n this.onImageAction = async ({\n insertOnCanvasDirectly\n }) => {\n try {\n const clientX = this.state.width / 2 + this.state.offsetLeft;\n const clientY = this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const imageFile = await (0,_data_filesystem__WEBPACK_IMPORTED_MODULE_43__.fileOpen)({\n description: \"Image\",\n extensions: Object.keys(_constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_MIME_TYPES)\n });\n const imageElement = this.createImageElement({\n sceneX: x,\n sceneY: y,\n addToFrameUnderCursor: false\n });\n\n if (insertOnCanvasDirectly) {\n this.insertImageElement(imageElement, imageFile);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } else {\n this.setState({\n pendingImageElementId: imageElement.id\n }, () => {\n this.insertImageElement(imageElement, imageFile,\n /* showCursorImagePreview */\n true);\n });\n }\n } catch (error) {\n if (error.name !== \"AbortError\") {\n console.error(error);\n } else {\n console.warn(error);\n }\n\n this.setState({\n pendingImageElementId: null,\n newElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n }\n };\n\n this.initializeImageDimensions = (imageElement, forceNaturalSize = false) => {\n var _a;\n\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(imageElement) && ((_a = this.imageCache.get(imageElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n\n if (!image || image instanceof Promise) {\n if (imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const placeholderSize = 100 / this.state.zoom.value;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x: imageElement.x - placeholderSize / 2,\n y: imageElement.y - placeholderSize / 2,\n width: placeholderSize,\n height: placeholderSize\n });\n }\n\n return;\n }\n\n if (forceNaturalSize || // if user-created bounding box is below threshold, assume the\n // intention was to click instead of drag, and use the image's\n // intrinsic size\n imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const minHeight = Math.max(this.state.height - 120, 160); // max 65% of canvas height, clamped to <300px, vh - 120px>\n\n const maxHeight = Math.min(minHeight, Math.floor(this.state.height * 0.5) / this.state.zoom.value);\n const height = Math.min(image.naturalHeight, maxHeight);\n const width = height * (image.naturalWidth / image.naturalHeight); // add current imageElement width/height to account for previous centering\n // of the placeholder image\n\n const x = imageElement.x + imageElement.width / 2 - width / 2;\n const y = imageElement.y + imageElement.height / 2 - height / 2;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x,\n y,\n width,\n height,\n crop: null\n });\n }\n };\n /** updates image cache, refreshing updated elements and/or setting status\n to error for images that fail during <img> element creation */\n\n\n this.updateImageCache = async (elements, files = this.files) => {\n const {\n updatedFiles,\n erroredFiles\n } = await (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.updateImageCache)({\n imageCache: this.imageCache,\n fileIds: elements.map(element => element.fileId),\n files\n });\n\n if (updatedFiles.size || erroredFiles.size) {\n for (const element of elements) {\n if (updatedFiles.has(element.fileId)) {\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element);\n }\n }\n }\n\n if (erroredFiles.size) {\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().map(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && erroredFiles.has(element.fileId)) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n status: \"error\"\n });\n }\n\n return element;\n }));\n }\n\n return {\n updatedFiles,\n erroredFiles\n };\n };\n /** adds new images to imageCache and re-renders if needed */\n\n\n this.addNewImagesToImageCache = async (imageElements = (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.getInitializedImageElements)(this.scene.getNonDeletedElements()), files = this.files) => {\n const uncachedImageElements = imageElements.filter(element => !element.isDeleted && !this.imageCache.has(element.fileId));\n\n if (uncachedImageElements.length) {\n const {\n updatedFiles\n } = await this.updateImageCache(uncachedImageElements, files);\n\n if (updatedFiles.size) {\n this.scene.triggerUpdate();\n }\n }\n };\n /** generally you should use `addNewImagesToImageCache()` directly if you need\n * to render new images. This is just a failsafe */\n\n\n this.scheduleImageRefresh = lodash_throttle__WEBPACK_IMPORTED_MODULE_42___default()(() => {\n this.addNewImagesToImageCache();\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_RENDER_TIMEOUT);\n\n this.updateBindingEnabledOnPointerMove = event => {\n const shouldEnableBinding = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.shouldEnableBindingForPointerEvent)(event);\n\n if (this.state.isBindingEnabled !== shouldEnableBinding) {\n this.setState({\n isBindingEnabled: shouldEnableBinding\n });\n }\n };\n\n this.maybeSuggestBindingAtCursor = pointerCoords => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerCoords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());\n this.setState({\n suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : []\n });\n };\n\n this.maybeSuggestBindingsForLinearElementAtCoords = (linearElement,\n /** scene coords */\n pointerCoords, // During line creation the start binding hasn't been written yet\n // into `linearElement`\n oppositeBindingBoundElement) => {\n if (!pointerCoords.length) {\n return;\n }\n\n const suggestedBindings = pointerCoords.reduce((acc, coords) => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(coords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap(), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(linearElement) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(linearElement));\n\n if (hoveredBindableElement != null && !(0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isLinearElementSimpleAndAlreadyBound)(linearElement, oppositeBindingBoundElement === null || oppositeBindingBoundElement === void 0 ? void 0 : oppositeBindingBoundElement.id, hoveredBindableElement)) {\n acc.push(hoveredBindableElement);\n }\n\n return acc;\n }, []);\n this.setState({\n suggestedBindings\n });\n };\n\n this.handleInteractiveCanvasRef = canvas => {\n var _a, _b; // canvas is null when unmounting\n\n\n if (canvas !== null) {\n this.interactiveCanvas = canvas; // -----------------------------------------------------------------------\n // NOTE wheel, touchstart, touchend events must be registered outside\n // of react because react binds them them passively (so we can't prevent\n // default on them)\n\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd); // -----------------------------------------------------------------------\n } else {\n (_a = this.interactiveCanvas) === null || _a === void 0 ? void 0 : _a.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n (_b = this.interactiveCanvas) === null || _b === void 0 ? void 0 : _b.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd);\n }\n };\n\n this.handleAppOnDrop = async event => {\n var _a, _b, _c, _d;\n\n if (this.props.onDrop) {\n try {\n if ((await this.props.onDrop(event)) === false) {\n return;\n }\n } catch (e) {\n console.error(e);\n }\n } // must be retrieved first, in the same frame\n\n\n const {\n file,\n fileHandle\n } = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getFileFromEvent)(event);\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n\n try {\n // if image tool not supported, don't show an error here and let it fall\n // through so we still support importing scene data from images. If no\n // scene data encoded, we'll show an error then\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isSupportedImageFile)(file) && this.isToolSupported(\"image\")) {\n // first attempt to decode scene from the image if it's embedded\n // ---------------------------------------------------------------------\n if ((file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.png || (file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n const scene = await (0,_data__WEBPACK_IMPORTED_MODULE_13__.loadFromBlob)(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n appState: Object.assign(Object.assign({}, scene.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n }));\n return;\n } catch (error) {\n // Don't throw for image scene daa\n if (error.name !== \"EncodingError\") {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"alerts.couldNotLoadInvalidFile\"));\n }\n }\n } // if no scene is embedded or we fail for whatever reason, fall back\n // to importing as regular image\n // ---------------------------------------------------------------------\n\n\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n } catch (error) {\n return this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n\n const libraryJSON = event.dataTransfer.getData(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib);\n\n if (libraryJSON && typeof libraryJSON === \"string\") {\n try {\n const libraryItems = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.parseLibraryJSON)(libraryJSON);\n this.addElementsFromPasteOrLibrary({\n elements: (0,_data_library__WEBPACK_IMPORTED_MODULE_14__.distributeLibraryItemsOnSquareGrid)(libraryItems),\n position: event,\n files: null\n });\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n\n return;\n }\n\n if (file) {\n // Attempt to parse an excalidraw/excalidrawlib file\n await this.loadFileToCanvas(file, fileHandle);\n }\n\n if ((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) === null || _b === void 0 ? void 0 : _b.includes(\"text/plain\")) {\n const text = (_c = event.dataTransfer) === null || _c === void 0 ? void 0 : _c.getData(\"text\");\n\n if (text && (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.embeddableURLValidator)(text, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(text) || ((_d = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)(text)) === null || _d === void 0 ? void 0 : _d.type) === \"video\")) {\n const embeddable = this.insertEmbeddableElement({\n sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(text)\n });\n\n if (embeddable) {\n this.setState({\n selectedElementIds: {\n [embeddable.id]: true\n }\n });\n }\n }\n }\n };\n\n this.loadFileToCanvas = async (file, fileHandle) => {\n file = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.normalizeFile)(file);\n\n try {\n const elements = this.scene.getElementsIncludingDeleted();\n let ret;\n\n try {\n ret = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.loadSceneOrLibraryFromBlob)(file, this.state, elements, fileHandle);\n } catch (error) {\n const imageSceneDataError = error instanceof _errors__WEBPACK_IMPORTED_MODULE_57__.ImageSceneDataError;\n\n if (imageSceneDataError && error.code === \"IMAGE_NOT_CONTAINS_SCENE_DATA\" && !this.isToolSupported(\"image\")) {\n this.setState({\n isLoading: false,\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageToolNotSupported\")\n });\n return;\n }\n\n const errorMessage = imageSceneDataError ? (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"alerts.cannotRestoreFromImage\") : (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"alerts.couldNotLoadInvalidFile\");\n this.setState({\n isLoading: false,\n errorMessage\n });\n }\n\n if (!ret) {\n return;\n }\n\n if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidraw) {\n // restore the fractional indices by mutating elements\n (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncInvalidIndices)(elements.concat(ret.data.elements)); // update the store snapshot for old elements, otherwise we would end up with duplicated fractional indices on undo\n\n this.store.updateSnapshot((0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(elements), this.state);\n this.setState({\n isLoading: true\n });\n this.syncActionResult(Object.assign(Object.assign({}, ret.data), {\n appState: Object.assign(Object.assign({}, ret.data.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n }));\n } else if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib) {\n await this.library.updateLibrary({\n libraryItems: file,\n merge: true,\n openLibraryMenu: true\n }).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.importLibraryError\")\n });\n });\n }\n } catch (error) {\n this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n };\n\n this.handleCanvasContextMenu = event => {\n event.preventDefault();\n\n if ((\"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"touch\" || \"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"pen\" && // always allow if user uses a pen secondary button\n event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.SECONDARY) && this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const element = this.getElementAtPosition(x, y, {\n preferSelected: true,\n includeLockedElements: true\n });\n const selectedElements = this.scene.getSelectedElements(this.state);\n const isHittingCommonBoundBox = this.isHittingCommonBoundingBoxOfSelectedElements({\n x,\n y\n }, selectedElements);\n const type = element || isHittingCommonBoundBox ? \"element\" : \"canvas\";\n const container = this.excalidrawContainerRef.current;\n const {\n top: offsetTop,\n left: offsetLeft\n } = container.getBoundingClientRect();\n const left = event.clientX - offsetLeft;\n const top = event.clientY - offsetTop;\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"contextMenu\", \"openContextMenu\", type);\n this.setState(Object.assign(Object.assign({}, element && !this.state.selectedElementIds[element.id] ? Object.assign(Object.assign(Object.assign({}, this.state), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: this.state.editingGroupId,\n selectedElementIds: {\n [element.id]: true\n }\n }, this.scene.getNonDeletedElements(), this.state, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(element) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(element) : null\n }) : this.state), {\n showHyperlinkPopup: false\n }), () => {\n this.setState({\n contextMenu: {\n top,\n left,\n items: this.getContextMenuItems(type)\n }\n });\n });\n };\n\n this.maybeDragNewGenericElement = (pointerDownState, event, informMutation = true) => {\n var _a, _b, _c, _d, _e;\n\n const selectionElement = this.state.selectionElement;\n const pointerCoords = pointerDownState.lastCoords;\n\n if (selectionElement && this.state.activeTool.type !== \"eraser\") {\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)({\n newElement: selectionElement,\n elementType: this.state.activeTool.type,\n originX: pointerDownState.origin.x,\n originY: pointerDownState.origin.y,\n x: pointerCoords.x,\n y: pointerCoords.y,\n width: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.origin.x, pointerCoords.x),\n height: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.origin.y, pointerCoords.y),\n shouldMaintainAspectRatio: (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event),\n shouldResizeFromCenter: (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event),\n zoom: this.state.zoom.value,\n informMutation\n });\n return;\n }\n\n const newElement = this.state.newElement;\n\n if (!newElement) {\n return;\n }\n\n let [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(newElement) && ((_a = this.imageCache.get(newElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n const aspectRatio = image && !(image instanceof Promise) ? image.width / image.height : null;\n this.maybeCacheReferenceSnapPoints(event, [newElement]);\n const {\n snapOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.snapNewElement)(newElement, this, event, {\n x: pointerDownState.originInGrid.x + ((_c = (_b = this.state.originSnapOffset) === null || _b === void 0 ? void 0 : _b.x) !== null && _c !== void 0 ? _c : 0),\n y: pointerDownState.originInGrid.y + ((_e = (_d = this.state.originSnapOffset) === null || _d === void 0 ? void 0 : _d.y) !== null && _e !== void 0 ? _e : 0)\n }, {\n x: gridX - pointerDownState.originInGrid.x,\n y: gridY - pointerDownState.originInGrid.y\n }, this.scene.getNonDeletedElementsMap());\n gridX += snapOffset.x;\n gridY += snapOffset.y;\n this.setState({\n snapLines\n });\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)({\n newElement,\n elementType: this.state.activeTool.type,\n originX: pointerDownState.originInGrid.x,\n originY: pointerDownState.originInGrid.y,\n x: gridX,\n y: gridY,\n width: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.originInGrid.x, gridX),\n height: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.originInGrid.y, gridY),\n shouldMaintainAspectRatio: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(newElement) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event),\n shouldResizeFromCenter: (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event),\n zoom: this.state.zoom.value,\n widthAspectRatio: aspectRatio,\n originOffset: this.state.originSnapOffset,\n informMutation\n });\n this.setState({\n newElement\n }); // highlight elements that are to be added to frames on frames creation\n\n if (this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.frame || this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe) {\n this.setState({\n elementsToHighlight: (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), newElement, this.state, this.scene.getNonDeletedElementsMap())\n });\n }\n };\n\n this.maybeHandleCrop = (pointerDownState, event) => {\n var _a; // to crop, we must already be in the cropping mode, where croppingElement has been set\n\n\n if (!this.state.croppingElementId) {\n return false;\n }\n\n const transformHandleType = pointerDownState.resize.handleType;\n const pointerCoords = pointerDownState.lastCoords;\n const [x, y] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x - pointerDownState.resize.offset.x, pointerCoords.y - pointerDownState.resize.offset.y, this.getEffectiveGridSize());\n const croppingElement = this.scene.getNonDeletedElementsMap().get(this.state.croppingElementId);\n\n if (transformHandleType && croppingElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(croppingElement)) {\n const croppingAtStateStart = pointerDownState.originalElements.get(croppingElement.id);\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(croppingElement) && ((_a = this.imageCache.get(croppingElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n\n if (croppingAtStateStart && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(croppingAtStateStart) && image && !(image instanceof Promise)) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(croppingElement, (0,_element_cropElement__WEBPACK_IMPORTED_MODULE_99__.cropElement)(croppingElement, transformHandleType, image.naturalWidth, image.naturalHeight, x, y, event.shiftKey ? croppingAtStateStart.width / croppingAtStateStart.height : undefined));\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(croppingElement, this.scene.getNonDeletedElementsMap(), {\n oldSize: {\n width: croppingElement.width,\n height: croppingElement.height\n }\n });\n this.setState({\n isCropping: transformHandleType && transformHandleType !== \"rotation\"\n });\n }\n\n return true;\n }\n\n return false;\n };\n\n this.maybeHandleResize = (pointerDownState, event) => {\n const selectedElements = this.scene.getSelectedElements(this.state);\n const selectedFrames = selectedElements.filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element));\n const transformHandleType = pointerDownState.resize.handleType;\n\n if ( // Frames cannot be rotated.\n selectedFrames.length > 0 && transformHandleType === \"rotation\" || // Elbow arrows cannot be transformed (resized or rotated).\n selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0]) || // Do not resize when in crop mode\n this.state.croppingElementId) {\n return false;\n }\n\n this.setState({\n // TODO: rename this state field to \"isScaling\" to distinguish\n // it from the generic \"isResizing\" which includes scaling and\n // rotating\n isResizing: transformHandleType && transformHandleType !== \"rotation\",\n isRotating: transformHandleType === \"rotation\",\n activeEmbeddable: null\n });\n const pointerCoords = pointerDownState.lastCoords;\n let [resizeX, resizeY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x - pointerDownState.resize.offset.x, pointerCoords.y - pointerDownState.resize.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const frameElementsOffsetsMap = new Map();\n selectedFrames.forEach(frame => {\n const elementsInFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameChildren)(this.scene.getNonDeletedElements(), frame.id);\n elementsInFrame.forEach(element => {\n frameElementsOffsetsMap.set(frame.id + element.id, {\n x: element.x - frame.x,\n y: element.y - frame.y\n });\n });\n }); // check needed for avoiding flickering when a key gets pressed\n // during dragging\n\n if (!this.state.selectedElementsAreBeingDragged) {\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const dragOffset = {\n x: gridX - pointerDownState.originInGrid.x,\n y: gridY - pointerDownState.originInGrid.y\n };\n const originalElements = [...pointerDownState.originalElements.values()];\n this.maybeCacheReferenceSnapPoints(event, selectedElements);\n const {\n snapOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.snapResizingElements)(selectedElements, (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(originalElements, this.state), this, event, dragOffset, transformHandleType);\n resizeX += snapOffset.x;\n resizeY += snapOffset.y;\n this.setState({\n snapLines\n });\n }\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.transformElements)(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event), selectedElements.some(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(element)) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {\n const suggestedBindings = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getSuggestedBindingsForArrows)(selectedElements, this.scene.getNonDeletedElementsMap());\n const elementsToHighlight = new Set();\n selectedFrames.forEach(frame => {\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), frame, this.state, this.scene.getNonDeletedElementsMap()).forEach(element => elementsToHighlight.add(element));\n });\n this.setState({\n elementsToHighlight: [...elementsToHighlight],\n suggestedBindings\n });\n return true;\n }\n\n return false;\n };\n\n this.getContextMenuItems = type => {\n const options = [];\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg); // canvas contextMenu\n // -------------------------------------------------------------------------\n\n if (type === \"canvas\") {\n if (this.state.viewModeEnabled) {\n return [...options, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_39__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats, _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleLaserPointer];\n }\n\n return [_actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg, _actions__WEBPACK_IMPORTED_MODULE_5__.copyText, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSelectAll, _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__.actionUnlockAllElements, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleObjectsSnapMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_39__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats];\n } // element contextMenu\n // -------------------------------------------------------------------------\n\n\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.copyText);\n\n if (this.state.viewModeEnabled) {\n return [_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, ...options];\n }\n\n return [_ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionSelectAllElementsInFrame, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionRemoveAllElementsFromFrame, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleCropEditor, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, ...options, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyStyles, _actions__WEBPACK_IMPORTED_MODULE_5__.actionPasteStyles, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionGroup, _actions_actionTextAutoResize__WEBPACK_IMPORTED_MODULE_90__.actionTextAutoResize, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUnbindText, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBindText, _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_59__.actionWrapTextInContainer, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUngroup, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionAddToLibrary, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendBackward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringForward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendToBack, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringToFront, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipHorizontal, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipVertical, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleLinearEditor, _actions__WEBPACK_IMPORTED_MODULE_5__.actionLink, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDuplicateSelection, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleElementLock, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDeleteSelected];\n };\n\n this.handleWheel = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n // if not scrolling on canvas/wysiwyg, ignore\n if (!(event.target instanceof HTMLCanvasElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLIFrameElement)) {\n // prevent zooming the browser (but allow scrolling DOM)\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n }\n\n return;\n }\n\n event.preventDefault();\n\n if (isPanning) {\n return;\n }\n\n const {\n deltaX,\n deltaY\n } = event; // note that event.ctrlKey is necessary to handle pinch zooming\n\n if ( //zsviczian\n (event.metaKey || event.ctrlKey) && !this.state.allowWheelZoom || !(event.metaKey || event.ctrlKey) && this.state.allowWheelZoom) {\n const sign = Math.sign(deltaY);\n const MAX_STEP = _constants__WEBPACK_IMPORTED_MODULE_12__.ZOOM_STEP * 100;\n const absDelta = Math.abs(deltaY);\n let delta = deltaY;\n\n if (absDelta > MAX_STEP) {\n delta = MAX_STEP * sign;\n }\n\n let newZoom = this.state.zoom.value - delta / 100; // increase zoom steps the more zoomed-in we are (applies to >100% only)\n\n newZoom += Math.log10(Math.max(1, this.state.zoom.value)) * -sign * // reduced amplification for small deltas (small movements on a trackpad)\n Math.min(1, absDelta / 20);\n this.translateCanvas(state => Object.assign(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(newZoom)\n }, state)), {\n shouldCacheIgnoreZoom: true\n }));\n this.resetShouldCacheIgnoreZoomDebounced();\n return;\n } // scroll horizontally when shift pressed\n\n\n if (event.shiftKey) {\n this.translateCanvas(({\n zoom,\n scrollX\n }) => ({\n // on Mac, shift+wheel tends to result in deltaX\n scrollX: scrollX - (deltaY || deltaX) / zoom.value\n }));\n return;\n }\n\n this.translateCanvas(({\n zoom,\n scrollX,\n scrollY\n }) => ({\n scrollX: scrollX - deltaX / zoom.value,\n scrollY: scrollY - deltaY / zoom.value\n }));\n });\n\n this.savePointer = (x, y, button) => {\n var _a, _b;\n\n if (!x || !y) {\n return;\n }\n\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: x,\n clientY: y\n }, this.state);\n\n if (isNaN(sceneX) || isNaN(sceneY)) {// sometimes the pointer goes off screen\n }\n\n const pointer = {\n x: sceneX,\n y: sceneY,\n tool: this.state.activeTool.type === \"laser\" ? \"laser\" : \"pointer\"\n };\n (_b = (_a = this.props).onPointerUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, {\n pointer,\n button,\n pointersMap: gesture.pointers\n });\n };\n\n this.resetShouldCacheIgnoreZoomDebounced = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.debounce)(() => {\n if (!this.unmounted) {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n }\n }, 300);\n\n this.updateDOMRect = cb => {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n width,\n height,\n left: offsetLeft,\n top: offsetTop\n } = excalidrawContainer.getBoundingClientRect();\n const {\n width: currentWidth,\n height: currentHeight,\n offsetTop: currentOffsetTop,\n offsetLeft: currentOffsetLeft\n } = this.state;\n\n if (width === currentWidth && height === currentHeight && offsetLeft === currentOffsetLeft && offsetTop === currentOffsetTop) {\n if (cb) {\n cb();\n }\n\n return;\n } //zsviczian\n\n\n if (width === 0 || height === 0) {\n if (cb) {\n cb();\n }\n\n return;\n }\n\n this.setState({\n width,\n height,\n offsetLeft,\n offsetTop\n }, () => {\n cb && cb();\n });\n }\n };\n\n this.refresh = () => {\n this.setState(Object.assign({}, this.getCanvasOffsets()));\n };\n\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)();\n const {\n excalidrawAPI,\n viewModeEnabled = false,\n zenModeEnabled = false,\n gridModeEnabled = false,\n objectsSnapModeEnabled = false,\n theme = defaultAppState.theme,\n initState,\n //zsviczian\n name = `${(0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.untitled\")}-${(0,_utils__WEBPACK_IMPORTED_MODULE_34__.getDateTime)()}`\n } = props;\n this.state = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaultAppState), {\n theme,\n isLoading: true\n }), this.getCanvasOffsets()), {\n viewModeEnabled,\n zenModeEnabled,\n objectsSnapModeEnabled,\n gridModeEnabled: gridModeEnabled !== null && gridModeEnabled !== void 0 ? gridModeEnabled : defaultAppState.gridModeEnabled,\n name,\n width: window.innerWidth,\n height: window.innerHeight\n }), initState !== null && initState !== void 0 ? initState : {});\n this.id = (0,nanoid__WEBPACK_IMPORTED_MODULE_100__.nanoid)();\n (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.initializeObsidianUtils)();\n this.library = new _data_library__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this);\n this.actionManager = new _actions_manager__WEBPACK_IMPORTED_MODULE_7__.ActionManager(this.syncActionResult, () => this.state, () => this.scene.getElementsIncludingDeleted(), this);\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_29__[\"default\"]();\n this.canvas = document.createElement(\"canvas\");\n this.rc = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__[\"default\"].canvas(this.canvas);\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_65__.Renderer(this.scene);\n this.visibleElements = [];\n this.store = new _store__WEBPACK_IMPORTED_MODULE_76__.Store();\n this.history = new _history__WEBPACK_IMPORTED_MODULE_24__.History();\n\n if (excalidrawAPI) {\n const api = {\n updateScene: this.updateScene,\n updateLibrary: this.library.updateLibrary,\n addFiles: this.addFiles,\n resetScene: this.resetScene,\n getSceneElementsIncludingDeleted: this.getSceneElementsIncludingDeleted,\n history: {\n clear: this.resetHistory\n },\n scrollToContent: this.scrollToContent,\n zoomToFit: this.zoomToFit,\n startLineEditor: this.startLineEditor,\n getSceneElements: this.getSceneElements,\n getAppState: () => this.state,\n getFiles: () => this.files,\n getName: this.getName,\n registerAction: action => {\n this.actionManager.registerAction(action);\n },\n refresh: this.refresh,\n setToast: this.setToast,\n updateContainerSize: this.updateContainerSize,\n id: this.id,\n selectElements: this.selectElements,\n sendBackward: this.sendBackward,\n bringForward: this.bringForward,\n sendToBack: this.sendToBack,\n bringToFront: this.bringToFront,\n setMobileModeAllowed: this.setMobileModeAllowed,\n setActiveTool: this.setActiveTool,\n setCursor: this.setCursor,\n resetCursor: this.resetCursor,\n updateFrameRendering: this.updateFrameRendering,\n toggleSidebar: this.toggleSidebar,\n getHTMLIFrameElement: id => this.getHTMLIFrameElement(id),\n onChange: cb => this.onChangeEmitter.on(cb),\n onPointerDown: cb => this.onPointerDownEmitter.on(cb),\n onPointerUp: cb => this.onPointerUpEmitter.on(cb),\n onScrollChange: cb => this.onScrollChangeEmitter.on(cb),\n onUserFollow: cb => this.onUserFollowEmitter.on(cb)\n };\n\n if (typeof excalidrawAPI === \"function\") {\n excalidrawAPI(api);\n } else {\n console.error(\"excalidrawAPI should be a function!\");\n }\n }\n\n this.excalidrawContainerValue = {\n container: this.excalidrawContainerRef.current,\n id: this.id\n };\n this.fonts = new _fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts(this.scene);\n this.history = new _history__WEBPACK_IMPORTED_MODULE_24__.History();\n this.actionManager.registerAll(_actions_register__WEBPACK_IMPORTED_MODULE_8__.actions);\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createUndoAction)(this.history, this.store));\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createRedoAction)(this.history, this.store));\n }\n\n onWindowMessage(event) {\n if (event.origin !== \"https://player.vimeo.com\" && event.origin !== \"https://www.youtube.com\") {\n return;\n }\n\n let data = null;\n\n try {\n data = JSON.parse(event.data);\n } catch (e) {}\n\n if (!data) {\n return;\n }\n\n switch (event.origin) {\n case \"https://player.vimeo.com\":\n //Allowing for multiple instances of Excalidraw running in the window\n if (data.method === \"paused\") {\n let source = null;\n const iframes = document.body.querySelectorAll(\"iframe.excalidraw__embeddable\");\n\n if (!iframes) {\n break;\n }\n\n for (const iframe of iframes) {\n if (iframe.contentWindow === event.source) {\n source = iframe.contentWindow;\n }\n }\n\n source === null || source === void 0 ? void 0 : source.postMessage(JSON.stringify({\n method: data.value ? \"play\" : \"pause\",\n value: true\n }), \"*\");\n }\n\n break;\n\n case \"https://www.youtube.com\":\n if (data.event === \"infoDelivery\" && data.info && data.id && typeof data.info.playerState === \"number\") {\n const id = data.id;\n const playerState = data.info.playerState;\n\n if (Object.values(_constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES).includes(playerState)) {\n YOUTUBE_VIDEO_STATES.set(id, playerState);\n }\n }\n\n break;\n }\n }\n\n cacheEmbeddableRef(element, ref) {\n if (ref) {\n this.iFrameRefs.set(element.id, ref);\n }\n }\n\n getHTMLIFrameElement(element) {\n //zsviczian\n if (typeof element === \"string\") {\n return this.iFrameRefs.get(element);\n }\n\n return this.iFrameRefs.get(element.id);\n }\n\n handleEmbeddableCenterClick(element) {\n var _a, _b, _c, _d;\n\n if (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) === element && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"active\") {\n return;\n } // The delay serves two purposes\n // 1. To prevent first click propagating to iframe on mobile,\n // else the click will immediately start and stop the video\n // 2. If the user double clicks the frame center to activate it\n // without the delay youtube will immediately open the video\n // in fullscreen mode\n\n\n setTimeout(() => {\n this.setState({\n activeEmbeddable: {\n element,\n state: \"active\"\n },\n selectedElementIds: {\n [element.id]: true\n },\n newElement: null,\n selectionElement: null\n });\n }, 100);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(element)) {\n return;\n }\n\n const iframe = this.getHTMLIFrameElement(element);\n\n if (!(iframe === null || iframe === void 0 ? void 0 : iframe.contentWindow)) {\n return;\n }\n\n if (iframe.src.includes(\"youtube\")) {\n const state = YOUTUBE_VIDEO_STATES.get(element.id);\n\n if (!state) {\n YOUTUBE_VIDEO_STATES.set(element.id, _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.UNSTARTED);\n iframe.contentWindow.postMessage(JSON.stringify({\n event: \"listening\",\n id: element.id\n }), \"*\");\n }\n\n switch (state) {\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.PLAYING:\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.BUFFERING:\n (_c = iframe.contentWindow) === null || _c === void 0 ? void 0 : _c.postMessage(JSON.stringify({\n event: \"command\",\n func: \"pauseVideo\",\n args: \"\"\n }), \"*\");\n break;\n\n default:\n (_d = iframe.contentWindow) === null || _d === void 0 ? void 0 : _d.postMessage(JSON.stringify({\n event: \"command\",\n func: \"playVideo\",\n args: \"\"\n }), \"*\");\n }\n }\n\n if (iframe.src.includes(\"player.vimeo.com\")) {\n iframe.contentWindow.postMessage(JSON.stringify({\n method: \"paused\" //video play/pause in onWindowMessage handler\n\n }), \"*\");\n }\n }\n\n isIframeLikeElementCenter(el, event, sceneX, sceneY) {\n var _a, _b;\n\n return el && !event.altKey && !event.shiftKey && !event.metaKey && !event.ctrlKey && (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) !== el || ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\" || !this.state.activeEmbeddable) && sceneX >= el.x + el.width / 3 && sceneX <= el.x + 2 * el.width / 3 && sceneY >= el.y + el.height / 3 && sceneY <= el.y + 2 * el.height / 3;\n }\n\n renderEmbeddables() {\n const scale = this.state.zoom.value;\n const normalizedWidth = this.state.width;\n const normalizedHeight = this.state.height;\n const embeddableElements = this.scene.getNonDeletedElements().filter(el => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(el) && this.embedsValidationStatus.get(el.id) === true || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el));\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: embeddableElements.map(el => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: el.x,\n sceneY: el.y\n }, this.state);\n const isVisible = (0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(el, normalizedWidth, normalizedHeight, this.state, this.scene.getNonDeletedElementsMap());\n const hasBeenInitialized = this.initializedEmbeds.has(el.id);\n\n if (isVisible && !hasBeenInitialized) {\n this.initializedEmbeds.add(el.id);\n }\n\n const shouldRender = isVisible || hasBeenInitialized;\n\n if (!shouldRender) {\n return null;\n }\n\n let src;\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)((0,_data_url__WEBPACK_IMPORTED_MODULE_46__.toValidURL)(el.link || \"\")); //zsviczian\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el)) {\n src = null;\n const data = ((_b = (_a = el.customData) === null || _a === void 0 ? void 0 : _a.generationData) !== null && _b !== void 0 ? _b : this.magicGenerations.get(el.id)) || {\n status: \"error\",\n message: \"No generation data\",\n code: \"ERR_NO_GENERATION_DATA\"\n };\n\n if (data.status === \"done\") {\n const html = data.html;\n src = {\n intrinsicSize: {\n w: el.width,\n h: el.height\n },\n type: \"document\",\n srcdoc: () => {\n return html;\n }\n };\n } else if (data.status === \"pending\") {\n src = {\n intrinsicSize: {\n w: el.width,\n h: el.height\n },\n type: \"document\",\n srcdoc: () => {\n return (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.createSrcDoc)(`\n <style>\n html, body {\n width: 100%;\n height: 100%;\n color: ${this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.DARK ? \"white\" : \"black\"};\n }\n body {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 1rem;\n }\n\n .Spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: auto;\n margin-right: auto;\n }\n\n .Spinner svg {\n animation: rotate 1.6s linear infinite;\n transform-origin: center center;\n width: 40px;\n height: 40px;\n }\n\n .Spinner circle {\n stroke: currentColor;\n animation: dash 1.6s linear 0s infinite;\n stroke-linecap: round;\n }\n\n @keyframes rotate {\n 100% {\n transform: rotate(360deg);\n }\n }\n\n @keyframes dash {\n 0% {\n stroke-dasharray: 1, 300;\n stroke-dashoffset: 0;\n }\n 50% {\n stroke-dasharray: 150, 300;\n stroke-dashoffset: -200;\n }\n 100% {\n stroke-dasharray: 1, 300;\n stroke-dashoffset: -280;\n }\n }\n </style>\n <div class=\"Spinner\">\n <svg\n viewBox=\"0 0 100 100\"\n >\n <circle\n cx=\"50\"\n cy=\"50\"\n r=\"46\"\n stroke-width=\"8\"\n fill=\"none\"\n stroke-miter-limit=\"10\"\n />\n </svg>\n </div>\n <div>Generating...</div>\n `);\n }\n };\n } else {\n let message;\n\n if (data.code === \"ERR_GENERATION_INTERRUPTED\") {\n message = \"Generation was interrupted...\";\n } else {\n message = data.message || \"Generation failed\";\n }\n\n src = {\n intrinsicSize: {\n w: el.width,\n h: el.height\n },\n type: \"document\",\n srcdoc: () => {\n return (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.createSrcDoc)(`\n <style>\n html, body {\n height: 100%;\n }\n body {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: ${_colors__WEBPACK_IMPORTED_MODULE_71__.COLOR_PALETTE.red[3]};\n }\n h1, h3 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n }\n </style>\n <h1>Error!</h1>\n <h3>${message}</h3>\n `);\n }\n };\n }\n } else {\n src = embedLink; //zsviczian getEmbedLink(toValidURL(el.link || \"\"));\n }\n\n const isActive = ((_c = this.state.activeEmbeddable) === null || _c === void 0 ? void 0 : _c.element) === el && ((_d = this.state.activeEmbeddable) === null || _d === void 0 ? void 0 : _d.state) === \"active\";\n const isHovered = ((_e = this.state.activeEmbeddable) === null || _e === void 0 ? void 0 : _e.element) === el && ((_f = this.state.activeEmbeddable) === null || _f === void 0 ? void 0 : _f.state) === \"hover\";\n const isWebview = //zsviczian\n !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el) && this.props.renderWebview && (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) !== \"document\" && !((_h = (_g = embedLink === null || embedLink === void 0 ? void 0 : embedLink.link) === null || _g === void 0 ? void 0 : _g.startsWith) === null || _h === void 0 ? void 0 : _h.call(_g, \"https://player.vimeo.com\")); // Modify the scale based on el.scale property\n\n const [xScale, yScale] = (_j = el.scale) !== null && _j !== void 0 ? _j : [1, 1]; //zsviczian\n\n const scaledTransform = `scale(${scale * xScale}, ${scale * yScale})`;\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw__embeddable-container\", {\n \"is-hovered\": isHovered\n }),\n style: {\n transform: isVisible ? `translate(${x - this.state.offsetLeft}px, ${y - this.state.offsetTop}px) ${scaledTransform}` : \"none\",\n display: isVisible ? \"block\" : \"none\",\n opacity: (0,_renderer_renderElement__WEBPACK_IMPORTED_MODULE_81__.getRenderOpacity)(el, (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(el, this.scene.getNonDeletedElementsMap()), this.elementsPendingErasure, null),\n [\"--embeddable-radius\"]: `${(0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getCornerRadius)(Math.min(el.width, el.height), el) / xScale //zsviczian\n }px`\n }\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n //this is a hack that addresses isse with embedded excalidraw.com embeddable\n //https://github.com/excalidraw/excalidraw/pull/6691#issuecomment-1607383938\n\n /*ref={(ref) => {\n if (!this.excalidrawContainerRef.current) {\n return;\n }\n const container = this.excalidrawContainerRef.current;\n const sh = container.scrollHeight;\n const ch = container.clientHeight;\n if (sh !== ch) {\n container.style.height = `${sh}px`;\n setTimeout(() => {\n container.style.height = `100%`;\n });\n }\n }}*/\n className: \"excalidraw__embeddable-container__inner\",\n style: {\n width: isVisible ? `${el.width / xScale}px` : 0,\n height: isVisible ? `${el.height / yScale}px` : 0,\n transform: isVisible ? `rotate(${el.angle}rad)` : \"none\",\n pointerEvents: isActive ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled\n }\n }, {\n children: [isHovered && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable-hint\"\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"buttons.embeddableInteractionButton\")\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable__outer\",\n style: {\n padding: `${el.strokeWidth / (4 * el.scale[0])}px` //zsviczian MDEmbeddable round border cutoff issue\n\n }\n }, {\n children: (_m = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(el) ? (_l = (_k = this.props).renderEmbeddable) === null || _l === void 0 ? void 0 : _l.call(_k, el, this.state) //zsviczian\n : null) !== null && _m !== void 0 ? _m : isWebview ? //zsviczian\n (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"webview\", {\n ref: ref => this.cacheEmbeddableRef(el, ref),\n className: \"excalidraw__embeddable\",\n src: (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) === \"generic\" || (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) === \"video\" ? embedLink.link : \"\",\n title: \"Excalidraw Embedded Content\",\n allowFullScreen: true\n }) : (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"iframe\", {\n ref: ref => this.cacheEmbeddableRef(el, ref),\n className: \"excalidraw__embeddable\",\n srcDoc: (src === null || src === void 0 ? void 0 : src.type) === \"document\" ? src.srcdoc(this.state.theme) : undefined,\n src: (src === null || src === void 0 ? void 0 : src.type) !== \"document\" ? (_o = src === null || src === void 0 ? void 0 : src.link) !== null && _o !== void 0 ? _o : \"\" : undefined,\n // https://stackoverflow.com/q/18470015\n scrolling: \"no\",\n referrerPolicy: \"no-referrer-when-downgrade\",\n title: \"Excalidraw Embedded Content\",\n allow: \"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\",\n allowFullScreen: true,\n sandbox: `${((_p = src === null || src === void 0 ? void 0 : src.sandbox) === null || _p === void 0 ? void 0 : _p.allowSameOrigin) ? \"allow-same-origin\" : \"\"} allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads`\n })\n }))]\n }))\n }), el.id);\n })\n });\n }\n\n toggleOverscrollBehavior(event) {\n // when pointer inside editor, disable overscroll behavior to prevent\n // panning to trigger history back/forward on MacOS Chrome\n document.documentElement.style.overscrollBehaviorX = event.type === \"pointerenter\" ? \"none\" : \"auto\";\n }\n\n render() {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n const {\n renderTopRightUI,\n renderCustomStats\n } = this.props;\n const sceneNonce = this.scene.getSceneNonce();\n const {\n elementsMap,\n visibleElements\n } = this.renderer.getRenderableElements({\n sceneNonce,\n zoom: this.state.zoom,\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n height: this.state.height,\n width: this.state.width,\n editingTextElement: this.state.editingTextElement,\n newElementId: (_a = this.state.newElement) === null || _a === void 0 ? void 0 : _a.id,\n pendingImageElementId: this.state.pendingImageElementId\n });\n this.visibleElements = visibleElements;\n const allElementsMap = this.scene.getNonDeletedElementsMap();\n const shouldBlockPointerEvents = this.state.selectionElement || this.state.newElement || this.state.selectedElementsAreBeingDragged || this.state.resizingElement || this.state.activeTool.type === \"laser\" && // technically we can just test on this once we make it more safe\n this.state.cursorButton === \"down\";\n const firstSelectedElement = selectedElements[0]; //zsviczian\n\n const isHighlighter = (_d = (_c = (_b = this.state.newElement) === null || _b === void 0 ? void 0 : _b.customData) === null || _c === void 0 ? void 0 : _c.strokeOptions) === null || _d === void 0 ? void 0 : _d.highlighter;\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw excalidraw-container\", {\n \"excalidraw--view-mode\": this.state.viewModeEnabled,\n \"excalidraw--mobile\": this.device.editor.isMobile || !(this.state.viewModeEnabled || this.state.zenModeEnabled) && this.state.trayModeEnabled //zsviczian\n\n }),\n style: Object.assign({\n //zsviczian\n [\"--ui-pointerEvents\"]: shouldBlockPointerEvents ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled\n }, this.state.dynamicStyle),\n ref: this.excalidrawContainerRef,\n onDrop: this.handleAppOnDrop,\n tabIndex: 0,\n onKeyDown: this.props.handleKeyboardGlobally ? undefined : this.onKeyDown,\n onPointerEnter: this.toggleOverscrollBehavior,\n onPointerLeave: this.toggleOverscrollBehavior\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppContext.Provider, Object.assign({\n value: this\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppPropsContext.Provider, Object.assign({\n value: this.props\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawContainerContext.Provider, Object.assign({\n value: this.excalidrawContainerValue\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DeviceContext.Provider, Object.assign({\n value: this.device\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawSetAppStateContext.Provider, Object.assign({\n value: this.setAppState\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawAppStateContext.Provider, Object.assign({\n value: this.state\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawElementsContext.Provider, Object.assign({\n value: this.scene.getNonDeletedElements()\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawActionManagerContext.Provider, Object.assign({\n value: this.actionManager\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LayerUI__WEBPACK_IMPORTED_MODULE_37__[\"default\"], Object.assign({\n canvas: this.canvas,\n appState: this.state,\n files: this.files,\n setAppState: this.setAppState,\n actionManager: this.actionManager,\n elements: this.scene.getNonDeletedElements(),\n onLockToggle: this.toggleLock,\n onPenModeToggle: this.togglePenMode,\n onHandToolToggle: this.onHandToolToggle,\n langCode: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.getLanguage)().code,\n renderTopRightUI: renderTopRightUI,\n renderCustomStats: renderCustomStats,\n showExitZenModeBtn: typeof ((_e = this.props) === null || _e === void 0 ? void 0 : _e.zenModeEnabled) === \"undefined\" && this.state.zenModeEnabled,\n UIOptions: this.props.UIOptions,\n onExportImage: this.onExportImage,\n renderWelcomeScreen: !this.state.isLoading && this.state.showWelcomeScreen && this.state.activeTool.type === \"selection\" && !this.state.zenModeEnabled && !this.scene.getElementsIncludingDeleted().length,\n app: this,\n isCollaborating: this.props.isCollaborating\n }, {\n children: this.props.children\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-textEditorContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-contextMenuContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-eye-dropper-container\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_SVGLayer__WEBPACK_IMPORTED_MODULE_67__.SVGLayer, {\n trails: [this.laserTrails, this.eraserTrail]\n }), selectedElements.length === 1 && this.state.showHyperlinkPopup && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.Hyperlink, {\n element: firstSelectedElement,\n elementsMap: allElementsMap,\n setAppState: this.setAppState,\n onLinkOpen: this.props.onLinkOpen,\n setToast: this.setToast,\n updateEmbedValidationStatus: this.updateEmbedValidationStatus\n }, firstSelectedElement.id), this.props.aiEnabled !== false && selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isMagicFrameElement)(firstSelectedElement) && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_element_ElementCanvasButtons__WEBPACK_IMPORTED_MODULE_70__.ElementCanvasButtons, Object.assign({\n element: firstSelectedElement,\n elementsMap: elementsMap\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MagicButton__WEBPACK_IMPORTED_MODULE_72__.ElementCanvasButton, {\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.convertToCode\"),\n icon: _icons__WEBPACK_IMPORTED_MODULE_73__.MagicIcon,\n checked: false,\n onChange: () => this.onMagicFrameGenerate(firstSelectedElement, \"button\")\n })\n })), selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(firstSelectedElement) && ((_g = (_f = firstSelectedElement.customData) === null || _f === void 0 ? void 0 : _f.generationData) === null || _g === void 0 ? void 0 : _g.status) === \"done\" && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_element_ElementCanvasButtons__WEBPACK_IMPORTED_MODULE_70__.ElementCanvasButtons, Object.assign({\n element: firstSelectedElement,\n elementsMap: elementsMap\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MagicButton__WEBPACK_IMPORTED_MODULE_72__.ElementCanvasButton, {\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.copySource\"),\n icon: _icons__WEBPACK_IMPORTED_MODULE_73__.copyIcon,\n checked: false,\n onChange: () => this.onIframeSrcCopy(firstSelectedElement)\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MagicButton__WEBPACK_IMPORTED_MODULE_72__.ElementCanvasButton, {\n title: \"Enter fullscreen\",\n icon: _icons__WEBPACK_IMPORTED_MODULE_73__.fullscreenIcon,\n checked: false,\n onChange: () => {\n const iframe = this.getHTMLIFrameElement(firstSelectedElement);\n\n if (iframe) {\n try {\n iframe.requestFullscreen();\n this.setState({\n activeEmbeddable: {\n element: firstSelectedElement,\n state: \"active\"\n },\n selectedElementIds: {\n [firstSelectedElement.id]: true\n },\n newElement: null,\n selectionElement: null\n });\n } catch (err) {\n console.warn(err);\n this.setState({\n errorMessage: \"Couldn't enter fullscreen\"\n });\n }\n }\n }\n })]\n })), this.state.toast !== null && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Toast__WEBPACK_IMPORTED_MODULE_38__.Toast, {\n message: this.state.toast.message,\n onClose: () => this.setToast(null),\n duration: this.state.toast.duration,\n closable: this.state.toast.closable\n }), this.state.contextMenu && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ContextMenu__WEBPACK_IMPORTED_MODULE_36__.ContextMenu, {\n items: this.state.contextMenu.items,\n top: this.state.contextMenu.top,\n left: this.state.contextMenu.left,\n actionManager: this.actionManager,\n onClose: callback => {\n this.setState({\n contextMenu: null\n }, () => {\n this.focusContainer();\n callback === null || callback === void 0 ? void 0 : callback();\n });\n }\n }), this.state.newElement && isHighlighter && //zsviczian\n (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases_NewElementCanvas__WEBPACK_IMPORTED_MODULE_94__[\"default\"], {\n appState: this.state,\n scale: window.devicePixelRatio,\n rc: this.rc,\n elementsMap: elementsMap,\n allElementsMap: allElementsMap,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: false,\n canvasBackgroundColor: this.state.viewBackgroundColor,\n embedsValidationStatus: this.embedsValidationStatus,\n elementsPendingErasure: this.elementsPendingErasure,\n pendingFlowchartNodes: null,\n isHighlighterPenDrawing: isHighlighter //zsviczian\n\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_64__.StaticCanvas, {\n canvas: this.canvas,\n rc: this.rc,\n elementsMap: elementsMap,\n allElementsMap: allElementsMap,\n visibleElements: visibleElements,\n sceneNonce: sceneNonce,\n selectionNonce: (_h = this.state.selectionElement) === null || _h === void 0 ? void 0 : _h.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isGridModeEnabled)(this),\n canvasBackgroundColor: this.state.viewBackgroundColor,\n embedsValidationStatus: this.embedsValidationStatus,\n elementsPendingErasure: this.elementsPendingErasure,\n pendingFlowchartNodes: this.flowChartCreator.pendingNodes,\n isHighlighterPenDrawing: isHighlighter //zsviczian\n\n }\n }), this.state.newElement && !isHighlighter && //zsviczian\n (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases_NewElementCanvas__WEBPACK_IMPORTED_MODULE_94__[\"default\"], {\n appState: this.state,\n scale: window.devicePixelRatio,\n rc: this.rc,\n elementsMap: elementsMap,\n allElementsMap: allElementsMap,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: false,\n canvasBackgroundColor: this.state.viewBackgroundColor,\n embedsValidationStatus: this.embedsValidationStatus,\n elementsPendingErasure: this.elementsPendingErasure,\n pendingFlowchartNodes: null,\n isHighlighterPenDrawing: isHighlighter //zsviczian\n\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_64__.InteractiveCanvas, {\n containerRef: this.excalidrawContainerRef,\n canvas: this.interactiveCanvas,\n elementsMap: elementsMap,\n visibleElements: visibleElements,\n allElementsMap: allElementsMap,\n selectedElements: selectedElements,\n sceneNonce: sceneNonce,\n selectionNonce: (_j = this.state.selectionElement) === null || _j === void 0 ? void 0 : _j.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n device: this.device,\n renderInteractiveSceneCallback: this.renderInteractiveSceneCallback,\n handleCanvasRef: this.handleInteractiveCanvasRef,\n onContextMenu: this.handleCanvasContextMenu,\n onPointerMove: this.handleCanvasPointerMove,\n onPointerUp: this.handleCanvasPointerUp,\n onPointerCancel: this.removePointer,\n onTouchMove: this.handleTouchMove,\n onPointerDown: this.handleCanvasPointerDown,\n onDoubleClick: this.handleCanvasDoubleClick\n }), this.state.userToFollow && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_FollowMode_FollowMode__WEBPACK_IMPORTED_MODULE_74__[\"default\"], {\n width: this.state.width,\n height: this.state.height,\n userToFollow: this.state.userToFollow,\n onDisconnect: this.maybeUnfollowRemoteUser\n }), this.renderFrameNames(), ((_k = this.state.activeEmbeddable) === null || _k === void 0 ? void 0 : _k.state) === \"active\" && ( //zsviczian\n (_m = (_l = this.props).renderEmbeddableMenu) === null || _m === void 0 ? void 0 : _m.call(_l, this.state))]\n })), this.renderEmbeddables()]\n }))\n }))\n }))\n }))\n }))\n }))\n }))\n }));\n }\n\n setPlugins(plugins) {\n Object.assign(this.plugins, plugins);\n }\n\n async onMagicFrameGenerate(magicFrame, source) {\n var _a;\n\n const generateDiagramToCode = (_a = this.plugins.diagramToCode) === null || _a === void 0 ? void 0 : _a.generate;\n\n if (!generateDiagramToCode) {\n this.setState({\n errorMessage: \"No diagram to code plugin found\"\n });\n return;\n }\n\n const magicFrameChildren = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsOverlappingFrame)(this.scene.getNonDeletedElements(), magicFrame).filter(el => !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isMagicFrameElement)(el));\n\n if (!magicFrameChildren.length) {\n if (source === \"button\") {\n this.setState({\n errorMessage: \"Cannot generate from an empty frame\"\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (no-children)\", \"d2c\");\n } else {\n this.setActiveTool({\n type: \"magicframe\"\n });\n }\n\n return;\n }\n\n const frameElement = this.insertIframeElement({\n sceneX: magicFrame.x + magicFrame.width + 30,\n sceneY: magicFrame.y,\n width: magicFrame.width,\n height: magicFrame.height\n });\n\n if (!frameElement) {\n return;\n }\n\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"pending\"\n }\n });\n this.setState({\n selectedElementIds: {\n [frameElement.id]: true\n }\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (start)\", \"d2c\");\n\n try {\n const {\n html\n } = await generateDiagramToCode({\n frame: magicFrame,\n children: magicFrameChildren\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (success)\", \"d2c\");\n\n if (!html.trim()) {\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"error\",\n code: \"ERR_OAI\",\n message: \"Nothing genereated :(\"\n }\n });\n return;\n }\n\n const parsedHtml = html.includes(\"<!DOCTYPE html>\") && html.includes(\"</html>\") ? html.slice(html.indexOf(\"<!DOCTYPE html>\"), html.indexOf(\"</html>\") + \"</html>\".length) : html;\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"done\",\n html: parsedHtml\n }\n });\n } catch (error) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (failed)\", \"d2c\");\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"error\",\n code: \"ERR_OAI\",\n message: error.message || \"Unknown error during generation\"\n }\n });\n }\n }\n\n onIframeSrcCopy(element) {\n var _a, _b;\n\n if (((_b = (_a = element.customData) === null || _a === void 0 ? void 0 : _a.generationData) === null || _b === void 0 ? void 0 : _b.status) === \"done\") {\n (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.copyTextToSystemClipboard)(element.customData.generationData.html);\n this.setToast({\n message: \"copied to clipboard\",\n closable: false,\n duration: 1500\n });\n }\n }\n\n clearImageShapeCache(filesMap) {\n const files = filesMap !== null && filesMap !== void 0 ? filesMap : this.files;\n this.scene.getNonDeletedElements().forEach(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && files[element.fileId]) {\n this.imageCache.delete(element.fileId);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element);\n }\n });\n }\n\n async componentDidMount() {\n var _a;\n\n this.unmounted = false;\n this.excalidrawContainerValue.container = this.excalidrawContainerRef.current;\n\n if (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_12__.ENV.TEST || \"development\" !== \"production\") {\n const setState = this.setState.bind(this);\n Object.defineProperties(window.h, {\n state: {\n configurable: true,\n get: () => {\n return this.state;\n }\n },\n setState: {\n configurable: true,\n value: (...args) => {\n return this.setState(...args);\n }\n },\n app: {\n configurable: true,\n value: this\n },\n history: {\n configurable: true,\n value: this.history\n },\n store: {\n configurable: true,\n value: this.store\n },\n fonts: {\n configurable: true,\n value: this.fonts\n }\n });\n }\n\n this.store.onStoreIncrementEmitter.on(increment => {\n this.history.record(increment.elementsChange, increment.appStateChange);\n });\n this.scene.onUpdate(this.triggerRender);\n this.addEventListeners();\n\n if (this.props.autoFocus && this.excalidrawContainerRef.current) {\n this.focusContainer();\n }\n\n if ( // bounding rects don't work in tests so updating\n // the state on init would result in making the test enviro run\n // in mobile breakpoint (0 width/height), making everything fail\n !(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isTestEnv)()) {\n this.refreshViewportBreakpoints();\n this.refreshEditorBreakpoints();\n }\n\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.supportsResizeObserver && this.excalidrawContainerRef.current) {\n this.resizeObserver = new ResizeObserver(() => {\n this.refreshEditorBreakpoints();\n this.updateDOMRect();\n });\n (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.observe(this.excalidrawContainerRef.current);\n }\n\n const searchParams = new URLSearchParams(window.location.search.slice(1));\n\n if (searchParams.has(\"web-share-target\")) {\n // Obtain a file that was shared via the Web Share Target API.\n this.restoreFileFromShare();\n } else {\n this.updateDOMRect(this.initializeScene);\n } // note that this check seems to always pass in localhost\n\n\n if ((0,_constants__WEBPACK_IMPORTED_MODULE_12__.isBrave)() && !(0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.isMeasureTextSupported)()) {\n this.setState({\n errorMessage: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_60__[\"default\"], {})\n });\n }\n }\n\n componentWillUnmount() {\n var _a, _b;\n\n (_a = window.launchQueue) === null || _a === void 0 ? void 0 : _a.setConsumer(() => {});\n this.renderer.destroy();\n this.scene.destroy();\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_29__[\"default\"]();\n this.fonts = new _fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts(this.scene);\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_65__.Renderer(this.scene);\n this.files = {};\n this.imageCache.clear();\n (_b = this.resizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();\n this.unmounted = true;\n this.removeEventListeners();\n this.library.destroy();\n this.laserTrails.stop();\n this.eraserTrail.stop();\n this.onChangeEmitter.clear();\n this.store.onStoreIncrementEmitter.clear();\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache.destroy();\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.destroy();\n clearTimeout(touchTimeout);\n _scene__WEBPACK_IMPORTED_MODULE_28__.isSomeElementSelected.clearCache();\n _groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements.clearCache();\n touchTimeout = 0;\n document.documentElement.style.overscrollBehaviorX = \"\";\n document.body.removeChild((0,_Tooltip__WEBPACK_IMPORTED_MODULE_93__.getTooltipDiv)()); //clearRenderCache(); //zsviczian\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.clearEraserCanvasCache)(); //zsviczian\n\n this.interactiveCanvas = null; //zsviczian\n\n this.iFrameRefs.clear(); //zsviczian\n //@ts-ignore\n\n this.iFrameRefs = null; //zsviczian\n\n this.embedsValidationStatus.clear(); //zsviczian\n //@ts-ignore\n\n this.embedsValidationStatus = null; //zsviczian\n\n this.initializedEmbeds.clear(); //zsviczian\n //@ts-ignore\n\n this.initializedEmbeds = null; //zsviczian\n\n this.elementsPendingErasure.clear(); //zsviczian\n //@ts-ignore\n\n this.elementsPendingErasure = null; //zsviczian\n\n this.lastPointerDownEvent = null; //zsviczian\n\n this.lastPointerUpEvent = null; //zsviczian\n\n this.lastPointerMoveEvent = null; //zsviczian\n //@ts-ignore\n\n this.actionManager.app = null; //zsviczian\n\n this.actionManager.actions = {}; //zsviczian\n\n this.history.clear(); //zsviczian\n\n this.store.clear(); //zsviczian\n //@ts-ignore\n\n this.store = null; //zsviczian\n //@ts-ignore\n\n this.library = null; //zsviczian\n //@ts-ignore\n\n this.canvas = null; //zsviczian\n //@ts-ignore\n\n this.rc = null; //zsviczian\n //@ts-ignore\n\n this.excalidrawContainerRef.current = undefined; //zsviczian\n\n this.nearestScrollableContainer = undefined; //zsviczian\n\n this.excalidrawContainerValue = {\n container: null,\n id: \"unknown\"\n }; //zsviczian\n //@ts-ignore\n // this.laserTrails.terminate(); //zsviczian\n // this.eraserTrail.terminate(); //zsviczian\n\n /*\n Object.keys(this).forEach((key) => {\n //@ts-ignore\n delete this[key];\n });*/\n }\n\n removeEventListeners() {\n this.onRemoveEventListenersEmitter.trigger();\n }\n\n addEventListeners() {\n // remove first as we can add event listeners multiple times\n this.removeEventListeners(); // -------------------------------------------------------------------------\n // view+edit mode listeners\n // -------------------------------------------------------------------------\n\n if (this.props.handleKeyboardGlobally) {\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, this.onKeyDown, false));\n }\n\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel, {\n passive: false\n }), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MESSAGE, this.onWindowMessage, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, this.removePointer), // #3553\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.COPY, this.onCopy), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, this.onKeyUp, {\n passive: true\n }), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, \"focus\", () => this.triggerRender(true), {\n passive: true\n }), //zsviczian\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, this.updateCurrentCursorPosition), // rerender text elements on font load to fix #637 && #1553\n // zsviczian In Obsidian this is not needed as I manage font load separately\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document.fonts, \"loadingdone\", event => {\n const loadedFontFaces = event.fontfaces;\n this.fonts.onLoaded(loadedFontFaces);\n }), // Safari-only desktop pinch zoom\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_START, this.onGestureStart, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_CHANGE, this.onGestureChange, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_END, this.onGestureEnd, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.FOCUS, () => {\n this.maybeCleanupAfterMissingPointerUp(null); // browsers (chrome?) tend to free up memory a lot, which results\n // in canvas context being cleared. Thus re-render on focus.\n\n this.triggerRender(true);\n }));\n\n if (this.state.viewModeEnabled) {\n return;\n } // -------------------------------------------------------------------------\n // edit-mode listeners only\n // -------------------------------------------------------------------------\n\n\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.FULLSCREENCHANGE, this.onFullscreenChange), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, this.pasteFromClipboard), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.CUT, this.onCut), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.RESIZE, this.onResize, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.UNLOAD, this.onUnload, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, this.onBlur, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DRAG_OVER, this.disableEvent, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DROP, this.disableEvent, false));\n\n if (this.props.detectScroll) {\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)((0,_utils__WEBPACK_IMPORTED_MODULE_34__.getNearestScrollableContainer)(this.excalidrawContainerRef.current), _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.SCROLL, this.onScroll));\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n var _a, _b, _c, _d, _e, _f;\n\n this.updateEmbeddables();\n const elements = this.scene.getElementsIncludingDeleted();\n const elementsMap = this.scene.getElementsMapIncludingDeleted();\n const nonDeletedElementsMap = this.scene.getNonDeletedElementsMap();\n\n if (!this.state.showWelcomeScreen && !elements.length) {\n this.setState({\n showWelcomeScreen: true\n });\n }\n\n if (prevProps.UIOptions.dockedSidebarBreakpoint !== this.props.UIOptions.dockedSidebarBreakpoint) {\n this.refreshEditorBreakpoints();\n }\n\n const hasFollowedPersonLeft = prevState.userToFollow && !this.state.collaborators.has(prevState.userToFollow.socketId);\n\n if (hasFollowedPersonLeft) {\n this.maybeUnfollowRemoteUser();\n }\n\n if (prevState.zoom.value !== this.state.zoom.value || prevState.scrollX !== this.state.scrollX || prevState.scrollY !== this.state.scrollY) {\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onScrollChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.scrollX, this.state.scrollY, this.state.zoom);\n this.onScrollChangeEmitter.trigger(this.state.scrollX, this.state.scrollY, this.state.zoom);\n }\n\n if (prevState.userToFollow !== this.state.userToFollow) {\n if (prevState.userToFollow) {\n this.onUserFollowEmitter.trigger({\n userToFollow: prevState.userToFollow,\n action: \"UNFOLLOW\"\n });\n }\n\n if (this.state.userToFollow) {\n this.onUserFollowEmitter.trigger({\n userToFollow: this.state.userToFollow,\n action: \"FOLLOW\"\n });\n }\n } // zsviczian\n\n\n if (this.state.highlightSearchResult && !this.debounceClearHighlightSearchResults && prevState.selectedElementIds !== this.state.selectedElementIds) {\n this.setState({\n highlightSearchResult: false\n });\n }\n\n if (Object.keys(this.state.selectedElementIds).length && (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n\n if (this.state.activeTool.type === \"eraser\" && prevState.theme !== this.state.theme) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setEraserCursor)(this.interactiveCanvas, this.state.theme);\n } // Hide hyperlink popup if shown when element type is not selection\n\n\n if (prevState.activeTool.type === \"selection\" && this.state.activeTool.type !== \"selection\" && this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: false\n });\n }\n\n if (prevProps.langCode !== this.props.langCode) {\n this.updateLanguage();\n }\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(prevState) && !(0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.eraserTrail.endPath();\n }\n\n if (prevProps.viewModeEnabled !== this.props.viewModeEnabled) {\n this.setState({\n viewModeEnabled: !!this.props.viewModeEnabled\n });\n }\n\n if (prevState.viewModeEnabled !== this.state.viewModeEnabled) {\n this.addEventListeners();\n this.deselectElements();\n }\n\n if (prevProps.zenModeEnabled !== this.props.zenModeEnabled) {\n this.setState({\n zenModeEnabled: !!this.props.zenModeEnabled\n });\n }\n\n if (prevProps.theme !== this.props.theme && this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.classList.toggle(\"theme--dark\", this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.DARK);\n\n if (this.state.editingLinearElement && !this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {\n // defer so that the storeAction flag isn't reset via current update\n setTimeout(() => {\n // execute only if the condition still holds when the deferred callback\n // executes (it can be scheduled multiple times depending on how\n // many times the component renders)\n this.state.editingLinearElement && this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } // failsafe in case the state is being updated in incorrect order resulting\n // in the editingTextElement being now a deleted element\n\n\n if ((_d = this.state.editingTextElement) === null || _d === void 0 ? void 0 : _d.isDeleted) {\n this.setState({\n editingTextElement: null\n });\n }\n\n if (this.state.selectedLinearElement && !this.state.selectedElementIds[this.state.selectedLinearElement.elementId]) {\n // To make sure `selectedLinearElement` is in sync with `selectedElementIds`, however this shouldn't be needed once\n // we have a single API to update `selectedElementIds`\n this.setState({\n selectedLinearElement: null\n });\n }\n\n const {\n multiElement\n } = prevState;\n\n if (prevState.activeTool !== this.state.activeTool && multiElement != null && (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(multiElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(multiElement, this.state, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)(_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements());\n }\n\n this.store.commit(elementsMap, this.state); // Do not notify consumers if we're still loading the scene. Among other\n // potential issues, this fixes a case where the tab isn't focused during\n // init, which would trigger onChange with empty elements, which would then\n // override whatever is in localStorage currently.\n\n if (!this.state.isLoading) {\n (_f = (_e = this.props).onChange) === null || _f === void 0 ? void 0 : _f.call(_e, elements, this.state, this.files);\n this.onChangeEmitter.trigger(elements, this.state, this.files);\n }\n }\n\n static resetTapTwice() {\n didTapTwice = false;\n } // TODO rewrite this to paste both text & images at the same time if\n // pasted data contains both\n\n\n async addElementsFromMixedContentPaste(mixedContent, {\n isPlainPaste,\n sceneX,\n sceneY\n }) {\n if (!isPlainPaste && mixedContent.some(node => node.type === \"imageUrl\") && this.isToolSupported(\"image\")) {\n const imageURLs = mixedContent.filter(node => node.type === \"imageUrl\").map(node => node.value);\n const responses = await Promise.all(imageURLs.map(async url => {\n try {\n return {\n file: await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.ImageURLToFile)(url)\n };\n } catch (error) {\n let errorMessage = error.message;\n\n if (error.cause === \"FETCH_ERROR\") {\n errorMessage = (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.failedToFetchImage\");\n } else if (error.cause === \"UNSUPPORTED\") {\n errorMessage = (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\");\n }\n\n return {\n errorMessage\n };\n }\n }));\n let y = sceneY;\n let firstImageYOffsetDone = false;\n const nextSelectedIds = {};\n\n for (const response of responses) {\n if (response.file) {\n const imageElement = this.createImageElement({\n sceneX,\n sceneY: y\n });\n const initializedImageElement = await this.insertImageElement(imageElement, response.file);\n\n if (initializedImageElement) {\n // vertically center first image in the batch\n if (!firstImageYOffsetDone) {\n firstImageYOffsetDone = true;\n y -= initializedImageElement.height / 2;\n } // hack to reset the `y` coord because we vertically center during\n // insertImageElement\n\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(initializedImageElement, {\n y\n }, false);\n y = imageElement.y + imageElement.height + 25;\n nextSelectedIds[imageElement.id] = true;\n }\n }\n }\n\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedIds, this.state)\n });\n const error = responses.find(response => !!response.errorMessage);\n\n if (error && error.errorMessage) {\n this.setState({\n errorMessage: error.errorMessage\n });\n }\n } else {\n const textNodes = mixedContent.filter(node => node.type === \"text\");\n\n if (textNodes.length) {\n this.addTextFromPaste(textNodes.map(node => node.value).join(\"\\n\\n\"), isPlainPaste);\n }\n }\n }\n\n addTextFromPaste(text, isPlainPaste = false) {\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state);\n const textElementProps = {\n x,\n y,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roundness: null,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text,\n rawText: text,\n fontSize: (0,_actions_actionProperties__WEBPACK_IMPORTED_MODULE_75__.getFontSize)(this.state.currentItemFontSize, this.state.zoom.value),\n fontFamily: this.state.currentItemFontFamily,\n textAlign: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_TEXT_ALIGN,\n verticalAlign: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n locked: false\n };\n const fontString = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.getFontString)({\n fontSize: textElementProps.fontSize,\n fontFamily: textElementProps.fontFamily\n });\n const lineHeight = (0,_fonts__WEBPACK_IMPORTED_MODULE_49__.getLineHeight)(textElementProps.fontFamily);\n const [x1,, x2] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_91__.getVisibleSceneBounds)(this.state); // long texts should not go beyond 800 pixels in width nor should it go below 200 px\n\n const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200);\n const LINE_GAP = 10;\n let currentY = y;\n const lines = isPlainPaste ? [text] : text.split(\"\\n\");\n const textElements = lines.reduce((acc, line, idx) => {\n var _a;\n\n const originalText = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.normalizeText)(line).trim();\n\n if (originalText.length) {\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x,\n y: currentY\n });\n let metrics = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.measureText)(originalText, fontString, lineHeight);\n const isTextUnwrapped = metrics.width > maxTextWidth;\n const text = isTextUnwrapped ? (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.wrapText)(originalText, fontString, maxTextWidth) : originalText;\n metrics = isTextUnwrapped ? (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.measureText)(text, fontString, lineHeight) : metrics;\n const startX = x - metrics.width / 2;\n const startY = currentY - metrics.height / 2;\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)(Object.assign(Object.assign({}, textElementProps), {\n x: startX,\n y: startY,\n text,\n rawText: originalText,\n //zsviczian\n originalText,\n lineHeight,\n autoResize: !isTextUnwrapped,\n frameId: topLayerFrame ? topLayerFrame.id : null\n }));\n acc.push(element);\n currentY += element.height + LINE_GAP;\n } else {\n const prevLine = (_a = lines[idx - 1]) === null || _a === void 0 ? void 0 : _a.trim(); // add paragraph only if previous line was not empty, IOW don't add\n // more than one empty line\n\n if (prevLine) {\n currentY += (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getLineHeightInPx)(textElementProps.fontSize, lineHeight) + LINE_GAP;\n }\n }\n\n return acc;\n }, []);\n\n if (textElements.length === 0) {\n return;\n }\n\n this.scene.insertElements(textElements);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.fromEntries(textElements.map(el => [el.id, true])), this.state)\n });\n\n if (!isPlainPaste && textElements.length > 1 && PLAIN_PASTE_TOAST_SHOWN === false && !this.device.editor.isMobile) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"toast.pasteAsSingleElement\", {\n shortcut: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.getShortcutKey)(\"CtrlOrCmd+Shift+V\")\n }),\n duration: 5000\n });\n PLAIN_PASTE_TOAST_SHOWN = true;\n }\n\n this.store.shouldCaptureIncrement();\n }\n\n handleTextWysiwyg(element, {\n isExistingElement = false\n }) {\n const elementsMap = this.scene.getElementsMapIncludingDeleted();\n\n const updateElement = (nextOriginalText, isDeleted, rawText, //zsviczian\n link) => {\n this.scene.replaceAllElements([// Not sure why we include deleted elements as well hence using deleted elements map\n ...this.scene.getElementsIncludingDeleted().map(_element => {\n if (_element.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(_element)) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(_element, Object.assign({\n originalText: nextOriginalText,\n rawText: rawText !== null && rawText !== void 0 ? rawText : nextOriginalText,\n //zsviczian\n link,\n isDeleted: isDeleted !== null && isDeleted !== void 0 ? isDeleted : _element.isDeleted\n }, (0,_element__WEBPACK_IMPORTED_MODULE_16__.refreshTextDimensions)(_element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(_element, elementsMap), elementsMap, nextOriginalText)));\n }\n\n return _element;\n })]);\n }; //zsviczian\n\n\n if (isExistingElement && this.props.onBeforeTextEdit) {\n const text = this.props.onBeforeTextEdit(element);\n\n if (text && text !== element.originalText) {\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted().map(_element => {\n if (_element.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(_element)) {\n //changing the value of element so this gets edited by textWysiwyg\n element = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(_element, Object.assign({\n originalText: text,\n rawText: text,\n isDeleted: false\n }, (0,_element__WEBPACK_IMPORTED_MODULE_16__.refreshTextDimensions)(_element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(_element, elementsMap), elementsMap, text)));\n return element;\n }\n\n return _element;\n })]);\n }\n }\n\n (0,_element_textWysiwyg__WEBPACK_IMPORTED_MODULE_84__.textWysiwyg)({\n id: element.id,\n canvas: this.canvas,\n getViewportCoords: (x, y) => {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: x,\n sceneY: y\n }, this.state);\n return [viewportX - this.state.offsetLeft, viewportY - this.state.offsetTop];\n },\n onChange: (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(nextOriginalText => {\n updateElement(nextOriginalText, false);\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element, this.scene.getNonDeletedElementsMap());\n }\n }),\n onSubmit: (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(({\n viaKeyboard,\n nextOriginalText\n }) => {\n var _a;\n\n const isDeleted = !nextOriginalText.trim(); //zsviczian insert start\n\n const rawText = nextOriginalText; //should this be originalText??\n\n let link = undefined;\n\n if (this.props.onBeforeTextSubmit) {\n const _element = this.scene.getElementsIncludingDeleted().find(el => el.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(el));\n\n if (_element) {\n const dismensionsData = (0,_element__WEBPACK_IMPORTED_MODULE_16__.refreshTextDimensions)(_element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(_element, elementsMap), elementsMap, nextOriginalText);\n const {\n updatedNextOriginalText,\n nextLink\n } = this.props.onBeforeTextSubmit(element, (_a = dismensionsData === null || dismensionsData === void 0 ? void 0 : dismensionsData.text) !== null && _a !== void 0 ? _a : nextOriginalText, //should never be undefined\n nextOriginalText, isDeleted);\n nextOriginalText = updatedNextOriginalText !== null && updatedNextOriginalText !== void 0 ? updatedNextOriginalText : nextOriginalText;\n link = nextLink;\n }\n } //zsviczian insert end\n\n\n updateElement(nextOriginalText, isDeleted, rawText, link); //zsviczian (added rawText, link, text)\n // select the created text element only if submitting via keyboard\n // (when submitting via click it should act as signal to deselect)\n\n if (!isDeleted && viaKeyboard) {\n const elementIdToSelect = element.containerId ? element.containerId : element.id; // needed to ensure state is updated before \"finalize\" action\n // that's invoked on keyboard-submit as well\n // TODO either move this into finalize as well, or handle all state\n // updates in one place, skipping finalize action\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [elementIdToSelect]: true\n }), prevState)\n }));\n });\n }\n\n if (isDeleted) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDeletion)(this.scene.getNonDeletedElements(), [element]);\n }\n\n if (!isDeleted || isExistingElement) {\n this.store.shouldCaptureIncrement();\n }\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n newElement: null,\n editingTextElement: null\n });\n });\n\n if (this.state.activeTool.locked) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n this.focusContainer();\n }),\n element,\n excalidrawContainer: this.excalidrawContainerRef.current,\n app: this,\n // when text is selected, it's hard (at least on iOS) to re-position the\n // caret (i.e. deselect). There's not much use for always selecting\n // the text on edit anyway (and users can select-all from contextmenu\n // if needed)\n autoSelect: !this.device.isTouchScreen\n }); // deselect all other elements when inserting text\n\n this.deselectElements(); // do an initial update to re-initialize element position since we were\n // modifying element's x/y for sake of editor (case: syncing to remote)\n\n updateElement(element.originalText, false);\n }\n\n deselectElements() {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n getTextElementAtPosition(x, y) {\n const element = this.getElementAtPosition(x, y, {\n includeBoundTextElement: true\n });\n\n if (element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && !element.isDeleted) {\n return element;\n }\n\n return null;\n }\n\n getElementAtPosition(x, y, opts) {\n const allHitElements = this.getElementsAtPosition(x, y, opts === null || opts === void 0 ? void 0 : opts.includeBoundTextElement, opts === null || opts === void 0 ? void 0 : opts.includeLockedElements);\n\n if (allHitElements.length > 1) {\n if (opts === null || opts === void 0 ? void 0 : opts.preferSelected) {\n for (let index = allHitElements.length - 1; index > -1; index--) {\n if (this.state.selectedElementIds[allHitElements[index].id]) {\n return allHitElements[index];\n }\n }\n }\n\n const elementWithHighestZIndex = allHitElements[allHitElements.length - 1]; // If we're hitting element with highest z-index only on its bounding box\n // while also hitting other element figure, the latter should be considered.\n\n return (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x,\n y,\n element: elementWithHighestZIndex,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(elementWithHighestZIndex, this.scene.getNonDeletedElementsMap()),\n // when overlapping, we would like to be more precise\n // this also avoids the need to update past tests\n threshold: this.getElementHitThreshold() / 2,\n frameNameBound: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(elementWithHighestZIndex) ? this.frameNameBoundsCache.get(elementWithHighestZIndex) : null\n }) ? elementWithHighestZIndex : allHitElements[allHitElements.length - 2];\n }\n\n if (allHitElements.length === 1) {\n return allHitElements[0];\n }\n\n return null;\n }\n\n getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {\n const iframeLikes = [];\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const elements = (includeBoundTextElement && includeLockedElements ? this.scene.getNonDeletedElements() : this.scene.getNonDeletedElements().filter(element => (includeLockedElements || !element.locked) && (includeBoundTextElement || !((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && element.containerId)))).filter(el => this.hitElement(x, y, el)).filter(element => {\n // hitting a frame's element from outside the frame is not considered a hit\n const containingFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(element, elementsMap);\n return containingFrame && this.state.frameRendering.enabled && this.state.frameRendering.clip ? (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)({\n x,\n y\n }, containingFrame, elementsMap) : true;\n }).filter(el => {\n // The parameter elements comes ordered from lower z-index to higher.\n // We want to preserve that order on the returned array.\n // Exception being embeddables which should be on top of everything else in\n // terms of hit testing.\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el)) {\n iframeLikes.push(el);\n return false;\n }\n\n return true;\n }).concat(iframeLikes);\n return elements;\n }\n\n getElementHitThreshold() {\n return _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_COLLISION_THRESHOLD / this.state.zoom.value;\n }\n\n hitElement(x, y, element, considerBoundingBox = true) {\n // if the element is selected, then hit test is done against its bounding box\n if (considerBoundingBox && this.state.selectedElementIds[element.id] && (0,_element_transformHandles__WEBPACK_IMPORTED_MODULE_47__.shouldShowBoundingBox)([element], this.state)) {\n const selectionShape = (0,_utils_geometry_shape__WEBPACK_IMPORTED_MODULE_32__.getSelectionBoxShape)(element, this.scene.getNonDeletedElementsMap(), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(element) ? 0 : this.getElementHitThreshold());\n return (0,_utils_collision__WEBPACK_IMPORTED_MODULE_33__.isPointInShape)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x, y), selectionShape);\n } // take bound text element into consideration for hit collision as well\n\n\n const hitBoundTextOfElement = (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementBoundText)(x, y, (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getBoundTextShape)(element, this.scene.getNonDeletedElementsMap()));\n\n if (hitBoundTextOfElement) {\n return true;\n }\n\n return (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x,\n y,\n element,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(element, this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold(),\n frameNameBound: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element) ? this.frameNameBoundsCache.get(element) : null\n });\n }\n\n getTextBindableContainerAtPosition(x, y) {\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n return (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isTextBindableContainer)(selectedElements[0], false) ? selectedElements[0] : null;\n }\n\n let hitElement = null; // We need to do hit testing from front (end of the array) to back (beginning of the array)\n\n for (let index = elements.length - 1; index >= 0; --index) {\n if (elements[index].isDeleted) {\n continue;\n }\n\n const [x1, y1, x2, y2] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementAbsoluteCoords)(elements[index], this.scene.getNonDeletedElementsMap());\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(elements[index]) && (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x,\n y,\n element: elements[index],\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(elements[index], this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold()\n })) {\n hitElement = elements[index];\n break;\n } else if (x1 < x && x < x2 && y1 < y && y < y2) {\n hitElement = elements[index];\n break;\n }\n }\n\n return (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isTextBindableContainer)(hitElement, false) ? hitElement : null;\n }\n\n handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const element = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getElement(linearElementEditor.elementId, elementsMap);\n\n if (!element) {\n return;\n }\n\n if (this.state.selectedLinearElement) {\n let hoverPointIndex = -1;\n let segmentMidPointHoveredCoords = null;\n\n if ((0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x: scenePointerX,\n y: scenePointerY,\n element,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(element, this.scene.getNonDeletedElementsMap())\n })) {\n hoverPointIndex = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);\n segmentMidPointHoveredCoords = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, {\n x: scenePointerX,\n y: scenePointerY\n }, this.state, this.scene.getNonDeletedElementsMap());\n\n if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else if (this.hitElement(scenePointerX, scenePointerY, element)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n } else if (this.hitElement(scenePointerX, scenePointerY, element)) {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(element) || !(element.startBinding || element.endBinding)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n }\n\n if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n hoverPointIndex\n })\n });\n }\n\n if (!_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.arePointsEqual(this.state.selectedLinearElement.segmentMidPointHoveredCoords, segmentMidPointHoveredCoords)) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n segmentMidPointHoveredCoords\n })\n });\n }\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n\n updateGestureOnPointerDown(event) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n\n if (gesture.pointers.size === 2) {\n gesture.lastCenter = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n gesture.initialScale = this.state.zoom.value;\n gesture.initialDistance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n }\n }\n\n initialPointerDownState(event) {\n const origin = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedElements = this.scene.getSelectedElements(this.state);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n const isElbowArrowOnly = selectedElements.findIndex(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow) === 0;\n return {\n origin,\n withCmdOrCtrl: event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD],\n originInGrid: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(origin.x, origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] || isElbowArrowOnly ? null : this.getEffectiveGridSize())),\n scrollbars: (0,_scene_scrollbars__WEBPACK_IMPORTED_MODULE_85__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop),\n // we need to duplicate because we'll be updating this state\n lastCoords: Object.assign({}, origin),\n originalElements: this.scene.getNonDeletedElements().reduce((acc, element) => {\n acc.set(element.id, (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.deepCopyElement)(element));\n return acc;\n }, new Map()),\n resize: {\n handleType: false,\n isResizing: false,\n offset: {\n x: 0,\n y: 0\n },\n arrowDirection: \"origin\",\n center: {\n x: (maxX + minX) / 2,\n y: (maxY + minY) / 2\n }\n },\n hit: {\n element: null,\n allHitElements: [],\n wasAddedToSelection: false,\n hasBeenDuplicated: false,\n hasHitCommonBoundingBoxOfSelectedElements: this.isHittingCommonBoundingBoxOfSelectedElements(origin, selectedElements)\n },\n drag: {\n hasOccurred: false,\n offset: null\n },\n eventListeners: {\n onMove: null,\n onUp: null,\n onKeyUp: null,\n onKeyDown: null\n },\n boxSelection: {\n hasOccurred: false\n }\n };\n } // Returns whether the event is a dragging a scrollbar\n\n\n handleDraggingScrollBar(event, pointerDownState) {\n if (!(pointerDownState.scrollbars.isOverEither && !this.state.multiElement)) {\n return false;\n }\n\n isDraggingScrollBar = true;\n pointerDownState.lastCoords.x = event.clientX;\n pointerDownState.lastCoords.y = event.clientY;\n const onPointerMove = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdatesThrottled)(event => {\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n this.handlePointerMoveOverScrollbars(event, pointerDownState);\n });\n const onPointerUp = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(() => {\n lastPointerUp = null;\n isDraggingScrollBar = false;\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n onPointerMove.flush();\n });\n lastPointerUp = onPointerUp;\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n return true;\n }\n\n isASelectedElement(hitElement) {\n return hitElement != null && this.state.selectedElementIds[hitElement.id];\n }\n\n isHittingCommonBoundingBoxOfSelectedElements(point, selectedElements) {\n if (selectedElements.length < 2) {\n return false;\n } // How many pixels off the shape boundary we still consider a hit\n\n\n const threshold = this.getElementHitThreshold();\n const [x1, y1, x2, y2] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n return point.x > x1 - threshold && point.x < x2 + threshold && point.y > y1 - threshold && point.y < y2 + threshold;\n }\n\n getCurrentItemRoundness(elementType) {\n return this.state.currentItemRoundness === \"round\" ? {\n type: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isUsingAdaptiveRadius)(elementType) ? _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.ADAPTIVE_RADIUS : _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null;\n }\n\n maybeCacheReferenceSnapPoints(event, selectedElements, recomputeAnyways = false) {\n if ((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isSnappingEnabled)({\n event,\n app: this,\n selectedElements\n }) && (recomputeAnyways || !_snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.getReferenceSnapPoints())) {\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setReferenceSnapPoints((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getReferenceSnapPoints)(this.scene.getNonDeletedElements(), selectedElements, this.state, this.scene.getNonDeletedElementsMap()));\n }\n }\n\n maybeCacheVisibleGaps(event, selectedElements, recomputeAnyways = false) {\n if ((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isSnappingEnabled)({\n event,\n app: this,\n selectedElements\n }) && (recomputeAnyways || !_snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.getVisibleGaps())) {\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setVisibleGaps((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getVisibleGaps)(this.scene.getNonDeletedElements(), selectedElements, this.state, this.scene.getNonDeletedElementsMap()));\n }\n }\n\n onKeyDownFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onKeyUpFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n // Prevents focus from escaping excalidraw tab\n event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ALT && event.preventDefault();\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onPointerMoveFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdatesThrottled)(event => {\n var _a, _b, _c, _d; //To avoid pointerMove canceling the selection of locked elements on mobile //zsviczian\n\n\n if (Boolean(this.state.contextMenu)) {\n return;\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const lastPointerCoords = (_a = this.lastPointerMoveCoords) !== null && _a !== void 0 ? _a : pointerDownState.origin;\n this.lastPointerMoveCoords = pointerCoords; // We need to initialize dragOffsetXY only after we've updated\n // `state.selectedElementIds` on pointerDown. Doing it here in pointerMove\n // event handler should hopefully ensure we're already working with\n // the updated state.\n\n if (pointerDownState.drag.offset === null) {\n pointerDownState.drag.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getDragOffsetXY)(this.scene.getSelectedElements(this.state), pointerDownState.origin.x, pointerDownState.origin.y));\n }\n\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n if (this.handlePointerMoveOverScrollbars(event, pointerDownState)) {\n return;\n }\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.handleEraser(event, pointerDownState, pointerCoords);\n return;\n }\n\n if (this.state.activeTool.type === \"laser\") {\n this.laserTrails.addPointToPath(pointerCoords.x, pointerCoords.y);\n }\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize()); // for arrows/lines, don't start dragging until a given threshold\n // to ensure we don't create a 2-point arrow by mistake when\n // user clicks mouse in a way that it moves a tiny bit (thus\n // triggering pointermove)\n\n if (!pointerDownState.drag.hasOccurred && (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\")) {\n if ((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerCoords.x, pointerCoords.y), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerDownState.origin.x, pointerDownState.origin.y)) < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD) {\n return;\n }\n }\n\n if (pointerDownState.resize.isResizing) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n\n if (this.maybeHandleCrop(pointerDownState, event)) {\n return true;\n }\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return true;\n }\n }\n\n const elementsMap = this.scene.getNonDeletedElementsMap();\n\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n\n if (_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.shouldAddMidpoint(this.state.selectedLinearElement, pointerCoords, this.state, elementsMap)) {\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.addMidpoint(this.state.selectedLinearElement, pointerCoords, this, !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD], elementsMap);\n\n if (!ret) {\n return;\n } // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n if (this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n });\n return;\n } else if (linearElementEditor.pointerDownState.segmentMidpoint.value !== null && !linearElementEditor.pointerDownState.segmentMidpoint.added) {\n return;\n }\n\n const didDrag = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointDragging(event, this, pointerCoords.x, pointerCoords.y, (element, pointsSceneCoords) => {\n this.maybeSuggestBindingsForLinearElementAtCoords(element, pointsSceneCoords);\n }, linearElementEditor, this.scene);\n\n if (didDrag) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n pointerDownState.drag.hasOccurred = true;\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n isDragging: true\n })\n });\n }\n\n if (!this.state.selectedLinearElement.isDragging) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n isDragging: true\n })\n });\n }\n\n return;\n }\n }\n\n const hasHitASelectedElement = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n const isSelectingPointsInLineEditor = this.state.editingLinearElement && event.shiftKey && this.state.editingLinearElement.elementId === ((_b = pointerDownState.hit.element) === null || _b === void 0 ? void 0 : _b.id);\n\n if ((hasHitASelectedElement || pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) && !isSelectingPointsInLineEditor) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.every(element => element.locked)) {\n return;\n }\n\n const selectedElementsHasAFrame = selectedElements.find(e => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(e));\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(pointerCoords);\n this.setState({\n frameToHighlight: topLayerFrame && !selectedElementsHasAFrame ? topLayerFrame : null\n }); // Marking that click was used for dragging to check\n // if elements should be deselected on pointerup\n\n pointerDownState.drag.hasOccurred = true; // prevent dragging even if we're no longer holding cmd/ctrl otherwise\n // it would have weird results (stuff jumping all over the screen)\n // Checking for editingTextElement to avoid jump while editing on mobile #6503\n\n if (selectedElements.length > 0 && !pointerDownState.withCmdOrCtrl && !this.state.editingTextElement && ((_c = this.state.activeEmbeddable) === null || _c === void 0 ? void 0 : _c.state) !== \"active\") {\n const dragOffset = {\n x: pointerCoords.x - pointerDownState.origin.x,\n y: pointerCoords.y - pointerDownState.origin.y\n };\n const originalElements = [...pointerDownState.originalElements.values()]; // We only drag in one direction if shift is pressed\n\n const lockDirection = event.shiftKey;\n\n if (lockDirection) {\n const distanceX = Math.abs(dragOffset.x);\n const distanceY = Math.abs(dragOffset.y);\n const lockX = lockDirection && distanceX < distanceY;\n const lockY = lockDirection && distanceX > distanceY;\n\n if (lockX) {\n dragOffset.x = 0;\n }\n\n if (lockY) {\n dragOffset.y = 0;\n }\n } // #region move crop region\n\n\n if (this.state.croppingElementId) {\n const croppingElement = this.scene.getNonDeletedElementsMap().get(this.state.croppingElementId);\n\n if (croppingElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(croppingElement) && croppingElement.crop !== null && pointerDownState.hit.element === croppingElement) {\n const crop = croppingElement.crop;\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(croppingElement) && ((_d = this.imageCache.get(croppingElement.fileId)) === null || _d === void 0 ? void 0 : _d.image);\n\n if (image && !(image instanceof Promise)) {\n const instantDragOffset = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorScale)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vector)(pointerCoords.x - lastPointerCoords.x, pointerCoords.y - lastPointerCoords.y), Math.max(this.state.zoom.value, 2));\n const [x1, y1, x2, y2, cx, cy] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementAbsoluteCoords)(croppingElement, elementsMap);\n const topLeft = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorFromPoint)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x1, y1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(cx, cy), croppingElement.angle));\n const topRight = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorFromPoint)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x2, y1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(cx, cy), croppingElement.angle));\n const bottomLeft = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorFromPoint)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x1, y2), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(cx, cy), croppingElement.angle));\n const topEdge = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorNormalize)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorSubtract)(topRight, topLeft));\n const leftEdge = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorNormalize)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorSubtract)(bottomLeft, topLeft)); // project instantDrafOffset onto leftEdge and topEdge to decompose\n\n const offsetVector = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vector)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorDot)(instantDragOffset, topEdge), (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorDot)(instantDragOffset, leftEdge));\n const nextCrop = Object.assign(Object.assign({}, crop), {\n x: (0,_math__WEBPACK_IMPORTED_MODULE_98__.clamp)(crop.x - offsetVector[0] * Math.sign(croppingElement.scale[0]), 0, image.naturalWidth - crop.width),\n y: (0,_math__WEBPACK_IMPORTED_MODULE_98__.clamp)(crop.y - offsetVector[1] * Math.sign(croppingElement.scale[1]), 0, image.naturalHeight - crop.height)\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(croppingElement, {\n crop: nextCrop\n });\n return;\n }\n }\n } // Snap cache *must* be synchronously popuplated before initial drag,\n // otherwise the first drag even will not snap, causing a jump before\n // it snaps to its position if previously snapped already.\n\n\n this.maybeCacheVisibleGaps(event, selectedElements);\n this.maybeCacheReferenceSnapPoints(event, selectedElements);\n const {\n snapOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.snapDraggedElements)(originalElements, dragOffset, this, event, this.scene.getNonDeletedElementsMap());\n this.setState({\n snapLines\n }); // when we're editing the name of a frame, we want the user to be\n // able to select and interact with the text input\n\n !this.state.editingFrame && (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragSelectedElements)(pointerDownState, selectedElements, dragOffset, this.scene, snapOffset, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n this.setState({\n selectedElementsAreBeingDragged: true,\n // element is being dragged and selectionElement that was created on pointer down\n // should be removed\n selectionElement: null\n });\n\n if (selectedElements.length !== 1 || !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0])) {\n this.setState({\n suggestedBindings: (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getSuggestedBindingsForArrows)(selectedElements, this.scene.getNonDeletedElementsMap())\n });\n } // We duplicate the selected element if alt is pressed on pointer move\n\n\n if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {\n // Move the currently selected elements to the top of the z index stack, and\n // put the duplicates where the selected elements used to be.\n // (the origin point where the dragging started)\n pointerDownState.hit.hasBeenDuplicated = true;\n const nextElements = [];\n const elementsToAppend = [];\n const groupIdMap = new Map();\n const oldIdToDuplicatedId = new Map();\n const hitElement = pointerDownState.hit.element;\n const selectedElementIds = new Set(this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n }).map(element => element.id));\n const elements = this.scene.getElementsIncludingDeleted();\n\n for (const element of elements) {\n if (selectedElementIds.has(element.id) || // case: the state.selectedElementIds might not have been\n // updated yet by the time this mousemove event is fired\n element.id === (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && pointerDownState.hit.wasAddedToSelection) {\n const duplicatedElement = (0,_element__WEBPACK_IMPORTED_MODULE_16__.duplicateElement)(this.state.editingGroupId, groupIdMap, element);\n const origElement = pointerDownState.originalElements.get(element.id);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(duplicatedElement, {\n x: origElement.x,\n y: origElement.y\n }); // put duplicated element to pointerDownState.originalElements\n // so that we can snap to the duplicated element without releasing\n\n pointerDownState.originalElements.set(duplicatedElement.id, duplicatedElement);\n nextElements.push(duplicatedElement);\n elementsToAppend.push(element);\n oldIdToDuplicatedId.set(element.id, duplicatedElement.id);\n } else {\n nextElements.push(element);\n }\n }\n\n const nextSceneElements = [...nextElements, ...elementsToAppend];\n (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncMovedIndices)(nextSceneElements, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(elementsToAppend));\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.bindTextToShapeAfterDuplication)(nextElements, elementsToAppend, oldIdToDuplicatedId);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, \"duplicatesServeAsOld\");\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.bindElementsToFramesAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);\n this.scene.replaceAllElements(nextSceneElements);\n this.maybeCacheVisibleGaps(event, selectedElements, true);\n this.maybeCacheReferenceSnapPoints(event, selectedElements, true);\n }\n\n return;\n }\n }\n\n if (this.state.selectionElement) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n this.maybeDragNewGenericElement(pointerDownState, event);\n } else {\n // It is very important to read this.state within each move event,\n // otherwise we would read a stale one!\n const newElement = this.state.newElement;\n\n if (!newElement) {\n return;\n }\n\n if (newElement.type === \"freedraw\") {\n const points = newElement.points;\n const dx = pointerCoords.x - newElement.x;\n const dy = pointerCoords.y - newElement.y;\n const lastPoint = points.length > 0 && points[points.length - 1];\n const discardPoint = lastPoint && lastPoint[0] === dx && lastPoint[1] === dy;\n\n if (!discardPoint) {\n const strokeOptions = this.state.currentStrokeOptions; //zsviczian\n\n const pressures = newElement.simulatePressure ? newElement.pressures : [//zsviczian\n ...newElement.pressures, (strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.constantPressure) ? 1 : event.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)],\n pressures\n }, false);\n this.setState({\n newElement\n });\n }\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newElement)) {\n pointerDownState.drag.hasOccurred = true;\n const points = newElement.points;\n let dx = gridX - newElement.x;\n let dy = gridY - newElement.y;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event) && points.length === 2) {\n ({\n width: dx,\n height: dy\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)(newElement.x, newElement.y, pointerCoords.x, pointerCoords.y));\n }\n\n if (points.length === 1) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)]\n }, false);\n } else if (points.length > 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(newElement)) {\n (0,_element_routing__WEBPACK_IMPORTED_MODULE_95__.mutateElbowArrow)(newElement, elementsMap, [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)], (0,_math__WEBPACK_IMPORTED_MODULE_98__.vector)(0, 0), undefined, {\n isDragging: true,\n informMutation: false\n });\n } else if (points.length === 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)]\n }, false);\n }\n\n this.setState({\n newElement\n });\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(newElement, false)) {\n // When creating a linear element by dragging\n this.maybeSuggestBindingsForLinearElementAtCoords(newElement, [pointerCoords], this.state.startBoundElement);\n }\n } else {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n this.maybeDragNewGenericElement(pointerDownState, event, false);\n }\n }\n\n if (this.state.activeTool.type === \"selection\") {\n pointerDownState.boxSelection.hasOccurred = true;\n const elements = this.scene.getNonDeletedElements(); // box-select line editor points\n\n if (this.state.editingLinearElement) {\n _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handleBoxSelection(event, this.state, this.setState.bind(this), this.scene.getNonDeletedElementsMap()); // regular box-select\n } else {\n let shouldReuseSelection = true;\n\n if (!event.shiftKey && (0,_scene__WEBPACK_IMPORTED_MODULE_28__.isSomeElementSelected)(elements, this.state)) {\n if (pointerDownState.withCmdOrCtrl && pointerDownState.hit.element) {\n this.setState(prevState => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)(Object.assign(Object.assign({}, prevState), {\n selectedElementIds: {\n [pointerDownState.hit.element.id]: true\n }\n }), this.scene.getNonDeletedElements(), prevState, this));\n } else {\n shouldReuseSelection = false;\n }\n }\n\n const elementsWithinSelection = this.state.selectionElement ? (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getElementsWithinSelection)(elements, this.state.selectionElement, this.scene.getNonDeletedElementsMap()) : [];\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, shouldReuseSelection && prevState.selectedElementIds), elementsWithinSelection.reduce((acc, element) => {\n acc[element.id] = true;\n return acc;\n }, {}));\n\n if (pointerDownState.hit.element) {\n // if using ctrl/cmd, select the hitElement only if we\n // haven't box-selected anything else\n if (!elementsWithinSelection.length) {\n nextSelectedElementIds[pointerDownState.hit.element.id] = true;\n } else {\n delete nextSelectedElementIds[pointerDownState.hit.element.id];\n }\n }\n\n prevState = !shouldReuseSelection ? Object.assign(Object.assign({}, prevState), {\n selectedGroupIds: {},\n editingGroupId: null\n }) : prevState;\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // select linear element only when we haven't box-selected anything else\n selectedLinearElement: elementsWithinSelection.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(elementsWithinSelection[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(elementsWithinSelection[0]) : null,\n showHyperlinkPopup: elementsWithinSelection.length === 1 && (elementsWithinSelection[0].link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(elementsWithinSelection[0])) ? \"info\" : false\n });\n });\n }\n }\n });\n } // Returns whether the pointer move happened over either scrollbar\n\n\n handlePointerMoveOverScrollbars(event, pointerDownState) {\n if (pointerDownState.scrollbars.isOverHorizontal) {\n const x = event.clientX;\n const dx = x - pointerDownState.lastCoords.x;\n this.translateCanvas({\n scrollX: this.state.scrollX - dx / this.state.zoom.value\n });\n pointerDownState.lastCoords.x = x;\n return true;\n }\n\n if (pointerDownState.scrollbars.isOverVertical) {\n const y = event.clientY;\n const dy = y - pointerDownState.lastCoords.y;\n this.translateCanvas({\n scrollY: this.state.scrollY - dy / this.state.zoom.value\n });\n pointerDownState.lastCoords.y = y;\n return true;\n }\n\n return false;\n }\n\n onPointerUpFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(childEvent => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;\n\n this.removePointer(childEvent);\n\n if (pointerDownState.eventListeners.onMove) {\n pointerDownState.eventListeners.onMove.flush();\n }\n\n const {\n newElement,\n resizingElement,\n croppingElementId,\n multiElement,\n activeTool,\n isResizing,\n isRotating,\n isCropping\n } = this.state;\n this.setState(prevState => ({\n isResizing: false,\n isRotating: false,\n isCropping: false,\n resizingElement: null,\n selectionElement: null,\n frameToHighlight: null,\n elementsToHighlight: null,\n cursorButton: \"up\",\n snapLines: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateStable)(prevState.snapLines, []),\n originSnapOffset: null\n }));\n this.lastPointerMoveCoords = null;\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setReferenceSnapPoints(null);\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setVisibleGaps(null);\n this.savePointer(childEvent.clientX, childEvent.clientY, \"up\");\n this.setState({\n selectedElementsAreBeingDragged: false\n });\n const elementsMap = this.scene.getNonDeletedElementsMap(); // Handle end of dragging a point of a linear element, might close a loop\n // and sets binding element\n\n if (this.state.editingLinearElement) {\n if (!pointerDownState.boxSelection.hasOccurred && ((_b = (_a = pointerDownState.hit) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.id) !== this.state.editingLinearElement.elementId) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n } else {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this.scene);\n\n if (editingLinearElement !== this.state.editingLinearElement) {\n this.setState({\n editingLinearElement,\n suggestedBindings: []\n });\n }\n }\n } else if (this.state.selectedLinearElement) {\n if (((_d = (_c = pointerDownState.hit) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.id) !== this.state.selectedLinearElement.elementId) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement to null if there is more than one element selected since we don't want to show linear element handles\n\n if (selectedELements.length > 1) {\n this.setState({\n selectedLinearElement: null\n });\n }\n } else {\n const linearElementEditor = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this.scene);\n const {\n startBindingElement,\n endBindingElement\n } = linearElementEditor;\n const element = this.scene.getElement(linearElementEditor.elementId);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElement)(element, startBindingElement, endBindingElement, elementsMap, this.scene);\n }\n\n if (linearElementEditor !== this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, linearElementEditor), {\n selectedPointsIndices: null\n }),\n suggestedBindings: []\n });\n }\n }\n }\n\n this.missingPointerEventCleanupEmitter.clear();\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, pointerDownState.eventListeners.onMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, pointerDownState.eventListeners.onUp);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, pointerDownState.eventListeners.onKeyDown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, pointerDownState.eventListeners.onKeyUp);\n\n if (this.state.pendingImageElementId) {\n this.setState({\n pendingImageElementId: null\n });\n }\n\n (_f = (_e = this.props) === null || _e === void 0 ? void 0 : _e.onPointerUp) === null || _f === void 0 ? void 0 : _f.call(_e, activeTool, pointerDownState);\n this.onPointerUpEmitter.trigger(this.state.activeTool, pointerDownState, childEvent);\n\n if ((newElement === null || newElement === void 0 ? void 0 : newElement.type) === \"freedraw\") {\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(childEvent, this.state);\n const points = newElement.points;\n let dx = pointerCoords.x - newElement.x;\n let dy = pointerCoords.y - newElement.y; // Allows dots to avoid being flagged as infinitely small\n\n if (dx === points[0][0] && dy === points[0][1]) {\n dy += 0.0001;\n dx += 0.0001;\n }\n\n const pressures = newElement.simulatePressure ? [] : [...newElement.pressures, childEvent.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)],\n pressures,\n lastCommittedPoint: (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(newElement)) {\n const imageElement = newElement;\n\n try {\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } catch (error) {\n console.error(error);\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().filter(el => el.id !== imageElement.id));\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n }\n\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newElement)) {\n if (newElement.points.length > 1) {\n this.store.shouldCaptureIncrement();\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(childEvent, this.state);\n\n if (!pointerDownState.drag.hasOccurred && newElement && !multiElement) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...newElement.points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerCoords.x - newElement.x, pointerCoords.y - newElement.y)]\n });\n this.setState({\n multiElement: newElement,\n newElement\n });\n } else if (pointerDownState.drag.hasOccurred && !multiElement) {\n if ((0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(newElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(newElement, this.state, pointerCoords, this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements());\n }\n\n this.setState({\n suggestedBindings: [],\n startBoundElement: null\n });\n\n if (!activeTool.locked) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n this.setState(prevState => ({\n newElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n }),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [newElement.id]: true\n }), prevState),\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(newElement)\n }));\n } else {\n this.setState(prevState => ({\n newElement: null\n }));\n } // so that the scene gets rendered again to display the newly drawn linear as well\n\n\n this.scene.triggerUpdate();\n }\n\n return;\n }\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(newElement)) {\n const minWidth = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getMinTextElementWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_34__.getFontString)({\n fontSize: newElement.fontSize,\n fontFamily: newElement.fontFamily\n }), newElement.lineHeight);\n\n if (newElement.width < minWidth) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n autoResize: true\n });\n }\n\n this.resetCursor();\n this.handleTextWysiwyg(newElement, {\n isExistingElement: true\n });\n }\n\n if (activeTool.type !== \"selection\" && newElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(newElement)) {\n // remove invisible element which was added in onPointerDown\n // update the store snapshot, so that invisible elements are not captured by the store\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== newElement.id),\n appState: {\n newElement: null\n },\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n });\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(newElement)) {\n const elementsInsideFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInNewFrame)(this.scene.getElementsIncludingDeleted(), newElement, this.scene.getNonDeletedElementsMap());\n this.scene.replaceAllElements((0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(this.scene.getElementsMapIncludingDeleted(), elementsInsideFrame, newElement));\n }\n\n if (newElement) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getNormalizedDimensions)(newElement)); // the above does not guarantee the scene to be rendered again, hence the trigger below\n\n this.scene.triggerUpdate();\n }\n\n if (pointerDownState.drag.hasOccurred) {\n const sceneCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(childEvent, this.state); // when editing the points of a linear element, we check if the\n // linear element still is in the frame afterwards\n // if not, the linear element will be removed from its frame (if any)\n\n if (this.state.selectedLinearElement && this.state.selectedLinearElement.isDragging) {\n const linearElement = this.scene.getElement(this.state.selectedLinearElement.elementId);\n\n if (linearElement === null || linearElement === void 0 ? void 0 : linearElement.frameId) {\n const frame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(linearElement, elementsMap);\n\n if (frame && linearElement) {\n if (!(0,_frame__WEBPACK_IMPORTED_MODULE_50__.elementOverlapsWithFrame)(linearElement, frame, this.scene.getNonDeletedElementsMap())) {\n // remove the linear element from all groups\n // before removing it from the frame as well\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(linearElement, {\n groupIds: []\n });\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.removeElementsFromFrame)([linearElement], this.scene.getNonDeletedElementsMap());\n this.scene.triggerUpdate();\n }\n }\n }\n } else {\n // update the relationships between selected elements and frames\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(sceneCoords);\n const selectedElements = this.scene.getSelectedElements(this.state);\n let nextElements = this.scene.getElementsMapIncludingDeleted();\n\n const updateGroupIdsAfterEditingGroup = elements => {\n if (elements.length > 0) {\n for (const element of elements) {\n const index = element.groupIds.indexOf(this.state.editingGroupId);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: element.groupIds.slice(0, index)\n }, false);\n }\n\n nextElements.forEach(element => {\n if (element.groupIds.length && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(nextElements, element.groupIds[element.groupIds.length - 1]).length < 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: []\n }, false);\n }\n });\n this.setState({\n editingGroupId: null\n });\n }\n };\n\n if (topLayerFrame && !this.state.selectedElementIds[topLayerFrame.id]) {\n const elementsToAdd = selectedElements.filter(element => element.frameId !== topLayerFrame.id && (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n\n if (this.state.editingGroupId) {\n updateGroupIdsAfterEditingGroup(elementsToAdd);\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(nextElements, elementsToAdd, topLayerFrame);\n } else if (!topLayerFrame) {\n if (this.state.editingGroupId) {\n const elementsToRemove = selectedElements.filter(element => element.frameId && !(0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n updateGroupIdsAfterEditingGroup(elementsToRemove);\n }\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(nextElements, this.state, this);\n this.scene.replaceAllElements(nextElements);\n }\n }\n\n if (resizingElement) {\n this.store.shouldCaptureIncrement();\n }\n\n if (resizingElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(resizingElement)) {\n // update the store snapshot, so that invisible elements are not captured by the store\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== resizingElement.id),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n });\n } // handle frame membership for resizing frames and/or selected elements\n\n\n if (pointerDownState.resize.isResizing) {\n let nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(this.scene.getElementsIncludingDeleted(), this.state, this);\n const selectedFrames = this.scene.getSelectedElements(this.state).filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element));\n\n for (const frame of selectedFrames) {\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.replaceAllElementsInFrame)(nextElements, (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getElementsIncludingDeleted(), frame, this.state, elementsMap), frame, this);\n }\n\n this.scene.replaceAllElements(nextElements);\n } // Code below handles selection when element(s) weren't\n // drag or added to selection on pointer down phase.\n\n\n const hitElement = pointerDownState.hit.element;\n\n if (((_g = this.state.selectedLinearElement) === null || _g === void 0 ? void 0 : _g.elementId) !== (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement)) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement when no other element selected except\n // the one we've hit\n\n if (selectedELements.length === 1) {\n this.setState({\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement)\n });\n }\n } // click outside the cropping region to exit\n\n\n if ( // not in the cropping mode at all\n !croppingElementId || // in the cropping mode\n croppingElementId && ( // not cropping and no hit element\n !hitElement && !isCropping || // hitting something else\n hitElement && hitElement.id !== croppingElementId)) {\n this.finishImageCropping();\n }\n\n const pointerStart = this.lastPointerDownEvent;\n const pointerEnd = this.lastPointerUpEvent || this.lastPointerMoveEvent;\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state) && pointerStart && pointerEnd) {\n this.eraserTrail.endPath();\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerStart.clientX, pointerStart.clientY), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerEnd.clientX, pointerEnd.clientY));\n\n if (draggedDistance === 0) {\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: pointerEnd.clientX,\n clientY: pointerEnd.clientY\n }, this.state);\n const hitElements = this.getElementsAtPosition(scenePointer.x, scenePointer.y);\n hitElements.forEach(hitElement => this.elementsPendingErasure.add(hitElement.id));\n }\n\n this.eraseElements();\n return;\n } else if (this.elementsPendingErasure.size) {\n this.restoreReadyToEraseElements();\n }\n\n if (hitElement && !pointerDownState.drag.hasOccurred && !pointerDownState.hit.wasAddedToSelection && ( // if we're editing a line, pointerup shouldn't switch selection if\n // box selected\n !this.state.editingLinearElement || !pointerDownState.boxSelection.hasOccurred)) {\n // when inside line editor, shift selects points instead\n if (childEvent.shiftKey && !this.state.editingLinearElement) {\n if (this.state.selectedElementIds[hitElement.id]) {\n if ((0,_groups__WEBPACK_IMPORTED_MODULE_23__.isSelectedViaGroup)(this.state, hitElement)) {\n this.setState(_prevState => {\n const nextSelectedElementIds = Object.assign({}, _prevState.selectedElementIds); // We want to unselect all groups hitElement is part of\n // as well as all elements that are part of the groups\n // hitElement is part of\n\n for (const groupedElement of hitElement.groupIds.flatMap(groupId => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), groupId))) {\n delete nextSelectedElementIds[groupedElement.id];\n }\n\n return {\n selectedGroupIds: Object.assign(Object.assign({}, _prevState.selectedElementIds), hitElement.groupIds.map(gId => ({\n [gId]: false\n })).reduce((prev, acc) => Object.assign(Object.assign({}, prev), acc), {})),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, _prevState)\n };\n }); // if not dragging a linear element point (outside editor)\n } else if (!((_h = this.state.selectedLinearElement) === null || _h === void 0 ? void 0 : _h.isDragging)) {\n // remove element from selection while\n // keeping prev elements selected\n this.setState(prevState => {\n const newSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete newSelectedElementIds[hitElement.id];\n const newSelectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElements(), {\n selectedElementIds: newSelectedElementIds\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: newSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // set selectedLinearElement only if thats the only element selected\n selectedLinearElement: newSelectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newSelectedElements[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(newSelectedElements[0]) : prevState.selectedLinearElement\n });\n });\n }\n } else if (hitElement.frameId && this.state.selectedElementIds[hitElement.frameId]) {\n // when hitElement is part of a selected frame, deselect the frame\n // to avoid frame and containing elements selected simultaneously\n this.setState(prevState => {\n var _a, _b;\n\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n }); // deselect the frame\n\n delete nextSelectedElementIds[hitElement.frameId]; // deselect groups containing the frame\n\n ((_b = (_a = this.scene.getElement(hitElement.frameId)) === null || _a === void 0 ? void 0 : _a.groupIds) !== null && _b !== void 0 ? _b : []).flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n } else {\n // add element to selection while keeping prev elements selected\n this.setState(_prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, _prevState.selectedElementIds), {\n [hitElement.id]: true\n }), _prevState)\n }));\n }\n } else {\n this.setState(prevState => {\n var _a;\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement) && // Don't set `selectedLinearElement` if its same as the hitElement, this is mainly to prevent resetting the `hoverPointIndex` to -1.\n // Future we should update the API to take care of setting the correct `hoverPointIndex` when initialized\n ((_a = prevState.selectedLinearElement) === null || _a === void 0 ? void 0 : _a.elementId) !== hitElement.id ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement) : prevState.selectedLinearElement\n });\n });\n }\n }\n\n if ( // not dragged\n !pointerDownState.drag.hasOccurred && // not resized\n !this.state.isResizing && ( // only hitting the bounding box of the previous hit element\n hitElement && (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementBoundingBoxOnly)({\n x: pointerDownState.origin.x,\n y: pointerDownState.origin.y,\n element: hitElement,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(hitElement, this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold(),\n frameNameBound: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(hitElement) ? this.frameNameBoundsCache.get(hitElement) : null\n }, elementsMap) || !hitElement && pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements)) {\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: null\n });\n } else {\n // Deselect selected elements\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } // reset cursor\n\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n return;\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\" && newElement) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [newElement.id]: true\n }), prevState),\n showHyperlinkPopup: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(newElement) && !newElement.link ? \"editor\" : prevState.showHyperlinkPopup\n }));\n }\n\n if (activeTool.type !== \"selection\" || (0,_scene__WEBPACK_IMPORTED_MODULE_28__.isSomeElementSelected)(this.scene.getNonDeletedElements(), this.state) || !(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isShallowEqual)(this.state.previousSelectedElementIds, this.state.selectedElementIds)) {\n this.store.shouldCaptureIncrement();\n }\n\n if (pointerDownState.drag.hasOccurred || isResizing || isRotating || isCropping) {\n // We only allow binding via linear elements, specifically via dragging\n // the endpoints (\"start\" or \"end\").\n const linearElements = this.scene.getSelectedElements(this.state).filter(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElements)(linearElements, this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements(), this.scene, (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state), (_k = (_j = this.state.selectedLinearElement) === null || _j === void 0 ? void 0 : _j.selectedPointsIndices) !== null && _k !== void 0 ? _k : []);\n }\n\n if (activeTool.type === \"laser\") {\n this.laserTrails.endPath();\n return;\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n this.setState({\n newElement: null,\n suggestedBindings: [],\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n } else {\n this.setState({\n newElement: null,\n suggestedBindings: []\n });\n }\n\n if (hitElement && this.lastPointerUpEvent && this.lastPointerDownEvent && this.lastPointerUpEvent.timeStamp - this.lastPointerDownEvent.timeStamp < 300 && gesture.pointers.size <= 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement) && this.isIframeLikeElementCenter(hitElement, this.lastPointerUpEvent, pointerDownState.origin.x, pointerDownState.origin.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n }\n });\n } //zsviczian - published on API\n\n\n setSelection(elements) {\n const selectedElementIds = {};\n const selectedGroupIds = {};\n elements.forEach(ele => {\n if (ele.groupIds.length) {\n selectedElementIds[ele.id] = true;\n ele.groupIds.forEach(id => {\n selectedGroupIds[id] = true;\n });\n } // exclude bound text elements as we don't mark them as selected when\n // container is selected unless in group\n else if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele)) {\n selectedElementIds[ele.id] = true;\n }\n });\n this.setState({\n previousSelectedElementIds: this.state.selectedElementIds,\n selectedElementIds,\n selectedGroupIds\n });\n }\n\n clearSelection(hitElement) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, prevState),\n activeEmbeddable: null,\n selectedGroupIds: {},\n // Continue editing the same group if the user selected a different\n // element from it\n editingGroupId: prevState.editingGroupId && hitElement != null && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, prevState.editingGroupId) ? prevState.editingGroupId : null\n }));\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null,\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n\n getTextWysiwygSnappedToCenterPosition(x, y, appState, container) {\n if (container) {\n let elementCenterX = container.x + container.width / 2;\n let elementCenterY = container.y + container.height / 2;\n const elementCenter = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerCenter)(container, appState, this.scene.getNonDeletedElementsMap());\n\n if (elementCenter) {\n elementCenterX = elementCenter.x;\n elementCenterY = elementCenter.y;\n }\n\n const distanceToCenter = Math.hypot(x - elementCenterX, y - elementCenterY);\n const isSnappedToCenter = distanceToCenter < _constants__WEBPACK_IMPORTED_MODULE_12__.TEXT_TO_CENTER_SNAP_THRESHOLD;\n\n if (isSnappedToCenter) {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: elementCenterX,\n sceneY: elementCenterY\n }, appState);\n return {\n viewportX,\n viewportY,\n elementCenterX,\n elementCenterY\n };\n }\n }\n }\n\n getCanvasOffsets() {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n left,\n top\n } = excalidrawContainer.getBoundingClientRect();\n return {\n offsetLeft: left,\n offsetTop: top\n };\n }\n\n return {\n offsetLeft: 0,\n offsetTop: 0\n };\n }\n\n async updateLanguage() {\n const currentLang = _i18n__WEBPACK_IMPORTED_MODULE_25__.languages.find(lang => lang.code === this.props.langCode) || _i18n__WEBPACK_IMPORTED_MODULE_25__.defaultLang;\n await (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.setLanguage)(currentLang);\n this.setAppState({});\n }\n\n}\n/* //zsviczian\nexport const createTestHook = () => {\n if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {\n window.h = window.h || ({} as Window[\"h\"]);\n\n Object.defineProperties(window.h, {\n elements: {\n configurable: true,\n get() {\n return this.app?.scene.getElementsIncludingDeleted();\n },\n set(elements: ExcalidrawElement[]) {\n return this.app?.scene.replaceAllElements(\n syncInvalidIndices(elements),\n );\n },\n },\n scene: {\n configurable: true,\n get() {\n return this.app?.scene;\n },\n },\n });\n }\n};\n\ncreateTestHook();*/\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);\n\n//# sourceURL=webpack://ExcalidrawLib/./components/App.tsx?");
927
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ExcalidrawContainerContext\": () => (/* binding */ ExcalidrawContainerContext),\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ \"useApp\": () => (/* binding */ useApp),\n/* harmony export */ \"useAppProps\": () => (/* binding */ useAppProps),\n/* harmony export */ \"useDevice\": () => (/* binding */ useDevice),\n/* harmony export */ \"useExcalidrawActionManager\": () => (/* binding */ useExcalidrawActionManager),\n/* harmony export */ \"useExcalidrawAppState\": () => (/* binding */ useExcalidrawAppState),\n/* harmony export */ \"useExcalidrawContainer\": () => (/* binding */ useExcalidrawContainer),\n/* harmony export */ \"useExcalidrawElements\": () => (/* binding */ useExcalidrawElements),\n/* harmony export */ \"useExcalidrawSetAppState\": () => (/* binding */ useExcalidrawSetAppState)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"../../node_modules/react/jsx-runtime.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var clsx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! clsx */ \"../../node_modules/clsx/dist/clsx.m.js\");\n/* harmony import */ var nanoid__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(/*! nanoid */ \"./node_modules/nanoid/index.browser.js\");\n/* harmony import */ var _actions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../actions */ \"./actions/index.ts\");\n/* harmony import */ var _actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../actions/actionHistory */ \"./actions/actionHistory.tsx\");\n/* harmony import */ var _actions_manager__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../actions/manager */ \"./actions/manager.tsx\");\n/* harmony import */ var _actions_register__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../actions/register */ \"./actions/register.ts\");\n/* harmony import */ var _analytics__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../analytics */ \"./analytics.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../clipboard */ \"./clipboard.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../data */ \"./data/index.ts\");\n/* harmony import */ var _data_library__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../data/library */ \"./data/library.ts\");\n/* harmony import */ var _data_restore__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../data/restore */ \"./data/restore.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_binding__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../element/binding */ \"./element/binding.ts\");\n/* harmony import */ var _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../element/linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../element/mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _element_newElement__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../element/newElement */ \"./element/newElement.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../element/typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _gesture__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../gesture */ \"./gesture.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../groups */ \"./groups.ts\");\n/* harmony import */ var _history__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../history */ \"./history.ts\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../i18n */ \"./i18n.ts\");\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../keys */ \"./keys.ts\");\n/* harmony import */ var _element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ../element/sizeHelpers */ \"./element/sizeHelpers.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ../scene */ \"./scene/index.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _scene_zoom__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ../scene/zoom */ \"./scene/zoom.ts\");\n/* harmony import */ var _shapes__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ../shapes */ \"./shapes.tsx\");\n/* harmony import */ var _utils_geometry_shape__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ../../utils/geometry/shape */ \"../utils/geometry/shape.ts\");\n/* harmony import */ var _utils_collision__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ../../utils/collision */ \"../utils/collision.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _element_embeddable__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ../element/embeddable */ \"./element/embeddable.ts\");\n/* harmony import */ var _ContextMenu__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./ContextMenu */ \"./components/ContextMenu.tsx\");\n/* harmony import */ var _LayerUI__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./LayerUI */ \"./components/LayerUI.tsx\");\n/* harmony import */ var _Toast__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./Toast */ \"./components/Toast.tsx\");\n/* harmony import */ var _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ../actions/actionToggleViewMode */ \"./actions/actionToggleViewMode.tsx\");\n/* harmony import */ var _data_blob__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ../data/blob */ \"./data/blob.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ../element/image */ \"./element/image.ts\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! lodash.throttle */ \"../../node_modules/lodash.throttle/index.js\");\n/* harmony import */ var lodash_throttle__WEBPACK_IMPORTED_MODULE_42___default = /*#__PURE__*/__webpack_require__.n(lodash_throttle__WEBPACK_IMPORTED_MODULE_42__);\n/* harmony import */ var _data_filesystem__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ../data/filesystem */ \"./data/filesystem.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ../components/hyperlink/Hyperlink */ \"./components/hyperlink/Hyperlink.tsx\");\n/* harmony import */ var _data_url__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ../data/url */ \"./data/url.ts\");\n/* harmony import */ var _element_transformHandles__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ../element/transformHandles */ \"./element/transformHandles.ts\");\n/* harmony import */ var _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ../actions/actionElementLock */ \"./actions/actionElementLock.ts\");\n/* harmony import */ var _fonts__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ../fonts */ \"./fonts/index.ts\");\n/* harmony import */ var _frame__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ../frame */ \"./frame.ts\");\n/* harmony import */ var _scene_selection__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ../scene/selection */ \"./scene/selection.ts\");\n/* harmony import */ var _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ../actions/actionClipboard */ \"./actions/actionClipboard.tsx\");\n/* harmony import */ var _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ../actions/actionFrame */ \"./actions/actionFrame.ts\");\n/* harmony import */ var _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ../actions/actionCanvas */ \"./actions/actionCanvas.tsx\");\n/* harmony import */ var _jotai__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ../jotai */ \"./jotai.ts\");\n/* harmony import */ var _ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./ActiveConfirmDialog */ \"./components/ActiveConfirmDialog.tsx\");\n/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ../errors */ \"./errors.ts\");\n/* harmony import */ var _snapping__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ../snapping */ \"./snapping.ts\");\n/* harmony import */ var _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ../actions/actionBoundText */ \"./actions/actionBoundText.tsx\");\n/* harmony import */ var _BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ./BraveMeasureTextError */ \"./components/BraveMeasureTextError.tsx\");\n/* harmony import */ var _EyeDropper__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./EyeDropper */ \"./components/EyeDropper.tsx\");\n/* harmony import */ var _data_transform__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ../data/transform */ \"./data/transform.ts\");\n/* harmony import */ var _Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ./Sidebar/Sidebar */ \"./components/Sidebar/Sidebar.tsx\");\n/* harmony import */ var _canvases__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ./canvases */ \"./components/canvases/index.tsx\");\n/* harmony import */ var _scene_Renderer__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! ../scene/Renderer */ \"./scene/Renderer.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(/*! ../scene/ShapeCache */ \"./scene/ShapeCache.ts\");\n/* harmony import */ var _SVGLayer__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(/*! ./SVGLayer */ \"./components/SVGLayer.tsx\");\n/* harmony import */ var _cursor__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(/*! ../cursor */ \"./cursor.ts\");\n/* harmony import */ var _emitter__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(/*! ../emitter */ \"./emitter.ts\");\n/* harmony import */ var _element_ElementCanvasButtons__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(/*! ../element/ElementCanvasButtons */ \"./element/ElementCanvasButtons.tsx\");\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(/*! ../colors */ \"./colors.ts\");\n/* harmony import */ var _MagicButton__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(/*! ./MagicButton */ \"./components/MagicButton.tsx\");\n/* harmony import */ var _icons__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(/*! ./icons */ \"./components/icons.tsx\");\n/* harmony import */ var _FollowMode_FollowMode__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(/*! ./FollowMode/FollowMode */ \"./components/FollowMode/FollowMode.tsx\");\n/* harmony import */ var _actions_actionProperties__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(/*! ../actions/actionProperties */ \"./actions/actionProperties.tsx\");\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(/*! ../store */ \"./store.ts\");\n/* harmony import */ var _animation_frame_handler__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(/*! ../animation-frame-handler */ \"./animation-frame-handler.ts\");\n/* harmony import */ var _animated_trail__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(/*! ../animated-trail */ \"./animated-trail.ts\");\n/* harmony import */ var _laser_trails__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(/*! ../laser-trails */ \"./laser-trails.ts\");\n/* harmony import */ var _reactUtils__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(/*! ../reactUtils */ \"./reactUtils.ts\");\n/* harmony import */ var _renderer_renderElement__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(/*! ../renderer/renderElement */ \"./renderer/renderElement.ts\");\n/* harmony import */ var _obsidianUtils__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(/*! ../obsidianUtils */ \"./obsidianUtils.ts\");\n/* harmony import */ var _element_collision__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(/*! ../element/collision */ \"./element/collision.ts\");\n/* harmony import */ var _element_textWysiwyg__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(/*! ../element/textWysiwyg */ \"./element/textWysiwyg.tsx\");\n/* harmony import */ var _scene_scrollbars__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(/*! ../scene/scrollbars */ \"./scene/scrollbars.ts\");\n/* harmony import */ var _fractionalIndex__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(/*! ../fractionalIndex */ \"./fractionalIndex.ts\");\n/* harmony import */ var _hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(/*! ./hyperlink/helpers */ \"./components/hyperlink/helpers.ts\");\n/* harmony import */ var _actions_shortcuts__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(/*! ../actions/shortcuts */ \"./actions/shortcuts.ts\");\n/* harmony import */ var _element_resizeElements__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(/*! ../element/resizeElements */ \"./element/resizeElements.ts\");\n/* harmony import */ var _actions_actionTextAutoResize__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(/*! ../actions/actionTextAutoResize */ \"./actions/actionTextAutoResize.ts\");\n/* harmony import */ var _element_bounds__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(/*! ../element/bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _mermaid__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(/*! ../mermaid */ \"./mermaid.ts\");\n/* harmony import */ var _Tooltip__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(/*! ./Tooltip */ \"./components/Tooltip.tsx\");\n/* harmony import */ var _canvases_NewElementCanvas__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(/*! ./canvases/NewElementCanvas */ \"./components/canvases/NewElementCanvas.tsx\");\n/* harmony import */ var _element_routing__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(/*! ../element/routing */ \"./element/routing.ts\");\n/* harmony import */ var _element_flowchart__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(/*! ../element/flowchart */ \"./element/flowchart.ts\");\n/* harmony import */ var _SearchMenu__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(/*! ./SearchMenu */ \"./components/SearchMenu.tsx\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(/*! ../../math */ \"../math/index.ts\");\n/* harmony import */ var _element_cropElement__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(/*! ../element/cropElement */ \"./element/cropElement.ts\");\n/* harmony import */ var _element_textWrapping__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(/*! ../element/textWrapping */ \"./element/textWrapping.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n //zsviczian\n\n\n\n\n\n\n\n\n\n\n\n\nconst AppContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst AppPropsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nconst deviceContextInitialValue = {\n viewport: {\n isMobile: false,\n isLandscape: false\n },\n editor: {\n isMobile: false,\n canFitSidebar: false\n },\n isTouchScreen: false\n};\nconst DeviceContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(deviceContextInitialValue);\nDeviceContext.displayName = \"DeviceContext\";\nconst ExcalidrawContainerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext({\n container: null,\n id: null\n});\nExcalidrawContainerContext.displayName = \"ExcalidrawContainerContext\";\nconst ExcalidrawElementsContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext([]);\nExcalidrawElementsContext.displayName = \"ExcalidrawElementsContext\";\nconst ExcalidrawAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n width: 0,\n height: 0,\n offsetLeft: 0,\n offsetTop: 0\n}));\nExcalidrawAppStateContext.displayName = \"ExcalidrawAppStateContext\";\nconst ExcalidrawSetAppStateContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(() => {\n console.warn(\"Uninitialized ExcalidrawSetAppStateContext context!\");\n});\nExcalidrawSetAppStateContext.displayName = \"ExcalidrawSetAppStateContext\";\nconst ExcalidrawActionManagerContext = react__WEBPACK_IMPORTED_MODULE_1___default().createContext(null);\nExcalidrawActionManagerContext.displayName = \"ExcalidrawActionManagerContext\";\nconst useApp = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppContext);\nconst useAppProps = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(AppPropsContext);\nconst useDevice = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(DeviceContext);\nconst useExcalidrawContainer = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawContainerContext);\nconst useExcalidrawElements = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawElementsContext);\nconst useExcalidrawAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawAppStateContext);\nconst useExcalidrawSetAppState = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawSetAppStateContext);\nconst useExcalidrawActionManager = () => (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ExcalidrawActionManagerContext);\nlet didTapTwice = false;\nlet tappedTwiceTimer = 0;\nlet isHoldingSpace = false;\nlet isPanning = false;\nlet isDraggingScrollBar = false;\nlet currentScrollBars = {\n horizontal: null,\n vertical: null\n};\nlet touchTimeout = 0;\nlet invalidateContextMenu = false;\n/**\n * Map of youtube embed video states\n */\n\nconst YOUTUBE_VIDEO_STATES = new Map();\nlet IS_PLAIN_PASTE = false;\nlet IS_PLAIN_PASTE_TIMER = 0;\nlet PLAIN_PASTE_TOAST_SHOWN = false;\nlet lastPointerUp = null;\nconst gesture = {\n pointers: new Map(),\n lastCenter: null,\n initialDistance: null,\n initialScale: null\n};\n\nclass App extends (react__WEBPACK_IMPORTED_MODULE_1___default().Component) {\n constructor(props) {\n super(props);\n this.interactiveCanvas = null;\n this.unmounted = false;\n this.device = deviceContextInitialValue;\n this.excalidrawContainerRef = react__WEBPACK_IMPORTED_MODULE_1___default().createRef();\n this.files = {};\n this.imageCache = new Map();\n this.iFrameRefs = new Map();\n /**\n * Indicates whether the embeddable's url has been validated for rendering.\n * If value not set, indicates that the validation is pending.\n * Initially or on url change the flag is not reset so that we can guarantee\n * the validation came from a trusted source (the editor).\n **/\n\n this.embedsValidationStatus = new Map();\n /** embeds that have been inserted to DOM (as a perf optim, we don't want to\n * insert to DOM before user initially scrolls to them) */\n\n this.initializedEmbeds = new Set();\n this.elementsPendingErasure = new Set();\n this.flowChartCreator = new _element_flowchart__WEBPACK_IMPORTED_MODULE_96__.FlowChartCreator();\n this.flowChartNavigator = new _element_flowchart__WEBPACK_IMPORTED_MODULE_96__.FlowChartNavigator();\n this.lastPointerDownEvent = null;\n this.lastPointerUpEvent = null;\n this.lastPointerMoveEvent = null;\n this.lastPointerMoveCoords = null;\n this.lastViewportPosition = {\n x: 0,\n y: 0\n };\n this.allowMobileMode = true; //zsviczian\n\n this.animationFrameHandler = new _animation_frame_handler__WEBPACK_IMPORTED_MODULE_77__.AnimationFrameHandler();\n this.laserTrails = new _laser_trails__WEBPACK_IMPORTED_MODULE_79__.LaserTrails(this.animationFrameHandler, this);\n this.eraserTrail = new _animated_trail__WEBPACK_IMPORTED_MODULE_78__.AnimatedTrail(this.animationFrameHandler, this, {\n streamline: 0.2,\n size: 5,\n keepHead: true,\n sizeMapping: c => {\n const DECAY_TIME = 200;\n const DECAY_LENGTH = 10;\n const t = Math.max(0, 1 - (performance.now() - c.pressure) / DECAY_TIME);\n const l = (DECAY_LENGTH - Math.min(DECAY_LENGTH, c.totalLength - c.currentIndex)) / DECAY_LENGTH;\n return Math.min((0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeOut)(l), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeOut)(t));\n },\n fill: () => this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.LIGHT ? \"rgba(0, 0, 0, 0.2)\" : \"rgba(255, 255, 255, 0.2)\"\n });\n this.onChangeEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onPointerDownEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onPointerUpEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onUserFollowEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onScrollChangeEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.missingPointerEventCleanupEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n this.onRemoveEventListenersEmitter = new _emitter__WEBPACK_IMPORTED_MODULE_69__.Emitter();\n /**\n * Returns gridSize taking into account `gridModeEnabled`.\n * If disabled, returns null.\n */\n\n this.getEffectiveGridSize = () => {\n return (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isGridModeEnabled)(this) ? this.state.gridSize : null;\n };\n\n this.updateEmbedValidationStatus = (element, status) => {\n this.embedsValidationStatus.set(element.id, status);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element);\n };\n\n this.updateEmbeddables = () => {\n const iframeLikes = new Set();\n let updated = false;\n this.scene.getNonDeletedElements().filter(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(element)) {\n iframeLikes.add(element.id);\n\n if (!this.embedsValidationStatus.has(element.id)) {\n updated = true;\n const validated = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.embeddableURLValidator)(element.link, this.props.validateEmbeddable);\n this.updateEmbedValidationStatus(element, validated);\n }\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(element)) {\n iframeLikes.add(element.id);\n }\n\n return false;\n });\n\n if (updated) {\n this.scene.triggerUpdate();\n } // GC\n\n\n this.iFrameRefs.forEach((ref, id) => {\n if (!iframeLikes.has(id)) {\n this.iFrameRefs.delete(id);\n }\n });\n };\n\n this.getFrameNameDOMId = frameElement => {\n return `${this.id}-frame-name-${frameElement.id}`;\n };\n\n this.frameNameBoundsCache = {\n get: frameElement => {\n let bounds = this.frameNameBoundsCache._cache.get(frameElement.id);\n\n if (!bounds || bounds.zoom !== this.state.zoom.value || bounds.versionNonce !== frameElement.versionNonce) {\n const frameNameDiv = document.getElementById(this.getFrameNameDOMId(frameElement));\n\n if (frameNameDiv) {\n const box = frameNameDiv.getBoundingClientRect();\n const boxSceneTopLeft = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: box.x,\n clientY: box.y\n }, this.state);\n const boxSceneBottomRight = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: box.right,\n clientY: box.bottom\n }, this.state);\n bounds = {\n x: boxSceneTopLeft.x,\n y: boxSceneTopLeft.y,\n width: boxSceneBottomRight.x - boxSceneTopLeft.x,\n height: boxSceneBottomRight.y - boxSceneTopLeft.y,\n angle: 0,\n zoom: this.state.zoom.value,\n versionNonce: frameElement.versionNonce\n };\n\n this.frameNameBoundsCache._cache.set(frameElement.id, bounds);\n\n return bounds;\n }\n\n return null;\n }\n\n return bounds;\n },\n\n /**\n * @private\n */\n _cache: new Map()\n };\n\n this.renderFrameNames = () => {\n if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {\n return null;\n }\n\n const isDarkTheme = this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.DARK;\n return this.scene.getNonDeletedFramesLikes().map(f => {\n var _a, _b;\n\n if (!(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(f, this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap())) {\n // if frame not visible, don't render its name\n return null;\n }\n\n const {\n x: x1,\n y: y1\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: f.x,\n sceneY: f.y\n }, this.state);\n const FRAME_NAME_EDIT_PADDING = 6;\n\n const reset = () => {\n var _a;\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: ((_a = f.name) === null || _a === void 0 ? void 0 : _a.trim()) || null\n });\n this.setState({\n editingFrame: null\n });\n };\n\n let frameNameJSX;\n const frameName = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameLikeTitle)(f);\n\n if (f.id === this.state.editingFrame) {\n const frameNameInEdit = frameName;\n frameNameJSX = (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"input\", {\n autoFocus: true,\n value: frameNameInEdit,\n onChange: e => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(f, {\n name: e.target.value\n });\n },\n onFocus: e => e.target.select(),\n onBlur: () => reset(),\n onKeyDown: event => {\n // for some inexplicable reason, `onBlur` triggered on ESC\n // does not reset `state.editingFrame` despite being called,\n // and we need to reset it here as well\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n reset();\n }\n },\n style: {\n background: this.state.viewBackgroundColor,\n filter: isDarkTheme ? _constants__WEBPACK_IMPORTED_MODULE_12__.THEME_FILTER : \"none\",\n zIndex: 2,\n border: \"none\",\n display: \"block\",\n padding: `${FRAME_NAME_EDIT_PADDING}px`,\n borderRadius: 4,\n boxShadow: \"inset 0 0 0 2px var(--color-on-primary-container)\",\n fontFamily: \"Assistant\",\n fontSize: \"14px\",\n transform: `translate(-${FRAME_NAME_EDIT_PADDING}px, ${FRAME_NAME_EDIT_PADDING}px)`,\n color: \"var(--color-gray-80)\",\n overflow: \"hidden\",\n maxWidth: `${(0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.getExcalidrawContentEl)().clientWidth - x1 - FRAME_NAME_EDIT_PADDING //zsviczian was document.body\n }px`\n },\n size: frameNameInEdit.length + 1 || 1,\n dir: \"auto\",\n autoComplete: \"off\",\n autoCapitalize: \"off\",\n autoCorrect: \"off\"\n });\n } else {\n frameNameJSX = frameName;\n }\n\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n id: this.getFrameNameDOMId(f),\n style: {\n position: \"absolute\",\n // Positioning from bottom so that we don't to either\n // calculate text height or adjust using transform (which)\n // messes up input position when editing the frame name.\n // This makes the positioning deterministic and we can calculate\n // the same position when rendering to canvas / svg.\n bottom: `${this.state.height + _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameOffsetY - y1 + this.state.offsetTop}px`,\n left: `${x1 - this.state.offsetLeft}px`,\n zIndex: 2,\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameFontSize,\n color: (_b = (_a = this.state.frameColor) === null || _a === void 0 ? void 0 : _a.nameColor) !== null && _b !== void 0 ? _b : isDarkTheme //zsviczian\n ? _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameColorDarkTheme : _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameColorLightTheme,\n lineHeight: _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE.nameLineHeight,\n width: \"max-content\",\n maxWidth: `${f.width}px`,\n overflow: f.id === this.state.editingFrame ? \"visible\" : \"hidden\",\n whiteSpace: \"nowrap\",\n textOverflow: \"ellipsis\",\n cursor: _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE,\n pointerEvents: this.state.viewModeEnabled ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled\n },\n onPointerDown: event => this.handleCanvasPointerDown(event),\n onWheel: event => this.handleWheel(event),\n onContextMenu: this.handleCanvasContextMenu,\n onDoubleClick: () => {\n this.setState({\n editingFrame: f.id\n });\n }\n }, {\n children: frameNameJSX\n }), f.id);\n });\n };\n\n this.focusContainer = () => {\n var _a;\n\n (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.focus();\n };\n\n this.getSceneElementsIncludingDeleted = () => {\n return this.scene.getElementsIncludingDeleted();\n };\n\n this.getSceneElements = () => {\n return this.scene.getNonDeletedElements();\n };\n\n this.onInsertElements = elements => {\n this.addElementsFromPasteOrLibrary({\n elements,\n position: \"center\",\n files: null\n });\n };\n\n this.onExportImage = async (type, elements, opts) => {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"export\", type, \"ui\");\n const fileHandle = await (0,_data__WEBPACK_IMPORTED_MODULE_13__.exportCanvas)(type, elements, this.state, this.files, {\n exportBackground: this.state.exportBackground,\n name: this.getName(),\n viewBackgroundColor: this.state.viewBackgroundColor,\n exportingFrame: opts.exportingFrame\n }).catch(_utils__WEBPACK_IMPORTED_MODULE_34__.muteFSAbortError).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: error.message\n });\n });\n\n if (this.state.exportEmbedScene && fileHandle && (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isImageFileHandle)(fileHandle)) {\n this.setState({\n fileHandle\n });\n }\n };\n\n this.magicGenerations = new Map();\n\n this.updateMagicGeneration = ({\n frameElement,\n data\n }) => {\n if (data.status === \"pending\") {\n // We don't wanna persist pending state to storage. It should be in-app\n // state only.\n // Thus reset so that we prefer local cache (if there was some\n // generationData set previously)\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(frameElement, {\n customData: {\n generationData: undefined\n }\n }, false);\n } else {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(frameElement, {\n customData: {\n generationData: data\n }\n }, false);\n }\n\n this.magicGenerations.set(frameElement.id, data);\n this.triggerRender();\n };\n\n this.plugins = {};\n\n this.onMagicframeToolSelect = () => {\n const selectedElements = this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds\n });\n\n if (selectedElements.length === 0) {\n this.setActiveTool({\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"tool-select (empty-selection)\", \"d2c\");\n } else {\n const selectedMagicFrame = selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isMagicFrameElement)(selectedElements[0]) && selectedElements[0]; // case: user selected elements containing frame-like(s) or are frame\n // members, we don't want to wrap into another magicframe\n // (unless the only selected element is a magic frame which we reuse)\n\n if (!selectedMagicFrame && selectedElements.some(el => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(el) || el.frameId)) {\n this.setActiveTool({\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe\n });\n return;\n }\n\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"tool-select (existing selection)\", \"d2c\");\n let frame;\n\n if (selectedMagicFrame) {\n // a single magicframe already selected -> use it\n frame = selectedMagicFrame;\n } else {\n // selected elements aren't wrapped in magic frame yet -> wrap now\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n const padding = 50;\n frame = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newMagicFrameElement)(Object.assign(Object.assign({}, _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE), {\n x: minX - padding,\n y: minY - padding,\n width: maxX - minX + padding * 2,\n height: maxY - minY + padding * 2,\n opacity: 100,\n locked: false\n }));\n this.scene.insertElement(frame);\n\n for (const child of selectedElements) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(child, {\n frameId: frame.id\n });\n }\n\n this.setState({\n selectedElementIds: {\n [frame.id]: true\n }\n });\n }\n\n this.onMagicFrameGenerate(frame, \"upstream\");\n }\n };\n\n this.openEyeDropper = ({\n type\n }) => {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_EyeDropper__WEBPACK_IMPORTED_MODULE_61__.activeEyeDropperAtom, {\n swapPreviewOnAlt: true,\n colorPickerType: type === \"stroke\" ? \"elementStroke\" : \"elementBackground\",\n onSelect: (color, event) => {\n const shouldUpdateStrokeColor = type === \"background\" && event.altKey || type === \"stroke\" && !event.altKey;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (!selectedElements.length || this.state.activeTool.type !== \"selection\") {\n if (shouldUpdateStrokeColor) {\n this.syncActionResult({\n appState: Object.assign(Object.assign({}, this.state), {\n currentItemStrokeColor: color\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n } else {\n this.syncActionResult({\n appState: Object.assign(Object.assign({}, this.state), {\n currentItemBackgroundColor: color\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n } else {\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().map(el => {\n if (this.state.selectedElementIds[el.id]) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(el, {\n [shouldUpdateStrokeColor ? \"strokeColor\" : \"backgroundColor\"]: color\n });\n }\n\n return el;\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n },\n keepOpenOnAlt: false\n });\n };\n\n this.dismissLinearEditor = () => {\n setTimeout(() => {\n this.setState({\n editingLinearElement: null\n });\n });\n };\n\n this.syncActionResult = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(actionResult => {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n\n if (this.unmounted || actionResult === false) {\n return;\n }\n\n if (actionResult.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE) {\n this.store.shouldUpdateSnapshot();\n } else if (actionResult.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE) {\n this.store.shouldCaptureIncrement();\n }\n\n let didUpdate = false;\n let editingTextElement = null;\n\n if (actionResult.elements) {\n this.scene.replaceAllElements(actionResult.elements);\n didUpdate = true;\n }\n\n if (actionResult.files) {\n this.addMissingFiles(actionResult.files, actionResult.replaceFiles);\n this.addNewImagesToImageCache();\n }\n\n if (actionResult.appState || editingTextElement || this.state.contextMenu) {\n let viewModeEnabled = ((_a = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _a === void 0 ? void 0 : _a.viewModeEnabled) || false;\n let zenModeEnabled = ((_b = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _b === void 0 ? void 0 : _b.zenModeEnabled) || false;\n const theme = ((_c = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _c === void 0 ? void 0 : _c.theme) || this.props.theme || _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.LIGHT;\n const name = (_e = (_d = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : this.state.name;\n const errorMessage = (_g = (_f = actionResult === null || actionResult === void 0 ? void 0 : actionResult.appState) === null || _f === void 0 ? void 0 : _f.errorMessage) !== null && _g !== void 0 ? _g : this.state.errorMessage;\n\n if (typeof this.props.viewModeEnabled !== \"undefined\") {\n viewModeEnabled = this.props.viewModeEnabled;\n }\n\n if (typeof this.props.zenModeEnabled !== \"undefined\") {\n zenModeEnabled = this.props.zenModeEnabled;\n }\n\n editingTextElement = ((_h = actionResult.appState) === null || _h === void 0 ? void 0 : _h.editingTextElement) || null; // make sure editingTextElement points to latest element reference\n\n if (actionResult.elements && editingTextElement) {\n actionResult.elements.forEach(element => {\n if ((editingTextElement === null || editingTextElement === void 0 ? void 0 : editingTextElement.id) === element.id && editingTextElement !== element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element) && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element)) {\n editingTextElement = element;\n }\n });\n }\n\n if (editingTextElement === null || editingTextElement === void 0 ? void 0 : editingTextElement.isDeleted) {\n editingTextElement = null;\n }\n\n this.setState(prevAppState => {\n const actionAppState = actionResult.appState || {};\n return Object.assign(Object.assign(Object.assign({}, prevAppState), actionAppState), {\n // NOTE this will prevent opening context menu using an action\n // or programmatically from the host, so it will need to be\n // rewritten later\n contextMenu: null,\n editingTextElement,\n viewModeEnabled,\n zenModeEnabled,\n theme,\n name,\n errorMessage\n });\n });\n didUpdate = true;\n }\n\n if (!didUpdate && actionResult.storeAction !== _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.NONE) {\n this.scene.triggerUpdate();\n }\n }); // Lifecycle\n\n this.onBlur = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(() => {\n isHoldingSpace = false;\n this.setState({\n isBindingEnabled: true\n });\n });\n\n this.onUnload = () => {\n this.onBlur();\n };\n\n this.disableEvent = event => {\n event.preventDefault();\n };\n\n this.resetHistory = () => {\n this.history.clear();\n };\n\n this.resetStore = () => {\n this.store.clear();\n };\n /**\n * Resets scene & history.\n * ! Do not use to clear scene user action !\n */\n\n\n this.resetScene = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(opts => {\n this.scene.replaceAllElements([]);\n this.setState(state => Object.assign(Object.assign({}, (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)()), {\n isLoading: (opts === null || opts === void 0 ? void 0 : opts.resetLoadingState) ? false : state.isLoading,\n theme: this.state.theme\n }));\n this.resetStore();\n this.resetHistory();\n });\n\n this.initializeScene = async () => {\n var _a;\n\n if (\"launchQueue\" in window && \"LaunchParams\" in window) {\n window.launchQueue.setConsumer(async launchParams => {\n if (!launchParams.files.length) {\n return;\n }\n\n const fileHandle = launchParams.files[0];\n const blob = await fileHandle.getFile();\n this.loadFileToCanvas(new File([blob], blob.name || \"\", {\n type: blob.type\n }), fileHandle);\n });\n }\n\n if (this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n if (!this.state.isLoading) {\n this.setState({\n isLoading: true\n });\n }\n\n let initialData = null;\n\n try {\n if (typeof this.props.initialData === \"function\") {\n initialData = (await this.props.initialData()) || null;\n } else {\n initialData = (await this.props.initialData) || null;\n }\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.libraryItems) {\n this.library.updateLibrary({\n libraryItems: initialData.libraryItems,\n merge: true\n }).catch(error => {\n console.error(error);\n });\n }\n } catch (error) {\n console.error(error);\n initialData = {\n appState: {\n errorMessage: error.message || \"Encountered an error during importing or restoring scene data\"\n }\n };\n }\n\n const scene = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restore)(initialData, null, null, {\n repairBindings: true\n });\n scene.appState = Object.assign(Object.assign({}, scene.appState), {\n theme: this.props.theme || scene.appState.theme,\n // we're falling back to current (pre-init) state when deciding\n // whether to open the library, to handle a case where we\n // update the state outside of initialData (e.g. when loading the app\n // with a library install link, which should auto-open the library)\n openSidebar: ((_a = scene.appState) === null || _a === void 0 ? void 0 : _a.openSidebar) || this.state.openSidebar,\n activeTool: scene.appState.activeTool.type === \"image\" ? Object.assign(Object.assign({}, scene.appState.activeTool), {\n type: \"selection\"\n }) : scene.appState.activeTool,\n isLoading: false,\n toast: this.state.toast\n });\n\n if (initialData === null || initialData === void 0 ? void 0 : initialData.scrollToContent) {\n scene.appState = Object.assign(Object.assign({}, scene.appState), (0,_scene__WEBPACK_IMPORTED_MODULE_28__.calculateScrollCenter)(scene.elements, Object.assign(Object.assign({}, scene.appState), {\n width: this.state.width,\n height: this.state.height,\n offsetTop: this.state.offsetTop,\n offsetLeft: this.state.offsetLeft\n })));\n }\n\n this.resetStore();\n this.resetHistory();\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n })); // clear the shape and image cache so that any images in initialData\n // can be loaded fresh\n\n this.clearImageShapeCache(); // manually loading the font faces seems faster even in browsers that do fire the loadingdone event\n\n this.fonts.loadSceneFonts().then(fontFaces => {\n this.fonts.onLoaded(fontFaces);\n });\n };\n\n this.isMobileBreakpoint = (width, height) => {\n return width !== 0 && //zsviczian changing tabs in Obsidian causes MobileMenu to be rendered\n this.allowMobileMode && ( //zsviczian\n width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_PORTRAIT || height < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_HEIGHT_LANDSCAPE && width < _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_MAX_WIDTH_LANDSCAPE);\n };\n\n this.refreshViewportBreakpoints = () => {\n const container = this.excalidrawContainerRef.current;\n\n if (!container) {\n return;\n }\n\n const {\n clientWidth: viewportWidth,\n clientHeight: viewportHeight\n } = (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.getExcalidrawContentEl)(); //zsviczian was document.body;\n\n const prevViewportState = this.device.viewport;\n const nextViewportState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevViewportState, {\n isLandscape: viewportWidth > viewportHeight,\n isMobile: this.isMobileBreakpoint(viewportWidth, viewportHeight)\n });\n\n if (prevViewportState !== nextViewportState) {\n this.device = Object.assign(Object.assign({}, this.device), {\n viewport: nextViewportState\n });\n return true;\n }\n\n return false;\n };\n\n this.refreshEditorBreakpoints = () => {\n const container = this.excalidrawContainerRef.current;\n\n if (!container) {\n return;\n }\n\n const {\n width: editorWidth,\n height: editorHeight\n } = container.getBoundingClientRect();\n const sidebarBreakpoint = this.props.UIOptions.dockedSidebarBreakpoint != null ? this.props.UIOptions.dockedSidebarBreakpoint : _constants__WEBPACK_IMPORTED_MODULE_12__.MQ_RIGHT_SIDEBAR_MIN_WIDTH;\n const prevEditorState = this.device.editor;\n const nextEditorState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevEditorState, {\n isMobile: this.isMobileBreakpoint(editorWidth, editorHeight),\n canFitSidebar: editorWidth > sidebarBreakpoint\n });\n\n if (prevEditorState !== nextEditorState) {\n this.device = Object.assign(Object.assign({}, this.device), {\n editor: nextEditorState\n });\n return true;\n }\n\n return false;\n };\n\n this.onResize = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(() => {\n this.scene.getElementsIncludingDeleted().forEach(element => _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element));\n this.refreshViewportBreakpoints();\n this.updateDOMRect();\n\n if (!_constants__WEBPACK_IMPORTED_MODULE_12__.supportsResizeObserver) {\n this.refreshEditorBreakpoints();\n }\n\n this.setState({});\n });\n /** generally invoked only if fullscreen was invoked programmatically */\n\n this.onFullscreenChange = () => {\n var _a;\n\n if ( // points to the iframe element we fullscreened\n !document.fullscreenElement && ((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.state) === \"active\") {\n this.setState({\n activeEmbeddable: null\n });\n }\n };\n\n this.renderInteractiveSceneCallback = ({\n atLeastOneVisibleElement,\n scrollBars,\n elementsMap\n }) => {\n if (!document.querySelector(\".excalidraw\")) {\n return;\n } //zsviczian - address issue when moving excalidraw to a new window/document\n\n\n if (scrollBars) {\n currentScrollBars = scrollBars;\n }\n\n const scrolledOutside = // hide when editing text\n this.state.editingTextElement ? false : !atLeastOneVisibleElement && elementsMap.size > 0;\n\n if (this.state.scrolledOutside !== scrolledOutside) {\n this.setState({\n scrolledOutside\n });\n }\n\n this.scheduleImageRefresh();\n };\n\n this.onScroll = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.debounce)(() => {\n const {\n offsetTop,\n offsetLeft\n } = this.getCanvasOffsets();\n this.setState(state => {\n if (state.offsetLeft === offsetLeft && state.offsetTop === offsetTop) {\n return null;\n }\n\n return {\n offsetTop,\n offsetLeft\n };\n });\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.SCROLL_TIMEOUT); // Copy/paste\n\n this.onCut = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target)) {\n return;\n }\n\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, \"keyboard\", event);\n event.preventDefault();\n event.stopPropagation();\n });\n this.onCopy = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a;\n\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);\n\n if (!isExcalidrawActive || (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target)) {\n return;\n }\n\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, \"keyboard\", event);\n event.preventDefault();\n event.stopPropagation();\n });\n\n this.onTouchStart = event => {\n // fix for Apple Pencil Scribble (do not prevent for other devices)\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.isIOS) {\n event.preventDefault();\n }\n\n if (!didTapTwice) {\n didTapTwice = true;\n clearTimeout(tappedTwiceTimer);\n tappedTwiceTimer = window.setTimeout(App.resetTapTwice, _constants__WEBPACK_IMPORTED_MODULE_12__.TAP_TWICE_TIMEOUT);\n return;\n } // insert text only if we tapped twice with a single finger\n // event.touches.length === 1 will also prevent inserting text when user's zooming\n\n\n if (didTapTwice && event.touches.length === 1) {\n const touch = event.touches[0]; // @ts-ignore\n\n this.handleCanvasDoubleClick({\n clientX: touch.clientX,\n clientY: touch.clientY\n });\n didTapTwice = false;\n clearTimeout(tappedTwiceTimer);\n }\n\n if (event.touches.length === 2) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n };\n\n this.onTouchEnd = event => {\n this.resetContextMenuTimer();\n\n if (event.touches.length > 0) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n } else {\n gesture.pointers.clear();\n }\n };\n\n this.pasteFromClipboard = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(async event => {\n var _a, _b;\n\n const isPlainPaste = !!IS_PLAIN_PASTE; // #686\n\n const target = document.activeElement;\n const isExcalidrawActive = (_a = this.excalidrawContainerRef.current) === null || _a === void 0 ? void 0 : _a.contains(target);\n\n if (event && !isExcalidrawActive) {\n return;\n }\n\n const elementUnderCursor = document.elementFromPoint(this.lastViewportPosition.x, this.lastViewportPosition.y);\n\n if (event && (!(elementUnderCursor instanceof HTMLCanvasElement) || (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(target))) {\n return;\n }\n\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state); // must be called in the same frame (thus before any awaits) as the paste\n // event else some browsers (FF...) will clear the clipboardData\n // (something something security)\n\n let file = (_b = event === null || event === void 0 ? void 0 : event.clipboardData) === null || _b === void 0 ? void 0 : _b.files[0];\n const data = await (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.parseClipboard)(event, isPlainPaste);\n\n if (!file && !isPlainPaste) {\n if (data.mixedContent) {\n return this.addElementsFromMixedContentPaste(data.mixedContent, {\n isPlainPaste,\n sceneX,\n sceneY\n });\n } else if (data.text) {\n const string = data.text.trim();\n\n if (string.startsWith(\"<svg\") && string.endsWith(\"</svg>\")) {\n // ignore SVG validation/normalization which will be done during image\n // initialization\n file = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.SVGStringToFile)(string);\n }\n }\n } // prefer spreadsheet data over image file (MS Office/Libre Office)\n\n\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isSupportedImageFile)(file) && !data.spreadsheet) {\n if (!this.isToolSupported(\"image\")) {\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageToolNotSupported\")\n });\n return;\n }\n\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n\n if (this.props.onPaste) {\n try {\n if ((await this.props.onPaste(data, event)) === false) {\n return;\n }\n } catch (error) {\n console.error(error);\n }\n }\n\n if (data.errorMessage) {\n this.setState({\n errorMessage: data.errorMessage\n });\n } else if (data.spreadsheet && !isPlainPaste) {\n this.setState({\n pasteDialog: {\n data: data.spreadsheet,\n shown: true\n }\n });\n } else if (data.elements) {\n const elements = data.programmaticAPI ? (0,_data_transform__WEBPACK_IMPORTED_MODULE_62__.convertToExcalidrawElements)(data.elements) : data.elements; // TODO remove formatting from elements if isPlainPaste\n\n this.addElementsFromPasteOrLibrary({\n elements,\n files: data.files || null,\n position: \"cursor\",\n retainSeed: isPlainPaste\n });\n } else if (data.text) {\n if (data.text && (0,_mermaid__WEBPACK_IMPORTED_MODULE_92__.isMaybeMermaidDefinition)(data.text)) {\n const api = await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! @zsviczian/mermaid-to-excalidraw */ \"../../node_modules/@zsviczian/mermaid-to-excalidraw/dist/index.js\")); //zsviczian\n\n try {\n const {\n elements: skeletonElements,\n files\n } = await api.parseMermaidToExcalidraw(data.text, {\n //zsviczian reverting https://github.com/excalidraw/excalidraw/pull/8226\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_FONT_SIZE\n }); //await api.parseMermaidToExcalidraw(data.text);\n\n const elements = (0,_data_transform__WEBPACK_IMPORTED_MODULE_62__.convertToExcalidrawElements)(skeletonElements, {\n regenerateIds: true\n });\n this.addElementsFromPasteOrLibrary({\n elements,\n files,\n position: \"cursor\"\n });\n return;\n } catch (err) {\n console.warn(`parsing pasted text as mermaid definition failed: ${err.message}`);\n }\n }\n\n const nonEmptyLines = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.normalizeEOL)(data.text).split(/\\n+/).map(s => s.trim()).filter(Boolean);\n const embbeddableUrls = nonEmptyLines.map(str => (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.maybeParseEmbedSrc)(str)).filter(string => {\n var _a;\n\n return (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.embeddableURLValidator)(string, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(string) || ((_a = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)(string)) === null || _a === void 0 ? void 0 : _a.type) === \"video\");\n });\n\n if (!IS_PLAIN_PASTE && embbeddableUrls.length > 0 && // if there were non-embeddable text (lines) mixed in with embeddable\n // urls, ignore and paste as text\n embbeddableUrls.length === nonEmptyLines.length) {\n const embeddables = [];\n\n for (const url of embbeddableUrls) {\n const prevEmbeddable = embeddables[embeddables.length - 1];\n const embeddable = this.insertEmbeddableElement({\n sceneX: prevEmbeddable ? prevEmbeddable.x + prevEmbeddable.width + 20 : sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(url)\n });\n\n if (embeddable) {\n embeddables.push(embeddable);\n }\n }\n\n if (embeddables.length) {\n this.setState({\n selectedElementIds: Object.fromEntries(embeddables.map(embeddable => [embeddable.id, true]))\n });\n }\n\n return;\n }\n\n this.addTextFromPaste(data.text, isPlainPaste);\n }\n\n this.setActiveTool({\n type: \"selection\"\n });\n event === null || event === void 0 ? void 0 : event.preventDefault();\n });\n\n this.addElementsFromPasteOrLibrary = opts => {\n let elements = opts.elements.map((el, _, elements) => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(el)) {\n const startEndElements = [el.startBinding && elements.find(l => {\n var _a;\n\n return l.id === ((_a = el.startBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n }), el.endBinding && elements.find(l => {\n var _a;\n\n return l.id === ((_a = el.endBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n })];\n const startBinding = startEndElements[0] ? el.startBinding : null;\n const endBinding = startEndElements[1] ? el.endBinding : null;\n return Object.assign(Object.assign({}, el), (0,_element_routing__WEBPACK_IMPORTED_MODULE_95__.updateElbowArrow)(Object.assign(Object.assign({}, el), {\n startBinding,\n endBinding\n }), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.toBrandedType)(new Map(startEndElements.filter(x => x != null).map(el => [el.id, el]))), [el.points[0], el.points[el.points.length - 1]]));\n }\n\n return el;\n });\n elements = (0,_data_restore__WEBPACK_IMPORTED_MODULE_15__.restoreElements)(elements, null, undefined);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(elements);\n const elementsCenterX = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(minX, maxX) / 2;\n const elementsCenterY = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(minY, maxY) / 2;\n const clientX = typeof opts.position === \"object\" ? opts.position.clientX : opts.position === \"cursor\" ? this.lastViewportPosition.x : this.state.width / 2 + this.state.offsetLeft;\n const clientY = typeof opts.position === \"object\" ? opts.position.clientY : opts.position === \"cursor\" ? this.lastViewportPosition.y : this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const dx = x - elementsCenterX;\n const dy = y - elementsCenterY;\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(dx, dy, this.getEffectiveGridSize());\n const newElements = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.duplicateElements)(elements.map(element => {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n x: element.x + gridX - minX,\n y: element.y + gridY - minY\n });\n }), {\n randomizeSeed: !opts.retainSeed\n });\n const prevElements = this.scene.getElementsIncludingDeleted();\n const nextElements = [...prevElements, ...newElements];\n (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncMovedIndices)(nextElements, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(newElements));\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x,\n y\n });\n\n if (topLayerFrame) {\n const eligibleElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.filterElementsEligibleAsFrameChildren)(newElements, topLayerFrame);\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(nextElements, eligibleElements, topLayerFrame);\n }\n\n this.scene.replaceAllElements(nextElements);\n newElements.forEach(newElement => {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(newElement) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(newElement)) {\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(newElement, this.scene.getElementsMapIncludingDeleted());\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.redrawTextBoundingBox)(newElement, container, this.scene.getElementsMapIncludingDeleted());\n }\n }); // paste event may not fire FontFace loadingdone event in Safari, hence loading font faces manually\n\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.isSafari) {\n _fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts.loadElementsFonts(newElements).then(fontFaces => {\n this.fonts.onLoaded(fontFaces);\n });\n }\n\n if (opts.files) {\n this.addMissingFiles(opts.files);\n }\n\n this.store.shouldCaptureIncrement();\n const nextElementsToSelect = (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.excludeElementsInFramesFromSelection)(newElements);\n this.setState(Object.assign(Object.assign(Object.assign({}, this.state), {\n // keep sidebar (presumably the library) open if it's docked and\n // can fit.\n //\n // Note, we should close the sidebar only if we're dropping items\n // from library, not when pasting from clipboard. Alas.\n openSidebar: this.state.openSidebar && this.device.editor.canFitSidebar && _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.get(_Sidebar_Sidebar__WEBPACK_IMPORTED_MODULE_63__.isSidebarDockedAtom) ? this.state.openSidebar : null\n }), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: null,\n selectedElementIds: nextElementsToSelect.reduce((acc, element) => {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(element)) {\n acc[element.id] = true;\n }\n\n return acc;\n }, {})\n }, this.scene.getNonDeletedElements(), this.state, this)), () => {\n if (opts.files) {\n this.addNewImagesToImageCache();\n }\n });\n this.setActiveTool({\n type: \"selection\"\n });\n\n if (opts.fitToContent) {\n this.scrollToContent(newElements, {\n fitToContent: true,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n };\n\n this.setAppState = (state, callback) => {\n this.setState(state, callback);\n };\n\n this.removePointer = event => {\n if (touchTimeout) {\n this.resetContextMenuTimer();\n }\n\n gesture.pointers.delete(event.pointerId);\n };\n\n this.toggleLock = (source = \"ui\") => {\n if (!this.state.activeTool.locked) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", \"toggleLock\", `${source} (${this.device.editor.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n this.setState(prevState => {\n return {\n activeTool: Object.assign(Object.assign(Object.assign({}, prevState.activeTool), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, prevState.activeTool.locked ? {\n type: \"selection\"\n } : prevState.activeTool)), {\n locked: !prevState.activeTool.locked\n })\n };\n });\n };\n\n this.updateFrameRendering = opts => {\n this.setState(prevState => {\n var _a, _b, _c, _d;\n\n const next = typeof opts === \"function\" ? opts(prevState.frameRendering) : opts;\n return {\n frameRendering: {\n enabled: (_a = next === null || next === void 0 ? void 0 : next.enabled) !== null && _a !== void 0 ? _a : prevState.frameRendering.enabled,\n clip: (_b = next === null || next === void 0 ? void 0 : next.clip) !== null && _b !== void 0 ? _b : prevState.frameRendering.clip,\n name: (_c = next === null || next === void 0 ? void 0 : next.name) !== null && _c !== void 0 ? _c : prevState.frameRendering.name,\n outline: (_d = next === null || next === void 0 ? void 0 : next.outline) !== null && _d !== void 0 ? _d : prevState.frameRendering.outline\n }\n };\n });\n };\n\n this.togglePenMode = force => {\n this.setState(prevState => {\n return {\n penMode: force !== null && force !== void 0 ? force : !prevState.penMode,\n penDetected: true\n };\n });\n };\n\n this.onHandToolToggle = () => {\n //zsviczian added timeout because button won't select otherwise\n setTimeout(() => this.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleHandTool));\n };\n /**\n * Zooms on canvas viewport center\n */\n\n\n this.zoomCanvas = (\n /**\n * Decimal fraction, auto-clamped between MIN_ZOOM and MAX_ZOOM.\n * 1 = 100% zoom, 2 = 200% zoom, 0.5 = 50% zoom\n */\n value) => {\n this.setState(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: this.state.width / 2 + this.state.offsetLeft,\n viewportY: this.state.height / 2 + this.state.offsetTop,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(value)\n }, this.state)));\n };\n\n this.cancelInProgressAnimation = null;\n\n this.scrollToContent = (target = this.scene.getNonDeletedElements(), opts) => {\n var _a, _b;\n\n (_a = this.cancelInProgressAnimation) === null || _a === void 0 ? void 0 : _a.call(this); // convert provided target into ExcalidrawElement[] if necessary\n\n const targetElements = Array.isArray(target) ? target : [target];\n let zoom = this.state.zoom;\n let scrollX = this.state.scrollX;\n let scrollY = this.state.scrollY;\n\n if ((opts === null || opts === void 0 ? void 0 : opts.fitToContent) || (opts === null || opts === void 0 ? void 0 : opts.fitToViewport)) {\n const {\n appState\n } = (0,_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.zoomToFit)({\n canvasOffsets: opts.canvasOffsets,\n targetElements,\n appState: this.state,\n fitToViewport: !!(opts === null || opts === void 0 ? void 0 : opts.fitToViewport),\n viewportZoomFactor: opts === null || opts === void 0 ? void 0 : opts.viewportZoomFactor,\n minZoom: opts === null || opts === void 0 ? void 0 : opts.minZoom,\n maxZoom: opts === null || opts === void 0 ? void 0 : opts.maxZoom\n });\n zoom = appState.zoom;\n scrollX = appState.scrollX;\n scrollY = appState.scrollY;\n } else {\n // compute only the viewport location, without any zoom adjustment\n const scroll = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.calculateScrollCenter)(targetElements, this.state);\n scrollX = scroll.scrollX;\n scrollY = scroll.scrollY;\n } // when animating, we use RequestAnimationFrame to prevent the animation\n // from slowing down other processes\n\n\n if (opts === null || opts === void 0 ? void 0 : opts.animate) {\n const origScrollX = this.state.scrollX;\n const origScrollY = this.state.scrollY;\n const origZoom = this.state.zoom.value;\n const cancel = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeToValuesRAF)({\n fromValues: {\n scrollX: origScrollX,\n scrollY: origScrollY,\n zoom: origZoom\n },\n toValues: {\n scrollX,\n scrollY,\n zoom: zoom.value\n },\n interpolateValue: (from, to, progress, key) => {\n // for zoom, use different easing\n if (key === \"zoom\") {\n return from * Math.pow(to / from, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.easeOut)(progress));\n } // handle using default\n\n\n return undefined;\n },\n onStep: ({\n scrollX,\n scrollY,\n zoom\n }) => {\n this.setState({\n scrollX,\n scrollY,\n zoom: {\n value: zoom\n }\n });\n },\n onStart: () => {\n this.setState({\n shouldCacheIgnoreZoom: true\n });\n },\n onEnd: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n onCancel: () => {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n },\n duration: (_b = opts === null || opts === void 0 ? void 0 : opts.duration) !== null && _b !== void 0 ? _b : 500\n });\n\n this.cancelInProgressAnimation = () => {\n cancel();\n this.cancelInProgressAnimation = null;\n };\n } else {\n this.setState({\n scrollX,\n scrollY,\n zoom\n });\n }\n };\n\n this.maybeUnfollowRemoteUser = () => {\n if (this.state.userToFollow) {\n this.setState({\n userToFollow: null\n });\n }\n };\n /** use when changing scrollX/scrollY/zoom based on user interaction */\n\n\n this.translateCanvas = state => {\n var _a;\n\n (_a = this.cancelInProgressAnimation) === null || _a === void 0 ? void 0 : _a.call(this);\n this.maybeUnfollowRemoteUser();\n this.setState(state);\n }; //zsviczian\n\n\n this.zoomToFit = (target = this.scene.getNonDeletedElements(), maxZoom, //null will zoom to max based on viewport\n margin = 0.03) => {\n if (typeof maxZoom === \"undefined\") {\n //zsviczian\n maxZoom = (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.getMaxZoom)();\n }\n\n if (!target) {\n target = this.scene.getNonDeletedElements();\n }\n\n if (target.length === 0) {\n maxZoom = 1;\n }\n\n this.setState((0,_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.zoomToFitElements)(target, this.state, false, this, maxZoom, margin).appState);\n }; //zsviczian\n\n\n this.startLineEditor = (el, selectedPointsIndices = null) => {\n if (!el || !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(el)) {\n return;\n }\n\n const editingLinearElement = new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(el);\n this.setState({\n selectedLinearElement: editingLinearElement,\n editingLinearElement: Object.assign(Object.assign({}, editingLinearElement), {\n selectedPointsIndices\n })\n });\n }; //zsviczian\n\n\n this.updateContainerSize = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(containers => {\n containers.forEach(el => {\n const [x, y] = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(el.x + el.width, el.y + el.height), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(el.x + el.width / 2, el.y + el.height / 2), el.angle);\n (0,_element_resizeElements__WEBPACK_IMPORTED_MODULE_89__.resizeSingleElement)(new Map().set(el.id, el), false, el, this.scene.getElementsMapIncludingDeleted(), \"se\", true, x, y);\n });\n });\n\n this.setToast = toast => {\n this.setState({\n toast\n });\n };\n\n this.restoreFileFromShare = async () => {\n try {\n const webShareTargetCache = await caches.open(\"web-share-target\");\n const response = await webShareTargetCache.match(\"shared-file\");\n\n if (response) {\n const blob = await response.blob();\n const file = new File([blob], blob.name || \"\", {\n type: blob.type\n });\n this.loadFileToCanvas(file, null);\n await webShareTargetCache.delete(\"shared-file\");\n window.history.replaceState(null, _constants__WEBPACK_IMPORTED_MODULE_12__.APP_NAME, window.location.pathname);\n }\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n };\n /**\n * adds supplied files to existing files in the appState.\n * NOTE if file already exists in editor state, the file data is not updated\n * */\n\n\n this.addFiles = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(files => {\n const {\n addedFiles\n } = this.addMissingFiles(files);\n this.clearImageShapeCache(addedFiles);\n this.scene.triggerUpdate();\n this.addNewImagesToImageCache();\n }); //zsviczian https://github.com/zsviczian/excalibrain/issues/9\n\n this.setMobileModeAllowed = allow => {\n const {\n width: editorWidth,\n height: editorHeight\n } = this.excalidrawContainerRef.current.getBoundingClientRect();\n this.allowMobileMode = allow;\n const prevEditorState = this.device.editor;\n let nextEditorState;\n\n if (allow) {\n nextEditorState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevEditorState, {\n isMobile: this.isMobileBreakpoint(editorWidth, editorHeight)\n });\n } else {\n nextEditorState = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(prevEditorState, {\n isMobile: false //must test this\n\n });\n }\n\n if (prevEditorState !== nextEditorState) {\n this.device = Object.assign(Object.assign({}, this.device), {\n editor: nextEditorState\n });\n this.forceUpdate();\n }\n }; //zsviczian\n\n\n this.debounceClearHighlightSearchResults = false;\n\n this.selectElements = (elements, highlightSearchResult = false) => {\n //zsviczian\n if (highlightSearchResult) {\n this.debounceClearHighlightSearchResults = true;\n setTimeout(() => {\n this.debounceClearHighlightSearchResults = false;\n }, 500);\n }\n\n this.updateScene({\n appState: Object.assign(Object.assign({}, this.state), {\n editingGroupId: null,\n selectedElementIds: elements.reduce((map, element) => {\n map[element.id] = true;\n return map;\n }, {}),\n highlightSearchResult\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.NONE,\n forceFlushSync: true\n });\n }; //zsviczian\n\n\n this.bringToFront = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionBringToFront.perform(this.scene.getNonDeletedElements(), this.state));\n }; //zsviczian\n\n\n this.bringForward = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionBringForward.perform(this.scene.getNonDeletedElements(), this.state));\n }; //zsviczian\n\n\n this.sendToBack = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionSendToBack.perform(this.scene.getNonDeletedElements(), this.state));\n }; //zsviczian\n\n\n this.sendBackward = elements => {\n this.selectElements(elements);\n this.updateScene(_actions__WEBPACK_IMPORTED_MODULE_5__.actionSendBackward.perform(this.scene.getNonDeletedElements(), this.state));\n };\n\n this.addMissingFiles = (files, replace = false) => {\n var _a;\n\n const nextFiles = replace ? {} : Object.assign({}, this.files);\n const addedFiles = {};\n\n const _files = Array.isArray(files) ? files : Object.values(files);\n\n for (const fileData of _files) {\n if (nextFiles[fileData.id]) {\n continue;\n }\n\n addedFiles[fileData.id] = fileData;\n nextFiles[fileData.id] = fileData;\n\n if (fileData.mimeType === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n const restoredDataURL = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getDataURL_sync)((0,_element_image__WEBPACK_IMPORTED_MODULE_41__.normalizeSVG)((0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.dataURLToString)(fileData.dataURL)), _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg);\n\n if (fileData.dataURL !== restoredDataURL) {\n // bump version so persistence layer can update the store\n fileData.version = ((_a = fileData.version) !== null && _a !== void 0 ? _a : 1) + 1;\n fileData.dataURL = restoredDataURL;\n }\n }\n }\n\n this.files = nextFiles;\n return {\n addedFiles\n };\n };\n\n this.updateScene = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(sceneData => {\n var _a;\n\n const nextElements = (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncInvalidIndices)((_a = sceneData.elements) !== null && _a !== void 0 ? _a : []);\n\n if (sceneData.storeAction && sceneData.storeAction !== _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.NONE) {\n const prevCommittedAppState = this.store.snapshot.appState;\n const prevCommittedElements = this.store.snapshot.elements;\n const nextCommittedAppState = sceneData.appState ? Object.assign({}, prevCommittedAppState, sceneData.appState) // new instance, with partial appstate applied to previously captured one, including hidden prop inside `prevCommittedAppState`\n : prevCommittedAppState;\n const nextCommittedElements = sceneData.elements ? this.store.filterUncomittedElements(this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(nextElements)) : prevCommittedElements; // WARN: store action always performs deep clone of changed elements, for ephemeral remote updates (i.e. remote dragging, resizing, drawing) we might consider doing something smarter\n // do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well\n\n if (sceneData.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE) {\n this.store.captureIncrement(nextCommittedElements, nextCommittedAppState);\n } else if (sceneData.storeAction === _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE) {\n this.store.updateSnapshot(nextCommittedElements, nextCommittedAppState);\n }\n } //zsviczian forceFlushSync is set to true in ExcalidrawView.updateScene.\n //without this e.g. text search did not select the elements\n\n\n if (sceneData.forceFlushSync === true) {\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n if (sceneData.appState) {\n this.setState(sceneData.appState);\n }\n });\n } else if (sceneData.appState) {\n this.setState(sceneData.appState);\n }\n\n if (sceneData.elements) {\n this.scene.replaceAllElements(nextElements);\n }\n\n if (sceneData.collaborators) {\n this.setState({\n collaborators: sceneData.collaborators\n });\n }\n });\n\n this.triggerRender = (\n /** force always re-renders canvas even if no change */\n force) => {\n if (force === true) {\n this.scene.triggerUpdate();\n } else {\n this.setState({});\n }\n };\n /**\n * @returns whether the menu was toggled on or off\n */\n\n\n this.toggleSidebar = ({\n name,\n tab,\n force\n }) => {\n var _a, _b;\n\n let nextName;\n\n if (force === undefined) {\n nextName = ((_a = this.state.openSidebar) === null || _a === void 0 ? void 0 : _a.name) === name && ((_b = this.state.openSidebar) === null || _b === void 0 ? void 0 : _b.tab) === tab ? null : name;\n } else {\n nextName = force ? name : null;\n }\n\n const nextState = nextName ? {\n name: nextName\n } : null;\n\n if (nextState && tab) {\n nextState.tab = tab;\n }\n\n this.setState({\n openSidebar: nextState\n });\n return !!nextName;\n };\n\n this.updateCurrentCursorPosition = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n this.lastViewportPosition.x = event.clientX;\n this.lastViewportPosition.y = event.clientY;\n });\n\n this.getEditorUIOffsets = () => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;\n\n const toolbarBottom = ((_e = (_d = (_c = (_b = (_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.querySelector(\".App-toolbar\")) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect()) === null || _d === void 0 ? void 0 : _d.bottom) !== null && _e !== void 0 ? _e : 0) - this.state.offsetTop;\n const sidebarRect = (_h = (_g = (_f = this.excalidrawContainerRef) === null || _f === void 0 ? void 0 : _f.current) === null || _g === void 0 ? void 0 : _g.querySelector(\".sidebar\")) === null || _h === void 0 ? void 0 : _h.getBoundingClientRect();\n const propertiesPanelRect = (_l = (_k = (_j = this.excalidrawContainerRef) === null || _j === void 0 ? void 0 : _j.current) === null || _k === void 0 ? void 0 : _k.querySelector(\".App-menu__left\")) === null || _l === void 0 ? void 0 : _l.getBoundingClientRect();\n const PADDING = 16;\n\n const adjustRectValueForOffset = ( //zsviczian https://github.com/excalidraw/excalidraw/issues/8561\n value, fallback) => (value !== null && value !== void 0 ? value : fallback + this.state.offsetLeft) - this.state.offsetLeft;\n\n return (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.getLanguage)().rtl ? {\n top: toolbarBottom + PADDING,\n right: Math.max(this.state.width - adjustRectValueForOffset( //zsivczian\n propertiesPanelRect === null || propertiesPanelRect === void 0 ? void 0 : propertiesPanelRect.left, this.state.width), 0) + PADDING,\n bottom: PADDING,\n left: //zsivczian\n Math.max(adjustRectValueForOffset(sidebarRect === null || sidebarRect === void 0 ? void 0 : sidebarRect.right, 0), 0) + PADDING\n } : {\n top: toolbarBottom + PADDING,\n right: Math.max(this.state.width - adjustRectValueForOffset(sidebarRect === null || sidebarRect === void 0 ? void 0 : sidebarRect.left, this.state.width) + //zsivczian\n PADDING, 0),\n bottom: PADDING,\n left: //zsivczian\n Math.max(adjustRectValueForOffset(propertiesPanelRect === null || propertiesPanelRect === void 0 ? void 0 : propertiesPanelRect.right, 0), 0) + PADDING\n };\n }; // Input handling\n\n\n this.onKeyDown = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a;\n\n if (this.state.activeTool.type === \"selection\" && this.state.resizingElement && (event.shiftKey || event.altKey)) {\n event.stopPropagation(); //zsviczian shift fires repeatedly causing slowdown when resizing sticky notes\n\n return;\n } // normalize `event.key` when CapsLock is pressed #2372\n\n\n if (\"Proxy\" in window && (!event.shiftKey && /^[A-Z]$/.test(event.key) || event.shiftKey && /^[a-z]$/.test(event.key))) {\n event = new Proxy(event, {\n get(ev, prop) {\n const value = ev[prop];\n\n if (typeof value === \"function\") {\n // fix for Proxies hijacking `this`\n return value.bind(ev);\n }\n\n return prop === \"key\" ? // CapsLock inverts capitalization based on ShiftKey, so invert\n // it back\n event.shiftKey ? ev.key.toUpperCase() : ev.key.toLowerCase() : value;\n }\n\n });\n }\n\n if (!(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isInputLike)(event.target)) {\n if ((event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) && this.state.croppingElementId) {\n this.finishImageCropping();\n return;\n }\n\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElementsMap(), this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(selectedElements[0]) && event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n this.startImageCropping(selectedElements[0]);\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE && this.flowChartCreator.isCreatingChart) {\n this.flowChartCreator.clear();\n this.triggerRender(true);\n return;\n }\n\n const arrowKeyPressed = (0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key);\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && arrowKeyPressed && !event.shiftKey) {\n event.preventDefault();\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElementsMap(), this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFlowchartNodeElement)(selectedElements[0])) {\n this.flowChartCreator.createNodes(selectedElements[0], this.scene.getNonDeletedElementsMap(), this.state, (0,_element_flowchart__WEBPACK_IMPORTED_MODULE_96__.getLinkDirectionFromKey)(event.key));\n }\n\n if (((_a = this.flowChartCreator.pendingNodes) === null || _a === void 0 ? void 0 : _a.length) && !(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementCompletelyInViewport)(this.flowChartCreator.pendingNodes, this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap(), this.getEditorUIOffsets())) {\n this.scrollToContent(this.flowChartCreator.pendingNodes, {\n animate: true,\n duration: 300,\n fitToContent: true,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n\n return;\n }\n\n if (event.altKey) {\n const selectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElementsMap(), this.state);\n\n if (selectedElements.length === 1 && arrowKeyPressed) {\n event.preventDefault();\n const nextId = this.flowChartNavigator.exploreByDirection(selectedElements[0], this.scene.getNonDeletedElementsMap(), (0,_element_flowchart__WEBPACK_IMPORTED_MODULE_96__.getLinkDirectionFromKey)(event.key));\n\n if (nextId) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [nextId]: true\n }, prevState)\n }));\n const nextNode = this.scene.getNonDeletedElementsMap().get(nextId);\n\n if (nextNode && !(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementCompletelyInViewport)([nextNode], this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap(), this.getEditorUIOffsets())) {\n this.scrollToContent(nextNode, {\n animate: true,\n duration: 300,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n }\n\n return;\n }\n }\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.P && !event.shiftKey && !event.altKey) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"commandPalette.shortcutHint\", {\n shortcut: (0,_actions_shortcuts__WEBPACK_IMPORTED_MODULE_88__.getShortcutFromShortcutName)(\"commandPalette\")\n })\n });\n event.preventDefault();\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.V) {\n IS_PLAIN_PASTE = event.shiftKey;\n clearTimeout(IS_PLAIN_PASTE_TIMER); // reset (100ms to be safe that we it runs after the ensuing\n // paste event). Though, technically unnecessary to reset since we\n // (re)set the flag before each paste event.\n\n IS_PLAIN_PASTE_TIMER = window.setTimeout(() => {\n IS_PLAIN_PASTE = false;\n }, 100);\n } // prevent browser zoom in input fields\n\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target)) {\n if (event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.MINUS || event.code === _keys__WEBPACK_IMPORTED_MODULE_26__.CODES.EQUAL) {\n event.preventDefault();\n return;\n }\n } // bail if\n\n\n if ( // inside an input\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isWritableElement)(event.target) && // unless pressing escape (finalize action)\n event.key !== _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ESCAPE || // or unless using arrows (to move between buttons)\n (0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key) && (0,_utils__WEBPACK_IMPORTED_MODULE_34__.isInputLike)(event.target)) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.QUESTION_MARK) {\n this.setState({\n openDialog: {\n name: \"help\"\n }\n });\n return;\n } else if (event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.E && event.shiftKey && event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n this.setState({\n openDialog: {\n name: \"imageExport\"\n }\n });\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_UP || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n let offset = (event.shiftKey ? this.state.width : this.state.height) / this.state.zoom.value;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.PAGE_DOWN) {\n offset = -offset;\n }\n\n if (event.shiftKey) {\n this.translateCanvas(state => ({\n scrollX: state.scrollX + offset\n }));\n } else {\n this.translateCanvas(state => ({\n scrollY: state.scrollY + offset\n }));\n }\n }\n\n if (this.actionManager.handleKeyDown(event)) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.K && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isLaserPointerActive)(this.state)) {\n this.setActiveTool({\n type: \"selection\"\n });\n } else {\n this.setActiveTool({\n type: \"laser\"\n });\n }\n\n return;\n }\n\n if (this.state.viewModeEnabled) {\n //revert to hand in case a key is pressed (K is handled above)\n if (event.key !== _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.K) {\n this.setActiveTool({\n type: \"selection\"\n });\n }\n\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: false\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n let selectedElements = this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n });\n const elbowArrow = selectedElements.find(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow);\n const arrowIdsToRemove = new Set();\n selectedElements.filter(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow).filter(arrow => {\n const startElementNotInSelection = arrow.startBinding && !selectedElements.some(el => {\n var _a;\n\n return el.id === ((_a = arrow.startBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n });\n const endElementNotInSelection = arrow.endBinding && !selectedElements.some(el => {\n var _a;\n\n return el.id === ((_a = arrow.endBinding) === null || _a === void 0 ? void 0 : _a.elementId);\n });\n return startElementNotInSelection || endElementNotInSelection;\n }).forEach(arrow => arrowIdsToRemove.add(arrow.id));\n selectedElements = selectedElements.filter(el => !arrowIdsToRemove.has(el.id));\n const step = this.getEffectiveGridSize() && (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT : this.getEffectiveGridSize()) || (event.shiftKey ? _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_SHIFT_TRANSLATE_AMOUNT : _constants__WEBPACK_IMPORTED_MODULE_12__.ELEMENT_TRANSLATE_AMOUNT);\n let offsetX = 0;\n let offsetY = 0;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_LEFT) {\n offsetX = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_RIGHT) {\n offsetX = step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_UP) {\n offsetY = -step;\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ARROW_DOWN) {\n offsetY = step;\n }\n\n selectedElements.forEach(element => {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n x: element.x + offsetX,\n y: element.y + offsetY\n });\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element, this.scene.getNonDeletedElementsMap(), {\n simultaneouslyUpdated: selectedElements\n });\n });\n this.setState({\n suggestedBindings: (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getSuggestedBindingsForArrows)(selectedElements.filter(element => element.id !== (elbowArrow === null || elbowArrow === void 0 ? void 0 : elbowArrow.id) || step !== 0), this.scene.getNonDeletedElementsMap())\n });\n event.preventDefault();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ENTER) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n const selectedElement = selectedElements[0];\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElement)) {\n if (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id) {\n this.store.shouldCaptureIncrement();\n\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElement)) {\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElement)\n });\n }\n }\n }\n } else if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.isValidTextContainer)(selectedElement)) {\n let container;\n\n if (!(0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElement)) {\n container = selectedElement;\n }\n\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerCenter)(selectedElement, this.state, this.scene.getNonDeletedElementsMap());\n const sceneX = midPoint.x;\n const sceneY = midPoint.y;\n this.startTextEditing({\n sceneX,\n sceneY,\n container\n });\n event.preventDefault();\n return;\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(selectedElement)) {\n this.setState({\n editingFrame: selectedElement.id\n });\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(selectedElement)) {\n //zsviczian\n this.setState({\n activeEmbeddable: {\n element: selectedElement,\n state: \"active\"\n }\n });\n }\n }\n } else if (!event.ctrlKey && !event.altKey && !event.metaKey && !this.state.newElement && !this.state.selectionElement && !this.state.selectedElementsAreBeingDragged) {\n const shape = (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.findShapeByKey)(event.key);\n\n if (shape) {\n if (this.state.activeTool.type !== shape) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"toolbar\", shape, `keyboard (${this.device.editor.isMobile ? \"mobile\" : \"desktop\"})`);\n }\n\n if (shape === \"arrow\" && this.state.activeTool.type === \"arrow\") {\n this.setState(prevState => ({\n currentItemArrowType: prevState.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.sharp ? _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.round : prevState.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.round ? _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.elbow : _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.sharp\n }));\n }\n\n this.setActiveTool({\n type: shape\n });\n event.stopPropagation();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.Q) {\n this.toggleLock(\"keyboard\");\n event.stopPropagation();\n }\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE && gesture.pointers.size === 0) {\n isHoldingSpace = true;\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n event.preventDefault();\n }\n\n if ((event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (this.state.activeTool.type === \"selection\" && !selectedElements.length) {\n return;\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && ((0,_scene__WEBPACK_IMPORTED_MODULE_28__.hasBackground)(this.state.activeTool.type) || selectedElements.some(element => (0,_scene__WEBPACK_IMPORTED_MODULE_28__.hasBackground)(element.type)))) {\n this.setState({\n openPopup: \"elementBackground\"\n });\n event.stopPropagation();\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S) {\n this.setState({\n openPopup: \"elementStroke\"\n });\n event.stopPropagation();\n }\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && event.shiftKey && event.key.toLowerCase() === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.F) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (this.state.activeTool.type === \"selection\" && !selectedElements.length) {\n return;\n }\n\n if (this.state.activeTool.type === \"text\" || selectedElements.find(element => (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) || (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getBoundTextElement)(element, this.scene.getNonDeletedElementsMap()))) {\n event.preventDefault();\n this.setState({\n openPopup: \"fontFamily\"\n });\n }\n }\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.K && !event.altKey && !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (this.state.activeTool.type === \"laser\") {\n this.setActiveTool({\n type: \"selection\"\n });\n } else {\n this.setActiveTool({\n type: \"laser\"\n });\n }\n\n return;\n }\n\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.BACKSPACE || event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.DELETE)) {\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_ActiveConfirmDialog__WEBPACK_IMPORTED_MODULE_56__.activeConfirmDialogAtom, \"clearCanvas\");\n } // eye dropper\n // -----------------------------------------------------------------------\n\n\n const lowerCased = event.key.toLocaleLowerCase();\n const isPickingStroke = lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.S && event.shiftKey;\n const isPickingBackground = event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.I || lowerCased === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.G && event.shiftKey;\n\n if (isPickingStroke || isPickingBackground) {\n this.openEyeDropper({\n type: isPickingStroke ? \"stroke\" : \"background\"\n });\n } // -----------------------------------------------------------------------\n\n });\n this.onKeyUp = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n var _a, _b, _c, _d;\n\n if (event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.SPACE) {\n if (this.state.viewModeEnabled) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (this.state.activeTool.type === \"selection\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n isHoldingSpace = false;\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.isBindingEnabled) {\n this.setState({\n isBindingEnabled: true\n });\n }\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.isArrowKey)(event.key)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElements)(this.scene.getSelectedElements(this.state).filter(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement), this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements(), this.scene, (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state), (_b = (_a = this.state.selectedLinearElement) === null || _a === void 0 ? void 0 : _a.selectedPointsIndices) !== null && _b !== void 0 ? _b : []);\n this.setState({\n suggestedBindings: []\n });\n }\n\n if (!event.altKey) {\n if (this.flowChartNavigator.isExploring) {\n this.flowChartNavigator.clear();\n this.syncActionResult({\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n }\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (this.flowChartCreator.isCreatingChart) {\n if ((_c = this.flowChartCreator.pendingNodes) === null || _c === void 0 ? void 0 : _c.length) {\n this.scene.insertElements(this.flowChartCreator.pendingNodes);\n }\n\n const firstNode = (_d = this.flowChartCreator.pendingNodes) === null || _d === void 0 ? void 0 : _d[0];\n\n if (firstNode) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [firstNode.id]: true\n }, prevState)\n }));\n\n if (!(0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementCompletelyInViewport)([firstNode], this.canvas.width / window.devicePixelRatio, this.canvas.height / window.devicePixelRatio, {\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n zoom: this.state.zoom\n }, this.scene.getNonDeletedElementsMap(), this.getEditorUIOffsets())) {\n this.scrollToContent(firstNode, {\n animate: true,\n duration: 300,\n canvasOffsets: this.getEditorUIOffsets()\n });\n }\n }\n\n this.flowChartCreator.clear();\n this.syncActionResult({\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n });\n }\n }\n }); // We purposely widen the `tool` type so this helper can be called with\n // any tool without having to type check it\n\n this.isToolSupported = tool => {\n var _a;\n\n return ((_a = this.props.UIOptions.tools) === null || _a === void 0 ? void 0 : _a[tool]) !== false;\n };\n\n this.setActiveTool = tool => {\n var _a;\n\n if (!this.isToolSupported(tool.type)) {\n console.warn(`\"${tool.type}\" tool is disabled via \"UIOptions.canvasActions.tools.${tool.type}\"`);\n return;\n }\n\n const nextActiveTool = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, tool);\n\n if (nextActiveTool.type === \"hand\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (!isHoldingSpace) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_34__.isToolIcon)(document.activeElement)) {\n this.focusContainer();\n }\n\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElementType)(nextActiveTool.type)) {\n this.setState({\n suggestedBindings: []\n });\n }\n\n if (nextActiveTool.type === \"image\") {\n this.onImageAction({\n insertOnCanvasDirectly: (_a = tool.type === \"image\" && tool.insertOnCanvasDirectly) !== null && _a !== void 0 ? _a : false\n });\n }\n\n setTimeout(() => {\n this.setState(prevState => {\n const commonResets = {\n snapLines: prevState.snapLines.length ? [] : prevState.snapLines,\n originSnapOffset: null,\n activeEmbeddable: null\n };\n\n if (nextActiveTool.type === \"freedraw\") {\n this.store.shouldCaptureIncrement();\n }\n\n if (nextActiveTool.type !== \"selection\") {\n return Object.assign(Object.assign(Object.assign({}, prevState), {\n activeTool: nextActiveTool,\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextActiveTool.type === \"mermaid\" //zsviczian\n ? this.state.selectedElementIds : {}, prevState),\n selectedGroupIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, prevState),\n editingGroupId: null,\n multiElement: null\n }), commonResets);\n }\n\n return Object.assign(Object.assign(Object.assign({}, prevState), {\n activeTool: nextActiveTool\n }), commonResets);\n }); //zsviczian added timeout because button won't select otherwise\n });\n };\n\n this.setOpenDialog = dialogType => {\n this.setState({\n openDialog: dialogType\n });\n };\n\n this.setCursor = cursor => {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, cursor);\n };\n\n this.resetCursor = () => {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n };\n /**\n * returns whether user is making a gesture with >= 2 fingers (points)\n * on o touch screen (not on a trackpad). Currently only relates to Darwin\n * (iOS/iPadOS,MacOS), but may work on other devices in the future if\n * GestureEvent is standardized.\n */\n\n\n this.isTouchScreenMultiTouchGesture = () => {\n // we don't want to deselect when using trackpad, and multi-point gestures\n // only work on touch screens, so checking for >= pointers means we're on a\n // touchscreen\n return gesture.pointers.size >= 2;\n };\n\n this.getName = () => {\n return this.state.name || this.props.name || `${(0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.untitled\")}-${(0,_utils__WEBPACK_IMPORTED_MODULE_34__.getDateTime)()}`;\n }; // fires only on Safari\n\n\n this.onGestureStart = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n event.preventDefault(); // we only want to deselect on touch screens because user may have selected\n // elements by mistake while zooming\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null\n });\n }\n\n gesture.initialScale = this.state.zoom.value;\n }); // fires only on Safari\n\n this.onGestureChange = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n event.preventDefault(); // onGestureChange only has zoom factor but not the center.\n // If we're on iPad or iPhone, then we recognize multi-touch and will\n // zoom in at the right location in the touchmove handler\n // (handleCanvasPointerMove).\n //\n // On Macbook trackpad, we don't have those events so will zoom in at the\n // current location instead.\n //\n // As such, bail from this handler on touch devices.\n\n if (this.isTouchScreenMultiTouchGesture()) {\n return;\n }\n\n const initialScale = gesture.initialScale;\n\n if (initialScale) {\n this.setState(state => Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(initialScale * event.scale)\n }, state)));\n }\n }); // fires only on Safari\n\n this.onGestureEnd = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n event.preventDefault(); // reselect elements only on touch screens (see onGestureStart)\n\n if (this.isTouchScreenMultiTouchGesture()) {\n this.setState({\n previousSelectedElementIds: {},\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(this.state.previousSelectedElementIds, this.state)\n });\n }\n\n gesture.initialScale = null;\n });\n\n this.startTextEditing = ({\n sceneX,\n sceneY,\n insertAtParentCenter = true,\n container,\n autoEdit = true\n }) => {\n var _a, _b;\n\n let shouldBindToContainer = false;\n let parentCenterPosition = insertAtParentCenter && this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n\n if (container && parentCenterPosition) {\n const boundTextElementToContainer = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getBoundTextElement)(container, this.scene.getNonDeletedElementsMap());\n\n if (!boundTextElementToContainer) {\n shouldBindToContainer = true;\n }\n }\n\n let existingTextElement = null;\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(selectedElements[0])) {\n existingTextElement = selectedElements[0];\n } else if (container) {\n existingTextElement = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getBoundTextElement)(selectedElements[0], this.scene.getNonDeletedElementsMap());\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n } else {\n existingTextElement = this.getTextElementAtPosition(sceneX, sceneY);\n }\n\n const fontFamily = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.fontFamily) || this.state.currentItemFontFamily;\n const lineHeight = (existingTextElement === null || existingTextElement === void 0 ? void 0 : existingTextElement.lineHeight) || (0,_fonts__WEBPACK_IMPORTED_MODULE_49__.getLineHeight)(fontFamily);\n const fontSize = (0,_actions_actionProperties__WEBPACK_IMPORTED_MODULE_75__.getFontSize)(this.state.currentItemFontSize, this.state.zoom.value); //zsviczian\n\n if (!existingTextElement && shouldBindToContainer && container && !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(container)) {\n const fontString = {\n fontSize,\n fontFamily\n };\n const minWidth = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getApproxMinLineWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_34__.getFontString)(fontString), lineHeight);\n const minHeight = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getApproxMinLineHeight)(fontSize, lineHeight);\n const newHeight = Math.max(container.height, minHeight);\n const newWidth = Math.max(container.width, minWidth);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n height: newHeight,\n width: newWidth\n });\n sceneX = container.x + newWidth / 2;\n sceneY = container.y + newHeight / 2;\n\n if (parentCenterPosition) {\n parentCenterPosition = this.getTextWysiwygSnappedToCenterPosition(sceneX, sceneY, this.state, container);\n }\n }\n\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: sceneX,\n y: sceneY\n });\n /*const shouldWrapText = !shouldBindToContainer && //zsviczian\n this.lastPointerDownEvent?.pointerType === \"pen\";\n const [x1, , x2] = getVisibleSceneBounds(this.state); //zsviczian\n const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.85, 800), 200); //zsviczian*/\n\n const element = existingTextElement ? existingTextElement : (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)({\n x: parentCenterPosition ? parentCenterPosition.elementCenterX : sceneX,\n y: parentCenterPosition ? parentCenterPosition.elementCenterY : sceneY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text: \"\",\n rawText: \"\",\n fontSize,\n fontFamily,\n textAlign: parentCenterPosition ? \"center\" : this.state.currentItemTextAlign,\n verticalAlign: parentCenterPosition ? _constants__WEBPACK_IMPORTED_MODULE_12__.VERTICAL_ALIGN.MIDDLE : _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n containerId: shouldBindToContainer ? container === null || container === void 0 ? void 0 : container.id : undefined,\n groupIds: (_a = container === null || container === void 0 ? void 0 : container.groupIds) !== null && _a !== void 0 ? _a : [],\n lineHeight,\n angle: (_b = container === null || container === void 0 ? void 0 : container.angle) !== null && _b !== void 0 ? _b : 0,\n frameId: topLayerFrame ? topLayerFrame.id : null\n /*...shouldWrapText //zsviczian\n ? {\n width: maxTextWidth,\n autoResize: false,\n }\n : {},*/\n\n });\n\n if (!existingTextElement && shouldBindToContainer && container) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: element.id\n })\n });\n }\n\n this.setState({\n editingTextElement: element\n });\n\n if (!existingTextElement) {\n if (container && shouldBindToContainer) {\n const containerIndex = this.scene.getElementIndex(container.id);\n this.scene.insertElementAtIndex(element, containerIndex + 1);\n } else {\n this.scene.insertElement(element);\n }\n }\n\n if (autoEdit || existingTextElement || container) {\n this.handleTextWysiwyg(element, {\n isExistingElement: !!existingTextElement\n });\n } else {\n this.setState({\n newElement: element,\n multiElement: null\n });\n }\n };\n\n this.debounceDoubleClickTimestamp = 0; //zsviczian\n\n this.startImageCropping = image => {\n this.store.shouldCaptureIncrement();\n this.setState({\n croppingElementId: image.id\n });\n };\n\n this.finishImageCropping = () => {\n if (this.state.croppingElementId) {\n this.store.shouldCaptureIncrement();\n this.setState({\n croppingElementId: null\n });\n }\n };\n\n this.handleCanvasDoubleClick = event => {\n var _a; // case: double-clicking with arrow/line tool selected would both create\n // text and enter multiElement mode\n\n\n if (this.state.multiElement) {\n return;\n }\n\n if ( //zsviczian - double click eraser\n this.state.penMode && (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.allowDoubleTapEraser)() && ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a.pointerType) === \"touch\" && this.state.activeTool.type !== \"selection\") {\n const now = Date.now();\n\n if (now - this.debounceDoubleClickTimestamp < 200) {\n //handleCanvasDoubleClick click fires twice in case of touch.\n //Once from the onTouchStart event handler, once from the double click event handler\n return;\n }\n\n this.debounceDoubleClickTimestamp = now;\n this.updateScene(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleEraserTool.perform([], this.state));\n return;\n } // zsviczian - end\n // we should only be able to double click when mode is selection\n\n\n if (this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0])) {\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && (!this.state.editingLinearElement || this.state.editingLinearElement.elementId !== selectedElements[0].id) && !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0])) {\n this.store.shouldCaptureIncrement();\n this.setState({\n editingLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(selectedElements[0])\n });\n return;\n }\n }\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(selectedElements[0])) {\n this.startImageCropping(selectedElements[0]);\n return;\n }\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n let {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedGroupIds = (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIds)(this.state);\n\n if (selectedGroupIds.length > 0) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n const selectedGroupId = hitElement && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getSelectedGroupIdForElement)(hitElement, this.state.selectedGroupIds);\n\n if (selectedGroupId) {\n this.store.shouldCaptureIncrement();\n this.setState(prevState => Object.assign(Object.assign({}, prevState), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: selectedGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)));\n return;\n }\n }\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n\n if (!event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] && !this.state.viewModeEnabled) {\n const hitElement = this.getElementAtPosition(sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement)) {\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"active\"\n }\n });\n return;\n }\n\n const container = this.getTextBindableContainerAtPosition(sceneX, sceneY);\n\n if (container) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(container) || !(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isTransparent)(container.backgroundColor) || (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x: sceneX,\n y: sceneY,\n element: container,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(container, this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold()\n })) {\n const midPoint = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerCenter)(container, this.state, this.scene.getNonDeletedElementsMap());\n sceneX = midPoint.x;\n sceneY = midPoint.y;\n }\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container\n });\n }\n };\n\n this.getElementLinkAtPosition = (scenePointer, hitElement) => {\n // Reversing so we traverse the elements in decreasing order\n // of z-index\n const elements = this.scene.getNonDeletedElements().slice().reverse();\n let hitElementIndex = Infinity;\n return elements.find((element, index) => {\n if (hitElement && element.id === hitElement.id) {\n hitElementIndex = index;\n }\n\n return element.link && index <= hitElementIndex && (0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLink)(element, this.scene.getNonDeletedElementsMap(), this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointer.x, scenePointer.y), this.device.editor.isMobile);\n });\n };\n\n this.redirectToLink = (event, isTouchScreen) => {\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(this.lastPointerDownEvent.clientX, this.lastPointerDownEvent.clientY), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(this.lastPointerUpEvent.clientX, this.lastPointerUpEvent.clientY));\n\n if (!this.hitLinkElement || // For touch screen allow dragging threshold else strict check\n isTouchScreen && draggedDistance > _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD || !isTouchScreen && draggedDistance !== 0) {\n return;\n }\n\n const lastPointerDownCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(this.lastPointerDownEvent, this.state);\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const lastPointerDownHittingLinkIcon = (0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLink)(this.hitLinkElement, elementsMap, this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastPointerDownCoords.x, lastPointerDownCoords.y), this.device.editor.isMobile);\n const lastPointerUpCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(this.lastPointerUpEvent, this.state);\n const lastPointerUpHittingLinkIcon = (0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLink)(this.hitLinkElement, elementsMap, this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastPointerUpCoords.x, lastPointerUpCoords.y), this.device.editor.isMobile);\n\n if (lastPointerDownHittingLinkIcon && lastPointerUpHittingLinkIcon) {\n let url = this.hitLinkElement.link;\n\n if (url) {\n url = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(url);\n let customEvent;\n\n if (this.props.onLinkOpen) {\n customEvent = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.wrapEvent)(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.EXCALIDRAW_LINK, event.nativeEvent);\n this.props.onLinkOpen(Object.assign(Object.assign({}, this.hitLinkElement), {\n link: url\n }), customEvent);\n }\n\n if (!(customEvent === null || customEvent === void 0 ? void 0 : customEvent.defaultPrevented)) {\n const target = (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.isLocalLink)(url) ? \"_self\" : \"_blank\";\n const newWindow = window.open(undefined, target); // https://mathiasbynens.github.io/rel-noopener/\n\n if (newWindow) {\n newWindow.opener = null;\n newWindow.location = url;\n }\n }\n }\n }\n };\n\n this.getTopLayerFrameAtSceneCoords = sceneCoords => {\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const frames = this.scene.getNonDeletedFramesLikes().filter(frame => (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)(sceneCoords, frame, elementsMap));\n return frames.length ? frames[frames.length - 1] : null;\n };\n\n this.handleCanvasPointerMove = event => {\n var _a, _b;\n\n this.savePointer(event.clientX, event.clientY, this.state.cursorButton);\n this.lastPointerMoveEvent = event.nativeEvent;\n\n if (gesture.pointers.has(event.pointerId)) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n }\n\n const initialScale = gesture.initialScale;\n\n if (gesture.pointers.size === 2 && gesture.lastCenter && initialScale && gesture.initialDistance) {\n const center = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n const deltaX = center.x - gesture.lastCenter.x;\n const deltaY = center.y - gesture.lastCenter.y;\n gesture.lastCenter = center;\n const distance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n const scaleFactor = !this.state.allowPinchZoom && //zsviczian\n this.state.activeTool.type === \"freedraw\" && this.state.penMode ? 1 : distance / gesture.initialDistance;\n const nextZoom = scaleFactor ? (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(initialScale * scaleFactor) : this.state.zoom.value;\n this.setState(state => {\n const zoomState = (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: center.x,\n viewportY: center.y,\n nextZoom\n }, state);\n this.translateCanvas({\n zoom: zoomState.zoom,\n // 2x multiplier is just a magic number that makes this work correctly\n // on touchscreen devices (note: if we get report that panning is slower/faster\n // than actual movement, consider swapping with devicePixelRatio)\n scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),\n scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),\n shouldCacheIgnoreZoom: true\n });\n });\n this.resetShouldCacheIgnoreZoomDebounced();\n } else {\n gesture.lastCenter = gesture.initialDistance = gesture.initialScale = null;\n }\n\n if (isHoldingSpace || isPanning || isDraggingScrollBar || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state)) {\n return;\n }\n\n const isPointerOverScrollBars = (0,_scene_scrollbars__WEBPACK_IMPORTED_MODULE_85__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop);\n const isOverScrollBar = isPointerOverScrollBars.isOverEither;\n const isPenFreedraw = this.state.activeTool.type === \"freedraw\" && event.pointerType === \"pen\"; //zsviczian\n\n if (!this.state.newElement && !this.state.selectionElement && !this.state.selectedElementsAreBeingDragged && !this.state.multiElement) {\n if (isOverScrollBar) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n } else if (isPenFreedraw && this.interactiveCanvas && (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.hideFreedrawPenmodeCursor)()) {\n //zsviczian https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/1659\n this.interactiveCanvas.style.cursor = \"none\";\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const {\n x: scenePointerX,\n y: scenePointerY\n } = scenePointer;\n\n if (!this.state.newElement && (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isActiveToolNonLinearSnappable)(this.state.activeTool.type)) {\n const {\n originOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getSnapLinesAtPointer)(this.scene.getNonDeletedElements(), this, {\n x: scenePointerX,\n y: scenePointerY\n }, event, this.scene.getNonDeletedElementsMap());\n this.setState(prevState => {\n const nextSnapLines = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateStable)(prevState.snapLines, snapLines);\n const nextOriginOffset = prevState.originSnapOffset ? (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateStable)(prevState.originSnapOffset, originOffset) : originOffset;\n\n if (prevState.snapLines === nextSnapLines && prevState.originSnapOffset === nextOriginOffset) {\n return null;\n }\n\n return {\n snapLines: nextSnapLines,\n originSnapOffset: nextOriginOffset\n };\n });\n } else if (!this.state.newElement && !this.state.selectedElementsAreBeingDragged && !this.state.selectionElement) {\n this.setState(prevState => {\n if (prevState.snapLines.length) {\n return {\n snapLines: []\n };\n }\n\n return null;\n });\n }\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerMove(event, scenePointerX, scenePointerY, this, this.scene.getNonDeletedElementsMap());\n\n if (editingLinearElement && editingLinearElement !== this.state.editingLinearElement) {\n // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n editingLinearElement\n });\n });\n }\n\n if ((editingLinearElement === null || editingLinearElement === void 0 ? void 0 : editingLinearElement.lastUncommittedPoint) != null) {\n this.maybeSuggestBindingAtCursor(scenePointer);\n } else {\n // causes stack overflow if not sync\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n suggestedBindings: []\n });\n });\n }\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElementType)(this.state.activeTool.type)) {\n // Hovering with a selected tool or creating new linear element via click\n // and point\n const {\n newElement\n } = this.state;\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(newElement, false)) {\n this.maybeSuggestBindingsForLinearElementAtCoords(newElement, [scenePointer], this.state.startBoundElement);\n } else {\n this.maybeSuggestBindingAtCursor(scenePointer);\n }\n }\n\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state;\n const {\n x: rx,\n y: ry\n } = multiElement;\n const {\n points,\n lastCommittedPoint\n } = multiElement;\n const lastPoint = points[points.length - 1];\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n\n if (lastPoint === lastCommittedPoint) {\n // if we haven't yet created a temp point and we're beyond commit-zone\n // threshold, add a point\n if ((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointerX - rx, scenePointerY - ry), lastPoint) >= _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointerX - rx, scenePointerY - ry)]\n }, false);\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER); // in this branch, we're inside the commit zone, and no uncommitted\n // point exists. Thus do nothing (don't add/remove points).\n }\n } else if (points.length > 2 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointerX - rx, scenePointerY - ry), lastCommittedPoint) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: points.slice(0, -1)\n }, false);\n } else {\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(scenePointerX, scenePointerY, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(multiElement) ? null : this.getEffectiveGridSize());\n const [lastCommittedX, lastCommittedY] = (_a = multiElement === null || multiElement === void 0 ? void 0 : multiElement.lastCommittedPoint) !== null && _a !== void 0 ? _a : [0, 0];\n let dxFromLastCommitted = gridX - rx - lastCommittedX;\n let dyFromLastCommitted = gridY - ry - lastCommittedY;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event)) {\n ({\n width: dxFromLastCommitted,\n height: dyFromLastCommitted\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)( // actual coordinate of the last committed point\n lastCommittedX + rx, lastCommittedY + ry, // cursor-grid coordinate\n gridX, gridY));\n }\n\n if ((0,_shapes__WEBPACK_IMPORTED_MODULE_31__.isPathALoop)(points, this.state.zoom.value)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(multiElement)) {\n (0,_element_routing__WEBPACK_IMPORTED_MODULE_95__.mutateElbowArrow)(multiElement, this.scene.getNonDeletedElementsMap(), [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastCommittedX + dxFromLastCommitted, lastCommittedY + dyFromLastCommitted)], undefined, undefined, {\n isDragging: true,\n informMutation: false\n });\n } else {\n // update last uncommitted point\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n points: [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(lastCommittedX + dxFromLastCommitted, lastCommittedY + dyFromLastCommitted)]\n }, false);\n } // in this path, we're mutating multiElement to reflect\n // how it will be after adding pointer position as the next point\n // trigger update here so that new element canvas renders again to reflect this\n\n\n this.triggerRender(false);\n }\n\n return;\n }\n\n const hasDeselectedButton = Boolean(event.buttons);\n\n if (hasDeselectedButton || this.state.activeTool.type !== \"selection\" && this.state.activeTool.type !== \"text\" && this.state.activeTool.type !== \"eraser\") {\n return;\n }\n\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !isOverScrollBar && !this.state.editingLinearElement) {\n // for linear elements, we'd like to prioritize point dragging over edge resizing\n // therefore, we update and check hovered point index first\n if (this.state.selectedLinearElement) {\n this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);\n }\n\n if ((!this.state.selectedLinearElement || this.state.selectedLinearElement.hoverPointIndex === -1) && !(selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0]))) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);\n\n if (elementWithTransformHandleType && elementWithTransformHandleType.transformHandleType) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)(elementWithTransformHandleType));\n return;\n }\n }\n } else if (selectedElements.length > 1 && !isOverScrollBar) {\n const transformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.device);\n\n if (transformHandleType) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCursorForResizingElement)({\n transformHandleType\n }));\n return;\n }\n }\n\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n return;\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n (0,_components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.showHyperlinkTooltip)(this.hitLinkElement, this.state, this.scene.getNonDeletedElementsMap());\n\n if (this.props.onLinkHover) {\n this.props.onLinkHover(this.hitLinkElement, event);\n } //zsviczian\n\n } else {\n (0,_components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.hideHyperlinkToolip)();\n\n if (hitElement && (hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement)) && this.state.selectedElementIds[hitElement.id] && !this.state.contextMenu && !this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: \"info\"\n });\n } else if (this.state.activeTool.type === \"text\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(hitElement) ? _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.TEXT : _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR);\n } else if (this.state.viewModeEnabled) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else if (isOverScrollBar) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n } else if (this.state.selectedLinearElement) {\n this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);\n } else if ( // if using cmd/ctrl, we're not dragging\n !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if ((hitElement || this.isHittingCommonBoundingBoxOfSelectedElements(scenePointer, selectedElements)) && !(hitElement === null || hitElement === void 0 ? void 0 : hitElement.locked)) {\n if (hitElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement) && this.isIframeLikeElementCenter(hitElement, event, scenePointerX, scenePointerY)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n this.setState({\n activeEmbeddable: {\n element: hitElement,\n state: \"hover\"\n }\n });\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n\n if (((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\") {\n this.setState({\n activeEmbeddable: null\n });\n }\n }\n }\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n };\n\n this.handleEraser = (event, pointerDownState, scenePointer) => {\n this.eraserTrail.addPointToPath(scenePointer.x, scenePointer.y);\n let didChange = false;\n const processedGroups = new Set();\n const nonDeletedElements = this.scene.getNonDeletedElements();\n\n const processElements = elements => {\n var _a;\n\n for (const element of elements) {\n if (element.locked) {\n return;\n }\n\n if (event.altKey) {\n if (this.elementsPendingErasure.delete(element.id)) {\n didChange = true;\n }\n } else if (!this.elementsPendingErasure.has(element.id)) {\n didChange = true;\n this.elementsPendingErasure.add(element.id);\n } // (un)erase groups atomically\n\n\n if (didChange && ((_a = element.groupIds) === null || _a === void 0 ? void 0 : _a.length)) {\n const shallowestGroupId = element.groupIds.at(-1);\n\n if (!processedGroups.has(shallowestGroupId)) {\n processedGroups.add(shallowestGroupId);\n const elems = (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(nonDeletedElements, shallowestGroupId);\n\n for (const elem of elems) {\n if (event.altKey) {\n this.elementsPendingErasure.delete(elem.id);\n } else {\n this.elementsPendingErasure.add(elem.id);\n }\n }\n }\n }\n }\n };\n\n const distance = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointer.x, scenePointer.y));\n const threshold = this.getElementHitThreshold();\n const p = Object.assign({}, pointerDownState.lastCoords);\n let samplingInterval = 0;\n\n while (samplingInterval <= distance) {\n const hitElements = this.getElementsAtPosition(p.x, p.y);\n processElements(hitElements); // Exit since we reached current point\n\n if (samplingInterval === distance) {\n break;\n } // Calculate next point in the line at a distance of sampling interval\n\n\n samplingInterval = Math.min(samplingInterval + threshold, distance);\n const distanceRatio = samplingInterval / distance;\n const nextX = (1 - distanceRatio) * p.x + distanceRatio * scenePointer.x;\n const nextY = (1 - distanceRatio) * p.y + distanceRatio * scenePointer.y;\n p.x = nextX;\n p.y = nextY;\n }\n\n pointerDownState.lastCoords.x = scenePointer.x;\n pointerDownState.lastCoords.y = scenePointer.y;\n\n if (didChange) {\n for (const element of this.scene.getNonDeletedElements()) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(element) && (this.elementsPendingErasure.has(element.id) || this.elementsPendingErasure.has(element.containerId))) {\n if (event.altKey) {\n this.elementsPendingErasure.delete(element.id);\n this.elementsPendingErasure.delete(element.containerId);\n } else {\n this.elementsPendingErasure.add(element.id);\n this.elementsPendingErasure.add(element.containerId);\n }\n }\n }\n\n this.elementsPendingErasure = new Set(this.elementsPendingErasure);\n this.triggerRender();\n }\n }; // set touch moving for mobile context menu\n\n\n this.handleTouchMove = event => {\n invalidateContextMenu = true;\n };\n\n this.handleCanvasPointerDown = event => {\n var _a, _b;\n\n this.focusContainer(); //zsviczian\n\n this.maybeCleanupAfterMissingPointerUp(event.nativeEvent);\n this.maybeUnfollowRemoteUser();\n\n if (this.state.searchMatches) {\n this.setState(state => ({\n searchMatches: state.searchMatches.map(searchMatch => Object.assign(Object.assign({}, searchMatch), {\n focus: false\n }))\n }));\n _jotai__WEBPACK_IMPORTED_MODULE_55__.jotaiStore.set(_SearchMenu__WEBPACK_IMPORTED_MODULE_97__.searchItemInFocusAtom, null);\n } // since contextMenu options are potentially evaluated on each render,\n // and an contextMenu action may depend on selection state, we must\n // close the contextMenu before we update the selection on pointerDown\n // (e.g. resetting selection)\n\n\n if (this.state.contextMenu) {\n this.setState({\n contextMenu: null\n });\n }\n\n if (this.state.snapLines) {\n this.setAppState({\n snapLines: []\n });\n }\n\n this.updateGestureOnPointerDown(event); // if dragging element is freedraw and another pointerdown event occurs\n // a second finger is on the screen\n // discard the freedraw element if it is very short because it is likely\n // just a spike, otherwise finalize the freedraw element when the second\n // finger is lifted\n\n if (event.pointerType === \"touch\" && this.state.newElement && this.state.newElement.type === \"freedraw\") {\n const element = this.state.newElement;\n this.updateScene(Object.assign(Object.assign({}, element.points.length < 10 ? {\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== element.id)\n } : {}), {\n appState: {\n newElement: null,\n editingTextElement: null,\n startBoundElement: null,\n suggestedBindings: [],\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.keys(this.state.selectedElementIds).filter(key => key !== element.id).reduce((obj, key) => {\n obj[key] = this.state.selectedElementIds[key];\n return obj;\n }, {}), this.state)\n },\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n }));\n return;\n } // remove any active selection when we start to interact with canvas\n // (mainly, we care about removing selection outside the component which\n // would prevent our copy handling otherwise)\n\n\n const selection = document.getSelection();\n\n if (selection === null || selection === void 0 ? void 0 : selection.anchorNode) {\n selection.removeAllRanges();\n }\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices(event); //fires only once, if pen is detected, penMode is enabled\n //the user can disable this by toggling the penMode button\n\n if (!this.state.penDetected && event.pointerType === \"pen\") {\n this.setState(prevState => {\n return {\n penMode: true,\n penDetected: true\n };\n });\n }\n\n if (!this.device.isTouchScreen && [\"pen\", \"touch\"].includes(event.pointerType)) {\n this.device = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateObject)(this.device, {\n isTouchScreen: true\n });\n }\n\n if (isPanning) {\n return;\n }\n\n this.lastPointerDownEvent = event; // we must exit before we set `cursorButton` state and `savePointer`\n // else it will send pointer state & laser pointer events in collab when\n // panning\n\n /*if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {\n return;\n }*/\n //zsviczian this broke on pointer down in onPointerUpdate\n\n this.setState({\n lastPointerDownWith: event.pointerType,\n cursorButton: \"down\"\n });\n this.savePointer(event.clientX, event.clientY, \"down\");\n\n if (this.handleCanvasPanUsingWheelOrSpaceDrag(event)) {\n return;\n } //zsviczian moved it here, because else pointer down in onPointerUpdate did not work\n\n\n if (event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.ERASER && this.state.activeTool.type !== _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.eraser) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.eraser,\n lastActiveToolBeforeEraser: this.state.activeTool\n })\n }, () => {\n this.handleCanvasPointerDown(event);\n\n const onPointerUp = () => {\n unsubPointerUp();\n unsubCleanup === null || unsubCleanup === void 0 ? void 0 : unsubCleanup();\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, Object.assign(Object.assign({}, this.state.activeTool.lastActiveTool || {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.selection\n }), {\n lastActiveToolBeforeEraser: null\n }))\n });\n }\n };\n\n const unsubPointerUp = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp, {\n once: true\n });\n let unsubCleanup; // subscribe inside rAF lest it'd be triggered on the same pointerdown\n // if we start erasing while coming from blurred document since\n // we cleanup pointer events on focus\n\n requestAnimationFrame(() => {\n unsubCleanup = this.missingPointerEventCleanupEmitter.once(onPointerUp);\n });\n });\n return;\n } // only handle left mouse button or touch\n\n\n if (event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.TOUCH && event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.ERASER) {\n return;\n } // don't select while panning\n\n\n if (gesture.pointers.size > 1) {\n return;\n } // State for the duration of a pointer interaction, which starts with a\n // pointerDown event, ends with a pointerUp event (or another pointerDown)\n\n\n const pointerDownState = this.initialPointerDownState(event);\n this.setState({\n selectedElementsAreBeingDragged: false\n });\n\n if (this.handleDraggingScrollBar(event, pointerDownState)) {\n return;\n }\n\n this.clearSelectionIfNotUsingSelection();\n this.updateBindingEnabledOnPointerMove(event);\n\n if (this.handleSelectionOnPointerDown(event, pointerDownState)) {\n return;\n }\n\n const allowOnPointerDown = !this.state.penMode || event.pointerType !== \"touch\" || this.state.activeTool.type === \"selection\" || this.state.activeTool.type === \"text\" || this.state.activeTool.type === \"image\";\n\n if (!allowOnPointerDown) {\n return;\n }\n\n if (this.state.activeTool.type === \"text\") {\n this.handleTextOnPointerDown(event, pointerDownState);\n } else if (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\") {\n this.handleLinearElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"image\") {\n // reset image preview on pointerdown\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.CROSSHAIR); // retrieve the latest element as the state may be stale\n\n const pendingImageElement = this.state.pendingImageElementId && this.scene.getElement(this.state.pendingImageElementId);\n\n if (!pendingImageElement) {\n return;\n }\n\n this.setState({\n newElement: pendingImageElement,\n pendingImageElementId: null,\n multiElement: null\n });\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const frame = this.getTopLayerFrameAtSceneCoords({\n x,\n y\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(pendingImageElement, {\n x,\n y,\n frameId: frame ? frame.id : null\n });\n } else if (this.state.activeTool.type === \"freedraw\") {\n this.handleFreeDrawElementOnPointerDown(event, this.state.activeTool.type, pointerDownState);\n } else if (this.state.activeTool.type === \"custom\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n } else if (this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.frame || this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe) {\n this.createFrameElementOnPointerDown(pointerDownState, this.state.activeTool.type);\n } else if (this.state.activeTool.type === \"laser\") {\n this.laserTrails.startPath(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y);\n } else if (this.state.activeTool.type !== \"eraser\" && this.state.activeTool.type !== \"hand\" && this.state.activeTool.type !== \"mermaid\") {\n this.createGenericElementOnPointerDown(this.state.activeTool.type, pointerDownState);\n }\n\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onPointerDown) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.activeTool, pointerDownState);\n this.onPointerDownEmitter.trigger(this.state.activeTool, pointerDownState, event);\n\n if (this.state.activeTool.type === \"eraser\") {\n this.eraserTrail.startPath(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y);\n }\n\n const onPointerMove = this.onPointerMoveFromPointerDownHandler(pointerDownState);\n const onPointerUp = this.onPointerUpFromPointerDownHandler(pointerDownState);\n const onKeyDown = this.onKeyDownFromPointerDownHandler(pointerDownState);\n const onKeyUp = this.onKeyUpFromPointerDownHandler(pointerDownState);\n this.missingPointerEventCleanupEmitter.once(_event => onPointerUp(_event || event.nativeEvent));\n\n if (!this.state.viewModeEnabled || this.state.activeTool.type === \"laser\") {\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, onKeyDown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, onKeyUp);\n pointerDownState.eventListeners.onMove = onPointerMove;\n pointerDownState.eventListeners.onUp = onPointerUp;\n pointerDownState.eventListeners.onKeyUp = onKeyUp;\n pointerDownState.eventListeners.onKeyDown = onKeyDown;\n }\n };\n\n this.handleCanvasPointerUp = event => {\n var _a, _b;\n\n this.removePointer(event);\n this.lastPointerUpEvent = event;\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: event.clientX,\n clientY: event.clientY\n }, this.state);\n const clicklength = event.timeStamp - ((_b = (_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a.timeStamp) !== null && _b !== void 0 ? _b : 0);\n\n if (this.device.editor.isMobile && clicklength < 300) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement) && this.isIframeLikeElementCenter(hitElement, event, scenePointer.x, scenePointer.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n return;\n }\n }\n\n if (this.device.isTouchScreen) {\n const hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);\n this.hitLinkElement = this.getElementLinkAtPosition(scenePointer, hitElement);\n }\n\n if (this.hitLinkElement && !this.state.selectedElementIds[this.hitLinkElement.id]) {\n if (clicklength < 300 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(this.hitLinkElement) && !(0,_hyperlink_helpers__WEBPACK_IMPORTED_MODULE_87__.isPointHittingLinkIcon)(this.hitLinkElement, this.scene.getNonDeletedElementsMap(), this.state, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(scenePointer.x, scenePointer.y))) {\n this.handleEmbeddableCenterClick(this.hitLinkElement);\n } else {\n this.redirectToLink(event, this.device.isTouchScreen);\n }\n } else if (this.state.viewModeEnabled) {\n this.setState({\n activeEmbeddable: null,\n selectedElementIds: {}\n });\n }\n };\n\n this.maybeOpenContextMenuAfterPointerDownOnTouchDevices = event => {\n // deal with opening context menu on touch devices\n if (event.pointerType === \"touch\") {\n invalidateContextMenu = false;\n\n if (touchTimeout) {\n // If there's already a touchTimeout, this means that there's another\n // touch down and we are doing another touch, so we shouldn't open the\n // context menu.\n invalidateContextMenu = true;\n } else {\n // open the context menu with the first touch's clientX and clientY\n // if the touch is not moving\n touchTimeout = window.setTimeout(() => {\n touchTimeout = 0;\n\n if (!invalidateContextMenu) {\n this.handleCanvasContextMenu(event);\n }\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.TOUCH_CTX_MENU_TIMEOUT);\n }\n }\n };\n\n this.resetContextMenuTimer = () => {\n clearTimeout(touchTimeout);\n touchTimeout = 0;\n invalidateContextMenu = false;\n };\n /**\n * pointerup may not fire in certian cases (user tabs away...), so in order\n * to properly cleanup pointerdown state, we need to fire any hanging\n * pointerup handlers manually\n */\n\n\n this.maybeCleanupAfterMissingPointerUp = event => {\n lastPointerUp === null || lastPointerUp === void 0 ? void 0 : lastPointerUp();\n this.missingPointerEventCleanupEmitter.trigger(event).clear();\n }; // Returns whether the event is a panning\n\n\n this.handleCanvasPanUsingWheelOrSpaceDrag = event => {\n if (!(gesture.pointers.size <= 1 && (event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.WHEEL || event.button === _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.MAIN && isHoldingSpace || (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isHandToolActive)(this.state) || //zsviczian\n (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.isTouchInPenMode)(this.state, event) || //!isLaserPointerActive added by zsviczian (but don't remember why....)\n this.state.viewModeEnabled && !(0,_appState__WEBPACK_IMPORTED_MODULE_10__.isLaserPointerActive)(this.state)))) {\n return false;\n }\n\n isPanning = true; // due to event.preventDefault below, container wouldn't get focus\n // automatically\n\n this.focusContainer(); // preventing defualt while text editing messes with cursor/focus\n\n if (!this.state.editingTextElement) {\n // necessary to prevent browser from scrolling the page if excalidraw\n // not full-page #4489\n //\n // as such, the above is broken when panning canvas while in wysiwyg\n event.preventDefault();\n }\n\n let nextPastePrevented = false;\n const isLinux = typeof window === undefined ? false : /Linux/.test(window.navigator.platform);\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRABBING);\n let {\n clientX: lastX,\n clientY: lastY\n } = event;\n const onPointerMove = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdatesThrottled)(event => {\n const deltaX = lastX - event.clientX;\n const deltaY = lastY - event.clientY;\n lastX = event.clientX;\n lastY = event.clientY;\n /*\n * Prevent paste event if we move while middle clicking on Linux.\n * See issue #1383.\n */\n\n if (isLinux && !nextPastePrevented && (Math.abs(deltaX) > 1 || Math.abs(deltaY) > 1)) {\n nextPastePrevented = true;\n /* Prevent the next paste event */\n\n const preventNextPaste = event => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n event.stopPropagation();\n };\n /*\n * Reenable next paste in case of disabled middle click paste for\n * any reason:\n * - right click paste\n * - empty clipboard\n */\n\n\n const enableNextPaste = () => {\n setTimeout(() => {\n document.body.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }, 100);\n };\n\n document.body.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, preventNextPaste);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, enableNextPaste);\n }\n\n this.translateCanvas({\n scrollX: this.state.scrollX - deltaX / this.state.zoom.value,\n scrollY: this.state.scrollY - deltaY / this.state.zoom.value\n });\n });\n const teardown = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(lastPointerUp = () => {\n lastPointerUp = null;\n isPanning = false;\n\n if (!isHoldingSpace) {\n if (this.state.viewModeEnabled) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.GRAB);\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n }\n\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n onPointerMove.flush();\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, teardown);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove, {\n passive: true\n });\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, teardown);\n return true;\n };\n\n this.clearSelectionIfNotUsingSelection = () => {\n if (this.state.activeTool.type !== \"selection\") {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n };\n /**\n * @returns whether the pointer event has been completely handled\n */\n\n\n this.handleSelectionOnPointerDown = (event, pointerDownState) => {\n var _a, _b;\n\n if (this.state.activeTool.type === \"selection\") {\n const elements = this.scene.getNonDeletedElements();\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1 && !this.state.editingLinearElement && !(this.state.selectedLinearElement && this.state.selectedLinearElement.hoverPointIndex !== -1)) {\n const elementWithTransformHandleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementWithTransformHandleType)(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);\n\n if (elementWithTransformHandleType != null) {\n if (elementWithTransformHandleType.transformHandleType === \"rotation\") {\n this.setState({\n resizingElement: elementWithTransformHandleType.element\n });\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n } else if (this.state.croppingElementId) {\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n } else {\n this.setState({\n resizingElement: elementWithTransformHandleType.element\n });\n pointerDownState.resize.handleType = elementWithTransformHandleType.transformHandleType;\n }\n }\n } else if (selectedElements.length > 1) {\n pointerDownState.resize.handleType = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getTransformHandleTypeFromCoords)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.device);\n }\n\n if (pointerDownState.resize.handleType) {\n pointerDownState.resize.isResizing = true;\n pointerDownState.resize.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeOffsetXY)(pointerDownState.resize.handleType, selectedElements, elementsMap, pointerDownState.origin.x, pointerDownState.origin.y));\n\n if (selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(selectedElements[0]) && selectedElements[0].points.length === 2) {\n pointerDownState.resize.arrowDirection = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getResizeArrowDirection)(pointerDownState.resize.handleType, selectedElements[0]);\n }\n } else {\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerDown(event, this, this.store, pointerDownState.origin, linearElementEditor, this.scene);\n\n if (ret.hitElement) {\n pointerDownState.hit.element = ret.hitElement;\n }\n\n if (ret.linearElementEditor) {\n this.setState({\n selectedLinearElement: ret.linearElementEditor\n });\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: ret.linearElementEditor\n });\n }\n }\n\n if (ret.didAddPoint) {\n return true;\n }\n } // hitElement may already be set above, so check first\n\n\n pointerDownState.hit.element = (_a = pointerDownState.hit.element) !== null && _a !== void 0 ? _a : this.getElementAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n\n if (this.state.croppingElementId && ((_b = pointerDownState.hit.element) === null || _b === void 0 ? void 0 : _b.id) !== this.state.croppingElementId) {\n this.finishImageCropping();\n }\n\n if (pointerDownState.hit.element) {\n // Early return if pointer is hitting link icon\n const hitLinkElement = this.getElementLinkAtPosition({\n x: pointerDownState.origin.x,\n y: pointerDownState.origin.y\n }, pointerDownState.hit.element);\n\n if (hitLinkElement) {\n return false;\n }\n } // For overlapped elements one position may hit\n // multiple elements\n\n\n pointerDownState.hit.allHitElements = this.getElementsAtPosition(pointerDownState.origin.x, pointerDownState.origin.y);\n const hitElement = pointerDownState.hit.element;\n const someHitElementIsSelected = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n\n if ((hitElement === null || !someHitElementIsSelected) && !event.shiftKey && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.clearSelection(hitElement);\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [this.state.editingLinearElement.elementId]: true\n }, this.state)\n }); // If we click on something\n } else if (hitElement != null) {\n // on CMD/CTRL, drill down to hit element regardless of groups etc.\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n if (!this.state.selectedElementIds[hitElement.id]) {\n pointerDownState.hit.wasAddedToSelection = true;\n }\n\n this.setState(prevState => Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.editGroupForSelectedElement)(prevState, hitElement)), {\n previousSelectedElementIds: this.state.selectedElementIds\n })); // mark as not completely handled so as to allow dragging etc.\n\n return false;\n } // deselect if item is selected\n // if shift is not clicked, this will always return true\n // otherwise, it will trigger selection based on current\n // state of the box\n\n\n if (!this.state.selectedElementIds[hitElement.id]) {\n // if we are currently editing a group, exiting editing mode and deselect the group.\n if (this.state.editingGroupId && !(0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, this.state.editingGroupId)) {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } // Add hit element to selection. At this point if we're not holding\n // SHIFT the previously selected element(s) were deselected above\n // (make sure you use setState updater to use latest state)\n // With shift-selection, we want to make sure that frames and their containing\n // elements are not selected at the same time.\n\n\n if (!someHitElementIsSelected && !pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) {\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n });\n const previouslySelectedElements = [];\n Object.keys(prevState.selectedElementIds).forEach(id => {\n const element = this.scene.getElement(id);\n element && previouslySelectedElements.push(element);\n }); // if hitElement is frame-like, deselect all of its elements\n // if they are selected\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(hitElement)) {\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameChildren)(previouslySelectedElements, hitElement.id).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n } else if (hitElement.frameId) {\n // if hitElement is in a frame and its frame has been selected\n // disable selection for the given element\n if (nextSelectedElementIds[hitElement.frameId]) {\n delete nextSelectedElementIds[hitElement.id];\n }\n } else {\n // hitElement is neither a frame nor an element in a frame\n // but since hitElement could be in a group with some frames\n // this means selecting hitElement will have the frames selected as well\n // because we want to keep the invariant:\n // - frames and their elements are not selected at the same time\n // we deselect elements in those frames that were previously selected\n const groupIds = hitElement.groupIds;\n const framesInGroups = new Set(groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element)).map(frame => frame.id));\n\n if (framesInGroups.size > 0) {\n previouslySelectedElements.forEach(element => {\n if (element.frameId && framesInGroups.has(element.frameId)) {\n // deselect element and groups containing the element\n delete nextSelectedElementIds[element.id];\n element.groupIds.flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n }\n });\n }\n }\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n pointerDownState.hit.wasAddedToSelection = true;\n }\n }\n }\n\n this.setState({\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n }\n\n return false;\n };\n\n this.handleTextOnPointerDown = (event, pointerDownState) => {\n // if we're currently still editing text, clicking outside\n // should only finalize it, not create another (irrespective\n // of state.activeTool.locked)\n if (this.state.editingTextElement) {\n return;\n }\n\n let sceneX = pointerDownState.origin.x;\n let sceneY = pointerDownState.origin.y;\n const element = this.getElementAtPosition(sceneX, sceneY, {\n includeBoundTextElement: true\n }); // FIXME\n\n let container = this.getTextBindableContainerAtPosition(sceneX, sceneY);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.hasBoundTextElement)(element)) {\n container = element;\n sceneX = element.x + element.width / 2;\n sceneY = element.y + element.height / 2;\n }\n\n this.startTextEditing({\n sceneX,\n sceneY,\n insertAtParentCenter: !event.altKey,\n container,\n autoEdit: false\n });\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n\n if (!this.state.activeTool.locked) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n };\n\n this.handleFreeDrawElementOnPointerDown = (event, elementType, pointerDownState) => {\n // Begin a mark capture. This does not have to update state yet.\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, null);\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const strokeOptions = this.state.currentStrokeOptions; //zsviczian\n\n const simulatePressure = (strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.constantPressure //zsviczian\n ) ? false : event.pressure === 0.5;\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFreeDrawElement)(Object.assign(Object.assign({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: null,\n simulatePressure,\n locked: false\n }, strokeOptions //zsviczian\n ? {\n customData: {\n strokeOptions\n }\n } : {}), {\n frameId: topLayerFrame ? topLayerFrame.id : null,\n points: [(0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(0, 0)],\n pressures: simulatePressure ? [] : [(strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.constantPressure) ? 1 : event.pressure]\n })); //zsviczian\n\n if (strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.highlighter) {\n this.scene.insertElement(element, 0);\n } else {\n this.scene.insertElement(element);\n }\n\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());\n this.setState({\n newElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n };\n\n this.insertIframeElement = ({\n sceneX,\n sceneY,\n width,\n height\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newIframeElement)({\n type: \"iframe\",\n x: gridX,\n y: gridY,\n strokeColor: \"transparent\",\n backgroundColor: \"transparent\",\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: this.getCurrentItemRoundness(\"iframe\"),\n opacity: this.state.currentItemOpacity,\n locked: false,\n width,\n height\n });\n this.scene.insertElement(element);\n return element;\n }; //create rectangle element with youtube top left on nearest grid point width / hight 640/360\n\n\n this.insertEmbeddableElement = ({\n sceneX,\n sceneY,\n link\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)(link);\n\n if (!embedLink) {\n return;\n }\n\n if (embedLink.error instanceof URIError) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"toast.unrecognizedLinkFormat\"),\n closable: true\n });\n }\n\n const element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)({\n type: \"embeddable\",\n x: gridX,\n y: gridY,\n strokeColor: \"transparent\",\n backgroundColor: \"transparent\",\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: this.getCurrentItemRoundness(\"embeddable\"),\n opacity: this.state.currentItemOpacity,\n locked: false,\n width: embedLink.intrinsicSize.w,\n height: embedLink.intrinsicSize.h,\n link\n });\n this.scene.insertElement(element);\n return element;\n };\n\n this.createImageElement = ({\n sceneX,\n sceneY,\n addToFrameUnderCursor = true\n }) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(sceneX, sceneY, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const topLayerFrame = addToFrameUnderCursor ? this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n }) : null;\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newImageElement)({\n type: \"image\",\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n roundness: null,\n opacity: this.state.currentItemOpacity,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n return element;\n };\n\n this.handleLinearElementOnPointerDown = (event, elementType, pointerDownState) => {\n if (this.state.multiElement) {\n const {\n multiElement\n } = this.state; // finalize if completing a loop\n\n if (multiElement.type === \"line\" && (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.isPathALoop)(multiElement.points, this.state.zoom.value)) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n } // Elbow arrows cannot be created by putting down points\n // only the start and end points can be defined\n\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(multiElement) && multiElement.points.length > 1) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n const {\n x: rx,\n y: ry,\n lastCommittedPoint\n } = multiElement; // clicking inside commit zone → finalize arrow\n\n if (multiElement.points.length > 1 && lastCommittedPoint && (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerDownState.origin.x - rx, pointerDownState.origin.y - ry), lastCommittedPoint) < _constants__WEBPACK_IMPORTED_MODULE_12__.LINE_CONFIRM_THRESHOLD) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [multiElement.id]: true\n }), prevState)\n })); // clicking outside commit zone → update reference for last committed\n // point\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(multiElement, {\n lastCommittedPoint: multiElement.points[multiElement.points.length - 1]\n });\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else {\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n /* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.\n If so, we want it to be null for start and \"arrow\" for end. If the linear item is not\n an arrow, we want it to be null for both. Otherwise, we want it to use the\n values from appState. */\n\n const {\n currentItemStartArrowhead,\n currentItemEndArrowhead\n } = this.state;\n const [startArrowhead, endArrowhead] = elementType === \"arrow\" ? [currentItemStartArrowhead, currentItemEndArrowhead] : [null, null];\n const element = elementType === \"arrow\" ? (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newArrowElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.state.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.round ? {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : // note, roundness doesn't have any effect for elbow arrows,\n // but it's best to set it to null as well\n null,\n startArrowhead,\n endArrowhead,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null,\n elbowed: this.state.currentItemArrowType === _constants__WEBPACK_IMPORTED_MODULE_12__.ARROW_TYPE.elbow\n }) : (0,_element__WEBPACK_IMPORTED_MODULE_16__.newLinearElement)({\n type: elementType,\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.state.currentItemRoundness === \"round\" ? {\n type: _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null,\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n });\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete nextSelectedElementIds[element.id];\n return {\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, prevState)\n };\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n points: [...element.points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(0, 0)]\n });\n const boundElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerDownState.origin, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap(), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(element));\n this.scene.insertElement(element);\n this.setState({\n newElement: element,\n startBoundElement: boundElement,\n suggestedBindings: []\n });\n }\n };\n\n this.createGenericElementOnPointerDown = (elementType, pointerDownState) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x: gridX,\n y: gridY\n });\n const baseElementAttributes = {\n x: gridX,\n y: gridY,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n roundness: this.getCurrentItemRoundness(elementType),\n locked: false,\n frameId: topLayerFrame ? topLayerFrame.id : null\n };\n let element;\n\n if (elementType === \"embeddable\") {\n element = (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newEmbeddableElement)(Object.assign({\n type: \"embeddable\"\n }, baseElementAttributes));\n } else {\n element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newElement)(Object.assign({\n type: elementType\n }, baseElementAttributes));\n }\n\n if (element.type === \"selection\") {\n this.setState({\n selectionElement: element\n });\n } else {\n this.scene.insertElement(element);\n this.setState({\n multiElement: null,\n newElement: element\n });\n }\n };\n\n this.createFrameElementOnPointerDown = (pointerDownState, type) => {\n var _a;\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerDownState.origin.x, pointerDownState.origin.y, ((_a = this.lastPointerDownEvent) === null || _a === void 0 ? void 0 : _a[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) ? null : this.getEffectiveGridSize());\n const constructorOpts = Object.assign(Object.assign({\n x: gridX,\n y: gridY,\n opacity: this.state.currentItemOpacity,\n locked: false\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.FRAME_STYLE), this.state.frameColor ? {\n //zsviczian\n customData: {\n frameColor: this.state.frameColor\n }\n } : {});\n const frame = type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe ? (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newMagicFrameElement)(constructorOpts) : (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.newFrameElement)(constructorOpts);\n this.scene.insertElement(frame);\n this.setState({\n multiElement: null,\n newElement: frame\n });\n };\n\n this.restoreReadyToEraseElements = () => {\n this.elementsPendingErasure = new Set();\n this.triggerRender();\n };\n\n this.eraseElements = () => {\n let didChange = false;\n const elements = this.scene.getElementsIncludingDeleted().map(ele => {\n if (this.elementsPendingErasure.has(ele.id) || ele.frameId && this.elementsPendingErasure.has(ele.frameId) || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele) && this.elementsPendingErasure.has(ele.containerId)) {\n didChange = true;\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(ele, {\n isDeleted: true\n });\n }\n\n return ele;\n });\n this.elementsPendingErasure = new Set();\n\n if (didChange) {\n this.store.shouldCaptureIncrement();\n this.scene.replaceAllElements(elements);\n }\n };\n\n this.initializeImage = async ({\n imageFile,\n imageElement: _imageElement,\n showCursorImagePreview = false\n }) => {\n var _a, _b, _c, _d; // at this point this should be guaranteed image file, but we do this check\n // to satisfy TS down the line\n\n\n if (!(0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isSupportedImageFile)(imageFile)) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\"));\n }\n\n const mimeType = imageFile.type;\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, \"wait\");\n\n if (mimeType === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n imageFile = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.SVGStringToFile)((0,_element_image__WEBPACK_IMPORTED_MODULE_41__.normalizeSVG)(await imageFile.text()), imageFile.name);\n } catch (error) {\n console.warn(error);\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.svgImageInsertError\"));\n }\n } // generate image id (by default the file digest) before any\n // resizing/compression takes place to keep it more portable\n\n\n const fileId = await (((_b = (_a = this.props).generateIdForFile) === null || _b === void 0 ? void 0 : _b.call(_a, imageFile)) || (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.generateIdFromFile)(imageFile));\n\n if (!fileId) {\n console.warn(\"Couldn't generate file id or the supplied `generateIdForFile` didn't resolve to one.\");\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\"));\n }\n\n const existingFileData = this.files[fileId];\n\n if (!(existingFileData === null || existingFileData === void 0 ? void 0 : existingFileData.dataURL)) {\n try {\n imageFile = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT\n });\n } catch (error) {\n console.error(\"Error trying to resizing image file on insertion\", error);\n }\n\n if (imageFile.size > _constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES) {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.fileTooBig\", {\n maxSize: `${Math.trunc(_constants__WEBPACK_IMPORTED_MODULE_12__.MAX_ALLOWED_FILE_BYTES / 1024 / 1024)}MB`\n }));\n }\n }\n\n if (showCursorImagePreview) {\n const dataURL = (_c = this.files[fileId]) === null || _c === void 0 ? void 0 : _c.dataURL; // optimization so that we don't unnecessarily resize the original\n // full-size file for cursor preview\n // (it's much faster to convert the resized dataURL to File)\n\n const resizedFile = dataURL && (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.dataURLToFile)(dataURL);\n this.setImagePreviewCursor(resizedFile || imageFile);\n }\n\n const dataURL = ((_d = this.files[fileId]) === null || _d === void 0 ? void 0 : _d.dataURL) || (await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getDataURL)(imageFile));\n const imageElement = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(_imageElement, {\n fileId\n }, false);\n return new Promise(async (resolve, reject) => {\n var _a;\n\n try {\n this.addMissingFiles([{\n mimeType,\n id: fileId,\n dataURL,\n created: Date.now(),\n lastRetrieved: Date.now(),\n //@ts-ignore\n name: (imageFile === null || imageFile === void 0 ? void 0 : imageFile.name) && imageFile.name !== \"image.png\" ? imageFile.name : undefined // zsviczian\n\n }]);\n const cachedImageData = this.imageCache.get(fileId);\n\n if (!cachedImageData) {\n this.addNewImagesToImageCache();\n await this.updateImageCache([imageElement]);\n }\n\n if ((cachedImageData === null || cachedImageData === void 0 ? void 0 : cachedImageData.image) instanceof Promise) {\n await cachedImageData.image;\n }\n\n if (this.state.pendingImageElementId !== imageElement.id && ((_a = this.state.newElement) === null || _a === void 0 ? void 0 : _a.id) !== imageElement.id) {\n this.initializeImageDimensions(imageElement, true);\n }\n\n resolve(imageElement);\n } catch (error) {\n console.error(error);\n reject(new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")));\n } finally {\n if (!showCursorImagePreview) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n }\n }\n });\n };\n /**\n * inserts image into elements array and rerenders\n */\n\n\n this.insertImageElement = async (imageElement, imageFile, showCursorImagePreview) => {\n // we should be handling all cases upstream, but in case we forget to handle\n // a future case, let's throw here\n if (!this.isToolSupported(\"image\")) {\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageToolNotSupported\")\n });\n return;\n }\n\n this.scene.insertElement(imageElement);\n\n try {\n return await this.initializeImage({\n imageFile,\n imageElement,\n showCursorImagePreview\n });\n } catch (error) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n isDeleted: true\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n this.setState({\n errorMessage: error.message || (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageInsertError\")\n });\n return null;\n }\n };\n\n this.setImagePreviewCursor = async imageFile => {\n // mustn't be larger than 128 px\n // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Basic_User_Interface/Using_URL_values_for_the_cursor_property\n const cursorImageSizePx = 96;\n let imagePreview;\n\n try {\n imagePreview = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.resizeImageFile)(imageFile, {\n maxWidthOrHeight: cursorImageSizePx\n });\n } catch (e) {\n if (e.cause === \"UNSUPPORTED\") {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\"));\n }\n\n throw e;\n }\n\n let previewDataURL = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getDataURL)(imagePreview); // SVG cannot be resized via `resizeImageFile` so we resize by rendering to\n // a small canvas\n\n if (imageFile.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n const img = await (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.loadHTMLImageElement)(previewDataURL);\n let height = Math.min(img.height, cursorImageSizePx);\n let width = height * (img.width / img.height);\n\n if (width > cursorImageSizePx) {\n width = cursorImageSizePx;\n height = width * (img.height / img.width);\n }\n\n const canvas = document.createElement(\"canvas\");\n canvas.height = height;\n canvas.width = width;\n const context = canvas.getContext(\"2d\");\n context.drawImage(img, 0, 0, width, height);\n previewDataURL = canvas.toDataURL(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg);\n }\n\n if (this.state.pendingImageElementId) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, `url(${previewDataURL}) 4 4, auto`);\n }\n };\n\n this.onImageAction = async ({\n insertOnCanvasDirectly\n }) => {\n try {\n const clientX = this.state.width / 2 + this.state.offsetLeft;\n const clientY = this.state.height / 2 + this.state.offsetTop;\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX,\n clientY\n }, this.state);\n const imageFile = await (0,_data_filesystem__WEBPACK_IMPORTED_MODULE_43__.fileOpen)({\n description: \"Image\",\n extensions: Object.keys(_constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_MIME_TYPES)\n });\n const imageElement = this.createImageElement({\n sceneX: x,\n sceneY: y,\n addToFrameUnderCursor: false\n });\n\n if (insertOnCanvasDirectly) {\n this.insertImageElement(imageElement, imageFile);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } else {\n this.setState({\n pendingImageElementId: imageElement.id\n }, () => {\n this.insertImageElement(imageElement, imageFile,\n /* showCursorImagePreview */\n true);\n });\n }\n } catch (error) {\n if (error.name !== \"AbortError\") {\n console.error(error);\n } else {\n console.warn(error);\n }\n\n this.setState({\n pendingImageElementId: null,\n newElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n }\n };\n\n this.initializeImageDimensions = (imageElement, forceNaturalSize = false) => {\n var _a;\n\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(imageElement) && ((_a = this.imageCache.get(imageElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n\n if (!image || image instanceof Promise) {\n if (imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const placeholderSize = 100 / this.state.zoom.value;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x: imageElement.x - placeholderSize / 2,\n y: imageElement.y - placeholderSize / 2,\n width: placeholderSize,\n height: placeholderSize\n });\n }\n\n return;\n }\n\n if (forceNaturalSize || // if user-created bounding box is below threshold, assume the\n // intention was to click instead of drag, and use the image's\n // intrinsic size\n imageElement.width < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value && imageElement.height < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD / this.state.zoom.value) {\n const minHeight = Math.max(this.state.height - 120, 160); // max 65% of canvas height, clamped to <300px, vh - 120px>\n\n const maxHeight = Math.min(minHeight, Math.floor(this.state.height * 0.5) / this.state.zoom.value);\n const height = Math.min(image.naturalHeight, maxHeight);\n const width = height * (image.naturalWidth / image.naturalHeight); // add current imageElement width/height to account for previous centering\n // of the placeholder image\n\n const x = imageElement.x + imageElement.width / 2 - width / 2;\n const y = imageElement.y + imageElement.height / 2 - height / 2;\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(imageElement, {\n x,\n y,\n width,\n height,\n crop: null\n });\n }\n };\n /** updates image cache, refreshing updated elements and/or setting status\n to error for images that fail during <img> element creation */\n\n\n this.updateImageCache = async (elements, files = this.files) => {\n const {\n updatedFiles,\n erroredFiles\n } = await (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.updateImageCache)({\n imageCache: this.imageCache,\n fileIds: elements.map(element => element.fileId),\n files\n });\n\n if (updatedFiles.size || erroredFiles.size) {\n for (const element of elements) {\n if (updatedFiles.has(element.fileId)) {\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element);\n }\n }\n }\n\n if (erroredFiles.size) {\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().map(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && erroredFiles.has(element.fileId)) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(element, {\n status: \"error\"\n });\n }\n\n return element;\n }));\n }\n\n return {\n updatedFiles,\n erroredFiles\n };\n };\n /** adds new images to imageCache and re-renders if needed */\n\n\n this.addNewImagesToImageCache = async (imageElements = (0,_element_image__WEBPACK_IMPORTED_MODULE_41__.getInitializedImageElements)(this.scene.getNonDeletedElements()), files = this.files) => {\n const uncachedImageElements = imageElements.filter(element => !element.isDeleted && !this.imageCache.has(element.fileId));\n\n if (uncachedImageElements.length) {\n const {\n updatedFiles\n } = await this.updateImageCache(uncachedImageElements, files);\n\n if (updatedFiles.size) {\n this.scene.triggerUpdate();\n }\n }\n };\n /** generally you should use `addNewImagesToImageCache()` directly if you need\n * to render new images. This is just a failsafe */\n\n\n this.scheduleImageRefresh = lodash_throttle__WEBPACK_IMPORTED_MODULE_42___default()(() => {\n this.addNewImagesToImageCache();\n }, _constants__WEBPACK_IMPORTED_MODULE_12__.IMAGE_RENDER_TIMEOUT);\n\n this.updateBindingEnabledOnPointerMove = event => {\n const shouldEnableBinding = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.shouldEnableBindingForPointerEvent)(event);\n\n if (this.state.isBindingEnabled !== shouldEnableBinding) {\n this.setState({\n isBindingEnabled: shouldEnableBinding\n });\n }\n };\n\n this.maybeSuggestBindingAtCursor = pointerCoords => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(pointerCoords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());\n this.setState({\n suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : []\n });\n };\n\n this.maybeSuggestBindingsForLinearElementAtCoords = (linearElement,\n /** scene coords */\n pointerCoords, // During line creation the start binding hasn't been written yet\n // into `linearElement`\n oppositeBindingBoundElement) => {\n if (!pointerCoords.length) {\n return;\n }\n\n const suggestedBindings = pointerCoords.reduce((acc, coords) => {\n const hoveredBindableElement = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getHoveredElementForBinding)(coords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap(), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(linearElement) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(linearElement));\n\n if (hoveredBindableElement != null && !(0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isLinearElementSimpleAndAlreadyBound)(linearElement, oppositeBindingBoundElement === null || oppositeBindingBoundElement === void 0 ? void 0 : oppositeBindingBoundElement.id, hoveredBindableElement)) {\n acc.push(hoveredBindableElement);\n }\n\n return acc;\n }, []);\n this.setState({\n suggestedBindings\n });\n };\n\n this.handleInteractiveCanvasRef = canvas => {\n var _a, _b; // canvas is null when unmounting\n\n\n if (canvas !== null) {\n this.interactiveCanvas = canvas; // -----------------------------------------------------------------------\n // NOTE wheel, touchstart, touchend events must be registered outside\n // of react because react binds them them passively (so we can't prevent\n // default on them)\n\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n this.interactiveCanvas.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd); // -----------------------------------------------------------------------\n } else {\n (_a = this.interactiveCanvas) === null || _a === void 0 ? void 0 : _a.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_START, this.onTouchStart);\n (_b = this.interactiveCanvas) === null || _b === void 0 ? void 0 : _b.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.TOUCH_END, this.onTouchEnd);\n }\n };\n\n this.handleAppOnDrop = async event => {\n var _a, _b, _c, _d;\n\n if (this.props.onDrop) {\n try {\n if ((await this.props.onDrop(event)) === false) {\n return;\n }\n } catch (e) {\n console.error(e);\n }\n } // must be retrieved first, in the same frame\n\n\n const {\n file,\n fileHandle\n } = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.getFileFromEvent)(event);\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n\n try {\n // if image tool not supported, don't show an error here and let it fall\n // through so we still support importing scene data from images. If no\n // scene data encoded, we'll show an error then\n if ((0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.isSupportedImageFile)(file) && this.isToolSupported(\"image\")) {\n // first attempt to decode scene from the image if it's embedded\n // ---------------------------------------------------------------------\n if ((file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.png || (file === null || file === void 0 ? void 0 : file.type) === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.svg) {\n try {\n const scene = await (0,_data__WEBPACK_IMPORTED_MODULE_13__.loadFromBlob)(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);\n this.syncActionResult(Object.assign(Object.assign({}, scene), {\n appState: Object.assign(Object.assign({}, scene.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n }));\n return;\n } catch (error) {\n // Don't throw for image scene daa\n if (error.name !== \"EncodingError\") {\n throw new Error((0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"alerts.couldNotLoadInvalidFile\"));\n }\n }\n } // if no scene is embedded or we fail for whatever reason, fall back\n // to importing as regular image\n // ---------------------------------------------------------------------\n\n\n const imageElement = this.createImageElement({\n sceneX,\n sceneY\n });\n this.insertImageElement(imageElement, file);\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n });\n return;\n }\n } catch (error) {\n return this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n\n const libraryJSON = event.dataTransfer.getData(_constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib);\n\n if (libraryJSON && typeof libraryJSON === \"string\") {\n try {\n const libraryItems = (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.parseLibraryJSON)(libraryJSON);\n this.addElementsFromPasteOrLibrary({\n elements: (0,_data_library__WEBPACK_IMPORTED_MODULE_14__.distributeLibraryItemsOnSquareGrid)(libraryItems),\n position: event,\n files: null\n });\n } catch (error) {\n this.setState({\n errorMessage: error.message\n });\n }\n\n return;\n }\n\n if (file) {\n // Attempt to parse an excalidraw/excalidrawlib file\n await this.loadFileToCanvas(file, fileHandle);\n }\n\n if ((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) === null || _b === void 0 ? void 0 : _b.includes(\"text/plain\")) {\n const text = (_c = event.dataTransfer) === null || _c === void 0 ? void 0 : _c.getData(\"text\");\n\n if (text && (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.embeddableURLValidator)(text, this.props.validateEmbeddable) && (/^(http|https):\\/\\/[^\\s/$.?#].[^\\s]*$/.test(text) || ((_d = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)(text)) === null || _d === void 0 ? void 0 : _d.type) === \"video\")) {\n const embeddable = this.insertEmbeddableElement({\n sceneX,\n sceneY,\n link: (0,_data_url__WEBPACK_IMPORTED_MODULE_46__.normalizeLink)(text)\n });\n\n if (embeddable) {\n this.setState({\n selectedElementIds: {\n [embeddable.id]: true\n }\n });\n }\n }\n }\n };\n\n this.loadFileToCanvas = async (file, fileHandle) => {\n file = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.normalizeFile)(file);\n\n try {\n const elements = this.scene.getElementsIncludingDeleted();\n let ret;\n\n try {\n ret = await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.loadSceneOrLibraryFromBlob)(file, this.state, elements, fileHandle);\n } catch (error) {\n const imageSceneDataError = error instanceof _errors__WEBPACK_IMPORTED_MODULE_57__.ImageSceneDataError;\n\n if (imageSceneDataError && error.code === \"IMAGE_NOT_CONTAINS_SCENE_DATA\" && !this.isToolSupported(\"image\")) {\n this.setState({\n isLoading: false,\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.imageToolNotSupported\")\n });\n return;\n }\n\n const errorMessage = imageSceneDataError ? (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"alerts.cannotRestoreFromImage\") : (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"alerts.couldNotLoadInvalidFile\");\n this.setState({\n isLoading: false,\n errorMessage\n });\n }\n\n if (!ret) {\n return;\n }\n\n if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidraw) {\n // restore the fractional indices by mutating elements\n (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncInvalidIndices)(elements.concat(ret.data.elements)); // update the store snapshot for old elements, otherwise we would end up with duplicated fractional indices on undo\n\n this.store.updateSnapshot((0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(elements), this.state);\n this.setState({\n isLoading: true\n });\n this.syncActionResult(Object.assign(Object.assign({}, ret.data), {\n appState: Object.assign(Object.assign({}, ret.data.appState || this.state), {\n isLoading: false\n }),\n replaceFiles: true,\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.CAPTURE\n }));\n } else if (ret.type === _constants__WEBPACK_IMPORTED_MODULE_12__.MIME_TYPES.excalidrawlib) {\n await this.library.updateLibrary({\n libraryItems: file,\n merge: true,\n openLibraryMenu: true\n }).catch(error => {\n console.error(error);\n this.setState({\n errorMessage: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.importLibraryError\")\n });\n });\n }\n } catch (error) {\n this.setState({\n isLoading: false,\n errorMessage: error.message\n });\n }\n };\n\n this.handleCanvasContextMenu = event => {\n event.preventDefault();\n\n if ((\"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"touch\" || \"pointerType\" in event.nativeEvent && event.nativeEvent.pointerType === \"pen\" && // always allow if user uses a pen secondary button\n event.button !== _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_BUTTON.SECONDARY) && this.state.activeTool.type !== \"selection\") {\n return;\n }\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const element = this.getElementAtPosition(x, y, {\n preferSelected: true,\n includeLockedElements: true\n });\n const selectedElements = this.scene.getSelectedElements(this.state);\n const isHittingCommonBoundBox = this.isHittingCommonBoundingBoxOfSelectedElements({\n x,\n y\n }, selectedElements);\n const type = element || isHittingCommonBoundBox ? \"element\" : \"canvas\";\n const container = this.excalidrawContainerRef.current;\n const {\n top: offsetTop,\n left: offsetLeft\n } = container.getBoundingClientRect();\n const left = event.clientX - offsetLeft;\n const top = event.clientY - offsetTop;\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"contextMenu\", \"openContextMenu\", type);\n this.setState(Object.assign(Object.assign({}, element && !this.state.selectedElementIds[element.id] ? Object.assign(Object.assign(Object.assign({}, this.state), (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: this.state.editingGroupId,\n selectedElementIds: {\n [element.id]: true\n }\n }, this.scene.getNonDeletedElements(), this.state, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(element) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(element) : null\n }) : this.state), {\n showHyperlinkPopup: false\n }), () => {\n this.setState({\n contextMenu: {\n top,\n left,\n items: this.getContextMenuItems(type)\n }\n });\n });\n };\n\n this.maybeDragNewGenericElement = (pointerDownState, event, informMutation = true) => {\n var _a, _b, _c, _d, _e;\n\n const selectionElement = this.state.selectionElement;\n const pointerCoords = pointerDownState.lastCoords;\n\n if (selectionElement && this.state.activeTool.type !== \"eraser\") {\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)({\n newElement: selectionElement,\n elementType: this.state.activeTool.type,\n originX: pointerDownState.origin.x,\n originY: pointerDownState.origin.y,\n x: pointerCoords.x,\n y: pointerCoords.y,\n width: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.origin.x, pointerCoords.x),\n height: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.origin.y, pointerCoords.y),\n shouldMaintainAspectRatio: (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event),\n shouldResizeFromCenter: (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event),\n zoom: this.state.zoom.value,\n informMutation\n });\n return;\n }\n\n const newElement = this.state.newElement;\n\n if (!newElement) {\n return;\n }\n\n let [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(newElement) && ((_a = this.imageCache.get(newElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n const aspectRatio = image && !(image instanceof Promise) ? image.width / image.height : null;\n this.maybeCacheReferenceSnapPoints(event, [newElement]);\n const {\n snapOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.snapNewElement)(newElement, this, event, {\n x: pointerDownState.originInGrid.x + ((_c = (_b = this.state.originSnapOffset) === null || _b === void 0 ? void 0 : _b.x) !== null && _c !== void 0 ? _c : 0),\n y: pointerDownState.originInGrid.y + ((_e = (_d = this.state.originSnapOffset) === null || _d === void 0 ? void 0 : _d.y) !== null && _e !== void 0 ? _e : 0)\n }, {\n x: gridX - pointerDownState.originInGrid.x,\n y: gridY - pointerDownState.originInGrid.y\n }, this.scene.getNonDeletedElementsMap());\n gridX += snapOffset.x;\n gridY += snapOffset.y;\n this.setState({\n snapLines\n });\n (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragNewElement)({\n newElement,\n elementType: this.state.activeTool.type,\n originX: pointerDownState.originInGrid.x,\n originY: pointerDownState.originInGrid.y,\n x: gridX,\n y: gridY,\n width: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.originInGrid.x, gridX),\n height: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.distance)(pointerDownState.originInGrid.y, gridY),\n shouldMaintainAspectRatio: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(newElement) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event),\n shouldResizeFromCenter: (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event),\n zoom: this.state.zoom.value,\n widthAspectRatio: aspectRatio,\n originOffset: this.state.originSnapOffset,\n informMutation\n });\n this.setState({\n newElement\n }); // highlight elements that are to be added to frames on frames creation\n\n if (this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.frame || this.state.activeTool.type === _constants__WEBPACK_IMPORTED_MODULE_12__.TOOL_TYPE.magicframe) {\n this.setState({\n elementsToHighlight: (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), newElement, this.state, this.scene.getNonDeletedElementsMap())\n });\n }\n };\n\n this.maybeHandleCrop = (pointerDownState, event) => {\n var _a; // to crop, we must already be in the cropping mode, where croppingElement has been set\n\n\n if (!this.state.croppingElementId) {\n return false;\n }\n\n const transformHandleType = pointerDownState.resize.handleType;\n const pointerCoords = pointerDownState.lastCoords;\n const [x, y] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x - pointerDownState.resize.offset.x, pointerCoords.y - pointerDownState.resize.offset.y, this.getEffectiveGridSize());\n const croppingElement = this.scene.getNonDeletedElementsMap().get(this.state.croppingElementId);\n\n if (transformHandleType && croppingElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(croppingElement)) {\n const croppingAtStateStart = pointerDownState.originalElements.get(croppingElement.id);\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(croppingElement) && ((_a = this.imageCache.get(croppingElement.fileId)) === null || _a === void 0 ? void 0 : _a.image);\n\n if (croppingAtStateStart && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(croppingAtStateStart) && image && !(image instanceof Promise)) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(croppingElement, (0,_element_cropElement__WEBPACK_IMPORTED_MODULE_99__.cropElement)(croppingElement, transformHandleType, image.naturalWidth, image.naturalHeight, x, y, event.shiftKey ? croppingAtStateStart.width / croppingAtStateStart.height : undefined));\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(croppingElement, this.scene.getNonDeletedElementsMap(), {\n oldSize: {\n width: croppingElement.width,\n height: croppingElement.height\n }\n });\n this.setState({\n isCropping: transformHandleType && transformHandleType !== \"rotation\"\n });\n }\n\n return true;\n }\n\n return false;\n };\n\n this.maybeHandleResize = (pointerDownState, event) => {\n const selectedElements = this.scene.getSelectedElements(this.state);\n const selectedFrames = selectedElements.filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element));\n const transformHandleType = pointerDownState.resize.handleType;\n\n if ( // Frames cannot be rotated.\n selectedFrames.length > 0 && transformHandleType === \"rotation\" || // Elbow arrows cannot be transformed (resized or rotated).\n selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0]) || // Do not resize when in crop mode\n this.state.croppingElementId) {\n return false;\n }\n\n this.setState({\n // TODO: rename this state field to \"isScaling\" to distinguish\n // it from the generic \"isResizing\" which includes scaling and\n // rotating\n isResizing: transformHandleType && transformHandleType !== \"rotation\",\n isRotating: transformHandleType === \"rotation\",\n activeEmbeddable: null\n });\n const pointerCoords = pointerDownState.lastCoords;\n let [resizeX, resizeY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x - pointerDownState.resize.offset.x, pointerCoords.y - pointerDownState.resize.offset.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const frameElementsOffsetsMap = new Map();\n selectedFrames.forEach(frame => {\n const elementsInFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getFrameChildren)(this.scene.getNonDeletedElements(), frame.id);\n elementsInFrame.forEach(element => {\n frameElementsOffsetsMap.set(frame.id + element.id, {\n x: element.x - frame.x,\n y: element.y - frame.y\n });\n });\n }); // check needed for avoiding flickering when a key gets pressed\n // during dragging\n\n if (!this.state.selectedElementsAreBeingDragged) {\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n const dragOffset = {\n x: gridX - pointerDownState.originInGrid.x,\n y: gridY - pointerDownState.originInGrid.y\n };\n const originalElements = [...pointerDownState.originalElements.values()];\n this.maybeCacheReferenceSnapPoints(event, selectedElements);\n const {\n snapOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.snapResizingElements)(selectedElements, (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(originalElements, this.state), this, event, dragOffset, transformHandleType);\n resizeX += snapOffset.x;\n resizeY += snapOffset.y;\n this.setState({\n snapLines\n });\n }\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.transformElements)(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event), (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldResizeFromCenter)(event), selectedElements.some(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(element)) ? !(0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event) : (0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldMaintainAspectRatio)(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {\n const suggestedBindings = (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getSuggestedBindingsForArrows)(selectedElements, this.scene.getNonDeletedElementsMap());\n const elementsToHighlight = new Set();\n selectedFrames.forEach(frame => {\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getNonDeletedElements(), frame, this.state, this.scene.getNonDeletedElementsMap()).forEach(element => elementsToHighlight.add(element));\n });\n this.setState({\n elementsToHighlight: [...elementsToHighlight],\n suggestedBindings\n });\n return true;\n }\n\n return false;\n };\n\n this.getContextMenuItems = type => {\n const options = [];\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg); // canvas contextMenu\n // -------------------------------------------------------------------------\n\n if (type === \"canvas\") {\n if (this.state.viewModeEnabled) {\n return [...options, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_39__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats, _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_54__.actionToggleLaserPointer];\n }\n\n return [_actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsPng, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyAsSvg, _actions__WEBPACK_IMPORTED_MODULE_5__.copyText, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSelectAll, _actions_actionElementLock__WEBPACK_IMPORTED_MODULE_48__.actionUnlockAllElements, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleGridMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleObjectsSnapMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleZenMode, _actions_actionToggleViewMode__WEBPACK_IMPORTED_MODULE_39__.actionToggleViewMode, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleStats];\n } // element contextMenu\n // -------------------------------------------------------------------------\n\n\n options.push(_actions__WEBPACK_IMPORTED_MODULE_5__.copyText);\n\n if (this.state.viewModeEnabled) {\n return [_actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, ...options];\n }\n\n return [_ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCut, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopy, _actions_actionClipboard__WEBPACK_IMPORTED_MODULE_52__.actionPaste, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionSelectAllElementsInFrame, _actions_actionFrame__WEBPACK_IMPORTED_MODULE_53__.actionRemoveAllElementsFromFrame, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleCropEditor, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, ...options, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionCopyStyles, _actions__WEBPACK_IMPORTED_MODULE_5__.actionPasteStyles, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionGroup, _actions_actionTextAutoResize__WEBPACK_IMPORTED_MODULE_90__.actionTextAutoResize, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUnbindText, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBindText, _actions_actionBoundText__WEBPACK_IMPORTED_MODULE_59__.actionWrapTextInContainer, _actions__WEBPACK_IMPORTED_MODULE_5__.actionUngroup, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionAddToLibrary, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendBackward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringForward, _actions__WEBPACK_IMPORTED_MODULE_5__.actionSendToBack, _actions__WEBPACK_IMPORTED_MODULE_5__.actionBringToFront, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipHorizontal, _actions__WEBPACK_IMPORTED_MODULE_5__.actionFlipVertical, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleLinearEditor, _actions__WEBPACK_IMPORTED_MODULE_5__.actionLink, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDuplicateSelection, _actions__WEBPACK_IMPORTED_MODULE_5__.actionToggleElementLock, _ContextMenu__WEBPACK_IMPORTED_MODULE_36__.CONTEXT_MENU_SEPARATOR, _actions__WEBPACK_IMPORTED_MODULE_5__.actionDeleteSelected];\n };\n\n this.handleWheel = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n // if not scrolling on canvas/wysiwyg, ignore\n if (!(event.target instanceof HTMLCanvasElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLIFrameElement)) {\n // prevent zooming the browser (but allow scrolling DOM)\n if (event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n }\n\n return;\n }\n\n event.preventDefault();\n\n if (isPanning) {\n return;\n }\n\n const {\n deltaX,\n deltaY\n } = event; // note that event.ctrlKey is necessary to handle pinch zooming\n\n if ( //zsviczian\n (event.metaKey || event.ctrlKey) && !this.state.allowWheelZoom || !(event.metaKey || event.ctrlKey) && this.state.allowWheelZoom) {\n const sign = Math.sign(deltaY);\n const MAX_STEP = _constants__WEBPACK_IMPORTED_MODULE_12__.ZOOM_STEP * 100;\n const absDelta = Math.abs(deltaY);\n let delta = deltaY;\n\n if (absDelta > MAX_STEP) {\n delta = MAX_STEP * sign;\n }\n\n let newZoom = this.state.zoom.value - delta / 100; // increase zoom steps the more zoomed-in we are (applies to >100% only)\n\n newZoom += Math.log10(Math.max(1, this.state.zoom.value)) * -sign * // reduced amplification for small deltas (small movements on a trackpad)\n Math.min(1, absDelta / 20);\n this.translateCanvas(state => Object.assign(Object.assign({}, (0,_scene_zoom__WEBPACK_IMPORTED_MODULE_30__.getStateForZoom)({\n viewportX: this.lastViewportPosition.x,\n viewportY: this.lastViewportPosition.y,\n nextZoom: (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getNormalizedZoom)(newZoom)\n }, state)), {\n shouldCacheIgnoreZoom: true\n }));\n this.resetShouldCacheIgnoreZoomDebounced();\n return;\n } // scroll horizontally when shift pressed\n\n\n if (event.shiftKey) {\n this.translateCanvas(({\n zoom,\n scrollX\n }) => ({\n // on Mac, shift+wheel tends to result in deltaX\n scrollX: scrollX - (deltaY || deltaX) / zoom.value\n }));\n return;\n }\n\n this.translateCanvas(({\n zoom,\n scrollX,\n scrollY\n }) => ({\n scrollX: scrollX - deltaX / zoom.value,\n scrollY: scrollY - deltaY / zoom.value\n }));\n });\n\n this.savePointer = (x, y, button) => {\n var _a, _b;\n\n if (!x || !y) {\n return;\n }\n\n const {\n x: sceneX,\n y: sceneY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: x,\n clientY: y\n }, this.state);\n\n if (isNaN(sceneX) || isNaN(sceneY)) {// sometimes the pointer goes off screen\n }\n\n const pointer = {\n x: sceneX,\n y: sceneY,\n tool: this.state.activeTool.type === \"laser\" ? \"laser\" : \"pointer\"\n };\n (_b = (_a = this.props).onPointerUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, {\n pointer,\n button,\n pointersMap: gesture.pointers\n });\n };\n\n this.resetShouldCacheIgnoreZoomDebounced = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.debounce)(() => {\n if (!this.unmounted) {\n this.setState({\n shouldCacheIgnoreZoom: false\n });\n }\n }, 300);\n\n this.updateDOMRect = cb => {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n width,\n height,\n left: offsetLeft,\n top: offsetTop\n } = excalidrawContainer.getBoundingClientRect();\n const {\n width: currentWidth,\n height: currentHeight,\n offsetTop: currentOffsetTop,\n offsetLeft: currentOffsetLeft\n } = this.state;\n\n if (width === currentWidth && height === currentHeight && offsetLeft === currentOffsetLeft && offsetTop === currentOffsetTop) {\n if (cb) {\n cb();\n }\n\n return;\n } //zsviczian\n\n\n if (width === 0 || height === 0) {\n if (cb) {\n cb();\n }\n\n return;\n }\n\n this.setState({\n width,\n height,\n offsetLeft,\n offsetTop\n }, () => {\n cb && cb();\n });\n }\n };\n\n this.refresh = () => {\n this.setState(Object.assign({}, this.getCanvasOffsets()));\n };\n\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_10__.getDefaultAppState)();\n const {\n excalidrawAPI,\n viewModeEnabled = false,\n zenModeEnabled = false,\n gridModeEnabled = false,\n objectsSnapModeEnabled = false,\n theme = defaultAppState.theme,\n initState,\n //zsviczian\n name = `${(0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.untitled\")}-${(0,_utils__WEBPACK_IMPORTED_MODULE_34__.getDateTime)()}`\n } = props;\n this.state = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaultAppState), {\n theme,\n isLoading: true\n }), this.getCanvasOffsets()), {\n viewModeEnabled,\n zenModeEnabled,\n objectsSnapModeEnabled,\n gridModeEnabled: gridModeEnabled !== null && gridModeEnabled !== void 0 ? gridModeEnabled : defaultAppState.gridModeEnabled,\n name,\n width: window.innerWidth,\n height: window.innerHeight\n }), initState !== null && initState !== void 0 ? initState : {});\n this.id = (0,nanoid__WEBPACK_IMPORTED_MODULE_101__.nanoid)();\n (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_82__.initializeObsidianUtils)();\n this.library = new _data_library__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this);\n this.actionManager = new _actions_manager__WEBPACK_IMPORTED_MODULE_7__.ActionManager(this.syncActionResult, () => this.state, () => this.scene.getElementsIncludingDeleted(), this);\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_29__[\"default\"]();\n this.canvas = document.createElement(\"canvas\");\n this.rc = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_3__[\"default\"].canvas(this.canvas);\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_65__.Renderer(this.scene);\n this.visibleElements = [];\n this.store = new _store__WEBPACK_IMPORTED_MODULE_76__.Store();\n this.history = new _history__WEBPACK_IMPORTED_MODULE_24__.History();\n\n if (excalidrawAPI) {\n const api = {\n updateScene: this.updateScene,\n updateLibrary: this.library.updateLibrary,\n addFiles: this.addFiles,\n resetScene: this.resetScene,\n getSceneElementsIncludingDeleted: this.getSceneElementsIncludingDeleted,\n history: {\n clear: this.resetHistory\n },\n scrollToContent: this.scrollToContent,\n zoomToFit: this.zoomToFit,\n startLineEditor: this.startLineEditor,\n getSceneElements: this.getSceneElements,\n getAppState: () => this.state,\n getFiles: () => this.files,\n getName: this.getName,\n registerAction: action => {\n this.actionManager.registerAction(action);\n },\n refresh: this.refresh,\n setToast: this.setToast,\n updateContainerSize: this.updateContainerSize,\n id: this.id,\n selectElements: this.selectElements,\n sendBackward: this.sendBackward,\n bringForward: this.bringForward,\n sendToBack: this.sendToBack,\n bringToFront: this.bringToFront,\n setMobileModeAllowed: this.setMobileModeAllowed,\n setActiveTool: this.setActiveTool,\n setCursor: this.setCursor,\n resetCursor: this.resetCursor,\n updateFrameRendering: this.updateFrameRendering,\n toggleSidebar: this.toggleSidebar,\n getHTMLIFrameElement: id => this.getHTMLIFrameElement(id),\n onChange: cb => this.onChangeEmitter.on(cb),\n onPointerDown: cb => this.onPointerDownEmitter.on(cb),\n onPointerUp: cb => this.onPointerUpEmitter.on(cb),\n onScrollChange: cb => this.onScrollChangeEmitter.on(cb),\n onUserFollow: cb => this.onUserFollowEmitter.on(cb)\n };\n\n if (typeof excalidrawAPI === \"function\") {\n excalidrawAPI(api);\n } else {\n console.error(\"excalidrawAPI should be a function!\");\n }\n }\n\n this.excalidrawContainerValue = {\n container: this.excalidrawContainerRef.current,\n id: this.id\n };\n this.fonts = new _fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts(this.scene);\n this.history = new _history__WEBPACK_IMPORTED_MODULE_24__.History();\n this.actionManager.registerAll(_actions_register__WEBPACK_IMPORTED_MODULE_8__.actions);\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createUndoAction)(this.history, this.store));\n this.actionManager.registerAction((0,_actions_actionHistory__WEBPACK_IMPORTED_MODULE_6__.createRedoAction)(this.history, this.store));\n }\n\n onWindowMessage(event) {\n if (event.origin !== \"https://player.vimeo.com\" && event.origin !== \"https://www.youtube.com\") {\n return;\n }\n\n let data = null;\n\n try {\n data = JSON.parse(event.data);\n } catch (e) {}\n\n if (!data) {\n return;\n }\n\n switch (event.origin) {\n case \"https://player.vimeo.com\":\n //Allowing for multiple instances of Excalidraw running in the window\n if (data.method === \"paused\") {\n let source = null;\n const iframes = document.body.querySelectorAll(\"iframe.excalidraw__embeddable\");\n\n if (!iframes) {\n break;\n }\n\n for (const iframe of iframes) {\n if (iframe.contentWindow === event.source) {\n source = iframe.contentWindow;\n }\n }\n\n source === null || source === void 0 ? void 0 : source.postMessage(JSON.stringify({\n method: data.value ? \"play\" : \"pause\",\n value: true\n }), \"*\");\n }\n\n break;\n\n case \"https://www.youtube.com\":\n if (data.event === \"infoDelivery\" && data.info && data.id && typeof data.info.playerState === \"number\") {\n const id = data.id;\n const playerState = data.info.playerState;\n\n if (Object.values(_constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES).includes(playerState)) {\n YOUTUBE_VIDEO_STATES.set(id, playerState);\n }\n }\n\n break;\n }\n }\n\n cacheEmbeddableRef(element, ref) {\n if (ref) {\n this.iFrameRefs.set(element.id, ref);\n }\n }\n\n getHTMLIFrameElement(element) {\n //zsviczian\n if (typeof element === \"string\") {\n return this.iFrameRefs.get(element);\n }\n\n return this.iFrameRefs.get(element.id);\n }\n\n handleEmbeddableCenterClick(element) {\n var _a, _b, _c, _d;\n\n if (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) === element && ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"active\") {\n return;\n } // The delay serves two purposes\n // 1. To prevent first click propagating to iframe on mobile,\n // else the click will immediately start and stop the video\n // 2. If the user double clicks the frame center to activate it\n // without the delay youtube will immediately open the video\n // in fullscreen mode\n\n\n setTimeout(() => {\n this.setState({\n activeEmbeddable: {\n element,\n state: \"active\"\n },\n selectedElementIds: {\n [element.id]: true\n },\n newElement: null,\n selectionElement: null\n });\n }, 100);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(element)) {\n return;\n }\n\n const iframe = this.getHTMLIFrameElement(element);\n\n if (!(iframe === null || iframe === void 0 ? void 0 : iframe.contentWindow)) {\n return;\n }\n\n if (iframe.src.includes(\"youtube\")) {\n const state = YOUTUBE_VIDEO_STATES.get(element.id);\n\n if (!state) {\n YOUTUBE_VIDEO_STATES.set(element.id, _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.UNSTARTED);\n iframe.contentWindow.postMessage(JSON.stringify({\n event: \"listening\",\n id: element.id\n }), \"*\");\n }\n\n switch (state) {\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.PLAYING:\n case _constants__WEBPACK_IMPORTED_MODULE_12__.YOUTUBE_STATES.BUFFERING:\n (_c = iframe.contentWindow) === null || _c === void 0 ? void 0 : _c.postMessage(JSON.stringify({\n event: \"command\",\n func: \"pauseVideo\",\n args: \"\"\n }), \"*\");\n break;\n\n default:\n (_d = iframe.contentWindow) === null || _d === void 0 ? void 0 : _d.postMessage(JSON.stringify({\n event: \"command\",\n func: \"playVideo\",\n args: \"\"\n }), \"*\");\n }\n }\n\n if (iframe.src.includes(\"player.vimeo.com\")) {\n iframe.contentWindow.postMessage(JSON.stringify({\n method: \"paused\" //video play/pause in onWindowMessage handler\n\n }), \"*\");\n }\n }\n\n isIframeLikeElementCenter(el, event, sceneX, sceneY) {\n var _a, _b;\n\n return el && !event.altKey && !event.shiftKey && !event.metaKey && !event.ctrlKey && (((_a = this.state.activeEmbeddable) === null || _a === void 0 ? void 0 : _a.element) !== el || ((_b = this.state.activeEmbeddable) === null || _b === void 0 ? void 0 : _b.state) === \"hover\" || !this.state.activeEmbeddable) && sceneX >= el.x + el.width / 3 && sceneX <= el.x + 2 * el.width / 3 && sceneY >= el.y + el.height / 3 && sceneY <= el.y + 2 * el.height / 3;\n }\n\n renderEmbeddables() {\n const scale = this.state.zoom.value;\n const normalizedWidth = this.state.width;\n const normalizedHeight = this.state.height;\n const embeddableElements = this.scene.getNonDeletedElements().filter(el => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(el) && this.embedsValidationStatus.get(el.id) === true || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el));\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n children: embeddableElements.map(el => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;\n\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: el.x,\n sceneY: el.y\n }, this.state);\n const isVisible = (0,_element_sizeHelpers__WEBPACK_IMPORTED_MODULE_27__.isElementInViewport)(el, normalizedWidth, normalizedHeight, this.state, this.scene.getNonDeletedElementsMap());\n const hasBeenInitialized = this.initializedEmbeds.has(el.id);\n\n if (isVisible && !hasBeenInitialized) {\n this.initializedEmbeds.add(el.id);\n }\n\n const shouldRender = isVisible || hasBeenInitialized;\n\n if (!shouldRender) {\n return null;\n }\n\n let src;\n const embedLink = (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.getEmbedLink)((0,_data_url__WEBPACK_IMPORTED_MODULE_46__.toValidURL)(el.link || \"\")); //zsviczian\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el)) {\n src = null;\n const data = ((_b = (_a = el.customData) === null || _a === void 0 ? void 0 : _a.generationData) !== null && _b !== void 0 ? _b : this.magicGenerations.get(el.id)) || {\n status: \"error\",\n message: \"No generation data\",\n code: \"ERR_NO_GENERATION_DATA\"\n };\n\n if (data.status === \"done\") {\n const html = data.html;\n src = {\n intrinsicSize: {\n w: el.width,\n h: el.height\n },\n type: \"document\",\n srcdoc: () => {\n return html;\n }\n };\n } else if (data.status === \"pending\") {\n src = {\n intrinsicSize: {\n w: el.width,\n h: el.height\n },\n type: \"document\",\n srcdoc: () => {\n return (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.createSrcDoc)(`\n <style>\n html, body {\n width: 100%;\n height: 100%;\n color: ${this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.DARK ? \"white\" : \"black\"};\n }\n body {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n gap: 1rem;\n }\n\n .Spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-left: auto;\n margin-right: auto;\n }\n\n .Spinner svg {\n animation: rotate 1.6s linear infinite;\n transform-origin: center center;\n width: 40px;\n height: 40px;\n }\n\n .Spinner circle {\n stroke: currentColor;\n animation: dash 1.6s linear 0s infinite;\n stroke-linecap: round;\n }\n\n @keyframes rotate {\n 100% {\n transform: rotate(360deg);\n }\n }\n\n @keyframes dash {\n 0% {\n stroke-dasharray: 1, 300;\n stroke-dashoffset: 0;\n }\n 50% {\n stroke-dasharray: 150, 300;\n stroke-dashoffset: -200;\n }\n 100% {\n stroke-dasharray: 1, 300;\n stroke-dashoffset: -280;\n }\n }\n </style>\n <div class=\"Spinner\">\n <svg\n viewBox=\"0 0 100 100\"\n >\n <circle\n cx=\"50\"\n cy=\"50\"\n r=\"46\"\n stroke-width=\"8\"\n fill=\"none\"\n stroke-miter-limit=\"10\"\n />\n </svg>\n </div>\n <div>Generating...</div>\n `);\n }\n };\n } else {\n let message;\n\n if (data.code === \"ERR_GENERATION_INTERRUPTED\") {\n message = \"Generation was interrupted...\";\n } else {\n message = data.message || \"Generation failed\";\n }\n\n src = {\n intrinsicSize: {\n w: el.width,\n h: el.height\n },\n type: \"document\",\n srcdoc: () => {\n return (0,_element_embeddable__WEBPACK_IMPORTED_MODULE_35__.createSrcDoc)(`\n <style>\n html, body {\n height: 100%;\n }\n body {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: ${_colors__WEBPACK_IMPORTED_MODULE_71__.COLOR_PALETTE.red[3]};\n }\n h1, h3 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n }\n </style>\n <h1>Error!</h1>\n <h3>${message}</h3>\n `);\n }\n };\n }\n } else {\n src = embedLink; //zsviczian getEmbedLink(toValidURL(el.link || \"\"));\n }\n\n const isActive = ((_c = this.state.activeEmbeddable) === null || _c === void 0 ? void 0 : _c.element) === el && ((_d = this.state.activeEmbeddable) === null || _d === void 0 ? void 0 : _d.state) === \"active\";\n const isHovered = ((_e = this.state.activeEmbeddable) === null || _e === void 0 ? void 0 : _e.element) === el && ((_f = this.state.activeEmbeddable) === null || _f === void 0 ? void 0 : _f.state) === \"hover\";\n const isWebview = //zsviczian\n !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el) && this.props.renderWebview && (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) !== \"document\" && !((_h = (_g = embedLink === null || embedLink === void 0 ? void 0 : embedLink.link) === null || _g === void 0 ? void 0 : _g.startsWith) === null || _h === void 0 ? void 0 : _h.call(_g, \"https://player.vimeo.com\")); // Modify the scale based on el.scale property\n\n const [xScale, yScale] = (_j = el.scale) !== null && _j !== void 0 ? _j : [1, 1]; //zsviczian\n\n const scaledTransform = `scale(${scale * xScale}, ${scale * yScale})`;\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw__embeddable-container\", {\n \"is-hovered\": isHovered\n }),\n style: {\n transform: isVisible ? `translate(${x - this.state.offsetLeft}px, ${y - this.state.offsetTop}px) ${scaledTransform}` : \"none\",\n display: isVisible ? \"block\" : \"none\",\n opacity: (0,_renderer_renderElement__WEBPACK_IMPORTED_MODULE_81__.getRenderOpacity)(el, (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(el, this.scene.getNonDeletedElementsMap()), this.elementsPendingErasure, null),\n [\"--embeddable-radius\"]: `${(0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getCornerRadius)(Math.min(el.width, el.height), el) / xScale //zsviczian\n }px`\n }\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", Object.assign({\n //this is a hack that addresses isse with embedded excalidraw.com embeddable\n //https://github.com/excalidraw/excalidraw/pull/6691#issuecomment-1607383938\n\n /*ref={(ref) => {\n if (!this.excalidrawContainerRef.current) {\n return;\n }\n const container = this.excalidrawContainerRef.current;\n const sh = container.scrollHeight;\n const ch = container.clientHeight;\n if (sh !== ch) {\n container.style.height = `${sh}px`;\n setTimeout(() => {\n container.style.height = `100%`;\n });\n }\n }}*/\n className: \"excalidraw__embeddable-container__inner\",\n style: {\n width: isVisible ? `${el.width / xScale}px` : 0,\n height: isVisible ? `${el.height / yScale}px` : 0,\n transform: isVisible ? `rotate(${el.angle}rad)` : \"none\",\n pointerEvents: isActive ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled\n }\n }, {\n children: [isHovered && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable-hint\"\n }, {\n children: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"buttons.embeddableInteractionButton\")\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: \"excalidraw__embeddable__outer\",\n style: {\n padding: `${el.strokeWidth / (4 * el.scale[0])}px` //zsviczian MDEmbeddable round border cutoff issue\n\n }\n }, {\n children: (_m = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(el) ? (_l = (_k = this.props).renderEmbeddable) === null || _l === void 0 ? void 0 : _l.call(_k, el, this.state) //zsviczian\n : null) !== null && _m !== void 0 ? _m : isWebview ? //zsviczian\n (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"webview\", {\n ref: ref => this.cacheEmbeddableRef(el, ref),\n className: \"excalidraw__embeddable\",\n src: (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) === \"generic\" || (embedLink === null || embedLink === void 0 ? void 0 : embedLink.type) === \"video\" ? embedLink.link : \"\",\n title: \"Excalidraw Embedded Content\",\n allowFullScreen: true\n }) : (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"iframe\", {\n ref: ref => this.cacheEmbeddableRef(el, ref),\n className: \"excalidraw__embeddable\",\n srcDoc: (src === null || src === void 0 ? void 0 : src.type) === \"document\" ? src.srcdoc(this.state.theme) : undefined,\n src: (src === null || src === void 0 ? void 0 : src.type) !== \"document\" ? (_o = src === null || src === void 0 ? void 0 : src.link) !== null && _o !== void 0 ? _o : \"\" : undefined,\n // https://stackoverflow.com/q/18470015\n scrolling: \"no\",\n referrerPolicy: \"no-referrer-when-downgrade\",\n title: \"Excalidraw Embedded Content\",\n allow: \"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\",\n allowFullScreen: true,\n sandbox: `${((_p = src === null || src === void 0 ? void 0 : src.sandbox) === null || _p === void 0 ? void 0 : _p.allowSameOrigin) ? \"allow-same-origin\" : \"\"} allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads`\n })\n }))]\n }))\n }), el.id);\n })\n });\n }\n\n toggleOverscrollBehavior(event) {\n // when pointer inside editor, disable overscroll behavior to prevent\n // panning to trigger history back/forward on MacOS Chrome\n document.documentElement.style.overscrollBehaviorX = event.type === \"pointerenter\" ? \"none\" : \"auto\";\n }\n\n render() {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;\n\n const selectedElements = this.scene.getSelectedElements(this.state);\n const {\n renderTopRightUI,\n renderCustomStats\n } = this.props;\n const sceneNonce = this.scene.getSceneNonce();\n const {\n elementsMap,\n visibleElements\n } = this.renderer.getRenderableElements({\n sceneNonce,\n zoom: this.state.zoom,\n offsetLeft: this.state.offsetLeft,\n offsetTop: this.state.offsetTop,\n scrollX: this.state.scrollX,\n scrollY: this.state.scrollY,\n height: this.state.height,\n width: this.state.width,\n editingTextElement: this.state.editingTextElement,\n newElementId: (_a = this.state.newElement) === null || _a === void 0 ? void 0 : _a.id,\n pendingImageElementId: this.state.pendingImageElementId\n });\n this.visibleElements = visibleElements;\n const allElementsMap = this.scene.getNonDeletedElementsMap();\n const shouldBlockPointerEvents = this.state.selectionElement || this.state.newElement || this.state.selectedElementsAreBeingDragged || this.state.resizingElement || this.state.activeTool.type === \"laser\" && // technically we can just test on this once we make it more safe\n this.state.cursorButton === \"down\";\n const firstSelectedElement = selectedElements[0]; //zsviczian\n\n const isHighlighter = (_d = (_c = (_b = this.state.newElement) === null || _b === void 0 ? void 0 : _b.customData) === null || _c === void 0 ? void 0 : _c.strokeOptions) === null || _d === void 0 ? void 0 : _d.highlighter;\n return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", Object.assign({\n className: (0,clsx__WEBPACK_IMPORTED_MODULE_4__[\"default\"])(\"excalidraw excalidraw-container\", {\n \"excalidraw--view-mode\": this.state.viewModeEnabled,\n \"excalidraw--mobile\": this.device.editor.isMobile || !(this.state.viewModeEnabled || this.state.zenModeEnabled) && this.state.trayModeEnabled //zsviczian\n\n }),\n style: Object.assign({\n //zsviczian\n [\"--ui-pointerEvents\"]: shouldBlockPointerEvents ? _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.disabled : _constants__WEBPACK_IMPORTED_MODULE_12__.POINTER_EVENTS.enabled\n }, this.state.dynamicStyle),\n ref: this.excalidrawContainerRef,\n onDrop: this.handleAppOnDrop,\n tabIndex: 0,\n onKeyDown: this.props.handleKeyboardGlobally ? undefined : this.onKeyDown,\n onPointerEnter: this.toggleOverscrollBehavior,\n onPointerLeave: this.toggleOverscrollBehavior\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppContext.Provider, Object.assign({\n value: this\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AppPropsContext.Provider, Object.assign({\n value: this.props\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawContainerContext.Provider, Object.assign({\n value: this.excalidrawContainerValue\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DeviceContext.Provider, Object.assign({\n value: this.device\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawSetAppStateContext.Provider, Object.assign({\n value: this.setAppState\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ExcalidrawAppStateContext.Provider, Object.assign({\n value: this.state\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawElementsContext.Provider, Object.assign({\n value: this.scene.getNonDeletedElements()\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(ExcalidrawActionManagerContext.Provider, Object.assign({\n value: this.actionManager\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_LayerUI__WEBPACK_IMPORTED_MODULE_37__[\"default\"], Object.assign({\n canvas: this.canvas,\n appState: this.state,\n files: this.files,\n setAppState: this.setAppState,\n actionManager: this.actionManager,\n elements: this.scene.getNonDeletedElements(),\n onLockToggle: this.toggleLock,\n onPenModeToggle: this.togglePenMode,\n onHandToolToggle: this.onHandToolToggle,\n langCode: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.getLanguage)().code,\n renderTopRightUI: renderTopRightUI,\n renderCustomStats: renderCustomStats,\n showExitZenModeBtn: typeof ((_e = this.props) === null || _e === void 0 ? void 0 : _e.zenModeEnabled) === \"undefined\" && this.state.zenModeEnabled,\n UIOptions: this.props.UIOptions,\n onExportImage: this.onExportImage,\n renderWelcomeScreen: !this.state.isLoading && this.state.showWelcomeScreen && this.state.activeTool.type === \"selection\" && !this.state.zenModeEnabled && !this.scene.getElementsIncludingDeleted().length,\n app: this,\n isCollaborating: this.props.isCollaborating\n }, {\n children: this.props.children\n })), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-textEditorContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-contextMenuContainer\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", {\n className: \"excalidraw-eye-dropper-container\"\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_SVGLayer__WEBPACK_IMPORTED_MODULE_67__.SVGLayer, {\n trails: [this.laserTrails, this.eraserTrail]\n }), selectedElements.length === 1 && this.state.showHyperlinkPopup && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_components_hyperlink_Hyperlink__WEBPACK_IMPORTED_MODULE_45__.Hyperlink, {\n element: firstSelectedElement,\n elementsMap: allElementsMap,\n setAppState: this.setAppState,\n onLinkOpen: this.props.onLinkOpen,\n setToast: this.setToast,\n updateEmbedValidationStatus: this.updateEmbedValidationStatus\n }, firstSelectedElement.id), this.props.aiEnabled !== false && selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isMagicFrameElement)(firstSelectedElement) && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_element_ElementCanvasButtons__WEBPACK_IMPORTED_MODULE_70__.ElementCanvasButtons, Object.assign({\n element: firstSelectedElement,\n elementsMap: elementsMap\n }, {\n children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MagicButton__WEBPACK_IMPORTED_MODULE_72__.ElementCanvasButton, {\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.convertToCode\"),\n icon: _icons__WEBPACK_IMPORTED_MODULE_73__.MagicIcon,\n checked: false,\n onChange: () => this.onMagicFrameGenerate(firstSelectedElement, \"button\")\n })\n })), selectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(firstSelectedElement) && ((_g = (_f = firstSelectedElement.customData) === null || _f === void 0 ? void 0 : _f.generationData) === null || _g === void 0 ? void 0 : _g.status) === \"done\" && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(_element_ElementCanvasButtons__WEBPACK_IMPORTED_MODULE_70__.ElementCanvasButtons, Object.assign({\n element: firstSelectedElement,\n elementsMap: elementsMap\n }, {\n children: [(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MagicButton__WEBPACK_IMPORTED_MODULE_72__.ElementCanvasButton, {\n title: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"labels.copySource\"),\n icon: _icons__WEBPACK_IMPORTED_MODULE_73__.copyIcon,\n checked: false,\n onChange: () => this.onIframeSrcCopy(firstSelectedElement)\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_MagicButton__WEBPACK_IMPORTED_MODULE_72__.ElementCanvasButton, {\n title: \"Enter fullscreen\",\n icon: _icons__WEBPACK_IMPORTED_MODULE_73__.fullscreenIcon,\n checked: false,\n onChange: () => {\n const iframe = this.getHTMLIFrameElement(firstSelectedElement);\n\n if (iframe) {\n try {\n iframe.requestFullscreen();\n this.setState({\n activeEmbeddable: {\n element: firstSelectedElement,\n state: \"active\"\n },\n selectedElementIds: {\n [firstSelectedElement.id]: true\n },\n newElement: null,\n selectionElement: null\n });\n } catch (err) {\n console.warn(err);\n this.setState({\n errorMessage: \"Couldn't enter fullscreen\"\n });\n }\n }\n }\n })]\n })), this.state.toast !== null && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_Toast__WEBPACK_IMPORTED_MODULE_38__.Toast, {\n message: this.state.toast.message,\n onClose: () => this.setToast(null),\n duration: this.state.toast.duration,\n closable: this.state.toast.closable\n }), this.state.contextMenu && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_ContextMenu__WEBPACK_IMPORTED_MODULE_36__.ContextMenu, {\n items: this.state.contextMenu.items,\n top: this.state.contextMenu.top,\n left: this.state.contextMenu.left,\n actionManager: this.actionManager,\n onClose: callback => {\n this.setState({\n contextMenu: null\n }, () => {\n this.focusContainer();\n callback === null || callback === void 0 ? void 0 : callback();\n });\n }\n }), this.state.newElement && isHighlighter && //zsviczian\n (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases_NewElementCanvas__WEBPACK_IMPORTED_MODULE_94__[\"default\"], {\n appState: this.state,\n scale: window.devicePixelRatio,\n rc: this.rc,\n elementsMap: elementsMap,\n allElementsMap: allElementsMap,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: false,\n canvasBackgroundColor: this.state.viewBackgroundColor,\n embedsValidationStatus: this.embedsValidationStatus,\n elementsPendingErasure: this.elementsPendingErasure,\n pendingFlowchartNodes: null,\n isHighlighterPenDrawing: isHighlighter //zsviczian\n\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_64__.StaticCanvas, {\n canvas: this.canvas,\n rc: this.rc,\n elementsMap: elementsMap,\n allElementsMap: allElementsMap,\n visibleElements: visibleElements,\n sceneNonce: sceneNonce,\n selectionNonce: (_h = this.state.selectionElement) === null || _h === void 0 ? void 0 : _h.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isGridModeEnabled)(this),\n canvasBackgroundColor: this.state.viewBackgroundColor,\n embedsValidationStatus: this.embedsValidationStatus,\n elementsPendingErasure: this.elementsPendingErasure,\n pendingFlowchartNodes: this.flowChartCreator.pendingNodes,\n isHighlighterPenDrawing: isHighlighter //zsviczian\n\n }\n }), this.state.newElement && !isHighlighter && //zsviczian\n (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases_NewElementCanvas__WEBPACK_IMPORTED_MODULE_94__[\"default\"], {\n appState: this.state,\n scale: window.devicePixelRatio,\n rc: this.rc,\n elementsMap: elementsMap,\n allElementsMap: allElementsMap,\n renderConfig: {\n imageCache: this.imageCache,\n isExporting: false,\n renderGrid: false,\n canvasBackgroundColor: this.state.viewBackgroundColor,\n embedsValidationStatus: this.embedsValidationStatus,\n elementsPendingErasure: this.elementsPendingErasure,\n pendingFlowchartNodes: null,\n isHighlighterPenDrawing: isHighlighter //zsviczian\n\n }\n }), (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_canvases__WEBPACK_IMPORTED_MODULE_64__.InteractiveCanvas, {\n containerRef: this.excalidrawContainerRef,\n canvas: this.interactiveCanvas,\n elementsMap: elementsMap,\n visibleElements: visibleElements,\n allElementsMap: allElementsMap,\n selectedElements: selectedElements,\n sceneNonce: sceneNonce,\n selectionNonce: (_j = this.state.selectionElement) === null || _j === void 0 ? void 0 : _j.versionNonce,\n scale: window.devicePixelRatio,\n appState: this.state,\n device: this.device,\n renderInteractiveSceneCallback: this.renderInteractiveSceneCallback,\n handleCanvasRef: this.handleInteractiveCanvasRef,\n onContextMenu: this.handleCanvasContextMenu,\n onPointerMove: this.handleCanvasPointerMove,\n onPointerUp: this.handleCanvasPointerUp,\n onPointerCancel: this.removePointer,\n onTouchMove: this.handleTouchMove,\n onPointerDown: this.handleCanvasPointerDown,\n onDoubleClick: this.handleCanvasDoubleClick\n }), this.state.userToFollow && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_FollowMode_FollowMode__WEBPACK_IMPORTED_MODULE_74__[\"default\"], {\n width: this.state.width,\n height: this.state.height,\n userToFollow: this.state.userToFollow,\n onDisconnect: this.maybeUnfollowRemoteUser\n }), this.renderFrameNames(), ((_k = this.state.activeEmbeddable) === null || _k === void 0 ? void 0 : _k.state) === \"active\" && ( //zsviczian\n (_m = (_l = this.props).renderEmbeddableMenu) === null || _m === void 0 ? void 0 : _m.call(_l, this.state))]\n })), this.renderEmbeddables()]\n }))\n }))\n }))\n }))\n }))\n }))\n }))\n }));\n }\n\n setPlugins(plugins) {\n Object.assign(this.plugins, plugins);\n }\n\n async onMagicFrameGenerate(magicFrame, source) {\n var _a;\n\n const generateDiagramToCode = (_a = this.plugins.diagramToCode) === null || _a === void 0 ? void 0 : _a.generate;\n\n if (!generateDiagramToCode) {\n this.setState({\n errorMessage: \"No diagram to code plugin found\"\n });\n return;\n }\n\n const magicFrameChildren = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsOverlappingFrame)(this.scene.getNonDeletedElements(), magicFrame).filter(el => !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isMagicFrameElement)(el));\n\n if (!magicFrameChildren.length) {\n if (source === \"button\") {\n this.setState({\n errorMessage: \"Cannot generate from an empty frame\"\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (no-children)\", \"d2c\");\n } else {\n this.setActiveTool({\n type: \"magicframe\"\n });\n }\n\n return;\n }\n\n const frameElement = this.insertIframeElement({\n sceneX: magicFrame.x + magicFrame.width + 30,\n sceneY: magicFrame.y,\n width: magicFrame.width,\n height: magicFrame.height\n });\n\n if (!frameElement) {\n return;\n }\n\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"pending\"\n }\n });\n this.setState({\n selectedElementIds: {\n [frameElement.id]: true\n }\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (start)\", \"d2c\");\n\n try {\n const {\n html\n } = await generateDiagramToCode({\n frame: magicFrame,\n children: magicFrameChildren\n });\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (success)\", \"d2c\");\n\n if (!html.trim()) {\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"error\",\n code: \"ERR_OAI\",\n message: \"Nothing genereated :(\"\n }\n });\n return;\n }\n\n const parsedHtml = html.includes(\"<!DOCTYPE html>\") && html.includes(\"</html>\") ? html.slice(html.indexOf(\"<!DOCTYPE html>\"), html.indexOf(\"</html>\") + \"</html>\".length) : html;\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"done\",\n html: parsedHtml\n }\n });\n } catch (error) {\n (0,_analytics__WEBPACK_IMPORTED_MODULE_9__.trackEvent)(\"ai\", \"generate (failed)\", \"d2c\");\n this.updateMagicGeneration({\n frameElement,\n data: {\n status: \"error\",\n code: \"ERR_OAI\",\n message: error.message || \"Unknown error during generation\"\n }\n });\n }\n }\n\n onIframeSrcCopy(element) {\n var _a, _b;\n\n if (((_b = (_a = element.customData) === null || _a === void 0 ? void 0 : _a.generationData) === null || _b === void 0 ? void 0 : _b.status) === \"done\") {\n (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.copyTextToSystemClipboard)(element.customData.generationData.html);\n this.setToast({\n message: \"copied to clipboard\",\n closable: false,\n duration: 1500\n });\n }\n }\n\n clearImageShapeCache(filesMap) {\n const files = filesMap !== null && filesMap !== void 0 ? filesMap : this.files;\n this.scene.getNonDeletedElements().forEach(element => {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(element) && files[element.fileId]) {\n this.imageCache.delete(element.fileId);\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache[\"delete\"](element);\n }\n });\n }\n\n async componentDidMount() {\n var _a;\n\n this.unmounted = false;\n this.excalidrawContainerValue.container = this.excalidrawContainerRef.current;\n\n if (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_12__.ENV.TEST || \"development\" !== \"production\") {\n const setState = this.setState.bind(this);\n Object.defineProperties(window.h, {\n state: {\n configurable: true,\n get: () => {\n return this.state;\n }\n },\n setState: {\n configurable: true,\n value: (...args) => {\n return this.setState(...args);\n }\n },\n app: {\n configurable: true,\n value: this\n },\n history: {\n configurable: true,\n value: this.history\n },\n store: {\n configurable: true,\n value: this.store\n },\n fonts: {\n configurable: true,\n value: this.fonts\n }\n });\n }\n\n this.store.onStoreIncrementEmitter.on(increment => {\n this.history.record(increment.elementsChange, increment.appStateChange);\n });\n this.scene.onUpdate(this.triggerRender);\n this.addEventListeners();\n\n if (this.props.autoFocus && this.excalidrawContainerRef.current) {\n this.focusContainer();\n }\n\n if ( // bounding rects don't work in tests so updating\n // the state on init would result in making the test enviro run\n // in mobile breakpoint (0 width/height), making everything fail\n !(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isTestEnv)()) {\n this.refreshViewportBreakpoints();\n this.refreshEditorBreakpoints();\n }\n\n if (_constants__WEBPACK_IMPORTED_MODULE_12__.supportsResizeObserver && this.excalidrawContainerRef.current) {\n this.resizeObserver = new ResizeObserver(() => {\n this.refreshEditorBreakpoints();\n this.updateDOMRect();\n });\n (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.observe(this.excalidrawContainerRef.current);\n }\n\n const searchParams = new URLSearchParams(window.location.search.slice(1));\n\n if (searchParams.has(\"web-share-target\")) {\n // Obtain a file that was shared via the Web Share Target API.\n this.restoreFileFromShare();\n } else {\n this.updateDOMRect(this.initializeScene);\n } // note that this check seems to always pass in localhost\n\n\n if ((0,_constants__WEBPACK_IMPORTED_MODULE_12__.isBrave)() && !(0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.isMeasureTextSupported)()) {\n this.setState({\n errorMessage: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(_BraveMeasureTextError__WEBPACK_IMPORTED_MODULE_60__[\"default\"], {})\n });\n }\n }\n\n componentWillUnmount() {\n var _a, _b;\n\n (_a = window.launchQueue) === null || _a === void 0 ? void 0 : _a.setConsumer(() => {});\n this.renderer.destroy();\n this.scene.destroy();\n this.scene = new _scene_Scene__WEBPACK_IMPORTED_MODULE_29__[\"default\"]();\n this.fonts = new _fonts__WEBPACK_IMPORTED_MODULE_49__.Fonts(this.scene);\n this.renderer = new _scene_Renderer__WEBPACK_IMPORTED_MODULE_65__.Renderer(this.scene);\n this.files = {};\n this.imageCache.clear();\n (_b = this.resizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();\n this.unmounted = true;\n this.removeEventListeners();\n this.library.destroy();\n this.laserTrails.stop();\n this.eraserTrail.stop();\n this.onChangeEmitter.clear();\n this.store.onStoreIncrementEmitter.clear();\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_66__.ShapeCache.destroy();\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.destroy();\n clearTimeout(touchTimeout);\n _scene__WEBPACK_IMPORTED_MODULE_28__.isSomeElementSelected.clearCache();\n _groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements.clearCache();\n touchTimeout = 0;\n document.documentElement.style.overscrollBehaviorX = \"\";\n document.body.removeChild((0,_Tooltip__WEBPACK_IMPORTED_MODULE_93__.getTooltipDiv)()); //clearRenderCache(); //zsviczian\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.clearEraserCanvasCache)(); //zsviczian\n\n this.interactiveCanvas = null; //zsviczian\n\n this.iFrameRefs.clear(); //zsviczian\n //@ts-ignore\n\n this.iFrameRefs = null; //zsviczian\n\n this.embedsValidationStatus.clear(); //zsviczian\n //@ts-ignore\n\n this.embedsValidationStatus = null; //zsviczian\n\n this.initializedEmbeds.clear(); //zsviczian\n //@ts-ignore\n\n this.initializedEmbeds = null; //zsviczian\n\n this.elementsPendingErasure.clear(); //zsviczian\n //@ts-ignore\n\n this.elementsPendingErasure = null; //zsviczian\n\n this.lastPointerDownEvent = null; //zsviczian\n\n this.lastPointerUpEvent = null; //zsviczian\n\n this.lastPointerMoveEvent = null; //zsviczian\n //@ts-ignore\n\n this.actionManager.app = null; //zsviczian\n\n this.actionManager.actions = {}; //zsviczian\n\n this.history.clear(); //zsviczian\n\n this.store.clear(); //zsviczian\n //@ts-ignore\n\n this.store = null; //zsviczian\n //@ts-ignore\n\n this.library = null; //zsviczian\n //@ts-ignore\n\n this.canvas = null; //zsviczian\n //@ts-ignore\n\n this.rc = null; //zsviczian\n //@ts-ignore\n\n this.excalidrawContainerRef.current = undefined; //zsviczian\n\n this.nearestScrollableContainer = undefined; //zsviczian\n\n this.excalidrawContainerValue = {\n container: null,\n id: \"unknown\"\n }; //zsviczian\n //@ts-ignore\n // this.laserTrails.terminate(); //zsviczian\n // this.eraserTrail.terminate(); //zsviczian\n\n /*\n Object.keys(this).forEach((key) => {\n //@ts-ignore\n delete this[key];\n });*/\n }\n\n removeEventListeners() {\n this.onRemoveEventListenersEmitter.trigger();\n }\n\n addEventListeners() {\n // remove first as we can add event listeners multiple times\n this.removeEventListeners(); // -------------------------------------------------------------------------\n // view+edit mode listeners\n // -------------------------------------------------------------------------\n\n if (this.props.handleKeyboardGlobally) {\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, this.onKeyDown, false));\n }\n\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel, {\n passive: false\n }), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.MESSAGE, this.onWindowMessage, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, this.removePointer), // #3553\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.COPY, this.onCopy), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, this.onKeyUp, {\n passive: true\n }), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, \"focus\", () => this.triggerRender(true), {\n passive: true\n }), //zsviczian\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, this.updateCurrentCursorPosition), // rerender text elements on font load to fix #637 && #1553\n // zsviczian In Obsidian this is not needed as I manage font load separately\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document.fonts, \"loadingdone\", event => {\n const fontFaces = event.fontfaces;\n this.fonts.onLoaded(fontFaces);\n }), // Safari-only desktop pinch zoom\n (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_START, this.onGestureStart, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_CHANGE, this.onGestureChange, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.GESTURE_END, this.onGestureEnd, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.FOCUS, () => {\n this.maybeCleanupAfterMissingPointerUp(null); // browsers (chrome?) tend to free up memory a lot, which results\n // in canvas context being cleared. Thus re-render on focus.\n\n this.triggerRender(true);\n }));\n\n if (this.state.viewModeEnabled) {\n return;\n } // -------------------------------------------------------------------------\n // edit-mode listeners only\n // -------------------------------------------------------------------------\n\n\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.FULLSCREENCHANGE, this.onFullscreenChange), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.PASTE, this.pasteFromClipboard), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(document, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.CUT, this.onCut), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.RESIZE, this.onResize, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.UNLOAD, this.onUnload, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(window, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.BLUR, this.onBlur, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.WHEEL, this.handleWheel), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DRAG_OVER, this.disableEvent, false), (0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)(this.excalidrawContainerRef.current, _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.DROP, this.disableEvent, false));\n\n if (this.props.detectScroll) {\n this.onRemoveEventListenersEmitter.once((0,_utils__WEBPACK_IMPORTED_MODULE_34__.addEventListener)((0,_utils__WEBPACK_IMPORTED_MODULE_34__.getNearestScrollableContainer)(this.excalidrawContainerRef.current), _constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.SCROLL, this.onScroll));\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n var _a, _b, _c, _d, _e, _f;\n\n this.updateEmbeddables();\n const elements = this.scene.getElementsIncludingDeleted();\n const elementsMap = this.scene.getElementsMapIncludingDeleted();\n const nonDeletedElementsMap = this.scene.getNonDeletedElementsMap();\n\n if (!this.state.showWelcomeScreen && !elements.length) {\n this.setState({\n showWelcomeScreen: true\n });\n }\n\n if (prevProps.UIOptions.dockedSidebarBreakpoint !== this.props.UIOptions.dockedSidebarBreakpoint) {\n this.refreshEditorBreakpoints();\n }\n\n const hasFollowedPersonLeft = prevState.userToFollow && !this.state.collaborators.has(prevState.userToFollow.socketId);\n\n if (hasFollowedPersonLeft) {\n this.maybeUnfollowRemoteUser();\n }\n\n if (prevState.zoom.value !== this.state.zoom.value || prevState.scrollX !== this.state.scrollX || prevState.scrollY !== this.state.scrollY) {\n (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onScrollChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.state.scrollX, this.state.scrollY, this.state.zoom);\n this.onScrollChangeEmitter.trigger(this.state.scrollX, this.state.scrollY, this.state.zoom);\n }\n\n if (prevState.userToFollow !== this.state.userToFollow) {\n if (prevState.userToFollow) {\n this.onUserFollowEmitter.trigger({\n userToFollow: prevState.userToFollow,\n action: \"UNFOLLOW\"\n });\n }\n\n if (this.state.userToFollow) {\n this.onUserFollowEmitter.trigger({\n userToFollow: this.state.userToFollow,\n action: \"FOLLOW\"\n });\n }\n } // zsviczian\n\n\n if (this.state.highlightSearchResult && !this.debounceClearHighlightSearchResults && prevState.selectedElementIds !== this.state.selectedElementIds) {\n this.setState({\n highlightSearchResult: false\n });\n }\n\n if (Object.keys(this.state.selectedElementIds).length && (0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.setState({\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n }\n\n if (this.state.activeTool.type === \"eraser\" && prevState.theme !== this.state.theme) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setEraserCursor)(this.interactiveCanvas, this.state.theme);\n } // Hide hyperlink popup if shown when element type is not selection\n\n\n if (prevState.activeTool.type === \"selection\" && this.state.activeTool.type !== \"selection\" && this.state.showHyperlinkPopup) {\n this.setState({\n showHyperlinkPopup: false\n });\n }\n\n if (prevProps.langCode !== this.props.langCode) {\n this.updateLanguage();\n }\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(prevState) && !(0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.eraserTrail.endPath();\n }\n\n if (prevProps.viewModeEnabled !== this.props.viewModeEnabled) {\n this.setState({\n viewModeEnabled: !!this.props.viewModeEnabled\n });\n }\n\n if (prevState.viewModeEnabled !== this.state.viewModeEnabled) {\n this.addEventListeners();\n this.deselectElements();\n }\n\n if (prevProps.zenModeEnabled !== this.props.zenModeEnabled) {\n this.setState({\n zenModeEnabled: !!this.props.zenModeEnabled\n });\n }\n\n if (prevProps.theme !== this.props.theme && this.props.theme) {\n this.setState({\n theme: this.props.theme\n });\n }\n\n (_c = this.excalidrawContainerRef.current) === null || _c === void 0 ? void 0 : _c.classList.toggle(\"theme--dark\", this.state.theme === _constants__WEBPACK_IMPORTED_MODULE_12__.THEME.DARK);\n\n if (this.state.editingLinearElement && !this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {\n // defer so that the storeAction flag isn't reset via current update\n setTimeout(() => {\n // execute only if the condition still holds when the deferred callback\n // executes (it can be scheduled multiple times depending on how\n // many times the component renders)\n this.state.editingLinearElement && this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } // failsafe in case the state is being updated in incorrect order resulting\n // in the editingTextElement being now a deleted element\n\n\n if ((_d = this.state.editingTextElement) === null || _d === void 0 ? void 0 : _d.isDeleted) {\n this.setState({\n editingTextElement: null\n });\n }\n\n if (this.state.selectedLinearElement && !this.state.selectedElementIds[this.state.selectedLinearElement.elementId]) {\n // To make sure `selectedLinearElement` is in sync with `selectedElementIds`, however this shouldn't be needed once\n // we have a single API to update `selectedElementIds`\n this.setState({\n selectedLinearElement: null\n });\n }\n\n const {\n multiElement\n } = prevState;\n\n if (prevState.activeTool !== this.state.activeTool && multiElement != null && (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(multiElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(multiElement, this.state, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)(_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements());\n }\n\n this.store.commit(elementsMap, this.state); // Do not notify consumers if we're still loading the scene. Among other\n // potential issues, this fixes a case where the tab isn't focused during\n // init, which would trigger onChange with empty elements, which would then\n // override whatever is in localStorage currently.\n\n if (!this.state.isLoading) {\n (_f = (_e = this.props).onChange) === null || _f === void 0 ? void 0 : _f.call(_e, elements, this.state, this.files);\n this.onChangeEmitter.trigger(elements, this.state, this.files);\n }\n }\n\n static resetTapTwice() {\n didTapTwice = false;\n } // TODO rewrite this to paste both text & images at the same time if\n // pasted data contains both\n\n\n async addElementsFromMixedContentPaste(mixedContent, {\n isPlainPaste,\n sceneX,\n sceneY\n }) {\n if (!isPlainPaste && mixedContent.some(node => node.type === \"imageUrl\") && this.isToolSupported(\"image\")) {\n const imageURLs = mixedContent.filter(node => node.type === \"imageUrl\").map(node => node.value);\n const responses = await Promise.all(imageURLs.map(async url => {\n try {\n return {\n file: await (0,_data_blob__WEBPACK_IMPORTED_MODULE_40__.ImageURLToFile)(url)\n };\n } catch (error) {\n let errorMessage = error.message;\n\n if (error.cause === \"FETCH_ERROR\") {\n errorMessage = (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.failedToFetchImage\");\n } else if (error.cause === \"UNSUPPORTED\") {\n errorMessage = (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"errors.unsupportedFileType\");\n }\n\n return {\n errorMessage\n };\n }\n }));\n let y = sceneY;\n let firstImageYOffsetDone = false;\n const nextSelectedIds = {};\n\n for (const response of responses) {\n if (response.file) {\n const imageElement = this.createImageElement({\n sceneX,\n sceneY: y\n });\n const initializedImageElement = await this.insertImageElement(imageElement, response.file);\n\n if (initializedImageElement) {\n // vertically center first image in the batch\n if (!firstImageYOffsetDone) {\n firstImageYOffsetDone = true;\n y -= initializedImageElement.height / 2;\n } // hack to reset the `y` coord because we vertically center during\n // insertImageElement\n\n\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(initializedImageElement, {\n y\n }, false);\n y = imageElement.y + imageElement.height + 25;\n nextSelectedIds[imageElement.id] = true;\n }\n }\n }\n\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedIds, this.state)\n });\n const error = responses.find(response => !!response.errorMessage);\n\n if (error && error.errorMessage) {\n this.setState({\n errorMessage: error.errorMessage\n });\n }\n } else {\n const textNodes = mixedContent.filter(node => node.type === \"text\");\n\n if (textNodes.length) {\n this.addTextFromPaste(textNodes.map(node => node.value).join(\"\\n\\n\"), isPlainPaste);\n }\n }\n }\n\n addTextFromPaste(text, isPlainPaste = false) {\n const {\n x,\n y\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: this.lastViewportPosition.x,\n clientY: this.lastViewportPosition.y\n }, this.state);\n const textElementProps = {\n x,\n y,\n strokeColor: this.state.currentItemStrokeColor,\n backgroundColor: this.state.currentItemBackgroundColor,\n fillStyle: this.state.currentItemFillStyle,\n strokeWidth: this.state.currentItemStrokeWidth,\n strokeStyle: this.state.currentItemStrokeStyle,\n roundness: null,\n roughness: this.state.currentItemRoughness,\n opacity: this.state.currentItemOpacity,\n text,\n rawText: text,\n fontSize: (0,_actions_actionProperties__WEBPACK_IMPORTED_MODULE_75__.getFontSize)(this.state.currentItemFontSize, this.state.zoom.value),\n fontFamily: this.state.currentItemFontFamily,\n textAlign: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_TEXT_ALIGN,\n verticalAlign: _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_VERTICAL_ALIGN,\n locked: false\n };\n const fontString = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.getFontString)({\n fontSize: textElementProps.fontSize,\n fontFamily: textElementProps.fontFamily\n });\n const lineHeight = (0,_fonts__WEBPACK_IMPORTED_MODULE_49__.getLineHeight)(textElementProps.fontFamily);\n const [x1,, x2] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_91__.getVisibleSceneBounds)(this.state); // long texts should not go beyond 800 pixels in width nor should it go below 200 px\n\n const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200);\n const LINE_GAP = 10;\n let currentY = y;\n const lines = isPlainPaste ? [text] : text.split(\"\\n\");\n const textElements = lines.reduce((acc, line, idx) => {\n var _a;\n\n const originalText = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.normalizeText)(line).trim();\n\n if (originalText.length) {\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords({\n x,\n y: currentY\n });\n let metrics = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.measureText)(originalText, fontString, lineHeight);\n const isTextUnwrapped = metrics.width > maxTextWidth;\n const text = isTextUnwrapped ? (0,_element_textWrapping__WEBPACK_IMPORTED_MODULE_100__.wrapText)(originalText, fontString, maxTextWidth) : originalText;\n metrics = isTextUnwrapped ? (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.measureText)(text, fontString, lineHeight) : metrics;\n const startX = x - metrics.width / 2;\n const startY = currentY - metrics.height / 2;\n const element = (0,_element__WEBPACK_IMPORTED_MODULE_16__.newTextElement)(Object.assign(Object.assign({}, textElementProps), {\n x: startX,\n y: startY,\n text,\n rawText: originalText,\n //zsviczian\n originalText,\n lineHeight,\n autoResize: !isTextUnwrapped,\n frameId: topLayerFrame ? topLayerFrame.id : null\n }));\n acc.push(element);\n currentY += element.height + LINE_GAP;\n } else {\n const prevLine = (_a = lines[idx - 1]) === null || _a === void 0 ? void 0 : _a.trim(); // add paragraph only if previous line was not empty, IOW don't add\n // more than one empty line\n\n if (prevLine) {\n currentY += (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getLineHeightInPx)(textElementProps.fontSize, lineHeight) + LINE_GAP;\n }\n }\n\n return acc;\n }, []);\n\n if (textElements.length === 0) {\n return;\n }\n\n this.scene.insertElements(textElements);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.fromEntries(textElements.map(el => [el.id, true])), this.state)\n });\n\n if (!isPlainPaste && textElements.length > 1 && PLAIN_PASTE_TOAST_SHOWN === false && !this.device.editor.isMobile) {\n this.setToast({\n message: (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.t)(\"toast.pasteAsSingleElement\", {\n shortcut: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.getShortcutKey)(\"CtrlOrCmd+Shift+V\")\n }),\n duration: 5000\n });\n PLAIN_PASTE_TOAST_SHOWN = true;\n }\n\n this.store.shouldCaptureIncrement();\n }\n\n handleTextWysiwyg(element, {\n isExistingElement = false\n }) {\n const elementsMap = this.scene.getElementsMapIncludingDeleted();\n\n const updateElement = (nextOriginalText, isDeleted, rawText, //zsviczian\n link) => {\n this.scene.replaceAllElements([// Not sure why we include deleted elements as well hence using deleted elements map\n ...this.scene.getElementsIncludingDeleted().map(_element => {\n if (_element.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(_element)) {\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(_element, Object.assign({\n originalText: nextOriginalText,\n rawText: rawText !== null && rawText !== void 0 ? rawText : nextOriginalText,\n //zsviczian\n link,\n isDeleted: isDeleted !== null && isDeleted !== void 0 ? isDeleted : _element.isDeleted\n }, (0,_element__WEBPACK_IMPORTED_MODULE_16__.refreshTextDimensions)(_element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(_element, elementsMap), elementsMap, nextOriginalText)));\n }\n\n return _element;\n })]);\n }; //zsviczian\n\n\n if (isExistingElement && this.props.onBeforeTextEdit) {\n const text = this.props.onBeforeTextEdit(element);\n\n if (text && text !== element.originalText) {\n this.scene.replaceAllElements([...this.scene.getElementsIncludingDeleted().map(_element => {\n if (_element.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(_element)) {\n //changing the value of element so this gets edited by textWysiwyg\n element = (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.newElementWith)(_element, Object.assign({\n originalText: text,\n rawText: text,\n isDeleted: false\n }, (0,_element__WEBPACK_IMPORTED_MODULE_16__.refreshTextDimensions)(_element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(_element, elementsMap), elementsMap, text)));\n return element;\n }\n\n return _element;\n })]);\n }\n }\n\n (0,_element_textWysiwyg__WEBPACK_IMPORTED_MODULE_84__.textWysiwyg)({\n id: element.id,\n canvas: this.canvas,\n getViewportCoords: (x, y) => {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: x,\n sceneY: y\n }, this.state);\n return [viewportX - this.state.offsetLeft, viewportY - this.state.offsetTop];\n },\n onChange: (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(nextOriginalText => {\n updateElement(nextOriginalText, false);\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isNonDeletedElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.updateBoundElements)(element, this.scene.getNonDeletedElementsMap());\n }\n }),\n onSubmit: (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(({\n viaKeyboard,\n nextOriginalText\n }) => {\n var _a;\n\n const isDeleted = !nextOriginalText.trim(); //zsviczian insert start\n\n const rawText = nextOriginalText; //should this be originalText??\n\n let link = undefined;\n\n if (this.props.onBeforeTextSubmit) {\n const _element = this.scene.getElementsIncludingDeleted().find(el => el.id === element.id && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(el));\n\n if (_element) {\n const dismensionsData = (0,_element__WEBPACK_IMPORTED_MODULE_16__.refreshTextDimensions)(_element, (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerElement)(_element, elementsMap), elementsMap, nextOriginalText);\n const {\n updatedNextOriginalText,\n nextLink\n } = this.props.onBeforeTextSubmit(element, (_a = dismensionsData === null || dismensionsData === void 0 ? void 0 : dismensionsData.text) !== null && _a !== void 0 ? _a : nextOriginalText, //should never be undefined\n nextOriginalText, isDeleted);\n nextOriginalText = updatedNextOriginalText !== null && updatedNextOriginalText !== void 0 ? updatedNextOriginalText : nextOriginalText;\n link = nextLink;\n }\n } //zsviczian insert end\n\n\n updateElement(nextOriginalText, isDeleted, rawText, link); //zsviczian (added rawText, link, text)\n // select the created text element only if submitting via keyboard\n // (when submitting via click it should act as signal to deselect)\n\n if (!isDeleted && viaKeyboard) {\n const elementIdToSelect = element.containerId ? element.containerId : element.id; // needed to ensure state is updated before \"finalize\" action\n // that's invoked on keyboard-submit as well\n // TODO either move this into finalize as well, or handle all state\n // updates in one place, skipping finalize action\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [elementIdToSelect]: true\n }), prevState)\n }));\n });\n }\n\n if (isDeleted) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDeletion)(this.scene.getNonDeletedElements(), [element]);\n }\n\n if (!isDeleted || isExistingElement) {\n this.store.shouldCaptureIncrement();\n }\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n this.setState({\n newElement: null,\n editingTextElement: null\n });\n });\n\n if (this.state.activeTool.locked) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n }\n\n this.focusContainer();\n }),\n element,\n excalidrawContainer: this.excalidrawContainerRef.current,\n app: this,\n // when text is selected, it's hard (at least on iOS) to re-position the\n // caret (i.e. deselect). There's not much use for always selecting\n // the text on edit anyway (and users can select-all from contextmenu\n // if needed)\n autoSelect: !this.device.isTouchScreen\n }); // deselect all other elements when inserting text\n\n this.deselectElements(); // do an initial update to re-initialize element position since we were\n // modifying element's x/y for sake of editor (case: syncing to remote)\n\n updateElement(element.originalText, false);\n }\n\n deselectElements() {\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n }\n\n getTextElementAtPosition(x, y) {\n const element = this.getElementAtPosition(x, y, {\n includeBoundTextElement: true\n });\n\n if (element && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && !element.isDeleted) {\n return element;\n }\n\n return null;\n }\n\n getElementAtPosition(x, y, opts) {\n const allHitElements = this.getElementsAtPosition(x, y, opts === null || opts === void 0 ? void 0 : opts.includeBoundTextElement, opts === null || opts === void 0 ? void 0 : opts.includeLockedElements);\n\n if (allHitElements.length > 1) {\n if (opts === null || opts === void 0 ? void 0 : opts.preferSelected) {\n for (let index = allHitElements.length - 1; index > -1; index--) {\n if (this.state.selectedElementIds[allHitElements[index].id]) {\n return allHitElements[index];\n }\n }\n }\n\n const elementWithHighestZIndex = allHitElements[allHitElements.length - 1]; // If we're hitting element with highest z-index only on its bounding box\n // while also hitting other element figure, the latter should be considered.\n\n return (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x,\n y,\n element: elementWithHighestZIndex,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(elementWithHighestZIndex, this.scene.getNonDeletedElementsMap()),\n // when overlapping, we would like to be more precise\n // this also avoids the need to update past tests\n threshold: this.getElementHitThreshold() / 2,\n frameNameBound: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(elementWithHighestZIndex) ? this.frameNameBoundsCache.get(elementWithHighestZIndex) : null\n }) ? elementWithHighestZIndex : allHitElements[allHitElements.length - 2];\n }\n\n if (allHitElements.length === 1) {\n return allHitElements[0];\n }\n\n return null;\n }\n\n getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {\n const iframeLikes = [];\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const elements = (includeBoundTextElement && includeLockedElements ? this.scene.getNonDeletedElements() : this.scene.getNonDeletedElements().filter(element => (includeLockedElements || !element.locked) && (includeBoundTextElement || !((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(element) && element.containerId)))).filter(el => this.hitElement(x, y, el)).filter(element => {\n // hitting a frame's element from outside the frame is not considered a hit\n const containingFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(element, elementsMap);\n return containingFrame && this.state.frameRendering.enabled && this.state.frameRendering.clip ? (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isCursorInFrame)({\n x,\n y\n }, containingFrame, elementsMap) : true;\n }).filter(el => {\n // The parameter elements comes ordered from lower z-index to higher.\n // We want to preserve that order on the returned array.\n // Exception being embeddables which should be on top of everything else in\n // terms of hit testing.\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeElement)(el)) {\n iframeLikes.push(el);\n return false;\n }\n\n return true;\n }).concat(iframeLikes);\n return elements;\n }\n\n getElementHitThreshold() {\n return _constants__WEBPACK_IMPORTED_MODULE_12__.DEFAULT_COLLISION_THRESHOLD / this.state.zoom.value;\n }\n\n hitElement(x, y, element, considerBoundingBox = true) {\n // if the element is selected, then hit test is done against its bounding box\n if (considerBoundingBox && this.state.selectedElementIds[element.id] && (0,_element_transformHandles__WEBPACK_IMPORTED_MODULE_47__.shouldShowBoundingBox)([element], this.state)) {\n const selectionShape = (0,_utils_geometry_shape__WEBPACK_IMPORTED_MODULE_32__.getSelectionBoxShape)(element, this.scene.getNonDeletedElementsMap(), (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(element) ? 0 : this.getElementHitThreshold());\n return (0,_utils_collision__WEBPACK_IMPORTED_MODULE_33__.isPointInShape)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x, y), selectionShape);\n } // take bound text element into consideration for hit collision as well\n\n\n const hitBoundTextOfElement = (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementBoundText)(x, y, (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getBoundTextShape)(element, this.scene.getNonDeletedElementsMap()));\n\n if (hitBoundTextOfElement) {\n return true;\n }\n\n return (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x,\n y,\n element,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(element, this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold(),\n frameNameBound: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element) ? this.frameNameBoundsCache.get(element) : null\n });\n }\n\n getTextBindableContainerAtPosition(x, y) {\n const elements = this.scene.getNonDeletedElements();\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.length === 1) {\n return (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isTextBindableContainer)(selectedElements[0], false) ? selectedElements[0] : null;\n }\n\n let hitElement = null; // We need to do hit testing from front (end of the array) to back (beginning of the array)\n\n for (let index = elements.length - 1; index >= 0; --index) {\n if (elements[index].isDeleted) {\n continue;\n }\n\n const [x1, y1, x2, y2] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementAbsoluteCoords)(elements[index], this.scene.getNonDeletedElementsMap());\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isArrowElement)(elements[index]) && (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x,\n y,\n element: elements[index],\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(elements[index], this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold()\n })) {\n hitElement = elements[index];\n break;\n } else if (x1 < x && x < x2 && y1 < y && y < y2) {\n hitElement = elements[index];\n break;\n }\n }\n\n return (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isTextBindableContainer)(hitElement, false) ? hitElement : null;\n }\n\n handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {\n const elementsMap = this.scene.getNonDeletedElementsMap();\n const element = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getElement(linearElementEditor.elementId, elementsMap);\n\n if (!element) {\n return;\n }\n\n if (this.state.selectedLinearElement) {\n let hoverPointIndex = -1;\n let segmentMidPointHoveredCoords = null;\n\n if ((0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementItself)({\n x: scenePointerX,\n y: scenePointerY,\n element,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(element, this.scene.getNonDeletedElementsMap())\n })) {\n hoverPointIndex = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);\n segmentMidPointHoveredCoords = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, {\n x: scenePointerX,\n y: scenePointerY\n }, this.state, this.scene.getNonDeletedElementsMap());\n\n if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.POINTER);\n } else if (this.hitElement(scenePointerX, scenePointerY, element)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n } else if (this.hitElement(scenePointerX, scenePointerY, element)) {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(element) || !(element.startBinding || element.endBinding)) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.MOVE);\n }\n }\n\n if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n hoverPointIndex\n })\n });\n }\n\n if (!_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.arePointsEqual(this.state.selectedLinearElement.segmentMidPointHoveredCoords, segmentMidPointHoveredCoords)) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n segmentMidPointHoveredCoords\n })\n });\n }\n } else {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n }\n }\n\n updateGestureOnPointerDown(event) {\n gesture.pointers.set(event.pointerId, {\n x: event.clientX,\n y: event.clientY\n });\n\n if (gesture.pointers.size === 2) {\n gesture.lastCenter = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getCenter)(gesture.pointers);\n gesture.initialScale = this.state.zoom.value;\n gesture.initialDistance = (0,_gesture__WEBPACK_IMPORTED_MODULE_22__.getDistance)(Array.from(gesture.pointers.values()));\n }\n }\n\n initialPointerDownState(event) {\n const origin = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const selectedElements = this.scene.getSelectedElements(this.state);\n const [minX, minY, maxX, maxY] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n const isElbowArrowOnly = selectedElements.findIndex(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow) === 0;\n return {\n origin,\n withCmdOrCtrl: event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD],\n originInGrid: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(origin.x, origin.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] || isElbowArrowOnly ? null : this.getEffectiveGridSize())),\n scrollbars: (0,_scene_scrollbars__WEBPACK_IMPORTED_MODULE_85__.isOverScrollBars)(currentScrollBars, event.clientX - this.state.offsetLeft, event.clientY - this.state.offsetTop),\n // we need to duplicate because we'll be updating this state\n lastCoords: Object.assign({}, origin),\n originalElements: this.scene.getNonDeletedElements().reduce((acc, element) => {\n acc.set(element.id, (0,_element_newElement__WEBPACK_IMPORTED_MODULE_20__.deepCopyElement)(element));\n return acc;\n }, new Map()),\n resize: {\n handleType: false,\n isResizing: false,\n offset: {\n x: 0,\n y: 0\n },\n arrowDirection: \"origin\",\n center: {\n x: (maxX + minX) / 2,\n y: (maxY + minY) / 2\n }\n },\n hit: {\n element: null,\n allHitElements: [],\n wasAddedToSelection: false,\n hasBeenDuplicated: false,\n hasHitCommonBoundingBoxOfSelectedElements: this.isHittingCommonBoundingBoxOfSelectedElements(origin, selectedElements)\n },\n drag: {\n hasOccurred: false,\n offset: null\n },\n eventListeners: {\n onMove: null,\n onUp: null,\n onKeyUp: null,\n onKeyDown: null\n },\n boxSelection: {\n hasOccurred: false\n }\n };\n } // Returns whether the event is a dragging a scrollbar\n\n\n handleDraggingScrollBar(event, pointerDownState) {\n if (!(pointerDownState.scrollbars.isOverEither && !this.state.multiElement)) {\n return false;\n }\n\n isDraggingScrollBar = true;\n pointerDownState.lastCoords.x = event.clientX;\n pointerDownState.lastCoords.y = event.clientY;\n const onPointerMove = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdatesThrottled)(event => {\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n this.handlePointerMoveOverScrollbars(event, pointerDownState);\n });\n const onPointerUp = (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(() => {\n lastPointerUp = null;\n isDraggingScrollBar = false;\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursorForShape)(this.interactiveCanvas, this.state);\n this.setState({\n cursorButton: \"up\"\n });\n this.savePointer(event.clientX, event.clientY, \"up\");\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n onPointerMove.flush();\n });\n lastPointerUp = onPointerUp;\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, onPointerMove);\n window.addEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, onPointerUp);\n return true;\n }\n\n isASelectedElement(hitElement) {\n return hitElement != null && this.state.selectedElementIds[hitElement.id];\n }\n\n isHittingCommonBoundingBoxOfSelectedElements(point, selectedElements) {\n if (selectedElements.length < 2) {\n return false;\n } // How many pixels off the shape boundary we still consider a hit\n\n\n const threshold = this.getElementHitThreshold();\n const [x1, y1, x2, y2] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getCommonBounds)(selectedElements);\n return point.x > x1 - threshold && point.x < x2 + threshold && point.y > y1 - threshold && point.y < y2 + threshold;\n }\n\n getCurrentItemRoundness(elementType) {\n return this.state.currentItemRoundness === \"round\" ? {\n type: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isUsingAdaptiveRadius)(elementType) ? _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.ADAPTIVE_RADIUS : _constants__WEBPACK_IMPORTED_MODULE_12__.ROUNDNESS.PROPORTIONAL_RADIUS\n } : null;\n }\n\n maybeCacheReferenceSnapPoints(event, selectedElements, recomputeAnyways = false) {\n if ((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isSnappingEnabled)({\n event,\n app: this,\n selectedElements\n }) && (recomputeAnyways || !_snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.getReferenceSnapPoints())) {\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setReferenceSnapPoints((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getReferenceSnapPoints)(this.scene.getNonDeletedElements(), selectedElements, this.state, this.scene.getNonDeletedElementsMap()));\n }\n }\n\n maybeCacheVisibleGaps(event, selectedElements, recomputeAnyways = false) {\n if ((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.isSnappingEnabled)({\n event,\n app: this,\n selectedElements\n }) && (recomputeAnyways || !_snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.getVisibleGaps())) {\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setVisibleGaps((0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getVisibleGaps)(this.scene.getNonDeletedElements(), selectedElements, this.state, this.scene.getNonDeletedElementsMap()));\n }\n }\n\n onKeyDownFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onKeyUpFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(event => {\n // Prevents focus from escaping excalidraw tab\n event.key === _keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.ALT && event.preventDefault();\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return;\n }\n\n this.maybeDragNewGenericElement(pointerDownState, event);\n });\n }\n\n onPointerMoveFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdatesThrottled)(event => {\n var _a, _b, _c, _d; //To avoid pointerMove canceling the selection of locked elements on mobile //zsviczian\n\n\n if (Boolean(this.state.contextMenu)) {\n return;\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(event, this.state);\n const lastPointerCoords = (_a = this.lastPointerMoveCoords) !== null && _a !== void 0 ? _a : pointerDownState.origin;\n this.lastPointerMoveCoords = pointerCoords; // We need to initialize dragOffsetXY only after we've updated\n // `state.selectedElementIds` on pointerDown. Doing it here in pointerMove\n // event handler should hopefully ensure we're already working with\n // the updated state.\n\n if (pointerDownState.drag.offset === null) {\n pointerDownState.drag.offset = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.tupleToCoors)((0,_element__WEBPACK_IMPORTED_MODULE_16__.getDragOffsetXY)(this.scene.getSelectedElements(this.state), pointerDownState.origin.x, pointerDownState.origin.y));\n }\n\n const target = event.target;\n\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n if (this.handlePointerMoveOverScrollbars(event, pointerDownState)) {\n return;\n }\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state)) {\n this.handleEraser(event, pointerDownState, pointerCoords);\n return;\n }\n\n if (this.state.activeTool.type === \"laser\") {\n this.laserTrails.addPointToPath(pointerCoords.x, pointerCoords.y);\n }\n\n const [gridX, gridY] = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.getGridPoint)(pointerCoords.x, pointerCoords.y, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize()); // for arrows/lines, don't start dragging until a given threshold\n // to ensure we don't create a 2-point arrow by mistake when\n // user clicks mouse in a way that it moves a tiny bit (thus\n // triggering pointermove)\n\n if (!pointerDownState.drag.hasOccurred && (this.state.activeTool.type === \"arrow\" || this.state.activeTool.type === \"line\")) {\n if ((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerCoords.x, pointerCoords.y), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerDownState.origin.x, pointerDownState.origin.y)) < _constants__WEBPACK_IMPORTED_MODULE_12__.DRAGGING_THRESHOLD) {\n return;\n }\n }\n\n if (pointerDownState.resize.isResizing) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n\n if (this.maybeHandleCrop(pointerDownState, event)) {\n return true;\n }\n\n if (this.maybeHandleResize(pointerDownState, event)) {\n return true;\n }\n }\n\n const elementsMap = this.scene.getNonDeletedElementsMap();\n\n if (this.state.selectedLinearElement) {\n const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;\n\n if (_element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.shouldAddMidpoint(this.state.selectedLinearElement, pointerCoords, this.state, elementsMap)) {\n const ret = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.addMidpoint(this.state.selectedLinearElement, pointerCoords, this, !event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD], elementsMap);\n\n if (!ret) {\n return;\n } // Since we are reading from previous state which is not possible with\n // automatic batching in React 18 hence using flush sync to synchronously\n // update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.\n\n\n (0,react_dom__WEBPACK_IMPORTED_MODULE_2__.flushSync)(() => {\n if (this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n pointerDownState: ret.pointerDownState,\n selectedPointsIndices: ret.selectedPointsIndices\n })\n });\n }\n });\n return;\n } else if (linearElementEditor.pointerDownState.segmentMidpoint.value !== null && !linearElementEditor.pointerDownState.segmentMidpoint.added) {\n return;\n }\n\n const didDrag = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointDragging(event, this, pointerCoords.x, pointerCoords.y, (element, pointsSceneCoords) => {\n this.maybeSuggestBindingsForLinearElementAtCoords(element, pointsSceneCoords);\n }, linearElementEditor, this.scene);\n\n if (didDrag) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n pointerDownState.drag.hasOccurred = true;\n\n if (this.state.editingLinearElement && !this.state.editingLinearElement.isDragging) {\n this.setState({\n editingLinearElement: Object.assign(Object.assign({}, this.state.editingLinearElement), {\n isDragging: true\n })\n });\n }\n\n if (!this.state.selectedLinearElement.isDragging) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, this.state.selectedLinearElement), {\n isDragging: true\n })\n });\n }\n\n return;\n }\n }\n\n const hasHitASelectedElement = pointerDownState.hit.allHitElements.some(element => this.isASelectedElement(element));\n const isSelectingPointsInLineEditor = this.state.editingLinearElement && event.shiftKey && this.state.editingLinearElement.elementId === ((_b = pointerDownState.hit.element) === null || _b === void 0 ? void 0 : _b.id);\n\n if ((hasHitASelectedElement || pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements) && !isSelectingPointsInLineEditor) {\n const selectedElements = this.scene.getSelectedElements(this.state);\n\n if (selectedElements.every(element => element.locked)) {\n return;\n }\n\n const selectedElementsHasAFrame = selectedElements.find(e => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(e));\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(pointerCoords);\n this.setState({\n frameToHighlight: topLayerFrame && !selectedElementsHasAFrame ? topLayerFrame : null\n }); // Marking that click was used for dragging to check\n // if elements should be deselected on pointerup\n\n pointerDownState.drag.hasOccurred = true; // prevent dragging even if we're no longer holding cmd/ctrl otherwise\n // it would have weird results (stuff jumping all over the screen)\n // Checking for editingTextElement to avoid jump while editing on mobile #6503\n\n if (selectedElements.length > 0 && !pointerDownState.withCmdOrCtrl && !this.state.editingTextElement && ((_c = this.state.activeEmbeddable) === null || _c === void 0 ? void 0 : _c.state) !== \"active\") {\n const dragOffset = {\n x: pointerCoords.x - pointerDownState.origin.x,\n y: pointerCoords.y - pointerDownState.origin.y\n };\n const originalElements = [...pointerDownState.originalElements.values()]; // We only drag in one direction if shift is pressed\n\n const lockDirection = event.shiftKey;\n\n if (lockDirection) {\n const distanceX = Math.abs(dragOffset.x);\n const distanceY = Math.abs(dragOffset.y);\n const lockX = lockDirection && distanceX < distanceY;\n const lockY = lockDirection && distanceX > distanceY;\n\n if (lockX) {\n dragOffset.x = 0;\n }\n\n if (lockY) {\n dragOffset.y = 0;\n }\n } // #region move crop region\n\n\n if (this.state.croppingElementId) {\n const croppingElement = this.scene.getNonDeletedElementsMap().get(this.state.croppingElementId);\n\n if (croppingElement && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(croppingElement) && croppingElement.crop !== null && pointerDownState.hit.element === croppingElement) {\n const crop = croppingElement.crop;\n const image = (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isInitializedImageElement)(croppingElement) && ((_d = this.imageCache.get(croppingElement.fileId)) === null || _d === void 0 ? void 0 : _d.image);\n\n if (image && !(image instanceof Promise)) {\n const instantDragOffset = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorScale)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vector)(pointerCoords.x - lastPointerCoords.x, pointerCoords.y - lastPointerCoords.y), Math.max(this.state.zoom.value, 2));\n const [x1, y1, x2, y2, cx, cy] = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getElementAbsoluteCoords)(croppingElement, elementsMap);\n const topLeft = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorFromPoint)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x1, y1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(cx, cy), croppingElement.angle));\n const topRight = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorFromPoint)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x2, y1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(cx, cy), croppingElement.angle));\n const bottomLeft = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorFromPoint)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(x1, y2), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(cx, cy), croppingElement.angle));\n const topEdge = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorNormalize)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorSubtract)(topRight, topLeft));\n const leftEdge = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorNormalize)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorSubtract)(bottomLeft, topLeft)); // project instantDrafOffset onto leftEdge and topEdge to decompose\n\n const offsetVector = (0,_math__WEBPACK_IMPORTED_MODULE_98__.vector)((0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorDot)(instantDragOffset, topEdge), (0,_math__WEBPACK_IMPORTED_MODULE_98__.vectorDot)(instantDragOffset, leftEdge));\n const nextCrop = Object.assign(Object.assign({}, crop), {\n x: (0,_math__WEBPACK_IMPORTED_MODULE_98__.clamp)(crop.x - offsetVector[0] * Math.sign(croppingElement.scale[0]), 0, image.naturalWidth - crop.width),\n y: (0,_math__WEBPACK_IMPORTED_MODULE_98__.clamp)(crop.y - offsetVector[1] * Math.sign(croppingElement.scale[1]), 0, image.naturalHeight - crop.height)\n });\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(croppingElement, {\n crop: nextCrop\n });\n return;\n }\n }\n } // Snap cache *must* be synchronously popuplated before initial drag,\n // otherwise the first drag even will not snap, causing a jump before\n // it snaps to its position if previously snapped already.\n\n\n this.maybeCacheVisibleGaps(event, selectedElements);\n this.maybeCacheReferenceSnapPoints(event, selectedElements);\n const {\n snapOffset,\n snapLines\n } = (0,_snapping__WEBPACK_IMPORTED_MODULE_58__.snapDraggedElements)(originalElements, dragOffset, this, event, this.scene.getNonDeletedElementsMap());\n this.setState({\n snapLines\n }); // when we're editing the name of a frame, we want the user to be\n // able to select and interact with the text input\n\n !this.state.editingFrame && (0,_element__WEBPACK_IMPORTED_MODULE_16__.dragSelectedElements)(pointerDownState, selectedElements, dragOffset, this.scene, snapOffset, event[_keys__WEBPACK_IMPORTED_MODULE_26__.KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize());\n this.setState({\n selectedElementsAreBeingDragged: true,\n // element is being dragged and selectionElement that was created on pointer down\n // should be removed\n selectionElement: null\n });\n\n if (selectedElements.length !== 1 || !(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(selectedElements[0])) {\n this.setState({\n suggestedBindings: (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.getSuggestedBindingsForArrows)(selectedElements, this.scene.getNonDeletedElementsMap())\n });\n } // We duplicate the selected element if alt is pressed on pointer move\n\n\n if (event.altKey && !pointerDownState.hit.hasBeenDuplicated) {\n // Move the currently selected elements to the top of the z index stack, and\n // put the duplicates where the selected elements used to be.\n // (the origin point where the dragging started)\n pointerDownState.hit.hasBeenDuplicated = true;\n const nextElements = [];\n const elementsToAppend = [];\n const groupIdMap = new Map();\n const oldIdToDuplicatedId = new Map();\n const hitElement = pointerDownState.hit.element;\n const selectedElementIds = new Set(this.scene.getSelectedElements({\n selectedElementIds: this.state.selectedElementIds,\n includeBoundTextElement: true,\n includeElementsInFrames: true\n }).map(element => element.id));\n const elements = this.scene.getElementsIncludingDeleted();\n\n for (const element of elements) {\n if (selectedElementIds.has(element.id) || // case: the state.selectedElementIds might not have been\n // updated yet by the time this mousemove event is fired\n element.id === (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && pointerDownState.hit.wasAddedToSelection) {\n const duplicatedElement = (0,_element__WEBPACK_IMPORTED_MODULE_16__.duplicateElement)(this.state.editingGroupId, groupIdMap, element);\n const origElement = pointerDownState.originalElements.get(element.id);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(duplicatedElement, {\n x: origElement.x,\n y: origElement.y\n }); // put duplicated element to pointerDownState.originalElements\n // so that we can snap to the duplicated element without releasing\n\n pointerDownState.originalElements.set(duplicatedElement.id, duplicatedElement);\n nextElements.push(duplicatedElement);\n elementsToAppend.push(element);\n oldIdToDuplicatedId.set(element.id, duplicatedElement.id);\n } else {\n nextElements.push(element);\n }\n }\n\n const nextSceneElements = [...nextElements, ...elementsToAppend];\n (0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_86__.syncMovedIndices)(nextSceneElements, (0,_utils__WEBPACK_IMPORTED_MODULE_34__.arrayToMap)(elementsToAppend));\n (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.bindTextToShapeAfterDuplication)(nextElements, elementsToAppend, oldIdToDuplicatedId);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.fixBindingsAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, \"duplicatesServeAsOld\");\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.bindElementsToFramesAfterDuplication)(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);\n this.scene.replaceAllElements(nextSceneElements);\n this.maybeCacheVisibleGaps(event, selectedElements, true);\n this.maybeCacheReferenceSnapPoints(event, selectedElements, true);\n }\n\n return;\n }\n }\n\n if (this.state.selectionElement) {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n this.maybeDragNewGenericElement(pointerDownState, event);\n } else {\n // It is very important to read this.state within each move event,\n // otherwise we would read a stale one!\n const newElement = this.state.newElement;\n\n if (!newElement) {\n return;\n }\n\n if (newElement.type === \"freedraw\") {\n const points = newElement.points;\n const dx = pointerCoords.x - newElement.x;\n const dy = pointerCoords.y - newElement.y;\n const lastPoint = points.length > 0 && points[points.length - 1];\n const discardPoint = lastPoint && lastPoint[0] === dx && lastPoint[1] === dy;\n\n if (!discardPoint) {\n const strokeOptions = this.state.currentStrokeOptions; //zsviczian\n\n const pressures = newElement.simulatePressure ? newElement.pressures : [//zsviczian\n ...newElement.pressures, (strokeOptions === null || strokeOptions === void 0 ? void 0 : strokeOptions.constantPressure) ? 1 : event.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)],\n pressures\n }, false);\n this.setState({\n newElement\n });\n }\n } else if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newElement)) {\n pointerDownState.drag.hasOccurred = true;\n const points = newElement.points;\n let dx = gridX - newElement.x;\n let dy = gridY - newElement.y;\n\n if ((0,_keys__WEBPACK_IMPORTED_MODULE_26__.shouldRotateWithDiscreteAngle)(event) && points.length === 2) {\n ({\n width: dx,\n height: dy\n } = (0,_element__WEBPACK_IMPORTED_MODULE_16__.getLockedLinearCursorAlignSize)(newElement.x, newElement.y, pointerCoords.x, pointerCoords.y));\n }\n\n if (points.length === 1) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)]\n }, false);\n } else if (points.length > 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isElbowArrow)(newElement)) {\n (0,_element_routing__WEBPACK_IMPORTED_MODULE_95__.mutateElbowArrow)(newElement, elementsMap, [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)], (0,_math__WEBPACK_IMPORTED_MODULE_98__.vector)(0, 0), undefined, {\n isDragging: true,\n informMutation: false\n });\n } else if (points.length === 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points.slice(0, -1), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)]\n }, false);\n }\n\n this.setState({\n newElement\n });\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(newElement, false)) {\n // When creating a linear element by dragging\n this.maybeSuggestBindingsForLinearElementAtCoords(newElement, [pointerCoords], this.state.startBoundElement);\n }\n } else {\n pointerDownState.lastCoords.x = pointerCoords.x;\n pointerDownState.lastCoords.y = pointerCoords.y;\n this.maybeDragNewGenericElement(pointerDownState, event, false);\n }\n }\n\n if (this.state.activeTool.type === \"selection\") {\n pointerDownState.boxSelection.hasOccurred = true;\n const elements = this.scene.getNonDeletedElements(); // box-select line editor points\n\n if (this.state.editingLinearElement) {\n _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handleBoxSelection(event, this.state, this.setState.bind(this), this.scene.getNonDeletedElementsMap()); // regular box-select\n } else {\n let shouldReuseSelection = true;\n\n if (!event.shiftKey && (0,_scene__WEBPACK_IMPORTED_MODULE_28__.isSomeElementSelected)(elements, this.state)) {\n if (pointerDownState.withCmdOrCtrl && pointerDownState.hit.element) {\n this.setState(prevState => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)(Object.assign(Object.assign({}, prevState), {\n selectedElementIds: {\n [pointerDownState.hit.element.id]: true\n }\n }), this.scene.getNonDeletedElements(), prevState, this));\n } else {\n shouldReuseSelection = false;\n }\n }\n\n const elementsWithinSelection = this.state.selectionElement ? (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getElementsWithinSelection)(elements, this.state.selectionElement, this.scene.getNonDeletedElementsMap()) : [];\n this.setState(prevState => {\n const nextSelectedElementIds = Object.assign(Object.assign({}, shouldReuseSelection && prevState.selectedElementIds), elementsWithinSelection.reduce((acc, element) => {\n acc[element.id] = true;\n return acc;\n }, {}));\n\n if (pointerDownState.hit.element) {\n // if using ctrl/cmd, select the hitElement only if we\n // haven't box-selected anything else\n if (!elementsWithinSelection.length) {\n nextSelectedElementIds[pointerDownState.hit.element.id] = true;\n } else {\n delete nextSelectedElementIds[pointerDownState.hit.element.id];\n }\n }\n\n prevState = !shouldReuseSelection ? Object.assign(Object.assign({}, prevState), {\n selectedGroupIds: {},\n editingGroupId: null\n }) : prevState;\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // select linear element only when we haven't box-selected anything else\n selectedLinearElement: elementsWithinSelection.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(elementsWithinSelection[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(elementsWithinSelection[0]) : null,\n showHyperlinkPopup: elementsWithinSelection.length === 1 && (elementsWithinSelection[0].link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(elementsWithinSelection[0])) ? \"info\" : false\n });\n });\n }\n }\n });\n } // Returns whether the pointer move happened over either scrollbar\n\n\n handlePointerMoveOverScrollbars(event, pointerDownState) {\n if (pointerDownState.scrollbars.isOverHorizontal) {\n const x = event.clientX;\n const dx = x - pointerDownState.lastCoords.x;\n this.translateCanvas({\n scrollX: this.state.scrollX - dx / this.state.zoom.value\n });\n pointerDownState.lastCoords.x = x;\n return true;\n }\n\n if (pointerDownState.scrollbars.isOverVertical) {\n const y = event.clientY;\n const dy = y - pointerDownState.lastCoords.y;\n this.translateCanvas({\n scrollY: this.state.scrollY - dy / this.state.zoom.value\n });\n pointerDownState.lastCoords.y = y;\n return true;\n }\n\n return false;\n }\n\n onPointerUpFromPointerDownHandler(pointerDownState) {\n return (0,_reactUtils__WEBPACK_IMPORTED_MODULE_80__.withBatchedUpdates)(childEvent => {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;\n\n this.removePointer(childEvent);\n\n if (pointerDownState.eventListeners.onMove) {\n pointerDownState.eventListeners.onMove.flush();\n }\n\n const {\n newElement,\n resizingElement,\n croppingElementId,\n multiElement,\n activeTool,\n isResizing,\n isRotating,\n isCropping\n } = this.state;\n this.setState(prevState => ({\n isResizing: false,\n isRotating: false,\n isCropping: false,\n resizingElement: null,\n selectionElement: null,\n frameToHighlight: null,\n elementsToHighlight: null,\n cursorButton: \"up\",\n snapLines: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateStable)(prevState.snapLines, []),\n originSnapOffset: null\n }));\n this.lastPointerMoveCoords = null;\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setReferenceSnapPoints(null);\n _snapping__WEBPACK_IMPORTED_MODULE_58__.SnapCache.setVisibleGaps(null);\n this.savePointer(childEvent.clientX, childEvent.clientY, \"up\");\n this.setState({\n selectedElementsAreBeingDragged: false\n });\n const elementsMap = this.scene.getNonDeletedElementsMap(); // Handle end of dragging a point of a linear element, might close a loop\n // and sets binding element\n\n if (this.state.editingLinearElement) {\n if (!pointerDownState.boxSelection.hasOccurred && ((_b = (_a = pointerDownState.hit) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.id) !== this.state.editingLinearElement.elementId) {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n } else {\n const editingLinearElement = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this.scene);\n\n if (editingLinearElement !== this.state.editingLinearElement) {\n this.setState({\n editingLinearElement,\n suggestedBindings: []\n });\n }\n }\n } else if (this.state.selectedLinearElement) {\n if (((_d = (_c = pointerDownState.hit) === null || _c === void 0 ? void 0 : _c.element) === null || _d === void 0 ? void 0 : _d.id) !== this.state.selectedLinearElement.elementId) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement to null if there is more than one element selected since we don't want to show linear element handles\n\n if (selectedELements.length > 1) {\n this.setState({\n selectedLinearElement: null\n });\n }\n } else {\n const linearElementEditor = _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this.scene);\n const {\n startBindingElement,\n endBindingElement\n } = linearElementEditor;\n const element = this.scene.getElement(linearElementEditor.elementId);\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(element)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElement)(element, startBindingElement, endBindingElement, elementsMap, this.scene);\n }\n\n if (linearElementEditor !== this.state.selectedLinearElement) {\n this.setState({\n selectedLinearElement: Object.assign(Object.assign({}, linearElementEditor), {\n selectedPointsIndices: null\n }),\n suggestedBindings: []\n });\n }\n }\n }\n\n this.missingPointerEventCleanupEmitter.clear();\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_MOVE, pointerDownState.eventListeners.onMove);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.POINTER_UP, pointerDownState.eventListeners.onUp);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYDOWN, pointerDownState.eventListeners.onKeyDown);\n window.removeEventListener(_constants__WEBPACK_IMPORTED_MODULE_12__.EVENT.KEYUP, pointerDownState.eventListeners.onKeyUp);\n\n if (this.state.pendingImageElementId) {\n this.setState({\n pendingImageElementId: null\n });\n }\n\n (_f = (_e = this.props) === null || _e === void 0 ? void 0 : _e.onPointerUp) === null || _f === void 0 ? void 0 : _f.call(_e, activeTool, pointerDownState);\n this.onPointerUpEmitter.trigger(this.state.activeTool, pointerDownState, childEvent);\n\n if ((newElement === null || newElement === void 0 ? void 0 : newElement.type) === \"freedraw\") {\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(childEvent, this.state);\n const points = newElement.points;\n let dx = pointerCoords.x - newElement.x;\n let dy = pointerCoords.y - newElement.y; // Allows dots to avoid being flagged as infinitely small\n\n if (dx === points[0][0] && dy === points[0][1]) {\n dy += 0.0001;\n dx += 0.0001;\n }\n\n const pressures = newElement.simulatePressure ? [] : [...newElement.pressures, childEvent.pressure];\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)],\n pressures,\n lastCommittedPoint: (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(dx, dy)\n });\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isImageElement)(newElement)) {\n const imageElement = newElement;\n\n try {\n this.initializeImageDimensions(imageElement);\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({\n [imageElement.id]: true\n }, this.state)\n }, () => {\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n });\n } catch (error) {\n console.error(error);\n this.scene.replaceAllElements(this.scene.getElementsIncludingDeleted().filter(el => el.id !== imageElement.id));\n this.actionManager.executeAction(_actions__WEBPACK_IMPORTED_MODULE_5__.actionFinalize);\n }\n\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newElement)) {\n if (newElement.points.length > 1) {\n this.store.shouldCaptureIncrement();\n }\n\n const pointerCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(childEvent, this.state);\n\n if (!pointerDownState.drag.hasOccurred && newElement && !multiElement) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n points: [...newElement.points, (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerCoords.x - newElement.x, pointerCoords.y - newElement.y)]\n });\n this.setState({\n multiElement: newElement,\n newElement\n });\n } else if (pointerDownState.drag.hasOccurred && !multiElement) {\n if ((0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBindingElement)(newElement, false)) {\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.maybeBindLinearElement)(newElement, this.state, pointerCoords, this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements());\n }\n\n this.setState({\n suggestedBindings: [],\n startBoundElement: null\n });\n\n if (!activeTool.locked) {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n this.setState(prevState => ({\n newElement: null,\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n }),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [newElement.id]: true\n }), prevState),\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(newElement)\n }));\n } else {\n this.setState(prevState => ({\n newElement: null\n }));\n } // so that the scene gets rendered again to display the newly drawn linear as well\n\n\n this.scene.triggerUpdate();\n }\n\n return;\n }\n\n if ((0,_element__WEBPACK_IMPORTED_MODULE_16__.isTextElement)(newElement)) {\n const minWidth = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getMinTextElementWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_34__.getFontString)({\n fontSize: newElement.fontSize,\n fontFamily: newElement.fontFamily\n }), newElement.lineHeight);\n\n if (newElement.width < minWidth) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, {\n autoResize: true\n });\n }\n\n this.resetCursor();\n this.handleTextWysiwyg(newElement, {\n isExistingElement: true\n });\n }\n\n if (activeTool.type !== \"selection\" && newElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(newElement)) {\n // remove invisible element which was added in onPointerDown\n // update the store snapshot, so that invisible elements are not captured by the store\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== newElement.id),\n appState: {\n newElement: null\n },\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n });\n return;\n }\n\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(newElement)) {\n const elementsInsideFrame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInNewFrame)(this.scene.getElementsIncludingDeleted(), newElement, this.scene.getNonDeletedElementsMap());\n this.scene.replaceAllElements((0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(this.scene.getElementsMapIncludingDeleted(), elementsInsideFrame, newElement));\n }\n\n if (newElement) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(newElement, (0,_element__WEBPACK_IMPORTED_MODULE_16__.getNormalizedDimensions)(newElement)); // the above does not guarantee the scene to be rendered again, hence the trigger below\n\n this.scene.triggerUpdate();\n }\n\n if (pointerDownState.drag.hasOccurred) {\n const sceneCoords = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)(childEvent, this.state); // when editing the points of a linear element, we check if the\n // linear element still is in the frame afterwards\n // if not, the linear element will be removed from its frame (if any)\n\n if (this.state.selectedLinearElement && this.state.selectedLinearElement.isDragging) {\n const linearElement = this.scene.getElement(this.state.selectedLinearElement.elementId);\n\n if (linearElement === null || linearElement === void 0 ? void 0 : linearElement.frameId) {\n const frame = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getContainingFrame)(linearElement, elementsMap);\n\n if (frame && linearElement) {\n if (!(0,_frame__WEBPACK_IMPORTED_MODULE_50__.elementOverlapsWithFrame)(linearElement, frame, this.scene.getNonDeletedElementsMap())) {\n // remove the linear element from all groups\n // before removing it from the frame as well\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(linearElement, {\n groupIds: []\n });\n (0,_frame__WEBPACK_IMPORTED_MODULE_50__.removeElementsFromFrame)([linearElement], this.scene.getNonDeletedElementsMap());\n this.scene.triggerUpdate();\n }\n }\n }\n } else {\n // update the relationships between selected elements and frames\n const topLayerFrame = this.getTopLayerFrameAtSceneCoords(sceneCoords);\n const selectedElements = this.scene.getSelectedElements(this.state);\n let nextElements = this.scene.getElementsMapIncludingDeleted();\n\n const updateGroupIdsAfterEditingGroup = elements => {\n if (elements.length > 0) {\n for (const element of elements) {\n const index = element.groupIds.indexOf(this.state.editingGroupId);\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: element.groupIds.slice(0, index)\n }, false);\n }\n\n nextElements.forEach(element => {\n if (element.groupIds.length && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(nextElements, element.groupIds[element.groupIds.length - 1]).length < 2) {\n (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_19__.mutateElement)(element, {\n groupIds: []\n }, false);\n }\n });\n this.setState({\n editingGroupId: null\n });\n }\n };\n\n if (topLayerFrame && !this.state.selectedElementIds[topLayerFrame.id]) {\n const elementsToAdd = selectedElements.filter(element => element.frameId !== topLayerFrame.id && (0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n\n if (this.state.editingGroupId) {\n updateGroupIdsAfterEditingGroup(elementsToAdd);\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.addElementsToFrame)(nextElements, elementsToAdd, topLayerFrame);\n } else if (!topLayerFrame) {\n if (this.state.editingGroupId) {\n const elementsToRemove = selectedElements.filter(element => element.frameId && !(0,_frame__WEBPACK_IMPORTED_MODULE_50__.isElementInFrame)(element, nextElements, this.state));\n updateGroupIdsAfterEditingGroup(elementsToRemove);\n }\n }\n\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(nextElements, this.state, this);\n this.scene.replaceAllElements(nextElements);\n }\n }\n\n if (resizingElement) {\n this.store.shouldCaptureIncrement();\n }\n\n if (resizingElement && (0,_element__WEBPACK_IMPORTED_MODULE_16__.isInvisiblySmallElement)(resizingElement)) {\n // update the store snapshot, so that invisible elements are not captured by the store\n this.updateScene({\n elements: this.scene.getElementsIncludingDeleted().filter(el => el.id !== resizingElement.id),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_76__.StoreAction.UPDATE\n });\n } // handle frame membership for resizing frames and/or selected elements\n\n\n if (pointerDownState.resize.isResizing) {\n let nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.updateFrameMembershipOfSelectedElements)(this.scene.getElementsIncludingDeleted(), this.state, this);\n const selectedFrames = this.scene.getSelectedElements(this.state).filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(element));\n\n for (const frame of selectedFrames) {\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_50__.replaceAllElementsInFrame)(nextElements, (0,_frame__WEBPACK_IMPORTED_MODULE_50__.getElementsInResizingFrame)(this.scene.getElementsIncludingDeleted(), frame, this.state, elementsMap), frame, this);\n }\n\n this.scene.replaceAllElements(nextElements);\n } // Code below handles selection when element(s) weren't\n // drag or added to selection on pointer down phase.\n\n\n const hitElement = pointerDownState.hit.element;\n\n if (((_g = this.state.selectedLinearElement) === null || _g === void 0 ? void 0 : _g.elementId) !== (hitElement === null || hitElement === void 0 ? void 0 : hitElement.id) && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement)) {\n const selectedELements = this.scene.getSelectedElements(this.state); // set selectedLinearElement when no other element selected except\n // the one we've hit\n\n if (selectedELements.length === 1) {\n this.setState({\n selectedLinearElement: new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement)\n });\n }\n } // click outside the cropping region to exit\n\n\n if ( // not in the cropping mode at all\n !croppingElementId || // in the cropping mode\n croppingElementId && ( // not cropping and no hit element\n !hitElement && !isCropping || // hitting something else\n hitElement && hitElement.id !== croppingElementId)) {\n this.finishImageCropping();\n }\n\n const pointerStart = this.lastPointerDownEvent;\n const pointerEnd = this.lastPointerUpEvent || this.lastPointerMoveEvent;\n\n if ((0,_appState__WEBPACK_IMPORTED_MODULE_10__.isEraserActive)(this.state) && pointerStart && pointerEnd) {\n this.eraserTrail.endPath();\n const draggedDistance = (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointDistance)((0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerStart.clientX, pointerStart.clientY), (0,_math__WEBPACK_IMPORTED_MODULE_98__.pointFrom)(pointerEnd.clientX, pointerEnd.clientY));\n\n if (draggedDistance === 0) {\n const scenePointer = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.viewportCoordsToSceneCoords)({\n clientX: pointerEnd.clientX,\n clientY: pointerEnd.clientY\n }, this.state);\n const hitElements = this.getElementsAtPosition(scenePointer.x, scenePointer.y);\n hitElements.forEach(hitElement => this.elementsPendingErasure.add(hitElement.id));\n }\n\n this.eraseElements();\n return;\n } else if (this.elementsPendingErasure.size) {\n this.restoreReadyToEraseElements();\n }\n\n if (hitElement && !pointerDownState.drag.hasOccurred && !pointerDownState.hit.wasAddedToSelection && ( // if we're editing a line, pointerup shouldn't switch selection if\n // box selected\n !this.state.editingLinearElement || !pointerDownState.boxSelection.hasOccurred)) {\n // when inside line editor, shift selects points instead\n if (childEvent.shiftKey && !this.state.editingLinearElement) {\n if (this.state.selectedElementIds[hitElement.id]) {\n if ((0,_groups__WEBPACK_IMPORTED_MODULE_23__.isSelectedViaGroup)(this.state, hitElement)) {\n this.setState(_prevState => {\n const nextSelectedElementIds = Object.assign({}, _prevState.selectedElementIds); // We want to unselect all groups hitElement is part of\n // as well as all elements that are part of the groups\n // hitElement is part of\n\n for (const groupedElement of hitElement.groupIds.flatMap(groupId => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), groupId))) {\n delete nextSelectedElementIds[groupedElement.id];\n }\n\n return {\n selectedGroupIds: Object.assign(Object.assign({}, _prevState.selectedElementIds), hitElement.groupIds.map(gId => ({\n [gId]: false\n })).reduce((prev, acc) => Object.assign(Object.assign({}, prev), acc), {})),\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(nextSelectedElementIds, _prevState)\n };\n }); // if not dragging a linear element point (outside editor)\n } else if (!((_h = this.state.selectedLinearElement) === null || _h === void 0 ? void 0 : _h.isDragging)) {\n // remove element from selection while\n // keeping prev elements selected\n this.setState(prevState => {\n const newSelectedElementIds = Object.assign({}, prevState.selectedElementIds);\n delete newSelectedElementIds[hitElement.id];\n const newSelectedElements = (0,_scene__WEBPACK_IMPORTED_MODULE_28__.getSelectedElements)(this.scene.getNonDeletedElements(), {\n selectedElementIds: newSelectedElementIds\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: newSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n // set selectedLinearElement only if thats the only element selected\n selectedLinearElement: newSelectedElements.length === 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(newSelectedElements[0]) ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(newSelectedElements[0]) : prevState.selectedLinearElement\n });\n });\n }\n } else if (hitElement.frameId && this.state.selectedElementIds[hitElement.frameId]) {\n // when hitElement is part of a selected frame, deselect the frame\n // to avoid frame and containing elements selected simultaneously\n this.setState(prevState => {\n var _a, _b;\n\n const nextSelectedElementIds = Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [hitElement.id]: true\n }); // deselect the frame\n\n delete nextSelectedElementIds[hitElement.frameId]; // deselect groups containing the frame\n\n ((_b = (_a = this.scene.getElement(hitElement.frameId)) === null || _a === void 0 ? void 0 : _a.groupIds) !== null && _b !== void 0 ? _b : []).flatMap(gid => (0,_groups__WEBPACK_IMPORTED_MODULE_23__.getElementsInGroup)(this.scene.getNonDeletedElements(), gid)).forEach(element => {\n delete nextSelectedElementIds[element.id];\n });\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: nextSelectedElementIds\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n showHyperlinkPopup: hitElement.link || (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(hitElement) ? \"info\" : false\n });\n });\n } else {\n // add element to selection while keeping prev elements selected\n this.setState(_prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, _prevState.selectedElementIds), {\n [hitElement.id]: true\n }), _prevState)\n }));\n }\n } else {\n this.setState(prevState => {\n var _a;\n\n return Object.assign(Object.assign({}, (0,_groups__WEBPACK_IMPORTED_MODULE_23__.selectGroupsForSelectedElements)({\n editingGroupId: prevState.editingGroupId,\n selectedElementIds: {\n [hitElement.id]: true\n }\n }, this.scene.getNonDeletedElements(), prevState, this)), {\n selectedLinearElement: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement)(hitElement) && // Don't set `selectedLinearElement` if its same as the hitElement, this is mainly to prevent resetting the `hoverPointIndex` to -1.\n // Future we should update the API to take care of setting the correct `hoverPointIndex` when initialized\n ((_a = prevState.selectedLinearElement) === null || _a === void 0 ? void 0 : _a.elementId) !== hitElement.id ? new _element_linearElementEditor__WEBPACK_IMPORTED_MODULE_18__.LinearElementEditor(hitElement) : prevState.selectedLinearElement\n });\n });\n }\n }\n\n if ( // not dragged\n !pointerDownState.drag.hasOccurred && // not resized\n !this.state.isResizing && ( // only hitting the bounding box of the previous hit element\n hitElement && (0,_element_collision__WEBPACK_IMPORTED_MODULE_83__.hitElementBoundingBoxOnly)({\n x: pointerDownState.origin.x,\n y: pointerDownState.origin.y,\n element: hitElement,\n shape: (0,_shapes__WEBPACK_IMPORTED_MODULE_31__.getElementShape)(hitElement, this.scene.getNonDeletedElementsMap()),\n threshold: this.getElementHitThreshold(),\n frameNameBound: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isFrameLikeElement)(hitElement) ? this.frameNameBoundsCache.get(hitElement) : null\n }, elementsMap) || !hitElement && pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements)) {\n if (this.state.editingLinearElement) {\n this.setState({\n editingLinearElement: null\n });\n } else {\n // Deselect selected elements\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n selectedGroupIds: {},\n editingGroupId: null,\n activeEmbeddable: null\n });\n } // reset cursor\n\n\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.setCursor)(this.interactiveCanvas, _constants__WEBPACK_IMPORTED_MODULE_12__.CURSOR_TYPE.AUTO);\n return;\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\" && newElement) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)(Object.assign(Object.assign({}, prevState.selectedElementIds), {\n [newElement.id]: true\n }), prevState),\n showHyperlinkPopup: (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isEmbeddableElement)(newElement) && !newElement.link ? \"editor\" : prevState.showHyperlinkPopup\n }));\n }\n\n if (activeTool.type !== \"selection\" || (0,_scene__WEBPACK_IMPORTED_MODULE_28__.isSomeElementSelected)(this.scene.getNonDeletedElements(), this.state) || !(0,_utils__WEBPACK_IMPORTED_MODULE_34__.isShallowEqual)(this.state.previousSelectedElementIds, this.state.selectedElementIds)) {\n this.store.shouldCaptureIncrement();\n }\n\n if (pointerDownState.drag.hasOccurred || isResizing || isRotating || isCropping) {\n // We only allow binding via linear elements, specifically via dragging\n // the endpoints (\"start\" or \"end\").\n const linearElements = this.scene.getSelectedElements(this.state).filter(_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isLinearElement);\n (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.bindOrUnbindLinearElements)(linearElements, this.scene.getNonDeletedElementsMap(), this.scene.getNonDeletedElements(), this.scene, (0,_element_binding__WEBPACK_IMPORTED_MODULE_17__.isBindingEnabled)(this.state), (_k = (_j = this.state.selectedLinearElement) === null || _j === void 0 ? void 0 : _j.selectedPointsIndices) !== null && _k !== void 0 ? _k : []);\n }\n\n if (activeTool.type === \"laser\") {\n this.laserTrails.endPath();\n return;\n }\n\n if (!activeTool.locked && activeTool.type !== \"freedraw\") {\n (0,_cursor__WEBPACK_IMPORTED_MODULE_68__.resetCursor)(this.interactiveCanvas);\n this.setState({\n newElement: null,\n suggestedBindings: [],\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_34__.updateActiveTool)(this.state, {\n type: \"selection\"\n })\n });\n } else {\n this.setState({\n newElement: null,\n suggestedBindings: []\n });\n }\n\n if (hitElement && this.lastPointerUpEvent && this.lastPointerDownEvent && this.lastPointerUpEvent.timeStamp - this.lastPointerDownEvent.timeStamp < 300 && gesture.pointers.size <= 1 && (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isIframeLikeElement)(hitElement) && this.isIframeLikeElementCenter(hitElement, this.lastPointerUpEvent, pointerDownState.origin.x, pointerDownState.origin.y)) {\n this.handleEmbeddableCenterClick(hitElement);\n }\n });\n } //zsviczian - published on API\n\n\n setSelection(elements) {\n const selectedElementIds = {};\n const selectedGroupIds = {};\n elements.forEach(ele => {\n if (ele.groupIds.length) {\n selectedElementIds[ele.id] = true;\n ele.groupIds.forEach(id => {\n selectedGroupIds[id] = true;\n });\n } // exclude bound text elements as we don't mark them as selected when\n // container is selected unless in group\n else if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_21__.isBoundToContainer)(ele)) {\n selectedElementIds[ele.id] = true;\n }\n });\n this.setState({\n previousSelectedElementIds: this.state.selectedElementIds,\n selectedElementIds,\n selectedGroupIds\n });\n }\n\n clearSelection(hitElement) {\n this.setState(prevState => ({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, prevState),\n activeEmbeddable: null,\n selectedGroupIds: {},\n // Continue editing the same group if the user selected a different\n // element from it\n editingGroupId: prevState.editingGroupId && hitElement != null && (0,_groups__WEBPACK_IMPORTED_MODULE_23__.isElementInGroup)(hitElement, prevState.editingGroupId) ? prevState.editingGroupId : null\n }));\n this.setState({\n selectedElementIds: (0,_scene_selection__WEBPACK_IMPORTED_MODULE_51__.makeNextSelectedElementIds)({}, this.state),\n activeEmbeddable: null,\n previousSelectedElementIds: this.state.selectedElementIds\n });\n }\n\n getTextWysiwygSnappedToCenterPosition(x, y, appState, container) {\n if (container) {\n let elementCenterX = container.x + container.width / 2;\n let elementCenterY = container.y + container.height / 2;\n const elementCenter = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_44__.getContainerCenter)(container, appState, this.scene.getNonDeletedElementsMap());\n\n if (elementCenter) {\n elementCenterX = elementCenter.x;\n elementCenterY = elementCenter.y;\n }\n\n const distanceToCenter = Math.hypot(x - elementCenterX, y - elementCenterY);\n const isSnappedToCenter = distanceToCenter < _constants__WEBPACK_IMPORTED_MODULE_12__.TEXT_TO_CENTER_SNAP_THRESHOLD;\n\n if (isSnappedToCenter) {\n const {\n x: viewportX,\n y: viewportY\n } = (0,_utils__WEBPACK_IMPORTED_MODULE_34__.sceneCoordsToViewportCoords)({\n sceneX: elementCenterX,\n sceneY: elementCenterY\n }, appState);\n return {\n viewportX,\n viewportY,\n elementCenterX,\n elementCenterY\n };\n }\n }\n }\n\n getCanvasOffsets() {\n var _a;\n\n if ((_a = this.excalidrawContainerRef) === null || _a === void 0 ? void 0 : _a.current) {\n const excalidrawContainer = this.excalidrawContainerRef.current;\n const {\n left,\n top\n } = excalidrawContainer.getBoundingClientRect();\n return {\n offsetLeft: left,\n offsetTop: top\n };\n }\n\n return {\n offsetLeft: 0,\n offsetTop: 0\n };\n }\n\n async updateLanguage() {\n const currentLang = _i18n__WEBPACK_IMPORTED_MODULE_25__.languages.find(lang => lang.code === this.props.langCode) || _i18n__WEBPACK_IMPORTED_MODULE_25__.defaultLang;\n await (0,_i18n__WEBPACK_IMPORTED_MODULE_25__.setLanguage)(currentLang);\n this.setAppState({});\n }\n\n}\n/* //zsviczian\nexport const createTestHook = () => {\n if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {\n window.h = window.h || ({} as Window[\"h\"]);\n\n Object.defineProperties(window.h, {\n elements: {\n configurable: true,\n get() {\n return this.app?.scene.getElementsIncludingDeleted();\n },\n set(elements: ExcalidrawElement[]) {\n return this.app?.scene.replaceAllElements(\n syncInvalidIndices(elements),\n );\n },\n },\n scene: {\n configurable: true,\n get() {\n return this.app?.scene;\n },\n },\n });\n }\n};\n\ncreateTestHook();*/\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);\n\n//# sourceURL=webpack://ExcalidrawLib/./components/App.tsx?");
928
928
 
929
929
  /***/ }),
930
930
 
@@ -2629,7 +2629,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2629
2629
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2630
2630
 
2631
2631
  "use strict";
2632
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ImageURLToFile\": () => (/* binding */ ImageURLToFile),\n/* harmony export */ \"SVGStringToFile\": () => (/* binding */ SVGStringToFile),\n/* harmony export */ \"blobToArrayBuffer\": () => (/* binding */ blobToArrayBuffer),\n/* harmony export */ \"canvasToBlob\": () => (/* binding */ canvasToBlob),\n/* harmony export */ \"createFile\": () => (/* binding */ createFile),\n/* harmony export */ \"dataURLToFile\": () => (/* binding */ dataURLToFile),\n/* harmony export */ \"generateIdFromFile\": () => (/* binding */ generateIdFromFile),\n/* harmony export */ \"getDataURL\": () => (/* binding */ getDataURL),\n/* harmony export */ \"getFileFromEvent\": () => (/* binding */ getFileFromEvent),\n/* harmony export */ \"getFileHandle\": () => (/* binding */ getFileHandle),\n/* harmony export */ \"getFileHandleType\": () => (/* binding */ getFileHandleType),\n/* harmony export */ \"getMimeType\": () => (/* binding */ getMimeType),\n/* harmony export */ \"isImageFileHandle\": () => (/* binding */ isImageFileHandle),\n/* harmony export */ \"isImageFileHandleType\": () => (/* binding */ isImageFileHandleType),\n/* harmony export */ \"isSupportedImageFile\": () => (/* binding */ isSupportedImageFile),\n/* harmony export */ \"loadFromBlob\": () => (/* binding */ loadFromBlob),\n/* harmony export */ \"loadLibraryFromBlob\": () => (/* binding */ loadLibraryFromBlob),\n/* harmony export */ \"loadSceneOrLibraryFromBlob\": () => (/* binding */ loadSceneOrLibraryFromBlob),\n/* harmony export */ \"normalizeFile\": () => (/* binding */ normalizeFile),\n/* harmony export */ \"parseLibraryJSON\": () => (/* binding */ parseLibraryJSON),\n/* harmony export */ \"resizeImageFile\": () => (/* binding */ resizeImageFile)\n/* harmony export */ });\n/* harmony import */ var nanoid__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! nanoid */ \"./node_modules/nanoid/index.browser.js\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ \"./errors.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../scene */ \"./scene/index.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _filesystem__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./filesystem */ \"./data/filesystem.ts\");\n/* harmony import */ var _json__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./json */ \"./data/json.ts\");\n/* harmony import */ var _restore__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./restore */ \"./data/restore.ts\");\n\n\n\n\n\n\n\n\n\n\n\nconst parseFileContents = async blob => {\n let contents;\n\n if (blob.type === _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.png) {\n try {\n return await (await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./image */ \"./data/image.ts\"))).decodePngMetadata(blob);\n } catch (error) {\n if (error.message === \"INVALID\") {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Image doesn't contain scene\", \"IMAGE_NOT_CONTAINS_SCENE_DATA\");\n } else {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Error: cannot restore image\");\n }\n }\n } else {\n if (\"text\" in Blob) {\n contents = await blob.text();\n } else {\n contents = await new Promise(resolve => {\n const reader = new FileReader();\n reader.readAsText(blob, \"utf8\");\n\n reader.onloadend = () => {\n if (reader.readyState === FileReader.DONE) {\n resolve(reader.result);\n }\n };\n });\n }\n\n if (blob.type === _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg) {\n try {\n return await (await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./image */ \"./data/image.ts\"))).decodeSvgMetadata({\n svg: contents\n });\n } catch (error) {\n if (error.message === \"INVALID\") {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Image doesn't contain scene\", \"IMAGE_NOT_CONTAINS_SCENE_DATA\");\n } else {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Error: cannot restore image\");\n }\n }\n }\n }\n\n return contents;\n};\n\nconst getMimeType = blob => {\n let name;\n\n if (typeof blob === \"string\") {\n name = blob;\n } else {\n if (blob.type) {\n return blob.type;\n }\n\n name = blob.name || \"\";\n }\n\n if (/\\.(excalidraw|json)$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.json;\n } else if (/\\.png$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.png;\n } else if (/\\.jpe?g$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.jpg;\n } else if (/\\.svg$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg;\n }\n\n return \"\";\n};\nconst getFileHandleType = handle => {\n var _a;\n\n if (!handle) {\n return null;\n }\n\n return ((_a = handle.name.match(/\\.(json|excalidraw|png|svg)$/)) === null || _a === void 0 ? void 0 : _a[1]) || null;\n};\nconst isImageFileHandleType = type => {\n return type === \"png\" || type === \"svg\";\n};\nconst isImageFileHandle = handle => {\n const type = getFileHandleType(handle);\n return type === \"png\" || type === \"svg\";\n};\nconst isSupportedImageFile = blob => {\n const {\n type\n } = blob || {};\n return !!type && Object.values(_constants__WEBPACK_IMPORTED_MODULE_1__.IMAGE_MIME_TYPES).includes(type);\n};\nconst loadSceneOrLibraryFromBlob = async (blob,\n/** @see restore.localAppState */\nlocalAppState, localElements,\n/** FileSystemHandle. Defaults to `blob.handle` if defined, otherwise null. */\nfileHandle) => {\n const contents = await parseFileContents(blob);\n let data;\n\n try {\n try {\n data = JSON.parse(contents);\n } catch (error) {\n if (isSupportedImageFile(blob)) {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Image doesn't contain scene\", \"IMAGE_NOT_CONTAINS_SCENE_DATA\");\n }\n\n throw error;\n }\n\n if ((0,_json__WEBPACK_IMPORTED_MODULE_7__.isValidExcalidrawData)(data)) {\n return {\n type: _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidraw,\n data: (0,_restore__WEBPACK_IMPORTED_MODULE_8__.restore)({\n elements: (0,_element__WEBPACK_IMPORTED_MODULE_2__.clearElementsForExport)(data.elements || []),\n appState: Object.assign(Object.assign({\n theme: localAppState === null || localAppState === void 0 ? void 0 : localAppState.theme,\n fileHandle: fileHandle || blob.handle || null\n }, (0,_appState__WEBPACK_IMPORTED_MODULE_0__.cleanAppStateForExport)(data.appState || {})), localAppState ? (0,_scene__WEBPACK_IMPORTED_MODULE_4__.calculateScrollCenter)(data.elements || [], localAppState) : {}),\n files: data.files\n }, localAppState, localElements, {\n repairBindings: true,\n refreshDimensions: false\n })\n };\n } else if ((0,_json__WEBPACK_IMPORTED_MODULE_7__.isValidLibrary)(data)) {\n return {\n type: _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidrawlib,\n data\n };\n }\n\n throw new Error(\"Error: invalid file\");\n } catch (error) {\n if (error instanceof _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError) {\n throw error;\n }\n\n throw new Error(\"Error: invalid file\");\n }\n};\nconst loadFromBlob = async (blob,\n/** @see restore.localAppState */\nlocalAppState, localElements,\n/** FileSystemHandle. Defaults to `blob.handle` if defined, otherwise null. */\nfileHandle) => {\n const ret = await loadSceneOrLibraryFromBlob(blob, localAppState, localElements, fileHandle);\n\n if (ret.type !== _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidraw) {\n throw new Error(\"Error: invalid file\");\n }\n\n return ret.data;\n};\nconst parseLibraryJSON = (json, defaultStatus = \"unpublished\") => {\n const data = JSON.parse(json);\n\n if (!(0,_json__WEBPACK_IMPORTED_MODULE_7__.isValidLibrary)(data)) {\n throw new Error(\"Invalid library\");\n }\n\n const libraryItems = data.libraryItems || data.library;\n return (0,_restore__WEBPACK_IMPORTED_MODULE_8__.restoreLibraryItems)(libraryItems, defaultStatus);\n};\nconst loadLibraryFromBlob = async (blob, defaultStatus = \"unpublished\") => {\n return parseLibraryJSON(await parseFileContents(blob), defaultStatus);\n};\nconst canvasToBlob = async canvas => {\n return new Promise(async (resolve, reject) => {\n try {\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_5__.isPromiseLike)(canvas)) {\n canvas = await canvas;\n }\n\n canvas.toBlob(blob => {\n if (!blob) {\n return reject(new _errors__WEBPACK_IMPORTED_MODULE_3__.CanvasError(\"Error: Canvas too big\", \"CANVAS_POSSIBLY_TOO_BIG\"));\n }\n\n resolve(blob);\n });\n } catch (error) {\n reject(error);\n }\n });\n};\n/** generates SHA-1 digest from supplied file (if not supported, falls back\n to a 40-char base64 random id) */\n\nconst generateIdFromFile = async file => {\n try {\n const hashBuffer = await window.crypto.subtle.digest(\"SHA-1\", await blobToArrayBuffer(file));\n return (0,_utils__WEBPACK_IMPORTED_MODULE_5__.bytesToHexString)(new Uint8Array(hashBuffer));\n } catch (error) {\n console.error(error); // length 40 to align with the HEX length of SHA-1 (which is 160 bit)\n\n return (0,nanoid__WEBPACK_IMPORTED_MODULE_9__.nanoid)(40);\n }\n};\nconst getDataURL = async file => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n const dataURL = reader.result;\n resolve(dataURL);\n };\n\n reader.onerror = error => reject(error);\n\n reader.readAsDataURL(file);\n });\n};\nconst dataURLToFile = (dataURL, filename = \"\") => {\n const dataIndexStart = dataURL.indexOf(\",\");\n const byteString = atob(dataURL.slice(dataIndexStart + 1));\n const mimeType = dataURL.slice(0, dataIndexStart).split(\":\")[1].split(\";\")[0];\n const ab = new ArrayBuffer(byteString.length);\n const ia = new Uint8Array(ab);\n\n for (let i = 0; i < byteString.length; i++) {\n ia[i] = byteString.charCodeAt(i);\n }\n\n return new File([ab], filename, {\n type: mimeType\n });\n};\nconst resizeImageFile = async (file, opts) => {\n // SVG files shouldn't a can't be resized\n if (file.type === _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg) {\n return file;\n }\n\n const [pica, imageBlobReduce] = await Promise.all([Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! pica */ \"../../node_modules/pica/dist/pica.js\", 23)).then(res => res.default), // a wrapper for pica for better API\n Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! image-blob-reduce */ \"../../node_modules/image-blob-reduce/dist/image-blob-reduce.esm.mjs\")).then(res => res.default)]); // CRA's minification settings break pica in WebWorkers, so let's disable\n // them for now\n // https://github.com/nodeca/image-blob-reduce/issues/21#issuecomment-757365513\n\n const reduce = imageBlobReduce({\n pica: pica({\n features: [\"js\", \"wasm\"]\n })\n });\n\n if (opts.outputType) {\n const {\n outputType\n } = opts;\n\n reduce._create_blob = function (env) {\n return this.pica.toBlob(env.out_canvas, outputType, 0.8).then(blob => {\n env.out_blob = blob;\n return env;\n });\n };\n }\n\n if (!isSupportedImageFile(file)) {\n throw new Error(\"Error: unsupported file type\", {\n cause: \"UNSUPPORTED\"\n });\n }\n\n return new File([await reduce.toBlob(file, {\n max: opts.maxWidthOrHeight\n })], file.name, {\n type: opts.outputType || file.type\n });\n};\nconst SVGStringToFile = (SVGString, filename = \"\") => {\n return new File([new TextEncoder().encode(SVGString)], filename, {\n type: _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg\n });\n};\nconst ImageURLToFile = async (imageUrl, filename = \"\") => {\n let response;\n\n try {\n response = await fetch(imageUrl);\n } catch (error) {\n throw new Error(\"Error: failed to fetch image\", {\n cause: \"FETCH_ERROR\"\n });\n }\n\n if (!response.ok) {\n throw new Error(\"Error: failed to fetch image\", {\n cause: \"FETCH_ERROR\"\n });\n }\n\n const blob = await response.blob();\n\n if (blob.type && isSupportedImageFile(blob)) {\n const name = filename || blob.name || \"\";\n return new File([blob], name, {\n type: blob.type\n });\n }\n\n throw new Error(\"Error: unsupported file type\", {\n cause: \"UNSUPPORTED\"\n });\n};\nconst getFileFromEvent = async event => {\n const file = event.dataTransfer.files.item(0);\n const fileHandle = await getFileHandle(event);\n return {\n file: file ? await normalizeFile(file) : null,\n fileHandle\n };\n};\nconst getFileHandle = async event => {\n if (_filesystem__WEBPACK_IMPORTED_MODULE_6__.nativeFileSystemSupported) {\n try {\n const item = event.dataTransfer.items[0];\n\n if (!item) {\n //zsviczian (Obsidian move tab to new pane generates a drop event without an item)\n return null;\n }\n\n const handle = (await item.getAsFileSystemHandle()) || null;\n return handle;\n } catch (error) {\n console.warn(error.name, error.message);\n return null;\n }\n }\n\n return null;\n};\n/**\n * attempts to detect if a buffer is a valid image by checking its leading bytes\n */\n\nconst getActualMimeTypeFromImage = buffer => {\n let mimeType = null;\n const first8Bytes = `${[...new Uint8Array(buffer).slice(0, 8)].join(\" \")} `; // uint8 leading bytes\n\n const headerBytes = {\n // https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header\n png: \"137 80 78 71 13 10 26 10 \",\n // https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure\n // jpg is a bit wonky. Checking the first three bytes should be enough,\n // but may yield false positives. (https://stackoverflow.com/a/23360709/927631)\n jpg: \"255 216 255 \",\n // https://en.wikipedia.org/wiki/GIF#Example_GIF_file\n gif: \"71 73 70 56 57 97 \"\n };\n\n if (first8Bytes === headerBytes.png) {\n mimeType = _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.png;\n } else if (first8Bytes.startsWith(headerBytes.jpg)) {\n mimeType = _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.jpg;\n } else if (first8Bytes.startsWith(headerBytes.gif)) {\n mimeType = _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.gif;\n }\n\n return mimeType;\n};\n\nconst createFile = (blob, mimeType, name) => {\n return new File([blob], name || \"\", {\n type: mimeType\n });\n};\n/** attempts to detect correct mimeType if none is set, or if an image\n * has an incorrect extension.\n * Note: doesn't handle missing .excalidraw/.excalidrawlib extension */\n\nconst normalizeFile = async file => {\n var _a, _b;\n\n if (!file.type) {\n if ((_a = file === null || file === void 0 ? void 0 : file.name) === null || _a === void 0 ? void 0 : _a.endsWith(\".excalidrawlib\")) {\n file = createFile(await blobToArrayBuffer(file), _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidrawlib, file.name);\n } else if ((_b = file === null || file === void 0 ? void 0 : file.name) === null || _b === void 0 ? void 0 : _b.endsWith(\".excalidraw\")) {\n file = createFile(await blobToArrayBuffer(file), _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidraw, file.name);\n } else {\n const buffer = await blobToArrayBuffer(file);\n const mimeType = getActualMimeTypeFromImage(buffer);\n\n if (mimeType) {\n file = createFile(buffer, mimeType, file.name);\n }\n } // when the file is an image, make sure the extension corresponds to the\n // actual mimeType (this is an edge case, but happens sometime)\n\n } else if (isSupportedImageFile(file)) {\n const buffer = await blobToArrayBuffer(file);\n const mimeType = getActualMimeTypeFromImage(buffer);\n\n if (mimeType && mimeType !== file.type) {\n file = createFile(buffer, mimeType, file.name);\n }\n }\n\n return file;\n};\nconst blobToArrayBuffer = blob => {\n if (\"arrayBuffer\" in blob) {\n return blob.arrayBuffer();\n } // Safari\n\n\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = event => {\n var _a;\n\n if (!((_a = event.target) === null || _a === void 0 ? void 0 : _a.result)) {\n return reject(new Error(\"Couldn't convert blob to ArrayBuffer\"));\n }\n\n resolve(event.target.result);\n };\n\n reader.readAsArrayBuffer(blob);\n });\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./data/blob.ts?");
2632
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ImageURLToFile\": () => (/* binding */ ImageURLToFile),\n/* harmony export */ \"SVGStringToFile\": () => (/* binding */ SVGStringToFile),\n/* harmony export */ \"blobToArrayBuffer\": () => (/* binding */ blobToArrayBuffer),\n/* harmony export */ \"canvasToBlob\": () => (/* binding */ canvasToBlob),\n/* harmony export */ \"createFile\": () => (/* binding */ createFile),\n/* harmony export */ \"dataURLToFile\": () => (/* binding */ dataURLToFile),\n/* harmony export */ \"dataURLToString\": () => (/* binding */ dataURLToString),\n/* harmony export */ \"generateIdFromFile\": () => (/* binding */ generateIdFromFile),\n/* harmony export */ \"getDataURL\": () => (/* binding */ getDataURL),\n/* harmony export */ \"getDataURL_sync\": () => (/* binding */ getDataURL_sync),\n/* harmony export */ \"getFileFromEvent\": () => (/* binding */ getFileFromEvent),\n/* harmony export */ \"getFileHandle\": () => (/* binding */ getFileHandle),\n/* harmony export */ \"getFileHandleType\": () => (/* binding */ getFileHandleType),\n/* harmony export */ \"getMimeType\": () => (/* binding */ getMimeType),\n/* harmony export */ \"isImageFileHandle\": () => (/* binding */ isImageFileHandle),\n/* harmony export */ \"isImageFileHandleType\": () => (/* binding */ isImageFileHandleType),\n/* harmony export */ \"isSupportedImageFile\": () => (/* binding */ isSupportedImageFile),\n/* harmony export */ \"loadFromBlob\": () => (/* binding */ loadFromBlob),\n/* harmony export */ \"loadLibraryFromBlob\": () => (/* binding */ loadLibraryFromBlob),\n/* harmony export */ \"loadSceneOrLibraryFromBlob\": () => (/* binding */ loadSceneOrLibraryFromBlob),\n/* harmony export */ \"normalizeFile\": () => (/* binding */ normalizeFile),\n/* harmony export */ \"parseLibraryJSON\": () => (/* binding */ parseLibraryJSON),\n/* harmony export */ \"resizeImageFile\": () => (/* binding */ resizeImageFile)\n/* harmony export */ });\n/* harmony import */ var nanoid__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! nanoid */ \"./node_modules/nanoid/index.browser.js\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../errors */ \"./errors.ts\");\n/* harmony import */ var _scene__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../scene */ \"./scene/index.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _encode__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./encode */ \"./data/encode.ts\");\n/* harmony import */ var _filesystem__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./filesystem */ \"./data/filesystem.ts\");\n/* harmony import */ var _json__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./json */ \"./data/json.ts\");\n/* harmony import */ var _restore__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./restore */ \"./data/restore.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\nconst parseFileContents = async blob => {\n let contents;\n\n if (blob.type === _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.png) {\n try {\n return await (await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./image */ \"./data/image.ts\"))).decodePngMetadata(blob);\n } catch (error) {\n if (error.message === \"INVALID\") {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Image doesn't contain scene\", \"IMAGE_NOT_CONTAINS_SCENE_DATA\");\n } else {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Error: cannot restore image\");\n }\n }\n } else {\n if (\"text\" in Blob) {\n contents = await blob.text();\n } else {\n contents = await new Promise(resolve => {\n const reader = new FileReader();\n reader.readAsText(blob, \"utf8\");\n\n reader.onloadend = () => {\n if (reader.readyState === FileReader.DONE) {\n resolve(reader.result);\n }\n };\n });\n }\n\n if (blob.type === _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg) {\n try {\n return (await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ./image */ \"./data/image.ts\"))).decodeSvgMetadata({\n svg: contents\n });\n } catch (error) {\n if (error.message === \"INVALID\") {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Image doesn't contain scene\", \"IMAGE_NOT_CONTAINS_SCENE_DATA\");\n } else {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Error: cannot restore image\");\n }\n }\n }\n }\n\n return contents;\n};\n\nconst getMimeType = blob => {\n let name;\n\n if (typeof blob === \"string\") {\n name = blob;\n } else {\n if (blob.type) {\n return blob.type;\n }\n\n name = blob.name || \"\";\n }\n\n if (/\\.(excalidraw|json)$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.json;\n } else if (/\\.png$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.png;\n } else if (/\\.jpe?g$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.jpg;\n } else if (/\\.svg$/.test(name)) {\n return _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg;\n }\n\n return \"\";\n};\nconst getFileHandleType = handle => {\n var _a;\n\n if (!handle) {\n return null;\n }\n\n return ((_a = handle.name.match(/\\.(json|excalidraw|png|svg)$/)) === null || _a === void 0 ? void 0 : _a[1]) || null;\n};\nconst isImageFileHandleType = type => {\n return type === \"png\" || type === \"svg\";\n};\nconst isImageFileHandle = handle => {\n const type = getFileHandleType(handle);\n return type === \"png\" || type === \"svg\";\n};\nconst isSupportedImageFile = blob => {\n const {\n type\n } = blob || {};\n return !!type && Object.values(_constants__WEBPACK_IMPORTED_MODULE_1__.IMAGE_MIME_TYPES).includes(type);\n};\nconst loadSceneOrLibraryFromBlob = async (blob,\n/** @see restore.localAppState */\nlocalAppState, localElements,\n/** FileSystemHandle. Defaults to `blob.handle` if defined, otherwise null. */\nfileHandle) => {\n const contents = await parseFileContents(blob);\n let data;\n\n try {\n try {\n data = JSON.parse(contents);\n } catch (error) {\n if (isSupportedImageFile(blob)) {\n throw new _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError(\"Image doesn't contain scene\", \"IMAGE_NOT_CONTAINS_SCENE_DATA\");\n }\n\n throw error;\n }\n\n if ((0,_json__WEBPACK_IMPORTED_MODULE_8__.isValidExcalidrawData)(data)) {\n return {\n type: _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidraw,\n data: (0,_restore__WEBPACK_IMPORTED_MODULE_9__.restore)({\n elements: (0,_element__WEBPACK_IMPORTED_MODULE_2__.clearElementsForExport)(data.elements || []),\n appState: Object.assign(Object.assign({\n theme: localAppState === null || localAppState === void 0 ? void 0 : localAppState.theme,\n fileHandle: fileHandle || blob.handle || null\n }, (0,_appState__WEBPACK_IMPORTED_MODULE_0__.cleanAppStateForExport)(data.appState || {})), localAppState ? (0,_scene__WEBPACK_IMPORTED_MODULE_4__.calculateScrollCenter)(data.elements || [], localAppState) : {}),\n files: data.files\n }, localAppState, localElements, {\n repairBindings: true,\n refreshDimensions: false\n })\n };\n } else if ((0,_json__WEBPACK_IMPORTED_MODULE_8__.isValidLibrary)(data)) {\n return {\n type: _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidrawlib,\n data\n };\n }\n\n throw new Error(\"Error: invalid file\");\n } catch (error) {\n if (error instanceof _errors__WEBPACK_IMPORTED_MODULE_3__.ImageSceneDataError) {\n throw error;\n }\n\n throw new Error(\"Error: invalid file\");\n }\n};\nconst loadFromBlob = async (blob,\n/** @see restore.localAppState */\nlocalAppState, localElements,\n/** FileSystemHandle. Defaults to `blob.handle` if defined, otherwise null. */\nfileHandle) => {\n const ret = await loadSceneOrLibraryFromBlob(blob, localAppState, localElements, fileHandle);\n\n if (ret.type !== _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidraw) {\n throw new Error(\"Error: invalid file\");\n }\n\n return ret.data;\n};\nconst parseLibraryJSON = (json, defaultStatus = \"unpublished\") => {\n const data = JSON.parse(json);\n\n if (!(0,_json__WEBPACK_IMPORTED_MODULE_8__.isValidLibrary)(data)) {\n throw new Error(\"Invalid library\");\n }\n\n const libraryItems = data.libraryItems || data.library;\n return (0,_restore__WEBPACK_IMPORTED_MODULE_9__.restoreLibraryItems)(libraryItems, defaultStatus);\n};\nconst loadLibraryFromBlob = async (blob, defaultStatus = \"unpublished\") => {\n return parseLibraryJSON(await parseFileContents(blob), defaultStatus);\n};\nconst canvasToBlob = async canvas => {\n return new Promise(async (resolve, reject) => {\n try {\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_5__.isPromiseLike)(canvas)) {\n canvas = await canvas;\n }\n\n canvas.toBlob(blob => {\n if (!blob) {\n return reject(new _errors__WEBPACK_IMPORTED_MODULE_3__.CanvasError(\"Error: Canvas too big\", \"CANVAS_POSSIBLY_TOO_BIG\"));\n }\n\n resolve(blob);\n });\n } catch (error) {\n reject(error);\n }\n });\n};\n/** generates SHA-1 digest from supplied file (if not supported, falls back\n to a 40-char base64 random id) */\n\nconst generateIdFromFile = async file => {\n try {\n const hashBuffer = await window.crypto.subtle.digest(\"SHA-1\", await blobToArrayBuffer(file));\n return (0,_utils__WEBPACK_IMPORTED_MODULE_5__.bytesToHexString)(new Uint8Array(hashBuffer));\n } catch (error) {\n console.error(error); // length 40 to align with the HEX length of SHA-1 (which is 160 bit)\n\n return (0,nanoid__WEBPACK_IMPORTED_MODULE_10__.nanoid)(40);\n }\n};\n/** async. For sync variant, use getDataURL_sync */\n\nconst getDataURL = async file => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n const dataURL = reader.result;\n resolve(dataURL);\n };\n\n reader.onerror = error => reject(error);\n\n reader.readAsDataURL(file);\n });\n};\nconst getDataURL_sync = (data, mimeType) => {\n return `data:${mimeType};base64,${(0,_encode__WEBPACK_IMPORTED_MODULE_6__.stringToBase64)((0,_encode__WEBPACK_IMPORTED_MODULE_6__.toByteString)(data), true)}`;\n};\nconst dataURLToFile = (dataURL, filename = \"\") => {\n const dataIndexStart = dataURL.indexOf(\",\");\n const byteString = atob(dataURL.slice(dataIndexStart + 1));\n const mimeType = dataURL.slice(0, dataIndexStart).split(\":\")[1].split(\";\")[0];\n const ab = new ArrayBuffer(byteString.length);\n const ia = new Uint8Array(ab);\n\n for (let i = 0; i < byteString.length; i++) {\n ia[i] = byteString.charCodeAt(i);\n }\n\n return new File([ab], filename, {\n type: mimeType\n });\n};\nconst dataURLToString = dataURL => {\n return (0,_encode__WEBPACK_IMPORTED_MODULE_6__.base64ToString)(dataURL.slice(dataURL.indexOf(\",\") + 1));\n};\nconst resizeImageFile = async (file, opts) => {\n // SVG files shouldn't a can't be resized\n if (file.type === _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg) {\n return file;\n }\n\n const [pica, imageBlobReduce] = await Promise.all([Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! pica */ \"../../node_modules/pica/dist/pica.js\", 23)).then(res => res.default), // a wrapper for pica for better API\n Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! image-blob-reduce */ \"../../node_modules/image-blob-reduce/dist/image-blob-reduce.esm.mjs\")).then(res => res.default)]); // CRA's minification settings break pica in WebWorkers, so let's disable\n // them for now\n // https://github.com/nodeca/image-blob-reduce/issues/21#issuecomment-757365513\n\n const reduce = imageBlobReduce({\n pica: pica({\n features: [\"js\", \"wasm\"]\n })\n });\n\n if (opts.outputType) {\n const {\n outputType\n } = opts;\n\n reduce._create_blob = function (env) {\n return this.pica.toBlob(env.out_canvas, outputType, 0.8).then(blob => {\n env.out_blob = blob;\n return env;\n });\n };\n }\n\n if (!isSupportedImageFile(file)) {\n throw new Error(\"Error: unsupported file type\", {\n cause: \"UNSUPPORTED\"\n });\n }\n\n return new File([await reduce.toBlob(file, {\n max: opts.maxWidthOrHeight\n })], file.name, {\n type: opts.outputType || file.type\n });\n};\nconst SVGStringToFile = (SVGString, filename = \"\") => {\n return new File([new TextEncoder().encode(SVGString)], filename, {\n type: _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.svg\n });\n};\nconst ImageURLToFile = async (imageUrl, filename = \"\") => {\n let response;\n\n try {\n response = await fetch(imageUrl);\n } catch (error) {\n throw new Error(\"Error: failed to fetch image\", {\n cause: \"FETCH_ERROR\"\n });\n }\n\n if (!response.ok) {\n throw new Error(\"Error: failed to fetch image\", {\n cause: \"FETCH_ERROR\"\n });\n }\n\n const blob = await response.blob();\n\n if (blob.type && isSupportedImageFile(blob)) {\n const name = filename || blob.name || \"\";\n return new File([blob], name, {\n type: blob.type\n });\n }\n\n throw new Error(\"Error: unsupported file type\", {\n cause: \"UNSUPPORTED\"\n });\n};\nconst getFileFromEvent = async event => {\n const file = event.dataTransfer.files.item(0);\n const fileHandle = await getFileHandle(event);\n return {\n file: file ? await normalizeFile(file) : null,\n fileHandle\n };\n};\nconst getFileHandle = async event => {\n if (_filesystem__WEBPACK_IMPORTED_MODULE_7__.nativeFileSystemSupported) {\n try {\n const item = event.dataTransfer.items[0];\n\n if (!item) {\n //zsviczian (Obsidian move tab to new pane generates a drop event without an item)\n return null;\n }\n\n const handle = (await item.getAsFileSystemHandle()) || null;\n return handle;\n } catch (error) {\n console.warn(error.name, error.message);\n return null;\n }\n }\n\n return null;\n};\n/**\n * attempts to detect if a buffer is a valid image by checking its leading bytes\n */\n\nconst getActualMimeTypeFromImage = buffer => {\n let mimeType = null;\n const first8Bytes = `${[...new Uint8Array(buffer).slice(0, 8)].join(\" \")} `; // uint8 leading bytes\n\n const headerBytes = {\n // https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header\n png: \"137 80 78 71 13 10 26 10 \",\n // https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure\n // jpg is a bit wonky. Checking the first three bytes should be enough,\n // but may yield false positives. (https://stackoverflow.com/a/23360709/927631)\n jpg: \"255 216 255 \",\n // https://en.wikipedia.org/wiki/GIF#Example_GIF_file\n gif: \"71 73 70 56 57 97 \"\n };\n\n if (first8Bytes === headerBytes.png) {\n mimeType = _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.png;\n } else if (first8Bytes.startsWith(headerBytes.jpg)) {\n mimeType = _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.jpg;\n } else if (first8Bytes.startsWith(headerBytes.gif)) {\n mimeType = _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.gif;\n }\n\n return mimeType;\n};\n\nconst createFile = (blob, mimeType, name) => {\n return new File([blob], name || \"\", {\n type: mimeType\n });\n};\n/** attempts to detect correct mimeType if none is set, or if an image\n * has an incorrect extension.\n * Note: doesn't handle missing .excalidraw/.excalidrawlib extension */\n\nconst normalizeFile = async file => {\n var _a, _b;\n\n if (!file.type) {\n if ((_a = file === null || file === void 0 ? void 0 : file.name) === null || _a === void 0 ? void 0 : _a.endsWith(\".excalidrawlib\")) {\n file = createFile(await blobToArrayBuffer(file), _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidrawlib, file.name);\n } else if ((_b = file === null || file === void 0 ? void 0 : file.name) === null || _b === void 0 ? void 0 : _b.endsWith(\".excalidraw\")) {\n file = createFile(await blobToArrayBuffer(file), _constants__WEBPACK_IMPORTED_MODULE_1__.MIME_TYPES.excalidraw, file.name);\n } else {\n const buffer = await blobToArrayBuffer(file);\n const mimeType = getActualMimeTypeFromImage(buffer);\n\n if (mimeType) {\n file = createFile(buffer, mimeType, file.name);\n }\n } // when the file is an image, make sure the extension corresponds to the\n // actual mimeType (this is an edge case, but happens sometime)\n\n } else if (isSupportedImageFile(file)) {\n const buffer = await blobToArrayBuffer(file);\n const mimeType = getActualMimeTypeFromImage(buffer);\n\n if (mimeType && mimeType !== file.type) {\n file = createFile(buffer, mimeType, file.name);\n }\n }\n\n return file;\n};\nconst blobToArrayBuffer = blob => {\n if (\"arrayBuffer\" in blob) {\n return blob.arrayBuffer();\n } // Safari\n\n\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = event => {\n var _a;\n\n if (!((_a = event.target) === null || _a === void 0 ? void 0 : _a.result)) {\n return reject(new Error(\"Couldn't convert blob to ArrayBuffer\"));\n }\n\n resolve(event.target.result);\n };\n\n reader.readAsArrayBuffer(blob);\n });\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./data/blob.ts?");
2633
2633
 
2634
2634
  /***/ }),
2635
2635
 
@@ -2640,7 +2640,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2640
2640
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2641
2641
 
2642
2642
  "use strict";
2643
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64ToArrayBuffer\": () => (/* binding */ base64ToArrayBuffer),\n/* harmony export */ \"base64ToString\": () => (/* binding */ base64ToString),\n/* harmony export */ \"compressData\": () => (/* binding */ compressData),\n/* harmony export */ \"decode\": () => (/* binding */ decode),\n/* harmony export */ \"decompressData\": () => (/* binding */ decompressData),\n/* harmony export */ \"encode\": () => (/* binding */ encode),\n/* harmony export */ \"stringToBase64\": () => (/* binding */ stringToBase64),\n/* harmony export */ \"toByteString\": () => (/* binding */ toByteString)\n/* harmony export */ });\n/* harmony import */ var pako__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! pako */ \"../../node_modules/pako/index.js\");\n/* harmony import */ var pako__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(pako__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _encryption__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./encryption */ \"./data/encryption.ts\");\n\n // -----------------------------------------------------------------------------\n// byte (binary) strings\n// -----------------------------------------------------------------------------\n// fast, Buffer-compatible implem\n\nconst toByteString = data => {\n return new Promise((resolve, reject) => {\n const blob = typeof data === \"string\" ? new Blob([new TextEncoder().encode(data)]) : new Blob([data instanceof Uint8Array ? data : new Uint8Array(data)]);\n const reader = new FileReader();\n\n reader.onload = event => {\n if (!event.target || typeof event.target.result !== \"string\") {\n return reject(new Error(\"couldn't convert to byte string\"));\n }\n\n resolve(event.target.result);\n };\n\n reader.readAsBinaryString(blob);\n });\n};\n\nconst byteStringToArrayBuffer = byteString => {\n const buffer = new ArrayBuffer(byteString.length);\n const bufferView = new Uint8Array(buffer);\n\n for (let i = 0, len = byteString.length; i < len; i++) {\n bufferView[i] = byteString.charCodeAt(i);\n }\n\n return buffer;\n};\n\nconst byteStringToString = byteString => {\n return new TextDecoder(\"utf-8\").decode(byteStringToArrayBuffer(byteString));\n}; // -----------------------------------------------------------------------------\n// base64\n// -----------------------------------------------------------------------------\n\n/**\n * @param isByteString set to true if already byte string to prevent bloat\n * due to reencoding\n */\n\n\nconst stringToBase64 = async (str, isByteString = false) => {\n return isByteString ? window.btoa(str) : window.btoa(await toByteString(str));\n}; // async to align with stringToBase64\n\nconst base64ToString = async (base64, isByteString = false) => {\n return isByteString ? window.atob(base64) : byteStringToString(window.atob(base64));\n};\nconst base64ToArrayBuffer = base64 => {\n if (typeof Buffer !== \"undefined\") {\n // Node.js environment\n return Buffer.from(base64, \"base64\").buffer;\n } // Browser environment\n\n\n return byteStringToArrayBuffer(atob(base64));\n};\n/**\n * Encodes (and potentially compresses via zlib) text to byte string\n */\n\nconst encode = async ({\n text,\n compress\n}) => {\n let deflated;\n\n if (compress !== false) {\n try {\n deflated = await toByteString((0,pako__WEBPACK_IMPORTED_MODULE_0__.deflate)(text));\n } catch (error) {\n console.error(\"encode: cannot deflate\", error);\n }\n }\n\n return {\n version: \"1\",\n encoding: \"bstring\",\n compressed: !!deflated,\n encoded: deflated || (await toByteString(text))\n };\n};\nconst decode = async data => {\n let decoded;\n\n switch (data.encoding) {\n case \"bstring\":\n // if compressed, do not double decode the bstring\n decoded = data.compressed ? data.encoded : await byteStringToString(data.encoded);\n break;\n\n default:\n throw new Error(`decode: unknown encoding \"${data.encoding}\"`);\n }\n\n if (data.compressed) {\n return (0,pako__WEBPACK_IMPORTED_MODULE_0__.inflate)(new Uint8Array(byteStringToArrayBuffer(decoded)), {\n to: \"string\"\n });\n }\n\n return decoded;\n}; // -----------------------------------------------------------------------------\n\nconst CONCAT_BUFFERS_VERSION = 1;\n/** how many bytes we use to encode how many bytes the next chunk has.\n * Corresponds to DataView setter methods (setUint32, setUint16, etc).\n *\n * NOTE ! values must not be changed, which would be backwards incompatible !\n */\n\nconst VERSION_DATAVIEW_BYTES = 4;\nconst NEXT_CHUNK_SIZE_DATAVIEW_BYTES = 4; // -----------------------------------------------------------------------------\n\nconst DATA_VIEW_BITS_MAP = {\n 1: 8,\n 2: 16,\n 4: 32\n};\n/**\n * abstraction over DataView that serves as a typed getter/setter in case\n * you're using constants for the byte size and want to ensure there's no\n * discrepenancy in the encoding across refactors.\n *\n * DataView serves for an endian-agnostic handling of numbers in ArrayBuffers.\n */\n\nfunction dataView(buffer, bytes, offset, value) {\n if (value != null) {\n if (value > Math.pow(2, DATA_VIEW_BITS_MAP[bytes]) - 1) {\n throw new Error(`attempting to set value higher than the allocated bytes (value: ${value}, bytes: ${bytes})`);\n }\n\n const method = `setUint${DATA_VIEW_BITS_MAP[bytes]}`;\n new DataView(buffer.buffer)[method](offset, value);\n return buffer;\n }\n\n const method = `getUint${DATA_VIEW_BITS_MAP[bytes]}`;\n return new DataView(buffer.buffer)[method](offset);\n} // -----------------------------------------------------------------------------\n\n/**\n * Resulting concatenated buffer has this format:\n *\n * [\n * VERSION chunk (4 bytes)\n * LENGTH chunk 1 (4 bytes)\n * DATA chunk 1 (up to 2^32 bits)\n * LENGTH chunk 2 (4 bytes)\n * DATA chunk 2 (up to 2^32 bits)\n * ...\n * ]\n *\n * @param buffers each buffer (chunk) must be at most 2^32 bits large (~4GB)\n */\n\n\nconst concatBuffers = (...buffers) => {\n const bufferView = new Uint8Array(VERSION_DATAVIEW_BYTES + NEXT_CHUNK_SIZE_DATAVIEW_BYTES * buffers.length + buffers.reduce((acc, buffer) => acc + buffer.byteLength, 0));\n let cursor = 0; // as the first chunk we'll encode the version for backwards compatibility\n\n dataView(bufferView, VERSION_DATAVIEW_BYTES, cursor, CONCAT_BUFFERS_VERSION);\n cursor += VERSION_DATAVIEW_BYTES;\n\n for (const buffer of buffers) {\n dataView(bufferView, NEXT_CHUNK_SIZE_DATAVIEW_BYTES, cursor, buffer.byteLength);\n cursor += NEXT_CHUNK_SIZE_DATAVIEW_BYTES;\n bufferView.set(buffer, cursor);\n cursor += buffer.byteLength;\n }\n\n return bufferView;\n};\n/** can only be used on buffers created via `concatBuffers()` */\n\n\nconst splitBuffers = concatenatedBuffer => {\n const buffers = [];\n let cursor = 0; // first chunk is the version\n\n const version = dataView(concatenatedBuffer, NEXT_CHUNK_SIZE_DATAVIEW_BYTES, cursor); // If version is outside of the supported versions, throw an error.\n // This usually means the buffer wasn't encoded using this API, so we'd only\n // waste compute.\n\n if (version > CONCAT_BUFFERS_VERSION) {\n throw new Error(`invalid version ${version}`);\n }\n\n cursor += VERSION_DATAVIEW_BYTES;\n\n while (true) {\n const chunkSize = dataView(concatenatedBuffer, NEXT_CHUNK_SIZE_DATAVIEW_BYTES, cursor);\n cursor += NEXT_CHUNK_SIZE_DATAVIEW_BYTES;\n buffers.push(concatenatedBuffer.slice(cursor, cursor + chunkSize));\n cursor += chunkSize;\n\n if (cursor >= concatenatedBuffer.byteLength) {\n break;\n }\n }\n\n return buffers;\n}; // helpers for (de)compressing data with JSON metadata including encryption\n// -----------------------------------------------------------------------------\n\n/** @private */\n\n\nconst _encryptAndCompress = async (data, encryptionKey) => {\n const {\n encryptedBuffer,\n iv\n } = await (0,_encryption__WEBPACK_IMPORTED_MODULE_1__.encryptData)(encryptionKey, (0,pako__WEBPACK_IMPORTED_MODULE_0__.deflate)(data));\n return {\n iv,\n buffer: new Uint8Array(encryptedBuffer)\n };\n};\n/**\n * The returned buffer has following format:\n * `[]` refers to a buffers wrapper (see `concatBuffers`)\n *\n * [\n * encodingMetadataBuffer,\n * iv,\n * [\n * contentsMetadataBuffer\n * contentsBuffer\n * ]\n * ]\n */\n\n\nconst compressData = async (dataBuffer, options) => {\n const fileInfo = {\n version: 2,\n compression: \"pako@1\",\n encryption: \"AES-GCM\"\n };\n const encodingMetadataBuffer = new TextEncoder().encode(JSON.stringify(fileInfo));\n const contentsMetadataBuffer = new TextEncoder().encode(JSON.stringify(options.metadata || null));\n const {\n iv,\n buffer\n } = await _encryptAndCompress(concatBuffers(contentsMetadataBuffer, dataBuffer), options.encryptionKey);\n return concatBuffers(encodingMetadataBuffer, iv, buffer);\n};\n/** @private */\n\nconst _decryptAndDecompress = async (iv, decryptedBuffer, decryptionKey, isCompressed) => {\n decryptedBuffer = new Uint8Array(await (0,_encryption__WEBPACK_IMPORTED_MODULE_1__.decryptData)(iv, decryptedBuffer, decryptionKey));\n\n if (isCompressed) {\n return (0,pako__WEBPACK_IMPORTED_MODULE_0__.inflate)(decryptedBuffer);\n }\n\n return decryptedBuffer;\n};\n\nconst decompressData = async (bufferView, options) => {\n // first chunk is encoding metadata (ignored for now)\n const [encodingMetadataBuffer, iv, buffer] = splitBuffers(bufferView);\n const encodingMetadata = JSON.parse(new TextDecoder().decode(encodingMetadataBuffer));\n\n try {\n const [contentsMetadataBuffer, contentsBuffer] = splitBuffers(await _decryptAndDecompress(iv, buffer, options.decryptionKey, !!encodingMetadata.compression));\n const metadata = JSON.parse(new TextDecoder().decode(contentsMetadataBuffer));\n return {\n /** metadata source is always JSON so we can decode it here */\n metadata,\n\n /** data can be anything so the caller must decode it */\n data: contentsBuffer\n };\n } catch (error) {\n console.error(`Error during decompressing and decrypting the file.`, encodingMetadata);\n throw error;\n }\n}; // -----------------------------------------------------------------------------\n\n//# sourceURL=webpack://ExcalidrawLib/./data/encode.ts?");
2643
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64ToArrayBuffer\": () => (/* binding */ base64ToArrayBuffer),\n/* harmony export */ \"base64ToString\": () => (/* binding */ base64ToString),\n/* harmony export */ \"compressData\": () => (/* binding */ compressData),\n/* harmony export */ \"decode\": () => (/* binding */ decode),\n/* harmony export */ \"decompressData\": () => (/* binding */ decompressData),\n/* harmony export */ \"encode\": () => (/* binding */ encode),\n/* harmony export */ \"stringToBase64\": () => (/* binding */ stringToBase64),\n/* harmony export */ \"toByteString\": () => (/* binding */ toByteString)\n/* harmony export */ });\n/* harmony import */ var pako__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! pako */ \"../../node_modules/pako/index.js\");\n/* harmony import */ var pako__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(pako__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _encryption__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./encryption */ \"./data/encryption.ts\");\n\n // -----------------------------------------------------------------------------\n// byte (binary) strings\n// -----------------------------------------------------------------------------\n// Buffer-compatible implem.\n//\n// Note that in V8, spreading the uint8array (by chunks) into\n// `String.fromCharCode(...uint8array)` tends to be faster for large\n// strings/buffers, in case perf is needed in the future.\n\nconst toByteString = data => {\n const bytes = typeof data === \"string\" ? new TextEncoder().encode(data) : data instanceof Uint8Array ? data : new Uint8Array(data);\n let bstring = \"\";\n\n for (const byte of bytes) {\n bstring += String.fromCharCode(byte);\n }\n\n return bstring;\n};\n\nconst byteStringToArrayBuffer = byteString => {\n const buffer = new ArrayBuffer(byteString.length);\n const bufferView = new Uint8Array(buffer);\n\n for (let i = 0, len = byteString.length; i < len; i++) {\n bufferView[i] = byteString.charCodeAt(i);\n }\n\n return buffer;\n};\n\nconst byteStringToString = byteString => {\n return new TextDecoder(\"utf-8\").decode(byteStringToArrayBuffer(byteString));\n}; // -----------------------------------------------------------------------------\n// base64\n// -----------------------------------------------------------------------------\n\n/**\n * @param isByteString set to true if already byte string to prevent bloat\n * due to reencoding\n */\n\n\nconst stringToBase64 = (str, isByteString = false) => {\n return isByteString ? window.btoa(str) : window.btoa(toByteString(str));\n}; // async to align with stringToBase64\n\nconst base64ToString = (base64, isByteString = false) => {\n return isByteString ? window.atob(base64) : byteStringToString(window.atob(base64));\n};\nconst base64ToArrayBuffer = base64 => {\n if (typeof Buffer !== \"undefined\") {\n // Node.js environment\n return Buffer.from(base64, \"base64\").buffer;\n } // Browser environment\n\n\n return byteStringToArrayBuffer(atob(base64));\n};\n/**\n * Encodes (and potentially compresses via zlib) text to byte string\n */\n\nconst encode = ({\n text,\n compress\n}) => {\n let deflated;\n\n if (compress !== false) {\n try {\n deflated = toByteString((0,pako__WEBPACK_IMPORTED_MODULE_0__.deflate)(text));\n } catch (error) {\n console.error(\"encode: cannot deflate\", error);\n }\n }\n\n return {\n version: \"1\",\n encoding: \"bstring\",\n compressed: !!deflated,\n encoded: deflated || toByteString(text)\n };\n};\nconst decode = data => {\n let decoded;\n\n switch (data.encoding) {\n case \"bstring\":\n // if compressed, do not double decode the bstring\n decoded = data.compressed ? data.encoded : byteStringToString(data.encoded);\n break;\n\n default:\n throw new Error(`decode: unknown encoding \"${data.encoding}\"`);\n }\n\n if (data.compressed) {\n return (0,pako__WEBPACK_IMPORTED_MODULE_0__.inflate)(new Uint8Array(byteStringToArrayBuffer(decoded)), {\n to: \"string\"\n });\n }\n\n return decoded;\n}; // -----------------------------------------------------------------------------\n\nconst CONCAT_BUFFERS_VERSION = 1;\n/** how many bytes we use to encode how many bytes the next chunk has.\n * Corresponds to DataView setter methods (setUint32, setUint16, etc).\n *\n * NOTE ! values must not be changed, which would be backwards incompatible !\n */\n\nconst VERSION_DATAVIEW_BYTES = 4;\nconst NEXT_CHUNK_SIZE_DATAVIEW_BYTES = 4; // -----------------------------------------------------------------------------\n\nconst DATA_VIEW_BITS_MAP = {\n 1: 8,\n 2: 16,\n 4: 32\n};\n/**\n * abstraction over DataView that serves as a typed getter/setter in case\n * you're using constants for the byte size and want to ensure there's no\n * discrepenancy in the encoding across refactors.\n *\n * DataView serves for an endian-agnostic handling of numbers in ArrayBuffers.\n */\n\nfunction dataView(buffer, bytes, offset, value) {\n if (value != null) {\n if (value > Math.pow(2, DATA_VIEW_BITS_MAP[bytes]) - 1) {\n throw new Error(`attempting to set value higher than the allocated bytes (value: ${value}, bytes: ${bytes})`);\n }\n\n const method = `setUint${DATA_VIEW_BITS_MAP[bytes]}`;\n new DataView(buffer.buffer)[method](offset, value);\n return buffer;\n }\n\n const method = `getUint${DATA_VIEW_BITS_MAP[bytes]}`;\n return new DataView(buffer.buffer)[method](offset);\n} // -----------------------------------------------------------------------------\n\n/**\n * Resulting concatenated buffer has this format:\n *\n * [\n * VERSION chunk (4 bytes)\n * LENGTH chunk 1 (4 bytes)\n * DATA chunk 1 (up to 2^32 bits)\n * LENGTH chunk 2 (4 bytes)\n * DATA chunk 2 (up to 2^32 bits)\n * ...\n * ]\n *\n * @param buffers each buffer (chunk) must be at most 2^32 bits large (~4GB)\n */\n\n\nconst concatBuffers = (...buffers) => {\n const bufferView = new Uint8Array(VERSION_DATAVIEW_BYTES + NEXT_CHUNK_SIZE_DATAVIEW_BYTES * buffers.length + buffers.reduce((acc, buffer) => acc + buffer.byteLength, 0));\n let cursor = 0; // as the first chunk we'll encode the version for backwards compatibility\n\n dataView(bufferView, VERSION_DATAVIEW_BYTES, cursor, CONCAT_BUFFERS_VERSION);\n cursor += VERSION_DATAVIEW_BYTES;\n\n for (const buffer of buffers) {\n dataView(bufferView, NEXT_CHUNK_SIZE_DATAVIEW_BYTES, cursor, buffer.byteLength);\n cursor += NEXT_CHUNK_SIZE_DATAVIEW_BYTES;\n bufferView.set(buffer, cursor);\n cursor += buffer.byteLength;\n }\n\n return bufferView;\n};\n/** can only be used on buffers created via `concatBuffers()` */\n\n\nconst splitBuffers = concatenatedBuffer => {\n const buffers = [];\n let cursor = 0; // first chunk is the version\n\n const version = dataView(concatenatedBuffer, NEXT_CHUNK_SIZE_DATAVIEW_BYTES, cursor); // If version is outside of the supported versions, throw an error.\n // This usually means the buffer wasn't encoded using this API, so we'd only\n // waste compute.\n\n if (version > CONCAT_BUFFERS_VERSION) {\n throw new Error(`invalid version ${version}`);\n }\n\n cursor += VERSION_DATAVIEW_BYTES;\n\n while (true) {\n const chunkSize = dataView(concatenatedBuffer, NEXT_CHUNK_SIZE_DATAVIEW_BYTES, cursor);\n cursor += NEXT_CHUNK_SIZE_DATAVIEW_BYTES;\n buffers.push(concatenatedBuffer.slice(cursor, cursor + chunkSize));\n cursor += chunkSize;\n\n if (cursor >= concatenatedBuffer.byteLength) {\n break;\n }\n }\n\n return buffers;\n}; // helpers for (de)compressing data with JSON metadata including encryption\n// -----------------------------------------------------------------------------\n\n/** @private */\n\n\nconst _encryptAndCompress = async (data, encryptionKey) => {\n const {\n encryptedBuffer,\n iv\n } = await (0,_encryption__WEBPACK_IMPORTED_MODULE_1__.encryptData)(encryptionKey, (0,pako__WEBPACK_IMPORTED_MODULE_0__.deflate)(data));\n return {\n iv,\n buffer: new Uint8Array(encryptedBuffer)\n };\n};\n/**\n * The returned buffer has following format:\n * `[]` refers to a buffers wrapper (see `concatBuffers`)\n *\n * [\n * encodingMetadataBuffer,\n * iv,\n * [\n * contentsMetadataBuffer\n * contentsBuffer\n * ]\n * ]\n */\n\n\nconst compressData = async (dataBuffer, options) => {\n const fileInfo = {\n version: 2,\n compression: \"pako@1\",\n encryption: \"AES-GCM\"\n };\n const encodingMetadataBuffer = new TextEncoder().encode(JSON.stringify(fileInfo));\n const contentsMetadataBuffer = new TextEncoder().encode(JSON.stringify(options.metadata || null));\n const {\n iv,\n buffer\n } = await _encryptAndCompress(concatBuffers(contentsMetadataBuffer, dataBuffer), options.encryptionKey);\n return concatBuffers(encodingMetadataBuffer, iv, buffer);\n};\n/** @private */\n\nconst _decryptAndDecompress = async (iv, decryptedBuffer, decryptionKey, isCompressed) => {\n decryptedBuffer = new Uint8Array(await (0,_encryption__WEBPACK_IMPORTED_MODULE_1__.decryptData)(iv, decryptedBuffer, decryptionKey));\n\n if (isCompressed) {\n return (0,pako__WEBPACK_IMPORTED_MODULE_0__.inflate)(decryptedBuffer);\n }\n\n return decryptedBuffer;\n};\n\nconst decompressData = async (bufferView, options) => {\n // first chunk is encoding metadata (ignored for now)\n const [encodingMetadataBuffer, iv, buffer] = splitBuffers(bufferView);\n const encodingMetadata = JSON.parse(new TextDecoder().decode(encodingMetadataBuffer));\n\n try {\n const [contentsMetadataBuffer, contentsBuffer] = splitBuffers(await _decryptAndDecompress(iv, buffer, options.decryptionKey, !!encodingMetadata.compression));\n const metadata = JSON.parse(new TextDecoder().decode(contentsMetadataBuffer));\n return {\n /** metadata source is always JSON so we can decode it here */\n metadata,\n\n /** data can be anything so the caller must decode it */\n data: contentsBuffer\n };\n } catch (error) {\n console.error(`Error during decompressing and decrypting the file.`, encodingMetadata);\n throw error;\n }\n}; // -----------------------------------------------------------------------------\n\n//# sourceURL=webpack://ExcalidrawLib/./data/encode.ts?");
2644
2644
 
2645
2645
  /***/ }),
2646
2646
 
@@ -2673,7 +2673,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2673
2673
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2674
2674
 
2675
2675
  "use strict";
2676
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"decodePngMetadata\": () => (/* binding */ decodePngMetadata),\n/* harmony export */ \"decodeSvgMetadata\": () => (/* binding */ decodeSvgMetadata),\n/* harmony export */ \"encodePngMetadata\": () => (/* binding */ encodePngMetadata),\n/* harmony export */ \"encodeSvgMetadata\": () => (/* binding */ encodeSvgMetadata),\n/* harmony export */ \"getTEXtChunk\": () => (/* binding */ getTEXtChunk)\n/* harmony export */ });\n/* harmony import */ var png_chunks_extract__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! png-chunks-extract */ \"../../node_modules/png-chunks-extract/index.js\");\n/* harmony import */ var png_chunks_extract__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(png_chunks_extract__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var png_chunk_text__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! png-chunk-text */ \"../../node_modules/png-chunk-text/index.js\");\n/* harmony import */ var png_chunks_encode__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! png-chunks-encode */ \"../../node_modules/png-chunks-encode/index.js\");\n/* harmony import */ var png_chunks_encode__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(png_chunks_encode__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _encode__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./encode */ \"./data/encode.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _blob__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./blob */ \"./data/blob.ts\");\n\n\n\n\n\n // -----------------------------------------------------------------------------\n// PNG\n// -----------------------------------------------------------------------------\n\nconst getTEXtChunk = async blob => {\n const chunks = png_chunks_extract__WEBPACK_IMPORTED_MODULE_0___default()(new Uint8Array(await (0,_blob__WEBPACK_IMPORTED_MODULE_5__.blobToArrayBuffer)(blob)));\n const metadataChunk = chunks.find(chunk => chunk.name === \"tEXt\");\n\n if (metadataChunk) {\n return png_chunk_text__WEBPACK_IMPORTED_MODULE_1__.decode(metadataChunk.data);\n }\n\n return null;\n};\nconst encodePngMetadata = async ({\n blob,\n metadata\n}) => {\n const chunks = png_chunks_extract__WEBPACK_IMPORTED_MODULE_0___default()(new Uint8Array(await (0,_blob__WEBPACK_IMPORTED_MODULE_5__.blobToArrayBuffer)(blob)));\n const metadataChunk = png_chunk_text__WEBPACK_IMPORTED_MODULE_1__.encode(_constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw, JSON.stringify(await (0,_encode__WEBPACK_IMPORTED_MODULE_3__.encode)({\n text: metadata,\n compress: true\n }))); // insert metadata before last chunk (iEND)\n\n chunks.splice(-1, 0, metadataChunk);\n return new Blob([png_chunks_encode__WEBPACK_IMPORTED_MODULE_2___default()(chunks)], {\n type: _constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.png\n });\n};\nconst decodePngMetadata = async blob => {\n const metadata = await getTEXtChunk(blob);\n\n if ((metadata === null || metadata === void 0 ? void 0 : metadata.keyword) === _constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw) {\n try {\n const encodedData = JSON.parse(metadata.text);\n\n if (!(\"encoded\" in encodedData)) {\n // legacy, un-encoded scene JSON\n if (\"type\" in encodedData && encodedData.type === _constants__WEBPACK_IMPORTED_MODULE_4__.EXPORT_DATA_TYPES.excalidraw) {\n return metadata.text;\n }\n\n throw new Error(\"FAILED\");\n }\n\n return await (0,_encode__WEBPACK_IMPORTED_MODULE_3__.decode)(encodedData);\n } catch (error) {\n console.error(error);\n throw new Error(\"FAILED\");\n }\n }\n\n throw new Error(\"INVALID\");\n}; // -----------------------------------------------------------------------------\n// SVG\n// -----------------------------------------------------------------------------\n\nconst encodeSvgMetadata = async ({\n text\n}) => {\n const base64 = await (0,_encode__WEBPACK_IMPORTED_MODULE_3__.stringToBase64)(JSON.stringify(await (0,_encode__WEBPACK_IMPORTED_MODULE_3__.encode)({\n text\n })), true\n /* is already byte string */\n );\n let metadata = \"\";\n metadata += `<!-- payload-type:${_constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw} -->`;\n metadata += `<!-- payload-version:2 -->`;\n metadata += \"<!-- payload-start -->\";\n metadata += base64;\n metadata += \"<!-- payload-end -->\";\n return metadata;\n};\nconst decodeSvgMetadata = async ({\n svg\n}) => {\n if (svg.includes(`payload-type:${_constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw}`)) {\n const match = svg.match(/<!-- payload-start -->\\s*(.+?)\\s*<!-- payload-end -->/);\n\n if (!match) {\n throw new Error(\"INVALID\");\n }\n\n const versionMatch = svg.match(/<!-- payload-version:(\\d+) -->/);\n const version = (versionMatch === null || versionMatch === void 0 ? void 0 : versionMatch[1]) || \"1\";\n const isByteString = version !== \"1\";\n\n try {\n const json = await (0,_encode__WEBPACK_IMPORTED_MODULE_3__.base64ToString)(match[1], isByteString);\n const encodedData = JSON.parse(json);\n\n if (!(\"encoded\" in encodedData)) {\n // legacy, un-encoded scene JSON\n if (\"type\" in encodedData && encodedData.type === _constants__WEBPACK_IMPORTED_MODULE_4__.EXPORT_DATA_TYPES.excalidraw) {\n return json;\n }\n\n throw new Error(\"FAILED\");\n }\n\n return await (0,_encode__WEBPACK_IMPORTED_MODULE_3__.decode)(encodedData);\n } catch (error) {\n console.error(error);\n throw new Error(\"FAILED\");\n }\n }\n\n throw new Error(\"INVALID\");\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./data/image.ts?");
2676
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"decodePngMetadata\": () => (/* binding */ decodePngMetadata),\n/* harmony export */ \"decodeSvgMetadata\": () => (/* binding */ decodeSvgMetadata),\n/* harmony export */ \"encodePngMetadata\": () => (/* binding */ encodePngMetadata),\n/* harmony export */ \"encodeSvgMetadata\": () => (/* binding */ encodeSvgMetadata),\n/* harmony export */ \"getTEXtChunk\": () => (/* binding */ getTEXtChunk)\n/* harmony export */ });\n/* harmony import */ var png_chunks_extract__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! png-chunks-extract */ \"../../node_modules/png-chunks-extract/index.js\");\n/* harmony import */ var png_chunks_extract__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(png_chunks_extract__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var png_chunk_text__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! png-chunk-text */ \"../../node_modules/png-chunk-text/index.js\");\n/* harmony import */ var png_chunks_encode__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! png-chunks-encode */ \"../../node_modules/png-chunks-encode/index.js\");\n/* harmony import */ var png_chunks_encode__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(png_chunks_encode__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _encode__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./encode */ \"./data/encode.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _blob__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./blob */ \"./data/blob.ts\");\n\n\n\n\n\n // -----------------------------------------------------------------------------\n// PNG\n// -----------------------------------------------------------------------------\n\nconst getTEXtChunk = async blob => {\n const chunks = png_chunks_extract__WEBPACK_IMPORTED_MODULE_0___default()(new Uint8Array(await (0,_blob__WEBPACK_IMPORTED_MODULE_5__.blobToArrayBuffer)(blob)));\n const metadataChunk = chunks.find(chunk => chunk.name === \"tEXt\");\n\n if (metadataChunk) {\n return png_chunk_text__WEBPACK_IMPORTED_MODULE_1__.decode(metadataChunk.data);\n }\n\n return null;\n};\nconst encodePngMetadata = async ({\n blob,\n metadata\n}) => {\n const chunks = png_chunks_extract__WEBPACK_IMPORTED_MODULE_0___default()(new Uint8Array(await (0,_blob__WEBPACK_IMPORTED_MODULE_5__.blobToArrayBuffer)(blob)));\n const metadataChunk = png_chunk_text__WEBPACK_IMPORTED_MODULE_1__.encode(_constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw, JSON.stringify((0,_encode__WEBPACK_IMPORTED_MODULE_3__.encode)({\n text: metadata,\n compress: true\n }))); // insert metadata before last chunk (iEND)\n\n chunks.splice(-1, 0, metadataChunk);\n return new Blob([png_chunks_encode__WEBPACK_IMPORTED_MODULE_2___default()(chunks)], {\n type: _constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.png\n });\n};\nconst decodePngMetadata = async blob => {\n const metadata = await getTEXtChunk(blob);\n\n if ((metadata === null || metadata === void 0 ? void 0 : metadata.keyword) === _constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw) {\n try {\n const encodedData = JSON.parse(metadata.text);\n\n if (!(\"encoded\" in encodedData)) {\n // legacy, un-encoded scene JSON\n if (\"type\" in encodedData && encodedData.type === _constants__WEBPACK_IMPORTED_MODULE_4__.EXPORT_DATA_TYPES.excalidraw) {\n return metadata.text;\n }\n\n throw new Error(\"FAILED\");\n }\n\n return (0,_encode__WEBPACK_IMPORTED_MODULE_3__.decode)(encodedData);\n } catch (error) {\n console.error(error);\n throw new Error(\"FAILED\");\n }\n }\n\n throw new Error(\"INVALID\");\n}; // -----------------------------------------------------------------------------\n// SVG\n// -----------------------------------------------------------------------------\n\nconst encodeSvgMetadata = ({\n text\n}) => {\n const base64 = (0,_encode__WEBPACK_IMPORTED_MODULE_3__.stringToBase64)(JSON.stringify((0,_encode__WEBPACK_IMPORTED_MODULE_3__.encode)({\n text\n })), true\n /* is already byte string */\n );\n let metadata = \"\";\n metadata += `<!-- payload-type:${_constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw} -->`;\n metadata += `<!-- payload-version:2 -->`;\n metadata += \"<!-- payload-start -->\";\n metadata += base64;\n metadata += \"<!-- payload-end -->\";\n return metadata;\n};\nconst decodeSvgMetadata = ({\n svg\n}) => {\n if (svg.includes(`payload-type:${_constants__WEBPACK_IMPORTED_MODULE_4__.MIME_TYPES.excalidraw}`)) {\n const match = svg.match(/<!-- payload-start -->\\s*(.+?)\\s*<!-- payload-end -->/);\n\n if (!match) {\n throw new Error(\"INVALID\");\n }\n\n const versionMatch = svg.match(/<!-- payload-version:(\\d+) -->/);\n const version = (versionMatch === null || versionMatch === void 0 ? void 0 : versionMatch[1]) || \"1\";\n const isByteString = version !== \"1\";\n\n try {\n const json = (0,_encode__WEBPACK_IMPORTED_MODULE_3__.base64ToString)(match[1], isByteString);\n const encodedData = JSON.parse(json);\n\n if (!(\"encoded\" in encodedData)) {\n // legacy, un-encoded scene JSON\n if (\"type\" in encodedData && encodedData.type === _constants__WEBPACK_IMPORTED_MODULE_4__.EXPORT_DATA_TYPES.excalidraw) {\n return json;\n }\n\n throw new Error(\"FAILED\");\n }\n\n return (0,_encode__WEBPACK_IMPORTED_MODULE_3__.decode)(encodedData);\n } catch (error) {\n console.error(error);\n throw new Error(\"FAILED\");\n }\n }\n\n throw new Error(\"INVALID\");\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./data/image.ts?");
2677
2677
 
2678
2678
  /***/ }),
2679
2679
 
@@ -2871,7 +2871,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2871
2871
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2872
2872
 
2873
2873
  "use strict";
2874
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"actionSetEmbeddableAsActiveTool\": () => (/* binding */ actionSetEmbeddableAsActiveTool),\n/* harmony export */ \"createPlaceholderEmbeddableLabel\": () => (/* binding */ createPlaceholderEmbeddableLabel),\n/* harmony export */ \"createSrcDoc\": () => (/* binding */ createSrcDoc),\n/* harmony export */ \"embeddableURLValidator\": () => (/* binding */ embeddableURLValidator),\n/* harmony export */ \"getEmbedLink\": () => (/* binding */ getEmbedLink),\n/* harmony export */ \"maybeParseEmbedSrc\": () => (/* binding */ maybeParseEmbedSrc)\n/* harmony export */ });\n/* harmony import */ var _actions_register__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../actions/register */ \"./actions/register.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _cursor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../cursor */ \"./cursor.ts\");\n/* harmony import */ var _newElement__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./newElement */ \"./element/newElement.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _data_url__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../data/url */ \"./data/url.ts\");\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../store */ \"./store.ts\");\n\n\n\n\n\n\n\n\n\nconst embeddedLinkCache = new Map();\nconst RE_YOUTUBE = /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?youtu(?:be\\.com|\\.be)\\/(embed\\/|watch\\?v=|shorts\\/|playlist\\?list=|embed\\/videoseries\\?list=)?([a-zA-Z0-9_-]+)(?:\\?t=|.*&t=|\\?start=|.*&start=)?([a-zA-Z0-9_-]+)?[^\\s]*$/;\nconst RE_VIMEO = /^(?:http(?:s)?:\\/\\/)?(?:(?:w){3}\\.)?(?:player\\.)?vimeo\\.com\\/(?:video\\/)?([^?\\s]+)(?:\\?.*)?$/;\nconst RE_FIGMA = /^https:\\/\\/(?:www\\.)?figma\\.com/;\nconst RE_GH_GIST = /^https:\\/\\/gist\\.github\\.com\\/([\\w_-]+)\\/([\\w_-]+)/;\nconst RE_GH_GIST_EMBED = /^<script[\\s\\S]*?\\ssrc=[\"'](https:\\/\\/gist\\.github\\.com\\/.*?)\\.js[\"']/i; // not anchored to start to allow <blockquote> twitter embeds\n\nconst RE_TWITTER = /(?:https?:\\/\\/)?(?:(?:w){3}\\.)?(?:twitter|x)\\.com\\/[^/]+\\/status\\/(\\d+)/;\nconst RE_TWITTER_EMBED = /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:twitter|x)\\.com\\/[^\"']*)/i;\nconst RE_VALTOWN = /^https:\\/\\/(?:www\\.)?val\\.town\\/(v|embed)\\/[a-zA-Z_$][0-9a-zA-Z_$]+\\.[a-zA-Z_$][0-9a-zA-Z_$]+/;\nconst RE_GENERIC_EMBED = /^<(?:iframe|blockquote)[\\s\\S]*?\\s(?:src|href)=[\"']([^\"']*)[\"'][\\s\\S]*?>$/i;\nconst RE_GIPHY = /giphy.com\\/(?:clips|embed|gifs)\\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;\nconst RE_REDDIT = /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?reddit\\.com\\/r\\/([a-zA-Z0-9_]+)\\/comments\\/([a-zA-Z0-9_]+)\\/([a-zA-Z0-9_]+)\\/?(?:\\?[^#\\s]*)?(?:#[^\\s]*)?$/;\nconst RE_REDDIT_EMBED = /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:www\\.)?reddit\\.com\\/[^\"']*)/i;\nconst ALLOWED_DOMAINS = new Set([\"youtube.com\", \"youtu.be\", \"vimeo.com\", \"player.vimeo.com\", \"figma.com\", \"link.excalidraw.com\", \"gist.github.com\", \"twitter.com\", \"x.com\", \"*.simplepdf.eu\", \"stackblitz.com\", \"val.town\", \"giphy.com\", \"reddit.com\"]);\nconst ALLOW_SAME_ORIGIN = new Set([\"youtube.com\", \"youtu.be\", \"vimeo.com\", \"player.vimeo.com\", \"figma.com\", \"twitter.com\", \"x.com\", \"*.simplepdf.eu\", \"stackblitz.com\", \"reddit.com\"]);\nconst createSrcDoc = body => {\n return `<html><body>${body}</body></html>`;\n};\nconst getEmbedLink = link => {\n if (!link) {\n return null;\n }\n\n const allowSameOrigin = true; //zsviczian I don't worry about same origin in Obsidian\n\n if (link.startsWith(\"data:text/html\")) {\n //zsviczian\n return {\n link,\n intrinsicSize: {\n w: 550,\n h: 720\n },\n type: \"generic\",\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n if (embeddedLinkCache.has(link)) {\n return embeddedLinkCache.get(link);\n }\n\n const originalLink = link;\n /* zsviczian\n const allowSameOrigin = ALLOW_SAME_ORIGIN.has(\n matchHostname(link, ALLOW_SAME_ORIGIN) || \"\",\n );*/\n\n let type = \"generic\";\n let aspectRatio = {\n w: 560,\n h: 840\n };\n const ytLink = link.match(RE_YOUTUBE);\n\n if (ytLink === null || ytLink === void 0 ? void 0 : ytLink[2]) {\n const time = ytLink[3] ? `&start=${ytLink[3]}` : ``;\n const isPortrait = link.includes(\"shorts\");\n type = \"video\";\n\n switch (ytLink[1]) {\n case \"embed/\":\n case \"watch?v=\":\n case \"shorts/\":\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\n break;\n\n case \"playlist?list=\":\n case \"embed/videoseries?list=\":\n link = `https://www.youtube.com/embed/videoseries?list=${ytLink[2]}&enablejsapi=1${time}`;\n break;\n\n default:\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\n break;\n }\n\n aspectRatio = isPortrait ? {\n w: 315,\n h: 560\n } : {\n w: 560,\n h: 315\n };\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n const vimeoLink = link.match(RE_VIMEO);\n\n if (vimeoLink === null || vimeoLink === void 0 ? void 0 : vimeoLink[1]) {\n const target = vimeoLink === null || vimeoLink === void 0 ? void 0 : vimeoLink[1];\n const error = !/^\\d+$/.test(target) ? new URIError(\"Invalid embed link format\") : undefined;\n type = \"video\";\n link = `https://player.vimeo.com/video/${target}?api=1`;\n aspectRatio = {\n w: 560,\n h: 315\n }; //warning deliberately ommited so it is displayed only once per link\n //same link next time will be served from cache\n\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n error,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n const figmaLink = link.match(RE_FIGMA);\n\n if (figmaLink) {\n type = \"generic\";\n link = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(link)}`;\n aspectRatio = {\n w: 550,\n h: 550\n };\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n const valLink = link.match(RE_VALTOWN);\n\n if (valLink) {\n link = valLink[1] === \"embed\" ? valLink[0] : valLink[0].replace(\"/v\", \"/embed\");\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n if (RE_TWITTER.test(link)) {\n const postId = link.match(RE_TWITTER)[1]; // the embed srcdoc still supports twitter.com domain only.\n // Note that we don't attempt to parse the username as it can consist of\n // non-latin1 characters, and the username in the url can be set to anything\n // without affecting the embed.\n\n const safeURL = (0,_data_url__WEBPACK_IMPORTED_MODULE_7__.sanitizeHTMLAttribute)(`https://twitter.com/x/status/${postId}`);\n const ret = {\n type: \"document\",\n srcdoc: theme => createSrcDoc(`<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"${theme}\"><a href=\"${safeURL}\"></a></blockquote> <script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>`),\n intrinsicSize: {\n w: 480,\n h: 480\n },\n sandbox: {\n allowSameOrigin\n }\n };\n embeddedLinkCache.set(originalLink, ret);\n return ret;\n }\n\n if (RE_REDDIT.test(link)) {\n const [, page, postId, title] = link.match(RE_REDDIT);\n const safeURL = (0,_data_url__WEBPACK_IMPORTED_MODULE_7__.sanitizeHTMLAttribute)(`https://reddit.com/r/${page}/comments/${postId}/${title}`);\n const ret = {\n type: \"document\",\n srcdoc: theme => createSrcDoc(`<blockquote class=\"reddit-embed-bq\" data-embed-theme=\"${theme}\"><a href=\"${safeURL}\"></a><br></blockquote><script async=\"\" src=\"https://embed.reddit.com/widgets.js\" charset=\"UTF-8\"></script>`),\n intrinsicSize: {\n w: 480,\n h: 480\n },\n sandbox: {\n allowSameOrigin\n }\n };\n embeddedLinkCache.set(originalLink, ret);\n return ret;\n }\n\n if (RE_GH_GIST.test(link)) {\n const [, user, gistId] = link.match(RE_GH_GIST);\n const safeURL = (0,_data_url__WEBPACK_IMPORTED_MODULE_7__.sanitizeHTMLAttribute)(`https://gist.github.com/${user}/${gistId}`);\n const ret = {\n type: \"document\",\n srcdoc: () => createSrcDoc(`\n <script src=\"${safeURL}.js\"></script>\n <style type=\"text/css\">\n * { margin: 0px; }\n table, .gist { height: 100%; }\n .gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n </style>\n `),\n intrinsicSize: {\n w: 550,\n h: 720\n },\n sandbox: {\n allowSameOrigin\n }\n };\n embeddedLinkCache.set(link, ret);\n return ret;\n }\n\n embeddedLinkCache.set(link, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n};\nconst createPlaceholderEmbeddableLabel = element => {\n var _a;\n\n let text;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_6__.isIframeElement)(element)) {\n text = \"IFrame element\";\n } else {\n text = !element.link || (element === null || element === void 0 ? void 0 : element.link) === \"\" ? \"Empty Web-Embed\" : element.link;\n }\n\n const fontSize = Math.max(Math.min(element.width / 2, element.width / text.length), element.width / 30);\n const fontFamily = _constants__WEBPACK_IMPORTED_MODULE_1__.FONT_FAMILY.Helvetica;\n const fontString = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getFontString)({\n fontSize,\n fontFamily\n });\n return (0,_newElement__WEBPACK_IMPORTED_MODULE_4__.newTextElement)({\n x: element.x + element.width / 2,\n y: element.y + element.height / 2,\n strokeColor: element.strokeColor !== \"transparent\" ? element.strokeColor : \"black\",\n backgroundColor: \"transparent\",\n fontFamily,\n fontSize,\n text: (0,_textElement__WEBPACK_IMPORTED_MODULE_5__.wrapText)(text, fontString, element.width - 20),\n rawText: text,\n textAlign: \"center\",\n verticalAlign: _constants__WEBPACK_IMPORTED_MODULE_1__.VERTICAL_ALIGN.MIDDLE,\n angle: (_a = element.angle) !== null && _a !== void 0 ? _a : 0\n });\n};\nconst actionSetEmbeddableAsActiveTool = (0,_actions_register__WEBPACK_IMPORTED_MODULE_0__.register)({\n name: \"setEmbeddableAsActiveTool\",\n trackEvent: {\n category: \"toolbar\"\n },\n target: \"Tool\",\n label: \"toolBar.embeddable\",\n perform: (elements, appState, _, app) => {\n const nextActiveTool = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.updateActiveTool)(appState, {\n type: \"embeddable\"\n });\n (0,_cursor__WEBPACK_IMPORTED_MODULE_3__.setCursorForShape)(app.canvas, Object.assign(Object.assign({}, appState), {\n activeTool: nextActiveTool\n }));\n return {\n elements,\n appState: Object.assign(Object.assign({}, appState), {\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_2__.updateActiveTool)(appState, {\n type: \"embeddable\"\n })\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_8__.StoreAction.NONE\n };\n }\n});\n\nconst matchHostname = (url,\n/** using a Set assumes it already contains normalized bare domains */\nallowedHostnames) => {\n try {\n const {\n hostname\n } = new URL(url);\n const bareDomain = hostname.replace(/^www\\./, \"\");\n\n if (allowedHostnames instanceof Set) {\n if (ALLOWED_DOMAINS.has(bareDomain)) {\n return bareDomain;\n }\n\n const bareDomainWithFirstSubdomainWildcarded = bareDomain.replace(/^([^.]+)/, \"*\");\n\n if (ALLOWED_DOMAINS.has(bareDomainWithFirstSubdomainWildcarded)) {\n return bareDomainWithFirstSubdomainWildcarded;\n }\n\n return null;\n }\n\n const bareAllowedHostname = allowedHostnames.replace(/^www\\./, \"\");\n\n if (bareDomain === bareAllowedHostname) {\n return bareAllowedHostname;\n }\n } catch (error) {// ignore\n }\n\n return null;\n};\n\nconst maybeParseEmbedSrc = str => {\n const twitterMatch = str.match(RE_TWITTER_EMBED);\n\n if (twitterMatch && twitterMatch.length === 2) {\n return twitterMatch[1];\n }\n\n const redditMatch = str.match(RE_REDDIT_EMBED);\n\n if (redditMatch && redditMatch.length === 2) {\n return redditMatch[1];\n }\n\n const gistMatch = str.match(RE_GH_GIST_EMBED);\n\n if (gistMatch && gistMatch.length === 2) {\n return gistMatch[1];\n }\n\n if (RE_GIPHY.test(str)) {\n return `https://giphy.com/embed/${RE_GIPHY.exec(str)[1]}`;\n }\n\n const match = str.match(RE_GENERIC_EMBED);\n\n if (match && match.length === 2) {\n return match[1];\n }\n\n return str;\n};\nconst embeddableURLValidator = (url, validateEmbeddable) => {\n if (!url) {\n return false;\n }\n\n if (validateEmbeddable != null) {\n if (typeof validateEmbeddable === \"function\") {\n const ret = validateEmbeddable(url); // if return value is undefined, leave validation to default\n\n if (typeof ret === \"boolean\") {\n return ret;\n }\n } else if (typeof validateEmbeddable === \"boolean\") {\n return validateEmbeddable;\n } else if (validateEmbeddable instanceof RegExp) {\n return validateEmbeddable.test(url);\n } else if (Array.isArray(validateEmbeddable)) {\n for (const domain of validateEmbeddable) {\n if (domain instanceof RegExp) {\n if (url.match(domain)) {\n return true;\n }\n } else if (matchHostname(url, domain)) {\n return true;\n }\n }\n\n return false;\n }\n }\n\n return !!matchHostname(url, ALLOWED_DOMAINS);\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/embeddable.ts?");
2874
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"actionSetEmbeddableAsActiveTool\": () => (/* binding */ actionSetEmbeddableAsActiveTool),\n/* harmony export */ \"createPlaceholderEmbeddableLabel\": () => (/* binding */ createPlaceholderEmbeddableLabel),\n/* harmony export */ \"createSrcDoc\": () => (/* binding */ createSrcDoc),\n/* harmony export */ \"embeddableURLValidator\": () => (/* binding */ embeddableURLValidator),\n/* harmony export */ \"getEmbedLink\": () => (/* binding */ getEmbedLink),\n/* harmony export */ \"maybeParseEmbedSrc\": () => (/* binding */ maybeParseEmbedSrc)\n/* harmony export */ });\n/* harmony import */ var _actions_register__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../actions/register */ \"./actions/register.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _cursor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../cursor */ \"./cursor.ts\");\n/* harmony import */ var _newElement__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./newElement */ \"./element/newElement.ts\");\n/* harmony import */ var _textWrapping__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _data_url__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../data/url */ \"./data/url.ts\");\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../store */ \"./store.ts\");\n\n\n\n\n\n\n\n\n\nconst embeddedLinkCache = new Map();\nconst RE_YOUTUBE = /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?youtu(?:be\\.com|\\.be)\\/(embed\\/|watch\\?v=|shorts\\/|playlist\\?list=|embed\\/videoseries\\?list=)?([a-zA-Z0-9_-]+)(?:\\?t=|.*&t=|\\?start=|.*&start=)?([a-zA-Z0-9_-]+)?[^\\s]*$/;\nconst RE_VIMEO = /^(?:http(?:s)?:\\/\\/)?(?:(?:w){3}\\.)?(?:player\\.)?vimeo\\.com\\/(?:video\\/)?([^?\\s]+)(?:\\?.*)?$/;\nconst RE_FIGMA = /^https:\\/\\/(?:www\\.)?figma\\.com/;\nconst RE_GH_GIST = /^https:\\/\\/gist\\.github\\.com\\/([\\w_-]+)\\/([\\w_-]+)/;\nconst RE_GH_GIST_EMBED = /^<script[\\s\\S]*?\\ssrc=[\"'](https:\\/\\/gist\\.github\\.com\\/.*?)\\.js[\"']/i; // not anchored to start to allow <blockquote> twitter embeds\n\nconst RE_TWITTER = /(?:https?:\\/\\/)?(?:(?:w){3}\\.)?(?:twitter|x)\\.com\\/[^/]+\\/status\\/(\\d+)/;\nconst RE_TWITTER_EMBED = /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:twitter|x)\\.com\\/[^\"']*)/i;\nconst RE_VALTOWN = /^https:\\/\\/(?:www\\.)?val\\.town\\/(v|embed)\\/[a-zA-Z_$][0-9a-zA-Z_$]+\\.[a-zA-Z_$][0-9a-zA-Z_$]+/;\nconst RE_GENERIC_EMBED = /^<(?:iframe|blockquote)[\\s\\S]*?\\s(?:src|href)=[\"']([^\"']*)[\"'][\\s\\S]*?>$/i;\nconst RE_GIPHY = /giphy.com\\/(?:clips|embed|gifs)\\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;\nconst RE_REDDIT = /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?reddit\\.com\\/r\\/([a-zA-Z0-9_]+)\\/comments\\/([a-zA-Z0-9_]+)\\/([a-zA-Z0-9_]+)\\/?(?:\\?[^#\\s]*)?(?:#[^\\s]*)?$/;\nconst RE_REDDIT_EMBED = /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:www\\.)?reddit\\.com\\/[^\"']*)/i;\nconst ALLOWED_DOMAINS = new Set([\"youtube.com\", \"youtu.be\", \"vimeo.com\", \"player.vimeo.com\", \"figma.com\", \"link.excalidraw.com\", \"gist.github.com\", \"twitter.com\", \"x.com\", \"*.simplepdf.eu\", \"stackblitz.com\", \"val.town\", \"giphy.com\", \"reddit.com\"]);\nconst ALLOW_SAME_ORIGIN = new Set([\"youtube.com\", \"youtu.be\", \"vimeo.com\", \"player.vimeo.com\", \"figma.com\", \"twitter.com\", \"x.com\", \"*.simplepdf.eu\", \"stackblitz.com\", \"reddit.com\"]);\nconst createSrcDoc = body => {\n return `<html><body>${body}</body></html>`;\n};\nconst getEmbedLink = link => {\n if (!link) {\n return null;\n }\n\n const allowSameOrigin = true; //zsviczian I don't worry about same origin in Obsidian\n\n if (link.startsWith(\"data:text/html\")) {\n //zsviczian\n return {\n link,\n intrinsicSize: {\n w: 550,\n h: 720\n },\n type: \"generic\",\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n if (embeddedLinkCache.has(link)) {\n return embeddedLinkCache.get(link);\n }\n\n const originalLink = link;\n /* zsviczian\n const allowSameOrigin = ALLOW_SAME_ORIGIN.has(\n matchHostname(link, ALLOW_SAME_ORIGIN) || \"\",\n );*/\n\n let type = \"generic\";\n let aspectRatio = {\n w: 560,\n h: 840\n };\n const ytLink = link.match(RE_YOUTUBE);\n\n if (ytLink === null || ytLink === void 0 ? void 0 : ytLink[2]) {\n const time = ytLink[3] ? `&start=${ytLink[3]}` : ``;\n const isPortrait = link.includes(\"shorts\");\n type = \"video\";\n\n switch (ytLink[1]) {\n case \"embed/\":\n case \"watch?v=\":\n case \"shorts/\":\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\n break;\n\n case \"playlist?list=\":\n case \"embed/videoseries?list=\":\n link = `https://www.youtube.com/embed/videoseries?list=${ytLink[2]}&enablejsapi=1${time}`;\n break;\n\n default:\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\n break;\n }\n\n aspectRatio = isPortrait ? {\n w: 315,\n h: 560\n } : {\n w: 560,\n h: 315\n };\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n const vimeoLink = link.match(RE_VIMEO);\n\n if (vimeoLink === null || vimeoLink === void 0 ? void 0 : vimeoLink[1]) {\n const target = vimeoLink === null || vimeoLink === void 0 ? void 0 : vimeoLink[1];\n const error = !/^\\d+$/.test(target) ? new URIError(\"Invalid embed link format\") : undefined;\n type = \"video\";\n link = `https://player.vimeo.com/video/${target}?api=1`;\n aspectRatio = {\n w: 560,\n h: 315\n }; //warning deliberately ommited so it is displayed only once per link\n //same link next time will be served from cache\n\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n error,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n const figmaLink = link.match(RE_FIGMA);\n\n if (figmaLink) {\n type = \"generic\";\n link = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(link)}`;\n aspectRatio = {\n w: 550,\n h: 550\n };\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n const valLink = link.match(RE_VALTOWN);\n\n if (valLink) {\n link = valLink[1] === \"embed\" ? valLink[0] : valLink[0].replace(\"/v\", \"/embed\");\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n }\n\n if (RE_TWITTER.test(link)) {\n const postId = link.match(RE_TWITTER)[1]; // the embed srcdoc still supports twitter.com domain only.\n // Note that we don't attempt to parse the username as it can consist of\n // non-latin1 characters, and the username in the url can be set to anything\n // without affecting the embed.\n\n const safeURL = (0,_data_url__WEBPACK_IMPORTED_MODULE_7__.sanitizeHTMLAttribute)(`https://twitter.com/x/status/${postId}`);\n const ret = {\n type: \"document\",\n srcdoc: theme => createSrcDoc(`<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"${theme}\"><a href=\"${safeURL}\"></a></blockquote> <script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>`),\n intrinsicSize: {\n w: 480,\n h: 480\n },\n sandbox: {\n allowSameOrigin\n }\n };\n embeddedLinkCache.set(originalLink, ret);\n return ret;\n }\n\n if (RE_REDDIT.test(link)) {\n const [, page, postId, title] = link.match(RE_REDDIT);\n const safeURL = (0,_data_url__WEBPACK_IMPORTED_MODULE_7__.sanitizeHTMLAttribute)(`https://reddit.com/r/${page}/comments/${postId}/${title}`);\n const ret = {\n type: \"document\",\n srcdoc: theme => createSrcDoc(`<blockquote class=\"reddit-embed-bq\" data-embed-theme=\"${theme}\"><a href=\"${safeURL}\"></a><br></blockquote><script async=\"\" src=\"https://embed.reddit.com/widgets.js\" charset=\"UTF-8\"></script>`),\n intrinsicSize: {\n w: 480,\n h: 480\n },\n sandbox: {\n allowSameOrigin\n }\n };\n embeddedLinkCache.set(originalLink, ret);\n return ret;\n }\n\n if (RE_GH_GIST.test(link)) {\n const [, user, gistId] = link.match(RE_GH_GIST);\n const safeURL = (0,_data_url__WEBPACK_IMPORTED_MODULE_7__.sanitizeHTMLAttribute)(`https://gist.github.com/${user}/${gistId}`);\n const ret = {\n type: \"document\",\n srcdoc: () => createSrcDoc(`\n <script src=\"${safeURL}.js\"></script>\n <style type=\"text/css\">\n * { margin: 0px; }\n table, .gist { height: 100%; }\n .gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n </style>\n `),\n intrinsicSize: {\n w: 550,\n h: 720\n },\n sandbox: {\n allowSameOrigin\n }\n };\n embeddedLinkCache.set(link, ret);\n return ret;\n }\n\n embeddedLinkCache.set(link, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: {\n allowSameOrigin\n }\n };\n};\nconst createPlaceholderEmbeddableLabel = element => {\n var _a;\n\n let text;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_6__.isIframeElement)(element)) {\n text = \"IFrame element\";\n } else {\n text = !element.link || (element === null || element === void 0 ? void 0 : element.link) === \"\" ? \"Empty Web-Embed\" : element.link;\n }\n\n const fontSize = Math.max(Math.min(element.width / 2, element.width / text.length), element.width / 30);\n const fontFamily = _constants__WEBPACK_IMPORTED_MODULE_1__.FONT_FAMILY.Helvetica;\n const fontString = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.getFontString)({\n fontSize,\n fontFamily\n });\n return (0,_newElement__WEBPACK_IMPORTED_MODULE_4__.newTextElement)({\n x: element.x + element.width / 2,\n y: element.y + element.height / 2,\n strokeColor: element.strokeColor !== \"transparent\" ? element.strokeColor : \"black\",\n backgroundColor: \"transparent\",\n fontFamily,\n fontSize,\n text: (0,_textWrapping__WEBPACK_IMPORTED_MODULE_5__.wrapText)(text, fontString, element.width - 20),\n rawText: text,\n textAlign: \"center\",\n verticalAlign: _constants__WEBPACK_IMPORTED_MODULE_1__.VERTICAL_ALIGN.MIDDLE,\n angle: (_a = element.angle) !== null && _a !== void 0 ? _a : 0\n });\n};\nconst actionSetEmbeddableAsActiveTool = (0,_actions_register__WEBPACK_IMPORTED_MODULE_0__.register)({\n name: \"setEmbeddableAsActiveTool\",\n trackEvent: {\n category: \"toolbar\"\n },\n target: \"Tool\",\n label: \"toolBar.embeddable\",\n perform: (elements, appState, _, app) => {\n const nextActiveTool = (0,_utils__WEBPACK_IMPORTED_MODULE_2__.updateActiveTool)(appState, {\n type: \"embeddable\"\n });\n (0,_cursor__WEBPACK_IMPORTED_MODULE_3__.setCursorForShape)(app.canvas, Object.assign(Object.assign({}, appState), {\n activeTool: nextActiveTool\n }));\n return {\n elements,\n appState: Object.assign(Object.assign({}, appState), {\n activeTool: (0,_utils__WEBPACK_IMPORTED_MODULE_2__.updateActiveTool)(appState, {\n type: \"embeddable\"\n })\n }),\n storeAction: _store__WEBPACK_IMPORTED_MODULE_8__.StoreAction.NONE\n };\n }\n});\n\nconst matchHostname = (url,\n/** using a Set assumes it already contains normalized bare domains */\nallowedHostnames) => {\n try {\n const {\n hostname\n } = new URL(url);\n const bareDomain = hostname.replace(/^www\\./, \"\");\n\n if (allowedHostnames instanceof Set) {\n if (ALLOWED_DOMAINS.has(bareDomain)) {\n return bareDomain;\n }\n\n const bareDomainWithFirstSubdomainWildcarded = bareDomain.replace(/^([^.]+)/, \"*\");\n\n if (ALLOWED_DOMAINS.has(bareDomainWithFirstSubdomainWildcarded)) {\n return bareDomainWithFirstSubdomainWildcarded;\n }\n\n return null;\n }\n\n const bareAllowedHostname = allowedHostnames.replace(/^www\\./, \"\");\n\n if (bareDomain === bareAllowedHostname) {\n return bareAllowedHostname;\n }\n } catch (error) {// ignore\n }\n\n return null;\n};\n\nconst maybeParseEmbedSrc = str => {\n const twitterMatch = str.match(RE_TWITTER_EMBED);\n\n if (twitterMatch && twitterMatch.length === 2) {\n return twitterMatch[1];\n }\n\n const redditMatch = str.match(RE_REDDIT_EMBED);\n\n if (redditMatch && redditMatch.length === 2) {\n return redditMatch[1];\n }\n\n const gistMatch = str.match(RE_GH_GIST_EMBED);\n\n if (gistMatch && gistMatch.length === 2) {\n return gistMatch[1];\n }\n\n if (RE_GIPHY.test(str)) {\n return `https://giphy.com/embed/${RE_GIPHY.exec(str)[1]}`;\n }\n\n const match = str.match(RE_GENERIC_EMBED);\n\n if (match && match.length === 2) {\n return match[1];\n }\n\n return str;\n};\nconst embeddableURLValidator = (url, validateEmbeddable) => {\n if (!url) {\n return false;\n }\n\n if (validateEmbeddable != null) {\n if (typeof validateEmbeddable === \"function\") {\n const ret = validateEmbeddable(url); // if return value is undefined, leave validation to default\n\n if (typeof ret === \"boolean\") {\n return ret;\n }\n } else if (typeof validateEmbeddable === \"boolean\") {\n return validateEmbeddable;\n } else if (validateEmbeddable instanceof RegExp) {\n return validateEmbeddable.test(url);\n } else if (Array.isArray(validateEmbeddable)) {\n for (const domain of validateEmbeddable) {\n if (domain instanceof RegExp) {\n if (url.match(domain)) {\n return true;\n }\n } else if (matchHostname(url, domain)) {\n return true;\n }\n }\n\n return false;\n }\n }\n\n return !!matchHostname(url, ALLOWED_DOMAINS);\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/embeddable.ts?");
2875
2875
 
2876
2876
  /***/ }),
2877
2877
 
@@ -2904,7 +2904,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2904
2904
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2905
2905
 
2906
2906
  "use strict";
2907
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"getInitializedImageElements\": () => (/* binding */ getInitializedImageElements),\n/* harmony export */ \"isHTMLSVGElement\": () => (/* binding */ isHTMLSVGElement),\n/* harmony export */ \"loadHTMLImageElement\": () => (/* binding */ loadHTMLImageElement),\n/* harmony export */ \"normalizeSVG\": () => (/* binding */ normalizeSVG),\n/* harmony export */ \"updateImageCache\": () => (/* binding */ updateImageCache)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n// -----------------------------------------------------------------------------\n// ExcalidrawImageElement & related helpers\n// -----------------------------------------------------------------------------\n\n\nconst loadHTMLImageElement = dataURL => {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n image.onload = () => {\n resolve(image);\n };\n\n image.onerror = error => {\n reject(error);\n };\n\n image.src = dataURL;\n });\n};\n/** NOTE: updates cache even if already populated with given image. Thus,\n * you should filter out the images upstream if you want to optimize this. */\n\nconst updateImageCache = async ({\n fileIds,\n files,\n imageCache\n}) => {\n const updatedFiles = new Map();\n const erroredFiles = new Map();\n await Promise.all(fileIds.reduce((promises, fileId) => {\n const fileData = files[fileId];\n\n if (fileData && !updatedFiles.has(fileId)) {\n updatedFiles.set(fileId, true);\n return promises.concat((async () => {\n try {\n if (fileData.mimeType === _constants__WEBPACK_IMPORTED_MODULE_0__.MIME_TYPES.binary) {\n throw new Error(\"Only images can be added to ImageCache\");\n }\n\n const imagePromise = loadHTMLImageElement(fileData.dataURL);\n const data = {\n image: imagePromise,\n mimeType: fileData.mimeType\n }; // store the promise immediately to indicate there's an in-progress\n // initialization\n\n imageCache.set(fileId, data);\n const image = await imagePromise;\n imageCache.set(fileId, Object.assign(Object.assign({}, data), {\n image\n }));\n } catch (error) {\n erroredFiles.set(fileId, true);\n }\n })());\n }\n\n return promises;\n }, []));\n return {\n imageCache,\n\n /** includes errored files because they cache was updated nonetheless */\n updatedFiles,\n\n /** files that failed when creating HTMLImageElement */\n erroredFiles\n };\n};\nconst getInitializedImageElements = elements => elements.filter(element => (0,_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isInitializedImageElement)(element));\nconst isHTMLSVGElement = node => {\n // lower-casing due to XML/HTML convention differences\n // https://johnresig.com/blog/nodename-case-sensitivity\n return (node === null || node === void 0 ? void 0 : node.nodeName.toLowerCase()) === \"svg\";\n};\nconst normalizeSVG = async SVGString => {\n const doc = new DOMParser().parseFromString(SVGString, _constants__WEBPACK_IMPORTED_MODULE_0__.MIME_TYPES.svg);\n const svg = doc.querySelector(\"svg\");\n const errorNode = doc.querySelector(\"parsererror\");\n\n if (errorNode || !isHTMLSVGElement(svg)) {\n throw new Error(\"Invalid SVG\");\n } else {\n if (!svg.hasAttribute(\"xmlns\")) {\n svg.setAttribute(\"xmlns\", _constants__WEBPACK_IMPORTED_MODULE_0__.SVG_NS);\n }\n\n if (!svg.hasAttribute(\"width\") || !svg.hasAttribute(\"height\")) {\n const viewBox = svg.getAttribute(\"viewBox\");\n let width = svg.getAttribute(\"width\") || \"50\";\n let height = svg.getAttribute(\"height\") || \"50\";\n\n if (viewBox) {\n const match = viewBox.match(/\\d+ +\\d+ +(\\d+) +(\\d+)/);\n\n if (match) {\n [, width, height] = match;\n }\n }\n\n svg.setAttribute(\"width\", width);\n svg.setAttribute(\"height\", height);\n }\n\n return svg.outerHTML;\n }\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/image.ts?");
2907
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"getInitializedImageElements\": () => (/* binding */ getInitializedImageElements),\n/* harmony export */ \"isHTMLSVGElement\": () => (/* binding */ isHTMLSVGElement),\n/* harmony export */ \"loadHTMLImageElement\": () => (/* binding */ loadHTMLImageElement),\n/* harmony export */ \"normalizeSVG\": () => (/* binding */ normalizeSVG),\n/* harmony export */ \"updateImageCache\": () => (/* binding */ updateImageCache)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n// -----------------------------------------------------------------------------\n// ExcalidrawImageElement & related helpers\n// -----------------------------------------------------------------------------\n\n\nconst loadHTMLImageElement = dataURL => {\n return new Promise((resolve, reject) => {\n const image = new Image();\n\n image.onload = () => {\n resolve(image);\n };\n\n image.onerror = error => {\n reject(error);\n };\n\n image.src = dataURL;\n });\n};\n/** NOTE: updates cache even if already populated with given image. Thus,\n * you should filter out the images upstream if you want to optimize this. */\n\nconst updateImageCache = async ({\n fileIds,\n files,\n imageCache\n}) => {\n const updatedFiles = new Map();\n const erroredFiles = new Map();\n await Promise.all(fileIds.reduce((promises, fileId) => {\n const fileData = files[fileId];\n\n if (fileData && !updatedFiles.has(fileId)) {\n updatedFiles.set(fileId, true);\n return promises.concat((async () => {\n try {\n if (fileData.mimeType === _constants__WEBPACK_IMPORTED_MODULE_0__.MIME_TYPES.binary) {\n throw new Error(\"Only images can be added to ImageCache\");\n }\n\n const imagePromise = loadHTMLImageElement(fileData.dataURL);\n const data = {\n image: imagePromise,\n mimeType: fileData.mimeType\n }; // store the promise immediately to indicate there's an in-progress\n // initialization\n\n imageCache.set(fileId, data);\n const image = await imagePromise;\n imageCache.set(fileId, Object.assign(Object.assign({}, data), {\n image\n }));\n } catch (error) {\n erroredFiles.set(fileId, true);\n }\n })());\n }\n\n return promises;\n }, []));\n return {\n imageCache,\n\n /** includes errored files because they cache was updated nonetheless */\n updatedFiles,\n\n /** files that failed when creating HTMLImageElement */\n erroredFiles\n };\n};\nconst getInitializedImageElements = elements => elements.filter(element => (0,_typeChecks__WEBPACK_IMPORTED_MODULE_1__.isInitializedImageElement)(element));\nconst isHTMLSVGElement = node => {\n // lower-casing due to XML/HTML convention differences\n // https://johnresig.com/blog/nodename-case-sensitivity\n return (node === null || node === void 0 ? void 0 : node.nodeName.toLowerCase()) === \"svg\";\n};\nconst normalizeSVG = SVGString => {\n const doc = new DOMParser().parseFromString(SVGString, _constants__WEBPACK_IMPORTED_MODULE_0__.MIME_TYPES.svg);\n const svg = doc.querySelector(\"svg\");\n const errorNode = doc.querySelector(\"parsererror\");\n\n if (errorNode || !isHTMLSVGElement(svg)) {\n throw new Error(\"Invalid SVG\");\n } else {\n if (!svg.hasAttribute(\"xmlns\")) {\n svg.setAttribute(\"xmlns\", _constants__WEBPACK_IMPORTED_MODULE_0__.SVG_NS);\n }\n\n if (!svg.hasAttribute(\"width\") || !svg.hasAttribute(\"height\")) {\n const viewBox = svg.getAttribute(\"viewBox\");\n let width = svg.getAttribute(\"width\") || \"50\";\n let height = svg.getAttribute(\"height\") || \"50\";\n\n if (viewBox) {\n const match = viewBox.match(/\\d+ +\\d+ +(\\d+) +(\\d+)/);\n\n if (match) {\n [, width, height] = match;\n }\n }\n\n svg.setAttribute(\"width\", width);\n svg.setAttribute(\"height\", height);\n }\n\n return svg.outerHTML;\n }\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/image.ts?");
2908
2908
 
2909
2909
  /***/ }),
2910
2910
 
@@ -2948,7 +2948,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2948
2948
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2949
2949
 
2950
2950
  "use strict";
2951
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"deepCopyElement\": () => (/* binding */ deepCopyElement),\n/* harmony export */ \"duplicateElement\": () => (/* binding */ duplicateElement),\n/* harmony export */ \"duplicateElements\": () => (/* binding */ duplicateElements),\n/* harmony export */ \"newArrowElement\": () => (/* binding */ newArrowElement),\n/* harmony export */ \"newElement\": () => (/* binding */ newElement),\n/* harmony export */ \"newEmbeddableElement\": () => (/* binding */ newEmbeddableElement),\n/* harmony export */ \"newFrameElement\": () => (/* binding */ newFrameElement),\n/* harmony export */ \"newFreeDrawElement\": () => (/* binding */ newFreeDrawElement),\n/* harmony export */ \"newIframeElement\": () => (/* binding */ newIframeElement),\n/* harmony export */ \"newImageElement\": () => (/* binding */ newImageElement),\n/* harmony export */ \"newLinearElement\": () => (/* binding */ newLinearElement),\n/* harmony export */ \"newMagicFrameElement\": () => (/* binding */ newMagicFrameElement),\n/* harmony export */ \"newTextElement\": () => (/* binding */ newTextElement),\n/* harmony export */ \"refreshTextDimensions\": () => (/* binding */ refreshTextDimensions),\n/* harmony export */ \"regenerateId\": () => (/* binding */ regenerateId)\n/* harmony export */ });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _random__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../random */ \"./random.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../groups */ \"./groups.ts\");\n/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! . */ \"./element/index.ts\");\n/* harmony import */ var _bounds__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _fonts__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../fonts */ \"./fonts/index.ts\");\nvar __rest = undefined && undefined.__rest || function (s, e) {\n var t = {};\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n};\n\n\n\n\n\n\n\n\n\n\n\nconst _newElementBase = (type, _a) => {\n var _b, _c;\n\n var {\n x,\n y,\n strokeColor = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.strokeColor,\n backgroundColor = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.backgroundColor,\n fillStyle = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.fillStyle,\n strokeWidth = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.strokeWidth,\n strokeStyle = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.strokeStyle,\n roughness = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.roughness,\n opacity = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.opacity,\n width = 0,\n height = 0,\n angle = 0,\n groupIds = [],\n frameId = null,\n index = null,\n roundness = null,\n boundElements = null,\n link = null,\n locked = _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_ELEMENT_PROPS.locked\n } = _a,\n rest = __rest(_a, [\"x\", \"y\", \"strokeColor\", \"backgroundColor\", \"fillStyle\", \"strokeWidth\", \"strokeStyle\", \"roughness\", \"opacity\", \"width\", \"height\", \"angle\", \"groupIds\", \"frameId\", \"index\", \"roundness\", \"boundElements\", \"link\", \"locked\"]); // assign type to guard against excess properties\n\n\n const element = {\n id: rest.id || (type === \"text\" ? (0,_random__WEBPACK_IMPORTED_MODULE_1__.obsidianId)() : (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomId)()),\n type,\n x,\n y,\n width,\n height,\n angle,\n strokeColor,\n backgroundColor,\n fillStyle,\n strokeWidth,\n strokeStyle,\n roughness,\n opacity,\n groupIds,\n frameId,\n index,\n roundness,\n seed: (_b = rest.seed) !== null && _b !== void 0 ? _b : (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomInteger)(),\n version: rest.version || 1,\n versionNonce: (_c = rest.versionNonce) !== null && _c !== void 0 ? _c : 0,\n isDeleted: false,\n boundElements,\n updated: (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getUpdatedTimestamp)(),\n link,\n locked,\n //...(rest.customData ? { customData: rest.customData } : {}), //zsviczian\n customData: rest.customData\n };\n return element;\n};\n\nconst newElement = opts => _newElementBase(opts.type, opts);\nconst newEmbeddableElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(\"embeddable\", opts)), {\n scale: [1, 1]\n });\n};\nconst newIframeElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(\"iframe\", opts)), {\n scale: [1, 1]\n });\n};\nconst newFrameElement = opts => {\n const frameElement = (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.newElementWith)(Object.assign(Object.assign({}, _newElementBase(\"frame\", opts)), {\n type: \"frame\",\n name: (opts === null || opts === void 0 ? void 0 : opts.name) || null\n }), {});\n return frameElement;\n};\nconst newMagicFrameElement = opts => {\n const frameElement = (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.newElementWith)(Object.assign(Object.assign({}, _newElementBase(\"magicframe\", opts)), {\n type: \"magicframe\",\n name: (opts === null || opts === void 0 ? void 0 : opts.name) || null\n }), {});\n return frameElement;\n};\n/** computes element x/y offset based on textAlign/verticalAlign */\n\nconst getTextElementPositionOffsets = (opts, metrics) => {\n return {\n x: opts.textAlign === \"center\" ? metrics.width / 2 : opts.textAlign === \"right\" ? metrics.width : 0,\n y: opts.verticalAlign === \"middle\" ? metrics.height / 2 : 0\n };\n};\n\nconst newTextElement = opts => {\n var _a, _b;\n\n const fontFamily = opts.fontFamily || _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_FONT_FAMILY;\n const fontSize = opts.fontSize || _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_FONT_SIZE;\n const lineHeight = opts.lineHeight || (0,_fonts__WEBPACK_IMPORTED_MODULE_8__.getLineHeight)(fontFamily);\n const text = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(opts.text);\n const rawText = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(opts.rawText); //zsviczian\n\n const metrics = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.measureText)(text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)({\n fontFamily,\n fontSize\n }), lineHeight);\n const textAlign = opts.textAlign || _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_TEXT_ALIGN;\n const verticalAlign = opts.verticalAlign || _constants__WEBPACK_IMPORTED_MODULE_7__.DEFAULT_VERTICAL_ALIGN;\n const offsets = getTextElementPositionOffsets({\n textAlign,\n verticalAlign\n }, metrics);\n const textElementProps = Object.assign(Object.assign({}, _newElementBase(\"text\", opts)), {\n text,\n rawText,\n fontSize,\n fontFamily,\n textAlign,\n verticalAlign,\n x: opts.x - offsets.x,\n y: opts.y - offsets.y,\n width: metrics.width,\n //width: Math.max(opts.width??0,metrics.width), //zsviczian\n height: metrics.height,\n containerId: opts.containerId || null,\n originalText: (_a = opts.originalText) !== null && _a !== void 0 ? _a : text,\n autoResize: (_b = opts.autoResize) !== null && _b !== void 0 ? _b : true,\n lineHeight\n });\n const textElement = (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.newElementWith)(textElementProps, {});\n return textElement;\n};\n\nconst getAdjustedDimensions = (element, elementsMap, nextText) => {\n let {\n width: nextWidth,\n height: nextHeight\n } = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.measureText)(nextText, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(element), element.lineHeight); // wrapped text\n\n if (!element.autoResize) {\n nextWidth = element.width;\n }\n\n const {\n textAlign,\n verticalAlign\n } = element;\n let x;\n let y;\n\n if (textAlign === \"center\" && verticalAlign === _constants__WEBPACK_IMPORTED_MODULE_7__.VERTICAL_ALIGN.MIDDLE && !element.containerId && element.autoResize) {\n const prevMetrics = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.measureText)(element.text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(element), element.lineHeight);\n const offsets = getTextElementPositionOffsets(element, {\n width: nextWidth - prevMetrics.width,\n height: nextHeight - prevMetrics.height\n });\n x = element.x - offsets.x;\n y = element.y - offsets.y;\n } else {\n const [x1, y1, x2, y2] = (0,___WEBPACK_IMPORTED_MODULE_4__.getElementAbsoluteCoords)(element, elementsMap);\n const [nextX1, nextY1, nextX2, nextY2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getResizedElementAbsoluteCoords)(element, nextWidth, nextHeight, false);\n const deltaX1 = (x1 - nextX1) / 2;\n const deltaY1 = (y1 - nextY1) / 2;\n const deltaX2 = (x2 - nextX2) / 2;\n const deltaY2 = (y2 - nextY2) / 2;\n [x, y] = adjustXYWithRotation({\n s: true,\n e: textAlign === \"center\" || textAlign === \"left\",\n w: textAlign === \"center\" || textAlign === \"right\"\n }, element.x, element.y, element.angle, deltaX1, deltaY1, deltaX2, deltaY2);\n }\n\n return {\n width: nextWidth,\n height: nextHeight,\n x: Number.isFinite(x) ? x : element.x,\n y: Number.isFinite(y) ? y : element.y\n };\n};\n\nconst adjustXYWithRotation = (sides, x, y, angle, deltaX1, deltaY1, deltaX2, deltaY2) => {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n if (sides.e && sides.w) {\n x += deltaX1 + deltaX2;\n } else if (sides.e) {\n x += deltaX1 * (1 + cos);\n y += deltaX1 * sin;\n x += deltaX2 * (1 - cos);\n y += deltaX2 * -sin;\n } else if (sides.w) {\n x += deltaX1 * (1 - cos);\n y += deltaX1 * -sin;\n x += deltaX2 * (1 + cos);\n y += deltaX2 * sin;\n }\n\n if (sides.n && sides.s) {\n y += deltaY1 + deltaY2;\n } else if (sides.n) {\n x += deltaY1 * sin;\n y += deltaY1 * (1 - cos);\n x += deltaY2 * -sin;\n y += deltaY2 * (1 + cos);\n } else if (sides.s) {\n x += deltaY1 * -sin;\n y += deltaY1 * (1 + cos);\n x += deltaY2 * sin;\n y += deltaY2 * (1 - cos);\n }\n\n return [x, y];\n};\n\nconst refreshTextDimensions = (textElement, container, elementsMap, text = textElement.text) => {\n if (textElement.isDeleted) {\n return;\n }\n\n if (container || !textElement.autoResize) {\n text = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.wrapText)(text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), container ? (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxWidth)(container, textElement) : textElement.width);\n }\n\n const dimensions = getAdjustedDimensions(textElement, elementsMap, text);\n return Object.assign({\n text\n }, dimensions);\n};\nconst newFreeDrawElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(opts.type, opts)), {\n points: opts.points || [],\n pressures: opts.pressures || [],\n simulatePressure: opts.simulatePressure,\n lastCommittedPoint: null\n });\n};\nconst newLinearElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(opts.type, opts)), {\n points: opts.points || [],\n lastCommittedPoint: null,\n startBinding: null,\n endBinding: null,\n startArrowhead: null,\n endArrowhead: null\n });\n};\nconst newArrowElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(opts.type, opts)), {\n points: opts.points || [],\n lastCommittedPoint: null,\n startBinding: null,\n endBinding: null,\n startArrowhead: opts.startArrowhead || null,\n endArrowhead: opts.endArrowhead || null,\n elbowed: opts.elbowed || false\n });\n};\nconst newImageElement = opts => {\n var _a, _b, _c, _d;\n\n return Object.assign(Object.assign({}, _newElementBase(\"image\", opts)), {\n // in the future we'll support changing stroke color for some SVG elements,\n // and `transparent` will likely mean \"use original colors of the image\"\n strokeColor: \"transparent\",\n status: (_a = opts.status) !== null && _a !== void 0 ? _a : \"pending\",\n fileId: (_b = opts.fileId) !== null && _b !== void 0 ? _b : null,\n scale: (_c = opts.scale) !== null && _c !== void 0 ? _c : [1, 1],\n crop: (_d = opts.crop) !== null && _d !== void 0 ? _d : null\n });\n}; // Simplified deep clone for the purpose of cloning ExcalidrawElement.\n//\n// Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\n// Typed arrays and other non-null objects.\n//\n// Adapted from https://github.com/lukeed/klona\n//\n// The reason for `deepCopyElement()` wrapper is type safety (only allow\n// passing ExcalidrawElement as the top-level argument).\n\nconst _deepCopyElement = (val, depth = 0) => {\n // only clone non-primitives\n if (val == null || typeof val !== \"object\") {\n return val;\n }\n\n const objectType = Object.prototype.toString.call(val);\n\n if (objectType === \"[object Object]\") {\n const tmp = typeof val.constructor === \"function\" ? Object.create(Object.getPrototypeOf(val)) : {};\n\n for (const key in val) {\n if (val.hasOwnProperty(key)) {\n // don't copy non-serializable objects like these caches. They'll be\n // populated when the element is rendered.\n if (depth === 0 && (key === \"shape\" || key === \"canvas\")) {\n continue;\n }\n\n tmp[key] = _deepCopyElement(val[key], depth + 1);\n }\n }\n\n return tmp;\n }\n\n if (Array.isArray(val)) {\n let k = val.length;\n const arr = new Array(k);\n\n while (k--) {\n arr[k] = _deepCopyElement(val[k], depth + 1);\n }\n\n return arr;\n } // we're not cloning non-array & non-plain-object objects because we\n // don't support them on excalidraw elements yet. If we do, we need to make\n // sure we start cloning them, so let's warn about it.\n\n\n if (true) {\n if (objectType !== \"[object Object]\" && objectType !== \"[object Array]\" && objectType.startsWith(\"[object \")) {\n console.warn(`_deepCloneElement: unexpected object type ${objectType}. This value will not be cloned!`);\n }\n }\n\n return val;\n};\n/**\n * Clones ExcalidrawElement data structure. Does not regenerate id, nonce, or\n * any value. The purpose is to to break object references for immutability\n * reasons, whenever we want to keep the original element, but ensure it's not\n * mutated.\n *\n * Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\n * Typed arrays and other non-null objects.\n */\n\n\nconst deepCopyElement = val => {\n return _deepCopyElement(val);\n};\n/**\n * utility wrapper to generate new id. In test env it reuses the old + postfix\n * for test assertions.\n */\n\nconst regenerateId = (\n/** supply null if no previous id exists */\npreviousId) => {\n var _a, _b;\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_0__.isTestEnv)() && previousId) {\n let nextId = `${previousId}_copy`; // `window.h` may not be defined in some unit tests\n\n if ((_b = (_a = window.h) === null || _a === void 0 ? void 0 : _a.app) === null || _b === void 0 ? void 0 : _b.getSceneElementsIncludingDeleted().find(el => el.id === nextId)) {\n nextId += \"_copy\";\n }\n\n return nextId;\n }\n\n return (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomId)();\n};\n/**\n * Duplicate an element, often used in the alt-drag operation.\n * Note that this method has gotten a bit complicated since the\n * introduction of gruoping/ungrouping elements.\n * @param editingGroupId The current group being edited. The new\n * element will inherit this group and its\n * parents.\n * @param groupIdMapForOperation A Map that maps old group IDs to\n * duplicated ones. If you are duplicating\n * multiple elements at once, share this map\n * amongst all of them\n * @param element Element to duplicate\n * @param overrides Any element properties to override\n */\n\nconst duplicateElement = (editingGroupId, groupIdMapForOperation, element, overrides) => {\n let copy = deepCopyElement(element);\n copy.id = copy.type === \"text\" ? (0,_random__WEBPACK_IMPORTED_MODULE_1__.obsidianId)() : regenerateId(copy.id); //zsviczian\n\n copy.boundElements = null;\n copy.updated = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getUpdatedTimestamp)();\n copy.seed = (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomInteger)();\n copy.groupIds = (0,_groups__WEBPACK_IMPORTED_MODULE_3__.getNewGroupIdsForDuplication)(copy.groupIds, editingGroupId, groupId => {\n if (!groupIdMapForOperation.has(groupId)) {\n groupIdMapForOperation.set(groupId, regenerateId(groupId));\n }\n\n return groupIdMapForOperation.get(groupId);\n });\n\n if (overrides) {\n copy = Object.assign(copy, overrides);\n }\n\n return copy;\n};\n/**\n * Clones elements, regenerating their ids (including bindings) and group ids.\n *\n * If bindings don't exist in the elements array, they are removed. Therefore,\n * it's advised to supply the whole elements array, or sets of elements that\n * are encapsulated (such as library items), if the purpose is to retain\n * bindings to the cloned elements intact.\n *\n * NOTE by default does not randomize or regenerate anything except the id.\n */\n\nconst duplicateElements = (elements, opts) => {\n const clonedElements = [];\n const origElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.arrayToMap)(elements); // used for for migrating old ids to new ids\n\n const elementNewIdsMap = new Map();\n\n const maybeGetNewId = id => {\n // if we've already migrated the element id, return the new one directly\n if (elementNewIdsMap.has(id)) {\n return elementNewIdsMap.get(id);\n } // if we haven't migrated the element id, but an old element with the same\n // id exists, generate a new id for it and return it\n\n\n if (origElementsMap.has(id)) {\n const newId = regenerateId(id);\n elementNewIdsMap.set(id, newId);\n return newId;\n } // if old element doesn't exist, return null to mark it for removal\n\n\n return null;\n };\n\n const groupNewIdsMap = new Map();\n\n for (const element of elements) {\n const clonedElement = _deepCopyElement(element);\n\n clonedElement.id = maybeGetNewId(element.id);\n\n if (opts === null || opts === void 0 ? void 0 : opts.randomizeSeed) {\n clonedElement.seed = (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomInteger)();\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.bumpVersion)(clonedElement);\n }\n\n if (clonedElement.groupIds) {\n clonedElement.groupIds = clonedElement.groupIds.map(groupId => {\n if (!groupNewIdsMap.has(groupId)) {\n groupNewIdsMap.set(groupId, regenerateId(groupId));\n }\n\n return groupNewIdsMap.get(groupId);\n });\n }\n\n if (\"containerId\" in clonedElement && clonedElement.containerId) {\n const newContainerId = maybeGetNewId(clonedElement.containerId);\n clonedElement.containerId = newContainerId;\n }\n\n if (\"boundElements\" in clonedElement && clonedElement.boundElements) {\n clonedElement.boundElements = clonedElement.boundElements.reduce((acc, binding) => {\n const newBindingId = maybeGetNewId(binding.id);\n\n if (newBindingId) {\n acc.push(Object.assign(Object.assign({}, binding), {\n id: newBindingId\n }));\n }\n\n return acc;\n }, []);\n }\n\n if (\"endBinding\" in clonedElement && clonedElement.endBinding) {\n const newEndBindingId = maybeGetNewId(clonedElement.endBinding.elementId);\n clonedElement.endBinding = newEndBindingId ? Object.assign(Object.assign({}, clonedElement.endBinding), {\n elementId: newEndBindingId\n }) : null;\n }\n\n if (\"startBinding\" in clonedElement && clonedElement.startBinding) {\n const newEndBindingId = maybeGetNewId(clonedElement.startBinding.elementId);\n clonedElement.startBinding = newEndBindingId ? Object.assign(Object.assign({}, clonedElement.startBinding), {\n elementId: newEndBindingId\n }) : null;\n }\n\n if (clonedElement.frameId) {\n clonedElement.frameId = maybeGetNewId(clonedElement.frameId);\n }\n\n clonedElements.push(clonedElement);\n }\n\n return clonedElements;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/newElement.ts?");
2951
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"deepCopyElement\": () => (/* binding */ deepCopyElement),\n/* harmony export */ \"duplicateElement\": () => (/* binding */ duplicateElement),\n/* harmony export */ \"duplicateElements\": () => (/* binding */ duplicateElements),\n/* harmony export */ \"newArrowElement\": () => (/* binding */ newArrowElement),\n/* harmony export */ \"newElement\": () => (/* binding */ newElement),\n/* harmony export */ \"newEmbeddableElement\": () => (/* binding */ newEmbeddableElement),\n/* harmony export */ \"newFrameElement\": () => (/* binding */ newFrameElement),\n/* harmony export */ \"newFreeDrawElement\": () => (/* binding */ newFreeDrawElement),\n/* harmony export */ \"newIframeElement\": () => (/* binding */ newIframeElement),\n/* harmony export */ \"newImageElement\": () => (/* binding */ newImageElement),\n/* harmony export */ \"newLinearElement\": () => (/* binding */ newLinearElement),\n/* harmony export */ \"newMagicFrameElement\": () => (/* binding */ newMagicFrameElement),\n/* harmony export */ \"newTextElement\": () => (/* binding */ newTextElement),\n/* harmony export */ \"refreshTextDimensions\": () => (/* binding */ refreshTextDimensions),\n/* harmony export */ \"regenerateId\": () => (/* binding */ regenerateId)\n/* harmony export */ });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _random__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../random */ \"./random.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../groups */ \"./groups.ts\");\n/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! . */ \"./element/index.ts\");\n/* harmony import */ var _bounds__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _textWrapping__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _fonts__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../fonts */ \"./fonts/index.ts\");\nvar __rest = undefined && undefined.__rest || function (s, e) {\n var t = {};\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n};\n\n\n\n\n\n\n\n\n\n\n\n\nconst _newElementBase = (type, _a) => {\n var _b, _c;\n\n var {\n x,\n y,\n strokeColor = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.strokeColor,\n backgroundColor = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.backgroundColor,\n fillStyle = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.fillStyle,\n strokeWidth = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.strokeWidth,\n strokeStyle = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.strokeStyle,\n roughness = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.roughness,\n opacity = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.opacity,\n width = 0,\n height = 0,\n angle = 0,\n groupIds = [],\n frameId = null,\n index = null,\n roundness = null,\n boundElements = null,\n link = null,\n locked = _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_ELEMENT_PROPS.locked\n } = _a,\n rest = __rest(_a, [\"x\", \"y\", \"strokeColor\", \"backgroundColor\", \"fillStyle\", \"strokeWidth\", \"strokeStyle\", \"roughness\", \"opacity\", \"width\", \"height\", \"angle\", \"groupIds\", \"frameId\", \"index\", \"roundness\", \"boundElements\", \"link\", \"locked\"]); // assign type to guard against excess properties\n\n\n const element = {\n id: rest.id || (type === \"text\" ? (0,_random__WEBPACK_IMPORTED_MODULE_1__.obsidianId)() : (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomId)()),\n type,\n x,\n y,\n width,\n height,\n angle,\n strokeColor,\n backgroundColor,\n fillStyle,\n strokeWidth,\n strokeStyle,\n roughness,\n opacity,\n groupIds,\n frameId,\n index,\n roundness,\n seed: (_b = rest.seed) !== null && _b !== void 0 ? _b : (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomInteger)(),\n version: rest.version || 1,\n versionNonce: (_c = rest.versionNonce) !== null && _c !== void 0 ? _c : 0,\n isDeleted: false,\n boundElements,\n updated: (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getUpdatedTimestamp)(),\n link,\n locked,\n //...(rest.customData ? { customData: rest.customData } : {}), //zsviczian\n customData: rest.customData\n };\n return element;\n};\n\nconst newElement = opts => _newElementBase(opts.type, opts);\nconst newEmbeddableElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(\"embeddable\", opts)), {\n scale: [1, 1]\n });\n};\nconst newIframeElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(\"iframe\", opts)), {\n scale: [1, 1]\n });\n};\nconst newFrameElement = opts => {\n const frameElement = (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.newElementWith)(Object.assign(Object.assign({}, _newElementBase(\"frame\", opts)), {\n type: \"frame\",\n name: (opts === null || opts === void 0 ? void 0 : opts.name) || null\n }), {});\n return frameElement;\n};\nconst newMagicFrameElement = opts => {\n const frameElement = (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.newElementWith)(Object.assign(Object.assign({}, _newElementBase(\"magicframe\", opts)), {\n type: \"magicframe\",\n name: (opts === null || opts === void 0 ? void 0 : opts.name) || null\n }), {});\n return frameElement;\n};\n/** computes element x/y offset based on textAlign/verticalAlign */\n\nconst getTextElementPositionOffsets = (opts, metrics) => {\n return {\n x: opts.textAlign === \"center\" ? metrics.width / 2 : opts.textAlign === \"right\" ? metrics.width : 0,\n y: opts.verticalAlign === \"middle\" ? metrics.height / 2 : 0\n };\n};\n\nconst newTextElement = opts => {\n var _a, _b;\n\n const fontFamily = opts.fontFamily || _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_FONT_FAMILY;\n const fontSize = opts.fontSize || _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_FONT_SIZE;\n const lineHeight = opts.lineHeight || (0,_fonts__WEBPACK_IMPORTED_MODULE_9__.getLineHeight)(fontFamily);\n const text = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(opts.text);\n const rawText = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(opts.rawText); //zsviczian\n\n const metrics = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.measureText)(text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)({\n fontFamily,\n fontSize\n }), lineHeight);\n const textAlign = opts.textAlign || _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_TEXT_ALIGN;\n const verticalAlign = opts.verticalAlign || _constants__WEBPACK_IMPORTED_MODULE_8__.DEFAULT_VERTICAL_ALIGN;\n const offsets = getTextElementPositionOffsets({\n textAlign,\n verticalAlign\n }, metrics);\n const textElementProps = Object.assign(Object.assign({}, _newElementBase(\"text\", opts)), {\n text,\n rawText,\n fontSize,\n fontFamily,\n textAlign,\n verticalAlign,\n x: opts.x - offsets.x,\n y: opts.y - offsets.y,\n width: metrics.width,\n //width: Math.max(opts.width??0,metrics.width), //zsviczian\n height: metrics.height,\n containerId: opts.containerId || null,\n originalText: (_a = opts.originalText) !== null && _a !== void 0 ? _a : text,\n autoResize: (_b = opts.autoResize) !== null && _b !== void 0 ? _b : true,\n lineHeight\n });\n const textElement = (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.newElementWith)(textElementProps, {});\n return textElement;\n};\n\nconst getAdjustedDimensions = (element, elementsMap, nextText) => {\n let {\n width: nextWidth,\n height: nextHeight\n } = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.measureText)(nextText, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(element), element.lineHeight); // wrapped text\n\n if (!element.autoResize) {\n nextWidth = element.width;\n }\n\n const {\n textAlign,\n verticalAlign\n } = element;\n let x;\n let y;\n\n if (textAlign === \"center\" && verticalAlign === _constants__WEBPACK_IMPORTED_MODULE_8__.VERTICAL_ALIGN.MIDDLE && !element.containerId && element.autoResize) {\n const prevMetrics = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.measureText)(element.text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(element), element.lineHeight);\n const offsets = getTextElementPositionOffsets(element, {\n width: nextWidth - prevMetrics.width,\n height: nextHeight - prevMetrics.height\n });\n x = element.x - offsets.x;\n y = element.y - offsets.y;\n } else {\n const [x1, y1, x2, y2] = (0,___WEBPACK_IMPORTED_MODULE_4__.getElementAbsoluteCoords)(element, elementsMap);\n const [nextX1, nextY1, nextX2, nextY2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_5__.getResizedElementAbsoluteCoords)(element, nextWidth, nextHeight, false);\n const deltaX1 = (x1 - nextX1) / 2;\n const deltaY1 = (y1 - nextY1) / 2;\n const deltaX2 = (x2 - nextX2) / 2;\n const deltaY2 = (y2 - nextY2) / 2;\n [x, y] = adjustXYWithRotation({\n s: true,\n e: textAlign === \"center\" || textAlign === \"left\",\n w: textAlign === \"center\" || textAlign === \"right\"\n }, element.x, element.y, element.angle, deltaX1, deltaY1, deltaX2, deltaY2);\n }\n\n return {\n width: nextWidth,\n height: nextHeight,\n x: Number.isFinite(x) ? x : element.x,\n y: Number.isFinite(y) ? y : element.y\n };\n};\n\nconst adjustXYWithRotation = (sides, x, y, angle, deltaX1, deltaY1, deltaX2, deltaY2) => {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n if (sides.e && sides.w) {\n x += deltaX1 + deltaX2;\n } else if (sides.e) {\n x += deltaX1 * (1 + cos);\n y += deltaX1 * sin;\n x += deltaX2 * (1 - cos);\n y += deltaX2 * -sin;\n } else if (sides.w) {\n x += deltaX1 * (1 - cos);\n y += deltaX1 * -sin;\n x += deltaX2 * (1 + cos);\n y += deltaX2 * sin;\n }\n\n if (sides.n && sides.s) {\n y += deltaY1 + deltaY2;\n } else if (sides.n) {\n x += deltaY1 * sin;\n y += deltaY1 * (1 - cos);\n x += deltaY2 * -sin;\n y += deltaY2 * (1 + cos);\n } else if (sides.s) {\n x += deltaY1 * -sin;\n y += deltaY1 * (1 + cos);\n x += deltaY2 * sin;\n y += deltaY2 * (1 - cos);\n }\n\n return [x, y];\n};\n\nconst refreshTextDimensions = (textElement, container, elementsMap, text = textElement.text) => {\n if (textElement.isDeleted) {\n return;\n }\n\n if (container || !textElement.autoResize) {\n text = (0,_textWrapping__WEBPACK_IMPORTED_MODULE_7__.wrapText)(text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), container ? (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxWidth)(container, textElement) : textElement.width);\n }\n\n const dimensions = getAdjustedDimensions(textElement, elementsMap, text);\n return Object.assign({\n text\n }, dimensions);\n};\nconst newFreeDrawElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(opts.type, opts)), {\n points: opts.points || [],\n pressures: opts.pressures || [],\n simulatePressure: opts.simulatePressure,\n lastCommittedPoint: null\n });\n};\nconst newLinearElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(opts.type, opts)), {\n points: opts.points || [],\n lastCommittedPoint: null,\n startBinding: null,\n endBinding: null,\n startArrowhead: null,\n endArrowhead: null\n });\n};\nconst newArrowElement = opts => {\n return Object.assign(Object.assign({}, _newElementBase(opts.type, opts)), {\n points: opts.points || [],\n lastCommittedPoint: null,\n startBinding: null,\n endBinding: null,\n startArrowhead: opts.startArrowhead || null,\n endArrowhead: opts.endArrowhead || null,\n elbowed: opts.elbowed || false\n });\n};\nconst newImageElement = opts => {\n var _a, _b, _c, _d;\n\n return Object.assign(Object.assign({}, _newElementBase(\"image\", opts)), {\n // in the future we'll support changing stroke color for some SVG elements,\n // and `transparent` will likely mean \"use original colors of the image\"\n strokeColor: \"transparent\",\n status: (_a = opts.status) !== null && _a !== void 0 ? _a : \"pending\",\n fileId: (_b = opts.fileId) !== null && _b !== void 0 ? _b : null,\n scale: (_c = opts.scale) !== null && _c !== void 0 ? _c : [1, 1],\n crop: (_d = opts.crop) !== null && _d !== void 0 ? _d : null\n });\n}; // Simplified deep clone for the purpose of cloning ExcalidrawElement.\n//\n// Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\n// Typed arrays and other non-null objects.\n//\n// Adapted from https://github.com/lukeed/klona\n//\n// The reason for `deepCopyElement()` wrapper is type safety (only allow\n// passing ExcalidrawElement as the top-level argument).\n\nconst _deepCopyElement = (val, depth = 0) => {\n // only clone non-primitives\n if (val == null || typeof val !== \"object\") {\n return val;\n }\n\n const objectType = Object.prototype.toString.call(val);\n\n if (objectType === \"[object Object]\") {\n const tmp = typeof val.constructor === \"function\" ? Object.create(Object.getPrototypeOf(val)) : {};\n\n for (const key in val) {\n if (val.hasOwnProperty(key)) {\n // don't copy non-serializable objects like these caches. They'll be\n // populated when the element is rendered.\n if (depth === 0 && (key === \"shape\" || key === \"canvas\")) {\n continue;\n }\n\n tmp[key] = _deepCopyElement(val[key], depth + 1);\n }\n }\n\n return tmp;\n }\n\n if (Array.isArray(val)) {\n let k = val.length;\n const arr = new Array(k);\n\n while (k--) {\n arr[k] = _deepCopyElement(val[k], depth + 1);\n }\n\n return arr;\n } // we're not cloning non-array & non-plain-object objects because we\n // don't support them on excalidraw elements yet. If we do, we need to make\n // sure we start cloning them, so let's warn about it.\n\n\n if (true) {\n if (objectType !== \"[object Object]\" && objectType !== \"[object Array]\" && objectType.startsWith(\"[object \")) {\n console.warn(`_deepCloneElement: unexpected object type ${objectType}. This value will not be cloned!`);\n }\n }\n\n return val;\n};\n/**\n * Clones ExcalidrawElement data structure. Does not regenerate id, nonce, or\n * any value. The purpose is to to break object references for immutability\n * reasons, whenever we want to keep the original element, but ensure it's not\n * mutated.\n *\n * Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\n * Typed arrays and other non-null objects.\n */\n\n\nconst deepCopyElement = val => {\n return _deepCopyElement(val);\n};\n/**\n * utility wrapper to generate new id. In test env it reuses the old + postfix\n * for test assertions.\n */\n\nconst regenerateId = (\n/** supply null if no previous id exists */\npreviousId) => {\n var _a, _b;\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_0__.isTestEnv)() && previousId) {\n let nextId = `${previousId}_copy`; // `window.h` may not be defined in some unit tests\n\n if ((_b = (_a = window.h) === null || _a === void 0 ? void 0 : _a.app) === null || _b === void 0 ? void 0 : _b.getSceneElementsIncludingDeleted().find(el => el.id === nextId)) {\n nextId += \"_copy\";\n }\n\n return nextId;\n }\n\n return (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomId)();\n};\n/**\n * Duplicate an element, often used in the alt-drag operation.\n * Note that this method has gotten a bit complicated since the\n * introduction of gruoping/ungrouping elements.\n * @param editingGroupId The current group being edited. The new\n * element will inherit this group and its\n * parents.\n * @param groupIdMapForOperation A Map that maps old group IDs to\n * duplicated ones. If you are duplicating\n * multiple elements at once, share this map\n * amongst all of them\n * @param element Element to duplicate\n * @param overrides Any element properties to override\n */\n\nconst duplicateElement = (editingGroupId, groupIdMapForOperation, element, overrides) => {\n let copy = deepCopyElement(element);\n copy.id = copy.type === \"text\" ? (0,_random__WEBPACK_IMPORTED_MODULE_1__.obsidianId)() : regenerateId(copy.id); //zsviczian\n\n copy.boundElements = null;\n copy.updated = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getUpdatedTimestamp)();\n copy.seed = (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomInteger)();\n copy.groupIds = (0,_groups__WEBPACK_IMPORTED_MODULE_3__.getNewGroupIdsForDuplication)(copy.groupIds, editingGroupId, groupId => {\n if (!groupIdMapForOperation.has(groupId)) {\n groupIdMapForOperation.set(groupId, regenerateId(groupId));\n }\n\n return groupIdMapForOperation.get(groupId);\n });\n\n if (overrides) {\n copy = Object.assign(copy, overrides);\n }\n\n return copy;\n};\n/**\n * Clones elements, regenerating their ids (including bindings) and group ids.\n *\n * If bindings don't exist in the elements array, they are removed. Therefore,\n * it's advised to supply the whole elements array, or sets of elements that\n * are encapsulated (such as library items), if the purpose is to retain\n * bindings to the cloned elements intact.\n *\n * NOTE by default does not randomize or regenerate anything except the id.\n */\n\nconst duplicateElements = (elements, opts) => {\n const clonedElements = [];\n const origElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.arrayToMap)(elements); // used for for migrating old ids to new ids\n\n const elementNewIdsMap = new Map();\n\n const maybeGetNewId = id => {\n // if we've already migrated the element id, return the new one directly\n if (elementNewIdsMap.has(id)) {\n return elementNewIdsMap.get(id);\n } // if we haven't migrated the element id, but an old element with the same\n // id exists, generate a new id for it and return it\n\n\n if (origElementsMap.has(id)) {\n const newId = regenerateId(id);\n elementNewIdsMap.set(id, newId);\n return newId;\n } // if old element doesn't exist, return null to mark it for removal\n\n\n return null;\n };\n\n const groupNewIdsMap = new Map();\n\n for (const element of elements) {\n const clonedElement = _deepCopyElement(element);\n\n clonedElement.id = maybeGetNewId(element.id);\n\n if (opts === null || opts === void 0 ? void 0 : opts.randomizeSeed) {\n clonedElement.seed = (0,_random__WEBPACK_IMPORTED_MODULE_1__.randomInteger)();\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_2__.bumpVersion)(clonedElement);\n }\n\n if (clonedElement.groupIds) {\n clonedElement.groupIds = clonedElement.groupIds.map(groupId => {\n if (!groupNewIdsMap.has(groupId)) {\n groupNewIdsMap.set(groupId, regenerateId(groupId));\n }\n\n return groupNewIdsMap.get(groupId);\n });\n }\n\n if (\"containerId\" in clonedElement && clonedElement.containerId) {\n const newContainerId = maybeGetNewId(clonedElement.containerId);\n clonedElement.containerId = newContainerId;\n }\n\n if (\"boundElements\" in clonedElement && clonedElement.boundElements) {\n clonedElement.boundElements = clonedElement.boundElements.reduce((acc, binding) => {\n const newBindingId = maybeGetNewId(binding.id);\n\n if (newBindingId) {\n acc.push(Object.assign(Object.assign({}, binding), {\n id: newBindingId\n }));\n }\n\n return acc;\n }, []);\n }\n\n if (\"endBinding\" in clonedElement && clonedElement.endBinding) {\n const newEndBindingId = maybeGetNewId(clonedElement.endBinding.elementId);\n clonedElement.endBinding = newEndBindingId ? Object.assign(Object.assign({}, clonedElement.endBinding), {\n elementId: newEndBindingId\n }) : null;\n }\n\n if (\"startBinding\" in clonedElement && clonedElement.startBinding) {\n const newEndBindingId = maybeGetNewId(clonedElement.startBinding.elementId);\n clonedElement.startBinding = newEndBindingId ? Object.assign(Object.assign({}, clonedElement.startBinding), {\n elementId: newEndBindingId\n }) : null;\n }\n\n if (clonedElement.frameId) {\n clonedElement.frameId = maybeGetNewId(clonedElement.frameId);\n }\n\n clonedElements.push(clonedElement);\n }\n\n return clonedElements;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/newElement.ts?");
2952
2952
 
2953
2953
  /***/ }),
2954
2954
 
@@ -2959,7 +2959,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
2959
2959
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2960
2960
 
2961
2961
  "use strict";
2962
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"getResizeArrowDirection\": () => (/* binding */ getResizeArrowDirection),\n/* harmony export */ \"getResizeOffsetXY\": () => (/* binding */ getResizeOffsetXY),\n/* harmony export */ \"measureFontSizeFromWidth\": () => (/* binding */ measureFontSizeFromWidth),\n/* harmony export */ \"rescalePointsInElement\": () => (/* binding */ rescalePointsInElement),\n/* harmony export */ \"resizeMultipleElements\": () => (/* binding */ resizeMultipleElements),\n/* harmony export */ \"resizeSingleElement\": () => (/* binding */ resizeSingleElement),\n/* harmony export */ \"transformElements\": () => (/* binding */ transformElements)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _points__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../points */ \"./points.ts\");\n/* harmony import */ var _bounds__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _binding__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./binding */ \"./element/binding.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../groups */ \"./groups.ts\");\n/* harmony import */ var _routing__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./routing */ \"./element/routing.ts\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../math */ \"../math/index.ts\");\nvar __rest = undefined && undefined.__rest || function (s, e) {\n var t = {};\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n // Returns true when transform (resizing/rotation) happened\n\nconst transformElements = (originalElements, transformHandleType, selectedElements, elementsMap, shouldRotateWithDiscreteAngle, shouldResizeFromCenter, shouldMaintainAspectRatio, pointerX, pointerY, centerX, centerY) => {\n if (selectedElements.length === 1) {\n const [element] = selectedElements;\n\n if (transformHandleType === \"rotation\") {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isElbowArrow)(element)) {\n rotateSingleElement(element, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap);\n }\n } else if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(element) && transformHandleType) {\n resizeSingleTextElement(originalElements, element, elementsMap, transformHandleType, shouldResizeFromCenter, pointerX, pointerY);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap);\n } else if (transformHandleType) {\n resizeSingleElement(originalElements, shouldMaintainAspectRatio, element, elementsMap, transformHandleType, shouldResizeFromCenter, pointerX, pointerY);\n }\n\n return true;\n } else if (selectedElements.length > 1) {\n if (transformHandleType === \"rotation\") {\n rotateMultipleElements(originalElements, selectedElements, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle, centerX, centerY);\n return true;\n } else if (transformHandleType) {\n resizeMultipleElements(originalElements, selectedElements, elementsMap, transformHandleType, shouldResizeFromCenter, shouldMaintainAspectRatio, pointerX, pointerY);\n return true;\n }\n }\n\n return false;\n};\n\nconst rotateSingleElement = (element, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle) => {\n var _a;\n\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n let angle;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFrameLikeElement)(element)) {\n angle = 0;\n } else {\n angle = 5 * Math.PI / 2 + Math.atan2(pointerY - cy, pointerX - cx);\n\n if (shouldRotateWithDiscreteAngle) {\n angle = angle + _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE / 2;\n angle = angle - angle % _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE;\n }\n\n angle = (0,_math__WEBPACK_IMPORTED_MODULE_12__.normalizeRadians)(angle);\n }\n\n const boundTextElementId = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElementId)(element);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n angle\n });\n\n if (boundTextElementId) {\n const textElement = (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_7__[\"default\"].getScene(element)) === null || _a === void 0 ? void 0 : _a.getElement(boundTextElementId);\n\n if (textElement && !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(element)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(textElement, {\n angle\n });\n }\n }\n};\n\nconst rescalePointsInElement = (element, width, height, normalizePoints) => (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(element) || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFreeDrawElement)(element) ? {\n points: (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(0, width, (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(1, height, element.points, normalizePoints), normalizePoints)\n} : {};\nconst measureFontSizeFromWidth = (element, elementsMap, nextWidth) => {\n // We only use width to scale font on resize\n let width = element.width;\n const hasContainer = (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(element);\n\n if (hasContainer) {\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getContainerElement)(element, elementsMap);\n\n if (container) {\n width = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextMaxWidth)(container, element);\n }\n }\n\n const nextFontSize = element.fontSize * (nextWidth / width);\n\n if (nextFontSize < _constants__WEBPACK_IMPORTED_MODULE_0__.MIN_FONT_SIZE) {\n return null;\n }\n\n return {\n size: nextFontSize\n };\n};\n\nconst resizeSingleTextElement = (originalElements, element, elementsMap, transformHandleType, shouldResizeFromCenter, pointerX, pointerY) => {\n const [x1, y1, x2, y2, cx, cy] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(element, elementsMap); // rotation pointer with reverse angle\n\n const [rotatedX, rotatedY] = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(pointerX, pointerY), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(cx, cy), -element.angle);\n let scaleX = 0;\n let scaleY = 0;\n\n if (transformHandleType !== \"e\" && transformHandleType !== \"w\") {\n if (transformHandleType.includes(\"e\")) {\n scaleX = (rotatedX - x1) / (x2 - x1);\n }\n\n if (transformHandleType.includes(\"w\")) {\n scaleX = (x2 - rotatedX) / (x2 - x1);\n }\n\n if (transformHandleType.includes(\"n\")) {\n scaleY = (y2 - rotatedY) / (y2 - y1);\n }\n\n if (transformHandleType.includes(\"s\")) {\n scaleY = (rotatedY - y1) / (y2 - y1);\n }\n }\n\n const scale = Math.max(scaleX, scaleY);\n\n if (scale > 0) {\n const nextWidth = element.width * scale;\n const nextHeight = element.height * scale;\n const metrics = measureFontSizeFromWidth(element, elementsMap, nextWidth);\n\n if (metrics === null) {\n return;\n }\n\n const startTopLeft = [x1, y1];\n const startBottomRight = [x2, y2];\n const startCenter = [cx, cy];\n let newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x1, y1);\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandleType)) {\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(startBottomRight[0] - Math.abs(nextWidth), startBottomRight[1] - Math.abs(nextHeight));\n }\n\n if (transformHandleType === \"ne\") {\n const bottomLeft = [startTopLeft[0], startBottomRight[1]];\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(bottomLeft[0], bottomLeft[1] - Math.abs(nextHeight));\n }\n\n if (transformHandleType === \"sw\") {\n const topRight = [startBottomRight[0], startTopLeft[1]];\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(topRight[0] - Math.abs(nextWidth), topRight[1]);\n }\n\n if ([\"s\", \"n\"].includes(transformHandleType)) {\n newTopLeft[0] = startCenter[0] - nextWidth / 2;\n }\n\n if ([\"e\", \"w\"].includes(transformHandleType)) {\n newTopLeft[1] = startCenter[1] - nextHeight / 2;\n }\n\n if (shouldResizeFromCenter) {\n newTopLeft[0] = startCenter[0] - Math.abs(nextWidth) / 2;\n newTopLeft[1] = startCenter[1] - Math.abs(nextHeight) / 2;\n }\n\n const angle = element.angle;\n const rotatedTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(newTopLeft, (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(cx, cy), angle);\n const newCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(newTopLeft[0] + Math.abs(nextWidth) / 2, newTopLeft[1] + Math.abs(nextHeight) / 2);\n const rotatedNewCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(newCenter, (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(cx, cy), angle);\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(rotatedTopLeft, rotatedNewCenter, -angle);\n const [nextX, nextY] = newTopLeft;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n fontSize: metrics.size,\n width: nextWidth,\n height: nextHeight,\n x: nextX,\n y: nextY\n });\n }\n\n if (transformHandleType === \"e\" || transformHandleType === \"w\") {\n const stateAtResizeStart = originalElements.get(element.id);\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, stateAtResizeStart.width, stateAtResizeStart.height, true);\n const startTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x1, y1);\n const startBottomRight = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x2, y2);\n const startCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointCenter)(startTopLeft, startBottomRight);\n const rotatedPointer = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(pointerX, pointerY), startCenter, -stateAtResizeStart.angle);\n const [esx1,, esx2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(element, element.width, element.height, true);\n const boundsCurrentWidth = esx2 - esx1;\n const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];\n const minWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getMinTextElementWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)({\n fontSize: element.fontSize,\n fontFamily: element.fontFamily\n }), element.lineHeight);\n let scaleX = atStartBoundsWidth / boundsCurrentWidth;\n\n if (transformHandleType.includes(\"e\")) {\n scaleX = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;\n }\n\n if (transformHandleType.includes(\"w\")) {\n scaleX = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;\n }\n\n const newWidth = element.width * scaleX < minWidth ? minWidth : element.width * scaleX;\n const text = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.wrapText)(element.originalText, (0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(element), Math.abs(newWidth));\n const metrics = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.measureText)(text, (0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(element), element.lineHeight);\n const eleNewHeight = metrics.height;\n const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, newWidth, eleNewHeight, true);\n const newBoundsWidth = newBoundsX2 - newBoundsX1;\n const newBoundsHeight = newBoundsY2 - newBoundsY1;\n let newTopLeft = [...startTopLeft];\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandleType)) {\n newTopLeft = [startBottomRight[0] - Math.abs(newBoundsWidth), startTopLeft[1]];\n } // adjust topLeft to new rotation point\n\n\n const angle = stateAtResizeStart.angle;\n const rotatedTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFromPair)(newTopLeft), startCenter, angle);\n const newCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(newTopLeft[0] + Math.abs(newBoundsWidth) / 2, newTopLeft[1] + Math.abs(newBoundsHeight) / 2);\n const rotatedNewCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(newCenter, startCenter, angle);\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(rotatedTopLeft, rotatedNewCenter, -angle);\n const resizedElement = {\n width: Math.abs(newWidth),\n height: Math.abs(metrics.height),\n x: newTopLeft[0],\n y: newTopLeft[1],\n text,\n autoResize: false\n };\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, resizedElement);\n }\n};\n\nconst resizeSingleElement = (originalElements, shouldMaintainAspectRatio, element, elementsMap, transformHandleDirection, shouldResizeFromCenter, pointerX, pointerY) => {\n var _a;\n\n if ((_a = element.customData) === null || _a === void 0 ? void 0 : _a.isAnchored) {\n return;\n } //zsviczian\n\n\n const stateAtResizeStart = originalElements.get(element.id); // Gets bounds corners\n\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, stateAtResizeStart.width, stateAtResizeStart.height, true);\n const startTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x1, y1);\n const startBottomRight = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x2, y2);\n const startCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointCenter)(startTopLeft, startBottomRight); // Calculate new dimensions based on cursor position\n\n const rotatedPointer = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(pointerX, pointerY), startCenter, -stateAtResizeStart.angle); // Get bounds corners rendered on screen\n\n const [esx1, esy1, esx2, esy2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(element, element.width, element.height, true);\n const boundsCurrentWidth = esx2 - esx1;\n const boundsCurrentHeight = esy2 - esy1; // It's important we set the initial scale value based on the width and height at resize start,\n // otherwise previous dimensions affected by modifiers will be taken into account.\n\n const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];\n const atStartBoundsHeight = startBottomRight[1] - startTopLeft[1];\n let scaleX = atStartBoundsWidth / boundsCurrentWidth;\n let scaleY = atStartBoundsHeight / boundsCurrentHeight;\n let boundTextFont = {};\n const boundTextElement = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElement)(element, elementsMap);\n\n if (transformHandleDirection.includes(\"e\")) {\n scaleX = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;\n }\n\n if (transformHandleDirection.includes(\"s\")) {\n scaleY = (rotatedPointer[1] - startTopLeft[1]) / boundsCurrentHeight;\n }\n\n if (transformHandleDirection.includes(\"w\")) {\n scaleX = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;\n }\n\n if (transformHandleDirection.includes(\"n\")) {\n scaleY = (startBottomRight[1] - rotatedPointer[1]) / boundsCurrentHeight;\n } // Linear elements dimensions differ from bounds dimensions\n\n\n const eleInitialWidth = stateAtResizeStart.width;\n const eleInitialHeight = stateAtResizeStart.height; // We have to use dimensions of element on screen, otherwise the scaling of the\n // dimensions won't match the cursor for linear elements.\n\n let eleNewWidth = element.width * scaleX;\n let eleNewHeight = element.height * scaleY; // adjust dimensions for resizing from center\n\n if (shouldResizeFromCenter) {\n eleNewWidth = 2 * eleNewWidth - eleInitialWidth;\n eleNewHeight = 2 * eleNewHeight - eleInitialHeight;\n } // adjust dimensions to keep sides ratio\n\n\n if (shouldMaintainAspectRatio) {\n const widthRatio = Math.abs(eleNewWidth) / eleInitialWidth;\n const heightRatio = Math.abs(eleNewHeight) / eleInitialHeight;\n\n if (transformHandleDirection.length === 1) {\n eleNewHeight *= widthRatio;\n eleNewWidth *= heightRatio;\n }\n\n if (transformHandleDirection.length === 2) {\n const ratio = Math.max(widthRatio, heightRatio);\n eleNewWidth = eleInitialWidth * ratio * Math.sign(eleNewWidth);\n eleNewHeight = eleInitialHeight * ratio * Math.sign(eleNewHeight);\n }\n }\n\n if (boundTextElement) {\n const stateOfBoundTextElementAtResize = originalElements.get(boundTextElement.id);\n\n if (stateOfBoundTextElementAtResize) {\n boundTextFont = {\n fontSize: stateOfBoundTextElementAtResize.fontSize\n };\n }\n\n if (shouldMaintainAspectRatio) {\n const updatedElement = Object.assign(Object.assign({}, element), {\n width: eleNewWidth,\n height: eleNewHeight\n });\n const nextFont = measureFontSizeFromWidth(boundTextElement, elementsMap, (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextMaxWidth)(updatedElement, boundTextElement));\n\n if (nextFont === null) {\n return;\n }\n\n boundTextFont = {\n fontSize: nextFont.size\n };\n } else {\n const minWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getApproxMinLineWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(boundTextElement), boundTextElement.lineHeight);\n const minHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getApproxMinLineHeight)(boundTextElement.fontSize, boundTextElement.lineHeight);\n eleNewWidth = Math.max(eleNewWidth, minWidth);\n eleNewHeight = Math.max(eleNewHeight, minHeight);\n }\n }\n\n const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, eleNewWidth, eleNewHeight, true);\n const newBoundsWidth = newBoundsX2 - newBoundsX1;\n const newBoundsHeight = newBoundsY2 - newBoundsY1; // Calculate new topLeft based on fixed corner during resize\n\n let newTopLeft = [...startTopLeft];\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandleDirection)) {\n newTopLeft = [startBottomRight[0] - Math.abs(newBoundsWidth), startBottomRight[1] - Math.abs(newBoundsHeight)];\n }\n\n if (transformHandleDirection === \"ne\") {\n const bottomLeft = [startTopLeft[0], startBottomRight[1]];\n newTopLeft = [bottomLeft[0], bottomLeft[1] - Math.abs(newBoundsHeight)];\n }\n\n if (transformHandleDirection === \"sw\") {\n const topRight = [startBottomRight[0], startTopLeft[1]];\n newTopLeft = [topRight[0] - Math.abs(newBoundsWidth), topRight[1]];\n } // Keeps opposite handle fixed during resize\n\n\n if (shouldMaintainAspectRatio) {\n if ([\"s\", \"n\"].includes(transformHandleDirection)) {\n newTopLeft[0] = startCenter[0] - newBoundsWidth / 2;\n }\n\n if ([\"e\", \"w\"].includes(transformHandleDirection)) {\n newTopLeft[1] = startCenter[1] - newBoundsHeight / 2;\n }\n }\n\n const flipX = eleNewWidth < 0;\n const flipY = eleNewHeight < 0; // Flip horizontally\n\n if (flipX) {\n if (transformHandleDirection.includes(\"e\")) {\n newTopLeft[0] -= Math.abs(newBoundsWidth);\n }\n\n if (transformHandleDirection.includes(\"w\")) {\n newTopLeft[0] += Math.abs(newBoundsWidth);\n }\n } // Flip vertically\n\n\n if (flipY) {\n if (transformHandleDirection.includes(\"s\")) {\n newTopLeft[1] -= Math.abs(newBoundsHeight);\n }\n\n if (transformHandleDirection.includes(\"n\")) {\n newTopLeft[1] += Math.abs(newBoundsHeight);\n }\n }\n\n if (shouldResizeFromCenter) {\n newTopLeft[0] = startCenter[0] - Math.abs(newBoundsWidth) / 2;\n newTopLeft[1] = startCenter[1] - Math.abs(newBoundsHeight) / 2;\n } // adjust topLeft to new rotation point\n\n\n const angle = stateAtResizeStart.angle;\n const rotatedTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFromPair)(newTopLeft), startCenter, angle);\n const newCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(newTopLeft[0] + Math.abs(newBoundsWidth) / 2, newTopLeft[1] + Math.abs(newBoundsHeight) / 2);\n const rotatedNewCenter = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(newCenter, startCenter, angle);\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)(rotatedTopLeft, rotatedNewCenter, -angle); // For linear elements (x,y) are the coordinates of the first drawn point not the top-left corner\n // So we need to readjust (x,y) to be where the first point should be\n\n const newOrigin = [...newTopLeft];\n const linearElementXOffset = stateAtResizeStart.x - newBoundsX1;\n const linearElementYOffset = stateAtResizeStart.y - newBoundsY1;\n newOrigin[0] += linearElementXOffset;\n newOrigin[1] += linearElementYOffset;\n const nextX = newOrigin[0];\n const nextY = newOrigin[1]; // Readjust points for linear elements\n\n let rescaledElementPointsY;\n let rescaledPoints;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(element) || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFreeDrawElement)(element)) {\n rescaledElementPointsY = (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(1, eleNewHeight, stateAtResizeStart.points, true);\n rescaledPoints = (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(0, eleNewWidth, rescaledElementPointsY, true);\n }\n\n const resizedElement = {\n width: Math.abs(eleNewWidth),\n height: Math.abs(eleNewHeight),\n x: nextX,\n y: nextY,\n points: rescaledPoints\n };\n\n if (\"scale\" in element && \"scale\" in stateAtResizeStart) {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isIframeLikeElement)(element)) {\n //zsviczian\n if (shouldMaintainAspectRatio) {\n const scale = [Math.abs(eleNewWidth / (stateAtResizeStart.width / stateAtResizeStart.scale[0])), Math.abs(eleNewHeight / (stateAtResizeStart.height / stateAtResizeStart.scale[1]))];\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n scale\n });\n }\n } else {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n scale: [// defaulting because scaleX/Y can be 0/-0\n (Math.sign(newBoundsX2 - stateAtResizeStart.x) || stateAtResizeStart.scale[0]) * stateAtResizeStart.scale[0], (Math.sign(newBoundsY2 - stateAtResizeStart.y) || stateAtResizeStart.scale[1]) * stateAtResizeStart.scale[1]]\n });\n }\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(element) && boundTextElement && shouldMaintainAspectRatio) {\n const fontSize = resizedElement.width / element.width * boundTextElement.fontSize;\n\n if (fontSize < _constants__WEBPACK_IMPORTED_MODULE_0__.MIN_FONT_SIZE) {\n return;\n }\n\n boundTextFont.fontSize = fontSize;\n }\n\n if (resizedElement.width !== 0 && resizedElement.height !== 0 && Number.isFinite(resizedElement.x) && Number.isFinite(resizedElement.y)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, resizedElement);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap, {\n oldSize: {\n width: stateAtResizeStart.width,\n height: stateAtResizeStart.height\n }\n });\n\n if (boundTextElement && boundTextFont != null) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(boundTextElement, {\n fontSize: boundTextFont.fontSize\n });\n }\n\n (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.handleBindTextResize)(element, elementsMap, transformHandleDirection, shouldMaintainAspectRatio);\n }\n};\nconst resizeMultipleElements = (originalElements, selectedElements, elementsMap, transformHandleType, shouldResizeFromCenter, shouldMaintainAspectRatio, pointerX, pointerY) => {\n var _a, _b, _c, _d; // map selected elements to the original elements. While it never should\n // happen that pointerDownState.originalElements won't contain the selected\n // elements during resize, this coupling isn't guaranteed, so to ensure\n // type safety we need to transform only those elements we filter.\n\n\n const targetElements = selectedElements.reduce((acc, element) => {\n const origElement = originalElements.get(element.id);\n\n if (origElement) {\n acc.push({\n orig: origElement,\n latest: element\n });\n }\n\n return acc;\n }, []); // getCommonBoundingBox() uses getBoundTextElement() which returns null for\n // original elements from pointerDownState, so we have to find and add these\n // bound text elements manually. Additionally, the coordinates of bound text\n // elements aren't always up to date.\n\n const boundTextElements = targetElements.reduce((acc, {\n orig\n }) => {\n var _a;\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(orig)) {\n return acc;\n }\n\n const textId = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElementId)(orig);\n\n if (!textId) {\n return acc;\n }\n\n const text = (_a = originalElements.get(textId)) !== null && _a !== void 0 ? _a : null;\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(text)) {\n return acc;\n }\n\n const xy = _linearElementEditor__WEBPACK_IMPORTED_MODULE_9__.LinearElementEditor.getBoundTextElementPosition(orig, text, elementsMap);\n return [...acc, Object.assign(Object.assign({}, text), xy)];\n }, []);\n const {\n minX,\n minY,\n maxX,\n maxY,\n midX,\n midY\n } = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getCommonBoundingBox)(targetElements.map(({\n orig\n }) => orig).concat(boundTextElements));\n const width = maxX - minX;\n const height = maxY - minY;\n const direction = transformHandleType;\n const anchorsMap = {\n ne: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(minX, maxY),\n se: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(minX, minY),\n sw: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(maxX, minY),\n nw: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(maxX, maxY),\n e: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(minX, minY + height / 2),\n w: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(maxX, minY + height / 2),\n n: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(minX + width / 2, maxY),\n s: (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(minX + width / 2, minY)\n }; // anchor point must be on the opposite side of the dragged selection handle\n // or be the center of the selection if shouldResizeFromCenter\n\n const [anchorX, anchorY] = shouldResizeFromCenter ? (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(midX, midY) : anchorsMap[direction];\n const resizeFromCenterScale = shouldResizeFromCenter ? 2 : 1;\n const scale = Math.max(Math.abs(pointerX - anchorX) / width || 0, Math.abs(pointerY - anchorY) / height || 0) * resizeFromCenterScale;\n\n if (scale === 0) {\n return;\n }\n\n let scaleX = direction.includes(\"e\") || direction.includes(\"w\") ? Math.abs(pointerX - anchorX) / width * resizeFromCenterScale : 1;\n let scaleY = direction.includes(\"n\") || direction.includes(\"s\") ? Math.abs(pointerY - anchorY) / height * resizeFromCenterScale : 1;\n const keepAspectRatio = shouldMaintainAspectRatio || targetElements.some(item => item.latest.angle !== 0 || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(item.latest) || (0,_groups__WEBPACK_IMPORTED_MODULE_10__.isInGroup)(item.latest));\n\n if (keepAspectRatio) {\n scaleX = scale;\n scaleY = scale;\n }\n\n const flipConditionsMap = {\n ne: [pointerX < anchorX, pointerY > anchorY],\n se: [pointerX < anchorX, pointerY < anchorY],\n sw: [pointerX > anchorX, pointerY < anchorY],\n nw: [pointerX > anchorX, pointerY > anchorY],\n // e.g. when resizing from the \"e\" side, we do not need to consider changes in the `y` direction\n // and therefore, we do not need to flip in the `y` direction at all\n e: [pointerX < anchorX, false],\n w: [pointerX > anchorX, false],\n n: [false, pointerY > anchorY],\n s: [false, pointerY < anchorY]\n };\n /**\n * to flip an element:\n * 1. determine over which axis is the element being flipped\n * (could be x, y, or both) indicated by `flipFactorX` & `flipFactorY`\n * 2. shift element's position by the amount of width or height (or both) or\n * mirror points in the case of linear & freedraw elemenets\n * 3. adjust element angle\n */\n\n const [flipFactorX, flipFactorY] = flipConditionsMap[direction].map(condition => condition ? -1 : 1);\n const isFlippedByX = flipFactorX < 0;\n const isFlippedByY = flipFactorY < 0;\n const elementsAndUpdates = [];\n\n for (const {\n orig,\n latest\n } of targetElements) {\n // bounded text elements are updated along with their container elements\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(orig) && (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(orig)) {\n continue;\n }\n\n const width = ((_a = orig.customData) === null || _a === void 0 ? void 0 : _a.isAnchored) ? orig.width : orig.width * scaleX; //zsviczian\n\n const height = ((_b = orig.customData) === null || _b === void 0 ? void 0 : _b.isAnchored) ? orig.height : orig.height * scaleY; //zsviczian\n\n const angle = (0,_math__WEBPACK_IMPORTED_MODULE_12__.normalizeRadians)(orig.angle * flipFactorX * flipFactorY);\n const isLinearOrFreeDraw = (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(orig) || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFreeDrawElement)(orig);\n const offsetX = orig.x - anchorX;\n const offsetY = orig.y - anchorY;\n const shiftX = isFlippedByX && !isLinearOrFreeDraw ? width : 0;\n const shiftY = isFlippedByY && !isLinearOrFreeDraw ? height : 0;\n const x = anchorX + flipFactorX * (offsetX * scaleX + shiftX);\n const y = anchorY + flipFactorY * (offsetY * scaleY + shiftY);\n const rescaledPoints = rescalePointsInElement(orig, width * flipFactorX, height * flipFactorY, false);\n const update = Object.assign({\n x,\n y,\n width,\n height,\n angle\n }, rescaledPoints);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isImageElement)(orig)) {\n update.scale = [orig.scale[0] * flipFactorX, orig.scale[1] * flipFactorY];\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(orig)) {\n const metrics = measureFontSizeFromWidth(orig, elementsMap, width);\n\n if (!metrics) {\n return;\n }\n\n update.fontSize = metrics.size;\n }\n\n const boundTextElement = originalElements.get((_c = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElementId)(orig)) !== null && _c !== void 0 ? _c : \"\");\n\n if (boundTextElement) {\n if (keepAspectRatio) {\n const newFontSize = boundTextElement.fontSize * scale;\n\n if (newFontSize < _constants__WEBPACK_IMPORTED_MODULE_0__.MIN_FONT_SIZE) {\n return;\n }\n\n update.boundTextFontSize = newFontSize;\n } else {\n update.boundTextFontSize = boundTextElement.fontSize;\n }\n }\n\n elementsAndUpdates.push({\n element: latest,\n update\n });\n }\n\n const elementsToUpdate = elementsAndUpdates.map(({\n element\n }) => element);\n\n for (let _e of elementsAndUpdates) {\n const {\n element\n } = _e,\n _f = _e.update,\n {\n boundTextFontSize\n } = _f,\n update = __rest(_f, [\"boundTextFontSize\"]);\n\n const {\n angle\n } = update;\n const {\n width: oldWidth,\n height: oldHeight\n } = element;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, update, false);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap, {\n simultaneouslyUpdated: elementsToUpdate,\n oldSize: {\n width: oldWidth,\n height: oldHeight\n }\n });\n const boundTextElement = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElement)(element, elementsMap);\n\n if (boundTextElement && boundTextFontSize) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(boundTextElement, {\n fontSize: boundTextFontSize,\n angle: (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(element) ? undefined : angle\n }, false);\n (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.handleBindTextResize)(element, elementsMap, transformHandleType, true);\n }\n }\n\n (_d = _scene_Scene__WEBPACK_IMPORTED_MODULE_7__[\"default\"].getScene(elementsAndUpdates[0].element)) === null || _d === void 0 ? void 0 : _d.triggerUpdate();\n};\n\nconst rotateMultipleElements = (originalElements, elements, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle, centerX, centerY) => {\n var _a;\n\n let centerAngle = 5 * Math.PI / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);\n\n if (shouldRotateWithDiscreteAngle) {\n centerAngle += _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE / 2;\n centerAngle -= centerAngle % _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE;\n }\n\n elements.filter(element => !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFrameLikeElement)(element)).forEach(element => {\n var _a, _b;\n\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const origAngle = (_b = (_a = originalElements.get(element.id)) === null || _a === void 0 ? void 0 : _a.angle) !== null && _b !== void 0 ? _b : element.angle;\n const [rotatedCX, rotatedCY] = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(cx, cy), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(centerX, centerY), centerAngle + origAngle - element.angle);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isElbowArrow)(element)) {\n const points = (0,_binding__WEBPACK_IMPORTED_MODULE_6__.getArrowLocalFixedPoints)(element, elementsMap);\n (0,_routing__WEBPACK_IMPORTED_MODULE_11__.mutateElbowArrow)(element, elementsMap, points);\n } else {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n x: element.x + (rotatedCX - cx),\n y: element.y + (rotatedCY - cy),\n angle: (0,_math__WEBPACK_IMPORTED_MODULE_12__.normalizeRadians)(centerAngle + origAngle)\n }, false);\n }\n\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap, {\n simultaneouslyUpdated: elements\n });\n const boundText = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElement)(element, elementsMap);\n\n if (boundText && !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(element)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(boundText, {\n x: boundText.x + (rotatedCX - cx),\n y: boundText.y + (rotatedCY - cy),\n angle: (0,_math__WEBPACK_IMPORTED_MODULE_12__.normalizeRadians)(centerAngle + origAngle)\n }, false);\n }\n });\n (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_7__[\"default\"].getScene(elements[0])) === null || _a === void 0 ? void 0 : _a.triggerUpdate();\n};\n\nconst getResizeOffsetXY = (transformHandleType, selectedElements, elementsMap, x, y) => {\n const [x1, y1, x2, y2] = selectedElements.length === 1 ? (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(selectedElements[0], elementsMap) : (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getCommonBounds)(selectedElements);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const angle = selectedElements.length === 1 ? selectedElements[0].angle : 0;\n [x, y] = (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x, y), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(cx, cy), -angle);\n\n switch (transformHandleType) {\n case \"n\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - (x1 + x2) / 2, y - y1), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"s\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - (x1 + x2) / 2, y - y2), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"w\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - x1, y - (y1 + y2) / 2), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"e\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - x2, y - (y1 + y2) / 2), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"nw\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - x1, y - y1), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"ne\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - x2, y - y1), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"sw\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - x1, y - y2), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n case \"se\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(x - x2, y - y2), (0,_math__WEBPACK_IMPORTED_MODULE_12__.pointFrom)(0, 0), angle);\n\n default:\n return [0, 0];\n }\n};\nconst getResizeArrowDirection = (transformHandleType, element) => {\n const [, [px, py]] = element.points;\n const isResizeEnd = transformHandleType === \"nw\" && (px < 0 || py < 0) || transformHandleType === \"ne\" && px >= 0 || transformHandleType === \"sw\" && px <= 0 || transformHandleType === \"se\" && (px > 0 || py > 0);\n return isResizeEnd ? \"end\" : \"origin\";\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/resizeElements.ts?");
2962
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"getResizeArrowDirection\": () => (/* binding */ getResizeArrowDirection),\n/* harmony export */ \"getResizeOffsetXY\": () => (/* binding */ getResizeOffsetXY),\n/* harmony export */ \"measureFontSizeFromWidth\": () => (/* binding */ measureFontSizeFromWidth),\n/* harmony export */ \"rescalePointsInElement\": () => (/* binding */ rescalePointsInElement),\n/* harmony export */ \"resizeMultipleElements\": () => (/* binding */ resizeMultipleElements),\n/* harmony export */ \"resizeSingleElement\": () => (/* binding */ resizeSingleElement),\n/* harmony export */ \"transformElements\": () => (/* binding */ transformElements)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _points__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../points */ \"./points.ts\");\n/* harmony import */ var _bounds__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _binding__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./binding */ \"./element/binding.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _textWrapping__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _groups__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../groups */ \"./groups.ts\");\n/* harmony import */ var _routing__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./routing */ \"./element/routing.ts\");\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../math */ \"../math/index.ts\");\nvar __rest = undefined && undefined.__rest || function (s, e) {\n var t = {};\n\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];\n\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];\n }\n return t;\n};\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n // Returns true when transform (resizing/rotation) happened\n\nconst transformElements = (originalElements, transformHandleType, selectedElements, elementsMap, shouldRotateWithDiscreteAngle, shouldResizeFromCenter, shouldMaintainAspectRatio, pointerX, pointerY, centerX, centerY) => {\n if (selectedElements.length === 1) {\n const [element] = selectedElements;\n\n if (transformHandleType === \"rotation\") {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isElbowArrow)(element)) {\n rotateSingleElement(element, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap);\n }\n } else if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(element) && transformHandleType) {\n resizeSingleTextElement(originalElements, element, elementsMap, transformHandleType, shouldResizeFromCenter, pointerX, pointerY);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap);\n } else if (transformHandleType) {\n resizeSingleElement(originalElements, shouldMaintainAspectRatio, element, elementsMap, transformHandleType, shouldResizeFromCenter, pointerX, pointerY);\n }\n\n return true;\n } else if (selectedElements.length > 1) {\n if (transformHandleType === \"rotation\") {\n rotateMultipleElements(originalElements, selectedElements, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle, centerX, centerY);\n return true;\n } else if (transformHandleType) {\n resizeMultipleElements(originalElements, selectedElements, elementsMap, transformHandleType, shouldResizeFromCenter, shouldMaintainAspectRatio, pointerX, pointerY);\n return true;\n }\n }\n\n return false;\n};\n\nconst rotateSingleElement = (element, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle) => {\n var _a;\n\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n let angle;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFrameLikeElement)(element)) {\n angle = 0;\n } else {\n angle = 5 * Math.PI / 2 + Math.atan2(pointerY - cy, pointerX - cx);\n\n if (shouldRotateWithDiscreteAngle) {\n angle = angle + _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE / 2;\n angle = angle - angle % _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE;\n }\n\n angle = (0,_math__WEBPACK_IMPORTED_MODULE_13__.normalizeRadians)(angle);\n }\n\n const boundTextElementId = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElementId)(element);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n angle\n });\n\n if (boundTextElementId) {\n const textElement = (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_7__[\"default\"].getScene(element)) === null || _a === void 0 ? void 0 : _a.getElement(boundTextElementId);\n\n if (textElement && !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(element)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(textElement, {\n angle\n });\n }\n }\n};\n\nconst rescalePointsInElement = (element, width, height, normalizePoints) => (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(element) || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFreeDrawElement)(element) ? {\n points: (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(0, width, (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(1, height, element.points, normalizePoints), normalizePoints)\n} : {};\nconst measureFontSizeFromWidth = (element, elementsMap, nextWidth) => {\n // We only use width to scale font on resize\n let width = element.width;\n const hasContainer = (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(element);\n\n if (hasContainer) {\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getContainerElement)(element, elementsMap);\n\n if (container) {\n width = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextMaxWidth)(container, element);\n }\n }\n\n const nextFontSize = element.fontSize * (nextWidth / width);\n\n if (nextFontSize < _constants__WEBPACK_IMPORTED_MODULE_0__.MIN_FONT_SIZE) {\n return null;\n }\n\n return {\n size: nextFontSize\n };\n};\n\nconst resizeSingleTextElement = (originalElements, element, elementsMap, transformHandleType, shouldResizeFromCenter, pointerX, pointerY) => {\n const [x1, y1, x2, y2, cx, cy] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(element, elementsMap); // rotation pointer with reverse angle\n\n const [rotatedX, rotatedY] = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(pointerX, pointerY), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(cx, cy), -element.angle);\n let scaleX = 0;\n let scaleY = 0;\n\n if (transformHandleType !== \"e\" && transformHandleType !== \"w\") {\n if (transformHandleType.includes(\"e\")) {\n scaleX = (rotatedX - x1) / (x2 - x1);\n }\n\n if (transformHandleType.includes(\"w\")) {\n scaleX = (x2 - rotatedX) / (x2 - x1);\n }\n\n if (transformHandleType.includes(\"n\")) {\n scaleY = (y2 - rotatedY) / (y2 - y1);\n }\n\n if (transformHandleType.includes(\"s\")) {\n scaleY = (rotatedY - y1) / (y2 - y1);\n }\n }\n\n const scale = Math.max(scaleX, scaleY);\n\n if (scale > 0) {\n const nextWidth = element.width * scale;\n const nextHeight = element.height * scale;\n const metrics = measureFontSizeFromWidth(element, elementsMap, nextWidth);\n\n if (metrics === null) {\n return;\n }\n\n const startTopLeft = [x1, y1];\n const startBottomRight = [x2, y2];\n const startCenter = [cx, cy];\n let newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x1, y1);\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandleType)) {\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(startBottomRight[0] - Math.abs(nextWidth), startBottomRight[1] - Math.abs(nextHeight));\n }\n\n if (transformHandleType === \"ne\") {\n const bottomLeft = [startTopLeft[0], startBottomRight[1]];\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(bottomLeft[0], bottomLeft[1] - Math.abs(nextHeight));\n }\n\n if (transformHandleType === \"sw\") {\n const topRight = [startBottomRight[0], startTopLeft[1]];\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(topRight[0] - Math.abs(nextWidth), topRight[1]);\n }\n\n if ([\"s\", \"n\"].includes(transformHandleType)) {\n newTopLeft[0] = startCenter[0] - nextWidth / 2;\n }\n\n if ([\"e\", \"w\"].includes(transformHandleType)) {\n newTopLeft[1] = startCenter[1] - nextHeight / 2;\n }\n\n if (shouldResizeFromCenter) {\n newTopLeft[0] = startCenter[0] - Math.abs(nextWidth) / 2;\n newTopLeft[1] = startCenter[1] - Math.abs(nextHeight) / 2;\n }\n\n const angle = element.angle;\n const rotatedTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(newTopLeft, (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(cx, cy), angle);\n const newCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(newTopLeft[0] + Math.abs(nextWidth) / 2, newTopLeft[1] + Math.abs(nextHeight) / 2);\n const rotatedNewCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(newCenter, (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(cx, cy), angle);\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(rotatedTopLeft, rotatedNewCenter, -angle);\n const [nextX, nextY] = newTopLeft;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n fontSize: metrics.size,\n width: nextWidth,\n height: nextHeight,\n x: nextX,\n y: nextY\n });\n }\n\n if (transformHandleType === \"e\" || transformHandleType === \"w\") {\n const stateAtResizeStart = originalElements.get(element.id);\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, stateAtResizeStart.width, stateAtResizeStart.height, true);\n const startTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x1, y1);\n const startBottomRight = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x2, y2);\n const startCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointCenter)(startTopLeft, startBottomRight);\n const rotatedPointer = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(pointerX, pointerY), startCenter, -stateAtResizeStart.angle);\n const [esx1,, esx2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(element, element.width, element.height, true);\n const boundsCurrentWidth = esx2 - esx1;\n const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];\n const minWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getMinTextElementWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)({\n fontSize: element.fontSize,\n fontFamily: element.fontFamily\n }), element.lineHeight);\n let scaleX = atStartBoundsWidth / boundsCurrentWidth;\n\n if (transformHandleType.includes(\"e\")) {\n scaleX = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;\n }\n\n if (transformHandleType.includes(\"w\")) {\n scaleX = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;\n }\n\n const newWidth = element.width * scaleX < minWidth ? minWidth : element.width * scaleX;\n const text = (0,_textWrapping__WEBPACK_IMPORTED_MODULE_9__.wrapText)(element.originalText, (0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(element), Math.abs(newWidth));\n const metrics = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.measureText)(text, (0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(element), element.lineHeight);\n const eleNewHeight = metrics.height;\n const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, newWidth, eleNewHeight, true);\n const newBoundsWidth = newBoundsX2 - newBoundsX1;\n const newBoundsHeight = newBoundsY2 - newBoundsY1;\n let newTopLeft = [...startTopLeft];\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandleType)) {\n newTopLeft = [startBottomRight[0] - Math.abs(newBoundsWidth), startTopLeft[1]];\n } // adjust topLeft to new rotation point\n\n\n const angle = stateAtResizeStart.angle;\n const rotatedTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFromPair)(newTopLeft), startCenter, angle);\n const newCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(newTopLeft[0] + Math.abs(newBoundsWidth) / 2, newTopLeft[1] + Math.abs(newBoundsHeight) / 2);\n const rotatedNewCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(newCenter, startCenter, angle);\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(rotatedTopLeft, rotatedNewCenter, -angle);\n const resizedElement = {\n width: Math.abs(newWidth),\n height: Math.abs(metrics.height),\n x: newTopLeft[0],\n y: newTopLeft[1],\n text,\n autoResize: false\n };\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, resizedElement);\n }\n};\n\nconst resizeSingleElement = (originalElements, shouldMaintainAspectRatio, element, elementsMap, transformHandleDirection, shouldResizeFromCenter, pointerX, pointerY) => {\n var _a;\n\n if ((_a = element.customData) === null || _a === void 0 ? void 0 : _a.isAnchored) {\n return;\n } //zsviczian\n\n\n const stateAtResizeStart = originalElements.get(element.id); // Gets bounds corners\n\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, stateAtResizeStart.width, stateAtResizeStart.height, true);\n const startTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x1, y1);\n const startBottomRight = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x2, y2);\n const startCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointCenter)(startTopLeft, startBottomRight); // Calculate new dimensions based on cursor position\n\n const rotatedPointer = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(pointerX, pointerY), startCenter, -stateAtResizeStart.angle); // Get bounds corners rendered on screen\n\n const [esx1, esy1, esx2, esy2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(element, element.width, element.height, true);\n const boundsCurrentWidth = esx2 - esx1;\n const boundsCurrentHeight = esy2 - esy1; // It's important we set the initial scale value based on the width and height at resize start,\n // otherwise previous dimensions affected by modifiers will be taken into account.\n\n const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];\n const atStartBoundsHeight = startBottomRight[1] - startTopLeft[1];\n let scaleX = atStartBoundsWidth / boundsCurrentWidth;\n let scaleY = atStartBoundsHeight / boundsCurrentHeight;\n let boundTextFont = {};\n const boundTextElement = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElement)(element, elementsMap);\n\n if (transformHandleDirection.includes(\"e\")) {\n scaleX = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;\n }\n\n if (transformHandleDirection.includes(\"s\")) {\n scaleY = (rotatedPointer[1] - startTopLeft[1]) / boundsCurrentHeight;\n }\n\n if (transformHandleDirection.includes(\"w\")) {\n scaleX = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;\n }\n\n if (transformHandleDirection.includes(\"n\")) {\n scaleY = (startBottomRight[1] - rotatedPointer[1]) / boundsCurrentHeight;\n } // Linear elements dimensions differ from bounds dimensions\n\n\n const eleInitialWidth = stateAtResizeStart.width;\n const eleInitialHeight = stateAtResizeStart.height; // We have to use dimensions of element on screen, otherwise the scaling of the\n // dimensions won't match the cursor for linear elements.\n\n let eleNewWidth = element.width * scaleX;\n let eleNewHeight = element.height * scaleY; // adjust dimensions for resizing from center\n\n if (shouldResizeFromCenter) {\n eleNewWidth = 2 * eleNewWidth - eleInitialWidth;\n eleNewHeight = 2 * eleNewHeight - eleInitialHeight;\n } // adjust dimensions to keep sides ratio\n\n\n if (shouldMaintainAspectRatio) {\n const widthRatio = Math.abs(eleNewWidth) / eleInitialWidth;\n const heightRatio = Math.abs(eleNewHeight) / eleInitialHeight;\n\n if (transformHandleDirection.length === 1) {\n eleNewHeight *= widthRatio;\n eleNewWidth *= heightRatio;\n }\n\n if (transformHandleDirection.length === 2) {\n const ratio = Math.max(widthRatio, heightRatio);\n eleNewWidth = eleInitialWidth * ratio * Math.sign(eleNewWidth);\n eleNewHeight = eleInitialHeight * ratio * Math.sign(eleNewHeight);\n }\n }\n\n if (boundTextElement) {\n const stateOfBoundTextElementAtResize = originalElements.get(boundTextElement.id);\n\n if (stateOfBoundTextElementAtResize) {\n boundTextFont = {\n fontSize: stateOfBoundTextElementAtResize.fontSize\n };\n }\n\n if (shouldMaintainAspectRatio) {\n const updatedElement = Object.assign(Object.assign({}, element), {\n width: eleNewWidth,\n height: eleNewHeight\n });\n const nextFont = measureFontSizeFromWidth(boundTextElement, elementsMap, (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextMaxWidth)(updatedElement, boundTextElement));\n\n if (nextFont === null) {\n return;\n }\n\n boundTextFont = {\n fontSize: nextFont.size\n };\n } else {\n const minWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getApproxMinLineWidth)((0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(boundTextElement), boundTextElement.lineHeight);\n const minHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getApproxMinLineHeight)(boundTextElement.fontSize, boundTextElement.lineHeight);\n eleNewWidth = Math.max(eleNewWidth, minWidth);\n eleNewHeight = Math.max(eleNewHeight, minHeight);\n }\n }\n\n const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getResizedElementAbsoluteCoords)(stateAtResizeStart, eleNewWidth, eleNewHeight, true);\n const newBoundsWidth = newBoundsX2 - newBoundsX1;\n const newBoundsHeight = newBoundsY2 - newBoundsY1; // Calculate new topLeft based on fixed corner during resize\n\n let newTopLeft = [...startTopLeft];\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandleDirection)) {\n newTopLeft = [startBottomRight[0] - Math.abs(newBoundsWidth), startBottomRight[1] - Math.abs(newBoundsHeight)];\n }\n\n if (transformHandleDirection === \"ne\") {\n const bottomLeft = [startTopLeft[0], startBottomRight[1]];\n newTopLeft = [bottomLeft[0], bottomLeft[1] - Math.abs(newBoundsHeight)];\n }\n\n if (transformHandleDirection === \"sw\") {\n const topRight = [startBottomRight[0], startTopLeft[1]];\n newTopLeft = [topRight[0] - Math.abs(newBoundsWidth), topRight[1]];\n } // Keeps opposite handle fixed during resize\n\n\n if (shouldMaintainAspectRatio) {\n if ([\"s\", \"n\"].includes(transformHandleDirection)) {\n newTopLeft[0] = startCenter[0] - newBoundsWidth / 2;\n }\n\n if ([\"e\", \"w\"].includes(transformHandleDirection)) {\n newTopLeft[1] = startCenter[1] - newBoundsHeight / 2;\n }\n }\n\n const flipX = eleNewWidth < 0;\n const flipY = eleNewHeight < 0; // Flip horizontally\n\n if (flipX) {\n if (transformHandleDirection.includes(\"e\")) {\n newTopLeft[0] -= Math.abs(newBoundsWidth);\n }\n\n if (transformHandleDirection.includes(\"w\")) {\n newTopLeft[0] += Math.abs(newBoundsWidth);\n }\n } // Flip vertically\n\n\n if (flipY) {\n if (transformHandleDirection.includes(\"s\")) {\n newTopLeft[1] -= Math.abs(newBoundsHeight);\n }\n\n if (transformHandleDirection.includes(\"n\")) {\n newTopLeft[1] += Math.abs(newBoundsHeight);\n }\n }\n\n if (shouldResizeFromCenter) {\n newTopLeft[0] = startCenter[0] - Math.abs(newBoundsWidth) / 2;\n newTopLeft[1] = startCenter[1] - Math.abs(newBoundsHeight) / 2;\n } // adjust topLeft to new rotation point\n\n\n const angle = stateAtResizeStart.angle;\n const rotatedTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFromPair)(newTopLeft), startCenter, angle);\n const newCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(newTopLeft[0] + Math.abs(newBoundsWidth) / 2, newTopLeft[1] + Math.abs(newBoundsHeight) / 2);\n const rotatedNewCenter = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(newCenter, startCenter, angle);\n newTopLeft = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)(rotatedTopLeft, rotatedNewCenter, -angle); // For linear elements (x,y) are the coordinates of the first drawn point not the top-left corner\n // So we need to readjust (x,y) to be where the first point should be\n\n const newOrigin = [...newTopLeft];\n const linearElementXOffset = stateAtResizeStart.x - newBoundsX1;\n const linearElementYOffset = stateAtResizeStart.y - newBoundsY1;\n newOrigin[0] += linearElementXOffset;\n newOrigin[1] += linearElementYOffset;\n const nextX = newOrigin[0];\n const nextY = newOrigin[1]; // Readjust points for linear elements\n\n let rescaledElementPointsY;\n let rescaledPoints;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(element) || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFreeDrawElement)(element)) {\n rescaledElementPointsY = (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(1, eleNewHeight, stateAtResizeStart.points, true);\n rescaledPoints = (0,_points__WEBPACK_IMPORTED_MODULE_1__.rescalePoints)(0, eleNewWidth, rescaledElementPointsY, true);\n }\n\n const resizedElement = {\n width: Math.abs(eleNewWidth),\n height: Math.abs(eleNewHeight),\n x: nextX,\n y: nextY,\n points: rescaledPoints\n };\n\n if (\"scale\" in element && \"scale\" in stateAtResizeStart) {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isIframeLikeElement)(element)) {\n //zsviczian\n if (shouldMaintainAspectRatio) {\n const scale = [Math.abs(eleNewWidth / (stateAtResizeStart.width / stateAtResizeStart.scale[0])), Math.abs(eleNewHeight / (stateAtResizeStart.height / stateAtResizeStart.scale[1]))];\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n scale\n });\n }\n } else {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n scale: [// defaulting because scaleX/Y can be 0/-0\n (Math.sign(newBoundsX2 - stateAtResizeStart.x) || stateAtResizeStart.scale[0]) * stateAtResizeStart.scale[0], (Math.sign(newBoundsY2 - stateAtResizeStart.y) || stateAtResizeStart.scale[1]) * stateAtResizeStart.scale[1]]\n });\n }\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(element) && boundTextElement && shouldMaintainAspectRatio) {\n const fontSize = resizedElement.width / element.width * boundTextElement.fontSize;\n\n if (fontSize < _constants__WEBPACK_IMPORTED_MODULE_0__.MIN_FONT_SIZE) {\n return;\n }\n\n boundTextFont.fontSize = fontSize;\n }\n\n if (resizedElement.width !== 0 && resizedElement.height !== 0 && Number.isFinite(resizedElement.x) && Number.isFinite(resizedElement.y)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, resizedElement);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap, {\n oldSize: {\n width: stateAtResizeStart.width,\n height: stateAtResizeStart.height\n }\n });\n\n if (boundTextElement && boundTextFont != null) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(boundTextElement, {\n fontSize: boundTextFont.fontSize\n });\n }\n\n (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.handleBindTextResize)(element, elementsMap, transformHandleDirection, shouldMaintainAspectRatio);\n }\n};\nconst resizeMultipleElements = (originalElements, selectedElements, elementsMap, transformHandleType, shouldResizeFromCenter, shouldMaintainAspectRatio, pointerX, pointerY) => {\n var _a, _b, _c, _d; // map selected elements to the original elements. While it never should\n // happen that pointerDownState.originalElements won't contain the selected\n // elements during resize, this coupling isn't guaranteed, so to ensure\n // type safety we need to transform only those elements we filter.\n\n\n const targetElements = selectedElements.reduce((acc, element) => {\n const origElement = originalElements.get(element.id);\n\n if (origElement) {\n acc.push({\n orig: origElement,\n latest: element\n });\n }\n\n return acc;\n }, []); // getCommonBoundingBox() uses getBoundTextElement() which returns null for\n // original elements from pointerDownState, so we have to find and add these\n // bound text elements manually. Additionally, the coordinates of bound text\n // elements aren't always up to date.\n\n const boundTextElements = targetElements.reduce((acc, {\n orig\n }) => {\n var _a;\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(orig)) {\n return acc;\n }\n\n const textId = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElementId)(orig);\n\n if (!textId) {\n return acc;\n }\n\n const text = (_a = originalElements.get(textId)) !== null && _a !== void 0 ? _a : null;\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(text)) {\n return acc;\n }\n\n const xy = _linearElementEditor__WEBPACK_IMPORTED_MODULE_10__.LinearElementEditor.getBoundTextElementPosition(orig, text, elementsMap);\n return [...acc, Object.assign(Object.assign({}, text), xy)];\n }, []);\n const {\n minX,\n minY,\n maxX,\n maxY,\n midX,\n midY\n } = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getCommonBoundingBox)(targetElements.map(({\n orig\n }) => orig).concat(boundTextElements));\n const width = maxX - minX;\n const height = maxY - minY;\n const direction = transformHandleType;\n const anchorsMap = {\n ne: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(minX, maxY),\n se: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(minX, minY),\n sw: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(maxX, minY),\n nw: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(maxX, maxY),\n e: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(minX, minY + height / 2),\n w: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(maxX, minY + height / 2),\n n: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(minX + width / 2, maxY),\n s: (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(minX + width / 2, minY)\n }; // anchor point must be on the opposite side of the dragged selection handle\n // or be the center of the selection if shouldResizeFromCenter\n\n const [anchorX, anchorY] = shouldResizeFromCenter ? (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(midX, midY) : anchorsMap[direction];\n const resizeFromCenterScale = shouldResizeFromCenter ? 2 : 1;\n const scale = Math.max(Math.abs(pointerX - anchorX) / width || 0, Math.abs(pointerY - anchorY) / height || 0) * resizeFromCenterScale;\n\n if (scale === 0) {\n return;\n }\n\n let scaleX = direction.includes(\"e\") || direction.includes(\"w\") ? Math.abs(pointerX - anchorX) / width * resizeFromCenterScale : 1;\n let scaleY = direction.includes(\"n\") || direction.includes(\"s\") ? Math.abs(pointerY - anchorY) / height * resizeFromCenterScale : 1;\n const keepAspectRatio = shouldMaintainAspectRatio || targetElements.some(item => item.latest.angle !== 0 || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(item.latest) || (0,_groups__WEBPACK_IMPORTED_MODULE_11__.isInGroup)(item.latest));\n\n if (keepAspectRatio) {\n scaleX = scale;\n scaleY = scale;\n }\n\n const flipConditionsMap = {\n ne: [pointerX < anchorX, pointerY > anchorY],\n se: [pointerX < anchorX, pointerY < anchorY],\n sw: [pointerX > anchorX, pointerY < anchorY],\n nw: [pointerX > anchorX, pointerY > anchorY],\n // e.g. when resizing from the \"e\" side, we do not need to consider changes in the `y` direction\n // and therefore, we do not need to flip in the `y` direction at all\n e: [pointerX < anchorX, false],\n w: [pointerX > anchorX, false],\n n: [false, pointerY > anchorY],\n s: [false, pointerY < anchorY]\n };\n /**\n * to flip an element:\n * 1. determine over which axis is the element being flipped\n * (could be x, y, or both) indicated by `flipFactorX` & `flipFactorY`\n * 2. shift element's position by the amount of width or height (or both) or\n * mirror points in the case of linear & freedraw elemenets\n * 3. adjust element angle\n */\n\n const [flipFactorX, flipFactorY] = flipConditionsMap[direction].map(condition => condition ? -1 : 1);\n const isFlippedByX = flipFactorX < 0;\n const isFlippedByY = flipFactorY < 0;\n const elementsAndUpdates = [];\n\n for (const {\n orig,\n latest\n } of targetElements) {\n // bounded text elements are updated along with their container elements\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(orig) && (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(orig)) {\n continue;\n }\n\n const width = ((_a = orig.customData) === null || _a === void 0 ? void 0 : _a.isAnchored) ? orig.width : orig.width * scaleX; //zsviczian\n\n const height = ((_b = orig.customData) === null || _b === void 0 ? void 0 : _b.isAnchored) ? orig.height : orig.height * scaleY; //zsviczian\n\n const angle = (0,_math__WEBPACK_IMPORTED_MODULE_13__.normalizeRadians)(orig.angle * flipFactorX * flipFactorY);\n const isLinearOrFreeDraw = (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(orig) || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFreeDrawElement)(orig);\n const offsetX = orig.x - anchorX;\n const offsetY = orig.y - anchorY;\n const shiftX = isFlippedByX && !isLinearOrFreeDraw ? width : 0;\n const shiftY = isFlippedByY && !isLinearOrFreeDraw ? height : 0;\n const x = anchorX + flipFactorX * (offsetX * scaleX + shiftX);\n const y = anchorY + flipFactorY * (offsetY * scaleY + shiftY);\n const rescaledPoints = rescalePointsInElement(orig, width * flipFactorX, height * flipFactorY, false);\n const update = Object.assign({\n x,\n y,\n width,\n height,\n angle\n }, rescaledPoints);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isImageElement)(orig)) {\n update.scale = [orig.scale[0] * flipFactorX, orig.scale[1] * flipFactorY];\n }\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(orig)) {\n const metrics = measureFontSizeFromWidth(orig, elementsMap, width);\n\n if (!metrics) {\n return;\n }\n\n update.fontSize = metrics.size;\n }\n\n const boundTextElement = originalElements.get((_c = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElementId)(orig)) !== null && _c !== void 0 ? _c : \"\");\n\n if (boundTextElement) {\n if (keepAspectRatio) {\n const newFontSize = boundTextElement.fontSize * scale;\n\n if (newFontSize < _constants__WEBPACK_IMPORTED_MODULE_0__.MIN_FONT_SIZE) {\n return;\n }\n\n update.boundTextFontSize = newFontSize;\n } else {\n update.boundTextFontSize = boundTextElement.fontSize;\n }\n }\n\n elementsAndUpdates.push({\n element: latest,\n update\n });\n }\n\n const elementsToUpdate = elementsAndUpdates.map(({\n element\n }) => element);\n\n for (let _e of elementsAndUpdates) {\n const {\n element\n } = _e,\n _f = _e.update,\n {\n boundTextFontSize\n } = _f,\n update = __rest(_f, [\"boundTextFontSize\"]);\n\n const {\n angle\n } = update;\n const {\n width: oldWidth,\n height: oldHeight\n } = element;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, update, false);\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap, {\n simultaneouslyUpdated: elementsToUpdate,\n oldSize: {\n width: oldWidth,\n height: oldHeight\n }\n });\n const boundTextElement = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElement)(element, elementsMap);\n\n if (boundTextElement && boundTextFontSize) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(boundTextElement, {\n fontSize: boundTextFontSize,\n angle: (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isLinearElement)(element) ? undefined : angle\n }, false);\n (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.handleBindTextResize)(element, elementsMap, transformHandleType, true);\n }\n }\n\n (_d = _scene_Scene__WEBPACK_IMPORTED_MODULE_7__[\"default\"].getScene(elementsAndUpdates[0].element)) === null || _d === void 0 ? void 0 : _d.triggerUpdate();\n};\n\nconst rotateMultipleElements = (originalElements, elements, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle, centerX, centerY) => {\n var _a;\n\n let centerAngle = 5 * Math.PI / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);\n\n if (shouldRotateWithDiscreteAngle) {\n centerAngle += _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE / 2;\n centerAngle -= centerAngle % _constants__WEBPACK_IMPORTED_MODULE_0__.SHIFT_LOCKING_ANGLE;\n }\n\n elements.filter(element => !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isFrameLikeElement)(element)).forEach(element => {\n var _a, _b;\n\n const [x1, y1, x2, y2] = (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const origAngle = (_b = (_a = originalElements.get(element.id)) === null || _a === void 0 ? void 0 : _a.angle) !== null && _b !== void 0 ? _b : element.angle;\n const [rotatedCX, rotatedCY] = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(cx, cy), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(centerX, centerY), centerAngle + origAngle - element.angle);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isElbowArrow)(element)) {\n const points = (0,_binding__WEBPACK_IMPORTED_MODULE_6__.getArrowLocalFixedPoints)(element, elementsMap);\n (0,_routing__WEBPACK_IMPORTED_MODULE_12__.mutateElbowArrow)(element, elementsMap, points);\n } else {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(element, {\n x: element.x + (rotatedCX - cx),\n y: element.y + (rotatedCY - cy),\n angle: (0,_math__WEBPACK_IMPORTED_MODULE_13__.normalizeRadians)(centerAngle + origAngle)\n }, false);\n }\n\n (0,_binding__WEBPACK_IMPORTED_MODULE_6__.updateBoundElements)(element, elementsMap, {\n simultaneouslyUpdated: elements\n });\n const boundText = (0,_textElement__WEBPACK_IMPORTED_MODULE_8__.getBoundTextElement)(element, elementsMap);\n\n if (boundText && !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(element)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_4__.mutateElement)(boundText, {\n x: boundText.x + (rotatedCX - cx),\n y: boundText.y + (rotatedCY - cy),\n angle: (0,_math__WEBPACK_IMPORTED_MODULE_13__.normalizeRadians)(centerAngle + origAngle)\n }, false);\n }\n });\n (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_7__[\"default\"].getScene(elements[0])) === null || _a === void 0 ? void 0 : _a.triggerUpdate();\n};\n\nconst getResizeOffsetXY = (transformHandleType, selectedElements, elementsMap, x, y) => {\n const [x1, y1, x2, y2] = selectedElements.length === 1 ? (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getElementAbsoluteCoords)(selectedElements[0], elementsMap) : (0,_bounds__WEBPACK_IMPORTED_MODULE_2__.getCommonBounds)(selectedElements);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const angle = selectedElements.length === 1 ? selectedElements[0].angle : 0;\n [x, y] = (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x, y), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(cx, cy), -angle);\n\n switch (transformHandleType) {\n case \"n\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - (x1 + x2) / 2, y - y1), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"s\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - (x1 + x2) / 2, y - y2), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"w\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - x1, y - (y1 + y2) / 2), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"e\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - x2, y - (y1 + y2) / 2), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"nw\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - x1, y - y1), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"ne\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - x2, y - y1), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"sw\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - x1, y - y2), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n case \"se\":\n return (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointRotateRads)((0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(x - x2, y - y2), (0,_math__WEBPACK_IMPORTED_MODULE_13__.pointFrom)(0, 0), angle);\n\n default:\n return [0, 0];\n }\n};\nconst getResizeArrowDirection = (transformHandleType, element) => {\n const [, [px, py]] = element.points;\n const isResizeEnd = transformHandleType === \"nw\" && (px < 0 || py < 0) || transformHandleType === \"ne\" && px >= 0 || transformHandleType === \"sw\" && px <= 0 || transformHandleType === \"se\" && (px > 0 || py > 0);\n return isResizeEnd ? \"end\" : \"origin\";\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/resizeElements.ts?");
2963
2963
 
2964
2964
  /***/ }),
2965
2965
 
@@ -3025,7 +3025,18 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3025
3025
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3026
3026
 
3027
3027
  "use strict";
3028
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"bindTextToShapeAfterDuplication\": () => (/* binding */ bindTextToShapeAfterDuplication),\n/* harmony export */ \"charWidth\": () => (/* binding */ charWidth),\n/* harmony export */ \"computeBoundTextPosition\": () => (/* binding */ computeBoundTextPosition),\n/* harmony export */ \"computeContainerDimensionForBoundText\": () => (/* binding */ computeContainerDimensionForBoundText),\n/* harmony export */ \"containsCJK\": () => (/* binding */ containsCJK),\n/* harmony export */ \"containsEmoji\": () => (/* binding */ containsEmoji),\n/* harmony export */ \"detectLineHeight\": () => (/* binding */ detectLineHeight),\n/* harmony export */ \"getApproxMinLineHeight\": () => (/* binding */ getApproxMinLineHeight),\n/* harmony export */ \"getApproxMinLineWidth\": () => (/* binding */ getApproxMinLineWidth),\n/* harmony export */ \"getBoundTextElement\": () => (/* binding */ getBoundTextElement),\n/* harmony export */ \"getBoundTextElementId\": () => (/* binding */ getBoundTextElementId),\n/* harmony export */ \"getBoundTextElementPosition\": () => (/* binding */ getBoundTextElementPosition),\n/* harmony export */ \"getBoundTextMaxHeight\": () => (/* binding */ getBoundTextMaxHeight),\n/* harmony export */ \"getBoundTextMaxWidth\": () => (/* binding */ getBoundTextMaxWidth),\n/* harmony export */ \"getContainerCenter\": () => (/* binding */ getContainerCenter),\n/* harmony export */ \"getContainerCoords\": () => (/* binding */ getContainerCoords),\n/* harmony export */ \"getContainerElement\": () => (/* binding */ getContainerElement),\n/* harmony export */ \"getLineHeightInPx\": () => (/* binding */ getLineHeightInPx),\n/* harmony export */ \"getMaxCharWidth\": () => (/* binding */ getMaxCharWidth),\n/* harmony export */ \"getMinCharWidth\": () => (/* binding */ getMinCharWidth),\n/* harmony export */ \"getMinTextElementWidth\": () => (/* binding */ getMinTextElementWidth),\n/* harmony export */ \"getTextElementAngle\": () => (/* binding */ getTextElementAngle),\n/* harmony export */ \"getTextFromElements\": () => (/* binding */ getTextFromElements),\n/* harmony export */ \"getTextHeight\": () => (/* binding */ getTextHeight),\n/* harmony export */ \"getTextWidth\": () => (/* binding */ getTextWidth),\n/* harmony export */ \"handleBindTextResize\": () => (/* binding */ handleBindTextResize),\n/* harmony export */ \"isMeasureTextSupported\": () => (/* binding */ isMeasureTextSupported),\n/* harmony export */ \"isValidTextContainer\": () => (/* binding */ isValidTextContainer),\n/* harmony export */ \"measureText\": () => (/* binding */ measureText),\n/* harmony export */ \"normalizeText\": () => (/* binding */ normalizeText),\n/* harmony export */ \"parseTokens\": () => (/* binding */ parseTokens),\n/* harmony export */ \"redrawTextBoundingBox\": () => (/* binding */ redrawTextBoundingBox),\n/* harmony export */ \"shouldAllowVerticalAlign\": () => (/* binding */ shouldAllowVerticalAlign),\n/* harmony export */ \"suppportsHorizontalAlign\": () => (/* binding */ suppportsHorizontalAlign),\n/* harmony export */ \"wrapText\": () => (/* binding */ wrapText)\n/* harmony export */ });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! . */ \"./element/index.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _containerCache__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./containerCache */ \"./element/containerCache.ts\");\n\n\n\n\n\n\n\n/**\n * Matches various emoji types.\n *\n * 1. basic emojis (😀, 🌍)\n * 2. flags (🇨🇿)\n * 3. multi-codepoint emojis:\n * - skin tones (👍🏽)\n * - variation selectors (☂️)\n * - keycaps (1️⃣)\n * - tag sequences (🏴󠁧󠁢󠁥󠁮󠁧󠁿)\n * - emoji sequences (👨‍👩‍👧‍👦, 👩‍🚀, 🏳️‍🌈)\n *\n * Unicode points:\n * - \\uFE0F: presentation selector\n * - \\u20E3: enclosing keycap\n * - \\u200D: ZWJ (zero width joiner)\n * - \\u{E0020}-\\u{E007E}: tags\n * - \\u{E007F}: cancel tag\n *\n * @see https://unicode.org/reports/tr51/#EBNF_and_Regex, with changes:\n * - replaced \\p{Emoji} with [\\p{Extended_Pictographic}\\p{Emoji_Presentation}], see more in `should tokenize emojis mixed with mixed text` test\n * - replaced \\p{Emod} with \\p{Emoji_Modifier} as some do not understand the abbreviation (i.e. https://devina.io/redos-checker)\n */\n\nconst _EMOJI_CHAR = /(\\p{RI}\\p{RI}|[\\p{Extended_Pictographic}\\p{Emoji_Presentation}](?:\\p{Emoji_Modifier}|\\uFE0F\\u20E3?|[\\u{E0020}-\\u{E007E}]+\\u{E007F})?(?:\\u200D(?:\\p{RI}\\p{RI}|[\\p{Emoji}](?:\\p{Emoji_Modifier}|\\uFE0F\\u20E3?|[\\u{E0020}-\\u{E007E}]+\\u{E007F})?))*)/u;\n/**\n * Detect a CJK char, though does not include every possible char used in CJK texts,\n * such as symbols and punctuations.\n *\n * By default every CJK is a breaking point, though CJK has additional breaking points,\n * including full width punctuations or symbols (Chinese and Japanese) and western punctuations (Korean).\n *\n * Additional CJK breaking point rules:\n * - expect a break before (lookahead), but not after (negative lookbehind), i.e. \"(\" or \"(\"\n * - expect a break after (lookbehind), but not before (negative lookahead), i.e. \")\" or \")\"\n * - expect a break always (lookahead and lookbehind), i.e. \"〃\"\n */\n\nconst _CJK_CHAR = /\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}/u;\n/**\n * Following characters break only with CJK, not with alphabetic characters.\n * This is essential for Korean, as it uses alphabetic punctuation, but expects CJK-like breaking points.\n *\n * Hello((た)) → [\"Hello\", \"((た))\"]\n * Hello((World)) → [\"Hello((World))\"]\n */\n\nconst _CJK_BREAK_NOT_AFTER_BUT_BEFORE = /<\\(\\[\\{/u;\nconst _CJK_BREAK_NOT_BEFORE_BUT_AFTER = />\\)\\]\\}.,:;\\?!/u;\nconst _CJK_BREAK_ALWAYS = / 〃〜~〰#&*+-ー/=|¬ ̄¦/u;\nconst _CJK_SYMBOLS_AND_PUNCTUATION = /()[]{}〈〉《》⦅⦆「」「」『』【】〖〗〔〕〘〙〚〛<>〝〞'〟・。゚゙,、.:;?!%ー/u;\n/**\n * Following characters break with any character, even though are mostly used with CJK.\n *\n * Hello た。→ [\"Hello\", \"た。\"]\n * ↑ DON'T BREAK \"た。\" (negative lookahead)\n * Hello「た」 World → [\"Hello\", \"「た」\", \"World\"]\n * ↑ DON'T BREAK \"「た\" (negative lookbehind)\n * ↑ DON'T BREAK \"た」\"(negative lookahead)\n * ↑ BREAK BEFORE \"「\" (lookahead)\n * ↑ BREAK AFTER \"」\" (lookbehind)\n */\n\nconst _ANY_BREAK_NOT_AFTER_BUT_BEFORE = /([{〈《⦅「「『【〖〔〘〚<〝/u;\nconst _ANY_BREAK_NOT_BEFORE_BUT_AFTER = /)]}〉》⦆」」』】〗〕〙〛>〞'〟・。゚゙,、.:;?!%±‥…\\//u;\n/**\n * Natural breaking points for any grammars.\n *\n * Hello-world\n * ↑ BREAK AFTER \"-\" → [\"Hello-\", \"world\"]\n * Hello world\n * ↑ BREAK ALWAYS \" \" → [\"Hello\", \" \", \"world\"]\n */\n\nconst _ANY_BREAK_AFTER = /-/u;\nconst _ANY_BREAK_ALWAYS = /\\s/u;\n/**\n * Simple fallback for browsers (mainly Safari < 16.4) that don't support \"Lookbehind assertion\".\n *\n * Browser support as of 10/2024:\n * - 91% Lookbehind assertion https://caniuse.com/mdn-javascript_regular_expressions_lookbehind_assertion\n * - 94% Unicode character class escape https://caniuse.com/mdn-javascript_regular_expressions_unicode_character_class_escape\n *\n * Does not include advanced CJK breaking rules, but covers most of the core cases, especially for latin.\n */\n\nconst BREAK_LINE_REGEX_SIMPLE = new RegExp(`${_EMOJI_CHAR.source}|([${_ANY_BREAK_ALWAYS.source}${_CJK_CHAR.source}${_CJK_BREAK_ALWAYS.source}${_ANY_BREAK_AFTER.source}])`, \"u\"); // Hello World → [\"Hello\", \" World\"]\n// ↑ BREAK BEFORE \" \"\n// HelloたWorld → [\"Hello\", \"たWorld\"]\n// ↑ BREAK BEFORE \"た\"\n// Hello「World」→ [\"Hello\", \"「World」\"]\n// ↑ BREAK BEFORE \"「\"\n\nconst getLookaheadBreakingPoints = () => {\n const ANY_BREAKING_POINT = `(?<![${_ANY_BREAK_NOT_AFTER_BUT_BEFORE.source}])(?=[${_ANY_BREAK_NOT_AFTER_BUT_BEFORE.source}${_ANY_BREAK_ALWAYS.source}])`;\n const CJK_BREAKING_POINT = `(?<![${_ANY_BREAK_NOT_AFTER_BUT_BEFORE.source}${_CJK_BREAK_NOT_AFTER_BUT_BEFORE.source}])(?=[${_CJK_BREAK_NOT_AFTER_BUT_BEFORE.source}]*[${_CJK_CHAR.source}${_CJK_BREAK_ALWAYS.source}])`;\n return new RegExp(`(?:${ANY_BREAKING_POINT}|${CJK_BREAKING_POINT})`, \"u\");\n}; // Hello World → [\"Hello \", \"World\"]\n// ↑ BREAK AFTER \" \"\n// Hello-World → [\"Hello-\", \"World\"]\n// ↑ BREAK AFTER \"-\"\n// HelloたWorld → [\"Helloた\", \"World\"]\n// ↑ BREAK AFTER \"た\"\n//「Hello」World → [\"「Hello」\", \"World\"]\n// ↑ BREAK AFTER \"」\"\n\n\nconst getLookbehindBreakingPoints = () => {\n const ANY_BREAKING_POINT = `(?![${_ANY_BREAK_NOT_BEFORE_BUT_AFTER.source}])(?<=[${_ANY_BREAK_NOT_BEFORE_BUT_AFTER.source}${_ANY_BREAK_ALWAYS.source}${_ANY_BREAK_AFTER.source}])`;\n const CJK_BREAKING_POINT = `(?![${_ANY_BREAK_NOT_BEFORE_BUT_AFTER.source}${_CJK_BREAK_NOT_BEFORE_BUT_AFTER.source}${_ANY_BREAK_AFTER.source}])(?<=[${_CJK_CHAR.source}${_CJK_BREAK_ALWAYS.source}][${_CJK_BREAK_NOT_BEFORE_BUT_AFTER.source}]*)`;\n return new RegExp(`(?:${ANY_BREAKING_POINT}|${CJK_BREAKING_POINT})`, \"u\");\n};\n/**\n * Break a line based on the whitespaces, CJK / emoji chars and language specific breaking points,\n * like hyphen for alphabetic and various full-width codepoints for CJK - especially Japanese, e.g.:\n *\n * \"Hello 世界。🌎🗺\" → [\"Hello\", \" \", \"世\", \"界。\", \"🌎\", \"🗺\"]\n * \"Hello-world\" → [\"Hello-\", \"world\"]\n * \"「Hello World」\" → [\"「Hello\", \" \", \"World」\"]\n */\n\n\nconst getBreakLineRegexAdvanced = () => new RegExp(`${_EMOJI_CHAR.source}|${getLookaheadBreakingPoints().source}|${getLookbehindBreakingPoints().source}`, \"u\");\n\nlet cachedBreakLineRegex; // Lazy-load for browsers that don't support \"Lookbehind assertion\"\n\nconst getBreakLineRegex = () => {\n if (!cachedBreakLineRegex) {\n try {\n cachedBreakLineRegex = getBreakLineRegexAdvanced();\n } catch (_a) {\n cachedBreakLineRegex = BREAK_LINE_REGEX_SIMPLE;\n }\n }\n\n return cachedBreakLineRegex;\n};\n\nconst CJK_REGEX = new RegExp(`[${_CJK_CHAR.source}${_CJK_BREAK_ALWAYS.source}${_CJK_SYMBOLS_AND_PUNCTUATION.source}]`, \"u\");\nconst EMOJI_REGEX = new RegExp(`${_EMOJI_CHAR.source}`, \"u\");\nconst containsCJK = text => {\n return CJK_REGEX.test(text);\n};\nconst containsEmoji = text => {\n return EMOJI_REGEX.test(text);\n};\nconst normalizeText = text => {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_0__.normalizeEOL)(text) // replace tabs with spaces so they render and measure correctly\n .replace(/\\t/g, \" \");\n};\n\nconst splitIntoLines = text => {\n return normalizeText(text).split(\"\\n\");\n};\n\nconst redrawTextBoundingBox = (textElement, container, elementsMap, informMutation = true) => {\n var _a, _b;\n\n let maxWidth = undefined;\n const boundTextUpdates = {\n x: textElement.x,\n y: textElement.y,\n text: textElement.text,\n width: textElement.width,\n height: textElement.height,\n angle: (_a = container === null || container === void 0 ? void 0 : container.angle) !== null && _a !== void 0 ? _a : textElement.angle\n };\n boundTextUpdates.text = textElement.text;\n\n if (container || !textElement.autoResize) {\n maxWidth = container ? getBoundTextMaxWidth(container, textElement) : textElement.width;\n boundTextUpdates.text = wrapText(textElement.originalText, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), maxWidth);\n }\n\n const metrics = measureText(boundTextUpdates.text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), textElement.lineHeight); // Note: only update width for unwrapped text and bound texts (which always have autoResize set to true)\n\n if (textElement.autoResize) {\n boundTextUpdates.width = metrics.width;\n }\n\n boundTextUpdates.height = metrics.height;\n\n if (container) {\n const maxContainerHeight = getBoundTextMaxHeight(container, textElement);\n const maxContainerWidth = getBoundTextMaxWidth(container, textElement);\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container) && metrics.height > maxContainerHeight) {\n const nextHeight = computeContainerDimensionForBoundText(metrics.height, container.type, (_b = container.customData) === null || _b === void 0 ? void 0 : _b.legacyTextWrap);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(container, {\n height: nextHeight\n }, informMutation);\n (0,_containerCache__WEBPACK_IMPORTED_MODULE_6__.updateOriginalContainerCache)(container.id, nextHeight);\n }\n\n if (metrics.width > maxContainerWidth) {\n const nextWidth = computeContainerDimensionForBoundText(metrics.width, container.type);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(container, {\n width: nextWidth\n }, informMutation);\n }\n\n const updatedTextElement = Object.assign(Object.assign({}, textElement), boundTextUpdates);\n const {\n x,\n y\n } = computeBoundTextPosition(container, updatedTextElement, elementsMap);\n boundTextUpdates.x = x;\n boundTextUpdates.y = y;\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(textElement, boundTextUpdates, informMutation);\n};\nconst bindTextToShapeAfterDuplication = (newElements, oldElements, oldIdToDuplicatedId) => {\n const newElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.arrayToMap)(newElements);\n oldElements.forEach(element => {\n const newElementId = oldIdToDuplicatedId.get(element.id);\n const boundTextElementId = getBoundTextElementId(element);\n\n if (boundTextElementId) {\n const newTextElementId = oldIdToDuplicatedId.get(boundTextElementId);\n\n if (newTextElementId) {\n const newContainer = newElementsMap.get(newElementId);\n\n if (newContainer) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(newContainer, {\n boundElements: (element.boundElements || []).filter(boundElement => boundElement.id !== newTextElementId && boundElement.id !== boundTextElementId).concat({\n type: \"text\",\n id: newTextElementId\n })\n });\n }\n\n const newTextElement = newElementsMap.get(newTextElementId);\n\n if (newTextElement && (0,___WEBPACK_IMPORTED_MODULE_3__.isTextElement)(newTextElement)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(newTextElement, {\n containerId: newContainer ? newElementId : null\n });\n }\n }\n }\n });\n};\nconst handleBindTextResize = (container, elementsMap, transformHandleType, shouldMaintainAspectRatio = false) => {\n var _a;\n\n const boundTextElementId = getBoundTextElementId(container);\n\n if (!boundTextElementId) {\n return;\n }\n\n (0,_containerCache__WEBPACK_IMPORTED_MODULE_6__.resetOriginalContainerCache)(container.id);\n const textElement = getBoundTextElement(container, elementsMap);\n\n if (textElement && textElement.text) {\n if (!container) {\n return;\n }\n\n let text = textElement.text;\n let nextHeight = textElement.height;\n let nextWidth = textElement.width;\n const maxWidth = getBoundTextMaxWidth(container, textElement);\n const maxHeight = getBoundTextMaxHeight(container, textElement);\n let containerHeight = container.height;\n\n if (shouldMaintainAspectRatio || transformHandleType !== \"n\" && transformHandleType !== \"s\") {\n if (text) {\n text = wrapText(textElement.originalText, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), maxWidth);\n }\n\n const metrics = measureText(text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), textElement.lineHeight);\n nextHeight = metrics.height;\n nextWidth = metrics.width;\n } // increase height in case text element height exceeds\n\n\n if (nextHeight > maxHeight) {\n containerHeight = computeContainerDimensionForBoundText(nextHeight, container.type, (_a = container.customData) === null || _a === void 0 ? void 0 : _a.legacyTextWrap);\n const diff = containerHeight - container.height; // fix the y coord when resizing from ne/nw/n\n\n const updatedY = !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container) && (transformHandleType === \"ne\" || transformHandleType === \"nw\" || transformHandleType === \"n\") ? container.y - diff : container.y;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(container, {\n height: containerHeight,\n y: updatedY\n });\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(textElement, {\n text,\n width: nextWidth,\n height: nextHeight\n });\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(textElement, computeBoundTextPosition(container, textElement, elementsMap));\n }\n }\n};\nconst computeBoundTextPosition = (container, boundTextElement, elementsMap) => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n return _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getBoundTextElementPosition(container, boundTextElement, elementsMap);\n }\n\n const containerCoords = getContainerCoords(container);\n const maxContainerHeight = getBoundTextMaxHeight(container, boundTextElement);\n const maxContainerWidth = getBoundTextMaxWidth(container, boundTextElement);\n let x;\n let y;\n\n if (boundTextElement.verticalAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.VERTICAL_ALIGN.TOP) {\n y = containerCoords.y;\n } else if (boundTextElement.verticalAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.VERTICAL_ALIGN.BOTTOM) {\n y = containerCoords.y + (maxContainerHeight - boundTextElement.height);\n } else {\n y = containerCoords.y + (maxContainerHeight / 2 - boundTextElement.height / 2);\n }\n\n if (boundTextElement.textAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.TEXT_ALIGN.LEFT) {\n x = containerCoords.x;\n } else if (boundTextElement.textAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.TEXT_ALIGN.RIGHT) {\n x = containerCoords.x + (maxContainerWidth - boundTextElement.width);\n } else {\n x = containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);\n }\n\n return {\n x,\n y\n };\n};\nconst measureText = (text, font, lineHeight, forceAdvanceWidth) => {\n const _text = text.split(\"\\n\") // replace empty lines with single space because leading/trailing empty\n // lines would be stripped from computation\n .map(x => x || \" \").join(\"\\n\");\n\n const fontSize = parseFloat(font);\n const height = getTextHeight(_text, fontSize, lineHeight);\n const width = getTextWidth(_text, font, forceAdvanceWidth);\n return {\n width,\n height\n };\n};\n/**\n * To get unitless line-height (if unknown) we can calculate it by dividing\n * height-per-line by fontSize.\n */\n\nconst detectLineHeight = textElement => {\n const lineCount = splitIntoLines(textElement.text).length;\n return textElement.height / lineCount / textElement.fontSize;\n};\n/**\n * We calculate the line height from the font size and the unitless line height,\n * aligning with the W3C spec.\n */\n\nconst getLineHeightInPx = (fontSize, lineHeight) => {\n return fontSize * lineHeight;\n}; // FIXME rename to getApproxMinContainerHeight\n\nconst getApproxMinLineHeight = (fontSize, lineHeight) => {\n return getLineHeightInPx(fontSize, lineHeight) + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nlet canvas;\n/**\n * @param forceAdvanceWidth use to force retrieve the \"advance width\" ~ `metrics.width`, instead of the actual boundind box width.\n *\n * > The advance width is the distance between the glyph's initial pen position and the next glyph's initial pen position.\n *\n * We need to use the advance width as that's the closest thing to the browser wrapping algo, hence using it for:\n * - text wrapping\n * - wysiwyg editor (+padding)\n *\n * Everything else should be based on the actual bounding box width.\n *\n * `Math.ceil` of the final width adds additional buffer which stabilizes slight wrapping incosistencies.\n */\n\nconst getLineWidth = (text, font, forceAdvanceWidth) => {\n if (!canvas) {\n canvas = document.createElement(\"canvas\");\n }\n\n const canvas2dContext = canvas.getContext(\"2d\");\n canvas2dContext.font = font;\n const metrics = canvas2dContext.measureText(text);\n const advanceWidth = metrics.width; // retrieve the actual bounding box width if these metrics are available (as of now > 95% coverage)\n\n if (!forceAdvanceWidth && window.TextMetrics && \"actualBoundingBoxLeft\" in window.TextMetrics.prototype && \"actualBoundingBoxRight\" in window.TextMetrics.prototype) {\n // could be negative, therefore getting the absolute value\n const actualWidth = Math.abs(metrics.actualBoundingBoxLeft) + Math.abs(metrics.actualBoundingBoxRight); // fallback to advance width if the actual width is zero, i.e. on text editing start\n // or when actual width does not respect whitespace chars, i.e. spaces\n // otherwise actual width should always be bigger\n\n return Math.max(actualWidth, advanceWidth);\n } // since in test env the canvas measureText algo\n // doesn't measure text and instead just returns number of\n // characters hence we assume that each letteris 10px\n\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_0__.isTestEnv)()) {\n return advanceWidth * 10;\n }\n\n return advanceWidth;\n};\n\nconst getTextWidth = (text, font, forceAdvanceWidth) => {\n const lines = splitIntoLines(text);\n let width = 0;\n lines.forEach(line => {\n width = Math.max(width, getLineWidth(line, font, forceAdvanceWidth));\n });\n return width;\n};\nconst getTextHeight = (text, fontSize, lineHeight) => {\n const lineCount = splitIntoLines(text).length;\n return getLineHeightInPx(fontSize, lineHeight) * lineCount;\n};\nconst parseTokens = line => {\n const breakLineRegex = getBreakLineRegex(); // normalizing to single-codepoint composed chars due to canonical equivalence of multi-codepoint versions for chars like č, で (~ so that we don't break a line in between c and ˇ)\n // filtering due to multi-codepoint chars like 👨‍👩‍👧‍👦, 👩🏽‍🦰\n\n return line.normalize(\"NFC\").split(breakLineRegex).filter(Boolean);\n}; // handles multi-byte chars (é, 中) and purposefully does not handle multi-codepoint char (👨‍👩‍👧‍👦, 👩🏽‍🦰)\n\nconst isSingleCharacter = maybeSingleCharacter => {\n return maybeSingleCharacter.codePointAt(0) !== undefined && maybeSingleCharacter.codePointAt(1) === undefined;\n};\n\nconst satisfiesWordInvariant = word => {\n if (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_2__.ENV.TEST || \"development\" !== \"production\") {\n if (/\\s/.test(word)) {\n throw new Error(\"Word should not contain any whitespaces!\");\n }\n }\n};\n\nconst wrapWord = (word, font, maxWidth) => {\n // multi-codepoint emojis are already broken apart and shouldn't be broken further\n if (EMOJI_REGEX.test(word)) {\n return [word];\n }\n\n satisfiesWordInvariant(word);\n const lines = [];\n const chars = Array.from(word);\n let currentLine = \"\";\n let currentLineWidth = 0;\n\n for (const char of chars) {\n const _charWidth = charWidth.calculate(char, font);\n\n const testLineWidth = currentLineWidth + _charWidth;\n\n if (testLineWidth <= maxWidth) {\n currentLine = currentLine + char;\n currentLineWidth = testLineWidth;\n continue;\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n currentLine = char;\n currentLineWidth = _charWidth;\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n return lines;\n};\n\nconst wrapLine = (line, font, maxWidth) => {\n var _a;\n\n const lines = [];\n const tokens = parseTokens(line);\n const tokenIterator = tokens[Symbol.iterator]();\n let currentLine = \"\";\n let currentLineWidth = 0;\n let iterator = tokenIterator.next();\n\n while (!iterator.done) {\n const token = iterator.value;\n const testLine = currentLine + token; // cache single codepoint whitespace, CJK or emoji width calc. as kerning should not apply here\n\n const testLineWidth = isSingleCharacter(token) ? currentLineWidth + charWidth.calculate(token, font) : getLineWidth(testLine, font, true); // build up the current line, skipping length check for possibly trailing whitespaces\n\n if (/\\s/.test(token) || testLineWidth <= maxWidth) {\n currentLine = testLine;\n currentLineWidth = testLineWidth;\n iterator = tokenIterator.next();\n continue;\n } // current line is empty => just the token (word) is longer than `maxWidth` and needs to be wrapped\n\n\n if (!currentLine) {\n const wrappedWord = wrapWord(token, font, maxWidth);\n const trailingLine = (_a = wrappedWord[wrappedWord.length - 1]) !== null && _a !== void 0 ? _a : \"\";\n const precedingLines = wrappedWord.slice(0, -1);\n lines.push(...precedingLines); // trailing line of the wrapped word might still be joined with next token/s\n\n currentLine = trailingLine;\n currentLineWidth = getLineWidth(trailingLine, font, true);\n iterator = tokenIterator.next();\n } else {\n // push & reset, but don't iterate on the next token, as we didn't use it yet!\n lines.push(currentLine.trimEnd()); // purposefully not iterating and not setting `currentLine` to `token`, so that we could use a simple !currentLine check above\n\n currentLine = \"\";\n currentLineWidth = 0;\n }\n } // iterator done, push the trailing line if exists\n\n\n if (currentLine) {\n lines.push(currentLine.trimEnd());\n }\n\n return lines;\n};\n\nconst wrapText = (text, font, maxWidth) => {\n // if maxWidth is not finite or NaN which can happen in case of bugs in\n // computation, we need to make sure we don't continue as we'll end up\n // in an infinite loop\n if (!Number.isFinite(maxWidth) || maxWidth < 0) {\n return text;\n }\n\n const lines = [];\n const originalLines = text.split(\"\\n\");\n\n for (const originalLine of originalLines) {\n const currentLineWidth = getLineWidth(originalLine, font, true);\n\n if (currentLineWidth <= maxWidth) {\n lines.push(originalLine);\n continue;\n }\n\n const wrappedLine = wrapLine(originalLine, font, maxWidth);\n lines.push(...wrappedLine);\n }\n\n return lines.join(\"\\n\");\n};\nconst charWidth = (() => {\n const cachedCharWidth = {};\n\n const calculate = (char, font) => {\n const unicode = char.charCodeAt(0);\n\n if (!cachedCharWidth[font]) {\n cachedCharWidth[font] = [];\n }\n\n if (!cachedCharWidth[font][unicode]) {\n const width = getLineWidth(char, font, true);\n cachedCharWidth[font][unicode] = width;\n }\n\n return cachedCharWidth[font][unicode];\n };\n\n const getCache = font => {\n return cachedCharWidth[font];\n };\n\n const clearCache = font => {\n cachedCharWidth[font] = [];\n };\n\n return {\n calculate,\n getCache,\n clearCache\n };\n})();\nconst DUMMY_TEXT = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\".toLocaleUpperCase(); // FIXME rename to getApproxMinContainerWidth\n\nconst getApproxMinLineWidth = (font, lineHeight) => {\n const maxCharWidth = getMaxCharWidth(font);\n\n if (maxCharWidth === 0) {\n return measureText(DUMMY_TEXT.split(\"\").join(\"\\n\"), font, lineHeight).width + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n return maxCharWidth + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nconst getMinCharWidth = font => {\n const cache = charWidth.getCache(font);\n\n if (!cache) {\n return 0;\n }\n\n const cacheWithOutEmpty = cache.filter(val => val !== undefined);\n return Math.min(...cacheWithOutEmpty);\n};\nconst getMaxCharWidth = font => {\n const cache = charWidth.getCache(font);\n\n if (!cache) {\n return 0;\n }\n\n const cacheWithOutEmpty = cache.filter(val => val !== undefined);\n return Math.max(...cacheWithOutEmpty);\n};\nconst getBoundTextElementId = container => {\n var _a, _b, _c;\n\n return ((_a = container === null || container === void 0 ? void 0 : container.boundElements) === null || _a === void 0 ? void 0 : _a.length) ? ((_c = (_b = container === null || container === void 0 ? void 0 : container.boundElements) === null || _b === void 0 ? void 0 : _b.find(ele => ele.type === \"text\")) === null || _c === void 0 ? void 0 : _c.id) || null : null;\n};\nconst getBoundTextElement = (element, elementsMap) => {\n if (!element) {\n return null;\n }\n\n const boundTextElementId = getBoundTextElementId(element);\n\n if (boundTextElementId) {\n return elementsMap.get(boundTextElementId) || null;\n }\n\n return null;\n};\nconst getContainerElement = (element, elementsMap) => {\n if (!element) {\n return null;\n }\n\n if (element.containerId) {\n return elementsMap.get(element.containerId) || null;\n }\n\n return null;\n};\nconst getContainerCenter = (container, appState, elementsMap) => {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n return {\n x: container.x + container.width / 2,\n y: container.y + container.height / 2\n };\n }\n\n const points = _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getPointsGlobalCoordinates(container, elementsMap);\n\n if (points.length % 2 === 1) {\n const index = Math.floor(container.points.length / 2);\n const midPoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getPointGlobalCoordinates(container, container.points[index], elementsMap);\n return {\n x: midPoint[0],\n y: midPoint[1]\n };\n }\n\n const index = container.points.length / 2 - 1;\n let midSegmentMidpoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getEditorMidPoints(container, elementsMap, appState)[index];\n\n if (!midSegmentMidpoint) {\n midSegmentMidpoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getSegmentMidPoint(container, points[index], points[index + 1], index + 1, elementsMap);\n }\n\n return {\n x: midSegmentMidpoint[0],\n y: midSegmentMidpoint[1]\n };\n};\nconst getContainerCoords = container => {\n var _a;\n\n let offsetX = _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING;\n let offsetY = _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING;\n const legacy = (_a = container.customData) === null || _a === void 0 ? void 0 : _a.legacyTextWrap; //zsviczian\n\n if (container.type === \"ellipse\" && !legacy) {\n // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6172\n offsetX += container.width / 2 * (1 - Math.sqrt(2) / 2);\n offsetY += container.height / 2 * (1 - Math.sqrt(2) / 2);\n } // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6265\n\n\n if (container.type === \"diamond\" && !legacy) {\n offsetX += container.width / 4;\n offsetY += container.height / 4;\n }\n\n return {\n x: container.x + offsetX,\n y: container.y + offsetY\n };\n};\nconst getTextElementAngle = (textElement, container) => {\n if (!container || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n return textElement.angle;\n }\n\n return container.angle;\n};\nconst getBoundTextElementPosition = (container, boundTextElement, elementsMap) => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n return _linearElementEditor__WEBPACK_IMPORTED_MODULE_5__.LinearElementEditor.getBoundTextElementPosition(container, boundTextElement, elementsMap);\n }\n};\nconst shouldAllowVerticalAlign = (selectedElements, elementsMap) => {\n return selectedElements.some(element => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isBoundToContainer)(element)) {\n const container = getContainerElement(element, elementsMap);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n return false;\n }\n\n return true;\n }\n\n return false;\n });\n};\nconst suppportsHorizontalAlign = (selectedElements, elementsMap) => {\n return selectedElements.some(element => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isBoundToContainer)(element)) {\n const container = getContainerElement(element, elementsMap);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n return false;\n }\n\n return true;\n }\n\n return (0,___WEBPACK_IMPORTED_MODULE_3__.isTextElement)(element);\n });\n};\nconst VALID_CONTAINER_TYPES = new Set([\"rectangle\", \"ellipse\", \"diamond\", \"arrow\"]);\nconst isValidTextContainer = element => VALID_CONTAINER_TYPES.has(element.type);\nconst computeContainerDimensionForBoundText = (dimension, containerType, legacy = false) => {\n dimension = Math.ceil(dimension);\n const padding = _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n\n if (containerType === \"ellipse\" && !legacy) {\n //zsviczian\n return Math.round((dimension + padding) / Math.sqrt(2) * 2);\n }\n\n if (containerType === \"arrow\") {\n return dimension + padding * 8;\n }\n\n if (containerType === \"diamond\" && !legacy) {\n //zsviczian\n return 2 * (dimension + padding);\n }\n\n return dimension + padding;\n};\nconst getBoundTextMaxWidth = (container, boundTextElement) => {\n var _a, _b;\n\n const {\n width\n } = container;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n const minWidth = ((_a = boundTextElement === null || boundTextElement === void 0 ? void 0 : boundTextElement.fontSize) !== null && _a !== void 0 ? _a : _constants__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_FONT_SIZE) * _constants__WEBPACK_IMPORTED_MODULE_2__.ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO;\n return Math.max(_constants__WEBPACK_IMPORTED_MODULE_2__.ARROW_LABEL_WIDTH_FRACTION * width, minWidth);\n }\n\n const legacy = (_b = container.customData) === null || _b === void 0 ? void 0 : _b.legacyTextWrap; //zsviczian\n\n if (container.type === \"ellipse\" && !legacy) {\n // The width of the largest rectangle inscribed inside an ellipse is\n // Math.round((ellipse.width / 2) * Math.sqrt(2)) which is derived from\n // equation of an ellipse -https://github.com/excalidraw/excalidraw/pull/6172\n return Math.round(width / 2 * Math.sqrt(2)) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n if (container.type === \"diamond\" && !legacy) {\n // The width of the largest rectangle inscribed inside a rhombus is\n // Math.round(width / 2) - https://github.com/excalidraw/excalidraw/pull/6265\n return Math.round(width / 2) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n return width - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nconst getBoundTextMaxHeight = (container, boundTextElement) => {\n var _a;\n\n const {\n height\n } = container;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_4__.isArrowElement)(container)) {\n const containerHeight = height - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 8 * 2;\n\n if (containerHeight <= 0) {\n return boundTextElement.height;\n }\n\n return height;\n }\n\n const legacy = (_a = container.customData) === null || _a === void 0 ? void 0 : _a.legacyTextWrap; //zsviczian\n\n if (container.type === \"ellipse\" && !legacy) {\n // The height of the largest rectangle inscribed inside an ellipse is\n // Math.round((ellipse.height / 2) * Math.sqrt(2)) which is derived from\n // equation of an ellipse - https://github.com/excalidraw/excalidraw/pull/6172\n return Math.round(height / 2 * Math.sqrt(2)) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n if (container.type === \"diamond\" && !legacy) {\n // The height of the largest rectangle inscribed inside a rhombus is\n // Math.round(height / 2) - https://github.com/excalidraw/excalidraw/pull/6265\n return Math.round(height / 2) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n return height - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nconst isMeasureTextSupported = () => {\n const width = getTextWidth(DUMMY_TEXT, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)({\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_FONT_SIZE,\n fontFamily: _constants__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_FONT_FAMILY\n }));\n return width > 0;\n};\nconst getMinTextElementWidth = (font, lineHeight) => {\n return measureText(\"\", font, lineHeight).width + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\n/** retrieves text from text elements and concatenates to a single string */\n\nconst getTextFromElements = (elements, separator = \"\\n\\n\") => {\n const text = elements.reduce((acc, element) => {\n if ((0,___WEBPACK_IMPORTED_MODULE_3__.isTextElement)(element)) {\n acc.push(element.text);\n }\n\n return acc;\n }, []).join(separator);\n return text;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/textElement.ts?");
3028
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"bindTextToShapeAfterDuplication\": () => (/* binding */ bindTextToShapeAfterDuplication),\n/* harmony export */ \"charWidth\": () => (/* binding */ charWidth),\n/* harmony export */ \"computeBoundTextPosition\": () => (/* binding */ computeBoundTextPosition),\n/* harmony export */ \"computeContainerDimensionForBoundText\": () => (/* binding */ computeContainerDimensionForBoundText),\n/* harmony export */ \"detectLineHeight\": () => (/* binding */ detectLineHeight),\n/* harmony export */ \"getApproxMinLineHeight\": () => (/* binding */ getApproxMinLineHeight),\n/* harmony export */ \"getApproxMinLineWidth\": () => (/* binding */ getApproxMinLineWidth),\n/* harmony export */ \"getBoundTextElement\": () => (/* binding */ getBoundTextElement),\n/* harmony export */ \"getBoundTextElementId\": () => (/* binding */ getBoundTextElementId),\n/* harmony export */ \"getBoundTextElementPosition\": () => (/* binding */ getBoundTextElementPosition),\n/* harmony export */ \"getBoundTextMaxHeight\": () => (/* binding */ getBoundTextMaxHeight),\n/* harmony export */ \"getBoundTextMaxWidth\": () => (/* binding */ getBoundTextMaxWidth),\n/* harmony export */ \"getContainerCenter\": () => (/* binding */ getContainerCenter),\n/* harmony export */ \"getContainerCoords\": () => (/* binding */ getContainerCoords),\n/* harmony export */ \"getContainerElement\": () => (/* binding */ getContainerElement),\n/* harmony export */ \"getLineHeightInPx\": () => (/* binding */ getLineHeightInPx),\n/* harmony export */ \"getLineWidth\": () => (/* binding */ getLineWidth),\n/* harmony export */ \"getMaxCharWidth\": () => (/* binding */ getMaxCharWidth),\n/* harmony export */ \"getMinCharWidth\": () => (/* binding */ getMinCharWidth),\n/* harmony export */ \"getMinTextElementWidth\": () => (/* binding */ getMinTextElementWidth),\n/* harmony export */ \"getTextElementAngle\": () => (/* binding */ getTextElementAngle),\n/* harmony export */ \"getTextFromElements\": () => (/* binding */ getTextFromElements),\n/* harmony export */ \"getTextHeight\": () => (/* binding */ getTextHeight),\n/* harmony export */ \"getTextWidth\": () => (/* binding */ getTextWidth),\n/* harmony export */ \"handleBindTextResize\": () => (/* binding */ handleBindTextResize),\n/* harmony export */ \"isMeasureTextSupported\": () => (/* binding */ isMeasureTextSupported),\n/* harmony export */ \"isValidTextContainer\": () => (/* binding */ isValidTextContainer),\n/* harmony export */ \"measureText\": () => (/* binding */ measureText),\n/* harmony export */ \"normalizeText\": () => (/* binding */ normalizeText),\n/* harmony export */ \"redrawTextBoundingBox\": () => (/* binding */ redrawTextBoundingBox),\n/* harmony export */ \"shouldAllowVerticalAlign\": () => (/* binding */ shouldAllowVerticalAlign),\n/* harmony export */ \"suppportsHorizontalAlign\": () => (/* binding */ suppportsHorizontalAlign)\n/* harmony export */ });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! . */ \"./element/index.ts\");\n/* harmony import */ var _textWrapping__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _containerCache__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./containerCache */ \"./element/containerCache.ts\");\n\n\n\n\n\n\n\n\nconst normalizeText = text => {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_0__.normalizeEOL)(text) // replace tabs with spaces so they render and measure correctly\n .replace(/\\t/g, \" \");\n};\n\nconst splitIntoLines = text => {\n return normalizeText(text).split(\"\\n\");\n};\n\nconst redrawTextBoundingBox = (textElement, container, elementsMap, informMutation = true) => {\n var _a, _b;\n\n let maxWidth = undefined;\n const boundTextUpdates = {\n x: textElement.x,\n y: textElement.y,\n text: textElement.text,\n width: textElement.width,\n height: textElement.height,\n angle: (_a = container === null || container === void 0 ? void 0 : container.angle) !== null && _a !== void 0 ? _a : textElement.angle\n };\n boundTextUpdates.text = textElement.text;\n\n if (container || !textElement.autoResize) {\n maxWidth = container ? getBoundTextMaxWidth(container, textElement) : textElement.width;\n boundTextUpdates.text = (0,_textWrapping__WEBPACK_IMPORTED_MODULE_4__.wrapText)(textElement.originalText, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), maxWidth);\n }\n\n const metrics = measureText(boundTextUpdates.text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), textElement.lineHeight); // Note: only update width for unwrapped text and bound texts (which always have autoResize set to true)\n\n if (textElement.autoResize) {\n boundTextUpdates.width = metrics.width;\n }\n\n boundTextUpdates.height = metrics.height;\n\n if (container) {\n const maxContainerHeight = getBoundTextMaxHeight(container, textElement);\n const maxContainerWidth = getBoundTextMaxWidth(container, textElement);\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container) && metrics.height > maxContainerHeight) {\n const nextHeight = computeContainerDimensionForBoundText(metrics.height, container.type, (_b = container.customData) === null || _b === void 0 ? void 0 : _b.legacyTextWrap);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(container, {\n height: nextHeight\n }, informMutation);\n (0,_containerCache__WEBPACK_IMPORTED_MODULE_7__.updateOriginalContainerCache)(container.id, nextHeight);\n }\n\n if (metrics.width > maxContainerWidth) {\n const nextWidth = computeContainerDimensionForBoundText(metrics.width, container.type);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(container, {\n width: nextWidth\n }, informMutation);\n }\n\n const updatedTextElement = Object.assign(Object.assign({}, textElement), boundTextUpdates);\n const {\n x,\n y\n } = computeBoundTextPosition(container, updatedTextElement, elementsMap);\n boundTextUpdates.x = x;\n boundTextUpdates.y = y;\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(textElement, boundTextUpdates, informMutation);\n};\nconst bindTextToShapeAfterDuplication = (newElements, oldElements, oldIdToDuplicatedId) => {\n const newElementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.arrayToMap)(newElements);\n oldElements.forEach(element => {\n const newElementId = oldIdToDuplicatedId.get(element.id);\n const boundTextElementId = getBoundTextElementId(element);\n\n if (boundTextElementId) {\n const newTextElementId = oldIdToDuplicatedId.get(boundTextElementId);\n\n if (newTextElementId) {\n const newContainer = newElementsMap.get(newElementId);\n\n if (newContainer) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(newContainer, {\n boundElements: (element.boundElements || []).filter(boundElement => boundElement.id !== newTextElementId && boundElement.id !== boundTextElementId).concat({\n type: \"text\",\n id: newTextElementId\n })\n });\n }\n\n const newTextElement = newElementsMap.get(newTextElementId);\n\n if (newTextElement && (0,___WEBPACK_IMPORTED_MODULE_3__.isTextElement)(newTextElement)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(newTextElement, {\n containerId: newContainer ? newElementId : null\n });\n }\n }\n }\n });\n};\nconst handleBindTextResize = (container, elementsMap, transformHandleType, shouldMaintainAspectRatio = false) => {\n var _a;\n\n const boundTextElementId = getBoundTextElementId(container);\n\n if (!boundTextElementId) {\n return;\n }\n\n (0,_containerCache__WEBPACK_IMPORTED_MODULE_7__.resetOriginalContainerCache)(container.id);\n const textElement = getBoundTextElement(container, elementsMap);\n\n if (textElement && textElement.text) {\n if (!container) {\n return;\n }\n\n let text = textElement.text;\n let nextHeight = textElement.height;\n let nextWidth = textElement.width;\n const maxWidth = getBoundTextMaxWidth(container, textElement);\n const maxHeight = getBoundTextMaxHeight(container, textElement);\n let containerHeight = container.height;\n\n if (shouldMaintainAspectRatio || transformHandleType !== \"n\" && transformHandleType !== \"s\") {\n if (text) {\n text = (0,_textWrapping__WEBPACK_IMPORTED_MODULE_4__.wrapText)(textElement.originalText, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), maxWidth);\n }\n\n const metrics = measureText(text, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)(textElement), textElement.lineHeight);\n nextHeight = metrics.height;\n nextWidth = metrics.width;\n } // increase height in case text element height exceeds\n\n\n if (nextHeight > maxHeight) {\n containerHeight = computeContainerDimensionForBoundText(nextHeight, container.type, (_a = container.customData) === null || _a === void 0 ? void 0 : _a.legacyTextWrap);\n const diff = containerHeight - container.height; // fix the y coord when resizing from ne/nw/n\n\n const updatedY = !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container) && (transformHandleType === \"ne\" || transformHandleType === \"nw\" || transformHandleType === \"n\") ? container.y - diff : container.y;\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(container, {\n height: containerHeight,\n y: updatedY\n });\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(textElement, {\n text,\n width: nextWidth,\n height: nextHeight\n });\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_1__.mutateElement)(textElement, computeBoundTextPosition(container, textElement, elementsMap));\n }\n }\n};\nconst computeBoundTextPosition = (container, boundTextElement, elementsMap) => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n return _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__.LinearElementEditor.getBoundTextElementPosition(container, boundTextElement, elementsMap);\n }\n\n const containerCoords = getContainerCoords(container);\n const maxContainerHeight = getBoundTextMaxHeight(container, boundTextElement);\n const maxContainerWidth = getBoundTextMaxWidth(container, boundTextElement);\n let x;\n let y;\n\n if (boundTextElement.verticalAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.VERTICAL_ALIGN.TOP) {\n y = containerCoords.y;\n } else if (boundTextElement.verticalAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.VERTICAL_ALIGN.BOTTOM) {\n y = containerCoords.y + (maxContainerHeight - boundTextElement.height);\n } else {\n y = containerCoords.y + (maxContainerHeight / 2 - boundTextElement.height / 2);\n }\n\n if (boundTextElement.textAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.TEXT_ALIGN.LEFT) {\n x = containerCoords.x;\n } else if (boundTextElement.textAlign === _constants__WEBPACK_IMPORTED_MODULE_2__.TEXT_ALIGN.RIGHT) {\n x = containerCoords.x + (maxContainerWidth - boundTextElement.width);\n } else {\n x = containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);\n }\n\n return {\n x,\n y\n };\n};\nconst measureText = (text, font, lineHeight, forceAdvanceWidth) => {\n const _text = text.split(\"\\n\") // replace empty lines with single space because leading/trailing empty\n // lines would be stripped from computation\n .map(x => x || \" \").join(\"\\n\");\n\n const fontSize = parseFloat(font);\n const height = getTextHeight(_text, fontSize, lineHeight);\n const width = getTextWidth(_text, font, forceAdvanceWidth);\n return {\n width,\n height\n };\n};\n/**\n * To get unitless line-height (if unknown) we can calculate it by dividing\n * height-per-line by fontSize.\n */\n\nconst detectLineHeight = textElement => {\n const lineCount = splitIntoLines(textElement.text).length;\n return textElement.height / lineCount / textElement.fontSize;\n};\n/**\n * We calculate the line height from the font size and the unitless line height,\n * aligning with the W3C spec.\n */\n\nconst getLineHeightInPx = (fontSize, lineHeight) => {\n return fontSize * lineHeight;\n}; // FIXME rename to getApproxMinContainerHeight\n\nconst getApproxMinLineHeight = (fontSize, lineHeight) => {\n return getLineHeightInPx(fontSize, lineHeight) + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nlet canvas;\n/**\n * @param forceAdvanceWidth use to force retrieve the \"advance width\" ~ `metrics.width`, instead of the actual boundind box width.\n *\n * > The advance width is the distance between the glyph's initial pen position and the next glyph's initial pen position.\n *\n * We need to use the advance width as that's the closest thing to the browser wrapping algo, hence using it for:\n * - text wrapping\n * - wysiwyg editor (+padding)\n *\n * Everything else should be based on the actual bounding box width.\n *\n * `Math.ceil` of the final width adds additional buffer which stabilizes slight wrapping incosistencies.\n */\n\nconst getLineWidth = (text, font, forceAdvanceWidth) => {\n if (!canvas) {\n canvas = document.createElement(\"canvas\");\n }\n\n const canvas2dContext = canvas.getContext(\"2d\");\n canvas2dContext.font = font;\n const metrics = canvas2dContext.measureText(text);\n const advanceWidth = metrics.width; // retrieve the actual bounding box width if these metrics are available (as of now > 95% coverage)\n\n if (!forceAdvanceWidth && window.TextMetrics && \"actualBoundingBoxLeft\" in window.TextMetrics.prototype && \"actualBoundingBoxRight\" in window.TextMetrics.prototype) {\n // could be negative, therefore getting the absolute value\n const actualWidth = Math.abs(metrics.actualBoundingBoxLeft) + Math.abs(metrics.actualBoundingBoxRight); // fallback to advance width if the actual width is zero, i.e. on text editing start\n // or when actual width does not respect whitespace chars, i.e. spaces\n // otherwise actual width should always be bigger\n\n return Math.max(actualWidth, advanceWidth);\n } // since in test env the canvas measureText algo\n // doesn't measure text and instead just returns number of\n // characters hence we assume that each letteris 10px\n\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_0__.isTestEnv)()) {\n return advanceWidth * 10;\n }\n\n return advanceWidth;\n};\nconst getTextWidth = (text, font, forceAdvanceWidth) => {\n const lines = splitIntoLines(text);\n let width = 0;\n lines.forEach(line => {\n width = Math.max(width, getLineWidth(line, font, forceAdvanceWidth));\n });\n return width;\n};\nconst getTextHeight = (text, fontSize, lineHeight) => {\n const lineCount = splitIntoLines(text).length;\n return getLineHeightInPx(fontSize, lineHeight) * lineCount;\n};\nconst charWidth = (() => {\n const cachedCharWidth = {};\n\n const calculate = (char, font) => {\n const unicode = char.charCodeAt(0);\n\n if (!cachedCharWidth[font]) {\n cachedCharWidth[font] = [];\n }\n\n if (!cachedCharWidth[font][unicode]) {\n const width = getLineWidth(char, font, true);\n cachedCharWidth[font][unicode] = width;\n }\n\n return cachedCharWidth[font][unicode];\n };\n\n const getCache = font => {\n return cachedCharWidth[font];\n };\n\n const clearCache = font => {\n cachedCharWidth[font] = [];\n };\n\n return {\n calculate,\n getCache,\n clearCache\n };\n})();\nconst DUMMY_TEXT = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\".toLocaleUpperCase(); // FIXME rename to getApproxMinContainerWidth\n\nconst getApproxMinLineWidth = (font, lineHeight) => {\n const maxCharWidth = getMaxCharWidth(font);\n\n if (maxCharWidth === 0) {\n return measureText(DUMMY_TEXT.split(\"\").join(\"\\n\"), font, lineHeight).width + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n return maxCharWidth + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nconst getMinCharWidth = font => {\n const cache = charWidth.getCache(font);\n\n if (!cache) {\n return 0;\n }\n\n const cacheWithOutEmpty = cache.filter(val => val !== undefined);\n return Math.min(...cacheWithOutEmpty);\n};\nconst getMaxCharWidth = font => {\n const cache = charWidth.getCache(font);\n\n if (!cache) {\n return 0;\n }\n\n const cacheWithOutEmpty = cache.filter(val => val !== undefined);\n return Math.max(...cacheWithOutEmpty);\n};\nconst getBoundTextElementId = container => {\n var _a, _b, _c;\n\n return ((_a = container === null || container === void 0 ? void 0 : container.boundElements) === null || _a === void 0 ? void 0 : _a.length) ? ((_c = (_b = container === null || container === void 0 ? void 0 : container.boundElements) === null || _b === void 0 ? void 0 : _b.find(ele => ele.type === \"text\")) === null || _c === void 0 ? void 0 : _c.id) || null : null;\n};\nconst getBoundTextElement = (element, elementsMap) => {\n if (!element) {\n return null;\n }\n\n const boundTextElementId = getBoundTextElementId(element);\n\n if (boundTextElementId) {\n return elementsMap.get(boundTextElementId) || null;\n }\n\n return null;\n};\nconst getContainerElement = (element, elementsMap) => {\n if (!element) {\n return null;\n }\n\n if (element.containerId) {\n return elementsMap.get(element.containerId) || null;\n }\n\n return null;\n};\nconst getContainerCenter = (container, appState, elementsMap) => {\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n return {\n x: container.x + container.width / 2,\n y: container.y + container.height / 2\n };\n }\n\n const points = _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__.LinearElementEditor.getPointsGlobalCoordinates(container, elementsMap);\n\n if (points.length % 2 === 1) {\n const index = Math.floor(container.points.length / 2);\n const midPoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__.LinearElementEditor.getPointGlobalCoordinates(container, container.points[index], elementsMap);\n return {\n x: midPoint[0],\n y: midPoint[1]\n };\n }\n\n const index = container.points.length / 2 - 1;\n let midSegmentMidpoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__.LinearElementEditor.getEditorMidPoints(container, elementsMap, appState)[index];\n\n if (!midSegmentMidpoint) {\n midSegmentMidpoint = _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__.LinearElementEditor.getSegmentMidPoint(container, points[index], points[index + 1], index + 1, elementsMap);\n }\n\n return {\n x: midSegmentMidpoint[0],\n y: midSegmentMidpoint[1]\n };\n};\nconst getContainerCoords = container => {\n var _a;\n\n let offsetX = _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING;\n let offsetY = _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING;\n const legacy = (_a = container.customData) === null || _a === void 0 ? void 0 : _a.legacyTextWrap; //zsviczian\n\n if (container.type === \"ellipse\" && !legacy) {\n // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6172\n offsetX += container.width / 2 * (1 - Math.sqrt(2) / 2);\n offsetY += container.height / 2 * (1 - Math.sqrt(2) / 2);\n } // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6265\n\n\n if (container.type === \"diamond\" && !legacy) {\n offsetX += container.width / 4;\n offsetY += container.height / 4;\n }\n\n return {\n x: container.x + offsetX,\n y: container.y + offsetY\n };\n};\nconst getTextElementAngle = (textElement, container) => {\n if (!container || (0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n return textElement.angle;\n }\n\n return container.angle;\n};\nconst getBoundTextElementPosition = (container, boundTextElement, elementsMap) => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n return _linearElementEditor__WEBPACK_IMPORTED_MODULE_6__.LinearElementEditor.getBoundTextElementPosition(container, boundTextElement, elementsMap);\n }\n};\nconst shouldAllowVerticalAlign = (selectedElements, elementsMap) => {\n return selectedElements.some(element => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isBoundToContainer)(element)) {\n const container = getContainerElement(element, elementsMap);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n return false;\n }\n\n return true;\n }\n\n return false;\n });\n};\nconst suppportsHorizontalAlign = (selectedElements, elementsMap) => {\n return selectedElements.some(element => {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isBoundToContainer)(element)) {\n const container = getContainerElement(element, elementsMap);\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n return false;\n }\n\n return true;\n }\n\n return (0,___WEBPACK_IMPORTED_MODULE_3__.isTextElement)(element);\n });\n};\nconst VALID_CONTAINER_TYPES = new Set([\"rectangle\", \"ellipse\", \"diamond\", \"arrow\"]);\nconst isValidTextContainer = element => VALID_CONTAINER_TYPES.has(element.type);\nconst computeContainerDimensionForBoundText = (dimension, containerType, legacy = false) => {\n dimension = Math.ceil(dimension);\n const padding = _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n\n if (containerType === \"ellipse\" && !legacy) {\n //zsviczian\n return Math.round((dimension + padding) / Math.sqrt(2) * 2);\n }\n\n if (containerType === \"arrow\") {\n return dimension + padding * 8;\n }\n\n if (containerType === \"diamond\" && !legacy) {\n //zsviczian\n return 2 * (dimension + padding);\n }\n\n return dimension + padding;\n};\nconst getBoundTextMaxWidth = (container, boundTextElement) => {\n var _a, _b;\n\n const {\n width\n } = container;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n const minWidth = ((_a = boundTextElement === null || boundTextElement === void 0 ? void 0 : boundTextElement.fontSize) !== null && _a !== void 0 ? _a : _constants__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_FONT_SIZE) * _constants__WEBPACK_IMPORTED_MODULE_2__.ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO;\n return Math.max(_constants__WEBPACK_IMPORTED_MODULE_2__.ARROW_LABEL_WIDTH_FRACTION * width, minWidth);\n }\n\n const legacy = (_b = container.customData) === null || _b === void 0 ? void 0 : _b.legacyTextWrap; //zsviczian\n\n if (container.type === \"ellipse\" && !legacy) {\n // The width of the largest rectangle inscribed inside an ellipse is\n // Math.round((ellipse.width / 2) * Math.sqrt(2)) which is derived from\n // equation of an ellipse -https://github.com/excalidraw/excalidraw/pull/6172\n return Math.round(width / 2 * Math.sqrt(2)) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n if (container.type === \"diamond\" && !legacy) {\n // The width of the largest rectangle inscribed inside a rhombus is\n // Math.round(width / 2) - https://github.com/excalidraw/excalidraw/pull/6265\n return Math.round(width / 2) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n return width - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nconst getBoundTextMaxHeight = (container, boundTextElement) => {\n var _a;\n\n const {\n height\n } = container;\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_5__.isArrowElement)(container)) {\n const containerHeight = height - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 8 * 2;\n\n if (containerHeight <= 0) {\n return boundTextElement.height;\n }\n\n return height;\n }\n\n const legacy = (_a = container.customData) === null || _a === void 0 ? void 0 : _a.legacyTextWrap; //zsviczian\n\n if (container.type === \"ellipse\" && !legacy) {\n // The height of the largest rectangle inscribed inside an ellipse is\n // Math.round((ellipse.height / 2) * Math.sqrt(2)) which is derived from\n // equation of an ellipse - https://github.com/excalidraw/excalidraw/pull/6172\n return Math.round(height / 2 * Math.sqrt(2)) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n if (container.type === \"diamond\" && !legacy) {\n // The height of the largest rectangle inscribed inside a rhombus is\n // Math.round(height / 2) - https://github.com/excalidraw/excalidraw/pull/6265\n return Math.round(height / 2) - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n }\n\n return height - _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\nconst isMeasureTextSupported = () => {\n const width = getTextWidth(DUMMY_TEXT, (0,_utils__WEBPACK_IMPORTED_MODULE_0__.getFontString)({\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_FONT_SIZE,\n fontFamily: _constants__WEBPACK_IMPORTED_MODULE_2__.DEFAULT_FONT_FAMILY\n }));\n return width > 0;\n};\nconst getMinTextElementWidth = (font, lineHeight) => {\n return measureText(\"\", font, lineHeight).width + _constants__WEBPACK_IMPORTED_MODULE_2__.BOUND_TEXT_PADDING * 2;\n};\n/** retrieves text from text elements and concatenates to a single string */\n\nconst getTextFromElements = (elements, separator = \"\\n\\n\") => {\n const text = elements.reduce((acc, element) => {\n if ((0,___WEBPACK_IMPORTED_MODULE_3__.isTextElement)(element)) {\n acc.push(element.text);\n }\n\n return acc;\n }, []).join(separator);\n return text;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/textElement.ts?");
3029
+
3030
+ /***/ }),
3031
+
3032
+ /***/ "./element/textWrapping.ts":
3033
+ /*!*********************************!*\
3034
+ !*** ./element/textWrapping.ts ***!
3035
+ \*********************************/
3036
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3037
+
3038
+ "use strict";
3039
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"containsCJK\": () => (/* binding */ containsCJK),\n/* harmony export */ \"parseTokens\": () => (/* binding */ parseTokens),\n/* harmony export */ \"wrapText\": () => (/* binding */ wrapText)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n\n\nlet cachedCjkRegex;\nlet cachedLineBreakRegex;\nlet cachedEmojiRegex;\n/**\n * Test if a given text contains any CJK characters (including symbols, punctuation, etc,).\n */\n\nconst containsCJK = text => {\n if (!cachedCjkRegex) {\n cachedCjkRegex = Regex.class(...Object.values(CJK));\n }\n\n return cachedCjkRegex.test(text);\n};\n\nconst getLineBreakRegex = () => {\n if (!cachedLineBreakRegex) {\n try {\n cachedLineBreakRegex = getLineBreakRegexAdvanced();\n } catch (_a) {\n cachedLineBreakRegex = getLineBreakRegexSimple();\n }\n }\n\n return cachedLineBreakRegex;\n};\n\nconst getEmojiRegex = () => {\n if (!cachedEmojiRegex) {\n cachedEmojiRegex = getEmojiRegexUnicode();\n }\n\n return cachedEmojiRegex;\n};\n/**\n * Common symbols used across different languages.\n */\n\n\nconst COMMON = {\n /**\n * Natural breaking points for any grammars.\n *\n * Hello world\n * ↑ BREAK ALWAYS \" \" → [\"Hello\", \" \", \"world\"]\n * Hello-world\n * ↑ BREAK AFTER \"-\" → [\"Hello-\", \"world\"]\n */\n WHITESPACE: /\\s/u,\n HYPHEN: /-/u,\n\n /**\n * Generally do not break, unless closed symbol is followed by an opening symbol.\n *\n * Also, western punctation is often used in modern Korean and expects to be treated\n * similarly to the CJK opening and closing symbols.\n *\n * Hello(한글)→ [\"Hello\", \"(한\", \"글)\"]\n * ↑ BREAK BEFORE \"(\"\n * ↑ BREAK AFTER \")\"\n */\n OPENING: /<\\(\\[\\{/u,\n CLOSING: />\\)\\]\\}.,:;!\\?…\\//u\n};\n/**\n * Characters and symbols used in Chinese, Japanese and Korean.\n */\n\nconst CJK = {\n /**\n * Every CJK breaks before and after, unless it's paired with an opening or closing symbol.\n *\n * Does not include every possible char used in CJK texts, such as currency, parentheses or punctuation.\n */\n CHAR: /\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}`'^〃〰〆#&*+-ー/\=|¦〒¬ ̄/u,\n\n /**\n * Opening and closing CJK punctuation breaks before and after all such characters (in case of many),\n * and creates pairs with neighboring characters.\n *\n * Hello た。→ [\"Hello\", \"た。\"]\n * ↑ DON'T BREAK \"た。\"\n * * Hello「た」 World → [\"Hello\", \"「た」\", \"World\"]\n * ↑ DON'T BREAK \"「た\"\n * ↑ DON'T BREAK \"た\"\n * ↑ BREAK BEFORE \"「\"\n * ↑ BREAK AFTER \"」\"\n */\n // eslint-disable-next-line prettier/prettier\n OPENING: /([{〈《⦅「「『【〖〔〘〚<〝/u,\n CLOSING: /)]}〉》⦆」」』】〗〕〙〛>。.,、〟‥?!:;・〜〞/u,\n\n /**\n * Currency symbols break before, not after\n *\n * Price¥100 → [\"Price\", \"¥100\"]\n * ↑ BREAK BEFORE \"¥\"\n */\n CURRENCY: /¥₩£¢$/u\n};\nconst EMOJI = {\n FLAG: /\\p{RI}\\p{RI}/u,\n JOINER: /(?:\\p{Emoji_Modifier}|\\uFE0F\\u20E3?|[\\u{E0020}-\\u{E007E}]+\\u{E007F})?/u,\n ZWJ: /\\u200D/u,\n ANY: /[\\p{Emoji}]/u,\n MOST: /[\\p{Extended_Pictographic}\\p{Emoji_Presentation}]/u\n};\n/**\n * Simple fallback for browsers (mainly Safari < 16.4) that don't support \"Lookbehind assertion\".\n *\n * Browser support as of 10/2024:\n * - 91% Lookbehind assertion https://caniuse.com/mdn-javascript_regular_expressions_lookbehind_assertion\n * - 94% Unicode character class escape https://caniuse.com/mdn-javascript_regular_expressions_unicode_character_class_escape\n *\n * Does not include advanced CJK breaking rules, but covers most of the core cases, especially for latin.\n */\n\nconst getLineBreakRegexSimple = () => Regex.or(getEmojiRegex(), Break.On(COMMON.HYPHEN, COMMON.WHITESPACE, CJK.CHAR));\n/**\n * Specifies the line breaking rules based for alphabetic-based languages,\n * Chinese, Japanese, Korean and Emojis.\n *\n * \"Hello-world\" → [\"Hello-\", \"world\"]\n * \"Hello 「世界。」🌎🗺\" → [\"Hello\", \" \", \"「世\", \"界。」\", \"🌎\", \"🗺\"]\n */\n\n\nconst getLineBreakRegexAdvanced = () => Regex.or( // Unicode-defined regex for (multi-codepoint) Emojis\ngetEmojiRegex(), // Rules for whitespace and hyphen\nBreak.Before(COMMON.WHITESPACE).Build(), Break.After(COMMON.WHITESPACE, COMMON.HYPHEN).Build(), // Rules for CJK (chars, symbols, currency)\nBreak.Before(CJK.CHAR, CJK.CURRENCY).NotPrecededBy(COMMON.OPENING, CJK.OPENING).Build(), Break.After(CJK.CHAR).NotFollowedBy(COMMON.HYPHEN, COMMON.CLOSING, CJK.CLOSING).Build(), // Rules for opening and closing punctuation\nBreak.BeforeMany(CJK.OPENING).NotPrecededBy(COMMON.OPENING).Build(), Break.AfterMany(CJK.CLOSING).NotFollowedBy(COMMON.CLOSING).Build(), Break.AfterMany(COMMON.CLOSING).FollowedBy(COMMON.OPENING).Build());\n/**\n * Matches various emoji types.\n *\n * 1. basic emojis (😀, 🌍)\n * 2. flags (🇨🇿)\n * 3. multi-codepoint emojis:\n * - skin tones (👍🏽)\n * - variation selectors (☂️)\n * - keycaps (1️⃣)\n * - tag sequences (🏴󠁧󠁢󠁥󠁮󠁧󠁿)\n * - emoji sequences (👨‍👩‍👧‍👦, 👩‍🚀, 🏳️‍🌈)\n *\n * Unicode points:\n * - \\uFE0F: presentation selector\n * - \\u20E3: enclosing keycap\n * - \\u200D: zero width joiner\n * - \\u{E0020}-\\u{E007E}: tags\n * - \\u{E007F}: cancel tag\n *\n * @see https://unicode.org/reports/tr51/#EBNF_and_Regex, with changes:\n * - replaced \\p{Emoji} with [\\p{Extended_Pictographic}\\p{Emoji_Presentation}], see more in `should tokenize emojis mixed with mixed text` test\n * - replaced \\p{Emod} with \\p{Emoji_Modifier} as some engines do not understand the abbreviation (i.e. https://devina.io/redos-checker)\n */\n\n\nconst getEmojiRegexUnicode = () => Regex.group(Regex.or(EMOJI.FLAG, Regex.and(EMOJI.MOST, EMOJI.JOINER, Regex.build(`(?:${EMOJI.ZWJ.source}(?:${EMOJI.FLAG.source}|${EMOJI.ANY.source}${EMOJI.JOINER.source}))*`))));\n/**\n * Regex utilities for unicode character classes.\n */\n\n\nconst Regex = {\n /**\n * Builds a regex from a string.\n */\n build: regex => new RegExp(regex, \"u\"),\n\n /**\n * Joins regexes into a single string.\n */\n join: (...regexes) => regexes.map(x => x.source).join(\"\"),\n\n /**\n * Joins regexes into a single regex as with \"and\" operator.\n */\n and: (...regexes) => Regex.build(Regex.join(...regexes)),\n\n /**\n * Joins regexes into a single regex with \"or\" operator.\n */\n or: (...regexes) => Regex.build(regexes.map(x => x.source).join(\"|\")),\n\n /**\n * Puts regexes into a matching group.\n */\n group: (...regexes) => Regex.build(`(${Regex.join(...regexes)})`),\n\n /**\n * Puts regexes into a character class.\n */\n class: (...regexes) => Regex.build(`[${Regex.join(...regexes)}]`)\n};\n/**\n * Human-readable lookahead and lookbehind utilities for defining line break\n * opportunities between pairs of character classes.\n */\n\nconst Break = {\n /**\n * Break on the given class of characters.\n */\n On: (...regexes) => {\n const joined = Regex.join(...regexes);\n return Regex.build(`([${joined}])`);\n },\n\n /**\n * Break before the given class of characters.\n */\n Before: (...regexes) => {\n const joined = Regex.join(...regexes);\n\n const builder = () => Regex.build(`(?=[${joined}])`);\n\n return Break.Chain(builder);\n },\n\n /**\n * Break after the given class of characters.\n */\n After: (...regexes) => {\n const joined = Regex.join(...regexes);\n\n const builder = () => Regex.build(`(?<=[${joined}])`);\n\n return Break.Chain(builder);\n },\n\n /**\n * Break before one or multiple characters of the same class.\n */\n BeforeMany: (...regexes) => {\n const joined = Regex.join(...regexes);\n\n const builder = () => Regex.build(`(?<![${joined}])(?=[${joined}])`);\n\n return Break.Chain(builder);\n },\n\n /**\n * Break after one or multiple character from the same class.\n */\n AfterMany: (...regexes) => {\n const joined = Regex.join(...regexes);\n\n const builder = () => Regex.build(`(?<=[${joined}])(?![${joined}])`);\n\n return Break.Chain(builder);\n },\n\n /**\n * Do not break before the given class of characters.\n */\n NotBefore: (...regexes) => {\n const joined = Regex.join(...regexes);\n\n const builder = () => Regex.build(`(?![${joined}])`);\n\n return Break.Chain(builder);\n },\n\n /**\n * Do not break after the given class of characters.\n */\n NotAfter: (...regexes) => {\n const joined = Regex.join(...regexes);\n\n const builder = () => Regex.build(`(?<![${joined}])`);\n\n return Break.Chain(builder);\n },\n Chain: rootBuilder => ({\n /**\n * Build the root regex.\n */\n Build: rootBuilder,\n\n /**\n * Specify additional class of characters that should precede the root regex.\n */\n PreceededBy: (...regexes) => {\n const root = rootBuilder();\n const preceeded = Break.After(...regexes).Build();\n\n const builder = () => Regex.and(preceeded, root);\n\n return Break.Chain(builder);\n },\n\n /**\n * Specify additional class of characters that should follow the root regex.\n */\n FollowedBy: (...regexes) => {\n const root = rootBuilder();\n const followed = Break.Before(...regexes).Build();\n\n const builder = () => Regex.and(root, followed);\n\n return Break.Chain(builder);\n },\n\n /**\n * Specify additional class of characters that should not precede the root regex.\n */\n NotPrecededBy: (...regexes) => {\n const root = rootBuilder();\n const notPreceeded = Break.NotAfter(...regexes).Build();\n\n const builder = () => Regex.and(notPreceeded, root);\n\n return Break.Chain(builder);\n },\n\n /**\n * Specify additional class of characters that should not follow the root regex.\n */\n NotFollowedBy: (...regexes) => {\n const root = rootBuilder();\n const notFollowed = Break.NotBefore(...regexes).Build();\n\n const builder = () => Regex.and(root, notFollowed);\n\n return Break.Chain(builder);\n }\n })\n};\n/**\n * Breaks the line into the tokens based on the found line break opporutnities.\n */\n\nconst parseTokens = line => {\n const breakLineRegex = getLineBreakRegex(); // normalizing to single-codepoint composed chars due to canonical equivalence\n // of multi-codepoint versions for chars like č, で (~ so that we don't break a line in between c and ˇ)\n // filtering due to multi-codepoint chars like 👨‍👩‍👧‍👦, 👩🏽‍🦰\n\n return line.normalize(\"NFC\").split(breakLineRegex).filter(Boolean);\n};\n/**\n * Wraps the original text into the lines based on the given width.\n */\n\nconst wrapText = (text, font, maxWidth) => {\n // if maxWidth is not finite or NaN which can happen in case of bugs in\n // computation, we need to make sure we don't continue as we'll end up\n // in an infinite loop\n if (!Number.isFinite(maxWidth) || maxWidth < 0) {\n return text;\n }\n\n const lines = [];\n const originalLines = text.split(\"\\n\");\n\n for (const originalLine of originalLines) {\n const currentLineWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_1__.getLineWidth)(originalLine, font, true);\n\n if (currentLineWidth <= maxWidth) {\n lines.push(originalLine);\n continue;\n }\n\n const wrappedLine = wrapLine(originalLine, font, maxWidth);\n lines.push(...wrappedLine);\n }\n\n return lines.join(\"\\n\");\n};\n/**\n * Wraps the original line into the lines based on the given width.\n */\n\nconst wrapLine = (line, font, maxWidth) => {\n var _a;\n\n const lines = [];\n const tokens = parseTokens(line);\n const tokenIterator = tokens[Symbol.iterator]();\n let currentLine = \"\";\n let currentLineWidth = 0;\n let iterator = tokenIterator.next();\n\n while (!iterator.done) {\n const token = iterator.value;\n const testLine = currentLine + token; // cache single codepoint whitespace, CJK or emoji width calc. as kerning should not apply here\n\n const testLineWidth = isSingleCharacter(token) ? currentLineWidth + _textElement__WEBPACK_IMPORTED_MODULE_1__.charWidth.calculate(token, font) : (0,_textElement__WEBPACK_IMPORTED_MODULE_1__.getLineWidth)(testLine, font, true); // build up the current line, skipping length check for possibly trailing whitespaces\n\n if (/\\s/.test(token) || testLineWidth <= maxWidth) {\n currentLine = testLine;\n currentLineWidth = testLineWidth;\n iterator = tokenIterator.next();\n continue;\n } // current line is empty => just the token (word) is longer than `maxWidth` and needs to be wrapped\n\n\n if (!currentLine) {\n const wrappedWord = wrapWord(token, font, maxWidth);\n const trailingLine = (_a = wrappedWord[wrappedWord.length - 1]) !== null && _a !== void 0 ? _a : \"\";\n const precedingLines = wrappedWord.slice(0, -1);\n lines.push(...precedingLines); // trailing line of the wrapped word might still be joined with next token/s\n\n currentLine = trailingLine;\n currentLineWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_1__.getLineWidth)(trailingLine, font, true);\n iterator = tokenIterator.next();\n } else {\n // push & reset, but don't iterate on the next token, as we didn't use it yet!\n lines.push(currentLine.trimEnd()); // purposefully not iterating and not setting `currentLine` to `token`, so that we could use a simple !currentLine check above\n\n currentLine = \"\";\n currentLineWidth = 0;\n }\n } // iterator done, push the trailing line if exists\n\n\n if (currentLine) {\n const trailingLine = trimLine(currentLine, font, maxWidth);\n lines.push(trailingLine);\n }\n\n return lines;\n};\n/**\n * Wraps the word into the lines based on the given width.\n */\n\n\nconst wrapWord = (word, font, maxWidth) => {\n // multi-codepoint emojis are already broken apart and shouldn't be broken further\n if (getEmojiRegex().test(word)) {\n return [word];\n }\n\n satisfiesWordInvariant(word);\n const lines = [];\n const chars = Array.from(word);\n let currentLine = \"\";\n let currentLineWidth = 0;\n\n for (const char of chars) {\n const _charWidth = _textElement__WEBPACK_IMPORTED_MODULE_1__.charWidth.calculate(char, font);\n\n const testLineWidth = currentLineWidth + _charWidth;\n\n if (testLineWidth <= maxWidth) {\n currentLine = currentLine + char;\n currentLineWidth = testLineWidth;\n continue;\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n currentLine = char;\n currentLineWidth = _charWidth;\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n return lines;\n};\n/**\n * Similarly to browsers, does not trim all trailing whitespaces, but only those exceeding the `maxWidth`.\n */\n\n\nconst trimLine = (line, font, maxWidth) => {\n var _a;\n\n const shouldTrimWhitespaces = (0,_textElement__WEBPACK_IMPORTED_MODULE_1__.getLineWidth)(line, font, true) > maxWidth;\n\n if (!shouldTrimWhitespaces) {\n return line;\n } // defensively default to `trimeEnd` in case the regex does not match\n\n\n let [, trimmedLine, whitespaces] = (_a = line.match(/^(.+?)(\\s+)$/)) !== null && _a !== void 0 ? _a : [line, line.trimEnd(), \"\"];\n let trimmedLineWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_1__.getLineWidth)(trimmedLine, font, true);\n\n for (const whitespace of Array.from(whitespaces)) {\n const _charWidth = _textElement__WEBPACK_IMPORTED_MODULE_1__.charWidth.calculate(whitespace, font);\n\n const testLineWidth = trimmedLineWidth + _charWidth;\n\n if (testLineWidth > maxWidth) {\n break;\n }\n\n trimmedLine = trimmedLine + whitespace;\n trimmedLineWidth = testLineWidth;\n }\n\n return trimmedLine;\n};\n/**\n * Check if the given string is a single character.\n *\n * Handles multi-byte chars (é, 中) and purposefully does not handle multi-codepoint char (👨‍👩‍👧‍👦, 👩🏽‍🦰).\n */\n\n\nconst isSingleCharacter = maybeSingleCharacter => {\n return maybeSingleCharacter.codePointAt(0) !== undefined && maybeSingleCharacter.codePointAt(1) === undefined;\n};\n/**\n * Invariant for the word wrapping algorithm.\n */\n\n\nconst satisfiesWordInvariant = word => {\n if (\"development\" === _constants__WEBPACK_IMPORTED_MODULE_0__.ENV.TEST || \"development\" !== \"production\") {\n if (/\\s/.test(word)) {\n throw new Error(\"Word should not contain any whitespaces!\");\n }\n }\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/textWrapping.ts?");
3029
3040
 
3030
3041
  /***/ }),
3031
3042
 
@@ -3036,7 +3047,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3036
3047
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3037
3048
 
3038
3049
  "use strict";
3039
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"textWysiwyg\": () => (/* binding */ textWysiwyg)\n/* harmony export */ });\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../keys */ \"./keys.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _actions_actionProperties__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../actions/actionProperties */ \"./actions/actionProperties.tsx\");\n/* harmony import */ var _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../actions/actionCanvas */ \"./actions/actionCanvas.tsx\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../clipboard */ \"./clipboard.ts\");\n/* harmony import */ var _containerCache__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./containerCache */ \"./element/containerCache.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst getTransform = (width, height, angle, appState, maxWidth, maxHeight) => {\n const {\n zoom\n } = appState;\n const degree = 180 * angle / Math.PI;\n let translateX = width * (zoom.value - 1) / 2;\n let translateY = height * (zoom.value - 1) / 2;\n\n if (width > maxWidth && zoom.value !== 1) {\n translateX = maxWidth * (zoom.value - 1) / 2;\n }\n\n if (height > maxHeight && zoom.value !== 1) {\n translateY = maxHeight * (zoom.value - 1) / 2;\n }\n\n return `translate(${translateX}px, ${translateY}px) scale(${zoom.value}) rotate(${degree}deg)`;\n};\n\nconst textWysiwyg = ({\n id,\n onChange,\n onSubmit,\n getViewportCoords,\n element,\n canvas,\n excalidrawContainer,\n app,\n autoSelect = true\n}) => {\n const textPropertiesUpdated = (updatedTextElement, editable) => {\n if (!editable.style.fontFamily || !editable.style.fontSize) {\n return false;\n }\n\n const currentFont = editable.style.fontFamily.replace(/\"/g, \"\");\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontFamilyString)({\n fontFamily: updatedTextElement.fontFamily\n }) !== currentFont) {\n return true;\n }\n\n if (`${updatedTextElement.fontSize}px` !== editable.style.fontSize) {\n return true;\n }\n\n return false;\n };\n\n const updateWysiwygStyle = () => {\n var _a;\n\n const appState = app.state;\n const updatedTextElement = (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getScene(element)) === null || _a === void 0 ? void 0 : _a.getElement(id);\n\n if (!updatedTextElement) {\n return;\n }\n\n const {\n textAlign,\n verticalAlign\n } = updatedTextElement;\n const elementsMap = app.scene.getNonDeletedElementsMap();\n\n if (updatedTextElement && (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(updatedTextElement)) {\n let coordX = updatedTextElement.x;\n let coordY = updatedTextElement.y;\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getContainerElement)(updatedTextElement, app.scene.getNonDeletedElementsMap());\n let width = updatedTextElement.width; // set to element height by default since that's\n // what is going to be used for unbounded text\n\n let height = updatedTextElement.height;\n let maxWidth = updatedTextElement.width;\n let maxHeight = updatedTextElement.height;\n\n if (container && updatedTextElement.containerId) {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container)) {\n const boundTextCoords = _linearElementEditor__WEBPACK_IMPORTED_MODULE_9__.LinearElementEditor.getBoundTextElementPosition(container, updatedTextElement, elementsMap);\n coordX = boundTextCoords.x;\n coordY = boundTextCoords.y;\n }\n\n const propertiesUpdated = textPropertiesUpdated(updatedTextElement, editable);\n let originalContainerData;\n\n if (propertiesUpdated) {\n originalContainerData = (0,_containerCache__WEBPACK_IMPORTED_MODULE_11__.updateOriginalContainerCache)(container.id, container.height);\n } else {\n originalContainerData = _containerCache__WEBPACK_IMPORTED_MODULE_11__.originalContainerCache[container.id];\n\n if (!originalContainerData) {\n originalContainerData = (0,_containerCache__WEBPACK_IMPORTED_MODULE_11__.updateOriginalContainerCache)(container.id, container.height);\n }\n }\n\n maxWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxWidth)(container, updatedTextElement);\n maxHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxHeight)(container, updatedTextElement); // autogrow container height if text exceeds\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container) && height > maxHeight) {\n const targetContainerHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.computeContainerDimensionForBoundText)(height, container.type);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n height: targetContainerHeight\n });\n return;\n } else if ( // autoshrink container height until original container height\n // is reached when text is removed\n !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container) && container.height > originalContainerData.height && height < maxHeight) {\n const targetContainerHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.computeContainerDimensionForBoundText)(height, container.type);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n height: targetContainerHeight\n });\n } else {\n const {\n y\n } = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.computeBoundTextPosition)(container, updatedTextElement, elementsMap);\n coordY = y;\n }\n }\n\n const [viewportX, viewportY] = getViewportCoords(coordX, coordY);\n const initialSelectionStart = editable.selectionStart;\n const initialSelectionEnd = editable.selectionEnd;\n const initialLength = editable.value.length; // restore cursor position after value updated so it doesn't\n // go to the end of text when container auto expanded\n\n if (initialSelectionStart === initialSelectionEnd && initialSelectionEnd !== initialLength) {\n // get diff between length and selection end and shift\n // the cursor by \"diff\" times to position correctly\n const diff = initialLength - initialSelectionEnd;\n editable.selectionStart = editable.value.length - diff;\n editable.selectionEnd = editable.value.length - diff;\n }\n\n if (!container) {\n maxWidth = (appState.width - 8 - viewportX) / appState.zoom.value;\n width = Math.min(width, maxWidth);\n } else {\n width += 0.5;\n } // add 5% buffer otherwise it causes wysiwyg to jump\n\n\n height *= 1.05;\n const font = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontString)(updatedTextElement); // adding left and right padding buffer, so that browser does not cut the glyphs (does not work in Safari)\n\n const padding = !_constants__WEBPACK_IMPORTED_MODULE_4__.isSafari ? Math.ceil(updatedTextElement.fontSize / appState.zoom.value / 2) : 0; // Make sure text editor height doesn't go beyond viewport\n\n const editorMaxHeight = (appState.height - viewportY) / appState.zoom.value;\n Object.assign(editable.style, {\n font,\n // must be defined *after* font ¯\\_(ツ)_/¯\n lineHeight: updatedTextElement.lineHeight,\n width: `${Math.ceil(width)}px`,\n height: `${height}px`,\n left: `${viewportX - padding}px`,\n top: `${viewportY}px`,\n transform: getTransform(width, height, (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getTextElementAngle)(updatedTextElement, container), appState, maxWidth, editorMaxHeight),\n padding: `0 ${padding}px`,\n textAlign,\n verticalAlign,\n color: updatedTextElement.strokeColor,\n opacity: updatedTextElement.opacity / 100,\n filter: \"var(--theme-filter)\",\n maxHeight: `${editorMaxHeight}px`\n });\n editable.scrollTop = 0; // For some reason updating font attribute doesn't set font family\n // hence updating font family explicitly for test environment\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.isTestEnv)()) {\n editable.style.fontFamily = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontFamilyString)(updatedTextElement);\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(updatedTextElement, {\n x: coordX,\n y: coordY\n });\n }\n };\n\n const editable = document.createElement(\"textarea\");\n editable.dir = \"auto\";\n editable.tabIndex = 0;\n editable.dataset.type = \"wysiwyg\"; // prevent line wrapping on Safari\n\n editable.wrap = \"off\";\n editable.classList.add(\"excalidraw-wysiwyg\");\n let whiteSpace = \"pre\";\n let wordBreak = \"normal\";\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(element) || !element.autoResize) {\n whiteSpace = \"pre-wrap\";\n wordBreak = \"break-word\";\n }\n\n Object.assign(editable.style, {\n position: \"absolute\",\n display: \"inline-block\",\n minHeight: \"1em\",\n backfaceVisibility: \"hidden\",\n margin: 0,\n border: 0,\n outline: 0,\n resize: \"none\",\n background: \"transparent\",\n overflow: \"hidden\",\n // must be specified because in dark mode canvas creates a stacking context\n zIndex: \"var(--zIndex-wysiwyg)\",\n wordBreak,\n // prevent line wrapping (`whitespace: nowrap` doesn't work on FF)\n whiteSpace,\n overflowWrap: \"break-word\",\n boxSizing: \"content-box\"\n });\n editable.value = element.originalText;\n updateWysiwygStyle();\n\n if (onChange) {\n editable.onpaste = async event => {\n const clipboardData = await (0,_clipboard__WEBPACK_IMPORTED_MODULE_10__.parseClipboard)(event, true);\n\n if (!clipboardData.text) {\n return;\n }\n\n const data = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(clipboardData.text);\n\n if (!data) {\n return;\n }\n\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getContainerElement)(element, app.scene.getNonDeletedElementsMap());\n const font = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontString)({\n fontSize: app.state.currentItemFontSize,\n fontFamily: app.state.currentItemFontFamily\n });\n\n if (container) {\n const boundTextElement = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextElement)(container, app.scene.getNonDeletedElementsMap());\n const wrappedText = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.wrapText)(`${editable.value}${data}`, font, (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxWidth)(container, boundTextElement));\n const width = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getTextWidth)(wrappedText, font, true);\n editable.style.width = `${Math.ceil(width)}px`; //zsviczian Obsidian app zoom !== 100% issue\n }\n };\n\n editable.oninput = () => {\n const normalized = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(editable.value);\n\n if (editable.value !== normalized) {\n const selectionStart = editable.selectionStart;\n editable.value = normalized; // put the cursor at some position close to where it was before\n // normalization (otherwise it'll end up at the end of the text)\n\n editable.selectionStart = selectionStart;\n editable.selectionEnd = selectionStart;\n }\n\n onChange(editable.value);\n };\n }\n\n editable.onkeydown = event => {\n if (!event.shiftKey && _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__.actionZoomIn.keyTest(event)) {\n event.preventDefault();\n app.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__.actionZoomIn);\n updateWysiwygStyle();\n } else if (!event.shiftKey && _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__.actionZoomOut.keyTest(event)) {\n event.preventDefault();\n app.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__.actionZoomOut);\n updateWysiwygStyle();\n } else if (!event.shiftKey && _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__.actionResetZoom.keyTest(event)) {\n event.preventDefault();\n app.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_8__.actionResetZoom);\n updateWysiwygStyle();\n } else if (_actions_actionProperties__WEBPACK_IMPORTED_MODULE_7__.actionDecreaseFontSize.keyTest(event)) {\n app.actionManager.executeAction(_actions_actionProperties__WEBPACK_IMPORTED_MODULE_7__.actionDecreaseFontSize);\n } else if (_actions_actionProperties__WEBPACK_IMPORTED_MODULE_7__.actionIncreaseFontSize.keyTest(event)) {\n app.actionManager.executeAction(_actions_actionProperties__WEBPACK_IMPORTED_MODULE_7__.actionIncreaseFontSize);\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.ESCAPE) {\n event.preventDefault();\n submittedViaKeyboard = true;\n handleSubmit();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.ENTER && event[_keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n\n if (event.isComposing || event.keyCode === 229) {\n return;\n }\n\n submittedViaKeyboard = true;\n handleSubmit();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.TAB || event[_keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.CTRL_OR_CMD] && (event.code === _keys__WEBPACK_IMPORTED_MODULE_0__.CODES.BRACKET_LEFT || event.code === _keys__WEBPACK_IMPORTED_MODULE_0__.CODES.BRACKET_RIGHT)) {\n event.preventDefault();\n\n if (event.isComposing) {\n return;\n } else if (event.shiftKey || event.code === _keys__WEBPACK_IMPORTED_MODULE_0__.CODES.BRACKET_LEFT) {\n outdent();\n } else {\n indent();\n } // We must send an input event to resize the element\n\n\n editable.dispatchEvent(new Event(\"input\"));\n }\n };\n\n const TAB_SIZE = 4;\n const TAB = \" \".repeat(TAB_SIZE);\n const RE_LEADING_TAB = new RegExp(`^ {1,${TAB_SIZE}}`);\n\n const indent = () => {\n const {\n selectionStart,\n selectionEnd\n } = editable;\n const linesStartIndices = getSelectedLinesStartIndices();\n let value = editable.value;\n linesStartIndices.forEach(startIndex => {\n const startValue = value.slice(0, startIndex);\n const endValue = value.slice(startIndex);\n value = `${startValue}${TAB}${endValue}`;\n });\n editable.value = value;\n editable.selectionStart = selectionStart + TAB_SIZE;\n editable.selectionEnd = selectionEnd + TAB_SIZE * linesStartIndices.length;\n };\n\n const outdent = () => {\n const {\n selectionStart,\n selectionEnd\n } = editable;\n const linesStartIndices = getSelectedLinesStartIndices();\n const removedTabs = [];\n let value = editable.value;\n linesStartIndices.forEach(startIndex => {\n const tabMatch = value.slice(startIndex, startIndex + TAB_SIZE).match(RE_LEADING_TAB);\n\n if (tabMatch) {\n const startValue = value.slice(0, startIndex);\n const endValue = value.slice(startIndex + tabMatch[0].length); // Delete a tab from the line\n\n value = `${startValue}${endValue}`;\n removedTabs.push(startIndex);\n }\n });\n editable.value = value;\n\n if (removedTabs.length) {\n if (selectionStart > removedTabs[removedTabs.length - 1]) {\n editable.selectionStart = Math.max(selectionStart - TAB_SIZE, removedTabs[removedTabs.length - 1]);\n } else {\n // If the cursor is before the first tab removed, ex:\n // Line| #1\n // Line #2\n // Lin|e #3\n // we should reset the selectionStart to his initial value.\n editable.selectionStart = selectionStart;\n }\n\n editable.selectionEnd = Math.max(editable.selectionStart, selectionEnd - TAB_SIZE * removedTabs.length);\n }\n };\n /**\n * @returns indices of start positions of selected lines, in reverse order\n */\n\n\n const getSelectedLinesStartIndices = () => {\n let {\n selectionStart,\n selectionEnd,\n value\n } = editable; // chars before selectionStart on the same line\n\n const startOffset = value.slice(0, selectionStart).match(/[^\\n]*$/)[0].length; // put caret at the start of the line\n\n selectionStart = selectionStart - startOffset;\n const selected = value.slice(selectionStart, selectionEnd);\n return selected.split(\"\\n\").reduce((startIndices, line, idx, lines) => startIndices.concat(idx ? // curr line index is prev line's start + prev line's length + \\n\n startIndices[idx - 1] + lines[idx - 1].length + 1 : // first selected line\n selectionStart), []).reverse();\n };\n\n const stopEvent = event => {\n if (event.target instanceof HTMLCanvasElement) {\n event.preventDefault();\n event.stopPropagation();\n }\n }; // using a state variable instead of passing it to the handleSubmit callback\n // so that we don't need to create separate a callback for event handlers\n\n\n let submittedViaKeyboard = false;\n\n const handleSubmit = () => {\n var _a, _b; // prevent double submit\n\n\n if (isDestroyed) {\n return;\n }\n\n isDestroyed = true; // cleanup must be run before onSubmit otherwise when app blurs the wysiwyg\n // it'd get stuck in an infinite loop of blur→onSubmit after we re-focus the\n // wysiwyg on update\n\n cleanup();\n const updateElement = (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getScene(element)) === null || _a === void 0 ? void 0 : _a.getElement(element.id);\n\n if (!updateElement) {\n return;\n }\n\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getContainerElement)(updateElement, app.scene.getNonDeletedElementsMap());\n\n if (container) {\n if (editable.value.trim()) {\n const boundTextElementId = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextElementId)(container);\n\n if (!boundTextElementId || boundTextElementId !== element.id) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: element.id\n })\n });\n } else if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container)) {\n // updating an arrow label may change bounds, prevent stale cache:\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.bumpVersion)(container);\n }\n } else {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n boundElements: (_b = container.boundElements) === null || _b === void 0 ? void 0 : _b.filter(ele => !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(ele))\n });\n }\n\n (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.redrawTextBoundingBox)(updateElement, container, app.scene.getNonDeletedElementsMap());\n }\n\n app.setState({\n openPopup: null\n }); //zsviczian (container text color issue)\n\n onSubmit({\n viaKeyboard: submittedViaKeyboard,\n nextOriginalText: editable.value\n });\n };\n\n const cleanup = () => {\n // remove events to ensure they don't late-fire\n editable.onblur = null;\n editable.oninput = null;\n editable.onkeydown = null;\n\n if (observer) {\n observer.disconnect();\n }\n\n window.removeEventListener(\"resize\", updateWysiwygStyle);\n window.removeEventListener(\"wheel\", stopEvent, true);\n window.removeEventListener(\"pointerdown\", onPointerDown);\n window.removeEventListener(\"pointerup\", bindBlurEvent);\n window.removeEventListener(\"blur\", handleSubmit);\n window.removeEventListener(\"beforeunload\", handleSubmit);\n unbindUpdate();\n unbindOnScroll();\n editable.remove();\n };\n\n const bindBlurEvent = event => {\n window.removeEventListener(\"pointerup\", bindBlurEvent); // Deferred so that the pointerdown that initiates the wysiwyg doesn't\n // trigger the blur on ensuing pointerup.\n // Also to handle cases such as picking a color which would trigger a blur\n // in that same tick.\n\n const target = event === null || event === void 0 ? void 0 : event.target;\n const isPropertiesTrigger = target instanceof HTMLElement && target.classList.contains(\"properties-trigger\");\n setTimeout(() => {\n editable.onblur = handleSubmit; // case: clicking on the same property → no change → no update → no focus\n\n if (!isPropertiesTrigger) {\n editable.focus();\n }\n });\n };\n\n const temporarilyDisableSubmit = () => {\n editable.onblur = null;\n window.addEventListener(\"pointerup\", bindBlurEvent); // handle edge-case where pointerup doesn't fire e.g. due to user\n // alt-tabbing away\n\n window.addEventListener(\"blur\", handleSubmit);\n }; // prevent blur when changing properties from the menu\n\n\n const onPointerDown = event => {\n const target = event === null || event === void 0 ? void 0 : event.target;\n const isShapeActionsPanel = //zsviczian\n (event.target instanceof HTMLElement || event.target instanceof SVGElement) && (event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.SHAPE_ACTIONS_MENU}`) || event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.SHAPE_ACTIONS_MOBILE_MENU}`) || event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.MOBILE_TOOLBAR}`)); // panning canvas\n\n if (event.button === _constants__WEBPACK_IMPORTED_MODULE_4__.POINTER_BUTTON.WHEEL) {\n // trying to pan by clicking inside text area itself -> handle here\n if (target instanceof HTMLTextAreaElement) {\n event.preventDefault();\n app.handleCanvasPanUsingWheelOrSpaceDrag(event);\n }\n\n temporarilyDisableSubmit();\n return;\n }\n\n const isPropertiesTrigger = target instanceof HTMLElement && target.classList.contains(\"properties-trigger\");\n\n if ((event.target instanceof HTMLElement || event.target instanceof SVGElement) && (isShapeActionsPanel || //zsviczian\n event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.SHAPE_ACTIONS_MENU}, .${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.ZOOM_ACTIONS}`)) && !(0,_utils__WEBPACK_IMPORTED_MODULE_1__.isWritableElement)(event.target) || isPropertiesTrigger) {\n temporarilyDisableSubmit();\n } else if (event.target instanceof HTMLCanvasElement && // Vitest simply ignores stopPropagation, capture-mode, or rAF\n // so without introducing crazier hacks, nothing we can do\n !(0,_utils__WEBPACK_IMPORTED_MODULE_1__.isTestEnv)()) {\n // On mobile, blur event doesn't seem to always fire correctly,\n // so we want to also submit on pointerdown outside the wysiwyg.\n // Done in the next frame to prevent pointerdown from creating a new text\n // immediately (if tools locked) so that users on mobile have chance\n // to submit first (to hide virtual keyboard).\n // Note: revisit if we want to differ this behavior on Desktop\n requestAnimationFrame(() => {\n handleSubmit();\n });\n }\n }; // handle updates of textElement properties of editing element\n\n\n const unbindUpdate = app.scene.onUpdate(() => {\n var _a;\n\n updateWysiwygStyle();\n const isPopupOpened = !!((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(\".properties-content\"));\n\n if (!isPopupOpened) {\n editable.focus();\n }\n });\n const unbindOnScroll = app.onScrollChangeEmitter.on(() => {\n updateWysiwygStyle();\n }); // ---------------------------------------------------------------------------\n\n let isDestroyed = false;\n\n if (autoSelect) {\n // select on init (focusing is done separately inside the bindBlurEvent()\n // because we need it to happen *after* the blur event from `pointerdown`)\n editable.select();\n }\n\n bindBlurEvent(); // reposition wysiwyg in case of canvas is resized. Using ResizeObserver\n // is preferred so we catch changes from host, where window may not resize.\n\n let observer = null;\n\n if (canvas && \"ResizeObserver\" in window) {\n observer = new window.ResizeObserver(() => {\n updateWysiwygStyle();\n });\n observer.observe(canvas);\n } else {\n window.addEventListener(\"resize\", updateWysiwygStyle);\n }\n\n editable.onpointerdown = event => event.stopPropagation(); // rAF (+ capture to by doubly sure) so we don't catch te pointerdown that\n // triggered the wysiwyg\n\n\n requestAnimationFrame(() => {\n window.addEventListener(\"pointerdown\", onPointerDown, {\n capture: true\n });\n });\n window.addEventListener(\"beforeunload\", handleSubmit);\n excalidrawContainer === null || excalidrawContainer === void 0 ? void 0 : excalidrawContainer.querySelector(\".excalidraw-textEditorContainer\").appendChild(editable);\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/textWysiwyg.tsx?");
3050
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"textWysiwyg\": () => (/* binding */ textWysiwyg)\n/* harmony export */ });\n/* harmony import */ var _keys__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../keys */ \"./keys.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _scene_Scene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../scene/Scene */ \"./scene/Scene.ts\");\n/* harmony import */ var _typeChecks__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _mutateElement__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _textElement__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _textWrapping__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _actions_actionProperties__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../actions/actionProperties */ \"./actions/actionProperties.tsx\");\n/* harmony import */ var _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../actions/actionCanvas */ \"./actions/actionCanvas.tsx\");\n/* harmony import */ var _linearElementEditor__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./linearElementEditor */ \"./element/linearElementEditor.ts\");\n/* harmony import */ var _clipboard__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../clipboard */ \"./clipboard.ts\");\n/* harmony import */ var _containerCache__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./containerCache */ \"./element/containerCache.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst getTransform = (width, height, angle, appState, maxWidth, maxHeight) => {\n const {\n zoom\n } = appState;\n const degree = 180 * angle / Math.PI;\n let translateX = width * (zoom.value - 1) / 2;\n let translateY = height * (zoom.value - 1) / 2;\n\n if (width > maxWidth && zoom.value !== 1) {\n translateX = maxWidth * (zoom.value - 1) / 2;\n }\n\n if (height > maxHeight && zoom.value !== 1) {\n translateY = maxHeight * (zoom.value - 1) / 2;\n }\n\n return `translate(${translateX}px, ${translateY}px) scale(${zoom.value}) rotate(${degree}deg)`;\n};\n\nconst textWysiwyg = ({\n id,\n onChange,\n onSubmit,\n getViewportCoords,\n element,\n canvas,\n excalidrawContainer,\n app,\n autoSelect = true\n}) => {\n const textPropertiesUpdated = (updatedTextElement, editable) => {\n if (!editable.style.fontFamily || !editable.style.fontSize) {\n return false;\n }\n\n const currentFont = editable.style.fontFamily.replace(/\"/g, \"\");\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontFamilyString)({\n fontFamily: updatedTextElement.fontFamily\n }) !== currentFont) {\n return true;\n }\n\n if (`${updatedTextElement.fontSize}px` !== editable.style.fontSize) {\n return true;\n }\n\n return false;\n };\n\n const updateWysiwygStyle = () => {\n var _a;\n\n const appState = app.state;\n const updatedTextElement = (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getScene(element)) === null || _a === void 0 ? void 0 : _a.getElement(id);\n\n if (!updatedTextElement) {\n return;\n }\n\n const {\n textAlign,\n verticalAlign\n } = updatedTextElement;\n const elementsMap = app.scene.getNonDeletedElementsMap();\n\n if (updatedTextElement && (0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(updatedTextElement)) {\n let coordX = updatedTextElement.x;\n let coordY = updatedTextElement.y;\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getContainerElement)(updatedTextElement, app.scene.getNonDeletedElementsMap());\n let width = updatedTextElement.width; // set to element height by default since that's\n // what is going to be used for unbounded text\n\n let height = updatedTextElement.height;\n let maxWidth = updatedTextElement.width;\n let maxHeight = updatedTextElement.height;\n\n if (container && updatedTextElement.containerId) {\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container)) {\n const boundTextCoords = _linearElementEditor__WEBPACK_IMPORTED_MODULE_10__.LinearElementEditor.getBoundTextElementPosition(container, updatedTextElement, elementsMap);\n coordX = boundTextCoords.x;\n coordY = boundTextCoords.y;\n }\n\n const propertiesUpdated = textPropertiesUpdated(updatedTextElement, editable);\n let originalContainerData;\n\n if (propertiesUpdated) {\n originalContainerData = (0,_containerCache__WEBPACK_IMPORTED_MODULE_12__.updateOriginalContainerCache)(container.id, container.height);\n } else {\n originalContainerData = _containerCache__WEBPACK_IMPORTED_MODULE_12__.originalContainerCache[container.id];\n\n if (!originalContainerData) {\n originalContainerData = (0,_containerCache__WEBPACK_IMPORTED_MODULE_12__.updateOriginalContainerCache)(container.id, container.height);\n }\n }\n\n maxWidth = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxWidth)(container, updatedTextElement);\n maxHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxHeight)(container, updatedTextElement); // autogrow container height if text exceeds\n\n if (!(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container) && height > maxHeight) {\n const targetContainerHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.computeContainerDimensionForBoundText)(height, container.type);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n height: targetContainerHeight\n });\n return;\n } else if ( // autoshrink container height until original container height\n // is reached when text is removed\n !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container) && container.height > originalContainerData.height && height < maxHeight) {\n const targetContainerHeight = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.computeContainerDimensionForBoundText)(height, container.type);\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n height: targetContainerHeight\n });\n } else {\n const {\n y\n } = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.computeBoundTextPosition)(container, updatedTextElement, elementsMap);\n coordY = y;\n }\n }\n\n const [viewportX, viewportY] = getViewportCoords(coordX, coordY);\n const initialSelectionStart = editable.selectionStart;\n const initialSelectionEnd = editable.selectionEnd;\n const initialLength = editable.value.length; // restore cursor position after value updated so it doesn't\n // go to the end of text when container auto expanded\n\n if (initialSelectionStart === initialSelectionEnd && initialSelectionEnd !== initialLength) {\n // get diff between length and selection end and shift\n // the cursor by \"diff\" times to position correctly\n const diff = initialLength - initialSelectionEnd;\n editable.selectionStart = editable.value.length - diff;\n editable.selectionEnd = editable.value.length - diff;\n }\n\n if (!container) {\n maxWidth = (appState.width - 8 - viewportX) / appState.zoom.value;\n width = Math.min(width, maxWidth);\n } else {\n width += 0.5;\n } // add 5% buffer otherwise it causes wysiwyg to jump\n\n\n height *= 1.05;\n const font = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontString)(updatedTextElement); // adding left and right padding buffer, so that browser does not cut the glyphs (does not work in Safari)\n\n const padding = !_constants__WEBPACK_IMPORTED_MODULE_4__.isSafari ? Math.ceil(updatedTextElement.fontSize / appState.zoom.value / 2) : 0; // Make sure text editor height doesn't go beyond viewport\n\n const editorMaxHeight = (appState.height - viewportY) / appState.zoom.value;\n Object.assign(editable.style, {\n font,\n // must be defined *after* font ¯\\_(ツ)_/¯\n lineHeight: updatedTextElement.lineHeight,\n width: `${Math.ceil(width)}px`,\n height: `${height}px`,\n left: `${viewportX - padding}px`,\n top: `${viewportY}px`,\n transform: getTransform(width, height, (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getTextElementAngle)(updatedTextElement, container), appState, maxWidth, editorMaxHeight),\n padding: `0 ${padding}px`,\n textAlign,\n verticalAlign,\n color: updatedTextElement.strokeColor,\n opacity: updatedTextElement.opacity / 100,\n filter: \"var(--theme-filter)\",\n maxHeight: `${editorMaxHeight}px`\n });\n editable.scrollTop = 0; // For some reason updating font attribute doesn't set font family\n // hence updating font family explicitly for test environment\n\n if ((0,_utils__WEBPACK_IMPORTED_MODULE_1__.isTestEnv)()) {\n editable.style.fontFamily = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontFamilyString)(updatedTextElement);\n }\n\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(updatedTextElement, {\n x: coordX,\n y: coordY\n });\n }\n };\n\n const editable = document.createElement(\"textarea\");\n editable.dir = \"auto\";\n editable.tabIndex = 0;\n editable.dataset.type = \"wysiwyg\"; // prevent line wrapping on Safari\n\n editable.wrap = \"off\";\n editable.classList.add(\"excalidraw-wysiwyg\");\n let whiteSpace = \"pre\";\n let wordBreak = \"normal\";\n\n if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isBoundToContainer)(element) || !element.autoResize) {\n whiteSpace = \"pre-wrap\";\n wordBreak = \"break-word\";\n }\n\n Object.assign(editable.style, {\n position: \"absolute\",\n display: \"inline-block\",\n minHeight: \"1em\",\n backfaceVisibility: \"hidden\",\n margin: 0,\n border: 0,\n outline: 0,\n resize: \"none\",\n background: \"transparent\",\n overflow: \"hidden\",\n // must be specified because in dark mode canvas creates a stacking context\n zIndex: \"var(--zIndex-wysiwyg)\",\n wordBreak,\n // prevent line wrapping (`whitespace: nowrap` doesn't work on FF)\n whiteSpace,\n overflowWrap: \"break-word\",\n boxSizing: \"content-box\"\n });\n editable.value = element.originalText;\n updateWysiwygStyle();\n\n if (onChange) {\n editable.onpaste = async event => {\n const clipboardData = await (0,_clipboard__WEBPACK_IMPORTED_MODULE_11__.parseClipboard)(event, true);\n\n if (!clipboardData.text) {\n return;\n }\n\n const data = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(clipboardData.text);\n\n if (!data) {\n return;\n }\n\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getContainerElement)(element, app.scene.getNonDeletedElementsMap());\n const font = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.getFontString)({\n fontSize: app.state.currentItemFontSize,\n fontFamily: app.state.currentItemFontFamily\n });\n\n if (container) {\n const boundTextElement = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextElement)(container, app.scene.getNonDeletedElementsMap());\n const wrappedText = (0,_textWrapping__WEBPACK_IMPORTED_MODULE_7__.wrapText)(`${editable.value}${data}`, font, (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextMaxWidth)(container, boundTextElement));\n const width = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getTextWidth)(wrappedText, font, true);\n editable.style.width = `${Math.ceil(width)}px`; //zsviczian Obsidian app zoom !== 100% issue\n }\n };\n\n editable.oninput = () => {\n const normalized = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.normalizeText)(editable.value);\n\n if (editable.value !== normalized) {\n const selectionStart = editable.selectionStart;\n editable.value = normalized; // put the cursor at some position close to where it was before\n // normalization (otherwise it'll end up at the end of the text)\n\n editable.selectionStart = selectionStart;\n editable.selectionEnd = selectionStart;\n }\n\n onChange(editable.value);\n };\n }\n\n editable.onkeydown = event => {\n if (!event.shiftKey && _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__.actionZoomIn.keyTest(event)) {\n event.preventDefault();\n app.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__.actionZoomIn);\n updateWysiwygStyle();\n } else if (!event.shiftKey && _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__.actionZoomOut.keyTest(event)) {\n event.preventDefault();\n app.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__.actionZoomOut);\n updateWysiwygStyle();\n } else if (!event.shiftKey && _actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__.actionResetZoom.keyTest(event)) {\n event.preventDefault();\n app.actionManager.executeAction(_actions_actionCanvas__WEBPACK_IMPORTED_MODULE_9__.actionResetZoom);\n updateWysiwygStyle();\n } else if (_actions_actionProperties__WEBPACK_IMPORTED_MODULE_8__.actionDecreaseFontSize.keyTest(event)) {\n app.actionManager.executeAction(_actions_actionProperties__WEBPACK_IMPORTED_MODULE_8__.actionDecreaseFontSize);\n } else if (_actions_actionProperties__WEBPACK_IMPORTED_MODULE_8__.actionIncreaseFontSize.keyTest(event)) {\n app.actionManager.executeAction(_actions_actionProperties__WEBPACK_IMPORTED_MODULE_8__.actionIncreaseFontSize);\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.ESCAPE) {\n event.preventDefault();\n submittedViaKeyboard = true;\n handleSubmit();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.ENTER && event[_keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.CTRL_OR_CMD]) {\n event.preventDefault();\n\n if (event.isComposing || event.keyCode === 229) {\n return;\n }\n\n submittedViaKeyboard = true;\n handleSubmit();\n } else if (event.key === _keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.TAB || event[_keys__WEBPACK_IMPORTED_MODULE_0__.KEYS.CTRL_OR_CMD] && (event.code === _keys__WEBPACK_IMPORTED_MODULE_0__.CODES.BRACKET_LEFT || event.code === _keys__WEBPACK_IMPORTED_MODULE_0__.CODES.BRACKET_RIGHT)) {\n event.preventDefault();\n\n if (event.isComposing) {\n return;\n } else if (event.shiftKey || event.code === _keys__WEBPACK_IMPORTED_MODULE_0__.CODES.BRACKET_LEFT) {\n outdent();\n } else {\n indent();\n } // We must send an input event to resize the element\n\n\n editable.dispatchEvent(new Event(\"input\"));\n }\n };\n\n const TAB_SIZE = 4;\n const TAB = \" \".repeat(TAB_SIZE);\n const RE_LEADING_TAB = new RegExp(`^ {1,${TAB_SIZE}}`);\n\n const indent = () => {\n const {\n selectionStart,\n selectionEnd\n } = editable;\n const linesStartIndices = getSelectedLinesStartIndices();\n let value = editable.value;\n linesStartIndices.forEach(startIndex => {\n const startValue = value.slice(0, startIndex);\n const endValue = value.slice(startIndex);\n value = `${startValue}${TAB}${endValue}`;\n });\n editable.value = value;\n editable.selectionStart = selectionStart + TAB_SIZE;\n editable.selectionEnd = selectionEnd + TAB_SIZE * linesStartIndices.length;\n };\n\n const outdent = () => {\n const {\n selectionStart,\n selectionEnd\n } = editable;\n const linesStartIndices = getSelectedLinesStartIndices();\n const removedTabs = [];\n let value = editable.value;\n linesStartIndices.forEach(startIndex => {\n const tabMatch = value.slice(startIndex, startIndex + TAB_SIZE).match(RE_LEADING_TAB);\n\n if (tabMatch) {\n const startValue = value.slice(0, startIndex);\n const endValue = value.slice(startIndex + tabMatch[0].length); // Delete a tab from the line\n\n value = `${startValue}${endValue}`;\n removedTabs.push(startIndex);\n }\n });\n editable.value = value;\n\n if (removedTabs.length) {\n if (selectionStart > removedTabs[removedTabs.length - 1]) {\n editable.selectionStart = Math.max(selectionStart - TAB_SIZE, removedTabs[removedTabs.length - 1]);\n } else {\n // If the cursor is before the first tab removed, ex:\n // Line| #1\n // Line #2\n // Lin|e #3\n // we should reset the selectionStart to his initial value.\n editable.selectionStart = selectionStart;\n }\n\n editable.selectionEnd = Math.max(editable.selectionStart, selectionEnd - TAB_SIZE * removedTabs.length);\n }\n };\n /**\n * @returns indices of start positions of selected lines, in reverse order\n */\n\n\n const getSelectedLinesStartIndices = () => {\n let {\n selectionStart,\n selectionEnd,\n value\n } = editable; // chars before selectionStart on the same line\n\n const startOffset = value.slice(0, selectionStart).match(/[^\\n]*$/)[0].length; // put caret at the start of the line\n\n selectionStart = selectionStart - startOffset;\n const selected = value.slice(selectionStart, selectionEnd);\n return selected.split(\"\\n\").reduce((startIndices, line, idx, lines) => startIndices.concat(idx ? // curr line index is prev line's start + prev line's length + \\n\n startIndices[idx - 1] + lines[idx - 1].length + 1 : // first selected line\n selectionStart), []).reverse();\n };\n\n const stopEvent = event => {\n if (event.target instanceof HTMLCanvasElement) {\n event.preventDefault();\n event.stopPropagation();\n }\n }; // using a state variable instead of passing it to the handleSubmit callback\n // so that we don't need to create separate a callback for event handlers\n\n\n let submittedViaKeyboard = false;\n\n const handleSubmit = () => {\n var _a, _b; // prevent double submit\n\n\n if (isDestroyed) {\n return;\n }\n\n isDestroyed = true; // cleanup must be run before onSubmit otherwise when app blurs the wysiwyg\n // it'd get stuck in an infinite loop of blur→onSubmit after we re-focus the\n // wysiwyg on update\n\n cleanup();\n const updateElement = (_a = _scene_Scene__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getScene(element)) === null || _a === void 0 ? void 0 : _a.getElement(element.id);\n\n if (!updateElement) {\n return;\n }\n\n const container = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getContainerElement)(updateElement, app.scene.getNonDeletedElementsMap());\n\n if (container) {\n if (editable.value.trim()) {\n const boundTextElementId = (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.getBoundTextElementId)(container);\n\n if (!boundTextElementId || boundTextElementId !== element.id) {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: element.id\n })\n });\n } else if ((0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isArrowElement)(container)) {\n // updating an arrow label may change bounds, prevent stale cache:\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.bumpVersion)(container);\n }\n } else {\n (0,_mutateElement__WEBPACK_IMPORTED_MODULE_5__.mutateElement)(container, {\n boundElements: (_b = container.boundElements) === null || _b === void 0 ? void 0 : _b.filter(ele => !(0,_typeChecks__WEBPACK_IMPORTED_MODULE_3__.isTextElement)(ele))\n });\n }\n\n (0,_textElement__WEBPACK_IMPORTED_MODULE_6__.redrawTextBoundingBox)(updateElement, container, app.scene.getNonDeletedElementsMap());\n }\n\n app.setState({\n openPopup: null\n }); //zsviczian (container text color issue)\n\n onSubmit({\n viaKeyboard: submittedViaKeyboard,\n nextOriginalText: editable.value\n });\n };\n\n const cleanup = () => {\n // remove events to ensure they don't late-fire\n editable.onblur = null;\n editable.oninput = null;\n editable.onkeydown = null;\n\n if (observer) {\n observer.disconnect();\n }\n\n window.removeEventListener(\"resize\", updateWysiwygStyle);\n window.removeEventListener(\"wheel\", stopEvent, true);\n window.removeEventListener(\"pointerdown\", onPointerDown);\n window.removeEventListener(\"pointerup\", bindBlurEvent);\n window.removeEventListener(\"blur\", handleSubmit);\n window.removeEventListener(\"beforeunload\", handleSubmit);\n unbindUpdate();\n unbindOnScroll();\n editable.remove();\n };\n\n const bindBlurEvent = event => {\n window.removeEventListener(\"pointerup\", bindBlurEvent); // Deferred so that the pointerdown that initiates the wysiwyg doesn't\n // trigger the blur on ensuing pointerup.\n // Also to handle cases such as picking a color which would trigger a blur\n // in that same tick.\n\n const target = event === null || event === void 0 ? void 0 : event.target;\n const isPropertiesTrigger = target instanceof HTMLElement && target.classList.contains(\"properties-trigger\");\n setTimeout(() => {\n editable.onblur = handleSubmit; // case: clicking on the same property → no change → no update → no focus\n\n if (!isPropertiesTrigger) {\n editable.focus();\n }\n });\n };\n\n const temporarilyDisableSubmit = () => {\n editable.onblur = null;\n window.addEventListener(\"pointerup\", bindBlurEvent); // handle edge-case where pointerup doesn't fire e.g. due to user\n // alt-tabbing away\n\n window.addEventListener(\"blur\", handleSubmit);\n }; // prevent blur when changing properties from the menu\n\n\n const onPointerDown = event => {\n const target = event === null || event === void 0 ? void 0 : event.target;\n const isShapeActionsPanel = //zsviczian\n (event.target instanceof HTMLElement || event.target instanceof SVGElement) && (event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.SHAPE_ACTIONS_MENU}`) || event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.SHAPE_ACTIONS_MOBILE_MENU}`) || event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.MOBILE_TOOLBAR}`)); // panning canvas\n\n if (event.button === _constants__WEBPACK_IMPORTED_MODULE_4__.POINTER_BUTTON.WHEEL) {\n // trying to pan by clicking inside text area itself -> handle here\n if (target instanceof HTMLTextAreaElement) {\n event.preventDefault();\n app.handleCanvasPanUsingWheelOrSpaceDrag(event);\n }\n\n temporarilyDisableSubmit();\n return;\n }\n\n const isPropertiesTrigger = target instanceof HTMLElement && target.classList.contains(\"properties-trigger\");\n\n if ((event.target instanceof HTMLElement || event.target instanceof SVGElement) && (isShapeActionsPanel || //zsviczian\n event.target.closest(`.${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.SHAPE_ACTIONS_MENU}, .${_constants__WEBPACK_IMPORTED_MODULE_4__.CLASSES.ZOOM_ACTIONS}`)) && !(0,_utils__WEBPACK_IMPORTED_MODULE_1__.isWritableElement)(event.target) || isPropertiesTrigger) {\n temporarilyDisableSubmit();\n } else if (event.target instanceof HTMLCanvasElement && // Vitest simply ignores stopPropagation, capture-mode, or rAF\n // so without introducing crazier hacks, nothing we can do\n !(0,_utils__WEBPACK_IMPORTED_MODULE_1__.isTestEnv)()) {\n // On mobile, blur event doesn't seem to always fire correctly,\n // so we want to also submit on pointerdown outside the wysiwyg.\n // Done in the next frame to prevent pointerdown from creating a new text\n // immediately (if tools locked) so that users on mobile have chance\n // to submit first (to hide virtual keyboard).\n // Note: revisit if we want to differ this behavior on Desktop\n requestAnimationFrame(() => {\n handleSubmit();\n });\n }\n }; // handle updates of textElement properties of editing element\n\n\n const unbindUpdate = app.scene.onUpdate(() => {\n var _a;\n\n updateWysiwygStyle();\n const isPopupOpened = !!((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(\".properties-content\"));\n\n if (!isPopupOpened) {\n editable.focus();\n }\n });\n const unbindOnScroll = app.onScrollChangeEmitter.on(() => {\n updateWysiwygStyle();\n }); // ---------------------------------------------------------------------------\n\n let isDestroyed = false;\n\n if (autoSelect) {\n // select on init (focusing is done separately inside the bindBlurEvent()\n // because we need it to happen *after* the blur event from `pointerdown`)\n editable.select();\n }\n\n bindBlurEvent(); // reposition wysiwyg in case of canvas is resized. Using ResizeObserver\n // is preferred so we catch changes from host, where window may not resize.\n\n let observer = null;\n\n if (canvas && \"ResizeObserver\" in window) {\n observer = new window.ResizeObserver(() => {\n updateWysiwygStyle();\n });\n observer.observe(canvas);\n } else {\n window.addEventListener(\"resize\", updateWysiwygStyle);\n }\n\n editable.onpointerdown = event => event.stopPropagation(); // rAF (+ capture to by doubly sure) so we don't catch te pointerdown that\n // triggered the wysiwyg\n\n\n requestAnimationFrame(() => {\n window.addEventListener(\"pointerdown\", onPointerDown, {\n capture: true\n });\n });\n window.addEventListener(\"beforeunload\", handleSubmit);\n excalidrawContainer === null || excalidrawContainer === void 0 ? void 0 : excalidrawContainer.querySelector(\".excalidraw-textEditorContainer\").appendChild(editable);\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./element/textWysiwyg.tsx?");
3040
3051
 
3041
3052
  /***/ }),
3042
3053
 
@@ -3135,7 +3146,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3135
3146
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3136
3147
 
3137
3148
  "use strict";
3138
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ExcalidrawFontFace\": () => (/* binding */ ExcalidrawFontFace)\n/* harmony export */ });\n/* harmony import */ var _data_encode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../data/encode */ \"./data/encode.ts\");\n/* harmony import */ var _obsidianUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../obsidianUtils */ \"./obsidianUtils.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _FontMetadata__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./FontMetadata */ \"./fonts/FontMetadata.ts\");\n/* harmony import */ var _subset_subset_main__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../subset/subset-main */ \"./subset/subset-main.ts\");\n\n\n\n\n\nclass ExcalidrawFontFace {\n constructor(family, uri, descriptors) {\n this.urls = ExcalidrawFontFace.createUrls(uri);\n const sources = this.urls.map(url => `url(${url}) ${ExcalidrawFontFace.getFormat(url)}`).join(\", \");\n this.fontFace = new FontFace(family, sources, Object.assign({\n display: \"swap\",\n style: \"normal\",\n weight: \"400\"\n }, descriptors));\n }\n /**\n * Generates CSS `@font-face` definition with the (subsetted) font source as a data url for the characters within the unicode range.\n *\n * Retrieves `undefined` otherwise.\n */\n\n\n toCSS(characters) {\n // quick exit in case the characters are not within this font face's unicode range\n if (!this.getUnicodeRangeRegex().test(characters)) {\n return;\n } //zsviczian - only woffs are chopped into glyphs other fonts are returned as is\n\n\n if (typeof this.urls[0] === \"string\" && !this.urls[0].startsWith(\"data:font/woff2\")) {\n return Promise.resolve(`@font-face { font-family: ${this.fontFace.family}; src: url(${this.urls[0]}); }`);\n }\n\n const codepoints = Array.from(characters).map(char => char.codePointAt(0));\n return this.getContent(codepoints).then(content => `@font-face { font-family: ${this.fontFace.family}; src: url(${content}); }`);\n }\n /**\n * Tries to fetch woff2 content, based on the registered urls (from first to last, treated as fallbacks).\n *\n * @returns base64 with subsetted glyphs based on the passed codepoint, last defined url otherwise\n */\n\n\n async getContent(codePoints) {\n let i = 0;\n const errorMessages = [];\n\n while (i < this.urls.length) {\n const url = this.urls[i];\n\n try {\n const arrayBuffer = await this.fetchFont(url);\n const base64 = await (0,_subset_subset_main__WEBPACK_IMPORTED_MODULE_4__.subsetWoff2GlyphsByCodepoints)(arrayBuffer, codePoints);\n return base64;\n } catch (e) {\n errorMessages.push(`\"${url.toString()}\" returned error \"${e}\"`);\n }\n\n i++;\n }\n\n console.error(`Failed to fetch font family \"${this.fontFace.family}\"`, JSON.stringify(errorMessages, undefined, 2)); // in case of issues, at least return the last url as a content\n // defaults to unpkg for bundled fonts (so that we don't have to host them forever) and http url for others\n\n return this.urls.length ? this.urls[this.urls.length - 1].toString() : \"\";\n }\n\n fetchFont(url) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_2__.promiseTry)(async () => {\n const result = await (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_1__.fetchFontFromVault)(url); //zsviczian\n\n if (result) {\n return result;\n }\n\n const response = await fetch(url, {\n // always prefer cache (even stale), otherwise it always triggers an unnecessary validation request\n // which we don't need as we are controlling freshness of the fonts with the stable hash suffix in the url\n // https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n cache: \"force-cache\",\n headers: {\n Accept: \"font/woff2\"\n }\n });\n\n if (!response.ok) {\n const urlString = url instanceof URL ? url.toString() : \"dataurl\";\n throw new Error(`Failed to fetch \"${urlString}\": ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return arrayBuffer;\n });\n }\n\n getUnicodeRangeRegex() {\n // using \\u{h} or \\u{hhhhh} to match any number of hex digits,\n // otherwise we would get an \"Invalid Unicode escape\" error\n // e.g. U+0-1007F -> \\u{0}-\\u{1007F}\n const unicodeRangeRegex = this.fontFace.unicodeRange.split(/,\\s*/).map(range => {\n const [start, end] = range.replace(\"U+\", \"\").split(\"-\");\n\n if (end) {\n return `\\\\u{${start}}-\\\\u{${end}}`;\n }\n\n return `\\\\u{${start}}`;\n }).join(\"\");\n return new RegExp(`[${unicodeRangeRegex}]`, \"u\");\n }\n\n static createUrls(uri) {\n if (uri.startsWith(\"data\")) {\n // don't create the URL instance, as parsing the huge dataurl string is expensive\n return [uri];\n }\n\n if (uri.startsWith(_FontMetadata__WEBPACK_IMPORTED_MODULE_3__.LOCAL_FONT_PROTOCOL)) {\n // no url for local fonts\n return [];\n }\n\n if (uri.startsWith(\"http\")) {\n // one url for http imports or data url\n return [new URL(uri)];\n } // absolute assets paths, which are found in tests and excalidraw-app build, won't work with base url, so we are stripping initial slash away\n\n\n const assetUrl = uri.replace(/^\\/+/, \"\");\n const urls = [];\n\n if (typeof window.EXCALIDRAW_ASSET_PATH === \"string\") {\n const normalizedBaseUrl = this.normalizeBaseUrl(window.EXCALIDRAW_ASSET_PATH);\n urls.push(new URL(assetUrl, normalizedBaseUrl));\n } else if (Array.isArray(window.EXCALIDRAW_ASSET_PATH)) {\n window.EXCALIDRAW_ASSET_PATH.forEach(path => {\n const normalizedBaseUrl = this.normalizeBaseUrl(path);\n urls.push(new URL(assetUrl, normalizedBaseUrl));\n });\n } // fallback url for bundled fonts\n\n\n urls.push(new URL(assetUrl, ExcalidrawFontFace.UNPKG_FALLBACK_URL));\n return urls;\n }\n\n static getFormat(url) {\n if (!(url instanceof URL)) {\n // format is irrelevant for data url\n return \"\";\n }\n\n try {\n const parts = new URL(url).pathname.split(\".\");\n\n if (parts.length === 1) {\n return \"\";\n }\n\n return `format('${parts.pop()}')`;\n } catch (error) {\n return \"\";\n }\n }\n\n static normalizeBaseUrl(baseUrl) {\n var _a;\n\n let result = baseUrl; // in case user passed a root-relative url (~absolute path),\n // like \"/\" or \"/some/path\", or relative (starts with \"./\"),\n // prepend it with `location.origin`\n\n if (/^\\.?\\//.test(result)) {\n result = new URL(result.replace(/^\\.?\\/+/, \"\"), (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.origin).toString();\n } // ensure there is a trailing slash, otherwise url won't be correctly concatenated\n\n\n result = `${result.replace(/\\/+$/, \"\")}/`;\n return result;\n }\n /**\n * zsviczian https://github.com/zsviczian/excalidraw/commit/b4cfaaa4b4f46ca01f94e27fb7bf651a9da99daa\n */\n\n\n async getContentLegacy() {\n let i = 0;\n const errorMessages = [];\n\n while (i < this.urls.length) {\n const url = this.urls[i];\n\n if (typeof url === \"string\" && url.startsWith(\"data:\")) {\n // it's dataurl, the font is inlined as base64, no need to fetch\n return url;\n }\n\n try {\n const result = await (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_1__.fetchFontFromVault)(url); //zsviczian\n\n if (result) {\n return `data:font/woff2;base64,${await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.stringToBase64)(await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.toByteString)(result), true)}`;\n }\n\n const response = await fetch(url, {\n headers: {\n Accept: \"font/woff2\"\n }\n });\n\n if (response.ok) {\n const mimeType = response.headers.get(\"Content-Type\");\n const buffer = await response.arrayBuffer();\n return `data:${mimeType};base64,${await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.stringToBase64)(await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.toByteString)(buffer), true)}`;\n } // response not ok, try to continue\n\n\n errorMessages.push(`\"${url.toString()}\" returned status \"${response.status}\"`);\n } catch (e) {\n errorMessages.push(`\"${url.toString()}\" returned error \"${e}\"`);\n }\n\n i++;\n }\n\n console.error(`Failed to fetch font \"${this.fontFace.family}\" from urls \"${this.urls.toString()}`, JSON.stringify(errorMessages, undefined, 2)); // in case of issues, at least return the last url as a content\n // defaults to unpkg for bundled fonts (so that we don't have to host them forever) and http url for others\n\n return this.urls.length ? this.urls[this.urls.length - 1].toString() : \"\";\n }\n\n}\nExcalidrawFontFace.UNPKG_FALLBACK_URL = `https://unpkg.com/${ true ? `${\"@zsviczian/excalidraw\"}@${({\"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_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_ENABLE_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.6-8\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).PKG_VERSION}` // should be provided by vite during package build\n: 0 // fallback to latest package version (i.e. for app)\n}/dist/prod/`;\n\n//# sourceURL=webpack://ExcalidrawLib/./fonts/ExcalidrawFontFace.ts?");
3149
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"ExcalidrawFontFace\": () => (/* binding */ ExcalidrawFontFace)\n/* harmony export */ });\n/* harmony import */ var _data_encode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../data/encode */ \"./data/encode.ts\");\n/* harmony import */ var _obsidianUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../obsidianUtils */ \"./obsidianUtils.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _FontMetadata__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./FontMetadata */ \"./fonts/FontMetadata.ts\");\n/* harmony import */ var _subset_subset_main__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../subset/subset-main */ \"./subset/subset-main.ts\");\n\n\n\n\n\nclass ExcalidrawFontFace {\n constructor(family, uri, descriptors) {\n this.urls = ExcalidrawFontFace.createUrls(uri);\n const sources = this.urls.map(url => `url(${url}) ${ExcalidrawFontFace.getFormat(url)}`).join(\", \");\n this.fontFace = new FontFace(family, sources, Object.assign({\n display: \"swap\",\n style: \"normal\",\n weight: \"400\"\n }, descriptors));\n }\n /**\n * Generates CSS `@font-face` definition with the (subsetted) font source as a data url for the characters within the unicode range.\n *\n * Retrieves `undefined` otherwise.\n */\n\n\n toCSS(characters) {\n // quick exit in case the characters are not within this font face's unicode range\n if (!this.getUnicodeRangeRegex().test(characters)) {\n return;\n } //zsviczian - only woffs are chopped into glyphs other fonts are returned as is\n\n\n if (typeof this.urls[0] === \"string\" && !this.urls[0].startsWith(\"data:font/woff2\")) {\n return Promise.resolve(`@font-face { font-family: ${this.fontFace.family}; src: url(${this.urls[0]}); }`);\n }\n\n const codepoints = Array.from(characters).map(char => char.codePointAt(0));\n return this.getContent(codepoints).then(content => `@font-face { font-family: ${this.fontFace.family}; src: url(${content}); }`);\n }\n /**\n * Tries to fetch woff2 content, based on the registered urls (from first to last, treated as fallbacks).\n *\n * @returns base64 with subsetted glyphs based on the passed codepoint, last defined url otherwise\n */\n\n\n async getContent(codePoints) {\n let i = 0;\n const errorMessages = [];\n\n while (i < this.urls.length) {\n const url = this.urls[i];\n\n try {\n const arrayBuffer = await this.fetchFont(url);\n const base64 = await (0,_subset_subset_main__WEBPACK_IMPORTED_MODULE_4__.subsetWoff2GlyphsByCodepoints)(arrayBuffer, codePoints);\n return base64;\n } catch (e) {\n errorMessages.push(`\"${url.toString()}\" returned error \"${e}\"`);\n }\n\n i++;\n }\n\n console.error(`Failed to fetch font family \"${this.fontFace.family}\"`, JSON.stringify(errorMessages, undefined, 2)); // in case of issues, at least return the last url as a content\n // defaults to unpkg for bundled fonts (so that we don't have to host them forever) and http url for others\n\n return this.urls.length ? this.urls[this.urls.length - 1].toString() : \"\";\n }\n\n fetchFont(url) {\n return (0,_utils__WEBPACK_IMPORTED_MODULE_2__.promiseTry)(async () => {\n const result = await (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_1__.fetchFontFromVault)(url); //zsviczian\n\n if (result) {\n return result;\n }\n\n const response = await fetch(url, {\n // always prefer cache (even stale), otherwise it always triggers an unnecessary validation request\n // which we don't need as we are controlling freshness of the fonts with the stable hash suffix in the url\n // https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n cache: \"force-cache\",\n headers: {\n Accept: \"font/woff2\"\n }\n });\n\n if (!response.ok) {\n const urlString = url instanceof URL ? url.toString() : \"dataurl\";\n throw new Error(`Failed to fetch \"${urlString}\": ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return arrayBuffer;\n });\n }\n\n getUnicodeRangeRegex() {\n // using \\u{h} or \\u{hhhhh} to match any number of hex digits,\n // otherwise we would get an \"Invalid Unicode escape\" error\n // e.g. U+0-1007F -> \\u{0}-\\u{1007F}\n const unicodeRangeRegex = this.fontFace.unicodeRange.split(/,\\s*/).map(range => {\n const [start, end] = range.replace(\"U+\", \"\").split(\"-\");\n\n if (end) {\n return `\\\\u{${start}}-\\\\u{${end}}`;\n }\n\n return `\\\\u{${start}}`;\n }).join(\"\");\n return new RegExp(`[${unicodeRangeRegex}]`, \"u\");\n }\n\n static createUrls(uri) {\n if (uri.startsWith(\"data\")) {\n // don't create the URL instance, as parsing the huge dataurl string is expensive\n return [uri];\n }\n\n if (uri.startsWith(_FontMetadata__WEBPACK_IMPORTED_MODULE_3__.LOCAL_FONT_PROTOCOL)) {\n // no url for local fonts\n return [];\n }\n\n if (uri.startsWith(\"http\")) {\n // one url for http imports or data url\n return [new URL(uri)];\n } // absolute assets paths, which are found in tests and excalidraw-app build, won't work with base url, so we are stripping initial slash away\n\n\n const assetUrl = uri.replace(/^\\/+/, \"\");\n const urls = [];\n\n if (typeof window.EXCALIDRAW_ASSET_PATH === \"string\") {\n const normalizedBaseUrl = this.normalizeBaseUrl(window.EXCALIDRAW_ASSET_PATH);\n urls.push(new URL(assetUrl, normalizedBaseUrl));\n } else if (Array.isArray(window.EXCALIDRAW_ASSET_PATH)) {\n window.EXCALIDRAW_ASSET_PATH.forEach(path => {\n const normalizedBaseUrl = this.normalizeBaseUrl(path);\n urls.push(new URL(assetUrl, normalizedBaseUrl));\n });\n } // fallback url for bundled fonts\n\n\n urls.push(new URL(assetUrl, ExcalidrawFontFace.UNPKG_FALLBACK_URL));\n return urls;\n }\n\n static getFormat(url) {\n if (!(url instanceof URL)) {\n // format is irrelevant for data url\n return \"\";\n }\n\n try {\n const parts = new URL(url).pathname.split(\".\");\n\n if (parts.length === 1) {\n return \"\";\n }\n\n return `format('${parts.pop()}')`;\n } catch (error) {\n return \"\";\n }\n }\n\n static normalizeBaseUrl(baseUrl) {\n var _a;\n\n let result = baseUrl; // in case user passed a root-relative url (~absolute path),\n // like \"/\" or \"/some/path\", or relative (starts with \"./\"),\n // prepend it with `location.origin`\n\n if (/^\\.?\\//.test(result)) {\n result = new URL(result.replace(/^\\.?\\/+/, \"\"), (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.origin).toString();\n } // ensure there is a trailing slash, otherwise url won't be correctly concatenated\n\n\n result = `${result.replace(/\\/+$/, \"\")}/`;\n return result;\n }\n /**\n * zsviczian https://github.com/zsviczian/excalidraw/commit/b4cfaaa4b4f46ca01f94e27fb7bf651a9da99daa\n */\n\n\n async getContentLegacy() {\n let i = 0;\n const errorMessages = [];\n\n while (i < this.urls.length) {\n const url = this.urls[i];\n\n if (typeof url === \"string\" && url.startsWith(\"data:\")) {\n // it's dataurl, the font is inlined as base64, no need to fetch\n return url;\n }\n\n try {\n const result = await (0,_obsidianUtils__WEBPACK_IMPORTED_MODULE_1__.fetchFontFromVault)(url); //zsviczian\n\n if (result) {\n return `data:font/woff2;base64,${await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.stringToBase64)(await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.toByteString)(result), true)}`;\n }\n\n const response = await fetch(url, {\n headers: {\n Accept: \"font/woff2\"\n }\n });\n\n if (response.ok) {\n const mimeType = response.headers.get(\"Content-Type\");\n const buffer = await response.arrayBuffer();\n return `data:${mimeType};base64,${await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.stringToBase64)(await (0,_data_encode__WEBPACK_IMPORTED_MODULE_0__.toByteString)(buffer), true)}`;\n } // response not ok, try to continue\n\n\n errorMessages.push(`\"${url.toString()}\" returned status \"${response.status}\"`);\n } catch (e) {\n errorMessages.push(`\"${url.toString()}\" returned error \"${e}\"`);\n }\n\n i++;\n }\n\n console.error(`Failed to fetch font \"${this.fontFace.family}\" from urls \"${this.urls.toString()}`, JSON.stringify(errorMessages, undefined, 2)); // in case of issues, at least return the last url as a content\n // defaults to unpkg for bundled fonts (so that we don't have to host them forever) and http url for others\n\n return this.urls.length ? this.urls[this.urls.length - 1].toString() : \"\";\n }\n\n}\nExcalidrawFontFace.UNPKG_FALLBACK_URL = `https://unpkg.com/${ true ? `${\"@zsviczian/excalidraw\"}@${({\"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_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_ENABLE_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.6-9\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true}).PKG_VERSION}` // should be provided by vite during package build\n: 0 // fallback to latest package version (i.e. for app)\n}/dist/prod/`;\n\n//# sourceURL=webpack://ExcalidrawLib/./fonts/ExcalidrawFontFace.ts?");
3139
3150
 
3140
3151
  /***/ }),
3141
3152
 
@@ -3168,7 +3179,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3168
3179
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3169
3180
 
3170
3181
  "use strict";
3171
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Fonts\": () => (/* binding */ Fonts),\n/* harmony export */ \"getLineHeight\": () => (/* binding */ getLineHeight),\n/* harmony export */ \"getVerticalOffset\": () => (/* binding */ getVerticalOffset)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../scene/ShapeCache */ \"./scene/ShapeCache.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _ExcalidrawFontFace__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ExcalidrawFontFace */ \"./fonts/ExcalidrawFontFace.ts\");\n/* harmony import */ var _Cascadia__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Cascadia */ \"./fonts/Cascadia/index.ts\");\n/* harmony import */ var _ComicShanns__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./ComicShanns */ \"./fonts/ComicShanns/index.ts\");\n/* harmony import */ var _Emoji__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Emoji */ \"./fonts/Emoji/index.ts\");\n/* harmony import */ var _Excalifont__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./Excalifont */ \"./fonts/Excalifont/index.ts\");\n/* harmony import */ var _Helvetica__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./Helvetica */ \"./fonts/Helvetica/index.ts\");\n/* harmony import */ var _Liberation__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./Liberation */ \"./fonts/Liberation/index.ts\");\n/* harmony import */ var _Lilita__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./Lilita */ \"./fonts/Lilita/index.ts\");\n/* harmony import */ var _Nunito__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Nunito */ \"./fonts/Nunito/index.ts\");\n/* harmony import */ var _Virgil__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./Virgil */ \"./fonts/Virgil/index.ts\");\n/* harmony import */ var _Xiaolai__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./Xiaolai */ \"./fonts/Xiaolai/index.ts\");\n/* harmony import */ var _FontMetadata__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./FontMetadata */ \"./fonts/FontMetadata.ts\");\nvar _a;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nclass Fonts {\n static get registered() {\n // lazy load the font registration\n if (!Fonts._registered) {\n Fonts._registered = Fonts.init();\n } else if (!Fonts._initialized) {\n // case when host app register fonts before they are lazy loaded\n // don't override whatever has been previously registered\n Fonts._registered = new Map([...Fonts.init().entries(), ...Fonts._registered.entries()]);\n }\n\n return Fonts._registered;\n }\n\n get registered() {\n return Fonts.registered;\n }\n\n constructor(scene) {\n /**\n * if we load a (new) font, it's likely that text elements using it have\n * already been rendered using a fallback font. Thus, we want invalidate\n * their shapes and rerender. See #637.\n *\n * Invalidates text elements and rerenders scene, provided that at least one\n * of the supplied fontFaces has not already been processed.\n */\n this.onLoaded = fontFaces => {\n // bail if all fonts with have been processed. We're checking just a\n // subset of the font properties (though it should be enough), so it\n // can technically bail on a false positive.\n let shouldBail = true;\n\n for (const fontFace of fontFaces) {\n const sig = `${fontFace.family}-${fontFace.style}-${fontFace.weight}-${fontFace.unicodeRange}`; // make sure to update our cache with all the loaded font faces\n\n if (!Fonts.loadedFontsCache.has(sig)) {\n Fonts.loadedFontsCache.add(sig);\n shouldBail = false;\n }\n }\n\n if (shouldBail) {\n return;\n }\n\n let didUpdate = false;\n const elementsMap = this.scene.getNonDeletedElementsMap();\n\n for (const element of this.scene.getNonDeletedElements()) {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n didUpdate = true;\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_3__.ShapeCache[\"delete\"](element); // clear the width cache, so that we don't perform subsequent wrapping based on the stale fallback font metrics\n\n _element_textElement__WEBPACK_IMPORTED_MODULE_2__.charWidth.clearCache((0,_utils__WEBPACK_IMPORTED_MODULE_4__.getFontString)(element));\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_2__.getContainerElement)(element, elementsMap);\n\n if (container) {\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_3__.ShapeCache[\"delete\"](container);\n }\n }\n }\n\n if (didUpdate) {\n this.scene.triggerUpdate();\n }\n };\n /**\n * Load font faces for a given scene and trigger scene update.\n */\n\n\n this.loadSceneFonts = async () => {\n const sceneFamilies = this.getSceneFamilies();\n const loaded = await Fonts.loadFontFaces(sceneFamilies);\n this.onLoaded(loaded);\n return loaded;\n };\n /**\n * Gets all the font families for the given scene.\n */\n\n\n this.getSceneFamilies = () => {\n return Fonts.getElementsFamilies(this.scene.getNonDeletedElements());\n };\n\n this.scene = scene;\n } //zsviczian made public\n\n\n static async loadFontFaces(fontFamilies) {\n // add all registered font faces into the `document.fonts` (if not added already)\n for (const {\n fontFaces,\n metadata\n } of Fonts.registered.values()) {\n // skip registering font faces for local fonts (i.e. Helvetica)\n if (metadata.local) {\n continue;\n }\n\n for (const {\n fontFace\n } of fontFaces) {\n if (!window.document.fonts.has(fontFace) && fontFace.family !== \"Local Font\" //zsviczian if Local Font is registered I can't change it dymamically\n ) {\n window.document.fonts.add(fontFace);\n }\n }\n }\n\n const loadedFontFaces = await Promise.all(fontFamilies.map(async fontFamily => {\n var _b;\n\n const fontString = (0,_utils__WEBPACK_IMPORTED_MODULE_4__.getFontString)({\n fontFamily,\n fontSize: 16\n }); // WARN: without \"text\" param it does not have to mean that all font faces are loaded, instead it could be just one!\n\n if (!window.document.fonts.check(fontString) && !fontString.startsWith(\"16px Local Font\") && //zsviczian if Local Font is registered I can't change it dymamically\n !fontString.startsWith(\"16px Helvetica\") //zsviczian there is an error loading Helvetica font (need to validate the error still exists)\n ) {\n try {\n // WARN: browser prioritizes loading only font faces with unicode ranges for characters which are present in the document (html & canvas), other font faces could stay unloaded\n // we might want to retry here, i.e. in case CDN is down, but so far I didn't experience any issues - maybe it handles retry-like logic under the hood\n return await window.document.fonts.load(fontString);\n } catch (e) {\n // don't let it all fail if just one font fails to load\n console.error(`Failed to load font \"${fontString}\" from urls \"${(_b = Fonts.registered.get(fontFamily)) === null || _b === void 0 ? void 0 : _b.fontFaces.map(x => x.urls)}\"`, e);\n }\n }\n\n return Promise.resolve();\n }));\n return loadedFontFaces.flat().filter(Boolean);\n }\n /**\n * WARN: should be called just once on init, even across multiple instances.\n */\n\n\n static init() {\n const fonts = {\n registered: new Map()\n };\n\n const init = (family, ...fontFacesDescriptors) => {\n var _b, _c;\n\n const fontFamily = (_b = _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY[family]) !== null && _b !== void 0 ? _b : _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY_FALLBACKS[family]; // default to Excalifont metrics\n\n const metadata = (_c = _FontMetadata__WEBPACK_IMPORTED_MODULE_16__.FONT_METADATA[fontFamily]) !== null && _c !== void 0 ? _c : _FontMetadata__WEBPACK_IMPORTED_MODULE_16__.FONT_METADATA[_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY.Excalifont];\n Fonts.register.call(fonts, family, metadata, ...fontFacesDescriptors);\n };\n\n init(\"Cascadia\", ..._Cascadia__WEBPACK_IMPORTED_MODULE_6__.CascadiaFontFaces);\n init(\"Comic Shanns\", ..._ComicShanns__WEBPACK_IMPORTED_MODULE_7__.ComicShannsFontFaces);\n init(\"Excalifont\", ..._Excalifont__WEBPACK_IMPORTED_MODULE_9__.ExcalifontFontFaces); // keeping for backwards compatibility reasons, uses system font (Helvetica on MacOS, Arial on Win)\n\n init(\"Helvetica\", ..._Helvetica__WEBPACK_IMPORTED_MODULE_10__.HelveticaFontFaces); // used for server-side pdf & png export instead of helvetica (technically does not need metrics, but kept in for consistency)\n\n init(\"Liberation Sans\", ..._Liberation__WEBPACK_IMPORTED_MODULE_11__.LiberationFontFaces);\n init(\"Lilita One\", ..._Lilita__WEBPACK_IMPORTED_MODULE_12__.LilitaFontFaces);\n init(\"Nunito\", ..._Nunito__WEBPACK_IMPORTED_MODULE_13__.NunitoFontFaces);\n init(\"Virgil\", ..._Virgil__WEBPACK_IMPORTED_MODULE_14__.VirgilFontFaces); // fallback font faces\n\n init(_constants__WEBPACK_IMPORTED_MODULE_0__.CJK_HAND_DRAWN_FALLBACK_FONT, ..._Xiaolai__WEBPACK_IMPORTED_MODULE_15__.XiaolaiFontFaces);\n init(_constants__WEBPACK_IMPORTED_MODULE_0__.WINDOWS_EMOJI_FALLBACK_FONT, ..._Emoji__WEBPACK_IMPORTED_MODULE_8__.EmojiFontFaces);\n Fonts._initialized = true;\n return fonts.registered;\n }\n /**\n * Register a new font.\n *\n * @param family font family\n * @param metadata font metadata\n * @param fontFacesDecriptors font faces descriptors\n */\n\n\n static register(family, metadata, ...fontFacesDecriptors) {\n var _b; // TODO: likely we will need to abandon number value in order to support custom fonts\n\n\n const fontFamily = (_b = _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY[family]) !== null && _b !== void 0 ? _b : _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY_FALLBACKS[family];\n const registeredFamily = this.registered.get(fontFamily);\n\n if (!registeredFamily) {\n this.registered.set(fontFamily, {\n metadata,\n fontFaces: fontFacesDecriptors.map(({\n uri,\n descriptors\n }) => new _ExcalidrawFontFace__WEBPACK_IMPORTED_MODULE_5__.ExcalidrawFontFace(family, uri, descriptors))\n });\n }\n\n return this.registered;\n }\n\n static getAllFamilies() {\n return Array.from(Fonts.registered.keys());\n } //zsviczian made public\n\n\n static getElementsFamilies(elements) {\n return Array.from(elements.reduce((families, element) => {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n families.add(element.fontFamily);\n }\n\n return families;\n }, new Set()));\n }\n\n}\n_a = Fonts; // it's ok to track fonts across multiple instances only once, so let's use\n// a static member to reduce memory footprint\n\nFonts.loadedFontsCache = new Set();\nFonts._initialized = false;\n/**\n * Load all registered font faces.\n */\n\nFonts.loadAllFonts = async () => {\n const allFamilies = Fonts.getAllFamilies();\n return Fonts.loadFontFaces(allFamilies);\n};\n/**\n * Load font faces for passed elements - use when the scene is unavailable (i.e. export).\n */\n\n\nFonts.loadElementsFonts = async elements => {\n const fontFamilies = Fonts.getElementsFamilies(elements);\n return await Fonts.loadFontFaces(fontFamilies);\n};\n/**\n * Calculates vertical offset for a text with alphabetic baseline.\n */\n\n\nconst getVerticalOffset = (fontFamily, fontSize, lineHeightPx) => {\n var _b;\n\n const {\n unitsPerEm,\n ascender,\n descender\n } = ((_b = Fonts.registered.get(fontFamily)) === null || _b === void 0 ? void 0 : _b.metadata.metrics) || _FontMetadata__WEBPACK_IMPORTED_MODULE_16__.FONT_METADATA[_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY.Virgil].metrics;\n const fontSizeEm = fontSize / unitsPerEm;\n const lineGap = (lineHeightPx - fontSizeEm * ascender + fontSizeEm * descender) / 2;\n const verticalOffset = fontSizeEm * ascender + lineGap;\n return verticalOffset;\n};\n/**\n * Gets line height forr a selected family.\n */\n\nconst getLineHeight = fontFamily => {\n var _b;\n\n const {\n lineHeight\n } = ((_b = Fonts.registered.get(fontFamily)) === null || _b === void 0 ? void 0 : _b.metadata.metrics) || _FontMetadata__WEBPACK_IMPORTED_MODULE_16__.FONT_METADATA[_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY.Excalifont].metrics;\n return lineHeight;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./fonts/Fonts.ts?");
3182
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"Fonts\": () => (/* binding */ Fonts),\n/* harmony export */ \"getLineHeight\": () => (/* binding */ getLineHeight),\n/* harmony export */ \"getVerticalOffset\": () => (/* binding */ getVerticalOffset)\n/* harmony export */ });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _element_textWrapping__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../element/textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../scene/ShapeCache */ \"./scene/ShapeCache.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _ExcalidrawFontFace__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ExcalidrawFontFace */ \"./fonts/ExcalidrawFontFace.ts\");\n/* harmony import */ var _Cascadia__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Cascadia */ \"./fonts/Cascadia/index.ts\");\n/* harmony import */ var _ComicShanns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./ComicShanns */ \"./fonts/ComicShanns/index.ts\");\n/* harmony import */ var _Emoji__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./Emoji */ \"./fonts/Emoji/index.ts\");\n/* harmony import */ var _Excalifont__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./Excalifont */ \"./fonts/Excalifont/index.ts\");\n/* harmony import */ var _Helvetica__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./Helvetica */ \"./fonts/Helvetica/index.ts\");\n/* harmony import */ var _Liberation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./Liberation */ \"./fonts/Liberation/index.ts\");\n/* harmony import */ var _Lilita__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Lilita */ \"./fonts/Lilita/index.ts\");\n/* harmony import */ var _Nunito__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./Nunito */ \"./fonts/Nunito/index.ts\");\n/* harmony import */ var _Virgil__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./Virgil */ \"./fonts/Virgil/index.ts\");\n/* harmony import */ var _Xiaolai__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./Xiaolai */ \"./fonts/Xiaolai/index.ts\");\n/* harmony import */ var _FontMetadata__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./FontMetadata */ \"./fonts/FontMetadata.ts\");\nvar _a;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nclass Fonts {\n static get registered() {\n // lazy load the font registration\n if (!Fonts._registered) {\n Fonts._registered = Fonts.init();\n } else if (!Fonts._initialized) {\n // case when host app register fonts before they are lazy loaded\n // don't override whatever has been previously registered\n Fonts._registered = new Map([...Fonts.init().entries(), ...Fonts._registered.entries()]);\n }\n\n return Fonts._registered;\n }\n\n get registered() {\n return Fonts.registered;\n }\n\n constructor(scene) {\n /**\n * Get all the font families for the given scene.\n */\n this.getSceneFamilies = () => {\n return Fonts.getUniqueFamilies(this.scene.getNonDeletedElements());\n };\n /**\n * if we load a (new) font, it's likely that text elements using it have\n * already been rendered using a fallback font. Thus, we want invalidate\n * their shapes and rerender. See #637.\n *\n * Invalidates text elements and rerenders scene, provided that at least one\n * of the supplied fontFaces has not already been processed.\n */\n\n\n this.onLoaded = fontFaces => {\n // bail if all fonts with have been processed. We're checking just a\n // subset of the font properties (though it should be enough), so it\n // can technically bail on a false positive.\n let shouldBail = true;\n\n for (const fontFace of fontFaces) {\n const sig = `${fontFace.family}-${fontFace.style}-${fontFace.weight}-${fontFace.unicodeRange}`; // make sure to update our cache with all the loaded font faces\n\n if (!Fonts.loadedFontsCache.has(sig)) {\n Fonts.loadedFontsCache.add(sig);\n shouldBail = false;\n }\n }\n\n if (shouldBail) {\n return;\n }\n\n let didUpdate = false;\n const elementsMap = this.scene.getNonDeletedElementsMap();\n\n for (const element of this.scene.getNonDeletedElements()) {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n didUpdate = true;\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_4__.ShapeCache[\"delete\"](element); // clear the width cache, so that we don't perform subsequent wrapping based on the stale fallback font metrics\n\n _element_textElement__WEBPACK_IMPORTED_MODULE_2__.charWidth.clearCache((0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)(element));\n const container = (0,_element_textElement__WEBPACK_IMPORTED_MODULE_2__.getContainerElement)(element, elementsMap);\n\n if (container) {\n _scene_ShapeCache__WEBPACK_IMPORTED_MODULE_4__.ShapeCache[\"delete\"](container);\n }\n }\n }\n\n if (didUpdate) {\n this.scene.triggerUpdate();\n }\n };\n /**\n * Load font faces for a given scene and trigger scene update.\n *\n * FontFaceSet loadingdone event we listen on may not always\n * fire (looking at you Safari), so on init we manually load all\n * fonts and rerender scene text elements once done.\n *\n * For Safari we make sure to check against each loaded font face\n * with the unique characters per family in the scene,\n * otherwise fonts might remain unloaded.\n */\n\n\n this.loadSceneFonts = async () => {\n const sceneFamilies = this.getSceneFamilies();\n const charsPerFamily = _constants__WEBPACK_IMPORTED_MODULE_0__.isSafari ? Fonts.getCharsPerFamily(this.scene.getNonDeletedElements()) : undefined;\n return Fonts.loadFontFaces(sceneFamilies, charsPerFamily);\n };\n\n this.scene = scene;\n }\n /**\n * Generate CSS @font-face declarations for the given elements.\n */\n\n\n static async generateFontFaceDeclarations(elements) {\n const families = Fonts.getUniqueFamilies(elements);\n const charsPerFamily = Fonts.getCharsPerFamily(elements); // for simplicity, assuming we have just one family with the CJK handdrawn fallback\n\n const familyWithCJK = families.find(x => (0,_constants__WEBPACK_IMPORTED_MODULE_0__.getFontFamilyFallbacks)(x).includes(_constants__WEBPACK_IMPORTED_MODULE_0__.CJK_HAND_DRAWN_FALLBACK_FONT));\n\n if (familyWithCJK) {\n const characters = Fonts.getCharacters(charsPerFamily, familyWithCJK);\n\n if ((0,_element_textWrapping__WEBPACK_IMPORTED_MODULE_3__.containsCJK)(characters)) {\n const family = _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY_FALLBACKS[_constants__WEBPACK_IMPORTED_MODULE_0__.CJK_HAND_DRAWN_FALLBACK_FONT]; // adding the same characters to the CJK handrawn family\n\n charsPerFamily[family] = new Set(characters); // the order between the families and fallbacks is important, as fallbacks need to be defined first and in the reversed order\n // so that they get overriden with the later defined font faces, i.e. in case they share some codepoints\n\n families.unshift(_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY_FALLBACKS[_constants__WEBPACK_IMPORTED_MODULE_0__.CJK_HAND_DRAWN_FALLBACK_FONT]);\n }\n } // don't trigger hundreds of concurrent requests (each performing fetch, creating a worker, etc.),\n // instead go three requests at a time, in a controlled manner, without completely blocking the main thread\n // and avoiding potential issues such as rate limits\n\n\n const iterator = Fonts.fontFacesStylesGenerator(families, charsPerFamily);\n const concurrency = 3;\n const fontFaces = await new _utils__WEBPACK_IMPORTED_MODULE_5__.PromisePool(iterator, concurrency).all(); // dedup just in case (i.e. could be the same font faces with 0 glyphs)\n\n return Array.from(new Set(fontFaces));\n } //zsviczian made public\n\n\n static async loadFontFaces(fontFamilies, charsPerFamily) {\n // add all registered font faces into the `document.fonts` (if not added already)\n for (const {\n fontFaces,\n metadata\n } of Fonts.registered.values()) {\n // skip registering font faces for local fonts (i.e. Helvetica)\n if (metadata.local) {\n continue;\n }\n\n for (const {\n fontFace\n } of fontFaces) {\n if (!window.document.fonts.has(fontFace) && fontFace.family !== \"Local Font\" //zsviczian if Local Font is registered I can't change it dymamically\n ) {\n window.document.fonts.add(fontFace);\n }\n }\n } // loading 10 font faces at a time, in a controlled manner\n\n\n const iterator = Fonts.fontFacesLoader(fontFamilies, charsPerFamily);\n const concurrency = 10;\n const fontFaces = await new _utils__WEBPACK_IMPORTED_MODULE_5__.PromisePool(iterator, concurrency).all();\n return fontFaces.flat().filter(Boolean);\n }\n\n static *fontFacesLoader(fontFamilies, charsPerFamily) {\n for (const [index, fontFamily] of fontFamilies.entries()) {\n const font = (0,_utils__WEBPACK_IMPORTED_MODULE_5__.getFontString)({\n fontFamily,\n fontSize: 16\n }); // WARN: without \"text\" param it does not have to mean that all font faces are loaded, instead it could be just one!\n // for Safari on init, we rather check with the \"text\" param, even though it's less efficient, as otherwise fonts might remain unloaded\n\n const text = _constants__WEBPACK_IMPORTED_MODULE_0__.isSafari && charsPerFamily ? Fonts.getCharacters(charsPerFamily, fontFamily) : \"\";\n\n if (!window.document.fonts.check(font, text) && !font.startsWith(\"16px Local Font\") && //zsviczian if Local Font is registered I can't change it dymamically\n !font.startsWith(\"16px Helvetica\") //zsviczian there is an error loading Helvetica font (need to validate the error still exists)\n ) {\n yield (0,_utils__WEBPACK_IMPORTED_MODULE_5__.promiseTry)(async () => {\n var _b;\n\n try {\n // WARN: browser prioritizes loading only font faces with unicode ranges for characters which are present in the document (html & canvas), other font faces could stay unloaded\n // we might want to retry here, i.e. in case CDN is down, but so far I didn't experience any issues - maybe it handles retry-like logic under the hood\n const fontFaces = await window.document.fonts.load(font, text);\n return [index, fontFaces];\n } catch (e) {\n // don't let it all fail if just one font fails to load\n console.error(`Failed to load font \"${font}\" from urls \"${(_b = Fonts.registered.get(fontFamily)) === null || _b === void 0 ? void 0 : _b.fontFaces.map(x => x.urls)}\"`, e);\n }\n });\n }\n }\n }\n\n static *fontFacesStylesGenerator(families, charsPerFamily) {\n var _b;\n\n for (const [familyIndex, family] of families.entries()) {\n const {\n fontFaces,\n metadata\n } = (_b = Fonts.registered.get(family)) !== null && _b !== void 0 ? _b : {};\n\n if (!Array.isArray(fontFaces)) {\n console.error(`Couldn't find registered fonts for font-family \"${family}\"`, Fonts.registered);\n continue;\n }\n\n if (metadata === null || metadata === void 0 ? void 0 : metadata.local) {\n // don't inline local fonts\n continue;\n }\n\n for (const [fontFaceIndex, fontFace] of fontFaces.entries()) {\n yield (0,_utils__WEBPACK_IMPORTED_MODULE_5__.promiseTry)(async () => {\n try {\n const characters = Fonts.getCharacters(charsPerFamily, family);\n const fontFaceCSS = await fontFace.toCSS(characters);\n\n if (!fontFaceCSS) {\n return;\n } // giving a buffer of 10K font faces per family\n\n\n const fontFaceOrder = familyIndex * 10000 + fontFaceIndex;\n const fontFaceTuple = [fontFaceOrder, fontFaceCSS];\n return fontFaceTuple;\n } catch (error) {\n console.error(`Couldn't transform font-face to css for family \"${fontFace.fontFace.family}\"`, error);\n }\n });\n }\n }\n }\n /**\n * Register a new font.\n *\n * @param family font family\n * @param metadata font metadata\n * @param fontFacesDecriptors font faces descriptors\n */\n\n\n static register(family, metadata, ...fontFacesDecriptors) {\n var _b; // TODO: likely we will need to abandon number value in order to support custom fonts\n\n\n const fontFamily = (_b = _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY[family]) !== null && _b !== void 0 ? _b : _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY_FALLBACKS[family];\n const registeredFamily = this.registered.get(fontFamily);\n\n if (!registeredFamily) {\n this.registered.set(fontFamily, {\n metadata,\n fontFaces: fontFacesDecriptors.map(({\n uri,\n descriptors\n }) => new _ExcalidrawFontFace__WEBPACK_IMPORTED_MODULE_6__.ExcalidrawFontFace(family, uri, descriptors))\n });\n }\n\n return this.registered;\n }\n /**\n * WARN: should be called just once on init, even across multiple instances.\n */\n\n\n static init() {\n const fonts = {\n registered: new Map()\n };\n\n const init = (family, ...fontFacesDescriptors) => {\n var _b, _c;\n\n const fontFamily = (_b = _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY[family]) !== null && _b !== void 0 ? _b : _constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY_FALLBACKS[family]; // default to Excalifont metrics\n\n const metadata = (_c = _FontMetadata__WEBPACK_IMPORTED_MODULE_17__.FONT_METADATA[fontFamily]) !== null && _c !== void 0 ? _c : _FontMetadata__WEBPACK_IMPORTED_MODULE_17__.FONT_METADATA[_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY.Excalifont];\n Fonts.register.call(fonts, family, metadata, ...fontFacesDescriptors);\n };\n\n init(\"Cascadia\", ..._Cascadia__WEBPACK_IMPORTED_MODULE_7__.CascadiaFontFaces);\n init(\"Comic Shanns\", ..._ComicShanns__WEBPACK_IMPORTED_MODULE_8__.ComicShannsFontFaces);\n init(\"Excalifont\", ..._Excalifont__WEBPACK_IMPORTED_MODULE_10__.ExcalifontFontFaces); // keeping for backwards compatibility reasons, uses system font (Helvetica on MacOS, Arial on Win)\n\n init(\"Helvetica\", ..._Helvetica__WEBPACK_IMPORTED_MODULE_11__.HelveticaFontFaces); // used for server-side pdf & png export instead of helvetica (technically does not need metrics, but kept in for consistency)\n\n init(\"Liberation Sans\", ..._Liberation__WEBPACK_IMPORTED_MODULE_12__.LiberationFontFaces);\n init(\"Lilita One\", ..._Lilita__WEBPACK_IMPORTED_MODULE_13__.LilitaFontFaces);\n init(\"Nunito\", ..._Nunito__WEBPACK_IMPORTED_MODULE_14__.NunitoFontFaces);\n init(\"Virgil\", ..._Virgil__WEBPACK_IMPORTED_MODULE_15__.VirgilFontFaces); // fallback font faces\n\n init(_constants__WEBPACK_IMPORTED_MODULE_0__.CJK_HAND_DRAWN_FALLBACK_FONT, ..._Xiaolai__WEBPACK_IMPORTED_MODULE_16__.XiaolaiFontFaces);\n init(_constants__WEBPACK_IMPORTED_MODULE_0__.WINDOWS_EMOJI_FALLBACK_FONT, ..._Emoji__WEBPACK_IMPORTED_MODULE_9__.EmojiFontFaces);\n Fonts._initialized = true;\n return fonts.registered;\n }\n /**\n * Get all the unique font families for the given elements.\n */\n\n\n static getUniqueFamilies(elements) {\n return Array.from(elements.reduce((families, element) => {\n if ((0,_element__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n families.add(element.fontFamily);\n }\n\n return families;\n }, new Set()));\n }\n /**\n * Get all the unique characters per font family for the given scene.\n */\n\n\n static getCharsPerFamily(elements) {\n const charsPerFamily = {};\n\n for (const element of elements) {\n if (!(0,_element__WEBPACK_IMPORTED_MODULE_1__.isTextElement)(element)) {\n continue;\n } // gather unique codepoints only when inlining fonts\n\n\n for (const char of element.originalText) {\n if (!charsPerFamily[element.fontFamily]) {\n charsPerFamily[element.fontFamily] = new Set();\n }\n\n charsPerFamily[element.fontFamily].add(char);\n }\n }\n\n return charsPerFamily;\n }\n /**\n * Get characters for a given family.\n */\n\n\n static getCharacters(charsPerFamily, family) {\n return charsPerFamily[family] ? Array.from(charsPerFamily[family]).join(\"\") : \"\";\n }\n /**\n * Get all registered font families.\n */\n\n\n static getAllFamilies() {\n return Array.from(Fonts.registered.keys());\n }\n\n}\n_a = Fonts; // it's ok to track fonts across multiple instances only once, so let's use\n// a static member to reduce memory footprint\n\nFonts.loadedFontsCache = new Set();\nFonts._initialized = false;\n/**\n * Load font faces for passed elements - use when the scene is unavailable (i.e. export).\n *\n * For Safari we make sure to check against each loaded font face,\n * with the unique characters per family in the elements\n * otherwise fonts might remain unloaded.\n */\n\nFonts.loadElementsFonts = async elements => {\n const fontFamilies = Fonts.getUniqueFamilies(elements);\n const charsPerFamily = _constants__WEBPACK_IMPORTED_MODULE_0__.isSafari ? Fonts.getCharsPerFamily(elements) : undefined;\n return Fonts.loadFontFaces(fontFamilies, charsPerFamily);\n};\n/**\n * Load all registered font faces.\n */\n\n\nFonts.loadAllFonts = async () => {\n const allFamilies = Fonts.getAllFamilies();\n return Fonts.loadFontFaces(allFamilies);\n};\n/**\n * Calculates vertical offset for a text with alphabetic baseline.\n */\n\n\nconst getVerticalOffset = (fontFamily, fontSize, lineHeightPx) => {\n var _b;\n\n const {\n unitsPerEm,\n ascender,\n descender\n } = ((_b = Fonts.registered.get(fontFamily)) === null || _b === void 0 ? void 0 : _b.metadata.metrics) || _FontMetadata__WEBPACK_IMPORTED_MODULE_17__.FONT_METADATA[_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY.Virgil].metrics;\n const fontSizeEm = fontSize / unitsPerEm;\n const lineGap = (lineHeightPx - fontSizeEm * ascender + fontSizeEm * descender) / 2;\n const verticalOffset = fontSizeEm * ascender + lineGap;\n return verticalOffset;\n};\n/**\n * Gets line height forr a selected family.\n */\n\nconst getLineHeight = fontFamily => {\n var _b;\n\n const {\n lineHeight\n } = ((_b = Fonts.registered.get(fontFamily)) === null || _b === void 0 ? void 0 : _b.metadata.metrics) || _FontMetadata__WEBPACK_IMPORTED_MODULE_17__.FONT_METADATA[_constants__WEBPACK_IMPORTED_MODULE_0__.FONT_FAMILY.Excalifont].metrics;\n return lineHeight;\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./fonts/Fonts.ts?");
3172
3183
 
3173
3184
  /***/ }),
3174
3185
 
@@ -3520,7 +3531,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3520
3531
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3521
3532
 
3522
3533
  "use strict";
3523
- 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.6-8\"}/dist/`;\n}\n\n//# sourceURL=webpack://ExcalidrawLib/./publicPath.js?");
3534
+ 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.6-9\"}/dist/`;\n}\n\n//# sourceURL=webpack://ExcalidrawLib/./publicPath.js?");
3524
3535
 
3525
3536
  /***/ }),
3526
3537
 
@@ -3718,7 +3729,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3718
3729
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3719
3730
 
3720
3731
  "use strict";
3721
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"exportToCanvas\": () => (/* binding */ exportToCanvas),\n/* harmony export */ \"exportToSvg\": () => (/* binding */ exportToSvg),\n/* harmony export */ \"getExportSize\": () => (/* binding */ getExportSize)\n/* harmony export */ });\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var _element_bounds__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element/bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _renderer_staticSvgScene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../renderer/staticSvgScene */ \"./renderer/staticSvgScene.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _data_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../data/json */ \"./data/json.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../element/image */ \"./element/image.ts\");\n/* harmony import */ var _frame__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../frame */ \"./frame.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../element/mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../element/typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _fractionalIndex__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../fractionalIndex */ \"./fractionalIndex.ts\");\n/* harmony import */ var _renderer_staticScene__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../renderer/staticScene */ \"./renderer/staticScene.ts\");\n/* harmony import */ var _fonts__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../fonts */ \"./fonts/index.ts\");\n/* harmony import */ var _element_textElement__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../element/textElement */ \"./element/textElement.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;\n\nconst truncateText = (element, maxWidth) => {\n if (element.width <= maxWidth) {\n return element;\n }\n\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n ctx.font = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getFontString)({\n fontFamily: element.fontFamily,\n fontSize: element.fontSize\n });\n let text = element.text;\n const metrics = ctx.measureText(text);\n\n if (metrics.width > maxWidth) {\n // we iterate from the right, removing characters one by one instead\n // of bulding the string up. This assumes that it's more likely\n // your frame names will overflow by not that many characters\n // (if ever), so it sohuld be faster this way.\n for (let i = text.length; i > 0; i--) {\n const newText = `${text.slice(0, i)}...`;\n\n if (ctx.measureText(newText).width <= maxWidth) {\n text = newText;\n break;\n }\n }\n }\n\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_10__.newElementWith)(element, {\n text,\n width: maxWidth\n });\n};\n/**\n * When exporting frames, we need to render frame labels which are currently\n * being rendered in DOM when editing. Adding the labels as regular text\n * elements seems like a simple hack. In the future we'll want to move to\n * proper canvas rendering, even within editor (instead of DOM).\n */\n\n\nconst addFrameLabelsAsTextElements = (elements, opts) => {\n var _a, _b, _c;\n\n const nextElements = [];\n\n for (const element of elements) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_11__.isFrameLikeElement)(element)) {\n let textElement = (0,_element__WEBPACK_IMPORTED_MODULE_9__.newTextElement)({\n x: element.x,\n y: element.y - _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameOffsetY,\n fontFamily: _constants__WEBPACK_IMPORTED_MODULE_4__.FONT_FAMILY.Helvetica,\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameFontSize,\n lineHeight: _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameLineHeight,\n strokeColor: (_c = (_b = (_a = element.customData) === null || _a === void 0 ? void 0 : _a.frameColor) === null || _b === void 0 ? void 0 : _b.nameColor) !== null && _c !== void 0 ? _c : opts.exportWithDarkMode ? _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameColorDarkTheme : _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameColorLightTheme,\n text: (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getFrameLikeTitle)(element),\n rawText: (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getFrameLikeTitle)(element) //zsviczian\n\n });\n textElement.y -= textElement.height;\n textElement = truncateText(textElement, element.width);\n nextElements.push(textElement);\n }\n\n nextElements.push(element);\n }\n\n return nextElements;\n};\n\nconst getFrameRenderingConfig = (exportingFrame, frameRendering) => {\n frameRendering = frameRendering || (0,_appState__WEBPACK_IMPORTED_MODULE_5__.getDefaultAppState)().frameRendering;\n return {\n enabled: exportingFrame ? true : frameRendering.enabled,\n outline: exportingFrame ? false : frameRendering.outline,\n name: exportingFrame ? false : frameRendering.name,\n clip: exportingFrame ? true : frameRendering.clip\n };\n};\n\nconst prepareElementsForRender = ({\n elements,\n exportingFrame,\n frameRendering,\n exportWithDarkMode\n}) => {\n let nextElements;\n\n if (exportingFrame) {\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getElementsOverlappingFrame)(elements, exportingFrame);\n } else if (frameRendering.enabled && frameRendering.name) {\n nextElements = addFrameLabelsAsTextElements(elements, {\n exportWithDarkMode\n });\n } else {\n nextElements = elements;\n }\n\n return nextElements;\n};\n\nconst exportToCanvas = async (elements, appState, files, {\n exportBackground,\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n viewBackgroundColor,\n exportingFrame\n}, createCanvas = (width, height) => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width * appState.exportScale;\n canvas.height = height * appState.exportScale;\n return {\n canvas,\n scale: appState.exportScale\n };\n}, loadFonts = async () => {\n await _fonts__WEBPACK_IMPORTED_MODULE_14__.Fonts.loadElementsFonts(elements);\n}) => {\n var _a; // load font faces before continuing, by default leverages browsers' [FontFace API](https://developer.mozilla.org/en-US/docs/Web/API/FontFace)\n\n\n await loadFonts();\n const frameRendering = getFrameRenderingConfig(exportingFrame !== null && exportingFrame !== void 0 ? exportingFrame : null, (_a = appState.frameRendering) !== null && _a !== void 0 ? _a : null); // for canvas export, don't clip if exporting a specific frame as it would\n // clip the corners of the content\n\n if (exportingFrame) {\n frameRendering.clip = false;\n }\n\n const elementsForRender = prepareElementsForRender({\n elements,\n exportingFrame,\n exportWithDarkMode: appState.exportWithDarkMode,\n frameRendering\n });\n\n if (exportingFrame) {\n exportPadding = 0;\n }\n\n const [minX, minY, width, height] = getCanvasSize(exportingFrame ? [exportingFrame] : (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getRootElements)(elementsForRender), exportPadding);\n const {\n canvas,\n scale = 1\n } = createCanvas(width, height);\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_5__.getDefaultAppState)();\n const {\n imageCache\n } = await (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.updateImageCache)({\n imageCache: new Map(),\n fileIds: (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.getInitializedImageElements)(elementsForRender).map(element => element.fileId),\n files\n });\n (0,_renderer_staticScene__WEBPACK_IMPORTED_MODULE_13__.renderStaticScene)({\n canvas,\n rc: roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].canvas(canvas),\n elementsMap: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.toBrandedType)((0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)(elementsForRender)),\n allElementsMap: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.toBrandedType)((0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)((0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_12__.syncInvalidIndices)(elements))),\n visibleElements: elementsForRender,\n scale,\n appState: Object.assign(Object.assign({}, appState), {\n frameRendering,\n viewBackgroundColor: exportBackground ? viewBackgroundColor : null,\n scrollX: -minX + exportPadding,\n scrollY: -minY + exportPadding,\n zoom: defaultAppState.zoom,\n shouldCacheIgnoreZoom: false,\n theme: appState.exportWithDarkMode ? _constants__WEBPACK_IMPORTED_MODULE_4__.THEME.DARK : _constants__WEBPACK_IMPORTED_MODULE_4__.THEME.LIGHT\n }),\n renderConfig: {\n canvasBackgroundColor: viewBackgroundColor,\n imageCache,\n renderGrid: false,\n isExporting: true,\n // empty disables embeddable rendering\n embedsValidationStatus: new Map(),\n elementsPendingErasure: new Set(),\n pendingFlowchartNodes: null\n }\n });\n return canvas;\n};\nconst exportToSvg = async (elements, appState, files, opts) => {\n var _a, _b, _c, _d;\n\n const frameRendering = getFrameRenderingConfig((_a = opts === null || opts === void 0 ? void 0 : opts.exportingFrame) !== null && _a !== void 0 ? _a : null, (_b = appState.frameRendering) !== null && _b !== void 0 ? _b : null);\n let {\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n exportWithDarkMode = false,\n viewBackgroundColor,\n exportScale = 1,\n exportEmbedScene\n } = appState;\n const {\n exportingFrame = null\n } = opts || {};\n const elementsForRender = prepareElementsForRender({\n elements,\n exportingFrame,\n exportWithDarkMode,\n frameRendering\n });\n\n if (exportingFrame) {\n exportPadding = 0;\n }\n\n let metadata = \"\"; // we need to serialize the \"original\" elements before we put them through\n // the tempScene hack which duplicates and regenerates ids\n\n if (exportEmbedScene) {\n try {\n metadata = await (await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ../data/image */ \"./data/image.ts\"))).encodeSvgMetadata({\n // when embedding scene, we want to embed the origionally supplied\n // elements which don't contain the temp frame labels.\n // But it also requires that the exportToSvg is being supplied with\n // only the elements that we're exporting, and no extra.\n text: (0,_data_json__WEBPACK_IMPORTED_MODULE_6__.serializeAsJSON)(elements, appState, files || {}, \"local\")\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n const [minX, minY, width, height] = getCanvasSize(exportingFrame ? [exportingFrame] : (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getRootElements)(elementsForRender), exportPadding); // initialize SVG root\n\n const svgRoot = document.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"svg\");\n svgRoot.setAttribute(\"version\", \"1.1\");\n svgRoot.setAttribute(\"xmlns\", _constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS);\n svgRoot.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svgRoot.setAttribute(\"width\", `${width * exportScale}`);\n svgRoot.setAttribute(\"height\", `${height * exportScale}`);\n\n if (exportWithDarkMode) {\n svgRoot.setAttribute(\"filter\", _constants__WEBPACK_IMPORTED_MODULE_4__.THEME_FILTER);\n }\n\n const offsetX = -minX + exportPadding;\n const offsetY = -minY + exportPadding;\n const frameElements = (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getFrameLikeElements)(elements);\n let exportingFrameClipPath = \"\";\n const elementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)(elements);\n\n for (const frame of frameElements) {\n const [x1, y1, x2, y2] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getElementAbsoluteCoords)(frame, elementsMap);\n const cx = (x2 - x1) / 2 - (frame.x - x1);\n const cy = (y2 - y1) / 2 - (frame.y - y1);\n exportingFrameClipPath += `<clipPath id=${frame.id}>\n <rect transform=\"translate(${frame.x + offsetX} ${frame.y + offsetY}) rotate(${frame.angle} ${cx} ${cy})\"\n width=\"${frame.width}\"\n height=\"${frame.height}\"\n ${exportingFrame ? \"\" : `rx=${_constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.radius} ry=${_constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.radius}`}\n >\n </rect>\n </clipPath>`;\n }\n\n const fontFaces = (opts === null || opts === void 0 ? void 0 : opts.skipInliningFonts) ? [] : await getFontFaces(elements);\n const delimiter = \"\\n \"; // 6 spaces\n\n svgRoot.innerHTML = `\n ${SVG_EXPORT_TAG}\n ${metadata}\n <defs>\n <style class=\"style-fonts\">${delimiter}${fontFaces.join(delimiter)}\n </style>\n ${exportingFrameClipPath}\n </defs>\n `; // render background rect\n\n if (appState.exportBackground && viewBackgroundColor) {\n const rect = svgRoot.ownerDocument.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"rect\");\n rect.setAttribute(\"x\", \"0\");\n rect.setAttribute(\"y\", \"0\");\n rect.setAttribute(\"width\", `${width}`);\n rect.setAttribute(\"height\", `${height}`);\n rect.setAttribute(\"fill\", viewBackgroundColor);\n svgRoot.appendChild(rect);\n }\n\n const rsvg = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].svg(svgRoot);\n const renderEmbeddables = (_c = opts === null || opts === void 0 ? void 0 : opts.renderEmbeddables) !== null && _c !== void 0 ? _c : false;\n (0,_renderer_staticSvgScene__WEBPACK_IMPORTED_MODULE_2__.renderSceneToSvg)(elementsForRender, (0,_utils__WEBPACK_IMPORTED_MODULE_3__.toBrandedType)((0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)(elementsForRender)), rsvg, svgRoot, files || {}, {\n offsetX,\n offsetY,\n isExporting: true,\n exportWithDarkMode,\n renderEmbeddables,\n frameRendering,\n frameColor: appState.frameColor,\n canvasBackgroundColor: viewBackgroundColor,\n embedsValidationStatus: renderEmbeddables ? new Map(elementsForRender.filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_11__.isFrameLikeElement)(element)).map(element => [element.id, true])) : new Map(),\n reuseImages: (_d = opts === null || opts === void 0 ? void 0 : opts.reuseImages) !== null && _d !== void 0 ? _d : true\n });\n return svgRoot;\n}; // calculate smallest area to fit the contents in\n\nconst getCanvasSize = (elements, exportPadding) => {\n const [minX, minY, maxX, maxY] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getCommonBounds)(elements);\n const width = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minX, maxX) + exportPadding * 2;\n const height = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minY, maxY) + exportPadding * 2;\n return [minX, minY, width, height];\n};\n\nconst getExportSize = (elements, exportPadding, scale) => {\n const [,, width, height] = getCanvasSize(elements, exportPadding).map(dimension => Math.trunc(dimension * scale));\n return [width, height];\n};\n\nconst getFontFaces = async elements => {\n const fontFamilies = new Set();\n const charsPerFamily = {};\n\n for (const element of elements) {\n if (!(0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_11__.isTextElement)(element)) {\n continue;\n }\n\n fontFamilies.add(element.fontFamily); // gather unique codepoints only when inlining fonts\n\n for (const char of element.originalText) {\n if (!charsPerFamily[element.fontFamily]) {\n charsPerFamily[element.fontFamily] = new Set();\n }\n\n charsPerFamily[element.fontFamily].add(char);\n }\n }\n\n const orderedFamilies = Array.from(fontFamilies); // for simplicity, assuming we have just one family with the CJK handdrawn fallback\n\n const familyWithCJK = orderedFamilies.find(x => (0,_constants__WEBPACK_IMPORTED_MODULE_4__.getFontFamilyFallbacks)(x).includes(_constants__WEBPACK_IMPORTED_MODULE_4__.CJK_HAND_DRAWN_FALLBACK_FONT));\n\n if (familyWithCJK) {\n const characters = getChars(charsPerFamily[familyWithCJK]);\n\n if ((0,_element_textElement__WEBPACK_IMPORTED_MODULE_15__.containsCJK)(characters)) {\n const family = _constants__WEBPACK_IMPORTED_MODULE_4__.FONT_FAMILY_FALLBACKS[_constants__WEBPACK_IMPORTED_MODULE_4__.CJK_HAND_DRAWN_FALLBACK_FONT]; // adding the same characters to the CJK handrawn family\n\n charsPerFamily[family] = new Set(characters); // the order between the families and fallbacks is important, as fallbacks need to be defined first and in the reversed order\n // so that they get overriden with the later defined font faces, i.e. in case they share some codepoints\n\n orderedFamilies.unshift(_constants__WEBPACK_IMPORTED_MODULE_4__.FONT_FAMILY_FALLBACKS[_constants__WEBPACK_IMPORTED_MODULE_4__.CJK_HAND_DRAWN_FALLBACK_FONT]);\n }\n }\n\n const iterator = fontFacesIterator(orderedFamilies, charsPerFamily); // don't trigger hundreds of concurrent requests (each performing fetch, creating a worker, etc.),\n // instead go three requests at a time, in a controlled manner, without completely blocking the main thread\n // and avoiding potential issues such as rate limits\n\n const concurrency = 3;\n const fontFaces = await new _utils__WEBPACK_IMPORTED_MODULE_3__.PromisePool(iterator, concurrency).all(); // dedup just in case (i.e. could be the same font faces with 0 glyphs)\n\n return Array.from(new Set(fontFaces));\n};\n\nfunction* fontFacesIterator(families, charsPerFamily) {\n var _a;\n\n for (const [familyIndex, family] of families.entries()) {\n const {\n fontFaces,\n metadata\n } = (_a = _fonts__WEBPACK_IMPORTED_MODULE_14__.Fonts.registered.get(family)) !== null && _a !== void 0 ? _a : {};\n\n if (!Array.isArray(fontFaces)) {\n console.error(`Couldn't find registered fonts for font-family \"${family}\"`, _fonts__WEBPACK_IMPORTED_MODULE_14__.Fonts.registered);\n continue;\n }\n\n if (metadata === null || metadata === void 0 ? void 0 : metadata.local) {\n // don't inline local fonts\n continue;\n }\n\n for (const [fontFaceIndex, fontFace] of fontFaces.entries()) {\n yield (0,_utils__WEBPACK_IMPORTED_MODULE_3__.promiseTry)(async () => {\n try {\n const characters = getChars(charsPerFamily[family]);\n const fontFaceCSS = await fontFace.toCSS(characters);\n\n if (!fontFaceCSS) {\n return;\n } // giving a buffer of 10K font faces per family\n\n\n const fontFaceOrder = familyIndex * 10000 + fontFaceIndex;\n const fontFaceTuple = [fontFaceOrder, fontFaceCSS];\n return fontFaceTuple;\n } catch (error) {\n console.error(`Couldn't transform font-face to css for family \"${fontFace.fontFace.family}\"`, error);\n }\n });\n }\n }\n}\n\nconst getChars = characterSet => Array.from(characterSet).join(\"\");\n\n//# sourceURL=webpack://ExcalidrawLib/./scene/export.ts?");
3732
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"exportToCanvas\": () => (/* binding */ exportToCanvas),\n/* harmony export */ \"exportToSvg\": () => (/* binding */ exportToSvg),\n/* harmony export */ \"getExportSize\": () => (/* binding */ getExportSize)\n/* harmony export */ });\n/* harmony import */ var roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! roughjs/bin/rough */ \"../../node_modules/roughjs/bin/rough.js\");\n/* harmony import */ var _element_bounds__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../element/bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _renderer_staticSvgScene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../renderer/staticSvgScene */ \"./renderer/staticSvgScene.ts\");\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils */ \"./utils.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../constants */ \"./constants.ts\");\n/* harmony import */ var _appState__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../appState */ \"./appState.ts\");\n/* harmony import */ var _data_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../data/json */ \"./data/json.ts\");\n/* harmony import */ var _element_image__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../element/image */ \"./element/image.ts\");\n/* harmony import */ var _frame__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../frame */ \"./frame.ts\");\n/* harmony import */ var _element__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../element */ \"./element/index.ts\");\n/* harmony import */ var _element_mutateElement__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../element/mutateElement */ \"./element/mutateElement.ts\");\n/* harmony import */ var _element_typeChecks__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../element/typeChecks */ \"./element/typeChecks.ts\");\n/* harmony import */ var _fractionalIndex__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../fractionalIndex */ \"./fractionalIndex.ts\");\n/* harmony import */ var _renderer_staticScene__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../renderer/staticScene */ \"./renderer/staticScene.ts\");\n/* harmony import */ var _fonts__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../fonts */ \"./fonts/index.ts\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;\n\nconst truncateText = (element, maxWidth) => {\n if (element.width <= maxWidth) {\n return element;\n }\n\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n ctx.font = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.getFontString)({\n fontFamily: element.fontFamily,\n fontSize: element.fontSize\n });\n let text = element.text;\n const metrics = ctx.measureText(text);\n\n if (metrics.width > maxWidth) {\n // we iterate from the right, removing characters one by one instead\n // of bulding the string up. This assumes that it's more likely\n // your frame names will overflow by not that many characters\n // (if ever), so it sohuld be faster this way.\n for (let i = text.length; i > 0; i--) {\n const newText = `${text.slice(0, i)}...`;\n\n if (ctx.measureText(newText).width <= maxWidth) {\n text = newText;\n break;\n }\n }\n }\n\n return (0,_element_mutateElement__WEBPACK_IMPORTED_MODULE_10__.newElementWith)(element, {\n text,\n width: maxWidth\n });\n};\n/**\n * When exporting frames, we need to render frame labels which are currently\n * being rendered in DOM when editing. Adding the labels as regular text\n * elements seems like a simple hack. In the future we'll want to move to\n * proper canvas rendering, even within editor (instead of DOM).\n */\n\n\nconst addFrameLabelsAsTextElements = (elements, opts) => {\n var _a, _b, _c;\n\n const nextElements = [];\n\n for (const element of elements) {\n if ((0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_11__.isFrameLikeElement)(element)) {\n let textElement = (0,_element__WEBPACK_IMPORTED_MODULE_9__.newTextElement)({\n x: element.x,\n y: element.y - _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameOffsetY,\n fontFamily: _constants__WEBPACK_IMPORTED_MODULE_4__.FONT_FAMILY.Helvetica,\n fontSize: _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameFontSize,\n lineHeight: _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameLineHeight,\n strokeColor: (_c = (_b = (_a = element.customData) === null || _a === void 0 ? void 0 : _a.frameColor) === null || _b === void 0 ? void 0 : _b.nameColor) !== null && _c !== void 0 ? _c : opts.exportWithDarkMode ? _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameColorDarkTheme : _constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.nameColorLightTheme,\n text: (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getFrameLikeTitle)(element),\n rawText: (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getFrameLikeTitle)(element) //zsviczian\n\n });\n textElement.y -= textElement.height;\n textElement = truncateText(textElement, element.width);\n nextElements.push(textElement);\n }\n\n nextElements.push(element);\n }\n\n return nextElements;\n};\n\nconst getFrameRenderingConfig = (exportingFrame, frameRendering) => {\n frameRendering = frameRendering || (0,_appState__WEBPACK_IMPORTED_MODULE_5__.getDefaultAppState)().frameRendering;\n return {\n enabled: exportingFrame ? true : frameRendering.enabled,\n outline: exportingFrame ? false : frameRendering.outline,\n name: exportingFrame ? false : frameRendering.name,\n clip: exportingFrame ? true : frameRendering.clip\n };\n};\n\nconst prepareElementsForRender = ({\n elements,\n exportingFrame,\n frameRendering,\n exportWithDarkMode\n}) => {\n let nextElements;\n\n if (exportingFrame) {\n nextElements = (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getElementsOverlappingFrame)(elements, exportingFrame);\n } else if (frameRendering.enabled && frameRendering.name) {\n nextElements = addFrameLabelsAsTextElements(elements, {\n exportWithDarkMode\n });\n } else {\n nextElements = elements;\n }\n\n return nextElements;\n};\n\nconst exportToCanvas = async (elements, appState, files, {\n exportBackground,\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n viewBackgroundColor,\n exportingFrame\n}, createCanvas = (width, height) => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width * appState.exportScale;\n canvas.height = height * appState.exportScale;\n return {\n canvas,\n scale: appState.exportScale\n };\n}, loadFonts = async () => {\n await _fonts__WEBPACK_IMPORTED_MODULE_14__.Fonts.loadElementsFonts(elements);\n}) => {\n var _a; // load font faces before continuing, by default leverages browsers' [FontFace API](https://developer.mozilla.org/en-US/docs/Web/API/FontFace)\n\n\n await loadFonts();\n const frameRendering = getFrameRenderingConfig(exportingFrame !== null && exportingFrame !== void 0 ? exportingFrame : null, (_a = appState.frameRendering) !== null && _a !== void 0 ? _a : null); // for canvas export, don't clip if exporting a specific frame as it would\n // clip the corners of the content\n\n if (exportingFrame) {\n frameRendering.clip = false;\n }\n\n const elementsForRender = prepareElementsForRender({\n elements,\n exportingFrame,\n exportWithDarkMode: appState.exportWithDarkMode,\n frameRendering\n });\n\n if (exportingFrame) {\n exportPadding = 0;\n }\n\n const [minX, minY, width, height] = getCanvasSize(exportingFrame ? [exportingFrame] : (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getRootElements)(elementsForRender), exportPadding);\n const {\n canvas,\n scale = 1\n } = createCanvas(width, height);\n const defaultAppState = (0,_appState__WEBPACK_IMPORTED_MODULE_5__.getDefaultAppState)();\n const {\n imageCache\n } = await (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.updateImageCache)({\n imageCache: new Map(),\n fileIds: (0,_element_image__WEBPACK_IMPORTED_MODULE_7__.getInitializedImageElements)(elementsForRender).map(element => element.fileId),\n files\n });\n (0,_renderer_staticScene__WEBPACK_IMPORTED_MODULE_13__.renderStaticScene)({\n canvas,\n rc: roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].canvas(canvas),\n elementsMap: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.toBrandedType)((0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)(elementsForRender)),\n allElementsMap: (0,_utils__WEBPACK_IMPORTED_MODULE_3__.toBrandedType)((0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)((0,_fractionalIndex__WEBPACK_IMPORTED_MODULE_12__.syncInvalidIndices)(elements))),\n visibleElements: elementsForRender,\n scale,\n appState: Object.assign(Object.assign({}, appState), {\n frameRendering,\n viewBackgroundColor: exportBackground ? viewBackgroundColor : null,\n scrollX: -minX + exportPadding,\n scrollY: -minY + exportPadding,\n zoom: defaultAppState.zoom,\n shouldCacheIgnoreZoom: false,\n theme: appState.exportWithDarkMode ? _constants__WEBPACK_IMPORTED_MODULE_4__.THEME.DARK : _constants__WEBPACK_IMPORTED_MODULE_4__.THEME.LIGHT\n }),\n renderConfig: {\n canvasBackgroundColor: viewBackgroundColor,\n imageCache,\n renderGrid: false,\n isExporting: true,\n // empty disables embeddable rendering\n embedsValidationStatus: new Map(),\n elementsPendingErasure: new Set(),\n pendingFlowchartNodes: null\n }\n });\n return canvas;\n};\nconst exportToSvg = async (elements, appState, files, opts) => {\n var _a, _b, _c, _d;\n\n const frameRendering = getFrameRenderingConfig((_a = opts === null || opts === void 0 ? void 0 : opts.exportingFrame) !== null && _a !== void 0 ? _a : null, (_b = appState.frameRendering) !== null && _b !== void 0 ? _b : null);\n let {\n exportPadding = _constants__WEBPACK_IMPORTED_MODULE_4__.DEFAULT_EXPORT_PADDING,\n exportWithDarkMode = false,\n viewBackgroundColor,\n exportScale = 1,\n exportEmbedScene\n } = appState;\n const {\n exportingFrame = null\n } = opts || {};\n const elementsForRender = prepareElementsForRender({\n elements,\n exportingFrame,\n exportWithDarkMode,\n frameRendering\n });\n\n if (exportingFrame) {\n exportPadding = 0;\n }\n\n let metadata = \"\"; // we need to serialize the \"original\" elements before we put them through\n // the tempScene hack which duplicates and regenerates ids\n\n if (exportEmbedScene) {\n try {\n metadata = (await Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ../data/image */ \"./data/image.ts\"))).encodeSvgMetadata({\n // when embedding scene, we want to embed the origionally supplied\n // elements which don't contain the temp frame labels.\n // But it also requires that the exportToSvg is being supplied with\n // only the elements that we're exporting, and no extra.\n text: (0,_data_json__WEBPACK_IMPORTED_MODULE_6__.serializeAsJSON)(elements, appState, files || {}, \"local\")\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n const [minX, minY, width, height] = getCanvasSize(exportingFrame ? [exportingFrame] : (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getRootElements)(elementsForRender), exportPadding); // initialize SVG root\n\n const svgRoot = document.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"svg\");\n svgRoot.setAttribute(\"version\", \"1.1\");\n svgRoot.setAttribute(\"xmlns\", _constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS);\n svgRoot.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svgRoot.setAttribute(\"width\", `${width * exportScale}`);\n svgRoot.setAttribute(\"height\", `${height * exportScale}`);\n\n if (exportWithDarkMode) {\n svgRoot.setAttribute(\"filter\", _constants__WEBPACK_IMPORTED_MODULE_4__.THEME_FILTER);\n }\n\n const offsetX = -minX + exportPadding;\n const offsetY = -minY + exportPadding;\n const frameElements = (0,_frame__WEBPACK_IMPORTED_MODULE_8__.getFrameLikeElements)(elements);\n let exportingFrameClipPath = \"\";\n const elementsMap = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)(elements);\n\n for (const frame of frameElements) {\n const [x1, y1, x2, y2] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getElementAbsoluteCoords)(frame, elementsMap);\n const cx = (x2 - x1) / 2 - (frame.x - x1);\n const cy = (y2 - y1) / 2 - (frame.y - y1);\n exportingFrameClipPath += `<clipPath id=${frame.id}>\n <rect transform=\"translate(${frame.x + offsetX} ${frame.y + offsetY}) rotate(${frame.angle} ${cx} ${cy})\"\n width=\"${frame.width}\"\n height=\"${frame.height}\"\n ${exportingFrame ? \"\" : `rx=${_constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.radius} ry=${_constants__WEBPACK_IMPORTED_MODULE_4__.FRAME_STYLE.radius}`}\n >\n </rect>\n </clipPath>`;\n }\n\n const fontFaces = !(opts === null || opts === void 0 ? void 0 : opts.skipInliningFonts) ? await _fonts__WEBPACK_IMPORTED_MODULE_14__.Fonts.generateFontFaceDeclarations(elements) : [];\n const delimiter = \"\\n \"; // 6 spaces\n\n svgRoot.innerHTML = `\n ${SVG_EXPORT_TAG}\n ${metadata}\n <defs>\n <style class=\"style-fonts\">${delimiter}${fontFaces.join(delimiter)}\n </style>\n ${exportingFrameClipPath}\n </defs>\n `; // render background rect\n\n if (appState.exportBackground && viewBackgroundColor) {\n const rect = svgRoot.ownerDocument.createElementNS(_constants__WEBPACK_IMPORTED_MODULE_4__.SVG_NS, \"rect\");\n rect.setAttribute(\"x\", \"0\");\n rect.setAttribute(\"y\", \"0\");\n rect.setAttribute(\"width\", `${width}`);\n rect.setAttribute(\"height\", `${height}`);\n rect.setAttribute(\"fill\", viewBackgroundColor);\n svgRoot.appendChild(rect);\n }\n\n const rsvg = roughjs_bin_rough__WEBPACK_IMPORTED_MODULE_0__[\"default\"].svg(svgRoot);\n const renderEmbeddables = (_c = opts === null || opts === void 0 ? void 0 : opts.renderEmbeddables) !== null && _c !== void 0 ? _c : false;\n (0,_renderer_staticSvgScene__WEBPACK_IMPORTED_MODULE_2__.renderSceneToSvg)(elementsForRender, (0,_utils__WEBPACK_IMPORTED_MODULE_3__.toBrandedType)((0,_utils__WEBPACK_IMPORTED_MODULE_3__.arrayToMap)(elementsForRender)), rsvg, svgRoot, files || {}, {\n offsetX,\n offsetY,\n isExporting: true,\n exportWithDarkMode,\n renderEmbeddables,\n frameRendering,\n frameColor: appState.frameColor,\n canvasBackgroundColor: viewBackgroundColor,\n embedsValidationStatus: renderEmbeddables ? new Map(elementsForRender.filter(element => (0,_element_typeChecks__WEBPACK_IMPORTED_MODULE_11__.isFrameLikeElement)(element)).map(element => [element.id, true])) : new Map(),\n reuseImages: (_d = opts === null || opts === void 0 ? void 0 : opts.reuseImages) !== null && _d !== void 0 ? _d : true\n });\n return svgRoot;\n}; // calculate smallest area to fit the contents in\n\nconst getCanvasSize = (elements, exportPadding) => {\n const [minX, minY, maxX, maxY] = (0,_element_bounds__WEBPACK_IMPORTED_MODULE_1__.getCommonBounds)(elements);\n const width = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minX, maxX) + exportPadding * 2;\n const height = (0,_utils__WEBPACK_IMPORTED_MODULE_3__.distance)(minY, maxY) + exportPadding * 2;\n return [minX, minY, width, height];\n};\n\nconst getExportSize = (elements, exportPadding, scale) => {\n const [,, width, height] = getCanvasSize(elements, exportPadding).map(dimension => Math.trunc(dimension * scale));\n return [width, height];\n};\n\n//# sourceURL=webpack://ExcalidrawLib/./scene/export.ts?");
3722
3733
 
3723
3734
  /***/ }),
3724
3735
 
@@ -3938,7 +3949,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
3938
3949
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3939
3950
 
3940
3951
  "use strict";
3941
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"PromisePool\": () => (/* binding */ PromisePool),\n/* harmony export */ \"addEventListener\": () => (/* binding */ addEventListener),\n/* harmony export */ \"allowFullScreen\": () => (/* binding */ allowFullScreen),\n/* harmony export */ \"arrayToList\": () => (/* binding */ arrayToList),\n/* harmony export */ \"arrayToMap\": () => (/* binding */ arrayToMap),\n/* harmony export */ \"arrayToMapWithIndex\": () => (/* binding */ arrayToMapWithIndex),\n/* harmony export */ \"arrayToObject\": () => (/* binding */ arrayToObject),\n/* harmony export */ \"assertNever\": () => (/* binding */ assertNever),\n/* harmony export */ \"bytesToHexString\": () => (/* binding */ bytesToHexString),\n/* harmony export */ \"capitalizeString\": () => (/* binding */ capitalizeString),\n/* harmony export */ \"chunk\": () => (/* binding */ chunk),\n/* harmony export */ \"cloneJSON\": () => (/* binding */ cloneJSON),\n/* harmony export */ \"composeEventHandlers\": () => (/* binding */ composeEventHandlers),\n/* harmony export */ \"debounce\": () => (/* binding */ debounce),\n/* harmony export */ \"distance\": () => (/* binding */ distance),\n/* harmony export */ \"easeOut\": () => (/* binding */ easeOut),\n/* harmony export */ \"easeToValuesRAF\": () => (/* binding */ easeToValuesRAF),\n/* harmony export */ \"exitFullScreen\": () => (/* binding */ exitFullScreen),\n/* harmony export */ \"findIndex\": () => (/* binding */ findIndex),\n/* harmony export */ \"findLastIndex\": () => (/* binding */ findLastIndex),\n/* harmony export */ \"focusNearestParent\": () => (/* binding */ focusNearestParent),\n/* harmony export */ \"getDateTime\": () => (/* binding */ getDateTime),\n/* harmony export */ \"getFontFamilyString\": () => (/* binding */ getFontFamilyString),\n/* harmony export */ \"getFontString\": () => (/* binding */ getFontString),\n/* harmony export */ \"getFrame\": () => (/* binding */ getFrame),\n/* harmony export */ \"getGlobalCSSVariable\": () => (/* binding */ getGlobalCSSVariable),\n/* harmony export */ \"getNearestScrollableContainer\": () => (/* binding */ getNearestScrollableContainer),\n/* harmony export */ \"getShortcutKey\": () => (/* binding */ getShortcutKey),\n/* harmony export */ \"getSvgPathFromStroke\": () => (/* binding */ getSvgPathFromStroke),\n/* harmony export */ \"getUpdatedTimestamp\": () => (/* binding */ getUpdatedTimestamp),\n/* harmony export */ \"getVersion\": () => (/* binding */ getVersion),\n/* harmony export */ \"invariant\": () => (/* binding */ invariant),\n/* harmony export */ \"isAnyTrue\": () => (/* binding */ isAnyTrue),\n/* harmony export */ \"isDevEnv\": () => (/* binding */ isDevEnv),\n/* harmony export */ \"isFullScreen\": () => (/* binding */ isFullScreen),\n/* harmony export */ \"isInputLike\": () => (/* binding */ isInputLike),\n/* harmony export */ \"isInteractive\": () => (/* binding */ isInteractive),\n/* harmony export */ \"isMemberOf\": () => (/* binding */ isMemberOf),\n/* harmony export */ \"isPrimitive\": () => (/* binding */ isPrimitive),\n/* harmony export */ \"isPromiseLike\": () => (/* binding */ isPromiseLike),\n/* harmony export */ \"isRTL\": () => (/* binding */ isRTL),\n/* harmony export */ \"isRunningInIframe\": () => (/* binding */ isRunningInIframe),\n/* harmony export */ \"isServerEnv\": () => (/* binding */ isServerEnv),\n/* harmony export */ \"isShallowEqual\": () => (/* binding */ isShallowEqual),\n/* harmony export */ \"isTestEnv\": () => (/* binding */ isTestEnv),\n/* harmony export */ \"isToolIcon\": () => (/* binding */ isToolIcon),\n/* harmony export */ \"isTransparent\": () => (/* binding */ isTransparent),\n/* harmony export */ \"isWritableElement\": () => (/* binding */ isWritableElement),\n/* harmony export */ \"memoize\": () => (/* binding */ memoize),\n/* harmony export */ \"muteFSAbortError\": () => (/* binding */ muteFSAbortError),\n/* harmony export */ \"nFormatter\": () => (/* binding */ nFormatter),\n/* harmony export */ \"normalizeEOL\": () => (/* binding */ normalizeEOL),\n/* harmony export */ \"preventUnload\": () => (/* binding */ preventUnload),\n/* harmony export */ \"promiseTry\": () => (/* binding */ promiseTry),\n/* harmony export */ \"queryFocusableElements\": () => (/* binding */ queryFocusableElements),\n/* harmony export */ \"removeSelection\": () => (/* binding */ removeSelection),\n/* harmony export */ \"resolvablePromise\": () => (/* binding */ resolvablePromise),\n/* harmony export */ \"safelyParseJSON\": () => (/* binding */ safelyParseJSON),\n/* harmony export */ \"sceneCoordsToViewportCoords\": () => (/* binding */ sceneCoordsToViewportCoords),\n/* harmony export */ \"selectNode\": () => (/* binding */ selectNode),\n/* harmony export */ \"setDateTimeForTests\": () => (/* binding */ setDateTimeForTests),\n/* harmony export */ \"supportsEmoji\": () => (/* binding */ supportsEmoji),\n/* harmony export */ \"throttleRAF\": () => (/* binding */ throttleRAF),\n/* harmony export */ \"toBrandedType\": () => (/* binding */ toBrandedType),\n/* harmony export */ \"tupleToCoors\": () => (/* binding */ tupleToCoors),\n/* harmony export */ \"updateActiveTool\": () => (/* binding */ updateActiveTool),\n/* harmony export */ \"updateObject\": () => (/* binding */ updateObject),\n/* harmony export */ \"updateStable\": () => (/* binding */ updateStable),\n/* harmony export */ \"viewportCoordsToSceneCoords\": () => (/* binding */ viewportCoordsToSceneCoords),\n/* harmony export */ \"wrapEvent\": () => (/* binding */ wrapEvent)\n/* harmony export */ });\n/* harmony import */ var es6_promise_pool__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! es6-promise-pool */ \"../../node_modules/es6-promise-pool/es6-promise-pool.js\");\n/* harmony import */ var es6_promise_pool__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(es6_promise_pool__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../math */ \"../math/index.ts\");\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./colors */ \"./colors.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./constants */ \"./constants.ts\");\n\n\n\n\nlet mockDateTime = null;\nconst setDateTimeForTests = dateTime => {\n mockDateTime = dateTime;\n};\nconst getDateTime = () => {\n if (mockDateTime) {\n return mockDateTime;\n }\n\n const date = new Date();\n const year = date.getFullYear();\n const month = `${date.getMonth() + 1}`.padStart(2, \"0\");\n const day = `${date.getDate()}`.padStart(2, \"0\");\n const hr = `${date.getHours()}`.padStart(2, \"0\");\n const min = `${date.getMinutes()}`.padStart(2, \"0\");\n return `${year}-${month}-${day}-${hr}${min}`;\n};\nconst capitalizeString = str => str.charAt(0).toUpperCase() + str.slice(1);\nconst isToolIcon = target => target instanceof HTMLElement && target.className.includes(\"ToolIcon\");\nconst isInputLike = target => target instanceof HTMLElement && target.dataset.type === \"wysiwyg\" || target instanceof HTMLBRElement || // newline in wysiwyg\ntarget instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement;\nconst isInteractive = target => {\n return isInputLike(target) || target instanceof Element && !!target.closest(\"label, button\");\n};\nconst isWritableElement = target => target instanceof HTMLElement && target.dataset.type === \"wysiwyg\" || target instanceof HTMLBRElement || // newline in wysiwyg\ntarget instanceof HTMLTextAreaElement || target instanceof HTMLInputElement && (target.type === \"text\" || target.type === \"number\" || target.type === \"password\");\nconst getFontFamilyString = ({\n fontFamily\n}) => {\n for (const [fontFamilyString, id] of Object.entries(_constants__WEBPACK_IMPORTED_MODULE_3__.FONT_FAMILY)) {\n if (id === fontFamily) {\n // TODO: we should fallback first to generic family names first\n return `${fontFamilyString}${(0,_constants__WEBPACK_IMPORTED_MODULE_3__.getFontFamilyFallbacks)(id).map(x => `, ${x}`).join(\"\")}`;\n }\n }\n\n return _constants__WEBPACK_IMPORTED_MODULE_3__.WINDOWS_EMOJI_FALLBACK_FONT;\n};\n/** returns fontSize+fontFamily string for assignment to DOM elements */\n\nconst getFontString = ({\n fontSize,\n fontFamily\n}) => {\n return `${fontSize}px ${getFontFamilyString({\n fontFamily\n })}`;\n};\nconst debounce = (fn, timeout) => {\n let handle = 0;\n let lastArgs = null;\n\n const ret = (...args) => {\n lastArgs = args;\n clearTimeout(handle);\n handle = window.setTimeout(() => {\n lastArgs = null;\n fn(...args);\n }, timeout);\n };\n\n ret.flush = () => {\n clearTimeout(handle);\n\n if (lastArgs) {\n const _lastArgs = lastArgs;\n lastArgs = null;\n fn(..._lastArgs);\n }\n };\n\n ret.cancel = () => {\n lastArgs = null;\n clearTimeout(handle);\n };\n\n return ret;\n}; // throttle callback to execute once per animation frame\n\nconst throttleRAF = (fn, opts) => {\n let timerId = null;\n let lastArgs = null;\n let lastArgsTrailing = null;\n\n const scheduleFunc = args => {\n timerId = window.requestAnimationFrame(() => {\n timerId = null;\n fn(...args);\n lastArgs = null;\n\n if (lastArgsTrailing) {\n lastArgs = lastArgsTrailing;\n lastArgsTrailing = null;\n scheduleFunc(lastArgs);\n }\n });\n };\n\n const ret = (...args) => {\n if (false) {}\n\n lastArgs = args;\n\n if (timerId === null) {\n scheduleFunc(lastArgs);\n } else if (opts === null || opts === void 0 ? void 0 : opts.trailing) {\n lastArgsTrailing = args;\n }\n };\n\n ret.flush = () => {\n if (timerId !== null) {\n cancelAnimationFrame(timerId);\n timerId = null;\n }\n\n if (lastArgs) {\n fn(...(lastArgsTrailing || lastArgs));\n lastArgs = lastArgsTrailing = null;\n }\n };\n\n ret.cancel = () => {\n lastArgs = lastArgsTrailing = null;\n\n if (timerId !== null) {\n cancelAnimationFrame(timerId);\n timerId = null;\n }\n };\n\n return ret;\n};\n/**\n * Exponential ease-out method\n *\n * @param {number} k - The value to be tweened.\n * @returns {number} The tweened value.\n */\n\nconst easeOut = k => {\n return 1 - Math.pow(1 - k, 4);\n};\n\nconst easeOutInterpolate = (from, to, progress) => {\n return (to - from) * easeOut(progress) + from;\n};\n/**\n * Animates values from `fromValues` to `toValues` using the requestAnimationFrame API.\n * Executes the `onStep` callback on each step with the interpolated values.\n * Returns a function that can be called to cancel the animation.\n *\n * @example\n * // Example usage:\n * const fromValues = { x: 0, y: 0 };\n * const toValues = { x: 100, y: 200 };\n * const onStep = ({x, y}) => {\n * setState(x, y)\n * };\n * const onCancel = () => {\n * console.log(\"Animation canceled\");\n * };\n *\n * const cancelAnimation = easeToValuesRAF({\n * fromValues,\n * toValues,\n * onStep,\n * onCancel,\n * });\n *\n * // To cancel the animation:\n * cancelAnimation();\n */\n\n\nconst easeToValuesRAF = ({\n fromValues,\n toValues,\n onStep,\n duration = 250,\n interpolateValue,\n onStart,\n onEnd,\n onCancel\n}) => {\n let canceled = false;\n let frameId = 0;\n let startTime;\n\n function step(timestamp) {\n if (canceled) {\n return;\n }\n\n if (startTime === undefined) {\n startTime = timestamp;\n onStart === null || onStart === void 0 ? void 0 : onStart();\n }\n\n const elapsed = Math.min(timestamp - startTime, duration);\n const factor = easeOut(elapsed / duration);\n const newValues = {};\n Object.keys(fromValues).forEach(key => {\n const _key = key;\n const result = (toValues[_key] - fromValues[_key]) * factor + fromValues[_key];\n newValues[_key] = result;\n });\n onStep(newValues);\n\n if (elapsed < duration) {\n const progress = elapsed / duration;\n const newValues = {};\n Object.keys(fromValues).forEach(key => {\n const _key = key;\n const startValue = fromValues[_key];\n const endValue = toValues[_key];\n let result;\n result = interpolateValue ? interpolateValue(startValue, endValue, progress, _key) : easeOutInterpolate(startValue, endValue, progress);\n\n if (result == null) {\n result = easeOutInterpolate(startValue, endValue, progress);\n }\n\n newValues[_key] = result;\n });\n onStep(newValues);\n frameId = window.requestAnimationFrame(step);\n } else {\n onStep(toValues);\n onEnd === null || onEnd === void 0 ? void 0 : onEnd();\n }\n }\n\n frameId = window.requestAnimationFrame(step);\n return () => {\n onCancel === null || onCancel === void 0 ? void 0 : onCancel();\n canceled = true;\n window.cancelAnimationFrame(frameId);\n };\n}; // https://github.com/lodash/lodash/blob/es/chunk.js\n\nconst chunk = (array, size) => {\n if (!array.length || size < 1) {\n return [];\n }\n\n let index = 0;\n let resIndex = 0;\n const result = Array(Math.ceil(array.length / size));\n\n while (index < array.length) {\n result[resIndex++] = array.slice(index, index += size);\n }\n\n return result;\n};\nconst selectNode = node => {\n const selection = window.getSelection();\n\n if (selection) {\n const range = document.createRange();\n range.selectNodeContents(node);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n};\nconst removeSelection = () => {\n const selection = window.getSelection();\n\n if (selection) {\n selection.removeAllRanges();\n }\n};\nconst distance = (x, y) => Math.abs(x - y);\nconst updateActiveTool = (appState, data) => {\n var _a, _b;\n\n if (data.type === \"custom\") {\n return Object.assign(Object.assign({}, appState.activeTool), {\n type: \"custom\",\n customType: data.customType,\n locked: (_a = data.locked) !== null && _a !== void 0 ? _a : appState.activeTool.locked\n });\n }\n\n return Object.assign(Object.assign({}, appState.activeTool), {\n lastActiveTool: data.lastActiveToolBeforeEraser === undefined ? appState.activeTool.lastActiveTool : data.lastActiveToolBeforeEraser,\n type: data.type,\n customType: null,\n locked: (_b = data.locked) !== null && _b !== void 0 ? _b : appState.activeTool.locked\n });\n};\nconst isFullScreen = () => {\n var _a;\n\n return ((_a = document.fullscreenElement) === null || _a === void 0 ? void 0 : _a.nodeName) === \"HTML\";\n};\nconst allowFullScreen = () => document.documentElement.requestFullscreen();\nconst exitFullScreen = () => document.exitFullscreen();\nconst getShortcutKey = shortcut => {\n shortcut = shortcut.replace(/\\bAlt\\b/i, \"Alt\").replace(/\\bShift\\b/i, \"Shift\").replace(/\\b(Enter|Return)\\b/i, \"Enter\");\n\n if (_constants__WEBPACK_IMPORTED_MODULE_3__.isDarwin) {\n return shortcut.replace(/\\bCtrlOrCmd\\b/gi, \"Cmd\").replace(/\\bAlt\\b/i, \"Option\");\n }\n\n return shortcut.replace(/\\bCtrlOrCmd\\b/gi, \"Ctrl\");\n};\nconst viewportCoordsToSceneCoords = ({\n clientX,\n clientY\n}, {\n zoom,\n offsetLeft,\n offsetTop,\n scrollX,\n scrollY\n}) => {\n const x = (clientX - offsetLeft) / zoom.value - scrollX;\n const y = (clientY - offsetTop) / zoom.value - scrollY;\n return {\n x,\n y\n };\n};\nconst sceneCoordsToViewportCoords = ({\n sceneX,\n sceneY\n}, {\n zoom,\n offsetLeft,\n offsetTop,\n scrollX,\n scrollY\n}) => {\n const x = (sceneX + scrollX) * zoom.value + offsetLeft;\n const y = (sceneY + scrollY) * zoom.value + offsetTop;\n return {\n x,\n y\n };\n};\nconst getGlobalCSSVariable = name => getComputedStyle(document.documentElement).getPropertyValue(`--${name}`);\nconst RS_LTR_CHARS = \"A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02B8\\u0300-\\u0590\\u0800-\\u1FFF\" + \"\\u2C00-\\uFB1C\\uFDFE-\\uFE6F\\uFEFD-\\uFFFF\";\nconst RS_RTL_CHARS = \"\\u0591-\\u07FF\\uFB1D-\\uFDFD\\uFE70-\\uFEFC\";\nconst RE_RTL_CHECK = new RegExp(`^[^${RS_LTR_CHARS}]*[${RS_RTL_CHARS}]`);\n/**\n * Checks whether first directional character is RTL. Meaning whether it starts\n * with RTL characters, or indeterminate (numbers etc.) characters followed by\n * RTL.\n * See https://github.com/excalidraw/excalidraw/pull/1722#discussion_r436340171\n */\n\nconst isRTL = text => RE_RTL_CHECK.test(text);\nconst tupleToCoors = xyTuple => {\n const [x, y] = xyTuple;\n return {\n x,\n y\n };\n};\n/** use as a rejectionHandler to mute filesystem Abort errors */\n\nconst muteFSAbortError = error => {\n if ((error === null || error === void 0 ? void 0 : error.name) === \"AbortError\") {\n console.warn(error);\n return;\n }\n\n throw error;\n};\nconst findIndex = (array, cb, fromIndex = 0) => {\n if (fromIndex < 0) {\n fromIndex = array.length + fromIndex;\n }\n\n fromIndex = Math.min(array.length, Math.max(fromIndex, 0));\n let index = fromIndex - 1;\n\n while (++index < array.length) {\n if (cb(array[index], index, array)) {\n return index;\n }\n }\n\n return -1;\n};\nconst findLastIndex = (array, cb, fromIndex = array.length - 1) => {\n if (fromIndex < 0) {\n fromIndex = array.length + fromIndex;\n }\n\n fromIndex = Math.min(array.length - 1, Math.max(fromIndex, 0));\n let index = fromIndex + 1;\n\n while (--index > -1) {\n if (cb(array[index], index, array)) {\n return index;\n }\n }\n\n return -1;\n};\nconst isTransparent = color => {\n const isRGBTransparent = color.length === 5 && color.substr(4, 1) === \"0\";\n const isRRGGBBTransparent = color.length === 9 && color.substr(7, 2) === \"00\";\n return isRGBTransparent || isRRGGBBTransparent || color === _colors__WEBPACK_IMPORTED_MODULE_2__.COLOR_PALETTE.transparent;\n};\nconst resolvablePromise = () => {\n let resolve;\n let reject;\n const promise = new Promise((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n promise.resolve = resolve;\n promise.reject = reject;\n return promise;\n}; //https://stackoverflow.com/a/9462382/8418\n\nconst nFormatter = (num, digits) => {\n const si = [{\n value: 1,\n symbol: \"b\"\n }, {\n value: 1e3,\n symbol: \"k\"\n }, {\n value: 1e6,\n symbol: \"M\"\n }, {\n value: 1e9,\n symbol: \"G\"\n }];\n const rx = /\\.0+$|(\\.[0-9]*[1-9])0+$/;\n let index;\n\n for (index = si.length - 1; index > 0; index--) {\n if (num >= si[index].value) {\n break;\n }\n }\n\n return (num / si[index].value).toFixed(digits).replace(rx, \"$1\") + si[index].symbol;\n};\nconst getVersion = () => {\n var _a;\n\n return ((_a = document.querySelector('meta[name=\"version\"]')) === null || _a === void 0 ? void 0 : _a.content) || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_VERSION;\n}; // Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/emoji.js\n\nconst supportsEmoji = () => {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n\n if (!ctx) {\n return false;\n }\n\n const offset = 12;\n ctx.fillStyle = \"#f00\";\n ctx.textBaseline = \"top\";\n ctx.font = \"32px Arial\"; // Modernizr used 🐨, but it is sort of supported on Windows 7.\n // Luckily 😀 isn't supported.\n\n ctx.fillText(\"😀\", 0, 0);\n return ctx.getImageData(offset, offset, 1, 1).data[0] !== 0;\n};\nconst getNearestScrollableContainer = element => {\n let parent = element.parentElement;\n\n while (parent) {\n if (parent === document.body) {\n return document;\n }\n\n const {\n overflowY\n } = window.getComputedStyle(parent);\n const hasScrollableContent = parent.scrollHeight > parent.clientHeight;\n\n if (hasScrollableContent && (overflowY === \"auto\" || overflowY === \"scroll\" || overflowY === \"overlay\")) {\n return parent;\n }\n\n parent = parent.parentElement;\n }\n\n return document;\n};\nconst focusNearestParent = element => {\n let parent = element.parentElement;\n\n while (parent) {\n if (parent.tabIndex > -1) {\n parent.focus();\n return;\n }\n\n parent = parent.parentElement;\n }\n};\nconst preventUnload = event => {\n event.preventDefault(); // NOTE: modern browsers no longer allow showing a custom message here\n\n event.returnValue = \"\";\n};\nconst bytesToHexString = bytes => {\n return Array.from(bytes).map(byte => `0${byte.toString(16)}`.slice(-2)).join(\"\");\n};\nconst getUpdatedTimestamp = () => isTestEnv() ? 1 : Date.now();\n/**\n * Transforms array of objects containing `id` attribute,\n * or array of ids (strings), into a Map, keyd by `id`.\n */\n\nconst arrayToMap = items => {\n if (items instanceof Map) {\n return items;\n }\n\n return items.reduce((acc, element) => {\n acc.set(typeof element === \"string\" ? element : element.id, element);\n return acc;\n }, new Map());\n};\nconst arrayToMapWithIndex = elements => elements.reduce((acc, element, idx) => {\n acc.set(element.id, [element, idx]);\n return acc;\n}, new Map());\n/**\n * Transform array into an object, use only when array order is irrelevant.\n */\n\nconst arrayToObject = (array, groupBy) => array.reduce((acc, value) => {\n acc[groupBy ? groupBy(value) : String(value)] = value;\n return acc;\n}, {});\n/**\n * Creates a circular doubly linked list by adding `prev` and `next` props to the existing array nodes.\n */\n\nconst arrayToList = array => array.reduce((acc, curr, index) => {\n const node = Object.assign(Object.assign({}, curr), {\n prev: null,\n next: null\n }); // no-op for first item, we don't want circular references on a single item\n\n if (index !== 0) {\n const prevNode = acc[index - 1];\n node.prev = prevNode;\n prevNode.next = node;\n\n if (index === array.length - 1) {\n // make the references circular and connect head & tail\n const firstNode = acc[0];\n node.next = firstNode;\n firstNode.prev = node;\n }\n }\n\n acc.push(node);\n return acc;\n}, []);\nconst isTestEnv = () => \"development\" === \"test\";\nconst isDevEnv = () => \"development\" === \"development\";\nconst isServerEnv = () => {\n var _a;\n\n return typeof process !== \"undefined\" && !!((_a = process === null || process === void 0 ? void 0 : ({\"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_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_ENABLE_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.6-8\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true})) === null || _a === void 0 ? void 0 : _a.NODE_ENV);\n};\nconst wrapEvent = (name, nativeEvent) => {\n return new CustomEvent(name, {\n detail: {\n nativeEvent\n },\n cancelable: true\n });\n};\nconst updateObject = (obj, updates) => {\n let didChange = false;\n\n for (const key in updates) {\n const value = updates[key];\n\n if (typeof value !== \"undefined\") {\n if (obj[key] === value && ( // if object, always update because its attrs could have changed\n typeof value !== \"object\" || value === null)) {\n continue;\n }\n\n didChange = true;\n }\n }\n\n if (!didChange) {\n return obj;\n }\n\n return Object.assign(Object.assign({}, obj), updates);\n};\nconst isPrimitive = val => {\n const type = typeof val;\n return val == null || type !== \"object\" && type !== \"function\";\n};\nconst getFrame = () => {\n try {\n return window.self === window.top ? \"top\" : \"iframe\";\n } catch (error) {\n return \"iframe\";\n }\n};\nconst isRunningInIframe = () => getFrame() === \"iframe\";\nconst isPromiseLike = value => {\n return !!value && typeof value === \"object\" && \"then\" in value && \"catch\" in value && \"finally\" in value;\n};\nconst queryFocusableElements = container => {\n const focusableElements = container === null || container === void 0 ? void 0 : container.querySelectorAll(\"button, a, input, select, textarea, div[tabindex], label[tabindex]\");\n return focusableElements ? Array.from(focusableElements).filter(element => element.tabIndex > -1 && !element.disabled) : [];\n};\n/** use as a fallback after identity check (for perf reasons) */\n\nconst _defaultIsShallowComparatorFallback = (a, b) => {\n // consider two empty arrays equal\n if (Array.isArray(a) && Array.isArray(b) && a.length === 0 && b.length === 0) {\n return true;\n }\n\n return a === b;\n};\n/**\n * Returns whether object/array is shallow equal.\n * Considers empty object/arrays as equal (whether top-level or second-level).\n */\n\n\nconst isShallowEqual = (objA, objB, comparators, debug = false) => {\n const aKeys = Object.keys(objA);\n const bKeys = Object.keys(objB);\n\n if (aKeys.length !== bKeys.length) {\n if (debug) {\n console.warn(`%cisShallowEqual: objects don't have same properties ->`, \"color: #8B4000\", objA, objB);\n }\n\n return false;\n }\n\n if (comparators && Array.isArray(comparators)) {\n for (const key of comparators) {\n const ret = objA[key] === objB[key] || _defaultIsShallowComparatorFallback(objA[key], objB[key]);\n\n if (!ret) {\n if (debug) {\n console.warn(`%cisShallowEqual: ${key} not equal ->`, \"color: #8B4000\", objA[key], objB[key]);\n }\n\n return false;\n }\n }\n\n return true;\n }\n\n return aKeys.every(key => {\n const comparator = comparators === null || comparators === void 0 ? void 0 : comparators[key];\n const ret = comparator ? comparator(objA[key], objB[key]) : objA[key] === objB[key] || _defaultIsShallowComparatorFallback(objA[key], objB[key]);\n\n if (!ret && debug) {\n console.warn(`%cisShallowEqual: ${key} not equal ->`, \"color: #8B4000\", objA[key], objB[key]);\n }\n\n return ret;\n });\n}; // taken from Radix UI\n// https://github.com/radix-ui/primitives/blob/main/packages/core/primitive/src/primitive.tsx\n\nconst composeEventHandlers = (originalEventHandler, ourEventHandler, {\n checkForDefaultPrevented = true\n} = {}) => {\n return function handleEvent(event) {\n originalEventHandler === null || originalEventHandler === void 0 ? void 0 : originalEventHandler(event);\n\n if (!checkForDefaultPrevented || !(event === null || event === void 0 ? void 0 : event.defaultPrevented)) {\n return ourEventHandler === null || ourEventHandler === void 0 ? void 0 : ourEventHandler(event);\n }\n };\n};\n/**\n * supply `null` as message if non-never value is valid, you just need to\n * typecheck against it\n */\n\nconst assertNever = (value, message, softAssert) => {\n if (!message) {\n return value;\n }\n\n if (softAssert) {\n console.error(message);\n return value;\n }\n\n throw new Error(message);\n};\nfunction invariant(condition, message) {\n if (!condition) {\n throw new Error(message);\n }\n}\n/**\n * Memoizes on values of `opts` object (strict equality).\n */\n\nconst memoize = func => {\n let lastArgs;\n let lastResult;\n\n const ret = function (opts) {\n const currentArgs = Object.entries(opts);\n\n if (lastArgs) {\n let argsAreEqual = true;\n\n for (const [key, value] of currentArgs) {\n if (lastArgs.get(key) !== value) {\n argsAreEqual = false;\n break;\n }\n }\n\n if (argsAreEqual) {\n return lastResult;\n }\n }\n\n const result = func(opts);\n lastArgs = new Map(currentArgs);\n lastResult = result;\n return result;\n };\n\n ret.clear = () => {\n lastArgs = undefined;\n lastResult = undefined;\n };\n\n return ret;\n};\n/** Checks if value is inside given collection. Useful for type-safety. */\n\nconst isMemberOf = (\n/** Set/Map/Array/Object */\ncollection,\n/** value to look for */\nvalue) => {\n return collection instanceof Set || collection instanceof Map ? collection.has(value) : \"includes\" in collection ? collection.includes(value) : collection.hasOwnProperty(value);\n};\nconst cloneJSON = obj => JSON.parse(JSON.stringify(obj));\nconst updateStable = (prevValue, nextValue) => {\n if (isShallowEqual(prevValue, nextValue)) {\n return prevValue;\n }\n\n return nextValue;\n}; // implem\n\nfunction addEventListener(\n/**\n * allows for falsy values so you don't have to type check when adding\n * event listeners to optional elements\n */\ntarget, type, listener, options) {\n var _a;\n\n if (!target) {\n return () => {};\n }\n\n (_a = target === null || target === void 0 ? void 0 : target.addEventListener) === null || _a === void 0 ? void 0 : _a.call(target, type, listener, options);\n return () => {\n var _a;\n\n (_a = target === null || target === void 0 ? void 0 : target.removeEventListener) === null || _a === void 0 ? void 0 : _a.call(target, type, listener, options);\n };\n}\nfunction getSvgPathFromStroke(points, closed = true) {\n const len = points.length;\n\n if (len < 4) {\n return ``;\n }\n\n let a = points[0];\n let b = points[1];\n const c = points[2];\n let result = `M${a[0].toFixed(2)},${a[1].toFixed(2)} Q${b[0].toFixed(2)},${b[1].toFixed(2)} ${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(b[0], c[0]).toFixed(2)},${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(b[1], c[1]).toFixed(2)} T`;\n\n for (let i = 2, max = len - 1; i < max; i++) {\n a = points[i];\n b = points[i + 1];\n result += `${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(a[0], b[0]).toFixed(2)},${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(a[1], b[1]).toFixed(2)} `;\n }\n\n if (closed) {\n result += \"Z\";\n }\n\n return result;\n}\nconst normalizeEOL = str => {\n return str.replace(/\\r?\\n|\\r/g, \"\\n\");\n};\n/**\n * Makes type into a branded type, ensuring that value is assignable to\n * the base ubranded type. Optionally you can explicitly supply current value\n * type to combine both (useful for composite branded types. Make sure you\n * compose branded types which are not composite themselves.)\n */\n\nconst toBrandedType = value => {\n return value;\n}; // -----------------------------------------------------------------------------\n// Promise.try, adapted from https://github.com/sindresorhus/p-try\n\nconst promiseTry = async (fn, ...args) => {\n return new Promise(resolve => {\n resolve(fn(...args));\n });\n};\nconst isAnyTrue = (...args) => Math.max(...args.map(arg => arg ? 1 : 0)) > 0;\nconst safelyParseJSON = json => {\n try {\n return JSON.parse(json);\n } catch (_a) {\n return null;\n }\n};\nclass PromisePool {\n constructor(source, concurrency) {\n this.entries = {};\n this.pool = new (es6_promise_pool__WEBPACK_IMPORTED_MODULE_0___default())(source, concurrency);\n }\n\n all() {\n const listener = event => {\n if (event.data.result) {\n // by default pool does not return the results, so we are gathering them manually\n // with the correct call order (represented by the index in the tuple)\n const [index, value] = event.data.result;\n this.entries[index] = value;\n }\n };\n\n this.pool.addEventListener(\"fulfilled\", listener);\n return this.pool.start().then(() => {\n setTimeout(() => {\n this.pool.removeEventListener(\"fulfilled\", listener);\n });\n return Object.values(this.entries);\n });\n }\n\n}\n\n//# sourceURL=webpack://ExcalidrawLib/./utils.ts?");
3952
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"PromisePool\": () => (/* binding */ PromisePool),\n/* harmony export */ \"addEventListener\": () => (/* binding */ addEventListener),\n/* harmony export */ \"allowFullScreen\": () => (/* binding */ allowFullScreen),\n/* harmony export */ \"arrayToList\": () => (/* binding */ arrayToList),\n/* harmony export */ \"arrayToMap\": () => (/* binding */ arrayToMap),\n/* harmony export */ \"arrayToMapWithIndex\": () => (/* binding */ arrayToMapWithIndex),\n/* harmony export */ \"arrayToObject\": () => (/* binding */ arrayToObject),\n/* harmony export */ \"assertNever\": () => (/* binding */ assertNever),\n/* harmony export */ \"bytesToHexString\": () => (/* binding */ bytesToHexString),\n/* harmony export */ \"capitalizeString\": () => (/* binding */ capitalizeString),\n/* harmony export */ \"chunk\": () => (/* binding */ chunk),\n/* harmony export */ \"cloneJSON\": () => (/* binding */ cloneJSON),\n/* harmony export */ \"composeEventHandlers\": () => (/* binding */ composeEventHandlers),\n/* harmony export */ \"debounce\": () => (/* binding */ debounce),\n/* harmony export */ \"distance\": () => (/* binding */ distance),\n/* harmony export */ \"easeOut\": () => (/* binding */ easeOut),\n/* harmony export */ \"easeToValuesRAF\": () => (/* binding */ easeToValuesRAF),\n/* harmony export */ \"exitFullScreen\": () => (/* binding */ exitFullScreen),\n/* harmony export */ \"findIndex\": () => (/* binding */ findIndex),\n/* harmony export */ \"findLastIndex\": () => (/* binding */ findLastIndex),\n/* harmony export */ \"focusNearestParent\": () => (/* binding */ focusNearestParent),\n/* harmony export */ \"getDateTime\": () => (/* binding */ getDateTime),\n/* harmony export */ \"getFontFamilyString\": () => (/* binding */ getFontFamilyString),\n/* harmony export */ \"getFontString\": () => (/* binding */ getFontString),\n/* harmony export */ \"getFrame\": () => (/* binding */ getFrame),\n/* harmony export */ \"getGlobalCSSVariable\": () => (/* binding */ getGlobalCSSVariable),\n/* harmony export */ \"getNearestScrollableContainer\": () => (/* binding */ getNearestScrollableContainer),\n/* harmony export */ \"getShortcutKey\": () => (/* binding */ getShortcutKey),\n/* harmony export */ \"getSvgPathFromStroke\": () => (/* binding */ getSvgPathFromStroke),\n/* harmony export */ \"getUpdatedTimestamp\": () => (/* binding */ getUpdatedTimestamp),\n/* harmony export */ \"getVersion\": () => (/* binding */ getVersion),\n/* harmony export */ \"invariant\": () => (/* binding */ invariant),\n/* harmony export */ \"isAnyTrue\": () => (/* binding */ isAnyTrue),\n/* harmony export */ \"isDevEnv\": () => (/* binding */ isDevEnv),\n/* harmony export */ \"isFullScreen\": () => (/* binding */ isFullScreen),\n/* harmony export */ \"isInputLike\": () => (/* binding */ isInputLike),\n/* harmony export */ \"isInteractive\": () => (/* binding */ isInteractive),\n/* harmony export */ \"isMemberOf\": () => (/* binding */ isMemberOf),\n/* harmony export */ \"isPrimitive\": () => (/* binding */ isPrimitive),\n/* harmony export */ \"isPromiseLike\": () => (/* binding */ isPromiseLike),\n/* harmony export */ \"isRTL\": () => (/* binding */ isRTL),\n/* harmony export */ \"isRunningInIframe\": () => (/* binding */ isRunningInIframe),\n/* harmony export */ \"isServerEnv\": () => (/* binding */ isServerEnv),\n/* harmony export */ \"isShallowEqual\": () => (/* binding */ isShallowEqual),\n/* harmony export */ \"isTestEnv\": () => (/* binding */ isTestEnv),\n/* harmony export */ \"isToolIcon\": () => (/* binding */ isToolIcon),\n/* harmony export */ \"isTransparent\": () => (/* binding */ isTransparent),\n/* harmony export */ \"isWritableElement\": () => (/* binding */ isWritableElement),\n/* harmony export */ \"memoize\": () => (/* binding */ memoize),\n/* harmony export */ \"muteFSAbortError\": () => (/* binding */ muteFSAbortError),\n/* harmony export */ \"nFormatter\": () => (/* binding */ nFormatter),\n/* harmony export */ \"normalizeEOL\": () => (/* binding */ normalizeEOL),\n/* harmony export */ \"preventUnload\": () => (/* binding */ preventUnload),\n/* harmony export */ \"promiseTry\": () => (/* binding */ promiseTry),\n/* harmony export */ \"queryFocusableElements\": () => (/* binding */ queryFocusableElements),\n/* harmony export */ \"removeSelection\": () => (/* binding */ removeSelection),\n/* harmony export */ \"resolvablePromise\": () => (/* binding */ resolvablePromise),\n/* harmony export */ \"safelyParseJSON\": () => (/* binding */ safelyParseJSON),\n/* harmony export */ \"sceneCoordsToViewportCoords\": () => (/* binding */ sceneCoordsToViewportCoords),\n/* harmony export */ \"selectNode\": () => (/* binding */ selectNode),\n/* harmony export */ \"setDateTimeForTests\": () => (/* binding */ setDateTimeForTests),\n/* harmony export */ \"supportsEmoji\": () => (/* binding */ supportsEmoji),\n/* harmony export */ \"throttleRAF\": () => (/* binding */ throttleRAF),\n/* harmony export */ \"toBrandedType\": () => (/* binding */ toBrandedType),\n/* harmony export */ \"tupleToCoors\": () => (/* binding */ tupleToCoors),\n/* harmony export */ \"updateActiveTool\": () => (/* binding */ updateActiveTool),\n/* harmony export */ \"updateObject\": () => (/* binding */ updateObject),\n/* harmony export */ \"updateStable\": () => (/* binding */ updateStable),\n/* harmony export */ \"viewportCoordsToSceneCoords\": () => (/* binding */ viewportCoordsToSceneCoords),\n/* harmony export */ \"wrapEvent\": () => (/* binding */ wrapEvent)\n/* harmony export */ });\n/* harmony import */ var es6_promise_pool__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! es6-promise-pool */ \"../../node_modules/es6-promise-pool/es6-promise-pool.js\");\n/* harmony import */ var es6_promise_pool__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(es6_promise_pool__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../math */ \"../math/index.ts\");\n/* harmony import */ var _colors__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./colors */ \"./colors.ts\");\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./constants */ \"./constants.ts\");\n\n\n\n\nlet mockDateTime = null;\nconst setDateTimeForTests = dateTime => {\n mockDateTime = dateTime;\n};\nconst getDateTime = () => {\n if (mockDateTime) {\n return mockDateTime;\n }\n\n const date = new Date();\n const year = date.getFullYear();\n const month = `${date.getMonth() + 1}`.padStart(2, \"0\");\n const day = `${date.getDate()}`.padStart(2, \"0\");\n const hr = `${date.getHours()}`.padStart(2, \"0\");\n const min = `${date.getMinutes()}`.padStart(2, \"0\");\n return `${year}-${month}-${day}-${hr}${min}`;\n};\nconst capitalizeString = str => str.charAt(0).toUpperCase() + str.slice(1);\nconst isToolIcon = target => target instanceof HTMLElement && target.className.includes(\"ToolIcon\");\nconst isInputLike = target => target instanceof HTMLElement && target.dataset.type === \"wysiwyg\" || target instanceof HTMLBRElement || // newline in wysiwyg\ntarget instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement;\nconst isInteractive = target => {\n return isInputLike(target) || target instanceof Element && !!target.closest(\"label, button\");\n};\nconst isWritableElement = target => target instanceof HTMLElement && target.dataset.type === \"wysiwyg\" || target instanceof HTMLBRElement || // newline in wysiwyg\ntarget instanceof HTMLTextAreaElement || target instanceof HTMLInputElement && (target.type === \"text\" || target.type === \"number\" || target.type === \"password\");\nconst getFontFamilyString = ({\n fontFamily\n}) => {\n for (const [fontFamilyString, id] of Object.entries(_constants__WEBPACK_IMPORTED_MODULE_3__.FONT_FAMILY)) {\n if (id === fontFamily) {\n // TODO: we should fallback first to generic family names first\n return `${fontFamilyString}${(0,_constants__WEBPACK_IMPORTED_MODULE_3__.getFontFamilyFallbacks)(id).map(x => `, ${x}`).join(\"\")}`;\n }\n }\n\n return _constants__WEBPACK_IMPORTED_MODULE_3__.WINDOWS_EMOJI_FALLBACK_FONT;\n};\n/** returns fontSize+fontFamily string for assignment to DOM elements */\n\nconst getFontString = ({\n fontSize,\n fontFamily\n}) => {\n return `${fontSize}px ${getFontFamilyString({\n fontFamily\n })}`;\n};\nconst debounce = (fn, timeout) => {\n let handle = 0;\n let lastArgs = null;\n\n const ret = (...args) => {\n lastArgs = args;\n clearTimeout(handle);\n handle = window.setTimeout(() => {\n lastArgs = null;\n fn(...args);\n }, timeout);\n };\n\n ret.flush = () => {\n clearTimeout(handle);\n\n if (lastArgs) {\n const _lastArgs = lastArgs;\n lastArgs = null;\n fn(..._lastArgs);\n }\n };\n\n ret.cancel = () => {\n lastArgs = null;\n clearTimeout(handle);\n };\n\n return ret;\n}; // throttle callback to execute once per animation frame\n\nconst throttleRAF = (fn, opts) => {\n let timerId = null;\n let lastArgs = null;\n let lastArgsTrailing = null;\n\n const scheduleFunc = args => {\n timerId = window.requestAnimationFrame(() => {\n timerId = null;\n fn(...args);\n lastArgs = null;\n\n if (lastArgsTrailing) {\n lastArgs = lastArgsTrailing;\n lastArgsTrailing = null;\n scheduleFunc(lastArgs);\n }\n });\n };\n\n const ret = (...args) => {\n if (false) {}\n\n lastArgs = args;\n\n if (timerId === null) {\n scheduleFunc(lastArgs);\n } else if (opts === null || opts === void 0 ? void 0 : opts.trailing) {\n lastArgsTrailing = args;\n }\n };\n\n ret.flush = () => {\n if (timerId !== null) {\n cancelAnimationFrame(timerId);\n timerId = null;\n }\n\n if (lastArgs) {\n fn(...(lastArgsTrailing || lastArgs));\n lastArgs = lastArgsTrailing = null;\n }\n };\n\n ret.cancel = () => {\n lastArgs = lastArgsTrailing = null;\n\n if (timerId !== null) {\n cancelAnimationFrame(timerId);\n timerId = null;\n }\n };\n\n return ret;\n};\n/**\n * Exponential ease-out method\n *\n * @param {number} k - The value to be tweened.\n * @returns {number} The tweened value.\n */\n\nconst easeOut = k => {\n return 1 - Math.pow(1 - k, 4);\n};\n\nconst easeOutInterpolate = (from, to, progress) => {\n return (to - from) * easeOut(progress) + from;\n};\n/**\n * Animates values from `fromValues` to `toValues` using the requestAnimationFrame API.\n * Executes the `onStep` callback on each step with the interpolated values.\n * Returns a function that can be called to cancel the animation.\n *\n * @example\n * // Example usage:\n * const fromValues = { x: 0, y: 0 };\n * const toValues = { x: 100, y: 200 };\n * const onStep = ({x, y}) => {\n * setState(x, y)\n * };\n * const onCancel = () => {\n * console.log(\"Animation canceled\");\n * };\n *\n * const cancelAnimation = easeToValuesRAF({\n * fromValues,\n * toValues,\n * onStep,\n * onCancel,\n * });\n *\n * // To cancel the animation:\n * cancelAnimation();\n */\n\n\nconst easeToValuesRAF = ({\n fromValues,\n toValues,\n onStep,\n duration = 250,\n interpolateValue,\n onStart,\n onEnd,\n onCancel\n}) => {\n let canceled = false;\n let frameId = 0;\n let startTime;\n\n function step(timestamp) {\n if (canceled) {\n return;\n }\n\n if (startTime === undefined) {\n startTime = timestamp;\n onStart === null || onStart === void 0 ? void 0 : onStart();\n }\n\n const elapsed = Math.min(timestamp - startTime, duration);\n const factor = easeOut(elapsed / duration);\n const newValues = {};\n Object.keys(fromValues).forEach(key => {\n const _key = key;\n const result = (toValues[_key] - fromValues[_key]) * factor + fromValues[_key];\n newValues[_key] = result;\n });\n onStep(newValues);\n\n if (elapsed < duration) {\n const progress = elapsed / duration;\n const newValues = {};\n Object.keys(fromValues).forEach(key => {\n const _key = key;\n const startValue = fromValues[_key];\n const endValue = toValues[_key];\n let result;\n result = interpolateValue ? interpolateValue(startValue, endValue, progress, _key) : easeOutInterpolate(startValue, endValue, progress);\n\n if (result == null) {\n result = easeOutInterpolate(startValue, endValue, progress);\n }\n\n newValues[_key] = result;\n });\n onStep(newValues);\n frameId = window.requestAnimationFrame(step);\n } else {\n onStep(toValues);\n onEnd === null || onEnd === void 0 ? void 0 : onEnd();\n }\n }\n\n frameId = window.requestAnimationFrame(step);\n return () => {\n onCancel === null || onCancel === void 0 ? void 0 : onCancel();\n canceled = true;\n window.cancelAnimationFrame(frameId);\n };\n}; // https://github.com/lodash/lodash/blob/es/chunk.js\n\nconst chunk = (array, size) => {\n if (!array.length || size < 1) {\n return [];\n }\n\n let index = 0;\n let resIndex = 0;\n const result = Array(Math.ceil(array.length / size));\n\n while (index < array.length) {\n result[resIndex++] = array.slice(index, index += size);\n }\n\n return result;\n};\nconst selectNode = node => {\n const selection = window.getSelection();\n\n if (selection) {\n const range = document.createRange();\n range.selectNodeContents(node);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n};\nconst removeSelection = () => {\n const selection = window.getSelection();\n\n if (selection) {\n selection.removeAllRanges();\n }\n};\nconst distance = (x, y) => Math.abs(x - y);\nconst updateActiveTool = (appState, data) => {\n var _a, _b;\n\n if (data.type === \"custom\") {\n return Object.assign(Object.assign({}, appState.activeTool), {\n type: \"custom\",\n customType: data.customType,\n locked: (_a = data.locked) !== null && _a !== void 0 ? _a : appState.activeTool.locked\n });\n }\n\n return Object.assign(Object.assign({}, appState.activeTool), {\n lastActiveTool: data.lastActiveToolBeforeEraser === undefined ? appState.activeTool.lastActiveTool : data.lastActiveToolBeforeEraser,\n type: data.type,\n customType: null,\n locked: (_b = data.locked) !== null && _b !== void 0 ? _b : appState.activeTool.locked\n });\n};\nconst isFullScreen = () => {\n var _a;\n\n return ((_a = document.fullscreenElement) === null || _a === void 0 ? void 0 : _a.nodeName) === \"HTML\";\n};\nconst allowFullScreen = () => document.documentElement.requestFullscreen();\nconst exitFullScreen = () => document.exitFullscreen();\nconst getShortcutKey = shortcut => {\n shortcut = shortcut.replace(/\\bAlt\\b/i, \"Alt\").replace(/\\bShift\\b/i, \"Shift\").replace(/\\b(Enter|Return)\\b/i, \"Enter\");\n\n if (_constants__WEBPACK_IMPORTED_MODULE_3__.isDarwin) {\n return shortcut.replace(/\\bCtrlOrCmd\\b/gi, \"Cmd\").replace(/\\bAlt\\b/i, \"Option\");\n }\n\n return shortcut.replace(/\\bCtrlOrCmd\\b/gi, \"Ctrl\");\n};\nconst viewportCoordsToSceneCoords = ({\n clientX,\n clientY\n}, {\n zoom,\n offsetLeft,\n offsetTop,\n scrollX,\n scrollY\n}) => {\n const x = (clientX - offsetLeft) / zoom.value - scrollX;\n const y = (clientY - offsetTop) / zoom.value - scrollY;\n return {\n x,\n y\n };\n};\nconst sceneCoordsToViewportCoords = ({\n sceneX,\n sceneY\n}, {\n zoom,\n offsetLeft,\n offsetTop,\n scrollX,\n scrollY\n}) => {\n const x = (sceneX + scrollX) * zoom.value + offsetLeft;\n const y = (sceneY + scrollY) * zoom.value + offsetTop;\n return {\n x,\n y\n };\n};\nconst getGlobalCSSVariable = name => getComputedStyle(document.documentElement).getPropertyValue(`--${name}`);\nconst RS_LTR_CHARS = \"A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02B8\\u0300-\\u0590\\u0800-\\u1FFF\" + \"\\u2C00-\\uFB1C\\uFDFE-\\uFE6F\\uFEFD-\\uFFFF\";\nconst RS_RTL_CHARS = \"\\u0591-\\u07FF\\uFB1D-\\uFDFD\\uFE70-\\uFEFC\";\nconst RE_RTL_CHECK = new RegExp(`^[^${RS_LTR_CHARS}]*[${RS_RTL_CHARS}]`);\n/**\n * Checks whether first directional character is RTL. Meaning whether it starts\n * with RTL characters, or indeterminate (numbers etc.) characters followed by\n * RTL.\n * See https://github.com/excalidraw/excalidraw/pull/1722#discussion_r436340171\n */\n\nconst isRTL = text => RE_RTL_CHECK.test(text);\nconst tupleToCoors = xyTuple => {\n const [x, y] = xyTuple;\n return {\n x,\n y\n };\n};\n/** use as a rejectionHandler to mute filesystem Abort errors */\n\nconst muteFSAbortError = error => {\n if ((error === null || error === void 0 ? void 0 : error.name) === \"AbortError\") {\n console.warn(error);\n return;\n }\n\n throw error;\n};\nconst findIndex = (array, cb, fromIndex = 0) => {\n if (fromIndex < 0) {\n fromIndex = array.length + fromIndex;\n }\n\n fromIndex = Math.min(array.length, Math.max(fromIndex, 0));\n let index = fromIndex - 1;\n\n while (++index < array.length) {\n if (cb(array[index], index, array)) {\n return index;\n }\n }\n\n return -1;\n};\nconst findLastIndex = (array, cb, fromIndex = array.length - 1) => {\n if (fromIndex < 0) {\n fromIndex = array.length + fromIndex;\n }\n\n fromIndex = Math.min(array.length - 1, Math.max(fromIndex, 0));\n let index = fromIndex + 1;\n\n while (--index > -1) {\n if (cb(array[index], index, array)) {\n return index;\n }\n }\n\n return -1;\n};\nconst isTransparent = color => {\n const isRGBTransparent = color.length === 5 && color.substr(4, 1) === \"0\";\n const isRRGGBBTransparent = color.length === 9 && color.substr(7, 2) === \"00\";\n return isRGBTransparent || isRRGGBBTransparent || color === _colors__WEBPACK_IMPORTED_MODULE_2__.COLOR_PALETTE.transparent;\n};\nconst resolvablePromise = () => {\n let resolve;\n let reject;\n const promise = new Promise((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n promise.resolve = resolve;\n promise.reject = reject;\n return promise;\n}; //https://stackoverflow.com/a/9462382/8418\n\nconst nFormatter = (num, digits) => {\n const si = [{\n value: 1,\n symbol: \"b\"\n }, {\n value: 1e3,\n symbol: \"k\"\n }, {\n value: 1e6,\n symbol: \"M\"\n }, {\n value: 1e9,\n symbol: \"G\"\n }];\n const rx = /\\.0+$|(\\.[0-9]*[1-9])0+$/;\n let index;\n\n for (index = si.length - 1; index > 0; index--) {\n if (num >= si[index].value) {\n break;\n }\n }\n\n return (num / si[index].value).toFixed(digits).replace(rx, \"$1\") + si[index].symbol;\n};\nconst getVersion = () => {\n var _a;\n\n return ((_a = document.querySelector('meta[name=\"version\"]')) === null || _a === void 0 ? void 0 : _a.content) || _constants__WEBPACK_IMPORTED_MODULE_3__.DEFAULT_VERSION;\n}; // Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/emoji.js\n\nconst supportsEmoji = () => {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n\n if (!ctx) {\n return false;\n }\n\n const offset = 12;\n ctx.fillStyle = \"#f00\";\n ctx.textBaseline = \"top\";\n ctx.font = \"32px Arial\"; // Modernizr used 🐨, but it is sort of supported on Windows 7.\n // Luckily 😀 isn't supported.\n\n ctx.fillText(\"😀\", 0, 0);\n return ctx.getImageData(offset, offset, 1, 1).data[0] !== 0;\n};\nconst getNearestScrollableContainer = element => {\n let parent = element.parentElement;\n\n while (parent) {\n if (parent === document.body) {\n return document;\n }\n\n const {\n overflowY\n } = window.getComputedStyle(parent);\n const hasScrollableContent = parent.scrollHeight > parent.clientHeight;\n\n if (hasScrollableContent && (overflowY === \"auto\" || overflowY === \"scroll\" || overflowY === \"overlay\")) {\n return parent;\n }\n\n parent = parent.parentElement;\n }\n\n return document;\n};\nconst focusNearestParent = element => {\n let parent = element.parentElement;\n\n while (parent) {\n if (parent.tabIndex > -1) {\n parent.focus();\n return;\n }\n\n parent = parent.parentElement;\n }\n};\nconst preventUnload = event => {\n event.preventDefault(); // NOTE: modern browsers no longer allow showing a custom message here\n\n event.returnValue = \"\";\n};\nconst bytesToHexString = bytes => {\n return Array.from(bytes).map(byte => `0${byte.toString(16)}`.slice(-2)).join(\"\");\n};\nconst getUpdatedTimestamp = () => isTestEnv() ? 1 : Date.now();\n/**\n * Transforms array of objects containing `id` attribute,\n * or array of ids (strings), into a Map, keyd by `id`.\n */\n\nconst arrayToMap = items => {\n if (items instanceof Map) {\n return items;\n }\n\n return items.reduce((acc, element) => {\n acc.set(typeof element === \"string\" ? element : element.id, element);\n return acc;\n }, new Map());\n};\nconst arrayToMapWithIndex = elements => elements.reduce((acc, element, idx) => {\n acc.set(element.id, [element, idx]);\n return acc;\n}, new Map());\n/**\n * Transform array into an object, use only when array order is irrelevant.\n */\n\nconst arrayToObject = (array, groupBy) => array.reduce((acc, value) => {\n acc[groupBy ? groupBy(value) : String(value)] = value;\n return acc;\n}, {});\n/**\n * Creates a circular doubly linked list by adding `prev` and `next` props to the existing array nodes.\n */\n\nconst arrayToList = array => array.reduce((acc, curr, index) => {\n const node = Object.assign(Object.assign({}, curr), {\n prev: null,\n next: null\n }); // no-op for first item, we don't want circular references on a single item\n\n if (index !== 0) {\n const prevNode = acc[index - 1];\n node.prev = prevNode;\n prevNode.next = node;\n\n if (index === array.length - 1) {\n // make the references circular and connect head & tail\n const firstNode = acc[0];\n node.next = firstNode;\n firstNode.prev = node;\n }\n }\n\n acc.push(node);\n return acc;\n}, []);\nconst isTestEnv = () => \"development\" === \"test\";\nconst isDevEnv = () => \"development\" === \"development\";\nconst isServerEnv = () => {\n var _a;\n\n return typeof process !== \"undefined\" && !!((_a = process === null || process === void 0 ? void 0 : ({\"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_DISABLE_LIVE_RELOAD\":\"\",\"VITE_APP_ENABLE_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.6-9\",\"VITE_IS_EXCALIDRAW_NPM_PACKAGE\":true})) === null || _a === void 0 ? void 0 : _a.NODE_ENV);\n};\nconst wrapEvent = (name, nativeEvent) => {\n return new CustomEvent(name, {\n detail: {\n nativeEvent\n },\n cancelable: true\n });\n};\nconst updateObject = (obj, updates) => {\n let didChange = false;\n\n for (const key in updates) {\n const value = updates[key];\n\n if (typeof value !== \"undefined\") {\n if (obj[key] === value && ( // if object, always update because its attrs could have changed\n typeof value !== \"object\" || value === null)) {\n continue;\n }\n\n didChange = true;\n }\n }\n\n if (!didChange) {\n return obj;\n }\n\n return Object.assign(Object.assign({}, obj), updates);\n};\nconst isPrimitive = val => {\n const type = typeof val;\n return val == null || type !== \"object\" && type !== \"function\";\n};\nconst getFrame = () => {\n try {\n return window.self === window.top ? \"top\" : \"iframe\";\n } catch (error) {\n return \"iframe\";\n }\n};\nconst isRunningInIframe = () => getFrame() === \"iframe\";\nconst isPromiseLike = value => {\n return !!value && typeof value === \"object\" && \"then\" in value && \"catch\" in value && \"finally\" in value;\n};\nconst queryFocusableElements = container => {\n const focusableElements = container === null || container === void 0 ? void 0 : container.querySelectorAll(\"button, a, input, select, textarea, div[tabindex], label[tabindex]\");\n return focusableElements ? Array.from(focusableElements).filter(element => element.tabIndex > -1 && !element.disabled) : [];\n};\n/** use as a fallback after identity check (for perf reasons) */\n\nconst _defaultIsShallowComparatorFallback = (a, b) => {\n // consider two empty arrays equal\n if (Array.isArray(a) && Array.isArray(b) && a.length === 0 && b.length === 0) {\n return true;\n }\n\n return a === b;\n};\n/**\n * Returns whether object/array is shallow equal.\n * Considers empty object/arrays as equal (whether top-level or second-level).\n */\n\n\nconst isShallowEqual = (objA, objB, comparators, debug = false) => {\n const aKeys = Object.keys(objA);\n const bKeys = Object.keys(objB);\n\n if (aKeys.length !== bKeys.length) {\n if (debug) {\n console.warn(`%cisShallowEqual: objects don't have same properties ->`, \"color: #8B4000\", objA, objB);\n }\n\n return false;\n }\n\n if (comparators && Array.isArray(comparators)) {\n for (const key of comparators) {\n const ret = objA[key] === objB[key] || _defaultIsShallowComparatorFallback(objA[key], objB[key]);\n\n if (!ret) {\n if (debug) {\n console.warn(`%cisShallowEqual: ${key} not equal ->`, \"color: #8B4000\", objA[key], objB[key]);\n }\n\n return false;\n }\n }\n\n return true;\n }\n\n return aKeys.every(key => {\n const comparator = comparators === null || comparators === void 0 ? void 0 : comparators[key];\n const ret = comparator ? comparator(objA[key], objB[key]) : objA[key] === objB[key] || _defaultIsShallowComparatorFallback(objA[key], objB[key]);\n\n if (!ret && debug) {\n console.warn(`%cisShallowEqual: ${key} not equal ->`, \"color: #8B4000\", objA[key], objB[key]);\n }\n\n return ret;\n });\n}; // taken from Radix UI\n// https://github.com/radix-ui/primitives/blob/main/packages/core/primitive/src/primitive.tsx\n\nconst composeEventHandlers = (originalEventHandler, ourEventHandler, {\n checkForDefaultPrevented = true\n} = {}) => {\n return function handleEvent(event) {\n originalEventHandler === null || originalEventHandler === void 0 ? void 0 : originalEventHandler(event);\n\n if (!checkForDefaultPrevented || !(event === null || event === void 0 ? void 0 : event.defaultPrevented)) {\n return ourEventHandler === null || ourEventHandler === void 0 ? void 0 : ourEventHandler(event);\n }\n };\n};\n/**\n * supply `null` as message if non-never value is valid, you just need to\n * typecheck against it\n */\n\nconst assertNever = (value, message, softAssert) => {\n if (!message) {\n return value;\n }\n\n if (softAssert) {\n console.error(message);\n return value;\n }\n\n throw new Error(message);\n};\nfunction invariant(condition, message) {\n if (!condition) {\n throw new Error(message);\n }\n}\n/**\n * Memoizes on values of `opts` object (strict equality).\n */\n\nconst memoize = func => {\n let lastArgs;\n let lastResult;\n\n const ret = function (opts) {\n const currentArgs = Object.entries(opts);\n\n if (lastArgs) {\n let argsAreEqual = true;\n\n for (const [key, value] of currentArgs) {\n if (lastArgs.get(key) !== value) {\n argsAreEqual = false;\n break;\n }\n }\n\n if (argsAreEqual) {\n return lastResult;\n }\n }\n\n const result = func(opts);\n lastArgs = new Map(currentArgs);\n lastResult = result;\n return result;\n };\n\n ret.clear = () => {\n lastArgs = undefined;\n lastResult = undefined;\n };\n\n return ret;\n};\n/** Checks if value is inside given collection. Useful for type-safety. */\n\nconst isMemberOf = (\n/** Set/Map/Array/Object */\ncollection,\n/** value to look for */\nvalue) => {\n return collection instanceof Set || collection instanceof Map ? collection.has(value) : \"includes\" in collection ? collection.includes(value) : collection.hasOwnProperty(value);\n};\nconst cloneJSON = obj => JSON.parse(JSON.stringify(obj));\nconst updateStable = (prevValue, nextValue) => {\n if (isShallowEqual(prevValue, nextValue)) {\n return prevValue;\n }\n\n return nextValue;\n}; // implem\n\nfunction addEventListener(\n/**\n * allows for falsy values so you don't have to type check when adding\n * event listeners to optional elements\n */\ntarget, type, listener, options) {\n var _a;\n\n if (!target) {\n return () => {};\n }\n\n (_a = target === null || target === void 0 ? void 0 : target.addEventListener) === null || _a === void 0 ? void 0 : _a.call(target, type, listener, options);\n return () => {\n var _a;\n\n (_a = target === null || target === void 0 ? void 0 : target.removeEventListener) === null || _a === void 0 ? void 0 : _a.call(target, type, listener, options);\n };\n}\nfunction getSvgPathFromStroke(points, closed = true) {\n const len = points.length;\n\n if (len < 4) {\n return ``;\n }\n\n let a = points[0];\n let b = points[1];\n const c = points[2];\n let result = `M${a[0].toFixed(2)},${a[1].toFixed(2)} Q${b[0].toFixed(2)},${b[1].toFixed(2)} ${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(b[0], c[0]).toFixed(2)},${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(b[1], c[1]).toFixed(2)} T`;\n\n for (let i = 2, max = len - 1; i < max; i++) {\n a = points[i];\n b = points[i + 1];\n result += `${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(a[0], b[0]).toFixed(2)},${(0,_math__WEBPACK_IMPORTED_MODULE_1__.average)(a[1], b[1]).toFixed(2)} `;\n }\n\n if (closed) {\n result += \"Z\";\n }\n\n return result;\n}\nconst normalizeEOL = str => {\n return str.replace(/\\r?\\n|\\r/g, \"\\n\");\n};\n/**\n * Makes type into a branded type, ensuring that value is assignable to\n * the base ubranded type. Optionally you can explicitly supply current value\n * type to combine both (useful for composite branded types. Make sure you\n * compose branded types which are not composite themselves.)\n */\n\nconst toBrandedType = value => {\n return value;\n}; // -----------------------------------------------------------------------------\n// Promise.try, adapted from https://github.com/sindresorhus/p-try\n\nconst promiseTry = async (fn, ...args) => {\n return new Promise(resolve => {\n resolve(fn(...args));\n });\n};\nconst isAnyTrue = (...args) => Math.max(...args.map(arg => arg ? 1 : 0)) > 0;\nconst safelyParseJSON = json => {\n try {\n return JSON.parse(json);\n } catch (_a) {\n return null;\n }\n};\nclass PromisePool {\n constructor(source, concurrency) {\n this.entries = {};\n this.pool = new (es6_promise_pool__WEBPACK_IMPORTED_MODULE_0___default())(source, concurrency);\n }\n\n all() {\n const listener = event => {\n if (event.data.result) {\n // by default pool does not return the results, so we are gathering them manually\n // with the correct call order (represented by the index in the tuple)\n const [index, value] = event.data.result;\n this.entries[index] = value;\n }\n };\n\n this.pool.addEventListener(\"fulfilled\", listener);\n return this.pool.start().then(() => {\n setTimeout(() => {\n this.pool.removeEventListener(\"fulfilled\", listener);\n });\n return Object.values(this.entries);\n });\n }\n\n}\n\n//# sourceURL=webpack://ExcalidrawLib/./utils.ts?");
3942
3953
 
3943
3954
  /***/ }),
3944
3955
 
@@ -4191,7 +4202,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
4191
4202
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4192
4203
 
4193
4204
  "use strict";
4194
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"MIME_TYPES\": () => (/* reexport safe */ _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES),\n/* harmony export */ \"destroyObsidianUtils\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__.destroyObsidianUtils),\n/* harmony export */ \"determineFocusDistance\": () => (/* reexport safe */ _excalidraw_element_binding__WEBPACK_IMPORTED_MODULE_9__.determineFocusDistance),\n/* harmony export */ \"exportToBlob\": () => (/* binding */ exportToBlob),\n/* harmony export */ \"exportToCanvas\": () => (/* binding */ exportToCanvas),\n/* harmony export */ \"exportToClipboard\": () => (/* binding */ exportToClipboard),\n/* harmony export */ \"exportToSvg\": () => (/* binding */ exportToSvg),\n/* harmony export */ \"getBoundTextMaxWidth\": () => (/* reexport safe */ _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__.getBoundTextMaxWidth),\n/* harmony export */ \"getCSSFontDefinition\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__.getCSSFontDefinition),\n/* harmony export */ \"getCommonBoundingBox\": () => (/* reexport safe */ _excalidraw_element_bounds__WEBPACK_IMPORTED_MODULE_7__.getCommonBoundingBox),\n/* harmony export */ \"getFontFamilies\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__.getFontFamilies),\n/* harmony export */ \"getFontFamilyString\": () => (/* reexport safe */ _excalidraw_utils__WEBPACK_IMPORTED_MODULE_12__.getFontFamilyString),\n/* harmony export */ \"getFontString\": () => (/* reexport safe */ _excalidraw_utils__WEBPACK_IMPORTED_MODULE_12__.getFontString),\n/* harmony export */ \"getLineHeight\": () => (/* reexport safe */ _excalidraw_fonts_index__WEBPACK_IMPORTED_MODULE_11__.getLineHeight),\n/* harmony export */ \"getMaximumGroups\": () => (/* reexport safe */ _excalidraw_groups__WEBPACK_IMPORTED_MODULE_8__.getMaximumGroups),\n/* harmony export */ \"intersectElementWithLine\": () => (/* reexport safe */ _excalidraw_element_binding__WEBPACK_IMPORTED_MODULE_9__.intersectElementWithLine),\n/* harmony export */ \"loadSceneFonts\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__.loadSceneFonts),\n/* harmony export */ \"measureText\": () => (/* reexport safe */ _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__.measureText),\n/* harmony export */ \"mermaidToExcalidraw\": () => (/* reexport safe */ _excalidraw_components_TTDDialog_MermaidToExcalidraw__WEBPACK_IMPORTED_MODULE_13__.mermaidToExcalidraw),\n/* harmony export */ \"registerFontsInCSS\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__.registerFontsInCSS),\n/* harmony export */ \"registerLocalFont\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__.registerLocalFont),\n/* harmony export */ \"wrapText\": () => (/* reexport safe */ _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__.wrapText)\n/* harmony export */ });\n/* harmony import */ var _excalidraw_scene_export__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../excalidraw/scene/export */ \"./scene/export.ts\");\n/* harmony import */ var _excalidraw_appState__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../excalidraw/appState */ \"./appState.ts\");\n/* harmony import */ var _excalidraw_data_restore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../excalidraw/data/restore */ \"./data/restore.ts\");\n/* harmony import */ var _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../excalidraw/constants */ \"./constants.ts\");\n/* harmony import */ var _excalidraw_data_image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../excalidraw/data/image */ \"./data/image.ts\");\n/* harmony import */ var _excalidraw_data_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../excalidraw/data/json */ \"./data/json.ts\");\n/* harmony import */ var _excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../excalidraw/clipboard */ \"./clipboard.ts\");\n/* harmony import */ var _excalidraw_element_bounds__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../excalidraw/element/bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _excalidraw_groups__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../excalidraw/groups */ \"./groups.ts\");\n/* harmony import */ var _excalidraw_element_binding__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../excalidraw/element/binding */ \"./element/binding.ts\");\n/* harmony import */ var _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../excalidraw/element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _excalidraw_fonts_index__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../excalidraw/fonts/index */ \"./fonts/index.ts\");\n/* harmony import */ var _excalidraw_utils__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../excalidraw/utils */ \"./utils.ts\");\n/* harmony import */ var _excalidraw_components_TTDDialog_MermaidToExcalidraw__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../excalidraw/components/TTDDialog/MermaidToExcalidraw */ \"./components/TTDDialog/MermaidToExcalidraw.tsx\");\n/* harmony import */ var _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../excalidraw/obsidianUtils */ \"./obsidianUtils.ts\");\n\n\n\n\n\n\n\n\nconst exportToCanvas = ({\n elements,\n appState,\n files,\n maxWidthOrHeight,\n getDimensions,\n exportPadding,\n exportingFrame\n}) => {\n const {\n elements: restoredElements,\n appState: restoredAppState\n } = (0,_excalidraw_data_restore__WEBPACK_IMPORTED_MODULE_2__.restore)({\n elements,\n appState\n }, null, null);\n const {\n exportBackground,\n viewBackgroundColor\n } = restoredAppState;\n return (0,_excalidraw_scene_export__WEBPACK_IMPORTED_MODULE_0__.exportToCanvas)(restoredElements, Object.assign(Object.assign({}, restoredAppState), {\n offsetTop: 0,\n offsetLeft: 0,\n width: 0,\n height: 0\n }), files || {}, {\n exportBackground,\n exportPadding,\n viewBackgroundColor,\n exportingFrame\n }, (width, height) => {\n var _a, _b;\n\n const canvas = document.createElement(\"canvas\");\n\n if (maxWidthOrHeight) {\n if (typeof getDimensions === \"function\") {\n console.warn(\"`getDimensions()` is ignored when `maxWidthOrHeight` is supplied.\");\n }\n\n const max = Math.max(width, height); // if content is less then maxWidthOrHeight, fallback on supplied scale\n\n const scale = maxWidthOrHeight < max ? maxWidthOrHeight / max : (_a = appState === null || appState === void 0 ? void 0 : appState.exportScale) !== null && _a !== void 0 ? _a : 1;\n canvas.width = width * scale;\n canvas.height = height * scale;\n return {\n canvas,\n scale\n };\n }\n\n const ret = (getDimensions === null || getDimensions === void 0 ? void 0 : getDimensions(width, height)) || {\n width,\n height\n };\n canvas.width = ret.width;\n canvas.height = ret.height;\n return {\n canvas,\n scale: (_b = ret.scale) !== null && _b !== void 0 ? _b : 1\n };\n });\n};\nconst exportToBlob = async opts => {\n var _a;\n\n let {\n mimeType = _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png,\n quality\n } = opts;\n\n if (mimeType === _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png && typeof quality === \"number\") {\n console.warn(`\"quality\" will be ignored for \"${_excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png}\" mimeType`);\n } // typo in MIME type (should be \"jpeg\")\n\n\n if (mimeType === \"image/jpg\") {\n mimeType = _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.jpg;\n }\n\n if (mimeType === _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.jpg && !((_a = opts.appState) === null || _a === void 0 ? void 0 : _a.exportBackground)) {\n console.warn(`Defaulting \"exportBackground\" to \"true\" for \"${_excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.jpg}\" mimeType`);\n opts = Object.assign(Object.assign({}, opts), {\n appState: Object.assign(Object.assign({}, opts.appState), {\n exportBackground: true\n })\n });\n }\n\n const canvas = await exportToCanvas(opts);\n quality = quality ? quality : /image\\/jpe?g/.test(mimeType) ? 0.92 : 0.8;\n return new Promise((resolve, reject) => {\n canvas.toBlob(async blob => {\n var _a;\n\n if (!blob) {\n return reject(new Error(\"couldn't export to blob\"));\n }\n\n if (blob && mimeType === _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png && ((_a = opts.appState) === null || _a === void 0 ? void 0 : _a.exportEmbedScene)) {\n blob = await (0,_excalidraw_data_image__WEBPACK_IMPORTED_MODULE_4__.encodePngMetadata)({\n blob,\n metadata: (0,_excalidraw_data_json__WEBPACK_IMPORTED_MODULE_5__.serializeAsJSON)( // NOTE as long as we're using the Scene hack, we need to ensure\n // we pass the original, uncloned elements when serializing\n // so that we keep ids stable\n opts.elements, opts.appState, opts.files || {}, \"local\")\n });\n }\n\n resolve(blob);\n }, mimeType, quality);\n });\n};\nconst exportToSvg = async ({\n elements,\n appState = (0,_excalidraw_appState__WEBPACK_IMPORTED_MODULE_1__.getDefaultAppState)(),\n files = {},\n exportPadding,\n renderEmbeddables,\n exportingFrame,\n skipInliningFonts,\n reuseImages\n}) => {\n const {\n elements: restoredElements,\n appState: restoredAppState\n } = (0,_excalidraw_data_restore__WEBPACK_IMPORTED_MODULE_2__.restore)({\n elements,\n appState\n }, null, null);\n const exportAppState = Object.assign(Object.assign({}, restoredAppState), {\n exportPadding\n });\n return (0,_excalidraw_scene_export__WEBPACK_IMPORTED_MODULE_0__.exportToSvg)(restoredElements, exportAppState, files, {\n exportingFrame,\n renderEmbeddables,\n skipInliningFonts,\n reuseImages\n });\n};\nconst exportToClipboard = async opts => {\n if (opts.type === \"svg\") {\n const svg = await exportToSvg(opts);\n await (0,_excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__.copyTextToSystemClipboard)(svg.outerHTML);\n } else if (opts.type === \"png\") {\n await (0,_excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__.copyBlobToClipboardAsPng)(exportToBlob(opts));\n } else if (opts.type === \"json\") {\n await (0,_excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__.copyToClipboard)(opts.elements, opts.files);\n } else {\n throw new Error(\"Invalid export type\");\n }\n};\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n//# sourceURL=webpack://ExcalidrawLib/../utils/export.ts?");
4205
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"MIME_TYPES\": () => (/* reexport safe */ _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES),\n/* harmony export */ \"destroyObsidianUtils\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__.destroyObsidianUtils),\n/* harmony export */ \"determineFocusDistance\": () => (/* reexport safe */ _excalidraw_element_binding__WEBPACK_IMPORTED_MODULE_9__.determineFocusDistance),\n/* harmony export */ \"exportToBlob\": () => (/* binding */ exportToBlob),\n/* harmony export */ \"exportToCanvas\": () => (/* binding */ exportToCanvas),\n/* harmony export */ \"exportToClipboard\": () => (/* binding */ exportToClipboard),\n/* harmony export */ \"exportToSvg\": () => (/* binding */ exportToSvg),\n/* harmony export */ \"getBoundTextMaxWidth\": () => (/* reexport safe */ _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__.getBoundTextMaxWidth),\n/* harmony export */ \"getCSSFontDefinition\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__.getCSSFontDefinition),\n/* harmony export */ \"getCommonBoundingBox\": () => (/* reexport safe */ _excalidraw_element_bounds__WEBPACK_IMPORTED_MODULE_7__.getCommonBoundingBox),\n/* harmony export */ \"getFontFamilies\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__.getFontFamilies),\n/* harmony export */ \"getFontFamilyString\": () => (/* reexport safe */ _excalidraw_utils__WEBPACK_IMPORTED_MODULE_13__.getFontFamilyString),\n/* harmony export */ \"getFontString\": () => (/* reexport safe */ _excalidraw_utils__WEBPACK_IMPORTED_MODULE_13__.getFontString),\n/* harmony export */ \"getLineHeight\": () => (/* reexport safe */ _excalidraw_fonts_index__WEBPACK_IMPORTED_MODULE_12__.getLineHeight),\n/* harmony export */ \"getMaximumGroups\": () => (/* reexport safe */ _excalidraw_groups__WEBPACK_IMPORTED_MODULE_8__.getMaximumGroups),\n/* harmony export */ \"intersectElementWithLine\": () => (/* reexport safe */ _excalidraw_element_binding__WEBPACK_IMPORTED_MODULE_9__.intersectElementWithLine),\n/* harmony export */ \"loadSceneFonts\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__.loadSceneFonts),\n/* harmony export */ \"measureText\": () => (/* reexport safe */ _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__.measureText),\n/* harmony export */ \"mermaidToExcalidraw\": () => (/* reexport safe */ _excalidraw_components_TTDDialog_MermaidToExcalidraw__WEBPACK_IMPORTED_MODULE_14__.mermaidToExcalidraw),\n/* harmony export */ \"registerFontsInCSS\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__.registerFontsInCSS),\n/* harmony export */ \"registerLocalFont\": () => (/* reexport safe */ _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__.registerLocalFont),\n/* harmony export */ \"wrapText\": () => (/* reexport safe */ _excalidraw_element_textWrapping__WEBPACK_IMPORTED_MODULE_11__.wrapText)\n/* harmony export */ });\n/* harmony import */ var _excalidraw_scene_export__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../excalidraw/scene/export */ \"./scene/export.ts\");\n/* harmony import */ var _excalidraw_appState__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../excalidraw/appState */ \"./appState.ts\");\n/* harmony import */ var _excalidraw_data_restore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../excalidraw/data/restore */ \"./data/restore.ts\");\n/* harmony import */ var _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../excalidraw/constants */ \"./constants.ts\");\n/* harmony import */ var _excalidraw_data_image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../excalidraw/data/image */ \"./data/image.ts\");\n/* harmony import */ var _excalidraw_data_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../excalidraw/data/json */ \"./data/json.ts\");\n/* harmony import */ var _excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../excalidraw/clipboard */ \"./clipboard.ts\");\n/* harmony import */ var _excalidraw_element_bounds__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../excalidraw/element/bounds */ \"./element/bounds.ts\");\n/* harmony import */ var _excalidraw_groups__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../excalidraw/groups */ \"./groups.ts\");\n/* harmony import */ var _excalidraw_element_binding__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../excalidraw/element/binding */ \"./element/binding.ts\");\n/* harmony import */ var _excalidraw_element_textElement__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../excalidraw/element/textElement */ \"./element/textElement.ts\");\n/* harmony import */ var _excalidraw_element_textWrapping__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../excalidraw/element/textWrapping */ \"./element/textWrapping.ts\");\n/* harmony import */ var _excalidraw_fonts_index__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../excalidraw/fonts/index */ \"./fonts/index.ts\");\n/* harmony import */ var _excalidraw_utils__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../excalidraw/utils */ \"./utils.ts\");\n/* harmony import */ var _excalidraw_components_TTDDialog_MermaidToExcalidraw__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../excalidraw/components/TTDDialog/MermaidToExcalidraw */ \"./components/TTDDialog/MermaidToExcalidraw.tsx\");\n/* harmony import */ var _excalidraw_obsidianUtils__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../excalidraw/obsidianUtils */ \"./obsidianUtils.ts\");\n\n\n\n\n\n\n\n\nconst exportToCanvas = ({\n elements,\n appState,\n files,\n maxWidthOrHeight,\n getDimensions,\n exportPadding,\n exportingFrame\n}) => {\n const {\n elements: restoredElements,\n appState: restoredAppState\n } = (0,_excalidraw_data_restore__WEBPACK_IMPORTED_MODULE_2__.restore)({\n elements,\n appState\n }, null, null);\n const {\n exportBackground,\n viewBackgroundColor\n } = restoredAppState;\n return (0,_excalidraw_scene_export__WEBPACK_IMPORTED_MODULE_0__.exportToCanvas)(restoredElements, Object.assign(Object.assign({}, restoredAppState), {\n offsetTop: 0,\n offsetLeft: 0,\n width: 0,\n height: 0\n }), files || {}, {\n exportBackground,\n exportPadding,\n viewBackgroundColor,\n exportingFrame\n }, (width, height) => {\n var _a, _b;\n\n const canvas = document.createElement(\"canvas\");\n\n if (maxWidthOrHeight) {\n if (typeof getDimensions === \"function\") {\n console.warn(\"`getDimensions()` is ignored when `maxWidthOrHeight` is supplied.\");\n }\n\n const max = Math.max(width, height); // if content is less then maxWidthOrHeight, fallback on supplied scale\n\n const scale = maxWidthOrHeight < max ? maxWidthOrHeight / max : (_a = appState === null || appState === void 0 ? void 0 : appState.exportScale) !== null && _a !== void 0 ? _a : 1;\n canvas.width = width * scale;\n canvas.height = height * scale;\n return {\n canvas,\n scale\n };\n }\n\n const ret = (getDimensions === null || getDimensions === void 0 ? void 0 : getDimensions(width, height)) || {\n width,\n height\n };\n canvas.width = ret.width;\n canvas.height = ret.height;\n return {\n canvas,\n scale: (_b = ret.scale) !== null && _b !== void 0 ? _b : 1\n };\n });\n};\nconst exportToBlob = async opts => {\n var _a;\n\n let {\n mimeType = _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png,\n quality\n } = opts;\n\n if (mimeType === _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png && typeof quality === \"number\") {\n console.warn(`\"quality\" will be ignored for \"${_excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png}\" mimeType`);\n } // typo in MIME type (should be \"jpeg\")\n\n\n if (mimeType === \"image/jpg\") {\n mimeType = _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.jpg;\n }\n\n if (mimeType === _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.jpg && !((_a = opts.appState) === null || _a === void 0 ? void 0 : _a.exportBackground)) {\n console.warn(`Defaulting \"exportBackground\" to \"true\" for \"${_excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.jpg}\" mimeType`);\n opts = Object.assign(Object.assign({}, opts), {\n appState: Object.assign(Object.assign({}, opts.appState), {\n exportBackground: true\n })\n });\n }\n\n const canvas = await exportToCanvas(opts);\n quality = quality ? quality : /image\\/jpe?g/.test(mimeType) ? 0.92 : 0.8;\n return new Promise((resolve, reject) => {\n canvas.toBlob(async blob => {\n var _a;\n\n if (!blob) {\n return reject(new Error(\"couldn't export to blob\"));\n }\n\n if (blob && mimeType === _excalidraw_constants__WEBPACK_IMPORTED_MODULE_3__.MIME_TYPES.png && ((_a = opts.appState) === null || _a === void 0 ? void 0 : _a.exportEmbedScene)) {\n blob = await (0,_excalidraw_data_image__WEBPACK_IMPORTED_MODULE_4__.encodePngMetadata)({\n blob,\n metadata: (0,_excalidraw_data_json__WEBPACK_IMPORTED_MODULE_5__.serializeAsJSON)( // NOTE as long as we're using the Scene hack, we need to ensure\n // we pass the original, uncloned elements when serializing\n // so that we keep ids stable\n opts.elements, opts.appState, opts.files || {}, \"local\")\n });\n }\n\n resolve(blob);\n }, mimeType, quality);\n });\n};\nconst exportToSvg = async ({\n elements,\n appState = (0,_excalidraw_appState__WEBPACK_IMPORTED_MODULE_1__.getDefaultAppState)(),\n files = {},\n exportPadding,\n renderEmbeddables,\n exportingFrame,\n skipInliningFonts,\n reuseImages\n}) => {\n const {\n elements: restoredElements,\n appState: restoredAppState\n } = (0,_excalidraw_data_restore__WEBPACK_IMPORTED_MODULE_2__.restore)({\n elements,\n appState\n }, null, null);\n const exportAppState = Object.assign(Object.assign({}, restoredAppState), {\n exportPadding\n });\n return (0,_excalidraw_scene_export__WEBPACK_IMPORTED_MODULE_0__.exportToSvg)(restoredElements, exportAppState, files, {\n exportingFrame,\n renderEmbeddables,\n skipInliningFonts,\n reuseImages\n });\n};\nconst exportToClipboard = async opts => {\n if (opts.type === \"svg\") {\n const svg = await exportToSvg(opts);\n await (0,_excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__.copyTextToSystemClipboard)(svg.outerHTML);\n } else if (opts.type === \"png\") {\n await (0,_excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__.copyBlobToClipboardAsPng)(exportToBlob(opts));\n } else if (opts.type === \"json\") {\n await (0,_excalidraw_clipboard__WEBPACK_IMPORTED_MODULE_6__.copyToClipboard)(opts.elements, opts.files);\n } else {\n throw new Error(\"Invalid export type\");\n }\n};\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n //zsviczian\n\n//# sourceURL=webpack://ExcalidrawLib/../utils/export.ts?");
4195
4206
 
4196
4207
  /***/ }),
4197
4208