@excalidraw-modify/element 0.18.0-8b71db27
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.
- package/README.md +19 -0
- package/dist/dev/index.js +21148 -0
- package/dist/dev/index.js.map +7 -0
- package/dist/prod/index.js +27 -0
- package/package.json +63 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["<define:import.meta.env>", "../../../../node_modules/lodash.throttle/index.js", "../../src/index.ts", "../../src/sizeHelpers.ts", "../../src/bounds.ts", "../../../../node_modules/roughjs/bin/rough.js", "../../../../node_modules/roughjs/bin/canvas.js", "../../../../node_modules/roughjs/bin/generator.js", "../../../../node_modules/roughjs/bin/renderer.js", "../../../../node_modules/roughjs/bin/fillers/filler.js", "../../../../node_modules/roughjs/bin/fillers/hachure-filler.js", "../../../../node_modules/roughjs/bin/fillers/scan-line-hachure.js", "../../../../node_modules/hachure-fill/bin/hachure.js", "../../../../node_modules/roughjs/bin/fillers/zigzag-filler.js", "../../../../node_modules/roughjs/bin/geometry.js", "../../../../node_modules/roughjs/bin/fillers/hatch-filler.js", "../../../../node_modules/roughjs/bin/fillers/dot-filler.js", "../../../../node_modules/roughjs/bin/fillers/dashed-filler.js", "../../../../node_modules/roughjs/bin/fillers/zigzag-line-filler.js", "../../../../node_modules/roughjs/bin/math.js", "../../../../node_modules/path-data-parser/lib/index.js", "../../../../node_modules/path-data-parser/lib/parser.js", "../../../../node_modules/path-data-parser/lib/absolutize.js", "../../../../node_modules/path-data-parser/lib/normalize.js", "../../../../node_modules/points-on-curve/lib/curve-to-bezier.js", "../../../../node_modules/points-on-curve/lib/index.js", "../../../../node_modules/points-on-path/lib/index.js", "../../../../node_modules/roughjs/bin/svg.js", "../../../../node_modules/roughjs/bin/core.js", "../../../utils/src/shape.ts", "../../src/shape.ts", "../../src/renderElement.ts", "../../../../node_modules/perfect-freehand/dist/esm/index.js", "../../src/cropElement.ts", "../../src/linearElementEditor.ts", "../../src/binding.ts", "../../src/collision.ts", "../../src/utils.ts", "../../src/typeChecks.ts", "../../src/textElement.ts", "../../src/containerCache.ts", "../../src/textMeasurements.ts", "../../src/textWrapping.ts", "../../src/distance.ts", "../../src/heading.ts", "../../src/mutateElement.ts", "../../src/elbowArrow.ts", "../../src/frame.ts", "../../../utils/src/bbox.ts", "../../../utils/src/withinBounds.ts", "../../src/selection.ts", "../../src/groups.ts", "../../src/comparisons.ts", "../../src/align.ts", "../../src/delta.ts", "../../src/store.ts", "../../src/duplicate.ts", "../../src/sortElements.ts", "../../src/fractionalIndex.ts", "../../../../node_modules/fractional-indexing/src/index.js", "../../src/Scene.ts", "../../src/distribute.ts", "../../src/dragElements.ts", "../../src/elementLink.ts", "../../src/embeddable.ts", "../../src/newElement.ts", "../../src/flowchart.ts", "../../src/image.ts", "../../src/positionElementsOnGrid.ts", "../../src/resizeElements.ts", "../../src/resizeTest.ts", "../../src/transformHandles.ts", "../../src/showSelectedShapeActions.ts", "../../src/transform.ts", "../../src/zindex.ts"],
|
|
4
|
+
"sourcesContent": ["", "/**\n * lodash (Custom Build) <https://lodash.com/>\n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors <https://jquery.org/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\n/**\n * Creates a throttled function that only invokes `func` at most once per\n * every `wait` milliseconds. The throttled function comes with a `cancel`\n * method to cancel delayed `func` invocations and a `flush` method to\n * immediately invoke them. Provide `options` to indicate whether `func`\n * should be invoked on the leading and/or trailing edge of the `wait`\n * timeout. The `func` is invoked with the last arguments provided to the\n * throttled function. Subsequent calls to the throttled function return the\n * result of the last `func` invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the throttled function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.throttle` and `_.debounce`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to throttle.\n * @param {number} [wait=0] The number of milliseconds to throttle invocations to.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=true]\n * Specify invoking on the leading edge of the timeout.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new throttled function.\n * @example\n *\n * // Avoid excessively updating the position while scrolling.\n * jQuery(window).on('scroll', _.throttle(updatePosition, 100));\n *\n * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.\n * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });\n * jQuery(element).on('click', throttled);\n *\n * // Cancel the trailing throttled invocation.\n * jQuery(window).on('popstate', throttled.cancel);\n */\nfunction throttle(func, wait, options) {\n var leading = true,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n if (isObject(options)) {\n leading = 'leading' in options ? !!options.leading : leading;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n return debounce(func, wait, {\n 'leading': leading,\n 'maxWait': wait,\n 'trailing': trailing\n });\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = throttle;\n", "import { toIterable } from \"@excalidraw-modify/common\";\r\n\r\nimport { isInvisiblySmallElement } from \"./sizeHelpers\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n NonDeletedExcalidrawElement,\r\n NonDeleted,\r\n ElementsMapOrArray,\r\n} from \"./types\";\r\n\r\n/**\r\n * @deprecated unsafe, use hashElementsVersion instead\r\n */\r\nexport const getSceneVersion = (elements: readonly ExcalidrawElement[]) =>\r\n elements.reduce((acc, el) => acc + el.version, 0);\r\n\r\n/**\r\n * Hashes elements' versionNonce (using djb2 algo). Order of elements matters.\r\n */\r\nexport const hashElementsVersion = (elements: ElementsMapOrArray): number => {\r\n let hash = 5381;\r\n for (const element of toIterable(elements)) {\r\n hash = (hash << 5) + hash + element.versionNonce;\r\n }\r\n return hash >>> 0; // Ensure unsigned 32-bit integer\r\n};\r\n\r\n// string hash function (using djb2). Not cryptographically secure, use only\r\n// for versioning and such.\r\n// note: hashes individual code units (not code points),\r\n// but for hashing purposes this is fine as it iterates through every code unit\r\n// (as such, no need to encode to byte string first)\r\nexport const hashString = (s: string): number => {\r\n let hash: number = 5381;\r\n for (let i = 0; i < s.length; i++) {\r\n const char: number = s.charCodeAt(i);\r\n hash = (hash << 5) + hash + char;\r\n }\r\n return hash >>> 0; // Ensure unsigned 32-bit integer\r\n};\r\n\r\nexport const getVisibleElements = (elements: readonly ExcalidrawElement[]) =>\r\n elements.filter(\r\n (el) => !el.isDeleted && !isInvisiblySmallElement(el),\r\n ) as readonly NonDeletedExcalidrawElement[];\r\n\r\nexport const getNonDeletedElements = <T extends ExcalidrawElement>(\r\n elements: readonly T[],\r\n) =>\r\n elements.filter((element) => !element.isDeleted) as readonly NonDeleted<T>[];\r\n\r\nexport const isNonDeletedElement = <T extends ExcalidrawElement>(\r\n element: T,\r\n): element is NonDeleted<T> => !element.isDeleted;\r\n\r\nexport * from \"./align\";\r\nexport * from \"./binding\";\r\nexport * from \"./bounds\";\r\nexport * from \"./collision\";\r\nexport * from \"./comparisons\";\r\nexport * from \"./containerCache\";\r\nexport * from \"./cropElement\";\r\nexport * from \"./delta\";\r\nexport * from \"./distance\";\r\nexport * from \"./distribute\";\r\nexport * from \"./dragElements\";\r\nexport * from \"./duplicate\";\r\nexport * from \"./elbowArrow\";\r\nexport * from \"./elementLink\";\r\nexport * from \"./embeddable\";\r\nexport * from \"./flowchart\";\r\nexport * from \"./fractionalIndex\";\r\nexport * from \"./frame\";\r\nexport * from \"./groups\";\r\nexport * from \"./heading\";\r\nexport * from \"./image\";\r\nexport * from \"./linearElementEditor\";\r\nexport * from \"./mutateElement\";\r\nexport * from \"./newElement\";\r\nexport * from \"./positionElementsOnGrid\";\r\nexport * from \"./renderElement\";\r\nexport * from \"./resizeElements\";\r\nexport * from \"./resizeTest\";\r\nexport * from \"./Scene\";\r\nexport * from \"./selection\";\r\nexport * from \"./shape\";\r\nexport * from \"./showSelectedShapeActions\";\r\nexport * from \"./sizeHelpers\";\r\nexport * from \"./sortElements\";\r\nexport * from \"./store\";\r\nexport * from \"./textElement\";\r\nexport * from \"./textMeasurements\";\r\nexport * from \"./textWrapping\";\r\nexport * from \"./transform\";\r\nexport * from \"./transformHandles\";\r\nexport * from \"./typeChecks\";\r\nexport * from \"./utils\";\r\nexport * from \"./zindex\";\r\n", "import {\r\n SHIFT_LOCKING_ANGLE,\r\n viewportCoordsToSceneCoords,\r\n} from \"@excalidraw-modify/common\";\r\nimport {\r\n normalizeRadians,\r\n radiansBetweenAngles,\r\n radiansDifference,\r\n type Radians,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport { pointsEqual } from \"@excalidraw-modify/math\";\r\n\r\nimport type { AppState, Offsets, Zoom } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { getCommonBounds, getElementBounds } from \"./bounds\";\r\nimport {\r\n isArrowElement,\r\n isFreeDrawElement,\r\n isLinearElement,\r\n} from \"./typeChecks\";\r\n\r\nimport type { ElementsMap, ExcalidrawElement } from \"./types\";\r\n\r\nexport const INVISIBLY_SMALL_ELEMENT_SIZE = 0.1;\r\n\r\n// TODO: remove invisible elements consistently actions, so that invisible elements are not recorded by the store, exported, broadcasted or persisted\r\n// - perhaps could be as part of a standalone 'cleanup' action, in addition to 'finalize'\r\n// - could also be part of `_clearElements`\r\nexport const isInvisiblySmallElement = (\r\n element: ExcalidrawElement,\r\n): boolean => {\r\n if (isLinearElement(element) || isFreeDrawElement(element)) {\r\n return (\r\n element.points.length < 2 ||\r\n (element.points.length === 2 &&\r\n isArrowElement(element) &&\r\n pointsEqual(\r\n element.points[0],\r\n element.points[element.points.length - 1],\r\n INVISIBLY_SMALL_ELEMENT_SIZE,\r\n ))\r\n );\r\n }\r\n\r\n return element.width === 0 && element.height === 0;\r\n};\r\n\r\nexport const isElementInViewport = (\r\n element: ExcalidrawElement,\r\n width: number,\r\n height: number,\r\n viewTransformations: {\r\n zoom: Zoom;\r\n offsetLeft: number;\r\n offsetTop: number;\r\n scrollX: number;\r\n scrollY: number;\r\n },\r\n elementsMap: ElementsMap,\r\n) => {\r\n const [x1, y1, x2, y2] = getElementBounds(element, elementsMap); // scene coordinates\r\n const topLeftSceneCoords = viewportCoordsToSceneCoords(\r\n {\r\n clientX: viewTransformations.offsetLeft,\r\n clientY: viewTransformations.offsetTop,\r\n },\r\n viewTransformations,\r\n );\r\n const bottomRightSceneCoords = viewportCoordsToSceneCoords(\r\n {\r\n clientX: viewTransformations.offsetLeft + width,\r\n clientY: viewTransformations.offsetTop + height,\r\n },\r\n viewTransformations,\r\n );\r\n\r\n return (\r\n topLeftSceneCoords.x <= x2 &&\r\n topLeftSceneCoords.y <= y2 &&\r\n bottomRightSceneCoords.x >= x1 &&\r\n bottomRightSceneCoords.y >= y1\r\n );\r\n};\r\n\r\nexport const isElementCompletelyInViewport = (\r\n elements: ExcalidrawElement[],\r\n width: number,\r\n height: number,\r\n viewTransformations: {\r\n zoom: Zoom;\r\n offsetLeft: number;\r\n offsetTop: number;\r\n scrollX: number;\r\n scrollY: number;\r\n },\r\n elementsMap: ElementsMap,\r\n padding?: Offsets,\r\n) => {\r\n const [x1, y1, x2, y2] = getCommonBounds(elements, elementsMap); // scene coordinates\r\n const topLeftSceneCoords = viewportCoordsToSceneCoords(\r\n {\r\n clientX: viewTransformations.offsetLeft + (padding?.left || 0),\r\n clientY: viewTransformations.offsetTop + (padding?.top || 0),\r\n },\r\n viewTransformations,\r\n );\r\n const bottomRightSceneCoords = viewportCoordsToSceneCoords(\r\n {\r\n clientX: viewTransformations.offsetLeft + width - (padding?.right || 0),\r\n clientY: viewTransformations.offsetTop + height - (padding?.bottom || 0),\r\n },\r\n viewTransformations,\r\n );\r\n\r\n return (\r\n x1 >= topLeftSceneCoords.x &&\r\n y1 >= topLeftSceneCoords.y &&\r\n x2 <= bottomRightSceneCoords.x &&\r\n y2 <= bottomRightSceneCoords.y\r\n );\r\n};\r\n\r\n/**\r\n * Makes a perfect shape or diagonal/horizontal/vertical line\r\n */\r\nexport const getPerfectElementSize = (\r\n elementType: AppState[\"activeTool\"][\"type\"],\r\n width: number,\r\n height: number,\r\n): { width: number; height: number } => {\r\n const absWidth = Math.abs(width);\r\n const absHeight = Math.abs(height);\r\n\r\n if (\r\n elementType === \"line\" ||\r\n elementType === \"arrow\" ||\r\n elementType === \"freedraw\"\r\n ) {\r\n const lockedAngle =\r\n Math.round(Math.atan(absHeight / absWidth) / SHIFT_LOCKING_ANGLE) *\r\n SHIFT_LOCKING_ANGLE;\r\n if (lockedAngle === 0) {\r\n height = 0;\r\n } else if (lockedAngle === Math.PI / 2) {\r\n width = 0;\r\n } else {\r\n height = absWidth * Math.tan(lockedAngle) * Math.sign(height) || height;\r\n }\r\n } else if (elementType !== \"selection\") {\r\n height = absWidth * Math.sign(height);\r\n }\r\n return { width, height };\r\n};\r\n\r\nexport const getLockedLinearCursorAlignSize = (\r\n originX: number,\r\n originY: number,\r\n x: number,\r\n y: number,\r\n customAngle?: number,\r\n) => {\r\n let width = x - originX;\r\n let height = y - originY;\r\n\r\n const angle = Math.atan2(height, width) as Radians;\r\n let lockedAngle = (Math.round(angle / SHIFT_LOCKING_ANGLE) *\r\n SHIFT_LOCKING_ANGLE) as Radians;\r\n\r\n if (customAngle) {\r\n // If custom angle is provided, we check if the angle is close to the\r\n // custom angle, snap to that if close engough, otherwise snap to the\r\n // higher or lower angle depending on the current angle vs custom angle.\r\n const lower = (Math.floor(customAngle / SHIFT_LOCKING_ANGLE) *\r\n SHIFT_LOCKING_ANGLE) as Radians;\r\n if (\r\n radiansBetweenAngles(\r\n angle,\r\n lower,\r\n (lower + SHIFT_LOCKING_ANGLE) as Radians,\r\n )\r\n ) {\r\n if (\r\n radiansDifference(angle, customAngle as Radians) <\r\n SHIFT_LOCKING_ANGLE / 6\r\n ) {\r\n lockedAngle = customAngle as Radians;\r\n } else if (\r\n normalizeRadians(angle) > normalizeRadians(customAngle as Radians)\r\n ) {\r\n lockedAngle = (lower + SHIFT_LOCKING_ANGLE) as Radians;\r\n } else {\r\n lockedAngle = lower;\r\n }\r\n }\r\n }\r\n\r\n if (lockedAngle === 0) {\r\n height = 0;\r\n } else if (lockedAngle === Math.PI / 2) {\r\n width = 0;\r\n } else {\r\n // locked angle line, y = mx + b => mx - y + b = 0\r\n const a1 = Math.tan(lockedAngle);\r\n const b1 = -1;\r\n const c1 = originY - a1 * originX;\r\n\r\n // line through cursor, perpendicular to locked angle line\r\n const a2 = -1 / a1;\r\n const b2 = -1;\r\n const c2 = y - a2 * x;\r\n\r\n // intersection of the two lines above\r\n const intersectX = (b1 * c2 - b2 * c1) / (a1 * b2 - a2 * b1);\r\n const intersectY = (c1 * a2 - c2 * a1) / (a1 * b2 - a2 * b1);\r\n\r\n // delta\r\n width = intersectX - originX;\r\n height = intersectY - originY;\r\n }\r\n\r\n return { width, height };\r\n};\r\n\r\nexport const getNormalizedDimensions = (\r\n element: Pick<ExcalidrawElement, \"width\" | \"height\" | \"x\" | \"y\">,\r\n): {\r\n width: ExcalidrawElement[\"width\"];\r\n height: ExcalidrawElement[\"height\"];\r\n x: ExcalidrawElement[\"x\"];\r\n y: ExcalidrawElement[\"y\"];\r\n} => {\r\n const ret = {\r\n width: element.width,\r\n height: element.height,\r\n x: element.x,\r\n y: element.y,\r\n };\r\n\r\n if (element.width < 0) {\r\n const nextWidth = Math.abs(element.width);\r\n ret.width = nextWidth;\r\n ret.x = element.x - nextWidth;\r\n }\r\n\r\n if (element.height < 0) {\r\n const nextHeight = Math.abs(element.height);\r\n ret.height = nextHeight;\r\n ret.y = element.y - nextHeight;\r\n }\r\n\r\n return ret;\r\n};\r\n", "import rough from \"roughjs/bin/rough\";\r\n\r\nimport {\r\n arrayToMap,\r\n type Bounds,\r\n invariant,\r\n rescalePoints,\r\n sizeOf,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n degreesToRadians,\r\n lineSegment,\r\n pointDistance,\r\n pointFrom,\r\n pointFromArray,\r\n pointRotateRads,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport { getCurvePathOps } from \"@excalidraw/utils/shape\";\r\n\r\nimport { pointsOnBezierCurves } from \"points-on-curve\";\r\n\r\nimport type {\r\n Curve,\r\n Degrees,\r\n GlobalPoint,\r\n LineSegment,\r\n LocalPoint,\r\n Radians,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type { Mutable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport { generateRoughOptions } from \"./shape\";\r\nimport { ShapeCache } from \"./shape\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\r\nimport {\r\n isArrowElement,\r\n isBoundToContainer,\r\n isFreeDrawElement,\r\n isLinearElement,\r\n isLineElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport { getElementShape } from \"./shape\";\r\n\r\nimport {\r\n deconstructDiamondElement,\r\n deconstructRectanguloidElement,\r\n} from \"./utils\";\r\n\r\nimport type { Drawable, Op } from \"roughjs/bin/core\";\r\nimport type { Point as RoughPoint } from \"roughjs/bin/geometry\";\r\nimport type {\r\n Arrowhead,\r\n ElementsMap,\r\n ElementsMapOrArray,\r\n ExcalidrawElement,\r\n ExcalidrawEllipseElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawRectanguloidElement,\r\n ExcalidrawTextElementWithContainer,\r\n NonDeleted,\r\n} from \"./types\";\r\n\r\nexport type RectangleBox = {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n angle: number;\r\n};\r\n\r\ntype MaybeQuadraticSolution = [number | null, number | null] | false;\r\n\r\nexport type SceneBounds = readonly [\r\n sceneX: number,\r\n sceneY: number,\r\n sceneX2: number,\r\n sceneY2: number,\r\n];\r\n\r\nexport class ElementBounds {\r\n private static boundsCache = new WeakMap<\r\n ExcalidrawElement,\r\n {\r\n bounds: Bounds;\r\n version: ExcalidrawElement[\"version\"];\r\n }\r\n >();\r\n private static nonRotatedBoundsCache = new WeakMap<\r\n ExcalidrawElement,\r\n {\r\n bounds: Bounds;\r\n version: ExcalidrawElement[\"version\"];\r\n }\r\n >();\r\n\r\n static getBounds(\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n nonRotated: boolean = false,\r\n ) {\r\n const cachedBounds =\r\n nonRotated && element.angle !== 0\r\n ? ElementBounds.nonRotatedBoundsCache.get(element)\r\n : ElementBounds.boundsCache.get(element);\r\n\r\n if (\r\n cachedBounds?.version &&\r\n cachedBounds.version === element.version &&\r\n // we don't invalidate cache when we update containers and not labels,\r\n // which is causing problems down the line. Fix TBA.\r\n !isBoundToContainer(element)\r\n ) {\r\n return cachedBounds.bounds;\r\n }\r\n\r\n if (nonRotated && element.angle !== 0) {\r\n const nonRotatedBounds = ElementBounds.calculateBounds(\r\n {\r\n ...element,\r\n angle: 0 as Radians,\r\n },\r\n elementsMap,\r\n );\r\n ElementBounds.nonRotatedBoundsCache.set(element, {\r\n version: element.version,\r\n bounds: nonRotatedBounds,\r\n });\r\n\r\n return nonRotatedBounds;\r\n }\r\n\r\n const bounds = ElementBounds.calculateBounds(element, elementsMap);\r\n\r\n ElementBounds.boundsCache.set(element, {\r\n version: element.version,\r\n bounds,\r\n });\r\n\r\n return bounds;\r\n }\r\n\r\n private static calculateBounds(\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n ): Bounds {\r\n let bounds: Bounds;\r\n\r\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\r\n element,\r\n elementsMap,\r\n );\r\n if (isFreeDrawElement(element)) {\r\n const [minX, minY, maxX, maxY] = getBoundsFromPoints(\r\n element.points.map(([x, y]) =>\r\n pointRotateRads(\r\n pointFrom(x, y),\r\n pointFrom(cx - element.x, cy - element.y),\r\n element.angle,\r\n ),\r\n ),\r\n );\r\n\r\n return [\r\n minX + element.x,\r\n minY + element.y,\r\n maxX + element.x,\r\n maxY + element.y,\r\n ];\r\n } else if (isLinearElement(element)) {\r\n bounds = getLinearElementRotatedBounds(element, cx, cy, elementsMap);\r\n } else if (element.type === \"diamond\") {\r\n const [x11, y11] = pointRotateRads(\r\n pointFrom(cx, y1),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const [x12, y12] = pointRotateRads(\r\n pointFrom(cx, y2),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const [x22, y22] = pointRotateRads(\r\n pointFrom(x1, cy),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const [x21, y21] = pointRotateRads(\r\n pointFrom(x2, cy),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const minX = Math.min(x11, x12, x22, x21);\r\n const minY = Math.min(y11, y12, y22, y21);\r\n const maxX = Math.max(x11, x12, x22, x21);\r\n const maxY = Math.max(y11, y12, y22, y21);\r\n bounds = [minX, minY, maxX, maxY];\r\n } else if (element.type === \"ellipse\") {\r\n const w = (x2 - x1) / 2;\r\n const h = (y2 - y1) / 2;\r\n const cos = Math.cos(element.angle);\r\n const sin = Math.sin(element.angle);\r\n const ww = Math.hypot(w * cos, h * sin);\r\n const hh = Math.hypot(h * cos, w * sin);\r\n bounds = [cx - ww, cy - hh, cx + ww, cy + hh];\r\n } else {\r\n const [x11, y11] = pointRotateRads(\r\n pointFrom(x1, y1),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const [x12, y12] = pointRotateRads(\r\n pointFrom(x1, y2),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const [x22, y22] = pointRotateRads(\r\n pointFrom(x2, y2),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const [x21, y21] = pointRotateRads(\r\n pointFrom(x2, y1),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const minX = Math.min(x11, x12, x22, x21);\r\n const minY = Math.min(y11, y12, y22, y21);\r\n const maxX = Math.max(x11, x12, x22, x21);\r\n const maxY = Math.max(y11, y12, y22, y21);\r\n bounds = [minX, minY, maxX, maxY];\r\n }\r\n\r\n return bounds;\r\n }\r\n}\r\n\r\n// Scene -> Scene coords, but in x1,x2,y1,y2 format.\r\n//\r\n// If the element is created from right to left, the width is going to be negative\r\n// This set of functions retrieves the absolute position of the 4 points.\r\nexport const getElementAbsoluteCoords = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n includeBoundText: boolean = false,\r\n): [number, number, number, number, number, number] => {\r\n if (isFreeDrawElement(element)) {\r\n return getFreeDrawElementAbsoluteCoords(element);\r\n } else if (isLinearElement(element)) {\r\n return LinearElementEditor.getElementAbsoluteCoords(\r\n element,\r\n elementsMap,\r\n includeBoundText,\r\n );\r\n } else if (isTextElement(element)) {\r\n const container = elementsMap\r\n ? getContainerElement(element, elementsMap)\r\n : null;\r\n if (isArrowElement(container)) {\r\n const { x, y } = LinearElementEditor.getBoundTextElementPosition(\r\n container,\r\n element as ExcalidrawTextElementWithContainer,\r\n elementsMap,\r\n );\r\n return [\r\n x,\r\n y,\r\n x + element.width,\r\n y + element.height,\r\n x + element.width / 2,\r\n y + element.height / 2,\r\n ];\r\n }\r\n }\r\n return [\r\n element.x,\r\n element.y,\r\n element.x + element.width,\r\n element.y + element.height,\r\n element.x + element.width / 2,\r\n element.y + element.height / 2,\r\n ];\r\n};\r\n\r\n/*\r\n * for a given element, `getElementLineSegments` returns line segments\r\n * that can be used for visual collision detection (useful for frames)\r\n * as opposed to bounding box collision detection\r\n */\r\n/**\r\n * Given an element, return the line segments that make up the element.\r\n *\r\n * Uses helpers from /math\r\n */\r\nexport const getElementLineSegments = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n): LineSegment<GlobalPoint>[] => {\r\n const shape = getElementShape(element, elementsMap);\r\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\r\n element,\r\n elementsMap,\r\n );\r\n const center = pointFrom<GlobalPoint>(cx, cy);\r\n\r\n if (shape.type === \"polycurve\") {\r\n const curves = shape.data;\r\n const pointsOnCurves = curves.map((curve) =>\r\n pointsOnBezierCurves(curve, 10),\r\n );\r\n\r\n const segments: LineSegment<GlobalPoint>[] = [];\r\n\r\n if (\r\n (isLineElement(element) && !element.polygon) ||\r\n isArrowElement(element)\r\n ) {\r\n for (const points of pointsOnCurves) {\r\n let i = 0;\r\n\r\n while (i < points.length - 1) {\r\n segments.push(\r\n lineSegment(\r\n pointFrom(points[i][0], points[i][1]),\r\n pointFrom(points[i + 1][0], points[i + 1][1]),\r\n ),\r\n );\r\n i++;\r\n }\r\n }\r\n } else {\r\n const points = pointsOnCurves.flat();\r\n let i = 0;\r\n\r\n while (i < points.length - 1) {\r\n segments.push(\r\n lineSegment(\r\n pointFrom(points[i][0], points[i][1]),\r\n pointFrom(points[i + 1][0], points[i + 1][1]),\r\n ),\r\n );\r\n i++;\r\n }\r\n }\r\n\r\n return segments;\r\n } else if (shape.type === \"polyline\") {\r\n return shape.data as LineSegment<GlobalPoint>[];\r\n } else if (_isRectanguloidElement(element)) {\r\n const [sides, corners] = deconstructRectanguloidElement(element);\r\n const cornerSegments: LineSegment<GlobalPoint>[] = corners\r\n .map((corner) => getSegmentsOnCurve(corner, center, element.angle))\r\n .flat();\r\n const rotatedSides = getRotatedSides(sides, center, element.angle);\r\n return [...rotatedSides, ...cornerSegments];\r\n } else if (element.type === \"diamond\") {\r\n const [sides, corners] = deconstructDiamondElement(element);\r\n const cornerSegments = corners\r\n .map((corner) => getSegmentsOnCurve(corner, center, element.angle))\r\n .flat();\r\n const rotatedSides = getRotatedSides(sides, center, element.angle);\r\n\r\n return [...rotatedSides, ...cornerSegments];\r\n } else if (shape.type === \"polygon\") {\r\n if (isTextElement(element)) {\r\n const container = getContainerElement(element, elementsMap);\r\n if (container && isLinearElement(container)) {\r\n const segments: LineSegment<GlobalPoint>[] = [\r\n lineSegment(pointFrom(x1, y1), pointFrom(x2, y1)),\r\n lineSegment(pointFrom(x2, y1), pointFrom(x2, y2)),\r\n lineSegment(pointFrom(x2, y2), pointFrom(x1, y2)),\r\n lineSegment(pointFrom(x1, y2), pointFrom(x1, y1)),\r\n ];\r\n return segments;\r\n }\r\n }\r\n\r\n const points = shape.data as GlobalPoint[];\r\n const segments: LineSegment<GlobalPoint>[] = [];\r\n for (let i = 0; i < points.length - 1; i++) {\r\n segments.push(lineSegment(points[i], points[i + 1]));\r\n }\r\n return segments;\r\n } else if (shape.type === \"ellipse\") {\r\n return getSegmentsOnEllipse(element as ExcalidrawEllipseElement);\r\n }\r\n\r\n const [nw, ne, sw, se, , , w, e] = (\r\n [\r\n [x1, y1],\r\n [x2, y1],\r\n [x1, y2],\r\n [x2, y2],\r\n [cx, y1],\r\n [cx, y2],\r\n [x1, cy],\r\n [x2, cy],\r\n ] as GlobalPoint[]\r\n ).map((point) => pointRotateRads(point, center, element.angle));\r\n\r\n return [\r\n lineSegment(nw, ne),\r\n lineSegment(sw, se),\r\n lineSegment(nw, sw),\r\n lineSegment(ne, se),\r\n lineSegment(nw, e),\r\n lineSegment(sw, e),\r\n lineSegment(ne, w),\r\n lineSegment(se, w),\r\n ];\r\n};\r\n\r\nconst _isRectanguloidElement = (\r\n element: ExcalidrawElement,\r\n): element is ExcalidrawRectanguloidElement => {\r\n return (\r\n element != null &&\r\n (element.type === \"rectangle\" ||\r\n element.type === \"image\" ||\r\n element.type === \"iframe\" ||\r\n element.type === \"embeddable\" ||\r\n element.type === \"frame\" ||\r\n element.type === \"magicframe\" ||\r\n (element.type === \"text\" && !element.containerId))\r\n );\r\n};\r\n\r\nconst getRotatedSides = (\r\n sides: LineSegment<GlobalPoint>[],\r\n center: GlobalPoint,\r\n angle: Radians,\r\n) => {\r\n return sides.map((side) => {\r\n return lineSegment(\r\n pointRotateRads<GlobalPoint>(side[0], center, angle),\r\n pointRotateRads<GlobalPoint>(side[1], center, angle),\r\n );\r\n });\r\n};\r\n\r\nconst getSegmentsOnCurve = (\r\n curve: Curve<GlobalPoint>,\r\n center: GlobalPoint,\r\n angle: Radians,\r\n): LineSegment<GlobalPoint>[] => {\r\n const points = pointsOnBezierCurves(curve, 10);\r\n let i = 0;\r\n const segments: LineSegment<GlobalPoint>[] = [];\r\n while (i < points.length - 1) {\r\n segments.push(\r\n lineSegment(\r\n pointRotateRads<GlobalPoint>(\r\n pointFrom(points[i][0], points[i][1]),\r\n center,\r\n angle,\r\n ),\r\n pointRotateRads<GlobalPoint>(\r\n pointFrom(points[i + 1][0], points[i + 1][1]),\r\n center,\r\n angle,\r\n ),\r\n ),\r\n );\r\n i++;\r\n }\r\n\r\n return segments;\r\n};\r\n\r\nconst getSegmentsOnEllipse = (\r\n ellipse: ExcalidrawEllipseElement,\r\n): LineSegment<GlobalPoint>[] => {\r\n const center = pointFrom<GlobalPoint>(\r\n ellipse.x + ellipse.width / 2,\r\n ellipse.y + ellipse.height / 2,\r\n );\r\n\r\n const a = ellipse.width / 2;\r\n const b = ellipse.height / 2;\r\n\r\n const segments: LineSegment<GlobalPoint>[] = [];\r\n const points: GlobalPoint[] = [];\r\n const n = 90;\r\n const deltaT = (Math.PI * 2) / n;\r\n\r\n for (let i = 0; i < n; i++) {\r\n const t = i * deltaT;\r\n const x = center[0] + a * Math.cos(t);\r\n const y = center[1] + b * Math.sin(t);\r\n points.push(pointRotateRads(pointFrom(x, y), center, ellipse.angle));\r\n }\r\n\r\n for (let i = 0; i < points.length - 1; i++) {\r\n segments.push(lineSegment(points[i], points[i + 1]));\r\n }\r\n\r\n segments.push(lineSegment(points[points.length - 1], points[0]));\r\n return segments;\r\n};\r\n\r\n/**\r\n * Scene -> Scene coords, but in x1,x2,y1,y2 format.\r\n *\r\n * Rectangle here means any rectangular frame, not an excalidraw element.\r\n */\r\nexport const getRectangleBoxAbsoluteCoords = (boxSceneCoords: RectangleBox) => {\r\n return [\r\n boxSceneCoords.x,\r\n boxSceneCoords.y,\r\n boxSceneCoords.x + boxSceneCoords.width,\r\n boxSceneCoords.y + boxSceneCoords.height,\r\n boxSceneCoords.x + boxSceneCoords.width / 2,\r\n boxSceneCoords.y + boxSceneCoords.height / 2,\r\n ];\r\n};\r\n\r\nexport const getDiamondPoints = (element: ExcalidrawElement) => {\r\n // Here we add +1 to avoid these numbers to be 0\r\n // otherwise rough.js will throw an error complaining about it\r\n const topX = Math.floor(element.width / 2) + 1;\r\n const topY = 0;\r\n const rightX = element.width;\r\n const rightY = Math.floor(element.height / 2) + 1;\r\n const bottomX = topX;\r\n const bottomY = element.height;\r\n const leftX = 0;\r\n const leftY = rightY;\r\n\r\n return [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY];\r\n};\r\n\r\n// reference: https://eliot-jones.com/2019/12/cubic-bezier-curve-bounding-boxes\r\nconst getBezierValueForT = (\r\n t: number,\r\n p0: number,\r\n p1: number,\r\n p2: number,\r\n p3: number,\r\n) => {\r\n const oneMinusT = 1 - t;\r\n return (\r\n Math.pow(oneMinusT, 3) * p0 +\r\n 3 * Math.pow(oneMinusT, 2) * t * p1 +\r\n 3 * oneMinusT * Math.pow(t, 2) * p2 +\r\n Math.pow(t, 3) * p3\r\n );\r\n};\r\n\r\nconst solveQuadratic = (\r\n p0: number,\r\n p1: number,\r\n p2: number,\r\n p3: number,\r\n): MaybeQuadraticSolution => {\r\n const i = p1 - p0;\r\n const j = p2 - p1;\r\n const k = p3 - p2;\r\n\r\n const a = 3 * i - 6 * j + 3 * k;\r\n const b = 6 * j - 6 * i;\r\n const c = 3 * i;\r\n\r\n const sqrtPart = b * b - 4 * a * c;\r\n const hasSolution = sqrtPart >= 0;\r\n\r\n if (!hasSolution) {\r\n return false;\r\n }\r\n\r\n let s1 = null;\r\n let s2 = null;\r\n\r\n let t1 = Infinity;\r\n let t2 = Infinity;\r\n\r\n if (a === 0) {\r\n t1 = t2 = -c / b;\r\n } else {\r\n t1 = (-b + Math.sqrt(sqrtPart)) / (2 * a);\r\n t2 = (-b - Math.sqrt(sqrtPart)) / (2 * a);\r\n }\r\n\r\n if (t1 >= 0 && t1 <= 1) {\r\n s1 = getBezierValueForT(t1, p0, p1, p2, p3);\r\n }\r\n\r\n if (t2 >= 0 && t2 <= 1) {\r\n s2 = getBezierValueForT(t2, p0, p1, p2, p3);\r\n }\r\n\r\n return [s1, s2];\r\n};\r\n\r\nexport const getCubicBezierCurveBound = (\r\n p0: GlobalPoint,\r\n p1: GlobalPoint,\r\n p2: GlobalPoint,\r\n p3: GlobalPoint,\r\n): Bounds => {\r\n const solX = solveQuadratic(p0[0], p1[0], p2[0], p3[0]);\r\n const solY = solveQuadratic(p0[1], p1[1], p2[1], p3[1]);\r\n\r\n let minX = Math.min(p0[0], p3[0]);\r\n let maxX = Math.max(p0[0], p3[0]);\r\n\r\n if (solX) {\r\n const xs = solX.filter((x) => x !== null) as number[];\r\n minX = Math.min(minX, ...xs);\r\n maxX = Math.max(maxX, ...xs);\r\n }\r\n\r\n let minY = Math.min(p0[1], p3[1]);\r\n let maxY = Math.max(p0[1], p3[1]);\r\n if (solY) {\r\n const ys = solY.filter((y) => y !== null) as number[];\r\n minY = Math.min(minY, ...ys);\r\n maxY = Math.max(maxY, ...ys);\r\n }\r\n return [minX, minY, maxX, maxY];\r\n};\r\n\r\nexport const getMinMaxXYFromCurvePathOps = (\r\n ops: Op[],\r\n transformXY?: (p: GlobalPoint) => GlobalPoint,\r\n): Bounds => {\r\n let currentP: GlobalPoint = pointFrom(0, 0);\r\n\r\n const { minX, minY, maxX, maxY } = ops.reduce(\r\n (limits, { op, data }) => {\r\n // There are only four operation types:\r\n // move, bcurveTo, lineTo, and curveTo\r\n if (op === \"move\") {\r\n // change starting point\r\n const p: GlobalPoint | undefined = pointFromArray(data);\r\n invariant(p != null, \"Op data is not a point\");\r\n currentP = p;\r\n // move operation does not draw anything; so, it always\r\n // returns false\r\n } else if (op === \"bcurveTo\") {\r\n const _p1 = pointFrom<GlobalPoint>(data[0], data[1]);\r\n const _p2 = pointFrom<GlobalPoint>(data[2], data[3]);\r\n const _p3 = pointFrom<GlobalPoint>(data[4], data[5]);\r\n\r\n const p1 = transformXY ? transformXY(_p1) : _p1;\r\n const p2 = transformXY ? transformXY(_p2) : _p2;\r\n const p3 = transformXY ? transformXY(_p3) : _p3;\r\n\r\n const p0 = transformXY ? transformXY(currentP) : currentP;\r\n currentP = _p3;\r\n\r\n const [minX, minY, maxX, maxY] = getCubicBezierCurveBound(\r\n p0,\r\n p1,\r\n p2,\r\n p3,\r\n );\r\n\r\n limits.minX = Math.min(limits.minX, minX);\r\n limits.minY = Math.min(limits.minY, minY);\r\n\r\n limits.maxX = Math.max(limits.maxX, maxX);\r\n limits.maxY = Math.max(limits.maxY, maxY);\r\n } else if (op === \"lineTo\") {\r\n // TODO: Implement this\r\n } else if (op === \"qcurveTo\") {\r\n // TODO: Implement this\r\n }\r\n return limits;\r\n },\r\n { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },\r\n );\r\n return [minX, minY, maxX, maxY];\r\n};\r\n\r\nexport const getBoundsFromPoints = (\r\n points: ExcalidrawFreeDrawElement[\"points\"],\r\n): Bounds => {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const [x, y] of points) {\r\n minX = Math.min(minX, x);\r\n minY = Math.min(minY, y);\r\n maxX = Math.max(maxX, x);\r\n maxY = Math.max(maxY, y);\r\n }\r\n\r\n return [minX, minY, maxX, maxY];\r\n};\r\n\r\nconst getFreeDrawElementAbsoluteCoords = (\r\n element: ExcalidrawFreeDrawElement,\r\n): [number, number, number, number, number, number] => {\r\n const [minX, minY, maxX, maxY] = getBoundsFromPoints(element.points);\r\n const x1 = minX + element.x;\r\n const y1 = minY + element.y;\r\n const x2 = maxX + element.x;\r\n const y2 = maxY + element.y;\r\n return [x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2];\r\n};\r\n\r\n/** @returns number in pixels */\r\nexport const getArrowheadSize = (arrowhead: Arrowhead): number => {\r\n switch (arrowhead) {\r\n case \"arrow\":\r\n return 25;\r\n case \"diamond\":\r\n case \"diamond_outline\":\r\n return 12;\r\n case \"crowfoot_many\":\r\n case \"crowfoot_one\":\r\n case \"crowfoot_one_or_many\":\r\n return 20;\r\n default:\r\n return 15;\r\n }\r\n};\r\n\r\n/** @returns number in degrees */\r\nexport const getArrowheadAngle = (arrowhead: Arrowhead): Degrees => {\r\n switch (arrowhead) {\r\n case \"bar\":\r\n return 90 as Degrees;\r\n case \"arrow\":\r\n return 20 as Degrees;\r\n default:\r\n return 25 as Degrees;\r\n }\r\n};\r\n\r\nexport const getArrowheadPoints = (\r\n element: ExcalidrawLinearElement,\r\n shape: Drawable[],\r\n position: \"start\" | \"end\",\r\n arrowhead: Arrowhead,\r\n) => {\r\n if (shape.length < 1) {\r\n return null;\r\n }\r\n\r\n const ops = getCurvePathOps(shape[0]);\r\n if (ops.length < 1) {\r\n return null;\r\n }\r\n\r\n // The index of the bCurve operation to examine.\r\n const index = position === \"start\" ? 1 : ops.length - 1;\r\n\r\n const data = ops[index].data;\r\n\r\n invariant(data.length === 6, \"Op data length is not 6\");\r\n\r\n const p3 = pointFrom(data[4], data[5]);\r\n const p2 = pointFrom(data[2], data[3]);\r\n const p1 = pointFrom(data[0], data[1]);\r\n\r\n // We need to find p0 of the bezier curve.\r\n // It is typically the last point of the previous\r\n // curve; it can also be the position of moveTo operation.\r\n const prevOp = ops[index - 1];\r\n let p0 = pointFrom(0, 0);\r\n if (prevOp.op === \"move\") {\r\n const p = pointFromArray(prevOp.data);\r\n invariant(p != null, \"Op data is not a point\");\r\n p0 = p;\r\n } else if (prevOp.op === \"bcurveTo\") {\r\n p0 = pointFrom(prevOp.data[4], prevOp.data[5]);\r\n }\r\n\r\n // B(t) = p0 * (1-t)^3 + 3p1 * t * (1-t)^2 + 3p2 * t^2 * (1-t) + p3 * t^3\r\n const equation = (t: number, idx: number) =>\r\n Math.pow(1 - t, 3) * p3[idx] +\r\n 3 * t * Math.pow(1 - t, 2) * p2[idx] +\r\n 3 * Math.pow(t, 2) * (1 - t) * p1[idx] +\r\n p0[idx] * Math.pow(t, 3);\r\n\r\n // Ee know the last point of the arrow (or the first, if start arrowhead).\r\n const [x2, y2] = position === \"start\" ? p0 : p3;\r\n\r\n // By using cubic bezier equation (B(t)) and the given parameters,\r\n // we calculate a point that is closer to the last point.\r\n // The value 0.3 is chosen arbitrarily and it works best for all\r\n // the tested cases.\r\n const [x1, y1] = [equation(0.3, 0), equation(0.3, 1)];\r\n\r\n // Find the normalized direction vector based on the\r\n // previously calculated points.\r\n const distance = Math.hypot(x2 - x1, y2 - y1);\r\n const nx = (x2 - x1) / distance;\r\n const ny = (y2 - y1) / distance;\r\n\r\n const size = getArrowheadSize(arrowhead);\r\n\r\n let length = 0;\r\n\r\n {\r\n // Length for -> arrows is based on the length of the last section\r\n const [cx, cy] =\r\n position === \"end\"\r\n ? element.points[element.points.length - 1]\r\n : element.points[0];\r\n const [px, py] =\r\n element.points.length > 1\r\n ? position === \"end\"\r\n ? element.points[element.points.length - 2]\r\n : element.points[1]\r\n : [0, 0];\r\n\r\n length = Math.hypot(cx - px, cy - py);\r\n }\r\n\r\n // Scale down the arrowhead until we hit a certain size so that it doesn't look weird.\r\n // This value is selected by minimizing a minimum size with the last segment of the arrowhead\r\n const lengthMultiplier =\r\n arrowhead === \"diamond\" || arrowhead === \"diamond_outline\" ? 0.25 : 0.5;\r\n const minSize = Math.min(size, length * lengthMultiplier);\r\n const xs = x2 - nx * minSize;\r\n const ys = y2 - ny * minSize;\r\n\r\n if (\r\n arrowhead === \"dot\" ||\r\n arrowhead === \"circle\" ||\r\n arrowhead === \"circle_outline\"\r\n ) {\r\n const diameter = Math.hypot(ys - y2, xs - x2) + element.strokeWidth - 2;\r\n return [x2, y2, diameter];\r\n }\r\n\r\n const angle = getArrowheadAngle(arrowhead);\r\n\r\n if (arrowhead === \"crowfoot_many\" || arrowhead === \"crowfoot_one_or_many\") {\r\n // swap (xs, ys) with (x2, y2)\r\n const [x3, y3] = pointRotateRads(\r\n pointFrom(x2, y2),\r\n pointFrom(xs, ys),\r\n degreesToRadians(-angle as Degrees),\r\n );\r\n const [x4, y4] = pointRotateRads(\r\n pointFrom(x2, y2),\r\n pointFrom(xs, ys),\r\n degreesToRadians(angle),\r\n );\r\n return [xs, ys, x3, y3, x4, y4];\r\n }\r\n\r\n // Return points\r\n const [x3, y3] = pointRotateRads(\r\n pointFrom(xs, ys),\r\n pointFrom(x2, y2),\r\n ((-angle * Math.PI) / 180) as Radians,\r\n );\r\n const [x4, y4] = pointRotateRads(\r\n pointFrom(xs, ys),\r\n pointFrom(x2, y2),\r\n degreesToRadians(angle),\r\n );\r\n\r\n if (arrowhead === \"diamond\" || arrowhead === \"diamond_outline\") {\r\n // point opposite to the arrowhead point\r\n let ox;\r\n let oy;\r\n\r\n if (position === \"start\") {\r\n const [px, py] = element.points.length > 1 ? element.points[1] : [0, 0];\r\n\r\n [ox, oy] = pointRotateRads(\r\n pointFrom(x2 + minSize * 2, y2),\r\n pointFrom(x2, y2),\r\n Math.atan2(py - y2, px - x2) as Radians,\r\n );\r\n } else {\r\n const [px, py] =\r\n element.points.length > 1\r\n ? element.points[element.points.length - 2]\r\n : [0, 0];\r\n\r\n [ox, oy] = pointRotateRads(\r\n pointFrom(x2 - minSize * 2, y2),\r\n pointFrom(x2, y2),\r\n Math.atan2(y2 - py, x2 - px) as Radians,\r\n );\r\n }\r\n\r\n return [x2, y2, x3, y3, ox, oy, x4, y4];\r\n }\r\n\r\n return [x2, y2, x3, y3, x4, y4];\r\n};\r\n\r\nconst generateLinearElementShape = (\r\n element: ExcalidrawLinearElement,\r\n): Drawable => {\r\n const generator = rough.generator();\r\n const options = generateRoughOptions(element);\r\n\r\n const method = (() => {\r\n if (element.roundness) {\r\n return \"curve\";\r\n }\r\n if (options.fill) {\r\n return \"polygon\";\r\n }\r\n return \"linearPath\";\r\n })();\r\n\r\n return generator[method](\r\n element.points as Mutable<LocalPoint>[] as RoughPoint[],\r\n options,\r\n );\r\n};\r\n\r\nconst getLinearElementRotatedBounds = (\r\n element: ExcalidrawLinearElement,\r\n cx: number,\r\n cy: number,\r\n elementsMap: ElementsMap,\r\n): Bounds => {\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n\r\n if (element.points.length < 2) {\r\n const [pointX, pointY] = element.points[0];\r\n const [x, y] = pointRotateRads(\r\n pointFrom(element.x + pointX, element.y + pointY),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n\r\n let coords: Bounds = [x, y, x, y];\r\n if (boundTextElement) {\r\n const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText(\r\n element,\r\n elementsMap,\r\n [x, y, x, y],\r\n boundTextElement,\r\n );\r\n coords = [\r\n coordsWithBoundText[0],\r\n coordsWithBoundText[1],\r\n coordsWithBoundText[2],\r\n coordsWithBoundText[3],\r\n ];\r\n }\r\n return coords;\r\n }\r\n\r\n // first element is always the curve\r\n const cachedShape = ShapeCache.get(element)?.[0];\r\n const shape = cachedShape ?? generateLinearElementShape(element);\r\n const ops = getCurvePathOps(shape);\r\n const transformXY = ([x, y]: GlobalPoint) =>\r\n pointRotateRads<GlobalPoint>(\r\n pointFrom(element.x + x, element.y + y),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n const res = getMinMaxXYFromCurvePathOps(ops, transformXY);\r\n let coords: Bounds = [res[0], res[1], res[2], res[3]];\r\n if (boundTextElement) {\r\n const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText(\r\n element,\r\n elementsMap,\r\n coords,\r\n boundTextElement,\r\n );\r\n coords = [\r\n coordsWithBoundText[0],\r\n coordsWithBoundText[1],\r\n coordsWithBoundText[2],\r\n coordsWithBoundText[3],\r\n ];\r\n }\r\n return coords;\r\n};\r\n\r\nexport const getElementBounds = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n nonRotated: boolean = false,\r\n): Bounds => {\r\n return ElementBounds.getBounds(element, elementsMap, nonRotated);\r\n};\r\n\r\nexport const getCommonBounds = (\r\n elements: ElementsMapOrArray,\r\n elementsMap?: ElementsMap,\r\n): Bounds => {\r\n if (!sizeOf(elements)) {\r\n return [0, 0, 0, 0];\r\n }\r\n\r\n let minX = Infinity;\r\n let maxX = -Infinity;\r\n let minY = Infinity;\r\n let maxY = -Infinity;\r\n\r\n const _elementsMap = elementsMap || arrayToMap(elements);\r\n\r\n elements.forEach((element) => {\r\n const [x1, y1, x2, y2] = getElementBounds(element, _elementsMap);\r\n minX = Math.min(minX, x1);\r\n minY = Math.min(minY, y1);\r\n maxX = Math.max(maxX, x2);\r\n maxY = Math.max(maxY, y2);\r\n });\r\n\r\n return [minX, minY, maxX, maxY];\r\n};\r\n\r\nexport const getDraggedElementsBounds = (\r\n elements: ExcalidrawElement[],\r\n dragOffset: { x: number; y: number },\r\n) => {\r\n const [minX, minY, maxX, maxY] = getCommonBounds(elements);\r\n return [\r\n minX + dragOffset.x,\r\n minY + dragOffset.y,\r\n maxX + dragOffset.x,\r\n maxY + dragOffset.y,\r\n ];\r\n};\r\n\r\nexport const getResizedElementAbsoluteCoords = (\r\n element: ExcalidrawElement,\r\n nextWidth: number,\r\n nextHeight: number,\r\n normalizePoints: boolean,\r\n): Bounds => {\r\n if (!(isLinearElement(element) || isFreeDrawElement(element))) {\r\n return [\r\n element.x,\r\n element.y,\r\n element.x + nextWidth,\r\n element.y + nextHeight,\r\n ];\r\n }\r\n\r\n const points = rescalePoints(\r\n 0,\r\n nextWidth,\r\n rescalePoints(1, nextHeight, element.points, normalizePoints),\r\n normalizePoints,\r\n );\r\n\r\n let bounds: Bounds;\r\n\r\n if (isFreeDrawElement(element)) {\r\n // Free Draw\r\n bounds = getBoundsFromPoints(points);\r\n } else {\r\n // Line\r\n const gen = rough.generator();\r\n const curve = !element.roundness\r\n ? gen.linearPath(\r\n points as [number, number][],\r\n generateRoughOptions(element),\r\n )\r\n : gen.curve(points as [number, number][], generateRoughOptions(element));\r\n\r\n const ops = getCurvePathOps(curve);\r\n bounds = getMinMaxXYFromCurvePathOps(ops);\r\n }\r\n\r\n const [minX, minY, maxX, maxY] = bounds;\r\n return [\r\n minX + element.x,\r\n minY + element.y,\r\n maxX + element.x,\r\n maxY + element.y,\r\n ];\r\n};\r\n\r\nexport const getElementPointsCoords = (\r\n element: ExcalidrawLinearElement,\r\n points: readonly (readonly [number, number])[],\r\n): Bounds => {\r\n // This might be computationally heavey\r\n const gen = rough.generator();\r\n const curve =\r\n element.roundness == null\r\n ? gen.linearPath(\r\n points as [number, number][],\r\n generateRoughOptions(element),\r\n )\r\n : gen.curve(points as [number, number][], generateRoughOptions(element));\r\n const ops = getCurvePathOps(curve);\r\n const [minX, minY, maxX, maxY] = getMinMaxXYFromCurvePathOps(ops);\r\n return [\r\n minX + element.x,\r\n minY + element.y,\r\n maxX + element.x,\r\n maxY + element.y,\r\n ];\r\n};\r\n\r\nexport const getClosestElementBounds = (\r\n elements: readonly ExcalidrawElement[],\r\n from: { x: number; y: number },\r\n): Bounds => {\r\n if (!elements.length) {\r\n return [0, 0, 0, 0];\r\n }\r\n\r\n let minDistance = Infinity;\r\n let closestElement = elements[0];\r\n const elementsMap = arrayToMap(elements);\r\n elements.forEach((element) => {\r\n const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);\r\n const distance = pointDistance(\r\n pointFrom((x1 + x2) / 2, (y1 + y2) / 2),\r\n pointFrom(from.x, from.y),\r\n );\r\n\r\n if (distance < minDistance) {\r\n minDistance = distance;\r\n closestElement = element;\r\n }\r\n });\r\n\r\n return getElementBounds(closestElement, elementsMap);\r\n};\r\n\r\nexport interface BoundingBox {\r\n minX: number;\r\n minY: number;\r\n maxX: number;\r\n maxY: number;\r\n midX: number;\r\n midY: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\nexport const getCommonBoundingBox = (\r\n elements:\r\n | readonly ExcalidrawElement[]\r\n | readonly NonDeleted<ExcalidrawElement>[],\r\n): BoundingBox => {\r\n const [minX, minY, maxX, maxY] = getCommonBounds(elements);\r\n return {\r\n minX,\r\n minY,\r\n maxX,\r\n maxY,\r\n width: maxX - minX,\r\n height: maxY - minY,\r\n midX: (minX + maxX) / 2,\r\n midY: (minY + maxY) / 2,\r\n };\r\n};\r\n\r\n/**\r\n * returns scene coords of user's editor viewport (visible canvas area) bounds\r\n */\r\nexport const getVisibleSceneBounds = ({\r\n scrollX,\r\n scrollY,\r\n width,\r\n height,\r\n zoom,\r\n}: AppState): SceneBounds => {\r\n return [\r\n -scrollX,\r\n -scrollY,\r\n -scrollX + width / zoom.value,\r\n -scrollY + height / zoom.value,\r\n ];\r\n};\r\n\r\nexport const getCenterForBounds = (bounds: Bounds): GlobalPoint =>\r\n pointFrom(\r\n bounds[0] + (bounds[2] - bounds[0]) / 2,\r\n bounds[1] + (bounds[3] - bounds[1]) / 2,\r\n );\r\n\r\n/**\r\n * Get the axis-aligned bounding box for a given element\r\n */\r\nexport const aabbForElement = (\r\n element: Readonly<ExcalidrawElement>,\r\n elementsMap: ElementsMap,\r\n offset?: [number, number, number, number],\r\n) => {\r\n const bbox = {\r\n minX: element.x,\r\n minY: element.y,\r\n maxX: element.x + element.width,\r\n maxY: element.y + element.height,\r\n midX: element.x + element.width / 2,\r\n midY: element.y + element.height / 2,\r\n };\r\n\r\n const center = elementCenterPoint(element, elementsMap);\r\n const [topLeftX, topLeftY] = pointRotateRads(\r\n pointFrom(bbox.minX, bbox.minY),\r\n center,\r\n element.angle,\r\n );\r\n const [topRightX, topRightY] = pointRotateRads(\r\n pointFrom(bbox.maxX, bbox.minY),\r\n center,\r\n element.angle,\r\n );\r\n const [bottomRightX, bottomRightY] = pointRotateRads(\r\n pointFrom(bbox.maxX, bbox.maxY),\r\n center,\r\n element.angle,\r\n );\r\n const [bottomLeftX, bottomLeftY] = pointRotateRads(\r\n pointFrom(bbox.minX, bbox.maxY),\r\n center,\r\n element.angle,\r\n );\r\n\r\n const bounds = [\r\n Math.min(topLeftX, topRightX, bottomRightX, bottomLeftX),\r\n Math.min(topLeftY, topRightY, bottomRightY, bottomLeftY),\r\n Math.max(topLeftX, topRightX, bottomRightX, bottomLeftX),\r\n Math.max(topLeftY, topRightY, bottomRightY, bottomLeftY),\r\n ] as Bounds;\r\n\r\n if (offset) {\r\n const [topOffset, rightOffset, downOffset, leftOffset] = offset;\r\n return [\r\n bounds[0] - leftOffset,\r\n bounds[1] - topOffset,\r\n bounds[2] + rightOffset,\r\n bounds[3] + downOffset,\r\n ] as Bounds;\r\n }\r\n\r\n return bounds;\r\n};\r\n\r\nexport const pointInsideBounds = <P extends GlobalPoint | LocalPoint>(\r\n p: P,\r\n bounds: Bounds,\r\n): boolean =>\r\n p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];\r\n\r\nexport const doBoundsIntersect = (\r\n bounds1: Bounds | null,\r\n bounds2: Bounds | null,\r\n): boolean => {\r\n if (bounds1 == null || bounds2 == null) {\r\n return false;\r\n }\r\n\r\n const [minX1, minY1, maxX1, maxY1] = bounds1;\r\n const [minX2, minY2, maxX2, maxY2] = bounds2;\r\n\r\n return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;\r\n};\r\n\r\nexport const elementCenterPoint = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n xOffset: number = 0,\r\n yOffset: number = 0,\r\n) => {\r\n if (isLinearElement(element)) {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const [x, y] = pointFrom<GlobalPoint>((x1 + x2) / 2, (y1 + y2) / 2);\r\n\r\n return pointFrom<GlobalPoint>(x + xOffset, y + yOffset);\r\n }\r\n\r\n const [x, y] = getCenterForBounds(getElementBounds(element, elementsMap));\r\n\r\n return pointFrom<GlobalPoint>(x + xOffset, y + yOffset);\r\n};\r\n", "import { RoughCanvas } from './canvas';\nimport { RoughGenerator } from './generator';\nimport { RoughSVG } from './svg';\nexport default {\n canvas(canvas, config) {\n return new RoughCanvas(canvas, config);\n },\n svg(svg, config) {\n return new RoughSVG(svg, config);\n },\n generator(config) {\n return new RoughGenerator(config);\n },\n newSeed() {\n return RoughGenerator.newSeed();\n },\n};\n", "import { RoughGenerator } from './generator';\nexport class RoughCanvas {\n constructor(canvas, config) {\n this.canvas = canvas;\n this.ctx = this.canvas.getContext('2d');\n this.gen = new RoughGenerator(config);\n }\n draw(drawable) {\n const sets = drawable.sets || [];\n const o = drawable.options || this.getDefaultOptions();\n const ctx = this.ctx;\n const precision = drawable.options.fixedDecimalPlaceDigits;\n for (const drawing of sets) {\n switch (drawing.type) {\n case 'path':\n ctx.save();\n ctx.strokeStyle = o.stroke === 'none' ? 'transparent' : o.stroke;\n ctx.lineWidth = o.strokeWidth;\n if (o.strokeLineDash) {\n ctx.setLineDash(o.strokeLineDash);\n }\n if (o.strokeLineDashOffset) {\n ctx.lineDashOffset = o.strokeLineDashOffset;\n }\n this._drawToContext(ctx, drawing, precision);\n ctx.restore();\n break;\n case 'fillPath': {\n ctx.save();\n ctx.fillStyle = o.fill || '';\n const fillRule = (drawable.shape === 'curve' || drawable.shape === 'polygon' || drawable.shape === 'path') ? 'evenodd' : 'nonzero';\n this._drawToContext(ctx, drawing, precision, fillRule);\n ctx.restore();\n break;\n }\n case 'fillSketch':\n this.fillSketch(ctx, drawing, o);\n break;\n }\n }\n }\n fillSketch(ctx, drawing, o) {\n let fweight = o.fillWeight;\n if (fweight < 0) {\n fweight = o.strokeWidth / 2;\n }\n ctx.save();\n if (o.fillLineDash) {\n ctx.setLineDash(o.fillLineDash);\n }\n if (o.fillLineDashOffset) {\n ctx.lineDashOffset = o.fillLineDashOffset;\n }\n ctx.strokeStyle = o.fill || '';\n ctx.lineWidth = fweight;\n this._drawToContext(ctx, drawing, o.fixedDecimalPlaceDigits);\n ctx.restore();\n }\n _drawToContext(ctx, drawing, fixedDecimals, rule = 'nonzero') {\n ctx.beginPath();\n for (const item of drawing.ops) {\n const data = ((typeof fixedDecimals === 'number') && fixedDecimals >= 0) ? (item.data.map((d) => +d.toFixed(fixedDecimals))) : item.data;\n switch (item.op) {\n case 'move':\n ctx.moveTo(data[0], data[1]);\n break;\n case 'bcurveTo':\n ctx.bezierCurveTo(data[0], data[1], data[2], data[3], data[4], data[5]);\n break;\n case 'lineTo':\n ctx.lineTo(data[0], data[1]);\n break;\n }\n }\n if (drawing.type === 'fillPath') {\n ctx.fill(rule);\n }\n else {\n ctx.stroke();\n }\n }\n get generator() {\n return this.gen;\n }\n getDefaultOptions() {\n return this.gen.defaultOptions;\n }\n line(x1, y1, x2, y2, options) {\n const d = this.gen.line(x1, y1, x2, y2, options);\n this.draw(d);\n return d;\n }\n rectangle(x, y, width, height, options) {\n const d = this.gen.rectangle(x, y, width, height, options);\n this.draw(d);\n return d;\n }\n ellipse(x, y, width, height, options) {\n const d = this.gen.ellipse(x, y, width, height, options);\n this.draw(d);\n return d;\n }\n circle(x, y, diameter, options) {\n const d = this.gen.circle(x, y, diameter, options);\n this.draw(d);\n return d;\n }\n linearPath(points, options) {\n const d = this.gen.linearPath(points, options);\n this.draw(d);\n return d;\n }\n polygon(points, options) {\n const d = this.gen.polygon(points, options);\n this.draw(d);\n return d;\n }\n arc(x, y, width, height, start, stop, closed = false, options) {\n const d = this.gen.arc(x, y, width, height, start, stop, closed, options);\n this.draw(d);\n return d;\n }\n curve(points, options) {\n const d = this.gen.curve(points, options);\n this.draw(d);\n return d;\n }\n path(d, options) {\n const drawing = this.gen.path(d, options);\n this.draw(drawing);\n return drawing;\n }\n}\n", "import { line, solidFillPolygon, patternFillPolygons, rectangle, ellipseWithParams, generateEllipseParams, linearPath, arc, patternFillArc, curve, svgPath } from './renderer.js';\nimport { randomSeed } from './math.js';\nimport { curveToBezier } from 'points-on-curve/lib/curve-to-bezier.js';\nimport { pointsOnBezierCurves } from 'points-on-curve';\nimport { pointsOnPath } from 'points-on-path';\nconst NOS = 'none';\nexport class RoughGenerator {\n constructor(config) {\n this.defaultOptions = {\n maxRandomnessOffset: 2,\n roughness: 1,\n bowing: 1,\n stroke: '#000',\n strokeWidth: 1,\n curveTightness: 0,\n curveFitting: 0.95,\n curveStepCount: 9,\n fillStyle: 'hachure',\n fillWeight: -1,\n hachureAngle: -41,\n hachureGap: -1,\n dashOffset: -1,\n dashGap: -1,\n zigzagOffset: -1,\n seed: 0,\n disableMultiStroke: false,\n disableMultiStrokeFill: false,\n preserveVertices: false,\n fillShapeRoughnessGain: 0.8,\n };\n this.config = config || {};\n if (this.config.options) {\n this.defaultOptions = this._o(this.config.options);\n }\n }\n static newSeed() {\n return randomSeed();\n }\n _o(options) {\n return options ? Object.assign({}, this.defaultOptions, options) : this.defaultOptions;\n }\n _d(shape, sets, options) {\n return { shape, sets: sets || [], options: options || this.defaultOptions };\n }\n line(x1, y1, x2, y2, options) {\n const o = this._o(options);\n return this._d('line', [line(x1, y1, x2, y2, o)], o);\n }\n rectangle(x, y, width, height, options) {\n const o = this._o(options);\n const paths = [];\n const outline = rectangle(x, y, width, height, o);\n if (o.fill) {\n const points = [[x, y], [x + width, y], [x + width, y + height], [x, y + height]];\n if (o.fillStyle === 'solid') {\n paths.push(solidFillPolygon([points], o));\n }\n else {\n paths.push(patternFillPolygons([points], o));\n }\n }\n if (o.stroke !== NOS) {\n paths.push(outline);\n }\n return this._d('rectangle', paths, o);\n }\n ellipse(x, y, width, height, options) {\n const o = this._o(options);\n const paths = [];\n const ellipseParams = generateEllipseParams(width, height, o);\n const ellipseResponse = ellipseWithParams(x, y, o, ellipseParams);\n if (o.fill) {\n if (o.fillStyle === 'solid') {\n const shape = ellipseWithParams(x, y, o, ellipseParams).opset;\n shape.type = 'fillPath';\n paths.push(shape);\n }\n else {\n paths.push(patternFillPolygons([ellipseResponse.estimatedPoints], o));\n }\n }\n if (o.stroke !== NOS) {\n paths.push(ellipseResponse.opset);\n }\n return this._d('ellipse', paths, o);\n }\n circle(x, y, diameter, options) {\n const ret = this.ellipse(x, y, diameter, diameter, options);\n ret.shape = 'circle';\n return ret;\n }\n linearPath(points, options) {\n const o = this._o(options);\n return this._d('linearPath', [linearPath(points, false, o)], o);\n }\n arc(x, y, width, height, start, stop, closed = false, options) {\n const o = this._o(options);\n const paths = [];\n const outline = arc(x, y, width, height, start, stop, closed, true, o);\n if (closed && o.fill) {\n if (o.fillStyle === 'solid') {\n const fillOptions = Object.assign({}, o);\n fillOptions.disableMultiStroke = true;\n const shape = arc(x, y, width, height, start, stop, true, false, fillOptions);\n shape.type = 'fillPath';\n paths.push(shape);\n }\n else {\n paths.push(patternFillArc(x, y, width, height, start, stop, o));\n }\n }\n if (o.stroke !== NOS) {\n paths.push(outline);\n }\n return this._d('arc', paths, o);\n }\n curve(points, options) {\n const o = this._o(options);\n const paths = [];\n const outline = curve(points, o);\n if (o.fill && o.fill !== NOS && points.length >= 3) {\n if (o.fillStyle === 'solid') {\n const fillShape = curve(points, Object.assign(Object.assign({}, o), { disableMultiStroke: true, roughness: o.roughness ? (o.roughness + o.fillShapeRoughnessGain) : 0 }));\n paths.push({\n type: 'fillPath',\n ops: this._mergedShape(fillShape.ops),\n });\n }\n else {\n const bcurve = curveToBezier(points);\n const polyPoints = pointsOnBezierCurves(bcurve, 10, (1 + o.roughness) / 2);\n paths.push(patternFillPolygons([polyPoints], o));\n }\n }\n if (o.stroke !== NOS) {\n paths.push(outline);\n }\n return this._d('curve', paths, o);\n }\n polygon(points, options) {\n const o = this._o(options);\n const paths = [];\n const outline = linearPath(points, true, o);\n if (o.fill) {\n if (o.fillStyle === 'solid') {\n paths.push(solidFillPolygon([points], o));\n }\n else {\n paths.push(patternFillPolygons([points], o));\n }\n }\n if (o.stroke !== NOS) {\n paths.push(outline);\n }\n return this._d('polygon', paths, o);\n }\n path(d, options) {\n const o = this._o(options);\n const paths = [];\n if (!d) {\n return this._d('path', paths, o);\n }\n d = (d || '').replace(/\\n/g, ' ').replace(/(-\\s)/g, '-').replace('/(\\s\\s)/g', ' ');\n const hasFill = o.fill && o.fill !== 'transparent' && o.fill !== NOS;\n const hasStroke = o.stroke !== NOS;\n const simplified = !!(o.simplification && (o.simplification < 1));\n const distance = simplified ? (4 - 4 * (o.simplification || 1)) : ((1 + o.roughness) / 2);\n const sets = pointsOnPath(d, 1, distance);\n const shape = svgPath(d, o);\n if (hasFill) {\n if (o.fillStyle === 'solid') {\n if (sets.length === 1) {\n const fillShape = svgPath(d, Object.assign(Object.assign({}, o), { disableMultiStroke: true, roughness: o.roughness ? (o.roughness + o.fillShapeRoughnessGain) : 0 }));\n paths.push({\n type: 'fillPath',\n ops: this._mergedShape(fillShape.ops),\n });\n }\n else {\n paths.push(solidFillPolygon(sets, o));\n }\n }\n else {\n paths.push(patternFillPolygons(sets, o));\n }\n }\n if (hasStroke) {\n if (simplified) {\n sets.forEach((set) => {\n paths.push(linearPath(set, false, o));\n });\n }\n else {\n paths.push(shape);\n }\n }\n return this._d('path', paths, o);\n }\n opsToPath(drawing, fixedDecimals) {\n let path = '';\n for (const item of drawing.ops) {\n const data = ((typeof fixedDecimals === 'number') && fixedDecimals >= 0) ? (item.data.map((d) => +d.toFixed(fixedDecimals))) : item.data;\n switch (item.op) {\n case 'move':\n path += `M${data[0]} ${data[1]} `;\n break;\n case 'bcurveTo':\n path += `C${data[0]} ${data[1]}, ${data[2]} ${data[3]}, ${data[4]} ${data[5]} `;\n break;\n case 'lineTo':\n path += `L${data[0]} ${data[1]} `;\n break;\n }\n }\n return path.trim();\n }\n toPaths(drawable) {\n const sets = drawable.sets || [];\n const o = drawable.options || this.defaultOptions;\n const paths = [];\n for (const drawing of sets) {\n let path = null;\n switch (drawing.type) {\n case 'path':\n path = {\n d: this.opsToPath(drawing),\n stroke: o.stroke,\n strokeWidth: o.strokeWidth,\n fill: NOS,\n };\n break;\n case 'fillPath':\n path = {\n d: this.opsToPath(drawing),\n stroke: NOS,\n strokeWidth: 0,\n fill: o.fill || NOS,\n };\n break;\n case 'fillSketch':\n path = this.fillSketch(drawing, o);\n break;\n }\n if (path) {\n paths.push(path);\n }\n }\n return paths;\n }\n fillSketch(drawing, o) {\n let fweight = o.fillWeight;\n if (fweight < 0) {\n fweight = o.strokeWidth / 2;\n }\n return {\n d: this.opsToPath(drawing),\n stroke: o.fill || NOS,\n strokeWidth: fweight,\n fill: NOS,\n };\n }\n _mergedShape(input) {\n return input.filter((d, i) => {\n if (i === 0) {\n return true;\n }\n if (d.op === 'move') {\n return false;\n }\n return true;\n });\n }\n}\n", "import { getFiller } from './fillers/filler.js';\nimport { Random } from './math.js';\nimport { parsePath, normalize, absolutize } from 'path-data-parser';\nconst helper = {\n randOffset,\n randOffsetWithRange,\n ellipse,\n doubleLineOps: doubleLineFillOps,\n};\nexport function line(x1, y1, x2, y2, o) {\n return { type: 'path', ops: _doubleLine(x1, y1, x2, y2, o) };\n}\nexport function linearPath(points, close, o) {\n const len = (points || []).length;\n if (len > 2) {\n const ops = [];\n for (let i = 0; i < (len - 1); i++) {\n ops.push(..._doubleLine(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1], o));\n }\n if (close) {\n ops.push(..._doubleLine(points[len - 1][0], points[len - 1][1], points[0][0], points[0][1], o));\n }\n return { type: 'path', ops };\n }\n else if (len === 2) {\n return line(points[0][0], points[0][1], points[1][0], points[1][1], o);\n }\n return { type: 'path', ops: [] };\n}\nexport function polygon(points, o) {\n return linearPath(points, true, o);\n}\nexport function rectangle(x, y, width, height, o) {\n const points = [\n [x, y],\n [x + width, y],\n [x + width, y + height],\n [x, y + height],\n ];\n return polygon(points, o);\n}\nexport function curve(points, o) {\n let o1 = _curveWithOffset(points, 1 * (1 + o.roughness * 0.2), o);\n if (!o.disableMultiStroke) {\n const o2 = _curveWithOffset(points, 1.5 * (1 + o.roughness * 0.22), cloneOptionsAlterSeed(o));\n o1 = o1.concat(o2);\n }\n return { type: 'path', ops: o1 };\n}\nexport function ellipse(x, y, width, height, o) {\n const params = generateEllipseParams(width, height, o);\n return ellipseWithParams(x, y, o, params).opset;\n}\nexport function generateEllipseParams(width, height, o) {\n const psq = Math.sqrt(Math.PI * 2 * Math.sqrt((Math.pow(width / 2, 2) + Math.pow(height / 2, 2)) / 2));\n const stepCount = Math.ceil(Math.max(o.curveStepCount, (o.curveStepCount / Math.sqrt(200)) * psq));\n const increment = (Math.PI * 2) / stepCount;\n let rx = Math.abs(width / 2);\n let ry = Math.abs(height / 2);\n const curveFitRandomness = 1 - o.curveFitting;\n rx += _offsetOpt(rx * curveFitRandomness, o);\n ry += _offsetOpt(ry * curveFitRandomness, o);\n return { increment, rx, ry };\n}\nexport function ellipseWithParams(x, y, o, ellipseParams) {\n const [ap1, cp1] = _computeEllipsePoints(ellipseParams.increment, x, y, ellipseParams.rx, ellipseParams.ry, 1, ellipseParams.increment * _offset(0.1, _offset(0.4, 1, o), o), o);\n let o1 = _curve(ap1, null, o);\n if ((!o.disableMultiStroke) && (o.roughness !== 0)) {\n const [ap2] = _computeEllipsePoints(ellipseParams.increment, x, y, ellipseParams.rx, ellipseParams.ry, 1.5, 0, o);\n const o2 = _curve(ap2, null, o);\n o1 = o1.concat(o2);\n }\n return {\n estimatedPoints: cp1,\n opset: { type: 'path', ops: o1 },\n };\n}\nexport function arc(x, y, width, height, start, stop, closed, roughClosure, o) {\n const cx = x;\n const cy = y;\n let rx = Math.abs(width / 2);\n let ry = Math.abs(height / 2);\n rx += _offsetOpt(rx * 0.01, o);\n ry += _offsetOpt(ry * 0.01, o);\n let strt = start;\n let stp = stop;\n while (strt < 0) {\n strt += Math.PI * 2;\n stp += Math.PI * 2;\n }\n if ((stp - strt) > (Math.PI * 2)) {\n strt = 0;\n stp = Math.PI * 2;\n }\n const ellipseInc = (Math.PI * 2) / o.curveStepCount;\n const arcInc = Math.min(ellipseInc / 2, (stp - strt) / 2);\n const ops = _arc(arcInc, cx, cy, rx, ry, strt, stp, 1, o);\n if (!o.disableMultiStroke) {\n const o2 = _arc(arcInc, cx, cy, rx, ry, strt, stp, 1.5, o);\n ops.push(...o2);\n }\n if (closed) {\n if (roughClosure) {\n ops.push(..._doubleLine(cx, cy, cx + rx * Math.cos(strt), cy + ry * Math.sin(strt), o), ..._doubleLine(cx, cy, cx + rx * Math.cos(stp), cy + ry * Math.sin(stp), o));\n }\n else {\n ops.push({ op: 'lineTo', data: [cx, cy] }, { op: 'lineTo', data: [cx + rx * Math.cos(strt), cy + ry * Math.sin(strt)] });\n }\n }\n return { type: 'path', ops };\n}\nexport function svgPath(path, o) {\n const segments = normalize(absolutize(parsePath(path)));\n const ops = [];\n let first = [0, 0];\n let current = [0, 0];\n for (const { key, data } of segments) {\n switch (key) {\n case 'M': {\n current = [data[0], data[1]];\n first = [data[0], data[1]];\n break;\n }\n case 'L':\n ops.push(..._doubleLine(current[0], current[1], data[0], data[1], o));\n current = [data[0], data[1]];\n break;\n case 'C': {\n const [x1, y1, x2, y2, x, y] = data;\n ops.push(..._bezierTo(x1, y1, x2, y2, x, y, current, o));\n current = [x, y];\n break;\n }\n case 'Z':\n ops.push(..._doubleLine(current[0], current[1], first[0], first[1], o));\n current = [first[0], first[1]];\n break;\n }\n }\n return { type: 'path', ops };\n}\n// Fills\nexport function solidFillPolygon(polygonList, o) {\n const ops = [];\n for (const points of polygonList) {\n if (points.length) {\n const offset = o.maxRandomnessOffset || 0;\n const len = points.length;\n if (len > 2) {\n ops.push({ op: 'move', data: [points[0][0] + _offsetOpt(offset, o), points[0][1] + _offsetOpt(offset, o)] });\n for (let i = 1; i < len; i++) {\n ops.push({ op: 'lineTo', data: [points[i][0] + _offsetOpt(offset, o), points[i][1] + _offsetOpt(offset, o)] });\n }\n }\n }\n }\n return { type: 'fillPath', ops };\n}\nexport function patternFillPolygons(polygonList, o) {\n return getFiller(o, helper).fillPolygons(polygonList, o);\n}\nexport function patternFillArc(x, y, width, height, start, stop, o) {\n const cx = x;\n const cy = y;\n let rx = Math.abs(width / 2);\n let ry = Math.abs(height / 2);\n rx += _offsetOpt(rx * 0.01, o);\n ry += _offsetOpt(ry * 0.01, o);\n let strt = start;\n let stp = stop;\n while (strt < 0) {\n strt += Math.PI * 2;\n stp += Math.PI * 2;\n }\n if ((stp - strt) > (Math.PI * 2)) {\n strt = 0;\n stp = Math.PI * 2;\n }\n const increment = (stp - strt) / o.curveStepCount;\n const points = [];\n for (let angle = strt; angle <= stp; angle = angle + increment) {\n points.push([cx + rx * Math.cos(angle), cy + ry * Math.sin(angle)]);\n }\n points.push([cx + rx * Math.cos(stp), cy + ry * Math.sin(stp)]);\n points.push([cx, cy]);\n return patternFillPolygons([points], o);\n}\nexport function randOffset(x, o) {\n return _offsetOpt(x, o);\n}\nexport function randOffsetWithRange(min, max, o) {\n return _offset(min, max, o);\n}\nexport function doubleLineFillOps(x1, y1, x2, y2, o) {\n return _doubleLine(x1, y1, x2, y2, o, true);\n}\n// Private helpers\nfunction cloneOptionsAlterSeed(ops) {\n const result = Object.assign({}, ops);\n result.randomizer = undefined;\n if (ops.seed) {\n result.seed = ops.seed + 1;\n }\n return result;\n}\nfunction random(ops) {\n if (!ops.randomizer) {\n ops.randomizer = new Random(ops.seed || 0);\n }\n return ops.randomizer.next();\n}\nfunction _offset(min, max, ops, roughnessGain = 1) {\n return ops.roughness * roughnessGain * ((random(ops) * (max - min)) + min);\n}\nfunction _offsetOpt(x, ops, roughnessGain = 1) {\n return _offset(-x, x, ops, roughnessGain);\n}\nfunction _doubleLine(x1, y1, x2, y2, o, filling = false) {\n const singleStroke = filling ? o.disableMultiStrokeFill : o.disableMultiStroke;\n const o1 = _line(x1, y1, x2, y2, o, true, false);\n if (singleStroke) {\n return o1;\n }\n const o2 = _line(x1, y1, x2, y2, o, true, true);\n return o1.concat(o2);\n}\nfunction _line(x1, y1, x2, y2, o, move, overlay) {\n const lengthSq = Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2);\n const length = Math.sqrt(lengthSq);\n let roughnessGain = 1;\n if (length < 200) {\n roughnessGain = 1;\n }\n else if (length > 500) {\n roughnessGain = 0.4;\n }\n else {\n roughnessGain = (-0.0016668) * length + 1.233334;\n }\n let offset = o.maxRandomnessOffset || 0;\n if ((offset * offset * 100) > lengthSq) {\n offset = length / 10;\n }\n const halfOffset = offset / 2;\n const divergePoint = 0.2 + random(o) * 0.2;\n let midDispX = o.bowing * o.maxRandomnessOffset * (y2 - y1) / 200;\n let midDispY = o.bowing * o.maxRandomnessOffset * (x1 - x2) / 200;\n midDispX = _offsetOpt(midDispX, o, roughnessGain);\n midDispY = _offsetOpt(midDispY, o, roughnessGain);\n const ops = [];\n const randomHalf = () => _offsetOpt(halfOffset, o, roughnessGain);\n const randomFull = () => _offsetOpt(offset, o, roughnessGain);\n const preserveVertices = o.preserveVertices;\n if (move) {\n if (overlay) {\n ops.push({\n op: 'move', data: [\n x1 + (preserveVertices ? 0 : randomHalf()),\n y1 + (preserveVertices ? 0 : randomHalf()),\n ],\n });\n }\n else {\n ops.push({\n op: 'move', data: [\n x1 + (preserveVertices ? 0 : _offsetOpt(offset, o, roughnessGain)),\n y1 + (preserveVertices ? 0 : _offsetOpt(offset, o, roughnessGain)),\n ],\n });\n }\n }\n if (overlay) {\n ops.push({\n op: 'bcurveTo',\n data: [\n midDispX + x1 + (x2 - x1) * divergePoint + randomHalf(),\n midDispY + y1 + (y2 - y1) * divergePoint + randomHalf(),\n midDispX + x1 + 2 * (x2 - x1) * divergePoint + randomHalf(),\n midDispY + y1 + 2 * (y2 - y1) * divergePoint + randomHalf(),\n x2 + (preserveVertices ? 0 : randomHalf()),\n y2 + (preserveVertices ? 0 : randomHalf()),\n ],\n });\n }\n else {\n ops.push({\n op: 'bcurveTo',\n data: [\n midDispX + x1 + (x2 - x1) * divergePoint + randomFull(),\n midDispY + y1 + (y2 - y1) * divergePoint + randomFull(),\n midDispX + x1 + 2 * (x2 - x1) * divergePoint + randomFull(),\n midDispY + y1 + 2 * (y2 - y1) * divergePoint + randomFull(),\n x2 + (preserveVertices ? 0 : randomFull()),\n y2 + (preserveVertices ? 0 : randomFull()),\n ],\n });\n }\n return ops;\n}\nfunction _curveWithOffset(points, offset, o) {\n const ps = [];\n ps.push([\n points[0][0] + _offsetOpt(offset, o),\n points[0][1] + _offsetOpt(offset, o),\n ]);\n ps.push([\n points[0][0] + _offsetOpt(offset, o),\n points[0][1] + _offsetOpt(offset, o),\n ]);\n for (let i = 1; i < points.length; i++) {\n ps.push([\n points[i][0] + _offsetOpt(offset, o),\n points[i][1] + _offsetOpt(offset, o),\n ]);\n if (i === (points.length - 1)) {\n ps.push([\n points[i][0] + _offsetOpt(offset, o),\n points[i][1] + _offsetOpt(offset, o),\n ]);\n }\n }\n return _curve(ps, null, o);\n}\nfunction _curve(points, closePoint, o) {\n const len = points.length;\n const ops = [];\n if (len > 3) {\n const b = [];\n const s = 1 - o.curveTightness;\n ops.push({ op: 'move', data: [points[1][0], points[1][1]] });\n for (let i = 1; (i + 2) < len; i++) {\n const cachedVertArray = points[i];\n b[0] = [cachedVertArray[0], cachedVertArray[1]];\n b[1] = [cachedVertArray[0] + (s * points[i + 1][0] - s * points[i - 1][0]) / 6, cachedVertArray[1] + (s * points[i + 1][1] - s * points[i - 1][1]) / 6];\n b[2] = [points[i + 1][0] + (s * points[i][0] - s * points[i + 2][0]) / 6, points[i + 1][1] + (s * points[i][1] - s * points[i + 2][1]) / 6];\n b[3] = [points[i + 1][0], points[i + 1][1]];\n ops.push({ op: 'bcurveTo', data: [b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1]] });\n }\n if (closePoint && closePoint.length === 2) {\n const ro = o.maxRandomnessOffset;\n ops.push({ op: 'lineTo', data: [closePoint[0] + _offsetOpt(ro, o), closePoint[1] + _offsetOpt(ro, o)] });\n }\n }\n else if (len === 3) {\n ops.push({ op: 'move', data: [points[1][0], points[1][1]] });\n ops.push({\n op: 'bcurveTo',\n data: [\n points[1][0], points[1][1],\n points[2][0], points[2][1],\n points[2][0], points[2][1],\n ],\n });\n }\n else if (len === 2) {\n ops.push(..._doubleLine(points[0][0], points[0][1], points[1][0], points[1][1], o));\n }\n return ops;\n}\nfunction _computeEllipsePoints(increment, cx, cy, rx, ry, offset, overlap, o) {\n const coreOnly = o.roughness === 0;\n const corePoints = [];\n const allPoints = [];\n if (coreOnly) {\n increment = increment / 4;\n allPoints.push([\n cx + rx * Math.cos(-increment),\n cy + ry * Math.sin(-increment),\n ]);\n for (let angle = 0; angle <= Math.PI * 2; angle = angle + increment) {\n const p = [\n cx + rx * Math.cos(angle),\n cy + ry * Math.sin(angle),\n ];\n corePoints.push(p);\n allPoints.push(p);\n }\n allPoints.push([\n cx + rx * Math.cos(0),\n cy + ry * Math.sin(0),\n ]);\n allPoints.push([\n cx + rx * Math.cos(increment),\n cy + ry * Math.sin(increment),\n ]);\n }\n else {\n const radOffset = _offsetOpt(0.5, o) - (Math.PI / 2);\n allPoints.push([\n _offsetOpt(offset, o) + cx + 0.9 * rx * Math.cos(radOffset - increment),\n _offsetOpt(offset, o) + cy + 0.9 * ry * Math.sin(radOffset - increment),\n ]);\n const endAngle = Math.PI * 2 + radOffset - 0.01;\n for (let angle = radOffset; angle < endAngle; angle = angle + increment) {\n const p = [\n _offsetOpt(offset, o) + cx + rx * Math.cos(angle),\n _offsetOpt(offset, o) + cy + ry * Math.sin(angle),\n ];\n corePoints.push(p);\n allPoints.push(p);\n }\n allPoints.push([\n _offsetOpt(offset, o) + cx + rx * Math.cos(radOffset + Math.PI * 2 + overlap * 0.5),\n _offsetOpt(offset, o) + cy + ry * Math.sin(radOffset + Math.PI * 2 + overlap * 0.5),\n ]);\n allPoints.push([\n _offsetOpt(offset, o) + cx + 0.98 * rx * Math.cos(radOffset + overlap),\n _offsetOpt(offset, o) + cy + 0.98 * ry * Math.sin(radOffset + overlap),\n ]);\n allPoints.push([\n _offsetOpt(offset, o) + cx + 0.9 * rx * Math.cos(radOffset + overlap * 0.5),\n _offsetOpt(offset, o) + cy + 0.9 * ry * Math.sin(radOffset + overlap * 0.5),\n ]);\n }\n return [allPoints, corePoints];\n}\nfunction _arc(increment, cx, cy, rx, ry, strt, stp, offset, o) {\n const radOffset = strt + _offsetOpt(0.1, o);\n const points = [];\n points.push([\n _offsetOpt(offset, o) + cx + 0.9 * rx * Math.cos(radOffset - increment),\n _offsetOpt(offset, o) + cy + 0.9 * ry * Math.sin(radOffset - increment),\n ]);\n for (let angle = radOffset; angle <= stp; angle = angle + increment) {\n points.push([\n _offsetOpt(offset, o) + cx + rx * Math.cos(angle),\n _offsetOpt(offset, o) + cy + ry * Math.sin(angle),\n ]);\n }\n points.push([\n cx + rx * Math.cos(stp),\n cy + ry * Math.sin(stp),\n ]);\n points.push([\n cx + rx * Math.cos(stp),\n cy + ry * Math.sin(stp),\n ]);\n return _curve(points, null, o);\n}\nfunction _bezierTo(x1, y1, x2, y2, x, y, current, o) {\n const ops = [];\n const ros = [o.maxRandomnessOffset || 1, (o.maxRandomnessOffset || 1) + 0.3];\n let f = [0, 0];\n const iterations = o.disableMultiStroke ? 1 : 2;\n const preserveVertices = o.preserveVertices;\n for (let i = 0; i < iterations; i++) {\n if (i === 0) {\n ops.push({ op: 'move', data: [current[0], current[1]] });\n }\n else {\n ops.push({ op: 'move', data: [current[0] + (preserveVertices ? 0 : _offsetOpt(ros[0], o)), current[1] + (preserveVertices ? 0 : _offsetOpt(ros[0], o))] });\n }\n f = preserveVertices ? [x, y] : [x + _offsetOpt(ros[i], o), y + _offsetOpt(ros[i], o)];\n ops.push({\n op: 'bcurveTo',\n data: [\n x1 + _offsetOpt(ros[i], o), y1 + _offsetOpt(ros[i], o),\n x2 + _offsetOpt(ros[i], o), y2 + _offsetOpt(ros[i], o),\n f[0], f[1],\n ],\n });\n }\n return ops;\n}\n", "import { HachureFiller } from './hachure-filler';\nimport { ZigZagFiller } from './zigzag-filler';\nimport { HatchFiller } from './hatch-filler';\nimport { DotFiller } from './dot-filler';\nimport { DashedFiller } from './dashed-filler';\nimport { ZigZagLineFiller } from './zigzag-line-filler';\nconst fillers = {};\nexport function getFiller(o, helper) {\n let fillerName = o.fillStyle || 'hachure';\n if (!fillers[fillerName]) {\n switch (fillerName) {\n case 'zigzag':\n if (!fillers[fillerName]) {\n fillers[fillerName] = new ZigZagFiller(helper);\n }\n break;\n case 'cross-hatch':\n if (!fillers[fillerName]) {\n fillers[fillerName] = new HatchFiller(helper);\n }\n break;\n case 'dots':\n if (!fillers[fillerName]) {\n fillers[fillerName] = new DotFiller(helper);\n }\n break;\n case 'dashed':\n if (!fillers[fillerName]) {\n fillers[fillerName] = new DashedFiller(helper);\n }\n break;\n case 'zigzag-line':\n if (!fillers[fillerName]) {\n fillers[fillerName] = new ZigZagLineFiller(helper);\n }\n break;\n case 'hachure':\n default:\n fillerName = 'hachure';\n if (!fillers[fillerName]) {\n fillers[fillerName] = new HachureFiller(helper);\n }\n break;\n }\n }\n return fillers[fillerName];\n}\n", "import { polygonHachureLines } from './scan-line-hachure';\nexport class HachureFiller {\n constructor(helper) {\n this.helper = helper;\n }\n fillPolygons(polygonList, o) {\n return this._fillPolygons(polygonList, o);\n }\n _fillPolygons(polygonList, o) {\n const lines = polygonHachureLines(polygonList, o);\n const ops = this.renderLines(lines, o);\n return { type: 'fillSketch', ops };\n }\n renderLines(lines, o) {\n const ops = [];\n for (const line of lines) {\n ops.push(...this.helper.doubleLineOps(line[0][0], line[0][1], line[1][0], line[1][1], o));\n }\n return ops;\n }\n}\n", "import { hachureLines } from 'hachure-fill';\nexport function polygonHachureLines(polygonList, o) {\n var _a;\n const angle = o.hachureAngle + 90;\n let gap = o.hachureGap;\n if (gap < 0) {\n gap = o.strokeWidth * 4;\n }\n gap = Math.max(gap, 0.1);\n let skipOffset = 1;\n if (o.roughness >= 1) {\n if ((((_a = o.randomizer) === null || _a === void 0 ? void 0 : _a.next()) || Math.random()) > 0.7) {\n skipOffset = gap;\n }\n }\n return hachureLines(polygonList, gap, angle, skipOffset || 1);\n}\n", "function rotatePoints(points, center, degrees) {\n if (points && points.length) {\n const [cx, cy] = center;\n const angle = (Math.PI / 180) * degrees;\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n for (const p of points) {\n const [x, y] = p;\n p[0] = ((x - cx) * cos) - ((y - cy) * sin) + cx;\n p[1] = ((x - cx) * sin) + ((y - cy) * cos) + cy;\n }\n }\n}\nfunction rotateLines(lines, center, degrees) {\n const points = [];\n lines.forEach((line) => points.push(...line));\n rotatePoints(points, center, degrees);\n}\nfunction areSamePoints(p1, p2) {\n return p1[0] === p2[0] && p1[1] === p2[1];\n}\nexport function hachureLines(polygons, hachureGap, hachureAngle, hachureStepOffset = 1) {\n const angle = hachureAngle;\n const gap = Math.max(hachureGap, 0.1);\n const polygonList = (polygons[0] && polygons[0][0] && (typeof polygons[0][0] === 'number')) ? [polygons] : polygons;\n const rotationCenter = [0, 0];\n if (angle) {\n for (const polygon of polygonList) {\n rotatePoints(polygon, rotationCenter, angle);\n }\n }\n const lines = straightHachureLines(polygonList, gap, hachureStepOffset);\n if (angle) {\n for (const polygon of polygonList) {\n rotatePoints(polygon, rotationCenter, -angle);\n }\n rotateLines(lines, rotationCenter, -angle);\n }\n return lines;\n}\nfunction straightHachureLines(polygons, gap, hachureStepOffset) {\n const vertexArray = [];\n for (const polygon of polygons) {\n const vertices = [...polygon];\n if (!areSamePoints(vertices[0], vertices[vertices.length - 1])) {\n vertices.push([vertices[0][0], vertices[0][1]]);\n }\n if (vertices.length > 2) {\n vertexArray.push(vertices);\n }\n }\n const lines = [];\n gap = Math.max(gap, 0.1);\n // Create sorted edges table\n const edges = [];\n for (const vertices of vertexArray) {\n for (let i = 0; i < vertices.length - 1; i++) {\n const p1 = vertices[i];\n const p2 = vertices[i + 1];\n if (p1[1] !== p2[1]) {\n const ymin = Math.min(p1[1], p2[1]);\n edges.push({\n ymin,\n ymax: Math.max(p1[1], p2[1]),\n x: ymin === p1[1] ? p1[0] : p2[0],\n islope: (p2[0] - p1[0]) / (p2[1] - p1[1]),\n });\n }\n }\n }\n edges.sort((e1, e2) => {\n if (e1.ymin < e2.ymin) {\n return -1;\n }\n if (e1.ymin > e2.ymin) {\n return 1;\n }\n if (e1.x < e2.x) {\n return -1;\n }\n if (e1.x > e2.x) {\n return 1;\n }\n if (e1.ymax === e2.ymax) {\n return 0;\n }\n return (e1.ymax - e2.ymax) / Math.abs((e1.ymax - e2.ymax));\n });\n if (!edges.length) {\n return lines;\n }\n // Start scanning\n let activeEdges = [];\n let y = edges[0].ymin;\n let iteration = 0;\n while (activeEdges.length || edges.length) {\n if (edges.length) {\n let ix = -1;\n for (let i = 0; i < edges.length; i++) {\n if (edges[i].ymin > y) {\n break;\n }\n ix = i;\n }\n const removed = edges.splice(0, ix + 1);\n removed.forEach((edge) => {\n activeEdges.push({ s: y, edge });\n });\n }\n activeEdges = activeEdges.filter((ae) => {\n if (ae.edge.ymax <= y) {\n return false;\n }\n return true;\n });\n activeEdges.sort((ae1, ae2) => {\n if (ae1.edge.x === ae2.edge.x) {\n return 0;\n }\n return (ae1.edge.x - ae2.edge.x) / Math.abs((ae1.edge.x - ae2.edge.x));\n });\n // fill between the edges\n if ((hachureStepOffset !== 1) || (iteration % gap === 0)) {\n if (activeEdges.length > 1) {\n for (let i = 0; i < activeEdges.length; i = i + 2) {\n const nexti = i + 1;\n if (nexti >= activeEdges.length) {\n break;\n }\n const ce = activeEdges[i].edge;\n const ne = activeEdges[nexti].edge;\n lines.push([\n [Math.round(ce.x), y],\n [Math.round(ne.x), y],\n ]);\n }\n }\n }\n y += hachureStepOffset;\n activeEdges.forEach((ae) => {\n ae.edge.x = ae.edge.x + (hachureStepOffset * ae.edge.islope);\n });\n iteration++;\n }\n return lines;\n}\n", "import { HachureFiller } from './hachure-filler';\nimport { polygonHachureLines } from './scan-line-hachure';\nimport { lineLength } from '../geometry';\nexport class ZigZagFiller extends HachureFiller {\n fillPolygons(polygonList, o) {\n let gap = o.hachureGap;\n if (gap < 0) {\n gap = o.strokeWidth * 4;\n }\n gap = Math.max(gap, 0.1);\n const o2 = Object.assign({}, o, { hachureGap: gap });\n const lines = polygonHachureLines(polygonList, o2);\n const zigZagAngle = (Math.PI / 180) * o.hachureAngle;\n const zigzagLines = [];\n const dgx = gap * 0.5 * Math.cos(zigZagAngle);\n const dgy = gap * 0.5 * Math.sin(zigZagAngle);\n for (const [p1, p2] of lines) {\n if (lineLength([p1, p2])) {\n zigzagLines.push([\n [p1[0] - dgx, p1[1] + dgy],\n [...p2],\n ], [\n [p1[0] + dgx, p1[1] - dgy],\n [...p2],\n ]);\n }\n }\n const ops = this.renderLines(zigzagLines, o);\n return { type: 'fillSketch', ops };\n }\n}\n", "export function lineLength(line) {\n const p1 = line[0];\n const p2 = line[1];\n return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));\n}\n", "import { HachureFiller } from './hachure-filler';\nexport class HatchFiller extends HachureFiller {\n fillPolygons(polygonList, o) {\n const set = this._fillPolygons(polygonList, o);\n const o2 = Object.assign({}, o, { hachureAngle: o.hachureAngle + 90 });\n const set2 = this._fillPolygons(polygonList, o2);\n set.ops = set.ops.concat(set2.ops);\n return set;\n }\n}\n", "import { lineLength } from '../geometry';\nimport { polygonHachureLines } from './scan-line-hachure';\nexport class DotFiller {\n constructor(helper) {\n this.helper = helper;\n }\n fillPolygons(polygonList, o) {\n o = Object.assign({}, o, { hachureAngle: 0 });\n const lines = polygonHachureLines(polygonList, o);\n return this.dotsOnLines(lines, o);\n }\n dotsOnLines(lines, o) {\n const ops = [];\n let gap = o.hachureGap;\n if (gap < 0) {\n gap = o.strokeWidth * 4;\n }\n gap = Math.max(gap, 0.1);\n let fweight = o.fillWeight;\n if (fweight < 0) {\n fweight = o.strokeWidth / 2;\n }\n const ro = gap / 4;\n for (const line of lines) {\n const length = lineLength(line);\n const dl = length / gap;\n const count = Math.ceil(dl) - 1;\n const offset = length - (count * gap);\n const x = ((line[0][0] + line[1][0]) / 2) - (gap / 4);\n const minY = Math.min(line[0][1], line[1][1]);\n for (let i = 0; i < count; i++) {\n const y = minY + offset + (i * gap);\n const cx = (x - ro) + Math.random() * 2 * ro;\n const cy = (y - ro) + Math.random() * 2 * ro;\n const el = this.helper.ellipse(cx, cy, fweight, fweight, o);\n ops.push(...el.ops);\n }\n }\n return { type: 'fillSketch', ops };\n }\n}\n", "import { lineLength } from '../geometry';\nimport { polygonHachureLines } from './scan-line-hachure';\nexport class DashedFiller {\n constructor(helper) {\n this.helper = helper;\n }\n fillPolygons(polygonList, o) {\n const lines = polygonHachureLines(polygonList, o);\n return { type: 'fillSketch', ops: this.dashedLine(lines, o) };\n }\n dashedLine(lines, o) {\n const offset = o.dashOffset < 0 ? (o.hachureGap < 0 ? (o.strokeWidth * 4) : o.hachureGap) : o.dashOffset;\n const gap = o.dashGap < 0 ? (o.hachureGap < 0 ? (o.strokeWidth * 4) : o.hachureGap) : o.dashGap;\n const ops = [];\n lines.forEach((line) => {\n const length = lineLength(line);\n const count = Math.floor(length / (offset + gap));\n const startOffset = (length + gap - (count * (offset + gap))) / 2;\n let p1 = line[0];\n let p2 = line[1];\n if (p1[0] > p2[0]) {\n p1 = line[1];\n p2 = line[0];\n }\n const alpha = Math.atan((p2[1] - p1[1]) / (p2[0] - p1[0]));\n for (let i = 0; i < count; i++) {\n const lstart = i * (offset + gap);\n const lend = lstart + offset;\n const start = [p1[0] + (lstart * Math.cos(alpha)) + (startOffset * Math.cos(alpha)), p1[1] + lstart * Math.sin(alpha) + (startOffset * Math.sin(alpha))];\n const end = [p1[0] + (lend * Math.cos(alpha)) + (startOffset * Math.cos(alpha)), p1[1] + (lend * Math.sin(alpha)) + (startOffset * Math.sin(alpha))];\n ops.push(...this.helper.doubleLineOps(start[0], start[1], end[0], end[1], o));\n }\n });\n return ops;\n }\n}\n", "import { lineLength } from '../geometry';\nimport { polygonHachureLines } from './scan-line-hachure';\nexport class ZigZagLineFiller {\n constructor(helper) {\n this.helper = helper;\n }\n fillPolygons(polygonList, o) {\n const gap = o.hachureGap < 0 ? (o.strokeWidth * 4) : o.hachureGap;\n const zo = o.zigzagOffset < 0 ? gap : o.zigzagOffset;\n o = Object.assign({}, o, { hachureGap: gap + zo });\n const lines = polygonHachureLines(polygonList, o);\n return { type: 'fillSketch', ops: this.zigzagLines(lines, zo, o) };\n }\n zigzagLines(lines, zo, o) {\n const ops = [];\n lines.forEach((line) => {\n const length = lineLength(line);\n const count = Math.round(length / (2 * zo));\n let p1 = line[0];\n let p2 = line[1];\n if (p1[0] > p2[0]) {\n p1 = line[1];\n p2 = line[0];\n }\n const alpha = Math.atan((p2[1] - p1[1]) / (p2[0] - p1[0]));\n for (let i = 0; i < count; i++) {\n const lstart = i * 2 * zo;\n const lend = (i + 1) * 2 * zo;\n const dz = Math.sqrt(2 * Math.pow(zo, 2));\n const start = [p1[0] + (lstart * Math.cos(alpha)), p1[1] + lstart * Math.sin(alpha)];\n const end = [p1[0] + (lend * Math.cos(alpha)), p1[1] + (lend * Math.sin(alpha))];\n const middle = [start[0] + dz * Math.cos(alpha + Math.PI / 4), start[1] + dz * Math.sin(alpha + Math.PI / 4)];\n ops.push(...this.helper.doubleLineOps(start[0], start[1], middle[0], middle[1], o), ...this.helper.doubleLineOps(middle[0], middle[1], end[0], end[1], o));\n }\n });\n return ops;\n }\n}\n", "export function randomSeed() {\n return Math.floor(Math.random() * 2 ** 31);\n}\nexport class Random {\n constructor(seed) {\n this.seed = seed;\n }\n next() {\n if (this.seed) {\n return ((2 ** 31 - 1) & (this.seed = Math.imul(48271, this.seed))) / 2 ** 31;\n }\n else {\n return Math.random();\n }\n }\n}\n", "export { parsePath, serialize } from './parser.js';\nexport { absolutize } from './absolutize.js';\nexport { normalize } from './normalize.js';\n", "const COMMAND = 0;\nconst NUMBER = 1;\nconst EOD = 2;\nconst PARAMS = { A: 7, a: 7, C: 6, c: 6, H: 1, h: 1, L: 2, l: 2, M: 2, m: 2, Q: 4, q: 4, S: 4, s: 4, T: 2, t: 2, V: 1, v: 1, Z: 0, z: 0 };\nfunction tokenize(d) {\n const tokens = new Array();\n while (d !== '') {\n if (d.match(/^([ \\t\\r\\n,]+)/)) {\n d = d.substr(RegExp.$1.length);\n }\n else if (d.match(/^([aAcChHlLmMqQsStTvVzZ])/)) {\n tokens[tokens.length] = { type: COMMAND, text: RegExp.$1 };\n d = d.substr(RegExp.$1.length);\n }\n else if (d.match(/^(([-+]?[0-9]+(\\.[0-9]*)?|[-+]?\\.[0-9]+)([eE][-+]?[0-9]+)?)/)) {\n tokens[tokens.length] = { type: NUMBER, text: `${parseFloat(RegExp.$1)}` };\n d = d.substr(RegExp.$1.length);\n }\n else {\n return [];\n }\n }\n tokens[tokens.length] = { type: EOD, text: '' };\n return tokens;\n}\nfunction isType(token, type) {\n return token.type === type;\n}\nexport function parsePath(d) {\n const segments = [];\n const tokens = tokenize(d);\n let mode = 'BOD';\n let index = 0;\n let token = tokens[index];\n while (!isType(token, EOD)) {\n let paramsCount = 0;\n const params = [];\n if (mode === 'BOD') {\n if (token.text === 'M' || token.text === 'm') {\n index++;\n paramsCount = PARAMS[token.text];\n mode = token.text;\n }\n else {\n return parsePath('M0,0' + d);\n }\n }\n else if (isType(token, NUMBER)) {\n paramsCount = PARAMS[mode];\n }\n else {\n index++;\n paramsCount = PARAMS[token.text];\n mode = token.text;\n }\n if ((index + paramsCount) < tokens.length) {\n for (let i = index; i < index + paramsCount; i++) {\n const numbeToken = tokens[i];\n if (isType(numbeToken, NUMBER)) {\n params[params.length] = +numbeToken.text;\n }\n else {\n throw new Error('Param not a number: ' + mode + ',' + numbeToken.text);\n }\n }\n if (typeof PARAMS[mode] === 'number') {\n const segment = { key: mode, data: params };\n segments.push(segment);\n index += paramsCount;\n token = tokens[index];\n if (mode === 'M')\n mode = 'L';\n if (mode === 'm')\n mode = 'l';\n }\n else {\n throw new Error('Bad segment: ' + mode);\n }\n }\n else {\n throw new Error('Path data ended short');\n }\n }\n return segments;\n}\nexport function serialize(segments) {\n const tokens = [];\n for (const { key, data } of segments) {\n tokens.push(key);\n switch (key) {\n case 'C':\n case 'c':\n tokens.push(data[0], `${data[1]},`, data[2], `${data[3]},`, data[4], data[5]);\n break;\n case 'S':\n case 's':\n case 'Q':\n case 'q':\n tokens.push(data[0], `${data[1]},`, data[2], data[3]);\n break;\n default:\n tokens.push(...data);\n break;\n }\n }\n return tokens.join(' ');\n}\n", "// Translate relative commands to absolute commands\nexport function absolutize(segments) {\n let cx = 0, cy = 0;\n let subx = 0, suby = 0;\n const out = [];\n for (const { key, data } of segments) {\n switch (key) {\n case 'M':\n out.push({ key: 'M', data: [...data] });\n [cx, cy] = data;\n [subx, suby] = data;\n break;\n case 'm':\n cx += data[0];\n cy += data[1];\n out.push({ key: 'M', data: [cx, cy] });\n subx = cx;\n suby = cy;\n break;\n case 'L':\n out.push({ key: 'L', data: [...data] });\n [cx, cy] = data;\n break;\n case 'l':\n cx += data[0];\n cy += data[1];\n out.push({ key: 'L', data: [cx, cy] });\n break;\n case 'C':\n out.push({ key: 'C', data: [...data] });\n cx = data[4];\n cy = data[5];\n break;\n case 'c': {\n const newdata = data.map((d, i) => (i % 2) ? (d + cy) : (d + cx));\n out.push({ key: 'C', data: newdata });\n cx = newdata[4];\n cy = newdata[5];\n break;\n }\n case 'Q':\n out.push({ key: 'Q', data: [...data] });\n cx = data[2];\n cy = data[3];\n break;\n case 'q': {\n const newdata = data.map((d, i) => (i % 2) ? (d + cy) : (d + cx));\n out.push({ key: 'Q', data: newdata });\n cx = newdata[2];\n cy = newdata[3];\n break;\n }\n case 'A':\n out.push({ key: 'A', data: [...data] });\n cx = data[5];\n cy = data[6];\n break;\n case 'a':\n cx += data[5];\n cy += data[6];\n out.push({ key: 'A', data: [data[0], data[1], data[2], data[3], data[4], cx, cy] });\n break;\n case 'H':\n out.push({ key: 'H', data: [...data] });\n cx = data[0];\n break;\n case 'h':\n cx += data[0];\n out.push({ key: 'H', data: [cx] });\n break;\n case 'V':\n out.push({ key: 'V', data: [...data] });\n cy = data[0];\n break;\n case 'v':\n cy += data[0];\n out.push({ key: 'V', data: [cy] });\n break;\n case 'S':\n out.push({ key: 'S', data: [...data] });\n cx = data[2];\n cy = data[3];\n break;\n case 's': {\n const newdata = data.map((d, i) => (i % 2) ? (d + cy) : (d + cx));\n out.push({ key: 'S', data: newdata });\n cx = newdata[2];\n cy = newdata[3];\n break;\n }\n case 'T':\n out.push({ key: 'T', data: [...data] });\n cx = data[0];\n cy = data[1];\n break;\n case 't':\n cx += data[0];\n cy += data[1];\n out.push({ key: 'T', data: [cx, cy] });\n break;\n case 'Z':\n case 'z':\n out.push({ key: 'Z', data: [] });\n cx = subx;\n cy = suby;\n break;\n }\n }\n return out;\n}\n", "// Normalize path to include only M, L, C, and Z commands\nexport function normalize(segments) {\n const out = [];\n let lastType = '';\n let cx = 0, cy = 0;\n let subx = 0, suby = 0;\n let lcx = 0, lcy = 0;\n for (const { key, data } of segments) {\n switch (key) {\n case 'M':\n out.push({ key: 'M', data: [...data] });\n [cx, cy] = data;\n [subx, suby] = data;\n break;\n case 'C':\n out.push({ key: 'C', data: [...data] });\n cx = data[4];\n cy = data[5];\n lcx = data[2];\n lcy = data[3];\n break;\n case 'L':\n out.push({ key: 'L', data: [...data] });\n [cx, cy] = data;\n break;\n case 'H':\n cx = data[0];\n out.push({ key: 'L', data: [cx, cy] });\n break;\n case 'V':\n cy = data[0];\n out.push({ key: 'L', data: [cx, cy] });\n break;\n case 'S': {\n let cx1 = 0, cy1 = 0;\n if (lastType === 'C' || lastType === 'S') {\n cx1 = cx + (cx - lcx);\n cy1 = cy + (cy - lcy);\n }\n else {\n cx1 = cx;\n cy1 = cy;\n }\n out.push({ key: 'C', data: [cx1, cy1, ...data] });\n lcx = data[0];\n lcy = data[1];\n cx = data[2];\n cy = data[3];\n break;\n }\n case 'T': {\n const [x, y] = data;\n let x1 = 0, y1 = 0;\n if (lastType === 'Q' || lastType === 'T') {\n x1 = cx + (cx - lcx);\n y1 = cy + (cy - lcy);\n }\n else {\n x1 = cx;\n y1 = cy;\n }\n const cx1 = cx + 2 * (x1 - cx) / 3;\n const cy1 = cy + 2 * (y1 - cy) / 3;\n const cx2 = x + 2 * (x1 - x) / 3;\n const cy2 = y + 2 * (y1 - y) / 3;\n out.push({ key: 'C', data: [cx1, cy1, cx2, cy2, x, y] });\n lcx = x1;\n lcy = y1;\n cx = x;\n cy = y;\n break;\n }\n case 'Q': {\n const [x1, y1, x, y] = data;\n const cx1 = cx + 2 * (x1 - cx) / 3;\n const cy1 = cy + 2 * (y1 - cy) / 3;\n const cx2 = x + 2 * (x1 - x) / 3;\n const cy2 = y + 2 * (y1 - y) / 3;\n out.push({ key: 'C', data: [cx1, cy1, cx2, cy2, x, y] });\n lcx = x1;\n lcy = y1;\n cx = x;\n cy = y;\n break;\n }\n case 'A': {\n const r1 = Math.abs(data[0]);\n const r2 = Math.abs(data[1]);\n const angle = data[2];\n const largeArcFlag = data[3];\n const sweepFlag = data[4];\n const x = data[5];\n const y = data[6];\n if (r1 === 0 || r2 === 0) {\n out.push({ key: 'C', data: [cx, cy, x, y, x, y] });\n cx = x;\n cy = y;\n }\n else {\n if (cx !== x || cy !== y) {\n const curves = arcToCubicCurves(cx, cy, x, y, r1, r2, angle, largeArcFlag, sweepFlag);\n curves.forEach(function (curve) {\n out.push({ key: 'C', data: curve });\n });\n cx = x;\n cy = y;\n }\n }\n break;\n }\n case 'Z':\n out.push({ key: 'Z', data: [] });\n cx = subx;\n cy = suby;\n break;\n }\n lastType = key;\n }\n return out;\n}\nfunction degToRad(degrees) {\n return (Math.PI * degrees) / 180;\n}\nfunction rotate(x, y, angleRad) {\n const X = x * Math.cos(angleRad) - y * Math.sin(angleRad);\n const Y = x * Math.sin(angleRad) + y * Math.cos(angleRad);\n return [X, Y];\n}\nfunction arcToCubicCurves(x1, y1, x2, y2, r1, r2, angle, largeArcFlag, sweepFlag, recursive) {\n const angleRad = degToRad(angle);\n let params = [];\n let f1 = 0, f2 = 0, cx = 0, cy = 0;\n if (recursive) {\n [f1, f2, cx, cy] = recursive;\n }\n else {\n [x1, y1] = rotate(x1, y1, -angleRad);\n [x2, y2] = rotate(x2, y2, -angleRad);\n const x = (x1 - x2) / 2;\n const y = (y1 - y2) / 2;\n let h = (x * x) / (r1 * r1) + (y * y) / (r2 * r2);\n if (h > 1) {\n h = Math.sqrt(h);\n r1 = h * r1;\n r2 = h * r2;\n }\n const sign = (largeArcFlag === sweepFlag) ? -1 : 1;\n const r1Pow = r1 * r1;\n const r2Pow = r2 * r2;\n const left = r1Pow * r2Pow - r1Pow * y * y - r2Pow * x * x;\n const right = r1Pow * y * y + r2Pow * x * x;\n const k = sign * Math.sqrt(Math.abs(left / right));\n cx = k * r1 * y / r2 + (x1 + x2) / 2;\n cy = k * -r2 * x / r1 + (y1 + y2) / 2;\n f1 = Math.asin(parseFloat(((y1 - cy) / r2).toFixed(9)));\n f2 = Math.asin(parseFloat(((y2 - cy) / r2).toFixed(9)));\n if (x1 < cx) {\n f1 = Math.PI - f1;\n }\n if (x2 < cx) {\n f2 = Math.PI - f2;\n }\n if (f1 < 0) {\n f1 = Math.PI * 2 + f1;\n }\n if (f2 < 0) {\n f2 = Math.PI * 2 + f2;\n }\n if (sweepFlag && f1 > f2) {\n f1 = f1 - Math.PI * 2;\n }\n if (!sweepFlag && f2 > f1) {\n f2 = f2 - Math.PI * 2;\n }\n }\n let df = f2 - f1;\n if (Math.abs(df) > (Math.PI * 120 / 180)) {\n const f2old = f2;\n const x2old = x2;\n const y2old = y2;\n if (sweepFlag && f2 > f1) {\n f2 = f1 + (Math.PI * 120 / 180) * (1);\n }\n else {\n f2 = f1 + (Math.PI * 120 / 180) * (-1);\n }\n x2 = cx + r1 * Math.cos(f2);\n y2 = cy + r2 * Math.sin(f2);\n params = arcToCubicCurves(x2, y2, x2old, y2old, r1, r2, angle, 0, sweepFlag, [f2, f2old, cx, cy]);\n }\n df = f2 - f1;\n const c1 = Math.cos(f1);\n const s1 = Math.sin(f1);\n const c2 = Math.cos(f2);\n const s2 = Math.sin(f2);\n const t = Math.tan(df / 4);\n const hx = 4 / 3 * r1 * t;\n const hy = 4 / 3 * r2 * t;\n const m1 = [x1, y1];\n const m2 = [x1 + hx * s1, y1 - hy * c1];\n const m3 = [x2 + hx * s2, y2 - hy * c2];\n const m4 = [x2, y2];\n m2[0] = 2 * m1[0] - m2[0];\n m2[1] = 2 * m1[1] - m2[1];\n if (recursive) {\n return [m2, m3, m4].concat(params);\n }\n else {\n params = [m2, m3, m4].concat(params);\n const curves = [];\n for (let i = 0; i < params.length; i += 3) {\n const r1 = rotate(params[i][0], params[i][1], angleRad);\n const r2 = rotate(params[i + 1][0], params[i + 1][1], angleRad);\n const r3 = rotate(params[i + 2][0], params[i + 2][1], angleRad);\n curves.push([r1[0], r1[1], r2[0], r2[1], r3[0], r3[1]]);\n }\n return curves;\n }\n}\n", "function clone(p) {\n return [...p];\n}\nexport function curveToBezier(pointsIn, curveTightness = 0) {\n const len = pointsIn.length;\n if (len < 3) {\n throw new Error('A curve must have at least three points.');\n }\n const out = [];\n if (len === 3) {\n out.push(clone(pointsIn[0]), clone(pointsIn[1]), clone(pointsIn[2]), clone(pointsIn[2]));\n }\n else {\n const points = [];\n points.push(pointsIn[0], pointsIn[0]);\n for (let i = 1; i < pointsIn.length; i++) {\n points.push(pointsIn[i]);\n if (i === (pointsIn.length - 1)) {\n points.push(pointsIn[i]);\n }\n }\n const b = [];\n const s = 1 - curveTightness;\n out.push(clone(points[0]));\n for (let i = 1; (i + 2) < points.length; i++) {\n const cachedVertArray = points[i];\n b[0] = [cachedVertArray[0], cachedVertArray[1]];\n b[1] = [cachedVertArray[0] + (s * points[i + 1][0] - s * points[i - 1][0]) / 6, cachedVertArray[1] + (s * points[i + 1][1] - s * points[i - 1][1]) / 6];\n b[2] = [points[i + 1][0] + (s * points[i][0] - s * points[i + 2][0]) / 6, points[i + 1][1] + (s * points[i][1] - s * points[i + 2][1]) / 6];\n b[3] = [points[i + 1][0], points[i + 1][1]];\n out.push(b[1], b[2], b[3]);\n }\n }\n return out;\n}\n", "// distance between 2 points\nfunction distance(p1, p2) {\n return Math.sqrt(distanceSq(p1, p2));\n}\n// distance between 2 points squared\nfunction distanceSq(p1, p2) {\n return Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2);\n}\n// Sistance squared from a point p to the line segment vw\nfunction distanceToSegmentSq(p, v, w) {\n const l2 = distanceSq(v, w);\n if (l2 === 0) {\n return distanceSq(p, v);\n }\n let t = ((p[0] - v[0]) * (w[0] - v[0]) + (p[1] - v[1]) * (w[1] - v[1])) / l2;\n t = Math.max(0, Math.min(1, t));\n return distanceSq(p, lerp(v, w, t));\n}\nfunction lerp(a, b, t) {\n return [\n a[0] + (b[0] - a[0]) * t,\n a[1] + (b[1] - a[1]) * t,\n ];\n}\n// Adapted from https://seant23.wordpress.com/2010/11/12/offset-bezier-curves/\nfunction flatness(points, offset) {\n const p1 = points[offset + 0];\n const p2 = points[offset + 1];\n const p3 = points[offset + 2];\n const p4 = points[offset + 3];\n let ux = 3 * p2[0] - 2 * p1[0] - p4[0];\n ux *= ux;\n let uy = 3 * p2[1] - 2 * p1[1] - p4[1];\n uy *= uy;\n let vx = 3 * p3[0] - 2 * p4[0] - p1[0];\n vx *= vx;\n let vy = 3 * p3[1] - 2 * p4[1] - p1[1];\n vy *= vy;\n if (ux < vx) {\n ux = vx;\n }\n if (uy < vy) {\n uy = vy;\n }\n return ux + uy;\n}\nfunction getPointsOnBezierCurveWithSplitting(points, offset, tolerance, newPoints) {\n const outPoints = newPoints || [];\n if (flatness(points, offset) < tolerance) {\n const p0 = points[offset + 0];\n if (outPoints.length) {\n const d = distance(outPoints[outPoints.length - 1], p0);\n if (d > 1) {\n outPoints.push(p0);\n }\n }\n else {\n outPoints.push(p0);\n }\n outPoints.push(points[offset + 3]);\n }\n else {\n // subdivide\n const t = .5;\n const p1 = points[offset + 0];\n const p2 = points[offset + 1];\n const p3 = points[offset + 2];\n const p4 = points[offset + 3];\n const q1 = lerp(p1, p2, t);\n const q2 = lerp(p2, p3, t);\n const q3 = lerp(p3, p4, t);\n const r1 = lerp(q1, q2, t);\n const r2 = lerp(q2, q3, t);\n const red = lerp(r1, r2, t);\n getPointsOnBezierCurveWithSplitting([p1, q1, r1, red], 0, tolerance, outPoints);\n getPointsOnBezierCurveWithSplitting([red, r2, q3, p4], 0, tolerance, outPoints);\n }\n return outPoints;\n}\nexport function simplify(points, distance) {\n return simplifyPoints(points, 0, points.length, distance);\n}\n// Ramer\u2013Douglas\u2013Peucker algorithm\n// https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm\nfunction simplifyPoints(points, start, end, epsilon, newPoints) {\n const outPoints = newPoints || [];\n // find the most distance point from the endpoints\n const s = points[start];\n const e = points[end - 1];\n let maxDistSq = 0;\n let maxNdx = 1;\n for (let i = start + 1; i < end - 1; ++i) {\n const distSq = distanceToSegmentSq(points[i], s, e);\n if (distSq > maxDistSq) {\n maxDistSq = distSq;\n maxNdx = i;\n }\n }\n // if that point is too far, split\n if (Math.sqrt(maxDistSq) > epsilon) {\n simplifyPoints(points, start, maxNdx + 1, epsilon, outPoints);\n simplifyPoints(points, maxNdx, end, epsilon, outPoints);\n }\n else {\n if (!outPoints.length) {\n outPoints.push(s);\n }\n outPoints.push(e);\n }\n return outPoints;\n}\nexport function pointsOnBezierCurves(points, tolerance = 0.15, distance) {\n const newPoints = [];\n const numSegments = (points.length - 1) / 3;\n for (let i = 0; i < numSegments; i++) {\n const offset = i * 3;\n getPointsOnBezierCurveWithSplitting(points, offset, tolerance, newPoints);\n }\n if (distance && distance > 0) {\n return simplifyPoints(newPoints, 0, newPoints.length, distance);\n }\n return newPoints;\n}\n", "import { pointsOnBezierCurves, simplify } from 'points-on-curve';\nimport { parsePath, absolutize, normalize } from 'path-data-parser';\nexport function pointsOnPath(path, tolerance, distance) {\n const segments = parsePath(path);\n const normalized = normalize(absolutize(segments));\n const sets = [];\n let currentPoints = [];\n let start = [0, 0];\n let pendingCurve = [];\n const appendPendingCurve = () => {\n if (pendingCurve.length >= 4) {\n currentPoints.push(...pointsOnBezierCurves(pendingCurve, tolerance));\n }\n pendingCurve = [];\n };\n const appendPendingPoints = () => {\n appendPendingCurve();\n if (currentPoints.length) {\n sets.push(currentPoints);\n currentPoints = [];\n }\n };\n for (const { key, data } of normalized) {\n switch (key) {\n case 'M':\n appendPendingPoints();\n start = [data[0], data[1]];\n currentPoints.push(start);\n break;\n case 'L':\n appendPendingCurve();\n currentPoints.push([data[0], data[1]]);\n break;\n case 'C':\n if (!pendingCurve.length) {\n const lastPoint = currentPoints.length ? currentPoints[currentPoints.length - 1] : start;\n pendingCurve.push([lastPoint[0], lastPoint[1]]);\n }\n pendingCurve.push([data[0], data[1]]);\n pendingCurve.push([data[2], data[3]]);\n pendingCurve.push([data[4], data[5]]);\n break;\n case 'Z':\n appendPendingCurve();\n currentPoints.push([start[0], start[1]]);\n break;\n }\n }\n appendPendingPoints();\n if (!distance) {\n return sets;\n }\n const out = [];\n for (const set of sets) {\n const simplifiedSet = simplify(set, distance);\n if (simplifiedSet.length) {\n out.push(simplifiedSet);\n }\n }\n return out;\n}\n", "import { SVGNS } from './core';\nimport { RoughGenerator } from './generator';\nexport class RoughSVG {\n constructor(svg, config) {\n this.svg = svg;\n this.gen = new RoughGenerator(config);\n }\n draw(drawable) {\n const sets = drawable.sets || [];\n const o = drawable.options || this.getDefaultOptions();\n const doc = this.svg.ownerDocument || window.document;\n const g = doc.createElementNS(SVGNS, 'g');\n const precision = drawable.options.fixedDecimalPlaceDigits;\n for (const drawing of sets) {\n let path = null;\n switch (drawing.type) {\n case 'path': {\n path = doc.createElementNS(SVGNS, 'path');\n path.setAttribute('d', this.opsToPath(drawing, precision));\n path.setAttribute('stroke', o.stroke);\n path.setAttribute('stroke-width', o.strokeWidth + '');\n path.setAttribute('fill', 'none');\n if (o.strokeLineDash) {\n path.setAttribute('stroke-dasharray', o.strokeLineDash.join(' ').trim());\n }\n if (o.strokeLineDashOffset) {\n path.setAttribute('stroke-dashoffset', `${o.strokeLineDashOffset}`);\n }\n break;\n }\n case 'fillPath': {\n path = doc.createElementNS(SVGNS, 'path');\n path.setAttribute('d', this.opsToPath(drawing, precision));\n path.setAttribute('stroke', 'none');\n path.setAttribute('stroke-width', '0');\n path.setAttribute('fill', o.fill || '');\n if (drawable.shape === 'curve' || drawable.shape === 'polygon') {\n path.setAttribute('fill-rule', 'evenodd');\n }\n break;\n }\n case 'fillSketch': {\n path = this.fillSketch(doc, drawing, o);\n break;\n }\n }\n if (path) {\n g.appendChild(path);\n }\n }\n return g;\n }\n fillSketch(doc, drawing, o) {\n let fweight = o.fillWeight;\n if (fweight < 0) {\n fweight = o.strokeWidth / 2;\n }\n const path = doc.createElementNS(SVGNS, 'path');\n path.setAttribute('d', this.opsToPath(drawing, o.fixedDecimalPlaceDigits));\n path.setAttribute('stroke', o.fill || '');\n path.setAttribute('stroke-width', fweight + '');\n path.setAttribute('fill', 'none');\n if (o.fillLineDash) {\n path.setAttribute('stroke-dasharray', o.fillLineDash.join(' ').trim());\n }\n if (o.fillLineDashOffset) {\n path.setAttribute('stroke-dashoffset', `${o.fillLineDashOffset}`);\n }\n return path;\n }\n get generator() {\n return this.gen;\n }\n getDefaultOptions() {\n return this.gen.defaultOptions;\n }\n opsToPath(drawing, fixedDecimalPlaceDigits) {\n return this.gen.opsToPath(drawing, fixedDecimalPlaceDigits);\n }\n line(x1, y1, x2, y2, options) {\n const d = this.gen.line(x1, y1, x2, y2, options);\n return this.draw(d);\n }\n rectangle(x, y, width, height, options) {\n const d = this.gen.rectangle(x, y, width, height, options);\n return this.draw(d);\n }\n ellipse(x, y, width, height, options) {\n const d = this.gen.ellipse(x, y, width, height, options);\n return this.draw(d);\n }\n circle(x, y, diameter, options) {\n const d = this.gen.circle(x, y, diameter, options);\n return this.draw(d);\n }\n linearPath(points, options) {\n const d = this.gen.linearPath(points, options);\n return this.draw(d);\n }\n polygon(points, options) {\n const d = this.gen.polygon(points, options);\n return this.draw(d);\n }\n arc(x, y, width, height, start, stop, closed = false, options) {\n const d = this.gen.arc(x, y, width, height, start, stop, closed, options);\n return this.draw(d);\n }\n curve(points, options) {\n const d = this.gen.curve(points, options);\n return this.draw(d);\n }\n path(d, options) {\n const drawing = this.gen.path(d, options);\n return this.draw(drawing);\n }\n}\n", "export const SVGNS = 'http://www.w3.org/2000/svg';\n", "/**\r\n * this file defines pure geometric shapes\r\n *\r\n * for instance, a cubic bezier curve is specified by its four control points and\r\n * an ellipse is defined by its center, angle, semi major axis and semi minor axis\r\n * (but in semi-width and semi-height so it's more relevant to Excalidraw)\r\n *\r\n * the idea with pure shapes is so that we can provide collision and other geoemtric methods not depending on\r\n * the specifics of roughjs or elements in Excalidraw; instead, we can focus on the pure shapes themselves\r\n *\r\n * also included in this file are methods for converting an Excalidraw element or a Drawable from roughjs\r\n * to pure shapes\r\n */\r\nimport { pointsOnBezierCurves } from \"points-on-curve\";\r\n\r\nimport { invariant } from \"@excalidraw-modify/common\";\r\nimport {\r\n curve,\r\n lineSegment,\r\n pointFrom,\r\n pointDistance,\r\n pointFromArray,\r\n pointFromVector,\r\n pointRotateRads,\r\n polygon,\r\n polygonFromPoints,\r\n PRECISION,\r\n segmentsIntersectAt,\r\n vector,\r\n vectorAdd,\r\n vectorFromPoint,\r\n vectorScale,\r\n type GlobalPoint,\r\n type LocalPoint,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport { getElementAbsoluteCoords } from \"@excalidraw-modify/element\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawBindableElement,\r\n ExcalidrawDiamondElement,\r\n ExcalidrawElement,\r\n ExcalidrawEllipseElement,\r\n ExcalidrawEmbeddableElement,\r\n ExcalidrawFrameLikeElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawIframeElement,\r\n ExcalidrawImageElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawRectangleElement,\r\n ExcalidrawSelectionElement,\r\n ExcalidrawTextElement,\r\n} from \"@excalidraw-modify/element/types\";\r\nimport type { Curve, LineSegment, Polygon, Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport type { Drawable, Op } from \"roughjs/bin/core\";\r\n\r\n// a polyline (made up term here) is a line consisting of other line segments\r\n// this corresponds to a straight line element in the editor but it could also\r\n// be used to model other elements\r\nexport type Polyline<Point extends GlobalPoint | LocalPoint> =\r\n LineSegment<Point>[];\r\n\r\n// a polycurve is a curve consisting of ther curves, this corresponds to a complex\r\n// curve on the canvas\r\nexport type Polycurve<Point extends GlobalPoint | LocalPoint> = Curve<Point>[];\r\n\r\n// an ellipse is specified by its center, angle, and its major and minor axes\r\n// but for the sake of simplicity, we've used halfWidth and halfHeight instead\r\n// in replace of semi major and semi minor axes\r\nexport type Ellipse<Point extends GlobalPoint | LocalPoint> = {\r\n center: Point;\r\n angle: Radians;\r\n halfWidth: number;\r\n halfHeight: number;\r\n};\r\n\r\nexport type GeometricShape<Point extends GlobalPoint | LocalPoint> =\r\n | {\r\n type: \"line\";\r\n data: LineSegment<Point>;\r\n }\r\n | {\r\n type: \"polygon\";\r\n data: Polygon<Point>;\r\n }\r\n | {\r\n type: \"curve\";\r\n data: Curve<Point>;\r\n }\r\n | {\r\n type: \"ellipse\";\r\n data: Ellipse<Point>;\r\n }\r\n | {\r\n type: \"polyline\";\r\n data: Polyline<Point>;\r\n }\r\n | {\r\n type: \"polycurve\";\r\n data: Polycurve<Point>;\r\n };\r\n\r\ntype RectangularElement =\r\n | ExcalidrawRectangleElement\r\n | ExcalidrawDiamondElement\r\n | ExcalidrawFrameLikeElement\r\n | ExcalidrawEmbeddableElement\r\n | ExcalidrawImageElement\r\n | ExcalidrawIframeElement\r\n | ExcalidrawTextElement\r\n | ExcalidrawSelectionElement;\r\n\r\n// polygon\r\nexport const getPolygonShape = <Point extends GlobalPoint | LocalPoint>(\r\n element: RectangularElement,\r\n): GeometricShape<Point> => {\r\n const { angle, width, height, x, y } = element;\r\n\r\n const cx = x + width / 2;\r\n const cy = y + height / 2;\r\n\r\n const center: Point = pointFrom(cx, cy);\r\n\r\n let data: Polygon<Point>;\r\n\r\n if (element.type === \"diamond\") {\r\n data = polygon(\r\n pointRotateRads(pointFrom(cx, y), center, angle),\r\n pointRotateRads(pointFrom(x + width, cy), center, angle),\r\n pointRotateRads(pointFrom(cx, y + height), center, angle),\r\n pointRotateRads(pointFrom(x, cy), center, angle),\r\n );\r\n } else {\r\n data = polygon(\r\n pointRotateRads(pointFrom(x, y), center, angle),\r\n pointRotateRads(pointFrom(x + width, y), center, angle),\r\n pointRotateRads(pointFrom(x + width, y + height), center, angle),\r\n pointRotateRads(pointFrom(x, y + height), center, angle),\r\n );\r\n }\r\n\r\n return {\r\n type: \"polygon\",\r\n data,\r\n };\r\n};\r\n\r\n// return the selection box for an element, possibly rotated as well\r\nexport const getSelectionBoxShape = <Point extends GlobalPoint | LocalPoint>(\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n padding = 10,\r\n) => {\r\n let [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\r\n element,\r\n elementsMap,\r\n true,\r\n );\r\n\r\n x1 -= padding;\r\n x2 += padding;\r\n y1 -= padding;\r\n y2 += padding;\r\n\r\n //const angleInDegrees = angleToDegrees(element.angle);\r\n const center = pointFrom(cx, cy);\r\n const topLeft = pointRotateRads(pointFrom(x1, y1), center, element.angle);\r\n const topRight = pointRotateRads(pointFrom(x2, y1), center, element.angle);\r\n const bottomLeft = pointRotateRads(pointFrom(x1, y2), center, element.angle);\r\n const bottomRight = pointRotateRads(pointFrom(x2, y2), center, element.angle);\r\n\r\n return {\r\n type: \"polygon\",\r\n data: [topLeft, topRight, bottomRight, bottomLeft],\r\n } as GeometricShape<Point>;\r\n};\r\n\r\n// ellipse\r\nexport const getEllipseShape = <Point extends GlobalPoint | LocalPoint>(\r\n element: ExcalidrawEllipseElement,\r\n): GeometricShape<Point> => {\r\n const { width, height, angle, x, y } = element;\r\n\r\n return {\r\n type: \"ellipse\",\r\n data: {\r\n center: pointFrom(x + width / 2, y + height / 2),\r\n angle,\r\n halfWidth: width / 2,\r\n halfHeight: height / 2,\r\n },\r\n };\r\n};\r\n\r\nexport const getCurvePathOps = (shape: Drawable): Op[] => {\r\n // NOTE (mtolmacs): Temporary fix for extremely large elements\r\n if (!shape) {\r\n return [];\r\n }\r\n\r\n for (const set of shape.sets) {\r\n if (set.type === \"path\") {\r\n return set.ops;\r\n }\r\n }\r\n return shape.sets[0].ops;\r\n};\r\n\r\n// linear\r\nexport const getCurveShape = <Point extends GlobalPoint | LocalPoint>(\r\n roughShape: Drawable,\r\n startingPoint: Point = pointFrom(0, 0),\r\n angleInRadian: Radians,\r\n center: Point,\r\n): GeometricShape<Point> => {\r\n const transform = (p: Point): Point =>\r\n pointRotateRads(\r\n pointFrom(p[0] + startingPoint[0], p[1] + startingPoint[1]),\r\n center,\r\n angleInRadian,\r\n );\r\n\r\n const ops = getCurvePathOps(roughShape);\r\n const polycurve: Polycurve<Point> = [];\r\n let p0 = pointFrom<Point>(0, 0);\r\n\r\n for (const op of ops) {\r\n if (op.op === \"move\") {\r\n const p = pointFromArray<Point>(op.data);\r\n invariant(p != null, \"Ops data is not a point\");\r\n p0 = transform(p);\r\n }\r\n if (op.op === \"bcurveTo\") {\r\n const p1 = transform(pointFrom<Point>(op.data[0], op.data[1]));\r\n const p2 = transform(pointFrom<Point>(op.data[2], op.data[3]));\r\n const p3 = transform(pointFrom<Point>(op.data[4], op.data[5]));\r\n polycurve.push(curve<Point>(p0, p1, p2, p3));\r\n p0 = p3;\r\n }\r\n }\r\n\r\n return {\r\n type: \"polycurve\",\r\n data: polycurve,\r\n };\r\n};\r\n\r\nconst polylineFromPoints = <Point extends GlobalPoint | LocalPoint>(\r\n points: Point[],\r\n): Polyline<Point> => {\r\n let previousPoint: Point = points[0];\r\n const polyline: LineSegment<Point>[] = [];\r\n\r\n for (let i = 1; i < points.length; i++) {\r\n const nextPoint = points[i];\r\n polyline.push(lineSegment<Point>(previousPoint, nextPoint));\r\n previousPoint = nextPoint;\r\n }\r\n\r\n return polyline;\r\n};\r\n\r\nexport const getFreedrawShape = <Point extends GlobalPoint | LocalPoint>(\r\n element: ExcalidrawFreeDrawElement,\r\n center: Point,\r\n isClosed: boolean = false,\r\n): GeometricShape<Point> => {\r\n const transform = (p: Point) =>\r\n pointRotateRads(\r\n pointFromVector(\r\n vectorAdd(vectorFromPoint(p), vector(element.x, element.y)),\r\n ),\r\n center,\r\n element.angle,\r\n );\r\n\r\n const polyline = polylineFromPoints(\r\n element.points.map((p) => transform(p as Point)),\r\n );\r\n\r\n return (\r\n isClosed\r\n ? {\r\n type: \"polygon\",\r\n data: polygonFromPoints(polyline.flat()),\r\n }\r\n : {\r\n type: \"polyline\",\r\n data: polyline,\r\n }\r\n ) as GeometricShape<Point>;\r\n};\r\n\r\nexport const getClosedCurveShape = <Point extends GlobalPoint | LocalPoint>(\r\n element: ExcalidrawLinearElement,\r\n roughShape: Drawable,\r\n startingPoint: Point = pointFrom<Point>(0, 0),\r\n angleInRadian: Radians,\r\n center: Point,\r\n): GeometricShape<Point> => {\r\n const transform = (p: Point) =>\r\n pointRotateRads(\r\n pointFrom(p[0] + startingPoint[0], p[1] + startingPoint[1]),\r\n center,\r\n angleInRadian,\r\n );\r\n\r\n if (element.roundness === null) {\r\n return {\r\n type: \"polygon\",\r\n data: polygonFromPoints(\r\n element.points.map((p) => transform(p as Point)) as Point[],\r\n ),\r\n };\r\n }\r\n\r\n const ops = getCurvePathOps(roughShape);\r\n\r\n const points: Point[] = [];\r\n let odd = false;\r\n for (const operation of ops) {\r\n if (operation.op === \"move\") {\r\n odd = !odd;\r\n if (odd) {\r\n points.push(pointFrom(operation.data[0], operation.data[1]));\r\n }\r\n } else if (operation.op === \"bcurveTo\") {\r\n if (odd) {\r\n points.push(pointFrom(operation.data[0], operation.data[1]));\r\n points.push(pointFrom(operation.data[2], operation.data[3]));\r\n points.push(pointFrom(operation.data[4], operation.data[5]));\r\n }\r\n } else if (operation.op === \"lineTo\") {\r\n if (odd) {\r\n points.push(pointFrom(operation.data[0], operation.data[1]));\r\n }\r\n }\r\n }\r\n\r\n const polygonPoints = pointsOnBezierCurves(points, 10, 5).map((p) =>\r\n transform(p as Point),\r\n ) as Point[];\r\n\r\n return {\r\n type: \"polygon\",\r\n data: polygonFromPoints<Point>(polygonPoints),\r\n };\r\n};\r\n\r\n/**\r\n * Determine intersection of a rectangular shaped element and a\r\n * line segment.\r\n *\r\n * @param element The rectangular element to test against\r\n * @param segment The segment intersecting the element\r\n * @param gap Optional value to inflate the shape before testing\r\n * @returns An array of intersections\r\n */\r\n// TODO: Replace with final rounded rectangle code\r\nexport const segmentIntersectRectangleElement = <\r\n Point extends LocalPoint | GlobalPoint,\r\n>(\r\n element: ExcalidrawBindableElement,\r\n segment: LineSegment<Point>,\r\n gap: number = 0,\r\n): Point[] => {\r\n const bounds = [\r\n element.x - gap,\r\n element.y - gap,\r\n element.x + element.width + gap,\r\n element.y + element.height + gap,\r\n ];\r\n const center = pointFrom(\r\n (bounds[0] + bounds[2]) / 2,\r\n (bounds[1] + bounds[3]) / 2,\r\n );\r\n\r\n return [\r\n lineSegment(\r\n pointRotateRads(pointFrom(bounds[0], bounds[1]), center, element.angle),\r\n pointRotateRads(pointFrom(bounds[2], bounds[1]), center, element.angle),\r\n ),\r\n lineSegment(\r\n pointRotateRads(pointFrom(bounds[2], bounds[1]), center, element.angle),\r\n pointRotateRads(pointFrom(bounds[2], bounds[3]), center, element.angle),\r\n ),\r\n lineSegment(\r\n pointRotateRads(pointFrom(bounds[2], bounds[3]), center, element.angle),\r\n pointRotateRads(pointFrom(bounds[0], bounds[3]), center, element.angle),\r\n ),\r\n lineSegment(\r\n pointRotateRads(pointFrom(bounds[0], bounds[3]), center, element.angle),\r\n pointRotateRads(pointFrom(bounds[0], bounds[1]), center, element.angle),\r\n ),\r\n ]\r\n .map((s) => segmentsIntersectAt(segment, s))\r\n .filter((i): i is Point => !!i);\r\n};\r\n\r\nconst distanceToEllipse = <Point extends LocalPoint | GlobalPoint>(\r\n p: Point,\r\n ellipse: Ellipse<Point>,\r\n) => {\r\n const { angle, halfWidth, halfHeight, center } = ellipse;\r\n const a = halfWidth;\r\n const b = halfHeight;\r\n const translatedPoint = vectorAdd(\r\n vectorFromPoint(p),\r\n vectorScale(vectorFromPoint(center), -1),\r\n );\r\n const [rotatedPointX, rotatedPointY] = pointRotateRads(\r\n pointFromVector(translatedPoint),\r\n pointFrom(0, 0),\r\n -angle as Radians,\r\n );\r\n\r\n const px = Math.abs(rotatedPointX);\r\n const py = Math.abs(rotatedPointY);\r\n\r\n let tx = 0.707;\r\n let ty = 0.707;\r\n\r\n for (let i = 0; i < 3; i++) {\r\n const x = a * tx;\r\n const y = b * ty;\r\n\r\n const ex = ((a * a - b * b) * tx ** 3) / a;\r\n const ey = ((b * b - a * a) * ty ** 3) / b;\r\n\r\n const rx = x - ex;\r\n const ry = y - ey;\r\n\r\n const qx = px - ex;\r\n const qy = py - ey;\r\n\r\n const r = Math.hypot(ry, rx);\r\n const q = Math.hypot(qy, qx);\r\n\r\n tx = Math.min(1, Math.max(0, ((qx * r) / q + ex) / a));\r\n ty = Math.min(1, Math.max(0, ((qy * r) / q + ey) / b));\r\n const t = Math.hypot(ty, tx);\r\n tx /= t;\r\n ty /= t;\r\n }\r\n\r\n const [minX, minY] = [\r\n a * tx * Math.sign(rotatedPointX),\r\n b * ty * Math.sign(rotatedPointY),\r\n ];\r\n\r\n return pointDistance(\r\n pointFrom(rotatedPointX, rotatedPointY),\r\n pointFrom(minX, minY),\r\n );\r\n};\r\n\r\nexport const pointOnEllipse = <Point extends LocalPoint | GlobalPoint>(\r\n point: Point,\r\n ellipse: Ellipse<Point>,\r\n threshold = PRECISION,\r\n) => {\r\n return distanceToEllipse(point, ellipse) <= threshold;\r\n};\r\n\r\nexport const pointInEllipse = <Point extends LocalPoint | GlobalPoint>(\r\n p: Point,\r\n ellipse: Ellipse<Point>,\r\n) => {\r\n const { center, angle, halfWidth, halfHeight } = ellipse;\r\n const translatedPoint = vectorAdd(\r\n vectorFromPoint(p),\r\n vectorScale(vectorFromPoint(center), -1),\r\n );\r\n const [rotatedPointX, rotatedPointY] = pointRotateRads(\r\n pointFromVector(translatedPoint),\r\n pointFrom(0, 0),\r\n -angle as Radians,\r\n );\r\n\r\n return (\r\n (rotatedPointX / halfWidth) * (rotatedPointX / halfWidth) +\r\n (rotatedPointY / halfHeight) * (rotatedPointY / halfHeight) <=\r\n 1\r\n );\r\n};\r\n\r\nexport const ellipseAxes = <Point extends LocalPoint | GlobalPoint>(\r\n ellipse: Ellipse<Point>,\r\n) => {\r\n const widthGreaterThanHeight = ellipse.halfWidth > ellipse.halfHeight;\r\n\r\n const majorAxis = widthGreaterThanHeight\r\n ? ellipse.halfWidth * 2\r\n : ellipse.halfHeight * 2;\r\n const minorAxis = widthGreaterThanHeight\r\n ? ellipse.halfHeight * 2\r\n : ellipse.halfWidth * 2;\r\n\r\n return {\r\n majorAxis,\r\n minorAxis,\r\n };\r\n};\r\n\r\nexport const ellipseFocusToCenter = <Point extends LocalPoint | GlobalPoint>(\r\n ellipse: Ellipse<Point>,\r\n) => {\r\n const { majorAxis, minorAxis } = ellipseAxes(ellipse);\r\n\r\n return Math.sqrt(majorAxis ** 2 - minorAxis ** 2);\r\n};\r\n\r\nexport const ellipseExtremes = <Point extends LocalPoint | GlobalPoint>(\r\n ellipse: Ellipse<Point>,\r\n) => {\r\n const { center, angle } = ellipse;\r\n const { majorAxis, minorAxis } = ellipseAxes(ellipse);\r\n\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n\r\n const sqSum = majorAxis ** 2 + minorAxis ** 2;\r\n const sqDiff = (majorAxis ** 2 - minorAxis ** 2) * Math.cos(2 * angle);\r\n\r\n const yMax = Math.sqrt((sqSum - sqDiff) / 2);\r\n const xAtYMax =\r\n (yMax * sqSum * sin * cos) /\r\n (majorAxis ** 2 * sin ** 2 + minorAxis ** 2 * cos ** 2);\r\n\r\n const xMax = Math.sqrt((sqSum + sqDiff) / 2);\r\n const yAtXMax =\r\n (xMax * sqSum * sin * cos) /\r\n (majorAxis ** 2 * cos ** 2 + minorAxis ** 2 * sin ** 2);\r\n const centerVector = vectorFromPoint(center);\r\n\r\n return [\r\n vectorAdd(vector(xAtYMax, yMax), centerVector),\r\n vectorAdd(vectorScale(vector(xAtYMax, yMax), -1), centerVector),\r\n vectorAdd(vector(xMax, yAtXMax), centerVector),\r\n vectorAdd(vector(xMax, yAtXMax), centerVector),\r\n ];\r\n};\r\n", "import { simplify } from \"points-on-curve\";\r\n\r\nimport {\r\n type GeometricShape,\r\n getClosedCurveShape,\r\n getCurveShape,\r\n getEllipseShape,\r\n getFreedrawShape,\r\n getPolygonShape,\r\n} from \"@excalidraw/utils/shape\";\r\n\r\nimport {\r\n pointFrom,\r\n pointDistance,\r\n type LocalPoint,\r\n pointRotateRads,\r\n} from \"@excalidraw-modify/math\";\r\nimport {\r\n ROUGHNESS,\r\n isTransparent,\r\n assertNever,\r\n COLOR_PALETTE,\r\n LINE_POLYGON_POINT_MERGE_DISTANCE,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport { RoughGenerator } from \"roughjs/bin/generator\";\r\n\r\nimport type { GlobalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport type { Mutable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport type {\r\n AppState,\r\n EmbedsValidationStatus,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\nimport type {\r\n ElementShape,\r\n ElementShapes,\r\n} from \"@excalidraw-modify/excalidraw/scene/types\";\r\n\r\nimport { elementWithCanvasCache } from \"./renderElement\";\r\n\r\nimport {\r\n canBecomePolygon,\r\n isElbowArrow,\r\n isEmbeddableElement,\r\n isIframeElement,\r\n isIframeLikeElement,\r\n isLinearElement,\r\n} from \"./typeChecks\";\r\nimport { getCornerRadius, isPathALoop } from \"./utils\";\r\nimport { headingForPointIsHorizontal } from \"./heading\";\r\n\r\nimport { canChangeRoundness } from \"./comparisons\";\r\nimport { generateFreeDrawShape } from \"./renderElement\";\r\nimport {\r\n getArrowheadPoints,\r\n getCenterForBounds,\r\n getDiamondPoints,\r\n getElementAbsoluteCoords,\r\n} from \"./bounds\";\r\nimport { shouldTestInside } from \"./collision\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n NonDeletedExcalidrawElement,\r\n ExcalidrawSelectionElement,\r\n ExcalidrawLinearElement,\r\n Arrowhead,\r\n ExcalidrawFreeDrawElement,\r\n ElementsMap,\r\n ExcalidrawLineElement,\r\n} from \"./types\";\r\n\r\nimport type { Drawable, Options } from \"roughjs/bin/core\";\r\nimport type { Point as RoughPoint } from \"roughjs/bin/geometry\";\r\n\r\nexport class ShapeCache {\r\n private static rg = new RoughGenerator();\r\n private static cache = new WeakMap<ExcalidrawElement, ElementShape>();\r\n\r\n /**\r\n * Retrieves shape from cache if available. Use this only if shape\r\n * is optional and you have a fallback in case it's not cached.\r\n */\r\n public static get = <T extends ExcalidrawElement>(element: T) => {\r\n return ShapeCache.cache.get(\r\n element,\r\n ) as T[\"type\"] extends keyof ElementShapes\r\n ? ElementShapes[T[\"type\"]] | undefined\r\n : ElementShape | undefined;\r\n };\r\n\r\n public static set = <T extends ExcalidrawElement>(\r\n element: T,\r\n shape: T[\"type\"] extends keyof ElementShapes\r\n ? ElementShapes[T[\"type\"]]\r\n : Drawable,\r\n ) => ShapeCache.cache.set(element, shape);\r\n\r\n public static delete = (element: ExcalidrawElement) =>\r\n ShapeCache.cache.delete(element);\r\n\r\n public static destroy = () => {\r\n ShapeCache.cache = new WeakMap();\r\n };\r\n\r\n /**\r\n * Generates & caches shape for element if not already cached, otherwise\r\n * returns cached shape.\r\n */\r\n public static generateElementShape = <\r\n T extends Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,\r\n >(\r\n element: T,\r\n renderConfig: {\r\n isExporting: boolean;\r\n canvasBackgroundColor: AppState[\"viewBackgroundColor\"];\r\n embedsValidationStatus: EmbedsValidationStatus;\r\n } | null,\r\n ) => {\r\n // when exporting, always regenerated to guarantee the latest shape\r\n const cachedShape = renderConfig?.isExporting\r\n ? undefined\r\n : ShapeCache.get(element);\r\n\r\n // `null` indicates no rc shape applicable for this element type,\r\n // but it's considered a valid cache value (= do not regenerate)\r\n if (cachedShape !== undefined) {\r\n return cachedShape;\r\n }\r\n\r\n elementWithCanvasCache.delete(element);\r\n\r\n const shape = generateElementShape(\r\n element,\r\n ShapeCache.rg,\r\n renderConfig || {\r\n isExporting: false,\r\n canvasBackgroundColor: COLOR_PALETTE.white,\r\n embedsValidationStatus: null,\r\n },\r\n ) as T[\"type\"] extends keyof ElementShapes\r\n ? ElementShapes[T[\"type\"]]\r\n : Drawable | null;\r\n\r\n ShapeCache.cache.set(element, shape);\r\n\r\n return shape;\r\n };\r\n}\r\n\r\nconst getDashArrayDashed = (strokeWidth: number) => [8, 8 + strokeWidth];\r\n\r\nconst getDashArrayDotted = (strokeWidth: number) => [1.5, 6 + strokeWidth];\r\n\r\nfunction adjustRoughness(element: ExcalidrawElement): number {\r\n const roughness = element.roughness;\r\n\r\n const maxSize = Math.max(element.width, element.height);\r\n const minSize = Math.min(element.width, element.height);\r\n\r\n // don't reduce roughness if\r\n if (\r\n // both sides relatively big\r\n (minSize >= 20 && maxSize >= 50) ||\r\n // is round & both sides above 15px\r\n (minSize >= 15 &&\r\n !!element.roundness &&\r\n canChangeRoundness(element.type)) ||\r\n // relatively long linear element\r\n (isLinearElement(element) && maxSize >= 50)\r\n ) {\r\n return roughness;\r\n }\r\n\r\n return Math.min(roughness / (maxSize < 10 ? 3 : 2), 2.5);\r\n}\r\n\r\nexport const generateRoughOptions = (\r\n element: ExcalidrawElement,\r\n continuousPath = false,\r\n): Options => {\r\n const options: Options = {\r\n seed: element.seed,\r\n strokeLineDash:\r\n element.strokeStyle === \"dashed\"\r\n ? getDashArrayDashed(element.strokeWidth)\r\n : element.strokeStyle === \"dotted\"\r\n ? getDashArrayDotted(element.strokeWidth)\r\n : undefined,\r\n // for non-solid strokes, disable multiStroke because it tends to make\r\n // dashes/dots overlay each other\r\n disableMultiStroke: element.strokeStyle !== \"solid\",\r\n // for non-solid strokes, increase the width a bit to make it visually\r\n // similar to solid strokes, because we're also disabling multiStroke\r\n strokeWidth:\r\n element.strokeStyle !== \"solid\"\r\n ? element.strokeWidth + 0.5\r\n : element.strokeWidth,\r\n // when increasing strokeWidth, we must explicitly set fillWeight and\r\n // hachureGap because if not specified, roughjs uses strokeWidth to\r\n // calculate them (and we don't want the fills to be modified)\r\n fillWeight: element.strokeWidth / 2,\r\n hachureGap: element.strokeWidth * 4,\r\n roughness: adjustRoughness(element),\r\n stroke: element.strokeColor,\r\n preserveVertices:\r\n continuousPath || element.roughness < ROUGHNESS.cartoonist,\r\n };\r\n\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"iframe\":\r\n case \"embeddable\":\r\n case \"diamond\":\r\n case \"ellipse\": {\r\n options.fillStyle = element.fillStyle;\r\n options.fill = isTransparent(element.backgroundColor)\r\n ? undefined\r\n : element.backgroundColor;\r\n if (element.type === \"ellipse\") {\r\n options.curveFitting = 1;\r\n }\r\n return options;\r\n }\r\n case \"line\":\r\n case \"freedraw\": {\r\n if (isPathALoop(element.points)) {\r\n options.fillStyle = element.fillStyle;\r\n options.fill =\r\n element.backgroundColor === \"transparent\"\r\n ? undefined\r\n : element.backgroundColor;\r\n }\r\n return options;\r\n }\r\n case \"arrow\":\r\n return options;\r\n default: {\r\n throw new Error(`Unimplemented type ${element.type}`);\r\n }\r\n }\r\n};\r\n\r\nconst modifyIframeLikeForRoughOptions = (\r\n element: NonDeletedExcalidrawElement,\r\n isExporting: boolean,\r\n embedsValidationStatus: EmbedsValidationStatus | null,\r\n) => {\r\n if (\r\n isIframeLikeElement(element) &&\r\n (isExporting ||\r\n (isEmbeddableElement(element) &&\r\n embedsValidationStatus?.get(element.id) !== true)) &&\r\n isTransparent(element.backgroundColor) &&\r\n isTransparent(element.strokeColor)\r\n ) {\r\n return {\r\n ...element,\r\n roughness: 0,\r\n backgroundColor: \"#d3d3d3\",\r\n fillStyle: \"solid\",\r\n } as const;\r\n } else if (isIframeElement(element)) {\r\n return {\r\n ...element,\r\n strokeColor: isTransparent(element.strokeColor)\r\n ? \"#000000\"\r\n : element.strokeColor,\r\n backgroundColor: isTransparent(element.backgroundColor)\r\n ? \"#f4f4f6\"\r\n : element.backgroundColor,\r\n };\r\n }\r\n return element;\r\n};\r\n\r\nconst getArrowheadShapes = (\r\n element: ExcalidrawLinearElement,\r\n shape: Drawable[],\r\n position: \"start\" | \"end\",\r\n arrowhead: Arrowhead,\r\n generator: RoughGenerator,\r\n options: Options,\r\n canvasBackgroundColor: string,\r\n) => {\r\n const arrowheadPoints = getArrowheadPoints(\r\n element,\r\n shape,\r\n position,\r\n arrowhead,\r\n );\r\n\r\n if (arrowheadPoints === null) {\r\n return [];\r\n }\r\n\r\n const generateCrowfootOne = (\r\n arrowheadPoints: number[] | null,\r\n options: Options,\r\n ) => {\r\n if (arrowheadPoints === null) {\r\n return [];\r\n }\r\n\r\n const [, , x3, y3, x4, y4] = arrowheadPoints;\r\n\r\n return [generator.line(x3, y3, x4, y4, options)];\r\n };\r\n\r\n switch (arrowhead) {\r\n case \"dot\":\r\n case \"circle\":\r\n case \"circle_outline\": {\r\n const [x, y, diameter] = arrowheadPoints;\r\n\r\n // always use solid stroke for arrowhead\r\n delete options.strokeLineDash;\r\n\r\n return [\r\n generator.circle(x, y, diameter, {\r\n ...options,\r\n fill:\r\n arrowhead === \"circle_outline\"\r\n ? canvasBackgroundColor\r\n : element.strokeColor,\r\n\r\n fillStyle: \"solid\",\r\n stroke: element.strokeColor,\r\n roughness: Math.min(0.5, options.roughness || 0),\r\n }),\r\n ];\r\n }\r\n case \"triangle\":\r\n case \"triangle_outline\": {\r\n const [x, y, x2, y2, x3, y3] = arrowheadPoints;\r\n\r\n // always use solid stroke for arrowhead\r\n delete options.strokeLineDash;\r\n\r\n return [\r\n generator.polygon(\r\n [\r\n [x, y],\r\n [x2, y2],\r\n [x3, y3],\r\n [x, y],\r\n ],\r\n {\r\n ...options,\r\n fill:\r\n arrowhead === \"triangle_outline\"\r\n ? canvasBackgroundColor\r\n : element.strokeColor,\r\n fillStyle: \"solid\",\r\n roughness: Math.min(1, options.roughness || 0),\r\n },\r\n ),\r\n ];\r\n }\r\n case \"diamond\":\r\n case \"diamond_outline\": {\r\n const [x, y, x2, y2, x3, y3, x4, y4] = arrowheadPoints;\r\n\r\n // always use solid stroke for arrowhead\r\n delete options.strokeLineDash;\r\n\r\n return [\r\n generator.polygon(\r\n [\r\n [x, y],\r\n [x2, y2],\r\n [x3, y3],\r\n [x4, y4],\r\n [x, y],\r\n ],\r\n {\r\n ...options,\r\n fill:\r\n arrowhead === \"diamond_outline\"\r\n ? canvasBackgroundColor\r\n : element.strokeColor,\r\n fillStyle: \"solid\",\r\n roughness: Math.min(1, options.roughness || 0),\r\n },\r\n ),\r\n ];\r\n }\r\n case \"crowfoot_one\":\r\n return generateCrowfootOne(arrowheadPoints, options);\r\n case \"bar\":\r\n case \"arrow\":\r\n case \"crowfoot_many\":\r\n case \"crowfoot_one_or_many\":\r\n default: {\r\n const [x2, y2, x3, y3, x4, y4] = arrowheadPoints;\r\n\r\n if (element.strokeStyle === \"dotted\") {\r\n // for dotted arrows caps, reduce gap to make it more legible\r\n const dash = getDashArrayDotted(element.strokeWidth - 1);\r\n options.strokeLineDash = [dash[0], dash[1] - 1];\r\n } else {\r\n // for solid/dashed, keep solid arrow cap\r\n delete options.strokeLineDash;\r\n }\r\n options.roughness = Math.min(1, options.roughness || 0);\r\n return [\r\n generator.line(x3, y3, x2, y2, options),\r\n generator.line(x4, y4, x2, y2, options),\r\n ...(arrowhead === \"crowfoot_one_or_many\"\r\n ? generateCrowfootOne(\r\n getArrowheadPoints(element, shape, position, \"crowfoot_one\"),\r\n options,\r\n )\r\n : []),\r\n ];\r\n }\r\n }\r\n};\r\n\r\nexport const generateLinearCollisionShape = (\r\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\r\n) => {\r\n const generator = new RoughGenerator();\r\n const options: Options = {\r\n seed: element.seed,\r\n disableMultiStroke: true,\r\n disableMultiStrokeFill: true,\r\n roughness: 0,\r\n preserveVertices: true,\r\n };\r\n const center = getCenterForBounds(\r\n // Need a non-rotated center point\r\n element.points.reduce(\r\n (acc, point) => {\r\n return [\r\n Math.min(element.x + point[0], acc[0]),\r\n Math.min(element.y + point[1], acc[1]),\r\n Math.max(element.x + point[0], acc[2]),\r\n Math.max(element.y + point[1], acc[3]),\r\n ];\r\n },\r\n [Infinity, Infinity, -Infinity, -Infinity],\r\n ),\r\n );\r\n\r\n switch (element.type) {\r\n case \"line\":\r\n case \"arrow\": {\r\n // points array can be empty in the beginning, so it is important to add\r\n // initial position to it\r\n const points = element.points.length\r\n ? element.points\r\n : [pointFrom<LocalPoint>(0, 0)];\r\n\r\n if (isElbowArrow(element)) {\r\n return generator.path(generateElbowArrowShape(points, 16), options)\r\n .sets[0].ops;\r\n } else if (!element.roundness) {\r\n return points.map((point, idx) => {\r\n const p = pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x + point[0], element.y + point[1]),\r\n center,\r\n element.angle,\r\n );\r\n\r\n return {\r\n op: idx === 0 ? \"move\" : \"lineTo\",\r\n data: pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\r\n };\r\n });\r\n }\r\n\r\n return generator\r\n .curve(points as unknown as RoughPoint[], options)\r\n .sets[0].ops.slice(0, element.points.length)\r\n .map((op, i) => {\r\n if (i === 0) {\r\n const p = pointRotateRads<GlobalPoint>(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[0],\r\n element.y + op.data[1],\r\n ),\r\n center,\r\n element.angle,\r\n );\r\n\r\n return {\r\n op: \"move\",\r\n data: pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\r\n };\r\n }\r\n\r\n return {\r\n op: \"bcurveTo\",\r\n data: [\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[0],\r\n element.y + op.data[1],\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[2],\r\n element.y + op.data[3],\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[4],\r\n element.y + op.data[5],\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n ]\r\n .map((p) =>\r\n pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\r\n )\r\n .flat(),\r\n };\r\n });\r\n }\r\n case \"freedraw\": {\r\n if (element.points.length < 2) {\r\n return [];\r\n }\r\n\r\n const simplifiedPoints = simplify(\r\n element.points as Mutable<LocalPoint[]>,\r\n 0.75,\r\n );\r\n\r\n return generator\r\n .curve(simplifiedPoints as [number, number][], options)\r\n .sets[0].ops.slice(0, element.points.length)\r\n .map((op, i) => {\r\n if (i === 0) {\r\n const p = pointRotateRads<GlobalPoint>(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[0],\r\n element.y + op.data[1],\r\n ),\r\n center,\r\n element.angle,\r\n );\r\n\r\n return {\r\n op: \"move\",\r\n data: pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\r\n };\r\n }\r\n\r\n return {\r\n op: \"bcurveTo\",\r\n data: [\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[0],\r\n element.y + op.data[1],\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[2],\r\n element.y + op.data[3],\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[4],\r\n element.y + op.data[5],\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n ]\r\n .map((p) =>\r\n pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\r\n )\r\n .flat(),\r\n };\r\n });\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Generates the roughjs shape for given element.\r\n *\r\n * Low-level. Use `ShapeCache.generateElementShape` instead.\r\n *\r\n * @private\r\n */\r\nconst generateElementShape = (\r\n element: Exclude<NonDeletedExcalidrawElement, ExcalidrawSelectionElement>,\r\n generator: RoughGenerator,\r\n {\r\n isExporting,\r\n canvasBackgroundColor,\r\n embedsValidationStatus,\r\n }: {\r\n isExporting: boolean;\r\n canvasBackgroundColor: string;\r\n embedsValidationStatus: EmbedsValidationStatus | null;\r\n },\r\n): Drawable | Drawable[] | null => {\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"iframe\":\r\n case \"embeddable\": {\r\n let shape: ElementShapes[typeof element.type];\r\n // this is for rendering the stroke/bg of the embeddable, especially\r\n // when the src url is not set\r\n\r\n if (element.roundness) {\r\n const w = element.width;\r\n const h = element.height;\r\n const r = getCornerRadius(Math.min(w, h), element);\r\n shape = generator.path(\r\n `M ${r} 0 L ${w - r} 0 Q ${w} 0, ${w} ${r} L ${w} ${\r\n h - r\r\n } Q ${w} ${h}, ${w - r} ${h} L ${r} ${h} Q 0 ${h}, 0 ${\r\n h - r\r\n } L 0 ${r} Q 0 0, ${r} 0`,\r\n generateRoughOptions(\r\n modifyIframeLikeForRoughOptions(\r\n element,\r\n isExporting,\r\n embedsValidationStatus,\r\n ),\r\n true,\r\n ),\r\n );\r\n } else {\r\n shape = generator.rectangle(\r\n 0,\r\n 0,\r\n element.width,\r\n element.height,\r\n generateRoughOptions(\r\n modifyIframeLikeForRoughOptions(\r\n element,\r\n isExporting,\r\n embedsValidationStatus,\r\n ),\r\n false,\r\n ),\r\n );\r\n }\r\n return shape;\r\n }\r\n case \"diamond\": {\r\n let shape: ElementShapes[typeof element.type];\r\n\r\n const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =\r\n getDiamondPoints(element);\r\n if (element.roundness) {\r\n const verticalRadius = getCornerRadius(Math.abs(topX - leftX), element);\r\n\r\n const horizontalRadius = getCornerRadius(\r\n Math.abs(rightY - topY),\r\n element,\r\n );\r\n\r\n shape = generator.path(\r\n `M ${topX + verticalRadius} ${topY + horizontalRadius} L ${\r\n rightX - verticalRadius\r\n } ${rightY - horizontalRadius}\r\n C ${rightX} ${rightY}, ${rightX} ${rightY}, ${\r\n rightX - verticalRadius\r\n } ${rightY + horizontalRadius}\r\n L ${bottomX + verticalRadius} ${bottomY - horizontalRadius}\r\n C ${bottomX} ${bottomY}, ${bottomX} ${bottomY}, ${\r\n bottomX - verticalRadius\r\n } ${bottomY - horizontalRadius}\r\n L ${leftX + verticalRadius} ${leftY + horizontalRadius}\r\n C ${leftX} ${leftY}, ${leftX} ${leftY}, ${leftX + verticalRadius} ${\r\n leftY - horizontalRadius\r\n }\r\n L ${topX - verticalRadius} ${topY + horizontalRadius}\r\n C ${topX} ${topY}, ${topX} ${topY}, ${topX + verticalRadius} ${\r\n topY + horizontalRadius\r\n }`,\r\n generateRoughOptions(element, true),\r\n );\r\n } else {\r\n shape = generator.polygon(\r\n [\r\n [topX, topY],\r\n [rightX, rightY],\r\n [bottomX, bottomY],\r\n [leftX, leftY],\r\n ],\r\n generateRoughOptions(element),\r\n );\r\n }\r\n return shape;\r\n }\r\n case \"ellipse\": {\r\n const shape: ElementShapes[typeof element.type] = generator.ellipse(\r\n element.width / 2,\r\n element.height / 2,\r\n element.width,\r\n element.height,\r\n generateRoughOptions(element),\r\n );\r\n return shape;\r\n }\r\n case \"line\":\r\n case \"arrow\": {\r\n let shape: ElementShapes[typeof element.type];\r\n const options = generateRoughOptions(element);\r\n\r\n // points array can be empty in the beginning, so it is important to add\r\n // initial position to it\r\n const points = element.points.length\r\n ? element.points\r\n : [pointFrom<LocalPoint>(0, 0)];\r\n\r\n if (isElbowArrow(element)) {\r\n // NOTE (mtolmacs): Temporary fix for extremely big arrow shapes\r\n if (\r\n !points.every(\r\n (point) => Math.abs(point[0]) <= 1e6 && Math.abs(point[1]) <= 1e6,\r\n )\r\n ) {\r\n console.error(\r\n `Elbow arrow with extreme point positions detected. Arrow not rendered.`,\r\n element.id,\r\n JSON.stringify(points),\r\n );\r\n shape = [];\r\n } else {\r\n shape = [\r\n generator.path(\r\n generateElbowArrowShape(points, 16),\r\n generateRoughOptions(element, true),\r\n ),\r\n ];\r\n }\r\n } else if (!element.roundness) {\r\n // curve is always the first element\r\n // this simplifies finding the curve for an element\r\n if (options.fill) {\r\n shape = [\r\n generator.polygon(points as unknown as RoughPoint[], options),\r\n ];\r\n } else {\r\n shape = [\r\n generator.linearPath(points as unknown as RoughPoint[], options),\r\n ];\r\n }\r\n } else {\r\n shape = [generator.curve(points as unknown as RoughPoint[], options)];\r\n }\r\n\r\n // add lines only in arrow\r\n if (element.type === \"arrow\") {\r\n const { startArrowhead = null, endArrowhead = \"arrow\" } = element;\r\n\r\n if (startArrowhead !== null) {\r\n const shapes = getArrowheadShapes(\r\n element,\r\n shape,\r\n \"start\",\r\n startArrowhead,\r\n generator,\r\n options,\r\n canvasBackgroundColor,\r\n );\r\n shape.push(...shapes);\r\n }\r\n\r\n if (endArrowhead !== null) {\r\n if (endArrowhead === undefined) {\r\n // Hey, we have an old arrow here!\r\n }\r\n\r\n const shapes = getArrowheadShapes(\r\n element,\r\n shape,\r\n \"end\",\r\n endArrowhead,\r\n generator,\r\n options,\r\n canvasBackgroundColor,\r\n );\r\n shape.push(...shapes);\r\n }\r\n }\r\n return shape;\r\n }\r\n case \"freedraw\": {\r\n let shape: ElementShapes[typeof element.type];\r\n generateFreeDrawShape(element);\r\n\r\n if (isPathALoop(element.points)) {\r\n // generate rough polygon to fill freedraw shape\r\n const simplifiedPoints = simplify(\r\n element.points as Mutable<LocalPoint[]>,\r\n 0.75,\r\n );\r\n shape = generator.curve(simplifiedPoints as [number, number][], {\r\n ...generateRoughOptions(element),\r\n stroke: \"none\",\r\n });\r\n } else {\r\n shape = null;\r\n }\r\n return shape;\r\n }\r\n case \"frame\":\r\n case \"magicframe\":\r\n case \"text\":\r\n case \"image\": {\r\n const shape: ElementShapes[typeof element.type] = null;\r\n // we return (and cache) `null` to make sure we don't regenerate\r\n // `element.canvas` on rerenders\r\n return shape;\r\n }\r\n default: {\r\n assertNever(\r\n element,\r\n `generateElementShape(): Unimplemented type ${(element as any)?.type}`,\r\n );\r\n return null;\r\n }\r\n }\r\n};\r\n\r\nconst generateElbowArrowShape = (\r\n points: readonly LocalPoint[],\r\n radius: number,\r\n) => {\r\n const subpoints = [] as [number, number][];\r\n for (let i = 1; i < points.length - 1; i += 1) {\r\n const prev = points[i - 1];\r\n const next = points[i + 1];\r\n const point = points[i];\r\n const prevIsHorizontal = headingForPointIsHorizontal(point, prev);\r\n const nextIsHorizontal = headingForPointIsHorizontal(next, point);\r\n const corner = Math.min(\r\n radius,\r\n pointDistance(points[i], next) / 2,\r\n pointDistance(points[i], prev) / 2,\r\n );\r\n\r\n if (prevIsHorizontal) {\r\n if (prev[0] < point[0]) {\r\n // LEFT\r\n subpoints.push([points[i][0] - corner, points[i][1]]);\r\n } else {\r\n // RIGHT\r\n subpoints.push([points[i][0] + corner, points[i][1]]);\r\n }\r\n } else if (prev[1] < point[1]) {\r\n // UP\r\n subpoints.push([points[i][0], points[i][1] - corner]);\r\n } else {\r\n subpoints.push([points[i][0], points[i][1] + corner]);\r\n }\r\n\r\n subpoints.push(points[i] as [number, number]);\r\n\r\n if (nextIsHorizontal) {\r\n if (next[0] < point[0]) {\r\n // LEFT\r\n subpoints.push([points[i][0] - corner, points[i][1]]);\r\n } else {\r\n // RIGHT\r\n subpoints.push([points[i][0] + corner, points[i][1]]);\r\n }\r\n } else if (next[1] < point[1]) {\r\n // UP\r\n subpoints.push([points[i][0], points[i][1] - corner]);\r\n } else {\r\n // DOWN\r\n subpoints.push([points[i][0], points[i][1] + corner]);\r\n }\r\n }\r\n\r\n const d = [`M ${points[0][0]} ${points[0][1]}`];\r\n for (let i = 0; i < subpoints.length; i += 3) {\r\n d.push(`L ${subpoints[i][0]} ${subpoints[i][1]}`);\r\n d.push(\r\n `Q ${subpoints[i + 1][0]} ${subpoints[i + 1][1]}, ${\r\n subpoints[i + 2][0]\r\n } ${subpoints[i + 2][1]}`,\r\n );\r\n }\r\n d.push(`L ${points[points.length - 1][0]} ${points[points.length - 1][1]}`);\r\n\r\n return d.join(\" \");\r\n};\r\n\r\n/**\r\n * get the pure geometric shape of an excalidraw elementw\r\n * which is then used for hit detection\r\n */\r\nexport const getElementShape = <Point extends GlobalPoint | LocalPoint>(\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n): GeometricShape<Point> => {\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"diamond\":\r\n case \"frame\":\r\n case \"magicframe\":\r\n case \"embeddable\":\r\n case \"image\":\r\n case \"iframe\":\r\n case \"text\":\r\n case \"selection\":\r\n return getPolygonShape(element);\r\n case \"arrow\":\r\n case \"line\": {\r\n const roughShape =\r\n ShapeCache.get(element)?.[0] ??\r\n ShapeCache.generateElementShape(element, null)[0];\r\n const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);\r\n\r\n return shouldTestInside(element)\r\n ? getClosedCurveShape<Point>(\r\n element,\r\n roughShape,\r\n pointFrom<Point>(element.x, element.y),\r\n element.angle,\r\n pointFrom(cx, cy),\r\n )\r\n : getCurveShape<Point>(\r\n roughShape,\r\n pointFrom<Point>(element.x, element.y),\r\n element.angle,\r\n pointFrom(cx, cy),\r\n );\r\n }\r\n\r\n case \"ellipse\":\r\n return getEllipseShape(element);\r\n\r\n case \"freedraw\": {\r\n const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);\r\n return getFreedrawShape(\r\n element,\r\n pointFrom(cx, cy),\r\n shouldTestInside(element),\r\n );\r\n }\r\n }\r\n};\r\n\r\nexport const toggleLinePolygonState = (\r\n element: ExcalidrawLineElement,\r\n nextPolygonState: boolean,\r\n): {\r\n polygon: ExcalidrawLineElement[\"polygon\"];\r\n points: ExcalidrawLineElement[\"points\"];\r\n} | null => {\r\n const updatedPoints = [...element.points];\r\n\r\n if (nextPolygonState) {\r\n if (!canBecomePolygon(element.points)) {\r\n return null;\r\n }\r\n\r\n const firstPoint = updatedPoints[0];\r\n const lastPoint = updatedPoints[updatedPoints.length - 1];\r\n\r\n const distance = Math.hypot(\r\n firstPoint[0] - lastPoint[0],\r\n firstPoint[1] - lastPoint[1],\r\n );\r\n\r\n if (\r\n distance > LINE_POLYGON_POINT_MERGE_DISTANCE ||\r\n updatedPoints.length < 4\r\n ) {\r\n updatedPoints.push(pointFrom(firstPoint[0], firstPoint[1]));\r\n } else {\r\n updatedPoints[updatedPoints.length - 1] = pointFrom(\r\n firstPoint[0],\r\n firstPoint[1],\r\n );\r\n }\r\n }\r\n\r\n // TODO: satisfies ElementUpdate<ExcalidrawLineElement>\r\n const ret = {\r\n polygon: nextPolygonState,\r\n points: updatedPoints,\r\n };\r\n\r\n return ret;\r\n};\r\n", "import rough from \"roughjs/bin/rough\";\r\nimport { getStroke } from \"perfect-freehand\";\r\n\r\nimport {\r\n type GlobalPoint,\r\n isRightAngleRads,\r\n lineSegment,\r\n pointFrom,\r\n pointRotateRads,\r\n type Radians,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n BOUND_TEXT_PADDING,\r\n DEFAULT_REDUCED_GLOBAL_ALPHA,\r\n ELEMENT_READY_TO_ERASE_OPACITY,\r\n FRAME_STYLE,\r\n MIME_TYPES,\r\n THEME,\r\n distance,\r\n getFontString,\r\n isRTL,\r\n getVerticalOffset,\r\n invariant,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type {\r\n AppState,\r\n StaticCanvasAppState,\r\n Zoom,\r\n InteractiveCanvasAppState,\r\n ElementsPendingErasure,\r\n PendingExcalidrawElements,\r\n NormalizedZoomValue,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type {\r\n StaticCanvasRenderConfig,\r\n RenderableElementsMap,\r\n InteractiveCanvasRenderConfig,\r\n} from \"@excalidraw-modify/excalidraw/scene/types\";\r\n\r\nimport { getElementAbsoluteCoords, getElementBounds } from \"./bounds\";\r\nimport { getUncroppedImageElement } from \"./cropElement\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport {\r\n getBoundTextElement,\r\n getContainerCoords,\r\n getContainerElement,\r\n getBoundTextMaxHeight,\r\n getBoundTextMaxWidth,\r\n} from \"./textElement\";\r\nimport { getLineHeightInPx } from \"./textMeasurements\";\r\nimport {\r\n isTextElement,\r\n isLinearElement,\r\n isFreeDrawElement,\r\n isInitializedImageElement,\r\n isArrowElement,\r\n hasBoundTextElement,\r\n isMagicFrameElement,\r\n isImageElement,\r\n} from \"./typeChecks\";\r\nimport { getContainingFrame } from \"./frame\";\r\nimport { getCornerRadius } from \"./utils\";\r\n\r\nimport { ShapeCache } from \"./shape\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n ExcalidrawTextElement,\r\n NonDeletedExcalidrawElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawImageElement,\r\n ExcalidrawTextElementWithContainer,\r\n ExcalidrawFrameLikeElement,\r\n NonDeletedSceneElementsMap,\r\n ElementsMap,\r\n} from \"./types\";\r\n\r\nimport type { StrokeOptions } from \"perfect-freehand\";\r\nimport type { RoughCanvas } from \"roughjs/bin/canvas\";\r\n\r\n// using a stronger invert (100% vs our regular 93%) and saturate\r\n// as a temp hack to make images in dark theme look closer to original\r\n// color scheme (it's still not quite there and the colors look slightly\r\n// desatured, alas...)\r\nexport const IMAGE_INVERT_FILTER =\r\n \"invert(100%) hue-rotate(180deg) saturate(1.25)\";\r\n\r\nconst isPendingImageElement = (\r\n element: ExcalidrawElement,\r\n renderConfig: StaticCanvasRenderConfig,\r\n) =>\r\n isInitializedImageElement(element) &&\r\n !renderConfig.imageCache.has(element.fileId);\r\n\r\nconst shouldResetImageFilter = (\r\n element: ExcalidrawElement,\r\n renderConfig: StaticCanvasRenderConfig,\r\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\r\n) => {\r\n return (\r\n appState.theme === THEME.DARK &&\r\n isInitializedImageElement(element) &&\r\n !isPendingImageElement(element, renderConfig) &&\r\n renderConfig.imageCache.get(element.fileId)?.mimeType !== MIME_TYPES.svg\r\n );\r\n};\r\n\r\nconst getCanvasPadding = (element: ExcalidrawElement) => {\r\n switch (element.type) {\r\n case \"freedraw\":\r\n return element.strokeWidth * 12;\r\n case \"text\":\r\n return element.fontSize / 2;\r\n case \"arrow\":\r\n if (element.endArrowhead || element.endArrowhead) {\r\n return 40;\r\n }\r\n return 20;\r\n default:\r\n return 20;\r\n }\r\n};\r\n\r\nexport const getRenderOpacity = (\r\n element: ExcalidrawElement,\r\n containingFrame: ExcalidrawFrameLikeElement | null,\r\n elementsPendingErasure: ElementsPendingErasure,\r\n pendingNodes: Readonly<PendingExcalidrawElements> | null,\r\n globalAlpha: number = 1,\r\n) => {\r\n // multiplying frame opacity with element opacity to combine them\r\n // (e.g. frame 50% and element 50% opacity should result in 25% opacity)\r\n let opacity =\r\n (((containingFrame?.opacity ?? 100) * element.opacity) / 10000) *\r\n globalAlpha;\r\n\r\n // if pending erasure, multiply again to combine further\r\n // (so that erasing always results in lower opacity than original)\r\n if (\r\n elementsPendingErasure.has(element.id) ||\r\n (pendingNodes && pendingNodes.some((node) => node.id === element.id)) ||\r\n (containingFrame && elementsPendingErasure.has(containingFrame.id))\r\n ) {\r\n opacity *= ELEMENT_READY_TO_ERASE_OPACITY / 100;\r\n }\r\n\r\n return opacity;\r\n};\r\n\r\nexport interface ExcalidrawElementWithCanvas {\r\n element: ExcalidrawElement | ExcalidrawTextElement;\r\n canvas: HTMLCanvasElement;\r\n theme: AppState[\"theme\"];\r\n scale: number;\r\n angle: number;\r\n zoomValue: AppState[\"zoom\"][\"value\"];\r\n canvasOffsetX: number;\r\n canvasOffsetY: number;\r\n boundTextElementVersion: number | null;\r\n imageCrop: ExcalidrawImageElement[\"crop\"] | null;\r\n containingFrameOpacity: number;\r\n boundTextCanvas: HTMLCanvasElement;\r\n}\r\n\r\nconst cappedElementCanvasSize = (\r\n element: NonDeletedExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n zoom: Zoom,\r\n): {\r\n width: number;\r\n height: number;\r\n scale: number;\r\n} => {\r\n // these limits are ballpark, they depend on specific browsers and device.\r\n // We've chosen lower limits to be safe. We might want to change these limits\r\n // based on browser/device type, if we get reports of low quality rendering\r\n // on zoom.\r\n //\r\n // ~ safari mobile canvas area limit\r\n const AREA_LIMIT = 16777216;\r\n // ~ safari width/height limit based on developer.mozilla.org.\r\n const WIDTH_HEIGHT_LIMIT = 32767;\r\n\r\n const padding = getCanvasPadding(element);\r\n\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const elementWidth =\r\n isLinearElement(element) || isFreeDrawElement(element)\r\n ? distance(x1, x2)\r\n : element.width;\r\n const elementHeight =\r\n isLinearElement(element) || isFreeDrawElement(element)\r\n ? distance(y1, y2)\r\n : element.height;\r\n\r\n let width = elementWidth * window.devicePixelRatio + padding * 2;\r\n let height = elementHeight * window.devicePixelRatio + padding * 2;\r\n\r\n let scale: number = zoom.value;\r\n\r\n // rescale to ensure width and height is within limits\r\n if (\r\n width * scale > WIDTH_HEIGHT_LIMIT ||\r\n height * scale > WIDTH_HEIGHT_LIMIT\r\n ) {\r\n scale = Math.min(WIDTH_HEIGHT_LIMIT / width, WIDTH_HEIGHT_LIMIT / height);\r\n }\r\n\r\n // rescale to ensure canvas area is within limits\r\n if (width * height * scale * scale > AREA_LIMIT) {\r\n scale = Math.sqrt(AREA_LIMIT / (width * height));\r\n }\r\n\r\n width = Math.floor(width * scale);\r\n height = Math.floor(height * scale);\r\n\r\n return { width, height, scale };\r\n};\r\n\r\nconst generateElementCanvas = (\r\n element: NonDeletedExcalidrawElement,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n zoom: Zoom,\r\n renderConfig: StaticCanvasRenderConfig,\r\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\r\n): ExcalidrawElementWithCanvas | null => {\r\n const canvas = document.createElement(\"canvas\");\r\n const context = canvas.getContext(\"2d\")!;\r\n const padding = getCanvasPadding(element);\r\n\r\n const { width, height, scale } = cappedElementCanvasSize(\r\n element,\r\n elementsMap,\r\n zoom,\r\n );\r\n\r\n if (!width || !height) {\r\n return null;\r\n }\r\n\r\n canvas.width = width;\r\n canvas.height = height;\r\n\r\n let canvasOffsetX = -100;\r\n let canvasOffsetY = 0;\r\n\r\n if (isLinearElement(element) || isFreeDrawElement(element)) {\r\n const [x1, y1] = getElementAbsoluteCoords(element, elementsMap);\r\n\r\n canvasOffsetX =\r\n element.x > x1\r\n ? distance(element.x, x1) * window.devicePixelRatio * scale\r\n : 0;\r\n\r\n canvasOffsetY =\r\n element.y > y1\r\n ? distance(element.y, y1) * window.devicePixelRatio * scale\r\n : 0;\r\n\r\n context.translate(canvasOffsetX, canvasOffsetY);\r\n }\r\n\r\n context.save();\r\n context.translate(padding * scale, padding * scale);\r\n context.scale(\r\n window.devicePixelRatio * scale,\r\n window.devicePixelRatio * scale,\r\n );\r\n\r\n const rc = rough.canvas(canvas);\r\n\r\n // in dark theme, revert the image color filter\r\n if (shouldResetImageFilter(element, renderConfig, appState)) {\r\n context.filter = IMAGE_INVERT_FILTER;\r\n }\r\n\r\n drawElementOnCanvas(element, rc, context, renderConfig);\r\n\r\n context.restore();\r\n\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n const boundTextCanvas = document.createElement(\"canvas\");\r\n const boundTextCanvasContext = boundTextCanvas.getContext(\"2d\")!;\r\n\r\n if (isArrowElement(element) && boundTextElement) {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n // Take max dimensions of arrow canvas so that when canvas is rotated\r\n // the arrow doesn't get clipped\r\n const maxDim = Math.max(distance(x1, x2), distance(y1, y2));\r\n boundTextCanvas.width =\r\n maxDim * window.devicePixelRatio * scale + padding * scale * 10;\r\n boundTextCanvas.height =\r\n maxDim * window.devicePixelRatio * scale + padding * scale * 10;\r\n boundTextCanvasContext.translate(\r\n boundTextCanvas.width / 2,\r\n boundTextCanvas.height / 2,\r\n );\r\n boundTextCanvasContext.rotate(element.angle);\r\n boundTextCanvasContext.drawImage(\r\n canvas!,\r\n -canvas.width / 2,\r\n -canvas.height / 2,\r\n canvas.width,\r\n canvas.height,\r\n );\r\n\r\n const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords(\r\n boundTextElement,\r\n elementsMap,\r\n );\r\n\r\n boundTextCanvasContext.rotate(-element.angle);\r\n const offsetX = (boundTextCanvas.width - canvas!.width) / 2;\r\n const offsetY = (boundTextCanvas.height - canvas!.height) / 2;\r\n const shiftX =\r\n boundTextCanvas.width / 2 -\r\n (boundTextCx - x1) * window.devicePixelRatio * scale -\r\n offsetX -\r\n padding * scale;\r\n\r\n const shiftY =\r\n boundTextCanvas.height / 2 -\r\n (boundTextCy - y1) * window.devicePixelRatio * scale -\r\n offsetY -\r\n padding * scale;\r\n boundTextCanvasContext.translate(-shiftX, -shiftY);\r\n // Clear the bound text area\r\n boundTextCanvasContext.clearRect(\r\n -(boundTextElement.width / 2 + BOUND_TEXT_PADDING) *\r\n window.devicePixelRatio *\r\n scale,\r\n -(boundTextElement.height / 2 + BOUND_TEXT_PADDING) *\r\n window.devicePixelRatio *\r\n scale,\r\n (boundTextElement.width + BOUND_TEXT_PADDING * 2) *\r\n window.devicePixelRatio *\r\n scale,\r\n (boundTextElement.height + BOUND_TEXT_PADDING * 2) *\r\n window.devicePixelRatio *\r\n scale,\r\n );\r\n }\r\n\r\n return {\r\n element,\r\n canvas,\r\n theme: appState.theme,\r\n scale,\r\n zoomValue: zoom.value,\r\n canvasOffsetX,\r\n canvasOffsetY,\r\n boundTextElementVersion:\r\n getBoundTextElement(element, elementsMap)?.version || null,\r\n containingFrameOpacity:\r\n getContainingFrame(element, elementsMap)?.opacity || 100,\r\n boundTextCanvas,\r\n angle: element.angle,\r\n imageCrop: isImageElement(element) ? element.crop : null,\r\n };\r\n};\r\n\r\nexport const DEFAULT_LINK_SIZE = 14;\r\n\r\nconst IMAGE_PLACEHOLDER_IMG =\r\n typeof document !== \"undefined\"\r\n ? document.createElement(\"img\")\r\n : ({ src: \"\" } as HTMLImageElement); // mock image element outside of browser\r\n\r\nIMAGE_PLACEHOLDER_IMG.src = `data:${MIME_TYPES.svg},${encodeURIComponent(\r\n `<svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"fas\" data-icon=\"image\" class=\"svg-inline--fa fa-image fa-w-16\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"#888\" d=\"M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z\"></path></svg>`,\r\n)}`;\r\n\r\nconst IMAGE_ERROR_PLACEHOLDER_IMG =\r\n typeof document !== \"undefined\"\r\n ? document.createElement(\"img\")\r\n : ({ src: \"\" } as HTMLImageElement); // mock image element outside of browser\r\n\r\nIMAGE_ERROR_PLACEHOLDER_IMG.src = `data:${MIME_TYPES.svg},${encodeURIComponent(\r\n `<svg viewBox=\"0 0 668 668\" xmlns=\"http://www.w3.org/2000/svg\" xml:space=\"preserve\" style=\"fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2\"><path d=\"M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48ZM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56ZM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48Z\" style=\"fill:#888;fill-rule:nonzero\" transform=\"matrix(.81709 0 0 .81709 124.825 145.825)\"/><path d=\"M256 8C119.034 8 8 119.033 8 256c0 136.967 111.034 248 248 248s248-111.034 248-248S392.967 8 256 8Zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676ZM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676Z\" style=\"fill:#888;fill-rule:nonzero\" transform=\"matrix(.30366 0 0 .30366 506.822 60.065)\"/></svg>`,\r\n)}`;\r\n\r\nconst drawImagePlaceholder = (\r\n element: ExcalidrawImageElement,\r\n context: CanvasRenderingContext2D,\r\n) => {\r\n context.fillStyle = \"#E7E7E7\";\r\n context.fillRect(0, 0, element.width, element.height);\r\n\r\n const imageMinWidthOrHeight = Math.min(element.width, element.height);\r\n\r\n const size = Math.min(\r\n imageMinWidthOrHeight,\r\n Math.min(imageMinWidthOrHeight * 0.4, 100),\r\n );\r\n\r\n context.drawImage(\r\n element.status === \"error\"\r\n ? IMAGE_ERROR_PLACEHOLDER_IMG\r\n : IMAGE_PLACEHOLDER_IMG,\r\n element.width / 2 - size / 2,\r\n element.height / 2 - size / 2,\r\n size,\r\n size,\r\n );\r\n};\r\n\r\nconst drawElementOnCanvas = (\r\n element: NonDeletedExcalidrawElement,\r\n rc: RoughCanvas,\r\n context: CanvasRenderingContext2D,\r\n renderConfig: StaticCanvasRenderConfig,\r\n) => {\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"iframe\":\r\n case \"embeddable\":\r\n case \"diamond\":\r\n case \"ellipse\": {\r\n context.lineJoin = \"round\";\r\n context.lineCap = \"round\";\r\n rc.draw(ShapeCache.get(element)!);\r\n break;\r\n }\r\n case \"arrow\":\r\n case \"line\": {\r\n context.lineJoin = \"round\";\r\n context.lineCap = \"round\";\r\n\r\n ShapeCache.get(element)!.forEach((shape) => {\r\n rc.draw(shape);\r\n });\r\n break;\r\n }\r\n case \"freedraw\": {\r\n // Draw directly to canvas\r\n context.save();\r\n context.fillStyle = element.strokeColor;\r\n\r\n const path = getFreeDrawPath2D(element) as Path2D;\r\n const fillShape = ShapeCache.get(element);\r\n\r\n if (fillShape) {\r\n rc.draw(fillShape);\r\n }\r\n\r\n context.fillStyle = element.strokeColor;\r\n context.fill(path);\r\n\r\n context.restore();\r\n break;\r\n }\r\n case \"image\": {\r\n const img = isInitializedImageElement(element)\r\n ? renderConfig.imageCache.get(element.fileId)?.image\r\n : undefined;\r\n if (img != null && !(img instanceof Promise)) {\r\n if (element.roundness && context.roundRect) {\r\n context.beginPath();\r\n context.roundRect(\r\n 0,\r\n 0,\r\n element.width,\r\n element.height,\r\n getCornerRadius(Math.min(element.width, element.height), element),\r\n );\r\n context.clip();\r\n }\r\n\r\n const { x, y, width, height } = element.crop\r\n ? element.crop\r\n : {\r\n x: 0,\r\n y: 0,\r\n width: img.naturalWidth,\r\n height: img.naturalHeight,\r\n };\r\n\r\n context.drawImage(\r\n img,\r\n x,\r\n y,\r\n width,\r\n height,\r\n 0 /* hardcoded for the selection box*/,\r\n 0,\r\n element.width,\r\n element.height,\r\n );\r\n } else {\r\n drawImagePlaceholder(element, context);\r\n }\r\n break;\r\n }\r\n default: {\r\n if (isTextElement(element)) {\r\n const rtl = isRTL(element.text);\r\n const shouldTemporarilyAttach = rtl && !context.canvas.isConnected;\r\n if (shouldTemporarilyAttach) {\r\n // to correctly render RTL text mixed with LTR, we have to append it\r\n // to the DOM\r\n document.body.appendChild(context.canvas);\r\n }\r\n context.canvas.setAttribute(\"dir\", rtl ? \"rtl\" : \"ltr\");\r\n context.save();\r\n context.font = getFontString(element);\r\n context.fillStyle = element.strokeColor;\r\n context.textAlign = element.textAlign as CanvasTextAlign;\r\n\r\n // Canvas does not support multiline text by default\r\n const lines = element.text.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\r\n\r\n const horizontalOffset =\r\n element.textAlign === \"center\"\r\n ? element.width / 2\r\n : element.textAlign === \"right\"\r\n ? element.width\r\n : 0;\r\n\r\n const lineHeightPx = getLineHeightInPx(\r\n element.fontSize,\r\n element.lineHeight,\r\n );\r\n\r\n const verticalOffset = getVerticalOffset(\r\n element.fontFamily,\r\n element.fontSize,\r\n lineHeightPx,\r\n );\r\n\r\n for (let index = 0; index < lines.length; index++) {\r\n context.fillText(\r\n lines[index],\r\n horizontalOffset,\r\n index * lineHeightPx + verticalOffset,\r\n );\r\n }\r\n context.restore();\r\n if (shouldTemporarilyAttach) {\r\n context.canvas.remove();\r\n }\r\n } else {\r\n throw new Error(`Unimplemented type ${element.type}`);\r\n }\r\n }\r\n }\r\n};\r\n\r\nexport const elementWithCanvasCache = new WeakMap<\r\n ExcalidrawElement,\r\n ExcalidrawElementWithCanvas\r\n>();\r\n\r\nconst generateElementWithCanvas = (\r\n element: NonDeletedExcalidrawElement,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n renderConfig: StaticCanvasRenderConfig,\r\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\r\n) => {\r\n const zoom: Zoom = renderConfig\r\n ? appState.zoom\r\n : {\r\n value: 1 as NormalizedZoomValue,\r\n };\r\n const prevElementWithCanvas = elementWithCanvasCache.get(element);\r\n const shouldRegenerateBecauseZoom =\r\n prevElementWithCanvas &&\r\n prevElementWithCanvas.zoomValue !== zoom.value &&\r\n !appState?.shouldCacheIgnoreZoom;\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n const boundTextElementVersion = boundTextElement?.version || null;\r\n const imageCrop = isImageElement(element) ? element.crop : null;\r\n\r\n const containingFrameOpacity =\r\n getContainingFrame(element, elementsMap)?.opacity || 100;\r\n\r\n if (\r\n !prevElementWithCanvas ||\r\n shouldRegenerateBecauseZoom ||\r\n prevElementWithCanvas.theme !== appState.theme ||\r\n prevElementWithCanvas.boundTextElementVersion !== boundTextElementVersion ||\r\n prevElementWithCanvas.imageCrop !== imageCrop ||\r\n prevElementWithCanvas.containingFrameOpacity !== containingFrameOpacity ||\r\n // since we rotate the canvas when copying from cached canvas, we don't\r\n // regenerate the cached canvas. But we need to in case of labels which are\r\n // cached alongside the arrow, and we want the labels to remain unrotated\r\n // with respect to the arrow.\r\n (isArrowElement(element) &&\r\n boundTextElement &&\r\n element.angle !== prevElementWithCanvas.angle)\r\n ) {\r\n const elementWithCanvas = generateElementCanvas(\r\n element,\r\n elementsMap,\r\n zoom,\r\n renderConfig,\r\n appState,\r\n );\r\n\r\n if (!elementWithCanvas) {\r\n return null;\r\n }\r\n\r\n elementWithCanvasCache.set(element, elementWithCanvas);\r\n\r\n return elementWithCanvas;\r\n }\r\n return prevElementWithCanvas;\r\n};\r\n\r\nconst drawElementFromCanvas = (\r\n elementWithCanvas: ExcalidrawElementWithCanvas,\r\n context: CanvasRenderingContext2D,\r\n renderConfig: StaticCanvasRenderConfig,\r\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\r\n allElementsMap: NonDeletedSceneElementsMap,\r\n) => {\r\n const element = elementWithCanvas.element;\r\n const padding = getCanvasPadding(element);\r\n const zoom = elementWithCanvas.scale;\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, allElementsMap);\r\n const cx = ((x1 + x2) / 2 + appState.scrollX) * window.devicePixelRatio;\r\n const cy = ((y1 + y2) / 2 + appState.scrollY) * window.devicePixelRatio;\r\n\r\n context.save();\r\n context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);\r\n\r\n const boundTextElement = getBoundTextElement(element, allElementsMap);\r\n\r\n if (isArrowElement(element) && boundTextElement) {\r\n const offsetX =\r\n (elementWithCanvas.boundTextCanvas.width -\r\n elementWithCanvas.canvas!.width) /\r\n 2;\r\n const offsetY =\r\n (elementWithCanvas.boundTextCanvas.height -\r\n elementWithCanvas.canvas!.height) /\r\n 2;\r\n context.translate(cx, cy);\r\n context.drawImage(\r\n elementWithCanvas.boundTextCanvas,\r\n (-(x2 - x1) / 2) * window.devicePixelRatio - offsetX / zoom - padding,\r\n (-(y2 - y1) / 2) * window.devicePixelRatio - offsetY / zoom - padding,\r\n elementWithCanvas.boundTextCanvas.width / zoom,\r\n elementWithCanvas.boundTextCanvas.height / zoom,\r\n );\r\n } else {\r\n // we translate context to element center so that rotation and scale\r\n // originates from the element center\r\n context.translate(cx, cy);\r\n\r\n context.rotate(element.angle);\r\n\r\n if (\r\n \"scale\" in elementWithCanvas.element &&\r\n !isPendingImageElement(element, renderConfig)\r\n ) {\r\n context.scale(\r\n elementWithCanvas.element.scale[0],\r\n elementWithCanvas.element.scale[1],\r\n );\r\n }\r\n\r\n // revert afterwards we don't have account for it during drawing\r\n context.translate(-cx, -cy);\r\n\r\n context.drawImage(\r\n elementWithCanvas.canvas!,\r\n (x1 + appState.scrollX) * window.devicePixelRatio -\r\n (padding * elementWithCanvas.scale) / elementWithCanvas.scale,\r\n (y1 + appState.scrollY) * window.devicePixelRatio -\r\n (padding * elementWithCanvas.scale) / elementWithCanvas.scale,\r\n elementWithCanvas.canvas!.width / elementWithCanvas.scale,\r\n elementWithCanvas.canvas!.height / elementWithCanvas.scale,\r\n );\r\n\r\n if (\r\n import.meta.env.VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX ===\r\n \"true\" &&\r\n hasBoundTextElement(element)\r\n ) {\r\n const textElement = getBoundTextElement(\r\n element,\r\n allElementsMap,\r\n ) as ExcalidrawTextElementWithContainer;\r\n const coords = getContainerCoords(element);\r\n context.strokeStyle = \"#c92a2a\";\r\n context.lineWidth = 3;\r\n context.strokeRect(\r\n (coords.x + appState.scrollX) * window.devicePixelRatio,\r\n (coords.y + appState.scrollY) * window.devicePixelRatio,\r\n getBoundTextMaxWidth(element, textElement) * window.devicePixelRatio,\r\n getBoundTextMaxHeight(element, textElement) * window.devicePixelRatio,\r\n );\r\n }\r\n }\r\n context.restore();\r\n\r\n // Clear the nested element we appended to the DOM\r\n};\r\n\r\nexport const renderSelectionElement = (\r\n element: NonDeletedExcalidrawElement,\r\n context: CanvasRenderingContext2D,\r\n appState: InteractiveCanvasAppState,\r\n selectionColor: InteractiveCanvasRenderConfig[\"selectionColor\"],\r\n) => {\r\n context.save();\r\n context.translate(element.x + appState.scrollX, element.y + appState.scrollY);\r\n context.fillStyle = \"rgba(0, 0, 200, 0.04)\";\r\n\r\n // render from 0.5px offset to get 1px wide line\r\n // https://stackoverflow.com/questions/7530593/html5-canvas-and-line-width/7531540#7531540\r\n // TODO can be be improved by offseting to the negative when user selects\r\n // from right to left\r\n const offset = 0.5 / appState.zoom.value;\r\n\r\n context.fillRect(offset, offset, element.width, element.height);\r\n context.lineWidth = 1 / appState.zoom.value;\r\n context.strokeStyle = selectionColor;\r\n context.strokeRect(offset, offset, element.width, element.height);\r\n\r\n context.restore();\r\n};\r\n\r\nexport const renderElement = (\r\n element: NonDeletedExcalidrawElement,\r\n elementsMap: RenderableElementsMap,\r\n allElementsMap: NonDeletedSceneElementsMap,\r\n rc: RoughCanvas,\r\n context: CanvasRenderingContext2D,\r\n renderConfig: StaticCanvasRenderConfig,\r\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\r\n) => {\r\n const reduceAlphaForSelection =\r\n appState.openDialog?.name === \"elementLinkSelector\" &&\r\n !appState.selectedElementIds[element.id] &&\r\n !appState.hoveredElementIds[element.id];\r\n\r\n context.globalAlpha = getRenderOpacity(\r\n element,\r\n getContainingFrame(element, elementsMap),\r\n renderConfig.elementsPendingErasure,\r\n renderConfig.pendingFlowchartNodes,\r\n reduceAlphaForSelection ? DEFAULT_REDUCED_GLOBAL_ALPHA : 1,\r\n );\r\n\r\n switch (element.type) {\r\n case \"magicframe\":\r\n case \"frame\": {\r\n if (appState.frameRendering.enabled && appState.frameRendering.outline) {\r\n context.save();\r\n context.translate(\r\n element.x + appState.scrollX,\r\n element.y + appState.scrollY,\r\n );\r\n context.fillStyle = \"rgba(0, 0, 200, 0.04)\";\r\n\r\n context.lineWidth = FRAME_STYLE.strokeWidth / appState.zoom.value;\r\n context.strokeStyle = FRAME_STYLE.strokeColor;\r\n\r\n // TODO change later to only affect AI frames\r\n if (isMagicFrameElement(element)) {\r\n context.strokeStyle =\r\n appState.theme === THEME.LIGHT ? \"#7affd7\" : \"#1d8264\";\r\n }\r\n\r\n if (FRAME_STYLE.radius && context.roundRect) {\r\n context.beginPath();\r\n context.roundRect(\r\n 0,\r\n 0,\r\n element.width,\r\n element.height,\r\n FRAME_STYLE.radius / appState.zoom.value,\r\n );\r\n context.stroke();\r\n context.closePath();\r\n } else {\r\n context.strokeRect(0, 0, element.width, element.height);\r\n }\r\n\r\n context.restore();\r\n }\r\n break;\r\n }\r\n case \"freedraw\": {\r\n // TODO investigate if we can do this in situ. Right now we need to call\r\n // beforehand because math helpers (such as getElementAbsoluteCoords)\r\n // rely on existing shapes\r\n ShapeCache.generateElementShape(element, null);\r\n\r\n if (renderConfig.isExporting) {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2 + appState.scrollX;\r\n const cy = (y1 + y2) / 2 + appState.scrollY;\r\n const shiftX = (x2 - x1) / 2 - (element.x - x1);\r\n const shiftY = (y2 - y1) / 2 - (element.y - y1);\r\n context.save();\r\n context.translate(cx, cy);\r\n context.rotate(element.angle);\r\n context.translate(-shiftX, -shiftY);\r\n drawElementOnCanvas(element, rc, context, renderConfig);\r\n context.restore();\r\n } else {\r\n const elementWithCanvas = generateElementWithCanvas(\r\n element,\r\n allElementsMap,\r\n renderConfig,\r\n appState,\r\n );\r\n if (!elementWithCanvas) {\r\n return;\r\n }\r\n\r\n drawElementFromCanvas(\r\n elementWithCanvas,\r\n context,\r\n renderConfig,\r\n appState,\r\n allElementsMap,\r\n );\r\n }\r\n\r\n break;\r\n }\r\n case \"rectangle\":\r\n case \"diamond\":\r\n case \"ellipse\":\r\n case \"line\":\r\n case \"arrow\":\r\n case \"image\":\r\n case \"text\":\r\n case \"iframe\":\r\n case \"embeddable\": {\r\n // TODO investigate if we can do this in situ. Right now we need to call\r\n // beforehand because math helpers (such as getElementAbsoluteCoords)\r\n // rely on existing shapes\r\n ShapeCache.generateElementShape(element, renderConfig);\r\n if (renderConfig.isExporting) {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2 + appState.scrollX;\r\n const cy = (y1 + y2) / 2 + appState.scrollY;\r\n let shiftX = (x2 - x1) / 2 - (element.x - x1);\r\n let shiftY = (y2 - y1) / 2 - (element.y - y1);\r\n if (isTextElement(element)) {\r\n const container = getContainerElement(element, elementsMap);\r\n if (isArrowElement(container)) {\r\n const boundTextCoords =\r\n LinearElementEditor.getBoundTextElementPosition(\r\n container,\r\n element as ExcalidrawTextElementWithContainer,\r\n elementsMap,\r\n );\r\n shiftX = (x2 - x1) / 2 - (boundTextCoords.x - x1);\r\n shiftY = (y2 - y1) / 2 - (boundTextCoords.y - y1);\r\n }\r\n }\r\n context.save();\r\n context.translate(cx, cy);\r\n\r\n if (shouldResetImageFilter(element, renderConfig, appState)) {\r\n context.filter = \"none\";\r\n }\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n\r\n if (isArrowElement(element) && boundTextElement) {\r\n const tempCanvas = document.createElement(\"canvas\");\r\n\r\n const tempCanvasContext = tempCanvas.getContext(\"2d\")!;\r\n\r\n // Take max dimensions of arrow canvas so that when canvas is rotated\r\n // the arrow doesn't get clipped\r\n const maxDim = Math.max(distance(x1, x2), distance(y1, y2));\r\n const padding = getCanvasPadding(element);\r\n tempCanvas.width =\r\n maxDim * appState.exportScale + padding * 10 * appState.exportScale;\r\n tempCanvas.height =\r\n maxDim * appState.exportScale + padding * 10 * appState.exportScale;\r\n\r\n tempCanvasContext.translate(\r\n tempCanvas.width / 2,\r\n tempCanvas.height / 2,\r\n );\r\n tempCanvasContext.scale(appState.exportScale, appState.exportScale);\r\n\r\n // Shift the canvas to left most point of the arrow\r\n shiftX = element.width / 2 - (element.x - x1);\r\n shiftY = element.height / 2 - (element.y - y1);\r\n\r\n tempCanvasContext.rotate(element.angle);\r\n const tempRc = rough.canvas(tempCanvas);\r\n\r\n tempCanvasContext.translate(-shiftX, -shiftY);\r\n\r\n drawElementOnCanvas(element, tempRc, tempCanvasContext, renderConfig);\r\n\r\n tempCanvasContext.translate(shiftX, shiftY);\r\n\r\n tempCanvasContext.rotate(-element.angle);\r\n\r\n // Shift the canvas to center of bound text\r\n const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords(\r\n boundTextElement,\r\n elementsMap,\r\n );\r\n const boundTextShiftX = (x1 + x2) / 2 - boundTextCx;\r\n const boundTextShiftY = (y1 + y2) / 2 - boundTextCy;\r\n tempCanvasContext.translate(-boundTextShiftX, -boundTextShiftY);\r\n\r\n // Clear the bound text area\r\n tempCanvasContext.clearRect(\r\n -boundTextElement.width / 2,\r\n -boundTextElement.height / 2,\r\n boundTextElement.width,\r\n boundTextElement.height,\r\n );\r\n context.scale(1 / appState.exportScale, 1 / appState.exportScale);\r\n context.drawImage(\r\n tempCanvas,\r\n -tempCanvas.width / 2,\r\n -tempCanvas.height / 2,\r\n tempCanvas.width,\r\n tempCanvas.height,\r\n );\r\n } else {\r\n context.rotate(element.angle);\r\n\r\n if (element.type === \"image\") {\r\n // note: scale must be applied *after* rotating\r\n context.scale(element.scale[0], element.scale[1]);\r\n }\r\n\r\n context.translate(-shiftX, -shiftY);\r\n drawElementOnCanvas(element, rc, context, renderConfig);\r\n }\r\n\r\n context.restore();\r\n // not exporting \u2192 optimized rendering (cache & render from element\r\n // canvases)\r\n } else {\r\n const elementWithCanvas = generateElementWithCanvas(\r\n element,\r\n allElementsMap,\r\n renderConfig,\r\n appState,\r\n );\r\n\r\n if (!elementWithCanvas) {\r\n return;\r\n }\r\n\r\n const currentImageSmoothingStatus = context.imageSmoothingEnabled;\r\n\r\n if (\r\n // do not disable smoothing during zoom as blurry shapes look better\r\n // on low resolution (while still zooming in) than sharp ones\r\n !appState?.shouldCacheIgnoreZoom &&\r\n // angle is 0 -> always disable smoothing\r\n (!element.angle ||\r\n // or check if angle is a right angle in which case we can still\r\n // disable smoothing without adversely affecting the result\r\n // We need less-than comparison because of FP artihmetic\r\n isRightAngleRads(element.angle))\r\n ) {\r\n // Disabling smoothing makes output much sharper, especially for\r\n // text. Unless for non-right angles, where the aliasing is really\r\n // terrible on Chromium.\r\n //\r\n // Note that `context.imageSmoothingQuality=\"high\"` has almost\r\n // zero effect.\r\n //\r\n context.imageSmoothingEnabled = false;\r\n }\r\n\r\n if (\r\n element.id === appState.croppingElementId &&\r\n isImageElement(elementWithCanvas.element) &&\r\n elementWithCanvas.element.crop !== null\r\n ) {\r\n context.save();\r\n context.globalAlpha = 0.1;\r\n\r\n const uncroppedElementCanvas = generateElementCanvas(\r\n getUncroppedImageElement(elementWithCanvas.element, elementsMap),\r\n allElementsMap,\r\n appState.zoom,\r\n renderConfig,\r\n appState,\r\n );\r\n\r\n if (uncroppedElementCanvas) {\r\n drawElementFromCanvas(\r\n uncroppedElementCanvas,\r\n context,\r\n renderConfig,\r\n appState,\r\n allElementsMap,\r\n );\r\n }\r\n\r\n context.restore();\r\n }\r\n\r\n drawElementFromCanvas(\r\n elementWithCanvas,\r\n context,\r\n renderConfig,\r\n appState,\r\n allElementsMap,\r\n );\r\n\r\n // reset\r\n context.imageSmoothingEnabled = currentImageSmoothingStatus;\r\n }\r\n break;\r\n }\r\n default: {\r\n // @ts-ignore\r\n throw new Error(`Unimplemented type ${element.type}`);\r\n }\r\n }\r\n\r\n context.globalAlpha = 1;\r\n};\r\n\r\nexport const pathsCache = new WeakMap<ExcalidrawFreeDrawElement, Path2D>([]);\r\n\r\nexport function generateFreeDrawShape(element: ExcalidrawFreeDrawElement) {\r\n const svgPathData = getFreeDrawSvgPath(element);\r\n const path = new Path2D(svgPathData);\r\n pathsCache.set(element, path);\r\n return path;\r\n}\r\n\r\nexport function getFreeDrawPath2D(element: ExcalidrawFreeDrawElement) {\r\n return pathsCache.get(element);\r\n}\r\n\r\nexport function getFreeDrawSvgPath(element: ExcalidrawFreeDrawElement) {\r\n return getSvgPathFromStroke(getFreedrawOutlinePoints(element));\r\n}\r\n\r\nexport function getFreedrawOutlineAsSegments(\r\n element: ExcalidrawFreeDrawElement,\r\n points: [number, number][],\r\n elementsMap: ElementsMap,\r\n) {\r\n const bounds = getElementBounds(\r\n {\r\n ...element,\r\n angle: 0 as Radians,\r\n },\r\n elementsMap,\r\n );\r\n const center = pointFrom<GlobalPoint>(\r\n (bounds[0] + bounds[2]) / 2,\r\n (bounds[1] + bounds[3]) / 2,\r\n );\r\n\r\n invariant(points.length >= 2, \"Freepath outline must have at least 2 points\");\r\n\r\n return points.slice(2).reduce(\r\n (acc, curr) => {\r\n acc.push(\r\n lineSegment<GlobalPoint>(\r\n acc[acc.length - 1][1],\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(curr[0] + element.x, curr[1] + element.y),\r\n center,\r\n element.angle,\r\n ),\r\n ),\r\n );\r\n return acc;\r\n },\r\n [\r\n lineSegment<GlobalPoint>(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n points[0][0] + element.x,\r\n points[0][1] + element.y,\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n points[1][0] + element.x,\r\n points[1][1] + element.y,\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n ),\r\n ],\r\n );\r\n}\r\n\r\nexport function getFreedrawOutlinePoints(element: ExcalidrawFreeDrawElement) {\r\n // If input points are empty (should they ever be?) return a dot\r\n const inputPoints = element.simulatePressure\r\n ? element.points\r\n : element.points.length\r\n ? element.points.map(([x, y], i) => [x, y, element.pressures[i]])\r\n : [[0, 0, 0.5]];\r\n\r\n // Consider changing the options for simulated pressure vs real pressure\r\n const options: StrokeOptions = {\r\n simulatePressure: element.simulatePressure,\r\n size: element.strokeWidth * 4.25,\r\n thinning: 0.6,\r\n smoothing: 0.5,\r\n streamline: 0.5,\r\n easing: (t) => Math.sin((t * Math.PI) / 2), // https://easings.net/#easeOutSine\r\n last: true,\r\n };\r\n\r\n return getStroke(inputPoints as number[][], options) as [number, number][];\r\n}\r\n\r\nfunction med(A: number[], B: number[]) {\r\n return [(A[0] + B[0]) / 2, (A[1] + B[1]) / 2];\r\n}\r\n\r\n// Trim SVG path data so number are each two decimal points. This\r\n// improves SVG exports, and prevents rendering errors on points\r\n// with long decimals.\r\nconst TO_FIXED_PRECISION = /(\\s?[A-Z]?,?-?[0-9]*\\.[0-9]{0,2})(([0-9]|e|-)*)/g;\r\n\r\nfunction getSvgPathFromStroke(points: number[][]): string {\r\n if (!points.length) {\r\n return \"\";\r\n }\r\n\r\n const max = points.length - 1;\r\n\r\n return points\r\n .reduce(\r\n (acc, point, i, arr) => {\r\n if (i === max) {\r\n acc.push(point, med(point, arr[0]), \"L\", arr[0], \"Z\");\r\n } else {\r\n acc.push(point, med(point, arr[i + 1]));\r\n }\r\n return acc;\r\n },\r\n [\"M\", points[0], \"Q\"],\r\n )\r\n .join(\" \")\r\n .replace(TO_FIXED_PRECISION, \"$1\");\r\n}\r\n", "function $(e,t,u,x=h=>h){return e*x(.5-t*(.5-u))}function se(e){return[-e[0],-e[1]]}function l(e,t){return[e[0]+t[0],e[1]+t[1]]}function a(e,t){return[e[0]-t[0],e[1]-t[1]]}function b(e,t){return[e[0]*t,e[1]*t]}function he(e,t){return[e[0]/t,e[1]/t]}function R(e){return[e[1],-e[0]]}function B(e,t){return e[0]*t[0]+e[1]*t[1]}function ue(e,t){return e[0]===t[0]&&e[1]===t[1]}function ge(e){return Math.hypot(e[0],e[1])}function de(e){return e[0]*e[0]+e[1]*e[1]}function A(e,t){return de(a(e,t))}function G(e){return he(e,ge(e))}function ie(e,t){return Math.hypot(e[1]-t[1],e[0]-t[0])}function L(e,t,u){let x=Math.sin(u),h=Math.cos(u),y=e[0]-t[0],n=e[1]-t[1],f=y*h-n*x,d=y*x+n*h;return[f+t[0],d+t[1]]}function K(e,t,u){return l(e,b(a(t,e),u))}function ee(e,t,u){return l(e,b(t,u))}var{min:C,PI:xe}=Math,pe=.275,V=xe+1e-4;function ce(e,t={}){let{size:u=16,smoothing:x=.5,thinning:h=.5,simulatePressure:y=!0,easing:n=r=>r,start:f={},end:d={},last:D=!1}=t,{cap:S=!0,easing:j=r=>r*(2-r)}=f,{cap:q=!0,easing:c=r=>--r*r*r+1}=d;if(e.length===0||u<=0)return[];let p=e[e.length-1].runningLength,g=f.taper===!1?0:f.taper===!0?Math.max(u,p):f.taper,T=d.taper===!1?0:d.taper===!0?Math.max(u,p):d.taper,te=Math.pow(u*x,2),_=[],M=[],H=e.slice(0,10).reduce((r,i)=>{let o=i.pressure;if(y){let s=C(1,i.distance/u),W=C(1,1-s);o=C(1,r+(W-r)*(s*pe))}return(r+o)/2},e[0].pressure),m=$(u,h,e[e.length-1].pressure,n),U,X=e[0].vector,z=e[0].point,F=z,O=z,E=F,J=!1;for(let r=0;r<e.length;r++){let{pressure:i}=e[r],{point:o,vector:s,distance:W,runningLength:I}=e[r];if(r<e.length-1&&p-I<3)continue;if(h){if(y){let v=C(1,W/u),Z=C(1,1-v);i=C(1,H+(Z-H)*(v*pe))}m=$(u,h,i,n)}else m=u/2;U===void 0&&(U=m);let le=I<g?j(I/g):1,fe=p-I<T?c((p-I)/T):1;m=Math.max(.01,m*Math.min(le,fe));let re=(r<e.length-1?e[r+1]:e[r]).vector,Y=r<e.length-1?B(s,re):1,be=B(s,X)<0&&!J,ne=Y!==null&&Y<0;if(be||ne){let v=b(R(X),m);for(let Z=1/13,w=0;w<=1;w+=Z)O=L(a(o,v),o,V*w),_.push(O),E=L(l(o,v),o,V*-w),M.push(E);z=O,F=E,ne&&(J=!0);continue}if(J=!1,r===e.length-1){let v=b(R(s),m);_.push(a(o,v)),M.push(l(o,v));continue}let oe=b(R(K(re,s,Y)),m);O=a(o,oe),(r<=1||A(z,O)>te)&&(_.push(O),z=O),E=l(o,oe),(r<=1||A(F,E)>te)&&(M.push(E),F=E),H=i,X=s}let P=e[0].point.slice(0,2),k=e.length>1?e[e.length-1].point.slice(0,2):l(e[0].point,[1,1]),Q=[],N=[];if(e.length===1){if(!(g||T)||D){let r=ee(P,G(R(a(P,k))),-(U||m)),i=[];for(let o=1/13,s=o;s<=1;s+=o)i.push(L(r,P,V*2*s));return i}}else{if(!(g||T&&e.length===1))if(S)for(let i=1/13,o=i;o<=1;o+=i){let s=L(M[0],P,V*o);Q.push(s)}else{let i=a(_[0],M[0]),o=b(i,.5),s=b(i,.51);Q.push(a(P,o),a(P,s),l(P,s),l(P,o))}let r=R(se(e[e.length-1].vector));if(T||g&&e.length===1)N.push(k);else if(q){let i=ee(k,r,m);for(let o=1/29,s=o;s<1;s+=o)N.push(L(i,k,V*3*s))}else N.push(l(k,b(r,m)),l(k,b(r,m*.99)),a(k,b(r,m*.99)),a(k,b(r,m)))}return _.concat(N,M.reverse(),Q)}function me(e,t={}){var q;let{streamline:u=.5,size:x=16,last:h=!1}=t;if(e.length===0)return[];let y=.15+(1-u)*.85,n=Array.isArray(e[0])?e:e.map(({x:c,y:p,pressure:g=.5})=>[c,p,g]);if(n.length===2){let c=n[1];n=n.slice(0,-1);for(let p=1;p<5;p++)n.push(K(n[0],c,p/4))}n.length===1&&(n=[...n,[...l(n[0],[1,1]),...n[0].slice(2)]]);let f=[{point:[n[0][0],n[0][1]],pressure:n[0][2]>=0?n[0][2]:.25,vector:[1,1],distance:0,runningLength:0}],d=!1,D=0,S=f[0],j=n.length-1;for(let c=1;c<n.length;c++){let p=h&&c===j?n[c].slice(0,2):K(S.point,n[c],y);if(ue(S.point,p))continue;let g=ie(p,S.point);if(D+=g,c<j&&!d){if(D<x)continue;d=!0}S={point:p,pressure:n[c][2]>=0?n[c][2]:.5,vector:G(a(S.point,p)),distance:g,runningLength:D},f.push(S)}return f[0].vector=((q=f[1])==null?void 0:q.vector)||[0,0],f}function ae(e,t={}){return ce(me(e,t),t)}var _e=ae;export{_e as default,ae as getStroke,ce as getStrokeOutlinePoints,me as getStrokePoints};\n", "import {\r\n type Radians,\r\n pointFrom,\r\n pointCenter,\r\n pointRotateRads,\r\n vectorFromPoint,\r\n vectorNormalize,\r\n vectorSubtract,\r\n vectorAdd,\r\n vectorScale,\r\n pointFromVector,\r\n clamp,\r\n isCloseTo,\r\n} from \"@excalidraw-modify/math\";\r\nimport { type Point } from \"points-on-curve\";\r\n\r\nimport {\r\n elementCenterPoint,\r\n getElementAbsoluteCoords,\r\n getResizedElementAbsoluteCoords,\r\n} from \"./bounds\";\r\n\r\nimport type { TransformHandleType } from \"./transformHandles\";\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawElement,\r\n ExcalidrawImageElement,\r\n ImageCrop,\r\n NonDeleted,\r\n} from \"./types\";\r\n\r\nexport const MINIMAL_CROP_SIZE = 10;\r\n\r\nexport const cropElement = (\r\n element: ExcalidrawImageElement,\r\n elementsMap: ElementsMap,\r\n transformHandle: TransformHandleType,\r\n naturalWidth: number,\r\n naturalHeight: number,\r\n pointerX: number,\r\n pointerY: number,\r\n widthAspectRatio?: number,\r\n) => {\r\n const { width: uncroppedWidth, height: uncroppedHeight } =\r\n getUncroppedWidthAndHeight(element);\r\n\r\n const naturalWidthToUncropped = naturalWidth / uncroppedWidth;\r\n const naturalHeightToUncropped = naturalHeight / uncroppedHeight;\r\n\r\n const croppedLeft = (element.crop?.x ?? 0) / naturalWidthToUncropped;\r\n const croppedTop = (element.crop?.y ?? 0) / naturalHeightToUncropped;\r\n\r\n /**\r\n * uncropped width\r\n * *\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013*\r\n * | (x,y) (natural) |\r\n * | *\u2013\u2013\u2013\u2013\u2013\u2013\u2013* |\r\n * | |///////| height | uncropped height\r\n * | *\u2013\u2013\u2013\u2013\u2013\u2013\u2013* |\r\n * | width (natural) |\r\n * *\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013\u2013*\r\n */\r\n\r\n const rotatedPointer = pointRotateRads(\r\n pointFrom(pointerX, pointerY),\r\n elementCenterPoint(element, elementsMap),\r\n -element.angle as Radians,\r\n );\r\n\r\n pointerX = rotatedPointer[0];\r\n pointerY = rotatedPointer[1];\r\n\r\n let nextWidth = element.width;\r\n let nextHeight = element.height;\r\n\r\n let crop: ImageCrop | null = element.crop ?? {\r\n x: 0,\r\n y: 0,\r\n width: naturalWidth,\r\n height: naturalHeight,\r\n naturalWidth,\r\n naturalHeight,\r\n };\r\n\r\n const previousCropHeight = crop.height;\r\n const previousCropWidth = crop.width;\r\n\r\n const isFlippedByX = element.scale[0] === -1;\r\n const isFlippedByY = element.scale[1] === -1;\r\n\r\n let changeInHeight = pointerY - element.y;\r\n let changeInWidth = pointerX - element.x;\r\n\r\n if (transformHandle.includes(\"n\")) {\r\n nextHeight = clamp(\r\n element.height - changeInHeight,\r\n MINIMAL_CROP_SIZE,\r\n isFlippedByY ? uncroppedHeight - croppedTop : element.height + croppedTop,\r\n );\r\n }\r\n\r\n if (transformHandle.includes(\"s\")) {\r\n changeInHeight = pointerY - element.y - element.height;\r\n nextHeight = clamp(\r\n element.height + changeInHeight,\r\n MINIMAL_CROP_SIZE,\r\n isFlippedByY ? element.height + croppedTop : uncroppedHeight - croppedTop,\r\n );\r\n }\r\n\r\n if (transformHandle.includes(\"e\")) {\r\n changeInWidth = pointerX - element.x - element.width;\r\n\r\n nextWidth = clamp(\r\n element.width + changeInWidth,\r\n MINIMAL_CROP_SIZE,\r\n isFlippedByX ? element.width + croppedLeft : uncroppedWidth - croppedLeft,\r\n );\r\n }\r\n\r\n if (transformHandle.includes(\"w\")) {\r\n nextWidth = clamp(\r\n element.width - changeInWidth,\r\n MINIMAL_CROP_SIZE,\r\n isFlippedByX ? uncroppedWidth - croppedLeft : element.width + croppedLeft,\r\n );\r\n }\r\n\r\n const updateCropWidthAndHeight = (crop: ImageCrop) => {\r\n crop.height = nextHeight * naturalHeightToUncropped;\r\n crop.width = nextWidth * naturalWidthToUncropped;\r\n };\r\n\r\n updateCropWidthAndHeight(crop);\r\n\r\n const adjustFlipForHandle = (\r\n handle: TransformHandleType,\r\n crop: ImageCrop,\r\n ) => {\r\n updateCropWidthAndHeight(crop);\r\n if (handle.includes(\"n\")) {\r\n if (!isFlippedByY) {\r\n crop.y += previousCropHeight - crop.height;\r\n }\r\n }\r\n if (handle.includes(\"s\")) {\r\n if (isFlippedByY) {\r\n crop.y += previousCropHeight - crop.height;\r\n }\r\n }\r\n if (handle.includes(\"e\")) {\r\n if (isFlippedByX) {\r\n crop.x += previousCropWidth - crop.width;\r\n }\r\n }\r\n if (handle.includes(\"w\")) {\r\n if (!isFlippedByX) {\r\n crop.x += previousCropWidth - crop.width;\r\n }\r\n }\r\n };\r\n\r\n switch (transformHandle) {\r\n case \"n\": {\r\n if (widthAspectRatio) {\r\n const distanceToLeft = croppedLeft + element.width / 2;\r\n const distanceToRight =\r\n uncroppedWidth - croppedLeft - element.width / 2;\r\n\r\n const MAX_WIDTH = Math.min(distanceToLeft, distanceToRight) * 2;\r\n\r\n nextWidth = clamp(\r\n nextHeight * widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_WIDTH,\r\n );\r\n nextHeight = nextWidth / widthAspectRatio;\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n\r\n if (widthAspectRatio) {\r\n crop.x += (previousCropWidth - crop.width) / 2;\r\n }\r\n\r\n break;\r\n }\r\n case \"s\": {\r\n if (widthAspectRatio) {\r\n const distanceToLeft = croppedLeft + element.width / 2;\r\n const distanceToRight =\r\n uncroppedWidth - croppedLeft - element.width / 2;\r\n\r\n const MAX_WIDTH = Math.min(distanceToLeft, distanceToRight) * 2;\r\n\r\n nextWidth = clamp(\r\n nextHeight * widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_WIDTH,\r\n );\r\n nextHeight = nextWidth / widthAspectRatio;\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n\r\n if (widthAspectRatio) {\r\n crop.x += (previousCropWidth - crop.width) / 2;\r\n }\r\n\r\n break;\r\n }\r\n case \"w\": {\r\n if (widthAspectRatio) {\r\n const distanceToTop = croppedTop + element.height / 2;\r\n const distanceToBottom =\r\n uncroppedHeight - croppedTop - element.height / 2;\r\n\r\n const MAX_HEIGHT = Math.min(distanceToTop, distanceToBottom) * 2;\r\n\r\n nextHeight = clamp(\r\n nextWidth / widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_HEIGHT,\r\n );\r\n nextWidth = nextHeight * widthAspectRatio;\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n\r\n if (widthAspectRatio) {\r\n crop.y += (previousCropHeight - crop.height) / 2;\r\n }\r\n\r\n break;\r\n }\r\n case \"e\": {\r\n if (widthAspectRatio) {\r\n const distanceToTop = croppedTop + element.height / 2;\r\n const distanceToBottom =\r\n uncroppedHeight - croppedTop - element.height / 2;\r\n\r\n const MAX_HEIGHT = Math.min(distanceToTop, distanceToBottom) * 2;\r\n\r\n nextHeight = clamp(\r\n nextWidth / widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_HEIGHT,\r\n );\r\n nextWidth = nextHeight * widthAspectRatio;\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n\r\n if (widthAspectRatio) {\r\n crop.y += (previousCropHeight - crop.height) / 2;\r\n }\r\n\r\n break;\r\n }\r\n case \"ne\": {\r\n if (widthAspectRatio) {\r\n if (changeInWidth > -changeInHeight) {\r\n const MAX_HEIGHT = isFlippedByY\r\n ? uncroppedHeight - croppedTop\r\n : croppedTop + element.height;\r\n\r\n nextHeight = clamp(\r\n nextWidth / widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_HEIGHT,\r\n );\r\n nextWidth = nextHeight * widthAspectRatio;\r\n } else {\r\n const MAX_WIDTH = isFlippedByX\r\n ? croppedLeft + element.width\r\n : uncroppedWidth - croppedLeft;\r\n\r\n nextWidth = clamp(\r\n nextHeight * widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_WIDTH,\r\n );\r\n nextHeight = nextWidth / widthAspectRatio;\r\n }\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n break;\r\n }\r\n case \"nw\": {\r\n if (widthAspectRatio) {\r\n if (changeInWidth < changeInHeight) {\r\n const MAX_HEIGHT = isFlippedByY\r\n ? uncroppedHeight - croppedTop\r\n : croppedTop + element.height;\r\n nextHeight = clamp(\r\n nextWidth / widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_HEIGHT,\r\n );\r\n nextWidth = nextHeight * widthAspectRatio;\r\n } else {\r\n const MAX_WIDTH = isFlippedByX\r\n ? uncroppedWidth - croppedLeft\r\n : croppedLeft + element.width;\r\n\r\n nextWidth = clamp(\r\n nextHeight * widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_WIDTH,\r\n );\r\n nextHeight = nextWidth / widthAspectRatio;\r\n }\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n break;\r\n }\r\n case \"se\": {\r\n if (widthAspectRatio) {\r\n if (changeInWidth > changeInHeight) {\r\n const MAX_HEIGHT = isFlippedByY\r\n ? croppedTop + element.height\r\n : uncroppedHeight - croppedTop;\r\n\r\n nextHeight = clamp(\r\n nextWidth / widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_HEIGHT,\r\n );\r\n nextWidth = nextHeight * widthAspectRatio;\r\n } else {\r\n const MAX_WIDTH = isFlippedByX\r\n ? croppedLeft + element.width\r\n : uncroppedWidth - croppedLeft;\r\n\r\n nextWidth = clamp(\r\n nextHeight * widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_WIDTH,\r\n );\r\n nextHeight = nextWidth / widthAspectRatio;\r\n }\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n break;\r\n }\r\n case \"sw\": {\r\n if (widthAspectRatio) {\r\n if (-changeInWidth > changeInHeight) {\r\n const MAX_HEIGHT = isFlippedByY\r\n ? croppedTop + element.height\r\n : uncroppedHeight - croppedTop;\r\n\r\n nextHeight = clamp(\r\n nextWidth / widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_HEIGHT,\r\n );\r\n nextWidth = nextHeight * widthAspectRatio;\r\n } else {\r\n const MAX_WIDTH = isFlippedByX\r\n ? uncroppedWidth - croppedLeft\r\n : croppedLeft + element.width;\r\n\r\n nextWidth = clamp(\r\n nextHeight * widthAspectRatio,\r\n MINIMAL_CROP_SIZE,\r\n MAX_WIDTH,\r\n );\r\n nextHeight = nextWidth / widthAspectRatio;\r\n }\r\n }\r\n\r\n adjustFlipForHandle(transformHandle, crop);\r\n break;\r\n }\r\n default:\r\n break;\r\n }\r\n\r\n const newOrigin = recomputeOrigin(\r\n element,\r\n transformHandle,\r\n nextWidth,\r\n nextHeight,\r\n !!widthAspectRatio,\r\n );\r\n\r\n // reset crop to null if we're back to orig size\r\n if (\r\n isCloseTo(crop.width, crop.naturalWidth) &&\r\n isCloseTo(crop.height, crop.naturalHeight)\r\n ) {\r\n crop = null;\r\n }\r\n\r\n return {\r\n x: newOrigin[0],\r\n y: newOrigin[1],\r\n width: nextWidth,\r\n height: nextHeight,\r\n crop,\r\n };\r\n};\r\n\r\nconst recomputeOrigin = (\r\n stateAtCropStart: NonDeleted<ExcalidrawElement>,\r\n transformHandle: TransformHandleType,\r\n width: number,\r\n height: number,\r\n shouldMaintainAspectRatio?: boolean,\r\n) => {\r\n const [x1, y1, x2, y2] = getResizedElementAbsoluteCoords(\r\n stateAtCropStart,\r\n stateAtCropStart.width,\r\n stateAtCropStart.height,\r\n true,\r\n );\r\n const startTopLeft = pointFrom(x1, y1);\r\n const startBottomRight = pointFrom(x2, y2);\r\n const startCenter: any = pointCenter(startTopLeft, startBottomRight);\r\n\r\n const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] =\r\n getResizedElementAbsoluteCoords(stateAtCropStart, width, height, true);\r\n const newBoundsWidth = newBoundsX2 - newBoundsX1;\r\n const newBoundsHeight = newBoundsY2 - newBoundsY1;\r\n\r\n // Calculate new topLeft based on fixed corner during resize\r\n let newTopLeft = [...startTopLeft] as [number, number];\r\n\r\n if ([\"n\", \"w\", \"nw\"].includes(transformHandle)) {\r\n newTopLeft = [\r\n startBottomRight[0] - Math.abs(newBoundsWidth),\r\n startBottomRight[1] - Math.abs(newBoundsHeight),\r\n ];\r\n }\r\n if (transformHandle === \"ne\") {\r\n const bottomLeft = [startTopLeft[0], startBottomRight[1]];\r\n newTopLeft = [bottomLeft[0], bottomLeft[1] - Math.abs(newBoundsHeight)];\r\n }\r\n if (transformHandle === \"sw\") {\r\n const topRight = [startBottomRight[0], startTopLeft[1]];\r\n newTopLeft = [topRight[0] - Math.abs(newBoundsWidth), topRight[1]];\r\n }\r\n\r\n if (shouldMaintainAspectRatio) {\r\n if ([\"s\", \"n\"].includes(transformHandle)) {\r\n newTopLeft[0] = startCenter[0] - newBoundsWidth / 2;\r\n }\r\n if ([\"e\", \"w\"].includes(transformHandle)) {\r\n newTopLeft[1] = startCenter[1] - newBoundsHeight / 2;\r\n }\r\n }\r\n\r\n // adjust topLeft to new rotation point\r\n const angle = stateAtCropStart.angle;\r\n const rotatedTopLeft = pointRotateRads(newTopLeft, startCenter, angle);\r\n const newCenter: Point = [\r\n newTopLeft[0] + Math.abs(newBoundsWidth) / 2,\r\n newTopLeft[1] + Math.abs(newBoundsHeight) / 2,\r\n ];\r\n const rotatedNewCenter = pointRotateRads(newCenter, startCenter, angle);\r\n newTopLeft = pointRotateRads(\r\n rotatedTopLeft,\r\n rotatedNewCenter,\r\n -angle as Radians,\r\n );\r\n\r\n const newOrigin = [...newTopLeft];\r\n newOrigin[0] += stateAtCropStart.x - newBoundsX1;\r\n newOrigin[1] += stateAtCropStart.y - newBoundsY1;\r\n\r\n return newOrigin;\r\n};\r\n\r\n// refer to https://link.excalidraw.com/l/6rfy1007QOo/6stx5PmRn0k\r\nexport const getUncroppedImageElement = (\r\n element: ExcalidrawImageElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (element.crop) {\r\n const { width, height } = getUncroppedWidthAndHeight(element);\r\n\r\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\r\n element,\r\n elementsMap,\r\n );\r\n\r\n const topLeftVector = vectorFromPoint(\r\n pointRotateRads(pointFrom(x1, y1), pointFrom(cx, cy), element.angle),\r\n );\r\n const topRightVector = vectorFromPoint(\r\n pointRotateRads(pointFrom(x2, y1), pointFrom(cx, cy), element.angle),\r\n );\r\n const topEdgeNormalized = vectorNormalize(\r\n vectorSubtract(topRightVector, topLeftVector),\r\n );\r\n const bottomLeftVector = vectorFromPoint(\r\n pointRotateRads(pointFrom(x1, y2), pointFrom(cx, cy), element.angle),\r\n );\r\n const leftEdgeVector = vectorSubtract(bottomLeftVector, topLeftVector);\r\n const leftEdgeNormalized = vectorNormalize(leftEdgeVector);\r\n\r\n const { cropX, cropY } = adjustCropPosition(element.crop, element.scale);\r\n\r\n const rotatedTopLeft = vectorAdd(\r\n vectorAdd(\r\n topLeftVector,\r\n vectorScale(\r\n topEdgeNormalized,\r\n (-cropX * width) / element.crop.naturalWidth,\r\n ),\r\n ),\r\n vectorScale(\r\n leftEdgeNormalized,\r\n (-cropY * height) / element.crop.naturalHeight,\r\n ),\r\n );\r\n\r\n const center = pointFromVector(\r\n vectorAdd(\r\n vectorAdd(rotatedTopLeft, vectorScale(topEdgeNormalized, width / 2)),\r\n vectorScale(leftEdgeNormalized, height / 2),\r\n ),\r\n );\r\n\r\n const unrotatedTopLeft = pointRotateRads(\r\n pointFromVector(rotatedTopLeft),\r\n center,\r\n -element.angle as Radians,\r\n );\r\n\r\n const uncroppedElement: ExcalidrawImageElement = {\r\n ...element,\r\n x: unrotatedTopLeft[0],\r\n y: unrotatedTopLeft[1],\r\n width,\r\n height,\r\n crop: null,\r\n };\r\n\r\n return uncroppedElement;\r\n }\r\n\r\n return element;\r\n};\r\n\r\nexport const getUncroppedWidthAndHeight = (element: ExcalidrawImageElement) => {\r\n if (element.crop) {\r\n const width =\r\n element.width / (element.crop.width / element.crop.naturalWidth);\r\n const height =\r\n element.height / (element.crop.height / element.crop.naturalHeight);\r\n\r\n return {\r\n width,\r\n height,\r\n };\r\n }\r\n\r\n return {\r\n width: element.width,\r\n height: element.height,\r\n };\r\n};\r\n\r\nconst adjustCropPosition = (\r\n crop: ImageCrop,\r\n scale: ExcalidrawImageElement[\"scale\"],\r\n) => {\r\n let cropX = crop.x;\r\n let cropY = crop.y;\r\n\r\n const flipX = scale[0] === -1;\r\n const flipY = scale[1] === -1;\r\n\r\n if (flipX) {\r\n cropX = crop.naturalWidth - Math.abs(cropX) - crop.width;\r\n }\r\n\r\n if (flipY) {\r\n cropY = crop.naturalHeight - Math.abs(cropY) - crop.height;\r\n }\r\n\r\n return {\r\n cropX,\r\n cropY,\r\n };\r\n};\r\n\r\nexport const getFlipAdjustedCropPosition = (\r\n element: ExcalidrawImageElement,\r\n natural = false,\r\n) => {\r\n const crop = element.crop;\r\n if (!crop) {\r\n return null;\r\n }\r\n\r\n const isFlippedByX = element.scale[0] === -1;\r\n const isFlippedByY = element.scale[1] === -1;\r\n\r\n let cropX = crop.x;\r\n let cropY = crop.y;\r\n\r\n if (isFlippedByX) {\r\n cropX = crop.naturalWidth - crop.width - crop.x;\r\n }\r\n\r\n if (isFlippedByY) {\r\n cropY = crop.naturalHeight - crop.height - crop.y;\r\n }\r\n\r\n if (natural) {\r\n return {\r\n x: cropX,\r\n y: cropY,\r\n };\r\n }\r\n\r\n const { width, height } = getUncroppedWidthAndHeight(element);\r\n\r\n return {\r\n x: cropX / (crop.naturalWidth / width),\r\n y: cropY / (crop.naturalHeight / height),\r\n };\r\n};\r\n", "import {\r\n pointCenter,\r\n pointFrom,\r\n pointRotateRads,\r\n pointsEqual,\r\n type GlobalPoint,\r\n type LocalPoint,\r\n pointDistance,\r\n vectorFromPoint,\r\n curveLength,\r\n curvePointAtLength,\r\n lineSegment,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport { getCurvePathOps } from \"@excalidraw/utils/shape\";\r\n\r\nimport {\r\n DRAGGING_THRESHOLD,\r\n KEYS,\r\n shouldRotateWithDiscreteAngle,\r\n getGridPoint,\r\n invariant,\r\n isShallowEqual,\r\n getFeatureFlag,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n deconstructLinearOrFreeDrawElement,\r\n isPathALoop,\r\n moveArrowAboveBindable,\r\n projectFixedPointOntoDiagonal,\r\n type Store,\r\n} from \"@excalidraw-modify/element\";\r\n\r\nimport type { Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport type {\r\n AppState,\r\n PointerCoords,\r\n InteractiveCanvasAppState,\r\n AppClassProperties,\r\n NullableGridSize,\r\n Zoom,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { Bounds } from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n calculateFixedPointForNonElbowArrowBinding,\r\n getBindingStrategyForDraggingBindingElementEndpoints,\r\n isBindingEnabled,\r\n updateBoundPoint,\r\n} from \"./binding\";\r\nimport {\r\n getElementAbsoluteCoords,\r\n getElementPointsCoords,\r\n getMinMaxXYFromCurvePathOps,\r\n} from \"./bounds\";\r\n\r\nimport { headingIsHorizontal, vectorToHeading } from \"./heading\";\r\nimport { mutateElement } from \"./mutateElement\";\r\nimport { getBoundTextElement, handleBindTextResize } from \"./textElement\";\r\nimport { isArrowElement, isBindingElement, isElbowArrow } from \"./typeChecks\";\r\n\r\nimport { ShapeCache, toggleLinePolygonState } from \"./shape\";\r\n\r\nimport { getLockedLinearCursorAlignSize } from \"./sizeHelpers\";\r\n\r\nimport { isLineElement } from \"./typeChecks\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\nimport type {\r\n NonDeleted,\r\n ExcalidrawLinearElement,\r\n ExcalidrawElement,\r\n ExcalidrawTextElementWithContainer,\r\n ElementsMap,\r\n NonDeletedSceneElementsMap,\r\n FixedPointBinding,\r\n FixedSegment,\r\n ExcalidrawElbowArrowElement,\r\n PointsPositionUpdates,\r\n NonDeletedExcalidrawElement,\r\n Ordered,\r\n ExcalidrawBindableElement,\r\n} from \"./types\";\r\n\r\n/**\r\n * Normalizes line points so that the start point is at [0,0]. This is\r\n * expected in various parts of the codebase.\r\n *\r\n * Also returns the offsets - [0,0] if no normalization needed.\r\n *\r\n * @private\r\n */\r\nconst getNormalizedPoints = ({\r\n points,\r\n}: {\r\n points: ExcalidrawLinearElement[\"points\"];\r\n}): {\r\n points: LocalPoint[];\r\n offsetX: number;\r\n offsetY: number;\r\n} => {\r\n const offsetX = points[0][0];\r\n const offsetY = points[0][1];\r\n\r\n return {\r\n points: points.map((p) => {\r\n return pointFrom(p[0] - offsetX, p[1] - offsetY);\r\n }),\r\n offsetX,\r\n offsetY,\r\n };\r\n};\r\n\r\ntype PointMoveOtherUpdates = {\r\n startBinding?: FixedPointBinding | null;\r\n endBinding?: FixedPointBinding | null;\r\n moveMidPointsWithElement?: boolean | null;\r\n suggestedBinding?: AppState[\"suggestedBinding\"] | null;\r\n};\r\n\r\nexport class LinearElementEditor {\r\n public readonly elementId: ExcalidrawElement[\"id\"] & {\r\n _brand: \"excalidrawLinearElementId\";\r\n };\r\n /** indices */\r\n public readonly selectedPointsIndices: readonly number[] | null;\r\n\r\n public readonly initialState: Readonly<{\r\n prevSelectedPointsIndices: readonly number[] | null;\r\n /** index */\r\n lastClickedPoint: number;\r\n origin: Readonly<GlobalPoint> | null;\r\n segmentMidpoint: {\r\n value: GlobalPoint | null;\r\n index: number | null;\r\n added: boolean;\r\n };\r\n arrowStartIsInside: boolean;\r\n altFocusPoint: Readonly<GlobalPoint> | null;\r\n }>;\r\n\r\n /** whether you're dragging a point */\r\n public readonly isDragging: boolean;\r\n public readonly lastUncommittedPoint: LocalPoint | null;\r\n public readonly lastCommittedPoint: LocalPoint | null;\r\n public readonly pointerOffset: Readonly<{ x: number; y: number }>;\r\n public readonly hoverPointIndex: number;\r\n public readonly segmentMidPointHoveredCoords: GlobalPoint | null;\r\n public readonly elbowed: boolean;\r\n public readonly customLineAngle: number | null;\r\n public readonly isEditing: boolean;\r\n\r\n // @deprecated renamed to initialState because the data is used during linear\r\n // element click creation as well (with multiple pointer down events)\r\n // @ts-ignore\r\n public readonly pointerDownState: never;\r\n\r\n constructor(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elementsMap: ElementsMap,\r\n isEditing: boolean = false,\r\n ) {\r\n this.elementId = element.id as string & {\r\n _brand: \"excalidrawLinearElementId\";\r\n };\r\n if (!pointsEqual(element.points[0], pointFrom(0, 0))) {\r\n console.error(\"Linear element is not normalized\", Error().stack);\r\n mutateElement(\r\n element,\r\n elementsMap,\r\n LinearElementEditor.getNormalizeElementPointsAndCoords(element),\r\n );\r\n }\r\n this.selectedPointsIndices = null;\r\n this.lastUncommittedPoint = null;\r\n this.lastCommittedPoint = null;\r\n this.isDragging = false;\r\n this.pointerOffset = { x: 0, y: 0 };\r\n this.initialState = {\r\n prevSelectedPointsIndices: null,\r\n lastClickedPoint: -1,\r\n origin: null,\r\n\r\n segmentMidpoint: {\r\n value: null,\r\n index: null,\r\n added: false,\r\n },\r\n arrowStartIsInside: false,\r\n altFocusPoint: null,\r\n };\r\n this.hoverPointIndex = -1;\r\n this.segmentMidPointHoveredCoords = null;\r\n this.elbowed = isElbowArrow(element) && element.elbowed;\r\n this.customLineAngle = null;\r\n this.isEditing = isEditing;\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n // static methods\r\n // ---------------------------------------------------------------------------\r\n\r\n static POINT_HANDLE_SIZE = 10;\r\n\r\n /**\r\n * @param id the `elementId` from the instance of this class (so that we can\r\n * statically guarantee this method returns an ExcalidrawLinearElement)\r\n */\r\n static getElement<T extends ExcalidrawLinearElement>(\r\n id: InstanceType<typeof LinearElementEditor>[\"elementId\"],\r\n elementsMap: ElementsMap,\r\n ): T | null {\r\n const element = elementsMap.get(id);\r\n if (element) {\r\n return element as NonDeleted<T>;\r\n }\r\n return null;\r\n }\r\n\r\n static handleBoxSelection(\r\n event: PointerEvent,\r\n appState: AppState,\r\n setState: React.Component<any, AppState>[\"setState\"],\r\n elementsMap: NonDeletedSceneElementsMap,\r\n ) {\r\n if (\r\n !appState.selectedLinearElement?.isEditing ||\r\n !appState.selectionElement\r\n ) {\r\n return false;\r\n }\r\n const { selectedLinearElement } = appState;\r\n const { selectedPointsIndices, elementId } = selectedLinearElement;\r\n\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n if (!element) {\r\n return false;\r\n }\r\n\r\n const [selectionX1, selectionY1, selectionX2, selectionY2] =\r\n getElementAbsoluteCoords(appState.selectionElement, elementsMap);\r\n\r\n const pointsSceneCoords = LinearElementEditor.getPointsGlobalCoordinates(\r\n element,\r\n elementsMap,\r\n );\r\n\r\n const nextSelectedPoints = pointsSceneCoords\r\n .reduce((acc: number[], point, index) => {\r\n if (\r\n (point[0] >= selectionX1 &&\r\n point[0] <= selectionX2 &&\r\n point[1] >= selectionY1 &&\r\n point[1] <= selectionY2) ||\r\n (event.shiftKey && selectedPointsIndices?.includes(index))\r\n ) {\r\n acc.push(index);\r\n }\r\n\r\n return acc;\r\n }, [])\r\n .filter((index) => {\r\n if (\r\n isElbowArrow(element) &&\r\n index !== 0 &&\r\n index !== element.points.length - 1\r\n ) {\r\n return false;\r\n }\r\n return true;\r\n });\r\n\r\n setState({\r\n selectedLinearElement: {\r\n ...selectedLinearElement,\r\n selectedPointsIndices: nextSelectedPoints.length\r\n ? nextSelectedPoints\r\n : null,\r\n },\r\n });\r\n }\r\n\r\n static handlePointerMove(\r\n event: PointerEvent,\r\n app: AppClassProperties,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n linearElementEditor: LinearElementEditor,\r\n ): Pick<AppState, \"suggestedBinding\" | \"selectedLinearElement\"> | null {\r\n const elementsMap = app.scene.getNonDeletedElementsMap();\r\n const elements = app.scene.getNonDeletedElements();\r\n const { elementId } = linearElementEditor;\r\n\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n\r\n invariant(element, \"Element being dragged must exist in the scene\");\r\n invariant(element.points.length > 1, \"Element must have at least 2 points\");\r\n\r\n const idx = element.points.length - 1;\r\n const point = element.points[idx];\r\n const pivotPoint = element.points[idx - 1];\r\n const customLineAngle =\r\n linearElementEditor.customLineAngle ??\r\n determineCustomLinearAngle(pivotPoint, element.points[idx]);\r\n\r\n // Determine if point movement should happen and how much\r\n let deltaX = 0;\r\n let deltaY = 0;\r\n if (shouldRotateWithDiscreteAngle(event)) {\r\n const [width, height] = LinearElementEditor._getShiftLockedDelta(\r\n element,\r\n elementsMap,\r\n pivotPoint,\r\n pointFrom(scenePointerX, scenePointerY),\r\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\r\n customLineAngle,\r\n );\r\n const target = pointFrom<LocalPoint>(\r\n width + pivotPoint[0],\r\n height + pivotPoint[1],\r\n );\r\n\r\n deltaX = target[0] - point[0];\r\n deltaY = target[1] - point[1];\r\n } else {\r\n const newDraggingPointPosition = LinearElementEditor.createPointAt(\r\n element,\r\n elementsMap,\r\n scenePointerX - linearElementEditor.pointerOffset.x,\r\n scenePointerY - linearElementEditor.pointerOffset.y,\r\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\r\n );\r\n deltaX = newDraggingPointPosition[0] - point[0];\r\n deltaY = newDraggingPointPosition[1] - point[1];\r\n }\r\n\r\n // Apply the point movement if needed\r\n let suggestedBinding: AppState[\"suggestedBinding\"] = null;\r\n const { positions, updates } = pointDraggingUpdates(\r\n [idx],\r\n deltaX,\r\n deltaY,\r\n scenePointerX,\r\n scenePointerY,\r\n elementsMap,\r\n element,\r\n elements,\r\n app,\r\n shouldRotateWithDiscreteAngle(event),\r\n event.altKey,\r\n );\r\n\r\n LinearElementEditor.movePoints(element, app.scene, positions, {\r\n startBinding: updates?.startBinding,\r\n endBinding: updates?.endBinding,\r\n moveMidPointsWithElement: updates?.moveMidPointsWithElement,\r\n });\r\n // Set the suggested binding from the updates if available\r\n if (isBindingElement(element, false)) {\r\n if (isBindingEnabled(app.state)) {\r\n suggestedBinding = updates?.suggestedBinding ?? null;\r\n }\r\n }\r\n\r\n // Move the arrow over the bindable object in terms of z-index\r\n if (isBindingElement(element)) {\r\n moveArrowAboveBindable(\r\n LinearElementEditor.getPointGlobalCoordinates(\r\n element,\r\n element.points[element.points.length - 1],\r\n elementsMap,\r\n ),\r\n element,\r\n elements,\r\n elementsMap,\r\n app.scene,\r\n );\r\n }\r\n\r\n // PERF: Avoid state updates if not absolutely necessary\r\n if (\r\n app.state.selectedLinearElement?.customLineAngle === customLineAngle &&\r\n linearElementEditor.initialState.altFocusPoint &&\r\n (!suggestedBinding ||\r\n isShallowEqual(app.state.suggestedBinding ?? [], suggestedBinding))\r\n ) {\r\n return null;\r\n }\r\n\r\n const startBindingElement =\r\n isBindingElement(element) &&\r\n element.startBinding &&\r\n (elementsMap.get(\r\n element.startBinding.elementId,\r\n ) as ExcalidrawBindableElement | null);\r\n const newLinearElementEditor = {\r\n ...linearElementEditor,\r\n customLineAngle,\r\n initialState: {\r\n ...linearElementEditor.initialState,\r\n altFocusPoint:\r\n !linearElementEditor.initialState.altFocusPoint &&\r\n startBindingElement &&\r\n updates?.suggestedBinding?.id !== startBindingElement.id\r\n ? projectFixedPointOntoDiagonal(\r\n element,\r\n pointFrom<GlobalPoint>(element.x, element.y),\r\n startBindingElement,\r\n \"start\",\r\n elementsMap,\r\n )\r\n : linearElementEditor.initialState.altFocusPoint,\r\n },\r\n };\r\n\r\n return {\r\n selectedLinearElement: newLinearElementEditor,\r\n suggestedBinding,\r\n };\r\n }\r\n\r\n static handlePointDragging(\r\n event: PointerEvent,\r\n app: AppClassProperties,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n linearElementEditor: LinearElementEditor,\r\n ): Pick<AppState, \"suggestedBinding\" | \"selectedLinearElement\"> | null {\r\n const elementsMap = app.scene.getNonDeletedElementsMap();\r\n const elements = app.scene.getNonDeletedElements();\r\n const { elbowed, elementId, initialState } = linearElementEditor;\r\n const selectedPointsIndices = Array.from(\r\n linearElementEditor.selectedPointsIndices ?? [],\r\n );\r\n let { lastClickedPoint } = initialState;\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n\r\n invariant(element, \"Element being dragged must exist in the scene\");\r\n\r\n invariant(element.points.length > 1, \"Element must have at least 2 points\");\r\n\r\n invariant(\r\n selectedPointsIndices,\r\n \"There must be selected points in order to drag them\",\r\n );\r\n\r\n if (elbowed) {\r\n selectedPointsIndices.some((pointIdx, idx) => {\r\n if (pointIdx > 0 && pointIdx !== element.points.length - 1) {\r\n selectedPointsIndices[idx] = element.points.length - 1;\r\n lastClickedPoint = element.points.length - 1;\r\n return true;\r\n }\r\n\r\n return false;\r\n });\r\n }\r\n\r\n invariant(\r\n lastClickedPoint > -1 &&\r\n selectedPointsIndices.includes(lastClickedPoint) &&\r\n element.points[lastClickedPoint],\r\n `There must be a valid lastClickedPoint in order to drag it. selectedPointsIndices(${JSON.stringify(\r\n selectedPointsIndices,\r\n )}) points(0..${\r\n element.points.length - 1\r\n }) lastClickedPoint(${lastClickedPoint})`,\r\n );\r\n\r\n // point that's being dragged (out of all selected points)\r\n const draggingPoint = element.points[lastClickedPoint];\r\n // The adjacent point to the one dragged point\r\n const pivotPoint =\r\n element.points[lastClickedPoint === 0 ? 1 : lastClickedPoint - 1];\r\n const singlePointDragged = selectedPointsIndices.length === 1;\r\n const customLineAngle =\r\n linearElementEditor.customLineAngle ??\r\n determineCustomLinearAngle(pivotPoint, element.points[lastClickedPoint]);\r\n const startIsSelected = selectedPointsIndices.includes(0);\r\n const endIsSelected = selectedPointsIndices.includes(\r\n element.points.length - 1,\r\n );\r\n\r\n // Determine if point movement should happen and how much\r\n let deltaX = 0;\r\n let deltaY = 0;\r\n if (shouldRotateWithDiscreteAngle(event) && singlePointDragged) {\r\n const [width, height] = LinearElementEditor._getShiftLockedDelta(\r\n element,\r\n elementsMap,\r\n pivotPoint,\r\n pointFrom(scenePointerX, scenePointerY),\r\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\r\n customLineAngle,\r\n );\r\n const target = pointFrom<LocalPoint>(\r\n width + pivotPoint[0],\r\n height + pivotPoint[1],\r\n );\r\n deltaX = target[0] - draggingPoint[0];\r\n deltaY = target[1] - draggingPoint[1];\r\n } else {\r\n const newDraggingPointPosition = LinearElementEditor.createPointAt(\r\n element,\r\n elementsMap,\r\n scenePointerX - linearElementEditor.pointerOffset.x,\r\n scenePointerY - linearElementEditor.pointerOffset.y,\r\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\r\n );\r\n deltaX = newDraggingPointPosition[0] - draggingPoint[0];\r\n deltaY = newDraggingPointPosition[1] - draggingPoint[1];\r\n }\r\n\r\n // Apply the point movement if needed\r\n let suggestedBinding: AppState[\"suggestedBinding\"] = null;\r\n const { positions, updates } = pointDraggingUpdates(\r\n selectedPointsIndices,\r\n deltaX,\r\n deltaY,\r\n scenePointerX,\r\n scenePointerY,\r\n elementsMap,\r\n element,\r\n elements,\r\n app,\r\n shouldRotateWithDiscreteAngle(event) && singlePointDragged,\r\n event.altKey,\r\n );\r\n\r\n LinearElementEditor.movePoints(element, app.scene, positions, {\r\n startBinding: updates?.startBinding,\r\n endBinding: updates?.endBinding,\r\n moveMidPointsWithElement: updates?.moveMidPointsWithElement,\r\n });\r\n\r\n // Set the suggested binding from the updates if available\r\n if (isBindingElement(element, false)) {\r\n if (isBindingEnabled(app.state) && (startIsSelected || endIsSelected)) {\r\n suggestedBinding = updates?.suggestedBinding ?? null;\r\n }\r\n }\r\n\r\n // Move the arrow over the bindable object in terms of z-index\r\n if (isBindingElement(element) && startIsSelected !== endIsSelected) {\r\n moveArrowAboveBindable(\r\n LinearElementEditor.getPointGlobalCoordinates(\r\n element,\r\n startIsSelected\r\n ? element.points[0]\r\n : element.points[element.points.length - 1],\r\n elementsMap,\r\n ),\r\n element,\r\n elements,\r\n elementsMap,\r\n app.scene,\r\n );\r\n }\r\n\r\n // Attached text might need to update if arrow dimensions change\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n if (boundTextElement) {\r\n handleBindTextResize(element, app.scene, false);\r\n }\r\n\r\n // Update selected points for elbow arrows because elbow arrows add and\r\n // remove points as they route\r\n const newSelectedPointsIndices = elbowed\r\n ? endIsSelected\r\n ? [element.points.length - 1]\r\n : [0]\r\n : selectedPointsIndices;\r\n\r\n const newLastClickedPoint = elbowed\r\n ? newSelectedPointsIndices[0]\r\n : lastClickedPoint;\r\n\r\n const newSelectedMidPointHoveredCoords =\r\n !startIsSelected && !endIsSelected\r\n ? LinearElementEditor.getPointGlobalCoordinates(\r\n element,\r\n draggingPoint,\r\n elementsMap,\r\n )\r\n : null;\r\n\r\n const newHoverPointIndex = newLastClickedPoint;\r\n const startBindingElement =\r\n isBindingElement(element) &&\r\n element.startBinding &&\r\n (elementsMap.get(\r\n element.startBinding.elementId,\r\n ) as ExcalidrawBindableElement | null);\r\n const endBindingElement =\r\n isBindingElement(element) &&\r\n element.endBinding &&\r\n (elementsMap.get(\r\n element.endBinding.elementId,\r\n ) as ExcalidrawBindableElement | null);\r\n const altFocusPointBindableElement =\r\n endIsSelected && // The \"other\" end (i.e. \"end\") is dragged\r\n startBindingElement &&\r\n updates?.suggestedBinding?.id !== startBindingElement.id // The end point is not hovering the start bindable + it's binding gap\r\n ? startBindingElement\r\n : startIsSelected && // The \"other\" end (i.e. \"start\") is dragged\r\n endBindingElement &&\r\n updates?.suggestedBinding?.id !== endBindingElement.id // The start point is not hovering the end bindable + it's binding gap\r\n ? endBindingElement\r\n : null;\r\n\r\n const newLinearElementEditor: LinearElementEditor = {\r\n ...linearElementEditor,\r\n selectedPointsIndices: newSelectedPointsIndices,\r\n initialState: {\r\n ...linearElementEditor.initialState,\r\n lastClickedPoint: newLastClickedPoint,\r\n altFocusPoint:\r\n !linearElementEditor.initialState.altFocusPoint && // We only set it once per arrow drag\r\n isBindingElement(element) &&\r\n altFocusPointBindableElement\r\n ? projectFixedPointOntoDiagonal(\r\n element,\r\n pointFrom<GlobalPoint>(element.x, element.y),\r\n altFocusPointBindableElement,\r\n \"start\",\r\n elementsMap,\r\n )\r\n : linearElementEditor.initialState.altFocusPoint,\r\n },\r\n segmentMidPointHoveredCoords: newSelectedMidPointHoveredCoords,\r\n hoverPointIndex: newHoverPointIndex,\r\n isDragging: true,\r\n customLineAngle,\r\n };\r\n\r\n return {\r\n selectedLinearElement: newLinearElementEditor,\r\n suggestedBinding,\r\n };\r\n }\r\n\r\n static handlePointerUp(\r\n event: PointerEvent,\r\n editingLinearElement: LinearElementEditor,\r\n appState: AppState,\r\n scene: Scene,\r\n ): LinearElementEditor {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n\r\n const {\r\n elementId,\r\n selectedPointsIndices,\r\n isDragging,\r\n initialState: pointerDownState,\r\n } = editingLinearElement;\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n if (!element) {\r\n return editingLinearElement;\r\n }\r\n\r\n if (isDragging && selectedPointsIndices) {\r\n for (const selectedPoint of selectedPointsIndices) {\r\n if (\r\n selectedPoint === 0 ||\r\n selectedPoint === element.points.length - 1\r\n ) {\r\n if (isPathALoop(element.points, appState.zoom.value)) {\r\n if (isLineElement(element)) {\r\n scene.mutateElement(\r\n element,\r\n {\r\n ...toggleLinePolygonState(element, true),\r\n },\r\n {\r\n informMutation: false,\r\n isDragging: false,\r\n },\r\n );\r\n }\r\n LinearElementEditor.movePoints(\r\n element,\r\n scene,\r\n new Map([\r\n [\r\n selectedPoint,\r\n {\r\n point:\r\n selectedPoint === 0\r\n ? element.points[element.points.length - 1]\r\n : element.points[0],\r\n },\r\n ],\r\n ]),\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n ...editingLinearElement,\r\n segmentMidPointHoveredCoords: null,\r\n hoverPointIndex: -1,\r\n // if clicking without previously dragging a point(s), and not holding\r\n // shift, deselect all points except the one clicked. If holding shift,\r\n // toggle the point.\r\n selectedPointsIndices:\r\n isDragging || event.shiftKey\r\n ? !isDragging &&\r\n event.shiftKey &&\r\n pointerDownState.prevSelectedPointsIndices?.includes(\r\n pointerDownState.lastClickedPoint,\r\n )\r\n ? selectedPointsIndices &&\r\n selectedPointsIndices.filter(\r\n (pointIndex) =>\r\n pointIndex !== pointerDownState.lastClickedPoint,\r\n )\r\n : selectedPointsIndices\r\n : selectedPointsIndices?.includes(pointerDownState.lastClickedPoint)\r\n ? [pointerDownState.lastClickedPoint]\r\n : selectedPointsIndices,\r\n isDragging: false,\r\n pointerOffset: { x: 0, y: 0 },\r\n customLineAngle: null,\r\n initialState: {\r\n ...editingLinearElement.initialState,\r\n origin: null,\r\n arrowStartIsInside: false,\r\n },\r\n };\r\n }\r\n\r\n static getEditorMidPoints = (\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elementsMap: ElementsMap,\r\n appState: InteractiveCanvasAppState,\r\n ): (GlobalPoint | null)[] => {\r\n const boundText = getBoundTextElement(element, elementsMap);\r\n\r\n // Since its not needed outside editor unless 2 pointer lines or bound text\r\n if (\r\n !isElbowArrow(element) &&\r\n !appState.selectedLinearElement?.isEditing &&\r\n element.points.length > 2 &&\r\n !boundText\r\n ) {\r\n return [];\r\n }\r\n\r\n const points = LinearElementEditor.getPointsGlobalCoordinates(\r\n element,\r\n elementsMap,\r\n );\r\n\r\n let index = 0;\r\n const midpoints: (GlobalPoint | null)[] = [];\r\n while (index < points.length - 1) {\r\n if (\r\n LinearElementEditor.isSegmentTooShort(\r\n element,\r\n element.points[index],\r\n element.points[index + 1],\r\n index,\r\n appState.zoom,\r\n )\r\n ) {\r\n midpoints.push(null);\r\n index++;\r\n continue;\r\n }\r\n const segmentMidPoint = LinearElementEditor.getSegmentMidPoint(\r\n element,\r\n index + 1,\r\n );\r\n midpoints.push(segmentMidPoint);\r\n index++;\r\n }\r\n\r\n return midpoints;\r\n };\r\n\r\n static getSegmentMidpointHitCoords = (\r\n linearElementEditor: LinearElementEditor,\r\n scenePointer: { x: number; y: number },\r\n appState: AppState,\r\n elementsMap: ElementsMap,\r\n ): GlobalPoint | null => {\r\n const { elementId } = linearElementEditor;\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n if (!element) {\r\n return null;\r\n }\r\n const clickedPointIndex = LinearElementEditor.getPointIndexUnderCursor(\r\n element,\r\n elementsMap,\r\n appState.zoom,\r\n scenePointer.x,\r\n scenePointer.y,\r\n );\r\n if (!isElbowArrow(element) && clickedPointIndex >= 0) {\r\n return null;\r\n }\r\n const points = LinearElementEditor.getPointsGlobalCoordinates(\r\n element,\r\n elementsMap,\r\n );\r\n if (\r\n points.length >= 3 &&\r\n !appState.selectedLinearElement?.isEditing &&\r\n !isElbowArrow(element)\r\n ) {\r\n return null;\r\n }\r\n\r\n const threshold =\r\n (LinearElementEditor.POINT_HANDLE_SIZE + 1) / appState.zoom.value;\r\n\r\n const existingSegmentMidpointHitCoords =\r\n linearElementEditor.segmentMidPointHoveredCoords;\r\n if (existingSegmentMidpointHitCoords) {\r\n const distance = pointDistance(\r\n pointFrom(\r\n existingSegmentMidpointHitCoords[0],\r\n existingSegmentMidpointHitCoords[1],\r\n ),\r\n pointFrom(scenePointer.x, scenePointer.y),\r\n );\r\n if (distance <= threshold) {\r\n return existingSegmentMidpointHitCoords;\r\n }\r\n }\r\n let index = 0;\r\n const midPoints = LinearElementEditor.getEditorMidPoints(\r\n element,\r\n elementsMap,\r\n appState,\r\n );\r\n\r\n while (index < midPoints.length) {\r\n if (midPoints[index] !== null) {\r\n const distance = pointDistance(\r\n midPoints[index]!,\r\n pointFrom(scenePointer.x, scenePointer.y),\r\n );\r\n if (distance <= threshold) {\r\n return midPoints[index];\r\n }\r\n }\r\n\r\n index++;\r\n }\r\n return null;\r\n };\r\n\r\n static isSegmentTooShort<P extends GlobalPoint | LocalPoint>(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n startPoint: P,\r\n endPoint: P,\r\n index: number,\r\n zoom: Zoom,\r\n ) {\r\n if (isElbowArrow(element)) {\r\n if (index >= 0 && index < element.points.length) {\r\n return (\r\n pointDistance(startPoint, endPoint) * zoom.value <\r\n LinearElementEditor.POINT_HANDLE_SIZE / 2\r\n );\r\n }\r\n\r\n return false;\r\n }\r\n\r\n let distance = pointDistance(startPoint, endPoint);\r\n if (element.points.length > 2 && element.roundness) {\r\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\r\n\r\n invariant(\r\n lines.length === 0 && curves.length > 0,\r\n \"Only linears built out of curves are supported\",\r\n );\r\n invariant(\r\n lines.length + curves.length >= index,\r\n \"Invalid segment index while calculating mid point\",\r\n );\r\n\r\n distance = curveLength<GlobalPoint>(curves[index]);\r\n }\r\n\r\n return distance * zoom.value < LinearElementEditor.POINT_HANDLE_SIZE * 4;\r\n }\r\n\r\n static getSegmentMidPoint(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n index: number,\r\n ): GlobalPoint {\r\n if (isElbowArrow(element)) {\r\n invariant(\r\n element.points.length >= index,\r\n \"Invalid segment index while calculating elbow arrow mid point\",\r\n );\r\n\r\n const p = pointCenter(element.points[index - 1], element.points[index]);\r\n\r\n return pointFrom<GlobalPoint>(element.x + p[0], element.y + p[1]);\r\n }\r\n\r\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\r\n\r\n invariant(\r\n (lines.length === 0 && curves.length > 0) ||\r\n (lines.length > 0 && curves.length === 0),\r\n \"Only linears built out of either segments or curves are supported\",\r\n );\r\n invariant(\r\n lines.length + curves.length >= index,\r\n \"Invalid segment index while calculating mid point\",\r\n );\r\n\r\n if (lines.length) {\r\n const segment = lines[index - 1];\r\n return pointCenter(segment[0], segment[1]);\r\n }\r\n\r\n if (curves.length) {\r\n const segment = curves[index - 1];\r\n return curvePointAtLength(segment, 0.5);\r\n }\r\n\r\n invariant(false, \"Invalid segment type while calculating mid point\");\r\n }\r\n\r\n static getSegmentMidPointIndex(\r\n linearElementEditor: LinearElementEditor,\r\n appState: AppState,\r\n midPoint: GlobalPoint,\r\n elementsMap: ElementsMap,\r\n ) {\r\n const element = LinearElementEditor.getElement(\r\n linearElementEditor.elementId,\r\n elementsMap,\r\n );\r\n if (!element) {\r\n return -1;\r\n }\r\n const midPoints = LinearElementEditor.getEditorMidPoints(\r\n element,\r\n elementsMap,\r\n appState,\r\n );\r\n let index = 0;\r\n while (index < midPoints.length) {\r\n if (LinearElementEditor.arePointsEqual(midPoint, midPoints[index])) {\r\n return index + 1;\r\n }\r\n index++;\r\n }\r\n return -1;\r\n }\r\n\r\n static handlePointerDown(\r\n event: React.PointerEvent<HTMLElement>,\r\n app: AppClassProperties,\r\n store: Store,\r\n scenePointer: { x: number; y: number },\r\n linearElementEditor: LinearElementEditor,\r\n scene: Scene,\r\n ): {\r\n didAddPoint: boolean;\r\n hitElement: NonDeleted<ExcalidrawElement> | null;\r\n linearElementEditor: LinearElementEditor | null;\r\n } {\r\n const appState = app.state;\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n\r\n const ret: ReturnType<typeof LinearElementEditor[\"handlePointerDown\"]> = {\r\n didAddPoint: false,\r\n hitElement: null,\r\n linearElementEditor: null,\r\n };\r\n\r\n if (!linearElementEditor) {\r\n return ret;\r\n }\r\n\r\n const { elementId } = linearElementEditor;\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n\r\n if (!element) {\r\n return ret;\r\n }\r\n\r\n const segmentMidpoint = LinearElementEditor.getSegmentMidpointHitCoords(\r\n linearElementEditor,\r\n scenePointer,\r\n appState,\r\n elementsMap,\r\n );\r\n const point = pointFrom<GlobalPoint>(scenePointer.x, scenePointer.y);\r\n let segmentMidpointIndex = null;\r\n\r\n if (segmentMidpoint) {\r\n segmentMidpointIndex = LinearElementEditor.getSegmentMidPointIndex(\r\n linearElementEditor,\r\n appState,\r\n segmentMidpoint,\r\n elementsMap,\r\n );\r\n } else if (event.altKey && appState.selectedLinearElement?.isEditing) {\r\n if (linearElementEditor.lastUncommittedPoint == null) {\r\n scene.mutateElement(element, {\r\n points: [\r\n ...element.points,\r\n LinearElementEditor.createPointAt(\r\n element,\r\n elementsMap,\r\n scenePointer.x,\r\n scenePointer.y,\r\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\r\n ),\r\n ],\r\n });\r\n ret.didAddPoint = true;\r\n }\r\n store.scheduleCapture();\r\n ret.linearElementEditor = {\r\n ...linearElementEditor,\r\n initialState: {\r\n prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices,\r\n lastClickedPoint: -1,\r\n origin: point,\r\n segmentMidpoint: {\r\n value: segmentMidpoint,\r\n index: segmentMidpointIndex,\r\n added: false,\r\n },\r\n arrowStartIsInside:\r\n !!app.state.newElement &&\r\n (app.state.bindMode === \"inside\" || app.state.bindMode === \"skip\"),\r\n altFocusPoint: null,\r\n },\r\n selectedPointsIndices: [element.points.length - 1],\r\n lastUncommittedPoint: null,\r\n };\r\n\r\n ret.didAddPoint = true;\r\n\r\n return ret;\r\n }\r\n\r\n const clickedPointIndex = LinearElementEditor.getPointIndexUnderCursor(\r\n element,\r\n elementsMap,\r\n appState.zoom,\r\n scenePointer.x,\r\n scenePointer.y,\r\n );\r\n // if we clicked on a point, set the element as hitElement otherwise\r\n // it would get deselected if the point is outside the hitbox area\r\n if (clickedPointIndex >= 0 || segmentMidpoint) {\r\n ret.hitElement = element;\r\n }\r\n\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n const targetPoint =\r\n clickedPointIndex > -1 &&\r\n pointRotateRads(\r\n pointFrom(\r\n element.x + element.points[clickedPointIndex][0],\r\n element.y + element.points[clickedPointIndex][1],\r\n ),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n\r\n const nextSelectedPointsIndices =\r\n clickedPointIndex > -1 || event.shiftKey\r\n ? event.shiftKey ||\r\n linearElementEditor.selectedPointsIndices?.includes(clickedPointIndex)\r\n ? normalizeSelectedPoints([\r\n ...(linearElementEditor.selectedPointsIndices || []),\r\n clickedPointIndex,\r\n ])\r\n : [clickedPointIndex]\r\n : null;\r\n ret.linearElementEditor = {\r\n ...linearElementEditor,\r\n initialState: {\r\n prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices,\r\n lastClickedPoint: clickedPointIndex,\r\n origin: point,\r\n segmentMidpoint: {\r\n value: segmentMidpoint,\r\n index: segmentMidpointIndex,\r\n added: false,\r\n },\r\n arrowStartIsInside:\r\n !!app.state.newElement &&\r\n (app.state.bindMode === \"inside\" || app.state.bindMode === \"skip\"),\r\n altFocusPoint: null,\r\n },\r\n selectedPointsIndices: nextSelectedPointsIndices,\r\n pointerOffset: targetPoint\r\n ? {\r\n x: scenePointer.x - targetPoint[0],\r\n y: scenePointer.y - targetPoint[1],\r\n }\r\n : { x: 0, y: 0 },\r\n };\r\n\r\n return ret;\r\n }\r\n\r\n static arePointsEqual<Point extends LocalPoint | GlobalPoint>(\r\n point1: Point | null,\r\n point2: Point | null,\r\n ) {\r\n if (!point1 && !point2) {\r\n return true;\r\n }\r\n if (!point1 || !point2) {\r\n return false;\r\n }\r\n return pointsEqual(point1, point2);\r\n }\r\n\r\n static handlePointerMoveInEditMode(\r\n event: React.PointerEvent<HTMLCanvasElement>,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n app: AppClassProperties,\r\n ): LinearElementEditor | null {\r\n const appState = app.state;\r\n if (!appState.selectedLinearElement?.isEditing) {\r\n return null;\r\n }\r\n const { elementId, lastUncommittedPoint } = appState.selectedLinearElement;\r\n const elementsMap = app.scene.getNonDeletedElementsMap();\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n if (!element) {\r\n return appState.selectedLinearElement;\r\n }\r\n\r\n const { points } = element;\r\n const lastPoint = points[points.length - 1];\r\n\r\n if (!event.altKey) {\r\n if (lastPoint === lastUncommittedPoint) {\r\n LinearElementEditor.deletePoints(element, app, [points.length - 1]);\r\n }\r\n return appState.selectedLinearElement?.lastUncommittedPoint\r\n ? {\r\n ...appState.selectedLinearElement,\r\n lastUncommittedPoint: null,\r\n }\r\n : appState.selectedLinearElement;\r\n }\r\n\r\n let newPoint: LocalPoint;\r\n\r\n if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) {\r\n const anchor = points[points.length - 2];\r\n const [width, height] = LinearElementEditor._getShiftLockedDelta(\r\n element,\r\n elementsMap,\r\n anchor,\r\n pointFrom(scenePointerX, scenePointerY),\r\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\r\n );\r\n\r\n newPoint = pointFrom(width + anchor[0], height + anchor[1]);\r\n } else {\r\n newPoint = LinearElementEditor.createPointAt(\r\n element,\r\n elementsMap,\r\n scenePointerX - appState.selectedLinearElement.pointerOffset.x,\r\n scenePointerY - appState.selectedLinearElement.pointerOffset.y,\r\n event[KEYS.CTRL_OR_CMD] || isElbowArrow(element)\r\n ? null\r\n : app.getEffectiveGridSize(),\r\n );\r\n }\r\n\r\n if (lastPoint === lastUncommittedPoint) {\r\n LinearElementEditor.movePoints(\r\n element,\r\n app.scene,\r\n new Map([\r\n [\r\n element.points.length - 1,\r\n {\r\n point: newPoint,\r\n },\r\n ],\r\n ]),\r\n );\r\n } else {\r\n LinearElementEditor.addPoints(element, app.scene, [newPoint]);\r\n }\r\n return {\r\n ...appState.selectedLinearElement,\r\n lastUncommittedPoint: element.points[element.points.length - 1],\r\n };\r\n }\r\n\r\n /** scene coords */\r\n static getPointGlobalCoordinates(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n p: LocalPoint,\r\n elementsMap: ElementsMap,\r\n ): GlobalPoint {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n\r\n const { x, y } = element;\r\n return pointRotateRads(\r\n pointFrom(x + p[0], y + p[1]),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n }\r\n\r\n /** scene coords */\r\n static getPointsGlobalCoordinates(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elementsMap: ElementsMap,\r\n ): GlobalPoint[] {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n return element.points.map((p) => {\r\n const { x, y } = element;\r\n return pointRotateRads(\r\n pointFrom(x + p[0], y + p[1]),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n });\r\n }\r\n\r\n static getPointAtIndexGlobalCoordinates(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n indexMaybeFromEnd: number, // -1 for last element\r\n elementsMap: ElementsMap,\r\n ): GlobalPoint {\r\n const index =\r\n indexMaybeFromEnd < 0\r\n ? element.points.length + indexMaybeFromEnd\r\n : indexMaybeFromEnd;\r\n const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);\r\n const center = pointFrom<GlobalPoint>(cx, cy);\r\n const p = element.points[index];\r\n const { x, y } = element;\r\n\r\n return p\r\n ? pointRotateRads(\r\n pointFrom<GlobalPoint>(x + p[0], y + p[1]),\r\n center,\r\n element.angle,\r\n )\r\n : pointRotateRads(pointFrom<GlobalPoint>(x, y), center, element.angle);\r\n }\r\n\r\n static pointFromAbsoluteCoords(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n absoluteCoords: GlobalPoint,\r\n elementsMap: ElementsMap,\r\n ): LocalPoint {\r\n if (isElbowArrow(element)) {\r\n // No rotation for elbow arrows\r\n return pointFrom(\r\n absoluteCoords[0] - element.x,\r\n absoluteCoords[1] - element.y,\r\n );\r\n }\r\n\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n const [x, y] = pointRotateRads(\r\n pointFrom(absoluteCoords[0], absoluteCoords[1]),\r\n pointFrom(cx, cy),\r\n -element.angle as Radians,\r\n );\r\n return pointFrom(x - element.x, y - element.y);\r\n }\r\n\r\n static getPointIndexUnderCursor(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elementsMap: ElementsMap,\r\n zoom: AppState[\"zoom\"],\r\n x: number,\r\n y: number,\r\n ) {\r\n const pointHandles = LinearElementEditor.getPointsGlobalCoordinates(\r\n element,\r\n elementsMap,\r\n );\r\n let idx = pointHandles.length;\r\n // loop from right to left because points on the right are rendered over\r\n // points on the left, thus should take precedence when clicking, if they\r\n // overlap\r\n while (--idx > -1) {\r\n const p = pointHandles[idx];\r\n if (\r\n pointDistance(pointFrom(x, y), pointFrom(p[0], p[1])) * zoom.value <\r\n // +1px to account for outline stroke\r\n LinearElementEditor.POINT_HANDLE_SIZE + 1\r\n ) {\r\n return idx;\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n static createPointAt(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elementsMap: ElementsMap,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n gridSize: NullableGridSize,\r\n ): LocalPoint {\r\n const pointerOnGrid = getGridPoint(scenePointerX, scenePointerY, gridSize);\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n const [rotatedX, rotatedY] = pointRotateRads(\r\n pointFrom(pointerOnGrid[0], pointerOnGrid[1]),\r\n pointFrom(cx, cy),\r\n -element.angle as Radians,\r\n );\r\n\r\n return pointFrom(rotatedX - element.x, rotatedY - element.y);\r\n }\r\n\r\n /**\r\n * Normalizes line points so that the start point is at [0,0]. This is\r\n * expected in various parts of the codebase.\r\n *\r\n * Also returns normalized x and y coords to account for the normalization\r\n * of the points.\r\n */\r\n static getNormalizeElementPointsAndCoords(element: ExcalidrawLinearElement) {\r\n const { points, offsetX, offsetY } = getNormalizedPoints(element);\r\n\r\n return {\r\n points,\r\n x: element.x + offsetX,\r\n y: element.y + offsetY,\r\n };\r\n }\r\n\r\n // element-mutating methods\r\n // ---------------------------------------------------------------------------\r\n static duplicateSelectedPoints(appState: AppState, scene: Scene): AppState {\r\n invariant(\r\n appState.selectedLinearElement?.isEditing,\r\n \"Not currently editing a linear element\",\r\n );\r\n\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n const { selectedPointsIndices, elementId } = appState.selectedLinearElement;\r\n const element = LinearElementEditor.getElement(elementId, elementsMap);\r\n\r\n invariant(\r\n element,\r\n \"The linear element does not exist in the provided Scene\",\r\n );\r\n invariant(\r\n selectedPointsIndices != null,\r\n \"There are no selected points to duplicate\",\r\n );\r\n\r\n const { points } = element;\r\n\r\n const nextSelectedIndices: number[] = [];\r\n\r\n let pointAddedToEnd = false;\r\n let indexCursor = -1;\r\n const nextPoints = points.reduce((acc: LocalPoint[], p, index) => {\r\n ++indexCursor;\r\n acc.push(p);\r\n\r\n const isSelected = selectedPointsIndices.includes(index);\r\n if (isSelected) {\r\n const nextPoint = points[index + 1];\r\n\r\n if (!nextPoint) {\r\n pointAddedToEnd = true;\r\n }\r\n acc.push(\r\n nextPoint\r\n ? pointFrom((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2)\r\n : pointFrom(p[0], p[1]),\r\n );\r\n\r\n nextSelectedIndices.push(indexCursor + 1);\r\n ++indexCursor;\r\n }\r\n\r\n return acc;\r\n }, []);\r\n\r\n scene.mutateElement(element, { points: nextPoints });\r\n\r\n // temp hack to ensure the line doesn't move when adding point to the end,\r\n // potentially expanding the bounding box\r\n if (pointAddedToEnd) {\r\n const lastPoint = element.points[element.points.length - 1];\r\n LinearElementEditor.movePoints(\r\n element,\r\n scene,\r\n new Map([\r\n [\r\n element.points.length - 1,\r\n { point: pointFrom(lastPoint[0] + 30, lastPoint[1] + 30) },\r\n ],\r\n ]),\r\n );\r\n }\r\n\r\n return {\r\n ...appState,\r\n selectedLinearElement: {\r\n ...appState.selectedLinearElement,\r\n selectedPointsIndices: nextSelectedIndices,\r\n },\r\n };\r\n }\r\n\r\n static deletePoints(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n app: AppClassProperties,\r\n pointIndices: readonly number[],\r\n ) {\r\n const isUncommittedPoint =\r\n app.state.selectedLinearElement?.isEditing &&\r\n app.state.selectedLinearElement?.lastUncommittedPoint ===\r\n element.points[element.points.length - 1];\r\n\r\n const nextPoints = element.points.filter((_, idx) => {\r\n return !pointIndices.includes(idx);\r\n });\r\n\r\n const isPolygon = isLineElement(element) && element.polygon;\r\n\r\n // keep polygon intact if deleting start/end point or uncommitted point\r\n if (\r\n isPolygon &&\r\n (isUncommittedPoint ||\r\n pointIndices.includes(0) ||\r\n pointIndices.includes(element.points.length - 1))\r\n ) {\r\n nextPoints[0] = pointFrom(\r\n nextPoints[nextPoints.length - 1][0],\r\n nextPoints[nextPoints.length - 1][1],\r\n );\r\n }\r\n\r\n const {\r\n points: normalizedPoints,\r\n offsetX,\r\n offsetY,\r\n } = getNormalizedPoints({ points: nextPoints });\r\n\r\n LinearElementEditor._updatePoints(\r\n element,\r\n app.scene,\r\n normalizedPoints,\r\n offsetX,\r\n offsetY,\r\n );\r\n }\r\n\r\n static addPoints(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n scene: Scene,\r\n addedPoints: LocalPoint[],\r\n ) {\r\n const nextPoints = [...element.points, ...addedPoints];\r\n\r\n if (isLineElement(element) && element.polygon) {\r\n nextPoints[0] = pointFrom(\r\n nextPoints[nextPoints.length - 1][0],\r\n nextPoints[nextPoints.length - 1][1],\r\n );\r\n }\r\n\r\n const {\r\n points: normalizedPoints,\r\n offsetX,\r\n offsetY,\r\n } = getNormalizedPoints({ points: nextPoints });\r\n\r\n LinearElementEditor._updatePoints(\r\n element,\r\n scene,\r\n normalizedPoints,\r\n offsetX,\r\n offsetY,\r\n );\r\n }\r\n\r\n static movePoints(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n scene: Scene,\r\n pointUpdates: PointsPositionUpdates,\r\n otherUpdates?: {\r\n startBinding?: FixedPointBinding | null;\r\n endBinding?: FixedPointBinding | null;\r\n moveMidPointsWithElement?: boolean | null;\r\n },\r\n ) {\r\n const { points } = element;\r\n\r\n // if polygon, move start and end points together\r\n if (isLineElement(element) && element.polygon) {\r\n const firstPointUpdate = pointUpdates.get(0);\r\n const lastPointUpdate = pointUpdates.get(points.length - 1);\r\n\r\n if (firstPointUpdate) {\r\n pointUpdates.set(points.length - 1, {\r\n point: pointFrom(\r\n firstPointUpdate.point[0],\r\n firstPointUpdate.point[1],\r\n ),\r\n isDragging: firstPointUpdate.isDragging,\r\n });\r\n } else if (lastPointUpdate) {\r\n pointUpdates.set(0, {\r\n point: pointFrom(lastPointUpdate.point[0], lastPointUpdate.point[1]),\r\n isDragging: lastPointUpdate.isDragging,\r\n });\r\n }\r\n }\r\n\r\n // in case we're moving start point, instead of modifying its position\r\n // which would break the invariant of it being at [0,0], we move\r\n // all the other points in the opposite direction by delta to\r\n // offset it. We do the same with actual element.x/y position, so\r\n // this hacks are completely transparent to the user.\r\n\r\n const updatedOriginPoint =\r\n pointUpdates.get(0)?.point ?? pointFrom<LocalPoint>(0, 0);\r\n\r\n const [offsetX, offsetY] = updatedOriginPoint;\r\n\r\n const nextPoints = isElbowArrow(element)\r\n ? [\r\n pointUpdates.get(0)?.point ?? points[0],\r\n pointUpdates.get(points.length - 1)?.point ??\r\n points[points.length - 1],\r\n ]\r\n : points.map((p, idx) => {\r\n const current = pointUpdates.get(idx)?.point ?? p;\r\n\r\n if (\r\n otherUpdates?.moveMidPointsWithElement &&\r\n idx !== 0 &&\r\n idx !== points.length - 1 &&\r\n !pointUpdates.has(idx)\r\n ) {\r\n return current;\r\n }\r\n\r\n return pointFrom<LocalPoint>(\r\n current[0] - offsetX,\r\n current[1] - offsetY,\r\n );\r\n });\r\n\r\n LinearElementEditor._updatePoints(\r\n element,\r\n scene,\r\n nextPoints,\r\n offsetX,\r\n offsetY,\r\n otherUpdates,\r\n {\r\n isDragging: Array.from(pointUpdates.values()).some((t) => t.isDragging),\r\n },\r\n );\r\n }\r\n\r\n static shouldAddMidpoint(\r\n linearElementEditor: LinearElementEditor,\r\n pointerCoords: PointerCoords,\r\n appState: AppState,\r\n elementsMap: ElementsMap,\r\n ) {\r\n const element = LinearElementEditor.getElement(\r\n linearElementEditor.elementId,\r\n elementsMap,\r\n );\r\n\r\n // Elbow arrows don't allow midpoints\r\n if (element && isElbowArrow(element)) {\r\n return false;\r\n }\r\n\r\n if (!element) {\r\n return false;\r\n }\r\n\r\n const { segmentMidpoint } = linearElementEditor.initialState;\r\n\r\n if (\r\n segmentMidpoint.added ||\r\n segmentMidpoint.value === null ||\r\n segmentMidpoint.index === null ||\r\n linearElementEditor.initialState.origin === null\r\n ) {\r\n return false;\r\n }\r\n\r\n const origin = linearElementEditor.initialState.origin!;\r\n const dist = pointDistance(\r\n origin,\r\n pointFrom(pointerCoords.x, pointerCoords.y),\r\n );\r\n if (\r\n !appState.selectedLinearElement?.isEditing &&\r\n dist < DRAGGING_THRESHOLD / appState.zoom.value\r\n ) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n static addMidpoint(\r\n linearElementEditor: LinearElementEditor,\r\n pointerCoords: PointerCoords,\r\n app: AppClassProperties,\r\n snapToGrid: boolean,\r\n scene: Scene,\r\n ) {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n const element = LinearElementEditor.getElement(\r\n linearElementEditor.elementId,\r\n elementsMap,\r\n );\r\n if (!element) {\r\n return;\r\n }\r\n const { segmentMidpoint } = linearElementEditor.initialState;\r\n const ret: {\r\n pointerDownState: LinearElementEditor[\"initialState\"];\r\n selectedPointsIndices: LinearElementEditor[\"selectedPointsIndices\"];\r\n } = {\r\n pointerDownState: linearElementEditor.initialState,\r\n selectedPointsIndices: linearElementEditor.selectedPointsIndices,\r\n };\r\n\r\n const midpoint = LinearElementEditor.createPointAt(\r\n element,\r\n elementsMap,\r\n pointerCoords.x,\r\n pointerCoords.y,\r\n snapToGrid && !isElbowArrow(element) ? app.getEffectiveGridSize() : null,\r\n );\r\n const points = [\r\n ...element.points.slice(0, segmentMidpoint.index!),\r\n midpoint,\r\n ...element.points.slice(segmentMidpoint.index!),\r\n ];\r\n\r\n scene.mutateElement(element, { points });\r\n\r\n ret.pointerDownState = {\r\n ...linearElementEditor.initialState,\r\n segmentMidpoint: {\r\n ...linearElementEditor.initialState.segmentMidpoint,\r\n added: true,\r\n },\r\n lastClickedPoint: segmentMidpoint.index!,\r\n };\r\n ret.selectedPointsIndices = [segmentMidpoint.index!];\r\n return ret;\r\n }\r\n\r\n private static _updatePoints(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n scene: Scene,\r\n nextPoints: readonly LocalPoint[],\r\n offsetX: number,\r\n offsetY: number,\r\n otherUpdates?: {\r\n startBinding?: FixedPointBinding | null;\r\n endBinding?: FixedPointBinding | null;\r\n },\r\n options?: {\r\n isDragging?: boolean;\r\n zoom?: AppState[\"zoom\"];\r\n sceneElementsMap?: NonDeletedSceneElementsMap;\r\n },\r\n ) {\r\n if (isElbowArrow(element)) {\r\n const updates: {\r\n startBinding?: FixedPointBinding | null;\r\n endBinding?: FixedPointBinding | null;\r\n points?: LocalPoint[];\r\n } = {};\r\n if (otherUpdates?.startBinding !== undefined) {\r\n updates.startBinding = otherUpdates.startBinding;\r\n }\r\n if (otherUpdates?.endBinding !== undefined) {\r\n updates.endBinding = otherUpdates.endBinding;\r\n }\r\n\r\n updates.points = Array.from(nextPoints);\r\n\r\n scene.mutateElement(element, updates, {\r\n informMutation: true,\r\n isDragging: options?.isDragging ?? false,\r\n });\r\n } else {\r\n // TODO do we need to get precise coords here just to calc centers?\r\n const nextCoords = getElementPointsCoords(element, nextPoints);\r\n const prevCoords = getElementPointsCoords(element, element.points);\r\n const nextCenterX = (nextCoords[0] + nextCoords[2]) / 2;\r\n const nextCenterY = (nextCoords[1] + nextCoords[3]) / 2;\r\n const prevCenterX = (prevCoords[0] + prevCoords[2]) / 2;\r\n const prevCenterY = (prevCoords[1] + prevCoords[3]) / 2;\r\n const dX = prevCenterX - nextCenterX;\r\n const dY = prevCenterY - nextCenterY;\r\n const rotatedOffset = pointRotateRads(\r\n pointFrom(offsetX, offsetY),\r\n pointFrom(dX, dY),\r\n element.angle,\r\n );\r\n scene.mutateElement(element, {\r\n ...otherUpdates,\r\n points: nextPoints,\r\n x: element.x + rotatedOffset[0],\r\n y: element.y + rotatedOffset[1],\r\n });\r\n }\r\n }\r\n\r\n private static _getShiftLockedDelta(\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elementsMap: ElementsMap,\r\n referencePoint: LocalPoint,\r\n scenePointer: GlobalPoint,\r\n gridSize: NullableGridSize,\r\n customLineAngle?: number,\r\n ) {\r\n const referencePointCoords = LinearElementEditor.getPointGlobalCoordinates(\r\n element,\r\n referencePoint,\r\n elementsMap,\r\n );\r\n\r\n if (isElbowArrow(element)) {\r\n return [\r\n scenePointer[0] - referencePointCoords[0],\r\n scenePointer[1] - referencePointCoords[1],\r\n ];\r\n }\r\n\r\n const [gridX, gridY] = getGridPoint(\r\n scenePointer[0],\r\n scenePointer[1],\r\n gridSize,\r\n );\r\n\r\n const { width, height } = getLockedLinearCursorAlignSize(\r\n referencePointCoords[0],\r\n referencePointCoords[1],\r\n gridX,\r\n gridY,\r\n customLineAngle,\r\n );\r\n\r\n return pointRotateRads(\r\n pointFrom(width, height),\r\n pointFrom(0, 0),\r\n -element.angle as Radians,\r\n );\r\n }\r\n\r\n static getBoundTextElementPosition = (\r\n element: ExcalidrawLinearElement,\r\n boundTextElement: ExcalidrawTextElementWithContainer,\r\n elementsMap: ElementsMap,\r\n ): { x: number; y: number } => {\r\n const points = LinearElementEditor.getPointsGlobalCoordinates(\r\n element,\r\n elementsMap,\r\n );\r\n if (points.length < 2) {\r\n mutateElement(boundTextElement, elementsMap, { isDeleted: true });\r\n }\r\n let x = 0;\r\n let y = 0;\r\n if (element.points.length % 2 === 1) {\r\n const index = Math.floor(element.points.length / 2);\r\n const midPoint = LinearElementEditor.getPointGlobalCoordinates(\r\n element,\r\n element.points[index],\r\n elementsMap,\r\n );\r\n x = midPoint[0] - boundTextElement.width / 2;\r\n y = midPoint[1] - boundTextElement.height / 2;\r\n } else {\r\n const index = element.points.length / 2 - 1;\r\n const midSegmentMidpoint = LinearElementEditor.getSegmentMidPoint(\r\n element,\r\n index + 1,\r\n );\r\n\r\n x = midSegmentMidpoint[0] - boundTextElement.width / 2;\r\n y = midSegmentMidpoint[1] - boundTextElement.height / 2;\r\n }\r\n return { x, y };\r\n };\r\n\r\n static getMinMaxXYWithBoundText = (\r\n element: ExcalidrawLinearElement,\r\n elementsMap: ElementsMap,\r\n elementBounds: Bounds,\r\n boundTextElement: ExcalidrawTextElementWithContainer,\r\n ): [number, number, number, number, number, number] => {\r\n let [x1, y1, x2, y2] = elementBounds;\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n const { x: boundTextX1, y: boundTextY1 } =\r\n LinearElementEditor.getBoundTextElementPosition(\r\n element,\r\n boundTextElement,\r\n elementsMap,\r\n );\r\n const boundTextX2 = boundTextX1 + boundTextElement.width;\r\n const boundTextY2 = boundTextY1 + boundTextElement.height;\r\n const centerPoint = pointFrom(cx, cy);\r\n\r\n const topLeftRotatedPoint = pointRotateRads(\r\n pointFrom(x1, y1),\r\n centerPoint,\r\n element.angle,\r\n );\r\n const topRightRotatedPoint = pointRotateRads(\r\n pointFrom(x2, y1),\r\n centerPoint,\r\n element.angle,\r\n );\r\n\r\n const counterRotateBoundTextTopLeft = pointRotateRads(\r\n pointFrom(boundTextX1, boundTextY1),\r\n centerPoint,\r\n -element.angle as Radians,\r\n );\r\n const counterRotateBoundTextTopRight = pointRotateRads(\r\n pointFrom(boundTextX2, boundTextY1),\r\n centerPoint,\r\n -element.angle as Radians,\r\n );\r\n const counterRotateBoundTextBottomLeft = pointRotateRads(\r\n pointFrom(boundTextX1, boundTextY2),\r\n centerPoint,\r\n -element.angle as Radians,\r\n );\r\n const counterRotateBoundTextBottomRight = pointRotateRads(\r\n pointFrom(boundTextX2, boundTextY2),\r\n centerPoint,\r\n -element.angle as Radians,\r\n );\r\n\r\n if (\r\n topLeftRotatedPoint[0] < topRightRotatedPoint[0] &&\r\n topLeftRotatedPoint[1] >= topRightRotatedPoint[1]\r\n ) {\r\n x1 = Math.min(x1, counterRotateBoundTextBottomLeft[0]);\r\n x2 = Math.max(\r\n x2,\r\n Math.max(\r\n counterRotateBoundTextTopRight[0],\r\n counterRotateBoundTextBottomRight[0],\r\n ),\r\n );\r\n y1 = Math.min(y1, counterRotateBoundTextTopLeft[1]);\r\n\r\n y2 = Math.max(y2, counterRotateBoundTextBottomRight[1]);\r\n } else if (\r\n topLeftRotatedPoint[0] >= topRightRotatedPoint[0] &&\r\n topLeftRotatedPoint[1] > topRightRotatedPoint[1]\r\n ) {\r\n x1 = Math.min(x1, counterRotateBoundTextBottomRight[0]);\r\n x2 = Math.max(\r\n x2,\r\n Math.max(\r\n counterRotateBoundTextTopLeft[0],\r\n counterRotateBoundTextTopRight[0],\r\n ),\r\n );\r\n y1 = Math.min(y1, counterRotateBoundTextBottomLeft[1]);\r\n\r\n y2 = Math.max(y2, counterRotateBoundTextTopRight[1]);\r\n } else if (topLeftRotatedPoint[0] >= topRightRotatedPoint[0]) {\r\n x1 = Math.min(x1, counterRotateBoundTextTopRight[0]);\r\n x2 = Math.max(x2, counterRotateBoundTextBottomLeft[0]);\r\n y1 = Math.min(y1, counterRotateBoundTextBottomRight[1]);\r\n\r\n y2 = Math.max(y2, counterRotateBoundTextTopLeft[1]);\r\n } else if (topLeftRotatedPoint[1] <= topRightRotatedPoint[1]) {\r\n x1 = Math.min(\r\n x1,\r\n Math.min(\r\n counterRotateBoundTextTopRight[0],\r\n counterRotateBoundTextTopLeft[0],\r\n ),\r\n );\r\n\r\n x2 = Math.max(x2, counterRotateBoundTextBottomRight[0]);\r\n y1 = Math.min(y1, counterRotateBoundTextTopRight[1]);\r\n y2 = Math.max(y2, counterRotateBoundTextBottomLeft[1]);\r\n }\r\n\r\n return [x1, y1, x2, y2, cx, cy];\r\n };\r\n\r\n static getElementAbsoluteCoords = (\r\n element: ExcalidrawLinearElement,\r\n elementsMap: ElementsMap,\r\n includeBoundText: boolean = false,\r\n ): [number, number, number, number, number, number] => {\r\n const shape = ShapeCache.generateElementShape(element, null);\r\n\r\n // first element is always the curve\r\n const ops = getCurvePathOps(shape[0]);\r\n\r\n const [minX, minY, maxX, maxY] = getMinMaxXYFromCurvePathOps(ops);\r\n const x1 = minX + element.x;\r\n const y1 = minY + element.y;\r\n const x2 = maxX + element.x;\r\n const y2 = maxY + element.y;\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n\r\n const boundTextElement =\r\n includeBoundText && getBoundTextElement(element, elementsMap);\r\n if (boundTextElement) {\r\n return LinearElementEditor.getMinMaxXYWithBoundText(\r\n element,\r\n elementsMap,\r\n [x1, y1, x2, y2],\r\n boundTextElement,\r\n );\r\n }\r\n\r\n return [x1, y1, x2, y2, cx, cy];\r\n };\r\n\r\n static moveFixedSegment(\r\n linearElement: LinearElementEditor,\r\n index: number,\r\n x: number,\r\n y: number,\r\n scene: Scene,\r\n ): Pick<\r\n LinearElementEditor,\r\n \"segmentMidPointHoveredCoords\" | \"initialState\"\r\n > {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n const element = LinearElementEditor.getElement(\r\n linearElement.elementId,\r\n elementsMap,\r\n );\r\n\r\n if (!element || !isElbowArrow(element)) {\r\n return linearElement;\r\n }\r\n\r\n if (index && index > 0 && index < element.points.length) {\r\n const isHorizontal = headingIsHorizontal(\r\n vectorToHeading(\r\n vectorFromPoint(element.points[index], element.points[index - 1]),\r\n ),\r\n );\r\n\r\n const fixedSegments = (element.fixedSegments ?? []).reduce(\r\n (segments, s) => {\r\n segments[s.index] = s;\r\n return segments;\r\n },\r\n {} as Record<number, FixedSegment>,\r\n );\r\n fixedSegments[index] = {\r\n index,\r\n start: pointFrom<LocalPoint>(\r\n !isHorizontal ? x - element.x : element.points[index - 1][0],\r\n isHorizontal ? y - element.y : element.points[index - 1][1],\r\n ),\r\n end: pointFrom<LocalPoint>(\r\n !isHorizontal ? x - element.x : element.points[index][0],\r\n isHorizontal ? y - element.y : element.points[index][1],\r\n ),\r\n };\r\n const nextFixedSegments = Object.values(fixedSegments).sort(\r\n (a, b) => a.index - b.index,\r\n );\r\n\r\n const offset = nextFixedSegments\r\n .map((segment) => segment.index)\r\n .reduce((count, idx) => (idx < index ? count + 1 : count), 0);\r\n\r\n scene.mutateElement(element, {\r\n fixedSegments: nextFixedSegments,\r\n });\r\n\r\n const point = pointFrom<GlobalPoint>(\r\n element.x +\r\n (element.fixedSegments![offset].start[0] +\r\n element.fixedSegments![offset].end[0]) /\r\n 2,\r\n element.y +\r\n (element.fixedSegments![offset].start[1] +\r\n element.fixedSegments![offset].end[1]) /\r\n 2,\r\n );\r\n\r\n return {\r\n ...linearElement,\r\n segmentMidPointHoveredCoords: point,\r\n initialState: {\r\n ...linearElement.initialState,\r\n segmentMidpoint: {\r\n added: false,\r\n index: element.fixedSegments![offset].index,\r\n value: point,\r\n },\r\n },\r\n };\r\n }\r\n\r\n return linearElement;\r\n }\r\n\r\n static deleteFixedSegment(\r\n element: ExcalidrawElbowArrowElement,\r\n scene: Scene,\r\n index: number,\r\n ): void {\r\n scene.mutateElement(element, {\r\n fixedSegments: element.fixedSegments?.filter(\r\n (segment) => segment.index !== index,\r\n ),\r\n });\r\n }\r\n}\r\n\r\nconst normalizeSelectedPoints = (\r\n points: (number | null)[],\r\n): number[] | null => {\r\n let nextPoints = [\r\n ...new Set(points.filter((p) => p !== null && p !== -1)),\r\n ] as number[];\r\n nextPoints = nextPoints.sort((a, b) => a - b);\r\n return nextPoints.length ? nextPoints : null;\r\n};\r\n\r\nconst pointDraggingUpdates = (\r\n selectedPointsIndices: readonly number[],\r\n deltaX: number,\r\n deltaY: number,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n app: AppClassProperties,\r\n angleLocked: boolean,\r\n altKey: boolean,\r\n): {\r\n positions: PointsPositionUpdates;\r\n updates?: PointMoveOtherUpdates;\r\n} => {\r\n const naiveDraggingPoints = new Map(\r\n selectedPointsIndices.map((pointIndex) => {\r\n return [\r\n pointIndex,\r\n {\r\n point: pointFrom<LocalPoint>(\r\n element.points[pointIndex][0] + deltaX,\r\n element.points[pointIndex][1] + deltaY,\r\n ),\r\n isDragging: true,\r\n },\r\n ];\r\n }),\r\n );\r\n\r\n // Linear elements have no special logic\r\n if (!isArrowElement(element)) {\r\n return {\r\n positions: naiveDraggingPoints,\r\n };\r\n }\r\n\r\n const startIsDragged = selectedPointsIndices.includes(0);\r\n const endIsDragged = selectedPointsIndices.includes(\r\n element.points.length - 1,\r\n );\r\n\r\n const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints(\r\n element,\r\n naiveDraggingPoints,\r\n scenePointerX,\r\n scenePointerY,\r\n elementsMap,\r\n elements,\r\n app.state,\r\n {\r\n newArrow: !!app.state.newElement,\r\n angleLocked,\r\n altKey,\r\n },\r\n );\r\n\r\n if (isElbowArrow(element)) {\r\n return {\r\n positions: naiveDraggingPoints,\r\n updates: {\r\n suggestedBinding: startIsDragged\r\n ? start.element\r\n : endIsDragged\r\n ? end.element\r\n : null,\r\n },\r\n };\r\n }\r\n\r\n if (startIsDragged === endIsDragged) {\r\n return {\r\n positions: naiveDraggingPoints,\r\n };\r\n }\r\n\r\n // Generate the next bindings for the arrow\r\n const updates: PointMoveOtherUpdates = {\r\n suggestedBinding: null,\r\n };\r\n if (start.mode === null) {\r\n updates.startBinding = null;\r\n } else if (start.mode) {\r\n updates.startBinding = {\r\n elementId: start.element.id,\r\n mode: start.mode,\r\n ...calculateFixedPointForNonElbowArrowBinding(\r\n element,\r\n start.element,\r\n \"start\",\r\n elementsMap,\r\n start.focusPoint,\r\n ),\r\n };\r\n\r\n if (\r\n startIsDragged &&\r\n (updates.startBinding.mode === \"orbit\" ||\r\n !getFeatureFlag(\"COMPLEX_BINDINGS\"))\r\n ) {\r\n updates.suggestedBinding = start.element;\r\n }\r\n } else if (startIsDragged) {\r\n updates.suggestedBinding = app.state.suggestedBinding;\r\n }\r\n\r\n if (end.mode === null) {\r\n updates.endBinding = null;\r\n } else if (end.mode) {\r\n updates.endBinding = {\r\n elementId: end.element.id,\r\n mode: end.mode,\r\n ...calculateFixedPointForNonElbowArrowBinding(\r\n element,\r\n end.element,\r\n \"end\",\r\n elementsMap,\r\n end.focusPoint,\r\n ),\r\n };\r\n\r\n if (\r\n endIsDragged &&\r\n (updates.endBinding.mode === \"orbit\" ||\r\n !getFeatureFlag(\"COMPLEX_BINDINGS\"))\r\n ) {\r\n updates.suggestedBinding = end.element;\r\n }\r\n } else if (endIsDragged) {\r\n updates.suggestedBinding = app.state.suggestedBinding;\r\n }\r\n\r\n // Simulate the updated arrow for the bind point calculation\r\n const offsetStartLocalPoint = startIsDragged\r\n ? pointFrom<LocalPoint>(\r\n element.points[0][0] + deltaX,\r\n element.points[0][1] + deltaY,\r\n )\r\n : element.points[0];\r\n const offsetEndLocalPoint = endIsDragged\r\n ? pointFrom<LocalPoint>(\r\n element.points[element.points.length - 1][0] + deltaX,\r\n element.points[element.points.length - 1][1] + deltaY,\r\n )\r\n : element.points[element.points.length - 1];\r\n const nextArrow = {\r\n ...element,\r\n points: [\r\n offsetStartLocalPoint,\r\n ...element.points.slice(1, -1),\r\n offsetEndLocalPoint,\r\n ],\r\n startBinding:\r\n updates.startBinding === undefined\r\n ? element.startBinding\r\n : updates.startBinding === null\r\n ? null\r\n : updates.startBinding,\r\n endBinding:\r\n updates.endBinding === undefined\r\n ? element.endBinding\r\n : updates.endBinding === null\r\n ? null\r\n : updates.endBinding,\r\n };\r\n\r\n // We need to use a custom intersector to ensure that if there is a big \"jump\"\r\n // in the arrow's position, we can position it with outline avoidance\r\n // pixel-perfectly and avoid \"dancing\" arrows.\r\n // NOTE: Direction matters here, so we create two intersectors\r\n const startCustomIntersector =\r\n start.focusPoint && end.focusPoint\r\n ? lineSegment(start.focusPoint, end.focusPoint)\r\n : undefined;\r\n const endCustomIntersector =\r\n start.focusPoint && end.focusPoint\r\n ? lineSegment(end.focusPoint, start.focusPoint)\r\n : undefined;\r\n\r\n // Needed to handle a special case where an existing arrow is dragged over\r\n // the same element it is bound to on the other side\r\n const startIsDraggingOverEndElement =\r\n element.endBinding &&\r\n nextArrow.startBinding &&\r\n startIsDragged &&\r\n nextArrow.startBinding.elementId === element.endBinding.elementId;\r\n const endIsDraggingOverStartElement =\r\n element.startBinding &&\r\n nextArrow.endBinding &&\r\n endIsDragged &&\r\n element.startBinding.elementId === nextArrow.endBinding.elementId;\r\n\r\n // We need to update the non-dragged point too if bound,\r\n // so we look up the old binding to trigger updateBoundPoint\r\n const endBindable = nextArrow.endBinding\r\n ? end.element ??\r\n (elementsMap.get(\r\n nextArrow.endBinding.elementId,\r\n )! as ExcalidrawBindableElement)\r\n : null;\r\n\r\n const endLocalPoint = startIsDraggingOverEndElement\r\n ? nextArrow.points[nextArrow.points.length - 1]\r\n : endIsDraggingOverStartElement &&\r\n app.state.bindMode !== \"inside\" &&\r\n getFeatureFlag(\"COMPLEX_BINDINGS\")\r\n ? nextArrow.points[0]\r\n : endBindable\r\n ? updateBoundPoint(\r\n element,\r\n \"endBinding\",\r\n nextArrow.endBinding,\r\n endBindable,\r\n elementsMap,\r\n endCustomIntersector,\r\n ) || nextArrow.points[nextArrow.points.length - 1]\r\n : nextArrow.points[nextArrow.points.length - 1];\r\n\r\n // We need to keep the simulated next arrow up-to-date, because\r\n // updateBoundPoint looks at the opposite point\r\n nextArrow.points[nextArrow.points.length - 1] = endLocalPoint;\r\n\r\n // We need to update the non-dragged point too if bound,\r\n // so we look up the old binding to trigger updateBoundPoint\r\n const startBindable = nextArrow.startBinding\r\n ? start.element ??\r\n (elementsMap.get(\r\n nextArrow.startBinding.elementId,\r\n )! as ExcalidrawBindableElement)\r\n : null;\r\n\r\n const startLocalPoint =\r\n endIsDraggingOverStartElement && getFeatureFlag(\"COMPLEX_BINDINGS\")\r\n ? nextArrow.points[0]\r\n : startIsDraggingOverEndElement &&\r\n app.state.bindMode !== \"inside\" &&\r\n getFeatureFlag(\"COMPLEX_BINDINGS\")\r\n ? nextArrow.points[nextArrow.points.length - 1]\r\n : startBindable\r\n ? updateBoundPoint(\r\n element,\r\n \"startBinding\",\r\n nextArrow.startBinding,\r\n startBindable,\r\n elementsMap,\r\n startCustomIntersector,\r\n ) || nextArrow.points[0]\r\n : nextArrow.points[0];\r\n\r\n const endChanged =\r\n pointDistance(\r\n endLocalPoint,\r\n nextArrow.points[nextArrow.points.length - 1],\r\n ) !== 0;\r\n const startChanged =\r\n pointDistance(startLocalPoint, nextArrow.points[0]) !== 0;\r\n\r\n const indicesSet = new Set(selectedPointsIndices);\r\n if (startBindable && startChanged) {\r\n indicesSet.add(0);\r\n }\r\n if (endBindable && endChanged) {\r\n indicesSet.add(element.points.length - 1);\r\n }\r\n const indices = Array.from(indicesSet);\r\n\r\n return {\r\n updates:\r\n updates.startBinding || updates.suggestedBinding\r\n ? {\r\n startBinding: updates.startBinding,\r\n suggestedBinding: updates.suggestedBinding,\r\n }\r\n : undefined,\r\n positions: new Map(\r\n indices.map((idx) => {\r\n return [\r\n idx,\r\n idx === 0\r\n ? {\r\n point: startLocalPoint,\r\n isDragging: true,\r\n }\r\n : idx === element.points.length - 1\r\n ? {\r\n point: endLocalPoint,\r\n isDragging: true,\r\n }\r\n : naiveDraggingPoints.get(idx)!,\r\n ];\r\n }),\r\n ),\r\n };\r\n};\r\n\r\nconst determineCustomLinearAngle = (\r\n pivotPoint: LocalPoint,\r\n draggedPoint: LocalPoint,\r\n) =>\r\n Math.atan2(draggedPoint[1] - pivotPoint[1], draggedPoint[0] - pivotPoint[0]);\r\n", "import {\r\n KEYS,\r\n arrayToMap,\r\n getFeatureFlag,\r\n invariant,\r\n isTransparent,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n PRECISION,\r\n clamp,\r\n lineSegment,\r\n pointDistance,\r\n pointDistanceSq,\r\n pointFrom,\r\n pointFromVector,\r\n pointRotateRads,\r\n vectorFromPoint,\r\n vectorNormalize,\r\n vectorScale,\r\n type GlobalPoint,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type { LineSegment, LocalPoint, Radians } from \"@excalidraw-modify/math\";\r\nimport type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { MapEntry, Mutable } from \"@excalidraw-modify/common/utility-types\";\r\nimport type { Bounds } from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n doBoundsIntersect,\r\n getCenterForBounds,\r\n getElementBounds,\r\n} from \"./bounds\";\r\nimport {\r\n getAllHoveredElementAtPoint,\r\n getHoveredElementForBinding,\r\n intersectElementWithLineSegment,\r\n isBindableElementInsideOtherBindable,\r\n isPointInElement,\r\n} from \"./collision\";\r\nimport { distanceToElement } from \"./distance\";\r\nimport {\r\n headingForPointFromElement,\r\n headingIsHorizontal,\r\n vectorToHeading,\r\n type Heading,\r\n} from \"./heading\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport { mutateElement } from \"./mutateElement\";\r\nimport { getBoundTextElement, handleBindTextResize } from \"./textElement\";\r\nimport {\r\n isArrowElement,\r\n isBindableElement,\r\n isBoundToContainer,\r\n isElbowArrow,\r\n isRectangularElement,\r\n isRectanguloidElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport { aabbForElement, elementCenterPoint } from \"./bounds\";\r\nimport { updateElbowArrowPoints } from \"./elbowArrow\";\r\nimport {\r\n deconstructDiamondElement,\r\n deconstructRectanguloidElement,\r\n projectFixedPointOntoDiagonal,\r\n} from \"./utils\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\nimport type { ElementUpdate } from \"./mutateElement\";\r\nimport type {\r\n BindMode,\r\n ElementsMap,\r\n ExcalidrawArrowElement,\r\n ExcalidrawBindableElement,\r\n ExcalidrawElbowArrowElement,\r\n ExcalidrawElement,\r\n ExcalidrawRectanguloidElement,\r\n ExcalidrawTextElement,\r\n FixedPoint,\r\n FixedPointBinding,\r\n NonDeleted,\r\n NonDeletedExcalidrawElement,\r\n NonDeletedSceneElementsMap,\r\n Ordered,\r\n PointsPositionUpdates,\r\n} from \"./types\";\r\n\r\nexport type BindingStrategy =\r\n // Create a new binding with this mode\r\n | {\r\n mode: BindMode;\r\n element: NonDeleted<ExcalidrawBindableElement>;\r\n focusPoint: GlobalPoint;\r\n }\r\n // Break the binding\r\n | {\r\n mode: null;\r\n element?: undefined;\r\n focusPoint?: undefined;\r\n }\r\n // Keep the existing binding\r\n | {\r\n mode: undefined;\r\n element?: undefined;\r\n focusPoint?: undefined;\r\n };\r\n\r\n/**\r\n * gaps exclude element strokeWidth\r\n *\r\n * IMPORTANT: currently must be > 0 (this also applies to the computed gap)\r\n */\r\nexport const BASE_BINDING_GAP = 10;\r\nexport const BASE_BINDING_GAP_ELBOW = 5;\r\n\r\nexport const getBindingGap = (\r\n bindTarget: ExcalidrawBindableElement,\r\n opts: Pick<ExcalidrawArrowElement, \"elbowed\">,\r\n): number => {\r\n return (\r\n (opts.elbowed ? BASE_BINDING_GAP_ELBOW : BASE_BINDING_GAP) +\r\n bindTarget.strokeWidth / 2\r\n );\r\n};\r\n\r\nexport const maxBindingDistance_simple = (zoom?: AppState[\"zoom\"]): number => {\r\n const BASE_BINDING_DISTANCE = Math.max(BASE_BINDING_GAP, 15);\r\n const zoomValue = zoom?.value && zoom.value < 1 ? zoom.value : 1;\r\n return clamp(\r\n // reducing zoom impact so that the diff between binding distance and\r\n // binding gap is kept to minimum when possible\r\n BASE_BINDING_DISTANCE / (zoomValue * 1.5),\r\n BASE_BINDING_DISTANCE,\r\n BASE_BINDING_DISTANCE * 2,\r\n );\r\n};\r\n\r\nexport const shouldEnableBindingForPointerEvent = (\r\n event: React.PointerEvent<HTMLElement>,\r\n) => {\r\n return !event[KEYS.CTRL_OR_CMD];\r\n};\r\n\r\nexport const isBindingEnabled = (appState: AppState): boolean => {\r\n return appState.isBindingEnabled;\r\n};\r\n\r\nexport const bindOrUnbindBindingElement = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n draggingPoints: PointsPositionUpdates,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n scene: Scene,\r\n appState: AppState,\r\n opts?: {\r\n newArrow?: boolean;\r\n altKey?: boolean;\r\n angleLocked?: boolean;\r\n initialBinding?: boolean;\r\n },\r\n) => {\r\n const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints(\r\n arrow,\r\n draggingPoints,\r\n scenePointerX,\r\n scenePointerY,\r\n scene.getNonDeletedElementsMap(),\r\n scene.getNonDeletedElements(),\r\n appState,\r\n {\r\n ...opts,\r\n finalize: true,\r\n },\r\n );\r\n\r\n bindOrUnbindBindingElementEdge(arrow, start, \"start\", scene);\r\n bindOrUnbindBindingElementEdge(arrow, end, \"end\", scene);\r\n if (start.focusPoint || end.focusPoint) {\r\n // If the strategy dictates a focus point override, then\r\n // update the arrow points to point to the focus point.\r\n const updates: PointsPositionUpdates = new Map();\r\n\r\n if (start.focusPoint) {\r\n updates.set(0, {\r\n point:\r\n updateBoundPoint(\r\n arrow,\r\n \"startBinding\",\r\n arrow.startBinding,\r\n start.element,\r\n scene.getNonDeletedElementsMap(),\r\n ) || arrow.points[0],\r\n });\r\n }\r\n\r\n if (end.focusPoint) {\r\n updates.set(arrow.points.length - 1, {\r\n point:\r\n updateBoundPoint(\r\n arrow,\r\n \"endBinding\",\r\n arrow.endBinding,\r\n end.element,\r\n scene.getNonDeletedElementsMap(),\r\n ) || arrow.points[arrow.points.length - 1],\r\n });\r\n }\r\n\r\n LinearElementEditor.movePoints(arrow, scene, updates);\r\n }\r\n\r\n return { start, end };\r\n};\r\n\r\nconst bindOrUnbindBindingElementEdge = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n { mode, element, focusPoint }: BindingStrategy,\r\n startOrEnd: \"start\" | \"end\",\r\n scene: Scene,\r\n): void => {\r\n if (mode === null) {\r\n // null means break the binding\r\n unbindBindingElement(arrow, startOrEnd, scene);\r\n } else if (mode !== undefined) {\r\n bindBindingElement(arrow, element, mode, startOrEnd, scene, focusPoint);\r\n }\r\n};\r\n\r\nconst bindingStrategyForElbowArrowEndpointDragging = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n draggingPoints: PointsPositionUpdates,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n zoom?: AppState[\"zoom\"],\r\n): {\r\n start: BindingStrategy;\r\n end: BindingStrategy;\r\n} => {\r\n invariant(draggingPoints.size === 1, \"Bound elbow arrows cannot be moved\");\r\n\r\n const update = draggingPoints.entries().next().value;\r\n\r\n invariant(\r\n update,\r\n \"There should be a position update for dragging an elbow arrow endpoint\",\r\n );\r\n\r\n const [pointIdx, { point }] = update;\r\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\r\n arrow,\r\n point,\r\n elementsMap,\r\n );\r\n const hit = getHoveredElementForBinding(\r\n globalPoint,\r\n elements,\r\n elementsMap,\r\n (element) => maxBindingDistance_simple(zoom),\r\n );\r\n\r\n const current = hit\r\n ? {\r\n element: hit,\r\n mode: \"orbit\" as const,\r\n focusPoint: LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrow,\r\n pointIdx,\r\n elementsMap,\r\n ),\r\n }\r\n : {\r\n mode: null,\r\n };\r\n const other = { mode: undefined };\r\n\r\n return pointIdx === 0\r\n ? { start: current, end: other }\r\n : { start: other, end: current };\r\n};\r\n\r\nconst bindingStrategyForNewSimpleArrowEndpointDragging = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n draggingPoints: PointsPositionUpdates,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n startDragged: boolean,\r\n endDragged: boolean,\r\n startIdx: number,\r\n endIdx: number,\r\n appState: AppState,\r\n globalBindMode?: AppState[\"bindMode\"],\r\n shiftKey?: boolean,\r\n): {\r\n start: BindingStrategy;\r\n end: BindingStrategy;\r\n} => {\r\n let start: BindingStrategy = { mode: undefined };\r\n let end: BindingStrategy = { mode: undefined };\r\n\r\n const isMultiPoint = arrow.points.length > 2;\r\n const point = LinearElementEditor.getPointGlobalCoordinates(\r\n arrow,\r\n draggingPoints.get(startDragged ? startIdx : endIdx)!.point,\r\n elementsMap,\r\n );\r\n const hit = getHoveredElementForBinding(point, elements, elementsMap);\r\n\r\n // With new arrows this handles the binding at arrow creation\r\n if (startDragged) {\r\n if (hit) {\r\n start = {\r\n element: hit,\r\n mode: \"inside\",\r\n focusPoint: point,\r\n };\r\n } else {\r\n start = { mode: null };\r\n }\r\n\r\n return { start, end };\r\n }\r\n\r\n // With new arrows it represents the continuous dragging of the end point\r\n if (endDragged) {\r\n const origin = appState?.selectedLinearElement?.initialState.origin;\r\n\r\n // Inside -> inside binding\r\n if (hit && arrow.startBinding?.elementId === hit.id) {\r\n const center = pointFrom<GlobalPoint>(\r\n hit.x + hit.width / 2,\r\n hit.y + hit.height / 2,\r\n );\r\n\r\n return {\r\n start: isMultiPoint\r\n ? { mode: undefined }\r\n : {\r\n mode: \"inside\",\r\n element: hit,\r\n focusPoint: origin ?? center,\r\n },\r\n end: isMultiPoint\r\n ? { mode: \"orbit\", element: hit, focusPoint: point }\r\n : { mode: \"inside\", element: hit, focusPoint: point },\r\n };\r\n }\r\n\r\n // Check and handle nested shapes\r\n if (hit && arrow.startBinding) {\r\n const startBinding = arrow.startBinding;\r\n const allHits = getAllHoveredElementAtPoint(point, elements, elementsMap);\r\n\r\n if (allHits.find((el) => el.id === startBinding.elementId)) {\r\n const otherElement = elementsMap.get(\r\n arrow.startBinding.elementId,\r\n ) as ExcalidrawBindableElement;\r\n\r\n invariant(otherElement, \"Other element must be in the elements map\");\r\n\r\n return {\r\n start: isMultiPoint\r\n ? { mode: undefined }\r\n : {\r\n mode: otherElement.id !== hit.id ? \"orbit\" : \"inside\",\r\n element: otherElement,\r\n focusPoint: origin ?? pointFrom<GlobalPoint>(arrow.x, arrow.y),\r\n },\r\n end: {\r\n mode: \"orbit\",\r\n element: hit,\r\n focusPoint: point,\r\n },\r\n };\r\n }\r\n }\r\n\r\n // Inside -> outside binding\r\n if (arrow.startBinding && arrow.startBinding.elementId !== hit?.id) {\r\n const otherElement = elementsMap.get(\r\n arrow.startBinding.elementId,\r\n ) as ExcalidrawBindableElement;\r\n invariant(otherElement, \"Other element must be in the elements map\");\r\n\r\n const otherIsInsideBinding =\r\n !!appState.selectedLinearElement?.initialState.arrowStartIsInside;\r\n const other: BindingStrategy = {\r\n mode: otherIsInsideBinding ? \"inside\" : \"orbit\",\r\n element: otherElement,\r\n focusPoint: shiftKey\r\n ? elementCenterPoint(otherElement, elementsMap)\r\n : origin ?? pointFrom<GlobalPoint>(arrow.x, arrow.y),\r\n };\r\n\r\n // We are hovering another element with the end point\r\n const isNested =\r\n hit &&\r\n isBindableElementInsideOtherBindable(otherElement, hit, elementsMap);\r\n let current: BindingStrategy;\r\n if (hit) {\r\n const isInsideBinding =\r\n globalBindMode === \"inside\" || globalBindMode === \"skip\";\r\n current = {\r\n mode: isInsideBinding && !isNested ? \"inside\" : \"orbit\",\r\n element: hit,\r\n focusPoint: isInsideBinding || isNested ? point : point,\r\n };\r\n } else {\r\n current = { mode: null };\r\n }\r\n\r\n return {\r\n start: isMultiPoint ? { mode: undefined } : other,\r\n end: current,\r\n };\r\n }\r\n\r\n // No start binding\r\n if (!arrow.startBinding) {\r\n if (hit) {\r\n const isInsideBinding =\r\n globalBindMode === \"inside\" || globalBindMode === \"skip\";\r\n\r\n end = {\r\n mode: isInsideBinding ? \"inside\" : \"orbit\",\r\n element: hit,\r\n focusPoint: point,\r\n };\r\n } else {\r\n end = { mode: null };\r\n }\r\n\r\n return { start, end };\r\n }\r\n }\r\n\r\n invariant(false, \"New arrow creation should not reach here\");\r\n};\r\n\r\nconst bindingStrategyForSimpleArrowEndpointDragging_complex = (\r\n point: GlobalPoint,\r\n currentBinding: FixedPointBinding | null,\r\n oppositeBinding: FixedPointBinding | null,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n globalBindMode: AppState[\"bindMode\"],\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n finalize?: boolean,\r\n): { current: BindingStrategy; other: BindingStrategy } => {\r\n let current: BindingStrategy = { mode: undefined };\r\n let other: BindingStrategy = { mode: undefined };\r\n\r\n const isMultiPoint = arrow.points.length > 2;\r\n const hit = getHoveredElementForBinding(point, elements, elementsMap);\r\n const isOverlapping = oppositeBinding\r\n ? getAllHoveredElementAtPoint(point, elements, elementsMap).some(\r\n (el) => el.id === oppositeBinding.elementId,\r\n )\r\n : false;\r\n const oppositeElement = oppositeBinding\r\n ? (elementsMap.get(oppositeBinding.elementId) as ExcalidrawBindableElement)\r\n : null;\r\n const otherIsTransparent =\r\n isOverlapping && oppositeElement\r\n ? isTransparent(oppositeElement.backgroundColor)\r\n : false;\r\n const isNested =\r\n hit &&\r\n oppositeElement &&\r\n isBindableElementInsideOtherBindable(oppositeElement, hit, elementsMap);\r\n\r\n // If the global bind mode is in free binding mode, just bind\r\n // where the pointer is and keep the other end intact\r\n if (globalBindMode === \"inside\" || globalBindMode === \"skip\") {\r\n current = hit\r\n ? {\r\n element:\r\n !isOverlapping || !oppositeElement || otherIsTransparent\r\n ? hit\r\n : oppositeElement,\r\n focusPoint: point,\r\n mode: \"inside\",\r\n }\r\n : { mode: null };\r\n other =\r\n finalize && hit && hit.id === oppositeBinding?.elementId\r\n ? { mode: null }\r\n : other;\r\n\r\n return { current, other };\r\n }\r\n\r\n // Dragged point is outside of any bindable element\r\n // so we break any existing binding\r\n if (!hit) {\r\n return { current: { mode: null }, other };\r\n }\r\n\r\n // Already inside binding over the same hit element should remain inside bound\r\n if (\r\n hit.id === currentBinding?.elementId &&\r\n currentBinding.mode === \"inside\"\r\n ) {\r\n return {\r\n current: { mode: \"inside\", focusPoint: point, element: hit },\r\n other,\r\n };\r\n }\r\n\r\n // The dragged point is inside the hovered bindable element\r\n if (oppositeBinding) {\r\n // The opposite binding is on the same element\r\n if (oppositeBinding.elementId === hit.id) {\r\n // The opposite binding is on the binding gap of the same element\r\n if (oppositeBinding.mode === \"orbit\") {\r\n current = { element: hit, mode: \"orbit\", focusPoint: point };\r\n other = { mode: finalize ? null : undefined };\r\n\r\n return { current, other: isMultiPoint ? { mode: undefined } : other };\r\n }\r\n // The opposite binding is inside the same element\r\n // eslint-disable-next-line no-else-return\r\n else {\r\n current = { element: hit, mode: \"inside\", focusPoint: point };\r\n\r\n return { current, other: isMultiPoint ? { mode: undefined } : other };\r\n }\r\n }\r\n // The opposite binding is on a different element (or nested)\r\n // eslint-disable-next-line no-else-return\r\n else {\r\n // Handle the nested element case\r\n if (isOverlapping && oppositeElement && !otherIsTransparent) {\r\n current = {\r\n element: oppositeElement,\r\n mode: \"inside\",\r\n focusPoint: point,\r\n };\r\n } else {\r\n current = {\r\n element: hit,\r\n mode: \"orbit\",\r\n focusPoint: isNested ? point : point,\r\n };\r\n }\r\n\r\n return { current, other: isMultiPoint ? { mode: undefined } : other };\r\n }\r\n }\r\n // The opposite binding is on a different element or no binding\r\n else {\r\n current = {\r\n element: hit,\r\n mode: \"orbit\",\r\n focusPoint: point,\r\n };\r\n }\r\n\r\n // Must return as only one endpoint is dragged, therefore\r\n // the end binding strategy might accidentally gets overriden\r\n return { current, other: isMultiPoint ? { mode: undefined } : other };\r\n};\r\n\r\nexport const getBindingStrategyForDraggingBindingElementEndpoints = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n draggingPoints: PointsPositionUpdates,\r\n screenPointerX: number,\r\n screenPointerY: number,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n appState: AppState,\r\n opts?: {\r\n newArrow?: boolean;\r\n angleLocked?: boolean;\r\n altKey?: boolean;\r\n finalize?: boolean;\r\n initialBinding?: boolean;\r\n zoom?: AppState[\"zoom\"];\r\n },\r\n): { start: BindingStrategy; end: BindingStrategy } => {\r\n if (getFeatureFlag(\"COMPLEX_BINDINGS\")) {\r\n return getBindingStrategyForDraggingBindingElementEndpoints_complex(\r\n arrow,\r\n draggingPoints,\r\n elementsMap,\r\n elements,\r\n appState,\r\n opts,\r\n );\r\n }\r\n\r\n return getBindingStrategyForDraggingBindingElementEndpoints_simple(\r\n arrow,\r\n draggingPoints,\r\n screenPointerX,\r\n screenPointerY,\r\n elementsMap,\r\n elements,\r\n appState,\r\n opts,\r\n );\r\n};\r\n\r\nconst getBindingStrategyForDraggingBindingElementEndpoints_simple = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n draggingPoints: PointsPositionUpdates,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n appState: AppState,\r\n opts?: {\r\n newArrow?: boolean;\r\n angleLocked?: boolean;\r\n altKey?: boolean;\r\n finalize?: boolean;\r\n initialBinding?: boolean;\r\n zoom?: AppState[\"zoom\"];\r\n },\r\n): { start: BindingStrategy; end: BindingStrategy } => {\r\n const startIdx = 0;\r\n const endIdx = arrow.points.length - 1;\r\n const startDragged = draggingPoints.has(startIdx);\r\n const endDragged = draggingPoints.has(endIdx);\r\n\r\n let start: BindingStrategy = { mode: undefined };\r\n let end: BindingStrategy = { mode: undefined };\r\n\r\n invariant(\r\n arrow.points.length > 1,\r\n \"Do not attempt to bind linear elements with a single point\",\r\n );\r\n\r\n // If none of the ends are dragged, we don't change anything\r\n if (!startDragged && !endDragged) {\r\n return { start, end };\r\n }\r\n\r\n // If both ends are dragged, we don't bind to anything\r\n // and break existing bindings\r\n if (startDragged && endDragged) {\r\n return { start: { mode: null }, end: { mode: null } };\r\n }\r\n\r\n // If binding is disabled and an endpoint is dragged,\r\n // we actively break the end binding\r\n if (!isBindingEnabled(appState)) {\r\n start = startDragged ? { mode: null } : start;\r\n end = endDragged ? { mode: null } : end;\r\n\r\n return { start, end };\r\n }\r\n\r\n // Handle simpler elbow arrow binding\r\n if (isElbowArrow(arrow)) {\r\n return bindingStrategyForElbowArrowEndpointDragging(\r\n arrow,\r\n draggingPoints,\r\n elementsMap,\r\n elements,\r\n opts?.zoom,\r\n );\r\n }\r\n\r\n const otherBinding = startDragged ? arrow.endBinding : arrow.startBinding;\r\n const localPoint = draggingPoints.get(\r\n startDragged ? startIdx : endIdx,\r\n )?.point;\r\n invariant(\r\n localPoint,\r\n `Local point must be defined for ${\r\n startDragged ? \"start\" : \"end\"\r\n } dragging`,\r\n );\r\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\r\n arrow,\r\n localPoint,\r\n elementsMap,\r\n );\r\n const hit = getHoveredElementForBinding(\r\n globalPoint,\r\n elements,\r\n elementsMap,\r\n (e) => maxBindingDistance_simple(appState.zoom),\r\n );\r\n const pointInElement =\r\n hit &&\r\n (opts?.angleLocked\r\n ? isPointInElement(\r\n pointFrom<GlobalPoint>(scenePointerX, scenePointerY),\r\n hit,\r\n elementsMap,\r\n )\r\n : isPointInElement(globalPoint, hit, elementsMap));\r\n const otherBindableElement = otherBinding\r\n ? (elementsMap.get(\r\n otherBinding.elementId,\r\n ) as NonDeleted<ExcalidrawBindableElement>)\r\n : undefined;\r\n const otherFocusPoint =\r\n otherBinding &&\r\n otherBindableElement &&\r\n getGlobalFixedPointForBindableElement(\r\n otherBinding.fixedPoint,\r\n otherBindableElement,\r\n elementsMap,\r\n );\r\n const otherFocusPointIsInElement =\r\n otherBindableElement &&\r\n otherFocusPoint &&\r\n isPointInElement(otherFocusPoint, otherBindableElement, elementsMap);\r\n\r\n // Handle outside-outside binding to the same element\r\n if (otherBinding && otherBinding.elementId === hit?.id) {\r\n invariant(\r\n !opts?.newArrow || appState.selectedLinearElement?.initialState.origin,\r\n \"appState.selectedLinearElement.initialState.origin must be defined for new arrows\",\r\n );\r\n\r\n return {\r\n start: {\r\n mode: \"inside\",\r\n element: hit,\r\n focusPoint: startDragged\r\n ? globalPoint\r\n : // NOTE: Can only affect the start point because new arrows always drag the end point\r\n opts?.newArrow\r\n ? appState.selectedLinearElement!.initialState.origin!\r\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrow,\r\n 0,\r\n elementsMap,\r\n ), // startFixedPoint,\r\n },\r\n end: {\r\n mode: \"inside\",\r\n element: hit,\r\n focusPoint: endDragged\r\n ? globalPoint\r\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrow,\r\n -1,\r\n elementsMap,\r\n ), // endFixedPoint\r\n },\r\n };\r\n }\r\n\r\n // Handle special alt key case to inside bind no matter what\r\n if (opts?.altKey) {\r\n return {\r\n start: startDragged\r\n ? hit\r\n ? {\r\n mode: \"inside\",\r\n element: hit,\r\n focusPoint: globalPoint,\r\n }\r\n : { mode: null }\r\n : start,\r\n end: endDragged\r\n ? hit\r\n ? {\r\n mode: \"inside\",\r\n element: hit,\r\n focusPoint: globalPoint,\r\n }\r\n : { mode: null }\r\n : end,\r\n };\r\n }\r\n\r\n // Handle normal cases\r\n const current: BindingStrategy = hit\r\n ? pointInElement\r\n ? {\r\n mode: \"inside\",\r\n element: hit,\r\n focusPoint: globalPoint,\r\n }\r\n : {\r\n mode: \"orbit\",\r\n element: hit,\r\n focusPoint:\r\n projectFixedPointOntoDiagonal(\r\n arrow,\r\n globalPoint,\r\n hit,\r\n startDragged ? \"start\" : \"end\",\r\n elementsMap,\r\n ) || globalPoint,\r\n }\r\n : { mode: null };\r\n\r\n const otherEndpoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrow,\r\n startDragged ? -1 : 0,\r\n elementsMap,\r\n );\r\n\r\n const other: BindingStrategy =\r\n otherBindableElement &&\r\n !otherFocusPointIsInElement &&\r\n appState.selectedLinearElement?.initialState.altFocusPoint\r\n ? {\r\n mode: \"orbit\",\r\n element: otherBindableElement,\r\n focusPoint: appState.selectedLinearElement.initialState.altFocusPoint,\r\n }\r\n : opts?.angleLocked && otherBindableElement\r\n ? {\r\n mode: \"orbit\",\r\n element: otherBindableElement,\r\n focusPoint:\r\n projectFixedPointOntoDiagonal(\r\n arrow,\r\n otherEndpoint,\r\n otherBindableElement,\r\n startDragged ? \"end\" : \"start\",\r\n elementsMap,\r\n ) || otherEndpoint,\r\n }\r\n : { mode: undefined };\r\n\r\n return {\r\n start: startDragged ? current : other,\r\n end: endDragged ? current : other,\r\n };\r\n};\r\n\r\nconst getBindingStrategyForDraggingBindingElementEndpoints_complex = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n draggingPoints: PointsPositionUpdates,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n appState: AppState,\r\n opts?: {\r\n newArrow?: boolean;\r\n shiftKey?: boolean;\r\n finalize?: boolean;\r\n initialBinding?: boolean;\r\n },\r\n): { start: BindingStrategy; end: BindingStrategy } => {\r\n const globalBindMode = appState.bindMode || \"orbit\";\r\n const startIdx = 0;\r\n const endIdx = arrow.points.length - 1;\r\n const startDragged = draggingPoints.has(startIdx);\r\n const endDragged = draggingPoints.has(endIdx);\r\n\r\n let start: BindingStrategy = { mode: undefined };\r\n let end: BindingStrategy = { mode: undefined };\r\n\r\n invariant(\r\n arrow.points.length > 1,\r\n \"Do not attempt to bind linear elements with a single point\",\r\n );\r\n\r\n // If none of the ends are dragged, we don't change anything\r\n if (!startDragged && !endDragged) {\r\n return { start, end };\r\n }\r\n\r\n // If both ends are dragged, we don't bind to anything\r\n // and break existing bindings\r\n if (startDragged && endDragged) {\r\n return { start: { mode: null }, end: { mode: null } };\r\n }\r\n\r\n // If binding is disabled and an endpoint is dragged,\r\n // we actively break the end binding\r\n if (!isBindingEnabled(appState)) {\r\n start = startDragged ? { mode: null } : start;\r\n end = endDragged ? { mode: null } : end;\r\n\r\n return { start, end };\r\n }\r\n\r\n // Handle simpler elbow arrow binding\r\n if (isElbowArrow(arrow)) {\r\n return bindingStrategyForElbowArrowEndpointDragging(\r\n arrow,\r\n draggingPoints,\r\n elementsMap,\r\n elements,\r\n );\r\n }\r\n\r\n // Handle new arrow creation separately, as it is special\r\n if (opts?.newArrow) {\r\n const { start, end } = bindingStrategyForNewSimpleArrowEndpointDragging(\r\n arrow,\r\n draggingPoints,\r\n elementsMap,\r\n elements,\r\n startDragged,\r\n endDragged,\r\n startIdx,\r\n endIdx,\r\n appState,\r\n globalBindMode,\r\n opts?.shiftKey,\r\n );\r\n\r\n return { start, end };\r\n }\r\n\r\n // Only the start point is dragged\r\n if (startDragged) {\r\n const localPoint = draggingPoints.get(startIdx)?.point;\r\n invariant(localPoint, \"Local point must be defined for start dragging\");\r\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\r\n arrow,\r\n localPoint,\r\n elementsMap,\r\n );\r\n\r\n const { current, other } =\r\n bindingStrategyForSimpleArrowEndpointDragging_complex(\r\n globalPoint,\r\n arrow.startBinding,\r\n arrow.endBinding,\r\n elementsMap,\r\n elements,\r\n globalBindMode,\r\n arrow,\r\n opts?.finalize,\r\n );\r\n\r\n return { start: current, end: other };\r\n }\r\n\r\n // Only the end point is dragged\r\n if (endDragged) {\r\n const localPoint = draggingPoints.get(endIdx)?.point;\r\n invariant(localPoint, \"Local point must be defined for end dragging\");\r\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\r\n arrow,\r\n localPoint,\r\n elementsMap,\r\n );\r\n const { current, other } =\r\n bindingStrategyForSimpleArrowEndpointDragging_complex(\r\n globalPoint,\r\n arrow.endBinding,\r\n arrow.startBinding,\r\n elementsMap,\r\n elements,\r\n globalBindMode,\r\n arrow,\r\n opts?.finalize,\r\n );\r\n\r\n return { start: other, end: current };\r\n }\r\n\r\n return { start, end };\r\n};\r\n\r\nexport const bindOrUnbindBindingElements = (\r\n selectedArrows: NonDeleted<ExcalidrawArrowElement>[],\r\n scene: Scene,\r\n appState: AppState,\r\n): void => {\r\n selectedArrows.forEach((arrow) => {\r\n bindOrUnbindBindingElement(\r\n arrow,\r\n new Map(), // No dragging points in this case\r\n Infinity,\r\n Infinity,\r\n scene,\r\n appState,\r\n );\r\n });\r\n};\r\n\r\nexport const bindBindingElement = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n hoveredElement: ExcalidrawBindableElement,\r\n mode: BindMode,\r\n startOrEnd: \"start\" | \"end\",\r\n scene: Scene,\r\n focusPoint?: GlobalPoint,\r\n): void => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n\r\n let binding: FixedPointBinding;\r\n\r\n if (isElbowArrow(arrow)) {\r\n binding = {\r\n elementId: hoveredElement.id,\r\n mode: \"orbit\",\r\n ...calculateFixedPointForElbowArrowBinding(\r\n arrow,\r\n hoveredElement,\r\n startOrEnd,\r\n elementsMap,\r\n ),\r\n };\r\n } else {\r\n binding = {\r\n elementId: hoveredElement.id,\r\n mode,\r\n ...calculateFixedPointForNonElbowArrowBinding(\r\n arrow,\r\n hoveredElement,\r\n startOrEnd,\r\n elementsMap,\r\n focusPoint,\r\n ),\r\n };\r\n }\r\n\r\n scene.mutateElement(arrow, {\r\n [startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\"]: binding,\r\n });\r\n\r\n const boundElementsMap = arrayToMap(hoveredElement.boundElements || []);\r\n if (!boundElementsMap.has(arrow.id)) {\r\n scene.mutateElement(hoveredElement, {\r\n boundElements: (hoveredElement.boundElements || []).concat({\r\n id: arrow.id,\r\n type: \"arrow\",\r\n }),\r\n });\r\n }\r\n};\r\n\r\nexport const unbindBindingElement = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n startOrEnd: \"start\" | \"end\",\r\n scene: Scene,\r\n): ExcalidrawBindableElement[\"id\"] | null => {\r\n const field = startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\";\r\n const binding = arrow[field];\r\n\r\n if (binding == null) {\r\n return null;\r\n }\r\n\r\n const oppositeBinding =\r\n arrow[startOrEnd === \"start\" ? \"endBinding\" : \"startBinding\"];\r\n if (!oppositeBinding || oppositeBinding.elementId !== binding.elementId) {\r\n // Only remove the record on the bound element if the other\r\n // end is not bound to the same element\r\n const boundElement = scene\r\n .getNonDeletedElementsMap()\r\n .get(binding.elementId) as ExcalidrawBindableElement;\r\n scene.mutateElement(boundElement, {\r\n boundElements: boundElement.boundElements?.filter(\r\n (element) => element.id !== arrow.id,\r\n ),\r\n });\r\n }\r\n\r\n scene.mutateElement(arrow, { [field]: null });\r\n\r\n return binding.elementId;\r\n};\r\n\r\n// Supports translating, rotating and scaling `changedElement` with bound\r\n// linear elements.\r\nexport const updateBoundElements = (\r\n changedElement: NonDeletedExcalidrawElement,\r\n scene: Scene,\r\n options?: {\r\n simultaneouslyUpdated?: readonly ExcalidrawElement[];\r\n changedElements?: Map<string, ExcalidrawElement>;\r\n },\r\n) => {\r\n if (!isBindableElement(changedElement)) {\r\n return;\r\n }\r\n\r\n const { simultaneouslyUpdated } = options ?? {};\r\n const simultaneouslyUpdatedElementIds = getSimultaneouslyUpdatedElementIds(\r\n simultaneouslyUpdated,\r\n );\r\n\r\n let elementsMap: ElementsMap = scene.getNonDeletedElementsMap();\r\n if (options?.changedElements) {\r\n elementsMap = new Map(elementsMap) as typeof elementsMap;\r\n options.changedElements.forEach((element) => {\r\n elementsMap.set(element.id, element);\r\n });\r\n }\r\n\r\n boundElementsVisitor(elementsMap, changedElement, (element) => {\r\n if (!isArrowElement(element) || element.isDeleted) {\r\n return;\r\n }\r\n\r\n // In case the boundElements are stale\r\n if (!doesNeedUpdate(element, changedElement)) {\r\n return;\r\n }\r\n\r\n // Check for intersections before updating bound elements incase connected elements overlap\r\n const startBindingElement = element.startBinding\r\n ? elementsMap.get(element.startBinding.elementId)\r\n : null;\r\n const endBindingElement = element.endBinding\r\n ? // PERF: If the arrow is bound to the same element on both ends.\r\n startBindingElement?.id === element.endBinding.elementId\r\n ? startBindingElement\r\n : elementsMap.get(element.endBinding.elementId)\r\n : null;\r\n\r\n // `linearElement` is being moved/scaled already, just update the binding\r\n if (simultaneouslyUpdatedElementIds.has(element.id)) {\r\n return;\r\n }\r\n\r\n const updates = bindableElementsVisitor(\r\n elementsMap,\r\n element,\r\n (bindableElement, bindingProp) => {\r\n if (\r\n bindableElement &&\r\n isBindableElement(bindableElement) &&\r\n (bindingProp === \"startBinding\" || bindingProp === \"endBinding\") &&\r\n (changedElement.id === element[bindingProp]?.elementId ||\r\n changedElement.id ===\r\n element[\r\n bindingProp === \"startBinding\" ? \"endBinding\" : \"startBinding\"\r\n ]?.elementId)\r\n ) {\r\n const point = updateBoundPoint(\r\n element,\r\n bindingProp,\r\n element[bindingProp],\r\n bindableElement,\r\n elementsMap,\r\n );\r\n\r\n if (point) {\r\n return [\r\n bindingProp === \"startBinding\" ? 0 : element.points.length - 1,\r\n { point },\r\n ] as MapEntry<PointsPositionUpdates>;\r\n }\r\n }\r\n\r\n return null;\r\n },\r\n ).filter(\r\n (update): update is MapEntry<PointsPositionUpdates> => update !== null,\r\n );\r\n\r\n LinearElementEditor.movePoints(element, scene, new Map(updates), {\r\n moveMidPointsWithElement:\r\n !!startBindingElement &&\r\n startBindingElement?.id === endBindingElement?.id,\r\n });\r\n\r\n const boundText = getBoundTextElement(element, elementsMap);\r\n if (boundText && !boundText.isDeleted) {\r\n handleBindTextResize(element, scene, false);\r\n }\r\n });\r\n};\r\n\r\nexport const updateBindings = (\r\n latestElement: ExcalidrawElement,\r\n scene: Scene,\r\n appState: AppState,\r\n options?: {\r\n simultaneouslyUpdated?: readonly ExcalidrawElement[];\r\n newSize?: { width: number; height: number };\r\n },\r\n) => {\r\n if (isArrowElement(latestElement)) {\r\n bindOrUnbindBindingElement(\r\n latestElement,\r\n new Map(),\r\n Infinity,\r\n Infinity,\r\n scene,\r\n appState,\r\n );\r\n } else {\r\n updateBoundElements(latestElement, scene, {\r\n ...options,\r\n changedElements: new Map([[latestElement.id, latestElement]]),\r\n });\r\n }\r\n};\r\n\r\nconst doesNeedUpdate = (\r\n boundElement: NonDeleted<ExcalidrawArrowElement>,\r\n changedElement: ExcalidrawBindableElement,\r\n) => {\r\n return (\r\n boundElement.startBinding?.elementId === changedElement.id ||\r\n boundElement.endBinding?.elementId === changedElement.id\r\n );\r\n};\r\n\r\nconst getSimultaneouslyUpdatedElementIds = (\r\n simultaneouslyUpdated: readonly ExcalidrawElement[] | undefined,\r\n): Set<ExcalidrawElement[\"id\"]> => {\r\n return new Set((simultaneouslyUpdated || []).map((element) => element.id));\r\n};\r\n\r\nexport const getHeadingForElbowArrowSnap = (\r\n p: Readonly<GlobalPoint>,\r\n otherPoint: Readonly<GlobalPoint>,\r\n bindableElement: ExcalidrawBindableElement | undefined | null,\r\n aabb: Bounds | undefined | null,\r\n origPoint: GlobalPoint,\r\n elementsMap: ElementsMap,\r\n zoom?: AppState[\"zoom\"],\r\n): Heading => {\r\n const otherPointHeading = vectorToHeading(vectorFromPoint(otherPoint, p));\r\n\r\n if (!bindableElement || !aabb) {\r\n return otherPointHeading;\r\n }\r\n\r\n const distance = getDistanceForBinding(\r\n origPoint,\r\n bindableElement,\r\n elementsMap,\r\n zoom,\r\n );\r\n\r\n if (!distance) {\r\n return vectorToHeading(\r\n vectorFromPoint(p, elementCenterPoint(bindableElement, elementsMap)),\r\n );\r\n }\r\n\r\n return headingForPointFromElement(bindableElement, aabb, p);\r\n};\r\n\r\nconst getDistanceForBinding = (\r\n point: Readonly<GlobalPoint>,\r\n bindableElement: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n zoom?: AppState[\"zoom\"],\r\n) => {\r\n const distance = distanceToElement(bindableElement, elementsMap, point);\r\n const bindDistance = maxBindingDistance_simple(zoom);\r\n\r\n return distance > bindDistance ? null : distance;\r\n};\r\n\r\nexport const bindPointToSnapToElementOutline = (\r\n arrowElement: ExcalidrawArrowElement,\r\n bindableElement: ExcalidrawBindableElement,\r\n startOrEnd: \"start\" | \"end\",\r\n elementsMap: ElementsMap,\r\n customIntersector?: LineSegment<GlobalPoint>,\r\n): GlobalPoint => {\r\n const elbowed = isElbowArrow(arrowElement);\r\n const point = LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrowElement,\r\n startOrEnd === \"start\" ? 0 : -1,\r\n elementsMap,\r\n );\r\n\r\n if (arrowElement.points.length < 2) {\r\n // New arrow creation, so no snapping\r\n return point;\r\n }\r\n\r\n const edgePoint =\r\n isRectanguloidElement(bindableElement) && elbowed\r\n ? avoidRectangularCorner(\r\n arrowElement,\r\n bindableElement,\r\n elementsMap,\r\n point,\r\n )\r\n : point;\r\n const adjacentPoint =\r\n customIntersector && !elbowed\r\n ? customIntersector[1]\r\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrowElement,\r\n startOrEnd === \"start\" ? 1 : -2,\r\n elementsMap,\r\n );\r\n const bindingGap = getBindingGap(bindableElement, arrowElement);\r\n const aabb = aabbForElement(bindableElement, elementsMap);\r\n const bindableCenter = getCenterForBounds(aabb);\r\n\r\n let intersection: GlobalPoint | null = null;\r\n if (elbowed) {\r\n const isHorizontal = headingIsHorizontal(\r\n headingForPointFromElement(bindableElement, aabb, point),\r\n );\r\n const snapPoint = snapToMid(\r\n arrowElement,\r\n bindableElement,\r\n elementsMap,\r\n edgePoint,\r\n );\r\n const otherPoint = pointFrom<GlobalPoint>(\r\n isHorizontal ? bindableCenter[0] : snapPoint[0],\r\n !isHorizontal ? bindableCenter[1] : snapPoint[1],\r\n );\r\n const intersector =\r\n customIntersector ??\r\n lineSegment(\r\n otherPoint,\r\n pointFromVector(\r\n vectorScale(\r\n vectorNormalize(vectorFromPoint(snapPoint, otherPoint)),\r\n Math.max(bindableElement.width, bindableElement.height) * 2,\r\n ),\r\n otherPoint,\r\n ),\r\n );\r\n intersection = intersectElementWithLineSegment(\r\n bindableElement,\r\n elementsMap,\r\n intersector,\r\n bindingGap,\r\n ).sort(pointDistanceSq)[0];\r\n\r\n if (!intersection) {\r\n const anotherPoint = pointFrom<GlobalPoint>(\r\n !isHorizontal ? bindableCenter[0] : snapPoint[0],\r\n isHorizontal ? bindableCenter[1] : snapPoint[1],\r\n );\r\n const anotherIntersector = lineSegment(\r\n anotherPoint,\r\n pointFromVector(\r\n vectorScale(\r\n vectorNormalize(vectorFromPoint(snapPoint, anotherPoint)),\r\n Math.max(bindableElement.width, bindableElement.height) * 2,\r\n ),\r\n anotherPoint,\r\n ),\r\n );\r\n intersection = intersectElementWithLineSegment(\r\n bindableElement,\r\n elementsMap,\r\n anotherIntersector,\r\n BASE_BINDING_GAP_ELBOW,\r\n ).sort(pointDistanceSq)[0];\r\n }\r\n } else {\r\n let intersector = customIntersector;\r\n if (!intersector) {\r\n const halfVector = vectorScale(\r\n vectorNormalize(vectorFromPoint(edgePoint, adjacentPoint)),\r\n pointDistance(edgePoint, adjacentPoint) +\r\n Math.max(bindableElement.width, bindableElement.height) +\r\n bindingGap * 2,\r\n );\r\n intersector =\r\n customIntersector ??\r\n lineSegment(\r\n pointFromVector(halfVector, adjacentPoint),\r\n pointFromVector(vectorScale(halfVector, -1), adjacentPoint),\r\n );\r\n }\r\n\r\n intersection =\r\n pointDistance(edgePoint, adjacentPoint) < 1\r\n ? edgePoint\r\n : intersectElementWithLineSegment(\r\n bindableElement,\r\n elementsMap,\r\n intersector,\r\n bindingGap,\r\n ).sort(\r\n (g, h) =>\r\n pointDistanceSq(g, adjacentPoint) -\r\n pointDistanceSq(h, adjacentPoint),\r\n )[0];\r\n }\r\n\r\n if (\r\n !intersection ||\r\n // Too close to determine vector from intersection to edgePoint\r\n pointDistanceSq(edgePoint, intersection) < PRECISION\r\n ) {\r\n return edgePoint;\r\n }\r\n\r\n return intersection;\r\n};\r\n\r\nexport const avoidRectangularCorner = (\r\n arrowElement: ExcalidrawArrowElement,\r\n bindTarget: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n p: GlobalPoint,\r\n): GlobalPoint => {\r\n const center = elementCenterPoint(bindTarget, elementsMap);\r\n const nonRotatedPoint = pointRotateRads(\r\n p,\r\n center,\r\n -bindTarget.angle as Radians,\r\n );\r\n\r\n const bindingGap = getBindingGap(bindTarget, arrowElement);\r\n\r\n if (nonRotatedPoint[0] < bindTarget.x && nonRotatedPoint[1] < bindTarget.y) {\r\n // Top left\r\n if (nonRotatedPoint[1] - bindTarget.y > -bindingGap) {\r\n return pointRotateRads<GlobalPoint>(\r\n pointFrom(bindTarget.x - bindingGap, bindTarget.y),\r\n center,\r\n bindTarget.angle,\r\n );\r\n }\r\n return pointRotateRads(\r\n pointFrom(bindTarget.x, bindTarget.y - bindingGap),\r\n center,\r\n bindTarget.angle,\r\n );\r\n } else if (\r\n nonRotatedPoint[0] < bindTarget.x &&\r\n nonRotatedPoint[1] > bindTarget.y + bindTarget.height\r\n ) {\r\n // Bottom left\r\n if (nonRotatedPoint[0] - bindTarget.x > -bindingGap) {\r\n return pointRotateRads(\r\n pointFrom(bindTarget.x, bindTarget.y + bindTarget.height + bindingGap),\r\n center,\r\n bindTarget.angle,\r\n );\r\n }\r\n return pointRotateRads(\r\n pointFrom(bindTarget.x - bindingGap, bindTarget.y + bindTarget.height),\r\n center,\r\n bindTarget.angle,\r\n );\r\n } else if (\r\n nonRotatedPoint[0] > bindTarget.x + bindTarget.width &&\r\n nonRotatedPoint[1] > bindTarget.y + bindTarget.height\r\n ) {\r\n // Bottom right\r\n if (nonRotatedPoint[0] - bindTarget.x < bindTarget.width + bindingGap) {\r\n return pointRotateRads(\r\n pointFrom(\r\n bindTarget.x + bindTarget.width,\r\n bindTarget.y + bindTarget.height + bindingGap,\r\n ),\r\n center,\r\n bindTarget.angle,\r\n );\r\n }\r\n return pointRotateRads(\r\n pointFrom(\r\n bindTarget.x + bindTarget.width + bindingGap,\r\n bindTarget.y + bindTarget.height,\r\n ),\r\n center,\r\n bindTarget.angle,\r\n );\r\n } else if (\r\n nonRotatedPoint[0] > bindTarget.x + bindTarget.width &&\r\n nonRotatedPoint[1] < bindTarget.y\r\n ) {\r\n // Top right\r\n if (nonRotatedPoint[0] - bindTarget.x < bindTarget.width + bindingGap) {\r\n return pointRotateRads(\r\n pointFrom(bindTarget.x + bindTarget.width, bindTarget.y - bindingGap),\r\n center,\r\n bindTarget.angle,\r\n );\r\n }\r\n return pointRotateRads(\r\n pointFrom(bindTarget.x + bindTarget.width + bindingGap, bindTarget.y),\r\n center,\r\n bindTarget.angle,\r\n );\r\n }\r\n\r\n return p;\r\n};\r\n\r\nconst snapToMid = (\r\n arrowElement: ExcalidrawArrowElement,\r\n bindTarget: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n p: GlobalPoint,\r\n tolerance: number = 0.05,\r\n): GlobalPoint => {\r\n const { x, y, width, height, angle } = bindTarget;\r\n const center = elementCenterPoint(bindTarget, elementsMap, -0.1, -0.1);\r\n const nonRotated = pointRotateRads(p, center, -angle as Radians);\r\n\r\n const bindingGap = getBindingGap(bindTarget, arrowElement);\r\n\r\n // snap-to-center point is adaptive to element size, but we don't want to go\r\n // above and below certain px distance\r\n const verticalThreshold = clamp(tolerance * height, 5, 80);\r\n const horizontalThreshold = clamp(tolerance * width, 5, 80);\r\n\r\n // Too close to the center makes it hard to resolve direction precisely\r\n if (pointDistance(center, nonRotated) < bindingGap) {\r\n return p;\r\n }\r\n\r\n if (\r\n nonRotated[0] <= x + width / 2 &&\r\n nonRotated[1] > center[1] - verticalThreshold &&\r\n nonRotated[1] < center[1] + verticalThreshold\r\n ) {\r\n // LEFT\r\n return pointRotateRads<GlobalPoint>(\r\n pointFrom(x - bindingGap, center[1]),\r\n center,\r\n angle,\r\n );\r\n } else if (\r\n nonRotated[1] <= y + height / 2 &&\r\n nonRotated[0] > center[0] - horizontalThreshold &&\r\n nonRotated[0] < center[0] + horizontalThreshold\r\n ) {\r\n // TOP\r\n return pointRotateRads(pointFrom(center[0], y - bindingGap), center, angle);\r\n } else if (\r\n nonRotated[0] >= x + width / 2 &&\r\n nonRotated[1] > center[1] - verticalThreshold &&\r\n nonRotated[1] < center[1] + verticalThreshold\r\n ) {\r\n // RIGHT\r\n return pointRotateRads(\r\n pointFrom(x + width + bindingGap, center[1]),\r\n center,\r\n angle,\r\n );\r\n } else if (\r\n nonRotated[1] >= y + height / 2 &&\r\n nonRotated[0] > center[0] - horizontalThreshold &&\r\n nonRotated[0] < center[0] + horizontalThreshold\r\n ) {\r\n // DOWN\r\n return pointRotateRads(\r\n pointFrom(center[0], y + height + bindingGap),\r\n center,\r\n angle,\r\n );\r\n } else if (bindTarget.type === \"diamond\") {\r\n const distance = bindingGap;\r\n const topLeft = pointFrom<GlobalPoint>(\r\n x + width / 4 - distance,\r\n y + height / 4 - distance,\r\n );\r\n const topRight = pointFrom<GlobalPoint>(\r\n x + (3 * width) / 4 + distance,\r\n y + height / 4 - distance,\r\n );\r\n const bottomLeft = pointFrom<GlobalPoint>(\r\n x + width / 4 - distance,\r\n y + (3 * height) / 4 + distance,\r\n );\r\n const bottomRight = pointFrom<GlobalPoint>(\r\n x + (3 * width) / 4 + distance,\r\n y + (3 * height) / 4 + distance,\r\n );\r\n\r\n if (\r\n pointDistance(topLeft, nonRotated) <\r\n Math.max(horizontalThreshold, verticalThreshold)\r\n ) {\r\n return pointRotateRads(topLeft, center, angle);\r\n }\r\n if (\r\n pointDistance(topRight, nonRotated) <\r\n Math.max(horizontalThreshold, verticalThreshold)\r\n ) {\r\n return pointRotateRads(topRight, center, angle);\r\n }\r\n if (\r\n pointDistance(bottomLeft, nonRotated) <\r\n Math.max(horizontalThreshold, verticalThreshold)\r\n ) {\r\n return pointRotateRads(bottomLeft, center, angle);\r\n }\r\n if (\r\n pointDistance(bottomRight, nonRotated) <\r\n Math.max(horizontalThreshold, verticalThreshold)\r\n ) {\r\n return pointRotateRads(bottomRight, center, angle);\r\n }\r\n }\r\n\r\n return p;\r\n};\r\n\r\nconst compareElementArea = (\r\n a: ExcalidrawBindableElement,\r\n b: ExcalidrawBindableElement,\r\n) => b.width ** 2 + b.height ** 2 - (a.width ** 2 + a.height ** 2);\r\n\r\nexport const updateBoundPoint = (\r\n arrow: NonDeleted<ExcalidrawArrowElement>,\r\n startOrEnd: \"startBinding\" | \"endBinding\",\r\n binding: FixedPointBinding | null | undefined,\r\n bindableElement: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n customIntersector?: LineSegment<GlobalPoint>,\r\n): LocalPoint | null => {\r\n if (\r\n binding == null ||\r\n // We only need to update the other end if this is a 2 point line element\r\n (binding.elementId !== bindableElement.id && arrow.points.length > 2)\r\n ) {\r\n return null;\r\n }\r\n\r\n const global = getGlobalFixedPointForBindableElement(\r\n normalizeFixedPoint(binding.fixedPoint),\r\n bindableElement,\r\n elementsMap,\r\n );\r\n const pointIndex =\r\n startOrEnd === \"startBinding\" ? 0 : arrow.points.length - 1;\r\n const elbowed = isElbowArrow(arrow);\r\n const otherBinding =\r\n startOrEnd === \"startBinding\" ? arrow.endBinding : arrow.startBinding;\r\n const otherBindableElement =\r\n otherBinding &&\r\n (elementsMap.get(otherBinding.elementId)! as ExcalidrawBindableElement);\r\n const bounds = getElementBounds(bindableElement, elementsMap);\r\n const otherBounds =\r\n otherBindableElement && getElementBounds(otherBindableElement, elementsMap);\r\n const isLargerThanOther =\r\n otherBindableElement &&\r\n compareElementArea(bindableElement, otherBindableElement) <\r\n // if both shapes the same size, pretend the other is larger\r\n (startOrEnd === \"endBinding\" ? 1 : 0);\r\n const isOverlapping = otherBounds && doBoundsIntersect(bounds, otherBounds);\r\n\r\n // GOAL: If the arrow becomes too short, we want to jump the arrow endpoints\r\n // to the exact focus points on the elements.\r\n // INTUITION: We're not interested in the exacts length of the arrow (which\r\n // will change if we change where we route it), we want to know the length of\r\n // the part which lies outside of both shapes and consider that as a trigger\r\n // to change where we point the arrow. Avoids jumping the arrow in and out\r\n // at every frame.\r\n let arrowTooShort = false;\r\n if (\r\n !isOverlapping &&\r\n !elbowed &&\r\n arrow.startBinding &&\r\n arrow.endBinding &&\r\n otherBindableElement &&\r\n arrow.points.length === 2\r\n ) {\r\n const startFocusPoint = getGlobalFixedPointForBindableElement(\r\n arrow.startBinding.fixedPoint,\r\n startOrEnd === \"startBinding\" ? bindableElement : otherBindableElement,\r\n elementsMap,\r\n );\r\n const endFocusPoint = getGlobalFixedPointForBindableElement(\r\n arrow.endBinding.fixedPoint,\r\n startOrEnd === \"endBinding\" ? bindableElement : otherBindableElement,\r\n elementsMap,\r\n );\r\n const segment = lineSegment(startFocusPoint, endFocusPoint);\r\n const startIntersection = intersectElementWithLineSegment(\r\n startOrEnd === \"endBinding\" ? bindableElement : otherBindableElement,\r\n elementsMap,\r\n segment,\r\n 0,\r\n true,\r\n );\r\n const endIntersection = intersectElementWithLineSegment(\r\n startOrEnd === \"startBinding\" ? bindableElement : otherBindableElement,\r\n elementsMap,\r\n segment,\r\n 0,\r\n true,\r\n );\r\n if (startIntersection.length > 0 && endIntersection.length > 0) {\r\n const len = pointDistance(startIntersection[0], endIntersection[0]);\r\n arrowTooShort = len < 40;\r\n }\r\n }\r\n\r\n const isNested = (arrowTooShort || isOverlapping) && isLargerThanOther;\r\n\r\n let _customIntersector = customIntersector;\r\n if (!elbowed && !_customIntersector) {\r\n const [x1, y1, x2, y2] = LinearElementEditor.getElementAbsoluteCoords(\r\n arrow,\r\n elementsMap,\r\n );\r\n const center = pointFrom<GlobalPoint>((x1 + x2) / 2, (y1 + y2) / 2);\r\n const edgePoint = isRectanguloidElement(bindableElement)\r\n ? avoidRectangularCorner(arrow, bindableElement, elementsMap, global)\r\n : global;\r\n const adjacentPoint = pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n arrow.x +\r\n arrow.points[pointIndex === 0 ? 1 : arrow.points.length - 2][0],\r\n arrow.y +\r\n arrow.points[pointIndex === 0 ? 1 : arrow.points.length - 2][1],\r\n ),\r\n center,\r\n arrow.angle as Radians,\r\n );\r\n const bindingGap = getBindingGap(bindableElement, arrow);\r\n const halfVector = vectorScale(\r\n vectorNormalize(vectorFromPoint(edgePoint, adjacentPoint)),\r\n pointDistance(edgePoint, adjacentPoint) +\r\n Math.max(bindableElement.width, bindableElement.height) +\r\n bindingGap * 2,\r\n );\r\n _customIntersector = lineSegment(\r\n pointFromVector(halfVector, adjacentPoint),\r\n pointFromVector(vectorScale(halfVector, -1), adjacentPoint),\r\n );\r\n }\r\n\r\n const maybeOutlineGlobal =\r\n binding.mode === \"orbit\" && bindableElement\r\n ? isNested\r\n ? global\r\n : bindPointToSnapToElementOutline(\r\n {\r\n ...arrow,\r\n points: [\r\n pointIndex === 0\r\n ? LinearElementEditor.createPointAt(\r\n arrow,\r\n elementsMap,\r\n global[0],\r\n global[1],\r\n null,\r\n )\r\n : arrow.points[0],\r\n ...arrow.points.slice(1, -1),\r\n pointIndex === arrow.points.length - 1\r\n ? LinearElementEditor.createPointAt(\r\n arrow,\r\n elementsMap,\r\n global[0],\r\n global[1],\r\n null,\r\n )\r\n : arrow.points[arrow.points.length - 1],\r\n ],\r\n },\r\n bindableElement,\r\n pointIndex === 0 ? \"start\" : \"end\",\r\n elementsMap,\r\n _customIntersector,\r\n )\r\n : global;\r\n\r\n return LinearElementEditor.createPointAt(\r\n arrow,\r\n elementsMap,\r\n maybeOutlineGlobal[0],\r\n maybeOutlineGlobal[1],\r\n null,\r\n );\r\n};\r\n\r\nexport const calculateFixedPointForElbowArrowBinding = (\r\n linearElement: NonDeleted<ExcalidrawElbowArrowElement>,\r\n hoveredElement: ExcalidrawBindableElement,\r\n startOrEnd: \"start\" | \"end\",\r\n elementsMap: ElementsMap,\r\n): { fixedPoint: FixedPoint } => {\r\n const bounds = [\r\n hoveredElement.x,\r\n hoveredElement.y,\r\n hoveredElement.x + hoveredElement.width,\r\n hoveredElement.y + hoveredElement.height,\r\n ] as Bounds;\r\n const snappedPoint = bindPointToSnapToElementOutline(\r\n linearElement,\r\n hoveredElement,\r\n startOrEnd,\r\n elementsMap,\r\n );\r\n const globalMidPoint = pointFrom(\r\n bounds[0] + (bounds[2] - bounds[0]) / 2,\r\n bounds[1] + (bounds[3] - bounds[1]) / 2,\r\n );\r\n const nonRotatedSnappedGlobalPoint = pointRotateRads(\r\n snappedPoint,\r\n globalMidPoint,\r\n -hoveredElement.angle as Radians,\r\n );\r\n\r\n return {\r\n fixedPoint: normalizeFixedPoint([\r\n (nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) /\r\n hoveredElement.width,\r\n (nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) /\r\n hoveredElement.height,\r\n ]),\r\n };\r\n};\r\n\r\nexport const calculateFixedPointForNonElbowArrowBinding = (\r\n linearElement: NonDeleted<ExcalidrawArrowElement>,\r\n hoveredElement: ExcalidrawBindableElement,\r\n startOrEnd: \"start\" | \"end\",\r\n elementsMap: ElementsMap,\r\n focusPoint?: GlobalPoint,\r\n): { fixedPoint: FixedPoint } => {\r\n const edgePoint = focusPoint\r\n ? focusPoint\r\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n linearElement,\r\n startOrEnd === \"start\" ? 0 : -1,\r\n elementsMap,\r\n );\r\n\r\n // Convert the global point to element-local coordinates\r\n const elementCenter = pointFrom(\r\n hoveredElement.x + hoveredElement.width / 2,\r\n hoveredElement.y + hoveredElement.height / 2,\r\n );\r\n\r\n // Rotate the point to account for element rotation\r\n const nonRotatedPoint = pointRotateRads(\r\n edgePoint,\r\n elementCenter,\r\n -hoveredElement.angle as Radians,\r\n );\r\n\r\n // Calculate the ratio relative to the element's bounds\r\n const fixedPointX =\r\n (nonRotatedPoint[0] - hoveredElement.x) / hoveredElement.width;\r\n const fixedPointY =\r\n (nonRotatedPoint[1] - hoveredElement.y) / hoveredElement.height;\r\n\r\n return {\r\n fixedPoint: normalizeFixedPoint([fixedPointX, fixedPointY]),\r\n };\r\n};\r\n\r\nexport const fixDuplicatedBindingsAfterDuplication = (\r\n duplicatedElements: ExcalidrawElement[],\r\n origIdToDuplicateId: Map<ExcalidrawElement[\"id\"], ExcalidrawElement[\"id\"]>,\r\n duplicateElementsMap: NonDeletedSceneElementsMap,\r\n) => {\r\n for (const duplicateElement of duplicatedElements) {\r\n if (\"boundElements\" in duplicateElement && duplicateElement.boundElements) {\r\n Object.assign(duplicateElement, {\r\n boundElements: duplicateElement.boundElements.reduce(\r\n (\r\n acc: Mutable<NonNullable<ExcalidrawElement[\"boundElements\"]>>,\r\n binding,\r\n ) => {\r\n const newBindingId = origIdToDuplicateId.get(binding.id);\r\n if (newBindingId) {\r\n acc.push({ ...binding, id: newBindingId });\r\n }\r\n return acc;\r\n },\r\n [],\r\n ),\r\n });\r\n }\r\n\r\n if (\"containerId\" in duplicateElement && duplicateElement.containerId) {\r\n Object.assign(duplicateElement, {\r\n containerId:\r\n origIdToDuplicateId.get(duplicateElement.containerId) ?? null,\r\n });\r\n }\r\n\r\n if (\"endBinding\" in duplicateElement && duplicateElement.endBinding) {\r\n const newEndBindingId = origIdToDuplicateId.get(\r\n duplicateElement.endBinding.elementId,\r\n );\r\n Object.assign(duplicateElement, {\r\n endBinding: newEndBindingId\r\n ? {\r\n ...duplicateElement.endBinding,\r\n elementId: newEndBindingId,\r\n }\r\n : null,\r\n });\r\n }\r\n if (\"startBinding\" in duplicateElement && duplicateElement.startBinding) {\r\n const newEndBindingId = origIdToDuplicateId.get(\r\n duplicateElement.startBinding.elementId,\r\n );\r\n Object.assign(duplicateElement, {\r\n startBinding: newEndBindingId\r\n ? {\r\n ...duplicateElement.startBinding,\r\n elementId: newEndBindingId,\r\n }\r\n : null,\r\n });\r\n }\r\n\r\n if (isElbowArrow(duplicateElement)) {\r\n Object.assign(\r\n duplicateElement,\r\n updateElbowArrowPoints(duplicateElement, duplicateElementsMap, {\r\n points: [\r\n duplicateElement.points[0],\r\n duplicateElement.points[duplicateElement.points.length - 1],\r\n ],\r\n }),\r\n );\r\n }\r\n }\r\n};\r\n\r\nexport const fixBindingsAfterDeletion = (\r\n sceneElements: readonly ExcalidrawElement[],\r\n deletedElements: readonly ExcalidrawElement[],\r\n): void => {\r\n const elements = arrayToMap(sceneElements);\r\n\r\n for (const element of deletedElements) {\r\n BoundElement.unbindAffected(elements, element, (element, updates) =>\r\n mutateElement(element, elements, updates),\r\n );\r\n BindableElement.unbindAffected(elements, element, (element, updates) =>\r\n mutateElement(element, elements, updates),\r\n );\r\n }\r\n};\r\n\r\nconst newBoundElements = (\r\n boundElements: ExcalidrawElement[\"boundElements\"],\r\n idsToRemove: Set<ExcalidrawElement[\"id\"]>,\r\n elementsToAdd: Array<ExcalidrawElement> = [],\r\n) => {\r\n if (!boundElements) {\r\n return null;\r\n }\r\n\r\n const nextBoundElements = boundElements.filter(\r\n (boundElement) => !idsToRemove.has(boundElement.id),\r\n );\r\n\r\n nextBoundElements.push(\r\n ...elementsToAdd.map(\r\n (x) =>\r\n ({ id: x.id, type: x.type } as\r\n | ExcalidrawArrowElement\r\n | ExcalidrawTextElement),\r\n ),\r\n );\r\n\r\n return nextBoundElements;\r\n};\r\n\r\nexport const bindingProperties: Set<BindableProp | BindingProp> = new Set([\r\n \"boundElements\",\r\n \"frameId\",\r\n \"containerId\",\r\n \"startBinding\",\r\n \"endBinding\",\r\n]);\r\n\r\nexport type BindableProp = \"boundElements\";\r\n\r\nexport type BindingProp =\r\n | \"frameId\"\r\n | \"containerId\"\r\n | \"startBinding\"\r\n | \"endBinding\";\r\n\r\ntype BoundElementsVisitingFunc = (\r\n boundElement: ExcalidrawElement | undefined,\r\n bindingProp: BindableProp,\r\n bindingId: string,\r\n) => void;\r\n\r\ntype BindableElementVisitingFunc<T> = (\r\n bindableElement: ExcalidrawElement | undefined,\r\n bindingProp: BindingProp,\r\n bindingId: string,\r\n) => T;\r\n\r\n/**\r\n * Tries to visit each bound element (does not have to be found).\r\n */\r\nconst boundElementsVisitor = (\r\n elements: ElementsMap,\r\n element: ExcalidrawElement,\r\n visit: BoundElementsVisitingFunc,\r\n) => {\r\n if (isBindableElement(element)) {\r\n // create new instance so that possible mutations won't play a role in visiting order\r\n const boundElements = element.boundElements?.slice() ?? [];\r\n\r\n // last added text should be the one we keep (~previous are duplicates)\r\n boundElements.forEach(({ id }) => {\r\n visit(elements.get(id), \"boundElements\", id);\r\n });\r\n }\r\n};\r\n\r\n/**\r\n * Tries to visit each bindable element (does not have to be found).\r\n */\r\nconst bindableElementsVisitor = <T>(\r\n elements: ElementsMap,\r\n element: ExcalidrawElement,\r\n visit: BindableElementVisitingFunc<T>,\r\n): T[] => {\r\n const result: T[] = [];\r\n\r\n if (element.frameId) {\r\n const id = element.frameId;\r\n result.push(visit(elements.get(id), \"frameId\", id));\r\n }\r\n\r\n if (isBoundToContainer(element)) {\r\n const id = element.containerId;\r\n result.push(visit(elements.get(id), \"containerId\", id));\r\n }\r\n\r\n if (isArrowElement(element)) {\r\n if (element.startBinding) {\r\n const id = element.startBinding.elementId;\r\n result.push(visit(elements.get(id), \"startBinding\", id));\r\n }\r\n\r\n if (element.endBinding) {\r\n const id = element.endBinding.elementId;\r\n result.push(visit(elements.get(id), \"endBinding\", id));\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Bound element containing bindings to `frameId`, `containerId`, `startBinding` or `endBinding`.\r\n */\r\nexport class BoundElement {\r\n /**\r\n * Unbind the affected non deleted bindable elements (removing element from `boundElements`).\r\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\r\n * - prepares updates to unbind each bindable element's `boundElements` from the current element\r\n */\r\n public static unbindAffected(\r\n elements: ElementsMap,\r\n boundElement: ExcalidrawElement | undefined,\r\n updateElementWith: (\r\n affected: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => void,\r\n ) {\r\n if (!boundElement) {\r\n return;\r\n }\r\n\r\n bindableElementsVisitor(elements, boundElement, (bindableElement) => {\r\n // bindable element is deleted, this is fine\r\n if (!bindableElement || bindableElement.isDeleted) {\r\n return;\r\n }\r\n\r\n boundElementsVisitor(\r\n elements,\r\n bindableElement,\r\n (_, __, boundElementId) => {\r\n if (boundElementId === boundElement.id) {\r\n updateElementWith(bindableElement, {\r\n boundElements: newBoundElements(\r\n bindableElement.boundElements,\r\n new Set([boundElementId]),\r\n ),\r\n });\r\n }\r\n },\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Rebind the next affected non deleted bindable elements (adding element to `boundElements`).\r\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\r\n * - prepares updates to rebind each bindable element's `boundElements` to the current element\r\n *\r\n * NOTE: rebind expects that affected elements were previously unbound with `BoundElement.unbindAffected`\r\n */\r\n public static rebindAffected = (\r\n elements: ElementsMap,\r\n boundElement: ExcalidrawElement | undefined,\r\n updateElementWith: (\r\n affected: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => void,\r\n ) => {\r\n // don't try to rebind element that is deleted\r\n if (!boundElement || boundElement.isDeleted) {\r\n return;\r\n }\r\n\r\n bindableElementsVisitor(\r\n elements,\r\n boundElement,\r\n (bindableElement, bindingProp) => {\r\n // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\r\n if (!bindableElement || bindableElement.isDeleted) {\r\n updateElementWith(boundElement, { [bindingProp]: null });\r\n return;\r\n }\r\n\r\n // frame bindings are unidirectional, there is nothing to rebind\r\n if (bindingProp === \"frameId\") {\r\n return;\r\n }\r\n\r\n if (\r\n bindableElement.boundElements?.find((x) => x.id === boundElement.id)\r\n ) {\r\n return;\r\n }\r\n\r\n if (isArrowElement(boundElement)) {\r\n // rebind if not found!\r\n updateElementWith(bindableElement, {\r\n boundElements: newBoundElements(\r\n bindableElement.boundElements,\r\n new Set(),\r\n new Array(boundElement),\r\n ),\r\n });\r\n }\r\n\r\n if (isTextElement(boundElement)) {\r\n if (!bindableElement.boundElements?.find((x) => x.type === \"text\")) {\r\n // rebind only if there is no other text bound already\r\n updateElementWith(bindableElement, {\r\n boundElements: newBoundElements(\r\n bindableElement.boundElements,\r\n new Set(),\r\n new Array(boundElement),\r\n ),\r\n });\r\n } else {\r\n // unbind otherwise\r\n updateElementWith(boundElement, { [bindingProp]: null });\r\n }\r\n }\r\n },\r\n );\r\n };\r\n}\r\n\r\n/**\r\n * Bindable element containing bindings to `boundElements`.\r\n */\r\nexport class BindableElement {\r\n /**\r\n * Unbind the affected non deleted bound elements (resetting `containerId`, `startBinding`, `endBinding` to `null`).\r\n * - iterates through non deleted `boundElements` of the current element\r\n * - prepares updates to unbind each bound element from the current element\r\n */\r\n public static unbindAffected(\r\n elements: ElementsMap,\r\n bindableElement: ExcalidrawElement | undefined,\r\n updateElementWith: (\r\n affected: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => void,\r\n ) {\r\n if (!bindableElement) {\r\n return;\r\n }\r\n\r\n boundElementsVisitor(elements, bindableElement, (boundElement) => {\r\n // bound element is deleted, this is fine\r\n if (!boundElement || boundElement.isDeleted) {\r\n return;\r\n }\r\n\r\n bindableElementsVisitor(\r\n elements,\r\n boundElement,\r\n (_, bindingProp, bindableElementId) => {\r\n // making sure there is an element to be unbound\r\n if (bindableElementId === bindableElement.id) {\r\n updateElementWith(boundElement, { [bindingProp]: null });\r\n }\r\n },\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Rebind the affected non deleted bound elements (for now setting only `containerId`, as we cannot rebind arrows atm).\r\n * - iterates through non deleted `boundElements` of the current element\r\n * - prepares updates to rebind each bound element to the current element or unbind it from `boundElements` in case of conflicts\r\n *\r\n * NOTE: rebind expects that affected elements were previously unbound with `BindaleElement.unbindAffected`\r\n */\r\n public static rebindAffected = (\r\n elements: ElementsMap,\r\n bindableElement: ExcalidrawElement | undefined,\r\n updateElementWith: (\r\n affected: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => void,\r\n ) => {\r\n // don't try to rebind element that is deleted (i.e. updated as deleted)\r\n if (!bindableElement || bindableElement.isDeleted) {\r\n return;\r\n }\r\n\r\n boundElementsVisitor(\r\n elements,\r\n bindableElement,\r\n (boundElement, _, boundElementId) => {\r\n // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\r\n if (!boundElement || boundElement.isDeleted) {\r\n updateElementWith(bindableElement, {\r\n boundElements: newBoundElements(\r\n bindableElement.boundElements,\r\n new Set([boundElementId]),\r\n ),\r\n });\r\n return;\r\n }\r\n\r\n if (isTextElement(boundElement)) {\r\n const boundElements = bindableElement.boundElements?.slice() ?? [];\r\n // check if this is the last element in the array, if not, there is an previously bound text which should be unbound\r\n if (\r\n boundElements.reverse().find((x) => x.type === \"text\")?.id ===\r\n boundElement.id\r\n ) {\r\n if (boundElement.containerId !== bindableElement.id) {\r\n // rebind if not bound already!\r\n updateElementWith(boundElement, {\r\n containerId: bindableElement.id,\r\n } as ElementUpdate<ExcalidrawTextElement>);\r\n }\r\n } else {\r\n if (boundElement.containerId !== null) {\r\n // unbind if not unbound already\r\n updateElementWith(boundElement, {\r\n containerId: null,\r\n } as ElementUpdate<ExcalidrawTextElement>);\r\n }\r\n\r\n // unbind from boundElements as the element got bound to some other element in the meantime\r\n updateElementWith(bindableElement, {\r\n boundElements: newBoundElements(\r\n bindableElement.boundElements,\r\n new Set([boundElement.id]),\r\n ),\r\n });\r\n }\r\n }\r\n },\r\n );\r\n };\r\n}\r\n\r\nexport const getGlobalFixedPointForBindableElement = (\r\n fixedPointRatio: FixedPoint,\r\n element: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n): GlobalPoint => {\r\n const [fixedX, fixedY] = normalizeFixedPoint(fixedPointRatio);\r\n\r\n return pointRotateRads(\r\n pointFrom(\r\n element.x + element.width * fixedX,\r\n element.y + element.height * fixedY,\r\n ),\r\n elementCenterPoint(element, elementsMap),\r\n element.angle,\r\n );\r\n};\r\n\r\nexport const getGlobalFixedPoints = (\r\n arrow: ExcalidrawArrowElement,\r\n elementsMap: ElementsMap,\r\n): [GlobalPoint, GlobalPoint] => {\r\n const startElement =\r\n arrow.startBinding &&\r\n (elementsMap.get(arrow.startBinding.elementId) as\r\n | ExcalidrawBindableElement\r\n | undefined);\r\n const endElement =\r\n arrow.endBinding &&\r\n (elementsMap.get(arrow.endBinding.elementId) as\r\n | ExcalidrawBindableElement\r\n | undefined);\r\n const startPoint =\r\n startElement && arrow.startBinding\r\n ? getGlobalFixedPointForBindableElement(\r\n arrow.startBinding.fixedPoint,\r\n startElement as ExcalidrawBindableElement,\r\n elementsMap,\r\n )\r\n : pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[0][0],\r\n arrow.y + arrow.points[0][1],\r\n );\r\n const endPoint =\r\n endElement && arrow.endBinding\r\n ? getGlobalFixedPointForBindableElement(\r\n arrow.endBinding.fixedPoint,\r\n endElement as ExcalidrawBindableElement,\r\n elementsMap,\r\n )\r\n : pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[arrow.points.length - 1][0],\r\n arrow.y + arrow.points[arrow.points.length - 1][1],\r\n );\r\n\r\n return [startPoint, endPoint];\r\n};\r\n\r\nexport const getArrowLocalFixedPoints = (\r\n arrow: ExcalidrawElbowArrowElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n const [startPoint, endPoint] = getGlobalFixedPoints(arrow, elementsMap);\r\n\r\n return [\r\n LinearElementEditor.pointFromAbsoluteCoords(arrow, startPoint, elementsMap),\r\n LinearElementEditor.pointFromAbsoluteCoords(arrow, endPoint, elementsMap),\r\n ];\r\n};\r\n\r\nexport const normalizeFixedPoint = <T extends FixedPoint | null>(\r\n fixedPoint: T,\r\n): T extends null ? null : FixedPoint => {\r\n // Do not allow a precise 0.5 for fixed point ratio\r\n // to avoid jumping arrow heading due to floating point imprecision\r\n if (\r\n fixedPoint &&\r\n (Math.abs(fixedPoint[0] - 0.5) < 0.0001 ||\r\n Math.abs(fixedPoint[1] - 0.5) < 0.0001)\r\n ) {\r\n return fixedPoint.map((ratio) =>\r\n Math.abs(ratio - 0.5) < 0.0001 ? 0.5001 : ratio,\r\n ) as T extends null ? null : FixedPoint;\r\n }\r\n return fixedPoint as any as T extends null ? null : FixedPoint;\r\n};\r\n\r\ntype Side =\r\n | \"top\"\r\n | \"top-right\"\r\n | \"right\"\r\n | \"bottom-right\"\r\n | \"bottom\"\r\n | \"bottom-left\"\r\n | \"left\"\r\n | \"top-left\";\r\ntype ShapeType = \"rectangle\" | \"ellipse\" | \"diamond\";\r\nconst getShapeType = (element: ExcalidrawBindableElement): ShapeType => {\r\n if (element.type === \"ellipse\" || element.type === \"diamond\") {\r\n return element.type;\r\n }\r\n return \"rectangle\";\r\n};\r\n\r\ninterface SectorConfig {\r\n // center angle of the sector in degrees\r\n centerAngle: number;\r\n // width of the sector in degrees\r\n sectorWidth: number;\r\n side: Side;\r\n}\r\n\r\n// Define sector configurations for different shape types\r\nconst SHAPE_CONFIGS: Record<ShapeType, SectorConfig[]> = {\r\n // rectangle: 15\u00B0 corners, 75\u00B0 edges\r\n rectangle: [\r\n { centerAngle: 0, sectorWidth: 75, side: \"right\" },\r\n { centerAngle: 45, sectorWidth: 15, side: \"bottom-right\" },\r\n { centerAngle: 90, sectorWidth: 75, side: \"bottom\" },\r\n { centerAngle: 135, sectorWidth: 15, side: \"bottom-left\" },\r\n { centerAngle: 180, sectorWidth: 75, side: \"left\" },\r\n { centerAngle: 225, sectorWidth: 15, side: \"top-left\" },\r\n { centerAngle: 270, sectorWidth: 75, side: \"top\" },\r\n { centerAngle: 315, sectorWidth: 15, side: \"top-right\" },\r\n ],\r\n\r\n // diamond: 15\u00B0 vertices, 75\u00B0 edges\r\n diamond: [\r\n { centerAngle: 0, sectorWidth: 15, side: \"right\" },\r\n { centerAngle: 45, sectorWidth: 75, side: \"bottom-right\" },\r\n { centerAngle: 90, sectorWidth: 15, side: \"bottom\" },\r\n { centerAngle: 135, sectorWidth: 75, side: \"bottom-left\" },\r\n { centerAngle: 180, sectorWidth: 15, side: \"left\" },\r\n { centerAngle: 225, sectorWidth: 75, side: \"top-left\" },\r\n { centerAngle: 270, sectorWidth: 15, side: \"top\" },\r\n { centerAngle: 315, sectorWidth: 75, side: \"top-right\" },\r\n ],\r\n\r\n // ellipse: 15\u00B0 cardinal points, 75\u00B0 diagonals\r\n ellipse: [\r\n { centerAngle: 0, sectorWidth: 15, side: \"right\" },\r\n { centerAngle: 45, sectorWidth: 75, side: \"bottom-right\" },\r\n { centerAngle: 90, sectorWidth: 15, side: \"bottom\" },\r\n { centerAngle: 135, sectorWidth: 75, side: \"bottom-left\" },\r\n { centerAngle: 180, sectorWidth: 15, side: \"left\" },\r\n { centerAngle: 225, sectorWidth: 75, side: \"top-left\" },\r\n { centerAngle: 270, sectorWidth: 15, side: \"top\" },\r\n { centerAngle: 315, sectorWidth: 75, side: \"top-right\" },\r\n ],\r\n};\r\n\r\nconst getSectorBoundaries = (\r\n config: SectorConfig[],\r\n): Array<{ start: number; end: number; side: Side }> => {\r\n return config.map((sector, index) => {\r\n const halfWidth = sector.sectorWidth / 2;\r\n let start = sector.centerAngle - halfWidth;\r\n let end = sector.centerAngle + halfWidth;\r\n\r\n // normalize angles to [0, 360) range\r\n start = ((start % 360) + 360) % 360;\r\n end = ((end % 360) + 360) % 360;\r\n\r\n return { start, end, side: sector.side };\r\n });\r\n};\r\n\r\n// determine which side a point falls into using adaptive sectors\r\nconst getShapeSideAdaptive = (\r\n fixedPoint: FixedPoint,\r\n shapeType: ShapeType,\r\n): Side => {\r\n const [x, y] = fixedPoint;\r\n\r\n // convert to centered coordinates\r\n const centerX = x - 0.5;\r\n const centerY = y - 0.5;\r\n\r\n // calculate angle\r\n let angle = Math.atan2(centerY, centerX);\r\n if (angle < 0) {\r\n angle += 2 * Math.PI;\r\n }\r\n const degrees = (angle * 180) / Math.PI;\r\n\r\n // get sector configuration for this shape type\r\n const config = SHAPE_CONFIGS[shapeType];\r\n const boundaries = getSectorBoundaries(config);\r\n\r\n // find which sector the angle falls into\r\n for (const boundary of boundaries) {\r\n if (boundary.start <= boundary.end) {\r\n // Normal case: sector doesn't cross 0\u00B0\r\n if (degrees >= boundary.start && degrees <= boundary.end) {\r\n return boundary.side;\r\n }\r\n } else if (degrees >= boundary.start || degrees <= boundary.end) {\r\n return boundary.side;\r\n }\r\n }\r\n\r\n // fallback - find nearest sector center\r\n let minDiff = Infinity;\r\n let nearestSide = config[0].side;\r\n\r\n for (const sector of config) {\r\n let diff = Math.abs(degrees - sector.centerAngle);\r\n // handle wraparound\r\n if (diff > 180) {\r\n diff = 360 - diff;\r\n }\r\n\r\n if (diff < minDiff) {\r\n minDiff = diff;\r\n nearestSide = sector.side;\r\n }\r\n }\r\n\r\n return nearestSide;\r\n};\r\n\r\nexport const getBindingSideMidPoint = (\r\n binding: FixedPointBinding,\r\n elementsMap: ElementsMap,\r\n) => {\r\n const bindableElement = elementsMap.get(binding.elementId);\r\n if (\r\n !bindableElement ||\r\n bindableElement.isDeleted ||\r\n !isBindableElement(bindableElement)\r\n ) {\r\n return null;\r\n }\r\n\r\n const center = elementCenterPoint(bindableElement, elementsMap);\r\n const shapeType = getShapeType(bindableElement);\r\n const side = getShapeSideAdaptive(\r\n normalizeFixedPoint(binding.fixedPoint),\r\n shapeType,\r\n );\r\n\r\n // small offset to avoid precision issues in elbow\r\n const OFFSET = 0.01;\r\n\r\n if (bindableElement.type === \"diamond\") {\r\n const [sides, corners] = deconstructDiamondElement(bindableElement);\r\n const [bottomRight, bottomLeft, topLeft, topRight] = sides;\r\n\r\n let x: number;\r\n let y: number;\r\n switch (side) {\r\n case \"left\": {\r\n // left vertex - use the center of the left corner curve\r\n if (corners.length >= 3) {\r\n const leftCorner = corners[2];\r\n const midPoint = leftCorner[1];\r\n x = midPoint[0] - OFFSET;\r\n y = midPoint[1];\r\n } else {\r\n // fallback for non-rounded diamond\r\n const midPoint = getMidPoint(bottomLeft[1], topLeft[0]);\r\n x = midPoint[0] - OFFSET;\r\n y = midPoint[1];\r\n }\r\n break;\r\n }\r\n case \"right\": {\r\n if (corners.length >= 1) {\r\n const rightCorner = corners[0];\r\n const midPoint = rightCorner[1];\r\n x = midPoint[0] + OFFSET;\r\n y = midPoint[1];\r\n } else {\r\n const midPoint = getMidPoint(topRight[1], bottomRight[0]);\r\n x = midPoint[0] + OFFSET;\r\n y = midPoint[1];\r\n }\r\n break;\r\n }\r\n case \"top\": {\r\n if (corners.length >= 4) {\r\n const topCorner = corners[3];\r\n const midPoint = topCorner[1];\r\n x = midPoint[0];\r\n y = midPoint[1] - OFFSET;\r\n } else {\r\n const midPoint = getMidPoint(topLeft[1], topRight[0]);\r\n x = midPoint[0];\r\n y = midPoint[1] - OFFSET;\r\n }\r\n break;\r\n }\r\n case \"bottom\": {\r\n if (corners.length >= 2) {\r\n const bottomCorner = corners[1];\r\n const midPoint = bottomCorner[1];\r\n x = midPoint[0];\r\n y = midPoint[1] + OFFSET;\r\n } else {\r\n const midPoint = getMidPoint(bottomRight[1], bottomLeft[0]);\r\n x = midPoint[0];\r\n y = midPoint[1] + OFFSET;\r\n }\r\n break;\r\n }\r\n case \"top-right\": {\r\n const midPoint = getMidPoint(topRight[0], topRight[1]);\r\n\r\n x = midPoint[0] + OFFSET * 0.707;\r\n y = midPoint[1] - OFFSET * 0.707;\r\n break;\r\n }\r\n case \"bottom-right\": {\r\n const midPoint = getMidPoint(bottomRight[0], bottomRight[1]);\r\n\r\n x = midPoint[0] + OFFSET * 0.707;\r\n y = midPoint[1] + OFFSET * 0.707;\r\n break;\r\n }\r\n case \"bottom-left\": {\r\n const midPoint = getMidPoint(bottomLeft[0], bottomLeft[1]);\r\n x = midPoint[0] - OFFSET * 0.707;\r\n y = midPoint[1] + OFFSET * 0.707;\r\n break;\r\n }\r\n case \"top-left\": {\r\n const midPoint = getMidPoint(topLeft[0], topLeft[1]);\r\n x = midPoint[0] - OFFSET * 0.707;\r\n y = midPoint[1] - OFFSET * 0.707;\r\n break;\r\n }\r\n default: {\r\n return null;\r\n }\r\n }\r\n\r\n return pointRotateRads(pointFrom(x, y), center, bindableElement.angle);\r\n }\r\n\r\n if (bindableElement.type === \"ellipse\") {\r\n const ellipseCenterX = bindableElement.x + bindableElement.width / 2;\r\n const ellipseCenterY = bindableElement.y + bindableElement.height / 2;\r\n const radiusX = bindableElement.width / 2;\r\n const radiusY = bindableElement.height / 2;\r\n\r\n let x: number;\r\n let y: number;\r\n\r\n switch (side) {\r\n case \"top\": {\r\n x = ellipseCenterX;\r\n y = ellipseCenterY - radiusY - OFFSET;\r\n break;\r\n }\r\n case \"right\": {\r\n x = ellipseCenterX + radiusX + OFFSET;\r\n y = ellipseCenterY;\r\n break;\r\n }\r\n case \"bottom\": {\r\n x = ellipseCenterX;\r\n y = ellipseCenterY + radiusY + OFFSET;\r\n break;\r\n }\r\n case \"left\": {\r\n x = ellipseCenterX - radiusX - OFFSET;\r\n y = ellipseCenterY;\r\n break;\r\n }\r\n case \"top-right\": {\r\n const angle = -Math.PI / 4;\r\n const ellipseX = radiusX * Math.cos(angle);\r\n const ellipseY = radiusY * Math.sin(angle);\r\n x = ellipseCenterX + ellipseX + OFFSET * 0.707;\r\n y = ellipseCenterY + ellipseY - OFFSET * 0.707;\r\n break;\r\n }\r\n case \"bottom-right\": {\r\n const angle = Math.PI / 4;\r\n const ellipseX = radiusX * Math.cos(angle);\r\n const ellipseY = radiusY * Math.sin(angle);\r\n x = ellipseCenterX + ellipseX + OFFSET * 0.707;\r\n y = ellipseCenterY + ellipseY + OFFSET * 0.707;\r\n break;\r\n }\r\n case \"bottom-left\": {\r\n const angle = (3 * Math.PI) / 4;\r\n const ellipseX = radiusX * Math.cos(angle);\r\n const ellipseY = radiusY * Math.sin(angle);\r\n x = ellipseCenterX + ellipseX - OFFSET * 0.707;\r\n y = ellipseCenterY + ellipseY + OFFSET * 0.707;\r\n break;\r\n }\r\n case \"top-left\": {\r\n const angle = (-3 * Math.PI) / 4;\r\n const ellipseX = radiusX * Math.cos(angle);\r\n const ellipseY = radiusY * Math.sin(angle);\r\n x = ellipseCenterX + ellipseX - OFFSET * 0.707;\r\n y = ellipseCenterY + ellipseY - OFFSET * 0.707;\r\n break;\r\n }\r\n default: {\r\n return null;\r\n }\r\n }\r\n\r\n return pointRotateRads(pointFrom(x, y), center, bindableElement.angle);\r\n }\r\n\r\n if (isRectangularElement(bindableElement)) {\r\n const [sides, corners] = deconstructRectanguloidElement(\r\n bindableElement as ExcalidrawRectanguloidElement,\r\n );\r\n const [top, right, bottom, left] = sides;\r\n\r\n let x: number;\r\n let y: number;\r\n switch (side) {\r\n case \"top\": {\r\n const midPoint = getMidPoint(top[0], top[1]);\r\n x = midPoint[0];\r\n y = midPoint[1] - OFFSET;\r\n break;\r\n }\r\n case \"right\": {\r\n const midPoint = getMidPoint(right[0], right[1]);\r\n x = midPoint[0] + OFFSET;\r\n y = midPoint[1];\r\n break;\r\n }\r\n case \"bottom\": {\r\n const midPoint = getMidPoint(bottom[0], bottom[1]);\r\n x = midPoint[0];\r\n y = midPoint[1] + OFFSET;\r\n break;\r\n }\r\n case \"left\": {\r\n const midPoint = getMidPoint(left[0], left[1]);\r\n x = midPoint[0] - OFFSET;\r\n y = midPoint[1];\r\n break;\r\n }\r\n case \"top-left\": {\r\n if (corners.length >= 1) {\r\n const corner = corners[0];\r\n\r\n const p1 = corner[0];\r\n const p2 = corner[3];\r\n const midPoint = getMidPoint(p1, p2);\r\n\r\n x = midPoint[0] - OFFSET * 0.707;\r\n y = midPoint[1] - OFFSET * 0.707;\r\n } else {\r\n x = bindableElement.x - OFFSET;\r\n y = bindableElement.y - OFFSET;\r\n }\r\n break;\r\n }\r\n case \"top-right\": {\r\n if (corners.length >= 2) {\r\n const corner = corners[1];\r\n const p1 = corner[0];\r\n const p2 = corner[3];\r\n const midPoint = getMidPoint(p1, p2);\r\n\r\n x = midPoint[0] + OFFSET * 0.707;\r\n y = midPoint[1] - OFFSET * 0.707;\r\n } else {\r\n x = bindableElement.x + bindableElement.width + OFFSET;\r\n y = bindableElement.y - OFFSET;\r\n }\r\n break;\r\n }\r\n case \"bottom-right\": {\r\n if (corners.length >= 3) {\r\n const corner = corners[2];\r\n const p1 = corner[0];\r\n const p2 = corner[3];\r\n const midPoint = getMidPoint(p1, p2);\r\n\r\n x = midPoint[0] + OFFSET * 0.707;\r\n y = midPoint[1] + OFFSET * 0.707;\r\n } else {\r\n x = bindableElement.x + bindableElement.width + OFFSET;\r\n y = bindableElement.y + bindableElement.height + OFFSET;\r\n }\r\n break;\r\n }\r\n case \"bottom-left\": {\r\n if (corners.length >= 4) {\r\n const corner = corners[3];\r\n const p1 = corner[0];\r\n const p2 = corner[3];\r\n const midPoint = getMidPoint(p1, p2);\r\n\r\n x = midPoint[0] - OFFSET * 0.707;\r\n y = midPoint[1] + OFFSET * 0.707;\r\n } else {\r\n x = bindableElement.x - OFFSET;\r\n y = bindableElement.y + bindableElement.height + OFFSET;\r\n }\r\n break;\r\n }\r\n default: {\r\n return null;\r\n }\r\n }\r\n\r\n return pointRotateRads(pointFrom(x, y), center, bindableElement.angle);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst getMidPoint = (p1: GlobalPoint, p2: GlobalPoint): GlobalPoint => {\r\n return pointFrom((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2);\r\n};\r\n", "import { invariant, isTransparent, type Bounds } from \"@excalidraw-modify/common\";\r\nimport {\r\n curveIntersectLineSegment,\r\n isPointWithinBounds,\r\n lineSegment,\r\n lineSegmentIntersectionPoints,\r\n pointFrom,\r\n pointFromVector,\r\n pointRotateRads,\r\n pointsEqual,\r\n vectorFromPoint,\r\n vectorNormalize,\r\n vectorScale,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n ellipse,\r\n ellipseSegmentInterceptPoints,\r\n} from \"@excalidraw-modify/math/ellipse\";\r\n\r\nimport type {\r\n Curve,\r\n GlobalPoint,\r\n LineSegment,\r\n Radians,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type { FrameNameBounds } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { isPathALoop } from \"./utils\";\r\nimport {\r\n doBoundsIntersect,\r\n elementCenterPoint,\r\n getCenterForBounds,\r\n getCubicBezierCurveBound,\r\n getDiamondPoints,\r\n getElementBounds,\r\n pointInsideBounds,\r\n} from \"./bounds\";\r\nimport {\r\n hasBoundTextElement,\r\n isBindableElement,\r\n isFrameLikeElement,\r\n isFreeDrawElement,\r\n isIframeLikeElement,\r\n isImageElement,\r\n isLinearElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\nimport {\r\n deconstructDiamondElement,\r\n deconstructLinearOrFreeDrawElement,\r\n deconstructRectanguloidElement,\r\n} from \"./utils\";\r\n\r\nimport { getBoundTextElement } from \"./textElement\";\r\n\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\n\r\nimport { distanceToElement } from \"./distance\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawBindableElement,\r\n ExcalidrawDiamondElement,\r\n ExcalidrawElement,\r\n ExcalidrawEllipseElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawRectanguloidElement,\r\n NonDeleted,\r\n NonDeletedExcalidrawElement,\r\n NonDeletedSceneElementsMap,\r\n Ordered,\r\n} from \"./types\";\r\n\r\nexport const shouldTestInside = (element: ExcalidrawElement) => {\r\n if (element.type === \"arrow\") {\r\n return false;\r\n }\r\n\r\n const isDraggableFromInside =\r\n !isTransparent(element.backgroundColor) ||\r\n hasBoundTextElement(element) ||\r\n isIframeLikeElement(element) ||\r\n isTextElement(element);\r\n\r\n if (element.type === \"line\") {\r\n return isDraggableFromInside && isPathALoop(element.points);\r\n }\r\n\r\n if (element.type === \"freedraw\") {\r\n return isDraggableFromInside && isPathALoop(element.points);\r\n }\r\n\r\n return isDraggableFromInside || isImageElement(element);\r\n};\r\n\r\nexport type HitTestArgs = {\r\n point: GlobalPoint;\r\n element: ExcalidrawElement;\r\n threshold: number;\r\n elementsMap: ElementsMap;\r\n frameNameBound?: FrameNameBounds | null;\r\n overrideShouldTestInside?: boolean;\r\n};\r\n\r\nexport const hitElementItself = ({\r\n point,\r\n element,\r\n threshold,\r\n elementsMap,\r\n frameNameBound = null,\r\n overrideShouldTestInside = false,\r\n}: HitTestArgs) => {\r\n // Hit test against a frame's name\r\n const hitFrameName = frameNameBound\r\n ? isPointWithinBounds(\r\n pointFrom(frameNameBound.x - threshold, frameNameBound.y - threshold),\r\n point,\r\n pointFrom(\r\n frameNameBound.x + frameNameBound.width + threshold,\r\n frameNameBound.y + frameNameBound.height + threshold,\r\n ),\r\n )\r\n : false;\r\n\r\n // Hit test against the extended, rotated bounding box of the element first\r\n const bounds = getElementBounds(element, elementsMap, true);\r\n const hitBounds = isPointWithinBounds(\r\n pointFrom(bounds[0] - threshold, bounds[1] - threshold),\r\n pointRotateRads(\r\n point,\r\n getCenterForBounds(bounds),\r\n -element.angle as Radians,\r\n ),\r\n pointFrom(bounds[2] + threshold, bounds[3] + threshold),\r\n );\r\n\r\n // PERF: Bail out early if the point is not even in the\r\n // rotated bounding box or not hitting the frame name (saves 99%)\r\n if (!hitBounds && !hitFrameName) {\r\n return false;\r\n }\r\n\r\n // Do the precise (and relatively costly) hit test\r\n const hitElement = (\r\n overrideShouldTestInside ? true : shouldTestInside(element)\r\n )\r\n ? // Since `inShape` tests STRICTLY againt the insides of a shape\r\n // we would need `onShape` as well to include the \"borders\"\r\n isPointInElement(point, element, elementsMap) ||\r\n isPointOnElementOutline(point, element, elementsMap, threshold)\r\n : isPointOnElementOutline(point, element, elementsMap, threshold);\r\n\r\n return hitElement || hitFrameName;\r\n};\r\n\r\nexport const hitElementBoundingBox = (\r\n point: GlobalPoint,\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n tolerance = 0,\r\n) => {\r\n let [x1, y1, x2, y2] = getElementBounds(element, elementsMap);\r\n x1 -= tolerance;\r\n y1 -= tolerance;\r\n x2 += tolerance;\r\n y2 += tolerance;\r\n return isPointWithinBounds(pointFrom(x1, y1), point, pointFrom(x2, y2));\r\n};\r\n\r\nexport const hitElementBoundingBoxOnly = (\r\n hitArgs: HitTestArgs,\r\n elementsMap: ElementsMap,\r\n) =>\r\n !hitElementItself(hitArgs) &&\r\n // bound text is considered part of the element (even if it's outside the bounding box)\r\n !hitElementBoundText(hitArgs.point, hitArgs.element, elementsMap) &&\r\n hitElementBoundingBox(hitArgs.point, hitArgs.element, elementsMap);\r\n\r\nexport const hitElementBoundText = (\r\n point: GlobalPoint,\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n): boolean => {\r\n const boundTextElementCandidate = getBoundTextElement(element, elementsMap);\r\n\r\n if (!boundTextElementCandidate) {\r\n return false;\r\n }\r\n const boundTextElement = isLinearElement(element)\r\n ? {\r\n ...boundTextElementCandidate,\r\n // arrow's bound text accurate position is not stored in the element's property\r\n // but rather calculated and returned from the following static method\r\n ...LinearElementEditor.getBoundTextElementPosition(\r\n element,\r\n boundTextElementCandidate,\r\n elementsMap,\r\n ),\r\n }\r\n : boundTextElementCandidate;\r\n\r\n return isPointInElement(point, boundTextElement, elementsMap);\r\n};\r\n\r\nconst bindingBorderTest = (\r\n element: NonDeleted<ExcalidrawBindableElement>,\r\n [x, y]: Readonly<GlobalPoint>,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n tolerance: number = 0,\r\n): boolean => {\r\n const p = pointFrom<GlobalPoint>(x, y);\r\n const shouldTestInside =\r\n // disable fullshape snapping for frame elements so we\r\n // can bind to frame children\r\n !isFrameLikeElement(element);\r\n\r\n // PERF: Run a cheap test to see if the binding element\r\n // is even close to the element\r\n const t = Math.max(1, tolerance);\r\n const bounds = [x - t, y - t, x + t, y + t] as Bounds;\r\n const elementBounds = getElementBounds(element, elementsMap);\r\n if (!doBoundsIntersect(bounds, elementBounds)) {\r\n return false;\r\n }\r\n\r\n // If the element is inside a frame, we should clip the element\r\n if (element.frameId) {\r\n const enclosingFrame = elementsMap.get(element.frameId);\r\n if (enclosingFrame && isFrameLikeElement(enclosingFrame)) {\r\n const enclosingFrameBounds = getElementBounds(\r\n enclosingFrame,\r\n elementsMap,\r\n );\r\n if (!pointInsideBounds(p, enclosingFrameBounds)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n // Do the intersection test against the element since it's close enough\r\n const intersections = intersectElementWithLineSegment(\r\n element,\r\n elementsMap,\r\n lineSegment(elementCenterPoint(element, elementsMap), p),\r\n );\r\n const distance = distanceToElement(element, elementsMap, p);\r\n\r\n return shouldTestInside\r\n ? intersections.length === 0 || distance <= tolerance\r\n : intersections.length > 0 && distance <= t;\r\n};\r\n\r\nexport const getAllHoveredElementAtPoint = (\r\n point: Readonly<GlobalPoint>,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n elementsMap: NonDeletedSceneElementsMap,\r\n toleranceFn?: (element: ExcalidrawBindableElement) => number,\r\n): NonDeleted<ExcalidrawBindableElement>[] => {\r\n const candidateElements: NonDeleted<ExcalidrawBindableElement>[] = [];\r\n // We need to to hit testing from front (end of the array) to back (beginning of the array)\r\n // because array is ordered from lower z-index to highest and we want element z-index\r\n // with higher z-index\r\n for (let index = elements.length - 1; index >= 0; --index) {\r\n const element = elements[index];\r\n\r\n invariant(\r\n !element.isDeleted,\r\n \"Elements in the function parameter for getAllElementsAtPositionForBinding() should not contain deleted elements\",\r\n );\r\n\r\n if (\r\n isBindableElement(element, false) &&\r\n bindingBorderTest(element, point, elementsMap, toleranceFn?.(element))\r\n ) {\r\n candidateElements.push(element);\r\n\r\n if (!isTransparent(element.backgroundColor)) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return candidateElements;\r\n};\r\n\r\nexport const getHoveredElementForBinding = (\r\n point: Readonly<GlobalPoint>,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n elementsMap: NonDeletedSceneElementsMap,\r\n toleranceFn?: (element: ExcalidrawBindableElement) => number,\r\n): NonDeleted<ExcalidrawBindableElement> | null => {\r\n const candidateElements = getAllHoveredElementAtPoint(\r\n point,\r\n elements,\r\n elementsMap,\r\n toleranceFn,\r\n );\r\n\r\n if (!candidateElements || candidateElements.length === 0) {\r\n return null;\r\n }\r\n\r\n if (candidateElements.length === 1) {\r\n return candidateElements[0];\r\n }\r\n\r\n // Prefer smaller shapes\r\n return candidateElements\r\n .sort(\r\n (a, b) => b.width ** 2 + b.height ** 2 - (a.width ** 2 + a.height ** 2),\r\n )\r\n .pop() as NonDeleted<ExcalidrawBindableElement>;\r\n};\r\n\r\n/**\r\n * Intersect a line with an element for binding test\r\n *\r\n * @param element\r\n * @param line\r\n * @param offset\r\n * @returns\r\n */\r\nexport const intersectElementWithLineSegment = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n line: LineSegment<GlobalPoint>,\r\n offset: number = 0,\r\n onlyFirst = false,\r\n): GlobalPoint[] => {\r\n // First check if the line intersects the element's axis-aligned bounding box\r\n // as it is much faster than checking intersection against the element's shape\r\n const intersectorBounds = [\r\n Math.min(line[0][0] - offset, line[1][0] - offset),\r\n Math.min(line[0][1] - offset, line[1][1] - offset),\r\n Math.max(line[0][0] + offset, line[1][0] + offset),\r\n Math.max(line[0][1] + offset, line[1][1] + offset),\r\n ] as Bounds;\r\n const elementBounds = getElementBounds(element, elementsMap);\r\n\r\n if (!doBoundsIntersect(intersectorBounds, elementBounds)) {\r\n return [];\r\n }\r\n\r\n // Do the actual intersection test against the element's shape\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"image\":\r\n case \"text\":\r\n case \"iframe\":\r\n case \"embeddable\":\r\n case \"frame\":\r\n case \"selection\":\r\n case \"magicframe\":\r\n return intersectRectanguloidWithLineSegment(\r\n element,\r\n elementsMap,\r\n line,\r\n offset,\r\n onlyFirst,\r\n );\r\n case \"diamond\":\r\n return intersectDiamondWithLineSegment(\r\n element,\r\n elementsMap,\r\n line,\r\n offset,\r\n onlyFirst,\r\n );\r\n case \"ellipse\":\r\n return intersectEllipseWithLineSegment(\r\n element,\r\n elementsMap,\r\n line,\r\n offset,\r\n );\r\n case \"line\":\r\n case \"freedraw\":\r\n case \"arrow\":\r\n return intersectLinearOrFreeDrawWithLineSegment(element, line, onlyFirst);\r\n }\r\n};\r\n\r\nconst curveIntersections = (\r\n curves: Curve<GlobalPoint>[],\r\n segment: LineSegment<GlobalPoint>,\r\n intersections: GlobalPoint[],\r\n center: GlobalPoint,\r\n angle: Radians,\r\n onlyFirst = false,\r\n) => {\r\n for (const c of curves) {\r\n // Optimize by doing a cheap bounding box check first\r\n const b1 = getCubicBezierCurveBound(c[0], c[1], c[2], c[3]);\r\n const b2 = [\r\n Math.min(segment[0][0], segment[1][0]),\r\n Math.min(segment[0][1], segment[1][1]),\r\n Math.max(segment[0][0], segment[1][0]),\r\n Math.max(segment[0][1], segment[1][1]),\r\n ] as Bounds;\r\n\r\n if (!doBoundsIntersect(b1, b2)) {\r\n continue;\r\n }\r\n\r\n const hits = curveIntersectLineSegment(c, segment);\r\n\r\n if (hits.length > 0) {\r\n for (const j of hits) {\r\n intersections.push(pointRotateRads(j, center, angle));\r\n }\r\n\r\n if (onlyFirst) {\r\n return intersections;\r\n }\r\n }\r\n }\r\n\r\n return intersections;\r\n};\r\n\r\nconst lineIntersections = (\r\n lines: LineSegment<GlobalPoint>[],\r\n segment: LineSegment<GlobalPoint>,\r\n intersections: GlobalPoint[],\r\n center: GlobalPoint,\r\n angle: Radians,\r\n onlyFirst = false,\r\n) => {\r\n for (const l of lines) {\r\n const intersection = lineSegmentIntersectionPoints(l, segment);\r\n if (intersection) {\r\n intersections.push(pointRotateRads(intersection, center, angle));\r\n\r\n if (onlyFirst) {\r\n return intersections;\r\n }\r\n }\r\n }\r\n\r\n return intersections;\r\n};\r\n\r\nconst intersectLinearOrFreeDrawWithLineSegment = (\r\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\r\n segment: LineSegment<GlobalPoint>,\r\n onlyFirst = false,\r\n): GlobalPoint[] => {\r\n // NOTE: This is the only one which return the decomposed elements\r\n // rotated! This is due to taking advantage of roughjs definitions.\r\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\r\n const intersections: GlobalPoint[] = [];\r\n\r\n for (const l of lines) {\r\n const intersection = lineSegmentIntersectionPoints(l, segment);\r\n if (intersection) {\r\n intersections.push(intersection);\r\n\r\n if (onlyFirst) {\r\n return intersections;\r\n }\r\n }\r\n }\r\n\r\n for (const c of curves) {\r\n // Optimize by doing a cheap bounding box check first\r\n const b1 = getCubicBezierCurveBound(c[0], c[1], c[2], c[3]);\r\n const b2 = [\r\n Math.min(segment[0][0], segment[1][0]),\r\n Math.min(segment[0][1], segment[1][1]),\r\n Math.max(segment[0][0], segment[1][0]),\r\n Math.max(segment[0][1], segment[1][1]),\r\n ] as Bounds;\r\n\r\n if (!doBoundsIntersect(b1, b2)) {\r\n continue;\r\n }\r\n\r\n const hits = curveIntersectLineSegment(c, segment);\r\n\r\n if (hits.length > 0) {\r\n intersections.push(...hits);\r\n\r\n if (onlyFirst) {\r\n return intersections;\r\n }\r\n }\r\n }\r\n\r\n return intersections;\r\n};\r\n\r\nconst intersectRectanguloidWithLineSegment = (\r\n element: ExcalidrawRectanguloidElement,\r\n elementsMap: ElementsMap,\r\n segment: LineSegment<GlobalPoint>,\r\n offset: number = 0,\r\n onlyFirst = false,\r\n): GlobalPoint[] => {\r\n const center = elementCenterPoint(element, elementsMap);\r\n // To emulate a rotated rectangle we rotate the point in the inverse angle\r\n // instead. It's all the same distance-wise.\r\n const rotatedA = pointRotateRads<GlobalPoint>(\r\n segment[0],\r\n center,\r\n -element.angle as Radians,\r\n );\r\n const rotatedB = pointRotateRads<GlobalPoint>(\r\n segment[1],\r\n center,\r\n -element.angle as Radians,\r\n );\r\n const rotatedIntersector = lineSegment(rotatedA, rotatedB);\r\n\r\n // Get the element's building components we can test against\r\n const [sides, corners] = deconstructRectanguloidElement(element, offset);\r\n\r\n const intersections: GlobalPoint[] = [];\r\n\r\n lineIntersections(\r\n sides,\r\n rotatedIntersector,\r\n intersections,\r\n center,\r\n element.angle,\r\n onlyFirst,\r\n );\r\n\r\n if (onlyFirst && intersections.length > 0) {\r\n return intersections;\r\n }\r\n\r\n curveIntersections(\r\n corners,\r\n rotatedIntersector,\r\n intersections,\r\n center,\r\n element.angle,\r\n onlyFirst,\r\n );\r\n\r\n return intersections;\r\n};\r\n\r\n/**\r\n *\r\n * @param element\r\n * @param a\r\n * @param b\r\n * @returns\r\n */\r\nconst intersectDiamondWithLineSegment = (\r\n element: ExcalidrawDiamondElement,\r\n elementsMap: ElementsMap,\r\n l: LineSegment<GlobalPoint>,\r\n offset: number = 0,\r\n onlyFirst = false,\r\n): GlobalPoint[] => {\r\n const center = elementCenterPoint(element, elementsMap);\r\n\r\n // Rotate the point to the inverse direction to simulate the rotated diamond\r\n // points. It's all the same distance-wise.\r\n const rotatedA = pointRotateRads(l[0], center, -element.angle as Radians);\r\n const rotatedB = pointRotateRads(l[1], center, -element.angle as Radians);\r\n const rotatedIntersector = lineSegment(rotatedA, rotatedB);\r\n\r\n const [sides, corners] = deconstructDiamondElement(element, offset);\r\n const intersections: GlobalPoint[] = [];\r\n\r\n lineIntersections(\r\n sides,\r\n rotatedIntersector,\r\n intersections,\r\n center,\r\n element.angle,\r\n onlyFirst,\r\n );\r\n\r\n if (onlyFirst && intersections.length > 0) {\r\n return intersections;\r\n }\r\n\r\n curveIntersections(\r\n corners,\r\n rotatedIntersector,\r\n intersections,\r\n center,\r\n element.angle,\r\n onlyFirst,\r\n );\r\n\r\n return intersections;\r\n};\r\n\r\n/**\r\n *\r\n * @param element\r\n * @param a\r\n * @param b\r\n * @returns\r\n */\r\nconst intersectEllipseWithLineSegment = (\r\n element: ExcalidrawEllipseElement,\r\n elementsMap: ElementsMap,\r\n l: LineSegment<GlobalPoint>,\r\n offset: number = 0,\r\n): GlobalPoint[] => {\r\n const center = elementCenterPoint(element, elementsMap);\r\n\r\n const rotatedA = pointRotateRads(l[0], center, -element.angle as Radians);\r\n const rotatedB = pointRotateRads(l[1], center, -element.angle as Radians);\r\n\r\n return ellipseSegmentInterceptPoints(\r\n ellipse(center, element.width / 2 + offset, element.height / 2 + offset),\r\n lineSegment(rotatedA, rotatedB),\r\n ).map((p) => pointRotateRads(p, center, element.angle));\r\n};\r\n\r\n/**\r\n * Check if the given point is considered on the given shape's border\r\n *\r\n * @param point\r\n * @param element\r\n * @param tolerance\r\n * @returns\r\n */\r\nconst isPointOnElementOutline = (\r\n point: GlobalPoint,\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n tolerance = 1,\r\n) => distanceToElement(element, elementsMap, point) <= tolerance;\r\n\r\n/**\r\n * Check if the given point is considered inside the element's border\r\n *\r\n * @param point\r\n * @param element\r\n * @returns\r\n */\r\nexport const isPointInElement = (\r\n point: GlobalPoint,\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (\r\n (isLinearElement(element) || isFreeDrawElement(element)) &&\r\n !isPathALoop(element.points)\r\n ) {\r\n // There isn't any \"inside\" for a non-looping path\r\n return false;\r\n }\r\n\r\n const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);\r\n\r\n if (!isPointWithinBounds(pointFrom(x1, y1), point, pointFrom(x2, y2))) {\r\n return false;\r\n }\r\n\r\n const center = pointFrom<GlobalPoint>((x1 + x2) / 2, (y1 + y2) / 2);\r\n const otherPoint = pointFromVector(\r\n vectorScale(\r\n vectorNormalize(vectorFromPoint(point, center, 0.1)),\r\n Math.max(element.width, element.height) * 2,\r\n ),\r\n center,\r\n );\r\n const intersector = lineSegment(point, otherPoint);\r\n const intersections = intersectElementWithLineSegment(\r\n element,\r\n elementsMap,\r\n intersector,\r\n ).filter((p, pos, arr) => arr.findIndex((q) => pointsEqual(q, p)) === pos);\r\n\r\n return intersections.length % 2 === 1;\r\n};\r\n\r\nexport const isBindableElementInsideOtherBindable = (\r\n innerElement: ExcalidrawBindableElement,\r\n outerElement: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n): boolean => {\r\n // Get corner points of the inner element based on its type\r\n const getCornerPoints = (\r\n element: ExcalidrawElement,\r\n offset: number,\r\n ): GlobalPoint[] => {\r\n const { x, y, width, height, angle } = element;\r\n const center = elementCenterPoint(element, elementsMap);\r\n\r\n if (element.type === \"diamond\") {\r\n // Diamond has 4 corner points at the middle of each side\r\n const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =\r\n getDiamondPoints(element);\r\n const corners: GlobalPoint[] = [\r\n pointFrom(x + topX, y + topY - offset), // top\r\n pointFrom(x + rightX + offset, y + rightY), // right\r\n pointFrom(x + bottomX, y + bottomY + offset), // bottom\r\n pointFrom(x + leftX - offset, y + leftY), // left\r\n ];\r\n return corners.map((corner) => pointRotateRads(corner, center, angle));\r\n }\r\n if (element.type === \"ellipse\") {\r\n // For ellipse, test points at the extremes (top, right, bottom, left)\r\n const cx = x + width / 2;\r\n const cy = y + height / 2;\r\n const rx = width / 2;\r\n const ry = height / 2;\r\n const corners: GlobalPoint[] = [\r\n pointFrom(cx, cy - ry - offset), // top\r\n pointFrom(cx + rx + offset, cy), // right\r\n pointFrom(cx, cy + ry + offset), // bottom\r\n pointFrom(cx - rx - offset, cy), // left\r\n ];\r\n return corners.map((corner) => pointRotateRads(corner, center, angle));\r\n }\r\n // Rectangle and other rectangular shapes (image, text, etc.)\r\n const corners: GlobalPoint[] = [\r\n pointFrom(x - offset, y - offset), // top-left\r\n pointFrom(x + width + offset, y - offset), // top-right\r\n pointFrom(x + width + offset, y + height + offset), // bottom-right\r\n pointFrom(x - offset, y + height + offset), // bottom-left\r\n ];\r\n return corners.map((corner) => pointRotateRads(corner, center, angle));\r\n };\r\n\r\n const offset = (-1 * Math.max(innerElement.width, innerElement.height)) / 20; // 5% offset\r\n const innerCorners = getCornerPoints(innerElement, offset);\r\n\r\n // Check if all corner points of the inner element are inside the outer element\r\n return innerCorners.every((corner) =>\r\n isPointInElement(corner, outerElement, elementsMap),\r\n );\r\n};\r\n", "import {\r\n DEFAULT_ADAPTIVE_RADIUS,\r\n DEFAULT_PROPORTIONAL_RADIUS,\r\n invariant,\r\n LINE_CONFIRM_THRESHOLD,\r\n ROUNDNESS,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n curve,\r\n curveCatmullRomCubicApproxPoints,\r\n curveOffsetPoints,\r\n lineSegment,\r\n lineSegmentIntersectionPoints,\r\n pointDistance,\r\n pointFrom,\r\n pointFromArray,\r\n pointFromVector,\r\n pointRotateRads,\r\n pointTranslate,\r\n rectangle,\r\n vectorFromPoint,\r\n vectorNormalize,\r\n vectorScale,\r\n type GlobalPoint,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type { Curve, LineSegment, LocalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport type { NormalizedZoomValue, Zoom } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { elementCenterPoint, getDiamondPoints } from \"./bounds\";\r\n\r\nimport { generateLinearCollisionShape } from \"./shape\";\r\n\r\nimport { isPointInElement } from \"./collision\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport { isRectangularElement } from \"./typeChecks\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawArrowElement,\r\n ExcalidrawDiamondElement,\r\n ExcalidrawElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawRectanguloidElement,\r\n} from \"./types\";\r\n\r\ntype ElementShape = [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]];\r\n\r\nconst ElementShapesCache = new WeakMap<\r\n ExcalidrawElement,\r\n { version: ExcalidrawElement[\"version\"]; shapes: Map<number, ElementShape> }\r\n>();\r\n\r\nconst getElementShapesCacheEntry = <T extends ExcalidrawElement>(\r\n element: T,\r\n offset: number,\r\n): ElementShape | undefined => {\r\n const record = ElementShapesCache.get(element);\r\n\r\n if (!record) {\r\n return undefined;\r\n }\r\n\r\n const { version, shapes } = record;\r\n\r\n if (version !== element.version) {\r\n ElementShapesCache.delete(element);\r\n return undefined;\r\n }\r\n\r\n return shapes.get(offset);\r\n};\r\n\r\nconst setElementShapesCacheEntry = <T extends ExcalidrawElement>(\r\n element: T,\r\n shape: ElementShape,\r\n offset: number,\r\n) => {\r\n const record = ElementShapesCache.get(element);\r\n\r\n if (!record) {\r\n ElementShapesCache.set(element, {\r\n version: element.version,\r\n shapes: new Map([[offset, shape]]),\r\n });\r\n\r\n return;\r\n }\r\n\r\n const { version, shapes } = record;\r\n\r\n if (version !== element.version) {\r\n ElementShapesCache.set(element, {\r\n version: element.version,\r\n shapes: new Map([[offset, shape]]),\r\n });\r\n\r\n return;\r\n }\r\n\r\n shapes.set(offset, shape);\r\n};\r\n\r\n/**\r\n * Returns the **rotated** components of freedraw, line or arrow elements.\r\n *\r\n * @param element The linear element to deconstruct\r\n * @returns The rotated in components.\r\n */\r\nexport function deconstructLinearOrFreeDrawElement(\r\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\r\n): [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]] {\r\n const cachedShape = getElementShapesCacheEntry(element, 0);\r\n\r\n if (cachedShape) {\r\n return cachedShape;\r\n }\r\n\r\n const ops = generateLinearCollisionShape(element) as {\r\n op: string;\r\n data: number[];\r\n }[];\r\n const lines = [];\r\n const curves = [];\r\n\r\n for (let idx = 0; idx < ops.length; idx += 1) {\r\n const op = ops[idx];\r\n const prevPoint =\r\n ops[idx - 1] && pointFromArray<LocalPoint>(ops[idx - 1].data.slice(-2));\r\n switch (op.op) {\r\n case \"move\":\r\n continue;\r\n case \"lineTo\":\r\n if (!prevPoint) {\r\n throw new Error(\"prevPoint is undefined\");\r\n }\r\n\r\n lines.push(\r\n lineSegment<GlobalPoint>(\r\n pointFrom<GlobalPoint>(\r\n element.x + prevPoint[0],\r\n element.y + prevPoint[1],\r\n ),\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[0],\r\n element.y + op.data[1],\r\n ),\r\n ),\r\n );\r\n continue;\r\n case \"bcurveTo\":\r\n if (!prevPoint) {\r\n throw new Error(\"prevPoint is undefined\");\r\n }\r\n\r\n curves.push(\r\n curve<GlobalPoint>(\r\n pointFrom<GlobalPoint>(\r\n element.x + prevPoint[0],\r\n element.y + prevPoint[1],\r\n ),\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[0],\r\n element.y + op.data[1],\r\n ),\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[2],\r\n element.y + op.data[3],\r\n ),\r\n pointFrom<GlobalPoint>(\r\n element.x + op.data[4],\r\n element.y + op.data[5],\r\n ),\r\n ),\r\n );\r\n continue;\r\n default: {\r\n console.error(\"Unknown op type\", op.op);\r\n }\r\n }\r\n }\r\n\r\n const shape = [lines, curves] as ElementShape;\r\n setElementShapesCacheEntry(element, shape, 0);\r\n\r\n return shape;\r\n}\r\n\r\n/**\r\n * Get the building components of a rectanguloid element in the form of\r\n * line segments and curves **unrotated**.\r\n *\r\n * @param element Target rectanguloid element\r\n * @param offset Optional offset to expand the rectanguloid shape\r\n * @returns Tuple of **unrotated** line segments (0) and curves (1)\r\n */\r\nexport function deconstructRectanguloidElement(\r\n element: ExcalidrawRectanguloidElement,\r\n offset: number = 0,\r\n): [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]] {\r\n const cachedShape = getElementShapesCacheEntry(element, offset);\r\n\r\n if (cachedShape) {\r\n return cachedShape;\r\n }\r\n\r\n let radius = getCornerRadius(\r\n Math.min(element.width, element.height),\r\n element,\r\n );\r\n\r\n if (radius === 0) {\r\n radius = 0.01;\r\n }\r\n\r\n const r = rectangle(\r\n pointFrom(element.x, element.y),\r\n pointFrom(element.x + element.width, element.y + element.height),\r\n );\r\n\r\n const top = lineSegment<GlobalPoint>(\r\n pointFrom<GlobalPoint>(r[0][0] + radius, r[0][1]),\r\n pointFrom<GlobalPoint>(r[1][0] - radius, r[0][1]),\r\n );\r\n const right = lineSegment<GlobalPoint>(\r\n pointFrom<GlobalPoint>(r[1][0], r[0][1] + radius),\r\n pointFrom<GlobalPoint>(r[1][0], r[1][1] - radius),\r\n );\r\n const bottom = lineSegment<GlobalPoint>(\r\n pointFrom<GlobalPoint>(r[0][0] + radius, r[1][1]),\r\n pointFrom<GlobalPoint>(r[1][0] - radius, r[1][1]),\r\n );\r\n const left = lineSegment<GlobalPoint>(\r\n pointFrom<GlobalPoint>(r[0][0], r[1][1] - radius),\r\n pointFrom<GlobalPoint>(r[0][0], r[0][1] + radius),\r\n );\r\n\r\n const baseCorners = [\r\n curve(\r\n left[1],\r\n pointFrom<GlobalPoint>(\r\n left[1][0] + (2 / 3) * (r[0][0] - left[1][0]),\r\n left[1][1] + (2 / 3) * (r[0][1] - left[1][1]),\r\n ),\r\n pointFrom<GlobalPoint>(\r\n top[0][0] + (2 / 3) * (r[0][0] - top[0][0]),\r\n top[0][1] + (2 / 3) * (r[0][1] - top[0][1]),\r\n ),\r\n top[0],\r\n ), // TOP LEFT\r\n curve(\r\n top[1],\r\n pointFrom<GlobalPoint>(\r\n top[1][0] + (2 / 3) * (r[1][0] - top[1][0]),\r\n top[1][1] + (2 / 3) * (r[0][1] - top[1][1]),\r\n ),\r\n pointFrom<GlobalPoint>(\r\n right[0][0] + (2 / 3) * (r[1][0] - right[0][0]),\r\n right[0][1] + (2 / 3) * (r[0][1] - right[0][1]),\r\n ),\r\n right[0],\r\n ), // TOP RIGHT\r\n curve(\r\n right[1],\r\n pointFrom<GlobalPoint>(\r\n right[1][0] + (2 / 3) * (r[1][0] - right[1][0]),\r\n right[1][1] + (2 / 3) * (r[1][1] - right[1][1]),\r\n ),\r\n pointFrom<GlobalPoint>(\r\n bottom[1][0] + (2 / 3) * (r[1][0] - bottom[1][0]),\r\n bottom[1][1] + (2 / 3) * (r[1][1] - bottom[1][1]),\r\n ),\r\n bottom[1],\r\n ), // BOTTOM RIGHT\r\n curve(\r\n bottom[0],\r\n pointFrom<GlobalPoint>(\r\n bottom[0][0] + (2 / 3) * (r[0][0] - bottom[0][0]),\r\n bottom[0][1] + (2 / 3) * (r[1][1] - bottom[0][1]),\r\n ),\r\n pointFrom<GlobalPoint>(\r\n left[0][0] + (2 / 3) * (r[0][0] - left[0][0]),\r\n left[0][1] + (2 / 3) * (r[1][1] - left[0][1]),\r\n ),\r\n left[0],\r\n ), // BOTTOM LEFT\r\n ];\r\n\r\n const corners =\r\n offset > 0\r\n ? baseCorners.map(\r\n (corner) =>\r\n curveCatmullRomCubicApproxPoints(\r\n curveOffsetPoints(corner, offset),\r\n )!,\r\n )\r\n : [\r\n [baseCorners[0]],\r\n [baseCorners[1]],\r\n [baseCorners[2]],\r\n [baseCorners[3]],\r\n ];\r\n\r\n const sides = [\r\n lineSegment<GlobalPoint>(\r\n corners[0][corners[0].length - 1][3],\r\n corners[1][0][0],\r\n ),\r\n lineSegment<GlobalPoint>(\r\n corners[1][corners[1].length - 1][3],\r\n corners[2][0][0],\r\n ),\r\n lineSegment<GlobalPoint>(\r\n corners[2][corners[2].length - 1][3],\r\n corners[3][0][0],\r\n ),\r\n lineSegment<GlobalPoint>(\r\n corners[3][corners[3].length - 1][3],\r\n corners[0][0][0],\r\n ),\r\n ];\r\n const shape = [sides, corners.flat()] as ElementShape;\r\n\r\n setElementShapesCacheEntry(element, shape, offset);\r\n\r\n return shape;\r\n}\r\n\r\n/**\r\n * Get the **unrotated** building components of a diamond element\r\n * in the form of line segments and curves as a tuple, in this order.\r\n *\r\n * @param element The element to deconstruct\r\n * @param offset An optional offset\r\n * @returns Tuple of line **unrotated** segments (0) and curves (1)\r\n */\r\nexport function deconstructDiamondElement(\r\n element: ExcalidrawDiamondElement,\r\n offset: number = 0,\r\n): [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]] {\r\n const cachedShape = getElementShapesCacheEntry(element, offset);\r\n\r\n if (cachedShape) {\r\n return cachedShape;\r\n }\r\n\r\n const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =\r\n getDiamondPoints(element);\r\n const verticalRadius = element.roundness\r\n ? getCornerRadius(Math.abs(topX - leftX), element)\r\n : (topX - leftX) * 0.01;\r\n const horizontalRadius = element.roundness\r\n ? getCornerRadius(Math.abs(rightY - topY), element)\r\n : (rightY - topY) * 0.01;\r\n\r\n const [top, right, bottom, left]: GlobalPoint[] = [\r\n pointFrom(element.x + topX, element.y + topY),\r\n pointFrom(element.x + rightX, element.y + rightY),\r\n pointFrom(element.x + bottomX, element.y + bottomY),\r\n pointFrom(element.x + leftX, element.y + leftY),\r\n ];\r\n\r\n const baseCorners = [\r\n curve(\r\n pointFrom<GlobalPoint>(\r\n right[0] - verticalRadius,\r\n right[1] - horizontalRadius,\r\n ),\r\n right,\r\n right,\r\n pointFrom<GlobalPoint>(\r\n right[0] - verticalRadius,\r\n right[1] + horizontalRadius,\r\n ),\r\n ), // RIGHT\r\n curve(\r\n pointFrom<GlobalPoint>(\r\n bottom[0] + verticalRadius,\r\n bottom[1] - horizontalRadius,\r\n ),\r\n bottom,\r\n bottom,\r\n pointFrom<GlobalPoint>(\r\n bottom[0] - verticalRadius,\r\n bottom[1] - horizontalRadius,\r\n ),\r\n ), // BOTTOM\r\n curve(\r\n pointFrom<GlobalPoint>(\r\n left[0] + verticalRadius,\r\n left[1] + horizontalRadius,\r\n ),\r\n left,\r\n left,\r\n pointFrom<GlobalPoint>(\r\n left[0] + verticalRadius,\r\n left[1] - horizontalRadius,\r\n ),\r\n ), // LEFT\r\n curve(\r\n pointFrom<GlobalPoint>(\r\n top[0] - verticalRadius,\r\n top[1] + horizontalRadius,\r\n ),\r\n top,\r\n top,\r\n pointFrom<GlobalPoint>(\r\n top[0] + verticalRadius,\r\n top[1] + horizontalRadius,\r\n ),\r\n ), // TOP\r\n ];\r\n\r\n const corners = baseCorners.map(\r\n (corner) =>\r\n curveCatmullRomCubicApproxPoints(curveOffsetPoints(corner, offset))!,\r\n );\r\n\r\n const sides = [\r\n lineSegment<GlobalPoint>(\r\n corners[0][corners[0].length - 1][3],\r\n corners[1][0][0],\r\n ),\r\n lineSegment<GlobalPoint>(\r\n corners[1][corners[1].length - 1][3],\r\n corners[2][0][0],\r\n ),\r\n lineSegment<GlobalPoint>(\r\n corners[2][corners[2].length - 1][3],\r\n corners[3][0][0],\r\n ),\r\n lineSegment<GlobalPoint>(\r\n corners[3][corners[3].length - 1][3],\r\n corners[0][0][0],\r\n ),\r\n ];\r\n\r\n const shape = [sides, corners.flat()] as ElementShape;\r\n\r\n setElementShapesCacheEntry(element, shape, offset);\r\n\r\n return shape;\r\n}\r\n\r\n// Checks if the first and last point are close enough\r\n// to be considered a loop\r\nexport const isPathALoop = (\r\n points: ExcalidrawLinearElement[\"points\"],\r\n /** supply if you want the loop detection to account for current zoom */\r\n zoomValue: Zoom[\"value\"] = 1 as NormalizedZoomValue,\r\n): boolean => {\r\n if (points.length >= 3) {\r\n const [first, last] = [points[0], points[points.length - 1]];\r\n const distance = pointDistance(first, last);\r\n\r\n // Adjusting LINE_CONFIRM_THRESHOLD to current zoom so that when zoomed in\r\n // really close we make the threshold smaller, and vice versa.\r\n return distance <= LINE_CONFIRM_THRESHOLD / zoomValue;\r\n }\r\n return false;\r\n};\r\n\r\nexport const getCornerRadius = (x: number, element: ExcalidrawElement) => {\r\n if (\r\n element.roundness?.type === ROUNDNESS.PROPORTIONAL_RADIUS ||\r\n element.roundness?.type === ROUNDNESS.LEGACY\r\n ) {\r\n return x * DEFAULT_PROPORTIONAL_RADIUS;\r\n }\r\n\r\n if (element.roundness?.type === ROUNDNESS.ADAPTIVE_RADIUS) {\r\n const fixedRadiusSize = element.roundness?.value ?? DEFAULT_ADAPTIVE_RADIUS;\r\n\r\n const CUTOFF_SIZE = fixedRadiusSize / DEFAULT_PROPORTIONAL_RADIUS;\r\n\r\n if (x <= CUTOFF_SIZE) {\r\n return x * DEFAULT_PROPORTIONAL_RADIUS;\r\n }\r\n\r\n return fixedRadiusSize;\r\n }\r\n\r\n return 0;\r\n};\r\n\r\nconst getDiagonalsForBindableElement = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n // for rectangles, shrink the diagonals a bit because there's something\r\n // going on with the focus points around the corners. Ask Mark for details.\r\n const OFFSET_PX = element.type === \"rectangle\" ? 15 : 0;\r\n const shrinkSegment = (seg: LineSegment<GlobalPoint>) => {\r\n const v = vectorNormalize(vectorFromPoint(seg[1], seg[0]));\r\n const offset = vectorScale(v, OFFSET_PX);\r\n return lineSegment<GlobalPoint>(\r\n pointTranslate(seg[0], offset),\r\n pointTranslate(seg[1], vectorScale(offset, -1)),\r\n );\r\n };\r\n\r\n const center = elementCenterPoint(element, elementsMap);\r\n const diagonalOne = shrinkSegment(\r\n isRectangularElement(element)\r\n ? lineSegment<GlobalPoint>(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x, element.y),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + element.width,\r\n element.y + element.height,\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n )\r\n : lineSegment<GlobalPoint>(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x + element.width / 2, element.y),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + element.width / 2,\r\n element.y + element.height,\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n ),\r\n );\r\n const diagonalTwo = shrinkSegment(\r\n isRectangularElement(element)\r\n ? lineSegment<GlobalPoint>(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x + element.width, element.y),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x, element.y + element.height),\r\n center,\r\n element.angle,\r\n ),\r\n )\r\n : lineSegment<GlobalPoint>(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x, element.y + element.height / 2),\r\n center,\r\n element.angle,\r\n ),\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + element.width,\r\n element.y + element.height / 2,\r\n ),\r\n center,\r\n element.angle,\r\n ),\r\n ),\r\n );\r\n\r\n return [diagonalOne, diagonalTwo];\r\n};\r\n\r\nexport const projectFixedPointOntoDiagonal = (\r\n arrow: ExcalidrawArrowElement,\r\n point: GlobalPoint,\r\n element: ExcalidrawElement,\r\n startOrEnd: \"start\" | \"end\",\r\n elementsMap: ElementsMap,\r\n): GlobalPoint | null => {\r\n invariant(arrow.points.length >= 2, \"Arrow must have at least two points\");\r\n if (arrow.width < 3 && arrow.height < 3) {\r\n return null;\r\n }\r\n\r\n const [diagonalOne, diagonalTwo] = getDiagonalsForBindableElement(\r\n element,\r\n elementsMap,\r\n );\r\n\r\n const a = LinearElementEditor.getPointAtIndexGlobalCoordinates(\r\n arrow,\r\n startOrEnd === \"start\" ? 1 : arrow.points.length - 2,\r\n elementsMap,\r\n );\r\n const b = pointFromVector<GlobalPoint>(\r\n vectorScale(\r\n vectorFromPoint(point, a),\r\n 2 * pointDistance(a, point) +\r\n Math.max(\r\n pointDistance(diagonalOne[0], diagonalOne[1]),\r\n pointDistance(diagonalTwo[0], diagonalTwo[1]),\r\n ),\r\n ),\r\n a,\r\n );\r\n const intersector = lineSegment<GlobalPoint>(point, b);\r\n const p1 = lineSegmentIntersectionPoints(diagonalOne, intersector);\r\n const p2 = lineSegmentIntersectionPoints(diagonalTwo, intersector);\r\n const d1 = p1 && pointDistance(a, p1);\r\n const d2 = p2 && pointDistance(a, p2);\r\n\r\n let p = null;\r\n if (d1 != null && d2 != null) {\r\n p = d1 < d2 ? p1 : p2;\r\n } else {\r\n p = p1 || p2 || null;\r\n }\r\n\r\n return p && isPointInElement(p, element, elementsMap) ? p : null;\r\n};\r\n", "import { ROUNDNESS, assertNever } from \"@excalidraw-modify/common\";\r\n\r\nimport { pointsEqual } from \"@excalidraw-modify/math\";\r\n\r\nimport type { ElementOrToolType } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type { MarkNonNullable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n ExcalidrawTextElement,\r\n ExcalidrawEmbeddableElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawBindableElement,\r\n ExcalidrawFreeDrawElement,\r\n InitializedExcalidrawImageElement,\r\n ExcalidrawImageElement,\r\n ExcalidrawTextElementWithContainer,\r\n ExcalidrawTextContainer,\r\n ExcalidrawFrameElement,\r\n RoundnessType,\r\n ExcalidrawFrameLikeElement,\r\n ExcalidrawElementType,\r\n ExcalidrawIframeElement,\r\n ExcalidrawIframeLikeElement,\r\n ExcalidrawMagicFrameElement,\r\n ExcalidrawArrowElement,\r\n ExcalidrawElbowArrowElement,\r\n ExcalidrawLineElement,\r\n ExcalidrawFlowchartNodeElement,\r\n ExcalidrawLinearElementSubType,\r\n} from \"./types\";\r\n\r\nexport const isInitializedImageElement = (\r\n element: ExcalidrawElement | null,\r\n): element is InitializedExcalidrawImageElement => {\r\n return !!element && element.type === \"image\" && !!element.fileId;\r\n};\r\n\r\nexport const isImageElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawImageElement => {\r\n return !!element && element.type === \"image\";\r\n};\r\n\r\nexport const isEmbeddableElement = (\r\n element: ExcalidrawElement | null | undefined,\r\n): element is ExcalidrawEmbeddableElement => {\r\n return !!element && element.type === \"embeddable\";\r\n};\r\n\r\nexport const isIframeElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawIframeElement => {\r\n return !!element && element.type === \"iframe\";\r\n};\r\n\r\nexport const isIframeLikeElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawIframeLikeElement => {\r\n return (\r\n !!element && (element.type === \"iframe\" || element.type === \"embeddable\")\r\n );\r\n};\r\n\r\nexport const isTextElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawTextElement => {\r\n return element != null && element.type === \"text\";\r\n};\r\n\r\nexport const isFrameElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawFrameElement => {\r\n return element != null && element.type === \"frame\";\r\n};\r\n\r\nexport const isMagicFrameElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawMagicFrameElement => {\r\n return element != null && element.type === \"magicframe\";\r\n};\r\n\r\nexport const isFrameLikeElement = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawFrameLikeElement => {\r\n return (\r\n element != null &&\r\n (element.type === \"frame\" || element.type === \"magicframe\")\r\n );\r\n};\r\n\r\nexport const isFreeDrawElement = (\r\n element?: ExcalidrawElement | null,\r\n): element is ExcalidrawFreeDrawElement => {\r\n return element != null && isFreeDrawElementType(element.type);\r\n};\r\n\r\nexport const isFreeDrawElementType = (\r\n elementType: ExcalidrawElementType,\r\n): boolean => {\r\n return elementType === \"freedraw\";\r\n};\r\n\r\nexport const isLinearElement = (\r\n element?: ExcalidrawElement | null,\r\n): element is ExcalidrawLinearElement => {\r\n return element != null && isLinearElementType(element.type);\r\n};\r\n\r\nexport const isLineElement = (\r\n element?: ExcalidrawElement | null,\r\n): element is ExcalidrawLineElement => {\r\n return element != null && element.type === \"line\";\r\n};\r\n\r\nexport const isArrowElement = (\r\n element?: ExcalidrawElement | null,\r\n): element is ExcalidrawArrowElement => {\r\n return element != null && element.type === \"arrow\";\r\n};\r\n\r\nexport const isElbowArrow = (\r\n element?: ExcalidrawElement,\r\n): element is ExcalidrawElbowArrowElement => {\r\n return isArrowElement(element) && element.elbowed;\r\n};\r\n\r\n/**\r\n * sharp or curved arrow, but not elbow\r\n */\r\nexport const isSimpleArrow = (\r\n element?: ExcalidrawElement,\r\n): element is ExcalidrawArrowElement => {\r\n return isArrowElement(element) && !element.elbowed;\r\n};\r\n\r\nexport const isSharpArrow = (\r\n element?: ExcalidrawElement,\r\n): element is ExcalidrawArrowElement => {\r\n return isArrowElement(element) && !element.elbowed && !element.roundness;\r\n};\r\n\r\nexport const isCurvedArrow = (\r\n element?: ExcalidrawElement,\r\n): element is ExcalidrawArrowElement => {\r\n return (\r\n isArrowElement(element) && !element.elbowed && element.roundness !== null\r\n );\r\n};\r\n\r\nexport const isLinearElementType = (\r\n elementType: ElementOrToolType,\r\n): boolean => {\r\n return (\r\n elementType === \"arrow\" || elementType === \"line\" // || elementType === \"freedraw\"\r\n );\r\n};\r\n\r\nexport const isBindingElement = (\r\n element?: ExcalidrawElement | null,\r\n includeLocked = true,\r\n): element is ExcalidrawArrowElement => {\r\n return (\r\n element != null &&\r\n (!element.locked || includeLocked === true) &&\r\n isBindingElementType(element.type)\r\n );\r\n};\r\n\r\nexport const isBindingElementType = (\r\n elementType: ElementOrToolType,\r\n): boolean => {\r\n return elementType === \"arrow\";\r\n};\r\n\r\nexport const isBindableElement = (\r\n element: ExcalidrawElement | null | undefined,\r\n includeLocked = true,\r\n): element is ExcalidrawBindableElement => {\r\n return (\r\n element != null &&\r\n (!element.locked || includeLocked === true) &&\r\n (element.type === \"rectangle\" ||\r\n element.type === \"diamond\" ||\r\n element.type === \"ellipse\" ||\r\n element.type === \"image\" ||\r\n element.type === \"iframe\" ||\r\n element.type === \"embeddable\" ||\r\n element.type === \"frame\" ||\r\n element.type === \"magicframe\" ||\r\n (element.type === \"text\" && !element.containerId))\r\n );\r\n};\r\n\r\nexport const isRectanguloidElement = (\r\n element?: ExcalidrawElement | null,\r\n): element is ExcalidrawBindableElement => {\r\n return (\r\n element != null &&\r\n (element.type === \"rectangle\" ||\r\n element.type === \"diamond\" ||\r\n element.type === \"image\" ||\r\n element.type === \"iframe\" ||\r\n element.type === \"embeddable\" ||\r\n element.type === \"frame\" ||\r\n element.type === \"magicframe\" ||\r\n (element.type === \"text\" && !element.containerId))\r\n );\r\n};\r\n\r\n// TODO: Remove this when proper distance calculation is introduced\r\n// @see binding.ts:distanceToBindableElement()\r\nexport const isRectangularElement = (\r\n element?: ExcalidrawElement | null,\r\n): element is ExcalidrawBindableElement => {\r\n return (\r\n element != null &&\r\n (element.type === \"rectangle\" ||\r\n element.type === \"image\" ||\r\n element.type === \"text\" ||\r\n element.type === \"iframe\" ||\r\n element.type === \"embeddable\" ||\r\n element.type === \"frame\" ||\r\n element.type === \"magicframe\" ||\r\n element.type === \"freedraw\")\r\n );\r\n};\r\n\r\nexport const isTextBindableContainer = (\r\n element: ExcalidrawElement | null,\r\n includeLocked = true,\r\n): element is ExcalidrawTextContainer => {\r\n return (\r\n element != null &&\r\n (!element.locked || includeLocked === true) &&\r\n (element.type === \"rectangle\" ||\r\n element.type === \"diamond\" ||\r\n element.type === \"ellipse\" ||\r\n isArrowElement(element))\r\n );\r\n};\r\n\r\nexport const isExcalidrawElement = (\r\n element: any,\r\n): element is ExcalidrawElement => {\r\n const type: ExcalidrawElementType | undefined = element?.type;\r\n if (!type) {\r\n return false;\r\n }\r\n switch (type) {\r\n case \"text\":\r\n case \"diamond\":\r\n case \"rectangle\":\r\n case \"iframe\":\r\n case \"embeddable\":\r\n case \"ellipse\":\r\n case \"arrow\":\r\n case \"freedraw\":\r\n case \"line\":\r\n case \"frame\":\r\n case \"magicframe\":\r\n case \"image\":\r\n case \"selection\": {\r\n return true;\r\n }\r\n default: {\r\n assertNever(type, null);\r\n return false;\r\n }\r\n }\r\n};\r\n\r\nexport const isFlowchartNodeElement = (\r\n element: ExcalidrawElement,\r\n): element is ExcalidrawFlowchartNodeElement => {\r\n return (\r\n element.type === \"rectangle\" ||\r\n element.type === \"ellipse\" ||\r\n element.type === \"diamond\"\r\n );\r\n};\r\n\r\nexport const hasBoundTextElement = (\r\n element: ExcalidrawElement | null,\r\n): element is MarkNonNullable<ExcalidrawBindableElement, \"boundElements\"> => {\r\n return (\r\n isTextBindableContainer(element) &&\r\n !!element.boundElements?.some(({ type }) => type === \"text\")\r\n );\r\n};\r\n\r\nexport const isBoundToContainer = (\r\n element: ExcalidrawElement | null,\r\n): element is ExcalidrawTextElementWithContainer => {\r\n return (\r\n element !== null &&\r\n \"containerId\" in element &&\r\n element.containerId !== null &&\r\n isTextElement(element)\r\n );\r\n};\r\n\r\nexport const isArrowBoundToElement = (element: ExcalidrawArrowElement) => {\r\n return !!element.startBinding || !!element.endBinding;\r\n};\r\n\r\nexport const isUsingAdaptiveRadius = (type: string) =>\r\n type === \"rectangle\" ||\r\n type === \"embeddable\" ||\r\n type === \"iframe\" ||\r\n type === \"image\";\r\n\r\nexport const isUsingProportionalRadius = (type: string) =>\r\n type === \"line\" || type === \"arrow\" || type === \"diamond\";\r\n\r\nexport const canApplyRoundnessTypeToElement = (\r\n roundnessType: RoundnessType,\r\n element: ExcalidrawElement,\r\n) => {\r\n if (\r\n (roundnessType === ROUNDNESS.ADAPTIVE_RADIUS ||\r\n // if legacy roundness, it can be applied to elements that currently\r\n // use adaptive radius\r\n roundnessType === ROUNDNESS.LEGACY) &&\r\n isUsingAdaptiveRadius(element.type)\r\n ) {\r\n return true;\r\n }\r\n if (\r\n roundnessType === ROUNDNESS.PROPORTIONAL_RADIUS &&\r\n isUsingProportionalRadius(element.type)\r\n ) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport const getDefaultRoundnessTypeForElement = (\r\n element: ExcalidrawElement,\r\n) => {\r\n if (isUsingProportionalRadius(element.type)) {\r\n return {\r\n type: ROUNDNESS.PROPORTIONAL_RADIUS,\r\n };\r\n }\r\n\r\n if (isUsingAdaptiveRadius(element.type)) {\r\n return {\r\n type: ROUNDNESS.ADAPTIVE_RADIUS,\r\n };\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const getLinearElementSubType = (\r\n element: ExcalidrawLinearElement,\r\n): ExcalidrawLinearElementSubType => {\r\n if (isSharpArrow(element)) {\r\n return \"sharpArrow\";\r\n }\r\n if (isCurvedArrow(element)) {\r\n return \"curvedArrow\";\r\n }\r\n if (isElbowArrow(element)) {\r\n return \"elbowArrow\";\r\n }\r\n return \"line\";\r\n};\r\n\r\n/**\r\n * Checks if current element points meet all the conditions for polygon=true\r\n * (this isn't a element type check, for that use isLineElement).\r\n *\r\n * If you want to check if points *can* be turned into a polygon, use\r\n * canBecomePolygon(points).\r\n */\r\nexport const isValidPolygon = (\r\n points: ExcalidrawLineElement[\"points\"],\r\n): boolean => {\r\n return points.length > 3 && pointsEqual(points[0], points[points.length - 1]);\r\n};\r\n\r\nexport const canBecomePolygon = (\r\n points: ExcalidrawLineElement[\"points\"],\r\n): boolean => {\r\n return (\r\n points.length > 3 ||\r\n // 3-point polygons can't have all points in a single line\r\n (points.length === 3 && !pointsEqual(points[0], points[points.length - 1]))\r\n );\r\n};\r\n", "import {\r\n ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO,\r\n ARROW_LABEL_WIDTH_FRACTION,\r\n BOUND_TEXT_PADDING,\r\n DEFAULT_FONT_SIZE,\r\n TEXT_ALIGN,\r\n VERTICAL_ALIGN,\r\n getFontString,\r\n isProdEnv,\r\n invariant,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport { pointFrom, pointRotateRads, type Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type { ExtractSetType } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport {\r\n resetOriginalContainerCache,\r\n updateOriginalContainerCache,\r\n} from \"./containerCache\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\n\r\nimport { measureText } from \"./textMeasurements\";\r\nimport { wrapText } from \"./textWrapping\";\r\nimport {\r\n isBoundToContainer,\r\n isArrowElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\nimport type { MaybeTransformHandleType } from \"./transformHandles\";\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawElement,\r\n ExcalidrawElementType,\r\n ExcalidrawTextContainer,\r\n ExcalidrawTextElement,\r\n ExcalidrawTextElementWithContainer,\r\n NonDeletedExcalidrawElement,\r\n} from \"./types\";\r\n\r\nexport const redrawTextBoundingBox = (\r\n textElement: ExcalidrawTextElement,\r\n container: ExcalidrawElement | null,\r\n scene: Scene,\r\n) => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n\r\n let maxWidth = undefined;\r\n\r\n if (!isProdEnv()) {\r\n invariant(\r\n !container || !isArrowElement(container) || textElement.angle === 0,\r\n \"text element angle must be 0 if bound to arrow container\",\r\n );\r\n }\r\n\r\n const boundTextUpdates = {\r\n x: textElement.x,\r\n y: textElement.y,\r\n text: textElement.text,\r\n width: textElement.width,\r\n height: textElement.height,\r\n angle: (container\r\n ? isArrowElement(container)\r\n ? 0\r\n : container.angle\r\n : textElement.angle) as Radians,\r\n };\r\n\r\n boundTextUpdates.text = textElement.text;\r\n\r\n if (container || !textElement.autoResize) {\r\n maxWidth = container\r\n ? getBoundTextMaxWidth(container, textElement)\r\n : textElement.width;\r\n boundTextUpdates.text = wrapText(\r\n textElement.originalText,\r\n getFontString(textElement),\r\n maxWidth,\r\n );\r\n }\r\n\r\n const metrics = measureText(\r\n boundTextUpdates.text,\r\n getFontString(textElement),\r\n textElement.lineHeight,\r\n );\r\n\r\n // Note: only update width for unwrapped text and bound texts (which always have autoResize set to true)\r\n if (textElement.autoResize) {\r\n boundTextUpdates.width = metrics.width;\r\n }\r\n boundTextUpdates.height = metrics.height;\r\n\r\n if (container) {\r\n const maxContainerHeight = getBoundTextMaxHeight(\r\n container,\r\n textElement as ExcalidrawTextElementWithContainer,\r\n );\r\n const maxContainerWidth = getBoundTextMaxWidth(container, textElement);\r\n\r\n if (!isArrowElement(container) && metrics.height > maxContainerHeight) {\r\n const nextHeight = computeContainerDimensionForBoundText(\r\n metrics.height,\r\n container.type,\r\n );\r\n scene.mutateElement(container, { height: nextHeight });\r\n updateOriginalContainerCache(container.id, nextHeight);\r\n }\r\n\r\n if (metrics.width > maxContainerWidth) {\r\n const nextWidth = computeContainerDimensionForBoundText(\r\n metrics.width,\r\n container.type,\r\n );\r\n scene.mutateElement(container, { width: nextWidth });\r\n }\r\n\r\n const updatedTextElement = {\r\n ...textElement,\r\n ...boundTextUpdates,\r\n } as ExcalidrawTextElementWithContainer;\r\n\r\n const { x, y } = computeBoundTextPosition(\r\n container,\r\n updatedTextElement,\r\n elementsMap,\r\n );\r\n\r\n boundTextUpdates.x = x;\r\n boundTextUpdates.y = y;\r\n }\r\n\r\n scene.mutateElement(textElement, boundTextUpdates);\r\n};\r\n\r\nexport const handleBindTextResize = (\r\n container: NonDeletedExcalidrawElement,\r\n scene: Scene,\r\n transformHandleType: MaybeTransformHandleType,\r\n shouldMaintainAspectRatio = false,\r\n) => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n const boundTextElementId = getBoundTextElementId(container);\r\n if (!boundTextElementId) {\r\n return;\r\n }\r\n resetOriginalContainerCache(container.id);\r\n const textElement = getBoundTextElement(container, elementsMap);\r\n if (textElement && textElement.text) {\r\n if (!container) {\r\n return;\r\n }\r\n\r\n let text = textElement.text;\r\n let nextHeight = textElement.height;\r\n let nextWidth = textElement.width;\r\n const maxWidth = getBoundTextMaxWidth(container, textElement);\r\n const maxHeight = getBoundTextMaxHeight(container, textElement);\r\n let containerHeight = container.height;\r\n if (\r\n shouldMaintainAspectRatio ||\r\n (transformHandleType !== \"n\" && transformHandleType !== \"s\")\r\n ) {\r\n if (text) {\r\n text = wrapText(\r\n textElement.originalText,\r\n getFontString(textElement),\r\n maxWidth,\r\n );\r\n }\r\n const metrics = measureText(\r\n text,\r\n getFontString(textElement),\r\n textElement.lineHeight,\r\n );\r\n nextHeight = metrics.height;\r\n nextWidth = metrics.width;\r\n }\r\n // increase height in case text element height exceeds\r\n if (nextHeight > maxHeight) {\r\n containerHeight = computeContainerDimensionForBoundText(\r\n nextHeight,\r\n container.type,\r\n );\r\n\r\n const diff = containerHeight - container.height;\r\n // fix the y coord when resizing from ne/nw/n\r\n const updatedY =\r\n !isArrowElement(container) &&\r\n (transformHandleType === \"ne\" ||\r\n transformHandleType === \"nw\" ||\r\n transformHandleType === \"n\")\r\n ? container.y - diff\r\n : container.y;\r\n scene.mutateElement(container, {\r\n height: containerHeight,\r\n y: updatedY,\r\n });\r\n }\r\n\r\n scene.mutateElement(textElement, {\r\n text,\r\n width: nextWidth,\r\n height: nextHeight,\r\n });\r\n\r\n if (!isArrowElement(container)) {\r\n scene.mutateElement(\r\n textElement,\r\n computeBoundTextPosition(container, textElement, elementsMap),\r\n );\r\n }\r\n }\r\n};\r\n\r\nexport const computeBoundTextPosition = (\r\n container: ExcalidrawElement,\r\n boundTextElement: ExcalidrawTextElementWithContainer,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (isArrowElement(container)) {\r\n return LinearElementEditor.getBoundTextElementPosition(\r\n container,\r\n boundTextElement,\r\n elementsMap,\r\n );\r\n }\r\n const containerCoords = getContainerCoords(container);\r\n const maxContainerHeight = getBoundTextMaxHeight(container, boundTextElement);\r\n const maxContainerWidth = getBoundTextMaxWidth(container, boundTextElement);\r\n\r\n let x;\r\n let y;\r\n if (boundTextElement.verticalAlign === VERTICAL_ALIGN.TOP) {\r\n y = containerCoords.y;\r\n } else if (boundTextElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {\r\n y = containerCoords.y + (maxContainerHeight - boundTextElement.height);\r\n } else {\r\n y =\r\n containerCoords.y +\r\n (maxContainerHeight / 2 - boundTextElement.height / 2);\r\n }\r\n if (boundTextElement.textAlign === TEXT_ALIGN.LEFT) {\r\n x = containerCoords.x;\r\n } else if (boundTextElement.textAlign === TEXT_ALIGN.RIGHT) {\r\n x = containerCoords.x + (maxContainerWidth - boundTextElement.width);\r\n } else {\r\n x =\r\n containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);\r\n }\r\n const angle = (container.angle ?? 0) as Radians;\r\n\r\n if (angle !== 0) {\r\n const contentCenter = pointFrom(\r\n containerCoords.x + maxContainerWidth / 2,\r\n containerCoords.y + maxContainerHeight / 2,\r\n );\r\n const textCenter = pointFrom(\r\n x + boundTextElement.width / 2,\r\n y + boundTextElement.height / 2,\r\n );\r\n\r\n const [rx, ry] = pointRotateRads(textCenter, contentCenter, angle);\r\n\r\n return {\r\n x: rx - boundTextElement.width / 2,\r\n y: ry - boundTextElement.height / 2,\r\n };\r\n }\r\n\r\n return { x, y };\r\n};\r\n\r\nexport const getBoundTextElementId = (container: ExcalidrawElement | null) => {\r\n return container?.boundElements?.length\r\n ? container?.boundElements?.find((ele) => ele.type === \"text\")?.id || null\r\n : null;\r\n};\r\n\r\nexport const getBoundTextElement = (\r\n element: ExcalidrawElement | null,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (!element) {\r\n return null;\r\n }\r\n const boundTextElementId = getBoundTextElementId(element);\r\n\r\n if (boundTextElementId) {\r\n return (elementsMap.get(boundTextElementId) ||\r\n null) as ExcalidrawTextElementWithContainer | null;\r\n }\r\n return null;\r\n};\r\n\r\nexport const getContainerElement = (\r\n element: ExcalidrawTextElement | null,\r\n elementsMap: ElementsMap,\r\n): ExcalidrawTextContainer | null => {\r\n if (!element) {\r\n return null;\r\n }\r\n if (element.containerId) {\r\n return (elementsMap.get(element.containerId) ||\r\n null) as ExcalidrawTextContainer | null;\r\n }\r\n return null;\r\n};\r\n\r\nexport const getContainerCenter = (\r\n container: ExcalidrawElement,\r\n appState: AppState,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (!isArrowElement(container)) {\r\n return {\r\n x: container.x + container.width / 2,\r\n y: container.y + container.height / 2,\r\n };\r\n }\r\n const points = LinearElementEditor.getPointsGlobalCoordinates(\r\n container,\r\n elementsMap,\r\n );\r\n if (points.length % 2 === 1) {\r\n const index = Math.floor(container.points.length / 2);\r\n const midPoint = LinearElementEditor.getPointGlobalCoordinates(\r\n container,\r\n container.points[index],\r\n elementsMap,\r\n );\r\n return { x: midPoint[0], y: midPoint[1] };\r\n }\r\n const index = container.points.length / 2 - 1;\r\n let midSegmentMidpoint = LinearElementEditor.getEditorMidPoints(\r\n container,\r\n elementsMap,\r\n appState,\r\n )[index];\r\n if (!midSegmentMidpoint) {\r\n midSegmentMidpoint = LinearElementEditor.getSegmentMidPoint(\r\n container,\r\n index + 1,\r\n );\r\n }\r\n return { x: midSegmentMidpoint[0], y: midSegmentMidpoint[1] };\r\n};\r\n\r\nexport const getContainerCoords = (container: NonDeletedExcalidrawElement) => {\r\n let offsetX = BOUND_TEXT_PADDING;\r\n let offsetY = BOUND_TEXT_PADDING;\r\n\r\n if (container.type === \"ellipse\") {\r\n // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6172\r\n offsetX += (container.width / 2) * (1 - Math.sqrt(2) / 2);\r\n offsetY += (container.height / 2) * (1 - Math.sqrt(2) / 2);\r\n }\r\n // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6265\r\n if (container.type === \"diamond\") {\r\n offsetX += container.width / 4;\r\n offsetY += container.height / 4;\r\n }\r\n return {\r\n x: container.x + offsetX,\r\n y: container.y + offsetY,\r\n };\r\n};\r\n\r\nexport const getTextElementAngle = (\r\n textElement: ExcalidrawTextElement,\r\n container: ExcalidrawTextContainer | null,\r\n) => {\r\n if (isArrowElement(container)) {\r\n return 0;\r\n }\r\n if (!container) {\r\n return textElement.angle;\r\n }\r\n return container.angle;\r\n};\r\n\r\nexport const getBoundTextElementPosition = (\r\n container: ExcalidrawElement,\r\n boundTextElement: ExcalidrawTextElementWithContainer,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (isArrowElement(container)) {\r\n return LinearElementEditor.getBoundTextElementPosition(\r\n container,\r\n boundTextElement,\r\n elementsMap,\r\n );\r\n }\r\n};\r\n\r\nexport const shouldAllowVerticalAlign = (\r\n selectedElements: NonDeletedExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n) => {\r\n return selectedElements.some((element) => {\r\n if (isBoundToContainer(element)) {\r\n const container = getContainerElement(element, elementsMap);\r\n if (isArrowElement(container)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n return false;\r\n });\r\n};\r\n\r\nexport const suppportsHorizontalAlign = (\r\n selectedElements: NonDeletedExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n) => {\r\n return selectedElements.some((element) => {\r\n if (isBoundToContainer(element)) {\r\n const container = getContainerElement(element, elementsMap);\r\n if (isArrowElement(container)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n return isTextElement(element);\r\n });\r\n};\r\n\r\nconst VALID_CONTAINER_TYPES = new Set([\r\n \"rectangle\",\r\n \"ellipse\",\r\n \"diamond\",\r\n \"arrow\",\r\n]);\r\n\r\nexport const isValidTextContainer = (element: {\r\n type: ExcalidrawElementType;\r\n}) => VALID_CONTAINER_TYPES.has(element.type);\r\n\r\nexport const computeContainerDimensionForBoundText = (\r\n dimension: number,\r\n containerType: ExtractSetType<typeof VALID_CONTAINER_TYPES>,\r\n) => {\r\n dimension = Math.ceil(dimension);\r\n const padding = BOUND_TEXT_PADDING * 2;\r\n\r\n if (containerType === \"ellipse\") {\r\n return Math.round(((dimension + padding) / Math.sqrt(2)) * 2);\r\n }\r\n if (containerType === \"arrow\") {\r\n return dimension + padding * 8;\r\n }\r\n if (containerType === \"diamond\") {\r\n return 2 * (dimension + padding);\r\n }\r\n return dimension + padding;\r\n};\r\n\r\nexport const getBoundTextMaxWidth = (\r\n container: ExcalidrawElement,\r\n boundTextElement: ExcalidrawTextElement | null,\r\n) => {\r\n const { width } = container;\r\n if (isArrowElement(container)) {\r\n const minWidth =\r\n (boundTextElement?.fontSize ?? DEFAULT_FONT_SIZE) *\r\n ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO;\r\n return Math.max(ARROW_LABEL_WIDTH_FRACTION * width, minWidth);\r\n }\r\n if (container.type === \"ellipse\") {\r\n // The width of the largest rectangle inscribed inside an ellipse is\r\n // Math.round((ellipse.width / 2) * Math.sqrt(2)) which is derived from\r\n // equation of an ellipse -https://github.com/excalidraw/excalidraw/pull/6172\r\n return Math.round((width / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;\r\n }\r\n if (container.type === \"diamond\") {\r\n // The width of the largest rectangle inscribed inside a rhombus is\r\n // Math.round(width / 2) - https://github.com/excalidraw/excalidraw/pull/6265\r\n return Math.round(width / 2) - BOUND_TEXT_PADDING * 2;\r\n }\r\n return width - BOUND_TEXT_PADDING * 2;\r\n};\r\n\r\nexport const getBoundTextMaxHeight = (\r\n container: ExcalidrawElement,\r\n boundTextElement: ExcalidrawTextElementWithContainer,\r\n) => {\r\n const { height } = container;\r\n if (isArrowElement(container)) {\r\n const containerHeight = height - BOUND_TEXT_PADDING * 8 * 2;\r\n if (containerHeight <= 0) {\r\n return boundTextElement.height;\r\n }\r\n return height;\r\n }\r\n if (container.type === \"ellipse\") {\r\n // The height of the largest rectangle inscribed inside an ellipse is\r\n // Math.round((ellipse.height / 2) * Math.sqrt(2)) which is derived from\r\n // equation of an ellipse - https://github.com/excalidraw/excalidraw/pull/6172\r\n return Math.round((height / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;\r\n }\r\n if (container.type === \"diamond\") {\r\n // The height of the largest rectangle inscribed inside a rhombus is\r\n // Math.round(height / 2) - https://github.com/excalidraw/excalidraw/pull/6265\r\n return Math.round(height / 2) - BOUND_TEXT_PADDING * 2;\r\n }\r\n return height - BOUND_TEXT_PADDING * 2;\r\n};\r\n\r\n/** retrieves text from text elements and concatenates to a single string */\r\nexport const getTextFromElements = (\r\n elements: readonly ExcalidrawElement[],\r\n separator = \"\\n\\n\",\r\n) => {\r\n const text = elements\r\n .reduce((acc: string[], element) => {\r\n if (isTextElement(element)) {\r\n acc.push(element.text);\r\n }\r\n return acc;\r\n }, [])\r\n .join(separator);\r\n return text;\r\n};\r\n", "import type { ExcalidrawTextContainer } from \"./types\";\n\nexport const originalContainerCache: {\n [id: ExcalidrawTextContainer[\"id\"]]:\n | {\n height: ExcalidrawTextContainer[\"height\"];\n }\n | undefined;\n} = {};\n\nexport const updateOriginalContainerCache = (\n id: ExcalidrawTextContainer[\"id\"],\n height: ExcalidrawTextContainer[\"height\"],\n) => {\n const data =\n originalContainerCache[id] || (originalContainerCache[id] = { height });\n data.height = height;\n return data;\n};\n\nexport const resetOriginalContainerCache = (\n id: ExcalidrawTextContainer[\"id\"],\n) => {\n if (originalContainerCache[id]) {\n delete originalContainerCache[id];\n }\n};\n\nexport const getOriginalContainerHeightFromCache = (\n id: ExcalidrawTextContainer[\"id\"],\n) => {\n return originalContainerCache[id]?.height ?? null;\n};\n", "import {\r\n BOUND_TEXT_PADDING,\r\n DEFAULT_FONT_SIZE,\r\n DEFAULT_FONT_FAMILY,\r\n getFontString,\r\n isTestEnv,\r\n normalizeEOL,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { FontString, ExcalidrawTextElement } from \"./types\";\r\n\r\nexport const measureText = (\r\n text: string,\r\n font: FontString,\r\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\r\n) => {\r\n const _text = text\r\n .split(\"\\n\")\r\n // replace empty lines with single space because leading/trailing empty\r\n // lines would be stripped from computation\r\n .map((x) => x || \" \")\r\n .join(\"\\n\");\r\n const fontSize = parseFloat(font);\r\n const height = getTextHeight(_text, fontSize, lineHeight);\r\n const width = getTextWidth(_text, font);\r\n return { width, height };\r\n};\r\n\r\nconst DUMMY_TEXT = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\".toLocaleUpperCase();\r\n\r\n// FIXME rename to getApproxMinContainerWidth\r\nexport const getApproxMinLineWidth = (\r\n font: FontString,\r\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\r\n) => {\r\n const maxCharWidth = getMaxCharWidth(font);\r\n if (maxCharWidth === 0) {\r\n return (\r\n measureText(DUMMY_TEXT.split(\"\").join(\"\\n\"), font, lineHeight).width +\r\n BOUND_TEXT_PADDING * 2\r\n );\r\n }\r\n return maxCharWidth + BOUND_TEXT_PADDING * 2;\r\n};\r\n\r\nexport const getMinTextElementWidth = (\r\n font: FontString,\r\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\r\n) => {\r\n return measureText(\"\", font, lineHeight).width + BOUND_TEXT_PADDING * 2;\r\n};\r\n\r\nexport const isMeasureTextSupported = () => {\r\n const width = getTextWidth(\r\n DUMMY_TEXT,\r\n getFontString({\r\n fontSize: DEFAULT_FONT_SIZE,\r\n fontFamily: DEFAULT_FONT_FAMILY,\r\n }),\r\n );\r\n return width > 0;\r\n};\r\n\r\nexport const normalizeText = (text: string) => {\r\n return (\r\n normalizeEOL(text)\r\n // replace tabs with spaces so they render and measure correctly\r\n .replace(/\\t/g, \" \")\r\n );\r\n};\r\n\r\nconst splitIntoLines = (text: string) => {\r\n return normalizeText(text).split(\"\\n\");\r\n};\r\n\r\n/**\r\n * To get unitless line-height (if unknown) we can calculate it by dividing\r\n * height-per-line by fontSize.\r\n */\r\nexport const detectLineHeight = (textElement: ExcalidrawTextElement) => {\r\n const lineCount = splitIntoLines(textElement.text).length;\r\n return (textElement.height /\r\n lineCount /\r\n textElement.fontSize) as ExcalidrawTextElement[\"lineHeight\"];\r\n};\r\n\r\n/**\r\n * We calculate the line height from the font size and the unitless line height,\r\n * aligning with the W3C spec.\r\n */\r\nexport const getLineHeightInPx = (\r\n fontSize: ExcalidrawTextElement[\"fontSize\"],\r\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\r\n) => {\r\n return fontSize * lineHeight;\r\n};\r\n\r\n// FIXME rename to getApproxMinContainerHeight\r\nexport const getApproxMinLineHeight = (\r\n fontSize: ExcalidrawTextElement[\"fontSize\"],\r\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\r\n) => {\r\n return getLineHeightInPx(fontSize, lineHeight) + BOUND_TEXT_PADDING * 2;\r\n};\r\n\r\nlet textMetricsProvider: TextMetricsProvider | undefined;\r\n\r\n/**\r\n * Set a custom text metrics provider.\r\n *\r\n * Useful for overriding the width calculation algorithm where canvas API is not available / desired.\r\n */\r\nexport const setCustomTextMetricsProvider = (provider: TextMetricsProvider) => {\r\n textMetricsProvider = provider;\r\n};\r\n\r\nexport interface TextMetricsProvider {\r\n getLineWidth(text: string, fontString: FontString): number;\r\n}\r\n\r\nclass CanvasTextMetricsProvider implements TextMetricsProvider {\r\n private canvas: HTMLCanvasElement;\r\n\r\n constructor() {\r\n this.canvas = document.createElement(\"canvas\");\r\n }\r\n\r\n /**\r\n * We need to use the advance width as that's the closest thing to the browser wrapping algo, hence using it for:\r\n * - text wrapping\r\n * - wysiwyg editor (+padding)\r\n *\r\n * > The advance width is the distance between the glyph's initial pen position and the next glyph's initial pen position.\r\n */\r\n public getLineWidth(text: string, fontString: FontString): number {\r\n const context = this.canvas.getContext(\"2d\")!;\r\n context.font = fontString;\r\n const metrics = context.measureText(text);\r\n const advanceWidth = metrics.width;\r\n\r\n // since in test env the canvas measureText algo\r\n // doesn't measure text and instead just returns number of\r\n // characters hence we assume that each letteris 10px\r\n if (isTestEnv()) {\r\n return advanceWidth * 10;\r\n }\r\n\r\n return advanceWidth;\r\n }\r\n}\r\n\r\nexport const getLineWidth = (text: string, font: FontString) => {\r\n if (!textMetricsProvider) {\r\n textMetricsProvider = new CanvasTextMetricsProvider();\r\n }\r\n\r\n return textMetricsProvider.getLineWidth(text, font);\r\n};\r\n\r\nexport const getTextWidth = (text: string, font: FontString) => {\r\n const lines = splitIntoLines(text);\r\n let width = 0;\r\n lines.forEach((line) => {\r\n width = Math.max(width, getLineWidth(line, font));\r\n });\r\n\r\n return width;\r\n};\r\n\r\nexport const getTextHeight = (\r\n text: string,\r\n fontSize: number,\r\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\r\n) => {\r\n const lineCount = splitIntoLines(text).length;\r\n return getLineHeightInPx(fontSize, lineHeight) * lineCount;\r\n};\r\n\r\nexport const charWidth = (() => {\r\n const cachedCharWidth: { [key: FontString]: Array<number> } = {};\r\n\r\n const calculate = (char: string, font: FontString) => {\r\n const unicode = char.charCodeAt(0);\r\n if (!cachedCharWidth[font]) {\r\n cachedCharWidth[font] = [];\r\n }\r\n if (!cachedCharWidth[font][unicode]) {\r\n const width = getLineWidth(char, font);\r\n cachedCharWidth[font][unicode] = width;\r\n }\r\n\r\n return cachedCharWidth[font][unicode];\r\n };\r\n\r\n const getCache = (font: FontString) => {\r\n return cachedCharWidth[font];\r\n };\r\n\r\n const clearCache = (font: FontString) => {\r\n cachedCharWidth[font] = [];\r\n };\r\n\r\n return {\r\n calculate,\r\n getCache,\r\n clearCache,\r\n };\r\n})();\r\n\r\nexport const getMinCharWidth = (font: FontString) => {\r\n const cache = charWidth.getCache(font);\r\n if (!cache) {\r\n return 0;\r\n }\r\n const cacheWithOutEmpty = cache.filter((val) => val !== undefined);\r\n\r\n return Math.min(...cacheWithOutEmpty);\r\n};\r\n\r\nexport const getMaxCharWidth = (font: FontString) => {\r\n const cache = charWidth.getCache(font);\r\n if (!cache) {\r\n return 0;\r\n }\r\n const cacheWithOutEmpty = cache.filter((val) => val !== undefined);\r\n return Math.max(...cacheWithOutEmpty);\r\n};\r\n", "import { isDevEnv, isTestEnv } from \"@excalidraw-modify/common\";\r\n\r\nimport { charWidth, getLineWidth } from \"./textMeasurements\";\r\n\r\nimport type { FontString } from \"./types\";\r\n\r\nlet cachedCjkRegex: RegExp | undefined;\r\nlet cachedLineBreakRegex: RegExp | undefined;\r\nlet cachedEmojiRegex: RegExp | undefined;\r\n\r\n/**\r\n * Test if a given text contains any CJK characters (including symbols, punctuation, etc,).\r\n */\r\nexport const containsCJK = (text: string) => {\r\n if (!cachedCjkRegex) {\r\n cachedCjkRegex = Regex.class(...Object.values(CJK));\r\n }\r\n\r\n return cachedCjkRegex.test(text);\r\n};\r\n\r\nconst getLineBreakRegex = () => {\r\n if (!cachedLineBreakRegex) {\r\n try {\r\n cachedLineBreakRegex = getLineBreakRegexAdvanced();\r\n } catch {\r\n cachedLineBreakRegex = getLineBreakRegexSimple();\r\n }\r\n }\r\n\r\n return cachedLineBreakRegex;\r\n};\r\n\r\nconst getEmojiRegex = () => {\r\n if (!cachedEmojiRegex) {\r\n cachedEmojiRegex = getEmojiRegexUnicode();\r\n }\r\n\r\n return cachedEmojiRegex;\r\n};\r\n\r\n/**\r\n * Common symbols used across different languages.\r\n */\r\nconst COMMON = {\r\n /**\r\n * Natural breaking points for any grammars.\r\n *\r\n * Hello world\r\n * \u2191 BREAK ALWAYS \" \" \u2192 [\"Hello\", \" \", \"world\"]\r\n * Hello-world\r\n * \u2191 BREAK AFTER \"-\" \u2192 [\"Hello-\", \"world\"]\r\n */\r\n WHITESPACE: /\\s/u,\r\n HYPHEN: /-/u,\r\n /**\r\n * Generally do not break, unless closed symbol is followed by an opening symbol.\r\n *\r\n * Also, western punctation is often used in modern Korean and expects to be treated\r\n * similarly to the CJK opening and closing symbols.\r\n *\r\n * Hello(\uD55C\uAE00)\u2192 [\"Hello\", \"(\uD55C\", \"\uAE00)\"]\r\n * \u2191 BREAK BEFORE \"(\"\r\n * \u2191 BREAK AFTER \")\"\r\n */\r\n OPENING: /<\\(\\[\\{/u,\r\n CLOSING: />\\)\\]\\}.,:;!\\?\u2026\\//u,\r\n};\r\n\r\n/**\r\n * Characters and symbols used in Chinese, Japanese and Korean.\r\n */\r\nconst CJK = {\r\n /**\r\n * Every CJK breaks before and after, unless it's paired with an opening or closing symbol.\r\n *\r\n * Does not include every possible char used in CJK texts, such as currency, parentheses or punctuation.\r\n */\r\n CHAR: /\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}\uFF40\uFF07\uFF3E\u3003\u3030\u3006\uFF03\uFF06\uFF0A\uFF0B\uFF0D\u30FC\uFF0F\uFF3C\uFF1D\uFF5C\uFFE4\u3012\uFFE2\uFFE3/u,\r\n /**\r\n * Opening and closing CJK punctuation breaks before and after all such characters (in case of many),\r\n * and creates pairs with neighboring characters.\r\n *\r\n * Hello \u305F\u3002\u2192 [\"Hello\", \"\u305F\u3002\"]\r\n * \u2191 DON'T BREAK \"\u305F\u3002\"\r\n * * Hello\u300C\u305F\u300D World \u2192 [\"Hello\", \"\u300C\u305F\u300D\", \"World\"]\r\n * \u2191 DON'T BREAK \"\u300C\u305F\"\r\n * \u2191 DON'T BREAK \"\u305F\"\r\n * \u2191 BREAK BEFORE \"\u300C\"\r\n * \u2191 BREAK AFTER \"\u300D\"\r\n */\r\n // eslint-disable-next-line prettier/prettier\r\n OPENING:/\uFF08\uFF3B\uFF5B\u3008\u300A\uFF5F\uFF62\u300C\u300E\u3010\u3016\u3014\u3018\u301A\uFF1C\u301D/u,\r\n CLOSING: /\uFF09\uFF3D\uFF5D\u3009\u300B\uFF60\uFF63\u300D\u300F\u3011\u3017\u3015\u3019\u301B\uFF1E\u3002\uFF0E\uFF0C\u3001\u301F\u2025\uFF1F\uFF01\uFF1A\uFF1B\u30FB\u301C\u301E/u,\r\n /**\r\n * Currency symbols break before, not after\r\n *\r\n * Price\uFFE5100 \u2192 [\"Price\", \"\uFFE5100\"]\r\n * \u2191 BREAK BEFORE \"\uFFE5\"\r\n */\r\n CURRENCY: /\uFFE5\uFFE6\uFFE1\uFFE0\uFF04/u,\r\n};\r\n\r\nconst EMOJI = {\r\n FLAG: /\\p{RI}\\p{RI}/u,\r\n JOINER:\r\n /(?:\\p{Emoji_Modifier}|\\uFE0F\\u20E3?|[\\u{E0020}-\\u{E007E}]+\\u{E007F})?/u,\r\n ZWJ: /\\u200D/u,\r\n ANY: /[\\p{Emoji}]/u,\r\n MOST: /[\\p{Extended_Pictographic}\\p{Emoji_Presentation}]/u,\r\n};\r\n\r\n/**\r\n * Simple fallback for browsers (mainly Safari < 16.4) that don't support \"Lookbehind assertion\".\r\n *\r\n * Browser support as of 10/2024:\r\n * - 91% Lookbehind assertion https://caniuse.com/mdn-javascript_regular_expressions_lookbehind_assertion\r\n * - 94% Unicode character class escape https://caniuse.com/mdn-javascript_regular_expressions_unicode_character_class_escape\r\n *\r\n * Does not include advanced CJK breaking rules, but covers most of the core cases, especially for latin.\r\n */\r\nconst getLineBreakRegexSimple = () =>\r\n Regex.or(\r\n getEmojiRegex(),\r\n Break.On(COMMON.HYPHEN, COMMON.WHITESPACE, CJK.CHAR),\r\n );\r\n\r\n/**\r\n * Specifies the line breaking rules based for alphabetic-based languages,\r\n * Chinese, Japanese, Korean and Emojis.\r\n *\r\n * \"Hello-world\" \u2192 [\"Hello-\", \"world\"]\r\n * \"Hello \u300C\u4E16\u754C\u3002\u300D\uD83C\uDF0E\uD83D\uDDFA\" \u2192 [\"Hello\", \" \", \"\u300C\u4E16\", \"\u754C\u3002\u300D\", \"\uD83C\uDF0E\", \"\uD83D\uDDFA\"]\r\n */\r\nconst getLineBreakRegexAdvanced = () =>\r\n Regex.or(\r\n // Unicode-defined regex for (multi-codepoint) Emojis\r\n getEmojiRegex(),\r\n // Rules for whitespace and hyphen\r\n Break.Before(COMMON.WHITESPACE).Build(),\r\n Break.After(COMMON.WHITESPACE, COMMON.HYPHEN).Build(),\r\n // Rules for CJK (chars, symbols, currency)\r\n Break.Before(CJK.CHAR, CJK.CURRENCY)\r\n .NotPrecededBy(COMMON.OPENING, CJK.OPENING)\r\n .Build(),\r\n Break.After(CJK.CHAR)\r\n .NotFollowedBy(COMMON.HYPHEN, COMMON.CLOSING, CJK.CLOSING)\r\n .Build(),\r\n // Rules for opening and closing punctuation\r\n Break.BeforeMany(CJK.OPENING).NotPrecededBy(COMMON.OPENING).Build(),\r\n Break.AfterMany(CJK.CLOSING).NotFollowedBy(COMMON.CLOSING).Build(),\r\n Break.AfterMany(COMMON.CLOSING).FollowedBy(COMMON.OPENING).Build(),\r\n );\r\n\r\n/**\r\n * Matches various emoji types.\r\n *\r\n * 1. basic emojis (\uD83D\uDE00, \uD83C\uDF0D)\r\n * 2. flags (\uD83C\uDDE8\uD83C\uDDFF)\r\n * 3. multi-codepoint emojis:\r\n * - skin tones (\uD83D\uDC4D\uD83C\uDFFD)\r\n * - variation selectors (\u2602\uFE0F)\r\n * - keycaps (1\uFE0F\u20E3)\r\n * - tag sequences (\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F)\r\n * - emoji sequences (\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66, \uD83D\uDC69\u200D\uD83D\uDE80, \uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08)\r\n *\r\n * Unicode points:\r\n * - \\uFE0F: presentation selector\r\n * - \\u20E3: enclosing keycap\r\n * - \\u200D: zero width joiner\r\n * - \\u{E0020}-\\u{E007E}: tags\r\n * - \\u{E007F}: cancel tag\r\n *\r\n * @see https://unicode.org/reports/tr51/#EBNF_and_Regex, with changes:\r\n * - replaced \\p{Emoji} with [\\p{Extended_Pictographic}\\p{Emoji_Presentation}], see more in `should tokenize emojis mixed with mixed text` test\r\n * - replaced \\p{Emod} with \\p{Emoji_Modifier} as some engines do not understand the abbreviation (i.e. https://devina.io/redos-checker)\r\n */\r\nconst getEmojiRegexUnicode = () =>\r\n Regex.group(\r\n Regex.or(\r\n EMOJI.FLAG,\r\n Regex.and(\r\n EMOJI.MOST,\r\n EMOJI.JOINER,\r\n Regex.build(\r\n `(?:${EMOJI.ZWJ.source}(?:${EMOJI.FLAG.source}|${EMOJI.ANY.source}${EMOJI.JOINER.source}))*`,\r\n ),\r\n ),\r\n ),\r\n );\r\n\r\n/**\r\n * Regex utilities for unicode character classes.\r\n */\r\nconst Regex = {\r\n /**\r\n * Builds a regex from a string.\r\n */\r\n build: (regex: string): RegExp => new RegExp(regex, \"u\"),\r\n /**\r\n * Joins regexes into a single string.\r\n */\r\n join: (...regexes: RegExp[]): string => regexes.map((x) => x.source).join(\"\"),\r\n /**\r\n * Joins regexes into a single regex as with \"and\" operator.\r\n */\r\n and: (...regexes: RegExp[]): RegExp => Regex.build(Regex.join(...regexes)),\r\n /**\r\n * Joins regexes into a single regex with \"or\" operator.\r\n */\r\n or: (...regexes: RegExp[]): RegExp =>\r\n Regex.build(regexes.map((x) => x.source).join(\"|\")),\r\n /**\r\n * Puts regexes into a matching group.\r\n */\r\n group: (...regexes: RegExp[]): RegExp =>\r\n Regex.build(`(${Regex.join(...regexes)})`),\r\n /**\r\n * Puts regexes into a character class.\r\n */\r\n class: (...regexes: RegExp[]): RegExp =>\r\n Regex.build(`[${Regex.join(...regexes)}]`),\r\n};\r\n\r\n/**\r\n * Human-readable lookahead and lookbehind utilities for defining line break\r\n * opportunities between pairs of character classes.\r\n */\r\nconst Break = {\r\n /**\r\n * Break on the given class of characters.\r\n */\r\n On: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n return Regex.build(`([${joined}])`);\r\n },\r\n /**\r\n * Break before the given class of characters.\r\n */\r\n Before: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n const builder = () => Regex.build(`(?=[${joined}])`);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"FollowedBy\"\r\n >;\r\n },\r\n /**\r\n * Break after the given class of characters.\r\n */\r\n After: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n const builder = () => Regex.build(`(?<=[${joined}])`);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"PreceededBy\"\r\n >;\r\n },\r\n /**\r\n * Break before one or multiple characters of the same class.\r\n */\r\n BeforeMany: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n const builder = () => Regex.build(`(?<![${joined}])(?=[${joined}])`);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"FollowedBy\"\r\n >;\r\n },\r\n /**\r\n * Break after one or multiple character from the same class.\r\n */\r\n AfterMany: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n const builder = () => Regex.build(`(?<=[${joined}])(?![${joined}])`);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"PreceededBy\"\r\n >;\r\n },\r\n /**\r\n * Do not break before the given class of characters.\r\n */\r\n NotBefore: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n const builder = () => Regex.build(`(?![${joined}])`);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"NotFollowedBy\"\r\n >;\r\n },\r\n /**\r\n * Do not break after the given class of characters.\r\n */\r\n NotAfter: (...regexes: RegExp[]) => {\r\n const joined = Regex.join(...regexes);\r\n const builder = () => Regex.build(`(?<![${joined}])`);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"NotPrecededBy\"\r\n >;\r\n },\r\n Chain: (rootBuilder: () => RegExp) => ({\r\n /**\r\n * Build the root regex.\r\n */\r\n Build: rootBuilder,\r\n /**\r\n * Specify additional class of characters that should precede the root regex.\r\n */\r\n PreceededBy: (...regexes: RegExp[]) => {\r\n const root = rootBuilder();\r\n const preceeded = Break.After(...regexes).Build();\r\n const builder = () => Regex.and(preceeded, root);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"PreceededBy\"\r\n >;\r\n },\r\n /**\r\n * Specify additional class of characters that should follow the root regex.\r\n */\r\n FollowedBy: (...regexes: RegExp[]) => {\r\n const root = rootBuilder();\r\n const followed = Break.Before(...regexes).Build();\r\n const builder = () => Regex.and(root, followed);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"FollowedBy\"\r\n >;\r\n },\r\n /**\r\n * Specify additional class of characters that should not precede the root regex.\r\n */\r\n NotPrecededBy: (...regexes: RegExp[]) => {\r\n const root = rootBuilder();\r\n const notPreceeded = Break.NotAfter(...regexes).Build();\r\n const builder = () => Regex.and(notPreceeded, root);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"NotPrecededBy\"\r\n >;\r\n },\r\n /**\r\n * Specify additional class of characters that should not follow the root regex.\r\n */\r\n NotFollowedBy: (...regexes: RegExp[]) => {\r\n const root = rootBuilder();\r\n const notFollowed = Break.NotBefore(...regexes).Build();\r\n const builder = () => Regex.and(root, notFollowed);\r\n return Break.Chain(builder) as Omit<\r\n ReturnType<typeof Break.Chain>,\r\n \"NotFollowedBy\"\r\n >;\r\n },\r\n }),\r\n};\r\n\r\n/**\r\n * Breaks the line into the tokens based on the found line break opporutnities.\r\n */\r\nexport const parseTokens = (line: string) => {\r\n const breakLineRegex = getLineBreakRegex();\r\n\r\n // normalizing to single-codepoint composed chars due to canonical equivalence\r\n // of multi-codepoint versions for chars like \u010D, \u3067 (~ so that we don't break a line in between c and \u02C7)\r\n // filtering due to multi-codepoint chars like \uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66, \uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDDB0\r\n return line.normalize(\"NFC\").split(breakLineRegex).filter(Boolean);\r\n};\r\n\r\n/**\r\n * Wraps the original text into the lines based on the given width.\r\n */\r\nexport const wrapText = (\r\n text: string,\r\n font: FontString,\r\n maxWidth: number,\r\n): string => {\r\n // if maxWidth is not finite or NaN which can happen in case of bugs in\r\n // computation, we need to make sure we don't continue as we'll end up\r\n // in an infinite loop\r\n if (!Number.isFinite(maxWidth) || maxWidth < 0) {\r\n return text;\r\n }\r\n\r\n const lines: Array<string> = [];\r\n const originalLines = text.split(\"\\n\");\r\n\r\n for (const originalLine of originalLines) {\r\n const currentLineWidth = getLineWidth(originalLine, font);\r\n\r\n if (currentLineWidth <= maxWidth) {\r\n lines.push(originalLine);\r\n continue;\r\n }\r\n\r\n const wrappedLine = wrapLine(originalLine, font, maxWidth);\r\n lines.push(...wrappedLine);\r\n }\r\n\r\n return lines.join(\"\\n\");\r\n};\r\n\r\n/**\r\n * Wraps the original line into the lines based on the given width.\r\n */\r\nconst wrapLine = (\r\n line: string,\r\n font: FontString,\r\n maxWidth: number,\r\n): string[] => {\r\n const lines: Array<string> = [];\r\n const tokens = parseTokens(line);\r\n const tokenIterator = tokens[Symbol.iterator]();\r\n\r\n let currentLine = \"\";\r\n let currentLineWidth = 0;\r\n\r\n let iterator = tokenIterator.next();\r\n\r\n while (!iterator.done) {\r\n const token = iterator.value;\r\n const testLine = currentLine + token;\r\n\r\n // cache single codepoint whitespace, CJK or emoji width calc. as kerning should not apply here\r\n const testLineWidth = isSingleCharacter(token)\r\n ? currentLineWidth + charWidth.calculate(token, font)\r\n : getLineWidth(testLine, font);\r\n\r\n // build up the current line, skipping length check for possibly trailing whitespaces\r\n if (/\\s/.test(token) || testLineWidth <= maxWidth) {\r\n currentLine = testLine;\r\n currentLineWidth = testLineWidth;\r\n iterator = tokenIterator.next();\r\n continue;\r\n }\r\n\r\n // current line is empty => just the token (word) is longer than `maxWidth` and needs to be wrapped\r\n if (!currentLine) {\r\n const wrappedWord = wrapWord(token, font, maxWidth);\r\n const trailingLine = wrappedWord[wrappedWord.length - 1] ?? \"\";\r\n const precedingLines = wrappedWord.slice(0, -1);\r\n\r\n lines.push(...precedingLines);\r\n\r\n // trailing line of the wrapped word might still be joined with next token/s\r\n currentLine = trailingLine;\r\n currentLineWidth = getLineWidth(trailingLine, font);\r\n iterator = tokenIterator.next();\r\n } else {\r\n // push & reset, but don't iterate on the next token, as we didn't use it yet!\r\n lines.push(currentLine.trimEnd());\r\n\r\n // purposefully not iterating and not setting `currentLine` to `token`, so that we could use a simple !currentLine check above\r\n currentLine = \"\";\r\n currentLineWidth = 0;\r\n }\r\n }\r\n\r\n // iterator done, push the trailing line if exists\r\n if (currentLine) {\r\n const trailingLine = trimLine(currentLine, font, maxWidth);\r\n lines.push(trailingLine);\r\n }\r\n\r\n return lines;\r\n};\r\n\r\n/**\r\n * Wraps the word into the lines based on the given width.\r\n */\r\nconst wrapWord = (\r\n word: string,\r\n font: FontString,\r\n maxWidth: number,\r\n): Array<string> => {\r\n // multi-codepoint emojis are already broken apart and shouldn't be broken further\r\n if (getEmojiRegex().test(word)) {\r\n return [word];\r\n }\r\n\r\n satisfiesWordInvariant(word);\r\n\r\n const lines: Array<string> = [];\r\n const chars = Array.from(word);\r\n\r\n let currentLine = \"\";\r\n let currentLineWidth = 0;\r\n\r\n for (const char of chars) {\r\n const _charWidth = charWidth.calculate(char, font);\r\n const testLineWidth = currentLineWidth + _charWidth;\r\n\r\n if (testLineWidth <= maxWidth) {\r\n currentLine = currentLine + char;\r\n currentLineWidth = testLineWidth;\r\n continue;\r\n }\r\n\r\n if (currentLine) {\r\n lines.push(currentLine);\r\n }\r\n\r\n currentLine = char;\r\n currentLineWidth = _charWidth;\r\n }\r\n\r\n if (currentLine) {\r\n lines.push(currentLine);\r\n }\r\n\r\n return lines;\r\n};\r\n\r\n/**\r\n * Similarly to browsers, does not trim all trailing whitespaces, but only those exceeding the `maxWidth`.\r\n */\r\nconst trimLine = (line: string, font: FontString, maxWidth: number) => {\r\n const shouldTrimWhitespaces = getLineWidth(line, font) > maxWidth;\r\n\r\n if (!shouldTrimWhitespaces) {\r\n return line;\r\n }\r\n\r\n // defensively default to `trimeEnd` in case the regex does not match\r\n let [, trimmedLine, whitespaces] = line.match(/^(.+?)(\\s+)$/) ?? [\r\n line,\r\n line.trimEnd(),\r\n \"\",\r\n ];\r\n\r\n let trimmedLineWidth = getLineWidth(trimmedLine, font);\r\n\r\n for (const whitespace of Array.from(whitespaces)) {\r\n const _charWidth = charWidth.calculate(whitespace, font);\r\n const testLineWidth = trimmedLineWidth + _charWidth;\r\n\r\n if (testLineWidth > maxWidth) {\r\n break;\r\n }\r\n\r\n trimmedLine = trimmedLine + whitespace;\r\n trimmedLineWidth = testLineWidth;\r\n }\r\n\r\n return trimmedLine;\r\n};\r\n\r\n/**\r\n * Check if the given string is a single character.\r\n *\r\n * Handles multi-byte chars (\u00E9, \u4E2D) and purposefully does not handle multi-codepoint char (\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66, \uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDDB0).\r\n */\r\nconst isSingleCharacter = (maybeSingleCharacter: string) => {\r\n return (\r\n maybeSingleCharacter.codePointAt(0) !== undefined &&\r\n maybeSingleCharacter.codePointAt(1) === undefined\r\n );\r\n};\r\n\r\n/**\r\n * Invariant for the word wrapping algorithm.\r\n */\r\nconst satisfiesWordInvariant = (word: string) => {\r\n if (isTestEnv() || isDevEnv()) {\r\n if (/\\s/.test(word)) {\r\n throw new Error(\"Word should not contain any whitespaces!\");\r\n }\r\n }\r\n};\r\n", "import {\r\n curvePointDistance,\r\n distanceToLineSegment,\r\n pointRotateRads,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport { ellipse, ellipseDistanceFromPoint } from \"@excalidraw-modify/math/ellipse\";\r\n\r\nimport type { GlobalPoint, Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n deconstructDiamondElement,\r\n deconstructLinearOrFreeDrawElement,\r\n deconstructRectanguloidElement,\r\n} from \"./utils\";\r\n\r\nimport { elementCenterPoint } from \"./bounds\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawDiamondElement,\r\n ExcalidrawElement,\r\n ExcalidrawEllipseElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawRectanguloidElement,\r\n} from \"./types\";\r\n\r\nexport const distanceToElement = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n p: GlobalPoint,\r\n): number => {\r\n switch (element.type) {\r\n case \"selection\":\r\n case \"rectangle\":\r\n case \"image\":\r\n case \"text\":\r\n case \"iframe\":\r\n case \"embeddable\":\r\n case \"frame\":\r\n case \"magicframe\":\r\n return distanceToRectanguloidElement(element, elementsMap, p);\r\n case \"diamond\":\r\n return distanceToDiamondElement(element, elementsMap, p);\r\n case \"ellipse\":\r\n return distanceToEllipseElement(element, elementsMap, p);\r\n case \"line\":\r\n case \"arrow\":\r\n case \"freedraw\":\r\n return distanceToLinearOrFreeDraElement(element, p);\r\n }\r\n};\r\n\r\n/**\r\n * Returns the distance of a point and the provided rectangular-shaped element,\r\n * accounting for roundness and rotation\r\n *\r\n * @param element The rectanguloid element\r\n * @param p The point to consider\r\n * @returns The eucledian distance to the outline of the rectanguloid element\r\n */\r\nconst distanceToRectanguloidElement = (\r\n element: ExcalidrawRectanguloidElement,\r\n elementsMap: ElementsMap,\r\n p: GlobalPoint,\r\n) => {\r\n const center = elementCenterPoint(element, elementsMap);\r\n // To emulate a rotated rectangle we rotate the point in the inverse angle\r\n // instead. It's all the same distance-wise.\r\n const rotatedPoint = pointRotateRads(p, center, -element.angle as Radians);\r\n\r\n // Get the element's building components we can test against\r\n const [sides, corners] = deconstructRectanguloidElement(element);\r\n\r\n return Math.min(\r\n ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)),\r\n ...corners\r\n .map((a) => curvePointDistance(a, rotatedPoint))\r\n .filter((d): d is number => d !== null),\r\n );\r\n};\r\n\r\n/**\r\n * Returns the distance of a point and the provided diamond element, accounting\r\n * for roundness and rotation\r\n *\r\n * @param element The diamond element\r\n * @param p The point to consider\r\n * @returns The eucledian distance to the outline of the diamond\r\n */\r\nconst distanceToDiamondElement = (\r\n element: ExcalidrawDiamondElement,\r\n elementsMap: ElementsMap,\r\n p: GlobalPoint,\r\n): number => {\r\n const center = elementCenterPoint(element, elementsMap);\r\n\r\n // Rotate the point to the inverse direction to simulate the rotated diamond\r\n // points. It's all the same distance-wise.\r\n const rotatedPoint = pointRotateRads(p, center, -element.angle as Radians);\r\n\r\n const [sides, curves] = deconstructDiamondElement(element);\r\n\r\n return Math.min(\r\n ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)),\r\n ...curves\r\n .map((a) => curvePointDistance(a, rotatedPoint))\r\n .filter((d): d is number => d !== null),\r\n );\r\n};\r\n\r\n/**\r\n * Returns the distance of a point and the provided ellipse element, accounting\r\n * for roundness and rotation\r\n *\r\n * @param element The ellipse element\r\n * @param p The point to consider\r\n * @returns The eucledian distance to the outline of the ellipse\r\n */\r\nconst distanceToEllipseElement = (\r\n element: ExcalidrawEllipseElement,\r\n elementsMap: ElementsMap,\r\n p: GlobalPoint,\r\n): number => {\r\n const center = elementCenterPoint(element, elementsMap);\r\n return ellipseDistanceFromPoint(\r\n // Instead of rotating the ellipse, rotate the point to the inverse angle\r\n pointRotateRads(p, center, -element.angle as Radians),\r\n ellipse(center, element.width / 2, element.height / 2),\r\n );\r\n};\r\n\r\nconst distanceToLinearOrFreeDraElement = (\r\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\r\n p: GlobalPoint,\r\n) => {\r\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\r\n return Math.min(\r\n ...lines.map((s) => distanceToLineSegment(p, s)),\r\n ...curves.map((a) => curvePointDistance(a, p)),\r\n );\r\n};\r\n", "import {\r\n invariant,\r\n isDevEnv,\r\n isTestEnv,\r\n type Bounds,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport {\r\n pointFrom,\r\n pointFromVector,\r\n pointRotateRads,\r\n pointScaleFromOrigin,\r\n pointsEqual,\r\n triangleIncludesPoint,\r\n vectorCross,\r\n vectorFromPoint,\r\n vectorScale,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type {\r\n LocalPoint,\r\n GlobalPoint,\r\n Triangle,\r\n Vector,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport { getCenterForBounds } from \"./bounds\";\r\n\r\nimport type { ExcalidrawBindableElement } from \"./types\";\r\n\r\nexport const HEADING_RIGHT = [1, 0] as Heading;\r\nexport const HEADING_DOWN = [0, 1] as Heading;\r\nexport const HEADING_LEFT = [-1, 0] as Heading;\r\nexport const HEADING_UP = [0, -1] as Heading;\r\nexport type Heading = [1, 0] | [0, 1] | [-1, 0] | [0, -1];\r\n\r\nexport const vectorToHeading = (vec: Vector): Heading => {\r\n const [x, y] = vec;\r\n const absX = Math.abs(x);\r\n const absY = Math.abs(y);\r\n if (x > absY) {\r\n return HEADING_RIGHT;\r\n } else if (x <= -absY) {\r\n return HEADING_LEFT;\r\n } else if (y > absX) {\r\n return HEADING_DOWN;\r\n }\r\n return HEADING_UP;\r\n};\r\n\r\nexport const headingForPoint = <P extends GlobalPoint | LocalPoint>(\r\n p: P,\r\n o: P,\r\n) => vectorToHeading(vectorFromPoint<P>(p, o));\r\n\r\nexport const headingForPointIsHorizontal = <P extends GlobalPoint | LocalPoint>(\r\n p: P,\r\n o: P,\r\n) => headingIsHorizontal(headingForPoint<P>(p, o));\r\n\r\nexport const compareHeading = (a: Heading, b: Heading) =>\r\n a[0] === b[0] && a[1] === b[1];\r\n\r\nexport const headingIsHorizontal = (a: Heading) =>\r\n compareHeading(a, HEADING_RIGHT) || compareHeading(a, HEADING_LEFT);\r\n\r\nexport const headingIsVertical = (a: Heading) => !headingIsHorizontal(a);\r\n\r\nconst headingForPointFromDiamondElement = (\r\n element: Readonly<ExcalidrawBindableElement>,\r\n aabb: Readonly<Bounds>,\r\n point: Readonly<GlobalPoint>,\r\n): Heading => {\r\n const midPoint = getCenterForBounds(aabb);\r\n\r\n if (isDevEnv() || isTestEnv()) {\r\n invariant(\r\n element.width > 0 && element.height > 0,\r\n \"Diamond element has no width or height\",\r\n );\r\n invariant(\r\n !pointsEqual(midPoint, point),\r\n \"The point is too close to the element mid point to determine heading\",\r\n );\r\n }\r\n\r\n const SHRINK = 0.95; // Rounded elements tolerance\r\n const top = pointFromVector(\r\n vectorScale(\r\n vectorFromPoint(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x + element.width / 2, element.y),\r\n midPoint,\r\n element.angle,\r\n ),\r\n midPoint,\r\n ),\r\n SHRINK,\r\n ),\r\n midPoint,\r\n );\r\n const right = pointFromVector(\r\n vectorScale(\r\n vectorFromPoint(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + element.width,\r\n element.y + element.height / 2,\r\n ),\r\n midPoint,\r\n element.angle,\r\n ),\r\n midPoint,\r\n ),\r\n SHRINK,\r\n ),\r\n midPoint,\r\n );\r\n const bottom = pointFromVector(\r\n vectorScale(\r\n vectorFromPoint(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(\r\n element.x + element.width / 2,\r\n element.y + element.height,\r\n ),\r\n midPoint,\r\n element.angle,\r\n ),\r\n midPoint,\r\n ),\r\n SHRINK,\r\n ),\r\n midPoint,\r\n );\r\n const left = pointFromVector(\r\n vectorScale(\r\n vectorFromPoint(\r\n pointRotateRads(\r\n pointFrom<GlobalPoint>(element.x, element.y + element.height / 2),\r\n midPoint,\r\n element.angle,\r\n ),\r\n midPoint,\r\n ),\r\n SHRINK,\r\n ),\r\n midPoint,\r\n );\r\n\r\n // Corners\r\n if (\r\n vectorCross(vectorFromPoint(point, top), vectorFromPoint(top, right)) <=\r\n 0 &&\r\n vectorCross(vectorFromPoint(point, top), vectorFromPoint(top, left)) > 0\r\n ) {\r\n return headingForPoint(top, midPoint);\r\n } else if (\r\n vectorCross(\r\n vectorFromPoint(point, right),\r\n vectorFromPoint(right, bottom),\r\n ) <= 0 &&\r\n vectorCross(vectorFromPoint(point, right), vectorFromPoint(right, top)) > 0\r\n ) {\r\n return headingForPoint(right, midPoint);\r\n } else if (\r\n vectorCross(\r\n vectorFromPoint(point, bottom),\r\n vectorFromPoint(bottom, left),\r\n ) <= 0 &&\r\n vectorCross(\r\n vectorFromPoint(point, bottom),\r\n vectorFromPoint(bottom, right),\r\n ) > 0\r\n ) {\r\n return headingForPoint(bottom, midPoint);\r\n } else if (\r\n vectorCross(vectorFromPoint(point, left), vectorFromPoint(left, top)) <=\r\n 0 &&\r\n vectorCross(vectorFromPoint(point, left), vectorFromPoint(left, bottom)) > 0\r\n ) {\r\n return headingForPoint(left, midPoint);\r\n }\r\n\r\n // Sides\r\n if (\r\n vectorCross(\r\n vectorFromPoint(point, midPoint),\r\n vectorFromPoint(top, midPoint),\r\n ) <= 0 &&\r\n vectorCross(\r\n vectorFromPoint(point, midPoint),\r\n vectorFromPoint(right, midPoint),\r\n ) > 0\r\n ) {\r\n const p = element.width > element.height ? top : right;\r\n return headingForPoint(p, midPoint);\r\n } else if (\r\n vectorCross(\r\n vectorFromPoint(point, midPoint),\r\n vectorFromPoint(right, midPoint),\r\n ) <= 0 &&\r\n vectorCross(\r\n vectorFromPoint(point, midPoint),\r\n vectorFromPoint(bottom, midPoint),\r\n ) > 0\r\n ) {\r\n const p = element.width > element.height ? bottom : right;\r\n return headingForPoint(p, midPoint);\r\n } else if (\r\n vectorCross(\r\n vectorFromPoint(point, midPoint),\r\n vectorFromPoint(bottom, midPoint),\r\n ) <= 0 &&\r\n vectorCross(\r\n vectorFromPoint(point, midPoint),\r\n vectorFromPoint(left, midPoint),\r\n ) > 0\r\n ) {\r\n const p = element.width > element.height ? bottom : left;\r\n return headingForPoint(p, midPoint);\r\n }\r\n\r\n const p = element.width > element.height ? top : left;\r\n return headingForPoint(p, midPoint);\r\n};\r\n\r\n// Gets the heading for the point by creating a bounding box around the rotated\r\n// close fitting bounding box, then creating 4 search cones around the center of\r\n// the external bbox.\r\nexport const headingForPointFromElement = <Point extends GlobalPoint>(\r\n element: Readonly<ExcalidrawBindableElement>,\r\n aabb: Readonly<Bounds>,\r\n p: Readonly<Point>,\r\n): Heading => {\r\n const SEARCH_CONE_MULTIPLIER = 2;\r\n\r\n const midPoint = getCenterForBounds(aabb);\r\n\r\n if (element.type === \"diamond\") {\r\n return headingForPointFromDiamondElement(element, aabb, p);\r\n }\r\n\r\n const topLeft = pointScaleFromOrigin(\r\n pointFrom(aabb[0], aabb[1]),\r\n midPoint,\r\n SEARCH_CONE_MULTIPLIER,\r\n ) as Point;\r\n const topRight = pointScaleFromOrigin(\r\n pointFrom(aabb[2], aabb[1]),\r\n midPoint,\r\n SEARCH_CONE_MULTIPLIER,\r\n ) as Point;\r\n const bottomLeft = pointScaleFromOrigin(\r\n pointFrom(aabb[0], aabb[3]),\r\n midPoint,\r\n SEARCH_CONE_MULTIPLIER,\r\n ) as Point;\r\n const bottomRight = pointScaleFromOrigin(\r\n pointFrom(aabb[2], aabb[3]),\r\n midPoint,\r\n SEARCH_CONE_MULTIPLIER,\r\n ) as Point;\r\n\r\n return triangleIncludesPoint<Point>(\r\n [topLeft, topRight, midPoint] as Triangle<Point>,\r\n p,\r\n )\r\n ? HEADING_UP\r\n : triangleIncludesPoint<Point>(\r\n [topRight, bottomRight, midPoint] as Triangle<Point>,\r\n p,\r\n )\r\n ? HEADING_RIGHT\r\n : triangleIncludesPoint<Point>(\r\n [bottomRight, bottomLeft, midPoint] as Triangle<Point>,\r\n p,\r\n )\r\n ? HEADING_DOWN\r\n : HEADING_LEFT;\r\n};\r\n\r\nexport const flipHeading = (h: Heading): Heading =>\r\n [\r\n h[0] === 0 ? 0 : h[0] > 0 ? -1 : 1,\r\n h[1] === 0 ? 0 : h[1] > 0 ? -1 : 1,\r\n ] as Heading;\r\n", "import {\r\n getSizeFromPoints,\r\n randomInteger,\r\n getUpdatedTimestamp,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport type { Mutable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport { ShapeCache } from \"./shape\";\r\n\r\nimport { updateElbowArrowPoints } from \"./elbowArrow\";\r\n\r\nimport { isElbowArrow } from \"./typeChecks\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawElbowArrowElement,\r\n ExcalidrawElement,\r\n NonDeletedSceneElementsMap,\r\n} from \"./types\";\r\n\r\nexport type ElementUpdate<TElement extends ExcalidrawElement> = Omit<\r\n Partial<TElement>,\r\n \"id\" | \"updated\"\r\n>;\r\n\r\n/**\r\n * This function tracks updates of text elements for the purposes for collaboration.\r\n * The version is used to compare updates when more than one user is working in\r\n * the same drawing.\r\n *\r\n * WARNING: this won't trigger the component to update, so if you need to trigger component update,\r\n * use `scene.mutateElement` or `ExcalidrawImperativeAPI.mutateElement` instead.\r\n */\r\nexport const mutateElement = <TElement extends Mutable<ExcalidrawElement>>(\r\n element: TElement,\r\n elementsMap: ElementsMap,\r\n updates: ElementUpdate<TElement>,\r\n options?: {\r\n isDragging?: boolean;\r\n },\r\n) => {\r\n let didChange = false;\r\n\r\n // casting to any because can't use `in` operator\r\n // (see https://github.com/microsoft/TypeScript/issues/21732)\r\n const { points, fixedSegments, fileId } = updates as any;\r\n\r\n if (\r\n isElbowArrow(element) &&\r\n (Object.keys(updates).length === 0 || // normalization case\r\n typeof points !== \"undefined\" || // repositioning\r\n typeof fixedSegments !== \"undefined\") // segment fixing\r\n ) {\r\n updates = {\r\n ...updates,\r\n angle: 0 as Radians,\r\n ...updateElbowArrowPoints(\r\n {\r\n ...element,\r\n x: updates.x || element.x,\r\n y: updates.y || element.y,\r\n },\r\n elementsMap as NonDeletedSceneElementsMap,\r\n updates as ElementUpdate<ExcalidrawElbowArrowElement>,\r\n options,\r\n ),\r\n };\r\n } else if (typeof points !== \"undefined\") {\r\n updates = { ...getSizeFromPoints(points), ...updates };\r\n }\r\n\r\n for (const key in updates) {\r\n const value = (updates as any)[key];\r\n if (typeof value !== \"undefined\") {\r\n if (\r\n (element as any)[key] === value &&\r\n // if object, always update because its attrs could have changed\r\n // (except for specific keys we handle below)\r\n (typeof value !== \"object\" ||\r\n value === null ||\r\n key === \"groupIds\" ||\r\n key === \"scale\")\r\n ) {\r\n continue;\r\n }\r\n\r\n if (key === \"scale\") {\r\n const prevScale = (element as any)[key];\r\n const nextScale = value;\r\n if (prevScale[0] === nextScale[0] && prevScale[1] === nextScale[1]) {\r\n continue;\r\n }\r\n } else if (key === \"points\") {\r\n const prevPoints = (element as any)[key];\r\n const nextPoints = value;\r\n if (prevPoints.length === nextPoints.length) {\r\n let didChangePoints = false;\r\n let index = prevPoints.length;\r\n while (--index) {\r\n const prevPoint = prevPoints[index];\r\n const nextPoint = nextPoints[index];\r\n if (\r\n prevPoint[0] !== nextPoint[0] ||\r\n prevPoint[1] !== nextPoint[1]\r\n ) {\r\n didChangePoints = true;\r\n break;\r\n }\r\n }\r\n if (!didChangePoints) {\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n (element as any)[key] = value;\r\n didChange = true;\r\n }\r\n }\r\n\r\n if (!didChange) {\r\n return element;\r\n }\r\n\r\n if (\r\n typeof updates.height !== \"undefined\" ||\r\n typeof updates.width !== \"undefined\" ||\r\n typeof fileId != \"undefined\" ||\r\n typeof points !== \"undefined\"\r\n ) {\r\n ShapeCache.delete(element);\r\n }\r\n\r\n element.version = updates.version ?? element.version + 1;\r\n element.versionNonce = updates.versionNonce ?? randomInteger();\r\n element.updated = getUpdatedTimestamp();\r\n\r\n return element;\r\n};\r\n\r\nexport const newElementWith = <TElement extends ExcalidrawElement>(\r\n element: TElement,\r\n updates: ElementUpdate<TElement>,\r\n /** pass `true` to always regenerate */\r\n force = false,\r\n): TElement => {\r\n let didChange = false;\r\n for (const key in updates) {\r\n const value = (updates as any)[key];\r\n if (typeof value !== \"undefined\") {\r\n if (\r\n (element as any)[key] === value &&\r\n // if object, always update because its attrs could have changed\r\n (typeof value !== \"object\" || value === null)\r\n ) {\r\n continue;\r\n }\r\n didChange = true;\r\n }\r\n }\r\n\r\n if (!didChange && !force) {\r\n return element;\r\n }\r\n\r\n return {\r\n ...element,\r\n ...updates,\r\n version: updates.version ?? element.version + 1,\r\n versionNonce: updates.versionNonce ?? randomInteger(),\r\n updated: getUpdatedTimestamp(),\r\n };\r\n};\r\n\r\n/**\r\n * Mutates element, bumping `version`, `versionNonce`, and `updated`.\r\n *\r\n * NOTE: does not trigger re-render.\r\n */\r\nexport const bumpVersion = <T extends Mutable<ExcalidrawElement>>(\r\n element: T,\r\n version?: ExcalidrawElement[\"version\"],\r\n) => {\r\n element.version = (version ?? element.version) + 1;\r\n element.versionNonce = randomInteger();\r\n element.updated = getUpdatedTimestamp();\r\n return element;\r\n};\r\n", "import {\r\n clamp,\r\n pointDistance,\r\n pointFrom,\r\n pointScaleFromOrigin,\r\n pointsEqual,\r\n pointTranslate,\r\n vector,\r\n vectorCross,\r\n vectorFromPoint,\r\n vectorScale,\r\n type GlobalPoint,\r\n type LocalPoint,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n type Bounds,\r\n BinaryHeap,\r\n invariant,\r\n isAnyTrue,\r\n getSizeFromPoints,\r\n isDevEnv,\r\n arrayToMap,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport {\r\n bindPointToSnapToElementOutline,\r\n getHeadingForElbowArrowSnap,\r\n getGlobalFixedPointForBindableElement,\r\n getBindingGap,\r\n maxBindingDistance_simple,\r\n BASE_BINDING_GAP_ELBOW,\r\n} from \"./binding\";\r\nimport { distanceToElement } from \"./distance\";\r\nimport {\r\n compareHeading,\r\n flipHeading,\r\n HEADING_DOWN,\r\n HEADING_LEFT,\r\n HEADING_RIGHT,\r\n HEADING_UP,\r\n headingForPointIsHorizontal,\r\n headingIsHorizontal,\r\n vectorToHeading,\r\n headingForPoint,\r\n} from \"./heading\";\r\nimport { type ElementUpdate } from \"./mutateElement\";\r\nimport { isBindableElement } from \"./typeChecks\";\r\nimport {\r\n type ExcalidrawElbowArrowElement,\r\n type NonDeletedSceneElementsMap,\r\n} from \"./types\";\r\nimport { aabbForElement, pointInsideBounds } from \"./bounds\";\r\nimport { getHoveredElementForBinding } from \"./collision\";\r\n\r\nimport type { Heading } from \"./heading\";\r\nimport type {\r\n Arrowhead,\r\n ElementsMap,\r\n ExcalidrawBindableElement,\r\n FixedPointBinding,\r\n FixedSegment,\r\n NonDeletedExcalidrawElement,\r\n Ordered,\r\n} from \"./types\";\r\n\r\ntype GridAddress = [number, number] & { _brand: \"gridaddress\" };\r\n\r\ntype Node = {\r\n f: number;\r\n g: number;\r\n h: number;\r\n closed: boolean;\r\n visited: boolean;\r\n parent: Node | null;\r\n pos: GlobalPoint;\r\n addr: GridAddress;\r\n};\r\n\r\ntype Grid = {\r\n row: number;\r\n col: number;\r\n data: (Node | null)[];\r\n};\r\n\r\ntype ElbowArrowState = {\r\n x: number;\r\n y: number;\r\n startBinding: FixedPointBinding | null;\r\n endBinding: FixedPointBinding | null;\r\n startArrowhead: Arrowhead | null;\r\n endArrowhead: Arrowhead | null;\r\n};\r\n\r\ntype ElbowArrowData = {\r\n dynamicAABBs: Bounds[];\r\n startDonglePosition: GlobalPoint | null;\r\n startGlobalPoint: GlobalPoint;\r\n startHeading: Heading;\r\n endDonglePosition: GlobalPoint | null;\r\n endGlobalPoint: GlobalPoint;\r\n endHeading: Heading;\r\n commonBounds: Bounds;\r\n hoveredStartElement: ExcalidrawBindableElement | null;\r\n hoveredEndElement: ExcalidrawBindableElement | null;\r\n};\r\n\r\nconst DEDUP_TRESHOLD = 1;\r\nexport const BASE_PADDING = 40;\r\n\r\nconst handleSegmentRenormalization = (\r\n arrow: ExcalidrawElbowArrowElement,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n) => {\r\n const nextFixedSegments: FixedSegment[] | null = arrow.fixedSegments\r\n ? arrow.fixedSegments.slice()\r\n : null;\r\n\r\n if (nextFixedSegments) {\r\n const _nextPoints: GlobalPoint[] = [];\r\n\r\n arrow.points\r\n .map((p) => pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]))\r\n .forEach((p, i, points) => {\r\n if (i < 2) {\r\n return _nextPoints.push(p);\r\n }\r\n\r\n const currentSegmentIsHorizontal = headingForPoint(p, points[i - 1]);\r\n const prevSegmentIsHorizontal = headingForPoint(\r\n points[i - 1],\r\n points[i - 2],\r\n );\r\n\r\n if (\r\n // Check if previous two points are on the same line\r\n compareHeading(currentSegmentIsHorizontal, prevSegmentIsHorizontal)\r\n ) {\r\n const prevSegmentIdx =\r\n nextFixedSegments?.findIndex(\r\n (segment) => segment.index === i - 1,\r\n ) ?? -1;\r\n const segmentIdx =\r\n nextFixedSegments?.findIndex((segment) => segment.index === i) ??\r\n -1;\r\n\r\n // If the current segment is a fixed segment, update its start point\r\n if (segmentIdx !== -1) {\r\n nextFixedSegments[segmentIdx].start = pointFrom<LocalPoint>(\r\n points[i - 2][0] - arrow.x,\r\n points[i - 2][1] - arrow.y,\r\n );\r\n }\r\n\r\n // Remove the fixed segment status from the previous segment if it is\r\n // a fixed segment, because we are going to unify that segment with\r\n // the current one\r\n if (prevSegmentIdx !== -1) {\r\n nextFixedSegments.splice(prevSegmentIdx, 1);\r\n }\r\n\r\n // Remove the duplicate point\r\n _nextPoints.splice(-1, 1);\r\n\r\n // Update fixed point indices\r\n nextFixedSegments.forEach((segment) => {\r\n if (segment.index > i - 1) {\r\n segment.index -= 1;\r\n }\r\n });\r\n }\r\n\r\n return _nextPoints.push(p);\r\n });\r\n\r\n const nextPoints: GlobalPoint[] = [];\r\n\r\n _nextPoints.forEach((p, i, points) => {\r\n if (i < 3) {\r\n return nextPoints.push(p);\r\n }\r\n\r\n if (\r\n // Remove segments that are too short\r\n pointDistance(points[i - 2], points[i - 1]) < DEDUP_TRESHOLD\r\n ) {\r\n const prevPrevSegmentIdx =\r\n nextFixedSegments?.findIndex((segment) => segment.index === i - 2) ??\r\n -1;\r\n const prevSegmentIdx =\r\n nextFixedSegments?.findIndex((segment) => segment.index === i - 1) ??\r\n -1;\r\n\r\n // Remove the previous fixed segment if it exists (i.e. the segment\r\n // which will be removed due to being parallel or too short)\r\n if (prevSegmentIdx !== -1) {\r\n nextFixedSegments.splice(prevSegmentIdx, 1);\r\n }\r\n\r\n // Remove the fixed segment status from the segment 2 steps back\r\n // if it is a fixed segment, because we are going to unify that\r\n // segment with the current one\r\n if (prevPrevSegmentIdx !== -1) {\r\n nextFixedSegments.splice(prevPrevSegmentIdx, 1);\r\n }\r\n\r\n nextPoints.splice(-2, 2);\r\n\r\n // Since we have to remove two segments, update any fixed segment\r\n nextFixedSegments.forEach((segment) => {\r\n if (segment.index > i - 2) {\r\n segment.index -= 2;\r\n }\r\n });\r\n\r\n // Remove aligned segment points\r\n const isHorizontal = headingForPointIsHorizontal(p, points[i - 1]);\r\n\r\n return nextPoints.push(\r\n pointFrom<GlobalPoint>(\r\n !isHorizontal ? points[i - 2][0] : p[0],\r\n isHorizontal ? points[i - 2][1] : p[1],\r\n ),\r\n );\r\n }\r\n\r\n nextPoints.push(p);\r\n });\r\n\r\n const filteredNextFixedSegments = nextFixedSegments.filter(\r\n (segment) =>\r\n segment.index !== 1 && segment.index !== nextPoints.length - 1,\r\n );\r\n if (filteredNextFixedSegments.length === 0) {\r\n return normalizeArrowElementUpdate(\r\n getElbowArrowCornerPoints(\r\n removeElbowArrowShortSegments(\r\n routeElbowArrow(\r\n arrow,\r\n getElbowArrowData(\r\n arrow,\r\n elementsMap,\r\n nextPoints.map((p) =>\r\n pointFrom<LocalPoint>(p[0] - arrow.x, p[1] - arrow.y),\r\n ),\r\n ),\r\n ) ?? [],\r\n ),\r\n ),\r\n filteredNextFixedSegments,\r\n null,\r\n null,\r\n );\r\n }\r\n\r\n isDevEnv() &&\r\n invariant(\r\n validateElbowPoints(nextPoints),\r\n \"Invalid elbow points with fixed segments\",\r\n );\r\n\r\n return normalizeArrowElementUpdate(\r\n nextPoints,\r\n filteredNextFixedSegments,\r\n arrow.startIsSpecial,\r\n arrow.endIsSpecial,\r\n );\r\n }\r\n\r\n return {\r\n x: arrow.x,\r\n y: arrow.y,\r\n points: arrow.points,\r\n fixedSegments: arrow.fixedSegments,\r\n startIsSpecial: arrow.startIsSpecial,\r\n endIsSpecial: arrow.endIsSpecial,\r\n };\r\n};\r\n\r\nconst handleSegmentRelease = (\r\n arrow: ExcalidrawElbowArrowElement,\r\n fixedSegments: readonly FixedSegment[],\r\n elementsMap: NonDeletedSceneElementsMap,\r\n) => {\r\n const newFixedSegmentIndices = fixedSegments.map((segment) => segment.index);\r\n const oldFixedSegmentIndices =\r\n arrow.fixedSegments?.map((segment) => segment.index) ?? [];\r\n const deletedSegmentIdx = oldFixedSegmentIndices.findIndex(\r\n (idx) => !newFixedSegmentIndices.includes(idx),\r\n );\r\n\r\n if (deletedSegmentIdx === -1 || !arrow.fixedSegments?.[deletedSegmentIdx]) {\r\n return {\r\n points: arrow.points,\r\n };\r\n }\r\n\r\n const deletedIdx = arrow.fixedSegments[deletedSegmentIdx].index;\r\n\r\n // Find prev and next fixed segments\r\n const prevSegment = arrow.fixedSegments[deletedSegmentIdx - 1];\r\n const nextSegment = arrow.fixedSegments[deletedSegmentIdx + 1];\r\n\r\n // We need to render a sub-arrow path to restore deleted segments\r\n const x = arrow.x + (prevSegment ? prevSegment.end[0] : 0);\r\n const y = arrow.y + (prevSegment ? prevSegment.end[1] : 0);\r\n const startBinding = prevSegment ? null : arrow.startBinding;\r\n const endBinding = nextSegment ? null : arrow.endBinding;\r\n const {\r\n startHeading,\r\n endHeading,\r\n startGlobalPoint,\r\n endGlobalPoint,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n ...rest\r\n } = getElbowArrowData(\r\n {\r\n x,\r\n y,\r\n startBinding,\r\n endBinding,\r\n startArrowhead: null,\r\n endArrowhead: null,\r\n points: arrow.points,\r\n },\r\n elementsMap,\r\n [\r\n pointFrom<LocalPoint>(0, 0),\r\n pointFrom<LocalPoint>(\r\n arrow.x +\r\n (nextSegment?.start[0] ?? arrow.points[arrow.points.length - 1][0]) -\r\n x,\r\n arrow.y +\r\n (nextSegment?.start[1] ?? arrow.points[arrow.points.length - 1][1]) -\r\n y,\r\n ),\r\n ],\r\n { isDragging: false },\r\n );\r\n\r\n const { points: restoredPoints } = normalizeArrowElementUpdate(\r\n getElbowArrowCornerPoints(\r\n removeElbowArrowShortSegments(\r\n routeElbowArrow(arrow, {\r\n startHeading,\r\n endHeading,\r\n startGlobalPoint,\r\n endGlobalPoint,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n ...rest,\r\n }) ?? [],\r\n ),\r\n ),\r\n fixedSegments,\r\n null,\r\n null,\r\n );\r\n\r\n if (!restoredPoints || restoredPoints.length < 2) {\r\n throw new Error(\r\n \"Property 'points' is required in the update returned by normalizeArrowElementUpdate()\",\r\n );\r\n }\r\n\r\n const nextPoints: GlobalPoint[] = [];\r\n\r\n // First part of the arrow are the old points\r\n if (prevSegment) {\r\n for (let i = 0; i < prevSegment.index; i++) {\r\n nextPoints.push(\r\n pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[i][0],\r\n arrow.y + arrow.points[i][1],\r\n ),\r\n );\r\n }\r\n }\r\n\r\n restoredPoints.forEach((p) => {\r\n nextPoints.push(\r\n pointFrom<GlobalPoint>(\r\n arrow.x + (prevSegment ? prevSegment.end[0] : 0) + p[0],\r\n arrow.y + (prevSegment ? prevSegment.end[1] : 0) + p[1],\r\n ),\r\n );\r\n });\r\n\r\n // Last part of the arrow are the old points too\r\n if (nextSegment) {\r\n for (let i = nextSegment.index; i < arrow.points.length; i++) {\r\n nextPoints.push(\r\n pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[i][0],\r\n arrow.y + arrow.points[i][1],\r\n ),\r\n );\r\n }\r\n }\r\n\r\n // Update nextFixedSegments\r\n const originalSegmentCountDiff =\r\n (nextSegment?.index ?? arrow.points.length) - (prevSegment?.index ?? 0) - 1;\r\n\r\n const nextFixedSegments = fixedSegments.map((segment) => {\r\n if (segment.index > deletedIdx) {\r\n return {\r\n ...segment,\r\n index:\r\n segment.index -\r\n originalSegmentCountDiff +\r\n (restoredPoints.length - 1),\r\n };\r\n }\r\n\r\n return segment;\r\n });\r\n\r\n const simplifiedPoints = nextPoints.flatMap((p, i) => {\r\n const prev = nextPoints[i - 1];\r\n const next = nextPoints[i + 1];\r\n\r\n if (prev && next) {\r\n const prevHeading = headingForPoint(p, prev);\r\n const nextHeading = headingForPoint(next, p);\r\n\r\n if (compareHeading(prevHeading, nextHeading)) {\r\n // Update subsequent fixed segment indices\r\n nextFixedSegments.forEach((segment) => {\r\n if (segment.index > i) {\r\n segment.index -= 1;\r\n }\r\n });\r\n\r\n return [];\r\n } else if (compareHeading(prevHeading, flipHeading(nextHeading))) {\r\n // Update subsequent fixed segment indices\r\n nextFixedSegments.forEach((segment) => {\r\n if (segment.index > i) {\r\n segment.index += 1;\r\n }\r\n });\r\n\r\n return [p, p];\r\n }\r\n }\r\n\r\n return [p];\r\n });\r\n\r\n return normalizeArrowElementUpdate(\r\n simplifiedPoints,\r\n nextFixedSegments,\r\n false,\r\n false,\r\n );\r\n};\r\n\r\n/**\r\n *\r\n */\r\nconst handleSegmentMove = (\r\n arrow: ExcalidrawElbowArrowElement,\r\n fixedSegments: readonly FixedSegment[],\r\n startHeading: Heading,\r\n endHeading: Heading,\r\n hoveredStartElement: ExcalidrawBindableElement | null,\r\n hoveredEndElement: ExcalidrawBindableElement | null,\r\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\r\n const activelyModifiedSegmentIdx = fixedSegments\r\n .map((segment, i) => {\r\n if (\r\n arrow.fixedSegments == null ||\r\n arrow.fixedSegments[i] === undefined ||\r\n arrow.fixedSegments[i].index !== segment.index\r\n ) {\r\n return i;\r\n }\r\n\r\n return (segment.start[0] !== arrow.fixedSegments![i].start[0] &&\r\n segment.end[0] !== arrow.fixedSegments![i].end[0]) !==\r\n (segment.start[1] !== arrow.fixedSegments![i].start[1] &&\r\n segment.end[1] !== arrow.fixedSegments![i].end[1])\r\n ? i\r\n : null;\r\n })\r\n .filter((idx) => idx !== null)\r\n .shift();\r\n\r\n if (activelyModifiedSegmentIdx == null) {\r\n return { points: arrow.points };\r\n }\r\n\r\n const firstSegmentIdx =\r\n arrow.fixedSegments?.findIndex((segment) => segment.index === 1) ?? -1;\r\n const lastSegmentIdx =\r\n arrow.fixedSegments?.findIndex(\r\n (segment) => segment.index === arrow.points.length - 1,\r\n ) ?? -1;\r\n\r\n // Handle special case for first segment move\r\n const segmentLength = pointDistance(\r\n fixedSegments[activelyModifiedSegmentIdx].start,\r\n fixedSegments[activelyModifiedSegmentIdx].end,\r\n );\r\n const segmentIsTooShort = segmentLength < BASE_PADDING + 5;\r\n if (\r\n firstSegmentIdx === -1 &&\r\n fixedSegments[activelyModifiedSegmentIdx].index === 1 &&\r\n hoveredStartElement\r\n ) {\r\n const startIsHorizontal = headingIsHorizontal(startHeading);\r\n const startIsPositive = startIsHorizontal\r\n ? compareHeading(startHeading, HEADING_RIGHT)\r\n : compareHeading(startHeading, HEADING_DOWN);\r\n const padding = startIsPositive\r\n ? segmentIsTooShort\r\n ? segmentLength / 2\r\n : BASE_PADDING\r\n : segmentIsTooShort\r\n ? -segmentLength / 2\r\n : -BASE_PADDING;\r\n fixedSegments[activelyModifiedSegmentIdx].start = pointFrom<LocalPoint>(\r\n fixedSegments[activelyModifiedSegmentIdx].start[0] +\r\n (startIsHorizontal ? padding : 0),\r\n fixedSegments[activelyModifiedSegmentIdx].start[1] +\r\n (!startIsHorizontal ? padding : 0),\r\n );\r\n }\r\n\r\n // Handle special case for last segment move\r\n if (\r\n lastSegmentIdx === -1 &&\r\n fixedSegments[activelyModifiedSegmentIdx].index ===\r\n arrow.points.length - 1 &&\r\n hoveredEndElement\r\n ) {\r\n const endIsHorizontal = headingIsHorizontal(endHeading);\r\n const endIsPositive = endIsHorizontal\r\n ? compareHeading(endHeading, HEADING_RIGHT)\r\n : compareHeading(endHeading, HEADING_DOWN);\r\n const padding = endIsPositive\r\n ? segmentIsTooShort\r\n ? segmentLength / 2\r\n : BASE_PADDING\r\n : segmentIsTooShort\r\n ? -segmentLength / 2\r\n : -BASE_PADDING;\r\n fixedSegments[activelyModifiedSegmentIdx].end = pointFrom<LocalPoint>(\r\n fixedSegments[activelyModifiedSegmentIdx].end[0] +\r\n (endIsHorizontal ? padding : 0),\r\n fixedSegments[activelyModifiedSegmentIdx].end[1] +\r\n (!endIsHorizontal ? padding : 0),\r\n );\r\n }\r\n\r\n // Translate all fixed segments to global coordinates\r\n const nextFixedSegments = fixedSegments.map((segment) => ({\r\n ...segment,\r\n start: pointFrom<GlobalPoint>(\r\n arrow.x + segment.start[0],\r\n arrow.y + segment.start[1],\r\n ),\r\n end: pointFrom<GlobalPoint>(\r\n arrow.x + segment.end[0],\r\n arrow.y + segment.end[1],\r\n ),\r\n }));\r\n\r\n // For start, clone old arrow points\r\n const newPoints: GlobalPoint[] = arrow.points.map((p, i) =>\r\n pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),\r\n );\r\n\r\n const startIdx = nextFixedSegments[activelyModifiedSegmentIdx].index - 1;\r\n const endIdx = nextFixedSegments[activelyModifiedSegmentIdx].index;\r\n const start = nextFixedSegments[activelyModifiedSegmentIdx].start;\r\n const end = nextFixedSegments[activelyModifiedSegmentIdx].end;\r\n const prevSegmentIsHorizontal =\r\n newPoints[startIdx - 1] &&\r\n !pointsEqual(newPoints[startIdx], newPoints[startIdx - 1])\r\n ? headingForPointIsHorizontal(\r\n newPoints[startIdx - 1],\r\n newPoints[startIdx],\r\n )\r\n : undefined;\r\n const nextSegmentIsHorizontal =\r\n newPoints[endIdx + 1] &&\r\n !pointsEqual(newPoints[endIdx], newPoints[endIdx + 1])\r\n ? headingForPointIsHorizontal(newPoints[endIdx + 1], newPoints[endIdx])\r\n : undefined;\r\n\r\n // Override the segment points with the actively moved fixed segment\r\n if (prevSegmentIsHorizontal !== undefined) {\r\n const dir = prevSegmentIsHorizontal ? 1 : 0;\r\n newPoints[startIdx - 1][dir] = start[dir];\r\n }\r\n newPoints[startIdx] = start;\r\n newPoints[endIdx] = end;\r\n if (nextSegmentIsHorizontal !== undefined) {\r\n const dir = nextSegmentIsHorizontal ? 1 : 0;\r\n newPoints[endIdx + 1][dir] = end[dir];\r\n }\r\n\r\n // Override neighboring fixedSegment start/end points, if any\r\n const prevSegmentIdx = nextFixedSegments.findIndex(\r\n (segment) => segment.index === startIdx,\r\n );\r\n if (prevSegmentIdx !== -1) {\r\n // Align the next segment points with the moved segment\r\n const dir = headingForPointIsHorizontal(\r\n nextFixedSegments[prevSegmentIdx].end,\r\n nextFixedSegments[prevSegmentIdx].start,\r\n )\r\n ? 1\r\n : 0;\r\n nextFixedSegments[prevSegmentIdx].start[dir] = start[dir];\r\n nextFixedSegments[prevSegmentIdx].end = start;\r\n }\r\n\r\n const nextSegmentIdx = nextFixedSegments.findIndex(\r\n (segment) => segment.index === endIdx + 1,\r\n );\r\n if (nextSegmentIdx !== -1) {\r\n // Align the next segment points with the moved segment\r\n const dir = headingForPointIsHorizontal(\r\n nextFixedSegments[nextSegmentIdx].end,\r\n nextFixedSegments[nextSegmentIdx].start,\r\n )\r\n ? 1\r\n : 0;\r\n nextFixedSegments[nextSegmentIdx].end[dir] = end[dir];\r\n nextFixedSegments[nextSegmentIdx].start = end;\r\n }\r\n\r\n // First segment move needs an additional segment\r\n if (firstSegmentIdx === -1 && startIdx === 0) {\r\n const startIsHorizontal = hoveredStartElement\r\n ? headingIsHorizontal(startHeading)\r\n : headingForPointIsHorizontal(newPoints[1], newPoints[0]);\r\n newPoints.unshift(\r\n pointFrom<GlobalPoint>(\r\n startIsHorizontal ? start[0] : arrow.x + arrow.points[0][0],\r\n !startIsHorizontal ? start[1] : arrow.y + arrow.points[0][1],\r\n ),\r\n );\r\n\r\n if (hoveredStartElement) {\r\n newPoints.unshift(\r\n pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[0][0],\r\n arrow.y + arrow.points[0][1],\r\n ),\r\n );\r\n }\r\n\r\n for (const segment of nextFixedSegments) {\r\n segment.index += hoveredStartElement ? 2 : 1;\r\n }\r\n }\r\n\r\n // Last segment move needs an additional segment\r\n if (lastSegmentIdx === -1 && endIdx === arrow.points.length - 1) {\r\n const endIsHorizontal = headingIsHorizontal(endHeading);\r\n newPoints.push(\r\n pointFrom<GlobalPoint>(\r\n endIsHorizontal\r\n ? end[0]\r\n : arrow.x + arrow.points[arrow.points.length - 1][0],\r\n !endIsHorizontal\r\n ? end[1]\r\n : arrow.y + arrow.points[arrow.points.length - 1][1],\r\n ),\r\n );\r\n if (hoveredEndElement) {\r\n newPoints.push(\r\n pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[arrow.points.length - 1][0],\r\n arrow.y + arrow.points[arrow.points.length - 1][1],\r\n ),\r\n );\r\n }\r\n }\r\n\r\n return normalizeArrowElementUpdate(\r\n newPoints,\r\n nextFixedSegments.map((segment) => ({\r\n ...segment,\r\n start: pointFrom<LocalPoint>(\r\n segment.start[0] - arrow.x,\r\n segment.start[1] - arrow.y,\r\n ),\r\n end: pointFrom<LocalPoint>(\r\n segment.end[0] - arrow.x,\r\n segment.end[1] - arrow.y,\r\n ),\r\n })),\r\n false, // If you move a segment, there is no special point anymore\r\n false, // If you move a segment, there is no special point anymore\r\n );\r\n};\r\n\r\nconst handleEndpointDrag = (\r\n arrow: ExcalidrawElbowArrowElement,\r\n updatedPoints: readonly LocalPoint[],\r\n fixedSegments: readonly FixedSegment[],\r\n startHeading: Heading,\r\n endHeading: Heading,\r\n startGlobalPoint: GlobalPoint,\r\n endGlobalPoint: GlobalPoint,\r\n hoveredStartElement: ExcalidrawBindableElement | null,\r\n hoveredEndElement: ExcalidrawBindableElement | null,\r\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\r\n let startIsSpecial = arrow.startIsSpecial ?? null;\r\n let endIsSpecial = arrow.endIsSpecial ?? null;\r\n const globalUpdatedPoints = updatedPoints.map((p, i) =>\r\n i === 0\r\n ? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])\r\n : i === updatedPoints.length - 1\r\n ? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])\r\n : pointFrom<GlobalPoint>(\r\n arrow.x + arrow.points[i][0],\r\n arrow.y + arrow.points[i][1],\r\n ),\r\n );\r\n const nextFixedSegments = fixedSegments.map((segment) => ({\r\n ...segment,\r\n start: pointFrom<GlobalPoint>(\r\n arrow.x + (segment.start[0] - updatedPoints[0][0]),\r\n arrow.y + (segment.start[1] - updatedPoints[0][1]),\r\n ),\r\n end: pointFrom<GlobalPoint>(\r\n arrow.x + (segment.end[0] - updatedPoints[0][0]),\r\n arrow.y + (segment.end[1] - updatedPoints[0][1]),\r\n ),\r\n }));\r\n const newPoints: GlobalPoint[] = [];\r\n\r\n // Add the inside points\r\n const offset = 2 + (startIsSpecial ? 1 : 0);\r\n const endOffset = 2 + (endIsSpecial ? 1 : 0);\r\n while (newPoints.length + offset < globalUpdatedPoints.length - endOffset) {\r\n newPoints.push(globalUpdatedPoints[newPoints.length + offset]);\r\n }\r\n\r\n // Calculate the moving second point connection and add the start point\r\n {\r\n const secondPoint = globalUpdatedPoints.at(startIsSpecial ? 2 : 1);\r\n const thirdPoint = globalUpdatedPoints.at(startIsSpecial ? 3 : 2);\r\n\r\n if (!secondPoint || !thirdPoint) {\r\n throw new Error(\r\n `Second and third points must exist when handling endpoint drag (${startIsSpecial})`,\r\n );\r\n }\r\n\r\n const startIsHorizontal = headingIsHorizontal(startHeading);\r\n const secondIsHorizontal = headingIsHorizontal(\r\n vectorToHeading(vectorFromPoint(secondPoint, thirdPoint)),\r\n );\r\n\r\n if (hoveredStartElement && startIsHorizontal === secondIsHorizontal) {\r\n const positive = startIsHorizontal\r\n ? compareHeading(startHeading, HEADING_RIGHT)\r\n : compareHeading(startHeading, HEADING_DOWN);\r\n newPoints.unshift(\r\n pointFrom<GlobalPoint>(\r\n !secondIsHorizontal\r\n ? thirdPoint[0]\r\n : startGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING),\r\n secondIsHorizontal\r\n ? thirdPoint[1]\r\n : startGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING),\r\n ),\r\n );\r\n newPoints.unshift(\r\n pointFrom<GlobalPoint>(\r\n startIsHorizontal\r\n ? startGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING)\r\n : startGlobalPoint[0],\r\n !startIsHorizontal\r\n ? startGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING)\r\n : startGlobalPoint[1],\r\n ),\r\n );\r\n if (!startIsSpecial) {\r\n startIsSpecial = true;\r\n for (const segment of nextFixedSegments) {\r\n if (segment.index > 1) {\r\n segment.index += 1;\r\n }\r\n }\r\n }\r\n } else {\r\n newPoints.unshift(\r\n pointFrom<GlobalPoint>(\r\n !secondIsHorizontal ? secondPoint[0] : startGlobalPoint[0],\r\n secondIsHorizontal ? secondPoint[1] : startGlobalPoint[1],\r\n ),\r\n );\r\n if (startIsSpecial) {\r\n startIsSpecial = false;\r\n for (const segment of nextFixedSegments) {\r\n if (segment.index > 1) {\r\n segment.index -= 1;\r\n }\r\n }\r\n }\r\n }\r\n newPoints.unshift(startGlobalPoint);\r\n }\r\n\r\n // Calculate the moving second to last point connection\r\n {\r\n const secondToLastPoint = globalUpdatedPoints.at(\r\n globalUpdatedPoints.length - (endIsSpecial ? 3 : 2),\r\n );\r\n const thirdToLastPoint = globalUpdatedPoints.at(\r\n globalUpdatedPoints.length - (endIsSpecial ? 4 : 3),\r\n );\r\n\r\n if (!secondToLastPoint || !thirdToLastPoint) {\r\n throw new Error(\r\n `Second and third to last points must exist when handling endpoint drag (${endIsSpecial})`,\r\n );\r\n }\r\n\r\n const endIsHorizontal = headingIsHorizontal(endHeading);\r\n const secondIsHorizontal = headingForPointIsHorizontal(\r\n thirdToLastPoint,\r\n secondToLastPoint,\r\n );\r\n if (hoveredEndElement && endIsHorizontal === secondIsHorizontal) {\r\n const positive = endIsHorizontal\r\n ? compareHeading(endHeading, HEADING_RIGHT)\r\n : compareHeading(endHeading, HEADING_DOWN);\r\n newPoints.push(\r\n pointFrom<GlobalPoint>(\r\n !secondIsHorizontal\r\n ? thirdToLastPoint[0]\r\n : endGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING),\r\n secondIsHorizontal\r\n ? thirdToLastPoint[1]\r\n : endGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING),\r\n ),\r\n );\r\n newPoints.push(\r\n pointFrom<GlobalPoint>(\r\n endIsHorizontal\r\n ? endGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING)\r\n : endGlobalPoint[0],\r\n !endIsHorizontal\r\n ? endGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING)\r\n : endGlobalPoint[1],\r\n ),\r\n );\r\n if (!endIsSpecial) {\r\n endIsSpecial = true;\r\n }\r\n } else {\r\n newPoints.push(\r\n pointFrom<GlobalPoint>(\r\n !secondIsHorizontal ? secondToLastPoint[0] : endGlobalPoint[0],\r\n secondIsHorizontal ? secondToLastPoint[1] : endGlobalPoint[1],\r\n ),\r\n );\r\n if (endIsSpecial) {\r\n endIsSpecial = false;\r\n }\r\n }\r\n }\r\n\r\n newPoints.push(endGlobalPoint);\r\n\r\n return normalizeArrowElementUpdate(\r\n newPoints,\r\n nextFixedSegments\r\n .map(({ index }) => ({\r\n index,\r\n start: newPoints[index - 1],\r\n end: newPoints[index],\r\n }))\r\n .map((segment) => ({\r\n ...segment,\r\n start: pointFrom<LocalPoint>(\r\n segment.start[0] - startGlobalPoint[0],\r\n segment.start[1] - startGlobalPoint[1],\r\n ),\r\n end: pointFrom<LocalPoint>(\r\n segment.end[0] - startGlobalPoint[0],\r\n segment.end[1] - startGlobalPoint[1],\r\n ),\r\n })),\r\n startIsSpecial,\r\n endIsSpecial,\r\n );\r\n};\r\n\r\nconst MAX_POS = 1e6;\r\n\r\n/**\r\n *\r\n */\r\nexport const updateElbowArrowPoints = (\r\n arrow: Readonly<ExcalidrawElbowArrowElement>,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n updates: {\r\n points?: readonly LocalPoint[];\r\n fixedSegments?: readonly FixedSegment[] | null;\r\n startBinding?: FixedPointBinding | null;\r\n endBinding?: FixedPointBinding | null;\r\n },\r\n options?: {\r\n isDragging?: boolean;\r\n },\r\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\r\n if (arrow.points.length < 2) {\r\n return { points: updates.points ?? arrow.points };\r\n }\r\n\r\n if (!import.meta.env.PROD) {\r\n invariant(\r\n !updates.points || updates.points.length >= 2,\r\n \"Updated point array length must match the arrow point length, contain \" +\r\n \"exactly the new start and end points or not be specified at all (i.e. \" +\r\n \"you can't add new points between start and end manually to elbow arrows)\",\r\n );\r\n\r\n invariant(\r\n !arrow.fixedSegments ||\r\n arrow.fixedSegments\r\n .map((s) => s.start[0] === s.end[0] || s.start[1] === s.end[1])\r\n .every(Boolean),\r\n \"Fixed segments must be either horizontal or vertical\",\r\n );\r\n\r\n invariant(\r\n !updates.fixedSegments ||\r\n updates.fixedSegments\r\n .map((s) => s.start[0] === s.end[0] || s.start[1] === s.end[1])\r\n .every(Boolean),\r\n \"Updates to fixed segments must be either horizontal or vertical\",\r\n );\r\n\r\n invariant(\r\n arrow.points\r\n .slice(1)\r\n .map(\r\n (p, i) => p[0] === arrow.points[i][0] || p[1] === arrow.points[i][1],\r\n ),\r\n \"Elbow arrow segments must be either horizontal or vertical\",\r\n );\r\n\r\n invariant(\r\n updates.fixedSegments?.find(\r\n (segment) =>\r\n segment.index === 1 &&\r\n pointsEqual(segment.start, (updates.points ?? arrow.points)[0]),\r\n ) == null &&\r\n updates.fixedSegments?.find(\r\n (segment) =>\r\n segment.index === (updates.points ?? arrow.points).length - 1 &&\r\n pointsEqual(\r\n segment.end,\r\n (updates.points ?? arrow.points)[\r\n (updates.points ?? arrow.points).length - 1\r\n ],\r\n ),\r\n ) == null,\r\n \"The first and last segments cannot be fixed\",\r\n );\r\n }\r\n\r\n const fixedSegments = updates.fixedSegments ?? arrow.fixedSegments ?? [];\r\n\r\n const updatedPoints: readonly LocalPoint[] = updates.points\r\n ? updates.points && updates.points.length === 2\r\n ? arrow.points.map((p, idx) =>\r\n idx === 0\r\n ? updates.points![0]\r\n : idx === arrow.points.length - 1\r\n ? updates.points![1]\r\n : p,\r\n )\r\n : updates.points.slice()\r\n : arrow.points.slice();\r\n\r\n // During all element replacement in the scene, we just need to renormalize\r\n // the arrow\r\n // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed\r\n const {\r\n startBinding: updatedStartBinding,\r\n endBinding: updatedEndBinding,\r\n ...restOfTheUpdates\r\n } = updates;\r\n const startBinding =\r\n typeof updatedStartBinding !== \"undefined\"\r\n ? updatedStartBinding\r\n : arrow.startBinding;\r\n const endBinding =\r\n typeof updatedEndBinding !== \"undefined\"\r\n ? updatedEndBinding\r\n : arrow.endBinding;\r\n const startElement =\r\n startBinding &&\r\n getBindableElementForId(startBinding.elementId, elementsMap);\r\n const endElement =\r\n endBinding && getBindableElementForId(endBinding.elementId, elementsMap);\r\n const areUpdatedPointsValid = validateElbowPoints(updatedPoints);\r\n\r\n if (\r\n (startBinding && !startElement && areUpdatedPointsValid) ||\r\n (endBinding && !endElement && areUpdatedPointsValid) ||\r\n (elementsMap.size === 0 && areUpdatedPointsValid) ||\r\n (Object.keys(restOfTheUpdates).length === 0 &&\r\n (startElement?.id !== startBinding?.elementId ||\r\n endElement?.id !== endBinding?.elementId))\r\n ) {\r\n return normalizeArrowElementUpdate(\r\n updatedPoints.map((p) =>\r\n pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),\r\n ),\r\n arrow.fixedSegments,\r\n arrow.startIsSpecial,\r\n arrow.endIsSpecial,\r\n );\r\n }\r\n\r\n const {\r\n startHeading,\r\n endHeading,\r\n startGlobalPoint,\r\n endGlobalPoint,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n ...rest\r\n } = getElbowArrowData(\r\n {\r\n x: arrow.x,\r\n y: arrow.y,\r\n startBinding,\r\n endBinding,\r\n startArrowhead: arrow.startArrowhead,\r\n endArrowhead: arrow.endArrowhead,\r\n points: arrow.points,\r\n },\r\n elementsMap,\r\n updatedPoints,\r\n options,\r\n );\r\n\r\n // 0. During all element replacement in the scene, we just need to renormalize\r\n // the arrow\r\n // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed\r\n if (elementsMap.size === 0 && areUpdatedPointsValid) {\r\n return normalizeArrowElementUpdate(\r\n updatedPoints.map((p) =>\r\n pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),\r\n ),\r\n arrow.fixedSegments,\r\n arrow.startIsSpecial,\r\n arrow.endIsSpecial,\r\n );\r\n }\r\n\r\n ////\r\n // 1. Renormalize the arrow\r\n ////\r\n if (\r\n !updates.points &&\r\n !updates.fixedSegments &&\r\n !updates.startBinding &&\r\n !updates.endBinding\r\n ) {\r\n return handleSegmentRenormalization(arrow, elementsMap);\r\n }\r\n\r\n // Short circuit on no-op to avoid huge performance hit\r\n if (\r\n updates.startBinding === arrow.startBinding &&\r\n updates.endBinding === arrow.endBinding &&\r\n (updates.points ?? []).every((p, i) =>\r\n pointsEqual(\r\n p,\r\n arrow.points[i] ?? pointFrom<LocalPoint>(Infinity, Infinity),\r\n ),\r\n ) &&\r\n areUpdatedPointsValid\r\n ) {\r\n return {};\r\n }\r\n\r\n ////\r\n // 2. Just normal elbow arrow things\r\n ////\r\n if (fixedSegments.length === 0) {\r\n return normalizeArrowElementUpdate(\r\n getElbowArrowCornerPoints(\r\n removeElbowArrowShortSegments(\r\n routeElbowArrow(arrow, {\r\n startHeading,\r\n endHeading,\r\n startGlobalPoint,\r\n endGlobalPoint,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n ...rest,\r\n }) ?? [],\r\n ),\r\n ),\r\n fixedSegments,\r\n null,\r\n null,\r\n );\r\n }\r\n\r\n ////\r\n // 3. Handle releasing a fixed segment\r\n if ((arrow.fixedSegments?.length ?? 0) > fixedSegments.length) {\r\n return handleSegmentRelease(arrow, fixedSegments, elementsMap);\r\n }\r\n\r\n ////\r\n // 4. Handle manual segment move\r\n ////\r\n if (!updates.points) {\r\n return handleSegmentMove(\r\n arrow,\r\n fixedSegments,\r\n startHeading,\r\n endHeading,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n );\r\n }\r\n\r\n ////\r\n // 5. Handle resize\r\n ////\r\n if (updates.points && updates.fixedSegments) {\r\n return updates;\r\n }\r\n\r\n ////\r\n // 6. One or more segments are fixed and endpoints are moved\r\n //\r\n // The key insights are:\r\n // - When segments are fixed, the arrow will keep the exact amount of segments\r\n // - Fixed segments are \"replacements\" for exactly one segment in the old arrow\r\n ////\r\n return handleEndpointDrag(\r\n arrow,\r\n updatedPoints,\r\n fixedSegments,\r\n startHeading,\r\n endHeading,\r\n startGlobalPoint,\r\n endGlobalPoint,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n );\r\n};\r\n\r\n/**\r\n * Retrieves data necessary for calculating the elbow arrow path.\r\n *\r\n * @param arrow - The arrow object containing its properties.\r\n * @param elementsMap - A map of elements in the scene.\r\n * @param nextPoints - The next set of points for the arrow.\r\n * @param options - Optional parameters for the calculation.\r\n * @param options.isDragging - Indicates if the arrow is being dragged.\r\n * @param options.startIsMidPoint - Indicates if the start point is a midpoint.\r\n * @param options.endIsMidPoint - Indicates if the end point is a midpoint.\r\n *\r\n * @returns An object containing various properties needed for elbow arrow calculations:\r\n * - dynamicAABBs: Dynamically generated axis-aligned bounding boxes.\r\n * - startDonglePosition: The position of the start dongle.\r\n * - startGlobalPoint: The global coordinates of the start point.\r\n * - startHeading: The heading direction from the start point.\r\n * - endDonglePosition: The position of the end dongle.\r\n * - endGlobalPoint: The global coordinates of the end point.\r\n * - endHeading: The heading direction from the end point.\r\n * - commonBounds: The common bounding box that encompasses both start and end points.\r\n * - hoveredStartElement: The element being hovered over at the start point.\r\n * - hoveredEndElement: The element being hovered over at the end point.\r\n */\r\nconst getElbowArrowData = (\r\n arrow: {\r\n x: number;\r\n y: number;\r\n startBinding: FixedPointBinding | null;\r\n endBinding: FixedPointBinding | null;\r\n startArrowhead: Arrowhead | null;\r\n endArrowhead: Arrowhead | null;\r\n points: readonly LocalPoint[];\r\n },\r\n elementsMap: NonDeletedSceneElementsMap,\r\n nextPoints: readonly LocalPoint[],\r\n options?: {\r\n isDragging?: boolean;\r\n zoom?: AppState[\"zoom\"];\r\n },\r\n) => {\r\n const origStartGlobalPoint: GlobalPoint = pointTranslate<\r\n LocalPoint,\r\n GlobalPoint\r\n >(nextPoints[0], vector(arrow.x, arrow.y));\r\n const origEndGlobalPoint: GlobalPoint = pointTranslate<\r\n LocalPoint,\r\n GlobalPoint\r\n >(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y));\r\n\r\n let hoveredStartElement = null;\r\n let hoveredEndElement = null;\r\n if (options?.isDragging) {\r\n const elements = Array.from(elementsMap.values());\r\n hoveredStartElement =\r\n getHoveredElement(\r\n origStartGlobalPoint,\r\n elementsMap,\r\n elements,\r\n options?.zoom,\r\n ) || null;\r\n hoveredEndElement =\r\n getHoveredElement(\r\n origEndGlobalPoint,\r\n elementsMap,\r\n elements,\r\n options?.zoom,\r\n ) || null;\r\n } else {\r\n hoveredStartElement = arrow.startBinding\r\n ? getBindableElementForId(arrow.startBinding.elementId, elementsMap) ||\r\n null\r\n : null;\r\n hoveredEndElement = arrow.endBinding\r\n ? getBindableElementForId(arrow.endBinding.elementId, elementsMap) || null\r\n : null;\r\n }\r\n\r\n const startGlobalPoint = getGlobalPoint(\r\n {\r\n ...arrow,\r\n angle: 0,\r\n type: \"arrow\",\r\n elbowed: true,\r\n points: nextPoints,\r\n } as ExcalidrawElbowArrowElement,\r\n \"start\",\r\n arrow.startBinding?.fixedPoint,\r\n origStartGlobalPoint,\r\n hoveredStartElement,\r\n elementsMap,\r\n options?.isDragging,\r\n );\r\n const endGlobalPoint = getGlobalPoint(\r\n {\r\n ...arrow,\r\n angle: 0,\r\n type: \"arrow\",\r\n elbowed: true,\r\n points: nextPoints,\r\n } as ExcalidrawElbowArrowElement,\r\n \"end\",\r\n arrow.endBinding?.fixedPoint,\r\n origEndGlobalPoint,\r\n hoveredEndElement,\r\n elementsMap,\r\n options?.isDragging,\r\n );\r\n const startHeading = getBindPointHeading(\r\n startGlobalPoint,\r\n endGlobalPoint,\r\n hoveredStartElement,\r\n origStartGlobalPoint,\r\n elementsMap,\r\n options?.zoom,\r\n );\r\n const endHeading = getBindPointHeading(\r\n endGlobalPoint,\r\n startGlobalPoint,\r\n hoveredEndElement,\r\n origEndGlobalPoint,\r\n elementsMap,\r\n options?.zoom,\r\n );\r\n const startPointBounds = [\r\n startGlobalPoint[0] - 2,\r\n startGlobalPoint[1] - 2,\r\n startGlobalPoint[0] + 2,\r\n startGlobalPoint[1] + 2,\r\n ] as Bounds;\r\n const endPointBounds = [\r\n endGlobalPoint[0] - 2,\r\n endGlobalPoint[1] - 2,\r\n endGlobalPoint[0] + 2,\r\n endGlobalPoint[1] + 2,\r\n ] as Bounds;\r\n const startElementBounds = hoveredStartElement\r\n ? aabbForElement(\r\n hoveredStartElement,\r\n elementsMap,\r\n offsetFromHeading(\r\n startHeading,\r\n arrow.startArrowhead\r\n ? getBindingGap(hoveredStartElement, { elbowed: true }) * 6\r\n : getBindingGap(hoveredStartElement, { elbowed: true }) * 2,\r\n 1,\r\n ),\r\n )\r\n : startPointBounds;\r\n const endElementBounds = hoveredEndElement\r\n ? aabbForElement(\r\n hoveredEndElement,\r\n elementsMap,\r\n offsetFromHeading(\r\n endHeading,\r\n arrow.endArrowhead\r\n ? getBindingGap(hoveredEndElement, { elbowed: true }) * 6\r\n : getBindingGap(hoveredEndElement, { elbowed: true }) * 2,\r\n 1,\r\n ),\r\n )\r\n : endPointBounds;\r\n const boundsOverlap =\r\n pointInsideBounds(\r\n startGlobalPoint,\r\n hoveredEndElement\r\n ? aabbForElement(\r\n hoveredEndElement,\r\n elementsMap,\r\n offsetFromHeading(endHeading, BASE_PADDING, BASE_PADDING),\r\n )\r\n : endPointBounds,\r\n ) ||\r\n pointInsideBounds(\r\n endGlobalPoint,\r\n hoveredStartElement\r\n ? aabbForElement(\r\n hoveredStartElement,\r\n elementsMap,\r\n offsetFromHeading(startHeading, BASE_PADDING, BASE_PADDING),\r\n )\r\n : startPointBounds,\r\n );\r\n const commonBounds = commonAABB(\r\n boundsOverlap\r\n ? [startPointBounds, endPointBounds]\r\n : [startElementBounds, endElementBounds],\r\n );\r\n const dynamicAABBs = generateDynamicAABBs(\r\n boundsOverlap ? startPointBounds : startElementBounds,\r\n boundsOverlap ? endPointBounds : endElementBounds,\r\n commonBounds,\r\n boundsOverlap\r\n ? offsetFromHeading(\r\n startHeading,\r\n !hoveredStartElement && !hoveredEndElement ? 0 : BASE_PADDING,\r\n 0,\r\n )\r\n : offsetFromHeading(\r\n startHeading,\r\n !hoveredStartElement && !hoveredEndElement\r\n ? 0\r\n : BASE_PADDING -\r\n (arrow.startArrowhead\r\n ? BASE_BINDING_GAP_ELBOW * 6\r\n : BASE_BINDING_GAP_ELBOW * 2),\r\n BASE_PADDING,\r\n ),\r\n boundsOverlap\r\n ? offsetFromHeading(\r\n endHeading,\r\n !hoveredStartElement && !hoveredEndElement ? 0 : BASE_PADDING,\r\n 0,\r\n )\r\n : offsetFromHeading(\r\n endHeading,\r\n !hoveredStartElement && !hoveredEndElement\r\n ? 0\r\n : BASE_PADDING -\r\n (arrow.endArrowhead\r\n ? BASE_BINDING_GAP_ELBOW * 6\r\n : BASE_BINDING_GAP_ELBOW * 2),\r\n BASE_PADDING,\r\n ),\r\n boundsOverlap,\r\n hoveredStartElement && aabbForElement(hoveredStartElement, elementsMap),\r\n hoveredEndElement && aabbForElement(hoveredEndElement, elementsMap),\r\n );\r\n const startDonglePosition = getDonglePosition(\r\n dynamicAABBs[0],\r\n startHeading,\r\n startGlobalPoint,\r\n );\r\n const endDonglePosition = getDonglePosition(\r\n dynamicAABBs[1],\r\n endHeading,\r\n endGlobalPoint,\r\n );\r\n\r\n return {\r\n dynamicAABBs,\r\n startDonglePosition,\r\n startGlobalPoint,\r\n startHeading,\r\n endDonglePosition,\r\n endGlobalPoint,\r\n endHeading,\r\n commonBounds,\r\n hoveredStartElement,\r\n hoveredEndElement,\r\n boundsOverlap,\r\n startElementBounds,\r\n endElementBounds,\r\n };\r\n};\r\n\r\n/**\r\n * Generate the elbow arrow segments\r\n *\r\n * @param arrow\r\n * @param elementsMap\r\n * @param nextPoints\r\n * @param options\r\n * @returns\r\n */\r\nconst routeElbowArrow = (\r\n arrow: ElbowArrowState,\r\n elbowArrowData: ElbowArrowData,\r\n): GlobalPoint[] | null => {\r\n const {\r\n dynamicAABBs,\r\n startDonglePosition,\r\n startGlobalPoint,\r\n startHeading,\r\n endDonglePosition,\r\n endGlobalPoint,\r\n endHeading,\r\n commonBounds,\r\n hoveredEndElement,\r\n } = elbowArrowData;\r\n\r\n // Canculate Grid positions\r\n const grid = calculateGrid(\r\n dynamicAABBs,\r\n startDonglePosition ? startDonglePosition : startGlobalPoint,\r\n startHeading,\r\n endDonglePosition ? endDonglePosition : endGlobalPoint,\r\n endHeading,\r\n commonBounds,\r\n );\r\n\r\n const startDongle =\r\n startDonglePosition && pointToGridNode(startDonglePosition, grid);\r\n const endDongle =\r\n endDonglePosition && pointToGridNode(endDonglePosition, grid);\r\n\r\n // Do not allow stepping on the true end or true start points\r\n const endNode = pointToGridNode(endGlobalPoint, grid);\r\n if (endNode && hoveredEndElement) {\r\n endNode.closed = true;\r\n }\r\n const startNode = pointToGridNode(startGlobalPoint, grid);\r\n if (startNode && arrow.startBinding) {\r\n startNode.closed = true;\r\n }\r\n const dongleOverlap =\r\n startDongle &&\r\n endDongle &&\r\n (pointInsideBounds(startDongle.pos, dynamicAABBs[1]) ||\r\n pointInsideBounds(endDongle.pos, dynamicAABBs[0]));\r\n\r\n // Create path to end dongle from start dongle\r\n const path = astar(\r\n startDongle ? startDongle : startNode!,\r\n endDongle ? endDongle : endNode!,\r\n grid,\r\n startHeading ? startHeading : HEADING_RIGHT,\r\n endHeading ? endHeading : HEADING_RIGHT,\r\n dongleOverlap ? [] : dynamicAABBs,\r\n );\r\n\r\n if (path) {\r\n const points = path.map((node) => [\r\n node.pos[0],\r\n node.pos[1],\r\n ]) as GlobalPoint[];\r\n startDongle && points.unshift(startGlobalPoint);\r\n endDongle && points.push(endGlobalPoint);\r\n\r\n return points;\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst offsetFromHeading = (\r\n heading: Heading,\r\n head: number,\r\n side: number,\r\n): [number, number, number, number] => {\r\n switch (heading) {\r\n case HEADING_UP:\r\n return [head, side, side, side];\r\n case HEADING_RIGHT:\r\n return [side, head, side, side];\r\n case HEADING_DOWN:\r\n return [side, side, head, side];\r\n }\r\n\r\n return [side, side, side, head];\r\n};\r\n\r\n/**\r\n * Routing algorithm based on the A* path search algorithm.\r\n * @see https://www.geeksforgeeks.org/a-search-algorithm/\r\n *\r\n * Binary heap is used to optimize node lookup.\r\n * See {@link calculateGrid} for the grid calculation details.\r\n *\r\n * Additional modifications added due to aesthetic route reasons:\r\n * 1) Arrow segment direction change is penalized by specific linear constant (bendMultiplier)\r\n * 2) Arrow segments are not allowed to go \"backwards\", overlapping with the previous segment\r\n */\r\nconst astar = (\r\n start: Node,\r\n end: Node,\r\n grid: Grid,\r\n startHeading: Heading,\r\n endHeading: Heading,\r\n aabbs: Bounds[],\r\n) => {\r\n const bendMultiplier = m_dist(start.pos, end.pos);\r\n const open = new BinaryHeap<Node>((node) => node.f);\r\n\r\n open.push(start);\r\n\r\n while (open.size() > 0) {\r\n // Grab the lowest f(x) to process next. Heap keeps this sorted for us.\r\n const current = open.pop();\r\n\r\n if (!current || current.closed) {\r\n // Current is not passable, continue with next element\r\n continue;\r\n }\r\n\r\n // End case -- result has been found, return the traced path.\r\n if (current === end) {\r\n return pathTo(start, current);\r\n }\r\n\r\n // Normal case -- move current from open to closed, process each of its neighbors.\r\n current.closed = true;\r\n\r\n // Find all neighbors for the current node.\r\n const neighbors = getNeighbors(current.addr, grid);\r\n\r\n for (let i = 0; i < 4; i++) {\r\n const neighbor = neighbors[i];\r\n\r\n if (!neighbor || neighbor.closed) {\r\n // Not a valid node to process, skip to next neighbor.\r\n continue;\r\n }\r\n\r\n // Intersect\r\n const neighborHalfPoint = pointScaleFromOrigin(\r\n neighbor.pos,\r\n current.pos,\r\n 0.5,\r\n );\r\n if (\r\n isAnyTrue(\r\n ...aabbs.map((aabb) => pointInsideBounds(neighborHalfPoint, aabb)),\r\n )\r\n ) {\r\n continue;\r\n }\r\n\r\n // The g score is the shortest distance from start to current node.\r\n // We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.\r\n const neighborHeading = neighborIndexToHeading(i as 0 | 1 | 2 | 3);\r\n const previousDirection = current.parent\r\n ? vectorToHeading(vectorFromPoint(current.pos, current.parent.pos))\r\n : startHeading;\r\n\r\n // Do not allow going in reverse\r\n const reverseHeading = flipHeading(previousDirection);\r\n const neighborIsReverseRoute =\r\n compareHeading(reverseHeading, neighborHeading) ||\r\n (gridAddressesEqual(start.addr, neighbor.addr) &&\r\n compareHeading(neighborHeading, startHeading)) ||\r\n (gridAddressesEqual(end.addr, neighbor.addr) &&\r\n compareHeading(neighborHeading, endHeading));\r\n if (neighborIsReverseRoute) {\r\n continue;\r\n }\r\n\r\n const directionChange = previousDirection !== neighborHeading;\r\n const gScore =\r\n current.g +\r\n m_dist(neighbor.pos, current.pos) +\r\n (directionChange ? Math.pow(bendMultiplier, 3) : 0);\r\n\r\n const beenVisited = neighbor.visited;\r\n\r\n if (!beenVisited || gScore < neighbor.g) {\r\n const estBendCount = estimateSegmentCount(\r\n neighbor,\r\n end,\r\n neighborHeading,\r\n endHeading,\r\n );\r\n // Found an optimal (so far) path to this node. Take score for node to see how good it is.\r\n neighbor.visited = true;\r\n neighbor.parent = current;\r\n neighbor.h =\r\n m_dist(end.pos, neighbor.pos) +\r\n estBendCount * Math.pow(bendMultiplier, 2);\r\n neighbor.g = gScore;\r\n neighbor.f = neighbor.g + neighbor.h;\r\n if (!beenVisited) {\r\n // Pushing to heap will put it in proper place based on the 'f' value.\r\n open.push(neighbor);\r\n } else {\r\n // Already seen the node, but since it has been rescored we need to reorder it in the heap\r\n open.rescoreElement(neighbor);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst pathTo = (start: Node, node: Node) => {\r\n let curr = node;\r\n const path = [];\r\n while (curr.parent) {\r\n path.unshift(curr);\r\n curr = curr.parent;\r\n }\r\n path.unshift(start);\r\n\r\n return path;\r\n};\r\n\r\nconst m_dist = (a: GlobalPoint | LocalPoint, b: GlobalPoint | LocalPoint) =>\r\n Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);\r\n\r\n/**\r\n * Create dynamically resizing, always touching\r\n * bounding boxes having a minimum extent represented\r\n * by the given static bounds.\r\n */\r\nconst generateDynamicAABBs = (\r\n a: Bounds,\r\n b: Bounds,\r\n common: Bounds,\r\n startDifference?: [number, number, number, number],\r\n endDifference?: [number, number, number, number],\r\n disableSideHack?: boolean,\r\n startElementBounds?: Bounds | null,\r\n endElementBounds?: Bounds | null,\r\n): Bounds[] => {\r\n const startEl = startElementBounds ?? a;\r\n const endEl = endElementBounds ?? b;\r\n const [startUp, startRight, startDown, startLeft] = startDifference ?? [\r\n 0, 0, 0, 0,\r\n ];\r\n const [endUp, endRight, endDown, endLeft] = endDifference ?? [0, 0, 0, 0];\r\n\r\n const first = [\r\n a[0] > b[2]\r\n ? a[1] > b[3] || a[3] < b[1]\r\n ? Math.min((startEl[0] + endEl[2]) / 2, a[0] - startLeft)\r\n : (startEl[0] + endEl[2]) / 2\r\n : a[0] > b[0]\r\n ? a[0] - startLeft\r\n : common[0] - startLeft,\r\n a[1] > b[3]\r\n ? a[0] > b[2] || a[2] < b[0]\r\n ? Math.min((startEl[1] + endEl[3]) / 2, a[1] - startUp)\r\n : (startEl[1] + endEl[3]) / 2\r\n : a[1] > b[1]\r\n ? a[1] - startUp\r\n : common[1] - startUp,\r\n a[2] < b[0]\r\n ? a[1] > b[3] || a[3] < b[1]\r\n ? Math.max((startEl[2] + endEl[0]) / 2, a[2] + startRight)\r\n : (startEl[2] + endEl[0]) / 2\r\n : a[2] < b[2]\r\n ? a[2] + startRight\r\n : common[2] + startRight,\r\n a[3] < b[1]\r\n ? a[0] > b[2] || a[2] < b[0]\r\n ? Math.max((startEl[3] + endEl[1]) / 2, a[3] + startDown)\r\n : (startEl[3] + endEl[1]) / 2\r\n : a[3] < b[3]\r\n ? a[3] + startDown\r\n : common[3] + startDown,\r\n ] as Bounds;\r\n const second = [\r\n b[0] > a[2]\r\n ? b[1] > a[3] || b[3] < a[1]\r\n ? Math.min((endEl[0] + startEl[2]) / 2, b[0] - endLeft)\r\n : (endEl[0] + startEl[2]) / 2\r\n : b[0] > a[0]\r\n ? b[0] - endLeft\r\n : common[0] - endLeft,\r\n b[1] > a[3]\r\n ? b[0] > a[2] || b[2] < a[0]\r\n ? Math.min((endEl[1] + startEl[3]) / 2, b[1] - endUp)\r\n : (endEl[1] + startEl[3]) / 2\r\n : b[1] > a[1]\r\n ? b[1] - endUp\r\n : common[1] - endUp,\r\n b[2] < a[0]\r\n ? b[1] > a[3] || b[3] < a[1]\r\n ? Math.max((endEl[2] + startEl[0]) / 2, b[2] + endRight)\r\n : (endEl[2] + startEl[0]) / 2\r\n : b[2] < a[2]\r\n ? b[2] + endRight\r\n : common[2] + endRight,\r\n b[3] < a[1]\r\n ? b[0] > a[2] || b[2] < a[0]\r\n ? Math.max((endEl[3] + startEl[1]) / 2, b[3] + endDown)\r\n : (endEl[3] + startEl[1]) / 2\r\n : b[3] < a[3]\r\n ? b[3] + endDown\r\n : common[3] + endDown,\r\n ] as Bounds;\r\n\r\n const c = commonAABB([first, second]);\r\n if (\r\n !disableSideHack &&\r\n first[2] - first[0] + second[2] - second[0] > c[2] - c[0] + 0.00000000001 &&\r\n first[3] - first[1] + second[3] - second[1] > c[3] - c[1] + 0.00000000001\r\n ) {\r\n const [endCenterX, endCenterY] = [\r\n (second[0] + second[2]) / 2,\r\n (second[1] + second[3]) / 2,\r\n ];\r\n if (b[0] > a[2] && a[1] > b[3]) {\r\n // BOTTOM LEFT\r\n const cX = first[2] + (second[0] - first[2]) / 2;\r\n const cY = second[3] + (first[1] - second[3]) / 2;\r\n\r\n if (\r\n vectorCross(\r\n vector(a[2] - endCenterX, a[1] - endCenterY),\r\n vector(a[0] - endCenterX, a[3] - endCenterY),\r\n ) > 0\r\n ) {\r\n return [\r\n [first[0], first[1], cX, first[3]],\r\n [cX, second[1], second[2], second[3]],\r\n ];\r\n }\r\n\r\n return [\r\n [first[0], cY, first[2], first[3]],\r\n [second[0], second[1], second[2], cY],\r\n ];\r\n } else if (a[2] < b[0] && a[3] < b[1]) {\r\n // TOP LEFT\r\n const cX = first[2] + (second[0] - first[2]) / 2;\r\n const cY = first[3] + (second[1] - first[3]) / 2;\r\n\r\n if (\r\n vectorCross(\r\n vector(a[0] - endCenterX, a[1] - endCenterY),\r\n vector(a[2] - endCenterX, a[3] - endCenterY),\r\n ) > 0\r\n ) {\r\n return [\r\n [first[0], first[1], first[2], cY],\r\n [second[0], cY, second[2], second[3]],\r\n ];\r\n }\r\n\r\n return [\r\n [first[0], first[1], cX, first[3]],\r\n [cX, second[1], second[2], second[3]],\r\n ];\r\n } else if (a[0] > b[2] && a[3] < b[1]) {\r\n // TOP RIGHT\r\n const cX = second[2] + (first[0] - second[2]) / 2;\r\n const cY = first[3] + (second[1] - first[3]) / 2;\r\n\r\n if (\r\n vectorCross(\r\n vector(a[2] - endCenterX, a[1] - endCenterY),\r\n vector(a[0] - endCenterX, a[3] - endCenterY),\r\n ) > 0\r\n ) {\r\n return [\r\n [cX, first[1], first[2], first[3]],\r\n [second[0], second[1], cX, second[3]],\r\n ];\r\n }\r\n\r\n return [\r\n [first[0], first[1], first[2], cY],\r\n [second[0], cY, second[2], second[3]],\r\n ];\r\n } else if (a[0] > b[2] && a[1] > b[3]) {\r\n // BOTTOM RIGHT\r\n const cX = second[2] + (first[0] - second[2]) / 2;\r\n const cY = second[3] + (first[1] - second[3]) / 2;\r\n\r\n if (\r\n vectorCross(\r\n vector(a[0] - endCenterX, a[1] - endCenterY),\r\n vector(a[2] - endCenterX, a[3] - endCenterY),\r\n ) > 0\r\n ) {\r\n return [\r\n [cX, first[1], first[2], first[3]],\r\n [second[0], second[1], cX, second[3]],\r\n ];\r\n }\r\n\r\n return [\r\n [first[0], cY, first[2], first[3]],\r\n [second[0], second[1], second[2], cY],\r\n ];\r\n }\r\n }\r\n\r\n return [first, second];\r\n};\r\n\r\n/**\r\n * Calculates the grid which is used as nodes at\r\n * the grid line intersections by the A* algorithm.\r\n *\r\n * NOTE: This is not a uniform grid. It is built at\r\n * various intersections of bounding boxes.\r\n */\r\nconst calculateGrid = (\r\n aabbs: Bounds[],\r\n start: GlobalPoint,\r\n startHeading: Heading,\r\n end: GlobalPoint,\r\n endHeading: Heading,\r\n common: Bounds,\r\n): Grid => {\r\n const horizontal = new Set<number>();\r\n const vertical = new Set<number>();\r\n\r\n if (startHeading === HEADING_LEFT || startHeading === HEADING_RIGHT) {\r\n vertical.add(start[1]);\r\n } else {\r\n horizontal.add(start[0]);\r\n }\r\n if (endHeading === HEADING_LEFT || endHeading === HEADING_RIGHT) {\r\n vertical.add(end[1]);\r\n } else {\r\n horizontal.add(end[0]);\r\n }\r\n\r\n aabbs.forEach((aabb) => {\r\n horizontal.add(aabb[0]);\r\n horizontal.add(aabb[2]);\r\n vertical.add(aabb[1]);\r\n vertical.add(aabb[3]);\r\n });\r\n\r\n horizontal.add(common[0]);\r\n horizontal.add(common[2]);\r\n vertical.add(common[1]);\r\n vertical.add(common[3]);\r\n\r\n const _vertical = Array.from(vertical).sort((a, b) => a - b);\r\n const _horizontal = Array.from(horizontal).sort((a, b) => a - b);\r\n\r\n return {\r\n row: _vertical.length,\r\n col: _horizontal.length,\r\n data: _vertical.flatMap((y, row) =>\r\n _horizontal.map(\r\n (x, col): Node => ({\r\n f: 0,\r\n g: 0,\r\n h: 0,\r\n closed: false,\r\n visited: false,\r\n parent: null,\r\n addr: [col, row] as GridAddress,\r\n pos: [x, y] as GlobalPoint,\r\n }),\r\n ),\r\n ),\r\n };\r\n};\r\n\r\nconst getDonglePosition = (\r\n bounds: Bounds,\r\n heading: Heading,\r\n p: GlobalPoint,\r\n): GlobalPoint => {\r\n switch (heading) {\r\n case HEADING_UP:\r\n return pointFrom(p[0], bounds[1]);\r\n case HEADING_RIGHT:\r\n return pointFrom(bounds[2], p[1]);\r\n case HEADING_DOWN:\r\n return pointFrom(p[0], bounds[3]);\r\n }\r\n return pointFrom(bounds[0], p[1]);\r\n};\r\n\r\nconst estimateSegmentCount = (\r\n start: Node,\r\n end: Node,\r\n startHeading: Heading,\r\n endHeading: Heading,\r\n) => {\r\n if (endHeading === HEADING_RIGHT) {\r\n switch (startHeading) {\r\n case HEADING_RIGHT: {\r\n if (start.pos[0] >= end.pos[0]) {\r\n return 4;\r\n }\r\n if (start.pos[1] === end.pos[1]) {\r\n return 0;\r\n }\r\n return 2;\r\n }\r\n case HEADING_UP:\r\n if (start.pos[1] > end.pos[1] && start.pos[0] < end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n case HEADING_DOWN:\r\n if (start.pos[1] < end.pos[1] && start.pos[0] < end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n case HEADING_LEFT:\r\n if (start.pos[1] === end.pos[1]) {\r\n return 4;\r\n }\r\n return 2;\r\n }\r\n } else if (endHeading === HEADING_LEFT) {\r\n switch (startHeading) {\r\n case HEADING_RIGHT:\r\n if (start.pos[1] === end.pos[1]) {\r\n return 4;\r\n }\r\n return 2;\r\n case HEADING_UP:\r\n if (start.pos[1] > end.pos[1] && start.pos[0] > end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n case HEADING_DOWN:\r\n if (start.pos[1] < end.pos[1] && start.pos[0] > end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n case HEADING_LEFT:\r\n if (start.pos[0] <= end.pos[0]) {\r\n return 4;\r\n }\r\n if (start.pos[1] === end.pos[1]) {\r\n return 0;\r\n }\r\n return 2;\r\n }\r\n } else if (endHeading === HEADING_UP) {\r\n switch (startHeading) {\r\n case HEADING_RIGHT:\r\n if (start.pos[1] > end.pos[1] && start.pos[0] < end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n case HEADING_UP:\r\n if (start.pos[1] >= end.pos[1]) {\r\n return 4;\r\n }\r\n if (start.pos[0] === end.pos[0]) {\r\n return 0;\r\n }\r\n return 2;\r\n case HEADING_DOWN:\r\n if (start.pos[0] === end.pos[0]) {\r\n return 4;\r\n }\r\n return 2;\r\n case HEADING_LEFT:\r\n if (start.pos[1] > end.pos[1] && start.pos[0] > end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n }\r\n } else if (endHeading === HEADING_DOWN) {\r\n switch (startHeading) {\r\n case HEADING_RIGHT:\r\n if (start.pos[1] < end.pos[1] && start.pos[0] < end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n case HEADING_UP:\r\n if (start.pos[0] === end.pos[0]) {\r\n return 4;\r\n }\r\n return 2;\r\n case HEADING_DOWN:\r\n if (start.pos[1] <= end.pos[1]) {\r\n return 4;\r\n }\r\n if (start.pos[0] === end.pos[0]) {\r\n return 0;\r\n }\r\n return 2;\r\n case HEADING_LEFT:\r\n if (start.pos[1] < end.pos[1] && start.pos[0] > end.pos[0]) {\r\n return 1;\r\n }\r\n return 3;\r\n }\r\n }\r\n return 0;\r\n};\r\n\r\n/**\r\n * Get neighboring points for a gived grid address\r\n */\r\nconst getNeighbors = ([col, row]: [number, number], grid: Grid) =>\r\n [\r\n gridNodeFromAddr([col, row - 1], grid),\r\n gridNodeFromAddr([col + 1, row], grid),\r\n gridNodeFromAddr([col, row + 1], grid),\r\n gridNodeFromAddr([col - 1, row], grid),\r\n ] as [Node | null, Node | null, Node | null, Node | null];\r\n\r\nconst gridNodeFromAddr = (\r\n [col, row]: [col: number, row: number],\r\n grid: Grid,\r\n): Node | null => {\r\n if (col < 0 || col >= grid.col || row < 0 || row >= grid.row) {\r\n return null;\r\n }\r\n\r\n return grid.data[row * grid.col + col] ?? null;\r\n};\r\n\r\n/**\r\n * Get node for global point on canvas (if exists)\r\n */\r\nconst pointToGridNode = (point: GlobalPoint, grid: Grid): Node | null => {\r\n for (let col = 0; col < grid.col; col++) {\r\n for (let row = 0; row < grid.row; row++) {\r\n const candidate = gridNodeFromAddr([col, row], grid);\r\n if (\r\n candidate &&\r\n point[0] === candidate.pos[0] &&\r\n point[1] === candidate.pos[1]\r\n ) {\r\n return candidate;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst commonAABB = (aabbs: Bounds[]): Bounds => [\r\n Math.min(...aabbs.map((aabb) => aabb[0])),\r\n Math.min(...aabbs.map((aabb) => aabb[1])),\r\n Math.max(...aabbs.map((aabb) => aabb[2])),\r\n Math.max(...aabbs.map((aabb) => aabb[3])),\r\n];\r\n\r\n/// #region Utils\r\n\r\nconst getBindableElementForId = (\r\n id: string,\r\n elementsMap: ElementsMap,\r\n): ExcalidrawBindableElement | null => {\r\n const element = elementsMap.get(id);\r\n if (element && isBindableElement(element)) {\r\n return element;\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst normalizeArrowElementUpdate = (\r\n global: GlobalPoint[],\r\n nextFixedSegments: readonly FixedSegment[] | null,\r\n startIsSpecial?: ExcalidrawElbowArrowElement[\"startIsSpecial\"],\r\n endIsSpecial?: ExcalidrawElbowArrowElement[\"startIsSpecial\"],\r\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\r\n const offsetX = global[0][0];\r\n const offsetY = global[0][1];\r\n let points = global.map((p) =>\r\n pointTranslate<GlobalPoint, LocalPoint>(\r\n p,\r\n vectorScale(vectorFromPoint(global[0]), -1),\r\n ),\r\n );\r\n\r\n // NOTE (mtolmacs): This is a temporary check to see if the normalization\r\n // creates an overly large arrow. This should be removed once we have an answer.\r\n if (\r\n offsetX < -MAX_POS ||\r\n offsetX > MAX_POS ||\r\n offsetY < -MAX_POS ||\r\n offsetY > MAX_POS ||\r\n offsetX + points[points.length - 1][0] < -MAX_POS ||\r\n offsetY + points[points.length - 1][0] > MAX_POS ||\r\n offsetX + points[points.length - 1][1] < -MAX_POS ||\r\n offsetY + points[points.length - 1][1] > MAX_POS\r\n ) {\r\n console.error(\r\n \"Elbow arrow normalization is outside reasonable bounds (> 1e6)\",\r\n {\r\n x: offsetX,\r\n y: offsetY,\r\n points,\r\n ...getSizeFromPoints(points),\r\n },\r\n );\r\n }\r\n\r\n points = points.map(([x, y]) =>\r\n pointFrom<LocalPoint>(clamp(x, -1e6, 1e6), clamp(y, -1e6, 1e6)),\r\n );\r\n\r\n return {\r\n points,\r\n x: clamp(offsetX, -1e6, 1e6),\r\n y: clamp(offsetY, -1e6, 1e6),\r\n fixedSegments:\r\n (nextFixedSegments?.length ?? 0) > 0 ? nextFixedSegments : null,\r\n ...getSizeFromPoints(points),\r\n startIsSpecial,\r\n endIsSpecial,\r\n };\r\n};\r\n\r\nconst getElbowArrowCornerPoints = (points: GlobalPoint[]): GlobalPoint[] => {\r\n if (points.length > 1) {\r\n let previousHorizontal =\r\n Math.abs(points[0][1] - points[1][1]) <\r\n Math.abs(points[0][0] - points[1][0]);\r\n\r\n return points.filter((p, idx) => {\r\n // The very first and last points are always kept\r\n if (idx === 0 || idx === points.length - 1) {\r\n return true;\r\n }\r\n\r\n const next = points[idx + 1];\r\n const nextHorizontal =\r\n Math.abs(p[1] - next[1]) < Math.abs(p[0] - next[0]);\r\n if (previousHorizontal === nextHorizontal) {\r\n previousHorizontal = nextHorizontal;\r\n return false;\r\n }\r\n\r\n previousHorizontal = nextHorizontal;\r\n return true;\r\n });\r\n }\r\n\r\n return points;\r\n};\r\n\r\nconst removeElbowArrowShortSegments = (\r\n points: GlobalPoint[],\r\n): GlobalPoint[] => {\r\n if (points.length >= 4) {\r\n return points.filter((p, idx) => {\r\n if (idx === 0 || idx === points.length - 1) {\r\n return true;\r\n }\r\n\r\n const prev = points[idx - 1];\r\n const prevDist = pointDistance(prev, p);\r\n return prevDist > DEDUP_TRESHOLD;\r\n });\r\n }\r\n\r\n return points;\r\n};\r\n\r\nconst neighborIndexToHeading = (idx: number): Heading => {\r\n switch (idx) {\r\n case 0:\r\n return HEADING_UP;\r\n case 1:\r\n return HEADING_RIGHT;\r\n case 2:\r\n return HEADING_DOWN;\r\n }\r\n return HEADING_LEFT;\r\n};\r\n\r\nconst getGlobalPoint = (\r\n arrow: ExcalidrawElbowArrowElement,\r\n startOrEnd: \"start\" | \"end\",\r\n fixedPointRatio: [number, number] | undefined | null,\r\n initialPoint: GlobalPoint,\r\n element?: ExcalidrawBindableElement | null,\r\n elementsMap?: ElementsMap,\r\n isDragging?: boolean,\r\n): GlobalPoint => {\r\n if (isDragging) {\r\n if (element && elementsMap) {\r\n return bindPointToSnapToElementOutline(\r\n arrow,\r\n element,\r\n startOrEnd,\r\n elementsMap,\r\n );\r\n }\r\n\r\n return initialPoint;\r\n }\r\n\r\n if (element) {\r\n return getGlobalFixedPointForBindableElement(\r\n fixedPointRatio || [0, 0],\r\n element,\r\n elementsMap ?? arrayToMap([element]),\r\n );\r\n }\r\n\r\n return initialPoint;\r\n};\r\n\r\nconst getBindPointHeading = (\r\n p: GlobalPoint,\r\n otherPoint: GlobalPoint,\r\n hoveredElement: ExcalidrawBindableElement | null | undefined,\r\n origPoint: GlobalPoint,\r\n elementsMap: ElementsMap,\r\n zoom?: AppState[\"zoom\"],\r\n): Heading =>\r\n getHeadingForElbowArrowSnap(\r\n p,\r\n otherPoint,\r\n hoveredElement,\r\n hoveredElement &&\r\n aabbForElement(\r\n hoveredElement,\r\n elementsMap,\r\n Array(4).fill(distanceToElement(hoveredElement, elementsMap, p)) as [\r\n number,\r\n number,\r\n number,\r\n number,\r\n ],\r\n ),\r\n origPoint,\r\n elementsMap,\r\n zoom,\r\n );\r\n\r\nconst getHoveredElement = (\r\n origPoint: GlobalPoint,\r\n elementsMap: NonDeletedSceneElementsMap,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n zoom?: AppState[\"zoom\"],\r\n) => {\r\n return getHoveredElementForBinding(\r\n origPoint,\r\n elements,\r\n elementsMap,\r\n (element) => maxBindingDistance_simple(zoom),\r\n );\r\n};\r\n\r\nconst gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean =>\r\n a[0] === b[0] && a[1] === b[1];\r\n\r\nexport const validateElbowPoints = <P extends GlobalPoint | LocalPoint>(\r\n points: readonly P[],\r\n tolerance: number = DEDUP_TRESHOLD,\r\n) =>\r\n points\r\n .slice(1)\r\n .map(\r\n (p, i) =>\r\n Math.abs(p[0] - points[i][0]) < tolerance ||\r\n Math.abs(p[1] - points[i][1]) < tolerance,\r\n )\r\n .every(Boolean);\r\n", "import { arrayToMap } from \"@excalidraw-modify/common\";\r\nimport { isPointWithinBounds, pointFrom } from \"@excalidraw-modify/math\";\r\nimport { doLineSegmentsIntersect } from \"@excalidraw/utils/bbox\";\r\nimport { elementsOverlappingBBox } from \"@excalidraw/utils/withinBounds\";\r\n\r\nimport type {\r\n AppClassProperties,\r\n AppState,\r\n StaticCanvasAppState,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type { ReadonlySetLike } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport { getElementsWithinSelection, getSelectedElements } from \"./selection\";\r\nimport { getElementsInGroup, selectGroupsFromGivenElements } from \"./groups\";\r\n\r\nimport {\r\n getElementLineSegments,\r\n getCommonBounds,\r\n getElementAbsoluteCoords,\r\n} from \"./bounds\";\r\nimport { mutateElement } from \"./mutateElement\";\r\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\r\nimport {\r\n isFrameElement,\r\n isFrameLikeElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport type { ExcalidrawElementsIncludingDeleted } from \"./Scene\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ElementsMapOrArray,\r\n ExcalidrawElement,\r\n ExcalidrawFrameLikeElement,\r\n NonDeleted,\r\n NonDeletedExcalidrawElement,\r\n} from \"./types\";\r\n\r\n// --------------------------- Frame State ------------------------------------\r\nexport const bindElementsToFramesAfterDuplication = (\r\n nextElements: readonly ExcalidrawElement[],\r\n origElements: readonly ExcalidrawElement[],\r\n origIdToDuplicateId: Map<ExcalidrawElement[\"id\"], ExcalidrawElement[\"id\"]>,\r\n) => {\r\n const nextElementMap = arrayToMap(nextElements) as Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement\r\n >;\r\n\r\n for (const element of origElements) {\r\n if (element.frameId) {\r\n // use its frameId to get the new frameId\r\n const nextElementId = origIdToDuplicateId.get(element.id);\r\n const nextFrameId = origIdToDuplicateId.get(element.frameId);\r\n const nextElement = nextElementId && nextElementMap.get(nextElementId);\r\n if (nextElement) {\r\n mutateElement(nextElement, nextElementMap, {\r\n frameId: nextFrameId ?? null,\r\n });\r\n }\r\n }\r\n }\r\n};\r\n\r\nexport function isElementIntersectingFrame(\r\n element: ExcalidrawElement,\r\n frame: ExcalidrawFrameLikeElement,\r\n elementsMap: ElementsMap,\r\n) {\r\n const frameLineSegments = getElementLineSegments(frame, elementsMap);\r\n\r\n const elementLineSegments = getElementLineSegments(element, elementsMap);\r\n\r\n const intersecting = frameLineSegments.some((frameLineSegment) =>\r\n elementLineSegments.some((elementLineSegment) =>\r\n doLineSegmentsIntersect(frameLineSegment, elementLineSegment),\r\n ),\r\n );\r\n\r\n return intersecting;\r\n}\r\n\r\nexport const getElementsCompletelyInFrame = (\r\n elements: readonly ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n elementsMap: ElementsMap,\r\n) =>\r\n omitGroupsContainingFrameLikes(\r\n getElementsWithinSelection(elements, frame, elementsMap, false),\r\n ).filter(\r\n (element) =>\r\n (!isFrameLikeElement(element) && !element.frameId) ||\r\n element.frameId === frame.id,\r\n );\r\n\r\nexport const isElementContainingFrame = (\r\n element: ExcalidrawElement,\r\n frame: ExcalidrawFrameLikeElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n return getElementsWithinSelection([frame], element, elementsMap).some(\r\n (e) => e.id === frame.id,\r\n );\r\n};\r\n\r\nexport const getElementsIntersectingFrame = (\r\n elements: readonly ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n) => {\r\n const elementsMap = arrayToMap(elements);\r\n return elements.filter((element) =>\r\n isElementIntersectingFrame(element, frame, elementsMap),\r\n );\r\n};\r\n\r\nexport const elementsAreInFrameBounds = (\r\n elements: readonly ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n const [frameX1, frameY1, frameX2, frameY2] = getElementAbsoluteCoords(\r\n frame,\r\n elementsMap,\r\n );\r\n\r\n const [elementX1, elementY1, elementX2, elementY2] =\r\n getCommonBounds(elements);\r\n\r\n return (\r\n frameX1 <= elementX1 &&\r\n frameY1 <= elementY1 &&\r\n frameX2 >= elementX2 &&\r\n frameY2 >= elementY2\r\n );\r\n};\r\n\r\nexport const elementOverlapsWithFrame = (\r\n element: ExcalidrawElement,\r\n frame: ExcalidrawFrameLikeElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n return (\r\n elementsAreInFrameBounds([element], frame, elementsMap) ||\r\n isElementIntersectingFrame(element, frame, elementsMap) ||\r\n isElementContainingFrame(element, frame, elementsMap)\r\n );\r\n};\r\n\r\nexport const isCursorInFrame = (\r\n cursorCoords: {\r\n x: number;\r\n y: number;\r\n },\r\n frame: NonDeleted<ExcalidrawFrameLikeElement>,\r\n elementsMap: ElementsMap,\r\n) => {\r\n const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);\r\n\r\n return isPointWithinBounds(\r\n pointFrom(fx1, fy1),\r\n pointFrom(cursorCoords.x, cursorCoords.y),\r\n pointFrom(fx2, fy2),\r\n );\r\n};\r\n\r\nexport const groupsAreAtLeastIntersectingTheFrame = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n groupIds: readonly string[],\r\n frame: ExcalidrawFrameLikeElement,\r\n) => {\r\n const elementsMap = arrayToMap(elements);\r\n const elementsInGroup = groupIds.flatMap((groupId) =>\r\n getElementsInGroup(elements, groupId),\r\n );\r\n\r\n if (elementsInGroup.length === 0) {\r\n return true;\r\n }\r\n\r\n return !!elementsInGroup.find(\r\n (element) =>\r\n elementsAreInFrameBounds([element], frame, elementsMap) ||\r\n isElementIntersectingFrame(element, frame, elementsMap),\r\n );\r\n};\r\n\r\nexport const groupsAreCompletelyOutOfFrame = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n groupIds: readonly string[],\r\n frame: ExcalidrawFrameLikeElement,\r\n) => {\r\n const elementsMap = arrayToMap(elements);\r\n const elementsInGroup = groupIds.flatMap((groupId) =>\r\n getElementsInGroup(elements, groupId),\r\n );\r\n\r\n if (elementsInGroup.length === 0) {\r\n return true;\r\n }\r\n\r\n return (\r\n elementsInGroup.find(\r\n (element) =>\r\n elementsAreInFrameBounds([element], frame, elementsMap) ||\r\n isElementIntersectingFrame(element, frame, elementsMap),\r\n ) === undefined\r\n );\r\n};\r\n\r\n// --------------------------- Frame Utils ------------------------------------\r\n\r\n/**\r\n * Returns a map of frameId to frame elements. Includes empty frames.\r\n */\r\nexport const groupByFrameLikes = (elements: readonly ExcalidrawElement[]) => {\r\n const frameElementsMap = new Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement[]\r\n >();\r\n\r\n for (const element of elements) {\r\n const frameId = isFrameLikeElement(element) ? element.id : element.frameId;\r\n if (frameId && !frameElementsMap.has(frameId)) {\r\n frameElementsMap.set(frameId, getFrameChildren(elements, frameId));\r\n }\r\n }\r\n\r\n return frameElementsMap;\r\n};\r\n\r\nexport const getFrameChildren = (\r\n allElements: ElementsMapOrArray,\r\n frameId: string,\r\n) => {\r\n const frameChildren: ExcalidrawElement[] = [];\r\n for (const element of allElements.values()) {\r\n if (element.frameId === frameId) {\r\n frameChildren.push(element);\r\n }\r\n }\r\n return frameChildren;\r\n};\r\n\r\nexport const getFrameLikeElements = (\r\n allElements: ExcalidrawElementsIncludingDeleted,\r\n): ExcalidrawFrameLikeElement[] => {\r\n return allElements.filter((element): element is ExcalidrawFrameLikeElement =>\r\n isFrameLikeElement(element),\r\n );\r\n};\r\n\r\n/**\r\n * Returns ExcalidrawFrameElements and non-frame-children elements.\r\n *\r\n * Considers children as root elements if they point to a frame parent\r\n * non-existing in the elements set.\r\n *\r\n * Considers non-frame bound elements (container or arrow labels) as root.\r\n */\r\nexport const getRootElements = (\r\n allElements: ExcalidrawElementsIncludingDeleted,\r\n) => {\r\n const frameElements = arrayToMap(getFrameLikeElements(allElements));\r\n return allElements.filter(\r\n (element) =>\r\n frameElements.has(element.id) ||\r\n !element.frameId ||\r\n !frameElements.has(element.frameId),\r\n );\r\n};\r\n\r\nexport const getElementsInResizingFrame = (\r\n allElements: ExcalidrawElementsIncludingDeleted,\r\n frame: ExcalidrawFrameLikeElement,\r\n appState: AppState,\r\n elementsMap: ElementsMap,\r\n): ExcalidrawElement[] => {\r\n const prevElementsInFrame = getFrameChildren(allElements, frame.id);\r\n const nextElementsInFrame = new Set<ExcalidrawElement>(prevElementsInFrame);\r\n\r\n const elementsCompletelyInFrame = new Set([\r\n ...getElementsCompletelyInFrame(allElements, frame, elementsMap),\r\n ...prevElementsInFrame.filter((element) =>\r\n isElementContainingFrame(element, frame, elementsMap),\r\n ),\r\n ]);\r\n\r\n const elementsNotCompletelyInFrame = prevElementsInFrame.filter(\r\n (element) => !elementsCompletelyInFrame.has(element),\r\n );\r\n\r\n // for elements that are completely in the frame\r\n // if they are part of some groups, then those groups are still\r\n // considered to belong to the frame\r\n const groupsToKeep = new Set<string>(\r\n Array.from(elementsCompletelyInFrame).flatMap(\r\n (element) => element.groupIds,\r\n ),\r\n );\r\n\r\n for (const element of elementsNotCompletelyInFrame) {\r\n if (!isElementIntersectingFrame(element, frame, elementsMap)) {\r\n if (element.groupIds.length === 0) {\r\n nextElementsInFrame.delete(element);\r\n }\r\n } else if (element.groupIds.length > 0) {\r\n // group element intersects with the frame, we should keep the groups\r\n // that this element is part of\r\n for (const id of element.groupIds) {\r\n groupsToKeep.add(id);\r\n }\r\n }\r\n }\r\n\r\n for (const element of elementsNotCompletelyInFrame) {\r\n if (element.groupIds.length > 0) {\r\n let shouldRemoveElement = true;\r\n\r\n for (const id of element.groupIds) {\r\n if (groupsToKeep.has(id)) {\r\n shouldRemoveElement = false;\r\n }\r\n }\r\n\r\n if (shouldRemoveElement) {\r\n nextElementsInFrame.delete(element);\r\n }\r\n }\r\n }\r\n\r\n const individualElementsCompletelyInFrame = Array.from(\r\n elementsCompletelyInFrame,\r\n ).filter((element) => element.groupIds.length === 0);\r\n\r\n for (const element of individualElementsCompletelyInFrame) {\r\n nextElementsInFrame.add(element);\r\n }\r\n\r\n const newGroupElementsCompletelyInFrame = Array.from(\r\n elementsCompletelyInFrame,\r\n ).filter((element) => element.groupIds.length > 0);\r\n\r\n const groupIds = selectGroupsFromGivenElements(\r\n newGroupElementsCompletelyInFrame,\r\n appState,\r\n );\r\n\r\n // new group elements\r\n for (const [id, isSelected] of Object.entries(groupIds)) {\r\n if (isSelected) {\r\n const elementsInGroup = getElementsInGroup(allElements, id);\r\n\r\n if (elementsAreInFrameBounds(elementsInGroup, frame, elementsMap)) {\r\n for (const element of elementsInGroup) {\r\n nextElementsInFrame.add(element);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return [...nextElementsInFrame].filter((element) => {\r\n return !(isTextElement(element) && element.containerId);\r\n });\r\n};\r\n\r\nexport const getElementsInNewFrame = (\r\n elements: ExcalidrawElementsIncludingDeleted,\r\n frame: ExcalidrawFrameLikeElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n return omitPartialGroups(\r\n omitGroupsContainingFrameLikes(\r\n elements,\r\n getElementsCompletelyInFrame(elements, frame, elementsMap),\r\n ),\r\n frame,\r\n elementsMap,\r\n );\r\n};\r\n\r\nexport const omitPartialGroups = (\r\n elements: ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n allElementsMap: ElementsMap,\r\n) => {\r\n const elementsToReturn = [];\r\n const checkedGroups = new Map<string, boolean>();\r\n\r\n for (const element of elements) {\r\n let shouldOmit = false;\r\n if (element.groupIds.length > 0) {\r\n // if some partial group should be omitted, then all elements in that group should be omitted\r\n if (element.groupIds.some((gid) => checkedGroups.get(gid))) {\r\n shouldOmit = true;\r\n } else {\r\n const allElementsInGroup = new Set(\r\n element.groupIds.flatMap((gid) =>\r\n getElementsInGroup(allElementsMap, gid),\r\n ),\r\n );\r\n\r\n shouldOmit = !elementsAreInFrameBounds(\r\n Array.from(allElementsInGroup),\r\n frame,\r\n allElementsMap,\r\n );\r\n }\r\n\r\n element.groupIds.forEach((gid) => {\r\n checkedGroups.set(gid, shouldOmit);\r\n });\r\n }\r\n\r\n if (!shouldOmit) {\r\n elementsToReturn.push(element);\r\n }\r\n }\r\n\r\n return elementsToReturn;\r\n};\r\n\r\nexport const getContainingFrame = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n if (!element.frameId) {\r\n return null;\r\n }\r\n return (elementsMap.get(element.frameId) ||\r\n null) as null | ExcalidrawFrameLikeElement;\r\n};\r\n\r\n// --------------------------- Frame Operations -------------------------------\r\n\r\n/** */\r\nexport const filterElementsEligibleAsFrameChildren = (\r\n elements: readonly ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n) => {\r\n const otherFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>();\r\n const elementsMap = arrayToMap(elements);\r\n elements = omitGroupsContainingFrameLikes(elements);\r\n\r\n for (const element of elements) {\r\n if (isFrameLikeElement(element) && element.id !== frame.id) {\r\n otherFrames.add(element.id);\r\n }\r\n }\r\n\r\n const processedGroups = new Set<ExcalidrawElement[\"id\"]>();\r\n\r\n const eligibleElements: ExcalidrawElement[] = [];\r\n\r\n for (const element of elements) {\r\n // don't add frames or their children\r\n if (\r\n isFrameLikeElement(element) ||\r\n (element.frameId && otherFrames.has(element.frameId))\r\n ) {\r\n continue;\r\n }\r\n\r\n if (element.groupIds.length) {\r\n const shallowestGroupId = element.groupIds.at(-1)!;\r\n if (!processedGroups.has(shallowestGroupId)) {\r\n processedGroups.add(shallowestGroupId);\r\n const groupElements = getElementsInGroup(elements, shallowestGroupId);\r\n if (\r\n groupElements.some((el) =>\r\n elementOverlapsWithFrame(el, frame, elementsMap),\r\n )\r\n ) {\r\n for (const child of groupElements) {\r\n eligibleElements.push(child);\r\n }\r\n }\r\n }\r\n } else {\r\n const overlaps = elementOverlapsWithFrame(element, frame, elementsMap);\r\n if (overlaps) {\r\n eligibleElements.push(element);\r\n }\r\n }\r\n }\r\n\r\n return eligibleElements;\r\n};\r\n\r\n/**\r\n * Retains (or repairs for target frame) the ordering invriant where children\r\n * elements come right before the parent frame:\r\n * [el, el, child, child, frame, el]\r\n *\r\n * @returns mutated allElements (same data structure)\r\n */\r\nexport const addElementsToFrame = <T extends ElementsMapOrArray>(\r\n allElements: T,\r\n elementsToAdd: NonDeletedExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n appState: AppState,\r\n): T => {\r\n const elementsMap = arrayToMap(allElements);\r\n const currTargetFrameChildrenMap = new Map<ExcalidrawElement[\"id\"], true>();\r\n for (const element of allElements.values()) {\r\n if (element.frameId === frame.id) {\r\n currTargetFrameChildrenMap.set(element.id, true);\r\n }\r\n }\r\n\r\n const suppliedElementsToAddSet = new Set(elementsToAdd.map((el) => el.id));\r\n\r\n const finalElementsToAdd: ExcalidrawElement[] = [];\r\n\r\n const otherFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>();\r\n\r\n for (const element of elementsToAdd) {\r\n if (isFrameLikeElement(element) && element.id !== frame.id) {\r\n otherFrames.add(element.id);\r\n }\r\n }\r\n\r\n // - add bound text elements if not already in the array\r\n // - filter out elements that are already in the frame\r\n for (const element of omitGroupsContainingFrameLikes(\r\n allElements,\r\n elementsToAdd,\r\n )) {\r\n // don't add frames or their children\r\n if (\r\n isFrameLikeElement(element) ||\r\n (element.frameId && otherFrames.has(element.frameId))\r\n ) {\r\n continue;\r\n }\r\n\r\n // if the element is already in another frame (which is also in elementsToAdd),\r\n // it means that frame and children are selected at the same time\r\n // => keep original frame membership, do not add to the target frame\r\n if (\r\n element.frameId &&\r\n appState.selectedElementIds[element.id] &&\r\n appState.selectedElementIds[element.frameId]\r\n ) {\r\n continue;\r\n }\r\n\r\n if (!currTargetFrameChildrenMap.has(element.id)) {\r\n finalElementsToAdd.push(element);\r\n }\r\n\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n if (\r\n boundTextElement &&\r\n !suppliedElementsToAddSet.has(boundTextElement.id) &&\r\n !currTargetFrameChildrenMap.has(boundTextElement.id)\r\n ) {\r\n finalElementsToAdd.push(boundTextElement);\r\n }\r\n }\r\n\r\n for (const element of finalElementsToAdd) {\r\n mutateElement(element, elementsMap, {\r\n frameId: frame.id,\r\n });\r\n }\r\n\r\n return allElements;\r\n};\r\n\r\nexport const removeElementsFromFrame = (\r\n elementsToRemove: ReadonlySetLike<NonDeletedExcalidrawElement>,\r\n elementsMap: ElementsMap,\r\n) => {\r\n const _elementsToRemove = new Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement\r\n >();\r\n\r\n const toRemoveElementsByFrame = new Map<\r\n ExcalidrawFrameLikeElement[\"id\"],\r\n ExcalidrawElement[]\r\n >();\r\n\r\n for (const element of elementsToRemove) {\r\n if (element.frameId) {\r\n _elementsToRemove.set(element.id, element);\r\n\r\n const arr = toRemoveElementsByFrame.get(element.frameId) || [];\r\n arr.push(element);\r\n\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n if (boundTextElement) {\r\n _elementsToRemove.set(boundTextElement.id, boundTextElement);\r\n arr.push(boundTextElement);\r\n }\r\n\r\n toRemoveElementsByFrame.set(element.frameId, arr);\r\n }\r\n }\r\n\r\n for (const [, element] of _elementsToRemove) {\r\n mutateElement(element, elementsMap, {\r\n frameId: null,\r\n });\r\n }\r\n};\r\n\r\nexport const removeAllElementsFromFrame = <T extends ExcalidrawElement>(\r\n allElements: readonly T[],\r\n frame: ExcalidrawFrameLikeElement,\r\n) => {\r\n const elementsInFrame = getFrameChildren(allElements, frame.id);\r\n removeElementsFromFrame(elementsInFrame, arrayToMap(allElements));\r\n return allElements;\r\n};\r\n\r\nexport const replaceAllElementsInFrame = <T extends ExcalidrawElement>(\r\n allElements: readonly T[],\r\n nextElementsInFrame: ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n app: AppClassProperties,\r\n): T[] => {\r\n return addElementsToFrame(\r\n removeAllElementsFromFrame(allElements, frame),\r\n nextElementsInFrame,\r\n frame,\r\n app.state,\r\n ).slice();\r\n};\r\n\r\n/** does not mutate elements, but returns new ones */\r\nexport const updateFrameMembershipOfSelectedElements = <\r\n T extends ElementsMapOrArray,\r\n>(\r\n allElements: T,\r\n appState: AppState,\r\n app: AppClassProperties,\r\n) => {\r\n const selectedElements = app.scene.getSelectedElements({\r\n selectedElementIds: appState.selectedElementIds,\r\n // supplying elements explicitly in case we're passed non-state elements\r\n elements: allElements,\r\n });\r\n const elementsToFilter = new Set<ExcalidrawElement>(selectedElements);\r\n\r\n if (appState.editingGroupId) {\r\n for (const element of selectedElements) {\r\n if (element.groupIds.length === 0) {\r\n elementsToFilter.add(element);\r\n } else {\r\n element.groupIds\r\n .flatMap((gid) => getElementsInGroup(allElements, gid))\r\n .forEach((element) => elementsToFilter.add(element));\r\n }\r\n }\r\n }\r\n\r\n const elementsToRemove = new Set<ExcalidrawElement>();\r\n\r\n const elementsMap = arrayToMap(allElements);\r\n\r\n elementsToFilter.forEach((element) => {\r\n if (\r\n element.frameId &&\r\n !isFrameLikeElement(element) &&\r\n !isElementInFrame(element, elementsMap, appState)\r\n ) {\r\n elementsToRemove.add(element);\r\n }\r\n });\r\n\r\n if (elementsToRemove.size > 0) {\r\n removeElementsFromFrame(elementsToRemove, elementsMap);\r\n }\r\n return allElements;\r\n};\r\n\r\n/**\r\n * filters out elements that are inside groups that contain a frame element\r\n * anywhere in the group tree\r\n */\r\nexport const omitGroupsContainingFrameLikes = (\r\n allElements: ElementsMapOrArray,\r\n /** subset of elements you want to filter. Optional perf optimization so we\r\n * don't have to filter all elements unnecessarily\r\n */\r\n selectedElements?: readonly ExcalidrawElement[],\r\n) => {\r\n const uniqueGroupIds = new Set<string>();\r\n const elements = selectedElements || allElements;\r\n\r\n for (const el of elements.values()) {\r\n const topMostGroupId = el.groupIds[el.groupIds.length - 1];\r\n if (topMostGroupId) {\r\n uniqueGroupIds.add(topMostGroupId);\r\n }\r\n }\r\n\r\n const rejectedGroupIds = new Set<string>();\r\n for (const groupId of uniqueGroupIds) {\r\n if (\r\n getElementsInGroup(allElements, groupId).some((el) =>\r\n isFrameLikeElement(el),\r\n )\r\n ) {\r\n rejectedGroupIds.add(groupId);\r\n }\r\n }\r\n\r\n const ret: ExcalidrawElement[] = [];\r\n\r\n for (const element of elements.values()) {\r\n if (!rejectedGroupIds.has(element.groupIds[element.groupIds.length - 1])) {\r\n ret.push(element);\r\n }\r\n }\r\n\r\n return ret;\r\n};\r\n\r\n/**\r\n * depending on the appState, return target frame, which is the frame the given element\r\n * is going to be added to or remove from\r\n */\r\nexport const getTargetFrame = (\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n appState: StaticCanvasAppState,\r\n) => {\r\n const _element = isTextElement(element)\r\n ? getContainerElement(element, elementsMap) || element\r\n : element;\r\n\r\n // if the element and its containing frame are both selected, then\r\n // the containing frame is the target frame\r\n if (\r\n _element.frameId &&\r\n appState.selectedElementIds[_element.id] &&\r\n appState.selectedElementIds[_element.frameId]\r\n ) {\r\n return getContainingFrame(_element, elementsMap);\r\n }\r\n\r\n return appState.selectedElementIds[_element.id] &&\r\n appState.selectedElementsAreBeingDragged\r\n ? appState.frameToHighlight\r\n : getContainingFrame(_element, elementsMap);\r\n};\r\n\r\n// TODO: this a huge bottleneck for large scenes, optimise\r\n// given an element, return if the element is in some frame\r\nexport const isElementInFrame = (\r\n element: ExcalidrawElement,\r\n allElementsMap: ElementsMap,\r\n appState: StaticCanvasAppState,\r\n opts?: {\r\n targetFrame?: ExcalidrawFrameLikeElement;\r\n checkedGroups?: Map<string, boolean>;\r\n },\r\n) => {\r\n const frame =\r\n opts?.targetFrame ?? getTargetFrame(element, allElementsMap, appState);\r\n\r\n if (!frame) {\r\n return false;\r\n }\r\n\r\n const _element = isTextElement(element)\r\n ? getContainerElement(element, allElementsMap) || element\r\n : element;\r\n\r\n const setGroupsInFrame = (isInFrame: boolean) => {\r\n if (opts?.checkedGroups) {\r\n _element.groupIds.forEach((groupId) => {\r\n opts.checkedGroups?.set(groupId, isInFrame);\r\n });\r\n }\r\n };\r\n\r\n if (\r\n // if the element is not selected, or it is selected but not being dragged,\r\n // frame membership won't update, so return true\r\n !appState.selectedElementIds[_element.id] ||\r\n !appState.selectedElementsAreBeingDragged ||\r\n // if both frame and element are selected, won't update membership, so return true\r\n (appState.selectedElementIds[_element.id] &&\r\n appState.selectedElementIds[frame.id])\r\n ) {\r\n return true;\r\n }\r\n\r\n if (_element.groupIds.length === 0) {\r\n return elementOverlapsWithFrame(_element, frame, allElementsMap);\r\n }\r\n\r\n for (const gid of _element.groupIds) {\r\n if (opts?.checkedGroups?.has(gid)) {\r\n return opts.checkedGroups.get(gid)!!;\r\n }\r\n }\r\n\r\n const allElementsInGroup = new Set(\r\n _element.groupIds\r\n .filter((gid) => {\r\n if (opts?.checkedGroups) {\r\n return !opts.checkedGroups.has(gid);\r\n }\r\n return true;\r\n })\r\n .flatMap((gid) => getElementsInGroup(allElementsMap, gid)),\r\n );\r\n\r\n if (appState.editingGroupId && appState.selectedElementsAreBeingDragged) {\r\n const selectedElements = new Set(\r\n getSelectedElements(allElementsMap, appState),\r\n );\r\n\r\n const editingGroupOverlapsFrame = appState.frameToHighlight !== null;\r\n\r\n if (editingGroupOverlapsFrame) {\r\n return true;\r\n }\r\n\r\n selectedElements.forEach((selectedElement) => {\r\n allElementsInGroup.delete(selectedElement);\r\n });\r\n }\r\n\r\n for (const elementInGroup of allElementsInGroup) {\r\n if (isFrameLikeElement(elementInGroup)) {\r\n setGroupsInFrame(false);\r\n return false;\r\n }\r\n }\r\n\r\n for (const elementInGroup of allElementsInGroup) {\r\n if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {\r\n setGroupsInFrame(true);\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport const shouldApplyFrameClip = (\r\n element: ExcalidrawElement,\r\n frame: ExcalidrawFrameLikeElement,\r\n appState: StaticCanvasAppState,\r\n elementsMap: ElementsMap,\r\n checkedGroups?: Map<string, boolean>,\r\n) => {\r\n if (!appState.frameRendering || !appState.frameRendering.clip) {\r\n return false;\r\n }\r\n\r\n // for individual elements, only clip when the element is\r\n // a. overlapping with the frame, or\r\n // b. containing the frame, for example when an element is used as a background\r\n // and is therefore bigger than the frame and completely contains the frame\r\n const shouldClipElementItself =\r\n isElementIntersectingFrame(element, frame, elementsMap) ||\r\n isElementContainingFrame(element, frame, elementsMap);\r\n\r\n if (shouldClipElementItself) {\r\n for (const groupId of element.groupIds) {\r\n checkedGroups?.set(groupId, true);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n // if an element is outside the frame, but is part of a group that has some elements\r\n // \"in\" the frame, we should clip the element\r\n if (\r\n !shouldClipElementItself &&\r\n element.groupIds.length > 0 &&\r\n !elementsAreInFrameBounds([element], frame, elementsMap)\r\n ) {\r\n let shouldClip = false;\r\n\r\n // if no elements are being dragged, we can skip the geometry check\r\n // because we know if the element is in the given frame or not\r\n if (!appState.selectedElementsAreBeingDragged) {\r\n shouldClip = element.frameId === frame.id;\r\n for (const groupId of element.groupIds) {\r\n checkedGroups?.set(groupId, shouldClip);\r\n }\r\n } else {\r\n shouldClip = isElementInFrame(element, elementsMap, appState, {\r\n targetFrame: frame,\r\n checkedGroups,\r\n });\r\n }\r\n\r\n for (const groupId of element.groupIds) {\r\n checkedGroups?.set(groupId, shouldClip);\r\n }\r\n\r\n return shouldClip;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst DEFAULT_FRAME_NAME = \"Frame\";\r\nconst DEFAULT_AI_FRAME_NAME = \"AI Frame\";\r\n\r\nexport const getDefaultFrameName = (element: ExcalidrawFrameLikeElement) => {\r\n // TODO name frames \"AI\" only if specific to AI frames\r\n return isFrameElement(element) ? DEFAULT_FRAME_NAME : DEFAULT_AI_FRAME_NAME;\r\n};\r\n\r\nexport const getFrameLikeTitle = (element: ExcalidrawFrameLikeElement) => {\r\n return element.name === null ? getDefaultFrameName(element) : element.name;\r\n};\r\n\r\nexport const getElementsOverlappingFrame = (\r\n elements: readonly ExcalidrawElement[],\r\n frame: ExcalidrawFrameLikeElement,\r\n) => {\r\n return (\r\n elementsOverlappingBBox({\r\n elements,\r\n bounds: frame,\r\n type: \"overlap\",\r\n })\r\n // removes elements who are overlapping, but are in a different frame,\r\n // and thus invisible in target frame\r\n .filter((el) => !el.frameId || el.frameId === frame.id)\r\n );\r\n};\r\n\r\nexport const frameAndChildrenSelectedTogether = (\r\n selectedElements: readonly ExcalidrawElement[],\r\n) => {\r\n const selectedElementsMap = arrayToMap(selectedElements);\r\n\r\n return (\r\n selectedElements.length > 1 &&\r\n selectedElements.some(\r\n (element) => element.frameId && selectedElementsMap.has(element.frameId),\r\n )\r\n );\r\n};\r\n", "import {\r\n vectorCross,\r\n vectorFromPoint,\r\n type GlobalPoint,\r\n type LocalPoint,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type { Bounds } from \"@excalidraw-modify/common\";\r\n\r\nexport type LineSegment<P extends LocalPoint | GlobalPoint> = [P, P];\r\n\r\nexport function getBBox<P extends LocalPoint | GlobalPoint>(\r\n line: LineSegment<P>,\r\n): Bounds {\r\n return [\r\n Math.min(line[0][0], line[1][0]),\r\n Math.min(line[0][1], line[1][1]),\r\n Math.max(line[0][0], line[1][0]),\r\n Math.max(line[0][1], line[1][1]),\r\n ];\r\n}\r\n\r\nexport function doBBoxesIntersect(a: Bounds, b: Bounds) {\r\n return a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];\r\n}\r\n\r\nconst EPSILON = 0.000001;\r\n\r\nexport function isPointOnLine<P extends GlobalPoint | LocalPoint>(\r\n l: LineSegment<P>,\r\n p: P,\r\n) {\r\n const p1 = vectorFromPoint(l[1], l[0]);\r\n const p2 = vectorFromPoint(p, l[0]);\r\n\r\n const r = vectorCross(p1, p2);\r\n\r\n return Math.abs(r) < EPSILON;\r\n}\r\n\r\nexport function isPointRightOfLine<P extends GlobalPoint | LocalPoint>(\r\n l: LineSegment<P>,\r\n p: P,\r\n) {\r\n const p1 = vectorFromPoint(l[1], l[0]);\r\n const p2 = vectorFromPoint(p, l[0]);\r\n\r\n return vectorCross(p1, p2) < 0;\r\n}\r\n\r\nexport function isLineSegmentTouchingOrCrossingLine<\r\n P extends GlobalPoint | LocalPoint,\r\n>(a: LineSegment<P>, b: LineSegment<P>) {\r\n return (\r\n isPointOnLine(a, b[0]) ||\r\n isPointOnLine(a, b[1]) ||\r\n (isPointRightOfLine(a, b[0])\r\n ? !isPointRightOfLine(a, b[1])\r\n : isPointRightOfLine(a, b[1]))\r\n );\r\n}\r\n\r\n// https://martin-thoma.com/how-to-check-if-two-line-segments-intersect/\r\nexport function doLineSegmentsIntersect<P extends GlobalPoint | LocalPoint>(\r\n a: LineSegment<P>,\r\n b: LineSegment<P>,\r\n) {\r\n return (\r\n doBBoxesIntersect(getBBox(a), getBBox(b)) &&\r\n isLineSegmentTouchingOrCrossingLine(a, b) &&\r\n isLineSegmentTouchingOrCrossingLine(b, a)\r\n );\r\n}\r\n", "import { arrayToMap, type Bounds } from \"@excalidraw-modify/common\";\r\nimport { getElementBounds } from \"@excalidraw-modify/element\";\r\nimport {\r\n isArrowElement,\r\n isExcalidrawElement,\r\n isFreeDrawElement,\r\n isLinearElement,\r\n isTextElement,\r\n} from \"@excalidraw-modify/element\";\r\nimport {\r\n rangeIncludesValue,\r\n pointFrom,\r\n pointRotateRads,\r\n rangeInclusive,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawLinearElement,\r\n NonDeletedExcalidrawElement,\r\n} from \"@excalidraw-modify/element/types\";\r\nimport type { LocalPoint } from \"@excalidraw-modify/math\";\r\n\r\ntype Element = NonDeletedExcalidrawElement;\r\ntype Elements = readonly NonDeletedExcalidrawElement[];\r\n\r\ntype Points = readonly LocalPoint[];\r\n\r\n/** @returns vertices relative to element's top-left [0,0] position */\r\nconst getNonLinearElementRelativePoints = (\r\n element: Exclude<\r\n Element,\r\n ExcalidrawLinearElement | ExcalidrawFreeDrawElement\r\n >,\r\n): [\r\n TopLeft: LocalPoint,\r\n TopRight: LocalPoint,\r\n BottomRight: LocalPoint,\r\n BottomLeft: LocalPoint,\r\n] => {\r\n if (element.type === \"diamond\") {\r\n return [\r\n pointFrom(element.width / 2, 0),\r\n pointFrom(element.width, element.height / 2),\r\n pointFrom(element.width / 2, element.height),\r\n pointFrom(0, element.height / 2),\r\n ];\r\n }\r\n return [\r\n pointFrom(0, 0),\r\n pointFrom(0 + element.width, 0),\r\n pointFrom(0 + element.width, element.height),\r\n pointFrom(0, element.height),\r\n ];\r\n};\r\n\r\n/** @returns vertices relative to element's top-left [0,0] position */\r\nconst getElementRelativePoints = (element: ExcalidrawElement): Points => {\r\n if (isLinearElement(element) || isFreeDrawElement(element)) {\r\n return element.points;\r\n }\r\n return getNonLinearElementRelativePoints(element);\r\n};\r\n\r\nconst getMinMaxPoints = (points: Points) => {\r\n const ret = points.reduce(\r\n (limits, [x, y]) => {\r\n limits.minY = Math.min(limits.minY, y);\r\n limits.minX = Math.min(limits.minX, x);\r\n\r\n limits.maxX = Math.max(limits.maxX, x);\r\n limits.maxY = Math.max(limits.maxY, y);\r\n\r\n return limits;\r\n },\r\n {\r\n minX: Infinity,\r\n minY: Infinity,\r\n maxX: -Infinity,\r\n maxY: -Infinity,\r\n cx: 0,\r\n cy: 0,\r\n },\r\n );\r\n\r\n ret.cx = (ret.maxX + ret.minX) / 2;\r\n ret.cy = (ret.maxY + ret.minY) / 2;\r\n\r\n return ret;\r\n};\r\n\r\nconst getRotatedBBox = (element: Element): Bounds => {\r\n const points = getElementRelativePoints(element);\r\n\r\n const { cx, cy } = getMinMaxPoints(points);\r\n const centerPoint = pointFrom<LocalPoint>(cx, cy);\r\n\r\n const rotatedPoints = points.map((p) =>\r\n pointRotateRads(p, centerPoint, element.angle),\r\n );\r\n const { minX, minY, maxX, maxY } = getMinMaxPoints(rotatedPoints);\r\n\r\n return [\r\n minX + element.x,\r\n minY + element.y,\r\n maxX + element.x,\r\n maxY + element.y,\r\n ];\r\n};\r\n\r\nexport const isElementInsideBBox = (\r\n element: Element,\r\n bbox: Bounds,\r\n eitherDirection = false,\r\n): boolean => {\r\n const elementBBox = getRotatedBBox(element);\r\n\r\n const elementInsideBbox =\r\n bbox[0] <= elementBBox[0] &&\r\n bbox[2] >= elementBBox[2] &&\r\n bbox[1] <= elementBBox[1] &&\r\n bbox[3] >= elementBBox[3];\r\n\r\n if (!eitherDirection) {\r\n return elementInsideBbox;\r\n }\r\n\r\n if (elementInsideBbox) {\r\n return true;\r\n }\r\n\r\n return (\r\n elementBBox[0] <= bbox[0] &&\r\n elementBBox[2] >= bbox[2] &&\r\n elementBBox[1] <= bbox[1] &&\r\n elementBBox[3] >= bbox[3]\r\n );\r\n};\r\n\r\nexport const elementPartiallyOverlapsWithOrContainsBBox = (\r\n element: Element,\r\n bbox: Bounds,\r\n): boolean => {\r\n const elementBBox = getRotatedBBox(element);\r\n\r\n return (\r\n (rangeIncludesValue(elementBBox[0], rangeInclusive(bbox[0], bbox[2])) ||\r\n rangeIncludesValue(\r\n bbox[0],\r\n rangeInclusive(elementBBox[0], elementBBox[2]),\r\n )) &&\r\n (rangeIncludesValue(elementBBox[1], rangeInclusive(bbox[1], bbox[3])) ||\r\n rangeIncludesValue(\r\n bbox[1],\r\n rangeInclusive(elementBBox[1], elementBBox[3]),\r\n ))\r\n );\r\n};\r\n\r\nexport const elementsOverlappingBBox = ({\r\n elements,\r\n bounds,\r\n type,\r\n errorMargin = 0,\r\n}: {\r\n elements: Elements;\r\n bounds: Bounds | ExcalidrawElement;\r\n /** safety offset. Defaults to 0. */\r\n errorMargin?: number;\r\n /**\r\n * - overlap: elements overlapping or inside bounds\r\n * - contain: elements inside bounds or bounds inside elements\r\n * - inside: elements inside bounds\r\n **/\r\n type: \"overlap\" | \"contain\" | \"inside\";\r\n}) => {\r\n if (isExcalidrawElement(bounds)) {\r\n bounds = getElementBounds(bounds, arrayToMap(elements));\r\n }\r\n const adjustedBBox: Bounds = [\r\n bounds[0] - errorMargin,\r\n bounds[1] - errorMargin,\r\n bounds[2] + errorMargin,\r\n bounds[3] + errorMargin,\r\n ];\r\n\r\n const includedElementSet = new Set<string>();\r\n\r\n for (const element of elements) {\r\n if (includedElementSet.has(element.id)) {\r\n continue;\r\n }\r\n\r\n const isOverlaping =\r\n type === \"overlap\"\r\n ? elementPartiallyOverlapsWithOrContainsBBox(element, adjustedBBox)\r\n : type === \"inside\"\r\n ? isElementInsideBBox(element, adjustedBBox)\r\n : isElementInsideBBox(element, adjustedBBox, true);\r\n\r\n if (isOverlaping) {\r\n includedElementSet.add(element.id);\r\n\r\n if (element.boundElements) {\r\n for (const boundElement of element.boundElements) {\r\n includedElementSet.add(boundElement.id);\r\n }\r\n }\r\n\r\n if (isTextElement(element) && element.containerId) {\r\n includedElementSet.add(element.containerId);\r\n }\r\n\r\n if (isArrowElement(element)) {\r\n if (element.startBinding) {\r\n includedElementSet.add(element.startBinding.elementId);\r\n }\r\n\r\n if (element.endBinding) {\r\n includedElementSet.add(element.endBinding?.elementId);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return elements.filter((element) => includedElementSet.has(element.id));\r\n};\r\n", "import { arrayToMap, isShallowEqual } from \"@excalidraw-modify/common\";\r\n\r\nimport type {\r\n AppState,\r\n InteractiveCanvasAppState,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { getElementAbsoluteCoords, getElementBounds } from \"./bounds\";\r\nimport { isElementInViewport } from \"./sizeHelpers\";\r\nimport {\r\n isBoundToContainer,\r\n isFrameLikeElement,\r\n isLinearElement,\r\n} from \"./typeChecks\";\r\nimport {\r\n elementOverlapsWithFrame,\r\n getContainingFrame,\r\n getFrameChildren,\r\n} from \"./frame\";\r\n\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport { selectGroupsForSelectedElements } from \"./groups\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ElementsMapOrArray,\r\n ExcalidrawElement,\r\n NonDeletedExcalidrawElement,\r\n} from \"./types\";\r\n\r\n/**\r\n * Frames and their containing elements are not to be selected at the same time.\r\n * Given an array of selected elements, if there are frames and their containing elements\r\n * we only keep the frames.\r\n * @param selectedElements\r\n */\r\nexport const excludeElementsInFramesFromSelection = <\r\n T extends ExcalidrawElement,\r\n>(\r\n selectedElements: readonly T[],\r\n) => {\r\n const framesInSelection = new Set<T[\"id\"]>();\r\n\r\n selectedElements.forEach((element) => {\r\n if (isFrameLikeElement(element)) {\r\n framesInSelection.add(element.id);\r\n }\r\n });\r\n\r\n return selectedElements.filter((element) => {\r\n if (element.frameId && framesInSelection.has(element.frameId)) {\r\n return false;\r\n }\r\n return true;\r\n });\r\n};\r\n\r\nexport const getElementsWithinSelection = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n selection: NonDeletedExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n excludeElementsInFrames: boolean = true,\r\n) => {\r\n const [selectionX1, selectionY1, selectionX2, selectionY2] =\r\n getElementAbsoluteCoords(selection, elementsMap);\r\n\r\n let elementsInSelection = elements.filter((element) => {\r\n let [elementX1, elementY1, elementX2, elementY2] = getElementBounds(\r\n element,\r\n elementsMap,\r\n );\r\n\r\n const containingFrame = getContainingFrame(element, elementsMap);\r\n if (containingFrame) {\r\n const [fx1, fy1, fx2, fy2] = getElementBounds(\r\n containingFrame,\r\n elementsMap,\r\n );\r\n\r\n elementX1 = Math.max(fx1, elementX1);\r\n elementY1 = Math.max(fy1, elementY1);\r\n elementX2 = Math.min(fx2, elementX2);\r\n elementY2 = Math.min(fy2, elementY2);\r\n }\r\n\r\n return (\r\n element.locked === false &&\r\n element.type !== \"selection\" &&\r\n !isBoundToContainer(element) &&\r\n selectionX1 <= elementX1 &&\r\n selectionY1 <= elementY1 &&\r\n selectionX2 >= elementX2 &&\r\n selectionY2 >= elementY2\r\n );\r\n });\r\n\r\n elementsInSelection = excludeElementsInFrames\r\n ? excludeElementsInFramesFromSelection(elementsInSelection)\r\n : elementsInSelection;\r\n\r\n elementsInSelection = elementsInSelection.filter((element) => {\r\n const containingFrame = getContainingFrame(element, elementsMap);\r\n\r\n if (containingFrame) {\r\n return elementOverlapsWithFrame(element, containingFrame, elementsMap);\r\n }\r\n\r\n return true;\r\n });\r\n\r\n return elementsInSelection;\r\n};\r\n\r\nexport const getVisibleAndNonSelectedElements = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n selectedElements: readonly NonDeletedExcalidrawElement[],\r\n appState: AppState,\r\n elementsMap: ElementsMap,\r\n) => {\r\n const selectedElementsSet = new Set(\r\n selectedElements.map((element) => element.id),\r\n );\r\n return elements.filter((element) => {\r\n const isVisible = isElementInViewport(\r\n element,\r\n appState.width,\r\n appState.height,\r\n appState,\r\n elementsMap,\r\n );\r\n\r\n return !selectedElementsSet.has(element.id) && isVisible;\r\n });\r\n};\r\n\r\n// FIXME move this into the editor instance to keep utility methods stateless\r\nexport const isSomeElementSelected = (function () {\r\n let lastElements: readonly NonDeletedExcalidrawElement[] | null = null;\r\n let lastSelectedElementIds: AppState[\"selectedElementIds\"] | null = null;\r\n let isSelected: boolean | null = null;\r\n\r\n const ret = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n appState: Pick<AppState, \"selectedElementIds\">,\r\n ): boolean => {\r\n if (\r\n isSelected != null &&\r\n elements === lastElements &&\r\n appState.selectedElementIds === lastSelectedElementIds\r\n ) {\r\n return isSelected;\r\n }\r\n\r\n isSelected = elements.some(\r\n (element) => appState.selectedElementIds[element.id],\r\n );\r\n lastElements = elements;\r\n lastSelectedElementIds = appState.selectedElementIds;\r\n\r\n return isSelected;\r\n };\r\n\r\n ret.clearCache = () => {\r\n lastElements = null;\r\n lastSelectedElementIds = null;\r\n isSelected = null;\r\n };\r\n\r\n return ret;\r\n})();\r\n\r\nexport const getSelectedElements = (\r\n elements: ElementsMapOrArray,\r\n appState: Pick<InteractiveCanvasAppState, \"selectedElementIds\">,\r\n opts?: {\r\n includeBoundTextElement?: boolean;\r\n includeElementsInFrames?: boolean;\r\n },\r\n) => {\r\n const addedElements = new Set<ExcalidrawElement[\"id\"]>();\r\n const selectedElements: ExcalidrawElement[] = [];\r\n for (const element of elements.values()) {\r\n if (appState.selectedElementIds[element.id]) {\r\n selectedElements.push(element);\r\n addedElements.add(element.id);\r\n continue;\r\n }\r\n if (\r\n opts?.includeBoundTextElement &&\r\n isBoundToContainer(element) &&\r\n appState.selectedElementIds[element?.containerId]\r\n ) {\r\n selectedElements.push(element);\r\n addedElements.add(element.id);\r\n continue;\r\n }\r\n }\r\n\r\n if (opts?.includeElementsInFrames) {\r\n const elementsToInclude: ExcalidrawElement[] = [];\r\n selectedElements.forEach((element) => {\r\n if (isFrameLikeElement(element)) {\r\n getFrameChildren(elements, element.id).forEach(\r\n (e) => !addedElements.has(e.id) && elementsToInclude.push(e),\r\n );\r\n }\r\n elementsToInclude.push(element);\r\n });\r\n\r\n return elementsToInclude;\r\n }\r\n\r\n return selectedElements;\r\n};\r\n\r\nexport const getTargetElements = (\r\n elements: ElementsMapOrArray,\r\n appState: Pick<\r\n AppState,\r\n \"selectedElementIds\" | \"editingTextElement\" | \"newElement\"\r\n >,\r\n) =>\r\n appState.editingTextElement\r\n ? [appState.editingTextElement]\r\n : appState.newElement\r\n ? [appState.newElement]\r\n : getSelectedElements(elements, appState, {\r\n includeBoundTextElement: true,\r\n });\r\n\r\n/**\r\n * returns prevState's selectedElementids if no change from previous, so as to\r\n * retain reference identity for memoization\r\n */\r\nexport const makeNextSelectedElementIds = (\r\n nextSelectedElementIds: AppState[\"selectedElementIds\"],\r\n prevState: Pick<AppState, \"selectedElementIds\">,\r\n) => {\r\n if (isShallowEqual(prevState.selectedElementIds, nextSelectedElementIds)) {\r\n return prevState.selectedElementIds;\r\n }\r\n\r\n return nextSelectedElementIds;\r\n};\r\n\r\nconst _getLinearElementEditor = (\r\n targetElements: readonly ExcalidrawElement[],\r\n allElements: readonly NonDeletedExcalidrawElement[],\r\n) => {\r\n const linears = targetElements.filter(isLinearElement);\r\n if (linears.length === 1) {\r\n const linear = linears[0];\r\n const boundElements = linear.boundElements?.map((def) => def.id) ?? [];\r\n const onlySingleLinearSelected = targetElements.every(\r\n (el) => el.id === linear.id || boundElements.includes(el.id),\r\n );\r\n\r\n if (onlySingleLinearSelected) {\r\n return new LinearElementEditor(linear, arrayToMap(allElements));\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const getSelectionStateForElements = (\r\n targetElements: readonly ExcalidrawElement[],\r\n allElements: readonly NonDeletedExcalidrawElement[],\r\n appState: AppState,\r\n) => {\r\n return {\r\n selectedLinearElement: _getLinearElementEditor(targetElements, allElements),\r\n ...selectGroupsForSelectedElements(\r\n {\r\n editingGroupId: appState.editingGroupId,\r\n selectedElementIds: excludeElementsInFramesFromSelection(\r\n targetElements,\r\n ).reduce((acc: Record<ExcalidrawElement[\"id\"], true>, element) => {\r\n if (!isBoundToContainer(element)) {\r\n acc[element.id] = true;\r\n }\r\n return acc;\r\n }, {}),\r\n },\r\n allElements,\r\n appState,\r\n null,\r\n ),\r\n };\r\n};\r\n", "import type {\r\n AppClassProperties,\r\n AppState,\r\n InteractiveCanvasAppState,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { Mutable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport { getBoundTextElement } from \"./textElement\";\r\n\r\nimport { isBoundToContainer } from \"./typeChecks\";\r\n\r\nimport { makeNextSelectedElementIds, getSelectedElements } from \"./selection\";\r\n\r\nimport type {\r\n GroupId,\r\n ExcalidrawElement,\r\n NonDeleted,\r\n NonDeletedExcalidrawElement,\r\n ElementsMapOrArray,\r\n ElementsMap,\r\n} from \"./types\";\r\n\r\nexport const selectGroup = (\r\n groupId: GroupId,\r\n appState: InteractiveCanvasAppState,\r\n elements: readonly NonDeleted<ExcalidrawElement>[],\r\n): Pick<\r\n InteractiveCanvasAppState,\r\n \"selectedGroupIds\" | \"selectedElementIds\" | \"editingGroupId\"\r\n> => {\r\n const elementsInGroup = elements.reduce(\r\n (acc: Record<string, true>, element) => {\r\n if (element.groupIds.includes(groupId)) {\r\n acc[element.id] = true;\r\n }\r\n return acc;\r\n },\r\n {},\r\n );\r\n\r\n if (Object.keys(elementsInGroup).length < 2) {\r\n if (\r\n appState.selectedGroupIds[groupId] ||\r\n appState.editingGroupId === groupId\r\n ) {\r\n return {\r\n selectedElementIds: appState.selectedElementIds,\r\n selectedGroupIds: { ...appState.selectedGroupIds, [groupId]: false },\r\n editingGroupId: null,\r\n };\r\n }\r\n return appState;\r\n }\r\n\r\n return {\r\n editingGroupId: appState.editingGroupId,\r\n selectedGroupIds: { ...appState.selectedGroupIds, [groupId]: true },\r\n selectedElementIds: {\r\n ...appState.selectedElementIds,\r\n ...elementsInGroup,\r\n },\r\n };\r\n};\r\n\r\nexport const selectGroupsForSelectedElements = (function () {\r\n type SelectGroupsReturnType = Pick<\r\n InteractiveCanvasAppState,\r\n \"selectedGroupIds\" | \"editingGroupId\" | \"selectedElementIds\"\r\n >;\r\n\r\n let lastSelectedElements: readonly NonDeleted<ExcalidrawElement>[] | null =\r\n null;\r\n let lastElements: readonly NonDeleted<ExcalidrawElement>[] | null = null;\r\n let lastReturnValue: SelectGroupsReturnType | null = null;\r\n\r\n const _selectGroups = (\r\n selectedElements: readonly NonDeleted<ExcalidrawElement>[],\r\n elements: readonly NonDeleted<ExcalidrawElement>[],\r\n appState: Pick<AppState, \"selectedElementIds\" | \"editingGroupId\">,\r\n prevAppState: InteractiveCanvasAppState,\r\n ): SelectGroupsReturnType => {\r\n if (\r\n lastReturnValue !== undefined &&\r\n elements === lastElements &&\r\n selectedElements === lastSelectedElements &&\r\n appState.editingGroupId === lastReturnValue?.editingGroupId\r\n ) {\r\n return lastReturnValue;\r\n }\r\n\r\n const selectedGroupIds: Record<GroupId, boolean> = {};\r\n // Gather all the groups withing selected elements\r\n for (const selectedElement of selectedElements) {\r\n let groupIds = selectedElement.groupIds;\r\n if (appState.editingGroupId) {\r\n // handle the case where a group is nested within a group\r\n const indexOfEditingGroup = groupIds.indexOf(appState.editingGroupId);\r\n if (indexOfEditingGroup > -1) {\r\n groupIds = groupIds.slice(0, indexOfEditingGroup);\r\n }\r\n }\r\n if (groupIds.length > 0) {\r\n const lastSelectedGroup = groupIds[groupIds.length - 1];\r\n selectedGroupIds[lastSelectedGroup] = true;\r\n }\r\n }\r\n\r\n // Gather all the elements within selected groups\r\n const groupElementsIndex: Record<GroupId, string[]> = {};\r\n const selectedElementIdsInGroups = elements.reduce(\r\n (acc: Record<string, true>, element) => {\r\n if (element.isDeleted) {\r\n return acc;\r\n }\r\n\r\n const groupId = element.groupIds.find((id) => selectedGroupIds[id]);\r\n\r\n if (groupId) {\r\n acc[element.id] = true;\r\n\r\n // Populate the index\r\n if (!Array.isArray(groupElementsIndex[groupId])) {\r\n groupElementsIndex[groupId] = [element.id];\r\n } else {\r\n groupElementsIndex[groupId].push(element.id);\r\n }\r\n }\r\n return acc;\r\n },\r\n {},\r\n );\r\n\r\n for (const groupId of Object.keys(groupElementsIndex)) {\r\n // If there is one element in the group, and the group is selected or it's being edited, it's not a group\r\n if (groupElementsIndex[groupId].length < 2) {\r\n if (selectedGroupIds[groupId]) {\r\n selectedGroupIds[groupId] = false;\r\n }\r\n }\r\n }\r\n\r\n lastElements = elements;\r\n lastSelectedElements = selectedElements;\r\n\r\n lastReturnValue = {\r\n editingGroupId: appState.editingGroupId,\r\n selectedGroupIds,\r\n selectedElementIds: makeNextSelectedElementIds(\r\n {\r\n ...appState.selectedElementIds,\r\n ...selectedElementIdsInGroups,\r\n },\r\n prevAppState,\r\n ),\r\n };\r\n\r\n return lastReturnValue;\r\n };\r\n\r\n /**\r\n * When you select an element, you often want to actually select the whole group it's in, unless\r\n * you're currently editing that group.\r\n */\r\n const selectGroupsForSelectedElements = (\r\n appState: Pick<AppState, \"selectedElementIds\" | \"editingGroupId\">,\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n prevAppState: InteractiveCanvasAppState,\r\n /**\r\n * supply null in cases where you don't have access to App instance and\r\n * you don't care about optimizing selectElements retrieval\r\n */\r\n app: AppClassProperties | null,\r\n ): Mutable<\r\n Pick<\r\n InteractiveCanvasAppState,\r\n \"selectedGroupIds\" | \"editingGroupId\" | \"selectedElementIds\"\r\n >\r\n > => {\r\n const selectedElements = app\r\n ? app.scene.getSelectedElements({\r\n selectedElementIds: appState.selectedElementIds,\r\n // supplying elements explicitly in case we're passed non-state elements\r\n elements,\r\n })\r\n : getSelectedElements(elements, appState);\r\n\r\n if (!selectedElements.length) {\r\n return {\r\n selectedGroupIds: {},\r\n editingGroupId: null,\r\n selectedElementIds: makeNextSelectedElementIds(\r\n appState.selectedElementIds,\r\n prevAppState,\r\n ),\r\n };\r\n }\r\n\r\n return _selectGroups(selectedElements, elements, appState, prevAppState);\r\n };\r\n\r\n selectGroupsForSelectedElements.clearCache = () => {\r\n lastElements = null;\r\n lastSelectedElements = null;\r\n lastReturnValue = null;\r\n };\r\n\r\n return selectGroupsForSelectedElements;\r\n})();\r\n\r\n/**\r\n * If the element's group is selected, don't render an individual\r\n * selection border around it.\r\n */\r\nexport const isSelectedViaGroup = (\r\n appState: InteractiveCanvasAppState,\r\n element: ExcalidrawElement,\r\n) => getSelectedGroupForElement(appState, element) != null;\r\n\r\nexport const getSelectedGroupForElement = (\r\n appState: Pick<\r\n InteractiveCanvasAppState,\r\n \"editingGroupId\" | \"selectedGroupIds\"\r\n >,\r\n element: ExcalidrawElement,\r\n) =>\r\n element.groupIds\r\n .filter((groupId) => groupId !== appState.editingGroupId)\r\n .find((groupId) => appState.selectedGroupIds[groupId]);\r\n\r\nexport const getSelectedGroupIds = (\r\n appState: InteractiveCanvasAppState,\r\n): GroupId[] =>\r\n Object.entries(appState.selectedGroupIds)\r\n .filter(([groupId, isSelected]) => isSelected)\r\n .map(([groupId, isSelected]) => groupId);\r\n\r\n// given a list of elements, return the the actual group ids that should be selected\r\n// or used to update the elements\r\nexport const selectGroupsFromGivenElements = (\r\n elements: readonly NonDeleted<ExcalidrawElement>[],\r\n appState: InteractiveCanvasAppState,\r\n) => {\r\n let nextAppState: InteractiveCanvasAppState = {\r\n ...appState,\r\n selectedGroupIds: {},\r\n };\r\n\r\n for (const element of elements) {\r\n let groupIds = element.groupIds;\r\n if (appState.editingGroupId) {\r\n const indexOfEditingGroup = groupIds.indexOf(appState.editingGroupId);\r\n if (indexOfEditingGroup > -1) {\r\n groupIds = groupIds.slice(0, indexOfEditingGroup);\r\n }\r\n }\r\n if (groupIds.length > 0) {\r\n const groupId = groupIds[groupIds.length - 1];\r\n nextAppState = {\r\n ...nextAppState,\r\n ...selectGroup(groupId, nextAppState, elements),\r\n };\r\n }\r\n }\r\n\r\n return nextAppState.selectedGroupIds;\r\n};\r\n\r\nexport const editGroupForSelectedElement = (\r\n appState: AppState,\r\n element: NonDeleted<ExcalidrawElement>,\r\n): AppState => {\r\n return {\r\n ...appState,\r\n editingGroupId: element.groupIds.length ? element.groupIds[0] : null,\r\n selectedGroupIds: {},\r\n selectedElementIds: {\r\n [element.id]: true,\r\n },\r\n };\r\n};\r\n\r\nexport const isElementInGroup = (element: ExcalidrawElement, groupId: string) =>\r\n element.groupIds.includes(groupId);\r\n\r\nexport const getElementsInGroup = (\r\n elements: ElementsMapOrArray,\r\n groupId: string,\r\n) => {\r\n const elementsInGroup: ExcalidrawElement[] = [];\r\n for (const element of elements.values()) {\r\n if (isElementInGroup(element, groupId)) {\r\n elementsInGroup.push(element);\r\n }\r\n }\r\n return elementsInGroup;\r\n};\r\n\r\nexport const getSelectedGroupIdForElement = (\r\n element: ExcalidrawElement,\r\n selectedGroupIds: { [groupId: string]: boolean },\r\n) => element.groupIds.find((groupId) => selectedGroupIds[groupId]);\r\n\r\nexport const addToGroup = (\r\n prevGroupIds: ExcalidrawElement[\"groupIds\"],\r\n newGroupId: GroupId,\r\n editingGroupId: AppState[\"editingGroupId\"],\r\n) => {\r\n // insert before the editingGroupId, or push to the end.\r\n const groupIds = [...prevGroupIds];\r\n const positionOfEditingGroupId = editingGroupId\r\n ? groupIds.indexOf(editingGroupId)\r\n : -1;\r\n const positionToInsert =\r\n positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;\r\n groupIds.splice(positionToInsert, 0, newGroupId);\r\n return groupIds;\r\n};\r\n\r\nexport const removeFromSelectedGroups = (\r\n groupIds: ExcalidrawElement[\"groupIds\"],\r\n selectedGroupIds: { [groupId: string]: boolean },\r\n) => groupIds.filter((groupId) => !selectedGroupIds[groupId]);\r\n\r\nexport const getMaximumGroups = (\r\n elements: ExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n): ExcalidrawElement[][] => {\r\n const groups: Map<String, ExcalidrawElement[]> = new Map<\r\n String,\r\n ExcalidrawElement[]\r\n >();\r\n elements.forEach((element: ExcalidrawElement) => {\r\n const groupId =\r\n element.groupIds.length === 0\r\n ? element.id\r\n : element.groupIds[element.groupIds.length - 1];\r\n\r\n const currentGroupMembers = groups.get(groupId) || [];\r\n\r\n // Include bound text if present when grouping\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n if (boundTextElement) {\r\n currentGroupMembers.push(boundTextElement);\r\n }\r\n groups.set(groupId, [...currentGroupMembers, element]);\r\n });\r\n\r\n return Array.from(groups.values());\r\n};\r\n\r\nexport const getNonDeletedGroupIds = (elements: ElementsMap) => {\r\n const nonDeletedGroupIds = new Set<string>();\r\n\r\n for (const [, element] of elements) {\r\n // defensive check\r\n if (element.isDeleted) {\r\n continue;\r\n }\r\n\r\n // defensive fallback\r\n for (const groupId of element.groupIds ?? []) {\r\n nonDeletedGroupIds.add(groupId);\r\n }\r\n }\r\n\r\n return nonDeletedGroupIds;\r\n};\r\n\r\nexport const elementsAreInSameGroup = (\r\n elements: readonly ExcalidrawElement[],\r\n) => {\r\n const allGroups = elements.flatMap((element) => element.groupIds);\r\n const groupCount = new Map<string, number>();\r\n let maxGroup = 0;\r\n\r\n for (const group of allGroups) {\r\n groupCount.set(group, (groupCount.get(group) ?? 0) + 1);\r\n if (groupCount.get(group)! > maxGroup) {\r\n maxGroup = groupCount.get(group)!;\r\n }\r\n }\r\n\r\n return maxGroup === elements.length;\r\n};\r\n\r\nexport const isInGroup = (element: NonDeletedExcalidrawElement) => {\r\n return element.groupIds.length > 0;\r\n};\r\n\r\nexport const getNewGroupIdsForDuplication = (\r\n groupIds: ExcalidrawElement[\"groupIds\"],\r\n editingGroupId: AppState[\"editingGroupId\"],\r\n mapper: (groupId: GroupId) => GroupId,\r\n) => {\r\n const copy = [...groupIds];\r\n const positionOfEditingGroupId = editingGroupId\r\n ? groupIds.indexOf(editingGroupId)\r\n : -1;\r\n const endIndex =\r\n positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;\r\n for (let index = 0; index < endIndex; index++) {\r\n copy[index] = mapper(copy[index]);\r\n }\r\n\r\n return copy;\r\n};\r\n\r\n// given a list of selected elements, return the element grouped by their immediate group selected state\r\n// in the case if only one group is selected and all elements selected are within the group, it will respect group hierarchy in accordance to their nested grouping order\r\nexport const getSelectedElementsByGroup = (\r\n selectedElements: ExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n appState: Readonly<AppState>,\r\n): ExcalidrawElement[][] => {\r\n const selectedGroupIds = getSelectedGroupIds(appState);\r\n const unboundElements = selectedElements.filter(\r\n (element) => !isBoundToContainer(element),\r\n );\r\n const groups: Map<string, ExcalidrawElement[]> = new Map();\r\n const elements: Map<string, ExcalidrawElement[]> = new Map();\r\n\r\n // helper function to add an element to the elements map\r\n const addToElementsMap = (element: ExcalidrawElement) => {\r\n // elements\r\n const currentElementMembers = elements.get(element.id) || [];\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n\r\n if (boundTextElement) {\r\n currentElementMembers.push(boundTextElement);\r\n }\r\n elements.set(element.id, [...currentElementMembers, element]);\r\n };\r\n\r\n // helper function to add an element to the groups map\r\n const addToGroupsMap = (element: ExcalidrawElement, groupId: string) => {\r\n // groups\r\n const currentGroupMembers = groups.get(groupId) || [];\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n\r\n if (boundTextElement) {\r\n currentGroupMembers.push(boundTextElement);\r\n }\r\n groups.set(groupId, [...currentGroupMembers, element]);\r\n };\r\n\r\n // helper function to handle the case where a single group is selected\r\n // and all elements selected are within the group, it will respect group hierarchy in accordance to\r\n // their nested grouping order\r\n const handleSingleSelectedGroupCase = (\r\n element: ExcalidrawElement,\r\n selectedGroupId: GroupId,\r\n ) => {\r\n const indexOfSelectedGroupId = element.groupIds.indexOf(selectedGroupId, 0);\r\n const nestedGroupCount = element.groupIds.slice(\r\n 0,\r\n indexOfSelectedGroupId,\r\n ).length;\r\n return nestedGroupCount > 0\r\n ? addToGroupsMap(element, element.groupIds[indexOfSelectedGroupId - 1])\r\n : addToElementsMap(element);\r\n };\r\n\r\n const isAllInSameGroup = selectedElements.every((element) =>\r\n isSelectedViaGroup(appState, element),\r\n );\r\n\r\n unboundElements.forEach((element) => {\r\n const selectedGroupId = getSelectedGroupIdForElement(\r\n element,\r\n appState.selectedGroupIds,\r\n );\r\n if (!selectedGroupId) {\r\n addToElementsMap(element);\r\n } else if (selectedGroupIds.length === 1 && isAllInSameGroup) {\r\n handleSingleSelectedGroupCase(element, selectedGroupId);\r\n } else {\r\n addToGroupsMap(element, selectedGroupId);\r\n }\r\n });\r\n return Array.from(groups.values()).concat(Array.from(elements.values()));\r\n};\r\n", "import type { ElementOrToolType } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nexport const hasBackground = (type: ElementOrToolType) =>\r\n type === \"rectangle\" ||\r\n type === \"iframe\" ||\r\n type === \"embeddable\" ||\r\n type === \"ellipse\" ||\r\n type === \"diamond\" ||\r\n type === \"line\" ||\r\n type === \"freedraw\";\r\n\r\nexport const hasStrokeColor = (type: ElementOrToolType) =>\r\n type === \"rectangle\" ||\r\n type === \"ellipse\" ||\r\n type === \"diamond\" ||\r\n type === \"freedraw\" ||\r\n type === \"arrow\" ||\r\n type === \"line\" ||\r\n type === \"text\" ||\r\n type === \"embeddable\";\r\n\r\nexport const hasStrokeWidth = (type: ElementOrToolType) =>\r\n type === \"rectangle\" ||\r\n type === \"iframe\" ||\r\n type === \"embeddable\" ||\r\n type === \"ellipse\" ||\r\n type === \"diamond\" ||\r\n type === \"freedraw\" ||\r\n type === \"arrow\" ||\r\n type === \"line\";\r\n\r\nexport const hasStrokeStyle = (type: ElementOrToolType) =>\r\n type === \"rectangle\" ||\r\n type === \"iframe\" ||\r\n type === \"embeddable\" ||\r\n type === \"ellipse\" ||\r\n type === \"diamond\" ||\r\n type === \"arrow\" ||\r\n type === \"line\";\r\n\r\nexport const canChangeRoundness = (type: ElementOrToolType) =>\r\n type === \"rectangle\" ||\r\n type === \"iframe\" ||\r\n type === \"embeddable\" ||\r\n type === \"line\" ||\r\n type === \"diamond\" ||\r\n type === \"image\";\r\n\r\nexport const toolIsArrow = (type: ElementOrToolType) => type === \"arrow\";\r\n\r\nexport const canHaveArrowheads = (type: ElementOrToolType) => type === \"arrow\";\r\n", "import type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { updateBoundElements } from \"./binding\";\r\nimport { getCommonBoundingBox } from \"./bounds\";\r\nimport { getSelectedElementsByGroup } from \"./groups\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\nimport type { BoundingBox } from \"./bounds\";\r\nimport type { ExcalidrawElement } from \"./types\";\r\n\r\nexport interface Alignment {\r\n position: \"start\" | \"center\" | \"end\";\r\n axis: \"x\" | \"y\";\r\n}\r\n\r\nexport const alignElements = (\r\n selectedElements: ExcalidrawElement[],\r\n alignment: Alignment,\r\n scene: Scene,\r\n appState: Readonly<AppState>,\r\n): ExcalidrawElement[] => {\r\n const groups: ExcalidrawElement[][] = getSelectedElementsByGroup(\r\n selectedElements,\r\n scene.getNonDeletedElementsMap(),\r\n appState,\r\n );\r\n const selectionBoundingBox = getCommonBoundingBox(selectedElements);\r\n\r\n return groups.flatMap((group) => {\r\n const translation = calculateTranslation(\r\n group,\r\n selectionBoundingBox,\r\n alignment,\r\n );\r\n return group.map((element) => {\r\n // update element\r\n const updatedEle = scene.mutateElement(element, {\r\n x: element.x + translation.x,\r\n y: element.y + translation.y,\r\n });\r\n\r\n // update bound elements\r\n updateBoundElements(element, scene, {\r\n simultaneouslyUpdated: group,\r\n });\r\n return updatedEle;\r\n });\r\n });\r\n};\r\n\r\nconst calculateTranslation = (\r\n group: ExcalidrawElement[],\r\n selectionBoundingBox: BoundingBox,\r\n { axis, position }: Alignment,\r\n): { x: number; y: number } => {\r\n const groupBoundingBox = getCommonBoundingBox(group);\r\n\r\n const [min, max]: [\"minX\" | \"minY\", \"maxX\" | \"maxY\"] =\r\n axis === \"x\" ? [\"minX\", \"maxX\"] : [\"minY\", \"maxY\"];\r\n\r\n const noTranslation = { x: 0, y: 0 };\r\n if (position === \"start\") {\r\n return {\r\n ...noTranslation,\r\n [axis]: selectionBoundingBox[min] - groupBoundingBox[min],\r\n };\r\n } else if (position === \"end\") {\r\n return {\r\n ...noTranslation,\r\n [axis]: selectionBoundingBox[max] - groupBoundingBox[max],\r\n };\r\n } // else if (position === \"center\") {\r\n return {\r\n ...noTranslation,\r\n [axis]:\r\n (selectionBoundingBox[min] + selectionBoundingBox[max]) / 2 -\r\n (groupBoundingBox[min] + groupBoundingBox[max]) / 2,\r\n };\r\n};\r\n", "import {\r\n arrayToMap,\r\n arrayToObject,\r\n assertNever,\r\n isDevEnv,\r\n isShallowEqual,\r\n isTestEnv,\r\n randomInteger,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawTextElement,\r\n NonDeleted,\r\n Ordered,\r\n OrderedExcalidrawElement,\r\n SceneElementsMap,\r\n} from \"@excalidraw-modify/element/types\";\r\n\r\nimport type {\r\n DTO,\r\n Mutable,\r\n SubtypeOf,\r\n ValueOf,\r\n} from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport type {\r\n AppState,\r\n ObservedAppState,\r\n ObservedElementsAppState,\r\n ObservedStandaloneAppState,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { getObservedAppState } from \"./store\";\r\n\r\nimport {\r\n BoundElement,\r\n BindableElement,\r\n bindingProperties,\r\n updateBoundElements,\r\n} from \"./binding\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport { mutateElement, newElementWith } from \"./mutateElement\";\r\nimport { getBoundTextElementId, redrawTextBoundingBox } from \"./textElement\";\r\nimport {\r\n hasBoundTextElement,\r\n isBindableElement,\r\n isBoundToContainer,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport { getNonDeletedGroupIds } from \"./groups\";\r\n\r\nimport { orderByFractionalIndex, syncMovedIndices } from \"./fractionalIndex\";\r\n\r\nimport { StoreSnapshot } from \"./store\";\r\n\r\nimport { Scene } from \"./Scene\";\r\n\r\nimport type { BindableProp, BindingProp } from \"./binding\";\r\n\r\nimport type { ElementUpdate } from \"./mutateElement\";\r\n\r\n/**\r\n * Represents the difference between two objects of the same type.\r\n *\r\n * Both `deleted` and `inserted` partials represent the same set of added, removed or updated properties, where:\r\n * - `deleted` is a set of all the deleted values\r\n * - `inserted` is a set of all the inserted (added, updated) values\r\n *\r\n * Keeping it as pure object (without transient state, side-effects, etc.), so we won't have to instantiate it on load.\r\n */\r\nexport class Delta<T> {\r\n private constructor(\r\n public readonly deleted: Partial<T>,\r\n public readonly inserted: Partial<T>,\r\n ) {}\r\n\r\n public static create<T>(\r\n deleted: Partial<T>,\r\n inserted: Partial<T>,\r\n modifier?: (\r\n delta: Partial<T>,\r\n partialType: \"deleted\" | \"inserted\",\r\n ) => Partial<T>,\r\n modifierOptions?: \"deleted\" | \"inserted\" | \"both\",\r\n ) {\r\n const modifiedDeleted =\r\n modifier && modifierOptions !== \"inserted\"\r\n ? modifier(deleted, \"deleted\")\r\n : deleted;\r\n const modifiedInserted =\r\n modifier && modifierOptions !== \"deleted\"\r\n ? modifier(inserted, \"inserted\")\r\n : inserted;\r\n\r\n return new Delta(modifiedDeleted, modifiedInserted);\r\n }\r\n\r\n /**\r\n * Calculates the delta between two objects.\r\n *\r\n * @param prevObject - The previous state of the object.\r\n * @param nextObject - The next state of the object.\r\n *\r\n * @returns new delta instance.\r\n */\r\n public static calculate<T extends { [key: string]: any }>(\r\n prevObject: T,\r\n nextObject: T,\r\n modifier?: (partial: Partial<T>) => Partial<T>,\r\n postProcess?: (\r\n deleted: Partial<T>,\r\n inserted: Partial<T>,\r\n ) => [Partial<T>, Partial<T>],\r\n ): Delta<T> {\r\n if (prevObject === nextObject) {\r\n return Delta.empty();\r\n }\r\n\r\n const deleted = {} as Partial<T>;\r\n const inserted = {} as Partial<T>;\r\n\r\n // O(n^3) here for elements, but it's not as bad as it looks:\r\n // - we do this only on store recordings, not on every frame (not for ephemerals)\r\n // - we do this only on previously detected changed elements\r\n // - we do shallow compare only on the first level of properties (not going any deeper)\r\n // - # of properties is reasonably small\r\n for (const key of this.getDifferences(prevObject, nextObject)) {\r\n deleted[key as keyof T] = prevObject[key];\r\n inserted[key as keyof T] = nextObject[key];\r\n }\r\n\r\n const [processedDeleted, processedInserted] = postProcess\r\n ? postProcess(deleted, inserted)\r\n : [deleted, inserted];\r\n\r\n return Delta.create(processedDeleted, processedInserted, modifier);\r\n }\r\n\r\n public static empty() {\r\n return new Delta({}, {});\r\n }\r\n\r\n public static isEmpty<T>(delta: Delta<T>): boolean {\r\n return (\r\n !Object.keys(delta.deleted).length && !Object.keys(delta.inserted).length\r\n );\r\n }\r\n\r\n /**\r\n * Merges two deltas into a new one.\r\n */\r\n public static merge<T>(\r\n delta1: Delta<T>,\r\n delta2: Delta<T>,\r\n delta3: Delta<T> = Delta.empty(),\r\n ) {\r\n return Delta.create(\r\n { ...delta1.deleted, ...delta2.deleted, ...delta3.deleted },\r\n { ...delta1.inserted, ...delta2.inserted, ...delta3.inserted },\r\n );\r\n }\r\n\r\n /**\r\n * Merges deleted and inserted object partials.\r\n */\r\n public static mergeObjects<T extends { [key: string]: unknown }>(\r\n prev: T,\r\n added: T,\r\n removed: T = {} as T,\r\n ) {\r\n const cloned = { ...prev };\r\n\r\n for (const key of Object.keys(removed)) {\r\n delete cloned[key];\r\n }\r\n\r\n return { ...cloned, ...added };\r\n }\r\n\r\n /**\r\n * Merges deleted and inserted array partials.\r\n */\r\n public static mergeArrays<T>(\r\n prev: readonly T[] | null,\r\n added: readonly T[] | null | undefined,\r\n removed: readonly T[] | null | undefined,\r\n predicate?: (value: T) => string,\r\n ) {\r\n return Object.values(\r\n Delta.mergeObjects(\r\n arrayToObject(prev ?? [], predicate),\r\n arrayToObject(added ?? [], predicate),\r\n arrayToObject(removed ?? [], predicate),\r\n ),\r\n );\r\n }\r\n\r\n /**\r\n * Diff object partials as part of the `postProcess`.\r\n */\r\n public static diffObjects<T, K extends keyof T, V extends ValueOf<T[K]>>(\r\n deleted: Partial<T>,\r\n inserted: Partial<T>,\r\n property: K,\r\n setValue: (prevValue: V | undefined) => V,\r\n ) {\r\n if (!deleted[property] && !inserted[property]) {\r\n return;\r\n }\r\n\r\n const isDeletedObject =\r\n deleted[property] !== null && typeof deleted[property] === \"object\";\r\n const isInsertedObject =\r\n inserted[property] !== null && typeof inserted[property] === \"object\";\r\n\r\n if (isDeletedObject || isInsertedObject) {\r\n type RecordLike = Record<string, V | undefined>;\r\n\r\n const deletedObject: RecordLike = deleted[property] ?? {};\r\n const insertedObject: RecordLike = inserted[property] ?? {};\r\n\r\n const deletedDifferences = Delta.getLeftDifferences(\r\n deletedObject,\r\n insertedObject,\r\n ).reduce((acc, curr) => {\r\n acc[curr] = setValue(deletedObject[curr]);\r\n return acc;\r\n }, {} as RecordLike);\r\n\r\n const insertedDifferences = Delta.getRightDifferences(\r\n deletedObject,\r\n insertedObject,\r\n ).reduce((acc, curr) => {\r\n acc[curr] = setValue(insertedObject[curr]);\r\n return acc;\r\n }, {} as RecordLike);\r\n\r\n if (\r\n Object.keys(deletedDifferences).length ||\r\n Object.keys(insertedDifferences).length\r\n ) {\r\n Reflect.set(deleted, property, deletedDifferences);\r\n Reflect.set(inserted, property, insertedDifferences);\r\n } else {\r\n Reflect.deleteProperty(deleted, property);\r\n Reflect.deleteProperty(inserted, property);\r\n }\r\n } else if (deleted[property] === inserted[property]) {\r\n Reflect.deleteProperty(deleted, property);\r\n Reflect.deleteProperty(inserted, property);\r\n }\r\n }\r\n\r\n /**\r\n * Diff array partials as part of the `postProcess`.\r\n */\r\n public static diffArrays<T, K extends keyof T, V extends T[K]>(\r\n deleted: Partial<T>,\r\n inserted: Partial<T>,\r\n property: K,\r\n groupBy: (value: V extends ArrayLike<infer T> ? T : never) => string,\r\n ) {\r\n if (!deleted[property] && !inserted[property]) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(deleted[property]) || Array.isArray(inserted[property])) {\r\n const deletedArray = (\r\n Array.isArray(deleted[property]) ? deleted[property] : []\r\n ) as [];\r\n const insertedArray = (\r\n Array.isArray(inserted[property]) ? inserted[property] : []\r\n ) as [];\r\n\r\n const deletedDifferences = arrayToObject(\r\n Delta.getLeftDifferences(\r\n arrayToObject(deletedArray, groupBy),\r\n arrayToObject(insertedArray, groupBy),\r\n ),\r\n (x) => x,\r\n );\r\n const insertedDifferences = arrayToObject(\r\n Delta.getRightDifferences(\r\n arrayToObject(deletedArray, groupBy),\r\n arrayToObject(insertedArray, groupBy),\r\n ),\r\n (x) => x,\r\n );\r\n\r\n if (\r\n Object.keys(deletedDifferences).length ||\r\n Object.keys(insertedDifferences).length\r\n ) {\r\n const deletedValue = deletedArray.filter(\r\n (x) => deletedDifferences[groupBy ? groupBy(x) : String(x)],\r\n );\r\n const insertedValue = insertedArray.filter(\r\n (x) => insertedDifferences[groupBy ? groupBy(x) : String(x)],\r\n );\r\n\r\n Reflect.set(deleted, property, deletedValue);\r\n Reflect.set(inserted, property, insertedValue);\r\n } else {\r\n Reflect.deleteProperty(deleted, property);\r\n Reflect.deleteProperty(inserted, property);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Compares if object1 contains any different value compared to the object2.\r\n */\r\n public static isLeftDifferent<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ): boolean {\r\n const anyDistinctKey = this.distinctKeysIterator(\r\n \"left\",\r\n object1,\r\n object2,\r\n skipShallowCompare,\r\n ).next().value;\r\n\r\n return !!anyDistinctKey;\r\n }\r\n\r\n /**\r\n * Compares if object2 contains any different value compared to the object1.\r\n */\r\n public static isRightDifferent<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ): boolean {\r\n const anyDistinctKey = this.distinctKeysIterator(\r\n \"right\",\r\n object1,\r\n object2,\r\n skipShallowCompare,\r\n ).next().value;\r\n\r\n return !!anyDistinctKey;\r\n }\r\n\r\n /**\r\n * Compares if shared properties of object1 and object2 contain any different value (aka inner join).\r\n */\r\n public static isInnerDifferent<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ): boolean {\r\n const anyDistinctKey = !!this.distinctKeysIterator(\r\n \"inner\",\r\n object1,\r\n object2,\r\n skipShallowCompare,\r\n ).next().value;\r\n\r\n return !!anyDistinctKey;\r\n }\r\n\r\n /**\r\n * Compares if any properties of object1 and object2 contain any different value (aka full join).\r\n */\r\n public static isDifferent<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ): boolean {\r\n const anyDistinctKey = !!this.distinctKeysIterator(\r\n \"full\",\r\n object1,\r\n object2,\r\n skipShallowCompare,\r\n ).next().value;\r\n\r\n return !!anyDistinctKey;\r\n }\r\n\r\n /**\r\n * Returns sorted object1 keys that have distinct values.\r\n */\r\n public static getLeftDifferences<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ) {\r\n return Array.from(\r\n this.distinctKeysIterator(\"left\", object1, object2, skipShallowCompare),\r\n ).sort();\r\n }\r\n\r\n /**\r\n * Returns sorted object2 keys that have distinct values.\r\n */\r\n public static getRightDifferences<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ) {\r\n return Array.from(\r\n this.distinctKeysIterator(\"right\", object1, object2, skipShallowCompare),\r\n ).sort();\r\n }\r\n\r\n /**\r\n * Returns sorted keys of shared object1 and object2 properties that have distinct values (aka inner join).\r\n */\r\n public static getInnerDifferences<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ) {\r\n return Array.from(\r\n this.distinctKeysIterator(\"inner\", object1, object2, skipShallowCompare),\r\n ).sort();\r\n }\r\n\r\n /**\r\n * Returns sorted keys that have distinct values between object1 and object2 (aka full join).\r\n */\r\n public static getDifferences<T extends {}>(\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ) {\r\n return Array.from(\r\n this.distinctKeysIterator(\"full\", object1, object2, skipShallowCompare),\r\n ).sort();\r\n }\r\n\r\n /**\r\n * Iterator comparing values of object properties based on the passed joining strategy.\r\n *\r\n * @yields keys of properties with different values\r\n *\r\n * WARN: it's based on shallow compare performed only on the first level and doesn't go deeper than that.\r\n */\r\n private static *distinctKeysIterator<T extends {}>(\r\n join: \"left\" | \"right\" | \"inner\" | \"full\",\r\n object1: T,\r\n object2: T,\r\n skipShallowCompare = false,\r\n ) {\r\n if (object1 === object2) {\r\n return;\r\n }\r\n\r\n let keys: string[] = [];\r\n\r\n if (join === \"left\") {\r\n keys = Object.keys(object1);\r\n } else if (join === \"right\") {\r\n keys = Object.keys(object2);\r\n } else if (join === \"inner\") {\r\n keys = Object.keys(object1).filter((key) => key in object2);\r\n } else if (join === \"full\") {\r\n keys = Array.from(\r\n new Set([...Object.keys(object1), ...Object.keys(object2)]),\r\n );\r\n } else {\r\n assertNever(\r\n join,\r\n `Unknown distinctKeysIterator's join param \"${join}\"`,\r\n true,\r\n );\r\n }\r\n\r\n for (const key of keys) {\r\n const value1 = object1[key as keyof T];\r\n const value2 = object2[key as keyof T];\r\n\r\n if (value1 !== value2) {\r\n if (\r\n !skipShallowCompare &&\r\n typeof value1 === \"object\" &&\r\n typeof value2 === \"object\" &&\r\n value1 !== null &&\r\n value2 !== null &&\r\n isShallowEqual(value1, value2)\r\n ) {\r\n continue;\r\n }\r\n\r\n yield key;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Encapsulates a set of application-level `Delta`s.\r\n */\r\nexport interface DeltaContainer<T> {\r\n /**\r\n * Inverses the `Delta`s while creating a new `DeltaContainer` instance.\r\n */\r\n inverse(): DeltaContainer<T>;\r\n\r\n /**\r\n * Applies the `Delta`s to the previous object.\r\n *\r\n * @returns a tuple of the next object `T` with applied `Delta`s, and `boolean`, indicating whether the applied deltas resulted in a visible change.\r\n */\r\n applyTo(previous: T, ...options: unknown[]): [T, boolean];\r\n\r\n /**\r\n * Squashes the current delta with the given one.\r\n */\r\n squash(delta: DeltaContainer<T>): this;\r\n\r\n /**\r\n * Checks whether all `Delta`s are empty.\r\n */\r\n isEmpty(): boolean;\r\n}\r\n\r\nexport class AppStateDelta implements DeltaContainer<AppState> {\r\n private constructor(public delta: Delta<ObservedAppState>) {}\r\n\r\n public static create(delta: Delta<ObservedAppState>): AppStateDelta {\r\n return new AppStateDelta(delta);\r\n }\r\n\r\n public static calculate<T extends ObservedAppState>(\r\n prevAppState: T,\r\n nextAppState: T,\r\n ): AppStateDelta {\r\n const delta = Delta.calculate(\r\n prevAppState,\r\n nextAppState,\r\n // making the order of keys in deltas stable for hashing purposes\r\n AppStateDelta.orderAppStateKeys,\r\n AppStateDelta.postProcess,\r\n );\r\n\r\n return new AppStateDelta(delta);\r\n }\r\n\r\n public static restore(appStateDeltaDTO: DTO<AppStateDelta>): AppStateDelta {\r\n const { delta } = appStateDeltaDTO;\r\n return new AppStateDelta(delta);\r\n }\r\n\r\n public static empty() {\r\n return new AppStateDelta(Delta.create({}, {}));\r\n }\r\n\r\n public inverse(): AppStateDelta {\r\n const inversedDelta = Delta.create(this.delta.inserted, this.delta.deleted);\r\n return new AppStateDelta(inversedDelta);\r\n }\r\n\r\n public squash(delta: AppStateDelta): this {\r\n if (delta.isEmpty()) {\r\n return this;\r\n }\r\n\r\n const mergedDeletedSelectedElementIds = Delta.mergeObjects(\r\n this.delta.deleted.selectedElementIds ?? {},\r\n delta.delta.deleted.selectedElementIds ?? {},\r\n );\r\n\r\n const mergedInsertedSelectedElementIds = Delta.mergeObjects(\r\n this.delta.inserted.selectedElementIds ?? {},\r\n delta.delta.inserted.selectedElementIds ?? {},\r\n );\r\n\r\n const mergedDeletedSelectedGroupIds = Delta.mergeObjects(\r\n this.delta.deleted.selectedGroupIds ?? {},\r\n delta.delta.deleted.selectedGroupIds ?? {},\r\n );\r\n\r\n const mergedInsertedSelectedGroupIds = Delta.mergeObjects(\r\n this.delta.inserted.selectedGroupIds ?? {},\r\n delta.delta.inserted.selectedGroupIds ?? {},\r\n );\r\n\r\n const mergedDeletedLockedMultiSelections = Delta.mergeObjects(\r\n this.delta.deleted.lockedMultiSelections ?? {},\r\n delta.delta.deleted.lockedMultiSelections ?? {},\r\n );\r\n\r\n const mergedInsertedLockedMultiSelections = Delta.mergeObjects(\r\n this.delta.inserted.lockedMultiSelections ?? {},\r\n delta.delta.inserted.lockedMultiSelections ?? {},\r\n );\r\n\r\n const mergedInserted: Partial<ObservedAppState> = {};\r\n const mergedDeleted: Partial<ObservedAppState> = {};\r\n\r\n if (\r\n Object.keys(mergedDeletedSelectedElementIds).length ||\r\n Object.keys(mergedInsertedSelectedElementIds).length\r\n ) {\r\n mergedDeleted.selectedElementIds = mergedDeletedSelectedElementIds;\r\n mergedInserted.selectedElementIds = mergedInsertedSelectedElementIds;\r\n }\r\n\r\n if (\r\n Object.keys(mergedDeletedSelectedGroupIds).length ||\r\n Object.keys(mergedInsertedSelectedGroupIds).length\r\n ) {\r\n mergedDeleted.selectedGroupIds = mergedDeletedSelectedGroupIds;\r\n mergedInserted.selectedGroupIds = mergedInsertedSelectedGroupIds;\r\n }\r\n\r\n if (\r\n Object.keys(mergedDeletedLockedMultiSelections).length ||\r\n Object.keys(mergedInsertedLockedMultiSelections).length\r\n ) {\r\n mergedDeleted.lockedMultiSelections = mergedDeletedLockedMultiSelections;\r\n mergedInserted.lockedMultiSelections =\r\n mergedInsertedLockedMultiSelections;\r\n }\r\n\r\n this.delta = Delta.merge(\r\n this.delta,\r\n delta.delta,\r\n Delta.create(mergedDeleted, mergedInserted),\r\n );\r\n\r\n return this;\r\n }\r\n\r\n public applyTo(\r\n appState: AppState,\r\n nextElements: SceneElementsMap,\r\n ): [AppState, boolean] {\r\n try {\r\n const {\r\n selectedElementIds: deletedSelectedElementIds = {},\r\n selectedGroupIds: deletedSelectedGroupIds = {},\r\n lockedMultiSelections: deletedLockedMultiSelections = {},\r\n } = this.delta.deleted;\r\n\r\n const {\r\n selectedElementIds: insertedSelectedElementIds = {},\r\n selectedGroupIds: insertedSelectedGroupIds = {},\r\n lockedMultiSelections: insertedLockedMultiSelections = {},\r\n selectedLinearElement: insertedSelectedLinearElement,\r\n ...directlyApplicablePartial\r\n } = this.delta.inserted;\r\n\r\n const mergedSelectedElementIds = Delta.mergeObjects(\r\n appState.selectedElementIds,\r\n insertedSelectedElementIds,\r\n deletedSelectedElementIds,\r\n );\r\n\r\n const mergedSelectedGroupIds = Delta.mergeObjects(\r\n appState.selectedGroupIds,\r\n insertedSelectedGroupIds,\r\n deletedSelectedGroupIds,\r\n );\r\n\r\n const mergedLockedMultiSelections = Delta.mergeObjects(\r\n appState.lockedMultiSelections,\r\n insertedLockedMultiSelections,\r\n deletedLockedMultiSelections,\r\n );\r\n\r\n const selectedLinearElement =\r\n insertedSelectedLinearElement &&\r\n nextElements.has(insertedSelectedLinearElement.elementId)\r\n ? new LinearElementEditor(\r\n nextElements.get(\r\n insertedSelectedLinearElement.elementId,\r\n ) as NonDeleted<ExcalidrawLinearElement>,\r\n nextElements,\r\n insertedSelectedLinearElement.isEditing,\r\n )\r\n : null;\r\n\r\n const nextAppState = {\r\n ...appState,\r\n ...directlyApplicablePartial,\r\n selectedElementIds: mergedSelectedElementIds,\r\n selectedGroupIds: mergedSelectedGroupIds,\r\n lockedMultiSelections: mergedLockedMultiSelections,\r\n selectedLinearElement:\r\n typeof insertedSelectedLinearElement !== \"undefined\"\r\n ? selectedLinearElement\r\n : appState.selectedLinearElement,\r\n };\r\n\r\n const constainsVisibleChanges = this.filterInvisibleChanges(\r\n appState,\r\n nextAppState,\r\n nextElements,\r\n );\r\n\r\n return [nextAppState, constainsVisibleChanges];\r\n } catch (e) {\r\n // shouldn't really happen, but just in case\r\n console.error(`Couldn't apply appstate change`, e);\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw e;\r\n }\r\n\r\n return [appState, false];\r\n }\r\n }\r\n\r\n public isEmpty(): boolean {\r\n return Delta.isEmpty(this.delta);\r\n }\r\n\r\n /**\r\n * Mutates `nextAppState` be filtering out state related to deleted elements.\r\n *\r\n * @returns `true` if a visible change is found, `false` otherwise.\r\n */\r\n private filterInvisibleChanges(\r\n prevAppState: AppState,\r\n nextAppState: AppState,\r\n nextElements: SceneElementsMap,\r\n ): boolean {\r\n // TODO: #7348 we could still get an empty undo/redo, as we assume that previous appstate does not contain references to deleted elements\r\n // which is not always true - i.e. now we do cleanup appstate during history, but we do not do it during remote updates\r\n const prevObservedAppState = getObservedAppState(prevAppState);\r\n const nextObservedAppState = getObservedAppState(nextAppState);\r\n\r\n const containsStandaloneDifference = Delta.isRightDifferent(\r\n AppStateDelta.stripElementsProps(prevObservedAppState),\r\n AppStateDelta.stripElementsProps(nextObservedAppState),\r\n );\r\n\r\n const containsElementsDifference = Delta.isRightDifferent(\r\n AppStateDelta.stripStandaloneProps(prevObservedAppState),\r\n AppStateDelta.stripStandaloneProps(nextObservedAppState),\r\n );\r\n\r\n if (!containsStandaloneDifference && !containsElementsDifference) {\r\n // no change in appstate was detected\r\n return false;\r\n }\r\n\r\n const visibleDifferenceFlag = {\r\n value: containsStandaloneDifference,\r\n };\r\n\r\n if (containsElementsDifference) {\r\n // filter invisible changes on each iteration\r\n const changedElementsProps = Delta.getRightDifferences(\r\n AppStateDelta.stripStandaloneProps(prevObservedAppState),\r\n AppStateDelta.stripStandaloneProps(nextObservedAppState),\r\n ) as Array<keyof ObservedElementsAppState>;\r\n\r\n let nonDeletedGroupIds = new Set<string>();\r\n\r\n if (\r\n changedElementsProps.includes(\"editingGroupId\") ||\r\n changedElementsProps.includes(\"selectedGroupIds\")\r\n ) {\r\n // this one iterates through all the non deleted elements, so make sure it's not done twice\r\n nonDeletedGroupIds = getNonDeletedGroupIds(nextElements);\r\n }\r\n\r\n // check whether delta properties are related to the existing non-deleted elements\r\n for (const key of changedElementsProps) {\r\n switch (key) {\r\n case \"selectedElementIds\":\r\n nextAppState[key] = AppStateDelta.filterSelectedElements(\r\n nextAppState[key],\r\n nextElements,\r\n visibleDifferenceFlag,\r\n );\r\n\r\n break;\r\n case \"selectedGroupIds\":\r\n nextAppState[key] = AppStateDelta.filterSelectedGroups(\r\n nextAppState[key],\r\n nonDeletedGroupIds,\r\n visibleDifferenceFlag,\r\n );\r\n\r\n break;\r\n case \"croppingElementId\": {\r\n const croppingElementId = nextAppState[key];\r\n\r\n if (!croppingElementId) {\r\n // previously there was a croppingElementId (assuming visible), now there is none\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n const element = nextElements.get(croppingElementId);\r\n\r\n if (element && !element.isDeleted) {\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n nextAppState[key] = null;\r\n }\r\n }\r\n\r\n break;\r\n }\r\n case \"editingGroupId\":\r\n const editingGroupId = nextAppState[key];\r\n\r\n if (!editingGroupId) {\r\n // previously there was an editingGroup (assuming visible), now there is none\r\n visibleDifferenceFlag.value = true;\r\n } else if (nonDeletedGroupIds.has(editingGroupId)) {\r\n // previously there wasn't an editingGroup, now there is one which is visible\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n // there was assigned an editingGroup now, but it's related to deleted element\r\n nextAppState[key] = null;\r\n }\r\n\r\n break;\r\n case \"selectedLinearElement\":\r\n const nextLinearElement = nextAppState[key];\r\n\r\n if (!nextLinearElement) {\r\n // previously there was a linear element (assuming visible), now there is none\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n const element = nextElements.get(nextLinearElement.elementId);\r\n\r\n if (element && !element.isDeleted) {\r\n // previously there wasn't a linear element, now there is one which is visible\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n // there was assigned a linear element now, but it's deleted\r\n nextAppState[key] = null;\r\n }\r\n }\r\n\r\n break;\r\n case \"lockedMultiSelections\":\r\n const prevLockedUnits = prevAppState[key] || {};\r\n const nextLockedUnits = nextAppState[key] || {};\r\n\r\n // TODO: this seems wrong, we are already doing this comparison generically above,\r\n // hence instead we should check whether elements are actually visible,\r\n // so that once these changes are applied they actually result in a visible change to the user\r\n if (!isShallowEqual(prevLockedUnits, nextLockedUnits)) {\r\n visibleDifferenceFlag.value = true;\r\n }\r\n break;\r\n case \"activeLockedId\":\r\n const prevHitLockedId = prevAppState[key] || null;\r\n const nextHitLockedId = nextAppState[key] || null;\r\n\r\n // TODO: this seems wrong, we are already doing this comparison generically above,\r\n // hence instead we should check whether elements are actually visible,\r\n // so that once these changes are applied they actually result in a visible change to the user\r\n if (prevHitLockedId !== nextHitLockedId) {\r\n visibleDifferenceFlag.value = true;\r\n }\r\n break;\r\n default:\r\n assertNever(\r\n key,\r\n `Unknown ObservedElementsAppState's key \"${key}\"`,\r\n true,\r\n );\r\n }\r\n }\r\n }\r\n\r\n return visibleDifferenceFlag.value;\r\n }\r\n\r\n private static filterSelectedElements(\r\n selectedElementIds: AppState[\"selectedElementIds\"],\r\n elements: SceneElementsMap,\r\n visibleDifferenceFlag: { value: boolean },\r\n ) {\r\n const ids = Object.keys(selectedElementIds);\r\n\r\n if (!ids.length) {\r\n // previously there were ids (assuming related to visible elements), now there are none\r\n visibleDifferenceFlag.value = true;\r\n return selectedElementIds;\r\n }\r\n\r\n const nextSelectedElementIds = { ...selectedElementIds };\r\n\r\n for (const id of ids) {\r\n const element = elements.get(id);\r\n\r\n if (element && !element.isDeleted) {\r\n // there is a selected element id related to a visible element\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n delete nextSelectedElementIds[id];\r\n }\r\n }\r\n\r\n return nextSelectedElementIds;\r\n }\r\n\r\n private static filterSelectedGroups(\r\n selectedGroupIds: AppState[\"selectedGroupIds\"],\r\n nonDeletedGroupIds: Set<string>,\r\n visibleDifferenceFlag: { value: boolean },\r\n ) {\r\n const ids = Object.keys(selectedGroupIds);\r\n\r\n if (!ids.length) {\r\n // previously there were ids (assuming related to visible groups), now there are none\r\n visibleDifferenceFlag.value = true;\r\n return selectedGroupIds;\r\n }\r\n\r\n const nextSelectedGroupIds = { ...selectedGroupIds };\r\n\r\n for (const id of Object.keys(nextSelectedGroupIds)) {\r\n if (nonDeletedGroupIds.has(id)) {\r\n // there is a selected group id related to a visible group\r\n visibleDifferenceFlag.value = true;\r\n } else {\r\n delete nextSelectedGroupIds[id];\r\n }\r\n }\r\n\r\n return nextSelectedGroupIds;\r\n }\r\n\r\n private static stripElementsProps(\r\n delta: Partial<ObservedAppState>,\r\n ): Partial<ObservedStandaloneAppState> {\r\n // WARN: Do not remove the type-casts as they here to ensure proper type checks\r\n const {\r\n editingGroupId,\r\n selectedGroupIds,\r\n selectedElementIds,\r\n selectedLinearElement,\r\n croppingElementId,\r\n lockedMultiSelections,\r\n activeLockedId,\r\n ...standaloneProps\r\n } = delta as ObservedAppState;\r\n\r\n return standaloneProps as SubtypeOf<\r\n typeof standaloneProps,\r\n ObservedStandaloneAppState\r\n >;\r\n }\r\n\r\n private static stripStandaloneProps(\r\n delta: Partial<ObservedAppState>,\r\n ): Partial<ObservedElementsAppState> {\r\n // WARN: Do not remove the type-casts as they here to ensure proper type checks\r\n const { name, viewBackgroundColor, ...elementsProps } =\r\n delta as ObservedAppState;\r\n\r\n return elementsProps as SubtypeOf<\r\n typeof elementsProps,\r\n ObservedElementsAppState\r\n >;\r\n }\r\n\r\n /**\r\n * It is necessary to post process the partials in case of reference values,\r\n * for which we need to calculate the real diff between `deleted` and `inserted`.\r\n */\r\n private static postProcess<T extends ObservedAppState>(\r\n deleted: Partial<T>,\r\n inserted: Partial<T>,\r\n ): [Partial<T>, Partial<T>] {\r\n try {\r\n Delta.diffObjects(\r\n deleted,\r\n inserted,\r\n \"selectedElementIds\",\r\n // ts language server has a bit trouble resolving this, so we are giving it a little push\r\n (_) => true as ValueOf<T[\"selectedElementIds\"]>,\r\n );\r\n Delta.diffObjects(\r\n deleted,\r\n inserted,\r\n \"selectedGroupIds\",\r\n (prevValue) => (prevValue ?? false) as ValueOf<T[\"selectedGroupIds\"]>,\r\n );\r\n Delta.diffObjects(\r\n deleted,\r\n inserted,\r\n \"lockedMultiSelections\",\r\n (prevValue) => (prevValue ?? {}) as ValueOf<T[\"lockedMultiSelections\"]>,\r\n );\r\n } catch (e) {\r\n // if postprocessing fails it does not make sense to bubble up, but let's make sure we know about it\r\n console.error(`Couldn't postprocess appstate change deltas.`);\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw e;\r\n }\r\n } finally {\r\n return [deleted, inserted];\r\n }\r\n }\r\n\r\n private static orderAppStateKeys(partial: Partial<ObservedAppState>) {\r\n const orderedPartial: { [key: string]: unknown } = {};\r\n\r\n for (const key of Object.keys(partial).sort()) {\r\n // relying on insertion order\r\n orderedPartial[key] = partial[key as keyof ObservedAppState];\r\n }\r\n\r\n return orderedPartial as Partial<ObservedAppState>;\r\n }\r\n}\r\n\r\ntype ElementPartial<TElement extends ExcalidrawElement = ExcalidrawElement> =\r\n Omit<Partial<Ordered<TElement>>, \"id\" | \"updated\" | \"seed\">;\r\n\r\nexport type ApplyToOptions = {\r\n excludedProperties?: Set<keyof ElementPartial>;\r\n};\r\n\r\ntype ApplyToFlags = {\r\n containsVisibleDifference: boolean;\r\n containsZindexDifference: boolean;\r\n applyDirection: \"forward\" | \"backward\" | undefined;\r\n};\r\n\r\n/**\r\n * Elements change is a low level primitive to capture a change between two sets of elements.\r\n * It does so by encapsulating forward and backward `Delta`s, allowing to time-travel in both directions.\r\n */\r\nexport class ElementsDelta implements DeltaContainer<SceneElementsMap> {\r\n private constructor(\r\n public readonly added: Record<string, Delta<ElementPartial>>,\r\n public readonly removed: Record<string, Delta<ElementPartial>>,\r\n public readonly updated: Record<string, Delta<ElementPartial>>,\r\n ) {}\r\n\r\n public static create(\r\n added: Record<string, Delta<ElementPartial>>,\r\n removed: Record<string, Delta<ElementPartial>>,\r\n updated: Record<string, Delta<ElementPartial>>,\r\n options: {\r\n shouldRedistribute: boolean;\r\n } = {\r\n shouldRedistribute: false,\r\n },\r\n ) {\r\n let delta: ElementsDelta;\r\n\r\n if (options.shouldRedistribute) {\r\n const nextAdded: Record<string, Delta<ElementPartial>> = {};\r\n const nextRemoved: Record<string, Delta<ElementPartial>> = {};\r\n const nextUpdated: Record<string, Delta<ElementPartial>> = {};\r\n\r\n const deltas = [\r\n ...Object.entries(added),\r\n ...Object.entries(removed),\r\n ...Object.entries(updated),\r\n ];\r\n\r\n for (const [id, delta] of deltas) {\r\n if (this.satisfiesAddition(delta)) {\r\n nextAdded[id] = delta;\r\n } else if (this.satisfiesRemoval(delta)) {\r\n nextRemoved[id] = delta;\r\n } else {\r\n nextUpdated[id] = delta;\r\n }\r\n }\r\n\r\n delta = new ElementsDelta(nextAdded, nextRemoved, nextUpdated);\r\n } else {\r\n delta = new ElementsDelta(added, removed, updated);\r\n }\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n ElementsDelta.validate(delta, \"added\", this.satisfiesAddition);\r\n ElementsDelta.validate(delta, \"removed\", this.satisfiesRemoval);\r\n ElementsDelta.validate(delta, \"updated\", this.satisfiesUpdate);\r\n }\r\n\r\n return delta;\r\n }\r\n\r\n public static restore(elementsDeltaDTO: DTO<ElementsDelta>): ElementsDelta {\r\n const { added, removed, updated } = elementsDeltaDTO;\r\n return ElementsDelta.create(added, removed, updated);\r\n }\r\n\r\n private static satisfiesAddition = ({\r\n deleted,\r\n inserted,\r\n }: Delta<ElementPartial>) =>\r\n // dissallowing added as \"deleted\", which could cause issues when resolving conflicts\r\n deleted.isDeleted === true && !inserted.isDeleted;\r\n\r\n private static satisfiesRemoval = ({\r\n deleted,\r\n inserted,\r\n }: Delta<ElementPartial>) =>\r\n !deleted.isDeleted && inserted.isDeleted === true;\r\n\r\n private static satisfiesUpdate = ({\r\n deleted,\r\n inserted,\r\n }: Delta<ElementPartial>) => !!deleted.isDeleted === !!inserted.isDeleted;\r\n\r\n private static satisfiesCommmonInvariants = ({\r\n deleted,\r\n inserted,\r\n }: Delta<ElementPartial>) =>\r\n !!(\r\n // versions are required integers\r\n (\r\n Number.isInteger(deleted.version) &&\r\n Number.isInteger(inserted.version) &&\r\n // versions should be positive, zero included\r\n deleted.version! >= 0 &&\r\n inserted.version! >= 0 &&\r\n // versions should never be the same\r\n deleted.version !== inserted.version\r\n )\r\n );\r\n\r\n private static satisfiesUniqueInvariants = (\r\n elementsDelta: ElementsDelta,\r\n id: string,\r\n ) => {\r\n const { added, removed, updated } = elementsDelta;\r\n // it's required that there is only one unique delta type per element\r\n return [added[id], removed[id], updated[id]].filter(Boolean).length === 1;\r\n };\r\n\r\n private static validate(\r\n elementsDelta: ElementsDelta,\r\n type: \"added\" | \"removed\" | \"updated\",\r\n satifiesSpecialInvariants: (delta: Delta<ElementPartial>) => boolean,\r\n ) {\r\n for (const [id, delta] of Object.entries(elementsDelta[type])) {\r\n if (\r\n !this.satisfiesCommmonInvariants(delta) ||\r\n !this.satisfiesUniqueInvariants(elementsDelta, id) ||\r\n !satifiesSpecialInvariants(delta)\r\n ) {\r\n console.error(\r\n `Broken invariant for \"${type}\" delta, element \"${id}\", delta:`,\r\n delta,\r\n );\r\n throw new Error(`ElementsDelta invariant broken for element \"${id}\".`);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Calculates the `Delta`s between the previous and next set of elements.\r\n *\r\n * @param prevElements - Map representing the previous state of elements.\r\n * @param nextElements - Map representing the next state of elements.\r\n *\r\n * @returns `ElementsDelta` instance representing the `Delta` changes between the two sets of elements.\r\n */\r\n public static calculate<T extends OrderedExcalidrawElement>(\r\n prevElements: Map<string, T>,\r\n nextElements: Map<string, T>,\r\n ): ElementsDelta {\r\n if (prevElements === nextElements) {\r\n return ElementsDelta.empty();\r\n }\r\n\r\n const added: Record<string, Delta<ElementPartial>> = {};\r\n const removed: Record<string, Delta<ElementPartial>> = {};\r\n const updated: Record<string, Delta<ElementPartial>> = {};\r\n\r\n // this might be needed only in same edge cases, like during collab, when `isDeleted` elements get removed or when we (un)intentionally remove the elements\r\n for (const prevElement of prevElements.values()) {\r\n const nextElement = nextElements.get(prevElement.id);\r\n\r\n if (!nextElement) {\r\n const deleted = { ...prevElement } as ElementPartial;\r\n\r\n const inserted = {\r\n isDeleted: true,\r\n version: prevElement.version + 1,\r\n versionNonce: randomInteger(),\r\n } as ElementPartial;\r\n\r\n const delta = Delta.create(\r\n deleted,\r\n inserted,\r\n ElementsDelta.stripIrrelevantProps,\r\n );\r\n\r\n if (!prevElement.isDeleted) {\r\n removed[prevElement.id] = delta;\r\n } else {\r\n updated[prevElement.id] = delta;\r\n }\r\n }\r\n }\r\n\r\n for (const nextElement of nextElements.values()) {\r\n const prevElement = prevElements.get(nextElement.id);\r\n\r\n if (!prevElement) {\r\n const deleted = {\r\n isDeleted: true,\r\n version: nextElement.version - 1,\r\n versionNonce: randomInteger(),\r\n } as ElementPartial;\r\n\r\n const inserted = {\r\n ...nextElement,\r\n } as ElementPartial;\r\n\r\n const delta = Delta.create(\r\n deleted,\r\n inserted,\r\n ElementsDelta.stripIrrelevantProps,\r\n );\r\n\r\n // ignore updates which would \"delete\" already deleted element\r\n if (!nextElement.isDeleted) {\r\n added[nextElement.id] = delta;\r\n } else {\r\n updated[nextElement.id] = delta;\r\n }\r\n\r\n continue;\r\n }\r\n\r\n if (prevElement.versionNonce !== nextElement.versionNonce) {\r\n const delta = Delta.calculate<ElementPartial>(\r\n prevElement,\r\n nextElement,\r\n ElementsDelta.stripIrrelevantProps,\r\n ElementsDelta.postProcess,\r\n );\r\n\r\n if (\r\n // making sure we don't get here some non-boolean values (i.e. undefined, null, etc.)\r\n typeof prevElement.isDeleted === \"boolean\" &&\r\n typeof nextElement.isDeleted === \"boolean\" &&\r\n prevElement.isDeleted !== nextElement.isDeleted\r\n ) {\r\n // notice that other props could have been updated as well\r\n if (prevElement.isDeleted && !nextElement.isDeleted) {\r\n added[nextElement.id] = delta;\r\n } else {\r\n removed[nextElement.id] = delta;\r\n }\r\n\r\n continue;\r\n }\r\n\r\n updated[nextElement.id] = delta;\r\n }\r\n }\r\n\r\n return ElementsDelta.create(added, removed, updated);\r\n }\r\n\r\n public static empty() {\r\n return ElementsDelta.create({}, {}, {});\r\n }\r\n\r\n public inverse(): ElementsDelta {\r\n const inverseInternal = (deltas: Record<string, Delta<ElementPartial>>) => {\r\n const inversedDeltas: Record<string, Delta<ElementPartial>> = {};\r\n\r\n for (const [id, { inserted, deleted }] of Object.entries(deltas)) {\r\n inversedDeltas[id] = Delta.create({ ...inserted }, { ...deleted });\r\n }\r\n\r\n return inversedDeltas;\r\n };\r\n\r\n const added = inverseInternal(this.added);\r\n const removed = inverseInternal(this.removed);\r\n const updated = inverseInternal(this.updated);\r\n\r\n // notice we inverse removed with added not to break the invariants\r\n return ElementsDelta.create(removed, added, updated);\r\n }\r\n\r\n public isEmpty(): boolean {\r\n return (\r\n Object.keys(this.added).length === 0 &&\r\n Object.keys(this.removed).length === 0 &&\r\n Object.keys(this.updated).length === 0\r\n );\r\n }\r\n\r\n /**\r\n * Update delta/s based on the existing elements.\r\n *\r\n * @param nextElements current elements\r\n * @param modifierOptions defines which of the delta (`deleted` or `inserted`) will be updated\r\n * @returns new instance with modified delta/s\r\n */\r\n public applyLatestChanges(\r\n prevElements: SceneElementsMap,\r\n nextElements: SceneElementsMap,\r\n modifierOptions?: \"deleted\" | \"inserted\",\r\n ): ElementsDelta {\r\n const modifier =\r\n (\r\n prevElement: OrderedExcalidrawElement | undefined,\r\n nextElement: OrderedExcalidrawElement | undefined,\r\n ) =>\r\n (partial: ElementPartial, partialType: \"deleted\" | \"inserted\") => {\r\n let element: OrderedExcalidrawElement | undefined;\r\n\r\n switch (partialType) {\r\n case \"deleted\":\r\n element = prevElement;\r\n break;\r\n case \"inserted\":\r\n element = nextElement;\r\n break;\r\n }\r\n\r\n // the element wasn't found -> don't update the partial\r\n if (!element) {\r\n console.error(\r\n `Element not found when trying to apply latest changes`,\r\n );\r\n return partial;\r\n }\r\n\r\n const latestPartial: { [key: string]: unknown } = {};\r\n\r\n for (const key of Object.keys(partial) as Array<keyof typeof partial>) {\r\n // do not update following props:\r\n // - `boundElements`, as it is a reference value which is postprocessed to contain only deleted/inserted keys\r\n switch (key) {\r\n case \"boundElements\":\r\n latestPartial[key] = partial[key];\r\n break;\r\n default:\r\n latestPartial[key] = element[key];\r\n }\r\n }\r\n\r\n return latestPartial;\r\n };\r\n\r\n const applyLatestChangesInternal = (\r\n deltas: Record<string, Delta<ElementPartial>>,\r\n ) => {\r\n const modifiedDeltas: Record<string, Delta<ElementPartial>> = {};\r\n\r\n for (const [id, delta] of Object.entries(deltas)) {\r\n const prevElement = prevElements.get(id);\r\n const nextElement = nextElements.get(id);\r\n\r\n let latestDelta: Delta<ElementPartial> | null = null;\r\n\r\n if (prevElement || nextElement) {\r\n latestDelta = Delta.create(\r\n delta.deleted,\r\n delta.inserted,\r\n modifier(prevElement, nextElement),\r\n modifierOptions,\r\n );\r\n } else {\r\n latestDelta = delta;\r\n }\r\n\r\n // it might happen that after applying latest changes the delta itself does not contain any changes\r\n if (Delta.isInnerDifferent(latestDelta.deleted, latestDelta.inserted)) {\r\n modifiedDeltas[id] = latestDelta;\r\n }\r\n }\r\n\r\n return modifiedDeltas;\r\n };\r\n\r\n const added = applyLatestChangesInternal(this.added);\r\n const removed = applyLatestChangesInternal(this.removed);\r\n const updated = applyLatestChangesInternal(this.updated);\r\n\r\n return ElementsDelta.create(added, removed, updated, {\r\n shouldRedistribute: true, // redistribute the deltas as `isDeleted` could have been updated\r\n });\r\n }\r\n\r\n public applyTo(\r\n elements: SceneElementsMap,\r\n snapshot: StoreSnapshot[\"elements\"] = StoreSnapshot.empty().elements,\r\n options?: ApplyToOptions,\r\n ): [SceneElementsMap, boolean] {\r\n let nextElements = new Map(elements) as SceneElementsMap;\r\n let changedElements: Map<string, OrderedExcalidrawElement>;\r\n\r\n const flags: ApplyToFlags = {\r\n containsVisibleDifference: false,\r\n containsZindexDifference: false,\r\n applyDirection: undefined,\r\n };\r\n\r\n // mimic a transaction by applying deltas into `nextElements` (always new instance, no mutation)\r\n try {\r\n const applyDeltas = ElementsDelta.createApplier(\r\n elements,\r\n nextElements,\r\n snapshot,\r\n flags,\r\n options,\r\n );\r\n\r\n const addedElements = applyDeltas(this.added);\r\n const removedElements = applyDeltas(this.removed);\r\n const updatedElements = applyDeltas(this.updated);\r\n\r\n const affectedElements = this.resolveConflicts(\r\n elements,\r\n nextElements,\r\n flags.applyDirection,\r\n );\r\n\r\n // TODO: #7348 validate elements semantically and syntactically the changed elements, in case they would result data integrity issues\r\n changedElements = new Map([\r\n ...addedElements,\r\n ...removedElements,\r\n ...updatedElements,\r\n ...affectedElements,\r\n ]);\r\n } catch (e) {\r\n console.error(`Couldn't apply elements delta`, e);\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw e;\r\n }\r\n\r\n // should not really happen, but just in case we cannot apply deltas, let's return the previous elements with visible change set to `true`\r\n // even though there is obviously no visible change, returning `false` could be dangerous, as i.e.:\r\n // in the worst case, it could lead into iterating through the whole stack with no possibility to redo\r\n // instead, the worst case when returning `true` is an empty undo / redo\r\n return [elements, true];\r\n }\r\n\r\n try {\r\n // the following reorder performs mutations, but only on new instances of changed elements,\r\n // unless something goes really bad and it fallbacks to fixing all invalid indices\r\n nextElements = ElementsDelta.reorderElements(\r\n nextElements,\r\n changedElements,\r\n flags,\r\n );\r\n\r\n ElementsDelta.redrawElements(nextElements, changedElements);\r\n } catch (e) {\r\n console.error(\r\n `Couldn't mutate elements after applying elements change`,\r\n e,\r\n );\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw e;\r\n }\r\n } finally {\r\n return [nextElements, flags.containsVisibleDifference];\r\n }\r\n }\r\n\r\n public squash(delta: ElementsDelta): this {\r\n if (delta.isEmpty()) {\r\n return this;\r\n }\r\n\r\n const { added, removed, updated } = delta;\r\n\r\n const mergeBoundElements = (\r\n prevDelta: Delta<ElementPartial>,\r\n nextDelta: Delta<ElementPartial>,\r\n ) => {\r\n const mergedDeletedBoundElements =\r\n Delta.mergeArrays(\r\n prevDelta.deleted.boundElements ?? [],\r\n nextDelta.deleted.boundElements ?? [],\r\n undefined,\r\n (x) => x.id,\r\n ) ?? [];\r\n\r\n const mergedInsertedBoundElements =\r\n Delta.mergeArrays(\r\n prevDelta.inserted.boundElements ?? [],\r\n nextDelta.inserted.boundElements ?? [],\r\n undefined,\r\n (x) => x.id,\r\n ) ?? [];\r\n\r\n if (\r\n !mergedDeletedBoundElements.length &&\r\n !mergedInsertedBoundElements.length\r\n ) {\r\n return;\r\n }\r\n\r\n return Delta.create(\r\n {\r\n boundElements: mergedDeletedBoundElements,\r\n },\r\n {\r\n boundElements: mergedInsertedBoundElements,\r\n },\r\n );\r\n };\r\n\r\n for (const [id, nextDelta] of Object.entries(added)) {\r\n const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];\r\n\r\n if (!prevDelta) {\r\n this.added[id] = nextDelta;\r\n } else {\r\n const mergedDelta = mergeBoundElements(prevDelta, nextDelta);\r\n delete this.removed[id];\r\n delete this.updated[id];\r\n\r\n this.added[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);\r\n }\r\n }\r\n\r\n for (const [id, nextDelta] of Object.entries(removed)) {\r\n const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];\r\n\r\n if (!prevDelta) {\r\n this.removed[id] = nextDelta;\r\n } else {\r\n const mergedDelta = mergeBoundElements(prevDelta, nextDelta);\r\n delete this.added[id];\r\n delete this.updated[id];\r\n\r\n this.removed[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);\r\n }\r\n }\r\n\r\n for (const [id, nextDelta] of Object.entries(updated)) {\r\n const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];\r\n\r\n if (!prevDelta) {\r\n this.updated[id] = nextDelta;\r\n } else {\r\n const mergedDelta = mergeBoundElements(prevDelta, nextDelta);\r\n const updatedDelta = Delta.merge(prevDelta, nextDelta, mergedDelta);\r\n\r\n if (prevDelta === this.added[id]) {\r\n this.added[id] = updatedDelta;\r\n } else if (prevDelta === this.removed[id]) {\r\n this.removed[id] = updatedDelta;\r\n } else {\r\n this.updated[id] = updatedDelta;\r\n }\r\n }\r\n }\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n ElementsDelta.validate(this, \"added\", ElementsDelta.satisfiesAddition);\r\n ElementsDelta.validate(this, \"removed\", ElementsDelta.satisfiesRemoval);\r\n ElementsDelta.validate(this, \"updated\", ElementsDelta.satisfiesUpdate);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n private static createApplier =\r\n (\r\n prevElements: SceneElementsMap,\r\n nextElements: SceneElementsMap,\r\n snapshot: StoreSnapshot[\"elements\"],\r\n flags: ApplyToFlags,\r\n options?: ApplyToOptions,\r\n ) =>\r\n (deltas: Record<string, Delta<ElementPartial>>) => {\r\n const getElement = ElementsDelta.createGetter(\r\n nextElements,\r\n snapshot,\r\n flags,\r\n );\r\n\r\n return Object.entries(deltas).reduce((acc, [id, delta]) => {\r\n const element = getElement(id, delta.inserted);\r\n\r\n if (element) {\r\n const nextElement = ElementsDelta.applyDelta(\r\n element,\r\n delta,\r\n flags,\r\n options,\r\n );\r\n\r\n nextElements.set(nextElement.id, nextElement);\r\n acc.set(nextElement.id, nextElement);\r\n\r\n if (!flags.applyDirection) {\r\n const prevElement = prevElements.get(id);\r\n\r\n if (prevElement) {\r\n flags.applyDirection =\r\n prevElement.version > nextElement.version\r\n ? \"backward\"\r\n : \"forward\";\r\n }\r\n }\r\n }\r\n\r\n return acc;\r\n }, new Map<string, OrderedExcalidrawElement>());\r\n };\r\n\r\n private static createGetter =\r\n (\r\n elements: SceneElementsMap,\r\n snapshot: StoreSnapshot[\"elements\"],\r\n flags: ApplyToFlags,\r\n ) =>\r\n (id: string, partial: ElementPartial) => {\r\n let element = elements.get(id);\r\n\r\n if (!element) {\r\n // always fallback to the local snapshot, in cases when we cannot find the element in the elements array\r\n element = snapshot.get(id);\r\n\r\n if (element) {\r\n // as the element was brought from the snapshot, it automatically results in a possible zindex difference\r\n flags.containsZindexDifference = true;\r\n\r\n // as the element was force deleted, we need to check if adding it back results in a visible change\r\n if (!partial.isDeleted || (partial.isDeleted && !element.isDeleted)) {\r\n flags.containsVisibleDifference = true;\r\n }\r\n } else {\r\n // not in elements, not in snapshot? element might have been added remotely!\r\n element = newElementWith(\r\n { id, version: 1 } as OrderedExcalidrawElement,\r\n {\r\n ...partial,\r\n },\r\n );\r\n }\r\n }\r\n\r\n return element;\r\n };\r\n\r\n private static applyDelta(\r\n element: OrderedExcalidrawElement,\r\n delta: Delta<ElementPartial>,\r\n flags: ApplyToFlags,\r\n options?: ApplyToOptions,\r\n ) {\r\n const directlyApplicablePartial: Mutable<ElementPartial> = {};\r\n\r\n // some properties are not directly applicable, such as:\r\n // - boundElements which contains only diff)\r\n // - version & versionNonce, if we don't want to return to previous versions\r\n for (const key of Object.keys(delta.inserted) as Array<\r\n keyof typeof delta.inserted\r\n >) {\r\n if (key === \"boundElements\") {\r\n continue;\r\n }\r\n\r\n if (options?.excludedProperties?.has(key)) {\r\n continue;\r\n }\r\n\r\n const value = delta.inserted[key];\r\n Reflect.set(directlyApplicablePartial, key, value);\r\n }\r\n\r\n if (\r\n delta.deleted.boundElements?.length ||\r\n delta.inserted.boundElements?.length\r\n ) {\r\n const mergedBoundElements = Delta.mergeArrays(\r\n element.boundElements,\r\n delta.inserted.boundElements,\r\n delta.deleted.boundElements,\r\n (x) => x.id,\r\n );\r\n\r\n Object.assign(directlyApplicablePartial, {\r\n boundElements: mergedBoundElements,\r\n });\r\n }\r\n\r\n if (!flags.containsVisibleDifference) {\r\n // strip away fractional index, as even if it would be different, it doesn't have to result in visible change\r\n const { index, ...rest } = directlyApplicablePartial;\r\n const containsVisibleDifference = ElementsDelta.checkForVisibleDifference(\r\n element,\r\n rest,\r\n );\r\n\r\n flags.containsVisibleDifference = containsVisibleDifference;\r\n }\r\n\r\n if (!flags.containsZindexDifference) {\r\n flags.containsZindexDifference =\r\n delta.deleted.index !== delta.inserted.index;\r\n }\r\n\r\n return newElementWith(element, directlyApplicablePartial, true);\r\n }\r\n\r\n /**\r\n * Check for visible changes regardless of whether they were removed, added or updated.\r\n */\r\n private static checkForVisibleDifference(\r\n element: OrderedExcalidrawElement,\r\n partial: ElementPartial,\r\n ) {\r\n if (element.isDeleted && partial.isDeleted !== false) {\r\n // when it's deleted and partial is not false, it cannot end up with a visible change\r\n return false;\r\n }\r\n\r\n if (element.isDeleted && partial.isDeleted === false) {\r\n // when we add an element, it results in a visible change\r\n return true;\r\n }\r\n\r\n if (element.isDeleted === false && partial.isDeleted) {\r\n // when we remove an element, it results in a visible change\r\n return true;\r\n }\r\n\r\n // check for any difference on a visible element\r\n return Delta.isRightDifferent(element, partial);\r\n }\r\n\r\n /**\r\n * Resolves conflicts for all previously added, removed and updated elements.\r\n * Updates the previous deltas with all the changes after conflict resolution.\r\n *\r\n * // TODO: revisit since some bound arrows seem to be often redrawn incorrectly\r\n *\r\n * @returns all elements affected by the conflict resolution\r\n */\r\n private resolveConflicts(\r\n prevElements: SceneElementsMap,\r\n nextElements: SceneElementsMap,\r\n applyDirection: \"forward\" | \"backward\" = \"forward\",\r\n ) {\r\n const nextAffectedElements = new Map<string, OrderedExcalidrawElement>();\r\n const updater = (\r\n element: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => {\r\n const nextElement = nextElements.get(element.id); // only ever modify next element!\r\n if (!nextElement) {\r\n return;\r\n }\r\n\r\n const prevElement = prevElements.get(element.id);\r\n const nextVersion =\r\n applyDirection === \"forward\"\r\n ? nextElement.version + 1\r\n : nextElement.version - 1;\r\n\r\n const elementUpdates = updates as ElementUpdate<OrderedExcalidrawElement>;\r\n\r\n let affectedElement: OrderedExcalidrawElement;\r\n\r\n if (prevElement === nextElement) {\r\n // create the new element instance in case we didn't modify the element yet\r\n // so that we won't end up in an incosistent state in case we would fail in the middle of mutations\r\n affectedElement = newElementWith(\r\n nextElement,\r\n {\r\n ...elementUpdates,\r\n version: nextVersion,\r\n },\r\n true,\r\n );\r\n } else {\r\n affectedElement = mutateElement(nextElement, nextElements, {\r\n ...elementUpdates,\r\n // don't modify the version further, if it's already different\r\n version:\r\n prevElement?.version !== nextElement.version\r\n ? nextElement.version\r\n : nextVersion,\r\n });\r\n }\r\n\r\n nextAffectedElements.set(affectedElement.id, affectedElement);\r\n nextElements.set(affectedElement.id, affectedElement);\r\n };\r\n\r\n // removed delta is affecting the bindings always, as all the affected elements of the removed elements need to be unbound\r\n for (const id of Object.keys(this.removed)) {\r\n ElementsDelta.unbindAffected(prevElements, nextElements, id, updater);\r\n }\r\n\r\n // added delta is affecting the bindings always, all the affected elements of the added elements need to be rebound\r\n for (const id of Object.keys(this.added)) {\r\n ElementsDelta.rebindAffected(prevElements, nextElements, id, updater);\r\n }\r\n\r\n // updated delta is affecting the binding only in case it contains changed binding or bindable property\r\n for (const [id] of Array.from(Object.entries(this.updated)).filter(\r\n ([_, delta]) =>\r\n Object.keys({ ...delta.deleted, ...delta.inserted }).find((prop) =>\r\n bindingProperties.has(prop as BindingProp | BindableProp),\r\n ),\r\n )) {\r\n const updatedElement = nextElements.get(id);\r\n if (!updatedElement || updatedElement.isDeleted) {\r\n // skip fixing bindings for updates on deleted elements\r\n continue;\r\n }\r\n\r\n ElementsDelta.rebindAffected(prevElements, nextElements, id, updater);\r\n }\r\n\r\n // filter only previous elements, which were now affected\r\n const prevAffectedElements = new Map(\r\n Array.from(prevElements).filter(([id]) => nextAffectedElements.has(id)),\r\n );\r\n\r\n // calculate complete deltas for affected elements, and squash them back to the current deltas\r\n this.squash(\r\n // technically we could do better here if perf. would become an issue\r\n ElementsDelta.calculate(prevAffectedElements, nextAffectedElements),\r\n );\r\n\r\n return nextAffectedElements;\r\n }\r\n\r\n /**\r\n * Non deleted affected elements of removed elements (before and after applying delta),\r\n * should be unbound ~ bindings should not point from non deleted into the deleted element/s.\r\n */\r\n private static unbindAffected(\r\n prevElements: SceneElementsMap,\r\n nextElements: SceneElementsMap,\r\n id: string,\r\n updater: (\r\n element: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => void,\r\n ) {\r\n // the instance could have been updated, so make sure we are passing the latest element to each function below\r\n const prevElement = () => prevElements.get(id); // element before removal\r\n const nextElement = () => nextElements.get(id); // element after removal\r\n\r\n BoundElement.unbindAffected(nextElements, prevElement(), updater);\r\n BoundElement.unbindAffected(nextElements, nextElement(), updater);\r\n\r\n BindableElement.unbindAffected(nextElements, prevElement(), updater);\r\n BindableElement.unbindAffected(nextElements, nextElement(), updater);\r\n }\r\n\r\n /**\r\n * Non deleted affected elements of added or updated element/s (before and after applying delta),\r\n * should be rebound (if possible) with the current element ~ bindings should be bidirectional.\r\n */\r\n private static rebindAffected(\r\n prevElements: SceneElementsMap,\r\n nextElements: SceneElementsMap,\r\n id: string,\r\n updater: (\r\n element: ExcalidrawElement,\r\n updates: ElementUpdate<ExcalidrawElement>,\r\n ) => void,\r\n ) {\r\n // the instance could have been updated, so make sure we are passing the latest element to each function below\r\n const prevElement = () => prevElements.get(id); // element before addition / update\r\n const nextElement = () => nextElements.get(id); // element after addition / update\r\n\r\n BoundElement.unbindAffected(nextElements, prevElement(), updater);\r\n BoundElement.rebindAffected(nextElements, nextElement(), updater);\r\n\r\n BindableElement.unbindAffected(\r\n nextElements,\r\n prevElement(),\r\n (element, updates) => {\r\n // we cannot rebind arrows with bindable element so we don't unbind them at all during rebind (we still need to unbind them on removal)\r\n // TODO: #7348 add startBinding / endBinding to the `BoundElement` context so that we could rebind arrows and remove this condition\r\n if (isTextElement(element)) {\r\n updater(element, updates);\r\n }\r\n },\r\n );\r\n BindableElement.rebindAffected(nextElements, nextElement(), updater);\r\n }\r\n\r\n public static redrawElements(\r\n nextElements: SceneElementsMap,\r\n changedElements: Map<string, OrderedExcalidrawElement>,\r\n ) {\r\n try {\r\n // we don't have an up-to-date scene, as we can be just in the middle of applying history entry\r\n // we also don't have a scene on the server\r\n // so we are creating a temp scene just to query and mutate elements\r\n const tempScene = new Scene(nextElements, { skipValidation: true });\r\n\r\n ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);\r\n\r\n // needs ordered nextElements to avoid z-index binding issues\r\n ElementsDelta.redrawBoundArrows(tempScene, changedElements);\r\n } catch (e) {\r\n console.error(`Couldn't redraw elements`, e);\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw e;\r\n }\r\n } finally {\r\n return nextElements;\r\n }\r\n }\r\n\r\n private static redrawTextBoundingBoxes(\r\n scene: Scene,\r\n changed: Map<string, OrderedExcalidrawElement>,\r\n ) {\r\n const elements = scene.getNonDeletedElementsMap();\r\n const boxesToRedraw = new Map<\r\n string,\r\n { container: OrderedExcalidrawElement; boundText: ExcalidrawTextElement }\r\n >();\r\n\r\n for (const element of changed.values()) {\r\n if (isBoundToContainer(element)) {\r\n const { containerId } = element as ExcalidrawTextElement;\r\n const container = containerId ? elements.get(containerId) : undefined;\r\n\r\n if (container) {\r\n boxesToRedraw.set(container.id, {\r\n container,\r\n boundText: element as ExcalidrawTextElement,\r\n });\r\n }\r\n }\r\n\r\n if (hasBoundTextElement(element)) {\r\n const boundTextElementId = getBoundTextElementId(element);\r\n const boundText = boundTextElementId\r\n ? elements.get(boundTextElementId)\r\n : undefined;\r\n\r\n if (boundText) {\r\n boxesToRedraw.set(element.id, {\r\n container: element,\r\n boundText: boundText as ExcalidrawTextElement,\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (const { container, boundText } of boxesToRedraw.values()) {\r\n if (container.isDeleted || boundText.isDeleted) {\r\n // skip redraw if one of them is deleted, as it would not result in a meaningful redraw\r\n continue;\r\n }\r\n\r\n redrawTextBoundingBox(boundText, container, scene);\r\n }\r\n }\r\n\r\n private static redrawBoundArrows(\r\n scene: Scene,\r\n changed: Map<string, OrderedExcalidrawElement>,\r\n ) {\r\n for (const element of changed.values()) {\r\n if (!element.isDeleted && isBindableElement(element)) {\r\n // TODO: with precise bindings this is quite expensive, so consider optimisation so it's only triggered when the arrow does not intersect (imprecise) element bounds\r\n updateBoundElements(element, scene, {\r\n changedElements: changed,\r\n });\r\n }\r\n }\r\n }\r\n\r\n private static reorderElements(\r\n elements: SceneElementsMap,\r\n changed: Map<string, OrderedExcalidrawElement>,\r\n flags: {\r\n containsVisibleDifference: boolean;\r\n containsZindexDifference: boolean;\r\n },\r\n ) {\r\n if (!flags.containsZindexDifference) {\r\n return elements;\r\n }\r\n\r\n const unordered = Array.from(elements.values());\r\n const ordered = orderByFractionalIndex([...unordered]);\r\n const moved = Delta.getRightDifferences(unordered, ordered, true).reduce(\r\n (acc, arrayIndex) => {\r\n const candidate = unordered[Number(arrayIndex)];\r\n if (candidate && changed.has(candidate.id)) {\r\n acc.set(candidate.id, candidate);\r\n }\r\n\r\n return acc;\r\n },\r\n new Map(),\r\n );\r\n\r\n if (!flags.containsVisibleDifference && moved.size) {\r\n // we found a difference in order!\r\n flags.containsVisibleDifference = true;\r\n }\r\n\r\n // synchronize all elements that were actually moved\r\n // could fallback to synchronizing all invalid indices\r\n return arrayToMap(syncMovedIndices(ordered, moved)) as typeof elements;\r\n }\r\n\r\n /**\r\n * It is necessary to post process the partials in case of reference values,\r\n * for which we need to calculate the real diff between `deleted` and `inserted`.\r\n */\r\n private static postProcess(\r\n deleted: ElementPartial,\r\n inserted: ElementPartial,\r\n ): [ElementPartial, ElementPartial] {\r\n try {\r\n Delta.diffArrays(deleted, inserted, \"boundElements\", (x) => x.id);\r\n\r\n // don't diff the points as:\r\n // - we can't ensure the multiplayer order consistency without fractional index on each point\r\n // - we prefer to not merge the points, as it might just lead to unexpected / incosistent results\r\n const deletedPoints =\r\n (\r\n deleted as ElementPartial<\r\n ExcalidrawFreeDrawElement | ExcalidrawLinearElement\r\n >\r\n ).points ?? [];\r\n\r\n const insertedPoints =\r\n (\r\n inserted as ElementPartial<\r\n ExcalidrawFreeDrawElement | ExcalidrawLinearElement\r\n >\r\n ).points ?? [];\r\n\r\n if (!Delta.isDifferent(deletedPoints, insertedPoints)) {\r\n // delete the points from delta if there is no difference, otherwise leave them as they were captured due to consistency\r\n Reflect.deleteProperty(deleted, \"points\");\r\n Reflect.deleteProperty(inserted, \"points\");\r\n }\r\n } catch (e) {\r\n // if postprocessing fails, it does not make sense to bubble up, but let's make sure we know about it\r\n console.error(`Couldn't postprocess elements delta.`);\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw e;\r\n }\r\n } finally {\r\n return [deleted, inserted];\r\n }\r\n }\r\n\r\n private static stripIrrelevantProps(\r\n partial: Partial<OrderedExcalidrawElement>,\r\n ): ElementPartial {\r\n const { id, updated, ...strippedPartial } = partial;\r\n\r\n return strippedPartial;\r\n }\r\n}\r\n", "import {\r\n assertNever,\r\n COLOR_PALETTE,\r\n isDevEnv,\r\n isTestEnv,\r\n randomId,\r\n Emitter,\r\n toIterable,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type App from \"@excalidraw-modify/excalidraw/components/App\";\r\n\r\nimport type { DTO, ValueOf } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport type { AppState, ObservedAppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { deepCopyElement } from \"./duplicate\";\r\nimport { newElementWith } from \"./mutateElement\";\r\n\r\nimport { ElementsDelta, AppStateDelta, Delta } from \"./delta\";\r\n\r\nimport {\r\n syncInvalidIndicesImmutable,\r\n hashElementsVersion,\r\n hashString,\r\n isInitializedImageElement,\r\n isImageElement,\r\n} from \"./index\";\r\n\r\nimport type { ApplyToOptions } from \"./delta\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n OrderedExcalidrawElement,\r\n SceneElementsMap,\r\n} from \"./types\";\r\n\r\nexport const CaptureUpdateAction = {\r\n /**\r\n * Immediately undoable.\r\n *\r\n * Use for updates which should be captured.\r\n * Should be used for most of the local updates, except ephemerals such as dragging or resizing.\r\n *\r\n * These updates will _immediately_ make it to the local undo / redo stacks.\r\n */\r\n IMMEDIATELY: \"IMMEDIATELY\",\r\n /**\r\n * Never undoable.\r\n *\r\n * Use for updates which should never be recorded, such as remote updates\r\n * or scene initialization.\r\n *\r\n * These updates will _never_ make it to the local undo / redo stacks.\r\n */\r\n NEVER: \"NEVER\",\r\n /**\r\n * Eventually undoable.\r\n *\r\n * Use for updates which should not be captured immediately - likely\r\n * exceptions which are part of some async multi-step process. Otherwise, all\r\n * such updates would end up being captured with the next\r\n * `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene`\r\n * or internally by the editor.\r\n *\r\n * These updates will _eventually_ make it to the local undo / redo stacks.\r\n */\r\n EVENTUALLY: \"EVENTUALLY\",\r\n} as const;\r\n\r\nexport type CaptureUpdateActionType = ValueOf<typeof CaptureUpdateAction>;\r\n\r\ntype MicroActionsQueue = (() => void)[];\r\n\r\n/**\r\n * Store which captures the observed changes and emits them as `StoreIncrement` events.\r\n */\r\nexport class Store {\r\n // for internal use by history\r\n public readonly onDurableIncrementEmitter = new Emitter<[DurableIncrement]>();\r\n // for public use as part of onIncrement API\r\n public readonly onStoreIncrementEmitter = new Emitter<\r\n [DurableIncrement | EphemeralIncrement]\r\n >();\r\n\r\n private scheduledMacroActions: Set<CaptureUpdateActionType> = new Set();\r\n private scheduledMicroActions: MicroActionsQueue = [];\r\n\r\n private _snapshot = StoreSnapshot.empty();\r\n\r\n public get snapshot() {\r\n return this._snapshot;\r\n }\r\n\r\n public set snapshot(snapshot: StoreSnapshot) {\r\n this._snapshot = snapshot;\r\n }\r\n\r\n constructor(private readonly app: App) {}\r\n\r\n public scheduleAction(action: CaptureUpdateActionType) {\r\n this.scheduledMacroActions.add(action);\r\n this.satisfiesScheduledActionsInvariant();\r\n }\r\n\r\n /**\r\n * Use to schedule a delta calculation, which will consquentially be emitted as `DurableStoreIncrement` and pushed in the undo stack.\r\n */\r\n // TODO: Suspicious that this is called so many places. Seems error-prone.\r\n public scheduleCapture() {\r\n this.scheduleAction(CaptureUpdateAction.IMMEDIATELY);\r\n }\r\n\r\n /**\r\n * Schedule special \"micro\" actions, to-be executed before the next commit, before it executes a scheduled \"macro\" action.\r\n */\r\n public scheduleMicroAction(\r\n params:\r\n | {\r\n action: CaptureUpdateActionType;\r\n elements: readonly ExcalidrawElement[] | undefined;\r\n appState: AppState | ObservedAppState | undefined;\r\n }\r\n | {\r\n action: typeof CaptureUpdateAction.IMMEDIATELY;\r\n change: StoreChange;\r\n delta: StoreDelta;\r\n }\r\n | {\r\n action:\r\n | typeof CaptureUpdateAction.NEVER\r\n | typeof CaptureUpdateAction.EVENTUALLY;\r\n change: StoreChange;\r\n },\r\n ) {\r\n const { action } = params;\r\n\r\n let change: StoreChange;\r\n\r\n if (\"change\" in params) {\r\n change = params.change;\r\n } else {\r\n // immediately create an immutable change of the scheduled updates,\r\n // compared to the current state, so that they won't mutate later on during batching\r\n // also, we have to compare against the current state,\r\n // as comparing against the snapshot might include yet uncomitted changes (i.e. async freedraw / text / image, etc.)\r\n const currentSnapshot = StoreSnapshot.create(\r\n this.app.scene.getElementsMapIncludingDeleted(),\r\n this.app.state,\r\n );\r\n\r\n const scheduledSnapshot = currentSnapshot.maybeClone(\r\n action,\r\n // let's sync invalid indices first, so that we could detect this change\r\n // also have the synced elements immutable, so that we don't mutate elements,\r\n // that are already in the scene, otherwise we wouldn't see any change\r\n params.elements\r\n ? syncInvalidIndicesImmutable(params.elements)\r\n : undefined,\r\n params.appState,\r\n );\r\n\r\n change = StoreChange.create(currentSnapshot, scheduledSnapshot);\r\n }\r\n\r\n const delta = \"delta\" in params ? params.delta : undefined;\r\n\r\n this.scheduledMicroActions.push(() =>\r\n this.processAction({\r\n action,\r\n change,\r\n delta,\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Performs the incoming `CaptureUpdateAction` and emits the corresponding `StoreIncrement`.\r\n * Emits `DurableStoreIncrement` when action is \"capture\", emits `EphemeralStoreIncrement` otherwise.\r\n *\r\n * @emits StoreIncrement\r\n */\r\n public commit(\r\n elements: SceneElementsMap | undefined,\r\n appState: AppState | ObservedAppState | undefined,\r\n ): void {\r\n // execute all scheduled micro actions first\r\n // similar to microTasks, there can be many\r\n this.flushMicroActions();\r\n\r\n try {\r\n // execute a single scheduled \"macro\" function\r\n // similar to macro tasks, there can be only one within a single commit (loop)\r\n const action = this.getScheduledMacroAction();\r\n this.processAction({ action, elements, appState });\r\n } finally {\r\n this.satisfiesScheduledActionsInvariant();\r\n // defensively reset all scheduled \"macro\" actions, possibly cleans up other runtime garbage\r\n this.scheduledMacroActions = new Set();\r\n }\r\n }\r\n\r\n /**\r\n * Clears the store instance.\r\n */\r\n public clear(): void {\r\n this.snapshot = StoreSnapshot.empty();\r\n this.scheduledMacroActions = new Set();\r\n }\r\n\r\n /**\r\n * Performs delta & change calculation and emits a durable increment.\r\n *\r\n * @emits StoreIncrement.\r\n */\r\n private emitDurableIncrement(\r\n snapshot: StoreSnapshot,\r\n change: StoreChange | undefined = undefined,\r\n delta: StoreDelta | undefined = undefined,\r\n ) {\r\n const prevSnapshot = this.snapshot;\r\n\r\n let storeChange: StoreChange;\r\n let storeDelta: StoreDelta;\r\n\r\n if (change) {\r\n storeChange = change;\r\n } else {\r\n storeChange = StoreChange.create(prevSnapshot, snapshot);\r\n }\r\n\r\n if (delta) {\r\n // we might have the delta already (i.e. when applying history entry), thus we don't need to calculate it again\r\n // using the same instance, since in history we have a check against `HistoryEntry`, so that we don't re-record the same delta again\r\n storeDelta = delta;\r\n } else {\r\n storeDelta = StoreDelta.calculate(prevSnapshot, snapshot);\r\n }\r\n\r\n if (!storeDelta.isEmpty()) {\r\n const increment = new DurableIncrement(storeChange, storeDelta);\r\n\r\n this.onDurableIncrementEmitter.trigger(increment);\r\n this.onStoreIncrementEmitter.trigger(increment);\r\n }\r\n }\r\n\r\n /**\r\n * Performs change calculation and emits an ephemeral increment.\r\n *\r\n * @emits EphemeralStoreIncrement\r\n */\r\n private emitEphemeralIncrement(\r\n snapshot: StoreSnapshot,\r\n change: StoreChange | undefined = undefined,\r\n ) {\r\n let storeChange: StoreChange;\r\n\r\n if (change) {\r\n storeChange = change;\r\n } else {\r\n const prevSnapshot = this.snapshot;\r\n storeChange = StoreChange.create(prevSnapshot, snapshot);\r\n }\r\n\r\n const increment = new EphemeralIncrement(storeChange);\r\n\r\n // Notify listeners with the increment\r\n this.onStoreIncrementEmitter.trigger(increment);\r\n }\r\n\r\n private applyChangeToSnapshot(change: StoreChange) {\r\n const prevSnapshot = this.snapshot;\r\n const nextSnapshot = this.snapshot.applyChange(change);\r\n\r\n if (prevSnapshot === nextSnapshot) {\r\n return null;\r\n }\r\n\r\n return nextSnapshot;\r\n }\r\n\r\n /**\r\n * Clones the snapshot if there are changes detected.\r\n */\r\n private maybeCloneSnapshot(\r\n action: CaptureUpdateActionType,\r\n elements: SceneElementsMap | undefined,\r\n appState: AppState | ObservedAppState | undefined,\r\n ) {\r\n if (!elements && !appState) {\r\n return null;\r\n }\r\n\r\n const prevSnapshot = this.snapshot;\r\n const nextSnapshot = this.snapshot.maybeClone(action, elements, appState);\r\n\r\n if (prevSnapshot === nextSnapshot) {\r\n return null;\r\n }\r\n\r\n return nextSnapshot;\r\n }\r\n\r\n private flushMicroActions() {\r\n for (const microAction of this.scheduledMicroActions) {\r\n try {\r\n microAction();\r\n } catch (error) {\r\n console.error(`Failed to execute scheduled micro action`, error);\r\n }\r\n }\r\n\r\n this.scheduledMicroActions = [];\r\n }\r\n\r\n private processAction(\r\n params:\r\n | {\r\n action: CaptureUpdateActionType;\r\n elements: SceneElementsMap | undefined;\r\n appState: AppState | ObservedAppState | undefined;\r\n }\r\n | {\r\n action: CaptureUpdateActionType;\r\n change: StoreChange;\r\n delta: StoreDelta | undefined;\r\n },\r\n ) {\r\n const { action } = params;\r\n\r\n // perf. optimisation, since \"EVENTUALLY\" does not update the snapshot,\r\n // so if nobody is listening for increments, we don't need to even clone the snapshot\r\n // as it's only needed for `StoreChange` computation inside `EphemeralIncrement`\r\n if (\r\n action === CaptureUpdateAction.EVENTUALLY &&\r\n !this.onStoreIncrementEmitter.subscribers.length\r\n ) {\r\n return;\r\n }\r\n\r\n let nextSnapshot: StoreSnapshot | null;\r\n\r\n if (\"change\" in params) {\r\n nextSnapshot = this.applyChangeToSnapshot(params.change);\r\n } else {\r\n nextSnapshot = this.maybeCloneSnapshot(\r\n action,\r\n params.elements,\r\n params.appState,\r\n );\r\n }\r\n\r\n if (!nextSnapshot) {\r\n // don't continue if there is not change detected\r\n return;\r\n }\r\n\r\n const change = \"change\" in params ? params.change : undefined;\r\n const delta = \"delta\" in params ? params.delta : undefined;\r\n\r\n try {\r\n switch (action) {\r\n // only immediately emits a durable increment\r\n case CaptureUpdateAction.IMMEDIATELY:\r\n this.emitDurableIncrement(nextSnapshot, change, delta);\r\n break;\r\n // both never and eventually emit an ephemeral increment\r\n case CaptureUpdateAction.NEVER:\r\n case CaptureUpdateAction.EVENTUALLY:\r\n this.emitEphemeralIncrement(nextSnapshot, change);\r\n break;\r\n default:\r\n assertNever(action, `Unknown store action`);\r\n }\r\n } finally {\r\n // update the snapshot no-matter what, as it would mess up with the next action\r\n switch (action) {\r\n // both immediately and never update the snapshot, unlike eventually\r\n case CaptureUpdateAction.IMMEDIATELY:\r\n case CaptureUpdateAction.NEVER:\r\n this.snapshot = nextSnapshot;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the scheduled macro action.\r\n */\r\n private getScheduledMacroAction() {\r\n let scheduledAction: CaptureUpdateActionType;\r\n\r\n if (this.scheduledMacroActions.has(CaptureUpdateAction.IMMEDIATELY)) {\r\n // Capture has a precedence over update, since it also performs snapshot update\r\n scheduledAction = CaptureUpdateAction.IMMEDIATELY;\r\n } else if (this.scheduledMacroActions.has(CaptureUpdateAction.NEVER)) {\r\n // Update has a precedence over none, since it also emits an (ephemeral) increment\r\n scheduledAction = CaptureUpdateAction.NEVER;\r\n } else {\r\n // Default is to emit ephemeral increment and don't update the snapshot\r\n scheduledAction = CaptureUpdateAction.EVENTUALLY;\r\n }\r\n\r\n return scheduledAction;\r\n }\r\n\r\n /**\r\n * Ensures that the scheduled actions invariant is satisfied.\r\n */\r\n private satisfiesScheduledActionsInvariant() {\r\n if (\r\n !(\r\n this.scheduledMacroActions.size >= 0 &&\r\n this.scheduledMacroActions.size <=\r\n Object.keys(CaptureUpdateAction).length\r\n )\r\n ) {\r\n const message = `There can be at most three store actions scheduled at the same time, but there are \"${this.scheduledMacroActions.size}\".`;\r\n console.error(message, this.scheduledMacroActions.values());\r\n\r\n if (isTestEnv() || isDevEnv()) {\r\n throw new Error(message);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Repsents a change to the store containing changed elements and appState.\r\n */\r\nexport class StoreChange {\r\n // so figuring out what has changed should ideally be just quick reference checks\r\n // TODO: we might need to have binary files here as well, in order to be drop-in replacement for `onChange`\r\n private constructor(\r\n public readonly elements: Record<string, OrderedExcalidrawElement>,\r\n public readonly appState: Partial<ObservedAppState>,\r\n ) {}\r\n\r\n public static create(\r\n prevSnapshot: StoreSnapshot,\r\n nextSnapshot: StoreSnapshot,\r\n ) {\r\n const changedElements = nextSnapshot.getChangedElements(prevSnapshot);\r\n const changedAppState = nextSnapshot.getChangedAppState(prevSnapshot);\r\n\r\n return new StoreChange(changedElements, changedAppState);\r\n }\r\n}\r\n\r\n/**\r\n * Encpasulates any change to the store (durable or ephemeral).\r\n */\r\nexport abstract class StoreIncrement {\r\n protected constructor(\r\n public readonly type: \"durable\" | \"ephemeral\",\r\n public readonly change: StoreChange,\r\n ) {}\r\n\r\n public static isDurable(\r\n increment: StoreIncrement,\r\n ): increment is DurableIncrement {\r\n return increment.type === \"durable\";\r\n }\r\n\r\n public static isEphemeral(\r\n increment: StoreIncrement,\r\n ): increment is EphemeralIncrement {\r\n return increment.type === \"ephemeral\";\r\n }\r\n}\r\n\r\n/**\r\n * Represents a durable change to the store.\r\n */\r\nexport class DurableIncrement extends StoreIncrement {\r\n constructor(\r\n public readonly change: StoreChange,\r\n public readonly delta: StoreDelta,\r\n ) {\r\n super(\"durable\", change);\r\n }\r\n}\r\n\r\n/**\r\n * Represents an ephemeral change to the store.\r\n */\r\nexport class EphemeralIncrement extends StoreIncrement {\r\n constructor(public readonly change: StoreChange) {\r\n super(\"ephemeral\", change);\r\n }\r\n}\r\n\r\n/**\r\n * Represents a captured delta by the Store.\r\n */\r\nexport class StoreDelta {\r\n protected constructor(\r\n public readonly id: string,\r\n public readonly elements: ElementsDelta,\r\n public readonly appState: AppStateDelta,\r\n ) {}\r\n\r\n /**\r\n * Create a new instance of `StoreDelta`.\r\n */\r\n public static create(\r\n elements: ElementsDelta,\r\n appState: AppStateDelta,\r\n opts: {\r\n id: string;\r\n } = {\r\n id: randomId(),\r\n },\r\n ) {\r\n return new this(opts.id, elements, appState);\r\n }\r\n\r\n /**\r\n * Calculate the delta between the previous and next snapshot.\r\n */\r\n public static calculate(\r\n prevSnapshot: StoreSnapshot,\r\n nextSnapshot: StoreSnapshot,\r\n ) {\r\n const elementsDelta = nextSnapshot.metadata.didElementsChange\r\n ? ElementsDelta.calculate(prevSnapshot.elements, nextSnapshot.elements)\r\n : ElementsDelta.empty();\r\n\r\n const appStateDelta = nextSnapshot.metadata.didAppStateChange\r\n ? AppStateDelta.calculate(prevSnapshot.appState, nextSnapshot.appState)\r\n : AppStateDelta.empty();\r\n\r\n return this.create(elementsDelta, appStateDelta);\r\n }\r\n\r\n /**\r\n * Restore a store delta instance from a DTO.\r\n */\r\n public static restore(storeDeltaDTO: DTO<StoreDelta>) {\r\n const { id, elements, appState } = storeDeltaDTO;\r\n return new this(\r\n id,\r\n ElementsDelta.restore(elements),\r\n AppStateDelta.restore(appState),\r\n );\r\n }\r\n\r\n /**\r\n * Parse and load the delta from the remote payload.\r\n */\r\n public static load({\r\n id,\r\n elements: { added, removed, updated },\r\n appState: { delta: appStateDelta },\r\n }: DTO<StoreDelta>) {\r\n const elements = ElementsDelta.create(added, removed, updated);\r\n const appState = AppStateDelta.create(appStateDelta);\r\n\r\n return new this(id, elements, appState);\r\n }\r\n\r\n /**\r\n * Squash the passed deltas into the aggregated delta instance.\r\n */\r\n public static squash(...deltas: StoreDelta[]) {\r\n const aggregatedDelta = StoreDelta.empty();\r\n\r\n for (const delta of deltas) {\r\n aggregatedDelta.elements.squash(delta.elements);\r\n aggregatedDelta.appState.squash(delta.appState);\r\n }\r\n\r\n return aggregatedDelta;\r\n }\r\n\r\n /**\r\n * Inverse store delta, creates new instance of `StoreDelta`.\r\n */\r\n public static inverse(delta: StoreDelta) {\r\n return this.create(delta.elements.inverse(), delta.appState.inverse());\r\n }\r\n\r\n /**\r\n * Apply the delta to the passed elements and appState, does not modify the snapshot.\r\n */\r\n public static applyTo(\r\n delta: StoreDelta,\r\n elements: SceneElementsMap,\r\n appState: AppState,\r\n options?: ApplyToOptions,\r\n ): [SceneElementsMap, AppState, boolean] {\r\n const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(\r\n elements,\r\n StoreSnapshot.empty().elements,\r\n options,\r\n );\r\n\r\n const [nextAppState, appStateContainsVisibleChange] =\r\n delta.appState.applyTo(appState, nextElements);\r\n\r\n const appliedVisibleChanges =\r\n elementsContainVisibleChange || appStateContainsVisibleChange;\r\n\r\n return [nextElements, nextAppState, appliedVisibleChanges];\r\n }\r\n\r\n /**\r\n * Apply latest (remote) changes to the delta, creates new instance of `StoreDelta`.\r\n */\r\n public static applyLatestChanges(\r\n delta: StoreDelta,\r\n prevElements: SceneElementsMap,\r\n nextElements: SceneElementsMap,\r\n modifierOptions?: \"deleted\" | \"inserted\",\r\n ): StoreDelta {\r\n return this.create(\r\n delta.elements.applyLatestChanges(\r\n prevElements,\r\n nextElements,\r\n modifierOptions,\r\n ),\r\n delta.appState,\r\n {\r\n id: delta.id,\r\n },\r\n );\r\n }\r\n\r\n public static empty() {\r\n return StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());\r\n }\r\n\r\n public isEmpty() {\r\n return this.elements.isEmpty() && this.appState.isEmpty();\r\n }\r\n}\r\n\r\n/**\r\n * Represents a snapshot of the captured or updated changes in the store,\r\n * used for producing deltas and emitting `DurableStoreIncrement`s.\r\n */\r\nexport class StoreSnapshot {\r\n private _lastChangedElementsHash: number = 0;\r\n private _lastChangedAppStateHash: number = 0;\r\n\r\n private constructor(\r\n public readonly elements: SceneElementsMap,\r\n public readonly appState: ObservedAppState,\r\n public readonly metadata: {\r\n didElementsChange: boolean;\r\n didAppStateChange: boolean;\r\n isEmpty?: boolean;\r\n } = {\r\n didElementsChange: false,\r\n didAppStateChange: false,\r\n isEmpty: false,\r\n },\r\n ) {}\r\n\r\n public static create(\r\n elements: SceneElementsMap,\r\n appState: AppState | ObservedAppState,\r\n metadata: {\r\n didElementsChange: boolean;\r\n didAppStateChange: boolean;\r\n } = {\r\n didElementsChange: false,\r\n didAppStateChange: false,\r\n },\r\n ) {\r\n return new StoreSnapshot(\r\n elements,\r\n isObservedAppState(appState) ? appState : getObservedAppState(appState),\r\n metadata,\r\n );\r\n }\r\n\r\n public static empty() {\r\n return new StoreSnapshot(\r\n new Map() as SceneElementsMap,\r\n getDefaultObservedAppState(),\r\n {\r\n didElementsChange: false,\r\n didAppStateChange: false,\r\n isEmpty: true,\r\n },\r\n );\r\n }\r\n\r\n public getChangedElements(prevSnapshot: StoreSnapshot) {\r\n const changedElements: Record<string, OrderedExcalidrawElement> = {};\r\n\r\n for (const prevElement of toIterable(prevSnapshot.elements)) {\r\n const nextElement = this.elements.get(prevElement.id);\r\n\r\n if (!nextElement) {\r\n changedElements[prevElement.id] = newElementWith(prevElement, {\r\n isDeleted: true,\r\n });\r\n }\r\n }\r\n\r\n for (const nextElement of toIterable(this.elements)) {\r\n // Due to the structural clone inside `maybeClone`, we can perform just these reference checks\r\n if (prevSnapshot.elements.get(nextElement.id) !== nextElement) {\r\n changedElements[nextElement.id] = nextElement;\r\n }\r\n }\r\n\r\n return changedElements;\r\n }\r\n\r\n public getChangedAppState(\r\n prevSnapshot: StoreSnapshot,\r\n ): Partial<ObservedAppState> {\r\n return Delta.getRightDifferences(\r\n prevSnapshot.appState,\r\n this.appState,\r\n ).reduce(\r\n (acc, key) =>\r\n Object.assign(acc, {\r\n [key]: this.appState[key as keyof ObservedAppState],\r\n }),\r\n {} as Partial<ObservedAppState>,\r\n );\r\n }\r\n\r\n public isEmpty() {\r\n return this.metadata.isEmpty;\r\n }\r\n\r\n /**\r\n * Apply the change and return a new snapshot instance.\r\n */\r\n public applyChange(change: StoreChange): StoreSnapshot {\r\n const nextElements = new Map(this.elements) as SceneElementsMap;\r\n\r\n for (const [id, changedElement] of Object.entries(change.elements)) {\r\n nextElements.set(id, changedElement);\r\n }\r\n\r\n const nextAppState = getObservedAppState({\r\n ...this.appState,\r\n ...change.appState,\r\n });\r\n\r\n return StoreSnapshot.create(nextElements, nextAppState, {\r\n // by default we assume that change is different from what we have in the snapshot\r\n // so that we trigger the delta calculation and if it isn't different, delta will be empty\r\n didElementsChange: Object.keys(change.elements).length > 0,\r\n didAppStateChange: Object.keys(change.appState).length > 0,\r\n });\r\n }\r\n\r\n /**\r\n * Efficiently clone the existing snapshot, only if we detected changes.\r\n *\r\n * @returns same instance if there are no changes detected, new instance otherwise.\r\n */\r\n public maybeClone(\r\n action: CaptureUpdateActionType,\r\n elements: SceneElementsMap | undefined,\r\n appState: AppState | ObservedAppState | undefined,\r\n ) {\r\n const options = {\r\n shouldCompareHashes: false,\r\n };\r\n\r\n if (action === CaptureUpdateAction.EVENTUALLY) {\r\n // actions that do not update the snapshot immediately, must be additionally checked for changes against the latest hash\r\n // as we are always comparing against the latest snapshot, so they would emit elements or appState as changed on every component update\r\n // instead of just the first time the elements or appState actually changed\r\n options.shouldCompareHashes = true;\r\n }\r\n\r\n const nextElementsSnapshot = this.maybeCreateElementsSnapshot(\r\n elements,\r\n options,\r\n );\r\n const nextAppStateSnapshot = this.maybeCreateAppStateSnapshot(\r\n appState,\r\n options,\r\n );\r\n\r\n let didElementsChange = false;\r\n let didAppStateChange = false;\r\n\r\n if (this.elements !== nextElementsSnapshot) {\r\n didElementsChange = true;\r\n }\r\n\r\n if (this.appState !== nextAppStateSnapshot) {\r\n didAppStateChange = true;\r\n }\r\n\r\n if (!didElementsChange && !didAppStateChange) {\r\n return this;\r\n }\r\n\r\n const snapshot = new StoreSnapshot(\r\n nextElementsSnapshot,\r\n nextAppStateSnapshot,\r\n {\r\n didElementsChange,\r\n didAppStateChange,\r\n },\r\n );\r\n\r\n return snapshot;\r\n }\r\n\r\n private maybeCreateAppStateSnapshot(\r\n appState: AppState | ObservedAppState | undefined,\r\n options: {\r\n shouldCompareHashes: boolean;\r\n } = {\r\n shouldCompareHashes: false,\r\n },\r\n ): ObservedAppState {\r\n if (!appState) {\r\n return this.appState;\r\n }\r\n\r\n // Not watching over everything from the app state, just the relevant props\r\n const nextAppStateSnapshot = !isObservedAppState(appState)\r\n ? getObservedAppState(appState)\r\n : appState;\r\n\r\n const didAppStateChange = this.detectChangedAppState(\r\n nextAppStateSnapshot,\r\n options,\r\n );\r\n\r\n if (!didAppStateChange) {\r\n return this.appState;\r\n }\r\n\r\n return nextAppStateSnapshot;\r\n }\r\n\r\n private maybeCreateElementsSnapshot(\r\n elements: SceneElementsMap | undefined,\r\n options: {\r\n shouldCompareHashes: boolean;\r\n } = {\r\n shouldCompareHashes: false,\r\n },\r\n ): SceneElementsMap {\r\n if (!elements) {\r\n return this.elements;\r\n }\r\n\r\n const changedElements = this.detectChangedElements(elements, options);\r\n\r\n if (!changedElements?.size) {\r\n return this.elements;\r\n }\r\n\r\n const elementsSnapshot = this.createElementsSnapshot(changedElements);\r\n return elementsSnapshot;\r\n }\r\n\r\n private detectChangedAppState(\r\n nextObservedAppState: ObservedAppState,\r\n options: {\r\n shouldCompareHashes: boolean;\r\n } = {\r\n shouldCompareHashes: false,\r\n },\r\n ): boolean | undefined {\r\n if (this.appState === nextObservedAppState) {\r\n return;\r\n }\r\n\r\n const didAppStateChange = Delta.isRightDifferent(\r\n this.appState,\r\n nextObservedAppState,\r\n );\r\n\r\n if (!didAppStateChange) {\r\n return;\r\n }\r\n\r\n const changedAppStateHash = hashString(\r\n JSON.stringify(nextObservedAppState),\r\n );\r\n\r\n if (\r\n options.shouldCompareHashes &&\r\n this._lastChangedAppStateHash === changedAppStateHash\r\n ) {\r\n return;\r\n }\r\n\r\n this._lastChangedAppStateHash = changedAppStateHash;\r\n\r\n return didAppStateChange;\r\n }\r\n\r\n /**\r\n * Detect if there are any changed elements.\r\n */\r\n private detectChangedElements(\r\n nextElements: SceneElementsMap,\r\n options: {\r\n shouldCompareHashes: boolean;\r\n } = {\r\n shouldCompareHashes: false,\r\n },\r\n ): SceneElementsMap | undefined {\r\n if (this.elements === nextElements) {\r\n return;\r\n }\r\n\r\n const changedElements: SceneElementsMap = new Map() as SceneElementsMap;\r\n\r\n for (const prevElement of toIterable(this.elements)) {\r\n const nextElement = nextElements.get(prevElement.id);\r\n\r\n if (!nextElement) {\r\n // element was deleted\r\n changedElements.set(\r\n prevElement.id,\r\n newElementWith(prevElement, { isDeleted: true }),\r\n );\r\n }\r\n }\r\n\r\n for (const nextElement of toIterable(nextElements)) {\r\n const prevElement = this.elements.get(nextElement.id);\r\n\r\n if (\r\n !prevElement || // element was added\r\n prevElement.version < nextElement.version // element was updated\r\n ) {\r\n if (\r\n isImageElement(nextElement) &&\r\n !isInitializedImageElement(nextElement)\r\n ) {\r\n // ignore any updates on uninitialized image elements\r\n continue;\r\n }\r\n\r\n changedElements.set(nextElement.id, nextElement);\r\n }\r\n }\r\n\r\n if (!changedElements.size) {\r\n return;\r\n }\r\n\r\n const changedElementsHash = hashElementsVersion(changedElements);\r\n\r\n if (\r\n options.shouldCompareHashes &&\r\n this._lastChangedElementsHash === changedElementsHash\r\n ) {\r\n return;\r\n }\r\n\r\n this._lastChangedElementsHash = changedElementsHash;\r\n\r\n return changedElements;\r\n }\r\n\r\n /**\r\n * Perform structural clone, deep cloning only elements that changed.\r\n */\r\n private createElementsSnapshot(changedElements: SceneElementsMap) {\r\n const clonedElements = new Map() as SceneElementsMap;\r\n\r\n for (const prevElement of toIterable(this.elements)) {\r\n // Clone previous elements, never delete, in case nextElements would be just a subset of previous elements\r\n // i.e. during collab, persist or whenenever isDeleted elements get cleared\r\n clonedElements.set(prevElement.id, prevElement);\r\n }\r\n\r\n for (const changedElement of toIterable(changedElements)) {\r\n // TODO: consider just creating new instance, once we can ensure that all reference properties on every element are immutable\r\n // TODO: consider creating a lazy deep clone, having a one-time-usage proxy over the snapshotted element and deep cloning only if it gets mutated\r\n clonedElements.set(changedElement.id, deepCopyElement(changedElement));\r\n }\r\n\r\n return clonedElements;\r\n }\r\n}\r\n\r\n// hidden non-enumerable property for runtime checks\r\nconst hiddenObservedAppStateProp = \"__observedAppState\";\r\n\r\nconst getDefaultObservedAppState = (): ObservedAppState => {\r\n return {\r\n name: null,\r\n editingGroupId: null,\r\n viewBackgroundColor: COLOR_PALETTE.white,\r\n selectedElementIds: {},\r\n selectedGroupIds: {},\r\n selectedLinearElement: null,\r\n croppingElementId: null,\r\n activeLockedId: null,\r\n lockedMultiSelections: {},\r\n };\r\n};\r\n\r\nexport const getObservedAppState = (\r\n appState: AppState | ObservedAppState,\r\n): ObservedAppState => {\r\n const observedAppState = {\r\n name: appState.name,\r\n editingGroupId: appState.editingGroupId,\r\n viewBackgroundColor: appState.viewBackgroundColor,\r\n selectedElementIds: appState.selectedElementIds,\r\n selectedGroupIds: appState.selectedGroupIds,\r\n croppingElementId: appState.croppingElementId,\r\n activeLockedId: appState.activeLockedId,\r\n lockedMultiSelections: appState.lockedMultiSelections,\r\n selectedLinearElement: appState.selectedLinearElement\r\n ? {\r\n elementId: appState.selectedLinearElement.elementId,\r\n isEditing: !!appState.selectedLinearElement.isEditing,\r\n }\r\n : null,\r\n };\r\n\r\n Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {\r\n value: true,\r\n enumerable: false,\r\n });\r\n\r\n return observedAppState;\r\n};\r\n\r\nconst isObservedAppState = (\r\n appState: AppState | ObservedAppState,\r\n): appState is ObservedAppState =>\r\n !!Reflect.get(appState, hiddenObservedAppStateProp);\r\n", "import {\r\n ORIG_ID,\r\n randomId,\r\n randomInteger,\r\n arrayToMap,\r\n castArray,\r\n findLastIndex,\r\n getUpdatedTimestamp,\r\n isTestEnv,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { Mutable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport {\r\n getElementsInGroup,\r\n getNewGroupIdsForDuplication,\r\n getSelectedGroupForElement,\r\n} from \"./groups\";\r\n\r\nimport {\r\n bindElementsToFramesAfterDuplication,\r\n getFrameChildren,\r\n} from \"./frame\";\r\n\r\nimport { normalizeElementOrder } from \"./sortElements\";\r\n\r\nimport { bumpVersion } from \"./mutateElement\";\r\n\r\nimport {\r\n hasBoundTextElement,\r\n isBoundToContainer,\r\n isFrameLikeElement,\r\n} from \"./typeChecks\";\r\n\r\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\r\n\r\nimport { fixDuplicatedBindingsAfterDuplication } from \"./binding\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawElement,\r\n GroupId,\r\n NonDeletedSceneElementsMap,\r\n} from \"./types\";\r\n\r\n/**\r\n * Duplicate an element, often used in the alt-drag operation.\r\n * Note that this method has gotten a bit complicated since the\r\n * introduction of gruoping/ungrouping elements.\r\n * @param editingGroupId The current group being edited. The new\r\n * element will inherit this group and its\r\n * parents.\r\n * @param groupIdMapForOperation A Map that maps old group IDs to\r\n * duplicated ones. If you are duplicating\r\n * multiple elements at once, share this map\r\n * amongst all of them\r\n * @param element Element to duplicate\r\n */\r\nexport const duplicateElement = <TElement extends ExcalidrawElement>(\r\n editingGroupId: AppState[\"editingGroupId\"],\r\n groupIdMapForOperation: Map<GroupId, GroupId>,\r\n element: TElement,\r\n randomizeSeed?: boolean,\r\n): Readonly<TElement> => {\r\n const copy = deepCopyElement(element);\r\n\r\n if (isTestEnv()) {\r\n __test__defineOrigId(copy, element.id);\r\n }\r\n\r\n copy.id = randomId();\r\n copy.updated = getUpdatedTimestamp();\r\n if (randomizeSeed) {\r\n copy.seed = randomInteger();\r\n bumpVersion(copy);\r\n }\r\n\r\n copy.groupIds = getNewGroupIdsForDuplication(\r\n copy.groupIds,\r\n editingGroupId,\r\n (groupId) => {\r\n if (!groupIdMapForOperation.has(groupId)) {\r\n groupIdMapForOperation.set(groupId, randomId());\r\n }\r\n return groupIdMapForOperation.get(groupId)!;\r\n },\r\n );\r\n return copy;\r\n};\r\n\r\nexport const duplicateElements = (\r\n opts: {\r\n elements: readonly ExcalidrawElement[];\r\n randomizeSeed?: boolean;\r\n overrides?: (data: {\r\n duplicateElement: ExcalidrawElement;\r\n origElement: ExcalidrawElement;\r\n origIdToDuplicateId: Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement[\"id\"]\r\n >;\r\n }) => Partial<ExcalidrawElement>;\r\n } & (\r\n | {\r\n /**\r\n * Duplicates all elements in array.\r\n *\r\n * Use this when programmaticaly duplicating elements, without direct\r\n * user interaction.\r\n */\r\n type: \"everything\";\r\n }\r\n | {\r\n /**\r\n * Duplicates specified elements and inserts them back into the array\r\n * in specified order.\r\n *\r\n * Use this when duplicating Scene elements, during user interaction\r\n * such as alt-drag or on duplicate action.\r\n */\r\n type: \"in-place\";\r\n idsOfElementsToDuplicate: Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement\r\n >;\r\n appState: {\r\n editingGroupId: AppState[\"editingGroupId\"];\r\n selectedGroupIds: AppState[\"selectedGroupIds\"];\r\n };\r\n }\r\n ),\r\n) => {\r\n let { elements } = opts;\r\n\r\n const appState =\r\n \"appState\" in opts\r\n ? opts.appState\r\n : ({\r\n editingGroupId: null,\r\n selectedGroupIds: {},\r\n } as const);\r\n\r\n // Ids of elements that have already been processed so we don't push them\r\n // into the array twice if we end up backtracking when retrieving\r\n // discontiguous group of elements (can happen due to a bug, or in edge\r\n // cases such as a group containing deleted elements which were not selected).\r\n //\r\n // This is not enough to prevent duplicates, so we do a second loop afterwards\r\n // to remove them.\r\n //\r\n // For convenience we mark even the newly created ones even though we don't\r\n // loop over them.\r\n const processedIds = new Map<ExcalidrawElement[\"id\"], true>();\r\n const groupIdMap = new Map();\r\n const duplicatedElements: ExcalidrawElement[] = [];\r\n const origElements: ExcalidrawElement[] = [];\r\n const origIdToDuplicateId = new Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement[\"id\"]\r\n >();\r\n const duplicateIdToOrigElement = new Map<\r\n ExcalidrawElement[\"id\"],\r\n ExcalidrawElement\r\n >();\r\n const duplicateElementsMap = new Map<string, ExcalidrawElement>();\r\n const elementsMap = arrayToMap(elements) as ElementsMap;\r\n const _idsOfElementsToDuplicate =\r\n opts.type === \"in-place\"\r\n ? opts.idsOfElementsToDuplicate\r\n : new Map(elements.map((el) => [el.id, el]));\r\n\r\n // For sanity\r\n if (opts.type === \"in-place\") {\r\n for (const groupId of Object.keys(opts.appState.selectedGroupIds)) {\r\n elements\r\n .filter((el) => el.groupIds?.includes(groupId))\r\n .forEach((el) => _idsOfElementsToDuplicate.set(el.id, el));\r\n }\r\n }\r\n\r\n elements = normalizeElementOrder(elements);\r\n\r\n const elementsWithDuplicates: ExcalidrawElement[] = elements.slice();\r\n\r\n // helper functions\r\n // -------------------------------------------------------------------------\r\n\r\n // Used for the heavy lifing of copying a single element, a group of elements\r\n // an element with bound text etc.\r\n const copyElements = <T extends ExcalidrawElement | ExcalidrawElement[]>(\r\n element: T,\r\n ): T extends ExcalidrawElement[]\r\n ? ExcalidrawElement[]\r\n : ExcalidrawElement | null => {\r\n const elements = castArray(element);\r\n\r\n const _newElements = elements.reduce(\r\n (acc: ExcalidrawElement[], element) => {\r\n if (processedIds.has(element.id)) {\r\n return acc;\r\n }\r\n\r\n processedIds.set(element.id, true);\r\n\r\n const newElement = duplicateElement(\r\n appState.editingGroupId,\r\n groupIdMap,\r\n element,\r\n opts.randomizeSeed,\r\n );\r\n\r\n processedIds.set(newElement.id, true);\r\n\r\n duplicateElementsMap.set(newElement.id, newElement);\r\n origIdToDuplicateId.set(element.id, newElement.id);\r\n duplicateIdToOrigElement.set(newElement.id, element);\r\n\r\n origElements.push(element);\r\n duplicatedElements.push(newElement);\r\n\r\n acc.push(newElement);\r\n return acc;\r\n },\r\n [],\r\n );\r\n\r\n return (\r\n Array.isArray(element) ? _newElements : _newElements[0] || null\r\n ) as T extends ExcalidrawElement[]\r\n ? ExcalidrawElement[]\r\n : ExcalidrawElement | null;\r\n };\r\n\r\n // Helper to position cloned elements in the Z-order the product needs it\r\n const insertBeforeOrAfterIndex = (\r\n index: number,\r\n elements: ExcalidrawElement | null | ExcalidrawElement[],\r\n ) => {\r\n if (!elements) {\r\n return;\r\n }\r\n\r\n if (index > elementsWithDuplicates.length - 1) {\r\n elementsWithDuplicates.push(...castArray(elements));\r\n return;\r\n }\r\n\r\n elementsWithDuplicates.splice(index + 1, 0, ...castArray(elements));\r\n };\r\n\r\n const frameIdsToDuplicate = new Set(\r\n elements\r\n .filter(\r\n (el) => _idsOfElementsToDuplicate.has(el.id) && isFrameLikeElement(el),\r\n )\r\n .map((el) => el.id),\r\n );\r\n\r\n for (const element of elements) {\r\n if (processedIds.has(element.id)) {\r\n continue;\r\n }\r\n\r\n if (!_idsOfElementsToDuplicate.has(element.id)) {\r\n continue;\r\n }\r\n\r\n // groups\r\n // -------------------------------------------------------------------------\r\n\r\n const groupId = getSelectedGroupForElement(appState, element);\r\n if (groupId) {\r\n const groupElements = getElementsInGroup(elements, groupId).flatMap(\r\n (element) =>\r\n isFrameLikeElement(element)\r\n ? [...getFrameChildren(elements, element.id), element]\r\n : [element],\r\n );\r\n\r\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\r\n return el.groupIds?.includes(groupId);\r\n });\r\n\r\n insertBeforeOrAfterIndex(targetIndex, copyElements(groupElements));\r\n continue;\r\n }\r\n\r\n // frame duplication\r\n // -------------------------------------------------------------------------\r\n\r\n if (element.frameId && frameIdsToDuplicate.has(element.frameId)) {\r\n continue;\r\n }\r\n\r\n if (isFrameLikeElement(element)) {\r\n const frameId = element.id;\r\n\r\n const frameChildren = getFrameChildren(elements, frameId);\r\n\r\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\r\n return el.frameId === frameId || el.id === frameId;\r\n });\r\n\r\n insertBeforeOrAfterIndex(\r\n targetIndex,\r\n copyElements([...frameChildren, element]),\r\n );\r\n continue;\r\n }\r\n\r\n // text container\r\n // -------------------------------------------------------------------------\r\n\r\n if (hasBoundTextElement(element)) {\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n\r\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\r\n return (\r\n el.id === element.id ||\r\n (\"containerId\" in el && el.containerId === element.id)\r\n );\r\n });\r\n\r\n if (boundTextElement) {\r\n insertBeforeOrAfterIndex(\r\n targetIndex,\r\n copyElements([element, boundTextElement]),\r\n );\r\n } else {\r\n insertBeforeOrAfterIndex(targetIndex, copyElements(element));\r\n }\r\n\r\n continue;\r\n }\r\n\r\n if (isBoundToContainer(element)) {\r\n const container = getContainerElement(element, elementsMap);\r\n\r\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\r\n return el.id === element.id || el.id === container?.id;\r\n });\r\n\r\n if (container) {\r\n insertBeforeOrAfterIndex(\r\n targetIndex,\r\n copyElements([container, element]),\r\n );\r\n } else {\r\n insertBeforeOrAfterIndex(targetIndex, copyElements(element));\r\n }\r\n\r\n continue;\r\n }\r\n\r\n // default duplication (regular elements)\r\n // -------------------------------------------------------------------------\r\n\r\n insertBeforeOrAfterIndex(\r\n findLastIndex(elementsWithDuplicates, (el) => el.id === element.id),\r\n copyElements(element),\r\n );\r\n }\r\n\r\n // ---------------------------------------------------------------------------\r\n\r\n fixDuplicatedBindingsAfterDuplication(\r\n duplicatedElements,\r\n origIdToDuplicateId,\r\n duplicateElementsMap as NonDeletedSceneElementsMap,\r\n );\r\n\r\n bindElementsToFramesAfterDuplication(\r\n elementsWithDuplicates,\r\n origElements,\r\n origIdToDuplicateId,\r\n );\r\n\r\n if (opts.overrides) {\r\n for (const duplicateElement of duplicatedElements) {\r\n const origElement = duplicateIdToOrigElement.get(duplicateElement.id);\r\n if (origElement) {\r\n Object.assign(\r\n duplicateElement,\r\n opts.overrides({\r\n duplicateElement,\r\n origElement,\r\n origIdToDuplicateId,\r\n }),\r\n );\r\n }\r\n }\r\n }\r\n\r\n return {\r\n duplicatedElements,\r\n duplicateElementsMap,\r\n elementsWithDuplicates,\r\n origIdToDuplicateId,\r\n };\r\n};\r\n\r\n// Simplified deep clone for the purpose of cloning ExcalidrawElement.\r\n//\r\n// Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\r\n// Typed arrays and other non-null objects.\r\n//\r\n// Adapted from https://github.com/lukeed/klona\r\n//\r\n// The reason for `deepCopyElement()` wrapper is type safety (only allow\r\n// passing ExcalidrawElement as the top-level argument).\r\nconst _deepCopyElement = (val: any, depth: number = 0) => {\r\n // only clone non-primitives\r\n if (val == null || typeof val !== \"object\") {\r\n return val;\r\n }\r\n\r\n const objectType = Object.prototype.toString.call(val);\r\n\r\n if (objectType === \"[object Object]\") {\r\n const tmp =\r\n typeof val.constructor === \"function\"\r\n ? Object.create(Object.getPrototypeOf(val))\r\n : {};\r\n for (const key in val) {\r\n if (val.hasOwnProperty(key)) {\r\n // don't copy non-serializable objects like these caches. They'll be\r\n // populated when the element is rendered.\r\n if (depth === 0 && (key === \"shape\" || key === \"canvas\")) {\r\n continue;\r\n }\r\n tmp[key] = _deepCopyElement(val[key], depth + 1);\r\n }\r\n }\r\n return tmp;\r\n }\r\n\r\n if (Array.isArray(val)) {\r\n let k = val.length;\r\n const arr = new Array(k);\r\n while (k--) {\r\n arr[k] = _deepCopyElement(val[k], depth + 1);\r\n }\r\n return arr;\r\n }\r\n\r\n // we're not cloning non-array & non-plain-object objects because we\r\n // don't support them on excalidraw elements yet. If we do, we need to make\r\n // sure we start cloning them, so let's warn about it.\r\n if (import.meta.env.DEV) {\r\n if (\r\n objectType !== \"[object Object]\" &&\r\n objectType !== \"[object Array]\" &&\r\n objectType.startsWith(\"[object \")\r\n ) {\r\n console.warn(\r\n `_deepCloneElement: unexpected object type ${objectType}. This value will not be cloned!`,\r\n );\r\n }\r\n }\r\n\r\n return val;\r\n};\r\n\r\n/**\r\n * Clones ExcalidrawElement data structure. Does not regenerate id, nonce, or\r\n * any value. The purpose is to to break object references for immutability\r\n * reasons, whenever we want to keep the original element, but ensure it's not\r\n * mutated.\r\n *\r\n * Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\r\n * Typed arrays and other non-null objects.\r\n */\r\nexport const deepCopyElement = <T extends ExcalidrawElement>(\r\n val: T,\r\n): Mutable<T> => {\r\n return _deepCopyElement(val);\r\n};\r\n\r\nconst __test__defineOrigId = (clonedObj: object, origId: string) => {\r\n Object.defineProperty(clonedObj, ORIG_ID, {\r\n value: origId,\r\n writable: false,\r\n enumerable: false,\r\n });\r\n};\r\n", "import { arrayToMapWithIndex } from \"@excalidraw-modify/common\";\r\n\r\nimport type { ExcalidrawElement } from \"./types\";\r\n\r\nconst normalizeGroupElementOrder = (elements: readonly ExcalidrawElement[]) => {\r\n const origElements: ExcalidrawElement[] = elements.slice();\r\n const sortedElements = new Set<ExcalidrawElement>();\r\n\r\n const orderInnerGroups = (\r\n elements: readonly ExcalidrawElement[],\r\n ): ExcalidrawElement[] => {\r\n const firstGroupSig = elements[0]?.groupIds?.join(\"\");\r\n const aGroup: ExcalidrawElement[] = [elements[0]];\r\n const bGroup: ExcalidrawElement[] = [];\r\n for (const element of elements.slice(1)) {\r\n if (element.groupIds?.join(\"\") === firstGroupSig) {\r\n aGroup.push(element);\r\n } else {\r\n bGroup.push(element);\r\n }\r\n }\r\n return bGroup.length ? [...aGroup, ...orderInnerGroups(bGroup)] : aGroup;\r\n };\r\n\r\n const groupHandledElements = new Map<string, true>();\r\n\r\n origElements.forEach((element, idx) => {\r\n if (groupHandledElements.has(element.id)) {\r\n return;\r\n }\r\n if (element.groupIds?.length) {\r\n const topGroup = element.groupIds[element.groupIds.length - 1];\r\n const groupElements = origElements.slice(idx).filter((element) => {\r\n const ret = element?.groupIds?.some((id) => id === topGroup);\r\n if (ret) {\r\n groupHandledElements.set(element!.id, true);\r\n }\r\n return ret;\r\n });\r\n\r\n for (const elem of orderInnerGroups(groupElements)) {\r\n sortedElements.add(elem);\r\n }\r\n } else {\r\n sortedElements.add(element);\r\n }\r\n });\r\n\r\n // if there's a bug which resulted in losing some of the elements, return\r\n // original instead as that's better than losing data\r\n if (sortedElements.size !== elements.length) {\r\n console.error(\"normalizeGroupElementOrder: lost some elements... bailing!\");\r\n return elements;\r\n }\r\n\r\n return [...sortedElements];\r\n};\r\n\r\n/**\r\n * In theory, when we have text elements bound to a container, they\r\n * should be right after the container element in the elements array.\r\n * However, this is not guaranteed due to old and potential future bugs.\r\n *\r\n * This function sorts containers and their bound texts together. It prefers\r\n * original z-index of container (i.e. it moves bound text elements after\r\n * containers).\r\n */\r\nconst normalizeBoundElementsOrder = (\r\n elements: readonly ExcalidrawElement[],\r\n) => {\r\n const elementsMap = arrayToMapWithIndex(elements);\r\n\r\n const origElements: (ExcalidrawElement | null)[] = elements.slice();\r\n const sortedElements = new Set<ExcalidrawElement>();\r\n\r\n origElements.forEach((element, idx) => {\r\n if (!element) {\r\n return;\r\n }\r\n if (element.boundElements?.length) {\r\n sortedElements.add(element);\r\n origElements[idx] = null;\r\n element.boundElements.forEach((boundElement) => {\r\n const child = elementsMap.get(boundElement.id);\r\n if (child && boundElement.type === \"text\") {\r\n sortedElements.add(child[0]);\r\n origElements[child[1]] = null;\r\n }\r\n });\r\n } else if (element.type === \"text\" && element.containerId) {\r\n const parent = elementsMap.get(element.containerId);\r\n if (!parent?.[0].boundElements?.find((x) => x.id === element.id)) {\r\n sortedElements.add(element);\r\n origElements[idx] = null;\r\n\r\n // if element has a container and container lists it, skip this element\r\n // as it'll be taken care of by the container\r\n }\r\n } else {\r\n sortedElements.add(element);\r\n origElements[idx] = null;\r\n }\r\n });\r\n\r\n // if there's a bug which resulted in losing some of the elements, return\r\n // original instead as that's better than losing data\r\n if (sortedElements.size !== elements.length) {\r\n console.error(\r\n \"normalizeBoundElementsOrder: lost some elements... bailing!\",\r\n );\r\n return elements;\r\n }\r\n\r\n return [...sortedElements];\r\n};\r\n\r\nexport const normalizeElementOrder = (\r\n elements: readonly ExcalidrawElement[],\r\n) => {\r\n return normalizeBoundElementsOrder(normalizeGroupElementOrder(elements));\r\n};\r\n", "import { generateNKeysBetween } from \"fractional-indexing\";\r\n\r\nimport { arrayToMap } from \"@excalidraw-modify/common\";\r\n\r\nimport { mutateElement, newElementWith } from \"./mutateElement\";\r\nimport { getBoundTextElement } from \"./textElement\";\r\nimport { hasBoundTextElement } from \"./typeChecks\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawElement,\r\n FractionalIndex,\r\n OrderedExcalidrawElement,\r\n SceneElementsMap,\r\n} from \"./types\";\r\n\r\nexport class InvalidFractionalIndexError extends Error {\r\n public code = \"ELEMENT_HAS_INVALID_INDEX\" as const;\r\n}\r\n\r\n/**\r\n * Envisioned relation between array order and fractional indices:\r\n *\r\n * 1) Array (or array-like ordered data structure) should be used as a cache of elements order, hiding the internal fractional indices implementation.\r\n * - it's undesirable to perform reorder for each related operation, therefore it's necessary to cache the order defined by fractional indices into an ordered data structure\r\n * - it's easy enough to define the order of the elements from the outside (boundaries), without worrying about the underlying structure of fractional indices (especially for the host apps)\r\n * - it's necessary to always keep the array support for backwards compatibility (restore) - old scenes, old libraries, supporting multiple excalidraw versions etc.\r\n * - it's necessary to always keep the fractional indices in sync with the array order\r\n * - elements with invalid indices should be detected and synced, without altering the already valid indices\r\n *\r\n * 2) Fractional indices should be used to reorder the elements, whenever the cached order is expected to be invalidated.\r\n * - as the fractional indices are encoded as part of the elements, it opens up possibilities for incremental-like APIs\r\n * - re-order based on fractional indices should be part of (multiplayer) operations such as reconciliation & undo/redo\r\n * - technically all the z-index actions could perform also re-order based on fractional indices,but in current state it would not bring much benefits,\r\n * as it's faster & more efficient to perform re-order based on array manipulation and later synchronisation of moved indices with the array order\r\n */\r\n\r\n/**\r\n * Ensure that all elements have valid fractional indices.\r\n *\r\n * @throws `InvalidFractionalIndexError` if invalid index is detected.\r\n */\r\nexport const validateFractionalIndices = (\r\n elements: readonly ExcalidrawElement[],\r\n {\r\n shouldThrow = false,\r\n includeBoundTextValidation = false,\r\n ignoreLogs,\r\n reconciliationContext,\r\n }: {\r\n shouldThrow: boolean;\r\n includeBoundTextValidation: boolean;\r\n ignoreLogs?: true;\r\n reconciliationContext?: {\r\n localElements: ReadonlyArray<ExcalidrawElement>;\r\n remoteElements: ReadonlyArray<ExcalidrawElement>;\r\n };\r\n },\r\n) => {\r\n const errorMessages = [];\r\n const stringifyElement = (element: ExcalidrawElement | void) =>\r\n `${element?.index}:${element?.id}:${element?.type}:${element?.isDeleted}:${element?.version}:${element?.versionNonce}`;\r\n\r\n const indices = elements.map((x) => x.index);\r\n for (const [i, index] of indices.entries()) {\r\n const predecessorIndex = indices[i - 1];\r\n const successorIndex = indices[i + 1];\r\n\r\n if (!isValidFractionalIndex(index, predecessorIndex, successorIndex)) {\r\n errorMessages.push(\r\n `Fractional indices invariant has been compromised: \"${stringifyElement(\r\n elements[i - 1],\r\n )}\", \"${stringifyElement(elements[i])}\", \"${stringifyElement(\r\n elements[i + 1],\r\n )}\"`,\r\n );\r\n }\r\n\r\n // disabled by default, as we don't fix it\r\n if (includeBoundTextValidation && hasBoundTextElement(elements[i])) {\r\n const container = elements[i];\r\n const text = getBoundTextElement(container, arrayToMap(elements));\r\n\r\n if (text && text.index! <= container.index!) {\r\n errorMessages.push(\r\n `Fractional indices invariant for bound elements has been compromised: \"${stringifyElement(\r\n text,\r\n )}\", \"${stringifyElement(container)}\"`,\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (errorMessages.length) {\r\n const error = new InvalidFractionalIndexError();\r\n const additionalContext = [];\r\n\r\n if (reconciliationContext) {\r\n additionalContext.push(\"Additional reconciliation context:\");\r\n additionalContext.push(\r\n reconciliationContext.localElements.map((x) => stringifyElement(x)),\r\n );\r\n additionalContext.push(\r\n reconciliationContext.remoteElements.map((x) => stringifyElement(x)),\r\n );\r\n }\r\n\r\n if (!ignoreLogs) {\r\n // report just once and with the stacktrace\r\n console.error(\r\n errorMessages.join(\"\\n\\n\"),\r\n error.stack,\r\n elements.map((x) => stringifyElement(x)),\r\n ...additionalContext,\r\n );\r\n }\r\n\r\n if (shouldThrow) {\r\n // if enabled, gather all the errors first, throw once\r\n throw error;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Order the elements based on the fractional indices.\r\n * - when fractional indices are identical, break the tie based on the element id\r\n * - when there is no fractional index in one of the elements, respect the order of the array\r\n */\r\nexport const orderByFractionalIndex = (\r\n elements: OrderedExcalidrawElement[],\r\n) => {\r\n return elements.sort((a, b) => {\r\n // in case the indices are not the defined at runtime\r\n if (isOrderedElement(a) && isOrderedElement(b)) {\r\n if (a.index < b.index) {\r\n return -1;\r\n } else if (a.index > b.index) {\r\n return 1;\r\n }\r\n\r\n // break ties based on the element id\r\n return a.id < b.id ? -1 : 1;\r\n }\r\n\r\n // defensively keep the array order\r\n return 1;\r\n });\r\n};\r\n\r\n/**\r\n * Synchronizes invalid fractional indices of moved elements with the array order by mutating passed elements.\r\n * If the synchronization fails or the result is invalid, it fallbacks to `syncInvalidIndices`.\r\n */\r\nexport const syncMovedIndices = (\r\n elements: readonly ExcalidrawElement[],\r\n movedElements: ElementsMap,\r\n): OrderedExcalidrawElement[] => {\r\n try {\r\n const elementsMap = arrayToMap(elements);\r\n const indicesGroups = getMovedIndicesGroups(elements, movedElements);\r\n\r\n // try generatating indices, throws on invalid movedElements\r\n const elementsUpdates = generateIndices(elements, indicesGroups);\r\n const elementsCandidates = elements.map((x) => {\r\n const elementUpdates = elementsUpdates.get(x);\r\n\r\n if (elementUpdates) {\r\n return { ...x, index: elementUpdates.index };\r\n }\r\n\r\n return x;\r\n });\r\n\r\n // ensure next indices are valid before mutation, throws on invalid ones\r\n validateFractionalIndices(\r\n elementsCandidates,\r\n // we don't autofix invalid bound text indices, hence don't include it in the validation\r\n {\r\n includeBoundTextValidation: false,\r\n shouldThrow: true,\r\n ignoreLogs: true,\r\n },\r\n );\r\n\r\n // split mutation so we don't end up in an incosistent state\r\n for (const [element, { index }] of elementsUpdates) {\r\n mutateElement(element, elementsMap, { index });\r\n }\r\n } catch (e) {\r\n // fallback to default sync\r\n syncInvalidIndices(elements);\r\n }\r\n\r\n return elements as OrderedExcalidrawElement[];\r\n};\r\n\r\n/**\r\n * Synchronizes all invalid fractional indices within the array order by mutating elements in the passed array.\r\n *\r\n * WARN: in edge cases it could modify the elements which were not moved, as it's impossible to guess the actually moved elements from the elements array itself.\r\n */\r\nexport const syncInvalidIndices = (\r\n elements: readonly ExcalidrawElement[],\r\n): OrderedExcalidrawElement[] => {\r\n const elementsMap = arrayToMap(elements);\r\n const indicesGroups = getInvalidIndicesGroups(elements);\r\n const elementsUpdates = generateIndices(elements, indicesGroups);\r\n\r\n for (const [element, { index }] of elementsUpdates) {\r\n mutateElement(element, elementsMap, { index });\r\n }\r\n\r\n return elements as OrderedExcalidrawElement[];\r\n};\r\n\r\n/**\r\n * Synchronizes all invalid fractional indices within the array order by creating new instances of elements with corrected indices.\r\n *\r\n * WARN: in edge cases it could modify the elements which were not moved, as it's impossible to guess the actually moved elements from the elements array itself.\r\n */\r\nexport const syncInvalidIndicesImmutable = (\r\n elements: readonly ExcalidrawElement[],\r\n): SceneElementsMap | undefined => {\r\n const syncedElements = arrayToMap(elements);\r\n const indicesGroups = getInvalidIndicesGroups(elements);\r\n const elementsUpdates = generateIndices(elements, indicesGroups);\r\n\r\n for (const [element, { index }] of elementsUpdates) {\r\n syncedElements.set(element.id, newElementWith(element, { index }));\r\n }\r\n\r\n return syncedElements as SceneElementsMap;\r\n};\r\n\r\n/**\r\n * Get contiguous groups of indices of passed moved elements.\r\n *\r\n * NOTE: First and last elements within the groups are indices of lower and upper bounds.\r\n */\r\nconst getMovedIndicesGroups = (\r\n elements: readonly ExcalidrawElement[],\r\n movedElements: ElementsMap,\r\n) => {\r\n const indicesGroups: number[][] = [];\r\n\r\n let i = 0;\r\n\r\n while (i < elements.length) {\r\n if (movedElements.has(elements[i].id)) {\r\n const indicesGroup = [i - 1, i]; // push the lower bound index as the first item\r\n\r\n while (++i < elements.length) {\r\n if (!movedElements.has(elements[i].id)) {\r\n break;\r\n }\r\n\r\n indicesGroup.push(i);\r\n }\r\n\r\n indicesGroup.push(i); // push the upper bound index as the last item\r\n indicesGroups.push(indicesGroup);\r\n } else {\r\n i++;\r\n }\r\n }\r\n\r\n return indicesGroups;\r\n};\r\n\r\n/**\r\n * Gets contiguous groups of all invalid indices automatically detected inside the elements array.\r\n *\r\n * WARN: First and last items within the groups do NOT have to be contiguous, those are the found lower and upper bounds!\r\n */\r\nconst getInvalidIndicesGroups = (elements: readonly ExcalidrawElement[]) => {\r\n const indicesGroups: number[][] = [];\r\n\r\n // once we find lowerBound / upperBound, it cannot be lower than that, so we cache it for better perf.\r\n let lowerBound: ExcalidrawElement[\"index\"] | undefined = undefined;\r\n let upperBound: ExcalidrawElement[\"index\"] | undefined = undefined;\r\n let lowerBoundIndex: number = -1;\r\n let upperBoundIndex: number = 0;\r\n\r\n /** @returns maybe valid lowerBound */\r\n const getLowerBound = (\r\n index: number,\r\n ): [ExcalidrawElement[\"index\"] | undefined, number] => {\r\n const lowerBound = elements[lowerBoundIndex]\r\n ? elements[lowerBoundIndex].index\r\n : undefined;\r\n\r\n // we are already iterating left to right, therefore there is no need for additional looping\r\n const candidate = elements[index - 1]?.index;\r\n\r\n if (\r\n (!lowerBound && candidate) || // first lowerBound\r\n (lowerBound && candidate && candidate > lowerBound) // next lowerBound\r\n ) {\r\n // WARN: candidate's index could be higher or same as the current element's index\r\n return [candidate, index - 1];\r\n }\r\n\r\n // cache hit! take the last lower bound\r\n return [lowerBound, lowerBoundIndex];\r\n };\r\n\r\n /** @returns always valid upperBound */\r\n const getUpperBound = (\r\n index: number,\r\n ): [ExcalidrawElement[\"index\"] | undefined, number] => {\r\n const upperBound = elements[upperBoundIndex]\r\n ? elements[upperBoundIndex].index\r\n : undefined;\r\n\r\n // cache hit! don't let it find the upper bound again\r\n if (upperBound && index < upperBoundIndex) {\r\n return [upperBound, upperBoundIndex];\r\n }\r\n\r\n // set the current upperBoundIndex as the starting point\r\n let i = upperBoundIndex;\r\n while (++i < elements.length) {\r\n const candidate = elements[i]?.index;\r\n\r\n if (\r\n (!upperBound && candidate) || // first upperBound\r\n (upperBound && candidate && candidate > upperBound) // next upperBound\r\n ) {\r\n return [candidate, i];\r\n }\r\n }\r\n\r\n // we reached the end, sky is the limit\r\n return [undefined, i];\r\n };\r\n\r\n let i = 0;\r\n\r\n while (i < elements.length) {\r\n const current = elements[i].index;\r\n [lowerBound, lowerBoundIndex] = getLowerBound(i);\r\n [upperBound, upperBoundIndex] = getUpperBound(i);\r\n\r\n if (!isValidFractionalIndex(current, lowerBound, upperBound)) {\r\n // push the lower bound index as the first item\r\n const indicesGroup = [lowerBoundIndex, i];\r\n\r\n while (++i < elements.length) {\r\n const current = elements[i].index;\r\n const [nextLowerBound, nextLowerBoundIndex] = getLowerBound(i);\r\n const [nextUpperBound, nextUpperBoundIndex] = getUpperBound(i);\r\n\r\n if (isValidFractionalIndex(current, nextLowerBound, nextUpperBound)) {\r\n break;\r\n }\r\n\r\n // assign bounds only for the moved elements\r\n [lowerBound, lowerBoundIndex] = [nextLowerBound, nextLowerBoundIndex];\r\n [upperBound, upperBoundIndex] = [nextUpperBound, nextUpperBoundIndex];\r\n\r\n indicesGroup.push(i);\r\n }\r\n\r\n // push the upper bound index as the last item\r\n indicesGroup.push(upperBoundIndex);\r\n indicesGroups.push(indicesGroup);\r\n } else {\r\n i++;\r\n }\r\n }\r\n\r\n return indicesGroups;\r\n};\r\n\r\nconst isValidFractionalIndex = (\r\n index: ExcalidrawElement[\"index\"] | undefined,\r\n predecessor: ExcalidrawElement[\"index\"] | undefined,\r\n successor: ExcalidrawElement[\"index\"] | undefined,\r\n) => {\r\n if (!index) {\r\n return false;\r\n }\r\n\r\n if (predecessor && successor) {\r\n return predecessor < index && index < successor;\r\n }\r\n\r\n if (!predecessor && successor) {\r\n // first element\r\n return index < successor;\r\n }\r\n\r\n if (predecessor && !successor) {\r\n // last element\r\n return predecessor < index;\r\n }\r\n\r\n // only element in the array\r\n return !!index;\r\n};\r\n\r\nconst generateIndices = (\r\n elements: readonly ExcalidrawElement[],\r\n indicesGroups: number[][],\r\n) => {\r\n const elementsUpdates = new Map<\r\n ExcalidrawElement,\r\n { index: FractionalIndex }\r\n >();\r\n\r\n for (const indices of indicesGroups) {\r\n const lowerBoundIndex = indices.shift()!;\r\n const upperBoundIndex = indices.pop()!;\r\n\r\n const fractionalIndices = generateNKeysBetween(\r\n elements[lowerBoundIndex]?.index,\r\n elements[upperBoundIndex]?.index,\r\n indices.length,\r\n ) as FractionalIndex[];\r\n\r\n for (let i = 0; i < indices.length; i++) {\r\n const element = elements[indices[i]];\r\n\r\n elementsUpdates.set(element, {\r\n index: fractionalIndices[i],\r\n });\r\n }\r\n }\r\n\r\n return elementsUpdates;\r\n};\r\n\r\nconst isOrderedElement = (\r\n element: ExcalidrawElement,\r\n): element is OrderedExcalidrawElement => {\r\n // for now it's sufficient whether the index is there\r\n // meaning, the element was already ordered in the past\r\n // meaning, it is not a newly inserted element, not an unrestored element, etc.\r\n // it does not have to mean that the index itself is valid\r\n if (element.index) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n", "// License: CC0 (no rights reserved).\n\n// This is based on https://observablehq.com/@dgreensp/implementing-fractional-indexing\n\nexport const BASE_62_DIGITS =\n \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n// `a` may be empty string, `b` is null or non-empty string.\n// `a < b` lexicographically if `b` is non-null.\n// no trailing zeros allowed.\n// digits is a string such as '0123456789' for base 10. Digits must be in\n// ascending character code order!\n/**\n * @param {string} a\n * @param {string | null | undefined} b\n * @param {string} digits\n * @returns {string}\n */\nfunction midpoint(a, b, digits) {\n const zero = digits[0];\n if (b != null && a >= b) {\n throw new Error(a + \" >= \" + b);\n }\n if (a.slice(-1) === zero || (b && b.slice(-1) === zero)) {\n throw new Error(\"trailing zero\");\n }\n if (b) {\n // remove longest common prefix. pad `a` with 0s as we\n // go. note that we don't need to pad `b`, because it can't\n // end before `a` while traversing the common prefix.\n let n = 0;\n while ((a[n] || zero) === b[n]) {\n n++;\n }\n if (n > 0) {\n return b.slice(0, n) + midpoint(a.slice(n), b.slice(n), digits);\n }\n }\n // first digits (or lack of digit) are different\n const digitA = a ? digits.indexOf(a[0]) : 0;\n const digitB = b != null ? digits.indexOf(b[0]) : digits.length;\n if (digitB - digitA > 1) {\n const midDigit = Math.round(0.5 * (digitA + digitB));\n return digits[midDigit];\n } else {\n // first digits are consecutive\n if (b && b.length > 1) {\n return b.slice(0, 1);\n } else {\n // `b` is null or has length 1 (a single digit).\n // the first digit of `a` is the previous digit to `b`,\n // or 9 if `b` is null.\n // given, for example, midpoint('49', '5'), return\n // '4' + midpoint('9', null), which will become\n // '4' + '9' + midpoint('', null), which is '495'\n return digits[digitA] + midpoint(a.slice(1), null, digits);\n }\n }\n}\n\n/**\n * @param {string} int\n * @return {void}\n */\n\nfunction validateInteger(int) {\n if (int.length !== getIntegerLength(int[0])) {\n throw new Error(\"invalid integer part of order key: \" + int);\n }\n}\n\n/**\n * @param {string} head\n * @return {number}\n */\n\nfunction getIntegerLength(head) {\n if (head >= \"a\" && head <= \"z\") {\n return head.charCodeAt(0) - \"a\".charCodeAt(0) + 2;\n } else if (head >= \"A\" && head <= \"Z\") {\n return \"Z\".charCodeAt(0) - head.charCodeAt(0) + 2;\n } else {\n throw new Error(\"invalid order key head: \" + head);\n }\n}\n\n/**\n * @param {string} key\n * @return {string}\n */\n\nfunction getIntegerPart(key) {\n const integerPartLength = getIntegerLength(key[0]);\n if (integerPartLength > key.length) {\n throw new Error(\"invalid order key: \" + key);\n }\n return key.slice(0, integerPartLength);\n}\n\n/**\n * @param {string} key\n * @param {string} digits\n * @return {void}\n */\n\nfunction validateOrderKey(key, digits) {\n if (key === \"A\" + digits[0].repeat(26)) {\n throw new Error(\"invalid order key: \" + key);\n }\n // getIntegerPart will throw if the first character is bad,\n // or the key is too short. we'd call it to check these things\n // even if we didn't need the result\n const i = getIntegerPart(key);\n const f = key.slice(i.length);\n if (f.slice(-1) === digits[0]) {\n throw new Error(\"invalid order key: \" + key);\n }\n}\n\n// note that this may return null, as there is a largest integer\n/**\n * @param {string} x\n * @param {string} digits\n * @return {string | null}\n */\nfunction incrementInteger(x, digits) {\n validateInteger(x);\n const [head, ...digs] = x.split(\"\");\n let carry = true;\n for (let i = digs.length - 1; carry && i >= 0; i--) {\n const d = digits.indexOf(digs[i]) + 1;\n if (d === digits.length) {\n digs[i] = digits[0];\n } else {\n digs[i] = digits[d];\n carry = false;\n }\n }\n if (carry) {\n if (head === \"Z\") {\n return \"a\" + digits[0];\n }\n if (head === \"z\") {\n return null;\n }\n const h = String.fromCharCode(head.charCodeAt(0) + 1);\n if (h > \"a\") {\n digs.push(digits[0]);\n } else {\n digs.pop();\n }\n return h + digs.join(\"\");\n } else {\n return head + digs.join(\"\");\n }\n}\n\n// note that this may return null, as there is a smallest integer\n/**\n * @param {string} x\n * @param {string} digits\n * @return {string | null}\n */\n\nfunction decrementInteger(x, digits) {\n validateInteger(x);\n const [head, ...digs] = x.split(\"\");\n let borrow = true;\n for (let i = digs.length - 1; borrow && i >= 0; i--) {\n const d = digits.indexOf(digs[i]) - 1;\n if (d === -1) {\n digs[i] = digits.slice(-1);\n } else {\n digs[i] = digits[d];\n borrow = false;\n }\n }\n if (borrow) {\n if (head === \"a\") {\n return \"Z\" + digits.slice(-1);\n }\n if (head === \"A\") {\n return null;\n }\n const h = String.fromCharCode(head.charCodeAt(0) - 1);\n if (h < \"Z\") {\n digs.push(digits.slice(-1));\n } else {\n digs.pop();\n }\n return h + digs.join(\"\");\n } else {\n return head + digs.join(\"\");\n }\n}\n\n// `a` is an order key or null (START).\n// `b` is an order key or null (END).\n// `a < b` lexicographically if both are non-null.\n// digits is a string such as '0123456789' for base 10. Digits must be in\n// ascending character code order!\n/**\n * @param {string | null | undefined} a\n * @param {string | null | undefined} b\n * @param {string=} digits\n * @return {string}\n */\nexport function generateKeyBetween(a, b, digits = BASE_62_DIGITS) {\n if (a != null) {\n validateOrderKey(a, digits);\n }\n if (b != null) {\n validateOrderKey(b, digits);\n }\n if (a != null && b != null && a >= b) {\n throw new Error(a + \" >= \" + b);\n }\n if (a == null) {\n if (b == null) {\n return \"a\" + digits[0];\n }\n\n const ib = getIntegerPart(b);\n const fb = b.slice(ib.length);\n if (ib === \"A\" + digits[0].repeat(26)) {\n return ib + midpoint(\"\", fb, digits);\n }\n if (ib < b) {\n return ib;\n }\n const res = decrementInteger(ib, digits);\n if (res == null) {\n throw new Error(\"cannot decrement any more\");\n }\n return res;\n }\n\n if (b == null) {\n const ia = getIntegerPart(a);\n const fa = a.slice(ia.length);\n const i = incrementInteger(ia, digits);\n return i == null ? ia + midpoint(fa, null, digits) : i;\n }\n\n const ia = getIntegerPart(a);\n const fa = a.slice(ia.length);\n const ib = getIntegerPart(b);\n const fb = b.slice(ib.length);\n if (ia === ib) {\n return ia + midpoint(fa, fb, digits);\n }\n const i = incrementInteger(ia, digits);\n if (i == null) {\n throw new Error(\"cannot increment any more\");\n }\n if (i < b) {\n return i;\n }\n return ia + midpoint(fa, null, digits);\n}\n\n/**\n * same preconditions as generateKeysBetween.\n * n >= 0.\n * Returns an array of n distinct keys in sorted order.\n * If a and b are both null, returns [a0, a1, ...]\n * If one or the other is null, returns consecutive \"integer\"\n * keys. Otherwise, returns relatively short keys between\n * a and b.\n * @param {string | null | undefined} a\n * @param {string | null | undefined} b\n * @param {number} n\n * @param {string} digits\n * @return {string[]}\n */\nexport function generateNKeysBetween(a, b, n, digits = BASE_62_DIGITS) {\n if (n === 0) {\n return [];\n }\n if (n === 1) {\n return [generateKeyBetween(a, b, digits)];\n }\n if (b == null) {\n let c = generateKeyBetween(a, b, digits);\n const result = [c];\n for (let i = 0; i < n - 1; i++) {\n c = generateKeyBetween(c, b, digits);\n result.push(c);\n }\n return result;\n }\n if (a == null) {\n let c = generateKeyBetween(a, b, digits);\n const result = [c];\n for (let i = 0; i < n - 1; i++) {\n c = generateKeyBetween(a, c, digits);\n result.push(c);\n }\n result.reverse();\n return result;\n }\n const mid = Math.floor(n / 2);\n const c = generateKeyBetween(a, b, digits);\n return [\n ...generateNKeysBetween(a, c, mid, digits),\n c,\n ...generateNKeysBetween(c, b, n - mid - 1, digits),\n ];\n}\n", "import throttle from \"lodash.throttle\";\r\n\r\nimport {\r\n randomInteger,\r\n arrayToMap,\r\n toBrandedType,\r\n isDevEnv,\r\n isTestEnv,\r\n toArray,\r\n} from \"@excalidraw-modify/common\";\r\nimport { isNonDeletedElement } from \"@excalidraw-modify/element\";\r\nimport { isFrameLikeElement } from \"@excalidraw-modify/element\";\r\nimport { getElementsInGroup } from \"@excalidraw-modify/element\";\r\n\r\nimport {\r\n syncInvalidIndices,\r\n syncMovedIndices,\r\n validateFractionalIndices,\r\n} from \"@excalidraw-modify/element\";\r\n\r\nimport { getSelectedElements } from \"@excalidraw-modify/element\";\r\n\r\nimport { mutateElement, type ElementUpdate } from \"@excalidraw-modify/element\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n NonDeletedExcalidrawElement,\r\n NonDeleted,\r\n ExcalidrawFrameLikeElement,\r\n ElementsMapOrArray,\r\n SceneElementsMap,\r\n NonDeletedSceneElementsMap,\r\n OrderedExcalidrawElement,\r\n Ordered,\r\n} from \"@excalidraw-modify/element/types\";\r\n\r\nimport type {\r\n Assert,\r\n Mutable,\r\n SameType,\r\n} from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport type { AppState } from \"../../excalidraw/types\";\r\n\r\ntype SceneStateCallback = () => void;\r\ntype SceneStateCallbackRemover = () => void;\r\n\r\ntype SelectionHash = string & { __brand: \"selectionHash\" };\r\n\r\nconst getNonDeletedElements = <T extends ExcalidrawElement>(\r\n allElements: readonly T[],\r\n) => {\r\n const elementsMap = new Map() as NonDeletedSceneElementsMap;\r\n const elements: T[] = [];\r\n for (const element of allElements) {\r\n if (!element.isDeleted) {\r\n elements.push(element as NonDeleted<T>);\r\n elementsMap.set(\r\n element.id,\r\n element as Ordered<NonDeletedExcalidrawElement>,\r\n );\r\n }\r\n }\r\n return { elementsMap, elements };\r\n};\r\n\r\nconst validateIndicesThrottled = throttle(\r\n (elements: readonly ExcalidrawElement[]) => {\r\n if (isDevEnv() || isTestEnv() || window?.DEBUG_FRACTIONAL_INDICES) {\r\n validateFractionalIndices(elements, {\r\n // throw only in dev & test, to remain functional on `DEBUG_FRACTIONAL_INDICES`\r\n shouldThrow: isDevEnv() || isTestEnv(),\r\n includeBoundTextValidation: true,\r\n });\r\n }\r\n },\r\n 1000 * 60,\r\n { leading: true, trailing: false },\r\n);\r\n\r\nconst hashSelectionOpts = (\r\n opts: Parameters<InstanceType<typeof Scene>[\"getSelectedElements\"]>[0],\r\n) => {\r\n const keys = [\"includeBoundTextElement\", \"includeElementsInFrames\"] as const;\r\n\r\n type HashableKeys = Omit<typeof opts, \"selectedElementIds\" | \"elements\">;\r\n\r\n // just to ensure we're hashing all expected keys\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n type _ = Assert<\r\n SameType<\r\n Required<HashableKeys>,\r\n Pick<Required<HashableKeys>, typeof keys[number]>\r\n >\r\n >;\r\n\r\n let hash = \"\";\r\n for (const key of keys) {\r\n hash += `${key}:${opts[key] ? \"1\" : \"0\"}`;\r\n }\r\n return hash as SelectionHash;\r\n};\r\n\r\n// ideally this would be a branded type but it'd be insanely hard to work with\r\n// in our codebase\r\nexport type ExcalidrawElementsIncludingDeleted = readonly ExcalidrawElement[];\r\n\r\nexport class Scene {\r\n // ---------------------------------------------------------------------------\r\n // instance methods/props\r\n // ---------------------------------------------------------------------------\r\n\r\n private callbacks: Set<SceneStateCallback> = new Set();\r\n\r\n private nonDeletedElements: readonly Ordered<NonDeletedExcalidrawElement>[] =\r\n [];\r\n private nonDeletedElementsMap = toBrandedType<NonDeletedSceneElementsMap>(\r\n new Map(),\r\n );\r\n // ideally all elements within the scene should be wrapped around with `Ordered` type, but right now there is no real benefit doing so\r\n private elements: readonly OrderedExcalidrawElement[] = [];\r\n private nonDeletedFramesLikes: readonly NonDeleted<ExcalidrawFrameLikeElement>[] =\r\n [];\r\n private frames: readonly ExcalidrawFrameLikeElement[] = [];\r\n private elementsMap = toBrandedType<SceneElementsMap>(new Map());\r\n private selectedElementsCache: {\r\n selectedElementIds: AppState[\"selectedElementIds\"] | null;\r\n elements: readonly NonDeletedExcalidrawElement[] | null;\r\n cache: Map<SelectionHash, NonDeletedExcalidrawElement[]>;\r\n } = {\r\n selectedElementIds: null,\r\n elements: null,\r\n cache: new Map(),\r\n };\r\n /**\r\n * Random integer regenerated each scene update.\r\n *\r\n * Does not relate to elements versions, it's only a renderer\r\n * cache-invalidation nonce at the moment.\r\n */\r\n private sceneNonce: number | undefined;\r\n\r\n getSceneNonce() {\r\n return this.sceneNonce;\r\n }\r\n\r\n getNonDeletedElementsMap() {\r\n return this.nonDeletedElementsMap;\r\n }\r\n\r\n getElementsIncludingDeleted() {\r\n return this.elements;\r\n }\r\n\r\n getElementsMapIncludingDeleted() {\r\n return this.elementsMap;\r\n }\r\n\r\n getNonDeletedElements() {\r\n return this.nonDeletedElements;\r\n }\r\n\r\n getFramesIncludingDeleted() {\r\n return this.frames;\r\n }\r\n\r\n constructor(\r\n elements: ElementsMapOrArray | null = null,\r\n options?: {\r\n skipValidation?: true;\r\n },\r\n ) {\r\n if (elements) {\r\n this.replaceAllElements(elements, options);\r\n }\r\n }\r\n\r\n getSelectedElements(opts: {\r\n // NOTE can be ommitted by making Scene constructor require App instance\r\n selectedElementIds: AppState[\"selectedElementIds\"];\r\n /**\r\n * for specific cases where you need to use elements not from current\r\n * scene state. This in effect will likely result in cache-miss, and\r\n * the cache won't be updated in this case.\r\n */\r\n elements?: ElementsMapOrArray;\r\n // selection-related options\r\n includeBoundTextElement?: boolean;\r\n includeElementsInFrames?: boolean;\r\n }): NonDeleted<ExcalidrawElement>[] {\r\n const hash = hashSelectionOpts(opts);\r\n\r\n const elements = opts?.elements || this.nonDeletedElements;\r\n if (\r\n this.selectedElementsCache.elements === elements &&\r\n this.selectedElementsCache.selectedElementIds === opts.selectedElementIds\r\n ) {\r\n const cached = this.selectedElementsCache.cache.get(hash);\r\n if (cached) {\r\n return cached;\r\n }\r\n } else if (opts?.elements == null) {\r\n // if we're operating on latest scene elements and the cache is not\r\n // storing the latest elements, clear the cache\r\n this.selectedElementsCache.cache.clear();\r\n }\r\n\r\n const selectedElements = getSelectedElements(\r\n elements,\r\n { selectedElementIds: opts.selectedElementIds },\r\n opts,\r\n );\r\n\r\n // cache only if we're not using custom elements\r\n if (opts?.elements == null) {\r\n this.selectedElementsCache.selectedElementIds = opts.selectedElementIds;\r\n this.selectedElementsCache.elements = this.nonDeletedElements;\r\n this.selectedElementsCache.cache.set(hash, selectedElements);\r\n }\r\n\r\n return selectedElements;\r\n }\r\n\r\n getNonDeletedFramesLikes(): readonly NonDeleted<ExcalidrawFrameLikeElement>[] {\r\n return this.nonDeletedFramesLikes;\r\n }\r\n\r\n getElement<T extends ExcalidrawElement>(id: T[\"id\"]): T | null {\r\n return (this.elementsMap.get(id) as T | undefined) || null;\r\n }\r\n\r\n getNonDeletedElement(\r\n id: ExcalidrawElement[\"id\"],\r\n ): NonDeleted<ExcalidrawElement> | null {\r\n const element = this.getElement(id);\r\n if (element && isNonDeletedElement(element)) {\r\n return element;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * A utility method to help with updating all scene elements, with the added\r\n * performance optimization of not renewing the array if no change is made.\r\n *\r\n * Maps all current excalidraw elements, invoking the callback for each\r\n * element. The callback should either return a new mapped element, or the\r\n * original element if no changes are made. If no changes are made to any\r\n * element, this results in a no-op. Otherwise, the newly mapped elements\r\n * are set as the next scene's elements.\r\n *\r\n * @returns whether a change was made\r\n */\r\n mapElements(\r\n iteratee: (element: ExcalidrawElement) => ExcalidrawElement,\r\n ): boolean {\r\n let didChange = false;\r\n const newElements = this.elements.map((element) => {\r\n const nextElement = iteratee(element);\r\n if (nextElement !== element) {\r\n didChange = true;\r\n }\r\n return nextElement;\r\n });\r\n if (didChange) {\r\n this.replaceAllElements(newElements);\r\n }\r\n return didChange;\r\n }\r\n\r\n replaceAllElements(\r\n nextElements: ElementsMapOrArray,\r\n options?: {\r\n skipValidation?: true;\r\n },\r\n ) {\r\n // we do trust the insertion order on the map, though maybe we shouldn't and should prefer order defined by fractional indices\r\n const _nextElements = toArray(nextElements);\r\n const nextFrameLikes: ExcalidrawFrameLikeElement[] = [];\r\n\r\n if (!options?.skipValidation) {\r\n validateIndicesThrottled(_nextElements);\r\n }\r\n\r\n this.elements = syncInvalidIndices(_nextElements);\r\n this.elementsMap.clear();\r\n this.elements.forEach((element) => {\r\n if (isFrameLikeElement(element)) {\r\n nextFrameLikes.push(element);\r\n }\r\n this.elementsMap.set(element.id, element);\r\n });\r\n const nonDeletedElements = getNonDeletedElements(this.elements);\r\n this.nonDeletedElements = nonDeletedElements.elements;\r\n this.nonDeletedElementsMap = nonDeletedElements.elementsMap;\r\n\r\n this.frames = nextFrameLikes;\r\n this.nonDeletedFramesLikes = getNonDeletedElements(this.frames).elements;\r\n\r\n this.triggerUpdate();\r\n }\r\n\r\n triggerUpdate() {\r\n this.sceneNonce = randomInteger();\r\n\r\n for (const callback of Array.from(this.callbacks)) {\r\n callback();\r\n }\r\n }\r\n\r\n onUpdate(cb: SceneStateCallback): SceneStateCallbackRemover {\r\n if (this.callbacks.has(cb)) {\r\n throw new Error();\r\n }\r\n\r\n this.callbacks.add(cb);\r\n\r\n return () => {\r\n if (!this.callbacks.has(cb)) {\r\n throw new Error();\r\n }\r\n this.callbacks.delete(cb);\r\n };\r\n }\r\n\r\n destroy() {\r\n this.elements = [];\r\n this.nonDeletedElements = [];\r\n this.nonDeletedFramesLikes = [];\r\n this.frames = [];\r\n this.elementsMap.clear();\r\n this.selectedElementsCache.selectedElementIds = null;\r\n this.selectedElementsCache.elements = null;\r\n this.selectedElementsCache.cache.clear();\r\n\r\n // done not for memory leaks, but to guard against possible late fires\r\n // (I guess?)\r\n this.callbacks.clear();\r\n }\r\n\r\n insertElementAtIndex(element: ExcalidrawElement, index: number) {\r\n if (!Number.isFinite(index) || index < 0) {\r\n throw new Error(\r\n \"insertElementAtIndex can only be called with index >= 0\",\r\n );\r\n }\r\n\r\n const nextElements = [\r\n ...this.elements.slice(0, index),\r\n element,\r\n ...this.elements.slice(index),\r\n ];\r\n\r\n syncMovedIndices(nextElements, arrayToMap([element]));\r\n\r\n this.replaceAllElements(nextElements);\r\n }\r\n\r\n insertElementsAtIndex(elements: ExcalidrawElement[], index: number) {\r\n if (!elements.length) {\r\n return;\r\n }\r\n\r\n if (!Number.isFinite(index) || index < 0) {\r\n throw new Error(\r\n \"insertElementAtIndex can only be called with index >= 0\",\r\n );\r\n }\r\n\r\n const nextElements = [\r\n ...this.elements.slice(0, index),\r\n ...elements,\r\n ...this.elements.slice(index),\r\n ];\r\n\r\n syncMovedIndices(nextElements, arrayToMap(elements));\r\n\r\n this.replaceAllElements(nextElements);\r\n }\r\n\r\n insertElement = (element: ExcalidrawElement) => {\r\n const index = element.frameId\r\n ? this.getElementIndex(element.frameId)\r\n : this.elements.length;\r\n\r\n this.insertElementAtIndex(element, index);\r\n };\r\n\r\n insertElements = (elements: ExcalidrawElement[]) => {\r\n if (!elements.length) {\r\n return;\r\n }\r\n\r\n const index = elements[0]?.frameId\r\n ? this.getElementIndex(elements[0].frameId)\r\n : this.elements.length;\r\n\r\n this.insertElementsAtIndex(elements, index);\r\n };\r\n\r\n getElementIndex(elementId: string) {\r\n return this.elements.findIndex((element) => element.id === elementId);\r\n }\r\n\r\n getContainerElement = (\r\n element:\r\n | (ExcalidrawElement & {\r\n containerId: ExcalidrawElement[\"id\"] | null;\r\n })\r\n | null,\r\n ) => {\r\n if (!element) {\r\n return null;\r\n }\r\n if (element.containerId) {\r\n return this.getElement(element.containerId) || null;\r\n }\r\n return null;\r\n };\r\n\r\n getElementsFromId = (id: string): ExcalidrawElement[] => {\r\n const elementsMap = this.getNonDeletedElementsMap();\r\n // first check if the id is an element\r\n const el = elementsMap.get(id);\r\n if (el) {\r\n return [el];\r\n }\r\n\r\n // then, check if the id is a group\r\n return getElementsInGroup(elementsMap, id);\r\n };\r\n\r\n // Mutate an element with passed updates and trigger the component to update. Make sure you\r\n // are calling it either from a React event handler or within unstable_batchedUpdates().\r\n mutateElement<TElement extends Mutable<ExcalidrawElement>>(\r\n element: TElement,\r\n updates: ElementUpdate<TElement>,\r\n options: {\r\n informMutation: boolean;\r\n isDragging: boolean;\r\n } = {\r\n informMutation: true,\r\n isDragging: false,\r\n },\r\n ) {\r\n const elementsMap = this.getNonDeletedElementsMap();\r\n\r\n const { version: prevVersion } = element;\r\n const { version: nextVersion } = mutateElement(\r\n element,\r\n elementsMap,\r\n updates,\r\n options,\r\n );\r\n\r\n if (\r\n // skip if the element is not in the scene (i.e. selection)\r\n this.elementsMap.has(element.id) &&\r\n // skip if the element's version hasn't changed, as mutateElement returned the same element\r\n prevVersion !== nextVersion &&\r\n options.informMutation\r\n ) {\r\n this.triggerUpdate();\r\n }\r\n\r\n return element;\r\n }\r\n}\r\n", "import type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { getCommonBoundingBox } from \"./bounds\";\r\nimport { newElementWith } from \"./mutateElement\";\r\n\r\nimport { getSelectedElementsByGroup } from \"./groups\";\r\n\r\nimport type { ElementsMap, ExcalidrawElement } from \"./types\";\r\n\r\nexport interface Distribution {\r\n space: \"between\";\r\n axis: \"x\" | \"y\";\r\n}\r\n\r\nexport const distributeElements = (\r\n selectedElements: ExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n distribution: Distribution,\r\n appState: Readonly<AppState>,\r\n): ExcalidrawElement[] => {\r\n const [start, mid, end, extent] =\r\n distribution.axis === \"x\"\r\n ? ([\"minX\", \"midX\", \"maxX\", \"width\"] as const)\r\n : ([\"minY\", \"midY\", \"maxY\", \"height\"] as const);\r\n\r\n const bounds = getCommonBoundingBox(selectedElements);\r\n const groups = getSelectedElementsByGroup(\r\n selectedElements,\r\n elementsMap,\r\n appState,\r\n )\r\n .map((group) => [group, getCommonBoundingBox(group)] as const)\r\n .sort((a, b) => a[1][mid] - b[1][mid]);\r\n\r\n let span = 0;\r\n for (const group of groups) {\r\n span += group[1][extent];\r\n }\r\n\r\n const step = (bounds[extent] - span) / (groups.length - 1);\r\n\r\n if (step < 0) {\r\n // If we have a negative step, we'll need to distribute from centers\r\n // rather than from gaps. Buckle up, this is a weird one.\r\n\r\n // Get indices of boxes that define start and end of our bounding box\r\n const index0 = groups.findIndex((g) => g[1][start] === bounds[start]);\r\n const index1 = groups.findIndex((g) => g[1][end] === bounds[end]);\r\n\r\n // Get our step, based on the distance between the center points of our\r\n // start and end boxes\r\n const step =\r\n (groups[index1][1][mid] - groups[index0][1][mid]) / (groups.length - 1);\r\n\r\n let pos = groups[index0][1][mid];\r\n\r\n return groups.flatMap(([group, box], index) => {\r\n const translation = {\r\n x: 0,\r\n y: 0,\r\n };\r\n\r\n // Don't move our start and end boxes\r\n if (index !== index0 && index !== index1) {\r\n pos += step;\r\n translation[distribution.axis] = pos - box[mid];\r\n }\r\n\r\n return group.map((element) =>\r\n newElementWith(element, {\r\n x: element.x + translation.x,\r\n y: element.y + translation.y,\r\n }),\r\n );\r\n });\r\n }\r\n\r\n // Distribute from gaps\r\n\r\n let pos = bounds[start];\r\n\r\n return groups.flatMap(([group, box]) => {\r\n const translation = {\r\n x: 0,\r\n y: 0,\r\n };\r\n\r\n translation[distribution.axis] = pos - box[start];\r\n\r\n pos += step;\r\n pos += box[extent];\r\n\r\n return group.map((element) =>\r\n newElementWith(element, {\r\n x: element.x + translation.x,\r\n y: element.y + translation.y,\r\n }),\r\n );\r\n });\r\n};\r\n", "import {\r\n type Bounds,\r\n TEXT_AUTOWRAP_THRESHOLD,\r\n getGridPoint,\r\n getFontString,\r\n DRAGGING_THRESHOLD,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type {\r\n AppState,\r\n NormalizedZoomValue,\r\n NullableGridSize,\r\n PointerDownState,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type { NonDeletedExcalidrawElement } from \"@excalidraw-modify/element/types\";\r\n\r\nimport { unbindBindingElement, updateBoundElements } from \"./binding\";\r\nimport { getCommonBounds } from \"./bounds\";\r\nimport { getPerfectElementSize } from \"./sizeHelpers\";\r\nimport { getBoundTextElement } from \"./textElement\";\r\nimport { getMinTextElementWidth } from \"./textMeasurements\";\r\nimport {\r\n isArrowElement,\r\n isElbowArrow,\r\n isFrameLikeElement,\r\n isImageElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\nimport type { ExcalidrawElement } from \"./types\";\r\n\r\nexport const dragSelectedElements = (\r\n pointerDownState: PointerDownState,\r\n _selectedElements: NonDeletedExcalidrawElement[],\r\n offset: { x: number; y: number },\r\n scene: Scene,\r\n snapOffset: {\r\n x: number;\r\n y: number;\r\n },\r\n gridSize: NullableGridSize,\r\n) => {\r\n if (\r\n _selectedElements.length === 1 &&\r\n isElbowArrow(_selectedElements[0]) &&\r\n (_selectedElements[0].startBinding || _selectedElements[0].endBinding)\r\n ) {\r\n return;\r\n }\r\n\r\n const selectedElements = _selectedElements.filter((element) => {\r\n if (isElbowArrow(element) && element.startBinding && element.endBinding) {\r\n const startElement = _selectedElements.find(\r\n (el) => el.id === element.startBinding?.elementId,\r\n );\r\n const endElement = _selectedElements.find(\r\n (el) => el.id === element.endBinding?.elementId,\r\n );\r\n\r\n return startElement && endElement;\r\n }\r\n\r\n return true;\r\n });\r\n\r\n // we do not want a frame and its elements to be selected at the same time\r\n // but when it happens (due to some bug), we want to avoid updating element\r\n // in the frame twice, hence the use of set\r\n const elementsToUpdate = new Set<NonDeletedExcalidrawElement>(\r\n selectedElements,\r\n );\r\n const frames = selectedElements\r\n .filter((e) => isFrameLikeElement(e))\r\n .map((f) => f.id);\r\n\r\n if (frames.length > 0) {\r\n for (const element of scene.getNonDeletedElements()) {\r\n if (element.frameId !== null && frames.includes(element.frameId)) {\r\n elementsToUpdate.add(element);\r\n }\r\n }\r\n }\r\n\r\n const origElements: ExcalidrawElement[] = [];\r\n\r\n for (const element of elementsToUpdate) {\r\n const origElement = pointerDownState.originalElements.get(element.id);\r\n // if original element is not set (e.g. when you duplicate during a drag\r\n // operation), exit to avoid undefined behavior\r\n if (!origElement) {\r\n return;\r\n }\r\n origElements.push(origElement);\r\n }\r\n\r\n const adjustedOffset = calculateOffset(\r\n getCommonBounds(origElements),\r\n offset,\r\n snapOffset,\r\n gridSize,\r\n );\r\n\r\n const elementsToUpdateIds = new Set(\r\n Array.from(elementsToUpdate, (el) => el.id),\r\n );\r\n\r\n elementsToUpdate.forEach((element) => {\r\n const isArrow = !isArrowElement(element);\r\n const isStartBoundElementSelected =\r\n isArrow ||\r\n (element.startBinding\r\n ? elementsToUpdateIds.has(element.startBinding.elementId)\r\n : false);\r\n const isEndBoundElementSelected =\r\n isArrow ||\r\n (element.endBinding\r\n ? elementsToUpdateIds.has(element.endBinding.elementId)\r\n : false);\r\n\r\n if (!isArrowElement(element)) {\r\n updateElementCoords(pointerDownState, element, scene, adjustedOffset);\r\n\r\n // skip arrow labels since we calculate its position during render\r\n const textElement = getBoundTextElement(\r\n element,\r\n scene.getNonDeletedElementsMap(),\r\n );\r\n if (textElement) {\r\n updateElementCoords(\r\n pointerDownState,\r\n textElement,\r\n scene,\r\n adjustedOffset,\r\n );\r\n }\r\n updateBoundElements(element, scene, {\r\n simultaneouslyUpdated: Array.from(elementsToUpdate),\r\n });\r\n } else if (\r\n // NOTE: Add a little initial drag to the arrow dragging when the arrow\r\n // is the single element being dragged to avoid accidentally unbinding\r\n // the arrow when the user just wants to select it.\r\n\r\n elementsToUpdate.size > 1 ||\r\n Math.max(Math.abs(adjustedOffset.x), Math.abs(adjustedOffset.y)) >\r\n DRAGGING_THRESHOLD ||\r\n (!element.startBinding && !element.endBinding)\r\n ) {\r\n updateElementCoords(pointerDownState, element, scene, adjustedOffset);\r\n\r\n const shouldUnbindStart =\r\n element.startBinding && !isStartBoundElementSelected;\r\n const shouldUnbindEnd = element.endBinding && !isEndBoundElementSelected;\r\n if (shouldUnbindStart || shouldUnbindEnd) {\r\n // NOTE: Moving the bound arrow should unbind it, otherwise we would\r\n // have weird situations, like 0 lenght arrow when the user moves\r\n // the arrow outside a filled shape suddenly forcing the arrow start\r\n // and end point to jump \"outside\" the shape.\r\n if (shouldUnbindStart) {\r\n unbindBindingElement(element, \"start\", scene);\r\n }\r\n if (shouldUnbindEnd) {\r\n unbindBindingElement(element, \"end\", scene);\r\n }\r\n }\r\n }\r\n });\r\n};\r\n\r\nconst calculateOffset = (\r\n commonBounds: Bounds,\r\n dragOffset: { x: number; y: number },\r\n snapOffset: { x: number; y: number },\r\n gridSize: NullableGridSize,\r\n): { x: number; y: number } => {\r\n const [x, y] = commonBounds;\r\n let nextX = x + dragOffset.x + snapOffset.x;\r\n let nextY = y + dragOffset.y + snapOffset.y;\r\n\r\n if (snapOffset.x === 0 || snapOffset.y === 0) {\r\n const [nextGridX, nextGridY] = getGridPoint(\r\n x + dragOffset.x,\r\n y + dragOffset.y,\r\n gridSize,\r\n );\r\n\r\n if (snapOffset.x === 0) {\r\n nextX = nextGridX;\r\n }\r\n\r\n if (snapOffset.y === 0) {\r\n nextY = nextGridY;\r\n }\r\n }\r\n return {\r\n x: nextX - x,\r\n y: nextY - y,\r\n };\r\n};\r\n\r\nconst updateElementCoords = (\r\n pointerDownState: PointerDownState,\r\n element: NonDeletedExcalidrawElement,\r\n scene: Scene,\r\n dragOffset: { x: number; y: number },\r\n) => {\r\n const originalElement =\r\n pointerDownState.originalElements.get(element.id) ?? element;\r\n\r\n const nextX = originalElement.x + dragOffset.x;\r\n const nextY = originalElement.y + dragOffset.y;\r\n\r\n scene.mutateElement(element, {\r\n x: nextX,\r\n y: nextY,\r\n });\r\n};\r\n\r\nexport const getDragOffsetXY = (\r\n selectedElements: NonDeletedExcalidrawElement[],\r\n x: number,\r\n y: number,\r\n): [number, number] => {\r\n const [x1, y1] = getCommonBounds(selectedElements);\r\n return [x - x1, y - y1];\r\n};\r\n\r\nexport const dragNewElement = ({\r\n newElement,\r\n elementType,\r\n originX,\r\n originY,\r\n x,\r\n y,\r\n width,\r\n height,\r\n shouldMaintainAspectRatio,\r\n shouldResizeFromCenter,\r\n zoom,\r\n scene,\r\n widthAspectRatio = null,\r\n originOffset = null,\r\n informMutation = true,\r\n}: {\r\n newElement: NonDeletedExcalidrawElement;\r\n elementType: AppState[\"activeTool\"][\"type\"];\r\n originX: number;\r\n originY: number;\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n shouldMaintainAspectRatio: boolean;\r\n shouldResizeFromCenter: boolean;\r\n zoom: NormalizedZoomValue;\r\n scene: Scene;\r\n /** whether to keep given aspect ratio when `isResizeWithSidesSameLength` is\r\n true */\r\n widthAspectRatio?: number | null;\r\n originOffset?: {\r\n x: number;\r\n y: number;\r\n } | null;\r\n informMutation?: boolean;\r\n}) => {\r\n if (shouldMaintainAspectRatio && newElement.type !== \"selection\") {\r\n if (widthAspectRatio) {\r\n height = width / widthAspectRatio;\r\n } else {\r\n // Depending on where the cursor is at (x, y) relative to where the starting point is\r\n // (originX, originY), we use ONLY width or height to control size increase.\r\n // This allows the cursor to always \"stick\" to one of the sides of the bounding box.\r\n if (Math.abs(y - originY) > Math.abs(x - originX)) {\r\n ({ width, height } = getPerfectElementSize(\r\n elementType,\r\n height,\r\n x < originX ? -width : width,\r\n ));\r\n } else {\r\n ({ width, height } = getPerfectElementSize(\r\n elementType,\r\n width,\r\n y < originY ? -height : height,\r\n ));\r\n }\r\n\r\n if (height < 0) {\r\n height = -height;\r\n }\r\n }\r\n }\r\n\r\n let newX = x < originX ? originX - width : originX;\r\n let newY = y < originY ? originY - height : originY;\r\n\r\n if (shouldResizeFromCenter) {\r\n width += width;\r\n height += height;\r\n newX = originX - width / 2;\r\n newY = originY - height / 2;\r\n }\r\n\r\n let textAutoResize = null;\r\n\r\n if (isTextElement(newElement)) {\r\n height = newElement.height;\r\n const minWidth = getMinTextElementWidth(\r\n getFontString({\r\n fontSize: newElement.fontSize,\r\n fontFamily: newElement.fontFamily,\r\n }),\r\n newElement.lineHeight,\r\n );\r\n width = Math.max(width, minWidth);\r\n\r\n if (Math.abs(x - originX) > TEXT_AUTOWRAP_THRESHOLD / zoom) {\r\n textAutoResize = {\r\n autoResize: false,\r\n };\r\n }\r\n\r\n newY = originY;\r\n if (shouldResizeFromCenter) {\r\n newX = originX - width / 2;\r\n }\r\n }\r\n\r\n if (width !== 0 && height !== 0) {\r\n let imageInitialDimension = null;\r\n if (isImageElement(newElement)) {\r\n imageInitialDimension = {\r\n initialWidth: width,\r\n initialHeight: height,\r\n };\r\n }\r\n\r\n scene.mutateElement(\r\n newElement,\r\n {\r\n x: newX + (originOffset?.x ?? 0),\r\n y: newY + (originOffset?.y ?? 0),\r\n width,\r\n height,\r\n ...textAutoResize,\r\n ...imageInitialDimension,\r\n },\r\n { informMutation, isDragging: false },\r\n );\r\n }\r\n};\r\n", "/**\r\n * Create and link between shapes.\r\n */\r\n\r\nimport { ELEMENT_LINK_KEY, normalizeLink } from \"@excalidraw-modify/common\";\r\n\r\nimport type { AppProps, AppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { elementsAreInSameGroup } from \"./groups\";\r\n\r\nimport type { ExcalidrawElement } from \"./types\";\r\n\r\nexport const defaultGetElementLinkFromSelection: Exclude<\r\n AppProps[\"generateLinkForSelection\"],\r\n undefined\r\n> = (id, type) => {\r\n const url = window.location.href;\r\n\r\n try {\r\n const link = new URL(url);\r\n link.searchParams.set(ELEMENT_LINK_KEY, id);\r\n\r\n return normalizeLink(link.toString());\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n\r\n return normalizeLink(url);\r\n};\r\n\r\nexport const getLinkIdAndTypeFromSelection = (\r\n selectedElements: ExcalidrawElement[],\r\n appState: AppState,\r\n): {\r\n id: string;\r\n type: \"element\" | \"group\";\r\n} | null => {\r\n if (\r\n selectedElements.length > 0 &&\r\n canCreateLinkFromElements(selectedElements)\r\n ) {\r\n if (selectedElements.length === 1) {\r\n return {\r\n id: selectedElements[0].id,\r\n type: \"element\",\r\n };\r\n }\r\n\r\n if (selectedElements.length > 1) {\r\n const selectedGroupId = Object.keys(appState.selectedGroupIds)[0];\r\n\r\n if (selectedGroupId) {\r\n return {\r\n id: selectedGroupId,\r\n type: \"group\",\r\n };\r\n }\r\n return {\r\n id: selectedElements[0].groupIds[0],\r\n type: \"group\",\r\n };\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const canCreateLinkFromElements = (\r\n selectedElements: ExcalidrawElement[],\r\n) => {\r\n if (selectedElements.length === 1) {\r\n return true;\r\n }\r\n\r\n if (selectedElements.length > 1 && elementsAreInSameGroup(selectedElements)) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport const isElementLink = (url: string) => {\r\n try {\r\n const _url = new URL(url);\r\n return (\r\n _url.searchParams.has(ELEMENT_LINK_KEY) &&\r\n _url.host === window.location.host\r\n );\r\n } catch (error) {\r\n return false;\r\n }\r\n};\r\n\r\nexport const parseElementLinkFromURL = (url: string) => {\r\n try {\r\n const { searchParams } = new URL(url);\r\n if (searchParams.has(ELEMENT_LINK_KEY)) {\r\n const id = searchParams.get(ELEMENT_LINK_KEY);\r\n return id;\r\n }\r\n } catch {}\r\n\r\n return null;\r\n};\r\n", "import {\r\n FONT_FAMILY,\r\n VERTICAL_ALIGN,\r\n escapeDoubleQuotes,\r\n getFontString,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { ExcalidrawProps } from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { MarkRequired } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport { newTextElement } from \"./newElement\";\r\nimport { wrapText } from \"./textWrapping\";\r\nimport { isIframeElement } from \"./typeChecks\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n ExcalidrawIframeLikeElement,\r\n IframeData,\r\n} from \"./types\";\r\n\r\ntype IframeDataWithSandbox = MarkRequired<IframeData, \"sandbox\">;\r\n\r\nconst embeddedLinkCache = new Map<string, IframeDataWithSandbox>();\r\n\r\nconst RE_YOUTUBE =\r\n /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?youtu(?:be\\.com|\\.be)\\/(embed\\/|watch\\?v=|shorts\\/|playlist\\?list=|embed\\/videoseries\\?list=)?([a-zA-Z0-9_-]+)/;\r\n\r\nconst RE_VIMEO =\r\n /^(?:http(?:s)?:\\/\\/)?(?:(?:w){3}\\.)?(?:player\\.)?vimeo\\.com\\/(?:video\\/)?([^?\\s]+)(?:\\?.*)?$/;\r\nconst RE_FIGMA = /^https:\\/\\/(?:www\\.)?figma\\.com/;\r\n\r\nconst RE_GH_GIST = /^https:\\/\\/gist\\.github\\.com\\/([\\w_-]+)\\/([\\w_-]+)/;\r\nconst RE_GH_GIST_EMBED =\r\n /^<script[\\s\\S]*?\\ssrc=[\"'](https:\\/\\/gist\\.github\\.com\\/.*?)\\.js[\"']/i;\r\n\r\nconst RE_MSFORMS = /^(?:https?:\\/\\/)?forms\\.microsoft\\.com\\//;\r\n\r\n// not anchored to start to allow <blockquote> twitter embeds\r\nconst RE_TWITTER =\r\n /(?:https?:\\/\\/)?(?:(?:w){3}\\.)?(?:twitter|x)\\.com\\/[^/]+\\/status\\/(\\d+)/;\r\nconst RE_TWITTER_EMBED =\r\n /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:twitter|x)\\.com\\/[^\"']*)/i;\r\n\r\nconst RE_VALTOWN =\r\n /^https:\\/\\/(?:www\\.)?val\\.town\\/(v|embed)\\/[a-zA-Z_$][0-9a-zA-Z_$]+\\.[a-zA-Z_$][0-9a-zA-Z_$]+/;\r\n\r\nconst RE_GENERIC_EMBED =\r\n /^<(?:iframe|blockquote)[\\s\\S]*?\\s(?:src|href)=[\"']([^\"']*)[\"'][\\s\\S]*?>$/i;\r\n\r\nconst RE_GIPHY =\r\n /giphy.com\\/(?:clips|embed|gifs)\\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;\r\n\r\nconst RE_REDDIT =\r\n /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?reddit\\.com\\/r\\/([a-zA-Z0-9_]+)\\/comments\\/([a-zA-Z0-9_]+)\\/([a-zA-Z0-9_]+)\\/?(?:\\?[^#\\s]*)?(?:#[^\\s]*)?$/;\r\n\r\nconst RE_REDDIT_EMBED =\r\n /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:www\\.)?reddit\\.com\\/[^\"']*)/i;\r\n\r\nconst parseYouTubeTimestamp = (url: string): number => {\r\n let timeParam: string | null | undefined;\r\n\r\n try {\r\n const urlObj = new URL(url.startsWith(\"http\") ? url : `https://${url}`);\r\n timeParam =\r\n urlObj.searchParams.get(\"t\") || urlObj.searchParams.get(\"start\");\r\n } catch (error) {\r\n const timeMatch = url.match(/[?&#](?:t|start)=([^&#\\s]+)/);\r\n timeParam = timeMatch?.[1];\r\n }\r\n\r\n if (!timeParam) {\r\n return 0;\r\n }\r\n\r\n if (/^\\d+$/.test(timeParam)) {\r\n return parseInt(timeParam, 10);\r\n }\r\n\r\n const timeMatch = timeParam.match(/^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/);\r\n if (!timeMatch) {\r\n return 0;\r\n }\r\n\r\n const [, hours = \"0\", minutes = \"0\", seconds = \"0\"] = timeMatch;\r\n return parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds);\r\n};\r\n\r\nconst ALLOWED_DOMAINS = new Set([\r\n \"youtube.com\",\r\n \"youtu.be\",\r\n \"vimeo.com\",\r\n \"player.vimeo.com\",\r\n \"figma.com\",\r\n \"link.excalidraw.com\",\r\n \"gist.github.com\",\r\n \"twitter.com\",\r\n \"x.com\",\r\n \"*.simplepdf.eu\",\r\n \"stackblitz.com\",\r\n \"val.town\",\r\n \"giphy.com\",\r\n \"reddit.com\",\r\n \"forms.microsoft.com\",\r\n]);\r\n\r\nconst ALLOW_SAME_ORIGIN = new Set([\r\n \"youtube.com\",\r\n \"youtu.be\",\r\n \"vimeo.com\",\r\n \"player.vimeo.com\",\r\n \"figma.com\",\r\n \"twitter.com\",\r\n \"x.com\",\r\n \"*.simplepdf.eu\",\r\n \"stackblitz.com\",\r\n \"reddit.com\",\r\n \"forms.microsoft.com\",\r\n]);\r\n\r\nexport const createSrcDoc = (body: string) => {\r\n return `<html><body>${body}</body></html>`;\r\n};\r\n\r\nexport const getEmbedLink = (\r\n link: string | null | undefined,\r\n): IframeDataWithSandbox | null => {\r\n if (!link) {\r\n return null;\r\n }\r\n\r\n if (embeddedLinkCache.has(link)) {\r\n return embeddedLinkCache.get(link)!;\r\n }\r\n\r\n const originalLink = link;\r\n\r\n const allowSameOrigin = ALLOW_SAME_ORIGIN.has(\r\n matchHostname(link, ALLOW_SAME_ORIGIN) || \"\",\r\n );\r\n\r\n let type: \"video\" | \"generic\" = \"generic\";\r\n let aspectRatio = { w: 560, h: 840 };\r\n const ytLink = link.match(RE_YOUTUBE);\r\n if (ytLink?.[2]) {\r\n const startTime = parseYouTubeTimestamp(originalLink);\r\n const time = startTime > 0 ? `&start=${startTime}` : ``;\r\n const isPortrait = link.includes(\"shorts\");\r\n type = \"video\";\r\n switch (ytLink[1]) {\r\n case \"embed/\":\r\n case \"watch?v=\":\r\n case \"shorts/\":\r\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\r\n break;\r\n case \"playlist?list=\":\r\n case \"embed/videoseries?list=\":\r\n link = `https://www.youtube.com/embed/videoseries?list=${ytLink[2]}&enablejsapi=1${time}`;\r\n break;\r\n default:\r\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\r\n break;\r\n }\r\n aspectRatio = isPortrait ? { w: 315, h: 560 } : { w: 560, h: 315 };\r\n embeddedLinkCache.set(originalLink, {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n });\r\n return {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n };\r\n }\r\n\r\n const vimeoLink = link.match(RE_VIMEO);\r\n if (vimeoLink?.[1]) {\r\n const target = vimeoLink?.[1];\r\n const error = !/^\\d+$/.test(target)\r\n ? new URIError(\"Invalid embed link format\")\r\n : undefined;\r\n type = \"video\";\r\n link = `https://player.vimeo.com/video/${target}?api=1`;\r\n aspectRatio = { w: 560, h: 315 };\r\n //warning deliberately ommited so it is displayed only once per link\r\n //same link next time will be served from cache\r\n embeddedLinkCache.set(originalLink, {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n });\r\n return {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n error,\r\n sandbox: { allowSameOrigin },\r\n };\r\n }\r\n\r\n const figmaLink = link.match(RE_FIGMA);\r\n if (figmaLink) {\r\n type = \"generic\";\r\n link = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(\r\n link,\r\n )}`;\r\n aspectRatio = { w: 550, h: 550 };\r\n embeddedLinkCache.set(originalLink, {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n });\r\n return {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n };\r\n }\r\n\r\n const valLink = link.match(RE_VALTOWN);\r\n if (valLink) {\r\n link =\r\n valLink[1] === \"embed\" ? valLink[0] : valLink[0].replace(\"/v\", \"/embed\");\r\n embeddedLinkCache.set(originalLink, {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n });\r\n return {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n };\r\n }\r\n\r\n if (RE_MSFORMS.test(link) && !link.includes(\"embed=true\")) {\r\n link += link.includes(\"?\") ? \"&embed=true\" : \"?embed=true\";\r\n }\r\n\r\n if (RE_TWITTER.test(link)) {\r\n const postId = link.match(RE_TWITTER)![1];\r\n // the embed srcdoc still supports twitter.com domain only.\r\n // Note that we don't attempt to parse the username as it can consist of\r\n // non-latin1 characters, and the username in the url can be set to anything\r\n // without affecting the embed.\r\n const safeURL = escapeDoubleQuotes(\r\n `https://twitter.com/x/status/${postId}`,\r\n );\r\n\r\n const ret: IframeDataWithSandbox = {\r\n type: \"document\",\r\n srcdoc: (theme: string) =>\r\n createSrcDoc(\r\n `<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>`,\r\n ),\r\n intrinsicSize: { w: 480, h: 480 },\r\n sandbox: { allowSameOrigin },\r\n };\r\n embeddedLinkCache.set(originalLink, ret);\r\n return ret;\r\n }\r\n\r\n if (RE_REDDIT.test(link)) {\r\n const [, page, postId, title] = link.match(RE_REDDIT)!;\r\n const safeURL = escapeDoubleQuotes(\r\n `https://reddit.com/r/${page}/comments/${postId}/${title}`,\r\n );\r\n const ret: IframeDataWithSandbox = {\r\n type: \"document\",\r\n srcdoc: (theme: string) =>\r\n createSrcDoc(\r\n `<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>`,\r\n ),\r\n intrinsicSize: { w: 480, h: 480 },\r\n sandbox: { allowSameOrigin },\r\n };\r\n embeddedLinkCache.set(originalLink, ret);\r\n return ret;\r\n }\r\n\r\n if (RE_GH_GIST.test(link)) {\r\n const [, user, gistId] = link.match(RE_GH_GIST)!;\r\n const safeURL = escapeDoubleQuotes(\r\n `https://gist.github.com/${user}/${gistId}`,\r\n );\r\n const ret: IframeDataWithSandbox = {\r\n type: \"document\",\r\n srcdoc: () =>\r\n createSrcDoc(`\r\n <script src=\"${safeURL}.js\"></script>\r\n <style type=\"text/css\">\r\n * { margin: 0px; }\r\n table, .gist { height: 100%; }\r\n .gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\r\n </style>\r\n `),\r\n intrinsicSize: { w: 550, h: 720 },\r\n sandbox: { allowSameOrigin },\r\n };\r\n embeddedLinkCache.set(link, ret);\r\n return ret;\r\n }\r\n\r\n embeddedLinkCache.set(link, {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n });\r\n return {\r\n link,\r\n intrinsicSize: aspectRatio,\r\n type,\r\n sandbox: { allowSameOrigin },\r\n };\r\n};\r\n\r\nexport const createPlaceholderEmbeddableLabel = (\r\n element: ExcalidrawIframeLikeElement,\r\n): ExcalidrawElement => {\r\n let text: string;\r\n if (isIframeElement(element)) {\r\n text = \"IFrame element\";\r\n } else {\r\n text =\r\n !element.link || element?.link === \"\" ? \"Empty Web-Embed\" : element.link;\r\n }\r\n\r\n const fontSize = Math.max(\r\n Math.min(element.width / 2, element.width / text.length),\r\n element.width / 30,\r\n );\r\n const fontFamily = FONT_FAMILY.Helvetica;\r\n\r\n const fontString = getFontString({\r\n fontSize,\r\n fontFamily,\r\n });\r\n\r\n return newTextElement({\r\n x: element.x + element.width / 2,\r\n y: element.y + element.height / 2,\r\n strokeColor:\r\n element.strokeColor !== \"transparent\" ? element.strokeColor : \"black\",\r\n backgroundColor: \"transparent\",\r\n fontFamily,\r\n fontSize,\r\n text: wrapText(text, fontString, element.width - 20),\r\n textAlign: \"center\",\r\n verticalAlign: VERTICAL_ALIGN.MIDDLE,\r\n angle: element.angle ?? 0,\r\n });\r\n};\r\n\r\nconst matchHostname = (\r\n url: string,\r\n /** using a Set assumes it already contains normalized bare domains */\r\n allowedHostnames: Set<string> | string,\r\n): string | null => {\r\n try {\r\n const { hostname } = new URL(url);\r\n\r\n const bareDomain = hostname.replace(/^www\\./, \"\");\r\n\r\n if (allowedHostnames instanceof Set) {\r\n if (ALLOWED_DOMAINS.has(bareDomain)) {\r\n return bareDomain;\r\n }\r\n\r\n const bareDomainWithFirstSubdomainWildcarded = bareDomain.replace(\r\n /^([^.]+)/,\r\n \"*\",\r\n );\r\n if (ALLOWED_DOMAINS.has(bareDomainWithFirstSubdomainWildcarded)) {\r\n return bareDomainWithFirstSubdomainWildcarded;\r\n }\r\n return null;\r\n }\r\n\r\n const bareAllowedHostname = allowedHostnames.replace(/^www\\./, \"\");\r\n if (bareDomain === bareAllowedHostname) {\r\n return bareAllowedHostname;\r\n }\r\n } catch (error) {\r\n // ignore\r\n }\r\n return null;\r\n};\r\n\r\nexport const maybeParseEmbedSrc = (str: string): string => {\r\n const twitterMatch = str.match(RE_TWITTER_EMBED);\r\n if (twitterMatch && twitterMatch.length === 2) {\r\n return twitterMatch[1];\r\n }\r\n\r\n const redditMatch = str.match(RE_REDDIT_EMBED);\r\n if (redditMatch && redditMatch.length === 2) {\r\n return redditMatch[1];\r\n }\r\n\r\n const gistMatch = str.match(RE_GH_GIST_EMBED);\r\n if (gistMatch && gistMatch.length === 2) {\r\n return gistMatch[1];\r\n }\r\n\r\n if (RE_GIPHY.test(str)) {\r\n return `https://giphy.com/embed/${RE_GIPHY.exec(str)![1]}`;\r\n }\r\n\r\n const match = str.match(RE_GENERIC_EMBED);\r\n if (match && match.length === 2) {\r\n return match[1];\r\n }\r\n\r\n return str;\r\n};\r\n\r\nexport const embeddableURLValidator = (\r\n url: string | null | undefined,\r\n validateEmbeddable: ExcalidrawProps[\"validateEmbeddable\"],\r\n): boolean => {\r\n if (!url) {\r\n return false;\r\n }\r\n if (validateEmbeddable != null) {\r\n if (typeof validateEmbeddable === \"function\") {\r\n const ret = validateEmbeddable(url);\r\n // if return value is undefined, leave validation to default\r\n if (typeof ret === \"boolean\") {\r\n return ret;\r\n }\r\n } else if (typeof validateEmbeddable === \"boolean\") {\r\n return validateEmbeddable;\r\n } else if (validateEmbeddable instanceof RegExp) {\r\n return validateEmbeddable.test(url);\r\n } else if (Array.isArray(validateEmbeddable)) {\r\n for (const domain of validateEmbeddable) {\r\n if (domain instanceof RegExp) {\r\n if (url.match(domain)) {\r\n return true;\r\n }\r\n } else if (matchHostname(url, domain)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n }\r\n\r\n return !!matchHostname(url, ALLOWED_DOMAINS);\r\n};\r\n", "import {\r\n DEFAULT_ELEMENT_PROPS,\r\n DEFAULT_FONT_FAMILY,\r\n DEFAULT_FONT_SIZE,\r\n DEFAULT_TEXT_ALIGN,\r\n DEFAULT_VERTICAL_ALIGN,\r\n VERTICAL_ALIGN,\r\n randomInteger,\r\n randomId,\r\n getFontString,\r\n getUpdatedTimestamp,\r\n getLineHeight,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport type { MarkOptional, Merge } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport {\r\n getElementAbsoluteCoords,\r\n getResizedElementAbsoluteCoords,\r\n} from \"./bounds\";\r\nimport { newElementWith } from \"./mutateElement\";\r\nimport { getBoundTextMaxWidth } from \"./textElement\";\r\nimport { normalizeText, measureText } from \"./textMeasurements\";\r\nimport { wrapText } from \"./textWrapping\";\r\n\r\nimport { isLineElement } from \"./typeChecks\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n ExcalidrawImageElement,\r\n ExcalidrawTextElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawGenericElement,\r\n NonDeleted,\r\n TextAlign,\r\n VerticalAlign,\r\n Arrowhead,\r\n ExcalidrawFreeDrawElement,\r\n FontFamilyValues,\r\n ExcalidrawTextContainer,\r\n ExcalidrawFrameElement,\r\n ExcalidrawEmbeddableElement,\r\n ExcalidrawMagicFrameElement,\r\n ExcalidrawIframeElement,\r\n ElementsMap,\r\n ExcalidrawArrowElement,\r\n ExcalidrawElbowArrowElement,\r\n ExcalidrawLineElement,\r\n} from \"./types\";\r\n\r\nexport type ElementConstructorOpts = MarkOptional<\r\n Omit<ExcalidrawGenericElement, \"id\" | \"type\" | \"isDeleted\" | \"updated\">,\r\n | \"width\"\r\n | \"height\"\r\n | \"angle\"\r\n | \"groupIds\"\r\n | \"frameId\"\r\n | \"index\"\r\n | \"boundElements\"\r\n | \"seed\"\r\n | \"version\"\r\n | \"versionNonce\"\r\n | \"link\"\r\n | \"strokeStyle\"\r\n | \"fillStyle\"\r\n | \"strokeColor\"\r\n | \"backgroundColor\"\r\n | \"roughness\"\r\n | \"strokeWidth\"\r\n | \"roundness\"\r\n | \"locked\"\r\n | \"opacity\"\r\n | \"showResizeHandles\"\r\n | \"customData\"\r\n>;\r\n\r\nconst _newElementBase = <T extends ExcalidrawElement>(\r\n type: T[\"type\"],\r\n {\r\n x,\r\n y,\r\n strokeColor = DEFAULT_ELEMENT_PROPS.strokeColor,\r\n backgroundColor = DEFAULT_ELEMENT_PROPS.backgroundColor,\r\n fillStyle = DEFAULT_ELEMENT_PROPS.fillStyle,\r\n strokeWidth = DEFAULT_ELEMENT_PROPS.strokeWidth,\r\n strokeStyle = DEFAULT_ELEMENT_PROPS.strokeStyle,\r\n roughness = DEFAULT_ELEMENT_PROPS.roughness,\r\n opacity = DEFAULT_ELEMENT_PROPS.opacity,\r\n width = 0,\r\n height = 0,\r\n angle = 0 as Radians,\r\n groupIds = [],\r\n frameId = null,\r\n index = null,\r\n roundness = null,\r\n boundElements = null,\r\n link = null,\r\n locked = DEFAULT_ELEMENT_PROPS.locked,\r\n showResizeHandles = true,\r\n ...rest\r\n }: ElementConstructorOpts & Omit<Partial<ExcalidrawGenericElement>, \"type\">,\r\n) => {\r\n // NOTE (mtolmacs): This is a temporary check to detect extremely large\r\n // element position or sizing\r\n if (\r\n x < -1e6 ||\r\n x > 1e6 ||\r\n y < -1e6 ||\r\n y > 1e6 ||\r\n width < -1e6 ||\r\n width > 1e6 ||\r\n height < -1e6 ||\r\n height > 1e6\r\n ) {\r\n console.error(\"New element size or position is too large\", {\r\n x,\r\n y,\r\n width,\r\n height,\r\n // @ts-ignore\r\n points: rest.points,\r\n });\r\n }\r\n\r\n // assign type to guard against excess properties\r\n const element: Merge<ExcalidrawGenericElement, { type: T[\"type\"] }> = {\r\n id: rest.id || randomId(),\r\n type,\r\n x,\r\n y,\r\n width,\r\n height,\r\n angle,\r\n strokeColor,\r\n backgroundColor,\r\n fillStyle,\r\n strokeWidth,\r\n strokeStyle,\r\n roughness,\r\n opacity,\r\n groupIds,\r\n frameId,\r\n index,\r\n roundness,\r\n seed: rest.seed ?? randomInteger(),\r\n version: rest.version || 1,\r\n versionNonce: rest.versionNonce ?? 0,\r\n isDeleted: false as false,\r\n boundElements,\r\n updated: getUpdatedTimestamp(),\r\n link,\r\n locked,\r\n showResizeHandles,\r\n customData: rest.customData,\r\n };\r\n return element;\r\n};\r\n\r\nexport const newElement = (\r\n opts: {\r\n type: ExcalidrawGenericElement[\"type\"];\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawGenericElement> =>\r\n _newElementBase<ExcalidrawGenericElement>(opts.type, opts);\r\n\r\nexport const newEmbeddableElement = (\r\n opts: {\r\n type: \"embeddable\";\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawEmbeddableElement> => {\r\n return _newElementBase<ExcalidrawEmbeddableElement>(\"embeddable\", opts);\r\n};\r\n\r\nexport const newIframeElement = (\r\n opts: {\r\n type: \"iframe\";\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawIframeElement> => {\r\n return {\r\n ..._newElementBase<ExcalidrawIframeElement>(\"iframe\", opts),\r\n };\r\n};\r\n\r\nexport const newFrameElement = (\r\n opts: {\r\n name?: string;\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawFrameElement> => {\r\n const frameElement = newElementWith(\r\n {\r\n ..._newElementBase<ExcalidrawFrameElement>(\"frame\", opts),\r\n type: \"frame\",\r\n name: opts?.name || null,\r\n },\r\n {},\r\n );\r\n\r\n return frameElement;\r\n};\r\n\r\nexport const newMagicFrameElement = (\r\n opts: {\r\n name?: string;\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawMagicFrameElement> => {\r\n const frameElement = newElementWith(\r\n {\r\n ..._newElementBase<ExcalidrawMagicFrameElement>(\"magicframe\", opts),\r\n type: \"magicframe\",\r\n name: opts?.name || null,\r\n },\r\n {},\r\n );\r\n\r\n return frameElement;\r\n};\r\n\r\n/** computes element x/y offset based on textAlign/verticalAlign */\r\nconst getTextElementPositionOffsets = (\r\n opts: {\r\n textAlign: ExcalidrawTextElement[\"textAlign\"];\r\n verticalAlign: ExcalidrawTextElement[\"verticalAlign\"];\r\n },\r\n metrics: {\r\n width: number;\r\n height: number;\r\n },\r\n) => {\r\n return {\r\n x:\r\n opts.textAlign === \"center\"\r\n ? metrics.width / 2\r\n : opts.textAlign === \"right\"\r\n ? metrics.width\r\n : 0,\r\n y: opts.verticalAlign === \"middle\" ? metrics.height / 2 : 0,\r\n };\r\n};\r\n\r\nexport const newTextElement = (\r\n opts: {\r\n text: string;\r\n originalText?: string;\r\n fontSize?: number;\r\n fontFamily?: FontFamilyValues;\r\n textAlign?: TextAlign;\r\n verticalAlign?: VerticalAlign;\r\n containerId?: ExcalidrawTextContainer[\"id\"] | null;\r\n lineHeight?: ExcalidrawTextElement[\"lineHeight\"];\r\n autoResize?: ExcalidrawTextElement[\"autoResize\"];\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawTextElement> => {\r\n const fontFamily = opts.fontFamily || DEFAULT_FONT_FAMILY;\r\n const fontSize = opts.fontSize || DEFAULT_FONT_SIZE;\r\n const lineHeight = opts.lineHeight || getLineHeight(fontFamily);\r\n const text = normalizeText(opts.text);\r\n const metrics = measureText(\r\n text,\r\n getFontString({ fontFamily, fontSize }),\r\n lineHeight,\r\n );\r\n const textAlign = opts.textAlign || DEFAULT_TEXT_ALIGN;\r\n const verticalAlign = opts.verticalAlign || DEFAULT_VERTICAL_ALIGN;\r\n const offsets = getTextElementPositionOffsets(\r\n { textAlign, verticalAlign },\r\n metrics,\r\n );\r\n\r\n const textElementProps: ExcalidrawTextElement = {\r\n ..._newElementBase<ExcalidrawTextElement>(\"text\", opts),\r\n text,\r\n fontSize,\r\n fontFamily,\r\n textAlign,\r\n verticalAlign,\r\n x: opts.x - offsets.x,\r\n y: opts.y - offsets.y,\r\n width: metrics.width,\r\n height: metrics.height,\r\n containerId: opts.containerId || null,\r\n originalText: opts.originalText ?? text,\r\n autoResize: opts.autoResize ?? true,\r\n lineHeight,\r\n };\r\n\r\n const textElement: ExcalidrawTextElement = newElementWith(\r\n textElementProps,\r\n {},\r\n );\r\n\r\n return textElement;\r\n};\r\n\r\nconst getAdjustedDimensions = (\r\n element: ExcalidrawTextElement,\r\n elementsMap: ElementsMap,\r\n nextText: string,\r\n): {\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n} => {\r\n let { width: nextWidth, height: nextHeight } = measureText(\r\n nextText,\r\n getFontString(element),\r\n element.lineHeight,\r\n );\r\n\r\n // wrapped text\r\n if (!element.autoResize) {\r\n nextWidth = element.width;\r\n }\r\n\r\n const { textAlign, verticalAlign } = element;\r\n let x: number;\r\n let y: number;\r\n if (\r\n textAlign === \"center\" &&\r\n verticalAlign === VERTICAL_ALIGN.MIDDLE &&\r\n !element.containerId &&\r\n element.autoResize\r\n ) {\r\n const prevMetrics = measureText(\r\n element.text,\r\n getFontString(element),\r\n element.lineHeight,\r\n );\r\n const offsets = getTextElementPositionOffsets(element, {\r\n width: nextWidth - prevMetrics.width,\r\n height: nextHeight - prevMetrics.height,\r\n });\r\n\r\n x = element.x - offsets.x;\r\n y = element.y - offsets.y;\r\n } else {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n\r\n const [nextX1, nextY1, nextX2, nextY2] = getResizedElementAbsoluteCoords(\r\n element,\r\n nextWidth,\r\n nextHeight,\r\n false,\r\n );\r\n const deltaX1 = (x1 - nextX1) / 2;\r\n const deltaY1 = (y1 - nextY1) / 2;\r\n const deltaX2 = (x2 - nextX2) / 2;\r\n const deltaY2 = (y2 - nextY2) / 2;\r\n\r\n [x, y] = adjustXYWithRotation(\r\n {\r\n s: true,\r\n e: textAlign === \"center\" || textAlign === \"left\",\r\n w: textAlign === \"center\" || textAlign === \"right\",\r\n },\r\n element.x,\r\n element.y,\r\n element.angle,\r\n deltaX1,\r\n deltaY1,\r\n deltaX2,\r\n deltaY2,\r\n );\r\n }\r\n\r\n return {\r\n width: nextWidth,\r\n height: nextHeight,\r\n x: Number.isFinite(x) ? x : element.x,\r\n y: Number.isFinite(y) ? y : element.y,\r\n };\r\n};\r\n\r\nconst adjustXYWithRotation = (\r\n sides: {\r\n n?: boolean;\r\n e?: boolean;\r\n s?: boolean;\r\n w?: boolean;\r\n },\r\n x: number,\r\n y: number,\r\n angle: number,\r\n deltaX1: number,\r\n deltaY1: number,\r\n deltaX2: number,\r\n deltaY2: number,\r\n): [number, number] => {\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n if (sides.e && sides.w) {\r\n x += deltaX1 + deltaX2;\r\n } else if (sides.e) {\r\n x += deltaX1 * (1 + cos);\r\n y += deltaX1 * sin;\r\n x += deltaX2 * (1 - cos);\r\n y += deltaX2 * -sin;\r\n } else if (sides.w) {\r\n x += deltaX1 * (1 - cos);\r\n y += deltaX1 * -sin;\r\n x += deltaX2 * (1 + cos);\r\n y += deltaX2 * sin;\r\n }\r\n\r\n if (sides.n && sides.s) {\r\n y += deltaY1 + deltaY2;\r\n } else if (sides.n) {\r\n x += deltaY1 * sin;\r\n y += deltaY1 * (1 - cos);\r\n x += deltaY2 * -sin;\r\n y += deltaY2 * (1 + cos);\r\n } else if (sides.s) {\r\n x += deltaY1 * -sin;\r\n y += deltaY1 * (1 + cos);\r\n x += deltaY2 * sin;\r\n y += deltaY2 * (1 - cos);\r\n }\r\n return [x, y];\r\n};\r\n\r\nexport const refreshTextDimensions = (\r\n textElement: ExcalidrawTextElement,\r\n container: ExcalidrawTextContainer | null,\r\n elementsMap: ElementsMap,\r\n text = textElement.text,\r\n) => {\r\n if (textElement.isDeleted) {\r\n return;\r\n }\r\n if (container || !textElement.autoResize) {\r\n text = wrapText(\r\n text,\r\n getFontString(textElement),\r\n container\r\n ? getBoundTextMaxWidth(container, textElement)\r\n : textElement.width,\r\n );\r\n }\r\n const dimensions = getAdjustedDimensions(textElement, elementsMap, text);\r\n return { text, ...dimensions };\r\n};\r\n\r\nexport const newFreeDrawElement = (\r\n opts: {\r\n type: \"freedraw\";\r\n points?: ExcalidrawFreeDrawElement[\"points\"];\r\n simulatePressure: boolean;\r\n pressures?: ExcalidrawFreeDrawElement[\"pressures\"];\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawFreeDrawElement> => {\r\n return {\r\n ..._newElementBase<ExcalidrawFreeDrawElement>(opts.type, opts),\r\n points: opts.points || [],\r\n pressures: opts.pressures || [],\r\n simulatePressure: opts.simulatePressure,\r\n };\r\n};\r\n\r\nexport const newLinearElement = (\r\n opts: {\r\n type: ExcalidrawLinearElement[\"type\"];\r\n points?: ExcalidrawLinearElement[\"points\"];\r\n polygon?: ExcalidrawLineElement[\"polygon\"];\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawLinearElement> => {\r\n const element = {\r\n ..._newElementBase<ExcalidrawLinearElement>(opts.type, opts),\r\n points: opts.points || [],\r\n\r\n startBinding: null,\r\n endBinding: null,\r\n startArrowhead: null,\r\n endArrowhead: null,\r\n };\r\n\r\n if (isLineElement(element)) {\r\n const lineElement: NonDeleted<ExcalidrawLineElement> = {\r\n ...element,\r\n polygon: opts.polygon ?? false,\r\n };\r\n\r\n return lineElement;\r\n }\r\n\r\n return element;\r\n};\r\n\r\nexport const newArrowElement = <T extends boolean>(\r\n opts: {\r\n type: ExcalidrawArrowElement[\"type\"];\r\n startArrowhead?: Arrowhead | null;\r\n endArrowhead?: Arrowhead | null;\r\n points?: ExcalidrawArrowElement[\"points\"];\r\n elbowed?: T;\r\n fixedSegments?: ExcalidrawElbowArrowElement[\"fixedSegments\"] | null;\r\n } & ElementConstructorOpts,\r\n): T extends true\r\n ? NonDeleted<ExcalidrawElbowArrowElement>\r\n : NonDeleted<ExcalidrawArrowElement> => {\r\n if (opts.elbowed) {\r\n return {\r\n ..._newElementBase<ExcalidrawElbowArrowElement>(opts.type, opts),\r\n points: opts.points || [],\r\n startBinding: null,\r\n endBinding: null,\r\n startArrowhead: opts.startArrowhead || null,\r\n endArrowhead: opts.endArrowhead || null,\r\n elbowed: true,\r\n fixedSegments: opts.fixedSegments || [],\r\n startIsSpecial: false,\r\n endIsSpecial: false,\r\n } as NonDeleted<ExcalidrawElbowArrowElement>;\r\n }\r\n\r\n return {\r\n ..._newElementBase<ExcalidrawArrowElement>(opts.type, opts),\r\n points: opts.points || [],\r\n startBinding: null,\r\n endBinding: null,\r\n startArrowhead: opts.startArrowhead || null,\r\n endArrowhead: opts.endArrowhead || null,\r\n elbowed: false,\r\n } as T extends true\r\n ? NonDeleted<ExcalidrawElbowArrowElement>\r\n : NonDeleted<ExcalidrawArrowElement>;\r\n};\r\n\r\nexport const newImageElement = (\r\n opts: {\r\n type: ExcalidrawImageElement[\"type\"];\r\n status?: ExcalidrawImageElement[\"status\"];\r\n fileId?: ExcalidrawImageElement[\"fileId\"];\r\n scale?: ExcalidrawImageElement[\"scale\"];\r\n crop?: ExcalidrawImageElement[\"crop\"];\r\n } & ElementConstructorOpts,\r\n): NonDeleted<ExcalidrawImageElement> => {\r\n return {\r\n ..._newElementBase<ExcalidrawImageElement>(\"image\", opts),\r\n // in the future we'll support changing stroke color for some SVG elements,\r\n // and `transparent` will likely mean \"use original colors of the image\"\r\n strokeColor: \"transparent\",\r\n status: opts.status ?? \"pending\",\r\n fileId: opts.fileId ?? null,\r\n scale: opts.scale ?? [1, 1],\r\n crop: opts.crop ?? null,\r\n };\r\n};\r\n", "import { KEYS, invariant, toBrandedType } from \"@excalidraw-modify/common\";\r\n\r\nimport { type GlobalPoint, pointFrom, type LocalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport type {\r\n AppState,\r\n PendingExcalidrawElements,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { bindBindingElement } from \"./binding\";\r\nimport { updateElbowArrowPoints } from \"./elbowArrow\";\r\nimport {\r\n HEADING_DOWN,\r\n HEADING_LEFT,\r\n HEADING_RIGHT,\r\n HEADING_UP,\r\n compareHeading,\r\n headingForPointFromElement,\r\n type Heading,\r\n} from \"./heading\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport { mutateElement } from \"./mutateElement\";\r\nimport { newArrowElement, newElement } from \"./newElement\";\r\nimport { aabbForElement } from \"./bounds\";\r\nimport { elementsAreInFrameBounds, elementOverlapsWithFrame } from \"./frame\";\r\nimport {\r\n isBindableElement,\r\n isElbowArrow,\r\n isFrameElement,\r\n isFlowchartNodeElement,\r\n} from \"./typeChecks\";\r\nimport {\r\n type ElementsMap,\r\n type ExcalidrawBindableElement,\r\n type ExcalidrawElement,\r\n type ExcalidrawFlowchartNodeElement,\r\n type NonDeletedSceneElementsMap,\r\n type Ordered,\r\n type OrderedExcalidrawElement,\r\n} from \"./types\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\ntype LinkDirection = \"up\" | \"right\" | \"down\" | \"left\";\r\n\r\nconst VERTICAL_OFFSET = 100;\r\nconst HORIZONTAL_OFFSET = 100;\r\n\r\nexport const getLinkDirectionFromKey = (key: string): LinkDirection => {\r\n switch (key) {\r\n case KEYS.ARROW_UP:\r\n return \"up\";\r\n case KEYS.ARROW_DOWN:\r\n return \"down\";\r\n case KEYS.ARROW_RIGHT:\r\n return \"right\";\r\n case KEYS.ARROW_LEFT:\r\n return \"left\";\r\n default:\r\n return \"right\";\r\n }\r\n};\r\n\r\nconst getNodeRelatives = (\r\n type: \"predecessors\" | \"successors\",\r\n node: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n direction: LinkDirection,\r\n) => {\r\n const items = [...elementsMap.values()].reduce(\r\n (acc: { relative: ExcalidrawBindableElement; heading: Heading }[], el) => {\r\n let oppositeBinding;\r\n if (\r\n isElbowArrow(el) &&\r\n // we want check existence of the opposite binding, in the direction\r\n // we're interested in\r\n (oppositeBinding =\r\n el[type === \"predecessors\" ? \"startBinding\" : \"endBinding\"]) &&\r\n // similarly, we need to filter only arrows bound to target node\r\n el[type === \"predecessors\" ? \"endBinding\" : \"startBinding\"]\r\n ?.elementId === node.id\r\n ) {\r\n const relative = elementsMap.get(oppositeBinding.elementId);\r\n\r\n if (!relative) {\r\n return acc;\r\n }\r\n\r\n invariant(\r\n isBindableElement(relative),\r\n \"not an ExcalidrawBindableElement\",\r\n );\r\n\r\n const edgePoint = (\r\n type === \"predecessors\" ? el.points[el.points.length - 1] : [0, 0]\r\n ) as Readonly<LocalPoint>;\r\n\r\n const heading = headingForPointFromElement(\r\n node,\r\n aabbForElement(node, elementsMap),\r\n [edgePoint[0] + el.x, edgePoint[1] + el.y] as Readonly<GlobalPoint>,\r\n );\r\n\r\n acc.push({\r\n relative,\r\n heading,\r\n });\r\n }\r\n return acc;\r\n },\r\n [],\r\n );\r\n\r\n switch (direction) {\r\n case \"up\":\r\n return items\r\n .filter((item) => compareHeading(item.heading, HEADING_UP))\r\n .map((item) => item.relative);\r\n case \"down\":\r\n return items\r\n .filter((item) => compareHeading(item.heading, HEADING_DOWN))\r\n .map((item) => item.relative);\r\n case \"right\":\r\n return items\r\n .filter((item) => compareHeading(item.heading, HEADING_RIGHT))\r\n .map((item) => item.relative);\r\n case \"left\":\r\n return items\r\n .filter((item) => compareHeading(item.heading, HEADING_LEFT))\r\n .map((item) => item.relative);\r\n }\r\n};\r\n\r\nconst getSuccessors = (\r\n node: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n direction: LinkDirection,\r\n) => {\r\n return getNodeRelatives(\"successors\", node, elementsMap, direction);\r\n};\r\n\r\nexport const getPredecessors = (\r\n node: ExcalidrawBindableElement,\r\n elementsMap: ElementsMap,\r\n direction: LinkDirection,\r\n) => {\r\n return getNodeRelatives(\"predecessors\", node, elementsMap, direction);\r\n};\r\n\r\nconst getOffsets = (\r\n element: ExcalidrawFlowchartNodeElement,\r\n linkedNodes: ExcalidrawElement[],\r\n direction: LinkDirection,\r\n) => {\r\n const _HORIZONTAL_OFFSET = HORIZONTAL_OFFSET + element.width;\r\n\r\n // check if vertical space or horizontal space is available first\r\n if (direction === \"up\" || direction === \"down\") {\r\n const _VERTICAL_OFFSET = VERTICAL_OFFSET + element.height;\r\n // check vertical space\r\n const minX = element.x;\r\n const maxX = element.x + element.width;\r\n\r\n // vertical space is available\r\n if (\r\n linkedNodes.every(\r\n (linkedNode) =>\r\n linkedNode.x + linkedNode.width < minX || linkedNode.x > maxX,\r\n )\r\n ) {\r\n return {\r\n x: 0,\r\n y: _VERTICAL_OFFSET * (direction === \"up\" ? -1 : 1),\r\n };\r\n }\r\n } else if (direction === \"right\" || direction === \"left\") {\r\n const minY = element.y;\r\n const maxY = element.y + element.height;\r\n\r\n if (\r\n linkedNodes.every(\r\n (linkedNode) =>\r\n linkedNode.y + linkedNode.height < minY || linkedNode.y > maxY,\r\n )\r\n ) {\r\n return {\r\n x:\r\n (HORIZONTAL_OFFSET + element.width) * (direction === \"left\" ? -1 : 1),\r\n y: 0,\r\n };\r\n }\r\n }\r\n\r\n if (direction === \"up\" || direction === \"down\") {\r\n const _VERTICAL_OFFSET = VERTICAL_OFFSET + element.height;\r\n const y = linkedNodes.length === 0 ? _VERTICAL_OFFSET : _VERTICAL_OFFSET;\r\n const x =\r\n linkedNodes.length === 0\r\n ? 0\r\n : (linkedNodes.length + 1) % 2 === 0\r\n ? ((linkedNodes.length + 1) / 2) * _HORIZONTAL_OFFSET\r\n : (linkedNodes.length / 2) * _HORIZONTAL_OFFSET * -1;\r\n\r\n if (direction === \"up\") {\r\n return {\r\n x,\r\n y: y * -1,\r\n };\r\n }\r\n\r\n return {\r\n x,\r\n y,\r\n };\r\n }\r\n\r\n const _VERTICAL_OFFSET = VERTICAL_OFFSET + element.height;\r\n const x =\r\n (linkedNodes.length === 0 ? HORIZONTAL_OFFSET : HORIZONTAL_OFFSET) +\r\n element.width;\r\n const y =\r\n linkedNodes.length === 0\r\n ? 0\r\n : (linkedNodes.length + 1) % 2 === 0\r\n ? ((linkedNodes.length + 1) / 2) * _VERTICAL_OFFSET\r\n : (linkedNodes.length / 2) * _VERTICAL_OFFSET * -1;\r\n\r\n if (direction === \"left\") {\r\n return {\r\n x: x * -1,\r\n y,\r\n };\r\n }\r\n return {\r\n x,\r\n y,\r\n };\r\n};\r\n\r\nconst addNewNode = (\r\n element: ExcalidrawFlowchartNodeElement,\r\n appState: AppState,\r\n direction: LinkDirection,\r\n scene: Scene,\r\n) => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n const successors = getSuccessors(element, elementsMap, direction);\r\n const predeccessors = getPredecessors(element, elementsMap, direction);\r\n\r\n const offsets = getOffsets(\r\n element,\r\n [...successors, ...predeccessors],\r\n direction,\r\n );\r\n\r\n const nextNode = newElement({\r\n type: element.type,\r\n x: element.x + offsets.x,\r\n y: element.y + offsets.y,\r\n // TODO: extract this to a util\r\n width: element.width,\r\n height: element.height,\r\n roundness: element.roundness,\r\n roughness: element.roughness,\r\n backgroundColor: element.backgroundColor,\r\n strokeColor: element.strokeColor,\r\n strokeWidth: element.strokeWidth,\r\n opacity: element.opacity,\r\n fillStyle: element.fillStyle,\r\n strokeStyle: element.strokeStyle,\r\n });\r\n\r\n invariant(\r\n isFlowchartNodeElement(nextNode),\r\n \"not an ExcalidrawFlowchartNodeElement\",\r\n );\r\n\r\n const bindingArrow = createBindingArrow(\r\n element,\r\n nextNode,\r\n direction,\r\n appState,\r\n scene,\r\n );\r\n\r\n return {\r\n nextNode,\r\n bindingArrow,\r\n };\r\n};\r\n\r\nexport const addNewNodes = (\r\n startNode: ExcalidrawFlowchartNodeElement,\r\n appState: AppState,\r\n direction: LinkDirection,\r\n scene: Scene,\r\n numberOfNodes: number,\r\n) => {\r\n // always start from 0 and distribute evenly\r\n const newNodes: ExcalidrawElement[] = [];\r\n\r\n for (let i = 0; i < numberOfNodes; i++) {\r\n let nextX: number;\r\n let nextY: number;\r\n if (direction === \"left\" || direction === \"right\") {\r\n const totalHeight =\r\n VERTICAL_OFFSET * (numberOfNodes - 1) +\r\n numberOfNodes * startNode.height;\r\n\r\n const startY = startNode.y + startNode.height / 2 - totalHeight / 2;\r\n\r\n let offsetX = HORIZONTAL_OFFSET + startNode.width;\r\n if (direction === \"left\") {\r\n offsetX *= -1;\r\n }\r\n nextX = startNode.x + offsetX;\r\n const offsetY = (VERTICAL_OFFSET + startNode.height) * i;\r\n nextY = startY + offsetY;\r\n } else {\r\n const totalWidth =\r\n HORIZONTAL_OFFSET * (numberOfNodes - 1) +\r\n numberOfNodes * startNode.width;\r\n const startX = startNode.x + startNode.width / 2 - totalWidth / 2;\r\n let offsetY = VERTICAL_OFFSET + startNode.height;\r\n\r\n if (direction === \"up\") {\r\n offsetY *= -1;\r\n }\r\n nextY = startNode.y + offsetY;\r\n const offsetX = (HORIZONTAL_OFFSET + startNode.width) * i;\r\n nextX = startX + offsetX;\r\n }\r\n\r\n const nextNode = newElement({\r\n type: startNode.type,\r\n x: nextX,\r\n y: nextY,\r\n // TODO: extract this to a util\r\n width: startNode.width,\r\n height: startNode.height,\r\n roundness: startNode.roundness,\r\n roughness: startNode.roughness,\r\n backgroundColor: startNode.backgroundColor,\r\n strokeColor: startNode.strokeColor,\r\n strokeWidth: startNode.strokeWidth,\r\n opacity: startNode.opacity,\r\n fillStyle: startNode.fillStyle,\r\n strokeStyle: startNode.strokeStyle,\r\n });\r\n\r\n invariant(\r\n isFlowchartNodeElement(nextNode),\r\n \"not an ExcalidrawFlowchartNodeElement\",\r\n );\r\n\r\n const bindingArrow = createBindingArrow(\r\n startNode,\r\n nextNode,\r\n direction,\r\n appState,\r\n scene,\r\n );\r\n\r\n newNodes.push(nextNode);\r\n newNodes.push(bindingArrow);\r\n }\r\n\r\n return newNodes;\r\n};\r\n\r\nconst createBindingArrow = (\r\n startBindingElement: ExcalidrawFlowchartNodeElement,\r\n endBindingElement: ExcalidrawFlowchartNodeElement,\r\n direction: LinkDirection,\r\n appState: AppState,\r\n scene: Scene,\r\n) => {\r\n let startX: number;\r\n let startY: number;\r\n\r\n const PADDING = 6;\r\n\r\n switch (direction) {\r\n case \"up\": {\r\n startX = startBindingElement.x + startBindingElement.width / 2;\r\n startY = startBindingElement.y - PADDING;\r\n break;\r\n }\r\n case \"down\": {\r\n startX = startBindingElement.x + startBindingElement.width / 2;\r\n startY = startBindingElement.y + startBindingElement.height + PADDING;\r\n break;\r\n }\r\n case \"right\": {\r\n startX = startBindingElement.x + startBindingElement.width + PADDING;\r\n startY = startBindingElement.y + startBindingElement.height / 2;\r\n break;\r\n }\r\n case \"left\": {\r\n startX = startBindingElement.x - PADDING;\r\n startY = startBindingElement.y + startBindingElement.height / 2;\r\n break;\r\n }\r\n }\r\n\r\n let endX: number;\r\n let endY: number;\r\n\r\n switch (direction) {\r\n case \"up\": {\r\n endX = endBindingElement.x + endBindingElement.width / 2 - startX;\r\n endY = endBindingElement.y + endBindingElement.height - startY + PADDING;\r\n break;\r\n }\r\n case \"down\": {\r\n endX = endBindingElement.x + endBindingElement.width / 2 - startX;\r\n endY = endBindingElement.y - startY - PADDING;\r\n break;\r\n }\r\n case \"right\": {\r\n endX = endBindingElement.x - startX - PADDING;\r\n endY = endBindingElement.y - startY + endBindingElement.height / 2;\r\n break;\r\n }\r\n case \"left\": {\r\n endX = endBindingElement.x + endBindingElement.width - startX + PADDING;\r\n endY = endBindingElement.y - startY + endBindingElement.height / 2;\r\n break;\r\n }\r\n }\r\n\r\n const bindingArrow = newArrowElement({\r\n type: \"arrow\",\r\n x: startX,\r\n y: startY,\r\n startArrowhead: null,\r\n endArrowhead: appState.currentItemEndArrowhead,\r\n strokeColor: startBindingElement.strokeColor,\r\n strokeStyle: startBindingElement.strokeStyle,\r\n strokeWidth: startBindingElement.strokeWidth,\r\n opacity: startBindingElement.opacity,\r\n roughness: startBindingElement.roughness,\r\n points: [pointFrom(0, 0), pointFrom(endX, endY)],\r\n elbowed: true,\r\n });\r\n\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n\r\n bindBindingElement(\r\n bindingArrow,\r\n startBindingElement,\r\n \"orbit\",\r\n \"start\",\r\n scene,\r\n );\r\n bindBindingElement(bindingArrow, endBindingElement, \"orbit\", \"end\", scene);\r\n\r\n const changedElements = new Map<string, OrderedExcalidrawElement>();\r\n changedElements.set(\r\n startBindingElement.id,\r\n startBindingElement as OrderedExcalidrawElement,\r\n );\r\n changedElements.set(\r\n endBindingElement.id,\r\n endBindingElement as OrderedExcalidrawElement,\r\n );\r\n changedElements.set(\r\n bindingArrow.id,\r\n bindingArrow as OrderedExcalidrawElement,\r\n );\r\n\r\n LinearElementEditor.movePoints(\r\n bindingArrow,\r\n scene,\r\n new Map([\r\n [\r\n 1,\r\n {\r\n point: bindingArrow.points[1],\r\n },\r\n ],\r\n ]),\r\n );\r\n\r\n const update = updateElbowArrowPoints(\r\n bindingArrow,\r\n toBrandedType<NonDeletedSceneElementsMap>(\r\n new Map([\r\n ...elementsMap.entries(),\r\n [startBindingElement.id, startBindingElement],\r\n [endBindingElement.id, endBindingElement],\r\n [bindingArrow.id, bindingArrow],\r\n ] as [string, Ordered<ExcalidrawElement>][]),\r\n ),\r\n { points: bindingArrow.points },\r\n );\r\n\r\n return {\r\n ...bindingArrow,\r\n ...update,\r\n };\r\n};\r\n\r\nexport class FlowChartNavigator {\r\n isExploring: boolean = false;\r\n // nodes that are ONE link away (successor and predecessor both included)\r\n private sameLevelNodes: ExcalidrawElement[] = [];\r\n private sameLevelIndex: number = 0;\r\n // set it to the opposite of the defalut creation direction\r\n private direction: LinkDirection | null = null;\r\n // for speedier navigation\r\n private visitedNodes: Set<ExcalidrawElement[\"id\"]> = new Set();\r\n\r\n clear() {\r\n this.isExploring = false;\r\n this.sameLevelNodes = [];\r\n this.sameLevelIndex = 0;\r\n this.direction = null;\r\n this.visitedNodes.clear();\r\n }\r\n\r\n exploreByDirection(\r\n element: ExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n direction: LinkDirection,\r\n ): ExcalidrawElement[\"id\"] | null {\r\n if (!isBindableElement(element)) {\r\n return null;\r\n }\r\n\r\n // clear if going at a different direction\r\n if (direction !== this.direction) {\r\n this.clear();\r\n }\r\n\r\n // add the current node to the visited\r\n if (!this.visitedNodes.has(element.id)) {\r\n this.visitedNodes.add(element.id);\r\n }\r\n\r\n /**\r\n * CASE:\r\n * - already started exploring, AND\r\n * - there are multiple nodes at the same level, AND\r\n * - still going at the same direction, AND\r\n *\r\n * RESULT:\r\n * - loop through nodes at the same level\r\n *\r\n * WHY:\r\n * - provides user the capability to loop through nodes at the same level\r\n */\r\n if (\r\n this.isExploring &&\r\n direction === this.direction &&\r\n this.sameLevelNodes.length > 1\r\n ) {\r\n this.sameLevelIndex =\r\n (this.sameLevelIndex + 1) % this.sameLevelNodes.length;\r\n\r\n return this.sameLevelNodes[this.sameLevelIndex].id;\r\n }\r\n\r\n const nodes = [\r\n ...getSuccessors(element, elementsMap, direction),\r\n ...getPredecessors(element, elementsMap, direction),\r\n ];\r\n\r\n /**\r\n * CASE:\r\n * - just started exploring at the given direction\r\n *\r\n * RESULT:\r\n * - go to the first node in the given direction\r\n */\r\n if (nodes.length > 0) {\r\n this.sameLevelIndex = 0;\r\n this.isExploring = true;\r\n this.sameLevelNodes = nodes;\r\n this.direction = direction;\r\n this.visitedNodes.add(nodes[0].id);\r\n\r\n return nodes[0].id;\r\n }\r\n\r\n /**\r\n * CASE:\r\n * - (just started exploring or still going at the same direction) OR\r\n * - there're no nodes at the given direction\r\n *\r\n * RESULT:\r\n * - go to some other unvisited linked node\r\n *\r\n * WHY:\r\n * - provide a speedier navigation from a given node to some predecessor\r\n * without the user having to change arrow key\r\n */\r\n if (direction === this.direction || !this.isExploring) {\r\n if (!this.isExploring) {\r\n // just started and no other nodes at the given direction\r\n // so the current node is technically the first visited node\r\n // (this is needed so that we don't get stuck between looping through )\r\n this.visitedNodes.add(element.id);\r\n }\r\n\r\n const otherDirections: LinkDirection[] = [\r\n \"up\",\r\n \"right\",\r\n \"down\",\r\n \"left\",\r\n ].filter((dir): dir is LinkDirection => dir !== direction);\r\n\r\n const otherLinkedNodes = otherDirections\r\n .map((dir) => [\r\n ...getSuccessors(element, elementsMap, dir),\r\n ...getPredecessors(element, elementsMap, dir),\r\n ])\r\n .flat()\r\n .filter((linkedNode) => !this.visitedNodes.has(linkedNode.id));\r\n\r\n for (const linkedNode of otherLinkedNodes) {\r\n if (!this.visitedNodes.has(linkedNode.id)) {\r\n this.visitedNodes.add(linkedNode.id);\r\n this.isExploring = true;\r\n this.direction = direction;\r\n return linkedNode.id;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nexport class FlowChartCreator {\r\n isCreatingChart: boolean = false;\r\n private numberOfNodes: number = 0;\r\n private direction: LinkDirection | null = \"right\";\r\n pendingNodes: PendingExcalidrawElements | null = null;\r\n\r\n createNodes(\r\n startNode: ExcalidrawFlowchartNodeElement,\r\n appState: AppState,\r\n direction: LinkDirection,\r\n scene: Scene,\r\n ) {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n if (direction !== this.direction) {\r\n const { nextNode, bindingArrow } = addNewNode(\r\n startNode,\r\n appState,\r\n direction,\r\n scene,\r\n );\r\n\r\n this.numberOfNodes = 1;\r\n this.isCreatingChart = true;\r\n this.direction = direction;\r\n this.pendingNodes = [nextNode, bindingArrow];\r\n } else {\r\n this.numberOfNodes += 1;\r\n const newNodes = addNewNodes(\r\n startNode,\r\n appState,\r\n direction,\r\n scene,\r\n this.numberOfNodes,\r\n );\r\n\r\n this.isCreatingChart = true;\r\n this.direction = direction;\r\n this.pendingNodes = newNodes;\r\n }\r\n\r\n // add pending nodes to the same frame as the start node\r\n // if every pending node is at least intersecting with the frame\r\n if (startNode.frameId) {\r\n const frame = elementsMap.get(startNode.frameId);\r\n\r\n invariant(\r\n frame && isFrameElement(frame),\r\n \"not an ExcalidrawFrameElement\",\r\n );\r\n\r\n if (\r\n frame &&\r\n this.pendingNodes.every(\r\n (node) =>\r\n elementsAreInFrameBounds([node], frame, elementsMap) ||\r\n elementOverlapsWithFrame(node, frame, elementsMap),\r\n )\r\n ) {\r\n this.pendingNodes = this.pendingNodes.map((node) =>\r\n mutateElement(node, elementsMap, {\r\n frameId: startNode.frameId,\r\n }),\r\n );\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n this.isCreatingChart = false;\r\n this.pendingNodes = null;\r\n this.direction = null;\r\n this.numberOfNodes = 0;\r\n }\r\n}\r\n\r\nexport const isNodeInFlowchart = (\r\n element: ExcalidrawFlowchartNodeElement,\r\n elementsMap: ElementsMap,\r\n) => {\r\n for (const [, el] of elementsMap) {\r\n if (\r\n el.type === \"arrow\" &&\r\n (el.startBinding?.elementId === element.id ||\r\n el.endBinding?.elementId === element.id)\r\n ) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n", "// -----------------------------------------------------------------------------\r\n// ExcalidrawImageElement & related helpers\r\n// -----------------------------------------------------------------------------\r\n\r\nimport { MIME_TYPES, SVG_NS } from \"@excalidraw-modify/common\";\r\n\r\nimport type {\r\n AppClassProperties,\r\n DataURL,\r\n BinaryFiles,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { isInitializedImageElement } from \"./typeChecks\";\r\n\r\nimport type {\r\n ExcalidrawElement,\r\n FileId,\r\n InitializedExcalidrawImageElement,\r\n} from \"./types\";\r\n\r\nexport const loadHTMLImageElement = (dataURL: DataURL) => {\r\n return new Promise<HTMLImageElement>((resolve, reject) => {\r\n const image = new Image();\r\n image.onload = () => {\r\n resolve(image);\r\n };\r\n image.onerror = (error) => {\r\n reject(error);\r\n };\r\n image.src = dataURL;\r\n });\r\n};\r\n\r\n/** NOTE: updates cache even if already populated with given image. Thus,\r\n * you should filter out the images upstream if you want to optimize this. */\r\nexport const updateImageCache = async ({\r\n fileIds,\r\n files,\r\n imageCache,\r\n}: {\r\n fileIds: FileId[];\r\n files: BinaryFiles;\r\n imageCache: AppClassProperties[\"imageCache\"];\r\n}) => {\r\n const updatedFiles = new Map<FileId, true>();\r\n const erroredFiles = new Map<FileId, true>();\r\n\r\n await Promise.all(\r\n fileIds.reduce((promises, fileId) => {\r\n const fileData = files[fileId as string];\r\n if (fileData && !updatedFiles.has(fileId)) {\r\n updatedFiles.set(fileId, true);\r\n return promises.concat(\r\n (async () => {\r\n try {\r\n if (fileData.mimeType === MIME_TYPES.binary) {\r\n throw new Error(\"Only images can be added to ImageCache\");\r\n }\r\n\r\n const imagePromise = loadHTMLImageElement(fileData.dataURL);\r\n const data = {\r\n image: imagePromise,\r\n mimeType: fileData.mimeType,\r\n } as const;\r\n // store the promise immediately to indicate there's an in-progress\r\n // initialization\r\n imageCache.set(fileId, data);\r\n\r\n const image = await imagePromise;\r\n\r\n imageCache.set(fileId, { ...data, image });\r\n } catch (error: any) {\r\n erroredFiles.set(fileId, true);\r\n }\r\n })(),\r\n );\r\n }\r\n return promises;\r\n }, [] as Promise<any>[]),\r\n );\r\n\r\n return {\r\n imageCache,\r\n /** includes errored files because they cache was updated nonetheless */\r\n updatedFiles,\r\n /** files that failed when creating HTMLImageElement */\r\n erroredFiles,\r\n };\r\n};\r\n\r\nexport const getInitializedImageElements = (\r\n elements: readonly ExcalidrawElement[],\r\n) =>\r\n elements.filter((element) =>\r\n isInitializedImageElement(element),\r\n ) as InitializedExcalidrawImageElement[];\r\n\r\nexport const isHTMLSVGElement = (node: Node | null): node is SVGElement => {\r\n // lower-casing due to XML/HTML convention differences\r\n // https://johnresig.com/blog/nodename-case-sensitivity\r\n return node?.nodeName.toLowerCase() === \"svg\";\r\n};\r\n\r\nexport const normalizeSVG = (SVGString: string) => {\r\n const doc = new DOMParser().parseFromString(SVGString, MIME_TYPES.svg);\r\n const svg = doc.querySelector(\"svg\");\r\n const errorNode = doc.querySelector(\"parsererror\");\r\n if (errorNode || !isHTMLSVGElement(svg)) {\r\n throw new Error(\"Invalid SVG\");\r\n } else {\r\n if (!svg.hasAttribute(\"xmlns\")) {\r\n svg.setAttribute(\"xmlns\", SVG_NS);\r\n }\r\n\r\n let width = svg.getAttribute(\"width\");\r\n let height = svg.getAttribute(\"height\");\r\n\r\n // Do not use % or auto values for width/height\r\n // to avoid scaling issues when rendering at different sizes/zoom levels\r\n if (width?.includes(\"%\") || width === \"auto\") {\r\n width = null;\r\n }\r\n if (height?.includes(\"%\") || height === \"auto\") {\r\n height = null;\r\n }\r\n\r\n const viewBox = svg.getAttribute(\"viewBox\");\r\n\r\n if (!width || !height) {\r\n width = width || \"50\";\r\n height = height || \"50\";\r\n\r\n if (viewBox) {\r\n const match = viewBox.match(\r\n /\\d+ +\\d+ +(\\d+(?:\\.\\d+)?) +(\\d+(?:\\.\\d+)?)/,\r\n );\r\n if (match) {\r\n [, width, height] = match;\r\n }\r\n }\r\n\r\n svg.setAttribute(\"width\", width);\r\n svg.setAttribute(\"height\", height);\r\n }\r\n\r\n // Make sure viewBox is set\r\n if (!viewBox) {\r\n svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\r\n }\r\n\r\n return svg.outerHTML;\r\n }\r\n};\r\n", "import { getCommonBounds } from \"./bounds\";\nimport { type ElementUpdate, newElementWith } from \"./mutateElement\";\n\nimport type { ExcalidrawElement } from \"./types\";\n\n// TODO rewrite (mostly vibe-coded)\nexport const positionElementsOnGrid = <TElement extends ExcalidrawElement>(\n elements: TElement[] | TElement[][],\n centerX: number,\n centerY: number,\n padding = 50,\n): TElement[] => {\n // Ensure there are elements to position\n if (!elements || elements.length === 0) {\n return [];\n }\n\n const res: TElement[] = [];\n // Normalize input to work with atomic units (groups of elements)\n // If elements is a flat array, treat each element as its own atomic unit\n const atomicUnits: TElement[][] = Array.isArray(elements[0])\n ? (elements as TElement[][])\n : (elements as TElement[]).map((element) => [element]);\n\n // Determine the number of columns for atomic units\n // A common approach for a \"grid-like\" layout without specific column constraints\n // is to aim for a roughly square arrangement.\n const numUnits = atomicUnits.length;\n const numColumns = Math.max(1, Math.ceil(Math.sqrt(numUnits)));\n\n // Group atomic units into rows based on the calculated number of columns\n const rows: TElement[][][] = [];\n for (let i = 0; i < numUnits; i += numColumns) {\n rows.push(atomicUnits.slice(i, i + numColumns));\n }\n\n // Calculate properties for each row (total width, max height)\n // and the total actual height of all row content.\n let totalGridActualHeight = 0; // Sum of max heights of rows, without inter-row padding\n const rowProperties = rows.map((rowUnits) => {\n let rowWidth = 0;\n let maxUnitHeightInRow = 0;\n\n const unitBounds = rowUnits.map((unit) => {\n const [minX, minY, maxX, maxY] = getCommonBounds(unit);\n return {\n elements: unit,\n bounds: [minX, minY, maxX, maxY] as const,\n width: maxX - minX,\n height: maxY - minY,\n };\n });\n\n unitBounds.forEach((unitBound, index) => {\n rowWidth += unitBound.width;\n // Add padding between units in the same row, but not after the last one\n if (index < unitBounds.length - 1) {\n rowWidth += padding;\n }\n if (unitBound.height > maxUnitHeightInRow) {\n maxUnitHeightInRow = unitBound.height;\n }\n });\n\n totalGridActualHeight += maxUnitHeightInRow;\n return {\n unitBounds,\n width: rowWidth,\n maxHeight: maxUnitHeightInRow,\n };\n });\n\n // Calculate the total height of the grid including padding between rows\n const totalGridHeightWithPadding =\n totalGridActualHeight + Math.max(0, rows.length - 1) * padding;\n\n // Calculate the starting Y position to center the entire grid vertically around centerY\n let currentY = centerY - totalGridHeightWithPadding / 2;\n\n // Position atomic units row by row\n rowProperties.forEach((rowProp) => {\n const { unitBounds, width: rowWidth, maxHeight: rowMaxHeight } = rowProp;\n\n // Calculate the starting X for the current row to center it horizontally around centerX\n let currentX = centerX - rowWidth / 2;\n\n unitBounds.forEach((unitBound) => {\n // Calculate the offset needed to position this atomic unit\n const [originalMinX, originalMinY] = unitBound.bounds;\n const offsetX = currentX - originalMinX;\n const offsetY = currentY - originalMinY;\n\n // Apply the offset to all elements in this atomic unit\n unitBound.elements.forEach((element) => {\n res.push(\n newElementWith(element, {\n x: element.x + offsetX,\n y: element.y + offsetY,\n } as ElementUpdate<TElement>),\n );\n });\n\n // Move X for the next unit in the row\n currentX += unitBound.width + padding;\n });\n\n // Move Y to the starting position for the next row\n // This accounts for the tallest unit in the current row and the inter-row padding\n currentY += rowMaxHeight + padding;\n });\n return res;\n};\n", "import {\r\n pointCenter,\r\n normalizeRadians,\r\n pointFrom,\r\n pointRotateRads,\r\n type Radians,\r\n type LocalPoint,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n MIN_FONT_SIZE,\r\n SHIFT_LOCKING_ANGLE,\r\n rescalePoints,\r\n getFontString,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { GlobalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport type { PointerDownState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport type { Mutable } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport {\r\n getArrowLocalFixedPoints,\r\n unbindBindingElement,\r\n updateBoundElements,\r\n} from \"./binding\";\r\nimport {\r\n getElementAbsoluteCoords,\r\n getCommonBounds,\r\n getResizedElementAbsoluteCoords,\r\n getCommonBoundingBox,\r\n getElementBounds,\r\n} from \"./bounds\";\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\nimport {\r\n getBoundTextElement,\r\n getBoundTextElementId,\r\n getContainerElement,\r\n handleBindTextResize,\r\n getBoundTextMaxWidth,\r\n computeBoundTextPosition,\r\n} from \"./textElement\";\r\nimport {\r\n getMinTextElementWidth,\r\n measureText,\r\n getApproxMinLineWidth,\r\n getApproxMinLineHeight,\r\n} from \"./textMeasurements\";\r\nimport { wrapText } from \"./textWrapping\";\r\nimport {\r\n isArrowElement,\r\n isBindingElement,\r\n isBoundToContainer,\r\n isElbowArrow,\r\n isFrameLikeElement,\r\n isFreeDrawElement,\r\n isImageElement,\r\n isLinearElement,\r\n isTextElement,\r\n} from \"./typeChecks\";\r\n\r\nimport { isInGroup } from \"./groups\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\n\r\nimport type { BoundingBox } from \"./bounds\";\r\nimport type {\r\n MaybeTransformHandleType,\r\n TransformHandleDirection,\r\n} from \"./transformHandles\";\r\nimport type {\r\n ExcalidrawLinearElement,\r\n ExcalidrawTextElement,\r\n NonDeletedExcalidrawElement,\r\n NonDeleted,\r\n ExcalidrawElement,\r\n ExcalidrawTextElementWithContainer,\r\n ExcalidrawImageElement,\r\n ElementsMap,\r\n ExcalidrawElbowArrowElement,\r\n ExcalidrawArrowElement,\r\n} from \"./types\";\r\nimport type { ElementUpdate } from \"./mutateElement\";\r\n\r\n// Returns true when transform (resizing/rotation) happened\r\nexport const transformElements = (\r\n originalElements: PointerDownState[\"originalElements\"],\r\n transformHandleType: MaybeTransformHandleType,\r\n selectedElements: readonly NonDeletedExcalidrawElement[],\r\n scene: Scene,\r\n shouldRotateWithDiscreteAngle: boolean,\r\n shouldResizeFromCenter: boolean,\r\n shouldMaintainAspectRatio: boolean,\r\n pointerX: number,\r\n pointerY: number,\r\n centerX: number,\r\n centerY: number,\r\n): boolean => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n if (selectedElements.length === 1) {\r\n const [element] = selectedElements;\r\n if (transformHandleType === \"rotation\") {\r\n if (!isElbowArrow(element)) {\r\n rotateSingleElement(\r\n element,\r\n scene,\r\n pointerX,\r\n pointerY,\r\n shouldRotateWithDiscreteAngle,\r\n );\r\n updateBoundElements(element, scene);\r\n }\r\n } else if (transformHandleType) {\r\n const elementId = selectedElements[0].id;\r\n const latestElement = elementsMap.get(elementId);\r\n const origElement = originalElements.get(elementId);\r\n\r\n if (latestElement && origElement) {\r\n const { nextWidth, nextHeight } =\r\n getNextSingleWidthAndHeightFromPointer(\r\n latestElement,\r\n origElement,\r\n transformHandleType,\r\n pointerX,\r\n pointerY,\r\n {\r\n shouldMaintainAspectRatio,\r\n shouldResizeFromCenter,\r\n },\r\n );\r\n\r\n resizeSingleElement(\r\n nextWidth,\r\n nextHeight,\r\n latestElement,\r\n origElement,\r\n originalElements,\r\n scene,\r\n transformHandleType,\r\n {\r\n shouldMaintainAspectRatio,\r\n shouldResizeFromCenter,\r\n },\r\n );\r\n }\r\n }\r\n if (isTextElement(element)) {\r\n updateBoundElements(element, scene);\r\n }\r\n return true;\r\n } else if (selectedElements.length > 1) {\r\n if (transformHandleType === \"rotation\") {\r\n rotateMultipleElements(\r\n originalElements,\r\n selectedElements,\r\n scene,\r\n pointerX,\r\n pointerY,\r\n shouldRotateWithDiscreteAngle,\r\n centerX,\r\n centerY,\r\n );\r\n return true;\r\n } else if (transformHandleType) {\r\n const { nextWidth, nextHeight, flipByX, flipByY, originalBoundingBox } =\r\n getNextMultipleWidthAndHeightFromPointer(\r\n selectedElements,\r\n originalElements,\r\n elementsMap,\r\n transformHandleType,\r\n pointerX,\r\n pointerY,\r\n {\r\n shouldMaintainAspectRatio,\r\n shouldResizeFromCenter,\r\n },\r\n );\r\n\r\n resizeMultipleElements(\r\n selectedElements,\r\n elementsMap,\r\n transformHandleType,\r\n scene,\r\n originalElements,\r\n {\r\n shouldResizeFromCenter,\r\n shouldMaintainAspectRatio,\r\n flipByX,\r\n flipByY,\r\n nextWidth,\r\n nextHeight,\r\n originalBoundingBox,\r\n },\r\n );\r\n\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\nconst rotateSingleElement = (\r\n element: NonDeletedExcalidrawElement,\r\n scene: Scene,\r\n pointerX: number,\r\n pointerY: number,\r\n shouldRotateWithDiscreteAngle: boolean,\r\n) => {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(\r\n element,\r\n scene.getNonDeletedElementsMap(),\r\n );\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n let angle: Radians;\r\n if (isFrameLikeElement(element)) {\r\n angle = 0 as Radians;\r\n } else {\r\n angle = ((5 * Math.PI) / 2 +\r\n Math.atan2(pointerY - cy, pointerX - cx)) as Radians;\r\n if (shouldRotateWithDiscreteAngle) {\r\n angle = (angle + SHIFT_LOCKING_ANGLE / 2) as Radians;\r\n angle = (angle - (angle % SHIFT_LOCKING_ANGLE)) as Radians;\r\n }\r\n angle = normalizeRadians(angle as Radians);\r\n }\r\n const boundTextElementId = getBoundTextElementId(element);\r\n\r\n let update: ElementUpdate<NonDeletedExcalidrawElement> = {\r\n angle,\r\n };\r\n\r\n if (isBindingElement(element)) {\r\n update = {\r\n ...update,\r\n } as ElementUpdate<ExcalidrawArrowElement>;\r\n\r\n if (element.startBinding) {\r\n unbindBindingElement(element, \"start\", scene);\r\n }\r\n if (element.endBinding) {\r\n unbindBindingElement(element, \"end\", scene);\r\n }\r\n }\r\n\r\n scene.mutateElement(element, update);\r\n\r\n if (boundTextElementId) {\r\n const textElement =\r\n scene.getElement<ExcalidrawTextElementWithContainer>(boundTextElementId);\r\n\r\n if (textElement && !isArrowElement(element)) {\r\n const { x, y } = computeBoundTextPosition(\r\n element,\r\n textElement,\r\n scene.getNonDeletedElementsMap(),\r\n );\r\n scene.mutateElement(textElement, {\r\n angle,\r\n x,\r\n y,\r\n });\r\n }\r\n }\r\n};\r\n\r\nexport const rescalePointsInElement = (\r\n element: NonDeletedExcalidrawElement,\r\n width: number,\r\n height: number,\r\n normalizePoints: boolean,\r\n) =>\r\n isLinearElement(element) || isFreeDrawElement(element)\r\n ? {\r\n points: rescalePoints(\r\n 0,\r\n width,\r\n rescalePoints(1, height, element.points, normalizePoints),\r\n normalizePoints,\r\n ),\r\n }\r\n : {};\r\n\r\nexport const measureFontSizeFromWidth = (\r\n element: NonDeleted<ExcalidrawTextElement>,\r\n elementsMap: ElementsMap,\r\n nextWidth: number,\r\n): { size: number } | null => {\r\n // We only use width to scale font on resize\r\n let width = element.width;\r\n\r\n const hasContainer = isBoundToContainer(element);\r\n if (hasContainer) {\r\n const container = getContainerElement(element, elementsMap);\r\n if (container) {\r\n width = getBoundTextMaxWidth(container, element);\r\n }\r\n }\r\n const nextFontSize = element.fontSize * (nextWidth / width);\r\n if (nextFontSize < MIN_FONT_SIZE) {\r\n return null;\r\n }\r\n\r\n return {\r\n size: nextFontSize,\r\n };\r\n};\r\n\r\nexport const resizeSingleTextElement = (\r\n origElement: NonDeleted<ExcalidrawTextElement>,\r\n element: NonDeleted<ExcalidrawTextElement>,\r\n scene: Scene,\r\n transformHandleType: TransformHandleDirection,\r\n shouldResizeFromCenter: boolean,\r\n nextWidth: number,\r\n nextHeight: number,\r\n) => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n\r\n const metricsWidth = element.width * (nextHeight / element.height);\r\n\r\n const metrics = measureFontSizeFromWidth(element, elementsMap, metricsWidth);\r\n if (metrics === null) {\r\n return;\r\n }\r\n\r\n if (transformHandleType.includes(\"n\") || transformHandleType.includes(\"s\")) {\r\n const previousOrigin = pointFrom<GlobalPoint>(origElement.x, origElement.y);\r\n\r\n const newOrigin = getResizedOrigin(\r\n previousOrigin,\r\n origElement.width,\r\n origElement.height,\r\n metricsWidth,\r\n nextHeight,\r\n origElement.angle,\r\n transformHandleType,\r\n false,\r\n shouldResizeFromCenter,\r\n );\r\n\r\n scene.mutateElement(element, {\r\n fontSize: metrics.size,\r\n width: metricsWidth,\r\n height: nextHeight,\r\n x: newOrigin.x,\r\n y: newOrigin.y,\r\n });\r\n return;\r\n }\r\n\r\n if (transformHandleType === \"e\" || transformHandleType === \"w\") {\r\n const minWidth = getMinTextElementWidth(\r\n getFontString({\r\n fontSize: element.fontSize,\r\n fontFamily: element.fontFamily,\r\n }),\r\n element.lineHeight,\r\n );\r\n\r\n const newWidth = Math.max(minWidth, nextWidth);\r\n\r\n const text = wrapText(\r\n element.originalText,\r\n getFontString(element),\r\n Math.abs(newWidth),\r\n );\r\n const metrics = measureText(\r\n text,\r\n getFontString(element),\r\n element.lineHeight,\r\n );\r\n\r\n const newHeight = metrics.height;\r\n\r\n const previousOrigin = pointFrom<GlobalPoint>(origElement.x, origElement.y);\r\n\r\n const newOrigin = getResizedOrigin(\r\n previousOrigin,\r\n origElement.width,\r\n origElement.height,\r\n newWidth,\r\n newHeight,\r\n element.angle,\r\n transformHandleType,\r\n false,\r\n shouldResizeFromCenter,\r\n );\r\n\r\n const resizedElement: Partial<ExcalidrawTextElement> = {\r\n width: Math.abs(newWidth),\r\n height: Math.abs(metrics.height),\r\n x: newOrigin.x,\r\n y: newOrigin.y,\r\n text,\r\n autoResize: false,\r\n };\r\n\r\n scene.mutateElement(element, resizedElement);\r\n }\r\n};\r\n\r\nconst rotateMultipleElements = (\r\n originalElements: PointerDownState[\"originalElements\"],\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n scene: Scene,\r\n pointerX: number,\r\n pointerY: number,\r\n shouldRotateWithDiscreteAngle: boolean,\r\n centerX: number,\r\n centerY: number,\r\n) => {\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n let centerAngle =\r\n (5 * Math.PI) / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);\r\n if (shouldRotateWithDiscreteAngle) {\r\n centerAngle += SHIFT_LOCKING_ANGLE / 2;\r\n centerAngle -= centerAngle % SHIFT_LOCKING_ANGLE;\r\n }\r\n\r\n const rotatedElementsMap = new Map<\r\n ExcalidrawElement[\"id\"],\r\n NonDeletedExcalidrawElement\r\n >(elements.map((element) => [element.id, element]));\r\n\r\n for (const element of elements) {\r\n if (!isFrameLikeElement(element)) {\r\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n const origAngle =\r\n originalElements.get(element.id)?.angle ?? element.angle;\r\n const [rotatedCX, rotatedCY] = pointRotateRads(\r\n pointFrom(cx, cy),\r\n pointFrom(centerX, centerY),\r\n (centerAngle + origAngle - element.angle) as Radians,\r\n );\r\n\r\n const updates = isElbowArrow(element)\r\n ? {\r\n // Needed to re-route the arrow\r\n points: getArrowLocalFixedPoints(element, elementsMap),\r\n }\r\n : {\r\n x: element.x + (rotatedCX - cx),\r\n y: element.y + (rotatedCY - cy),\r\n angle: normalizeRadians((centerAngle + origAngle) as Radians),\r\n };\r\n\r\n scene.mutateElement(element, updates);\r\n\r\n updateBoundElements(element, scene, {\r\n simultaneouslyUpdated: elements,\r\n });\r\n\r\n if (isBindingElement(element)) {\r\n if (element.startBinding) {\r\n if (!rotatedElementsMap.has(element.startBinding.elementId)) {\r\n unbindBindingElement(element, \"start\", scene);\r\n }\r\n }\r\n if (element.endBinding) {\r\n if (!rotatedElementsMap.has(element.endBinding.elementId)) {\r\n unbindBindingElement(element, \"end\", scene);\r\n }\r\n }\r\n }\r\n\r\n const boundText = getBoundTextElement(element, elementsMap);\r\n if (boundText && !isArrowElement(element)) {\r\n const { x, y } = computeBoundTextPosition(\r\n element,\r\n boundText,\r\n elementsMap,\r\n );\r\n\r\n scene.mutateElement(boundText, {\r\n x,\r\n y,\r\n angle: normalizeRadians((centerAngle + origAngle) as Radians),\r\n });\r\n }\r\n }\r\n }\r\n\r\n scene.triggerUpdate();\r\n};\r\n\r\nexport const getResizeOffsetXY = (\r\n transformHandleType: MaybeTransformHandleType,\r\n selectedElements: NonDeletedExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n x: number,\r\n y: number,\r\n): [number, number] => {\r\n const [x1, y1, x2, y2] =\r\n selectedElements.length === 1\r\n ? getElementAbsoluteCoords(selectedElements[0], elementsMap)\r\n : getCommonBounds(selectedElements);\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n const angle = (\r\n selectedElements.length === 1 ? selectedElements[0].angle : 0\r\n ) as Radians;\r\n [x, y] = pointRotateRads(\r\n pointFrom(x, y),\r\n pointFrom(cx, cy),\r\n -angle as Radians,\r\n );\r\n switch (transformHandleType) {\r\n case \"n\":\r\n return pointRotateRads(\r\n pointFrom(x - (x1 + x2) / 2, y - y1),\r\n pointFrom(0, 0),\r\n angle,\r\n );\r\n case \"s\":\r\n return pointRotateRads(\r\n pointFrom(x - (x1 + x2) / 2, y - y2),\r\n pointFrom(0, 0),\r\n angle,\r\n );\r\n case \"w\":\r\n return pointRotateRads(\r\n pointFrom(x - x1, y - (y1 + y2) / 2),\r\n pointFrom(0, 0),\r\n angle,\r\n );\r\n case \"e\":\r\n return pointRotateRads(\r\n pointFrom(x - x2, y - (y1 + y2) / 2),\r\n pointFrom(0, 0),\r\n angle,\r\n );\r\n case \"nw\":\r\n return pointRotateRads(pointFrom(x - x1, y - y1), pointFrom(0, 0), angle);\r\n case \"ne\":\r\n return pointRotateRads(pointFrom(x - x2, y - y1), pointFrom(0, 0), angle);\r\n case \"sw\":\r\n return pointRotateRads(pointFrom(x - x1, y - y2), pointFrom(0, 0), angle);\r\n case \"se\":\r\n return pointRotateRads(pointFrom(x - x2, y - y2), pointFrom(0, 0), angle);\r\n default:\r\n return [0, 0];\r\n }\r\n};\r\n\r\nexport const getResizeArrowDirection = (\r\n transformHandleType: MaybeTransformHandleType,\r\n element: NonDeleted<ExcalidrawLinearElement>,\r\n): \"origin\" | \"end\" => {\r\n const [, [px, py]] = element.points;\r\n const isResizeEnd =\r\n (transformHandleType === \"nw\" && (px < 0 || py < 0)) ||\r\n (transformHandleType === \"ne\" && px >= 0) ||\r\n (transformHandleType === \"sw\" && px <= 0) ||\r\n (transformHandleType === \"se\" && (px > 0 || py > 0));\r\n return isResizeEnd ? \"end\" : \"origin\";\r\n};\r\n\r\ntype ResizeAnchor =\r\n | \"top-left\"\r\n | \"top-right\"\r\n | \"bottom-left\"\r\n | \"bottom-right\"\r\n | \"west-side\"\r\n | \"north-side\"\r\n | \"east-side\"\r\n | \"south-side\"\r\n | \"center\";\r\n\r\nconst getResizeAnchor = (\r\n handleDirection: TransformHandleDirection,\r\n shouldMaintainAspectRatio: boolean,\r\n shouldResizeFromCenter: boolean,\r\n): ResizeAnchor => {\r\n if (shouldResizeFromCenter) {\r\n return \"center\";\r\n }\r\n\r\n if (shouldMaintainAspectRatio) {\r\n switch (handleDirection) {\r\n case \"n\":\r\n return \"south-side\";\r\n case \"e\": {\r\n return \"west-side\";\r\n }\r\n case \"s\":\r\n return \"north-side\";\r\n case \"w\":\r\n return \"east-side\";\r\n case \"ne\":\r\n return \"bottom-left\";\r\n case \"nw\":\r\n return \"bottom-right\";\r\n case \"se\":\r\n return \"top-left\";\r\n case \"sw\":\r\n return \"top-right\";\r\n }\r\n }\r\n\r\n if ([\"e\", \"se\", \"s\"].includes(handleDirection)) {\r\n return \"top-left\";\r\n } else if ([\"n\", \"nw\", \"w\"].includes(handleDirection)) {\r\n return \"bottom-right\";\r\n } else if (handleDirection === \"ne\") {\r\n return \"bottom-left\";\r\n }\r\n return \"top-right\";\r\n};\r\n\r\nconst getResizedOrigin = (\r\n prevOrigin: GlobalPoint,\r\n prevWidth: number,\r\n prevHeight: number,\r\n newWidth: number,\r\n newHeight: number,\r\n angle: number,\r\n handleDirection: TransformHandleDirection,\r\n shouldMaintainAspectRatio: boolean,\r\n shouldResizeFromCenter: boolean,\r\n): { x: number; y: number } => {\r\n const anchor = getResizeAnchor(\r\n handleDirection,\r\n shouldMaintainAspectRatio,\r\n shouldResizeFromCenter,\r\n );\r\n\r\n const [x, y] = prevOrigin;\r\n\r\n switch (anchor) {\r\n case \"top-left\":\r\n return {\r\n x:\r\n x +\r\n (prevWidth - newWidth) / 2 +\r\n ((newWidth - prevWidth) / 2) * Math.cos(angle) +\r\n ((prevHeight - newHeight) / 2) * Math.sin(angle),\r\n y:\r\n y +\r\n (prevHeight - newHeight) / 2 +\r\n ((newWidth - prevWidth) / 2) * Math.sin(angle) +\r\n ((newHeight - prevHeight) / 2) * Math.cos(angle),\r\n };\r\n case \"top-right\":\r\n return {\r\n x:\r\n x +\r\n ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1) +\r\n ((prevHeight - newHeight) / 2) * Math.sin(angle),\r\n y:\r\n y +\r\n (prevHeight - newHeight) / 2 +\r\n ((prevWidth - newWidth) / 2) * Math.sin(angle) +\r\n ((newHeight - prevHeight) / 2) * Math.cos(angle),\r\n };\r\n\r\n case \"bottom-left\":\r\n return {\r\n x:\r\n x +\r\n ((prevWidth - newWidth) / 2) * (1 - Math.cos(angle)) +\r\n ((newHeight - prevHeight) / 2) * Math.sin(angle),\r\n y:\r\n y +\r\n ((prevHeight - newHeight) / 2) * (Math.cos(angle) + 1) +\r\n ((newWidth - prevWidth) / 2) * Math.sin(angle),\r\n };\r\n case \"bottom-right\":\r\n return {\r\n x:\r\n x +\r\n ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1) +\r\n ((newHeight - prevHeight) / 2) * Math.sin(angle),\r\n y:\r\n y +\r\n ((prevHeight - newHeight) / 2) * (Math.cos(angle) + 1) +\r\n ((prevWidth - newWidth) / 2) * Math.sin(angle),\r\n };\r\n case \"center\":\r\n return {\r\n x: x - (newWidth - prevWidth) / 2,\r\n y: y - (newHeight - prevHeight) / 2,\r\n };\r\n case \"east-side\":\r\n return {\r\n x: x + ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1),\r\n y:\r\n y +\r\n ((prevWidth - newWidth) / 2) * Math.sin(angle) +\r\n (prevHeight - newHeight) / 2,\r\n };\r\n case \"west-side\":\r\n return {\r\n x: x + ((prevWidth - newWidth) / 2) * (1 - Math.cos(angle)),\r\n y:\r\n y +\r\n ((newWidth - prevWidth) / 2) * Math.sin(angle) +\r\n (prevHeight - newHeight) / 2,\r\n };\r\n case \"north-side\":\r\n return {\r\n x:\r\n x +\r\n (prevWidth - newWidth) / 2 +\r\n ((prevHeight - newHeight) / 2) * Math.sin(angle),\r\n y: y + ((newHeight - prevHeight) / 2) * (Math.cos(angle) - 1),\r\n };\r\n case \"south-side\":\r\n return {\r\n x:\r\n x +\r\n (prevWidth - newWidth) / 2 +\r\n ((newHeight - prevHeight) / 2) * Math.sin(angle),\r\n y: y + ((prevHeight - newHeight) / 2) * (Math.cos(angle) + 1),\r\n };\r\n }\r\n};\r\n\r\nexport const resizeSingleElement = (\r\n nextWidth: number,\r\n nextHeight: number,\r\n latestElement: ExcalidrawElement,\r\n origElement: ExcalidrawElement,\r\n originalElementsMap: ElementsMap,\r\n scene: Scene,\r\n handleDirection: TransformHandleDirection,\r\n {\r\n shouldInformMutation = true,\r\n shouldMaintainAspectRatio = false,\r\n shouldResizeFromCenter = false,\r\n }: {\r\n shouldMaintainAspectRatio?: boolean;\r\n shouldResizeFromCenter?: boolean;\r\n shouldInformMutation?: boolean;\r\n } = {},\r\n) => {\r\n if (isTextElement(latestElement) && isTextElement(origElement)) {\r\n return resizeSingleTextElement(\r\n origElement,\r\n latestElement,\r\n scene,\r\n handleDirection,\r\n shouldResizeFromCenter,\r\n nextWidth,\r\n nextHeight,\r\n );\r\n }\r\n\r\n let boundTextFont: { fontSize?: number } = {};\r\n const elementsMap = scene.getNonDeletedElementsMap();\r\n const boundTextElement = getBoundTextElement(latestElement, elementsMap);\r\n\r\n if (boundTextElement) {\r\n const stateOfBoundTextElementAtResize = originalElementsMap.get(\r\n boundTextElement.id,\r\n ) as typeof boundTextElement | undefined;\r\n if (stateOfBoundTextElementAtResize) {\r\n boundTextFont = {\r\n fontSize: stateOfBoundTextElementAtResize.fontSize,\r\n };\r\n }\r\n if (shouldMaintainAspectRatio) {\r\n const updatedElement = {\r\n ...latestElement,\r\n width: nextWidth,\r\n height: nextHeight,\r\n };\r\n\r\n const nextFont = measureFontSizeFromWidth(\r\n boundTextElement,\r\n elementsMap,\r\n getBoundTextMaxWidth(updatedElement, boundTextElement),\r\n );\r\n if (nextFont === null) {\r\n return;\r\n }\r\n boundTextFont = {\r\n fontSize: nextFont.size,\r\n };\r\n } else {\r\n const minWidth = getApproxMinLineWidth(\r\n getFontString(boundTextElement),\r\n boundTextElement.lineHeight,\r\n );\r\n const minHeight = getApproxMinLineHeight(\r\n boundTextElement.fontSize,\r\n boundTextElement.lineHeight,\r\n );\r\n nextWidth = Math.max(nextWidth, minWidth);\r\n nextHeight = Math.max(nextHeight, minHeight);\r\n }\r\n }\r\n\r\n const rescaledPoints = rescalePointsInElement(\r\n origElement,\r\n nextWidth,\r\n nextHeight,\r\n true,\r\n );\r\n\r\n let previousOrigin = pointFrom<GlobalPoint>(origElement.x, origElement.y);\r\n\r\n if (isLinearElement(origElement)) {\r\n const [x1, y1] = getElementBounds(origElement, originalElementsMap);\r\n previousOrigin = pointFrom<GlobalPoint>(x1, y1);\r\n }\r\n\r\n const newOrigin: {\r\n x: number;\r\n y: number;\r\n } = getResizedOrigin(\r\n previousOrigin,\r\n origElement.width,\r\n origElement.height,\r\n nextWidth,\r\n nextHeight,\r\n origElement.angle,\r\n handleDirection,\r\n shouldMaintainAspectRatio!!,\r\n shouldResizeFromCenter!!,\r\n );\r\n\r\n if (isLinearElement(origElement) && rescaledPoints.points) {\r\n const offsetX = origElement.x - previousOrigin[0];\r\n const offsetY = origElement.y - previousOrigin[1];\r\n\r\n newOrigin.x += offsetX;\r\n newOrigin.y += offsetY;\r\n\r\n const scaledX = rescaledPoints.points[0][0];\r\n const scaledY = rescaledPoints.points[0][1];\r\n\r\n newOrigin.x += scaledX;\r\n newOrigin.y += scaledY;\r\n\r\n rescaledPoints.points = rescaledPoints.points.map((p) =>\r\n pointFrom<LocalPoint>(p[0] - scaledX, p[1] - scaledY),\r\n );\r\n }\r\n\r\n // flipping\r\n if (nextWidth < 0) {\r\n newOrigin.x = newOrigin.x + nextWidth;\r\n }\r\n if (nextHeight < 0) {\r\n newOrigin.y = newOrigin.y + nextHeight;\r\n }\r\n\r\n if (\"scale\" in latestElement && \"scale\" in origElement) {\r\n scene.mutateElement(latestElement, {\r\n scale: [\r\n // defaulting because scaleX/Y can be 0/-0\r\n (Math.sign(nextWidth) || origElement.scale[0]) * origElement.scale[0],\r\n (Math.sign(nextHeight) || origElement.scale[1]) * origElement.scale[1],\r\n ],\r\n });\r\n }\r\n\r\n if (\r\n isArrowElement(latestElement) &&\r\n boundTextElement &&\r\n shouldMaintainAspectRatio\r\n ) {\r\n const fontSize =\r\n (nextWidth / latestElement.width) * boundTextElement.fontSize;\r\n if (fontSize < MIN_FONT_SIZE) {\r\n return;\r\n }\r\n boundTextFont.fontSize = fontSize;\r\n }\r\n\r\n if (\r\n nextWidth !== 0 &&\r\n nextHeight !== 0 &&\r\n Number.isFinite(newOrigin.x) &&\r\n Number.isFinite(newOrigin.y)\r\n ) {\r\n let updates: ElementUpdate<ExcalidrawElement> = {\r\n ...newOrigin,\r\n width: Math.abs(nextWidth),\r\n height: Math.abs(nextHeight),\r\n ...rescaledPoints,\r\n };\r\n\r\n if (isBindingElement(latestElement)) {\r\n if (latestElement.startBinding) {\r\n updates = {\r\n ...updates,\r\n } as ElementUpdate<ExcalidrawArrowElement>;\r\n\r\n if (latestElement.startBinding) {\r\n unbindBindingElement(latestElement, \"start\", scene);\r\n }\r\n }\r\n\r\n if (latestElement.endBinding) {\r\n updates = {\r\n ...updates,\r\n endBinding: null,\r\n } as ElementUpdate<ExcalidrawArrowElement>;\r\n }\r\n }\r\n\r\n scene.mutateElement(latestElement, updates, {\r\n informMutation: shouldInformMutation,\r\n isDragging: false,\r\n });\r\n\r\n if (boundTextElement && boundTextFont != null) {\r\n scene.mutateElement(boundTextElement, {\r\n fontSize: boundTextFont.fontSize,\r\n });\r\n }\r\n handleBindTextResize(\r\n latestElement,\r\n scene,\r\n handleDirection,\r\n shouldMaintainAspectRatio,\r\n );\r\n\r\n updateBoundElements(latestElement, scene);\r\n }\r\n};\r\n\r\nconst getNextSingleWidthAndHeightFromPointer = (\r\n latestElement: ExcalidrawElement,\r\n origElement: ExcalidrawElement,\r\n handleDirection: TransformHandleDirection,\r\n pointerX: number,\r\n pointerY: number,\r\n {\r\n shouldMaintainAspectRatio = false,\r\n shouldResizeFromCenter = false,\r\n }: {\r\n shouldMaintainAspectRatio?: boolean;\r\n shouldResizeFromCenter?: boolean;\r\n } = {},\r\n) => {\r\n // Gets bounds corners\r\n const [x1, y1, x2, y2] = getResizedElementAbsoluteCoords(\r\n origElement,\r\n origElement.width,\r\n origElement.height,\r\n true,\r\n );\r\n const startTopLeft = pointFrom(x1, y1);\r\n const startBottomRight = pointFrom(x2, y2);\r\n const startCenter = pointCenter(startTopLeft, startBottomRight);\r\n\r\n // Calculate new dimensions based on cursor position\r\n const rotatedPointer = pointRotateRads(\r\n pointFrom(pointerX, pointerY),\r\n startCenter,\r\n -origElement.angle as Radians,\r\n );\r\n\r\n // Get bounds corners rendered on screen\r\n const [esx1, esy1, esx2, esy2] = getResizedElementAbsoluteCoords(\r\n latestElement,\r\n latestElement.width,\r\n latestElement.height,\r\n true,\r\n );\r\n\r\n const boundsCurrentWidth = esx2 - esx1;\r\n const boundsCurrentHeight = esy2 - esy1;\r\n\r\n // It's important we set the initial scale value based on the width and height at resize start,\r\n // otherwise previous dimensions affected by modifiers will be taken into account.\r\n const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];\r\n const atStartBoundsHeight = startBottomRight[1] - startTopLeft[1];\r\n let scaleX = atStartBoundsWidth / boundsCurrentWidth;\r\n let scaleY = atStartBoundsHeight / boundsCurrentHeight;\r\n\r\n if (handleDirection.includes(\"e\")) {\r\n scaleX = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;\r\n }\r\n if (handleDirection.includes(\"s\")) {\r\n scaleY = (rotatedPointer[1] - startTopLeft[1]) / boundsCurrentHeight;\r\n }\r\n if (handleDirection.includes(\"w\")) {\r\n scaleX = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;\r\n }\r\n if (handleDirection.includes(\"n\")) {\r\n scaleY = (startBottomRight[1] - rotatedPointer[1]) / boundsCurrentHeight;\r\n }\r\n\r\n // We have to use dimensions of element on screen, otherwise the scaling of the\r\n // dimensions won't match the cursor for linear elements.\r\n let nextWidth = latestElement.width * scaleX;\r\n let nextHeight = latestElement.height * scaleY;\r\n\r\n if (shouldResizeFromCenter) {\r\n nextWidth = 2 * nextWidth - origElement.width;\r\n nextHeight = 2 * nextHeight - origElement.height;\r\n }\r\n\r\n // adjust dimensions to keep sides ratio\r\n if (shouldMaintainAspectRatio) {\r\n const widthRatio = Math.abs(nextWidth) / origElement.width;\r\n const heightRatio = Math.abs(nextHeight) / origElement.height;\r\n if (handleDirection.length === 1) {\r\n nextHeight *= widthRatio;\r\n nextWidth *= heightRatio;\r\n }\r\n if (handleDirection.length === 2) {\r\n const ratio = Math.max(widthRatio, heightRatio);\r\n nextWidth = origElement.width * ratio * Math.sign(nextWidth);\r\n nextHeight = origElement.height * ratio * Math.sign(nextHeight);\r\n }\r\n }\r\n\r\n return {\r\n nextWidth,\r\n nextHeight,\r\n };\r\n};\r\n\r\nconst getNextMultipleWidthAndHeightFromPointer = (\r\n selectedElements: readonly NonDeletedExcalidrawElement[],\r\n originalElementsMap: ElementsMap,\r\n elementsMap: ElementsMap,\r\n handleDirection: TransformHandleDirection,\r\n pointerX: number,\r\n pointerY: number,\r\n {\r\n shouldMaintainAspectRatio = false,\r\n shouldResizeFromCenter = false,\r\n }: {\r\n shouldResizeFromCenter?: boolean;\r\n shouldMaintainAspectRatio?: boolean;\r\n } = {},\r\n) => {\r\n const originalElementsArray = selectedElements.map(\r\n (el) => originalElementsMap.get(el.id)!,\r\n );\r\n\r\n // getCommonBoundingBox() uses getBoundTextElement() which returns null for\r\n // original elements from pointerDownState, so we have to find and add these\r\n // bound text elements manually. Additionally, the coordinates of bound text\r\n // elements aren't always up to date.\r\n const boundTextElements = originalElementsArray.reduce((acc, orig) => {\r\n if (!isLinearElement(orig)) {\r\n return acc;\r\n }\r\n const textId = getBoundTextElementId(orig);\r\n if (!textId) {\r\n return acc;\r\n }\r\n const text = originalElementsMap.get(textId) ?? null;\r\n if (!isBoundToContainer(text)) {\r\n return acc;\r\n }\r\n return [\r\n ...acc,\r\n {\r\n ...text,\r\n ...LinearElementEditor.getBoundTextElementPosition(\r\n orig,\r\n text,\r\n elementsMap,\r\n ),\r\n },\r\n ];\r\n }, [] as ExcalidrawTextElementWithContainer[]);\r\n\r\n const originalBoundingBox = getCommonBoundingBox(\r\n originalElementsArray.map((orig) => orig).concat(boundTextElements),\r\n );\r\n\r\n const { minX, minY, maxX, maxY, midX, midY } = originalBoundingBox;\r\n const width = maxX - minX;\r\n const height = maxY - minY;\r\n\r\n const anchorsMap = {\r\n ne: [minX, maxY],\r\n se: [minX, minY],\r\n sw: [maxX, minY],\r\n nw: [maxX, maxY],\r\n e: [minX, minY + height / 2],\r\n w: [maxX, minY + height / 2],\r\n n: [minX + width / 2, maxY],\r\n s: [minX + width / 2, minY],\r\n } as Record<TransformHandleDirection, GlobalPoint>;\r\n\r\n // anchor point must be on the opposite side of the dragged selection handle\r\n // or be the center of the selection if shouldResizeFromCenter\r\n const [anchorX, anchorY] = shouldResizeFromCenter\r\n ? [midX, midY]\r\n : anchorsMap[handleDirection];\r\n\r\n const resizeFromCenterScale = shouldResizeFromCenter ? 2 : 1;\r\n\r\n const scale =\r\n Math.max(\r\n Math.abs(pointerX - anchorX) / width || 0,\r\n Math.abs(pointerY - anchorY) / height || 0,\r\n ) * resizeFromCenterScale;\r\n\r\n let nextWidth =\r\n handleDirection.includes(\"e\") || handleDirection.includes(\"w\")\r\n ? Math.abs(pointerX - anchorX) * resizeFromCenterScale\r\n : width;\r\n let nextHeight =\r\n handleDirection.includes(\"n\") || handleDirection.includes(\"s\")\r\n ? Math.abs(pointerY - anchorY) * resizeFromCenterScale\r\n : height;\r\n\r\n if (shouldMaintainAspectRatio) {\r\n nextWidth = width * scale * Math.sign(pointerX - anchorX);\r\n nextHeight = height * scale * Math.sign(pointerY - anchorY);\r\n }\r\n\r\n const flipConditionsMap: Record<\r\n TransformHandleDirection,\r\n // Condition for which we should flip or not flip the selected elements\r\n // - when evaluated to `true`, we flip\r\n // - therefore, setting it to always `false` means we do not flip (in that direction) at all\r\n [x: boolean, y: boolean]\r\n > = {\r\n ne: [pointerX < anchorX, pointerY > anchorY],\r\n se: [pointerX < anchorX, pointerY < anchorY],\r\n sw: [pointerX > anchorX, pointerY < anchorY],\r\n nw: [pointerX > anchorX, pointerY > anchorY],\r\n // e.g. when resizing from the \"e\" side, we do not need to consider changes in the `y` direction\r\n // and therefore, we do not need to flip in the `y` direction at all\r\n e: [pointerX < anchorX, false],\r\n w: [pointerX > anchorX, false],\r\n n: [false, pointerY > anchorY],\r\n s: [false, pointerY < anchorY],\r\n };\r\n\r\n const [flipByX, flipByY] = flipConditionsMap[handleDirection].map(\r\n (condition) => condition,\r\n );\r\n\r\n return {\r\n originalBoundingBox,\r\n nextWidth,\r\n nextHeight,\r\n flipByX,\r\n flipByY,\r\n };\r\n};\r\n\r\nexport const resizeMultipleElements = (\r\n selectedElements: readonly NonDeletedExcalidrawElement[],\r\n elementsMap: ElementsMap,\r\n handleDirection: TransformHandleDirection,\r\n scene: Scene,\r\n originalElementsMap: ElementsMap,\r\n {\r\n shouldMaintainAspectRatio = false,\r\n shouldResizeFromCenter = false,\r\n flipByX = false,\r\n flipByY = false,\r\n nextHeight,\r\n nextWidth,\r\n originalBoundingBox,\r\n }: {\r\n nextWidth?: number;\r\n nextHeight?: number;\r\n shouldMaintainAspectRatio?: boolean;\r\n shouldResizeFromCenter?: boolean;\r\n flipByX?: boolean;\r\n flipByY?: boolean;\r\n // added to improve performance\r\n originalBoundingBox?: BoundingBox;\r\n } = {},\r\n) => {\r\n // in the case of just flipping, there is no need to specify the next width and height\r\n if (\r\n nextWidth === undefined &&\r\n nextHeight === undefined &&\r\n flipByX === undefined &&\r\n flipByY === undefined\r\n ) {\r\n return;\r\n }\r\n\r\n // do not allow next width or height to be 0\r\n if (nextHeight === 0 || nextWidth === 0) {\r\n return;\r\n }\r\n\r\n if (!originalElementsMap) {\r\n originalElementsMap = elementsMap;\r\n }\r\n\r\n const targetElements = selectedElements.reduce(\r\n (\r\n acc: {\r\n /** element at resize start */\r\n orig: NonDeletedExcalidrawElement;\r\n /** latest element */\r\n latest: NonDeletedExcalidrawElement;\r\n }[],\r\n element,\r\n ) => {\r\n const origElement = originalElementsMap!.get(element.id);\r\n if (origElement) {\r\n acc.push({ orig: origElement, latest: element });\r\n }\r\n return acc;\r\n },\r\n [],\r\n );\r\n\r\n let boundingBox: BoundingBox;\r\n\r\n if (originalBoundingBox) {\r\n boundingBox = originalBoundingBox;\r\n } else {\r\n const boundTextElements = targetElements.reduce((acc, { orig }) => {\r\n if (!isLinearElement(orig)) {\r\n return acc;\r\n }\r\n const textId = getBoundTextElementId(orig);\r\n if (!textId) {\r\n return acc;\r\n }\r\n const text = originalElementsMap!.get(textId) ?? null;\r\n if (!isBoundToContainer(text)) {\r\n return acc;\r\n }\r\n return [\r\n ...acc,\r\n {\r\n ...text,\r\n ...LinearElementEditor.getBoundTextElementPosition(\r\n orig,\r\n text,\r\n elementsMap,\r\n ),\r\n },\r\n ];\r\n }, [] as ExcalidrawTextElementWithContainer[]);\r\n\r\n boundingBox = getCommonBoundingBox(\r\n targetElements.map(({ orig }) => orig).concat(boundTextElements),\r\n );\r\n }\r\n const { minX, minY, maxX, maxY, midX, midY } = boundingBox;\r\n const width = maxX - minX;\r\n const height = maxY - minY;\r\n\r\n if (nextWidth === undefined && nextHeight === undefined) {\r\n nextWidth = width;\r\n nextHeight = height;\r\n }\r\n\r\n if (shouldMaintainAspectRatio) {\r\n if (nextWidth === undefined) {\r\n nextWidth = nextHeight! * (width / height);\r\n } else if (nextHeight === undefined) {\r\n nextHeight = nextWidth! * (height / width);\r\n } else if (Math.abs(nextWidth / nextHeight - width / height) > 0.001) {\r\n nextWidth = nextHeight * (width / height);\r\n }\r\n }\r\n\r\n if (nextWidth && nextHeight) {\r\n let scaleX =\r\n handleDirection.includes(\"e\") || handleDirection.includes(\"w\")\r\n ? Math.abs(nextWidth) / width\r\n : 1;\r\n let scaleY =\r\n handleDirection.includes(\"n\") || handleDirection.includes(\"s\")\r\n ? Math.abs(nextHeight) / height\r\n : 1;\r\n\r\n let scale: number;\r\n\r\n if (handleDirection.length === 1) {\r\n scale =\r\n handleDirection.includes(\"e\") || handleDirection.includes(\"w\")\r\n ? scaleX\r\n : scaleY;\r\n } else {\r\n scale = Math.max(\r\n Math.abs(nextWidth) / width || 0,\r\n Math.abs(nextHeight) / height || 0,\r\n );\r\n }\r\n\r\n const anchorsMap = {\r\n ne: [minX, maxY],\r\n se: [minX, minY],\r\n sw: [maxX, minY],\r\n nw: [maxX, maxY],\r\n e: [minX, minY + height / 2],\r\n w: [maxX, minY + height / 2],\r\n n: [minX + width / 2, maxY],\r\n s: [minX + width / 2, minY],\r\n } as Record<TransformHandleDirection, GlobalPoint>;\r\n\r\n // anchor point must be on the opposite side of the dragged selection handle\r\n // or be the center of the selection if shouldResizeFromCenter\r\n const [anchorX, anchorY] = shouldResizeFromCenter\r\n ? [midX, midY]\r\n : anchorsMap[handleDirection];\r\n\r\n const keepAspectRatio =\r\n shouldMaintainAspectRatio ||\r\n targetElements.some(\r\n (item) =>\r\n item.latest.angle !== 0 ||\r\n isTextElement(item.latest) ||\r\n isInGroup(item.latest),\r\n );\r\n\r\n if (keepAspectRatio) {\r\n scaleX = scale;\r\n scaleY = scale;\r\n }\r\n\r\n /**\r\n * to flip an element:\r\n * 1. determine over which axis is the element being flipped\r\n * (could be x, y, or both) indicated by `flipFactorX` & `flipFactorY`\r\n * 2. shift element's position by the amount of width or height (or both) or\r\n * mirror points in the case of linear & freedraw elemenets\r\n * 3. adjust element angle\r\n */\r\n const [flipFactorX, flipFactorY] = [flipByX ? -1 : 1, flipByY ? -1 : 1];\r\n\r\n const elementsAndUpdates: {\r\n element: NonDeletedExcalidrawElement;\r\n update: Mutable<\r\n Pick<ExcalidrawElement, \"x\" | \"y\" | \"width\" | \"height\" | \"angle\">\r\n > & {\r\n points?: ExcalidrawLinearElement[\"points\"];\r\n fontSize?: ExcalidrawTextElement[\"fontSize\"];\r\n scale?: ExcalidrawImageElement[\"scale\"];\r\n boundTextFontSize?: ExcalidrawTextElement[\"fontSize\"];\r\n startBinding?: ExcalidrawElbowArrowElement[\"startBinding\"];\r\n endBinding?: ExcalidrawElbowArrowElement[\"endBinding\"];\r\n fixedSegments?: ExcalidrawElbowArrowElement[\"fixedSegments\"];\r\n };\r\n }[] = [];\r\n\r\n for (const { orig, latest } of targetElements) {\r\n // bounded text elements are updated along with their container elements\r\n if (isTextElement(orig) && isBoundToContainer(orig)) {\r\n continue;\r\n }\r\n\r\n const width = orig.width * scaleX;\r\n const height = orig.height * scaleY;\r\n const angle = normalizeRadians(\r\n (orig.angle * flipFactorX * flipFactorY) as Radians,\r\n );\r\n\r\n const isLinearOrFreeDraw =\r\n isLinearElement(orig) || isFreeDrawElement(orig);\r\n const offsetX = orig.x - anchorX;\r\n const offsetY = orig.y - anchorY;\r\n const shiftX = flipByX && !isLinearOrFreeDraw ? width : 0;\r\n const shiftY = flipByY && !isLinearOrFreeDraw ? height : 0;\r\n const x = anchorX + flipFactorX * (offsetX * scaleX + shiftX);\r\n const y = anchorY + flipFactorY * (offsetY * scaleY + shiftY);\r\n\r\n const rescaledPoints = rescalePointsInElement(\r\n orig,\r\n width * flipFactorX,\r\n height * flipFactorY,\r\n false,\r\n );\r\n\r\n const update: typeof elementsAndUpdates[0][\"update\"] = {\r\n x,\r\n y,\r\n width,\r\n height,\r\n angle,\r\n ...rescaledPoints,\r\n };\r\n\r\n if (isElbowArrow(orig)) {\r\n // Mirror fixed point binding for elbow arrows\r\n // when resize goes into the negative direction\r\n if (orig.startBinding) {\r\n update.startBinding = {\r\n ...orig.startBinding,\r\n fixedPoint: [\r\n flipByX\r\n ? -orig.startBinding.fixedPoint[0] + 1\r\n : orig.startBinding.fixedPoint[0],\r\n flipByY\r\n ? -orig.startBinding.fixedPoint[1] + 1\r\n : orig.startBinding.fixedPoint[1],\r\n ],\r\n };\r\n }\r\n if (orig.endBinding) {\r\n update.endBinding = {\r\n ...orig.endBinding,\r\n fixedPoint: [\r\n flipByX\r\n ? -orig.endBinding.fixedPoint[0] + 1\r\n : orig.endBinding.fixedPoint[0],\r\n flipByY\r\n ? -orig.endBinding.fixedPoint[1] + 1\r\n : orig.endBinding.fixedPoint[1],\r\n ],\r\n };\r\n }\r\n if (orig.fixedSegments && rescaledPoints.points) {\r\n update.fixedSegments = orig.fixedSegments.map((segment) => ({\r\n ...segment,\r\n start: rescaledPoints.points[segment.index - 1],\r\n end: rescaledPoints.points[segment.index],\r\n }));\r\n }\r\n }\r\n\r\n if (isImageElement(orig)) {\r\n update.scale = [\r\n orig.scale[0] * flipFactorX,\r\n orig.scale[1] * flipFactorY,\r\n ];\r\n }\r\n\r\n if (isTextElement(orig)) {\r\n const metrics = measureFontSizeFromWidth(orig, elementsMap, width);\r\n if (!metrics) {\r\n return;\r\n }\r\n update.fontSize = metrics.size;\r\n }\r\n\r\n const boundTextElement = originalElementsMap.get(\r\n getBoundTextElementId(orig) ?? \"\",\r\n ) as ExcalidrawTextElementWithContainer | undefined;\r\n\r\n if (boundTextElement) {\r\n if (keepAspectRatio) {\r\n const newFontSize = boundTextElement.fontSize * scale;\r\n if (newFontSize < MIN_FONT_SIZE) {\r\n return;\r\n }\r\n update.boundTextFontSize = newFontSize;\r\n } else {\r\n update.boundTextFontSize = boundTextElement.fontSize;\r\n }\r\n }\r\n\r\n elementsAndUpdates.push({\r\n element: latest,\r\n update,\r\n });\r\n }\r\n\r\n const elementsToUpdate = elementsAndUpdates.map(({ element }) => element);\r\n const resizedElementsMap = new Map<\r\n ExcalidrawElement[\"id\"],\r\n NonDeletedExcalidrawElement\r\n >(elementsAndUpdates.map(({ element }) => [element.id, element]));\r\n\r\n for (const {\r\n element,\r\n update: { boundTextFontSize, ...update },\r\n } of elementsAndUpdates) {\r\n const { angle } = update;\r\n\r\n scene.mutateElement(element, update);\r\n\r\n updateBoundElements(element, scene, {\r\n simultaneouslyUpdated: elementsToUpdate,\r\n });\r\n\r\n if (isBindingElement(element)) {\r\n if (element.startBinding) {\r\n if (!resizedElementsMap.has(element.startBinding.elementId)) {\r\n unbindBindingElement(element, \"start\", scene);\r\n }\r\n }\r\n if (element.endBinding) {\r\n if (!resizedElementsMap.has(element.endBinding.elementId)) {\r\n unbindBindingElement(element, \"end\", scene);\r\n }\r\n }\r\n }\r\n\r\n const boundTextElement = getBoundTextElement(element, elementsMap);\r\n if (boundTextElement && boundTextFontSize) {\r\n scene.mutateElement(boundTextElement, {\r\n fontSize: boundTextFontSize,\r\n angle: isLinearElement(element) ? undefined : angle,\r\n });\r\n handleBindTextResize(element, scene, handleDirection, true);\r\n }\r\n }\r\n\r\n scene.triggerUpdate();\r\n }\r\n};\r\n", "import {\r\n pointFrom,\r\n pointOnLineSegment,\r\n pointRotateRads,\r\n type Radians,\r\n} from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n SIDE_RESIZING_THRESHOLD,\r\n type EditorInterface,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { GlobalPoint, LineSegment, LocalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport type { AppState, Zoom } from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { Bounds } from \"@excalidraw-modify/common\";\r\n\r\nimport { getElementAbsoluteCoords } from \"./bounds\";\r\nimport {\r\n getTransformHandlesFromCoords,\r\n getTransformHandles,\r\n getOmitSidesForEditorInterface,\r\n canResizeFromSides,\r\n} from \"./transformHandles\";\r\nimport { isImageElement, isLinearElement } from \"./typeChecks\";\r\n\r\nimport type {\r\n TransformHandleType,\r\n TransformHandle,\r\n MaybeTransformHandleType,\r\n} from \"./transformHandles\";\r\nimport type {\r\n ExcalidrawElement,\r\n PointerType,\r\n NonDeletedExcalidrawElement,\r\n ElementsMap,\r\n} from \"./types\";\r\n\r\nconst isInsideTransformHandle = (\r\n transformHandle: TransformHandle,\r\n x: number,\r\n y: number,\r\n) =>\r\n x >= transformHandle[0] &&\r\n x <= transformHandle[0] + transformHandle[2] &&\r\n y >= transformHandle[1] &&\r\n y <= transformHandle[1] + transformHandle[3];\r\n\r\nexport const resizeTest = <Point extends GlobalPoint | LocalPoint>(\r\n element: NonDeletedExcalidrawElement,\r\n elementsMap: ElementsMap,\r\n appState: AppState,\r\n x: number,\r\n y: number,\r\n zoom: Zoom,\r\n pointerType: PointerType,\r\n editorInterface: EditorInterface,\r\n): MaybeTransformHandleType => {\r\n if (!appState.selectedElementIds[element.id]) {\r\n return false;\r\n }\r\n\r\n const { rotation: rotationTransformHandle, ...transformHandles } =\r\n getTransformHandles(\r\n element,\r\n zoom,\r\n elementsMap,\r\n pointerType,\r\n getOmitSidesForEditorInterface(editorInterface),\r\n );\r\n\r\n if (\r\n rotationTransformHandle &&\r\n isInsideTransformHandle(rotationTransformHandle, x, y)\r\n ) {\r\n return \"rotation\" as TransformHandleType;\r\n }\r\n\r\n const filter = Object.keys(transformHandles).filter((key) => {\r\n const transformHandle =\r\n transformHandles[key as Exclude<TransformHandleType, \"rotation\">]!;\r\n if (!transformHandle) {\r\n return false;\r\n }\r\n return isInsideTransformHandle(transformHandle, x, y);\r\n });\r\n\r\n if (filter.length > 0) {\r\n return filter[0] as TransformHandleType;\r\n }\r\n\r\n if (canResizeFromSides(editorInterface)) {\r\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\r\n element,\r\n elementsMap,\r\n );\r\n\r\n // do not resize from the sides for linear elements with only two points\r\n if (!(isLinearElement(element) && element.points.length <= 2)) {\r\n const SPACING = isImageElement(element)\r\n ? 0\r\n : SIDE_RESIZING_THRESHOLD / zoom.value;\r\n const ZOOMED_SIDE_RESIZING_THRESHOLD =\r\n SIDE_RESIZING_THRESHOLD / zoom.value;\r\n const sides = getSelectionBorders(\r\n pointFrom(x1 - SPACING, y1 - SPACING),\r\n pointFrom(x2 + SPACING, y2 + SPACING),\r\n pointFrom(cx, cy),\r\n element.angle,\r\n );\r\n\r\n for (const [dir, side] of Object.entries(sides)) {\r\n // test to see if x, y are on the line segment\r\n if (\r\n pointOnLineSegment(\r\n pointFrom(x, y),\r\n side as LineSegment<Point>,\r\n ZOOMED_SIDE_RESIZING_THRESHOLD,\r\n )\r\n ) {\r\n return dir as TransformHandleType;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport const getElementWithTransformHandleType = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n appState: AppState,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n zoom: Zoom,\r\n pointerType: PointerType,\r\n elementsMap: ElementsMap,\r\n editorInterface: EditorInterface,\r\n) => {\r\n return elements.reduce((result, element) => {\r\n if (result) {\r\n return result;\r\n }\r\n const transformHandleType = resizeTest(\r\n element,\r\n elementsMap,\r\n appState,\r\n scenePointerX,\r\n scenePointerY,\r\n zoom,\r\n pointerType,\r\n editorInterface,\r\n );\r\n return transformHandleType ? { element, transformHandleType } : null;\r\n }, null as { element: NonDeletedExcalidrawElement; transformHandleType: MaybeTransformHandleType } | null);\r\n};\r\n\r\nexport const getTransformHandleTypeFromCoords = <\r\n Point extends GlobalPoint | LocalPoint,\r\n>(\r\n [x1, y1, x2, y2]: Bounds,\r\n scenePointerX: number,\r\n scenePointerY: number,\r\n zoom: Zoom,\r\n pointerType: PointerType,\r\n editorInterface: EditorInterface,\r\n): MaybeTransformHandleType => {\r\n const transformHandles = getTransformHandlesFromCoords(\r\n [x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2],\r\n 0 as Radians,\r\n zoom,\r\n pointerType,\r\n getOmitSidesForEditorInterface(editorInterface),\r\n );\r\n\r\n const found = Object.keys(transformHandles).find((key) => {\r\n const transformHandle =\r\n transformHandles[key as Exclude<TransformHandleType, \"rotation\">]!;\r\n return (\r\n transformHandle &&\r\n isInsideTransformHandle(transformHandle, scenePointerX, scenePointerY)\r\n );\r\n });\r\n\r\n if (found) {\r\n return found as MaybeTransformHandleType;\r\n }\r\n\r\n if (canResizeFromSides(editorInterface)) {\r\n const cx = (x1 + x2) / 2;\r\n const cy = (y1 + y2) / 2;\r\n\r\n const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;\r\n\r\n const sides = getSelectionBorders(\r\n pointFrom(x1 - SPACING, y1 - SPACING),\r\n pointFrom(x2 + SPACING, y2 + SPACING),\r\n pointFrom(cx, cy),\r\n 0 as Radians,\r\n );\r\n\r\n for (const [dir, side] of Object.entries(sides)) {\r\n // test to see if x, y are on the line segment\r\n if (\r\n pointOnLineSegment(\r\n pointFrom(scenePointerX, scenePointerY),\r\n side as LineSegment<Point>,\r\n SPACING,\r\n )\r\n ) {\r\n return dir as TransformHandleType;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst RESIZE_CURSORS = [\"ns\", \"nesw\", \"ew\", \"nwse\"];\r\nconst rotateResizeCursor = (cursor: string, angle: number) => {\r\n const index = RESIZE_CURSORS.indexOf(cursor);\r\n if (index >= 0) {\r\n const a = Math.round(angle / (Math.PI / 4));\r\n cursor = RESIZE_CURSORS[(index + a) % RESIZE_CURSORS.length];\r\n }\r\n return cursor;\r\n};\r\n\r\n/*\r\n * Returns bi-directional cursor for the element being resized\r\n */\r\nexport const getCursorForResizingElement = (resizingElement: {\r\n element?: ExcalidrawElement;\r\n transformHandleType: MaybeTransformHandleType;\r\n}): string => {\r\n const { element, transformHandleType } = resizingElement;\r\n const shouldSwapCursors =\r\n element && Math.sign(element.height) * Math.sign(element.width) === -1;\r\n let cursor = null;\r\n\r\n switch (transformHandleType) {\r\n case \"n\":\r\n case \"s\":\r\n cursor = \"ns\";\r\n break;\r\n case \"w\":\r\n case \"e\":\r\n cursor = \"ew\";\r\n break;\r\n case \"nw\":\r\n case \"se\":\r\n if (shouldSwapCursors) {\r\n cursor = \"nesw\";\r\n } else {\r\n cursor = \"nwse\";\r\n }\r\n break;\r\n case \"ne\":\r\n case \"sw\":\r\n if (shouldSwapCursors) {\r\n cursor = \"nwse\";\r\n } else {\r\n cursor = \"nesw\";\r\n }\r\n break;\r\n case \"rotation\":\r\n return \"grab\";\r\n }\r\n\r\n if (cursor && element) {\r\n cursor = rotateResizeCursor(cursor, element.angle);\r\n }\r\n\r\n return cursor ? `${cursor}-resize` : \"\";\r\n};\r\n\r\nconst getSelectionBorders = <Point extends LocalPoint | GlobalPoint>(\r\n [x1, y1]: Point,\r\n [x2, y2]: Point,\r\n center: Point,\r\n angle: Radians,\r\n) => {\r\n const topLeft = pointRotateRads(pointFrom(x1, y1), center, angle);\r\n const topRight = pointRotateRads(pointFrom(x2, y1), center, angle);\r\n const bottomLeft = pointRotateRads(pointFrom(x1, y2), center, angle);\r\n const bottomRight = pointRotateRads(pointFrom(x2, y2), center, angle);\r\n\r\n return {\r\n n: [topLeft, topRight],\r\n e: [topRight, bottomRight],\r\n s: [bottomRight, bottomLeft],\r\n w: [bottomLeft, topLeft],\r\n };\r\n};\r\n", "import {\r\n DEFAULT_TRANSFORM_HANDLE_SPACING,\r\n type EditorInterface,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport { pointFrom, pointRotateRads } from \"@excalidraw-modify/math\";\r\n\r\nimport type { Radians } from \"@excalidraw-modify/math\";\r\n\r\nimport type {\r\n InteractiveCanvasAppState,\r\n Zoom,\r\n} from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { Bounds } from \"@excalidraw-modify/common\";\r\n\r\nimport { getElementAbsoluteCoords } from \"./bounds\";\r\nimport {\r\n isElbowArrow,\r\n isFrameLikeElement,\r\n isImageElement,\r\n isLinearElement,\r\n} from \"./typeChecks\";\r\n\r\nimport type {\r\n ElementsMap,\r\n ExcalidrawElement,\r\n NonDeletedExcalidrawElement,\r\n PointerType,\r\n} from \"./types\";\r\n\r\nexport type TransformHandleDirection =\r\n | \"n\"\r\n | \"s\"\r\n | \"w\"\r\n | \"e\"\r\n | \"nw\"\r\n | \"ne\"\r\n | \"sw\"\r\n | \"se\";\r\n\r\nexport type TransformHandleType = TransformHandleDirection | \"rotation\";\r\n\r\nexport type TransformHandle = Bounds;\r\nexport type TransformHandles = Partial<{\r\n [T in TransformHandleType]: TransformHandle;\r\n}>;\r\nexport type MaybeTransformHandleType = TransformHandleType | false;\r\n\r\nconst transformHandleSizes: { [k in PointerType]: number } = {\r\n mouse: 8,\r\n pen: 16,\r\n touch: 28,\r\n};\r\n\r\nconst ROTATION_RESIZE_HANDLE_GAP = 16;\r\n\r\nexport const DEFAULT_OMIT_SIDES = {\r\n e: true,\r\n s: true,\r\n n: true,\r\n w: true,\r\n};\r\n\r\nexport const OMIT_SIDES_FOR_MULTIPLE_ELEMENTS = {\r\n e: true,\r\n s: true,\r\n n: true,\r\n w: true,\r\n};\r\n\r\nexport const OMIT_SIDES_FOR_FRAME = {\r\n e: true,\r\n s: true,\r\n n: true,\r\n w: true,\r\n rotation: true,\r\n};\r\n\r\nconst OMIT_SIDES_FOR_LINE_SLASH = {\r\n e: true,\r\n s: true,\r\n n: true,\r\n w: true,\r\n nw: true,\r\n se: true,\r\n};\r\n\r\nconst OMIT_SIDES_FOR_LINE_BACKSLASH = {\r\n e: true,\r\n s: true,\r\n n: true,\r\n w: true,\r\n};\r\n\r\nconst generateTransformHandle = (\r\n x: number,\r\n y: number,\r\n width: number,\r\n height: number,\r\n cx: number,\r\n cy: number,\r\n angle: Radians,\r\n): TransformHandle => {\r\n const [xx, yy] = pointRotateRads(\r\n pointFrom(x + width / 2, y + height / 2),\r\n pointFrom(cx, cy),\r\n angle,\r\n );\r\n return [xx - width / 2, yy - height / 2, width, height];\r\n};\r\n\r\nexport const canResizeFromSides = (editorInterface: EditorInterface) => {\r\n if (\r\n editorInterface.formFactor === \"phone\" &&\r\n editorInterface.userAgent.isMobileDevice\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\nexport const getOmitSidesForEditorInterface = (\r\n editorInterface: EditorInterface,\r\n) => {\r\n if (canResizeFromSides(editorInterface)) {\r\n return DEFAULT_OMIT_SIDES;\r\n }\r\n\r\n return {};\r\n};\r\n\r\nexport const getTransformHandlesFromCoords = (\r\n [x1, y1, x2, y2, cx, cy]: [number, number, number, number, number, number],\r\n angle: Radians,\r\n zoom: Zoom,\r\n pointerType: PointerType,\r\n omitSides: { [T in TransformHandleType]?: boolean } = {},\r\n margin = 4,\r\n spacing = DEFAULT_TRANSFORM_HANDLE_SPACING,\r\n): TransformHandles => {\r\n const size = transformHandleSizes[pointerType];\r\n const handleWidth = size / zoom.value;\r\n const handleHeight = size / zoom.value;\r\n\r\n const handleMarginX = size / zoom.value;\r\n const handleMarginY = size / zoom.value;\r\n\r\n const width = x2 - x1;\r\n const height = y2 - y1;\r\n const dashedLineMargin = margin / zoom.value;\r\n const centeringOffset = (size - spacing * 2) / (2 * zoom.value);\r\n\r\n const transformHandles: TransformHandles = {\r\n nw: omitSides.nw\r\n ? undefined\r\n : generateTransformHandle(\r\n x1 - dashedLineMargin - handleMarginX + centeringOffset,\r\n y1 - dashedLineMargin - handleMarginY + centeringOffset,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n ),\r\n ne: omitSides.ne\r\n ? undefined\r\n : generateTransformHandle(\r\n x2 + dashedLineMargin - centeringOffset,\r\n y1 - dashedLineMargin - handleMarginY + centeringOffset,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n ),\r\n sw: omitSides.sw\r\n ? undefined\r\n : generateTransformHandle(\r\n x1 - dashedLineMargin - handleMarginX + centeringOffset,\r\n y2 + dashedLineMargin - centeringOffset,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n ),\r\n se: omitSides.se\r\n ? undefined\r\n : generateTransformHandle(\r\n x2 + dashedLineMargin - centeringOffset,\r\n y2 + dashedLineMargin - centeringOffset,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n ),\r\n rotation: omitSides.rotation\r\n ? undefined\r\n : generateTransformHandle(\r\n x1 + width / 2 - handleWidth / 2,\r\n y1 -\r\n dashedLineMargin -\r\n handleMarginY +\r\n centeringOffset -\r\n ROTATION_RESIZE_HANDLE_GAP / zoom.value,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n ),\r\n };\r\n\r\n // We only want to show height handles (all cardinal directions) above a certain size\r\n // Note: we render using \"mouse\" size so we should also use \"mouse\" size for this check\r\n const minimumSizeForEightHandles =\r\n (5 * transformHandleSizes.mouse) / zoom.value;\r\n if (Math.abs(width) > minimumSizeForEightHandles) {\r\n if (!omitSides.n) {\r\n transformHandles.n = generateTransformHandle(\r\n x1 + width / 2 - handleWidth / 2,\r\n y1 - dashedLineMargin - handleMarginY + centeringOffset,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n );\r\n }\r\n if (!omitSides.s) {\r\n transformHandles.s = generateTransformHandle(\r\n x1 + width / 2 - handleWidth / 2,\r\n y2 + dashedLineMargin - centeringOffset,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n );\r\n }\r\n }\r\n if (Math.abs(height) > minimumSizeForEightHandles) {\r\n if (!omitSides.w) {\r\n transformHandles.w = generateTransformHandle(\r\n x1 - dashedLineMargin - handleMarginX + centeringOffset,\r\n y1 + height / 2 - handleHeight / 2,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n );\r\n }\r\n if (!omitSides.e) {\r\n transformHandles.e = generateTransformHandle(\r\n x2 + dashedLineMargin - centeringOffset,\r\n y1 + height / 2 - handleHeight / 2,\r\n handleWidth,\r\n handleHeight,\r\n cx,\r\n cy,\r\n angle,\r\n );\r\n }\r\n }\r\n\r\n return transformHandles;\r\n};\r\n\r\nexport const getTransformHandles = (\r\n element: ExcalidrawElement,\r\n zoom: Zoom,\r\n elementsMap: ElementsMap,\r\n pointerType: PointerType = \"mouse\",\r\n omitSides: { [T in TransformHandleType]?: boolean } = DEFAULT_OMIT_SIDES,\r\n): TransformHandles => {\r\n // so that when locked element is selected (especially when you toggle lock\r\n // via keyboard) the locked element is visually distinct, indicating\r\n // you can't move/resize\r\n if (\r\n element.locked ||\r\n // Elbow arrows cannot be rotated\r\n isElbowArrow(element)\r\n ) {\r\n return {};\r\n }\r\n\r\n if (element.type === \"freedraw\" || isLinearElement(element)) {\r\n if (element.points.length === 2) {\r\n // only check the last point because starting point is always (0,0)\r\n const [, p1] = element.points;\r\n if (p1[0] === 0 || p1[1] === 0) {\r\n omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;\r\n } else if (p1[0] > 0 && p1[1] < 0) {\r\n omitSides = OMIT_SIDES_FOR_LINE_SLASH;\r\n } else if (p1[0] > 0 && p1[1] > 0) {\r\n omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;\r\n } else if (p1[0] < 0 && p1[1] > 0) {\r\n omitSides = OMIT_SIDES_FOR_LINE_SLASH;\r\n } else if (p1[0] < 0 && p1[1] < 0) {\r\n omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;\r\n }\r\n }\r\n } else if (isFrameLikeElement(element)) {\r\n omitSides = {\r\n ...omitSides,\r\n rotation: true,\r\n };\r\n }\r\n const margin = isLinearElement(element)\r\n ? DEFAULT_TRANSFORM_HANDLE_SPACING + 8\r\n : isImageElement(element)\r\n ? 0\r\n : DEFAULT_TRANSFORM_HANDLE_SPACING;\r\n return getTransformHandlesFromCoords(\r\n getElementAbsoluteCoords(element, elementsMap, true),\r\n element.angle,\r\n zoom,\r\n pointerType,\r\n omitSides,\r\n margin,\r\n isImageElement(element) ? 0 : undefined,\r\n );\r\n};\r\n\r\nexport const hasBoundingBox = (\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n appState: InteractiveCanvasAppState,\r\n editorInterface: EditorInterface,\r\n) => {\r\n if (\r\n appState.selectedLinearElement?.isEditing ||\r\n appState.selectedLinearElement?.isDragging\r\n ) {\r\n return false;\r\n }\r\n if (elements.length > 1) {\r\n return true;\r\n }\r\n const element = elements[0];\r\n if (isElbowArrow(element)) {\r\n // Elbow arrows cannot be resized as single selected elements\r\n return false;\r\n }\r\n if (!isLinearElement(element)) {\r\n return true;\r\n }\r\n\r\n // on mobile/tablet we currently don't show bbox because of resize issues\r\n // (also prob best for simplicity's sake)\r\n return element.points.length > 2 && !editorInterface.userAgent.isMobileDevice;\r\n};\r\n", "import type { UIAppState } from \"@excalidraw-modify/excalidraw/types\";\r\n\r\nimport { getSelectedElements } from \"./selection\";\r\n\r\nimport type { NonDeletedExcalidrawElement } from \"./types\";\r\n\r\nexport const showSelectedShapeActions = (\r\n appState: UIAppState,\r\n elements: readonly NonDeletedExcalidrawElement[],\r\n) =>\r\n Boolean(\r\n !appState.viewModeEnabled &&\r\n appState.openDialog?.name !== \"elementLinkSelector\" &&\r\n ((appState.activeTool.type !== \"custom\" &&\r\n (appState.editingTextElement ||\r\n (appState.activeTool.type !== \"selection\" &&\r\n appState.activeTool.type !== \"lasso\" &&\r\n appState.activeTool.type !== \"eraser\" &&\r\n appState.activeTool.type !== \"hand\" &&\r\n appState.activeTool.type !== \"laser\"))) ||\r\n getSelectedElements(elements, appState).length),\r\n );\r\n", "import { pointFrom, type LocalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport {\r\n DEFAULT_FONT_FAMILY,\r\n DEFAULT_FONT_SIZE,\r\n TEXT_ALIGN,\r\n VERTICAL_ALIGN,\r\n getSizeFromPoints,\r\n randomId,\r\n arrayToMap,\r\n assertNever,\r\n cloneJSON,\r\n getFontString,\r\n isDevEnv,\r\n toBrandedType,\r\n getLineHeight,\r\n} from \"@excalidraw-modify/common\";\r\n\r\nimport type { MarkOptional } from \"@excalidraw-modify/common/utility-types\";\r\n\r\nimport { bindBindingElement } from \"./binding\";\r\nimport {\r\n newArrowElement,\r\n newElement,\r\n newFrameElement,\r\n newImageElement,\r\n newLinearElement,\r\n newMagicFrameElement,\r\n newTextElement,\r\n type ElementConstructorOpts,\r\n} from \"./newElement\";\r\nimport { measureText, normalizeText } from \"./textMeasurements\";\r\nimport { isArrowElement } from \"./typeChecks\";\r\n\r\nimport { syncInvalidIndices } from \"./fractionalIndex\";\r\n\r\nimport { redrawTextBoundingBox } from \"./textElement\";\r\n\r\nimport { LinearElementEditor } from \"./linearElementEditor\";\r\n\r\nimport { getCommonBounds } from \"./bounds\";\r\n\r\nimport { Scene } from \"./Scene\";\r\n\r\nimport type {\r\n ExcalidrawArrowElement,\r\n ExcalidrawBindableElement,\r\n ExcalidrawElement,\r\n ExcalidrawFrameElement,\r\n ExcalidrawFreeDrawElement,\r\n ExcalidrawGenericElement,\r\n ExcalidrawIframeLikeElement,\r\n ExcalidrawImageElement,\r\n ExcalidrawLinearElement,\r\n ExcalidrawMagicFrameElement,\r\n ExcalidrawSelectionElement,\r\n ExcalidrawTextElement,\r\n FileId,\r\n FontFamilyValues,\r\n NonDeletedSceneElementsMap,\r\n TextAlign,\r\n VerticalAlign,\r\n} from \"./types\";\r\n\r\nexport type ValidLinearElement = {\r\n type: \"arrow\" | \"line\";\r\n x: number;\r\n y: number;\r\n label?: {\r\n text: string;\r\n fontSize?: number;\r\n fontFamily?: FontFamilyValues;\r\n textAlign?: TextAlign;\r\n verticalAlign?: VerticalAlign;\r\n } & MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\r\n end?:\r\n | (\r\n | (\r\n | {\r\n type: Exclude<\r\n ExcalidrawBindableElement[\"type\"],\r\n | \"image\"\r\n | \"text\"\r\n | \"frame\"\r\n | \"magicframe\"\r\n | \"embeddable\"\r\n | \"iframe\"\r\n >;\r\n id?: ExcalidrawGenericElement[\"id\"];\r\n }\r\n | {\r\n id: ExcalidrawGenericElement[\"id\"];\r\n type?: Exclude<\r\n ExcalidrawBindableElement[\"type\"],\r\n | \"image\"\r\n | \"text\"\r\n | \"frame\"\r\n | \"magicframe\"\r\n | \"embeddable\"\r\n | \"iframe\"\r\n >;\r\n }\r\n )\r\n | ((\r\n | {\r\n type: \"text\";\r\n text: string;\r\n }\r\n | {\r\n type?: \"text\";\r\n id: ExcalidrawTextElement[\"id\"];\r\n text: string;\r\n }\r\n ) &\r\n Partial<ExcalidrawTextElement>)\r\n ) &\r\n MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\r\n start?:\r\n | (\r\n | (\r\n | {\r\n type: Exclude<\r\n ExcalidrawBindableElement[\"type\"],\r\n | \"image\"\r\n | \"text\"\r\n | \"frame\"\r\n | \"magicframe\"\r\n | \"embeddable\"\r\n | \"iframe\"\r\n >;\r\n id?: ExcalidrawGenericElement[\"id\"];\r\n }\r\n | {\r\n id: ExcalidrawGenericElement[\"id\"];\r\n type?: Exclude<\r\n ExcalidrawBindableElement[\"type\"],\r\n | \"image\"\r\n | \"text\"\r\n | \"frame\"\r\n | \"magicframe\"\r\n | \"embeddable\"\r\n | \"iframe\"\r\n >;\r\n }\r\n )\r\n | ((\r\n | {\r\n type: \"text\";\r\n text: string;\r\n }\r\n | {\r\n type?: \"text\";\r\n id: ExcalidrawTextElement[\"id\"];\r\n text: string;\r\n }\r\n ) &\r\n Partial<ExcalidrawTextElement>)\r\n ) &\r\n MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\r\n} & Partial<ExcalidrawLinearElement>;\r\n\r\nexport type ValidContainer =\r\n | {\r\n type: Exclude<ExcalidrawGenericElement[\"type\"], \"selection\">;\r\n id?: ExcalidrawGenericElement[\"id\"];\r\n label?: {\r\n text: string;\r\n fontSize?: number;\r\n fontFamily?: FontFamilyValues;\r\n textAlign?: TextAlign;\r\n verticalAlign?: VerticalAlign;\r\n } & MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\r\n } & ElementConstructorOpts;\r\n\r\nexport type ExcalidrawElementSkeleton =\r\n | Extract<\r\n Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,\r\n ExcalidrawIframeLikeElement | ExcalidrawFreeDrawElement\r\n >\r\n | ({\r\n type: Extract<ExcalidrawLinearElement[\"type\"], \"line\">;\r\n x: number;\r\n y: number;\r\n } & Partial<ExcalidrawLinearElement>)\r\n | ValidContainer\r\n | ValidLinearElement\r\n | ({\r\n type: \"text\";\r\n text: string;\r\n x: number;\r\n y: number;\r\n id?: ExcalidrawTextElement[\"id\"];\r\n } & Partial<ExcalidrawTextElement>)\r\n | ({\r\n type: Extract<ExcalidrawImageElement[\"type\"], \"image\">;\r\n x: number;\r\n y: number;\r\n fileId: FileId;\r\n } & Partial<ExcalidrawImageElement>)\r\n | ({\r\n type: \"frame\";\r\n children: readonly ExcalidrawElement[\"id\"][];\r\n name?: string;\r\n } & Partial<ExcalidrawFrameElement>)\r\n | ({\r\n type: \"magicframe\";\r\n children: readonly ExcalidrawElement[\"id\"][];\r\n name?: string;\r\n } & Partial<ExcalidrawMagicFrameElement>);\r\n\r\nconst DEFAULT_LINEAR_ELEMENT_PROPS = {\r\n width: 100,\r\n height: 0,\r\n};\r\n\r\nconst DEFAULT_DIMENSION = 100;\r\n\r\nconst bindTextToContainer = (\r\n container: ExcalidrawElement,\r\n textProps: { text: string } & MarkOptional<ElementConstructorOpts, \"x\" | \"y\">,\r\n scene: Scene,\r\n) => {\r\n const textElement: ExcalidrawTextElement = newTextElement({\r\n x: 0,\r\n y: 0,\r\n textAlign: TEXT_ALIGN.CENTER,\r\n verticalAlign: VERTICAL_ALIGN.MIDDLE,\r\n ...textProps,\r\n containerId: container.id,\r\n strokeColor: textProps.strokeColor || container.strokeColor,\r\n });\r\n\r\n Object.assign(container, {\r\n boundElements: (container.boundElements || []).concat({\r\n type: \"text\",\r\n id: textElement.id,\r\n }),\r\n });\r\n\r\n redrawTextBoundingBox(textElement, container, scene);\r\n\r\n return [container, textElement] as const;\r\n};\r\n\r\nconst bindLinearElementToElement = (\r\n linearElement: ExcalidrawArrowElement,\r\n start: ValidLinearElement[\"start\"],\r\n end: ValidLinearElement[\"end\"],\r\n elementStore: ElementStore,\r\n scene: Scene,\r\n): {\r\n linearElement: ExcalidrawLinearElement;\r\n startBoundElement?: ExcalidrawElement;\r\n endBoundElement?: ExcalidrawElement;\r\n} => {\r\n let startBoundElement;\r\n let endBoundElement;\r\n\r\n Object.assign(linearElement, {\r\n startBinding: linearElement?.startBinding || null,\r\n endBinding: linearElement.endBinding || null,\r\n });\r\n\r\n if (start) {\r\n const width = start?.width ?? DEFAULT_DIMENSION;\r\n const height = start?.height ?? DEFAULT_DIMENSION;\r\n\r\n let existingElement;\r\n if (start.id) {\r\n existingElement = elementStore.getElement(start.id);\r\n if (!existingElement) {\r\n console.error(`No element for start binding with id ${start.id} found`);\r\n }\r\n }\r\n\r\n const startX = start.x || linearElement.x - width;\r\n const startY = start.y || linearElement.y - height / 2;\r\n const startType = existingElement ? existingElement.type : start.type;\r\n\r\n if (startType) {\r\n if (startType === \"text\") {\r\n let text = \"\";\r\n if (existingElement && existingElement.type === \"text\") {\r\n text = existingElement.text;\r\n } else if (start.type === \"text\") {\r\n text = start.text;\r\n }\r\n if (!text) {\r\n console.error(\r\n `No text found for start binding text element for ${linearElement.id}`,\r\n );\r\n }\r\n startBoundElement = newTextElement({\r\n x: startX,\r\n y: startY,\r\n type: \"text\",\r\n ...existingElement,\r\n ...start,\r\n text,\r\n });\r\n // to position the text correctly when coordinates not provided\r\n Object.assign(startBoundElement, {\r\n x: start.x || linearElement.x - startBoundElement.width,\r\n y: start.y || linearElement.y - startBoundElement.height / 2,\r\n });\r\n } else {\r\n switch (startType) {\r\n case \"rectangle\":\r\n case \"ellipse\":\r\n case \"diamond\": {\r\n startBoundElement = newElement({\r\n x: startX,\r\n y: startY,\r\n width,\r\n height,\r\n ...existingElement,\r\n ...start,\r\n type: startType,\r\n });\r\n break;\r\n }\r\n default: {\r\n assertNever(\r\n linearElement as never,\r\n `Unhandled element start type \"${start.type}\"`,\r\n true,\r\n );\r\n }\r\n }\r\n }\r\n\r\n bindBindingElement(\r\n linearElement,\r\n startBoundElement as ExcalidrawBindableElement,\r\n \"orbit\",\r\n \"start\",\r\n scene,\r\n );\r\n }\r\n }\r\n if (end) {\r\n const height = end?.height ?? DEFAULT_DIMENSION;\r\n const width = end?.width ?? DEFAULT_DIMENSION;\r\n\r\n let existingElement;\r\n if (end.id) {\r\n existingElement = elementStore.getElement(end.id);\r\n if (!existingElement) {\r\n console.error(`No element for end binding with id ${end.id} found`);\r\n }\r\n }\r\n const endX = end.x || linearElement.x + linearElement.width;\r\n const endY = end.y || linearElement.y - height / 2;\r\n const endType = existingElement ? existingElement.type : end.type;\r\n\r\n if (endType) {\r\n if (endType === \"text\") {\r\n let text = \"\";\r\n if (existingElement && existingElement.type === \"text\") {\r\n text = existingElement.text;\r\n } else if (end.type === \"text\") {\r\n text = end.text;\r\n }\r\n\r\n if (!text) {\r\n console.error(\r\n `No text found for end binding text element for ${linearElement.id}`,\r\n );\r\n }\r\n endBoundElement = newTextElement({\r\n x: endX,\r\n y: endY,\r\n type: \"text\",\r\n ...existingElement,\r\n ...end,\r\n text,\r\n });\r\n // to position the text correctly when coordinates not provided\r\n Object.assign(endBoundElement, {\r\n y: end.y || linearElement.y - endBoundElement.height / 2,\r\n });\r\n } else {\r\n switch (endType) {\r\n case \"rectangle\":\r\n case \"ellipse\":\r\n case \"diamond\": {\r\n endBoundElement = newElement({\r\n x: endX,\r\n y: endY,\r\n width,\r\n height,\r\n ...existingElement,\r\n ...end,\r\n type: endType,\r\n });\r\n break;\r\n }\r\n default: {\r\n assertNever(\r\n linearElement as never,\r\n `Unhandled element end type \"${endType}\"`,\r\n true,\r\n );\r\n }\r\n }\r\n }\r\n\r\n bindBindingElement(\r\n linearElement,\r\n endBoundElement as ExcalidrawBindableElement,\r\n \"orbit\",\r\n \"end\",\r\n scene,\r\n );\r\n }\r\n }\r\n\r\n // Safe check to early return for single point\r\n if (linearElement.points.length < 2) {\r\n return {\r\n linearElement,\r\n startBoundElement,\r\n endBoundElement,\r\n };\r\n }\r\n\r\n // Update start/end points by 0.5 so bindings don't overlap with start/end bound element coordinates.\r\n const endPointIndex = linearElement.points.length - 1;\r\n const delta = 0.5;\r\n\r\n const newPoints = cloneJSON<readonly LocalPoint[]>(linearElement.points);\r\n\r\n // left to right so shift the arrow towards right\r\n if (\r\n linearElement.points[endPointIndex][0] >\r\n linearElement.points[endPointIndex - 1][0]\r\n ) {\r\n newPoints[0][0] = delta;\r\n newPoints[endPointIndex][0] -= delta;\r\n }\r\n\r\n // right to left so shift the arrow towards left\r\n if (\r\n linearElement.points[endPointIndex][0] <\r\n linearElement.points[endPointIndex - 1][0]\r\n ) {\r\n newPoints[0][0] = -delta;\r\n newPoints[endPointIndex][0] += delta;\r\n }\r\n // top to bottom so shift the arrow towards top\r\n if (\r\n linearElement.points[endPointIndex][1] >\r\n linearElement.points[endPointIndex - 1][1]\r\n ) {\r\n newPoints[0][1] = delta;\r\n newPoints[endPointIndex][1] -= delta;\r\n }\r\n\r\n // bottom to top so shift the arrow towards bottom\r\n if (\r\n linearElement.points[endPointIndex][1] <\r\n linearElement.points[endPointIndex - 1][1]\r\n ) {\r\n newPoints[0][1] = -delta;\r\n newPoints[endPointIndex][1] += delta;\r\n }\r\n\r\n Object.assign(\r\n linearElement,\r\n LinearElementEditor.getNormalizeElementPointsAndCoords({\r\n ...linearElement,\r\n points: newPoints,\r\n }),\r\n );\r\n\r\n return {\r\n linearElement,\r\n startBoundElement,\r\n endBoundElement,\r\n };\r\n};\r\n\r\nclass ElementStore {\r\n excalidrawElements = new Map<string, ExcalidrawElement>();\r\n\r\n add = (ele?: ExcalidrawElement) => {\r\n if (!ele) {\r\n return;\r\n }\r\n\r\n this.excalidrawElements.set(ele.id, ele);\r\n };\r\n\r\n getElements = () => {\r\n return syncInvalidIndices(Array.from(this.excalidrawElements.values()));\r\n };\r\n\r\n getElementsMap = () => {\r\n return toBrandedType<NonDeletedSceneElementsMap>(\r\n arrayToMap(this.getElements()),\r\n );\r\n };\r\n\r\n getElement = (id: string) => {\r\n return this.excalidrawElements.get(id);\r\n };\r\n}\r\n\r\nexport const convertToExcalidrawElements = (\r\n elementsSkeleton: ExcalidrawElementSkeleton[] | null,\r\n opts?: { regenerateIds: boolean },\r\n) => {\r\n if (!elementsSkeleton) {\r\n return [];\r\n }\r\n const elements = cloneJSON(elementsSkeleton);\r\n const elementStore = new ElementStore();\r\n const elementsWithIds = new Map<string, ExcalidrawElementSkeleton>();\r\n const oldToNewElementIdMap = new Map<string, string>();\r\n\r\n // Create individual elements\r\n for (const element of elements) {\r\n let excalidrawElement: ExcalidrawElement;\r\n const originalId = element.id;\r\n if (opts?.regenerateIds !== false) {\r\n Object.assign(element, { id: randomId() });\r\n }\r\n\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"ellipse\":\r\n case \"diamond\": {\r\n const width =\r\n element?.label?.text && element.width === undefined\r\n ? 0\r\n : element?.width || DEFAULT_DIMENSION;\r\n const height =\r\n element?.label?.text && element.height === undefined\r\n ? 0\r\n : element?.height || DEFAULT_DIMENSION;\r\n excalidrawElement = newElement({\r\n ...element,\r\n width,\r\n height,\r\n });\r\n\r\n break;\r\n }\r\n case \"line\": {\r\n const width = element.width || DEFAULT_LINEAR_ELEMENT_PROPS.width;\r\n const height = element.height || DEFAULT_LINEAR_ELEMENT_PROPS.height;\r\n excalidrawElement = newLinearElement({\r\n width,\r\n height,\r\n points: [pointFrom(0, 0), pointFrom(width, height)],\r\n ...element,\r\n });\r\n\r\n break;\r\n }\r\n case \"arrow\": {\r\n const width = element.width || DEFAULT_LINEAR_ELEMENT_PROPS.width;\r\n const height = element.height || DEFAULT_LINEAR_ELEMENT_PROPS.height;\r\n excalidrawElement = newArrowElement({\r\n width,\r\n height,\r\n endArrowhead: \"arrow\",\r\n points: [pointFrom(0, 0), pointFrom(width, height)],\r\n ...element,\r\n type: \"arrow\",\r\n });\r\n\r\n Object.assign(\r\n excalidrawElement,\r\n getSizeFromPoints(excalidrawElement.points),\r\n );\r\n break;\r\n }\r\n case \"text\": {\r\n const fontFamily = element?.fontFamily || DEFAULT_FONT_FAMILY;\r\n const fontSize = element?.fontSize || DEFAULT_FONT_SIZE;\r\n const lineHeight = element?.lineHeight || getLineHeight(fontFamily);\r\n const text = element.text ?? \"\";\r\n const normalizedText = normalizeText(text);\r\n const metrics = measureText(\r\n normalizedText,\r\n getFontString({ fontFamily, fontSize }),\r\n lineHeight,\r\n );\r\n\r\n excalidrawElement = newTextElement({\r\n width: metrics.width,\r\n height: metrics.height,\r\n fontFamily,\r\n fontSize,\r\n ...element,\r\n });\r\n break;\r\n }\r\n case \"image\": {\r\n excalidrawElement = newImageElement({\r\n width: element?.width || DEFAULT_DIMENSION,\r\n height: element?.height || DEFAULT_DIMENSION,\r\n ...element,\r\n });\r\n\r\n break;\r\n }\r\n case \"frame\": {\r\n excalidrawElement = newFrameElement({\r\n x: 0,\r\n y: 0,\r\n ...element,\r\n });\r\n break;\r\n }\r\n case \"magicframe\": {\r\n excalidrawElement = newMagicFrameElement({\r\n x: 0,\r\n y: 0,\r\n ...element,\r\n });\r\n break;\r\n }\r\n case \"freedraw\":\r\n case \"iframe\":\r\n case \"embeddable\": {\r\n excalidrawElement = element;\r\n break;\r\n }\r\n\r\n default: {\r\n excalidrawElement = element;\r\n assertNever(\r\n element,\r\n `Unhandled element type \"${(element as any).type}\"`,\r\n true,\r\n );\r\n }\r\n }\r\n const existingElement = elementStore.getElement(excalidrawElement.id);\r\n if (existingElement) {\r\n console.error(`Duplicate id found for ${excalidrawElement.id}`);\r\n } else {\r\n elementStore.add(excalidrawElement);\r\n elementsWithIds.set(excalidrawElement.id, element);\r\n if (originalId) {\r\n oldToNewElementIdMap.set(originalId, excalidrawElement.id);\r\n }\r\n }\r\n }\r\n\r\n const elementsMap = elementStore.getElementsMap();\r\n // we don't have a real scene, so we just use a temp scene to query and mutate elements\r\n const scene = new Scene(elementsMap);\r\n\r\n // Add labels and arrow bindings\r\n for (const [id, element] of elementsWithIds) {\r\n const excalidrawElement = elementStore.getElement(id)!;\r\n\r\n switch (element.type) {\r\n case \"rectangle\":\r\n case \"ellipse\":\r\n case \"diamond\":\r\n case \"arrow\": {\r\n if (element.label?.text) {\r\n let [container, text] = bindTextToContainer(\r\n excalidrawElement,\r\n element?.label,\r\n scene,\r\n );\r\n elementStore.add(container);\r\n elementStore.add(text);\r\n\r\n if (isArrowElement(container)) {\r\n const originalStart =\r\n element.type === \"arrow\" ? element?.start : undefined;\r\n const originalEnd =\r\n element.type === \"arrow\" ? element?.end : undefined;\r\n if (originalStart && originalStart.id) {\r\n const newStartId = oldToNewElementIdMap.get(originalStart.id);\r\n if (newStartId) {\r\n Object.assign(originalStart, { id: newStartId });\r\n }\r\n }\r\n if (originalEnd && originalEnd.id) {\r\n const newEndId = oldToNewElementIdMap.get(originalEnd.id);\r\n if (newEndId) {\r\n Object.assign(originalEnd, { id: newEndId });\r\n }\r\n }\r\n const { linearElement, startBoundElement, endBoundElement } =\r\n bindLinearElementToElement(\r\n container,\r\n originalStart,\r\n originalEnd,\r\n elementStore,\r\n scene,\r\n );\r\n container = linearElement;\r\n elementStore.add(linearElement);\r\n elementStore.add(startBoundElement);\r\n elementStore.add(endBoundElement);\r\n }\r\n } else {\r\n switch (element.type) {\r\n case \"arrow\": {\r\n const { start, end } = element;\r\n if (start && start.id) {\r\n const newStartId = oldToNewElementIdMap.get(start.id);\r\n Object.assign(start, { id: newStartId });\r\n }\r\n if (end && end.id) {\r\n const newEndId = oldToNewElementIdMap.get(end.id);\r\n Object.assign(end, { id: newEndId });\r\n }\r\n const { linearElement, startBoundElement, endBoundElement } =\r\n bindLinearElementToElement(\r\n excalidrawElement as ExcalidrawArrowElement,\r\n start,\r\n end,\r\n elementStore,\r\n scene,\r\n );\r\n\r\n elementStore.add(linearElement);\r\n elementStore.add(startBoundElement);\r\n elementStore.add(endBoundElement);\r\n break;\r\n }\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // Once all the excalidraw elements are created, we can add frames since we\r\n // need to calculate coordinates and dimensions of frame which is possible after all\r\n // frame children are processed.\r\n for (const [id, element] of elementsWithIds) {\r\n if (element.type !== \"frame\" && element.type !== \"magicframe\") {\r\n continue;\r\n }\r\n const frame = elementStore.getElement(id);\r\n\r\n if (!frame) {\r\n throw new Error(`Excalidraw element with id ${id} doesn't exist`);\r\n }\r\n const childrenElements: ExcalidrawElement[] = [];\r\n\r\n element.children.forEach((id) => {\r\n const newElementId = oldToNewElementIdMap.get(id);\r\n if (!newElementId) {\r\n throw new Error(`Element with ${id} wasn't mapped correctly`);\r\n }\r\n\r\n const elementInFrame = elementStore.getElement(newElementId);\r\n if (!elementInFrame) {\r\n throw new Error(`Frame element with id ${newElementId} doesn't exist`);\r\n }\r\n Object.assign(elementInFrame, { frameId: frame.id });\r\n\r\n elementInFrame?.boundElements?.forEach((boundElement) => {\r\n const ele = elementStore.getElement(boundElement.id);\r\n if (!ele) {\r\n throw new Error(\r\n `Bound element with id ${boundElement.id} doesn't exist`,\r\n );\r\n }\r\n Object.assign(ele, { frameId: frame.id });\r\n childrenElements.push(ele);\r\n });\r\n\r\n childrenElements.push(elementInFrame);\r\n });\r\n\r\n let [minX, minY, maxX, maxY] = getCommonBounds(childrenElements);\r\n\r\n const PADDING = 10;\r\n minX = minX - PADDING;\r\n minY = minY - PADDING;\r\n maxX = maxX + PADDING;\r\n maxY = maxY + PADDING;\r\n\r\n const frameX = frame?.x || minX;\r\n const frameY = frame?.y || minY;\r\n const frameWidth = frame?.width || maxX - minX;\r\n const frameHeight = frame?.height || maxY - minY;\r\n\r\n Object.assign(frame, {\r\n x: frameX,\r\n y: frameY,\r\n width: frameWidth,\r\n height: frameHeight,\r\n });\r\n if (\r\n isDevEnv() &&\r\n element.children.length &&\r\n (frame?.x || frame?.y || frame?.width || frame?.height)\r\n ) {\r\n console.info(\r\n \"User provided frame attributes are being considered, if you find this inaccurate, please remove any of the attributes - x, y, width and height so frame coordinates and dimensions are calculated automatically\",\r\n );\r\n }\r\n }\r\n\r\n return elementStore.getElements();\r\n};\r\n", "import { arrayToMap, findIndex, findLastIndex } from \"@excalidraw-modify/common\";\r\n\r\nimport type { AppState } from \"@excalidraw-modify/excalidraw/types\";\r\nimport type { GlobalPoint } from \"@excalidraw-modify/math\";\r\n\r\nimport { isFrameLikeElement, isTextElement } from \"./typeChecks\";\r\nimport { getElementsInGroup } from \"./groups\";\r\nimport { syncMovedIndices } from \"./fractionalIndex\";\r\nimport { getSelectedElements } from \"./selection\";\r\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\r\nimport { getHoveredElementForBinding } from \"./collision\";\r\n\r\nimport type { Scene } from \"./Scene\";\r\nimport type {\r\n ExcalidrawArrowElement,\r\n ExcalidrawElement,\r\n ExcalidrawFrameLikeElement,\r\n NonDeletedExcalidrawElement,\r\n NonDeletedSceneElementsMap,\r\n Ordered,\r\n OrderedExcalidrawElement,\r\n} from \"./types\";\r\n\r\nconst isOfTargetFrame = (element: ExcalidrawElement, frameId: string) => {\r\n return element.frameId === frameId || element.id === frameId;\r\n};\r\n\r\n/**\r\n * Returns indices of elements to move based on selected elements.\r\n * Includes contiguous deleted elements that are between two selected elements,\r\n * e.g.: [0 (selected), 1 (deleted), 2 (deleted), 3 (selected)]\r\n *\r\n * Specified elements (elementsToBeMoved) take precedence over\r\n * appState.selectedElementsIds\r\n */\r\nconst getIndicesToMove = (\r\n elements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n elementsToBeMoved?: readonly ExcalidrawElement[],\r\n) => {\r\n let selectedIndices: number[] = [];\r\n let deletedIndices: number[] = [];\r\n let includeDeletedIndex = null;\r\n let index = -1;\r\n const selectedElementIds = arrayToMap(\r\n elementsToBeMoved\r\n ? elementsToBeMoved\r\n : getSelectedElements(elements, appState, {\r\n includeBoundTextElement: true,\r\n includeElementsInFrames: true,\r\n }),\r\n );\r\n while (++index < elements.length) {\r\n const element = elements[index];\r\n if (selectedElementIds.get(element.id)) {\r\n if (deletedIndices.length) {\r\n selectedIndices = selectedIndices.concat(deletedIndices);\r\n deletedIndices = [];\r\n }\r\n selectedIndices.push(index);\r\n includeDeletedIndex = index + 1;\r\n } else if (element.isDeleted && includeDeletedIndex === index) {\r\n includeDeletedIndex = index + 1;\r\n deletedIndices.push(index);\r\n } else {\r\n deletedIndices = [];\r\n }\r\n }\r\n return selectedIndices;\r\n};\r\n\r\nconst toContiguousGroups = (array: number[]) => {\r\n let cursor = 0;\r\n return array.reduce((acc, value, index) => {\r\n if (index > 0 && array[index - 1] !== value - 1) {\r\n cursor = ++cursor;\r\n }\r\n (acc[cursor] || (acc[cursor] = [])).push(value);\r\n return acc;\r\n }, [] as number[][]);\r\n};\r\n\r\n/**\r\n * @returns index of target element, consindering tightly-bound elements\r\n * (currently non-linear elements bound to a container) as a one unit.\r\n * If no binding present, returns `undefined`.\r\n */\r\nconst getTargetIndexAccountingForBinding = (\r\n nextElement: ExcalidrawElement,\r\n elements: readonly ExcalidrawElement[],\r\n direction: \"left\" | \"right\",\r\n scene: Scene,\r\n) => {\r\n if (\"containerId\" in nextElement && nextElement.containerId) {\r\n // TODO: why not to get the container from the nextElements?\r\n const containerElement = scene.getElement(nextElement.containerId);\r\n if (containerElement) {\r\n return direction === \"left\"\r\n ? Math.min(\r\n elements.indexOf(containerElement),\r\n elements.indexOf(nextElement),\r\n )\r\n : Math.max(\r\n elements.indexOf(containerElement),\r\n elements.indexOf(nextElement),\r\n );\r\n }\r\n } else {\r\n const boundElementId = nextElement.boundElements?.find(\r\n (binding) => binding.type !== \"arrow\",\r\n )?.id;\r\n if (boundElementId) {\r\n const boundTextElement = scene.getElement(boundElementId);\r\n if (boundTextElement) {\r\n return direction === \"left\"\r\n ? Math.min(\r\n elements.indexOf(boundTextElement),\r\n elements.indexOf(nextElement),\r\n )\r\n : Math.max(\r\n elements.indexOf(boundTextElement),\r\n elements.indexOf(nextElement),\r\n );\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst getContiguousFrameRangeElements = (\r\n allElements: readonly ExcalidrawElement[],\r\n frameId: ExcalidrawFrameLikeElement[\"id\"],\r\n) => {\r\n let rangeStart = -1;\r\n let rangeEnd = -1;\r\n allElements.forEach((element, index) => {\r\n if (isOfTargetFrame(element, frameId)) {\r\n if (rangeStart === -1) {\r\n rangeStart = index;\r\n }\r\n rangeEnd = index;\r\n }\r\n });\r\n if (rangeStart === -1) {\r\n return [];\r\n }\r\n return allElements.slice(rangeStart, rangeEnd + 1);\r\n};\r\n\r\n/**\r\n * Moves the arrow element above any bindable elements it intersects with or\r\n * hovers over.\r\n */\r\nexport const moveArrowAboveBindable = (\r\n point: GlobalPoint,\r\n arrow: ExcalidrawArrowElement,\r\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\r\n elementsMap: NonDeletedSceneElementsMap,\r\n scene: Scene,\r\n): readonly OrderedExcalidrawElement[] => {\r\n const hoveredElement = getHoveredElementForBinding(\r\n point,\r\n elements,\r\n elementsMap,\r\n );\r\n\r\n if (!hoveredElement) {\r\n return elements;\r\n }\r\n\r\n const boundTextElement = getBoundTextElement(hoveredElement, elementsMap);\r\n const containerElement = isTextElement(hoveredElement)\r\n ? getContainerElement(hoveredElement, elementsMap)\r\n : null;\r\n\r\n const bindableIds = [\r\n hoveredElement.id,\r\n boundTextElement?.id,\r\n containerElement?.id,\r\n ].filter((id): id is NonDeletedExcalidrawElement[\"id\"] => !!id);\r\n const bindableIdx = elements.findIndex((el) => bindableIds.includes(el.id));\r\n const arrowIdx = elements.findIndex((el) => el.id === arrow.id);\r\n\r\n if (arrowIdx !== -1 && bindableIdx !== -1 && arrowIdx < bindableIdx) {\r\n const updatedElements = Array.from(elements);\r\n const arrow = updatedElements.splice(arrowIdx, 1)[0];\r\n updatedElements.splice(bindableIdx, 0, arrow);\r\n\r\n scene.replaceAllElements(updatedElements);\r\n }\r\n\r\n return elements;\r\n};\r\n\r\n/**\r\n * Returns next candidate index that's available to be moved to. Currently that\r\n * is a non-deleted element, and not inside a group (unless we're editing it).\r\n */\r\nconst getTargetIndex = (\r\n appState: AppState,\r\n elements: readonly ExcalidrawElement[],\r\n boundaryIndex: number,\r\n direction: \"left\" | \"right\",\r\n /**\r\n * Frame id if moving frame children.\r\n * If whole frame (including all children) is being moved, supply `null`.\r\n */\r\n containingFrame: ExcalidrawFrameLikeElement[\"id\"] | null,\r\n scene: Scene,\r\n) => {\r\n const sourceElement = elements[boundaryIndex];\r\n\r\n const indexFilter = (element: ExcalidrawElement) => {\r\n if (element.isDeleted) {\r\n return false;\r\n }\r\n if (containingFrame) {\r\n return element.frameId === containingFrame;\r\n }\r\n // if we're editing group, find closest sibling irrespective of whether\r\n // there's a different-group element between them (for legacy reasons)\r\n if (appState.editingGroupId) {\r\n return element.groupIds.includes(appState.editingGroupId);\r\n }\r\n return true;\r\n };\r\n\r\n const candidateIndex =\r\n direction === \"left\"\r\n ? findLastIndex(\r\n elements,\r\n (el) => indexFilter(el),\r\n Math.max(0, boundaryIndex - 1),\r\n )\r\n : findIndex(elements, (el) => indexFilter(el), boundaryIndex + 1);\r\n\r\n const nextElement = elements[candidateIndex];\r\n\r\n if (!nextElement) {\r\n return -1;\r\n }\r\n\r\n if (appState.editingGroupId) {\r\n if (\r\n // candidate element is a sibling in current editing group \u2192 return\r\n sourceElement?.groupIds.join(\"\") === nextElement?.groupIds.join(\"\")\r\n ) {\r\n return (\r\n getTargetIndexAccountingForBinding(\r\n nextElement,\r\n elements,\r\n direction,\r\n scene,\r\n ) ?? candidateIndex\r\n );\r\n } else if (!nextElement?.groupIds.includes(appState.editingGroupId)) {\r\n // candidate element is outside current editing group \u2192 prevent\r\n return -1;\r\n }\r\n }\r\n\r\n if (\r\n !containingFrame &&\r\n (nextElement.frameId || isFrameLikeElement(nextElement))\r\n ) {\r\n const frameElements = getContiguousFrameRangeElements(\r\n elements,\r\n nextElement.frameId || nextElement.id,\r\n );\r\n return direction === \"left\"\r\n ? elements.indexOf(frameElements[0])\r\n : elements.indexOf(frameElements[frameElements.length - 1]);\r\n }\r\n\r\n if (!nextElement.groupIds.length) {\r\n return (\r\n getTargetIndexAccountingForBinding(\r\n nextElement,\r\n elements,\r\n direction,\r\n scene,\r\n ) ?? candidateIndex\r\n );\r\n }\r\n\r\n const siblingGroupId = appState.editingGroupId\r\n ? nextElement.groupIds[\r\n nextElement.groupIds.indexOf(appState.editingGroupId) - 1\r\n ]\r\n : nextElement.groupIds[nextElement.groupIds.length - 1];\r\n\r\n const elementsInSiblingGroup = getElementsInGroup(elements, siblingGroupId);\r\n\r\n if (elementsInSiblingGroup.length) {\r\n // assumes getElementsInGroup() returned elements are sorted\r\n // by zIndex (ascending)\r\n return direction === \"left\"\r\n ? elements.indexOf(elementsInSiblingGroup[0])\r\n : elements.indexOf(\r\n elementsInSiblingGroup[elementsInSiblingGroup.length - 1],\r\n );\r\n }\r\n\r\n return candidateIndex;\r\n};\r\n\r\nconst getTargetElementsMap = <T extends ExcalidrawElement>(\r\n elements: readonly T[],\r\n indices: number[],\r\n) => {\r\n return indices.reduce((acc, index) => {\r\n const element = elements[index];\r\n acc.set(element.id, element);\r\n return acc;\r\n }, new Map<string, ExcalidrawElement>());\r\n};\r\n\r\nconst shiftElementsByOne = (\r\n elements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n direction: \"left\" | \"right\",\r\n scene: Scene,\r\n) => {\r\n const indicesToMove = getIndicesToMove(elements, appState);\r\n const targetElementsMap = getTargetElementsMap(elements, indicesToMove);\r\n\r\n let groupedIndices = toContiguousGroups(indicesToMove);\r\n\r\n if (direction === \"right\") {\r\n groupedIndices = groupedIndices.reverse();\r\n }\r\n\r\n const selectedFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>(\r\n indicesToMove\r\n .filter((idx) => isFrameLikeElement(elements[idx]))\r\n .map((idx) => elements[idx].id),\r\n );\r\n\r\n groupedIndices.forEach((indices, i) => {\r\n const leadingIndex = indices[0];\r\n const trailingIndex = indices[indices.length - 1];\r\n const boundaryIndex = direction === \"left\" ? leadingIndex : trailingIndex;\r\n\r\n const containingFrame = indices.some((idx) => {\r\n const el = elements[idx];\r\n return el.frameId && selectedFrames.has(el.frameId);\r\n })\r\n ? null\r\n : elements[boundaryIndex]?.frameId;\r\n\r\n const targetIndex = getTargetIndex(\r\n appState,\r\n elements,\r\n boundaryIndex,\r\n direction,\r\n containingFrame,\r\n scene,\r\n );\r\n\r\n if (targetIndex === -1 || boundaryIndex === targetIndex) {\r\n return;\r\n }\r\n\r\n const leadingElements =\r\n direction === \"left\"\r\n ? elements.slice(0, targetIndex)\r\n : elements.slice(0, leadingIndex);\r\n const targetElements = elements.slice(leadingIndex, trailingIndex + 1);\r\n const displacedElements =\r\n direction === \"left\"\r\n ? elements.slice(targetIndex, leadingIndex)\r\n : elements.slice(trailingIndex + 1, targetIndex + 1);\r\n const trailingElements =\r\n direction === \"left\"\r\n ? elements.slice(trailingIndex + 1)\r\n : elements.slice(targetIndex + 1);\r\n\r\n elements =\r\n direction === \"left\"\r\n ? [\r\n ...leadingElements,\r\n ...targetElements,\r\n ...displacedElements,\r\n ...trailingElements,\r\n ]\r\n : [\r\n ...leadingElements,\r\n ...displacedElements,\r\n ...targetElements,\r\n ...trailingElements,\r\n ];\r\n });\r\n\r\n syncMovedIndices(elements, targetElementsMap);\r\n\r\n return elements;\r\n};\r\n\r\nconst shiftElementsToEnd = (\r\n elements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n direction: \"left\" | \"right\",\r\n containingFrame: ExcalidrawFrameLikeElement[\"id\"] | null,\r\n elementsToBeMoved?: readonly ExcalidrawElement[],\r\n) => {\r\n const indicesToMove = getIndicesToMove(elements, appState, elementsToBeMoved);\r\n const targetElementsMap = getTargetElementsMap(elements, indicesToMove);\r\n const displacedElements: ExcalidrawElement[] = [];\r\n\r\n let leadingIndex: number;\r\n let trailingIndex: number;\r\n if (direction === \"left\") {\r\n if (containingFrame) {\r\n leadingIndex = findIndex(elements, (el) =>\r\n isOfTargetFrame(el, containingFrame),\r\n );\r\n } else if (appState.editingGroupId) {\r\n const groupElements = getElementsInGroup(\r\n elements,\r\n appState.editingGroupId,\r\n );\r\n if (!groupElements.length) {\r\n return elements;\r\n }\r\n leadingIndex = elements.indexOf(groupElements[0]);\r\n } else {\r\n leadingIndex = 0;\r\n }\r\n\r\n trailingIndex = indicesToMove[indicesToMove.length - 1];\r\n } else {\r\n if (containingFrame) {\r\n trailingIndex = findLastIndex(elements, (el) =>\r\n isOfTargetFrame(el, containingFrame),\r\n );\r\n } else if (appState.editingGroupId) {\r\n const groupElements = getElementsInGroup(\r\n elements,\r\n appState.editingGroupId,\r\n );\r\n if (!groupElements.length) {\r\n return elements;\r\n }\r\n trailingIndex = elements.indexOf(groupElements[groupElements.length - 1]);\r\n } else {\r\n trailingIndex = elements.length - 1;\r\n }\r\n\r\n leadingIndex = indicesToMove[0];\r\n }\r\n\r\n if (leadingIndex === -1) {\r\n leadingIndex = 0;\r\n }\r\n\r\n for (let index = leadingIndex; index < trailingIndex + 1; index++) {\r\n if (!indicesToMove.includes(index)) {\r\n displacedElements.push(elements[index]);\r\n }\r\n }\r\n\r\n const targetElements = Array.from(targetElementsMap.values());\r\n const leadingElements = elements.slice(0, leadingIndex);\r\n const trailingElements = elements.slice(trailingIndex + 1);\r\n const nextElements =\r\n direction === \"left\"\r\n ? [\r\n ...leadingElements,\r\n ...targetElements,\r\n ...displacedElements,\r\n ...trailingElements,\r\n ]\r\n : [\r\n ...leadingElements,\r\n ...displacedElements,\r\n ...targetElements,\r\n ...trailingElements,\r\n ];\r\n\r\n syncMovedIndices(nextElements, targetElementsMap);\r\n\r\n return nextElements;\r\n};\r\n\r\nfunction shiftElementsAccountingForFrames(\r\n allElements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n direction: \"left\" | \"right\",\r\n shiftFunction: (\r\n elements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n direction: \"left\" | \"right\",\r\n containingFrame: ExcalidrawFrameLikeElement[\"id\"] | null,\r\n elementsToBeMoved?: readonly ExcalidrawElement[],\r\n ) => ExcalidrawElement[] | readonly ExcalidrawElement[],\r\n) {\r\n const elementsToMove = arrayToMap(\r\n getSelectedElements(allElements, appState, {\r\n includeBoundTextElement: true,\r\n includeElementsInFrames: true,\r\n }),\r\n );\r\n\r\n const frameAwareContiguousElementsToMove: {\r\n regularElements: ExcalidrawElement[];\r\n frameChildren: Map<ExcalidrawFrameLikeElement[\"id\"], ExcalidrawElement[]>;\r\n } = { regularElements: [], frameChildren: new Map() };\r\n\r\n const fullySelectedFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>();\r\n\r\n for (const element of allElements) {\r\n if (elementsToMove.has(element.id) && isFrameLikeElement(element)) {\r\n fullySelectedFrames.add(element.id);\r\n }\r\n }\r\n\r\n for (const element of allElements) {\r\n if (elementsToMove.has(element.id)) {\r\n if (\r\n isFrameLikeElement(element) ||\r\n (element.frameId && fullySelectedFrames.has(element.frameId))\r\n ) {\r\n frameAwareContiguousElementsToMove.regularElements.push(element);\r\n } else if (!element.frameId) {\r\n frameAwareContiguousElementsToMove.regularElements.push(element);\r\n } else {\r\n const frameChildren =\r\n frameAwareContiguousElementsToMove.frameChildren.get(\r\n element.frameId,\r\n ) || [];\r\n frameChildren.push(element);\r\n frameAwareContiguousElementsToMove.frameChildren.set(\r\n element.frameId,\r\n frameChildren,\r\n );\r\n }\r\n }\r\n }\r\n\r\n let nextElements = allElements;\r\n\r\n const frameChildrenSets = Array.from(\r\n frameAwareContiguousElementsToMove.frameChildren.entries(),\r\n );\r\n\r\n for (const [frameId, children] of frameChildrenSets) {\r\n nextElements = shiftFunction(\r\n allElements,\r\n appState,\r\n direction,\r\n frameId,\r\n children,\r\n );\r\n }\r\n\r\n return shiftFunction(\r\n nextElements,\r\n appState,\r\n direction,\r\n null,\r\n frameAwareContiguousElementsToMove.regularElements,\r\n );\r\n}\r\n\r\n// public API\r\n// -----------------------------------------------------------------------------\r\n\r\nexport const moveOneLeft = (\r\n allElements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n scene: Scene,\r\n) => {\r\n return shiftElementsByOne(allElements, appState, \"left\", scene);\r\n};\r\n\r\nexport const moveOneRight = (\r\n allElements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n scene: Scene,\r\n) => {\r\n return shiftElementsByOne(allElements, appState, \"right\", scene);\r\n};\r\n\r\nexport const moveAllLeft = (\r\n allElements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n) => {\r\n return shiftElementsAccountingForFrames(\r\n allElements,\r\n appState,\r\n \"left\",\r\n shiftElementsToEnd,\r\n );\r\n};\r\n\r\nexport const moveAllRight = (\r\n allElements: readonly ExcalidrawElement[],\r\n appState: AppState,\r\n) => {\r\n return shiftElementsAccountingForFrames(\r\n allElements,\r\n appState,\r\n \"right\",\r\n shiftElementsToEnd,\r\n );\r\n};\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["result", "throttle", "toIterable", "pointsEqual", "line", "polygon", "ae", "ce", "helper", "line", "line", "helper", "line", "helper", "line", "helper", "line", "helper", "curve", "r1", "r2", "b", "b", "a", "b", "distance", "distance", "distance", "arrayToMap", "invariant", "lineSegment", "pointDistance", "pointFrom", "pointFromArray", "pointRotateRads", "curve", "polygon", "curve", "pointFrom", "pointDistance", "pointRotateRads", "isTransparent", "assertNever", "lineSegment", "pointFrom", "pointRotateRads", "BOUND_TEXT_PADDING", "distance", "getFontString", "invariant", "pointFrom", "pointRotateRads", "vectorFromPoint", "vectorAdd", "vectorScale", "pointFromVector", "pointRotateRads", "pointFrom", "crop", "getElementAbsoluteCoords", "vectorFromPoint", "vectorAdd", "vectorScale", "pointFromVector", "pointCenter", "pointFrom", "pointRotateRads", "pointsEqual", "pointDistance", "vectorFromPoint", "lineSegment", "KEYS", "invariant", "getFeatureFlag", "deconstructLinearOrFreeDrawElement", "isPathALoop", "projectFixedPointOntoDiagonal", "arrayToMap", "invariant", "isTransparent", "PRECISION", "clamp", "lineSegment", "pointDistance", "pointFrom", "pointFromVector", "pointRotateRads", "vectorFromPoint", "vectorNormalize", "vectorScale", "invariant", "lineSegment", "lineSegmentIntersectionPoints", "pointFrom", "pointFromVector", "pointRotateRads", "pointsEqual", "vectorFromPoint", "vectorNormalize", "vectorScale", "ellipse", "invariant", "ROUNDNESS", "curve", "lineSegment", "pointDistance", "pointFrom", "pointFromArray", "pointFromVector", "pointRotateRads", "rectangle", "vectorFromPoint", "vectorNormalize", "vectorScale", "pointFromArray", "lineSegment", "pointFrom", "curve", "rectangle", "distance", "pointDistance", "ROUNDNESS", "vectorNormalize", "vectorFromPoint", "vectorScale", "pointRotateRads", "invariant", "a", "b", "pointFromVector", "BOUND_TEXT_PADDING", "DEFAULT_FONT_SIZE", "getFontString", "invariant", "pointFrom", "pointRotateRads", "line", "isTestEnv", "line", "isTestEnv", "invariant", "getFontString", "pointFrom", "pointRotateRads", "index", "BOUND_TEXT_PADDING", "DEFAULT_FONT_SIZE", "pointRotateRads", "ellipse", "pointRotateRads", "a", "ellipse", "pointFrom", "pointRotateRads", "shouldTestInside", "lineSegment", "distance", "invariant", "a", "b", "line", "l", "lineSegmentIntersectionPoints", "ellipse", "pointFromVector", "vectorScale", "vectorNormalize", "vectorFromPoint", "pointsEqual", "offset", "corners", "invariant", "isDevEnv", "isTestEnv", "pointFrom", "pointFromVector", "pointRotateRads", "pointsEqual", "vectorFromPoint", "vectorScale", "vectorFromPoint", "a", "b", "isDevEnv", "isTestEnv", "invariant", "pointsEqual", "pointFromVector", "vectorScale", "pointRotateRads", "pointFrom", "p", "getSizeFromPoints", "clamp", "pointDistance", "pointFrom", "pointScaleFromOrigin", "pointsEqual", "pointTranslate", "vector", "vectorCross", "vectorFromPoint", "vectorScale", "invariant", "isDevEnv", "pointFrom", "pointDistance", "isDevEnv", "invariant", "pointsEqual", "vectorFromPoint", "pointTranslate", "vector", "pointScaleFromOrigin", "a", "b", "vectorCross", "global", "vectorScale", "clamp", "getSizeFromPoints", "clamp", "invariant", "pointFrom", "isTransparent", "start", "end", "arrayToMap", "vectorFromPoint", "distance", "lineSegment", "pointFromVector", "vectorScale", "vectorNormalize", "pointDistance", "PRECISION", "pointRotateRads", "a", "b", "global", "duplicateElement", "element", "pointFrom", "pointsEqual", "getElementAbsoluteCoords", "invariant", "KEYS", "projectFixedPointOntoDiagonal", "isPathALoop", "distance", "pointDistance", "deconstructLinearOrFreeDrawElement", "pointCenter", "pointRotateRads", "midpoint", "vectorFromPoint", "a", "b", "getFeatureFlag", "lineSegment", "arrayToMap", "isPointWithinBounds", "pointFrom", "vectorCross", "vectorFromPoint", "line", "a", "b", "l", "arrayToMap", "getElementBounds", "isArrowElement", "isExcalidrawElement", "isFreeDrawElement", "isLinearElement", "isTextElement", "pointFrom", "pointRotateRads", "arrayToMap", "isShallowEqual", "selectGroupsForSelectedElements", "getElementAbsoluteCoords", "isShallowEqual", "arrayToMap", "arrayToMap", "getElementAbsoluteCoords", "isPointWithinBounds", "pointFrom", "element", "getElementAbsoluteCoords", "distance", "BOUND_TEXT_PADDING", "getFontString", "pointFrom", "invariant", "lineSegment", "pointRotateRads", "A", "B", "isTransparent", "arrowheadPoints", "options", "pointFrom", "pointRotateRads", "assertNever", "pointDistance", "getElementAbsoluteCoords", "distance", "getElementAbsoluteCoords", "pointRotateRads", "pointFrom", "curve", "lineSegment", "segments", "se", "ellipse", "a", "b", "pointFromArray", "invariant", "minX", "minY", "maxX", "maxY", "distance", "x3", "y3", "x4", "y4", "coords", "arrayToMap", "pointDistance", "x", "y", "pointsEqual", "arrayToMap", "assertNever", "isDevEnv", "isShallowEqual", "isTestEnv", "randomInteger", "assertNever", "COLOR_PALETTE", "isDevEnv", "isTestEnv", "randomId", "randomInteger", "arrayToMap", "getUpdatedTimestamp", "isTestEnv", "elements", "element", "isTestEnv", "getUpdatedTimestamp", "randomInteger", "arrayToMap", "elements", "element", "newElement", "duplicateElement", "assertNever", "isTestEnv", "isDevEnv", "randomId", "COLOR_PALETTE", "a", "b", "ib", "fb", "ia", "fa", "i", "c", "arrayToMap", "arrayToMap", "a", "b", "lowerBound", "upperBound", "i", "current", "randomInteger", "arrayToMap", "isDevEnv", "isTestEnv", "isFrameLikeElement", "getElementsInGroup", "syncInvalidIndices", "syncMovedIndices", "validateFractionalIndices", "getSelectedElements", "mutateElement", "throttle", "assertNever", "isShallowEqual", "isTestEnv", "isDevEnv", "delta", "randomInteger", "arrayToMap", "a", "b", "step", "pos", "getGridPoint", "getFontString", "DRAGGING_THRESHOLD", "DRAGGING_THRESHOLD", "getGridPoint", "newElement", "getFontString", "VERTICAL_ALIGN", "getFontString", "DEFAULT_FONT_FAMILY", "DEFAULT_FONT_SIZE", "VERTICAL_ALIGN", "randomInteger", "randomId", "getFontString", "getUpdatedTimestamp", "randomId", "randomInteger", "getUpdatedTimestamp", "DEFAULT_FONT_FAMILY", "DEFAULT_FONT_SIZE", "getFontString", "VERTICAL_ALIGN", "getElementAbsoluteCoords", "timeMatch", "getFontString", "VERTICAL_ALIGN", "KEYS", "invariant", "toBrandedType", "pointFrom", "KEYS", "invariant", "_VERTICAL_OFFSET", "y", "x", "pointFrom", "toBrandedType", "MIME_TYPES", "MIME_TYPES", "pointCenter", "normalizeRadians", "pointFrom", "pointRotateRads", "SHIFT_LOCKING_ANGLE", "rescalePoints", "getFontString", "shouldRotateWithDiscreteAngle", "getElementAbsoluteCoords", "SHIFT_LOCKING_ANGLE", "normalizeRadians", "rescalePoints", "pointFrom", "getFontString", "metrics", "pointRotateRads", "pointCenter", "width", "height", "pointFrom", "pointRotateRads", "pointFrom", "pointRotateRads", "pointRotateRads", "pointFrom", "getElementAbsoluteCoords", "getElementAbsoluteCoords", "pointFrom", "a", "pointRotateRads", "pointFrom", "DEFAULT_FONT_FAMILY", "DEFAULT_FONT_SIZE", "TEXT_ALIGN", "VERTICAL_ALIGN", "getSizeFromPoints", "randomId", "arrayToMap", "assertNever", "getFontString", "isDevEnv", "toBrandedType", "getLineHeight", "TEXT_ALIGN", "VERTICAL_ALIGN", "assertNever", "toBrandedType", "arrayToMap", "randomId", "pointFrom", "getSizeFromPoints", "DEFAULT_FONT_FAMILY", "DEFAULT_FONT_SIZE", "getLineHeight", "getFontString", "id", "isDevEnv", "arrayToMap", "findLastIndex", "arrayToMap", "moveArrowAboveBindable", "arrow", "findLastIndex", "toIterable", "getNonDeletedElements", "isNonDeletedElement"]
|
|
7
|
+
}
|