@excalidraw/excalidraw 0.17.1-1ed53b1 → 0.17.1-22b3927

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.
Files changed (122) hide show
  1. package/dist/browser/dev/excalidraw-assets-dev/{chunk-JKPJV7MZ.js → chunk-Q6A4M3MN.js} +4 -2
  2. package/dist/browser/dev/excalidraw-assets-dev/chunk-Q6A4M3MN.js.map +7 -0
  3. package/dist/browser/dev/excalidraw-assets-dev/{chunk-OKAZAA6U.js → chunk-VC7RRIDZ.js} +230 -93
  4. package/dist/browser/dev/excalidraw-assets-dev/chunk-VC7RRIDZ.js.map +7 -0
  5. package/dist/browser/dev/excalidraw-assets-dev/{dist-ITJNUBZF.js → dist-6QVAH5JA.js} +36 -14
  6. package/dist/browser/dev/excalidraw-assets-dev/dist-6QVAH5JA.js.map +7 -0
  7. package/dist/browser/dev/excalidraw-assets-dev/{en-BF4XUPIZ.js → en-Y27YPU72.js} +2 -2
  8. package/dist/browser/dev/excalidraw-assets-dev/{image-LVS32KQQ.js → image-J7S3ALXP.js} +2 -2
  9. package/dist/browser/dev/index.js +335 -116
  10. package/dist/browser/dev/index.js.map +4 -4
  11. package/dist/browser/prod/excalidraw-assets/chunk-CWO763YJ.js +55 -0
  12. package/dist/browser/prod/excalidraw-assets/{chunk-O4AI3NNG.js → chunk-IZMZ6RPD.js} +1 -1
  13. package/dist/browser/prod/excalidraw-assets/dist-567JAXHK.js +7 -0
  14. package/dist/browser/prod/excalidraw-assets/{en-N7CLNF6C.js → en-GSUSWMSH.js} +1 -1
  15. package/dist/browser/prod/excalidraw-assets/image-SZBFRCU2.js +1 -0
  16. package/dist/browser/prod/index.js +24 -24
  17. package/dist/dev/{en-UQDDYCH7.json → en-OIPCBIOA.json} +3 -1
  18. package/dist/dev/index.js +576 -207
  19. package/dist/dev/index.js.map +4 -4
  20. package/dist/excalidraw/actions/actionAddToLibrary.d.ts +3 -3
  21. package/dist/excalidraw/actions/actionAlign.d.ts +6 -6
  22. package/dist/excalidraw/actions/actionBoundText.d.ts +3 -3
  23. package/dist/excalidraw/actions/actionBoundText.js +3 -1
  24. package/dist/excalidraw/actions/actionCanvas.d.ts +13 -13
  25. package/dist/excalidraw/actions/actionClipboard.d.ts +12 -12
  26. package/dist/excalidraw/actions/actionDeleteSelected.d.ts +3 -3
  27. package/dist/excalidraw/actions/actionDistribute.d.ts +2 -2
  28. package/dist/excalidraw/actions/actionDuplicateSelection.d.ts +1 -1
  29. package/dist/excalidraw/actions/actionElementLock.d.ts +2 -2
  30. package/dist/excalidraw/actions/actionExport.d.ts +11 -11
  31. package/dist/excalidraw/actions/actionFinalize.d.ts +2 -2
  32. package/dist/excalidraw/actions/actionFlip.d.ts +2 -2
  33. package/dist/excalidraw/actions/actionFrame.d.ts +312 -4
  34. package/dist/excalidraw/actions/actionGroup.d.ts +312 -2
  35. package/dist/excalidraw/actions/actionHistory.js +4 -4
  36. package/dist/excalidraw/actions/actionLinearEditor.d.ts +1 -1
  37. package/dist/excalidraw/actions/actionLink.d.ts +1 -1
  38. package/dist/excalidraw/actions/actionMenu.d.ts +3 -3
  39. package/dist/excalidraw/actions/actionNavigate.d.ts +2 -2
  40. package/dist/excalidraw/actions/actionProperties.d.ts +13 -13
  41. package/dist/excalidraw/actions/actionProperties.js +1 -1
  42. package/dist/excalidraw/actions/actionSelectAll.d.ts +1 -1
  43. package/dist/excalidraw/actions/actionStyles.d.ts +5 -2
  44. package/dist/excalidraw/actions/actionTextAutoResize.d.ts +17 -0
  45. package/dist/excalidraw/actions/actionTextAutoResize.js +38 -0
  46. package/dist/excalidraw/actions/actionToggleGridMode.d.ts +1 -1
  47. package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +1 -1
  48. package/dist/excalidraw/actions/actionToggleStats.d.ts +1 -1
  49. package/dist/excalidraw/actions/actionToggleViewMode.d.ts +1 -1
  50. package/dist/excalidraw/actions/actionToggleZenMode.d.ts +1 -1
  51. package/dist/excalidraw/actions/actionZindex.d.ts +4 -4
  52. package/dist/excalidraw/actions/types.d.ts +1 -1
  53. package/dist/excalidraw/change.js +13 -6
  54. package/dist/excalidraw/components/Actions.js +1 -1
  55. package/dist/excalidraw/components/App.d.ts +2 -2
  56. package/dist/excalidraw/components/App.js +133 -51
  57. package/dist/excalidraw/components/ButtonIconSelect.js +1 -1
  58. package/dist/excalidraw/components/CheckboxItem.js +1 -1
  59. package/dist/excalidraw/components/CommandPalette/CommandPalette.js +2 -2
  60. package/dist/excalidraw/components/ContextMenu.js +1 -1
  61. package/dist/excalidraw/components/Dialog.js +1 -1
  62. package/dist/excalidraw/components/FollowMode/FollowMode.js +1 -1
  63. package/dist/excalidraw/components/IconPicker.js +2 -2
  64. package/dist/excalidraw/components/LayerUI.js +2 -2
  65. package/dist/excalidraw/components/MobileMenu.js +1 -1
  66. package/dist/excalidraw/components/PasteChartDialog.js +1 -1
  67. package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +3 -2
  68. package/dist/excalidraw/components/canvases/InteractiveCanvas.js +4 -2
  69. package/dist/excalidraw/components/canvases/StaticCanvas.d.ts +1 -1
  70. package/dist/excalidraw/components/canvases/StaticCanvas.js +2 -2
  71. package/dist/excalidraw/components/icons.js +6 -2
  72. package/dist/excalidraw/constants.d.ts +1 -0
  73. package/dist/excalidraw/constants.js +5 -0
  74. package/dist/excalidraw/data/restore.js +3 -0
  75. package/dist/excalidraw/element/dragElements.d.ts +2 -2
  76. package/dist/excalidraw/element/dragElements.js +27 -3
  77. package/dist/excalidraw/element/embeddable.d.ts +1 -1
  78. package/dist/excalidraw/element/index.d.ts +1 -1
  79. package/dist/excalidraw/element/index.js +1 -1
  80. package/dist/excalidraw/element/mutateElement.d.ts +1 -1
  81. package/dist/excalidraw/element/mutateElement.js +5 -3
  82. package/dist/excalidraw/element/newElement.d.ts +2 -5
  83. package/dist/excalidraw/element/newElement.js +16 -14
  84. package/dist/excalidraw/element/resizeElements.js +73 -21
  85. package/dist/excalidraw/element/resizeTest.js +2 -4
  86. package/dist/excalidraw/element/textElement.d.ts +1 -0
  87. package/dist/excalidraw/element/textElement.js +11 -3
  88. package/dist/excalidraw/element/textWysiwyg.d.ts +10 -4
  89. package/dist/excalidraw/element/textWysiwyg.js +38 -17
  90. package/dist/excalidraw/element/transformHandles.js +0 -10
  91. package/dist/excalidraw/element/types.d.ts +7 -0
  92. package/dist/excalidraw/fractionalIndex.js +2 -4
  93. package/dist/excalidraw/locales/en.json +3 -1
  94. package/dist/excalidraw/mermaid.d.ts +2 -0
  95. package/dist/excalidraw/mermaid.js +28 -0
  96. package/dist/excalidraw/renderer/interactiveScene.d.ts +1 -1
  97. package/dist/excalidraw/renderer/interactiveScene.js +31 -5
  98. package/dist/excalidraw/renderer/renderElement.d.ts +2 -2
  99. package/dist/excalidraw/renderer/renderElement.js +2 -2
  100. package/dist/excalidraw/scene/Fonts.d.ts +1 -3
  101. package/dist/excalidraw/scene/Fonts.js +6 -12
  102. package/dist/excalidraw/scene/Renderer.d.ts +1 -1
  103. package/dist/excalidraw/scene/Renderer.js +2 -3
  104. package/dist/excalidraw/scene/Scene.d.ts +10 -4
  105. package/dist/excalidraw/scene/Scene.js +14 -8
  106. package/dist/excalidraw/scene/export.js +1 -1
  107. package/dist/excalidraw/scene/types.d.ts +2 -1
  108. package/dist/excalidraw/snapping.js +2 -1
  109. package/dist/excalidraw/store.d.ts +32 -2
  110. package/dist/excalidraw/store.js +27 -0
  111. package/dist/excalidraw/types.d.ts +1 -0
  112. package/dist/prod/{en-UQDDYCH7.json → en-OIPCBIOA.json} +3 -1
  113. package/dist/prod/index.js +42 -42
  114. package/package.json +2 -2
  115. package/dist/browser/dev/excalidraw-assets-dev/chunk-JKPJV7MZ.js.map +0 -7
  116. package/dist/browser/dev/excalidraw-assets-dev/chunk-OKAZAA6U.js.map +0 -7
  117. package/dist/browser/dev/excalidraw-assets-dev/dist-ITJNUBZF.js.map +0 -7
  118. package/dist/browser/prod/excalidraw-assets/chunk-SXBDZOS3.js +0 -55
  119. package/dist/browser/prod/excalidraw-assets/dist-54276HPL.js +0 -6
  120. package/dist/browser/prod/excalidraw-assets/image-VAGBVQ3G.js +0 -1
  121. /package/dist/browser/dev/excalidraw-assets-dev/{en-BF4XUPIZ.js.map → en-Y27YPU72.js.map} +0 -0
  122. /package/dist/browser/dev/excalidraw-assets-dev/{image-LVS32KQQ.js.map → image-J7S3ALXP.js.map} +0 -0
package/dist/dev/index.js CHANGED
@@ -147,7 +147,7 @@ var init_colors = __esm({
147
147
  });
148
148
 
149
149
  // constants.ts
150
- var isDarwin, isWindows, isAndroid, isFirefox, isChrome, isSafari, isIOS, isBrave, supportsResizeObserver, APP_NAME, DRAGGING_THRESHOLD, LINE_CONFIRM_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, TEXT_TO_CENTER_SNAP_THRESHOLD, SHIFT_LOCKING_ANGLE, DEFAULT_LASER_COLOR, CURSOR_TYPE, POINTER_BUTTON, POINTER_EVENTS, YOUTUBE_STATES, ENV, CLASSES, FONT_FAMILY, THEME, FRAME_STYLE, WINDOWS_EMOJI_FALLBACK_FONT, MIN_FONT_SIZE, DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, DEFAULT_TRANSFORM_HANDLE_SPACING, SIDE_RESIZING_THRESHOLD, EPSILON, DEFAULT_COLLISION_THRESHOLD, COLOR_WHITE, COLOR_CHARCOAL_BLACK, COLOR_VOICE_CALL, GRID_SIZE, IMAGE_MIME_TYPES, ALLOWED_PASTE_MIME_TYPES, MIME_TYPES, EXPORT_IMAGE_TYPES, EXPORT_DATA_TYPES, EXPORT_SOURCE, IMAGE_RENDER_TIMEOUT, TAP_TWICE_TIMEOUT, TOUCH_CTX_MENU_TIMEOUT, SCROLL_TIMEOUT, ZOOM_STEP, MIN_ZOOM, MAX_ZOOM, HYPERLINK_TOOLTIP_DELAY, THEME_FILTER, URL_QUERY_KEYS, URL_HASH_KEYS, DEFAULT_UI_OPTIONS, MQ_MAX_WIDTH_PORTRAIT, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_HEIGHT_LANDSCAPE, MQ_RIGHT_SIDEBAR_MIN_WIDTH, LIBRARY_SIDEBAR_WIDTH, MAX_DECIMALS_FOR_SVG_EXPORT, EXPORT_SCALES, DEFAULT_EXPORT_PADDING, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, MAX_ALLOWED_FILE_BYTES, SVG_NS, VERSIONS, BOUND_TEXT_PADDING, ARROW_LABEL_WIDTH_FRACTION, ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, VERTICAL_ALIGN, TEXT_ALIGN, ELEMENT_READY_TO_ERASE_OPACITY, DEFAULT_PROPORTIONAL_RADIUS, DEFAULT_ADAPTIVE_RADIUS, ROUNDNESS, ROUGHNESS, STROKE_WIDTH, DEFAULT_ELEMENT_PROPS, LIBRARY_SIDEBAR_TAB, DEFAULT_SIDEBAR, LIBRARY_DISABLED_TYPES, TOOL_TYPE, EDITOR_LS_KEYS, DEFAULT_FILENAME;
150
+ var isDarwin, isWindows, isAndroid, isFirefox, isChrome, isSafari, isIOS, isBrave, supportsResizeObserver, APP_NAME, TEXT_AUTOWRAP_THRESHOLD, DRAGGING_THRESHOLD, LINE_CONFIRM_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, TEXT_TO_CENTER_SNAP_THRESHOLD, SHIFT_LOCKING_ANGLE, DEFAULT_LASER_COLOR, CURSOR_TYPE, POINTER_BUTTON, POINTER_EVENTS, YOUTUBE_STATES, ENV, CLASSES, FONT_FAMILY, THEME, FRAME_STYLE, WINDOWS_EMOJI_FALLBACK_FONT, MIN_FONT_SIZE, DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, DEFAULT_TRANSFORM_HANDLE_SPACING, SIDE_RESIZING_THRESHOLD, EPSILON, DEFAULT_COLLISION_THRESHOLD, COLOR_WHITE, COLOR_CHARCOAL_BLACK, COLOR_VOICE_CALL, GRID_SIZE, IMAGE_MIME_TYPES, ALLOWED_PASTE_MIME_TYPES, MIME_TYPES, EXPORT_IMAGE_TYPES, EXPORT_DATA_TYPES, EXPORT_SOURCE, IMAGE_RENDER_TIMEOUT, TAP_TWICE_TIMEOUT, TOUCH_CTX_MENU_TIMEOUT, SCROLL_TIMEOUT, ZOOM_STEP, MIN_ZOOM, MAX_ZOOM, HYPERLINK_TOOLTIP_DELAY, THEME_FILTER, URL_QUERY_KEYS, URL_HASH_KEYS, DEFAULT_UI_OPTIONS, MQ_MAX_WIDTH_PORTRAIT, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_HEIGHT_LANDSCAPE, MQ_RIGHT_SIDEBAR_MIN_WIDTH, LIBRARY_SIDEBAR_WIDTH, MAX_DECIMALS_FOR_SVG_EXPORT, EXPORT_SCALES, DEFAULT_EXPORT_PADDING, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, MAX_ALLOWED_FILE_BYTES, SVG_NS, VERSIONS, BOUND_TEXT_PADDING, ARROW_LABEL_WIDTH_FRACTION, ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, VERTICAL_ALIGN, TEXT_ALIGN, ELEMENT_READY_TO_ERASE_OPACITY, DEFAULT_PROPORTIONAL_RADIUS, DEFAULT_ADAPTIVE_RADIUS, ROUNDNESS, ROUGHNESS, STROKE_WIDTH, DEFAULT_ELEMENT_PROPS, LIBRARY_SIDEBAR_TAB, DEFAULT_SIDEBAR, LIBRARY_DISABLED_TYPES, TOOL_TYPE, EDITOR_LS_KEYS, DEFAULT_FILENAME;
151
151
  var init_constants = __esm({
152
152
  "constants.ts"() {
153
153
  "use strict";
@@ -165,6 +165,7 @@ var init_constants = __esm({
165
165
  isBrave = () => navigator.brave?.isBrave?.name === "isBrave";
166
166
  supportsResizeObserver = typeof window !== "undefined" && "ResizeObserver" in window;
167
167
  APP_NAME = "Excalidraw";
168
+ TEXT_AUTOWRAP_THRESHOLD = 36;
168
169
  DRAGGING_THRESHOLD = 10;
169
170
  LINE_CONFIRM_THRESHOLD = 8;
170
171
  ELEMENT_SHIFT_TRANSLATE_AMOUNT = 5;
@@ -1209,18 +1210,10 @@ var init_fractionalIndex = __esm({
1209
1210
  const indicesGroups = [];
1210
1211
  let i = 0;
1211
1212
  while (i < elements.length) {
1212
- if (movedElements.has(elements[i].id) && !isValidFractionalIndex(
1213
- elements[i]?.index,
1214
- elements[i - 1]?.index,
1215
- elements[i + 1]?.index
1216
- )) {
1213
+ if (movedElements.has(elements[i].id)) {
1217
1214
  const indicesGroup = [i - 1, i];
1218
1215
  while (++i < elements.length) {
1219
- if (!(movedElements.has(elements[i].id) && !isValidFractionalIndex(
1220
- elements[i]?.index,
1221
- elements[i - 1]?.index,
1222
- elements[i + 1]?.index
1223
- ))) {
1216
+ if (!movedElements.has(elements[i].id)) {
1224
1217
  break;
1225
1218
  }
1226
1219
  indicesGroup.push(i);
@@ -1412,7 +1405,16 @@ var init_Scene = __esm({
1412
1405
  elements: null,
1413
1406
  cache: /* @__PURE__ */ new Map()
1414
1407
  };
1415
- versionNonce;
1408
+ /**
1409
+ * Random integer regenerated each scene update.
1410
+ *
1411
+ * Does not relate to elements versions, it's only a renderer
1412
+ * cache-invalidation nonce at the moment.
1413
+ */
1414
+ sceneNonce;
1415
+ getSceneNonce() {
1416
+ return this.sceneNonce;
1417
+ }
1416
1418
  getNonDeletedElementsMap() {
1417
1419
  return this.nonDeletedElementsMap;
1418
1420
  }
@@ -1457,9 +1459,6 @@ var init_Scene = __esm({
1457
1459
  getElement(id) {
1458
1460
  return this.elementsMap.get(id) || null;
1459
1461
  }
1460
- getVersionNonce() {
1461
- return this.versionNonce;
1462
- }
1463
1462
  getNonDeletedElement(id) {
1464
1463
  const element = this.getElement(id);
1465
1464
  if (element && isNonDeletedElement(element)) {
@@ -1516,15 +1515,15 @@ var init_Scene = __esm({
1516
1515
  this.nonDeletedElementsMap = nonDeletedElements.elementsMap;
1517
1516
  this.frames = nextFrameLikes;
1518
1517
  this.nonDeletedFramesLikes = getNonDeletedElements(this.frames).elements;
1519
- this.informMutation();
1518
+ this.triggerUpdate();
1520
1519
  }
1521
- informMutation() {
1522
- this.versionNonce = randomInteger();
1520
+ triggerUpdate() {
1521
+ this.sceneNonce = randomInteger();
1523
1522
  for (const callback of Array.from(this.callbacks)) {
1524
1523
  callback();
1525
1524
  }
1526
1525
  }
1527
- addCallback(cb) {
1526
+ onUpdate(cb) {
1528
1527
  if (this.callbacks.has(cb)) {
1529
1528
  throw new Error();
1530
1529
  }
@@ -4996,7 +4995,7 @@ var init_containerCache = __esm({
4996
4995
  });
4997
4996
 
4998
4997
  // element/textElement.ts
4999
- var normalizeText, splitIntoLines, redrawTextBoundingBox, bindTextToShapeAfterDuplication, handleBindTextResize, computeBoundTextPosition, measureText, detectLineHeight, getLineHeightInPx, getVerticalOffset, getApproxMinLineHeight, canvas, getLineWidth, getTextWidth, getTextHeight, parseTokens, wrapText, charWidth, DUMMY_TEXT, getApproxMinLineWidth, getMaxCharWidth, getBoundTextElementId, getBoundTextElement, getContainerElement, getContainerCenter, getContainerCoords, getTextElementAngle, shouldAllowVerticalAlign, suppportsHorizontalAlign, VALID_CONTAINER_TYPES, isValidTextContainer, computeContainerDimensionForBoundText, getBoundTextMaxWidth, getBoundTextMaxHeight, isMeasureTextSupported, DEFAULT_LINE_HEIGHT, FONT_METRICS, getDefaultLineHeight;
4998
+ var normalizeText, splitIntoLines, redrawTextBoundingBox, bindTextToShapeAfterDuplication, handleBindTextResize, computeBoundTextPosition, measureText, detectLineHeight, getLineHeightInPx, getVerticalOffset, getApproxMinLineHeight, canvas, getLineWidth, getTextWidth, getTextHeight, parseTokens, wrapText, charWidth, DUMMY_TEXT, getApproxMinLineWidth, getMaxCharWidth, getBoundTextElementId, getBoundTextElement, getContainerElement, getContainerCenter, getContainerCoords, getTextElementAngle, shouldAllowVerticalAlign, suppportsHorizontalAlign, VALID_CONTAINER_TYPES, isValidTextContainer, computeContainerDimensionForBoundText, getBoundTextMaxWidth, getBoundTextMaxHeight, isMeasureTextSupported, DEFAULT_LINE_HEIGHT, FONT_METRICS, getDefaultLineHeight, getMinTextElementWidth;
5000
4999
  var init_textElement = __esm({
5001
5000
  "element/textElement.ts"() {
5002
5001
  "use strict";
@@ -5025,8 +5024,8 @@ var init_textElement = __esm({
5025
5024
  angle: container?.angle ?? textElement.angle
5026
5025
  };
5027
5026
  boundTextUpdates.text = textElement.text;
5028
- if (container) {
5029
- maxWidth = getBoundTextMaxWidth(container, textElement);
5027
+ if (container || !textElement.autoResize) {
5028
+ maxWidth = container ? getBoundTextMaxWidth(container, textElement) : textElement.width;
5030
5029
  boundTextUpdates.text = wrapText(
5031
5030
  textElement.originalText,
5032
5031
  getFontString(textElement),
@@ -5038,7 +5037,9 @@ var init_textElement = __esm({
5038
5037
  getFontString(textElement),
5039
5038
  textElement.lineHeight
5040
5039
  );
5041
- boundTextUpdates.width = metrics.width;
5040
+ if (textElement.autoResize) {
5041
+ boundTextUpdates.width = metrics.width;
5042
+ }
5042
5043
  boundTextUpdates.height = metrics.height;
5043
5044
  if (container) {
5044
5045
  const maxContainerHeight = getBoundTextMaxHeight(
@@ -5583,6 +5584,9 @@ var init_textElement = __esm({
5583
5584
  }
5584
5585
  return DEFAULT_LINE_HEIGHT[DEFAULT_FONT_FAMILY];
5585
5586
  };
5587
+ getMinTextElementWidth = (font, lineHeight) => {
5588
+ return measureText("", font, lineHeight).width + BOUND_TEXT_PADDING * 2;
5589
+ };
5586
5590
  }
5587
5591
  });
5588
5592
 
@@ -6757,7 +6761,7 @@ var init_cursor = __esm({
6757
6761
  });
6758
6762
 
6759
6763
  // element/newElement.ts
6760
- var _newElementBase, newElement, newEmbeddableElement, newIframeElement, newFrameElement, newMagicFrameElement, getTextElementPositionOffsets, newTextElement, getAdjustedDimensions, refreshTextDimensions, updateTextElement, newFreeDrawElement, newLinearElement, newImageElement, _deepCopyElement, deepCopyElement, regenerateId, duplicateElement, duplicateElements;
6764
+ var _newElementBase, newElement, newEmbeddableElement, newIframeElement, newFrameElement, newMagicFrameElement, getTextElementPositionOffsets, newTextElement, getAdjustedDimensions, refreshTextDimensions, newFreeDrawElement, newLinearElement, newImageElement, _deepCopyElement, deepCopyElement, regenerateId, duplicateElement, duplicateElements;
6761
6765
  var init_newElement = __esm({
6762
6766
  "element/newElement.ts"() {
6763
6767
  "use strict";
@@ -6877,36 +6881,41 @@ var init_newElement = __esm({
6877
6881
  { textAlign, verticalAlign },
6878
6882
  metrics
6879
6883
  );
6884
+ const textElementProps = {
6885
+ ..._newElementBase("text", opts),
6886
+ text,
6887
+ fontSize,
6888
+ fontFamily,
6889
+ textAlign,
6890
+ verticalAlign,
6891
+ x: opts.x - offsets.x,
6892
+ y: opts.y - offsets.y,
6893
+ width: metrics.width,
6894
+ height: metrics.height,
6895
+ containerId: opts.containerId || null,
6896
+ originalText: opts.originalText ?? text,
6897
+ autoResize: opts.autoResize ?? true,
6898
+ lineHeight
6899
+ };
6880
6900
  const textElement = newElementWith(
6881
- {
6882
- ..._newElementBase("text", opts),
6883
- text,
6884
- fontSize,
6885
- fontFamily,
6886
- textAlign,
6887
- verticalAlign,
6888
- x: opts.x - offsets.x,
6889
- y: opts.y - offsets.y,
6890
- width: metrics.width,
6891
- height: metrics.height,
6892
- containerId: opts.containerId || null,
6893
- originalText: text,
6894
- lineHeight
6895
- },
6901
+ textElementProps,
6896
6902
  {}
6897
6903
  );
6898
6904
  return textElement;
6899
6905
  };
6900
6906
  getAdjustedDimensions = (element, elementsMap, nextText) => {
6901
- const { width: nextWidth, height: nextHeight } = measureText(
6907
+ let { width: nextWidth, height: nextHeight } = measureText(
6902
6908
  nextText,
6903
6909
  getFontString(element),
6904
6910
  element.lineHeight
6905
6911
  );
6912
+ if (!element.autoResize) {
6913
+ nextWidth = element.width;
6914
+ }
6906
6915
  const { textAlign, verticalAlign } = element;
6907
6916
  let x;
6908
6917
  let y;
6909
- if (textAlign === "center" && verticalAlign === VERTICAL_ALIGN.MIDDLE && !element.containerId) {
6918
+ if (textAlign === "center" && verticalAlign === VERTICAL_ALIGN.MIDDLE && !element.containerId && element.autoResize) {
6910
6919
  const prevMetrics = measureText(
6911
6920
  element.text,
6912
6921
  getFontString(element),
@@ -6956,27 +6965,16 @@ var init_newElement = __esm({
6956
6965
  if (textElement.isDeleted) {
6957
6966
  return;
6958
6967
  }
6959
- if (container) {
6968
+ if (container || !textElement.autoResize) {
6960
6969
  text = wrapText(
6961
6970
  text,
6962
6971
  getFontString(textElement),
6963
- getBoundTextMaxWidth(container, textElement)
6972
+ container ? getBoundTextMaxWidth(container, textElement) : textElement.width
6964
6973
  );
6965
6974
  }
6966
6975
  const dimensions = getAdjustedDimensions(textElement, elementsMap, text);
6967
6976
  return { text, ...dimensions };
6968
6977
  };
6969
- updateTextElement = (textElement, container, elementsMap, {
6970
- text,
6971
- isDeleted,
6972
- originalText
6973
- }) => {
6974
- return newElementWith(textElement, {
6975
- originalText,
6976
- isDeleted: isDeleted ?? textElement.isDeleted,
6977
- ...refreshTextDimensions(textElement, container, elementsMap, originalText)
6978
- });
6979
- };
6980
6978
  newFreeDrawElement = (opts) => {
6981
6979
  return {
6982
6980
  ..._newElementBase(opts.type, opts),
@@ -8078,12 +8076,22 @@ var init_change = __esm({
8078
8076
  if (!flags.containsZindexDifference) {
8079
8077
  return elements;
8080
8078
  }
8081
- const previous = Array.from(elements.values());
8082
- const reordered = orderByFractionalIndex([...previous]);
8083
- if (!flags.containsVisibleDifference && Delta.isRightDifferent(previous, reordered, true)) {
8079
+ const unordered = Array.from(elements.values());
8080
+ const ordered = orderByFractionalIndex([...unordered]);
8081
+ const moved = Delta.getRightDifferences(unordered, ordered, true).reduce(
8082
+ (acc, arrayIndex) => {
8083
+ const candidate = unordered[Number(arrayIndex)];
8084
+ if (candidate && changed.has(candidate.id)) {
8085
+ acc.set(candidate.id, candidate);
8086
+ }
8087
+ return acc;
8088
+ },
8089
+ /* @__PURE__ */ new Map()
8090
+ );
8091
+ if (!flags.containsVisibleDifference && moved.size) {
8084
8092
  flags.containsVisibleDifference = true;
8085
8093
  }
8086
- return arrayToMap(syncMovedIndices(reordered, changed));
8094
+ return arrayToMap(syncMovedIndices(ordered, moved));
8087
8095
  }
8088
8096
  /**
8089
8097
  * It is necessary to post process the partials in case of reference values,
@@ -8184,8 +8192,35 @@ var init_store = __esm({
8184
8192
  };
8185
8193
  isObservedAppState = (appState) => !!Reflect.get(appState, hiddenObservedAppStateProp);
8186
8194
  StoreAction = {
8195
+ /**
8196
+ * Immediately undoable.
8197
+ *
8198
+ * Use for updates which should be captured.
8199
+ * Should be used for most of the local updates.
8200
+ *
8201
+ * These updates will _immediately_ make it to the local undo / redo stacks.
8202
+ */
8187
8203
  CAPTURE: "capture",
8204
+ /**
8205
+ * Never undoable.
8206
+ *
8207
+ * Use for updates which should never be recorded, such as remote updates
8208
+ * or scene initialization.
8209
+ *
8210
+ * These updates will _never_ make it to the local undo / redo stacks.
8211
+ */
8188
8212
  UPDATE: "update",
8213
+ /**
8214
+ * Eventually undoable.
8215
+ *
8216
+ * Use for updates which should not be captured immediately - likely
8217
+ * exceptions which are part of some async multi-step process. Otherwise, all
8218
+ * such updates would end up being captured with the next
8219
+ * `StoreAction.CAPTURE` - triggered either by the next `updateScene`
8220
+ * or internally by the editor.
8221
+ *
8222
+ * These updates will _eventually_ make it to the local undo / redo stacks.
8223
+ */
8189
8224
  NONE: "none"
8190
8225
  };
8191
8226
  StoreIncrementEvent = class {
@@ -9345,6 +9380,7 @@ var init_restore = __esm({
9345
9380
  init_textElement();
9346
9381
  init_url();
9347
9382
  init_fractionalIndex();
9383
+ init_points();
9348
9384
  AllowedExcalidrawActiveTools = {
9349
9385
  selection: true,
9350
9386
  text: true,
@@ -9446,6 +9482,7 @@ var init_restore = __esm({
9446
9482
  verticalAlign: element.verticalAlign || DEFAULT_VERTICAL_ALIGN,
9447
9483
  containerId: element.containerId ?? null,
9448
9484
  originalText: element.originalText || text,
9485
+ autoResize: element.autoResize ?? true,
9449
9486
  lineHeight
9450
9487
  });
9451
9488
  if (!text && !element.isDeleted) {
@@ -9495,7 +9532,8 @@ var init_restore = __esm({
9495
9532
  endArrowhead,
9496
9533
  points,
9497
9534
  x,
9498
- y
9535
+ y,
9536
+ ...getSizeFromPoints(points)
9499
9537
  });
9500
9538
  }
9501
9539
  case "ellipse":
@@ -11303,7 +11341,7 @@ var init_export = __esm({
11303
11341
  }
11304
11342
  let assetPath = "https://excalidraw.com/";
11305
11343
  if (define_import_meta_env_default.VITE_IS_EXCALIDRAW_NPM_PACKAGE) {
11306
- assetPath = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${define_import_meta_env_default.VITE_PKG_NAME}@${define_import_meta_env_default.PKG_VERSION}`;
11344
+ assetPath = window.EXCALIDRAW_ASSET_PATH || `https://unpkg.com/${define_import_meta_env_default.VITE_PKG_NAME}@${define_import_meta_env_default.VITE_PKG_VERSION}`;
11307
11345
  if (assetPath?.startsWith("/")) {
11308
11346
  assetPath = assetPath.replace("/", `${window.location.origin}/`);
11309
11347
  }
@@ -13196,14 +13234,14 @@ var init_renderElement = __esm({
13196
13234
  }
13197
13235
  context.restore();
13198
13236
  };
13199
- renderSelectionElement = (element, context, appState) => {
13237
+ renderSelectionElement = (element, context, appState, selectionColor) => {
13200
13238
  context.save();
13201
13239
  context.translate(element.x + appState.scrollX, element.y + appState.scrollY);
13202
13240
  context.fillStyle = "rgba(0, 0, 200, 0.04)";
13203
13241
  const offset2 = 0.5 / appState.zoom.value;
13204
13242
  context.fillRect(offset2, offset2, element.width, element.height);
13205
13243
  context.lineWidth = 1 / appState.zoom.value;
13206
- context.strokeStyle = " rgb(105, 101, 219)";
13244
+ context.strokeStyle = selectionColor;
13207
13245
  context.strokeRect(offset2, offset2, element.width, element.height);
13208
13246
  context.restore();
13209
13247
  };
@@ -13524,11 +13562,11 @@ var init_mutateElement = __esm({
13524
13562
  element.versionNonce = randomInteger();
13525
13563
  element.updated = getUpdatedTimestamp();
13526
13564
  if (informMutation) {
13527
- Scene_default.getScene(element)?.informMutation();
13565
+ Scene_default.getScene(element)?.triggerUpdate();
13528
13566
  }
13529
13567
  return element;
13530
13568
  };
13531
- newElementWith = (element, updates) => {
13569
+ newElementWith = (element, updates, force = false) => {
13532
13570
  let didChange = false;
13533
13571
  for (const key in updates) {
13534
13572
  const value = updates[key];
@@ -13540,7 +13578,7 @@ var init_mutateElement = __esm({
13540
13578
  didChange = true;
13541
13579
  }
13542
13580
  }
13543
- if (!didChange) {
13581
+ if (!didChange && !force) {
13544
13582
  return element;
13545
13583
  }
13546
13584
  return {
@@ -13657,14 +13695,13 @@ var init_sizeHelpers = __esm({
13657
13695
  });
13658
13696
 
13659
13697
  // element/transformHandles.ts
13660
- var transformHandleSizes, ROTATION_RESIZE_HANDLE_GAP, DEFAULT_OMIT_SIDES, OMIT_SIDES_FOR_TEXT_ELEMENT, OMIT_SIDES_FOR_LINE_SLASH, OMIT_SIDES_FOR_LINE_BACKSLASH, generateTransformHandle, canResizeFromSides, getOmitSidesForDevice, getTransformHandlesFromCoords, getTransformHandles, shouldShowBoundingBox;
13698
+ var transformHandleSizes, ROTATION_RESIZE_HANDLE_GAP, DEFAULT_OMIT_SIDES, OMIT_SIDES_FOR_LINE_SLASH, OMIT_SIDES_FOR_LINE_BACKSLASH, generateTransformHandle, canResizeFromSides, getOmitSidesForDevice, getTransformHandlesFromCoords, getTransformHandles, shouldShowBoundingBox;
13661
13699
  var init_transformHandles = __esm({
13662
13700
  "element/transformHandles.ts"() {
13663
13701
  "use strict";
13664
13702
  init_define_import_meta_env();
13665
13703
  init_bounds();
13666
13704
  init_math();
13667
- init_element();
13668
13705
  init_typeChecks();
13669
13706
  init_constants();
13670
13707
  transformHandleSizes = {
@@ -13679,12 +13716,6 @@ var init_transformHandles = __esm({
13679
13716
  n: true,
13680
13717
  w: true
13681
13718
  };
13682
- OMIT_SIDES_FOR_TEXT_ELEMENT = {
13683
- e: true,
13684
- s: true,
13685
- n: true,
13686
- w: true
13687
- };
13688
13719
  OMIT_SIDES_FOR_LINE_SLASH = {
13689
13720
  e: true,
13690
13721
  s: true,
@@ -13845,8 +13876,6 @@ var init_transformHandles = __esm({
13845
13876
  omitSides = OMIT_SIDES_FOR_LINE_BACKSLASH;
13846
13877
  }
13847
13878
  }
13848
- } else if (isTextElement(element)) {
13849
- omitSides = OMIT_SIDES_FOR_TEXT_ELEMENT;
13850
13879
  } else if (isFrameLikeElement(element)) {
13851
13880
  omitSides = {
13852
13881
  ...omitSides,
@@ -13920,7 +13949,7 @@ var init_resizeTest = __esm({
13920
13949
  element,
13921
13950
  elementsMap
13922
13951
  );
13923
- if (element.type !== "text" && !(isLinearElement(element) && element.points.length <= 2)) {
13952
+ if (!(isLinearElement(element) && element.points.length <= 2)) {
13924
13953
  const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;
13925
13954
  const sides = getSelectionBorders(
13926
13955
  [x1 - SPACING, y1 - SPACING],
@@ -14088,8 +14117,9 @@ var init_resizeElements = __esm({
14088
14117
  shouldRotateWithDiscreteAngle2
14089
14118
  );
14090
14119
  updateBoundElements(element, elementsMap);
14091
- } else if (isTextElement(element) && (transformHandleType === "nw" || transformHandleType === "ne" || transformHandleType === "sw" || transformHandleType === "se")) {
14120
+ } else if (isTextElement(element) && transformHandleType) {
14092
14121
  resizeSingleTextElement(
14122
+ originalElements,
14093
14123
  element,
14094
14124
  elementsMap,
14095
14125
  transformHandleType,
@@ -14191,7 +14221,7 @@ var init_resizeElements = __esm({
14191
14221
  size: nextFontSize
14192
14222
  };
14193
14223
  };
14194
- resizeSingleTextElement = (element, elementsMap, transformHandleType, shouldResizeFromCenter2, pointerX, pointerY) => {
14224
+ resizeSingleTextElement = (originalElements, element, elementsMap, transformHandleType, shouldResizeFromCenter2, pointerX, pointerY) => {
14195
14225
  const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(
14196
14226
  element,
14197
14227
  elementsMap
@@ -14205,17 +14235,19 @@ var init_resizeElements = __esm({
14205
14235
  );
14206
14236
  let scaleX = 0;
14207
14237
  let scaleY = 0;
14208
- if (transformHandleType.includes("e")) {
14209
- scaleX = (rotatedX - x1) / (x2 - x1);
14210
- }
14211
- if (transformHandleType.includes("w")) {
14212
- scaleX = (x2 - rotatedX) / (x2 - x1);
14213
- }
14214
- if (transformHandleType.includes("n")) {
14215
- scaleY = (y2 - rotatedY) / (y2 - y1);
14216
- }
14217
- if (transformHandleType.includes("s")) {
14218
- scaleY = (rotatedY - y1) / (y2 - y1);
14238
+ if (transformHandleType !== "e" && transformHandleType !== "w") {
14239
+ if (transformHandleType.includes("e")) {
14240
+ scaleX = (rotatedX - x1) / (x2 - x1);
14241
+ }
14242
+ if (transformHandleType.includes("w")) {
14243
+ scaleX = (x2 - rotatedX) / (x2 - x1);
14244
+ }
14245
+ if (transformHandleType.includes("n")) {
14246
+ scaleY = (y2 - rotatedY) / (y2 - y1);
14247
+ }
14248
+ if (transformHandleType.includes("s")) {
14249
+ scaleY = (rotatedY - y1) / (y2 - y1);
14250
+ }
14219
14251
  }
14220
14252
  const scale = Math.max(scaleX, scaleY);
14221
14253
  if (scale > 0) {
@@ -14270,6 +14302,89 @@ var init_resizeElements = __esm({
14270
14302
  y: nextY
14271
14303
  });
14272
14304
  }
14305
+ if (transformHandleType === "e" || transformHandleType === "w") {
14306
+ const stateAtResizeStart = originalElements.get(element.id);
14307
+ const [x12, y12, x22, y22] = getResizedElementAbsoluteCoords(
14308
+ stateAtResizeStart,
14309
+ stateAtResizeStart.width,
14310
+ stateAtResizeStart.height,
14311
+ true
14312
+ );
14313
+ const startTopLeft = [x12, y12];
14314
+ const startBottomRight = [x22, y22];
14315
+ const startCenter = centerPoint(startTopLeft, startBottomRight);
14316
+ const rotatedPointer = rotatePoint(
14317
+ [pointerX, pointerY],
14318
+ startCenter,
14319
+ -stateAtResizeStart.angle
14320
+ );
14321
+ const [esx1, , esx2] = getResizedElementAbsoluteCoords(
14322
+ element,
14323
+ element.width,
14324
+ element.height,
14325
+ true
14326
+ );
14327
+ const boundsCurrentWidth = esx2 - esx1;
14328
+ const atStartBoundsWidth = startBottomRight[0] - startTopLeft[0];
14329
+ const minWidth = getMinTextElementWidth(
14330
+ getFontString({
14331
+ fontSize: element.fontSize,
14332
+ fontFamily: element.fontFamily
14333
+ }),
14334
+ element.lineHeight
14335
+ );
14336
+ let scaleX2 = atStartBoundsWidth / boundsCurrentWidth;
14337
+ if (transformHandleType.includes("e")) {
14338
+ scaleX2 = (rotatedPointer[0] - startTopLeft[0]) / boundsCurrentWidth;
14339
+ }
14340
+ if (transformHandleType.includes("w")) {
14341
+ scaleX2 = (startBottomRight[0] - rotatedPointer[0]) / boundsCurrentWidth;
14342
+ }
14343
+ const newWidth = element.width * scaleX2 < minWidth ? minWidth : element.width * scaleX2;
14344
+ const text = wrapText(
14345
+ element.originalText,
14346
+ getFontString(element),
14347
+ Math.abs(newWidth)
14348
+ );
14349
+ const metrics = measureText(
14350
+ text,
14351
+ getFontString(element),
14352
+ element.lineHeight
14353
+ );
14354
+ const eleNewHeight = metrics.height;
14355
+ const [newBoundsX1, newBoundsY1, newBoundsX2, newBoundsY2] = getResizedElementAbsoluteCoords(
14356
+ stateAtResizeStart,
14357
+ newWidth,
14358
+ eleNewHeight,
14359
+ true
14360
+ );
14361
+ const newBoundsWidth = newBoundsX2 - newBoundsX1;
14362
+ const newBoundsHeight = newBoundsY2 - newBoundsY1;
14363
+ let newTopLeft = [...startTopLeft];
14364
+ if (["n", "w", "nw"].includes(transformHandleType)) {
14365
+ newTopLeft = [
14366
+ startBottomRight[0] - Math.abs(newBoundsWidth),
14367
+ startTopLeft[1]
14368
+ ];
14369
+ }
14370
+ const angle = stateAtResizeStart.angle;
14371
+ const rotatedTopLeft = rotatePoint(newTopLeft, startCenter, angle);
14372
+ const newCenter = [
14373
+ newTopLeft[0] + Math.abs(newBoundsWidth) / 2,
14374
+ newTopLeft[1] + Math.abs(newBoundsHeight) / 2
14375
+ ];
14376
+ const rotatedNewCenter = rotatePoint(newCenter, startCenter, angle);
14377
+ newTopLeft = rotatePoint(rotatedTopLeft, rotatedNewCenter, -angle);
14378
+ const resizedElement = {
14379
+ width: Math.abs(newWidth),
14380
+ height: Math.abs(metrics.height),
14381
+ x: newTopLeft[0],
14382
+ y: newTopLeft[1],
14383
+ text,
14384
+ autoResize: false
14385
+ };
14386
+ mutateElement(element, resizedElement);
14387
+ }
14273
14388
  };
14274
14389
  resizeSingleElement = (originalElements, shouldMaintainAspectRatio2, element, elementsMap, transformHandleDirection, shouldResizeFromCenter2, pointerX, pointerY) => {
14275
14390
  const stateAtResizeStart = originalElements.get(element.id);
@@ -14661,7 +14776,7 @@ var init_resizeElements = __esm({
14661
14776
  handleBindTextResize(element, elementsMap, transformHandleType, true);
14662
14777
  }
14663
14778
  }
14664
- Scene_default.getScene(elementsAndUpdates[0].element)?.informMutation();
14779
+ Scene_default.getScene(elementsAndUpdates[0].element)?.triggerUpdate();
14665
14780
  };
14666
14781
  rotateMultipleElements = (originalElements, elements, elementsMap, pointerX, pointerY, shouldRotateWithDiscreteAngle2, centerX, centerY) => {
14667
14782
  let centerAngle = 5 * Math.PI / 2 + Math.atan2(pointerY - centerY, pointerX - centerX);
@@ -14706,7 +14821,7 @@ var init_resizeElements = __esm({
14706
14821
  );
14707
14822
  }
14708
14823
  });
14709
- Scene_default.getScene(elements[0])?.informMutation();
14824
+ Scene_default.getScene(elements[0])?.triggerUpdate();
14710
14825
  };
14711
14826
  getResizeOffsetXY = (transformHandleType, selectedElements, elementsMap, x, y) => {
14712
14827
  const [x1, y1, x2, y2] = selectedElements.length === 1 ? getElementAbsoluteCoords(selectedElements[0], elementsMap) : getCommonBounds(selectedElements);
@@ -14756,6 +14871,8 @@ var init_dragElements = __esm({
14756
14871
  init_textElement();
14757
14872
  init_math();
14758
14873
  init_typeChecks();
14874
+ init_utils();
14875
+ init_constants();
14759
14876
  dragSelectedElements = (pointerDownState, selectedElements, offset2, appState, scene, snapOffset, gridSize) => {
14760
14877
  const elementsToUpdate = new Set(
14761
14878
  selectedElements
@@ -14833,7 +14950,7 @@ var init_dragElements = __esm({
14833
14950
  const [x1, y1] = getCommonBounds(selectedElements);
14834
14951
  return [x - x1, y - y1];
14835
14952
  };
14836
- dragNewElement = (draggingElement, elementType, originX, originY, x, y, width, height, shouldMaintainAspectRatio2, shouldResizeFromCenter2, widthAspectRatio, originOffset = null) => {
14953
+ dragNewElement = (draggingElement, elementType, originX, originY, x, y, width, height, shouldMaintainAspectRatio2, shouldResizeFromCenter2, zoom, widthAspectRatio, originOffset = null) => {
14837
14954
  if (shouldMaintainAspectRatio2 && draggingElement.type !== "selection") {
14838
14955
  if (widthAspectRatio) {
14839
14956
  height = width / widthAspectRatio;
@@ -14864,12 +14981,34 @@ var init_dragElements = __esm({
14864
14981
  newX = originX - width / 2;
14865
14982
  newY = originY - height / 2;
14866
14983
  }
14984
+ let textAutoResize = null;
14985
+ if (isTextElement(draggingElement)) {
14986
+ height = draggingElement.height;
14987
+ const minWidth = getMinTextElementWidth(
14988
+ getFontString({
14989
+ fontSize: draggingElement.fontSize,
14990
+ fontFamily: draggingElement.fontFamily
14991
+ }),
14992
+ draggingElement.lineHeight
14993
+ );
14994
+ width = Math.max(width, minWidth);
14995
+ if (Math.abs(x - originX) > TEXT_AUTOWRAP_THRESHOLD / zoom) {
14996
+ textAutoResize = {
14997
+ autoResize: false
14998
+ };
14999
+ }
15000
+ newY = originY;
15001
+ if (shouldResizeFromCenter2) {
15002
+ newX = originX - width / 2;
15003
+ }
15004
+ }
14867
15005
  if (width !== 0 && height !== 0) {
14868
15006
  mutateElement(draggingElement, {
14869
15007
  x: newX + (originOffset?.x ?? 0),
14870
15008
  y: newY + (originOffset?.y ?? 0),
14871
15009
  width,
14872
- height
15010
+ height,
15011
+ ...textAutoResize
14873
15012
  });
14874
15013
  }
14875
15014
  };
@@ -15193,7 +15332,7 @@ init_define_import_meta_env();
15193
15332
 
15194
15333
  // i18n.ts
15195
15334
  init_define_import_meta_env();
15196
- import fallbackLangData from "./en-UQDDYCH7.json";
15335
+ import fallbackLangData from "./en-OIPCBIOA.json";
15197
15336
  import percentages from "./percentages-UCQDHIQF.json";
15198
15337
 
15199
15338
  // jotai.ts
@@ -15217,7 +15356,7 @@ var globImport_locales_json = __glob({
15217
15356
  "./locales/da-DK.json": () => import("./da-DK-WBEQB3CJ.json"),
15218
15357
  "./locales/de-DE.json": () => import("./de-DE-VEIMCP7R.json"),
15219
15358
  "./locales/el-GR.json": () => import("./el-GR-TKRKG5GQ.json"),
15220
- "./locales/en.json": () => import("./en-UQDDYCH7.json"),
15359
+ "./locales/en.json": () => import("./en-OIPCBIOA.json"),
15221
15360
  "./locales/es-ES.json": () => import("./es-ES-TOLWEZNW.json"),
15222
15361
  "./locales/eu-ES.json": () => import("./eu-ES-7CDRJQWJ.json"),
15223
15362
  "./locales/fa-IR.json": () => import("./fa-IR-527E2XGU.json"),
@@ -16302,12 +16441,16 @@ var arrownNarrowUpJSX = /* @__PURE__ */ jsxs3("g", { strokeWidth: 1.5, children:
16302
16441
  var BringForwardIcon = createIcon(arrownNarrowUpJSX, tablerIconProps);
16303
16442
  var SendBackwardIcon = createIcon(arrownNarrowUpJSX, {
16304
16443
  ...tablerIconProps,
16305
- transform: "rotate(180)"
16444
+ style: {
16445
+ transform: "rotate(180deg)"
16446
+ }
16306
16447
  });
16307
16448
  var BringToFrontIcon = createIcon(arrowBarToTopJSX, tablerIconProps);
16308
16449
  var SendToBackIcon = createIcon(arrowBarToTopJSX, {
16309
16450
  ...tablerIconProps,
16310
- transform: "rotate(180)"
16451
+ style: {
16452
+ transform: "rotate(180deg)"
16453
+ }
16311
16454
  });
16312
16455
  var AlignTopIcon = createIcon(
16313
16456
  /* @__PURE__ */ jsxs3(Fragment, { children: [
@@ -18625,6 +18768,7 @@ var ButtonIconSelect = (props) => /* @__PURE__ */ jsx9("div", { className: "butt
18625
18768
  (option) => props.type === "button" ? /* @__PURE__ */ jsx9(
18626
18769
  "button",
18627
18770
  {
18771
+ type: "button",
18628
18772
  onClick: (event) => props.onClick(option.value, event),
18629
18773
  className: clsx4({
18630
18774
  active: option.active ?? props.value === option.value
@@ -20133,6 +20277,7 @@ function Picker2({
20133
20277
  children: /* @__PURE__ */ jsx20("div", { className: "picker-content", ref: rGallery, children: options.map((option, i) => /* @__PURE__ */ jsxs12(
20134
20278
  "button",
20135
20279
  {
20280
+ type: "button",
20136
20281
  className: clsx11("picker-option", {
20137
20282
  active: value === option.value
20138
20283
  }),
@@ -20179,6 +20324,7 @@ function IconPicker({
20179
20324
  "button",
20180
20325
  {
20181
20326
  name: group,
20327
+ type: "button",
20182
20328
  className: isActive ? "active" : "",
20183
20329
  "aria-label": label,
20184
20330
  onClick: () => setActive(!isActive),
@@ -20262,7 +20408,7 @@ var getFormValue = function(elements, appState, getAttribute, isRelevantElement,
20262
20408
  return ret;
20263
20409
  };
20264
20410
  var offsetElementAfterFontResize = (prevElement, nextElement) => {
20265
- if (isBoundToContainer(nextElement)) {
20411
+ if (isBoundToContainer(nextElement) || !nextElement.autoResize) {
20266
20412
  return nextElement;
20267
20413
  }
20268
20414
  return mutateElement(
@@ -22184,7 +22330,16 @@ var CheckboxItem = ({ children, checked, onChange, className }) => {
22184
22330
  ).focus();
22185
22331
  },
22186
22332
  children: [
22187
- /* @__PURE__ */ jsx27("button", { className: "Checkbox-box", role: "checkbox", "aria-checked": checked, children: checkIcon }),
22333
+ /* @__PURE__ */ jsx27(
22334
+ "button",
22335
+ {
22336
+ type: "button",
22337
+ className: "Checkbox-box",
22338
+ role: "checkbox",
22339
+ "aria-checked": checked,
22340
+ children: checkIcon
22341
+ }
22342
+ ),
22188
22343
  /* @__PURE__ */ jsx27("div", { className: "Checkbox-label", children })
22189
22344
  ]
22190
22345
  }
@@ -24272,7 +24427,8 @@ var actionBindText = register({
24272
24427
  mutateElement(textElement, {
24273
24428
  containerId: container.id,
24274
24429
  verticalAlign: VERTICAL_ALIGN.MIDDLE,
24275
- textAlign: TEXT_ALIGN.CENTER
24430
+ textAlign: TEXT_ALIGN.CENTER,
24431
+ autoResize: true
24276
24432
  });
24277
24433
  mutateElement(container, {
24278
24434
  boundElements: (container.boundElements || []).concat({
@@ -24394,7 +24550,8 @@ var actionWrapTextInContainer = register({
24394
24550
  containerId: container.id,
24395
24551
  verticalAlign: VERTICAL_ALIGN.MIDDLE,
24396
24552
  boundElements: null,
24397
- textAlign: TEXT_ALIGN.CENTER
24553
+ textAlign: TEXT_ALIGN.CENTER,
24554
+ autoResize: true
24398
24555
  },
24399
24556
  false
24400
24557
  );
@@ -27673,6 +27830,7 @@ var Dialog = (props) => {
27673
27830
  onClick: onClose,
27674
27831
  title: t("buttons.close"),
27675
27832
  "aria-label": t("buttons.close"),
27833
+ type: "button",
27676
27834
  children: CloseIcon
27677
27835
  }
27678
27836
  ),
@@ -28524,6 +28682,7 @@ var ExitZenModeAction = ({
28524
28682
  }) => /* @__PURE__ */ jsx62(
28525
28683
  "button",
28526
28684
  {
28685
+ type: "button",
28527
28686
  className: clsx28("disable-zen-mode", {
28528
28687
  "disable-zen-mode--visible": showExitZenModeBtn
28529
28688
  }),
@@ -29001,7 +29160,7 @@ function CommandPaletteInner({
29001
29160
  ...command,
29002
29161
  icon: command.icon || boltIcon,
29003
29162
  order: command.order ?? getCategoryOrder(command.category),
29004
- haystack: `${deburr(command.label)} ${command.keywords?.join(" ") || ""}`
29163
+ haystack: `${deburr(command.label.toLocaleLowerCase())} ${command.keywords?.join(" ") || ""}`
29005
29164
  };
29006
29165
  });
29007
29166
  setAllCommands(allCommands2);
@@ -29172,7 +29331,9 @@ function CommandPaletteInner({
29172
29331
  setCurrentCommand(showLastUsed ? lastUsed : matchingCommands[0] || null);
29173
29332
  return;
29174
29333
  }
29175
- const _query = deburr(commandSearch.replace(/[<>-_| ]/g, ""));
29334
+ const _query = deburr(
29335
+ commandSearch.toLocaleLowerCase().replace(/[<>_| -]/g, "")
29336
+ );
29176
29337
  matchingCommands = fuzzy.filter(_query, matchingCommands, {
29177
29338
  extract: (command) => command.haystack
29178
29339
  }).sort((a, b) => b.score - a.score).map((item) => item.original);
@@ -29556,7 +29717,10 @@ var createUndoAction = (history, store) => ({
29556
29717
  PanelComponent: ({ updateData, data }) => {
29557
29718
  const { isUndoStackEmpty } = useEmitter(
29558
29719
  history.onHistoryChangedEmitter,
29559
- new HistoryChangedEvent()
29720
+ new HistoryChangedEvent(
29721
+ history.isUndoStackEmpty,
29722
+ history.isRedoStackEmpty
29723
+ )
29560
29724
  );
29561
29725
  return /* @__PURE__ */ jsx66(
29562
29726
  ToolButton,
@@ -29566,7 +29730,8 @@ var createUndoAction = (history, store) => ({
29566
29730
  "aria-label": t("buttons.undo"),
29567
29731
  onClick: updateData,
29568
29732
  size: data?.size || "medium",
29569
- disabled: isUndoStackEmpty
29733
+ disabled: isUndoStackEmpty,
29734
+ "data-testid": "button-undo"
29570
29735
  }
29571
29736
  );
29572
29737
  }
@@ -29590,7 +29755,10 @@ var createRedoAction = (history, store) => ({
29590
29755
  PanelComponent: ({ updateData, data }) => {
29591
29756
  const { isRedoStackEmpty } = useEmitter(
29592
29757
  history.onHistoryChangedEmitter,
29593
- new HistoryChangedEvent()
29758
+ new HistoryChangedEvent(
29759
+ history.isUndoStackEmpty,
29760
+ history.isRedoStackEmpty
29761
+ )
29594
29762
  );
29595
29763
  return /* @__PURE__ */ jsx66(
29596
29764
  ToolButton,
@@ -29600,7 +29768,8 @@ var createRedoAction = (history, store) => ({
29600
29768
  "aria-label": t("buttons.redo"),
29601
29769
  onClick: updateData,
29602
29770
  size: data?.size || "medium",
29603
- disabled: isRedoStackEmpty
29771
+ disabled: isRedoStackEmpty,
29772
+ "data-testid": "button-redo"
29604
29773
  }
29605
29774
  );
29606
29775
  }
@@ -29737,6 +29906,7 @@ init_register();
29737
29906
  init_appState();
29738
29907
  init_clipboard();
29739
29908
  init_constants();
29909
+ init_constants();
29740
29910
  init_restore();
29741
29911
  init_element();
29742
29912
  init_binding();
@@ -29843,6 +30013,7 @@ var ContextMenu = React24.memo(
29843
30013
  children: /* @__PURE__ */ jsxs37(
29844
30014
  "button",
29845
30015
  {
30016
+ type: "button",
29846
30017
  className: clsx30("context-menu-item", {
29847
30018
  dangerous: actionName === "deleteSelectedElements",
29848
30019
  checkmark: item.checked?.(appState)
@@ -30850,6 +31021,7 @@ var MobileMenu = ({
30850
31021
  appState.scrolledOutside && !appState.openMenu && !appState.openSidebar && /* @__PURE__ */ jsx81(
30851
31022
  "button",
30852
31023
  {
31024
+ type: "button",
30853
31025
  className: "scroll-back-to-content",
30854
31026
  onClick: () => {
30855
31027
  setAppState((appState2) => ({
@@ -30915,6 +31087,7 @@ var ChartPreviewBtn = (props) => {
30915
31087
  return /* @__PURE__ */ jsx82(
30916
31088
  "button",
30917
31089
  {
31090
+ type: "button",
30918
31091
  className: "ChartPreview",
30919
31092
  onClick: () => {
30920
31093
  if (chartElements) {
@@ -34303,7 +34476,7 @@ var LayerUI = ({
34303
34476
  );
34304
34477
  ShapeCache.delete(element);
34305
34478
  }
34306
- Scene_default.getScene(selectedElements[0])?.informMutation();
34479
+ Scene_default.getScene(selectedElements[0])?.triggerUpdate();
34307
34480
  } else if (colorPickerType === "elementBackground") {
34308
34481
  setAppState({
34309
34482
  currentItemBackgroundColor: color
@@ -34413,6 +34586,7 @@ var LayerUI = ({
34413
34586
  appState.scrolledOutside && /* @__PURE__ */ jsx117(
34414
34587
  "button",
34415
34588
  {
34589
+ type: "button",
34416
34590
  className: "scroll-back-to-content",
34417
34591
  onClick: () => {
34418
34592
  setAppState((appState2) => ({
@@ -34558,19 +34732,12 @@ init_transformHandles();
34558
34732
  init_define_import_meta_env();
34559
34733
  init_element();
34560
34734
  init_mutateElement();
34561
- init_textElement();
34562
- init_typeChecks();
34563
34735
  init_utils();
34564
34736
  init_ShapeCache();
34565
34737
  var Fonts = class _Fonts {
34566
34738
  scene;
34567
- onSceneUpdated;
34568
- constructor({
34569
- scene,
34570
- onSceneUpdated
34571
- }) {
34739
+ constructor({ scene }) {
34572
34740
  this.scene = scene;
34573
- this.onSceneUpdated = onSceneUpdated;
34574
34741
  }
34575
34742
  // it's ok to track fonts across multiple instances only once, so let's use
34576
34743
  // a static member to reduce memory footprint
@@ -34601,21 +34768,15 @@ var Fonts = class _Fonts {
34601
34768
  }
34602
34769
  let didUpdate = false;
34603
34770
  this.scene.mapElements((element) => {
34604
- if (isTextElement(element) && !isBoundToContainer(element)) {
34605
- ShapeCache.delete(element);
34771
+ if (isTextElement(element)) {
34606
34772
  didUpdate = true;
34607
- return newElementWith(element, {
34608
- ...refreshTextDimensions(
34609
- element,
34610
- getContainerElement(element, this.scene.getNonDeletedElementsMap()),
34611
- this.scene.getNonDeletedElementsMap()
34612
- )
34613
- });
34773
+ ShapeCache.delete(element);
34774
+ return newElementWith(element, {}, true);
34614
34775
  }
34615
34776
  return element;
34616
34777
  });
34617
34778
  if (didUpdate) {
34618
- this.onSceneUpdated();
34779
+ this.scene.triggerUpdate();
34619
34780
  }
34620
34781
  };
34621
34782
  loadFontsForElements = async (elements) => {
@@ -35715,7 +35876,7 @@ var getSnapLinesAtPointer = (elements, appState, pointer, event, elementsMap) =>
35715
35876
  };
35716
35877
  };
35717
35878
  var isActiveToolNonLinearSnappable = (activeToolType) => {
35718
- return activeToolType === TOOL_TYPE.rectangle || activeToolType === TOOL_TYPE.ellipse || activeToolType === TOOL_TYPE.diamond || activeToolType === TOOL_TYPE.frame || activeToolType === TOOL_TYPE.magicframe || activeToolType === TOOL_TYPE.image;
35879
+ return activeToolType === TOOL_TYPE.rectangle || activeToolType === TOOL_TYPE.ellipse || activeToolType === TOOL_TYPE.diamond || activeToolType === TOOL_TYPE.frame || activeToolType === TOOL_TYPE.magicframe || activeToolType === TOOL_TYPE.image || activeToolType === TOOL_TYPE.text;
35719
35880
  };
35720
35881
 
35721
35882
  // components/BraveMeasureTextError.tsx
@@ -36576,7 +36737,7 @@ var renderBindingHighlightForSuggestedPointBinding = (context, suggestedBinding,
36576
36737
  fillCircle(context, x, y, threshold);
36577
36738
  });
36578
36739
  };
36579
- var renderSelectionBorder = (context, appState, elementProperties, padding = DEFAULT_TRANSFORM_HANDLE_SPACING * 2) => {
36740
+ var renderSelectionBorder = (context, appState, elementProperties) => {
36580
36741
  const {
36581
36742
  angle,
36582
36743
  elementX1,
@@ -36591,6 +36752,7 @@ var renderSelectionBorder = (context, appState, elementProperties, padding = DEF
36591
36752
  } = elementProperties;
36592
36753
  const elementWidth = elementX2 - elementX1;
36593
36754
  const elementHeight = elementY2 - elementY1;
36755
+ const padding = DEFAULT_TRANSFORM_HANDLE_SPACING * 2;
36594
36756
  const linePadding = padding / appState.zoom.value;
36595
36757
  const lineWidth = 8 / appState.zoom.value;
36596
36758
  const spaceWidth = 4 / appState.zoom.value;
@@ -36775,11 +36937,28 @@ var renderTransformHandles = (context, renderConfig, appState, transformHandles,
36775
36937
  }
36776
36938
  });
36777
36939
  };
36940
+ var renderTextBox = (text, context, appState, selectionColor) => {
36941
+ context.save();
36942
+ const padding = DEFAULT_TRANSFORM_HANDLE_SPACING * 2 / appState.zoom.value;
36943
+ const width = text.width + padding * 2;
36944
+ const height = text.height + padding * 2;
36945
+ const cx = text.x + width / 2;
36946
+ const cy = text.y + height / 2;
36947
+ const shiftX = -(width / 2 + padding);
36948
+ const shiftY = -(height / 2 + padding);
36949
+ context.translate(cx + appState.scrollX, cy + appState.scrollY);
36950
+ context.rotate(text.angle);
36951
+ context.lineWidth = 1 / appState.zoom.value;
36952
+ context.strokeStyle = selectionColor;
36953
+ context.strokeRect(shiftX, shiftY, width, height);
36954
+ context.restore();
36955
+ };
36778
36956
  var _renderInteractiveScene = ({
36779
36957
  canvas: canvas2,
36780
36958
  elementsMap,
36781
36959
  visibleElements,
36782
36960
  selectedElements,
36961
+ allElementsMap,
36783
36962
  scale,
36784
36963
  appState,
36785
36964
  renderConfig,
@@ -36818,11 +36997,27 @@ var _renderInteractiveScene = ({
36818
36997
  }
36819
36998
  if (appState.selectionElement) {
36820
36999
  try {
36821
- renderSelectionElement(appState.selectionElement, context, appState);
37000
+ renderSelectionElement(
37001
+ appState.selectionElement,
37002
+ context,
37003
+ appState,
37004
+ renderConfig.selectionColor
37005
+ );
36822
37006
  } catch (error) {
36823
37007
  console.error(error);
36824
37008
  }
36825
37009
  }
37010
+ if (appState.editingElement && isTextElement(appState.editingElement)) {
37011
+ const textElement = allElementsMap.get(appState.editingElement.id);
37012
+ if (textElement && !textElement.autoResize) {
37013
+ renderTextBox(
37014
+ textElement,
37015
+ context,
37016
+ appState,
37017
+ renderConfig.selectionColor
37018
+ );
37019
+ }
37020
+ }
36826
37021
  if (appState.isBindingEnabled) {
36827
37022
  appState.suggestedBindings.filter((binding) => binding != null).forEach((suggestedBinding) => {
36828
37023
  renderBindingHighlight(
@@ -36946,7 +37141,8 @@ var _renderInteractiveScene = ({
36946
37141
  // when we render we don't know which pointer type so use mouse,
36947
37142
  getOmitSidesForDevice(device)
36948
37143
  );
36949
- if (!appState.viewModeEnabled && showBoundingBox) {
37144
+ if (!appState.viewModeEnabled && showBoundingBox && // do not show transform handles when text is being edited
37145
+ !isTextElement(appState.editingElement)) {
36950
37146
  renderTransformHandles(
36951
37147
  context,
36952
37148
  renderConfig,
@@ -37105,6 +37301,7 @@ var InteractiveCanvas = (props) => {
37105
37301
  elementsMap: props.elementsMap,
37106
37302
  visibleElements: props.visibleElements,
37107
37303
  selectedElements: props.selectedElements,
37304
+ allElementsMap: props.allElementsMap,
37108
37305
  scale: window.devicePixelRatio,
37109
37306
  appState: props.appState,
37110
37307
  renderConfig: {
@@ -37172,11 +37369,12 @@ var getRelevantAppStateProps = (appState) => ({
37172
37369
  // Necessary for collab. sessions
37173
37370
  activeEmbeddable: appState.activeEmbeddable,
37174
37371
  snapLines: appState.snapLines,
37175
- zenModeEnabled: appState.zenModeEnabled
37372
+ zenModeEnabled: appState.zenModeEnabled,
37373
+ editingElement: appState.editingElement
37176
37374
  });
37177
37375
  var areEqual2 = (prevProps, nextProps) => {
37178
- if (prevProps.selectionNonce !== nextProps.selectionNonce || prevProps.versionNonce !== nextProps.versionNonce || prevProps.scale !== nextProps.scale || // we need to memoize on elementsMap because they may have renewed
37179
- // even if versionNonce didn't change (e.g. we filter elements out based
37376
+ if (prevProps.selectionNonce !== nextProps.selectionNonce || prevProps.sceneNonce !== nextProps.sceneNonce || prevProps.scale !== nextProps.scale || // we need to memoize on elementsMap because they may have renewed
37377
+ // even if sceneNonce didn't change (e.g. we filter elements out based
37180
37378
  // on appState)
37181
37379
  prevProps.elementsMap !== nextProps.elementsMap || prevProps.visibleElements !== nextProps.visibleElements || prevProps.selectedElements !== nextProps.selectedElements) {
37182
37380
  return false;
@@ -37264,8 +37462,8 @@ var getRelevantAppStateProps2 = (appState) => ({
37264
37462
  editingGroupId: appState.editingGroupId
37265
37463
  });
37266
37464
  var areEqual3 = (prevProps, nextProps) => {
37267
- if (prevProps.versionNonce !== nextProps.versionNonce || prevProps.scale !== nextProps.scale || // we need to memoize on elementsMap because they may have renewed
37268
- // even if versionNonce didn't change (e.g. we filter elements out based
37465
+ if (prevProps.sceneNonce !== nextProps.sceneNonce || prevProps.scale !== nextProps.scale || // we need to memoize on elementsMap because they may have renewed
37466
+ // even if sceneNonce didn't change (e.g. we filter elements out based
37269
37467
  // on appState)
37270
37468
  prevProps.elementsMap !== nextProps.elementsMap || prevProps.visibleElements !== nextProps.visibleElements) {
37271
37469
  return false;
@@ -37353,9 +37551,8 @@ var Renderer = class {
37353
37551
  width,
37354
37552
  editingElement,
37355
37553
  pendingImageElementId,
37356
- // unused but serves we cache on it to invalidate elements if they
37357
- // get mutated
37358
- versionNonce: _versionNonce
37554
+ // cache-invalidation nonce
37555
+ sceneNonce: _sceneNonce
37359
37556
  }) => {
37360
37557
  const elements = this.scene.getNonDeletedElements();
37361
37558
  const elementsMap = getRenderableElements({
@@ -37597,7 +37794,15 @@ var FollowMode = ({
37597
37794
  }
37598
37795
  )
37599
37796
  ] }),
37600
- /* @__PURE__ */ jsx125("button", { onClick: onDisconnect, className: "follow-mode__disconnect-btn", children: CloseIcon })
37797
+ /* @__PURE__ */ jsx125(
37798
+ "button",
37799
+ {
37800
+ type: "button",
37801
+ onClick: onDisconnect,
37802
+ className: "follow-mode__disconnect-btn",
37803
+ children: CloseIcon
37804
+ }
37805
+ )
37601
37806
  ] }) });
37602
37807
  };
37603
37808
  var FollowMode_default = FollowMode;
@@ -37891,7 +38096,8 @@ var textWysiwyg = ({
37891
38096
  element,
37892
38097
  canvas: canvas2,
37893
38098
  excalidrawContainer,
37894
- app
38099
+ app,
38100
+ autoSelect = true
37895
38101
  }) => {
37896
38102
  const textPropertiesUpdated = (updatedTextElement, editable2) => {
37897
38103
  if (!editable2.style.fontFamily || !editable2.style.fontSize) {
@@ -37997,6 +38203,8 @@ var textWysiwyg = ({
37997
38203
  if (!container) {
37998
38204
  maxWidth = (appState.width - 8 - viewportX) / appState.zoom.value;
37999
38205
  textElementWidth = Math.min(textElementWidth, maxWidth);
38206
+ } else {
38207
+ textElementWidth += 0.5;
38000
38208
  }
38001
38209
  const editorMaxHeight = (appState.height - viewportY) / appState.zoom.value;
38002
38210
  Object.assign(editable.style, {
@@ -38037,7 +38245,7 @@ var textWysiwyg = ({
38037
38245
  editable.classList.add("excalidraw-wysiwyg");
38038
38246
  let whiteSpace = "pre";
38039
38247
  let wordBreak = "normal";
38040
- if (isBoundToContainer(element)) {
38248
+ if (isBoundToContainer(element) || !element.autoResize) {
38041
38249
  whiteSpace = "pre-wrap";
38042
38250
  wordBreak = "break-word";
38043
38251
  }
@@ -38205,6 +38413,10 @@ var textWysiwyg = ({
38205
38413
  };
38206
38414
  let submittedViaKeyboard = false;
38207
38415
  const handleSubmit = () => {
38416
+ if (isDestroyed) {
38417
+ return;
38418
+ }
38419
+ isDestroyed = true;
38208
38420
  cleanup();
38209
38421
  const updateElement = Scene_default.getScene(element)?.getElement(
38210
38422
  element.id
@@ -38212,13 +38424,11 @@ var textWysiwyg = ({
38212
38424
  if (!updateElement) {
38213
38425
  return;
38214
38426
  }
38215
- let text = editable.value;
38216
38427
  const container = getContainerElement(
38217
38428
  updateElement,
38218
38429
  app.scene.getNonDeletedElementsMap()
38219
38430
  );
38220
38431
  if (container) {
38221
- text = updateElement.text;
38222
38432
  if (editable.value.trim()) {
38223
38433
  const boundTextElementId = getBoundTextElementId(container);
38224
38434
  if (!boundTextElementId || boundTextElementId !== element.id) {
@@ -38247,16 +38457,11 @@ var textWysiwyg = ({
38247
38457
  );
38248
38458
  }
38249
38459
  onSubmit({
38250
- text,
38251
38460
  viaKeyboard: submittedViaKeyboard,
38252
- originalText: editable.value
38461
+ nextOriginalText: editable.value
38253
38462
  });
38254
38463
  };
38255
38464
  const cleanup = () => {
38256
- if (isDestroyed) {
38257
- return;
38258
- }
38259
- isDestroyed = true;
38260
38465
  editable.onblur = null;
38261
38466
  editable.oninput = null;
38262
38467
  editable.onkeydown = null;
@@ -38306,9 +38511,15 @@ var textWysiwyg = ({
38306
38511
  editable.onblur = null;
38307
38512
  window.addEventListener("pointerup", bindBlurEvent);
38308
38513
  window.addEventListener("blur", handleSubmit);
38514
+ } else if (event.target instanceof HTMLElement && !event.target.contains(editable) && // Vitest simply ignores stopPropagation, capture-mode, or rAF
38515
+ // so without introducing crazier hacks, nothing we can do
38516
+ !isTestEnv()) {
38517
+ requestAnimationFrame(() => {
38518
+ handleSubmit();
38519
+ });
38309
38520
  }
38310
38521
  };
38311
- const unbindUpdate = Scene_default.getScene(element).addCallback(() => {
38522
+ const unbindUpdate = Scene_default.getScene(element).onUpdate(() => {
38312
38523
  updateWysiwygStyle();
38313
38524
  const isColorPickerActive = !!document.activeElement?.closest(
38314
38525
  ".color-picker-content"
@@ -38318,7 +38529,9 @@ var textWysiwyg = ({
38318
38529
  }
38319
38530
  });
38320
38531
  let isDestroyed = false;
38321
- editable.select();
38532
+ if (autoSelect) {
38533
+ editable.select();
38534
+ }
38322
38535
  bindBlurEvent();
38323
38536
  let observer = null;
38324
38537
  if (canvas2 && "ResizeObserver" in window) {
@@ -38329,7 +38542,10 @@ var textWysiwyg = ({
38329
38542
  } else {
38330
38543
  window.addEventListener("resize", updateWysiwygStyle);
38331
38544
  }
38332
- window.addEventListener("pointerdown", onPointerDown);
38545
+ editable.onpointerdown = (event) => event.stopPropagation();
38546
+ requestAnimationFrame(() => {
38547
+ window.addEventListener("pointerdown", onPointerDown, { capture: true });
38548
+ });
38333
38549
  window.addEventListener("wheel", stopEvent, {
38334
38550
  passive: false,
38335
38551
  capture: true
@@ -38341,6 +38557,84 @@ var textWysiwyg = ({
38341
38557
  // components/App.tsx
38342
38558
  init_fractionalIndex();
38343
38559
  init_helpers();
38560
+
38561
+ // actions/actionTextAutoResize.ts
38562
+ init_define_import_meta_env();
38563
+ init_element();
38564
+ init_mutateElement();
38565
+ init_textElement();
38566
+ init_scene();
38567
+ init_store();
38568
+ init_utils();
38569
+ init_register();
38570
+ var actionTextAutoResize = register({
38571
+ name: "autoResize",
38572
+ label: "labels.autoResize",
38573
+ icon: null,
38574
+ trackEvent: { category: "element" },
38575
+ predicate: (elements, appState, _, app) => {
38576
+ const selectedElements = getSelectedElements(elements, appState);
38577
+ return selectedElements.length === 1 && isTextElement(selectedElements[0]) && !selectedElements[0].autoResize;
38578
+ },
38579
+ perform: (elements, appState, _, app) => {
38580
+ const selectedElements = getSelectedElements(elements, appState);
38581
+ return {
38582
+ appState,
38583
+ elements: elements.map((element) => {
38584
+ if (element.id === selectedElements[0].id && isTextElement(element)) {
38585
+ const metrics = measureText(
38586
+ element.originalText,
38587
+ getFontString(element),
38588
+ element.lineHeight
38589
+ );
38590
+ return newElementWith(element, {
38591
+ autoResize: true,
38592
+ width: metrics.width,
38593
+ height: metrics.height,
38594
+ text: element.originalText
38595
+ });
38596
+ }
38597
+ return element;
38598
+ }),
38599
+ storeAction: StoreAction.CAPTURE
38600
+ };
38601
+ }
38602
+ });
38603
+
38604
+ // components/App.tsx
38605
+ init_bounds();
38606
+
38607
+ // mermaid.ts
38608
+ init_define_import_meta_env();
38609
+ var isMaybeMermaidDefinition = (text) => {
38610
+ const chartTypes = [
38611
+ "flowchart",
38612
+ "sequenceDiagram",
38613
+ "classDiagram",
38614
+ "stateDiagram",
38615
+ "stateDiagram-v2",
38616
+ "erDiagram",
38617
+ "journey",
38618
+ "gantt",
38619
+ "pie",
38620
+ "quadrantChart",
38621
+ "requirementDiagram",
38622
+ "gitGraph",
38623
+ "C4Context",
38624
+ "mindmap",
38625
+ "timeline",
38626
+ "zenuml",
38627
+ "sankey",
38628
+ "xychart",
38629
+ "block"
38630
+ ];
38631
+ const re = new RegExp(
38632
+ `^(?:%%{.*?}%%[\\s\\n]*)?\\b${chartTypes.map((x) => `${x}(-beta)?`).join("|")}\\b`
38633
+ );
38634
+ return re.test(text.trim());
38635
+ };
38636
+
38637
+ // components/App.tsx
38344
38638
  import { Fragment as Fragment21, jsx as jsx126, jsxs as jsxs71 } from "react/jsx-runtime";
38345
38639
  var AppContext = React38.createContext(null);
38346
38640
  var AppPropsContext = React38.createContext(null);
@@ -38545,10 +38839,7 @@ var App = class _App extends React38.Component {
38545
38839
  container: this.excalidrawContainerRef.current,
38546
38840
  id: this.id
38547
38841
  };
38548
- this.fonts = new Fonts({
38549
- scene: this.scene,
38550
- onSceneUpdated: this.onSceneUpdated
38551
- });
38842
+ this.fonts = new Fonts({ scene: this.scene });
38552
38843
  this.history = new History();
38553
38844
  this.actionManager.registerAll(actions);
38554
38845
  this.actionManager.registerAction(
@@ -38707,7 +38998,7 @@ var App = class _App extends React38.Component {
38707
38998
  return false;
38708
38999
  });
38709
39000
  if (updated) {
38710
- this.scene.informMutation();
39001
+ this.scene.triggerUpdate();
38711
39002
  }
38712
39003
  this.iFrameRefs.forEach((ref, id) => {
38713
39004
  if (!iframeLikes.has(id)) {
@@ -39114,9 +39405,9 @@ var App = class _App extends React38.Component {
39114
39405
  render() {
39115
39406
  const selectedElements = this.scene.getSelectedElements(this.state);
39116
39407
  const { renderTopRightUI, renderCustomStats } = this.props;
39117
- const versionNonce = this.scene.getVersionNonce();
39408
+ const sceneNonce = this.scene.getSceneNonce();
39118
39409
  const { elementsMap, visibleElements } = this.renderer.getRenderableElements({
39119
- versionNonce,
39410
+ sceneNonce,
39120
39411
  zoom: this.state.zoom,
39121
39412
  offsetLeft: this.state.offsetLeft,
39122
39413
  offsetTop: this.state.offsetTop,
@@ -39313,7 +39604,7 @@ var App = class _App extends React38.Component {
39313
39604
  elementsMap,
39314
39605
  allElementsMap,
39315
39606
  visibleElements,
39316
- versionNonce,
39607
+ sceneNonce,
39317
39608
  selectionNonce: this.state.selectionElement?.versionNonce,
39318
39609
  scale: window.devicePixelRatio,
39319
39610
  appState: this.state,
@@ -39334,8 +39625,9 @@ var App = class _App extends React38.Component {
39334
39625
  canvas: this.interactiveCanvas,
39335
39626
  elementsMap,
39336
39627
  visibleElements,
39628
+ allElementsMap,
39337
39629
  selectedElements,
39338
- versionNonce,
39630
+ sceneNonce,
39339
39631
  selectionNonce: this.state.selectionElement?.versionNonce,
39340
39632
  scale: window.devicePixelRatio,
39341
39633
  appState: this.state,
@@ -39429,7 +39721,7 @@ var App = class _App extends React38.Component {
39429
39721
  );
39430
39722
  }
39431
39723
  this.magicGenerations.set(frameElement.id, data);
39432
- this.onSceneUpdated();
39724
+ this.triggerRender();
39433
39725
  };
39434
39726
  getTextFromElements(elements) {
39435
39727
  const text = elements.reduce((acc, element) => {
@@ -39913,7 +40205,7 @@ var App = class _App extends React38.Component {
39913
40205
  this.store.onStoreIncrementEmitter.on((increment) => {
39914
40206
  this.history.record(increment.elementsChange, increment.appStateChange);
39915
40207
  });
39916
- this.scene.addCallback(this.onSceneUpdated);
40208
+ this.scene.onUpdate(this.triggerRender);
39917
40209
  this.addEventListeners();
39918
40210
  if (this.props.autoFocus && this.excalidrawContainerRef.current) {
39919
40211
  this.focusContainer();
@@ -39949,6 +40241,7 @@ var App = class _App extends React38.Component {
39949
40241
  componentWillUnmount() {
39950
40242
  this.renderer.destroy();
39951
40243
  this.scene = new Scene_default();
40244
+ this.fonts = new Fonts({ scene: this.scene });
39952
40245
  this.renderer = new Renderer(this.scene);
39953
40246
  this.files = {};
39954
40247
  this.imageCache.clear();
@@ -40013,7 +40306,7 @@ var App = class _App extends React38.Component {
40013
40306
  addEventListener(document, "keyup" /* KEYUP */, this.onKeyUp, { passive: true }),
40014
40307
  addEventListener(
40015
40308
  document,
40016
- "mousemove" /* MOUSE_MOVE */,
40309
+ "pointermove" /* POINTER_MOVE */,
40017
40310
  this.updateCurrentCursorPosition
40018
40311
  ),
40019
40312
  // rerender text elements on font load to fix #637 && #1553
@@ -40042,6 +40335,7 @@ var App = class _App extends React38.Component {
40042
40335
  ),
40043
40336
  addEventListener(window, "focus" /* FOCUS */, () => {
40044
40337
  this.maybeCleanupAfterMissingPointerUp(null);
40338
+ this.triggerRender(true);
40045
40339
  })
40046
40340
  );
40047
40341
  if (this.state.viewModeEnabled) {
@@ -40373,6 +40667,27 @@ var App = class _App extends React38.Component {
40373
40667
  retainSeed: isPlainPaste
40374
40668
  });
40375
40669
  } else if (data.text) {
40670
+ if (data.text && isMaybeMermaidDefinition(data.text)) {
40671
+ const api = await import("@excalidraw/mermaid-to-excalidraw");
40672
+ try {
40673
+ const { elements: skeletonElements, files } = await api.parseMermaidToExcalidraw(data.text, {
40674
+ fontSize: DEFAULT_FONT_SIZE
40675
+ });
40676
+ const elements = convertToExcalidrawElements(skeletonElements, {
40677
+ regenerateIds: true
40678
+ });
40679
+ this.addElementsFromPasteOrLibrary({
40680
+ elements,
40681
+ files,
40682
+ position: "cursor"
40683
+ });
40684
+ return;
40685
+ } catch (err) {
40686
+ console.warn(
40687
+ `parsing pasted text as mermaid definition failed: ${err.message}`
40688
+ );
40689
+ }
40690
+ }
40376
40691
  const nonEmptyLines = normalizeEOL(data.text).split(/\n+/).map((s) => s.trim()).filter(Boolean);
40377
40692
  const embbeddableUrls = nonEmptyLines.map((str) => maybeParseEmbedSrc(str)).filter((string) => {
40378
40693
  return embeddableURLValidator(string, this.props.validateEmbeddable) && (/^(http|https):\/\/[^\s/$.?#].[^\s]*$/.test(string) || getEmbedLink(string)?.type === "video");
@@ -40592,28 +40907,42 @@ var App = class _App extends React38.Component {
40592
40907
  text,
40593
40908
  fontSize: this.state.currentItemFontSize,
40594
40909
  fontFamily: this.state.currentItemFontFamily,
40595
- textAlign: this.state.currentItemTextAlign,
40910
+ textAlign: DEFAULT_TEXT_ALIGN,
40596
40911
  verticalAlign: DEFAULT_VERTICAL_ALIGN,
40597
40912
  locked: false
40598
40913
  };
40914
+ const fontString = getFontString({
40915
+ fontSize: textElementProps.fontSize,
40916
+ fontFamily: textElementProps.fontFamily
40917
+ });
40918
+ const lineHeight = getDefaultLineHeight(textElementProps.fontFamily);
40919
+ const [x1, , x2] = getVisibleSceneBounds(this.state);
40920
+ const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200);
40599
40921
  const LINE_GAP = 10;
40600
40922
  let currentY = y;
40601
40923
  const lines = isPlainPaste ? [text] : text.split("\n");
40602
40924
  const textElements = lines.reduce(
40603
40925
  (acc, line, idx) => {
40604
- const text2 = line.trim();
40605
- const lineHeight = getDefaultLineHeight(textElementProps.fontFamily);
40606
- if (text2.length) {
40926
+ const originalText = line.trim();
40927
+ if (originalText.length) {
40607
40928
  const topLayerFrame = this.getTopLayerFrameAtSceneCoords({
40608
40929
  x,
40609
40930
  y: currentY
40610
40931
  });
40932
+ let metrics = measureText(originalText, fontString, lineHeight);
40933
+ const isTextWrapped = metrics.width > maxTextWidth;
40934
+ const text2 = isTextWrapped ? wrapText(originalText, fontString, maxTextWidth) : originalText;
40935
+ metrics = isTextWrapped ? measureText(text2, fontString, lineHeight) : metrics;
40936
+ const startX = x - metrics.width / 2;
40937
+ const startY = currentY - metrics.height / 2;
40611
40938
  const element = newTextElement({
40612
40939
  ...textElementProps,
40613
- x,
40614
- y: currentY,
40940
+ x: startX,
40941
+ y: startY,
40615
40942
  text: text2,
40943
+ originalText,
40616
40944
  lineHeight,
40945
+ autoResize: !isTextWrapped,
40617
40946
  frameId: topLayerFrame ? topLayerFrame.id : null
40618
40947
  });
40619
40948
  acc.push(element);
@@ -40826,7 +41155,7 @@ var App = class _App extends React38.Component {
40826
41155
  ShapeCache.delete(element);
40827
41156
  }
40828
41157
  });
40829
- this.scene.informMutation();
41158
+ this.scene.triggerUpdate();
40830
41159
  this.addNewImagesToImageCache();
40831
41160
  }
40832
41161
  );
@@ -40866,8 +41195,12 @@ var App = class _App extends React38.Component {
40866
41195
  }
40867
41196
  }
40868
41197
  );
40869
- onSceneUpdated = () => {
40870
- this.setState({});
41198
+ triggerRender = (force) => {
41199
+ if (force === true) {
41200
+ this.scene.triggerUpdate();
41201
+ } else {
41202
+ this.setState({});
41203
+ }
40871
41204
  };
40872
41205
  /**
40873
41206
  * @returns whether the menu was toggled on or off
@@ -41270,21 +41603,22 @@ var App = class _App extends React38.Component {
41270
41603
  isExistingElement = false
41271
41604
  }) {
41272
41605
  const elementsMap = this.scene.getElementsMapIncludingDeleted();
41273
- const updateElement = (text, originalText, isDeleted) => {
41606
+ const updateElement = (nextOriginalText, isDeleted) => {
41274
41607
  this.scene.replaceAllElements([
41275
41608
  // Not sure why we include deleted elements as well hence using deleted elements map
41276
41609
  ...this.scene.getElementsIncludingDeleted().map((_element) => {
41277
41610
  if (_element.id === element.id && isTextElement(_element)) {
41278
- return updateTextElement(
41279
- _element,
41280
- getContainerElement(_element, elementsMap),
41281
- elementsMap,
41282
- {
41283
- text,
41284
- isDeleted,
41285
- originalText
41286
- }
41287
- );
41611
+ return newElementWith(_element, {
41612
+ originalText: nextOriginalText,
41613
+ isDeleted: isDeleted ?? _element.isDeleted,
41614
+ // returns (wrapped) text and new dimensions
41615
+ ...refreshTextDimensions(
41616
+ _element,
41617
+ getContainerElement(_element, elementsMap),
41618
+ elementsMap,
41619
+ nextOriginalText
41620
+ )
41621
+ });
41288
41622
  }
41289
41623
  return _element;
41290
41624
  })
@@ -41306,15 +41640,15 @@ var App = class _App extends React38.Component {
41306
41640
  viewportY - this.state.offsetTop
41307
41641
  ];
41308
41642
  },
41309
- onChange: withBatchedUpdates((text) => {
41310
- updateElement(text, text, false);
41643
+ onChange: withBatchedUpdates((nextOriginalText) => {
41644
+ updateElement(nextOriginalText, false);
41311
41645
  if (isNonDeletedElement(element)) {
41312
41646
  updateBoundElements(element, elementsMap);
41313
41647
  }
41314
41648
  }),
41315
- onSubmit: withBatchedUpdates(({ text, viaKeyboard, originalText }) => {
41316
- const isDeleted = !text.trim();
41317
- updateElement(text, originalText, isDeleted);
41649
+ onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
41650
+ const isDeleted = !nextOriginalText.trim();
41651
+ updateElement(nextOriginalText, isDeleted);
41318
41652
  if (!isDeleted && viaKeyboard) {
41319
41653
  const elementIdToSelect = element.containerId ? element.containerId : element.id;
41320
41654
  this.setState((prevState) => ({
@@ -41346,10 +41680,15 @@ var App = class _App extends React38.Component {
41346
41680
  }),
41347
41681
  element,
41348
41682
  excalidrawContainer: this.excalidrawContainerRef.current,
41349
- app: this
41683
+ app: this,
41684
+ // when text is selected, it's hard (at least on iOS) to re-position the
41685
+ // caret (i.e. deselect). There's not much use for always selecting
41686
+ // the text on edit anyway (and users can select-all from contextmenu
41687
+ // if needed)
41688
+ autoSelect: !this.device.isTouchScreen
41350
41689
  });
41351
41690
  this.deselectElements();
41352
- updateElement(element.text, element.originalText, false);
41691
+ updateElement(element.originalText, false);
41353
41692
  }
41354
41693
  deselectElements() {
41355
41694
  this.setState({
@@ -41548,7 +41887,8 @@ var App = class _App extends React38.Component {
41548
41887
  sceneX,
41549
41888
  sceneY,
41550
41889
  insertAtParentCenter = true,
41551
- container
41890
+ container,
41891
+ autoEdit = true
41552
41892
  }) => {
41553
41893
  let shouldBindToContainer = false;
41554
41894
  let parentCenterPosition = insertAtParentCenter && this.getTextWysiwygSnappedToCenterPosition(
@@ -41651,12 +41991,16 @@ var App = class _App extends React38.Component {
41651
41991
  this.scene.insertElement(element);
41652
41992
  }
41653
41993
  }
41654
- this.setState({
41655
- editingElement: element
41656
- });
41657
- this.handleTextWysiwyg(element, {
41658
- isExistingElement: !!existingTextElement
41659
- });
41994
+ if (autoEdit || existingTextElement || container) {
41995
+ this.handleTextWysiwyg(element, {
41996
+ isExistingElement: !!existingTextElement
41997
+ });
41998
+ } else {
41999
+ this.setState({
42000
+ draggingElement: element,
42001
+ multiElement: null
42002
+ });
42003
+ }
41660
42004
  };
41661
42005
  handleCanvasDoubleClick = (event) => {
41662
42006
  if (this.state.multiElement) {
@@ -41848,8 +42192,11 @@ var App = class _App extends React38.Component {
41848
42192
  );
41849
42193
  this.translateCanvas({
41850
42194
  zoom: zoomState.zoom,
41851
- scrollX: zoomState.scrollX + deltaX / nextZoom,
41852
- scrollY: zoomState.scrollY + deltaY / nextZoom,
42195
+ // 2x multiplier is just a magic number that makes this work correctly
42196
+ // on touchscreen devices (note: if we get report that panning is slower/faster
42197
+ // than actual movement, consider swapping with devicePixelRatio)
42198
+ scrollX: zoomState.scrollX + 2 * (deltaX / nextZoom),
42199
+ scrollY: zoomState.scrollY + 2 * (deltaY / nextZoom),
41853
42200
  shouldCacheIgnoreZoom: true
41854
42201
  });
41855
42202
  });
@@ -42198,7 +42545,7 @@ var App = class _App extends React38.Component {
42198
42545
  }
42199
42546
  }
42200
42547
  this.elementsPendingErasure = new Set(this.elementsPendingErasure);
42201
- this.onSceneUpdated();
42548
+ this.triggerRender();
42202
42549
  }
42203
42550
  };
42204
42551
  // set touch moving for mobile context menu
@@ -42392,7 +42739,6 @@ var App = class _App extends React38.Component {
42392
42739
  }
42393
42740
  if (this.state.activeTool.type === "text") {
42394
42741
  this.handleTextOnPointerDown(event, pointerDownState);
42395
- return;
42396
42742
  } else if (this.state.activeTool.type === "arrow" || this.state.activeTool.type === "line") {
42397
42743
  this.handleLinearElementOnPointerDown(
42398
42744
  event,
@@ -42962,7 +43308,8 @@ var App = class _App extends React38.Component {
42962
43308
  sceneX,
42963
43309
  sceneY,
42964
43310
  insertAtParentCenter: !event.altKey,
42965
- container
43311
+ container,
43312
+ autoEdit: false
42966
43313
  });
42967
43314
  resetCursor(this.interactiveCanvas);
42968
43315
  if (!this.state.activeTool.locked) {
@@ -43967,6 +44314,24 @@ var App = class _App extends React38.Component {
43967
44314
  }
43968
44315
  return;
43969
44316
  }
44317
+ if (isTextElement(draggingElement)) {
44318
+ const minWidth = getMinTextElementWidth(
44319
+ getFontString({
44320
+ fontSize: draggingElement.fontSize,
44321
+ fontFamily: draggingElement.fontFamily
44322
+ }),
44323
+ draggingElement.lineHeight
44324
+ );
44325
+ if (draggingElement.width < minWidth) {
44326
+ mutateElement(draggingElement, {
44327
+ autoResize: true
44328
+ });
44329
+ }
44330
+ this.resetCursor();
44331
+ this.handleTextWysiwyg(draggingElement, {
44332
+ isExistingElement: true
44333
+ });
44334
+ }
43970
44335
  if (activeTool.type !== "selection" && draggingElement && isInvisiblySmallElement(draggingElement)) {
43971
44336
  this.updateScene({
43972
44337
  elements: this.scene.getElementsIncludingDeleted().filter((el) => el.id !== draggingElement.id),
@@ -44002,7 +44367,7 @@ var App = class _App extends React38.Component {
44002
44367
  [linearElement],
44003
44368
  this.scene.getNonDeletedElementsMap()
44004
44369
  );
44005
- this.scene.informMutation();
44370
+ this.scene.triggerUpdate();
44006
44371
  }
44007
44372
  }
44008
44373
  }
@@ -44355,7 +44720,7 @@ var App = class _App extends React38.Component {
44355
44720
  }
44356
44721
  restoreReadyToEraseElements = () => {
44357
44722
  this.elementsPendingErasure = /* @__PURE__ */ new Set();
44358
- this.onSceneUpdated();
44723
+ this.triggerRender();
44359
44724
  };
44360
44725
  eraseElements = () => {
44361
44726
  let didChange = false;
@@ -44670,7 +45035,7 @@ var App = class _App extends React38.Component {
44670
45035
  files
44671
45036
  );
44672
45037
  if (updatedFiles.size) {
44673
- this.scene.informMutation();
45038
+ this.scene.triggerUpdate();
44674
45039
  }
44675
45040
  }
44676
45041
  };
@@ -44956,7 +45321,8 @@ var App = class _App extends React38.Component {
44956
45321
  distance(pointerDownState.origin.x, pointerCoords.x),
44957
45322
  distance(pointerDownState.origin.y, pointerCoords.y),
44958
45323
  shouldMaintainAspectRatio(event),
44959
- shouldResizeFromCenter(event)
45324
+ shouldResizeFromCenter(event),
45325
+ this.state.zoom.value
44960
45326
  );
44961
45327
  } else {
44962
45328
  let [gridX, gridY] = getGridPoint(
@@ -44997,6 +45363,7 @@ var App = class _App extends React38.Component {
44997
45363
  distance(pointerDownState.originInGrid.y, gridY),
44998
45364
  isImageElement(draggingElement) ? !shouldMaintainAspectRatio(event) : shouldMaintainAspectRatio(event),
44999
45365
  shouldResizeFromCenter(event),
45366
+ this.state.zoom.value,
45000
45367
  aspectRatio,
45001
45368
  this.state.originSnapOffset
45002
45369
  );
@@ -45143,6 +45510,7 @@ var App = class _App extends React38.Component {
45143
45510
  return [actionCopy, ...options];
45144
45511
  }
45145
45512
  return [
45513
+ CONTEXT_MENU_SEPARATOR,
45146
45514
  actionCut,
45147
45515
  actionCopy,
45148
45516
  actionPaste,
@@ -45155,6 +45523,7 @@ var App = class _App extends React38.Component {
45155
45523
  actionPasteStyles,
45156
45524
  CONTEXT_MENU_SEPARATOR,
45157
45525
  actionGroup,
45526
+ actionTextAutoResize,
45158
45527
  actionUnbindText,
45159
45528
  actionBindText,
45160
45529
  actionWrapTextInContainer,