@wildmio/excalidraw 0.18.0-custom-1 → 0.18.0-custom.2
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/dist/dev/chunk-4FKPNSAF.js +25438 -0
- package/dist/dev/chunk-4FKPNSAF.js.map +7 -0
- package/dist/dev/{chunk-WCM2OLWY.js → chunk-DJHLEOOZ.js} +5 -5
- package/dist/dev/{chunk-WCM2OLWY.js.map → chunk-DJHLEOOZ.js.map} +1 -1
- package/dist/dev/{chunk-OCFTI2BU.js → chunk-OWOU4ALI.js} +3 -2
- package/dist/dev/chunk-OWOU4ALI.js.map +7 -0
- package/dist/dev/{chunk-4BGRJMQS.js → chunk-QRXFLJOF.js} +2 -2
- package/dist/dev/data/{image-HFX5FVZR.js → image-ZNW3236J.js} +3 -3
- package/dist/dev/index.css +4 -3
- package/dist/dev/index.css.map +2 -2
- package/dist/dev/index.js +3274 -5359
- package/dist/dev/index.js.map +4 -4
- package/dist/dev/locales/{de-DE-HE4SJIAA.js → de-DE-ZRDYEPMS.js} +7 -7
- package/dist/dev/locales/de-DE-ZRDYEPMS.js.map +7 -0
- package/dist/dev/locales/{en-MLZIHOCR.js → en-GWPE5KV7.js} +2 -2
- package/dist/dev/locales/{es-ES-EDA76ZAF.js → es-ES-VLQBB7FJ.js} +3 -3
- package/dist/dev/locales/es-ES-VLQBB7FJ.js.map +7 -0
- package/dist/dev/locales/{fr-FR-Z3SBW42Y.js → fr-FR-A72LKGCO.js} +2 -2
- package/dist/dev/locales/{fr-FR-Z3SBW42Y.js.map → fr-FR-A72LKGCO.js.map} +1 -1
- package/dist/dev/locales/{it-IT-HD26UZNF.js → it-IT-X34PIOJ2.js} +2 -2
- package/dist/dev/locales/{it-IT-HD26UZNF.js.map → it-IT-X34PIOJ2.js.map} +1 -1
- package/dist/dev/locales/{nl-NL-RCSOXLW3.js → nl-NL-XGZJ7V2V.js} +226 -226
- package/dist/dev/locales/nl-NL-XGZJ7V2V.js.map +7 -0
- package/dist/dev/locales/{percentages-TR7IWPFY.js → percentages-OGWD7R2K.js} +2 -2
- package/dist/dev/locales/{sk-SK-G2J6PSCB.js → sk-SK-RWC6UWGY.js} +49 -49
- package/dist/dev/locales/sk-SK-RWC6UWGY.js.map +7 -0
- package/dist/dev/locales/{vi-VN-XF3AYKJ7.js → vi-VN-KBZAVWP5.js} +3 -3
- package/dist/dev/locales/{vi-VN-XF3AYKJ7.js.map → vi-VN-KBZAVWP5.js.map} +1 -1
- package/dist/dev/subset-shared.chunk.js +1 -1
- package/dist/dev/subset-worker.chunk.js +1 -1
- package/dist/prod/{chunk-QNG5NH6R.js → chunk-2KZFBCBN.js} +1 -1
- package/dist/prod/chunk-AJI3LATG.js +1 -0
- package/dist/prod/chunk-B42KGT6Z.js +33 -0
- package/dist/prod/{chunk-RKNJTMKK.js → chunk-OVC72EOF.js} +1 -1
- package/dist/prod/data/image-T7X6V6XU.js +1 -0
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +18 -25
- package/dist/prod/locales/{de-DE-KU2ABQRN.js → de-DE-G3JVZ4MQ.js} +2 -2
- package/dist/prod/locales/{en-BARVNJLJ.js → en-7B5CVO5K.js} +1 -1
- package/dist/prod/locales/{es-ES-MXQVAWTQ.js → es-ES-ART7BI3G.js} +2 -2
- package/dist/prod/locales/{fr-FR-PJOMXPCV.js → fr-FR-XEFNCM4I.js} +1 -1
- package/dist/prod/locales/{it-IT-DQZT3VFE.js → it-IT-GIGIGIBJ.js} +3 -3
- package/dist/prod/locales/nl-NL-R4C4SUIG.js +13 -0
- package/dist/prod/locales/percentages-OL6W367U.js +1 -0
- package/dist/prod/locales/sk-SK-MC7UOHQO.js +7 -0
- package/dist/prod/locales/{vi-VN-I6Q2YS4S.js → vi-VN-K34TWHF7.js} +1 -1
- package/dist/prod/subset-shared.chunk.js +1 -1
- package/dist/prod/subset-worker.chunk.js +1 -1
- package/dist/types/common/src/colors.d.ts +4 -1
- package/dist/types/common/src/constants.d.ts +0 -1
- package/dist/types/common/src/utils.d.ts +11 -7
- package/dist/types/element/src/Scene.d.ts +3 -3
- package/dist/types/element/src/renderElement.d.ts +0 -6
- package/dist/types/element/src/shape.d.ts +5 -4
- package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +3 -0
- package/dist/types/excalidraw/actions/actionBoundText.d.ts +2 -0
- package/dist/types/excalidraw/actions/actionCanvas.d.ts +12 -0
- package/dist/types/excalidraw/actions/actionClipboard.d.ts +2 -0
- package/dist/types/excalidraw/actions/actionCropEditor.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +3 -0
- package/dist/types/excalidraw/actions/actionElementLink.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionElementLock.d.ts +2 -0
- package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionExport.d.ts +5 -1
- package/dist/types/excalidraw/actions/actionFrame.d.ts +4 -0
- package/dist/types/excalidraw/actions/actionGroup.d.ts +2 -0
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionLink.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionMenu.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionProperties.d.ts +2 -0
- package/dist/types/excalidraw/actions/actionSelectAll.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionStyles.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionToggleStats.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +1 -0
- package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +1 -0
- package/dist/types/excalidraw/appState.d.ts +2 -1
- package/dist/types/excalidraw/components/App.d.ts +2 -1
- package/dist/types/excalidraw/components/ColorPicker/ColorInput.d.ts +7 -4
- package/dist/types/excalidraw/components/ColorPicker/ColorPicker.d.ts +0 -1
- package/dist/types/excalidraw/components/EyeButton.d.ts +8 -0
- package/dist/types/excalidraw/components/MobileMenu.d.ts +2 -1
- package/dist/types/excalidraw/components/footer/Footer.d.ts +3 -1
- package/dist/types/excalidraw/components/icons.d.ts +2 -0
- package/dist/types/excalidraw/data/blob.d.ts +314 -2
- package/dist/types/excalidraw/data/json.d.ts +157 -1
- package/dist/types/excalidraw/data/restore.d.ts +22 -16
- package/dist/types/excalidraw/index.d.ts +1 -2
- package/dist/types/excalidraw/scene/Renderer.d.ts +3 -1
- package/dist/types/excalidraw/scene/types.d.ts +7 -2
- package/dist/types/excalidraw/types.d.ts +9 -0
- package/dist/types/math/src/range.d.ts +1 -3
- package/package.json +4 -4
- package/dist/dev/chunk-55IZTNXR.js +0 -5472
- package/dist/dev/chunk-55IZTNXR.js.map +0 -7
- package/dist/dev/chunk-OCFTI2BU.js.map +0 -7
- package/dist/dev/locales/de-DE-HE4SJIAA.js.map +0 -7
- package/dist/dev/locales/es-ES-EDA76ZAF.js.map +0 -7
- package/dist/dev/locales/nl-NL-RCSOXLW3.js.map +0 -7
- package/dist/dev/locales/sk-SK-G2J6PSCB.js.map +0 -7
- package/dist/prod/chunk-2KZTCREM.js +0 -4
- package/dist/prod/chunk-Q7BNPSJU.js +0 -1
- package/dist/prod/data/image-CRABYHXF.js +0 -1
- package/dist/prod/locales/nl-NL-AVTAYVB7.js +0 -7
- package/dist/prod/locales/percentages-FZSTHYWV.js +0 -1
- package/dist/prod/locales/sk-SK-2KAMKFW5.js +0 -7
- /package/dist/dev/{chunk-4BGRJMQS.js.map → chunk-QRXFLJOF.js.map} +0 -0
- /package/dist/dev/data/{image-HFX5FVZR.js.map → image-ZNW3236J.js.map} +0 -0
- /package/dist/dev/locales/{en-MLZIHOCR.js.map → en-GWPE5KV7.js.map} +0 -0
- /package/dist/dev/locales/{percentages-TR7IWPFY.js.map → percentages-OGWD7R2K.js.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../data/image.ts", "../../../common/src/binary-heap.ts", "../../../common/src/colors.ts", "../../../math/src/utils.ts", "../../../math/src/angle.ts", "../../../math/src/vector.ts", "../../../math/src/point.ts", "../../../math/src/constants.ts", "../../../math/src/curve.ts", "../../../math/src/ellipse.ts", "../../../math/src/line.ts", "../../../math/src/segment.ts", "../../../math/src/polygon.ts", "../../../math/src/range.ts", "../../../math/src/rectangle.ts", "../../../math/src/triangle.ts", "../../../common/src/constants.ts", "../../../common/src/font-metadata.ts", "../../../common/src/queue.ts", "../../../common/src/editorInterface.ts", "../../../common/src/keys.ts", "../../../common/src/points.ts", "../../../common/src/promise-pool.ts", "../../../common/src/random.ts", "../../../common/src/utils.ts", "../../../common/src/url.ts", "../../../common/src/emitter.ts", "../../data/blob.ts", "../../appState.ts", "../../errors.ts", "../../../element/src/bounds.ts", "../../../utils/src/shape.ts", "../../../element/src/shape.ts", "../../../element/src/renderElement.ts", "../../../element/src/cropElement.ts", "../../../element/src/typeChecks.ts", "../../../element/src/utils.ts", "../../../element/src/containerCache.ts", "../../../element/src/textMeasurements.ts", "../../../element/src/textWrapping.ts", "../../../element/src/textElement.ts", "../../../element/src/distance.ts", "../../../element/src/collision.ts", "../../../element/src/heading.ts", "../../../element/src/elbowArrow.ts", "../../../element/src/mutateElement.ts", "../../../element/src/binding.ts", "../../../element/src/linearElementEditor.ts", "../../../utils/src/bbox.ts", "../../../utils/src/withinBounds.ts", "../../../element/src/groups.ts", "../../../element/src/selection.ts", "../../../element/src/frame.ts", "../../../element/src/comparisons.ts", "../../../element/src/sizeHelpers.ts", "../../../element/src/align.ts", "../../../element/src/sortElements.ts", "../../../element/src/duplicate.ts", "../../../element/src/store.ts", "../../../element/src/fractionalIndex.ts", "../../../element/src/Scene.ts", "../../../element/src/delta.ts", "../../../element/src/distribute.ts", "../../../element/src/dragElements.ts", "../../../element/src/elementLink.ts", "../../../element/src/newElement.ts", "../../../element/src/embeddable.ts", "../../../element/src/flowchart.ts", "../../../element/src/image.ts", "../../../element/src/positionElementsOnGrid.ts", "../../../element/src/resizeElements.ts", "../../../element/src/transformHandles.ts", "../../../element/src/resizeTest.ts", "../../../element/src/showSelectedShapeActions.ts", "../../../element/src/transform.ts", "../../../element/src/zindex.ts", "../../../element/src/index.ts", "../../scene/scroll.ts", "../../scene/normalize.ts", "../../scene/export.ts", "../../data/encode.ts", "../../data/filesystem.ts", "../../data/json.ts", "../../fonts/Cascadia/index.ts", "../../fonts/ComicShanns/index.ts", "../../fonts/Emoji/index.ts", "../../workers.ts", "../../subset/subset-main.ts", "../../fonts/ExcalidrawFontFace.ts", "../../fonts/Excalifont/index.ts", "../../fonts/Helvetica/index.ts", "../../fonts/Liberation/index.ts", "../../fonts/Lilita/index.ts", "../../fonts/Nunito/index.ts", "../../fonts/Virgil/index.ts", "../../fonts/Xiaolai/index.ts", "../../fonts/Fonts.ts", "../../components/hyperlink/helpers.ts", "../../renderer/helpers.ts", "../../renderer/staticScene.ts", "../../renderer/staticSvgScene.ts", "../../data/restore.ts"],
|
|
4
|
+
"sourcesContent": ["import tEXt from \"png-chunk-text\";\nimport encodePng from \"png-chunks-encode\";\nimport decodePng from \"png-chunks-extract\";\n\nimport { EXPORT_DATA_TYPES, MIME_TYPES } from \"@excalidraw/common\";\n\nimport { blobToArrayBuffer } from \"./blob\";\nimport { encode, decode } from \"./encode\";\n\n// -----------------------------------------------------------------------------\n// PNG\n// -----------------------------------------------------------------------------\n\nexport const getTEXtChunk = async (\n blob: Blob,\n): Promise<{ keyword: string; text: string } | null> => {\n const chunks = decodePng(new Uint8Array(await blobToArrayBuffer(blob)));\n const metadataChunk = chunks.find((chunk) => chunk.name === \"tEXt\");\n if (metadataChunk) {\n return tEXt.decode(metadataChunk.data);\n }\n return null;\n};\n\nexport const encodePngMetadata = async ({\n blob,\n metadata,\n}: {\n blob: Blob;\n metadata: string;\n}) => {\n const chunks = decodePng(new Uint8Array(await blobToArrayBuffer(blob)));\n\n const metadataChunk = tEXt.encode(\n MIME_TYPES.excalidraw,\n JSON.stringify(\n encode({\n text: metadata,\n compress: true,\n }),\n ),\n );\n // insert metadata before last chunk (iEND)\n chunks.splice(-1, 0, metadataChunk);\n\n return new Blob([encodePng(chunks)], { type: MIME_TYPES.png });\n};\n\nexport const decodePngMetadata = async (blob: Blob) => {\n const metadata = await getTEXtChunk(blob);\n if (metadata?.keyword === MIME_TYPES.excalidraw) {\n try {\n const encodedData = JSON.parse(metadata.text);\n if (!(\"encoded\" in encodedData)) {\n // legacy, un-encoded scene JSON\n if (\n \"type\" in encodedData &&\n encodedData.type === EXPORT_DATA_TYPES.excalidraw\n ) {\n return metadata.text;\n }\n throw new Error(\"FAILED\");\n }\n return decode(encodedData);\n } catch (error: any) {\n console.error(error);\n throw new Error(\"FAILED\");\n }\n }\n throw new Error(\"INVALID\");\n};\n", "export class BinaryHeap<T> {\n private content: T[] = [];\n\n constructor(private scoreFunction: (node: T) => number) {}\n\n sinkDown(idx: number) {\n const node = this.content[idx];\n const nodeScore = this.scoreFunction(node);\n while (idx > 0) {\n const parentN = ((idx + 1) >> 1) - 1;\n const parent = this.content[parentN];\n if (nodeScore < this.scoreFunction(parent)) {\n this.content[idx] = parent;\n idx = parentN; // TODO: Optimize\n } else {\n break;\n }\n }\n this.content[idx] = node;\n }\n\n bubbleUp(idx: number) {\n const length = this.content.length;\n const node = this.content[idx];\n const score = this.scoreFunction(node);\n\n while (true) {\n const child1N = ((idx + 1) << 1) - 1;\n const child2N = child1N + 1;\n let smallestIdx = idx;\n let smallestScore = score;\n\n // Check left child\n if (child1N < length) {\n const child1Score = this.scoreFunction(this.content[child1N]);\n if (child1Score < smallestScore) {\n smallestIdx = child1N;\n smallestScore = child1Score;\n }\n }\n\n // Check right child\n if (child2N < length) {\n const child2Score = this.scoreFunction(this.content[child2N]);\n if (child2Score < smallestScore) {\n smallestIdx = child2N;\n }\n }\n\n if (smallestIdx === idx) {\n break;\n }\n\n // Move the smaller child up, continue finding position for node\n this.content[idx] = this.content[smallestIdx];\n idx = smallestIdx;\n }\n\n // Place node in its final position\n this.content[idx] = node;\n }\n\n push(node: T) {\n this.content.push(node);\n this.sinkDown(this.content.length - 1);\n }\n\n pop(): T | null {\n if (this.content.length === 0) {\n return null;\n }\n\n const result = this.content[0];\n const end = this.content.pop()!;\n\n if (this.content.length > 0) {\n this.content[0] = end;\n this.bubbleUp(0);\n }\n\n return result;\n }\n\n remove(node: T) {\n if (this.content.length === 0) {\n return;\n }\n\n const i = this.content.indexOf(node);\n const end = this.content.pop()!;\n\n if (i < this.content.length) {\n this.content[i] = end;\n\n if (this.scoreFunction(end) < this.scoreFunction(node)) {\n this.sinkDown(i);\n } else {\n this.bubbleUp(i);\n }\n }\n }\n\n size(): number {\n return this.content.length;\n }\n\n rescoreElement(node: T) {\n this.sinkDown(this.content.indexOf(node));\n }\n}\n", "import oc from \"open-color\";\nimport tinycolor from \"tinycolor2\";\n\nimport { clamp } from \"@excalidraw/math\";\nimport { degreesToRadians } from \"@excalidraw/math\";\n\nimport type { Degrees } from \"@excalidraw/math\";\n\nimport type { Merge } from \"./utility-types\";\n\nexport { tinycolor };\n\n// Browser-only cache to avoid memory leaks on server\nconst DARK_MODE_COLORS_CACHE: Map<string, string> | null =\n typeof window !== \"undefined\" ? new Map() : null;\n\n// ---------------------------------------------------------------------------\n// Dark mode color transformation\n// ---------------------------------------------------------------------------\n\nfunction cssHueRotate(\n red: number,\n green: number,\n blue: number,\n degrees: Degrees,\n): { r: number; g: number; b: number } {\n // normalize\n const r = red / 255;\n const g = green / 255;\n const b = blue / 255;\n\n // Convert degrees to radians\n const a = degreesToRadians(degrees);\n\n const c = Math.cos(a);\n const s = Math.sin(a);\n\n // rotation matrix\n const matrix = [\n 0.213 + c * 0.787 - s * 0.213,\n 0.715 - c * 0.715 - s * 0.715,\n 0.072 - c * 0.072 + s * 0.928,\n 0.213 - c * 0.213 + s * 0.143,\n 0.715 + c * 0.285 + s * 0.14,\n 0.072 - c * 0.072 - s * 0.283,\n 0.213 - c * 0.213 - s * 0.787,\n 0.715 - c * 0.715 + s * 0.715,\n 0.072 + c * 0.928 + s * 0.072,\n ];\n\n // transform\n const newR = r * matrix[0] + g * matrix[1] + b * matrix[2];\n const newG = r * matrix[3] + g * matrix[4] + b * matrix[5];\n const newB = r * matrix[6] + g * matrix[7] + b * matrix[8];\n\n // clamp the values to [0, 1] range and convert back to [0, 255]\n return {\n r: Math.round(Math.max(0, Math.min(1, newR)) * 255),\n g: Math.round(Math.max(0, Math.min(1, newG)) * 255),\n b: Math.round(Math.max(0, Math.min(1, newB)) * 255),\n };\n}\n\nconst cssInvert = (\n r: number,\n g: number,\n b: number,\n percent: number,\n): { r: number; g: number; b: number } => {\n const p = clamp(percent, 0, 100) / 100;\n\n // Function to invert a single color component\n const invertComponent = (color: number): number => {\n // Apply the invert formula\n const inverted = color * (1 - p) + (255 - color) * p;\n // Round to the nearest integer and clamp to [0, 255]\n return Math.round(clamp(inverted, 0, 255));\n };\n\n // Calculate the inverted RGB components\n const invertedR = invertComponent(r);\n const invertedG = invertComponent(g);\n const invertedB = invertComponent(b);\n\n return { r: invertedR, g: invertedG, b: invertedB };\n};\n\nexport const applyDarkModeFilter = (color: string): string => {\n const cached = DARK_MODE_COLORS_CACHE?.get(color);\n if (cached) {\n return cached;\n }\n\n const tc = tinycolor(color);\n const alpha = tc.getAlpha();\n\n // order of operations matters\n // (corresponds to \"filter: invert(invertPercent) hue-rotate(hueDegrees)\" in css)\n const rgb = tc.toRgb();\n const inverted = cssInvert(rgb.r, rgb.g, rgb.b, 93);\n const rotated = cssHueRotate(\n inverted.r,\n inverted.g,\n inverted.b,\n 180 as Degrees,\n );\n\n const result = rgbToHex(rotated.r, rotated.g, rotated.b, alpha);\n\n if (DARK_MODE_COLORS_CACHE) {\n DARK_MODE_COLORS_CACHE.set(color, result);\n }\n\n return result;\n};\n\n// ---------------------------------------------------------------------------\n\nexport const COLOR_OUTLINE_CONTRAST_THRESHOLD = 240;\n\n// FIXME can't put to utils.ts rn because of circular dependency\nconst pick = <R extends Record<string, any>, K extends readonly (keyof R)[]>(\n source: R,\n keys: K,\n) => {\n return keys.reduce((acc, key: K[number]) => {\n if (key in source) {\n acc[key] = source[key];\n }\n return acc;\n }, {} as Pick<R, K[number]>) as Pick<R, K[number]>;\n};\n\nexport type ColorPickerColor =\n | Exclude<keyof oc, \"indigo\" | \"lime\">\n | \"transparent\"\n | \"bronze\";\nexport type ColorTuple = readonly [string, string, string, string, string];\nexport type ColorPalette = Merge<\n Record<ColorPickerColor, ColorTuple>,\n { black: \"#1e1e1e\"; white: \"#ffffff\"; transparent: \"transparent\" }\n>;\n\n// used general type instead of specific type (ColorPalette) to support custom colors\nexport type ColorPaletteCustom = { [key: string]: ColorTuple | string };\nexport type ColorShadesIndexes = [number, number, number, number, number];\n\nexport const MAX_CUSTOM_COLORS_USED_IN_CANVAS = 5;\nexport const COLORS_PER_ROW = 5;\n\nexport const DEFAULT_CHART_COLOR_INDEX = 4;\n\nexport const DEFAULT_ELEMENT_STROKE_COLOR_INDEX = 4;\nexport const DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX = 1;\nexport const ELEMENTS_PALETTE_SHADE_INDEXES = [0, 2, 4, 6, 8] as const;\nexport const CANVAS_PALETTE_SHADE_INDEXES = [0, 1, 2, 3, 4] as const;\n\nexport const getSpecificColorShades = (\n color: Exclude<\n ColorPickerColor,\n \"transparent\" | \"white\" | \"black\" | \"bronze\"\n >,\n indexArr: Readonly<ColorShadesIndexes>,\n) => {\n return indexArr.map((index) => oc[color][index]) as any as ColorTuple;\n};\n\nexport const COLOR_PALETTE = {\n transparent: \"transparent\",\n black: \"#1e1e1e\",\n white: \"#ffffff\",\n // open-colors\n gray: getSpecificColorShades(\"gray\", ELEMENTS_PALETTE_SHADE_INDEXES),\n red: getSpecificColorShades(\"red\", ELEMENTS_PALETTE_SHADE_INDEXES),\n pink: getSpecificColorShades(\"pink\", ELEMENTS_PALETTE_SHADE_INDEXES),\n grape: getSpecificColorShades(\"grape\", ELEMENTS_PALETTE_SHADE_INDEXES),\n violet: getSpecificColorShades(\"violet\", ELEMENTS_PALETTE_SHADE_INDEXES),\n blue: getSpecificColorShades(\"blue\", ELEMENTS_PALETTE_SHADE_INDEXES),\n cyan: getSpecificColorShades(\"cyan\", ELEMENTS_PALETTE_SHADE_INDEXES),\n teal: getSpecificColorShades(\"teal\", ELEMENTS_PALETTE_SHADE_INDEXES),\n green: getSpecificColorShades(\"green\", ELEMENTS_PALETTE_SHADE_INDEXES),\n yellow: getSpecificColorShades(\"yellow\", ELEMENTS_PALETTE_SHADE_INDEXES),\n orange: getSpecificColorShades(\"orange\", ELEMENTS_PALETTE_SHADE_INDEXES),\n // radix bronze shades 3,5,7,9,11\n bronze: [\"#f8f1ee\", \"#eaddd7\", \"#d2bab0\", \"#a18072\", \"#846358\"],\n} as ColorPalette;\n\nconst COMMON_ELEMENT_SHADES = pick(COLOR_PALETTE, [\n \"cyan\",\n \"blue\",\n \"violet\",\n \"grape\",\n \"pink\",\n \"green\",\n \"teal\",\n \"yellow\",\n \"orange\",\n \"red\",\n]);\n\n// -----------------------------------------------------------------------------\n// quick picks defaults\n// -----------------------------------------------------------------------------\n\n// ORDER matters for positioning in quick picker\nexport const DEFAULT_ELEMENT_STROKE_PICKS = [\n COLOR_PALETTE.black,\n COLOR_PALETTE.red[DEFAULT_ELEMENT_STROKE_COLOR_INDEX],\n COLOR_PALETTE.green[DEFAULT_ELEMENT_STROKE_COLOR_INDEX],\n COLOR_PALETTE.blue[DEFAULT_ELEMENT_STROKE_COLOR_INDEX],\n COLOR_PALETTE.yellow[DEFAULT_ELEMENT_STROKE_COLOR_INDEX],\n] as ColorTuple;\n\n// ORDER matters for positioning in quick picker\nexport const DEFAULT_ELEMENT_BACKGROUND_PICKS = [\n COLOR_PALETTE.transparent,\n COLOR_PALETTE.red[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX],\n COLOR_PALETTE.green[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX],\n COLOR_PALETTE.blue[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX],\n COLOR_PALETTE.yellow[DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX],\n] as ColorTuple;\n\n// ORDER matters for positioning in quick picker\nexport const DEFAULT_CANVAS_BACKGROUND_PICKS = [\n COLOR_PALETTE.white,\n // radix slate2\n \"#f8f9fa\",\n // radix blue2\n \"#f5faff\",\n // radix yellow2\n \"#fffce8\",\n // radix bronze2\n \"#fdf8f6\",\n] as ColorTuple;\n\n// -----------------------------------------------------------------------------\n// palette defaults\n// -----------------------------------------------------------------------------\n\nexport const DEFAULT_ELEMENT_STROKE_COLOR_PALETTE = {\n // 1st row\n transparent: COLOR_PALETTE.transparent,\n white: COLOR_PALETTE.white,\n gray: COLOR_PALETTE.gray,\n black: COLOR_PALETTE.black,\n bronze: COLOR_PALETTE.bronze,\n // rest\n ...COMMON_ELEMENT_SHADES,\n} as const;\n\n// ORDER matters for positioning in pallete (5x3 grid)s\nexport const DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE = {\n transparent: COLOR_PALETTE.transparent,\n white: COLOR_PALETTE.white,\n gray: COLOR_PALETTE.gray,\n black: COLOR_PALETTE.black,\n bronze: COLOR_PALETTE.bronze,\n\n ...COMMON_ELEMENT_SHADES,\n} as const;\n\n// -----------------------------------------------------------------------------\n// helpers\n// -----------------------------------------------------------------------------\n\n// !!!MUST BE WITHOUT GRAY, TRANSPARENT AND BLACK!!!\nexport const getAllColorsSpecificShade = (index: 0 | 1 | 2 | 3 | 4) =>\n [\n // 2nd row\n COLOR_PALETTE.cyan[index],\n COLOR_PALETTE.blue[index],\n COLOR_PALETTE.violet[index],\n COLOR_PALETTE.grape[index],\n COLOR_PALETTE.pink[index],\n\n // 3rd row\n COLOR_PALETTE.green[index],\n COLOR_PALETTE.teal[index],\n COLOR_PALETTE.yellow[index],\n COLOR_PALETTE.orange[index],\n COLOR_PALETTE.red[index],\n ] as const;\n\nexport const rgbToHex = (r: number, g: number, b: number, a?: number) => {\n // (1 << 24) adds 0x1000000 to ensure the hex string is always 7 chars,\n // then slice(1) removes the leading \"1\" to get exactly 6 hex digits\n // e.g. rgb(0,0,0) -> 0x1000000 -> \"1000000\" -> \"000000\"\n const hex6 = `#${((1 << 24) + (r << 16) + (g << 8) + b)\n .toString(16)\n .slice(1)}`;\n if (a !== undefined && a < 1) {\n // convert alpha from 0-1 float to 0-255 int, then to 2-digit hex\n // e.g. 0.5 -> 128 -> \"80\"\n const alphaHex = Math.round(a * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `${hex6}${alphaHex}`;\n }\n return hex6;\n};\n\n// -----------------------------------------------------------------------------\n", "export const PRECISION = 10e-5;\n\nexport const clamp = (value: number, min: number, max: number) => {\n return Math.min(Math.max(value, min), max);\n};\n\nexport const round = (\n value: number,\n precision: number,\n func: \"round\" | \"floor\" | \"ceil\" = \"round\",\n) => {\n const multiplier = Math.pow(10, precision);\n\n return Math[func]((value + Number.EPSILON) * multiplier) / multiplier;\n};\n\nexport const roundToStep = (\n value: number,\n step: number,\n func: \"round\" | \"floor\" | \"ceil\" = \"round\",\n): number => {\n const factor = 1 / step;\n return Math[func](value * factor) / factor;\n};\n\nexport const average = (a: number, b: number) => (a + b) / 2;\n\nexport const isFiniteNumber = (value: any): value is number => {\n return typeof value === \"number\" && Number.isFinite(value);\n};\n\nexport const isCloseTo = (a: number, b: number, precision = PRECISION) =>\n Math.abs(a - b) < precision;\n", "import { PRECISION } from \"./utils\";\n\nimport type {\n Degrees,\n GlobalPoint,\n LocalPoint,\n PolarCoords,\n Radians,\n} from \"./types\";\n\nexport const normalizeRadians = (angle: Radians): Radians =>\n angle < 0\n ? (((angle % (2 * Math.PI)) + 2 * Math.PI) as Radians)\n : ((angle % (2 * Math.PI)) as Radians);\n\n/**\n * Return the polar coordinates for the given cartesian point represented by\n * (x, y) for the center point 0,0 where the first number returned is the radius,\n * the second is the angle in radians.\n */\nexport const cartesian2Polar = <P extends GlobalPoint | LocalPoint>([\n x,\n y,\n]: P): PolarCoords => [\n Math.hypot(x, y),\n normalizeRadians(Math.atan2(y, x) as Radians),\n];\n\nexport function degreesToRadians(degrees: Degrees): Radians {\n return ((degrees * Math.PI) / 180) as Radians;\n}\n\nexport function radiansToDegrees(degrees: Radians): Degrees {\n return ((degrees * 180) / Math.PI) as Degrees;\n}\n\n/**\n * Determines if the provided angle is a right angle.\n *\n * @param rads The angle to measure\n * @returns TRUE if the provided angle is a right angle\n */\nexport function isRightAngleRads(rads: Radians): boolean {\n return Math.abs(Math.sin(2 * rads)) < PRECISION;\n}\n\nexport function radiansBetweenAngles(\n a: Radians,\n min: Radians,\n max: Radians,\n): boolean {\n a = normalizeRadians(a);\n min = normalizeRadians(min);\n max = normalizeRadians(max);\n\n if (min < max) {\n return a >= min && a <= max;\n }\n\n // The range wraps around the 0 angle\n return a >= min || a <= max;\n}\n\nexport function radiansDifference(a: Radians, b: Radians): Radians {\n a = normalizeRadians(a);\n b = normalizeRadians(b);\n\n let diff = a - b;\n\n if (diff < -Math.PI) {\n diff = (diff + 2 * Math.PI) as Radians;\n } else if (diff > Math.PI) {\n diff = (diff - 2 * Math.PI) as Radians;\n }\n\n return Math.abs(diff) as Radians;\n}\n", "import type { GlobalPoint, LocalPoint, Vector } from \"./types\";\n\n/**\n * Create a vector from the x and y coordiante elements.\n *\n * @param x The X aspect of the vector\n * @param y T Y aspect of the vector\n * @returns The constructed vector with X and Y as the coordinates\n */\nexport function vector(\n x: number,\n y: number,\n originX: number = 0,\n originY: number = 0,\n): Vector {\n return [x - originX, y - originY] as Vector;\n}\n\n/**\n * Turn a point into a vector with the origin point.\n *\n * @param p The point to turn into a vector\n * @param origin The origin point in a given coordiante system\n * @param threshold The threshold to consider the vector as 'undefined'\n * @param defaultValue The default value to return if the vector is 'undefined'\n * @returns The created vector from the point and the origin or default\n */\nexport function vectorFromPoint<Point extends GlobalPoint | LocalPoint>(\n p: Point,\n origin: Point = [0, 0] as Point,\n threshold?: number,\n defaultValue: Vector = [0, 1] as Vector,\n): Vector {\n const vec = vector(p[0] - origin[0], p[1] - origin[1]);\n\n if (threshold && vectorMagnitudeSq(vec) < threshold * threshold) {\n return defaultValue;\n }\n\n return vec;\n}\n\n/**\n * Cross product is a binary operation on two vectors in 2D space.\n * It results in a vector that is perpendicular to both vectors.\n *\n * @param a One of the vectors to use for the directed area calculation\n * @param b The other vector to use for the directed area calculation\n * @returns The directed area value for the two vectos\n */\nexport function vectorCross(a: Vector, b: Vector): number {\n return a[0] * b[1] - b[0] * a[1];\n}\n\n/**\n * Dot product is defined as the sum of the products of the\n * two vectors.\n *\n * @param a One of the vectors for which the sum of products is calculated\n * @param b The other vector for which the sum of products is calculated\n * @returns The sum of products of the two vectors\n */\nexport function vectorDot(a: Vector, b: Vector) {\n return a[0] * b[0] + a[1] * b[1];\n}\n\n/**\n * Determines if the value has the shape of a Vector.\n *\n * @param v The value to test\n * @returns TRUE if the value has the shape and components of a Vectors\n */\nexport function isVector(v: unknown): v is Vector {\n return (\n Array.isArray(v) &&\n v.length === 2 &&\n typeof v[0] === \"number\" &&\n !isNaN(v[0]) &&\n typeof v[1] === \"number\" &&\n !isNaN(v[1])\n );\n}\n\n/**\n * Add two vectors by adding their coordinates.\n *\n * @param a One of the vectors to add\n * @param b The other vector to add\n * @returns The sum vector of the two provided vectors\n */\nexport function vectorAdd(a: Readonly<Vector>, b: Readonly<Vector>): Vector {\n return [a[0] + b[0], a[1] + b[1]] as Vector;\n}\n\n/**\n * Add two vectors by adding their coordinates.\n *\n * @param start One of the vectors to add\n * @param end The other vector to add\n * @returns The sum vector of the two provided vectors\n */\nexport function vectorSubtract(\n start: Readonly<Vector>,\n end: Readonly<Vector>,\n): Vector {\n return [start[0] - end[0], start[1] - end[1]] as Vector;\n}\n\n/**\n * Scale vector by a scalar.\n *\n * @param v The vector to scale\n * @param scalar The scalar to multiply the vector components with\n * @returns The new scaled vector\n */\nexport function vectorScale(v: Vector, scalar: number): Vector {\n return vector(v[0] * scalar, v[1] * scalar);\n}\n\n/**\n * Calculates the sqare magnitude of a vector. Use this if you compare\n * magnitudes as it saves you an SQRT.\n *\n * @param v The vector to measure\n * @returns The scalar squared magnitude of the vector\n */\nexport function vectorMagnitudeSq(v: Vector) {\n return v[0] * v[0] + v[1] * v[1];\n}\n\n/**\n * Calculates the magnitude of a vector.\n *\n * @param v The vector to measure\n * @returns The scalar magnitude of the vector\n */\nexport function vectorMagnitude(v: Vector) {\n return Math.sqrt(vectorMagnitudeSq(v));\n}\n\n/**\n * Normalize the vector (i.e. make the vector magnitue equal 1).\n *\n * @param v The vector to normalize\n * @returns The new normalized vector\n */\nexport const vectorNormalize = (v: Vector): Vector => {\n const m = vectorMagnitude(v);\n\n if (m === 0) {\n return vector(0, 0);\n }\n\n return vector(v[0] / m, v[1] / m);\n};\n\n/**\n * Calculate the right-hand normal of the vector.\n */\nexport const vectorNormal = (v: Vector): Vector => vector(v[1], -v[0]);\n", "import { degreesToRadians } from \"./angle\";\nimport { PRECISION } from \"./utils\";\nimport { vectorFromPoint, vectorScale } from \"./vector\";\n\nimport type {\n LocalPoint,\n GlobalPoint,\n Radians,\n Degrees,\n Vector,\n} from \"./types\";\n\n/**\n * Create a properly typed Point instance from the X and Y coordinates.\n *\n * @param x The X coordinate\n * @param y The Y coordinate\n * @returns The branded and created point\n */\nexport function pointFrom<Point extends GlobalPoint | LocalPoint>(\n x: number,\n y: number,\n): Point {\n return [x, y] as Point;\n}\n\n/**\n * Converts and remaps an array containing a pair of numbers to Point.\n *\n * @param numberArray The number array to check and to convert to Point\n * @returns The point instance\n */\nexport function pointFromArray<Point extends GlobalPoint | LocalPoint>(\n numberArray: number[],\n): Point | undefined {\n return numberArray.length === 2\n ? pointFrom<Point>(numberArray[0], numberArray[1])\n : undefined;\n}\n\n/**\n * Converts and remaps a pair of numbers to Point.\n *\n * @param pair A number pair to convert to Point\n * @returns The point instance\n */\nexport function pointFromPair<Point extends GlobalPoint | LocalPoint>(\n pair: [number, number],\n): Point {\n return pair as Point;\n}\n\n/**\n * Convert a vector to a point.\n *\n * @param v The vector to convert\n * @returns The point the vector points at with origin 0,0\n */\nexport function pointFromVector<P extends GlobalPoint | LocalPoint>(\n v: Vector,\n offset: P = pointFrom(0, 0),\n): P {\n return pointFrom<P>(offset[0] + v[0], offset[1] + v[1]);\n}\n\n/**\n * Checks if the provided value has the shape of a Point.\n *\n * @param p The value to attempt verification on\n * @returns TRUE if the provided value has the shape of a local or global point\n */\nexport function isPoint(p: unknown): p is LocalPoint | GlobalPoint {\n return (\n Array.isArray(p) &&\n p.length === 2 &&\n typeof p[0] === \"number\" &&\n !isNaN(p[0]) &&\n typeof p[1] === \"number\" &&\n !isNaN(p[1])\n );\n}\n\n/**\n * Compare two points coordinate-by-coordinate and if\n * they are closer than INVERSE_PRECISION it returns TRUE.\n *\n * @param a Point The first point to compare\n * @param b Point The second point to compare\n * @returns TRUE if the points are sufficiently close to each other\n */\nexport function pointsEqual<Point extends GlobalPoint | LocalPoint>(\n a: Point,\n b: Point,\n tolerance: number = PRECISION,\n): boolean {\n const abs = Math.abs;\n return abs(a[0] - b[0]) < tolerance && abs(a[1] - b[1]) < tolerance;\n}\n\n/**\n * Rotate a point by [angle] radians.\n *\n * @param point The point to rotate\n * @param center The point to rotate around, the center point\n * @param angle The radians to rotate the point by\n * @returns The rotated point\n */\nexport function pointRotateRads<Point extends GlobalPoint | LocalPoint>(\n [x, y]: Point,\n [cx, cy]: Point,\n angle: Radians,\n): Point {\n return pointFrom(\n (x - cx) * Math.cos(angle) - (y - cy) * Math.sin(angle) + cx,\n (x - cx) * Math.sin(angle) + (y - cy) * Math.cos(angle) + cy,\n );\n}\n\n/**\n * Rotate a point by [angle] degree.\n *\n * @param point The point to rotate\n * @param center The point to rotate around, the center point\n * @param angle The degree to rotate the point by\n * @returns The rotated point\n */\nexport function pointRotateDegs<Point extends GlobalPoint | LocalPoint>(\n point: Point,\n center: Point,\n angle: Degrees,\n): Point {\n return pointRotateRads(point, center, degreesToRadians(angle));\n}\n\n/**\n * Translate a point by a vector.\n *\n * WARNING: This is not for translating Excalidraw element points!\n * You need to account for rotation on base coordinates\n * on your own.\n * CONSIDER USING AN APPROPRIATE ELEMENT-AWARE TRANSLATE!\n *\n * @param p The point to apply the translation on\n * @param v The vector to translate by\n * @returns\n */\n// TODO 99% of use is translating between global and local coords, which need to be formalized\nexport function pointTranslate<\n From extends GlobalPoint | LocalPoint,\n To extends GlobalPoint | LocalPoint,\n>(p: From, v: Vector = [0, 0] as Vector): To {\n return pointFrom(p[0] + v[0], p[1] + v[1]);\n}\n\n/**\n * Find the center point at equal distance from both points.\n *\n * @param a One of the points to create the middle point for\n * @param b The other point to create the middle point for\n * @returns The middle point\n */\nexport function pointCenter<P extends LocalPoint | GlobalPoint>(a: P, b: P): P {\n return pointFrom((a[0] + b[0]) / 2, (a[1] + b[1]) / 2);\n}\n\n/**\n * Calculate the distance between two points.\n *\n * @param a First point\n * @param b Second point\n * @returns The euclidean distance between the two points.\n */\nexport function pointDistance<P extends LocalPoint | GlobalPoint>(\n a: P,\n b: P,\n): number {\n return Math.hypot(b[0] - a[0], b[1] - a[1]);\n}\n\n/**\n * Calculate the squared distance between two points.\n *\n * Note: Use this if you only compare distances, it saves a square root.\n *\n * @param a First point\n * @param b Second point\n * @returns The euclidean distance between the two points.\n */\nexport function pointDistanceSq<P extends LocalPoint | GlobalPoint>(\n a: P,\n b: P,\n): number {\n const xDiff = b[0] - a[0];\n const yDiff = b[1] - a[1];\n\n return xDiff * xDiff + yDiff * yDiff;\n}\n\n/**\n * Scale a point from a given origin by the multiplier.\n *\n * @param p The point to scale\n * @param mid The origin to scale from\n * @param multiplier The scaling factor\n * @returns\n */\nexport const pointScaleFromOrigin = <P extends GlobalPoint | LocalPoint>(\n p: P,\n mid: P,\n multiplier: number,\n) => pointTranslate(mid, vectorScale(vectorFromPoint(p, mid), multiplier));\n\n/**\n * Returns whether `q` lies inside the segment/rectangle defined by `p` and `r`.\n * This is an approximation to \"does `q` lie on a segment `pr`\" check.\n *\n * @param p The first point to compare against\n * @param q The actual point this function checks whether is in between\n * @param r The other point to compare against\n * @returns TRUE if q is indeed between p and r\n */\nexport const isPointWithinBounds = <P extends GlobalPoint | LocalPoint>(\n p: P,\n q: P,\n r: P,\n) => {\n return (\n q[0] <= Math.max(p[0], r[0]) &&\n q[0] >= Math.min(p[0], r[0]) &&\n q[1] <= Math.max(p[1], r[1]) &&\n q[1] >= Math.min(p[1], r[1])\n );\n};\n", "export const PRECISION = 10e-5;\n\n// Legendre-Gauss abscissae (x values) and weights for n=24\n// Refeerence: https://pomax.github.io/bezierinfo/legendre-gauss.html\nexport const LegendreGaussN24TValues = [\n -0.0640568928626056260850430826247450385909,\n 0.0640568928626056260850430826247450385909,\n -0.1911188674736163091586398207570696318404,\n 0.1911188674736163091586398207570696318404,\n -0.3150426796961633743867932913198102407864,\n 0.3150426796961633743867932913198102407864,\n -0.4337935076260451384870842319133497124524,\n 0.4337935076260451384870842319133497124524,\n -0.5454214713888395356583756172183723700107,\n 0.5454214713888395356583756172183723700107,\n -0.6480936519369755692524957869107476266696,\n 0.6480936519369755692524957869107476266696,\n -0.7401241915785543642438281030999784255232,\n 0.7401241915785543642438281030999784255232,\n -0.8200019859739029219539498726697452080761,\n 0.8200019859739029219539498726697452080761,\n -0.8864155270044010342131543419821967550873,\n 0.8864155270044010342131543419821967550873,\n -0.9382745520027327585236490017087214496548,\n 0.9382745520027327585236490017087214496548,\n -0.9747285559713094981983919930081690617411,\n 0.9747285559713094981983919930081690617411,\n -0.9951872199970213601799974097007368118745,\n 0.9951872199970213601799974097007368118745,\n];\n\nexport const LegendreGaussN24CValues = [\n 0.1279381953467521569740561652246953718517,\n 0.1279381953467521569740561652246953718517,\n 0.1258374563468282961213753825111836887264,\n 0.1258374563468282961213753825111836887264,\n 0.121670472927803391204463153476262425607,\n 0.121670472927803391204463153476262425607,\n 0.1155056680537256013533444839067835598622,\n 0.1155056680537256013533444839067835598622,\n 0.1074442701159656347825773424466062227946,\n 0.1074442701159656347825773424466062227946,\n 0.0976186521041138882698806644642471544279,\n 0.0976186521041138882698806644642471544279,\n 0.086190161531953275917185202983742667185,\n 0.086190161531953275917185202983742667185,\n 0.0733464814110803057340336152531165181193,\n 0.0733464814110803057340336152531165181193,\n 0.0592985849154367807463677585001085845412,\n 0.0592985849154367807463677585001085845412,\n 0.0442774388174198061686027482113382288593,\n 0.0442774388174198061686027482113382288593,\n 0.0285313886289336631813078159518782864491,\n 0.0285313886289336631813078159518782864491,\n 0.0123412297999871995468056670700372915759,\n 0.0123412297999871995468056670700372915759,\n];\n", "import { isPoint, pointDistance, pointFrom, pointFromVector } from \"./point\";\nimport { vector, vectorNormal, vectorNormalize, vectorScale } from \"./vector\";\nimport { LegendreGaussN24CValues, LegendreGaussN24TValues } from \"./constants\";\n\nimport type { Curve, GlobalPoint, LineSegment, LocalPoint } from \"./types\";\n\n/**\n *\n * @param a\n * @param b\n * @param c\n * @param d\n * @returns\n */\nexport function curve<Point extends GlobalPoint | LocalPoint>(\n a: Point,\n b: Point,\n c: Point,\n d: Point,\n) {\n return [a, b, c, d] as Curve<Point>;\n}\n\nfunction solveWithAnalyticalJacobian<Point extends GlobalPoint | LocalPoint>(\n curve: Curve<Point>,\n lineSegment: LineSegment<Point>,\n t0: number,\n s0: number,\n tolerance: number = 1e-3,\n iterLimit: number = 10,\n): number[] | null {\n let error = Infinity;\n let iter = 0;\n\n while (error >= tolerance) {\n if (iter >= iterLimit) {\n return null;\n }\n\n // Compute bezier point at parameter t0\n const bt = 1 - t0;\n const bt2 = bt * bt;\n const bt3 = bt2 * bt;\n const t0_2 = t0 * t0;\n const t0_3 = t0_2 * t0;\n\n const bezierX =\n bt3 * curve[0][0] +\n 3 * bt2 * t0 * curve[1][0] +\n 3 * bt * t0_2 * curve[2][0] +\n t0_3 * curve[3][0];\n const bezierY =\n bt3 * curve[0][1] +\n 3 * bt2 * t0 * curve[1][1] +\n 3 * bt * t0_2 * curve[2][1] +\n t0_3 * curve[3][1];\n\n // Compute line point at parameter s0\n const lineX =\n lineSegment[0][0] + s0 * (lineSegment[1][0] - lineSegment[0][0]);\n const lineY =\n lineSegment[0][1] + s0 * (lineSegment[1][1] - lineSegment[0][1]);\n\n // Function values\n const fx = bezierX - lineX;\n const fy = bezierY - lineY;\n\n error = Math.abs(fx) + Math.abs(fy);\n\n if (error < tolerance) {\n break;\n }\n\n // Analytical derivatives\n const dfx_dt =\n -3 * bt2 * curve[0][0] +\n 3 * bt2 * curve[1][0] -\n 6 * bt * t0 * curve[1][0] -\n 3 * t0_2 * curve[2][0] +\n 6 * bt * t0 * curve[2][0] +\n 3 * t0_2 * curve[3][0];\n\n const dfy_dt =\n -3 * bt2 * curve[0][1] +\n 3 * bt2 * curve[1][1] -\n 6 * bt * t0 * curve[1][1] -\n 3 * t0_2 * curve[2][1] +\n 6 * bt * t0 * curve[2][1] +\n 3 * t0_2 * curve[3][1];\n\n // Line derivatives\n const dfx_ds = -(lineSegment[1][0] - lineSegment[0][0]);\n const dfy_ds = -(lineSegment[1][1] - lineSegment[0][1]);\n\n // Jacobian determinant\n const det = dfx_dt * dfy_ds - dfx_ds * dfy_dt;\n\n if (Math.abs(det) < 1e-12) {\n return null;\n }\n\n // Newton step\n const invDet = 1 / det;\n const dt = invDet * (dfy_ds * -fx - dfx_ds * -fy);\n const ds = invDet * (-dfy_dt * -fx + dfx_dt * -fy);\n\n t0 += dt;\n s0 += ds;\n iter += 1;\n }\n\n return [t0, s0];\n}\n\nexport const bezierEquation = <Point extends GlobalPoint | LocalPoint>(\n c: Curve<Point>,\n t: number,\n) =>\n pointFrom<Point>(\n (1 - t) ** 3 * c[0][0] +\n 3 * (1 - t) ** 2 * t * c[1][0] +\n 3 * (1 - t) * t ** 2 * c[2][0] +\n t ** 3 * c[3][0],\n (1 - t) ** 3 * c[0][1] +\n 3 * (1 - t) ** 2 * t * c[1][1] +\n 3 * (1 - t) * t ** 2 * c[2][1] +\n t ** 3 * c[3][1],\n );\n\nconst initial_guesses: [number, number][] = [\n [0.5, 0],\n [0.2, 0],\n [0.8, 0],\n];\n\nconst calculate = <Point extends GlobalPoint | LocalPoint>(\n [t0, s0]: [number, number],\n l: LineSegment<Point>,\n c: Curve<Point>,\n) => {\n const solution = solveWithAnalyticalJacobian(c, l, t0, s0, 1e-2, 3);\n\n if (!solution) {\n return null;\n }\n\n const [t, s] = solution;\n\n if (t < 0 || t > 1 || s < 0 || s > 1) {\n return null;\n }\n\n return bezierEquation(c, t);\n};\n\n/**\n * Computes the intersection between a cubic spline and a line segment.\n */\nexport function curveIntersectLineSegment<\n Point extends GlobalPoint | LocalPoint,\n>(c: Curve<Point>, l: LineSegment<Point>): Point[] {\n let solution = calculate(initial_guesses[0], l, c);\n if (solution) {\n return [solution];\n }\n\n solution = calculate(initial_guesses[1], l, c);\n if (solution) {\n return [solution];\n }\n\n solution = calculate(initial_guesses[2], l, c);\n if (solution) {\n return [solution];\n }\n\n return [];\n}\n\n/**\n * Finds the closest point on the Bezier curve from another point\n *\n * @param x\n * @param y\n * @param P0\n * @param P1\n * @param P2\n * @param P3\n * @param tolerance\n * @param maxLevel\n * @returns\n */\nexport function curveClosestPoint<Point extends GlobalPoint | LocalPoint>(\n c: Curve<Point>,\n p: Point,\n tolerance: number = 1e-3,\n): Point | null {\n const localMinimum = (\n min: number,\n max: number,\n f: (t: number) => number,\n e: number = tolerance,\n ) => {\n let m = min;\n let n = max;\n let k;\n\n while (n - m > e) {\n k = (n + m) / 2;\n if (f(k - e) < f(k + e)) {\n n = k;\n } else {\n m = k;\n }\n }\n\n return k;\n };\n\n const maxSteps = 30;\n let closestStep = 0;\n for (let min = Infinity, step = 0; step < maxSteps; step++) {\n const d = pointDistance(p, bezierEquation(c, step / maxSteps));\n if (d < min) {\n min = d;\n closestStep = step;\n }\n }\n\n const t0 = Math.max((closestStep - 1) / maxSteps, 0);\n const t1 = Math.min((closestStep + 1) / maxSteps, 1);\n const solution = localMinimum(t0, t1, (t) =>\n pointDistance(p, bezierEquation(c, t)),\n );\n\n if (!solution) {\n return null;\n }\n\n return bezierEquation(c, solution);\n}\n\n/**\n * Determines the distance between a point and the closest point on the\n * Bezier curve.\n *\n * @param c The curve to test\n * @param p The point to measure from\n */\nexport function curvePointDistance<Point extends GlobalPoint | LocalPoint>(\n c: Curve<Point>,\n p: Point,\n) {\n const closest = curveClosestPoint(c, p);\n\n if (!closest) {\n return 0;\n }\n\n return pointDistance(p, closest);\n}\n\n/**\n * Determines if the parameter is a Curve\n */\nexport function isCurve<P extends GlobalPoint | LocalPoint>(\n v: unknown,\n): v is Curve<P> {\n return (\n Array.isArray(v) &&\n v.length === 4 &&\n isPoint(v[0]) &&\n isPoint(v[1]) &&\n isPoint(v[2]) &&\n isPoint(v[3])\n );\n}\n\nexport function curveTangent<Point extends GlobalPoint | LocalPoint>(\n [p0, p1, p2, p3]: Curve<Point>,\n t: number,\n) {\n return vector(\n -3 * (1 - t) * (1 - t) * p0[0] +\n 3 * (1 - t) * (1 - t) * p1[0] -\n 6 * t * (1 - t) * p1[0] -\n 3 * t * t * p2[0] +\n 6 * t * (1 - t) * p2[0] +\n 3 * t * t * p3[0],\n -3 * (1 - t) * (1 - t) * p0[1] +\n 3 * (1 - t) * (1 - t) * p1[1] -\n 6 * t * (1 - t) * p1[1] -\n 3 * t * t * p2[1] +\n 6 * t * (1 - t) * p2[1] +\n 3 * t * t * p3[1],\n );\n}\n\nexport function curveCatmullRomQuadraticApproxPoints(\n points: GlobalPoint[],\n tension = 0.5,\n) {\n if (points.length < 2) {\n return;\n }\n\n const pointSets: [GlobalPoint, GlobalPoint][] = [];\n for (let i = 0; i < points.length - 1; i++) {\n const p0 = points[i - 1 < 0 ? 0 : i - 1];\n const p1 = points[i];\n const p2 = points[i + 1 >= points.length ? points.length - 1 : i + 1];\n const cpX = p1[0] + ((p2[0] - p0[0]) * tension) / 2;\n const cpY = p1[1] + ((p2[1] - p0[1]) * tension) / 2;\n\n pointSets.push([\n pointFrom<GlobalPoint>(cpX, cpY),\n pointFrom<GlobalPoint>(p2[0], p2[1]),\n ]);\n }\n\n return pointSets;\n}\n\nexport function curveCatmullRomCubicApproxPoints<\n Point extends GlobalPoint | LocalPoint,\n>(points: Point[], tension = 0.5) {\n if (points.length < 2) {\n return;\n }\n\n const pointSets: Curve<Point>[] = [];\n for (let i = 0; i < points.length - 1; i++) {\n const p0 = points[i - 1 < 0 ? 0 : i - 1];\n const p1 = points[i];\n const p2 = points[i + 1 >= points.length ? points.length - 1 : i + 1];\n const p3 = points[i + 2 >= points.length ? points.length - 1 : i + 2];\n const tangent1 = [(p2[0] - p0[0]) * tension, (p2[1] - p0[1]) * tension];\n const tangent2 = [(p3[0] - p1[0]) * tension, (p3[1] - p1[1]) * tension];\n const cp1x = p1[0] + tangent1[0] / 3;\n const cp1y = p1[1] + tangent1[1] / 3;\n const cp2x = p2[0] - tangent2[0] / 3;\n const cp2y = p2[1] - tangent2[1] / 3;\n\n pointSets.push(\n curve(\n pointFrom(p1[0], p1[1]),\n pointFrom(cp1x, cp1y),\n pointFrom(cp2x, cp2y),\n pointFrom(p2[0], p2[1]),\n ),\n );\n }\n\n return pointSets;\n}\n\nexport function curveOffsetPoints(\n [p0, p1, p2, p3]: Curve<GlobalPoint>,\n offset: number,\n steps = 50,\n) {\n const offsetPoints = [];\n\n for (let i = 0; i <= steps; i++) {\n const t = i / steps;\n const c = curve(p0, p1, p2, p3);\n const point = bezierEquation(c, t);\n const tangent = vectorNormalize(curveTangent(c, t));\n const normal = vectorNormal(tangent);\n\n offsetPoints.push(pointFromVector(vectorScale(normal, offset), point));\n }\n\n return offsetPoints;\n}\n\nexport function offsetPointsForQuadraticBezier(\n p0: GlobalPoint,\n p1: GlobalPoint,\n p2: GlobalPoint,\n offsetDist: number,\n steps = 50,\n) {\n const offsetPoints = [];\n\n for (let i = 0; i <= steps; i++) {\n const t = i / steps;\n const t1 = 1 - t;\n const point = pointFrom<GlobalPoint>(\n t1 * t1 * p0[0] + 2 * t1 * t * p1[0] + t * t * p2[0],\n t1 * t1 * p0[1] + 2 * t1 * t * p1[1] + t * t * p2[1],\n );\n const tangentX = 2 * (1 - t) * (p1[0] - p0[0]) + 2 * t * (p2[0] - p1[0]);\n const tangentY = 2 * (1 - t) * (p1[1] - p0[1]) + 2 * t * (p2[1] - p1[1]);\n const tangent = vectorNormalize(vector(tangentX, tangentY));\n const normal = vectorNormal(tangent);\n\n offsetPoints.push(pointFromVector(vectorScale(normal, offsetDist), point));\n }\n\n return offsetPoints;\n}\n\n/**\n * Implementation based on Legendre-Gauss quadrature for more accurate arc\n * length calculation.\n *\n * Reference: https://pomax.github.io/bezierinfo/#arclength\n *\n * @param c The curve to calculate the length of\n * @returns The approximated length of the curve\n */\nexport function curveLength<P extends GlobalPoint | LocalPoint>(\n c: Curve<P>,\n): number {\n const z2 = 0.5;\n let sum = 0;\n\n for (let i = 0; i < 24; i++) {\n const t = z2 * LegendreGaussN24TValues[i] + z2;\n const derivativeVector = curveTangent(c, t);\n const magnitude = Math.sqrt(\n derivativeVector[0] * derivativeVector[0] +\n derivativeVector[1] * derivativeVector[1],\n );\n sum += LegendreGaussN24CValues[i] * magnitude;\n }\n\n return z2 * sum;\n}\n\n/**\n * Calculates the curve length from t=0 to t=parameter using the same\n * Legendre-Gauss quadrature method used in curveLength\n *\n * @param c The curve to calculate the partial length for\n * @param t The parameter value (0 to 1) to calculate length up to\n * @returns The length of the curve from beginning to parameter t\n */\nexport function curveLengthAtParameter<P extends GlobalPoint | LocalPoint>(\n c: Curve<P>,\n t: number,\n): number {\n if (t <= 0) {\n return 0;\n }\n if (t >= 1) {\n return curveLength(c);\n }\n\n // Scale and shift the integration interval from [0,t] to [-1,1]\n // which is what the Legendre-Gauss quadrature expects\n const z1 = t / 2;\n const z2 = t / 2;\n\n let sum = 0;\n\n for (let i = 0; i < 24; i++) {\n const parameter = z1 * LegendreGaussN24TValues[i] + z2;\n const derivativeVector = curveTangent(c, parameter);\n const magnitude = Math.sqrt(\n derivativeVector[0] * derivativeVector[0] +\n derivativeVector[1] * derivativeVector[1],\n );\n sum += LegendreGaussN24CValues[i] * magnitude;\n }\n\n return z1 * sum; // Scale the result back to the original interval\n}\n\n/**\n * Calculates the point at a specific percentage of a curve's total length\n * using binary search for improved efficiency and accuracy.\n *\n * @param c The curve to calculate point on\n * @param percent A value between 0 and 1 representing the percentage of the curve's length\n * @returns The point at the specified percentage of curve length\n */\nexport function curvePointAtLength<P extends GlobalPoint | LocalPoint>(\n c: Curve<P>,\n percent: number,\n): P {\n if (percent <= 0) {\n return bezierEquation(c, 0);\n }\n\n if (percent >= 1) {\n return bezierEquation(c, 1);\n }\n\n const totalLength = curveLength(c);\n const targetLength = totalLength * percent;\n\n // Binary search to find parameter t where length at t equals target length\n let tMin = 0;\n let tMax = 1;\n let t = percent; // Start with a reasonable guess (t = percent)\n let currentLength = 0;\n\n // Tolerance for length comparison and iteration limit to avoid infinite loops\n const tolerance = totalLength * 0.0001;\n const maxIterations = 20;\n\n for (let iteration = 0; iteration < maxIterations; iteration++) {\n currentLength = curveLengthAtParameter(c, t);\n const error = Math.abs(currentLength - targetLength);\n\n if (error < tolerance) {\n break;\n }\n\n if (currentLength < targetLength) {\n tMin = t;\n } else {\n tMax = t;\n }\n\n t = (tMin + tMax) / 2;\n }\n\n return bezierEquation(c, t);\n}\n", "import {\n pointFrom,\n pointDistance,\n pointFromVector,\n pointsEqual,\n} from \"./point\";\nimport { PRECISION } from \"./utils\";\nimport {\n vector,\n vectorAdd,\n vectorDot,\n vectorFromPoint,\n vectorScale,\n} from \"./vector\";\n\nimport type {\n Ellipse,\n GlobalPoint,\n Line,\n LineSegment,\n LocalPoint,\n} from \"./types\";\n\n/**\n * Construct an Ellipse object from the parameters\n *\n * @param center The center of the ellipse\n * @param angle The slanting of the ellipse in radians\n * @param halfWidth Half of the width of a non-slanted version of the ellipse\n * @param halfHeight Half of the height of a non-slanted version of the ellipse\n * @returns The constructed Ellipse object\n */\nexport function ellipse<Point extends GlobalPoint | LocalPoint>(\n center: Point,\n halfWidth: number,\n halfHeight: number,\n): Ellipse<Point> {\n return {\n center,\n halfWidth,\n halfHeight,\n } as Ellipse<Point>;\n}\n\n/**\n * Determines if a point is inside or on the ellipse outline\n *\n * @param p The point to test\n * @param ellipse The ellipse to compare against\n * @returns TRUE if the point is inside or on the outline of the ellipse\n */\nexport const ellipseIncludesPoint = <Point extends GlobalPoint | LocalPoint>(\n p: Point,\n ellipse: Ellipse<Point>,\n) => {\n const { center, halfWidth, halfHeight } = ellipse;\n const normalizedX = (p[0] - center[0]) / halfWidth;\n const normalizedY = (p[1] - center[1]) / halfHeight;\n\n return normalizedX * normalizedX + normalizedY * normalizedY <= 1;\n};\n\n/**\n * Tests whether a point lies on the outline of the ellipse within a given\n * tolerance\n *\n * @param point The point to test\n * @param ellipse The ellipse to compare against\n * @param threshold The distance to consider a point close enough to be \"on\" the outline\n * @returns TRUE if the point is on the ellise outline\n */\nexport const ellipseTouchesPoint = <Point extends GlobalPoint | LocalPoint>(\n point: Point,\n ellipse: Ellipse<Point>,\n threshold = PRECISION,\n) => {\n return ellipseDistanceFromPoint(point, ellipse) <= threshold;\n};\n\n/**\n * Determine the shortest euclidean distance from a point to the\n * outline of the ellipse\n *\n * @param p The point to consider\n * @param ellipse The ellipse to calculate the distance to\n * @returns The eucledian distance\n */\nexport const ellipseDistanceFromPoint = <\n Point extends GlobalPoint | LocalPoint,\n>(\n p: Point,\n ellipse: Ellipse<Point>,\n): number => {\n const { halfWidth, halfHeight, center } = ellipse;\n const a = halfWidth;\n const b = halfHeight;\n const translatedPoint = vectorAdd(\n vectorFromPoint(p),\n vectorScale(vectorFromPoint(center), -1),\n );\n\n const px = Math.abs(translatedPoint[0]);\n const py = Math.abs(translatedPoint[1]);\n\n let tx = 0.707;\n let ty = 0.707;\n\n for (let i = 0; i < 3; i++) {\n const x = a * tx;\n const y = b * ty;\n\n const ex = ((a * a - b * b) * tx ** 3) / a;\n const ey = ((b * b - a * a) * ty ** 3) / b;\n\n const rx = x - ex;\n const ry = y - ey;\n\n const qx = px - ex;\n const qy = py - ey;\n\n const r = Math.hypot(ry, rx);\n const q = Math.hypot(qy, qx);\n\n tx = Math.min(1, Math.max(0, ((qx * r) / q + ex) / a));\n ty = Math.min(1, Math.max(0, ((qy * r) / q + ey) / b));\n const t = Math.hypot(ty, tx);\n tx /= t;\n ty /= t;\n }\n\n const [minX, minY] = [\n a * tx * Math.sign(translatedPoint[0]),\n b * ty * Math.sign(translatedPoint[1]),\n ];\n\n return pointDistance(pointFromVector(translatedPoint), pointFrom(minX, minY));\n};\n\n/**\n * Calculate a maximum of two intercept points for a line going throug an\n * ellipse.\n */\nexport function ellipseSegmentInterceptPoints<\n Point extends GlobalPoint | LocalPoint,\n>(e: Readonly<Ellipse<Point>>, s: Readonly<LineSegment<Point>>): Point[] {\n const rx = e.halfWidth;\n const ry = e.halfHeight;\n\n const dir = vectorFromPoint(s[1], s[0]);\n const diff = vector(s[0][0] - e.center[0], s[0][1] - e.center[1]);\n const mDir = vector(dir[0] / (rx * rx), dir[1] / (ry * ry));\n const mDiff = vector(diff[0] / (rx * rx), diff[1] / (ry * ry));\n\n const a = vectorDot(dir, mDir);\n const b = vectorDot(dir, mDiff);\n const c = vectorDot(diff, mDiff) - 1.0;\n const d = b * b - a * c;\n\n const intersections: Point[] = [];\n\n if (d > 0) {\n const t_a = (-b - Math.sqrt(d)) / a;\n const t_b = (-b + Math.sqrt(d)) / a;\n\n if (0 <= t_a && t_a <= 1) {\n intersections.push(\n pointFrom(\n s[0][0] + (s[1][0] - s[0][0]) * t_a,\n s[0][1] + (s[1][1] - s[0][1]) * t_a,\n ),\n );\n }\n\n if (0 <= t_b && t_b <= 1) {\n intersections.push(\n pointFrom(\n s[0][0] + (s[1][0] - s[0][0]) * t_b,\n s[0][1] + (s[1][1] - s[0][1]) * t_b,\n ),\n );\n }\n } else if (d === 0) {\n const t = -b / a;\n if (0 <= t && t <= 1) {\n intersections.push(\n pointFrom(\n s[0][0] + (s[1][0] - s[0][0]) * t,\n s[0][1] + (s[1][1] - s[0][1]) * t,\n ),\n );\n }\n }\n\n return intersections;\n}\n\nexport function ellipseLineIntersectionPoints<\n Point extends GlobalPoint | LocalPoint,\n>(\n { center, halfWidth, halfHeight }: Ellipse<Point>,\n [g, h]: Line<Point>,\n): Point[] {\n const [cx, cy] = center;\n const x1 = g[0] - cx;\n const y1 = g[1] - cy;\n const x2 = h[0] - cx;\n const y2 = h[1] - cy;\n const a =\n Math.pow(x2 - x1, 2) / Math.pow(halfWidth, 2) +\n Math.pow(y2 - y1, 2) / Math.pow(halfHeight, 2);\n const b =\n 2 *\n ((x1 * (x2 - x1)) / Math.pow(halfWidth, 2) +\n (y1 * (y2 - y1)) / Math.pow(halfHeight, 2));\n const c =\n Math.pow(x1, 2) / Math.pow(halfWidth, 2) +\n Math.pow(y1, 2) / Math.pow(halfHeight, 2) -\n 1;\n const t1 = (-b + Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a);\n const t2 = (-b - Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a);\n const candidates = [\n pointFrom<Point>(x1 + t1 * (x2 - x1) + cx, y1 + t1 * (y2 - y1) + cy),\n pointFrom<Point>(x1 + t2 * (x2 - x1) + cx, y1 + t2 * (y2 - y1) + cy),\n ].filter((p) => !isNaN(p[0]) && !isNaN(p[1]));\n\n if (candidates.length === 2 && pointsEqual(candidates[0], candidates[1])) {\n return [candidates[0]];\n }\n\n return candidates;\n}\n", "import { pointFrom } from \"./point\";\n\nimport type { GlobalPoint, Line, LocalPoint } from \"./types\";\n\n/**\n * Create a line from two points.\n *\n * @param points The two points lying on the line\n * @returns The line on which the points lie\n */\nexport function line<P extends GlobalPoint | LocalPoint>(a: P, b: P): Line<P> {\n return [a, b] as Line<P>;\n}\n\n/**\n * Determines the intersection point (unless the lines are parallel) of two\n * lines\n *\n * @param a\n * @param b\n * @returns\n */\nexport function linesIntersectAt<Point extends GlobalPoint | LocalPoint>(\n a: Line<Point>,\n b: Line<Point>,\n): Point | null {\n const A1 = a[1][1] - a[0][1];\n const B1 = a[0][0] - a[1][0];\n const A2 = b[1][1] - b[0][1];\n const B2 = b[0][0] - b[1][0];\n const D = A1 * B2 - A2 * B1;\n if (D !== 0) {\n const C1 = A1 * a[0][0] + B1 * a[0][1];\n const C2 = A2 * b[0][0] + B2 * b[0][1];\n return pointFrom<Point>((C1 * B2 - C2 * B1) / D, (A1 * C2 - A2 * C1) / D);\n }\n\n return null;\n}\n", "import { line, linesIntersectAt } from \"./line\";\nimport {\n isPoint,\n pointCenter,\n pointFromVector,\n pointRotateRads,\n} from \"./point\";\nimport { PRECISION } from \"./utils\";\nimport {\n vectorAdd,\n vectorCross,\n vectorFromPoint,\n vectorScale,\n vectorSubtract,\n} from \"./vector\";\n\nimport type { GlobalPoint, LineSegment, LocalPoint, Radians } from \"./types\";\n\n/**\n * Create a line segment from two points.\n *\n * @param points The two points delimiting the line segment on each end\n * @returns The line segment delineated by the points\n */\nexport function lineSegment<P extends GlobalPoint | LocalPoint>(\n a: P,\n b: P,\n): LineSegment<P> {\n return [a, b] as LineSegment<P>;\n}\n\n/**\n *\n * @param segment\n * @returns\n */\nexport const isLineSegment = <Point extends GlobalPoint | LocalPoint>(\n segment: unknown,\n): segment is LineSegment<Point> =>\n Array.isArray(segment) &&\n segment.length === 2 &&\n isPoint(segment[0]) &&\n isPoint(segment[0]);\n\n/**\n * Return the coordinates resulting from rotating the given line about an origin by an angle in radians\n * note that when the origin is not given, the midpoint of the given line is used as the origin.\n *\n * @param l\n * @param angle\n * @param origin\n * @returns\n */\nexport const lineSegmentRotate = <Point extends LocalPoint | GlobalPoint>(\n l: LineSegment<Point>,\n angle: Radians,\n origin?: Point,\n): LineSegment<Point> => {\n return lineSegment(\n pointRotateRads(l[0], origin || pointCenter(l[0], l[1]), angle),\n pointRotateRads(l[1], origin || pointCenter(l[0], l[1]), angle),\n );\n};\n\n/**\n * Calculates the point two line segments with a definite start and end point\n * intersect at.\n */\nexport const segmentsIntersectAt = <Point extends GlobalPoint | LocalPoint>(\n a: Readonly<LineSegment<Point>>,\n b: Readonly<LineSegment<Point>>,\n): Point | null => {\n const a0 = vectorFromPoint(a[0]);\n const a1 = vectorFromPoint(a[1]);\n const b0 = vectorFromPoint(b[0]);\n const b1 = vectorFromPoint(b[1]);\n const r = vectorSubtract(a1, a0);\n const s = vectorSubtract(b1, b0);\n const denominator = vectorCross(r, s);\n\n if (denominator === 0) {\n return null;\n }\n\n const i = vectorSubtract(vectorFromPoint(b[0]), vectorFromPoint(a[0]));\n const u = vectorCross(i, r) / denominator;\n const t = vectorCross(i, s) / denominator;\n\n if (u === 0) {\n return null;\n }\n\n const p = vectorAdd(a0, vectorScale(r, t));\n\n if (t >= 0 && t < 1 && u >= 0 && u < 1) {\n return pointFromVector<Point>(p);\n }\n\n return null;\n};\n\nexport const pointOnLineSegment = <Point extends LocalPoint | GlobalPoint>(\n point: Point,\n line: LineSegment<Point>,\n threshold = PRECISION,\n) => {\n const distance = distanceToLineSegment(point, line);\n\n if (distance === 0) {\n return true;\n }\n\n return distance < threshold;\n};\n\nexport const distanceToLineSegment = <Point extends LocalPoint | GlobalPoint>(\n point: Point,\n line: LineSegment<Point>,\n) => {\n const [x, y] = point;\n const [[x1, y1], [x2, y2]] = line;\n\n const A = x - x1;\n const B = y - y1;\n const C = x2 - x1;\n const D = y2 - y1;\n\n const dot = A * C + B * D;\n const len_sq = C * C + D * D;\n let param = -1;\n if (len_sq !== 0) {\n param = dot / len_sq;\n }\n\n let xx;\n let yy;\n\n if (param < 0) {\n xx = x1;\n yy = y1;\n } else if (param > 1) {\n xx = x2;\n yy = y2;\n } else {\n xx = x1 + param * C;\n yy = y1 + param * D;\n }\n\n const dx = x - xx;\n const dy = y - yy;\n return Math.sqrt(dx * dx + dy * dy);\n};\n\n/**\n * Returns the intersection point of a segment and a line\n *\n * @param l\n * @param s\n * @returns\n */\nexport function lineSegmentIntersectionPoints<\n Point extends GlobalPoint | LocalPoint,\n>(\n l: LineSegment<Point>,\n s: LineSegment<Point>,\n threshold?: number,\n): Point | null {\n const candidate = linesIntersectAt(line(l[0], l[1]), line(s[0], s[1]));\n\n if (\n !candidate ||\n !pointOnLineSegment(candidate, s, threshold) ||\n !pointOnLineSegment(candidate, l, threshold)\n ) {\n return null;\n }\n\n return candidate;\n}\n\nexport function lineSegmentsDistance<Point extends GlobalPoint | LocalPoint>(\n s1: LineSegment<Point>,\n s2: LineSegment<Point>,\n): number {\n if (lineSegmentIntersectionPoints(s1, s2)) {\n return 0;\n }\n\n return Math.min(\n distanceToLineSegment(s1[0], s2),\n distanceToLineSegment(s1[1], s2),\n distanceToLineSegment(s2[0], s1),\n distanceToLineSegment(s2[1], s1),\n );\n}\n", "import { pointsEqual } from \"./point\";\nimport { lineSegment, pointOnLineSegment } from \"./segment\";\nimport { PRECISION } from \"./utils\";\n\nimport type { GlobalPoint, LocalPoint, Polygon } from \"./types\";\n\nexport function polygon<Point extends GlobalPoint | LocalPoint>(\n ...points: Point[]\n) {\n return polygonClose(points) as Polygon<Point>;\n}\n\nexport function polygonFromPoints<Point extends GlobalPoint | LocalPoint>(\n points: Point[],\n) {\n return polygonClose(points) as Polygon<Point>;\n}\n\nexport const polygonIncludesPoint = <Point extends LocalPoint | GlobalPoint>(\n point: Point,\n polygon: Polygon<Point>,\n) => {\n const x = point[0];\n const y = point[1];\n let inside = false;\n\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const xi = polygon[i][0];\n const yi = polygon[i][1];\n const xj = polygon[j][0];\n const yj = polygon[j][1];\n\n if (\n ((yi > y && yj <= y) || (yi <= y && yj > y)) &&\n x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n ) {\n inside = !inside;\n }\n }\n\n return inside;\n};\n\nexport const polygonIncludesPointNonZero = <Point extends [number, number]>(\n point: Point,\n polygon: Point[],\n): boolean => {\n const [x, y] = point;\n let windingNumber = 0;\n\n for (let i = 0; i < polygon.length; i++) {\n const j = (i + 1) % polygon.length;\n const [xi, yi] = polygon[i];\n const [xj, yj] = polygon[j];\n\n if (yi <= y) {\n if (yj > y) {\n if ((xj - xi) * (y - yi) - (x - xi) * (yj - yi) > 0) {\n windingNumber++;\n }\n }\n } else if (yj <= y) {\n if ((xj - xi) * (y - yi) - (x - xi) * (yj - yi) < 0) {\n windingNumber--;\n }\n }\n }\n\n return windingNumber !== 0;\n};\n\nexport const pointOnPolygon = <Point extends LocalPoint | GlobalPoint>(\n p: Point,\n poly: Polygon<Point>,\n threshold = PRECISION,\n) => {\n let on = false;\n\n for (let i = 0, l = poly.length - 1; i < l; i++) {\n if (pointOnLineSegment(p, lineSegment(poly[i], poly[i + 1]), threshold)) {\n on = true;\n break;\n }\n }\n\n return on;\n};\n\nfunction polygonClose<Point extends LocalPoint | GlobalPoint>(\n polygon: Point[],\n) {\n return polygonIsClosed(polygon)\n ? polygon\n : ([...polygon, polygon[0]] as Polygon<Point>);\n}\n\nfunction polygonIsClosed<Point extends LocalPoint | GlobalPoint>(\n polygon: Point[],\n) {\n return pointsEqual(polygon[0], polygon[polygon.length - 1]);\n}\n", "import { toBrandedType } from \"@excalidraw/common\";\n\nimport type { InclusiveRange } from \"./types\";\n\n/**\n * Create an inclusive range from the two numbers provided.\n *\n * @param start Start of the range\n * @param end End of the range\n * @returns\n */\nexport function rangeInclusive(start: number, end: number): InclusiveRange {\n return toBrandedType<InclusiveRange>([start, end]);\n}\n\n/**\n * Turn a number pair into an inclusive range.\n *\n * @param pair The number pair to convert to an inclusive range\n * @returns The new inclusive range\n */\nexport function rangeInclusiveFromPair(pair: [start: number, end: number]) {\n return toBrandedType<InclusiveRange>(pair);\n}\n\n/**\n * Given two ranges, return if the two ranges overlap with each other e.g.\n * [1, 3] overlaps with [2, 4] while [1, 3] does not overlap with [4, 5].\n *\n * @param param0 One of the ranges to compare\n * @param param1 The other range to compare against\n * @returns TRUE if the ranges overlap\n */\nexport const rangesOverlap = (\n [a0, a1]: InclusiveRange,\n [b0, b1]: InclusiveRange,\n): boolean => {\n if (a0 <= b0) {\n return a1 >= b0;\n }\n\n if (a0 >= b0) {\n return b1 >= a0;\n }\n\n return false;\n};\n\n/**\n * Given two ranges,return ther intersection of the two ranges if any e.g. the\n * intersection of [1, 3] and [2, 4] is [2, 3].\n *\n * @param param0 The first range to compare\n * @param param1 The second range to compare\n * @returns The inclusive range intersection or NULL if no intersection\n */\nexport const rangeIntersection = (\n [a0, a1]: InclusiveRange,\n [b0, b1]: InclusiveRange,\n): InclusiveRange | null => {\n const rangeStart = Math.max(a0, b0);\n const rangeEnd = Math.min(a1, b1);\n\n if (rangeStart <= rangeEnd) {\n return toBrandedType<InclusiveRange>([rangeStart, rangeEnd]);\n }\n\n return null;\n};\n\n/**\n * Determine if a value is inside a range.\n *\n * @param value The value to check\n * @param range The range\n * @returns\n */\nexport const rangeIncludesValue = (\n value: number,\n [min, max]: InclusiveRange,\n): boolean => {\n return value >= min && value <= max;\n};\n", "import { pointFrom } from \"./point\";\nimport { lineSegment, lineSegmentIntersectionPoints } from \"./segment\";\n\nimport type { GlobalPoint, LineSegment, LocalPoint, Rectangle } from \"./types\";\n\nexport function rectangle<P extends GlobalPoint | LocalPoint>(\n topLeft: P,\n bottomRight: P,\n): Rectangle<P> {\n return [topLeft, bottomRight] as Rectangle<P>;\n}\n\nexport function rectangleFromNumberSequence<\n Point extends LocalPoint | GlobalPoint,\n>(minX: number, minY: number, maxX: number, maxY: number) {\n return rectangle(pointFrom<Point>(minX, minY), pointFrom<Point>(maxX, maxY));\n}\n\nexport function rectangleIntersectLineSegment<\n Point extends LocalPoint | GlobalPoint,\n>(r: Rectangle<Point>, l: LineSegment<Point>): Point[] {\n return [\n lineSegment(r[0], pointFrom(r[1][0], r[0][1])),\n lineSegment(pointFrom(r[1][0], r[0][1]), r[1]),\n lineSegment(r[1], pointFrom(r[0][0], r[1][1])),\n lineSegment(pointFrom(r[0][0], r[1][1]), r[0]),\n ]\n .map((s) => lineSegmentIntersectionPoints(l, s))\n .filter((i): i is Point => !!i);\n}\n\nexport function rectangleIntersectRectangle<\n Point extends LocalPoint | GlobalPoint,\n>(rectangle1: Rectangle<Point>, rectangle2: Rectangle<Point>): boolean {\n const [[minX1, minY1], [maxX1, maxY1]] = rectangle1;\n const [[minX2, minY2], [maxX2, maxY2]] = rectangle2;\n\n return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;\n}\n", "import type { GlobalPoint, LocalPoint, Triangle } from \"./types\";\n\n// Types\n\n/**\n * Tests if a point lies inside a triangle. This function\n * will return FALSE if the point lies exactly on the sides\n * of the triangle.\n *\n * @param triangle The triangle to test the point for\n * @param p The point to test whether is in the triangle\n * @returns TRUE if the point is inside of the triangle\n */\nexport function triangleIncludesPoint<P extends GlobalPoint | LocalPoint>(\n [a, b, c]: Triangle<P>,\n p: P,\n): boolean {\n const triangleSign = (p1: P, p2: P, p3: P) =>\n (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1]);\n const d1 = triangleSign(p, a, b);\n const d2 = triangleSign(p, b, c);\n const d3 = triangleSign(p, c, a);\n\n const has_neg = d1 < 0 || d2 < 0 || d3 < 0;\n const has_pos = d1 > 0 || d2 > 0 || d3 > 0;\n\n return !(has_neg && has_pos);\n}\n", "import type {\n ExcalidrawElement,\n FontFamilyValues,\n} from \"@excalidraw/element/types\";\nimport type { AppProps, AppState } from \"@excalidraw/excalidraw/types\";\n\nimport { COLOR_PALETTE } from \"./colors\";\n\nexport const supportsResizeObserver =\n typeof window !== \"undefined\" && \"ResizeObserver\" in window;\n\nexport const APP_NAME = \"Excalidraw\";\n\n// distance when creating text before it's considered `autoResize: false`\n// we're using higher threshold so that clicks that end up being drags\n// don't unintentionally create text elements that are wrapped to a few chars\n// (happens a lot with fast clicks with the text tool)\nexport const TEXT_AUTOWRAP_THRESHOLD = 36; // px\nexport const DRAGGING_THRESHOLD = 10; // px\nexport const MINIMUM_ARROW_SIZE = 20; // px\nexport const LINE_CONFIRM_THRESHOLD = 8; // px\nexport const ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;\nexport const ELEMENT_TRANSLATE_AMOUNT = 1;\nexport const TEXT_TO_CENTER_SNAP_THRESHOLD = 30;\nexport const SHIFT_LOCKING_ANGLE = Math.PI / 12;\nexport const DEFAULT_LASER_COLOR = \"red\";\nexport const CURSOR_TYPE = {\n TEXT: \"text\",\n CROSSHAIR: \"crosshair\",\n GRABBING: \"grabbing\",\n GRAB: \"grab\",\n POINTER: \"pointer\",\n MOVE: \"move\",\n AUTO: \"\",\n};\nexport const POINTER_BUTTON = {\n MAIN: 0,\n WHEEL: 1,\n SECONDARY: 2,\n TOUCH: -1,\n ERASER: 5,\n} as const;\n\nexport const POINTER_EVENTS = {\n enabled: \"all\",\n disabled: \"none\",\n // asserted as any so it can be freely assigned to React Element\n // \"pointerEnvets\" CSS prop\n inheritFromUI: \"var(--ui-pointerEvents)\" as any,\n} as const;\n\nexport enum EVENT {\n COPY = \"copy\",\n PASTE = \"paste\",\n CUT = \"cut\",\n KEYDOWN = \"keydown\",\n KEYUP = \"keyup\",\n MOUSE_MOVE = \"mousemove\",\n RESIZE = \"resize\",\n UNLOAD = \"unload\",\n FOCUS = \"focus\",\n BLUR = \"blur\",\n DRAG_OVER = \"dragover\",\n DROP = \"drop\",\n GESTURE_END = \"gestureend\",\n BEFORE_UNLOAD = \"beforeunload\",\n GESTURE_START = \"gesturestart\",\n GESTURE_CHANGE = \"gesturechange\",\n POINTER_MOVE = \"pointermove\",\n POINTER_DOWN = \"pointerdown\",\n POINTER_UP = \"pointerup\",\n STATE_CHANGE = \"statechange\",\n WHEEL = \"wheel\",\n TOUCH_START = \"touchstart\",\n TOUCH_END = \"touchend\",\n HASHCHANGE = \"hashchange\",\n VISIBILITY_CHANGE = \"visibilitychange\",\n SCROLL = \"scroll\",\n // custom events\n EXCALIDRAW_LINK = \"excalidraw-link\",\n MENU_ITEM_SELECT = \"menu.itemSelect\",\n MESSAGE = \"message\",\n FULLSCREENCHANGE = \"fullscreenchange\",\n}\n\nexport const YOUTUBE_STATES = {\n UNSTARTED: -1,\n ENDED: 0,\n PLAYING: 1,\n PAUSED: 2,\n BUFFERING: 3,\n CUED: 5,\n} as const;\n\nexport const ENV = {\n TEST: \"test\",\n DEVELOPMENT: \"development\",\n PRODUCTION: \"production\",\n};\n\nexport const CLASSES = {\n SIDEBAR: \"sidebar\",\n SHAPE_ACTIONS_MENU: \"App-menu__left\",\n ZOOM_ACTIONS: \"zoom-actions\",\n SEARCH_MENU_INPUT_WRAPPER: \"layer-ui__search-inputWrapper\",\n CONVERT_ELEMENT_TYPE_POPUP: \"ConvertElementTypePopup\",\n SHAPE_ACTIONS_THEME_SCOPE: \"shape-actions-theme-scope\",\n FRAME_NAME: \"frame-name\",\n};\n\nexport const FONT_SIZES = {\n sm: 16,\n md: 20,\n lg: 28,\n xl: 36,\n} as const;\n\nexport const CJK_HAND_DRAWN_FALLBACK_FONT = \"Xiaolai\";\nexport const WINDOWS_EMOJI_FALLBACK_FONT = \"Segoe UI Emoji\";\n\n/**\n * // TODO: shouldn't be really `const`, likely neither have integers as values, due to value for the custom fonts, which should likely be some hash.\n *\n * Let's think this through and consider:\n * - https://developer.mozilla.org/en-US/docs/Web/CSS/generic-family\n * - https://drafts.csswg.org/css-fonts-4/#font-family-prop\n * - https://learn.microsoft.com/en-us/typography/opentype/spec/ibmfc\n */\nexport const FONT_FAMILY = {\n Virgil: 1,\n Helvetica: 2,\n Cascadia: 3,\n // leave 4 unused as it was historically used for Assistant (which we don't use anymore) or custom font (Obsidian)\n Excalifont: 5,\n Nunito: 6,\n \"Lilita One\": 7,\n \"Comic Shanns\": 8,\n \"Liberation Sans\": 9,\n Assistant: 10,\n};\n\n// Segoe UI Emoji fails to properly fallback for some glyphs: \u221E, \u222B, \u2260\n// so we need to have generic font fallback before it\nexport const SANS_SERIF_GENERIC_FONT = \"sans-serif\";\nexport const MONOSPACE_GENERIC_FONT = \"monospace\";\n\nexport const FONT_FAMILY_GENERIC_FALLBACKS = {\n [SANS_SERIF_GENERIC_FONT]: 998,\n [MONOSPACE_GENERIC_FONT]: 999,\n};\n\nexport const FONT_FAMILY_FALLBACKS = {\n [CJK_HAND_DRAWN_FALLBACK_FONT]: 100,\n ...FONT_FAMILY_GENERIC_FALLBACKS,\n [WINDOWS_EMOJI_FALLBACK_FONT]: 1000,\n};\n\nexport function getGenericFontFamilyFallback(\n fontFamily: number,\n): keyof typeof FONT_FAMILY_GENERIC_FALLBACKS {\n switch (fontFamily) {\n case FONT_FAMILY.Cascadia:\n case FONT_FAMILY[\"Comic Shanns\"]:\n return MONOSPACE_GENERIC_FONT;\n\n default:\n return SANS_SERIF_GENERIC_FONT;\n }\n}\n\nexport const getFontFamilyFallbacks = (\n fontFamily: number,\n): Array<keyof typeof FONT_FAMILY_FALLBACKS> => {\n const genericFallbackFont = getGenericFontFamilyFallback(fontFamily);\n\n switch (fontFamily) {\n case FONT_FAMILY.Excalifont:\n return [\n CJK_HAND_DRAWN_FALLBACK_FONT,\n genericFallbackFont,\n WINDOWS_EMOJI_FALLBACK_FONT,\n ];\n default:\n return [genericFallbackFont, WINDOWS_EMOJI_FALLBACK_FONT];\n }\n};\n\nexport const THEME = {\n LIGHT: \"light\",\n DARK: \"dark\",\n} as const;\n\nexport const FRAME_STYLE = {\n strokeColor: \"#bbb\" as ExcalidrawElement[\"strokeColor\"],\n strokeWidth: 2 as ExcalidrawElement[\"strokeWidth\"],\n strokeStyle: \"solid\" as ExcalidrawElement[\"strokeStyle\"],\n fillStyle: \"solid\" as ExcalidrawElement[\"fillStyle\"],\n roughness: 0 as ExcalidrawElement[\"roughness\"],\n roundness: null as ExcalidrawElement[\"roundness\"],\n backgroundColor: \"transparent\" as ExcalidrawElement[\"backgroundColor\"],\n radius: 8,\n nameOffsetY: 3,\n nameColorLightTheme: \"#999999\",\n nameColorDarkTheme: \"#7a7a7a\",\n nameFontSize: 14,\n nameLineHeight: 1.25,\n};\n\nexport const MIN_FONT_SIZE = 1;\nexport const DEFAULT_FONT_SIZE = 20;\nexport const DEFAULT_FONT_FAMILY: FontFamilyValues = FONT_FAMILY.Excalifont;\nexport const DEFAULT_TEXT_ALIGN = \"left\";\nexport const DEFAULT_VERTICAL_ALIGN = \"top\";\nexport const DEFAULT_VERSION = \"{version}\";\nexport const DEFAULT_TRANSFORM_HANDLE_SPACING = 2;\n\nexport const SIDE_RESIZING_THRESHOLD = 2 * DEFAULT_TRANSFORM_HANDLE_SPACING;\n// a small epsilon to make side resizing always take precedence\n// (avoids an increase in renders and changes to tests)\nexport const EPSILON = 0.00001;\nexport const DEFAULT_COLLISION_THRESHOLD =\n 2 * SIDE_RESIZING_THRESHOLD - EPSILON;\n\nexport const COLOR_WHITE = \"#ffffff\";\nexport const COLOR_CHARCOAL_BLACK = \"#1e1e1e\";\n// keep this in sync with CSS\nexport const COLOR_VOICE_CALL = \"#a2f1a6\";\n\nexport const CANVAS_ONLY_ACTIONS = [\"selectAll\"];\n\nexport const DEFAULT_GRID_SIZE = 20;\nexport const DEFAULT_GRID_STEP = 5;\n\nexport const IMAGE_MIME_TYPES = {\n svg: \"image/svg+xml\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n bmp: \"image/bmp\",\n ico: \"image/x-icon\",\n avif: \"image/avif\",\n jfif: \"image/jfif\",\n} as const;\n\nexport const STRING_MIME_TYPES = {\n text: \"text/plain\",\n html: \"text/html\",\n json: \"application/json\",\n // excalidraw data\n excalidraw: \"application/vnd.excalidraw+json\",\n // LEGACY: fully-qualified library JSON data\n excalidrawlib: \"application/vnd.excalidrawlib+json\",\n // list of excalidraw library item ids\n excalidrawlibIds: \"application/vnd.excalidrawlib.ids+json\",\n} as const;\n\nexport const MIME_TYPES = {\n ...STRING_MIME_TYPES,\n // image-encoded excalidraw data\n \"excalidraw.svg\": \"image/svg+xml\",\n \"excalidraw.png\": \"image/png\",\n // binary\n binary: \"application/octet-stream\",\n // image\n ...IMAGE_MIME_TYPES,\n} as const;\n\nexport const ALLOWED_PASTE_MIME_TYPES = [\n MIME_TYPES.text,\n MIME_TYPES.html,\n ...Object.values(IMAGE_MIME_TYPES),\n] as const;\n\nexport const EXPORT_IMAGE_TYPES = {\n png: \"png\",\n svg: \"svg\",\n clipboard: \"clipboard\",\n} as const;\n\nexport const EXPORT_DATA_TYPES = {\n excalidraw: \"excalidraw\",\n excalidrawClipboard: \"excalidraw/clipboard\",\n excalidrawLibrary: \"excalidrawlib\",\n excalidrawClipboardWithAPI: \"excalidraw-api/clipboard\",\n} as const;\n\nexport const getExportSource = () =>\n window.EXCALIDRAW_EXPORT_SOURCE || window.location.origin;\n\n// time in milliseconds\nexport const IMAGE_RENDER_TIMEOUT = 500;\nexport const TAP_TWICE_TIMEOUT = 300;\nexport const TOUCH_CTX_MENU_TIMEOUT = 500;\nexport const TITLE_TIMEOUT = 10000;\nexport const VERSION_TIMEOUT = 30000;\nexport const SCROLL_TIMEOUT = 100;\nexport const ZOOM_STEP = 0.1;\nexport const MIN_ZOOM = 0.1;\nexport const MAX_ZOOM = 30;\nexport const HYPERLINK_TOOLTIP_DELAY = 300;\n\n// Report a user inactive after IDLE_THRESHOLD milliseconds\nexport const IDLE_THRESHOLD = 60_000;\n// Report a user active each ACTIVE_THRESHOLD milliseconds\nexport const ACTIVE_THRESHOLD = 3_000;\n\nexport const URL_QUERY_KEYS = {\n addLibrary: \"addLibrary\",\n} as const;\n\nexport const URL_HASH_KEYS = {\n addLibrary: \"addLibrary\",\n} as const;\n\nexport const DEFAULT_UI_OPTIONS: AppProps[\"UIOptions\"] = {\n canvasActions: {\n changeViewBackgroundColor: true,\n clearCanvas: true,\n export: { saveFileToDisk: true },\n loadScene: true,\n saveToActiveFile: true,\n toggleTheme: null,\n saveAsImage: true,\n },\n tools: {\n image: true,\n },\n toolBar: {\n lockEnabled: true,\n moreToolsEnabled: true,\n hintViewerEnabled: true,\n },\n topLeftMenuEnabled: true,\n libraryEnabled: true,\n footer: {\n helpEnabled: true,\n },\n fontPicker: {\n familyChangeEnabled: true,\n },\n shapeControl: {\n sloppinessChangeEnabled: true,\n },\n viewModeControlEnabled: true,\n hideAnnotationsControlEnabled: true,\n undoRedoPosition: \"footer\",\n swapTopMenuAndFooter: false,\n};\n\nexport const MAX_DECIMALS_FOR_SVG_EXPORT = 2;\n\nexport const EXPORT_SCALES = [1, 2, 3];\nexport const DEFAULT_EXPORT_PADDING = 10; // px\n\nexport const DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT = 1440;\n\nexport const MAX_ALLOWED_FILE_BYTES = 4 * 1024 * 1024;\n\nexport const SVG_NS = \"http://www.w3.org/2000/svg\";\nexport const SVG_DOCUMENT_PREAMBLE = `<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n`;\n\nexport const ENCRYPTION_KEY_BITS = 128;\n\nexport const VERSIONS = {\n excalidraw: 2,\n excalidrawLibrary: 2,\n} as const;\n\nexport const BOUND_TEXT_PADDING = 5;\nexport const ARROW_LABEL_WIDTH_FRACTION = 0.7;\nexport const ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO = 11;\n\nexport const VERTICAL_ALIGN = {\n TOP: \"top\",\n MIDDLE: \"middle\",\n BOTTOM: \"bottom\",\n};\n\nexport const TEXT_ALIGN = {\n LEFT: \"left\",\n CENTER: \"center\",\n RIGHT: \"right\",\n};\n\nexport const ELEMENT_READY_TO_ERASE_OPACITY = 20;\n\n// Radius represented as 25% of element's largest side (width/height).\n// Used for LEGACY and PROPORTIONAL_RADIUS algorithms, or when the element is\n// below the cutoff size.\nexport const DEFAULT_PROPORTIONAL_RADIUS = 0.25;\n// Fixed radius for the ADAPTIVE_RADIUS algorithm. In pixels.\nexport const DEFAULT_ADAPTIVE_RADIUS = 32;\n// roundness type (algorithm)\nexport const ROUNDNESS = {\n // Used for legacy rounding (rectangles), which currently works the same\n // as PROPORTIONAL_RADIUS, but we need to differentiate for UI purposes and\n // forwards-compat.\n LEGACY: 1,\n\n // Used for linear elements & diamonds\n PROPORTIONAL_RADIUS: 2,\n\n // Current default algorithm for rectangles, using fixed pixel radius.\n // It's working similarly to a regular border-radius, but attemps to make\n // radius visually similar across differnt element sizes, especially\n // very large and very small elements.\n //\n // NOTE right now we don't allow configuration and use a constant radius\n // (see DEFAULT_ADAPTIVE_RADIUS constant)\n ADAPTIVE_RADIUS: 3,\n} as const;\n\nexport const ROUGHNESS = {\n architect: 0,\n artist: 1,\n cartoonist: 2,\n} as const;\n\nexport const STROKE_WIDTH = {\n thin: 1,\n bold: 2,\n extraBold: 4,\n} as const;\n\nexport const DEFAULT_ELEMENT_PROPS: {\n strokeColor: ExcalidrawElement[\"strokeColor\"];\n backgroundColor: ExcalidrawElement[\"backgroundColor\"];\n fillStyle: ExcalidrawElement[\"fillStyle\"];\n strokeWidth: ExcalidrawElement[\"strokeWidth\"];\n strokeStyle: ExcalidrawElement[\"strokeStyle\"];\n roughness: ExcalidrawElement[\"roughness\"];\n opacity: ExcalidrawElement[\"opacity\"];\n locked: ExcalidrawElement[\"locked\"];\n} = {\n strokeColor: COLOR_PALETTE.black,\n backgroundColor: COLOR_PALETTE.transparent,\n fillStyle: \"solid\",\n strokeWidth: 2,\n strokeStyle: \"solid\",\n roughness: ROUGHNESS.artist,\n opacity: 100,\n locked: false,\n};\n\nexport const LIBRARY_SIDEBAR_TAB = \"library\";\nexport const CANVAS_SEARCH_TAB = \"search\";\n\nexport const DEFAULT_SIDEBAR = {\n name: \"default\",\n defaultTab: LIBRARY_SIDEBAR_TAB,\n} as const;\n\nexport const LIBRARY_DISABLED_TYPES = new Set([\n \"iframe\",\n \"embeddable\",\n \"image\",\n] as const);\n\n// use these constants to easily identify reference sites\nexport const TOOL_TYPE = {\n selection: \"selection\",\n lasso: \"lasso\",\n rectangle: \"rectangle\",\n diamond: \"diamond\",\n ellipse: \"ellipse\",\n arrow: \"arrow\",\n line: \"line\",\n freedraw: \"freedraw\",\n text: \"text\",\n image: \"image\",\n eraser: \"eraser\",\n hand: \"hand\",\n frame: \"frame\",\n magicframe: \"magicframe\",\n embeddable: \"embeddable\",\n laser: \"laser\",\n} as const;\n\nexport const EDITOR_LS_KEYS = {\n OAI_API_KEY: \"excalidraw-oai-api-key\",\n // legacy naming (non)scheme\n MERMAID_TO_EXCALIDRAW: \"mermaid-to-excalidraw\",\n PUBLISH_LIBRARY: \"publish-library-data\",\n} as const;\n\n/**\n * not translated as this is used only in public, stateless API as default value\n * where filename is optional and we can't retrieve name from app state\n */\nexport const DEFAULT_FILENAME = \"Untitled\";\n\nexport const STATS_PANELS = { generalStats: 1, elementProperties: 2 } as const;\n\nexport const MIN_WIDTH_OR_HEIGHT = 1;\n\nexport const ARROW_TYPE: { [T in AppState[\"currentItemArrowType\"]]: T } = {\n sharp: \"sharp\",\n round: \"round\",\n elbow: \"elbow\",\n};\n\nexport const DEFAULT_REDUCED_GLOBAL_ALPHA = 0.3;\nexport const ELEMENT_LINK_KEY = \"element\";\n\n/** used in tests */\nexport const ORIG_ID = Symbol.for(\"__test__originalId__\");\n\nexport enum UserIdleState {\n ACTIVE = \"active\",\n AWAY = \"away\",\n IDLE = \"idle\",\n}\n\n/**\n * distance at which we merge points instead of adding a new merge-point\n * when converting a line to a polygon (merge currently means overlaping\n * the start and end points)\n */\nexport const LINE_POLYGON_POINT_MERGE_DISTANCE = 20;\n\nexport const DOUBLE_TAP_POSITION_THRESHOLD = 35;\n\nexport const BIND_MODE_TIMEOUT = 700; // ms\n\n// glass background for mobile action buttons\nexport const MOBILE_ACTION_BUTTON_BG = {\n background: \"var(--mobile-action-button-bg)\",\n} as const;\n", "import type {\n ExcalidrawTextElement,\n FontFamilyValues,\n} from \"@excalidraw/element/types\";\n\nimport { FONT_FAMILY, FONT_FAMILY_FALLBACKS } from \"./constants\";\n\n/**\n * Encapsulates font metrics with additional font metadata.\n * */\nexport interface FontMetadata {\n /** for head & hhea metrics read the woff2 with https://fontdrop.info/ */\n metrics: {\n /** head.unitsPerEm metric */\n unitsPerEm: 1000 | 1024 | 2048;\n /** hhea.ascender metric */\n ascender: number;\n /** hhea.descender metric */\n descender: number;\n /** harcoded unitless line-height, https://github.com/excalidraw/excalidraw/pull/6360#issuecomment-1477635971 */\n lineHeight: number;\n };\n /** flag to indicate a deprecated font */\n deprecated?: true;\n /**\n * whether this is a font that users can use (= shown in font picker)\n */\n private?: true;\n /** flag to indiccate a local-only font */\n local?: true;\n /** flag to indicate a fallback font */\n fallback?: true;\n}\n\nexport const FONT_METADATA: Record<number, FontMetadata> = {\n [FONT_FAMILY.Excalifont]: {\n metrics: {\n unitsPerEm: 1000,\n ascender: 886,\n descender: -374,\n lineHeight: 1.25,\n },\n },\n [FONT_FAMILY.Nunito]: {\n metrics: {\n unitsPerEm: 1000,\n ascender: 1011,\n descender: -353,\n lineHeight: 1.25,\n },\n },\n [FONT_FAMILY[\"Lilita One\"]]: {\n metrics: {\n unitsPerEm: 1000,\n ascender: 923,\n descender: -220,\n lineHeight: 1.15,\n },\n },\n [FONT_FAMILY[\"Comic Shanns\"]]: {\n metrics: {\n unitsPerEm: 1000,\n ascender: 750,\n descender: -250,\n lineHeight: 1.25,\n },\n },\n [FONT_FAMILY.Virgil]: {\n metrics: {\n unitsPerEm: 1000,\n ascender: 886,\n descender: -374,\n lineHeight: 1.25,\n },\n deprecated: true,\n },\n [FONT_FAMILY.Helvetica]: {\n metrics: {\n unitsPerEm: 2048,\n ascender: 1577,\n descender: -471,\n lineHeight: 1.15,\n },\n deprecated: true,\n local: true,\n },\n [FONT_FAMILY.Cascadia]: {\n metrics: {\n unitsPerEm: 2048,\n ascender: 1900,\n descender: -480,\n lineHeight: 1.2,\n },\n deprecated: true,\n },\n [FONT_FAMILY[\"Liberation Sans\"]]: {\n metrics: {\n unitsPerEm: 2048,\n ascender: 1854,\n descender: -434,\n lineHeight: 1.15,\n },\n private: true,\n },\n [FONT_FAMILY.Assistant]: {\n metrics: {\n unitsPerEm: 2048,\n ascender: 1021,\n descender: -287,\n lineHeight: 1.25,\n },\n private: true,\n },\n [FONT_FAMILY_FALLBACKS.Xiaolai]: {\n metrics: {\n unitsPerEm: 1000,\n ascender: 880,\n descender: -144,\n lineHeight: 1.25,\n },\n fallback: true,\n },\n [FONT_FAMILY_FALLBACKS[\"Segoe UI Emoji\"]]: {\n metrics: {\n // reusing Excalifont metrics\n unitsPerEm: 1000,\n ascender: 886,\n descender: -374,\n lineHeight: 1.25,\n },\n local: true,\n fallback: true,\n },\n};\n\n/** Unicode ranges defined by google fonts */\nexport const GOOGLE_FONTS_RANGES = {\n LATIN:\n \"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD\",\n LATIN_EXT:\n \"U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF\",\n CYRILIC_EXT:\n \"U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F\",\n CYRILIC: \"U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116\",\n VIETNAMESE:\n \"U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB\",\n};\n\n/** local protocol to skip the local font from registering or inlining */\nexport const LOCAL_FONT_PROTOCOL = \"local:\";\n\n/**\n * Calculates vertical offset for a text with alphabetic baseline.\n */\nexport const getVerticalOffset = (\n fontFamily: ExcalidrawTextElement[\"fontFamily\"],\n fontSize: ExcalidrawTextElement[\"fontSize\"],\n lineHeightPx: number,\n) => {\n const { unitsPerEm, ascender, descender } =\n FONT_METADATA[fontFamily]?.metrics ||\n FONT_METADATA[FONT_FAMILY.Excalifont].metrics;\n\n const fontSizeEm = fontSize / unitsPerEm;\n const lineGap =\n (lineHeightPx - fontSizeEm * ascender + fontSizeEm * descender) / 2;\n\n const verticalOffset = fontSizeEm * ascender + lineGap;\n return verticalOffset;\n};\n\n/**\n * Gets line height for a selected family.\n */\nexport const getLineHeight = (fontFamily: FontFamilyValues) => {\n const { lineHeight } =\n FONT_METADATA[fontFamily]?.metrics ||\n FONT_METADATA[FONT_FAMILY.Excalifont].metrics;\n\n return lineHeight as ExcalidrawTextElement[\"lineHeight\"];\n};\n", "import { promiseTry, resolvablePromise } from \".\";\n\nimport type { ResolvablePromise } from \".\";\n\nimport type { MaybePromise } from \"./utility-types\";\n\ntype Job<T, TArgs extends unknown[]> = (...args: TArgs) => MaybePromise<T>;\n\ntype QueueJob<T, TArgs extends unknown[]> = {\n jobFactory: Job<T, TArgs>;\n promise: ResolvablePromise<T>;\n args: TArgs;\n};\n\nexport class Queue {\n private jobs: QueueJob<any, any[]>[] = [];\n private running = false;\n\n private tick() {\n if (this.running) {\n return;\n }\n const job = this.jobs.shift();\n if (job) {\n this.running = true;\n job.promise.resolve(\n promiseTry(job.jobFactory, ...job.args).finally(() => {\n this.running = false;\n this.tick();\n }),\n );\n } else {\n this.running = false;\n }\n }\n\n push<TValue, TArgs extends unknown[]>(\n jobFactory: Job<TValue, TArgs>,\n ...args: TArgs\n ): Promise<TValue> {\n const promise = resolvablePromise<TValue>();\n this.jobs.push({ jobFactory, promise, args });\n\n this.tick();\n\n return promise;\n }\n}\n", "export type StylesPanelMode = \"compact\" | \"full\" | \"mobile\";\n\nexport type EditorInterface = Readonly<{\n formFactor: \"phone\" | \"tablet\" | \"desktop\";\n desktopUIMode: \"compact\" | \"full\";\n userAgent: Readonly<{\n isMobileDevice: boolean;\n platform: \"ios\" | \"android\" | \"other\" | \"unknown\";\n }>;\n isTouchScreen: boolean;\n canFitSidebar: boolean;\n isLandscape: boolean;\n}>;\n\n// storage key\nconst DESKTOP_UI_MODE_STORAGE_KEY = \"excalidraw.desktopUIMode\";\n\n// breakpoints\n// mobile: up to 699px\nexport const MQ_MAX_MOBILE = 599;\n\nexport const MQ_MAX_WIDTH_LANDSCAPE = 1000;\nexport const MQ_MAX_HEIGHT_LANDSCAPE = 500;\n\n// tablets\nexport const MQ_MIN_TABLET = MQ_MAX_MOBILE + 1; // lower bound (excludes phones)\nexport const MQ_MAX_TABLET = 1400; // upper bound (excludes laptops/desktops)\n\n// desktop/laptop\nexport const MQ_MIN_WIDTH_DESKTOP = 1440;\n\n// sidebar\nexport const MQ_RIGHT_SIDEBAR_MIN_WIDTH = 1229;\n\n// -----------------------------------------------------------------------------\n\n// user agent detections\nexport const isDarwin = /Mac|iPod|iPhone|iPad/.test(navigator.platform);\nexport const isWindows = /^Win/.test(navigator.platform);\nexport const isAndroid = /\\b(android)\\b/i.test(navigator.userAgent);\nexport const isFirefox =\n typeof window !== \"undefined\" &&\n \"netscape\" in window &&\n navigator.userAgent.indexOf(\"rv:\") > 1 &&\n navigator.userAgent.indexOf(\"Gecko\") > 1;\nexport const isChrome = navigator.userAgent.indexOf(\"Chrome\") !== -1;\nexport const isSafari =\n !isChrome && navigator.userAgent.indexOf(\"Safari\") !== -1;\nexport const isIOS =\n /iPad|iPhone/i.test(navigator.platform) ||\n // iPadOS 13+\n (navigator.userAgent.includes(\"Mac\") && \"ontouchend\" in document);\n// keeping function so it can be mocked in test\nexport const isBrave = () =>\n (navigator as any).brave?.isBrave?.name === \"isBrave\";\n\n// export const isMobile =\n// isIOS ||\n// /android|webos|ipod|blackberry|iemobile|opera mini/i.test(\n// navigator.userAgent,\n// ) ||\n// /android|ios|ipod|blackberry|windows phone/i.test(navigator.platform);\n\n// utilities\nexport const isMobileBreakpoint = (width: number, height: number) => {\n return (\n width <= MQ_MAX_MOBILE ||\n (height < MQ_MAX_HEIGHT_LANDSCAPE && width < MQ_MAX_WIDTH_LANDSCAPE)\n );\n};\n\nexport const isTabletBreakpoint = (\n editorWidth: number,\n editorHeight: number,\n) => {\n const minSide = Math.min(editorWidth, editorHeight);\n const maxSide = Math.max(editorWidth, editorHeight);\n\n return minSide >= MQ_MIN_TABLET && maxSide <= MQ_MAX_TABLET;\n};\n\nconst isMobileOrTablet = (): boolean => {\n const ua = navigator.userAgent || \"\";\n const platform = navigator.platform || \"\";\n const uaData = (navigator as any).userAgentData as\n | { mobile?: boolean; platform?: string }\n | undefined;\n\n // --- 1) chromium: prefer ua client hints -------------------------------\n if (uaData) {\n const plat = (uaData.platform || \"\").toLowerCase();\n const isDesktopOS =\n plat === \"windows\" ||\n plat === \"macos\" ||\n plat === \"linux\" ||\n plat === \"chrome os\";\n if (uaData.mobile === true) {\n return true;\n }\n if (uaData.mobile === false && plat === \"android\") {\n const looksTouchTablet =\n matchMedia?.(\"(hover: none)\").matches &&\n matchMedia?.(\"(pointer: coarse)\").matches;\n return looksTouchTablet;\n }\n if (isDesktopOS) {\n return false;\n }\n }\n\n // --- 2) ios (includes ipad) --------------------------------------------\n if (isIOS) {\n return true;\n }\n\n // --- 3) android legacy ua fallback -------------------------------------\n if (isAndroid) {\n const isAndroidPhone = /Mobile/i.test(ua);\n const isAndroidTablet = !isAndroidPhone;\n if (isAndroidPhone || isAndroidTablet) {\n const looksTouchTablet =\n matchMedia?.(\"(hover: none)\").matches &&\n matchMedia?.(\"(pointer: coarse)\").matches;\n return looksTouchTablet;\n }\n }\n\n // --- 4) last resort desktop exclusion ----------------------------------\n const looksDesktopPlatform =\n /Win|Linux|CrOS|Mac/.test(platform) ||\n /Windows NT|X11|CrOS|Macintosh/.test(ua);\n if (looksDesktopPlatform) {\n return false;\n }\n return false;\n};\n\nexport const getFormFactor = (\n editorWidth: number,\n editorHeight: number,\n): EditorInterface[\"formFactor\"] => {\n if (isMobileBreakpoint(editorWidth, editorHeight)) {\n return \"phone\";\n }\n\n if (isTabletBreakpoint(editorWidth, editorHeight)) {\n return \"tablet\";\n }\n\n return \"desktop\";\n};\n\nexport const deriveStylesPanelMode = (\n editorInterface: EditorInterface,\n): StylesPanelMode => {\n if (editorInterface.formFactor === \"phone\") {\n return \"mobile\";\n }\n\n if (editorInterface.formFactor === \"tablet\") {\n return \"compact\";\n }\n\n return editorInterface.desktopUIMode;\n};\n\nexport const createUserAgentDescriptor = (\n userAgentString: string,\n): EditorInterface[\"userAgent\"] => {\n const normalizedUA = userAgentString ?? \"\";\n let platform: EditorInterface[\"userAgent\"][\"platform\"] = \"unknown\";\n\n if (isIOS) {\n platform = \"ios\";\n } else if (isAndroid) {\n platform = \"android\";\n } else if (normalizedUA) {\n platform = \"other\";\n }\n\n return {\n isMobileDevice: isMobileOrTablet(),\n platform,\n } as const;\n};\n\nexport const loadDesktopUIModePreference = () => {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n const stored = window.localStorage.getItem(DESKTOP_UI_MODE_STORAGE_KEY);\n if (stored === \"compact\" || stored === \"full\") {\n return stored as EditorInterface[\"desktopUIMode\"];\n }\n } catch (error) {\n // ignore storage access issues (e.g., Safari private mode)\n }\n\n return null;\n};\n\nconst persistDesktopUIMode = (mode: EditorInterface[\"desktopUIMode\"]) => {\n if (typeof window === \"undefined\") {\n return;\n }\n try {\n window.localStorage.setItem(DESKTOP_UI_MODE_STORAGE_KEY, mode);\n } catch (error) {\n // ignore storage access issues (e.g., Safari private mode)\n }\n};\n\nexport const setDesktopUIMode = (mode: EditorInterface[\"desktopUIMode\"]) => {\n if (mode !== \"compact\" && mode !== \"full\") {\n return;\n }\n\n persistDesktopUIMode(mode);\n\n return mode;\n};\n", "import { isDarwin } from \"./editorInterface\";\n\nimport type { ValueOf } from \"./utility-types\";\n\nexport const CODES = {\n EQUAL: \"Equal\",\n MINUS: \"Minus\",\n NUM_ADD: \"NumpadAdd\",\n NUM_SUBTRACT: \"NumpadSubtract\",\n NUM_ZERO: \"Numpad0\",\n BRACKET_RIGHT: \"BracketRight\",\n BRACKET_LEFT: \"BracketLeft\",\n ONE: \"Digit1\",\n TWO: \"Digit2\",\n THREE: \"Digit3\",\n NINE: \"Digit9\",\n QUOTE: \"Quote\",\n ZERO: \"Digit0\",\n SLASH: \"Slash\",\n C: \"KeyC\",\n D: \"KeyD\",\n H: \"KeyH\",\n V: \"KeyV\",\n Z: \"KeyZ\",\n Y: \"KeyY\",\n R: \"KeyR\",\n S: \"KeyS\",\n} as const;\n\nexport const KEYS = {\n ARROW_DOWN: \"ArrowDown\",\n ARROW_LEFT: \"ArrowLeft\",\n ARROW_RIGHT: \"ArrowRight\",\n ARROW_UP: \"ArrowUp\",\n PAGE_UP: \"PageUp\",\n PAGE_DOWN: \"PageDown\",\n BACKSPACE: \"Backspace\",\n ALT: \"Alt\",\n CTRL_OR_CMD: isDarwin ? \"metaKey\" : \"ctrlKey\",\n DELETE: \"Delete\",\n ENTER: \"Enter\",\n ESCAPE: \"Escape\",\n QUESTION_MARK: \"?\",\n SPACE: \" \",\n TAB: \"Tab\",\n CHEVRON_LEFT: \"<\",\n CHEVRON_RIGHT: \">\",\n PERIOD: \".\",\n COMMA: \",\",\n SUBTRACT: \"-\",\n SLASH: \"/\",\n\n A: \"a\",\n C: \"c\",\n D: \"d\",\n E: \"e\",\n F: \"f\",\n G: \"g\",\n H: \"h\",\n I: \"i\",\n L: \"l\",\n O: \"o\",\n P: \"p\",\n Q: \"q\",\n R: \"r\",\n S: \"s\",\n T: \"t\",\n V: \"v\",\n X: \"x\",\n Y: \"y\",\n Z: \"z\",\n K: \"k\",\n W: \"w\",\n\n 0: \"0\",\n 1: \"1\",\n 2: \"2\",\n 3: \"3\",\n 4: \"4\",\n 5: \"5\",\n 6: \"6\",\n 7: \"7\",\n 8: \"8\",\n 9: \"9\",\n} as const;\n\nexport type Key = keyof typeof KEYS;\n\n// defines key code mapping for matching codes as fallback to respective keys on non-latin keyboard layouts\nexport const KeyCodeMap = new Map<ValueOf<typeof KEYS>, ValueOf<typeof CODES>>([\n [KEYS.Z, CODES.Z],\n [KEYS.Y, CODES.Y],\n]);\n\nexport const isLatinChar = (key: string) => /^[a-z]$/.test(key.toLowerCase());\n\n/**\n * Used to match key events for any keyboard layout, especially on Windows and Linux,\n * where non-latin character with modified (CMD) is not substituted with latin-based alternative.\n *\n * Uses `event.key` when it's latin, otherwise fallbacks to `event.code` (if mapping exists).\n *\n * Example of pressing \"z\" on different layouts, with the chosen key or code highlighted in []:\n *\n * Layout | Code | Key | Comment\n * --------------------- | ----- | --- | -------\n * U.S. | KeyZ | [z] |\n * Czech | KeyY | [z] |\n * Turkish | KeyN | [z] |\n * French | KeyW | [z] |\n * Macedonian | [KeyZ] | \u0437 | z with cmd; \u0437 is Cyrillic equivalent of z\n * Russian | [KeyZ] | \u044F | z with cmd\n * Serbian | [KeyZ] | \u0455 | z with cmd\n * Greek | [KeyZ] | \u03B6 | z with cmd; also \u03B6 is Greek equivalent of z\n * Hebrew | [KeyZ] | \u05D6 | z with cmd; also \u05D6 is Hebrew equivalent of z\n * Pinyin - Simplified | KeyZ | [z] | due to IME\n * Cangije - Traditional | [KeyZ] | \u91CD | z with cmd\n * Japanese | [KeyZ] | \u3064 | z with cmd\n * 2-Set Korean | [KeyZ] | \u314B | z with cmd\n *\n * More details in https://github.com/excalidraw/excalidraw/pull/5944\n */\nexport const matchKey = (\n event: KeyboardEvent | React.KeyboardEvent<Element>,\n key: ValueOf<typeof KEYS>,\n): boolean => {\n // for latin layouts use key\n if (key === event.key.toLowerCase()) {\n return true;\n }\n\n // non-latin layouts fallback to code\n const code = KeyCodeMap.get(key);\n return Boolean(code && !isLatinChar(event.key) && event.code === code);\n};\n\nexport const isArrowKey = (key: string) =>\n key === KEYS.ARROW_LEFT ||\n key === KEYS.ARROW_RIGHT ||\n key === KEYS.ARROW_DOWN ||\n key === KEYS.ARROW_UP;\n\nexport const shouldResizeFromCenter = (event: MouseEvent | KeyboardEvent) =>\n event.altKey;\n\nexport const shouldMaintainAspectRatio = (event: MouseEvent | KeyboardEvent) =>\n event.shiftKey;\n\nexport const shouldRotateWithDiscreteAngle = (\n event: MouseEvent | KeyboardEvent | React.PointerEvent<HTMLCanvasElement>,\n) => event.shiftKey;\n", "import {\n pointFromPair,\n type GlobalPoint,\n type LocalPoint,\n} from \"@excalidraw/math\";\n\nimport type { NullableGridSize } from \"@excalidraw/excalidraw/types\";\n\nexport const getSizeFromPoints = (\n points: readonly (GlobalPoint | LocalPoint)[],\n) => {\n const xs = points.map((point) => point[0]);\n const ys = points.map((point) => point[1]);\n return {\n width: Math.max(...xs) - Math.min(...xs),\n height: Math.max(...ys) - Math.min(...ys),\n };\n};\n\n/** @arg dimension, 0 for rescaling only x, 1 for y */\nexport const rescalePoints = <Point extends GlobalPoint | LocalPoint>(\n dimension: 0 | 1,\n newSize: number,\n points: readonly Point[],\n normalize: boolean,\n): Point[] => {\n const coordinates = points.map((point) => point[dimension]);\n const maxCoordinate = Math.max(...coordinates);\n const minCoordinate = Math.min(...coordinates);\n const size = maxCoordinate - minCoordinate;\n const scale = size === 0 ? 1 : newSize / size;\n\n let nextMinCoordinate = Infinity;\n\n const scaledPoints = points.map((point): Point => {\n const newCoordinate = point[dimension] * scale;\n const newPoint = [...point];\n newPoint[dimension] = newCoordinate;\n if (newCoordinate < nextMinCoordinate) {\n nextMinCoordinate = newCoordinate;\n }\n return newPoint as Point;\n });\n\n if (!normalize) {\n return scaledPoints;\n }\n\n if (scaledPoints.length === 2) {\n // we don't translate two-point lines\n return scaledPoints;\n }\n\n const translation = minCoordinate - nextMinCoordinate;\n\n const nextPoints = scaledPoints.map((scaledPoint) =>\n pointFromPair<Point>(\n scaledPoint.map((value, currentDimension) => {\n return currentDimension === dimension ? value + translation : value;\n }) as [number, number],\n ),\n );\n\n return nextPoints;\n};\n\n// TODO: Rounding this point causes some shake when free drawing\nexport const getGridPoint = (\n x: number,\n y: number,\n gridSize: NullableGridSize,\n): [number, number] => {\n if (gridSize) {\n return [\n Math.round(x / gridSize) * gridSize,\n Math.round(y / gridSize) * gridSize,\n ];\n }\n return [x, y];\n};\n", "import Pool from \"es6-promise-pool\";\n\n// extending the missing types\n// relying on the [Index, T] to keep a correct order\ntype TPromisePool<T, Index = number> = Pool<[Index, T][]> & {\n addEventListener: (\n type: \"fulfilled\",\n listener: (event: { data: { result: [Index, T] } }) => void,\n ) => (event: { data: { result: [Index, T] } }) => void;\n removeEventListener: (\n type: \"fulfilled\",\n listener: (event: { data: { result: [Index, T] } }) => void,\n ) => void;\n};\n\nexport class PromisePool<T> {\n private readonly pool: TPromisePool<T>;\n private readonly entries: Record<number, T> = {};\n\n constructor(\n source: IterableIterator<Promise<void | readonly [number, T]>>,\n concurrency: number,\n ) {\n this.pool = new Pool(\n source as unknown as () => void | PromiseLike<[number, T][]>,\n concurrency,\n ) as TPromisePool<T>;\n }\n\n public all() {\n const listener = (event: { data: { result: void | [number, T] } }) => {\n if (event.data.result) {\n // by default pool does not return the results, so we are gathering them manually\n // with the correct call order (represented by the index in the tuple)\n const [index, value] = event.data.result;\n this.entries[index] = value;\n }\n };\n\n this.pool.addEventListener(\"fulfilled\", listener);\n\n return this.pool.start().then(() => {\n setTimeout(() => {\n this.pool.removeEventListener(\"fulfilled\", listener);\n });\n\n return Object.values(this.entries);\n });\n }\n}\n", "import { nanoid } from \"nanoid\";\nimport { Random } from \"roughjs/bin/math\";\n\nimport { isTestEnv } from \"./utils\";\n\nlet random = new Random(Date.now());\nlet testIdBase = 0;\n\nexport const randomInteger = () => Math.floor(random.next() * 2 ** 31);\n\nexport const reseed = (seed: number) => {\n random = new Random(seed);\n testIdBase = 0;\n};\n\nexport const randomId = () => (isTestEnv() ? `id${testIdBase++}` : nanoid());\n", "import { average } from \"@excalidraw/math\";\n\nimport type { FontFamilyValues, FontString } from \"@excalidraw/element/types\";\n\nimport type {\n ActiveTool,\n AppState,\n ToolType,\n UnsubscribeCallback,\n Zoom,\n} from \"@excalidraw/excalidraw/types\";\n\nimport { tinycolor } from \"./colors\";\nimport {\n DEFAULT_VERSION,\n ENV,\n FONT_FAMILY,\n getFontFamilyFallbacks,\n WINDOWS_EMOJI_FALLBACK_FONT,\n} from \"./constants\";\n\nimport type { MaybePromise, ResolutionType } from \"./utility-types\";\n\nimport type { EVENT } from \"./constants\";\n\nlet mockDateTime: string | null = null;\n\nexport const setDateTimeForTests = (dateTime: string) => {\n mockDateTime = dateTime;\n};\n\nexport const getDateTime = () => {\n if (mockDateTime) {\n return mockDateTime;\n }\n\n const date = new Date();\n const year = date.getFullYear();\n const month = `${date.getMonth() + 1}`.padStart(2, \"0\");\n const day = `${date.getDate()}`.padStart(2, \"0\");\n const hr = `${date.getHours()}`.padStart(2, \"0\");\n const min = `${date.getMinutes()}`.padStart(2, \"0\");\n\n return `${year}-${month}-${day}-${hr}${min}`;\n};\n\nexport const capitalizeString = (str: string) =>\n str.charAt(0).toUpperCase() + str.slice(1);\n\nexport const isToolIcon = (\n target: Element | EventTarget | null,\n): target is HTMLElement =>\n target instanceof HTMLElement && target.className.includes(\"ToolIcon\");\n\nexport const isInputLike = (\n target: Element | EventTarget | null,\n): target is\n | HTMLInputElement\n | HTMLTextAreaElement\n | HTMLSelectElement\n | HTMLBRElement\n | HTMLDivElement =>\n (target instanceof HTMLElement && target.dataset.type === \"wysiwyg\") ||\n target instanceof HTMLBRElement || // newline in wysiwyg\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement;\n\nexport const isInteractive = (target: Element | EventTarget | null) => {\n return (\n isInputLike(target) ||\n (target instanceof Element && !!target.closest(\"label, button\"))\n );\n};\n\nexport const isWritableElement = (\n target: Element | EventTarget | null,\n): target is\n | HTMLInputElement\n | HTMLTextAreaElement\n | HTMLBRElement\n | HTMLDivElement =>\n (target instanceof HTMLElement && target.dataset.type === \"wysiwyg\") ||\n target instanceof HTMLBRElement || // newline in wysiwyg\n target instanceof HTMLTextAreaElement ||\n (target instanceof HTMLInputElement &&\n (target.type === \"text\" ||\n target.type === \"number\" ||\n target.type === \"password\" ||\n target.type === \"search\"));\n\nexport const getFontFamilyString = ({\n fontFamily,\n}: {\n fontFamily: FontFamilyValues;\n}) => {\n for (const [fontFamilyString, id] of Object.entries(FONT_FAMILY)) {\n if (id === fontFamily) {\n return `${fontFamilyString}${getFontFamilyFallbacks(id)\n .map((x) => `, ${x}`)\n .join(\"\")}`;\n }\n }\n return WINDOWS_EMOJI_FALLBACK_FONT;\n};\n\n/** returns fontSize+fontFamily string for assignment to DOM elements */\nexport const getFontString = ({\n fontSize,\n fontFamily,\n}: {\n fontSize: number;\n fontFamily: FontFamilyValues;\n}) => {\n return `${fontSize}px ${getFontFamilyString({ fontFamily })}` as FontString;\n};\n\n/** executes callback in the frame that's after the current one */\nexport const nextAnimationFrame = async (cb: () => any) => {\n requestAnimationFrame(() => requestAnimationFrame(cb));\n};\n\nexport const debounce = <T extends any[]>(\n fn: (...args: T) => void,\n timeout: number,\n) => {\n let handle = 0;\n let lastArgs: T | null = null;\n const ret = (...args: T) => {\n lastArgs = args;\n clearTimeout(handle);\n handle = window.setTimeout(() => {\n lastArgs = null;\n fn(...args);\n }, timeout);\n };\n ret.flush = () => {\n clearTimeout(handle);\n if (lastArgs) {\n const _lastArgs = lastArgs;\n lastArgs = null;\n fn(..._lastArgs);\n }\n };\n ret.cancel = () => {\n lastArgs = null;\n clearTimeout(handle);\n };\n return ret;\n};\n\n// throttle callback to execute once per animation frame\nexport const throttleRAF = <T extends any[]>(\n fn: (...args: T) => void,\n opts?: { trailing?: boolean },\n) => {\n let timerId: number | null = null;\n let lastArgs: T | null = null;\n let lastArgsTrailing: T | null = null;\n\n const scheduleFunc = (args: T) => {\n timerId = window.requestAnimationFrame(() => {\n timerId = null;\n fn(...args);\n lastArgs = null;\n if (lastArgsTrailing) {\n lastArgs = lastArgsTrailing;\n lastArgsTrailing = null;\n scheduleFunc(lastArgs);\n }\n });\n };\n\n const ret = (...args: T) => {\n if (isTestEnv()) {\n fn(...args);\n return;\n }\n lastArgs = args;\n if (timerId === null) {\n scheduleFunc(lastArgs);\n } else if (opts?.trailing) {\n lastArgsTrailing = args;\n }\n };\n ret.flush = () => {\n if (timerId !== null) {\n cancelAnimationFrame(timerId);\n timerId = null;\n }\n if (lastArgs) {\n fn(...(lastArgsTrailing || lastArgs));\n lastArgs = lastArgsTrailing = null;\n }\n };\n ret.cancel = () => {\n lastArgs = lastArgsTrailing = null;\n if (timerId !== null) {\n cancelAnimationFrame(timerId);\n timerId = null;\n }\n };\n return ret;\n};\n\n/**\n * Exponential ease-out method\n *\n * @param {number} k - The value to be tweened.\n * @returns {number} The tweened value.\n */\nexport const easeOut = (k: number) => {\n return 1 - Math.pow(1 - k, 4);\n};\n\nconst easeOutInterpolate = (from: number, to: number, progress: number) => {\n return (to - from) * easeOut(progress) + from;\n};\n\n/**\n * Animates values from `fromValues` to `toValues` using the requestAnimationFrame API.\n * Executes the `onStep` callback on each step with the interpolated values.\n * Returns a function that can be called to cancel the animation.\n *\n * @example\n * // Example usage:\n * const fromValues = { x: 0, y: 0 };\n * const toValues = { x: 100, y: 200 };\n * const onStep = ({x, y}) => {\n * setState(x, y)\n * };\n * const onCancel = () => {\n * console.log(\"Animation canceled\");\n * };\n *\n * const cancelAnimation = easeToValuesRAF({\n * fromValues,\n * toValues,\n * onStep,\n * onCancel,\n * });\n *\n * // To cancel the animation:\n * cancelAnimation();\n */\nexport const easeToValuesRAF = <\n T extends Record<keyof T, number>,\n K extends keyof T,\n>({\n fromValues,\n toValues,\n onStep,\n duration = 250,\n interpolateValue,\n onStart,\n onEnd,\n onCancel,\n}: {\n fromValues: T;\n toValues: T;\n /**\n * Interpolate a single value.\n * Return undefined to be handled by the default interpolator.\n */\n interpolateValue?: (\n fromValue: number,\n toValue: number,\n /** no easing applied */\n progress: number,\n key: K,\n ) => number | undefined;\n onStep: (values: T) => void;\n duration?: number;\n onStart?: () => void;\n onEnd?: () => void;\n onCancel?: () => void;\n}) => {\n let canceled = false;\n let frameId = 0;\n let startTime: number;\n\n function step(timestamp: number) {\n if (canceled) {\n return;\n }\n if (startTime === undefined) {\n startTime = timestamp;\n onStart?.();\n }\n\n const elapsed = Math.min(timestamp - startTime, duration);\n const factor = easeOut(elapsed / duration);\n\n const newValues = {} as T;\n\n Object.keys(fromValues).forEach((key) => {\n const _key = key as keyof T;\n const result = ((toValues[_key] - fromValues[_key]) * factor +\n fromValues[_key]) as T[keyof T];\n newValues[_key] = result;\n });\n\n onStep(newValues);\n\n if (elapsed < duration) {\n const progress = elapsed / duration;\n\n const newValues = {} as T;\n\n Object.keys(fromValues).forEach((key) => {\n const _key = key as K;\n const startValue = fromValues[_key];\n const endValue = toValues[_key];\n\n let result;\n\n result = interpolateValue\n ? interpolateValue(startValue, endValue, progress, _key)\n : easeOutInterpolate(startValue, endValue, progress);\n\n if (result == null) {\n result = easeOutInterpolate(startValue, endValue, progress);\n }\n\n newValues[_key] = result as T[K];\n });\n onStep(newValues);\n\n frameId = window.requestAnimationFrame(step);\n } else {\n onStep(toValues);\n onEnd?.();\n }\n }\n\n frameId = window.requestAnimationFrame(step);\n\n return () => {\n onCancel?.();\n canceled = true;\n window.cancelAnimationFrame(frameId);\n };\n};\n\n// https://github.com/lodash/lodash/blob/es/chunk.js\nexport const chunk = <T extends any>(\n array: readonly T[],\n size: number,\n): T[][] => {\n if (!array.length || size < 1) {\n return [];\n }\n let index = 0;\n let resIndex = 0;\n const result = Array(Math.ceil(array.length / size));\n while (index < array.length) {\n result[resIndex++] = array.slice(index, (index += size));\n }\n return result;\n};\n\nexport const selectNode = (node: Element) => {\n const selection = window.getSelection();\n if (selection) {\n const range = document.createRange();\n range.selectNodeContents(node);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n};\n\nexport const removeSelection = () => {\n const selection = window.getSelection();\n if (selection) {\n selection.removeAllRanges();\n }\n};\n\nexport const distance = (x: number, y: number) => Math.abs(x - y);\n\nexport const isSelectionLikeTool = (type: ToolType | \"custom\") => {\n return type === \"selection\" || type === \"lasso\";\n};\n\nexport const updateActiveTool = (\n appState: Pick<AppState, \"activeTool\">,\n data: ((\n | {\n type: ToolType;\n }\n | { type: \"custom\"; customType: string }\n ) & { locked?: boolean; fromSelection?: boolean }) & {\n lastActiveToolBeforeEraser?: ActiveTool | null;\n },\n): AppState[\"activeTool\"] => {\n if (data.type === \"custom\") {\n return {\n ...appState.activeTool,\n type: \"custom\",\n customType: data.customType,\n locked: data.locked ?? appState.activeTool.locked,\n };\n }\n\n return {\n ...appState.activeTool,\n lastActiveTool:\n data.lastActiveToolBeforeEraser === undefined\n ? appState.activeTool.lastActiveTool\n : data.lastActiveToolBeforeEraser,\n type: data.type,\n customType: null,\n locked: data.locked ?? appState.activeTool.locked,\n fromSelection: data.fromSelection ?? false,\n };\n};\n\nexport const isFullScreen = () =>\n document.fullscreenElement?.nodeName === \"HTML\";\n\nexport const allowFullScreen = () =>\n document.documentElement.requestFullscreen();\n\nexport const exitFullScreen = () => document.exitFullscreen();\n\nexport const viewportCoordsToSceneCoords = (\n { clientX, clientY }: { clientX: number; clientY: number },\n {\n zoom,\n offsetLeft,\n offsetTop,\n scrollX,\n scrollY,\n }: {\n zoom: Zoom;\n offsetLeft: number;\n offsetTop: number;\n scrollX: number;\n scrollY: number;\n },\n) => {\n const x = (clientX - offsetLeft) / zoom.value - scrollX;\n const y = (clientY - offsetTop) / zoom.value - scrollY;\n\n return { x, y };\n};\n\nexport const sceneCoordsToViewportCoords = (\n { sceneX, sceneY }: { sceneX: number; sceneY: number },\n {\n zoom,\n offsetLeft,\n offsetTop,\n scrollX,\n scrollY,\n }: {\n zoom: Zoom;\n offsetLeft: number;\n offsetTop: number;\n scrollX: number;\n scrollY: number;\n },\n) => {\n const x = (sceneX + scrollX) * zoom.value + offsetLeft;\n const y = (sceneY + scrollY) * zoom.value + offsetTop;\n return { x, y };\n};\n\nexport const getGlobalCSSVariable = (name: string) =>\n getComputedStyle(document.documentElement).getPropertyValue(`--${name}`);\n\nconst RS_LTR_CHARS =\n \"A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02B8\\u0300-\\u0590\\u0800-\\u1FFF\" +\n \"\\u2C00-\\uFB1C\\uFDFE-\\uFE6F\\uFEFD-\\uFFFF\";\nconst RS_RTL_CHARS = \"\\u0591-\\u07FF\\uFB1D-\\uFDFD\\uFE70-\\uFEFC\";\nconst RE_RTL_CHECK = new RegExp(`^[^${RS_LTR_CHARS}]*[${RS_RTL_CHARS}]`);\n/**\n * Checks whether first directional character is RTL. Meaning whether it starts\n * with RTL characters, or indeterminate (numbers etc.) characters followed by\n * RTL.\n * See https://github.com/excalidraw/excalidraw/pull/1722#discussion_r436340171\n */\nexport const isRTL = (text: string) => RE_RTL_CHECK.test(text);\n\nexport const tupleToCoors = (\n xyTuple: readonly [number, number],\n): { x: number; y: number } => {\n const [x, y] = xyTuple;\n return { x, y };\n};\n\n/** use as a rejectionHandler to mute filesystem Abort errors */\nexport const muteFSAbortError = (error?: Error) => {\n if (error?.name === \"AbortError\") {\n console.warn(error);\n return;\n }\n throw error;\n};\n\nexport const findIndex = <T>(\n array: readonly T[],\n cb: (element: T, index: number, array: readonly T[]) => boolean,\n fromIndex: number = 0,\n) => {\n if (fromIndex < 0) {\n fromIndex = array.length + fromIndex;\n }\n fromIndex = Math.min(array.length, Math.max(fromIndex, 0));\n let index = fromIndex - 1;\n while (++index < array.length) {\n if (cb(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n};\n\nexport const findLastIndex = <T>(\n array: readonly T[],\n cb: (element: T, index: number, array: readonly T[]) => boolean,\n fromIndex: number = array.length - 1,\n) => {\n if (fromIndex < 0) {\n fromIndex = array.length + fromIndex;\n }\n fromIndex = Math.min(array.length - 1, Math.max(fromIndex, 0));\n let index = fromIndex + 1;\n while (--index > -1) {\n if (cb(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n};\n\n/** returns the first non-null mapped value */\nexport const mapFind = <T, K>(\n collection: readonly T[],\n iteratee: (value: T, index: number) => K | undefined | null,\n): K | undefined => {\n for (let idx = 0; idx < collection.length; idx++) {\n const result = iteratee(collection[idx], idx);\n if (result != null) {\n return result;\n }\n }\n return undefined;\n};\n\nexport const isTransparent = (color: string) => {\n return tinycolor(color).getAlpha() === 0;\n};\n\nexport type ResolvablePromise<T> = Promise<T> & {\n resolve: [T] extends [undefined]\n ? (value?: MaybePromise<Awaited<T>>) => void\n : (value: MaybePromise<Awaited<T>>) => void;\n reject: (error: Error) => void;\n};\nexport const resolvablePromise = <T>() => {\n let resolve!: any;\n let reject!: any;\n const promise = new Promise((_resolve, _reject) => {\n resolve = _resolve;\n reject = _reject;\n });\n (promise as any).resolve = resolve;\n (promise as any).reject = reject;\n return promise as ResolvablePromise<T>;\n};\n\n//https://stackoverflow.com/a/9462382/8418\nexport const nFormatter = (num: number, digits: number): string => {\n const si = [\n { value: 1, symbol: \"b\" },\n { value: 1e3, symbol: \"k\" },\n { value: 1e6, symbol: \"M\" },\n { value: 1e9, symbol: \"G\" },\n ];\n const rx = /\\.0+$|(\\.[0-9]*[1-9])0+$/;\n let index;\n for (index = si.length - 1; index > 0; index--) {\n if (num >= si[index].value) {\n break;\n }\n }\n return (\n (num / si[index].value).toFixed(digits).replace(rx, \"$1\") + si[index].symbol\n );\n};\n\nexport const getVersion = () => {\n return (\n document.querySelector<HTMLMetaElement>('meta[name=\"version\"]')?.content ||\n DEFAULT_VERSION\n );\n};\n\n// Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/emoji.js\nexport const supportsEmoji = () => {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n return false;\n }\n const offset = 12;\n ctx.fillStyle = \"#f00\";\n ctx.textBaseline = \"top\";\n ctx.font = \"32px Arial\";\n // Modernizr used \uD83D\uDC28, but it is sort of supported on Windows 7.\n // Luckily \uD83D\uDE00 isn't supported.\n ctx.fillText(\"\uD83D\uDE00\", 0, 0);\n return ctx.getImageData(offset, offset, 1, 1).data[0] !== 0;\n};\n\nexport const getNearestScrollableContainer = (\n element: HTMLElement,\n): HTMLElement | Document => {\n let parent = element.parentElement;\n while (parent) {\n if (parent === document.body) {\n return document;\n }\n const { overflowY } = window.getComputedStyle(parent);\n const hasScrollableContent = parent.scrollHeight > parent.clientHeight;\n if (\n hasScrollableContent &&\n (overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n overflowY === \"overlay\")\n ) {\n return parent;\n }\n parent = parent.parentElement;\n }\n return document;\n};\n\nexport const focusNearestParent = (element: HTMLInputElement) => {\n let parent = element.parentElement;\n while (parent) {\n if (parent.tabIndex > -1) {\n parent.focus();\n return;\n }\n parent = parent.parentElement;\n }\n};\n\nexport const preventUnload = (event: BeforeUnloadEvent) => {\n event.preventDefault();\n // NOTE: modern browsers no longer allow showing a custom message here\n event.returnValue = \"\";\n};\n\nexport const bytesToHexString = (bytes: Uint8Array) => {\n return Array.from(bytes)\n .map((byte) => `0${byte.toString(16)}`.slice(-2))\n .join(\"\");\n};\n\nexport const getUpdatedTimestamp = () => (isTestEnv() ? 1 : Date.now());\n\n/**\n * Transforms array of objects containing `id` attribute,\n * or array of ids (strings), into a Map, keyd by `id`.\n */\nexport const arrayToMap = <T extends { id: string } | string>(\n items: readonly T[] | Map<string, T>,\n) => {\n if (items instanceof Map) {\n return items;\n }\n return items.reduce((acc: Map<string, T>, element) => {\n acc.set(typeof element === \"string\" ? element : element.id, element);\n return acc;\n }, new Map() as Map<string, T>);\n};\n\nexport const arrayToMapWithIndex = <T extends { id: string }>(\n elements: readonly T[],\n) =>\n elements.reduce((acc, element: T, idx) => {\n acc.set(element.id, [element, idx]);\n return acc;\n }, new Map<string, [element: T, index: number]>());\n\n/**\n * Transform array into an object, use only when array order is irrelevant.\n */\nexport const arrayToObject = <T>(\n array: readonly T[],\n groupBy?: (value: T) => string | number,\n) =>\n array.reduce((acc, value, idx) => {\n acc[groupBy ? groupBy(value) : idx] = value;\n return acc;\n }, {} as { [key: string]: T });\n\n/** Doubly linked node */\nexport type Node<T> = T & {\n prev: Node<T> | null;\n next: Node<T> | null;\n};\n\n/**\n * Creates a circular doubly linked list by adding `prev` and `next` props to the existing array nodes.\n */\nexport const arrayToList = <T>(array: readonly T[]): Node<T>[] =>\n array.reduce((acc, curr, index) => {\n const node: Node<T> = { ...curr, prev: null, next: null };\n\n // no-op for first item, we don't want circular references on a single item\n if (index !== 0) {\n const prevNode = acc[index - 1];\n node.prev = prevNode;\n prevNode.next = node;\n\n if (index === array.length - 1) {\n // make the references circular and connect head & tail\n const firstNode = acc[0];\n node.next = firstNode;\n firstNode.prev = node;\n }\n }\n\n acc.push(node);\n\n return acc;\n }, [] as Node<T>[]);\n\n/**\n * Converts a readonly array or map into an iterable.\n * Useful for avoiding entry allocations when iterating object / map on each iteration.\n */\nexport const toIterable = <T>(\n values: readonly T[] | ReadonlyMap<string, T>,\n): Iterable<T> => {\n return Array.isArray(values) ? values : values.values();\n};\n\n/**\n * Converts a readonly array or map into an array.\n */\nexport const toArray = <T>(\n values: readonly T[] | ReadonlyMap<string, T>,\n): T[] => {\n return Array.isArray(values) ? values : Array.from(toIterable(values));\n};\n\nexport const isTestEnv = () => import.meta.env.MODE === ENV.TEST;\n\nexport const isDevEnv = () => import.meta.env.MODE === ENV.DEVELOPMENT;\n\nexport const isProdEnv = () => import.meta.env.MODE === ENV.PRODUCTION;\n\nexport const isServerEnv = () =>\n typeof process !== \"undefined\" && !!process?.env?.NODE_ENV;\n\nexport const wrapEvent = <T extends Event>(name: EVENT, nativeEvent: T) => {\n return new CustomEvent(name, {\n detail: {\n nativeEvent,\n },\n cancelable: true,\n });\n};\n\nexport const updateObject = <T extends Record<string, any>>(\n obj: T,\n updates: Partial<T>,\n): T => {\n let didChange = false;\n for (const key in updates) {\n const value = (updates as any)[key];\n if (typeof value !== \"undefined\") {\n if (\n (obj as any)[key] === value &&\n // if object, always update because its attrs could have changed\n (typeof value !== \"object\" || value === null)\n ) {\n continue;\n }\n didChange = true;\n }\n }\n\n if (!didChange) {\n return obj;\n }\n\n return {\n ...obj,\n ...updates,\n };\n};\n\nexport const isPrimitive = (val: any) => {\n const type = typeof val;\n return val == null || (type !== \"object\" && type !== \"function\");\n};\n\nexport const getFrame = () => {\n try {\n return window.self === window.top ? \"top\" : \"iframe\";\n } catch (error) {\n return \"iframe\";\n }\n};\n\nexport const isRunningInIframe = () => getFrame() === \"iframe\";\n\nexport const isPromiseLike = (\n value: any,\n): value is Promise<ResolutionType<typeof value>> => {\n return (\n !!value &&\n typeof value === \"object\" &&\n \"then\" in value &&\n \"catch\" in value &&\n \"finally\" in value\n );\n};\n\nexport const queryFocusableElements = (container: HTMLElement | null) => {\n const focusableElements = container?.querySelectorAll<HTMLElement>(\n \"button, a, input, select, textarea, div[tabindex], label[tabindex]\",\n );\n\n return focusableElements\n ? Array.from(focusableElements).filter(\n (element) =>\n element.tabIndex > -1 && !(element as HTMLInputElement).disabled,\n )\n : [];\n};\n\n/** use as a fallback after identity check (for perf reasons) */\nconst _defaultIsShallowComparatorFallback = (a: any, b: any): boolean => {\n // consider two empty arrays equal\n if (\n Array.isArray(a) &&\n Array.isArray(b) &&\n a.length === 0 &&\n b.length === 0\n ) {\n return true;\n }\n return a === b;\n};\n\n/**\n * Returns whether object/array is shallow equal.\n * Considers empty object/arrays as equal (whether top-level or second-level).\n */\nexport const isShallowEqual = <\n T extends Record<string, any>,\n K extends readonly unknown[],\n>(\n objA: T,\n objB: T,\n comparators?:\n | { [key in keyof T]?: (a: T[key], b: T[key]) => boolean }\n | (keyof T extends K[number]\n ? K extends readonly (keyof T)[]\n ? K\n : {\n _error: \"keys are either missing or include keys not in compared obj\";\n }\n : {\n _error: \"keys are either missing or include keys not in compared obj\";\n }),\n debug = false,\n) => {\n const aKeys = Object.keys(objA);\n const bKeys = Object.keys(objB);\n if (aKeys.length !== bKeys.length) {\n if (debug) {\n console.warn(\n `%cisShallowEqual: objects don't have same properties ->`,\n \"color: #8B4000\",\n objA,\n objB,\n );\n }\n return false;\n }\n\n if (comparators && Array.isArray(comparators)) {\n for (const key of comparators) {\n const ret =\n objA[key] === objB[key] ||\n _defaultIsShallowComparatorFallback(objA[key], objB[key]);\n if (!ret) {\n if (debug) {\n console.warn(\n `%cisShallowEqual: ${key} not equal ->`,\n \"color: #8B4000\",\n objA[key],\n objB[key],\n );\n }\n return false;\n }\n }\n return true;\n }\n\n return aKeys.every((key) => {\n const comparator = (\n comparators as { [key in keyof T]?: (a: T[key], b: T[key]) => boolean }\n )?.[key as keyof T];\n const ret = comparator\n ? comparator(objA[key], objB[key])\n : objA[key] === objB[key] ||\n _defaultIsShallowComparatorFallback(objA[key], objB[key]);\n\n if (!ret && debug) {\n console.warn(\n `%cisShallowEqual: ${key} not equal ->`,\n \"color: #8B4000\",\n objA[key],\n objB[key],\n );\n }\n return ret;\n });\n};\n\n// taken from Radix UI\n// https://github.com/radix-ui/primitives/blob/main/packages/core/primitive/src/primitive.tsx\nexport const composeEventHandlers = <E>(\n originalEventHandler?: (event: E) => void,\n ourEventHandler?: (event: E) => void,\n { checkForDefaultPrevented = true } = {},\n) => {\n return function handleEvent(event: E) {\n originalEventHandler?.(event);\n\n if (\n !checkForDefaultPrevented ||\n !(event as unknown as Event)?.defaultPrevented\n ) {\n return ourEventHandler?.(event);\n }\n };\n};\n\n/**\n * supply `null` as message if non-never value is valid, you just need to\n * typecheck against it\n */\nexport const assertNever = (\n value: never,\n message: string | null,\n softAssert?: boolean,\n): never => {\n if (!message) {\n return value;\n }\n if (softAssert) {\n console.error(message);\n return value;\n }\n\n throw new Error(message);\n};\n\nexport function invariant(condition: any, message: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n\n/**\n * Memoizes on values of `opts` object (strict equality).\n */\nexport const memoize = <T extends Record<string, any>, R extends any>(\n func: (opts: T) => R,\n) => {\n let lastArgs: Map<string, any> | undefined;\n let lastResult: R | undefined;\n\n const ret = function (opts: T) {\n const currentArgs = Object.entries(opts);\n\n if (lastArgs) {\n let argsAreEqual = true;\n for (const [key, value] of currentArgs) {\n if (lastArgs.get(key) !== value) {\n argsAreEqual = false;\n break;\n }\n }\n if (argsAreEqual) {\n return lastResult;\n }\n }\n\n const result = func(opts);\n\n lastArgs = new Map(currentArgs);\n lastResult = result;\n\n return result;\n };\n\n ret.clear = () => {\n lastArgs = undefined;\n lastResult = undefined;\n };\n\n return ret as typeof func & { clear: () => void };\n};\n\n/** Checks if value is inside given collection. Useful for type-safety. */\nexport const isMemberOf = <T extends string>(\n /** Set/Map/Array/Object */\n collection: Set<T> | readonly T[] | Record<T, any> | Map<T, any>,\n /** value to look for */\n value: string,\n): value is T => {\n return collection instanceof Set || collection instanceof Map\n ? collection.has(value as T)\n : \"includes\" in collection\n ? collection.includes(value as T)\n : collection.hasOwnProperty(value);\n};\n\nexport const cloneJSON = <T>(obj: T): T => JSON.parse(JSON.stringify(obj));\n\nexport const updateStable = <T extends any[] | Record<string, any>>(\n prevValue: T,\n nextValue: T,\n) => {\n if (isShallowEqual(prevValue, nextValue)) {\n return prevValue;\n }\n return nextValue;\n};\n\n// Window\nexport function addEventListener<K extends keyof WindowEventMap>(\n target: Window & typeof globalThis,\n type: K,\n listener: (this: Window, ev: WindowEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback;\nexport function addEventListener(\n target: Window & typeof globalThis,\n type: string,\n listener: (this: Window, ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback;\n// Document\nexport function addEventListener<K extends keyof DocumentEventMap>(\n target: Document,\n type: K,\n listener: (this: Document, ev: DocumentEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback;\nexport function addEventListener(\n target: Document,\n type: string,\n listener: (this: Document, ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback;\n// FontFaceSet (document.fonts)\nexport function addEventListener<K extends keyof FontFaceSetEventMap>(\n target: FontFaceSet,\n type: K,\n listener: (this: FontFaceSet, ev: FontFaceSetEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback;\n// HTMLElement / mix\nexport function addEventListener<K extends keyof HTMLElementEventMap>(\n target:\n | Document\n | (Window & typeof globalThis)\n | HTMLElement\n | undefined\n | null\n | false,\n type: K,\n listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback;\n// implem\nexport function addEventListener(\n /**\n * allows for falsy values so you don't have to type check when adding\n * event listeners to optional elements\n */\n target:\n | Document\n | (Window & typeof globalThis)\n | FontFaceSet\n | HTMLElement\n | undefined\n | null\n | false,\n type: keyof WindowEventMap | keyof DocumentEventMap | string,\n listener: (ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): UnsubscribeCallback {\n if (!target) {\n return () => {};\n }\n target?.addEventListener?.(type, listener, options);\n return () => {\n target?.removeEventListener?.(type, listener, options);\n };\n}\n\nexport function getSvgPathFromStroke(points: number[][], closed = true) {\n const len = points.length;\n\n if (len < 4) {\n return ``;\n }\n\n let a = points[0];\n let b = points[1];\n const c = points[2];\n\n let result = `M${a[0].toFixed(2)},${a[1].toFixed(2)} Q${b[0].toFixed(\n 2,\n )},${b[1].toFixed(2)} ${average(b[0], c[0]).toFixed(2)},${average(\n b[1],\n c[1],\n ).toFixed(2)} T`;\n\n for (let i = 2, max = len - 1; i < max; i++) {\n a = points[i];\n b = points[i + 1];\n result += `${average(a[0], b[0]).toFixed(2)},${average(a[1], b[1]).toFixed(\n 2,\n )} `;\n }\n\n if (closed) {\n result += \"Z\";\n }\n\n return result;\n}\n\nexport const normalizeEOL = (str: string) => {\n return str.replace(/\\r?\\n|\\r/g, \"\\n\");\n};\n\n// -----------------------------------------------------------------------------\nexport type HasBrand<T> = {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n [K in keyof T]: K extends `~brand${infer _}` | \"_brand\" ? true : never;\n}[keyof T];\n\ntype RemoveAllBrands<T> = HasBrand<T> extends true\n ? {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n [K in keyof T as K extends `~brand~${infer _}` | \"_brand\"\n ? never\n : K]: T[K];\n }\n : T;\n\n// For accepting values - uses loose matching for branded types\n// Preserves readonly modifier: mutable array requires mutable input\ntype UnbrandForValue<T> = T extends Map<infer E, infer F>\n ? Map<UnbrandForValue<E>, UnbrandForValue<F>>\n : T extends Set<infer E>\n ? Set<UnbrandForValue<E>>\n : T extends readonly any[]\n ? T extends any[]\n ? unknown[] // mutable array - require mutable input\n : readonly unknown[] // readonly array - accept readonly input\n : RemoveAllBrands<T>;\n\n// For return types - preserves array element unbranding\nexport type Unbrand<T> = T extends Map<infer E, infer F>\n ? Map<Unbrand<E>, Unbrand<F>>\n : T extends Set<infer E>\n ? Set<Unbrand<E>>\n : T extends readonly (infer E)[]\n ? Array<Unbrand<E>>\n : RemoveAllBrands<T>;\n\nexport type CombineBrands<BrandedType, CurrentType> =\n BrandedType extends readonly (infer BE)[]\n ? CurrentType extends readonly (infer CE)[]\n ? Array<CE & BE>\n : CurrentType & BrandedType\n : CurrentType & BrandedType;\n\nexport type CombineBrandsIfNeeded<T, Required> = [T] extends [Required]\n ? T[]\n : HasBrand<T> extends true\n ? CombineBrands<T, Required>[]\n : Required[];\n\n/**\n * Makes type into a branded type, ensuring that value is assignable to\n * the base unbranded type. Optionally you can explicitly supply current value\n * type to combine both (useful for composite branded types. Make sure you\n * compose branded types which are not composite themselves.)\n */\nexport function toBrandedType<BrandedType>(\n value: UnbrandForValue<BrandedType>,\n): BrandedType;\nexport function toBrandedType<BrandedType, CurrentType>(\n value: CurrentType,\n): CombineBrands<BrandedType, CurrentType>;\nexport function toBrandedType(value: unknown) {\n return value;\n}\n\n// -----------------------------------------------------------------------------\n\n// Promise.try, adapted from https://github.com/sindresorhus/p-try\nexport const promiseTry = async <TValue, TArgs extends unknown[]>(\n fn: (...args: TArgs) => PromiseLike<TValue> | TValue,\n ...args: TArgs\n): Promise<TValue> => {\n return new Promise((resolve) => {\n resolve(fn(...args));\n });\n};\n\nexport const isAnyTrue = (...args: boolean[]): boolean =>\n Math.max(...args.map((arg) => (arg ? 1 : 0))) > 0;\n\nexport const safelyParseJSON = (json: string): Record<string, any> | null => {\n try {\n return JSON.parse(json);\n } catch {\n return null;\n }\n};\n\n/**\n * use when you need to render unsafe string as HTML attribute, but MAKE SURE\n * the attribute is double-quoted when constructing the HTML string\n */\nexport const escapeDoubleQuotes = (str: string) => {\n return str.replace(/\"/g, \""\");\n};\n\nexport const castArray = <T>(value: T | T[]): T[] =>\n Array.isArray(value) ? value : [value];\n\n/** hack for Array.isArray type guard not working with readonly value[] */\nexport const isReadonlyArray = (value?: any): value is readonly any[] => {\n return Array.isArray(value);\n};\n\nexport const sizeOf = (\n value:\n | readonly unknown[]\n | Readonly<Map<string, unknown>>\n | Readonly<Record<string, unknown>>\n | ReadonlySet<unknown>,\n): number => {\n return isReadonlyArray(value)\n ? value.length\n : value instanceof Map || value instanceof Set\n ? value.size\n : Object.keys(value).length;\n};\n\nexport const reduceToCommonValue = <T, R = T>(\n collection: readonly T[] | ReadonlySet<T>,\n getValue?: (item: T) => R,\n): R | null => {\n if (sizeOf(collection) === 0) {\n return null;\n }\n\n const valueExtractor = getValue || ((item: T) => item as unknown as R);\n\n let commonValue: R | null = null;\n\n for (const item of collection) {\n const value = valueExtractor(item);\n if ((commonValue === null || commonValue === value) && value != null) {\n commonValue = value;\n } else {\n return null;\n }\n }\n\n return commonValue;\n};\n\ntype FEATURE_FLAGS = {\n COMPLEX_BINDINGS: boolean;\n};\n\nconst FEATURE_FLAGS_STORAGE_KEY = \"excalidraw-feature-flags\";\nconst DEFAULT_FEATURE_FLAGS: FEATURE_FLAGS = {\n COMPLEX_BINDINGS: false,\n};\nlet featureFlags: FEATURE_FLAGS | null = null;\n\nexport const getFeatureFlag = <F extends keyof FEATURE_FLAGS>(\n flag: F,\n): FEATURE_FLAGS[F] => {\n if (!featureFlags) {\n try {\n const serializedFlags = localStorage.getItem(FEATURE_FLAGS_STORAGE_KEY);\n if (serializedFlags) {\n const flags = JSON.parse(serializedFlags);\n featureFlags = flags ?? DEFAULT_FEATURE_FLAGS;\n }\n } catch {}\n }\n\n return (featureFlags || DEFAULT_FEATURE_FLAGS)[flag];\n};\n\nexport const setFeatureFlag = <F extends keyof FEATURE_FLAGS>(\n flag: F,\n value: FEATURE_FLAGS[F],\n) => {\n try {\n featureFlags = {\n ...(featureFlags || DEFAULT_FEATURE_FLAGS),\n [flag]: value,\n };\n localStorage.setItem(\n FEATURE_FLAGS_STORAGE_KEY,\n JSON.stringify(featureFlags),\n );\n } catch (e) {\n console.error(\"unable to set feature flag\", e);\n }\n};\n", "import { sanitizeUrl } from \"@braintree/sanitize-url\";\n\nimport { escapeDoubleQuotes } from \"./utils\";\n\nexport const normalizeLink = (link: string) => {\n link = link.trim();\n if (!link) {\n return link;\n }\n return sanitizeUrl(escapeDoubleQuotes(link));\n};\n\nexport const isLocalLink = (link: string | null) => {\n return !!(link?.includes(location.origin) || link?.startsWith(\"/\"));\n};\n\n/**\n * Returns URL sanitized and safe for usage in places such as\n * iframe's src attribute or <a> href attributes.\n */\nexport const toValidURL = (link: string) => {\n link = normalizeLink(link);\n\n // make relative links into fully-qualified urls\n if (link.startsWith(\"/\")) {\n return `${location.origin}${link}`;\n }\n\n try {\n new URL(link);\n } catch {\n // if link does not parse as URL, assume invalid and return blank page\n return \"about:blank\";\n }\n\n return link;\n};\n", "import type { UnsubscribeCallback } from \"@excalidraw/excalidraw/types\";\n\ntype Subscriber<T extends any[]> = (...payload: T) => void;\n\nexport class Emitter<T extends any[] = []> {\n public subscribers: Subscriber<T>[] = [];\n\n /**\n * Attaches subscriber\n *\n * @returns unsubscribe function\n */\n on(...handlers: Subscriber<T>[] | Subscriber<T>[][]): UnsubscribeCallback {\n const _handlers = handlers\n .flat()\n .filter((item) => typeof item === \"function\");\n\n this.subscribers.push(..._handlers);\n\n return () => this.off(_handlers);\n }\n\n once(...handlers: Subscriber<T>[] | Subscriber<T>[][]): UnsubscribeCallback {\n const _handlers = handlers\n .flat()\n .filter((item) => typeof item === \"function\");\n\n _handlers.push(() => detach());\n\n const detach = this.on(..._handlers);\n return detach;\n }\n\n off(...handlers: Subscriber<T>[] | Subscriber<T>[][]) {\n const _handlers = handlers.flat();\n this.subscribers = this.subscribers.filter(\n (handler) => !_handlers.includes(handler),\n );\n }\n\n trigger(...payload: T) {\n for (const handler of this.subscribers) {\n handler(...payload);\n }\n return this;\n }\n\n clear() {\n this.subscribers = [];\n }\n}\n", "import { nanoid } from \"nanoid\";\n\nimport {\n IMAGE_MIME_TYPES,\n MIME_TYPES,\n bytesToHexString,\n isPromiseLike,\n} from \"@excalidraw/common\";\n\nimport type { ValueOf } from \"@excalidraw/common/utility-types\";\nimport type { ExcalidrawElement, FileId } from \"@excalidraw/element/types\";\n\nimport { cleanAppStateForExport } from \"../appState\";\n\nimport { CanvasError, ImageSceneDataError } from \"../errors\";\nimport { calculateScrollCenter } from \"../scene\";\nimport { decodeSvgBase64Payload } from \"../scene/export\";\n\nimport { base64ToString, stringToBase64, toByteString } from \"./encode\";\nimport { nativeFileSystemSupported } from \"./filesystem\";\nimport { isValidExcalidrawData, isValidLibrary } from \"./json\";\nimport {\n restoreAppState,\n restoreElements,\n restoreLibraryItems,\n} from \"./restore\";\n\nimport type { AppState, DataURL, LibraryItem } from \"../types\";\n\nimport type { FileSystemHandle } from \"browser-fs-access\";\nimport type { ImportedLibraryData } from \"./types\";\n\nconst parseFileContents = async (blob: Blob | File): Promise<string> => {\n let contents: string;\n\n if (blob.type === MIME_TYPES.png) {\n try {\n return await (await import(\"./image\")).decodePngMetadata(blob);\n } catch (error: any) {\n if (error.message === \"INVALID\") {\n throw new ImageSceneDataError(\n \"Image doesn't contain scene\",\n \"IMAGE_NOT_CONTAINS_SCENE_DATA\",\n );\n } else {\n throw new ImageSceneDataError(\"Error: cannot restore image\");\n }\n }\n } else {\n if (\"text\" in Blob) {\n contents = await blob.text();\n } else {\n contents = await new Promise((resolve) => {\n const reader = new FileReader();\n reader.readAsText(blob, \"utf8\");\n reader.onloadend = () => {\n if (reader.readyState === FileReader.DONE) {\n resolve(reader.result as string);\n }\n };\n });\n }\n if (blob.type === MIME_TYPES.svg) {\n try {\n return decodeSvgBase64Payload({\n svg: contents,\n });\n } catch (error: any) {\n if (error.message === \"INVALID\") {\n throw new ImageSceneDataError(\n \"Image doesn't contain scene\",\n \"IMAGE_NOT_CONTAINS_SCENE_DATA\",\n );\n } else {\n throw new ImageSceneDataError(\"Error: cannot restore image\");\n }\n }\n }\n }\n return contents;\n};\n\nexport const getMimeType = (blob: Blob | string): string => {\n let name: string;\n if (typeof blob === \"string\") {\n name = blob;\n } else {\n if (blob.type) {\n return blob.type;\n }\n name = blob.name || \"\";\n }\n if (/\\.(excalidraw|json)$/.test(name)) {\n return MIME_TYPES.json;\n } else if (/\\.png$/.test(name)) {\n return MIME_TYPES.png;\n } else if (/\\.jpe?g$/.test(name)) {\n return MIME_TYPES.jpg;\n } else if (/\\.svg$/.test(name)) {\n return MIME_TYPES.svg;\n } else if (/\\.excalidrawlib$/.test(name)) {\n return MIME_TYPES.excalidrawlib;\n }\n return \"\";\n};\n\nexport const getFileHandleType = (handle: FileSystemHandle | null) => {\n if (!handle) {\n return null;\n }\n\n return handle.name.match(/\\.(json|excalidraw|png|svg)$/)?.[1] || null;\n};\n\nexport const isImageFileHandleType = (\n type: string | null,\n): type is \"png\" | \"svg\" => {\n return type === \"png\" || type === \"svg\";\n};\n\nexport const isImageFileHandle = (handle: FileSystemHandle | null) => {\n const type = getFileHandleType(handle);\n return type === \"png\" || type === \"svg\";\n};\n\nexport const isSupportedImageFileType = (type: string | null | undefined) => {\n return !!type && (Object.values(IMAGE_MIME_TYPES) as string[]).includes(type);\n};\n\nexport const isSupportedImageFile = (\n blob: Blob | null | undefined,\n): blob is Blob & { type: ValueOf<typeof IMAGE_MIME_TYPES> } => {\n const { type } = blob || {};\n return isSupportedImageFileType(type);\n};\n\nexport const loadSceneOrLibraryFromBlob = async (\n blob: Blob | File,\n /** @see restore.localAppState */\n localAppState: AppState | null,\n localElements: readonly ExcalidrawElement[] | null,\n /** FileSystemHandle. Defaults to `blob.handle` if defined, otherwise null. */\n fileHandle?: FileSystemHandle | null,\n) => {\n const contents = await parseFileContents(blob);\n let data;\n try {\n try {\n data = JSON.parse(contents);\n } catch (error: any) {\n if (isSupportedImageFile(blob)) {\n throw new ImageSceneDataError(\n \"Image doesn't contain scene\",\n \"IMAGE_NOT_CONTAINS_SCENE_DATA\",\n );\n }\n throw error;\n }\n if (isValidExcalidrawData(data)) {\n return {\n type: MIME_TYPES.excalidraw,\n data: {\n elements: restoreElements(data.elements, localElements, {\n repairBindings: true,\n deleteInvisibleElements: true,\n }),\n appState: restoreAppState(\n {\n theme: localAppState?.theme,\n fileHandle: fileHandle || blob.handle || null,\n ...cleanAppStateForExport(data.appState || {}),\n ...(localAppState\n ? calculateScrollCenter(data.elements || [], localAppState)\n : {}),\n },\n localAppState,\n ),\n files: data.files || {},\n },\n };\n } else if (isValidLibrary(data)) {\n return {\n type: MIME_TYPES.excalidrawlib,\n data,\n };\n }\n throw new Error(\"Error: invalid file\");\n } catch (error: any) {\n if (error instanceof ImageSceneDataError) {\n throw error;\n }\n throw new Error(\"Error: invalid file\");\n }\n};\n\nexport const loadFromBlob = async (\n blob: Blob,\n /** @see restore.localAppState */\n localAppState: AppState | null,\n localElements: readonly ExcalidrawElement[] | null,\n /** FileSystemHandle. Defaults to `blob.handle` if defined, otherwise null. */\n fileHandle?: FileSystemHandle | null,\n) => {\n const ret = await loadSceneOrLibraryFromBlob(\n blob,\n localAppState,\n localElements,\n fileHandle,\n );\n if (ret.type !== MIME_TYPES.excalidraw) {\n throw new Error(\"Error: invalid file\");\n }\n return ret.data;\n};\n\nexport const parseLibraryJSON = (\n json: string,\n defaultStatus: LibraryItem[\"status\"] = \"unpublished\",\n) => {\n const data: ImportedLibraryData | undefined = JSON.parse(json);\n if (!isValidLibrary(data)) {\n throw new Error(\"Invalid library\");\n }\n const libraryItems = data.libraryItems || data.library;\n return restoreLibraryItems(libraryItems, defaultStatus);\n};\n\nexport const loadLibraryFromBlob = async (\n blob: Blob,\n defaultStatus: LibraryItem[\"status\"] = \"unpublished\",\n) => {\n return parseLibraryJSON(await parseFileContents(blob), defaultStatus);\n};\n\nexport const canvasToBlob = async (\n canvas: HTMLCanvasElement | Promise<HTMLCanvasElement>,\n): Promise<Blob> => {\n return new Promise(async (resolve, reject) => {\n try {\n if (isPromiseLike(canvas)) {\n canvas = await canvas;\n }\n canvas.toBlob((blob) => {\n if (!blob) {\n return reject(\n new CanvasError(\"Error: Canvas too big\", \"CANVAS_POSSIBLY_TOO_BIG\"),\n );\n }\n resolve(blob);\n });\n } catch (error: any) {\n reject(error);\n }\n });\n};\n\n/** generates SHA-1 digest from supplied file (if not supported, falls back\n to a 40-char base64 random id) */\nexport const generateIdFromFile = async (file: File): Promise<FileId> => {\n try {\n const hashBuffer = await window.crypto.subtle.digest(\n \"SHA-1\",\n await blobToArrayBuffer(file),\n );\n return bytesToHexString(new Uint8Array(hashBuffer)) as FileId;\n } catch (error: any) {\n console.error(error);\n // length 40 to align with the HEX length of SHA-1 (which is 160 bit)\n return nanoid(40) as FileId;\n }\n};\n\n/** async. For sync variant, use getDataURL_sync */\nexport const getDataURL = async (file: Blob | File): Promise<DataURL> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataURL = reader.result as DataURL;\n resolve(dataURL);\n };\n reader.onerror = (error) => reject(error);\n reader.readAsDataURL(file);\n });\n};\n\nexport const getDataURL_sync = (\n data: string | Uint8Array | ArrayBuffer,\n mimeType: ValueOf<typeof MIME_TYPES>,\n): DataURL => {\n return `data:${mimeType};base64,${stringToBase64(\n toByteString(data),\n true,\n )}` as DataURL;\n};\n\nexport const dataURLToFile = (dataURL: DataURL, filename = \"\") => {\n const dataIndexStart = dataURL.indexOf(\",\");\n const byteString = atob(dataURL.slice(dataIndexStart + 1));\n const mimeType = dataURL.slice(0, dataIndexStart).split(\":\")[1].split(\";\")[0];\n\n const ab = new ArrayBuffer(byteString.length);\n const ia = new Uint8Array(ab);\n for (let i = 0; i < byteString.length; i++) {\n ia[i] = byteString.charCodeAt(i);\n }\n return new File([ab], filename, { type: mimeType });\n};\n\nexport const dataURLToString = (dataURL: DataURL) => {\n return base64ToString(dataURL.slice(dataURL.indexOf(\",\") + 1));\n};\n\nexport const resizeImageFile = async (\n file: File,\n opts: {\n /** undefined indicates auto */\n outputType?: typeof MIME_TYPES[\"jpg\"];\n maxWidthOrHeight: number;\n },\n): Promise<File> => {\n // SVG files shouldn't a can't be resized\n if (file.type === MIME_TYPES.svg) {\n return file;\n }\n\n const [pica, imageBlobReduce] = await Promise.all([\n import(\"pica\").then((res) => res.default),\n // a wrapper for pica for better API\n import(\"image-blob-reduce\").then((res) => res.default),\n ]);\n\n // CRA's minification settings break pica in WebWorkers, so let's disable\n // them for now\n // https://github.com/nodeca/image-blob-reduce/issues/21#issuecomment-757365513\n const reduce = imageBlobReduce({\n pica: pica({ features: [\"js\", \"wasm\"] }),\n });\n\n if (opts.outputType) {\n const { outputType } = opts;\n reduce._create_blob = function (env) {\n return this.pica.toBlob(env.out_canvas, outputType, 0.8).then((blob) => {\n env.out_blob = blob;\n return env;\n });\n };\n }\n\n if (!isSupportedImageFile(file)) {\n throw new Error(\"Error: unsupported file type\", { cause: \"UNSUPPORTED\" });\n }\n\n return new File(\n [await reduce.toBlob(file, { max: opts.maxWidthOrHeight, alpha: true })],\n file.name,\n {\n type: opts.outputType || file.type,\n },\n );\n};\n\nexport const SVGStringToFile = (SVGString: string, filename: string = \"\") => {\n return new File([new TextEncoder().encode(SVGString)], filename, {\n type: MIME_TYPES.svg,\n }) as File & { type: typeof MIME_TYPES.svg };\n};\n\nexport const ImageURLToFile = async (\n imageUrl: string,\n filename: string = \"\",\n): Promise<File | undefined> => {\n let response;\n try {\n response = await fetch(imageUrl);\n } catch (error: any) {\n throw new Error(\"Error: failed to fetch image\", { cause: \"FETCH_ERROR\" });\n }\n\n if (!response.ok) {\n throw new Error(\"Error: failed to fetch image\", { cause: \"FETCH_ERROR\" });\n }\n\n const blob = await response.blob();\n\n if (blob.type && isSupportedImageFile(blob)) {\n const name = filename || blob.name || \"\";\n return new File([blob], name, { type: blob.type });\n }\n\n throw new Error(\"Error: unsupported file type\", { cause: \"UNSUPPORTED\" });\n};\n\nexport const getFileHandle = async (\n event: DragEvent | React.DragEvent | DataTransferItem,\n): Promise<FileSystemHandle | null> => {\n if (nativeFileSystemSupported) {\n try {\n const dataTransferItem =\n event instanceof DataTransferItem\n ? event\n : (event as DragEvent).dataTransfer?.items?.[0];\n\n const handle: FileSystemHandle | null =\n (await (dataTransferItem as any).getAsFileSystemHandle()) || null;\n\n return handle;\n } catch (error: any) {\n console.warn(error.name, error.message);\n return null;\n }\n }\n return null;\n};\n\n/**\n * attempts to detect if a buffer is a valid image by checking its leading bytes\n */\nconst getActualMimeTypeFromImage = async (file: Blob | File) => {\n let mimeType: ValueOf<\n Pick<typeof MIME_TYPES, \"png\" | \"jpg\" | \"gif\" | \"webp\">\n > | null = null;\n\n const leadingBytes = [\n ...new Uint8Array(await blobToArrayBuffer(file.slice(0, 15))),\n ].join(\" \");\n\n // uint8 leading bytes\n const bytes = {\n // https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header\n png: /^137 80 78 71 13 10 26 10\\b/,\n // https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure\n // jpg is a bit wonky. Checking the first three bytes should be enough,\n // but may yield false positives. (https://stackoverflow.com/a/23360709/927631)\n jpg: /^255 216 255\\b/,\n // https://en.wikipedia.org/wiki/GIF#Example_GIF_file\n gif: /^71 73 70 56 57 97\\b/,\n // 4 bytes for RIFF + 4 bytes for chunk size + WEBP identifier\n webp: /^82 73 70 70 \\d+ \\d+ \\d+ \\d+ 87 69 66 80 86 80 56\\b/,\n };\n\n for (const type of Object.keys(bytes) as (keyof typeof bytes)[]) {\n if (leadingBytes.match(bytes[type])) {\n mimeType = MIME_TYPES[type];\n break;\n }\n }\n\n return mimeType || file.type || null;\n};\n\nexport const createFile = (\n blob: File | Blob | ArrayBuffer,\n mimeType: string,\n name: string | undefined,\n) => {\n return new File([blob], name || \"\", {\n type: mimeType,\n });\n};\n\nconst normalizedFileSymbol = Symbol(\"fileNormalized\");\n\n/** attempts to detect correct mimeType if none is set, or if an image\n * has an incorrect extension.\n * Note: doesn't handle missing .excalidraw/.excalidrawlib extension */\nexport const normalizeFile = async (file: File) => {\n // to prevent double normalization (perf optim)\n if ((file as any)[normalizedFileSymbol]) {\n return file;\n }\n\n if (file?.name?.endsWith(\".excalidrawlib\")) {\n file = createFile(file, MIME_TYPES.excalidrawlib, file.name);\n } else if (file?.name?.endsWith(\".excalidraw\")) {\n file = createFile(file, MIME_TYPES.excalidraw, file.name);\n } else if (!file.type || file.type?.startsWith(\"image/\")) {\n // when the file is an image, make sure the extension corresponds to the\n // actual mimeType (this is an edge case, but happens - especially\n // with AI generated images)\n const mimeType = await getActualMimeTypeFromImage(file);\n if (mimeType && mimeType !== file.type) {\n file = createFile(file, mimeType, file.name);\n }\n }\n\n (file as any)[normalizedFileSymbol] = true;\n\n return file;\n};\n\nexport const blobToArrayBuffer = (blob: Blob): Promise<ArrayBuffer> => {\n if (\"arrayBuffer\" in blob) {\n return blob.arrayBuffer();\n }\n // Safari\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (event) => {\n if (!event.target?.result) {\n return reject(new Error(\"Couldn't convert blob to ArrayBuffer\"));\n }\n resolve(event.target.result as ArrayBuffer);\n };\n reader.readAsArrayBuffer(blob);\n });\n};\n", "import {\n COLOR_PALETTE,\n ARROW_TYPE,\n DEFAULT_ELEMENT_PROPS,\n DEFAULT_FONT_FAMILY,\n DEFAULT_FONT_SIZE,\n DEFAULT_TEXT_ALIGN,\n DEFAULT_GRID_SIZE,\n EXPORT_SCALES,\n STATS_PANELS,\n THEME,\n DEFAULT_GRID_STEP,\n isTestEnv,\n} from \"@excalidraw/common\";\n\nimport type { AppState, NormalizedZoomValue } from \"./types\";\n\nconst defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio)\n ? devicePixelRatio\n : 1;\n\nexport const getDefaultAppState = (): Omit<\n AppState,\n \"offsetTop\" | \"offsetLeft\" | \"width\" | \"height\"\n> => {\n return {\n showWelcomeScreen: false,\n theme: THEME.LIGHT,\n collaborators: new Map(),\n currentChartType: \"bar\",\n currentItemBackgroundColor: DEFAULT_ELEMENT_PROPS.backgroundColor,\n currentItemEndArrowhead: \"arrow\",\n currentItemFillStyle: DEFAULT_ELEMENT_PROPS.fillStyle,\n currentItemFontFamily: DEFAULT_FONT_FAMILY,\n currentItemFontSize: DEFAULT_FONT_SIZE,\n currentItemOpacity: DEFAULT_ELEMENT_PROPS.opacity,\n currentItemRoughness: DEFAULT_ELEMENT_PROPS.roughness,\n currentItemStartArrowhead: null,\n currentItemStrokeColor: DEFAULT_ELEMENT_PROPS.strokeColor,\n currentItemRoundness: isTestEnv() ? \"sharp\" : \"round\",\n currentItemArrowType: ARROW_TYPE.round,\n currentItemStrokeStyle: DEFAULT_ELEMENT_PROPS.strokeStyle,\n currentItemStrokeWidth: DEFAULT_ELEMENT_PROPS.strokeWidth,\n currentItemTextAlign: DEFAULT_TEXT_ALIGN,\n currentHoveredFontFamily: null,\n cursorButton: \"up\",\n activeEmbeddable: null,\n newElement: null,\n editingTextElement: null,\n editingGroupId: null,\n activeTool: {\n type: \"selection\",\n customType: null,\n locked: DEFAULT_ELEMENT_PROPS.locked,\n fromSelection: false,\n lastActiveTool: null,\n },\n preferredSelectionTool: {\n type: \"selection\",\n initialized: false,\n },\n penMode: false,\n penDetected: false,\n errorMessage: null,\n exportBackground: true,\n exportScale: defaultExportScale,\n exportEmbedScene: false,\n exportWithDarkMode: false,\n fileHandle: null,\n gridSize: DEFAULT_GRID_SIZE,\n gridStep: DEFAULT_GRID_STEP,\n gridModeEnabled: false,\n isBindingEnabled: true,\n defaultSidebarDockedPreference: false,\n isLoading: false,\n isResizing: false,\n isRotating: false,\n lastPointerDownWith: \"mouse\",\n multiElement: null,\n name: null,\n contextMenu: null,\n openMenu: null,\n openPopup: null,\n openSidebar: null,\n openDialog: null,\n pasteDialog: { shown: false, data: null },\n previousSelectedElementIds: {},\n resizingElement: null,\n scrolledOutside: false,\n scrollX: 0,\n scrollY: 0,\n selectedElementIds: {},\n hoveredElementIds: {},\n selectedGroupIds: {},\n selectedElementsAreBeingDragged: false,\n selectionElement: null,\n shouldCacheIgnoreZoom: false,\n stats: {\n open: false,\n panels: STATS_PANELS.generalStats | STATS_PANELS.elementProperties,\n },\n startBoundElement: null,\n suggestedBinding: null,\n frameRendering: { enabled: true, clip: true, name: true, outline: true },\n frameToHighlight: null,\n editingFrame: null,\n elementsToHighlight: null,\n toast: null,\n viewBackgroundColor: COLOR_PALETTE.white,\n zenModeEnabled: false,\n zoom: {\n value: 1 as NormalizedZoomValue,\n },\n viewModeEnabled: false,\n showHyperlinkPopup: false,\n selectedLinearElement: null,\n snapLines: [],\n originSnapOffset: {\n x: 0,\n y: 0,\n },\n objectsSnapModeEnabled: false,\n userToFollow: null,\n followedBy: new Set(),\n isCropping: false,\n croppingElementId: null,\n searchMatches: null,\n lockedMultiSelections: {},\n activeLockedId: null,\n bindMode: \"orbit\",\n hideAnnotations: false,\n };\n};\n\n/**\n * Config containing all AppState keys. Used to determine whether given state\n * prop should be stripped when exporting to given storage type.\n */\nconst APP_STATE_STORAGE_CONF = (<\n Values extends {\n /** whether to keep when storing to browser storage (localStorage/IDB) */\n browser: boolean;\n /** whether to keep when exporting to file/database */\n export: boolean;\n /** server (shareLink/collab/...) */\n server: boolean;\n },\n T extends Record<keyof AppState, Values>,\n>(config: { [K in keyof T]: K extends keyof AppState ? T[K] : never }) =>\n config)({\n showWelcomeScreen: { browser: true, export: false, server: false },\n theme: { browser: true, export: false, server: false },\n collaborators: { browser: false, export: false, server: false },\n currentChartType: { browser: true, export: false, server: false },\n currentItemBackgroundColor: { browser: true, export: false, server: false },\n currentItemEndArrowhead: { browser: true, export: false, server: false },\n currentItemFillStyle: { browser: true, export: false, server: false },\n currentItemFontFamily: { browser: true, export: false, server: false },\n currentItemFontSize: { browser: true, export: false, server: false },\n currentItemRoundness: {\n browser: true,\n export: false,\n server: false,\n },\n currentItemArrowType: {\n browser: true,\n export: false,\n server: false,\n },\n currentItemOpacity: { browser: true, export: false, server: false },\n currentItemRoughness: { browser: true, export: false, server: false },\n currentItemStartArrowhead: { browser: true, export: false, server: false },\n currentItemStrokeColor: { browser: true, export: false, server: false },\n currentItemStrokeStyle: { browser: true, export: false, server: false },\n currentItemStrokeWidth: { browser: true, export: false, server: false },\n currentItemTextAlign: { browser: true, export: false, server: false },\n currentHoveredFontFamily: { browser: false, export: false, server: false },\n cursorButton: { browser: true, export: false, server: false },\n activeEmbeddable: { browser: false, export: false, server: false },\n newElement: { browser: false, export: false, server: false },\n editingTextElement: { browser: false, export: false, server: false },\n editingGroupId: { browser: true, export: false, server: false },\n activeTool: { browser: true, export: false, server: false },\n preferredSelectionTool: { browser: true, export: false, server: false },\n penMode: { browser: true, export: false, server: false },\n penDetected: { browser: true, export: false, server: false },\n errorMessage: { browser: false, export: false, server: false },\n exportBackground: { browser: true, export: false, server: false },\n exportEmbedScene: { browser: true, export: false, server: false },\n exportScale: { browser: true, export: false, server: false },\n exportWithDarkMode: { browser: true, export: false, server: false },\n fileHandle: { browser: false, export: false, server: false },\n gridSize: { browser: true, export: true, server: true },\n gridStep: { browser: true, export: true, server: true },\n gridModeEnabled: { browser: true, export: true, server: true },\n height: { browser: false, export: false, server: false },\n isBindingEnabled: { browser: false, export: false, server: false },\n defaultSidebarDockedPreference: {\n browser: true,\n export: false,\n server: false,\n },\n isLoading: { browser: false, export: false, server: false },\n isResizing: { browser: false, export: false, server: false },\n isRotating: { browser: false, export: false, server: false },\n lastPointerDownWith: { browser: true, export: false, server: false },\n multiElement: { browser: false, export: false, server: false },\n name: { browser: true, export: false, server: false },\n offsetLeft: { browser: false, export: false, server: false },\n offsetTop: { browser: false, export: false, server: false },\n contextMenu: { browser: false, export: false, server: false },\n openMenu: { browser: true, export: false, server: false },\n openPopup: { browser: false, export: false, server: false },\n openSidebar: { browser: true, export: false, server: false },\n openDialog: { browser: false, export: false, server: false },\n pasteDialog: { browser: false, export: false, server: false },\n previousSelectedElementIds: { browser: true, export: false, server: false },\n resizingElement: { browser: false, export: false, server: false },\n scrolledOutside: { browser: true, export: false, server: false },\n scrollX: { browser: true, export: false, server: false },\n scrollY: { browser: true, export: false, server: false },\n selectedElementIds: { browser: true, export: false, server: false },\n hoveredElementIds: { browser: false, export: false, server: false },\n selectedGroupIds: { browser: true, export: false, server: false },\n selectedElementsAreBeingDragged: {\n browser: false,\n export: false,\n server: false,\n },\n selectionElement: { browser: false, export: false, server: false },\n shouldCacheIgnoreZoom: { browser: true, export: false, server: false },\n stats: { browser: true, export: false, server: false },\n startBoundElement: { browser: false, export: false, server: false },\n suggestedBinding: { browser: false, export: false, server: false },\n frameRendering: { browser: false, export: false, server: false },\n frameToHighlight: { browser: false, export: false, server: false },\n editingFrame: { browser: false, export: false, server: false },\n elementsToHighlight: { browser: false, export: false, server: false },\n toast: { browser: false, export: false, server: false },\n viewBackgroundColor: { browser: true, export: true, server: true },\n width: { browser: false, export: false, server: false },\n zenModeEnabled: { browser: true, export: false, server: false },\n zoom: { browser: true, export: false, server: false },\n viewModeEnabled: { browser: false, export: false, server: false },\n showHyperlinkPopup: { browser: false, export: false, server: false },\n selectedLinearElement: { browser: true, export: false, server: false },\n snapLines: { browser: false, export: false, server: false },\n originSnapOffset: { browser: false, export: false, server: false },\n objectsSnapModeEnabled: { browser: true, export: false, server: false },\n userToFollow: { browser: false, export: false, server: false },\n followedBy: { browser: false, export: false, server: false },\n isCropping: { browser: false, export: false, server: false },\n croppingElementId: { browser: false, export: false, server: false },\n searchMatches: { browser: false, export: false, server: false },\n lockedMultiSelections: { browser: true, export: true, server: true },\n activeLockedId: { browser: false, export: false, server: false },\n bindMode: { browser: true, export: false, server: false },\n hideAnnotations: { browser: true, export: false, server: false },\n});\n\nconst _clearAppStateForStorage = <\n ExportType extends \"export\" | \"browser\" | \"server\",\n>(\n appState: Partial<AppState>,\n exportType: ExportType,\n) => {\n type ExportableKeys = {\n [K in keyof typeof APP_STATE_STORAGE_CONF]: typeof APP_STATE_STORAGE_CONF[K][ExportType] extends true\n ? K\n : never;\n }[keyof typeof APP_STATE_STORAGE_CONF];\n const stateForExport = {} as { [K in ExportableKeys]?: typeof appState[K] };\n for (const key of Object.keys(appState) as (keyof typeof appState)[]) {\n const propConfig = APP_STATE_STORAGE_CONF[key];\n if (propConfig?.[exportType]) {\n const nextValue = appState[key];\n\n // https://github.com/microsoft/TypeScript/issues/31445\n (stateForExport as any)[key] = nextValue;\n }\n }\n return stateForExport;\n};\n\nexport const clearAppStateForLocalStorage = (appState: Partial<AppState>) => {\n return _clearAppStateForStorage(appState, \"browser\");\n};\n\nexport const cleanAppStateForExport = (appState: Partial<AppState>) => {\n return _clearAppStateForStorage(appState, \"export\");\n};\n\nexport const clearAppStateForDatabase = (appState: Partial<AppState>) => {\n return _clearAppStateForStorage(appState, \"server\");\n};\n\nexport const isEraserActive = ({\n activeTool,\n}: {\n activeTool: AppState[\"activeTool\"];\n}) => activeTool.type === \"eraser\";\n\nexport const isHandToolActive = ({\n activeTool,\n}: {\n activeTool: AppState[\"activeTool\"];\n}) => {\n return activeTool.type === \"hand\";\n};\n", "type CANVAS_ERROR_NAMES = \"CANVAS_ERROR\" | \"CANVAS_POSSIBLY_TOO_BIG\";\n\nexport class CanvasError extends Error {\n constructor(\n message: string = \"Couldn't export canvas.\",\n name: CANVAS_ERROR_NAMES = \"CANVAS_ERROR\",\n ) {\n super();\n this.name = name;\n this.message = message;\n }\n}\n\nexport class AbortError extends DOMException {\n constructor(message: string = \"Request Aborted\") {\n super(message, \"AbortError\");\n }\n}\n\ntype ImageSceneDataErrorCode =\n | \"IMAGE_NOT_CONTAINS_SCENE_DATA\"\n | \"IMAGE_SCENE_DATA_ERROR\";\n\nexport class ImageSceneDataError extends Error {\n public code;\n constructor(\n message = \"Image Scene Data Error\",\n code: ImageSceneDataErrorCode = \"IMAGE_SCENE_DATA_ERROR\",\n ) {\n super(message);\n this.name = \"EncodingError\";\n this.code = code;\n }\n}\n\ntype WorkerErrorCodes = \"WORKER_URL_NOT_DEFINED\" | \"WORKER_IN_THE_MAIN_CHUNK\";\n\nexport class WorkerUrlNotDefinedError extends Error {\n public code;\n constructor(\n message = \"Worker URL is not defined!\",\n code: WorkerErrorCodes = \"WORKER_URL_NOT_DEFINED\",\n ) {\n super(message);\n this.name = \"WorkerUrlNotDefinedError\";\n this.code = code;\n }\n}\n\nexport class WorkerInTheMainChunkError extends Error {\n public code;\n constructor(\n message = \"Worker has to be in a separate chunk!\",\n code: WorkerErrorCodes = \"WORKER_IN_THE_MAIN_CHUNK\",\n ) {\n super(message);\n this.name = \"WorkerInTheMainChunkError\";\n this.code = code;\n }\n}\n\n/**\n * Use this for generic, handled errors, so you can check against them\n * and rethrow if needed\n */\nexport class ExcalidrawError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ExcalidrawError\";\n }\n}\n", "import rough from \"roughjs/bin/rough\";\n\nimport {\n arrayToMap,\n type Bounds,\n invariant,\n rescalePoints,\n sizeOf,\n} from \"@excalidraw/common\";\n\nimport {\n degreesToRadians,\n lineSegment,\n pointDistance,\n pointFrom,\n pointFromArray,\n pointRotateRads,\n} from \"@excalidraw/math\";\n\nimport { getCurvePathOps } from \"@excalidraw/utils/shape\";\n\nimport { pointsOnBezierCurves } from \"points-on-curve\";\n\nimport type {\n Curve,\n Degrees,\n GlobalPoint,\n LineSegment,\n LocalPoint,\n Radians,\n} from \"@excalidraw/math\";\n\nimport type { AppState } from \"@excalidraw/excalidraw/types\";\n\nimport type { Mutable } from \"@excalidraw/common/utility-types\";\n\nimport { generateRoughOptions } from \"./shape\";\nimport { ShapeCache } from \"./shape\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\nimport {\n isArrowElement,\n isBoundToContainer,\n isFreeDrawElement,\n isLinearElement,\n isLineElement,\n isTextElement,\n} from \"./typeChecks\";\n\nimport { getElementShape } from \"./shape\";\n\nimport {\n deconstructDiamondElement,\n deconstructRectanguloidElement,\n} from \"./utils\";\n\nimport type { Drawable, Op } from \"roughjs/bin/core\";\nimport type { Point as RoughPoint } from \"roughjs/bin/geometry\";\nimport type {\n Arrowhead,\n ElementsMap,\n ElementsMapOrArray,\n ExcalidrawElement,\n ExcalidrawEllipseElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawLinearElement,\n ExcalidrawRectanguloidElement,\n ExcalidrawTextElementWithContainer,\n NonDeleted,\n} from \"./types\";\n\nexport type RectangleBox = {\n x: number;\n y: number;\n width: number;\n height: number;\n angle: number;\n};\n\ntype MaybeQuadraticSolution = [number | null, number | null] | false;\n\nexport type SceneBounds = readonly [\n sceneX: number,\n sceneY: number,\n sceneX2: number,\n sceneY2: number,\n];\n\nexport class ElementBounds {\n private static boundsCache = new WeakMap<\n ExcalidrawElement,\n {\n bounds: Bounds;\n version: ExcalidrawElement[\"version\"];\n }\n >();\n private static nonRotatedBoundsCache = new WeakMap<\n ExcalidrawElement,\n {\n bounds: Bounds;\n version: ExcalidrawElement[\"version\"];\n }\n >();\n\n static getBounds(\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n nonRotated: boolean = false,\n ) {\n const cachedBounds =\n nonRotated && element.angle !== 0\n ? ElementBounds.nonRotatedBoundsCache.get(element)\n : ElementBounds.boundsCache.get(element);\n\n if (\n cachedBounds?.version &&\n cachedBounds.version === element.version &&\n // we don't invalidate cache when we update containers and not labels,\n // which is causing problems down the line. Fix TBA.\n !isBoundToContainer(element)\n ) {\n return cachedBounds.bounds;\n }\n\n if (nonRotated && element.angle !== 0) {\n const nonRotatedBounds = ElementBounds.calculateBounds(\n {\n ...element,\n angle: 0 as Radians,\n },\n elementsMap,\n );\n ElementBounds.nonRotatedBoundsCache.set(element, {\n version: element.version,\n bounds: nonRotatedBounds,\n });\n\n return nonRotatedBounds;\n }\n\n const bounds = ElementBounds.calculateBounds(element, elementsMap);\n\n ElementBounds.boundsCache.set(element, {\n version: element.version,\n bounds,\n });\n\n return bounds;\n }\n\n private static calculateBounds(\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n ): Bounds {\n let bounds: Bounds;\n\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\n element,\n elementsMap,\n );\n if (isFreeDrawElement(element)) {\n const [minX, minY, maxX, maxY] = getBoundsFromPoints(\n element.points.map(([x, y]) =>\n pointRotateRads(\n pointFrom(x, y),\n pointFrom(cx - element.x, cy - element.y),\n element.angle,\n ),\n ),\n );\n\n return [\n minX + element.x,\n minY + element.y,\n maxX + element.x,\n maxY + element.y,\n ];\n } else if (isLinearElement(element)) {\n bounds = getLinearElementRotatedBounds(element, cx, cy, elementsMap);\n } else if (element.type === \"diamond\") {\n const [x11, y11] = pointRotateRads(\n pointFrom(cx, y1),\n pointFrom(cx, cy),\n element.angle,\n );\n const [x12, y12] = pointRotateRads(\n pointFrom(cx, y2),\n pointFrom(cx, cy),\n element.angle,\n );\n const [x22, y22] = pointRotateRads(\n pointFrom(x1, cy),\n pointFrom(cx, cy),\n element.angle,\n );\n const [x21, y21] = pointRotateRads(\n pointFrom(x2, cy),\n pointFrom(cx, cy),\n element.angle,\n );\n const minX = Math.min(x11, x12, x22, x21);\n const minY = Math.min(y11, y12, y22, y21);\n const maxX = Math.max(x11, x12, x22, x21);\n const maxY = Math.max(y11, y12, y22, y21);\n bounds = [minX, minY, maxX, maxY];\n } else if (element.type === \"ellipse\") {\n const w = (x2 - x1) / 2;\n const h = (y2 - y1) / 2;\n const cos = Math.cos(element.angle);\n const sin = Math.sin(element.angle);\n const ww = Math.hypot(w * cos, h * sin);\n const hh = Math.hypot(h * cos, w * sin);\n bounds = [cx - ww, cy - hh, cx + ww, cy + hh];\n } else {\n const [x11, y11] = pointRotateRads(\n pointFrom(x1, y1),\n pointFrom(cx, cy),\n element.angle,\n );\n const [x12, y12] = pointRotateRads(\n pointFrom(x1, y2),\n pointFrom(cx, cy),\n element.angle,\n );\n const [x22, y22] = pointRotateRads(\n pointFrom(x2, y2),\n pointFrom(cx, cy),\n element.angle,\n );\n const [x21, y21] = pointRotateRads(\n pointFrom(x2, y1),\n pointFrom(cx, cy),\n element.angle,\n );\n const minX = Math.min(x11, x12, x22, x21);\n const minY = Math.min(y11, y12, y22, y21);\n const maxX = Math.max(x11, x12, x22, x21);\n const maxY = Math.max(y11, y12, y22, y21);\n bounds = [minX, minY, maxX, maxY];\n }\n\n return bounds;\n }\n}\n\n// Scene -> Scene coords, but in x1,x2,y1,y2 format.\n//\n// If the element is created from right to left, the width is going to be negative\n// This set of functions retrieves the absolute position of the 4 points.\nexport const getElementAbsoluteCoords = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n includeBoundText: boolean = false,\n): [number, number, number, number, number, number] => {\n if (isFreeDrawElement(element)) {\n return getFreeDrawElementAbsoluteCoords(element);\n } else if (isLinearElement(element)) {\n return LinearElementEditor.getElementAbsoluteCoords(\n element,\n elementsMap,\n includeBoundText,\n );\n } else if (isTextElement(element)) {\n const container = elementsMap\n ? getContainerElement(element, elementsMap)\n : null;\n if (isArrowElement(container)) {\n const { x, y } = LinearElementEditor.getBoundTextElementPosition(\n container,\n element as ExcalidrawTextElementWithContainer,\n elementsMap,\n );\n return [\n x,\n y,\n x + element.width,\n y + element.height,\n x + element.width / 2,\n y + element.height / 2,\n ];\n }\n }\n return [\n element.x,\n element.y,\n element.x + element.width,\n element.y + element.height,\n element.x + element.width / 2,\n element.y + element.height / 2,\n ];\n};\n\n/*\n * for a given element, `getElementLineSegments` returns line segments\n * that can be used for visual collision detection (useful for frames)\n * as opposed to bounding box collision detection\n */\n/**\n * Given an element, return the line segments that make up the element.\n *\n * Uses helpers from /math\n */\nexport const getElementLineSegments = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n): LineSegment<GlobalPoint>[] => {\n const shape = getElementShape(element, elementsMap);\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\n element,\n elementsMap,\n );\n const center = pointFrom<GlobalPoint>(cx, cy);\n\n if (shape.type === \"polycurve\") {\n const curves = shape.data;\n const pointsOnCurves = curves.map((curve) =>\n pointsOnBezierCurves(curve, 10),\n );\n\n const segments: LineSegment<GlobalPoint>[] = [];\n\n if (\n (isLineElement(element) && !element.polygon) ||\n isArrowElement(element)\n ) {\n for (const points of pointsOnCurves) {\n let i = 0;\n\n while (i < points.length - 1) {\n segments.push(\n lineSegment(\n pointFrom(points[i][0], points[i][1]),\n pointFrom(points[i + 1][0], points[i + 1][1]),\n ),\n );\n i++;\n }\n }\n } else {\n const points = pointsOnCurves.flat();\n let i = 0;\n\n while (i < points.length - 1) {\n segments.push(\n lineSegment(\n pointFrom(points[i][0], points[i][1]),\n pointFrom(points[i + 1][0], points[i + 1][1]),\n ),\n );\n i++;\n }\n }\n\n return segments;\n } else if (shape.type === \"polyline\") {\n return shape.data as LineSegment<GlobalPoint>[];\n } else if (_isRectanguloidElement(element)) {\n const [sides, corners] = deconstructRectanguloidElement(element);\n const cornerSegments: LineSegment<GlobalPoint>[] = corners\n .map((corner) => getSegmentsOnCurve(corner, center, element.angle))\n .flat();\n const rotatedSides = getRotatedSides(sides, center, element.angle);\n return [...rotatedSides, ...cornerSegments];\n } else if (element.type === \"diamond\") {\n const [sides, corners] = deconstructDiamondElement(element);\n const cornerSegments = corners\n .map((corner) => getSegmentsOnCurve(corner, center, element.angle))\n .flat();\n const rotatedSides = getRotatedSides(sides, center, element.angle);\n\n return [...rotatedSides, ...cornerSegments];\n } else if (shape.type === \"polygon\") {\n if (isTextElement(element)) {\n const container = getContainerElement(element, elementsMap);\n if (container && isLinearElement(container)) {\n const segments: LineSegment<GlobalPoint>[] = [\n lineSegment(pointFrom(x1, y1), pointFrom(x2, y1)),\n lineSegment(pointFrom(x2, y1), pointFrom(x2, y2)),\n lineSegment(pointFrom(x2, y2), pointFrom(x1, y2)),\n lineSegment(pointFrom(x1, y2), pointFrom(x1, y1)),\n ];\n return segments;\n }\n }\n\n const points = shape.data as GlobalPoint[];\n const segments: LineSegment<GlobalPoint>[] = [];\n for (let i = 0; i < points.length - 1; i++) {\n segments.push(lineSegment(points[i], points[i + 1]));\n }\n return segments;\n } else if (shape.type === \"ellipse\") {\n return getSegmentsOnEllipse(element as ExcalidrawEllipseElement);\n }\n\n const [nw, ne, sw, se, , , w, e] = (\n [\n [x1, y1],\n [x2, y1],\n [x1, y2],\n [x2, y2],\n [cx, y1],\n [cx, y2],\n [x1, cy],\n [x2, cy],\n ] as GlobalPoint[]\n ).map((point) => pointRotateRads(point, center, element.angle));\n\n return [\n lineSegment(nw, ne),\n lineSegment(sw, se),\n lineSegment(nw, sw),\n lineSegment(ne, se),\n lineSegment(nw, e),\n lineSegment(sw, e),\n lineSegment(ne, w),\n lineSegment(se, w),\n ];\n};\n\nconst _isRectanguloidElement = (\n element: ExcalidrawElement,\n): element is ExcalidrawRectanguloidElement => {\n return (\n element != null &&\n (element.type === \"rectangle\" ||\n element.type === \"image\" ||\n element.type === \"iframe\" ||\n element.type === \"embeddable\" ||\n element.type === \"frame\" ||\n element.type === \"magicframe\" ||\n (element.type === \"text\" && !element.containerId))\n );\n};\n\nconst getRotatedSides = (\n sides: LineSegment<GlobalPoint>[],\n center: GlobalPoint,\n angle: Radians,\n) => {\n return sides.map((side) => {\n return lineSegment(\n pointRotateRads<GlobalPoint>(side[0], center, angle),\n pointRotateRads<GlobalPoint>(side[1], center, angle),\n );\n });\n};\n\nconst getSegmentsOnCurve = (\n curve: Curve<GlobalPoint>,\n center: GlobalPoint,\n angle: Radians,\n): LineSegment<GlobalPoint>[] => {\n const points = pointsOnBezierCurves(curve, 10);\n let i = 0;\n const segments: LineSegment<GlobalPoint>[] = [];\n while (i < points.length - 1) {\n segments.push(\n lineSegment(\n pointRotateRads<GlobalPoint>(\n pointFrom(points[i][0], points[i][1]),\n center,\n angle,\n ),\n pointRotateRads<GlobalPoint>(\n pointFrom(points[i + 1][0], points[i + 1][1]),\n center,\n angle,\n ),\n ),\n );\n i++;\n }\n\n return segments;\n};\n\nconst getSegmentsOnEllipse = (\n ellipse: ExcalidrawEllipseElement,\n): LineSegment<GlobalPoint>[] => {\n const center = pointFrom<GlobalPoint>(\n ellipse.x + ellipse.width / 2,\n ellipse.y + ellipse.height / 2,\n );\n\n const a = ellipse.width / 2;\n const b = ellipse.height / 2;\n\n const segments: LineSegment<GlobalPoint>[] = [];\n const points: GlobalPoint[] = [];\n const n = 90;\n const deltaT = (Math.PI * 2) / n;\n\n for (let i = 0; i < n; i++) {\n const t = i * deltaT;\n const x = center[0] + a * Math.cos(t);\n const y = center[1] + b * Math.sin(t);\n points.push(pointRotateRads(pointFrom(x, y), center, ellipse.angle));\n }\n\n for (let i = 0; i < points.length - 1; i++) {\n segments.push(lineSegment(points[i], points[i + 1]));\n }\n\n segments.push(lineSegment(points[points.length - 1], points[0]));\n return segments;\n};\n\n/**\n * Scene -> Scene coords, but in x1,x2,y1,y2 format.\n *\n * Rectangle here means any rectangular frame, not an excalidraw element.\n */\nexport const getRectangleBoxAbsoluteCoords = (boxSceneCoords: RectangleBox) => {\n return [\n boxSceneCoords.x,\n boxSceneCoords.y,\n boxSceneCoords.x + boxSceneCoords.width,\n boxSceneCoords.y + boxSceneCoords.height,\n boxSceneCoords.x + boxSceneCoords.width / 2,\n boxSceneCoords.y + boxSceneCoords.height / 2,\n ];\n};\n\nexport const getDiamondPoints = (element: ExcalidrawElement) => {\n // Here we add +1 to avoid these numbers to be 0\n // otherwise rough.js will throw an error complaining about it\n const topX = Math.floor(element.width / 2) + 1;\n const topY = 0;\n const rightX = element.width;\n const rightY = Math.floor(element.height / 2) + 1;\n const bottomX = topX;\n const bottomY = element.height;\n const leftX = 0;\n const leftY = rightY;\n\n return [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY];\n};\n\n// reference: https://eliot-jones.com/2019/12/cubic-bezier-curve-bounding-boxes\nconst getBezierValueForT = (\n t: number,\n p0: number,\n p1: number,\n p2: number,\n p3: number,\n) => {\n const oneMinusT = 1 - t;\n return (\n Math.pow(oneMinusT, 3) * p0 +\n 3 * Math.pow(oneMinusT, 2) * t * p1 +\n 3 * oneMinusT * Math.pow(t, 2) * p2 +\n Math.pow(t, 3) * p3\n );\n};\n\nconst solveQuadratic = (\n p0: number,\n p1: number,\n p2: number,\n p3: number,\n): MaybeQuadraticSolution => {\n const i = p1 - p0;\n const j = p2 - p1;\n const k = p3 - p2;\n\n const a = 3 * i - 6 * j + 3 * k;\n const b = 6 * j - 6 * i;\n const c = 3 * i;\n\n const sqrtPart = b * b - 4 * a * c;\n const hasSolution = sqrtPart >= 0;\n\n if (!hasSolution) {\n return false;\n }\n\n let s1 = null;\n let s2 = null;\n\n let t1 = Infinity;\n let t2 = Infinity;\n\n if (a === 0) {\n t1 = t2 = -c / b;\n } else {\n t1 = (-b + Math.sqrt(sqrtPart)) / (2 * a);\n t2 = (-b - Math.sqrt(sqrtPart)) / (2 * a);\n }\n\n if (t1 >= 0 && t1 <= 1) {\n s1 = getBezierValueForT(t1, p0, p1, p2, p3);\n }\n\n if (t2 >= 0 && t2 <= 1) {\n s2 = getBezierValueForT(t2, p0, p1, p2, p3);\n }\n\n return [s1, s2];\n};\n\nexport const getCubicBezierCurveBound = (\n p0: GlobalPoint,\n p1: GlobalPoint,\n p2: GlobalPoint,\n p3: GlobalPoint,\n): Bounds => {\n const solX = solveQuadratic(p0[0], p1[0], p2[0], p3[0]);\n const solY = solveQuadratic(p0[1], p1[1], p2[1], p3[1]);\n\n let minX = Math.min(p0[0], p3[0]);\n let maxX = Math.max(p0[0], p3[0]);\n\n if (solX) {\n const xs = solX.filter((x) => x !== null) as number[];\n minX = Math.min(minX, ...xs);\n maxX = Math.max(maxX, ...xs);\n }\n\n let minY = Math.min(p0[1], p3[1]);\n let maxY = Math.max(p0[1], p3[1]);\n if (solY) {\n const ys = solY.filter((y) => y !== null) as number[];\n minY = Math.min(minY, ...ys);\n maxY = Math.max(maxY, ...ys);\n }\n return [minX, minY, maxX, maxY];\n};\n\nexport const getMinMaxXYFromCurvePathOps = (\n ops: Op[],\n transformXY?: (p: GlobalPoint) => GlobalPoint,\n): Bounds => {\n let currentP: GlobalPoint = pointFrom(0, 0);\n\n const { minX, minY, maxX, maxY } = ops.reduce(\n (limits, { op, data }) => {\n // There are only four operation types:\n // move, bcurveTo, lineTo, and curveTo\n if (op === \"move\") {\n // change starting point\n const p: GlobalPoint | undefined = pointFromArray(data);\n invariant(p != null, \"Op data is not a point\");\n currentP = p;\n // move operation does not draw anything; so, it always\n // returns false\n } else if (op === \"bcurveTo\") {\n const _p1 = pointFrom<GlobalPoint>(data[0], data[1]);\n const _p2 = pointFrom<GlobalPoint>(data[2], data[3]);\n const _p3 = pointFrom<GlobalPoint>(data[4], data[5]);\n\n const p1 = transformXY ? transformXY(_p1) : _p1;\n const p2 = transformXY ? transformXY(_p2) : _p2;\n const p3 = transformXY ? transformXY(_p3) : _p3;\n\n const p0 = transformXY ? transformXY(currentP) : currentP;\n currentP = _p3;\n\n const [minX, minY, maxX, maxY] = getCubicBezierCurveBound(\n p0,\n p1,\n p2,\n p3,\n );\n\n limits.minX = Math.min(limits.minX, minX);\n limits.minY = Math.min(limits.minY, minY);\n\n limits.maxX = Math.max(limits.maxX, maxX);\n limits.maxY = Math.max(limits.maxY, maxY);\n } else if (op === \"lineTo\") {\n // TODO: Implement this\n } else if (op === \"qcurveTo\") {\n // TODO: Implement this\n }\n return limits;\n },\n { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },\n );\n return [minX, minY, maxX, maxY];\n};\n\nexport const getBoundsFromPoints = (\n points: ExcalidrawFreeDrawElement[\"points\"],\n): Bounds => {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of points) {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n }\n\n return [minX, minY, maxX, maxY];\n};\n\nconst getFreeDrawElementAbsoluteCoords = (\n element: ExcalidrawFreeDrawElement,\n): [number, number, number, number, number, number] => {\n const [minX, minY, maxX, maxY] = getBoundsFromPoints(element.points);\n const x1 = minX + element.x;\n const y1 = minY + element.y;\n const x2 = maxX + element.x;\n const y2 = maxY + element.y;\n return [x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2];\n};\n\n/** @returns number in pixels */\nexport const getArrowheadSize = (arrowhead: Arrowhead): number => {\n switch (arrowhead) {\n case \"arrow\":\n return 25;\n case \"diamond\":\n case \"diamond_outline\":\n return 12;\n case \"crowfoot_many\":\n case \"crowfoot_one\":\n case \"crowfoot_one_or_many\":\n return 20;\n default:\n return 15;\n }\n};\n\n/** @returns number in degrees */\nexport const getArrowheadAngle = (arrowhead: Arrowhead): Degrees => {\n switch (arrowhead) {\n case \"bar\":\n return 90 as Degrees;\n case \"arrow\":\n return 20 as Degrees;\n default:\n return 25 as Degrees;\n }\n};\n\nexport const getArrowheadPoints = (\n element: ExcalidrawLinearElement,\n shape: Drawable[],\n position: \"start\" | \"end\",\n arrowhead: Arrowhead,\n) => {\n if (shape.length < 1) {\n return null;\n }\n\n const ops = getCurvePathOps(shape[0]);\n if (ops.length < 1) {\n return null;\n }\n\n // The index of the bCurve operation to examine.\n const index = position === \"start\" ? 1 : ops.length - 1;\n\n const data = ops[index].data;\n\n invariant(data.length === 6, \"Op data length is not 6\");\n\n const p3 = pointFrom(data[4], data[5]);\n const p2 = pointFrom(data[2], data[3]);\n const p1 = pointFrom(data[0], data[1]);\n\n // We need to find p0 of the bezier curve.\n // It is typically the last point of the previous\n // curve; it can also be the position of moveTo operation.\n const prevOp = ops[index - 1];\n let p0 = pointFrom(0, 0);\n if (prevOp.op === \"move\") {\n const p = pointFromArray(prevOp.data);\n invariant(p != null, \"Op data is not a point\");\n p0 = p;\n } else if (prevOp.op === \"bcurveTo\") {\n p0 = pointFrom(prevOp.data[4], prevOp.data[5]);\n }\n\n // B(t) = p0 * (1-t)^3 + 3p1 * t * (1-t)^2 + 3p2 * t^2 * (1-t) + p3 * t^3\n const equation = (t: number, idx: number) =>\n Math.pow(1 - t, 3) * p3[idx] +\n 3 * t * Math.pow(1 - t, 2) * p2[idx] +\n 3 * Math.pow(t, 2) * (1 - t) * p1[idx] +\n p0[idx] * Math.pow(t, 3);\n\n // Ee know the last point of the arrow (or the first, if start arrowhead).\n const [x2, y2] = position === \"start\" ? p0 : p3;\n\n // By using cubic bezier equation (B(t)) and the given parameters,\n // we calculate a point that is closer to the last point.\n // The value 0.3 is chosen arbitrarily and it works best for all\n // the tested cases.\n const [x1, y1] = [equation(0.3, 0), equation(0.3, 1)];\n\n // Find the normalized direction vector based on the\n // previously calculated points.\n const distance = Math.hypot(x2 - x1, y2 - y1);\n const nx = (x2 - x1) / distance;\n const ny = (y2 - y1) / distance;\n\n const size = getArrowheadSize(arrowhead);\n\n let length = 0;\n\n {\n // Length for -> arrows is based on the length of the last section\n const [cx, cy] =\n position === \"end\"\n ? element.points[element.points.length - 1]\n : element.points[0];\n const [px, py] =\n element.points.length > 1\n ? position === \"end\"\n ? element.points[element.points.length - 2]\n : element.points[1]\n : [0, 0];\n\n length = Math.hypot(cx - px, cy - py);\n }\n\n // Scale down the arrowhead until we hit a certain size so that it doesn't look weird.\n // This value is selected by minimizing a minimum size with the last segment of the arrowhead\n const lengthMultiplier =\n arrowhead === \"diamond\" || arrowhead === \"diamond_outline\" ? 0.25 : 0.5;\n const minSize = Math.min(size, length * lengthMultiplier);\n const xs = x2 - nx * minSize;\n const ys = y2 - ny * minSize;\n\n if (\n arrowhead === \"dot\" ||\n arrowhead === \"circle\" ||\n arrowhead === \"circle_outline\"\n ) {\n const diameter = Math.hypot(ys - y2, xs - x2) + element.strokeWidth - 2;\n return [x2, y2, diameter];\n }\n\n const angle = getArrowheadAngle(arrowhead);\n\n if (arrowhead === \"crowfoot_many\" || arrowhead === \"crowfoot_one_or_many\") {\n // swap (xs, ys) with (x2, y2)\n const [x3, y3] = pointRotateRads(\n pointFrom(x2, y2),\n pointFrom(xs, ys),\n degreesToRadians(-angle as Degrees),\n );\n const [x4, y4] = pointRotateRads(\n pointFrom(x2, y2),\n pointFrom(xs, ys),\n degreesToRadians(angle),\n );\n return [xs, ys, x3, y3, x4, y4];\n }\n\n // Return points\n const [x3, y3] = pointRotateRads(\n pointFrom(xs, ys),\n pointFrom(x2, y2),\n ((-angle * Math.PI) / 180) as Radians,\n );\n const [x4, y4] = pointRotateRads(\n pointFrom(xs, ys),\n pointFrom(x2, y2),\n degreesToRadians(angle),\n );\n\n if (arrowhead === \"diamond\" || arrowhead === \"diamond_outline\") {\n // point opposite to the arrowhead point\n let ox;\n let oy;\n\n if (position === \"start\") {\n const [px, py] = element.points.length > 1 ? element.points[1] : [0, 0];\n\n [ox, oy] = pointRotateRads(\n pointFrom(x2 + minSize * 2, y2),\n pointFrom(x2, y2),\n Math.atan2(py - y2, px - x2) as Radians,\n );\n } else {\n const [px, py] =\n element.points.length > 1\n ? element.points[element.points.length - 2]\n : [0, 0];\n\n [ox, oy] = pointRotateRads(\n pointFrom(x2 - minSize * 2, y2),\n pointFrom(x2, y2),\n Math.atan2(y2 - py, x2 - px) as Radians,\n );\n }\n\n return [x2, y2, x3, y3, ox, oy, x4, y4];\n }\n\n return [x2, y2, x3, y3, x4, y4];\n};\n\n// TODO reuse shape.ts\nconst generateLinearElementShape = (\n element: ExcalidrawLinearElement,\n): Drawable => {\n const generator = rough.generator();\n const options = generateRoughOptions(element);\n\n const method = (() => {\n if (element.roundness) {\n return \"curve\";\n }\n if (options.fill) {\n return \"polygon\";\n }\n return \"linearPath\";\n })();\n\n return generator[method](\n element.points as Mutable<LocalPoint>[] as RoughPoint[],\n options,\n );\n};\n\nconst getLinearElementRotatedBounds = (\n element: ExcalidrawLinearElement,\n cx: number,\n cy: number,\n elementsMap: ElementsMap,\n): Bounds => {\n const boundTextElement = getBoundTextElement(element, elementsMap);\n\n if (element.points.length < 2) {\n const [pointX, pointY] = element.points[0];\n const [x, y] = pointRotateRads(\n pointFrom(element.x + pointX, element.y + pointY),\n pointFrom(cx, cy),\n element.angle,\n );\n\n let coords: Bounds = [x, y, x, y];\n if (boundTextElement) {\n const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText(\n element,\n elementsMap,\n [x, y, x, y],\n boundTextElement,\n );\n coords = [\n coordsWithBoundText[0],\n coordsWithBoundText[1],\n coordsWithBoundText[2],\n coordsWithBoundText[3],\n ];\n }\n return coords;\n }\n\n // first element is always the curve\n const cachedShape = ShapeCache.get(element, null)?.[0];\n const shape = cachedShape ?? generateLinearElementShape(element);\n const ops = getCurvePathOps(shape);\n const transformXY = ([x, y]: GlobalPoint) =>\n pointRotateRads<GlobalPoint>(\n pointFrom(element.x + x, element.y + y),\n pointFrom(cx, cy),\n element.angle,\n );\n const res = getMinMaxXYFromCurvePathOps(ops, transformXY);\n let coords: Bounds = [res[0], res[1], res[2], res[3]];\n if (boundTextElement) {\n const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText(\n element,\n elementsMap,\n coords,\n boundTextElement,\n );\n coords = [\n coordsWithBoundText[0],\n coordsWithBoundText[1],\n coordsWithBoundText[2],\n coordsWithBoundText[3],\n ];\n }\n return coords;\n};\n\nexport const getElementBounds = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n nonRotated: boolean = false,\n): Bounds => {\n return ElementBounds.getBounds(element, elementsMap, nonRotated);\n};\n\nexport const getCommonBounds = (\n elements: ElementsMapOrArray,\n elementsMap?: ElementsMap,\n): Bounds => {\n if (!sizeOf(elements)) {\n return [0, 0, 0, 0];\n }\n\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n\n const _elementsMap = elementsMap || arrayToMap(elements);\n\n elements.forEach((element) => {\n const [x1, y1, x2, y2] = getElementBounds(element, _elementsMap);\n minX = Math.min(minX, x1);\n minY = Math.min(minY, y1);\n maxX = Math.max(maxX, x2);\n maxY = Math.max(maxY, y2);\n });\n\n return [minX, minY, maxX, maxY];\n};\n\nexport const getDraggedElementsBounds = (\n elements: ExcalidrawElement[],\n dragOffset: { x: number; y: number },\n) => {\n const [minX, minY, maxX, maxY] = getCommonBounds(elements);\n return [\n minX + dragOffset.x,\n minY + dragOffset.y,\n maxX + dragOffset.x,\n maxY + dragOffset.y,\n ];\n};\n\nexport const getResizedElementAbsoluteCoords = (\n element: ExcalidrawElement,\n nextWidth: number,\n nextHeight: number,\n normalizePoints: boolean,\n): Bounds => {\n if (!(isLinearElement(element) || isFreeDrawElement(element))) {\n return [\n element.x,\n element.y,\n element.x + nextWidth,\n element.y + nextHeight,\n ];\n }\n\n const points = rescalePoints(\n 0,\n nextWidth,\n rescalePoints(1, nextHeight, element.points, normalizePoints),\n normalizePoints,\n );\n\n let bounds: Bounds;\n\n if (isFreeDrawElement(element)) {\n // Free Draw\n bounds = getBoundsFromPoints(points);\n } else {\n // Line\n const gen = rough.generator();\n const curve = !element.roundness\n ? gen.linearPath(\n points as [number, number][],\n generateRoughOptions(element),\n )\n : gen.curve(points as [number, number][], generateRoughOptions(element));\n\n const ops = getCurvePathOps(curve);\n bounds = getMinMaxXYFromCurvePathOps(ops);\n }\n\n const [minX, minY, maxX, maxY] = bounds;\n return [\n minX + element.x,\n minY + element.y,\n maxX + element.x,\n maxY + element.y,\n ];\n};\n\nexport const getElementPointsCoords = (\n element: ExcalidrawLinearElement,\n points: readonly (readonly [number, number])[],\n): Bounds => {\n // This might be computationally heavey\n const gen = rough.generator();\n const curve =\n element.roundness == null\n ? gen.linearPath(\n points as [number, number][],\n generateRoughOptions(element),\n )\n : gen.curve(points as [number, number][], generateRoughOptions(element));\n const ops = getCurvePathOps(curve);\n const [minX, minY, maxX, maxY] = getMinMaxXYFromCurvePathOps(ops);\n return [\n minX + element.x,\n minY + element.y,\n maxX + element.x,\n maxY + element.y,\n ];\n};\n\nexport const getClosestElementBounds = (\n elements: readonly ExcalidrawElement[],\n from: { x: number; y: number },\n): Bounds => {\n if (!elements.length) {\n return [0, 0, 0, 0];\n }\n\n let minDistance = Infinity;\n let closestElement = elements[0];\n const elementsMap = arrayToMap(elements);\n elements.forEach((element) => {\n const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);\n const distance = pointDistance(\n pointFrom((x1 + x2) / 2, (y1 + y2) / 2),\n pointFrom(from.x, from.y),\n );\n\n if (distance < minDistance) {\n minDistance = distance;\n closestElement = element;\n }\n });\n\n return getElementBounds(closestElement, elementsMap);\n};\n\nexport interface BoundingBox {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n midX: number;\n midY: number;\n width: number;\n height: number;\n}\n\nexport const getCommonBoundingBox = (\n elements:\n | readonly ExcalidrawElement[]\n | readonly NonDeleted<ExcalidrawElement>[],\n): BoundingBox => {\n const [minX, minY, maxX, maxY] = getCommonBounds(elements);\n return {\n minX,\n minY,\n maxX,\n maxY,\n width: maxX - minX,\n height: maxY - minY,\n midX: (minX + maxX) / 2,\n midY: (minY + maxY) / 2,\n };\n};\n\n/**\n * returns scene coords of user's editor viewport (visible canvas area) bounds\n */\nexport const getVisibleSceneBounds = ({\n scrollX,\n scrollY,\n width,\n height,\n zoom,\n}: AppState): SceneBounds => {\n return [\n -scrollX,\n -scrollY,\n -scrollX + width / zoom.value,\n -scrollY + height / zoom.value,\n ];\n};\n\nexport const getCenterForBounds = (bounds: Bounds): GlobalPoint =>\n pointFrom(\n bounds[0] + (bounds[2] - bounds[0]) / 2,\n bounds[1] + (bounds[3] - bounds[1]) / 2,\n );\n\n/**\n * Get the axis-aligned bounding box for a given element\n */\nexport const aabbForElement = (\n element: Readonly<ExcalidrawElement>,\n elementsMap: ElementsMap,\n offset?: [number, number, number, number],\n) => {\n const bbox = {\n minX: element.x,\n minY: element.y,\n maxX: element.x + element.width,\n maxY: element.y + element.height,\n midX: element.x + element.width / 2,\n midY: element.y + element.height / 2,\n };\n\n const center = elementCenterPoint(element, elementsMap);\n const [topLeftX, topLeftY] = pointRotateRads(\n pointFrom(bbox.minX, bbox.minY),\n center,\n element.angle,\n );\n const [topRightX, topRightY] = pointRotateRads(\n pointFrom(bbox.maxX, bbox.minY),\n center,\n element.angle,\n );\n const [bottomRightX, bottomRightY] = pointRotateRads(\n pointFrom(bbox.maxX, bbox.maxY),\n center,\n element.angle,\n );\n const [bottomLeftX, bottomLeftY] = pointRotateRads(\n pointFrom(bbox.minX, bbox.maxY),\n center,\n element.angle,\n );\n\n const bounds = [\n Math.min(topLeftX, topRightX, bottomRightX, bottomLeftX),\n Math.min(topLeftY, topRightY, bottomRightY, bottomLeftY),\n Math.max(topLeftX, topRightX, bottomRightX, bottomLeftX),\n Math.max(topLeftY, topRightY, bottomRightY, bottomLeftY),\n ] as Bounds;\n\n if (offset) {\n const [topOffset, rightOffset, downOffset, leftOffset] = offset;\n return [\n bounds[0] - leftOffset,\n bounds[1] - topOffset,\n bounds[2] + rightOffset,\n bounds[3] + downOffset,\n ] as Bounds;\n }\n\n return bounds;\n};\n\nexport const pointInsideBounds = <P extends GlobalPoint | LocalPoint>(\n p: P,\n bounds: Bounds,\n): boolean =>\n p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];\n\nexport const doBoundsIntersect = (\n bounds1: Bounds | null,\n bounds2: Bounds | null,\n): boolean => {\n if (bounds1 == null || bounds2 == null) {\n return false;\n }\n\n const [minX1, minY1, maxX1, maxY1] = bounds1;\n const [minX2, minY2, maxX2, maxY2] = bounds2;\n\n return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;\n};\n\nexport const elementCenterPoint = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n xOffset: number = 0,\n yOffset: number = 0,\n) => {\n if (isLinearElement(element)) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const [x, y] = pointFrom<GlobalPoint>((x1 + x2) / 2, (y1 + y2) / 2);\n\n return pointFrom<GlobalPoint>(x + xOffset, y + yOffset);\n }\n\n const [x, y] = getCenterForBounds(getElementBounds(element, elementsMap));\n\n return pointFrom<GlobalPoint>(x + xOffset, y + yOffset);\n};\n", "/**\n * this file defines pure geometric shapes\n *\n * for instance, a cubic bezier curve is specified by its four control points and\n * an ellipse is defined by its center, angle, semi major axis and semi minor axis\n * (but in semi-width and semi-height so it's more relevant to Excalidraw)\n *\n * the idea with pure shapes is so that we can provide collision and other geoemtric methods not depending on\n * the specifics of roughjs or elements in Excalidraw; instead, we can focus on the pure shapes themselves\n *\n * also included in this file are methods for converting an Excalidraw element or a Drawable from roughjs\n * to pure shapes\n */\nimport { pointsOnBezierCurves } from \"points-on-curve\";\n\nimport { invariant } from \"@excalidraw/common\";\nimport {\n curve,\n lineSegment,\n pointFrom,\n pointDistance,\n pointFromArray,\n pointFromVector,\n pointRotateRads,\n polygon,\n polygonFromPoints,\n PRECISION,\n segmentsIntersectAt,\n vector,\n vectorAdd,\n vectorFromPoint,\n vectorScale,\n type GlobalPoint,\n type LocalPoint,\n} from \"@excalidraw/math\";\n\nimport { getElementAbsoluteCoords } from \"@excalidraw/element\";\n\nimport type {\n ElementsMap,\n ExcalidrawBindableElement,\n ExcalidrawDiamondElement,\n ExcalidrawElement,\n ExcalidrawEllipseElement,\n ExcalidrawEmbeddableElement,\n ExcalidrawFrameLikeElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawIframeElement,\n ExcalidrawImageElement,\n ExcalidrawLinearElement,\n ExcalidrawRectangleElement,\n ExcalidrawSelectionElement,\n ExcalidrawTextElement,\n} from \"@excalidraw/element/types\";\nimport type { Curve, LineSegment, Polygon, Radians } from \"@excalidraw/math\";\n\nimport type { Drawable, Op } from \"roughjs/bin/core\";\n\n// a polyline (made up term here) is a line consisting of other line segments\n// this corresponds to a straight line element in the editor but it could also\n// be used to model other elements\nexport type Polyline<Point extends GlobalPoint | LocalPoint> =\n LineSegment<Point>[];\n\n// a polycurve is a curve consisting of ther curves, this corresponds to a complex\n// curve on the canvas\nexport type Polycurve<Point extends GlobalPoint | LocalPoint> = Curve<Point>[];\n\n// an ellipse is specified by its center, angle, and its major and minor axes\n// but for the sake of simplicity, we've used halfWidth and halfHeight instead\n// in replace of semi major and semi minor axes\nexport type Ellipse<Point extends GlobalPoint | LocalPoint> = {\n center: Point;\n angle: Radians;\n halfWidth: number;\n halfHeight: number;\n};\n\nexport type GeometricShape<Point extends GlobalPoint | LocalPoint> =\n | {\n type: \"line\";\n data: LineSegment<Point>;\n }\n | {\n type: \"polygon\";\n data: Polygon<Point>;\n }\n | {\n type: \"curve\";\n data: Curve<Point>;\n }\n | {\n type: \"ellipse\";\n data: Ellipse<Point>;\n }\n | {\n type: \"polyline\";\n data: Polyline<Point>;\n }\n | {\n type: \"polycurve\";\n data: Polycurve<Point>;\n };\n\ntype RectangularElement =\n | ExcalidrawRectangleElement\n | ExcalidrawDiamondElement\n | ExcalidrawFrameLikeElement\n | ExcalidrawEmbeddableElement\n | ExcalidrawImageElement\n | ExcalidrawIframeElement\n | ExcalidrawTextElement\n | ExcalidrawSelectionElement;\n\n// polygon\nexport const getPolygonShape = <Point extends GlobalPoint | LocalPoint>(\n element: RectangularElement,\n): GeometricShape<Point> => {\n const { angle, width, height, x, y } = element;\n\n const cx = x + width / 2;\n const cy = y + height / 2;\n\n const center: Point = pointFrom(cx, cy);\n\n let data: Polygon<Point>;\n\n if (element.type === \"diamond\") {\n data = polygon(\n pointRotateRads(pointFrom(cx, y), center, angle),\n pointRotateRads(pointFrom(x + width, cy), center, angle),\n pointRotateRads(pointFrom(cx, y + height), center, angle),\n pointRotateRads(pointFrom(x, cy), center, angle),\n );\n } else {\n data = polygon(\n pointRotateRads(pointFrom(x, y), center, angle),\n pointRotateRads(pointFrom(x + width, y), center, angle),\n pointRotateRads(pointFrom(x + width, y + height), center, angle),\n pointRotateRads(pointFrom(x, y + height), center, angle),\n );\n }\n\n return {\n type: \"polygon\",\n data,\n };\n};\n\n// return the selection box for an element, possibly rotated as well\nexport const getSelectionBoxShape = <Point extends GlobalPoint | LocalPoint>(\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n padding = 10,\n) => {\n let [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\n element,\n elementsMap,\n true,\n );\n\n x1 -= padding;\n x2 += padding;\n y1 -= padding;\n y2 += padding;\n\n //const angleInDegrees = angleToDegrees(element.angle);\n const center = pointFrom(cx, cy);\n const topLeft = pointRotateRads(pointFrom(x1, y1), center, element.angle);\n const topRight = pointRotateRads(pointFrom(x2, y1), center, element.angle);\n const bottomLeft = pointRotateRads(pointFrom(x1, y2), center, element.angle);\n const bottomRight = pointRotateRads(pointFrom(x2, y2), center, element.angle);\n\n return {\n type: \"polygon\",\n data: [topLeft, topRight, bottomRight, bottomLeft],\n } as GeometricShape<Point>;\n};\n\n// ellipse\nexport const getEllipseShape = <Point extends GlobalPoint | LocalPoint>(\n element: ExcalidrawEllipseElement,\n): GeometricShape<Point> => {\n const { width, height, angle, x, y } = element;\n\n return {\n type: \"ellipse\",\n data: {\n center: pointFrom(x + width / 2, y + height / 2),\n angle,\n halfWidth: width / 2,\n halfHeight: height / 2,\n },\n };\n};\n\nexport const getCurvePathOps = (shape: Drawable): Op[] => {\n // NOTE (mtolmacs): Temporary fix for extremely large elements\n if (!shape) {\n return [];\n }\n\n for (const set of shape.sets) {\n if (set.type === \"path\") {\n return set.ops;\n }\n }\n return shape.sets[0].ops;\n};\n\n// linear\nexport const getCurveShape = <Point extends GlobalPoint | LocalPoint>(\n roughShape: Drawable,\n startingPoint: Point = pointFrom(0, 0),\n angleInRadian: Radians,\n center: Point,\n): GeometricShape<Point> => {\n const transform = (p: Point): Point =>\n pointRotateRads(\n pointFrom(p[0] + startingPoint[0], p[1] + startingPoint[1]),\n center,\n angleInRadian,\n );\n\n const ops = getCurvePathOps(roughShape);\n const polycurve: Polycurve<Point> = [];\n let p0 = pointFrom<Point>(0, 0);\n\n for (const op of ops) {\n if (op.op === \"move\") {\n const p = pointFromArray<Point>(op.data);\n invariant(p != null, \"Ops data is not a point\");\n p0 = transform(p);\n }\n if (op.op === \"bcurveTo\") {\n const p1 = transform(pointFrom<Point>(op.data[0], op.data[1]));\n const p2 = transform(pointFrom<Point>(op.data[2], op.data[3]));\n const p3 = transform(pointFrom<Point>(op.data[4], op.data[5]));\n polycurve.push(curve<Point>(p0, p1, p2, p3));\n p0 = p3;\n }\n }\n\n return {\n type: \"polycurve\",\n data: polycurve,\n };\n};\n\nconst polylineFromPoints = <Point extends GlobalPoint | LocalPoint>(\n points: Point[],\n): Polyline<Point> => {\n let previousPoint: Point = points[0];\n const polyline: LineSegment<Point>[] = [];\n\n for (let i = 1; i < points.length; i++) {\n const nextPoint = points[i];\n polyline.push(lineSegment<Point>(previousPoint, nextPoint));\n previousPoint = nextPoint;\n }\n\n return polyline;\n};\n\nexport const getFreedrawShape = <Point extends GlobalPoint | LocalPoint>(\n element: ExcalidrawFreeDrawElement,\n center: Point,\n isClosed: boolean = false,\n): GeometricShape<Point> => {\n const transform = (p: Point) =>\n pointRotateRads(\n pointFromVector(\n vectorAdd(vectorFromPoint(p), vector(element.x, element.y)),\n ),\n center,\n element.angle,\n );\n\n const polyline = polylineFromPoints(\n element.points.map((p) => transform(p as Point)),\n );\n\n return (\n isClosed\n ? {\n type: \"polygon\",\n data: polygonFromPoints(polyline.flat()),\n }\n : {\n type: \"polyline\",\n data: polyline,\n }\n ) as GeometricShape<Point>;\n};\n\nexport const getClosedCurveShape = <Point extends GlobalPoint | LocalPoint>(\n element: ExcalidrawLinearElement,\n roughShape: Drawable,\n startingPoint: Point = pointFrom<Point>(0, 0),\n angleInRadian: Radians,\n center: Point,\n): GeometricShape<Point> => {\n const transform = (p: Point) =>\n pointRotateRads(\n pointFrom(p[0] + startingPoint[0], p[1] + startingPoint[1]),\n center,\n angleInRadian,\n );\n\n if (element.roundness === null) {\n return {\n type: \"polygon\",\n data: polygonFromPoints(\n element.points.map((p) => transform(p as Point)) as Point[],\n ),\n };\n }\n\n const ops = getCurvePathOps(roughShape);\n\n const points: Point[] = [];\n let odd = false;\n for (const operation of ops) {\n if (operation.op === \"move\") {\n odd = !odd;\n if (odd) {\n points.push(pointFrom(operation.data[0], operation.data[1]));\n }\n } else if (operation.op === \"bcurveTo\") {\n if (odd) {\n points.push(pointFrom(operation.data[0], operation.data[1]));\n points.push(pointFrom(operation.data[2], operation.data[3]));\n points.push(pointFrom(operation.data[4], operation.data[5]));\n }\n } else if (operation.op === \"lineTo\") {\n if (odd) {\n points.push(pointFrom(operation.data[0], operation.data[1]));\n }\n }\n }\n\n const polygonPoints = pointsOnBezierCurves(points, 10, 5).map((p) =>\n transform(p as Point),\n ) as Point[];\n\n return {\n type: \"polygon\",\n data: polygonFromPoints<Point>(polygonPoints),\n };\n};\n\n/**\n * Determine intersection of a rectangular shaped element and a\n * line segment.\n *\n * @param element The rectangular element to test against\n * @param segment The segment intersecting the element\n * @param gap Optional value to inflate the shape before testing\n * @returns An array of intersections\n */\n// TODO: Replace with final rounded rectangle code\nexport const segmentIntersectRectangleElement = <\n Point extends LocalPoint | GlobalPoint,\n>(\n element: ExcalidrawBindableElement,\n segment: LineSegment<Point>,\n gap: number = 0,\n): Point[] => {\n const bounds = [\n element.x - gap,\n element.y - gap,\n element.x + element.width + gap,\n element.y + element.height + gap,\n ];\n const center = pointFrom(\n (bounds[0] + bounds[2]) / 2,\n (bounds[1] + bounds[3]) / 2,\n );\n\n return [\n lineSegment(\n pointRotateRads(pointFrom(bounds[0], bounds[1]), center, element.angle),\n pointRotateRads(pointFrom(bounds[2], bounds[1]), center, element.angle),\n ),\n lineSegment(\n pointRotateRads(pointFrom(bounds[2], bounds[1]), center, element.angle),\n pointRotateRads(pointFrom(bounds[2], bounds[3]), center, element.angle),\n ),\n lineSegment(\n pointRotateRads(pointFrom(bounds[2], bounds[3]), center, element.angle),\n pointRotateRads(pointFrom(bounds[0], bounds[3]), center, element.angle),\n ),\n lineSegment(\n pointRotateRads(pointFrom(bounds[0], bounds[3]), center, element.angle),\n pointRotateRads(pointFrom(bounds[0], bounds[1]), center, element.angle),\n ),\n ]\n .map((s) => segmentsIntersectAt(segment, s))\n .filter((i): i is Point => !!i);\n};\n\nconst distanceToEllipse = <Point extends LocalPoint | GlobalPoint>(\n p: Point,\n ellipse: Ellipse<Point>,\n) => {\n const { angle, halfWidth, halfHeight, center } = ellipse;\n const a = halfWidth;\n const b = halfHeight;\n const translatedPoint = vectorAdd(\n vectorFromPoint(p),\n vectorScale(vectorFromPoint(center), -1),\n );\n const [rotatedPointX, rotatedPointY] = pointRotateRads(\n pointFromVector(translatedPoint),\n pointFrom(0, 0),\n -angle as Radians,\n );\n\n const px = Math.abs(rotatedPointX);\n const py = Math.abs(rotatedPointY);\n\n let tx = 0.707;\n let ty = 0.707;\n\n for (let i = 0; i < 3; i++) {\n const x = a * tx;\n const y = b * ty;\n\n const ex = ((a * a - b * b) * tx ** 3) / a;\n const ey = ((b * b - a * a) * ty ** 3) / b;\n\n const rx = x - ex;\n const ry = y - ey;\n\n const qx = px - ex;\n const qy = py - ey;\n\n const r = Math.hypot(ry, rx);\n const q = Math.hypot(qy, qx);\n\n tx = Math.min(1, Math.max(0, ((qx * r) / q + ex) / a));\n ty = Math.min(1, Math.max(0, ((qy * r) / q + ey) / b));\n const t = Math.hypot(ty, tx);\n tx /= t;\n ty /= t;\n }\n\n const [minX, minY] = [\n a * tx * Math.sign(rotatedPointX),\n b * ty * Math.sign(rotatedPointY),\n ];\n\n return pointDistance(\n pointFrom(rotatedPointX, rotatedPointY),\n pointFrom(minX, minY),\n );\n};\n\nexport const pointOnEllipse = <Point extends LocalPoint | GlobalPoint>(\n point: Point,\n ellipse: Ellipse<Point>,\n threshold = PRECISION,\n) => {\n return distanceToEllipse(point, ellipse) <= threshold;\n};\n\nexport const pointInEllipse = <Point extends LocalPoint | GlobalPoint>(\n p: Point,\n ellipse: Ellipse<Point>,\n) => {\n const { center, angle, halfWidth, halfHeight } = ellipse;\n const translatedPoint = vectorAdd(\n vectorFromPoint(p),\n vectorScale(vectorFromPoint(center), -1),\n );\n const [rotatedPointX, rotatedPointY] = pointRotateRads(\n pointFromVector(translatedPoint),\n pointFrom(0, 0),\n -angle as Radians,\n );\n\n return (\n (rotatedPointX / halfWidth) * (rotatedPointX / halfWidth) +\n (rotatedPointY / halfHeight) * (rotatedPointY / halfHeight) <=\n 1\n );\n};\n\nexport const ellipseAxes = <Point extends LocalPoint | GlobalPoint>(\n ellipse: Ellipse<Point>,\n) => {\n const widthGreaterThanHeight = ellipse.halfWidth > ellipse.halfHeight;\n\n const majorAxis = widthGreaterThanHeight\n ? ellipse.halfWidth * 2\n : ellipse.halfHeight * 2;\n const minorAxis = widthGreaterThanHeight\n ? ellipse.halfHeight * 2\n : ellipse.halfWidth * 2;\n\n return {\n majorAxis,\n minorAxis,\n };\n};\n\nexport const ellipseFocusToCenter = <Point extends LocalPoint | GlobalPoint>(\n ellipse: Ellipse<Point>,\n) => {\n const { majorAxis, minorAxis } = ellipseAxes(ellipse);\n\n return Math.sqrt(majorAxis ** 2 - minorAxis ** 2);\n};\n\nexport const ellipseExtremes = <Point extends LocalPoint | GlobalPoint>(\n ellipse: Ellipse<Point>,\n) => {\n const { center, angle } = ellipse;\n const { majorAxis, minorAxis } = ellipseAxes(ellipse);\n\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n const sqSum = majorAxis ** 2 + minorAxis ** 2;\n const sqDiff = (majorAxis ** 2 - minorAxis ** 2) * Math.cos(2 * angle);\n\n const yMax = Math.sqrt((sqSum - sqDiff) / 2);\n const xAtYMax =\n (yMax * sqSum * sin * cos) /\n (majorAxis ** 2 * sin ** 2 + minorAxis ** 2 * cos ** 2);\n\n const xMax = Math.sqrt((sqSum + sqDiff) / 2);\n const yAtXMax =\n (xMax * sqSum * sin * cos) /\n (majorAxis ** 2 * cos ** 2 + minorAxis ** 2 * sin ** 2);\n const centerVector = vectorFromPoint(center);\n\n return [\n vectorAdd(vector(xAtYMax, yMax), centerVector),\n vectorAdd(vectorScale(vector(xAtYMax, yMax), -1), centerVector),\n vectorAdd(vector(xMax, yAtXMax), centerVector),\n vectorAdd(vector(xMax, yAtXMax), centerVector),\n ];\n};\n", "import { simplify } from \"points-on-curve\";\nimport { getStroke } from \"perfect-freehand\";\n\nimport {\n type GeometricShape,\n getClosedCurveShape,\n getCurveShape,\n getEllipseShape,\n getFreedrawShape,\n getPolygonShape,\n} from \"@excalidraw/utils/shape\";\n\nimport {\n pointFrom,\n pointDistance,\n type LocalPoint,\n pointRotateRads,\n} from \"@excalidraw/math\";\nimport {\n ROUGHNESS,\n THEME,\n isTransparent,\n assertNever,\n COLOR_PALETTE,\n LINE_POLYGON_POINT_MERGE_DISTANCE,\n applyDarkModeFilter,\n} from \"@excalidraw/common\";\n\nimport { RoughGenerator } from \"roughjs/bin/generator\";\n\nimport type { GlobalPoint } from \"@excalidraw/math\";\n\nimport type { Mutable } from \"@excalidraw/common/utility-types\";\n\nimport type {\n AppState,\n EmbedsValidationStatus,\n} from \"@excalidraw/excalidraw/types\";\nimport type {\n ElementShape,\n ElementShapes,\n SVGPathString,\n} from \"@excalidraw/excalidraw/scene/types\";\n\nimport { elementWithCanvasCache } from \"./renderElement\";\n\nimport {\n canBecomePolygon,\n isElbowArrow,\n isEmbeddableElement,\n isIframeElement,\n isIframeLikeElement,\n isLinearElement,\n} from \"./typeChecks\";\nimport { getCornerRadius, isPathALoop } from \"./utils\";\nimport { headingForPointIsHorizontal } from \"./heading\";\n\nimport { canChangeRoundness } from \"./comparisons\";\nimport {\n getArrowheadPoints,\n getCenterForBounds,\n getDiamondPoints,\n getElementAbsoluteCoords,\n} from \"./bounds\";\nimport { shouldTestInside } from \"./collision\";\n\nimport type {\n ExcalidrawElement,\n NonDeletedExcalidrawElement,\n ExcalidrawSelectionElement,\n ExcalidrawLinearElement,\n Arrowhead,\n ExcalidrawFreeDrawElement,\n ElementsMap,\n ExcalidrawLineElement,\n} from \"./types\";\n\nimport type { Drawable, Options } from \"roughjs/bin/core\";\nimport type { Point as RoughPoint } from \"roughjs/bin/geometry\";\n\nexport class ShapeCache {\n private static rg = new RoughGenerator();\n private static cache = new WeakMap<\n ExcalidrawElement,\n { shape: ElementShape; theme: AppState[\"theme\"] }\n >();\n\n /**\n * Retrieves shape from cache if available. Use this only if shape\n * is optional and you have a fallback in case it's not cached.\n */\n public static get = <T extends ExcalidrawElement>(\n element: T,\n theme: AppState[\"theme\"] | null,\n ) => {\n const cached = ShapeCache.cache.get(element);\n if (cached && (theme === null || cached.theme === theme)) {\n return cached.shape as T[\"type\"] extends keyof ElementShapes\n ? ElementShapes[T[\"type\"]] | undefined\n : ElementShape | undefined;\n }\n return undefined;\n };\n\n public static delete = (element: ExcalidrawElement) => {\n ShapeCache.cache.delete(element);\n elementWithCanvasCache.delete(element);\n };\n\n public static destroy = () => {\n ShapeCache.cache = new WeakMap();\n };\n\n /**\n * Generates & caches shape for element if not already cached, otherwise\n * returns cached shape.\n */\n public static generateElementShape = <\n T extends Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,\n >(\n element: T,\n renderConfig: {\n isExporting: boolean;\n canvasBackgroundColor: AppState[\"viewBackgroundColor\"];\n embedsValidationStatus: EmbedsValidationStatus;\n theme: AppState[\"theme\"];\n } | null,\n ) => {\n // when exporting, always regenerated to guarantee the latest shape\n const cachedShape = renderConfig?.isExporting\n ? undefined\n : ShapeCache.get(element, renderConfig ? renderConfig.theme : null);\n\n // `null` indicates no rc shape applicable for this element type,\n // but it's considered a valid cache value (= do not regenerate)\n if (cachedShape !== undefined) {\n return cachedShape;\n }\n\n elementWithCanvasCache.delete(element);\n\n const shape = _generateElementShape(\n element,\n ShapeCache.rg,\n renderConfig || {\n isExporting: false,\n canvasBackgroundColor: COLOR_PALETTE.white,\n embedsValidationStatus: null,\n theme: THEME.LIGHT,\n },\n ) as T[\"type\"] extends keyof ElementShapes\n ? ElementShapes[T[\"type\"]]\n : Drawable | null;\n\n if (!renderConfig?.isExporting) {\n ShapeCache.cache.set(element, {\n shape,\n theme: renderConfig?.theme || THEME.LIGHT,\n });\n }\n\n return shape;\n };\n}\n\nconst getDashArrayDashed = (strokeWidth: number) => [8, 8 + strokeWidth];\n\nconst getDashArrayDotted = (strokeWidth: number) => [1.5, 6 + strokeWidth];\n\nfunction adjustRoughness(element: ExcalidrawElement): number {\n const roughness = element.roughness;\n\n const maxSize = Math.max(element.width, element.height);\n const minSize = Math.min(element.width, element.height);\n\n // don't reduce roughness if\n if (\n // both sides relatively big\n (minSize >= 20 && maxSize >= 50) ||\n // is round & both sides above 15px\n (minSize >= 15 &&\n !!element.roundness &&\n canChangeRoundness(element.type)) ||\n // relatively long linear element\n (isLinearElement(element) && maxSize >= 50)\n ) {\n return roughness;\n }\n\n return Math.min(roughness / (maxSize < 10 ? 3 : 2), 2.5);\n}\n\nexport const generateRoughOptions = (\n element: ExcalidrawElement,\n continuousPath = false,\n isDarkMode: boolean = false,\n): Options => {\n const options: Options = {\n seed: element.seed,\n strokeLineDash:\n element.strokeStyle === \"dashed\"\n ? getDashArrayDashed(element.strokeWidth)\n : element.strokeStyle === \"dotted\"\n ? getDashArrayDotted(element.strokeWidth)\n : undefined,\n // for non-solid strokes, disable multiStroke because it tends to make\n // dashes/dots overlay each other\n disableMultiStroke: element.strokeStyle !== \"solid\",\n // for non-solid strokes, increase the width a bit to make it visually\n // similar to solid strokes, because we're also disabling multiStroke\n strokeWidth:\n element.strokeStyle !== \"solid\"\n ? element.strokeWidth + 0.5\n : element.strokeWidth,\n // when increasing strokeWidth, we must explicitly set fillWeight and\n // hachureGap because if not specified, roughjs uses strokeWidth to\n // calculate them (and we don't want the fills to be modified)\n fillWeight: element.strokeWidth / 2,\n hachureGap: element.strokeWidth * 4,\n roughness: adjustRoughness(element),\n stroke: isDarkMode\n ? applyDarkModeFilter(element.strokeColor)\n : element.strokeColor,\n preserveVertices:\n continuousPath || element.roughness < ROUGHNESS.cartoonist,\n };\n\n switch (element.type) {\n case \"rectangle\":\n case \"iframe\":\n case \"embeddable\":\n case \"diamond\":\n case \"ellipse\": {\n options.fillStyle = element.fillStyle;\n options.fill = isTransparent(element.backgroundColor)\n ? undefined\n : isDarkMode\n ? applyDarkModeFilter(element.backgroundColor)\n : element.backgroundColor;\n if (element.type === \"ellipse\") {\n options.curveFitting = 1;\n }\n return options;\n }\n case \"line\":\n case \"freedraw\": {\n if (isPathALoop(element.points)) {\n options.fillStyle = element.fillStyle;\n options.fill =\n element.backgroundColor === \"transparent\"\n ? undefined\n : isDarkMode\n ? applyDarkModeFilter(element.backgroundColor)\n : element.backgroundColor;\n }\n return options;\n }\n case \"arrow\":\n return options;\n default: {\n throw new Error(`Unimplemented type ${element.type}`);\n }\n }\n};\n\nconst modifyIframeLikeForRoughOptions = (\n element: NonDeletedExcalidrawElement,\n isExporting: boolean,\n embedsValidationStatus: EmbedsValidationStatus | null,\n) => {\n if (\n isIframeLikeElement(element) &&\n (isExporting ||\n (isEmbeddableElement(element) &&\n embedsValidationStatus?.get(element.id) !== true)) &&\n isTransparent(element.backgroundColor) &&\n isTransparent(element.strokeColor)\n ) {\n return {\n ...element,\n roughness: 0,\n backgroundColor: \"#d3d3d3\",\n fillStyle: \"solid\",\n } as const;\n } else if (isIframeElement(element)) {\n return {\n ...element,\n strokeColor: isTransparent(element.strokeColor)\n ? \"#000000\"\n : element.strokeColor,\n backgroundColor: isTransparent(element.backgroundColor)\n ? \"#f4f4f6\"\n : element.backgroundColor,\n };\n }\n return element;\n};\n\nconst getArrowheadShapes = (\n element: ExcalidrawLinearElement,\n shape: Drawable[],\n position: \"start\" | \"end\",\n arrowhead: Arrowhead,\n generator: RoughGenerator,\n options: Options,\n canvasBackgroundColor: string,\n isDarkMode: boolean,\n) => {\n const arrowheadPoints = getArrowheadPoints(\n element,\n shape,\n position,\n arrowhead,\n );\n\n if (arrowheadPoints === null) {\n return [];\n }\n\n const generateCrowfootOne = (\n arrowheadPoints: number[] | null,\n options: Options,\n ) => {\n if (arrowheadPoints === null) {\n return [];\n }\n\n const [, , x3, y3, x4, y4] = arrowheadPoints;\n\n return [generator.line(x3, y3, x4, y4, options)];\n };\n\n const strokeColor = isDarkMode\n ? applyDarkModeFilter(element.strokeColor)\n : element.strokeColor;\n\n switch (arrowhead) {\n case \"dot\":\n case \"circle\":\n case \"circle_outline\": {\n const [x, y, diameter] = arrowheadPoints;\n\n // always use solid stroke for arrowhead\n delete options.strokeLineDash;\n\n return [\n generator.circle(x, y, diameter, {\n ...options,\n fill:\n arrowhead === \"circle_outline\"\n ? canvasBackgroundColor\n : strokeColor,\n\n fillStyle: \"solid\",\n stroke: strokeColor,\n roughness: Math.min(0.5, options.roughness || 0),\n }),\n ];\n }\n case \"triangle\":\n case \"triangle_outline\": {\n const [x, y, x2, y2, x3, y3] = arrowheadPoints;\n\n // always use solid stroke for arrowhead\n delete options.strokeLineDash;\n\n return [\n generator.polygon(\n [\n [x, y],\n [x2, y2],\n [x3, y3],\n [x, y],\n ],\n {\n ...options,\n fill:\n arrowhead === \"triangle_outline\"\n ? canvasBackgroundColor\n : strokeColor,\n fillStyle: \"solid\",\n roughness: Math.min(1, options.roughness || 0),\n },\n ),\n ];\n }\n case \"diamond\":\n case \"diamond_outline\": {\n const [x, y, x2, y2, x3, y3, x4, y4] = arrowheadPoints;\n\n // always use solid stroke for arrowhead\n delete options.strokeLineDash;\n\n return [\n generator.polygon(\n [\n [x, y],\n [x2, y2],\n [x3, y3],\n [x4, y4],\n [x, y],\n ],\n {\n ...options,\n fill:\n arrowhead === \"diamond_outline\"\n ? canvasBackgroundColor\n : strokeColor,\n fillStyle: \"solid\",\n roughness: Math.min(1, options.roughness || 0),\n },\n ),\n ];\n }\n case \"crowfoot_one\":\n return generateCrowfootOne(arrowheadPoints, options);\n case \"bar\":\n case \"arrow\":\n case \"crowfoot_many\":\n case \"crowfoot_one_or_many\":\n default: {\n const [x2, y2, x3, y3, x4, y4] = arrowheadPoints;\n\n if (element.strokeStyle === \"dotted\") {\n // for dotted arrows caps, reduce gap to make it more legible\n const dash = getDashArrayDotted(element.strokeWidth - 1);\n options.strokeLineDash = [dash[0], dash[1] - 1];\n } else {\n // for solid/dashed, keep solid arrow cap\n delete options.strokeLineDash;\n }\n options.roughness = Math.min(1, options.roughness || 0);\n return [\n generator.line(x3, y3, x2, y2, options),\n generator.line(x4, y4, x2, y2, options),\n ...(arrowhead === \"crowfoot_one_or_many\"\n ? generateCrowfootOne(\n getArrowheadPoints(element, shape, position, \"crowfoot_one\"),\n options,\n )\n : []),\n ];\n }\n }\n};\n\nexport const generateLinearCollisionShape = (\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\n) => {\n const generator = new RoughGenerator();\n const options: Options = {\n seed: element.seed,\n disableMultiStroke: true,\n disableMultiStrokeFill: true,\n roughness: 0,\n preserveVertices: true,\n };\n const center = getCenterForBounds(\n // Need a non-rotated center point\n element.points.reduce(\n (acc, point) => {\n return [\n Math.min(element.x + point[0], acc[0]),\n Math.min(element.y + point[1], acc[1]),\n Math.max(element.x + point[0], acc[2]),\n Math.max(element.y + point[1], acc[3]),\n ];\n },\n [Infinity, Infinity, -Infinity, -Infinity],\n ),\n );\n\n switch (element.type) {\n case \"line\":\n case \"arrow\": {\n // points array can be empty in the beginning, so it is important to add\n // initial position to it\n const points = element.points.length\n ? element.points\n : [pointFrom<LocalPoint>(0, 0)];\n\n if (isElbowArrow(element)) {\n return generator.path(generateElbowArrowShape(points, 16), options)\n .sets[0].ops;\n } else if (!element.roundness) {\n return points.map((point, idx) => {\n const p = pointRotateRads(\n pointFrom<GlobalPoint>(element.x + point[0], element.y + point[1]),\n center,\n element.angle,\n );\n\n return {\n op: idx === 0 ? \"move\" : \"lineTo\",\n data: pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\n };\n });\n }\n\n return generator\n .curve(points as unknown as RoughPoint[], options)\n .sets[0].ops.slice(0, element.points.length)\n .map((op, i) => {\n if (i === 0) {\n const p = pointRotateRads<GlobalPoint>(\n pointFrom<GlobalPoint>(\n element.x + op.data[0],\n element.y + op.data[1],\n ),\n center,\n element.angle,\n );\n\n return {\n op: \"move\",\n data: pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\n };\n }\n\n return {\n op: \"bcurveTo\",\n data: [\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + op.data[0],\n element.y + op.data[1],\n ),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + op.data[2],\n element.y + op.data[3],\n ),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + op.data[4],\n element.y + op.data[5],\n ),\n center,\n element.angle,\n ),\n ]\n .map((p) =>\n pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\n )\n .flat(),\n };\n });\n }\n case \"freedraw\": {\n if (element.points.length < 2) {\n return [];\n }\n\n const simplifiedPoints = simplify(\n element.points as Mutable<LocalPoint[]>,\n 0.75,\n );\n\n return generator\n .curve(simplifiedPoints as [number, number][], options)\n .sets[0].ops.slice(0, element.points.length)\n .map((op, i) => {\n if (i === 0) {\n const p = pointRotateRads<GlobalPoint>(\n pointFrom<GlobalPoint>(\n element.x + op.data[0],\n element.y + op.data[1],\n ),\n center,\n element.angle,\n );\n\n return {\n op: \"move\",\n data: pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\n };\n }\n\n return {\n op: \"bcurveTo\",\n data: [\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + op.data[0],\n element.y + op.data[1],\n ),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + op.data[2],\n element.y + op.data[3],\n ),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + op.data[4],\n element.y + op.data[5],\n ),\n center,\n element.angle,\n ),\n ]\n .map((p) =>\n pointFrom<LocalPoint>(p[0] - element.x, p[1] - element.y),\n )\n .flat(),\n };\n });\n }\n }\n};\n\n/**\n * Generates the roughjs shape for given element.\n *\n * Low-level. Use `ShapeCache.generateElementShape` instead.\n *\n * @private\n */\nconst _generateElementShape = (\n element: Exclude<NonDeletedExcalidrawElement, ExcalidrawSelectionElement>,\n generator: RoughGenerator,\n {\n isExporting,\n canvasBackgroundColor,\n embedsValidationStatus,\n theme,\n }: {\n isExporting: boolean;\n canvasBackgroundColor: string;\n embedsValidationStatus: EmbedsValidationStatus | null;\n theme?: AppState[\"theme\"];\n },\n): ElementShape => {\n const isDarkMode = theme === THEME.DARK;\n switch (element.type) {\n case \"rectangle\":\n case \"iframe\":\n case \"embeddable\": {\n let shape: ElementShapes[typeof element.type];\n // this is for rendering the stroke/bg of the embeddable, especially\n // when the src url is not set\n\n if (element.roundness) {\n const w = element.width;\n const h = element.height;\n const r = getCornerRadius(Math.min(w, h), element);\n shape = generator.path(\n `M ${r} 0 L ${w - r} 0 Q ${w} 0, ${w} ${r} L ${w} ${\n h - r\n } Q ${w} ${h}, ${w - r} ${h} L ${r} ${h} Q 0 ${h}, 0 ${\n h - r\n } L 0 ${r} Q 0 0, ${r} 0`,\n generateRoughOptions(\n modifyIframeLikeForRoughOptions(\n element,\n isExporting,\n embedsValidationStatus,\n ),\n true,\n isDarkMode,\n ),\n );\n } else {\n shape = generator.rectangle(\n 0,\n 0,\n element.width,\n element.height,\n generateRoughOptions(\n modifyIframeLikeForRoughOptions(\n element,\n isExporting,\n embedsValidationStatus,\n ),\n false,\n isDarkMode,\n ),\n );\n }\n return shape;\n }\n case \"diamond\": {\n let shape: ElementShapes[typeof element.type];\n\n const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =\n getDiamondPoints(element);\n if (element.roundness) {\n const verticalRadius = getCornerRadius(Math.abs(topX - leftX), element);\n\n const horizontalRadius = getCornerRadius(\n Math.abs(rightY - topY),\n element,\n );\n\n shape = generator.path(\n `M ${topX + verticalRadius} ${topY + horizontalRadius} L ${\n rightX - verticalRadius\n } ${rightY - horizontalRadius}\n C ${rightX} ${rightY}, ${rightX} ${rightY}, ${\n rightX - verticalRadius\n } ${rightY + horizontalRadius}\n L ${bottomX + verticalRadius} ${bottomY - horizontalRadius}\n C ${bottomX} ${bottomY}, ${bottomX} ${bottomY}, ${\n bottomX - verticalRadius\n } ${bottomY - horizontalRadius}\n L ${leftX + verticalRadius} ${leftY + horizontalRadius}\n C ${leftX} ${leftY}, ${leftX} ${leftY}, ${leftX + verticalRadius} ${\n leftY - horizontalRadius\n }\n L ${topX - verticalRadius} ${topY + horizontalRadius}\n C ${topX} ${topY}, ${topX} ${topY}, ${topX + verticalRadius} ${\n topY + horizontalRadius\n }`,\n generateRoughOptions(element, true, isDarkMode),\n );\n } else {\n shape = generator.polygon(\n [\n [topX, topY],\n [rightX, rightY],\n [bottomX, bottomY],\n [leftX, leftY],\n ],\n generateRoughOptions(element, false, isDarkMode),\n );\n }\n return shape;\n }\n case \"ellipse\": {\n const shape: ElementShapes[typeof element.type] = generator.ellipse(\n element.width / 2,\n element.height / 2,\n element.width,\n element.height,\n generateRoughOptions(element, false, isDarkMode),\n );\n return shape;\n }\n case \"line\":\n case \"arrow\": {\n let shape: ElementShapes[typeof element.type];\n const options = generateRoughOptions(element, false, isDarkMode);\n\n // points array can be empty in the beginning, so it is important to add\n // initial position to it\n const points = element.points.length\n ? element.points\n : [pointFrom<LocalPoint>(0, 0)];\n\n if (isElbowArrow(element)) {\n // NOTE (mtolmacs): Temporary fix for extremely big arrow shapes\n if (\n !points.every(\n (point) => Math.abs(point[0]) <= 1e6 && Math.abs(point[1]) <= 1e6,\n )\n ) {\n console.error(\n `Elbow arrow with extreme point positions detected. Arrow not rendered.`,\n element.id,\n JSON.stringify(points),\n );\n shape = [];\n } else {\n shape = [\n generator.path(\n generateElbowArrowShape(points, 16),\n generateRoughOptions(element, true, isDarkMode),\n ),\n ];\n }\n } else if (!element.roundness) {\n // curve is always the first element\n // this simplifies finding the curve for an element\n if (options.fill) {\n shape = [\n generator.polygon(points as unknown as RoughPoint[], options),\n ];\n } else {\n shape = [\n generator.linearPath(points as unknown as RoughPoint[], options),\n ];\n }\n } else {\n shape = [generator.curve(points as unknown as RoughPoint[], options)];\n }\n\n // add lines only in arrow\n if (element.type === \"arrow\") {\n const { startArrowhead = null, endArrowhead = \"arrow\" } = element;\n\n if (startArrowhead !== null) {\n const shapes = getArrowheadShapes(\n element,\n shape,\n \"start\",\n startArrowhead,\n generator,\n options,\n canvasBackgroundColor,\n isDarkMode,\n );\n shape.push(...shapes);\n }\n\n if (endArrowhead !== null) {\n if (endArrowhead === undefined) {\n // Hey, we have an old arrow here!\n }\n\n const shapes = getArrowheadShapes(\n element,\n shape,\n \"end\",\n endArrowhead,\n generator,\n options,\n canvasBackgroundColor,\n isDarkMode,\n );\n shape.push(...shapes);\n }\n }\n return shape;\n }\n case \"freedraw\": {\n // oredered in terms of z-index [background, stroke]\n const shapes: ElementShapes[typeof element.type] = [];\n\n // (1) background fill (rc shape), optional\n if (isPathALoop(element.points)) {\n // generate rough polygon to fill freedraw shape\n const simplifiedPoints = simplify(\n element.points as Mutable<LocalPoint[]>,\n 0.75,\n );\n shapes.push(\n generator.curve(simplifiedPoints as [number, number][], {\n ...generateRoughOptions(element, false, isDarkMode),\n stroke: \"none\",\n }),\n );\n }\n\n // (2) stroke\n shapes.push(getFreeDrawSvgPath(element));\n\n return shapes;\n }\n case \"frame\":\n case \"magicframe\":\n case \"text\":\n case \"image\": {\n const shape: ElementShapes[typeof element.type] = null;\n // we return (and cache) `null` to make sure we don't regenerate\n // `element.canvas` on rerenders\n return shape;\n }\n default: {\n assertNever(\n element,\n `generateElementShape(): Unimplemented type ${(element as any)?.type}`,\n );\n return null;\n }\n }\n};\n\nconst generateElbowArrowShape = (\n points: readonly LocalPoint[],\n radius: number,\n) => {\n const subpoints = [] as [number, number][];\n for (let i = 1; i < points.length - 1; i += 1) {\n const prev = points[i - 1];\n const next = points[i + 1];\n const point = points[i];\n const prevIsHorizontal = headingForPointIsHorizontal(point, prev);\n const nextIsHorizontal = headingForPointIsHorizontal(next, point);\n const corner = Math.min(\n radius,\n pointDistance(points[i], next) / 2,\n pointDistance(points[i], prev) / 2,\n );\n\n if (prevIsHorizontal) {\n if (prev[0] < point[0]) {\n // LEFT\n subpoints.push([points[i][0] - corner, points[i][1]]);\n } else {\n // RIGHT\n subpoints.push([points[i][0] + corner, points[i][1]]);\n }\n } else if (prev[1] < point[1]) {\n // UP\n subpoints.push([points[i][0], points[i][1] - corner]);\n } else {\n subpoints.push([points[i][0], points[i][1] + corner]);\n }\n\n subpoints.push(points[i] as [number, number]);\n\n if (nextIsHorizontal) {\n if (next[0] < point[0]) {\n // LEFT\n subpoints.push([points[i][0] - corner, points[i][1]]);\n } else {\n // RIGHT\n subpoints.push([points[i][0] + corner, points[i][1]]);\n }\n } else if (next[1] < point[1]) {\n // UP\n subpoints.push([points[i][0], points[i][1] - corner]);\n } else {\n // DOWN\n subpoints.push([points[i][0], points[i][1] + corner]);\n }\n }\n\n const d = [`M ${points[0][0]} ${points[0][1]}`];\n for (let i = 0; i < subpoints.length; i += 3) {\n d.push(`L ${subpoints[i][0]} ${subpoints[i][1]}`);\n d.push(\n `Q ${subpoints[i + 1][0]} ${subpoints[i + 1][1]}, ${\n subpoints[i + 2][0]\n } ${subpoints[i + 2][1]}`,\n );\n }\n d.push(`L ${points[points.length - 1][0]} ${points[points.length - 1][1]}`);\n\n return d.join(\" \");\n};\n\n/**\n * get the pure geometric shape of an excalidraw elementw\n * which is then used for hit detection\n */\nexport const getElementShape = <Point extends GlobalPoint | LocalPoint>(\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n): GeometricShape<Point> => {\n switch (element.type) {\n case \"rectangle\":\n case \"diamond\":\n case \"frame\":\n case \"magicframe\":\n case \"embeddable\":\n case \"image\":\n case \"iframe\":\n case \"text\":\n case \"selection\":\n return getPolygonShape(element);\n case \"arrow\":\n case \"line\": {\n const roughShape = ShapeCache.generateElementShape(element, null)[0];\n const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);\n\n return shouldTestInside(element)\n ? getClosedCurveShape<Point>(\n element,\n roughShape,\n pointFrom<Point>(element.x, element.y),\n element.angle,\n pointFrom(cx, cy),\n )\n : getCurveShape<Point>(\n roughShape,\n pointFrom<Point>(element.x, element.y),\n element.angle,\n pointFrom(cx, cy),\n );\n }\n\n case \"ellipse\":\n return getEllipseShape(element);\n\n case \"freedraw\": {\n const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);\n return getFreedrawShape(\n element,\n pointFrom(cx, cy),\n shouldTestInside(element),\n );\n }\n }\n};\n\nexport const toggleLinePolygonState = (\n element: ExcalidrawLineElement,\n nextPolygonState: boolean,\n): {\n polygon: ExcalidrawLineElement[\"polygon\"];\n points: ExcalidrawLineElement[\"points\"];\n} | null => {\n const updatedPoints = [...element.points];\n\n if (nextPolygonState) {\n if (!canBecomePolygon(element.points)) {\n return null;\n }\n\n const firstPoint = updatedPoints[0];\n const lastPoint = updatedPoints[updatedPoints.length - 1];\n\n const distance = Math.hypot(\n firstPoint[0] - lastPoint[0],\n firstPoint[1] - lastPoint[1],\n );\n\n if (\n distance > LINE_POLYGON_POINT_MERGE_DISTANCE ||\n updatedPoints.length < 4\n ) {\n updatedPoints.push(pointFrom(firstPoint[0], firstPoint[1]));\n } else {\n updatedPoints[updatedPoints.length - 1] = pointFrom(\n firstPoint[0],\n firstPoint[1],\n );\n }\n }\n\n // TODO: satisfies ElementUpdate<ExcalidrawLineElement>\n const ret = {\n polygon: nextPolygonState,\n points: updatedPoints,\n };\n\n return ret;\n};\n\n// -----------------------------------------------------------------------------\n// freedraw shape helper\n// -----------------------------------------------------------------------------\n\n// NOTE not cached (-> for SVG export)\nconst getFreeDrawSvgPath = (element: ExcalidrawFreeDrawElement) => {\n return getSvgPathFromStroke(\n getFreedrawOutlinePoints(element),\n ) as SVGPathString;\n};\n\nexport const getFreedrawOutlinePoints = (\n element: ExcalidrawFreeDrawElement,\n) => {\n // If input points are empty (should they ever be?) return a dot\n const inputPoints = element.simulatePressure\n ? element.points\n : element.points.length\n ? element.points.map(([x, y], i) => [x, y, element.pressures[i]])\n : [[0, 0, 0.5]];\n\n return getStroke(inputPoints as number[][], {\n simulatePressure: element.simulatePressure,\n size: element.strokeWidth * 4.25,\n thinning: 0.6,\n smoothing: 0.5,\n streamline: 0.5,\n easing: (t) => Math.sin((t * Math.PI) / 2), // https://easings.net/#easeOutSine\n last: true,\n }) as [number, number][];\n};\n\nconst med = (A: number[], B: number[]) => {\n return [(A[0] + B[0]) / 2, (A[1] + B[1]) / 2];\n};\n\n// Trim SVG path data so number are each two decimal points. This\n// improves SVG exports, and prevents rendering errors on points\n// with long decimals.\nconst TO_FIXED_PRECISION = /(\\s?[A-Z]?,?-?[0-9]*\\.[0-9]{0,2})(([0-9]|e|-)*)/g;\n\nconst getSvgPathFromStroke = (points: number[][]): string => {\n if (!points.length) {\n return \"\";\n }\n\n const max = points.length - 1;\n\n return points\n .reduce(\n (acc, point, i, arr) => {\n if (i === max) {\n acc.push(point, med(point, arr[0]), \"L\", arr[0], \"Z\");\n } else {\n acc.push(point, med(point, arr[i + 1]));\n }\n return acc;\n },\n [\"M\", points[0], \"Q\"],\n )\n .join(\" \")\n .replace(TO_FIXED_PRECISION, \"$1\");\n};\n\n// -----------------------------------------------------------------------------\n", "import rough from \"roughjs/bin/rough\";\n\nimport {\n type GlobalPoint,\n isRightAngleRads,\n lineSegment,\n pointFrom,\n pointRotateRads,\n type Radians,\n} from \"@excalidraw/math\";\n\nimport {\n BOUND_TEXT_PADDING,\n DEFAULT_REDUCED_GLOBAL_ALPHA,\n ELEMENT_READY_TO_ERASE_OPACITY,\n FRAME_STYLE,\n MIME_TYPES,\n THEME,\n distance,\n getFontString,\n isRTL,\n getVerticalOffset,\n invariant,\n applyDarkModeFilter,\n} from \"@excalidraw/common\";\n\nimport type {\n AppState,\n StaticCanvasAppState,\n Zoom,\n InteractiveCanvasAppState,\n ElementsPendingErasure,\n PendingExcalidrawElements,\n NormalizedZoomValue,\n} from \"@excalidraw/excalidraw/types\";\n\nimport type {\n StaticCanvasRenderConfig,\n RenderableElementsMap,\n InteractiveCanvasRenderConfig,\n} from \"@excalidraw/excalidraw/scene/types\";\n\nimport { getElementAbsoluteCoords, getElementBounds } from \"./bounds\";\nimport { getUncroppedImageElement } from \"./cropElement\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport {\n getBoundTextElement,\n getContainerCoords,\n getContainerElement,\n getBoundTextMaxHeight,\n getBoundTextMaxWidth,\n} from \"./textElement\";\nimport { getLineHeightInPx } from \"./textMeasurements\";\nimport {\n isTextElement,\n isLinearElement,\n isFreeDrawElement,\n isInitializedImageElement,\n isArrowElement,\n hasBoundTextElement,\n isMagicFrameElement,\n isImageElement,\n} from \"./typeChecks\";\nimport { getContainingFrame } from \"./frame\";\nimport { getCornerRadius } from \"./utils\";\n\nimport { ShapeCache } from \"./shape\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawTextElement,\n NonDeletedExcalidrawElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawImageElement,\n ExcalidrawTextElementWithContainer,\n ExcalidrawFrameLikeElement,\n NonDeletedSceneElementsMap,\n ElementsMap,\n} from \"./types\";\n\nimport type { RoughCanvas } from \"roughjs/bin/canvas\";\n\nconst isPendingImageElement = (\n element: ExcalidrawElement,\n renderConfig: StaticCanvasRenderConfig,\n) =>\n isInitializedImageElement(element) &&\n !renderConfig.imageCache.has(element.fileId);\n\nconst getCanvasPadding = (element: ExcalidrawElement) => {\n switch (element.type) {\n case \"freedraw\":\n return element.strokeWidth * 12;\n case \"text\":\n return element.fontSize / 2;\n case \"arrow\":\n if (element.endArrowhead || element.endArrowhead) {\n return 40;\n }\n return 20;\n default:\n return 20;\n }\n};\n\nexport const getRenderOpacity = (\n element: ExcalidrawElement,\n containingFrame: ExcalidrawFrameLikeElement | null,\n elementsPendingErasure: ElementsPendingErasure,\n pendingNodes: Readonly<PendingExcalidrawElements> | null,\n globalAlpha: number = 1,\n) => {\n // multiplying frame opacity with element opacity to combine them\n // (e.g. frame 50% and element 50% opacity should result in 25% opacity)\n let opacity =\n (((containingFrame?.opacity ?? 100) * element.opacity) / 10000) *\n globalAlpha;\n\n // if pending erasure, multiply again to combine further\n // (so that erasing always results in lower opacity than original)\n if (\n elementsPendingErasure.has(element.id) ||\n (pendingNodes && pendingNodes.some((node) => node.id === element.id)) ||\n (containingFrame && elementsPendingErasure.has(containingFrame.id))\n ) {\n opacity *= ELEMENT_READY_TO_ERASE_OPACITY / 100;\n }\n\n return opacity;\n};\n\nexport interface ExcalidrawElementWithCanvas {\n element: ExcalidrawElement | ExcalidrawTextElement;\n canvas: HTMLCanvasElement;\n theme: AppState[\"theme\"];\n scale: number;\n angle: number;\n zoomValue: AppState[\"zoom\"][\"value\"];\n canvasOffsetX: number;\n canvasOffsetY: number;\n boundTextElementVersion: number | null;\n imageCrop: ExcalidrawImageElement[\"crop\"] | null;\n containingFrameOpacity: number;\n boundTextCanvas: HTMLCanvasElement;\n}\n\nconst cappedElementCanvasSize = (\n element: NonDeletedExcalidrawElement,\n elementsMap: ElementsMap,\n zoom: Zoom,\n): {\n width: number;\n height: number;\n scale: number;\n} => {\n // these limits are ballpark, they depend on specific browsers and device.\n // We've chosen lower limits to be safe. We might want to change these limits\n // based on browser/device type, if we get reports of low quality rendering\n // on zoom.\n //\n // ~ safari mobile canvas area limit\n const AREA_LIMIT = 16777216;\n // ~ safari width/height limit based on developer.mozilla.org.\n const WIDTH_HEIGHT_LIMIT = 32767;\n\n const padding = getCanvasPadding(element);\n\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const elementWidth =\n isLinearElement(element) || isFreeDrawElement(element)\n ? distance(x1, x2)\n : element.width;\n const elementHeight =\n isLinearElement(element) || isFreeDrawElement(element)\n ? distance(y1, y2)\n : element.height;\n\n let width = elementWidth * window.devicePixelRatio + padding * 2;\n let height = elementHeight * window.devicePixelRatio + padding * 2;\n\n let scale: number = zoom.value;\n\n // rescale to ensure width and height is within limits\n if (\n width * scale > WIDTH_HEIGHT_LIMIT ||\n height * scale > WIDTH_HEIGHT_LIMIT\n ) {\n scale = Math.min(WIDTH_HEIGHT_LIMIT / width, WIDTH_HEIGHT_LIMIT / height);\n }\n\n // rescale to ensure canvas area is within limits\n if (width * height * scale * scale > AREA_LIMIT) {\n scale = Math.sqrt(AREA_LIMIT / (width * height));\n }\n\n width = Math.floor(width * scale);\n height = Math.floor(height * scale);\n\n return { width, height, scale };\n};\n\nconst generateElementCanvas = (\n element: NonDeletedExcalidrawElement,\n elementsMap: NonDeletedSceneElementsMap,\n zoom: Zoom,\n renderConfig: StaticCanvasRenderConfig,\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\n): ExcalidrawElementWithCanvas | null => {\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\")!;\n const padding = getCanvasPadding(element);\n\n const { width, height, scale } = cappedElementCanvasSize(\n element,\n elementsMap,\n zoom,\n );\n\n if (!width || !height) {\n return null;\n }\n\n canvas.width = width;\n canvas.height = height;\n\n let canvasOffsetX = -100;\n let canvasOffsetY = 0;\n\n if (isLinearElement(element) || isFreeDrawElement(element)) {\n const [x1, y1] = getElementAbsoluteCoords(element, elementsMap);\n\n canvasOffsetX =\n element.x > x1\n ? distance(element.x, x1) * window.devicePixelRatio * scale\n : 0;\n\n canvasOffsetY =\n element.y > y1\n ? distance(element.y, y1) * window.devicePixelRatio * scale\n : 0;\n\n context.translate(canvasOffsetX, canvasOffsetY);\n }\n\n context.save();\n context.translate(padding * scale, padding * scale);\n context.scale(\n window.devicePixelRatio * scale,\n window.devicePixelRatio * scale,\n );\n\n const rc = rough.canvas(canvas);\n\n drawElementOnCanvas(element, rc, context, renderConfig);\n\n context.restore();\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n const boundTextCanvas = document.createElement(\"canvas\");\n const boundTextCanvasContext = boundTextCanvas.getContext(\"2d\")!;\n\n if (isArrowElement(element) && boundTextElement) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n // Take max dimensions of arrow canvas so that when canvas is rotated\n // the arrow doesn't get clipped\n const maxDim = Math.max(distance(x1, x2), distance(y1, y2));\n boundTextCanvas.width =\n maxDim * window.devicePixelRatio * scale + padding * scale * 10;\n boundTextCanvas.height =\n maxDim * window.devicePixelRatio * scale + padding * scale * 10;\n boundTextCanvasContext.translate(\n boundTextCanvas.width / 2,\n boundTextCanvas.height / 2,\n );\n boundTextCanvasContext.rotate(element.angle);\n boundTextCanvasContext.drawImage(\n canvas!,\n -canvas.width / 2,\n -canvas.height / 2,\n canvas.width,\n canvas.height,\n );\n\n const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords(\n boundTextElement,\n elementsMap,\n );\n\n boundTextCanvasContext.rotate(-element.angle);\n const offsetX = (boundTextCanvas.width - canvas!.width) / 2;\n const offsetY = (boundTextCanvas.height - canvas!.height) / 2;\n const shiftX =\n boundTextCanvas.width / 2 -\n (boundTextCx - x1) * window.devicePixelRatio * scale -\n offsetX -\n padding * scale;\n\n const shiftY =\n boundTextCanvas.height / 2 -\n (boundTextCy - y1) * window.devicePixelRatio * scale -\n offsetY -\n padding * scale;\n boundTextCanvasContext.translate(-shiftX, -shiftY);\n // Clear the bound text area\n boundTextCanvasContext.clearRect(\n -(boundTextElement.width / 2 + BOUND_TEXT_PADDING) *\n window.devicePixelRatio *\n scale,\n -(boundTextElement.height / 2 + BOUND_TEXT_PADDING) *\n window.devicePixelRatio *\n scale,\n (boundTextElement.width + BOUND_TEXT_PADDING * 2) *\n window.devicePixelRatio *\n scale,\n (boundTextElement.height + BOUND_TEXT_PADDING * 2) *\n window.devicePixelRatio *\n scale,\n );\n }\n\n return {\n element,\n canvas,\n theme: appState.theme,\n scale,\n zoomValue: zoom.value,\n canvasOffsetX,\n canvasOffsetY,\n boundTextElementVersion:\n getBoundTextElement(element, elementsMap)?.version || null,\n containingFrameOpacity:\n getContainingFrame(element, elementsMap)?.opacity || 100,\n boundTextCanvas,\n angle: element.angle,\n imageCrop: isImageElement(element) ? element.crop : null,\n };\n};\n\nexport const DEFAULT_LINK_SIZE = 14;\n\nconst IMAGE_PLACEHOLDER_IMG =\n typeof document !== \"undefined\"\n ? document.createElement(\"img\")\n : ({ src: \"\" } as HTMLImageElement); // mock image element outside of browser\n\nIMAGE_PLACEHOLDER_IMG.src = `data:${MIME_TYPES.svg},${encodeURIComponent(\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>`,\n)}`;\n\nconst IMAGE_ERROR_PLACEHOLDER_IMG =\n typeof document !== \"undefined\"\n ? document.createElement(\"img\")\n : ({ src: \"\" } as HTMLImageElement); // mock image element outside of browser\n\nIMAGE_ERROR_PLACEHOLDER_IMG.src = `data:${MIME_TYPES.svg},${encodeURIComponent(\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>`,\n)}`;\n\nconst drawImagePlaceholder = (\n element: ExcalidrawImageElement,\n context: CanvasRenderingContext2D,\n) => {\n context.fillStyle = \"#E7E7E7\";\n context.fillRect(0, 0, element.width, element.height);\n\n const imageMinWidthOrHeight = Math.min(element.width, element.height);\n\n const size = Math.min(\n imageMinWidthOrHeight,\n Math.min(imageMinWidthOrHeight * 0.4, 100),\n );\n\n context.drawImage(\n element.status === \"error\"\n ? IMAGE_ERROR_PLACEHOLDER_IMG\n : IMAGE_PLACEHOLDER_IMG,\n element.width / 2 - size / 2,\n element.height / 2 - size / 2,\n size,\n size,\n );\n};\n\nconst drawElementOnCanvas = (\n element: NonDeletedExcalidrawElement,\n rc: RoughCanvas,\n context: CanvasRenderingContext2D,\n renderConfig: StaticCanvasRenderConfig,\n) => {\n switch (element.type) {\n case \"rectangle\":\n case \"iframe\":\n case \"embeddable\":\n case \"diamond\":\n case \"ellipse\": {\n context.lineJoin = \"round\";\n context.lineCap = \"round\";\n\n rc.draw(ShapeCache.generateElementShape(element, renderConfig));\n break;\n }\n case \"arrow\":\n case \"line\": {\n context.lineJoin = \"round\";\n context.lineCap = \"round\";\n\n ShapeCache.generateElementShape(element, renderConfig).forEach(\n (shape) => {\n rc.draw(shape);\n },\n );\n break;\n }\n case \"freedraw\": {\n // Draw directly to canvas\n context.save();\n\n const shapes = ShapeCache.generateElementShape(element, renderConfig);\n\n for (const shape of shapes) {\n if (typeof shape === \"string\") {\n context.fillStyle =\n renderConfig.theme === THEME.DARK\n ? applyDarkModeFilter(element.strokeColor)\n : element.strokeColor;\n context.fill(new Path2D(shape));\n } else {\n rc.draw(shape);\n }\n }\n\n context.restore();\n break;\n }\n case \"image\": {\n const img = isInitializedImageElement(element)\n ? renderConfig.imageCache.get(element.fileId)?.image\n : undefined;\n if (img != null && !(img instanceof Promise)) {\n if (element.roundness && context.roundRect) {\n context.beginPath();\n context.roundRect(\n 0,\n 0,\n element.width,\n element.height,\n getCornerRadius(Math.min(element.width, element.height), element),\n );\n context.clip();\n }\n\n const { x, y, width, height } = element.crop\n ? element.crop\n : {\n x: 0,\n y: 0,\n width: img.naturalWidth,\n height: img.naturalHeight,\n };\n\n context.drawImage(\n img,\n x,\n y,\n width,\n height,\n 0 /* hardcoded for the selection box*/,\n 0,\n element.width,\n element.height,\n );\n } else {\n drawImagePlaceholder(element, context);\n }\n break;\n }\n default: {\n if (isTextElement(element)) {\n const rtl = isRTL(element.text);\n const shouldTemporarilyAttach = rtl && !context.canvas.isConnected;\n if (shouldTemporarilyAttach) {\n // to correctly render RTL text mixed with LTR, we have to append it\n // to the DOM\n document.body.appendChild(context.canvas);\n }\n context.canvas.setAttribute(\"dir\", rtl ? \"rtl\" : \"ltr\");\n context.save();\n context.font = getFontString(element);\n context.fillStyle =\n renderConfig.theme === THEME.DARK\n ? applyDarkModeFilter(element.strokeColor)\n : element.strokeColor;\n context.textAlign = element.textAlign as CanvasTextAlign;\n\n // Canvas does not support multiline text by default\n const lines = element.text.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n\n const horizontalOffset =\n element.textAlign === \"center\"\n ? element.width / 2\n : element.textAlign === \"right\"\n ? element.width\n : 0;\n\n const lineHeightPx = getLineHeightInPx(\n element.fontSize,\n element.lineHeight,\n );\n\n const verticalOffset = getVerticalOffset(\n element.fontFamily,\n element.fontSize,\n lineHeightPx,\n );\n\n for (let index = 0; index < lines.length; index++) {\n context.fillText(\n lines[index],\n horizontalOffset,\n index * lineHeightPx + verticalOffset,\n );\n }\n context.restore();\n if (shouldTemporarilyAttach) {\n context.canvas.remove();\n }\n } else {\n throw new Error(`Unimplemented type ${element.type}`);\n }\n }\n }\n};\n\nexport const elementWithCanvasCache = new WeakMap<\n ExcalidrawElement,\n ExcalidrawElementWithCanvas\n>();\n\nconst generateElementWithCanvas = (\n element: NonDeletedExcalidrawElement,\n elementsMap: NonDeletedSceneElementsMap,\n renderConfig: StaticCanvasRenderConfig,\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\n) => {\n const zoom: Zoom = renderConfig\n ? appState.zoom\n : {\n value: 1 as NormalizedZoomValue,\n };\n const prevElementWithCanvas = elementWithCanvasCache.get(element);\n const shouldRegenerateBecauseZoom =\n prevElementWithCanvas &&\n prevElementWithCanvas.zoomValue !== zoom.value &&\n !appState?.shouldCacheIgnoreZoom;\n const boundTextElement = getBoundTextElement(element, elementsMap);\n const boundTextElementVersion = boundTextElement?.version || null;\n const imageCrop = isImageElement(element) ? element.crop : null;\n\n const containingFrameOpacity =\n getContainingFrame(element, elementsMap)?.opacity || 100;\n\n if (\n !prevElementWithCanvas ||\n shouldRegenerateBecauseZoom ||\n prevElementWithCanvas.theme !== appState.theme ||\n prevElementWithCanvas.boundTextElementVersion !== boundTextElementVersion ||\n prevElementWithCanvas.imageCrop !== imageCrop ||\n prevElementWithCanvas.containingFrameOpacity !== containingFrameOpacity ||\n // since we rotate the canvas when copying from cached canvas, we don't\n // regenerate the cached canvas. But we need to in case of labels which are\n // cached alongside the arrow, and we want the labels to remain unrotated\n // with respect to the arrow.\n (isArrowElement(element) &&\n boundTextElement &&\n element.angle !== prevElementWithCanvas.angle)\n ) {\n const elementWithCanvas = generateElementCanvas(\n element,\n elementsMap,\n zoom,\n renderConfig,\n appState,\n );\n\n if (!elementWithCanvas) {\n return null;\n }\n\n elementWithCanvasCache.set(element, elementWithCanvas);\n\n return elementWithCanvas;\n }\n return prevElementWithCanvas;\n};\n\nconst drawElementFromCanvas = (\n elementWithCanvas: ExcalidrawElementWithCanvas,\n context: CanvasRenderingContext2D,\n renderConfig: StaticCanvasRenderConfig,\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\n allElementsMap: NonDeletedSceneElementsMap,\n) => {\n const element = elementWithCanvas.element;\n const padding = getCanvasPadding(element);\n const zoom = elementWithCanvas.scale;\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, allElementsMap);\n const cx = ((x1 + x2) / 2 + appState.scrollX) * window.devicePixelRatio;\n const cy = ((y1 + y2) / 2 + appState.scrollY) * window.devicePixelRatio;\n\n context.save();\n context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);\n\n const boundTextElement = getBoundTextElement(element, allElementsMap);\n\n if (isArrowElement(element) && boundTextElement) {\n const offsetX =\n (elementWithCanvas.boundTextCanvas.width -\n elementWithCanvas.canvas!.width) /\n 2;\n const offsetY =\n (elementWithCanvas.boundTextCanvas.height -\n elementWithCanvas.canvas!.height) /\n 2;\n context.translate(cx, cy);\n context.drawImage(\n elementWithCanvas.boundTextCanvas,\n (-(x2 - x1) / 2) * window.devicePixelRatio - offsetX / zoom - padding,\n (-(y2 - y1) / 2) * window.devicePixelRatio - offsetY / zoom - padding,\n elementWithCanvas.boundTextCanvas.width / zoom,\n elementWithCanvas.boundTextCanvas.height / zoom,\n );\n } else {\n // we translate context to element center so that rotation and scale\n // originates from the element center\n context.translate(cx, cy);\n\n context.rotate(element.angle);\n\n if (\n \"scale\" in elementWithCanvas.element &&\n !isPendingImageElement(element, renderConfig)\n ) {\n context.scale(\n elementWithCanvas.element.scale[0],\n elementWithCanvas.element.scale[1],\n );\n }\n\n // revert afterwards we don't have account for it during drawing\n context.translate(-cx, -cy);\n\n context.drawImage(\n elementWithCanvas.canvas!,\n (x1 + appState.scrollX) * window.devicePixelRatio -\n (padding * elementWithCanvas.scale) / elementWithCanvas.scale,\n (y1 + appState.scrollY) * window.devicePixelRatio -\n (padding * elementWithCanvas.scale) / elementWithCanvas.scale,\n elementWithCanvas.canvas!.width / elementWithCanvas.scale,\n elementWithCanvas.canvas!.height / elementWithCanvas.scale,\n );\n\n if (\n import.meta.env.VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX ===\n \"true\" &&\n hasBoundTextElement(element)\n ) {\n const textElement = getBoundTextElement(\n element,\n allElementsMap,\n ) as ExcalidrawTextElementWithContainer;\n const coords = getContainerCoords(element);\n context.strokeStyle = \"#c92a2a\";\n context.lineWidth = 3;\n context.strokeRect(\n (coords.x + appState.scrollX) * window.devicePixelRatio,\n (coords.y + appState.scrollY) * window.devicePixelRatio,\n getBoundTextMaxWidth(element, textElement) * window.devicePixelRatio,\n getBoundTextMaxHeight(element, textElement) * window.devicePixelRatio,\n );\n }\n }\n context.restore();\n\n // Clear the nested element we appended to the DOM\n};\n\nexport const renderSelectionElement = (\n element: NonDeletedExcalidrawElement,\n context: CanvasRenderingContext2D,\n appState: InteractiveCanvasAppState,\n selectionColor: InteractiveCanvasRenderConfig[\"selectionColor\"],\n) => {\n context.save();\n context.translate(element.x + appState.scrollX, element.y + appState.scrollY);\n context.fillStyle = \"rgba(0, 0, 200, 0.04)\";\n\n // render from 0.5px offset to get 1px wide line\n // https://stackoverflow.com/questions/7530593/html5-canvas-and-line-width/7531540#7531540\n // TODO can be be improved by offseting to the negative when user selects\n // from right to left\n const offset = 0.5 / appState.zoom.value;\n\n context.fillRect(offset, offset, element.width, element.height);\n context.lineWidth = 1 / appState.zoom.value;\n context.strokeStyle = selectionColor;\n context.strokeRect(offset, offset, element.width, element.height);\n\n context.restore();\n};\n\nexport const renderElement = (\n element: NonDeletedExcalidrawElement,\n elementsMap: RenderableElementsMap,\n allElementsMap: NonDeletedSceneElementsMap,\n rc: RoughCanvas,\n context: CanvasRenderingContext2D,\n renderConfig: StaticCanvasRenderConfig,\n appState: StaticCanvasAppState | InteractiveCanvasAppState,\n) => {\n const reduceAlphaForSelection =\n appState.openDialog?.name === \"elementLinkSelector\" &&\n !appState.selectedElementIds[element.id] &&\n !appState.hoveredElementIds[element.id];\n\n context.globalAlpha = getRenderOpacity(\n element,\n getContainingFrame(element, elementsMap),\n renderConfig.elementsPendingErasure,\n renderConfig.pendingFlowchartNodes,\n reduceAlphaForSelection ? DEFAULT_REDUCED_GLOBAL_ALPHA : 1,\n );\n\n switch (element.type) {\n case \"magicframe\":\n case \"frame\": {\n if (appState.frameRendering.enabled && appState.frameRendering.outline) {\n context.save();\n context.translate(\n element.x + appState.scrollX,\n element.y + appState.scrollY,\n );\n context.fillStyle = \"rgba(0, 0, 200, 0.04)\";\n\n context.lineWidth = FRAME_STYLE.strokeWidth / appState.zoom.value;\n context.strokeStyle =\n appState.theme === THEME.DARK\n ? applyDarkModeFilter(FRAME_STYLE.strokeColor)\n : FRAME_STYLE.strokeColor;\n\n // TODO change later to only affect AI frames\n if (isMagicFrameElement(element)) {\n context.strokeStyle =\n appState.theme === THEME.LIGHT\n ? \"#7affd7\"\n : applyDarkModeFilter(\"#1d8264\");\n }\n\n if (FRAME_STYLE.radius && context.roundRect) {\n context.beginPath();\n context.roundRect(\n 0,\n 0,\n element.width,\n element.height,\n FRAME_STYLE.radius / appState.zoom.value,\n );\n context.stroke();\n context.closePath();\n } else {\n context.strokeRect(0, 0, element.width, element.height);\n }\n\n context.restore();\n }\n break;\n }\n case \"freedraw\": {\n if (renderConfig.isExporting) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2 + appState.scrollX;\n const cy = (y1 + y2) / 2 + appState.scrollY;\n const shiftX = (x2 - x1) / 2 - (element.x - x1);\n const shiftY = (y2 - y1) / 2 - (element.y - y1);\n context.save();\n context.translate(cx, cy);\n context.rotate(element.angle);\n context.translate(-shiftX, -shiftY);\n drawElementOnCanvas(element, rc, context, renderConfig);\n context.restore();\n } else {\n const elementWithCanvas = generateElementWithCanvas(\n element,\n allElementsMap,\n renderConfig,\n appState,\n );\n if (!elementWithCanvas) {\n return;\n }\n\n drawElementFromCanvas(\n elementWithCanvas,\n context,\n renderConfig,\n appState,\n allElementsMap,\n );\n }\n\n break;\n }\n case \"rectangle\":\n case \"diamond\":\n case \"ellipse\":\n case \"line\":\n case \"arrow\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\": {\n if (renderConfig.isExporting) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2 + appState.scrollX;\n const cy = (y1 + y2) / 2 + appState.scrollY;\n let shiftX = (x2 - x1) / 2 - (element.x - x1);\n let shiftY = (y2 - y1) / 2 - (element.y - y1);\n if (isTextElement(element)) {\n const container = getContainerElement(element, elementsMap);\n if (isArrowElement(container)) {\n const boundTextCoords =\n LinearElementEditor.getBoundTextElementPosition(\n container,\n element as ExcalidrawTextElementWithContainer,\n elementsMap,\n );\n shiftX = (x2 - x1) / 2 - (boundTextCoords.x - x1);\n shiftY = (y2 - y1) / 2 - (boundTextCoords.y - y1);\n }\n }\n context.save();\n context.translate(cx, cy);\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n\n if (isArrowElement(element) && boundTextElement) {\n const tempCanvas = document.createElement(\"canvas\");\n\n const tempCanvasContext = tempCanvas.getContext(\"2d\")!;\n\n // Take max dimensions of arrow canvas so that when canvas is rotated\n // the arrow doesn't get clipped\n const maxDim = Math.max(distance(x1, x2), distance(y1, y2));\n const padding = getCanvasPadding(element);\n tempCanvas.width =\n maxDim * appState.exportScale + padding * 10 * appState.exportScale;\n tempCanvas.height =\n maxDim * appState.exportScale + padding * 10 * appState.exportScale;\n\n tempCanvasContext.translate(\n tempCanvas.width / 2,\n tempCanvas.height / 2,\n );\n tempCanvasContext.scale(appState.exportScale, appState.exportScale);\n\n // Shift the canvas to left most point of the arrow\n shiftX = element.width / 2 - (element.x - x1);\n shiftY = element.height / 2 - (element.y - y1);\n\n tempCanvasContext.rotate(element.angle);\n const tempRc = rough.canvas(tempCanvas);\n\n tempCanvasContext.translate(-shiftX, -shiftY);\n\n drawElementOnCanvas(element, tempRc, tempCanvasContext, renderConfig);\n\n tempCanvasContext.translate(shiftX, shiftY);\n\n tempCanvasContext.rotate(-element.angle);\n\n // Shift the canvas to center of bound text\n const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords(\n boundTextElement,\n elementsMap,\n );\n const boundTextShiftX = (x1 + x2) / 2 - boundTextCx;\n const boundTextShiftY = (y1 + y2) / 2 - boundTextCy;\n tempCanvasContext.translate(-boundTextShiftX, -boundTextShiftY);\n\n // Clear the bound text area\n tempCanvasContext.clearRect(\n -boundTextElement.width / 2,\n -boundTextElement.height / 2,\n boundTextElement.width,\n boundTextElement.height,\n );\n context.scale(1 / appState.exportScale, 1 / appState.exportScale);\n context.drawImage(\n tempCanvas,\n -tempCanvas.width / 2,\n -tempCanvas.height / 2,\n tempCanvas.width,\n tempCanvas.height,\n );\n } else {\n context.rotate(element.angle);\n\n if (element.type === \"image\") {\n // note: scale must be applied *after* rotating\n context.scale(element.scale[0], element.scale[1]);\n }\n\n context.translate(-shiftX, -shiftY);\n drawElementOnCanvas(element, rc, context, renderConfig);\n }\n\n context.restore();\n // not exporting \u2192 optimized rendering (cache & render from element\n // canvases)\n } else {\n const elementWithCanvas = generateElementWithCanvas(\n element,\n allElementsMap,\n renderConfig,\n appState,\n );\n\n if (!elementWithCanvas) {\n return;\n }\n\n const currentImageSmoothingStatus = context.imageSmoothingEnabled;\n\n if (\n // do not disable smoothing during zoom as blurry shapes look better\n // on low resolution (while still zooming in) than sharp ones\n !appState?.shouldCacheIgnoreZoom &&\n // angle is 0 -> always disable smoothing\n (!element.angle ||\n // or check if angle is a right angle in which case we can still\n // disable smoothing without adversely affecting the result\n // We need less-than comparison because of FP artihmetic\n isRightAngleRads(element.angle))\n ) {\n // Disabling smoothing makes output much sharper, especially for\n // text. Unless for non-right angles, where the aliasing is really\n // terrible on Chromium.\n //\n // Note that `context.imageSmoothingQuality=\"high\"` has almost\n // zero effect.\n //\n context.imageSmoothingEnabled = false;\n }\n\n if (\n element.id === appState.croppingElementId &&\n isImageElement(elementWithCanvas.element) &&\n elementWithCanvas.element.crop !== null\n ) {\n context.save();\n context.globalAlpha = 0.1;\n\n const uncroppedElementCanvas = generateElementCanvas(\n getUncroppedImageElement(elementWithCanvas.element, elementsMap),\n allElementsMap,\n appState.zoom,\n renderConfig,\n appState,\n );\n\n if (uncroppedElementCanvas) {\n drawElementFromCanvas(\n uncroppedElementCanvas,\n context,\n renderConfig,\n appState,\n allElementsMap,\n );\n }\n\n context.restore();\n }\n\n drawElementFromCanvas(\n elementWithCanvas,\n context,\n renderConfig,\n appState,\n allElementsMap,\n );\n\n // reset\n context.imageSmoothingEnabled = currentImageSmoothingStatus;\n }\n break;\n }\n default: {\n // @ts-ignore\n throw new Error(`Unimplemented type ${element.type}`);\n }\n }\n\n context.globalAlpha = 1;\n};\n\nexport function getFreedrawOutlineAsSegments(\n element: ExcalidrawFreeDrawElement,\n points: [number, number][],\n elementsMap: ElementsMap,\n) {\n const bounds = getElementBounds(\n {\n ...element,\n angle: 0 as Radians,\n },\n elementsMap,\n );\n const center = pointFrom<GlobalPoint>(\n (bounds[0] + bounds[2]) / 2,\n (bounds[1] + bounds[3]) / 2,\n );\n\n invariant(points.length >= 2, \"Freepath outline must have at least 2 points\");\n\n return points.slice(2).reduce(\n (acc, curr) => {\n acc.push(\n lineSegment<GlobalPoint>(\n acc[acc.length - 1][1],\n pointRotateRads(\n pointFrom<GlobalPoint>(curr[0] + element.x, curr[1] + element.y),\n center,\n element.angle,\n ),\n ),\n );\n return acc;\n },\n [\n lineSegment<GlobalPoint>(\n pointRotateRads(\n pointFrom<GlobalPoint>(\n points[0][0] + element.x,\n points[0][1] + element.y,\n ),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n points[1][0] + element.x,\n points[1][1] + element.y,\n ),\n center,\n element.angle,\n ),\n ),\n ],\n );\n}\n", "import {\n type Radians,\n pointFrom,\n pointCenter,\n pointRotateRads,\n vectorFromPoint,\n vectorNormalize,\n vectorSubtract,\n vectorAdd,\n vectorScale,\n pointFromVector,\n clamp,\n isCloseTo,\n} from \"@excalidraw/math\";\nimport { type Point } from \"points-on-curve\";\n\nimport {\n elementCenterPoint,\n getElementAbsoluteCoords,\n getResizedElementAbsoluteCoords,\n} from \"./bounds\";\n\nimport type { TransformHandleType } from \"./transformHandles\";\nimport type {\n ElementsMap,\n ExcalidrawElement,\n ExcalidrawImageElement,\n ImageCrop,\n NonDeleted,\n} from \"./types\";\n\nexport const MINIMAL_CROP_SIZE = 10;\n\nexport const cropElement = (\n element: ExcalidrawImageElement,\n elementsMap: ElementsMap,\n transformHandle: TransformHandleType,\n naturalWidth: number,\n naturalHeight: number,\n pointerX: number,\n pointerY: number,\n widthAspectRatio?: number,\n) => {\n const { width: uncroppedWidth, height: uncroppedHeight } =\n getUncroppedWidthAndHeight(element);\n\n const naturalWidthToUncropped = naturalWidth / uncroppedWidth;\n const naturalHeightToUncropped = naturalHeight / uncroppedHeight;\n\n const croppedLeft = (element.crop?.x ?? 0) / naturalWidthToUncropped;\n const croppedTop = (element.crop?.y ?? 0) / naturalHeightToUncropped;\n\n /**\n * uncropped width\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*\n * | (x,y) (natural) |\n * | *\u2013\u2013\u2013\u2013\u2013\u2013\u2013* |\n * | |///////| height | uncropped height\n * | *\u2013\u2013\u2013\u2013\u2013\u2013\u2013* |\n * | width (natural) |\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*\n */\n\n const rotatedPointer = pointRotateRads(\n pointFrom(pointerX, pointerY),\n elementCenterPoint(element, elementsMap),\n -element.angle as Radians,\n );\n\n pointerX = rotatedPointer[0];\n pointerY = rotatedPointer[1];\n\n let nextWidth = element.width;\n let nextHeight = element.height;\n\n let crop: ImageCrop | null = element.crop ?? {\n x: 0,\n y: 0,\n width: naturalWidth,\n height: naturalHeight,\n naturalWidth,\n naturalHeight,\n };\n\n const previousCropHeight = crop.height;\n const previousCropWidth = crop.width;\n\n const isFlippedByX = element.scale[0] === -1;\n const isFlippedByY = element.scale[1] === -1;\n\n let changeInHeight = pointerY - element.y;\n let changeInWidth = pointerX - element.x;\n\n if (transformHandle.includes(\"n\")) {\n nextHeight = clamp(\n element.height - changeInHeight,\n MINIMAL_CROP_SIZE,\n isFlippedByY ? uncroppedHeight - croppedTop : element.height + croppedTop,\n );\n }\n\n if (transformHandle.includes(\"s\")) {\n changeInHeight = pointerY - element.y - element.height;\n nextHeight = clamp(\n element.height + changeInHeight,\n MINIMAL_CROP_SIZE,\n isFlippedByY ? element.height + croppedTop : uncroppedHeight - croppedTop,\n );\n }\n\n if (transformHandle.includes(\"e\")) {\n changeInWidth = pointerX - element.x - element.width;\n\n nextWidth = clamp(\n element.width + changeInWidth,\n MINIMAL_CROP_SIZE,\n isFlippedByX ? element.width + croppedLeft : uncroppedWidth - croppedLeft,\n );\n }\n\n if (transformHandle.includes(\"w\")) {\n nextWidth = clamp(\n element.width - changeInWidth,\n MINIMAL_CROP_SIZE,\n isFlippedByX ? uncroppedWidth - croppedLeft : element.width + croppedLeft,\n );\n }\n\n const updateCropWidthAndHeight = (crop: ImageCrop) => {\n crop.height = nextHeight * naturalHeightToUncropped;\n crop.width = nextWidth * naturalWidthToUncropped;\n };\n\n updateCropWidthAndHeight(crop);\n\n const adjustFlipForHandle = (\n handle: TransformHandleType,\n crop: ImageCrop,\n ) => {\n updateCropWidthAndHeight(crop);\n if (handle.includes(\"n\")) {\n if (!isFlippedByY) {\n crop.y += previousCropHeight - crop.height;\n }\n }\n if (handle.includes(\"s\")) {\n if (isFlippedByY) {\n crop.y += previousCropHeight - crop.height;\n }\n }\n if (handle.includes(\"e\")) {\n if (isFlippedByX) {\n crop.x += previousCropWidth - crop.width;\n }\n }\n if (handle.includes(\"w\")) {\n if (!isFlippedByX) {\n crop.x += previousCropWidth - crop.width;\n }\n }\n };\n\n switch (transformHandle) {\n case \"n\": {\n if (widthAspectRatio) {\n const distanceToLeft = croppedLeft + element.width / 2;\n const distanceToRight =\n uncroppedWidth - croppedLeft - element.width / 2;\n\n const MAX_WIDTH = Math.min(distanceToLeft, distanceToRight) * 2;\n\n nextWidth = clamp(\n nextHeight * widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_WIDTH,\n );\n nextHeight = nextWidth / widthAspectRatio;\n }\n\n adjustFlipForHandle(transformHandle, crop);\n\n if (widthAspectRatio) {\n crop.x += (previousCropWidth - crop.width) / 2;\n }\n\n break;\n }\n case \"s\": {\n if (widthAspectRatio) {\n const distanceToLeft = croppedLeft + element.width / 2;\n const distanceToRight =\n uncroppedWidth - croppedLeft - element.width / 2;\n\n const MAX_WIDTH = Math.min(distanceToLeft, distanceToRight) * 2;\n\n nextWidth = clamp(\n nextHeight * widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_WIDTH,\n );\n nextHeight = nextWidth / widthAspectRatio;\n }\n\n adjustFlipForHandle(transformHandle, crop);\n\n if (widthAspectRatio) {\n crop.x += (previousCropWidth - crop.width) / 2;\n }\n\n break;\n }\n case \"w\": {\n if (widthAspectRatio) {\n const distanceToTop = croppedTop + element.height / 2;\n const distanceToBottom =\n uncroppedHeight - croppedTop - element.height / 2;\n\n const MAX_HEIGHT = Math.min(distanceToTop, distanceToBottom) * 2;\n\n nextHeight = clamp(\n nextWidth / widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_HEIGHT,\n );\n nextWidth = nextHeight * widthAspectRatio;\n }\n\n adjustFlipForHandle(transformHandle, crop);\n\n if (widthAspectRatio) {\n crop.y += (previousCropHeight - crop.height) / 2;\n }\n\n break;\n }\n case \"e\": {\n if (widthAspectRatio) {\n const distanceToTop = croppedTop + element.height / 2;\n const distanceToBottom =\n uncroppedHeight - croppedTop - element.height / 2;\n\n const MAX_HEIGHT = Math.min(distanceToTop, distanceToBottom) * 2;\n\n nextHeight = clamp(\n nextWidth / widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_HEIGHT,\n );\n nextWidth = nextHeight * widthAspectRatio;\n }\n\n adjustFlipForHandle(transformHandle, crop);\n\n if (widthAspectRatio) {\n crop.y += (previousCropHeight - crop.height) / 2;\n }\n\n break;\n }\n case \"ne\": {\n if (widthAspectRatio) {\n if (changeInWidth > -changeInHeight) {\n const MAX_HEIGHT = isFlippedByY\n ? uncroppedHeight - croppedTop\n : croppedTop + element.height;\n\n nextHeight = clamp(\n nextWidth / widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_HEIGHT,\n );\n nextWidth = nextHeight * widthAspectRatio;\n } else {\n const MAX_WIDTH = isFlippedByX\n ? croppedLeft + element.width\n : uncroppedWidth - croppedLeft;\n\n nextWidth = clamp(\n nextHeight * widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_WIDTH,\n );\n nextHeight = nextWidth / widthAspectRatio;\n }\n }\n\n adjustFlipForHandle(transformHandle, crop);\n break;\n }\n case \"nw\": {\n if (widthAspectRatio) {\n if (changeInWidth < changeInHeight) {\n const MAX_HEIGHT = isFlippedByY\n ? uncroppedHeight - croppedTop\n : croppedTop + element.height;\n nextHeight = clamp(\n nextWidth / widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_HEIGHT,\n );\n nextWidth = nextHeight * widthAspectRatio;\n } else {\n const MAX_WIDTH = isFlippedByX\n ? uncroppedWidth - croppedLeft\n : croppedLeft + element.width;\n\n nextWidth = clamp(\n nextHeight * widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_WIDTH,\n );\n nextHeight = nextWidth / widthAspectRatio;\n }\n }\n\n adjustFlipForHandle(transformHandle, crop);\n break;\n }\n case \"se\": {\n if (widthAspectRatio) {\n if (changeInWidth > changeInHeight) {\n const MAX_HEIGHT = isFlippedByY\n ? croppedTop + element.height\n : uncroppedHeight - croppedTop;\n\n nextHeight = clamp(\n nextWidth / widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_HEIGHT,\n );\n nextWidth = nextHeight * widthAspectRatio;\n } else {\n const MAX_WIDTH = isFlippedByX\n ? croppedLeft + element.width\n : uncroppedWidth - croppedLeft;\n\n nextWidth = clamp(\n nextHeight * widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_WIDTH,\n );\n nextHeight = nextWidth / widthAspectRatio;\n }\n }\n\n adjustFlipForHandle(transformHandle, crop);\n break;\n }\n case \"sw\": {\n if (widthAspectRatio) {\n if (-changeInWidth > changeInHeight) {\n const MAX_HEIGHT = isFlippedByY\n ? croppedTop + element.height\n : uncroppedHeight - croppedTop;\n\n nextHeight = clamp(\n nextWidth / widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_HEIGHT,\n );\n nextWidth = nextHeight * widthAspectRatio;\n } else {\n const MAX_WIDTH = isFlippedByX\n ? uncroppedWidth - croppedLeft\n : croppedLeft + element.width;\n\n nextWidth = clamp(\n nextHeight * widthAspectRatio,\n MINIMAL_CROP_SIZE,\n MAX_WIDTH,\n );\n nextHeight = nextWidth / widthAspectRatio;\n }\n }\n\n adjustFlipForHandle(transformHandle, crop);\n break;\n }\n default:\n break;\n }\n\n const newOrigin = recomputeOrigin(\n element,\n transformHandle,\n nextWidth,\n nextHeight,\n !!widthAspectRatio,\n );\n\n // reset crop to null if we're back to orig size\n if (\n isCloseTo(crop.width, crop.naturalWidth) &&\n isCloseTo(crop.height, crop.naturalHeight)\n ) {\n crop = null;\n }\n\n return {\n x: newOrigin[0],\n y: newOrigin[1],\n width: nextWidth,\n height: nextHeight,\n crop,\n };\n};\n\nconst recomputeOrigin = (\n stateAtCropStart: NonDeleted<ExcalidrawElement>,\n transformHandle: TransformHandleType,\n width: number,\n height: number,\n shouldMaintainAspectRatio?: boolean,\n) => {\n const [x1, y1, x2, y2] = getResizedElementAbsoluteCoords(\n stateAtCropStart,\n stateAtCropStart.width,\n stateAtCropStart.height,\n true,\n );\n const startTopLeft = pointFrom(x1, y1);\n const startBottomRight = pointFrom(x2, y2);\n const startCenter: any = pointCenter(startTopLeft, startBottomRight);\n\n const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] =\n getResizedElementAbsoluteCoords(stateAtCropStart, width, height, true);\n const newBoundsWidth = newBoundsX2 - newBoundsX1;\n const newBoundsHeight = newBoundsY2 - newBoundsY1;\n\n // Calculate new topLeft based on fixed corner during resize\n let newTopLeft = [...startTopLeft] as [number, number];\n\n if ([\"n\", \"w\", \"nw\"].includes(transformHandle)) {\n newTopLeft = [\n startBottomRight[0] - Math.abs(newBoundsWidth),\n startBottomRight[1] - Math.abs(newBoundsHeight),\n ];\n }\n if (transformHandle === \"ne\") {\n const bottomLeft = [startTopLeft[0], startBottomRight[1]];\n newTopLeft = [bottomLeft[0], bottomLeft[1] - Math.abs(newBoundsHeight)];\n }\n if (transformHandle === \"sw\") {\n const topRight = [startBottomRight[0], startTopLeft[1]];\n newTopLeft = [topRight[0] - Math.abs(newBoundsWidth), topRight[1]];\n }\n\n if (shouldMaintainAspectRatio) {\n if ([\"s\", \"n\"].includes(transformHandle)) {\n newTopLeft[0] = startCenter[0] - newBoundsWidth / 2;\n }\n if ([\"e\", \"w\"].includes(transformHandle)) {\n newTopLeft[1] = startCenter[1] - newBoundsHeight / 2;\n }\n }\n\n // adjust topLeft to new rotation point\n const angle = stateAtCropStart.angle;\n const rotatedTopLeft = pointRotateRads(newTopLeft, startCenter, angle);\n const newCenter: Point = [\n newTopLeft[0] + Math.abs(newBoundsWidth) / 2,\n newTopLeft[1] + Math.abs(newBoundsHeight) / 2,\n ];\n const rotatedNewCenter = pointRotateRads(newCenter, startCenter, angle);\n newTopLeft = pointRotateRads(\n rotatedTopLeft,\n rotatedNewCenter,\n -angle as Radians,\n );\n\n const newOrigin = [...newTopLeft];\n newOrigin[0] += stateAtCropStart.x - newBoundsX1;\n newOrigin[1] += stateAtCropStart.y - newBoundsY1;\n\n return newOrigin;\n};\n\n// refer to https://link.excalidraw.com/l/6rfy1007QOo/6stx5PmRn0k\nexport const getUncroppedImageElement = (\n element: ExcalidrawImageElement,\n elementsMap: ElementsMap,\n) => {\n if (element.crop) {\n const { width, height } = getUncroppedWidthAndHeight(element);\n\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\n element,\n elementsMap,\n );\n\n const topLeftVector = vectorFromPoint(\n pointRotateRads(pointFrom(x1, y1), pointFrom(cx, cy), element.angle),\n );\n const topRightVector = vectorFromPoint(\n pointRotateRads(pointFrom(x2, y1), pointFrom(cx, cy), element.angle),\n );\n const topEdgeNormalized = vectorNormalize(\n vectorSubtract(topRightVector, topLeftVector),\n );\n const bottomLeftVector = vectorFromPoint(\n pointRotateRads(pointFrom(x1, y2), pointFrom(cx, cy), element.angle),\n );\n const leftEdgeVector = vectorSubtract(bottomLeftVector, topLeftVector);\n const leftEdgeNormalized = vectorNormalize(leftEdgeVector);\n\n const { cropX, cropY } = adjustCropPosition(element.crop, element.scale);\n\n const rotatedTopLeft = vectorAdd(\n vectorAdd(\n topLeftVector,\n vectorScale(\n topEdgeNormalized,\n (-cropX * width) / element.crop.naturalWidth,\n ),\n ),\n vectorScale(\n leftEdgeNormalized,\n (-cropY * height) / element.crop.naturalHeight,\n ),\n );\n\n const center = pointFromVector(\n vectorAdd(\n vectorAdd(rotatedTopLeft, vectorScale(topEdgeNormalized, width / 2)),\n vectorScale(leftEdgeNormalized, height / 2),\n ),\n );\n\n const unrotatedTopLeft = pointRotateRads(\n pointFromVector(rotatedTopLeft),\n center,\n -element.angle as Radians,\n );\n\n const uncroppedElement: ExcalidrawImageElement = {\n ...element,\n x: unrotatedTopLeft[0],\n y: unrotatedTopLeft[1],\n width,\n height,\n crop: null,\n };\n\n return uncroppedElement;\n }\n\n return element;\n};\n\nexport const getUncroppedWidthAndHeight = (element: ExcalidrawImageElement) => {\n if (element.crop) {\n const width =\n element.width / (element.crop.width / element.crop.naturalWidth);\n const height =\n element.height / (element.crop.height / element.crop.naturalHeight);\n\n return {\n width,\n height,\n };\n }\n\n return {\n width: element.width,\n height: element.height,\n };\n};\n\nconst adjustCropPosition = (\n crop: ImageCrop,\n scale: ExcalidrawImageElement[\"scale\"],\n) => {\n let cropX = crop.x;\n let cropY = crop.y;\n\n const flipX = scale[0] === -1;\n const flipY = scale[1] === -1;\n\n if (flipX) {\n cropX = crop.naturalWidth - Math.abs(cropX) - crop.width;\n }\n\n if (flipY) {\n cropY = crop.naturalHeight - Math.abs(cropY) - crop.height;\n }\n\n return {\n cropX,\n cropY,\n };\n};\n\nexport const getFlipAdjustedCropPosition = (\n element: ExcalidrawImageElement,\n natural = false,\n) => {\n const crop = element.crop;\n if (!crop) {\n return null;\n }\n\n const isFlippedByX = element.scale[0] === -1;\n const isFlippedByY = element.scale[1] === -1;\n\n let cropX = crop.x;\n let cropY = crop.y;\n\n if (isFlippedByX) {\n cropX = crop.naturalWidth - crop.width - crop.x;\n }\n\n if (isFlippedByY) {\n cropY = crop.naturalHeight - crop.height - crop.y;\n }\n\n if (natural) {\n return {\n x: cropX,\n y: cropY,\n };\n }\n\n const { width, height } = getUncroppedWidthAndHeight(element);\n\n return {\n x: cropX / (crop.naturalWidth / width),\n y: cropY / (crop.naturalHeight / height),\n };\n};\n", "import { ROUNDNESS, assertNever } from \"@excalidraw/common\";\n\nimport { pointsEqual } from \"@excalidraw/math\";\n\nimport type { ElementOrToolType } from \"@excalidraw/excalidraw/types\";\n\nimport type { MarkNonNullable } from \"@excalidraw/common/utility-types\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawTextElement,\n ExcalidrawEmbeddableElement,\n ExcalidrawLinearElement,\n ExcalidrawBindableElement,\n ExcalidrawFreeDrawElement,\n InitializedExcalidrawImageElement,\n ExcalidrawImageElement,\n ExcalidrawTextElementWithContainer,\n ExcalidrawTextContainer,\n ExcalidrawFrameElement,\n RoundnessType,\n ExcalidrawFrameLikeElement,\n ExcalidrawElementType,\n ExcalidrawIframeElement,\n ExcalidrawIframeLikeElement,\n ExcalidrawMagicFrameElement,\n ExcalidrawArrowElement,\n ExcalidrawElbowArrowElement,\n ExcalidrawLineElement,\n ExcalidrawFlowchartNodeElement,\n ExcalidrawLinearElementSubType,\n} from \"./types\";\n\nexport const isInitializedImageElement = (\n element: ExcalidrawElement | null,\n): element is InitializedExcalidrawImageElement => {\n return !!element && element.type === \"image\" && !!element.fileId;\n};\n\nexport const isImageElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawImageElement => {\n return !!element && element.type === \"image\";\n};\n\nexport const isEmbeddableElement = (\n element: ExcalidrawElement | null | undefined,\n): element is ExcalidrawEmbeddableElement => {\n return !!element && element.type === \"embeddable\";\n};\n\nexport const isIframeElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawIframeElement => {\n return !!element && element.type === \"iframe\";\n};\n\nexport const isIframeLikeElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawIframeLikeElement => {\n return (\n !!element && (element.type === \"iframe\" || element.type === \"embeddable\")\n );\n};\n\nexport const isTextElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawTextElement => {\n return element != null && element.type === \"text\";\n};\n\nexport const isFrameElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawFrameElement => {\n return element != null && element.type === \"frame\";\n};\n\nexport const isMagicFrameElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawMagicFrameElement => {\n return element != null && element.type === \"magicframe\";\n};\n\nexport const isFrameLikeElement = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawFrameLikeElement => {\n return (\n element != null &&\n (element.type === \"frame\" || element.type === \"magicframe\")\n );\n};\n\nexport const isFreeDrawElement = (\n element?: ExcalidrawElement | null,\n): element is ExcalidrawFreeDrawElement => {\n return element != null && isFreeDrawElementType(element.type);\n};\n\nexport const isFreeDrawElementType = (\n elementType: ExcalidrawElementType,\n): boolean => {\n return elementType === \"freedraw\";\n};\n\nexport const isLinearElement = (\n element?: ExcalidrawElement | null,\n): element is ExcalidrawLinearElement => {\n return element != null && isLinearElementType(element.type);\n};\n\nexport const isLineElement = (\n element?: ExcalidrawElement | null,\n): element is ExcalidrawLineElement => {\n return element != null && element.type === \"line\";\n};\n\nexport const isArrowElement = (\n element?: ExcalidrawElement | null,\n): element is ExcalidrawArrowElement => {\n return element != null && element.type === \"arrow\";\n};\n\nexport const isElbowArrow = (\n element?: ExcalidrawElement,\n): element is ExcalidrawElbowArrowElement => {\n return isArrowElement(element) && element.elbowed;\n};\n\n/**\n * sharp or curved arrow, but not elbow\n */\nexport const isSimpleArrow = (\n element?: ExcalidrawElement,\n): element is ExcalidrawArrowElement => {\n return isArrowElement(element) && !element.elbowed;\n};\n\nexport const isSharpArrow = (\n element?: ExcalidrawElement,\n): element is ExcalidrawArrowElement => {\n return isArrowElement(element) && !element.elbowed && !element.roundness;\n};\n\nexport const isCurvedArrow = (\n element?: ExcalidrawElement,\n): element is ExcalidrawArrowElement => {\n return (\n isArrowElement(element) && !element.elbowed && element.roundness !== null\n );\n};\n\nexport const isLinearElementType = (\n elementType: ElementOrToolType,\n): boolean => {\n return (\n elementType === \"arrow\" || elementType === \"line\" // || elementType === \"freedraw\"\n );\n};\n\nexport const isBindingElement = (\n element?: ExcalidrawElement | null,\n includeLocked = true,\n): element is ExcalidrawArrowElement => {\n return (\n element != null &&\n (!element.locked || includeLocked === true) &&\n isBindingElementType(element.type)\n );\n};\n\nexport const isBindingElementType = (\n elementType: ElementOrToolType,\n): boolean => {\n return elementType === \"arrow\";\n};\n\nexport const isBindableElement = (\n element: ExcalidrawElement | null | undefined,\n includeLocked = true,\n): element is ExcalidrawBindableElement => {\n return (\n element != null &&\n (!element.locked || includeLocked === true) &&\n (element.type === \"rectangle\" ||\n element.type === \"diamond\" ||\n element.type === \"ellipse\" ||\n element.type === \"image\" ||\n element.type === \"iframe\" ||\n element.type === \"embeddable\" ||\n element.type === \"frame\" ||\n element.type === \"magicframe\" ||\n (element.type === \"text\" && !element.containerId))\n );\n};\n\nexport const isRectanguloidElement = (\n element?: ExcalidrawElement | null,\n): element is ExcalidrawBindableElement => {\n return (\n element != null &&\n (element.type === \"rectangle\" ||\n element.type === \"diamond\" ||\n element.type === \"image\" ||\n element.type === \"iframe\" ||\n element.type === \"embeddable\" ||\n element.type === \"frame\" ||\n element.type === \"magicframe\" ||\n (element.type === \"text\" && !element.containerId))\n );\n};\n\n// TODO: Remove this when proper distance calculation is introduced\n// @see binding.ts:distanceToBindableElement()\nexport const isRectangularElement = (\n element?: ExcalidrawElement | null,\n): element is ExcalidrawBindableElement => {\n return (\n element != null &&\n (element.type === \"rectangle\" ||\n element.type === \"image\" ||\n element.type === \"text\" ||\n element.type === \"iframe\" ||\n element.type === \"embeddable\" ||\n element.type === \"frame\" ||\n element.type === \"magicframe\" ||\n element.type === \"freedraw\")\n );\n};\n\nexport const isTextBindableContainer = (\n element: ExcalidrawElement | null,\n includeLocked = true,\n): element is ExcalidrawTextContainer => {\n return (\n element != null &&\n (!element.locked || includeLocked === true) &&\n (element.type === \"rectangle\" ||\n element.type === \"diamond\" ||\n element.type === \"ellipse\" ||\n isArrowElement(element))\n );\n};\n\nexport const isExcalidrawElement = (\n element: any,\n): element is ExcalidrawElement => {\n const type: ExcalidrawElementType | undefined = element?.type;\n if (!type) {\n return false;\n }\n switch (type) {\n case \"text\":\n case \"diamond\":\n case \"rectangle\":\n case \"iframe\":\n case \"embeddable\":\n case \"ellipse\":\n case \"arrow\":\n case \"freedraw\":\n case \"line\":\n case \"frame\":\n case \"magicframe\":\n case \"image\":\n case \"selection\": {\n return true;\n }\n default: {\n assertNever(type, null);\n return false;\n }\n }\n};\n\nexport const isFlowchartNodeElement = (\n element: ExcalidrawElement,\n): element is ExcalidrawFlowchartNodeElement => {\n return (\n element.type === \"rectangle\" ||\n element.type === \"ellipse\" ||\n element.type === \"diamond\"\n );\n};\n\nexport const hasBoundTextElement = (\n element: ExcalidrawElement | null,\n): element is MarkNonNullable<ExcalidrawBindableElement, \"boundElements\"> => {\n return (\n isTextBindableContainer(element) &&\n !!element.boundElements?.some(({ type }) => type === \"text\")\n );\n};\n\nexport const isBoundToContainer = (\n element: ExcalidrawElement | null,\n): element is ExcalidrawTextElementWithContainer => {\n return (\n element !== null &&\n \"containerId\" in element &&\n element.containerId !== null &&\n isTextElement(element)\n );\n};\n\nexport const isArrowBoundToElement = (element: ExcalidrawArrowElement) => {\n return !!element.startBinding || !!element.endBinding;\n};\n\nexport const isUsingAdaptiveRadius = (type: string) =>\n type === \"rectangle\" ||\n type === \"embeddable\" ||\n type === \"iframe\" ||\n type === \"image\";\n\nexport const isUsingProportionalRadius = (type: string) =>\n type === \"line\" || type === \"arrow\" || type === \"diamond\";\n\nexport const canApplyRoundnessTypeToElement = (\n roundnessType: RoundnessType,\n element: ExcalidrawElement,\n) => {\n if (\n (roundnessType === ROUNDNESS.ADAPTIVE_RADIUS ||\n // if legacy roundness, it can be applied to elements that currently\n // use adaptive radius\n roundnessType === ROUNDNESS.LEGACY) &&\n isUsingAdaptiveRadius(element.type)\n ) {\n return true;\n }\n if (\n roundnessType === ROUNDNESS.PROPORTIONAL_RADIUS &&\n isUsingProportionalRadius(element.type)\n ) {\n return true;\n }\n\n return false;\n};\n\nexport const getDefaultRoundnessTypeForElement = (\n element: ExcalidrawElement,\n) => {\n if (isUsingProportionalRadius(element.type)) {\n return {\n type: ROUNDNESS.PROPORTIONAL_RADIUS,\n };\n }\n\n if (isUsingAdaptiveRadius(element.type)) {\n return {\n type: ROUNDNESS.ADAPTIVE_RADIUS,\n };\n }\n\n return null;\n};\n\nexport const getLinearElementSubType = (\n element: ExcalidrawLinearElement,\n): ExcalidrawLinearElementSubType => {\n if (isSharpArrow(element)) {\n return \"sharpArrow\";\n }\n if (isCurvedArrow(element)) {\n return \"curvedArrow\";\n }\n if (isElbowArrow(element)) {\n return \"elbowArrow\";\n }\n return \"line\";\n};\n\n/**\n * Checks if current element points meet all the conditions for polygon=true\n * (this isn't a element type check, for that use isLineElement).\n *\n * If you want to check if points *can* be turned into a polygon, use\n * canBecomePolygon(points).\n */\nexport const isValidPolygon = (\n points: ExcalidrawLineElement[\"points\"],\n): boolean => {\n return points.length > 3 && pointsEqual(points[0], points[points.length - 1]);\n};\n\nexport const canBecomePolygon = (\n points: ExcalidrawLineElement[\"points\"],\n): boolean => {\n return (\n points.length > 3 ||\n // 3-point polygons can't have all points in a single line\n (points.length === 3 && !pointsEqual(points[0], points[points.length - 1]))\n );\n};\n", "import {\n DEFAULT_ADAPTIVE_RADIUS,\n DEFAULT_PROPORTIONAL_RADIUS,\n invariant,\n LINE_CONFIRM_THRESHOLD,\n ROUNDNESS,\n} from \"@excalidraw/common\";\n\nimport {\n curve,\n curveCatmullRomCubicApproxPoints,\n curveOffsetPoints,\n lineSegment,\n lineSegmentIntersectionPoints,\n pointDistance,\n pointFrom,\n pointFromArray,\n pointFromVector,\n pointRotateRads,\n pointTranslate,\n rectangle,\n vectorFromPoint,\n vectorNormalize,\n vectorScale,\n type GlobalPoint,\n} from \"@excalidraw/math\";\n\nimport type { Curve, LineSegment, LocalPoint } from \"@excalidraw/math\";\n\nimport type { NormalizedZoomValue, Zoom } from \"@excalidraw/excalidraw/types\";\n\nimport { elementCenterPoint, getDiamondPoints } from \"./bounds\";\n\nimport { generateLinearCollisionShape } from \"./shape\";\n\nimport { isPointInElement } from \"./collision\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport { isRectangularElement } from \"./typeChecks\";\n\nimport type {\n ElementsMap,\n ExcalidrawArrowElement,\n ExcalidrawDiamondElement,\n ExcalidrawElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawLinearElement,\n ExcalidrawRectanguloidElement,\n} from \"./types\";\n\ntype ElementShape = [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]];\n\nconst ElementShapesCache = new WeakMap<\n ExcalidrawElement,\n { version: ExcalidrawElement[\"version\"]; shapes: Map<number, ElementShape> }\n>();\n\nconst getElementShapesCacheEntry = <T extends ExcalidrawElement>(\n element: T,\n offset: number,\n): ElementShape | undefined => {\n const record = ElementShapesCache.get(element);\n\n if (!record) {\n return undefined;\n }\n\n const { version, shapes } = record;\n\n if (version !== element.version) {\n ElementShapesCache.delete(element);\n return undefined;\n }\n\n return shapes.get(offset);\n};\n\nconst setElementShapesCacheEntry = <T extends ExcalidrawElement>(\n element: T,\n shape: ElementShape,\n offset: number,\n) => {\n const record = ElementShapesCache.get(element);\n\n if (!record) {\n ElementShapesCache.set(element, {\n version: element.version,\n shapes: new Map([[offset, shape]]),\n });\n\n return;\n }\n\n const { version, shapes } = record;\n\n if (version !== element.version) {\n ElementShapesCache.set(element, {\n version: element.version,\n shapes: new Map([[offset, shape]]),\n });\n\n return;\n }\n\n shapes.set(offset, shape);\n};\n\n/**\n * Returns the **rotated** components of freedraw, line or arrow elements.\n *\n * @param element The linear element to deconstruct\n * @returns The rotated in components.\n */\nexport function deconstructLinearOrFreeDrawElement(\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\n): [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]] {\n const cachedShape = getElementShapesCacheEntry(element, 0);\n\n if (cachedShape) {\n return cachedShape;\n }\n\n const ops = generateLinearCollisionShape(element) as {\n op: string;\n data: number[];\n }[];\n const lines = [];\n const curves = [];\n\n for (let idx = 0; idx < ops.length; idx += 1) {\n const op = ops[idx];\n const prevPoint =\n ops[idx - 1] && pointFromArray<LocalPoint>(ops[idx - 1].data.slice(-2));\n switch (op.op) {\n case \"move\":\n continue;\n case \"lineTo\":\n if (!prevPoint) {\n throw new Error(\"prevPoint is undefined\");\n }\n\n lines.push(\n lineSegment<GlobalPoint>(\n pointFrom<GlobalPoint>(\n element.x + prevPoint[0],\n element.y + prevPoint[1],\n ),\n pointFrom<GlobalPoint>(\n element.x + op.data[0],\n element.y + op.data[1],\n ),\n ),\n );\n continue;\n case \"bcurveTo\":\n if (!prevPoint) {\n throw new Error(\"prevPoint is undefined\");\n }\n\n curves.push(\n curve<GlobalPoint>(\n pointFrom<GlobalPoint>(\n element.x + prevPoint[0],\n element.y + prevPoint[1],\n ),\n pointFrom<GlobalPoint>(\n element.x + op.data[0],\n element.y + op.data[1],\n ),\n pointFrom<GlobalPoint>(\n element.x + op.data[2],\n element.y + op.data[3],\n ),\n pointFrom<GlobalPoint>(\n element.x + op.data[4],\n element.y + op.data[5],\n ),\n ),\n );\n continue;\n default: {\n console.error(\"Unknown op type\", op.op);\n }\n }\n }\n\n const shape = [lines, curves] as ElementShape;\n setElementShapesCacheEntry(element, shape, 0);\n\n return shape;\n}\n\n/**\n * Get the building components of a rectanguloid element in the form of\n * line segments and curves **unrotated**.\n *\n * @param element Target rectanguloid element\n * @param offset Optional offset to expand the rectanguloid shape\n * @returns Tuple of **unrotated** line segments (0) and curves (1)\n */\nexport function deconstructRectanguloidElement(\n element: ExcalidrawRectanguloidElement,\n offset: number = 0,\n): [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]] {\n const cachedShape = getElementShapesCacheEntry(element, offset);\n\n if (cachedShape) {\n return cachedShape;\n }\n\n let radius = getCornerRadius(\n Math.min(element.width, element.height),\n element,\n );\n\n if (radius === 0) {\n radius = 0.01;\n }\n\n const r = rectangle(\n pointFrom(element.x, element.y),\n pointFrom(element.x + element.width, element.y + element.height),\n );\n\n const top = lineSegment<GlobalPoint>(\n pointFrom<GlobalPoint>(r[0][0] + radius, r[0][1]),\n pointFrom<GlobalPoint>(r[1][0] - radius, r[0][1]),\n );\n const right = lineSegment<GlobalPoint>(\n pointFrom<GlobalPoint>(r[1][0], r[0][1] + radius),\n pointFrom<GlobalPoint>(r[1][0], r[1][1] - radius),\n );\n const bottom = lineSegment<GlobalPoint>(\n pointFrom<GlobalPoint>(r[0][0] + radius, r[1][1]),\n pointFrom<GlobalPoint>(r[1][0] - radius, r[1][1]),\n );\n const left = lineSegment<GlobalPoint>(\n pointFrom<GlobalPoint>(r[0][0], r[1][1] - radius),\n pointFrom<GlobalPoint>(r[0][0], r[0][1] + radius),\n );\n\n const baseCorners = [\n curve(\n left[1],\n pointFrom<GlobalPoint>(\n left[1][0] + (2 / 3) * (r[0][0] - left[1][0]),\n left[1][1] + (2 / 3) * (r[0][1] - left[1][1]),\n ),\n pointFrom<GlobalPoint>(\n top[0][0] + (2 / 3) * (r[0][0] - top[0][0]),\n top[0][1] + (2 / 3) * (r[0][1] - top[0][1]),\n ),\n top[0],\n ), // TOP LEFT\n curve(\n top[1],\n pointFrom<GlobalPoint>(\n top[1][0] + (2 / 3) * (r[1][0] - top[1][0]),\n top[1][1] + (2 / 3) * (r[0][1] - top[1][1]),\n ),\n pointFrom<GlobalPoint>(\n right[0][0] + (2 / 3) * (r[1][0] - right[0][0]),\n right[0][1] + (2 / 3) * (r[0][1] - right[0][1]),\n ),\n right[0],\n ), // TOP RIGHT\n curve(\n right[1],\n pointFrom<GlobalPoint>(\n right[1][0] + (2 / 3) * (r[1][0] - right[1][0]),\n right[1][1] + (2 / 3) * (r[1][1] - right[1][1]),\n ),\n pointFrom<GlobalPoint>(\n bottom[1][0] + (2 / 3) * (r[1][0] - bottom[1][0]),\n bottom[1][1] + (2 / 3) * (r[1][1] - bottom[1][1]),\n ),\n bottom[1],\n ), // BOTTOM RIGHT\n curve(\n bottom[0],\n pointFrom<GlobalPoint>(\n bottom[0][0] + (2 / 3) * (r[0][0] - bottom[0][0]),\n bottom[0][1] + (2 / 3) * (r[1][1] - bottom[0][1]),\n ),\n pointFrom<GlobalPoint>(\n left[0][0] + (2 / 3) * (r[0][0] - left[0][0]),\n left[0][1] + (2 / 3) * (r[1][1] - left[0][1]),\n ),\n left[0],\n ), // BOTTOM LEFT\n ];\n\n const corners =\n offset > 0\n ? baseCorners.map(\n (corner) =>\n curveCatmullRomCubicApproxPoints(\n curveOffsetPoints(corner, offset),\n )!,\n )\n : [\n [baseCorners[0]],\n [baseCorners[1]],\n [baseCorners[2]],\n [baseCorners[3]],\n ];\n\n const sides = [\n lineSegment<GlobalPoint>(\n corners[0][corners[0].length - 1][3],\n corners[1][0][0],\n ),\n lineSegment<GlobalPoint>(\n corners[1][corners[1].length - 1][3],\n corners[2][0][0],\n ),\n lineSegment<GlobalPoint>(\n corners[2][corners[2].length - 1][3],\n corners[3][0][0],\n ),\n lineSegment<GlobalPoint>(\n corners[3][corners[3].length - 1][3],\n corners[0][0][0],\n ),\n ];\n const shape = [sides, corners.flat()] as ElementShape;\n\n setElementShapesCacheEntry(element, shape, offset);\n\n return shape;\n}\n\n/**\n * Get the **unrotated** building components of a diamond element\n * in the form of line segments and curves as a tuple, in this order.\n *\n * @param element The element to deconstruct\n * @param offset An optional offset\n * @returns Tuple of line **unrotated** segments (0) and curves (1)\n */\nexport function deconstructDiamondElement(\n element: ExcalidrawDiamondElement,\n offset: number = 0,\n): [LineSegment<GlobalPoint>[], Curve<GlobalPoint>[]] {\n const cachedShape = getElementShapesCacheEntry(element, offset);\n\n if (cachedShape) {\n return cachedShape;\n }\n\n const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =\n getDiamondPoints(element);\n const verticalRadius = element.roundness\n ? getCornerRadius(Math.abs(topX - leftX), element)\n : (topX - leftX) * 0.01;\n const horizontalRadius = element.roundness\n ? getCornerRadius(Math.abs(rightY - topY), element)\n : (rightY - topY) * 0.01;\n\n const [top, right, bottom, left]: GlobalPoint[] = [\n pointFrom(element.x + topX, element.y + topY),\n pointFrom(element.x + rightX, element.y + rightY),\n pointFrom(element.x + bottomX, element.y + bottomY),\n pointFrom(element.x + leftX, element.y + leftY),\n ];\n\n const baseCorners = [\n curve(\n pointFrom<GlobalPoint>(\n right[0] - verticalRadius,\n right[1] - horizontalRadius,\n ),\n right,\n right,\n pointFrom<GlobalPoint>(\n right[0] - verticalRadius,\n right[1] + horizontalRadius,\n ),\n ), // RIGHT\n curve(\n pointFrom<GlobalPoint>(\n bottom[0] + verticalRadius,\n bottom[1] - horizontalRadius,\n ),\n bottom,\n bottom,\n pointFrom<GlobalPoint>(\n bottom[0] - verticalRadius,\n bottom[1] - horizontalRadius,\n ),\n ), // BOTTOM\n curve(\n pointFrom<GlobalPoint>(\n left[0] + verticalRadius,\n left[1] + horizontalRadius,\n ),\n left,\n left,\n pointFrom<GlobalPoint>(\n left[0] + verticalRadius,\n left[1] - horizontalRadius,\n ),\n ), // LEFT\n curve(\n pointFrom<GlobalPoint>(\n top[0] - verticalRadius,\n top[1] + horizontalRadius,\n ),\n top,\n top,\n pointFrom<GlobalPoint>(\n top[0] + verticalRadius,\n top[1] + horizontalRadius,\n ),\n ), // TOP\n ];\n\n const corners = baseCorners.map(\n (corner) =>\n curveCatmullRomCubicApproxPoints(curveOffsetPoints(corner, offset))!,\n );\n\n const sides = [\n lineSegment<GlobalPoint>(\n corners[0][corners[0].length - 1][3],\n corners[1][0][0],\n ),\n lineSegment<GlobalPoint>(\n corners[1][corners[1].length - 1][3],\n corners[2][0][0],\n ),\n lineSegment<GlobalPoint>(\n corners[2][corners[2].length - 1][3],\n corners[3][0][0],\n ),\n lineSegment<GlobalPoint>(\n corners[3][corners[3].length - 1][3],\n corners[0][0][0],\n ),\n ];\n\n const shape = [sides, corners.flat()] as ElementShape;\n\n setElementShapesCacheEntry(element, shape, offset);\n\n return shape;\n}\n\n// Checks if the first and last point are close enough\n// to be considered a loop\nexport const isPathALoop = (\n points: ExcalidrawLinearElement[\"points\"],\n /** supply if you want the loop detection to account for current zoom */\n zoomValue: Zoom[\"value\"] = 1 as NormalizedZoomValue,\n): boolean => {\n if (points.length >= 3) {\n const [first, last] = [points[0], points[points.length - 1]];\n const distance = pointDistance(first, last);\n\n // Adjusting LINE_CONFIRM_THRESHOLD to current zoom so that when zoomed in\n // really close we make the threshold smaller, and vice versa.\n return distance <= LINE_CONFIRM_THRESHOLD / zoomValue;\n }\n return false;\n};\n\nexport const getCornerRadius = (x: number, element: ExcalidrawElement) => {\n if (\n element.roundness?.type === ROUNDNESS.PROPORTIONAL_RADIUS ||\n element.roundness?.type === ROUNDNESS.LEGACY\n ) {\n return x * DEFAULT_PROPORTIONAL_RADIUS;\n }\n\n if (element.roundness?.type === ROUNDNESS.ADAPTIVE_RADIUS) {\n const fixedRadiusSize = element.roundness?.value ?? DEFAULT_ADAPTIVE_RADIUS;\n\n const CUTOFF_SIZE = fixedRadiusSize / DEFAULT_PROPORTIONAL_RADIUS;\n\n if (x <= CUTOFF_SIZE) {\n return x * DEFAULT_PROPORTIONAL_RADIUS;\n }\n\n return fixedRadiusSize;\n }\n\n return 0;\n};\n\nconst getDiagonalsForBindableElement = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n) => {\n // for rectangles, shrink the diagonals a bit because there's something\n // going on with the focus points around the corners. Ask Mark for details.\n const OFFSET_PX = element.type === \"rectangle\" ? 15 : 0;\n const shrinkSegment = (seg: LineSegment<GlobalPoint>) => {\n const v = vectorNormalize(vectorFromPoint(seg[1], seg[0]));\n const offset = vectorScale(v, OFFSET_PX);\n return lineSegment<GlobalPoint>(\n pointTranslate(seg[0], offset),\n pointTranslate(seg[1], vectorScale(offset, -1)),\n );\n };\n\n const center = elementCenterPoint(element, elementsMap);\n const diagonalOne = shrinkSegment(\n isRectangularElement(element)\n ? lineSegment<GlobalPoint>(\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x, element.y),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + element.width,\n element.y + element.height,\n ),\n center,\n element.angle,\n ),\n )\n : lineSegment<GlobalPoint>(\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x + element.width / 2, element.y),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + element.width / 2,\n element.y + element.height,\n ),\n center,\n element.angle,\n ),\n ),\n );\n const diagonalTwo = shrinkSegment(\n isRectangularElement(element)\n ? lineSegment<GlobalPoint>(\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x + element.width, element.y),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x, element.y + element.height),\n center,\n element.angle,\n ),\n )\n : lineSegment<GlobalPoint>(\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x, element.y + element.height / 2),\n center,\n element.angle,\n ),\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + element.width,\n element.y + element.height / 2,\n ),\n center,\n element.angle,\n ),\n ),\n );\n\n return [diagonalOne, diagonalTwo];\n};\n\nexport const projectFixedPointOntoDiagonal = (\n arrow: ExcalidrawArrowElement,\n point: GlobalPoint,\n element: ExcalidrawElement,\n startOrEnd: \"start\" | \"end\",\n elementsMap: ElementsMap,\n): GlobalPoint | null => {\n invariant(arrow.points.length >= 2, \"Arrow must have at least two points\");\n if (arrow.width < 3 && arrow.height < 3) {\n return null;\n }\n\n const [diagonalOne, diagonalTwo] = getDiagonalsForBindableElement(\n element,\n elementsMap,\n );\n\n const a = LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrow,\n startOrEnd === \"start\" ? 1 : arrow.points.length - 2,\n elementsMap,\n );\n const b = pointFromVector<GlobalPoint>(\n vectorScale(\n vectorFromPoint(point, a),\n 2 * pointDistance(a, point) +\n Math.max(\n pointDistance(diagonalOne[0], diagonalOne[1]),\n pointDistance(diagonalTwo[0], diagonalTwo[1]),\n ),\n ),\n a,\n );\n const intersector = lineSegment<GlobalPoint>(point, b);\n const p1 = lineSegmentIntersectionPoints(diagonalOne, intersector);\n const p2 = lineSegmentIntersectionPoints(diagonalTwo, intersector);\n const d1 = p1 && pointDistance(a, p1);\n const d2 = p2 && pointDistance(a, p2);\n\n let p = null;\n if (d1 != null && d2 != null) {\n p = d1 < d2 ? p1 : p2;\n } else {\n p = p1 || p2 || null;\n }\n\n return p && isPointInElement(p, element, elementsMap) ? p : null;\n};\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 {\n BOUND_TEXT_PADDING,\n DEFAULT_FONT_SIZE,\n DEFAULT_FONT_FAMILY,\n getFontString,\n isTestEnv,\n normalizeEOL,\n} from \"@excalidraw/common\";\n\nimport type { FontString, ExcalidrawTextElement } from \"./types\";\n\nexport const measureText = (\n text: string,\n font: FontString,\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\n) => {\n const _text = text\n .split(\"\\n\")\n // replace empty lines with single space because leading/trailing empty\n // lines would be stripped from computation\n .map((x) => x || \" \")\n .join(\"\\n\");\n const fontSize = parseFloat(font);\n const height = getTextHeight(_text, fontSize, lineHeight);\n const width = getTextWidth(_text, font);\n return { width, height };\n};\n\nconst DUMMY_TEXT = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\".toLocaleUpperCase();\n\n// FIXME rename to getApproxMinContainerWidth\nexport const getApproxMinLineWidth = (\n font: FontString,\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\n) => {\n const maxCharWidth = getMaxCharWidth(font);\n if (maxCharWidth === 0) {\n return (\n measureText(DUMMY_TEXT.split(\"\").join(\"\\n\"), font, lineHeight).width +\n BOUND_TEXT_PADDING * 2\n );\n }\n return maxCharWidth + BOUND_TEXT_PADDING * 2;\n};\n\nexport const getMinTextElementWidth = (\n font: FontString,\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\n) => {\n return measureText(\"\", font, lineHeight).width + BOUND_TEXT_PADDING * 2;\n};\n\nexport const isMeasureTextSupported = () => {\n const width = getTextWidth(\n DUMMY_TEXT,\n getFontString({\n fontSize: DEFAULT_FONT_SIZE,\n fontFamily: DEFAULT_FONT_FAMILY,\n }),\n );\n return width > 0;\n};\n\nexport const normalizeText = (text: string) => {\n return (\n normalizeEOL(text)\n // replace tabs with spaces so they render and measure correctly\n .replace(/\\t/g, \" \")\n );\n};\n\nconst splitIntoLines = (text: string) => {\n return normalizeText(text).split(\"\\n\");\n};\n\n/**\n * To get unitless line-height (if unknown) we can calculate it by dividing\n * height-per-line by fontSize.\n */\nexport const detectLineHeight = (textElement: ExcalidrawTextElement) => {\n const lineCount = splitIntoLines(textElement.text).length;\n return (textElement.height /\n lineCount /\n textElement.fontSize) as ExcalidrawTextElement[\"lineHeight\"];\n};\n\n/**\n * We calculate the line height from the font size and the unitless line height,\n * aligning with the W3C spec.\n */\nexport const getLineHeightInPx = (\n fontSize: ExcalidrawTextElement[\"fontSize\"],\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\n) => {\n return fontSize * lineHeight;\n};\n\n// FIXME rename to getApproxMinContainerHeight\nexport const getApproxMinLineHeight = (\n fontSize: ExcalidrawTextElement[\"fontSize\"],\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\n) => {\n return getLineHeightInPx(fontSize, lineHeight) + BOUND_TEXT_PADDING * 2;\n};\n\nlet textMetricsProvider: TextMetricsProvider | undefined;\n\n/**\n * Set a custom text metrics provider.\n *\n * Useful for overriding the width calculation algorithm where canvas API is not available / desired.\n */\nexport const setCustomTextMetricsProvider = (provider: TextMetricsProvider) => {\n textMetricsProvider = provider;\n};\n\nexport interface TextMetricsProvider {\n getLineWidth(text: string, fontString: FontString): number;\n}\n\nclass CanvasTextMetricsProvider implements TextMetricsProvider {\n private canvas: HTMLCanvasElement;\n\n constructor() {\n this.canvas = document.createElement(\"canvas\");\n }\n\n /**\n * We need to use the advance width as that's the closest thing to the browser wrapping algo, hence using it for:\n * - text wrapping\n * - wysiwyg editor (+padding)\n *\n * > The advance width is the distance between the glyph's initial pen position and the next glyph's initial pen position.\n */\n public getLineWidth(text: string, fontString: FontString): number {\n const context = this.canvas.getContext(\"2d\")!;\n context.font = fontString;\n const metrics = context.measureText(text);\n const advanceWidth = metrics.width;\n\n // since in test env the canvas measureText algo\n // doesn't measure text and instead just returns number of\n // characters hence we assume that each letteris 10px\n if (isTestEnv()) {\n return advanceWidth * 10;\n }\n\n return advanceWidth;\n }\n}\n\nexport const getLineWidth = (text: string, font: FontString) => {\n if (!textMetricsProvider) {\n textMetricsProvider = new CanvasTextMetricsProvider();\n }\n\n return textMetricsProvider.getLineWidth(text, font);\n};\n\nexport const getTextWidth = (text: string, font: FontString) => {\n const lines = splitIntoLines(text);\n let width = 0;\n lines.forEach((line) => {\n width = Math.max(width, getLineWidth(line, font));\n });\n\n return width;\n};\n\nexport const getTextHeight = (\n text: string,\n fontSize: number,\n lineHeight: ExcalidrawTextElement[\"lineHeight\"],\n) => {\n const lineCount = splitIntoLines(text).length;\n return getLineHeightInPx(fontSize, lineHeight) * lineCount;\n};\n\nexport const charWidth = (() => {\n const cachedCharWidth: { [key: FontString]: Array<number> } = {};\n\n const calculate = (char: string, font: FontString) => {\n const unicode = char.charCodeAt(0);\n if (!cachedCharWidth[font]) {\n cachedCharWidth[font] = [];\n }\n if (!cachedCharWidth[font][unicode]) {\n const width = getLineWidth(char, font);\n cachedCharWidth[font][unicode] = width;\n }\n\n return cachedCharWidth[font][unicode];\n };\n\n const getCache = (font: FontString) => {\n return cachedCharWidth[font];\n };\n\n const clearCache = (font: FontString) => {\n cachedCharWidth[font] = [];\n };\n\n return {\n calculate,\n getCache,\n clearCache,\n };\n})();\n\nexport const getMinCharWidth = (font: FontString) => {\n const cache = charWidth.getCache(font);\n if (!cache) {\n return 0;\n }\n const cacheWithOutEmpty = cache.filter((val) => val !== undefined);\n\n return Math.min(...cacheWithOutEmpty);\n};\n\nexport const getMaxCharWidth = (font: FontString) => {\n const cache = charWidth.getCache(font);\n if (!cache) {\n return 0;\n }\n const cacheWithOutEmpty = cache.filter((val) => val !== undefined);\n return Math.max(...cacheWithOutEmpty);\n};\n", "import { isDevEnv, isTestEnv } from \"@excalidraw/common\";\n\nimport { charWidth, getLineWidth } from \"./textMeasurements\";\n\nimport type { FontString } from \"./types\";\n\nlet cachedCjkRegex: RegExp | undefined;\nlet cachedLineBreakRegex: RegExp | undefined;\nlet cachedEmojiRegex: RegExp | undefined;\n\n/**\n * Test if a given text contains any CJK characters (including symbols, punctuation, etc,).\n */\nexport const containsCJK = (text: string) => {\n if (!cachedCjkRegex) {\n cachedCjkRegex = Regex.class(...Object.values(CJK));\n }\n\n return cachedCjkRegex.test(text);\n};\n\nconst getLineBreakRegex = () => {\n if (!cachedLineBreakRegex) {\n try {\n cachedLineBreakRegex = getLineBreakRegexAdvanced();\n } catch {\n cachedLineBreakRegex = getLineBreakRegexSimple();\n }\n }\n\n return cachedLineBreakRegex;\n};\n\nconst getEmojiRegex = () => {\n if (!cachedEmojiRegex) {\n cachedEmojiRegex = getEmojiRegexUnicode();\n }\n\n return cachedEmojiRegex;\n};\n\n/**\n * Common symbols used across different languages.\n */\nconst COMMON = {\n /**\n * Natural breaking points for any grammars.\n *\n * Hello world\n * \u2191 BREAK ALWAYS \" \" \u2192 [\"Hello\", \" \", \"world\"]\n * Hello-world\n * \u2191 BREAK AFTER \"-\" \u2192 [\"Hello-\", \"world\"]\n */\n WHITESPACE: /\\s/u,\n HYPHEN: /-/u,\n /**\n * Generally do not break, unless closed symbol is followed by an opening symbol.\n *\n * Also, western punctation is often used in modern Korean and expects to be treated\n * similarly to the CJK opening and closing symbols.\n *\n * Hello(\uD55C\uAE00)\u2192 [\"Hello\", \"(\uD55C\", \"\uAE00)\"]\n * \u2191 BREAK BEFORE \"(\"\n * \u2191 BREAK AFTER \")\"\n */\n OPENING: /<\\(\\[\\{/u,\n CLOSING: />\\)\\]\\}.,:;!\\?\u2026\\//u,\n};\n\n/**\n * Characters and symbols used in Chinese, Japanese and Korean.\n */\nconst CJK = {\n /**\n * Every CJK breaks before and after, unless it's paired with an opening or closing symbol.\n *\n * Does not include every possible char used in CJK texts, such as currency, parentheses or punctuation.\n */\n CHAR: /\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}\uFF40\uFF07\uFF3E\u3003\u3030\u3006\uFF03\uFF06\uFF0A\uFF0B\uFF0D\u30FC\uFF0F\uFF3C\uFF1D\uFF5C\uFFE4\u3012\uFFE2\uFFE3/u,\n /**\n * Opening and closing CJK punctuation breaks before and after all such characters (in case of many),\n * and creates pairs with neighboring characters.\n *\n * Hello \u305F\u3002\u2192 [\"Hello\", \"\u305F\u3002\"]\n * \u2191 DON'T BREAK \"\u305F\u3002\"\n * * Hello\u300C\u305F\u300D World \u2192 [\"Hello\", \"\u300C\u305F\u300D\", \"World\"]\n * \u2191 DON'T BREAK \"\u300C\u305F\"\n * \u2191 DON'T BREAK \"\u305F\"\n * \u2191 BREAK BEFORE \"\u300C\"\n * \u2191 BREAK AFTER \"\u300D\"\n */\n // eslint-disable-next-line prettier/prettier\n OPENING:/\uFF08\uFF3B\uFF5B\u3008\u300A\uFF5F\uFF62\u300C\u300E\u3010\u3016\u3014\u3018\u301A\uFF1C\u301D/u,\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,\n /**\n * Currency symbols break before, not after\n *\n * Price\uFFE5100 \u2192 [\"Price\", \"\uFFE5100\"]\n * \u2191 BREAK BEFORE \"\uFFE5\"\n */\n CURRENCY: /\uFFE5\uFFE6\uFFE1\uFFE0\uFF04/u,\n};\n\nconst EMOJI = {\n FLAG: /\\p{RI}\\p{RI}/u,\n JOINER:\n /(?:\\p{Emoji_Modifier}|\\uFE0F\\u20E3?|[\\u{E0020}-\\u{E007E}]+\\u{E007F})?/u,\n ZWJ: /\\u200D/u,\n ANY: /[\\p{Emoji}]/u,\n MOST: /[\\p{Extended_Pictographic}\\p{Emoji_Presentation}]/u,\n};\n\n/**\n * Simple fallback for browsers (mainly Safari < 16.4) that don't support \"Lookbehind assertion\".\n *\n * Browser support as of 10/2024:\n * - 91% Lookbehind assertion https://caniuse.com/mdn-javascript_regular_expressions_lookbehind_assertion\n * - 94% Unicode character class escape https://caniuse.com/mdn-javascript_regular_expressions_unicode_character_class_escape\n *\n * Does not include advanced CJK breaking rules, but covers most of the core cases, especially for latin.\n */\nconst getLineBreakRegexSimple = () =>\n Regex.or(\n getEmojiRegex(),\n Break.On(COMMON.HYPHEN, COMMON.WHITESPACE, CJK.CHAR),\n );\n\n/**\n * Specifies the line breaking rules based for alphabetic-based languages,\n * Chinese, Japanese, Korean and Emojis.\n *\n * \"Hello-world\" \u2192 [\"Hello-\", \"world\"]\n * \"Hello \u300C\u4E16\u754C\u3002\u300D\uD83C\uDF0E\uD83D\uDDFA\" \u2192 [\"Hello\", \" \", \"\u300C\u4E16\", \"\u754C\u3002\u300D\", \"\uD83C\uDF0E\", \"\uD83D\uDDFA\"]\n */\nconst getLineBreakRegexAdvanced = () =>\n Regex.or(\n // Unicode-defined regex for (multi-codepoint) Emojis\n getEmojiRegex(),\n // Rules for whitespace and hyphen\n Break.Before(COMMON.WHITESPACE).Build(),\n Break.After(COMMON.WHITESPACE, COMMON.HYPHEN).Build(),\n // Rules for CJK (chars, symbols, currency)\n Break.Before(CJK.CHAR, CJK.CURRENCY)\n .NotPrecededBy(COMMON.OPENING, CJK.OPENING)\n .Build(),\n Break.After(CJK.CHAR)\n .NotFollowedBy(COMMON.HYPHEN, COMMON.CLOSING, CJK.CLOSING)\n .Build(),\n // Rules for opening and closing punctuation\n Break.BeforeMany(CJK.OPENING).NotPrecededBy(COMMON.OPENING).Build(),\n Break.AfterMany(CJK.CLOSING).NotFollowedBy(COMMON.CLOSING).Build(),\n Break.AfterMany(COMMON.CLOSING).FollowedBy(COMMON.OPENING).Build(),\n );\n\n/**\n * Matches various emoji types.\n *\n * 1. basic emojis (\uD83D\uDE00, \uD83C\uDF0D)\n * 2. flags (\uD83C\uDDE8\uD83C\uDDFF)\n * 3. multi-codepoint emojis:\n * - skin tones (\uD83D\uDC4D\uD83C\uDFFD)\n * - variation selectors (\u2602\uFE0F)\n * - keycaps (1\uFE0F\u20E3)\n * - tag sequences (\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F)\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)\n *\n * Unicode points:\n * - \\uFE0F: presentation selector\n * - \\u20E3: enclosing keycap\n * - \\u200D: zero width joiner\n * - \\u{E0020}-\\u{E007E}: tags\n * - \\u{E007F}: cancel tag\n *\n * @see https://unicode.org/reports/tr51/#EBNF_and_Regex, with changes:\n * - replaced \\p{Emoji} with [\\p{Extended_Pictographic}\\p{Emoji_Presentation}], see more in `should tokenize emojis mixed with mixed text` test\n * - replaced \\p{Emod} with \\p{Emoji_Modifier} as some engines do not understand the abbreviation (i.e. https://devina.io/redos-checker)\n */\nconst getEmojiRegexUnicode = () =>\n Regex.group(\n Regex.or(\n EMOJI.FLAG,\n Regex.and(\n EMOJI.MOST,\n EMOJI.JOINER,\n Regex.build(\n `(?:${EMOJI.ZWJ.source}(?:${EMOJI.FLAG.source}|${EMOJI.ANY.source}${EMOJI.JOINER.source}))*`,\n ),\n ),\n ),\n );\n\n/**\n * Regex utilities for unicode character classes.\n */\nconst Regex = {\n /**\n * Builds a regex from a string.\n */\n build: (regex: string): RegExp => new RegExp(regex, \"u\"),\n /**\n * Joins regexes into a single string.\n */\n join: (...regexes: RegExp[]): string => regexes.map((x) => x.source).join(\"\"),\n /**\n * Joins regexes into a single regex as with \"and\" operator.\n */\n and: (...regexes: RegExp[]): RegExp => Regex.build(Regex.join(...regexes)),\n /**\n * Joins regexes into a single regex with \"or\" operator.\n */\n or: (...regexes: RegExp[]): RegExp =>\n Regex.build(regexes.map((x) => x.source).join(\"|\")),\n /**\n * Puts regexes into a matching group.\n */\n group: (...regexes: RegExp[]): RegExp =>\n Regex.build(`(${Regex.join(...regexes)})`),\n /**\n * Puts regexes into a character class.\n */\n class: (...regexes: RegExp[]): RegExp =>\n Regex.build(`[${Regex.join(...regexes)}]`),\n};\n\n/**\n * Human-readable lookahead and lookbehind utilities for defining line break\n * opportunities between pairs of character classes.\n */\nconst Break = {\n /**\n * Break on the given class of characters.\n */\n On: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n return Regex.build(`([${joined}])`);\n },\n /**\n * Break before the given class of characters.\n */\n Before: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n const builder = () => Regex.build(`(?=[${joined}])`);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"FollowedBy\"\n >;\n },\n /**\n * Break after the given class of characters.\n */\n After: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n const builder = () => Regex.build(`(?<=[${joined}])`);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"PreceededBy\"\n >;\n },\n /**\n * Break before one or multiple characters of the same class.\n */\n BeforeMany: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n const builder = () => Regex.build(`(?<![${joined}])(?=[${joined}])`);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"FollowedBy\"\n >;\n },\n /**\n * Break after one or multiple character from the same class.\n */\n AfterMany: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n const builder = () => Regex.build(`(?<=[${joined}])(?![${joined}])`);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"PreceededBy\"\n >;\n },\n /**\n * Do not break before the given class of characters.\n */\n NotBefore: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n const builder = () => Regex.build(`(?![${joined}])`);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"NotFollowedBy\"\n >;\n },\n /**\n * Do not break after the given class of characters.\n */\n NotAfter: (...regexes: RegExp[]) => {\n const joined = Regex.join(...regexes);\n const builder = () => Regex.build(`(?<![${joined}])`);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"NotPrecededBy\"\n >;\n },\n Chain: (rootBuilder: () => RegExp) => ({\n /**\n * Build the root regex.\n */\n Build: rootBuilder,\n /**\n * Specify additional class of characters that should precede the root regex.\n */\n PreceededBy: (...regexes: RegExp[]) => {\n const root = rootBuilder();\n const preceeded = Break.After(...regexes).Build();\n const builder = () => Regex.and(preceeded, root);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"PreceededBy\"\n >;\n },\n /**\n * Specify additional class of characters that should follow the root regex.\n */\n FollowedBy: (...regexes: RegExp[]) => {\n const root = rootBuilder();\n const followed = Break.Before(...regexes).Build();\n const builder = () => Regex.and(root, followed);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"FollowedBy\"\n >;\n },\n /**\n * Specify additional class of characters that should not precede the root regex.\n */\n NotPrecededBy: (...regexes: RegExp[]) => {\n const root = rootBuilder();\n const notPreceeded = Break.NotAfter(...regexes).Build();\n const builder = () => Regex.and(notPreceeded, root);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"NotPrecededBy\"\n >;\n },\n /**\n * Specify additional class of characters that should not follow the root regex.\n */\n NotFollowedBy: (...regexes: RegExp[]) => {\n const root = rootBuilder();\n const notFollowed = Break.NotBefore(...regexes).Build();\n const builder = () => Regex.and(root, notFollowed);\n return Break.Chain(builder) as Omit<\n ReturnType<typeof Break.Chain>,\n \"NotFollowedBy\"\n >;\n },\n }),\n};\n\n/**\n * Breaks the line into the tokens based on the found line break opporutnities.\n */\nexport const parseTokens = (line: string) => {\n const breakLineRegex = getLineBreakRegex();\n\n // normalizing to single-codepoint composed chars due to canonical equivalence\n // of multi-codepoint versions for chars like \u010D, \u3067 (~ so that we don't break a line in between c and \u02C7)\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\n return line.normalize(\"NFC\").split(breakLineRegex).filter(Boolean);\n};\n\n/**\n * Wraps the original text into the lines based on the given width.\n */\nexport const wrapText = (\n text: string,\n font: FontString,\n maxWidth: number,\n): string => {\n // if maxWidth is not finite or NaN which can happen in case of bugs in\n // computation, we need to make sure we don't continue as we'll end up\n // in an infinite loop\n if (!Number.isFinite(maxWidth) || maxWidth < 0) {\n return text;\n }\n\n const lines: Array<string> = [];\n const originalLines = text.split(\"\\n\");\n\n for (const originalLine of originalLines) {\n const currentLineWidth = getLineWidth(originalLine, font);\n\n if (currentLineWidth <= maxWidth) {\n lines.push(originalLine);\n continue;\n }\n\n const wrappedLine = wrapLine(originalLine, font, maxWidth);\n lines.push(...wrappedLine);\n }\n\n return lines.join(\"\\n\");\n};\n\n/**\n * Wraps the original line into the lines based on the given width.\n */\nconst wrapLine = (\n line: string,\n font: FontString,\n maxWidth: number,\n): string[] => {\n const lines: Array<string> = [];\n const tokens = parseTokens(line);\n const tokenIterator = tokens[Symbol.iterator]();\n\n let currentLine = \"\";\n let currentLineWidth = 0;\n\n let iterator = tokenIterator.next();\n\n while (!iterator.done) {\n const token = iterator.value;\n const testLine = currentLine + token;\n\n // cache single codepoint whitespace, CJK or emoji width calc. as kerning should not apply here\n const testLineWidth = isSingleCharacter(token)\n ? currentLineWidth + charWidth.calculate(token, font)\n : getLineWidth(testLine, font);\n\n // build up the current line, skipping length check for possibly trailing whitespaces\n if (/\\s/.test(token) || testLineWidth <= maxWidth) {\n currentLine = testLine;\n currentLineWidth = testLineWidth;\n iterator = tokenIterator.next();\n continue;\n }\n\n // current line is empty => just the token (word) is longer than `maxWidth` and needs to be wrapped\n if (!currentLine) {\n const wrappedWord = wrapWord(token, font, maxWidth);\n const trailingLine = wrappedWord[wrappedWord.length - 1] ?? \"\";\n const precedingLines = wrappedWord.slice(0, -1);\n\n lines.push(...precedingLines);\n\n // trailing line of the wrapped word might still be joined with next token/s\n currentLine = trailingLine;\n currentLineWidth = getLineWidth(trailingLine, font);\n iterator = tokenIterator.next();\n } else {\n // push & reset, but don't iterate on the next token, as we didn't use it yet!\n lines.push(currentLine.trimEnd());\n\n // purposefully not iterating and not setting `currentLine` to `token`, so that we could use a simple !currentLine check above\n currentLine = \"\";\n currentLineWidth = 0;\n }\n }\n\n // iterator done, push the trailing line if exists\n if (currentLine) {\n const trailingLine = trimLine(currentLine, font, maxWidth);\n lines.push(trailingLine);\n }\n\n return lines;\n};\n\n/**\n * Wraps the word into the lines based on the given width.\n */\nconst wrapWord = (\n word: string,\n font: FontString,\n maxWidth: number,\n): Array<string> => {\n // multi-codepoint emojis are already broken apart and shouldn't be broken further\n if (getEmojiRegex().test(word)) {\n return [word];\n }\n\n satisfiesWordInvariant(word);\n\n const lines: Array<string> = [];\n const chars = Array.from(word);\n\n let currentLine = \"\";\n let currentLineWidth = 0;\n\n for (const char of chars) {\n const _charWidth = charWidth.calculate(char, font);\n const testLineWidth = currentLineWidth + _charWidth;\n\n if (testLineWidth <= maxWidth) {\n currentLine = currentLine + char;\n currentLineWidth = testLineWidth;\n continue;\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n currentLine = char;\n currentLineWidth = _charWidth;\n }\n\n if (currentLine) {\n lines.push(currentLine);\n }\n\n return lines;\n};\n\n/**\n * Similarly to browsers, does not trim all trailing whitespaces, but only those exceeding the `maxWidth`.\n */\nconst trimLine = (line: string, font: FontString, maxWidth: number) => {\n const shouldTrimWhitespaces = getLineWidth(line, font) > maxWidth;\n\n if (!shouldTrimWhitespaces) {\n return line;\n }\n\n // defensively default to `trimeEnd` in case the regex does not match\n let [, trimmedLine, whitespaces] = line.match(/^(.+?)(\\s+)$/) ?? [\n line,\n line.trimEnd(),\n \"\",\n ];\n\n let trimmedLineWidth = getLineWidth(trimmedLine, font);\n\n for (const whitespace of Array.from(whitespaces)) {\n const _charWidth = charWidth.calculate(whitespace, font);\n const testLineWidth = trimmedLineWidth + _charWidth;\n\n if (testLineWidth > maxWidth) {\n break;\n }\n\n trimmedLine = trimmedLine + whitespace;\n trimmedLineWidth = testLineWidth;\n }\n\n return trimmedLine;\n};\n\n/**\n * Check if the given string is a single character.\n *\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).\n */\nconst isSingleCharacter = (maybeSingleCharacter: string) => {\n return (\n maybeSingleCharacter.codePointAt(0) !== undefined &&\n maybeSingleCharacter.codePointAt(1) === undefined\n );\n};\n\n/**\n * Invariant for the word wrapping algorithm.\n */\nconst satisfiesWordInvariant = (word: string) => {\n if (isTestEnv() || isDevEnv()) {\n if (/\\s/.test(word)) {\n throw new Error(\"Word should not contain any whitespaces!\");\n }\n }\n};\n", "import {\n ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO,\n ARROW_LABEL_WIDTH_FRACTION,\n BOUND_TEXT_PADDING,\n DEFAULT_FONT_SIZE,\n TEXT_ALIGN,\n VERTICAL_ALIGN,\n getFontString,\n isProdEnv,\n invariant,\n} from \"@excalidraw/common\";\n\nimport { pointFrom, pointRotateRads, type Radians } from \"@excalidraw/math\";\n\nimport type { AppState } from \"@excalidraw/excalidraw/types\";\n\nimport type { ExtractSetType } from \"@excalidraw/common/utility-types\";\n\nimport {\n resetOriginalContainerCache,\n updateOriginalContainerCache,\n} from \"./containerCache\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\n\nimport { measureText } from \"./textMeasurements\";\nimport { wrapText } from \"./textWrapping\";\nimport {\n isBoundToContainer,\n isArrowElement,\n isTextElement,\n} from \"./typeChecks\";\n\nimport type { Scene } from \"./Scene\";\n\nimport type { MaybeTransformHandleType } from \"./transformHandles\";\nimport type {\n ElementsMap,\n ExcalidrawElement,\n ExcalidrawElementType,\n ExcalidrawTextContainer,\n ExcalidrawTextElement,\n ExcalidrawTextElementWithContainer,\n NonDeletedExcalidrawElement,\n} from \"./types\";\n\nexport const redrawTextBoundingBox = (\n textElement: ExcalidrawTextElement,\n container: ExcalidrawElement | null,\n scene: Scene,\n) => {\n const elementsMap = scene.getNonDeletedElementsMap();\n\n let maxWidth = undefined;\n\n if (!isProdEnv()) {\n invariant(\n !container || !isArrowElement(container) || textElement.angle === 0,\n \"text element angle must be 0 if bound to arrow container\",\n );\n }\n\n const boundTextUpdates = {\n x: textElement.x,\n y: textElement.y,\n text: textElement.text,\n width: textElement.width,\n height: textElement.height,\n angle: (container\n ? isArrowElement(container)\n ? 0\n : container.angle\n : textElement.angle) as Radians,\n };\n\n boundTextUpdates.text = textElement.text;\n\n if (container || !textElement.autoResize) {\n maxWidth = container\n ? getBoundTextMaxWidth(container, textElement)\n : textElement.width;\n boundTextUpdates.text = wrapText(\n textElement.originalText,\n getFontString(textElement),\n maxWidth,\n );\n }\n\n const metrics = measureText(\n boundTextUpdates.text,\n getFontString(textElement),\n textElement.lineHeight,\n );\n\n // Note: only update width for unwrapped text and bound texts (which always have autoResize set to true)\n if (textElement.autoResize) {\n boundTextUpdates.width = metrics.width;\n }\n boundTextUpdates.height = metrics.height;\n\n if (container) {\n const maxContainerHeight = getBoundTextMaxHeight(\n container,\n textElement as ExcalidrawTextElementWithContainer,\n );\n const maxContainerWidth = getBoundTextMaxWidth(container, textElement);\n\n if (!isArrowElement(container) && metrics.height > maxContainerHeight) {\n const nextHeight = computeContainerDimensionForBoundText(\n metrics.height,\n container.type,\n );\n scene.mutateElement(container, { height: nextHeight });\n updateOriginalContainerCache(container.id, nextHeight);\n }\n\n if (metrics.width > maxContainerWidth) {\n const nextWidth = computeContainerDimensionForBoundText(\n metrics.width,\n container.type,\n );\n scene.mutateElement(container, { width: nextWidth });\n }\n\n const updatedTextElement = {\n ...textElement,\n ...boundTextUpdates,\n } as ExcalidrawTextElementWithContainer;\n\n const { x, y } = computeBoundTextPosition(\n container,\n updatedTextElement,\n elementsMap,\n );\n\n boundTextUpdates.x = x;\n boundTextUpdates.y = y;\n }\n\n scene.mutateElement(textElement, boundTextUpdates);\n};\n\nexport const handleBindTextResize = (\n container: NonDeletedExcalidrawElement,\n scene: Scene,\n transformHandleType: MaybeTransformHandleType,\n shouldMaintainAspectRatio = false,\n) => {\n const elementsMap = scene.getNonDeletedElementsMap();\n const boundTextElementId = getBoundTextElementId(container);\n if (!boundTextElementId) {\n return;\n }\n resetOriginalContainerCache(container.id);\n const textElement = getBoundTextElement(container, elementsMap);\n if (textElement && textElement.text) {\n if (!container) {\n return;\n }\n\n let text = textElement.text;\n let nextHeight = textElement.height;\n let nextWidth = textElement.width;\n const maxWidth = getBoundTextMaxWidth(container, textElement);\n const maxHeight = getBoundTextMaxHeight(container, textElement);\n let containerHeight = container.height;\n if (\n shouldMaintainAspectRatio ||\n (transformHandleType !== \"n\" && transformHandleType !== \"s\")\n ) {\n if (text) {\n text = wrapText(\n textElement.originalText,\n getFontString(textElement),\n maxWidth,\n );\n }\n const metrics = measureText(\n text,\n getFontString(textElement),\n textElement.lineHeight,\n );\n nextHeight = metrics.height;\n nextWidth = metrics.width;\n }\n // increase height in case text element height exceeds\n if (nextHeight > maxHeight) {\n containerHeight = computeContainerDimensionForBoundText(\n nextHeight,\n container.type,\n );\n\n const diff = containerHeight - container.height;\n // fix the y coord when resizing from ne/nw/n\n const updatedY =\n !isArrowElement(container) &&\n (transformHandleType === \"ne\" ||\n transformHandleType === \"nw\" ||\n transformHandleType === \"n\")\n ? container.y - diff\n : container.y;\n scene.mutateElement(container, {\n height: containerHeight,\n y: updatedY,\n });\n }\n\n scene.mutateElement(textElement, {\n text,\n width: nextWidth,\n height: nextHeight,\n });\n\n if (!isArrowElement(container)) {\n scene.mutateElement(\n textElement,\n computeBoundTextPosition(container, textElement, elementsMap),\n );\n }\n }\n};\n\nexport const computeBoundTextPosition = (\n container: ExcalidrawElement,\n boundTextElement: ExcalidrawTextElementWithContainer,\n elementsMap: ElementsMap,\n) => {\n if (isArrowElement(container)) {\n return LinearElementEditor.getBoundTextElementPosition(\n container,\n boundTextElement,\n elementsMap,\n );\n }\n const containerCoords = getContainerCoords(container);\n const maxContainerHeight = getBoundTextMaxHeight(container, boundTextElement);\n const maxContainerWidth = getBoundTextMaxWidth(container, boundTextElement);\n\n let x;\n let y;\n if (boundTextElement.verticalAlign === VERTICAL_ALIGN.TOP) {\n y = containerCoords.y;\n } else if (boundTextElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {\n y = containerCoords.y + (maxContainerHeight - boundTextElement.height);\n } else {\n y =\n containerCoords.y +\n (maxContainerHeight / 2 - boundTextElement.height / 2);\n }\n if (boundTextElement.textAlign === TEXT_ALIGN.LEFT) {\n x = containerCoords.x;\n } else if (boundTextElement.textAlign === TEXT_ALIGN.RIGHT) {\n x = containerCoords.x + (maxContainerWidth - boundTextElement.width);\n } else {\n x =\n containerCoords.x + (maxContainerWidth / 2 - boundTextElement.width / 2);\n }\n const angle = (container.angle ?? 0) as Radians;\n\n if (angle !== 0) {\n const contentCenter = pointFrom(\n containerCoords.x + maxContainerWidth / 2,\n containerCoords.y + maxContainerHeight / 2,\n );\n const textCenter = pointFrom(\n x + boundTextElement.width / 2,\n y + boundTextElement.height / 2,\n );\n\n const [rx, ry] = pointRotateRads(textCenter, contentCenter, angle);\n\n return {\n x: rx - boundTextElement.width / 2,\n y: ry - boundTextElement.height / 2,\n };\n }\n\n return { x, y };\n};\n\nexport const getBoundTextElementId = (container: ExcalidrawElement | null) => {\n return container?.boundElements?.length\n ? container?.boundElements?.find((ele) => ele.type === \"text\")?.id || null\n : null;\n};\n\nexport const getBoundTextElement = (\n element: ExcalidrawElement | null,\n elementsMap: ElementsMap,\n) => {\n if (!element) {\n return null;\n }\n const boundTextElementId = getBoundTextElementId(element);\n\n if (boundTextElementId) {\n return (elementsMap.get(boundTextElementId) ||\n null) as ExcalidrawTextElementWithContainer | null;\n }\n return null;\n};\n\nexport const getContainerElement = (\n element: ExcalidrawTextElement | null,\n elementsMap: ElementsMap,\n): ExcalidrawTextContainer | null => {\n if (!element) {\n return null;\n }\n if (element.containerId) {\n return (elementsMap.get(element.containerId) ||\n null) as ExcalidrawTextContainer | null;\n }\n return null;\n};\n\nexport const getContainerCenter = (\n container: ExcalidrawElement,\n appState: AppState,\n elementsMap: ElementsMap,\n) => {\n if (!isArrowElement(container)) {\n return {\n x: container.x + container.width / 2,\n y: container.y + container.height / 2,\n };\n }\n const points = LinearElementEditor.getPointsGlobalCoordinates(\n container,\n elementsMap,\n );\n if (points.length % 2 === 1) {\n const index = Math.floor(container.points.length / 2);\n const midPoint = LinearElementEditor.getPointGlobalCoordinates(\n container,\n container.points[index],\n elementsMap,\n );\n return { x: midPoint[0], y: midPoint[1] };\n }\n const index = container.points.length / 2 - 1;\n let midSegmentMidpoint = LinearElementEditor.getEditorMidPoints(\n container,\n elementsMap,\n appState,\n )[index];\n if (!midSegmentMidpoint) {\n midSegmentMidpoint = LinearElementEditor.getSegmentMidPoint(\n container,\n index + 1,\n );\n }\n return { x: midSegmentMidpoint[0], y: midSegmentMidpoint[1] };\n};\n\nexport const getContainerCoords = (container: NonDeletedExcalidrawElement) => {\n let offsetX = BOUND_TEXT_PADDING;\n let offsetY = BOUND_TEXT_PADDING;\n\n if (container.type === \"ellipse\") {\n // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6172\n offsetX += (container.width / 2) * (1 - Math.sqrt(2) / 2);\n offsetY += (container.height / 2) * (1 - Math.sqrt(2) / 2);\n }\n // The derivation of coordinates is explained in https://github.com/excalidraw/excalidraw/pull/6265\n if (container.type === \"diamond\") {\n offsetX += container.width / 4;\n offsetY += container.height / 4;\n }\n return {\n x: container.x + offsetX,\n y: container.y + offsetY,\n };\n};\n\nexport const getTextElementAngle = (\n textElement: ExcalidrawTextElement,\n container: ExcalidrawTextContainer | null,\n) => {\n if (isArrowElement(container)) {\n return 0;\n }\n if (!container) {\n return textElement.angle;\n }\n return container.angle;\n};\n\nexport const getBoundTextElementPosition = (\n container: ExcalidrawElement,\n boundTextElement: ExcalidrawTextElementWithContainer,\n elementsMap: ElementsMap,\n) => {\n if (isArrowElement(container)) {\n return LinearElementEditor.getBoundTextElementPosition(\n container,\n boundTextElement,\n elementsMap,\n );\n }\n};\n\nexport const shouldAllowVerticalAlign = (\n selectedElements: NonDeletedExcalidrawElement[],\n elementsMap: ElementsMap,\n) => {\n return selectedElements.some((element) => {\n if (isBoundToContainer(element)) {\n const container = getContainerElement(element, elementsMap);\n if (isArrowElement(container)) {\n return false;\n }\n return true;\n }\n return false;\n });\n};\n\nexport const suppportsHorizontalAlign = (\n selectedElements: NonDeletedExcalidrawElement[],\n elementsMap: ElementsMap,\n) => {\n return selectedElements.some((element) => {\n if (isBoundToContainer(element)) {\n const container = getContainerElement(element, elementsMap);\n if (isArrowElement(container)) {\n return false;\n }\n return true;\n }\n\n return isTextElement(element);\n });\n};\n\nconst VALID_CONTAINER_TYPES = new Set([\n \"rectangle\",\n \"ellipse\",\n \"diamond\",\n \"arrow\",\n]);\n\nexport const isValidTextContainer = (element: {\n type: ExcalidrawElementType;\n}) => VALID_CONTAINER_TYPES.has(element.type);\n\nexport const computeContainerDimensionForBoundText = (\n dimension: number,\n containerType: ExtractSetType<typeof VALID_CONTAINER_TYPES>,\n) => {\n dimension = Math.ceil(dimension);\n const padding = BOUND_TEXT_PADDING * 2;\n\n if (containerType === \"ellipse\") {\n return Math.round(((dimension + padding) / Math.sqrt(2)) * 2);\n }\n if (containerType === \"arrow\") {\n return dimension + padding * 8;\n }\n if (containerType === \"diamond\") {\n return 2 * (dimension + padding);\n }\n return dimension + padding;\n};\n\nexport const getBoundTextMaxWidth = (\n container: ExcalidrawElement,\n boundTextElement: ExcalidrawTextElement | null,\n) => {\n const { width } = container;\n if (isArrowElement(container)) {\n const minWidth =\n (boundTextElement?.fontSize ?? DEFAULT_FONT_SIZE) *\n ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO;\n return Math.max(ARROW_LABEL_WIDTH_FRACTION * width, minWidth);\n }\n if (container.type === \"ellipse\") {\n // The width of the largest rectangle inscribed inside an ellipse is\n // Math.round((ellipse.width / 2) * Math.sqrt(2)) which is derived from\n // equation of an ellipse -https://github.com/excalidraw/excalidraw/pull/6172\n return Math.round((width / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;\n }\n if (container.type === \"diamond\") {\n // The width of the largest rectangle inscribed inside a rhombus is\n // Math.round(width / 2) - https://github.com/excalidraw/excalidraw/pull/6265\n return Math.round(width / 2) - BOUND_TEXT_PADDING * 2;\n }\n return width - BOUND_TEXT_PADDING * 2;\n};\n\nexport const getBoundTextMaxHeight = (\n container: ExcalidrawElement,\n boundTextElement: ExcalidrawTextElementWithContainer,\n) => {\n const { height } = container;\n if (isArrowElement(container)) {\n const containerHeight = height - BOUND_TEXT_PADDING * 8 * 2;\n if (containerHeight <= 0) {\n return boundTextElement.height;\n }\n return height;\n }\n if (container.type === \"ellipse\") {\n // The height of the largest rectangle inscribed inside an ellipse is\n // Math.round((ellipse.height / 2) * Math.sqrt(2)) which is derived from\n // equation of an ellipse - https://github.com/excalidraw/excalidraw/pull/6172\n return Math.round((height / 2) * Math.sqrt(2)) - BOUND_TEXT_PADDING * 2;\n }\n if (container.type === \"diamond\") {\n // The height of the largest rectangle inscribed inside a rhombus is\n // Math.round(height / 2) - https://github.com/excalidraw/excalidraw/pull/6265\n return Math.round(height / 2) - BOUND_TEXT_PADDING * 2;\n }\n return height - BOUND_TEXT_PADDING * 2;\n};\n\n/** retrieves text from text elements and concatenates to a single string */\nexport const getTextFromElements = (\n elements: readonly ExcalidrawElement[],\n separator = \"\\n\\n\",\n) => {\n const text = elements\n .reduce((acc: string[], element) => {\n if (isTextElement(element)) {\n acc.push(element.text);\n }\n return acc;\n }, [])\n .join(separator);\n return text;\n};\n", "import {\n curvePointDistance,\n distanceToLineSegment,\n pointRotateRads,\n} from \"@excalidraw/math\";\n\nimport { ellipse, ellipseDistanceFromPoint } from \"@excalidraw/math/ellipse\";\n\nimport type { GlobalPoint, Radians } from \"@excalidraw/math\";\n\nimport {\n deconstructDiamondElement,\n deconstructLinearOrFreeDrawElement,\n deconstructRectanguloidElement,\n} from \"./utils\";\n\nimport { elementCenterPoint } from \"./bounds\";\n\nimport type {\n ElementsMap,\n ExcalidrawDiamondElement,\n ExcalidrawElement,\n ExcalidrawEllipseElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawLinearElement,\n ExcalidrawRectanguloidElement,\n} from \"./types\";\n\nexport const distanceToElement = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n p: GlobalPoint,\n): number => {\n switch (element.type) {\n case \"selection\":\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"magicframe\":\n return distanceToRectanguloidElement(element, elementsMap, p);\n case \"diamond\":\n return distanceToDiamondElement(element, elementsMap, p);\n case \"ellipse\":\n return distanceToEllipseElement(element, elementsMap, p);\n case \"line\":\n case \"arrow\":\n case \"freedraw\":\n return distanceToLinearOrFreeDraElement(element, p);\n }\n};\n\n/**\n * Returns the distance of a point and the provided rectangular-shaped element,\n * accounting for roundness and rotation\n *\n * @param element The rectanguloid element\n * @param p The point to consider\n * @returns The eucledian distance to the outline of the rectanguloid element\n */\nconst distanceToRectanguloidElement = (\n element: ExcalidrawRectanguloidElement,\n elementsMap: ElementsMap,\n p: GlobalPoint,\n) => {\n const center = elementCenterPoint(element, elementsMap);\n // To emulate a rotated rectangle we rotate the point in the inverse angle\n // instead. It's all the same distance-wise.\n const rotatedPoint = pointRotateRads(p, center, -element.angle as Radians);\n\n // Get the element's building components we can test against\n const [sides, corners] = deconstructRectanguloidElement(element);\n\n return Math.min(\n ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)),\n ...corners\n .map((a) => curvePointDistance(a, rotatedPoint))\n .filter((d): d is number => d !== null),\n );\n};\n\n/**\n * Returns the distance of a point and the provided diamond element, accounting\n * for roundness and rotation\n *\n * @param element The diamond element\n * @param p The point to consider\n * @returns The eucledian distance to the outline of the diamond\n */\nconst distanceToDiamondElement = (\n element: ExcalidrawDiamondElement,\n elementsMap: ElementsMap,\n p: GlobalPoint,\n): number => {\n const center = elementCenterPoint(element, elementsMap);\n\n // Rotate the point to the inverse direction to simulate the rotated diamond\n // points. It's all the same distance-wise.\n const rotatedPoint = pointRotateRads(p, center, -element.angle as Radians);\n\n const [sides, curves] = deconstructDiamondElement(element);\n\n return Math.min(\n ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)),\n ...curves\n .map((a) => curvePointDistance(a, rotatedPoint))\n .filter((d): d is number => d !== null),\n );\n};\n\n/**\n * Returns the distance of a point and the provided ellipse element, accounting\n * for roundness and rotation\n *\n * @param element The ellipse element\n * @param p The point to consider\n * @returns The eucledian distance to the outline of the ellipse\n */\nconst distanceToEllipseElement = (\n element: ExcalidrawEllipseElement,\n elementsMap: ElementsMap,\n p: GlobalPoint,\n): number => {\n const center = elementCenterPoint(element, elementsMap);\n return ellipseDistanceFromPoint(\n // Instead of rotating the ellipse, rotate the point to the inverse angle\n pointRotateRads(p, center, -element.angle as Radians),\n ellipse(center, element.width / 2, element.height / 2),\n );\n};\n\nconst distanceToLinearOrFreeDraElement = (\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\n p: GlobalPoint,\n) => {\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\n return Math.min(\n ...lines.map((s) => distanceToLineSegment(p, s)),\n ...curves.map((a) => curvePointDistance(a, p)),\n );\n};\n", "import { invariant, isTransparent, type Bounds } from \"@excalidraw/common\";\nimport {\n curveIntersectLineSegment,\n isPointWithinBounds,\n lineSegment,\n lineSegmentIntersectionPoints,\n pointFrom,\n pointFromVector,\n pointRotateRads,\n pointsEqual,\n vectorFromPoint,\n vectorNormalize,\n vectorScale,\n} from \"@excalidraw/math\";\n\nimport {\n ellipse,\n ellipseSegmentInterceptPoints,\n} from \"@excalidraw/math/ellipse\";\n\nimport type {\n Curve,\n GlobalPoint,\n LineSegment,\n Radians,\n} from \"@excalidraw/math\";\n\nimport type { FrameNameBounds } from \"@excalidraw/excalidraw/types\";\n\nimport { isPathALoop } from \"./utils\";\nimport {\n doBoundsIntersect,\n elementCenterPoint,\n getCenterForBounds,\n getCubicBezierCurveBound,\n getDiamondPoints,\n getElementBounds,\n pointInsideBounds,\n} from \"./bounds\";\nimport {\n hasBoundTextElement,\n isBindableElement,\n isFrameLikeElement,\n isFreeDrawElement,\n isIframeLikeElement,\n isImageElement,\n isLinearElement,\n isTextElement,\n} from \"./typeChecks\";\nimport {\n deconstructDiamondElement,\n deconstructLinearOrFreeDrawElement,\n deconstructRectanguloidElement,\n} from \"./utils\";\n\nimport { getBoundTextElement } from \"./textElement\";\n\nimport { LinearElementEditor } from \"./linearElementEditor\";\n\nimport { distanceToElement } from \"./distance\";\n\nimport type {\n ElementsMap,\n ExcalidrawBindableElement,\n ExcalidrawDiamondElement,\n ExcalidrawElement,\n ExcalidrawEllipseElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawLinearElement,\n ExcalidrawRectanguloidElement,\n NonDeleted,\n NonDeletedExcalidrawElement,\n NonDeletedSceneElementsMap,\n Ordered,\n} from \"./types\";\n\nexport const shouldTestInside = (element: ExcalidrawElement) => {\n if (element.type === \"arrow\") {\n return false;\n }\n\n const isDraggableFromInside =\n !isTransparent(element.backgroundColor) ||\n hasBoundTextElement(element) ||\n isIframeLikeElement(element) ||\n isTextElement(element);\n\n if (element.type === \"line\") {\n return isDraggableFromInside && isPathALoop(element.points);\n }\n\n if (element.type === \"freedraw\") {\n return isDraggableFromInside && isPathALoop(element.points);\n }\n\n return isDraggableFromInside || isImageElement(element);\n};\n\nexport type HitTestArgs = {\n point: GlobalPoint;\n element: ExcalidrawElement;\n threshold: number;\n elementsMap: ElementsMap;\n frameNameBound?: FrameNameBounds | null;\n overrideShouldTestInside?: boolean;\n};\n\nexport const hitElementItself = ({\n point,\n element,\n threshold,\n elementsMap,\n frameNameBound = null,\n overrideShouldTestInside = false,\n}: HitTestArgs) => {\n if (element.customData?.isGhost) {\n return false;\n }\n\n // Hit test against a frame's name\n const hitFrameName = frameNameBound\n ? isPointWithinBounds(\n pointFrom(frameNameBound.x - threshold, frameNameBound.y - threshold),\n point,\n pointFrom(\n frameNameBound.x + frameNameBound.width + threshold,\n frameNameBound.y + frameNameBound.height + threshold,\n ),\n )\n : false;\n\n // Hit test against the extended, rotated bounding box of the element first\n const bounds = getElementBounds(element, elementsMap, true);\n const hitBounds = isPointWithinBounds(\n pointFrom(bounds[0] - threshold, bounds[1] - threshold),\n pointRotateRads(\n point,\n getCenterForBounds(bounds),\n -element.angle as Radians,\n ),\n pointFrom(bounds[2] + threshold, bounds[3] + threshold),\n );\n\n // PERF: Bail out early if the point is not even in the\n // rotated bounding box or not hitting the frame name (saves 99%)\n if (!hitBounds && !hitFrameName) {\n return false;\n }\n\n // Do the precise (and relatively costly) hit test\n const hitElement = (\n overrideShouldTestInside ? true : shouldTestInside(element)\n )\n ? // Since `inShape` tests STRICTLY againt the insides of a shape\n // we would need `onShape` as well to include the \"borders\"\n isPointInElement(point, element, elementsMap) ||\n isPointOnElementOutline(point, element, elementsMap, threshold)\n : isPointOnElementOutline(point, element, elementsMap, threshold);\n\n return hitElement || hitFrameName;\n};\n\nexport const hitElementBoundingBox = (\n point: GlobalPoint,\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n tolerance = 0,\n) => {\n let [x1, y1, x2, y2] = getElementBounds(element, elementsMap);\n x1 -= tolerance;\n y1 -= tolerance;\n x2 += tolerance;\n y2 += tolerance;\n return isPointWithinBounds(pointFrom(x1, y1), point, pointFrom(x2, y2));\n};\n\nexport const hitElementBoundingBoxOnly = (\n hitArgs: HitTestArgs,\n elementsMap: ElementsMap,\n) =>\n !hitElementItself(hitArgs) &&\n // bound text is considered part of the element (even if it's outside the bounding box)\n !hitElementBoundText(hitArgs.point, hitArgs.element, elementsMap) &&\n hitElementBoundingBox(hitArgs.point, hitArgs.element, elementsMap);\n\nexport const hitElementBoundText = (\n point: GlobalPoint,\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n): boolean => {\n const boundTextElementCandidate = getBoundTextElement(element, elementsMap);\n\n if (!boundTextElementCandidate) {\n return false;\n }\n const boundTextElement = isLinearElement(element)\n ? {\n ...boundTextElementCandidate,\n // arrow's bound text accurate position is not stored in the element's property\n // but rather calculated and returned from the following static method\n ...LinearElementEditor.getBoundTextElementPosition(\n element,\n boundTextElementCandidate,\n elementsMap,\n ),\n }\n : boundTextElementCandidate;\n\n return isPointInElement(point, boundTextElement, elementsMap);\n};\n\nconst bindingBorderTest = (\n element: NonDeleted<ExcalidrawBindableElement>,\n [x, y]: Readonly<GlobalPoint>,\n elementsMap: NonDeletedSceneElementsMap,\n tolerance: number = 0,\n): boolean => {\n const p = pointFrom<GlobalPoint>(x, y);\n const shouldTestInside =\n // disable fullshape snapping for frame elements so we\n // can bind to frame children\n !isFrameLikeElement(element);\n\n // PERF: Run a cheap test to see if the binding element\n // is even close to the element\n const t = Math.max(1, tolerance);\n const bounds = [x - t, y - t, x + t, y + t] as Bounds;\n const elementBounds = getElementBounds(element, elementsMap);\n if (!doBoundsIntersect(bounds, elementBounds)) {\n return false;\n }\n\n // If the element is inside a frame, we should clip the element\n if (element.frameId) {\n const enclosingFrame = elementsMap.get(element.frameId);\n if (enclosingFrame && isFrameLikeElement(enclosingFrame)) {\n const enclosingFrameBounds = getElementBounds(\n enclosingFrame,\n elementsMap,\n );\n if (!pointInsideBounds(p, enclosingFrameBounds)) {\n return false;\n }\n }\n }\n\n // Do the intersection test against the element since it's close enough\n const intersections = intersectElementWithLineSegment(\n element,\n elementsMap,\n lineSegment(elementCenterPoint(element, elementsMap), p),\n );\n const distance = distanceToElement(element, elementsMap, p);\n\n return shouldTestInside\n ? intersections.length === 0 || distance <= tolerance\n : intersections.length > 0 && distance <= t;\n};\n\nexport const getAllHoveredElementAtPoint = (\n point: Readonly<GlobalPoint>,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n elementsMap: NonDeletedSceneElementsMap,\n toleranceFn?: (element: ExcalidrawBindableElement) => number,\n): NonDeleted<ExcalidrawBindableElement>[] => {\n const candidateElements: NonDeleted<ExcalidrawBindableElement>[] = [];\n // We need to to hit testing from front (end of the array) to back (beginning of the array)\n // because array is ordered from lower z-index to highest and we want element z-index\n // with higher z-index\n for (let index = elements.length - 1; index >= 0; --index) {\n const element = elements[index];\n\n invariant(\n !element.isDeleted,\n \"Elements in the function parameter for getAllElementsAtPositionForBinding() should not contain deleted elements\",\n );\n\n if (\n isBindableElement(element, false) &&\n bindingBorderTest(element, point, elementsMap, toleranceFn?.(element))\n ) {\n candidateElements.push(element);\n\n if (!isTransparent(element.backgroundColor)) {\n break;\n }\n }\n }\n\n return candidateElements;\n};\n\nexport const getHoveredElementForBinding = (\n point: Readonly<GlobalPoint>,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n elementsMap: NonDeletedSceneElementsMap,\n toleranceFn?: (element: ExcalidrawBindableElement) => number,\n): NonDeleted<ExcalidrawBindableElement> | null => {\n const candidateElements = getAllHoveredElementAtPoint(\n point,\n elements,\n elementsMap,\n toleranceFn,\n );\n\n if (!candidateElements || candidateElements.length === 0) {\n return null;\n }\n\n if (candidateElements.length === 1) {\n return candidateElements[0];\n }\n\n // Prefer smaller shapes\n return candidateElements\n .sort(\n (a, b) => b.width ** 2 + b.height ** 2 - (a.width ** 2 + a.height ** 2),\n )\n .pop() as NonDeleted<ExcalidrawBindableElement>;\n};\n\n/**\n * Intersect a line with an element for binding test\n *\n * @param element\n * @param line\n * @param offset\n * @returns\n */\nexport const intersectElementWithLineSegment = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n line: LineSegment<GlobalPoint>,\n offset: number = 0,\n onlyFirst = false,\n): GlobalPoint[] => {\n // First check if the line intersects the element's axis-aligned bounding box\n // as it is much faster than checking intersection against the element's shape\n const intersectorBounds = [\n Math.min(line[0][0] - offset, line[1][0] - offset),\n Math.min(line[0][1] - offset, line[1][1] - offset),\n Math.max(line[0][0] + offset, line[1][0] + offset),\n Math.max(line[0][1] + offset, line[1][1] + offset),\n ] as Bounds;\n const elementBounds = getElementBounds(element, elementsMap);\n\n if (!doBoundsIntersect(intersectorBounds, elementBounds)) {\n return [];\n }\n\n // Do the actual intersection test against the element's shape\n switch (element.type) {\n case \"rectangle\":\n case \"image\":\n case \"text\":\n case \"iframe\":\n case \"embeddable\":\n case \"frame\":\n case \"selection\":\n case \"magicframe\":\n return intersectRectanguloidWithLineSegment(\n element,\n elementsMap,\n line,\n offset,\n onlyFirst,\n );\n case \"diamond\":\n return intersectDiamondWithLineSegment(\n element,\n elementsMap,\n line,\n offset,\n onlyFirst,\n );\n case \"ellipse\":\n return intersectEllipseWithLineSegment(\n element,\n elementsMap,\n line,\n offset,\n );\n case \"line\":\n case \"freedraw\":\n case \"arrow\":\n return intersectLinearOrFreeDrawWithLineSegment(element, line, onlyFirst);\n }\n};\n\nconst curveIntersections = (\n curves: Curve<GlobalPoint>[],\n segment: LineSegment<GlobalPoint>,\n intersections: GlobalPoint[],\n center: GlobalPoint,\n angle: Radians,\n onlyFirst = false,\n) => {\n for (const c of curves) {\n // Optimize by doing a cheap bounding box check first\n const b1 = getCubicBezierCurveBound(c[0], c[1], c[2], c[3]);\n const b2 = [\n Math.min(segment[0][0], segment[1][0]),\n Math.min(segment[0][1], segment[1][1]),\n Math.max(segment[0][0], segment[1][0]),\n Math.max(segment[0][1], segment[1][1]),\n ] as Bounds;\n\n if (!doBoundsIntersect(b1, b2)) {\n continue;\n }\n\n const hits = curveIntersectLineSegment(c, segment);\n\n if (hits.length > 0) {\n for (const j of hits) {\n intersections.push(pointRotateRads(j, center, angle));\n }\n\n if (onlyFirst) {\n return intersections;\n }\n }\n }\n\n return intersections;\n};\n\nconst lineIntersections = (\n lines: LineSegment<GlobalPoint>[],\n segment: LineSegment<GlobalPoint>,\n intersections: GlobalPoint[],\n center: GlobalPoint,\n angle: Radians,\n onlyFirst = false,\n) => {\n for (const l of lines) {\n const intersection = lineSegmentIntersectionPoints(l, segment);\n if (intersection) {\n intersections.push(pointRotateRads(intersection, center, angle));\n\n if (onlyFirst) {\n return intersections;\n }\n }\n }\n\n return intersections;\n};\n\nconst intersectLinearOrFreeDrawWithLineSegment = (\n element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,\n segment: LineSegment<GlobalPoint>,\n onlyFirst = false,\n): GlobalPoint[] => {\n // NOTE: This is the only one which return the decomposed elements\n // rotated! This is due to taking advantage of roughjs definitions.\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\n const intersections: GlobalPoint[] = [];\n\n for (const l of lines) {\n const intersection = lineSegmentIntersectionPoints(l, segment);\n if (intersection) {\n intersections.push(intersection);\n\n if (onlyFirst) {\n return intersections;\n }\n }\n }\n\n for (const c of curves) {\n // Optimize by doing a cheap bounding box check first\n const b1 = getCubicBezierCurveBound(c[0], c[1], c[2], c[3]);\n const b2 = [\n Math.min(segment[0][0], segment[1][0]),\n Math.min(segment[0][1], segment[1][1]),\n Math.max(segment[0][0], segment[1][0]),\n Math.max(segment[0][1], segment[1][1]),\n ] as Bounds;\n\n if (!doBoundsIntersect(b1, b2)) {\n continue;\n }\n\n const hits = curveIntersectLineSegment(c, segment);\n\n if (hits.length > 0) {\n intersections.push(...hits);\n\n if (onlyFirst) {\n return intersections;\n }\n }\n }\n\n return intersections;\n};\n\nconst intersectRectanguloidWithLineSegment = (\n element: ExcalidrawRectanguloidElement,\n elementsMap: ElementsMap,\n segment: LineSegment<GlobalPoint>,\n offset: number = 0,\n onlyFirst = false,\n): GlobalPoint[] => {\n const center = elementCenterPoint(element, elementsMap);\n // To emulate a rotated rectangle we rotate the point in the inverse angle\n // instead. It's all the same distance-wise.\n const rotatedA = pointRotateRads<GlobalPoint>(\n segment[0],\n center,\n -element.angle as Radians,\n );\n const rotatedB = pointRotateRads<GlobalPoint>(\n segment[1],\n center,\n -element.angle as Radians,\n );\n const rotatedIntersector = lineSegment(rotatedA, rotatedB);\n\n // Get the element's building components we can test against\n const [sides, corners] = deconstructRectanguloidElement(element, offset);\n\n const intersections: GlobalPoint[] = [];\n\n lineIntersections(\n sides,\n rotatedIntersector,\n intersections,\n center,\n element.angle,\n onlyFirst,\n );\n\n if (onlyFirst && intersections.length > 0) {\n return intersections;\n }\n\n curveIntersections(\n corners,\n rotatedIntersector,\n intersections,\n center,\n element.angle,\n onlyFirst,\n );\n\n return intersections;\n};\n\n/**\n *\n * @param element\n * @param a\n * @param b\n * @returns\n */\nconst intersectDiamondWithLineSegment = (\n element: ExcalidrawDiamondElement,\n elementsMap: ElementsMap,\n l: LineSegment<GlobalPoint>,\n offset: number = 0,\n onlyFirst = false,\n): GlobalPoint[] => {\n const center = elementCenterPoint(element, elementsMap);\n\n // Rotate the point to the inverse direction to simulate the rotated diamond\n // points. It's all the same distance-wise.\n const rotatedA = pointRotateRads(l[0], center, -element.angle as Radians);\n const rotatedB = pointRotateRads(l[1], center, -element.angle as Radians);\n const rotatedIntersector = lineSegment(rotatedA, rotatedB);\n\n const [sides, corners] = deconstructDiamondElement(element, offset);\n const intersections: GlobalPoint[] = [];\n\n lineIntersections(\n sides,\n rotatedIntersector,\n intersections,\n center,\n element.angle,\n onlyFirst,\n );\n\n if (onlyFirst && intersections.length > 0) {\n return intersections;\n }\n\n curveIntersections(\n corners,\n rotatedIntersector,\n intersections,\n center,\n element.angle,\n onlyFirst,\n );\n\n return intersections;\n};\n\n/**\n *\n * @param element\n * @param a\n * @param b\n * @returns\n */\nconst intersectEllipseWithLineSegment = (\n element: ExcalidrawEllipseElement,\n elementsMap: ElementsMap,\n l: LineSegment<GlobalPoint>,\n offset: number = 0,\n): GlobalPoint[] => {\n const center = elementCenterPoint(element, elementsMap);\n\n const rotatedA = pointRotateRads(l[0], center, -element.angle as Radians);\n const rotatedB = pointRotateRads(l[1], center, -element.angle as Radians);\n\n return ellipseSegmentInterceptPoints(\n ellipse(center, element.width / 2 + offset, element.height / 2 + offset),\n lineSegment(rotatedA, rotatedB),\n ).map((p) => pointRotateRads(p, center, element.angle));\n};\n\n/**\n * Check if the given point is considered on the given shape's border\n *\n * @param point\n * @param element\n * @param tolerance\n * @returns\n */\nconst isPointOnElementOutline = (\n point: GlobalPoint,\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n tolerance = 1,\n) => distanceToElement(element, elementsMap, point) <= tolerance;\n\n/**\n * Check if the given point is considered inside the element's border\n *\n * @param point\n * @param element\n * @returns\n */\nexport const isPointInElement = (\n point: GlobalPoint,\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n) => {\n if (\n (isLinearElement(element) || isFreeDrawElement(element)) &&\n !isPathALoop(element.points)\n ) {\n // There isn't any \"inside\" for a non-looping path\n return false;\n }\n\n const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);\n\n if (!isPointWithinBounds(pointFrom(x1, y1), point, pointFrom(x2, y2))) {\n return false;\n }\n\n const center = pointFrom<GlobalPoint>((x1 + x2) / 2, (y1 + y2) / 2);\n const otherPoint = pointFromVector(\n vectorScale(\n vectorNormalize(vectorFromPoint(point, center, 0.1)),\n Math.max(element.width, element.height) * 2,\n ),\n center,\n );\n const intersector = lineSegment(point, otherPoint);\n const intersections = intersectElementWithLineSegment(\n element,\n elementsMap,\n intersector,\n ).filter((p, pos, arr) => arr.findIndex((q) => pointsEqual(q, p)) === pos);\n\n return intersections.length % 2 === 1;\n};\n\nexport const isBindableElementInsideOtherBindable = (\n innerElement: ExcalidrawBindableElement,\n outerElement: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n): boolean => {\n // Get corner points of the inner element based on its type\n const getCornerPoints = (\n element: ExcalidrawElement,\n offset: number,\n ): GlobalPoint[] => {\n const { x, y, width, height, angle } = element;\n const center = elementCenterPoint(element, elementsMap);\n\n if (element.type === \"diamond\") {\n // Diamond has 4 corner points at the middle of each side\n const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =\n getDiamondPoints(element);\n const corners: GlobalPoint[] = [\n pointFrom(x + topX, y + topY - offset), // top\n pointFrom(x + rightX + offset, y + rightY), // right\n pointFrom(x + bottomX, y + bottomY + offset), // bottom\n pointFrom(x + leftX - offset, y + leftY), // left\n ];\n return corners.map((corner) => pointRotateRads(corner, center, angle));\n }\n if (element.type === \"ellipse\") {\n // For ellipse, test points at the extremes (top, right, bottom, left)\n const cx = x + width / 2;\n const cy = y + height / 2;\n const rx = width / 2;\n const ry = height / 2;\n const corners: GlobalPoint[] = [\n pointFrom(cx, cy - ry - offset), // top\n pointFrom(cx + rx + offset, cy), // right\n pointFrom(cx, cy + ry + offset), // bottom\n pointFrom(cx - rx - offset, cy), // left\n ];\n return corners.map((corner) => pointRotateRads(corner, center, angle));\n }\n // Rectangle and other rectangular shapes (image, text, etc.)\n const corners: GlobalPoint[] = [\n pointFrom(x - offset, y - offset), // top-left\n pointFrom(x + width + offset, y - offset), // top-right\n pointFrom(x + width + offset, y + height + offset), // bottom-right\n pointFrom(x - offset, y + height + offset), // bottom-left\n ];\n return corners.map((corner) => pointRotateRads(corner, center, angle));\n };\n\n const offset = (-1 * Math.max(innerElement.width, innerElement.height)) / 20; // 5% offset\n const innerCorners = getCornerPoints(innerElement, offset);\n\n // Check if all corner points of the inner element are inside the outer element\n return innerCorners.every((corner) =>\n isPointInElement(corner, outerElement, elementsMap),\n );\n};\n", "import {\n invariant,\n isDevEnv,\n isTestEnv,\n type Bounds,\n} from \"@excalidraw/common\";\n\nimport {\n pointFrom,\n pointFromVector,\n pointRotateRads,\n pointScaleFromOrigin,\n pointsEqual,\n triangleIncludesPoint,\n vectorCross,\n vectorFromPoint,\n vectorScale,\n} from \"@excalidraw/math\";\n\nimport type {\n LocalPoint,\n GlobalPoint,\n Triangle,\n Vector,\n} from \"@excalidraw/math\";\n\nimport { getCenterForBounds } from \"./bounds\";\n\nimport type { ExcalidrawBindableElement } from \"./types\";\n\nexport const HEADING_RIGHT = [1, 0] as Heading;\nexport const HEADING_DOWN = [0, 1] as Heading;\nexport const HEADING_LEFT = [-1, 0] as Heading;\nexport const HEADING_UP = [0, -1] as Heading;\nexport type Heading = [1, 0] | [0, 1] | [-1, 0] | [0, -1];\n\nexport const vectorToHeading = (vec: Vector): Heading => {\n const [x, y] = vec;\n const absX = Math.abs(x);\n const absY = Math.abs(y);\n if (x > absY) {\n return HEADING_RIGHT;\n } else if (x <= -absY) {\n return HEADING_LEFT;\n } else if (y > absX) {\n return HEADING_DOWN;\n }\n return HEADING_UP;\n};\n\nexport const headingForPoint = <P extends GlobalPoint | LocalPoint>(\n p: P,\n o: P,\n) => vectorToHeading(vectorFromPoint<P>(p, o));\n\nexport const headingForPointIsHorizontal = <P extends GlobalPoint | LocalPoint>(\n p: P,\n o: P,\n) => headingIsHorizontal(headingForPoint<P>(p, o));\n\nexport const compareHeading = (a: Heading, b: Heading) =>\n a[0] === b[0] && a[1] === b[1];\n\nexport const headingIsHorizontal = (a: Heading) =>\n compareHeading(a, HEADING_RIGHT) || compareHeading(a, HEADING_LEFT);\n\nexport const headingIsVertical = (a: Heading) => !headingIsHorizontal(a);\n\nconst headingForPointFromDiamondElement = (\n element: Readonly<ExcalidrawBindableElement>,\n aabb: Readonly<Bounds>,\n point: Readonly<GlobalPoint>,\n): Heading => {\n const midPoint = getCenterForBounds(aabb);\n\n if (isDevEnv() || isTestEnv()) {\n invariant(\n element.width > 0 && element.height > 0,\n \"Diamond element has no width or height\",\n );\n invariant(\n !pointsEqual(midPoint, point),\n \"The point is too close to the element mid point to determine heading\",\n );\n }\n\n const SHRINK = 0.95; // Rounded elements tolerance\n const top = pointFromVector(\n vectorScale(\n vectorFromPoint(\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x + element.width / 2, element.y),\n midPoint,\n element.angle,\n ),\n midPoint,\n ),\n SHRINK,\n ),\n midPoint,\n );\n const right = pointFromVector(\n vectorScale(\n vectorFromPoint(\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + element.width,\n element.y + element.height / 2,\n ),\n midPoint,\n element.angle,\n ),\n midPoint,\n ),\n SHRINK,\n ),\n midPoint,\n );\n const bottom = pointFromVector(\n vectorScale(\n vectorFromPoint(\n pointRotateRads(\n pointFrom<GlobalPoint>(\n element.x + element.width / 2,\n element.y + element.height,\n ),\n midPoint,\n element.angle,\n ),\n midPoint,\n ),\n SHRINK,\n ),\n midPoint,\n );\n const left = pointFromVector(\n vectorScale(\n vectorFromPoint(\n pointRotateRads(\n pointFrom<GlobalPoint>(element.x, element.y + element.height / 2),\n midPoint,\n element.angle,\n ),\n midPoint,\n ),\n SHRINK,\n ),\n midPoint,\n );\n\n // Corners\n if (\n vectorCross(vectorFromPoint(point, top), vectorFromPoint(top, right)) <=\n 0 &&\n vectorCross(vectorFromPoint(point, top), vectorFromPoint(top, left)) > 0\n ) {\n return headingForPoint(top, midPoint);\n } else if (\n vectorCross(\n vectorFromPoint(point, right),\n vectorFromPoint(right, bottom),\n ) <= 0 &&\n vectorCross(vectorFromPoint(point, right), vectorFromPoint(right, top)) > 0\n ) {\n return headingForPoint(right, midPoint);\n } else if (\n vectorCross(\n vectorFromPoint(point, bottom),\n vectorFromPoint(bottom, left),\n ) <= 0 &&\n vectorCross(\n vectorFromPoint(point, bottom),\n vectorFromPoint(bottom, right),\n ) > 0\n ) {\n return headingForPoint(bottom, midPoint);\n } else if (\n vectorCross(vectorFromPoint(point, left), vectorFromPoint(left, top)) <=\n 0 &&\n vectorCross(vectorFromPoint(point, left), vectorFromPoint(left, bottom)) > 0\n ) {\n return headingForPoint(left, midPoint);\n }\n\n // Sides\n if (\n vectorCross(\n vectorFromPoint(point, midPoint),\n vectorFromPoint(top, midPoint),\n ) <= 0 &&\n vectorCross(\n vectorFromPoint(point, midPoint),\n vectorFromPoint(right, midPoint),\n ) > 0\n ) {\n const p = element.width > element.height ? top : right;\n return headingForPoint(p, midPoint);\n } else if (\n vectorCross(\n vectorFromPoint(point, midPoint),\n vectorFromPoint(right, midPoint),\n ) <= 0 &&\n vectorCross(\n vectorFromPoint(point, midPoint),\n vectorFromPoint(bottom, midPoint),\n ) > 0\n ) {\n const p = element.width > element.height ? bottom : right;\n return headingForPoint(p, midPoint);\n } else if (\n vectorCross(\n vectorFromPoint(point, midPoint),\n vectorFromPoint(bottom, midPoint),\n ) <= 0 &&\n vectorCross(\n vectorFromPoint(point, midPoint),\n vectorFromPoint(left, midPoint),\n ) > 0\n ) {\n const p = element.width > element.height ? bottom : left;\n return headingForPoint(p, midPoint);\n }\n\n const p = element.width > element.height ? top : left;\n return headingForPoint(p, midPoint);\n};\n\n// Gets the heading for the point by creating a bounding box around the rotated\n// close fitting bounding box, then creating 4 search cones around the center of\n// the external bbox.\nexport const headingForPointFromElement = <Point extends GlobalPoint>(\n element: Readonly<ExcalidrawBindableElement>,\n aabb: Readonly<Bounds>,\n p: Readonly<Point>,\n): Heading => {\n const SEARCH_CONE_MULTIPLIER = 2;\n\n const midPoint = getCenterForBounds(aabb);\n\n if (element.type === \"diamond\") {\n return headingForPointFromDiamondElement(element, aabb, p);\n }\n\n const topLeft = pointScaleFromOrigin(\n pointFrom(aabb[0], aabb[1]),\n midPoint,\n SEARCH_CONE_MULTIPLIER,\n ) as Point;\n const topRight = pointScaleFromOrigin(\n pointFrom(aabb[2], aabb[1]),\n midPoint,\n SEARCH_CONE_MULTIPLIER,\n ) as Point;\n const bottomLeft = pointScaleFromOrigin(\n pointFrom(aabb[0], aabb[3]),\n midPoint,\n SEARCH_CONE_MULTIPLIER,\n ) as Point;\n const bottomRight = pointScaleFromOrigin(\n pointFrom(aabb[2], aabb[3]),\n midPoint,\n SEARCH_CONE_MULTIPLIER,\n ) as Point;\n\n return triangleIncludesPoint<Point>(\n [topLeft, topRight, midPoint] as Triangle<Point>,\n p,\n )\n ? HEADING_UP\n : triangleIncludesPoint<Point>(\n [topRight, bottomRight, midPoint] as Triangle<Point>,\n p,\n )\n ? HEADING_RIGHT\n : triangleIncludesPoint<Point>(\n [bottomRight, bottomLeft, midPoint] as Triangle<Point>,\n p,\n )\n ? HEADING_DOWN\n : HEADING_LEFT;\n};\n\nexport const flipHeading = (h: Heading): Heading =>\n [\n h[0] === 0 ? 0 : h[0] > 0 ? -1 : 1,\n h[1] === 0 ? 0 : h[1] > 0 ? -1 : 1,\n ] as Heading;\n", "import {\n clamp,\n pointDistance,\n pointFrom,\n pointScaleFromOrigin,\n pointsEqual,\n pointTranslate,\n vector,\n vectorCross,\n vectorFromPoint,\n vectorScale,\n type GlobalPoint,\n type LocalPoint,\n} from \"@excalidraw/math\";\n\nimport {\n type Bounds,\n BinaryHeap,\n invariant,\n isAnyTrue,\n getSizeFromPoints,\n isDevEnv,\n arrayToMap,\n} from \"@excalidraw/common\";\n\nimport type { AppState } from \"@excalidraw/excalidraw/types\";\n\nimport {\n bindPointToSnapToElementOutline,\n getHeadingForElbowArrowSnap,\n getGlobalFixedPointForBindableElement,\n getBindingGap,\n maxBindingDistance_simple,\n BASE_BINDING_GAP_ELBOW,\n} from \"./binding\";\nimport { distanceToElement } from \"./distance\";\nimport {\n compareHeading,\n flipHeading,\n HEADING_DOWN,\n HEADING_LEFT,\n HEADING_RIGHT,\n HEADING_UP,\n headingForPointIsHorizontal,\n headingIsHorizontal,\n vectorToHeading,\n headingForPoint,\n} from \"./heading\";\nimport { type ElementUpdate } from \"./mutateElement\";\nimport { isBindableElement } from \"./typeChecks\";\nimport {\n type ExcalidrawElbowArrowElement,\n type NonDeletedSceneElementsMap,\n} from \"./types\";\nimport { aabbForElement, pointInsideBounds } from \"./bounds\";\nimport { getHoveredElementForBinding } from \"./collision\";\n\nimport type { Heading } from \"./heading\";\nimport type {\n Arrowhead,\n ElementsMap,\n ExcalidrawBindableElement,\n FixedPointBinding,\n FixedSegment,\n NonDeletedExcalidrawElement,\n Ordered,\n} from \"./types\";\n\ntype GridAddress = [number, number] & { _brand: \"gridaddress\" };\n\ntype Node = {\n f: number;\n g: number;\n h: number;\n closed: boolean;\n visited: boolean;\n parent: Node | null;\n pos: GlobalPoint;\n addr: GridAddress;\n};\n\ntype Grid = {\n row: number;\n col: number;\n data: (Node | null)[];\n};\n\ntype ElbowArrowState = {\n x: number;\n y: number;\n startBinding: FixedPointBinding | null;\n endBinding: FixedPointBinding | null;\n startArrowhead: Arrowhead | null;\n endArrowhead: Arrowhead | null;\n};\n\ntype ElbowArrowData = {\n dynamicAABBs: Bounds[];\n startDonglePosition: GlobalPoint | null;\n startGlobalPoint: GlobalPoint;\n startHeading: Heading;\n endDonglePosition: GlobalPoint | null;\n endGlobalPoint: GlobalPoint;\n endHeading: Heading;\n commonBounds: Bounds;\n hoveredStartElement: ExcalidrawBindableElement | null;\n hoveredEndElement: ExcalidrawBindableElement | null;\n};\n\nconst DEDUP_TRESHOLD = 1;\nexport const BASE_PADDING = 40;\n\nconst handleSegmentRenormalization = (\n arrow: ExcalidrawElbowArrowElement,\n elementsMap: NonDeletedSceneElementsMap,\n) => {\n const nextFixedSegments: FixedSegment[] | null = arrow.fixedSegments\n ? arrow.fixedSegments.slice()\n : null;\n\n if (nextFixedSegments) {\n const _nextPoints: GlobalPoint[] = [];\n\n arrow.points\n .map((p) => pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]))\n .forEach((p, i, points) => {\n if (i < 2) {\n return _nextPoints.push(p);\n }\n\n const currentSegmentIsHorizontal = headingForPoint(p, points[i - 1]);\n const prevSegmentIsHorizontal = headingForPoint(\n points[i - 1],\n points[i - 2],\n );\n\n if (\n // Check if previous two points are on the same line\n compareHeading(currentSegmentIsHorizontal, prevSegmentIsHorizontal)\n ) {\n const prevSegmentIdx =\n nextFixedSegments?.findIndex(\n (segment) => segment.index === i - 1,\n ) ?? -1;\n const segmentIdx =\n nextFixedSegments?.findIndex((segment) => segment.index === i) ??\n -1;\n\n // If the current segment is a fixed segment, update its start point\n if (segmentIdx !== -1) {\n nextFixedSegments[segmentIdx].start = pointFrom<LocalPoint>(\n points[i - 2][0] - arrow.x,\n points[i - 2][1] - arrow.y,\n );\n }\n\n // Remove the fixed segment status from the previous segment if it is\n // a fixed segment, because we are going to unify that segment with\n // the current one\n if (prevSegmentIdx !== -1) {\n nextFixedSegments.splice(prevSegmentIdx, 1);\n }\n\n // Remove the duplicate point\n _nextPoints.splice(-1, 1);\n\n // Update fixed point indices\n nextFixedSegments.forEach((segment) => {\n if (segment.index > i - 1) {\n segment.index -= 1;\n }\n });\n }\n\n return _nextPoints.push(p);\n });\n\n const nextPoints: GlobalPoint[] = [];\n\n _nextPoints.forEach((p, i, points) => {\n if (i < 3) {\n return nextPoints.push(p);\n }\n\n if (\n // Remove segments that are too short\n pointDistance(points[i - 2], points[i - 1]) < DEDUP_TRESHOLD\n ) {\n const prevPrevSegmentIdx =\n nextFixedSegments?.findIndex((segment) => segment.index === i - 2) ??\n -1;\n const prevSegmentIdx =\n nextFixedSegments?.findIndex((segment) => segment.index === i - 1) ??\n -1;\n\n // Remove the previous fixed segment if it exists (i.e. the segment\n // which will be removed due to being parallel or too short)\n if (prevSegmentIdx !== -1) {\n nextFixedSegments.splice(prevSegmentIdx, 1);\n }\n\n // Remove the fixed segment status from the segment 2 steps back\n // if it is a fixed segment, because we are going to unify that\n // segment with the current one\n if (prevPrevSegmentIdx !== -1) {\n nextFixedSegments.splice(prevPrevSegmentIdx, 1);\n }\n\n nextPoints.splice(-2, 2);\n\n // Since we have to remove two segments, update any fixed segment\n nextFixedSegments.forEach((segment) => {\n if (segment.index > i - 2) {\n segment.index -= 2;\n }\n });\n\n // Remove aligned segment points\n const isHorizontal = headingForPointIsHorizontal(p, points[i - 1]);\n\n return nextPoints.push(\n pointFrom<GlobalPoint>(\n !isHorizontal ? points[i - 2][0] : p[0],\n isHorizontal ? points[i - 2][1] : p[1],\n ),\n );\n }\n\n nextPoints.push(p);\n });\n\n const filteredNextFixedSegments = nextFixedSegments.filter(\n (segment) =>\n segment.index !== 1 && segment.index !== nextPoints.length - 1,\n );\n if (filteredNextFixedSegments.length === 0) {\n return normalizeArrowElementUpdate(\n getElbowArrowCornerPoints(\n removeElbowArrowShortSegments(\n routeElbowArrow(\n arrow,\n getElbowArrowData(\n arrow,\n elementsMap,\n nextPoints.map((p) =>\n pointFrom<LocalPoint>(p[0] - arrow.x, p[1] - arrow.y),\n ),\n ),\n ) ?? [],\n ),\n ),\n filteredNextFixedSegments,\n null,\n null,\n );\n }\n\n isDevEnv() &&\n invariant(\n validateElbowPoints(nextPoints),\n \"Invalid elbow points with fixed segments\",\n );\n\n return normalizeArrowElementUpdate(\n nextPoints,\n filteredNextFixedSegments,\n arrow.startIsSpecial,\n arrow.endIsSpecial,\n );\n }\n\n return {\n x: arrow.x,\n y: arrow.y,\n points: arrow.points,\n fixedSegments: arrow.fixedSegments,\n startIsSpecial: arrow.startIsSpecial,\n endIsSpecial: arrow.endIsSpecial,\n };\n};\n\nconst handleSegmentRelease = (\n arrow: ExcalidrawElbowArrowElement,\n fixedSegments: readonly FixedSegment[],\n elementsMap: NonDeletedSceneElementsMap,\n) => {\n const newFixedSegmentIndices = fixedSegments.map((segment) => segment.index);\n const oldFixedSegmentIndices =\n arrow.fixedSegments?.map((segment) => segment.index) ?? [];\n const deletedSegmentIdx = oldFixedSegmentIndices.findIndex(\n (idx) => !newFixedSegmentIndices.includes(idx),\n );\n\n if (deletedSegmentIdx === -1 || !arrow.fixedSegments?.[deletedSegmentIdx]) {\n return {\n points: arrow.points,\n };\n }\n\n const deletedIdx = arrow.fixedSegments[deletedSegmentIdx].index;\n\n // Find prev and next fixed segments\n const prevSegment = arrow.fixedSegments[deletedSegmentIdx - 1];\n const nextSegment = arrow.fixedSegments[deletedSegmentIdx + 1];\n\n // We need to render a sub-arrow path to restore deleted segments\n const x = arrow.x + (prevSegment ? prevSegment.end[0] : 0);\n const y = arrow.y + (prevSegment ? prevSegment.end[1] : 0);\n const startBinding = prevSegment ? null : arrow.startBinding;\n const endBinding = nextSegment ? null : arrow.endBinding;\n const {\n startHeading,\n endHeading,\n startGlobalPoint,\n endGlobalPoint,\n hoveredStartElement,\n hoveredEndElement,\n ...rest\n } = getElbowArrowData(\n {\n x,\n y,\n startBinding,\n endBinding,\n startArrowhead: null,\n endArrowhead: null,\n points: arrow.points,\n },\n elementsMap,\n [\n pointFrom<LocalPoint>(0, 0),\n pointFrom<LocalPoint>(\n arrow.x +\n (nextSegment?.start[0] ?? arrow.points[arrow.points.length - 1][0]) -\n x,\n arrow.y +\n (nextSegment?.start[1] ?? arrow.points[arrow.points.length - 1][1]) -\n y,\n ),\n ],\n { isDragging: false },\n );\n\n const { points: restoredPoints } = normalizeArrowElementUpdate(\n getElbowArrowCornerPoints(\n removeElbowArrowShortSegments(\n routeElbowArrow(arrow, {\n startHeading,\n endHeading,\n startGlobalPoint,\n endGlobalPoint,\n hoveredStartElement,\n hoveredEndElement,\n ...rest,\n }) ?? [],\n ),\n ),\n fixedSegments,\n null,\n null,\n );\n\n if (!restoredPoints || restoredPoints.length < 2) {\n throw new Error(\n \"Property 'points' is required in the update returned by normalizeArrowElementUpdate()\",\n );\n }\n\n const nextPoints: GlobalPoint[] = [];\n\n // First part of the arrow are the old points\n if (prevSegment) {\n for (let i = 0; i < prevSegment.index; i++) {\n nextPoints.push(\n pointFrom<GlobalPoint>(\n arrow.x + arrow.points[i][0],\n arrow.y + arrow.points[i][1],\n ),\n );\n }\n }\n\n restoredPoints.forEach((p) => {\n nextPoints.push(\n pointFrom<GlobalPoint>(\n arrow.x + (prevSegment ? prevSegment.end[0] : 0) + p[0],\n arrow.y + (prevSegment ? prevSegment.end[1] : 0) + p[1],\n ),\n );\n });\n\n // Last part of the arrow are the old points too\n if (nextSegment) {\n for (let i = nextSegment.index; i < arrow.points.length; i++) {\n nextPoints.push(\n pointFrom<GlobalPoint>(\n arrow.x + arrow.points[i][0],\n arrow.y + arrow.points[i][1],\n ),\n );\n }\n }\n\n // Update nextFixedSegments\n const originalSegmentCountDiff =\n (nextSegment?.index ?? arrow.points.length) - (prevSegment?.index ?? 0) - 1;\n\n const nextFixedSegments = fixedSegments.map((segment) => {\n if (segment.index > deletedIdx) {\n return {\n ...segment,\n index:\n segment.index -\n originalSegmentCountDiff +\n (restoredPoints.length - 1),\n };\n }\n\n return segment;\n });\n\n const simplifiedPoints = nextPoints.flatMap((p, i) => {\n const prev = nextPoints[i - 1];\n const next = nextPoints[i + 1];\n\n if (prev && next) {\n const prevHeading = headingForPoint(p, prev);\n const nextHeading = headingForPoint(next, p);\n\n if (compareHeading(prevHeading, nextHeading)) {\n // Update subsequent fixed segment indices\n nextFixedSegments.forEach((segment) => {\n if (segment.index > i) {\n segment.index -= 1;\n }\n });\n\n return [];\n } else if (compareHeading(prevHeading, flipHeading(nextHeading))) {\n // Update subsequent fixed segment indices\n nextFixedSegments.forEach((segment) => {\n if (segment.index > i) {\n segment.index += 1;\n }\n });\n\n return [p, p];\n }\n }\n\n return [p];\n });\n\n return normalizeArrowElementUpdate(\n simplifiedPoints,\n nextFixedSegments,\n false,\n false,\n );\n};\n\n/**\n *\n */\nconst handleSegmentMove = (\n arrow: ExcalidrawElbowArrowElement,\n fixedSegments: readonly FixedSegment[],\n startHeading: Heading,\n endHeading: Heading,\n hoveredStartElement: ExcalidrawBindableElement | null,\n hoveredEndElement: ExcalidrawBindableElement | null,\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\n const activelyModifiedSegmentIdx = fixedSegments\n .map((segment, i) => {\n if (\n arrow.fixedSegments == null ||\n arrow.fixedSegments[i] === undefined ||\n arrow.fixedSegments[i].index !== segment.index\n ) {\n return i;\n }\n\n return (segment.start[0] !== arrow.fixedSegments![i].start[0] &&\n segment.end[0] !== arrow.fixedSegments![i].end[0]) !==\n (segment.start[1] !== arrow.fixedSegments![i].start[1] &&\n segment.end[1] !== arrow.fixedSegments![i].end[1])\n ? i\n : null;\n })\n .filter((idx) => idx !== null)\n .shift();\n\n if (activelyModifiedSegmentIdx == null) {\n return { points: arrow.points };\n }\n\n const firstSegmentIdx =\n arrow.fixedSegments?.findIndex((segment) => segment.index === 1) ?? -1;\n const lastSegmentIdx =\n arrow.fixedSegments?.findIndex(\n (segment) => segment.index === arrow.points.length - 1,\n ) ?? -1;\n\n // Handle special case for first segment move\n const segmentLength = pointDistance(\n fixedSegments[activelyModifiedSegmentIdx].start,\n fixedSegments[activelyModifiedSegmentIdx].end,\n );\n const segmentIsTooShort = segmentLength < BASE_PADDING + 5;\n if (\n firstSegmentIdx === -1 &&\n fixedSegments[activelyModifiedSegmentIdx].index === 1 &&\n hoveredStartElement\n ) {\n const startIsHorizontal = headingIsHorizontal(startHeading);\n const startIsPositive = startIsHorizontal\n ? compareHeading(startHeading, HEADING_RIGHT)\n : compareHeading(startHeading, HEADING_DOWN);\n const padding = startIsPositive\n ? segmentIsTooShort\n ? segmentLength / 2\n : BASE_PADDING\n : segmentIsTooShort\n ? -segmentLength / 2\n : -BASE_PADDING;\n fixedSegments[activelyModifiedSegmentIdx].start = pointFrom<LocalPoint>(\n fixedSegments[activelyModifiedSegmentIdx].start[0] +\n (startIsHorizontal ? padding : 0),\n fixedSegments[activelyModifiedSegmentIdx].start[1] +\n (!startIsHorizontal ? padding : 0),\n );\n }\n\n // Handle special case for last segment move\n if (\n lastSegmentIdx === -1 &&\n fixedSegments[activelyModifiedSegmentIdx].index ===\n arrow.points.length - 1 &&\n hoveredEndElement\n ) {\n const endIsHorizontal = headingIsHorizontal(endHeading);\n const endIsPositive = endIsHorizontal\n ? compareHeading(endHeading, HEADING_RIGHT)\n : compareHeading(endHeading, HEADING_DOWN);\n const padding = endIsPositive\n ? segmentIsTooShort\n ? segmentLength / 2\n : BASE_PADDING\n : segmentIsTooShort\n ? -segmentLength / 2\n : -BASE_PADDING;\n fixedSegments[activelyModifiedSegmentIdx].end = pointFrom<LocalPoint>(\n fixedSegments[activelyModifiedSegmentIdx].end[0] +\n (endIsHorizontal ? padding : 0),\n fixedSegments[activelyModifiedSegmentIdx].end[1] +\n (!endIsHorizontal ? padding : 0),\n );\n }\n\n // Translate all fixed segments to global coordinates\n const nextFixedSegments = fixedSegments.map((segment) => ({\n ...segment,\n start: pointFrom<GlobalPoint>(\n arrow.x + segment.start[0],\n arrow.y + segment.start[1],\n ),\n end: pointFrom<GlobalPoint>(\n arrow.x + segment.end[0],\n arrow.y + segment.end[1],\n ),\n }));\n\n // For start, clone old arrow points\n const newPoints: GlobalPoint[] = arrow.points.map((p, i) =>\n pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),\n );\n\n const startIdx = nextFixedSegments[activelyModifiedSegmentIdx].index - 1;\n const endIdx = nextFixedSegments[activelyModifiedSegmentIdx].index;\n const start = nextFixedSegments[activelyModifiedSegmentIdx].start;\n const end = nextFixedSegments[activelyModifiedSegmentIdx].end;\n const prevSegmentIsHorizontal =\n newPoints[startIdx - 1] &&\n !pointsEqual(newPoints[startIdx], newPoints[startIdx - 1])\n ? headingForPointIsHorizontal(\n newPoints[startIdx - 1],\n newPoints[startIdx],\n )\n : undefined;\n const nextSegmentIsHorizontal =\n newPoints[endIdx + 1] &&\n !pointsEqual(newPoints[endIdx], newPoints[endIdx + 1])\n ? headingForPointIsHorizontal(newPoints[endIdx + 1], newPoints[endIdx])\n : undefined;\n\n // Override the segment points with the actively moved fixed segment\n if (prevSegmentIsHorizontal !== undefined) {\n const dir = prevSegmentIsHorizontal ? 1 : 0;\n newPoints[startIdx - 1][dir] = start[dir];\n }\n newPoints[startIdx] = start;\n newPoints[endIdx] = end;\n if (nextSegmentIsHorizontal !== undefined) {\n const dir = nextSegmentIsHorizontal ? 1 : 0;\n newPoints[endIdx + 1][dir] = end[dir];\n }\n\n // Override neighboring fixedSegment start/end points, if any\n const prevSegmentIdx = nextFixedSegments.findIndex(\n (segment) => segment.index === startIdx,\n );\n if (prevSegmentIdx !== -1) {\n // Align the next segment points with the moved segment\n const dir = headingForPointIsHorizontal(\n nextFixedSegments[prevSegmentIdx].end,\n nextFixedSegments[prevSegmentIdx].start,\n )\n ? 1\n : 0;\n nextFixedSegments[prevSegmentIdx].start[dir] = start[dir];\n nextFixedSegments[prevSegmentIdx].end = start;\n }\n\n const nextSegmentIdx = nextFixedSegments.findIndex(\n (segment) => segment.index === endIdx + 1,\n );\n if (nextSegmentIdx !== -1) {\n // Align the next segment points with the moved segment\n const dir = headingForPointIsHorizontal(\n nextFixedSegments[nextSegmentIdx].end,\n nextFixedSegments[nextSegmentIdx].start,\n )\n ? 1\n : 0;\n nextFixedSegments[nextSegmentIdx].end[dir] = end[dir];\n nextFixedSegments[nextSegmentIdx].start = end;\n }\n\n // First segment move needs an additional segment\n if (firstSegmentIdx === -1 && startIdx === 0) {\n const startIsHorizontal = hoveredStartElement\n ? headingIsHorizontal(startHeading)\n : headingForPointIsHorizontal(newPoints[1], newPoints[0]);\n newPoints.unshift(\n pointFrom<GlobalPoint>(\n startIsHorizontal ? start[0] : arrow.x + arrow.points[0][0],\n !startIsHorizontal ? start[1] : arrow.y + arrow.points[0][1],\n ),\n );\n\n if (hoveredStartElement) {\n newPoints.unshift(\n pointFrom<GlobalPoint>(\n arrow.x + arrow.points[0][0],\n arrow.y + arrow.points[0][1],\n ),\n );\n }\n\n for (const segment of nextFixedSegments) {\n segment.index += hoveredStartElement ? 2 : 1;\n }\n }\n\n // Last segment move needs an additional segment\n if (lastSegmentIdx === -1 && endIdx === arrow.points.length - 1) {\n const endIsHorizontal = headingIsHorizontal(endHeading);\n newPoints.push(\n pointFrom<GlobalPoint>(\n endIsHorizontal\n ? end[0]\n : arrow.x + arrow.points[arrow.points.length - 1][0],\n !endIsHorizontal\n ? end[1]\n : arrow.y + arrow.points[arrow.points.length - 1][1],\n ),\n );\n if (hoveredEndElement) {\n newPoints.push(\n pointFrom<GlobalPoint>(\n arrow.x + arrow.points[arrow.points.length - 1][0],\n arrow.y + arrow.points[arrow.points.length - 1][1],\n ),\n );\n }\n }\n\n return normalizeArrowElementUpdate(\n newPoints,\n nextFixedSegments.map((segment) => ({\n ...segment,\n start: pointFrom<LocalPoint>(\n segment.start[0] - arrow.x,\n segment.start[1] - arrow.y,\n ),\n end: pointFrom<LocalPoint>(\n segment.end[0] - arrow.x,\n segment.end[1] - arrow.y,\n ),\n })),\n false, // If you move a segment, there is no special point anymore\n false, // If you move a segment, there is no special point anymore\n );\n};\n\nconst handleEndpointDrag = (\n arrow: ExcalidrawElbowArrowElement,\n updatedPoints: readonly LocalPoint[],\n fixedSegments: readonly FixedSegment[],\n startHeading: Heading,\n endHeading: Heading,\n startGlobalPoint: GlobalPoint,\n endGlobalPoint: GlobalPoint,\n hoveredStartElement: ExcalidrawBindableElement | null,\n hoveredEndElement: ExcalidrawBindableElement | null,\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\n let startIsSpecial = arrow.startIsSpecial ?? null;\n let endIsSpecial = arrow.endIsSpecial ?? null;\n const globalUpdatedPoints = updatedPoints.map((p, i) =>\n i === 0\n ? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])\n : i === updatedPoints.length - 1\n ? pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1])\n : pointFrom<GlobalPoint>(\n arrow.x + arrow.points[i][0],\n arrow.y + arrow.points[i][1],\n ),\n );\n const nextFixedSegments = fixedSegments.map((segment) => ({\n ...segment,\n start: pointFrom<GlobalPoint>(\n arrow.x + (segment.start[0] - updatedPoints[0][0]),\n arrow.y + (segment.start[1] - updatedPoints[0][1]),\n ),\n end: pointFrom<GlobalPoint>(\n arrow.x + (segment.end[0] - updatedPoints[0][0]),\n arrow.y + (segment.end[1] - updatedPoints[0][1]),\n ),\n }));\n const newPoints: GlobalPoint[] = [];\n\n // Add the inside points\n const offset = 2 + (startIsSpecial ? 1 : 0);\n const endOffset = 2 + (endIsSpecial ? 1 : 0);\n while (newPoints.length + offset < globalUpdatedPoints.length - endOffset) {\n newPoints.push(globalUpdatedPoints[newPoints.length + offset]);\n }\n\n // Calculate the moving second point connection and add the start point\n {\n const secondPoint = globalUpdatedPoints.at(startIsSpecial ? 2 : 1);\n const thirdPoint = globalUpdatedPoints.at(startIsSpecial ? 3 : 2);\n\n if (!secondPoint || !thirdPoint) {\n throw new Error(\n `Second and third points must exist when handling endpoint drag (${startIsSpecial})`,\n );\n }\n\n const startIsHorizontal = headingIsHorizontal(startHeading);\n const secondIsHorizontal = headingIsHorizontal(\n vectorToHeading(vectorFromPoint(secondPoint, thirdPoint)),\n );\n\n if (hoveredStartElement && startIsHorizontal === secondIsHorizontal) {\n const positive = startIsHorizontal\n ? compareHeading(startHeading, HEADING_RIGHT)\n : compareHeading(startHeading, HEADING_DOWN);\n newPoints.unshift(\n pointFrom<GlobalPoint>(\n !secondIsHorizontal\n ? thirdPoint[0]\n : startGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING),\n secondIsHorizontal\n ? thirdPoint[1]\n : startGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING),\n ),\n );\n newPoints.unshift(\n pointFrom<GlobalPoint>(\n startIsHorizontal\n ? startGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING)\n : startGlobalPoint[0],\n !startIsHorizontal\n ? startGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING)\n : startGlobalPoint[1],\n ),\n );\n if (!startIsSpecial) {\n startIsSpecial = true;\n for (const segment of nextFixedSegments) {\n if (segment.index > 1) {\n segment.index += 1;\n }\n }\n }\n } else {\n newPoints.unshift(\n pointFrom<GlobalPoint>(\n !secondIsHorizontal ? secondPoint[0] : startGlobalPoint[0],\n secondIsHorizontal ? secondPoint[1] : startGlobalPoint[1],\n ),\n );\n if (startIsSpecial) {\n startIsSpecial = false;\n for (const segment of nextFixedSegments) {\n if (segment.index > 1) {\n segment.index -= 1;\n }\n }\n }\n }\n newPoints.unshift(startGlobalPoint);\n }\n\n // Calculate the moving second to last point connection\n {\n const secondToLastPoint = globalUpdatedPoints.at(\n globalUpdatedPoints.length - (endIsSpecial ? 3 : 2),\n );\n const thirdToLastPoint = globalUpdatedPoints.at(\n globalUpdatedPoints.length - (endIsSpecial ? 4 : 3),\n );\n\n if (!secondToLastPoint || !thirdToLastPoint) {\n throw new Error(\n `Second and third to last points must exist when handling endpoint drag (${endIsSpecial})`,\n );\n }\n\n const endIsHorizontal = headingIsHorizontal(endHeading);\n const secondIsHorizontal = headingForPointIsHorizontal(\n thirdToLastPoint,\n secondToLastPoint,\n );\n if (hoveredEndElement && endIsHorizontal === secondIsHorizontal) {\n const positive = endIsHorizontal\n ? compareHeading(endHeading, HEADING_RIGHT)\n : compareHeading(endHeading, HEADING_DOWN);\n newPoints.push(\n pointFrom<GlobalPoint>(\n !secondIsHorizontal\n ? thirdToLastPoint[0]\n : endGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING),\n secondIsHorizontal\n ? thirdToLastPoint[1]\n : endGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING),\n ),\n );\n newPoints.push(\n pointFrom<GlobalPoint>(\n endIsHorizontal\n ? endGlobalPoint[0] + (positive ? BASE_PADDING : -BASE_PADDING)\n : endGlobalPoint[0],\n !endIsHorizontal\n ? endGlobalPoint[1] + (positive ? BASE_PADDING : -BASE_PADDING)\n : endGlobalPoint[1],\n ),\n );\n if (!endIsSpecial) {\n endIsSpecial = true;\n }\n } else {\n newPoints.push(\n pointFrom<GlobalPoint>(\n !secondIsHorizontal ? secondToLastPoint[0] : endGlobalPoint[0],\n secondIsHorizontal ? secondToLastPoint[1] : endGlobalPoint[1],\n ),\n );\n if (endIsSpecial) {\n endIsSpecial = false;\n }\n }\n }\n\n newPoints.push(endGlobalPoint);\n\n return normalizeArrowElementUpdate(\n newPoints,\n nextFixedSegments\n .map(({ index }) => ({\n index,\n start: newPoints[index - 1],\n end: newPoints[index],\n }))\n .map((segment) => ({\n ...segment,\n start: pointFrom<LocalPoint>(\n segment.start[0] - startGlobalPoint[0],\n segment.start[1] - startGlobalPoint[1],\n ),\n end: pointFrom<LocalPoint>(\n segment.end[0] - startGlobalPoint[0],\n segment.end[1] - startGlobalPoint[1],\n ),\n })),\n startIsSpecial,\n endIsSpecial,\n );\n};\n\nconst MAX_POS = 1e6;\n\n/**\n *\n */\nexport const updateElbowArrowPoints = (\n arrow: Readonly<ExcalidrawElbowArrowElement>,\n elementsMap: NonDeletedSceneElementsMap,\n updates: {\n points?: readonly LocalPoint[];\n fixedSegments?: readonly FixedSegment[] | null;\n startBinding?: FixedPointBinding | null;\n endBinding?: FixedPointBinding | null;\n },\n options?: {\n isDragging?: boolean;\n },\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\n if (arrow.points.length < 2) {\n return { points: updates.points ?? arrow.points };\n }\n\n if (!import.meta.env.PROD) {\n invariant(\n !updates.points || updates.points.length >= 2,\n \"Updated point array length must match the arrow point length, contain \" +\n \"exactly the new start and end points or not be specified at all (i.e. \" +\n \"you can't add new points between start and end manually to elbow arrows)\",\n );\n\n invariant(\n !arrow.fixedSegments ||\n arrow.fixedSegments\n .map((s) => s.start[0] === s.end[0] || s.start[1] === s.end[1])\n .every(Boolean),\n \"Fixed segments must be either horizontal or vertical\",\n );\n\n invariant(\n !updates.fixedSegments ||\n updates.fixedSegments\n .map((s) => s.start[0] === s.end[0] || s.start[1] === s.end[1])\n .every(Boolean),\n \"Updates to fixed segments must be either horizontal or vertical\",\n );\n\n invariant(\n arrow.points\n .slice(1)\n .map(\n (p, i) => p[0] === arrow.points[i][0] || p[1] === arrow.points[i][1],\n ),\n \"Elbow arrow segments must be either horizontal or vertical\",\n );\n\n invariant(\n updates.fixedSegments?.find(\n (segment) =>\n segment.index === 1 &&\n pointsEqual(segment.start, (updates.points ?? arrow.points)[0]),\n ) == null &&\n updates.fixedSegments?.find(\n (segment) =>\n segment.index === (updates.points ?? arrow.points).length - 1 &&\n pointsEqual(\n segment.end,\n (updates.points ?? arrow.points)[\n (updates.points ?? arrow.points).length - 1\n ],\n ),\n ) == null,\n \"The first and last segments cannot be fixed\",\n );\n }\n\n const fixedSegments = updates.fixedSegments ?? arrow.fixedSegments ?? [];\n\n const updatedPoints: readonly LocalPoint[] = updates.points\n ? updates.points && updates.points.length === 2\n ? arrow.points.map((p, idx) =>\n idx === 0\n ? updates.points![0]\n : idx === arrow.points.length - 1\n ? updates.points![1]\n : p,\n )\n : updates.points.slice()\n : arrow.points.slice();\n\n // During all element replacement in the scene, we just need to renormalize\n // the arrow\n // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed\n const {\n startBinding: updatedStartBinding,\n endBinding: updatedEndBinding,\n ...restOfTheUpdates\n } = updates;\n const startBinding =\n typeof updatedStartBinding !== \"undefined\"\n ? updatedStartBinding\n : arrow.startBinding;\n const endBinding =\n typeof updatedEndBinding !== \"undefined\"\n ? updatedEndBinding\n : arrow.endBinding;\n const startElement =\n startBinding &&\n getBindableElementForId(startBinding.elementId, elementsMap);\n const endElement =\n endBinding && getBindableElementForId(endBinding.elementId, elementsMap);\n const areUpdatedPointsValid = validateElbowPoints(updatedPoints);\n\n if (\n (startBinding && !startElement && areUpdatedPointsValid) ||\n (endBinding && !endElement && areUpdatedPointsValid) ||\n (elementsMap.size === 0 && areUpdatedPointsValid) ||\n (Object.keys(restOfTheUpdates).length === 0 &&\n (startElement?.id !== startBinding?.elementId ||\n endElement?.id !== endBinding?.elementId))\n ) {\n return normalizeArrowElementUpdate(\n updatedPoints.map((p) =>\n pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),\n ),\n arrow.fixedSegments,\n arrow.startIsSpecial,\n arrow.endIsSpecial,\n );\n }\n\n const {\n startHeading,\n endHeading,\n startGlobalPoint,\n endGlobalPoint,\n hoveredStartElement,\n hoveredEndElement,\n ...rest\n } = getElbowArrowData(\n {\n x: arrow.x,\n y: arrow.y,\n startBinding,\n endBinding,\n startArrowhead: arrow.startArrowhead,\n endArrowhead: arrow.endArrowhead,\n points: arrow.points,\n },\n elementsMap,\n updatedPoints,\n options,\n );\n\n // 0. During all element replacement in the scene, we just need to renormalize\n // the arrow\n // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed\n if (elementsMap.size === 0 && areUpdatedPointsValid) {\n return normalizeArrowElementUpdate(\n updatedPoints.map((p) =>\n pointFrom<GlobalPoint>(arrow.x + p[0], arrow.y + p[1]),\n ),\n arrow.fixedSegments,\n arrow.startIsSpecial,\n arrow.endIsSpecial,\n );\n }\n\n ////\n // 1. Renormalize the arrow\n ////\n if (\n !updates.points &&\n !updates.fixedSegments &&\n !updates.startBinding &&\n !updates.endBinding\n ) {\n return handleSegmentRenormalization(arrow, elementsMap);\n }\n\n // Short circuit on no-op to avoid huge performance hit\n if (\n updates.startBinding === arrow.startBinding &&\n updates.endBinding === arrow.endBinding &&\n (updates.points ?? []).every((p, i) =>\n pointsEqual(\n p,\n arrow.points[i] ?? pointFrom<LocalPoint>(Infinity, Infinity),\n ),\n ) &&\n areUpdatedPointsValid\n ) {\n return {};\n }\n\n ////\n // 2. Just normal elbow arrow things\n ////\n if (fixedSegments.length === 0) {\n return normalizeArrowElementUpdate(\n getElbowArrowCornerPoints(\n removeElbowArrowShortSegments(\n routeElbowArrow(arrow, {\n startHeading,\n endHeading,\n startGlobalPoint,\n endGlobalPoint,\n hoveredStartElement,\n hoveredEndElement,\n ...rest,\n }) ?? [],\n ),\n ),\n fixedSegments,\n null,\n null,\n );\n }\n\n ////\n // 3. Handle releasing a fixed segment\n if ((arrow.fixedSegments?.length ?? 0) > fixedSegments.length) {\n return handleSegmentRelease(arrow, fixedSegments, elementsMap);\n }\n\n ////\n // 4. Handle manual segment move\n ////\n if (!updates.points) {\n return handleSegmentMove(\n arrow,\n fixedSegments,\n startHeading,\n endHeading,\n hoveredStartElement,\n hoveredEndElement,\n );\n }\n\n ////\n // 5. Handle resize\n ////\n if (updates.points && updates.fixedSegments) {\n return updates;\n }\n\n ////\n // 6. One or more segments are fixed and endpoints are moved\n //\n // The key insights are:\n // - When segments are fixed, the arrow will keep the exact amount of segments\n // - Fixed segments are \"replacements\" for exactly one segment in the old arrow\n ////\n return handleEndpointDrag(\n arrow,\n updatedPoints,\n fixedSegments,\n startHeading,\n endHeading,\n startGlobalPoint,\n endGlobalPoint,\n hoveredStartElement,\n hoveredEndElement,\n );\n};\n\n/**\n * Retrieves data necessary for calculating the elbow arrow path.\n *\n * @param arrow - The arrow object containing its properties.\n * @param elementsMap - A map of elements in the scene.\n * @param nextPoints - The next set of points for the arrow.\n * @param options - Optional parameters for the calculation.\n * @param options.isDragging - Indicates if the arrow is being dragged.\n * @param options.startIsMidPoint - Indicates if the start point is a midpoint.\n * @param options.endIsMidPoint - Indicates if the end point is a midpoint.\n *\n * @returns An object containing various properties needed for elbow arrow calculations:\n * - dynamicAABBs: Dynamically generated axis-aligned bounding boxes.\n * - startDonglePosition: The position of the start dongle.\n * - startGlobalPoint: The global coordinates of the start point.\n * - startHeading: The heading direction from the start point.\n * - endDonglePosition: The position of the end dongle.\n * - endGlobalPoint: The global coordinates of the end point.\n * - endHeading: The heading direction from the end point.\n * - commonBounds: The common bounding box that encompasses both start and end points.\n * - hoveredStartElement: The element being hovered over at the start point.\n * - hoveredEndElement: The element being hovered over at the end point.\n */\nconst getElbowArrowData = (\n arrow: {\n x: number;\n y: number;\n startBinding: FixedPointBinding | null;\n endBinding: FixedPointBinding | null;\n startArrowhead: Arrowhead | null;\n endArrowhead: Arrowhead | null;\n points: readonly LocalPoint[];\n },\n elementsMap: NonDeletedSceneElementsMap,\n nextPoints: readonly LocalPoint[],\n options?: {\n isDragging?: boolean;\n zoom?: AppState[\"zoom\"];\n },\n) => {\n const origStartGlobalPoint: GlobalPoint = pointTranslate<\n LocalPoint,\n GlobalPoint\n >(nextPoints[0], vector(arrow.x, arrow.y));\n const origEndGlobalPoint: GlobalPoint = pointTranslate<\n LocalPoint,\n GlobalPoint\n >(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y));\n\n let hoveredStartElement = null;\n let hoveredEndElement = null;\n if (options?.isDragging) {\n const elements = Array.from(elementsMap.values());\n hoveredStartElement =\n getHoveredElement(\n origStartGlobalPoint,\n elementsMap,\n elements,\n options?.zoom,\n ) || null;\n hoveredEndElement =\n getHoveredElement(\n origEndGlobalPoint,\n elementsMap,\n elements,\n options?.zoom,\n ) || null;\n } else {\n hoveredStartElement = arrow.startBinding\n ? getBindableElementForId(arrow.startBinding.elementId, elementsMap) ||\n null\n : null;\n hoveredEndElement = arrow.endBinding\n ? getBindableElementForId(arrow.endBinding.elementId, elementsMap) || null\n : null;\n }\n\n const startGlobalPoint = getGlobalPoint(\n {\n ...arrow,\n angle: 0,\n type: \"arrow\",\n elbowed: true,\n points: nextPoints,\n } as ExcalidrawElbowArrowElement,\n \"start\",\n arrow.startBinding?.fixedPoint,\n origStartGlobalPoint,\n hoveredStartElement,\n elementsMap,\n options?.isDragging,\n );\n const endGlobalPoint = getGlobalPoint(\n {\n ...arrow,\n angle: 0,\n type: \"arrow\",\n elbowed: true,\n points: nextPoints,\n } as ExcalidrawElbowArrowElement,\n \"end\",\n arrow.endBinding?.fixedPoint,\n origEndGlobalPoint,\n hoveredEndElement,\n elementsMap,\n options?.isDragging,\n );\n const startHeading = getBindPointHeading(\n startGlobalPoint,\n endGlobalPoint,\n hoveredStartElement,\n origStartGlobalPoint,\n elementsMap,\n options?.zoom,\n );\n const endHeading = getBindPointHeading(\n endGlobalPoint,\n startGlobalPoint,\n hoveredEndElement,\n origEndGlobalPoint,\n elementsMap,\n options?.zoom,\n );\n const startPointBounds = [\n startGlobalPoint[0] - 2,\n startGlobalPoint[1] - 2,\n startGlobalPoint[0] + 2,\n startGlobalPoint[1] + 2,\n ] as Bounds;\n const endPointBounds = [\n endGlobalPoint[0] - 2,\n endGlobalPoint[1] - 2,\n endGlobalPoint[0] + 2,\n endGlobalPoint[1] + 2,\n ] as Bounds;\n const startElementBounds = hoveredStartElement\n ? aabbForElement(\n hoveredStartElement,\n elementsMap,\n offsetFromHeading(\n startHeading,\n arrow.startArrowhead\n ? getBindingGap(hoveredStartElement, { elbowed: true }) * 6\n : getBindingGap(hoveredStartElement, { elbowed: true }) * 2,\n 1,\n ),\n )\n : startPointBounds;\n const endElementBounds = hoveredEndElement\n ? aabbForElement(\n hoveredEndElement,\n elementsMap,\n offsetFromHeading(\n endHeading,\n arrow.endArrowhead\n ? getBindingGap(hoveredEndElement, { elbowed: true }) * 6\n : getBindingGap(hoveredEndElement, { elbowed: true }) * 2,\n 1,\n ),\n )\n : endPointBounds;\n const boundsOverlap =\n pointInsideBounds(\n startGlobalPoint,\n hoveredEndElement\n ? aabbForElement(\n hoveredEndElement,\n elementsMap,\n offsetFromHeading(endHeading, BASE_PADDING, BASE_PADDING),\n )\n : endPointBounds,\n ) ||\n pointInsideBounds(\n endGlobalPoint,\n hoveredStartElement\n ? aabbForElement(\n hoveredStartElement,\n elementsMap,\n offsetFromHeading(startHeading, BASE_PADDING, BASE_PADDING),\n )\n : startPointBounds,\n );\n const commonBounds = commonAABB(\n boundsOverlap\n ? [startPointBounds, endPointBounds]\n : [startElementBounds, endElementBounds],\n );\n const dynamicAABBs = generateDynamicAABBs(\n boundsOverlap ? startPointBounds : startElementBounds,\n boundsOverlap ? endPointBounds : endElementBounds,\n commonBounds,\n boundsOverlap\n ? offsetFromHeading(\n startHeading,\n !hoveredStartElement && !hoveredEndElement ? 0 : BASE_PADDING,\n 0,\n )\n : offsetFromHeading(\n startHeading,\n !hoveredStartElement && !hoveredEndElement\n ? 0\n : BASE_PADDING -\n (arrow.startArrowhead\n ? BASE_BINDING_GAP_ELBOW * 6\n : BASE_BINDING_GAP_ELBOW * 2),\n BASE_PADDING,\n ),\n boundsOverlap\n ? offsetFromHeading(\n endHeading,\n !hoveredStartElement && !hoveredEndElement ? 0 : BASE_PADDING,\n 0,\n )\n : offsetFromHeading(\n endHeading,\n !hoveredStartElement && !hoveredEndElement\n ? 0\n : BASE_PADDING -\n (arrow.endArrowhead\n ? BASE_BINDING_GAP_ELBOW * 6\n : BASE_BINDING_GAP_ELBOW * 2),\n BASE_PADDING,\n ),\n boundsOverlap,\n hoveredStartElement && aabbForElement(hoveredStartElement, elementsMap),\n hoveredEndElement && aabbForElement(hoveredEndElement, elementsMap),\n );\n const startDonglePosition = getDonglePosition(\n dynamicAABBs[0],\n startHeading,\n startGlobalPoint,\n );\n const endDonglePosition = getDonglePosition(\n dynamicAABBs[1],\n endHeading,\n endGlobalPoint,\n );\n\n return {\n dynamicAABBs,\n startDonglePosition,\n startGlobalPoint,\n startHeading,\n endDonglePosition,\n endGlobalPoint,\n endHeading,\n commonBounds,\n hoveredStartElement,\n hoveredEndElement,\n boundsOverlap,\n startElementBounds,\n endElementBounds,\n };\n};\n\n/**\n * Generate the elbow arrow segments\n *\n * @param arrow\n * @param elementsMap\n * @param nextPoints\n * @param options\n * @returns\n */\nconst routeElbowArrow = (\n arrow: ElbowArrowState,\n elbowArrowData: ElbowArrowData,\n): GlobalPoint[] | null => {\n const {\n dynamicAABBs,\n startDonglePosition,\n startGlobalPoint,\n startHeading,\n endDonglePosition,\n endGlobalPoint,\n endHeading,\n commonBounds,\n hoveredEndElement,\n } = elbowArrowData;\n\n // Canculate Grid positions\n const grid = calculateGrid(\n dynamicAABBs,\n startDonglePosition ? startDonglePosition : startGlobalPoint,\n startHeading,\n endDonglePosition ? endDonglePosition : endGlobalPoint,\n endHeading,\n commonBounds,\n );\n\n const startDongle =\n startDonglePosition && pointToGridNode(startDonglePosition, grid);\n const endDongle =\n endDonglePosition && pointToGridNode(endDonglePosition, grid);\n\n // Do not allow stepping on the true end or true start points\n const endNode = pointToGridNode(endGlobalPoint, grid);\n if (endNode && hoveredEndElement) {\n endNode.closed = true;\n }\n const startNode = pointToGridNode(startGlobalPoint, grid);\n if (startNode && arrow.startBinding) {\n startNode.closed = true;\n }\n const dongleOverlap =\n startDongle &&\n endDongle &&\n (pointInsideBounds(startDongle.pos, dynamicAABBs[1]) ||\n pointInsideBounds(endDongle.pos, dynamicAABBs[0]));\n\n // Create path to end dongle from start dongle\n const path = astar(\n startDongle ? startDongle : startNode!,\n endDongle ? endDongle : endNode!,\n grid,\n startHeading ? startHeading : HEADING_RIGHT,\n endHeading ? endHeading : HEADING_RIGHT,\n dongleOverlap ? [] : dynamicAABBs,\n );\n\n if (path) {\n const points = path.map((node) => [\n node.pos[0],\n node.pos[1],\n ]) as GlobalPoint[];\n startDongle && points.unshift(startGlobalPoint);\n endDongle && points.push(endGlobalPoint);\n\n return points;\n }\n\n return null;\n};\n\nconst offsetFromHeading = (\n heading: Heading,\n head: number,\n side: number,\n): [number, number, number, number] => {\n switch (heading) {\n case HEADING_UP:\n return [head, side, side, side];\n case HEADING_RIGHT:\n return [side, head, side, side];\n case HEADING_DOWN:\n return [side, side, head, side];\n }\n\n return [side, side, side, head];\n};\n\n/**\n * Routing algorithm based on the A* path search algorithm.\n * @see https://www.geeksforgeeks.org/a-search-algorithm/\n *\n * Binary heap is used to optimize node lookup.\n * See {@link calculateGrid} for the grid calculation details.\n *\n * Additional modifications added due to aesthetic route reasons:\n * 1) Arrow segment direction change is penalized by specific linear constant (bendMultiplier)\n * 2) Arrow segments are not allowed to go \"backwards\", overlapping with the previous segment\n */\nconst astar = (\n start: Node,\n end: Node,\n grid: Grid,\n startHeading: Heading,\n endHeading: Heading,\n aabbs: Bounds[],\n) => {\n const bendMultiplier = m_dist(start.pos, end.pos);\n const open = new BinaryHeap<Node>((node) => node.f);\n\n open.push(start);\n\n while (open.size() > 0) {\n // Grab the lowest f(x) to process next. Heap keeps this sorted for us.\n const current = open.pop();\n\n if (!current || current.closed) {\n // Current is not passable, continue with next element\n continue;\n }\n\n // End case -- result has been found, return the traced path.\n if (current === end) {\n return pathTo(start, current);\n }\n\n // Normal case -- move current from open to closed, process each of its neighbors.\n current.closed = true;\n\n // Find all neighbors for the current node.\n const neighbors = getNeighbors(current.addr, grid);\n\n for (let i = 0; i < 4; i++) {\n const neighbor = neighbors[i];\n\n if (!neighbor || neighbor.closed) {\n // Not a valid node to process, skip to next neighbor.\n continue;\n }\n\n // Intersect\n const neighborHalfPoint = pointScaleFromOrigin(\n neighbor.pos,\n current.pos,\n 0.5,\n );\n if (\n isAnyTrue(\n ...aabbs.map((aabb) => pointInsideBounds(neighborHalfPoint, aabb)),\n )\n ) {\n continue;\n }\n\n // The g score is the shortest distance from start to current node.\n // We need to check if the path we have arrived at this neighbor is the shortest one we have seen yet.\n const neighborHeading = neighborIndexToHeading(i as 0 | 1 | 2 | 3);\n const previousDirection = current.parent\n ? vectorToHeading(vectorFromPoint(current.pos, current.parent.pos))\n : startHeading;\n\n // Do not allow going in reverse\n const reverseHeading = flipHeading(previousDirection);\n const neighborIsReverseRoute =\n compareHeading(reverseHeading, neighborHeading) ||\n (gridAddressesEqual(start.addr, neighbor.addr) &&\n compareHeading(neighborHeading, startHeading)) ||\n (gridAddressesEqual(end.addr, neighbor.addr) &&\n compareHeading(neighborHeading, endHeading));\n if (neighborIsReverseRoute) {\n continue;\n }\n\n const directionChange = previousDirection !== neighborHeading;\n const gScore =\n current.g +\n m_dist(neighbor.pos, current.pos) +\n (directionChange ? Math.pow(bendMultiplier, 3) : 0);\n\n const beenVisited = neighbor.visited;\n\n if (!beenVisited || gScore < neighbor.g) {\n const estBendCount = estimateSegmentCount(\n neighbor,\n end,\n neighborHeading,\n endHeading,\n );\n // Found an optimal (so far) path to this node. Take score for node to see how good it is.\n neighbor.visited = true;\n neighbor.parent = current;\n neighbor.h =\n m_dist(end.pos, neighbor.pos) +\n estBendCount * Math.pow(bendMultiplier, 2);\n neighbor.g = gScore;\n neighbor.f = neighbor.g + neighbor.h;\n if (!beenVisited) {\n // Pushing to heap will put it in proper place based on the 'f' value.\n open.push(neighbor);\n } else {\n // Already seen the node, but since it has been rescored we need to reorder it in the heap\n open.rescoreElement(neighbor);\n }\n }\n }\n }\n\n return null;\n};\n\nconst pathTo = (start: Node, node: Node) => {\n let curr = node;\n const path = [];\n while (curr.parent) {\n path.unshift(curr);\n curr = curr.parent;\n }\n path.unshift(start);\n\n return path;\n};\n\nconst m_dist = (a: GlobalPoint | LocalPoint, b: GlobalPoint | LocalPoint) =>\n Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);\n\n/**\n * Create dynamically resizing, always touching\n * bounding boxes having a minimum extent represented\n * by the given static bounds.\n */\nconst generateDynamicAABBs = (\n a: Bounds,\n b: Bounds,\n common: Bounds,\n startDifference?: [number, number, number, number],\n endDifference?: [number, number, number, number],\n disableSideHack?: boolean,\n startElementBounds?: Bounds | null,\n endElementBounds?: Bounds | null,\n): Bounds[] => {\n const startEl = startElementBounds ?? a;\n const endEl = endElementBounds ?? b;\n const [startUp, startRight, startDown, startLeft] = startDifference ?? [\n 0, 0, 0, 0,\n ];\n const [endUp, endRight, endDown, endLeft] = endDifference ?? [0, 0, 0, 0];\n\n const first = [\n a[0] > b[2]\n ? a[1] > b[3] || a[3] < b[1]\n ? Math.min((startEl[0] + endEl[2]) / 2, a[0] - startLeft)\n : (startEl[0] + endEl[2]) / 2\n : a[0] > b[0]\n ? a[0] - startLeft\n : common[0] - startLeft,\n a[1] > b[3]\n ? a[0] > b[2] || a[2] < b[0]\n ? Math.min((startEl[1] + endEl[3]) / 2, a[1] - startUp)\n : (startEl[1] + endEl[3]) / 2\n : a[1] > b[1]\n ? a[1] - startUp\n : common[1] - startUp,\n a[2] < b[0]\n ? a[1] > b[3] || a[3] < b[1]\n ? Math.max((startEl[2] + endEl[0]) / 2, a[2] + startRight)\n : (startEl[2] + endEl[0]) / 2\n : a[2] < b[2]\n ? a[2] + startRight\n : common[2] + startRight,\n a[3] < b[1]\n ? a[0] > b[2] || a[2] < b[0]\n ? Math.max((startEl[3] + endEl[1]) / 2, a[3] + startDown)\n : (startEl[3] + endEl[1]) / 2\n : a[3] < b[3]\n ? a[3] + startDown\n : common[3] + startDown,\n ] as Bounds;\n const second = [\n b[0] > a[2]\n ? b[1] > a[3] || b[3] < a[1]\n ? Math.min((endEl[0] + startEl[2]) / 2, b[0] - endLeft)\n : (endEl[0] + startEl[2]) / 2\n : b[0] > a[0]\n ? b[0] - endLeft\n : common[0] - endLeft,\n b[1] > a[3]\n ? b[0] > a[2] || b[2] < a[0]\n ? Math.min((endEl[1] + startEl[3]) / 2, b[1] - endUp)\n : (endEl[1] + startEl[3]) / 2\n : b[1] > a[1]\n ? b[1] - endUp\n : common[1] - endUp,\n b[2] < a[0]\n ? b[1] > a[3] || b[3] < a[1]\n ? Math.max((endEl[2] + startEl[0]) / 2, b[2] + endRight)\n : (endEl[2] + startEl[0]) / 2\n : b[2] < a[2]\n ? b[2] + endRight\n : common[2] + endRight,\n b[3] < a[1]\n ? b[0] > a[2] || b[2] < a[0]\n ? Math.max((endEl[3] + startEl[1]) / 2, b[3] + endDown)\n : (endEl[3] + startEl[1]) / 2\n : b[3] < a[3]\n ? b[3] + endDown\n : common[3] + endDown,\n ] as Bounds;\n\n const c = commonAABB([first, second]);\n if (\n !disableSideHack &&\n first[2] - first[0] + second[2] - second[0] > c[2] - c[0] + 0.00000000001 &&\n first[3] - first[1] + second[3] - second[1] > c[3] - c[1] + 0.00000000001\n ) {\n const [endCenterX, endCenterY] = [\n (second[0] + second[2]) / 2,\n (second[1] + second[3]) / 2,\n ];\n if (b[0] > a[2] && a[1] > b[3]) {\n // BOTTOM LEFT\n const cX = first[2] + (second[0] - first[2]) / 2;\n const cY = second[3] + (first[1] - second[3]) / 2;\n\n if (\n vectorCross(\n vector(a[2] - endCenterX, a[1] - endCenterY),\n vector(a[0] - endCenterX, a[3] - endCenterY),\n ) > 0\n ) {\n return [\n [first[0], first[1], cX, first[3]],\n [cX, second[1], second[2], second[3]],\n ];\n }\n\n return [\n [first[0], cY, first[2], first[3]],\n [second[0], second[1], second[2], cY],\n ];\n } else if (a[2] < b[0] && a[3] < b[1]) {\n // TOP LEFT\n const cX = first[2] + (second[0] - first[2]) / 2;\n const cY = first[3] + (second[1] - first[3]) / 2;\n\n if (\n vectorCross(\n vector(a[0] - endCenterX, a[1] - endCenterY),\n vector(a[2] - endCenterX, a[3] - endCenterY),\n ) > 0\n ) {\n return [\n [first[0], first[1], first[2], cY],\n [second[0], cY, second[2], second[3]],\n ];\n }\n\n return [\n [first[0], first[1], cX, first[3]],\n [cX, second[1], second[2], second[3]],\n ];\n } else if (a[0] > b[2] && a[3] < b[1]) {\n // TOP RIGHT\n const cX = second[2] + (first[0] - second[2]) / 2;\n const cY = first[3] + (second[1] - first[3]) / 2;\n\n if (\n vectorCross(\n vector(a[2] - endCenterX, a[1] - endCenterY),\n vector(a[0] - endCenterX, a[3] - endCenterY),\n ) > 0\n ) {\n return [\n [cX, first[1], first[2], first[3]],\n [second[0], second[1], cX, second[3]],\n ];\n }\n\n return [\n [first[0], first[1], first[2], cY],\n [second[0], cY, second[2], second[3]],\n ];\n } else if (a[0] > b[2] && a[1] > b[3]) {\n // BOTTOM RIGHT\n const cX = second[2] + (first[0] - second[2]) / 2;\n const cY = second[3] + (first[1] - second[3]) / 2;\n\n if (\n vectorCross(\n vector(a[0] - endCenterX, a[1] - endCenterY),\n vector(a[2] - endCenterX, a[3] - endCenterY),\n ) > 0\n ) {\n return [\n [cX, first[1], first[2], first[3]],\n [second[0], second[1], cX, second[3]],\n ];\n }\n\n return [\n [first[0], cY, first[2], first[3]],\n [second[0], second[1], second[2], cY],\n ];\n }\n }\n\n return [first, second];\n};\n\n/**\n * Calculates the grid which is used as nodes at\n * the grid line intersections by the A* algorithm.\n *\n * NOTE: This is not a uniform grid. It is built at\n * various intersections of bounding boxes.\n */\nconst calculateGrid = (\n aabbs: Bounds[],\n start: GlobalPoint,\n startHeading: Heading,\n end: GlobalPoint,\n endHeading: Heading,\n common: Bounds,\n): Grid => {\n const horizontal = new Set<number>();\n const vertical = new Set<number>();\n\n if (startHeading === HEADING_LEFT || startHeading === HEADING_RIGHT) {\n vertical.add(start[1]);\n } else {\n horizontal.add(start[0]);\n }\n if (endHeading === HEADING_LEFT || endHeading === HEADING_RIGHT) {\n vertical.add(end[1]);\n } else {\n horizontal.add(end[0]);\n }\n\n aabbs.forEach((aabb) => {\n horizontal.add(aabb[0]);\n horizontal.add(aabb[2]);\n vertical.add(aabb[1]);\n vertical.add(aabb[3]);\n });\n\n horizontal.add(common[0]);\n horizontal.add(common[2]);\n vertical.add(common[1]);\n vertical.add(common[3]);\n\n const _vertical = Array.from(vertical).sort((a, b) => a - b);\n const _horizontal = Array.from(horizontal).sort((a, b) => a - b);\n\n return {\n row: _vertical.length,\n col: _horizontal.length,\n data: _vertical.flatMap((y, row) =>\n _horizontal.map(\n (x, col): Node => ({\n f: 0,\n g: 0,\n h: 0,\n closed: false,\n visited: false,\n parent: null,\n addr: [col, row] as GridAddress,\n pos: [x, y] as GlobalPoint,\n }),\n ),\n ),\n };\n};\n\nconst getDonglePosition = (\n bounds: Bounds,\n heading: Heading,\n p: GlobalPoint,\n): GlobalPoint => {\n switch (heading) {\n case HEADING_UP:\n return pointFrom(p[0], bounds[1]);\n case HEADING_RIGHT:\n return pointFrom(bounds[2], p[1]);\n case HEADING_DOWN:\n return pointFrom(p[0], bounds[3]);\n }\n return pointFrom(bounds[0], p[1]);\n};\n\nconst estimateSegmentCount = (\n start: Node,\n end: Node,\n startHeading: Heading,\n endHeading: Heading,\n) => {\n if (endHeading === HEADING_RIGHT) {\n switch (startHeading) {\n case HEADING_RIGHT: {\n if (start.pos[0] >= end.pos[0]) {\n return 4;\n }\n if (start.pos[1] === end.pos[1]) {\n return 0;\n }\n return 2;\n }\n case HEADING_UP:\n if (start.pos[1] > end.pos[1] && start.pos[0] < end.pos[0]) {\n return 1;\n }\n return 3;\n case HEADING_DOWN:\n if (start.pos[1] < end.pos[1] && start.pos[0] < end.pos[0]) {\n return 1;\n }\n return 3;\n case HEADING_LEFT:\n if (start.pos[1] === end.pos[1]) {\n return 4;\n }\n return 2;\n }\n } else if (endHeading === HEADING_LEFT) {\n switch (startHeading) {\n case HEADING_RIGHT:\n if (start.pos[1] === end.pos[1]) {\n return 4;\n }\n return 2;\n case HEADING_UP:\n if (start.pos[1] > end.pos[1] && start.pos[0] > end.pos[0]) {\n return 1;\n }\n return 3;\n case HEADING_DOWN:\n if (start.pos[1] < end.pos[1] && start.pos[0] > end.pos[0]) {\n return 1;\n }\n return 3;\n case HEADING_LEFT:\n if (start.pos[0] <= end.pos[0]) {\n return 4;\n }\n if (start.pos[1] === end.pos[1]) {\n return 0;\n }\n return 2;\n }\n } else if (endHeading === HEADING_UP) {\n switch (startHeading) {\n case HEADING_RIGHT:\n if (start.pos[1] > end.pos[1] && start.pos[0] < end.pos[0]) {\n return 1;\n }\n return 3;\n case HEADING_UP:\n if (start.pos[1] >= end.pos[1]) {\n return 4;\n }\n if (start.pos[0] === end.pos[0]) {\n return 0;\n }\n return 2;\n case HEADING_DOWN:\n if (start.pos[0] === end.pos[0]) {\n return 4;\n }\n return 2;\n case HEADING_LEFT:\n if (start.pos[1] > end.pos[1] && start.pos[0] > end.pos[0]) {\n return 1;\n }\n return 3;\n }\n } else if (endHeading === HEADING_DOWN) {\n switch (startHeading) {\n case HEADING_RIGHT:\n if (start.pos[1] < end.pos[1] && start.pos[0] < end.pos[0]) {\n return 1;\n }\n return 3;\n case HEADING_UP:\n if (start.pos[0] === end.pos[0]) {\n return 4;\n }\n return 2;\n case HEADING_DOWN:\n if (start.pos[1] <= end.pos[1]) {\n return 4;\n }\n if (start.pos[0] === end.pos[0]) {\n return 0;\n }\n return 2;\n case HEADING_LEFT:\n if (start.pos[1] < end.pos[1] && start.pos[0] > end.pos[0]) {\n return 1;\n }\n return 3;\n }\n }\n return 0;\n};\n\n/**\n * Get neighboring points for a gived grid address\n */\nconst getNeighbors = ([col, row]: [number, number], grid: Grid) =>\n [\n gridNodeFromAddr([col, row - 1], grid),\n gridNodeFromAddr([col + 1, row], grid),\n gridNodeFromAddr([col, row + 1], grid),\n gridNodeFromAddr([col - 1, row], grid),\n ] as [Node | null, Node | null, Node | null, Node | null];\n\nconst gridNodeFromAddr = (\n [col, row]: [col: number, row: number],\n grid: Grid,\n): Node | null => {\n if (col < 0 || col >= grid.col || row < 0 || row >= grid.row) {\n return null;\n }\n\n return grid.data[row * grid.col + col] ?? null;\n};\n\n/**\n * Get node for global point on canvas (if exists)\n */\nconst pointToGridNode = (point: GlobalPoint, grid: Grid): Node | null => {\n for (let col = 0; col < grid.col; col++) {\n for (let row = 0; row < grid.row; row++) {\n const candidate = gridNodeFromAddr([col, row], grid);\n if (\n candidate &&\n point[0] === candidate.pos[0] &&\n point[1] === candidate.pos[1]\n ) {\n return candidate;\n }\n }\n }\n\n return null;\n};\n\nconst commonAABB = (aabbs: Bounds[]): Bounds => [\n Math.min(...aabbs.map((aabb) => aabb[0])),\n Math.min(...aabbs.map((aabb) => aabb[1])),\n Math.max(...aabbs.map((aabb) => aabb[2])),\n Math.max(...aabbs.map((aabb) => aabb[3])),\n];\n\n/// #region Utils\n\nconst getBindableElementForId = (\n id: string,\n elementsMap: ElementsMap,\n): ExcalidrawBindableElement | null => {\n const element = elementsMap.get(id);\n if (element && isBindableElement(element)) {\n return element;\n }\n\n return null;\n};\n\nconst normalizeArrowElementUpdate = (\n global: GlobalPoint[],\n nextFixedSegments: readonly FixedSegment[] | null,\n startIsSpecial?: ExcalidrawElbowArrowElement[\"startIsSpecial\"],\n endIsSpecial?: ExcalidrawElbowArrowElement[\"startIsSpecial\"],\n): ElementUpdate<ExcalidrawElbowArrowElement> => {\n const offsetX = global[0][0];\n const offsetY = global[0][1];\n let points = global.map((p) =>\n pointTranslate<GlobalPoint, LocalPoint>(\n p,\n vectorScale(vectorFromPoint(global[0]), -1),\n ),\n );\n\n // NOTE (mtolmacs): This is a temporary check to see if the normalization\n // creates an overly large arrow. This should be removed once we have an answer.\n if (\n offsetX < -MAX_POS ||\n offsetX > MAX_POS ||\n offsetY < -MAX_POS ||\n offsetY > MAX_POS ||\n offsetX + points[points.length - 1][0] < -MAX_POS ||\n offsetY + points[points.length - 1][0] > MAX_POS ||\n offsetX + points[points.length - 1][1] < -MAX_POS ||\n offsetY + points[points.length - 1][1] > MAX_POS\n ) {\n console.error(\n \"Elbow arrow normalization is outside reasonable bounds (> 1e6)\",\n {\n x: offsetX,\n y: offsetY,\n points,\n ...getSizeFromPoints(points),\n },\n );\n }\n\n points = points.map(([x, y]) =>\n pointFrom<LocalPoint>(clamp(x, -1e6, 1e6), clamp(y, -1e6, 1e6)),\n );\n\n return {\n points,\n x: clamp(offsetX, -1e6, 1e6),\n y: clamp(offsetY, -1e6, 1e6),\n fixedSegments:\n (nextFixedSegments?.length ?? 0) > 0 ? nextFixedSegments : null,\n ...getSizeFromPoints(points),\n startIsSpecial,\n endIsSpecial,\n };\n};\n\nconst getElbowArrowCornerPoints = (points: GlobalPoint[]): GlobalPoint[] => {\n if (points.length > 1) {\n let previousHorizontal =\n Math.abs(points[0][1] - points[1][1]) <\n Math.abs(points[0][0] - points[1][0]);\n\n return points.filter((p, idx) => {\n // The very first and last points are always kept\n if (idx === 0 || idx === points.length - 1) {\n return true;\n }\n\n const next = points[idx + 1];\n const nextHorizontal =\n Math.abs(p[1] - next[1]) < Math.abs(p[0] - next[0]);\n if (previousHorizontal === nextHorizontal) {\n previousHorizontal = nextHorizontal;\n return false;\n }\n\n previousHorizontal = nextHorizontal;\n return true;\n });\n }\n\n return points;\n};\n\nconst removeElbowArrowShortSegments = (\n points: GlobalPoint[],\n): GlobalPoint[] => {\n if (points.length >= 4) {\n return points.filter((p, idx) => {\n if (idx === 0 || idx === points.length - 1) {\n return true;\n }\n\n const prev = points[idx - 1];\n const prevDist = pointDistance(prev, p);\n return prevDist > DEDUP_TRESHOLD;\n });\n }\n\n return points;\n};\n\nconst neighborIndexToHeading = (idx: number): Heading => {\n switch (idx) {\n case 0:\n return HEADING_UP;\n case 1:\n return HEADING_RIGHT;\n case 2:\n return HEADING_DOWN;\n }\n return HEADING_LEFT;\n};\n\nconst getGlobalPoint = (\n arrow: ExcalidrawElbowArrowElement,\n startOrEnd: \"start\" | \"end\",\n fixedPointRatio: [number, number] | undefined | null,\n initialPoint: GlobalPoint,\n element?: ExcalidrawBindableElement | null,\n elementsMap?: ElementsMap,\n isDragging?: boolean,\n): GlobalPoint => {\n if (isDragging) {\n if (element && elementsMap) {\n return bindPointToSnapToElementOutline(\n arrow,\n element,\n startOrEnd,\n elementsMap,\n );\n }\n\n return initialPoint;\n }\n\n if (element) {\n return getGlobalFixedPointForBindableElement(\n fixedPointRatio || [0, 0],\n element,\n elementsMap ?? arrayToMap([element]),\n );\n }\n\n return initialPoint;\n};\n\nconst getBindPointHeading = (\n p: GlobalPoint,\n otherPoint: GlobalPoint,\n hoveredElement: ExcalidrawBindableElement | null | undefined,\n origPoint: GlobalPoint,\n elementsMap: ElementsMap,\n zoom?: AppState[\"zoom\"],\n): Heading =>\n getHeadingForElbowArrowSnap(\n p,\n otherPoint,\n hoveredElement,\n hoveredElement &&\n aabbForElement(\n hoveredElement,\n elementsMap,\n Array(4).fill(distanceToElement(hoveredElement, elementsMap, p)) as [\n number,\n number,\n number,\n number,\n ],\n ),\n origPoint,\n elementsMap,\n zoom,\n );\n\nconst getHoveredElement = (\n origPoint: GlobalPoint,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n zoom?: AppState[\"zoom\"],\n) => {\n return getHoveredElementForBinding(\n origPoint,\n elements,\n elementsMap,\n (element) => maxBindingDistance_simple(zoom),\n );\n};\n\nconst gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean =>\n a[0] === b[0] && a[1] === b[1];\n\nexport const validateElbowPoints = <P extends GlobalPoint | LocalPoint>(\n points: readonly P[],\n tolerance: number = DEDUP_TRESHOLD,\n) =>\n points\n .slice(1)\n .map(\n (p, i) =>\n Math.abs(p[0] - points[i][0]) < tolerance ||\n Math.abs(p[1] - points[i][1]) < tolerance,\n )\n .every(Boolean);\n", "import {\n getSizeFromPoints,\n randomInteger,\n getUpdatedTimestamp,\n} from \"@excalidraw/common\";\n\nimport type { Radians } from \"@excalidraw/math\";\n\nimport type { Mutable } from \"@excalidraw/common/utility-types\";\n\nimport { ShapeCache } from \"./shape\";\n\nimport { updateElbowArrowPoints } from \"./elbowArrow\";\n\nimport { isElbowArrow } from \"./typeChecks\";\n\nimport type {\n ElementsMap,\n ExcalidrawElbowArrowElement,\n ExcalidrawElement,\n NonDeletedSceneElementsMap,\n} from \"./types\";\n\nexport type ElementUpdate<TElement extends ExcalidrawElement> = Omit<\n Partial<TElement>,\n \"id\" | \"updated\"\n>;\n\n/**\n * This function tracks updates of text elements for the purposes for collaboration.\n * The version is used to compare updates when more than one user is working in\n * the same drawing.\n *\n * WARNING: this won't trigger the component to update, so if you need to trigger component update,\n * use `scene.mutateElement` or `ExcalidrawImperativeAPI.mutateElement` instead.\n */\nexport const mutateElement = <TElement extends Mutable<ExcalidrawElement>>(\n element: TElement,\n elementsMap: ElementsMap,\n updates: ElementUpdate<TElement>,\n options?: {\n isDragging?: boolean;\n },\n) => {\n let didChange = false;\n\n // casting to any because can't use `in` operator\n // (see https://github.com/microsoft/TypeScript/issues/21732)\n const { points, fixedSegments, fileId } = updates as any;\n\n if (\n isElbowArrow(element) &&\n (Object.keys(updates).length === 0 || // normalization case\n typeof points !== \"undefined\" || // repositioning\n typeof fixedSegments !== \"undefined\") // segment fixing\n ) {\n updates = {\n ...updates,\n angle: 0 as Radians,\n ...updateElbowArrowPoints(\n {\n ...element,\n x: updates.x || element.x,\n y: updates.y || element.y,\n },\n elementsMap as NonDeletedSceneElementsMap,\n updates as ElementUpdate<ExcalidrawElbowArrowElement>,\n options,\n ),\n };\n } else if (typeof points !== \"undefined\") {\n updates = { ...getSizeFromPoints(points), ...updates };\n }\n\n for (const key in updates) {\n const value = (updates as any)[key];\n if (typeof value !== \"undefined\") {\n if (\n (element as any)[key] === value &&\n // if object, always update because its attrs could have changed\n // (except for specific keys we handle below)\n (typeof value !== \"object\" ||\n value === null ||\n key === \"groupIds\" ||\n key === \"scale\")\n ) {\n continue;\n }\n\n if (key === \"scale\") {\n const prevScale = (element as any)[key];\n const nextScale = value;\n if (prevScale[0] === nextScale[0] && prevScale[1] === nextScale[1]) {\n continue;\n }\n } else if (key === \"points\") {\n const prevPoints = (element as any)[key];\n const nextPoints = value;\n if (prevPoints.length === nextPoints.length) {\n let didChangePoints = false;\n let index = prevPoints.length;\n while (--index) {\n const prevPoint = prevPoints[index];\n const nextPoint = nextPoints[index];\n if (\n prevPoint[0] !== nextPoint[0] ||\n prevPoint[1] !== nextPoint[1]\n ) {\n didChangePoints = true;\n break;\n }\n }\n if (!didChangePoints) {\n continue;\n }\n }\n }\n\n (element as any)[key] = value;\n didChange = true;\n }\n }\n\n if (!didChange) {\n return element;\n }\n\n if (\n typeof updates.height !== \"undefined\" ||\n typeof updates.width !== \"undefined\" ||\n typeof fileId != \"undefined\" ||\n typeof points !== \"undefined\"\n ) {\n ShapeCache.delete(element);\n }\n\n element.version = updates.version ?? element.version + 1;\n element.versionNonce = updates.versionNonce ?? randomInteger();\n element.updated = getUpdatedTimestamp();\n\n return element;\n};\n\nexport const newElementWith = <TElement extends ExcalidrawElement>(\n element: TElement,\n updates: ElementUpdate<TElement>,\n /** pass `true` to always regenerate */\n force = false,\n): TElement => {\n let didChange = false;\n for (const key in updates) {\n const value = (updates as any)[key];\n if (typeof value !== \"undefined\") {\n if (\n (element as any)[key] === value &&\n // if object, always update because its attrs could have changed\n (typeof value !== \"object\" || value === null)\n ) {\n continue;\n }\n didChange = true;\n }\n }\n\n if (!didChange && !force) {\n return element;\n }\n\n return {\n ...element,\n ...updates,\n version: updates.version ?? element.version + 1,\n versionNonce: updates.versionNonce ?? randomInteger(),\n updated: getUpdatedTimestamp(),\n };\n};\n\n/**\n * Mutates element, bumping `version`, `versionNonce`, and `updated`.\n *\n * NOTE: does not trigger re-render.\n */\nexport const bumpVersion = <T extends Mutable<ExcalidrawElement>>(\n element: T,\n version?: ExcalidrawElement[\"version\"],\n) => {\n element.version = (version ?? element.version) + 1;\n element.versionNonce = randomInteger();\n element.updated = getUpdatedTimestamp();\n return element;\n};\n", "import {\n KEYS,\n arrayToMap,\n getFeatureFlag,\n invariant,\n isTransparent,\n} from \"@excalidraw/common\";\n\nimport {\n PRECISION,\n clamp,\n lineSegment,\n pointDistance,\n pointDistanceSq,\n pointFrom,\n pointFromVector,\n pointRotateRads,\n vectorFromPoint,\n vectorNormalize,\n vectorScale,\n type GlobalPoint,\n} from \"@excalidraw/math\";\n\nimport type { LineSegment, LocalPoint, Radians } from \"@excalidraw/math\";\nimport type { AppState } from \"@excalidraw/excalidraw/types\";\nimport type { MapEntry, Mutable } from \"@excalidraw/common/utility-types\";\nimport type { Bounds } from \"@excalidraw/common\";\n\nimport {\n doBoundsIntersect,\n getCenterForBounds,\n getElementBounds,\n} from \"./bounds\";\nimport {\n getAllHoveredElementAtPoint,\n getHoveredElementForBinding,\n intersectElementWithLineSegment,\n isBindableElementInsideOtherBindable,\n isPointInElement,\n} from \"./collision\";\nimport { distanceToElement } from \"./distance\";\nimport {\n headingForPointFromElement,\n headingIsHorizontal,\n vectorToHeading,\n type Heading,\n} from \"./heading\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport { mutateElement } from \"./mutateElement\";\nimport { getBoundTextElement, handleBindTextResize } from \"./textElement\";\nimport {\n isArrowElement,\n isBindableElement,\n isBoundToContainer,\n isElbowArrow,\n isRectangularElement,\n isRectanguloidElement,\n isTextElement,\n} from \"./typeChecks\";\n\nimport { aabbForElement, elementCenterPoint } from \"./bounds\";\nimport { updateElbowArrowPoints } from \"./elbowArrow\";\nimport {\n deconstructDiamondElement,\n deconstructRectanguloidElement,\n projectFixedPointOntoDiagonal,\n} from \"./utils\";\n\nimport type { Scene } from \"./Scene\";\n\nimport type { ElementUpdate } from \"./mutateElement\";\nimport type {\n BindMode,\n ElementsMap,\n ExcalidrawArrowElement,\n ExcalidrawBindableElement,\n ExcalidrawElbowArrowElement,\n ExcalidrawElement,\n ExcalidrawRectanguloidElement,\n ExcalidrawTextElement,\n FixedPoint,\n FixedPointBinding,\n NonDeleted,\n NonDeletedExcalidrawElement,\n NonDeletedSceneElementsMap,\n Ordered,\n PointsPositionUpdates,\n} from \"./types\";\n\nexport type BindingStrategy =\n // Create a new binding with this mode\n | {\n mode: BindMode;\n element: NonDeleted<ExcalidrawBindableElement>;\n focusPoint: GlobalPoint;\n }\n // Break the binding\n | {\n mode: null;\n element?: undefined;\n focusPoint?: undefined;\n }\n // Keep the existing binding\n | {\n mode: undefined;\n element?: undefined;\n focusPoint?: undefined;\n };\n\n/**\n * gaps exclude element strokeWidth\n *\n * IMPORTANT: currently must be > 0 (this also applies to the computed gap)\n */\nexport const BASE_BINDING_GAP = 10;\nexport const BASE_BINDING_GAP_ELBOW = 5;\n\nexport const getBindingGap = (\n bindTarget: ExcalidrawBindableElement,\n opts: Pick<ExcalidrawArrowElement, \"elbowed\">,\n): number => {\n return (\n (opts.elbowed ? BASE_BINDING_GAP_ELBOW : BASE_BINDING_GAP) +\n bindTarget.strokeWidth / 2\n );\n};\n\nexport const maxBindingDistance_simple = (zoom?: AppState[\"zoom\"]): number => {\n const BASE_BINDING_DISTANCE = Math.max(BASE_BINDING_GAP, 15);\n const zoomValue = zoom?.value && zoom.value < 1 ? zoom.value : 1;\n return clamp(\n // reducing zoom impact so that the diff between binding distance and\n // binding gap is kept to minimum when possible\n BASE_BINDING_DISTANCE / (zoomValue * 1.5),\n BASE_BINDING_DISTANCE,\n BASE_BINDING_DISTANCE * 2,\n );\n};\n\nexport const shouldEnableBindingForPointerEvent = (\n event: React.PointerEvent<HTMLElement>,\n) => {\n return !event[KEYS.CTRL_OR_CMD];\n};\n\nexport const isBindingEnabled = (appState: AppState): boolean => {\n return appState.isBindingEnabled;\n};\n\nexport const bindOrUnbindBindingElement = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n draggingPoints: PointsPositionUpdates,\n scenePointerX: number,\n scenePointerY: number,\n scene: Scene,\n appState: AppState,\n opts?: {\n newArrow?: boolean;\n altKey?: boolean;\n angleLocked?: boolean;\n initialBinding?: boolean;\n },\n) => {\n const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints(\n arrow,\n draggingPoints,\n scenePointerX,\n scenePointerY,\n scene.getNonDeletedElementsMap(),\n scene.getNonDeletedElements(),\n appState,\n {\n ...opts,\n finalize: true,\n },\n );\n\n bindOrUnbindBindingElementEdge(arrow, start, \"start\", scene);\n bindOrUnbindBindingElementEdge(arrow, end, \"end\", scene);\n if (start.focusPoint || end.focusPoint) {\n // If the strategy dictates a focus point override, then\n // update the arrow points to point to the focus point.\n const updates: PointsPositionUpdates = new Map();\n\n if (start.focusPoint) {\n updates.set(0, {\n point:\n updateBoundPoint(\n arrow,\n \"startBinding\",\n arrow.startBinding,\n start.element,\n scene.getNonDeletedElementsMap(),\n ) || arrow.points[0],\n });\n }\n\n if (end.focusPoint) {\n updates.set(arrow.points.length - 1, {\n point:\n updateBoundPoint(\n arrow,\n \"endBinding\",\n arrow.endBinding,\n end.element,\n scene.getNonDeletedElementsMap(),\n ) || arrow.points[arrow.points.length - 1],\n });\n }\n\n LinearElementEditor.movePoints(arrow, scene, updates);\n }\n\n return { start, end };\n};\n\nconst bindOrUnbindBindingElementEdge = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n { mode, element, focusPoint }: BindingStrategy,\n startOrEnd: \"start\" | \"end\",\n scene: Scene,\n): void => {\n if (mode === null) {\n // null means break the binding\n unbindBindingElement(arrow, startOrEnd, scene);\n } else if (mode !== undefined) {\n bindBindingElement(arrow, element, mode, startOrEnd, scene, focusPoint);\n }\n};\n\nconst bindingStrategyForElbowArrowEndpointDragging = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n draggingPoints: PointsPositionUpdates,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n zoom?: AppState[\"zoom\"],\n): {\n start: BindingStrategy;\n end: BindingStrategy;\n} => {\n invariant(draggingPoints.size === 1, \"Bound elbow arrows cannot be moved\");\n\n const update = draggingPoints.entries().next().value;\n\n invariant(\n update,\n \"There should be a position update for dragging an elbow arrow endpoint\",\n );\n\n const [pointIdx, { point }] = update;\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\n arrow,\n point,\n elementsMap,\n );\n const hit = getHoveredElementForBinding(\n globalPoint,\n elements,\n elementsMap,\n (element) => maxBindingDistance_simple(zoom),\n );\n\n const current = hit\n ? {\n element: hit,\n mode: \"orbit\" as const,\n focusPoint: LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrow,\n pointIdx,\n elementsMap,\n ),\n }\n : {\n mode: null,\n };\n const other = { mode: undefined };\n\n return pointIdx === 0\n ? { start: current, end: other }\n : { start: other, end: current };\n};\n\nconst bindingStrategyForNewSimpleArrowEndpointDragging = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n draggingPoints: PointsPositionUpdates,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n startDragged: boolean,\n endDragged: boolean,\n startIdx: number,\n endIdx: number,\n appState: AppState,\n globalBindMode?: AppState[\"bindMode\"],\n shiftKey?: boolean,\n): {\n start: BindingStrategy;\n end: BindingStrategy;\n} => {\n let start: BindingStrategy = { mode: undefined };\n let end: BindingStrategy = { mode: undefined };\n\n const isMultiPoint = arrow.points.length > 2;\n const point = LinearElementEditor.getPointGlobalCoordinates(\n arrow,\n draggingPoints.get(startDragged ? startIdx : endIdx)!.point,\n elementsMap,\n );\n const hit = getHoveredElementForBinding(point, elements, elementsMap);\n\n // With new arrows this handles the binding at arrow creation\n if (startDragged) {\n if (hit) {\n start = {\n element: hit,\n mode: \"inside\",\n focusPoint: point,\n };\n } else {\n start = { mode: null };\n }\n\n return { start, end };\n }\n\n // With new arrows it represents the continuous dragging of the end point\n if (endDragged) {\n const origin = appState?.selectedLinearElement?.initialState.origin;\n\n // Inside -> inside binding\n if (hit && arrow.startBinding?.elementId === hit.id) {\n const center = pointFrom<GlobalPoint>(\n hit.x + hit.width / 2,\n hit.y + hit.height / 2,\n );\n\n return {\n start: isMultiPoint\n ? { mode: undefined }\n : {\n mode: \"inside\",\n element: hit,\n focusPoint: origin ?? center,\n },\n end: isMultiPoint\n ? { mode: \"orbit\", element: hit, focusPoint: point }\n : { mode: \"inside\", element: hit, focusPoint: point },\n };\n }\n\n // Check and handle nested shapes\n if (hit && arrow.startBinding) {\n const startBinding = arrow.startBinding;\n const allHits = getAllHoveredElementAtPoint(point, elements, elementsMap);\n\n if (allHits.find((el) => el.id === startBinding.elementId)) {\n const otherElement = elementsMap.get(\n arrow.startBinding.elementId,\n ) as ExcalidrawBindableElement;\n\n invariant(otherElement, \"Other element must be in the elements map\");\n\n return {\n start: isMultiPoint\n ? { mode: undefined }\n : {\n mode: otherElement.id !== hit.id ? \"orbit\" : \"inside\",\n element: otherElement,\n focusPoint: origin ?? pointFrom<GlobalPoint>(arrow.x, arrow.y),\n },\n end: {\n mode: \"orbit\",\n element: hit,\n focusPoint: point,\n },\n };\n }\n }\n\n // Inside -> outside binding\n if (arrow.startBinding && arrow.startBinding.elementId !== hit?.id) {\n const otherElement = elementsMap.get(\n arrow.startBinding.elementId,\n ) as ExcalidrawBindableElement;\n invariant(otherElement, \"Other element must be in the elements map\");\n\n const otherIsInsideBinding =\n !!appState.selectedLinearElement?.initialState.arrowStartIsInside;\n const other: BindingStrategy = {\n mode: otherIsInsideBinding ? \"inside\" : \"orbit\",\n element: otherElement,\n focusPoint: shiftKey\n ? elementCenterPoint(otherElement, elementsMap)\n : origin ?? pointFrom<GlobalPoint>(arrow.x, arrow.y),\n };\n\n // We are hovering another element with the end point\n const isNested =\n hit &&\n isBindableElementInsideOtherBindable(otherElement, hit, elementsMap);\n let current: BindingStrategy;\n if (hit) {\n const isInsideBinding =\n globalBindMode === \"inside\" || globalBindMode === \"skip\";\n current = {\n mode: isInsideBinding && !isNested ? \"inside\" : \"orbit\",\n element: hit,\n focusPoint: isInsideBinding || isNested ? point : point,\n };\n } else {\n current = { mode: null };\n }\n\n return {\n start: isMultiPoint ? { mode: undefined } : other,\n end: current,\n };\n }\n\n // No start binding\n if (!arrow.startBinding) {\n if (hit) {\n const isInsideBinding =\n globalBindMode === \"inside\" || globalBindMode === \"skip\";\n\n end = {\n mode: isInsideBinding ? \"inside\" : \"orbit\",\n element: hit,\n focusPoint: point,\n };\n } else {\n end = { mode: null };\n }\n\n return { start, end };\n }\n }\n\n invariant(false, \"New arrow creation should not reach here\");\n};\n\nconst bindingStrategyForSimpleArrowEndpointDragging_complex = (\n point: GlobalPoint,\n currentBinding: FixedPointBinding | null,\n oppositeBinding: FixedPointBinding | null,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n globalBindMode: AppState[\"bindMode\"],\n arrow: NonDeleted<ExcalidrawArrowElement>,\n finalize?: boolean,\n): { current: BindingStrategy; other: BindingStrategy } => {\n let current: BindingStrategy = { mode: undefined };\n let other: BindingStrategy = { mode: undefined };\n\n const isMultiPoint = arrow.points.length > 2;\n const hit = getHoveredElementForBinding(point, elements, elementsMap);\n const isOverlapping = oppositeBinding\n ? getAllHoveredElementAtPoint(point, elements, elementsMap).some(\n (el) => el.id === oppositeBinding.elementId,\n )\n : false;\n const oppositeElement = oppositeBinding\n ? (elementsMap.get(oppositeBinding.elementId) as ExcalidrawBindableElement)\n : null;\n const otherIsTransparent =\n isOverlapping && oppositeElement\n ? isTransparent(oppositeElement.backgroundColor)\n : false;\n const isNested =\n hit &&\n oppositeElement &&\n isBindableElementInsideOtherBindable(oppositeElement, hit, elementsMap);\n\n // If the global bind mode is in free binding mode, just bind\n // where the pointer is and keep the other end intact\n if (globalBindMode === \"inside\" || globalBindMode === \"skip\") {\n current = hit\n ? {\n element:\n !isOverlapping || !oppositeElement || otherIsTransparent\n ? hit\n : oppositeElement,\n focusPoint: point,\n mode: \"inside\",\n }\n : { mode: null };\n other =\n finalize && hit && hit.id === oppositeBinding?.elementId\n ? { mode: null }\n : other;\n\n return { current, other };\n }\n\n // Dragged point is outside of any bindable element\n // so we break any existing binding\n if (!hit) {\n return { current: { mode: null }, other };\n }\n\n // Already inside binding over the same hit element should remain inside bound\n if (\n hit.id === currentBinding?.elementId &&\n currentBinding.mode === \"inside\"\n ) {\n return {\n current: { mode: \"inside\", focusPoint: point, element: hit },\n other,\n };\n }\n\n // The dragged point is inside the hovered bindable element\n if (oppositeBinding) {\n // The opposite binding is on the same element\n if (oppositeBinding.elementId === hit.id) {\n // The opposite binding is on the binding gap of the same element\n if (oppositeBinding.mode === \"orbit\") {\n current = { element: hit, mode: \"orbit\", focusPoint: point };\n other = { mode: finalize ? null : undefined };\n\n return { current, other: isMultiPoint ? { mode: undefined } : other };\n }\n // The opposite binding is inside the same element\n // eslint-disable-next-line no-else-return\n else {\n current = { element: hit, mode: \"inside\", focusPoint: point };\n\n return { current, other: isMultiPoint ? { mode: undefined } : other };\n }\n }\n // The opposite binding is on a different element (or nested)\n // eslint-disable-next-line no-else-return\n else {\n // Handle the nested element case\n if (isOverlapping && oppositeElement && !otherIsTransparent) {\n current = {\n element: oppositeElement,\n mode: \"inside\",\n focusPoint: point,\n };\n } else {\n current = {\n element: hit,\n mode: \"orbit\",\n focusPoint: isNested ? point : point,\n };\n }\n\n return { current, other: isMultiPoint ? { mode: undefined } : other };\n }\n }\n // The opposite binding is on a different element or no binding\n else {\n current = {\n element: hit,\n mode: \"orbit\",\n focusPoint: point,\n };\n }\n\n // Must return as only one endpoint is dragged, therefore\n // the end binding strategy might accidentally gets overriden\n return { current, other: isMultiPoint ? { mode: undefined } : other };\n};\n\nexport const getBindingStrategyForDraggingBindingElementEndpoints = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n draggingPoints: PointsPositionUpdates,\n screenPointerX: number,\n screenPointerY: number,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n appState: AppState,\n opts?: {\n newArrow?: boolean;\n angleLocked?: boolean;\n altKey?: boolean;\n finalize?: boolean;\n initialBinding?: boolean;\n zoom?: AppState[\"zoom\"];\n },\n): { start: BindingStrategy; end: BindingStrategy } => {\n if (getFeatureFlag(\"COMPLEX_BINDINGS\")) {\n return getBindingStrategyForDraggingBindingElementEndpoints_complex(\n arrow,\n draggingPoints,\n elementsMap,\n elements,\n appState,\n opts,\n );\n }\n\n return getBindingStrategyForDraggingBindingElementEndpoints_simple(\n arrow,\n draggingPoints,\n screenPointerX,\n screenPointerY,\n elementsMap,\n elements,\n appState,\n opts,\n );\n};\n\nconst getBindingStrategyForDraggingBindingElementEndpoints_simple = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n draggingPoints: PointsPositionUpdates,\n scenePointerX: number,\n scenePointerY: number,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n appState: AppState,\n opts?: {\n newArrow?: boolean;\n angleLocked?: boolean;\n altKey?: boolean;\n finalize?: boolean;\n initialBinding?: boolean;\n zoom?: AppState[\"zoom\"];\n },\n): { start: BindingStrategy; end: BindingStrategy } => {\n const startIdx = 0;\n const endIdx = arrow.points.length - 1;\n const startDragged = draggingPoints.has(startIdx);\n const endDragged = draggingPoints.has(endIdx);\n\n let start: BindingStrategy = { mode: undefined };\n let end: BindingStrategy = { mode: undefined };\n\n invariant(\n arrow.points.length > 1,\n \"Do not attempt to bind linear elements with a single point\",\n );\n\n // If none of the ends are dragged, we don't change anything\n if (!startDragged && !endDragged) {\n return { start, end };\n }\n\n // If both ends are dragged, we don't bind to anything\n // and break existing bindings\n if (startDragged && endDragged) {\n return { start: { mode: null }, end: { mode: null } };\n }\n\n // If binding is disabled and an endpoint is dragged,\n // we actively break the end binding\n if (!isBindingEnabled(appState)) {\n start = startDragged ? { mode: null } : start;\n end = endDragged ? { mode: null } : end;\n\n return { start, end };\n }\n\n // Handle simpler elbow arrow binding\n if (isElbowArrow(arrow)) {\n return bindingStrategyForElbowArrowEndpointDragging(\n arrow,\n draggingPoints,\n elementsMap,\n elements,\n opts?.zoom,\n );\n }\n\n const otherBinding = startDragged ? arrow.endBinding : arrow.startBinding;\n const localPoint = draggingPoints.get(\n startDragged ? startIdx : endIdx,\n )?.point;\n invariant(\n localPoint,\n `Local point must be defined for ${\n startDragged ? \"start\" : \"end\"\n } dragging`,\n );\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\n arrow,\n localPoint,\n elementsMap,\n );\n const hit = getHoveredElementForBinding(\n globalPoint,\n elements,\n elementsMap,\n (e) => maxBindingDistance_simple(appState.zoom),\n );\n const pointInElement =\n hit &&\n (opts?.angleLocked\n ? isPointInElement(\n pointFrom<GlobalPoint>(scenePointerX, scenePointerY),\n hit,\n elementsMap,\n )\n : isPointInElement(globalPoint, hit, elementsMap));\n const otherBindableElement = otherBinding\n ? (elementsMap.get(\n otherBinding.elementId,\n ) as NonDeleted<ExcalidrawBindableElement>)\n : undefined;\n const otherFocusPoint =\n otherBinding &&\n otherBindableElement &&\n getGlobalFixedPointForBindableElement(\n otherBinding.fixedPoint,\n otherBindableElement,\n elementsMap,\n );\n const otherFocusPointIsInElement =\n otherBindableElement &&\n otherFocusPoint &&\n isPointInElement(otherFocusPoint, otherBindableElement, elementsMap);\n\n // Handle outside-outside binding to the same element\n if (otherBinding && otherBinding.elementId === hit?.id) {\n invariant(\n !opts?.newArrow || appState.selectedLinearElement?.initialState.origin,\n \"appState.selectedLinearElement.initialState.origin must be defined for new arrows\",\n );\n\n return {\n start: {\n mode: \"inside\",\n element: hit,\n focusPoint: startDragged\n ? globalPoint\n : // NOTE: Can only affect the start point because new arrows always drag the end point\n opts?.newArrow\n ? appState.selectedLinearElement!.initialState.origin!\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrow,\n 0,\n elementsMap,\n ), // startFixedPoint,\n },\n end: {\n mode: \"inside\",\n element: hit,\n focusPoint: endDragged\n ? globalPoint\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrow,\n -1,\n elementsMap,\n ), // endFixedPoint\n },\n };\n }\n\n // Handle special alt key case to inside bind no matter what\n if (opts?.altKey) {\n return {\n start: startDragged\n ? hit\n ? {\n mode: \"inside\",\n element: hit,\n focusPoint: globalPoint,\n }\n : { mode: null }\n : start,\n end: endDragged\n ? hit\n ? {\n mode: \"inside\",\n element: hit,\n focusPoint: globalPoint,\n }\n : { mode: null }\n : end,\n };\n }\n\n // Handle normal cases\n const current: BindingStrategy = hit\n ? pointInElement\n ? {\n mode: \"inside\",\n element: hit,\n focusPoint: globalPoint,\n }\n : {\n mode: \"orbit\",\n element: hit,\n focusPoint:\n projectFixedPointOntoDiagonal(\n arrow,\n globalPoint,\n hit,\n startDragged ? \"start\" : \"end\",\n elementsMap,\n ) || globalPoint,\n }\n : { mode: null };\n\n const otherEndpoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrow,\n startDragged ? -1 : 0,\n elementsMap,\n );\n\n const other: BindingStrategy =\n otherBindableElement &&\n !otherFocusPointIsInElement &&\n appState.selectedLinearElement?.initialState.altFocusPoint\n ? {\n mode: \"orbit\",\n element: otherBindableElement,\n focusPoint: appState.selectedLinearElement.initialState.altFocusPoint,\n }\n : opts?.angleLocked && otherBindableElement\n ? {\n mode: \"orbit\",\n element: otherBindableElement,\n focusPoint:\n projectFixedPointOntoDiagonal(\n arrow,\n otherEndpoint,\n otherBindableElement,\n startDragged ? \"end\" : \"start\",\n elementsMap,\n ) || otherEndpoint,\n }\n : { mode: undefined };\n\n return {\n start: startDragged ? current : other,\n end: endDragged ? current : other,\n };\n};\n\nconst getBindingStrategyForDraggingBindingElementEndpoints_complex = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n draggingPoints: PointsPositionUpdates,\n elementsMap: NonDeletedSceneElementsMap,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n appState: AppState,\n opts?: {\n newArrow?: boolean;\n shiftKey?: boolean;\n finalize?: boolean;\n initialBinding?: boolean;\n },\n): { start: BindingStrategy; end: BindingStrategy } => {\n const globalBindMode = appState.bindMode || \"orbit\";\n const startIdx = 0;\n const endIdx = arrow.points.length - 1;\n const startDragged = draggingPoints.has(startIdx);\n const endDragged = draggingPoints.has(endIdx);\n\n let start: BindingStrategy = { mode: undefined };\n let end: BindingStrategy = { mode: undefined };\n\n invariant(\n arrow.points.length > 1,\n \"Do not attempt to bind linear elements with a single point\",\n );\n\n // If none of the ends are dragged, we don't change anything\n if (!startDragged && !endDragged) {\n return { start, end };\n }\n\n // If both ends are dragged, we don't bind to anything\n // and break existing bindings\n if (startDragged && endDragged) {\n return { start: { mode: null }, end: { mode: null } };\n }\n\n // If binding is disabled and an endpoint is dragged,\n // we actively break the end binding\n if (!isBindingEnabled(appState)) {\n start = startDragged ? { mode: null } : start;\n end = endDragged ? { mode: null } : end;\n\n return { start, end };\n }\n\n // Handle simpler elbow arrow binding\n if (isElbowArrow(arrow)) {\n return bindingStrategyForElbowArrowEndpointDragging(\n arrow,\n draggingPoints,\n elementsMap,\n elements,\n );\n }\n\n // Handle new arrow creation separately, as it is special\n if (opts?.newArrow) {\n const { start, end } = bindingStrategyForNewSimpleArrowEndpointDragging(\n arrow,\n draggingPoints,\n elementsMap,\n elements,\n startDragged,\n endDragged,\n startIdx,\n endIdx,\n appState,\n globalBindMode,\n opts?.shiftKey,\n );\n\n return { start, end };\n }\n\n // Only the start point is dragged\n if (startDragged) {\n const localPoint = draggingPoints.get(startIdx)?.point;\n invariant(localPoint, \"Local point must be defined for start dragging\");\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\n arrow,\n localPoint,\n elementsMap,\n );\n\n const { current, other } =\n bindingStrategyForSimpleArrowEndpointDragging_complex(\n globalPoint,\n arrow.startBinding,\n arrow.endBinding,\n elementsMap,\n elements,\n globalBindMode,\n arrow,\n opts?.finalize,\n );\n\n return { start: current, end: other };\n }\n\n // Only the end point is dragged\n if (endDragged) {\n const localPoint = draggingPoints.get(endIdx)?.point;\n invariant(localPoint, \"Local point must be defined for end dragging\");\n const globalPoint = LinearElementEditor.getPointGlobalCoordinates(\n arrow,\n localPoint,\n elementsMap,\n );\n const { current, other } =\n bindingStrategyForSimpleArrowEndpointDragging_complex(\n globalPoint,\n arrow.endBinding,\n arrow.startBinding,\n elementsMap,\n elements,\n globalBindMode,\n arrow,\n opts?.finalize,\n );\n\n return { start: other, end: current };\n }\n\n return { start, end };\n};\n\nexport const bindOrUnbindBindingElements = (\n selectedArrows: NonDeleted<ExcalidrawArrowElement>[],\n scene: Scene,\n appState: AppState,\n): void => {\n selectedArrows.forEach((arrow) => {\n bindOrUnbindBindingElement(\n arrow,\n new Map(), // No dragging points in this case\n Infinity,\n Infinity,\n scene,\n appState,\n );\n });\n};\n\nexport const bindBindingElement = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n hoveredElement: ExcalidrawBindableElement,\n mode: BindMode,\n startOrEnd: \"start\" | \"end\",\n scene: Scene,\n focusPoint?: GlobalPoint,\n): void => {\n const elementsMap = scene.getNonDeletedElementsMap();\n\n let binding: FixedPointBinding;\n\n if (isElbowArrow(arrow)) {\n binding = {\n elementId: hoveredElement.id,\n mode: \"orbit\",\n ...calculateFixedPointForElbowArrowBinding(\n arrow,\n hoveredElement,\n startOrEnd,\n elementsMap,\n ),\n };\n } else {\n binding = {\n elementId: hoveredElement.id,\n mode,\n ...calculateFixedPointForNonElbowArrowBinding(\n arrow,\n hoveredElement,\n startOrEnd,\n elementsMap,\n focusPoint,\n ),\n };\n }\n\n scene.mutateElement(arrow, {\n [startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\"]: binding,\n });\n\n const boundElementsMap = arrayToMap(hoveredElement.boundElements || []);\n if (!boundElementsMap.has(arrow.id)) {\n scene.mutateElement(hoveredElement, {\n boundElements: (hoveredElement.boundElements || []).concat({\n id: arrow.id,\n type: \"arrow\",\n }),\n });\n }\n};\n\nexport const unbindBindingElement = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n startOrEnd: \"start\" | \"end\",\n scene: Scene,\n): ExcalidrawBindableElement[\"id\"] | null => {\n const field = startOrEnd === \"start\" ? \"startBinding\" : \"endBinding\";\n const binding = arrow[field];\n\n if (binding == null) {\n return null;\n }\n\n const oppositeBinding =\n arrow[startOrEnd === \"start\" ? \"endBinding\" : \"startBinding\"];\n if (!oppositeBinding || oppositeBinding.elementId !== binding.elementId) {\n // Only remove the record on the bound element if the other\n // end is not bound to the same element\n const boundElement = scene\n .getNonDeletedElementsMap()\n .get(binding.elementId) as ExcalidrawBindableElement;\n scene.mutateElement(boundElement, {\n boundElements: boundElement.boundElements?.filter(\n (element) => element.id !== arrow.id,\n ),\n });\n }\n\n scene.mutateElement(arrow, { [field]: null });\n\n return binding.elementId;\n};\n\n// Supports translating, rotating and scaling `changedElement` with bound\n// linear elements.\nexport const updateBoundElements = (\n changedElement: NonDeletedExcalidrawElement,\n scene: Scene,\n options?: {\n simultaneouslyUpdated?: readonly ExcalidrawElement[];\n changedElements?: Map<string, ExcalidrawElement>;\n },\n) => {\n if (!isBindableElement(changedElement)) {\n return;\n }\n\n const { simultaneouslyUpdated } = options ?? {};\n const simultaneouslyUpdatedElementIds = getSimultaneouslyUpdatedElementIds(\n simultaneouslyUpdated,\n );\n\n let elementsMap: ElementsMap = scene.getNonDeletedElementsMap();\n if (options?.changedElements) {\n elementsMap = new Map(elementsMap) as typeof elementsMap;\n options.changedElements.forEach((element) => {\n elementsMap.set(element.id, element);\n });\n }\n\n boundElementsVisitor(elementsMap, changedElement, (element) => {\n if (!isArrowElement(element) || element.isDeleted) {\n return;\n }\n\n // In case the boundElements are stale\n if (!doesNeedUpdate(element, changedElement)) {\n return;\n }\n\n // Check for intersections before updating bound elements incase connected elements overlap\n const startBindingElement = element.startBinding\n ? elementsMap.get(element.startBinding.elementId)\n : null;\n const endBindingElement = element.endBinding\n ? // PERF: If the arrow is bound to the same element on both ends.\n startBindingElement?.id === element.endBinding.elementId\n ? startBindingElement\n : elementsMap.get(element.endBinding.elementId)\n : null;\n\n // `linearElement` is being moved/scaled already, just update the binding\n if (simultaneouslyUpdatedElementIds.has(element.id)) {\n return;\n }\n\n const updates = bindableElementsVisitor(\n elementsMap,\n element,\n (bindableElement, bindingProp) => {\n if (\n bindableElement &&\n isBindableElement(bindableElement) &&\n (bindingProp === \"startBinding\" || bindingProp === \"endBinding\") &&\n (changedElement.id === element[bindingProp]?.elementId ||\n changedElement.id ===\n element[\n bindingProp === \"startBinding\" ? \"endBinding\" : \"startBinding\"\n ]?.elementId)\n ) {\n const point = updateBoundPoint(\n element,\n bindingProp,\n element[bindingProp],\n bindableElement,\n elementsMap,\n );\n\n if (point) {\n return [\n bindingProp === \"startBinding\" ? 0 : element.points.length - 1,\n { point },\n ] as MapEntry<PointsPositionUpdates>;\n }\n }\n\n return null;\n },\n ).filter(\n (update): update is MapEntry<PointsPositionUpdates> => update !== null,\n );\n\n LinearElementEditor.movePoints(element, scene, new Map(updates), {\n moveMidPointsWithElement:\n !!startBindingElement &&\n startBindingElement?.id === endBindingElement?.id,\n });\n\n const boundText = getBoundTextElement(element, elementsMap);\n if (boundText && !boundText.isDeleted) {\n handleBindTextResize(element, scene, false);\n }\n });\n};\n\nexport const updateBindings = (\n latestElement: ExcalidrawElement,\n scene: Scene,\n appState: AppState,\n options?: {\n simultaneouslyUpdated?: readonly ExcalidrawElement[];\n newSize?: { width: number; height: number };\n },\n) => {\n if (isArrowElement(latestElement)) {\n bindOrUnbindBindingElement(\n latestElement,\n new Map(),\n Infinity,\n Infinity,\n scene,\n appState,\n );\n } else {\n updateBoundElements(latestElement, scene, {\n ...options,\n changedElements: new Map([[latestElement.id, latestElement]]),\n });\n }\n};\n\nconst doesNeedUpdate = (\n boundElement: NonDeleted<ExcalidrawArrowElement>,\n changedElement: ExcalidrawBindableElement,\n) => {\n return (\n boundElement.startBinding?.elementId === changedElement.id ||\n boundElement.endBinding?.elementId === changedElement.id\n );\n};\n\nconst getSimultaneouslyUpdatedElementIds = (\n simultaneouslyUpdated: readonly ExcalidrawElement[] | undefined,\n): Set<ExcalidrawElement[\"id\"]> => {\n return new Set((simultaneouslyUpdated || []).map((element) => element.id));\n};\n\nexport const getHeadingForElbowArrowSnap = (\n p: Readonly<GlobalPoint>,\n otherPoint: Readonly<GlobalPoint>,\n bindableElement: ExcalidrawBindableElement | undefined | null,\n aabb: Bounds | undefined | null,\n origPoint: GlobalPoint,\n elementsMap: ElementsMap,\n zoom?: AppState[\"zoom\"],\n): Heading => {\n const otherPointHeading = vectorToHeading(vectorFromPoint(otherPoint, p));\n\n if (!bindableElement || !aabb) {\n return otherPointHeading;\n }\n\n const distance = getDistanceForBinding(\n origPoint,\n bindableElement,\n elementsMap,\n zoom,\n );\n\n if (!distance) {\n return vectorToHeading(\n vectorFromPoint(p, elementCenterPoint(bindableElement, elementsMap)),\n );\n }\n\n return headingForPointFromElement(bindableElement, aabb, p);\n};\n\nconst getDistanceForBinding = (\n point: Readonly<GlobalPoint>,\n bindableElement: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n zoom?: AppState[\"zoom\"],\n) => {\n const distance = distanceToElement(bindableElement, elementsMap, point);\n const bindDistance = maxBindingDistance_simple(zoom);\n\n return distance > bindDistance ? null : distance;\n};\n\nexport const bindPointToSnapToElementOutline = (\n arrowElement: ExcalidrawArrowElement,\n bindableElement: ExcalidrawBindableElement,\n startOrEnd: \"start\" | \"end\",\n elementsMap: ElementsMap,\n customIntersector?: LineSegment<GlobalPoint>,\n): GlobalPoint => {\n const elbowed = isElbowArrow(arrowElement);\n const point = LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrowElement,\n startOrEnd === \"start\" ? 0 : -1,\n elementsMap,\n );\n\n if (arrowElement.points.length < 2) {\n // New arrow creation, so no snapping\n return point;\n }\n\n const edgePoint =\n isRectanguloidElement(bindableElement) && elbowed\n ? avoidRectangularCorner(\n arrowElement,\n bindableElement,\n elementsMap,\n point,\n )\n : point;\n const adjacentPoint =\n customIntersector && !elbowed\n ? customIntersector[1]\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\n arrowElement,\n startOrEnd === \"start\" ? 1 : -2,\n elementsMap,\n );\n const bindingGap = getBindingGap(bindableElement, arrowElement);\n const aabb = aabbForElement(bindableElement, elementsMap);\n const bindableCenter = getCenterForBounds(aabb);\n\n let intersection: GlobalPoint | null = null;\n if (elbowed) {\n const isHorizontal = headingIsHorizontal(\n headingForPointFromElement(bindableElement, aabb, point),\n );\n const snapPoint = snapToMid(\n arrowElement,\n bindableElement,\n elementsMap,\n edgePoint,\n );\n const otherPoint = pointFrom<GlobalPoint>(\n isHorizontal ? bindableCenter[0] : snapPoint[0],\n !isHorizontal ? bindableCenter[1] : snapPoint[1],\n );\n const intersector =\n customIntersector ??\n lineSegment(\n otherPoint,\n pointFromVector(\n vectorScale(\n vectorNormalize(vectorFromPoint(snapPoint, otherPoint)),\n Math.max(bindableElement.width, bindableElement.height) * 2,\n ),\n otherPoint,\n ),\n );\n intersection = intersectElementWithLineSegment(\n bindableElement,\n elementsMap,\n intersector,\n bindingGap,\n ).sort(pointDistanceSq)[0];\n\n if (!intersection) {\n const anotherPoint = pointFrom<GlobalPoint>(\n !isHorizontal ? bindableCenter[0] : snapPoint[0],\n isHorizontal ? bindableCenter[1] : snapPoint[1],\n );\n const anotherIntersector = lineSegment(\n anotherPoint,\n pointFromVector(\n vectorScale(\n vectorNormalize(vectorFromPoint(snapPoint, anotherPoint)),\n Math.max(bindableElement.width, bindableElement.height) * 2,\n ),\n anotherPoint,\n ),\n );\n intersection = intersectElementWithLineSegment(\n bindableElement,\n elementsMap,\n anotherIntersector,\n BASE_BINDING_GAP_ELBOW,\n ).sort(pointDistanceSq)[0];\n }\n } else {\n let intersector = customIntersector;\n if (!intersector) {\n const halfVector = vectorScale(\n vectorNormalize(vectorFromPoint(edgePoint, adjacentPoint)),\n pointDistance(edgePoint, adjacentPoint) +\n Math.max(bindableElement.width, bindableElement.height) +\n bindingGap * 2,\n );\n intersector =\n customIntersector ??\n lineSegment(\n pointFromVector(halfVector, adjacentPoint),\n pointFromVector(vectorScale(halfVector, -1), adjacentPoint),\n );\n }\n\n intersection =\n pointDistance(edgePoint, adjacentPoint) < 1\n ? edgePoint\n : intersectElementWithLineSegment(\n bindableElement,\n elementsMap,\n intersector,\n bindingGap,\n ).sort(\n (g, h) =>\n pointDistanceSq(g, adjacentPoint) -\n pointDistanceSq(h, adjacentPoint),\n )[0];\n }\n\n if (\n !intersection ||\n // Too close to determine vector from intersection to edgePoint\n pointDistanceSq(edgePoint, intersection) < PRECISION\n ) {\n return edgePoint;\n }\n\n return intersection;\n};\n\nexport const avoidRectangularCorner = (\n arrowElement: ExcalidrawArrowElement,\n bindTarget: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n p: GlobalPoint,\n): GlobalPoint => {\n const center = elementCenterPoint(bindTarget, elementsMap);\n const nonRotatedPoint = pointRotateRads(\n p,\n center,\n -bindTarget.angle as Radians,\n );\n\n const bindingGap = getBindingGap(bindTarget, arrowElement);\n\n if (nonRotatedPoint[0] < bindTarget.x && nonRotatedPoint[1] < bindTarget.y) {\n // Top left\n if (nonRotatedPoint[1] - bindTarget.y > -bindingGap) {\n return pointRotateRads<GlobalPoint>(\n pointFrom(bindTarget.x - bindingGap, bindTarget.y),\n center,\n bindTarget.angle,\n );\n }\n return pointRotateRads(\n pointFrom(bindTarget.x, bindTarget.y - bindingGap),\n center,\n bindTarget.angle,\n );\n } else if (\n nonRotatedPoint[0] < bindTarget.x &&\n nonRotatedPoint[1] > bindTarget.y + bindTarget.height\n ) {\n // Bottom left\n if (nonRotatedPoint[0] - bindTarget.x > -bindingGap) {\n return pointRotateRads(\n pointFrom(bindTarget.x, bindTarget.y + bindTarget.height + bindingGap),\n center,\n bindTarget.angle,\n );\n }\n return pointRotateRads(\n pointFrom(bindTarget.x - bindingGap, bindTarget.y + bindTarget.height),\n center,\n bindTarget.angle,\n );\n } else if (\n nonRotatedPoint[0] > bindTarget.x + bindTarget.width &&\n nonRotatedPoint[1] > bindTarget.y + bindTarget.height\n ) {\n // Bottom right\n if (nonRotatedPoint[0] - bindTarget.x < bindTarget.width + bindingGap) {\n return pointRotateRads(\n pointFrom(\n bindTarget.x + bindTarget.width,\n bindTarget.y + bindTarget.height + bindingGap,\n ),\n center,\n bindTarget.angle,\n );\n }\n return pointRotateRads(\n pointFrom(\n bindTarget.x + bindTarget.width + bindingGap,\n bindTarget.y + bindTarget.height,\n ),\n center,\n bindTarget.angle,\n );\n } else if (\n nonRotatedPoint[0] > bindTarget.x + bindTarget.width &&\n nonRotatedPoint[1] < bindTarget.y\n ) {\n // Top right\n if (nonRotatedPoint[0] - bindTarget.x < bindTarget.width + bindingGap) {\n return pointRotateRads(\n pointFrom(bindTarget.x + bindTarget.width, bindTarget.y - bindingGap),\n center,\n bindTarget.angle,\n );\n }\n return pointRotateRads(\n pointFrom(bindTarget.x + bindTarget.width + bindingGap, bindTarget.y),\n center,\n bindTarget.angle,\n );\n }\n\n return p;\n};\n\nconst snapToMid = (\n arrowElement: ExcalidrawArrowElement,\n bindTarget: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n p: GlobalPoint,\n tolerance: number = 0.05,\n): GlobalPoint => {\n const { x, y, width, height, angle } = bindTarget;\n const center = elementCenterPoint(bindTarget, elementsMap, -0.1, -0.1);\n const nonRotated = pointRotateRads(p, center, -angle as Radians);\n\n const bindingGap = getBindingGap(bindTarget, arrowElement);\n\n // snap-to-center point is adaptive to element size, but we don't want to go\n // above and below certain px distance\n const verticalThreshold = clamp(tolerance * height, 5, 80);\n const horizontalThreshold = clamp(tolerance * width, 5, 80);\n\n // Too close to the center makes it hard to resolve direction precisely\n if (pointDistance(center, nonRotated) < bindingGap) {\n return p;\n }\n\n if (\n nonRotated[0] <= x + width / 2 &&\n nonRotated[1] > center[1] - verticalThreshold &&\n nonRotated[1] < center[1] + verticalThreshold\n ) {\n // LEFT\n return pointRotateRads<GlobalPoint>(\n pointFrom(x - bindingGap, center[1]),\n center,\n angle,\n );\n } else if (\n nonRotated[1] <= y + height / 2 &&\n nonRotated[0] > center[0] - horizontalThreshold &&\n nonRotated[0] < center[0] + horizontalThreshold\n ) {\n // TOP\n return pointRotateRads(pointFrom(center[0], y - bindingGap), center, angle);\n } else if (\n nonRotated[0] >= x + width / 2 &&\n nonRotated[1] > center[1] - verticalThreshold &&\n nonRotated[1] < center[1] + verticalThreshold\n ) {\n // RIGHT\n return pointRotateRads(\n pointFrom(x + width + bindingGap, center[1]),\n center,\n angle,\n );\n } else if (\n nonRotated[1] >= y + height / 2 &&\n nonRotated[0] > center[0] - horizontalThreshold &&\n nonRotated[0] < center[0] + horizontalThreshold\n ) {\n // DOWN\n return pointRotateRads(\n pointFrom(center[0], y + height + bindingGap),\n center,\n angle,\n );\n } else if (bindTarget.type === \"diamond\") {\n const distance = bindingGap;\n const topLeft = pointFrom<GlobalPoint>(\n x + width / 4 - distance,\n y + height / 4 - distance,\n );\n const topRight = pointFrom<GlobalPoint>(\n x + (3 * width) / 4 + distance,\n y + height / 4 - distance,\n );\n const bottomLeft = pointFrom<GlobalPoint>(\n x + width / 4 - distance,\n y + (3 * height) / 4 + distance,\n );\n const bottomRight = pointFrom<GlobalPoint>(\n x + (3 * width) / 4 + distance,\n y + (3 * height) / 4 + distance,\n );\n\n if (\n pointDistance(topLeft, nonRotated) <\n Math.max(horizontalThreshold, verticalThreshold)\n ) {\n return pointRotateRads(topLeft, center, angle);\n }\n if (\n pointDistance(topRight, nonRotated) <\n Math.max(horizontalThreshold, verticalThreshold)\n ) {\n return pointRotateRads(topRight, center, angle);\n }\n if (\n pointDistance(bottomLeft, nonRotated) <\n Math.max(horizontalThreshold, verticalThreshold)\n ) {\n return pointRotateRads(bottomLeft, center, angle);\n }\n if (\n pointDistance(bottomRight, nonRotated) <\n Math.max(horizontalThreshold, verticalThreshold)\n ) {\n return pointRotateRads(bottomRight, center, angle);\n }\n }\n\n return p;\n};\n\nconst compareElementArea = (\n a: ExcalidrawBindableElement,\n b: ExcalidrawBindableElement,\n) => b.width ** 2 + b.height ** 2 - (a.width ** 2 + a.height ** 2);\n\nexport const updateBoundPoint = (\n arrow: NonDeleted<ExcalidrawArrowElement>,\n startOrEnd: \"startBinding\" | \"endBinding\",\n binding: FixedPointBinding | null | undefined,\n bindableElement: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n customIntersector?: LineSegment<GlobalPoint>,\n): LocalPoint | null => {\n if (\n binding == null ||\n // We only need to update the other end if this is a 2 point line element\n (binding.elementId !== bindableElement.id && arrow.points.length > 2)\n ) {\n return null;\n }\n\n const global = getGlobalFixedPointForBindableElement(\n normalizeFixedPoint(binding.fixedPoint),\n bindableElement,\n elementsMap,\n );\n const pointIndex =\n startOrEnd === \"startBinding\" ? 0 : arrow.points.length - 1;\n const elbowed = isElbowArrow(arrow);\n const otherBinding =\n startOrEnd === \"startBinding\" ? arrow.endBinding : arrow.startBinding;\n const otherBindableElement =\n otherBinding &&\n (elementsMap.get(otherBinding.elementId)! as ExcalidrawBindableElement);\n const bounds = getElementBounds(bindableElement, elementsMap);\n const otherBounds =\n otherBindableElement && getElementBounds(otherBindableElement, elementsMap);\n const isLargerThanOther =\n otherBindableElement &&\n compareElementArea(bindableElement, otherBindableElement) <\n // if both shapes the same size, pretend the other is larger\n (startOrEnd === \"endBinding\" ? 1 : 0);\n const isOverlapping = otherBounds && doBoundsIntersect(bounds, otherBounds);\n\n // GOAL: If the arrow becomes too short, we want to jump the arrow endpoints\n // to the exact focus points on the elements.\n // INTUITION: We're not interested in the exacts length of the arrow (which\n // will change if we change where we route it), we want to know the length of\n // the part which lies outside of both shapes and consider that as a trigger\n // to change where we point the arrow. Avoids jumping the arrow in and out\n // at every frame.\n let arrowTooShort = false;\n if (\n !isOverlapping &&\n !elbowed &&\n arrow.startBinding &&\n arrow.endBinding &&\n otherBindableElement &&\n arrow.points.length === 2\n ) {\n const startFocusPoint = getGlobalFixedPointForBindableElement(\n arrow.startBinding.fixedPoint,\n startOrEnd === \"startBinding\" ? bindableElement : otherBindableElement,\n elementsMap,\n );\n const endFocusPoint = getGlobalFixedPointForBindableElement(\n arrow.endBinding.fixedPoint,\n startOrEnd === \"endBinding\" ? bindableElement : otherBindableElement,\n elementsMap,\n );\n const segment = lineSegment(startFocusPoint, endFocusPoint);\n const startIntersection = intersectElementWithLineSegment(\n startOrEnd === \"endBinding\" ? bindableElement : otherBindableElement,\n elementsMap,\n segment,\n 0,\n true,\n );\n const endIntersection = intersectElementWithLineSegment(\n startOrEnd === \"startBinding\" ? bindableElement : otherBindableElement,\n elementsMap,\n segment,\n 0,\n true,\n );\n if (startIntersection.length > 0 && endIntersection.length > 0) {\n const len = pointDistance(startIntersection[0], endIntersection[0]);\n arrowTooShort = len < 40;\n }\n }\n\n const isNested = (arrowTooShort || isOverlapping) && isLargerThanOther;\n\n let _customIntersector = customIntersector;\n if (!elbowed && !_customIntersector) {\n const [x1, y1, x2, y2] = LinearElementEditor.getElementAbsoluteCoords(\n arrow,\n elementsMap,\n );\n const center = pointFrom<GlobalPoint>((x1 + x2) / 2, (y1 + y2) / 2);\n const edgePoint = isRectanguloidElement(bindableElement)\n ? avoidRectangularCorner(arrow, bindableElement, elementsMap, global)\n : global;\n const adjacentPoint = pointRotateRads(\n pointFrom<GlobalPoint>(\n arrow.x +\n arrow.points[pointIndex === 0 ? 1 : arrow.points.length - 2][0],\n arrow.y +\n arrow.points[pointIndex === 0 ? 1 : arrow.points.length - 2][1],\n ),\n center,\n arrow.angle as Radians,\n );\n const bindingGap = getBindingGap(bindableElement, arrow);\n const halfVector = vectorScale(\n vectorNormalize(vectorFromPoint(edgePoint, adjacentPoint)),\n pointDistance(edgePoint, adjacentPoint) +\n Math.max(bindableElement.width, bindableElement.height) +\n bindingGap * 2,\n );\n _customIntersector = lineSegment(\n pointFromVector(halfVector, adjacentPoint),\n pointFromVector(vectorScale(halfVector, -1), adjacentPoint),\n );\n }\n\n const maybeOutlineGlobal =\n binding.mode === \"orbit\" && bindableElement\n ? isNested\n ? global\n : bindPointToSnapToElementOutline(\n {\n ...arrow,\n points: [\n pointIndex === 0\n ? LinearElementEditor.createPointAt(\n arrow,\n elementsMap,\n global[0],\n global[1],\n null,\n )\n : arrow.points[0],\n ...arrow.points.slice(1, -1),\n pointIndex === arrow.points.length - 1\n ? LinearElementEditor.createPointAt(\n arrow,\n elementsMap,\n global[0],\n global[1],\n null,\n )\n : arrow.points[arrow.points.length - 1],\n ],\n },\n bindableElement,\n pointIndex === 0 ? \"start\" : \"end\",\n elementsMap,\n _customIntersector,\n )\n : global;\n\n return LinearElementEditor.createPointAt(\n arrow,\n elementsMap,\n maybeOutlineGlobal[0],\n maybeOutlineGlobal[1],\n null,\n );\n};\n\nexport const calculateFixedPointForElbowArrowBinding = (\n linearElement: NonDeleted<ExcalidrawElbowArrowElement>,\n hoveredElement: ExcalidrawBindableElement,\n startOrEnd: \"start\" | \"end\",\n elementsMap: ElementsMap,\n): { fixedPoint: FixedPoint } => {\n const bounds = [\n hoveredElement.x,\n hoveredElement.y,\n hoveredElement.x + hoveredElement.width,\n hoveredElement.y + hoveredElement.height,\n ] as Bounds;\n const snappedPoint = bindPointToSnapToElementOutline(\n linearElement,\n hoveredElement,\n startOrEnd,\n elementsMap,\n );\n const globalMidPoint = pointFrom(\n bounds[0] + (bounds[2] - bounds[0]) / 2,\n bounds[1] + (bounds[3] - bounds[1]) / 2,\n );\n const nonRotatedSnappedGlobalPoint = pointRotateRads(\n snappedPoint,\n globalMidPoint,\n -hoveredElement.angle as Radians,\n );\n\n return {\n fixedPoint: normalizeFixedPoint([\n (nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) /\n hoveredElement.width,\n (nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) /\n hoveredElement.height,\n ]),\n };\n};\n\nexport const calculateFixedPointForNonElbowArrowBinding = (\n linearElement: NonDeleted<ExcalidrawArrowElement>,\n hoveredElement: ExcalidrawBindableElement,\n startOrEnd: \"start\" | \"end\",\n elementsMap: ElementsMap,\n focusPoint?: GlobalPoint,\n): { fixedPoint: FixedPoint } => {\n const edgePoint = focusPoint\n ? focusPoint\n : LinearElementEditor.getPointAtIndexGlobalCoordinates(\n linearElement,\n startOrEnd === \"start\" ? 0 : -1,\n elementsMap,\n );\n\n // Convert the global point to element-local coordinates\n const elementCenter = pointFrom(\n hoveredElement.x + hoveredElement.width / 2,\n hoveredElement.y + hoveredElement.height / 2,\n );\n\n // Rotate the point to account for element rotation\n const nonRotatedPoint = pointRotateRads(\n edgePoint,\n elementCenter,\n -hoveredElement.angle as Radians,\n );\n\n // Calculate the ratio relative to the element's bounds\n const fixedPointX =\n (nonRotatedPoint[0] - hoveredElement.x) / hoveredElement.width;\n const fixedPointY =\n (nonRotatedPoint[1] - hoveredElement.y) / hoveredElement.height;\n\n return {\n fixedPoint: normalizeFixedPoint([fixedPointX, fixedPointY]),\n };\n};\n\nexport const fixDuplicatedBindingsAfterDuplication = (\n duplicatedElements: ExcalidrawElement[],\n origIdToDuplicateId: Map<ExcalidrawElement[\"id\"], ExcalidrawElement[\"id\"]>,\n duplicateElementsMap: NonDeletedSceneElementsMap,\n) => {\n for (const duplicateElement of duplicatedElements) {\n if (\"boundElements\" in duplicateElement && duplicateElement.boundElements) {\n Object.assign(duplicateElement, {\n boundElements: duplicateElement.boundElements.reduce(\n (\n acc: Mutable<NonNullable<ExcalidrawElement[\"boundElements\"]>>,\n binding,\n ) => {\n const newBindingId = origIdToDuplicateId.get(binding.id);\n if (newBindingId) {\n acc.push({ ...binding, id: newBindingId });\n }\n return acc;\n },\n [],\n ),\n });\n }\n\n if (\"containerId\" in duplicateElement && duplicateElement.containerId) {\n Object.assign(duplicateElement, {\n containerId:\n origIdToDuplicateId.get(duplicateElement.containerId) ?? null,\n });\n }\n\n if (\"endBinding\" in duplicateElement && duplicateElement.endBinding) {\n const newEndBindingId = origIdToDuplicateId.get(\n duplicateElement.endBinding.elementId,\n );\n Object.assign(duplicateElement, {\n endBinding: newEndBindingId\n ? {\n ...duplicateElement.endBinding,\n elementId: newEndBindingId,\n }\n : null,\n });\n }\n if (\"startBinding\" in duplicateElement && duplicateElement.startBinding) {\n const newEndBindingId = origIdToDuplicateId.get(\n duplicateElement.startBinding.elementId,\n );\n Object.assign(duplicateElement, {\n startBinding: newEndBindingId\n ? {\n ...duplicateElement.startBinding,\n elementId: newEndBindingId,\n }\n : null,\n });\n }\n\n if (isElbowArrow(duplicateElement)) {\n Object.assign(\n duplicateElement,\n updateElbowArrowPoints(duplicateElement, duplicateElementsMap, {\n points: [\n duplicateElement.points[0],\n duplicateElement.points[duplicateElement.points.length - 1],\n ],\n }),\n );\n }\n }\n};\n\nexport const fixBindingsAfterDeletion = (\n sceneElements: readonly ExcalidrawElement[],\n deletedElements: readonly ExcalidrawElement[],\n): void => {\n const elements = arrayToMap(sceneElements);\n\n for (const element of deletedElements) {\n BoundElement.unbindAffected(elements, element, (element, updates) =>\n mutateElement(element, elements, updates),\n );\n BindableElement.unbindAffected(elements, element, (element, updates) =>\n mutateElement(element, elements, updates),\n );\n }\n};\n\nconst newBoundElements = (\n boundElements: ExcalidrawElement[\"boundElements\"],\n idsToRemove: Set<ExcalidrawElement[\"id\"]>,\n elementsToAdd: Array<ExcalidrawElement> = [],\n) => {\n if (!boundElements) {\n return null;\n }\n\n const nextBoundElements = boundElements.filter(\n (boundElement) => !idsToRemove.has(boundElement.id),\n );\n\n nextBoundElements.push(\n ...elementsToAdd.map(\n (x) =>\n ({ id: x.id, type: x.type } as\n | ExcalidrawArrowElement\n | ExcalidrawTextElement),\n ),\n );\n\n return nextBoundElements;\n};\n\nexport const bindingProperties: Set<BindableProp | BindingProp> = new Set([\n \"boundElements\",\n \"frameId\",\n \"containerId\",\n \"startBinding\",\n \"endBinding\",\n]);\n\nexport type BindableProp = \"boundElements\";\n\nexport type BindingProp =\n | \"frameId\"\n | \"containerId\"\n | \"startBinding\"\n | \"endBinding\";\n\ntype BoundElementsVisitingFunc = (\n boundElement: ExcalidrawElement | undefined,\n bindingProp: BindableProp,\n bindingId: string,\n) => void;\n\ntype BindableElementVisitingFunc<T> = (\n bindableElement: ExcalidrawElement | undefined,\n bindingProp: BindingProp,\n bindingId: string,\n) => T;\n\n/**\n * Tries to visit each bound element (does not have to be found).\n */\nconst boundElementsVisitor = (\n elements: ElementsMap,\n element: ExcalidrawElement,\n visit: BoundElementsVisitingFunc,\n) => {\n if (isBindableElement(element)) {\n // create new instance so that possible mutations won't play a role in visiting order\n const boundElements = element.boundElements?.slice() ?? [];\n\n // last added text should be the one we keep (~previous are duplicates)\n boundElements.forEach(({ id }) => {\n visit(elements.get(id), \"boundElements\", id);\n });\n }\n};\n\n/**\n * Tries to visit each bindable element (does not have to be found).\n */\nconst bindableElementsVisitor = <T>(\n elements: ElementsMap,\n element: ExcalidrawElement,\n visit: BindableElementVisitingFunc<T>,\n): T[] => {\n const result: T[] = [];\n\n if (element.frameId) {\n const id = element.frameId;\n result.push(visit(elements.get(id), \"frameId\", id));\n }\n\n if (isBoundToContainer(element)) {\n const id = element.containerId;\n result.push(visit(elements.get(id), \"containerId\", id));\n }\n\n if (isArrowElement(element)) {\n if (element.startBinding) {\n const id = element.startBinding.elementId;\n result.push(visit(elements.get(id), \"startBinding\", id));\n }\n\n if (element.endBinding) {\n const id = element.endBinding.elementId;\n result.push(visit(elements.get(id), \"endBinding\", id));\n }\n }\n\n return result;\n};\n\n/**\n * Bound element containing bindings to `frameId`, `containerId`, `startBinding` or `endBinding`.\n */\nexport class BoundElement {\n /**\n * Unbind the affected non deleted bindable elements (removing element from `boundElements`).\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\n * - prepares updates to unbind each bindable element's `boundElements` from the current element\n */\n public static unbindAffected(\n elements: ElementsMap,\n boundElement: ExcalidrawElement | undefined,\n updateElementWith: (\n affected: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => void,\n ) {\n if (!boundElement) {\n return;\n }\n\n bindableElementsVisitor(elements, boundElement, (bindableElement) => {\n // bindable element is deleted, this is fine\n if (!bindableElement || bindableElement.isDeleted) {\n return;\n }\n\n boundElementsVisitor(\n elements,\n bindableElement,\n (_, __, boundElementId) => {\n if (boundElementId === boundElement.id) {\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(\n bindableElement.boundElements,\n new Set([boundElementId]),\n ),\n });\n }\n },\n );\n });\n }\n\n /**\n * Rebind the next affected non deleted bindable elements (adding element to `boundElements`).\n * - iterates non deleted bindable elements (`containerId` | `startBinding.elementId` | `endBinding.elementId`) of the current element\n * - prepares updates to rebind each bindable element's `boundElements` to the current element\n *\n * NOTE: rebind expects that affected elements were previously unbound with `BoundElement.unbindAffected`\n */\n public static rebindAffected = (\n elements: ElementsMap,\n boundElement: ExcalidrawElement | undefined,\n updateElementWith: (\n affected: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => void,\n ) => {\n // don't try to rebind element that is deleted\n if (!boundElement || boundElement.isDeleted) {\n return;\n }\n\n bindableElementsVisitor(\n elements,\n boundElement,\n (bindableElement, bindingProp) => {\n // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\n if (!bindableElement || bindableElement.isDeleted) {\n updateElementWith(boundElement, { [bindingProp]: null });\n return;\n }\n\n // frame bindings are unidirectional, there is nothing to rebind\n if (bindingProp === \"frameId\") {\n return;\n }\n\n if (\n bindableElement.boundElements?.find((x) => x.id === boundElement.id)\n ) {\n return;\n }\n\n if (isArrowElement(boundElement)) {\n // rebind if not found!\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(\n bindableElement.boundElements,\n new Set(),\n new Array(boundElement),\n ),\n });\n }\n\n if (isTextElement(boundElement)) {\n if (!bindableElement.boundElements?.find((x) => x.type === \"text\")) {\n // rebind only if there is no other text bound already\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(\n bindableElement.boundElements,\n new Set(),\n new Array(boundElement),\n ),\n });\n } else {\n // unbind otherwise\n updateElementWith(boundElement, { [bindingProp]: null });\n }\n }\n },\n );\n };\n}\n\n/**\n * Bindable element containing bindings to `boundElements`.\n */\nexport class BindableElement {\n /**\n * Unbind the affected non deleted bound elements (resetting `containerId`, `startBinding`, `endBinding` to `null`).\n * - iterates through non deleted `boundElements` of the current element\n * - prepares updates to unbind each bound element from the current element\n */\n public static unbindAffected(\n elements: ElementsMap,\n bindableElement: ExcalidrawElement | undefined,\n updateElementWith: (\n affected: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => void,\n ) {\n if (!bindableElement) {\n return;\n }\n\n boundElementsVisitor(elements, bindableElement, (boundElement) => {\n // bound element is deleted, this is fine\n if (!boundElement || boundElement.isDeleted) {\n return;\n }\n\n bindableElementsVisitor(\n elements,\n boundElement,\n (_, bindingProp, bindableElementId) => {\n // making sure there is an element to be unbound\n if (bindableElementId === bindableElement.id) {\n updateElementWith(boundElement, { [bindingProp]: null });\n }\n },\n );\n });\n }\n\n /**\n * Rebind the affected non deleted bound elements (for now setting only `containerId`, as we cannot rebind arrows atm).\n * - iterates through non deleted `boundElements` of the current element\n * - prepares updates to rebind each bound element to the current element or unbind it from `boundElements` in case of conflicts\n *\n * NOTE: rebind expects that affected elements were previously unbound with `BindaleElement.unbindAffected`\n */\n public static rebindAffected = (\n elements: ElementsMap,\n bindableElement: ExcalidrawElement | undefined,\n updateElementWith: (\n affected: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => void,\n ) => {\n // don't try to rebind element that is deleted (i.e. updated as deleted)\n if (!bindableElement || bindableElement.isDeleted) {\n return;\n }\n\n boundElementsVisitor(\n elements,\n bindableElement,\n (boundElement, _, boundElementId) => {\n // unbind from bindable elements, as bindings from non deleted elements into deleted elements are incorrect\n if (!boundElement || boundElement.isDeleted) {\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(\n bindableElement.boundElements,\n new Set([boundElementId]),\n ),\n });\n return;\n }\n\n if (isTextElement(boundElement)) {\n const boundElements = bindableElement.boundElements?.slice() ?? [];\n // check if this is the last element in the array, if not, there is an previously bound text which should be unbound\n if (\n boundElements.reverse().find((x) => x.type === \"text\")?.id ===\n boundElement.id\n ) {\n if (boundElement.containerId !== bindableElement.id) {\n // rebind if not bound already!\n updateElementWith(boundElement, {\n containerId: bindableElement.id,\n } as ElementUpdate<ExcalidrawTextElement>);\n }\n } else {\n if (boundElement.containerId !== null) {\n // unbind if not unbound already\n updateElementWith(boundElement, {\n containerId: null,\n } as ElementUpdate<ExcalidrawTextElement>);\n }\n\n // unbind from boundElements as the element got bound to some other element in the meantime\n updateElementWith(bindableElement, {\n boundElements: newBoundElements(\n bindableElement.boundElements,\n new Set([boundElement.id]),\n ),\n });\n }\n }\n },\n );\n };\n}\n\nexport const getGlobalFixedPointForBindableElement = (\n fixedPointRatio: FixedPoint,\n element: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n): GlobalPoint => {\n const [fixedX, fixedY] = normalizeFixedPoint(fixedPointRatio);\n\n return pointRotateRads(\n pointFrom(\n element.x + element.width * fixedX,\n element.y + element.height * fixedY,\n ),\n elementCenterPoint(element, elementsMap),\n element.angle,\n );\n};\n\nexport const getGlobalFixedPoints = (\n arrow: ExcalidrawArrowElement,\n elementsMap: ElementsMap,\n): [GlobalPoint, GlobalPoint] => {\n const startElement =\n arrow.startBinding &&\n (elementsMap.get(arrow.startBinding.elementId) as\n | ExcalidrawBindableElement\n | undefined);\n const endElement =\n arrow.endBinding &&\n (elementsMap.get(arrow.endBinding.elementId) as\n | ExcalidrawBindableElement\n | undefined);\n const startPoint =\n startElement && arrow.startBinding\n ? getGlobalFixedPointForBindableElement(\n arrow.startBinding.fixedPoint,\n startElement as ExcalidrawBindableElement,\n elementsMap,\n )\n : pointFrom<GlobalPoint>(\n arrow.x + arrow.points[0][0],\n arrow.y + arrow.points[0][1],\n );\n const endPoint =\n endElement && arrow.endBinding\n ? getGlobalFixedPointForBindableElement(\n arrow.endBinding.fixedPoint,\n endElement as ExcalidrawBindableElement,\n elementsMap,\n )\n : pointFrom<GlobalPoint>(\n arrow.x + arrow.points[arrow.points.length - 1][0],\n arrow.y + arrow.points[arrow.points.length - 1][1],\n );\n\n return [startPoint, endPoint];\n};\n\nexport const getArrowLocalFixedPoints = (\n arrow: ExcalidrawElbowArrowElement,\n elementsMap: ElementsMap,\n) => {\n const [startPoint, endPoint] = getGlobalFixedPoints(arrow, elementsMap);\n\n return [\n LinearElementEditor.pointFromAbsoluteCoords(arrow, startPoint, elementsMap),\n LinearElementEditor.pointFromAbsoluteCoords(arrow, endPoint, elementsMap),\n ];\n};\n\nexport const normalizeFixedPoint = <T extends FixedPoint | null>(\n fixedPoint: T,\n): T extends null ? null : FixedPoint => {\n // Do not allow a precise 0.5 for fixed point ratio\n // to avoid jumping arrow heading due to floating point imprecision\n if (\n fixedPoint &&\n (Math.abs(fixedPoint[0] - 0.5) < 0.0001 ||\n Math.abs(fixedPoint[1] - 0.5) < 0.0001)\n ) {\n return fixedPoint.map((ratio) =>\n Math.abs(ratio - 0.5) < 0.0001 ? 0.5001 : ratio,\n ) as T extends null ? null : FixedPoint;\n }\n return fixedPoint as any as T extends null ? null : FixedPoint;\n};\n\ntype Side =\n | \"top\"\n | \"top-right\"\n | \"right\"\n | \"bottom-right\"\n | \"bottom\"\n | \"bottom-left\"\n | \"left\"\n | \"top-left\";\ntype ShapeType = \"rectangle\" | \"ellipse\" | \"diamond\";\nconst getShapeType = (element: ExcalidrawBindableElement): ShapeType => {\n if (element.type === \"ellipse\" || element.type === \"diamond\") {\n return element.type;\n }\n return \"rectangle\";\n};\n\ninterface SectorConfig {\n // center angle of the sector in degrees\n centerAngle: number;\n // width of the sector in degrees\n sectorWidth: number;\n side: Side;\n}\n\n// Define sector configurations for different shape types\nconst SHAPE_CONFIGS: Record<ShapeType, SectorConfig[]> = {\n // rectangle: 15\u00B0 corners, 75\u00B0 edges\n rectangle: [\n { centerAngle: 0, sectorWidth: 75, side: \"right\" },\n { centerAngle: 45, sectorWidth: 15, side: \"bottom-right\" },\n { centerAngle: 90, sectorWidth: 75, side: \"bottom\" },\n { centerAngle: 135, sectorWidth: 15, side: \"bottom-left\" },\n { centerAngle: 180, sectorWidth: 75, side: \"left\" },\n { centerAngle: 225, sectorWidth: 15, side: \"top-left\" },\n { centerAngle: 270, sectorWidth: 75, side: \"top\" },\n { centerAngle: 315, sectorWidth: 15, side: \"top-right\" },\n ],\n\n // diamond: 15\u00B0 vertices, 75\u00B0 edges\n diamond: [\n { centerAngle: 0, sectorWidth: 15, side: \"right\" },\n { centerAngle: 45, sectorWidth: 75, side: \"bottom-right\" },\n { centerAngle: 90, sectorWidth: 15, side: \"bottom\" },\n { centerAngle: 135, sectorWidth: 75, side: \"bottom-left\" },\n { centerAngle: 180, sectorWidth: 15, side: \"left\" },\n { centerAngle: 225, sectorWidth: 75, side: \"top-left\" },\n { centerAngle: 270, sectorWidth: 15, side: \"top\" },\n { centerAngle: 315, sectorWidth: 75, side: \"top-right\" },\n ],\n\n // ellipse: 15\u00B0 cardinal points, 75\u00B0 diagonals\n ellipse: [\n { centerAngle: 0, sectorWidth: 15, side: \"right\" },\n { centerAngle: 45, sectorWidth: 75, side: \"bottom-right\" },\n { centerAngle: 90, sectorWidth: 15, side: \"bottom\" },\n { centerAngle: 135, sectorWidth: 75, side: \"bottom-left\" },\n { centerAngle: 180, sectorWidth: 15, side: \"left\" },\n { centerAngle: 225, sectorWidth: 75, side: \"top-left\" },\n { centerAngle: 270, sectorWidth: 15, side: \"top\" },\n { centerAngle: 315, sectorWidth: 75, side: \"top-right\" },\n ],\n};\n\nconst getSectorBoundaries = (\n config: SectorConfig[],\n): Array<{ start: number; end: number; side: Side }> => {\n return config.map((sector, index) => {\n const halfWidth = sector.sectorWidth / 2;\n let start = sector.centerAngle - halfWidth;\n let end = sector.centerAngle + halfWidth;\n\n // normalize angles to [0, 360) range\n start = ((start % 360) + 360) % 360;\n end = ((end % 360) + 360) % 360;\n\n return { start, end, side: sector.side };\n });\n};\n\n// determine which side a point falls into using adaptive sectors\nconst getShapeSideAdaptive = (\n fixedPoint: FixedPoint,\n shapeType: ShapeType,\n): Side => {\n const [x, y] = fixedPoint;\n\n // convert to centered coordinates\n const centerX = x - 0.5;\n const centerY = y - 0.5;\n\n // calculate angle\n let angle = Math.atan2(centerY, centerX);\n if (angle < 0) {\n angle += 2 * Math.PI;\n }\n const degrees = (angle * 180) / Math.PI;\n\n // get sector configuration for this shape type\n const config = SHAPE_CONFIGS[shapeType];\n const boundaries = getSectorBoundaries(config);\n\n // find which sector the angle falls into\n for (const boundary of boundaries) {\n if (boundary.start <= boundary.end) {\n // Normal case: sector doesn't cross 0\u00B0\n if (degrees >= boundary.start && degrees <= boundary.end) {\n return boundary.side;\n }\n } else if (degrees >= boundary.start || degrees <= boundary.end) {\n return boundary.side;\n }\n }\n\n // fallback - find nearest sector center\n let minDiff = Infinity;\n let nearestSide = config[0].side;\n\n for (const sector of config) {\n let diff = Math.abs(degrees - sector.centerAngle);\n // handle wraparound\n if (diff > 180) {\n diff = 360 - diff;\n }\n\n if (diff < minDiff) {\n minDiff = diff;\n nearestSide = sector.side;\n }\n }\n\n return nearestSide;\n};\n\nexport const getBindingSideMidPoint = (\n binding: FixedPointBinding,\n elementsMap: ElementsMap,\n) => {\n const bindableElement = elementsMap.get(binding.elementId);\n if (\n !bindableElement ||\n bindableElement.isDeleted ||\n !isBindableElement(bindableElement)\n ) {\n return null;\n }\n\n const center = elementCenterPoint(bindableElement, elementsMap);\n const shapeType = getShapeType(bindableElement);\n const side = getShapeSideAdaptive(\n normalizeFixedPoint(binding.fixedPoint),\n shapeType,\n );\n\n // small offset to avoid precision issues in elbow\n const OFFSET = 0.01;\n\n if (bindableElement.type === \"diamond\") {\n const [sides, corners] = deconstructDiamondElement(bindableElement);\n const [bottomRight, bottomLeft, topLeft, topRight] = sides;\n\n let x: number;\n let y: number;\n switch (side) {\n case \"left\": {\n // left vertex - use the center of the left corner curve\n if (corners.length >= 3) {\n const leftCorner = corners[2];\n const midPoint = leftCorner[1];\n x = midPoint[0] - OFFSET;\n y = midPoint[1];\n } else {\n // fallback for non-rounded diamond\n const midPoint = getMidPoint(bottomLeft[1], topLeft[0]);\n x = midPoint[0] - OFFSET;\n y = midPoint[1];\n }\n break;\n }\n case \"right\": {\n if (corners.length >= 1) {\n const rightCorner = corners[0];\n const midPoint = rightCorner[1];\n x = midPoint[0] + OFFSET;\n y = midPoint[1];\n } else {\n const midPoint = getMidPoint(topRight[1], bottomRight[0]);\n x = midPoint[0] + OFFSET;\n y = midPoint[1];\n }\n break;\n }\n case \"top\": {\n if (corners.length >= 4) {\n const topCorner = corners[3];\n const midPoint = topCorner[1];\n x = midPoint[0];\n y = midPoint[1] - OFFSET;\n } else {\n const midPoint = getMidPoint(topLeft[1], topRight[0]);\n x = midPoint[0];\n y = midPoint[1] - OFFSET;\n }\n break;\n }\n case \"bottom\": {\n if (corners.length >= 2) {\n const bottomCorner = corners[1];\n const midPoint = bottomCorner[1];\n x = midPoint[0];\n y = midPoint[1] + OFFSET;\n } else {\n const midPoint = getMidPoint(bottomRight[1], bottomLeft[0]);\n x = midPoint[0];\n y = midPoint[1] + OFFSET;\n }\n break;\n }\n case \"top-right\": {\n const midPoint = getMidPoint(topRight[0], topRight[1]);\n\n x = midPoint[0] + OFFSET * 0.707;\n y = midPoint[1] - OFFSET * 0.707;\n break;\n }\n case \"bottom-right\": {\n const midPoint = getMidPoint(bottomRight[0], bottomRight[1]);\n\n x = midPoint[0] + OFFSET * 0.707;\n y = midPoint[1] + OFFSET * 0.707;\n break;\n }\n case \"bottom-left\": {\n const midPoint = getMidPoint(bottomLeft[0], bottomLeft[1]);\n x = midPoint[0] - OFFSET * 0.707;\n y = midPoint[1] + OFFSET * 0.707;\n break;\n }\n case \"top-left\": {\n const midPoint = getMidPoint(topLeft[0], topLeft[1]);\n x = midPoint[0] - OFFSET * 0.707;\n y = midPoint[1] - OFFSET * 0.707;\n break;\n }\n default: {\n return null;\n }\n }\n\n return pointRotateRads(pointFrom(x, y), center, bindableElement.angle);\n }\n\n if (bindableElement.type === \"ellipse\") {\n const ellipseCenterX = bindableElement.x + bindableElement.width / 2;\n const ellipseCenterY = bindableElement.y + bindableElement.height / 2;\n const radiusX = bindableElement.width / 2;\n const radiusY = bindableElement.height / 2;\n\n let x: number;\n let y: number;\n\n switch (side) {\n case \"top\": {\n x = ellipseCenterX;\n y = ellipseCenterY - radiusY - OFFSET;\n break;\n }\n case \"right\": {\n x = ellipseCenterX + radiusX + OFFSET;\n y = ellipseCenterY;\n break;\n }\n case \"bottom\": {\n x = ellipseCenterX;\n y = ellipseCenterY + radiusY + OFFSET;\n break;\n }\n case \"left\": {\n x = ellipseCenterX - radiusX - OFFSET;\n y = ellipseCenterY;\n break;\n }\n case \"top-right\": {\n const angle = -Math.PI / 4;\n const ellipseX = radiusX * Math.cos(angle);\n const ellipseY = radiusY * Math.sin(angle);\n x = ellipseCenterX + ellipseX + OFFSET * 0.707;\n y = ellipseCenterY + ellipseY - OFFSET * 0.707;\n break;\n }\n case \"bottom-right\": {\n const angle = Math.PI / 4;\n const ellipseX = radiusX * Math.cos(angle);\n const ellipseY = radiusY * Math.sin(angle);\n x = ellipseCenterX + ellipseX + OFFSET * 0.707;\n y = ellipseCenterY + ellipseY + OFFSET * 0.707;\n break;\n }\n case \"bottom-left\": {\n const angle = (3 * Math.PI) / 4;\n const ellipseX = radiusX * Math.cos(angle);\n const ellipseY = radiusY * Math.sin(angle);\n x = ellipseCenterX + ellipseX - OFFSET * 0.707;\n y = ellipseCenterY + ellipseY + OFFSET * 0.707;\n break;\n }\n case \"top-left\": {\n const angle = (-3 * Math.PI) / 4;\n const ellipseX = radiusX * Math.cos(angle);\n const ellipseY = radiusY * Math.sin(angle);\n x = ellipseCenterX + ellipseX - OFFSET * 0.707;\n y = ellipseCenterY + ellipseY - OFFSET * 0.707;\n break;\n }\n default: {\n return null;\n }\n }\n\n return pointRotateRads(pointFrom(x, y), center, bindableElement.angle);\n }\n\n if (isRectangularElement(bindableElement)) {\n const [sides, corners] = deconstructRectanguloidElement(\n bindableElement as ExcalidrawRectanguloidElement,\n );\n const [top, right, bottom, left] = sides;\n\n let x: number;\n let y: number;\n switch (side) {\n case \"top\": {\n const midPoint = getMidPoint(top[0], top[1]);\n x = midPoint[0];\n y = midPoint[1] - OFFSET;\n break;\n }\n case \"right\": {\n const midPoint = getMidPoint(right[0], right[1]);\n x = midPoint[0] + OFFSET;\n y = midPoint[1];\n break;\n }\n case \"bottom\": {\n const midPoint = getMidPoint(bottom[0], bottom[1]);\n x = midPoint[0];\n y = midPoint[1] + OFFSET;\n break;\n }\n case \"left\": {\n const midPoint = getMidPoint(left[0], left[1]);\n x = midPoint[0] - OFFSET;\n y = midPoint[1];\n break;\n }\n case \"top-left\": {\n if (corners.length >= 1) {\n const corner = corners[0];\n\n const p1 = corner[0];\n const p2 = corner[3];\n const midPoint = getMidPoint(p1, p2);\n\n x = midPoint[0] - OFFSET * 0.707;\n y = midPoint[1] - OFFSET * 0.707;\n } else {\n x = bindableElement.x - OFFSET;\n y = bindableElement.y - OFFSET;\n }\n break;\n }\n case \"top-right\": {\n if (corners.length >= 2) {\n const corner = corners[1];\n const p1 = corner[0];\n const p2 = corner[3];\n const midPoint = getMidPoint(p1, p2);\n\n x = midPoint[0] + OFFSET * 0.707;\n y = midPoint[1] - OFFSET * 0.707;\n } else {\n x = bindableElement.x + bindableElement.width + OFFSET;\n y = bindableElement.y - OFFSET;\n }\n break;\n }\n case \"bottom-right\": {\n if (corners.length >= 3) {\n const corner = corners[2];\n const p1 = corner[0];\n const p2 = corner[3];\n const midPoint = getMidPoint(p1, p2);\n\n x = midPoint[0] + OFFSET * 0.707;\n y = midPoint[1] + OFFSET * 0.707;\n } else {\n x = bindableElement.x + bindableElement.width + OFFSET;\n y = bindableElement.y + bindableElement.height + OFFSET;\n }\n break;\n }\n case \"bottom-left\": {\n if (corners.length >= 4) {\n const corner = corners[3];\n const p1 = corner[0];\n const p2 = corner[3];\n const midPoint = getMidPoint(p1, p2);\n\n x = midPoint[0] - OFFSET * 0.707;\n y = midPoint[1] + OFFSET * 0.707;\n } else {\n x = bindableElement.x - OFFSET;\n y = bindableElement.y + bindableElement.height + OFFSET;\n }\n break;\n }\n default: {\n return null;\n }\n }\n\n return pointRotateRads(pointFrom(x, y), center, bindableElement.angle);\n }\n\n return null;\n};\n\nconst getMidPoint = (p1: GlobalPoint, p2: GlobalPoint): GlobalPoint => {\n return pointFrom((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2);\n};\n", "import {\n pointCenter,\n pointFrom,\n pointRotateRads,\n pointsEqual,\n type GlobalPoint,\n type LocalPoint,\n pointDistance,\n vectorFromPoint,\n curveLength,\n curvePointAtLength,\n lineSegment,\n} from \"@excalidraw/math\";\n\nimport { getCurvePathOps } from \"@excalidraw/utils/shape\";\n\nimport {\n DRAGGING_THRESHOLD,\n KEYS,\n shouldRotateWithDiscreteAngle,\n getGridPoint,\n invariant,\n isShallowEqual,\n getFeatureFlag,\n} from \"@excalidraw/common\";\n\nimport {\n deconstructLinearOrFreeDrawElement,\n isPathALoop,\n moveArrowAboveBindable,\n projectFixedPointOntoDiagonal,\n type Store,\n} from \"@excalidraw/element\";\n\nimport type { Radians } from \"@excalidraw/math\";\n\nimport type {\n AppState,\n PointerCoords,\n InteractiveCanvasAppState,\n AppClassProperties,\n NullableGridSize,\n Zoom,\n} from \"@excalidraw/excalidraw/types\";\nimport type { Bounds } from \"@excalidraw/common\";\n\nimport {\n calculateFixedPointForNonElbowArrowBinding,\n getBindingStrategyForDraggingBindingElementEndpoints,\n isBindingEnabled,\n updateBoundPoint,\n} from \"./binding\";\nimport {\n getElementAbsoluteCoords,\n getElementPointsCoords,\n getMinMaxXYFromCurvePathOps,\n} from \"./bounds\";\n\nimport { headingIsHorizontal, vectorToHeading } from \"./heading\";\nimport { mutateElement } from \"./mutateElement\";\nimport { getBoundTextElement, handleBindTextResize } from \"./textElement\";\nimport { isArrowElement, isBindingElement, isElbowArrow } from \"./typeChecks\";\n\nimport { ShapeCache, toggleLinePolygonState } from \"./shape\";\n\nimport { getLockedLinearCursorAlignSize } from \"./sizeHelpers\";\n\nimport { isLineElement } from \"./typeChecks\";\n\nimport type { Scene } from \"./Scene\";\n\nimport type {\n NonDeleted,\n ExcalidrawLinearElement,\n ExcalidrawElement,\n ExcalidrawTextElementWithContainer,\n ElementsMap,\n NonDeletedSceneElementsMap,\n FixedPointBinding,\n FixedSegment,\n ExcalidrawElbowArrowElement,\n PointsPositionUpdates,\n NonDeletedExcalidrawElement,\n Ordered,\n ExcalidrawBindableElement,\n} from \"./types\";\n\n/**\n * Normalizes line points so that the start point is at [0,0]. This is\n * expected in various parts of the codebase.\n *\n * Also returns the offsets - [0,0] if no normalization needed.\n *\n * @private\n */\nconst getNormalizedPoints = ({\n points,\n}: {\n points: ExcalidrawLinearElement[\"points\"];\n}): {\n points: LocalPoint[];\n offsetX: number;\n offsetY: number;\n} => {\n const offsetX = points[0][0];\n const offsetY = points[0][1];\n\n return {\n points: points.map((p) => {\n return pointFrom(p[0] - offsetX, p[1] - offsetY);\n }),\n offsetX,\n offsetY,\n };\n};\n\ntype PointMoveOtherUpdates = {\n startBinding?: FixedPointBinding | null;\n endBinding?: FixedPointBinding | null;\n moveMidPointsWithElement?: boolean | null;\n suggestedBinding?: AppState[\"suggestedBinding\"] | null;\n};\n\nexport class LinearElementEditor {\n public readonly elementId: ExcalidrawElement[\"id\"] & {\n _brand: \"excalidrawLinearElementId\";\n };\n /** indices */\n public readonly selectedPointsIndices: readonly number[] | null;\n\n public readonly initialState: Readonly<{\n prevSelectedPointsIndices: readonly number[] | null;\n /** index */\n lastClickedPoint: number;\n origin: Readonly<GlobalPoint> | null;\n segmentMidpoint: {\n value: GlobalPoint | null;\n index: number | null;\n added: boolean;\n };\n arrowStartIsInside: boolean;\n altFocusPoint: Readonly<GlobalPoint> | null;\n }>;\n\n /** whether you're dragging a point */\n public readonly isDragging: boolean;\n public readonly lastUncommittedPoint: LocalPoint | null;\n public readonly lastCommittedPoint: LocalPoint | null;\n public readonly pointerOffset: Readonly<{ x: number; y: number }>;\n public readonly hoverPointIndex: number;\n public readonly segmentMidPointHoveredCoords: GlobalPoint | null;\n public readonly elbowed: boolean;\n public readonly customLineAngle: number | null;\n public readonly isEditing: boolean;\n\n // @deprecated renamed to initialState because the data is used during linear\n // element click creation as well (with multiple pointer down events)\n // @ts-ignore\n public readonly pointerDownState: never;\n\n constructor(\n element: NonDeleted<ExcalidrawLinearElement>,\n elementsMap: ElementsMap,\n isEditing: boolean = false,\n ) {\n this.elementId = element.id as string & {\n _brand: \"excalidrawLinearElementId\";\n };\n if (!pointsEqual(element.points[0], pointFrom(0, 0))) {\n console.error(\"Linear element is not normalized\", Error().stack);\n mutateElement(\n element,\n elementsMap,\n LinearElementEditor.getNormalizeElementPointsAndCoords(element),\n );\n }\n this.selectedPointsIndices = null;\n this.lastUncommittedPoint = null;\n this.lastCommittedPoint = null;\n this.isDragging = false;\n this.pointerOffset = { x: 0, y: 0 };\n this.initialState = {\n prevSelectedPointsIndices: null,\n lastClickedPoint: -1,\n origin: null,\n\n segmentMidpoint: {\n value: null,\n index: null,\n added: false,\n },\n arrowStartIsInside: false,\n altFocusPoint: null,\n };\n this.hoverPointIndex = -1;\n this.segmentMidPointHoveredCoords = null;\n this.elbowed = isElbowArrow(element) && element.elbowed;\n this.customLineAngle = null;\n this.isEditing = isEditing;\n }\n\n // ---------------------------------------------------------------------------\n // static methods\n // ---------------------------------------------------------------------------\n\n static POINT_HANDLE_SIZE = 10;\n\n /**\n * @param id the `elementId` from the instance of this class (so that we can\n * statically guarantee this method returns an ExcalidrawLinearElement)\n */\n static getElement<T extends ExcalidrawLinearElement>(\n id: InstanceType<typeof LinearElementEditor>[\"elementId\"],\n elementsMap: ElementsMap,\n ): T | null {\n const element = elementsMap.get(id);\n if (element) {\n return element as NonDeleted<T>;\n }\n return null;\n }\n\n static handleBoxSelection(\n event: PointerEvent,\n appState: AppState,\n setState: React.Component<any, AppState>[\"setState\"],\n elementsMap: NonDeletedSceneElementsMap,\n ) {\n if (\n !appState.selectedLinearElement?.isEditing ||\n !appState.selectionElement\n ) {\n return false;\n }\n const { selectedLinearElement } = appState;\n const { selectedPointsIndices, elementId } = selectedLinearElement;\n\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n if (!element) {\n return false;\n }\n\n const [selectionX1, selectionY1, selectionX2, selectionY2] =\n getElementAbsoluteCoords(appState.selectionElement, elementsMap);\n\n const pointsSceneCoords = LinearElementEditor.getPointsGlobalCoordinates(\n element,\n elementsMap,\n );\n\n const nextSelectedPoints = pointsSceneCoords\n .reduce((acc: number[], point, index) => {\n if (\n (point[0] >= selectionX1 &&\n point[0] <= selectionX2 &&\n point[1] >= selectionY1 &&\n point[1] <= selectionY2) ||\n (event.shiftKey && selectedPointsIndices?.includes(index))\n ) {\n acc.push(index);\n }\n\n return acc;\n }, [])\n .filter((index) => {\n if (\n isElbowArrow(element) &&\n index !== 0 &&\n index !== element.points.length - 1\n ) {\n return false;\n }\n return true;\n });\n\n setState({\n selectedLinearElement: {\n ...selectedLinearElement,\n selectedPointsIndices: nextSelectedPoints.length\n ? nextSelectedPoints\n : null,\n },\n });\n }\n\n static handlePointerMove(\n event: PointerEvent,\n app: AppClassProperties,\n scenePointerX: number,\n scenePointerY: number,\n linearElementEditor: LinearElementEditor,\n ): Pick<AppState, \"suggestedBinding\" | \"selectedLinearElement\"> | null {\n const elementsMap = app.scene.getNonDeletedElementsMap();\n const elements = app.scene.getNonDeletedElements();\n const { elementId } = linearElementEditor;\n\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n\n invariant(element, \"Element being dragged must exist in the scene\");\n invariant(element.points.length > 1, \"Element must have at least 2 points\");\n\n const idx = element.points.length - 1;\n const point = element.points[idx];\n const pivotPoint = element.points[idx - 1];\n const customLineAngle =\n linearElementEditor.customLineAngle ??\n determineCustomLinearAngle(pivotPoint, element.points[idx]);\n\n // Determine if point movement should happen and how much\n let deltaX = 0;\n let deltaY = 0;\n if (shouldRotateWithDiscreteAngle(event)) {\n const [width, height] = LinearElementEditor._getShiftLockedDelta(\n element,\n elementsMap,\n pivotPoint,\n pointFrom(scenePointerX, scenePointerY),\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\n customLineAngle,\n );\n const target = pointFrom<LocalPoint>(\n width + pivotPoint[0],\n height + pivotPoint[1],\n );\n\n deltaX = target[0] - point[0];\n deltaY = target[1] - point[1];\n } else {\n const newDraggingPointPosition = LinearElementEditor.createPointAt(\n element,\n elementsMap,\n scenePointerX - linearElementEditor.pointerOffset.x,\n scenePointerY - linearElementEditor.pointerOffset.y,\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\n );\n deltaX = newDraggingPointPosition[0] - point[0];\n deltaY = newDraggingPointPosition[1] - point[1];\n }\n\n // Apply the point movement if needed\n let suggestedBinding: AppState[\"suggestedBinding\"] = null;\n const { positions, updates } = pointDraggingUpdates(\n [idx],\n deltaX,\n deltaY,\n scenePointerX,\n scenePointerY,\n elementsMap,\n element,\n elements,\n app,\n shouldRotateWithDiscreteAngle(event),\n event.altKey,\n );\n\n LinearElementEditor.movePoints(element, app.scene, positions, {\n startBinding: updates?.startBinding,\n endBinding: updates?.endBinding,\n moveMidPointsWithElement: updates?.moveMidPointsWithElement,\n });\n // Set the suggested binding from the updates if available\n if (isBindingElement(element, false)) {\n if (isBindingEnabled(app.state)) {\n suggestedBinding = updates?.suggestedBinding ?? null;\n }\n }\n\n // Move the arrow over the bindable object in terms of z-index\n if (isBindingElement(element)) {\n moveArrowAboveBindable(\n LinearElementEditor.getPointGlobalCoordinates(\n element,\n element.points[element.points.length - 1],\n elementsMap,\n ),\n element,\n elements,\n elementsMap,\n app.scene,\n );\n }\n\n // PERF: Avoid state updates if not absolutely necessary\n if (\n app.state.selectedLinearElement?.customLineAngle === customLineAngle &&\n linearElementEditor.initialState.altFocusPoint &&\n (!suggestedBinding ||\n isShallowEqual(app.state.suggestedBinding ?? [], suggestedBinding))\n ) {\n return null;\n }\n\n const startBindingElement =\n isBindingElement(element) &&\n element.startBinding &&\n (elementsMap.get(\n element.startBinding.elementId,\n ) as ExcalidrawBindableElement | null);\n const newLinearElementEditor = {\n ...linearElementEditor,\n customLineAngle,\n initialState: {\n ...linearElementEditor.initialState,\n altFocusPoint:\n !linearElementEditor.initialState.altFocusPoint &&\n startBindingElement &&\n updates?.suggestedBinding?.id !== startBindingElement.id\n ? projectFixedPointOntoDiagonal(\n element,\n pointFrom<GlobalPoint>(element.x, element.y),\n startBindingElement,\n \"start\",\n elementsMap,\n )\n : linearElementEditor.initialState.altFocusPoint,\n },\n };\n\n return {\n selectedLinearElement: newLinearElementEditor,\n suggestedBinding,\n };\n }\n\n static handlePointDragging(\n event: PointerEvent,\n app: AppClassProperties,\n scenePointerX: number,\n scenePointerY: number,\n linearElementEditor: LinearElementEditor,\n ): Pick<AppState, \"suggestedBinding\" | \"selectedLinearElement\"> | null {\n const elementsMap = app.scene.getNonDeletedElementsMap();\n const elements = app.scene.getNonDeletedElements();\n const { elbowed, elementId, initialState } = linearElementEditor;\n const selectedPointsIndices = Array.from(\n linearElementEditor.selectedPointsIndices ?? [],\n );\n let { lastClickedPoint } = initialState;\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n\n invariant(element, \"Element being dragged must exist in the scene\");\n\n invariant(element.points.length > 1, \"Element must have at least 2 points\");\n\n invariant(\n selectedPointsIndices,\n \"There must be selected points in order to drag them\",\n );\n\n if (elbowed) {\n selectedPointsIndices.some((pointIdx, idx) => {\n if (pointIdx > 0 && pointIdx !== element.points.length - 1) {\n selectedPointsIndices[idx] = element.points.length - 1;\n lastClickedPoint = element.points.length - 1;\n return true;\n }\n\n return false;\n });\n }\n\n invariant(\n lastClickedPoint > -1 &&\n selectedPointsIndices.includes(lastClickedPoint) &&\n element.points[lastClickedPoint],\n `There must be a valid lastClickedPoint in order to drag it. selectedPointsIndices(${JSON.stringify(\n selectedPointsIndices,\n )}) points(0..${\n element.points.length - 1\n }) lastClickedPoint(${lastClickedPoint})`,\n );\n\n // point that's being dragged (out of all selected points)\n const draggingPoint = element.points[lastClickedPoint];\n // The adjacent point to the one dragged point\n const pivotPoint =\n element.points[lastClickedPoint === 0 ? 1 : lastClickedPoint - 1];\n const singlePointDragged = selectedPointsIndices.length === 1;\n const customLineAngle =\n linearElementEditor.customLineAngle ??\n determineCustomLinearAngle(pivotPoint, element.points[lastClickedPoint]);\n const startIsSelected = selectedPointsIndices.includes(0);\n const endIsSelected = selectedPointsIndices.includes(\n element.points.length - 1,\n );\n\n // Determine if point movement should happen and how much\n let deltaX = 0;\n let deltaY = 0;\n if (shouldRotateWithDiscreteAngle(event) && singlePointDragged) {\n const [width, height] = LinearElementEditor._getShiftLockedDelta(\n element,\n elementsMap,\n pivotPoint,\n pointFrom(scenePointerX, scenePointerY),\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\n customLineAngle,\n );\n const target = pointFrom<LocalPoint>(\n width + pivotPoint[0],\n height + pivotPoint[1],\n );\n deltaX = target[0] - draggingPoint[0];\n deltaY = target[1] - draggingPoint[1];\n } else {\n const newDraggingPointPosition = LinearElementEditor.createPointAt(\n element,\n elementsMap,\n scenePointerX - linearElementEditor.pointerOffset.x,\n scenePointerY - linearElementEditor.pointerOffset.y,\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\n );\n deltaX = newDraggingPointPosition[0] - draggingPoint[0];\n deltaY = newDraggingPointPosition[1] - draggingPoint[1];\n }\n\n // Apply the point movement if needed\n let suggestedBinding: AppState[\"suggestedBinding\"] = null;\n const { positions, updates } = pointDraggingUpdates(\n selectedPointsIndices,\n deltaX,\n deltaY,\n scenePointerX,\n scenePointerY,\n elementsMap,\n element,\n elements,\n app,\n shouldRotateWithDiscreteAngle(event) && singlePointDragged,\n event.altKey,\n );\n\n LinearElementEditor.movePoints(element, app.scene, positions, {\n startBinding: updates?.startBinding,\n endBinding: updates?.endBinding,\n moveMidPointsWithElement: updates?.moveMidPointsWithElement,\n });\n\n // Set the suggested binding from the updates if available\n if (isBindingElement(element, false)) {\n if (isBindingEnabled(app.state) && (startIsSelected || endIsSelected)) {\n suggestedBinding = updates?.suggestedBinding ?? null;\n }\n }\n\n // Move the arrow over the bindable object in terms of z-index\n if (isBindingElement(element) && startIsSelected !== endIsSelected) {\n moveArrowAboveBindable(\n LinearElementEditor.getPointGlobalCoordinates(\n element,\n startIsSelected\n ? element.points[0]\n : element.points[element.points.length - 1],\n elementsMap,\n ),\n element,\n elements,\n elementsMap,\n app.scene,\n );\n }\n\n // Attached text might need to update if arrow dimensions change\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (boundTextElement) {\n handleBindTextResize(element, app.scene, false);\n }\n\n // Update selected points for elbow arrows because elbow arrows add and\n // remove points as they route\n const newSelectedPointsIndices = elbowed\n ? endIsSelected\n ? [element.points.length - 1]\n : [0]\n : selectedPointsIndices;\n\n const newLastClickedPoint = elbowed\n ? newSelectedPointsIndices[0]\n : lastClickedPoint;\n\n const newSelectedMidPointHoveredCoords =\n !startIsSelected && !endIsSelected\n ? LinearElementEditor.getPointGlobalCoordinates(\n element,\n draggingPoint,\n elementsMap,\n )\n : null;\n\n const newHoverPointIndex = newLastClickedPoint;\n const startBindingElement =\n isBindingElement(element) &&\n element.startBinding &&\n (elementsMap.get(\n element.startBinding.elementId,\n ) as ExcalidrawBindableElement | null);\n const endBindingElement =\n isBindingElement(element) &&\n element.endBinding &&\n (elementsMap.get(\n element.endBinding.elementId,\n ) as ExcalidrawBindableElement | null);\n const altFocusPointBindableElement =\n endIsSelected && // The \"other\" end (i.e. \"end\") is dragged\n startBindingElement &&\n updates?.suggestedBinding?.id !== startBindingElement.id // The end point is not hovering the start bindable + it's binding gap\n ? startBindingElement\n : startIsSelected && // The \"other\" end (i.e. \"start\") is dragged\n endBindingElement &&\n updates?.suggestedBinding?.id !== endBindingElement.id // The start point is not hovering the end bindable + it's binding gap\n ? endBindingElement\n : null;\n\n const newLinearElementEditor: LinearElementEditor = {\n ...linearElementEditor,\n selectedPointsIndices: newSelectedPointsIndices,\n initialState: {\n ...linearElementEditor.initialState,\n lastClickedPoint: newLastClickedPoint,\n altFocusPoint:\n !linearElementEditor.initialState.altFocusPoint && // We only set it once per arrow drag\n isBindingElement(element) &&\n altFocusPointBindableElement\n ? projectFixedPointOntoDiagonal(\n element,\n pointFrom<GlobalPoint>(element.x, element.y),\n altFocusPointBindableElement,\n \"start\",\n elementsMap,\n )\n : linearElementEditor.initialState.altFocusPoint,\n },\n segmentMidPointHoveredCoords: newSelectedMidPointHoveredCoords,\n hoverPointIndex: newHoverPointIndex,\n isDragging: true,\n customLineAngle,\n };\n\n return {\n selectedLinearElement: newLinearElementEditor,\n suggestedBinding,\n };\n }\n\n static handlePointerUp(\n event: PointerEvent,\n editingLinearElement: LinearElementEditor,\n appState: AppState,\n scene: Scene,\n ): LinearElementEditor {\n const elementsMap = scene.getNonDeletedElementsMap();\n\n const {\n elementId,\n selectedPointsIndices,\n isDragging,\n initialState: pointerDownState,\n } = editingLinearElement;\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n if (!element) {\n return editingLinearElement;\n }\n\n if (isDragging && selectedPointsIndices) {\n for (const selectedPoint of selectedPointsIndices) {\n if (\n selectedPoint === 0 ||\n selectedPoint === element.points.length - 1\n ) {\n if (isPathALoop(element.points, appState.zoom.value)) {\n if (isLineElement(element)) {\n scene.mutateElement(\n element,\n {\n ...toggleLinePolygonState(element, true),\n },\n {\n informMutation: false,\n isDragging: false,\n },\n );\n }\n LinearElementEditor.movePoints(\n element,\n scene,\n new Map([\n [\n selectedPoint,\n {\n point:\n selectedPoint === 0\n ? element.points[element.points.length - 1]\n : element.points[0],\n },\n ],\n ]),\n );\n }\n }\n }\n }\n\n return {\n ...editingLinearElement,\n segmentMidPointHoveredCoords: null,\n hoverPointIndex: -1,\n // if clicking without previously dragging a point(s), and not holding\n // shift, deselect all points except the one clicked. If holding shift,\n // toggle the point.\n selectedPointsIndices:\n isDragging || event.shiftKey\n ? !isDragging &&\n event.shiftKey &&\n pointerDownState.prevSelectedPointsIndices?.includes(\n pointerDownState.lastClickedPoint,\n )\n ? selectedPointsIndices &&\n selectedPointsIndices.filter(\n (pointIndex) =>\n pointIndex !== pointerDownState.lastClickedPoint,\n )\n : selectedPointsIndices\n : selectedPointsIndices?.includes(pointerDownState.lastClickedPoint)\n ? [pointerDownState.lastClickedPoint]\n : selectedPointsIndices,\n isDragging: false,\n pointerOffset: { x: 0, y: 0 },\n customLineAngle: null,\n initialState: {\n ...editingLinearElement.initialState,\n origin: null,\n arrowStartIsInside: false,\n },\n };\n }\n\n static getEditorMidPoints = (\n element: NonDeleted<ExcalidrawLinearElement>,\n elementsMap: ElementsMap,\n appState: InteractiveCanvasAppState,\n ): (GlobalPoint | null)[] => {\n const boundText = getBoundTextElement(element, elementsMap);\n\n // Since its not needed outside editor unless 2 pointer lines or bound text\n if (\n !isElbowArrow(element) &&\n !appState.selectedLinearElement?.isEditing &&\n element.points.length > 2 &&\n !boundText\n ) {\n return [];\n }\n\n const points = LinearElementEditor.getPointsGlobalCoordinates(\n element,\n elementsMap,\n );\n\n let index = 0;\n const midpoints: (GlobalPoint | null)[] = [];\n while (index < points.length - 1) {\n if (\n LinearElementEditor.isSegmentTooShort(\n element,\n element.points[index],\n element.points[index + 1],\n index,\n appState.zoom,\n )\n ) {\n midpoints.push(null);\n index++;\n continue;\n }\n const segmentMidPoint = LinearElementEditor.getSegmentMidPoint(\n element,\n index + 1,\n );\n midpoints.push(segmentMidPoint);\n index++;\n }\n\n return midpoints;\n };\n\n static getSegmentMidpointHitCoords = (\n linearElementEditor: LinearElementEditor,\n scenePointer: { x: number; y: number },\n appState: AppState,\n elementsMap: ElementsMap,\n ): GlobalPoint | null => {\n const { elementId } = linearElementEditor;\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n if (!element) {\n return null;\n }\n const clickedPointIndex = LinearElementEditor.getPointIndexUnderCursor(\n element,\n elementsMap,\n appState.zoom,\n scenePointer.x,\n scenePointer.y,\n );\n if (!isElbowArrow(element) && clickedPointIndex >= 0) {\n return null;\n }\n const points = LinearElementEditor.getPointsGlobalCoordinates(\n element,\n elementsMap,\n );\n if (\n points.length >= 3 &&\n !appState.selectedLinearElement?.isEditing &&\n !isElbowArrow(element)\n ) {\n return null;\n }\n\n const threshold =\n (LinearElementEditor.POINT_HANDLE_SIZE + 1) / appState.zoom.value;\n\n const existingSegmentMidpointHitCoords =\n linearElementEditor.segmentMidPointHoveredCoords;\n if (existingSegmentMidpointHitCoords) {\n const distance = pointDistance(\n pointFrom(\n existingSegmentMidpointHitCoords[0],\n existingSegmentMidpointHitCoords[1],\n ),\n pointFrom(scenePointer.x, scenePointer.y),\n );\n if (distance <= threshold) {\n return existingSegmentMidpointHitCoords;\n }\n }\n let index = 0;\n const midPoints = LinearElementEditor.getEditorMidPoints(\n element,\n elementsMap,\n appState,\n );\n\n while (index < midPoints.length) {\n if (midPoints[index] !== null) {\n const distance = pointDistance(\n midPoints[index]!,\n pointFrom(scenePointer.x, scenePointer.y),\n );\n if (distance <= threshold) {\n return midPoints[index];\n }\n }\n\n index++;\n }\n return null;\n };\n\n static isSegmentTooShort<P extends GlobalPoint | LocalPoint>(\n element: NonDeleted<ExcalidrawLinearElement>,\n startPoint: P,\n endPoint: P,\n index: number,\n zoom: Zoom,\n ) {\n if (isElbowArrow(element)) {\n if (index >= 0 && index < element.points.length) {\n return (\n pointDistance(startPoint, endPoint) * zoom.value <\n LinearElementEditor.POINT_HANDLE_SIZE / 2\n );\n }\n\n return false;\n }\n\n let distance = pointDistance(startPoint, endPoint);\n if (element.points.length > 2 && element.roundness) {\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\n\n invariant(\n lines.length === 0 && curves.length > 0,\n \"Only linears built out of curves are supported\",\n );\n invariant(\n lines.length + curves.length >= index,\n \"Invalid segment index while calculating mid point\",\n );\n\n distance = curveLength<GlobalPoint>(curves[index]);\n }\n\n return distance * zoom.value < LinearElementEditor.POINT_HANDLE_SIZE * 4;\n }\n\n static getSegmentMidPoint(\n element: NonDeleted<ExcalidrawLinearElement>,\n index: number,\n ): GlobalPoint {\n if (isElbowArrow(element)) {\n invariant(\n element.points.length >= index,\n \"Invalid segment index while calculating elbow arrow mid point\",\n );\n\n const p = pointCenter(element.points[index - 1], element.points[index]);\n\n return pointFrom<GlobalPoint>(element.x + p[0], element.y + p[1]);\n }\n\n const [lines, curves] = deconstructLinearOrFreeDrawElement(element);\n\n invariant(\n (lines.length === 0 && curves.length > 0) ||\n (lines.length > 0 && curves.length === 0),\n \"Only linears built out of either segments or curves are supported\",\n );\n invariant(\n lines.length + curves.length >= index,\n \"Invalid segment index while calculating mid point\",\n );\n\n if (lines.length) {\n const segment = lines[index - 1];\n return pointCenter(segment[0], segment[1]);\n }\n\n if (curves.length) {\n const segment = curves[index - 1];\n return curvePointAtLength(segment, 0.5);\n }\n\n invariant(false, \"Invalid segment type while calculating mid point\");\n }\n\n static getSegmentMidPointIndex(\n linearElementEditor: LinearElementEditor,\n appState: AppState,\n midPoint: GlobalPoint,\n elementsMap: ElementsMap,\n ) {\n const element = LinearElementEditor.getElement(\n linearElementEditor.elementId,\n elementsMap,\n );\n if (!element) {\n return -1;\n }\n const midPoints = LinearElementEditor.getEditorMidPoints(\n element,\n elementsMap,\n appState,\n );\n let index = 0;\n while (index < midPoints.length) {\n if (LinearElementEditor.arePointsEqual(midPoint, midPoints[index])) {\n return index + 1;\n }\n index++;\n }\n return -1;\n }\n\n static handlePointerDown(\n event: React.PointerEvent<HTMLElement>,\n app: AppClassProperties,\n store: Store,\n scenePointer: { x: number; y: number },\n linearElementEditor: LinearElementEditor,\n scene: Scene,\n ): {\n didAddPoint: boolean;\n hitElement: NonDeleted<ExcalidrawElement> | null;\n linearElementEditor: LinearElementEditor | null;\n } {\n const appState = app.state;\n const elementsMap = scene.getNonDeletedElementsMap();\n\n const ret: ReturnType<typeof LinearElementEditor[\"handlePointerDown\"]> = {\n didAddPoint: false,\n hitElement: null,\n linearElementEditor: null,\n };\n\n if (!linearElementEditor) {\n return ret;\n }\n\n const { elementId } = linearElementEditor;\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n\n if (!element) {\n return ret;\n }\n\n const segmentMidpoint = LinearElementEditor.getSegmentMidpointHitCoords(\n linearElementEditor,\n scenePointer,\n appState,\n elementsMap,\n );\n const point = pointFrom<GlobalPoint>(scenePointer.x, scenePointer.y);\n let segmentMidpointIndex = null;\n\n if (segmentMidpoint) {\n segmentMidpointIndex = LinearElementEditor.getSegmentMidPointIndex(\n linearElementEditor,\n appState,\n segmentMidpoint,\n elementsMap,\n );\n } else if (event.altKey && appState.selectedLinearElement?.isEditing) {\n if (linearElementEditor.lastUncommittedPoint == null) {\n scene.mutateElement(element, {\n points: [\n ...element.points,\n LinearElementEditor.createPointAt(\n element,\n elementsMap,\n scenePointer.x,\n scenePointer.y,\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\n ),\n ],\n });\n ret.didAddPoint = true;\n }\n store.scheduleCapture();\n ret.linearElementEditor = {\n ...linearElementEditor,\n initialState: {\n prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices,\n lastClickedPoint: -1,\n origin: point,\n segmentMidpoint: {\n value: segmentMidpoint,\n index: segmentMidpointIndex,\n added: false,\n },\n arrowStartIsInside:\n !!app.state.newElement &&\n (app.state.bindMode === \"inside\" || app.state.bindMode === \"skip\"),\n altFocusPoint: null,\n },\n selectedPointsIndices: [element.points.length - 1],\n lastUncommittedPoint: null,\n };\n\n ret.didAddPoint = true;\n\n return ret;\n }\n\n const clickedPointIndex = LinearElementEditor.getPointIndexUnderCursor(\n element,\n elementsMap,\n appState.zoom,\n scenePointer.x,\n scenePointer.y,\n );\n // if we clicked on a point, set the element as hitElement otherwise\n // it would get deselected if the point is outside the hitbox area\n if (clickedPointIndex >= 0 || segmentMidpoint) {\n ret.hitElement = element;\n }\n\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const targetPoint =\n clickedPointIndex > -1 &&\n pointRotateRads(\n pointFrom(\n element.x + element.points[clickedPointIndex][0],\n element.y + element.points[clickedPointIndex][1],\n ),\n pointFrom(cx, cy),\n element.angle,\n );\n\n const nextSelectedPointsIndices =\n clickedPointIndex > -1 || event.shiftKey\n ? event.shiftKey ||\n linearElementEditor.selectedPointsIndices?.includes(clickedPointIndex)\n ? normalizeSelectedPoints([\n ...(linearElementEditor.selectedPointsIndices || []),\n clickedPointIndex,\n ])\n : [clickedPointIndex]\n : null;\n ret.linearElementEditor = {\n ...linearElementEditor,\n initialState: {\n prevSelectedPointsIndices: linearElementEditor.selectedPointsIndices,\n lastClickedPoint: clickedPointIndex,\n origin: point,\n segmentMidpoint: {\n value: segmentMidpoint,\n index: segmentMidpointIndex,\n added: false,\n },\n arrowStartIsInside:\n !!app.state.newElement &&\n (app.state.bindMode === \"inside\" || app.state.bindMode === \"skip\"),\n altFocusPoint: null,\n },\n selectedPointsIndices: nextSelectedPointsIndices,\n pointerOffset: targetPoint\n ? {\n x: scenePointer.x - targetPoint[0],\n y: scenePointer.y - targetPoint[1],\n }\n : { x: 0, y: 0 },\n };\n\n return ret;\n }\n\n static arePointsEqual<Point extends LocalPoint | GlobalPoint>(\n point1: Point | null,\n point2: Point | null,\n ) {\n if (!point1 && !point2) {\n return true;\n }\n if (!point1 || !point2) {\n return false;\n }\n return pointsEqual(point1, point2);\n }\n\n static handlePointerMoveInEditMode(\n event: React.PointerEvent<HTMLCanvasElement>,\n scenePointerX: number,\n scenePointerY: number,\n app: AppClassProperties,\n ): LinearElementEditor | null {\n const appState = app.state;\n if (!appState.selectedLinearElement?.isEditing) {\n return null;\n }\n const { elementId, lastUncommittedPoint } = appState.selectedLinearElement;\n const elementsMap = app.scene.getNonDeletedElementsMap();\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n if (!element) {\n return appState.selectedLinearElement;\n }\n\n const { points } = element;\n const lastPoint = points[points.length - 1];\n\n if (!event.altKey) {\n if (lastPoint === lastUncommittedPoint) {\n LinearElementEditor.deletePoints(element, app, [points.length - 1]);\n }\n return appState.selectedLinearElement?.lastUncommittedPoint\n ? {\n ...appState.selectedLinearElement,\n lastUncommittedPoint: null,\n }\n : appState.selectedLinearElement;\n }\n\n let newPoint: LocalPoint;\n\n if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) {\n const anchor = points[points.length - 2];\n const [width, height] = LinearElementEditor._getShiftLockedDelta(\n element,\n elementsMap,\n anchor,\n pointFrom(scenePointerX, scenePointerY),\n event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),\n );\n\n newPoint = pointFrom(width + anchor[0], height + anchor[1]);\n } else {\n newPoint = LinearElementEditor.createPointAt(\n element,\n elementsMap,\n scenePointerX - appState.selectedLinearElement.pointerOffset.x,\n scenePointerY - appState.selectedLinearElement.pointerOffset.y,\n event[KEYS.CTRL_OR_CMD] || isElbowArrow(element)\n ? null\n : app.getEffectiveGridSize(),\n );\n }\n\n if (lastPoint === lastUncommittedPoint) {\n LinearElementEditor.movePoints(\n element,\n app.scene,\n new Map([\n [\n element.points.length - 1,\n {\n point: newPoint,\n },\n ],\n ]),\n );\n } else {\n LinearElementEditor.addPoints(element, app.scene, [newPoint]);\n }\n return {\n ...appState.selectedLinearElement,\n lastUncommittedPoint: element.points[element.points.length - 1],\n };\n }\n\n /** scene coords */\n static getPointGlobalCoordinates(\n element: NonDeleted<ExcalidrawLinearElement>,\n p: LocalPoint,\n elementsMap: ElementsMap,\n ): GlobalPoint {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n\n const { x, y } = element;\n return pointRotateRads(\n pointFrom(x + p[0], y + p[1]),\n pointFrom(cx, cy),\n element.angle,\n );\n }\n\n /** scene coords */\n static getPointsGlobalCoordinates(\n element: NonDeleted<ExcalidrawLinearElement>,\n elementsMap: ElementsMap,\n ): GlobalPoint[] {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n return element.points.map((p) => {\n const { x, y } = element;\n return pointRotateRads(\n pointFrom(x + p[0], y + p[1]),\n pointFrom(cx, cy),\n element.angle,\n );\n });\n }\n\n static getPointAtIndexGlobalCoordinates(\n element: NonDeleted<ExcalidrawLinearElement>,\n indexMaybeFromEnd: number, // -1 for last element\n elementsMap: ElementsMap,\n ): GlobalPoint {\n const index =\n indexMaybeFromEnd < 0\n ? element.points.length + indexMaybeFromEnd\n : indexMaybeFromEnd;\n const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);\n const center = pointFrom<GlobalPoint>(cx, cy);\n const p = element.points[index];\n const { x, y } = element;\n\n return p\n ? pointRotateRads(\n pointFrom<GlobalPoint>(x + p[0], y + p[1]),\n center,\n element.angle,\n )\n : pointRotateRads(pointFrom<GlobalPoint>(x, y), center, element.angle);\n }\n\n static pointFromAbsoluteCoords(\n element: NonDeleted<ExcalidrawLinearElement>,\n absoluteCoords: GlobalPoint,\n elementsMap: ElementsMap,\n ): LocalPoint {\n if (isElbowArrow(element)) {\n // No rotation for elbow arrows\n return pointFrom(\n absoluteCoords[0] - element.x,\n absoluteCoords[1] - element.y,\n );\n }\n\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const [x, y] = pointRotateRads(\n pointFrom(absoluteCoords[0], absoluteCoords[1]),\n pointFrom(cx, cy),\n -element.angle as Radians,\n );\n return pointFrom(x - element.x, y - element.y);\n }\n\n static getPointIndexUnderCursor(\n element: NonDeleted<ExcalidrawLinearElement>,\n elementsMap: ElementsMap,\n zoom: AppState[\"zoom\"],\n x: number,\n y: number,\n ) {\n const pointHandles = LinearElementEditor.getPointsGlobalCoordinates(\n element,\n elementsMap,\n );\n let idx = pointHandles.length;\n // loop from right to left because points on the right are rendered over\n // points on the left, thus should take precedence when clicking, if they\n // overlap\n while (--idx > -1) {\n const p = pointHandles[idx];\n if (\n pointDistance(pointFrom(x, y), pointFrom(p[0], p[1])) * zoom.value <\n // +1px to account for outline stroke\n LinearElementEditor.POINT_HANDLE_SIZE + 1\n ) {\n return idx;\n }\n }\n return -1;\n }\n\n static createPointAt(\n element: NonDeleted<ExcalidrawLinearElement>,\n elementsMap: ElementsMap,\n scenePointerX: number,\n scenePointerY: number,\n gridSize: NullableGridSize,\n ): LocalPoint {\n const pointerOnGrid = getGridPoint(scenePointerX, scenePointerY, gridSize);\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const [rotatedX, rotatedY] = pointRotateRads(\n pointFrom(pointerOnGrid[0], pointerOnGrid[1]),\n pointFrom(cx, cy),\n -element.angle as Radians,\n );\n\n return pointFrom(rotatedX - element.x, rotatedY - element.y);\n }\n\n /**\n * Normalizes line points so that the start point is at [0,0]. This is\n * expected in various parts of the codebase.\n *\n * Also returns normalized x and y coords to account for the normalization\n * of the points.\n */\n static getNormalizeElementPointsAndCoords(element: ExcalidrawLinearElement) {\n const { points, offsetX, offsetY } = getNormalizedPoints(element);\n\n return {\n points,\n x: element.x + offsetX,\n y: element.y + offsetY,\n };\n }\n\n // element-mutating methods\n // ---------------------------------------------------------------------------\n static duplicateSelectedPoints(appState: AppState, scene: Scene): AppState {\n invariant(\n appState.selectedLinearElement?.isEditing,\n \"Not currently editing a linear element\",\n );\n\n const elementsMap = scene.getNonDeletedElementsMap();\n const { selectedPointsIndices, elementId } = appState.selectedLinearElement;\n const element = LinearElementEditor.getElement(elementId, elementsMap);\n\n invariant(\n element,\n \"The linear element does not exist in the provided Scene\",\n );\n invariant(\n selectedPointsIndices != null,\n \"There are no selected points to duplicate\",\n );\n\n const { points } = element;\n\n const nextSelectedIndices: number[] = [];\n\n let pointAddedToEnd = false;\n let indexCursor = -1;\n const nextPoints = points.reduce((acc: LocalPoint[], p, index) => {\n ++indexCursor;\n acc.push(p);\n\n const isSelected = selectedPointsIndices.includes(index);\n if (isSelected) {\n const nextPoint = points[index + 1];\n\n if (!nextPoint) {\n pointAddedToEnd = true;\n }\n acc.push(\n nextPoint\n ? pointFrom((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2)\n : pointFrom(p[0], p[1]),\n );\n\n nextSelectedIndices.push(indexCursor + 1);\n ++indexCursor;\n }\n\n return acc;\n }, []);\n\n scene.mutateElement(element, { points: nextPoints });\n\n // temp hack to ensure the line doesn't move when adding point to the end,\n // potentially expanding the bounding box\n if (pointAddedToEnd) {\n const lastPoint = element.points[element.points.length - 1];\n LinearElementEditor.movePoints(\n element,\n scene,\n new Map([\n [\n element.points.length - 1,\n { point: pointFrom(lastPoint[0] + 30, lastPoint[1] + 30) },\n ],\n ]),\n );\n }\n\n return {\n ...appState,\n selectedLinearElement: {\n ...appState.selectedLinearElement,\n selectedPointsIndices: nextSelectedIndices,\n },\n };\n }\n\n static deletePoints(\n element: NonDeleted<ExcalidrawLinearElement>,\n app: AppClassProperties,\n pointIndices: readonly number[],\n ) {\n const isUncommittedPoint =\n app.state.selectedLinearElement?.isEditing &&\n app.state.selectedLinearElement?.lastUncommittedPoint ===\n element.points[element.points.length - 1];\n\n const nextPoints = element.points.filter((_, idx) => {\n return !pointIndices.includes(idx);\n });\n\n const isPolygon = isLineElement(element) && element.polygon;\n\n // keep polygon intact if deleting start/end point or uncommitted point\n if (\n isPolygon &&\n (isUncommittedPoint ||\n pointIndices.includes(0) ||\n pointIndices.includes(element.points.length - 1))\n ) {\n nextPoints[0] = pointFrom(\n nextPoints[nextPoints.length - 1][0],\n nextPoints[nextPoints.length - 1][1],\n );\n }\n\n const {\n points: normalizedPoints,\n offsetX,\n offsetY,\n } = getNormalizedPoints({ points: nextPoints });\n\n LinearElementEditor._updatePoints(\n element,\n app.scene,\n normalizedPoints,\n offsetX,\n offsetY,\n );\n }\n\n static addPoints(\n element: NonDeleted<ExcalidrawLinearElement>,\n scene: Scene,\n addedPoints: LocalPoint[],\n ) {\n const nextPoints = [...element.points, ...addedPoints];\n\n if (isLineElement(element) && element.polygon) {\n nextPoints[0] = pointFrom(\n nextPoints[nextPoints.length - 1][0],\n nextPoints[nextPoints.length - 1][1],\n );\n }\n\n const {\n points: normalizedPoints,\n offsetX,\n offsetY,\n } = getNormalizedPoints({ points: nextPoints });\n\n LinearElementEditor._updatePoints(\n element,\n scene,\n normalizedPoints,\n offsetX,\n offsetY,\n );\n }\n\n static movePoints(\n element: NonDeleted<ExcalidrawLinearElement>,\n scene: Scene,\n pointUpdates: PointsPositionUpdates,\n otherUpdates?: {\n startBinding?: FixedPointBinding | null;\n endBinding?: FixedPointBinding | null;\n moveMidPointsWithElement?: boolean | null;\n },\n ) {\n const { points } = element;\n\n // if polygon, move start and end points together\n if (isLineElement(element) && element.polygon) {\n const firstPointUpdate = pointUpdates.get(0);\n const lastPointUpdate = pointUpdates.get(points.length - 1);\n\n if (firstPointUpdate) {\n pointUpdates.set(points.length - 1, {\n point: pointFrom(\n firstPointUpdate.point[0],\n firstPointUpdate.point[1],\n ),\n isDragging: firstPointUpdate.isDragging,\n });\n } else if (lastPointUpdate) {\n pointUpdates.set(0, {\n point: pointFrom(lastPointUpdate.point[0], lastPointUpdate.point[1]),\n isDragging: lastPointUpdate.isDragging,\n });\n }\n }\n\n // in case we're moving start point, instead of modifying its position\n // which would break the invariant of it being at [0,0], we move\n // all the other points in the opposite direction by delta to\n // offset it. We do the same with actual element.x/y position, so\n // this hacks are completely transparent to the user.\n\n const updatedOriginPoint =\n pointUpdates.get(0)?.point ?? pointFrom<LocalPoint>(0, 0);\n\n const [offsetX, offsetY] = updatedOriginPoint;\n\n const nextPoints = isElbowArrow(element)\n ? [\n pointUpdates.get(0)?.point ?? points[0],\n pointUpdates.get(points.length - 1)?.point ??\n points[points.length - 1],\n ]\n : points.map((p, idx) => {\n const current = pointUpdates.get(idx)?.point ?? p;\n\n if (\n otherUpdates?.moveMidPointsWithElement &&\n idx !== 0 &&\n idx !== points.length - 1 &&\n !pointUpdates.has(idx)\n ) {\n return current;\n }\n\n return pointFrom<LocalPoint>(\n current[0] - offsetX,\n current[1] - offsetY,\n );\n });\n\n LinearElementEditor._updatePoints(\n element,\n scene,\n nextPoints,\n offsetX,\n offsetY,\n otherUpdates,\n {\n isDragging: Array.from(pointUpdates.values()).some((t) => t.isDragging),\n },\n );\n }\n\n static shouldAddMidpoint(\n linearElementEditor: LinearElementEditor,\n pointerCoords: PointerCoords,\n appState: AppState,\n elementsMap: ElementsMap,\n ) {\n const element = LinearElementEditor.getElement(\n linearElementEditor.elementId,\n elementsMap,\n );\n\n // Elbow arrows don't allow midpoints\n if (element && isElbowArrow(element)) {\n return false;\n }\n\n if (!element) {\n return false;\n }\n\n const { segmentMidpoint } = linearElementEditor.initialState;\n\n if (\n segmentMidpoint.added ||\n segmentMidpoint.value === null ||\n segmentMidpoint.index === null ||\n linearElementEditor.initialState.origin === null\n ) {\n return false;\n }\n\n const origin = linearElementEditor.initialState.origin!;\n const dist = pointDistance(\n origin,\n pointFrom(pointerCoords.x, pointerCoords.y),\n );\n if (\n !appState.selectedLinearElement?.isEditing &&\n dist < DRAGGING_THRESHOLD / appState.zoom.value\n ) {\n return false;\n }\n return true;\n }\n\n static addMidpoint(\n linearElementEditor: LinearElementEditor,\n pointerCoords: PointerCoords,\n app: AppClassProperties,\n snapToGrid: boolean,\n scene: Scene,\n ) {\n const elementsMap = scene.getNonDeletedElementsMap();\n const element = LinearElementEditor.getElement(\n linearElementEditor.elementId,\n elementsMap,\n );\n if (!element) {\n return;\n }\n const { segmentMidpoint } = linearElementEditor.initialState;\n const ret: {\n pointerDownState: LinearElementEditor[\"initialState\"];\n selectedPointsIndices: LinearElementEditor[\"selectedPointsIndices\"];\n } = {\n pointerDownState: linearElementEditor.initialState,\n selectedPointsIndices: linearElementEditor.selectedPointsIndices,\n };\n\n const midpoint = LinearElementEditor.createPointAt(\n element,\n elementsMap,\n pointerCoords.x,\n pointerCoords.y,\n snapToGrid && !isElbowArrow(element) ? app.getEffectiveGridSize() : null,\n );\n const points = [\n ...element.points.slice(0, segmentMidpoint.index!),\n midpoint,\n ...element.points.slice(segmentMidpoint.index!),\n ];\n\n scene.mutateElement(element, { points });\n\n ret.pointerDownState = {\n ...linearElementEditor.initialState,\n segmentMidpoint: {\n ...linearElementEditor.initialState.segmentMidpoint,\n added: true,\n },\n lastClickedPoint: segmentMidpoint.index!,\n };\n ret.selectedPointsIndices = [segmentMidpoint.index!];\n return ret;\n }\n\n private static _updatePoints(\n element: NonDeleted<ExcalidrawLinearElement>,\n scene: Scene,\n nextPoints: readonly LocalPoint[],\n offsetX: number,\n offsetY: number,\n otherUpdates?: {\n startBinding?: FixedPointBinding | null;\n endBinding?: FixedPointBinding | null;\n },\n options?: {\n isDragging?: boolean;\n zoom?: AppState[\"zoom\"];\n sceneElementsMap?: NonDeletedSceneElementsMap;\n },\n ) {\n if (isElbowArrow(element)) {\n const updates: {\n startBinding?: FixedPointBinding | null;\n endBinding?: FixedPointBinding | null;\n points?: LocalPoint[];\n } = {};\n if (otherUpdates?.startBinding !== undefined) {\n updates.startBinding = otherUpdates.startBinding;\n }\n if (otherUpdates?.endBinding !== undefined) {\n updates.endBinding = otherUpdates.endBinding;\n }\n\n updates.points = Array.from(nextPoints);\n\n scene.mutateElement(element, updates, {\n informMutation: true,\n isDragging: options?.isDragging ?? false,\n });\n } else {\n // TODO do we need to get precise coords here just to calc centers?\n const nextCoords = getElementPointsCoords(element, nextPoints);\n const prevCoords = getElementPointsCoords(element, element.points);\n const nextCenterX = (nextCoords[0] + nextCoords[2]) / 2;\n const nextCenterY = (nextCoords[1] + nextCoords[3]) / 2;\n const prevCenterX = (prevCoords[0] + prevCoords[2]) / 2;\n const prevCenterY = (prevCoords[1] + prevCoords[3]) / 2;\n const dX = prevCenterX - nextCenterX;\n const dY = prevCenterY - nextCenterY;\n const rotatedOffset = pointRotateRads(\n pointFrom(offsetX, offsetY),\n pointFrom(dX, dY),\n element.angle,\n );\n scene.mutateElement(element, {\n ...otherUpdates,\n points: nextPoints,\n x: element.x + rotatedOffset[0],\n y: element.y + rotatedOffset[1],\n });\n }\n }\n\n private static _getShiftLockedDelta(\n element: NonDeleted<ExcalidrawLinearElement>,\n elementsMap: ElementsMap,\n referencePoint: LocalPoint,\n scenePointer: GlobalPoint,\n gridSize: NullableGridSize,\n customLineAngle?: number,\n ) {\n const referencePointCoords = LinearElementEditor.getPointGlobalCoordinates(\n element,\n referencePoint,\n elementsMap,\n );\n\n if (isElbowArrow(element)) {\n return [\n scenePointer[0] - referencePointCoords[0],\n scenePointer[1] - referencePointCoords[1],\n ];\n }\n\n const [gridX, gridY] = getGridPoint(\n scenePointer[0],\n scenePointer[1],\n gridSize,\n );\n\n const { width, height } = getLockedLinearCursorAlignSize(\n referencePointCoords[0],\n referencePointCoords[1],\n gridX,\n gridY,\n customLineAngle,\n );\n\n return pointRotateRads(\n pointFrom(width, height),\n pointFrom(0, 0),\n -element.angle as Radians,\n );\n }\n\n static getBoundTextElementPosition = (\n element: ExcalidrawLinearElement,\n boundTextElement: ExcalidrawTextElementWithContainer,\n elementsMap: ElementsMap,\n ): { x: number; y: number } => {\n const points = LinearElementEditor.getPointsGlobalCoordinates(\n element,\n elementsMap,\n );\n if (points.length < 2) {\n mutateElement(boundTextElement, elementsMap, { isDeleted: true });\n }\n let x = 0;\n let y = 0;\n if (element.points.length % 2 === 1) {\n const index = Math.floor(element.points.length / 2);\n const midPoint = LinearElementEditor.getPointGlobalCoordinates(\n element,\n element.points[index],\n elementsMap,\n );\n x = midPoint[0] - boundTextElement.width / 2;\n y = midPoint[1] - boundTextElement.height / 2;\n } else {\n const index = element.points.length / 2 - 1;\n const midSegmentMidpoint = LinearElementEditor.getSegmentMidPoint(\n element,\n index + 1,\n );\n\n x = midSegmentMidpoint[0] - boundTextElement.width / 2;\n y = midSegmentMidpoint[1] - boundTextElement.height / 2;\n }\n return { x, y };\n };\n\n static getMinMaxXYWithBoundText = (\n element: ExcalidrawLinearElement,\n elementsMap: ElementsMap,\n elementBounds: Bounds,\n boundTextElement: ExcalidrawTextElementWithContainer,\n ): [number, number, number, number, number, number] => {\n let [x1, y1, x2, y2] = elementBounds;\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const { x: boundTextX1, y: boundTextY1 } =\n LinearElementEditor.getBoundTextElementPosition(\n element,\n boundTextElement,\n elementsMap,\n );\n const boundTextX2 = boundTextX1 + boundTextElement.width;\n const boundTextY2 = boundTextY1 + boundTextElement.height;\n const centerPoint = pointFrom(cx, cy);\n\n const topLeftRotatedPoint = pointRotateRads(\n pointFrom(x1, y1),\n centerPoint,\n element.angle,\n );\n const topRightRotatedPoint = pointRotateRads(\n pointFrom(x2, y1),\n centerPoint,\n element.angle,\n );\n\n const counterRotateBoundTextTopLeft = pointRotateRads(\n pointFrom(boundTextX1, boundTextY1),\n centerPoint,\n -element.angle as Radians,\n );\n const counterRotateBoundTextTopRight = pointRotateRads(\n pointFrom(boundTextX2, boundTextY1),\n centerPoint,\n -element.angle as Radians,\n );\n const counterRotateBoundTextBottomLeft = pointRotateRads(\n pointFrom(boundTextX1, boundTextY2),\n centerPoint,\n -element.angle as Radians,\n );\n const counterRotateBoundTextBottomRight = pointRotateRads(\n pointFrom(boundTextX2, boundTextY2),\n centerPoint,\n -element.angle as Radians,\n );\n\n if (\n topLeftRotatedPoint[0] < topRightRotatedPoint[0] &&\n topLeftRotatedPoint[1] >= topRightRotatedPoint[1]\n ) {\n x1 = Math.min(x1, counterRotateBoundTextBottomLeft[0]);\n x2 = Math.max(\n x2,\n Math.max(\n counterRotateBoundTextTopRight[0],\n counterRotateBoundTextBottomRight[0],\n ),\n );\n y1 = Math.min(y1, counterRotateBoundTextTopLeft[1]);\n\n y2 = Math.max(y2, counterRotateBoundTextBottomRight[1]);\n } else if (\n topLeftRotatedPoint[0] >= topRightRotatedPoint[0] &&\n topLeftRotatedPoint[1] > topRightRotatedPoint[1]\n ) {\n x1 = Math.min(x1, counterRotateBoundTextBottomRight[0]);\n x2 = Math.max(\n x2,\n Math.max(\n counterRotateBoundTextTopLeft[0],\n counterRotateBoundTextTopRight[0],\n ),\n );\n y1 = Math.min(y1, counterRotateBoundTextBottomLeft[1]);\n\n y2 = Math.max(y2, counterRotateBoundTextTopRight[1]);\n } else if (topLeftRotatedPoint[0] >= topRightRotatedPoint[0]) {\n x1 = Math.min(x1, counterRotateBoundTextTopRight[0]);\n x2 = Math.max(x2, counterRotateBoundTextBottomLeft[0]);\n y1 = Math.min(y1, counterRotateBoundTextBottomRight[1]);\n\n y2 = Math.max(y2, counterRotateBoundTextTopLeft[1]);\n } else if (topLeftRotatedPoint[1] <= topRightRotatedPoint[1]) {\n x1 = Math.min(\n x1,\n Math.min(\n counterRotateBoundTextTopRight[0],\n counterRotateBoundTextTopLeft[0],\n ),\n );\n\n x2 = Math.max(x2, counterRotateBoundTextBottomRight[0]);\n y1 = Math.min(y1, counterRotateBoundTextTopRight[1]);\n y2 = Math.max(y2, counterRotateBoundTextBottomLeft[1]);\n }\n\n return [x1, y1, x2, y2, cx, cy];\n };\n\n static getElementAbsoluteCoords = (\n element: ExcalidrawLinearElement,\n elementsMap: ElementsMap,\n includeBoundText: boolean = false,\n ): [number, number, number, number, number, number] => {\n const shape = ShapeCache.generateElementShape(element, null);\n\n // first element is always the curve\n const ops = getCurvePathOps(shape[0]);\n\n const [minX, minY, maxX, maxY] = getMinMaxXYFromCurvePathOps(ops);\n const x1 = minX + element.x;\n const y1 = minY + element.y;\n const x2 = maxX + element.x;\n const y2 = maxY + element.y;\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n\n const boundTextElement =\n includeBoundText && getBoundTextElement(element, elementsMap);\n if (boundTextElement) {\n return LinearElementEditor.getMinMaxXYWithBoundText(\n element,\n elementsMap,\n [x1, y1, x2, y2],\n boundTextElement,\n );\n }\n\n return [x1, y1, x2, y2, cx, cy];\n };\n\n static moveFixedSegment(\n linearElement: LinearElementEditor,\n index: number,\n x: number,\n y: number,\n scene: Scene,\n ): Pick<\n LinearElementEditor,\n \"segmentMidPointHoveredCoords\" | \"initialState\"\n > {\n const elementsMap = scene.getNonDeletedElementsMap();\n const element = LinearElementEditor.getElement(\n linearElement.elementId,\n elementsMap,\n );\n\n if (!element || !isElbowArrow(element)) {\n return linearElement;\n }\n\n if (index && index > 0 && index < element.points.length) {\n const isHorizontal = headingIsHorizontal(\n vectorToHeading(\n vectorFromPoint(element.points[index], element.points[index - 1]),\n ),\n );\n\n const fixedSegments = (element.fixedSegments ?? []).reduce(\n (segments, s) => {\n segments[s.index] = s;\n return segments;\n },\n {} as Record<number, FixedSegment>,\n );\n fixedSegments[index] = {\n index,\n start: pointFrom<LocalPoint>(\n !isHorizontal ? x - element.x : element.points[index - 1][0],\n isHorizontal ? y - element.y : element.points[index - 1][1],\n ),\n end: pointFrom<LocalPoint>(\n !isHorizontal ? x - element.x : element.points[index][0],\n isHorizontal ? y - element.y : element.points[index][1],\n ),\n };\n const nextFixedSegments = Object.values(fixedSegments).sort(\n (a, b) => a.index - b.index,\n );\n\n const offset = nextFixedSegments\n .map((segment) => segment.index)\n .reduce((count, idx) => (idx < index ? count + 1 : count), 0);\n\n scene.mutateElement(element, {\n fixedSegments: nextFixedSegments,\n });\n\n const point = pointFrom<GlobalPoint>(\n element.x +\n (element.fixedSegments![offset].start[0] +\n element.fixedSegments![offset].end[0]) /\n 2,\n element.y +\n (element.fixedSegments![offset].start[1] +\n element.fixedSegments![offset].end[1]) /\n 2,\n );\n\n return {\n ...linearElement,\n segmentMidPointHoveredCoords: point,\n initialState: {\n ...linearElement.initialState,\n segmentMidpoint: {\n added: false,\n index: element.fixedSegments![offset].index,\n value: point,\n },\n },\n };\n }\n\n return linearElement;\n }\n\n static deleteFixedSegment(\n element: ExcalidrawElbowArrowElement,\n scene: Scene,\n index: number,\n ): void {\n scene.mutateElement(element, {\n fixedSegments: element.fixedSegments?.filter(\n (segment) => segment.index !== index,\n ),\n });\n }\n}\n\nconst normalizeSelectedPoints = (\n points: (number | null)[],\n): number[] | null => {\n let nextPoints = [\n ...new Set(points.filter((p) => p !== null && p !== -1)),\n ] as number[];\n nextPoints = nextPoints.sort((a, b) => a - b);\n return nextPoints.length ? nextPoints : null;\n};\n\nconst pointDraggingUpdates = (\n selectedPointsIndices: readonly number[],\n deltaX: number,\n deltaY: number,\n scenePointerX: number,\n scenePointerY: number,\n elementsMap: NonDeletedSceneElementsMap,\n element: NonDeleted<ExcalidrawLinearElement>,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n app: AppClassProperties,\n angleLocked: boolean,\n altKey: boolean,\n): {\n positions: PointsPositionUpdates;\n updates?: PointMoveOtherUpdates;\n} => {\n const naiveDraggingPoints = new Map(\n selectedPointsIndices.map((pointIndex) => {\n return [\n pointIndex,\n {\n point: pointFrom<LocalPoint>(\n element.points[pointIndex][0] + deltaX,\n element.points[pointIndex][1] + deltaY,\n ),\n isDragging: true,\n },\n ];\n }),\n );\n\n // Linear elements have no special logic\n if (!isArrowElement(element)) {\n return {\n positions: naiveDraggingPoints,\n };\n }\n\n const startIsDragged = selectedPointsIndices.includes(0);\n const endIsDragged = selectedPointsIndices.includes(\n element.points.length - 1,\n );\n\n const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints(\n element,\n naiveDraggingPoints,\n scenePointerX,\n scenePointerY,\n elementsMap,\n elements,\n app.state,\n {\n newArrow: !!app.state.newElement,\n angleLocked,\n altKey,\n },\n );\n\n if (isElbowArrow(element)) {\n return {\n positions: naiveDraggingPoints,\n updates: {\n suggestedBinding: startIsDragged\n ? start.element\n : endIsDragged\n ? end.element\n : null,\n },\n };\n }\n\n if (startIsDragged === endIsDragged) {\n return {\n positions: naiveDraggingPoints,\n };\n }\n\n // Generate the next bindings for the arrow\n const updates: PointMoveOtherUpdates = {\n suggestedBinding: null,\n };\n if (start.mode === null) {\n updates.startBinding = null;\n } else if (start.mode) {\n updates.startBinding = {\n elementId: start.element.id,\n mode: start.mode,\n ...calculateFixedPointForNonElbowArrowBinding(\n element,\n start.element,\n \"start\",\n elementsMap,\n start.focusPoint,\n ),\n };\n\n if (\n startIsDragged &&\n (updates.startBinding.mode === \"orbit\" ||\n !getFeatureFlag(\"COMPLEX_BINDINGS\"))\n ) {\n updates.suggestedBinding = start.element;\n }\n } else if (startIsDragged) {\n updates.suggestedBinding = app.state.suggestedBinding;\n }\n\n if (end.mode === null) {\n updates.endBinding = null;\n } else if (end.mode) {\n updates.endBinding = {\n elementId: end.element.id,\n mode: end.mode,\n ...calculateFixedPointForNonElbowArrowBinding(\n element,\n end.element,\n \"end\",\n elementsMap,\n end.focusPoint,\n ),\n };\n\n if (\n endIsDragged &&\n (updates.endBinding.mode === \"orbit\" ||\n !getFeatureFlag(\"COMPLEX_BINDINGS\"))\n ) {\n updates.suggestedBinding = end.element;\n }\n } else if (endIsDragged) {\n updates.suggestedBinding = app.state.suggestedBinding;\n }\n\n // Simulate the updated arrow for the bind point calculation\n const offsetStartLocalPoint = startIsDragged\n ? pointFrom<LocalPoint>(\n element.points[0][0] + deltaX,\n element.points[0][1] + deltaY,\n )\n : element.points[0];\n const offsetEndLocalPoint = endIsDragged\n ? pointFrom<LocalPoint>(\n element.points[element.points.length - 1][0] + deltaX,\n element.points[element.points.length - 1][1] + deltaY,\n )\n : element.points[element.points.length - 1];\n const nextArrow = {\n ...element,\n points: [\n offsetStartLocalPoint,\n ...element.points.slice(1, -1),\n offsetEndLocalPoint,\n ],\n startBinding:\n updates.startBinding === undefined\n ? element.startBinding\n : updates.startBinding === null\n ? null\n : updates.startBinding,\n endBinding:\n updates.endBinding === undefined\n ? element.endBinding\n : updates.endBinding === null\n ? null\n : updates.endBinding,\n };\n\n // We need to use a custom intersector to ensure that if there is a big \"jump\"\n // in the arrow's position, we can position it with outline avoidance\n // pixel-perfectly and avoid \"dancing\" arrows.\n // NOTE: Direction matters here, so we create two intersectors\n const startCustomIntersector =\n start.focusPoint && end.focusPoint\n ? lineSegment(start.focusPoint, end.focusPoint)\n : undefined;\n const endCustomIntersector =\n start.focusPoint && end.focusPoint\n ? lineSegment(end.focusPoint, start.focusPoint)\n : undefined;\n\n // Needed to handle a special case where an existing arrow is dragged over\n // the same element it is bound to on the other side\n const startIsDraggingOverEndElement =\n element.endBinding &&\n nextArrow.startBinding &&\n startIsDragged &&\n nextArrow.startBinding.elementId === element.endBinding.elementId;\n const endIsDraggingOverStartElement =\n element.startBinding &&\n nextArrow.endBinding &&\n endIsDragged &&\n element.startBinding.elementId === nextArrow.endBinding.elementId;\n\n // We need to update the non-dragged point too if bound,\n // so we look up the old binding to trigger updateBoundPoint\n const endBindable = nextArrow.endBinding\n ? end.element ??\n (elementsMap.get(\n nextArrow.endBinding.elementId,\n )! as ExcalidrawBindableElement)\n : null;\n\n const endLocalPoint = startIsDraggingOverEndElement\n ? nextArrow.points[nextArrow.points.length - 1]\n : endIsDraggingOverStartElement &&\n app.state.bindMode !== \"inside\" &&\n getFeatureFlag(\"COMPLEX_BINDINGS\")\n ? nextArrow.points[0]\n : endBindable\n ? updateBoundPoint(\n element,\n \"endBinding\",\n nextArrow.endBinding,\n endBindable,\n elementsMap,\n endCustomIntersector,\n ) || nextArrow.points[nextArrow.points.length - 1]\n : nextArrow.points[nextArrow.points.length - 1];\n\n // We need to keep the simulated next arrow up-to-date, because\n // updateBoundPoint looks at the opposite point\n nextArrow.points[nextArrow.points.length - 1] = endLocalPoint;\n\n // We need to update the non-dragged point too if bound,\n // so we look up the old binding to trigger updateBoundPoint\n const startBindable = nextArrow.startBinding\n ? start.element ??\n (elementsMap.get(\n nextArrow.startBinding.elementId,\n )! as ExcalidrawBindableElement)\n : null;\n\n const startLocalPoint =\n endIsDraggingOverStartElement && getFeatureFlag(\"COMPLEX_BINDINGS\")\n ? nextArrow.points[0]\n : startIsDraggingOverEndElement &&\n app.state.bindMode !== \"inside\" &&\n getFeatureFlag(\"COMPLEX_BINDINGS\")\n ? nextArrow.points[nextArrow.points.length - 1]\n : startBindable\n ? updateBoundPoint(\n element,\n \"startBinding\",\n nextArrow.startBinding,\n startBindable,\n elementsMap,\n startCustomIntersector,\n ) || nextArrow.points[0]\n : nextArrow.points[0];\n\n const endChanged =\n pointDistance(\n endLocalPoint,\n nextArrow.points[nextArrow.points.length - 1],\n ) !== 0;\n const startChanged =\n pointDistance(startLocalPoint, nextArrow.points[0]) !== 0;\n\n const indicesSet = new Set(selectedPointsIndices);\n if (startBindable && startChanged) {\n indicesSet.add(0);\n }\n if (endBindable && endChanged) {\n indicesSet.add(element.points.length - 1);\n }\n const indices = Array.from(indicesSet);\n\n return {\n updates:\n updates.startBinding || updates.suggestedBinding\n ? {\n startBinding: updates.startBinding,\n suggestedBinding: updates.suggestedBinding,\n }\n : undefined,\n positions: new Map(\n indices.map((idx) => {\n return [\n idx,\n idx === 0\n ? {\n point: startLocalPoint,\n isDragging: true,\n }\n : idx === element.points.length - 1\n ? {\n point: endLocalPoint,\n isDragging: true,\n }\n : naiveDraggingPoints.get(idx)!,\n ];\n }),\n ),\n };\n};\n\nconst determineCustomLinearAngle = (\n pivotPoint: LocalPoint,\n draggedPoint: LocalPoint,\n) =>\n Math.atan2(draggedPoint[1] - pivotPoint[1], draggedPoint[0] - pivotPoint[0]);\n", "import {\n vectorCross,\n vectorFromPoint,\n type GlobalPoint,\n type LocalPoint,\n} from \"@excalidraw/math\";\n\nimport type { Bounds } from \"@excalidraw/common\";\n\nexport type LineSegment<P extends LocalPoint | GlobalPoint> = [P, P];\n\nexport function getBBox<P extends LocalPoint | GlobalPoint>(\n line: LineSegment<P>,\n): Bounds {\n return [\n Math.min(line[0][0], line[1][0]),\n Math.min(line[0][1], line[1][1]),\n Math.max(line[0][0], line[1][0]),\n Math.max(line[0][1], line[1][1]),\n ];\n}\n\nexport function doBBoxesIntersect(a: Bounds, b: Bounds) {\n return a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];\n}\n\nconst EPSILON = 0.000001;\n\nexport function isPointOnLine<P extends GlobalPoint | LocalPoint>(\n l: LineSegment<P>,\n p: P,\n) {\n const p1 = vectorFromPoint(l[1], l[0]);\n const p2 = vectorFromPoint(p, l[0]);\n\n const r = vectorCross(p1, p2);\n\n return Math.abs(r) < EPSILON;\n}\n\nexport function isPointRightOfLine<P extends GlobalPoint | LocalPoint>(\n l: LineSegment<P>,\n p: P,\n) {\n const p1 = vectorFromPoint(l[1], l[0]);\n const p2 = vectorFromPoint(p, l[0]);\n\n return vectorCross(p1, p2) < 0;\n}\n\nexport function isLineSegmentTouchingOrCrossingLine<\n P extends GlobalPoint | LocalPoint,\n>(a: LineSegment<P>, b: LineSegment<P>) {\n return (\n isPointOnLine(a, b[0]) ||\n isPointOnLine(a, b[1]) ||\n (isPointRightOfLine(a, b[0])\n ? !isPointRightOfLine(a, b[1])\n : isPointRightOfLine(a, b[1]))\n );\n}\n\n// https://martin-thoma.com/how-to-check-if-two-line-segments-intersect/\nexport function doLineSegmentsIntersect<P extends GlobalPoint | LocalPoint>(\n a: LineSegment<P>,\n b: LineSegment<P>,\n) {\n return (\n doBBoxesIntersect(getBBox(a), getBBox(b)) &&\n isLineSegmentTouchingOrCrossingLine(a, b) &&\n isLineSegmentTouchingOrCrossingLine(b, a)\n );\n}\n", "import { arrayToMap, type Bounds } from \"@excalidraw/common\";\nimport { getElementBounds } from \"@excalidraw/element\";\nimport {\n isArrowElement,\n isExcalidrawElement,\n isFreeDrawElement,\n isLinearElement,\n isTextElement,\n} from \"@excalidraw/element\";\nimport {\n rangeIncludesValue,\n pointFrom,\n pointRotateRads,\n rangeInclusive,\n} from \"@excalidraw/math\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawLinearElement,\n NonDeletedExcalidrawElement,\n} from \"@excalidraw/element/types\";\nimport type { LocalPoint } from \"@excalidraw/math\";\n\ntype Element = NonDeletedExcalidrawElement;\ntype Elements = readonly NonDeletedExcalidrawElement[];\n\ntype Points = readonly LocalPoint[];\n\n/** @returns vertices relative to element's top-left [0,0] position */\nconst getNonLinearElementRelativePoints = (\n element: Exclude<\n Element,\n ExcalidrawLinearElement | ExcalidrawFreeDrawElement\n >,\n): [\n TopLeft: LocalPoint,\n TopRight: LocalPoint,\n BottomRight: LocalPoint,\n BottomLeft: LocalPoint,\n] => {\n if (element.type === \"diamond\") {\n return [\n pointFrom(element.width / 2, 0),\n pointFrom(element.width, element.height / 2),\n pointFrom(element.width / 2, element.height),\n pointFrom(0, element.height / 2),\n ];\n }\n return [\n pointFrom(0, 0),\n pointFrom(0 + element.width, 0),\n pointFrom(0 + element.width, element.height),\n pointFrom(0, element.height),\n ];\n};\n\n/** @returns vertices relative to element's top-left [0,0] position */\nconst getElementRelativePoints = (element: ExcalidrawElement): Points => {\n if (isLinearElement(element) || isFreeDrawElement(element)) {\n return element.points;\n }\n return getNonLinearElementRelativePoints(element);\n};\n\nconst getMinMaxPoints = (points: Points) => {\n const ret = points.reduce(\n (limits, [x, y]) => {\n limits.minY = Math.min(limits.minY, y);\n limits.minX = Math.min(limits.minX, x);\n\n limits.maxX = Math.max(limits.maxX, x);\n limits.maxY = Math.max(limits.maxY, y);\n\n return limits;\n },\n {\n minX: Infinity,\n minY: Infinity,\n maxX: -Infinity,\n maxY: -Infinity,\n cx: 0,\n cy: 0,\n },\n );\n\n ret.cx = (ret.maxX + ret.minX) / 2;\n ret.cy = (ret.maxY + ret.minY) / 2;\n\n return ret;\n};\n\nconst getRotatedBBox = (element: Element): Bounds => {\n const points = getElementRelativePoints(element);\n\n const { cx, cy } = getMinMaxPoints(points);\n const centerPoint = pointFrom<LocalPoint>(cx, cy);\n\n const rotatedPoints = points.map((p) =>\n pointRotateRads(p, centerPoint, element.angle),\n );\n const { minX, minY, maxX, maxY } = getMinMaxPoints(rotatedPoints);\n\n return [\n minX + element.x,\n minY + element.y,\n maxX + element.x,\n maxY + element.y,\n ];\n};\n\nexport const isElementInsideBBox = (\n element: Element,\n bbox: Bounds,\n eitherDirection = false,\n): boolean => {\n const elementBBox = getRotatedBBox(element);\n\n const elementInsideBbox =\n bbox[0] <= elementBBox[0] &&\n bbox[2] >= elementBBox[2] &&\n bbox[1] <= elementBBox[1] &&\n bbox[3] >= elementBBox[3];\n\n if (!eitherDirection) {\n return elementInsideBbox;\n }\n\n if (elementInsideBbox) {\n return true;\n }\n\n return (\n elementBBox[0] <= bbox[0] &&\n elementBBox[2] >= bbox[2] &&\n elementBBox[1] <= bbox[1] &&\n elementBBox[3] >= bbox[3]\n );\n};\n\nexport const elementPartiallyOverlapsWithOrContainsBBox = (\n element: Element,\n bbox: Bounds,\n): boolean => {\n const elementBBox = getRotatedBBox(element);\n\n return (\n (rangeIncludesValue(elementBBox[0], rangeInclusive(bbox[0], bbox[2])) ||\n rangeIncludesValue(\n bbox[0],\n rangeInclusive(elementBBox[0], elementBBox[2]),\n )) &&\n (rangeIncludesValue(elementBBox[1], rangeInclusive(bbox[1], bbox[3])) ||\n rangeIncludesValue(\n bbox[1],\n rangeInclusive(elementBBox[1], elementBBox[3]),\n ))\n );\n};\n\nexport const elementsOverlappingBBox = ({\n elements,\n bounds,\n type,\n errorMargin = 0,\n}: {\n elements: Elements;\n bounds: Bounds | ExcalidrawElement;\n /** safety offset. Defaults to 0. */\n errorMargin?: number;\n /**\n * - overlap: elements overlapping or inside bounds\n * - contain: elements inside bounds or bounds inside elements\n * - inside: elements inside bounds\n **/\n type: \"overlap\" | \"contain\" | \"inside\";\n}) => {\n if (isExcalidrawElement(bounds)) {\n bounds = getElementBounds(bounds, arrayToMap(elements));\n }\n const adjustedBBox: Bounds = [\n bounds[0] - errorMargin,\n bounds[1] - errorMargin,\n bounds[2] + errorMargin,\n bounds[3] + errorMargin,\n ];\n\n const includedElementSet = new Set<string>();\n\n for (const element of elements) {\n if (includedElementSet.has(element.id)) {\n continue;\n }\n\n const isOverlaping =\n type === \"overlap\"\n ? elementPartiallyOverlapsWithOrContainsBBox(element, adjustedBBox)\n : type === \"inside\"\n ? isElementInsideBBox(element, adjustedBBox)\n : isElementInsideBBox(element, adjustedBBox, true);\n\n if (isOverlaping) {\n includedElementSet.add(element.id);\n\n if (element.boundElements) {\n for (const boundElement of element.boundElements) {\n includedElementSet.add(boundElement.id);\n }\n }\n\n if (isTextElement(element) && element.containerId) {\n includedElementSet.add(element.containerId);\n }\n\n if (isArrowElement(element)) {\n if (element.startBinding) {\n includedElementSet.add(element.startBinding.elementId);\n }\n\n if (element.endBinding) {\n includedElementSet.add(element.endBinding?.elementId);\n }\n }\n }\n }\n\n return elements.filter((element) => includedElementSet.has(element.id));\n};\n", "import type {\n AppClassProperties,\n AppState,\n InteractiveCanvasAppState,\n} from \"@excalidraw/excalidraw/types\";\nimport type { Mutable } from \"@excalidraw/common/utility-types\";\n\nimport { getBoundTextElement } from \"./textElement\";\n\nimport { isBoundToContainer } from \"./typeChecks\";\n\nimport { makeNextSelectedElementIds, getSelectedElements } from \"./selection\";\n\nimport type {\n GroupId,\n ExcalidrawElement,\n NonDeleted,\n NonDeletedExcalidrawElement,\n ElementsMapOrArray,\n ElementsMap,\n} from \"./types\";\n\nexport const selectGroup = (\n groupId: GroupId,\n appState: InteractiveCanvasAppState,\n elements: readonly NonDeleted<ExcalidrawElement>[],\n): Pick<\n InteractiveCanvasAppState,\n \"selectedGroupIds\" | \"selectedElementIds\" | \"editingGroupId\"\n> => {\n const elementsInGroup = elements.reduce(\n (acc: Record<string, true>, element) => {\n if (element.groupIds.includes(groupId)) {\n acc[element.id] = true;\n }\n return acc;\n },\n {},\n );\n\n if (Object.keys(elementsInGroup).length < 2) {\n if (\n appState.selectedGroupIds[groupId] ||\n appState.editingGroupId === groupId\n ) {\n return {\n selectedElementIds: appState.selectedElementIds,\n selectedGroupIds: { ...appState.selectedGroupIds, [groupId]: false },\n editingGroupId: null,\n };\n }\n return appState;\n }\n\n return {\n editingGroupId: appState.editingGroupId,\n selectedGroupIds: { ...appState.selectedGroupIds, [groupId]: true },\n selectedElementIds: {\n ...appState.selectedElementIds,\n ...elementsInGroup,\n },\n };\n};\n\nexport const selectGroupsForSelectedElements = (function () {\n type SelectGroupsReturnType = Pick<\n InteractiveCanvasAppState,\n \"selectedGroupIds\" | \"editingGroupId\" | \"selectedElementIds\"\n >;\n\n let lastSelectedElements: readonly NonDeleted<ExcalidrawElement>[] | null =\n null;\n let lastElements: readonly NonDeleted<ExcalidrawElement>[] | null = null;\n let lastReturnValue: SelectGroupsReturnType | null = null;\n\n const _selectGroups = (\n selectedElements: readonly NonDeleted<ExcalidrawElement>[],\n elements: readonly NonDeleted<ExcalidrawElement>[],\n appState: Pick<AppState, \"selectedElementIds\" | \"editingGroupId\">,\n prevAppState: InteractiveCanvasAppState,\n ): SelectGroupsReturnType => {\n if (\n lastReturnValue !== undefined &&\n elements === lastElements &&\n selectedElements === lastSelectedElements &&\n appState.editingGroupId === lastReturnValue?.editingGroupId\n ) {\n return lastReturnValue;\n }\n\n const selectedGroupIds: Record<GroupId, boolean> = {};\n // Gather all the groups withing selected elements\n for (const selectedElement of selectedElements) {\n let groupIds = selectedElement.groupIds;\n if (appState.editingGroupId) {\n // handle the case where a group is nested within a group\n const indexOfEditingGroup = groupIds.indexOf(appState.editingGroupId);\n if (indexOfEditingGroup > -1) {\n groupIds = groupIds.slice(0, indexOfEditingGroup);\n }\n }\n if (groupIds.length > 0) {\n const lastSelectedGroup = groupIds[groupIds.length - 1];\n selectedGroupIds[lastSelectedGroup] = true;\n }\n }\n\n // Gather all the elements within selected groups\n const groupElementsIndex: Record<GroupId, string[]> = {};\n const selectedElementIdsInGroups = elements.reduce(\n (acc: Record<string, true>, element) => {\n if (element.isDeleted) {\n return acc;\n }\n\n const groupId = element.groupIds.find((id) => selectedGroupIds[id]);\n\n if (groupId) {\n acc[element.id] = true;\n\n // Populate the index\n if (!Array.isArray(groupElementsIndex[groupId])) {\n groupElementsIndex[groupId] = [element.id];\n } else {\n groupElementsIndex[groupId].push(element.id);\n }\n }\n return acc;\n },\n {},\n );\n\n for (const groupId of Object.keys(groupElementsIndex)) {\n // If there is one element in the group, and the group is selected or it's being edited, it's not a group\n if (groupElementsIndex[groupId].length < 2) {\n if (selectedGroupIds[groupId]) {\n selectedGroupIds[groupId] = false;\n }\n }\n }\n\n lastElements = elements;\n lastSelectedElements = selectedElements;\n\n lastReturnValue = {\n editingGroupId: appState.editingGroupId,\n selectedGroupIds,\n selectedElementIds: makeNextSelectedElementIds(\n {\n ...appState.selectedElementIds,\n ...selectedElementIdsInGroups,\n },\n prevAppState,\n ),\n };\n\n return lastReturnValue;\n };\n\n /**\n * When you select an element, you often want to actually select the whole group it's in, unless\n * you're currently editing that group.\n */\n const selectGroupsForSelectedElements = (\n appState: Pick<AppState, \"selectedElementIds\" | \"editingGroupId\">,\n elements: readonly NonDeletedExcalidrawElement[],\n prevAppState: InteractiveCanvasAppState,\n /**\n * supply null in cases where you don't have access to App instance and\n * you don't care about optimizing selectElements retrieval\n */\n app: AppClassProperties | null,\n ): Mutable<\n Pick<\n InteractiveCanvasAppState,\n \"selectedGroupIds\" | \"editingGroupId\" | \"selectedElementIds\"\n >\n > => {\n const selectedElements = app\n ? app.scene.getSelectedElements({\n selectedElementIds: appState.selectedElementIds,\n // supplying elements explicitly in case we're passed non-state elements\n elements,\n })\n : getSelectedElements(elements, appState);\n\n if (!selectedElements.length) {\n return {\n selectedGroupIds: {},\n editingGroupId: null,\n selectedElementIds: makeNextSelectedElementIds(\n appState.selectedElementIds,\n prevAppState,\n ),\n };\n }\n\n return _selectGroups(selectedElements, elements, appState, prevAppState);\n };\n\n selectGroupsForSelectedElements.clearCache = () => {\n lastElements = null;\n lastSelectedElements = null;\n lastReturnValue = null;\n };\n\n return selectGroupsForSelectedElements;\n})();\n\n/**\n * If the element's group is selected, don't render an individual\n * selection border around it.\n */\nexport const isSelectedViaGroup = (\n appState: InteractiveCanvasAppState,\n element: ExcalidrawElement,\n) => getSelectedGroupForElement(appState, element) != null;\n\nexport const getSelectedGroupForElement = (\n appState: Pick<\n InteractiveCanvasAppState,\n \"editingGroupId\" | \"selectedGroupIds\"\n >,\n element: ExcalidrawElement,\n) =>\n element.groupIds\n .filter((groupId) => groupId !== appState.editingGroupId)\n .find((groupId) => appState.selectedGroupIds[groupId]);\n\nexport const getSelectedGroupIds = (\n appState: InteractiveCanvasAppState,\n): GroupId[] =>\n Object.entries(appState.selectedGroupIds)\n .filter(([groupId, isSelected]) => isSelected)\n .map(([groupId, isSelected]) => groupId);\n\n// given a list of elements, return the the actual group ids that should be selected\n// or used to update the elements\nexport const selectGroupsFromGivenElements = (\n elements: readonly NonDeleted<ExcalidrawElement>[],\n appState: InteractiveCanvasAppState,\n) => {\n let nextAppState: InteractiveCanvasAppState = {\n ...appState,\n selectedGroupIds: {},\n };\n\n for (const element of elements) {\n let groupIds = element.groupIds;\n if (appState.editingGroupId) {\n const indexOfEditingGroup = groupIds.indexOf(appState.editingGroupId);\n if (indexOfEditingGroup > -1) {\n groupIds = groupIds.slice(0, indexOfEditingGroup);\n }\n }\n if (groupIds.length > 0) {\n const groupId = groupIds[groupIds.length - 1];\n nextAppState = {\n ...nextAppState,\n ...selectGroup(groupId, nextAppState, elements),\n };\n }\n }\n\n return nextAppState.selectedGroupIds;\n};\n\nexport const editGroupForSelectedElement = (\n appState: AppState,\n element: NonDeleted<ExcalidrawElement>,\n): AppState => {\n return {\n ...appState,\n editingGroupId: element.groupIds.length ? element.groupIds[0] : null,\n selectedGroupIds: {},\n selectedElementIds: {\n [element.id]: true,\n },\n };\n};\n\nexport const isElementInGroup = (element: ExcalidrawElement, groupId: string) =>\n element.groupIds.includes(groupId);\n\nexport const getElementsInGroup = (\n elements: ElementsMapOrArray,\n groupId: string,\n) => {\n const elementsInGroup: ExcalidrawElement[] = [];\n for (const element of elements.values()) {\n if (isElementInGroup(element, groupId)) {\n elementsInGroup.push(element);\n }\n }\n return elementsInGroup;\n};\n\nexport const getSelectedGroupIdForElement = (\n element: ExcalidrawElement,\n selectedGroupIds: { [groupId: string]: boolean },\n) => element.groupIds.find((groupId) => selectedGroupIds[groupId]);\n\nexport const addToGroup = (\n prevGroupIds: ExcalidrawElement[\"groupIds\"],\n newGroupId: GroupId,\n editingGroupId: AppState[\"editingGroupId\"],\n) => {\n // insert before the editingGroupId, or push to the end.\n const groupIds = [...prevGroupIds];\n const positionOfEditingGroupId = editingGroupId\n ? groupIds.indexOf(editingGroupId)\n : -1;\n const positionToInsert =\n positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;\n groupIds.splice(positionToInsert, 0, newGroupId);\n return groupIds;\n};\n\nexport const removeFromSelectedGroups = (\n groupIds: ExcalidrawElement[\"groupIds\"],\n selectedGroupIds: { [groupId: string]: boolean },\n) => groupIds.filter((groupId) => !selectedGroupIds[groupId]);\n\nexport const getMaximumGroups = (\n elements: ExcalidrawElement[],\n elementsMap: ElementsMap,\n): ExcalidrawElement[][] => {\n const groups: Map<String, ExcalidrawElement[]> = new Map<\n String,\n ExcalidrawElement[]\n >();\n elements.forEach((element: ExcalidrawElement) => {\n const groupId =\n element.groupIds.length === 0\n ? element.id\n : element.groupIds[element.groupIds.length - 1];\n\n const currentGroupMembers = groups.get(groupId) || [];\n\n // Include bound text if present when grouping\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (boundTextElement) {\n currentGroupMembers.push(boundTextElement);\n }\n groups.set(groupId, [...currentGroupMembers, element]);\n });\n\n return Array.from(groups.values());\n};\n\nexport const getNonDeletedGroupIds = (elements: ElementsMap) => {\n const nonDeletedGroupIds = new Set<string>();\n\n for (const [, element] of elements) {\n // defensive check\n if (element.isDeleted) {\n continue;\n }\n\n // defensive fallback\n for (const groupId of element.groupIds ?? []) {\n nonDeletedGroupIds.add(groupId);\n }\n }\n\n return nonDeletedGroupIds;\n};\n\nexport const elementsAreInSameGroup = (\n elements: readonly ExcalidrawElement[],\n) => {\n const allGroups = elements.flatMap((element) => element.groupIds);\n const groupCount = new Map<string, number>();\n let maxGroup = 0;\n\n for (const group of allGroups) {\n groupCount.set(group, (groupCount.get(group) ?? 0) + 1);\n if (groupCount.get(group)! > maxGroup) {\n maxGroup = groupCount.get(group)!;\n }\n }\n\n return maxGroup === elements.length;\n};\n\nexport const isInGroup = (element: NonDeletedExcalidrawElement) => {\n return element.groupIds.length > 0;\n};\n\nexport const getNewGroupIdsForDuplication = (\n groupIds: ExcalidrawElement[\"groupIds\"],\n editingGroupId: AppState[\"editingGroupId\"],\n mapper: (groupId: GroupId) => GroupId,\n) => {\n const copy = [...groupIds];\n const positionOfEditingGroupId = editingGroupId\n ? groupIds.indexOf(editingGroupId)\n : -1;\n const endIndex =\n positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;\n for (let index = 0; index < endIndex; index++) {\n copy[index] = mapper(copy[index]);\n }\n\n return copy;\n};\n\n// given a list of selected elements, return the element grouped by their immediate group selected state\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\nexport const getSelectedElementsByGroup = (\n selectedElements: ExcalidrawElement[],\n elementsMap: ElementsMap,\n appState: Readonly<AppState>,\n): ExcalidrawElement[][] => {\n const selectedGroupIds = getSelectedGroupIds(appState);\n const unboundElements = selectedElements.filter(\n (element) => !isBoundToContainer(element),\n );\n const groups: Map<string, ExcalidrawElement[]> = new Map();\n const elements: Map<string, ExcalidrawElement[]> = new Map();\n\n // helper function to add an element to the elements map\n const addToElementsMap = (element: ExcalidrawElement) => {\n // elements\n const currentElementMembers = elements.get(element.id) || [];\n const boundTextElement = getBoundTextElement(element, elementsMap);\n\n if (boundTextElement) {\n currentElementMembers.push(boundTextElement);\n }\n elements.set(element.id, [...currentElementMembers, element]);\n };\n\n // helper function to add an element to the groups map\n const addToGroupsMap = (element: ExcalidrawElement, groupId: string) => {\n // groups\n const currentGroupMembers = groups.get(groupId) || [];\n const boundTextElement = getBoundTextElement(element, elementsMap);\n\n if (boundTextElement) {\n currentGroupMembers.push(boundTextElement);\n }\n groups.set(groupId, [...currentGroupMembers, element]);\n };\n\n // helper function to handle the case where a single group is selected\n // and all elements selected are within the group, it will respect group hierarchy in accordance to\n // their nested grouping order\n const handleSingleSelectedGroupCase = (\n element: ExcalidrawElement,\n selectedGroupId: GroupId,\n ) => {\n const indexOfSelectedGroupId = element.groupIds.indexOf(selectedGroupId, 0);\n const nestedGroupCount = element.groupIds.slice(\n 0,\n indexOfSelectedGroupId,\n ).length;\n return nestedGroupCount > 0\n ? addToGroupsMap(element, element.groupIds[indexOfSelectedGroupId - 1])\n : addToElementsMap(element);\n };\n\n const isAllInSameGroup = selectedElements.every((element) =>\n isSelectedViaGroup(appState, element),\n );\n\n unboundElements.forEach((element) => {\n const selectedGroupId = getSelectedGroupIdForElement(\n element,\n appState.selectedGroupIds,\n );\n if (!selectedGroupId) {\n addToElementsMap(element);\n } else if (selectedGroupIds.length === 1 && isAllInSameGroup) {\n handleSingleSelectedGroupCase(element, selectedGroupId);\n } else {\n addToGroupsMap(element, selectedGroupId);\n }\n });\n return Array.from(groups.values()).concat(Array.from(elements.values()));\n};\n", "import { arrayToMap, isShallowEqual } from \"@excalidraw/common\";\n\nimport type {\n AppState,\n InteractiveCanvasAppState,\n} from \"@excalidraw/excalidraw/types\";\n\nimport { getElementAbsoluteCoords, getElementBounds } from \"./bounds\";\nimport { isElementInViewport } from \"./sizeHelpers\";\nimport {\n isBoundToContainer,\n isFrameLikeElement,\n isLinearElement,\n} from \"./typeChecks\";\nimport {\n elementOverlapsWithFrame,\n getContainingFrame,\n getFrameChildren,\n} from \"./frame\";\n\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport { selectGroupsForSelectedElements } from \"./groups\";\n\nimport type {\n ElementsMap,\n ElementsMapOrArray,\n ExcalidrawElement,\n NonDeletedExcalidrawElement,\n} from \"./types\";\n\n/**\n * Frames and their containing elements are not to be selected at the same time.\n * Given an array of selected elements, if there are frames and their containing elements\n * we only keep the frames.\n * @param selectedElements\n */\nexport const excludeElementsInFramesFromSelection = <\n T extends ExcalidrawElement,\n>(\n selectedElements: readonly T[],\n) => {\n const framesInSelection = new Set<T[\"id\"]>();\n\n selectedElements.forEach((element) => {\n if (isFrameLikeElement(element)) {\n framesInSelection.add(element.id);\n }\n });\n\n return selectedElements.filter((element) => {\n if (element.frameId && framesInSelection.has(element.frameId)) {\n return false;\n }\n return true;\n });\n};\n\nexport const getElementsWithinSelection = (\n elements: readonly NonDeletedExcalidrawElement[],\n selection: NonDeletedExcalidrawElement,\n elementsMap: ElementsMap,\n excludeElementsInFrames: boolean = true,\n) => {\n const [selectionX1, selectionY1, selectionX2, selectionY2] =\n getElementAbsoluteCoords(selection, elementsMap);\n\n let elementsInSelection = elements.filter((element) => {\n if (element.customData?.isGhost) {\n return false;\n }\n\n let [elementX1, elementY1, elementX2, elementY2] = getElementBounds(\n element,\n elementsMap,\n );\n\n const containingFrame = getContainingFrame(element, elementsMap);\n if (containingFrame) {\n const [fx1, fy1, fx2, fy2] = getElementBounds(\n containingFrame,\n elementsMap,\n );\n\n elementX1 = Math.max(fx1, elementX1);\n elementY1 = Math.max(fy1, elementY1);\n elementX2 = Math.min(fx2, elementX2);\n elementY2 = Math.min(fy2, elementY2);\n }\n\n return (\n element.locked === false &&\n element.type !== \"selection\" &&\n !isBoundToContainer(element) &&\n selectionX1 <= elementX1 &&\n selectionY1 <= elementY1 &&\n selectionX2 >= elementX2 &&\n selectionY2 >= elementY2\n );\n });\n\n elementsInSelection = excludeElementsInFrames\n ? excludeElementsInFramesFromSelection(elementsInSelection)\n : elementsInSelection;\n\n elementsInSelection = elementsInSelection.filter((element) => {\n const containingFrame = getContainingFrame(element, elementsMap);\n\n if (containingFrame) {\n return elementOverlapsWithFrame(element, containingFrame, elementsMap);\n }\n\n return true;\n });\n\n return elementsInSelection;\n};\n\nexport const getVisibleAndNonSelectedElements = (\n elements: readonly NonDeletedExcalidrawElement[],\n selectedElements: readonly NonDeletedExcalidrawElement[],\n appState: AppState,\n elementsMap: ElementsMap,\n) => {\n const selectedElementsSet = new Set(\n selectedElements.map((element) => element.id),\n );\n return elements.filter((element) => {\n const isVisible = isElementInViewport(\n element,\n appState.width,\n appState.height,\n appState,\n elementsMap,\n );\n\n return !selectedElementsSet.has(element.id) && isVisible;\n });\n};\n\n// FIXME move this into the editor instance to keep utility methods stateless\nexport const isSomeElementSelected = (function () {\n let lastElements: readonly NonDeletedExcalidrawElement[] | null = null;\n let lastSelectedElementIds: AppState[\"selectedElementIds\"] | null = null;\n let isSelected: boolean | null = null;\n\n const ret = (\n elements: readonly NonDeletedExcalidrawElement[],\n appState: Pick<AppState, \"selectedElementIds\">,\n ): boolean => {\n if (\n isSelected != null &&\n elements === lastElements &&\n appState.selectedElementIds === lastSelectedElementIds\n ) {\n return isSelected;\n }\n\n isSelected = elements.some(\n (element) => appState.selectedElementIds[element.id],\n );\n lastElements = elements;\n lastSelectedElementIds = appState.selectedElementIds;\n\n return isSelected;\n };\n\n ret.clearCache = () => {\n lastElements = null;\n lastSelectedElementIds = null;\n isSelected = null;\n };\n\n return ret;\n})();\n\nexport const getSelectedElements = (\n elements: ElementsMapOrArray,\n appState: Pick<InteractiveCanvasAppState, \"selectedElementIds\">,\n opts?: {\n includeBoundTextElement?: boolean;\n includeElementsInFrames?: boolean;\n },\n) => {\n const addedElements = new Set<ExcalidrawElement[\"id\"]>();\n const selectedElements: ExcalidrawElement[] = [];\n for (const element of elements.values()) {\n if (appState.selectedElementIds[element.id]) {\n selectedElements.push(element);\n addedElements.add(element.id);\n continue;\n }\n if (\n opts?.includeBoundTextElement &&\n isBoundToContainer(element) &&\n appState.selectedElementIds[element?.containerId]\n ) {\n selectedElements.push(element);\n addedElements.add(element.id);\n continue;\n }\n }\n\n if (opts?.includeElementsInFrames) {\n const elementsToInclude: ExcalidrawElement[] = [];\n selectedElements.forEach((element) => {\n if (isFrameLikeElement(element)) {\n getFrameChildren(elements, element.id).forEach(\n (e) => !addedElements.has(e.id) && elementsToInclude.push(e),\n );\n }\n elementsToInclude.push(element);\n });\n\n return elementsToInclude;\n }\n\n return selectedElements;\n};\n\nexport const getTargetElements = (\n elements: ElementsMapOrArray,\n appState: Pick<\n AppState,\n \"selectedElementIds\" | \"editingTextElement\" | \"newElement\"\n >,\n) =>\n appState.editingTextElement\n ? [appState.editingTextElement]\n : appState.newElement\n ? [appState.newElement]\n : getSelectedElements(elements, appState, {\n includeBoundTextElement: true,\n });\n\n/**\n * returns prevState's selectedElementids if no change from previous, so as to\n * retain reference identity for memoization\n */\nexport const makeNextSelectedElementIds = (\n nextSelectedElementIds: AppState[\"selectedElementIds\"],\n prevState: Pick<AppState, \"selectedElementIds\">,\n) => {\n if (isShallowEqual(prevState.selectedElementIds, nextSelectedElementIds)) {\n return prevState.selectedElementIds;\n }\n\n return nextSelectedElementIds;\n};\n\nconst _getLinearElementEditor = (\n targetElements: readonly ExcalidrawElement[],\n allElements: readonly NonDeletedExcalidrawElement[],\n) => {\n const linears = targetElements.filter(isLinearElement);\n if (linears.length === 1) {\n const linear = linears[0];\n const boundElements = linear.boundElements?.map((def) => def.id) ?? [];\n const onlySingleLinearSelected = targetElements.every(\n (el) => el.id === linear.id || boundElements.includes(el.id),\n );\n\n if (onlySingleLinearSelected) {\n return new LinearElementEditor(linear, arrayToMap(allElements));\n }\n }\n\n return null;\n};\n\nexport const getSelectionStateForElements = (\n targetElements: readonly ExcalidrawElement[],\n allElements: readonly NonDeletedExcalidrawElement[],\n appState: AppState,\n) => {\n return {\n selectedLinearElement: _getLinearElementEditor(targetElements, allElements),\n ...selectGroupsForSelectedElements(\n {\n editingGroupId: appState.editingGroupId,\n selectedElementIds: excludeElementsInFramesFromSelection(\n targetElements,\n ).reduce((acc: Record<ExcalidrawElement[\"id\"], true>, element) => {\n if (!isBoundToContainer(element)) {\n acc[element.id] = true;\n }\n return acc;\n }, {}),\n },\n allElements,\n appState,\n null,\n ),\n };\n};\n", "import { arrayToMap } from \"@excalidraw/common\";\nimport { isPointWithinBounds, pointFrom } from \"@excalidraw/math\";\nimport { doLineSegmentsIntersect } from \"@excalidraw/utils/bbox\";\nimport { elementsOverlappingBBox } from \"@excalidraw/utils/withinBounds\";\n\nimport type {\n AppClassProperties,\n AppState,\n StaticCanvasAppState,\n} from \"@excalidraw/excalidraw/types\";\n\nimport type { ReadonlySetLike } from \"@excalidraw/common/utility-types\";\n\nimport { getElementsWithinSelection, getSelectedElements } from \"./selection\";\nimport { getElementsInGroup, selectGroupsFromGivenElements } from \"./groups\";\n\nimport {\n getElementLineSegments,\n getCommonBounds,\n getElementAbsoluteCoords,\n} from \"./bounds\";\nimport { mutateElement } from \"./mutateElement\";\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\nimport {\n isFrameElement,\n isFrameLikeElement,\n isTextElement,\n} from \"./typeChecks\";\n\nimport type { ExcalidrawElementsIncludingDeleted } from \"./Scene\";\n\nimport type {\n ElementsMap,\n ElementsMapOrArray,\n ExcalidrawElement,\n ExcalidrawFrameLikeElement,\n NonDeleted,\n NonDeletedExcalidrawElement,\n} from \"./types\";\n\n// --------------------------- Frame State ------------------------------------\nexport const bindElementsToFramesAfterDuplication = (\n nextElements: readonly ExcalidrawElement[],\n origElements: readonly ExcalidrawElement[],\n origIdToDuplicateId: Map<ExcalidrawElement[\"id\"], ExcalidrawElement[\"id\"]>,\n) => {\n const nextElementMap = arrayToMap(nextElements) as Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement\n >;\n\n for (const element of origElements) {\n if (element.frameId) {\n // use its frameId to get the new frameId\n const nextElementId = origIdToDuplicateId.get(element.id);\n const nextFrameId = origIdToDuplicateId.get(element.frameId);\n const nextElement = nextElementId && nextElementMap.get(nextElementId);\n if (nextElement) {\n mutateElement(nextElement, nextElementMap, {\n frameId: nextFrameId ?? null,\n });\n }\n }\n }\n};\n\nexport function isElementIntersectingFrame(\n element: ExcalidrawElement,\n frame: ExcalidrawFrameLikeElement,\n elementsMap: ElementsMap,\n) {\n const frameLineSegments = getElementLineSegments(frame, elementsMap);\n\n const elementLineSegments = getElementLineSegments(element, elementsMap);\n\n const intersecting = frameLineSegments.some((frameLineSegment) =>\n elementLineSegments.some((elementLineSegment) =>\n doLineSegmentsIntersect(frameLineSegment, elementLineSegment),\n ),\n );\n\n return intersecting;\n}\n\nexport const getElementsCompletelyInFrame = (\n elements: readonly ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n elementsMap: ElementsMap,\n) =>\n omitGroupsContainingFrameLikes(\n getElementsWithinSelection(elements, frame, elementsMap, false),\n ).filter(\n (element) =>\n (!isFrameLikeElement(element) && !element.frameId) ||\n element.frameId === frame.id,\n );\n\nexport const isElementContainingFrame = (\n element: ExcalidrawElement,\n frame: ExcalidrawFrameLikeElement,\n elementsMap: ElementsMap,\n) => {\n return getElementsWithinSelection([frame], element, elementsMap).some(\n (e) => e.id === frame.id,\n );\n};\n\nexport const getElementsIntersectingFrame = (\n elements: readonly ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n) => {\n const elementsMap = arrayToMap(elements);\n return elements.filter((element) =>\n isElementIntersectingFrame(element, frame, elementsMap),\n );\n};\n\nexport const elementsAreInFrameBounds = (\n elements: readonly ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n elementsMap: ElementsMap,\n) => {\n const [frameX1, frameY1, frameX2, frameY2] = getElementAbsoluteCoords(\n frame,\n elementsMap,\n );\n\n const [elementX1, elementY1, elementX2, elementY2] =\n getCommonBounds(elements);\n\n return (\n frameX1 <= elementX1 &&\n frameY1 <= elementY1 &&\n frameX2 >= elementX2 &&\n frameY2 >= elementY2\n );\n};\n\nexport const elementOverlapsWithFrame = (\n element: ExcalidrawElement,\n frame: ExcalidrawFrameLikeElement,\n elementsMap: ElementsMap,\n) => {\n return (\n elementsAreInFrameBounds([element], frame, elementsMap) ||\n isElementIntersectingFrame(element, frame, elementsMap) ||\n isElementContainingFrame(element, frame, elementsMap)\n );\n};\n\nexport const isCursorInFrame = (\n cursorCoords: {\n x: number;\n y: number;\n },\n frame: NonDeleted<ExcalidrawFrameLikeElement>,\n elementsMap: ElementsMap,\n) => {\n const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);\n\n return isPointWithinBounds(\n pointFrom(fx1, fy1),\n pointFrom(cursorCoords.x, cursorCoords.y),\n pointFrom(fx2, fy2),\n );\n};\n\nexport const groupsAreAtLeastIntersectingTheFrame = (\n elements: readonly NonDeletedExcalidrawElement[],\n groupIds: readonly string[],\n frame: ExcalidrawFrameLikeElement,\n) => {\n const elementsMap = arrayToMap(elements);\n const elementsInGroup = groupIds.flatMap((groupId) =>\n getElementsInGroup(elements, groupId),\n );\n\n if (elementsInGroup.length === 0) {\n return true;\n }\n\n return !!elementsInGroup.find(\n (element) =>\n elementsAreInFrameBounds([element], frame, elementsMap) ||\n isElementIntersectingFrame(element, frame, elementsMap),\n );\n};\n\nexport const groupsAreCompletelyOutOfFrame = (\n elements: readonly NonDeletedExcalidrawElement[],\n groupIds: readonly string[],\n frame: ExcalidrawFrameLikeElement,\n) => {\n const elementsMap = arrayToMap(elements);\n const elementsInGroup = groupIds.flatMap((groupId) =>\n getElementsInGroup(elements, groupId),\n );\n\n if (elementsInGroup.length === 0) {\n return true;\n }\n\n return (\n elementsInGroup.find(\n (element) =>\n elementsAreInFrameBounds([element], frame, elementsMap) ||\n isElementIntersectingFrame(element, frame, elementsMap),\n ) === undefined\n );\n};\n\n// --------------------------- Frame Utils ------------------------------------\n\n/**\n * Returns a map of frameId to frame elements. Includes empty frames.\n */\nexport const groupByFrameLikes = (elements: readonly ExcalidrawElement[]) => {\n const frameElementsMap = new Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement[]\n >();\n\n for (const element of elements) {\n const frameId = isFrameLikeElement(element) ? element.id : element.frameId;\n if (frameId && !frameElementsMap.has(frameId)) {\n frameElementsMap.set(frameId, getFrameChildren(elements, frameId));\n }\n }\n\n return frameElementsMap;\n};\n\nexport const getFrameChildren = (\n allElements: ElementsMapOrArray,\n frameId: string,\n) => {\n const frameChildren: ExcalidrawElement[] = [];\n for (const element of allElements.values()) {\n if (element.frameId === frameId) {\n frameChildren.push(element);\n }\n }\n return frameChildren;\n};\n\nexport const getFrameLikeElements = (\n allElements: ExcalidrawElementsIncludingDeleted,\n): ExcalidrawFrameLikeElement[] => {\n return allElements.filter((element): element is ExcalidrawFrameLikeElement =>\n isFrameLikeElement(element),\n );\n};\n\n/**\n * Returns ExcalidrawFrameElements and non-frame-children elements.\n *\n * Considers children as root elements if they point to a frame parent\n * non-existing in the elements set.\n *\n * Considers non-frame bound elements (container or arrow labels) as root.\n */\nexport const getRootElements = (\n allElements: ExcalidrawElementsIncludingDeleted,\n) => {\n const frameElements = arrayToMap(getFrameLikeElements(allElements));\n return allElements.filter(\n (element) =>\n frameElements.has(element.id) ||\n !element.frameId ||\n !frameElements.has(element.frameId),\n );\n};\n\nexport const getElementsInResizingFrame = (\n allElements: ExcalidrawElementsIncludingDeleted,\n frame: ExcalidrawFrameLikeElement,\n appState: AppState,\n elementsMap: ElementsMap,\n): ExcalidrawElement[] => {\n const prevElementsInFrame = getFrameChildren(allElements, frame.id);\n const nextElementsInFrame = new Set<ExcalidrawElement>(prevElementsInFrame);\n\n const elementsCompletelyInFrame = new Set([\n ...getElementsCompletelyInFrame(allElements, frame, elementsMap),\n ...prevElementsInFrame.filter((element) =>\n isElementContainingFrame(element, frame, elementsMap),\n ),\n ]);\n\n const elementsNotCompletelyInFrame = prevElementsInFrame.filter(\n (element) => !elementsCompletelyInFrame.has(element),\n );\n\n // for elements that are completely in the frame\n // if they are part of some groups, then those groups are still\n // considered to belong to the frame\n const groupsToKeep = new Set<string>(\n Array.from(elementsCompletelyInFrame).flatMap(\n (element) => element.groupIds,\n ),\n );\n\n for (const element of elementsNotCompletelyInFrame) {\n if (!isElementIntersectingFrame(element, frame, elementsMap)) {\n if (element.groupIds.length === 0) {\n nextElementsInFrame.delete(element);\n }\n } else if (element.groupIds.length > 0) {\n // group element intersects with the frame, we should keep the groups\n // that this element is part of\n for (const id of element.groupIds) {\n groupsToKeep.add(id);\n }\n }\n }\n\n for (const element of elementsNotCompletelyInFrame) {\n if (element.groupIds.length > 0) {\n let shouldRemoveElement = true;\n\n for (const id of element.groupIds) {\n if (groupsToKeep.has(id)) {\n shouldRemoveElement = false;\n }\n }\n\n if (shouldRemoveElement) {\n nextElementsInFrame.delete(element);\n }\n }\n }\n\n const individualElementsCompletelyInFrame = Array.from(\n elementsCompletelyInFrame,\n ).filter((element) => element.groupIds.length === 0);\n\n for (const element of individualElementsCompletelyInFrame) {\n nextElementsInFrame.add(element);\n }\n\n const newGroupElementsCompletelyInFrame = Array.from(\n elementsCompletelyInFrame,\n ).filter((element) => element.groupIds.length > 0);\n\n const groupIds = selectGroupsFromGivenElements(\n newGroupElementsCompletelyInFrame,\n appState,\n );\n\n // new group elements\n for (const [id, isSelected] of Object.entries(groupIds)) {\n if (isSelected) {\n const elementsInGroup = getElementsInGroup(allElements, id);\n\n if (elementsAreInFrameBounds(elementsInGroup, frame, elementsMap)) {\n for (const element of elementsInGroup) {\n nextElementsInFrame.add(element);\n }\n }\n }\n }\n\n return [...nextElementsInFrame].filter((element) => {\n return !(isTextElement(element) && element.containerId);\n });\n};\n\nexport const getElementsInNewFrame = (\n elements: ExcalidrawElementsIncludingDeleted,\n frame: ExcalidrawFrameLikeElement,\n elementsMap: ElementsMap,\n) => {\n return omitPartialGroups(\n omitGroupsContainingFrameLikes(\n elements,\n getElementsCompletelyInFrame(elements, frame, elementsMap),\n ),\n frame,\n elementsMap,\n );\n};\n\nexport const omitPartialGroups = (\n elements: ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n allElementsMap: ElementsMap,\n) => {\n const elementsToReturn = [];\n const checkedGroups = new Map<string, boolean>();\n\n for (const element of elements) {\n let shouldOmit = false;\n if (element.groupIds.length > 0) {\n // if some partial group should be omitted, then all elements in that group should be omitted\n if (element.groupIds.some((gid) => checkedGroups.get(gid))) {\n shouldOmit = true;\n } else {\n const allElementsInGroup = new Set(\n element.groupIds.flatMap((gid) =>\n getElementsInGroup(allElementsMap, gid),\n ),\n );\n\n shouldOmit = !elementsAreInFrameBounds(\n Array.from(allElementsInGroup),\n frame,\n allElementsMap,\n );\n }\n\n element.groupIds.forEach((gid) => {\n checkedGroups.set(gid, shouldOmit);\n });\n }\n\n if (!shouldOmit) {\n elementsToReturn.push(element);\n }\n }\n\n return elementsToReturn;\n};\n\nexport const getContainingFrame = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n) => {\n if (!element.frameId) {\n return null;\n }\n return (elementsMap.get(element.frameId) ||\n null) as null | ExcalidrawFrameLikeElement;\n};\n\n// --------------------------- Frame Operations -------------------------------\n\n/** */\nexport const filterElementsEligibleAsFrameChildren = (\n elements: readonly ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n) => {\n const otherFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>();\n const elementsMap = arrayToMap(elements);\n elements = omitGroupsContainingFrameLikes(elements);\n\n for (const element of elements) {\n if (isFrameLikeElement(element) && element.id !== frame.id) {\n otherFrames.add(element.id);\n }\n }\n\n const processedGroups = new Set<ExcalidrawElement[\"id\"]>();\n\n const eligibleElements: ExcalidrawElement[] = [];\n\n for (const element of elements) {\n // don't add frames or their children\n if (\n isFrameLikeElement(element) ||\n (element.frameId && otherFrames.has(element.frameId))\n ) {\n continue;\n }\n\n if (element.groupIds.length) {\n const shallowestGroupId = element.groupIds.at(-1)!;\n if (!processedGroups.has(shallowestGroupId)) {\n processedGroups.add(shallowestGroupId);\n const groupElements = getElementsInGroup(elements, shallowestGroupId);\n if (\n groupElements.some((el) =>\n elementOverlapsWithFrame(el, frame, elementsMap),\n )\n ) {\n for (const child of groupElements) {\n eligibleElements.push(child);\n }\n }\n }\n } else {\n const overlaps = elementOverlapsWithFrame(element, frame, elementsMap);\n if (overlaps) {\n eligibleElements.push(element);\n }\n }\n }\n\n return eligibleElements;\n};\n\n/**\n * Retains (or repairs for target frame) the ordering invriant where children\n * elements come right before the parent frame:\n * [el, el, child, child, frame, el]\n *\n * @returns mutated allElements (same data structure)\n */\nexport const addElementsToFrame = <T extends ElementsMapOrArray>(\n allElements: T,\n elementsToAdd: NonDeletedExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n appState: AppState,\n): T => {\n const elementsMap = arrayToMap(allElements);\n const currTargetFrameChildrenMap = new Map<ExcalidrawElement[\"id\"], true>();\n for (const element of allElements.values()) {\n if (element.frameId === frame.id) {\n currTargetFrameChildrenMap.set(element.id, true);\n }\n }\n\n const suppliedElementsToAddSet = new Set(elementsToAdd.map((el) => el.id));\n\n const finalElementsToAdd: ExcalidrawElement[] = [];\n\n const otherFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>();\n\n for (const element of elementsToAdd) {\n if (isFrameLikeElement(element) && element.id !== frame.id) {\n otherFrames.add(element.id);\n }\n }\n\n // - add bound text elements if not already in the array\n // - filter out elements that are already in the frame\n for (const element of omitGroupsContainingFrameLikes(\n allElements,\n elementsToAdd,\n )) {\n // don't add frames or their children\n if (\n isFrameLikeElement(element) ||\n (element.frameId && otherFrames.has(element.frameId))\n ) {\n continue;\n }\n\n // if the element is already in another frame (which is also in elementsToAdd),\n // it means that frame and children are selected at the same time\n // => keep original frame membership, do not add to the target frame\n if (\n element.frameId &&\n appState.selectedElementIds[element.id] &&\n appState.selectedElementIds[element.frameId]\n ) {\n continue;\n }\n\n if (!currTargetFrameChildrenMap.has(element.id)) {\n finalElementsToAdd.push(element);\n }\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (\n boundTextElement &&\n !suppliedElementsToAddSet.has(boundTextElement.id) &&\n !currTargetFrameChildrenMap.has(boundTextElement.id)\n ) {\n finalElementsToAdd.push(boundTextElement);\n }\n }\n\n for (const element of finalElementsToAdd) {\n mutateElement(element, elementsMap, {\n frameId: frame.id,\n });\n }\n\n return allElements;\n};\n\nexport const removeElementsFromFrame = (\n elementsToRemove: ReadonlySetLike<NonDeletedExcalidrawElement>,\n elementsMap: ElementsMap,\n) => {\n const _elementsToRemove = new Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement\n >();\n\n const toRemoveElementsByFrame = new Map<\n ExcalidrawFrameLikeElement[\"id\"],\n ExcalidrawElement[]\n >();\n\n for (const element of elementsToRemove) {\n if (element.frameId) {\n _elementsToRemove.set(element.id, element);\n\n const arr = toRemoveElementsByFrame.get(element.frameId) || [];\n arr.push(element);\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (boundTextElement) {\n _elementsToRemove.set(boundTextElement.id, boundTextElement);\n arr.push(boundTextElement);\n }\n\n toRemoveElementsByFrame.set(element.frameId, arr);\n }\n }\n\n for (const [, element] of _elementsToRemove) {\n mutateElement(element, elementsMap, {\n frameId: null,\n });\n }\n};\n\nexport const removeAllElementsFromFrame = <T extends ExcalidrawElement>(\n allElements: readonly T[],\n frame: ExcalidrawFrameLikeElement,\n) => {\n const elementsInFrame = getFrameChildren(allElements, frame.id);\n removeElementsFromFrame(elementsInFrame, arrayToMap(allElements));\n return allElements;\n};\n\nexport const replaceAllElementsInFrame = <T extends ExcalidrawElement>(\n allElements: readonly T[],\n nextElementsInFrame: ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n app: AppClassProperties,\n): T[] => {\n return addElementsToFrame(\n removeAllElementsFromFrame(allElements, frame),\n nextElementsInFrame,\n frame,\n app.state,\n ).slice();\n};\n\n/** does not mutate elements, but returns new ones */\nexport const updateFrameMembershipOfSelectedElements = <\n T extends ElementsMapOrArray,\n>(\n allElements: T,\n appState: AppState,\n app: AppClassProperties,\n) => {\n const selectedElements = app.scene.getSelectedElements({\n selectedElementIds: appState.selectedElementIds,\n // supplying elements explicitly in case we're passed non-state elements\n elements: allElements,\n });\n const elementsToFilter = new Set<ExcalidrawElement>(selectedElements);\n\n if (appState.editingGroupId) {\n for (const element of selectedElements) {\n if (element.groupIds.length === 0) {\n elementsToFilter.add(element);\n } else {\n element.groupIds\n .flatMap((gid) => getElementsInGroup(allElements, gid))\n .forEach((element) => elementsToFilter.add(element));\n }\n }\n }\n\n const elementsToRemove = new Set<ExcalidrawElement>();\n\n const elementsMap = arrayToMap(allElements);\n\n elementsToFilter.forEach((element) => {\n if (\n element.frameId &&\n !isFrameLikeElement(element) &&\n !isElementInFrame(element, elementsMap, appState)\n ) {\n elementsToRemove.add(element);\n }\n });\n\n if (elementsToRemove.size > 0) {\n removeElementsFromFrame(elementsToRemove, elementsMap);\n }\n return allElements;\n};\n\n/**\n * filters out elements that are inside groups that contain a frame element\n * anywhere in the group tree\n */\nexport const omitGroupsContainingFrameLikes = (\n allElements: ElementsMapOrArray,\n /** subset of elements you want to filter. Optional perf optimization so we\n * don't have to filter all elements unnecessarily\n */\n selectedElements?: readonly ExcalidrawElement[],\n) => {\n const uniqueGroupIds = new Set<string>();\n const elements = selectedElements || allElements;\n\n for (const el of elements.values()) {\n const topMostGroupId = el.groupIds[el.groupIds.length - 1];\n if (topMostGroupId) {\n uniqueGroupIds.add(topMostGroupId);\n }\n }\n\n const rejectedGroupIds = new Set<string>();\n for (const groupId of uniqueGroupIds) {\n if (\n getElementsInGroup(allElements, groupId).some((el) =>\n isFrameLikeElement(el),\n )\n ) {\n rejectedGroupIds.add(groupId);\n }\n }\n\n const ret: ExcalidrawElement[] = [];\n\n for (const element of elements.values()) {\n if (!rejectedGroupIds.has(element.groupIds[element.groupIds.length - 1])) {\n ret.push(element);\n }\n }\n\n return ret;\n};\n\n/**\n * depending on the appState, return target frame, which is the frame the given element\n * is going to be added to or remove from\n */\nexport const getTargetFrame = (\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n appState: StaticCanvasAppState,\n) => {\n const _element = isTextElement(element)\n ? getContainerElement(element, elementsMap) || element\n : element;\n\n // if the element and its containing frame are both selected, then\n // the containing frame is the target frame\n if (\n _element.frameId &&\n appState.selectedElementIds[_element.id] &&\n appState.selectedElementIds[_element.frameId]\n ) {\n return getContainingFrame(_element, elementsMap);\n }\n\n return appState.selectedElementIds[_element.id] &&\n appState.selectedElementsAreBeingDragged\n ? appState.frameToHighlight\n : getContainingFrame(_element, elementsMap);\n};\n\n// TODO: this a huge bottleneck for large scenes, optimise\n// given an element, return if the element is in some frame\nexport const isElementInFrame = (\n element: ExcalidrawElement,\n allElementsMap: ElementsMap,\n appState: StaticCanvasAppState,\n opts?: {\n targetFrame?: ExcalidrawFrameLikeElement;\n checkedGroups?: Map<string, boolean>;\n },\n) => {\n const frame =\n opts?.targetFrame ?? getTargetFrame(element, allElementsMap, appState);\n\n if (!frame) {\n return false;\n }\n\n const _element = isTextElement(element)\n ? getContainerElement(element, allElementsMap) || element\n : element;\n\n const setGroupsInFrame = (isInFrame: boolean) => {\n if (opts?.checkedGroups) {\n _element.groupIds.forEach((groupId) => {\n opts.checkedGroups?.set(groupId, isInFrame);\n });\n }\n };\n\n if (\n // if the element is not selected, or it is selected but not being dragged,\n // frame membership won't update, so return true\n !appState.selectedElementIds[_element.id] ||\n !appState.selectedElementsAreBeingDragged ||\n // if both frame and element are selected, won't update membership, so return true\n (appState.selectedElementIds[_element.id] &&\n appState.selectedElementIds[frame.id])\n ) {\n return true;\n }\n\n if (_element.groupIds.length === 0) {\n return elementOverlapsWithFrame(_element, frame, allElementsMap);\n }\n\n for (const gid of _element.groupIds) {\n if (opts?.checkedGroups?.has(gid)) {\n return opts.checkedGroups.get(gid)!!;\n }\n }\n\n const allElementsInGroup = new Set(\n _element.groupIds\n .filter((gid) => {\n if (opts?.checkedGroups) {\n return !opts.checkedGroups.has(gid);\n }\n return true;\n })\n .flatMap((gid) => getElementsInGroup(allElementsMap, gid)),\n );\n\n if (appState.editingGroupId && appState.selectedElementsAreBeingDragged) {\n const selectedElements = new Set(\n getSelectedElements(allElementsMap, appState),\n );\n\n const editingGroupOverlapsFrame = appState.frameToHighlight !== null;\n\n if (editingGroupOverlapsFrame) {\n return true;\n }\n\n selectedElements.forEach((selectedElement) => {\n allElementsInGroup.delete(selectedElement);\n });\n }\n\n for (const elementInGroup of allElementsInGroup) {\n if (isFrameLikeElement(elementInGroup)) {\n setGroupsInFrame(false);\n return false;\n }\n }\n\n for (const elementInGroup of allElementsInGroup) {\n if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {\n setGroupsInFrame(true);\n return true;\n }\n }\n\n return false;\n};\n\nexport const shouldApplyFrameClip = (\n element: ExcalidrawElement,\n frame: ExcalidrawFrameLikeElement,\n appState: StaticCanvasAppState,\n elementsMap: ElementsMap,\n checkedGroups?: Map<string, boolean>,\n) => {\n if (!appState.frameRendering || !appState.frameRendering.clip) {\n return false;\n }\n\n // for individual elements, only clip when the element is\n // a. overlapping with the frame, or\n // b. containing the frame, for example when an element is used as a background\n // and is therefore bigger than the frame and completely contains the frame\n const shouldClipElementItself =\n isElementIntersectingFrame(element, frame, elementsMap) ||\n isElementContainingFrame(element, frame, elementsMap);\n\n if (shouldClipElementItself) {\n for (const groupId of element.groupIds) {\n checkedGroups?.set(groupId, true);\n }\n\n return true;\n }\n\n // if an element is outside the frame, but is part of a group that has some elements\n // \"in\" the frame, we should clip the element\n if (\n !shouldClipElementItself &&\n element.groupIds.length > 0 &&\n !elementsAreInFrameBounds([element], frame, elementsMap)\n ) {\n let shouldClip = false;\n\n // if no elements are being dragged, we can skip the geometry check\n // because we know if the element is in the given frame or not\n if (!appState.selectedElementsAreBeingDragged) {\n shouldClip = element.frameId === frame.id;\n for (const groupId of element.groupIds) {\n checkedGroups?.set(groupId, shouldClip);\n }\n } else {\n shouldClip = isElementInFrame(element, elementsMap, appState, {\n targetFrame: frame,\n checkedGroups,\n });\n }\n\n for (const groupId of element.groupIds) {\n checkedGroups?.set(groupId, shouldClip);\n }\n\n return shouldClip;\n }\n\n return false;\n};\n\nconst DEFAULT_FRAME_NAME = \"Frame\";\nconst DEFAULT_AI_FRAME_NAME = \"AI Frame\";\n\nexport const getDefaultFrameName = (element: ExcalidrawFrameLikeElement) => {\n // TODO name frames \"AI\" only if specific to AI frames\n return isFrameElement(element) ? DEFAULT_FRAME_NAME : DEFAULT_AI_FRAME_NAME;\n};\n\nexport const getFrameLikeTitle = (element: ExcalidrawFrameLikeElement) => {\n return element.name === null ? getDefaultFrameName(element) : element.name;\n};\n\nexport const getElementsOverlappingFrame = (\n elements: readonly ExcalidrawElement[],\n frame: ExcalidrawFrameLikeElement,\n) => {\n return (\n elementsOverlappingBBox({\n elements,\n bounds: frame,\n type: \"overlap\",\n })\n // removes elements who are overlapping, but are in a different frame,\n // and thus invisible in target frame\n .filter((el) => !el.frameId || el.frameId === frame.id)\n );\n};\n\nexport const frameAndChildrenSelectedTogether = (\n selectedElements: readonly ExcalidrawElement[],\n) => {\n const selectedElementsMap = arrayToMap(selectedElements);\n\n return (\n selectedElements.length > 1 &&\n selectedElements.some(\n (element) => element.frameId && selectedElementsMap.has(element.frameId),\n )\n );\n};\n", "import type { ElementOrToolType } from \"@excalidraw/excalidraw/types\";\n\nexport const hasBackground = (type: ElementOrToolType) =>\n type === \"rectangle\" ||\n type === \"iframe\" ||\n type === \"embeddable\" ||\n type === \"ellipse\" ||\n type === \"diamond\" ||\n type === \"line\" ||\n type === \"freedraw\";\n\nexport const hasStrokeColor = (type: ElementOrToolType) =>\n type === \"rectangle\" ||\n type === \"ellipse\" ||\n type === \"diamond\" ||\n type === \"freedraw\" ||\n type === \"arrow\" ||\n type === \"line\" ||\n type === \"text\" ||\n type === \"embeddable\";\n\nexport const hasStrokeWidth = (type: ElementOrToolType) =>\n type === \"rectangle\" ||\n type === \"iframe\" ||\n type === \"embeddable\" ||\n type === \"ellipse\" ||\n type === \"diamond\" ||\n type === \"freedraw\" ||\n type === \"arrow\" ||\n type === \"line\";\n\nexport const hasStrokeStyle = (type: ElementOrToolType) =>\n type === \"rectangle\" ||\n type === \"iframe\" ||\n type === \"embeddable\" ||\n type === \"ellipse\" ||\n type === \"diamond\" ||\n type === \"arrow\" ||\n type === \"line\";\n\nexport const canChangeRoundness = (type: ElementOrToolType) =>\n type === \"rectangle\" ||\n type === \"iframe\" ||\n type === \"embeddable\" ||\n type === \"line\" ||\n type === \"diamond\" ||\n type === \"image\";\n\nexport const toolIsArrow = (type: ElementOrToolType) => type === \"arrow\";\n\nexport const canHaveArrowheads = (type: ElementOrToolType) => type === \"arrow\";\n", "import {\n SHIFT_LOCKING_ANGLE,\n viewportCoordsToSceneCoords,\n} from \"@excalidraw/common\";\nimport {\n normalizeRadians,\n radiansBetweenAngles,\n radiansDifference,\n type Radians,\n} from \"@excalidraw/math\";\n\nimport { pointsEqual } from \"@excalidraw/math\";\n\nimport type { AppState, Offsets, Zoom } from \"@excalidraw/excalidraw/types\";\n\nimport { getCommonBounds, getElementBounds } from \"./bounds\";\nimport {\n isArrowElement,\n isFreeDrawElement,\n isLinearElement,\n} from \"./typeChecks\";\n\nimport type { ElementsMap, ExcalidrawElement } from \"./types\";\n\nexport const INVISIBLY_SMALL_ELEMENT_SIZE = 0.1;\n\n// TODO: remove invisible elements consistently actions, so that invisible elements are not recorded by the store, exported, broadcasted or persisted\n// - perhaps could be as part of a standalone 'cleanup' action, in addition to 'finalize'\n// - could also be part of `_clearElements`\nexport const isInvisiblySmallElement = (\n element: ExcalidrawElement,\n): boolean => {\n if (isLinearElement(element) || isFreeDrawElement(element)) {\n return (\n element.points.length < 2 ||\n (element.points.length === 2 &&\n isArrowElement(element) &&\n pointsEqual(\n element.points[0],\n element.points[element.points.length - 1],\n INVISIBLY_SMALL_ELEMENT_SIZE,\n ))\n );\n }\n\n return element.width === 0 && element.height === 0;\n};\n\nexport const isElementInViewport = (\n element: ExcalidrawElement,\n width: number,\n height: number,\n viewTransformations: {\n zoom: Zoom;\n offsetLeft: number;\n offsetTop: number;\n scrollX: number;\n scrollY: number;\n },\n elementsMap: ElementsMap,\n) => {\n const [x1, y1, x2, y2] = getElementBounds(element, elementsMap); // scene coordinates\n const topLeftSceneCoords = viewportCoordsToSceneCoords(\n {\n clientX: viewTransformations.offsetLeft,\n clientY: viewTransformations.offsetTop,\n },\n viewTransformations,\n );\n const bottomRightSceneCoords = viewportCoordsToSceneCoords(\n {\n clientX: viewTransformations.offsetLeft + width,\n clientY: viewTransformations.offsetTop + height,\n },\n viewTransformations,\n );\n\n return (\n topLeftSceneCoords.x <= x2 &&\n topLeftSceneCoords.y <= y2 &&\n bottomRightSceneCoords.x >= x1 &&\n bottomRightSceneCoords.y >= y1\n );\n};\n\nexport const isElementCompletelyInViewport = (\n elements: ExcalidrawElement[],\n width: number,\n height: number,\n viewTransformations: {\n zoom: Zoom;\n offsetLeft: number;\n offsetTop: number;\n scrollX: number;\n scrollY: number;\n },\n elementsMap: ElementsMap,\n padding?: Offsets,\n) => {\n const [x1, y1, x2, y2] = getCommonBounds(elements, elementsMap); // scene coordinates\n const topLeftSceneCoords = viewportCoordsToSceneCoords(\n {\n clientX: viewTransformations.offsetLeft + (padding?.left || 0),\n clientY: viewTransformations.offsetTop + (padding?.top || 0),\n },\n viewTransformations,\n );\n const bottomRightSceneCoords = viewportCoordsToSceneCoords(\n {\n clientX: viewTransformations.offsetLeft + width - (padding?.right || 0),\n clientY: viewTransformations.offsetTop + height - (padding?.bottom || 0),\n },\n viewTransformations,\n );\n\n return (\n x1 >= topLeftSceneCoords.x &&\n y1 >= topLeftSceneCoords.y &&\n x2 <= bottomRightSceneCoords.x &&\n y2 <= bottomRightSceneCoords.y\n );\n};\n\n/**\n * Makes a perfect shape or diagonal/horizontal/vertical line\n */\nexport const getPerfectElementSize = (\n elementType: AppState[\"activeTool\"][\"type\"],\n width: number,\n height: number,\n): { width: number; height: number } => {\n const absWidth = Math.abs(width);\n const absHeight = Math.abs(height);\n\n if (\n elementType === \"line\" ||\n elementType === \"arrow\" ||\n elementType === \"freedraw\"\n ) {\n const lockedAngle =\n Math.round(Math.atan(absHeight / absWidth) / SHIFT_LOCKING_ANGLE) *\n SHIFT_LOCKING_ANGLE;\n if (lockedAngle === 0) {\n height = 0;\n } else if (lockedAngle === Math.PI / 2) {\n width = 0;\n } else {\n height = absWidth * Math.tan(lockedAngle) * Math.sign(height) || height;\n }\n } else if (elementType !== \"selection\") {\n height = absWidth * Math.sign(height);\n }\n return { width, height };\n};\n\nexport const getLockedLinearCursorAlignSize = (\n originX: number,\n originY: number,\n x: number,\n y: number,\n customAngle?: number,\n) => {\n let width = x - originX;\n let height = y - originY;\n\n const angle = Math.atan2(height, width) as Radians;\n let lockedAngle = (Math.round(angle / SHIFT_LOCKING_ANGLE) *\n SHIFT_LOCKING_ANGLE) as Radians;\n\n if (customAngle) {\n // If custom angle is provided, we check if the angle is close to the\n // custom angle, snap to that if close engough, otherwise snap to the\n // higher or lower angle depending on the current angle vs custom angle.\n const lower = (Math.floor(customAngle / SHIFT_LOCKING_ANGLE) *\n SHIFT_LOCKING_ANGLE) as Radians;\n if (\n radiansBetweenAngles(\n angle,\n lower,\n (lower + SHIFT_LOCKING_ANGLE) as Radians,\n )\n ) {\n if (\n radiansDifference(angle, customAngle as Radians) <\n SHIFT_LOCKING_ANGLE / 6\n ) {\n lockedAngle = customAngle as Radians;\n } else if (\n normalizeRadians(angle) > normalizeRadians(customAngle as Radians)\n ) {\n lockedAngle = (lower + SHIFT_LOCKING_ANGLE) as Radians;\n } else {\n lockedAngle = lower;\n }\n }\n }\n\n if (lockedAngle === 0) {\n height = 0;\n } else if (lockedAngle === Math.PI / 2) {\n width = 0;\n } else {\n // locked angle line, y = mx + b => mx - y + b = 0\n const a1 = Math.tan(lockedAngle);\n const b1 = -1;\n const c1 = originY - a1 * originX;\n\n // line through cursor, perpendicular to locked angle line\n const a2 = -1 / a1;\n const b2 = -1;\n const c2 = y - a2 * x;\n\n // intersection of the two lines above\n const intersectX = (b1 * c2 - b2 * c1) / (a1 * b2 - a2 * b1);\n const intersectY = (c1 * a2 - c2 * a1) / (a1 * b2 - a2 * b1);\n\n // delta\n width = intersectX - originX;\n height = intersectY - originY;\n }\n\n return { width, height };\n};\n\nexport const getNormalizedDimensions = (\n element: Pick<ExcalidrawElement, \"width\" | \"height\" | \"x\" | \"y\">,\n): {\n width: ExcalidrawElement[\"width\"];\n height: ExcalidrawElement[\"height\"];\n x: ExcalidrawElement[\"x\"];\n y: ExcalidrawElement[\"y\"];\n} => {\n const ret = {\n width: element.width,\n height: element.height,\n x: element.x,\n y: element.y,\n };\n\n if (element.width < 0) {\n const nextWidth = Math.abs(element.width);\n ret.width = nextWidth;\n ret.x = element.x - nextWidth;\n }\n\n if (element.height < 0) {\n const nextHeight = Math.abs(element.height);\n ret.height = nextHeight;\n ret.y = element.y - nextHeight;\n }\n\n return ret;\n};\n", "import type { AppState } from \"@excalidraw/excalidraw/types\";\n\nimport { updateBoundElements } from \"./binding\";\nimport { getCommonBoundingBox } from \"./bounds\";\nimport { getSelectedElementsByGroup } from \"./groups\";\n\nimport type { Scene } from \"./Scene\";\n\nimport type { BoundingBox } from \"./bounds\";\nimport type { ExcalidrawElement } from \"./types\";\n\nexport interface Alignment {\n position: \"start\" | \"center\" | \"end\";\n axis: \"x\" | \"y\";\n}\n\nexport const alignElements = (\n selectedElements: ExcalidrawElement[],\n alignment: Alignment,\n scene: Scene,\n appState: Readonly<AppState>,\n): ExcalidrawElement[] => {\n const groups: ExcalidrawElement[][] = getSelectedElementsByGroup(\n selectedElements,\n scene.getNonDeletedElementsMap(),\n appState,\n );\n const selectionBoundingBox = getCommonBoundingBox(selectedElements);\n\n return groups.flatMap((group) => {\n const translation = calculateTranslation(\n group,\n selectionBoundingBox,\n alignment,\n );\n return group.map((element) => {\n // update element\n const updatedEle = scene.mutateElement(element, {\n x: element.x + translation.x,\n y: element.y + translation.y,\n });\n\n // update bound elements\n updateBoundElements(element, scene, {\n simultaneouslyUpdated: group,\n });\n return updatedEle;\n });\n });\n};\n\nconst calculateTranslation = (\n group: ExcalidrawElement[],\n selectionBoundingBox: BoundingBox,\n { axis, position }: Alignment,\n): { x: number; y: number } => {\n const groupBoundingBox = getCommonBoundingBox(group);\n\n const [min, max]: [\"minX\" | \"minY\", \"maxX\" | \"maxY\"] =\n axis === \"x\" ? [\"minX\", \"maxX\"] : [\"minY\", \"maxY\"];\n\n const noTranslation = { x: 0, y: 0 };\n if (position === \"start\") {\n return {\n ...noTranslation,\n [axis]: selectionBoundingBox[min] - groupBoundingBox[min],\n };\n } else if (position === \"end\") {\n return {\n ...noTranslation,\n [axis]: selectionBoundingBox[max] - groupBoundingBox[max],\n };\n } // else if (position === \"center\") {\n return {\n ...noTranslation,\n [axis]:\n (selectionBoundingBox[min] + selectionBoundingBox[max]) / 2 -\n (groupBoundingBox[min] + groupBoundingBox[max]) / 2,\n };\n};\n", "import { arrayToMapWithIndex } from \"@excalidraw/common\";\n\nimport type { ExcalidrawElement } from \"./types\";\n\nconst normalizeGroupElementOrder = (elements: readonly ExcalidrawElement[]) => {\n const origElements: ExcalidrawElement[] = elements.slice();\n const sortedElements = new Set<ExcalidrawElement>();\n\n const orderInnerGroups = (\n elements: readonly ExcalidrawElement[],\n ): ExcalidrawElement[] => {\n const firstGroupSig = elements[0]?.groupIds?.join(\"\");\n const aGroup: ExcalidrawElement[] = [elements[0]];\n const bGroup: ExcalidrawElement[] = [];\n for (const element of elements.slice(1)) {\n if (element.groupIds?.join(\"\") === firstGroupSig) {\n aGroup.push(element);\n } else {\n bGroup.push(element);\n }\n }\n return bGroup.length ? [...aGroup, ...orderInnerGroups(bGroup)] : aGroup;\n };\n\n const groupHandledElements = new Map<string, true>();\n\n origElements.forEach((element, idx) => {\n if (groupHandledElements.has(element.id)) {\n return;\n }\n if (element.groupIds?.length) {\n const topGroup = element.groupIds[element.groupIds.length - 1];\n const groupElements = origElements.slice(idx).filter((element) => {\n const ret = element?.groupIds?.some((id) => id === topGroup);\n if (ret) {\n groupHandledElements.set(element!.id, true);\n }\n return ret;\n });\n\n for (const elem of orderInnerGroups(groupElements)) {\n sortedElements.add(elem);\n }\n } else {\n sortedElements.add(element);\n }\n });\n\n // if there's a bug which resulted in losing some of the elements, return\n // original instead as that's better than losing data\n if (sortedElements.size !== elements.length) {\n console.error(\"normalizeGroupElementOrder: lost some elements... bailing!\");\n return elements;\n }\n\n return [...sortedElements];\n};\n\n/**\n * In theory, when we have text elements bound to a container, they\n * should be right after the container element in the elements array.\n * However, this is not guaranteed due to old and potential future bugs.\n *\n * This function sorts containers and their bound texts together. It prefers\n * original z-index of container (i.e. it moves bound text elements after\n * containers).\n */\nconst normalizeBoundElementsOrder = (\n elements: readonly ExcalidrawElement[],\n) => {\n const elementsMap = arrayToMapWithIndex(elements);\n\n const origElements: (ExcalidrawElement | null)[] = elements.slice();\n const sortedElements = new Set<ExcalidrawElement>();\n\n origElements.forEach((element, idx) => {\n if (!element) {\n return;\n }\n if (element.boundElements?.length) {\n sortedElements.add(element);\n origElements[idx] = null;\n element.boundElements.forEach((boundElement) => {\n const child = elementsMap.get(boundElement.id);\n if (child && boundElement.type === \"text\") {\n sortedElements.add(child[0]);\n origElements[child[1]] = null;\n }\n });\n } else if (element.type === \"text\" && element.containerId) {\n const parent = elementsMap.get(element.containerId);\n if (!parent?.[0].boundElements?.find((x) => x.id === element.id)) {\n sortedElements.add(element);\n origElements[idx] = null;\n\n // if element has a container and container lists it, skip this element\n // as it'll be taken care of by the container\n }\n } else {\n sortedElements.add(element);\n origElements[idx] = null;\n }\n });\n\n // if there's a bug which resulted in losing some of the elements, return\n // original instead as that's better than losing data\n if (sortedElements.size !== elements.length) {\n console.error(\n \"normalizeBoundElementsOrder: lost some elements... bailing!\",\n );\n return elements;\n }\n\n return [...sortedElements];\n};\n\nexport const normalizeElementOrder = (\n elements: readonly ExcalidrawElement[],\n) => {\n return normalizeBoundElementsOrder(normalizeGroupElementOrder(elements));\n};\n", "import {\n ORIG_ID,\n randomId,\n randomInteger,\n arrayToMap,\n castArray,\n findLastIndex,\n getUpdatedTimestamp,\n isTestEnv,\n} from \"@excalidraw/common\";\n\nimport type { Mutable } from \"@excalidraw/common/utility-types\";\n\nimport type { AppState } from \"@excalidraw/excalidraw/types\";\n\nimport {\n getElementsInGroup,\n getNewGroupIdsForDuplication,\n getSelectedGroupForElement,\n} from \"./groups\";\n\nimport {\n bindElementsToFramesAfterDuplication,\n getFrameChildren,\n} from \"./frame\";\n\nimport { normalizeElementOrder } from \"./sortElements\";\n\nimport { bumpVersion } from \"./mutateElement\";\n\nimport {\n hasBoundTextElement,\n isBoundToContainer,\n isFrameLikeElement,\n} from \"./typeChecks\";\n\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\n\nimport { fixDuplicatedBindingsAfterDuplication } from \"./binding\";\n\nimport type {\n ElementsMap,\n ExcalidrawElement,\n GroupId,\n NonDeletedSceneElementsMap,\n} from \"./types\";\n\n/**\n * Duplicate an element, often used in the alt-drag operation.\n * Note that this method has gotten a bit complicated since the\n * introduction of gruoping/ungrouping elements.\n * @param editingGroupId The current group being edited. The new\n * element will inherit this group and its\n * parents.\n * @param groupIdMapForOperation A Map that maps old group IDs to\n * duplicated ones. If you are duplicating\n * multiple elements at once, share this map\n * amongst all of them\n * @param element Element to duplicate\n */\nexport const duplicateElement = <TElement extends ExcalidrawElement>(\n editingGroupId: AppState[\"editingGroupId\"],\n groupIdMapForOperation: Map<GroupId, GroupId>,\n element: TElement,\n randomizeSeed?: boolean,\n): Readonly<TElement> => {\n const copy = deepCopyElement(element);\n\n if (isTestEnv()) {\n __test__defineOrigId(copy, element.id);\n }\n\n copy.id = randomId();\n copy.updated = getUpdatedTimestamp();\n if (randomizeSeed) {\n copy.seed = randomInteger();\n bumpVersion(copy);\n }\n\n copy.groupIds = getNewGroupIdsForDuplication(\n copy.groupIds,\n editingGroupId,\n (groupId) => {\n if (!groupIdMapForOperation.has(groupId)) {\n groupIdMapForOperation.set(groupId, randomId());\n }\n return groupIdMapForOperation.get(groupId)!;\n },\n );\n return copy;\n};\n\nexport const duplicateElements = (\n opts: {\n elements: readonly ExcalidrawElement[];\n randomizeSeed?: boolean;\n overrides?: (data: {\n duplicateElement: ExcalidrawElement;\n origElement: ExcalidrawElement;\n origIdToDuplicateId: Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement[\"id\"]\n >;\n }) => Partial<ExcalidrawElement>;\n } & (\n | {\n /**\n * Duplicates all elements in array.\n *\n * Use this when programmaticaly duplicating elements, without direct\n * user interaction.\n */\n type: \"everything\";\n }\n | {\n /**\n * Duplicates specified elements and inserts them back into the array\n * in specified order.\n *\n * Use this when duplicating Scene elements, during user interaction\n * such as alt-drag or on duplicate action.\n */\n type: \"in-place\";\n idsOfElementsToDuplicate: Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement\n >;\n appState: {\n editingGroupId: AppState[\"editingGroupId\"];\n selectedGroupIds: AppState[\"selectedGroupIds\"];\n };\n }\n ),\n) => {\n let { elements } = opts;\n\n const appState =\n \"appState\" in opts\n ? opts.appState\n : ({\n editingGroupId: null,\n selectedGroupIds: {},\n } as const);\n\n // Ids of elements that have already been processed so we don't push them\n // into the array twice if we end up backtracking when retrieving\n // discontiguous group of elements (can happen due to a bug, or in edge\n // cases such as a group containing deleted elements which were not selected).\n //\n // This is not enough to prevent duplicates, so we do a second loop afterwards\n // to remove them.\n //\n // For convenience we mark even the newly created ones even though we don't\n // loop over them.\n const processedIds = new Map<ExcalidrawElement[\"id\"], true>();\n const groupIdMap = new Map();\n const duplicatedElements: ExcalidrawElement[] = [];\n const origElements: ExcalidrawElement[] = [];\n const origIdToDuplicateId = new Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement[\"id\"]\n >();\n const duplicateIdToOrigElement = new Map<\n ExcalidrawElement[\"id\"],\n ExcalidrawElement\n >();\n const duplicateElementsMap = new Map<string, ExcalidrawElement>();\n const elementsMap = arrayToMap(elements) as ElementsMap;\n const _idsOfElementsToDuplicate =\n opts.type === \"in-place\"\n ? opts.idsOfElementsToDuplicate\n : new Map(elements.map((el) => [el.id, el]));\n\n // For sanity\n if (opts.type === \"in-place\") {\n for (const groupId of Object.keys(opts.appState.selectedGroupIds)) {\n elements\n .filter((el) => el.groupIds?.includes(groupId))\n .forEach((el) => _idsOfElementsToDuplicate.set(el.id, el));\n }\n }\n\n elements = normalizeElementOrder(elements);\n\n const elementsWithDuplicates: ExcalidrawElement[] = elements.slice();\n\n // helper functions\n // -------------------------------------------------------------------------\n\n // Used for the heavy lifing of copying a single element, a group of elements\n // an element with bound text etc.\n const copyElements = <T extends ExcalidrawElement | ExcalidrawElement[]>(\n element: T,\n ): T extends ExcalidrawElement[]\n ? ExcalidrawElement[]\n : ExcalidrawElement | null => {\n const elements = castArray(element);\n\n const _newElements = elements.reduce(\n (acc: ExcalidrawElement[], element) => {\n if (processedIds.has(element.id)) {\n return acc;\n }\n\n processedIds.set(element.id, true);\n\n const newElement = duplicateElement(\n appState.editingGroupId,\n groupIdMap,\n element,\n opts.randomizeSeed,\n );\n\n processedIds.set(newElement.id, true);\n\n duplicateElementsMap.set(newElement.id, newElement);\n origIdToDuplicateId.set(element.id, newElement.id);\n duplicateIdToOrigElement.set(newElement.id, element);\n\n origElements.push(element);\n duplicatedElements.push(newElement);\n\n acc.push(newElement);\n return acc;\n },\n [],\n );\n\n return (\n Array.isArray(element) ? _newElements : _newElements[0] || null\n ) as T extends ExcalidrawElement[]\n ? ExcalidrawElement[]\n : ExcalidrawElement | null;\n };\n\n // Helper to position cloned elements in the Z-order the product needs it\n const insertBeforeOrAfterIndex = (\n index: number,\n elements: ExcalidrawElement | null | ExcalidrawElement[],\n ) => {\n if (!elements) {\n return;\n }\n\n if (index > elementsWithDuplicates.length - 1) {\n elementsWithDuplicates.push(...castArray(elements));\n return;\n }\n\n elementsWithDuplicates.splice(index + 1, 0, ...castArray(elements));\n };\n\n const frameIdsToDuplicate = new Set(\n elements\n .filter(\n (el) => _idsOfElementsToDuplicate.has(el.id) && isFrameLikeElement(el),\n )\n .map((el) => el.id),\n );\n\n for (const element of elements) {\n if (processedIds.has(element.id)) {\n continue;\n }\n\n if (!_idsOfElementsToDuplicate.has(element.id)) {\n continue;\n }\n\n // groups\n // -------------------------------------------------------------------------\n\n const groupId = getSelectedGroupForElement(appState, element);\n if (groupId) {\n const groupElements = getElementsInGroup(elements, groupId).flatMap(\n (element) =>\n isFrameLikeElement(element)\n ? [...getFrameChildren(elements, element.id), element]\n : [element],\n );\n\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\n return el.groupIds?.includes(groupId);\n });\n\n insertBeforeOrAfterIndex(targetIndex, copyElements(groupElements));\n continue;\n }\n\n // frame duplication\n // -------------------------------------------------------------------------\n\n if (element.frameId && frameIdsToDuplicate.has(element.frameId)) {\n continue;\n }\n\n if (isFrameLikeElement(element)) {\n const frameId = element.id;\n\n const frameChildren = getFrameChildren(elements, frameId);\n\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\n return el.frameId === frameId || el.id === frameId;\n });\n\n insertBeforeOrAfterIndex(\n targetIndex,\n copyElements([...frameChildren, element]),\n );\n continue;\n }\n\n // text container\n // -------------------------------------------------------------------------\n\n if (hasBoundTextElement(element)) {\n const boundTextElement = getBoundTextElement(element, elementsMap);\n\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\n return (\n el.id === element.id ||\n (\"containerId\" in el && el.containerId === element.id)\n );\n });\n\n if (boundTextElement) {\n insertBeforeOrAfterIndex(\n targetIndex,\n copyElements([element, boundTextElement]),\n );\n } else {\n insertBeforeOrAfterIndex(targetIndex, copyElements(element));\n }\n\n continue;\n }\n\n if (isBoundToContainer(element)) {\n const container = getContainerElement(element, elementsMap);\n\n const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {\n return el.id === element.id || el.id === container?.id;\n });\n\n if (container) {\n insertBeforeOrAfterIndex(\n targetIndex,\n copyElements([container, element]),\n );\n } else {\n insertBeforeOrAfterIndex(targetIndex, copyElements(element));\n }\n\n continue;\n }\n\n // default duplication (regular elements)\n // -------------------------------------------------------------------------\n\n insertBeforeOrAfterIndex(\n findLastIndex(elementsWithDuplicates, (el) => el.id === element.id),\n copyElements(element),\n );\n }\n\n // ---------------------------------------------------------------------------\n\n fixDuplicatedBindingsAfterDuplication(\n duplicatedElements,\n origIdToDuplicateId,\n duplicateElementsMap as NonDeletedSceneElementsMap,\n );\n\n bindElementsToFramesAfterDuplication(\n elementsWithDuplicates,\n origElements,\n origIdToDuplicateId,\n );\n\n if (opts.overrides) {\n for (const duplicateElement of duplicatedElements) {\n const origElement = duplicateIdToOrigElement.get(duplicateElement.id);\n if (origElement) {\n Object.assign(\n duplicateElement,\n opts.overrides({\n duplicateElement,\n origElement,\n origIdToDuplicateId,\n }),\n );\n }\n }\n }\n\n return {\n duplicatedElements,\n duplicateElementsMap,\n elementsWithDuplicates,\n origIdToDuplicateId,\n };\n};\n\n// Simplified deep clone for the purpose of cloning ExcalidrawElement.\n//\n// Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\n// Typed arrays and other non-null objects.\n//\n// Adapted from https://github.com/lukeed/klona\n//\n// The reason for `deepCopyElement()` wrapper is type safety (only allow\n// passing ExcalidrawElement as the top-level argument).\nconst _deepCopyElement = (val: any, depth: number = 0) => {\n // only clone non-primitives\n if (val == null || typeof val !== \"object\") {\n return val;\n }\n\n const objectType = Object.prototype.toString.call(val);\n\n if (objectType === \"[object Object]\") {\n const tmp =\n typeof val.constructor === \"function\"\n ? Object.create(Object.getPrototypeOf(val))\n : {};\n for (const key in val) {\n if (val.hasOwnProperty(key)) {\n // don't copy non-serializable objects like these caches. They'll be\n // populated when the element is rendered.\n if (depth === 0 && (key === \"shape\" || key === \"canvas\")) {\n continue;\n }\n tmp[key] = _deepCopyElement(val[key], depth + 1);\n }\n }\n return tmp;\n }\n\n if (Array.isArray(val)) {\n let k = val.length;\n const arr = new Array(k);\n while (k--) {\n arr[k] = _deepCopyElement(val[k], depth + 1);\n }\n return arr;\n }\n\n // we're not cloning non-array & non-plain-object objects because we\n // don't support them on excalidraw elements yet. If we do, we need to make\n // sure we start cloning them, so let's warn about it.\n if (import.meta.env.DEV) {\n if (\n objectType !== \"[object Object]\" &&\n objectType !== \"[object Array]\" &&\n objectType.startsWith(\"[object \")\n ) {\n console.warn(\n `_deepCloneElement: unexpected object type ${objectType}. This value will not be cloned!`,\n );\n }\n }\n\n return val;\n};\n\n/**\n * Clones ExcalidrawElement data structure. Does not regenerate id, nonce, or\n * any value. The purpose is to to break object references for immutability\n * reasons, whenever we want to keep the original element, but ensure it's not\n * mutated.\n *\n * Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set,\n * Typed arrays and other non-null objects.\n */\nexport const deepCopyElement = <T extends ExcalidrawElement>(\n val: T,\n): Mutable<T> => {\n return _deepCopyElement(val);\n};\n\nconst __test__defineOrigId = (clonedObj: object, origId: string) => {\n Object.defineProperty(clonedObj, ORIG_ID, {\n value: origId,\n writable: false,\n enumerable: false,\n });\n};\n", "import {\n assertNever,\n COLOR_PALETTE,\n isDevEnv,\n isTestEnv,\n randomId,\n Emitter,\n toIterable,\n} from \"@excalidraw/common\";\n\nimport type App from \"@excalidraw/excalidraw/components/App\";\n\nimport type { DTO, ValueOf } from \"@excalidraw/common/utility-types\";\n\nimport type { AppState, ObservedAppState } from \"@excalidraw/excalidraw/types\";\n\nimport { deepCopyElement } from \"./duplicate\";\nimport { newElementWith } from \"./mutateElement\";\n\nimport { ElementsDelta, AppStateDelta, Delta } from \"./delta\";\n\nimport {\n syncInvalidIndicesImmutable,\n hashElementsVersion,\n hashString,\n isInitializedImageElement,\n isImageElement,\n} from \"./index\";\n\nimport type { ApplyToOptions } from \"./delta\";\n\nimport type {\n ExcalidrawElement,\n OrderedExcalidrawElement,\n SceneElementsMap,\n} from \"./types\";\n\nexport const CaptureUpdateAction = {\n /**\n * Immediately undoable.\n *\n * Use for updates which should be captured.\n * Should be used for most of the local updates, except ephemerals such as dragging or resizing.\n *\n * These updates will _immediately_ make it to the local undo / redo stacks.\n */\n IMMEDIATELY: \"IMMEDIATELY\",\n /**\n * Never undoable.\n *\n * Use for updates which should never be recorded, such as remote updates\n * or scene initialization.\n *\n * These updates will _never_ make it to the local undo / redo stacks.\n */\n NEVER: \"NEVER\",\n /**\n * Eventually undoable.\n *\n * Use for updates which should not be captured immediately - likely\n * exceptions which are part of some async multi-step process. Otherwise, all\n * such updates would end up being captured with the next\n * `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene`\n * or internally by the editor.\n *\n * These updates will _eventually_ make it to the local undo / redo stacks.\n */\n EVENTUALLY: \"EVENTUALLY\",\n} as const;\n\nexport type CaptureUpdateActionType = ValueOf<typeof CaptureUpdateAction>;\n\ntype MicroActionsQueue = (() => void)[];\n\n/**\n * Store which captures the observed changes and emits them as `StoreIncrement` events.\n */\nexport class Store {\n // for internal use by history\n public readonly onDurableIncrementEmitter = new Emitter<[DurableIncrement]>();\n // for public use as part of onIncrement API\n public readonly onStoreIncrementEmitter = new Emitter<\n [DurableIncrement | EphemeralIncrement]\n >();\n\n private scheduledMacroActions: Set<CaptureUpdateActionType> = new Set();\n private scheduledMicroActions: MicroActionsQueue = [];\n\n private _snapshot = StoreSnapshot.empty();\n\n public get snapshot() {\n return this._snapshot;\n }\n\n public set snapshot(snapshot: StoreSnapshot) {\n this._snapshot = snapshot;\n }\n\n constructor(private readonly app: App) {}\n\n public scheduleAction(action: CaptureUpdateActionType) {\n this.scheduledMacroActions.add(action);\n this.satisfiesScheduledActionsInvariant();\n }\n\n /**\n * Use to schedule a delta calculation, which will consquentially be emitted as `DurableStoreIncrement` and pushed in the undo stack.\n */\n // TODO: Suspicious that this is called so many places. Seems error-prone.\n public scheduleCapture() {\n this.scheduleAction(CaptureUpdateAction.IMMEDIATELY);\n }\n\n /**\n * Schedule special \"micro\" actions, to-be executed before the next commit, before it executes a scheduled \"macro\" action.\n */\n public scheduleMicroAction(\n params:\n | {\n action: CaptureUpdateActionType;\n elements: readonly ExcalidrawElement[] | undefined;\n appState: AppState | ObservedAppState | undefined;\n }\n | {\n action: typeof CaptureUpdateAction.IMMEDIATELY;\n change: StoreChange;\n delta: StoreDelta;\n }\n | {\n action:\n | typeof CaptureUpdateAction.NEVER\n | typeof CaptureUpdateAction.EVENTUALLY;\n change: StoreChange;\n },\n ) {\n const { action } = params;\n\n let change: StoreChange;\n\n if (\"change\" in params) {\n change = params.change;\n } else {\n // immediately create an immutable change of the scheduled updates,\n // compared to the current state, so that they won't mutate later on during batching\n // also, we have to compare against the current state,\n // as comparing against the snapshot might include yet uncomitted changes (i.e. async freedraw / text / image, etc.)\n const currentSnapshot = StoreSnapshot.create(\n this.app.scene.getElementsMapIncludingDeleted(),\n this.app.state,\n );\n\n const scheduledSnapshot = currentSnapshot.maybeClone(\n action,\n // let's sync invalid indices first, so that we could detect this change\n // also have the synced elements immutable, so that we don't mutate elements,\n // that are already in the scene, otherwise we wouldn't see any change\n params.elements\n ? syncInvalidIndicesImmutable(params.elements)\n : undefined,\n params.appState,\n );\n\n change = StoreChange.create(currentSnapshot, scheduledSnapshot);\n }\n\n const delta = \"delta\" in params ? params.delta : undefined;\n\n this.scheduledMicroActions.push(() =>\n this.processAction({\n action,\n change,\n delta,\n }),\n );\n }\n\n /**\n * Performs the incoming `CaptureUpdateAction` and emits the corresponding `StoreIncrement`.\n * Emits `DurableStoreIncrement` when action is \"capture\", emits `EphemeralStoreIncrement` otherwise.\n *\n * @emits StoreIncrement\n */\n public commit(\n elements: SceneElementsMap | undefined,\n appState: AppState | ObservedAppState | undefined,\n ): void {\n // execute all scheduled micro actions first\n // similar to microTasks, there can be many\n this.flushMicroActions();\n\n try {\n // execute a single scheduled \"macro\" function\n // similar to macro tasks, there can be only one within a single commit (loop)\n const action = this.getScheduledMacroAction();\n this.processAction({ action, elements, appState });\n } finally {\n this.satisfiesScheduledActionsInvariant();\n // defensively reset all scheduled \"macro\" actions, possibly cleans up other runtime garbage\n this.scheduledMacroActions = new Set();\n }\n }\n\n /**\n * Clears the store instance.\n */\n public clear(): void {\n this.snapshot = StoreSnapshot.empty();\n this.scheduledMacroActions = new Set();\n }\n\n /**\n * Performs delta & change calculation and emits a durable increment.\n *\n * @emits StoreIncrement.\n */\n private emitDurableIncrement(\n snapshot: StoreSnapshot,\n change: StoreChange | undefined = undefined,\n delta: StoreDelta | undefined = undefined,\n ) {\n const prevSnapshot = this.snapshot;\n\n let storeChange: StoreChange;\n let storeDelta: StoreDelta;\n\n if (change) {\n storeChange = change;\n } else {\n storeChange = StoreChange.create(prevSnapshot, snapshot);\n }\n\n if (delta) {\n // we might have the delta already (i.e. when applying history entry), thus we don't need to calculate it again\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\n storeDelta = delta;\n } else {\n storeDelta = StoreDelta.calculate(prevSnapshot, snapshot);\n }\n\n if (!storeDelta.isEmpty()) {\n const increment = new DurableIncrement(storeChange, storeDelta);\n\n this.onDurableIncrementEmitter.trigger(increment);\n this.onStoreIncrementEmitter.trigger(increment);\n }\n }\n\n /**\n * Performs change calculation and emits an ephemeral increment.\n *\n * @emits EphemeralStoreIncrement\n */\n private emitEphemeralIncrement(\n snapshot: StoreSnapshot,\n change: StoreChange | undefined = undefined,\n ) {\n let storeChange: StoreChange;\n\n if (change) {\n storeChange = change;\n } else {\n const prevSnapshot = this.snapshot;\n storeChange = StoreChange.create(prevSnapshot, snapshot);\n }\n\n const increment = new EphemeralIncrement(storeChange);\n\n // Notify listeners with the increment\n this.onStoreIncrementEmitter.trigger(increment);\n }\n\n private applyChangeToSnapshot(change: StoreChange) {\n const prevSnapshot = this.snapshot;\n const nextSnapshot = this.snapshot.applyChange(change);\n\n if (prevSnapshot === nextSnapshot) {\n return null;\n }\n\n return nextSnapshot;\n }\n\n /**\n * Clones the snapshot if there are changes detected.\n */\n private maybeCloneSnapshot(\n action: CaptureUpdateActionType,\n elements: SceneElementsMap | undefined,\n appState: AppState | ObservedAppState | undefined,\n ) {\n if (!elements && !appState) {\n return null;\n }\n\n const prevSnapshot = this.snapshot;\n const nextSnapshot = this.snapshot.maybeClone(action, elements, appState);\n\n if (prevSnapshot === nextSnapshot) {\n return null;\n }\n\n return nextSnapshot;\n }\n\n private flushMicroActions() {\n for (const microAction of this.scheduledMicroActions) {\n try {\n microAction();\n } catch (error) {\n console.error(`Failed to execute scheduled micro action`, error);\n }\n }\n\n this.scheduledMicroActions = [];\n }\n\n private processAction(\n params:\n | {\n action: CaptureUpdateActionType;\n elements: SceneElementsMap | undefined;\n appState: AppState | ObservedAppState | undefined;\n }\n | {\n action: CaptureUpdateActionType;\n change: StoreChange;\n delta: StoreDelta | undefined;\n },\n ) {\n const { action } = params;\n\n // perf. optimisation, since \"EVENTUALLY\" does not update the snapshot,\n // so if nobody is listening for increments, we don't need to even clone the snapshot\n // as it's only needed for `StoreChange` computation inside `EphemeralIncrement`\n if (\n action === CaptureUpdateAction.EVENTUALLY &&\n !this.onStoreIncrementEmitter.subscribers.length\n ) {\n return;\n }\n\n let nextSnapshot: StoreSnapshot | null;\n\n if (\"change\" in params) {\n nextSnapshot = this.applyChangeToSnapshot(params.change);\n } else {\n nextSnapshot = this.maybeCloneSnapshot(\n action,\n params.elements,\n params.appState,\n );\n }\n\n if (!nextSnapshot) {\n // don't continue if there is not change detected\n return;\n }\n\n const change = \"change\" in params ? params.change : undefined;\n const delta = \"delta\" in params ? params.delta : undefined;\n\n try {\n switch (action) {\n // only immediately emits a durable increment\n case CaptureUpdateAction.IMMEDIATELY:\n this.emitDurableIncrement(nextSnapshot, change, delta);\n break;\n // both never and eventually emit an ephemeral increment\n case CaptureUpdateAction.NEVER:\n case CaptureUpdateAction.EVENTUALLY:\n this.emitEphemeralIncrement(nextSnapshot, change);\n break;\n default:\n assertNever(action, `Unknown store action`);\n }\n } finally {\n // update the snapshot no-matter what, as it would mess up with the next action\n switch (action) {\n // both immediately and never update the snapshot, unlike eventually\n case CaptureUpdateAction.IMMEDIATELY:\n case CaptureUpdateAction.NEVER:\n this.snapshot = nextSnapshot;\n break;\n }\n }\n }\n\n /**\n * Returns the scheduled macro action.\n */\n private getScheduledMacroAction() {\n let scheduledAction: CaptureUpdateActionType;\n\n if (this.scheduledMacroActions.has(CaptureUpdateAction.IMMEDIATELY)) {\n // Capture has a precedence over update, since it also performs snapshot update\n scheduledAction = CaptureUpdateAction.IMMEDIATELY;\n } else if (this.scheduledMacroActions.has(CaptureUpdateAction.NEVER)) {\n // Update has a precedence over none, since it also emits an (ephemeral) increment\n scheduledAction = CaptureUpdateAction.NEVER;\n } else {\n // Default is to emit ephemeral increment and don't update the snapshot\n scheduledAction = CaptureUpdateAction.EVENTUALLY;\n }\n\n return scheduledAction;\n }\n\n /**\n * Ensures that the scheduled actions invariant is satisfied.\n */\n private satisfiesScheduledActionsInvariant() {\n if (\n !(\n this.scheduledMacroActions.size >= 0 &&\n this.scheduledMacroActions.size <=\n Object.keys(CaptureUpdateAction).length\n )\n ) {\n const message = `There can be at most three store actions scheduled at the same time, but there are \"${this.scheduledMacroActions.size}\".`;\n console.error(message, this.scheduledMacroActions.values());\n\n if (isTestEnv() || isDevEnv()) {\n throw new Error(message);\n }\n }\n }\n}\n\n/**\n * Repsents a change to the store containing changed elements and appState.\n */\nexport class StoreChange {\n // so figuring out what has changed should ideally be just quick reference checks\n // TODO: we might need to have binary files here as well, in order to be drop-in replacement for `onChange`\n private constructor(\n public readonly elements: Record<string, OrderedExcalidrawElement>,\n public readonly appState: Partial<ObservedAppState>,\n ) {}\n\n public static create(\n prevSnapshot: StoreSnapshot,\n nextSnapshot: StoreSnapshot,\n ) {\n const changedElements = nextSnapshot.getChangedElements(prevSnapshot);\n const changedAppState = nextSnapshot.getChangedAppState(prevSnapshot);\n\n return new StoreChange(changedElements, changedAppState);\n }\n}\n\n/**\n * Encpasulates any change to the store (durable or ephemeral).\n */\nexport abstract class StoreIncrement {\n protected constructor(\n public readonly type: \"durable\" | \"ephemeral\",\n public readonly change: StoreChange,\n ) {}\n\n public static isDurable(\n increment: StoreIncrement,\n ): increment is DurableIncrement {\n return increment.type === \"durable\";\n }\n\n public static isEphemeral(\n increment: StoreIncrement,\n ): increment is EphemeralIncrement {\n return increment.type === \"ephemeral\";\n }\n}\n\n/**\n * Represents a durable change to the store.\n */\nexport class DurableIncrement extends StoreIncrement {\n constructor(\n public readonly change: StoreChange,\n public readonly delta: StoreDelta,\n ) {\n super(\"durable\", change);\n }\n}\n\n/**\n * Represents an ephemeral change to the store.\n */\nexport class EphemeralIncrement extends StoreIncrement {\n constructor(public readonly change: StoreChange) {\n super(\"ephemeral\", change);\n }\n}\n\n/**\n * Represents a captured delta by the Store.\n */\nexport class StoreDelta {\n protected constructor(\n public readonly id: string,\n public readonly elements: ElementsDelta,\n public readonly appState: AppStateDelta,\n ) {}\n\n /**\n * Create a new instance of `StoreDelta`.\n */\n public static create(\n elements: ElementsDelta,\n appState: AppStateDelta,\n opts: {\n id: string;\n } = {\n id: randomId(),\n },\n ) {\n return new this(opts.id, elements, appState);\n }\n\n /**\n * Calculate the delta between the previous and next snapshot.\n */\n public static calculate(\n prevSnapshot: StoreSnapshot,\n nextSnapshot: StoreSnapshot,\n ) {\n const elementsDelta = nextSnapshot.metadata.didElementsChange\n ? ElementsDelta.calculate(prevSnapshot.elements, nextSnapshot.elements)\n : ElementsDelta.empty();\n\n const appStateDelta = nextSnapshot.metadata.didAppStateChange\n ? AppStateDelta.calculate(prevSnapshot.appState, nextSnapshot.appState)\n : AppStateDelta.empty();\n\n return this.create(elementsDelta, appStateDelta);\n }\n\n /**\n * Restore a store delta instance from a DTO.\n */\n public static restore(storeDeltaDTO: DTO<StoreDelta>) {\n const { id, elements, appState } = storeDeltaDTO;\n return new this(\n id,\n ElementsDelta.restore(elements),\n AppStateDelta.restore(appState),\n );\n }\n\n /**\n * Parse and load the delta from the remote payload.\n */\n public static load({\n id,\n elements: { added, removed, updated },\n appState: { delta: appStateDelta },\n }: DTO<StoreDelta>) {\n const elements = ElementsDelta.create(added, removed, updated);\n const appState = AppStateDelta.create(appStateDelta);\n\n return new this(id, elements, appState);\n }\n\n /**\n * Squash the passed deltas into the aggregated delta instance.\n */\n public static squash(...deltas: StoreDelta[]) {\n const aggregatedDelta = StoreDelta.empty();\n\n for (const delta of deltas) {\n aggregatedDelta.elements.squash(delta.elements);\n aggregatedDelta.appState.squash(delta.appState);\n }\n\n return aggregatedDelta;\n }\n\n /**\n * Inverse store delta, creates new instance of `StoreDelta`.\n */\n public static inverse(delta: StoreDelta) {\n return this.create(delta.elements.inverse(), delta.appState.inverse());\n }\n\n /**\n * Apply the delta to the passed elements and appState, does not modify the snapshot.\n */\n public static applyTo(\n delta: StoreDelta,\n elements: SceneElementsMap,\n appState: AppState,\n options?: ApplyToOptions,\n ): [SceneElementsMap, AppState, boolean] {\n const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(\n elements,\n StoreSnapshot.empty().elements,\n options,\n );\n\n const [nextAppState, appStateContainsVisibleChange] =\n delta.appState.applyTo(appState, nextElements);\n\n const appliedVisibleChanges =\n elementsContainVisibleChange || appStateContainsVisibleChange;\n\n return [nextElements, nextAppState, appliedVisibleChanges];\n }\n\n /**\n * Apply latest (remote) changes to the delta, creates new instance of `StoreDelta`.\n */\n public static applyLatestChanges(\n delta: StoreDelta,\n prevElements: SceneElementsMap,\n nextElements: SceneElementsMap,\n modifierOptions?: \"deleted\" | \"inserted\",\n ): StoreDelta {\n return this.create(\n delta.elements.applyLatestChanges(\n prevElements,\n nextElements,\n modifierOptions,\n ),\n delta.appState,\n {\n id: delta.id,\n },\n );\n }\n\n public static empty() {\n return StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());\n }\n\n public isEmpty() {\n return this.elements.isEmpty() && this.appState.isEmpty();\n }\n}\n\n/**\n * Represents a snapshot of the captured or updated changes in the store,\n * used for producing deltas and emitting `DurableStoreIncrement`s.\n */\nexport class StoreSnapshot {\n private _lastChangedElementsHash: number = 0;\n private _lastChangedAppStateHash: number = 0;\n\n private constructor(\n public readonly elements: SceneElementsMap,\n public readonly appState: ObservedAppState,\n public readonly metadata: {\n didElementsChange: boolean;\n didAppStateChange: boolean;\n isEmpty?: boolean;\n } = {\n didElementsChange: false,\n didAppStateChange: false,\n isEmpty: false,\n },\n ) {}\n\n public static create(\n elements: SceneElementsMap,\n appState: AppState | ObservedAppState,\n metadata: {\n didElementsChange: boolean;\n didAppStateChange: boolean;\n } = {\n didElementsChange: false,\n didAppStateChange: false,\n },\n ) {\n return new StoreSnapshot(\n elements,\n isObservedAppState(appState) ? appState : getObservedAppState(appState),\n metadata,\n );\n }\n\n public static empty() {\n return new StoreSnapshot(\n new Map() as SceneElementsMap,\n getDefaultObservedAppState(),\n {\n didElementsChange: false,\n didAppStateChange: false,\n isEmpty: true,\n },\n );\n }\n\n public getChangedElements(prevSnapshot: StoreSnapshot) {\n const changedElements: Record<string, OrderedExcalidrawElement> = {};\n\n for (const prevElement of toIterable(prevSnapshot.elements)) {\n const nextElement = this.elements.get(prevElement.id);\n\n if (!nextElement) {\n changedElements[prevElement.id] = newElementWith(prevElement, {\n isDeleted: true,\n });\n }\n }\n\n for (const nextElement of toIterable(this.elements)) {\n // Due to the structural clone inside `maybeClone`, we can perform just these reference checks\n if (prevSnapshot.elements.get(nextElement.id) !== nextElement) {\n changedElements[nextElement.id] = nextElement;\n }\n }\n\n return changedElements;\n }\n\n public getChangedAppState(\n prevSnapshot: StoreSnapshot,\n ): Partial<ObservedAppState> {\n return Delta.getRightDifferences(\n prevSnapshot.appState,\n this.appState,\n ).reduce(\n (acc, key) =>\n Object.assign(acc, {\n [key]: this.appState[key as keyof ObservedAppState],\n }),\n {} as Partial<ObservedAppState>,\n );\n }\n\n public isEmpty() {\n return this.metadata.isEmpty;\n }\n\n /**\n * Apply the change and return a new snapshot instance.\n */\n public applyChange(change: StoreChange): StoreSnapshot {\n const nextElements = new Map(this.elements) as SceneElementsMap;\n\n for (const [id, changedElement] of Object.entries(change.elements)) {\n nextElements.set(id, changedElement);\n }\n\n const nextAppState = getObservedAppState({\n ...this.appState,\n ...change.appState,\n });\n\n return StoreSnapshot.create(nextElements, nextAppState, {\n // by default we assume that change is different from what we have in the snapshot\n // so that we trigger the delta calculation and if it isn't different, delta will be empty\n didElementsChange: Object.keys(change.elements).length > 0,\n didAppStateChange: Object.keys(change.appState).length > 0,\n });\n }\n\n /**\n * Efficiently clone the existing snapshot, only if we detected changes.\n *\n * @returns same instance if there are no changes detected, new instance otherwise.\n */\n public maybeClone(\n action: CaptureUpdateActionType,\n elements: SceneElementsMap | undefined,\n appState: AppState | ObservedAppState | undefined,\n ) {\n const options = {\n shouldCompareHashes: false,\n };\n\n if (action === CaptureUpdateAction.EVENTUALLY) {\n // actions that do not update the snapshot immediately, must be additionally checked for changes against the latest hash\n // as we are always comparing against the latest snapshot, so they would emit elements or appState as changed on every component update\n // instead of just the first time the elements or appState actually changed\n options.shouldCompareHashes = true;\n }\n\n const nextElementsSnapshot = this.maybeCreateElementsSnapshot(\n elements,\n options,\n );\n const nextAppStateSnapshot = this.maybeCreateAppStateSnapshot(\n appState,\n options,\n );\n\n let didElementsChange = false;\n let didAppStateChange = false;\n\n if (this.elements !== nextElementsSnapshot) {\n didElementsChange = true;\n }\n\n if (this.appState !== nextAppStateSnapshot) {\n didAppStateChange = true;\n }\n\n if (!didElementsChange && !didAppStateChange) {\n return this;\n }\n\n const snapshot = new StoreSnapshot(\n nextElementsSnapshot,\n nextAppStateSnapshot,\n {\n didElementsChange,\n didAppStateChange,\n },\n );\n\n return snapshot;\n }\n\n private maybeCreateAppStateSnapshot(\n appState: AppState | ObservedAppState | undefined,\n options: {\n shouldCompareHashes: boolean;\n } = {\n shouldCompareHashes: false,\n },\n ): ObservedAppState {\n if (!appState) {\n return this.appState;\n }\n\n // Not watching over everything from the app state, just the relevant props\n const nextAppStateSnapshot = !isObservedAppState(appState)\n ? getObservedAppState(appState)\n : appState;\n\n const didAppStateChange = this.detectChangedAppState(\n nextAppStateSnapshot,\n options,\n );\n\n if (!didAppStateChange) {\n return this.appState;\n }\n\n return nextAppStateSnapshot;\n }\n\n private maybeCreateElementsSnapshot(\n elements: SceneElementsMap | undefined,\n options: {\n shouldCompareHashes: boolean;\n } = {\n shouldCompareHashes: false,\n },\n ): SceneElementsMap {\n if (!elements) {\n return this.elements;\n }\n\n const changedElements = this.detectChangedElements(elements, options);\n\n if (!changedElements?.size) {\n return this.elements;\n }\n\n const elementsSnapshot = this.createElementsSnapshot(changedElements);\n return elementsSnapshot;\n }\n\n private detectChangedAppState(\n nextObservedAppState: ObservedAppState,\n options: {\n shouldCompareHashes: boolean;\n } = {\n shouldCompareHashes: false,\n },\n ): boolean | undefined {\n if (this.appState === nextObservedAppState) {\n return;\n }\n\n const didAppStateChange = Delta.isRightDifferent(\n this.appState,\n nextObservedAppState,\n );\n\n if (!didAppStateChange) {\n return;\n }\n\n const changedAppStateHash = hashString(\n JSON.stringify(nextObservedAppState),\n );\n\n if (\n options.shouldCompareHashes &&\n this._lastChangedAppStateHash === changedAppStateHash\n ) {\n return;\n }\n\n this._lastChangedAppStateHash = changedAppStateHash;\n\n return didAppStateChange;\n }\n\n /**\n * Detect if there are any changed elements.\n */\n private detectChangedElements(\n nextElements: SceneElementsMap,\n options: {\n shouldCompareHashes: boolean;\n } = {\n shouldCompareHashes: false,\n },\n ): SceneElementsMap | undefined {\n if (this.elements === nextElements) {\n return;\n }\n\n const changedElements: SceneElementsMap = new Map() as SceneElementsMap;\n\n for (const prevElement of toIterable(this.elements)) {\n const nextElement = nextElements.get(prevElement.id);\n\n if (!nextElement) {\n // element was deleted\n changedElements.set(\n prevElement.id,\n newElementWith(prevElement, { isDeleted: true }),\n );\n }\n }\n\n for (const nextElement of toIterable(nextElements)) {\n const prevElement = this.elements.get(nextElement.id);\n\n if (\n !prevElement || // element was added\n prevElement.version < nextElement.version // element was updated\n ) {\n if (\n isImageElement(nextElement) &&\n !isInitializedImageElement(nextElement)\n ) {\n // ignore any updates on uninitialized image elements\n continue;\n }\n\n changedElements.set(nextElement.id, nextElement);\n }\n }\n\n if (!changedElements.size) {\n return;\n }\n\n const changedElementsHash = hashElementsVersion(changedElements);\n\n if (\n options.shouldCompareHashes &&\n this._lastChangedElementsHash === changedElementsHash\n ) {\n return;\n }\n\n this._lastChangedElementsHash = changedElementsHash;\n\n return changedElements;\n }\n\n /**\n * Perform structural clone, deep cloning only elements that changed.\n */\n private createElementsSnapshot(changedElements: SceneElementsMap) {\n const clonedElements = new Map() as SceneElementsMap;\n\n for (const prevElement of toIterable(this.elements)) {\n // Clone previous elements, never delete, in case nextElements would be just a subset of previous elements\n // i.e. during collab, persist or whenenever isDeleted elements get cleared\n clonedElements.set(prevElement.id, prevElement);\n }\n\n for (const changedElement of toIterable(changedElements)) {\n // TODO: consider just creating new instance, once we can ensure that all reference properties on every element are immutable\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\n clonedElements.set(changedElement.id, deepCopyElement(changedElement));\n }\n\n return clonedElements;\n }\n}\n\n// hidden non-enumerable property for runtime checks\nconst hiddenObservedAppStateProp = \"__observedAppState\";\n\nconst getDefaultObservedAppState = (): ObservedAppState => {\n return {\n name: null,\n editingGroupId: null,\n viewBackgroundColor: COLOR_PALETTE.white,\n selectedElementIds: {},\n selectedGroupIds: {},\n selectedLinearElement: null,\n croppingElementId: null,\n activeLockedId: null,\n lockedMultiSelections: {},\n };\n};\n\nexport const getObservedAppState = (\n appState: AppState | ObservedAppState,\n): ObservedAppState => {\n const observedAppState = {\n name: appState.name,\n editingGroupId: appState.editingGroupId,\n viewBackgroundColor: appState.viewBackgroundColor,\n selectedElementIds: appState.selectedElementIds,\n selectedGroupIds: appState.selectedGroupIds,\n croppingElementId: appState.croppingElementId,\n activeLockedId: appState.activeLockedId,\n lockedMultiSelections: appState.lockedMultiSelections,\n selectedLinearElement: appState.selectedLinearElement\n ? {\n elementId: appState.selectedLinearElement.elementId,\n isEditing: !!appState.selectedLinearElement.isEditing,\n }\n : null,\n };\n\n Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {\n value: true,\n enumerable: false,\n });\n\n return observedAppState;\n};\n\nconst isObservedAppState = (\n appState: AppState | ObservedAppState,\n): appState is ObservedAppState =>\n !!Reflect.get(appState, hiddenObservedAppStateProp);\n", "import { generateNKeysBetween } from \"fractional-indexing\";\n\nimport { arrayToMap } from \"@excalidraw/common\";\n\nimport { mutateElement, newElementWith } from \"./mutateElement\";\nimport { getBoundTextElement } from \"./textElement\";\nimport { hasBoundTextElement } from \"./typeChecks\";\n\nimport type {\n ElementsMap,\n ExcalidrawElement,\n FractionalIndex,\n OrderedExcalidrawElement,\n SceneElementsMap,\n} from \"./types\";\n\nexport class InvalidFractionalIndexError extends Error {\n public code = \"ELEMENT_HAS_INVALID_INDEX\" as const;\n}\n\n/**\n * Envisioned relation between array order and fractional indices:\n *\n * 1) Array (or array-like ordered data structure) should be used as a cache of elements order, hiding the internal fractional indices implementation.\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\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)\n * - it's necessary to always keep the array support for backwards compatibility (restore) - old scenes, old libraries, supporting multiple excalidraw versions etc.\n * - it's necessary to always keep the fractional indices in sync with the array order\n * - elements with invalid indices should be detected and synced, without altering the already valid indices\n *\n * 2) Fractional indices should be used to reorder the elements, whenever the cached order is expected to be invalidated.\n * - as the fractional indices are encoded as part of the elements, it opens up possibilities for incremental-like APIs\n * - re-order based on fractional indices should be part of (multiplayer) operations such as reconciliation & undo/redo\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,\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\n */\n\n/**\n * Ensure that all elements have valid fractional indices.\n *\n * @throws `InvalidFractionalIndexError` if invalid index is detected.\n */\nexport const validateFractionalIndices = (\n elements: readonly ExcalidrawElement[],\n {\n shouldThrow = false,\n includeBoundTextValidation = false,\n ignoreLogs,\n reconciliationContext,\n }: {\n shouldThrow: boolean;\n includeBoundTextValidation: boolean;\n ignoreLogs?: true;\n reconciliationContext?: {\n localElements: ReadonlyArray<ExcalidrawElement>;\n remoteElements: ReadonlyArray<ExcalidrawElement>;\n };\n },\n) => {\n const errorMessages = [];\n const stringifyElement = (element: ExcalidrawElement | void) =>\n `${element?.index}:${element?.id}:${element?.type}:${element?.isDeleted}:${element?.version}:${element?.versionNonce}`;\n\n const indices = elements.map((x) => x.index);\n for (const [i, index] of indices.entries()) {\n const predecessorIndex = indices[i - 1];\n const successorIndex = indices[i + 1];\n\n if (!isValidFractionalIndex(index, predecessorIndex, successorIndex)) {\n errorMessages.push(\n `Fractional indices invariant has been compromised: \"${stringifyElement(\n elements[i - 1],\n )}\", \"${stringifyElement(elements[i])}\", \"${stringifyElement(\n elements[i + 1],\n )}\"`,\n );\n }\n\n // disabled by default, as we don't fix it\n if (includeBoundTextValidation && hasBoundTextElement(elements[i])) {\n const container = elements[i];\n const text = getBoundTextElement(container, arrayToMap(elements));\n\n if (text && text.index! <= container.index!) {\n errorMessages.push(\n `Fractional indices invariant for bound elements has been compromised: \"${stringifyElement(\n text,\n )}\", \"${stringifyElement(container)}\"`,\n );\n }\n }\n }\n\n if (errorMessages.length) {\n const error = new InvalidFractionalIndexError();\n const additionalContext = [];\n\n if (reconciliationContext) {\n additionalContext.push(\"Additional reconciliation context:\");\n additionalContext.push(\n reconciliationContext.localElements.map((x) => stringifyElement(x)),\n );\n additionalContext.push(\n reconciliationContext.remoteElements.map((x) => stringifyElement(x)),\n );\n }\n\n if (!ignoreLogs) {\n // report just once and with the stacktrace\n console.error(\n errorMessages.join(\"\\n\\n\"),\n error.stack,\n elements.map((x) => stringifyElement(x)),\n ...additionalContext,\n );\n }\n\n if (shouldThrow) {\n // if enabled, gather all the errors first, throw once\n throw error;\n }\n }\n};\n\n/**\n * Order the elements based on the fractional indices.\n * - when fractional indices are identical, break the tie based on the element id\n * - when there is no fractional index in one of the elements, respect the order of the array\n */\nexport const orderByFractionalIndex = (\n elements: OrderedExcalidrawElement[],\n) => {\n return elements.sort((a, b) => {\n // in case the indices are not the defined at runtime\n if (isOrderedElement(a) && isOrderedElement(b)) {\n if (a.index < b.index) {\n return -1;\n } else if (a.index > b.index) {\n return 1;\n }\n\n // break ties based on the element id\n return a.id < b.id ? -1 : 1;\n }\n\n // defensively keep the array order\n return 1;\n });\n};\n\n/**\n * Synchronizes invalid fractional indices of moved elements with the array order by mutating passed elements.\n * If the synchronization fails or the result is invalid, it fallbacks to `syncInvalidIndices`.\n */\nexport const syncMovedIndices = (\n elements: readonly ExcalidrawElement[],\n movedElements: ElementsMap,\n): OrderedExcalidrawElement[] => {\n try {\n const elementsMap = arrayToMap(elements);\n const indicesGroups = getMovedIndicesGroups(elements, movedElements);\n\n // try generatating indices, throws on invalid movedElements\n const elementsUpdates = generateIndices(elements, indicesGroups);\n const elementsCandidates = elements.map((x) => {\n const elementUpdates = elementsUpdates.get(x);\n\n if (elementUpdates) {\n return { ...x, index: elementUpdates.index };\n }\n\n return x;\n });\n\n // ensure next indices are valid before mutation, throws on invalid ones\n validateFractionalIndices(\n elementsCandidates,\n // we don't autofix invalid bound text indices, hence don't include it in the validation\n {\n includeBoundTextValidation: false,\n shouldThrow: true,\n ignoreLogs: true,\n },\n );\n\n // split mutation so we don't end up in an incosistent state\n for (const [element, { index }] of elementsUpdates) {\n mutateElement(element, elementsMap, { index });\n }\n } catch (e) {\n // fallback to default sync\n syncInvalidIndices(elements);\n }\n\n return elements as OrderedExcalidrawElement[];\n};\n\n/**\n * Synchronizes all invalid fractional indices within the array order by mutating elements in the passed array.\n *\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.\n */\nexport const syncInvalidIndices = (\n elements: readonly ExcalidrawElement[],\n): OrderedExcalidrawElement[] => {\n const elementsMap = arrayToMap(elements);\n const indicesGroups = getInvalidIndicesGroups(elements);\n const elementsUpdates = generateIndices(elements, indicesGroups);\n\n for (const [element, { index }] of elementsUpdates) {\n mutateElement(element, elementsMap, { index });\n }\n\n return elements as OrderedExcalidrawElement[];\n};\n\n/**\n * Synchronizes all invalid fractional indices within the array order by creating new instances of elements with corrected indices.\n *\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.\n */\nexport const syncInvalidIndicesImmutable = (\n elements: readonly ExcalidrawElement[],\n): SceneElementsMap | undefined => {\n const syncedElements = arrayToMap(elements);\n const indicesGroups = getInvalidIndicesGroups(elements);\n const elementsUpdates = generateIndices(elements, indicesGroups);\n\n for (const [element, { index }] of elementsUpdates) {\n syncedElements.set(element.id, newElementWith(element, { index }));\n }\n\n return syncedElements as SceneElementsMap;\n};\n\n/**\n * Get contiguous groups of indices of passed moved elements.\n *\n * NOTE: First and last elements within the groups are indices of lower and upper bounds.\n */\nconst getMovedIndicesGroups = (\n elements: readonly ExcalidrawElement[],\n movedElements: ElementsMap,\n) => {\n const indicesGroups: number[][] = [];\n\n let i = 0;\n\n while (i < elements.length) {\n if (movedElements.has(elements[i].id)) {\n const indicesGroup = [i - 1, i]; // push the lower bound index as the first item\n\n while (++i < elements.length) {\n if (!movedElements.has(elements[i].id)) {\n break;\n }\n\n indicesGroup.push(i);\n }\n\n indicesGroup.push(i); // push the upper bound index as the last item\n indicesGroups.push(indicesGroup);\n } else {\n i++;\n }\n }\n\n return indicesGroups;\n};\n\n/**\n * Gets contiguous groups of all invalid indices automatically detected inside the elements array.\n *\n * WARN: First and last items within the groups do NOT have to be contiguous, those are the found lower and upper bounds!\n */\nconst getInvalidIndicesGroups = (elements: readonly ExcalidrawElement[]) => {\n const indicesGroups: number[][] = [];\n\n // once we find lowerBound / upperBound, it cannot be lower than that, so we cache it for better perf.\n let lowerBound: ExcalidrawElement[\"index\"] | undefined = undefined;\n let upperBound: ExcalidrawElement[\"index\"] | undefined = undefined;\n let lowerBoundIndex: number = -1;\n let upperBoundIndex: number = 0;\n\n /** @returns maybe valid lowerBound */\n const getLowerBound = (\n index: number,\n ): [ExcalidrawElement[\"index\"] | undefined, number] => {\n const lowerBound = elements[lowerBoundIndex]\n ? elements[lowerBoundIndex].index\n : undefined;\n\n // we are already iterating left to right, therefore there is no need for additional looping\n const candidate = elements[index - 1]?.index;\n\n if (\n (!lowerBound && candidate) || // first lowerBound\n (lowerBound && candidate && candidate > lowerBound) // next lowerBound\n ) {\n // WARN: candidate's index could be higher or same as the current element's index\n return [candidate, index - 1];\n }\n\n // cache hit! take the last lower bound\n return [lowerBound, lowerBoundIndex];\n };\n\n /** @returns always valid upperBound */\n const getUpperBound = (\n index: number,\n ): [ExcalidrawElement[\"index\"] | undefined, number] => {\n const upperBound = elements[upperBoundIndex]\n ? elements[upperBoundIndex].index\n : undefined;\n\n // cache hit! don't let it find the upper bound again\n if (upperBound && index < upperBoundIndex) {\n return [upperBound, upperBoundIndex];\n }\n\n // set the current upperBoundIndex as the starting point\n let i = upperBoundIndex;\n while (++i < elements.length) {\n const candidate = elements[i]?.index;\n\n if (\n (!upperBound && candidate) || // first upperBound\n (upperBound && candidate && candidate > upperBound) // next upperBound\n ) {\n return [candidate, i];\n }\n }\n\n // we reached the end, sky is the limit\n return [undefined, i];\n };\n\n let i = 0;\n\n while (i < elements.length) {\n const current = elements[i].index;\n [lowerBound, lowerBoundIndex] = getLowerBound(i);\n [upperBound, upperBoundIndex] = getUpperBound(i);\n\n if (!isValidFractionalIndex(current, lowerBound, upperBound)) {\n // push the lower bound index as the first item\n const indicesGroup = [lowerBoundIndex, i];\n\n while (++i < elements.length) {\n const current = elements[i].index;\n const [nextLowerBound, nextLowerBoundIndex] = getLowerBound(i);\n const [nextUpperBound, nextUpperBoundIndex] = getUpperBound(i);\n\n if (isValidFractionalIndex(current, nextLowerBound, nextUpperBound)) {\n break;\n }\n\n // assign bounds only for the moved elements\n [lowerBound, lowerBoundIndex] = [nextLowerBound, nextLowerBoundIndex];\n [upperBound, upperBoundIndex] = [nextUpperBound, nextUpperBoundIndex];\n\n indicesGroup.push(i);\n }\n\n // push the upper bound index as the last item\n indicesGroup.push(upperBoundIndex);\n indicesGroups.push(indicesGroup);\n } else {\n i++;\n }\n }\n\n return indicesGroups;\n};\n\nconst isValidFractionalIndex = (\n index: ExcalidrawElement[\"index\"] | undefined,\n predecessor: ExcalidrawElement[\"index\"] | undefined,\n successor: ExcalidrawElement[\"index\"] | undefined,\n) => {\n if (!index) {\n return false;\n }\n\n if (predecessor && successor) {\n return predecessor < index && index < successor;\n }\n\n if (!predecessor && successor) {\n // first element\n return index < successor;\n }\n\n if (predecessor && !successor) {\n // last element\n return predecessor < index;\n }\n\n // only element in the array\n return !!index;\n};\n\nconst generateIndices = (\n elements: readonly ExcalidrawElement[],\n indicesGroups: number[][],\n) => {\n const elementsUpdates = new Map<\n ExcalidrawElement,\n { index: FractionalIndex }\n >();\n\n for (const indices of indicesGroups) {\n const lowerBoundIndex = indices.shift()!;\n const upperBoundIndex = indices.pop()!;\n\n const fractionalIndices = generateNKeysBetween(\n elements[lowerBoundIndex]?.index,\n elements[upperBoundIndex]?.index,\n indices.length,\n ) as FractionalIndex[];\n\n for (let i = 0; i < indices.length; i++) {\n const element = elements[indices[i]];\n\n elementsUpdates.set(element, {\n index: fractionalIndices[i],\n });\n }\n }\n\n return elementsUpdates;\n};\n\nconst isOrderedElement = (\n element: ExcalidrawElement,\n): element is OrderedExcalidrawElement => {\n // for now it's sufficient whether the index is there\n // meaning, the element was already ordered in the past\n // meaning, it is not a newly inserted element, not an unrestored element, etc.\n // it does not have to mean that the index itself is valid\n if (element.index) {\n return true;\n }\n\n return false;\n};\n", "import throttle from \"lodash.throttle\";\n\nimport {\n randomInteger,\n arrayToMap,\n toBrandedType,\n isDevEnv,\n isTestEnv,\n toArray,\n} from \"@excalidraw/common\";\nimport { isNonDeletedElement } from \"@excalidraw/element\";\nimport { isFrameLikeElement } from \"@excalidraw/element\";\nimport { getElementsInGroup } from \"@excalidraw/element\";\n\nimport {\n syncInvalidIndices,\n syncMovedIndices,\n validateFractionalIndices,\n} from \"@excalidraw/element\";\n\nimport { getSelectedElements } from \"@excalidraw/element\";\n\nimport { mutateElement, type ElementUpdate } from \"@excalidraw/element\";\n\nimport type {\n ExcalidrawElement,\n NonDeletedExcalidrawElement,\n NonDeleted,\n ExcalidrawFrameLikeElement,\n ElementsMapOrArray,\n SceneElementsMap,\n NonDeletedSceneElementsMap,\n OrderedExcalidrawElement,\n Ordered,\n} from \"@excalidraw/element/types\";\n\nimport type {\n Assert,\n Mutable,\n SameType,\n} from \"@excalidraw/common/utility-types\";\n\nimport type { AppState } from \"../../excalidraw/types\";\n\ntype SceneStateCallback = () => void;\ntype SceneStateCallbackRemover = () => void;\n\ntype SelectionHash = string & { __brand: \"selectionHash\" };\n\nconst getNonDeletedElements = <T extends ExcalidrawElement>(\n allElements: readonly T[],\n) => {\n const elementsMap = new Map() as NonDeletedSceneElementsMap;\n const elements: T[] = [];\n for (const element of allElements) {\n if (!element.isDeleted) {\n elements.push(element as NonDeleted<T>);\n elementsMap.set(\n element.id,\n element as Ordered<NonDeletedExcalidrawElement>,\n );\n }\n }\n return { elementsMap, elements };\n};\n\nconst validateIndicesThrottled = throttle(\n (elements: readonly ExcalidrawElement[]) => {\n if (isDevEnv() || isTestEnv() || window?.DEBUG_FRACTIONAL_INDICES) {\n validateFractionalIndices(elements, {\n // throw only in dev & test, to remain functional on `DEBUG_FRACTIONAL_INDICES`\n shouldThrow: isDevEnv() || isTestEnv(),\n includeBoundTextValidation: true,\n });\n }\n },\n 1000 * 60,\n { leading: true, trailing: false },\n);\n\nconst hashSelectionOpts = (\n opts: Parameters<InstanceType<typeof Scene>[\"getSelectedElements\"]>[0],\n) => {\n const keys = [\"includeBoundTextElement\", \"includeElementsInFrames\"] as const;\n\n type HashableKeys = Omit<typeof opts, \"selectedElementIds\" | \"elements\">;\n\n // just to ensure we're hashing all expected keys\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n type _ = Assert<\n SameType<\n Required<HashableKeys>,\n Pick<Required<HashableKeys>, typeof keys[number]>\n >\n >;\n\n let hash = \"\";\n for (const key of keys) {\n hash += `${key}:${opts[key] ? \"1\" : \"0\"}`;\n }\n return hash as SelectionHash;\n};\n\n// ideally this would be a branded type but it'd be insanely hard to work with\n// in our codebase\nexport type ExcalidrawElementsIncludingDeleted = readonly ExcalidrawElement[];\n\nexport class Scene {\n // ---------------------------------------------------------------------------\n // instance methods/props\n // ---------------------------------------------------------------------------\n\n private callbacks: Set<SceneStateCallback> = new Set();\n\n private nonDeletedElements: readonly Ordered<NonDeletedExcalidrawElement>[] =\n [];\n private nonDeletedElementsMap = toBrandedType<NonDeletedSceneElementsMap>(\n new Map(),\n );\n // ideally all elements within the scene should be wrapped around with `Ordered` type, but right now there is no real benefit doing so\n private elements: readonly OrderedExcalidrawElement[] = [];\n private nonDeletedFramesLikes: readonly NonDeleted<ExcalidrawFrameLikeElement>[] =\n [];\n private frames: readonly ExcalidrawFrameLikeElement[] = [];\n private elementsMap = toBrandedType<SceneElementsMap>(new Map());\n private selectedElementsCache: {\n selectedElementIds: AppState[\"selectedElementIds\"] | null;\n elements: readonly NonDeletedExcalidrawElement[] | null;\n cache: Map<SelectionHash, NonDeletedExcalidrawElement[]>;\n } = {\n selectedElementIds: null,\n elements: null,\n cache: new Map(),\n };\n /**\n * Random integer regenerated each scene update.\n *\n * Does not relate to elements versions, it's only a renderer\n * cache-invalidation nonce at the moment.\n */\n private sceneNonce: number | undefined;\n\n getSceneNonce() {\n return this.sceneNonce;\n }\n\n getNonDeletedElementsMap() {\n return this.nonDeletedElementsMap;\n }\n\n getElementsIncludingDeleted() {\n return this.elements;\n }\n\n getElementsMapIncludingDeleted() {\n return this.elementsMap;\n }\n\n getNonDeletedElements() {\n return this.nonDeletedElements;\n }\n\n getFramesIncludingDeleted() {\n return this.frames;\n }\n\n constructor(\n elements: ElementsMapOrArray | null = null,\n options?: {\n skipValidation?: true;\n },\n ) {\n if (elements) {\n this.replaceAllElements(elements, options);\n }\n }\n\n getSelectedElements(opts: {\n // NOTE can be ommitted by making Scene constructor require App instance\n selectedElementIds: AppState[\"selectedElementIds\"];\n /**\n * for specific cases where you need to use elements not from current\n * scene state. This in effect will likely result in cache-miss, and\n * the cache won't be updated in this case.\n */\n elements?: ElementsMapOrArray;\n // selection-related options\n includeBoundTextElement?: boolean;\n includeElementsInFrames?: boolean;\n }): NonDeleted<ExcalidrawElement>[] {\n const hash = hashSelectionOpts(opts);\n\n const elements = opts?.elements || this.nonDeletedElements;\n if (\n this.selectedElementsCache.elements === elements &&\n this.selectedElementsCache.selectedElementIds === opts.selectedElementIds\n ) {\n const cached = this.selectedElementsCache.cache.get(hash);\n if (cached) {\n return cached;\n }\n } else if (opts?.elements == null) {\n // if we're operating on latest scene elements and the cache is not\n // storing the latest elements, clear the cache\n this.selectedElementsCache.cache.clear();\n }\n\n const selectedElements = getSelectedElements(\n elements,\n { selectedElementIds: opts.selectedElementIds },\n opts,\n );\n\n // cache only if we're not using custom elements\n if (opts?.elements == null) {\n this.selectedElementsCache.selectedElementIds = opts.selectedElementIds;\n this.selectedElementsCache.elements = this.nonDeletedElements;\n this.selectedElementsCache.cache.set(hash, selectedElements);\n }\n\n return selectedElements;\n }\n\n getNonDeletedFramesLikes(): readonly NonDeleted<ExcalidrawFrameLikeElement>[] {\n return this.nonDeletedFramesLikes;\n }\n\n getElement<T extends ExcalidrawElement>(id: T[\"id\"]): T | null {\n return (this.elementsMap.get(id) as T | undefined) || null;\n }\n\n getNonDeletedElement(\n id: ExcalidrawElement[\"id\"],\n ): NonDeleted<ExcalidrawElement> | null {\n const element = this.getElement(id);\n if (element && isNonDeletedElement(element)) {\n return element;\n }\n return null;\n }\n\n /**\n * A utility method to help with updating all scene elements, with the added\n * performance optimization of not renewing the array if no change is made.\n *\n * Maps all current excalidraw elements, invoking the callback for each\n * element. The callback should either return a new mapped element, or the\n * original element if no changes are made. If no changes are made to any\n * element, this results in a no-op. Otherwise, the newly mapped elements\n * are set as the next scene's elements.\n *\n * @returns whether a change was made\n */\n mapElements(\n iteratee: (element: ExcalidrawElement) => ExcalidrawElement,\n ): boolean {\n let didChange = false;\n const newElements = this.elements.map((element) => {\n const nextElement = iteratee(element);\n if (nextElement !== element) {\n didChange = true;\n }\n return nextElement;\n });\n if (didChange) {\n this.replaceAllElements(newElements);\n }\n return didChange;\n }\n\n replaceAllElements(\n nextElements: ElementsMapOrArray,\n options?: {\n skipValidation?: true;\n },\n ) {\n // we do trust the insertion order on the map, though maybe we shouldn't and should prefer order defined by fractional indices\n const _nextElements = toArray(nextElements);\n const nextFrameLikes: ExcalidrawFrameLikeElement[] = [];\n\n if (!options?.skipValidation) {\n validateIndicesThrottled(_nextElements);\n }\n\n this.elements = syncInvalidIndices(_nextElements);\n this.elementsMap.clear();\n this.elements.forEach((element) => {\n if (isFrameLikeElement(element)) {\n nextFrameLikes.push(element);\n }\n this.elementsMap.set(element.id, element);\n });\n const nonDeletedElements = getNonDeletedElements(this.elements);\n this.nonDeletedElements = nonDeletedElements.elements;\n this.nonDeletedElementsMap = nonDeletedElements.elementsMap;\n\n this.frames = nextFrameLikes;\n this.nonDeletedFramesLikes = getNonDeletedElements(this.frames).elements;\n\n this.triggerUpdate();\n }\n\n triggerUpdate() {\n this.sceneNonce = randomInteger();\n\n for (const callback of Array.from(this.callbacks)) {\n callback();\n }\n }\n\n onUpdate(cb: SceneStateCallback): SceneStateCallbackRemover {\n if (this.callbacks.has(cb)) {\n throw new Error();\n }\n\n this.callbacks.add(cb);\n\n return () => {\n if (!this.callbacks.has(cb)) {\n throw new Error();\n }\n this.callbacks.delete(cb);\n };\n }\n\n destroy() {\n this.elements = [];\n this.nonDeletedElements = [];\n this.nonDeletedFramesLikes = [];\n this.frames = [];\n this.elementsMap.clear();\n this.selectedElementsCache.selectedElementIds = null;\n this.selectedElementsCache.elements = null;\n this.selectedElementsCache.cache.clear();\n\n // done not for memory leaks, but to guard against possible late fires\n // (I guess?)\n this.callbacks.clear();\n }\n\n insertElementAtIndex(element: ExcalidrawElement, index: number) {\n if (!Number.isFinite(index) || index < 0) {\n throw new Error(\n \"insertElementAtIndex can only be called with index >= 0\",\n );\n }\n\n const nextElements = [\n ...this.elements.slice(0, index),\n element,\n ...this.elements.slice(index),\n ];\n\n syncMovedIndices(nextElements, arrayToMap([element]));\n\n this.replaceAllElements(nextElements);\n }\n\n insertElementsAtIndex(elements: ExcalidrawElement[], index: number) {\n if (!elements.length) {\n return;\n }\n\n if (!Number.isFinite(index) || index < 0) {\n throw new Error(\n \"insertElementAtIndex can only be called with index >= 0\",\n );\n }\n\n const nextElements = [\n ...this.elements.slice(0, index),\n ...elements,\n ...this.elements.slice(index),\n ];\n\n syncMovedIndices(nextElements, arrayToMap(elements));\n\n this.replaceAllElements(nextElements);\n }\n\n insertElement = (element: ExcalidrawElement) => {\n const index = element.frameId\n ? this.getElementIndex(element.frameId)\n : this.elements.length;\n\n this.insertElementAtIndex(element, index);\n };\n\n insertElements = (elements: ExcalidrawElement[]) => {\n if (!elements.length) {\n return;\n }\n\n const index = elements[0]?.frameId\n ? this.getElementIndex(elements[0].frameId)\n : this.elements.length;\n\n this.insertElementsAtIndex(elements, index);\n };\n\n getElementIndex(elementId: string) {\n return this.elements.findIndex((element) => element.id === elementId);\n }\n\n getContainerElement = (\n element:\n | (ExcalidrawElement & {\n containerId: ExcalidrawElement[\"id\"] | null;\n })\n | null,\n ) => {\n if (!element) {\n return null;\n }\n if (element.containerId) {\n return this.getElement(element.containerId) || null;\n }\n return null;\n };\n\n getElementsFromId = (id: string): ExcalidrawElement[] => {\n const elementsMap = this.getNonDeletedElementsMap();\n // first check if the id is an element\n const el = elementsMap.get(id);\n if (el) {\n return [el];\n }\n\n // then, check if the id is a group\n return getElementsInGroup(elementsMap, id);\n };\n\n // Mutate an element with passed updates and trigger the component to update. Make sure you\n // are calling it either from a React event handler or within unstable_batchedUpdates().\n mutateElement<TElement extends Mutable<ExcalidrawElement>>(\n element: TElement,\n updates: ElementUpdate<TElement>,\n options: {\n informMutation: boolean;\n isDragging: boolean;\n } = {\n informMutation: true,\n isDragging: false,\n },\n ) {\n const elementsMap = this.getNonDeletedElementsMap();\n\n const { version: prevVersion } = element;\n const { version: nextVersion } = mutateElement(\n element,\n elementsMap,\n updates,\n options,\n );\n\n if (\n // skip if the element is not in the scene (i.e. selection)\n this.elementsMap.has(element.id) &&\n // skip if the element's version hasn't changed, as mutateElement returned the same element\n prevVersion !== nextVersion &&\n options.informMutation\n ) {\n this.triggerUpdate();\n }\n\n return element;\n }\n}\n", "import {\n arrayToMap,\n arrayToObject,\n assertNever,\n isDevEnv,\n isShallowEqual,\n isTestEnv,\n randomInteger,\n} from \"@excalidraw/common\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawLinearElement,\n ExcalidrawTextElement,\n NonDeleted,\n Ordered,\n OrderedExcalidrawElement,\n SceneElementsMap,\n} from \"@excalidraw/element/types\";\n\nimport type {\n DTO,\n Mutable,\n SubtypeOf,\n ValueOf,\n} from \"@excalidraw/common/utility-types\";\n\nimport type {\n AppState,\n ObservedAppState,\n ObservedElementsAppState,\n ObservedStandaloneAppState,\n} from \"@excalidraw/excalidraw/types\";\n\nimport { getObservedAppState } from \"./store\";\n\nimport {\n BoundElement,\n BindableElement,\n bindingProperties,\n updateBoundElements,\n} from \"./binding\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport { mutateElement, newElementWith } from \"./mutateElement\";\nimport { getBoundTextElementId, redrawTextBoundingBox } from \"./textElement\";\nimport {\n hasBoundTextElement,\n isBindableElement,\n isBoundToContainer,\n isTextElement,\n} from \"./typeChecks\";\n\nimport { getNonDeletedGroupIds } from \"./groups\";\n\nimport { orderByFractionalIndex, syncMovedIndices } from \"./fractionalIndex\";\n\nimport { StoreSnapshot } from \"./store\";\n\nimport { Scene } from \"./Scene\";\n\nimport type { BindableProp, BindingProp } from \"./binding\";\n\nimport type { ElementUpdate } from \"./mutateElement\";\n\n/**\n * Represents the difference between two objects of the same type.\n *\n * Both `deleted` and `inserted` partials represent the same set of added, removed or updated properties, where:\n * - `deleted` is a set of all the deleted values\n * - `inserted` is a set of all the inserted (added, updated) values\n *\n * Keeping it as pure object (without transient state, side-effects, etc.), so we won't have to instantiate it on load.\n */\nexport class Delta<T> {\n private constructor(\n public readonly deleted: Partial<T>,\n public readonly inserted: Partial<T>,\n ) {}\n\n public static create<T>(\n deleted: Partial<T>,\n inserted: Partial<T>,\n modifier?: (\n delta: Partial<T>,\n partialType: \"deleted\" | \"inserted\",\n ) => Partial<T>,\n modifierOptions?: \"deleted\" | \"inserted\" | \"both\",\n ) {\n const modifiedDeleted =\n modifier && modifierOptions !== \"inserted\"\n ? modifier(deleted, \"deleted\")\n : deleted;\n const modifiedInserted =\n modifier && modifierOptions !== \"deleted\"\n ? modifier(inserted, \"inserted\")\n : inserted;\n\n return new Delta(modifiedDeleted, modifiedInserted);\n }\n\n /**\n * Calculates the delta between two objects.\n *\n * @param prevObject - The previous state of the object.\n * @param nextObject - The next state of the object.\n *\n * @returns new delta instance.\n */\n public static calculate<T extends { [key: string]: any }>(\n prevObject: T,\n nextObject: T,\n modifier?: (partial: Partial<T>) => Partial<T>,\n postProcess?: (\n deleted: Partial<T>,\n inserted: Partial<T>,\n ) => [Partial<T>, Partial<T>],\n ): Delta<T> {\n if (prevObject === nextObject) {\n return Delta.empty();\n }\n\n const deleted = {} as Partial<T>;\n const inserted = {} as Partial<T>;\n\n // O(n^3) here for elements, but it's not as bad as it looks:\n // - we do this only on store recordings, not on every frame (not for ephemerals)\n // - we do this only on previously detected changed elements\n // - we do shallow compare only on the first level of properties (not going any deeper)\n // - # of properties is reasonably small\n for (const key of this.getDifferences(prevObject, nextObject)) {\n deleted[key as keyof T] = prevObject[key];\n inserted[key as keyof T] = nextObject[key];\n }\n\n const [processedDeleted, processedInserted] = postProcess\n ? postProcess(deleted, inserted)\n : [deleted, inserted];\n\n return Delta.create(processedDeleted, processedInserted, modifier);\n }\n\n public static empty() {\n return new Delta({}, {});\n }\n\n public static isEmpty<T>(delta: Delta<T>): boolean {\n return (\n !Object.keys(delta.deleted).length && !Object.keys(delta.inserted).length\n );\n }\n\n /**\n * Merges two deltas into a new one.\n */\n public static merge<T>(\n delta1: Delta<T>,\n delta2: Delta<T>,\n delta3: Delta<T> = Delta.empty(),\n ) {\n return Delta.create(\n { ...delta1.deleted, ...delta2.deleted, ...delta3.deleted },\n { ...delta1.inserted, ...delta2.inserted, ...delta3.inserted },\n );\n }\n\n /**\n * Merges deleted and inserted object partials.\n */\n public static mergeObjects<T extends { [key: string]: unknown }>(\n prev: T,\n added: T,\n removed: T = {} as T,\n ) {\n const cloned = { ...prev };\n\n for (const key of Object.keys(removed)) {\n delete cloned[key];\n }\n\n return { ...cloned, ...added };\n }\n\n /**\n * Merges deleted and inserted array partials.\n */\n public static mergeArrays<T>(\n prev: readonly T[] | null,\n added: readonly T[] | null | undefined,\n removed: readonly T[] | null | undefined,\n predicate?: (value: T) => string,\n ) {\n return Object.values(\n Delta.mergeObjects(\n arrayToObject(prev ?? [], predicate),\n arrayToObject(added ?? [], predicate),\n arrayToObject(removed ?? [], predicate),\n ),\n );\n }\n\n /**\n * Diff object partials as part of the `postProcess`.\n */\n public static diffObjects<T, K extends keyof T, V extends ValueOf<T[K]>>(\n deleted: Partial<T>,\n inserted: Partial<T>,\n property: K,\n setValue: (prevValue: V | undefined) => V,\n ) {\n if (!deleted[property] && !inserted[property]) {\n return;\n }\n\n const isDeletedObject =\n deleted[property] !== null && typeof deleted[property] === \"object\";\n const isInsertedObject =\n inserted[property] !== null && typeof inserted[property] === \"object\";\n\n if (isDeletedObject || isInsertedObject) {\n type RecordLike = Record<string, V | undefined>;\n\n const deletedObject: RecordLike = deleted[property] ?? {};\n const insertedObject: RecordLike = inserted[property] ?? {};\n\n const deletedDifferences = Delta.getLeftDifferences(\n deletedObject,\n insertedObject,\n ).reduce((acc, curr) => {\n acc[curr] = setValue(deletedObject[curr]);\n return acc;\n }, {} as RecordLike);\n\n const insertedDifferences = Delta.getRightDifferences(\n deletedObject,\n insertedObject,\n ).reduce((acc, curr) => {\n acc[curr] = setValue(insertedObject[curr]);\n return acc;\n }, {} as RecordLike);\n\n if (\n Object.keys(deletedDifferences).length ||\n Object.keys(insertedDifferences).length\n ) {\n Reflect.set(deleted, property, deletedDifferences);\n Reflect.set(inserted, property, insertedDifferences);\n } else {\n Reflect.deleteProperty(deleted, property);\n Reflect.deleteProperty(inserted, property);\n }\n } else if (deleted[property] === inserted[property]) {\n Reflect.deleteProperty(deleted, property);\n Reflect.deleteProperty(inserted, property);\n }\n }\n\n /**\n * Diff array partials as part of the `postProcess`.\n */\n public static diffArrays<T, K extends keyof T, V extends T[K]>(\n deleted: Partial<T>,\n inserted: Partial<T>,\n property: K,\n groupBy: (value: V extends ArrayLike<infer T> ? T : never) => string,\n ) {\n if (!deleted[property] && !inserted[property]) {\n return;\n }\n\n if (Array.isArray(deleted[property]) || Array.isArray(inserted[property])) {\n const deletedArray = (\n Array.isArray(deleted[property]) ? deleted[property] : []\n ) as [];\n const insertedArray = (\n Array.isArray(inserted[property]) ? inserted[property] : []\n ) as [];\n\n const deletedDifferences = arrayToObject(\n Delta.getLeftDifferences(\n arrayToObject(deletedArray, groupBy),\n arrayToObject(insertedArray, groupBy),\n ),\n (x) => x,\n );\n const insertedDifferences = arrayToObject(\n Delta.getRightDifferences(\n arrayToObject(deletedArray, groupBy),\n arrayToObject(insertedArray, groupBy),\n ),\n (x) => x,\n );\n\n if (\n Object.keys(deletedDifferences).length ||\n Object.keys(insertedDifferences).length\n ) {\n const deletedValue = deletedArray.filter(\n (x) => deletedDifferences[groupBy ? groupBy(x) : String(x)],\n );\n const insertedValue = insertedArray.filter(\n (x) => insertedDifferences[groupBy ? groupBy(x) : String(x)],\n );\n\n Reflect.set(deleted, property, deletedValue);\n Reflect.set(inserted, property, insertedValue);\n } else {\n Reflect.deleteProperty(deleted, property);\n Reflect.deleteProperty(inserted, property);\n }\n }\n }\n\n /**\n * Compares if object1 contains any different value compared to the object2.\n */\n public static isLeftDifferent<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ): boolean {\n const anyDistinctKey = this.distinctKeysIterator(\n \"left\",\n object1,\n object2,\n skipShallowCompare,\n ).next().value;\n\n return !!anyDistinctKey;\n }\n\n /**\n * Compares if object2 contains any different value compared to the object1.\n */\n public static isRightDifferent<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ): boolean {\n const anyDistinctKey = this.distinctKeysIterator(\n \"right\",\n object1,\n object2,\n skipShallowCompare,\n ).next().value;\n\n return !!anyDistinctKey;\n }\n\n /**\n * Compares if shared properties of object1 and object2 contain any different value (aka inner join).\n */\n public static isInnerDifferent<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ): boolean {\n const anyDistinctKey = !!this.distinctKeysIterator(\n \"inner\",\n object1,\n object2,\n skipShallowCompare,\n ).next().value;\n\n return !!anyDistinctKey;\n }\n\n /**\n * Compares if any properties of object1 and object2 contain any different value (aka full join).\n */\n public static isDifferent<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ): boolean {\n const anyDistinctKey = !!this.distinctKeysIterator(\n \"full\",\n object1,\n object2,\n skipShallowCompare,\n ).next().value;\n\n return !!anyDistinctKey;\n }\n\n /**\n * Returns sorted object1 keys that have distinct values.\n */\n public static getLeftDifferences<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ) {\n return Array.from(\n this.distinctKeysIterator(\"left\", object1, object2, skipShallowCompare),\n ).sort();\n }\n\n /**\n * Returns sorted object2 keys that have distinct values.\n */\n public static getRightDifferences<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ) {\n return Array.from(\n this.distinctKeysIterator(\"right\", object1, object2, skipShallowCompare),\n ).sort();\n }\n\n /**\n * Returns sorted keys of shared object1 and object2 properties that have distinct values (aka inner join).\n */\n public static getInnerDifferences<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ) {\n return Array.from(\n this.distinctKeysIterator(\"inner\", object1, object2, skipShallowCompare),\n ).sort();\n }\n\n /**\n * Returns sorted keys that have distinct values between object1 and object2 (aka full join).\n */\n public static getDifferences<T extends {}>(\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ) {\n return Array.from(\n this.distinctKeysIterator(\"full\", object1, object2, skipShallowCompare),\n ).sort();\n }\n\n /**\n * Iterator comparing values of object properties based on the passed joining strategy.\n *\n * @yields keys of properties with different values\n *\n * WARN: it's based on shallow compare performed only on the first level and doesn't go deeper than that.\n */\n private static *distinctKeysIterator<T extends {}>(\n join: \"left\" | \"right\" | \"inner\" | \"full\",\n object1: T,\n object2: T,\n skipShallowCompare = false,\n ) {\n if (object1 === object2) {\n return;\n }\n\n let keys: string[] = [];\n\n if (join === \"left\") {\n keys = Object.keys(object1);\n } else if (join === \"right\") {\n keys = Object.keys(object2);\n } else if (join === \"inner\") {\n keys = Object.keys(object1).filter((key) => key in object2);\n } else if (join === \"full\") {\n keys = Array.from(\n new Set([...Object.keys(object1), ...Object.keys(object2)]),\n );\n } else {\n assertNever(\n join,\n `Unknown distinctKeysIterator's join param \"${join}\"`,\n true,\n );\n }\n\n for (const key of keys) {\n const value1 = object1[key as keyof T];\n const value2 = object2[key as keyof T];\n\n if (value1 !== value2) {\n if (\n !skipShallowCompare &&\n typeof value1 === \"object\" &&\n typeof value2 === \"object\" &&\n value1 !== null &&\n value2 !== null &&\n isShallowEqual(value1, value2)\n ) {\n continue;\n }\n\n yield key;\n }\n }\n }\n}\n\n/**\n * Encapsulates a set of application-level `Delta`s.\n */\nexport interface DeltaContainer<T> {\n /**\n * Inverses the `Delta`s while creating a new `DeltaContainer` instance.\n */\n inverse(): DeltaContainer<T>;\n\n /**\n * Applies the `Delta`s to the previous object.\n *\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.\n */\n applyTo(previous: T, ...options: unknown[]): [T, boolean];\n\n /**\n * Squashes the current delta with the given one.\n */\n squash(delta: DeltaContainer<T>): this;\n\n /**\n * Checks whether all `Delta`s are empty.\n */\n isEmpty(): boolean;\n}\n\nexport class AppStateDelta implements DeltaContainer<AppState> {\n private constructor(public delta: Delta<ObservedAppState>) {}\n\n public static create(delta: Delta<ObservedAppState>): AppStateDelta {\n return new AppStateDelta(delta);\n }\n\n public static calculate<T extends ObservedAppState>(\n prevAppState: T,\n nextAppState: T,\n ): AppStateDelta {\n const delta = Delta.calculate(\n prevAppState,\n nextAppState,\n // making the order of keys in deltas stable for hashing purposes\n AppStateDelta.orderAppStateKeys,\n AppStateDelta.postProcess,\n );\n\n return new AppStateDelta(delta);\n }\n\n public static restore(appStateDeltaDTO: DTO<AppStateDelta>): AppStateDelta {\n const { delta } = appStateDeltaDTO;\n return new AppStateDelta(delta);\n }\n\n public static empty() {\n return new AppStateDelta(Delta.create({}, {}));\n }\n\n public inverse(): AppStateDelta {\n const inversedDelta = Delta.create(this.delta.inserted, this.delta.deleted);\n return new AppStateDelta(inversedDelta);\n }\n\n public squash(delta: AppStateDelta): this {\n if (delta.isEmpty()) {\n return this;\n }\n\n const mergedDeletedSelectedElementIds = Delta.mergeObjects(\n this.delta.deleted.selectedElementIds ?? {},\n delta.delta.deleted.selectedElementIds ?? {},\n );\n\n const mergedInsertedSelectedElementIds = Delta.mergeObjects(\n this.delta.inserted.selectedElementIds ?? {},\n delta.delta.inserted.selectedElementIds ?? {},\n );\n\n const mergedDeletedSelectedGroupIds = Delta.mergeObjects(\n this.delta.deleted.selectedGroupIds ?? {},\n delta.delta.deleted.selectedGroupIds ?? {},\n );\n\n const mergedInsertedSelectedGroupIds = Delta.mergeObjects(\n this.delta.inserted.selectedGroupIds ?? {},\n delta.delta.inserted.selectedGroupIds ?? {},\n );\n\n const mergedDeletedLockedMultiSelections = Delta.mergeObjects(\n this.delta.deleted.lockedMultiSelections ?? {},\n delta.delta.deleted.lockedMultiSelections ?? {},\n );\n\n const mergedInsertedLockedMultiSelections = Delta.mergeObjects(\n this.delta.inserted.lockedMultiSelections ?? {},\n delta.delta.inserted.lockedMultiSelections ?? {},\n );\n\n const mergedInserted: Partial<ObservedAppState> = {};\n const mergedDeleted: Partial<ObservedAppState> = {};\n\n if (\n Object.keys(mergedDeletedSelectedElementIds).length ||\n Object.keys(mergedInsertedSelectedElementIds).length\n ) {\n mergedDeleted.selectedElementIds = mergedDeletedSelectedElementIds;\n mergedInserted.selectedElementIds = mergedInsertedSelectedElementIds;\n }\n\n if (\n Object.keys(mergedDeletedSelectedGroupIds).length ||\n Object.keys(mergedInsertedSelectedGroupIds).length\n ) {\n mergedDeleted.selectedGroupIds = mergedDeletedSelectedGroupIds;\n mergedInserted.selectedGroupIds = mergedInsertedSelectedGroupIds;\n }\n\n if (\n Object.keys(mergedDeletedLockedMultiSelections).length ||\n Object.keys(mergedInsertedLockedMultiSelections).length\n ) {\n mergedDeleted.lockedMultiSelections = mergedDeletedLockedMultiSelections;\n mergedInserted.lockedMultiSelections =\n mergedInsertedLockedMultiSelections;\n }\n\n this.delta = Delta.merge(\n this.delta,\n delta.delta,\n Delta.create(mergedDeleted, mergedInserted),\n );\n\n return this;\n }\n\n public applyTo(\n appState: AppState,\n nextElements: SceneElementsMap,\n ): [AppState, boolean] {\n try {\n const {\n selectedElementIds: deletedSelectedElementIds = {},\n selectedGroupIds: deletedSelectedGroupIds = {},\n lockedMultiSelections: deletedLockedMultiSelections = {},\n } = this.delta.deleted;\n\n const {\n selectedElementIds: insertedSelectedElementIds = {},\n selectedGroupIds: insertedSelectedGroupIds = {},\n lockedMultiSelections: insertedLockedMultiSelections = {},\n selectedLinearElement: insertedSelectedLinearElement,\n ...directlyApplicablePartial\n } = this.delta.inserted;\n\n const mergedSelectedElementIds = Delta.mergeObjects(\n appState.selectedElementIds,\n insertedSelectedElementIds,\n deletedSelectedElementIds,\n );\n\n const mergedSelectedGroupIds = Delta.mergeObjects(\n appState.selectedGroupIds,\n insertedSelectedGroupIds,\n deletedSelectedGroupIds,\n );\n\n const mergedLockedMultiSelections = Delta.mergeObjects(\n appState.lockedMultiSelections,\n insertedLockedMultiSelections,\n deletedLockedMultiSelections,\n );\n\n const selectedLinearElement =\n insertedSelectedLinearElement &&\n nextElements.has(insertedSelectedLinearElement.elementId)\n ? new LinearElementEditor(\n nextElements.get(\n insertedSelectedLinearElement.elementId,\n ) as NonDeleted<ExcalidrawLinearElement>,\n nextElements,\n insertedSelectedLinearElement.isEditing,\n )\n : null;\n\n const nextAppState = {\n ...appState,\n ...directlyApplicablePartial,\n selectedElementIds: mergedSelectedElementIds,\n selectedGroupIds: mergedSelectedGroupIds,\n lockedMultiSelections: mergedLockedMultiSelections,\n selectedLinearElement:\n typeof insertedSelectedLinearElement !== \"undefined\"\n ? selectedLinearElement\n : appState.selectedLinearElement,\n };\n\n const constainsVisibleChanges = this.filterInvisibleChanges(\n appState,\n nextAppState,\n nextElements,\n );\n\n return [nextAppState, constainsVisibleChanges];\n } catch (e) {\n // shouldn't really happen, but just in case\n console.error(`Couldn't apply appstate change`, e);\n\n if (isTestEnv() || isDevEnv()) {\n throw e;\n }\n\n return [appState, false];\n }\n }\n\n public isEmpty(): boolean {\n return Delta.isEmpty(this.delta);\n }\n\n /**\n * Mutates `nextAppState` be filtering out state related to deleted elements.\n *\n * @returns `true` if a visible change is found, `false` otherwise.\n */\n private filterInvisibleChanges(\n prevAppState: AppState,\n nextAppState: AppState,\n nextElements: SceneElementsMap,\n ): boolean {\n // TODO: #7348 we could still get an empty undo/redo, as we assume that previous appstate does not contain references to deleted elements\n // which is not always true - i.e. now we do cleanup appstate during history, but we do not do it during remote updates\n const prevObservedAppState = getObservedAppState(prevAppState);\n const nextObservedAppState = getObservedAppState(nextAppState);\n\n const containsStandaloneDifference = Delta.isRightDifferent(\n AppStateDelta.stripElementsProps(prevObservedAppState),\n AppStateDelta.stripElementsProps(nextObservedAppState),\n );\n\n const containsElementsDifference = Delta.isRightDifferent(\n AppStateDelta.stripStandaloneProps(prevObservedAppState),\n AppStateDelta.stripStandaloneProps(nextObservedAppState),\n );\n\n if (!containsStandaloneDifference && !containsElementsDifference) {\n // no change in appstate was detected\n return false;\n }\n\n const visibleDifferenceFlag = {\n value: containsStandaloneDifference,\n };\n\n if (containsElementsDifference) {\n // filter invisible changes on each iteration\n const changedElementsProps = Delta.getRightDifferences(\n AppStateDelta.stripStandaloneProps(prevObservedAppState),\n AppStateDelta.stripStandaloneProps(nextObservedAppState),\n ) as Array<keyof ObservedElementsAppState>;\n\n let nonDeletedGroupIds = new Set<string>();\n\n if (\n changedElementsProps.includes(\"editingGroupId\") ||\n changedElementsProps.includes(\"selectedGroupIds\")\n ) {\n // this one iterates through all the non deleted elements, so make sure it's not done twice\n nonDeletedGroupIds = getNonDeletedGroupIds(nextElements);\n }\n\n // check whether delta properties are related to the existing non-deleted elements\n for (const key of changedElementsProps) {\n switch (key) {\n case \"selectedElementIds\":\n nextAppState[key] = AppStateDelta.filterSelectedElements(\n nextAppState[key],\n nextElements,\n visibleDifferenceFlag,\n );\n\n break;\n case \"selectedGroupIds\":\n nextAppState[key] = AppStateDelta.filterSelectedGroups(\n nextAppState[key],\n nonDeletedGroupIds,\n visibleDifferenceFlag,\n );\n\n break;\n case \"croppingElementId\": {\n const croppingElementId = nextAppState[key];\n\n if (!croppingElementId) {\n // previously there was a croppingElementId (assuming visible), now there is none\n visibleDifferenceFlag.value = true;\n } else {\n const element = nextElements.get(croppingElementId);\n\n if (element && !element.isDeleted) {\n visibleDifferenceFlag.value = true;\n } else {\n nextAppState[key] = null;\n }\n }\n\n break;\n }\n case \"editingGroupId\":\n const editingGroupId = nextAppState[key];\n\n if (!editingGroupId) {\n // previously there was an editingGroup (assuming visible), now there is none\n visibleDifferenceFlag.value = true;\n } else if (nonDeletedGroupIds.has(editingGroupId)) {\n // previously there wasn't an editingGroup, now there is one which is visible\n visibleDifferenceFlag.value = true;\n } else {\n // there was assigned an editingGroup now, but it's related to deleted element\n nextAppState[key] = null;\n }\n\n break;\n case \"selectedLinearElement\":\n const nextLinearElement = nextAppState[key];\n\n if (!nextLinearElement) {\n // previously there was a linear element (assuming visible), now there is none\n visibleDifferenceFlag.value = true;\n } else {\n const element = nextElements.get(nextLinearElement.elementId);\n\n if (element && !element.isDeleted) {\n // previously there wasn't a linear element, now there is one which is visible\n visibleDifferenceFlag.value = true;\n } else {\n // there was assigned a linear element now, but it's deleted\n nextAppState[key] = null;\n }\n }\n\n break;\n case \"lockedMultiSelections\":\n const prevLockedUnits = prevAppState[key] || {};\n const nextLockedUnits = nextAppState[key] || {};\n\n // TODO: this seems wrong, we are already doing this comparison generically above,\n // hence instead we should check whether elements are actually visible,\n // so that once these changes are applied they actually result in a visible change to the user\n if (!isShallowEqual(prevLockedUnits, nextLockedUnits)) {\n visibleDifferenceFlag.value = true;\n }\n break;\n case \"activeLockedId\":\n const prevHitLockedId = prevAppState[key] || null;\n const nextHitLockedId = nextAppState[key] || null;\n\n // TODO: this seems wrong, we are already doing this comparison generically above,\n // hence instead we should check whether elements are actually visible,\n // so that once these changes are applied they actually result in a visible change to the user\n if (prevHitLockedId !== nextHitLockedId) {\n visibleDifferenceFlag.value = true;\n }\n break;\n default:\n assertNever(\n key,\n `Unknown ObservedElementsAppState's key \"${key}\"`,\n true,\n );\n }\n }\n }\n\n return visibleDifferenceFlag.value;\n }\n\n private static filterSelectedElements(\n selectedElementIds: AppState[\"selectedElementIds\"],\n elements: SceneElementsMap,\n visibleDifferenceFlag: { value: boolean },\n ) {\n const ids = Object.keys(selectedElementIds);\n\n if (!ids.length) {\n // previously there were ids (assuming related to visible elements), now there are none\n visibleDifferenceFlag.value = true;\n return selectedElementIds;\n }\n\n const nextSelectedElementIds = { ...selectedElementIds };\n\n for (const id of ids) {\n const element = elements.get(id);\n\n if (element && !element.isDeleted) {\n // there is a selected element id related to a visible element\n visibleDifferenceFlag.value = true;\n } else {\n delete nextSelectedElementIds[id];\n }\n }\n\n return nextSelectedElementIds;\n }\n\n private static filterSelectedGroups(\n selectedGroupIds: AppState[\"selectedGroupIds\"],\n nonDeletedGroupIds: Set<string>,\n visibleDifferenceFlag: { value: boolean },\n ) {\n const ids = Object.keys(selectedGroupIds);\n\n if (!ids.length) {\n // previously there were ids (assuming related to visible groups), now there are none\n visibleDifferenceFlag.value = true;\n return selectedGroupIds;\n }\n\n const nextSelectedGroupIds = { ...selectedGroupIds };\n\n for (const id of Object.keys(nextSelectedGroupIds)) {\n if (nonDeletedGroupIds.has(id)) {\n // there is a selected group id related to a visible group\n visibleDifferenceFlag.value = true;\n } else {\n delete nextSelectedGroupIds[id];\n }\n }\n\n return nextSelectedGroupIds;\n }\n\n private static stripElementsProps(\n delta: Partial<ObservedAppState>,\n ): Partial<ObservedStandaloneAppState> {\n // WARN: Do not remove the type-casts as they here to ensure proper type checks\n const {\n editingGroupId,\n selectedGroupIds,\n selectedElementIds,\n selectedLinearElement,\n croppingElementId,\n lockedMultiSelections,\n activeLockedId,\n ...standaloneProps\n } = delta as ObservedAppState;\n\n return standaloneProps as SubtypeOf<\n typeof standaloneProps,\n ObservedStandaloneAppState\n >;\n }\n\n private static stripStandaloneProps(\n delta: Partial<ObservedAppState>,\n ): Partial<ObservedElementsAppState> {\n // WARN: Do not remove the type-casts as they here to ensure proper type checks\n const { name, viewBackgroundColor, ...elementsProps } =\n delta as ObservedAppState;\n\n return elementsProps as SubtypeOf<\n typeof elementsProps,\n ObservedElementsAppState\n >;\n }\n\n /**\n * It is necessary to post process the partials in case of reference values,\n * for which we need to calculate the real diff between `deleted` and `inserted`.\n */\n private static postProcess<T extends ObservedAppState>(\n deleted: Partial<T>,\n inserted: Partial<T>,\n ): [Partial<T>, Partial<T>] {\n try {\n Delta.diffObjects(\n deleted,\n inserted,\n \"selectedElementIds\",\n // ts language server has a bit trouble resolving this, so we are giving it a little push\n (_) => true as ValueOf<T[\"selectedElementIds\"]>,\n );\n Delta.diffObjects(\n deleted,\n inserted,\n \"selectedGroupIds\",\n (prevValue) => (prevValue ?? false) as ValueOf<T[\"selectedGroupIds\"]>,\n );\n Delta.diffObjects(\n deleted,\n inserted,\n \"lockedMultiSelections\",\n (prevValue) => (prevValue ?? {}) as ValueOf<T[\"lockedMultiSelections\"]>,\n );\n } catch (e) {\n // if postprocessing fails it does not make sense to bubble up, but let's make sure we know about it\n console.error(`Couldn't postprocess appstate change deltas.`);\n\n if (isTestEnv() || isDevEnv()) {\n throw e;\n }\n } finally {\n return [deleted, inserted];\n }\n }\n\n private static orderAppStateKeys(partial: Partial<ObservedAppState>) {\n const orderedPartial: { [key: string]: unknown } = {};\n\n for (const key of Object.keys(partial).sort()) {\n // relying on insertion order\n orderedPartial[key] = partial[key as keyof ObservedAppState];\n }\n\n return orderedPartial as Partial<ObservedAppState>;\n }\n}\n\ntype ElementPartial<TElement extends ExcalidrawElement = ExcalidrawElement> =\n Omit<Partial<Ordered<TElement>>, \"id\" | \"updated\" | \"seed\">;\n\nexport type ApplyToOptions = {\n excludedProperties?: Set<keyof ElementPartial>;\n};\n\ntype ApplyToFlags = {\n containsVisibleDifference: boolean;\n containsZindexDifference: boolean;\n applyDirection: \"forward\" | \"backward\" | undefined;\n};\n\n/**\n * Elements change is a low level primitive to capture a change between two sets of elements.\n * It does so by encapsulating forward and backward `Delta`s, allowing to time-travel in both directions.\n */\nexport class ElementsDelta implements DeltaContainer<SceneElementsMap> {\n private constructor(\n public readonly added: Record<string, Delta<ElementPartial>>,\n public readonly removed: Record<string, Delta<ElementPartial>>,\n public readonly updated: Record<string, Delta<ElementPartial>>,\n ) {}\n\n public static create(\n added: Record<string, Delta<ElementPartial>>,\n removed: Record<string, Delta<ElementPartial>>,\n updated: Record<string, Delta<ElementPartial>>,\n options: {\n shouldRedistribute: boolean;\n } = {\n shouldRedistribute: false,\n },\n ) {\n let delta: ElementsDelta;\n\n if (options.shouldRedistribute) {\n const nextAdded: Record<string, Delta<ElementPartial>> = {};\n const nextRemoved: Record<string, Delta<ElementPartial>> = {};\n const nextUpdated: Record<string, Delta<ElementPartial>> = {};\n\n const deltas = [\n ...Object.entries(added),\n ...Object.entries(removed),\n ...Object.entries(updated),\n ];\n\n for (const [id, delta] of deltas) {\n if (this.satisfiesAddition(delta)) {\n nextAdded[id] = delta;\n } else if (this.satisfiesRemoval(delta)) {\n nextRemoved[id] = delta;\n } else {\n nextUpdated[id] = delta;\n }\n }\n\n delta = new ElementsDelta(nextAdded, nextRemoved, nextUpdated);\n } else {\n delta = new ElementsDelta(added, removed, updated);\n }\n\n if (isTestEnv() || isDevEnv()) {\n ElementsDelta.validate(delta, \"added\", this.satisfiesAddition);\n ElementsDelta.validate(delta, \"removed\", this.satisfiesRemoval);\n ElementsDelta.validate(delta, \"updated\", this.satisfiesUpdate);\n }\n\n return delta;\n }\n\n public static restore(elementsDeltaDTO: DTO<ElementsDelta>): ElementsDelta {\n const { added, removed, updated } = elementsDeltaDTO;\n return ElementsDelta.create(added, removed, updated);\n }\n\n private static satisfiesAddition = ({\n deleted,\n inserted,\n }: Delta<ElementPartial>) =>\n // dissallowing added as \"deleted\", which could cause issues when resolving conflicts\n deleted.isDeleted === true && !inserted.isDeleted;\n\n private static satisfiesRemoval = ({\n deleted,\n inserted,\n }: Delta<ElementPartial>) =>\n !deleted.isDeleted && inserted.isDeleted === true;\n\n private static satisfiesUpdate = ({\n deleted,\n inserted,\n }: Delta<ElementPartial>) => !!deleted.isDeleted === !!inserted.isDeleted;\n\n private static satisfiesCommmonInvariants = ({\n deleted,\n inserted,\n }: Delta<ElementPartial>) =>\n !!(\n // versions are required integers\n (\n Number.isInteger(deleted.version) &&\n Number.isInteger(inserted.version) &&\n // versions should be positive, zero included\n deleted.version! >= 0 &&\n inserted.version! >= 0 &&\n // versions should never be the same\n deleted.version !== inserted.version\n )\n );\n\n private static satisfiesUniqueInvariants = (\n elementsDelta: ElementsDelta,\n id: string,\n ) => {\n const { added, removed, updated } = elementsDelta;\n // it's required that there is only one unique delta type per element\n return [added[id], removed[id], updated[id]].filter(Boolean).length === 1;\n };\n\n private static validate(\n elementsDelta: ElementsDelta,\n type: \"added\" | \"removed\" | \"updated\",\n satifiesSpecialInvariants: (delta: Delta<ElementPartial>) => boolean,\n ) {\n for (const [id, delta] of Object.entries(elementsDelta[type])) {\n if (\n !this.satisfiesCommmonInvariants(delta) ||\n !this.satisfiesUniqueInvariants(elementsDelta, id) ||\n !satifiesSpecialInvariants(delta)\n ) {\n console.error(\n `Broken invariant for \"${type}\" delta, element \"${id}\", delta:`,\n delta,\n );\n throw new Error(`ElementsDelta invariant broken for element \"${id}\".`);\n }\n }\n }\n\n /**\n * Calculates the `Delta`s between the previous and next set of elements.\n *\n * @param prevElements - Map representing the previous state of elements.\n * @param nextElements - Map representing the next state of elements.\n *\n * @returns `ElementsDelta` instance representing the `Delta` changes between the two sets of elements.\n */\n public static calculate<T extends OrderedExcalidrawElement>(\n prevElements: Map<string, T>,\n nextElements: Map<string, T>,\n ): ElementsDelta {\n if (prevElements === nextElements) {\n return ElementsDelta.empty();\n }\n\n const added: Record<string, Delta<ElementPartial>> = {};\n const removed: Record<string, Delta<ElementPartial>> = {};\n const updated: Record<string, Delta<ElementPartial>> = {};\n\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\n for (const prevElement of prevElements.values()) {\n const nextElement = nextElements.get(prevElement.id);\n\n if (!nextElement) {\n const deleted = { ...prevElement } as ElementPartial;\n\n const inserted = {\n isDeleted: true,\n version: prevElement.version + 1,\n versionNonce: randomInteger(),\n } as ElementPartial;\n\n const delta = Delta.create(\n deleted,\n inserted,\n ElementsDelta.stripIrrelevantProps,\n );\n\n if (!prevElement.isDeleted) {\n removed[prevElement.id] = delta;\n } else {\n updated[prevElement.id] = delta;\n }\n }\n }\n\n for (const nextElement of nextElements.values()) {\n const prevElement = prevElements.get(nextElement.id);\n\n if (!prevElement) {\n const deleted = {\n isDeleted: true,\n version: nextElement.version - 1,\n versionNonce: randomInteger(),\n } as ElementPartial;\n\n const inserted = {\n ...nextElement,\n } as ElementPartial;\n\n const delta = Delta.create(\n deleted,\n inserted,\n ElementsDelta.stripIrrelevantProps,\n );\n\n // ignore updates which would \"delete\" already deleted element\n if (!nextElement.isDeleted) {\n added[nextElement.id] = delta;\n } else {\n updated[nextElement.id] = delta;\n }\n\n continue;\n }\n\n if (prevElement.versionNonce !== nextElement.versionNonce) {\n const delta = Delta.calculate<ElementPartial>(\n prevElement,\n nextElement,\n ElementsDelta.stripIrrelevantProps,\n ElementsDelta.postProcess,\n );\n\n if (\n // making sure we don't get here some non-boolean values (i.e. undefined, null, etc.)\n typeof prevElement.isDeleted === \"boolean\" &&\n typeof nextElement.isDeleted === \"boolean\" &&\n prevElement.isDeleted !== nextElement.isDeleted\n ) {\n // notice that other props could have been updated as well\n if (prevElement.isDeleted && !nextElement.isDeleted) {\n added[nextElement.id] = delta;\n } else {\n removed[nextElement.id] = delta;\n }\n\n continue;\n }\n\n updated[nextElement.id] = delta;\n }\n }\n\n return ElementsDelta.create(added, removed, updated);\n }\n\n public static empty() {\n return ElementsDelta.create({}, {}, {});\n }\n\n public inverse(): ElementsDelta {\n const inverseInternal = (deltas: Record<string, Delta<ElementPartial>>) => {\n const inversedDeltas: Record<string, Delta<ElementPartial>> = {};\n\n for (const [id, { inserted, deleted }] of Object.entries(deltas)) {\n inversedDeltas[id] = Delta.create({ ...inserted }, { ...deleted });\n }\n\n return inversedDeltas;\n };\n\n const added = inverseInternal(this.added);\n const removed = inverseInternal(this.removed);\n const updated = inverseInternal(this.updated);\n\n // notice we inverse removed with added not to break the invariants\n return ElementsDelta.create(removed, added, updated);\n }\n\n public isEmpty(): boolean {\n return (\n Object.keys(this.added).length === 0 &&\n Object.keys(this.removed).length === 0 &&\n Object.keys(this.updated).length === 0\n );\n }\n\n /**\n * Update delta/s based on the existing elements.\n *\n * @param nextElements current elements\n * @param modifierOptions defines which of the delta (`deleted` or `inserted`) will be updated\n * @returns new instance with modified delta/s\n */\n public applyLatestChanges(\n prevElements: SceneElementsMap,\n nextElements: SceneElementsMap,\n modifierOptions?: \"deleted\" | \"inserted\",\n ): ElementsDelta {\n const modifier =\n (\n prevElement: OrderedExcalidrawElement | undefined,\n nextElement: OrderedExcalidrawElement | undefined,\n ) =>\n (partial: ElementPartial, partialType: \"deleted\" | \"inserted\") => {\n let element: OrderedExcalidrawElement | undefined;\n\n switch (partialType) {\n case \"deleted\":\n element = prevElement;\n break;\n case \"inserted\":\n element = nextElement;\n break;\n }\n\n // the element wasn't found -> don't update the partial\n if (!element) {\n console.error(\n `Element not found when trying to apply latest changes`,\n );\n return partial;\n }\n\n const latestPartial: { [key: string]: unknown } = {};\n\n for (const key of Object.keys(partial) as Array<keyof typeof partial>) {\n // do not update following props:\n // - `boundElements`, as it is a reference value which is postprocessed to contain only deleted/inserted keys\n switch (key) {\n case \"boundElements\":\n latestPartial[key] = partial[key];\n break;\n default:\n latestPartial[key] = element[key];\n }\n }\n\n return latestPartial;\n };\n\n const applyLatestChangesInternal = (\n deltas: Record<string, Delta<ElementPartial>>,\n ) => {\n const modifiedDeltas: Record<string, Delta<ElementPartial>> = {};\n\n for (const [id, delta] of Object.entries(deltas)) {\n const prevElement = prevElements.get(id);\n const nextElement = nextElements.get(id);\n\n let latestDelta: Delta<ElementPartial> | null = null;\n\n if (prevElement || nextElement) {\n latestDelta = Delta.create(\n delta.deleted,\n delta.inserted,\n modifier(prevElement, nextElement),\n modifierOptions,\n );\n } else {\n latestDelta = delta;\n }\n\n // it might happen that after applying latest changes the delta itself does not contain any changes\n if (Delta.isInnerDifferent(latestDelta.deleted, latestDelta.inserted)) {\n modifiedDeltas[id] = latestDelta;\n }\n }\n\n return modifiedDeltas;\n };\n\n const added = applyLatestChangesInternal(this.added);\n const removed = applyLatestChangesInternal(this.removed);\n const updated = applyLatestChangesInternal(this.updated);\n\n return ElementsDelta.create(added, removed, updated, {\n shouldRedistribute: true, // redistribute the deltas as `isDeleted` could have been updated\n });\n }\n\n public applyTo(\n elements: SceneElementsMap,\n snapshot: StoreSnapshot[\"elements\"] = StoreSnapshot.empty().elements,\n options?: ApplyToOptions,\n ): [SceneElementsMap, boolean] {\n let nextElements = new Map(elements) as SceneElementsMap;\n let changedElements: Map<string, OrderedExcalidrawElement>;\n\n const flags: ApplyToFlags = {\n containsVisibleDifference: false,\n containsZindexDifference: false,\n applyDirection: undefined,\n };\n\n // mimic a transaction by applying deltas into `nextElements` (always new instance, no mutation)\n try {\n const applyDeltas = ElementsDelta.createApplier(\n elements,\n nextElements,\n snapshot,\n flags,\n options,\n );\n\n const addedElements = applyDeltas(this.added);\n const removedElements = applyDeltas(this.removed);\n const updatedElements = applyDeltas(this.updated);\n\n const affectedElements = this.resolveConflicts(\n elements,\n nextElements,\n flags.applyDirection,\n );\n\n // TODO: #7348 validate elements semantically and syntactically the changed elements, in case they would result data integrity issues\n changedElements = new Map([\n ...addedElements,\n ...removedElements,\n ...updatedElements,\n ...affectedElements,\n ]);\n } catch (e) {\n console.error(`Couldn't apply elements delta`, e);\n\n if (isTestEnv() || isDevEnv()) {\n throw e;\n }\n\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`\n // even though there is obviously no visible change, returning `false` could be dangerous, as i.e.:\n // in the worst case, it could lead into iterating through the whole stack with no possibility to redo\n // instead, the worst case when returning `true` is an empty undo / redo\n return [elements, true];\n }\n\n try {\n // the following reorder performs mutations, but only on new instances of changed elements,\n // unless something goes really bad and it fallbacks to fixing all invalid indices\n nextElements = ElementsDelta.reorderElements(\n nextElements,\n changedElements,\n flags,\n );\n\n ElementsDelta.redrawElements(nextElements, changedElements);\n } catch (e) {\n console.error(\n `Couldn't mutate elements after applying elements change`,\n e,\n );\n\n if (isTestEnv() || isDevEnv()) {\n throw e;\n }\n } finally {\n return [nextElements, flags.containsVisibleDifference];\n }\n }\n\n public squash(delta: ElementsDelta): this {\n if (delta.isEmpty()) {\n return this;\n }\n\n const { added, removed, updated } = delta;\n\n const mergeBoundElements = (\n prevDelta: Delta<ElementPartial>,\n nextDelta: Delta<ElementPartial>,\n ) => {\n const mergedDeletedBoundElements =\n Delta.mergeArrays(\n prevDelta.deleted.boundElements ?? [],\n nextDelta.deleted.boundElements ?? [],\n undefined,\n (x) => x.id,\n ) ?? [];\n\n const mergedInsertedBoundElements =\n Delta.mergeArrays(\n prevDelta.inserted.boundElements ?? [],\n nextDelta.inserted.boundElements ?? [],\n undefined,\n (x) => x.id,\n ) ?? [];\n\n if (\n !mergedDeletedBoundElements.length &&\n !mergedInsertedBoundElements.length\n ) {\n return;\n }\n\n return Delta.create(\n {\n boundElements: mergedDeletedBoundElements,\n },\n {\n boundElements: mergedInsertedBoundElements,\n },\n );\n };\n\n for (const [id, nextDelta] of Object.entries(added)) {\n const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];\n\n if (!prevDelta) {\n this.added[id] = nextDelta;\n } else {\n const mergedDelta = mergeBoundElements(prevDelta, nextDelta);\n delete this.removed[id];\n delete this.updated[id];\n\n this.added[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);\n }\n }\n\n for (const [id, nextDelta] of Object.entries(removed)) {\n const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];\n\n if (!prevDelta) {\n this.removed[id] = nextDelta;\n } else {\n const mergedDelta = mergeBoundElements(prevDelta, nextDelta);\n delete this.added[id];\n delete this.updated[id];\n\n this.removed[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);\n }\n }\n\n for (const [id, nextDelta] of Object.entries(updated)) {\n const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];\n\n if (!prevDelta) {\n this.updated[id] = nextDelta;\n } else {\n const mergedDelta = mergeBoundElements(prevDelta, nextDelta);\n const updatedDelta = Delta.merge(prevDelta, nextDelta, mergedDelta);\n\n if (prevDelta === this.added[id]) {\n this.added[id] = updatedDelta;\n } else if (prevDelta === this.removed[id]) {\n this.removed[id] = updatedDelta;\n } else {\n this.updated[id] = updatedDelta;\n }\n }\n }\n\n if (isTestEnv() || isDevEnv()) {\n ElementsDelta.validate(this, \"added\", ElementsDelta.satisfiesAddition);\n ElementsDelta.validate(this, \"removed\", ElementsDelta.satisfiesRemoval);\n ElementsDelta.validate(this, \"updated\", ElementsDelta.satisfiesUpdate);\n }\n\n return this;\n }\n\n private static createApplier =\n (\n prevElements: SceneElementsMap,\n nextElements: SceneElementsMap,\n snapshot: StoreSnapshot[\"elements\"],\n flags: ApplyToFlags,\n options?: ApplyToOptions,\n ) =>\n (deltas: Record<string, Delta<ElementPartial>>) => {\n const getElement = ElementsDelta.createGetter(\n nextElements,\n snapshot,\n flags,\n );\n\n return Object.entries(deltas).reduce((acc, [id, delta]) => {\n const element = getElement(id, delta.inserted);\n\n if (element) {\n const nextElement = ElementsDelta.applyDelta(\n element,\n delta,\n flags,\n options,\n );\n\n nextElements.set(nextElement.id, nextElement);\n acc.set(nextElement.id, nextElement);\n\n if (!flags.applyDirection) {\n const prevElement = prevElements.get(id);\n\n if (prevElement) {\n flags.applyDirection =\n prevElement.version > nextElement.version\n ? \"backward\"\n : \"forward\";\n }\n }\n }\n\n return acc;\n }, new Map<string, OrderedExcalidrawElement>());\n };\n\n private static createGetter =\n (\n elements: SceneElementsMap,\n snapshot: StoreSnapshot[\"elements\"],\n flags: ApplyToFlags,\n ) =>\n (id: string, partial: ElementPartial) => {\n let element = elements.get(id);\n\n if (!element) {\n // always fallback to the local snapshot, in cases when we cannot find the element in the elements array\n element = snapshot.get(id);\n\n if (element) {\n // as the element was brought from the snapshot, it automatically results in a possible zindex difference\n flags.containsZindexDifference = true;\n\n // as the element was force deleted, we need to check if adding it back results in a visible change\n if (!partial.isDeleted || (partial.isDeleted && !element.isDeleted)) {\n flags.containsVisibleDifference = true;\n }\n } else {\n // not in elements, not in snapshot? element might have been added remotely!\n element = newElementWith(\n { id, version: 1 } as OrderedExcalidrawElement,\n {\n ...partial,\n },\n );\n }\n }\n\n return element;\n };\n\n private static applyDelta(\n element: OrderedExcalidrawElement,\n delta: Delta<ElementPartial>,\n flags: ApplyToFlags,\n options?: ApplyToOptions,\n ) {\n const directlyApplicablePartial: Mutable<ElementPartial> = {};\n\n // some properties are not directly applicable, such as:\n // - boundElements which contains only diff)\n // - version & versionNonce, if we don't want to return to previous versions\n for (const key of Object.keys(delta.inserted) as Array<\n keyof typeof delta.inserted\n >) {\n if (key === \"boundElements\") {\n continue;\n }\n\n if (options?.excludedProperties?.has(key)) {\n continue;\n }\n\n const value = delta.inserted[key];\n Reflect.set(directlyApplicablePartial, key, value);\n }\n\n if (\n delta.deleted.boundElements?.length ||\n delta.inserted.boundElements?.length\n ) {\n const mergedBoundElements = Delta.mergeArrays(\n element.boundElements,\n delta.inserted.boundElements,\n delta.deleted.boundElements,\n (x) => x.id,\n );\n\n Object.assign(directlyApplicablePartial, {\n boundElements: mergedBoundElements,\n });\n }\n\n if (!flags.containsVisibleDifference) {\n // strip away fractional index, as even if it would be different, it doesn't have to result in visible change\n const { index, ...rest } = directlyApplicablePartial;\n const containsVisibleDifference = ElementsDelta.checkForVisibleDifference(\n element,\n rest,\n );\n\n flags.containsVisibleDifference = containsVisibleDifference;\n }\n\n if (!flags.containsZindexDifference) {\n flags.containsZindexDifference =\n delta.deleted.index !== delta.inserted.index;\n }\n\n return newElementWith(element, directlyApplicablePartial, true);\n }\n\n /**\n * Check for visible changes regardless of whether they were removed, added or updated.\n */\n private static checkForVisibleDifference(\n element: OrderedExcalidrawElement,\n partial: ElementPartial,\n ) {\n if (element.isDeleted && partial.isDeleted !== false) {\n // when it's deleted and partial is not false, it cannot end up with a visible change\n return false;\n }\n\n if (element.isDeleted && partial.isDeleted === false) {\n // when we add an element, it results in a visible change\n return true;\n }\n\n if (element.isDeleted === false && partial.isDeleted) {\n // when we remove an element, it results in a visible change\n return true;\n }\n\n // check for any difference on a visible element\n return Delta.isRightDifferent(element, partial);\n }\n\n /**\n * Resolves conflicts for all previously added, removed and updated elements.\n * Updates the previous deltas with all the changes after conflict resolution.\n *\n * // TODO: revisit since some bound arrows seem to be often redrawn incorrectly\n *\n * @returns all elements affected by the conflict resolution\n */\n private resolveConflicts(\n prevElements: SceneElementsMap,\n nextElements: SceneElementsMap,\n applyDirection: \"forward\" | \"backward\" = \"forward\",\n ) {\n const nextAffectedElements = new Map<string, OrderedExcalidrawElement>();\n const updater = (\n element: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => {\n const nextElement = nextElements.get(element.id); // only ever modify next element!\n if (!nextElement) {\n return;\n }\n\n const prevElement = prevElements.get(element.id);\n const nextVersion =\n applyDirection === \"forward\"\n ? nextElement.version + 1\n : nextElement.version - 1;\n\n const elementUpdates = updates as ElementUpdate<OrderedExcalidrawElement>;\n\n let affectedElement: OrderedExcalidrawElement;\n\n if (prevElement === nextElement) {\n // create the new element instance in case we didn't modify the element yet\n // so that we won't end up in an incosistent state in case we would fail in the middle of mutations\n affectedElement = newElementWith(\n nextElement,\n {\n ...elementUpdates,\n version: nextVersion,\n },\n true,\n );\n } else {\n affectedElement = mutateElement(nextElement, nextElements, {\n ...elementUpdates,\n // don't modify the version further, if it's already different\n version:\n prevElement?.version !== nextElement.version\n ? nextElement.version\n : nextVersion,\n });\n }\n\n nextAffectedElements.set(affectedElement.id, affectedElement);\n nextElements.set(affectedElement.id, affectedElement);\n };\n\n // removed delta is affecting the bindings always, as all the affected elements of the removed elements need to be unbound\n for (const id of Object.keys(this.removed)) {\n ElementsDelta.unbindAffected(prevElements, nextElements, id, updater);\n }\n\n // added delta is affecting the bindings always, all the affected elements of the added elements need to be rebound\n for (const id of Object.keys(this.added)) {\n ElementsDelta.rebindAffected(prevElements, nextElements, id, updater);\n }\n\n // updated delta is affecting the binding only in case it contains changed binding or bindable property\n for (const [id] of Array.from(Object.entries(this.updated)).filter(\n ([_, delta]) =>\n Object.keys({ ...delta.deleted, ...delta.inserted }).find((prop) =>\n bindingProperties.has(prop as BindingProp | BindableProp),\n ),\n )) {\n const updatedElement = nextElements.get(id);\n if (!updatedElement || updatedElement.isDeleted) {\n // skip fixing bindings for updates on deleted elements\n continue;\n }\n\n ElementsDelta.rebindAffected(prevElements, nextElements, id, updater);\n }\n\n // filter only previous elements, which were now affected\n const prevAffectedElements = new Map(\n Array.from(prevElements).filter(([id]) => nextAffectedElements.has(id)),\n );\n\n // calculate complete deltas for affected elements, and squash them back to the current deltas\n this.squash(\n // technically we could do better here if perf. would become an issue\n ElementsDelta.calculate(prevAffectedElements, nextAffectedElements),\n );\n\n return nextAffectedElements;\n }\n\n /**\n * Non deleted affected elements of removed elements (before and after applying delta),\n * should be unbound ~ bindings should not point from non deleted into the deleted element/s.\n */\n private static unbindAffected(\n prevElements: SceneElementsMap,\n nextElements: SceneElementsMap,\n id: string,\n updater: (\n element: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => void,\n ) {\n // the instance could have been updated, so make sure we are passing the latest element to each function below\n const prevElement = () => prevElements.get(id); // element before removal\n const nextElement = () => nextElements.get(id); // element after removal\n\n BoundElement.unbindAffected(nextElements, prevElement(), updater);\n BoundElement.unbindAffected(nextElements, nextElement(), updater);\n\n BindableElement.unbindAffected(nextElements, prevElement(), updater);\n BindableElement.unbindAffected(nextElements, nextElement(), updater);\n }\n\n /**\n * Non deleted affected elements of added or updated element/s (before and after applying delta),\n * should be rebound (if possible) with the current element ~ bindings should be bidirectional.\n */\n private static rebindAffected(\n prevElements: SceneElementsMap,\n nextElements: SceneElementsMap,\n id: string,\n updater: (\n element: ExcalidrawElement,\n updates: ElementUpdate<ExcalidrawElement>,\n ) => void,\n ) {\n // the instance could have been updated, so make sure we are passing the latest element to each function below\n const prevElement = () => prevElements.get(id); // element before addition / update\n const nextElement = () => nextElements.get(id); // element after addition / update\n\n BoundElement.unbindAffected(nextElements, prevElement(), updater);\n BoundElement.rebindAffected(nextElements, nextElement(), updater);\n\n BindableElement.unbindAffected(\n nextElements,\n prevElement(),\n (element, updates) => {\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)\n // TODO: #7348 add startBinding / endBinding to the `BoundElement` context so that we could rebind arrows and remove this condition\n if (isTextElement(element)) {\n updater(element, updates);\n }\n },\n );\n BindableElement.rebindAffected(nextElements, nextElement(), updater);\n }\n\n public static redrawElements(\n nextElements: SceneElementsMap,\n changedElements: Map<string, OrderedExcalidrawElement>,\n ) {\n try {\n // we don't have an up-to-date scene, as we can be just in the middle of applying history entry\n // we also don't have a scene on the server\n // so we are creating a temp scene just to query and mutate elements\n const tempScene = new Scene(nextElements, { skipValidation: true });\n\n ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);\n\n // needs ordered nextElements to avoid z-index binding issues\n ElementsDelta.redrawBoundArrows(tempScene, changedElements);\n } catch (e) {\n console.error(`Couldn't redraw elements`, e);\n\n if (isTestEnv() || isDevEnv()) {\n throw e;\n }\n } finally {\n return nextElements;\n }\n }\n\n private static redrawTextBoundingBoxes(\n scene: Scene,\n changed: Map<string, OrderedExcalidrawElement>,\n ) {\n const elements = scene.getNonDeletedElementsMap();\n const boxesToRedraw = new Map<\n string,\n { container: OrderedExcalidrawElement; boundText: ExcalidrawTextElement }\n >();\n\n for (const element of changed.values()) {\n if (isBoundToContainer(element)) {\n const { containerId } = element as ExcalidrawTextElement;\n const container = containerId ? elements.get(containerId) : undefined;\n\n if (container) {\n boxesToRedraw.set(container.id, {\n container,\n boundText: element as ExcalidrawTextElement,\n });\n }\n }\n\n if (hasBoundTextElement(element)) {\n const boundTextElementId = getBoundTextElementId(element);\n const boundText = boundTextElementId\n ? elements.get(boundTextElementId)\n : undefined;\n\n if (boundText) {\n boxesToRedraw.set(element.id, {\n container: element,\n boundText: boundText as ExcalidrawTextElement,\n });\n }\n }\n }\n\n for (const { container, boundText } of boxesToRedraw.values()) {\n if (container.isDeleted || boundText.isDeleted) {\n // skip redraw if one of them is deleted, as it would not result in a meaningful redraw\n continue;\n }\n\n redrawTextBoundingBox(boundText, container, scene);\n }\n }\n\n private static redrawBoundArrows(\n scene: Scene,\n changed: Map<string, OrderedExcalidrawElement>,\n ) {\n for (const element of changed.values()) {\n if (!element.isDeleted && isBindableElement(element)) {\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\n updateBoundElements(element, scene, {\n changedElements: changed,\n });\n }\n }\n }\n\n private static reorderElements(\n elements: SceneElementsMap,\n changed: Map<string, OrderedExcalidrawElement>,\n flags: {\n containsVisibleDifference: boolean;\n containsZindexDifference: boolean;\n },\n ) {\n if (!flags.containsZindexDifference) {\n return elements;\n }\n\n const unordered = Array.from(elements.values());\n const ordered = orderByFractionalIndex([...unordered]);\n const moved = Delta.getRightDifferences(unordered, ordered, true).reduce(\n (acc, arrayIndex) => {\n const candidate = unordered[Number(arrayIndex)];\n if (candidate && changed.has(candidate.id)) {\n acc.set(candidate.id, candidate);\n }\n\n return acc;\n },\n new Map(),\n );\n\n if (!flags.containsVisibleDifference && moved.size) {\n // we found a difference in order!\n flags.containsVisibleDifference = true;\n }\n\n // synchronize all elements that were actually moved\n // could fallback to synchronizing all invalid indices\n return arrayToMap(syncMovedIndices(ordered, moved)) as typeof elements;\n }\n\n /**\n * It is necessary to post process the partials in case of reference values,\n * for which we need to calculate the real diff between `deleted` and `inserted`.\n */\n private static postProcess(\n deleted: ElementPartial,\n inserted: ElementPartial,\n ): [ElementPartial, ElementPartial] {\n try {\n Delta.diffArrays(deleted, inserted, \"boundElements\", (x) => x.id);\n\n // don't diff the points as:\n // - we can't ensure the multiplayer order consistency without fractional index on each point\n // - we prefer to not merge the points, as it might just lead to unexpected / incosistent results\n const deletedPoints =\n (\n deleted as ElementPartial<\n ExcalidrawFreeDrawElement | ExcalidrawLinearElement\n >\n ).points ?? [];\n\n const insertedPoints =\n (\n inserted as ElementPartial<\n ExcalidrawFreeDrawElement | ExcalidrawLinearElement\n >\n ).points ?? [];\n\n if (!Delta.isDifferent(deletedPoints, insertedPoints)) {\n // delete the points from delta if there is no difference, otherwise leave them as they were captured due to consistency\n Reflect.deleteProperty(deleted, \"points\");\n Reflect.deleteProperty(inserted, \"points\");\n }\n } catch (e) {\n // if postprocessing fails, it does not make sense to bubble up, but let's make sure we know about it\n console.error(`Couldn't postprocess elements delta.`);\n\n if (isTestEnv() || isDevEnv()) {\n throw e;\n }\n } finally {\n return [deleted, inserted];\n }\n }\n\n private static stripIrrelevantProps(\n partial: Partial<OrderedExcalidrawElement>,\n ): ElementPartial {\n const { id, updated, ...strippedPartial } = partial;\n\n return strippedPartial;\n }\n}\n", "import type { AppState } from \"@excalidraw/excalidraw/types\";\n\nimport { getCommonBoundingBox } from \"./bounds\";\nimport { newElementWith } from \"./mutateElement\";\n\nimport { getSelectedElementsByGroup } from \"./groups\";\n\nimport type { ElementsMap, ExcalidrawElement } from \"./types\";\n\nexport interface Distribution {\n space: \"between\";\n axis: \"x\" | \"y\";\n}\n\nexport const distributeElements = (\n selectedElements: ExcalidrawElement[],\n elementsMap: ElementsMap,\n distribution: Distribution,\n appState: Readonly<AppState>,\n): ExcalidrawElement[] => {\n const [start, mid, end, extent] =\n distribution.axis === \"x\"\n ? ([\"minX\", \"midX\", \"maxX\", \"width\"] as const)\n : ([\"minY\", \"midY\", \"maxY\", \"height\"] as const);\n\n const bounds = getCommonBoundingBox(selectedElements);\n const groups = getSelectedElementsByGroup(\n selectedElements,\n elementsMap,\n appState,\n )\n .map((group) => [group, getCommonBoundingBox(group)] as const)\n .sort((a, b) => a[1][mid] - b[1][mid]);\n\n let span = 0;\n for (const group of groups) {\n span += group[1][extent];\n }\n\n const step = (bounds[extent] - span) / (groups.length - 1);\n\n if (step < 0) {\n // If we have a negative step, we'll need to distribute from centers\n // rather than from gaps. Buckle up, this is a weird one.\n\n // Get indices of boxes that define start and end of our bounding box\n const index0 = groups.findIndex((g) => g[1][start] === bounds[start]);\n const index1 = groups.findIndex((g) => g[1][end] === bounds[end]);\n\n // Get our step, based on the distance between the center points of our\n // start and end boxes\n const step =\n (groups[index1][1][mid] - groups[index0][1][mid]) / (groups.length - 1);\n\n let pos = groups[index0][1][mid];\n\n return groups.flatMap(([group, box], index) => {\n const translation = {\n x: 0,\n y: 0,\n };\n\n // Don't move our start and end boxes\n if (index !== index0 && index !== index1) {\n pos += step;\n translation[distribution.axis] = pos - box[mid];\n }\n\n return group.map((element) =>\n newElementWith(element, {\n x: element.x + translation.x,\n y: element.y + translation.y,\n }),\n );\n });\n }\n\n // Distribute from gaps\n\n let pos = bounds[start];\n\n return groups.flatMap(([group, box]) => {\n const translation = {\n x: 0,\n y: 0,\n };\n\n translation[distribution.axis] = pos - box[start];\n\n pos += step;\n pos += box[extent];\n\n return group.map((element) =>\n newElementWith(element, {\n x: element.x + translation.x,\n y: element.y + translation.y,\n }),\n );\n });\n};\n", "import {\n type Bounds,\n TEXT_AUTOWRAP_THRESHOLD,\n getGridPoint,\n getFontString,\n DRAGGING_THRESHOLD,\n} from \"@excalidraw/common\";\n\nimport type {\n AppState,\n NormalizedZoomValue,\n NullableGridSize,\n PointerDownState,\n} from \"@excalidraw/excalidraw/types\";\n\nimport type { NonDeletedExcalidrawElement } from \"@excalidraw/element/types\";\n\nimport { unbindBindingElement, updateBoundElements } from \"./binding\";\nimport { getCommonBounds } from \"./bounds\";\nimport { getPerfectElementSize } from \"./sizeHelpers\";\nimport { getBoundTextElement } from \"./textElement\";\nimport { getMinTextElementWidth } from \"./textMeasurements\";\nimport {\n isArrowElement,\n isElbowArrow,\n isFrameLikeElement,\n isImageElement,\n isTextElement,\n} from \"./typeChecks\";\n\nimport type { Scene } from \"./Scene\";\n\nimport type { ExcalidrawElement } from \"./types\";\n\nexport const dragSelectedElements = (\n pointerDownState: PointerDownState,\n _selectedElements: NonDeletedExcalidrawElement[],\n offset: { x: number; y: number },\n scene: Scene,\n snapOffset: {\n x: number;\n y: number;\n },\n gridSize: NullableGridSize,\n) => {\n if (\n _selectedElements.length === 1 &&\n isElbowArrow(_selectedElements[0]) &&\n (_selectedElements[0].startBinding || _selectedElements[0].endBinding)\n ) {\n return;\n }\n\n const selectedElements = _selectedElements.filter((element) => {\n if (isElbowArrow(element) && element.startBinding && element.endBinding) {\n const startElement = _selectedElements.find(\n (el) => el.id === element.startBinding?.elementId,\n );\n const endElement = _selectedElements.find(\n (el) => el.id === element.endBinding?.elementId,\n );\n\n return startElement && endElement;\n }\n\n return true;\n });\n\n // we do not want a frame and its elements to be selected at the same time\n // but when it happens (due to some bug), we want to avoid updating element\n // in the frame twice, hence the use of set\n const elementsToUpdate = new Set<NonDeletedExcalidrawElement>(\n selectedElements,\n );\n const frames = selectedElements\n .filter((e) => isFrameLikeElement(e))\n .map((f) => f.id);\n\n if (frames.length > 0) {\n for (const element of scene.getNonDeletedElements()) {\n if (element.frameId !== null && frames.includes(element.frameId)) {\n elementsToUpdate.add(element);\n }\n }\n }\n\n const origElements: ExcalidrawElement[] = [];\n\n for (const element of elementsToUpdate) {\n const origElement = pointerDownState.originalElements.get(element.id);\n // if original element is not set (e.g. when you duplicate during a drag\n // operation), exit to avoid undefined behavior\n if (!origElement) {\n return;\n }\n origElements.push(origElement);\n }\n\n const adjustedOffset = calculateOffset(\n getCommonBounds(origElements),\n offset,\n snapOffset,\n gridSize,\n );\n\n const elementsToUpdateIds = new Set(\n Array.from(elementsToUpdate, (el) => el.id),\n );\n\n elementsToUpdate.forEach((element) => {\n const isArrow = !isArrowElement(element);\n const isStartBoundElementSelected =\n isArrow ||\n (element.startBinding\n ? elementsToUpdateIds.has(element.startBinding.elementId)\n : false);\n const isEndBoundElementSelected =\n isArrow ||\n (element.endBinding\n ? elementsToUpdateIds.has(element.endBinding.elementId)\n : false);\n\n if (!isArrowElement(element)) {\n updateElementCoords(pointerDownState, element, scene, adjustedOffset);\n\n // skip arrow labels since we calculate its position during render\n const textElement = getBoundTextElement(\n element,\n scene.getNonDeletedElementsMap(),\n );\n if (textElement) {\n updateElementCoords(\n pointerDownState,\n textElement,\n scene,\n adjustedOffset,\n );\n }\n updateBoundElements(element, scene, {\n simultaneouslyUpdated: Array.from(elementsToUpdate),\n });\n } else if (\n // NOTE: Add a little initial drag to the arrow dragging when the arrow\n // is the single element being dragged to avoid accidentally unbinding\n // the arrow when the user just wants to select it.\n\n elementsToUpdate.size > 1 ||\n Math.max(Math.abs(adjustedOffset.x), Math.abs(adjustedOffset.y)) >\n DRAGGING_THRESHOLD ||\n (!element.startBinding && !element.endBinding)\n ) {\n updateElementCoords(pointerDownState, element, scene, adjustedOffset);\n\n const shouldUnbindStart =\n element.startBinding && !isStartBoundElementSelected;\n const shouldUnbindEnd = element.endBinding && !isEndBoundElementSelected;\n if (shouldUnbindStart || shouldUnbindEnd) {\n // NOTE: Moving the bound arrow should unbind it, otherwise we would\n // have weird situations, like 0 lenght arrow when the user moves\n // the arrow outside a filled shape suddenly forcing the arrow start\n // and end point to jump \"outside\" the shape.\n if (shouldUnbindStart) {\n unbindBindingElement(element, \"start\", scene);\n }\n if (shouldUnbindEnd) {\n unbindBindingElement(element, \"end\", scene);\n }\n }\n }\n });\n};\n\nconst calculateOffset = (\n commonBounds: Bounds,\n dragOffset: { x: number; y: number },\n snapOffset: { x: number; y: number },\n gridSize: NullableGridSize,\n): { x: number; y: number } => {\n const [x, y] = commonBounds;\n let nextX = x + dragOffset.x + snapOffset.x;\n let nextY = y + dragOffset.y + snapOffset.y;\n\n if (snapOffset.x === 0 || snapOffset.y === 0) {\n const [nextGridX, nextGridY] = getGridPoint(\n x + dragOffset.x,\n y + dragOffset.y,\n gridSize,\n );\n\n if (snapOffset.x === 0) {\n nextX = nextGridX;\n }\n\n if (snapOffset.y === 0) {\n nextY = nextGridY;\n }\n }\n return {\n x: nextX - x,\n y: nextY - y,\n };\n};\n\nconst updateElementCoords = (\n pointerDownState: PointerDownState,\n element: NonDeletedExcalidrawElement,\n scene: Scene,\n dragOffset: { x: number; y: number },\n) => {\n const originalElement =\n pointerDownState.originalElements.get(element.id) ?? element;\n\n const nextX = originalElement.x + dragOffset.x;\n const nextY = originalElement.y + dragOffset.y;\n\n scene.mutateElement(element, {\n x: nextX,\n y: nextY,\n });\n};\n\nexport const getDragOffsetXY = (\n selectedElements: NonDeletedExcalidrawElement[],\n x: number,\n y: number,\n): [number, number] => {\n const [x1, y1] = getCommonBounds(selectedElements);\n return [x - x1, y - y1];\n};\n\nexport const dragNewElement = ({\n newElement,\n elementType,\n originX,\n originY,\n x,\n y,\n width,\n height,\n shouldMaintainAspectRatio,\n shouldResizeFromCenter,\n zoom,\n scene,\n widthAspectRatio = null,\n originOffset = null,\n informMutation = true,\n}: {\n newElement: NonDeletedExcalidrawElement;\n elementType: AppState[\"activeTool\"][\"type\"];\n originX: number;\n originY: number;\n x: number;\n y: number;\n width: number;\n height: number;\n shouldMaintainAspectRatio: boolean;\n shouldResizeFromCenter: boolean;\n zoom: NormalizedZoomValue;\n scene: Scene;\n /** whether to keep given aspect ratio when `isResizeWithSidesSameLength` is\n true */\n widthAspectRatio?: number | null;\n originOffset?: {\n x: number;\n y: number;\n } | null;\n informMutation?: boolean;\n}) => {\n if (shouldMaintainAspectRatio && newElement.type !== \"selection\") {\n if (widthAspectRatio) {\n height = width / widthAspectRatio;\n } else {\n // Depending on where the cursor is at (x, y) relative to where the starting point is\n // (originX, originY), we use ONLY width or height to control size increase.\n // This allows the cursor to always \"stick\" to one of the sides of the bounding box.\n if (Math.abs(y - originY) > Math.abs(x - originX)) {\n ({ width, height } = getPerfectElementSize(\n elementType,\n height,\n x < originX ? -width : width,\n ));\n } else {\n ({ width, height } = getPerfectElementSize(\n elementType,\n width,\n y < originY ? -height : height,\n ));\n }\n\n if (height < 0) {\n height = -height;\n }\n }\n }\n\n let newX = x < originX ? originX - width : originX;\n let newY = y < originY ? originY - height : originY;\n\n if (shouldResizeFromCenter) {\n width += width;\n height += height;\n newX = originX - width / 2;\n newY = originY - height / 2;\n }\n\n let textAutoResize = null;\n\n if (isTextElement(newElement)) {\n height = newElement.height;\n const minWidth = getMinTextElementWidth(\n getFontString({\n fontSize: newElement.fontSize,\n fontFamily: newElement.fontFamily,\n }),\n newElement.lineHeight,\n );\n width = Math.max(width, minWidth);\n\n if (Math.abs(x - originX) > TEXT_AUTOWRAP_THRESHOLD / zoom) {\n textAutoResize = {\n autoResize: false,\n };\n }\n\n newY = originY;\n if (shouldResizeFromCenter) {\n newX = originX - width / 2;\n }\n }\n\n if (width !== 0 && height !== 0) {\n let imageInitialDimension = null;\n if (isImageElement(newElement)) {\n imageInitialDimension = {\n initialWidth: width,\n initialHeight: height,\n };\n }\n\n scene.mutateElement(\n newElement,\n {\n x: newX + (originOffset?.x ?? 0),\n y: newY + (originOffset?.y ?? 0),\n width,\n height,\n ...textAutoResize,\n ...imageInitialDimension,\n },\n { informMutation, isDragging: false },\n );\n }\n};\n", "/**\n * Create and link between shapes.\n */\n\nimport { ELEMENT_LINK_KEY, normalizeLink } from \"@excalidraw/common\";\n\nimport type { AppProps, AppState } from \"@excalidraw/excalidraw/types\";\n\nimport { elementsAreInSameGroup } from \"./groups\";\n\nimport type { ExcalidrawElement } from \"./types\";\n\nexport const defaultGetElementLinkFromSelection: Exclude<\n AppProps[\"generateLinkForSelection\"],\n undefined\n> = (id, type) => {\n const url = window.location.href;\n\n try {\n const link = new URL(url);\n link.searchParams.set(ELEMENT_LINK_KEY, id);\n\n return normalizeLink(link.toString());\n } catch (error) {\n console.error(error);\n }\n\n return normalizeLink(url);\n};\n\nexport const getLinkIdAndTypeFromSelection = (\n selectedElements: ExcalidrawElement[],\n appState: AppState,\n): {\n id: string;\n type: \"element\" | \"group\";\n} | null => {\n if (\n selectedElements.length > 0 &&\n canCreateLinkFromElements(selectedElements)\n ) {\n if (selectedElements.length === 1) {\n return {\n id: selectedElements[0].id,\n type: \"element\",\n };\n }\n\n if (selectedElements.length > 1) {\n const selectedGroupId = Object.keys(appState.selectedGroupIds)[0];\n\n if (selectedGroupId) {\n return {\n id: selectedGroupId,\n type: \"group\",\n };\n }\n return {\n id: selectedElements[0].groupIds[0],\n type: \"group\",\n };\n }\n }\n\n return null;\n};\n\nexport const canCreateLinkFromElements = (\n selectedElements: ExcalidrawElement[],\n) => {\n if (selectedElements.length === 1) {\n return true;\n }\n\n if (selectedElements.length > 1 && elementsAreInSameGroup(selectedElements)) {\n return true;\n }\n\n return false;\n};\n\nexport const isElementLink = (url: string) => {\n try {\n const _url = new URL(url);\n return (\n _url.searchParams.has(ELEMENT_LINK_KEY) &&\n _url.host === window.location.host\n );\n } catch (error) {\n return false;\n }\n};\n\nexport const parseElementLinkFromURL = (url: string) => {\n try {\n const { searchParams } = new URL(url);\n if (searchParams.has(ELEMENT_LINK_KEY)) {\n const id = searchParams.get(ELEMENT_LINK_KEY);\n return id;\n }\n } catch {}\n\n return null;\n};\n", "import {\n DEFAULT_ELEMENT_PROPS,\n DEFAULT_FONT_FAMILY,\n DEFAULT_FONT_SIZE,\n DEFAULT_TEXT_ALIGN,\n DEFAULT_VERTICAL_ALIGN,\n VERTICAL_ALIGN,\n randomInteger,\n randomId,\n getFontString,\n getUpdatedTimestamp,\n getLineHeight,\n} from \"@excalidraw/common\";\n\nimport type { Radians } from \"@excalidraw/math\";\n\nimport type { MarkOptional, Merge } from \"@excalidraw/common/utility-types\";\n\nimport {\n getElementAbsoluteCoords,\n getResizedElementAbsoluteCoords,\n} from \"./bounds\";\nimport { newElementWith } from \"./mutateElement\";\nimport { getBoundTextMaxWidth } from \"./textElement\";\nimport { normalizeText, measureText } from \"./textMeasurements\";\nimport { wrapText } from \"./textWrapping\";\n\nimport { isLineElement } from \"./typeChecks\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawImageElement,\n ExcalidrawTextElement,\n ExcalidrawLinearElement,\n ExcalidrawGenericElement,\n NonDeleted,\n TextAlign,\n VerticalAlign,\n Arrowhead,\n ExcalidrawFreeDrawElement,\n FontFamilyValues,\n ExcalidrawTextContainer,\n ExcalidrawFrameElement,\n ExcalidrawEmbeddableElement,\n ExcalidrawMagicFrameElement,\n ExcalidrawIframeElement,\n ElementsMap,\n ExcalidrawArrowElement,\n ExcalidrawElbowArrowElement,\n ExcalidrawLineElement,\n} from \"./types\";\n\nexport type ElementConstructorOpts = MarkOptional<\n Omit<ExcalidrawGenericElement, \"id\" | \"type\" | \"isDeleted\" | \"updated\">,\n | \"width\"\n | \"height\"\n | \"angle\"\n | \"groupIds\"\n | \"frameId\"\n | \"index\"\n | \"boundElements\"\n | \"seed\"\n | \"version\"\n | \"versionNonce\"\n | \"link\"\n | \"strokeStyle\"\n | \"fillStyle\"\n | \"strokeColor\"\n | \"backgroundColor\"\n | \"roughness\"\n | \"strokeWidth\"\n | \"roundness\"\n | \"locked\"\n | \"opacity\"\n | \"customData\"\n>;\n\nconst _newElementBase = <T extends ExcalidrawElement>(\n type: T[\"type\"],\n {\n x,\n y,\n strokeColor = DEFAULT_ELEMENT_PROPS.strokeColor,\n backgroundColor = DEFAULT_ELEMENT_PROPS.backgroundColor,\n fillStyle = DEFAULT_ELEMENT_PROPS.fillStyle,\n strokeWidth = DEFAULT_ELEMENT_PROPS.strokeWidth,\n strokeStyle = DEFAULT_ELEMENT_PROPS.strokeStyle,\n roughness = DEFAULT_ELEMENT_PROPS.roughness,\n opacity = DEFAULT_ELEMENT_PROPS.opacity,\n width = 0,\n height = 0,\n angle = 0 as Radians,\n groupIds = [],\n frameId = null,\n index = null,\n roundness = null,\n boundElements = null,\n link = null,\n locked = DEFAULT_ELEMENT_PROPS.locked,\n ...rest\n }: ElementConstructorOpts & Omit<Partial<ExcalidrawGenericElement>, \"type\">,\n) => {\n // NOTE (mtolmacs): This is a temporary check to detect extremely large\n // element position or sizing\n if (\n x < -1e6 ||\n x > 1e6 ||\n y < -1e6 ||\n y > 1e6 ||\n width < -1e6 ||\n width > 1e6 ||\n height < -1e6 ||\n height > 1e6\n ) {\n console.error(\"New element size or position is too large\", {\n x,\n y,\n width,\n height,\n // @ts-ignore\n points: rest.points,\n });\n }\n\n // assign type to guard against excess properties\n const element: Merge<ExcalidrawGenericElement, { type: T[\"type\"] }> = {\n id: rest.id || randomId(),\n type,\n x,\n y,\n width,\n height,\n angle,\n strokeColor,\n backgroundColor,\n fillStyle,\n strokeWidth,\n strokeStyle,\n roughness,\n opacity,\n groupIds,\n frameId,\n index,\n roundness,\n seed: rest.seed ?? randomInteger(),\n version: rest.version || 1,\n versionNonce: rest.versionNonce ?? 0,\n isDeleted: false as false,\n boundElements,\n updated: getUpdatedTimestamp(),\n link,\n locked,\n customData: rest.customData,\n };\n return element;\n};\n\nexport const newElement = (\n opts: {\n type: ExcalidrawGenericElement[\"type\"];\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawGenericElement> =>\n _newElementBase<ExcalidrawGenericElement>(opts.type, opts);\n\nexport const newEmbeddableElement = (\n opts: {\n type: \"embeddable\";\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawEmbeddableElement> => {\n return _newElementBase<ExcalidrawEmbeddableElement>(\"embeddable\", opts);\n};\n\nexport const newIframeElement = (\n opts: {\n type: \"iframe\";\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawIframeElement> => {\n return {\n ..._newElementBase<ExcalidrawIframeElement>(\"iframe\", opts),\n };\n};\n\nexport const newFrameElement = (\n opts: {\n name?: string;\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawFrameElement> => {\n const frameElement = newElementWith(\n {\n ..._newElementBase<ExcalidrawFrameElement>(\"frame\", opts),\n type: \"frame\",\n name: opts?.name || null,\n },\n {},\n );\n\n return frameElement;\n};\n\nexport const newMagicFrameElement = (\n opts: {\n name?: string;\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawMagicFrameElement> => {\n const frameElement = newElementWith(\n {\n ..._newElementBase<ExcalidrawMagicFrameElement>(\"magicframe\", opts),\n type: \"magicframe\",\n name: opts?.name || null,\n },\n {},\n );\n\n return frameElement;\n};\n\n/** computes element x/y offset based on textAlign/verticalAlign */\nconst getTextElementPositionOffsets = (\n opts: {\n textAlign: ExcalidrawTextElement[\"textAlign\"];\n verticalAlign: ExcalidrawTextElement[\"verticalAlign\"];\n },\n metrics: {\n width: number;\n height: number;\n },\n) => {\n return {\n x:\n opts.textAlign === \"center\"\n ? metrics.width / 2\n : opts.textAlign === \"right\"\n ? metrics.width\n : 0,\n y: opts.verticalAlign === \"middle\" ? metrics.height / 2 : 0,\n };\n};\n\nexport const newTextElement = (\n opts: {\n text: string;\n originalText?: string;\n fontSize?: number;\n fontFamily?: FontFamilyValues;\n textAlign?: TextAlign;\n verticalAlign?: VerticalAlign;\n containerId?: ExcalidrawTextContainer[\"id\"] | null;\n lineHeight?: ExcalidrawTextElement[\"lineHeight\"];\n autoResize?: ExcalidrawTextElement[\"autoResize\"];\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawTextElement> => {\n const fontFamily = opts.fontFamily || DEFAULT_FONT_FAMILY;\n const fontSize = opts.fontSize || DEFAULT_FONT_SIZE;\n const lineHeight = opts.lineHeight || getLineHeight(fontFamily);\n const text = normalizeText(opts.text);\n const metrics = measureText(\n text,\n getFontString({ fontFamily, fontSize }),\n lineHeight,\n );\n const textAlign = opts.textAlign || DEFAULT_TEXT_ALIGN;\n const verticalAlign = opts.verticalAlign || DEFAULT_VERTICAL_ALIGN;\n const offsets = getTextElementPositionOffsets(\n { textAlign, verticalAlign },\n metrics,\n );\n\n const textElementProps: ExcalidrawTextElement = {\n ..._newElementBase<ExcalidrawTextElement>(\"text\", opts),\n text,\n fontSize,\n fontFamily,\n textAlign,\n verticalAlign,\n x: opts.x - offsets.x,\n y: opts.y - offsets.y,\n width: metrics.width,\n height: metrics.height,\n containerId: opts.containerId || null,\n originalText: opts.originalText ?? text,\n autoResize: opts.autoResize ?? true,\n lineHeight,\n };\n\n const textElement: ExcalidrawTextElement = newElementWith(\n textElementProps,\n {},\n );\n\n return textElement;\n};\n\nconst getAdjustedDimensions = (\n element: ExcalidrawTextElement,\n elementsMap: ElementsMap,\n nextText: string,\n): {\n x: number;\n y: number;\n width: number;\n height: number;\n} => {\n let { width: nextWidth, height: nextHeight } = measureText(\n nextText,\n getFontString(element),\n element.lineHeight,\n );\n\n // wrapped text\n if (!element.autoResize) {\n nextWidth = element.width;\n }\n\n const { textAlign, verticalAlign } = element;\n let x: number;\n let y: number;\n if (\n textAlign === \"center\" &&\n verticalAlign === VERTICAL_ALIGN.MIDDLE &&\n !element.containerId &&\n element.autoResize\n ) {\n const prevMetrics = measureText(\n element.text,\n getFontString(element),\n element.lineHeight,\n );\n const offsets = getTextElementPositionOffsets(element, {\n width: nextWidth - prevMetrics.width,\n height: nextHeight - prevMetrics.height,\n });\n\n x = element.x - offsets.x;\n y = element.y - offsets.y;\n } else {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n\n const [nextX1, nextY1, nextX2, nextY2] = getResizedElementAbsoluteCoords(\n element,\n nextWidth,\n nextHeight,\n false,\n );\n const deltaX1 = (x1 - nextX1) / 2;\n const deltaY1 = (y1 - nextY1) / 2;\n const deltaX2 = (x2 - nextX2) / 2;\n const deltaY2 = (y2 - nextY2) / 2;\n\n [x, y] = adjustXYWithRotation(\n {\n s: true,\n e: textAlign === \"center\" || textAlign === \"left\",\n w: textAlign === \"center\" || textAlign === \"right\",\n },\n element.x,\n element.y,\n element.angle,\n deltaX1,\n deltaY1,\n deltaX2,\n deltaY2,\n );\n }\n\n return {\n width: nextWidth,\n height: nextHeight,\n x: Number.isFinite(x) ? x : element.x,\n y: Number.isFinite(y) ? y : element.y,\n };\n};\n\nconst adjustXYWithRotation = (\n sides: {\n n?: boolean;\n e?: boolean;\n s?: boolean;\n w?: boolean;\n },\n x: number,\n y: number,\n angle: number,\n deltaX1: number,\n deltaY1: number,\n deltaX2: number,\n deltaY2: number,\n): [number, number] => {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n if (sides.e && sides.w) {\n x += deltaX1 + deltaX2;\n } else if (sides.e) {\n x += deltaX1 * (1 + cos);\n y += deltaX1 * sin;\n x += deltaX2 * (1 - cos);\n y += deltaX2 * -sin;\n } else if (sides.w) {\n x += deltaX1 * (1 - cos);\n y += deltaX1 * -sin;\n x += deltaX2 * (1 + cos);\n y += deltaX2 * sin;\n }\n\n if (sides.n && sides.s) {\n y += deltaY1 + deltaY2;\n } else if (sides.n) {\n x += deltaY1 * sin;\n y += deltaY1 * (1 - cos);\n x += deltaY2 * -sin;\n y += deltaY2 * (1 + cos);\n } else if (sides.s) {\n x += deltaY1 * -sin;\n y += deltaY1 * (1 + cos);\n x += deltaY2 * sin;\n y += deltaY2 * (1 - cos);\n }\n return [x, y];\n};\n\nexport const refreshTextDimensions = (\n textElement: ExcalidrawTextElement,\n container: ExcalidrawTextContainer | null,\n elementsMap: ElementsMap,\n text = textElement.text,\n) => {\n if (textElement.isDeleted) {\n return;\n }\n if (container || !textElement.autoResize) {\n text = wrapText(\n text,\n getFontString(textElement),\n container\n ? getBoundTextMaxWidth(container, textElement)\n : textElement.width,\n );\n }\n const dimensions = getAdjustedDimensions(textElement, elementsMap, text);\n return { text, ...dimensions };\n};\n\nexport const newFreeDrawElement = (\n opts: {\n type: \"freedraw\";\n points?: ExcalidrawFreeDrawElement[\"points\"];\n simulatePressure: boolean;\n pressures?: ExcalidrawFreeDrawElement[\"pressures\"];\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawFreeDrawElement> => {\n return {\n ..._newElementBase<ExcalidrawFreeDrawElement>(opts.type, opts),\n points: opts.points || [],\n pressures: opts.pressures || [],\n simulatePressure: opts.simulatePressure,\n };\n};\n\nexport const newLinearElement = (\n opts: {\n type: ExcalidrawLinearElement[\"type\"];\n points?: ExcalidrawLinearElement[\"points\"];\n polygon?: ExcalidrawLineElement[\"polygon\"];\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawLinearElement> => {\n const element = {\n ..._newElementBase<ExcalidrawLinearElement>(opts.type, opts),\n points: opts.points || [],\n\n startBinding: null,\n endBinding: null,\n startArrowhead: null,\n endArrowhead: null,\n };\n\n if (isLineElement(element)) {\n const lineElement: NonDeleted<ExcalidrawLineElement> = {\n ...element,\n polygon: opts.polygon ?? false,\n };\n\n return lineElement;\n }\n\n return element;\n};\n\nexport const newArrowElement = <T extends boolean>(\n opts: {\n type: ExcalidrawArrowElement[\"type\"];\n startArrowhead?: Arrowhead | null;\n endArrowhead?: Arrowhead | null;\n points?: ExcalidrawArrowElement[\"points\"];\n elbowed?: T;\n fixedSegments?: ExcalidrawElbowArrowElement[\"fixedSegments\"] | null;\n } & ElementConstructorOpts,\n): T extends true\n ? NonDeleted<ExcalidrawElbowArrowElement>\n : NonDeleted<ExcalidrawArrowElement> => {\n if (opts.elbowed) {\n return {\n ..._newElementBase<ExcalidrawElbowArrowElement>(opts.type, opts),\n points: opts.points || [],\n startBinding: null,\n endBinding: null,\n startArrowhead: opts.startArrowhead || null,\n endArrowhead: opts.endArrowhead || null,\n elbowed: true,\n fixedSegments: opts.fixedSegments || [],\n startIsSpecial: false,\n endIsSpecial: false,\n } as NonDeleted<ExcalidrawElbowArrowElement>;\n }\n\n return {\n ..._newElementBase<ExcalidrawArrowElement>(opts.type, opts),\n points: opts.points || [],\n startBinding: null,\n endBinding: null,\n startArrowhead: opts.startArrowhead || null,\n endArrowhead: opts.endArrowhead || null,\n elbowed: false,\n } as T extends true\n ? NonDeleted<ExcalidrawElbowArrowElement>\n : NonDeleted<ExcalidrawArrowElement>;\n};\n\nexport const newImageElement = (\n opts: {\n type: ExcalidrawImageElement[\"type\"];\n status?: ExcalidrawImageElement[\"status\"];\n fileId?: ExcalidrawImageElement[\"fileId\"];\n scale?: ExcalidrawImageElement[\"scale\"];\n crop?: ExcalidrawImageElement[\"crop\"];\n } & ElementConstructorOpts,\n): NonDeleted<ExcalidrawImageElement> => {\n return {\n ..._newElementBase<ExcalidrawImageElement>(\"image\", opts),\n // in the future we'll support changing stroke color for some SVG elements,\n // and `transparent` will likely mean \"use original colors of the image\"\n strokeColor: \"transparent\",\n status: opts.status ?? \"pending\",\n fileId: opts.fileId ?? null,\n scale: opts.scale ?? [1, 1],\n crop: opts.crop ?? null,\n };\n};\n", "import {\n FONT_FAMILY,\n VERTICAL_ALIGN,\n escapeDoubleQuotes,\n getFontString,\n} from \"@excalidraw/common\";\n\nimport type { ExcalidrawProps } from \"@excalidraw/excalidraw/types\";\nimport type { MarkRequired } from \"@excalidraw/common/utility-types\";\n\nimport { newTextElement } from \"./newElement\";\nimport { wrapText } from \"./textWrapping\";\nimport { isIframeElement } from \"./typeChecks\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawIframeLikeElement,\n IframeData,\n} from \"./types\";\n\ntype IframeDataWithSandbox = MarkRequired<IframeData, \"sandbox\">;\n\nconst embeddedLinkCache = new Map<string, IframeDataWithSandbox>();\n\nconst RE_YOUTUBE =\n /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?youtu(?:be\\.com|\\.be)\\/(embed\\/|watch\\?v=|shorts\\/|playlist\\?list=|embed\\/videoseries\\?list=)?([a-zA-Z0-9_-]+)/;\n\nconst RE_VIMEO =\n /^(?:http(?:s)?:\\/\\/)?(?:(?:w){3}\\.)?(?:player\\.)?vimeo\\.com\\/(?:video\\/)?([^?\\s]+)(?:\\?.*)?$/;\nconst RE_FIGMA = /^https:\\/\\/(?:www\\.)?figma\\.com/;\n\nconst RE_GH_GIST = /^https:\\/\\/gist\\.github\\.com\\/([\\w_-]+)\\/([\\w_-]+)/;\nconst RE_GH_GIST_EMBED =\n /^<script[\\s\\S]*?\\ssrc=[\"'](https:\\/\\/gist\\.github\\.com\\/.*?)\\.js[\"']/i;\n\nconst RE_MSFORMS = /^(?:https?:\\/\\/)?forms\\.microsoft\\.com\\//;\n\n// not anchored to start to allow <blockquote> twitter embeds\nconst RE_TWITTER =\n /(?:https?:\\/\\/)?(?:(?:w){3}\\.)?(?:twitter|x)\\.com\\/[^/]+\\/status\\/(\\d+)/;\nconst RE_TWITTER_EMBED =\n /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:twitter|x)\\.com\\/[^\"']*)/i;\n\nconst RE_VALTOWN =\n /^https:\\/\\/(?:www\\.)?val\\.town\\/(v|embed)\\/[a-zA-Z_$][0-9a-zA-Z_$]+\\.[a-zA-Z_$][0-9a-zA-Z_$]+/;\n\nconst RE_GENERIC_EMBED =\n /^<(?:iframe|blockquote)[\\s\\S]*?\\s(?:src|href)=[\"']([^\"']*)[\"'][\\s\\S]*?>$/i;\n\nconst RE_GIPHY =\n /giphy.com\\/(?:clips|embed|gifs)\\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;\n\nconst RE_REDDIT =\n /^(?:http(?:s)?:\\/\\/)?(?:www\\.)?reddit\\.com\\/r\\/([a-zA-Z0-9_]+)\\/comments\\/([a-zA-Z0-9_]+)\\/([a-zA-Z0-9_]+)\\/?(?:\\?[^#\\s]*)?(?:#[^\\s]*)?$/;\n\nconst RE_REDDIT_EMBED =\n /^<blockquote[\\s\\S]*?\\shref=[\"'](https?:\\/\\/(?:www\\.)?reddit\\.com\\/[^\"']*)/i;\n\nconst parseYouTubeTimestamp = (url: string): number => {\n let timeParam: string | null | undefined;\n\n try {\n const urlObj = new URL(url.startsWith(\"http\") ? url : `https://${url}`);\n timeParam =\n urlObj.searchParams.get(\"t\") || urlObj.searchParams.get(\"start\");\n } catch (error) {\n const timeMatch = url.match(/[?&#](?:t|start)=([^&#\\s]+)/);\n timeParam = timeMatch?.[1];\n }\n\n if (!timeParam) {\n return 0;\n }\n\n if (/^\\d+$/.test(timeParam)) {\n return parseInt(timeParam, 10);\n }\n\n const timeMatch = timeParam.match(/^(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/);\n if (!timeMatch) {\n return 0;\n }\n\n const [, hours = \"0\", minutes = \"0\", seconds = \"0\"] = timeMatch;\n return parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds);\n};\n\nconst ALLOWED_DOMAINS = new Set([\n \"youtube.com\",\n \"youtu.be\",\n \"vimeo.com\",\n \"player.vimeo.com\",\n \"figma.com\",\n \"link.excalidraw.com\",\n \"gist.github.com\",\n \"twitter.com\",\n \"x.com\",\n \"*.simplepdf.eu\",\n \"stackblitz.com\",\n \"val.town\",\n \"giphy.com\",\n \"reddit.com\",\n \"forms.microsoft.com\",\n]);\n\nconst ALLOW_SAME_ORIGIN = new Set([\n \"youtube.com\",\n \"youtu.be\",\n \"vimeo.com\",\n \"player.vimeo.com\",\n \"figma.com\",\n \"twitter.com\",\n \"x.com\",\n \"*.simplepdf.eu\",\n \"stackblitz.com\",\n \"reddit.com\",\n \"forms.microsoft.com\",\n]);\n\nexport const createSrcDoc = (body: string) => {\n return `<html><body>${body}</body></html>`;\n};\n\nexport const getEmbedLink = (\n link: string | null | undefined,\n): IframeDataWithSandbox | null => {\n if (!link) {\n return null;\n }\n\n if (embeddedLinkCache.has(link)) {\n return embeddedLinkCache.get(link)!;\n }\n\n const originalLink = link;\n\n const allowSameOrigin = ALLOW_SAME_ORIGIN.has(\n matchHostname(link, ALLOW_SAME_ORIGIN) || \"\",\n );\n\n let type: \"video\" | \"generic\" = \"generic\";\n let aspectRatio = { w: 560, h: 840 };\n const ytLink = link.match(RE_YOUTUBE);\n if (ytLink?.[2]) {\n const startTime = parseYouTubeTimestamp(originalLink);\n const time = startTime > 0 ? `&start=${startTime}` : ``;\n const isPortrait = link.includes(\"shorts\");\n type = \"video\";\n switch (ytLink[1]) {\n case \"embed/\":\n case \"watch?v=\":\n case \"shorts/\":\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\n break;\n case \"playlist?list=\":\n case \"embed/videoseries?list=\":\n link = `https://www.youtube.com/embed/videoseries?list=${ytLink[2]}&enablejsapi=1${time}`;\n break;\n default:\n link = `https://www.youtube.com/embed/${ytLink[2]}?enablejsapi=1${time}`;\n break;\n }\n aspectRatio = isPortrait ? { w: 315, h: 560 } : { w: 560, h: 315 };\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n };\n }\n\n const vimeoLink = link.match(RE_VIMEO);\n if (vimeoLink?.[1]) {\n const target = vimeoLink?.[1];\n const error = !/^\\d+$/.test(target)\n ? new URIError(\"Invalid embed link format\")\n : undefined;\n type = \"video\";\n link = `https://player.vimeo.com/video/${target}?api=1`;\n aspectRatio = { w: 560, h: 315 };\n //warning deliberately ommited so it is displayed only once per link\n //same link next time will be served from cache\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n error,\n sandbox: { allowSameOrigin },\n };\n }\n\n const figmaLink = link.match(RE_FIGMA);\n if (figmaLink) {\n type = \"generic\";\n link = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(\n link,\n )}`;\n aspectRatio = { w: 550, h: 550 };\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n };\n }\n\n const valLink = link.match(RE_VALTOWN);\n if (valLink) {\n link =\n valLink[1] === \"embed\" ? valLink[0] : valLink[0].replace(\"/v\", \"/embed\");\n embeddedLinkCache.set(originalLink, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n };\n }\n\n if (RE_MSFORMS.test(link) && !link.includes(\"embed=true\")) {\n link += link.includes(\"?\") ? \"&embed=true\" : \"?embed=true\";\n }\n\n if (RE_TWITTER.test(link)) {\n const postId = link.match(RE_TWITTER)![1];\n // the embed srcdoc still supports twitter.com domain only.\n // Note that we don't attempt to parse the username as it can consist of\n // non-latin1 characters, and the username in the url can be set to anything\n // without affecting the embed.\n const safeURL = escapeDoubleQuotes(\n `https://twitter.com/x/status/${postId}`,\n );\n\n const ret: IframeDataWithSandbox = {\n type: \"document\",\n srcdoc: (theme: string) =>\n createSrcDoc(\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>`,\n ),\n intrinsicSize: { w: 480, h: 480 },\n sandbox: { allowSameOrigin },\n };\n embeddedLinkCache.set(originalLink, ret);\n return ret;\n }\n\n if (RE_REDDIT.test(link)) {\n const [, page, postId, title] = link.match(RE_REDDIT)!;\n const safeURL = escapeDoubleQuotes(\n `https://reddit.com/r/${page}/comments/${postId}/${title}`,\n );\n const ret: IframeDataWithSandbox = {\n type: \"document\",\n srcdoc: (theme: string) =>\n createSrcDoc(\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>`,\n ),\n intrinsicSize: { w: 480, h: 480 },\n sandbox: { allowSameOrigin },\n };\n embeddedLinkCache.set(originalLink, ret);\n return ret;\n }\n\n if (RE_GH_GIST.test(link)) {\n const [, user, gistId] = link.match(RE_GH_GIST)!;\n const safeURL = escapeDoubleQuotes(\n `https://gist.github.com/${user}/${gistId}`,\n );\n const ret: IframeDataWithSandbox = {\n type: \"document\",\n srcdoc: () =>\n createSrcDoc(`\n <script src=\"${safeURL}.js\"></script>\n <style type=\"text/css\">\n * { margin: 0px; }\n table, .gist { height: 100%; }\n .gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n </style>\n `),\n intrinsicSize: { w: 550, h: 720 },\n sandbox: { allowSameOrigin },\n };\n embeddedLinkCache.set(link, ret);\n return ret;\n }\n\n embeddedLinkCache.set(link, {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n });\n return {\n link,\n intrinsicSize: aspectRatio,\n type,\n sandbox: { allowSameOrigin },\n };\n};\n\nexport const createPlaceholderEmbeddableLabel = (\n element: ExcalidrawIframeLikeElement,\n): ExcalidrawElement => {\n let text: string;\n if (isIframeElement(element)) {\n text = \"IFrame element\";\n } else {\n text =\n !element.link || element?.link === \"\" ? \"Empty Web-Embed\" : element.link;\n }\n\n const fontSize = Math.max(\n Math.min(element.width / 2, element.width / text.length),\n element.width / 30,\n );\n const fontFamily = FONT_FAMILY.Helvetica;\n\n const fontString = getFontString({\n fontSize,\n fontFamily,\n });\n\n return newTextElement({\n x: element.x + element.width / 2,\n y: element.y + element.height / 2,\n strokeColor:\n element.strokeColor !== \"transparent\" ? element.strokeColor : \"black\",\n backgroundColor: \"transparent\",\n fontFamily,\n fontSize,\n text: wrapText(text, fontString, element.width - 20),\n textAlign: \"center\",\n verticalAlign: VERTICAL_ALIGN.MIDDLE,\n angle: element.angle ?? 0,\n });\n};\n\nconst matchHostname = (\n url: string,\n /** using a Set assumes it already contains normalized bare domains */\n allowedHostnames: Set<string> | string,\n): string | null => {\n try {\n const { hostname } = new URL(url);\n\n const bareDomain = hostname.replace(/^www\\./, \"\");\n\n if (allowedHostnames instanceof Set) {\n if (ALLOWED_DOMAINS.has(bareDomain)) {\n return bareDomain;\n }\n\n const bareDomainWithFirstSubdomainWildcarded = bareDomain.replace(\n /^([^.]+)/,\n \"*\",\n );\n if (ALLOWED_DOMAINS.has(bareDomainWithFirstSubdomainWildcarded)) {\n return bareDomainWithFirstSubdomainWildcarded;\n }\n return null;\n }\n\n const bareAllowedHostname = allowedHostnames.replace(/^www\\./, \"\");\n if (bareDomain === bareAllowedHostname) {\n return bareAllowedHostname;\n }\n } catch (error) {\n // ignore\n }\n return null;\n};\n\nexport const maybeParseEmbedSrc = (str: string): string => {\n const twitterMatch = str.match(RE_TWITTER_EMBED);\n if (twitterMatch && twitterMatch.length === 2) {\n return twitterMatch[1];\n }\n\n const redditMatch = str.match(RE_REDDIT_EMBED);\n if (redditMatch && redditMatch.length === 2) {\n return redditMatch[1];\n }\n\n const gistMatch = str.match(RE_GH_GIST_EMBED);\n if (gistMatch && gistMatch.length === 2) {\n return gistMatch[1];\n }\n\n if (RE_GIPHY.test(str)) {\n return `https://giphy.com/embed/${RE_GIPHY.exec(str)![1]}`;\n }\n\n const match = str.match(RE_GENERIC_EMBED);\n if (match && match.length === 2) {\n return match[1];\n }\n\n return str;\n};\n\nexport const embeddableURLValidator = (\n url: string | null | undefined,\n validateEmbeddable: ExcalidrawProps[\"validateEmbeddable\"],\n): boolean => {\n if (!url) {\n return false;\n }\n if (validateEmbeddable != null) {\n if (typeof validateEmbeddable === \"function\") {\n const ret = validateEmbeddable(url);\n // if return value is undefined, leave validation to default\n if (typeof ret === \"boolean\") {\n return ret;\n }\n } else if (typeof validateEmbeddable === \"boolean\") {\n return validateEmbeddable;\n } else if (validateEmbeddable instanceof RegExp) {\n return validateEmbeddable.test(url);\n } else if (Array.isArray(validateEmbeddable)) {\n for (const domain of validateEmbeddable) {\n if (domain instanceof RegExp) {\n if (url.match(domain)) {\n return true;\n }\n } else if (matchHostname(url, domain)) {\n return true;\n }\n }\n return false;\n }\n }\n\n return !!matchHostname(url, ALLOWED_DOMAINS);\n};\n", "import { KEYS, invariant, toBrandedType } from \"@excalidraw/common\";\n\nimport { type GlobalPoint, pointFrom, type LocalPoint } from \"@excalidraw/math\";\n\nimport type {\n AppState,\n PendingExcalidrawElements,\n} from \"@excalidraw/excalidraw/types\";\n\nimport { bindBindingElement } from \"./binding\";\nimport { updateElbowArrowPoints } from \"./elbowArrow\";\nimport {\n HEADING_DOWN,\n HEADING_LEFT,\n HEADING_RIGHT,\n HEADING_UP,\n compareHeading,\n headingForPointFromElement,\n type Heading,\n} from \"./heading\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport { mutateElement } from \"./mutateElement\";\nimport { newArrowElement, newElement } from \"./newElement\";\nimport { aabbForElement } from \"./bounds\";\nimport { elementsAreInFrameBounds, elementOverlapsWithFrame } from \"./frame\";\nimport {\n isBindableElement,\n isElbowArrow,\n isFrameElement,\n isFlowchartNodeElement,\n} from \"./typeChecks\";\nimport {\n type ElementsMap,\n type ExcalidrawBindableElement,\n type ExcalidrawElement,\n type ExcalidrawFlowchartNodeElement,\n type NonDeletedSceneElementsMap,\n type Ordered,\n type OrderedExcalidrawElement,\n} from \"./types\";\n\nimport type { Scene } from \"./Scene\";\n\ntype LinkDirection = \"up\" | \"right\" | \"down\" | \"left\";\n\nconst VERTICAL_OFFSET = 100;\nconst HORIZONTAL_OFFSET = 100;\n\nexport const getLinkDirectionFromKey = (key: string): LinkDirection => {\n switch (key) {\n case KEYS.ARROW_UP:\n return \"up\";\n case KEYS.ARROW_DOWN:\n return \"down\";\n case KEYS.ARROW_RIGHT:\n return \"right\";\n case KEYS.ARROW_LEFT:\n return \"left\";\n default:\n return \"right\";\n }\n};\n\nconst getNodeRelatives = (\n type: \"predecessors\" | \"successors\",\n node: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n direction: LinkDirection,\n) => {\n const items = [...elementsMap.values()].reduce(\n (acc: { relative: ExcalidrawBindableElement; heading: Heading }[], el) => {\n let oppositeBinding;\n if (\n isElbowArrow(el) &&\n // we want check existence of the opposite binding, in the direction\n // we're interested in\n (oppositeBinding =\n el[type === \"predecessors\" ? \"startBinding\" : \"endBinding\"]) &&\n // similarly, we need to filter only arrows bound to target node\n el[type === \"predecessors\" ? \"endBinding\" : \"startBinding\"]\n ?.elementId === node.id\n ) {\n const relative = elementsMap.get(oppositeBinding.elementId);\n\n if (!relative) {\n return acc;\n }\n\n invariant(\n isBindableElement(relative),\n \"not an ExcalidrawBindableElement\",\n );\n\n const edgePoint = (\n type === \"predecessors\" ? el.points[el.points.length - 1] : [0, 0]\n ) as Readonly<LocalPoint>;\n\n const heading = headingForPointFromElement(\n node,\n aabbForElement(node, elementsMap),\n [edgePoint[0] + el.x, edgePoint[1] + el.y] as Readonly<GlobalPoint>,\n );\n\n acc.push({\n relative,\n heading,\n });\n }\n return acc;\n },\n [],\n );\n\n switch (direction) {\n case \"up\":\n return items\n .filter((item) => compareHeading(item.heading, HEADING_UP))\n .map((item) => item.relative);\n case \"down\":\n return items\n .filter((item) => compareHeading(item.heading, HEADING_DOWN))\n .map((item) => item.relative);\n case \"right\":\n return items\n .filter((item) => compareHeading(item.heading, HEADING_RIGHT))\n .map((item) => item.relative);\n case \"left\":\n return items\n .filter((item) => compareHeading(item.heading, HEADING_LEFT))\n .map((item) => item.relative);\n }\n};\n\nconst getSuccessors = (\n node: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n direction: LinkDirection,\n) => {\n return getNodeRelatives(\"successors\", node, elementsMap, direction);\n};\n\nexport const getPredecessors = (\n node: ExcalidrawBindableElement,\n elementsMap: ElementsMap,\n direction: LinkDirection,\n) => {\n return getNodeRelatives(\"predecessors\", node, elementsMap, direction);\n};\n\nconst getOffsets = (\n element: ExcalidrawFlowchartNodeElement,\n linkedNodes: ExcalidrawElement[],\n direction: LinkDirection,\n) => {\n const _HORIZONTAL_OFFSET = HORIZONTAL_OFFSET + element.width;\n\n // check if vertical space or horizontal space is available first\n if (direction === \"up\" || direction === \"down\") {\n const _VERTICAL_OFFSET = VERTICAL_OFFSET + element.height;\n // check vertical space\n const minX = element.x;\n const maxX = element.x + element.width;\n\n // vertical space is available\n if (\n linkedNodes.every(\n (linkedNode) =>\n linkedNode.x + linkedNode.width < minX || linkedNode.x > maxX,\n )\n ) {\n return {\n x: 0,\n y: _VERTICAL_OFFSET * (direction === \"up\" ? -1 : 1),\n };\n }\n } else if (direction === \"right\" || direction === \"left\") {\n const minY = element.y;\n const maxY = element.y + element.height;\n\n if (\n linkedNodes.every(\n (linkedNode) =>\n linkedNode.y + linkedNode.height < minY || linkedNode.y > maxY,\n )\n ) {\n return {\n x:\n (HORIZONTAL_OFFSET + element.width) * (direction === \"left\" ? -1 : 1),\n y: 0,\n };\n }\n }\n\n if (direction === \"up\" || direction === \"down\") {\n const _VERTICAL_OFFSET = VERTICAL_OFFSET + element.height;\n const y = linkedNodes.length === 0 ? _VERTICAL_OFFSET : _VERTICAL_OFFSET;\n const x =\n linkedNodes.length === 0\n ? 0\n : (linkedNodes.length + 1) % 2 === 0\n ? ((linkedNodes.length + 1) / 2) * _HORIZONTAL_OFFSET\n : (linkedNodes.length / 2) * _HORIZONTAL_OFFSET * -1;\n\n if (direction === \"up\") {\n return {\n x,\n y: y * -1,\n };\n }\n\n return {\n x,\n y,\n };\n }\n\n const _VERTICAL_OFFSET = VERTICAL_OFFSET + element.height;\n const x =\n (linkedNodes.length === 0 ? HORIZONTAL_OFFSET : HORIZONTAL_OFFSET) +\n element.width;\n const y =\n linkedNodes.length === 0\n ? 0\n : (linkedNodes.length + 1) % 2 === 0\n ? ((linkedNodes.length + 1) / 2) * _VERTICAL_OFFSET\n : (linkedNodes.length / 2) * _VERTICAL_OFFSET * -1;\n\n if (direction === \"left\") {\n return {\n x: x * -1,\n y,\n };\n }\n return {\n x,\n y,\n };\n};\n\nconst addNewNode = (\n element: ExcalidrawFlowchartNodeElement,\n appState: AppState,\n direction: LinkDirection,\n scene: Scene,\n) => {\n const elementsMap = scene.getNonDeletedElementsMap();\n const successors = getSuccessors(element, elementsMap, direction);\n const predeccessors = getPredecessors(element, elementsMap, direction);\n\n const offsets = getOffsets(\n element,\n [...successors, ...predeccessors],\n direction,\n );\n\n const nextNode = newElement({\n type: element.type,\n x: element.x + offsets.x,\n y: element.y + offsets.y,\n // TODO: extract this to a util\n width: element.width,\n height: element.height,\n roundness: element.roundness,\n roughness: element.roughness,\n backgroundColor: element.backgroundColor,\n strokeColor: element.strokeColor,\n strokeWidth: element.strokeWidth,\n opacity: element.opacity,\n fillStyle: element.fillStyle,\n strokeStyle: element.strokeStyle,\n });\n\n invariant(\n isFlowchartNodeElement(nextNode),\n \"not an ExcalidrawFlowchartNodeElement\",\n );\n\n const bindingArrow = createBindingArrow(\n element,\n nextNode,\n direction,\n appState,\n scene,\n );\n\n return {\n nextNode,\n bindingArrow,\n };\n};\n\nexport const addNewNodes = (\n startNode: ExcalidrawFlowchartNodeElement,\n appState: AppState,\n direction: LinkDirection,\n scene: Scene,\n numberOfNodes: number,\n) => {\n // always start from 0 and distribute evenly\n const newNodes: ExcalidrawElement[] = [];\n\n for (let i = 0; i < numberOfNodes; i++) {\n let nextX: number;\n let nextY: number;\n if (direction === \"left\" || direction === \"right\") {\n const totalHeight =\n VERTICAL_OFFSET * (numberOfNodes - 1) +\n numberOfNodes * startNode.height;\n\n const startY = startNode.y + startNode.height / 2 - totalHeight / 2;\n\n let offsetX = HORIZONTAL_OFFSET + startNode.width;\n if (direction === \"left\") {\n offsetX *= -1;\n }\n nextX = startNode.x + offsetX;\n const offsetY = (VERTICAL_OFFSET + startNode.height) * i;\n nextY = startY + offsetY;\n } else {\n const totalWidth =\n HORIZONTAL_OFFSET * (numberOfNodes - 1) +\n numberOfNodes * startNode.width;\n const startX = startNode.x + startNode.width / 2 - totalWidth / 2;\n let offsetY = VERTICAL_OFFSET + startNode.height;\n\n if (direction === \"up\") {\n offsetY *= -1;\n }\n nextY = startNode.y + offsetY;\n const offsetX = (HORIZONTAL_OFFSET + startNode.width) * i;\n nextX = startX + offsetX;\n }\n\n const nextNode = newElement({\n type: startNode.type,\n x: nextX,\n y: nextY,\n // TODO: extract this to a util\n width: startNode.width,\n height: startNode.height,\n roundness: startNode.roundness,\n roughness: startNode.roughness,\n backgroundColor: startNode.backgroundColor,\n strokeColor: startNode.strokeColor,\n strokeWidth: startNode.strokeWidth,\n opacity: startNode.opacity,\n fillStyle: startNode.fillStyle,\n strokeStyle: startNode.strokeStyle,\n });\n\n invariant(\n isFlowchartNodeElement(nextNode),\n \"not an ExcalidrawFlowchartNodeElement\",\n );\n\n const bindingArrow = createBindingArrow(\n startNode,\n nextNode,\n direction,\n appState,\n scene,\n );\n\n newNodes.push(nextNode);\n newNodes.push(bindingArrow);\n }\n\n return newNodes;\n};\n\nconst createBindingArrow = (\n startBindingElement: ExcalidrawFlowchartNodeElement,\n endBindingElement: ExcalidrawFlowchartNodeElement,\n direction: LinkDirection,\n appState: AppState,\n scene: Scene,\n) => {\n let startX: number;\n let startY: number;\n\n const PADDING = 6;\n\n switch (direction) {\n case \"up\": {\n startX = startBindingElement.x + startBindingElement.width / 2;\n startY = startBindingElement.y - PADDING;\n break;\n }\n case \"down\": {\n startX = startBindingElement.x + startBindingElement.width / 2;\n startY = startBindingElement.y + startBindingElement.height + PADDING;\n break;\n }\n case \"right\": {\n startX = startBindingElement.x + startBindingElement.width + PADDING;\n startY = startBindingElement.y + startBindingElement.height / 2;\n break;\n }\n case \"left\": {\n startX = startBindingElement.x - PADDING;\n startY = startBindingElement.y + startBindingElement.height / 2;\n break;\n }\n }\n\n let endX: number;\n let endY: number;\n\n switch (direction) {\n case \"up\": {\n endX = endBindingElement.x + endBindingElement.width / 2 - startX;\n endY = endBindingElement.y + endBindingElement.height - startY + PADDING;\n break;\n }\n case \"down\": {\n endX = endBindingElement.x + endBindingElement.width / 2 - startX;\n endY = endBindingElement.y - startY - PADDING;\n break;\n }\n case \"right\": {\n endX = endBindingElement.x - startX - PADDING;\n endY = endBindingElement.y - startY + endBindingElement.height / 2;\n break;\n }\n case \"left\": {\n endX = endBindingElement.x + endBindingElement.width - startX + PADDING;\n endY = endBindingElement.y - startY + endBindingElement.height / 2;\n break;\n }\n }\n\n const bindingArrow = newArrowElement({\n type: \"arrow\",\n x: startX,\n y: startY,\n startArrowhead: null,\n endArrowhead: appState.currentItemEndArrowhead,\n strokeColor: startBindingElement.strokeColor,\n strokeStyle: startBindingElement.strokeStyle,\n strokeWidth: startBindingElement.strokeWidth,\n opacity: startBindingElement.opacity,\n roughness: startBindingElement.roughness,\n points: [pointFrom(0, 0), pointFrom(endX, endY)],\n elbowed: true,\n });\n\n const elementsMap = scene.getNonDeletedElementsMap();\n\n bindBindingElement(\n bindingArrow,\n startBindingElement,\n \"orbit\",\n \"start\",\n scene,\n );\n bindBindingElement(bindingArrow, endBindingElement, \"orbit\", \"end\", scene);\n\n const changedElements = new Map<string, OrderedExcalidrawElement>();\n changedElements.set(\n startBindingElement.id,\n startBindingElement as OrderedExcalidrawElement,\n );\n changedElements.set(\n endBindingElement.id,\n endBindingElement as OrderedExcalidrawElement,\n );\n changedElements.set(\n bindingArrow.id,\n bindingArrow as OrderedExcalidrawElement,\n );\n\n LinearElementEditor.movePoints(\n bindingArrow,\n scene,\n new Map([\n [\n 1,\n {\n point: bindingArrow.points[1],\n },\n ],\n ]),\n );\n\n const update = updateElbowArrowPoints(\n bindingArrow,\n toBrandedType<NonDeletedSceneElementsMap>(\n new Map([\n ...elementsMap.entries(),\n [startBindingElement.id, startBindingElement],\n [endBindingElement.id, endBindingElement],\n [bindingArrow.id, bindingArrow],\n ] as [string, Ordered<ExcalidrawElement>][]),\n ),\n { points: bindingArrow.points },\n );\n\n return {\n ...bindingArrow,\n ...update,\n };\n};\n\nexport class FlowChartNavigator {\n isExploring: boolean = false;\n // nodes that are ONE link away (successor and predecessor both included)\n private sameLevelNodes: ExcalidrawElement[] = [];\n private sameLevelIndex: number = 0;\n // set it to the opposite of the defalut creation direction\n private direction: LinkDirection | null = null;\n // for speedier navigation\n private visitedNodes: Set<ExcalidrawElement[\"id\"]> = new Set();\n\n clear() {\n this.isExploring = false;\n this.sameLevelNodes = [];\n this.sameLevelIndex = 0;\n this.direction = null;\n this.visitedNodes.clear();\n }\n\n exploreByDirection(\n element: ExcalidrawElement,\n elementsMap: ElementsMap,\n direction: LinkDirection,\n ): ExcalidrawElement[\"id\"] | null {\n if (!isBindableElement(element)) {\n return null;\n }\n\n // clear if going at a different direction\n if (direction !== this.direction) {\n this.clear();\n }\n\n // add the current node to the visited\n if (!this.visitedNodes.has(element.id)) {\n this.visitedNodes.add(element.id);\n }\n\n /**\n * CASE:\n * - already started exploring, AND\n * - there are multiple nodes at the same level, AND\n * - still going at the same direction, AND\n *\n * RESULT:\n * - loop through nodes at the same level\n *\n * WHY:\n * - provides user the capability to loop through nodes at the same level\n */\n if (\n this.isExploring &&\n direction === this.direction &&\n this.sameLevelNodes.length > 1\n ) {\n this.sameLevelIndex =\n (this.sameLevelIndex + 1) % this.sameLevelNodes.length;\n\n return this.sameLevelNodes[this.sameLevelIndex].id;\n }\n\n const nodes = [\n ...getSuccessors(element, elementsMap, direction),\n ...getPredecessors(element, elementsMap, direction),\n ];\n\n /**\n * CASE:\n * - just started exploring at the given direction\n *\n * RESULT:\n * - go to the first node in the given direction\n */\n if (nodes.length > 0) {\n this.sameLevelIndex = 0;\n this.isExploring = true;\n this.sameLevelNodes = nodes;\n this.direction = direction;\n this.visitedNodes.add(nodes[0].id);\n\n return nodes[0].id;\n }\n\n /**\n * CASE:\n * - (just started exploring or still going at the same direction) OR\n * - there're no nodes at the given direction\n *\n * RESULT:\n * - go to some other unvisited linked node\n *\n * WHY:\n * - provide a speedier navigation from a given node to some predecessor\n * without the user having to change arrow key\n */\n if (direction === this.direction || !this.isExploring) {\n if (!this.isExploring) {\n // just started and no other nodes at the given direction\n // so the current node is technically the first visited node\n // (this is needed so that we don't get stuck between looping through )\n this.visitedNodes.add(element.id);\n }\n\n const otherDirections: LinkDirection[] = [\n \"up\",\n \"right\",\n \"down\",\n \"left\",\n ].filter((dir): dir is LinkDirection => dir !== direction);\n\n const otherLinkedNodes = otherDirections\n .map((dir) => [\n ...getSuccessors(element, elementsMap, dir),\n ...getPredecessors(element, elementsMap, dir),\n ])\n .flat()\n .filter((linkedNode) => !this.visitedNodes.has(linkedNode.id));\n\n for (const linkedNode of otherLinkedNodes) {\n if (!this.visitedNodes.has(linkedNode.id)) {\n this.visitedNodes.add(linkedNode.id);\n this.isExploring = true;\n this.direction = direction;\n return linkedNode.id;\n }\n }\n }\n\n return null;\n }\n}\n\nexport class FlowChartCreator {\n isCreatingChart: boolean = false;\n private numberOfNodes: number = 0;\n private direction: LinkDirection | null = \"right\";\n pendingNodes: PendingExcalidrawElements | null = null;\n\n createNodes(\n startNode: ExcalidrawFlowchartNodeElement,\n appState: AppState,\n direction: LinkDirection,\n scene: Scene,\n ) {\n const elementsMap = scene.getNonDeletedElementsMap();\n if (direction !== this.direction) {\n const { nextNode, bindingArrow } = addNewNode(\n startNode,\n appState,\n direction,\n scene,\n );\n\n this.numberOfNodes = 1;\n this.isCreatingChart = true;\n this.direction = direction;\n this.pendingNodes = [nextNode, bindingArrow];\n } else {\n this.numberOfNodes += 1;\n const newNodes = addNewNodes(\n startNode,\n appState,\n direction,\n scene,\n this.numberOfNodes,\n );\n\n this.isCreatingChart = true;\n this.direction = direction;\n this.pendingNodes = newNodes;\n }\n\n // add pending nodes to the same frame as the start node\n // if every pending node is at least intersecting with the frame\n if (startNode.frameId) {\n const frame = elementsMap.get(startNode.frameId);\n\n invariant(\n frame && isFrameElement(frame),\n \"not an ExcalidrawFrameElement\",\n );\n\n if (\n frame &&\n this.pendingNodes.every(\n (node) =>\n elementsAreInFrameBounds([node], frame, elementsMap) ||\n elementOverlapsWithFrame(node, frame, elementsMap),\n )\n ) {\n this.pendingNodes = this.pendingNodes.map((node) =>\n mutateElement(node, elementsMap, {\n frameId: startNode.frameId,\n }),\n );\n }\n }\n }\n\n clear() {\n this.isCreatingChart = false;\n this.pendingNodes = null;\n this.direction = null;\n this.numberOfNodes = 0;\n }\n}\n\nexport const isNodeInFlowchart = (\n element: ExcalidrawFlowchartNodeElement,\n elementsMap: ElementsMap,\n) => {\n for (const [, el] of elementsMap) {\n if (\n el.type === \"arrow\" &&\n (el.startBinding?.elementId === element.id ||\n el.endBinding?.elementId === element.id)\n ) {\n return true;\n }\n }\n\n return false;\n};\n", "// -----------------------------------------------------------------------------\n// ExcalidrawImageElement & related helpers\n// -----------------------------------------------------------------------------\n\nimport { MIME_TYPES, SVG_NS } from \"@excalidraw/common\";\n\nimport type {\n AppClassProperties,\n DataURL,\n BinaryFiles,\n} from \"@excalidraw/excalidraw/types\";\n\nimport { isInitializedImageElement } from \"./typeChecks\";\n\nimport type {\n ExcalidrawElement,\n FileId,\n InitializedExcalidrawImageElement,\n} from \"./types\";\n\nexport const loadHTMLImageElement = (dataURL: DataURL) => {\n return new Promise<HTMLImageElement>((resolve, reject) => {\n const image = new Image();\n image.onload = () => {\n resolve(image);\n };\n image.onerror = (error) => {\n reject(error);\n };\n image.src = dataURL;\n });\n};\n\n/** NOTE: updates cache even if already populated with given image. Thus,\n * you should filter out the images upstream if you want to optimize this. */\nexport const updateImageCache = async ({\n fileIds,\n files,\n imageCache,\n}: {\n fileIds: FileId[];\n files: BinaryFiles;\n imageCache: AppClassProperties[\"imageCache\"];\n}) => {\n const updatedFiles = new Map<FileId, true>();\n const erroredFiles = new Map<FileId, true>();\n\n await Promise.all(\n fileIds.reduce((promises, fileId) => {\n const fileData = files[fileId as string];\n if (fileData && !updatedFiles.has(fileId)) {\n updatedFiles.set(fileId, true);\n return promises.concat(\n (async () => {\n try {\n if (fileData.mimeType === MIME_TYPES.binary) {\n throw new Error(\"Only images can be added to ImageCache\");\n }\n\n const imagePromise = loadHTMLImageElement(fileData.dataURL);\n const data = {\n image: imagePromise,\n mimeType: fileData.mimeType,\n } as const;\n // store the promise immediately to indicate there's an in-progress\n // initialization\n imageCache.set(fileId, data);\n\n const image = await imagePromise;\n\n imageCache.set(fileId, { ...data, image });\n } catch (error: any) {\n erroredFiles.set(fileId, true);\n }\n })(),\n );\n }\n return promises;\n }, [] as Promise<any>[]),\n );\n\n return {\n imageCache,\n /** includes errored files because they cache was updated nonetheless */\n updatedFiles,\n /** files that failed when creating HTMLImageElement */\n erroredFiles,\n };\n};\n\nexport const getInitializedImageElements = (\n elements: readonly ExcalidrawElement[],\n) =>\n elements.filter((element) =>\n isInitializedImageElement(element),\n ) as InitializedExcalidrawImageElement[];\n\nexport const isHTMLSVGElement = (node: Node | null): node is SVGElement => {\n // lower-casing due to XML/HTML convention differences\n // https://johnresig.com/blog/nodename-case-sensitivity\n return node?.nodeName.toLowerCase() === \"svg\";\n};\n\nexport const normalizeSVG = (SVGString: string) => {\n const doc = new DOMParser().parseFromString(SVGString, MIME_TYPES.svg);\n const svg = doc.querySelector(\"svg\");\n const errorNode = doc.querySelector(\"parsererror\");\n if (errorNode || !isHTMLSVGElement(svg)) {\n throw new Error(\"Invalid SVG\");\n } else {\n if (!svg.hasAttribute(\"xmlns\")) {\n svg.setAttribute(\"xmlns\", SVG_NS);\n }\n\n let width = svg.getAttribute(\"width\");\n let height = svg.getAttribute(\"height\");\n\n // Do not use % or auto values for width/height\n // to avoid scaling issues when rendering at different sizes/zoom levels\n if (width?.includes(\"%\") || width === \"auto\") {\n width = null;\n }\n if (height?.includes(\"%\") || height === \"auto\") {\n height = null;\n }\n\n const viewBox = svg.getAttribute(\"viewBox\");\n\n if (!width || !height) {\n width = width || \"50\";\n height = height || \"50\";\n\n if (viewBox) {\n const match = viewBox.match(\n /\\d+ +\\d+ +(\\d+(?:\\.\\d+)?) +(\\d+(?:\\.\\d+)?)/,\n );\n if (match) {\n [, width, height] = match;\n }\n }\n\n svg.setAttribute(\"width\", width);\n svg.setAttribute(\"height\", height);\n }\n\n // Make sure viewBox is set\n if (!viewBox) {\n svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n }\n\n return svg.outerHTML;\n }\n};\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 {\n pointCenter,\n normalizeRadians,\n pointFrom,\n pointRotateRads,\n type Radians,\n type LocalPoint,\n} from \"@excalidraw/math\";\n\nimport {\n MIN_FONT_SIZE,\n SHIFT_LOCKING_ANGLE,\n rescalePoints,\n getFontString,\n} from \"@excalidraw/common\";\n\nimport type { GlobalPoint } from \"@excalidraw/math\";\n\nimport type { PointerDownState } from \"@excalidraw/excalidraw/types\";\n\nimport type { Mutable } from \"@excalidraw/common/utility-types\";\n\nimport {\n getArrowLocalFixedPoints,\n unbindBindingElement,\n updateBoundElements,\n} from \"./binding\";\nimport {\n getElementAbsoluteCoords,\n getCommonBounds,\n getResizedElementAbsoluteCoords,\n getCommonBoundingBox,\n getElementBounds,\n} from \"./bounds\";\nimport { LinearElementEditor } from \"./linearElementEditor\";\nimport {\n getBoundTextElement,\n getBoundTextElementId,\n getContainerElement,\n handleBindTextResize,\n getBoundTextMaxWidth,\n computeBoundTextPosition,\n} from \"./textElement\";\nimport {\n getMinTextElementWidth,\n measureText,\n getApproxMinLineWidth,\n getApproxMinLineHeight,\n} from \"./textMeasurements\";\nimport { wrapText } from \"./textWrapping\";\nimport {\n isArrowElement,\n isBindingElement,\n isBoundToContainer,\n isElbowArrow,\n isFrameLikeElement,\n isFreeDrawElement,\n isImageElement,\n isLinearElement,\n isTextElement,\n} from \"./typeChecks\";\n\nimport { isInGroup } from \"./groups\";\n\nimport type { Scene } from \"./Scene\";\n\nimport type { BoundingBox } from \"./bounds\";\nimport type {\n MaybeTransformHandleType,\n TransformHandleDirection,\n} from \"./transformHandles\";\nimport type {\n ExcalidrawLinearElement,\n ExcalidrawTextElement,\n NonDeletedExcalidrawElement,\n NonDeleted,\n ExcalidrawElement,\n ExcalidrawTextElementWithContainer,\n ExcalidrawImageElement,\n ElementsMap,\n ExcalidrawElbowArrowElement,\n ExcalidrawArrowElement,\n} from \"./types\";\nimport type { ElementUpdate } from \"./mutateElement\";\n\n// Returns true when transform (resizing/rotation) happened\nexport const transformElements = (\n originalElements: PointerDownState[\"originalElements\"],\n transformHandleType: MaybeTransformHandleType,\n selectedElements: readonly NonDeletedExcalidrawElement[],\n scene: Scene,\n shouldRotateWithDiscreteAngle: boolean,\n shouldResizeFromCenter: boolean,\n shouldMaintainAspectRatio: boolean,\n pointerX: number,\n pointerY: number,\n centerX: number,\n centerY: number,\n): boolean => {\n const elementsMap = scene.getNonDeletedElementsMap();\n if (selectedElements.length === 1) {\n const [element] = selectedElements;\n if (transformHandleType === \"rotation\") {\n if (!isElbowArrow(element)) {\n rotateSingleElement(\n element,\n scene,\n pointerX,\n pointerY,\n shouldRotateWithDiscreteAngle,\n );\n updateBoundElements(element, scene);\n }\n } else if (transformHandleType) {\n const elementId = selectedElements[0].id;\n const latestElement = elementsMap.get(elementId);\n const origElement = originalElements.get(elementId);\n\n if (latestElement && origElement) {\n const { nextWidth, nextHeight } =\n getNextSingleWidthAndHeightFromPointer(\n latestElement,\n origElement,\n transformHandleType,\n pointerX,\n pointerY,\n {\n shouldMaintainAspectRatio,\n shouldResizeFromCenter,\n },\n );\n\n resizeSingleElement(\n nextWidth,\n nextHeight,\n latestElement,\n origElement,\n originalElements,\n scene,\n transformHandleType,\n {\n shouldMaintainAspectRatio,\n shouldResizeFromCenter,\n },\n );\n }\n }\n if (isTextElement(element)) {\n updateBoundElements(element, scene);\n }\n return true;\n } else if (selectedElements.length > 1) {\n if (transformHandleType === \"rotation\") {\n rotateMultipleElements(\n originalElements,\n selectedElements,\n scene,\n pointerX,\n pointerY,\n shouldRotateWithDiscreteAngle,\n centerX,\n centerY,\n );\n return true;\n } else if (transformHandleType) {\n const { nextWidth, nextHeight, flipByX, flipByY, originalBoundingBox } =\n getNextMultipleWidthAndHeightFromPointer(\n selectedElements,\n originalElements,\n elementsMap,\n transformHandleType,\n pointerX,\n pointerY,\n {\n shouldMaintainAspectRatio,\n shouldResizeFromCenter,\n },\n );\n\n resizeMultipleElements(\n selectedElements,\n elementsMap,\n transformHandleType,\n scene,\n originalElements,\n {\n shouldResizeFromCenter,\n shouldMaintainAspectRatio,\n flipByX,\n flipByY,\n nextWidth,\n nextHeight,\n originalBoundingBox,\n },\n );\n\n return true;\n }\n }\n return false;\n};\n\nconst rotateSingleElement = (\n element: NonDeletedExcalidrawElement,\n scene: Scene,\n pointerX: number,\n pointerY: number,\n shouldRotateWithDiscreteAngle: boolean,\n) => {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(\n element,\n scene.getNonDeletedElementsMap(),\n );\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n let angle: Radians;\n if (isFrameLikeElement(element)) {\n angle = 0 as Radians;\n } else {\n angle = ((5 * Math.PI) / 2 +\n Math.atan2(pointerY - cy, pointerX - cx)) as Radians;\n if (shouldRotateWithDiscreteAngle) {\n angle = (angle + SHIFT_LOCKING_ANGLE / 2) as Radians;\n angle = (angle - (angle % SHIFT_LOCKING_ANGLE)) as Radians;\n }\n angle = normalizeRadians(angle as Radians);\n }\n const boundTextElementId = getBoundTextElementId(element);\n\n let update: ElementUpdate<NonDeletedExcalidrawElement> = {\n angle,\n };\n\n if (isBindingElement(element)) {\n update = {\n ...update,\n } as ElementUpdate<ExcalidrawArrowElement>;\n\n if (element.startBinding) {\n unbindBindingElement(element, \"start\", scene);\n }\n if (element.endBinding) {\n unbindBindingElement(element, \"end\", scene);\n }\n }\n\n scene.mutateElement(element, update);\n\n if (boundTextElementId) {\n const textElement =\n scene.getElement<ExcalidrawTextElementWithContainer>(boundTextElementId);\n\n if (textElement && !isArrowElement(element)) {\n const { x, y } = computeBoundTextPosition(\n element,\n textElement,\n scene.getNonDeletedElementsMap(),\n );\n scene.mutateElement(textElement, {\n angle,\n x,\n y,\n });\n }\n }\n};\n\nexport const rescalePointsInElement = (\n element: NonDeletedExcalidrawElement,\n width: number,\n height: number,\n normalizePoints: boolean,\n) =>\n isLinearElement(element) || isFreeDrawElement(element)\n ? {\n points: rescalePoints(\n 0,\n width,\n rescalePoints(1, height, element.points, normalizePoints),\n normalizePoints,\n ),\n }\n : {};\n\nexport const measureFontSizeFromWidth = (\n element: NonDeleted<ExcalidrawTextElement>,\n elementsMap: ElementsMap,\n nextWidth: number,\n): { size: number } | null => {\n // We only use width to scale font on resize\n let width = element.width;\n\n const hasContainer = isBoundToContainer(element);\n if (hasContainer) {\n const container = getContainerElement(element, elementsMap);\n if (container) {\n width = getBoundTextMaxWidth(container, element);\n }\n }\n const nextFontSize = element.fontSize * (nextWidth / width);\n if (nextFontSize < MIN_FONT_SIZE) {\n return null;\n }\n\n return {\n size: nextFontSize,\n };\n};\n\nexport const resizeSingleTextElement = (\n origElement: NonDeleted<ExcalidrawTextElement>,\n element: NonDeleted<ExcalidrawTextElement>,\n scene: Scene,\n transformHandleType: TransformHandleDirection,\n shouldResizeFromCenter: boolean,\n nextWidth: number,\n nextHeight: number,\n) => {\n const elementsMap = scene.getNonDeletedElementsMap();\n\n const metricsWidth = element.width * (nextHeight / element.height);\n\n const metrics = measureFontSizeFromWidth(element, elementsMap, metricsWidth);\n if (metrics === null) {\n return;\n }\n\n if (transformHandleType.includes(\"n\") || transformHandleType.includes(\"s\")) {\n const previousOrigin = pointFrom<GlobalPoint>(origElement.x, origElement.y);\n\n const newOrigin = getResizedOrigin(\n previousOrigin,\n origElement.width,\n origElement.height,\n metricsWidth,\n nextHeight,\n origElement.angle,\n transformHandleType,\n false,\n shouldResizeFromCenter,\n );\n\n scene.mutateElement(element, {\n fontSize: metrics.size,\n width: metricsWidth,\n height: nextHeight,\n x: newOrigin.x,\n y: newOrigin.y,\n });\n return;\n }\n\n if (transformHandleType === \"e\" || transformHandleType === \"w\") {\n const minWidth = getMinTextElementWidth(\n getFontString({\n fontSize: element.fontSize,\n fontFamily: element.fontFamily,\n }),\n element.lineHeight,\n );\n\n const newWidth = Math.max(minWidth, nextWidth);\n\n const text = wrapText(\n element.originalText,\n getFontString(element),\n Math.abs(newWidth),\n );\n const metrics = measureText(\n text,\n getFontString(element),\n element.lineHeight,\n );\n\n const newHeight = metrics.height;\n\n const previousOrigin = pointFrom<GlobalPoint>(origElement.x, origElement.y);\n\n const newOrigin = getResizedOrigin(\n previousOrigin,\n origElement.width,\n origElement.height,\n newWidth,\n newHeight,\n element.angle,\n transformHandleType,\n false,\n shouldResizeFromCenter,\n );\n\n const resizedElement: Partial<ExcalidrawTextElement> = {\n width: Math.abs(newWidth),\n height: Math.abs(metrics.height),\n x: newOrigin.x,\n y: newOrigin.y,\n text,\n autoResize: false,\n };\n\n scene.mutateElement(element, resizedElement);\n }\n};\n\nconst rotateMultipleElements = (\n originalElements: PointerDownState[\"originalElements\"],\n elements: readonly NonDeletedExcalidrawElement[],\n scene: Scene,\n pointerX: number,\n pointerY: number,\n shouldRotateWithDiscreteAngle: boolean,\n centerX: number,\n centerY: number,\n) => {\n const elementsMap = scene.getNonDeletedElementsMap();\n let centerAngle =\n (5 * Math.PI) / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);\n if (shouldRotateWithDiscreteAngle) {\n centerAngle += SHIFT_LOCKING_ANGLE / 2;\n centerAngle -= centerAngle % SHIFT_LOCKING_ANGLE;\n }\n\n const rotatedElementsMap = new Map<\n ExcalidrawElement[\"id\"],\n NonDeletedExcalidrawElement\n >(elements.map((element) => [element.id, element]));\n\n for (const element of elements) {\n if (!isFrameLikeElement(element)) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const origAngle =\n originalElements.get(element.id)?.angle ?? element.angle;\n const [rotatedCX, rotatedCY] = pointRotateRads(\n pointFrom(cx, cy),\n pointFrom(centerX, centerY),\n (centerAngle + origAngle - element.angle) as Radians,\n );\n\n const updates = isElbowArrow(element)\n ? {\n // Needed to re-route the arrow\n points: getArrowLocalFixedPoints(element, elementsMap),\n }\n : {\n x: element.x + (rotatedCX - cx),\n y: element.y + (rotatedCY - cy),\n angle: normalizeRadians((centerAngle + origAngle) as Radians),\n };\n\n scene.mutateElement(element, updates);\n\n updateBoundElements(element, scene, {\n simultaneouslyUpdated: elements,\n });\n\n if (isBindingElement(element)) {\n if (element.startBinding) {\n if (!rotatedElementsMap.has(element.startBinding.elementId)) {\n unbindBindingElement(element, \"start\", scene);\n }\n }\n if (element.endBinding) {\n if (!rotatedElementsMap.has(element.endBinding.elementId)) {\n unbindBindingElement(element, \"end\", scene);\n }\n }\n }\n\n const boundText = getBoundTextElement(element, elementsMap);\n if (boundText && !isArrowElement(element)) {\n const { x, y } = computeBoundTextPosition(\n element,\n boundText,\n elementsMap,\n );\n\n scene.mutateElement(boundText, {\n x,\n y,\n angle: normalizeRadians((centerAngle + origAngle) as Radians),\n });\n }\n }\n }\n\n scene.triggerUpdate();\n};\n\nexport const getResizeOffsetXY = (\n transformHandleType: MaybeTransformHandleType,\n selectedElements: NonDeletedExcalidrawElement[],\n elementsMap: ElementsMap,\n x: number,\n y: number,\n): [number, number] => {\n const [x1, y1, x2, y2] =\n selectedElements.length === 1\n ? getElementAbsoluteCoords(selectedElements[0], elementsMap)\n : getCommonBounds(selectedElements);\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n const angle = (\n selectedElements.length === 1 ? selectedElements[0].angle : 0\n ) as Radians;\n [x, y] = pointRotateRads(\n pointFrom(x, y),\n pointFrom(cx, cy),\n -angle as Radians,\n );\n switch (transformHandleType) {\n case \"n\":\n return pointRotateRads(\n pointFrom(x - (x1 + x2) / 2, y - y1),\n pointFrom(0, 0),\n angle,\n );\n case \"s\":\n return pointRotateRads(\n pointFrom(x - (x1 + x2) / 2, y - y2),\n pointFrom(0, 0),\n angle,\n );\n case \"w\":\n return pointRotateRads(\n pointFrom(x - x1, y - (y1 + y2) / 2),\n pointFrom(0, 0),\n angle,\n );\n case \"e\":\n return pointRotateRads(\n pointFrom(x - x2, y - (y1 + y2) / 2),\n pointFrom(0, 0),\n angle,\n );\n case \"nw\":\n return pointRotateRads(pointFrom(x - x1, y - y1), pointFrom(0, 0), angle);\n case \"ne\":\n return pointRotateRads(pointFrom(x - x2, y - y1), pointFrom(0, 0), angle);\n case \"sw\":\n return pointRotateRads(pointFrom(x - x1, y - y2), pointFrom(0, 0), angle);\n case \"se\":\n return pointRotateRads(pointFrom(x - x2, y - y2), pointFrom(0, 0), angle);\n default:\n return [0, 0];\n }\n};\n\nexport const getResizeArrowDirection = (\n transformHandleType: MaybeTransformHandleType,\n element: NonDeleted<ExcalidrawLinearElement>,\n): \"origin\" | \"end\" => {\n const [, [px, py]] = element.points;\n const isResizeEnd =\n (transformHandleType === \"nw\" && (px < 0 || py < 0)) ||\n (transformHandleType === \"ne\" && px >= 0) ||\n (transformHandleType === \"sw\" && px <= 0) ||\n (transformHandleType === \"se\" && (px > 0 || py > 0));\n return isResizeEnd ? \"end\" : \"origin\";\n};\n\ntype ResizeAnchor =\n | \"top-left\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"west-side\"\n | \"north-side\"\n | \"east-side\"\n | \"south-side\"\n | \"center\";\n\nconst getResizeAnchor = (\n handleDirection: TransformHandleDirection,\n shouldMaintainAspectRatio: boolean,\n shouldResizeFromCenter: boolean,\n): ResizeAnchor => {\n if (shouldResizeFromCenter) {\n return \"center\";\n }\n\n if (shouldMaintainAspectRatio) {\n switch (handleDirection) {\n case \"n\":\n return \"south-side\";\n case \"e\": {\n return \"west-side\";\n }\n case \"s\":\n return \"north-side\";\n case \"w\":\n return \"east-side\";\n case \"ne\":\n return \"bottom-left\";\n case \"nw\":\n return \"bottom-right\";\n case \"se\":\n return \"top-left\";\n case \"sw\":\n return \"top-right\";\n }\n }\n\n if ([\"e\", \"se\", \"s\"].includes(handleDirection)) {\n return \"top-left\";\n } else if ([\"n\", \"nw\", \"w\"].includes(handleDirection)) {\n return \"bottom-right\";\n } else if (handleDirection === \"ne\") {\n return \"bottom-left\";\n }\n return \"top-right\";\n};\n\nconst getResizedOrigin = (\n prevOrigin: GlobalPoint,\n prevWidth: number,\n prevHeight: number,\n newWidth: number,\n newHeight: number,\n angle: number,\n handleDirection: TransformHandleDirection,\n shouldMaintainAspectRatio: boolean,\n shouldResizeFromCenter: boolean,\n): { x: number; y: number } => {\n const anchor = getResizeAnchor(\n handleDirection,\n shouldMaintainAspectRatio,\n shouldResizeFromCenter,\n );\n\n const [x, y] = prevOrigin;\n\n switch (anchor) {\n case \"top-left\":\n return {\n x:\n x +\n (prevWidth - newWidth) / 2 +\n ((newWidth - prevWidth) / 2) * Math.cos(angle) +\n ((prevHeight - newHeight) / 2) * Math.sin(angle),\n y:\n y +\n (prevHeight - newHeight) / 2 +\n ((newWidth - prevWidth) / 2) * Math.sin(angle) +\n ((newHeight - prevHeight) / 2) * Math.cos(angle),\n };\n case \"top-right\":\n return {\n x:\n x +\n ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1) +\n ((prevHeight - newHeight) / 2) * Math.sin(angle),\n y:\n y +\n (prevHeight - newHeight) / 2 +\n ((prevWidth - newWidth) / 2) * Math.sin(angle) +\n ((newHeight - prevHeight) / 2) * Math.cos(angle),\n };\n\n case \"bottom-left\":\n return {\n x:\n x +\n ((prevWidth - newWidth) / 2) * (1 - Math.cos(angle)) +\n ((newHeight - prevHeight) / 2) * Math.sin(angle),\n y:\n y +\n ((prevHeight - newHeight) / 2) * (Math.cos(angle) + 1) +\n ((newWidth - prevWidth) / 2) * Math.sin(angle),\n };\n case \"bottom-right\":\n return {\n x:\n x +\n ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1) +\n ((newHeight - prevHeight) / 2) * Math.sin(angle),\n y:\n y +\n ((prevHeight - newHeight) / 2) * (Math.cos(angle) + 1) +\n ((prevWidth - newWidth) / 2) * Math.sin(angle),\n };\n case \"center\":\n return {\n x: x - (newWidth - prevWidth) / 2,\n y: y - (newHeight - prevHeight) / 2,\n };\n case \"east-side\":\n return {\n x: x + ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1),\n y:\n y +\n ((prevWidth - newWidth) / 2) * Math.sin(angle) +\n (prevHeight - newHeight) / 2,\n };\n case \"west-side\":\n return {\n x: x + ((prevWidth - newWidth) / 2) * (1 - Math.cos(angle)),\n y:\n y +\n ((newWidth - prevWidth) / 2) * Math.sin(angle) +\n (prevHeight - newHeight) / 2,\n };\n case \"north-side\":\n return {\n x:\n x +\n (prevWidth - newWidth) / 2 +\n ((prevHeight - newHeight) / 2) * Math.sin(angle),\n y: y + ((newHeight - prevHeight) / 2) * (Math.cos(angle) - 1),\n };\n case \"south-side\":\n return {\n x:\n x +\n (prevWidth - newWidth) / 2 +\n ((newHeight - prevHeight) / 2) * Math.sin(angle),\n y: y + ((prevHeight - newHeight) / 2) * (Math.cos(angle) + 1),\n };\n }\n};\n\nexport const resizeSingleElement = (\n nextWidth: number,\n nextHeight: number,\n latestElement: ExcalidrawElement,\n origElement: ExcalidrawElement,\n originalElementsMap: ElementsMap,\n scene: Scene,\n handleDirection: TransformHandleDirection,\n {\n shouldInformMutation = true,\n shouldMaintainAspectRatio = false,\n shouldResizeFromCenter = false,\n }: {\n shouldMaintainAspectRatio?: boolean;\n shouldResizeFromCenter?: boolean;\n shouldInformMutation?: boolean;\n } = {},\n) => {\n if (isTextElement(latestElement) && isTextElement(origElement)) {\n return resizeSingleTextElement(\n origElement,\n latestElement,\n scene,\n handleDirection,\n shouldResizeFromCenter,\n nextWidth,\n nextHeight,\n );\n }\n\n let boundTextFont: { fontSize?: number } = {};\n const elementsMap = scene.getNonDeletedElementsMap();\n const boundTextElement = getBoundTextElement(latestElement, elementsMap);\n\n if (boundTextElement) {\n const stateOfBoundTextElementAtResize = originalElementsMap.get(\n boundTextElement.id,\n ) as typeof boundTextElement | undefined;\n if (stateOfBoundTextElementAtResize) {\n boundTextFont = {\n fontSize: stateOfBoundTextElementAtResize.fontSize,\n };\n }\n if (shouldMaintainAspectRatio) {\n const updatedElement = {\n ...latestElement,\n width: nextWidth,\n height: nextHeight,\n };\n\n const nextFont = measureFontSizeFromWidth(\n boundTextElement,\n elementsMap,\n getBoundTextMaxWidth(updatedElement, boundTextElement),\n );\n if (nextFont === null) {\n return;\n }\n boundTextFont = {\n fontSize: nextFont.size,\n };\n } else {\n const minWidth = getApproxMinLineWidth(\n getFontString(boundTextElement),\n boundTextElement.lineHeight,\n );\n const minHeight = getApproxMinLineHeight(\n boundTextElement.fontSize,\n boundTextElement.lineHeight,\n );\n nextWidth = Math.max(nextWidth, minWidth);\n nextHeight = Math.max(nextHeight, minHeight);\n }\n }\n\n const rescaledPoints = rescalePointsInElement(\n origElement,\n nextWidth,\n nextHeight,\n true,\n );\n\n let previousOrigin = pointFrom<GlobalPoint>(origElement.x, origElement.y);\n\n if (isLinearElement(origElement)) {\n const [x1, y1] = getElementBounds(origElement, originalElementsMap);\n previousOrigin = pointFrom<GlobalPoint>(x1, y1);\n }\n\n const newOrigin: {\n x: number;\n y: number;\n } = getResizedOrigin(\n previousOrigin,\n origElement.width,\n origElement.height,\n nextWidth,\n nextHeight,\n origElement.angle,\n handleDirection,\n shouldMaintainAspectRatio!!,\n shouldResizeFromCenter!!,\n );\n\n if (isLinearElement(origElement) && rescaledPoints.points) {\n const offsetX = origElement.x - previousOrigin[0];\n const offsetY = origElement.y - previousOrigin[1];\n\n newOrigin.x += offsetX;\n newOrigin.y += offsetY;\n\n const scaledX = rescaledPoints.points[0][0];\n const scaledY = rescaledPoints.points[0][1];\n\n newOrigin.x += scaledX;\n newOrigin.y += scaledY;\n\n rescaledPoints.points = rescaledPoints.points.map((p) =>\n pointFrom<LocalPoint>(p[0] - scaledX, p[1] - scaledY),\n );\n }\n\n // flipping\n if (nextWidth < 0) {\n newOrigin.x = newOrigin.x + nextWidth;\n }\n if (nextHeight < 0) {\n newOrigin.y = newOrigin.y + nextHeight;\n }\n\n if (\"scale\" in latestElement && \"scale\" in origElement) {\n scene.mutateElement(latestElement, {\n scale: [\n // defaulting because scaleX/Y can be 0/-0\n (Math.sign(nextWidth) || origElement.scale[0]) * origElement.scale[0],\n (Math.sign(nextHeight) || origElement.scale[1]) * origElement.scale[1],\n ],\n });\n }\n\n if (\n isArrowElement(latestElement) &&\n boundTextElement &&\n shouldMaintainAspectRatio\n ) {\n const fontSize =\n (nextWidth / latestElement.width) * boundTextElement.fontSize;\n if (fontSize < MIN_FONT_SIZE) {\n return;\n }\n boundTextFont.fontSize = fontSize;\n }\n\n if (\n nextWidth !== 0 &&\n nextHeight !== 0 &&\n Number.isFinite(newOrigin.x) &&\n Number.isFinite(newOrigin.y)\n ) {\n let updates: ElementUpdate<ExcalidrawElement> = {\n ...newOrigin,\n width: Math.abs(nextWidth),\n height: Math.abs(nextHeight),\n ...rescaledPoints,\n };\n\n if (isBindingElement(latestElement)) {\n if (latestElement.startBinding) {\n updates = {\n ...updates,\n } as ElementUpdate<ExcalidrawArrowElement>;\n\n if (latestElement.startBinding) {\n unbindBindingElement(latestElement, \"start\", scene);\n }\n }\n\n if (latestElement.endBinding) {\n updates = {\n ...updates,\n endBinding: null,\n } as ElementUpdate<ExcalidrawArrowElement>;\n }\n }\n\n scene.mutateElement(latestElement, updates, {\n informMutation: shouldInformMutation,\n isDragging: false,\n });\n\n if (boundTextElement && boundTextFont != null) {\n scene.mutateElement(boundTextElement, {\n fontSize: boundTextFont.fontSize,\n });\n }\n handleBindTextResize(\n latestElement,\n scene,\n handleDirection,\n shouldMaintainAspectRatio,\n );\n\n updateBoundElements(latestElement, scene);\n }\n};\n\nconst getNextSingleWidthAndHeightFromPointer = (\n latestElement: ExcalidrawElement,\n origElement: ExcalidrawElement,\n handleDirection: TransformHandleDirection,\n pointerX: number,\n pointerY: number,\n {\n shouldMaintainAspectRatio = false,\n shouldResizeFromCenter = false,\n }: {\n shouldMaintainAspectRatio?: boolean;\n shouldResizeFromCenter?: boolean;\n } = {},\n) => {\n // Gets bounds corners\n const [x1, y1, x2, y2] = getResizedElementAbsoluteCoords(\n origElement,\n origElement.width,\n origElement.height,\n true,\n );\n const startTopLeft = pointFrom(x1, y1);\n const startBottomRight = pointFrom(x2, y2);\n const startCenter = pointCenter(startTopLeft, startBottomRight);\n\n // Calculate new dimensions based on cursor position\n const rotatedPointer = pointRotateRads(\n pointFrom(pointerX, pointerY),\n startCenter,\n -origElement.angle as Radians,\n );\n\n // Get bounds corners rendered on screen\n const [esx1, esy1, esx2, esy2] = getResizedElementAbsoluteCoords(\n latestElement,\n latestElement.width,\n latestElement.height,\n true,\n );\n\n const boundsCurrentWidth = esx2 - esx1;\n const boundsCurrentHeight = esy2 - esy1;\n\n // It's important we set the initial scale value based on the width and height at resize start,\n // otherwise previous dimensions affected by modifiers will be taken into account.\n const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];\n const atStartBoundsHeight = startBottomRight[1] - startTopLeft[1];\n let scaleX = atStartBoundsWidth / boundsCurrentWidth;\n let scaleY = atStartBoundsHeight / boundsCurrentHeight;\n\n if (handleDirection.includes(\"e\")) {\n scaleX = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;\n }\n if (handleDirection.includes(\"s\")) {\n scaleY = (rotatedPointer[1] - startTopLeft[1]) / boundsCurrentHeight;\n }\n if (handleDirection.includes(\"w\")) {\n scaleX = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;\n }\n if (handleDirection.includes(\"n\")) {\n scaleY = (startBottomRight[1] - rotatedPointer[1]) / boundsCurrentHeight;\n }\n\n // We have to use dimensions of element on screen, otherwise the scaling of the\n // dimensions won't match the cursor for linear elements.\n let nextWidth = latestElement.width * scaleX;\n let nextHeight = latestElement.height * scaleY;\n\n if (shouldResizeFromCenter) {\n nextWidth = 2 * nextWidth - origElement.width;\n nextHeight = 2 * nextHeight - origElement.height;\n }\n\n // adjust dimensions to keep sides ratio\n if (shouldMaintainAspectRatio) {\n const widthRatio = Math.abs(nextWidth) / origElement.width;\n const heightRatio = Math.abs(nextHeight) / origElement.height;\n if (handleDirection.length === 1) {\n nextHeight *= widthRatio;\n nextWidth *= heightRatio;\n }\n if (handleDirection.length === 2) {\n const ratio = Math.max(widthRatio, heightRatio);\n nextWidth = origElement.width * ratio * Math.sign(nextWidth);\n nextHeight = origElement.height * ratio * Math.sign(nextHeight);\n }\n }\n\n return {\n nextWidth,\n nextHeight,\n };\n};\n\nconst getNextMultipleWidthAndHeightFromPointer = (\n selectedElements: readonly NonDeletedExcalidrawElement[],\n originalElementsMap: ElementsMap,\n elementsMap: ElementsMap,\n handleDirection: TransformHandleDirection,\n pointerX: number,\n pointerY: number,\n {\n shouldMaintainAspectRatio = false,\n shouldResizeFromCenter = false,\n }: {\n shouldResizeFromCenter?: boolean;\n shouldMaintainAspectRatio?: boolean;\n } = {},\n) => {\n const originalElementsArray = selectedElements.map(\n (el) => originalElementsMap.get(el.id)!,\n );\n\n // getCommonBoundingBox() uses getBoundTextElement() which returns null for\n // original elements from pointerDownState, so we have to find and add these\n // bound text elements manually. Additionally, the coordinates of bound text\n // elements aren't always up to date.\n const boundTextElements = originalElementsArray.reduce((acc, orig) => {\n if (!isLinearElement(orig)) {\n return acc;\n }\n const textId = getBoundTextElementId(orig);\n if (!textId) {\n return acc;\n }\n const text = originalElementsMap.get(textId) ?? null;\n if (!isBoundToContainer(text)) {\n return acc;\n }\n return [\n ...acc,\n {\n ...text,\n ...LinearElementEditor.getBoundTextElementPosition(\n orig,\n text,\n elementsMap,\n ),\n },\n ];\n }, [] as ExcalidrawTextElementWithContainer[]);\n\n const originalBoundingBox = getCommonBoundingBox(\n originalElementsArray.map((orig) => orig).concat(boundTextElements),\n );\n\n const { minX, minY, maxX, maxY, midX, midY } = originalBoundingBox;\n const width = maxX - minX;\n const height = maxY - minY;\n\n const anchorsMap = {\n ne: [minX, maxY],\n se: [minX, minY],\n sw: [maxX, minY],\n nw: [maxX, maxY],\n e: [minX, minY + height / 2],\n w: [maxX, minY + height / 2],\n n: [minX + width / 2, maxY],\n s: [minX + width / 2, minY],\n } as Record<TransformHandleDirection, GlobalPoint>;\n\n // anchor point must be on the opposite side of the dragged selection handle\n // or be the center of the selection if shouldResizeFromCenter\n const [anchorX, anchorY] = shouldResizeFromCenter\n ? [midX, midY]\n : anchorsMap[handleDirection];\n\n const resizeFromCenterScale = shouldResizeFromCenter ? 2 : 1;\n\n const scale =\n Math.max(\n Math.abs(pointerX - anchorX) / width || 0,\n Math.abs(pointerY - anchorY) / height || 0,\n ) * resizeFromCenterScale;\n\n let nextWidth =\n handleDirection.includes(\"e\") || handleDirection.includes(\"w\")\n ? Math.abs(pointerX - anchorX) * resizeFromCenterScale\n : width;\n let nextHeight =\n handleDirection.includes(\"n\") || handleDirection.includes(\"s\")\n ? Math.abs(pointerY - anchorY) * resizeFromCenterScale\n : height;\n\n if (shouldMaintainAspectRatio) {\n nextWidth = width * scale * Math.sign(pointerX - anchorX);\n nextHeight = height * scale * Math.sign(pointerY - anchorY);\n }\n\n const flipConditionsMap: Record<\n TransformHandleDirection,\n // Condition for which we should flip or not flip the selected elements\n // - when evaluated to `true`, we flip\n // - therefore, setting it to always `false` means we do not flip (in that direction) at all\n [x: boolean, y: boolean]\n > = {\n ne: [pointerX < anchorX, pointerY > anchorY],\n se: [pointerX < anchorX, pointerY < anchorY],\n sw: [pointerX > anchorX, pointerY < anchorY],\n nw: [pointerX > anchorX, pointerY > anchorY],\n // e.g. when resizing from the \"e\" side, we do not need to consider changes in the `y` direction\n // and therefore, we do not need to flip in the `y` direction at all\n e: [pointerX < anchorX, false],\n w: [pointerX > anchorX, false],\n n: [false, pointerY > anchorY],\n s: [false, pointerY < anchorY],\n };\n\n const [flipByX, flipByY] = flipConditionsMap[handleDirection].map(\n (condition) => condition,\n );\n\n return {\n originalBoundingBox,\n nextWidth,\n nextHeight,\n flipByX,\n flipByY,\n };\n};\n\nexport const resizeMultipleElements = (\n selectedElements: readonly NonDeletedExcalidrawElement[],\n elementsMap: ElementsMap,\n handleDirection: TransformHandleDirection,\n scene: Scene,\n originalElementsMap: ElementsMap,\n {\n shouldMaintainAspectRatio = false,\n shouldResizeFromCenter = false,\n flipByX = false,\n flipByY = false,\n nextHeight,\n nextWidth,\n originalBoundingBox,\n }: {\n nextWidth?: number;\n nextHeight?: number;\n shouldMaintainAspectRatio?: boolean;\n shouldResizeFromCenter?: boolean;\n flipByX?: boolean;\n flipByY?: boolean;\n // added to improve performance\n originalBoundingBox?: BoundingBox;\n } = {},\n) => {\n // in the case of just flipping, there is no need to specify the next width and height\n if (\n nextWidth === undefined &&\n nextHeight === undefined &&\n flipByX === undefined &&\n flipByY === undefined\n ) {\n return;\n }\n\n // do not allow next width or height to be 0\n if (nextHeight === 0 || nextWidth === 0) {\n return;\n }\n\n if (!originalElementsMap) {\n originalElementsMap = elementsMap;\n }\n\n const targetElements = selectedElements.reduce(\n (\n acc: {\n /** element at resize start */\n orig: NonDeletedExcalidrawElement;\n /** latest element */\n latest: NonDeletedExcalidrawElement;\n }[],\n element,\n ) => {\n const origElement = originalElementsMap!.get(element.id);\n if (origElement) {\n acc.push({ orig: origElement, latest: element });\n }\n return acc;\n },\n [],\n );\n\n let boundingBox: BoundingBox;\n\n if (originalBoundingBox) {\n boundingBox = originalBoundingBox;\n } else {\n const boundTextElements = targetElements.reduce((acc, { orig }) => {\n if (!isLinearElement(orig)) {\n return acc;\n }\n const textId = getBoundTextElementId(orig);\n if (!textId) {\n return acc;\n }\n const text = originalElementsMap!.get(textId) ?? null;\n if (!isBoundToContainer(text)) {\n return acc;\n }\n return [\n ...acc,\n {\n ...text,\n ...LinearElementEditor.getBoundTextElementPosition(\n orig,\n text,\n elementsMap,\n ),\n },\n ];\n }, [] as ExcalidrawTextElementWithContainer[]);\n\n boundingBox = getCommonBoundingBox(\n targetElements.map(({ orig }) => orig).concat(boundTextElements),\n );\n }\n const { minX, minY, maxX, maxY, midX, midY } = boundingBox;\n const width = maxX - minX;\n const height = maxY - minY;\n\n if (nextWidth === undefined && nextHeight === undefined) {\n nextWidth = width;\n nextHeight = height;\n }\n\n if (shouldMaintainAspectRatio) {\n if (nextWidth === undefined) {\n nextWidth = nextHeight! * (width / height);\n } else if (nextHeight === undefined) {\n nextHeight = nextWidth! * (height / width);\n } else if (Math.abs(nextWidth / nextHeight - width / height) > 0.001) {\n nextWidth = nextHeight * (width / height);\n }\n }\n\n if (nextWidth && nextHeight) {\n let scaleX =\n handleDirection.includes(\"e\") || handleDirection.includes(\"w\")\n ? Math.abs(nextWidth) / width\n : 1;\n let scaleY =\n handleDirection.includes(\"n\") || handleDirection.includes(\"s\")\n ? Math.abs(nextHeight) / height\n : 1;\n\n let scale: number;\n\n if (handleDirection.length === 1) {\n scale =\n handleDirection.includes(\"e\") || handleDirection.includes(\"w\")\n ? scaleX\n : scaleY;\n } else {\n scale = Math.max(\n Math.abs(nextWidth) / width || 0,\n Math.abs(nextHeight) / height || 0,\n );\n }\n\n const anchorsMap = {\n ne: [minX, maxY],\n se: [minX, minY],\n sw: [maxX, minY],\n nw: [maxX, maxY],\n e: [minX, minY + height / 2],\n w: [maxX, minY + height / 2],\n n: [minX + width / 2, maxY],\n s: [minX + width / 2, minY],\n } as Record<TransformHandleDirection, GlobalPoint>;\n\n // anchor point must be on the opposite side of the dragged selection handle\n // or be the center of the selection if shouldResizeFromCenter\n const [anchorX, anchorY] = shouldResizeFromCenter\n ? [midX, midY]\n : anchorsMap[handleDirection];\n\n const keepAspectRatio =\n shouldMaintainAspectRatio ||\n targetElements.some(\n (item) =>\n item.latest.angle !== 0 ||\n isTextElement(item.latest) ||\n isInGroup(item.latest),\n );\n\n if (keepAspectRatio) {\n scaleX = scale;\n scaleY = scale;\n }\n\n /**\n * to flip an element:\n * 1. determine over which axis is the element being flipped\n * (could be x, y, or both) indicated by `flipFactorX` & `flipFactorY`\n * 2. shift element's position by the amount of width or height (or both) or\n * mirror points in the case of linear & freedraw elemenets\n * 3. adjust element angle\n */\n const [flipFactorX, flipFactorY] = [flipByX ? -1 : 1, flipByY ? -1 : 1];\n\n const elementsAndUpdates: {\n element: NonDeletedExcalidrawElement;\n update: Mutable<\n Pick<ExcalidrawElement, \"x\" | \"y\" | \"width\" | \"height\" | \"angle\">\n > & {\n points?: ExcalidrawLinearElement[\"points\"];\n fontSize?: ExcalidrawTextElement[\"fontSize\"];\n scale?: ExcalidrawImageElement[\"scale\"];\n boundTextFontSize?: ExcalidrawTextElement[\"fontSize\"];\n startBinding?: ExcalidrawElbowArrowElement[\"startBinding\"];\n endBinding?: ExcalidrawElbowArrowElement[\"endBinding\"];\n fixedSegments?: ExcalidrawElbowArrowElement[\"fixedSegments\"];\n };\n }[] = [];\n\n for (const { orig, latest } of targetElements) {\n // bounded text elements are updated along with their container elements\n if (isTextElement(orig) && isBoundToContainer(orig)) {\n continue;\n }\n\n const width = orig.width * scaleX;\n const height = orig.height * scaleY;\n const angle = normalizeRadians(\n (orig.angle * flipFactorX * flipFactorY) as Radians,\n );\n\n const isLinearOrFreeDraw =\n isLinearElement(orig) || isFreeDrawElement(orig);\n const offsetX = orig.x - anchorX;\n const offsetY = orig.y - anchorY;\n const shiftX = flipByX && !isLinearOrFreeDraw ? width : 0;\n const shiftY = flipByY && !isLinearOrFreeDraw ? height : 0;\n const x = anchorX + flipFactorX * (offsetX * scaleX + shiftX);\n const y = anchorY + flipFactorY * (offsetY * scaleY + shiftY);\n\n const rescaledPoints = rescalePointsInElement(\n orig,\n width * flipFactorX,\n height * flipFactorY,\n false,\n );\n\n const update: typeof elementsAndUpdates[0][\"update\"] = {\n x,\n y,\n width,\n height,\n angle,\n ...rescaledPoints,\n };\n\n if (isElbowArrow(orig)) {\n // Mirror fixed point binding for elbow arrows\n // when resize goes into the negative direction\n if (orig.startBinding) {\n update.startBinding = {\n ...orig.startBinding,\n fixedPoint: [\n flipByX\n ? -orig.startBinding.fixedPoint[0] + 1\n : orig.startBinding.fixedPoint[0],\n flipByY\n ? -orig.startBinding.fixedPoint[1] + 1\n : orig.startBinding.fixedPoint[1],\n ],\n };\n }\n if (orig.endBinding) {\n update.endBinding = {\n ...orig.endBinding,\n fixedPoint: [\n flipByX\n ? -orig.endBinding.fixedPoint[0] + 1\n : orig.endBinding.fixedPoint[0],\n flipByY\n ? -orig.endBinding.fixedPoint[1] + 1\n : orig.endBinding.fixedPoint[1],\n ],\n };\n }\n if (orig.fixedSegments && rescaledPoints.points) {\n update.fixedSegments = orig.fixedSegments.map((segment) => ({\n ...segment,\n start: rescaledPoints.points[segment.index - 1],\n end: rescaledPoints.points[segment.index],\n }));\n }\n }\n\n if (isImageElement(orig)) {\n update.scale = [\n orig.scale[0] * flipFactorX,\n orig.scale[1] * flipFactorY,\n ];\n }\n\n if (isTextElement(orig)) {\n const metrics = measureFontSizeFromWidth(orig, elementsMap, width);\n if (!metrics) {\n return;\n }\n update.fontSize = metrics.size;\n }\n\n const boundTextElement = originalElementsMap.get(\n getBoundTextElementId(orig) ?? \"\",\n ) as ExcalidrawTextElementWithContainer | undefined;\n\n if (boundTextElement) {\n if (keepAspectRatio) {\n const newFontSize = boundTextElement.fontSize * scale;\n if (newFontSize < MIN_FONT_SIZE) {\n return;\n }\n update.boundTextFontSize = newFontSize;\n } else {\n update.boundTextFontSize = boundTextElement.fontSize;\n }\n }\n\n elementsAndUpdates.push({\n element: latest,\n update,\n });\n }\n\n const elementsToUpdate = elementsAndUpdates.map(({ element }) => element);\n const resizedElementsMap = new Map<\n ExcalidrawElement[\"id\"],\n NonDeletedExcalidrawElement\n >(elementsAndUpdates.map(({ element }) => [element.id, element]));\n\n for (const {\n element,\n update: { boundTextFontSize, ...update },\n } of elementsAndUpdates) {\n const { angle } = update;\n\n scene.mutateElement(element, update);\n\n updateBoundElements(element, scene, {\n simultaneouslyUpdated: elementsToUpdate,\n });\n\n if (isBindingElement(element)) {\n if (element.startBinding) {\n if (!resizedElementsMap.has(element.startBinding.elementId)) {\n unbindBindingElement(element, \"start\", scene);\n }\n }\n if (element.endBinding) {\n if (!resizedElementsMap.has(element.endBinding.elementId)) {\n unbindBindingElement(element, \"end\", scene);\n }\n }\n }\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (boundTextElement && boundTextFontSize) {\n scene.mutateElement(boundTextElement, {\n fontSize: boundTextFontSize,\n angle: isLinearElement(element) ? undefined : angle,\n });\n handleBindTextResize(element, scene, handleDirection, true);\n }\n }\n\n scene.triggerUpdate();\n }\n};\n", "import {\n DEFAULT_TRANSFORM_HANDLE_SPACING,\n type EditorInterface,\n} from \"@excalidraw/common\";\n\nimport { pointFrom, pointRotateRads } from \"@excalidraw/math\";\n\nimport type { Radians } from \"@excalidraw/math\";\n\nimport type {\n InteractiveCanvasAppState,\n Zoom,\n} from \"@excalidraw/excalidraw/types\";\nimport type { Bounds } from \"@excalidraw/common\";\n\nimport { getElementAbsoluteCoords } from \"./bounds\";\nimport {\n isElbowArrow,\n isFrameLikeElement,\n isImageElement,\n isLinearElement,\n} from \"./typeChecks\";\n\nimport type {\n ElementsMap,\n ExcalidrawElement,\n NonDeletedExcalidrawElement,\n PointerType,\n} from \"./types\";\n\nexport type TransformHandleDirection =\n | \"n\"\n | \"s\"\n | \"w\"\n | \"e\"\n | \"nw\"\n | \"ne\"\n | \"sw\"\n | \"se\";\n\nexport type TransformHandleType = TransformHandleDirection | \"rotation\";\n\nexport type TransformHandle = Bounds;\nexport type TransformHandles = Partial<{\n [T in TransformHandleType]: TransformHandle;\n}>;\nexport type MaybeTransformHandleType = TransformHandleType | false;\n\nconst transformHandleSizes: { [k in PointerType]: number } = {\n mouse: 8,\n pen: 16,\n touch: 28,\n};\n\nconst ROTATION_RESIZE_HANDLE_GAP = 16;\n\nexport const DEFAULT_OMIT_SIDES = {\n e: true,\n s: true,\n n: true,\n w: true,\n};\n\nexport const OMIT_SIDES_FOR_MULTIPLE_ELEMENTS = {\n e: true,\n s: true,\n n: true,\n w: true,\n};\n\nexport const OMIT_SIDES_FOR_FRAME = {\n e: true,\n s: true,\n n: true,\n w: true,\n rotation: true,\n};\n\nconst OMIT_SIDES_FOR_LINE_SLASH = {\n e: true,\n s: true,\n n: true,\n w: true,\n nw: true,\n se: true,\n};\n\nconst OMIT_SIDES_FOR_LINE_BACKSLASH = {\n e: true,\n s: true,\n n: true,\n w: true,\n};\n\nconst generateTransformHandle = (\n x: number,\n y: number,\n width: number,\n height: number,\n cx: number,\n cy: number,\n angle: Radians,\n): TransformHandle => {\n const [xx, yy] = pointRotateRads(\n pointFrom(x + width / 2, y + height / 2),\n pointFrom(cx, cy),\n angle,\n );\n return [xx - width / 2, yy - height / 2, width, height];\n};\n\nexport const canResizeFromSides = (editorInterface: EditorInterface) => {\n if (\n editorInterface.formFactor === \"phone\" &&\n editorInterface.userAgent.isMobileDevice\n ) {\n return false;\n }\n\n return true;\n};\n\nexport const getOmitSidesForEditorInterface = (\n editorInterface: EditorInterface,\n) => {\n if (canResizeFromSides(editorInterface)) {\n return DEFAULT_OMIT_SIDES;\n }\n\n return {};\n};\n\nexport const getTransformHandlesFromCoords = (\n [x1, y1, x2, y2, cx, cy]: [number, number, number, number, number, number],\n angle: Radians,\n zoom: Zoom,\n pointerType: PointerType,\n omitSides: { [T in TransformHandleType]?: boolean } = {},\n margin = 4,\n spacing = DEFAULT_TRANSFORM_HANDLE_SPACING,\n): TransformHandles => {\n const size = transformHandleSizes[pointerType];\n const handleWidth = size / zoom.value;\n const handleHeight = size / zoom.value;\n\n const handleMarginX = size / zoom.value;\n const handleMarginY = size / zoom.value;\n\n const width = x2 - x1;\n const height = y2 - y1;\n const dashedLineMargin = margin / zoom.value;\n const centeringOffset = (size - spacing * 2) / (2 * zoom.value);\n\n const transformHandles: TransformHandles = {\n nw: omitSides.nw\n ? undefined\n : generateTransformHandle(\n x1 - dashedLineMargin - handleMarginX + centeringOffset,\n y1 - dashedLineMargin - handleMarginY + centeringOffset,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n ),\n ne: omitSides.ne\n ? undefined\n : generateTransformHandle(\n x2 + dashedLineMargin - centeringOffset,\n y1 - dashedLineMargin - handleMarginY + centeringOffset,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n ),\n sw: omitSides.sw\n ? undefined\n : generateTransformHandle(\n x1 - dashedLineMargin - handleMarginX + centeringOffset,\n y2 + dashedLineMargin - centeringOffset,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n ),\n se: omitSides.se\n ? undefined\n : generateTransformHandle(\n x2 + dashedLineMargin - centeringOffset,\n y2 + dashedLineMargin - centeringOffset,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n ),\n rotation: omitSides.rotation\n ? undefined\n : generateTransformHandle(\n x1 + width / 2 - handleWidth / 2,\n y1 -\n dashedLineMargin -\n handleMarginY +\n centeringOffset -\n ROTATION_RESIZE_HANDLE_GAP / zoom.value,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n ),\n };\n\n // We only want to show height handles (all cardinal directions) above a certain size\n // Note: we render using \"mouse\" size so we should also use \"mouse\" size for this check\n const minimumSizeForEightHandles =\n (5 * transformHandleSizes.mouse) / zoom.value;\n if (Math.abs(width) > minimumSizeForEightHandles) {\n if (!omitSides.n) {\n transformHandles.n = generateTransformHandle(\n x1 + width / 2 - handleWidth / 2,\n y1 - dashedLineMargin - handleMarginY + centeringOffset,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n );\n }\n if (!omitSides.s) {\n transformHandles.s = generateTransformHandle(\n x1 + width / 2 - handleWidth / 2,\n y2 + dashedLineMargin - centeringOffset,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n );\n }\n }\n if (Math.abs(height) > minimumSizeForEightHandles) {\n if (!omitSides.w) {\n transformHandles.w = generateTransformHandle(\n x1 - dashedLineMargin - handleMarginX + centeringOffset,\n y1 + height / 2 - handleHeight / 2,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n );\n }\n if (!omitSides.e) {\n transformHandles.e = generateTransformHandle(\n x2 + dashedLineMargin - centeringOffset,\n y1 + height / 2 - handleHeight / 2,\n handleWidth,\n handleHeight,\n cx,\n cy,\n angle,\n );\n }\n }\n\n return transformHandles;\n};\n\nexport const getTransformHandles = (\n element: ExcalidrawElement,\n zoom: Zoom,\n elementsMap: ElementsMap,\n pointerType: PointerType = \"mouse\",\n omitSides: { [T in TransformHandleType]?: boolean } = DEFAULT_OMIT_SIDES,\n): TransformHandles => {\n // so that when locked element is selected (especially when you toggle lock\n // via keyboard) the locked element is visually distinct, indicating\n // you can't move/resize\n if (\n element.locked ||\n // Elbow arrows cannot be rotated\n isElbowArrow(element)\n ) {\n return {};\n }\n\n if (element.type === \"freedraw\" || isLinearElement(element)) {\n if (element.points.length === 2) {\n // only check the last point because starting point is always (0,0)\n const [, p1] = element.points;\n if (p1[0] === 0 || p1[1] === 0) {\n omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;\n } else if (p1[0] > 0 && p1[1] < 0) {\n omitSides = OMIT_SIDES_FOR_LINE_SLASH;\n } else if (p1[0] > 0 && p1[1] > 0) {\n omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;\n } else if (p1[0] < 0 && p1[1] > 0) {\n omitSides = OMIT_SIDES_FOR_LINE_SLASH;\n } else if (p1[0] < 0 && p1[1] < 0) {\n omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;\n }\n }\n } else if (isFrameLikeElement(element)) {\n omitSides = {\n ...omitSides,\n rotation: true,\n };\n }\n const margin = isLinearElement(element)\n ? DEFAULT_TRANSFORM_HANDLE_SPACING + 8\n : isImageElement(element)\n ? 0\n : DEFAULT_TRANSFORM_HANDLE_SPACING;\n return getTransformHandlesFromCoords(\n getElementAbsoluteCoords(element, elementsMap, true),\n element.angle,\n zoom,\n pointerType,\n omitSides,\n margin,\n isImageElement(element) ? 0 : undefined,\n );\n};\n\nexport const hasBoundingBox = (\n elements: readonly NonDeletedExcalidrawElement[],\n appState: InteractiveCanvasAppState,\n editorInterface: EditorInterface,\n) => {\n if (\n appState.selectedLinearElement?.isEditing ||\n appState.selectedLinearElement?.isDragging\n ) {\n return false;\n }\n if (elements.length > 1) {\n return true;\n }\n const element = elements[0];\n if (isElbowArrow(element)) {\n // Elbow arrows cannot be resized as single selected elements\n return false;\n }\n if (!isLinearElement(element)) {\n return true;\n }\n\n // on mobile/tablet we currently don't show bbox because of resize issues\n // (also prob best for simplicity's sake)\n return element.points.length > 2 && !editorInterface.userAgent.isMobileDevice;\n};\n", "import {\n pointFrom,\n pointOnLineSegment,\n pointRotateRads,\n type Radians,\n} from \"@excalidraw/math\";\n\nimport {\n SIDE_RESIZING_THRESHOLD,\n type EditorInterface,\n} from \"@excalidraw/common\";\n\nimport type { GlobalPoint, LineSegment, LocalPoint } from \"@excalidraw/math\";\n\nimport type { AppState, Zoom } from \"@excalidraw/excalidraw/types\";\nimport type { Bounds } from \"@excalidraw/common\";\n\nimport { getElementAbsoluteCoords } from \"./bounds\";\nimport {\n getTransformHandlesFromCoords,\n getTransformHandles,\n getOmitSidesForEditorInterface,\n canResizeFromSides,\n} from \"./transformHandles\";\nimport { isImageElement, isLinearElement } from \"./typeChecks\";\n\nimport type {\n TransformHandleType,\n TransformHandle,\n MaybeTransformHandleType,\n} from \"./transformHandles\";\nimport type {\n ExcalidrawElement,\n PointerType,\n NonDeletedExcalidrawElement,\n ElementsMap,\n} from \"./types\";\n\nconst isInsideTransformHandle = (\n transformHandle: TransformHandle,\n x: number,\n y: number,\n) =>\n x >= transformHandle[0] &&\n x <= transformHandle[0] + transformHandle[2] &&\n y >= transformHandle[1] &&\n y <= transformHandle[1] + transformHandle[3];\n\nexport const resizeTest = <Point extends GlobalPoint | LocalPoint>(\n element: NonDeletedExcalidrawElement,\n elementsMap: ElementsMap,\n appState: AppState,\n x: number,\n y: number,\n zoom: Zoom,\n pointerType: PointerType,\n editorInterface: EditorInterface,\n): MaybeTransformHandleType => {\n if (!appState.selectedElementIds[element.id]) {\n return false;\n }\n\n const { rotation: rotationTransformHandle, ...transformHandles } =\n getTransformHandles(\n element,\n zoom,\n elementsMap,\n pointerType,\n getOmitSidesForEditorInterface(editorInterface),\n );\n\n if (\n rotationTransformHandle &&\n isInsideTransformHandle(rotationTransformHandle, x, y)\n ) {\n return \"rotation\" as TransformHandleType;\n }\n\n const filter = Object.keys(transformHandles).filter((key) => {\n const transformHandle =\n transformHandles[key as Exclude<TransformHandleType, \"rotation\">]!;\n if (!transformHandle) {\n return false;\n }\n return isInsideTransformHandle(transformHandle, x, y);\n });\n\n if (filter.length > 0) {\n return filter[0] as TransformHandleType;\n }\n\n if (canResizeFromSides(editorInterface)) {\n const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(\n element,\n elementsMap,\n );\n\n // do not resize from the sides for linear elements with only two points\n if (!(isLinearElement(element) && element.points.length <= 2)) {\n const SPACING = isImageElement(element)\n ? 0\n : SIDE_RESIZING_THRESHOLD / zoom.value;\n const ZOOMED_SIDE_RESIZING_THRESHOLD =\n SIDE_RESIZING_THRESHOLD / zoom.value;\n const sides = getSelectionBorders(\n pointFrom(x1 - SPACING, y1 - SPACING),\n pointFrom(x2 + SPACING, y2 + SPACING),\n pointFrom(cx, cy),\n element.angle,\n );\n\n for (const [dir, side] of Object.entries(sides)) {\n // test to see if x, y are on the line segment\n if (\n pointOnLineSegment(\n pointFrom(x, y),\n side as LineSegment<Point>,\n ZOOMED_SIDE_RESIZING_THRESHOLD,\n )\n ) {\n return dir as TransformHandleType;\n }\n }\n }\n }\n\n return false;\n};\n\nexport const getElementWithTransformHandleType = (\n elements: readonly NonDeletedExcalidrawElement[],\n appState: AppState,\n scenePointerX: number,\n scenePointerY: number,\n zoom: Zoom,\n pointerType: PointerType,\n elementsMap: ElementsMap,\n editorInterface: EditorInterface,\n) => {\n return elements.reduce((result, element) => {\n if (result) {\n return result;\n }\n const transformHandleType = resizeTest(\n element,\n elementsMap,\n appState,\n scenePointerX,\n scenePointerY,\n zoom,\n pointerType,\n editorInterface,\n );\n return transformHandleType ? { element, transformHandleType } : null;\n }, null as { element: NonDeletedExcalidrawElement; transformHandleType: MaybeTransformHandleType } | null);\n};\n\nexport const getTransformHandleTypeFromCoords = <\n Point extends GlobalPoint | LocalPoint,\n>(\n [x1, y1, x2, y2]: Bounds,\n scenePointerX: number,\n scenePointerY: number,\n zoom: Zoom,\n pointerType: PointerType,\n editorInterface: EditorInterface,\n): MaybeTransformHandleType => {\n const transformHandles = getTransformHandlesFromCoords(\n [x1, y1, x2, y2, (x1 + x2) / 2, (y1 + y2) / 2],\n 0 as Radians,\n zoom,\n pointerType,\n getOmitSidesForEditorInterface(editorInterface),\n );\n\n const found = Object.keys(transformHandles).find((key) => {\n const transformHandle =\n transformHandles[key as Exclude<TransformHandleType, \"rotation\">]!;\n return (\n transformHandle &&\n isInsideTransformHandle(transformHandle, scenePointerX, scenePointerY)\n );\n });\n\n if (found) {\n return found as MaybeTransformHandleType;\n }\n\n if (canResizeFromSides(editorInterface)) {\n const cx = (x1 + x2) / 2;\n const cy = (y1 + y2) / 2;\n\n const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;\n\n const sides = getSelectionBorders(\n pointFrom(x1 - SPACING, y1 - SPACING),\n pointFrom(x2 + SPACING, y2 + SPACING),\n pointFrom(cx, cy),\n 0 as Radians,\n );\n\n for (const [dir, side] of Object.entries(sides)) {\n // test to see if x, y are on the line segment\n if (\n pointOnLineSegment(\n pointFrom(scenePointerX, scenePointerY),\n side as LineSegment<Point>,\n SPACING,\n )\n ) {\n return dir as TransformHandleType;\n }\n }\n }\n\n return false;\n};\n\nconst RESIZE_CURSORS = [\"ns\", \"nesw\", \"ew\", \"nwse\"];\nconst rotateResizeCursor = (cursor: string, angle: number) => {\n const index = RESIZE_CURSORS.indexOf(cursor);\n if (index >= 0) {\n const a = Math.round(angle / (Math.PI / 4));\n cursor = RESIZE_CURSORS[(index + a) % RESIZE_CURSORS.length];\n }\n return cursor;\n};\n\n/*\n * Returns bi-directional cursor for the element being resized\n */\nexport const getCursorForResizingElement = (resizingElement: {\n element?: ExcalidrawElement;\n transformHandleType: MaybeTransformHandleType;\n}): string => {\n const { element, transformHandleType } = resizingElement;\n const shouldSwapCursors =\n element && Math.sign(element.height) * Math.sign(element.width) === -1;\n let cursor = null;\n\n switch (transformHandleType) {\n case \"n\":\n case \"s\":\n cursor = \"ns\";\n break;\n case \"w\":\n case \"e\":\n cursor = \"ew\";\n break;\n case \"nw\":\n case \"se\":\n if (shouldSwapCursors) {\n cursor = \"nesw\";\n } else {\n cursor = \"nwse\";\n }\n break;\n case \"ne\":\n case \"sw\":\n if (shouldSwapCursors) {\n cursor = \"nwse\";\n } else {\n cursor = \"nesw\";\n }\n break;\n case \"rotation\":\n return \"grab\";\n }\n\n if (cursor && element) {\n cursor = rotateResizeCursor(cursor, element.angle);\n }\n\n return cursor ? `${cursor}-resize` : \"\";\n};\n\nconst getSelectionBorders = <Point extends LocalPoint | GlobalPoint>(\n [x1, y1]: Point,\n [x2, y2]: Point,\n center: Point,\n angle: Radians,\n) => {\n const topLeft = pointRotateRads(pointFrom(x1, y1), center, angle);\n const topRight = pointRotateRads(pointFrom(x2, y1), center, angle);\n const bottomLeft = pointRotateRads(pointFrom(x1, y2), center, angle);\n const bottomRight = pointRotateRads(pointFrom(x2, y2), center, angle);\n\n return {\n n: [topLeft, topRight],\n e: [topRight, bottomRight],\n s: [bottomRight, bottomLeft],\n w: [bottomLeft, topLeft],\n };\n};\n", "import type { UIAppState } from \"@excalidraw/excalidraw/types\";\n\nimport { getSelectedElements } from \"./selection\";\n\nimport type { NonDeletedExcalidrawElement } from \"./types\";\n\nexport const showSelectedShapeActions = (\n appState: UIAppState,\n elements: readonly NonDeletedExcalidrawElement[],\n) =>\n Boolean(\n !(appState.viewModeEnabled || appState.hideAnnotations) &&\n appState.openDialog?.name !== \"elementLinkSelector\" &&\n ((appState.activeTool.type !== \"custom\" &&\n (appState.editingTextElement ||\n (appState.activeTool.type !== \"selection\" &&\n appState.activeTool.type !== \"lasso\" &&\n appState.activeTool.type !== \"eraser\" &&\n appState.activeTool.type !== \"hand\" &&\n appState.activeTool.type !== \"laser\"))) ||\n getSelectedElements(elements, appState).length),\n );\n", "import { pointFrom, type LocalPoint } from \"@excalidraw/math\";\n\nimport {\n DEFAULT_FONT_FAMILY,\n DEFAULT_FONT_SIZE,\n TEXT_ALIGN,\n VERTICAL_ALIGN,\n getSizeFromPoints,\n randomId,\n arrayToMap,\n assertNever,\n cloneJSON,\n getFontString,\n isDevEnv,\n toBrandedType,\n getLineHeight,\n} from \"@excalidraw/common\";\n\nimport type { MarkOptional } from \"@excalidraw/common/utility-types\";\n\nimport { bindBindingElement } from \"./binding\";\nimport {\n newArrowElement,\n newElement,\n newFrameElement,\n newImageElement,\n newLinearElement,\n newMagicFrameElement,\n newTextElement,\n type ElementConstructorOpts,\n} from \"./newElement\";\nimport { measureText, normalizeText } from \"./textMeasurements\";\nimport { isArrowElement } from \"./typeChecks\";\n\nimport { syncInvalidIndices } from \"./fractionalIndex\";\n\nimport { redrawTextBoundingBox } from \"./textElement\";\n\nimport { LinearElementEditor } from \"./linearElementEditor\";\n\nimport { getCommonBounds } from \"./bounds\";\n\nimport { Scene } from \"./Scene\";\n\nimport type {\n ExcalidrawArrowElement,\n ExcalidrawBindableElement,\n ExcalidrawElement,\n ExcalidrawFrameElement,\n ExcalidrawFreeDrawElement,\n ExcalidrawGenericElement,\n ExcalidrawIframeLikeElement,\n ExcalidrawImageElement,\n ExcalidrawLinearElement,\n ExcalidrawMagicFrameElement,\n ExcalidrawSelectionElement,\n ExcalidrawTextElement,\n FileId,\n FontFamilyValues,\n NonDeletedSceneElementsMap,\n TextAlign,\n VerticalAlign,\n} from \"./types\";\n\nexport type ValidLinearElement = {\n type: \"arrow\" | \"line\";\n x: number;\n y: number;\n label?: {\n text: string;\n fontSize?: number;\n fontFamily?: FontFamilyValues;\n textAlign?: TextAlign;\n verticalAlign?: VerticalAlign;\n } & MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\n end?:\n | (\n | (\n | {\n type: Exclude<\n ExcalidrawBindableElement[\"type\"],\n | \"image\"\n | \"text\"\n | \"frame\"\n | \"magicframe\"\n | \"embeddable\"\n | \"iframe\"\n >;\n id?: ExcalidrawGenericElement[\"id\"];\n }\n | {\n id: ExcalidrawGenericElement[\"id\"];\n type?: Exclude<\n ExcalidrawBindableElement[\"type\"],\n | \"image\"\n | \"text\"\n | \"frame\"\n | \"magicframe\"\n | \"embeddable\"\n | \"iframe\"\n >;\n }\n )\n | ((\n | {\n type: \"text\";\n text: string;\n }\n | {\n type?: \"text\";\n id: ExcalidrawTextElement[\"id\"];\n text: string;\n }\n ) &\n Partial<ExcalidrawTextElement>)\n ) &\n MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\n start?:\n | (\n | (\n | {\n type: Exclude<\n ExcalidrawBindableElement[\"type\"],\n | \"image\"\n | \"text\"\n | \"frame\"\n | \"magicframe\"\n | \"embeddable\"\n | \"iframe\"\n >;\n id?: ExcalidrawGenericElement[\"id\"];\n }\n | {\n id: ExcalidrawGenericElement[\"id\"];\n type?: Exclude<\n ExcalidrawBindableElement[\"type\"],\n | \"image\"\n | \"text\"\n | \"frame\"\n | \"magicframe\"\n | \"embeddable\"\n | \"iframe\"\n >;\n }\n )\n | ((\n | {\n type: \"text\";\n text: string;\n }\n | {\n type?: \"text\";\n id: ExcalidrawTextElement[\"id\"];\n text: string;\n }\n ) &\n Partial<ExcalidrawTextElement>)\n ) &\n MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\n} & Partial<ExcalidrawLinearElement>;\n\nexport type ValidContainer =\n | {\n type: Exclude<ExcalidrawGenericElement[\"type\"], \"selection\">;\n id?: ExcalidrawGenericElement[\"id\"];\n label?: {\n text: string;\n fontSize?: number;\n fontFamily?: FontFamilyValues;\n textAlign?: TextAlign;\n verticalAlign?: VerticalAlign;\n } & MarkOptional<ElementConstructorOpts, \"x\" | \"y\">;\n } & ElementConstructorOpts;\n\nexport type ExcalidrawElementSkeleton =\n | Extract<\n Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,\n ExcalidrawIframeLikeElement | ExcalidrawFreeDrawElement\n >\n | ({\n type: Extract<ExcalidrawLinearElement[\"type\"], \"line\">;\n x: number;\n y: number;\n } & Partial<ExcalidrawLinearElement>)\n | ValidContainer\n | ValidLinearElement\n | ({\n type: \"text\";\n text: string;\n x: number;\n y: number;\n id?: ExcalidrawTextElement[\"id\"];\n } & Partial<ExcalidrawTextElement>)\n | ({\n type: Extract<ExcalidrawImageElement[\"type\"], \"image\">;\n x: number;\n y: number;\n fileId: FileId;\n } & Partial<ExcalidrawImageElement>)\n | ({\n type: \"frame\";\n children: readonly ExcalidrawElement[\"id\"][];\n name?: string;\n } & Partial<ExcalidrawFrameElement>)\n | ({\n type: \"magicframe\";\n children: readonly ExcalidrawElement[\"id\"][];\n name?: string;\n } & Partial<ExcalidrawMagicFrameElement>);\n\nconst DEFAULT_LINEAR_ELEMENT_PROPS = {\n width: 100,\n height: 0,\n};\n\nconst DEFAULT_DIMENSION = 100;\n\nconst bindTextToContainer = (\n container: ExcalidrawElement,\n textProps: { text: string } & MarkOptional<ElementConstructorOpts, \"x\" | \"y\">,\n scene: Scene,\n) => {\n const textElement: ExcalidrawTextElement = newTextElement({\n x: 0,\n y: 0,\n textAlign: TEXT_ALIGN.CENTER,\n verticalAlign: VERTICAL_ALIGN.MIDDLE,\n ...textProps,\n containerId: container.id,\n strokeColor: textProps.strokeColor || container.strokeColor,\n });\n\n Object.assign(container, {\n boundElements: (container.boundElements || []).concat({\n type: \"text\",\n id: textElement.id,\n }),\n });\n\n redrawTextBoundingBox(textElement, container, scene);\n\n return [container, textElement] as const;\n};\n\nconst bindLinearElementToElement = (\n linearElement: ExcalidrawArrowElement,\n start: ValidLinearElement[\"start\"],\n end: ValidLinearElement[\"end\"],\n elementStore: ElementStore,\n scene: Scene,\n): {\n linearElement: ExcalidrawLinearElement;\n startBoundElement?: ExcalidrawElement;\n endBoundElement?: ExcalidrawElement;\n} => {\n let startBoundElement;\n let endBoundElement;\n\n Object.assign(linearElement, {\n startBinding: linearElement?.startBinding || null,\n endBinding: linearElement.endBinding || null,\n });\n\n if (start) {\n const width = start?.width ?? DEFAULT_DIMENSION;\n const height = start?.height ?? DEFAULT_DIMENSION;\n\n let existingElement;\n if (start.id) {\n existingElement = elementStore.getElement(start.id);\n if (!existingElement) {\n console.error(`No element for start binding with id ${start.id} found`);\n }\n }\n\n const startX = start.x || linearElement.x - width;\n const startY = start.y || linearElement.y - height / 2;\n const startType = existingElement ? existingElement.type : start.type;\n\n if (startType) {\n if (startType === \"text\") {\n let text = \"\";\n if (existingElement && existingElement.type === \"text\") {\n text = existingElement.text;\n } else if (start.type === \"text\") {\n text = start.text;\n }\n if (!text) {\n console.error(\n `No text found for start binding text element for ${linearElement.id}`,\n );\n }\n startBoundElement = newTextElement({\n x: startX,\n y: startY,\n type: \"text\",\n ...existingElement,\n ...start,\n text,\n });\n // to position the text correctly when coordinates not provided\n Object.assign(startBoundElement, {\n x: start.x || linearElement.x - startBoundElement.width,\n y: start.y || linearElement.y - startBoundElement.height / 2,\n });\n } else {\n switch (startType) {\n case \"rectangle\":\n case \"ellipse\":\n case \"diamond\": {\n startBoundElement = newElement({\n x: startX,\n y: startY,\n width,\n height,\n ...existingElement,\n ...start,\n type: startType,\n });\n break;\n }\n default: {\n assertNever(\n linearElement as never,\n `Unhandled element start type \"${start.type}\"`,\n true,\n );\n }\n }\n }\n\n bindBindingElement(\n linearElement,\n startBoundElement as ExcalidrawBindableElement,\n \"orbit\",\n \"start\",\n scene,\n );\n }\n }\n if (end) {\n const height = end?.height ?? DEFAULT_DIMENSION;\n const width = end?.width ?? DEFAULT_DIMENSION;\n\n let existingElement;\n if (end.id) {\n existingElement = elementStore.getElement(end.id);\n if (!existingElement) {\n console.error(`No element for end binding with id ${end.id} found`);\n }\n }\n const endX = end.x || linearElement.x + linearElement.width;\n const endY = end.y || linearElement.y - height / 2;\n const endType = existingElement ? existingElement.type : end.type;\n\n if (endType) {\n if (endType === \"text\") {\n let text = \"\";\n if (existingElement && existingElement.type === \"text\") {\n text = existingElement.text;\n } else if (end.type === \"text\") {\n text = end.text;\n }\n\n if (!text) {\n console.error(\n `No text found for end binding text element for ${linearElement.id}`,\n );\n }\n endBoundElement = newTextElement({\n x: endX,\n y: endY,\n type: \"text\",\n ...existingElement,\n ...end,\n text,\n });\n // to position the text correctly when coordinates not provided\n Object.assign(endBoundElement, {\n y: end.y || linearElement.y - endBoundElement.height / 2,\n });\n } else {\n switch (endType) {\n case \"rectangle\":\n case \"ellipse\":\n case \"diamond\": {\n endBoundElement = newElement({\n x: endX,\n y: endY,\n width,\n height,\n ...existingElement,\n ...end,\n type: endType,\n });\n break;\n }\n default: {\n assertNever(\n linearElement as never,\n `Unhandled element end type \"${endType}\"`,\n true,\n );\n }\n }\n }\n\n bindBindingElement(\n linearElement,\n endBoundElement as ExcalidrawBindableElement,\n \"orbit\",\n \"end\",\n scene,\n );\n }\n }\n\n // Safe check to early return for single point\n if (linearElement.points.length < 2) {\n return {\n linearElement,\n startBoundElement,\n endBoundElement,\n };\n }\n\n // Update start/end points by 0.5 so bindings don't overlap with start/end bound element coordinates.\n const endPointIndex = linearElement.points.length - 1;\n const delta = 0.5;\n\n const newPoints = cloneJSON<readonly LocalPoint[]>(linearElement.points);\n\n // left to right so shift the arrow towards right\n if (\n linearElement.points[endPointIndex][0] >\n linearElement.points[endPointIndex - 1][0]\n ) {\n newPoints[0][0] = delta;\n newPoints[endPointIndex][0] -= delta;\n }\n\n // right to left so shift the arrow towards left\n if (\n linearElement.points[endPointIndex][0] <\n linearElement.points[endPointIndex - 1][0]\n ) {\n newPoints[0][0] = -delta;\n newPoints[endPointIndex][0] += delta;\n }\n // top to bottom so shift the arrow towards top\n if (\n linearElement.points[endPointIndex][1] >\n linearElement.points[endPointIndex - 1][1]\n ) {\n newPoints[0][1] = delta;\n newPoints[endPointIndex][1] -= delta;\n }\n\n // bottom to top so shift the arrow towards bottom\n if (\n linearElement.points[endPointIndex][1] <\n linearElement.points[endPointIndex - 1][1]\n ) {\n newPoints[0][1] = -delta;\n newPoints[endPointIndex][1] += delta;\n }\n\n Object.assign(\n linearElement,\n LinearElementEditor.getNormalizeElementPointsAndCoords({\n ...linearElement,\n points: newPoints,\n }),\n );\n\n return {\n linearElement,\n startBoundElement,\n endBoundElement,\n };\n};\n\nclass ElementStore {\n excalidrawElements = new Map<string, ExcalidrawElement>();\n\n add = (ele?: ExcalidrawElement) => {\n if (!ele) {\n return;\n }\n\n this.excalidrawElements.set(ele.id, ele);\n };\n\n getElements = () => {\n return syncInvalidIndices(Array.from(this.excalidrawElements.values()));\n };\n\n getElementsMap = () => {\n return toBrandedType<NonDeletedSceneElementsMap>(\n arrayToMap(this.getElements()),\n );\n };\n\n getElement = (id: string) => {\n return this.excalidrawElements.get(id);\n };\n}\n\nexport const convertToExcalidrawElements = (\n elementsSkeleton: ExcalidrawElementSkeleton[] | null,\n opts?: { regenerateIds: boolean },\n) => {\n if (!elementsSkeleton) {\n return [];\n }\n const elements = cloneJSON(elementsSkeleton);\n const elementStore = new ElementStore();\n const elementsWithIds = new Map<string, ExcalidrawElementSkeleton>();\n const oldToNewElementIdMap = new Map<string, string>();\n\n // Create individual elements\n for (const element of elements) {\n let excalidrawElement: ExcalidrawElement;\n const originalId = element.id;\n if (opts?.regenerateIds !== false) {\n Object.assign(element, { id: randomId() });\n }\n\n switch (element.type) {\n case \"rectangle\":\n case \"ellipse\":\n case \"diamond\": {\n const width =\n element?.label?.text && element.width === undefined\n ? 0\n : element?.width || DEFAULT_DIMENSION;\n const height =\n element?.label?.text && element.height === undefined\n ? 0\n : element?.height || DEFAULT_DIMENSION;\n excalidrawElement = newElement({\n ...element,\n width,\n height,\n });\n\n break;\n }\n case \"line\": {\n const width = element.width || DEFAULT_LINEAR_ELEMENT_PROPS.width;\n const height = element.height || DEFAULT_LINEAR_ELEMENT_PROPS.height;\n excalidrawElement = newLinearElement({\n width,\n height,\n points: [pointFrom(0, 0), pointFrom(width, height)],\n ...element,\n });\n\n break;\n }\n case \"arrow\": {\n const width = element.width || DEFAULT_LINEAR_ELEMENT_PROPS.width;\n const height = element.height || DEFAULT_LINEAR_ELEMENT_PROPS.height;\n excalidrawElement = newArrowElement({\n width,\n height,\n endArrowhead: \"arrow\",\n points: [pointFrom(0, 0), pointFrom(width, height)],\n ...element,\n type: \"arrow\",\n });\n\n Object.assign(\n excalidrawElement,\n getSizeFromPoints(excalidrawElement.points),\n );\n break;\n }\n case \"text\": {\n const fontFamily = element?.fontFamily || DEFAULT_FONT_FAMILY;\n const fontSize = element?.fontSize || DEFAULT_FONT_SIZE;\n const lineHeight = element?.lineHeight || getLineHeight(fontFamily);\n const text = element.text ?? \"\";\n const normalizedText = normalizeText(text);\n const metrics = measureText(\n normalizedText,\n getFontString({ fontFamily, fontSize }),\n lineHeight,\n );\n\n excalidrawElement = newTextElement({\n width: metrics.width,\n height: metrics.height,\n fontFamily,\n fontSize,\n ...element,\n });\n break;\n }\n case \"image\": {\n excalidrawElement = newImageElement({\n width: element?.width || DEFAULT_DIMENSION,\n height: element?.height || DEFAULT_DIMENSION,\n ...element,\n });\n\n break;\n }\n case \"frame\": {\n excalidrawElement = newFrameElement({\n x: 0,\n y: 0,\n ...element,\n });\n break;\n }\n case \"magicframe\": {\n excalidrawElement = newMagicFrameElement({\n x: 0,\n y: 0,\n ...element,\n });\n break;\n }\n case \"freedraw\":\n case \"iframe\":\n case \"embeddable\": {\n excalidrawElement = element;\n break;\n }\n\n default: {\n excalidrawElement = element;\n assertNever(\n element,\n `Unhandled element type \"${(element as any).type}\"`,\n true,\n );\n }\n }\n const existingElement = elementStore.getElement(excalidrawElement.id);\n if (existingElement) {\n console.error(`Duplicate id found for ${excalidrawElement.id}`);\n } else {\n elementStore.add(excalidrawElement);\n elementsWithIds.set(excalidrawElement.id, element);\n if (originalId) {\n oldToNewElementIdMap.set(originalId, excalidrawElement.id);\n }\n }\n }\n\n const elementsMap = elementStore.getElementsMap();\n // we don't have a real scene, so we just use a temp scene to query and mutate elements\n const scene = new Scene(elementsMap);\n\n // Add labels and arrow bindings\n for (const [id, element] of elementsWithIds) {\n const excalidrawElement = elementStore.getElement(id)!;\n\n switch (element.type) {\n case \"rectangle\":\n case \"ellipse\":\n case \"diamond\":\n case \"arrow\": {\n if (element.label?.text) {\n let [container, text] = bindTextToContainer(\n excalidrawElement,\n element?.label,\n scene,\n );\n elementStore.add(container);\n elementStore.add(text);\n\n if (isArrowElement(container)) {\n const originalStart =\n element.type === \"arrow\" ? element?.start : undefined;\n const originalEnd =\n element.type === \"arrow\" ? element?.end : undefined;\n if (originalStart && originalStart.id) {\n const newStartId = oldToNewElementIdMap.get(originalStart.id);\n if (newStartId) {\n Object.assign(originalStart, { id: newStartId });\n }\n }\n if (originalEnd && originalEnd.id) {\n const newEndId = oldToNewElementIdMap.get(originalEnd.id);\n if (newEndId) {\n Object.assign(originalEnd, { id: newEndId });\n }\n }\n const { linearElement, startBoundElement, endBoundElement } =\n bindLinearElementToElement(\n container,\n originalStart,\n originalEnd,\n elementStore,\n scene,\n );\n container = linearElement;\n elementStore.add(linearElement);\n elementStore.add(startBoundElement);\n elementStore.add(endBoundElement);\n }\n } else {\n switch (element.type) {\n case \"arrow\": {\n const { start, end } = element;\n if (start && start.id) {\n const newStartId = oldToNewElementIdMap.get(start.id);\n Object.assign(start, { id: newStartId });\n }\n if (end && end.id) {\n const newEndId = oldToNewElementIdMap.get(end.id);\n Object.assign(end, { id: newEndId });\n }\n const { linearElement, startBoundElement, endBoundElement } =\n bindLinearElementToElement(\n excalidrawElement as ExcalidrawArrowElement,\n start,\n end,\n elementStore,\n scene,\n );\n\n elementStore.add(linearElement);\n elementStore.add(startBoundElement);\n elementStore.add(endBoundElement);\n break;\n }\n }\n }\n break;\n }\n }\n }\n\n // Once all the excalidraw elements are created, we can add frames since we\n // need to calculate coordinates and dimensions of frame which is possible after all\n // frame children are processed.\n for (const [id, element] of elementsWithIds) {\n if (element.type !== \"frame\" && element.type !== \"magicframe\") {\n continue;\n }\n const frame = elementStore.getElement(id);\n\n if (!frame) {\n throw new Error(`Excalidraw element with id ${id} doesn't exist`);\n }\n const childrenElements: ExcalidrawElement[] = [];\n\n element.children.forEach((id) => {\n const newElementId = oldToNewElementIdMap.get(id);\n if (!newElementId) {\n throw new Error(`Element with ${id} wasn't mapped correctly`);\n }\n\n const elementInFrame = elementStore.getElement(newElementId);\n if (!elementInFrame) {\n throw new Error(`Frame element with id ${newElementId} doesn't exist`);\n }\n Object.assign(elementInFrame, { frameId: frame.id });\n\n elementInFrame?.boundElements?.forEach((boundElement) => {\n const ele = elementStore.getElement(boundElement.id);\n if (!ele) {\n throw new Error(\n `Bound element with id ${boundElement.id} doesn't exist`,\n );\n }\n Object.assign(ele, { frameId: frame.id });\n childrenElements.push(ele);\n });\n\n childrenElements.push(elementInFrame);\n });\n\n let [minX, minY, maxX, maxY] = getCommonBounds(childrenElements);\n\n const PADDING = 10;\n minX = minX - PADDING;\n minY = minY - PADDING;\n maxX = maxX + PADDING;\n maxY = maxY + PADDING;\n\n const frameX = frame?.x || minX;\n const frameY = frame?.y || minY;\n const frameWidth = frame?.width || maxX - minX;\n const frameHeight = frame?.height || maxY - minY;\n\n Object.assign(frame, {\n x: frameX,\n y: frameY,\n width: frameWidth,\n height: frameHeight,\n });\n if (\n isDevEnv() &&\n element.children.length &&\n (frame?.x || frame?.y || frame?.width || frame?.height)\n ) {\n console.info(\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\",\n );\n }\n }\n\n return elementStore.getElements();\n};\n", "import { arrayToMap, findIndex, findLastIndex } from \"@excalidraw/common\";\n\nimport type { AppState } from \"@excalidraw/excalidraw/types\";\nimport type { GlobalPoint } from \"@excalidraw/math\";\n\nimport { isFrameLikeElement, isTextElement } from \"./typeChecks\";\nimport { getElementsInGroup } from \"./groups\";\nimport { syncMovedIndices } from \"./fractionalIndex\";\nimport { getSelectedElements } from \"./selection\";\nimport { getBoundTextElement, getContainerElement } from \"./textElement\";\nimport { getHoveredElementForBinding } from \"./collision\";\n\nimport type { Scene } from \"./Scene\";\nimport type {\n ExcalidrawArrowElement,\n ExcalidrawElement,\n ExcalidrawFrameLikeElement,\n NonDeletedExcalidrawElement,\n NonDeletedSceneElementsMap,\n Ordered,\n OrderedExcalidrawElement,\n} from \"./types\";\n\nconst isOfTargetFrame = (element: ExcalidrawElement, frameId: string) => {\n return element.frameId === frameId || element.id === frameId;\n};\n\n/**\n * Returns indices of elements to move based on selected elements.\n * Includes contiguous deleted elements that are between two selected elements,\n * e.g.: [0 (selected), 1 (deleted), 2 (deleted), 3 (selected)]\n *\n * Specified elements (elementsToBeMoved) take precedence over\n * appState.selectedElementsIds\n */\nconst getIndicesToMove = (\n elements: readonly ExcalidrawElement[],\n appState: AppState,\n elementsToBeMoved?: readonly ExcalidrawElement[],\n) => {\n let selectedIndices: number[] = [];\n let deletedIndices: number[] = [];\n let includeDeletedIndex = null;\n let index = -1;\n const selectedElementIds = arrayToMap(\n elementsToBeMoved\n ? elementsToBeMoved\n : getSelectedElements(elements, appState, {\n includeBoundTextElement: true,\n includeElementsInFrames: true,\n }),\n );\n while (++index < elements.length) {\n const element = elements[index];\n if (selectedElementIds.get(element.id)) {\n if (deletedIndices.length) {\n selectedIndices = selectedIndices.concat(deletedIndices);\n deletedIndices = [];\n }\n selectedIndices.push(index);\n includeDeletedIndex = index + 1;\n } else if (element.isDeleted && includeDeletedIndex === index) {\n includeDeletedIndex = index + 1;\n deletedIndices.push(index);\n } else {\n deletedIndices = [];\n }\n }\n return selectedIndices;\n};\n\nconst toContiguousGroups = (array: number[]) => {\n let cursor = 0;\n return array.reduce((acc, value, index) => {\n if (index > 0 && array[index - 1] !== value - 1) {\n cursor = ++cursor;\n }\n (acc[cursor] || (acc[cursor] = [])).push(value);\n return acc;\n }, [] as number[][]);\n};\n\n/**\n * @returns index of target element, consindering tightly-bound elements\n * (currently non-linear elements bound to a container) as a one unit.\n * If no binding present, returns `undefined`.\n */\nconst getTargetIndexAccountingForBinding = (\n nextElement: ExcalidrawElement,\n elements: readonly ExcalidrawElement[],\n direction: \"left\" | \"right\",\n scene: Scene,\n) => {\n if (\"containerId\" in nextElement && nextElement.containerId) {\n // TODO: why not to get the container from the nextElements?\n const containerElement = scene.getElement(nextElement.containerId);\n if (containerElement) {\n return direction === \"left\"\n ? Math.min(\n elements.indexOf(containerElement),\n elements.indexOf(nextElement),\n )\n : Math.max(\n elements.indexOf(containerElement),\n elements.indexOf(nextElement),\n );\n }\n } else {\n const boundElementId = nextElement.boundElements?.find(\n (binding) => binding.type !== \"arrow\",\n )?.id;\n if (boundElementId) {\n const boundTextElement = scene.getElement(boundElementId);\n if (boundTextElement) {\n return direction === \"left\"\n ? Math.min(\n elements.indexOf(boundTextElement),\n elements.indexOf(nextElement),\n )\n : Math.max(\n elements.indexOf(boundTextElement),\n elements.indexOf(nextElement),\n );\n }\n }\n }\n};\n\nconst getContiguousFrameRangeElements = (\n allElements: readonly ExcalidrawElement[],\n frameId: ExcalidrawFrameLikeElement[\"id\"],\n) => {\n let rangeStart = -1;\n let rangeEnd = -1;\n allElements.forEach((element, index) => {\n if (isOfTargetFrame(element, frameId)) {\n if (rangeStart === -1) {\n rangeStart = index;\n }\n rangeEnd = index;\n }\n });\n if (rangeStart === -1) {\n return [];\n }\n return allElements.slice(rangeStart, rangeEnd + 1);\n};\n\n/**\n * Moves the arrow element above any bindable elements it intersects with or\n * hovers over.\n */\nexport const moveArrowAboveBindable = (\n point: GlobalPoint,\n arrow: ExcalidrawArrowElement,\n elements: readonly Ordered<NonDeletedExcalidrawElement>[],\n elementsMap: NonDeletedSceneElementsMap,\n scene: Scene,\n): readonly OrderedExcalidrawElement[] => {\n const hoveredElement = getHoveredElementForBinding(\n point,\n elements,\n elementsMap,\n );\n\n if (!hoveredElement) {\n return elements;\n }\n\n const boundTextElement = getBoundTextElement(hoveredElement, elementsMap);\n const containerElement = isTextElement(hoveredElement)\n ? getContainerElement(hoveredElement, elementsMap)\n : null;\n\n const bindableIds = [\n hoveredElement.id,\n boundTextElement?.id,\n containerElement?.id,\n ].filter((id): id is NonDeletedExcalidrawElement[\"id\"] => !!id);\n const bindableIdx = elements.findIndex((el) => bindableIds.includes(el.id));\n const arrowIdx = elements.findIndex((el) => el.id === arrow.id);\n\n if (arrowIdx !== -1 && bindableIdx !== -1 && arrowIdx < bindableIdx) {\n const updatedElements = Array.from(elements);\n const arrow = updatedElements.splice(arrowIdx, 1)[0];\n updatedElements.splice(bindableIdx, 0, arrow);\n\n scene.replaceAllElements(updatedElements);\n }\n\n return elements;\n};\n\n/**\n * Returns next candidate index that's available to be moved to. Currently that\n * is a non-deleted element, and not inside a group (unless we're editing it).\n */\nconst getTargetIndex = (\n appState: AppState,\n elements: readonly ExcalidrawElement[],\n boundaryIndex: number,\n direction: \"left\" | \"right\",\n /**\n * Frame id if moving frame children.\n * If whole frame (including all children) is being moved, supply `null`.\n */\n containingFrame: ExcalidrawFrameLikeElement[\"id\"] | null,\n scene: Scene,\n) => {\n const sourceElement = elements[boundaryIndex];\n\n const indexFilter = (element: ExcalidrawElement) => {\n if (element.isDeleted) {\n return false;\n }\n if (containingFrame) {\n return element.frameId === containingFrame;\n }\n // if we're editing group, find closest sibling irrespective of whether\n // there's a different-group element between them (for legacy reasons)\n if (appState.editingGroupId) {\n return element.groupIds.includes(appState.editingGroupId);\n }\n return true;\n };\n\n const candidateIndex =\n direction === \"left\"\n ? findLastIndex(\n elements,\n (el) => indexFilter(el),\n Math.max(0, boundaryIndex - 1),\n )\n : findIndex(elements, (el) => indexFilter(el), boundaryIndex + 1);\n\n const nextElement = elements[candidateIndex];\n\n if (!nextElement) {\n return -1;\n }\n\n if (appState.editingGroupId) {\n if (\n // candidate element is a sibling in current editing group \u2192 return\n sourceElement?.groupIds.join(\"\") === nextElement?.groupIds.join(\"\")\n ) {\n return (\n getTargetIndexAccountingForBinding(\n nextElement,\n elements,\n direction,\n scene,\n ) ?? candidateIndex\n );\n } else if (!nextElement?.groupIds.includes(appState.editingGroupId)) {\n // candidate element is outside current editing group \u2192 prevent\n return -1;\n }\n }\n\n if (\n !containingFrame &&\n (nextElement.frameId || isFrameLikeElement(nextElement))\n ) {\n const frameElements = getContiguousFrameRangeElements(\n elements,\n nextElement.frameId || nextElement.id,\n );\n return direction === \"left\"\n ? elements.indexOf(frameElements[0])\n : elements.indexOf(frameElements[frameElements.length - 1]);\n }\n\n if (!nextElement.groupIds.length) {\n return (\n getTargetIndexAccountingForBinding(\n nextElement,\n elements,\n direction,\n scene,\n ) ?? candidateIndex\n );\n }\n\n const siblingGroupId = appState.editingGroupId\n ? nextElement.groupIds[\n nextElement.groupIds.indexOf(appState.editingGroupId) - 1\n ]\n : nextElement.groupIds[nextElement.groupIds.length - 1];\n\n const elementsInSiblingGroup = getElementsInGroup(elements, siblingGroupId);\n\n if (elementsInSiblingGroup.length) {\n // assumes getElementsInGroup() returned elements are sorted\n // by zIndex (ascending)\n return direction === \"left\"\n ? elements.indexOf(elementsInSiblingGroup[0])\n : elements.indexOf(\n elementsInSiblingGroup[elementsInSiblingGroup.length - 1],\n );\n }\n\n return candidateIndex;\n};\n\nconst getTargetElementsMap = <T extends ExcalidrawElement>(\n elements: readonly T[],\n indices: number[],\n) => {\n return indices.reduce((acc, index) => {\n const element = elements[index];\n acc.set(element.id, element);\n return acc;\n }, new Map<string, ExcalidrawElement>());\n};\n\nconst shiftElementsByOne = (\n elements: readonly ExcalidrawElement[],\n appState: AppState,\n direction: \"left\" | \"right\",\n scene: Scene,\n) => {\n const indicesToMove = getIndicesToMove(elements, appState);\n const targetElementsMap = getTargetElementsMap(elements, indicesToMove);\n\n let groupedIndices = toContiguousGroups(indicesToMove);\n\n if (direction === \"right\") {\n groupedIndices = groupedIndices.reverse();\n }\n\n const selectedFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>(\n indicesToMove\n .filter((idx) => isFrameLikeElement(elements[idx]))\n .map((idx) => elements[idx].id),\n );\n\n groupedIndices.forEach((indices, i) => {\n const leadingIndex = indices[0];\n const trailingIndex = indices[indices.length - 1];\n const boundaryIndex = direction === \"left\" ? leadingIndex : trailingIndex;\n\n const containingFrame = indices.some((idx) => {\n const el = elements[idx];\n return el.frameId && selectedFrames.has(el.frameId);\n })\n ? null\n : elements[boundaryIndex]?.frameId;\n\n const targetIndex = getTargetIndex(\n appState,\n elements,\n boundaryIndex,\n direction,\n containingFrame,\n scene,\n );\n\n if (targetIndex === -1 || boundaryIndex === targetIndex) {\n return;\n }\n\n const leadingElements =\n direction === \"left\"\n ? elements.slice(0, targetIndex)\n : elements.slice(0, leadingIndex);\n const targetElements = elements.slice(leadingIndex, trailingIndex + 1);\n const displacedElements =\n direction === \"left\"\n ? elements.slice(targetIndex, leadingIndex)\n : elements.slice(trailingIndex + 1, targetIndex + 1);\n const trailingElements =\n direction === \"left\"\n ? elements.slice(trailingIndex + 1)\n : elements.slice(targetIndex + 1);\n\n elements =\n direction === \"left\"\n ? [\n ...leadingElements,\n ...targetElements,\n ...displacedElements,\n ...trailingElements,\n ]\n : [\n ...leadingElements,\n ...displacedElements,\n ...targetElements,\n ...trailingElements,\n ];\n });\n\n syncMovedIndices(elements, targetElementsMap);\n\n return elements;\n};\n\nconst shiftElementsToEnd = (\n elements: readonly ExcalidrawElement[],\n appState: AppState,\n direction: \"left\" | \"right\",\n containingFrame: ExcalidrawFrameLikeElement[\"id\"] | null,\n elementsToBeMoved?: readonly ExcalidrawElement[],\n) => {\n const indicesToMove = getIndicesToMove(elements, appState, elementsToBeMoved);\n const targetElementsMap = getTargetElementsMap(elements, indicesToMove);\n const displacedElements: ExcalidrawElement[] = [];\n\n let leadingIndex: number;\n let trailingIndex: number;\n if (direction === \"left\") {\n if (containingFrame) {\n leadingIndex = findIndex(elements, (el) =>\n isOfTargetFrame(el, containingFrame),\n );\n } else if (appState.editingGroupId) {\n const groupElements = getElementsInGroup(\n elements,\n appState.editingGroupId,\n );\n if (!groupElements.length) {\n return elements;\n }\n leadingIndex = elements.indexOf(groupElements[0]);\n } else {\n leadingIndex = 0;\n }\n\n trailingIndex = indicesToMove[indicesToMove.length - 1];\n } else {\n if (containingFrame) {\n trailingIndex = findLastIndex(elements, (el) =>\n isOfTargetFrame(el, containingFrame),\n );\n } else if (appState.editingGroupId) {\n const groupElements = getElementsInGroup(\n elements,\n appState.editingGroupId,\n );\n if (!groupElements.length) {\n return elements;\n }\n trailingIndex = elements.indexOf(groupElements[groupElements.length - 1]);\n } else {\n trailingIndex = elements.length - 1;\n }\n\n leadingIndex = indicesToMove[0];\n }\n\n if (leadingIndex === -1) {\n leadingIndex = 0;\n }\n\n for (let index = leadingIndex; index < trailingIndex + 1; index++) {\n if (!indicesToMove.includes(index)) {\n displacedElements.push(elements[index]);\n }\n }\n\n const targetElements = Array.from(targetElementsMap.values());\n const leadingElements = elements.slice(0, leadingIndex);\n const trailingElements = elements.slice(trailingIndex + 1);\n const nextElements =\n direction === \"left\"\n ? [\n ...leadingElements,\n ...targetElements,\n ...displacedElements,\n ...trailingElements,\n ]\n : [\n ...leadingElements,\n ...displacedElements,\n ...targetElements,\n ...trailingElements,\n ];\n\n syncMovedIndices(nextElements, targetElementsMap);\n\n return nextElements;\n};\n\nfunction shiftElementsAccountingForFrames(\n allElements: readonly ExcalidrawElement[],\n appState: AppState,\n direction: \"left\" | \"right\",\n shiftFunction: (\n elements: readonly ExcalidrawElement[],\n appState: AppState,\n direction: \"left\" | \"right\",\n containingFrame: ExcalidrawFrameLikeElement[\"id\"] | null,\n elementsToBeMoved?: readonly ExcalidrawElement[],\n ) => ExcalidrawElement[] | readonly ExcalidrawElement[],\n) {\n const elementsToMove = arrayToMap(\n getSelectedElements(allElements, appState, {\n includeBoundTextElement: true,\n includeElementsInFrames: true,\n }),\n );\n\n const frameAwareContiguousElementsToMove: {\n regularElements: ExcalidrawElement[];\n frameChildren: Map<ExcalidrawFrameLikeElement[\"id\"], ExcalidrawElement[]>;\n } = { regularElements: [], frameChildren: new Map() };\n\n const fullySelectedFrames = new Set<ExcalidrawFrameLikeElement[\"id\"]>();\n\n for (const element of allElements) {\n if (elementsToMove.has(element.id) && isFrameLikeElement(element)) {\n fullySelectedFrames.add(element.id);\n }\n }\n\n for (const element of allElements) {\n if (elementsToMove.has(element.id)) {\n if (\n isFrameLikeElement(element) ||\n (element.frameId && fullySelectedFrames.has(element.frameId))\n ) {\n frameAwareContiguousElementsToMove.regularElements.push(element);\n } else if (!element.frameId) {\n frameAwareContiguousElementsToMove.regularElements.push(element);\n } else {\n const frameChildren =\n frameAwareContiguousElementsToMove.frameChildren.get(\n element.frameId,\n ) || [];\n frameChildren.push(element);\n frameAwareContiguousElementsToMove.frameChildren.set(\n element.frameId,\n frameChildren,\n );\n }\n }\n }\n\n let nextElements = allElements;\n\n const frameChildrenSets = Array.from(\n frameAwareContiguousElementsToMove.frameChildren.entries(),\n );\n\n for (const [frameId, children] of frameChildrenSets) {\n nextElements = shiftFunction(\n allElements,\n appState,\n direction,\n frameId,\n children,\n );\n }\n\n return shiftFunction(\n nextElements,\n appState,\n direction,\n null,\n frameAwareContiguousElementsToMove.regularElements,\n );\n}\n\n// public API\n// -----------------------------------------------------------------------------\n\nexport const moveOneLeft = (\n allElements: readonly ExcalidrawElement[],\n appState: AppState,\n scene: Scene,\n) => {\n return shiftElementsByOne(allElements, appState, \"left\", scene);\n};\n\nexport const moveOneRight = (\n allElements: readonly ExcalidrawElement[],\n appState: AppState,\n scene: Scene,\n) => {\n return shiftElementsByOne(allElements, appState, \"right\", scene);\n};\n\nexport const moveAllLeft = (\n allElements: readonly ExcalidrawElement[],\n appState: AppState,\n) => {\n return shiftElementsAccountingForFrames(\n allElements,\n appState,\n \"left\",\n shiftElementsToEnd,\n );\n};\n\nexport const moveAllRight = (\n allElements: readonly ExcalidrawElement[],\n appState: AppState,\n) => {\n return shiftElementsAccountingForFrames(\n allElements,\n appState,\n \"right\",\n shiftElementsToEnd,\n );\n};\n", "import { toIterable } from \"@excalidraw/common\";\n\nimport { isInvisiblySmallElement } from \"./sizeHelpers\";\n\nimport type {\n ExcalidrawElement,\n NonDeletedExcalidrawElement,\n NonDeleted,\n ElementsMapOrArray,\n} from \"./types\";\n\n/**\n * @deprecated unsafe, use hashElementsVersion instead\n */\nexport const getSceneVersion = (elements: readonly ExcalidrawElement[]) =>\n elements.reduce((acc, el) => acc + el.version, 0);\n\n/**\n * Hashes elements' versionNonce (using djb2 algo). Order of elements matters.\n */\nexport const hashElementsVersion = (elements: ElementsMapOrArray): number => {\n let hash = 5381;\n for (const element of toIterable(elements)) {\n hash = (hash << 5) + hash + element.versionNonce;\n }\n return hash >>> 0; // Ensure unsigned 32-bit integer\n};\n\n// string hash function (using djb2). Not cryptographically secure, use only\n// for versioning and such.\n// note: hashes individual code units (not code points),\n// but for hashing purposes this is fine as it iterates through every code unit\n// (as such, no need to encode to byte string first)\nexport const hashString = (s: string): number => {\n let hash: number = 5381;\n for (let i = 0; i < s.length; i++) {\n const char: number = s.charCodeAt(i);\n hash = (hash << 5) + hash + char;\n }\n return hash >>> 0; // Ensure unsigned 32-bit integer\n};\n\nexport const getVisibleElements = (elements: readonly ExcalidrawElement[]) =>\n elements.filter(\n (el) => !el.isDeleted && !isInvisiblySmallElement(el),\n ) as readonly NonDeletedExcalidrawElement[];\n\nexport const getNonDeletedElements = <T extends ExcalidrawElement>(\n elements: readonly T[],\n) =>\n elements.filter((element) => !element.isDeleted) as readonly NonDeleted<T>[];\n\nexport const isNonDeletedElement = <T extends ExcalidrawElement>(\n element: T,\n): element is NonDeleted<T> => !element.isDeleted;\n\nexport * from \"./align\";\nexport * from \"./binding\";\nexport * from \"./bounds\";\nexport * from \"./collision\";\nexport * from \"./comparisons\";\nexport * from \"./containerCache\";\nexport * from \"./cropElement\";\nexport * from \"./delta\";\nexport * from \"./distance\";\nexport * from \"./distribute\";\nexport * from \"./dragElements\";\nexport * from \"./duplicate\";\nexport * from \"./elbowArrow\";\nexport * from \"./elementLink\";\nexport * from \"./embeddable\";\nexport * from \"./flowchart\";\nexport * from \"./fractionalIndex\";\nexport * from \"./frame\";\nexport * from \"./groups\";\nexport * from \"./heading\";\nexport * from \"./image\";\nexport * from \"./linearElementEditor\";\nexport * from \"./mutateElement\";\nexport * from \"./newElement\";\nexport * from \"./positionElementsOnGrid\";\nexport * from \"./renderElement\";\nexport * from \"./resizeElements\";\nexport * from \"./resizeTest\";\nexport * from \"./Scene\";\nexport * from \"./selection\";\nexport * from \"./shape\";\nexport * from \"./showSelectedShapeActions\";\nexport * from \"./sizeHelpers\";\nexport * from \"./sortElements\";\nexport * from \"./store\";\nexport * from \"./textElement\";\nexport * from \"./textMeasurements\";\nexport * from \"./textWrapping\";\nexport * from \"./transform\";\nexport * from \"./transformHandles\";\nexport * from \"./typeChecks\";\nexport * from \"./utils\";\nexport * from \"./zindex\";\n", "import { getVisibleElements } from \"@excalidraw/element\";\nimport {\n sceneCoordsToViewportCoords,\n viewportCoordsToSceneCoords,\n} from \"@excalidraw/common\";\n\nimport { getClosestElementBounds } from \"@excalidraw/element\";\n\nimport { getCommonBounds } from \"@excalidraw/element\";\n\nimport type { ExcalidrawElement } from \"@excalidraw/element/types\";\n\nimport type { AppState, Offsets, PointerCoords, Zoom } from \"../types\";\n\nconst isOutsideViewPort = (appState: AppState, cords: Array<number>) => {\n const [x1, y1, x2, y2] = cords;\n const { x: viewportX1, y: viewportY1 } = sceneCoordsToViewportCoords(\n { sceneX: x1, sceneY: y1 },\n appState,\n );\n const { x: viewportX2, y: viewportY2 } = sceneCoordsToViewportCoords(\n { sceneX: x2, sceneY: y2 },\n appState,\n );\n return (\n viewportX2 - viewportX1 > appState.width ||\n viewportY2 - viewportY1 > appState.height\n );\n};\n\nexport const centerScrollOn = ({\n scenePoint,\n viewportDimensions,\n zoom,\n offsets,\n}: {\n scenePoint: PointerCoords;\n viewportDimensions: { height: number; width: number };\n zoom: Zoom;\n offsets?: Offsets;\n}) => {\n let scrollX =\n (viewportDimensions.width - (offsets?.right ?? 0)) / 2 / zoom.value -\n scenePoint.x;\n\n scrollX += (offsets?.left ?? 0) / 2 / zoom.value;\n\n let scrollY =\n (viewportDimensions.height - (offsets?.bottom ?? 0)) / 2 / zoom.value -\n scenePoint.y;\n\n scrollY += (offsets?.top ?? 0) / 2 / zoom.value;\n\n return {\n scrollX,\n scrollY,\n };\n};\n\nexport const calculateScrollCenter = (\n elements: readonly ExcalidrawElement[],\n appState: AppState,\n): { scrollX: number; scrollY: number } => {\n elements = getVisibleElements(elements);\n\n if (!elements.length) {\n return {\n scrollX: 0,\n scrollY: 0,\n };\n }\n let [x1, y1, x2, y2] = getCommonBounds(elements);\n\n if (isOutsideViewPort(appState, [x1, y1, x2, y2])) {\n [x1, y1, x2, y2] = getClosestElementBounds(\n elements,\n viewportCoordsToSceneCoords(\n { clientX: appState.scrollX, clientY: appState.scrollY },\n appState,\n ),\n );\n }\n\n const centerX = (x1 + x2) / 2;\n const centerY = (y1 + y2) / 2;\n\n return centerScrollOn({\n scenePoint: { x: centerX, y: centerY },\n viewportDimensions: { width: appState.width, height: appState.height },\n zoom: appState.zoom,\n });\n};\n", "import { MAX_ZOOM, MIN_ZOOM } from \"@excalidraw/common\";\n\nimport { clamp, round } from \"@excalidraw/math\";\n\nimport type { NormalizedZoomValue } from \"../types\";\n\nexport const getNormalizedZoom = (zoom: number): NormalizedZoomValue => {\n return clamp(round(zoom, 6), MIN_ZOOM, MAX_ZOOM) as NormalizedZoomValue;\n};\n\nexport const getNormalizedGridSize = (gridStep: number) => {\n return clamp(Math.round(gridStep), 1, 100);\n};\n\nexport const getNormalizedGridStep = (gridStep: number) => {\n return clamp(Math.round(gridStep), 1, 100);\n};\n", "import rough from \"roughjs/bin/rough\";\n\nimport {\n DEFAULT_EXPORT_PADDING,\n FRAME_STYLE,\n FONT_FAMILY,\n SVG_NS,\n THEME,\n MIME_TYPES,\n EXPORT_DATA_TYPES,\n arrayToMap,\n distance,\n getFontString,\n toBrandedType,\n applyDarkModeFilter,\n} from \"@excalidraw/common\";\n\nimport { getCommonBounds, getElementAbsoluteCoords } from \"@excalidraw/element\";\n\nimport {\n getInitializedImageElements,\n updateImageCache,\n} from \"@excalidraw/element\";\n\nimport { newElementWith } from \"@excalidraw/element\";\n\nimport { isFrameLikeElement } from \"@excalidraw/element\";\n\nimport {\n getElementsOverlappingFrame,\n getFrameLikeElements,\n getFrameLikeTitle,\n getRootElements,\n} from \"@excalidraw/element\";\n\nimport { syncInvalidIndices } from \"@excalidraw/element\";\n\nimport { type Mutable } from \"@excalidraw/common/utility-types\";\n\nimport { newTextElement } from \"@excalidraw/element\";\n\nimport type { Bounds } from \"@excalidraw/common\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawFrameLikeElement,\n ExcalidrawTextElement,\n NonDeletedExcalidrawElement,\n NonDeletedSceneElementsMap,\n} from \"@excalidraw/element/types\";\n\nimport { getDefaultAppState } from \"../appState\";\nimport { base64ToString, decode, encode, stringToBase64 } from \"../data/encode\";\nimport { serializeAsJSON } from \"../data/json\";\n\nimport { Fonts } from \"../fonts\";\n\nimport { renderStaticScene } from \"../renderer/staticScene\";\nimport { renderSceneToSvg } from \"../renderer/staticSvgScene\";\n\nimport type { RenderableElementsMap } from \"./types\";\n\nimport type { AppState, BinaryFiles } from \"../types\";\n\nconst truncateText = (element: ExcalidrawTextElement, maxWidth: number) => {\n if (element.width <= maxWidth) {\n return element;\n }\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\")!;\n ctx.font = getFontString({\n fontFamily: element.fontFamily,\n fontSize: element.fontSize,\n });\n\n let text = element.text;\n\n const metrics = ctx.measureText(text);\n\n if (metrics.width > maxWidth) {\n // we iterate from the right, removing characters one by one instead\n // of bulding the string up. This assumes that it's more likely\n // your frame names will overflow by not that many characters\n // (if ever), so it sohuld be faster this way.\n for (let i = text.length; i > 0; i--) {\n const newText = `${text.slice(0, i)}...`;\n if (ctx.measureText(newText).width <= maxWidth) {\n text = newText;\n break;\n }\n }\n }\n return newElementWith(element, { text, width: maxWidth });\n};\n\n/**\n * When exporting frames, we need to render frame labels which are currently\n * being rendered in DOM when editing. Adding the labels as regular text\n * elements seems like a simple hack. In the future we'll want to move to\n * proper canvas rendering, even within editor (instead of DOM).\n */\nconst addFrameLabelsAsTextElements = (\n elements: readonly NonDeletedExcalidrawElement[],\n opts: Pick<AppState, \"exportWithDarkMode\">,\n) => {\n const nextElements: NonDeletedExcalidrawElement[] = [];\n for (const element of elements) {\n if (isFrameLikeElement(element)) {\n let textElement: Mutable<ExcalidrawTextElement> = newTextElement({\n x: element.x,\n y: element.y - FRAME_STYLE.nameOffsetY,\n fontFamily: FONT_FAMILY.Helvetica,\n fontSize: FRAME_STYLE.nameFontSize,\n lineHeight:\n FRAME_STYLE.nameLineHeight as ExcalidrawTextElement[\"lineHeight\"],\n strokeColor: opts.exportWithDarkMode\n ? FRAME_STYLE.nameColorDarkTheme\n : FRAME_STYLE.nameColorLightTheme,\n text: getFrameLikeTitle(element),\n });\n textElement.y -= textElement.height;\n\n textElement = truncateText(textElement, element.width);\n\n nextElements.push(textElement);\n }\n nextElements.push(element);\n }\n\n return nextElements;\n};\n\nconst getFrameRenderingConfig = (\n exportingFrame: ExcalidrawFrameLikeElement | null,\n frameRendering: AppState[\"frameRendering\"] | null,\n): AppState[\"frameRendering\"] => {\n frameRendering = frameRendering || getDefaultAppState().frameRendering;\n return {\n enabled: exportingFrame ? true : frameRendering.enabled,\n outline: exportingFrame ? false : frameRendering.outline,\n name: exportingFrame ? false : frameRendering.name,\n clip: exportingFrame ? true : frameRendering.clip,\n };\n};\n\nconst prepareElementsForRender = ({\n elements,\n exportingFrame,\n frameRendering,\n exportWithDarkMode,\n}: {\n elements: readonly ExcalidrawElement[];\n exportingFrame: ExcalidrawFrameLikeElement | null | undefined;\n frameRendering: AppState[\"frameRendering\"];\n exportWithDarkMode: AppState[\"exportWithDarkMode\"];\n}) => {\n let nextElements: readonly ExcalidrawElement[];\n\n if (exportingFrame) {\n nextElements = getElementsOverlappingFrame(elements, exportingFrame);\n } else if (frameRendering.enabled && frameRendering.name) {\n nextElements = addFrameLabelsAsTextElements(elements, {\n exportWithDarkMode,\n });\n } else {\n nextElements = elements;\n }\n\n return nextElements;\n};\n\nexport const exportToCanvas = async (\n elements: readonly NonDeletedExcalidrawElement[],\n appState: AppState,\n files: BinaryFiles,\n {\n exportBackground,\n exportPadding = DEFAULT_EXPORT_PADDING,\n viewBackgroundColor,\n exportingFrame,\n }: {\n exportBackground: boolean;\n exportPadding?: number;\n viewBackgroundColor: string;\n exportingFrame?: ExcalidrawFrameLikeElement | null;\n },\n createCanvas: (\n width: number,\n height: number,\n ) => { canvas: HTMLCanvasElement; scale: number } = (width, height) => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width * appState.exportScale;\n canvas.height = height * appState.exportScale;\n return { canvas, scale: appState.exportScale };\n },\n loadFonts: () => Promise<void> = async () => {\n await Fonts.loadElementsFonts(elements);\n },\n) => {\n // load font faces before continuing, by default leverages browsers' [FontFace API](https://developer.mozilla.org/en-US/docs/Web/API/FontFace)\n await loadFonts();\n\n const frameRendering = getFrameRenderingConfig(\n exportingFrame ?? null,\n appState.frameRendering ?? null,\n );\n // for canvas export, don't clip if exporting a specific frame as it would\n // clip the corners of the content\n if (exportingFrame) {\n frameRendering.clip = false;\n }\n\n const elementsForRender = prepareElementsForRender({\n elements,\n exportingFrame,\n exportWithDarkMode: appState.exportWithDarkMode,\n frameRendering,\n });\n\n if (exportingFrame) {\n exportPadding = 0;\n }\n\n const [minX, minY, width, height] = getCanvasSize(\n exportingFrame ? [exportingFrame] : getRootElements(elementsForRender),\n exportPadding,\n );\n\n const { canvas, scale = 1 } = createCanvas(width, height);\n\n const defaultAppState = getDefaultAppState();\n\n const { imageCache } = await updateImageCache({\n imageCache: new Map(),\n fileIds: getInitializedImageElements(elementsForRender).map(\n (element) => element.fileId,\n ),\n files,\n });\n\n renderStaticScene({\n canvas,\n rc: rough.canvas(canvas),\n elementsMap: toBrandedType<RenderableElementsMap>(\n arrayToMap(elementsForRender),\n ),\n allElementsMap: toBrandedType<NonDeletedSceneElementsMap>(\n arrayToMap(syncInvalidIndices(elements)),\n ),\n visibleElements: elementsForRender,\n scale,\n appState: {\n ...appState,\n frameRendering,\n viewBackgroundColor: exportBackground ? viewBackgroundColor : null,\n scrollX: -minX + exportPadding,\n scrollY: -minY + exportPadding,\n zoom: defaultAppState.zoom,\n shouldCacheIgnoreZoom: false,\n theme: appState.exportWithDarkMode ? THEME.DARK : THEME.LIGHT,\n },\n renderConfig: {\n canvasBackgroundColor: viewBackgroundColor,\n imageCache,\n renderGrid: false,\n isExporting: true,\n // empty disables embeddable rendering\n embedsValidationStatus: new Map(),\n elementsPendingErasure: new Set(),\n pendingFlowchartNodes: null,\n theme: appState.exportWithDarkMode ? THEME.DARK : THEME.LIGHT,\n },\n });\n\n return canvas;\n};\n\nconst createHTMLComment = (text: string) => {\n // surrounding with spaces to maintain prettified consistency with previous\n // iterations\n // <!-- comment -->\n return document.createComment(` ${text} `);\n};\n\nexport const exportToSvg = async (\n elements: readonly NonDeletedExcalidrawElement[],\n appState: {\n exportBackground: boolean;\n exportPadding?: number;\n exportScale?: number;\n viewBackgroundColor: string;\n exportWithDarkMode?: boolean;\n exportEmbedScene?: boolean;\n frameRendering?: AppState[\"frameRendering\"];\n },\n files: BinaryFiles | null,\n opts?: {\n /**\n * if true, all embeddables passed in will be rendered when possible.\n */\n renderEmbeddables?: boolean;\n exportingFrame?: ExcalidrawFrameLikeElement | null;\n skipInliningFonts?: true;\n reuseImages?: boolean;\n },\n): Promise<SVGSVGElement> => {\n const frameRendering = getFrameRenderingConfig(\n opts?.exportingFrame ?? null,\n appState.frameRendering ?? null,\n );\n\n let {\n exportPadding = DEFAULT_EXPORT_PADDING,\n exportWithDarkMode = false,\n viewBackgroundColor,\n exportScale = 1,\n exportEmbedScene,\n } = appState;\n\n const { exportingFrame = null } = opts || {};\n\n const elementsForRender = prepareElementsForRender({\n elements,\n exportingFrame,\n exportWithDarkMode,\n frameRendering,\n });\n\n if (exportingFrame) {\n exportPadding = 0;\n }\n\n const [minX, minY, width, height] = getCanvasSize(\n exportingFrame ? [exportingFrame] : getRootElements(elementsForRender),\n exportPadding,\n );\n\n const offsetX = -minX + exportPadding;\n const offsetY = -minY + exportPadding;\n\n // ---------------------------------------------------------------------------\n // initialize SVG root element\n // ---------------------------------------------------------------------------\n\n const svgRoot = document.createElementNS(SVG_NS, \"svg\");\n\n svgRoot.setAttribute(\"version\", \"1.1\");\n svgRoot.setAttribute(\"xmlns\", SVG_NS);\n svgRoot.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svgRoot.setAttribute(\"width\", `${width * exportScale}`);\n svgRoot.setAttribute(\"height\", `${height * exportScale}`);\n\n const defsElement = svgRoot.ownerDocument.createElementNS(SVG_NS, \"defs\");\n\n const metadataElement = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"metadata\",\n );\n\n svgRoot.appendChild(createHTMLComment(\"svg-source:excalidraw\"));\n svgRoot.appendChild(metadataElement);\n svgRoot.appendChild(defsElement);\n\n // ---------------------------------------------------------------------------\n // scene embed\n // ---------------------------------------------------------------------------\n\n // we need to serialize the \"original\" elements before we put them through\n // the tempScene hack which duplicates and regenerates ids\n if (exportEmbedScene) {\n try {\n encodeSvgBase64Payload({\n metadataElement,\n // when embedding scene, we want to embed the origionally supplied\n // elements which don't contain the temp frame labels.\n // But it also requires that the exportToSvg is being supplied with\n // only the elements that we're exporting, and no extra.\n payload: serializeAsJSON(elements, appState, files || {}, \"local\"),\n });\n } catch (error: any) {\n console.error(error);\n }\n }\n\n // ---------------------------------------------------------------------------\n // frame clip paths\n // ---------------------------------------------------------------------------\n\n const frameElements = getFrameLikeElements(elements);\n\n if (frameElements.length) {\n const elementsMap = arrayToMap(elements);\n\n for (const frame of frameElements) {\n const clipPath = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"clipPath\",\n );\n\n clipPath.setAttribute(\"id\", frame.id);\n\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(frame, elementsMap);\n const cx = (x2 - x1) / 2 - (frame.x - x1);\n const cy = (y2 - y1) / 2 - (frame.y - y1);\n\n const rect = svgRoot.ownerDocument.createElementNS(SVG_NS, \"rect\");\n rect.setAttribute(\n \"transform\",\n `translate(${frame.x + offsetX} ${frame.y + offsetY}) rotate(${\n frame.angle\n } ${cx} ${cy})`,\n );\n rect.setAttribute(\"width\", `${frame.width}`);\n rect.setAttribute(\"height\", `${frame.height}`);\n\n if (!exportingFrame) {\n rect.setAttribute(\"rx\", `${FRAME_STYLE.radius}`);\n rect.setAttribute(\"ry\", `${FRAME_STYLE.radius}`);\n }\n\n clipPath.appendChild(rect);\n\n defsElement.appendChild(clipPath);\n }\n }\n\n // ---------------------------------------------------------------------------\n // inline font faces\n // ---------------------------------------------------------------------------\n\n const fontFaces = !opts?.skipInliningFonts\n ? await Fonts.generateFontFaceDeclarations(elements)\n : [];\n\n const delimiter = \"\\n \"; // 6 spaces\n\n const style = svgRoot.ownerDocument.createElementNS(SVG_NS, \"style\");\n style.classList.add(\"style-fonts\");\n style.appendChild(\n document.createTextNode(`${delimiter}${fontFaces.join(delimiter)}`),\n );\n\n defsElement.appendChild(style);\n\n // ---------------------------------------------------------------------------\n // background\n // ---------------------------------------------------------------------------\n\n // render background rect\n if (appState.exportBackground && viewBackgroundColor) {\n const rect = svgRoot.ownerDocument.createElementNS(SVG_NS, \"rect\");\n rect.setAttribute(\"x\", \"0\");\n rect.setAttribute(\"y\", \"0\");\n rect.setAttribute(\"width\", `${width}`);\n rect.setAttribute(\"height\", `${height}`);\n rect.setAttribute(\n \"fill\",\n exportWithDarkMode\n ? applyDarkModeFilter(viewBackgroundColor)\n : viewBackgroundColor,\n );\n svgRoot.appendChild(rect);\n }\n\n // ---------------------------------------------------------------------------\n // render elements\n // ---------------------------------------------------------------------------\n\n const rsvg = rough.svg(svgRoot);\n\n const renderEmbeddables = opts?.renderEmbeddables ?? false;\n\n renderSceneToSvg(\n elementsForRender,\n toBrandedType<RenderableElementsMap>(arrayToMap(elementsForRender)),\n rsvg,\n svgRoot,\n files || {},\n {\n offsetX,\n offsetY,\n isExporting: true,\n exportWithDarkMode,\n renderEmbeddables,\n frameRendering,\n canvasBackgroundColor: viewBackgroundColor,\n embedsValidationStatus: renderEmbeddables\n ? new Map(\n elementsForRender\n .filter((element) => isFrameLikeElement(element))\n .map((element) => [element.id, true]),\n )\n : new Map(),\n reuseImages: opts?.reuseImages ?? true,\n theme: exportWithDarkMode ? THEME.DARK : THEME.LIGHT,\n },\n );\n\n // ---------------------------------------------------------------------------\n\n return svgRoot;\n};\n\nexport const encodeSvgBase64Payload = ({\n payload,\n metadataElement,\n}: {\n payload: string;\n metadataElement: SVGMetadataElement;\n}) => {\n const base64 = stringToBase64(\n JSON.stringify(encode({ text: payload })),\n true /* is already byte string */,\n );\n\n metadataElement.appendChild(\n createHTMLComment(`payload-type:${MIME_TYPES.excalidraw}`),\n );\n metadataElement.appendChild(createHTMLComment(\"payload-version:2\"));\n metadataElement.appendChild(createHTMLComment(\"payload-start\"));\n metadataElement.appendChild(document.createTextNode(base64));\n metadataElement.appendChild(createHTMLComment(\"payload-end\"));\n};\n\nexport const decodeSvgBase64Payload = ({ svg }: { svg: string }) => {\n if (svg.includes(`payload-type:${MIME_TYPES.excalidraw}`)) {\n const match = svg.match(\n /<!-- payload-start -->\\s*(.+?)\\s*<!-- payload-end -->/,\n );\n if (!match) {\n throw new Error(\"INVALID\");\n }\n const versionMatch = svg.match(/<!-- payload-version:(\\d+) -->/);\n const version = versionMatch?.[1] || \"1\";\n const isByteString = version !== \"1\";\n\n try {\n const json = base64ToString(match[1], isByteString);\n const encodedData = JSON.parse(json);\n if (!(\"encoded\" in encodedData)) {\n // legacy, un-encoded scene JSON\n if (\n \"type\" in encodedData &&\n encodedData.type === EXPORT_DATA_TYPES.excalidraw\n ) {\n return json;\n }\n throw new Error(\"FAILED\");\n }\n return decode(encodedData);\n } catch (error: any) {\n console.error(error);\n throw new Error(\"FAILED\");\n }\n }\n throw new Error(\"INVALID\");\n};\n\n// calculate smallest area to fit the contents in\nconst getCanvasSize = (\n elements: readonly NonDeletedExcalidrawElement[],\n exportPadding: number,\n): Bounds => {\n const [minX, minY, maxX, maxY] = getCommonBounds(elements);\n const width = distance(minX, maxX) + exportPadding * 2;\n const height = distance(minY, maxY) + exportPadding * 2;\n\n return [minX, minY, width, height];\n};\n\nexport const getExportSize = (\n elements: readonly NonDeletedExcalidrawElement[],\n exportPadding: number,\n scale: number,\n): [number, number] => {\n const [, , width, height] = getCanvasSize(elements, exportPadding).map(\n (dimension) => Math.trunc(dimension * scale),\n );\n\n return [width, height];\n};\n", "import { deflate, inflate } from \"pako\";\n\nimport { encryptData, decryptData } from \"./encryption\";\n\n// -----------------------------------------------------------------------------\n// byte (binary) strings\n// -----------------------------------------------------------------------------\n\n// Buffer-compatible implem.\n//\n// Note that in V8, spreading the uint8array (by chunks) into\n// `String.fromCharCode(...uint8array)` tends to be faster for large\n// strings/buffers, in case perf is needed in the future.\nexport const toByteString = (data: string | Uint8Array | ArrayBuffer) => {\n const bytes =\n typeof data === \"string\"\n ? new TextEncoder().encode(data)\n : data instanceof Uint8Array\n ? data\n : new Uint8Array(data);\n let bstring = \"\";\n for (const byte of bytes) {\n bstring += String.fromCharCode(byte);\n }\n return bstring;\n};\n\nconst byteStringToArrayBuffer = (byteString: string) => {\n const buffer = new ArrayBuffer(byteString.length);\n const bufferView = new Uint8Array(buffer);\n for (let i = 0, len = byteString.length; i < len; i++) {\n bufferView[i] = byteString.charCodeAt(i);\n }\n return buffer;\n};\n\nconst byteStringToString = (byteString: string) => {\n return new TextDecoder(\"utf-8\").decode(byteStringToArrayBuffer(byteString));\n};\n\n// -----------------------------------------------------------------------------\n// base64\n// -----------------------------------------------------------------------------\n\n/**\n * @param isByteString set to true if already byte string to prevent bloat\n * due to reencoding\n */\nexport const stringToBase64 = (str: string, isByteString = false) => {\n return isByteString ? window.btoa(str) : window.btoa(toByteString(str));\n};\n\n// async to align with stringToBase64\nexport const base64ToString = (base64: string, isByteString = false) => {\n return isByteString\n ? window.atob(base64)\n : byteStringToString(window.atob(base64));\n};\n\nexport const base64ToArrayBuffer = (base64: string): ArrayBuffer => {\n if (typeof Buffer !== \"undefined\") {\n // Node.js environment\n return Buffer.from(base64, \"base64\").buffer;\n }\n // Browser environment\n return byteStringToArrayBuffer(atob(base64));\n};\n\n// -----------------------------------------------------------------------------\n// base64url\n// -----------------------------------------------------------------------------\n\nexport const base64urlToString = (str: string) => {\n return window.atob(\n // normalize base64URL to base64\n str\n .replace(/-/g, \"+\")\n .replace(/_/g, \"/\")\n .padEnd(str.length + ((4 - (str.length % 4)) % 4), \"=\"),\n );\n};\n\n// -----------------------------------------------------------------------------\n// text encoding\n// -----------------------------------------------------------------------------\n\ntype EncodedData = {\n encoded: string;\n encoding: \"bstring\";\n /** whether text is compressed (zlib) */\n compressed: boolean;\n /** version for potential migration purposes */\n version?: string;\n};\n\n/**\n * Encodes (and potentially compresses via zlib) text to byte string\n */\nexport const encode = ({\n text,\n compress,\n}: {\n text: string;\n /** defaults to `true`. If compression fails, falls back to bstring alone. */\n compress?: boolean;\n}): EncodedData => {\n let deflated!: string;\n if (compress !== false) {\n try {\n deflated = toByteString(deflate(text));\n } catch (error: any) {\n console.error(\"encode: cannot deflate\", error);\n }\n }\n return {\n version: \"1\",\n encoding: \"bstring\",\n compressed: !!deflated,\n encoded: deflated || toByteString(text),\n };\n};\n\nexport const decode = (data: EncodedData): string => {\n let decoded: string;\n\n switch (data.encoding) {\n case \"bstring\":\n // if compressed, do not double decode the bstring\n decoded = data.compressed\n ? data.encoded\n : byteStringToString(data.encoded);\n break;\n default:\n throw new Error(`decode: unknown encoding \"${data.encoding}\"`);\n }\n\n if (data.compressed) {\n return inflate(new Uint8Array(byteStringToArrayBuffer(decoded)), {\n to: \"string\",\n });\n }\n\n return decoded;\n};\n\n// -----------------------------------------------------------------------------\n// binary encoding\n// -----------------------------------------------------------------------------\n\ntype FileEncodingInfo = {\n /* version 2 is the version we're shipping the initial image support with.\n version 1 was a PR version that a lot of people were using anyway.\n Thus, if there are issues we can check whether they're not using the\n unoffic version */\n version: 1 | 2;\n compression: \"pako@1\" | null;\n encryption: \"AES-GCM\" | null;\n};\n\n// -----------------------------------------------------------------------------\nconst CONCAT_BUFFERS_VERSION = 1;\n/** how many bytes we use to encode how many bytes the next chunk has.\n * Corresponds to DataView setter methods (setUint32, setUint16, etc).\n *\n * NOTE ! values must not be changed, which would be backwards incompatible !\n */\nconst VERSION_DATAVIEW_BYTES = 4;\nconst NEXT_CHUNK_SIZE_DATAVIEW_BYTES = 4;\n// -----------------------------------------------------------------------------\n\nconst DATA_VIEW_BITS_MAP = { 1: 8, 2: 16, 4: 32 } as const;\n\n// getter\nfunction dataView(buffer: Uint8Array, bytes: 1 | 2 | 4, offset: number): number;\n// setter\nfunction dataView(\n buffer: Uint8Array,\n bytes: 1 | 2 | 4,\n offset: number,\n value: number,\n): Uint8Array;\n/**\n * abstraction over DataView that serves as a typed getter/setter in case\n * you're using constants for the byte size and want to ensure there's no\n * discrepenancy in the encoding across refactors.\n *\n * DataView serves for an endian-agnostic handling of numbers in ArrayBuffers.\n */\nfunction dataView(\n buffer: Uint8Array,\n bytes: 1 | 2 | 4,\n offset: number,\n value?: number,\n): Uint8Array | number {\n if (value != null) {\n if (value > Math.pow(2, DATA_VIEW_BITS_MAP[bytes]) - 1) {\n throw new Error(\n `attempting to set value higher than the allocated bytes (value: ${value}, bytes: ${bytes})`,\n );\n }\n const method = `setUint${DATA_VIEW_BITS_MAP[bytes]}` as const;\n new DataView(buffer.buffer)[method](offset, value);\n return buffer;\n }\n const method = `getUint${DATA_VIEW_BITS_MAP[bytes]}` as const;\n return new DataView(buffer.buffer)[method](offset);\n}\n\n// -----------------------------------------------------------------------------\n\n/**\n * Resulting concatenated buffer has this format:\n *\n * [\n * VERSION chunk (4 bytes)\n * LENGTH chunk 1 (4 bytes)\n * DATA chunk 1 (up to 2^32 bits)\n * LENGTH chunk 2 (4 bytes)\n * DATA chunk 2 (up to 2^32 bits)\n * ...\n * ]\n *\n * @param buffers each buffer (chunk) must be at most 2^32 bits large (~4GB)\n */\nconst concatBuffers = (...buffers: Uint8Array[]): Uint8Array<ArrayBuffer> => {\n const bufferView = new Uint8Array(\n VERSION_DATAVIEW_BYTES +\n NEXT_CHUNK_SIZE_DATAVIEW_BYTES * buffers.length +\n buffers.reduce((acc, buffer) => acc + buffer.byteLength, 0),\n );\n\n let cursor = 0;\n\n // as the first chunk we'll encode the version for backwards compatibility\n dataView(bufferView, VERSION_DATAVIEW_BYTES, cursor, CONCAT_BUFFERS_VERSION);\n cursor += VERSION_DATAVIEW_BYTES;\n\n for (const buffer of buffers) {\n dataView(\n bufferView,\n NEXT_CHUNK_SIZE_DATAVIEW_BYTES,\n cursor,\n buffer.byteLength,\n );\n cursor += NEXT_CHUNK_SIZE_DATAVIEW_BYTES;\n\n bufferView.set(buffer, cursor);\n cursor += buffer.byteLength;\n }\n\n return bufferView;\n};\n\n/** can only be used on buffers created via `concatBuffers()` */\nconst splitBuffers = (concatenatedBuffer: Uint8Array) => {\n const buffers = [];\n\n let cursor = 0;\n\n // first chunk is the version\n const version = dataView(\n concatenatedBuffer,\n NEXT_CHUNK_SIZE_DATAVIEW_BYTES,\n cursor,\n );\n // If version is outside of the supported versions, throw an error.\n // This usually means the buffer wasn't encoded using this API, so we'd only\n // waste compute.\n if (version > CONCAT_BUFFERS_VERSION) {\n throw new Error(`invalid version ${version}`);\n }\n\n cursor += VERSION_DATAVIEW_BYTES;\n\n while (true) {\n const chunkSize = dataView(\n concatenatedBuffer,\n NEXT_CHUNK_SIZE_DATAVIEW_BYTES,\n cursor,\n );\n cursor += NEXT_CHUNK_SIZE_DATAVIEW_BYTES;\n\n buffers.push(concatenatedBuffer.slice(cursor, cursor + chunkSize));\n cursor += chunkSize;\n if (cursor >= concatenatedBuffer.byteLength) {\n break;\n }\n }\n\n return buffers;\n};\n\n// helpers for (de)compressing data with JSON metadata including encryption\n// -----------------------------------------------------------------------------\n\n/** @private */\nconst _encryptAndCompress = async (\n data: Uint8Array<ArrayBuffer> | string,\n encryptionKey: string,\n) => {\n const { encryptedBuffer, iv } = await encryptData(\n encryptionKey,\n deflate(data) as Uint8Array<ArrayBuffer>,\n );\n\n return { iv, buffer: new Uint8Array(encryptedBuffer) };\n};\n\n/**\n * The returned buffer has following format:\n * `[]` refers to a buffers wrapper (see `concatBuffers`)\n *\n * [\n * encodingMetadataBuffer,\n * iv,\n * [\n * contentsMetadataBuffer\n * contentsBuffer\n * ]\n * ]\n */\nexport const compressData = async <T extends Record<string, any> = never>(\n dataBuffer: Uint8Array,\n options: {\n encryptionKey: string;\n } & ([T] extends [never]\n ? {\n metadata?: T;\n }\n : {\n metadata: T;\n }),\n): Promise<Uint8Array<ArrayBuffer>> => {\n const fileInfo: FileEncodingInfo = {\n version: 2,\n compression: \"pako@1\",\n encryption: \"AES-GCM\",\n };\n\n const encodingMetadataBuffer = new TextEncoder().encode(\n JSON.stringify(fileInfo),\n );\n\n const contentsMetadataBuffer = new TextEncoder().encode(\n JSON.stringify(options.metadata || null),\n );\n\n const { iv, buffer } = await _encryptAndCompress(\n concatBuffers(contentsMetadataBuffer, dataBuffer),\n options.encryptionKey,\n );\n\n return concatBuffers(encodingMetadataBuffer, iv, buffer);\n};\n\n/** @private */\nconst _decryptAndDecompress = async (\n iv: Uint8Array<ArrayBuffer>,\n decryptedBuffer: Uint8Array<ArrayBuffer>,\n decryptionKey: string,\n isCompressed: boolean,\n) => {\n decryptedBuffer = new Uint8Array(\n await decryptData(iv, decryptedBuffer, decryptionKey),\n );\n\n if (isCompressed) {\n return inflate(decryptedBuffer);\n }\n\n return decryptedBuffer;\n};\n\nexport const decompressData = async <T extends Record<string, any>>(\n bufferView: Uint8Array,\n options: { decryptionKey: string },\n) => {\n // first chunk is encoding metadata (ignored for now)\n const [encodingMetadataBuffer, iv, buffer] = splitBuffers(bufferView);\n\n const encodingMetadata: FileEncodingInfo = JSON.parse(\n new TextDecoder().decode(encodingMetadataBuffer),\n );\n\n try {\n const [contentsMetadataBuffer, contentsBuffer] = splitBuffers(\n await _decryptAndDecompress(\n iv,\n buffer,\n options.decryptionKey,\n !!encodingMetadata.compression,\n ),\n );\n\n const metadata = JSON.parse(\n new TextDecoder().decode(contentsMetadataBuffer),\n ) as T;\n\n return {\n /** metadata source is always JSON so we can decode it here */\n metadata,\n /** data can be anything so the caller must decode it */\n data: contentsBuffer,\n };\n } catch (error: any) {\n console.error(\n `Error during decompressing and decrypting the file.`,\n encodingMetadata,\n );\n throw error;\n }\n};\n\n// -----------------------------------------------------------------------------\n", "import {\n fileOpen as _fileOpen,\n fileSave as _fileSave,\n supported as nativeFileSystemSupported,\n} from \"browser-fs-access\";\n\nimport { EVENT, MIME_TYPES, debounce } from \"@excalidraw/common\";\n\nimport { AbortError } from \"../errors\";\n\nimport { normalizeFile } from \"./blob\";\n\nimport type { FileSystemHandle } from \"browser-fs-access\";\n\ntype FILE_EXTENSION = Exclude<keyof typeof MIME_TYPES, \"binary\">;\n\nconst INPUT_CHANGE_INTERVAL_MS = 5000;\n\nexport const fileOpen = async <M extends boolean | undefined = false>(opts: {\n extensions?: FILE_EXTENSION[];\n description: string;\n multiple?: M;\n}): Promise<M extends false | undefined ? File : File[]> => {\n // an unsafe TS hack, alas not much we can do AFAIK\n type RetType = M extends false | undefined ? File : File[];\n\n const mimeTypes = opts.extensions?.reduce((mimeTypes, type) => {\n mimeTypes.push(MIME_TYPES[type]);\n\n return mimeTypes;\n }, [] as string[]);\n\n const extensions = opts.extensions?.reduce((acc, ext) => {\n if (ext === \"jpg\") {\n return acc.concat(\".jpg\", \".jpeg\");\n }\n return acc.concat(`.${ext}`);\n }, [] as string[]);\n\n const files = await _fileOpen({\n description: opts.description,\n extensions,\n mimeTypes,\n multiple: opts.multiple ?? false,\n legacySetup: (resolve, reject, input) => {\n const scheduleRejection = debounce(reject, INPUT_CHANGE_INTERVAL_MS);\n const focusHandler = () => {\n checkForFile();\n document.addEventListener(EVENT.KEYUP, scheduleRejection);\n document.addEventListener(EVENT.POINTER_UP, scheduleRejection);\n scheduleRejection();\n };\n const checkForFile = () => {\n // this hack might not work when expecting multiple files\n if (input.files?.length) {\n const ret = opts.multiple ? [...input.files] : input.files[0];\n resolve(ret as RetType);\n }\n };\n requestAnimationFrame(() => {\n window.addEventListener(EVENT.FOCUS, focusHandler);\n });\n const interval = window.setInterval(() => {\n checkForFile();\n }, INPUT_CHANGE_INTERVAL_MS);\n return (rejectPromise) => {\n clearInterval(interval);\n scheduleRejection.cancel();\n window.removeEventListener(EVENT.FOCUS, focusHandler);\n document.removeEventListener(EVENT.KEYUP, scheduleRejection);\n document.removeEventListener(EVENT.POINTER_UP, scheduleRejection);\n if (rejectPromise) {\n // so that something is shown in console if we need to debug this\n console.warn(\"Opening the file was canceled (legacy-fs).\");\n rejectPromise(new AbortError());\n }\n };\n },\n });\n\n if (Array.isArray(files)) {\n return (await Promise.all(\n files.map((file) => normalizeFile(file)),\n )) as RetType;\n }\n return (await normalizeFile(files)) as RetType;\n};\n\nexport const fileSave = (\n blob: Blob | Promise<Blob>,\n opts: {\n /** supply without the extension */\n name: string;\n /** file extension */\n extension: FILE_EXTENSION;\n mimeTypes?: string[];\n description: string;\n /** existing FileSystemHandle */\n fileHandle?: FileSystemHandle | null;\n },\n) => {\n return _fileSave(\n blob,\n {\n fileName: `${opts.name}.${opts.extension}`,\n description: opts.description,\n extensions: [`.${opts.extension}`],\n mimeTypes: opts.mimeTypes,\n },\n opts.fileHandle,\n );\n};\n\nexport { nativeFileSystemSupported };\nexport type { FileSystemHandle };\n", "import {\n DEFAULT_FILENAME,\n EXPORT_DATA_TYPES,\n getExportSource,\n MIME_TYPES,\n VERSIONS,\n} from \"@excalidraw/common\";\n\nimport type { ExcalidrawElement } from \"@excalidraw/element/types\";\n\nimport { cleanAppStateForExport, clearAppStateForDatabase } from \"../appState\";\n\nimport { isImageFileHandle, loadFromBlob } from \"./blob\";\nimport { fileOpen, fileSave } from \"./filesystem\";\n\nimport type { AppState, BinaryFiles, LibraryItems } from \"../types\";\nimport type {\n ExportedDataState,\n ImportedDataState,\n ExportedLibraryData,\n ImportedLibraryData,\n} from \"./types\";\n\n/**\n * Strips out files which are only referenced by deleted elements\n */\nconst filterOutDeletedFiles = (\n elements: readonly ExcalidrawElement[],\n files: BinaryFiles,\n) => {\n const nextFiles: BinaryFiles = {};\n for (const element of elements) {\n if (\n !element.isDeleted &&\n \"fileId\" in element &&\n element.fileId &&\n files[element.fileId]\n ) {\n nextFiles[element.fileId] = files[element.fileId];\n }\n }\n return nextFiles;\n};\n\nexport const serializeAsJSON = (\n elements: readonly ExcalidrawElement[],\n appState: Partial<AppState>,\n files: BinaryFiles,\n type: \"local\" | \"database\",\n): string => {\n const data: ExportedDataState = {\n type: EXPORT_DATA_TYPES.excalidraw,\n version: VERSIONS.excalidraw,\n source: getExportSource(),\n elements,\n appState:\n type === \"local\"\n ? cleanAppStateForExport(appState)\n : clearAppStateForDatabase(appState),\n files:\n type === \"local\"\n ? filterOutDeletedFiles(elements, files)\n : // will be stripped from JSON\n undefined,\n };\n\n return JSON.stringify(data, null, 2);\n};\n\nexport const saveAsJSON = async (\n elements: readonly ExcalidrawElement[],\n appState: AppState,\n files: BinaryFiles,\n /** filename */\n name: string = appState.name || DEFAULT_FILENAME,\n) => {\n const serialized = serializeAsJSON(elements, appState, files, \"local\");\n const blob = new Blob([serialized], {\n type: MIME_TYPES.excalidraw,\n });\n\n const fileHandle = await fileSave(blob, {\n name,\n extension: \"excalidraw\",\n description: \"Excalidraw file\",\n fileHandle: isImageFileHandle(appState.fileHandle)\n ? null\n : appState.fileHandle,\n });\n return { fileHandle };\n};\n\nexport const loadFromJSON = async (\n localAppState: AppState,\n localElements: readonly ExcalidrawElement[] | null,\n) => {\n const file = await fileOpen({\n description: \"Excalidraw files\",\n // ToDo: Be over-permissive until https://bugs.webkit.org/show_bug.cgi?id=34442\n // gets resolved. Else, iOS users cannot open `.excalidraw` files.\n // extensions: [\"json\", \"excalidraw\", \"png\", \"svg\"],\n });\n return loadFromBlob(file, localAppState, localElements, file.handle);\n};\n\nexport const isValidExcalidrawData = (data?: {\n type?: any;\n elements?: any;\n appState?: any;\n}): data is ImportedDataState => {\n return (\n data?.type === EXPORT_DATA_TYPES.excalidraw &&\n (!data.elements ||\n (Array.isArray(data.elements) &&\n (!data.appState || typeof data.appState === \"object\")))\n );\n};\n\nexport const isValidLibrary = (json: any): json is ImportedLibraryData => {\n return (\n typeof json === \"object\" &&\n json &&\n json.type === EXPORT_DATA_TYPES.excalidrawLibrary &&\n (json.version === 1 || json.version === 2)\n );\n};\n\nexport const serializeLibraryAsJSON = (libraryItems: LibraryItems) => {\n const data: ExportedLibraryData = {\n type: EXPORT_DATA_TYPES.excalidrawLibrary,\n version: VERSIONS.excalidrawLibrary,\n source: getExportSource(),\n libraryItems,\n };\n return JSON.stringify(data, null, 2);\n};\n\nexport const saveLibraryAsJSON = async (libraryItems: LibraryItems) => {\n const serialized = serializeLibraryAsJSON(libraryItems);\n await fileSave(\n new Blob([serialized], {\n type: MIME_TYPES.excalidrawlib,\n }),\n {\n name: \"library\",\n extension: \"excalidrawlib\",\n description: \"Excalidraw library file\",\n },\n );\n};\n", "import { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport CascadiaCodeRegular from \"./CascadiaCode-Regular.woff2\";\n\nexport const CascadiaFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: CascadiaCodeRegular,\n },\n];\n", "// The following file content was generated with https://chinese-font.netlify.app/online-split,\n// but has been manully rewritten from `@font-face` rules into TS while leveraging FontFace API.\n\nimport { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport _0 from \"./ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2\";\nimport _3 from \"./ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2\";\nimport _2 from \"./ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2\";\nimport _1 from \"./ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2\";\n\n/* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split\nCreateTime: Thu, 17 Oct 2024 09:57:51 GMT;\nOrigin File Name Table:\ncopyright: MIT License\n\nCopyright (c) 2018 Shannon Miwa\nCopyright (c) 2023 Jesus Gonzalez\nCopyright (c) 2023 Rodrigo Batista de Moraes\nCopyright (c) 2024 Fini Jastrow\nCopyright (c) 2024 Kyle Beechly\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\nfontFamily: Comic Shanns Mono-Regular\nfontSubfamily: Regular\nuniqueID: FontForge 2.0 : Comic Shanns Mono Regular : 17-10-2024\nfullName: Comic Shanns Mono Regular\nversion: 1.3.0\npostScriptName: ComicShannsMono-Regular\nlicense: MIT License\n\nCopyright (c) 2018 Shannon Miwa\nCopyright (c) 2023 Jesus Gonzalez\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\npreferredFamily: Comic Shanns Mono\n */\n\nexport const ComicShannsFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: _0,\n descriptors: {\n unicodeRange:\n \"U+20-7e,U+a1-a6,U+a8,U+ab-ac,U+af-b1,U+b4,U+b8,U+bb-bc,U+bf-cf,U+d1-d7,U+d9-de,U+e0-ef,U+f1-f7,U+f9-ff,U+131,U+152-153,U+2c6,U+2da,U+2dc,U+2013-2014,U+2018-201a,U+201c-201d,U+2020-2022,U+2026,U+2039-203a,U+2044,U+20ac,U+2191,U+2193,U+2212\",\n },\n },\n {\n uri: _1,\n descriptors: {\n unicodeRange:\n \"U+100-10f,U+112-125,U+128-130,U+134-137,U+139-13c,U+141-148,U+14c-151,U+154-161,U+164-165,U+168-17f,U+1bf,U+1f7,U+218-21b,U+237,U+1e80-1e85,U+1ef2-1ef3,U+a75b\",\n },\n },\n {\n uri: _2,\n descriptors: {\n unicodeRange:\n \"U+2c7,U+2d8-2d9,U+2db,U+2dd,U+315,U+2190,U+2192,U+2200,U+2203-2204,U+2264-2265,U+f6c3\",\n },\n },\n {\n uri: _3,\n descriptors: { unicodeRange: \"U+3bb\" },\n },\n];\n", "import { LOCAL_FONT_PROTOCOL } from \"@excalidraw/common\";\n\nimport { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nexport const EmojiFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: LOCAL_FONT_PROTOCOL,\n },\n];\n", "import { debounce } from \"@excalidraw/common\";\n\nimport { WorkerInTheMainChunkError, WorkerUrlNotDefinedError } from \"./errors\";\n\nclass IdleWorker {\n public instance: Worker;\n\n constructor(workerUrl: URL) {\n this.instance = new Worker(workerUrl, { type: \"module\" });\n }\n\n /**\n * Use to prolong the worker's life by `workerTTL` or terminate it with a flush immediately.\n */\n public debounceTerminate!: ReturnType<typeof debounce>;\n}\n\n/**\n * Pool of idle short-lived workers.\n *\n * IMPORTANT: for simplicity it does not limit the number of newly created workers, leaving it up to the caller to manage the pool size.\n */\nexport class WorkerPool<T, R> {\n private idleWorkers: Set<IdleWorker> = new Set();\n private readonly workerUrl: URL;\n private readonly workerTTL: number;\n\n private constructor(\n workerUrl: URL,\n options: {\n ttl?: number;\n },\n ) {\n this.workerUrl = workerUrl;\n // by default, active & idle workers will be terminated after 1s of inactivity\n this.workerTTL = options.ttl || 1000;\n }\n\n /**\n * Create a new worker pool.\n *\n * @param workerUrl - The URL of the worker file.\n * @param options - The options for the worker pool.\n * @throws If the worker is bundled into the main chunk.\n * @returns A new worker pool instance.\n */\n public static create<T, R>(\n workerUrl: URL | undefined,\n options: {\n ttl?: number;\n } = {},\n ): WorkerPool<T, R> {\n if (!workerUrl) {\n throw new WorkerUrlNotDefinedError();\n }\n\n if (!import.meta.url || workerUrl.toString() === import.meta.url) {\n // in case the worker code is bundled into the main chunk\n throw new WorkerInTheMainChunkError();\n }\n\n return new WorkerPool(workerUrl, options);\n }\n\n /**\n * Take idle worker from the pool or create a new one and post a message to it.\n */\n public async postMessage(\n data: T,\n options: StructuredSerializeOptions,\n ): Promise<R> {\n let worker: IdleWorker;\n\n const idleWorker = Array.from(this.idleWorkers).shift();\n if (idleWorker) {\n this.idleWorkers.delete(idleWorker);\n worker = idleWorker;\n } else {\n worker = await this.createWorker();\n }\n\n return new Promise((resolve, reject) => {\n worker.instance.onmessage = this.onMessageHandler(worker, resolve);\n worker.instance.onerror = this.onErrorHandler(worker, reject);\n\n worker.instance.postMessage(data, options);\n worker.debounceTerminate(() =>\n reject(\n new Error(`Active worker did not respond for ${this.workerTTL}ms!`),\n ),\n );\n });\n }\n\n /**\n * Terminate the idle workers in the pool.\n */\n public async clear() {\n for (const worker of this.idleWorkers) {\n worker.debounceTerminate.cancel();\n worker.instance.terminate();\n }\n\n this.idleWorkers.clear();\n }\n\n /**\n * Used to get a worker from the pool or create a new one if there is no idle available.\n */\n private async createWorker(): Promise<IdleWorker> {\n const worker = new IdleWorker(this.workerUrl);\n\n worker.debounceTerminate = debounce((reject?: () => void) => {\n worker.instance.terminate();\n\n if (this.idleWorkers.has(worker)) {\n this.idleWorkers.delete(worker);\n\n // eslint-disable-next-line no-console\n console.debug(\n \"Job finished! Idle worker has been released from the pool.\",\n );\n } else if (reject) {\n reject();\n } else {\n console.error(\"Worker has been terminated!\");\n }\n }, this.workerTTL);\n\n return worker;\n }\n\n private onMessageHandler(worker: IdleWorker, resolve: (value: R) => void) {\n return (e: { data: R }) => {\n worker.debounceTerminate();\n this.idleWorkers.add(worker);\n resolve(e.data);\n };\n }\n\n private onErrorHandler(\n worker: IdleWorker,\n reject: (reason: ErrorEvent) => void,\n ) {\n return (e: ErrorEvent) => {\n // terminate the worker immediately before rejection\n worker.debounceTerminate(() => reject(e));\n worker.debounceTerminate.flush();\n\n // clear the worker pool in case there are some idle workers left\n this.clear();\n };\n }\n}\n", "import { isServerEnv, promiseTry } from \"@excalidraw/common\";\n\nimport { WorkerInTheMainChunkError, WorkerUrlNotDefinedError } from \"../errors\";\nimport { WorkerPool } from \"../workers\";\n\nimport type { Commands } from \"./subset-shared.chunk\";\n\nlet shouldUseWorkers = typeof Worker !== \"undefined\";\n\n/**\n * Tries to subset glyphs in a font based on the used codepoints, returning the font as dataurl.\n * Under the hood utilizes worker threads (Web Workers, if available), otherwise fallbacks to the main thread.\n *\n * Check the following diagram for details: link.excalidraw.com/readonly/MbbnWPSWXgadXdtmzgeO\n *\n * @param arrayBuffer font data buffer in the woff2 format\n * @param codePoints codepoints used to subset the glyphs\n *\n * @returns font with subsetted glyphs (all glyphs in case of errors) converted into a dataurl\n */\nexport const subsetWoff2GlyphsByCodepoints = async (\n arrayBuffer: ArrayBuffer,\n codePoints: Array<number>,\n): Promise<string> => {\n const { Commands, subsetToBase64, toBase64 } =\n await lazyLoadSharedSubsetChunk();\n\n if (!shouldUseWorkers) {\n return subsetToBase64(arrayBuffer, codePoints);\n }\n\n return promiseTry(async () => {\n try {\n const workerPool = await getOrCreateWorkerPool();\n // copy the buffer to avoid working on top of the detached array buffer in the fallback\n // i.e. in case the worker throws, the array buffer does not get automatically detached, even if the worker is terminated\n const arrayBufferCopy = arrayBuffer.slice(0);\n const result = await workerPool.postMessage(\n {\n command: Commands.Subset,\n arrayBuffer: arrayBufferCopy,\n codePoints,\n } as const,\n { transfer: [arrayBufferCopy] },\n );\n\n // encode on the main thread to avoid copying large binary strings (as dataurl) between threads\n return toBase64(result);\n } catch (e) {\n // don't use workers if they are failing\n shouldUseWorkers = false;\n\n if (\n // don't log the expected errors server-side\n !(\n isServerEnv() &&\n (e instanceof WorkerUrlNotDefinedError ||\n e instanceof WorkerInTheMainChunkError)\n )\n ) {\n // eslint-disable-next-line no-console\n console.error(\n \"Failed to use workers for subsetting, falling back to the main thread.\",\n e,\n );\n }\n\n // fallback to the main thread\n return subsetToBase64(arrayBuffer, codePoints);\n }\n });\n};\n\n// lazy-loaded and cached chunks\nlet subsetWorker: Promise<typeof import(\"./subset-worker.chunk\")> | null = null;\nlet subsetShared: Promise<typeof import(\"./subset-shared.chunk\")> | null = null;\n\nconst lazyLoadWorkerSubsetChunk = async () => {\n if (!subsetWorker) {\n subsetWorker = import(\"./subset-worker.chunk\");\n }\n\n return subsetWorker;\n};\n\nconst lazyLoadSharedSubsetChunk = async () => {\n if (!subsetShared) {\n // load dynamically to force create a shared chunk reused between main thread and the worker thread\n subsetShared = import(\"./subset-shared.chunk\");\n }\n\n return subsetShared;\n};\n\n// could be extended with multiple commands in the future\ntype SubsetWorkerData = {\n command: typeof Commands.Subset;\n arrayBuffer: ArrayBuffer;\n codePoints: Array<number>;\n};\n\ntype SubsetWorkerResult<T extends SubsetWorkerData[\"command\"]> =\n T extends typeof Commands.Subset ? ArrayBuffer : never;\n\nlet workerPool: Promise<\n WorkerPool<SubsetWorkerData, SubsetWorkerResult<SubsetWorkerData[\"command\"]>>\n> | null = null;\n\n/**\n * Lazy initialize or get the worker pool singleton.\n *\n * @throws implicitly if anything goes wrong - worker pool creation, loading wasm, initializing worker, etc.\n */\nconst getOrCreateWorkerPool = () => {\n if (!workerPool) {\n // immediate concurrent-friendly return, to ensure we have only one pool instance\n workerPool = promiseTry(async () => {\n const { WorkerUrl } = await lazyLoadWorkerSubsetChunk();\n\n const pool = WorkerPool.create<\n SubsetWorkerData,\n SubsetWorkerResult<SubsetWorkerData[\"command\"]>\n >(WorkerUrl);\n\n return pool;\n });\n }\n\n return workerPool;\n};\n", "import { promiseTry, LOCAL_FONT_PROTOCOL } from \"@excalidraw/common\";\n\nimport { subsetWoff2GlyphsByCodepoints } from \"../subset/subset-main\";\n\ntype DataURL = string;\n\nexport class ExcalidrawFontFace {\n public readonly urls: URL[] | DataURL[];\n public readonly fontFace: FontFace;\n\n private static readonly ASSETS_FALLBACK_URL = `https://esm.sh/${\n import.meta.env.PKG_NAME\n ? `${import.meta.env.PKG_NAME}@${import.meta.env.PKG_VERSION}` // is provided during package build\n : \"@excalidraw/excalidraw\" // fallback to the latest package version (i.e. for app)\n }/dist/prod/`;\n\n constructor(family: string, uri: string, descriptors?: FontFaceDescriptors) {\n this.urls = ExcalidrawFontFace.createUrls(uri);\n\n const sources = this.urls\n .map((url) => `url(${url}) ${ExcalidrawFontFace.getFormat(url)}`)\n .join(\", \");\n\n this.fontFace = new FontFace(family, sources, {\n display: \"swap\",\n style: \"normal\",\n weight: \"400\",\n ...descriptors,\n });\n }\n\n /**\n * Generates CSS `@font-face` definition with the (subsetted) font source as a data url for the characters within the unicode range.\n *\n * Retrieves `undefined` otherwise.\n */\n public toCSS(characters: string): Promise<string> | undefined {\n // quick exit in case the characters are not within this font face's unicode range\n if (!this.getUnicodeRangeRegex().test(characters)) {\n return;\n }\n\n const codepoints = Array.from(characters).map(\n (char) => char.codePointAt(0)!,\n );\n\n return this.getContent(codepoints).then(\n (content) =>\n `@font-face { font-family: ${this.fontFace.family}; src: url(${content}); }`,\n );\n }\n\n /**\n * Tries to fetch woff2 content, based on the registered urls (from first to last, treated as fallbacks).\n *\n * @returns base64 with subsetted glyphs based on the passed codepoint, last defined url otherwise\n */\n public async getContent(codePoints: Array<number>): Promise<string> {\n let i = 0;\n const errorMessages = [];\n\n while (i < this.urls.length) {\n const url = this.urls[i];\n\n try {\n const arrayBuffer = await this.fetchFont(url);\n const base64 = await subsetWoff2GlyphsByCodepoints(\n arrayBuffer,\n codePoints,\n );\n\n return base64;\n } catch (e) {\n errorMessages.push(`\"${url.toString()}\" returned error \"${e}\"`);\n }\n\n i++;\n }\n\n console.error(\n `Failed to fetch font family \"${this.fontFace.family}\"`,\n JSON.stringify(errorMessages, undefined, 2),\n );\n\n // in case of issues, at least return the last url as a content\n // defaults to unpkg for bundled fonts (so that we don't have to host them forever) and http url for others\n return this.urls.length ? this.urls[this.urls.length - 1].toString() : \"\";\n }\n\n public fetchFont(url: URL | DataURL): Promise<ArrayBuffer> {\n return promiseTry(async () => {\n const response = await fetch(url, {\n // always prefer cache (even stale), otherwise it always triggers an unnecessary validation request\n // which we don't need as we are controlling freshness of the fonts with the stable hash suffix in the url\n // https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n cache: \"force-cache\",\n headers: {\n Accept: \"font/woff2\",\n },\n });\n\n if (!response.ok) {\n const urlString = url instanceof URL ? url.toString() : \"dataurl\";\n throw new Error(\n `Failed to fetch \"${urlString}\": ${response.statusText}`,\n );\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return arrayBuffer;\n });\n }\n\n private getUnicodeRangeRegex() {\n // using \\u{h} or \\u{hhhhh} to match any number of hex digits,\n // otherwise we would get an \"Invalid Unicode escape\" error\n // e.g. U+0-1007F -> \\u{0}-\\u{1007F}\n const unicodeRangeRegex = this.fontFace.unicodeRange\n .split(/,\\s*/)\n .map((range) => {\n const [start, end] = range.replace(\"U+\", \"\").split(\"-\");\n if (end) {\n return `\\\\u{${start}}-\\\\u{${end}}`;\n }\n\n return `\\\\u{${start}}`;\n })\n .join(\"\");\n\n return new RegExp(`[${unicodeRangeRegex}]`, \"u\");\n }\n\n private static createUrls(uri: string): URL[] | DataURL[] {\n if (uri.startsWith(\"data\")) {\n // don't create the URL instance, as parsing the huge dataurl string is expensive\n return [uri];\n }\n\n if (uri.startsWith(LOCAL_FONT_PROTOCOL)) {\n // no url for local fonts\n return [];\n }\n\n if (uri.startsWith(\"http\")) {\n // one url for http imports or data url\n return [new URL(uri)];\n }\n\n // absolute assets paths, which are found in tests and excalidraw-app build, won't work with base url, so we are stripping initial slash away\n const assetUrl: string = uri.replace(/^\\/+/, \"\");\n const urls: URL[] = [];\n\n if (typeof window.EXCALIDRAW_ASSET_PATH === \"string\") {\n const normalizedBaseUrl = this.normalizeBaseUrl(\n window.EXCALIDRAW_ASSET_PATH,\n );\n\n urls.push(new URL(assetUrl, normalizedBaseUrl));\n } else if (Array.isArray(window.EXCALIDRAW_ASSET_PATH)) {\n window.EXCALIDRAW_ASSET_PATH.forEach((path) => {\n const normalizedBaseUrl = this.normalizeBaseUrl(path);\n urls.push(new URL(assetUrl, normalizedBaseUrl));\n });\n }\n\n // fallback url for bundled fonts\n urls.push(new URL(assetUrl, ExcalidrawFontFace.ASSETS_FALLBACK_URL));\n\n return urls;\n }\n\n private static getFormat(url: URL | DataURL) {\n if (!(url instanceof URL)) {\n // format is irrelevant for data url\n return \"\";\n }\n\n try {\n const parts = new URL(url).pathname.split(\".\");\n\n if (parts.length === 1) {\n return \"\";\n }\n\n return `format('${parts.pop()}')`;\n } catch (error) {\n return \"\";\n }\n }\n\n private static normalizeBaseUrl(baseUrl: string) {\n let result = baseUrl;\n\n // in case user passed a root-relative url (~absolute path),\n // like \"/\" or \"/some/path\", or relative (starts with \"./\"),\n // prepend it with `location.origin`\n if (/^\\.?\\//.test(result)) {\n result = new URL(\n result.replace(/^\\.?\\/+/, \"\"),\n window?.location?.origin,\n ).toString();\n }\n\n // ensure there is a trailing slash, otherwise url won't be correctly concatenated\n result = `${result.replace(/\\/+$/, \"\")}/`;\n\n return result;\n }\n}\n", "import { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport _5 from \"./Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2\";\nimport _4 from \"./Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2\";\nimport _3 from \"./Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2\";\nimport _6 from \"./Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2\";\nimport _0 from \"./Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2\";\nimport _2 from \"./Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2\";\nimport _1 from \"./Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2\";\n\n/* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split\nCreateTime: Mon, 14 Oct 2024 18:59:19 GMT;\nOrigin File Name Table:\ncopyright: Copyright (c) 2024 by Excalidraw. All rights reserved.\nfontFamily: Excalifont\nfontSubfamily: Regular\nuniqueID: 1.000;DSGN;Excalifont\nfullName: Excalifont Regular\nversion: Version 1.000;Glyphs 3.2 (3227)\npostScriptName: Excalifont-Regular\ntrademark: Excalifont is a trademark of Excalidraw.\nmanufacturer: Your Own Font Foundry (Virgil); J\u00E1n Fil\u00EDpek / DizajnDesign (Excalifont, modifications)\ndesigner: Your Own Font Foundry (Virgil); J\u00E1n Fil\u00EDpek / DizajnDesign (Excalifont, modifications)\nmanufacturerURL: https://dizajndesign.sk\ndesignerURL: https://dizajndesign.sk\nlicense: This Font Software is licensed under the SIL Open Font License, Version 1.1.\nThis license is copied below, and is also available with a FAQ at:\nhttp://scripts.sil.org/OFL\n\n\n-----------------------------------------------------------\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\n-----------------------------------------------------------\n\nPREAMBLE\nThe goals of the Open Font License (OFL) are to stimulate worldwide\ndevelopment of collaborative font projects, to support the font creation\nefforts of academic and linguistic communities, and to provide a free and\nopen framework in which fonts may be shared and improved in partnership\nwith others.\n\nThe OFL allows the licensed fonts to be used, studied, modified and\nredistributed freely as long as they are not sold by themselves. The\nfonts, including any derivative works, can be bundled, embedded, \nredistributed and/or sold with any software provided that any reserved\nnames are not used by derivative works. The fonts and derivatives,\nhowever, cannot be released under any other type of license. The\nrequirement for fonts to remain under this license does not apply\nto any document created using the fonts or their derivatives.\n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this license and clearly marked as such. This may\ninclude source files, build scripts and documentation.\n\n\"Reserved Font Name\" refers to any names specified as such after the\ncopyright statement(s).\n\n\"Original Version\" refers to the collection of Font Software components as\ndistributed by the Copyright Holder(s).\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting -- in part or in whole -- any of the components of the\nOriginal Version, by changing formats or by porting the Font Software to a\nnew environment.\n\n\"Author\" refers to any designer, engineer, programmer, technical\nwriter or other person who contributed to the Font Software.\n\nPERMISSION & CONDITIONS\nPermission is hereby granted, free of charge, to any person obtaining\na copy of the Font Software, to use, study, copy, merge, embed, modify,\nredistribute, and sell modified and unmodified copies of the Font\nSoftware, subject to the following conditions:\n\n1) Neither the Font Software nor any of its individual components,\nin Original or Modified Versions, may be sold by itself.\n\n2) Original or Modified Versions of the Font Software may be bundled,\nredistributed and/or sold with any software, provided that each copy\ncontains the above copyright notice and this license. These can be\nincluded either as stand-alone text files, human-readable headers or\nin the appropriate machine-readable metadata fields within text or\nbinary files as long as those fields can be easily viewed by the user.\n\n3) No Modified Version of the Font Software may use the Reserved Font\nName(s) unless explicit written permission is granted by the corresponding\nCopyright Holder. This restriction only applies to the primary font name as\npresented to the users.\n\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\nSoftware shall not be used to promote, endorse or advertise any\nModified Version, except to acknowledge the contribution(s) of the\nCopyright Holder(s) and the Author(s) or with their explicit written\npermission.\n\n5) The Font Software, modified or unmodified, in part or in whole,\nmust be distributed entirely under this license, and must not be\ndistributed under any other license. The requirement for fonts to\nremain under this license does not apply to any document created\nusing the Font Software.\n\nTERMINATION\nThis license becomes null and void if any of the above conditions are\nnot met.\n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\nOTHER DEALINGS IN THE FONT SOFTWARE.\nlicenseURL: http://scripts.sil.org/OFL\npreferredFamily: Excalifont\npreferredSubfamily: Regular\n */\n\nexport const ExcalifontFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: _0,\n descriptors: {\n unicodeRange:\n \"U+20-7e,U+a0-a3,U+a5-a6,U+a8-ab,U+ad-b1,U+b4,U+b6-b8,U+ba-ff,U+131,U+152-153,U+2bc,U+2c6,U+2da,U+2dc,U+304,U+308,U+2013-2014,U+2018-201a,U+201c-201e,U+2020,U+2022,U+2024-2026,U+2030,U+2039-203a,U+20ac,U+2122,U+2212\",\n },\n },\n {\n uri: _1,\n descriptors: {\n unicodeRange:\n \"U+100-130,U+132-137,U+139-149,U+14c-151,U+154-17e,U+192,U+1fc-1ff,U+218-21b,U+237,U+1e80-1e85,U+1ef2-1ef3,U+2113\",\n },\n },\n { uri: _2, descriptors: { unicodeRange: \"U+400-45f,U+490-491,U+2116\" } },\n {\n uri: _3,\n descriptors: {\n unicodeRange:\n \"U+37e,U+384-38a,U+38c,U+38e-393,U+395-3a1,U+3a3-3a8,U+3aa-3cf,U+3d7\",\n },\n },\n {\n uri: _4,\n descriptors: {\n unicodeRange:\n \"U+2c7,U+2d8-2d9,U+2db,U+2dd,U+302,U+306-307,U+30a-30c,U+326-328,U+212e,U+2211,U+fb01-fb02\",\n },\n },\n {\n uri: _5,\n descriptors: {\n unicodeRange:\n \"U+462-463,U+472-475,U+4d8-4d9,U+4e2-4e3,U+4e6-4e9,U+4ee-4ef\",\n },\n },\n { uri: _6, descriptors: { unicodeRange: \"U+300-301,U+303\" } },\n];\n", "import { LOCAL_FONT_PROTOCOL } from \"@excalidraw/common\";\n\nimport { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nexport const HelveticaFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: LOCAL_FONT_PROTOCOL,\n },\n];\n", "import { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport LiberationSansRegular from \"./LiberationSans-Regular.woff2\";\n\nexport const LiberationFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: LiberationSansRegular,\n },\n];\n", "import { GOOGLE_FONTS_RANGES } from \"@excalidraw/common\";\n\nimport { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport LilitaLatinExt from \"./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2\";\nimport LilitaLatin from \"./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2\";\n\nexport const LilitaFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: LilitaLatinExt,\n descriptors: { unicodeRange: GOOGLE_FONTS_RANGES.LATIN_EXT },\n },\n {\n uri: LilitaLatin,\n descriptors: { unicodeRange: GOOGLE_FONTS_RANGES.LATIN },\n },\n];\n", "import { GOOGLE_FONTS_RANGES } from \"@excalidraw/common\";\n\nimport { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport Cyrilic from \"./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2\";\nimport Latin from \"./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2\";\nimport CyrilicExt from \"./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2\";\nimport LatinExt from \"./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2\";\nimport Vietnamese from \"./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2\";\n\nexport const NunitoFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: CyrilicExt,\n descriptors: {\n unicodeRange: GOOGLE_FONTS_RANGES.CYRILIC_EXT,\n weight: \"500\",\n },\n },\n {\n uri: Cyrilic,\n descriptors: { unicodeRange: GOOGLE_FONTS_RANGES.CYRILIC, weight: \"500\" },\n },\n {\n uri: Vietnamese,\n descriptors: {\n unicodeRange: GOOGLE_FONTS_RANGES.VIETNAMESE,\n weight: \"500\",\n },\n },\n {\n uri: LatinExt,\n descriptors: { unicodeRange: GOOGLE_FONTS_RANGES.LATIN_EXT, weight: \"500\" },\n },\n {\n uri: Latin,\n descriptors: { unicodeRange: GOOGLE_FONTS_RANGES.LATIN, weight: \"500\" },\n },\n];\n", "import { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport Virgil from \"./Virgil-Regular.woff2\";\n\nexport const VirgilFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: Virgil,\n },\n];\n", "// The following file content was generated with https://chinese-font.netlify.app/online-split,\n// but has been manully rewritten from `@font-face` rules into TS while leveraging FontFace API.\n\nimport { type ExcalidrawFontFaceDescriptor } from \"../Fonts\";\n\nimport _80 from \"./Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2\";\nimport _16 from \"./Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2\";\nimport _13 from \"./Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2\";\nimport _166 from \"./Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2\";\nimport _71 from \"./Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2\";\nimport _161 from \"./Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2\";\nimport _183 from \"./Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2\";\nimport _0 from \"./Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2\";\nimport _14 from \"./Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2\";\nimport _10 from \"./Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2\";\nimport _2 from \"./Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2\";\nimport _1 from \"./Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2\";\nimport _3 from \"./Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2\";\nimport _6 from \"./Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2\";\nimport _4 from \"./Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2\";\nimport _5 from \"./Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2\";\nimport _7 from \"./Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2\";\nimport _30 from \"./Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2\";\nimport _8 from \"./Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2\";\nimport _9 from \"./Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2\";\nimport _11 from \"./Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2\";\nimport _12 from \"./Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2\";\nimport _15 from \"./Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2\";\nimport _17 from \"./Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2\";\nimport _18 from \"./Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2\";\nimport _19 from \"./Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2\";\nimport _20 from \"./Xiaolai-Regular-25b7f38e18f035f96cb5e547bd2bd08c.woff2\";\nimport _21 from \"./Xiaolai-Regular-ba3de316d63c7e339987b16f41a0b879.woff2\";\nimport _22 from \"./Xiaolai-Regular-12b52b58eb3df36804b9a654ec9ee194.woff2\";\nimport _23 from \"./Xiaolai-Regular-b1220a3c61f85cc0408deedb4c5f57a2.woff2\";\nimport _24 from \"./Xiaolai-Regular-4535823663ad81405188a528d8f2b1a2.woff2\";\nimport _25 from \"./Xiaolai-Regular-3eaa538115d76932653c21d8dc28f207.woff2\";\nimport _26 from \"./Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2\";\nimport _27 from \"./Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2\";\nimport _28 from \"./Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2\";\nimport _29 from \"./Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2\";\nimport _31 from \"./Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2\";\nimport _32 from \"./Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2\";\nimport _33 from \"./Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2\";\nimport _34 from \"./Xiaolai-Regular-95429962233afd82db1c27df1500a28c.woff2\";\nimport _35 from \"./Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2\";\nimport _36 from \"./Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2\";\nimport _37 from \"./Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2\";\nimport _38 from \"./Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2\";\nimport _41 from \"./Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2\";\nimport _105 from \"./Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2\";\nimport _82 from \"./Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2\";\nimport _45 from \"./Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2\";\nimport _47 from \"./Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2\";\nimport _39 from \"./Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2\";\nimport _40 from \"./Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2\";\nimport _42 from \"./Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2\";\nimport _43 from \"./Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2\";\nimport _44 from \"./Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2\";\nimport _46 from \"./Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2\";\nimport _48 from \"./Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2\";\nimport _49 from \"./Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2\";\nimport _50 from \"./Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2\";\nimport _51 from \"./Xiaolai-Regular-5572b3513ba8df57a3d5d7303ee6b11b.woff2\";\nimport _52 from \"./Xiaolai-Regular-3c9de2ae0ea4bc91a510942dfa4be8d2.woff2\";\nimport _53 from \"./Xiaolai-Regular-671a2c20b1eb9e4ef8a192833940e319.woff2\";\nimport _54 from \"./Xiaolai-Regular-4dc6d5f188d5c96d44815cd1e81aa885.woff2\";\nimport _55 from \"./Xiaolai-Regular-ce4884f96f11589608b76b726a755803.woff2\";\nimport _56 from \"./Xiaolai-Regular-8f476c4c99813d57cbe6eca4727388ad.woff2\";\nimport _57 from \"./Xiaolai-Regular-5935a5775af3d5c6307ac667bd9ae74e.woff2\";\nimport _58 from \"./Xiaolai-Regular-79f007c1c6d07557120982951ea67998.woff2\";\nimport _59 from \"./Xiaolai-Regular-bafff7a14c27403dcc6cf1432e8ea836.woff2\";\nimport _60 from \"./Xiaolai-Regular-543fa46ace099a7099dad69123399400.woff2\";\nimport _61 from \"./Xiaolai-Regular-4ddc14ed3eb0c3e46364317dfc0144a3.woff2\";\nimport _62 from \"./Xiaolai-Regular-0fa55a080fcd0f9dc2e0b0058b793df8.woff2\";\nimport _63 from \"./Xiaolai-Regular-66493ba5a8367f2928812f446f47b56a.woff2\";\nimport _64 from \"./Xiaolai-Regular-57862b464a55b18c7bf234ce22907d73.woff2\";\nimport _65 from \"./Xiaolai-Regular-8d3bcabb847b56243b16afe62adaaf21.woff2\";\nimport _66 from \"./Xiaolai-Regular-2b77e8ebfb2367ab2662396a60e7d320.woff2\";\nimport _67 from \"./Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2\";\nimport _68 from \"./Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2\";\nimport _69 from \"./Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2\";\nimport _70 from \"./Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2\";\nimport _72 from \"./Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2\";\nimport _73 from \"./Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2\";\nimport _74 from \"./Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2\";\nimport _75 from \"./Xiaolai-Regular-0986d134c05864f5025962eef9f994a0.woff2\";\nimport _76 from \"./Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2\";\nimport _77 from \"./Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2\";\nimport _78 from \"./Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2\";\nimport _79 from \"./Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2\";\nimport _81 from \"./Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2\";\nimport _83 from \"./Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2\";\nimport _84 from \"./Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2\";\nimport _85 from \"./Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2\";\nimport _86 from \"./Xiaolai-Regular-21430ee05a1248901da8d0de08744d47.woff2\";\nimport _87 from \"./Xiaolai-Regular-5330a2119a716e4e7224ed108b085dac.woff2\";\nimport _88 from \"./Xiaolai-Regular-cd145ce4a0ea18469358df53c207bc1b.woff2\";\nimport _89 from \"./Xiaolai-Regular-36925dfe329a45086cbb7fc5c20d45ac.woff2\";\nimport _90 from \"./Xiaolai-Regular-4bfaa8ffa64c5ee560aa2daba7c9cbd3.woff2\";\nimport _91 from \"./Xiaolai-Regular-112c051027b2d766c19a519f6ee1f4f7.woff2\";\nimport _92 from \"./Xiaolai-Regular-5b0ed6971aaab9c8ad563230bd5471a7.woff2\";\nimport _93 from \"./Xiaolai-Regular-98f2ad84457de7f3740d9920b8fa8667.woff2\";\nimport _94 from \"./Xiaolai-Regular-733171b4ffcd17ea1fe1c0ba627173bf.woff2\";\nimport _95 from \"./Xiaolai-Regular-684d65f1793cac449dde5d59cb3c47fb.woff2\";\nimport _96 from \"./Xiaolai-Regular-cbaaefaaf326668277aa24dfa93c4d28.woff2\";\nimport _97 from \"./Xiaolai-Regular-58fd02350d0bc52cf1ca3bb32ce9766e.woff2\";\nimport _98 from \"./Xiaolai-Regular-7ccce86603f80a099ddb0cb21d4ae3e3.woff2\";\nimport _99 from \"./Xiaolai-Regular-3717077e38f98d89eae729b6c14e56dc.woff2\";\nimport _100 from \"./Xiaolai-Regular-dbea1af6dcd9860be40c3d18254338f5.woff2\";\nimport _101 from \"./Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2\";\nimport _102 from \"./Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2\";\nimport _103 from \"./Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2\";\nimport _104 from \"./Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2\";\nimport _106 from \"./Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2\";\nimport _107 from \"./Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2\";\nimport _108 from \"./Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2\";\nimport _109 from \"./Xiaolai-Regular-4ee10ae43505e2e0bc62656ced49c0fa.woff2\";\nimport _110 from \"./Xiaolai-Regular-7494dc504ae00ee9cd0505f990f88c5d.woff2\";\nimport _111 from \"./Xiaolai-Regular-8de5b863cb50dfefdd07cb11c774d579.woff2\";\nimport _112 from \"./Xiaolai-Regular-3e1f8f654357353bf0e04ba5c34b5f7f.woff2\";\nimport _113 from \"./Xiaolai-Regular-2e33e8dc771ef5e1d9127d60a6b73679.woff2\";\nimport _114 from \"./Xiaolai-Regular-173945821411c09f70c95f98d590e697.woff2\";\nimport _115 from \"./Xiaolai-Regular-b358f7a51ece39a3247942b1feabdb29.woff2\";\nimport _116 from \"./Xiaolai-Regular-23ad2d71b280f00b1363b95b7bea94eb.woff2\";\nimport _117 from \"./Xiaolai-Regular-5882ffa04f32584d26109137e2da4352.woff2\";\nimport _118 from \"./Xiaolai-Regular-a203b91dad570bf05a58c3c3ddb529bf.woff2\";\nimport _119 from \"./Xiaolai-Regular-bd77e3c7f9e0b072d96af37f73d1aa32.woff2\";\nimport _120 from \"./Xiaolai-Regular-5a45d991244d4c7140217e1e5f5ca4f4.woff2\";\nimport _121 from \"./Xiaolai-Regular-f56414bf9bced67990def8660e306759.woff2\";\nimport _122 from \"./Xiaolai-Regular-583d166e56ba0de4b77eabb47ef67839.woff2\";\nimport _123 from \"./Xiaolai-Regular-7f855356ab893b0d2b9c1c83b8116f0e.woff2\";\nimport _124 from \"./Xiaolai-Regular-b57aaedfd8ebdf3931f25119dc6a5eb2.woff2\";\nimport _125 from \"./Xiaolai-Regular-b6fd38ca30869792244804b04bc058da.woff2\";\nimport _126 from \"./Xiaolai-Regular-452225341522a7942f0f6aab1a5c91a3.woff2\";\nimport _127 from \"./Xiaolai-Regular-866fa7613df6b3fd272bcfd4530c0bb9.woff2\";\nimport _128 from \"./Xiaolai-Regular-52a84a22fd1369bffeaf21da2d6158dc.woff2\";\nimport _129 from \"./Xiaolai-Regular-829615148e6357d826b9242eb7fbbd1e.woff2\";\nimport _130 from \"./Xiaolai-Regular-c99eda15fc26a2941579560f76c3a5cf.woff2\";\nimport _131 from \"./Xiaolai-Regular-395c35dd584b56b0789f58a0559beaf1.woff2\";\nimport _132 from \"./Xiaolai-Regular-203b0e569e3b14aac86a003dc3fa523e.woff2\";\nimport _133 from \"./Xiaolai-Regular-51a0e808bbc8361236ac521a119758a3.woff2\";\nimport _134 from \"./Xiaolai-Regular-6e092f71c1e634059ada0e52abadce67.woff2\";\nimport _135 from \"./Xiaolai-Regular-0f7fb1e0d5015bb1371343153ecf7ce3.woff2\";\nimport _136 from \"./Xiaolai-Regular-d0cf73942fea1c74edbdf0b3011f4656.woff2\";\nimport _137 from \"./Xiaolai-Regular-968cffdc8ee679da094e77ebf50f58ef.woff2\";\nimport _138 from \"./Xiaolai-Regular-7a07ddc0f0c0f5f4a9bad6ee3dda66b5.woff2\";\nimport _139 from \"./Xiaolai-Regular-ec181b795ac1fb5a50d700b6e996d745.woff2\";\nimport _140 from \"./Xiaolai-Regular-cfb211578629b7e8153b37240de6a9d5.woff2\";\nimport _141 from \"./Xiaolai-Regular-59e9ff77b0efaf684bc09274fb6908c9.woff2\";\nimport _142 from \"./Xiaolai-Regular-2adbc89c11e65905393d3dfc468b9d5b.woff2\";\nimport _143 from \"./Xiaolai-Regular-70e811fd7994e61f408c923de6ddd078.woff2\";\nimport _144 from \"./Xiaolai-Regular-c4a687ac4f0c2766eefc9f77ed99cddf.woff2\";\nimport _145 from \"./Xiaolai-Regular-51502f1206be09c565f1547c406e9558.woff2\";\nimport _146 from \"./Xiaolai-Regular-1fdc0c67ed57263a80fd108c1f6ccf24.woff2\";\nimport _147 from \"./Xiaolai-Regular-e11567fd2accf9957cd0d3c2be937d87.woff2\";\nimport _148 from \"./Xiaolai-Regular-20cc1bbf50e7efb442756cb605672c1f.woff2\";\nimport _149 from \"./Xiaolai-Regular-5d2898fbc097a7e24c6f38d80587621e.woff2\";\nimport _150 from \"./Xiaolai-Regular-ac9ceb44437becc3e9c4dbfebab7fc2d.woff2\";\nimport _151 from \"./Xiaolai-Regular-c16ed9740b85badf16e86ea782a3062f.woff2\";\nimport _152 from \"./Xiaolai-Regular-aa0d470430e6391eca720c7cfa44446f.woff2\";\nimport _153 from \"./Xiaolai-Regular-f2b54d4e7be0eaefe1c2c56836fa5368.woff2\";\nimport _154 from \"./Xiaolai-Regular-99a16ef6a64934d5781933dbd9c46b2e.woff2\";\nimport _155 from \"./Xiaolai-Regular-c40533fdf4cc57177b12803598af7e59.woff2\";\nimport _156 from \"./Xiaolai-Regular-91ddb2969bf2d31ba02ad82998d1314c.woff2\";\nimport _157 from \"./Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2\";\nimport _158 from \"./Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2\";\nimport _159 from \"./Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2\";\nimport _160 from \"./Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2\";\nimport _162 from \"./Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2\";\nimport _163 from \"./Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2\";\nimport _164 from \"./Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2\";\nimport _165 from \"./Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2\";\nimport _167 from \"./Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2\";\nimport _168 from \"./Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2\";\nimport _169 from \"./Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2\";\nimport _202 from \"./Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2\";\nimport _170 from \"./Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2\";\nimport _171 from \"./Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2\";\nimport _172 from \"./Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2\";\nimport _173 from \"./Xiaolai-Regular-ee8bae97908d5147b423f77ad0d3c1bb.woff2\";\nimport _174 from \"./Xiaolai-Regular-56467a5c8840c4d23a60b2f935114848.woff2\";\nimport _175 from \"./Xiaolai-Regular-145aa02cdd91946e67dc934e1acffe75.woff2\";\nimport _176 from \"./Xiaolai-Regular-54acdfc2166ad7fcbd074f75fd4a56ba.woff2\";\nimport _177 from \"./Xiaolai-Regular-29cec36cd205b211da97acabaa62f055.woff2\";\nimport _178 from \"./Xiaolai-Regular-3756e81d3e149cf6099163ee79944fec.woff2\";\nimport _179 from \"./Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2\";\nimport _180 from \"./Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2\";\nimport _181 from \"./Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2\";\nimport _182 from \"./Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2\";\nimport _184 from \"./Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2\";\nimport _185 from \"./Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2\";\nimport _186 from \"./Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2\";\nimport _187 from \"./Xiaolai-Regular-b7d203b051eff504ff59ddca7576b6a9.woff2\";\nimport _188 from \"./Xiaolai-Regular-4a38cc3e9cf104e69ba246d37f8cf135.woff2\";\nimport _189 from \"./Xiaolai-Regular-982b630266d87db93d2539affb1275c6.woff2\";\nimport _190 from \"./Xiaolai-Regular-9592bfc861f07bcb8d75c196b370e548.woff2\";\nimport _191 from \"./Xiaolai-Regular-a7accba310e821da5505f71c03b76bdb.woff2\";\nimport _192 from \"./Xiaolai-Regular-dac48066b5883d8b4551fc584f0c2a3e.woff2\";\nimport _193 from \"./Xiaolai-Regular-a1f916d6039285c4ffb900cd654e418f.woff2\";\nimport _194 from \"./Xiaolai-Regular-95bfd249da4902577b4b7d76ebdd0b44.woff2\";\nimport _195 from \"./Xiaolai-Regular-93fc8f28a33234bcadf1527cafabd502.woff2\";\nimport _196 from \"./Xiaolai-Regular-903bb6865f3452e2fda42e3a25547bc5.woff2\";\nimport _197 from \"./Xiaolai-Regular-4aca6a43e59aceee2166b0c7e4e85ef1.woff2\";\nimport _198 from \"./Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2\";\nimport _199 from \"./Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2\";\nimport _200 from \"./Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2\";\nimport _201 from \"./Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2\";\nimport _203 from \"./Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2\";\nimport _204 from \"./Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2\";\nimport _205 from \"./Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2\";\nimport _206 from \"./Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2\";\nimport _207 from \"./Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2\";\nimport _208 from \"./Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2\";\n\n/* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split\nCreateTime: Tue, 08 Oct 2024 18:34:44 GMT;\nOrigin File Name Table:\nfontFamily: Xiaolai SC\nfontSubfamily: Regular\npreferredFamily: \u5C0F\u8CF4\u5B57\u9AD4 SC\npostScriptFindFontName: \ncopyright: Copyright \u00A9 2020 LXGW\nuniqueID: Xiaolai SC:Version 3.11\nfullName: Xiaolai SC\nversion: Version 3.11;December 4, 2020;FontCreator 13.0.0.2613 64-bit\npostScriptName: XiaolaiSC\ntrademark: \u5C0F\u8D56\u5B57\u4F53 SC\ndesigner: Nozomi Seto \u702C\u6238\u306E\u305E\u307F\ndescription: This font was created using FontCreator from High-Logic.com\nlicense: This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.\nlicenseURL: http://scripts.sil.org/OFL\n */\n\n/**\n * The original font was modified with the following changes:\n * - removed non-CJK codepoints\n * - reduced any Hangul side-bearings to 40%\n * - centered in width of inproperly centered CJK codepoints\n */\n\nexport const XiaolaiFontFaces: ExcalidrawFontFaceDescriptor[] = [\n {\n uri: _0,\n descriptors: {\n unicodeRange:\n \"U+f9b8-fa6d,U+fe32,U+fe45-fe4f,U+ff02-ff0b,U+ff0d-ff1e,U+ff20-ff2a\",\n },\n },\n {\n uri: _1,\n descriptors: {\n unicodeRange:\n \"U+20dd-20de,U+25ef,U+ff2b-ffbe,U+ffc2-ffc7,U+ffca-ffcf,U+ffd2-ffd7,U+ffda-ffdc,U+ffe0-ffe6,U+ffe8-ffee\",\n },\n },\n { uri: _2, descriptors: { unicodeRange: \"U+d7eb-d7fb,U+f900-f9b7\" } },\n {\n uri: _3,\n descriptors: { unicodeRange: \"U+d6f2-d7a3,U+d7b0-d7c6,U+d7cb-d7ea\" },\n },\n { uri: _4, descriptors: { unicodeRange: \"U+d609-d6f1\" } },\n { uri: _5, descriptors: { unicodeRange: \"U+d520-d608\" } },\n { uri: _6, descriptors: { unicodeRange: \"U+d437-d51f\" } },\n { uri: _7, descriptors: { unicodeRange: \"U+d34e-d436\" } },\n { uri: _8, descriptors: { unicodeRange: \"U+d265-d34d\" } },\n { uri: _9, descriptors: { unicodeRange: \"U+d17c-d264\" } },\n { uri: _10, descriptors: { unicodeRange: \"U+d093-d17b\" } },\n { uri: _11, descriptors: { unicodeRange: \"U+cfaa-d092\" } },\n { uri: _12, descriptors: { unicodeRange: \"U+cec1-cfa9\" } },\n { uri: _13, descriptors: { unicodeRange: \"U+cdd8-cec0\" } },\n { uri: _14, descriptors: { unicodeRange: \"U+ccf1-cdd7\" } },\n { uri: _15, descriptors: { unicodeRange: \"U+cc08-ccf0\" } },\n { uri: _16, descriptors: { unicodeRange: \"U+cb43-cc07\" } },\n { uri: _17, descriptors: { unicodeRange: \"U+ca83-cb42\" } },\n { uri: _18, descriptors: { unicodeRange: \"U+c9a1-ca82\" } },\n { uri: _19, descriptors: { unicodeRange: \"U+c8b8-c9a0\" } },\n { uri: _20, descriptors: { unicodeRange: \"U+c7cf-c8b7\" } },\n { uri: _21, descriptors: { unicodeRange: \"U+c6e6-c7ce\" } },\n { uri: _22, descriptors: { unicodeRange: \"U+c5fd-c6e5\" } },\n { uri: _23, descriptors: { unicodeRange: \"U+c514-c5fc\" } },\n { uri: _24, descriptors: { unicodeRange: \"U+c42b-c513\" } },\n { uri: _25, descriptors: { unicodeRange: \"U+c341-c34e,U+c350-c42a\" } },\n { uri: _26, descriptors: { unicodeRange: \"U+c258-c340\" } },\n { uri: _27, descriptors: { unicodeRange: \"U+c16f-c257\" } },\n { uri: _28, descriptors: { unicodeRange: \"U+c086-c16e\" } },\n { uri: _29, descriptors: { unicodeRange: \"U+bf9d-c085\" } },\n { uri: _30, descriptors: { unicodeRange: \"U+beb4-bf9c\" } },\n { uri: _31, descriptors: { unicodeRange: \"U+bdcb-beb3\" } },\n { uri: _32, descriptors: { unicodeRange: \"U+bce2-bdca\" } },\n { uri: _33, descriptors: { unicodeRange: \"U+bbf9-bce1\" } },\n { uri: _34, descriptors: { unicodeRange: \"U+bb10-bbf8\" } },\n { uri: _35, descriptors: { unicodeRange: \"U+ba27-bb0f\" } },\n { uri: _36, descriptors: { unicodeRange: \"U+b93e-ba26\" } },\n { uri: _37, descriptors: { unicodeRange: \"U+b855-b93d\" } },\n { uri: _38, descriptors: { unicodeRange: \"U+b76c-b854\" } },\n { uri: _39, descriptors: { unicodeRange: \"U+b683-b76b\" } },\n { uri: _40, descriptors: { unicodeRange: \"U+b59a-b682\" } },\n { uri: _41, descriptors: { unicodeRange: \"U+b4b1-b599\" } },\n { uri: _42, descriptors: { unicodeRange: \"U+11fb-11ff,U+b3cd-b4b0\" } },\n { uri: _43, descriptors: { unicodeRange: \"U+11e6-11fa,U+b2f9-b3cc\" } },\n { uri: _44, descriptors: { unicodeRange: \"U+11d1-11e5,U+b225-b2f8\" } },\n { uri: _45, descriptors: { unicodeRange: \"U+11bc-11d0,U+b151-b224\" } },\n { uri: _46, descriptors: { unicodeRange: \"U+11a7-11bb,U+b07d-b150\" } },\n { uri: _47, descriptors: { unicodeRange: \"U+1191-11a6,U+afaa-b07c\" } },\n { uri: _48, descriptors: { unicodeRange: \"U+117c-1190,U+aed6-afa9\" } },\n { uri: _49, descriptors: { unicodeRange: \"U+1167-117b,U+ae02-aed5\" } },\n {\n uri: _50,\n descriptors: { unicodeRange: \"U+1152-115e,U+1160-1166,U+ad2d-ae01\" },\n },\n { uri: _51, descriptors: { unicodeRange: \"U+113d-1151,U+ac59-ad2c\" } },\n {\n uri: _52,\n descriptors: {\n unicodeRange:\n \"U+1100-113c,U+9f95-9f98,U+9f9c-9f9e,U+9fa1-9fce,U+9fd0,U+a960-a97c,U+ac00-ac58\",\n },\n },\n {\n uri: _53,\n descriptors: {\n unicodeRange:\n \"U+9771-9772,U+9775,U+9777-977b,U+977d-9784,U+9786-978a,U+978c,U+978e-9790,U+9793,U+9795-9797,U+9799-979f,U+97a1-97a2,U+97a4-97aa,U+97ac,U+97ae,U+97b0-97b1,U+97b3,U+97b5-97e5,U+97e8,U+97ee-97f2,U+97f4,U+97f7-982d\",\n },\n },\n {\n uri: _54,\n descriptors: {\n unicodeRange:\n \"U+9491,U+9496,U+9498,U+94c7,U+94cf,U+94d3-94d4,U+94da,U+94e6,U+94fb,U+951c,U+9520,U+9527,U+9533,U+953d,U+9543,U+9548,U+954b,U+9555,U+955a,U+9560,U+956e,U+9574-9575,U+9577-957e,U+9580-95e7,U+95ec,U+95ff,U+9607,U+9613,U+9618,U+961b,U+961e,U+9620,U+9623-9629,U+962b-962d,U+962f-9630,U+9637-963a,U+963e,U+9641,U+9643,U+964a,U+964e-964f,U+9651-9653,U+9656-965a,U+965c-965e,U+9660,U+9663,U+9665-9666,U+966b,U+966d-9671,U+9673,U+9678-9684,U+9687,U+9689-968a,U+968c,U+968e,U+9691-9693\",\n },\n },\n {\n uri: _55,\n descriptors: {\n unicodeRange:\n \"U+923c-9273,U+9275-928d,U+928f-92ad,U+92af-92c7,U+92c9-92ee\",\n },\n },\n {\n uri: _56,\n descriptors: {\n unicodeRange:\n \"U+9159,U+915b-915c,U+915f-9160,U+9166-9168,U+916b,U+916d,U+9173,U+917a-917c,U+9180-9184,U+9186,U+9188,U+918a,U+918e-918f,U+9193-9199,U+919c-91a1,U+91a4-91a9,U+91ab-91ac,U+91b0-91b3,U+91b6-91b9,U+91bb-91c6,U+91c8,U+91cb,U+91d0,U+91d2-91db,U+91dd-923b\",\n },\n },\n {\n uri: _57,\n descriptors: {\n unicodeRange:\n \"U+902b-902c,U+9030-9034,U+9037,U+9039-903a,U+903d,U+903f-9040,U+9043,U+9045-9046,U+9048-904c,U+904e,U+9054-9056,U+9059-905a,U+905c-9061,U+9064,U+9066-9067,U+9069-906c,U+906f-9073,U+9076-907c,U+907e,U+9081,U+9084-9087,U+9089-908a,U+908c-9090,U+9092,U+9094,U+9096,U+9098,U+909a,U+909c,U+909e-90a0,U+90a4-90a5,U+90a7-90a9,U+90ab,U+90ad,U+90b2,U+90b7,U+90bc-90bd,U+90bf-90c0,U+90c2-90c3,U+90c6,U+90c8-90c9,U+90cb-90cd,U+90d2,U+90d4-90d6,U+90d8-90da,U+90de-90e0,U+90e3-90e5,U+90e9-90ea,U+90ec,U+90ee,U+90f0-90f3,U+90f5-90f7,U+90f9-90fc,U+90ff-9101,U+9103,U+9105-9118,U+911a-911d,U+911f-9121,U+9124-912e,U+9130,U+9132-9138,U+913a-9142,U+9144-9145,U+9147-9148,U+9151,U+9153-9156,U+9158\",\n },\n },\n {\n uri: _58,\n descriptors: {\n unicodeRange:\n \"U+8f03-8f65,U+8f6a,U+8f80,U+8f8c,U+8f92,U+8f9d,U+8fa0-8fa2,U+8fa4-8fa7,U+8faa,U+8fac-8faf,U+8fb2-8fb5,U+8fb7-8fb8,U+8fba-8fbc,U+8fbf-8fc0,U+8fc3,U+8fc6,U+8fc9-8fcd,U+8fcf,U+8fd2,U+8fd6-8fd7,U+8fda,U+8fe0-8fe1,U+8fe3,U+8fe7,U+8fec,U+8fef,U+8ff1-8ff2,U+8ff4-8ff6,U+8ffa-8ffc,U+8ffe-8fff,U+9007-9008,U+900c,U+900e,U+9013,U+9015,U+9018-9019,U+901c,U+9023-9025,U+9027-902a\",\n },\n },\n {\n uri: _59,\n descriptors: {\n unicodeRange:\n \"U+8d03-8d1c,U+8d20,U+8d51-8d52,U+8d57,U+8d5f,U+8d65,U+8d68-8d6a,U+8d6c,U+8d6e-8d6f,U+8d71-8d72,U+8d78-8d80,U+8d82-8d83,U+8d86-8d89,U+8d8c-8d90,U+8d92-8d93,U+8d95-8d9e,U+8da0-8da2,U+8da4-8db0,U+8db2,U+8db6-8db7,U+8db9,U+8dbb,U+8dbd,U+8dc0-8dc2,U+8dc5,U+8dc7-8dca,U+8dcd,U+8dd0,U+8dd2-8dd5,U+8dd8-8dd9,U+8ddc,U+8de0-8de2,U+8de5-8de7,U+8de9,U+8ded-8dee,U+8df0-8df2,U+8df4,U+8df6,U+8dfc,U+8dfe-8e04,U+8e06-8e08,U+8e0b,U+8e0d-8e0e,U+8e10-8e13,U+8e15-8e1c,U+8e20-8e21,U+8e24-8e28,U+8e2b,U+8e2d,U+8e30,U+8e32-8e34,U+8e36-8e38,U+8e3b-8e3c,U+8e3e-8e3f,U+8e43,U+8e45-8e46\",\n },\n },\n {\n uri: _60,\n descriptors: {\n unicodeRange:\n \"U+8bea,U+8c09,U+8c1e,U+8c38-8c40,U+8c42-8c45,U+8c48,U+8c4a-8c4b,U+8c4d-8c54,U+8c56-8c59,U+8c5b-8c60,U+8c63-8c69,U+8c6c-8c72,U+8c74-8c77,U+8c7b-8c81,U+8c83-8c84,U+8c86-8c88,U+8c8b,U+8c8d-8c93,U+8c95-8c97,U+8c99-8d02\",\n },\n },\n {\n uri: _61,\n descriptors: {\n unicodeRange:\n \"U+8a64-8a78,U+8a7a-8a88,U+8a8b-8a92,U+8a94-8b06,U+8b08-8b1b\",\n },\n },\n {\n uri: _62,\n descriptors: {\n unicodeRange:\n \"U+8987-89c0,U+89c3,U+89cd,U+89d3-89d5,U+89d7-89d9,U+89db,U+89dd,U+89df-89e2,U+89e4,U+89e7-89ea,U+89ec-89ee,U+89f0-89f2,U+89f4-89ff,U+8a01-8a06,U+8a08-8a3d,U+8a3f-8a47,U+8a49-8a63\",\n },\n },\n {\n uri: _63,\n descriptors: {\n unicodeRange:\n \"U+87e3-87e4,U+87e6-87e9,U+87eb-87ed,U+87ef-87f8,U+87fa-87fd,U+87ff-8802,U+8804-8809,U+880b-8812,U+8814,U+8817-881a,U+881c-8820,U+8823-8831,U+8833-8838,U+883a-883b,U+883d-883f,U+8841-8843,U+8846-884b,U+884e-8853,U+8855-8856,U+8858,U+885a-8860,U+8866-8867,U+886a,U+886d,U+886f,U+8871,U+8873-8876,U+8878-887c,U+8880,U+8883,U+8886-8887,U+8889-888a,U+888c,U+888e-8891,U+8893-8895,U+8897-889b,U+889d-88a1,U+88a3,U+88a5-88aa,U+88ac,U+88ae-88b0,U+88b2-88b6,U+88b8-88bb\",\n },\n },\n {\n uri: _64,\n descriptors: {\n unicodeRange:\n \"U+86e7-86e8,U+86ea-86ec,U+86ef,U+86f5-86f7,U+86fa-86fd,U+86ff,U+8701,U+8704-8706,U+870b-870c,U+870e-8711,U+8714,U+8716,U+8719,U+871b,U+871d,U+871f-8720,U+8724,U+8726-8728,U+872a-872d,U+872f-8730,U+8732-8733,U+8735-8736,U+8738-873a,U+873c-873d,U+8740-8746,U+874a-874b,U+874d,U+874f-8752,U+8754-8756,U+8758,U+875a-875f,U+8761-8762,U+8766-876d,U+876f,U+8771-8773,U+8775,U+8777-877a,U+877f-8781,U+8784,U+8786-8787,U+8789-878a,U+878c,U+878e-8792,U+8794-8796,U+8798-879e,U+87a0-87a7,U+87a9-87aa,U+87ae,U+87b0-87b2,U+87b4,U+87b6-87b9,U+87bb-87bc,U+87be-87bf,U+87c1-87c5,U+87c7-87c9,U+87cc-87d0,U+87d4-87da,U+87dc-87df,U+87e1-87e2\",\n },\n },\n {\n uri: _65,\n descriptors: {\n unicodeRange:\n \"U+8604,U+8606-8610,U+8612-8615,U+8617-8626,U+8628,U+862a-8637,U+8639-863b,U+863d-864c,U+8652-8653,U+8655-8659,U+865b-865d,U+865f-8661,U+8663-866a,U+866d,U+866f-8670,U+8672-8678,U+8683-8689,U+868e-8692,U+8694,U+8696-869b,U+869e-86a2,U+86a5-86a6,U+86ab,U+86ad-86ae,U+86b2-86b3,U+86b7-86b9,U+86bb-86bf,U+86c1-86c3,U+86c5,U+86c8,U+86cc-86cd,U+86d2-86d3,U+86d5-86d7,U+86da,U+86dc-86dd,U+86e0-86e3,U+86e5-86e6\",\n },\n },\n {\n uri: _66,\n descriptors: {\n unicodeRange:\n \"U+8456,U+8458,U+845d-8460,U+8462,U+8464-8468,U+846a,U+846e-8470,U+8472,U+8474,U+8477,U+8479,U+847b-8481,U+8483-8486,U+848a,U+848d,U+848f-8496,U+8498,U+849a-849b,U+849d-84a0,U+84a2-84ae,U+84b0-84b1,U+84b3,U+84b5-84b7,U+84bb-84bc,U+84be,U+84c0,U+84c2-84c3,U+84c5-84c8,U+84cb-84cc,U+84ce-84cf,U+84d2,U+84d4-84d5,U+84d7-84dc,U+84de,U+84e1-84e2,U+84e4,U+84e7-84eb,U+84ed-84ef,U+84f1-84fb,U+84fd-84fe,U+8500-850b,U+850d-8510,U+8512,U+8514-8516,U+8518-8519,U+851b-851e,U+8520,U+8522-852a,U+852d-8536,U+853e-8542,U+8544-8547,U+854b-854f\",\n },\n },\n {\n uri: _67,\n descriptors: {\n unicodeRange:\n \"U+82c2-82c3,U+82c5-82c6,U+82c9,U+82d0,U+82d6,U+82d9-82da,U+82dd,U+82e2,U+82e7-82ea,U+82ec-82ee,U+82f0,U+82f2-82f3,U+82f5-82f6,U+82f8,U+82fa,U+82fc-8300,U+830a-830b,U+830d,U+8310,U+8312-8313,U+8316,U+8318-8319,U+831d-8326,U+8329-832a,U+832e,U+8330,U+8332,U+8337,U+833b,U+833d-833f,U+8341-8342,U+8344-8345,U+8348,U+834a-834e,U+8353,U+8355-8359,U+835d,U+8362,U+8370-8376,U+8379-837a,U+837e-8384,U+8387-8388,U+838a-838d,U+838f-8391,U+8394-8397,U+8399-839a,U+839d,U+839f,U+83a1-83a7,U+83ac-83af,U+83b5,U+83bb,U+83be-83bf,U+83c2-83c4,U+83c6,U+83c8-83c9,U+83cb,U+83cd-83ce,U+83d0-83d3,U+83d5,U+83d7,U+83d9-83db,U+83de,U+83e2-83e4,U+83e6-83e8,U+83eb-83ef,U+83f3-83f7,U+83fa-83fc,U+83fe-8400,U+8402,U+8405,U+8407-840a,U+8410,U+8412-8417,U+8419-841b,U+841e-8423,U+8429-8430,U+8432-8437,U+8439-843b,U+843e-8445,U+8447-8450,U+8452-8455\",\n },\n },\n {\n uri: _68,\n descriptors: {\n unicodeRange:\n \"U+81a4-81a5,U+81a7,U+81a9,U+81ab-81b2,U+81b4-81b9,U+81bc-81bf,U+81c4-81c5,U+81c7-81c9,U+81cb,U+81cd-81e2,U+81e4-81e6,U+81e8-81e9,U+81eb,U+81ee-81f2,U+81f5-81fa,U+81fd,U+81ff,U+8203,U+8207-820b,U+820e-820f,U+8211,U+8213,U+8215-821a,U+821d,U+8220,U+8224-8227,U+8229,U+822e,U+8232,U+823a,U+823c-823d,U+823f-8243,U+8245-8246,U+8248,U+824a,U+824c-824e,U+8250-8257,U+8259,U+825b-825e,U+8260-8267,U+8269-826d,U+8271,U+8275-8278,U+827b-827c,U+8280-8281,U+8283,U+8285-8287,U+8289,U+828c,U+8290,U+8293-8296,U+829a-829b,U+829e,U+82a0,U+82a2-82a3,U+82a7,U+82b2,U+82b5-82b6,U+82ba-82bc,U+82bf-82c0\",\n },\n },\n {\n uri: _69,\n descriptors: {\n unicodeRange:\n \"U+8059,U+805b-8068,U+806b-8070,U+8072-807e,U+8081-8082,U+8085,U+8088,U+808a,U+808d-8092,U+8094-8095,U+8097,U+8099,U+809e,U+80a3,U+80a6-80a8,U+80ac,U+80b0,U+80b3,U+80b5-80b6,U+80b8-80b9,U+80bb,U+80c5,U+80c7-80cb,U+80cf-80d5,U+80d8,U+80df-80e0,U+80e2-80e3,U+80e6,U+80ee,U+80f5,U+80f7,U+80f9,U+80fb,U+80fe-8101,U+8103-8105,U+8107-8108,U+810b-810c,U+8115,U+8117,U+8119,U+811b-811d,U+811f-812b,U+812d-812e,U+8130,U+8133-8135,U+8137,U+8139-813d,U+813f-8145,U+8147,U+8149,U+814d-814f,U+8152,U+8156-8158,U+815b-815f,U+8161-8164,U+8166,U+8168,U+816a-816c,U+816f,U+8172-8173,U+8175-8178,U+8181,U+8183-8187,U+8189,U+818b-818e,U+8190,U+8192-8197,U+8199-819a,U+819e-81a2\",\n },\n },\n {\n uri: _70,\n descriptors: {\n unicodeRange:\n \"U+7f3c-7f41,U+7f43,U+7f46-7f4f,U+7f52-7f53,U+7f56,U+7f59,U+7f5b-7f5e,U+7f60,U+7f63-7f67,U+7f6b-7f6d,U+7f6f-7f70,U+7f73,U+7f75-7f78,U+7f7a-7f7d,U+7f7f-7f80,U+7f82-7f89,U+7f8b,U+7f8d,U+7f8f-7f93,U+7f95-7f99,U+7f9b-7f9c,U+7fa0,U+7fa2-7fa3,U+7fa5-7fa6,U+7fa8-7fae,U+7fb1,U+7fb3-7fb7,U+7fba-7fbb,U+7fbe,U+7fc0,U+7fc2-7fc4,U+7fc6-7fc9,U+7fcb,U+7fcd,U+7fcf-7fd3,U+7fd6-7fd7,U+7fd9-7fde,U+7fe2-7fe4,U+7fe7-7fe8,U+7fea-7fed,U+7fef,U+7ff2,U+7ff4-7ffa,U+7ffd-7fff,U+8002,U+8007-800a,U+800e-800f,U+8011,U+8013,U+801a-801b,U+801d-801f,U+8021,U+8023-8024,U+802b-8030,U+8032,U+8034,U+8039-803a,U+803c,U+803e,U+8040-8041,U+8044-8045,U+8047-8049,U+804e-8051,U+8053,U+8055-8057\",\n },\n },\n {\n uri: _71,\n descriptors: {\n unicodeRange:\n \"U+7cd8,U+7cda-7cdb,U+7cdd-7cde,U+7ce1-7ce7,U+7ce9-7cee,U+7cf0-7cf7,U+7cf9-7cfa,U+7cfc-7d09,U+7d0b-7d1f,U+7d21,U+7d23-7d26,U+7d28-7d2a,U+7d2c-7d2e,U+7d30-7d6d,U+7d6f-7d76,U+7d78-7d94\",\n },\n },\n {\n uri: _72,\n descriptors: {\n unicodeRange:\n \"U+7afe,U+7b00-7b02,U+7b05,U+7b07,U+7b09,U+7b0c-7b0e,U+7b10,U+7b12-7b13,U+7b16-7b18,U+7b1a,U+7b1c-7b1d,U+7b1f,U+7b21-7b23,U+7b27,U+7b29,U+7b2d,U+7b2f-7b30,U+7b32,U+7b34-7b37,U+7b39,U+7b3b,U+7b3d,U+7b3f-7b44,U+7b46,U+7b48,U+7b4a,U+7b4d-7b4e,U+7b53,U+7b55,U+7b57,U+7b59,U+7b5c,U+7b5e-7b5f,U+7b61,U+7b63-7b6d,U+7b6f-7b70,U+7b73-7b74,U+7b76,U+7b78,U+7b7a,U+7b7c-7b7d,U+7b7f,U+7b81-7b84,U+7b86-7b8c,U+7b8e-7b8f,U+7b91-7b93,U+7b96,U+7b98-7b9b,U+7b9e-7ba0,U+7ba3-7ba5,U+7bae-7bb0,U+7bb2-7bb3,U+7bb5-7bb7,U+7bb9-7bc0,U+7bc2-7bc5,U+7bc8-7bcb,U+7bcd-7bd0,U+7bd2,U+7bd4-7bd8,U+7bdb-7bdc,U+7bde-7be0,U+7be2-7be4,U+7be7-7be9,U+7beb-7bed,U+7bef-7bf0,U+7bf2-7bf6,U+7bf8-7bfb,U+7bfd,U+7bff-7c06,U+7c08-7c0a,U+7c0d-7c0e,U+7c10-7c13\",\n },\n },\n {\n uri: _73,\n descriptors: {\n unicodeRange:\n \"U+7a10-7a13,U+7a15-7a16,U+7a18-7a19,U+7a1b-7a1d,U+7a1f,U+7a21-7a22,U+7a24-7a32,U+7a34-7a36,U+7a38,U+7a3a,U+7a3e,U+7a40-7a45,U+7a47-7a50,U+7a52-7a56,U+7a58-7a6f,U+7a71-7a73,U+7a75,U+7a7b-7a7e,U+7a82,U+7a85,U+7a87,U+7a89-7a8c,U+7a8e-7a90,U+7a93-7a94,U+7a99-7a9b,U+7a9e,U+7aa1-7aa4,U+7aa7,U+7aa9-7aab,U+7aae-7ab2,U+7ab4-7abe,U+7ac0-7aca,U+7acc-7ad5,U+7ad7-7ad8,U+7ada-7add,U+7ae1-7ae2,U+7ae4,U+7ae7-7aec,U+7aee,U+7af0-7af8,U+7afb-7afc\",\n },\n },\n {\n uri: _74,\n descriptors: {\n unicodeRange:\n \"U+790d-7912,U+7914-791d,U+791f-7923,U+7925-7933,U+7935-7939,U+793d,U+793f,U+7942-7945,U+7947,U+794a-7952,U+7954-7955,U+7958-7959,U+7961,U+7963-7964,U+7966,U+7969-796c,U+796e,U+7970-7976,U+7979,U+797b-797f,U+7982-7983,U+7986-7989,U+798b-798e,U+7990-7999,U+799b-79a6,U+79a8-79b2,U+79b4-79b8,U+79bc,U+79bf,U+79c2,U+79c4-79c5,U+79c7-79c8,U+79ca,U+79cc,U+79ce-79d0,U+79d3-79d4,U+79d6-79d7,U+79d9-79de,U+79e0-79e2,U+79e5,U+79e8,U+79ea,U+79ec,U+79ee,U+79f1-79f7,U+79f9-79fa,U+79fc,U+79fe-79ff,U+7a01,U+7a04-7a05,U+7a07-7a0a,U+7a0c,U+7a0f\",\n },\n },\n {\n uri: _75,\n descriptors: {\n unicodeRange:\n \"U+77d8-77da,U+77dd-77e1,U+77e4,U+77e6,U+77e8,U+77ea,U+77ef-77f2,U+77f4-77f5,U+77f7,U+77f9-77fc,U+7803-7808,U+780a-780b,U+780e-7810,U+7813,U+7815,U+7819,U+781b,U+781e,U+7820-7822,U+7824,U+7828,U+782a-782b,U+782e-782f,U+7831-7833,U+7835-7836,U+783d,U+783f,U+7841-7844,U+7846,U+7848-784b,U+784d,U+784f,U+7851,U+7853-7854,U+7858-785c,U+785e-7869,U+786f-7876,U+7878-787b,U+787d-7886,U+7888,U+788a-788b,U+788f-7890,U+7892,U+7894-7896,U+7899,U+789d-789e,U+78a0,U+78a2,U+78a4,U+78a6,U+78a8-78af,U+78b5-78b8,U+78ba-78bd,U+78bf-78c0,U+78c2-78c4,U+78c6-78c8,U+78cc-78cf,U+78d1-78d3,U+78d6-78d8,U+78da-78e7,U+78e9-78eb,U+78ed-78f1,U+78f3,U+78f5-78f6,U+78f8-78f9,U+78fb-7900,U+7902-7904,U+7906-790c\",\n },\n },\n {\n uri: _76,\n descriptors: {\n unicodeRange:\n \"U+76af-76b0,U+76b3,U+76b5-76be,U+76c0-76c1,U+76c3-76c4,U+76c7,U+76c9,U+76cb-76cc,U+76d3,U+76d5,U+76d9-76da,U+76dc-76de,U+76e0-76e4,U+76e6-76ed,U+76f0,U+76f3,U+76f5-76f7,U+76fa-76fb,U+76fd,U+76ff-7703,U+7705-7706,U+770a,U+770c,U+770e-7718,U+771b-771e,U+7721,U+7723-7725,U+7727,U+772a-772c,U+772e,U+7730-7734,U+7739,U+773b,U+773d-773f,U+7742,U+7744-7746,U+7748-774f,U+7752-7759,U+775c-7760,U+7764,U+7767,U+7769-776a,U+776d-7778,U+777a-777c,U+7781-7783,U+7786-778b,U+778f-7790,U+7793-779e,U+77a1,U+77a3-77a4,U+77a6,U+77a8,U+77ab,U+77ad-77af,U+77b1-77b2,U+77b4,U+77b6-77ba,U+77bc,U+77be,U+77c0-77cc,U+77ce-77d6\",\n },\n },\n {\n uri: _77,\n descriptors: {\n unicodeRange:\n \"U+7589-758a,U+758c-758e,U+7590,U+7593,U+7595,U+7598,U+759b-759c,U+759e,U+75a2,U+75a6-75aa,U+75ad,U+75b6-75b7,U+75ba-75bb,U+75bf-75c1,U+75c6,U+75cb-75cc,U+75ce-75d1,U+75d3,U+75d7,U+75d9-75da,U+75dc-75dd,U+75df-75e1,U+75e5,U+75e9,U+75ec-75ef,U+75f2-75f3,U+75f5-75f8,U+75fa-75fb,U+75fd-75fe,U+7602,U+7604,U+7606-7609,U+760b,U+760d-760f,U+7611-7614,U+7616,U+761a,U+761c-761e,U+7621,U+7623,U+7627-7628,U+762c,U+762e-762f,U+7631-7632,U+7636-7637,U+7639-763b,U+763d,U+7641-7642,U+7644-764b,U+764e-7653,U+7655,U+7657-765b,U+765d,U+765f-7662,U+7664-766a,U+766c-766e,U+7670-7677,U+7679-767a,U+767c,U+767f-7681,U+7683,U+7685,U+7689-768a,U+768c-768d,U+768f-7690,U+7692,U+7694-7695,U+7697-7698,U+769a-76a3,U+76a5-76ad\",\n },\n },\n {\n uri: _78,\n descriptors: {\n unicodeRange:\n \"U+7492-749b,U+749d,U+749f-74a6,U+74aa-74b9,U+74bb-74d1,U+74d3-74db,U+74dd,U+74df,U+74e1,U+74e5,U+74e7-74ed,U+74f0-74f3,U+74f5,U+74f8-74fe,U+7500-7503,U+7505-750c,U+750e,U+7510,U+7512,U+7514-7517,U+751b,U+751d-751e,U+7520-7524,U+7526-7527,U+752a,U+752e,U+7534,U+7536,U+7539,U+753c-753d,U+753f,U+7541-7544,U+7546-7547,U+7549-754a,U+754d,U+7550-7553,U+7555-7558,U+755d-7564,U+7567-7569,U+756b-7571,U+7573,U+7575-7577,U+757a-757e,U+7580-7582,U+7584-7585,U+7587-7588\",\n },\n },\n {\n uri: _79,\n descriptors: {\n unicodeRange:\n \"U+7372-737d,U+737f-7383,U+7385-7386,U+7388,U+738a,U+738c-738d,U+738f-7390,U+7392-7395,U+7397-739a,U+739c-739e,U+73a0-73a1,U+73a3-73a8,U+73aa,U+73ac-73ad,U+73b1,U+73b4-73b6,U+73b8-73b9,U+73bc-73bf,U+73c1,U+73c3-73c7,U+73cb-73cc,U+73ce,U+73d2-73d8,U+73da-73dd,U+73df,U+73e1-73e4,U+73e6,U+73e8,U+73ea-73ec,U+73ee-73f1,U+73f3-7402,U+7404,U+7407-7408,U+740b-740e,U+7411-7419,U+741c-7421,U+7423-7424,U+7427,U+7429,U+742b,U+742d,U+742f,U+7431-7432,U+7437-743b,U+743d-7440,U+7442-7454,U+7456,U+7458,U+745d,U+7460-746c,U+746e-746f,U+7471-7475,U+7478-747d,U+747f,U+7482,U+7484-7486,U+7488-748a,U+748c-748d,U+748f,U+7491\",\n },\n },\n {\n uri: _80,\n descriptors: {\n unicodeRange:\n \"U+7054-705d,U+705f-706a,U+706e,U+7071-7074,U+7077,U+7079-707b,U+707d,U+7081-7084,U+7086-7088,U+708b-708d,U+708f-7091,U+7093,U+7097-7098,U+709a-709b,U+709e-70aa,U+70b0,U+70b2,U+70b4-70b6,U+70ba,U+70be-70bf,U+70c4-70c7,U+70c9,U+70cb-70d7,U+70da,U+70dc-70de,U+70e0-70e3,U+70e5,U+70ea,U+70ee,U+70f0-70f6,U+70f8,U+70fa-70fc,U+70fe-7108,U+710b-710f,U+7111-7112,U+7114,U+7117,U+711b-7125,U+7127-712e,U+7132-7135,U+7137-7144,U+7146-7149,U+714b,U+714d,U+714f-715b,U+715d,U+715f-7163,U+7165,U+7169-716d,U+716f-7171,U+7174-7177\",\n },\n },\n {\n uri: _81,\n descriptors: {\n unicodeRange:\n \"U+722e-722f,U+7232-7234,U+723a,U+723c,U+723e,U+7240-7246,U+7249-724b,U+724e-7251,U+7253-7255,U+7257-7258,U+725a,U+725c,U+725e,U+7260,U+7263-7265,U+7268,U+726a-726d,U+7270-7271,U+7273-7274,U+7276-7278,U+727b-727d,U+7282-7283,U+7285-7289,U+728c,U+728e,U+7290-7291,U+7293-729e,U+72a0-72ab,U+72ae,U+72b1-72b3,U+72b5,U+72ba-72c0,U+72c5-72c7,U+72c9-72cc,U+72cf,U+72d1,U+72d3-72d6,U+72d8,U+72da-72dd,U+72df,U+72e2-72e7,U+72ea-72eb,U+72f5-72f6,U+72f9,U+72fd-7300,U+7302,U+7304-7309,U+730b-730d,U+730f-7312,U+7314,U+7318-731a,U+731f-7320,U+7323-7324,U+7326-7328,U+732d,U+732f-7330,U+7332-7333,U+7335-7336,U+733a-733d,U+7340-734c,U+734e-734f,U+7351,U+7353-7356,U+7358-735f,U+7361-736b,U+736e,U+7370-7371\",\n },\n },\n {\n uri: _82,\n descriptors: {\n unicodeRange:\n \"U+6ec5-6ec6,U+6ec8-6eca,U+6ecc-6ece,U+6ed0,U+6ed2,U+6ed6,U+6ed8-6ed9,U+6edb-6edd,U+6ee3,U+6ee7,U+6eea-6ef3,U+6ef5-6ef8,U+6efa-6f01,U+6f03-6f05,U+6f07-6f08,U+6f0a-6f0e,U+6f10-6f12,U+6f16-6f1f,U+6f21-6f23,U+6f25-6f28,U+6f2c,U+6f2e,U+6f30,U+6f32,U+6f34-6f35,U+6f37-6f3d,U+6f3f-6f45,U+6f48-6f4a,U+6f4c,U+6f4e-6f57,U+6f59-6f5b,U+6f5d,U+6f5f-6f61,U+6f63-6f65,U+6f67-6f6c,U+6f6f-6f71,U+6f73,U+6f75-6f77,U+6f79,U+6f7b,U+6f7d-6f83,U+6f85-6f87,U+6f8a-6f8b,U+6f8f-6f9b,U+6f9d-6fa0,U+6fa2-6fa6,U+6fa8-6fb1\",\n },\n },\n {\n uri: _83,\n descriptors: {\n unicodeRange:\n \"U+6d73,U+6d75-6d76,U+6d79-6d7b,U+6d7d-6d81,U+6d83-6d84,U+6d86-6d87,U+6d8a-6d8b,U+6d8d,U+6d8f-6d90,U+6d92,U+6d96-6d9a,U+6d9c,U+6da2,U+6da5,U+6dac-6dad,U+6db0-6db1,U+6db3-6db4,U+6db6-6db7,U+6db9-6dbe,U+6dc1-6dc3,U+6dc8-6dca,U+6dcd-6dd0,U+6dd2-6dd5,U+6dd7,U+6dda-6ddc,U+6ddf,U+6de2-6de3,U+6de5,U+6de7-6dea,U+6ded,U+6def-6df0,U+6df2,U+6df4-6df6,U+6df8,U+6dfa,U+6dfd-6e04,U+6e06-6e09,U+6e0b,U+6e0f,U+6e12-6e13,U+6e15,U+6e18-6e19,U+6e1b-6e1c,U+6e1e-6e1f,U+6e22,U+6e26-6e28,U+6e2a,U+6e2c,U+6e2e,U+6e30-6e31,U+6e33,U+6e35-6e37,U+6e39,U+6e3b-6e42,U+6e45-6e4c,U+6e4f-6e52,U+6e55,U+6e57,U+6e59-6e5a,U+6e5c-6e5e,U+6e60-6e6a,U+6e6c-6e6d,U+6e6f-6e7d,U+6e80-6e82,U+6e84,U+6e87-6e88,U+6e8a-6e8e,U+6e91-6e97,U+6e99-6e9b,U+6e9d-6e9e,U+6ea0-6ea1,U+6ea3-6ea4,U+6ea6,U+6ea8-6ea9,U+6eab-6eae,U+6eb0,U+6eb3,U+6eb5,U+6eb8-6eb9,U+6ebc,U+6ebe-6ec0,U+6ec3-6ec4\",\n },\n },\n {\n uri: _84,\n descriptors: {\n unicodeRange:\n \"U+6bbb-6bbe,U+6bc0,U+6bc3-6bc4,U+6bc6-6bca,U+6bcc,U+6bce,U+6bd0-6bd1,U+6bd8,U+6bda,U+6bdc-6be0,U+6be2-6be9,U+6bec-6bee,U+6bf0-6bf2,U+6bf4,U+6bf6-6bf8,U+6bfa-6bfc,U+6bfe-6c04,U+6c08-6c0c,U+6c0e,U+6c12,U+6c17,U+6c1c-6c1e,U+6c20,U+6c23,U+6c25,U+6c2b-6c2d,U+6c31,U+6c33,U+6c36-6c37,U+6c39-6c3c,U+6c3e-6c3f,U+6c43-6c45,U+6c48,U+6c4b-6c4f,U+6c51-6c53,U+6c56,U+6c58-6c5a,U+6c62-6c63,U+6c65-6c67,U+6c6b-6c6f,U+6c71,U+6c73,U+6c75,U+6c77-6c78,U+6c7a-6c7c,U+6c7f-6c80,U+6c84,U+6c87,U+6c8a-6c8b,U+6c8d-6c8e,U+6c91-6c92,U+6c95-6c98,U+6c9a,U+6c9c-6c9e,U+6ca0,U+6ca2,U+6ca8,U+6cac,U+6caf-6cb0,U+6cb4-6cb7,U+6cba,U+6cc0-6cc3,U+6cc6-6cc8,U+6ccb,U+6ccd-6ccf,U+6cd1-6cd2,U+6cd8-6cda,U+6cdc-6cdd,U+6cdf,U+6ce4,U+6ce6-6ce7,U+6ce9,U+6cec-6ced,U+6cf2,U+6cf4,U+6cf9,U+6cff-6d00,U+6d02-6d03,U+6d05-6d06,U+6d08-6d0a,U+6d0d,U+6d0f-6d11,U+6d13-6d16,U+6d18,U+6d1c-6d1d,U+6d1f-6d24,U+6d26,U+6d28-6d29,U+6d2c-6d2d,U+6d2f-6d30,U+6d34,U+6d36-6d38,U+6d3a,U+6d3f-6d40,U+6d42,U+6d44,U+6d49,U+6d4c,U+6d50,U+6d55-6d58,U+6d5b,U+6d5d,U+6d5f,U+6d61-6d62,U+6d64-6d65,U+6d67-6d68,U+6d6b-6d6d,U+6d70-6d72\",\n },\n },\n {\n uri: _85,\n descriptors: {\n unicodeRange:\n \"U+6967-696a,U+696c-696d,U+696f-6970,U+6972-6976,U+697a-697b,U+697d-697f,U+6981,U+6983,U+6985,U+698a-698c,U+698e-6993,U+6996-6997,U+6999-699a,U+699d-69a6,U+69a9-69aa,U+69ac,U+69ae-69b0,U+69b2-69b3,U+69b5-69b6,U+69b8-69ba,U+69bc-69c0,U+69c2-69c9,U+69cb,U+69cd,U+69cf,U+69d1-69d3,U+69d5-69da,U+69dc-69de,U+69e1-69ec,U+69ee-69f1,U+69f3-69fc,U+69fe,U+6a00-6a09,U+6a0b-6a16,U+6a19-6a1e,U+6a20,U+6a22-6a27,U+6a29,U+6a2b-6a2e,U+6a30,U+6a32-6a34,U+6a36-6a3c,U+6a3f-6a43,U+6a45-6a46,U+6a48-6a4a\",\n },\n },\n {\n uri: _86,\n descriptors: {\n unicodeRange:\n \"U+6830-6831,U+6834-6836,U+683a-683b,U+683f,U+6847,U+684b,U+684d,U+684f,U+6852,U+6856-685f,U+686a,U+686c-6873,U+6875,U+6878-6880,U+6882,U+6884,U+6887-688e,U+6890-6892,U+6894-6896,U+6898-68a1,U+68a3-68a5,U+68a9-68ac,U+68ae,U+68b1-68b2,U+68b4,U+68b6-68bf,U+68c1,U+68c3-68c8,U+68ca,U+68cc,U+68ce-68d1,U+68d3-68d4,U+68d6-68d7,U+68d9,U+68db-68df,U+68e1-68e2,U+68e4-68ed,U+68ef,U+68f2-68f4,U+68f6-68f8,U+68fb,U+68fd-6900,U+6902-6904,U+6906-690a,U+690c,U+690f,U+6911,U+6913-691e,U+6921-6923,U+6925-692c,U+692e-692f,U+6931-6933,U+6935-6938,U+693a-693c,U+693e,U+6940-6941,U+6943-6953,U+6955-6956,U+6958-6959,U+695b-695c,U+695f,U+6961-6962,U+6964-6965\",\n },\n },\n {\n uri: _87,\n descriptors: {\n unicodeRange:\n \"U+66b8,U+66ba-66bd,U+66bf-66d8,U+66da,U+66de-66e5,U+66e7-66e8,U+66ea-66ef,U+66f1,U+66f5-66f6,U+66f8,U+66fa-66fb,U+66fd,U+6701-6707,U+670c,U+670e-670f,U+6711-6713,U+6716,U+6718-671a,U+671c,U+671e,U+6720-6725,U+6727,U+6729,U+672e,U+6730,U+6732-6733,U+6736-6739,U+673b-673c,U+673e-673f,U+6741,U+6744-6745,U+6747,U+674a-674b,U+674d,U+6752,U+6754-6755,U+6757-675b,U+675d,U+6762-6764,U+6766-6767,U+676b-676c,U+676e,U+6771,U+6774,U+6776,U+6778-677b,U+677d,U+6780,U+6782-6783,U+6785-6786,U+6788,U+678a,U+678c-678f,U+6791-6794,U+6796,U+6799,U+679b,U+679f-67a1,U+67a4,U+67a6,U+67a9,U+67ac,U+67ae,U+67b1-67b2,U+67b4,U+67b9-67c0,U+67c2,U+67c5-67ce,U+67d5-67d7,U+67db,U+67df,U+67e1,U+67e3-67e4,U+67e6-67e8,U+67ea-67eb,U+67ed-67ee,U+67f2,U+67f5-67fc,U+67fe,U+6801-6804,U+6806,U+680d,U+6810,U+6812,U+6814-6815,U+6818-681c,U+681e-6820,U+6822-6828,U+682b-682f\",\n },\n },\n {\n uri: _88,\n descriptors: {\n unicodeRange:\n \"U+6569-656a,U+656d-656f,U+6571,U+6573,U+6575-6576,U+6578-6586,U+6588-658a,U+658d-658f,U+6592,U+6594-6596,U+6598,U+659a,U+659d-659e,U+65a0,U+65a2-65a3,U+65a6,U+65a8,U+65aa,U+65ac,U+65ae,U+65b1-65b8,U+65ba-65bb,U+65be-65c0,U+65c2,U+65c7-65ca,U+65cd,U+65d0-65d1,U+65d3-65d5,U+65d8-65df,U+65e1,U+65e3-65e4,U+65ea-65eb,U+65f2-65f5,U+65f8-65f9,U+65fb-65ff,U+6601,U+6604-6605,U+6607-6609,U+660b,U+660d,U+6610-6612,U+6616-6618,U+661a-661c,U+661e,U+6621-6624,U+6626,U+6629-662c,U+662e,U+6630,U+6632-6633,U+6637-663b,U+663d,U+663f-6640,U+6642,U+6644-664a,U+664d-664e,U+6650-6651,U+6658-6659,U+665b-665e,U+6660,U+6662-6663,U+6665,U+6667,U+6669-666d,U+6671-6673,U+6675,U+6678-6679,U+667b-667d,U+667f-6681,U+6683,U+6685-6686,U+6688-668b,U+668d-6690,U+6692-6695,U+6698-669c,U+669e-66a6,U+66a9-66ad,U+66af-66b3,U+66b5-66b7\",\n },\n },\n {\n uri: _89,\n descriptors: {\n unicodeRange:\n \"U+5f30,U+5f32-5f38,U+5f3b,U+5f3d-5f3f,U+5f41-5f4f,U+5f51,U+5f54,U+5f59-5f5c,U+5f5e-5f60,U+5f63,U+5f65,U+5f67-5f68,U+5f6b,U+5f6e-5f6f,U+5f72,U+5f74-5f76,U+5f78,U+5f7a,U+5f7d-5f7f,U+5f83,U+5f86,U+5f8d-5f8f,U+5f91,U+5f93-5f94,U+5f96,U+5f9a-5f9b,U+5f9d-5fa0,U+5fa2-5fa7,U+5fa9,U+5fab-5fac,U+5faf-5fb4,U+5fb6,U+5fb8-5fbb,U+5fbe-5fc2,U+5fc7-5fc8,U+5fca-5fcb,U+5fce,U+5fd3-5fd5,U+5fda-5fdc,U+5fde-5fdf,U+5fe2-5fe3,U+5fe5-5fe6,U+5fe8-5fe9,U+5fec,U+5fef-5ff0,U+5ff2-5ff4,U+5ff6-5ff7,U+5ff9-5ffa,U+5ffc,U+6007-6009,U+600b-600c,U+6010-6011,U+6013,U+6017-6018,U+601a,U+601e-601f,U+6022-6024,U+602c-602e,U+6030-6034,U+6036-603a,U+603d-603e,U+6040,U+6044-604a,U+604c,U+604e-604f,U+6051,U+6053-6054,U+6056-6058,U+605b-605c,U+605e-6061,U+6065-6066,U+606e,U+6071-6072,U+6074-6075,U+6077,U+607e,U+6080-6082,U+6085-6088,U+608a-608b,U+608e-6091,U+6093,U+6095,U+6097-6099,U+609c,U+609e,U+60a1-60a2,U+60a4-60a5,U+60a7,U+60a9-60aa,U+60ae,U+60b0,U+60b3,U+60b5-60b7,U+60b9-60ba,U+60bd-60c4,U+60c7-60c9,U+60cc\",\n },\n },\n {\n uri: _90,\n descriptors: {\n unicodeRange:\n \"U+635a-635d,U+6360,U+6364-6366,U+6368,U+636a-636c,U+636f-6370,U+6372-6375,U+6378-6379,U+637c-637f,U+6381,U+6383-6386,U+638b,U+638d,U+6391,U+6393-6395,U+6397,U+6399-639f,U+63a1,U+63a4,U+63a6,U+63ab,U+63af,U+63b1-63b2,U+63b5-63b6,U+63b9,U+63bb,U+63bd,U+63bf-63c3,U+63c5,U+63c7-63c8,U+63ca-63cc,U+63d1,U+63d3-63d5,U+63d7-63dd,U+63df,U+63e2,U+63e4-63e8,U+63eb-63ec,U+63ee-63f1,U+63f3,U+63f5,U+63f7,U+63f9-63fc,U+63fe,U+6403-6404,U+6406-640a,U+640d-640e,U+6411-6412,U+6415-641a,U+641d,U+641f,U+6422-6425,U+6427-6429,U+642b,U+642e-6433,U+6435-6439,U+643b-643c,U+643e,U+6440,U+6442-6443,U+6449,U+644b-6451,U+6453,U+6455-6457,U+6459-645d,U+645f-6466,U+6468,U+646a-646c,U+646e-6477,U+647b-6481,U+6483,U+6486,U+6488-648f\",\n },\n },\n {\n uri: _91,\n descriptors: {\n unicodeRange:\n \"U+61c5-61c7,U+61c9,U+61cc-61d0,U+61d3,U+61d5-61e5,U+61e7-61f4,U+61f6-61fe,U+6200-6205,U+6207,U+6209,U+6213-6214,U+6219,U+621c-621e,U+6220,U+6223,U+6226-6229,U+622b,U+622d,U+622f-6232,U+6235-6236,U+6238-623c,U+6242,U+6244-6246,U+624a,U+624f-6250,U+6255-6257,U+6259-625a,U+625c-6262,U+6264-6265,U+6268,U+6271-6272,U+6274-6275,U+6277-6278,U+627a-627b,U+627d,U+6281-6283,U+6285-6288,U+628b-6290,U+6294,U+6299,U+629c-629e,U+62a3,U+62a6-62a7,U+62a9-62aa,U+62ad-62b0,U+62b2-62b4,U+62b6-62b8,U+62ba,U+62be,U+62c0-62c1,U+62c3,U+62cb,U+62cf,U+62d1,U+62d5,U+62dd-62de,U+62e0-62e1,U+62e4,U+62ea-62eb,U+62f0,U+62f2,U+62f5,U+62f8-62fb,U+6300,U+6303-6306,U+630a-630d,U+630f-6310,U+6312-6315,U+6317-6319,U+631c,U+6326-6327,U+6329,U+632c-632e,U+6330-6331,U+6333-6338,U+633b-633c,U+633e-6341,U+6344,U+6347-6348,U+634a,U+6351-6354,U+6356-6359\",\n },\n },\n {\n uri: _92,\n descriptors: {\n unicodeRange:\n \"U+5dd0-5dda,U+5ddc,U+5ddf-5de0,U+5de3-5de4,U+5dea,U+5dec-5ded,U+5df0,U+5df5-5df6,U+5df8-5dfc,U+5dff-5e00,U+5e04,U+5e07,U+5e09-5e0b,U+5e0d-5e0e,U+5e12-5e13,U+5e17,U+5e1e-5e25,U+5e28-5e2c,U+5e2f-5e30,U+5e32-5e36,U+5e39-5e3a,U+5e3e-5e41,U+5e43,U+5e46-5e4b,U+5e4d-5e53,U+5e56-5e5a,U+5e5c-5e5d,U+5e5f-5e60,U+5e63-5e71,U+5e75,U+5e77,U+5e79,U+5e7e,U+5e81-5e83,U+5e85,U+5e88-5e89,U+5e8c-5e8e,U+5e92,U+5e98,U+5e9b,U+5e9d,U+5ea1-5ea4,U+5ea8-5eac,U+5eae-5eb2,U+5eb4,U+5eba-5ebd,U+5ebf-5ec8,U+5ecb-5ed0,U+5ed4-5ed5,U+5ed7-5eda,U+5edc-5ee7,U+5ee9,U+5eeb-5ef3,U+5ef5,U+5ef8-5ef9,U+5efb-5efd,U+5f05-5f07,U+5f09,U+5f0c-5f0e,U+5f10,U+5f12,U+5f14,U+5f16,U+5f19-5f1a,U+5f1c-5f1e,U+5f21-5f24,U+5f28,U+5f2b-5f2c,U+5f2e\",\n },\n },\n {\n uri: _93,\n descriptors: {\n unicodeRange:\n \"U+60cd-60d0,U+60d2-60d4,U+60d6-60d7,U+60d9,U+60db,U+60de,U+60e1-60e5,U+60ea,U+60f1-60f2,U+60f5,U+60f7-60f8,U+60fb-60ff,U+6102-6105,U+6107,U+610a-610c,U+6110-6114,U+6116-6119,U+611b-611e,U+6121-6122,U+6125,U+6128-612a,U+612c-613e,U+6140-6147,U+6149,U+614b,U+614d,U+614f-6150,U+6152-6154,U+6156-615c,U+615e-6161,U+6163-6166,U+6169-616f,U+6171-6174,U+6176,U+6178-618a,U+618c-618d,U+618f-6193,U+6195-619c,U+619e-61a6,U+61aa-61ab,U+61ad-61b6,U+61b8-61bd,U+61bf-61c1,U+61c3-61c4\",\n },\n },\n {\n uri: _94,\n descriptors: {\n unicodeRange:\n \"U+5cf4-5cfa,U+5cfc-5d01,U+5d04-5d05,U+5d08-5d0d,U+5d0f-5d13,U+5d15,U+5d17-5d1a,U+5d1c-5d1d,U+5d1f-5d23,U+5d25,U+5d28,U+5d2a-5d2c,U+5d2f-5d33,U+5d35-5d3c,U+5d3f-5d46,U+5d48-5d49,U+5d4d-5d57,U+5d59-5d5a,U+5d5c,U+5d5e-5d68,U+5d6a,U+5d6d-5d6e,U+5d70-5d73,U+5d75-5d81,U+5d83-5d98,U+5d9a-5d9c,U+5d9e-5db6,U+5db8-5dc4,U+5dc6-5dcc,U+5dce-5dcf\",\n },\n },\n {\n uri: _95,\n descriptors: {\n unicodeRange:\n \"U+5b52,U+5b56,U+5b5e,U+5b60-5b61,U+5b67-5b68,U+5b6b,U+5b6d-5b6f,U+5b72,U+5b74,U+5b76-5b79,U+5b7b-5b7c,U+5b7e-5b7f,U+5b82,U+5b86,U+5b8a,U+5b8d-5b8e,U+5b90-5b92,U+5b94,U+5b96,U+5b9f,U+5ba7-5ba9,U+5bac-5baf,U+5bb1-5bb2,U+5bb7,U+5bba-5bbc,U+5bc0-5bc1,U+5bc3,U+5bc8-5bcb,U+5bcd-5bcf,U+5bd1,U+5bd4-5bdc,U+5be0,U+5be2-5be3,U+5be6-5be7,U+5be9-5bed,U+5bef,U+5bf1-5bf7,U+5bfd-5bfe,U+5c00,U+5c02-5c03,U+5c05,U+5c07-5c08,U+5c0b-5c0e,U+5c10,U+5c12-5c13,U+5c17,U+5c19,U+5c1b,U+5c1e-5c21,U+5c23,U+5c26,U+5c28-5c2b,U+5c2d-5c30,U+5c32-5c33,U+5c35-5c37,U+5c43-5c44,U+5c46-5c47,U+5c4c-5c4d,U+5c52-5c54,U+5c56-5c58,U+5c5a-5c5d,U+5c5f,U+5c62,U+5c64,U+5c67-5c6d,U+5c70,U+5c72-5c78,U+5c7b-5c7e,U+5c80,U+5c83-5c87,U+5c89-5c8b,U+5c8e-5c8f,U+5c92-5c93,U+5c95,U+5c9d-5ca1,U+5ca4-5ca8,U+5caa,U+5cae-5cb0,U+5cb2,U+5cb4,U+5cb6,U+5cb9-5cbc,U+5cbe,U+5cc0,U+5cc2-5cc3,U+5cc5-5cca,U+5ccc-5cd1,U+5cd3-5cd8,U+5cda-5ce0,U+5ce2-5ce3,U+5ce7,U+5ce9,U+5ceb-5cec,U+5cee-5cef,U+5cf1-5cf3\",\n },\n },\n {\n uri: _96,\n descriptors: {\n unicodeRange:\n \"U+593b,U+593d-5940,U+5943,U+5945-5946,U+594a,U+594c-594d,U+5950,U+5952-5953,U+5959,U+595b-595f,U+5961,U+5963-5964,U+5966-5972,U+5975,U+5977,U+597a-597c,U+597e-5980,U+5985,U+5989,U+598b-598c,U+598e-5991,U+5994-5995,U+5998,U+599a-599d,U+599f-59a2,U+59a6-59a7,U+59ac-59ad,U+59b0-59b1,U+59b3-59b8,U+59ba,U+59bc-59bd,U+59bf-59c5,U+59c7-59c9,U+59cc-59cf,U+59d5-59d6,U+59d9,U+59db,U+59de-59e2,U+59e4,U+59e6-59e7,U+59e9-59eb,U+59ed-59f8,U+59fa,U+59fc-59fe,U+5a00,U+5a02,U+5a0a-5a0b,U+5a0d-5a10,U+5a12,U+5a14-5a17,U+5a19-5a1b,U+5a1d-5a1e,U+5a21-5a22,U+5a24,U+5a26-5a28,U+5a2a-5a30,U+5a33,U+5a35,U+5a37-5a3b,U+5a3d-5a3f,U+5a41-5a45,U+5a47-5a48,U+5a4b-5a54,U+5a56-5a59,U+5a5b-5a61,U+5a63-5a66,U+5a68-5a69,U+5a6b-5a73,U+5a78-5a79,U+5a7b-5a7e,U+5a80-5a90\",\n },\n },\n {\n uri: _97,\n descriptors: {\n unicodeRange:\n \"U+5a91,U+5a93-5a99,U+5a9c-5aa9,U+5aab-5ab1,U+5ab4,U+5ab6-5ab7,U+5ab9-5abd,U+5abf-5ac0,U+5ac3-5ac8,U+5aca-5acb,U+5acd-5ad1,U+5ad3,U+5ad5,U+5ad7,U+5ad9-5adb,U+5add-5adf,U+5ae2,U+5ae4-5ae5,U+5ae7-5ae8,U+5aea,U+5aec-5af0,U+5af2-5b08,U+5b0a-5b15,U+5b18-5b31,U+5b33,U+5b35-5b36,U+5b38-5b3f,U+5b41-5b4f\",\n },\n },\n {\n uri: _98,\n descriptors: {\n unicodeRange:\n \"U+5843,U+5845-584b,U+584e-5850,U+5852-5853,U+5855-5857,U+5859-585d,U+585f-5864,U+5866-586a,U+586d-587d,U+587f,U+5882,U+5884,U+5886-5888,U+588a-5891,U+5894-5898,U+589b-589d,U+58a0-58a7,U+58aa-58bb,U+58bd-58c0,U+58c2-58c4,U+58c6-58d0,U+58d2-58d4,U+58d6-58e3,U+58e5-58ea,U+58ed,U+58ef,U+58f1-58f2,U+58f4-58f5,U+58f7-58f8,U+58fa-5901,U+5903,U+5905-5906,U+5908-590c,U+590e,U+5910-5913,U+5917-5918,U+591b,U+591d-591e,U+5920-5923,U+5926,U+5928,U+592c,U+5930,U+5932-5933,U+5935-5936\",\n },\n },\n {\n uri: _99,\n descriptors: {\n unicodeRange:\n \"U+56d0-56d3,U+56d5-56d6,U+56d8-56d9,U+56dc,U+56e3,U+56e5-56ea,U+56ec,U+56ee-56ef,U+56f2-56f3,U+56f6-56f8,U+56fb-56fc,U+5700-5702,U+5705,U+5707,U+570b-571b,U+571d-571e,U+5720-5722,U+5724-5727,U+572b,U+5731-5732,U+5734-5738,U+573c-573d,U+573f,U+5741,U+5743-5746,U+5748-5749,U+574b,U+5752-5756,U+5758-5759,U+5762-5763,U+5765,U+5767,U+576c,U+576e,U+5770-5772,U+5774-5775,U+5778-577a,U+577d-5781,U+5787-578a,U+578d-5791,U+5794-579a,U+579c-579f,U+57a5,U+57a8,U+57aa,U+57ac,U+57af-57b1,U+57b3,U+57b5-57b7,U+57b9-57c1,U+57c4-57ca,U+57cc-57cd,U+57d0-57d1,U+57d3,U+57d6-57d7,U+57db-57dc,U+57de,U+57e1-57e3,U+57e5-57ec,U+57ee,U+57f0-57f3,U+57f5-57f7,U+57fb-57fc,U+57fe-57ff,U+5801,U+5803-5805,U+5808-580a,U+580c,U+580e-5810,U+5812-5814,U+5816-5818,U+581a-581d,U+581f,U+5822-5823,U+5825-5829,U+582b-582f,U+5831-5834,U+5836-5842\",\n },\n },\n {\n uri: _100,\n descriptors: {\n unicodeRange:\n \"U+55f9-55fc,U+55ff,U+5602-5607,U+560a-560b,U+560d,U+5610-5617,U+5619-561a,U+561c-561d,U+5620-5622,U+5625-5626,U+5628-562b,U+562e-5630,U+5633,U+5635,U+5637-5638,U+563a,U+563c-563e,U+5640-564b,U+564f-5653,U+5655-5656,U+565a-565b,U+565d-5661,U+5663,U+5665-5667,U+566d-5670,U+5672-5675,U+5677-567a,U+567d-5684,U+5687-568d,U+5690-5692,U+5694-56a2,U+56a4-56ae,U+56b0-56b6,U+56b8-56bb,U+56bd-56c9,U+56cb-56cf\",\n },\n },\n {\n uri: _101,\n descriptors: {\n unicodeRange:\n \"U+5286-5287,U+5289-528f,U+5291-5292,U+5294-529a,U+529c,U+52a4-52a7,U+52ae-52b0,U+52b4-52bd,U+52c0-52c2,U+52c4-52c6,U+52c8,U+52ca,U+52cc-52cf,U+52d1,U+52d3-52d5,U+52d7,U+52d9-52de,U+52e0-52e3,U+52e5-52ef,U+52f1-52f8,U+52fb-52fd,U+5301-5304,U+5307,U+5309-530c,U+530e,U+5311-5314,U+5318,U+531b-531c,U+531e-531f,U+5322,U+5324-5325,U+5327-5329,U+532b-532d,U+532f-5338,U+533c-533d,U+5340,U+5342,U+5344,U+5346,U+534b-534d,U+5350,U+5354,U+5358-5359,U+535b,U+535d,U+5365,U+5368,U+536a,U+536c-536d,U+5372,U+5376,U+5379,U+537b-537e,U+5380-5381,U+5383,U+5387-5388,U+538a,U+538e-5394,U+5396-5397,U+5399,U+539b-539c,U+539e,U+53a0-53a1,U+53a4,U+53a7,U+53aa-53ad,U+53af-53b5,U+53b7-53ba,U+53bc-53be,U+53c0,U+53c3-53c7,U+53ce-53d0,U+53d2-53d3,U+53d5,U+53da,U+53dc-53de,U+53e1-53e2,U+53e7,U+53f4,U+53fa,U+53fe-5400,U+5402,U+5405,U+5407,U+540b,U+5414,U+5418-541a,U+541c,U+5422,U+5424-5425,U+542a,U+5430,U+5433,U+5436-5437,U+543a\",\n },\n },\n {\n uri: _102,\n descriptors: {\n unicodeRange:\n \"U+5101-5105,U+5108-510a,U+510c-5111,U+5113-5120,U+5122-513e,U+5142,U+5147,U+514a,U+514c,U+514e-5150,U+5152-5153,U+5157-5159,U+515b,U+515d-5161,U+5163-5164,U+5166-5167,U+5169-516a,U+516f,U+5172,U+517a,U+517e-517f,U+5183-5184,U+5186-5187,U+518a-518b,U+518e-5191,U+5193-5194,U+5198,U+519a,U+519d-519f,U+51a1,U+51a3,U+51a6-51aa,U+51ad-51ae,U+51b4,U+51b8-51ba,U+51be-51bf,U+51c1-51c3,U+51c5,U+51c8,U+51ca,U+51cd-51ce,U+51d0,U+51d2-51da,U+51dc,U+51de-51df,U+51e2-51e3,U+51e5-51ea,U+51ec,U+51ee,U+51f1-51f2,U+51f4,U+51f7,U+51fe,U+5204-5205,U+5209,U+520b-520c,U+520f-5210,U+5213-5215,U+521c,U+521e-521f,U+5221-5223,U+5225-5227,U+522a,U+522c,U+522f,U+5231-5232,U+5234-5235,U+523c,U+523e,U+5244-5249,U+524b,U+524e-524f,U+5252-5253,U+5255,U+5257-525b,U+525d,U+525f-5260,U+5262-5264,U+5266,U+5268,U+526b-526e,U+5270-5271,U+5273-527c,U+527e,U+5280,U+5283-5285\",\n },\n },\n {\n uri: _103,\n descriptors: {\n unicodeRange:\n \"U+543d,U+543f,U+5441-5442,U+5444-5445,U+5447,U+5449,U+544c-544f,U+5451,U+545a,U+545d-5461,U+5463,U+5465,U+5467,U+5469-5470,U+5474,U+5479-547a,U+547e-547f,U+5481,U+5483,U+5485,U+5487-548a,U+548d,U+5491,U+5493,U+5497-5498,U+549c,U+549e-54a2,U+54a5,U+54ae,U+54b0,U+54b2,U+54b5-54b7,U+54b9-54ba,U+54bc,U+54be,U+54c3,U+54c5,U+54ca-54cb,U+54d6,U+54d8,U+54db,U+54e0-54e4,U+54eb-54ec,U+54ef-54f1,U+54f4-54f9,U+54fb,U+54fe,U+5500,U+5502-5505,U+5508,U+550a-550e,U+5512-5513,U+5515-551a,U+551c-551f,U+5521,U+5525-5526,U+5528-5529,U+552b,U+552d,U+5532,U+5534-5536,U+5538-553b,U+553d,U+5540,U+5542,U+5545,U+5547-5548,U+554b-554f,U+5551-5554,U+5557-555b,U+555d-5560,U+5562-5563,U+5568-5569,U+556b,U+556f-5574,U+5579-557a,U+557d,U+557f,U+5585-5586,U+558c-558e,U+5590,U+5592-5593,U+5595-5597,U+559a-559b,U+559e,U+55a0-55a6,U+55a8-55b0,U+55b2,U+55b4,U+55b6,U+55b8,U+55ba,U+55bc,U+55bf-55c3,U+55c6-55c8,U+55ca-55cb,U+55ce-55d0,U+55d5,U+55d7-55db,U+55de,U+55e0,U+55e2,U+55e7,U+55e9,U+55ed-55ee,U+55f0-55f1,U+55f4,U+55f6,U+55f8\",\n },\n },\n {\n uri: _104,\n descriptors: {\n unicodeRange:\n \"U+4fe0,U+4fe2,U+4fe4-4fe5,U+4fe7,U+4feb-4fec,U+4ff0,U+4ff2,U+4ff4-4ff7,U+4ff9,U+4ffb-4ffd,U+4fff-500b,U+500e,U+5010-5011,U+5013,U+5015-5017,U+501b,U+501d-501e,U+5020,U+5022-5024,U+5027,U+502b,U+502f-5039,U+503b,U+503d,U+503f-5042,U+5044-5046,U+5049-504b,U+504d,U+5050-5054,U+5056-5059,U+505b,U+505d-5064,U+5066-506b,U+506d-5075,U+5078-507a,U+507c-507d,U+5081-5084,U+5086-5087,U+5089-508c,U+508e-50a2,U+50a4,U+50a6,U+50aa-50ab,U+50ad-50b1,U+50b3-50b9,U+50bc-50ce,U+50d0-50d5,U+50d7-50d9,U+50db-50e5,U+50e8-50eb,U+50ef-50f2,U+50f4,U+50f6-50fa,U+50fc-5100\",\n },\n },\n { uri: _105, descriptors: { unicodeRange: \"U+49d5-4a77\" } },\n {\n uri: _106,\n descriptors: {\n unicodeRange:\n \"U+4dac-4dad,U+4daf-4db5,U+4e02,U+4e04-4e06,U+4e0f,U+4e12,U+4e17,U+4e1f-4e21,U+4e23,U+4e26,U+4e29,U+4e2e-4e2f,U+4e31,U+4e33,U+4e35,U+4e37,U+4e3c,U+4e40-4e42,U+4e44,U+4e46,U+4e4a,U+4e51,U+4e55,U+4e57,U+4e5a-4e5b,U+4e62-4e65,U+4e67-4e68,U+4e6a-4e6f,U+4e72,U+4e74-4e7d,U+4e7f-4e85,U+4e87,U+4e8a,U+4e90,U+4e96-4e97,U+4e99,U+4e9c-4e9e,U+4ea3,U+4eaa,U+4eaf-4eb1,U+4eb4,U+4eb6-4eb9,U+4ebc-4ebe,U+4ec8,U+4ecc,U+4ecf-4ed0,U+4ed2,U+4eda-4edc,U+4ee0,U+4ee2,U+4ee6-4ee7,U+4ee9,U+4eed-4eef,U+4ef1,U+4ef4,U+4ef8-4efa,U+4efc,U+4efe,U+4f00,U+4f02-4f08,U+4f0b-4f0c,U+4f12-4f16,U+4f1c-4f1d,U+4f21,U+4f23,U+4f28-4f29,U+4f2c-4f2e,U+4f31,U+4f33,U+4f35,U+4f37,U+4f39,U+4f3b,U+4f3e-4f42,U+4f44-4f45,U+4f47-4f4c,U+4f52,U+4f54,U+4f56,U+4f61-4f62,U+4f66,U+4f68,U+4f6a-4f6b,U+4f6d-4f6e,U+4f71-4f72,U+4f75,U+4f77-4f7a,U+4f7d,U+4f80-4f82,U+4f85-4f87,U+4f8a,U+4f8c,U+4f8e,U+4f90,U+4f92-4f93,U+4f95-4f96,U+4f98-4f9a,U+4f9c,U+4f9e-4f9f,U+4fa1-4fa2,U+4fa4,U+4fab,U+4fad,U+4fb0-4fb4,U+4fb6-4fbe,U+4fc0-4fc2,U+4fc6-4fc9,U+4fcb-4fcd,U+4fd2-4fd6,U+4fd9,U+4fdb\",\n },\n },\n { uri: _107, descriptors: { unicodeRange: \"U+4933-49d4\" } },\n { uri: _108, descriptors: { unicodeRange: \"U+487a-4932\" } },\n {\n uri: _109,\n descriptors: { unicodeRange: \"U+47d2-4879,U+2ce7c,U+2ce88,U+2ce93\" },\n },\n {\n uri: _110,\n descriptors: {\n unicodeRange:\n \"U+4756-47d1,U+2ca02,U+2ca0e,U+2ca7d,U+2caa9,U+2cb29,U+2cb2e,U+2cb31,U+2cb38-2cb39,U+2cb3f,U+2cb41,U+2cb4e,U+2cb5a,U+2cb64,U+2cb69,U+2cb6c,U+2cb6f,U+2cb76,U+2cb78,U+2cb7c,U+2cbb1,U+2cbbf-2cbc0,U+2cbce,U+2cc5f,U+2ccf5-2ccf6,U+2ccfd,U+2ccff,U+2cd02-2cd03,U+2cd0a,U+2cd8b,U+2cd8d,U+2cd8f-2cd90,U+2cd9f-2cda0,U+2cda8,U+2cdad-2cdae,U+2cdd5,U+2ce18,U+2ce1a,U+2ce23,U+2ce26,U+2ce2a\",\n },\n },\n {\n uri: _111,\n descriptors: {\n unicodeRange:\n \"U+46c3-4755,U+2c488,U+2c494,U+2c497,U+2c542,U+2c613,U+2c618,U+2c621,U+2c629,U+2c62b-2c62d,U+2c62f,U+2c642,U+2c64a-2c64b,U+2c72c,U+2c72f,U+2c79f,U+2c7c1,U+2c7fd,U+2c8d9,U+2c8de,U+2c8e1,U+2c8f3,U+2c907,U+2c90a,U+2c91d\",\n },\n },\n {\n uri: _112,\n descriptors: {\n unicodeRange:\n \"U+4629-46c2,U+2bdf7,U+2be29,U+2c029-2c02a,U+2c0a9,U+2c0ca,U+2c1d5,U+2c1d9,U+2c1f9,U+2c27c,U+2c288,U+2c2a4,U+2c317,U+2c35b,U+2c361,U+2c364\",\n },\n },\n {\n uri: _113,\n descriptors: {\n unicodeRange:\n \"U+458e-4628,U+2b7a9,U+2b7c5,U+2b7e6,U+2b7f9,U+2b806,U+2b80a,U+2b81c,U+2b8b8,U+2bac7,U+2bb5f,U+2bb62,U+2bb7c,U+2bb83,U+2bc1b,U+2bd77,U+2bd87\",\n },\n },\n {\n uri: _114,\n descriptors: {\n unicodeRange: \"U+4449-4511,U+2afa2,U+2b127-2b128,U+2b137-2b138,U+2b1ed\",\n },\n },\n {\n uri: _115,\n descriptors: {\n unicodeRange:\n \"U+439b-4448,U+2a437,U+2a5f1,U+2a602,U+2a61a,U+2a6b2,U+2a7dd,U+2a8fb,U+2a917,U+2aa30,U+2aa36,U+2aa58\",\n },\n },\n {\n uri: _116,\n descriptors: {\n unicodeRange:\n \"U+4275-430d,U+298c6,U+29a72,U+29d98,U+29ddb,U+29e15,U+29e3d,U+29e49\",\n },\n },\n {\n uri: _117,\n descriptors: {\n unicodeRange:\n \"U+4132-41de,U+28bef,U+28c47,U+28c4f,U+28c51,U+28c54,U+28d10,U+28d71,U+28dfb,U+28e1f,U+28e36,U+28e89,U+28e99,U+28eeb,U+28f32,U+28ff8,U+292a0\",\n },\n },\n {\n uri: _118,\n descriptors: {\n unicodeRange:\n \"U+41df-4274,U+292b1,U+29490,U+295cf,U+2967f,U+296f0,U+29719,U+29750\",\n },\n },\n {\n uri: _119,\n descriptors: {\n unicodeRange:\n \"U+408e-4131,U+285c8-285c9,U+28678,U+28695,U+286d7,U+286fa,U+287e0,U+28946,U+28949,U+2896b,U+28987-28988,U+289ba-289bb,U+28a1e,U+28a29,U+28a43,U+28a71,U+28a99,U+28acd,U+28add,U+28ae4,U+28b49,U+28bc1\",\n },\n },\n {\n uri: _120,\n descriptors: {\n unicodeRange:\n \"U+3e83-3f2f,U+27139,U+273da-273db,U+273fe,U+27410,U+27449,U+27614-27615,U+27631,U+27684,U+27693,U+2770e,U+27723,U+27752\",\n },\n },\n {\n uri: _121,\n descriptors: {\n unicodeRange:\n \"U+3f30-3fdb,U+27985,U+27a84,U+27bb3,U+27bbe,U+27bc7,U+27cb8,U+27da0,U+27e10\",\n },\n },\n {\n uri: _122,\n descriptors: {\n unicodeRange:\n \"U+3fdc-408d,U+27fb7,U+27ff9,U+2808a,U+280bb,U+2815d,U+28277,U+28282,U+282e2,U+282f3,U+283cd,U+28408,U+2840c,U+28455,U+28468,U+2856b\",\n },\n },\n {\n uri: _123,\n descriptors: {\n unicodeRange:\n \"U+3dd2-3e82,U+26a58,U+26a8c,U+26ab7,U+26aff,U+26b5c,U+26c21,U+26c29,U+26c73,U+26cdd,U+26e40,U+26e65,U+26f94,U+26ff6-26ff8,U+270f4,U+2710d\",\n },\n },\n {\n uri: _124,\n descriptors: {\n unicodeRange:\n \"U+3d34-3dd1,U+2648d,U+26676,U+2667e,U+266b0,U+2671d,U+2677c,U+267cc,U+268dd,U+268ea,U+26951,U+2696f,U+269dd,U+269fa,U+26a1e\",\n },\n },\n {\n uri: _125,\n descriptors: {\n unicodeRange:\n \"U+3c76-3d33,U+25d0a,U+25da1,U+25e2e,U+25e56,U+25e62,U+25e65,U+25ec2,U+25ed7-25ed8,U+25ee8,U+25f23,U+25f5c,U+25fd4,U+25fe0,U+25ffb,U+2600c,U+26017,U+26060,U+260ed,U+26221,U+26270,U+26286,U+2634c,U+26402\",\n },\n },\n {\n uri: _126,\n descriptors: {\n unicodeRange:\n \"U+3bda-3c75,U+25771,U+257a9,U+257b4,U+259c4,U+259d4,U+25ae3-25ae4,U+25af1,U+25bb2,U+25c14,U+25c4b,U+25c64\",\n },\n },\n {\n uri: _127,\n descriptors: {\n unicodeRange:\n \"U+3b25-3bd9,U+2504a,U+25055,U+25122,U+2512b,U+251a9,U+251cd,U+251e5,U+2521e,U+2524c,U+2542e,U+2548e,U+254d9,U+2550e,U+25532,U+25562,U+255a7-255a8\",\n },\n },\n {\n uri: _128,\n descriptors: {\n unicodeRange:\n \"U+3a6b-3b24,U+24896,U+249db,U+24a4d,U+24a7d,U+24ac9,U+24b56,U+24b6f,U+24c16,U+24d14,U+24dea,U+24e0e,U+24e37,U+24e6a,U+24e8b,U+24eaa\",\n },\n },\n {\n uri: _129,\n descriptors: {\n unicodeRange:\n \"U+39a9-3a6a,U+24096,U+24103,U+241ac,U+241c6,U+241fe,U+243bc,U+243f8,U+244d3,U+24629,U+246a5,U+247f1\",\n },\n },\n {\n uri: _130,\n descriptors: {\n unicodeRange:\n \"U+38e3-39a8,U+23a98,U+23c7f,U+23c97-23c98,U+23cfe,U+23d00,U+23d0e,U+23d40,U+23dd3,U+23df9-23dfa,U+23e23,U+23f7e\",\n },\n },\n {\n uri: _131,\n descriptors: {\n unicodeRange:\n \"U+3760-382a,U+22ab8,U+22b43,U+22b46,U+22b4f-22b50,U+22ba6,U+22bca,U+22c1d,U+22c24,U+22c55,U+22d4c,U+22de1\",\n },\n },\n {\n uri: _132,\n descriptors: {\n unicodeRange:\n \"U+382b-38e2,U+231b6,U+231c3-231c4,U+231f5,U+23350,U+23372,U+233d0,U+233d2-233d3,U+233d5,U+233da,U+233df,U+233e4,U+2344a-2344b,U+23451,U+23465,U+234e4,U+2355a,U+23594,U+235c4,U+235cb,U+23638-2363a,U+23647,U+2370c,U+2371c,U+2373f,U+23763-23764,U+237e7,U+237ff,U+23824,U+2383d\",\n },\n },\n {\n uri: _133,\n descriptors: {\n unicodeRange:\n \"U+3698-375f,U+22218,U+2231e,U+223ad,U+224dc,U+226f3,U+2285b,U+228ab,U+2298f\",\n },\n },\n {\n uri: _134,\n descriptors: {\n unicodeRange:\n \"U+35e6-3697,U+21c56,U+21cde,U+21d2d,U+21d45,U+21d62,U+21d78,U+21d92,U+21d9c,U+21da1,U+21db7,U+21de0,U+21e33-21e34,U+21f1e,U+21f76,U+21ffa,U+2217b\",\n },\n },\n {\n uri: _135,\n descriptors: {\n unicodeRange:\n \"U+3444-350e,U+20ad3,U+20b1d,U+20b9f,U+20c41,U+20cbf,U+20cd0,U+20d45,U+20de1,U+20e64,U+20e6d,U+20e95,U+20e9d,U+20ea2,U+20f5f,U+210c1,U+21201,U+2123d,U+21255,U+21274,U+2127b\",\n },\n },\n {\n uri: _136,\n descriptors: {\n unicodeRange:\n \"U+350f-35e5,U+212d7,U+212e4,U+212fd,U+2131b,U+21336,U+21344,U+2139a,U+213c4,U+21413,U+2146d-2146e,U+215d7,U+21647,U+216b4,U+21706,U+21742,U+218bd,U+219c3\",\n },\n },\n {\n uri: _137,\n descriptors: {\n unicodeRange:\n \"U+336d-3443,U+2032b,U+20371,U+20381,U+203f9,U+2044a,U+20509,U+20547,U+205d6,U+20628,U+20676,U+2074f,U+20779,U+20807,U+2083a,U+20895,U+208b9,U+2097c,U+2099d\",\n },\n },\n {\n uri: _138,\n descriptors: {\n unicodeRange:\n \"U+328b-336c,U+2000b,U+20089,U+200a2,U+200a4,U+20164,U+201a2,U+20213\",\n },\n },\n {\n uri: _139,\n descriptors: {\n unicodeRange:\n \"U+3192-31ba,U+31c0-31e3,U+31f0-321e,U+3220-328a,U+1f250-1f251\",\n },\n },\n {\n uri: _140,\n descriptors: {\n unicodeRange:\n \"U+2f74-2fd5,U+3000,U+3003-3007,U+3012-3013,U+3018-301c,U+3020-3029,U+302f-303f,U+3041-3096,U+3099-30a1\",\n },\n },\n {\n uri: _141,\n descriptors: {\n unicodeRange: \"U+30a2-30ff,U+3105-312f,U+3131-318e,U+3190-3191\",\n },\n },\n {\n uri: _142,\n descriptors: {\n unicodeRange:\n \"U+4e36,U+4ea0,U+4f74,U+4f91,U+4f94,U+4fc5,U+507e,U+50ed,U+5182,U+51f5,U+525e,U+5282,U+52f9,U+5326,U+537a,U+53a3,U+5423,U+5459,U+54b4,U+54d9,U+55c9,U+57f4,U+580b,U+5902,U+5925,U+5a08,U+5ab5,U+5b84,U+5be4,U+5c22,U+5cb5,U+5cbd,U+5d3e,U+5e31,U+5e5e,U+5e80,U+5ee8,U+5f82,U+5fc9,U+5fed,U+600a,U+605d,U+609b,U+609d,U+60dd,U+6243,U+6322,U+63ce,U+640c,U+643f,U+6445,U+64d7,U+6534,U+6549,U+656b,U+6603,U+674c,U+680a,U+6864,U+69d4,U+6a65,U+6c2a,U+6c46,U+6c5c,U+6d0e,U+6d48,U+6e2b,U+6eb2,U+6eb7,U+6f89,U+706c,U+70b1,U+7113,U+71d4,U+727f,U+72f3,U+7303,U+7321,U+736c,U+736f,U+74a9,U+74de,U+750d,U+7513,U+7592,U+75c4,U+7605,U+760a,U+761b,U+7625,U+762d,U+7643,U+7707,U+7747,U+77b5,U+7839,U+784e,U+78a5,U+7924,U+793b,U+798a,U+7a03,U+7a06,U+7a78,U+7a80,U+7aad,U+7ba8,U+7be5,U+7cc8,U+7ec1,U+7f0b,U+7f0f,U+7f12,U+7f68,U+7f9d,U+8025,U+809c,U+80ad,U+80b7,U+80e8,U+811e,U+8204,U+8223,U+822d,U+823b,U+824b,U+825a,U+827d,U+827f,U+828f,U+82c8,U+8307,U+831b,U+8347,U+837d,U+839b,U+83a9,U+83f9,U+84b9,U+8579,U+864d,U+867f,U+86b0,U+86d1,U+86d8,U+86f2,U+8764,U+8770,U+8788,U+8797,U+87ac-87ad,U+87b5,U+881b,U+8844,U+88bc,U+88fc,U+8930,U+89cf,U+89d6,U+8ba0,U+8bd4,U+8c02,U+8c2b,U+8c85,U+8e23,U+8f81-8f82,U+8fd5,U+90b6,U+90db,U+914e,U+9164,U+91ad,U+943e,U+94b7-94b8,U+94eb,U+950d,U+9514,U+9516,U+9518,U+9529,U+9538,U+953f,U+954e,U+955f,U+95fc,U+9667,U+96b3,U+9792,U+97b2,U+98a1,U+9969,U+9987,U+9998,U+9a80,U+9a92,U+9a96,U+9adf,U+9cb4,U+9cbd,U+9cd0,U+9cd4,U+9e31,U+9e3a,U+9e71,U+9ee5,U+9eea,U+9ef9,U+9fa0\",\n },\n },\n {\n uri: _143,\n descriptors: {\n unicodeRange:\n \"U+4e0c,U+4e28,U+4e3f,U+4ec2,U+502e,U+50ba,U+5155,U+5181,U+522d,U+5281,U+5290,U+5369,U+53b6,U+54d5,U+54dc,U+54ff,U+552a,U+553c,U+5588,U+55b5,U+5686,U+570a,U+5776,U+5786,U+57a4,U+5820,U+5865,U+58bc,U+5b32,U+5b65,U+5c1c,U+5c66,U+5c6e,U+5c8d,U+5ddb,U+5f2a,U+5f50,U+5f61,U+6067,U+614a,U+615d,U+619d,U+61d4,U+620b,U+6224-6225,U+6343,U+63ad,U+63f2,U+640b,U+6420,U+6434,U+6496,U+64d0,U+6509,U+652e,U+67a8,U+6833,U+6844,U+684a,U+6920,U+6957,U+6971,U+6a8e,U+6a91,U+6aa0,U+6b43,U+6bea,U+6bf5,U+6c15,U+6cd0,U+6ee0,U+6f24,U+6f2d,U+70c0,U+721d,U+728b,U+72c3,U+72e8,U+730a,U+7338-7339,U+734d,U+746d,U+752f,U+754e,U+770d,U+7735,U+778d,U+77a2,U+77e7,U+7857,U+786d,U+78c9,U+78f2,U+791e,U+7953,U+7b58,U+7b9d,U+7bda,U+7cd7,U+7f32-7f33,U+8022,U+8028-8029,U+8035,U+804d,U+8080,U+80c2,U+80e9,U+80ec,U+80f2,U+810e,U+8221,U+8274,U+82b0,U+82e0,U+83b0,U+8487-8488,U+848e,U+84cd,U+84d0,U+8539,U+857a,U+85a8,U+85b7,U+867c,U+871e,U+8723,U+877e,U+878b,U+8793,U+8803,U+88d2,U+8966,U+89cc,U+89eb,U+8b26,U+8c8a,U+8c98,U+8d33,U+8d47,U+8d55,U+8dbc,U+8e40,U+8e94,U+8f77,U+8f79,U+9058,U+91a2,U+91b5,U+928e,U+9494,U+94b6,U+94de,U+94f4,U+94f9,U+950a,U+950e,U+951e,U+952b,U+953c,U+953e,U+9544,U+9561,U+9564,U+9569,U+95f6,U+9603,U+960d,U+963d,U+9674,U+9794,U+97ab,U+98a5,U+9a9f,U+9ab1,U+9ad1,U+9b0f,U+9b2f,U+9c92,U+9c95,U+9cba,U+9cbc,U+9cc6,U+9ccb,U+9cd8,U+9e32,U+9e38,U+9e5b,U+9e7e,U+9eb4,U+9efb-9efc,U+9f3d\",\n },\n },\n {\n uri: _144,\n descriptors: {\n unicodeRange: \"U+2e3b,U+2e80-2e99,U+2e9b-2ef3,U+2f00-2f73,U+ffffd\",\n },\n },\n {\n uri: _145,\n descriptors: {\n unicodeRange:\n \"U+4e69,U+4f1b,U+4f67,U+4f7e,U+4fdc,U+50e6,U+5196,U+5202,U+5233,U+523f,U+52a2,U+536e,U+5476,U+54ad,U+54cf,U+5537,U+561e,U+56dd,U+56df,U+5709,U+572c,U+57cf,U+57f8,U+580d,U+5881,U+589a,U+5941,U+59b2,U+5c25,U+5d24,U+5d74,U+5e42,U+5e8b,U+5eb3,U+5ed2,U+5fad,U+6003,U+603c,U+6083,U+6100,U+6126,U+6206,U+62ca,U+638e,U+63b4,U+6426,U+646d,U+6535,U+65c4,U+66db,U+6715,U+6769,U+6798,U+67c3,U+6861,U+698d,U+69ca,U+69ed,U+69f2,U+69ff,U+6a18,U+6b39,U+6bb3,U+6c0d,U+6cb2,U+6cd6,U+6cf7,U+6cfa,U+6d33,U+6e16,U+6e53-6e54,U+6ebb,U+6fb6,U+709d,U+72ad,U+72f7,U+72fb,U+7313,U+739f,U+74ba,U+754b,U+755b,U+758b,U+75ac,U+75d6,U+7617,U+7635,U+7640,U+76a4,U+76b2,U+775a,U+77bd,U+781f,U+79b3,U+7b2b,U+7b31,U+7b3e,U+7b6e,U+7b9c,U+7c0b,U+7c9e,U+7cc1,U+7ce8,U+7ea5,U+7f21,U+7f27,U+7f74,U+7fb0,U+8031,U+8071,U+80ea,U+8114,U+8160,U+81a6,U+81c1,U+829f,U+82a4,U+82fb,U+831a,U+8333,U+836c,U+83b6,U+83f8,U+8411,U+841c,U+8489,U+848c,U+85a4,U+8627,U+8629,U+866e,U+86b5,U+872e,U+8731,U+877b,U+877d,U+87ea,U+8813,U+8816,U+8864,U+88ce,U+88e5,U+897b,U+89cb,U+89f3,U+8bfc,U+8c35,U+8d46,U+8d4d,U+8dba,U+8e3a,U+8f75,U+8f7e,U+8fd3,U+9161,U+9179,U+917e,U+91a3,U+94ac,U+94d7,U+94e5,U+952a,U+952c,U+9545,U+9565,U+9568,U+956a,U+961d,U+96e0,U+972a,U+9730,U+989f,U+98e7,U+990d,U+9967,U+9993,U+9aa3,U+9ac0,U+9ae1,U+9aeb,U+9af9,U+9c86,U+9c8b,U+9ca0-9ca1,U+9ca3,U+9ce2,U+9e48,U+9e6a,U+9e87,U+9ee2,U+9ee9,U+9f17,U+9f19,U+9f2c,U+9f80\",\n },\n },\n {\n uri: _146,\n descriptors: {\n unicodeRange:\n \"U+4ef3,U+50d6,U+50ec,U+51ab,U+51b1,U+52d6,U+54a9,U+54da,U+55be,U+55cd,U+564d,U+572f,U+574c,U+576b,U+57d8,U+57fd,U+5844,U+59d2,U+5ae0,U+5b16,U+5b37,U+5b5b,U+5b80,U+5d1e,U+5d6b,U+5efe,U+5f11,U+5f56,U+5f58,U+5f73,U+5f8c,U+5fc4,U+5fe4,U+602b,U+6106,U+610d,U+63de,U+63f8,U+641b,U+64e4,U+6634,U+676a,U+67b5,U+681d,U+6883,U+69b1,U+69e0,U+6b37,U+6b9b,U+6d7c,U+6ed7,U+6f36,U+6f72,U+6f8c,U+7035,U+7039,U+7173,U+7178,U+7228,U+728f,U+72b4,U+72ef,U+72f4,U+7331,U+7481,U+74e0,U+7540,U+75c3,U+75e6,U+763c,U+764d,U+76cd,U+7704,U+7743,U+7780,U+7847,U+786a,U+78b9,U+7962,U+7a02,U+7aac,U+7ab3,U+7b0a,U+7b4c,U+7b7b,U+7bfc,U+7c0f,U+7c16,U+7c40,U+7ca2,U+7cc7,U+7cf8,U+7d77,U+7e3b,U+7ea1,U+7ea9,U+7ef2,U+7f02,U+7f07,U+7f0c,U+7f23,U+7f2f,U+7fbc,U+8016,U+8020,U+812c,U+8136,U+8182,U+822f,U+8233,U+825f,U+8268,U+8284,U+8288,U+8291,U+8308,U+8311,U+835b,U+836d,U+83dd,U+8406,U+840f,U+845c,U+84b4,U+84e3,U+850c,U+855e,U+863c,U+86ba,U+86c4,U+86de,U+86f1,U+873e,U+87bd,U+87db,U+880a,U+883c,U+887f,U+88f0,U+890a,U+892b,U+895e,U+89ef,U+8a48,U+8bdc,U+8c18,U+8c33,U+8c94,U+8db1,U+8dcf,U+8dd6,U+8de3,U+8e6f,U+8e90,U+8f7a,U+8fb6,U+902d,U+90be,U+91af,U+936a,U+948b,U+94d8,U+9513,U+953a,U+956c,U+963c,U+9654,U+966c,U+9688,U+97b4,U+996b,U+9a75,U+9a7a,U+9aba,U+9aed,U+9b08,U+9b43,U+9c8e,U+9c94,U+9c9a,U+9e2b,U+9e36,U+9e4b,U+9e4e,U+9e55,U+9e63,U+9e68-9e69,U+9ebd,U+9ec9,U+9f0d,U+9f37,U+9f51\",\n },\n },\n {\n uri: _147,\n descriptors: {\n unicodeRange:\n \"U+50a7,U+5240,U+5261,U+52ac,U+531a,U+5363,U+5432,U+5452,U+5456,U+5472,U+5478,U+553f,U+5575,U+5581,U+55cc,U+55fe,U+5601,U+572e,U+57d2,U+57ef,U+581e,U+5924,U+5981,U+5997,U+59a3,U+5aaa,U+5ab8,U+5b34,U+5d5d,U+5def,U+5e11,U+5e91,U+5ed1,U+5ef4,U+5f40,U+600d,U+6019,U+601b,U+605a,U+6092,U+60ab,U+6217,U+623d,U+6369,U+65d2,U+6661,U+670a,U+6753,U+67a7,U+6855,U+68f9,U+6939,U+696e,U+6980,U+6a7c,U+6aab,U+6b82,U+6bf3,U+6bf9,U+6c05,U+6c19-6c1a,U+6ca9,U+6cf6,U+6d1a,U+6dab,U+6f74,U+7085,U+7198,U+71b5,U+7256,U+725d,U+727e,U+72fa,U+7322,U+738e,U+73e5,U+750f,U+755a,U+7594,U+75b3,U+760c,U+7615,U+7630,U+763f,U+77ec,U+7817,U+78a1,U+78d9,U+7905,U+7b2a,U+7b2e,U+7b62,U+7b85,U+7bcc,U+7bea,U+7c26,U+7c74,U+7c9c-7c9d,U+7e47,U+7e9b,U+7e9f,U+7ee0,U+7ee8,U+7ef1,U+7f01,U+7f11,U+7f17,U+7f36,U+7f7e,U+7fee,U+802a,U+80cd,U+8112,U+8169,U+8234,U+8279,U+8298,U+82ca,U+82d8,U+82e1,U+83c0,U+83d4,U+83df,U+8401,U+8451,U+845a,U+8476,U+8478,U+84ba,U+84bd,U+84e0,U+851f,U+8548,U+8556,U+8585,U+868d,U+86e9,U+86f4,U+86f8,U+8765,U+8785,U+87ab,U+87ee,U+8832,U+8872,U+88b7,U+88e2-88e3,U+89da,U+8bce,U+8bd3,U+8bd6,U+8bf9,U+8c16,U+8c73,U+8d5c,U+8dde,U+8f6d,U+8f94,U+8fe8,U+9011,U+915e,U+9185,U+918c,U+94ab,U+94d1,U+94f3,U+9515,U+951d,U+9558,U+9567,U+96ce,U+96e9,U+9785,U+9878,U+987c,U+9883,U+98d1,U+9954,U+9963,U+9a93,U+9ac1,U+9acc,U+9b1f,U+9b49,U+9b4d,U+9b51,U+9ca7,U+9cae,U+9cce,U+9cd3,U+9e37,U+9e39,U+9e41,U+9e46,U+9f22,U+9f2f,U+9f39,U+9f85\",\n },\n },\n {\n uri: _148,\n descriptors: {\n unicodeRange:\n \"U+4e5c,U+4edf,U+4f25,U+4f32,U+4f5e,U+4f76,U+4faa,U+4fe6,U+5028,U+5048,U+5250,U+535f,U+538d,U+53c1,U+5412,U+5443,U+54d4,U+54dd,U+5541,U+5550,U+5577,U+55dd,U+55f3,U+560f,U+562c,U+5657-5658,U+5664,U+56af,U+575c,U+577c,U+57b2,U+57da,U+5800,U+5a62,U+5aeb,U+5c3b,U+5ca3,U+5d26,U+5d9d,U+5f01,U+5fb5,U+5fdd,U+5ff8,U+6029,U+6041,U+6079,U+60b1,U+6222,U+629f,U+6332,U+63bc,U+63e0,U+6485,U+65ab,U+65c3,U+65c6,U+668c,U+669d,U+66be,U+67fd,U+6800,U+68fc,U+690b,U+6924,U+6978,U+69a7,U+6a3e,U+6a50,U+6a5b,U+6a97,U+6b24,U+6b8d,U+6baa,U+6c10,U+6c54,U+6ceb,U+6d04,U+6d4d,U+6eb1,U+6ebd,U+7110,U+71b3,U+71f9,U+7230,U+728d,U+7292,U+72b8,U+72d2,U+7360,U+73a2,U+7511,U+75a0,U+75c8,U+779f,U+7826,U+7877,U+7a39,U+7aa8,U+7ae6,U+7b04,U+7b0f,U+7baa,U+7bac,U+7c1f,U+7ccd,U+7ecb,U+7ed4,U+7ed7,U+7efb,U+7f0d,U+7f5f,U+7faf,U+7fd5,U+7fe5,U+8027,U+80bc,U+80dd,U+80fc,U+8132,U+815a,U+8167,U+816d,U+81ca,U+8228,U+82a1,U+82a9,U+82ab,U+82cc,U+8351,U+8368,U+83b8,U+83d8,U+83ea,U+83f0,U+8497,U+84c1,U+858f,U+85ff,U+867b,U+86a8-86a9,U+870a,U+8722,U+876e,U+877c,U+87e5,U+8888,U+88df,U+8919,U+8bcc,U+8bdf,U+8be8,U+8bee,U+8c20,U+8c2f,U+8d36,U+8df8,U+8e05,U+8e2f,U+8f9a,U+9021,U+908b,U+90b4,U+90ba,U+90d0,U+90eb,U+90fe,U+91aa,U+933e,U+9486-9487,U+948d,U+9490,U+94ad,U+94bd,U+94d6,U+94d9,U+9507,U+9546,U+955e,U+956b,U+95e9,U+9604,U+960b,U+9612,U+9615,U+9617,U+96b9,U+989a-989b,U+989e,U+9a78,U+9a7d,U+9aa0,U+9aa2,U+9ac2,U+9b23,U+9b3b,U+9c82,U+9cca,U+9cd9,U+9e28,U+9e5a,U+9e5e,U+9e6c,U+9efe,U+9f0b\",\n },\n },\n {\n uri: _149,\n descriptors: {\n unicodeRange:\n \"U+4e47,U+4e8d,U+4f65,U+4f89,U+50ee,U+520e,U+5416,U+5454,U+54bb,U+54c2,U+54d3,U+54de,U+5591,U+55e5,U+560c,U+566b,U+5769,U+578c,U+5793,U+57e4,U+5889,U+593c,U+59ab,U+5ad4,U+5ad8,U+5af1,U+5b53,U+5ba5,U+5c59,U+5c63,U+5d5b,U+5e0f,U+5e14,U+5edb,U+5fbc,U+6004,U+60ad,U+610e,U+61b7,U+624c,U+634c,U+647a,U+64ba,U+65f0,U+6600,U+66f7,U+67e2,U+67f0,U+680c,U+686b,U+6874,U+691f,U+6989,U+6a17,U+6b81,U+6b84,U+6c06-6c07,U+6c3d,U+6d07,U+6d27,U+6d2b,U+6d91,U+6e6b,U+6e8f,U+6fde,U+70bb,U+723b,U+726e,U+72b0,U+72ce,U+72f2,U+7301,U+731e,U+737e,U+7477,U+748e,U+74ff,U+7633,U+7654,U+771a,U+7726,U+7765,U+7768,U+781c,U+7829,U+78d4,U+7913,U+7957,U+79d5,U+79eb,U+7a70,U+7a86,U+7b25,U+7b38,U+7b47,U+7b72,U+7ba6-7ba7,U+7dae,U+7ee1,U+7efe,U+7f26,U+7f31,U+7f35,U+801c,U+8043,U+809f,U+80ab,U+80d7,U+8118,U+8188,U+81cc,U+823e,U+8244,U+824f,U+82b4,U+82c1,U+82e4,U+82f4,U+8306,U+833a,U+835c,U+839c,U+83b3,U+83bc,U+846d,U+867a,U+868b,U+8734,U+87ca,U+886e,U+887e,U+88a2,U+88c9,U+8921,U+8bb5,U+8bf3,U+8c04,U+8c17,U+8c1d,U+8c25,U+8c36,U+8c55,U+8c78,U+8d3d,U+8d40,U+8d59,U+8d67,U+8d91,U+8dbf,U+8deb-8dec,U+8dfd,U+8e14,U+8e41,U+8f8e,U+900b,U+9044,U+9062,U+90cf,U+9123,U+9146,U+9162,U+9172,U+918d,U+9190,U+92c8,U+93ca,U+948c,U+94aa,U+94b2,U+94c8,U+94ca,U+94d5,U+94df,U+94e9-94ea,U+94f7,U+94fc-94fd,U+951b,U+954f,U+9554,U+9559,U+9566,U+9571-9572,U+95f1,U+9608,U+960f,U+97af,U+988f,U+98d5,U+992e,U+9955,U+9ab0,U+9b32,U+9c90,U+9c9e,U+9ca5,U+9ca9,U+9cad,U+9cb1,U+9cc3,U+9e47,U+9ee7,U+9f87\",\n },\n },\n {\n uri: _150,\n descriptors: {\n unicodeRange:\n \"U+4e93,U+4ec4,U+4ef5,U+4f27,U+4f7b,U+4fe3,U+5080,U+5121,U+51eb,U+5208,U+52f0,U+53f5,U+5453,U+5466,U+54a6,U+54bf,U+54d0,U+5533,U+5549,U+5556,U+556d,U+558f,U+55f2,U+55f5,U+5627,U+567b,U+56d4,U+571c,U+5739,U+57b4,U+5807,U+58c5,U+59a4,U+59af,U+59d8,U+5a09,U+5a0c,U+5a4a,U+5ad2,U+5b6c,U+5ca2,U+5cac,U+5d03,U+5d6c,U+5db7,U+5ebe,U+5f2d,U+5fea,U+6042,U+6120,U+6175,U+6221,U+623e,U+6339,U+638a,U+643d,U+64b8,U+64e2,U+66e9,U+67b3,U+67c1,U+67d2,U+6832,U+6877,U+68f0,U+6934,U+6966,U+6987,U+6998,U+69c1,U+69ce,U+6a3d,U+6a84,U+6aa9,U+6b87,U+6bd6,U+6c16,U+6c18,U+6cd4,U+6cee,U+6de0,U+6e0c,U+6ecf,U+6f4b,U+70b7,U+7168,U+72d9,U+7352,U+73b3,U+73d0,U+7441,U+74d2,U+75a5,U+75e7-75e8,U+7610,U+7619,U+765e,U+772d,U+7812,U+782c,U+784c,U+7850,U+7856,U+789b,U+78f4,U+7a51,U+7b15,U+7b1e,U+7b24,U+7b5a,U+7bb8,U+7bc1,U+7bd9,U+7ed0,U+7ee6,U+7efa,U+7f1b,U+7f1f,U+7f22,U+7f45,U+7f71,U+7fa7,U+7fbf,U+7ff3,U+8052,U+80b1,U+80db,U+80f4,U+81bb,U+81ec,U+8202,U+8210,U+8249,U+828a,U+828e,U+82e3,U+8315,U+8369,U+8378,U+83a8,U+83aa,U+83b4,U+83e1,U+84fc,U+8538,U+853b,U+859c,U+85ae,U+86b4,U+86c9,U+86cf,U+8725,U+879f,U+87b3,U+887d,U+88fe,U+8a8a,U+8ba7,U+8c07,U+8c14,U+8c30,U+8c47,U+8db5,U+8dd7,U+8e1f,U+8e69,U+8e70,U+8e85,U+8f78,U+8f87,U+8f8b,U+8f8f,U+90c4,U+9143,U+917d,U+948f,U+94cd,U+94d2,U+94ef,U+954a,U+9609-960a,U+96d2,U+9708,U+9765,U+97ea,U+9880,U+98a7,U+996c,U+9980,U+9991,U+9a88,U+9ab6,U+9afb,U+9b47,U+9c87,U+9c9b,U+9cb5,U+9cc7,U+9e2c,U+9e42,U+9e58,U+9ecd,U+9ecf,U+9f8a,U+9f8c\",\n },\n },\n {\n uri: _151,\n descriptors: {\n unicodeRange:\n \"U+4ebb,U+4edd,U+4fa9,U+502c,U+50a5,U+51c7,U+51fc,U+523d,U+5241,U+530f,U+5464,U+549d,U+54a3,U+5514,U+5527,U+555c,U+556e,U+5576,U+55b1,U+55b9,U+55eb,U+5624,U+564c,U+5671,U+5685,U+568f,U+56d7,U+56e1,U+57a1,U+57d9,U+5942,U+5a67,U+5c50,U+5c7a,U+5c98,U+5d06,U+5d27,U+5d6f,U+5df3,U+5dfd,U+5e19,U+5ea0,U+5eb9,U+5eea,U+5ffe,U+600f,U+606b,U+6215,U+622c,U+6266,U+62bb,U+62bf,U+6308,U+6387,U+63b8,U+63c4,U+63c6,U+63f6,U+6441,U+6555,U+659b,U+6677,U+66a7,U+6775,U+678b,U+679e,U+6840,U+6849,U+6860,U+68c2,U+6910,U+6a28,U+6a2f,U+6a79,U+6b92-6b93,U+6bc2,U+6bfd,U+6c29,U+6c32,U+6c86,U+6cc5,U+6d0c,U+6d60,U+6da0,U+6ddd,U+6e86,U+6ed3,U+6edf,U+6fb9,U+6fd1,U+6fef,U+7023,U+7080,U+70ca,U+712f,U+7145,U+7284,U+732c,U+73c8,U+73d9,U+740a,U+7457,U+7596,U+759d,U+75a3,U+75d8,U+75e3-75e4,U+75ff,U+7622,U+7688,U+76b4,U+76e5,U+7818,U+7887,U+789a,U+78b2,U+7b08,U+7b33,U+7c2a,U+7ccc,U+7ea8,U+7ec0,U+7fe6,U+8012,U+8084,U+8093,U+80e4,U+80ef,U+8297,U+82a8,U+82be,U+8331,U+8366,U+83c5,U+83fd,U+8473,U+84a1,U+84ca,U+84d1,U+857b,U+85c1,U+85d3,U+8605,U+8662,U+86aa,U+86b1,U+86d4,U+86ed,U+86f3,U+8709,U+8748,U+874c,U+8763,U+89c7,U+89de,U+89e5,U+8a3e,U+8ba6,U+8c00,U+8c21,U+8c49,U+8c7a,U+8d30,U+8df9,U+8e51,U+8e59,U+8f6b,U+8f73,U+8ff3,U+9016,U+9026,U+902f,U+9099,U+909b,U+90c7,U+914a,U+91ae,U+91ba,U+9495,U+94a3,U+94af,U+94ba,U+94bf,U+94cc,U+94e1,U+94f0,U+9531,U+955d,U+95f3,U+9697,U+96bc,U+975b,U+977c,U+98a2,U+998a,U+9994-9995,U+9a9b,U+9ab7,U+9ac5,U+9c91,U+9ccf,U+9cd5,U+9e29,U+9edc,U+9edf,U+9f83,U+9f88-9f89\",\n },\n },\n {\n uri: _152,\n descriptors: {\n unicodeRange:\n \"U+4ee8,U+4f22,U+4f43,U+4f57,U+4f5d,U+4f6f,U+4ff8,U+502d,U+507b,U+5345,U+53df,U+53fb,U+544b,U+5482,U+54a7,U+54cc,U+550f,U+5544,U+5555,U+5594,U+55e8,U+55ec,U+55ef,U+564e,U+56f9,U+5704,U+576d,U+5785,U+57ad,U+5914,U+5958,U+599e,U+59aa,U+59be,U+5a06,U+5abe,U+5ae1,U+5b40,U+5bee,U+5cbf,U+5cc4,U+5ccb,U+5d47,U+603f,U+6078,U+607d,U+607f,U+608c,U+609a,U+60fa,U+61ff,U+621b,U+622e,U+626a,U+6371,U+63ae,U+63cd,U+63d6,U+6410,U+6414,U+6421,U+6448,U+64d8,U+6710,U+6748,U+6772,U+680e,U+6954,U+69ab,U+6c68,U+6c8f,U+6ca4,U+6d2e,U+6e4e,U+6e98,U+6fe0,U+7094,U+70e9,U+7116,U+7119,U+723f,U+73c9,U+74e4,U+753e,U+7548,U+75bd,U+75cd,U+7618,U+7634,U+76c5,U+76f1,U+7708,U+7719,U+777e,U+7791,U+77b3,U+7823,U+7827,U+7830,U+7889,U+7893,U+7949,U+795c,U+79e3,U+7a14,U+7a88,U+7a95,U+7aa0,U+7afd,U+7b90,U+7bd1,U+7bfe,U+7da6,U+7ec2,U+7eef,U+7f03-7f04,U+7f08,U+7f58,U+7f61,U+7f9f,U+8174,U+8200,U+828d,U+82c4,U+82d5,U+82dc,U+82f7,U+832d,U+835a,U+840b,U+8438,U+852b,U+869d,U+86ac,U+86d0,U+86f0,U+8782,U+87a8,U+87d1-87d2,U+87e0,U+8839,U+8913,U+891b,U+8934,U+8941,U+89ca,U+89ce,U+8a07,U+8ba3,U+8bc5,U+8bcb,U+8bdb,U+8c11,U+8c15,U+8c29,U+8c32,U+8dc4,U+8dce,U+8ddb,U+8dfa,U+8e09,U+8e1d,U+8e39,U+8e42,U+8e49,U+8e4b,U+8e8f,U+8f71-8f72,U+9004,U+9036,U+9097,U+90dc,U+90e2,U+90e6,U+90ef,U+9104,U+919a,U+91b4,U+938f,U+9497,U+950f,U+9557,U+9562-9563,U+9573,U+9606,U+9649,U+972d,U+973e,U+97a3,U+97eb,U+988c,U+9894,U+98a6,U+9974,U+9977,U+997d,U+9a90,U+9a9d,U+9aef,U+9ca2,U+9ccd,U+9cdf,U+9e20,U+9e4c,U+9e6b,U+9f3e\",\n },\n },\n {\n uri: _153,\n descriptors: {\n unicodeRange:\n \"U+4ede,U+4ee1,U+4eeb,U+4fda,U+4ffe,U+5025,U+506c,U+50f3,U+5106,U+520d,U+525c,U+52ad,U+530d,U+5310,U+539d,U+53a9,U+53fc,U+5421,U+5477,U+54e7,U+551b,U+5530,U+557e,U+5599,U+55c4,U+55d1,U+55d4,U+55df,U+55e4,U+55ea,U+5623,U+562d,U+5654,U+56eb,U+56f5,U+57a7,U+57d5,U+57dd,U+584d,U+5880,U+58ec,U+59dd,U+5a32,U+5a55,U+5a75,U+5b51,U+5b71,U+5b73,U+5cd2,U+5ce4,U+5e5b,U+5e96,U+5fd2,U+607b,U+61d1,U+634b,U+636d,U+63b3,U+63ff,U+64c0,U+661d,U+6657,U+66dc,U+67a5,U+6841,U+6867,U+6901,U+699b,U+6a47,U+6b46,U+6c21,U+6c24,U+6c35,U+6c4a,U+6c94,U+6ca3,U+6d39,U+6d63,U+6d6f,U+6d94,U+705e,U+71e7,U+726f,U+72cd,U+72de,U+72f0,U+7325,U+7350,U+7391,U+741a,U+757f,U+7583,U+75b1,U+75b4,U+75b8,U+75c2,U+75f1,U+766f,U+7699,U+7751,U+789c,U+7a17,U+7be6,U+7cb2,U+7ea3,U+7eb0,U+7ebe,U+7eeb,U+7f25,U+7f2c,U+7fb8,U+8026,U+8037,U+8153,U+8171,U+8191,U+8214,U+821b,U+8222,U+826e,U+82eb,U+830c,U+8314,U+8334,U+83d6,U+8418,U+843c,U+84ff,U+8564,U+8572,U+8616,U+866c,U+8693,U+86a3,U+86a7,U+86af,U+86b6,U+86c6,U+86ca,U+8708,U+870d,U+8759,U+8760,U+87af,U+87c6,U+8869,U+88c6,U+89d0,U+8b07,U+8baa-8bab,U+8bc2,U+8be4,U+8bf0,U+8c2a,U+8c62,U+8c89,U+8d49,U+8d6d,U+8d84,U+8d94,U+8db8,U+8dc6,U+8e2e,U+8e3d,U+8e47,U+8e7f,U+9005,U+9051,U+907d,U+9082,U+9088,U+90b0,U+90d3,U+9150,U+949c,U+94a4,U+94b9,U+94cb,U+94e0,U+9509,U+9512,U+951f,U+9534,U+9552-9553,U+965f,U+96b0,U+9791,U+9889,U+9990,U+9a9c,U+9aa7,U+9c88,U+9cb2-9cb3,U+9cb6-9cb7,U+9cc5,U+9cdc,U+9e22,U+9e2a,U+9e57,U+9e67,U+9e73,U+9e82,U+9eb8,U+9ee0,U+9f9b\",\n },\n },\n {\n uri: _154,\n descriptors: {\n unicodeRange:\n \"U+4eb5,U+4f09,U+4f5a,U+4f8f,U+4fce,U+4fdf,U+4fea,U+4ff3,U+500c,U+500f,U+504e,U+5088,U+52be,U+5420,U+5457,U+5499,U+549b,U+54c6,U+54d2,U+558b,U+559f,U+55bd,U+55d6,U+565c,U+567c,U+568e,U+5768,U+577b,U+57a9,U+57ed,U+59f9,U+5a11,U+5a40,U+5ae6,U+5b6a,U+5b93,U+5bb8,U+5c15,U+5c99,U+5c9c,U+5cc1,U+5d2e,U+5d4b,U+5d99,U+5e54,U+5e61,U+5fcf-5fd1,U+6002,U+6006,U+6014,U+60af,U+60c6,U+60da,U+60f4,U+621f,U+62c8,U+631b,U+631e,U+63e9,U+64b5,U+655d,U+6619,U+6635,U+6641,U+67ad,U+67b0,U+67b7,U+67e9,U+684e,U+688f,U+695d,U+696b,U+69b7,U+6a58,U+6c26,U+6d35,U+6d43,U+6d9e,U+6dd9,U+6dec,U+6e11,U+6e6e,U+6e9f,U+6ec2,U+6ee2,U+6ef9,U+6f09,U+6f66,U+6f8d,U+6fc2,U+6fc9,U+729f,U+72c8,U+73de,U+7430,U+7566,U+7579,U+75c9,U+75e2,U+75fc,U+762a,U+7638,U+7678,U+76c2,U+76f9,U+778c,U+77cd,U+77dc,U+7800,U+781d,U+782d,U+783b-783c,U+78a3,U+78ec,U+7980,U+7a23,U+7b95,U+7bdd,U+7c0c,U+7c41,U+7c91,U+7cb3,U+7cc5,U+7ecc,U+7f19,U+7fca,U+8006,U+8069,U+807f,U+80bd,U+80ed,U+814b,U+8198,U+82cb,U+82d2,U+834f,U+8360,U+847a,U+84d6,U+84e5,U+8537,U+85d0,U+8671,U+86a4,U+86ce,U+86f9,U+8703,U+8707,U+8737,U+873b,U+8815,U+8936,U+8bc3,U+8bcf,U+8bd2,U+8bd8,U+8be9,U+8c0c,U+8c0f,U+8c4c,U+8d45,U+8d5d,U+8d73,U+8e31,U+8e6d,U+8e76,U+8fe4,U+9041,U+90d7,U+9169,U+92ae,U+94a1,U+94c4,U+94c9,U+94db,U+94e7,U+9503,U+9506,U+9517,U+9528,U+9537,U+9542,U+9549,U+95fe,U+9616,U+961a,U+96c9,U+96f3,U+9701,U+970e,U+9739,U+9753,U+9798,U+98d2-98d3,U+98d9-98da,U+9968,U+996f,U+9984,U+9997,U+9acb,U+9b03,U+9c85,U+9ca8,U+9cab,U+9e49,U+9e51,U+9e66,U+9f10\",\n },\n },\n {\n uri: _155,\n descriptors: {\n unicodeRange:\n \"U+4e15,U+4e1e,U+4e2b,U+4eb3,U+4ec9,U+4f0e,U+4f64,U+501c,U+50a9,U+510b,U+51a2,U+51bc,U+527d,U+52d0,U+53fd,U+5429,U+542e,U+5486,U+54af,U+5506,U+5511,U+5522,U+552c,U+556c,U+55b3,U+55d2,U+55e6,U+55fd,U+561f,U+5639,U+5659,U+5662,U+5693,U+572a,U+5892,U+598a,U+5992,U+59a9,U+5a20,U+5ae3,U+5b17,U+5b7d,U+5d34,U+5d3d,U+5d4a,U+5d82,U+5e1a-5e1b,U+5ea5,U+5f0b,U+5f77,U+5fd6,U+5fff,U+6026,U+6035,U+6063,U+60b4,U+60bb,U+60ee,U+612b,U+6194,U+61ca,U+61e6,U+61f5,U+620a,U+6248,U+62a1,U+62d7,U+6376,U+637b,U+652b,U+65bc,U+65cc,U+65ce,U+65d6,U+664c,U+665f,U+6666,U+6684,U+66b9,U+6773,U+6777,U+6787,U+67de,U+6845,U+693d,U+6994,U+6a35,U+6d54,U+6d5c,U+6d8e,U+6dd6,U+6eb4,U+6f2a,U+6f78,U+704f,U+70ec,U+7118,U+714a,U+7172,U+71b9,U+724d,U+728a,U+7337,U+733e,U+7396,U+73b7,U+73cf,U+7428,U+742c,U+742e,U+74ee,U+74f4,U+7525,U+753a,U+7572,U+75d4,U+765c,U+768e,U+7762,U+777d,U+77fd,U+7825,U+7837,U+78b4,U+795f,U+79ed,U+7a1e,U+7b06,U+7b20,U+7ba9,U+7bab,U+7c7c,U+7cbd,U+7cdc,U+7ec9,U+7ef6,U+7f30,U+7f42,U+7f44,U+7f54,U+7f94,U+8004,U+800b,U+8019,U+809b,U+80ae,U+80c4,U+80f1,U+8146,U+816e,U+817c,U+81c0,U+81fc,U+81fe,U+822b,U+830f,U+832f,U+8340,U+8365,U+8385,U+8392,U+83a0,U+8424,U+84af,U+869c,U+8713,U+8717-8718,U+87c0,U+87cb,U+87fe,U+8821,U+8902,U+89d1,U+8bb9,U+8c12,U+8d32,U+8d53,U+8df7,U+8e7c,U+8f7c,U+8f95,U+8fab,U+9052,U+905b,U+9095,U+909d,U+90c5,U+911e,U+9122,U+916a,U+919b,U+948e,U+9492,U+949a,U+94b5,U+94bc,U+94c6,U+94f1,U+9502,U+9511,U+9536,U+956f-9570,U+9602,U+9621,U+9631,U+998b,U+99a5,U+9a81,U+9a9e,U+9ebe,U+9f8b\",\n },\n },\n {\n uri: _156,\n descriptors: {\n unicodeRange:\n \"U+4f2b,U+4f3d,U+4fac,U+5043,U+5055,U+5140,U+5156,U+51cb,U+5243,U+531d,U+536f,U+53a5,U+53ae,U+53f1,U+541d,U+5431,U+547b,U+5492,U+5494,U+54a4,U+54aa,U+54ce,U+54fd,U+5509,U+5520,U+553e,U+557b,U+55c5,U+55e1,U+55f7,U+5608,U+5636,U+563b,U+5773,U+57a0,U+5811,U+587e,U+58d5,U+59e3,U+5a29,U+5a6a,U+5a76,U+5a7a,U+5ac9,U+5b62,U+5b95,U+5c49,U+5c8c,U+5cab,U+5cb7,U+5d02,U+5d58,U+5e44,U+5e7a,U+5eff,U+5f29,U+5f89,U+5f9c,U+5fa8,U+6005,U+6043,U+60b8,U+60d8,U+60ec,U+60f0,U+6115,U+618e,U+630e,U+637a,U+6390,U+63ac,U+63b0,U+64de,U+6525,U+6538,U+65ee-65ef,U+6631,U+6636,U+6654,U+677c,U+67b8,U+67d8,U+683e,U+6886,U+68b5,U+692d,U+6963,U+6979,U+6988,U+6b59,U+6b9a,U+6c69,U+6c74,U+6cae,U+6ce0,U+6cef,U+6d95,U+6dc5,U+6dde,U+6de6,U+6dfc,U+6ea7,U+6f15,U+6f29,U+7096,U+70c3,U+7131,U+715c,U+7166,U+7266,U+7317,U+731d,U+7329,U+73e9,U+7425,U+7455,U+7490,U+74ef,U+7519,U+75b5,U+75b9,U+75de,U+7656,U+7663,U+7691,U+7729,U+77fe,U+783e,U+787c,U+795a,U+7a79,U+7abf,U+7b3a,U+7b4f,U+7b60,U+7b75,U+7b8d,U+7bb4,U+7bd3,U+7be1,U+7cbc,U+7edb,U+7f1c,U+7f8c,U+7fb2,U+7fb9,U+7fce,U+7ff1,U+810d,U+81c6,U+82a5,U+82aa,U+82de,U+8317,U+8343,U+835e,U+8364,U+836a,U+853a,U+8543,U+854a,U+8559,U+8568,U+85b0,U+85b9,U+864f,U+86e4,U+8715,U+8845,U+8884,U+88e8,U+88f1,U+8983,U+8be1,U+8c1f,U+8c27,U+8c5a,U+8c82,U+8d58,U+8dbe,U+8f98,U+9035,U+9074,U+90a1,U+9149,U+9157,U+93d6,U+949d,U+94c2,U+94e3-94e4,U+95eb,U+95f0,U+9611,U+9619,U+9642,U+968d,U+9706,U+970f,U+97ed,U+988a,U+9893,U+98e8,U+9a77,U+9a87,U+9aa1,U+9abc,U+9cdd,U+9e2f,U+9e33,U+9e44,U+9e5c,U+9e9d,U+9edd\",\n },\n },\n {\n uri: _157,\n descriptors: {\n unicodeRange:\n \"U+4f58,U+4f6c,U+4f70,U+4fd0,U+5014,U+51bd,U+524c,U+5315,U+5323,U+535e,U+540f,U+542d,U+545b,U+548e,U+549a,U+54ab,U+54fc,U+5567,U+556a,U+5600,U+5618,U+563f,U+5669,U+56f1,U+56ff,U+573b,U+574d,U+579b,U+57b8,U+57c2,U+586c,U+58f9,U+595a,U+598d,U+5993,U+5996,U+59d7,U+5b7a,U+5ba6,U+5c4e,U+5c96,U+5ce5,U+5eb6,U+5f08,U+5f99,U+602f,U+6059,U+606c,U+607a,U+60ed,U+61a9,U+620c,U+6249,U+62a8,U+62c4,U+62ed,U+62fd,U+6342,U+6345,U+6396,U+63a3,U+6402,U+6413,U+642a,U+6487,U+64a9,U+64ac,U+64ae,U+64b7,U+659f,U+65a1,U+667e,U+66f3,U+67e0,U+69db,U+69df,U+6aac,U+6b86,U+6c50,U+6c5e,U+6c76,U+6c85,U+6c8c,U+6cde,U+6d19,U+6d52,U+6da7,U+6db8,U+6e1a,U+6e25,U+6e4d,U+6e5f,U+6ec1,U+6f31,U+6f7a,U+6fa7,U+6fe1,U+701b,U+70ab,U+70f7,U+717d,U+71a8,U+7252,U+72c4,U+72e1,U+7315,U+736d,U+73ae,U+73c0,U+73c2,U+740f,U+75a4,U+7600-7601,U+768b,U+76bf,U+76d4,U+7728,U+772f,U+776c,U+77a0,U+77b0,U+77f8,U+783a,U+78d0,U+78fa,U+7977,U+7a37,U+7a92,U+7afa,U+7b71,U+7b94,U+7cef,U+7f28,U+7fe1,U+808b,U+80e5,U+80eb,U+8110,U+8113,U+812f,U+814c,U+81c3,U+8235,U+82d4,U+8309,U+83c1,U+8431,U+8469,U+84bf,U+84d3,U+84df,U+84e6,U+8511,U+8638,U+86c0,U+86db,U+86fe,U+8757,U+8822,U+8882,U+8885,U+8892,U+88f3,U+892a,U+8ba5,U+8bd9,U+8be0,U+8be7,U+8bfd,U+8c1a,U+8d4a,U+8d4e,U+8d66,U+8dda,U+8e0c,U+8e52,U+8e74,U+8e87,U+8f76,U+8fc2,U+8fe6,U+900d,U+9068,U+90ac,U+90b3,U+90b8,U+90e7,U+9119,U+9131,U+915a,U+916e,U+94b4,U+94d0,U+94e2,U+94ec,U+94ff,U+9522,U+9535,U+9556,U+965b,U+96f9,U+9774,U+9981,U+998d,U+998f,U+9a6e,U+9a7f,U+9a8a,U+9b13,U+9c9f,U+9e3e,U+9e43,U+9e6d,U+9e8b,U+9e92,U+9edb,U+9eef\",\n },\n },\n {\n uri: _158,\n descriptors: {\n unicodeRange:\n \"U+4e10,U+4e56,U+4e98,U+4ec3,U+4f3a,U+4f5f,U+4f88,U+4f97,U+4fa5,U+4fe8,U+504c,U+5197,U+52fa,U+5364,U+53e8,U+5406,U+543c,U+545c,U+5471,U+5480,U+5495,U+54b3,U+54df,U+54e6,U+54ee,U+557c,U+5583,U+55dc,U+55e3,U+566c,U+592f,U+5944,U+5983,U+59ca,U+59e5,U+5a13,U+5a7f,U+5b09,U+5bd0,U+5e4c,U+5eb5,U+5f1b,U+5f3c,U+608d,U+60cb,U+61a7,U+61ac,U+61cb,U+6233,U+62a0,U+62e7,U+62ee,U+62f4,U+62f7,U+634e,U+6382,U+63c9,U+63ea,U+6400,U+645e,U+6482,U+6556,U+6593,U+6615,U+664f,U+66e6,U+672d,U+675e,U+67da,U+6805,U+6808,U+6868,U+68a2,U+695e,U+69ad,U+6a80,U+6a90,U+6b83,U+6be1,U+6c30,U+6cad,U+6cb1,U+6cf1,U+6d31,U+6d93,U+6dae,U+6dbf,U+6dc6-6dc7,U+6e0d,U+6e32,U+6e3a,U+6e85,U+6eba,U+6f3e,U+6f5e,U+6f7c,U+6fee,U+71ee,U+722a,U+72b7,U+72e9,U+73ba,U+73d1,U+7409,U+7435-7436,U+7459-745a,U+747e,U+7487,U+74e2,U+7504,U+752c-752d,U+7599,U+759f,U+75a1,U+75ca,U+75f0,U+761f,U+7629,U+777f,U+7785,U+77a5,U+77bf,U+78d5,U+7934,U+7940,U+79a7,U+7b19,U+7c38,U+7c95,U+7cb1,U+7ce0,U+7eca,U+7ef7,U+7f2b,U+7f81,U+7fcc,U+8046,U+8148,U+8165,U+819b,U+81ba,U+828b,U+82ae,U+82b7,U+82d3,U+8301,U+830e,U+831c,U+8338,U+837c,U+8393,U+8398,U+83ba,U+83e0,U+83e9,U+853c,U+8654,U+86df,U+8712,U+873f,U+874e,U+8783,U+8859,U+88a4,U+8925,U+8bb7,U+8bff,U+8c19,U+8c1b,U+8c24,U+8c2c,U+8d61,U+8db4,U+8e6c,U+8f8a,U+8fe5,U+8ff8,U+901e,U+90f4,U+912f,U+9163,U+9170,U+91dc,U+949b,U+94a8,U+94b3,U+94c0,U+94e8,U+9525,U+9530,U+9539,U+954c-954d,U+9550,U+955b,U+962a,U+9685,U+96cc,U+9776,U+988d,U+9975,U+9985,U+9a6f,U+9aa5,U+9ab8,U+9c7f,U+9ca4,U+9cb8,U+9e25,U+9e35,U+9e4a\",\n },\n },\n {\n uri: _159,\n descriptors: {\n unicodeRange:\n \"U+4ea2,U+4ea5,U+4f36,U+4f84,U+4f8d,U+501a,U+5029,U+516e,U+51a5,U+51c4,U+51f8,U+5201,U+527f,U+5321,U+5352,U+5366,U+53e9,U+54c7,U+5632,U+5676,U+56b7,U+56bc,U+56da,U+56e4,U+5703,U+5729,U+5742,U+57a2-57a3,U+5815,U+58d1,U+5919,U+592d,U+5955,U+5a05,U+5a25,U+5a34,U+5b70,U+5b75,U+5bdd,U+5bf0,U+5c41,U+5c79,U+5c91,U+5c94,U+5ce6,U+5ced,U+5d69,U+5dc5,U+5e16,U+5e27,U+5f27,U+5f95,U+5ffb,U+6020,U+604d,U+6055,U+60e6,U+60eb,U+6123,U+618b,U+61a8,U+620d,U+62c7,U+62ce,U+62d9,U+631f,U+634d,U+6452,U+6479,U+64ce,U+64d2,U+655b,U+660a,U+6726,U+67c4,U+6809,U+6853,U+68e3,U+68f1,U+68fa,U+693f,U+6942,U+6995,U+69a8,U+69b4,U+6a71,U+6b89,U+6bcb,U+6bd3,U+6bd9,U+6c40,U+6cf8,U+6cfe,U+6d85,U+6da3,U+6daa,U+6e0e,U+6e43-6e44,U+6f88,U+7078,U+7099,U+70bd,U+70d9,U+70fd,U+7109,U+7184,U+7239,U+733f,U+73f2,U+748b,U+749c,U+749e,U+759a,U+75d2,U+75eb,U+7620,U+766b,U+7693,U+76cf,U+7738,U+773a,U+776b,U+778e,U+77aa,U+7852,U+78be,U+7948,U+795b,U+7960,U+796f,U+79ba,U+7a20,U+7a96,U+7aa5,U+7b03,U+7b28,U+7b50,U+7b77,U+7bc6,U+7bf1,U+7c27,U+7d0a,U+7ead,U+7ec5,U+7ee2,U+7ef0,U+7efd,U+7f0e,U+7f2e,U+7f79,U+7f9a,U+8098,U+80da,U+80e7,U+80f0,U+80f3,U+80fa,U+818a,U+81e7,U+8237-8238,U+8299,U+82b8,U+82ce,U+837b,U+83bd,U+83cf,U+8426,U+8475,U+85c9,U+85d5,U+85dc,U+85e9,U+871a,U+8747,U+8749,U+888d,U+8910,U+891a,U+8bb4,U+8be3,U+8bec,U+8bf2,U+8c06,U+8c0d,U+8d31,U+8d48,U+8de4,U+8e1e,U+8e4a,U+8e66,U+8f84,U+8f97,U+9083,U+90e1,U+9165,U+91c9,U+94b0,U+94f5,U+9504,U+9532,U+956d,U+95f5,U+95fa,U+9668,U+9698,U+96bd,U+9704,U+9773,U+9890,U+996a,U+997a,U+9a74,U+9a8b,U+9cc4,U+9ccc\",\n },\n },\n {\n uri: _160,\n descriptors: {\n unicodeRange:\n \"U+4ea8,U+4f1e,U+4f51,U+4f63,U+4f7c,U+4f83,U+4fa0,U+4fd1,U+4ffa,U+5018,U+5026,U+508d,U+50bb,U+50f5,U+50fb,U+5162,U+5319,U+5320,U+538c,U+5413,U+541f,U+5475,U+54bd,U+54d1,U+5589,U+5598,U+575f,U+57ae,U+57e0,U+5937,U+5974,U+5978,U+59ae,U+5a1f,U+5a49,U+5ab3,U+5b99,U+5b9b,U+5ba0,U+5be1,U+5be5,U+5c09,U+5c27,U+5de2,U+5e9a,U+5f26,U+5f8a,U+5f98,U+6021,U+606d,U+60bc,U+60d5,U+60e7,U+611a,U+614c,U+6254,U+626f,U+6292,U+6296,U+62b9,U+62e2,U+631a,U+631d,U+6320,U+6346,U+63ba,U+6467,U+64bc,U+658b,U+663c,U+6643,U+6652,U+6656,U+6687,U+66d9,U+66dd,U+66f0,U+673d,U+67ab,U+6816-6817,U+68a7,U+68ad,U+68cd,U+68e0,U+6986,U+69fd,U+6b47,U+6bd7,U+6c1f,U+6c2e-6c2f,U+6cbe,U+6de4,U+6e1d,U+6e83,U+6e9c,U+6ed4-6ed5,U+6f4d,U+70f9,U+7130,U+716e,U+718f,U+71ac,U+71e5,U+72fc,U+731c,U+7334,U+73ca,U+7422,U+7426,U+745f,U+7470,U+75af,U+75f4,U+762b,U+763e,U+7696,U+7737,U+7741,U+77a7,U+77bb,U+77ee,U+785d,U+788c,U+78ca,U+7901,U+796d,U+7985,U+79fd,U+7a3c,U+7a57,U+7a74,U+7b5b,U+7caa,U+7cb9,U+7cd5,U+7eac,U+7eb6,U+7ed1,U+7ee5,U+7f20,U+7f2a,U+7f38,U+7f69,U+7fa1,U+8018,U+8038,U+803f,U+804b,U+80a2,U+80be,U+80d6,U+817a,U+81fb,U+820c,U+82ad,U+82af,U+82bd,U+8327,U+8354,U+835f,U+8367,U+836b,U+840c,U+841d,U+8471,U+849c,U+84b2,U+84c9,U+8517,U+851a,U+8549,U+8681,U+8721,U+8776,U+88d9,U+88f9,U+89c5,U+8c1c,U+8c34,U+8d81,U+8d9f,U+8e0a,U+8e72,U+8eb2,U+8fed,U+901b,U+902e,U+906e,U+9091,U+90aa,U+90af,U+915d,U+9171,U+946b,U+9489,U+9499,U+94a5,U+9508,U+9524,U+952d,U+9551,U+9576,U+95f7,U+9600,U+96b6,U+96c0,U+9756,U+97f6,U+98a0,U+98a4,U+997f,U+9a73,U+9a86,U+9ad3,U+9e3d,U+9ed4\",\n },\n },\n {\n uri: _161,\n descriptors: {\n unicodeRange:\n \"U+4e4d,U+4e5e,U+4ec7,U+4ed5,U+50da,U+50e7,U+515c,U+51a4,U+51ff,U+5203,U+5254,U+5300,U+533e,U+5375,U+53ee,U+5435,U+543b,U+5455,U+548b,U+548f,U+54d7,U+54fa,U+5578,U+5587,U+55a7,U+560e,U+5760,U+576f,U+5777,U+5830,U+58a9,U+5962,U+59e8,U+5a07,U+5a23,U+5a3c,U+5b5a,U+5bb5,U+5bc5,U+5bde,U+5c7f,U+5cb1,U+5ce8,U+5cea,U+5d29,U+5d4c,U+5e18,U+5f57,U+5f5d,U+5f87,U+5ff1,U+6016,U+601c,U+6064,U+6177,U+61d2,U+625b,U+62e3,U+62f1,U+634f,U+63a0,U+6401,U+6405,U+6495,U+64c2,U+6512,U+6577,U+6590,U+65a7,U+65a9,U+65f7,U+6627,U+6655,U+6714,U+6795,U+67d1,U+67ff,U+68b3,U+68d5,U+68d8,U+6930,U+6960,U+6977,U+69bb,U+69d0,U+6a31,U+6b7c,U+6bb4,U+6c22,U+6c72,U+6c79,U+6c7e,U+6c81,U+6c93,U+6ca5,U+6cbc,U+6ce3,U+6cfb,U+6d3c,U+6da9,U+6df3,U+6e2d,U+6eaf,U+6ec7,U+6f13,U+6f33,U+6f62,U+6fa1,U+7011,U+707c,U+708a,U+70c1,U+70d8,U+70eb,U+711a,U+7194,U+7281,U+7316,U+7357,U+7384,U+7405,U+742a,U+745b,U+7574,U+7578,U+75ea,U+7682,U+7792,U+77d7,U+77e9,U+77eb,U+77f6,U+780c,U+78c5,U+7941,U+79e4,U+7a1a,U+7a9c,U+7ad6,U+7b5d,U+7bf7,U+7c07,U+7c3f,U+7c9f,U+7ca5,U+7cdf,U+7e82,U+7eab,U+7ece,U+7eda,U+7f09,U+7f15,U+7f9e,U+7fdf,U+7fe9,U+803b,U+803d,U+80aa,U+80b4,U+813e,U+8155,U+817b,U+819d,U+821c,U+82b9,U+82df,U+82ef,U+8304,U+83b9,U+8446,U+853d,U+85af,U+85fb,U+8650,U+865e,U+86d9,U+86ee,U+8700,U+8862,U+889c,U+88d4,U+88f8,U+895f,U+8a79,U+8bb3,U+8bb6,U+8bc0,U+8beb,U+8bf5,U+8c23,U+8c79,U+8d1e,U+8dcb,U+8e29,U+8e44,U+8e81,U+8eac,U+8eaf,U+8f8d,U+9050,U+90f8,U+914b,U+948a,U+94be,U+94ee,U+950c,U+9540,U+962e,U+9647,U+9661,U+9699,U+96cf,U+9716,U+9761,U+97a0,U+97e7,U+9a7c,U+9a8f,U+9ae6,U+9cd6,U+9e26\",\n },\n },\n {\n uri: _162,\n descriptors: {\n unicodeRange:\n \"U+4fa3,U+4fae,U+4fd8,U+4fef,U+50a3,U+5189,U+5195,U+51db,U+51f3,U+51f9,U+5220,U+5228,U+5288,U+52ff,U+532e,U+533f,U+5351,U+53db,U+53ed,U+5450,U+5484,U+5490,U+54c9,U+54e9,U+5501,U+5507,U+5543,U+55d3,U+56a3,U+575e,U+589f,U+5984,U+59ec,U+5a04,U+5a36,U+5a77,U+5a9a-5a9b,U+5ab2,U+5ac2,U+5ad6,U+5bc7,U+5c2c,U+5c34,U+5c51,U+5cd9,U+5d0e,U+5deb,U+5e3c,U+5e87,U+5ed3,U+5f13,U+5f64,U+5fe1,U+606a,U+6096,U+60df,U+60f6,U+60f9,U+6151,U+620e,U+6241,U+6252,U+6273,U+627c,U+6289,U+62c2,U+62cc,U+62ef,U+6361,U+6363,U+63b7,U+63e3,U+6518,U+66ae,U+6756,U+6789,U+6813,U+6829,U+6862,U+6866,U+6893,U+6897,U+690e,U+6984,U+69cc,U+6a1f,U+6a44,U+6a59,U+6ba1,U+6c13,U+6c90,U+6ca6,U+6cbd,U+6ccc,U+6cd3,U+6cd7,U+6d4a,U+6d4f,U+6d5a,U+6d9f,U+6da1,U+6dcc,U+6ea5,U+6ee4,U+6ee6,U+6f2f,U+6f8e,U+701a,U+7095,U+709c,U+70af,U+70db,U+70e8,U+714e,U+715e,U+71a0,U+71ce,U+7235,U+7280,U+72d0,U+72f8,U+73ab,U+7410,U+745c,U+7480,U+74a7-74a8,U+74e3,U+75ae,U+75f9,U+76b1,U+76ce,U+7736,U+77e2-77e3,U+781a,U+789f,U+797a,U+79be,U+79c3,U+79c6,U+79f8,U+7a8d,U+7a98,U+7aa6,U+7aff,U+7b1b,U+7cd9,U+7d6e,U+7ede,U+7eee,U+7f00,U+7f24,U+7f2d,U+7fd8,U+800d,U+8116,U+8151,U+81b3,U+8205,U+82c7,U+82db,U+832c,U+8335,U+8339,U+8386,U+846b,U+8587,U+8611,U+8682,U+868a,U+868c,U+8774,U+88d8,U+88f4,U+8912,U+8b6c,U+8bbd,U+8c0e,U+8c41,U+8d26,U+8d3b-8d3c,U+8d50,U+8dea,U+8e35,U+8f99,U+8fe2,U+8fe9,U+9017,U+914c,U+916f,U+9175-9176,U+918b,U+94a0,U+94ae,U+94ce,U+94f2,U+951a,U+952f,U+9541,U+9640,U+9672,U+968b,U+96cd,U+96ef,U+9713,U+97ec,U+9885,U+9992,U+9a6d,U+9a79,U+9a85,U+9cbb,U+9cd7,U+9cde,U+9e93,U+9f9f\",\n },\n },\n {\n uri: _163,\n descriptors: {\n unicodeRange:\n \"U+4e11,U+4ed7,U+4fcf,U+4fe9,U+4fed,U+50ac,U+50b2,U+5112,U+5180,U+5188,U+51f6,U+522e,U+5265,U+52cb,U+52df,U+5349,U+5367,U+5378,U+537f,U+5395,U+5398,U+53d4,U+543e,U+5440,U+5446,U+54b8,U+5565-5566,U+5580,U+55bb,U+56ca,U+572d,U+573e,U+574e,U+5782-5784,U+58f3,U+5938-5939,U+5948,U+594e,U+5a1c,U+5a74,U+5ae9,U+5b55,U+5b5c,U+5bb0,U+5bd3,U+5bf8,U+5c3f,U+5d14,U+5d2d,U+5df7,U+5dfe,U+5e05-5e06,U+5e1c,U+5e62,U+5e7b,U+5e7d,U+5ed6,U+5f2f,U+5f66,U+5f6c,U+5fa1,U+604b,U+609f,U+60a6,U+60e8,U+6101,U+6124,U+6127,U+6148,U+61be,U+6247,U+62d8,U+62da,U+633d,U+635e,U+6367,U+6380,U+638f,U+63a9,U+63fd,U+641c,U+64e6,U+655e,U+6572,U+6591,U+65a5,U+6691,U+6735,U+67a2-67a3,U+67ef,U+680b,U+6876,U+6905,U+6a0a,U+6a61,U+6b79,U+6bb7,U+6bbf,U+6c41,U+6c55,U+6c83,U+6c9b,U+6ca7,U+6cfc,U+6d46,U+6d51,U+6d74,U+6d9d,U+6daf,U+6dc0,U+6deb,U+6e17,U+6e24,U+6e89,U+6ea2,U+6ef4,U+6f6d,U+707f,U+70b3,U+70e4,U+70ef,U+710a,U+722c,U+725f,U+7261,U+72ee,U+72f1,U+730e,U+732b,U+7433,U+7538,U+75bc,U+7624,U+7709,U+7750,U+7779,U+7802,U+7898,U+78a7,U+78b1,U+78cb,U+78f7,U+7984,U+7a83,U+7aed,U+7b3c,U+7b4b,U+7c92,U+7c98,U+7ca4,U+7eb9,U+7ee3,U+7ef3,U+7ef5,U+7f05,U+7f55,U+7f62,U+7fc1,U+7fd4,U+7fe0,U+8042,U+806a,U+80a0,U+80a4,U+80c3,U+8102,U+8106,U+814a,U+8154,U+8247,U+8258,U+82cd,U+8328,U+832b,U+8389,U+83ca,U+845b,U+846c,U+84b8,U+8574,U+859b,U+8680,U+8695,U+86c7,U+8702,U+886c,U+8896,U+88b1,U+88e4,U+8bc8,U+8c10,U+8c26,U+8c28,U+8c2d,U+8d4c,U+8d63,U+8f67,U+8f74,U+8fc4,U+9006,U+9063,U+90a2,U+90b1,U+90c1,U+9177,U+9189,U+9493,U+949e,U+94fe,U+9610,U+961c,U+96a7,U+96fe,U+978d,U+97f5,U+9888,U+997c,U+9a84,U+9b3c,U+9b44-9b45,U+9b54,U+9e64,U+9f0e,U+9f9a\",\n },\n },\n {\n uri: _164,\n descriptors: {\n unicodeRange:\n \"U+4e19,U+4e38,U+4e53,U+4e7e,U+4e9f,U+4ec6,U+4f50,U+4fde,U+502a,U+5154,U+517d,U+51d1,U+51f0,U+5239,U+5256,U+52c9,U+52fe,U+5308,U+532a,U+535c,U+5384,U+53a2,U+53a8,U+53c9,U+53e0,U+5496,U+54ac,U+54c0,U+54c4,U+54e8,U+5561,U+5582,U+561b,U+5631,U+566a,U+5764,U+576a,U+5792,U+57ab,U+584c,U+5885,U+58f6,U+59a8,U+5acc,U+5bc2,U+5c38-5c39,U+5c60,U+5c6f,U+5c82,U+5c90,U+5d16,U+5dcd,U+5e37,U+5e90,U+5eb8,U+5f6a,U+5fcc,U+6012,U+6068,U+6073,U+607c,U+6094,U+6109,U+621a,U+626e,U+6284,U+62d0,U+62e6,U+62fe,U+6321,U+6328,U+632b,U+6349,U+6454,U+65ed,U+660f,U+6674,U+66a8,U+6749,U+674f,U+6760,U+67af,U+6850,U+6854,U+6869,U+68a8,U+68d2,U+68f5,U+6912,U+6b49,U+6b6a,U+6bef,U+6c28,U+6c5d,U+6c82,U+6cab,U+6cb8,U+6cc4,U+6cf5,U+6d47,U+6d78,U+6da4,U+6dc4,U+6dcb,U+6df9,U+6e0a,U+6e23,U+6e5b,U+6eb6,U+6f06,U+6f47,U+6f84,U+6f9c,U+6fd2,U+7076,U+70ac,U+7199,U+723d,U+72ac,U+72ed,U+7476,U+7529,U+752b,U+754f,U+7554,U+75d5,U+7626,U+76ef,U+7720,U+7766,U+7784,U+77ac,U+780d,U+7838,U+7845,U+786b,U+78b3,U+7978,U+79b9,U+79c9,U+79e7,U+7a3d,U+7a84,U+7a9f,U+7b0b,U+7b52,U+7c7d,U+7f1a,U+7fc5,U+7ff0,U+804a,U+8086-8087,U+808c,U+809a,U+80ba,U+810a,U+8180,U+818f,U+81c2,U+81ed,U+8231,U+8292,U+829c,U+82a6,U+82d1,U+8346,U+838e,U+839e,U+83c7,U+83f1,U+8403,U+840e,U+8513,U+857e,U+85e4,U+867e,U+871c,U+87ba,U+87f9,U+884d,U+8944,U+8a93,U+8c05,U+8d2c,U+8d2e,U+8d42-8d43,U+8dfb,U+8e22,U+8eba,U+8f69,U+8f9c,U+8fa3,U+8fa8,U+8fb1,U+900a,U+9038,U+903b,U+9042,U+904f,U+90b5,U+90dd,U+9102,U+9187,U+94a7,U+94c5,U+9523,U+95f8,U+95fd,U+960e,U+964b-964c,U+96c1,U+9709,U+971c,U+97ad,U+9882,U+9965,U+9976,U+9988,U+99a8,U+9a82,U+9a9a,U+9b41,U+9c8d,U+9e45,U+9e70,U+9e9f,U+9f3b,U+9f7f\",\n },\n },\n {\n uri: _165,\n descriptors: {\n unicodeRange:\n \"U+4e08,U+4e18,U+4e1b,U+4e22,U+4e27,U+4e32,U+4e52,U+4e73,U+4ead,U+4ed4,U+4ed9,U+4ef0,U+4fa6,U+5076,U+5179,U+51bb,U+51c9,U+51ef,U+51fd,U+524a,U+526a,U+529d,U+52ab,U+5306,U+5339,U+53d9,U+540a,U+5410,U+541e,U+5439,U+54b1,U+54ed,U+5564,U+558a,U+55b7,U+5634,U+574a,U+5751,U+57a6,U+57cb,U+57d4,U+5824,U+582a,U+5835,U+5858,U+5893,U+58e4,U+5951,U+5986,U+59da,U+59fb,U+59ff,U+5a03,U+5a46,U+5ac1,U+5b5d,U+5bfa,U+5c18,U+5c3a,U+5c48,U+5c4f,U+5c61,U+5cb3,U+5d1b,U+5e15,U+5e3d,U+5e99,U+5e9e,U+5eca,U+5f0a,U+5f17-5f18,U+5f25,U+5f7c,U+5fcd,U+6028,U+60a0,U+60ac,U+60d1,U+614e,U+6155,U+6168,U+61c8,U+6208,U+6212,U+6251,U+629a-629b,U+62ab-62ac,U+62fc,U+6323,U+632a,U+63d2,U+643a,U+6491-6492,U+649e,U+64b0,U+64c5,U+659c,U+6614,U+662d,U+6664,U+6670,U+6676,U+6746,U+67cf,U+67d4,U+682a,U+6843,U+6846,U+68da,U+6b3a,U+6b67,U+6c27,U+6c5b,U+6c64,U+6c70,U+6caa,U+6cca,U+6ce1,U+6d12,U+6d45,U+6dd1,U+6dd8,U+6e34,U+6e7f,U+6ee5,U+6f02,U+7092,U+70c2,U+70e6,U+7115,U+7237,U+7272,U+727a,U+72c2,U+739b,U+73b2,U+743c,U+751c,U+758f,U+75b2,U+7686,U+76c6,U+76d2,U+76fc,U+775b,U+77a9,U+7816,U+788e,U+7897,U+78b0,U+79bd,U+7a0d,U+7a91,U+7a9d,U+7ae3,U+7bad,U+7cca,U+7d2b,U+7eb1,U+7f06,U+7f14,U+7f1d,U+7f50,U+7ffc,U+8036,U+80bf,U+80c1,U+80ce,U+80f8,U+8109,U+810f,U+8170,U+8179,U+819c,U+821f,U+8230,U+8236,U+8273,U+829d,U+82f9,U+8305,U+8350,U+83b2,U+83cc,U+8404,U+840d,U+8427,U+8482,U+8679,U+8854,U+886b,U+8bbc,U+8be6,U+8c31,U+8c6b,U+8d4b,U+8dcc,U+8e2a,U+8e48,U+8f90,U+8fb0,U+9022,U+903c,U+903e,U+9065,U+916c,U+917f,U+94a9,U+94c3,U+94dd,U+94ed,U+9510,U+953b,U+96c7,U+970d,U+9738,U+9877,U+987d,U+989c,U+98d8,U+9a70,U+9a91,U+9aa4,U+9b42,U+9b4f,U+9e2d,U+9e3f,U+9e7f,U+9f20\",\n },\n },\n {\n uri: _166,\n descriptors: {\n unicodeRange:\n \"U+4e59,U+4ed3,U+4f0f,U+4f38,U+4f69,U+4fa7,U+4faf,U+4ff1,U+5077,U+5085,U+5144,U+5151,U+51af,U+51b6,U+51cc,U+523a,U+5251,U+5269,U+5272,U+52d8,U+5353,U+5389,U+53f9,U+5401,U+5415,U+541b,U+54f2,U+5524,U+554a,U+559d,U+5609,U+5740,U+575d,U+5806,U+5821,U+586b,U+5915,U+594f,U+5960,U+5999,U+59a5,U+59b9,U+59c6,U+59d1,U+59dc,U+5b5f,U+5b64,U+5b87,U+5bb4,U+5bbf,U+5c16,U+5c1d,U+5c3e,U+5c9a,U+5ca9,U+5cad,U+5cfb,U+5de1,U+5de7,U+5de9,U+5ef7,U+5f04,U+5f70,U+5f79,U+5fc6,U+602a,U+6050,U+6052,U+6070,U+6084,U+60b2,U+60dc,U+60e9,U+6167,U+6170,U+61c2,U+6270,U+6291,U+62b1,U+62bc,U+62dc,U+62df,U+62f3,U+6324,U+633a,U+6377,U+6398,U+63cf,U+640f,U+642c-642d,U+6458,U+6478,U+6500,U+654c,U+6566,U+658c,U+65c1,U+65cb,U+65e8,U+65ec,U+6696-6697,U+6734,U+679a,U+679d,U+67dc,U+67f3-67f4,U+680f,U+683d,U+684c,U+68af,U+699c,U+6bc1,U+6c0f,U+6c1b,U+6c57,U+6c6a,U+6d3d,U+6d6e,U+6d82,U+6db5,U+6dee,U+6e58,U+6eaa,U+6ecb,U+6ede,U+6ee9,U+6f0f,U+6f20,U+6f58,U+704c,U+7070,U+70b8,U+718a,U+7238,U+7262,U+7275,U+72b9,U+72d7,U+72e0,U+741b,U+7434,U+7483,U+74f6-74f7,U+75ab,U+764c,U+7761,U+7855,U+7891,U+78c1,U+79d2,U+7a00,U+7a3b,U+7c97,U+7ea4,U+7eb2,U+7ed2,U+7eea,U+7ef8,U+7f18,U+7fbd,U+8000,U+8010,U+8096,U+809d,U+80a9,U+817f,U+81e3,U+8206,U+8212,U+82ac,U+8302,U+8361,U+8377,U+83f2,U+8461,U+848b,U+84ec,U+8521,U+85aa,U+8870,U+8877,U+8881,U+888b,U+88ad,U+88c2,U+8986,U+8bd1,U+8bf1,U+8d24,U+8d2a,U+8d3e-8d3f,U+8d41,U+8d56,U+8d64,U+8d6b,U+8e0f,U+8f70,U+8f85,U+8f88,U+8fa9,U+9003,U+901d,U+90b9,U+90ce,U+94a6,U+94f8,U+9505,U+95ea,U+95ef,U+95f2,U+95f9,U+9601,U+9605,U+9634,U+966a,U+9677,U+9690,U+9694,U+96d5,U+971e,U+9896-9897,U+9972,U+9a71,U+9a76,U+9a7e,U+9e1f,U+9e23\",\n },\n },\n {\n uri: _167,\n descriptors: {\n unicodeRange:\n \"U+4e01,U+4e43,U+4ea6,U+4ef2,U+4eff,U+4f26,U+4f2a,U+4f2f,U+4f5b,U+4fa8,U+4fca,U+4fd7,U+5021,U+504f,U+5141,U+51c0,U+51dd,U+51e4,U+51ed,U+5200,U+5237,U+5427,U+5448,U+54a8,U+5706,U+5708,U+5723,U+575b,U+57c3,U+5899,U+58a8,U+58c1,U+5976,U+5988,U+59bb,U+59d0,U+59d3,U+5a18,U+5a31,U+5a92,U+5b54,U+5b85,U+5baa-5bab,U+5bc4,U+5bd2,U+5be8,U+5bff,U+5c65,U+5d07,U+5e1d,U+5e78,U+5e7c,U+5f03,U+5f1f,U+5f39,U+5f6d,U+5f92,U+5faa,U+5fbd,U+5fe7,U+5ffd,U+60a8,U+60ef,U+6108,U+6162,U+622a,U+6234,U+626b,U+626d,U+62c6,U+62d2,U+62d4,U+62d6,U+62e8,U+6316,U+6355,U+63ed,U+6447,U+64a4,U+65f1,U+6606,U+6628,U+664b,U+6668,U+6682,U+66f9,U+66fc,U+66ff,U+6717,U+6740,U+676d,U+67aa,U+67ec,U+67f1,U+6842,U+6851,U+695a,U+6982,U+6a2a,U+6b20,U+6b23,U+6b32,U+6b96,U+6bc5,U+6beb,U+6c60,U+6c9f,U+6cea,U+6cf3,U+6d1e,U+6d53,U+6d66,U+6d69,U+6d8c,U+6d9b,U+6db2,U+6de1,U+6dfb,U+6e14,U+6ed1,U+6eda,U+6ee8,U+6f2b,U+706d,U+7089,U+708e,U+70ad-70ae,U+70e7,U+7126,U+714c,U+71c3,U+71d5,U+7206,U+7259,U+731b,U+73a9,U+73bb,U+74dc,U+7532,U+7545,U+755c,U+75c7,U+7687,U+76d7,U+76f2,U+788d,U+78e8,U+79e6,U+79e9,U+7a3f,U+7a46,U+7a97,U+7af9,U+7bee,U+7c4d,U+7c89,U+7cd6,U+7eb5,U+7ebd,U+7ed8,U+8017,U+8033,U+80c0,U+80de,U+80f6,U+8138,U+817e,U+81a8,U+820d,U+827e,U+82b3,U+82d7,U+83b1,U+84c4,U+84dd,U+8584,U+864e,U+865a,U+866b,U+86cb,U+88d5,U+89e6,U+8bca,U+8bde,U+8bfa,U+8c0a,U+8c37,U+8c46,U+8c6a,U+8c8c,U+8d1d,U+8d29,U+8d4f,U+8d54,U+8d5a,U+8d60,U+8d62,U+8f7f,U+8f96,U+8f9e-8f9f,U+8fc1,U+8fdf,U+8fea,U+8ff7,U+9012,U+906d,U+9075,U+90a6,U+90bb,U+90ca,U+9178,U+9192,U+91ca,U+94bb,U+94dc,U+94fa,U+9501,U+950b,U+9521,U+955c,U+963b,U+9655,U+9675-9676,U+9887,U+9891,U+9971,U+9a97,U+9ece,U+9ed8\",\n },\n },\n {\n uri: _168,\n descriptors: {\n unicodeRange:\n \"U+4e1d,U+4e39,U+4e4c,U+4e4f,U+4e54,U+4e58,U+4e95,U+4ea1,U+4eab,U+4eae,U+4ec1,U+4f10,U+4f19,U+4f30,U+4f34,U+4fb5,U+503e,U+518c,U+5192,U+51a0,U+51ac,U+51b0,U+51e1,U+5211,U+5242,U+52a3,U+52b2,U+52c3,U+52c7,U+52d2,U+52e4,U+5377,U+539a,U+53a6,U+53e5,U+5417,U+5510,U+552f,U+5531,U+574f-5750,U+5761,U+5851,U+5854,U+58ee,U+593a,U+5949,U+5954,U+5a5a,U+5b8b,U+5bbd,U+5c04,U+5c0a,U+5c4b,U+5ce1,U+5cf0,U+5e10,U+5e8a,U+5e9f,U+5ec9,U+5f31,U+5f84,U+5fd8-5fd9,U+5fe0,U+6015,U+6062,U+6069,U+6076,U+6089,U+60a3,U+60ca,U+620f,U+624e,U+6263,U+6298,U+62a2,U+62bd,U+6311,U+6350,U+6389,U+638c,U+63f4,U+6446,U+644a,U+6469,U+64cd,U+654f,U+6562,U+656c,U+65d7,U+65e6,U+65fa,U+660c,U+6653,U+66b4,U+670b,U+672b,U+676f-6770,U+6881,U+6885,U+68a6,U+68cb,U+68ee,U+6b8a,U+6c88-6c89,U+6cc9,U+6ce5,U+6d01,U+6d17,U+6d1b,U+6d59,U+6d6a,U+6da8,U+6df7,U+6e10,U+6e20-6e21,U+6f5c,U+706f,U+70bc,U+719f,U+7267,U+732a,U+73cd,U+7518,U+756a,U+7586,U+7591,U+75db,U+76c8,U+76d0,U+76d6,U+76d8,U+76df,U+76fe,U+77db,U+7801,U+786c,U+795d,U+7965,U+79cb,U+7a77,U+7a7f,U+7aef,U+7b11,U+7bb1,U+7bc7,U+7ea0,U+7eaf,U+7ed5,U+7edc,U+7f13,U+7f29,U+7f34,U+7f8a,U+7ffb,U+8015,U+8058,U+805a,U+8083,U+80af,U+80c6,U+80cc,U+811a,U+8150,U+82e5,U+8336,U+8352,U+83ab,U+8428,U+8463,U+852c,U+8861,U+89c8,U+8bcd,U+8bd7,U+8bda,U+8be2,U+8bef,U+8bf8,U+8c0b,U+8c13,U+8d34,U+8d3a,U+8d74,U+8d76,U+8da3,U+8dd1,U+8ddd,U+8ddf,U+8df3,U+8f68,U+8f6f,U+8f7d,U+8f91,U+8f9b,U+8fbd,U+8fc8,U+8fd4,U+8feb,U+8ff9,U+900f,U+9057,U+907f-9080,U+90d1,U+90ed,U+91ce,U+9519,U+9526,U+95ed,U+9614,U+9635,U+9644,U+9686,U+96c5,U+96ea,U+9707,U+9732,U+9759,U+978b,U+9876,U+9881,U+9910,U+996e,U+9970,U+9c81,U+9e21,U+9ebb,U+9f84\",\n },\n },\n {\n uri: _169,\n descriptors: {\n unicodeRange:\n \"U+4e3d,U+4e4e,U+4e71,U+4e8f,U+4ed8,U+4eea,U+4f0a,U+4f0d,U+4f11,U+4f1f,U+4f24,U+4f3c,U+4f73,U+4fc4,U+500d,U+5012,U+501f,U+503a,U+505c,U+507f,U+50a8,U+514d,U+5178,U+517c,U+51b2,U+51b7,U+520a,U+5238,U+523b,U+52b1,U+535a,U+5371,U+5385,U+53eb-53ec,U+53f3,U+53f6,U+5409,U+542b,U+542f,U+5434,U+5462,U+5473,U+547c,U+54c8,U+54ea,U+56fa,U+5733,U+5757,U+5766,U+5802,U+585e,U+590f,U+591c,U+591f,U+5947,U+594b,U+5987,U+5a01,U+5b59,U+5b63,U+5b88,U+5b97,U+5b9c,U+5bbe,U+5bfb,U+5c01,U+5c1a,U+5c24,U+5c3c,U+5c97,U+5c9b,U+5cb8,U+5de6,U+5e01,U+5e2e,U+5e45,U+5e55,U+5e84,U+5ef6,U+5f02,U+5f52,U+5f69,U+5f7b,U+5f90,U+5fae,U+6000,U+600e,U+6025,U+60e0,U+6276,U+6297,U+62b5,U+62cd,U+62d3,U+62e5,U+62e9,U+62ff,U+6302,U+632f,U+63e1,U+6444,U+64ad,U+653b,U+6551,U+6563,U+65a4,U+65e7,U+6620,U+667a,U+66f2,U+671d,U+6731,U+6742,U+675f,U+6768,U+677e-677f,U+6790,U+67b6,U+67d3,U+6863,U+68b0,U+68c9,U+690d,U+6b8b,U+6bcd,U+6bd2,U+6bd5,U+6c38,U+6c61,U+6cbf,U+6cdb,U+6cf0,U+6d2a,U+6d89,U+6da6,U+6f6e,U+6fb3,U+7075,U+707e,U+70df,U+7164,U+7236,U+725b,U+7389,U+73e0,U+745e,U+74e6,U+751a,U+7537,U+75be,U+76ae,U+76db,U+793c,U+7956,U+7981,U+79d8,U+79df,U+79fb,U+7adf,U+7ae5,U+7b14,U+7b26,U+7b54,U+7b79,U+7d2f,U+7eb8,U+7eba,U+7ec6,U+7ee9,U+7eff,U+7f5a,U+7f6a,U+7f72,U+8089,U+80a5,U+80e1,U+8111,U+8131,U+821e,U+822c,U+8270,U+8499,U+8651,U+867d,U+8840,U+8857,U+8863,U+88c1,U+89c9,U+89d2,U+8a89,U+8bed,U+8bfe,U+8c01,U+8c22,U+8d21,U+8d25,U+8d2f,U+8d5e,U+8d75,U+8d8b,U+8dc3,U+8de8,U+8df5,U+8f6e,U+8f86,U+8f89,U+8fc5,U+8ff0,U+8ffd,U+9014,U+904d,U+90ae,U+9274,U+949f,U+952e,U+969c,U+96c4,U+96e8,U+96f6-96f7,U+97e9,U+987f,U+996d,U+9a7b,U+9aa8,U+9c7c,U+9c9c,U+9e4f,U+9f13,U+9f50\",\n },\n },\n {\n uri: _170,\n descriptors: {\n unicodeRange:\n \"U+4e13,U+4e16,U+4e1c,U+4e24,U+4e3e,U+4e49,U+4e61,U+4e66,U+4e89,U+4e8c,U+4e94,U+4e9b,U+4ea4,U+4eac,U+4ebf,U+4eca,U+4ef6-4ef7,U+4efb,U+4f18,U+4f20,U+4f46,U+4f7f,U+4fe1,U+503c,U+505a,U+5146,U+5148,U+515a,U+5171,U+5177,U+519b,U+51b3,U+51c6,U+51e0,U+5212,U+521b,U+522b,U+529e,U+52bf,U+534e-534f,U+5355,U+5357,U+5382,U+539f,U+53bb,U+53bf,U+53c2,U+53c8,U+53ca,U+53d6-53d8,U+53e3,U+53ea,U+53f0,U+540d,U+5411,U+56db,U+56de,U+56e0,U+56e2,U+578b,U+57ce,U+57fa,U+589e,U+5904,U+5934,U+5982,U+5b89,U+5b8c,U+5bfc,U+5c06,U+5c11,U+5c40,U+5c71,U+5e38,U+5e72,U+5e76,U+5e7f,U+5e94,U+5e9c,U+5f0f,U+5f15,U+5f20,U+5f3a,U+5f62,U+5f88,U+5fc5,U+5fd7,U+5feb,U+601d,U+6027,U+60c5,U+60f3,U+610f,U+6216,U+6218,U+624b,U+624d,U+6279,U+628a,U+6295,U+6301,U+6307,U+636e,U+63a5,U+63a8,U+652f,U+6536,U+653e,U+6548,U+6559,U+6570,U+65bd,U+65e0,U+6602,U+660e,U+6613,U+66f4,U+6700,U+670d,U+671f,U+672f,U+6743,U+674e,U+6751,U+6761,U+6784,U+6797,U+679c,U+67e5,U+6807,U+6837,U+683c,U+6b21,U+6b63-6b65,U+6bcf,U+6bd4,U+6c42,U+6c5f,U+6ca1,U+6cbb,U+6d3b,U+6d41,U+6d88,U+6df1,U+70b9,U+7136,U+7269,U+7279,U+7531,U+754c,U+767e,U+76ca,U+76f8,U+770b,U+7740,U+7814,U+79ef,U+7a0b,U+7a0e,U+7a76,U+7b80,U+7cbe,U+7cfb,U+7e41,U+7ea7,U+7ec4,U+7ec7,U+7ed3,U+7ed9,U+7edf,U+7f8e,U+8001,U+804c,U+8054,U+80b2,U+81f3,U+8425,U+8868,U+88ab,U+897f,U+89c1-89c2,U+89c4,U+89c6,U+89e3,U+8ba1,U+8ba4,U+8bae,U+8bb0,U+8bba,U+8bc1,U+8c03,U+8d28,U+8d39,U+8def,U+8f66,U+8f6c,U+8fd0-8fd1,U+9020,U+9053,U+90a3,U+90fd,U+91cc,U+9500,U+9547,U+95e8,U+95f4,U+961f,U+9645,U+9662,U+96be,U+96c6,U+9700,U+9769,U+97e6,U+9875,U+9879,U+9886,U+9898,U+98ce,U+9996,U+2b5af,U+2cc56,U+2e9f5,U+30edd-30ede\",\n },\n },\n {\n uri: _171,\n descriptors: {\n unicodeRange:\n \"U+4e03,U+4e30,U+4e34,U+4e45,U+4e60,U+4e70,U+4e88,U+4e91-4e92,U+4ea9,U+4eb2,U+4ec0,U+4ecb,U+4ecd,U+4ee4,U+4fee,U+5019,U+5047,U+50cf,U+5145,U+516d,U+5170,U+5175,U+5199,U+51cf,U+51fb,U+521a,U+5224,U+5267,U+52aa,U+5347-5348,U+534a,U+5356,U+5361,U+536b,U+5370,U+538b,U+53e4,U+53e6,U+5403,U+5426,U+5428,U+542c,U+5438,U+5668,U+56ed,U+56f4,U+56fe,U+57df,U+592a,U+5957,U+5b69,U+5b81,U+5b8f,U+5b98,U+5b9d,U+5ba1,U+5ba4,U+5bb3,U+5bc6,U+5bdf,U+5c3d,U+5c5e,U+5c81,U+5ddd,U+5de8,U+5dee,U+5e0c,U+5e86,U+5e8f,U+5e93,U+5e95,U+5e97,U+5ea7,U+5ead,U+5eb7,U+5f55,U+5f81,U+5f85,U+5ff5,U+6001,U+613f,U+6258,U+6267,U+6269,U+626c,U+627e,U+62db,U+62ec,U+6325,U+635f,U+6362,U+6388,U+6392,U+63a2,U+63a7,U+63aa,U+641e,U+6545,U+6597,U+65e2,U+65e9,U+661f,U+665a,U+666e-666f,U+66fe,U+6728,U+67d0,U+6811,U+6838,U+6865,U+697c,U+6b22,U+6b27,U+6b4c,U+6b62,U+6b66,U+6b7b,U+6bdb,U+6c47,U+6c49,U+6c7d,U+6c99,U+6cfd,U+6d0b,U+6d25,U+6d32,U+6d3e,U+6d4b,U+6e29,U+6e56,U+6e7e,U+6f14,U+6fc0,U+706b,U+70c8,U+7247,U+72af,U+72b6,U+72ec,U+732e,U+73ed,U+7403,U+7533,U+753b,U+7559,U+7565,U+7597,U+767b,U+773c,U+7763,U+77ed,U+77ff,U+7968,U+798f,U+79bb,U+79c0-79c1,U+7ad9,U+7ae0,U+7b51,U+7b7e,U+7cae,U+7d22,U+7ea2,U+7eb3,U+7eb7,U+7ec3,U+7ec8,U+7ecd,U+7edd,U+7efc,U+7f16,U+7f3a,U+7f51,U+7f57,U+7f6e,U+80dc,U+822a,U+8239,U+826f,U+82cf,U+82e6,U+8349,U+8363,U+83dc,U+8457,U+85cf,U+878d,U+8865,U+8a00,U+8b66,U+8ba2,U+8ba8,U+8bad,U+8bb2,U+8bc9,U+8bd5,U+8bfb,U+8d2b,U+8d35,U+8d37,U+8f7b,U+8f93,U+8fce,U+8fdd,U+9000-9002,U+9010,U+9047,U+9093,U+9152,U+9488,U+94a2,U+9633,U+9636,U+963f,U+9646,U+9648,U+964d,U+9664,U+9669,U+9760,U+97f3,U+987a,U+987e,U+9884,U+98de,U+9986,U+9ed1\",\n },\n },\n {\n uri: _172,\n descriptors: {\n unicodeRange:\n \"U+4e14,U+4e25,U+4e48,U+4e50,U+4e5d,U+4e9a,U+4ec5,U+4efd,U+4f17,U+4f4e-4f4f,U+4f55,U+4f59,U+4f60,U+4f8b,U+4f9b,U+4f9d,U+4fbf,U+4fc3,U+5065,U+513f,U+5149,U+514b,U+516b,U+5174,U+517b,U+518d,U+51b5,U+5207,U+5217-5219,U+521d,U+526f,U+529f,U+52a9,U+52b3,U+5305,U+533b,U+5343,U+5360,U+5373-5374,U+5386,U+53cb-53cd,U+53f2,U+53f7,U+544a,U+5468,U+547d,U+54cd,U+552e,U+5584,U+56f0,U+571f,U+5747,U+575a,U+57f9,U+5883,U+58eb,U+58f0,U+5907,U+590d,U+592e,U+5931,U+5956,U+5965,U+5973,U+5979,U+59cb,U+5b57-5b58,U+5b83,U+5ba2-5ba3,U+5bb9,U+5bcc,U+5c42,U+5c45,U+5c4a,U+5dde,U+5df1,U+5df4,U+5e03,U+5e08,U+5e26,U+5e2d,U+5f71,U+5f80,U+5f8b,U+5fb7,U+606f,U+611f,U+6237,U+623f,U+6253,U+627f,U+6293,U+62a4,U+62c5,U+62c9,U+6309,U+6574,U+6599,U+65ad,U+65af,U+65c5,U+65cf,U+6625,U+663e,U+671b,U+672a,U+6750,U+6781,U+6821,U+6839,U+6848,U+68c0,U+6a21,U+6b3e,U+6bb5,U+6c14,U+6cb3,U+6cb9,U+6ce8,U+6e05,U+6e2f,U+6e38,U+6e90,U+6ee1,U+70ed,U+7167,U+7231,U+7248,U+724c,U+7387,U+738b,U+73af,U+7530,U+75c5,U+767d,U+76d1,U+76f4,U+771f,U+77e5,U+77f3,U+7834,U+7840,U+786e,U+793a,U+795e,U+79f0,U+7a33,U+7a7a,U+7a81,U+7ade,U+7b56,U+7b97,U+7c73,U+7c7b,U+7d20,U+7d27,U+7ea6,U+7eaa,U+7ebf,U+7ee7,U+7eed,U+7ef4,U+7fa4,U+8003,U+80a1,U+81f4,U+8272,U+827a,U+8282,U+82b1,U+82f1,U+8303,U+836f,U+83b7,U+843d,U+88c5,U+8ba9,U+8baf,U+8bb8,U+8bbf,U+8bc4,U+8bc6,U+8bdd,U+8be5,U+8bf7,U+8c08,U+8c61,U+8d1f,U+8d22-8d23,U+8d27,U+8d2d,U+8d38,U+8d5b,U+8d70,U+8d85,U+8d8a,U+8db3,U+8eab,U+8f83,U+8fb9,U+8fdc,U+8fde,U+9009,U+901f,U+914d,U+91c7,U+94b1,U+94c1,U+94f6,U+95fb,U+9632,U+9650,U+968f,U+9752,U+975e,U+987b,U+989d,U+98df,U+9999,U+9a6c,U+9a8c,U+9ec4,U+9feb-9fec\",\n },\n },\n {\n uri: _173,\n descriptors: {\n unicodeRange:\n \"U+98fb-990c,U+990e-990f,U+9911-992d,U+992f-9953,U+9956-9962,U+9964,U+9966,U+9973,U+9978-9979,U+997b,U+997e,U+9982-9983,U+9989,U+998c,U+998e,U+999a-99a4,U+99a6-99a7,U+99a9-99c8\",\n },\n },\n {\n uri: _174,\n descriptors: {\n unicodeRange:\n \"U+8e4c-8e50,U+8e53-8e58,U+8e5a-8e65,U+8e67-8e68,U+8e6a-8e6b,U+8e6e,U+8e71,U+8e73,U+8e75,U+8e77-8e7b,U+8e7d-8e7e,U+8e80,U+8e82-8e84,U+8e86,U+8e88-8e8e,U+8e91-8e93,U+8e95-8e9b,U+8e9d,U+8e9f-8eaa,U+8ead-8eae,U+8eb0-8eb1,U+8eb3-8eb9,U+8ebb-8ecd,U+8ecf-8f02\",\n },\n },\n {\n uri: _175,\n descriptors: {\n unicodeRange:\n \"U+2e3a,U+3001-3002,U+3008-3011,U+3014-3017,U+301d-301f,U+4dae,U+4e00,U+4e07,U+4e09-4e0b,U+4e0d-4e0e,U+4e1a,U+4e2a,U+4e2d,U+4e3a-4e3b,U+4e4b,U+4e5f,U+4e86,U+4e8b,U+4e8e,U+4ea7,U+4eba,U+4ece,U+4ed1,U+4ed6,U+4ee3,U+4ee5,U+4eec,U+4f01,U+4f1a,U+4f4d,U+4f53,U+4f5c,U+4fdd,U+5143,U+5165,U+5168,U+516c,U+5173,U+5176,U+5185,U+519c,U+51fa,U+5206,U+5229,U+5230,U+5236,U+524d,U+529b,U+52a0-52a1,U+52a8,U+5316-5317,U+533a,U+5341,U+5362,U+53d1,U+53ef,U+53f8,U+5404,U+5408,U+540c,U+540e,U+5458,U+548c,U+54c1,U+54e5,U+5546,U+559c,U+56fd,U+5728,U+5730,U+573a,U+5916,U+591a,U+5927,U+5929,U+592b,U+597d,U+59d4,U+5b50,U+5b66,U+5b9a,U+5b9e,U+5bb6,U+5bf9,U+5c0f,U+5c14,U+5c31,U+5c55,U+5de5,U+5df2,U+5e02,U+5e73-5e74,U+5ea6,U+5efa,U+5f00,U+5f53,U+5f97,U+5fc3,U+603b,U+6210-6211,U+6240,U+6280,U+62a5,U+63d0,U+6539,U+653f,U+6587,U+65b0,U+65b9,U+65e5,U+65f6,U+662f,U+6708-6709,U+672c,U+673a,U+675c,U+6765,U+6c11,U+6c34,U+6cd5,U+6ce2,U+6d4e,U+6d77,U+73b0,U+7406,U+751f,U+7528,U+7535,U+7684,U+76ee,U+793e,U+79cd,U+79d1,U+7acb,U+7b2c,U+7b49,U+7ba1,U+7ecf,U+8005,U+800c,U+80fd,U+81ea,U+884c,U+8981,U+8bbe,U+8bf4,U+8d44,U+8d77,U+8fbe,U+8fc7,U+8fd8-8fd9,U+8fdb,U+901a,U+90e8,U+91cd,U+91cf,U+91d1,U+9485,U+957f,U+95ee,U+9762,U+9ad8,U+9ea6,U+9f99,U+9fcf,U+9fd4,U+9fed,U+fe10-fe19,U+fe30-fe31,U+fe33-fe44,U+ff01,U+ff0c,U+ff1f,U+2b4e7,U+2b7f7,U+2b7fc,U+2cb2d,U+2cb3b,U+2cb4a,U+2cb5b,U+2cb73\",\n },\n },\n {\n uri: _176,\n descriptors: {\n unicodeRange:\n \"U+6490,U+6493-6494,U+6497-6498,U+649a-649d,U+649f-64a3,U+64a5-64a8,U+64aa-64ab,U+64af,U+64b1-64b4,U+64b6,U+64b9,U+64bb,U+64bd-64bf,U+64c1,U+64c3-64c4,U+64c6-64cc,U+64cf,U+64d1,U+64d3-64d6,U+64d9-64dd,U+64df-64e1,U+64e3,U+64e5,U+64e7-64ff,U+6501-6508,U+650a-6511,U+6513-6517,U+6519-6524,U+6526-652a,U+652c-652d,U+6530-6533,U+6537,U+653a,U+653c-653d,U+6540-6544,U+6546-6547,U+654a-654b,U+654d-654e,U+6550,U+6552-6554,U+6557-6558,U+655a,U+655c,U+655f-6561,U+6564-6565,U+6567-6568\",\n },\n },\n {\n uri: _177,\n descriptors: {\n unicodeRange:\n \"U+9695-9696,U+969a-969b,U+969d-96a6,U+96a8-96af,U+96b1-96b2,U+96b4-96b5,U+96b7-96b8,U+96ba-96bb,U+96bf,U+96c2-96c3,U+96c8,U+96ca-96cb,U+96d0-96d1,U+96d3-96d4,U+96d6-96df,U+96e1-96e7,U+96eb-96ee,U+96f0-96f2,U+96f4-96f5,U+96f8,U+96fa-96fd,U+96ff,U+9702-9703,U+9705,U+970a-970c,U+9710-9712,U+9714-9715,U+9717-971b,U+971d,U+971f-9729,U+972b-972c,U+972e-972f,U+9731,U+9733-9737,U+973a-973d,U+973f-9751,U+9754-9755,U+9757-9758,U+975a,U+975c-975d,U+975f,U+9763-9764,U+9766-9768,U+976a-9770\",\n },\n },\n {\n uri: _178,\n descriptors: {\n unicodeRange:\n \"U+6af0-6b1f,U+6b25-6b26,U+6b28-6b31,U+6b33-6b36,U+6b38,U+6b3b-6b3d,U+6b3f-6b42,U+6b44-6b45,U+6b48,U+6b4a-6b4b,U+6b4d-6b58,U+6b5a-6b61,U+6b68-6b69,U+6b6b-6b78,U+6b7a,U+6b7d-6b80,U+6b85,U+6b88,U+6b8c,U+6b8e-6b91,U+6b94-6b95,U+6b97-6b99,U+6b9c-6ba0,U+6ba2-6ba9,U+6bab-6bb2,U+6bb6,U+6bb8-6bba\",\n },\n },\n {\n uri: _179,\n descriptors: {\n unicodeRange:\n \"U+430e-439a,U+29e8a,U+29ec4,U+29edb,U+29ee9,U+29f7e,U+29f83,U+29f8c,U+29fce,U+2a01a,U+2a02f,U+2a082,U+2a0f9,U+2a190,U+2a38c\",\n },\n },\n {\n uri: _180,\n descriptors: { unicodeRange: \"U+92ef-933d,U+933f-9369,U+936b-9388\" },\n },\n {\n uri: _181,\n descriptors: {\n unicodeRange:\n \"U+4512-458d,U+2b300,U+2b363,U+2b36f,U+2b372,U+2b37d,U+2b404,U+2b410,U+2b413,U+2b461,U+2b4ef,U+2b4f6,U+2b4f9,U+2b50d-2b50e,U+2b536,U+2b5ae,U+2b5b3,U+2b5e7,U+2b5f4,U+2b61c-2b61d,U+2b626-2b628,U+2b62a,U+2b62c,U+2b695-2b696,U+2b6ad,U+2b6ed\",\n },\n },\n {\n uri: _182,\n descriptors: {\n unicodeRange:\n \"U+88bd-88c0,U+88c3-88c4,U+88c7-88c8,U+88ca-88cd,U+88cf-88d1,U+88d3,U+88d6-88d7,U+88da-88de,U+88e0-88e1,U+88e6-88e7,U+88e9-88ef,U+88f2,U+88f5-88f7,U+88fa-88fb,U+88fd,U+88ff-8901,U+8903-8909,U+890b-890f,U+8911,U+8914-8918,U+891c-8920,U+8922-8924,U+8926-8929,U+892c-892f,U+8931-8933,U+8935,U+8937-8940,U+8942-8943,U+8945-895d,U+8960-8965,U+8967-897a,U+897c-897e,U+8980,U+8982,U+8984-8985\",\n },\n },\n { uri: _183, descriptors: { unicodeRange: \"U+4b0b-4ba0\" } },\n {\n uri: _184,\n descriptors: {\n unicodeRange:\n \"U+7179,U+717b-717c,U+717e-7183,U+7185-7189,U+718b-718e,U+7190-7193,U+7195-7197,U+719a-719e,U+71a1-71a7,U+71a9-71ab,U+71ad-71b2,U+71b4,U+71b6-71b8,U+71ba-71c2,U+71c4-71cd,U+71cf-71d3,U+71d6-71df,U+71e1-71e4,U+71e6,U+71e8-71ed,U+71ef-71f8,U+71fa-7205,U+7207-721c,U+721e-7227,U+7229,U+722b,U+722d\",\n },\n },\n {\n uri: _185,\n descriptors: {\n unicodeRange:\n \"U+982e-9874,U+988b,U+988e,U+9892,U+9895,U+9899,U+98a3,U+98a8-98cd,U+98cf-98d0,U+98d4,U+98d6-98d7,U+98db-98dd,U+98e0-98e6,U+98e9-98fa\",\n },\n },\n {\n uri: _186,\n descriptors: {\n unicodeRange:\n \"U+7c14-7c15,U+7c17-7c1e,U+7c20-7c25,U+7c28-7c29,U+7c2b-7c37,U+7c39-7c3e,U+7c42-7c4c,U+7c4e-7c72,U+7c75-7c7a,U+7c7e-7c88,U+7c8a-7c90,U+7c93-7c94,U+7c96,U+7c99-7c9b,U+7ca0-7ca1,U+7ca3,U+7ca6-7ca9,U+7cab-7cad,U+7caf-7cb0,U+7cb4-7cb8,U+7cba-7cbb,U+7cbf-7cc0,U+7cc2-7cc4,U+7cc6,U+7cc9,U+7ccb,U+7cce-7cd4\",\n },\n },\n {\n uri: _187,\n descriptors: { unicodeRange: \"U+7d95-7da5,U+7da7-7dad,U+7daf-7e2a\" },\n },\n { uri: _188, descriptors: { unicodeRange: \"U+4a78-4b0a\" } },\n {\n uri: _189,\n descriptors: {\n unicodeRange:\n \"U+9b30-9b31,U+9b33-9b3a,U+9b3d-9b40,U+9b46,U+9b4a-9b4c,U+9b4e,U+9b50,U+9b52-9b53,U+9b55-9bcf\",\n },\n },\n {\n uri: _190,\n descriptors: {\n unicodeRange:\n \"U+6a4b-6a4f,U+6a51-6a57,U+6a5a,U+6a5c-6a60,U+6a62-6a64,U+6a66-6a70,U+6a72-6a78,U+6a7a-6a7b,U+6a7d-6a7f,U+6a81-6a83,U+6a85-6a8d,U+6a8f,U+6a92-6a96,U+6a98-6a9f,U+6aa1-6aa8,U+6aaa,U+6aad-6aef\",\n },\n },\n { uri: _191, descriptors: { unicodeRange: \"U+99c9-9a53\" } },\n {\n uri: _192,\n descriptors: {\n unicodeRange:\n \"U+8550-8555,U+8557-8558,U+855a-855d,U+855f-8563,U+8565-8567,U+8569-8571,U+8573,U+8575-8578,U+857c-857d,U+857f-8583,U+8586,U+8588-858e,U+8590-859a,U+859d-85a3,U+85a5-85a7,U+85a9,U+85ab-85ad,U+85b1-85b6,U+85b8,U+85ba-85c0,U+85c2-85c8,U+85ca-85ce,U+85d1-85d2,U+85d4,U+85d6-85db,U+85dd-85e3,U+85e5-85e8,U+85ea-85fa,U+85fc-85fe,U+8600-8603\",\n },\n },\n {\n uri: _193,\n descriptors: {\n unicodeRange:\n \"U+6fb2,U+6fb4-6fb5,U+6fb7-6fb8,U+6fba-6fbf,U+6fc1,U+6fc3-6fc8,U+6fca-6fd0,U+6fd3-6fdd,U+6fdf,U+6fe2-6fed,U+6ff0-7010,U+7012-7019,U+701c-7022,U+7024-7034,U+7036-7038,U+703a-704b,U+704d-704e,U+7050-7053\",\n },\n },\n { uri: _194, descriptors: { unicodeRange: \"U+4ba1-4c2c\" } },\n {\n uri: _195,\n descriptors: {\n unicodeRange:\n \"U+9a54-9a6b,U+9a72,U+9a83,U+9a89,U+9a8d-9a8e,U+9a94-9a95,U+9a99,U+9aa6,U+9aa9-9aaf,U+9ab2-9ab5,U+9ab9,U+9abb,U+9abd-9abf,U+9ac3-9ac4,U+9ac6-9aca,U+9acd-9ad0,U+9ad2,U+9ad4-9ad7,U+9ad9-9ade,U+9ae0,U+9ae2-9ae5,U+9ae7-9aea,U+9aec,U+9aee,U+9af0-9af8,U+9afa,U+9afc-9b02,U+9b04-9b07,U+9b09-9b0e,U+9b10-9b12,U+9b14-9b1e,U+9b20-9b22,U+9b24-9b2e\",\n },\n },\n { uri: _196, descriptors: { unicodeRange: \"U+9d1a-9da1\" } },\n {\n uri: _197,\n descriptors: {\n unicodeRange:\n \"U+9e13-9e1e,U+9e24,U+9e27,U+9e2e,U+9e30,U+9e34,U+9e3b-9e3c,U+9e40,U+9e4d,U+9e50,U+9e52-9e54,U+9e56,U+9e59,U+9e5d,U+9e5f-9e62,U+9e65,U+9e6e-9e6f,U+9e72,U+9e74-9e7d,U+9e80-9e81,U+9e83-9e86,U+9e89-9e8a,U+9e8c-9e91,U+9e94-9e9c,U+9e9e,U+9ea0-9ea5,U+9ea7-9eb3,U+9eb5-9eb7,U+9eb9-9eba,U+9ebc,U+9ebf-9ec3,U+9ec5-9ec8,U+9eca-9ecc,U+9ed0,U+9ed2-9ed3,U+9ed5-9ed7,U+9ed9-9eda,U+9ede,U+9ee1,U+9ee3-9ee4,U+9ee6,U+9ee8,U+9eeb-9eee,U+9ef0-9ef8\",\n },\n },\n {\n uri: _198,\n descriptors: {\n unicodeRange:\n \"U+8b1c-8b25,U+8b27-8b65,U+8b67-8b6b,U+8b6d-8b9f,U+8bac,U+8bb1,U+8bbb,U+8bc7,U+8bd0\",\n },\n },\n { uri: _199, descriptors: { unicodeRange: \"U+4cad-4d2f\" } },\n {\n uri: _200,\n descriptors: {\n unicodeRange:\n \"U+9c4b-9c7b,U+9c7d-9c7e,U+9c80,U+9c83-9c84,U+9c89-9c8a,U+9c8c,U+9c8f,U+9c93,U+9c96-9c99,U+9c9d,U+9caa,U+9cac,U+9caf,U+9cb9,U+9cbe-9cc2,U+9cc8-9cc9,U+9cd1-9cd2,U+9cda-9cdb,U+9ce0-9ce1,U+9ce3-9d19\",\n },\n },\n {\n uri: _201,\n descriptors: {\n unicodeRange: \"U+9389-938e,U+9390-93c9,U+93cb-93d5,U+93d7-9410\",\n },\n },\n {\n uri: _202,\n descriptors: {\n unicodeRange:\n \"U+20a0-20b5,U+20b9-20ba,U+20bc-20bd,U+4e2c,U+5107,U+5216,U+5293,U+54f3,U+5523,U+5819,U+5adc,U+5c88,U+5e3b,U+5fee,U+62f6,U+63be,U+6484,U+6499,U+67d9,U+67dd,U+6d5e,U+6f46,U+717a,U+71e0,U+72c1,U+73e7,U+75b0,U+7603,U+7722,U+7809,U+7811,U+7946,U+7967,U+799a,U+7b45,U+7ba2,U+8014,U+80d9,U+8159,U+817d,U+81a3,U+81aa,U+8201,U+833c,U+836e,U+83e5,U+8459,U+84f0,U+8729,U+8753,U+87d3,U+89dc,U+8bf6,U+8c2e,U+8e2c,U+8e9c,U+8e9e,U+8ece,U+8fee,U+9139,U+914f,U+9174,U+9191,U+960c,U+9622,U+9a98,U+9b48,U+9ca6,U+9cb0,U+9da2-9e12,U+9e88,U+9f44,U+9f86\",\n },\n },\n { uri: _203, descriptors: { unicodeRange: \"U+9bd0-9c4a\" } },\n { uri: _204, descriptors: { unicodeRange: \"U+4c2d-4cac\" } },\n { uri: _205, descriptors: { unicodeRange: \"U+4d30-4dab\" } },\n {\n uri: _206,\n descriptors: { unicodeRange: \"U+9411-943d,U+943f-946a,U+946c-9484\" },\n },\n {\n uri: _207,\n descriptors: {\n unicodeRange:\n \"U+9efa,U+9efd,U+9eff-9f0a,U+9f0c,U+9f0f,U+9f11-9f12,U+9f14-9f16,U+9f18,U+9f1a-9f1f,U+9f21,U+9f23-9f2b,U+9f2d-9f2e,U+9f30-9f36,U+9f38,U+9f3a,U+9f3c,U+9f3f-9f43,U+9f45-9f4f,U+9f52-9f7e,U+9f81-9f82,U+9f8d-9f94\",\n },\n },\n {\n uri: _208,\n descriptors: {\n unicodeRange:\n \"U+7e2b-7e3a,U+7e3c-7e40,U+7e42-7e46,U+7e48-7e81,U+7e83-7e9a,U+7e9c-7e9e,U+7eae,U+7eb4,U+7ebb-7ebc,U+7ed6,U+7ee4,U+7eec,U+7ef9,U+7f0a,U+7f10,U+7f1e,U+7f37,U+7f39,U+7f3b\",\n },\n },\n];\n", "import {\n FONT_FAMILY,\n FONT_FAMILY_FALLBACKS,\n CJK_HAND_DRAWN_FALLBACK_FONT,\n WINDOWS_EMOJI_FALLBACK_FONT,\n getFontFamilyFallbacks,\n FONT_SIZES,\n} from \"@excalidraw/common\";\nimport { getContainerElement } from \"@excalidraw/element\";\nimport { charWidth } from \"@excalidraw/element\";\nimport { containsCJK } from \"@excalidraw/element\";\n\nimport {\n FONT_METADATA,\n type FontMetadata,\n getFontString,\n PromisePool,\n promiseTry,\n} from \"@excalidraw/common\";\n\nimport { ShapeCache } from \"@excalidraw/element\";\n\nimport { isTextElement } from \"@excalidraw/element\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawTextElement,\n} from \"@excalidraw/element/types\";\n\nimport type { ValueOf } from \"@excalidraw/common/utility-types\";\n\nimport type { Scene } from \"@excalidraw/element\";\n\nimport { CascadiaFontFaces } from \"./Cascadia\";\nimport { ComicShannsFontFaces } from \"./ComicShanns\";\nimport { EmojiFontFaces } from \"./Emoji\";\nimport { ExcalidrawFontFace } from \"./ExcalidrawFontFace\";\nimport { ExcalifontFontFaces } from \"./Excalifont\";\nimport { HelveticaFontFaces } from \"./Helvetica\";\nimport { LiberationFontFaces } from \"./Liberation\";\nimport { LilitaFontFaces } from \"./Lilita\";\nimport { NunitoFontFaces } from \"./Nunito\";\nimport { VirgilFontFaces } from \"./Virgil\";\nimport { XiaolaiFontFaces } from \"./Xiaolai\";\n\nexport class Fonts {\n // it's ok to track fonts across multiple instances only once, so let's use\n // a static member to reduce memory footprint\n public static readonly loadedFontsCache = new Set<string>();\n\n private static _registered:\n | Map<\n number,\n {\n metadata: FontMetadata;\n fontFaces: ExcalidrawFontFace[];\n }\n >\n | undefined;\n\n private static _initialized: boolean = false;\n\n public static get registered() {\n // lazy load the font registration\n if (!Fonts._registered) {\n Fonts._registered = Fonts.init();\n } else if (!Fonts._initialized) {\n // case when host app register fonts before they are lazy loaded\n // don't override whatever has been previously registered\n Fonts._registered = new Map([\n ...Fonts.init().entries(),\n ...Fonts._registered.entries(),\n ]);\n }\n\n return Fonts._registered;\n }\n\n public get registered() {\n return Fonts.registered;\n }\n\n private readonly scene: Scene;\n\n constructor(scene: Scene) {\n this.scene = scene;\n }\n\n /**\n * Get all the font families for the given scene.\n */\n public getSceneFamilies = () => {\n return Fonts.getUniqueFamilies(this.scene.getNonDeletedElements());\n };\n\n /**\n * if we load a (new) font, it's likely that text elements using it have\n * already been rendered using a fallback font. Thus, we want invalidate\n * their shapes and rerender. See #637.\n *\n * Invalidates text elements and rerenders scene, provided that at least one\n * of the supplied fontFaces has not already been processed.\n */\n public onLoaded = (fontFaces: readonly FontFace[]): void => {\n // bail if all fonts with have been processed. We're checking just a\n // subset of the font properties (though it should be enough), so it\n // can technically bail on a false positive.\n let shouldBail = true;\n\n for (const fontFace of fontFaces) {\n const sig = `${fontFace.family}-${fontFace.style}-${fontFace.weight}-${fontFace.unicodeRange}`;\n\n // make sure to update our cache with all the loaded font faces\n if (!Fonts.loadedFontsCache.has(sig)) {\n Fonts.loadedFontsCache.add(sig);\n shouldBail = false;\n }\n }\n\n if (shouldBail) {\n return;\n }\n\n let didUpdate = false;\n\n const elementsMap = this.scene.getNonDeletedElementsMap();\n\n for (const element of this.scene.getNonDeletedElements()) {\n if (isTextElement(element)) {\n didUpdate = true;\n ShapeCache.delete(element);\n\n // clear the width cache, so that we don't perform subsequent wrapping based on the stale fallback font metrics\n charWidth.clearCache(getFontString(element));\n\n const container = getContainerElement(element, elementsMap);\n if (container) {\n ShapeCache.delete(container);\n }\n }\n }\n\n if (didUpdate) {\n this.scene.triggerUpdate();\n }\n };\n\n /**\n * Load font faces for a given scene and trigger scene update.\n */\n public loadSceneFonts = async (): Promise<FontFace[]> => {\n const sceneFamilies = this.getSceneFamilies();\n const charsPerFamily = Fonts.getCharsPerFamily(\n this.scene.getNonDeletedElements(),\n );\n\n return Fonts.loadFontFaces(sceneFamilies, charsPerFamily);\n };\n\n /**\n * Load font faces for passed elements - use when the scene is unavailable (i.e. export).\n */\n public static loadElementsFonts = async (\n elements: readonly ExcalidrawElement[],\n ): Promise<FontFace[]> => {\n const fontFamilies = Fonts.getUniqueFamilies(elements);\n const charsPerFamily = Fonts.getCharsPerFamily(elements);\n\n return Fonts.loadFontFaces(fontFamilies, charsPerFamily);\n };\n\n /**\n * Generate CSS @font-face declarations for the given elements.\n */\n public static async generateFontFaceDeclarations(\n elements: readonly ExcalidrawElement[],\n ) {\n const families = Fonts.getUniqueFamilies(elements);\n const charsPerFamily = Fonts.getCharsPerFamily(elements);\n\n // for simplicity, assuming we have just one family with the CJK handdrawn fallback\n const familyWithCJK = families.find((x) =>\n getFontFamilyFallbacks(x).includes(CJK_HAND_DRAWN_FALLBACK_FONT),\n );\n\n if (familyWithCJK) {\n const characters = Fonts.getCharacters(charsPerFamily, familyWithCJK);\n\n if (containsCJK(characters)) {\n const family = FONT_FAMILY_FALLBACKS[CJK_HAND_DRAWN_FALLBACK_FONT];\n\n // adding the same characters to the CJK handrawn family\n charsPerFamily[family] = new Set(characters);\n\n // the order between the families and fallbacks is important, as fallbacks need to be defined first and in the reversed order\n // so that they get overriden with the later defined font faces, i.e. in case they share some codepoints\n families.unshift(FONT_FAMILY_FALLBACKS[CJK_HAND_DRAWN_FALLBACK_FONT]);\n }\n }\n\n // don't trigger hundreds of concurrent requests (each performing fetch, creating a worker, etc.),\n // instead go three requests at a time, in a controlled manner, without completely blocking the main thread\n // and avoiding potential issues such as rate limits\n const iterator = Fonts.fontFacesStylesGenerator(families, charsPerFamily);\n const concurrency = 3;\n const fontFaces = await new PromisePool(iterator, concurrency).all();\n\n // dedup just in case (i.e. could be the same font faces with 0 glyphs)\n return Array.from(new Set(fontFaces));\n }\n\n private static async loadFontFaces(\n fontFamilies: Array<ExcalidrawTextElement[\"fontFamily\"]>,\n charsPerFamily: Record<number, Set<string>>,\n ) {\n // add all registered font faces into the `document.fonts` (if not added already)\n for (const { fontFaces, metadata } of Fonts.registered.values()) {\n // skip registering font faces for local fonts (i.e. Helvetica)\n if (metadata.local) {\n continue;\n }\n\n for (const { fontFace } of fontFaces) {\n if (!window.document.fonts.has(fontFace)) {\n window.document.fonts.add(fontFace);\n }\n }\n }\n\n // loading 10 font faces at a time, in a controlled manner\n const iterator = Fonts.fontFacesLoader(fontFamilies, charsPerFamily);\n const concurrency = 10;\n const fontFaces = await new PromisePool(iterator, concurrency).all();\n return fontFaces.flat().filter(Boolean);\n }\n\n private static *fontFacesLoader(\n fontFamilies: Array<ExcalidrawTextElement[\"fontFamily\"]>,\n charsPerFamily: Record<number, Set<string>>,\n ): Generator<Promise<void | readonly [number, FontFace[]]>> {\n for (const [index, fontFamily] of fontFamilies.entries()) {\n const font = getFontString({\n fontFamily,\n fontSize: FONT_SIZES.sm,\n });\n\n // WARN: without \"text\" param it does not have to mean that all font faces are loaded as it could be just one irrelevant font face!\n // instead, we are always checking chars used in the family, so that no required font faces remain unloaded\n const text = Fonts.getCharacters(charsPerFamily, fontFamily);\n\n if (!window.document.fonts.check(font, text)) {\n yield promiseTry(async () => {\n try {\n // WARN: browser prioritizes loading only font faces with unicode ranges for characters which are present in the document (html & canvas), other font faces could stay unloaded\n // we might want to retry here, i.e. in case CDN is down, but so far I didn't experience any issues - maybe it handles retry-like logic under the hood\n const fontFaces = await window.document.fonts.load(font, text);\n\n return [index, fontFaces];\n } catch (e) {\n // don't let it all fail if just one font fails to load\n console.error(\n `Failed to load font \"${font}\" from urls \"${Fonts.registered\n .get(fontFamily)\n ?.fontFaces.map((x) => x.urls)}\"`,\n e,\n );\n }\n });\n }\n }\n }\n\n private static *fontFacesStylesGenerator(\n families: Array<number>,\n charsPerFamily: Record<number, Set<string>>,\n ): Generator<Promise<void | readonly [number, string]>> {\n for (const [familyIndex, family] of families.entries()) {\n const { fontFaces, metadata } = Fonts.registered.get(family) ?? {};\n\n if (!Array.isArray(fontFaces)) {\n console.error(\n `Couldn't find registered fonts for font-family \"${family}\"`,\n Fonts.registered,\n );\n continue;\n }\n\n if (metadata?.local) {\n // don't inline local fonts\n continue;\n }\n\n for (const [fontFaceIndex, fontFace] of fontFaces.entries()) {\n yield promiseTry(async () => {\n try {\n const characters = Fonts.getCharacters(charsPerFamily, family);\n const fontFaceCSS = await fontFace.toCSS(characters);\n\n if (!fontFaceCSS) {\n return;\n }\n\n // giving a buffer of 10K font faces per family\n const fontFaceOrder = familyIndex * 10_000 + fontFaceIndex;\n const fontFaceTuple = [fontFaceOrder, fontFaceCSS] as const;\n\n return fontFaceTuple;\n } catch (error) {\n console.error(\n `Couldn't transform font-face to css for family \"${fontFace.fontFace.family}\"`,\n error,\n );\n }\n });\n }\n }\n }\n\n /**\n * Register a new font.\n *\n * @param family font family\n * @param metadata font metadata\n * @param fontFacesDecriptors font faces descriptors\n */\n private static register(\n this:\n | Fonts\n | {\n registered: Map<\n number,\n { metadata: FontMetadata; fontFaces: ExcalidrawFontFace[] }\n >;\n },\n family: string,\n metadata: FontMetadata,\n ...fontFacesDecriptors: ExcalidrawFontFaceDescriptor[]\n ) {\n // TODO: likely we will need to abandon number value in order to support custom fonts\n const fontFamily =\n FONT_FAMILY[family as keyof typeof FONT_FAMILY] ??\n FONT_FAMILY_FALLBACKS[family as keyof typeof FONT_FAMILY_FALLBACKS];\n\n const registeredFamily = this.registered.get(fontFamily);\n\n if (!registeredFamily) {\n this.registered.set(fontFamily, {\n metadata,\n fontFaces: fontFacesDecriptors.map(\n ({ uri, descriptors }) =>\n new ExcalidrawFontFace(family, uri, descriptors),\n ),\n });\n }\n\n return this.registered;\n }\n\n /**\n * WARN: should be called just once on init, even across multiple instances.\n */\n private static init() {\n const fonts = {\n registered: new Map<\n ValueOf<typeof FONT_FAMILY | typeof FONT_FAMILY_FALLBACKS>,\n { metadata: FontMetadata; fontFaces: ExcalidrawFontFace[] }\n >(),\n };\n\n const init = (\n family: keyof typeof FONT_FAMILY | keyof typeof FONT_FAMILY_FALLBACKS,\n ...fontFacesDescriptors: ExcalidrawFontFaceDescriptor[]\n ) => {\n const fontFamily =\n FONT_FAMILY[family as keyof typeof FONT_FAMILY] ??\n FONT_FAMILY_FALLBACKS[family as keyof typeof FONT_FAMILY_FALLBACKS];\n\n // default to Excalifont metrics\n const metadata =\n FONT_METADATA[fontFamily] ?? FONT_METADATA[FONT_FAMILY.Excalifont];\n\n Fonts.register.call(fonts, family, metadata, ...fontFacesDescriptors);\n };\n\n init(\"Cascadia\", ...CascadiaFontFaces);\n init(\"Comic Shanns\", ...ComicShannsFontFaces);\n init(\"Excalifont\", ...ExcalifontFontFaces);\n // keeping for backwards compatibility reasons, uses system font (Helvetica on MacOS, Arial on Win)\n init(\"Helvetica\", ...HelveticaFontFaces);\n // used for server-side pdf & png export instead of helvetica (technically does not need metrics, but kept in for consistency)\n init(\"Liberation Sans\", ...LiberationFontFaces);\n init(\"Lilita One\", ...LilitaFontFaces);\n init(\"Nunito\", ...NunitoFontFaces);\n init(\"Virgil\", ...VirgilFontFaces);\n\n // fallback font faces\n init(CJK_HAND_DRAWN_FALLBACK_FONT, ...XiaolaiFontFaces);\n init(WINDOWS_EMOJI_FALLBACK_FONT, ...EmojiFontFaces);\n\n Fonts._initialized = true;\n\n return fonts.registered;\n }\n\n /**\n * Get all the unique font families for the given elements.\n */\n private static getUniqueFamilies(\n elements: ReadonlyArray<ExcalidrawElement>,\n ): Array<ExcalidrawTextElement[\"fontFamily\"]> {\n return Array.from(\n elements.reduce((families, element) => {\n if (isTextElement(element)) {\n families.add(element.fontFamily);\n }\n return families;\n }, new Set<number>()),\n );\n }\n\n /**\n * Get all the unique characters per font family for the given scene.\n */\n private static getCharsPerFamily(\n elements: ReadonlyArray<ExcalidrawElement>,\n ): Record<number, Set<string>> {\n const charsPerFamily: Record<number, Set<string>> = {};\n\n for (const element of elements) {\n if (!isTextElement(element)) {\n continue;\n }\n\n // gather unique codepoints only when inlining fonts\n for (const char of element.originalText) {\n if (!charsPerFamily[element.fontFamily]) {\n charsPerFamily[element.fontFamily] = new Set();\n }\n\n charsPerFamily[element.fontFamily].add(char);\n }\n }\n\n return charsPerFamily;\n }\n\n /**\n * Get characters for a given family.\n */\n private static getCharacters(\n charsPerFamily: Record<number, Set<string>>,\n family: number,\n ) {\n return charsPerFamily[family]\n ? Array.from(charsPerFamily[family]).join(\"\")\n : \"\";\n }\n\n /**\n * Get all registered font families.\n */\n private static getAllFamilies() {\n return Array.from(Fonts.registered.keys());\n }\n}\n\nexport interface ExcalidrawFontFaceDescriptor {\n uri: string;\n descriptors?: FontFaceDescriptors;\n}\n", "import { pointFrom, pointRotateRads } from \"@excalidraw/math\";\n\nimport { MIME_TYPES } from \"@excalidraw/common\";\nimport { getElementAbsoluteCoords } from \"@excalidraw/element\";\nimport { hitElementBoundingBox } from \"@excalidraw/element\";\n\nimport type { GlobalPoint, Radians } from \"@excalidraw/math\";\n\nimport type { Bounds } from \"@excalidraw/common\";\nimport type {\n ElementsMap,\n NonDeletedExcalidrawElement,\n} from \"@excalidraw/element/types\";\n\nimport type { AppState, UIAppState } from \"../../types\";\n\nexport const DEFAULT_LINK_SIZE = 12;\n\nexport const EXTERNAL_LINK_IMG = document.createElement(\"img\");\nEXTERNAL_LINK_IMG.src = `data:${MIME_TYPES.svg}, ${encodeURIComponent(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#1971c2\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-external-link\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path><polyline points=\"15 3 21 3 21 9\"></polyline><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"></line></svg>`,\n)}`;\n\nexport const ELEMENT_LINK_IMG = document.createElement(\"img\");\nELEMENT_LINK_IMG.src = `data:${MIME_TYPES.svg}, ${encodeURIComponent(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#1971c2\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"icon icon-tabler icons-tabler-outline icon-tabler-arrow-big-right-line\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M12 9v-3.586a1 1 0 0 1 1.707 -.707l6.586 6.586a1 1 0 0 1 0 1.414l-6.586 6.586a1 1 0 0 1 -1.707 -.707v-3.586h-6v-6h6z\" /><path d=\"M3 9v6\" /></svg>`,\n)}`;\n\nexport const getLinkHandleFromCoords = (\n [x1, y1, x2, y2]: Bounds,\n angle: Radians,\n appState: Pick<UIAppState, \"zoom\">,\n): Bounds => {\n const size = DEFAULT_LINK_SIZE;\n const zoom = appState.zoom.value > 1 ? appState.zoom.value : 1;\n const linkWidth = size / zoom;\n const linkHeight = size / zoom;\n const linkMarginY = size / zoom;\n const centerX = (x1 + x2) / 2;\n const centerY = (y1 + y2) / 2;\n const centeringOffset = (size - 8) / (2 * zoom);\n const dashedLineMargin = 4 / zoom;\n\n // Same as `ne` resize handle\n const x = x2 + dashedLineMargin - centeringOffset;\n const y = y1 - dashedLineMargin - linkMarginY + centeringOffset;\n\n const [rotatedX, rotatedY] = pointRotateRads(\n pointFrom(x + linkWidth / 2, y + linkHeight / 2),\n pointFrom(centerX, centerY),\n angle,\n );\n return [\n rotatedX - linkWidth / 2,\n rotatedY - linkHeight / 2,\n linkWidth,\n linkHeight,\n ];\n};\n\nexport const isPointHittingLinkIcon = (\n element: NonDeletedExcalidrawElement,\n elementsMap: ElementsMap,\n appState: AppState,\n [x, y]: GlobalPoint,\n) => {\n const threshold = 4 / appState.zoom.value;\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const [linkX, linkY, linkWidth, linkHeight] = getLinkHandleFromCoords(\n [x1, y1, x2, y2],\n element.angle,\n appState,\n );\n const hitLink =\n x > linkX - threshold &&\n x < linkX + threshold + linkWidth &&\n y > linkY - threshold &&\n y < linkY + linkHeight + threshold;\n return hitLink;\n};\n\nexport const isPointHittingLink = (\n element: NonDeletedExcalidrawElement,\n elementsMap: ElementsMap,\n appState: AppState,\n [x, y]: GlobalPoint,\n isMobile: boolean,\n) => {\n if (!element.link || appState.selectedElementIds[element.id]) {\n return false;\n }\n if (\n !isMobile &&\n (appState.viewModeEnabled || appState.hideAnnotations) &&\n hitElementBoundingBox(pointFrom(x, y), element, elementsMap)\n ) {\n return true;\n }\n return isPointHittingLinkIcon(\n element,\n elementsMap,\n appState,\n pointFrom(x, y),\n );\n};\n", "import { THEME, applyDarkModeFilter } from \"@excalidraw/common\";\n\nimport type { StaticCanvasRenderConfig } from \"../scene/types\";\nimport type { AppState, StaticCanvasAppState } from \"../types\";\n\nexport const fillCircle = (\n context: CanvasRenderingContext2D,\n cx: number,\n cy: number,\n radius: number,\n stroke: boolean,\n fill = true,\n) => {\n context.beginPath();\n context.arc(cx, cy, radius, 0, Math.PI * 2);\n if (fill) {\n context.fill();\n }\n if (stroke) {\n context.stroke();\n }\n};\n\nexport const getNormalizedCanvasDimensions = (\n canvas: HTMLCanvasElement,\n scale: number,\n): [number, number] => {\n // When doing calculations based on canvas width we should used normalized one\n return [canvas.width / scale, canvas.height / scale];\n};\n\nexport const bootstrapCanvas = ({\n canvas,\n scale,\n normalizedWidth,\n normalizedHeight,\n theme,\n isExporting,\n viewBackgroundColor,\n}: {\n canvas: HTMLCanvasElement;\n scale: number;\n normalizedWidth: number;\n normalizedHeight: number;\n theme?: AppState[\"theme\"];\n isExporting?: StaticCanvasRenderConfig[\"isExporting\"];\n viewBackgroundColor?: StaticCanvasAppState[\"viewBackgroundColor\"];\n}): CanvasRenderingContext2D => {\n const context = canvas.getContext(\"2d\")!;\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n context.scale(scale, scale);\n\n // Paint background\n if (typeof viewBackgroundColor === \"string\") {\n const hasTransparence =\n viewBackgroundColor === \"transparent\" ||\n viewBackgroundColor.length === 5 || // #RGBA\n viewBackgroundColor.length === 9 || // #RRGGBBA\n /(hsla|rgba)\\(/.test(viewBackgroundColor);\n if (hasTransparence) {\n context.clearRect(0, 0, normalizedWidth, normalizedHeight);\n }\n context.save();\n context.fillStyle =\n theme === THEME.DARK\n ? applyDarkModeFilter(viewBackgroundColor)\n : viewBackgroundColor;\n context.fillRect(0, 0, normalizedWidth, normalizedHeight);\n context.restore();\n } else {\n context.clearRect(0, 0, normalizedWidth, normalizedHeight);\n }\n\n return context;\n};\n\nexport const strokeRectWithRotation_simple = (\n context: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n cx: number,\n cy: number,\n angle: number,\n fill: boolean = false,\n /** should account for zoom */\n radius: number = 0,\n) => {\n context.save();\n context.translate(cx, cy);\n context.rotate(angle);\n if (fill) {\n context.fillRect(x - cx, y - cy, width, height);\n }\n if (radius && context.roundRect) {\n context.beginPath();\n context.roundRect(x - cx, y - cy, width, height, radius);\n context.stroke();\n context.closePath();\n } else {\n context.strokeRect(x - cx, y - cy, width, height);\n }\n context.restore();\n};\n", "import {\n applyDarkModeFilter,\n FRAME_STYLE,\n THEME,\n throttleRAF,\n} from \"@excalidraw/common\";\nimport { isElementLink } from \"@excalidraw/element\";\nimport { createPlaceholderEmbeddableLabel } from \"@excalidraw/element\";\nimport { getBoundTextElement } from \"@excalidraw/element\";\nimport {\n isEmbeddableElement,\n isIframeLikeElement,\n isTextElement,\n} from \"@excalidraw/element\";\nimport {\n elementOverlapsWithFrame,\n getTargetFrame,\n shouldApplyFrameClip,\n} from \"@excalidraw/element\";\n\nimport { renderElement } from \"@excalidraw/element\";\n\nimport { getElementAbsoluteCoords } from \"@excalidraw/element\";\n\nimport type {\n ElementsMap,\n ExcalidrawFrameLikeElement,\n NonDeletedExcalidrawElement,\n} from \"@excalidraw/element/types\";\n\nimport {\n EXTERNAL_LINK_IMG,\n ELEMENT_LINK_IMG,\n getLinkHandleFromCoords,\n} from \"../components/hyperlink/helpers\";\n\nimport { bootstrapCanvas, getNormalizedCanvasDimensions } from \"./helpers\";\n\nimport type {\n StaticCanvasRenderConfig,\n StaticSceneRenderConfig,\n} from \"../scene/types\";\nimport type { StaticCanvasAppState, Zoom } from \"../types\";\n\nconst GridLineColor = {\n [THEME.LIGHT]: {\n bold: \"#dddddd\",\n regular: \"#e5e5e5\",\n },\n [THEME.DARK]: {\n bold: applyDarkModeFilter(\"#dddddd\"),\n regular: applyDarkModeFilter(\"#e5e5e5\"),\n },\n} as const;\n\nconst strokeGrid = (\n context: CanvasRenderingContext2D,\n /** grid cell pixel size */\n gridSize: number,\n /** setting to 1 will disble bold lines */\n gridStep: number,\n scrollX: number,\n scrollY: number,\n zoom: Zoom,\n theme: StaticCanvasRenderConfig[\"theme\"],\n width: number,\n height: number,\n) => {\n const offsetX = (scrollX % gridSize) - gridSize;\n const offsetY = (scrollY % gridSize) - gridSize;\n\n const actualGridSize = gridSize * zoom.value;\n\n const spaceWidth = 1 / zoom.value;\n\n context.save();\n\n // Offset rendering by 0.5 to ensure that 1px wide lines are crisp.\n // We only do this when zoomed to 100% because otherwise the offset is\n // fractional, and also visibly offsets the elements.\n // We also do this per-axis, as each axis may already be offset by 0.5.\n if (zoom.value === 1) {\n context.translate(offsetX % 1 ? 0 : 0.5, offsetY % 1 ? 0 : 0.5);\n }\n\n // vertical lines\n for (let x = offsetX; x < offsetX + width + gridSize * 2; x += gridSize) {\n const isBold =\n gridStep > 1 && Math.round(x - scrollX) % (gridStep * gridSize) === 0;\n // don't render regular lines when zoomed out and they're barely visible\n if (!isBold && actualGridSize < 10) {\n continue;\n }\n\n const lineWidth = Math.min(1 / zoom.value, isBold ? 4 : 1);\n context.lineWidth = lineWidth;\n const lineDash = [lineWidth * 3, spaceWidth + (lineWidth + spaceWidth)];\n\n context.beginPath();\n context.setLineDash(isBold ? [] : lineDash);\n context.strokeStyle = isBold\n ? GridLineColor[theme].bold\n : GridLineColor[theme].regular;\n context.moveTo(x, offsetY - gridSize);\n context.lineTo(x, Math.ceil(offsetY + height + gridSize * 2));\n context.stroke();\n }\n\n for (let y = offsetY; y < offsetY + height + gridSize * 2; y += gridSize) {\n const isBold =\n gridStep > 1 && Math.round(y - scrollY) % (gridStep * gridSize) === 0;\n if (!isBold && actualGridSize < 10) {\n continue;\n }\n\n const lineWidth = Math.min(1 / zoom.value, isBold ? 4 : 1);\n context.lineWidth = lineWidth;\n const lineDash = [lineWidth * 3, spaceWidth + (lineWidth + spaceWidth)];\n\n context.beginPath();\n context.setLineDash(isBold ? [] : lineDash);\n context.strokeStyle = isBold\n ? GridLineColor[theme].bold\n : GridLineColor[theme].regular;\n context.moveTo(offsetX - gridSize, y);\n context.lineTo(Math.ceil(offsetX + width + gridSize * 2), y);\n context.stroke();\n }\n context.restore();\n};\n\nexport const frameClip = (\n frame: ExcalidrawFrameLikeElement,\n context: CanvasRenderingContext2D,\n renderConfig: StaticCanvasRenderConfig,\n appState: StaticCanvasAppState,\n) => {\n context.translate(frame.x + appState.scrollX, frame.y + appState.scrollY);\n context.beginPath();\n if (context.roundRect) {\n context.roundRect(\n 0,\n 0,\n frame.width,\n frame.height,\n FRAME_STYLE.radius / appState.zoom.value,\n );\n } else {\n context.rect(0, 0, frame.width, frame.height);\n }\n context.clip();\n context.translate(\n -(frame.x + appState.scrollX),\n -(frame.y + appState.scrollY),\n );\n};\n\ntype LinkIconCanvas = HTMLCanvasElement & { zoom: number };\n\nconst linkIconCanvasCache: {\n regularLink: LinkIconCanvas | null;\n elementLink: LinkIconCanvas | null;\n} = {\n regularLink: null,\n elementLink: null,\n};\n\nconst renderLinkIcon = (\n element: NonDeletedExcalidrawElement,\n context: CanvasRenderingContext2D,\n appState: StaticCanvasAppState,\n elementsMap: ElementsMap,\n) => {\n if (element.link && !appState.selectedElementIds[element.id]) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n const [x, y, width, height] = getLinkHandleFromCoords(\n [x1, y1, x2, y2],\n element.angle,\n appState,\n );\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n context.save();\n context.translate(appState.scrollX + centerX, appState.scrollY + centerY);\n context.rotate(element.angle);\n\n const canvasKey = isElementLink(element.link)\n ? \"elementLink\"\n : \"regularLink\";\n\n let linkCanvas = linkIconCanvasCache[canvasKey];\n\n if (!linkCanvas || linkCanvas.zoom !== appState.zoom.value) {\n linkCanvas = Object.assign(document.createElement(\"canvas\"), {\n zoom: appState.zoom.value,\n });\n linkCanvas.width = width * window.devicePixelRatio * appState.zoom.value;\n linkCanvas.height =\n height * window.devicePixelRatio * appState.zoom.value;\n linkIconCanvasCache[canvasKey] = linkCanvas;\n\n const linkCanvasCacheContext = linkCanvas.getContext(\"2d\")!;\n linkCanvasCacheContext.scale(\n window.devicePixelRatio * appState.zoom.value,\n window.devicePixelRatio * appState.zoom.value,\n );\n linkCanvasCacheContext.fillStyle = appState.viewBackgroundColor || \"#fff\";\n linkCanvasCacheContext.fillRect(0, 0, width, height);\n\n if (canvasKey === \"elementLink\") {\n linkCanvasCacheContext.drawImage(ELEMENT_LINK_IMG, 0, 0, width, height);\n } else {\n linkCanvasCacheContext.drawImage(\n EXTERNAL_LINK_IMG,\n 0,\n 0,\n width,\n height,\n );\n }\n\n linkCanvasCacheContext.restore();\n }\n context.drawImage(linkCanvas, x - centerX, y - centerY, width, height);\n context.restore();\n }\n};\nconst _renderStaticScene = ({\n canvas,\n rc,\n elementsMap,\n allElementsMap,\n visibleElements,\n scale,\n appState,\n renderConfig,\n}: StaticSceneRenderConfig) => {\n if (canvas === null) {\n return;\n }\n\n const { renderGrid = true, isExporting } = renderConfig;\n\n const [normalizedWidth, normalizedHeight] = getNormalizedCanvasDimensions(\n canvas,\n scale,\n );\n\n const context = bootstrapCanvas({\n canvas,\n scale,\n normalizedWidth,\n normalizedHeight,\n theme: appState.theme,\n isExporting,\n viewBackgroundColor: appState.viewBackgroundColor,\n });\n\n // Apply zoom\n context.scale(appState.zoom.value, appState.zoom.value);\n\n // Grid\n if (renderGrid) {\n strokeGrid(\n context,\n appState.gridSize,\n appState.gridStep,\n appState.scrollX,\n appState.scrollY,\n appState.zoom,\n renderConfig.theme,\n normalizedWidth / appState.zoom.value,\n normalizedHeight / appState.zoom.value,\n );\n }\n\n const groupsToBeAddedToFrame = new Set<string>();\n\n visibleElements.forEach((element) => {\n if (\n element.groupIds.length > 0 &&\n appState.frameToHighlight &&\n appState.selectedElementIds[element.id] &&\n (elementOverlapsWithFrame(\n element,\n appState.frameToHighlight,\n elementsMap,\n ) ||\n element.groupIds.find((groupId) => groupsToBeAddedToFrame.has(groupId)))\n ) {\n element.groupIds.forEach((groupId) =>\n groupsToBeAddedToFrame.add(groupId),\n );\n }\n });\n\n const inFrameGroupsMap = new Map<string, boolean>();\n\n // Paint visible elements\n visibleElements\n .filter((el) => !isIframeLikeElement(el))\n .forEach((element) => {\n try {\n const frameId = element.frameId || appState.frameToHighlight?.id;\n\n if (\n isTextElement(element) &&\n element.containerId &&\n elementsMap.has(element.containerId)\n ) {\n // will be rendered with the container\n return;\n }\n\n context.save();\n\n if (\n frameId &&\n appState.frameRendering.enabled &&\n appState.frameRendering.clip\n ) {\n const frame = getTargetFrame(element, elementsMap, appState);\n if (\n frame &&\n shouldApplyFrameClip(\n element,\n frame,\n appState,\n elementsMap,\n inFrameGroupsMap,\n )\n ) {\n frameClip(frame, context, renderConfig, appState);\n }\n renderElement(\n element,\n elementsMap,\n allElementsMap,\n rc,\n context,\n renderConfig,\n appState,\n );\n } else {\n renderElement(\n element,\n elementsMap,\n allElementsMap,\n rc,\n context,\n renderConfig,\n appState,\n );\n }\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (boundTextElement) {\n renderElement(\n boundTextElement,\n elementsMap,\n allElementsMap,\n rc,\n context,\n renderConfig,\n appState,\n );\n }\n\n context.restore();\n\n if (!isExporting) {\n renderLinkIcon(element, context, appState, elementsMap);\n }\n } catch (error: any) {\n console.error(\n error,\n element.id,\n element.x,\n element.y,\n element.width,\n element.height,\n );\n }\n });\n\n // render embeddables on top\n visibleElements\n .filter((el) => isIframeLikeElement(el))\n .forEach((element) => {\n try {\n const render = () => {\n renderElement(\n element,\n elementsMap,\n allElementsMap,\n rc,\n context,\n renderConfig,\n appState,\n );\n\n if (\n isIframeLikeElement(element) &&\n (isExporting ||\n (isEmbeddableElement(element) &&\n renderConfig.embedsValidationStatus.get(element.id) !==\n true)) &&\n element.width &&\n element.height\n ) {\n const label = createPlaceholderEmbeddableLabel(element);\n renderElement(\n label,\n elementsMap,\n allElementsMap,\n rc,\n context,\n renderConfig,\n appState,\n );\n }\n if (!isExporting) {\n renderLinkIcon(element, context, appState, elementsMap);\n }\n };\n // - when exporting the whole canvas, we DO NOT apply clipping\n // - when we are exporting a particular frame, apply clipping\n // if the containing frame is not selected, apply clipping\n const frameId = element.frameId || appState.frameToHighlight?.id;\n\n if (\n frameId &&\n appState.frameRendering.enabled &&\n appState.frameRendering.clip\n ) {\n context.save();\n\n const frame = getTargetFrame(element, elementsMap, appState);\n\n if (\n frame &&\n shouldApplyFrameClip(\n element,\n frame,\n appState,\n elementsMap,\n inFrameGroupsMap,\n )\n ) {\n frameClip(frame, context, renderConfig, appState);\n }\n render();\n context.restore();\n } else {\n render();\n }\n } catch (error: any) {\n console.error(error);\n }\n });\n\n // render pending nodes for flowcharts\n renderConfig.pendingFlowchartNodes?.forEach((element) => {\n try {\n renderElement(\n element,\n elementsMap,\n allElementsMap,\n rc,\n context,\n renderConfig,\n appState,\n );\n } catch (error) {\n console.error(error);\n }\n });\n};\n\n/** throttled to animation framerate */\nexport const renderStaticSceneThrottled = throttleRAF(\n (config: StaticSceneRenderConfig) => {\n _renderStaticScene(config);\n },\n { trailing: true },\n);\n\n/**\n * Static scene is the non-ui canvas where we render elements.\n */\nexport const renderStaticScene = (\n renderConfig: StaticSceneRenderConfig,\n throttle?: boolean,\n) => {\n if (throttle) {\n renderStaticSceneThrottled(renderConfig);\n return;\n }\n\n _renderStaticScene(renderConfig);\n};\n", "import {\n FRAME_STYLE,\n MAX_DECIMALS_FOR_SVG_EXPORT,\n SVG_NS,\n THEME,\n getFontFamilyString,\n isRTL,\n isTestEnv,\n getVerticalOffset,\n applyDarkModeFilter,\n} from \"@excalidraw/common\";\nimport { normalizeLink, toValidURL } from \"@excalidraw/common\";\nimport { hashString } from \"@excalidraw/element\";\nimport { getUncroppedWidthAndHeight } from \"@excalidraw/element\";\nimport {\n createPlaceholderEmbeddableLabel,\n getEmbedLink,\n} from \"@excalidraw/element\";\nimport { LinearElementEditor } from \"@excalidraw/element\";\nimport { getBoundTextElement, getContainerElement } from \"@excalidraw/element\";\nimport { getLineHeightInPx } from \"@excalidraw/element\";\nimport {\n isArrowElement,\n isIframeLikeElement,\n isInitializedImageElement,\n isTextElement,\n} from \"@excalidraw/element\";\n\nimport { getContainingFrame } from \"@excalidraw/element\";\n\nimport { getCornerRadius, isPathALoop } from \"@excalidraw/element\";\n\nimport { ShapeCache } from \"@excalidraw/element\";\n\nimport { getElementAbsoluteCoords } from \"@excalidraw/element\";\n\nimport type {\n ExcalidrawElement,\n ExcalidrawTextElementWithContainer,\n NonDeletedExcalidrawElement,\n} from \"@excalidraw/element/types\";\n\nimport type { RenderableElementsMap, SVGRenderConfig } from \"../scene/types\";\nimport type { AppState, BinaryFiles } from \"../types\";\nimport type { Drawable } from \"roughjs/bin/core\";\nimport type { RoughSVG } from \"roughjs/bin/svg\";\n\nconst roughSVGDrawWithPrecision = (\n rsvg: RoughSVG,\n drawable: Drawable,\n precision?: number,\n) => {\n if (typeof precision === \"undefined\") {\n return rsvg.draw(drawable);\n }\n const pshape: Drawable = {\n sets: drawable.sets,\n shape: drawable.shape,\n options: { ...drawable.options, fixedDecimalPlaceDigits: precision },\n };\n return rsvg.draw(pshape);\n};\n\nconst maybeWrapNodesInFrameClipPath = (\n element: NonDeletedExcalidrawElement,\n root: SVGElement,\n nodes: SVGElement[],\n frameRendering: AppState[\"frameRendering\"],\n elementsMap: RenderableElementsMap,\n) => {\n if (!frameRendering.enabled || !frameRendering.clip) {\n return null;\n }\n const frame = getContainingFrame(element, elementsMap);\n if (frame) {\n const g = root.ownerDocument.createElementNS(SVG_NS, \"g\");\n g.setAttributeNS(SVG_NS, \"clip-path\", `url(#${frame.id})`);\n nodes.forEach((node) => g.appendChild(node));\n return g;\n }\n\n return null;\n};\n\nconst renderElementToSvg = (\n element: NonDeletedExcalidrawElement,\n elementsMap: RenderableElementsMap,\n rsvg: RoughSVG,\n svgRoot: SVGElement,\n files: BinaryFiles,\n offsetX: number,\n offsetY: number,\n renderConfig: SVGRenderConfig,\n) => {\n const offset = { x: offsetX, y: offsetY };\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);\n let cx = (x2 - x1) / 2 - (element.x - x1);\n let cy = (y2 - y1) / 2 - (element.y - y1);\n if (isTextElement(element)) {\n const container = getContainerElement(element, elementsMap);\n if (isArrowElement(container)) {\n const [x1, y1, x2, y2] = getElementAbsoluteCoords(container, elementsMap);\n\n const boundTextCoords = LinearElementEditor.getBoundTextElementPosition(\n container,\n element as ExcalidrawTextElementWithContainer,\n elementsMap,\n );\n cx = (x2 - x1) / 2 - (boundTextCoords.x - x1);\n cy = (y2 - y1) / 2 - (boundTextCoords.y - y1);\n offsetX = offsetX + boundTextCoords.x - element.x;\n offsetY = offsetY + boundTextCoords.y - element.y;\n }\n }\n const degree = (180 * element.angle) / Math.PI;\n\n // element to append node to, most of the time svgRoot\n let root = svgRoot;\n\n // if the element has a link, create an anchor tag and make that the new root\n if (element.link) {\n const anchorTag = svgRoot.ownerDocument.createElementNS(SVG_NS, \"a\");\n anchorTag.setAttribute(\"href\", normalizeLink(element.link));\n root.appendChild(anchorTag);\n root = anchorTag;\n }\n\n const addToRoot = (node: SVGElement, element: ExcalidrawElement) => {\n if (isTestEnv()) {\n node.setAttribute(\"data-id\", element.id);\n }\n root.appendChild(node);\n };\n\n const opacity =\n ((getContainingFrame(element, elementsMap)?.opacity ?? 100) *\n element.opacity) /\n 10000;\n\n switch (element.type) {\n case \"selection\": {\n // Since this is used only during editing experience, which is canvas based,\n // this should not happen\n throw new Error(\"Selection rendering is not supported for SVG\");\n }\n case \"rectangle\":\n case \"diamond\":\n case \"ellipse\": {\n const shape = ShapeCache.generateElementShape(element, renderConfig);\n const node = roughSVGDrawWithPrecision(\n rsvg,\n shape,\n MAX_DECIMALS_FOR_SVG_EXPORT,\n );\n if (opacity !== 1) {\n node.setAttribute(\"stroke-opacity\", `${opacity}`);\n node.setAttribute(\"fill-opacity\", `${opacity}`);\n }\n node.setAttribute(\"stroke-linecap\", \"round\");\n node.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n\n const g = maybeWrapNodesInFrameClipPath(\n element,\n root,\n [node],\n renderConfig.frameRendering,\n elementsMap,\n );\n\n addToRoot(g || node, element);\n break;\n }\n case \"iframe\":\n case \"embeddable\": {\n // render placeholder rectangle\n const shape = ShapeCache.generateElementShape(element, renderConfig);\n const node = roughSVGDrawWithPrecision(\n rsvg,\n shape,\n MAX_DECIMALS_FOR_SVG_EXPORT,\n );\n const opacity = element.opacity / 100;\n if (opacity !== 1) {\n node.setAttribute(\"stroke-opacity\", `${opacity}`);\n node.setAttribute(\"fill-opacity\", `${opacity}`);\n }\n node.setAttribute(\"stroke-linecap\", \"round\");\n node.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n addToRoot(node, element);\n\n const label: ExcalidrawElement =\n createPlaceholderEmbeddableLabel(element);\n renderElementToSvg(\n label,\n elementsMap,\n rsvg,\n root,\n files,\n label.x + offset.x - element.x,\n label.y + offset.y - element.y,\n renderConfig,\n );\n\n // render embeddable element + iframe\n const embeddableNode = roughSVGDrawWithPrecision(\n rsvg,\n shape,\n MAX_DECIMALS_FOR_SVG_EXPORT,\n );\n embeddableNode.setAttribute(\"stroke-linecap\", \"round\");\n embeddableNode.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n while (embeddableNode.firstChild) {\n embeddableNode.removeChild(embeddableNode.firstChild);\n }\n const radius = getCornerRadius(\n Math.min(element.width, element.height),\n element,\n );\n\n const embedLink = getEmbedLink(toValidURL(element.link || \"\"));\n\n // if rendering embeddables explicitly disabled or\n // embedding documents via srcdoc (which doesn't seem to work for SVGs)\n // replace with a link instead\n if (\n renderConfig.renderEmbeddables === false ||\n embedLink?.type === \"document\"\n ) {\n const anchorTag = svgRoot.ownerDocument.createElementNS(SVG_NS, \"a\");\n anchorTag.setAttribute(\"href\", normalizeLink(element.link || \"\"));\n anchorTag.setAttribute(\"target\", \"_blank\");\n anchorTag.setAttribute(\"rel\", \"noopener noreferrer\");\n anchorTag.style.borderRadius = `${radius}px`;\n\n embeddableNode.appendChild(anchorTag);\n } else {\n const foreignObject = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"foreignObject\",\n );\n foreignObject.style.width = `${element.width}px`;\n foreignObject.style.height = `${element.height}px`;\n foreignObject.style.border = \"none\";\n const div = foreignObject.ownerDocument.createElementNS(SVG_NS, \"div\");\n div.setAttribute(\"xmlns\", \"http://www.w3.org/1999/xhtml\");\n div.style.width = \"100%\";\n div.style.height = \"100%\";\n const iframe = div.ownerDocument.createElement(\"iframe\");\n iframe.src = embedLink?.link ?? \"\";\n iframe.style.width = \"100%\";\n iframe.style.height = \"100%\";\n iframe.style.border = \"none\";\n iframe.style.borderRadius = `${radius}px`;\n iframe.style.top = \"0\";\n iframe.style.left = \"0\";\n iframe.allowFullscreen = true;\n div.appendChild(iframe);\n foreignObject.appendChild(div);\n\n embeddableNode.appendChild(foreignObject);\n }\n addToRoot(embeddableNode, element);\n break;\n }\n case \"line\":\n case \"arrow\": {\n const boundText = getBoundTextElement(element, elementsMap);\n const maskPath = svgRoot.ownerDocument.createElementNS(SVG_NS, \"mask\");\n if (boundText) {\n maskPath.setAttribute(\"id\", `mask-${element.id}`);\n const maskRectVisible = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"rect\",\n );\n offsetX = offsetX || 0;\n offsetY = offsetY || 0;\n maskRectVisible.setAttribute(\"x\", \"0\");\n maskRectVisible.setAttribute(\"y\", \"0\");\n maskRectVisible.setAttribute(\"fill\", \"#fff\");\n maskRectVisible.setAttribute(\n \"width\",\n `${element.width + 100 + offsetX}`,\n );\n maskRectVisible.setAttribute(\n \"height\",\n `${element.height + 100 + offsetY}`,\n );\n\n maskPath.appendChild(maskRectVisible);\n const maskRectInvisible = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"rect\",\n );\n const boundTextCoords = LinearElementEditor.getBoundTextElementPosition(\n element,\n boundText,\n elementsMap,\n );\n\n const maskX = offsetX + boundTextCoords.x - element.x;\n const maskY = offsetY + boundTextCoords.y - element.y;\n\n maskRectInvisible.setAttribute(\"x\", maskX.toString());\n maskRectInvisible.setAttribute(\"y\", maskY.toString());\n maskRectInvisible.setAttribute(\"fill\", \"#000\");\n maskRectInvisible.setAttribute(\"width\", `${boundText.width}`);\n maskRectInvisible.setAttribute(\"height\", `${boundText.height}`);\n maskRectInvisible.setAttribute(\"opacity\", \"1\");\n maskPath.appendChild(maskRectInvisible);\n }\n const group = svgRoot.ownerDocument.createElementNS(SVG_NS, \"g\");\n if (boundText) {\n group.setAttribute(\"mask\", `url(#mask-${element.id})`);\n }\n group.setAttribute(\"stroke-linecap\", \"round\");\n\n const shapes = ShapeCache.generateElementShape(element, renderConfig);\n shapes.forEach((shape) => {\n const node = roughSVGDrawWithPrecision(\n rsvg,\n shape,\n MAX_DECIMALS_FOR_SVG_EXPORT,\n );\n if (opacity !== 1) {\n node.setAttribute(\"stroke-opacity\", `${opacity}`);\n node.setAttribute(\"fill-opacity\", `${opacity}`);\n }\n node.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n if (\n element.type === \"line\" &&\n isPathALoop(element.points) &&\n element.backgroundColor !== \"transparent\"\n ) {\n node.setAttribute(\"fill-rule\", \"evenodd\");\n }\n group.appendChild(node);\n });\n\n const g = maybeWrapNodesInFrameClipPath(\n element,\n root,\n [group, maskPath],\n renderConfig.frameRendering,\n elementsMap,\n );\n if (g) {\n addToRoot(g, element);\n root.appendChild(g);\n } else {\n addToRoot(group, element);\n root.append(maskPath);\n }\n break;\n }\n case \"freedraw\": {\n const wrapper = svgRoot.ownerDocument.createElementNS(SVG_NS, \"g\");\n\n const shapes = ShapeCache.generateElementShape(element, renderConfig);\n // always ordered as [background, stroke]\n for (const shape of shapes) {\n if (typeof shape === \"string\") {\n // stroke (SVGPathString)\n\n const path = svgRoot.ownerDocument.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\n \"fill\",\n renderConfig.theme === THEME.DARK\n ? applyDarkModeFilter(element.strokeColor)\n : element.strokeColor,\n );\n path.setAttribute(\"d\", shape);\n wrapper.appendChild(path);\n } else {\n // background (Drawable)\n\n const bgNode = roughSVGDrawWithPrecision(\n rsvg,\n shape,\n MAX_DECIMALS_FOR_SVG_EXPORT,\n );\n\n // if children wrapped in <g>, unwrap it\n if (bgNode.nodeName === \"g\") {\n while (bgNode.firstChild) {\n wrapper.appendChild(bgNode.firstChild);\n }\n } else {\n wrapper.appendChild(bgNode);\n }\n }\n }\n if (opacity !== 1) {\n wrapper.setAttribute(\"stroke-opacity\", `${opacity}`);\n wrapper.setAttribute(\"fill-opacity\", `${opacity}`);\n }\n wrapper.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n wrapper.setAttribute(\"stroke\", \"none\");\n\n const g = maybeWrapNodesInFrameClipPath(\n element,\n root,\n [wrapper],\n renderConfig.frameRendering,\n elementsMap,\n );\n\n addToRoot(g || wrapper, element);\n break;\n }\n case \"image\": {\n const width = Math.round(element.width);\n const height = Math.round(element.height);\n const fileData =\n isInitializedImageElement(element) && files[element.fileId];\n if (fileData) {\n const { reuseImages = true } = renderConfig;\n\n let symbolId = `image-${fileData.id}`;\n\n let uncroppedWidth = element.width;\n let uncroppedHeight = element.height;\n if (element.crop) {\n ({ width: uncroppedWidth, height: uncroppedHeight } =\n getUncroppedWidthAndHeight(element));\n\n symbolId = `image-crop-${fileData.id}-${hashString(\n `${uncroppedWidth}x${uncroppedHeight}`,\n )}`;\n }\n\n if (!reuseImages) {\n symbolId = `image-${element.id}`;\n }\n\n let symbol = svgRoot.querySelector(`#${symbolId}`);\n if (!symbol) {\n symbol = svgRoot.ownerDocument.createElementNS(SVG_NS, \"symbol\");\n symbol.id = symbolId;\n\n const image = svgRoot.ownerDocument.createElementNS(SVG_NS, \"image\");\n image.setAttribute(\"href\", fileData.dataURL);\n image.setAttribute(\"preserveAspectRatio\", \"none\");\n\n if (element.crop || !reuseImages) {\n image.setAttribute(\"width\", `${uncroppedWidth}`);\n image.setAttribute(\"height\", `${uncroppedHeight}`);\n } else {\n image.setAttribute(\"width\", \"100%\");\n image.setAttribute(\"height\", \"100%\");\n }\n\n symbol.appendChild(image);\n\n (root.querySelector(\"defs\") || root).prepend(symbol);\n }\n\n const use = svgRoot.ownerDocument.createElementNS(SVG_NS, \"use\");\n use.setAttribute(\"href\", `#${symbolId}`);\n\n let normalizedCropX = 0;\n let normalizedCropY = 0;\n\n if (element.crop) {\n const { width: uncroppedWidth, height: uncroppedHeight } =\n getUncroppedWidthAndHeight(element);\n normalizedCropX =\n element.crop.x / (element.crop.naturalWidth / uncroppedWidth);\n normalizedCropY =\n element.crop.y / (element.crop.naturalHeight / uncroppedHeight);\n }\n\n const adjustedCenterX = cx + normalizedCropX;\n const adjustedCenterY = cy + normalizedCropY;\n\n use.setAttribute(\"width\", `${width + normalizedCropX}`);\n use.setAttribute(\"height\", `${height + normalizedCropY}`);\n use.setAttribute(\"opacity\", `${opacity}`);\n\n // We first apply `scale` transforms (horizontal/vertical mirroring)\n // on the <use> element, then apply translation and rotation\n // on the <g> element which wraps the <use>.\n // Doing this separately is a quick hack to to work around compositing\n // the transformations correctly (the transform-origin was not being\n // applied correctly).\n if (element.scale[0] !== 1 || element.scale[1] !== 1) {\n use.setAttribute(\n \"transform\",\n `translate(${adjustedCenterX} ${adjustedCenterY}) scale(${\n element.scale[0]\n } ${\n element.scale[1]\n }) translate(${-adjustedCenterX} ${-adjustedCenterY})`,\n );\n }\n\n const g = svgRoot.ownerDocument.createElementNS(SVG_NS, \"g\");\n\n if (element.crop) {\n const mask = svgRoot.ownerDocument.createElementNS(SVG_NS, \"mask\");\n mask.setAttribute(\"id\", `mask-image-crop-${element.id}`);\n mask.setAttribute(\"fill\", \"#fff\");\n const maskRect = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"rect\",\n );\n\n maskRect.setAttribute(\"x\", `${normalizedCropX}`);\n maskRect.setAttribute(\"y\", `${normalizedCropY}`);\n maskRect.setAttribute(\"width\", `${width}`);\n maskRect.setAttribute(\"height\", `${height}`);\n\n mask.appendChild(maskRect);\n root.appendChild(mask);\n g.setAttribute(\"mask\", `url(#${mask.id})`);\n }\n\n g.appendChild(use);\n g.setAttribute(\n \"transform\",\n `translate(${offsetX - normalizedCropX} ${\n offsetY - normalizedCropY\n }) rotate(${degree} ${adjustedCenterX} ${adjustedCenterY})`,\n );\n\n if (element.roundness) {\n const clipPath = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"clipPath\",\n );\n clipPath.id = `image-clipPath-${element.id}`;\n clipPath.setAttribute(\"clipPathUnits\", \"userSpaceOnUse\");\n const clipRect = svgRoot.ownerDocument.createElementNS(\n SVG_NS,\n \"rect\",\n );\n const radius = getCornerRadius(\n Math.min(element.width, element.height),\n element,\n );\n const clipOffsetX = element.crop ? normalizedCropX : 0;\n const clipOffsetY = element.crop ? normalizedCropY : 0;\n clipRect.setAttribute(\"x\", `${clipOffsetX}`);\n clipRect.setAttribute(\"y\", `${clipOffsetY}`);\n clipRect.setAttribute(\"width\", `${element.width}`);\n clipRect.setAttribute(\"height\", `${element.height}`);\n clipRect.setAttribute(\"rx\", `${radius}`);\n clipRect.setAttribute(\"ry\", `${radius}`);\n clipPath.appendChild(clipRect);\n addToRoot(clipPath, element);\n\n g.setAttributeNS(SVG_NS, \"clip-path\", `url(#${clipPath.id})`);\n }\n\n const clipG = maybeWrapNodesInFrameClipPath(\n element,\n root,\n [g],\n renderConfig.frameRendering,\n elementsMap,\n );\n addToRoot(clipG || g, element);\n }\n break;\n }\n // frames are not rendered and only acts as a container\n case \"frame\":\n case \"magicframe\": {\n if (\n renderConfig.frameRendering.enabled &&\n renderConfig.frameRendering.outline\n ) {\n const rect = document.createElementNS(SVG_NS, \"rect\");\n\n rect.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n\n rect.setAttribute(\"width\", `${element.width}px`);\n rect.setAttribute(\"height\", `${element.height}px`);\n // Rounded corners\n rect.setAttribute(\"rx\", FRAME_STYLE.radius.toString());\n rect.setAttribute(\"ry\", FRAME_STYLE.radius.toString());\n\n rect.setAttribute(\"fill\", \"none\");\n rect.setAttribute(\n \"stroke\",\n renderConfig.theme === THEME.DARK\n ? applyDarkModeFilter(FRAME_STYLE.strokeColor)\n : FRAME_STYLE.strokeColor,\n );\n rect.setAttribute(\"stroke-width\", FRAME_STYLE.strokeWidth.toString());\n\n addToRoot(rect, element);\n }\n break;\n }\n default: {\n if (isTextElement(element)) {\n const node = svgRoot.ownerDocument.createElementNS(SVG_NS, \"g\");\n if (opacity !== 1) {\n node.setAttribute(\"stroke-opacity\", `${opacity}`);\n node.setAttribute(\"fill-opacity\", `${opacity}`);\n }\n\n node.setAttribute(\n \"transform\",\n `translate(${offsetX || 0} ${\n offsetY || 0\n }) rotate(${degree} ${cx} ${cy})`,\n );\n const lines = element.text.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\");\n const lineHeightPx = getLineHeightInPx(\n element.fontSize,\n element.lineHeight,\n );\n const horizontalOffset =\n element.textAlign === \"center\"\n ? element.width / 2\n : element.textAlign === \"right\"\n ? element.width\n : 0;\n const verticalOffset = getVerticalOffset(\n element.fontFamily,\n element.fontSize,\n lineHeightPx,\n );\n const direction = isRTL(element.text) ? \"rtl\" : \"ltr\";\n const textAnchor =\n element.textAlign === \"center\"\n ? \"middle\"\n : element.textAlign === \"right\" || direction === \"rtl\"\n ? \"end\"\n : \"start\";\n for (let i = 0; i < lines.length; i++) {\n const text = svgRoot.ownerDocument.createElementNS(SVG_NS, \"text\");\n text.textContent = lines[i];\n text.setAttribute(\"x\", `${horizontalOffset}`);\n text.setAttribute(\"y\", `${i * lineHeightPx + verticalOffset}`);\n text.setAttribute(\"font-family\", getFontFamilyString(element));\n text.setAttribute(\"font-size\", `${element.fontSize}px`);\n text.setAttribute(\n \"fill\",\n renderConfig.theme === THEME.DARK\n ? applyDarkModeFilter(element.strokeColor)\n : element.strokeColor,\n );\n text.setAttribute(\"text-anchor\", textAnchor);\n text.setAttribute(\"style\", \"white-space: pre;\");\n text.setAttribute(\"direction\", direction);\n text.setAttribute(\"dominant-baseline\", \"alphabetic\");\n node.appendChild(text);\n }\n\n const g = maybeWrapNodesInFrameClipPath(\n element,\n root,\n [node],\n renderConfig.frameRendering,\n elementsMap,\n );\n\n addToRoot(g || node, element);\n } else {\n // @ts-ignore\n throw new Error(`Unimplemented type ${element.type}`);\n }\n }\n }\n};\n\nexport const renderSceneToSvg = (\n elements: readonly NonDeletedExcalidrawElement[],\n elementsMap: RenderableElementsMap,\n rsvg: RoughSVG,\n svgRoot: SVGElement,\n files: BinaryFiles,\n renderConfig: SVGRenderConfig,\n) => {\n if (!svgRoot) {\n return;\n }\n\n // render elements\n elements\n .filter((el) => !isIframeLikeElement(el))\n .forEach((element) => {\n if (!element.isDeleted) {\n if (\n isTextElement(element) &&\n element.containerId &&\n elementsMap.has(element.containerId)\n ) {\n // will be rendered with the container\n return;\n }\n\n try {\n renderElementToSvg(\n element,\n elementsMap,\n rsvg,\n svgRoot,\n files,\n element.x + renderConfig.offsetX,\n element.y + renderConfig.offsetY,\n renderConfig,\n );\n\n const boundTextElement = getBoundTextElement(element, elementsMap);\n if (boundTextElement) {\n renderElementToSvg(\n boundTextElement,\n elementsMap,\n rsvg,\n svgRoot,\n files,\n boundTextElement.x + renderConfig.offsetX,\n boundTextElement.y + renderConfig.offsetY,\n renderConfig,\n );\n }\n } catch (error: any) {\n console.error(error);\n }\n }\n });\n\n // render embeddables on top\n elements\n .filter((el) => isIframeLikeElement(el))\n .forEach((element) => {\n if (!element.isDeleted) {\n try {\n renderElementToSvg(\n element,\n elementsMap,\n rsvg,\n svgRoot,\n files,\n element.x + renderConfig.offsetX,\n element.y + renderConfig.offsetY,\n renderConfig,\n );\n } catch (error: any) {\n console.error(error);\n }\n }\n });\n};\n", "import { isFiniteNumber, pointFrom } from \"@excalidraw/math\";\n\nimport {\n type CombineBrandsIfNeeded,\n DEFAULT_FONT_FAMILY,\n DEFAULT_TEXT_ALIGN,\n DEFAULT_VERTICAL_ALIGN,\n FONT_FAMILY,\n ROUNDNESS,\n DEFAULT_SIDEBAR,\n DEFAULT_ELEMENT_PROPS,\n DEFAULT_GRID_SIZE,\n DEFAULT_GRID_STEP,\n randomId,\n getUpdatedTimestamp,\n updateActiveTool,\n arrayToMap,\n getSizeFromPoints,\n normalizeLink,\n getLineHeight,\n} from \"@excalidraw/common\";\nimport {\n calculateFixedPointForNonElbowArrowBinding,\n getNonDeletedElements,\n isPointInElement,\n isValidPolygon,\n projectFixedPointOntoDiagonal,\n} from \"@excalidraw/element\";\nimport { normalizeFixedPoint } from \"@excalidraw/element\";\nimport {\n updateElbowArrowPoints,\n validateElbowPoints,\n} from \"@excalidraw/element\";\nimport { LinearElementEditor } from \"@excalidraw/element\";\nimport { bumpVersion } from \"@excalidraw/element\";\nimport { getContainerElement } from \"@excalidraw/element\";\nimport { detectLineHeight } from \"@excalidraw/element\";\nimport {\n isArrowBoundToElement,\n isArrowElement,\n isElbowArrow,\n isLinearElement,\n isLineElement,\n isTextElement,\n isUsingAdaptiveRadius,\n} from \"@excalidraw/element\";\n\nimport { syncInvalidIndices } from \"@excalidraw/element\";\n\nimport { refreshTextDimensions } from \"@excalidraw/element\";\n\nimport { getNormalizedDimensions } from \"@excalidraw/element\";\n\nimport { isInvisiblySmallElement } from \"@excalidraw/element\";\n\nimport type { LocalPoint, Radians } from \"@excalidraw/math\";\n\nimport type {\n ElementsMap,\n ElementsMapOrArray,\n ExcalidrawArrowElement,\n ExcalidrawBindableElement,\n ExcalidrawElbowArrowElement,\n ExcalidrawElement,\n ExcalidrawLinearElement,\n ExcalidrawSelectionElement,\n ExcalidrawTextElement,\n FixedPointBinding,\n FontFamilyValues,\n NonDeletedSceneElementsMap,\n OrderedExcalidrawElement,\n StrokeRoundness,\n} from \"@excalidraw/element/types\";\n\nimport type { MarkOptional, Mutable } from \"@excalidraw/common/utility-types\";\n\nimport { getDefaultAppState } from \"../appState\";\n\nimport {\n getNormalizedGridSize,\n getNormalizedGridStep,\n getNormalizedZoom,\n} from \"../scene\";\n\nimport type { AppState, BinaryFiles, LibraryItem } from \"../types\";\nimport type { ImportedDataState, LegacyAppState } from \"./types\";\n\ntype RestoredAppState = Omit<\n AppState,\n \"offsetTop\" | \"offsetLeft\" | \"width\" | \"height\"\n>;\n\nexport const AllowedExcalidrawActiveTools: Record<\n AppState[\"activeTool\"][\"type\"],\n boolean\n> = {\n selection: true,\n lasso: true,\n text: true,\n rectangle: true,\n diamond: true,\n ellipse: true,\n line: true,\n image: true,\n arrow: true,\n freedraw: true,\n eraser: false,\n custom: true,\n frame: true,\n embeddable: true,\n hand: true,\n laser: false,\n magicframe: false,\n};\n\nexport type RestoredDataState = {\n elements: OrderedExcalidrawElement[];\n appState: RestoredAppState;\n files: BinaryFiles;\n};\n\nconst getFontFamilyByName = (fontFamilyName: string): FontFamilyValues => {\n if (Object.keys(FONT_FAMILY).includes(fontFamilyName)) {\n return FONT_FAMILY[\n fontFamilyName as keyof typeof FONT_FAMILY\n ] as FontFamilyValues;\n }\n return DEFAULT_FONT_FAMILY;\n};\n\nconst repairBinding = <T extends ExcalidrawArrowElement>(\n element: T,\n binding: FixedPointBinding | null,\n targetElementsMap: Readonly<ElementsMap>,\n /** used for context (arrow bindings) */\n existingElementsMap: Readonly<ElementsMap> | null | undefined,\n startOrEnd: \"start\" | \"end\",\n): FixedPointBinding | null => {\n if (!binding) {\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // elbow arrows\n // ---------------------------------------------------------------------------\n\n if (isElbowArrow(element)) {\n const fixedPointBinding:\n | ExcalidrawElbowArrowElement[\"startBinding\"]\n | ExcalidrawElbowArrowElement[\"endBinding\"] = {\n ...binding,\n fixedPoint: normalizeFixedPoint(binding.fixedPoint ?? [0, 0]),\n mode: binding.mode || \"orbit\",\n };\n\n return fixedPointBinding;\n }\n\n // ---------------------------------------------------------------------------\n // simple arrows\n // ---------------------------------------------------------------------------\n\n // binding schema v2\n // ---------------------------------------------------------------------------\n\n if (binding.mode) {\n // if latest binding schema, don't check if binding.elementId exists\n // (it's done in a separate pass)\n if (binding.elementId) {\n return {\n elementId: binding.elementId,\n mode: binding.mode,\n fixedPoint: normalizeFixedPoint(binding.fixedPoint || [0.5, 0.5]),\n } as FixedPointBinding | null;\n }\n return null;\n }\n\n // binding schema v1 (legacy) -> attempt to migrate to v2\n // ---------------------------------------------------------------------------\n\n const targetBoundElement =\n (targetElementsMap.get(binding.elementId) as ExcalidrawBindableElement) ||\n undefined;\n const boundElement =\n targetBoundElement ||\n (existingElementsMap?.get(\n binding.elementId,\n ) as ExcalidrawBindableElement) ||\n undefined;\n const elementsMap = targetBoundElement\n ? targetElementsMap\n : existingElementsMap;\n\n // migrating legacy focus point bindings\n if (boundElement && elementsMap) {\n const p = LinearElementEditor.getPointAtIndexGlobalCoordinates(\n element,\n startOrEnd === \"start\" ? 0 : element.points.length - 1,\n elementsMap,\n );\n const mode = isPointInElement(p, boundElement, elementsMap)\n ? \"inside\"\n : \"orbit\";\n const focusPoint =\n mode === \"inside\"\n ? p\n : projectFixedPointOntoDiagonal(\n element,\n p,\n boundElement,\n startOrEnd,\n elementsMap,\n ) || p;\n const { fixedPoint } = calculateFixedPointForNonElbowArrowBinding(\n element,\n boundElement,\n startOrEnd,\n elementsMap,\n focusPoint,\n );\n\n return {\n mode,\n elementId: binding.elementId,\n fixedPoint,\n };\n }\n\n console.error(`could not repair binding for element`);\n\n return null;\n};\n\nconst restoreElementWithProperties = <\n T extends Required<Omit<ExcalidrawElement, \"customData\">> & {\n customData?: ExcalidrawElement[\"customData\"];\n /** @deprecated */\n boundElementIds?: readonly ExcalidrawElement[\"id\"][];\n /** @deprecated */\n strokeSharpness?: StrokeRoundness;\n },\n K extends Pick<T, keyof Omit<Required<T>, keyof ExcalidrawElement>>,\n>(\n element: T,\n extra: Pick<\n T,\n // This extra Pick<T, keyof K> ensure no excess properties are passed.\n // @ts-ignore TS complains here but type checks the call sites fine.\n keyof K\n > &\n Partial<Pick<ExcalidrawElement, \"type\" | \"x\" | \"y\" | \"customData\">>,\n): T => {\n const base: Pick<T, keyof ExcalidrawElement> = {\n type: extra.type || element.type,\n // all elements must have version > 0 so getSceneVersion() will pick up\n // newly added elements\n version: element.version || 1,\n versionNonce: element.versionNonce ?? 0,\n index: element.index ?? null,\n isDeleted: element.isDeleted ?? false,\n id: element.id || randomId(),\n fillStyle: element.fillStyle || DEFAULT_ELEMENT_PROPS.fillStyle,\n strokeWidth: element.strokeWidth || DEFAULT_ELEMENT_PROPS.strokeWidth,\n strokeStyle: element.strokeStyle ?? DEFAULT_ELEMENT_PROPS.strokeStyle,\n roughness: element.roughness ?? DEFAULT_ELEMENT_PROPS.roughness,\n opacity:\n element.opacity == null ? DEFAULT_ELEMENT_PROPS.opacity : element.opacity,\n angle: element.angle || (0 as Radians),\n x: extra.x ?? element.x ?? 0,\n y: extra.y ?? element.y ?? 0,\n strokeColor: element.strokeColor || DEFAULT_ELEMENT_PROPS.strokeColor,\n backgroundColor:\n element.backgroundColor || DEFAULT_ELEMENT_PROPS.backgroundColor,\n width: element.width || 0,\n height: element.height || 0,\n seed: element.seed ?? 1,\n groupIds: element.groupIds ?? [],\n frameId: element.frameId ?? null,\n roundness: element.roundness\n ? element.roundness\n : element.strokeSharpness === \"round\"\n ? {\n // for old elements that would now use adaptive radius algo,\n // use legacy algo instead\n type: isUsingAdaptiveRadius(element.type)\n ? ROUNDNESS.LEGACY\n : ROUNDNESS.PROPORTIONAL_RADIUS,\n }\n : null,\n boundElements: element.boundElementIds\n ? element.boundElementIds.map((id) => ({ type: \"arrow\", id }))\n : element.boundElements ?? [],\n updated: element.updated ?? getUpdatedTimestamp(),\n link: element.link ? normalizeLink(element.link) : null,\n locked: element.locked ?? false,\n };\n\n if (\"customData\" in element || \"customData\" in extra) {\n base.customData =\n \"customData\" in extra ? extra.customData : element.customData;\n }\n\n const ret = {\n // spread the original element properties to not lose unknown ones\n // for forward-compatibility\n ...element,\n // normalized properties\n ...base,\n ...getNormalizedDimensions(base),\n ...extra,\n } as unknown as T;\n\n // strip legacy props (migrated in previous steps)\n delete ret.strokeSharpness;\n delete ret.boundElementIds;\n\n return ret;\n};\n\nexport const restoreElement = (\n /** element to be restored */\n element: Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,\n /** all elements to be restored */\n targetElementsMap: Readonly<ElementsMap>,\n /** used for additional context */\n existingElementsMap: Readonly<ElementsMap> | null | undefined,\n opts?: {\n deleteInvisibleElements?: boolean;\n },\n): typeof element | null => {\n element = { ...element };\n\n switch (element.type) {\n case \"text\":\n // temp fix: cleanup legacy obsidian-excalidraw attribute else it'll\n // conflict when porting between the apps\n delete (element as any).rawText;\n\n let fontSize = element.fontSize;\n let fontFamily = element.fontFamily;\n if (\"font\" in element) {\n const [fontPx, _fontFamily]: [string, string] = (\n element as any\n ).font.split(\" \");\n fontSize = parseFloat(fontPx);\n fontFamily = getFontFamilyByName(_fontFamily);\n }\n const text = (typeof element.text === \"string\" && element.text) || \"\";\n\n // line-height might not be specified either when creating elements\n // programmatically, or when importing old diagrams.\n // For the latter we want to detect the original line height which\n // will likely differ from our per-font fixed line height we now use,\n // to maintain backward compatibility.\n const lineHeight =\n element.lineHeight ||\n (element.height\n ? // detect line-height from current element height and font-size\n detectLineHeight(element)\n : // no element height likely means programmatic use, so default\n // to a fixed line height\n getLineHeight(element.fontFamily));\n element = restoreElementWithProperties(element, {\n fontSize,\n fontFamily,\n text,\n textAlign: element.textAlign || DEFAULT_TEXT_ALIGN,\n verticalAlign: element.verticalAlign || DEFAULT_VERTICAL_ALIGN,\n containerId: element.containerId ?? null,\n originalText: element.originalText || text,\n autoResize: element.autoResize ?? true,\n lineHeight,\n });\n\n // if empty text, mark as deleted. We keep in array\n // for data integrity purposes (collab etc.)\n if (opts?.deleteInvisibleElements && !text && !element.isDeleted) {\n // TODO: we should not do this since it breaks sync / versioning when we exchange / apply just deltas and restore the elements (deletion isn't recorded)\n element = { ...element, originalText: text, isDeleted: true };\n element = bumpVersion(element);\n }\n\n return element;\n case \"freedraw\": {\n return restoreElementWithProperties(element, {\n points: element.points,\n simulatePressure: element.simulatePressure,\n pressures: element.pressures,\n });\n }\n case \"image\":\n return restoreElementWithProperties(element, {\n status: element.status || \"pending\",\n fileId: element.fileId,\n scale: element.scale || [1, 1],\n crop: element.crop ?? null,\n });\n case \"line\":\n // @ts-ignore LEGACY type\n // eslint-disable-next-line no-fallthrough\n case \"draw\":\n const { startArrowhead = null, endArrowhead = null } = element;\n let x = element.x;\n let y = element.y;\n let points = // migrate old arrow model to new one\n !Array.isArray(element.points) || element.points.length < 2\n ? [pointFrom(0, 0), pointFrom(element.width, element.height)]\n : element.points;\n\n if (points[0][0] !== 0 || points[0][1] !== 0) {\n ({ points, x, y } =\n LinearElementEditor.getNormalizeElementPointsAndCoords(element));\n }\n\n return restoreElementWithProperties(element, {\n type: \"line\",\n startBinding: null,\n endBinding: null,\n startArrowhead,\n endArrowhead,\n points,\n x,\n y,\n ...(isLineElement(element)\n ? {\n polygon: isValidPolygon(element.points)\n ? element.polygon ?? false\n : false,\n }\n : {}),\n ...getSizeFromPoints(points),\n });\n case \"arrow\": {\n const { startArrowhead = null, endArrowhead = \"arrow\" } = element;\n const x: number | undefined = element.x;\n const y: number | undefined = element.y;\n const points: readonly LocalPoint[] | undefined = // migrate old arrow model to new one\n !Array.isArray(element.points) || element.points.length < 2\n ? [pointFrom(0, 0), pointFrom(element.width, element.height)]\n : element.points;\n\n const base = {\n type: element.type,\n startBinding: repairBinding(\n element as ExcalidrawArrowElement,\n element.startBinding,\n targetElementsMap,\n existingElementsMap,\n \"start\",\n ),\n endBinding: repairBinding(\n element as ExcalidrawArrowElement,\n element.endBinding,\n targetElementsMap,\n existingElementsMap,\n \"end\",\n ),\n startArrowhead,\n endArrowhead,\n points,\n x,\n y,\n elbowed: (element as ExcalidrawArrowElement).elbowed,\n ...getSizeFromPoints(points),\n };\n\n // TODO: Separate arrow from linear element\n const restoredElement = isElbowArrow(element)\n ? restoreElementWithProperties(element as ExcalidrawElbowArrowElement, {\n ...base,\n elbowed: true,\n fixedSegments:\n element.fixedSegments?.length && base.points.length >= 4\n ? element.fixedSegments\n : null,\n startIsSpecial: element.startIsSpecial,\n endIsSpecial: element.endIsSpecial,\n })\n : restoreElementWithProperties(element as ExcalidrawArrowElement, base);\n\n return {\n ...restoredElement,\n ...LinearElementEditor.getNormalizeElementPointsAndCoords(\n restoredElement,\n ),\n };\n }\n\n // generic elements\n case \"ellipse\":\n case \"rectangle\":\n case \"diamond\":\n case \"iframe\":\n case \"embeddable\":\n return restoreElementWithProperties(element, {});\n case \"magicframe\":\n case \"frame\":\n return restoreElementWithProperties(element, {\n name: element.name ?? null,\n });\n\n // Don't use default case so as to catch a missing an element type case.\n // We also don't want to throw, but instead return void so we filter\n // out these unsupported elements from the restored array.\n }\n return null;\n};\n\n/**\n * Repairs container element's boundElements array by removing duplicates and\n * fixing containerId of bound elements if not present. Also removes any\n * bound elements that do not exist in the elements array.\n *\n * NOTE mutates elements.\n */\nconst repairContainerElement = (\n container: Mutable<ExcalidrawElement>,\n elementsMap: Map<string, Mutable<ExcalidrawElement>>,\n) => {\n if (container.boundElements) {\n // copy because we're not cloning on restore, and we don't want to mutate upstream\n const boundElements = container.boundElements.slice();\n\n // dedupe bindings & fix boundElement.containerId if not set already\n const boundIds = new Set<ExcalidrawElement[\"id\"]>();\n container.boundElements = boundElements.reduce(\n (\n acc: Mutable<NonNullable<ExcalidrawElement[\"boundElements\"]>>,\n binding,\n ) => {\n const boundElement = elementsMap.get(binding.id);\n if (boundElement && !boundIds.has(binding.id)) {\n boundIds.add(binding.id);\n\n if (boundElement.isDeleted) {\n return acc;\n }\n\n acc.push(binding);\n\n if (\n isTextElement(boundElement) &&\n // being slightly conservative here, preserving existing containerId\n // if defined, lest boundElements is stale\n !boundElement.containerId\n ) {\n (boundElement as Mutable<typeof boundElement>).containerId =\n container.id;\n }\n }\n return acc;\n },\n [],\n );\n }\n};\n\n/**\n * Repairs target bound element's container's boundElements array,\n * or removes contaienrId if container does not exist.\n *\n * NOTE mutates elements.\n */\nconst repairBoundElement = (\n boundElement: Mutable<ExcalidrawTextElement>,\n elementsMap: Map<string, Mutable<ExcalidrawElement>>,\n) => {\n const container = boundElement.containerId\n ? elementsMap.get(boundElement.containerId)\n : null;\n\n (boundElement as Mutable<typeof boundElement>).angle = (\n isArrowElement(container) ? 0 : container?.angle ?? 0\n ) as Radians;\n\n if (!container) {\n boundElement.containerId = null;\n return;\n }\n\n if (boundElement.isDeleted) {\n return;\n }\n\n if (\n container.boundElements &&\n !container.boundElements.find((binding) => binding.id === boundElement.id)\n ) {\n // copy because we're not cloning on restore, and we don't want to mutate upstream\n const boundElements = (\n container.boundElements || (container.boundElements = [])\n ).slice();\n boundElements.push({ type: \"text\", id: boundElement.id });\n container.boundElements = boundElements;\n }\n};\n\n/**\n * Remove an element's frameId if its containing frame is non-existent\n *\n * NOTE mutates elements.\n */\nconst repairFrameMembership = (\n element: Mutable<ExcalidrawElement>,\n elementsMap: Map<string, Mutable<ExcalidrawElement>>,\n) => {\n if (element.frameId) {\n const containingFrame = elementsMap.get(element.frameId);\n\n if (!containingFrame) {\n element.frameId = null;\n }\n }\n};\n\nexport const restoreElements = <T extends ExcalidrawElement>(\n targetElements: readonly T[] | undefined | null,\n /** used for additional context (e.g. repairing arrow bindings) */\n existingElements: Readonly<ElementsMapOrArray> | null | undefined,\n opts?:\n | {\n refreshDimensions?: boolean;\n repairBindings?: boolean;\n deleteInvisibleElements?: boolean;\n }\n | undefined,\n): CombineBrandsIfNeeded<T, OrderedExcalidrawElement> => {\n // used to detect duplicate top-level element ids\n const existingIds = new Set<string>();\n const targetElementsMap = arrayToMap(targetElements || []);\n const existingElementsMap = existingElements\n ? arrayToMap(existingElements)\n : null;\n const restoredElements = syncInvalidIndices(\n (targetElements || []).reduce((elements, element) => {\n // filtering out selection, which is legacy, no longer kept in elements,\n // and causing issues if retained\n if (element.type === \"selection\") {\n return elements;\n }\n\n let migratedElement: ExcalidrawElement | null = restoreElement(\n element,\n targetElementsMap,\n existingElementsMap,\n {\n deleteInvisibleElements: opts?.deleteInvisibleElements,\n },\n );\n if (migratedElement) {\n const localElement = existingElementsMap?.get(element.id);\n\n const shouldMarkAsDeleted =\n opts?.deleteInvisibleElements && isInvisiblySmallElement(element);\n\n if (shouldMarkAsDeleted) {\n migratedElement = bumpVersion(migratedElement, localElement?.version);\n }\n\n if (shouldMarkAsDeleted) {\n migratedElement = { ...migratedElement, isDeleted: true };\n }\n\n if (existingIds.has(migratedElement.id)) {\n migratedElement = { ...migratedElement, id: randomId() };\n }\n existingIds.add(migratedElement.id);\n\n elements.push(migratedElement);\n }\n\n return elements;\n }, [] as ExcalidrawElement[]),\n );\n\n if (!opts?.repairBindings) {\n return restoredElements as CombineBrandsIfNeeded<\n T,\n OrderedExcalidrawElement\n >;\n }\n\n // repair binding. Mutates elements.\n const restoredElementsMap = arrayToMap(restoredElements);\n for (const element of restoredElements) {\n if (element.frameId) {\n repairFrameMembership(element, restoredElementsMap);\n }\n\n if (isTextElement(element) && element.containerId) {\n repairBoundElement(element, restoredElementsMap);\n } else if (element.boundElements) {\n repairContainerElement(element, restoredElementsMap);\n }\n\n if (opts.refreshDimensions && isTextElement(element)) {\n Object.assign(\n element,\n refreshTextDimensions(\n element,\n getContainerElement(element, restoredElementsMap),\n restoredElementsMap,\n ),\n );\n }\n\n if (isLinearElement(element)) {\n if (\n element.startBinding &&\n (!restoredElementsMap.has(element.startBinding.elementId) ||\n !isArrowElement(element))\n ) {\n (element as Mutable<ExcalidrawLinearElement>).startBinding = null;\n }\n if (\n element.endBinding &&\n (!restoredElementsMap.has(element.endBinding.elementId) ||\n !isArrowElement(element))\n ) {\n (element as Mutable<ExcalidrawLinearElement>).endBinding = null;\n }\n }\n }\n\n // NOTE (mtolmacs): Temporary fix for extremely large arrows\n // Need to iterate again so we have attached text nodes in elementsMap\n return restoredElements.map((element) => {\n if (\n isElbowArrow(element) &&\n !isArrowBoundToElement(element) &&\n !validateElbowPoints(element.points)\n ) {\n return {\n ...element,\n ...updateElbowArrowPoints(\n element,\n restoredElementsMap as NonDeletedSceneElementsMap,\n {\n points: [\n pointFrom<LocalPoint>(0, 0),\n element.points[element.points.length - 1],\n ],\n },\n ),\n index: element.index,\n };\n }\n\n if (\n isElbowArrow(element) &&\n element.startBinding &&\n element.endBinding &&\n element.startBinding.elementId === element.endBinding.elementId &&\n element.points.length > 1 &&\n element.points.some(\n ([rx, ry]) => Math.abs(rx) > 1e6 || Math.abs(ry) > 1e6,\n )\n ) {\n console.error(\"Fixing self-bound elbow arrow\", element.id);\n const boundElement = restoredElementsMap.get(\n element.startBinding.elementId,\n );\n if (!boundElement) {\n console.error(\n \"Bound element not found\",\n element.startBinding.elementId,\n );\n return element;\n }\n\n return {\n ...element,\n x: boundElement.x + boundElement.width / 2,\n y: boundElement.y - 5,\n width: boundElement.width,\n height: boundElement.height,\n points: [\n pointFrom<LocalPoint>(0, 0),\n pointFrom<LocalPoint>(0, -10),\n pointFrom<LocalPoint>(boundElement.width / 2 + 5, -10),\n pointFrom<LocalPoint>(\n boundElement.width / 2 + 5,\n boundElement.height / 2 + 5,\n ),\n ],\n };\n }\n\n return element;\n }) as CombineBrandsIfNeeded<T, OrderedExcalidrawElement>;\n};\n\n/**\n * When replacing elements that may exist locally, this bumps their versions\n * to the local version + 1. Mainly for later reconciliation to work properly.\n *\n * See https://github.com/excalidraw/excalidraw/issues/3795\n *\n * Generally use this on editor boundaries (importing from file etc.), though\n * it does not apply universally (e.g. we don't want to do this for collab\n * updates).\n */\nexport const bumpElementVersions = <T extends ExcalidrawElement>(\n targetElements: readonly T[],\n localElements: Readonly<ElementsMapOrArray> | null | undefined,\n) => {\n const localElementsMap = localElements ? arrayToMap(localElements) : null;\n\n return targetElements.map((element) => {\n const localElement = localElementsMap?.get(element.id);\n\n if (\n localElement &&\n (localElement.version > element.version ||\n // same versions but different versionNonce means different edits\n // (this often means the element was bumped during restore e.g. due\n // to re-indexing, and the original element was modified elsewhere\n // and supplied as localElements)\n (localElement.version === element.version &&\n localElement.versionNonce !== element.versionNonce))\n ) {\n return bumpVersion(element, localElement.version);\n }\n return element;\n });\n};\n\nconst coalesceAppStateValue = <\n T extends keyof ReturnType<typeof getDefaultAppState>,\n>(\n key: T,\n appState: Exclude<ImportedDataState[\"appState\"], null | undefined>,\n defaultAppState: ReturnType<typeof getDefaultAppState>,\n) => {\n const value = appState[key];\n // NOTE the value! assertion is needed in TS 4.5.5 (fixed in newer versions)\n return value !== undefined ? value! : defaultAppState[key];\n};\n\nconst LegacyAppStateMigrations: {\n [K in keyof LegacyAppState]: (\n ImportedDataState: Exclude<ImportedDataState[\"appState\"], null | undefined>,\n defaultAppState: ReturnType<typeof getDefaultAppState>,\n ) => [LegacyAppState[K][1], AppState[LegacyAppState[K][1]]];\n} = {\n isSidebarDocked: (appState, defaultAppState) => {\n return [\n \"defaultSidebarDockedPreference\",\n appState.isSidebarDocked ??\n coalesceAppStateValue(\n \"defaultSidebarDockedPreference\",\n appState,\n defaultAppState,\n ),\n ];\n },\n};\n\nexport const restoreAppState = (\n appState: ImportedDataState[\"appState\"],\n localAppState: Partial<AppState> | null | undefined,\n): RestoredAppState => {\n appState = appState || {};\n const defaultAppState = getDefaultAppState();\n const nextAppState = {} as typeof defaultAppState;\n\n // first, migrate all legacy AppState properties to new ones. We do it\n // in one go before migrate the rest of the properties in case the new ones\n // depend on checking any other key (i.e. they are coupled)\n for (const legacyKey of Object.keys(\n LegacyAppStateMigrations,\n ) as (keyof typeof LegacyAppStateMigrations)[]) {\n if (legacyKey in appState) {\n const [nextKey, nextValue] = LegacyAppStateMigrations[legacyKey](\n appState,\n defaultAppState,\n );\n (nextAppState as any)[nextKey] = nextValue;\n }\n }\n\n for (const [key, defaultValue] of Object.entries(defaultAppState) as [\n keyof typeof defaultAppState,\n any,\n ][]) {\n // if AppState contains a legacy key, prefer that one and migrate its\n // value to the new one\n const suppliedValue = appState[key];\n\n const localValue = localAppState ? localAppState[key] : undefined;\n (nextAppState as any)[key] =\n suppliedValue !== undefined\n ? suppliedValue\n : localValue !== undefined\n ? localValue\n : defaultValue;\n }\n\n return {\n ...nextAppState,\n cursorButton: localAppState?.cursorButton || \"up\",\n // reset on fresh restore so as to hide the UI button if penMode not active\n penDetected:\n localAppState?.penDetected ??\n (appState.penMode ? appState.penDetected ?? false : false),\n activeTool: {\n ...updateActiveTool(\n defaultAppState,\n nextAppState.activeTool.type &&\n AllowedExcalidrawActiveTools[nextAppState.activeTool.type]\n ? nextAppState.activeTool\n : { type: \"selection\" },\n ),\n lastActiveTool: null,\n locked: nextAppState.activeTool.locked ?? false,\n },\n // Migrates from previous version where appState.zoom was a number\n zoom: {\n value: getNormalizedZoom(\n isFiniteNumber(appState.zoom)\n ? appState.zoom\n : appState.zoom?.value ?? defaultAppState.zoom.value,\n ),\n },\n openSidebar:\n // string (legacy)\n typeof (appState.openSidebar as any as string) === \"string\"\n ? { name: DEFAULT_SIDEBAR.name }\n : nextAppState.openSidebar,\n gridSize: getNormalizedGridSize(\n isFiniteNumber(appState.gridSize) ? appState.gridSize : DEFAULT_GRID_SIZE,\n ),\n gridStep: getNormalizedGridStep(\n isFiniteNumber(appState.gridStep) ? appState.gridStep : DEFAULT_GRID_STEP,\n ),\n editingFrame: null,\n };\n};\n\nconst restoreLibraryItem = (libraryItem: LibraryItem) => {\n const elements = restoreElements(\n getNonDeletedElements(libraryItem.elements),\n null,\n );\n return elements.length ? { ...libraryItem, elements } : null;\n};\n\nexport const restoreLibraryItems = (\n libraryItems: ImportedDataState[\"libraryItems\"] = [],\n defaultStatus: LibraryItem[\"status\"],\n) => {\n const restoredItems: LibraryItem[] = [];\n for (const item of libraryItems) {\n // migrate older libraries\n if (Array.isArray(item)) {\n const restoredItem = restoreLibraryItem({\n status: defaultStatus,\n elements: item,\n id: randomId(),\n created: Date.now(),\n });\n if (restoredItem) {\n restoredItems.push(restoredItem);\n }\n } else {\n const _item = item as MarkOptional<\n LibraryItem,\n \"id\" | \"status\" | \"created\"\n >;\n const restoredItem = restoreLibraryItem({\n ..._item,\n id: _item.id || randomId(),\n status: _item.status || defaultStatus,\n created: _item.created || Date.now(),\n });\n if (restoredItem) {\n restoredItems.push(restoredItem);\n }\n }\n }\n return restoredItems;\n};\n"],
|
|
5
|
+
"mappings": "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,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,0BAA0B,EAAE;AAAA,EACrE,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,cAAc,EAAE;AAAA,EACzD,EAAE,KAAK,0DAAK,aAAa,EAAE,cAAc,c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",
|
|
6
|
+
"names": ["curve", "lineSegment", "ellipse", "line", "distance", "polygon", "polygon", "UserIdleState", "newValues", "nanoid", "rough", "pointsOnBezierCurves", "crop", "shouldMaintainAspectRatio", "distance", "line", "calculate", "line", "shouldMaintainAspectRatio", "index", "shouldTestInside", "distance", "line", "offset", "corners", "p", "start", "end", "distance", "duplicateElement", "element", "distance", "line", "EPSILON", "selectGroupsForSelectedElements", "element", "arrowheadPoints", "options", "distance", "getSvgPathFromStroke", "curve", "pointsOnBezierCurves", "segments", "ellipse", "minX", "minY", "maxX", "maxY", "distance", "x3", "y3", "x4", "y4", "rough", "coords", "curve", "x", "y", "elements", "element", "elements", "element", "newElement", "duplicateElement", "lowerBound", "upperBound", "i", "current", "delta", "step", "pos", "newElement", "shouldMaintainAspectRatio", "shouldResizeFromCenter", "timeMatch", "_VERTICAL_OFFSET", "y", "x", "shouldRotateWithDiscreteAngle", "shouldResizeFromCenter", "shouldMaintainAspectRatio", "metrics", "width", "height", "id", "arrow", "getNonDeletedElements", "rough", "mimeTypes", "workerPool", "fontFaces", "throttle", "x1", "y1", "x2", "y2", "element", "opacity", "uncroppedWidth", "uncroppedHeight", "rough", "startArrowhead", "endArrowhead", "x", "y", "points", "getNonDeletedElements", "nanoid", "chunk"]
|
|
7
|
+
}
|