@excalidraw/excalidraw 0.17.1-c0b80a0 → 0.17.1-c329470

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 (178) hide show
  1. package/dist/browser/dev/excalidraw-assets-dev/{chunk-JGDL4H2X.js → chunk-3DLVY5XU.js} +8272 -6864
  2. package/dist/browser/dev/excalidraw-assets-dev/chunk-3DLVY5XU.js.map +7 -0
  3. package/dist/browser/dev/excalidraw-assets-dev/{chunk-V7NFEZA6.js → chunk-NOAEU4NM.js} +9 -2
  4. package/dist/browser/dev/excalidraw-assets-dev/chunk-NOAEU4NM.js.map +7 -0
  5. package/dist/browser/dev/excalidraw-assets-dev/{en-ZSVWGT55.js → en-7IBTMWBG.js} +2 -2
  6. package/dist/browser/dev/excalidraw-assets-dev/{image-RJG3J34Y.js → image-N5AC7SEK.js} +2 -6
  7. package/dist/browser/dev/index.css +85 -50
  8. package/dist/browser/dev/index.css.map +3 -3
  9. package/dist/browser/dev/index.js +4375 -3766
  10. package/dist/browser/dev/index.js.map +4 -4
  11. package/dist/browser/prod/excalidraw-assets/{chunk-LDVEIXGO.js → chunk-7CSIPVOW.js} +2 -2
  12. package/dist/browser/prod/excalidraw-assets/chunk-TX3BU7T2.js +47 -0
  13. package/dist/browser/prod/excalidraw-assets/{en-UPNEHLDS.js → en-LOGQBETY.js} +1 -1
  14. package/dist/browser/prod/excalidraw-assets/image-3V4U7GZE.js +1 -0
  15. package/dist/browser/prod/index.css +1 -1
  16. package/dist/browser/prod/index.js +40 -40
  17. package/dist/dev/index.css +85 -50
  18. package/dist/dev/index.css.map +3 -3
  19. package/dist/dev/index.js +8688 -6706
  20. package/dist/dev/index.js.map +4 -4
  21. package/dist/{prod/locales/en-ZXYG7GCR.json → dev/locales/en-V6KXFSCK.json} +8 -1
  22. package/dist/excalidraw/actions/actionAlign.d.ts +7 -6
  23. package/dist/excalidraw/actions/actionAlign.js +14 -14
  24. package/dist/excalidraw/actions/actionClipboard.d.ts +7 -3
  25. package/dist/excalidraw/actions/actionDeleteSelected.d.ts +7 -3
  26. package/dist/excalidraw/actions/actionDeleteSelected.js +103 -34
  27. package/dist/excalidraw/actions/actionDuplicateSelection.js +105 -95
  28. package/dist/excalidraw/actions/actionFlip.js +16 -7
  29. package/dist/excalidraw/actions/actionFrame.d.ts +493 -0
  30. package/dist/excalidraw/actions/actionFrame.js +45 -2
  31. package/dist/excalidraw/actions/actionGroup.js +6 -4
  32. package/dist/excalidraw/actions/actionProperties.js +145 -116
  33. package/dist/excalidraw/actions/actionSelectAll.js +4 -3
  34. package/dist/excalidraw/actions/shortcuts.d.ts +1 -1
  35. package/dist/excalidraw/actions/shortcuts.js +1 -0
  36. package/dist/excalidraw/actions/types.d.ts +1 -1
  37. package/dist/excalidraw/align.d.ts +2 -1
  38. package/dist/excalidraw/align.js +15 -6
  39. package/dist/excalidraw/clipboard.d.ts +27 -5
  40. package/dist/excalidraw/clipboard.js +55 -28
  41. package/dist/excalidraw/components/Actions.d.ts +2 -1
  42. package/dist/excalidraw/components/Actions.js +4 -2
  43. package/dist/excalidraw/components/ActiveConfirmDialog.d.ts +1 -1
  44. package/dist/excalidraw/components/ActiveConfirmDialog.js +2 -3
  45. package/dist/excalidraw/components/App.d.ts +1 -0
  46. package/dist/excalidraw/components/App.js +216 -111
  47. package/dist/excalidraw/components/ColorPicker/ColorInput.js +2 -3
  48. package/dist/excalidraw/components/ColorPicker/ColorPicker.js +2 -3
  49. package/dist/excalidraw/components/ColorPicker/CustomColorList.js +1 -1
  50. package/dist/excalidraw/components/ColorPicker/Picker.js +1 -1
  51. package/dist/excalidraw/components/ColorPicker/PickerColorList.js +1 -1
  52. package/dist/excalidraw/components/ColorPicker/ShadeList.js +1 -1
  53. package/dist/excalidraw/components/ColorPicker/colorPickerUtils.d.ts +1 -1
  54. package/dist/excalidraw/components/ColorPicker/colorPickerUtils.js +1 -1
  55. package/dist/excalidraw/components/CommandPalette/CommandPalette.js +3 -3
  56. package/dist/excalidraw/components/ConfirmDialog.js +17 -5
  57. package/dist/excalidraw/components/Dialog.js +2 -3
  58. package/dist/excalidraw/components/EyeDropper.d.ts +1 -1
  59. package/dist/excalidraw/components/EyeDropper.js +1 -1
  60. package/dist/excalidraw/components/IconPicker.d.ts +2 -2
  61. package/dist/excalidraw/components/IconPicker.js +56 -53
  62. package/dist/excalidraw/components/LayerUI.js +6 -6
  63. package/dist/excalidraw/components/LibraryMenu.d.ts +2 -16
  64. package/dist/excalidraw/components/LibraryMenu.js +70 -28
  65. package/dist/excalidraw/components/LibraryMenuHeaderContent.js +4 -5
  66. package/dist/excalidraw/components/MobileMenu.js +1 -1
  67. package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirm.js +2 -3
  68. package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.d.ts +1 -1
  69. package/dist/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.js +2 -3
  70. package/dist/excalidraw/components/Range.d.ts +9 -0
  71. package/dist/excalidraw/components/Range.js +24 -0
  72. package/dist/excalidraw/components/SearchMenu.d.ts +1 -1
  73. package/dist/excalidraw/components/SearchMenu.js +3 -4
  74. package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +1 -1
  75. package/dist/excalidraw/components/Sidebar/Sidebar.js +2 -3
  76. package/dist/excalidraw/components/Stats/Collapsible.d.ts +2 -1
  77. package/dist/excalidraw/components/Stats/Collapsible.js +2 -2
  78. package/dist/excalidraw/components/Stats/Dimension.js +94 -8
  79. package/dist/excalidraw/components/Stats/MultiDimension.js +8 -5
  80. package/dist/excalidraw/components/Stats/Position.js +63 -3
  81. package/dist/excalidraw/components/Stats/index.js +21 -4
  82. package/dist/excalidraw/components/Stats/utils.d.ts +1 -1
  83. package/dist/excalidraw/components/Stats/utils.js +2 -55
  84. package/dist/excalidraw/components/TTDDialog/TTDDialog.js +1 -1
  85. package/dist/excalidraw/components/ToolButton.js +4 -9
  86. package/dist/excalidraw/components/hoc/withInternalFallback.js +3 -3
  87. package/dist/excalidraw/components/hyperlink/Hyperlink.js +6 -12
  88. package/dist/excalidraw/components/icons.d.ts +9 -0
  89. package/dist/excalidraw/components/icons.js +4 -4
  90. package/dist/excalidraw/components/main-menu/DefaultItems.js +2 -3
  91. package/dist/excalidraw/constants.d.ts +5 -1
  92. package/dist/excalidraw/constants.js +9 -1
  93. package/dist/excalidraw/context/tunnels.d.ts +2 -1
  94. package/dist/excalidraw/context/tunnels.js +3 -1
  95. package/dist/excalidraw/data/blob.d.ts +1 -0
  96. package/dist/excalidraw/data/blob.js +7 -3
  97. package/dist/excalidraw/data/filesystem.d.ts +2 -1
  98. package/dist/excalidraw/data/filesystem.js +1 -0
  99. package/dist/excalidraw/data/image.d.ts +0 -6
  100. package/dist/excalidraw/data/image.js +1 -43
  101. package/dist/excalidraw/data/index.js +6 -6
  102. package/dist/excalidraw/data/library.d.ts +9 -3
  103. package/dist/excalidraw/data/library.js +43 -6
  104. package/dist/excalidraw/data/restore.js +26 -8
  105. package/dist/excalidraw/data/url.d.ts +0 -1
  106. package/dist/excalidraw/data/url.js +2 -4
  107. package/dist/excalidraw/editor-jotai.d.ts +56 -0
  108. package/dist/excalidraw/editor-jotai.js +8 -0
  109. package/dist/excalidraw/element/binding.d.ts +9 -6
  110. package/dist/excalidraw/element/binding.js +124 -44
  111. package/dist/excalidraw/element/bounds.js +10 -0
  112. package/dist/excalidraw/element/cropElement.d.ts +5 -0
  113. package/dist/excalidraw/element/cropElement.js +28 -1
  114. package/dist/excalidraw/element/dragElements.js +13 -7
  115. package/dist/excalidraw/element/elbowArrow.d.ts +16 -0
  116. package/dist/excalidraw/element/elbowArrow.js +1268 -0
  117. package/dist/excalidraw/element/embeddable.js +4 -5
  118. package/dist/excalidraw/element/flowchart.d.ts +1 -1
  119. package/dist/excalidraw/element/flowchart.js +25 -9
  120. package/dist/excalidraw/element/heading.d.ts +5 -1
  121. package/dist/excalidraw/element/heading.js +5 -1
  122. package/dist/excalidraw/element/image.js +19 -5
  123. package/dist/excalidraw/element/linearElementEditor.d.ts +9 -10
  124. package/dist/excalidraw/element/linearElementEditor.js +97 -38
  125. package/dist/excalidraw/element/mutateElement.d.ts +3 -1
  126. package/dist/excalidraw/element/mutateElement.js +31 -4
  127. package/dist/excalidraw/element/newElement.d.ts +8 -12
  128. package/dist/excalidraw/element/newElement.js +36 -21
  129. package/dist/excalidraw/element/resizeElements.d.ts +20 -5
  130. package/dist/excalidraw/element/resizeElements.js +593 -361
  131. package/dist/excalidraw/element/sortElements.js +1 -4
  132. package/dist/excalidraw/element/types.d.ts +23 -1
  133. package/dist/excalidraw/fonts/Fonts.d.ts +0 -16
  134. package/dist/excalidraw/fonts/Fonts.js +6 -31
  135. package/dist/excalidraw/frame.d.ts +11 -5
  136. package/dist/excalidraw/frame.js +146 -35
  137. package/dist/excalidraw/groups.js +3 -0
  138. package/dist/excalidraw/hooks/useLibraryItemSvg.d.ts +1 -1
  139. package/dist/excalidraw/hooks/useLibraryItemSvg.js +2 -3
  140. package/dist/excalidraw/hooks/useScrollPosition.js +1 -1
  141. package/dist/excalidraw/i18n.js +3 -4
  142. package/dist/excalidraw/index.js +3 -4
  143. package/dist/excalidraw/locales/en.json +8 -1
  144. package/dist/excalidraw/renderer/interactiveScene.js +43 -32
  145. package/dist/excalidraw/renderer/staticScene.js +6 -4
  146. package/dist/excalidraw/renderer/staticSvgScene.js +1 -1
  147. package/dist/excalidraw/scene/Shape.js +40 -17
  148. package/dist/excalidraw/scene/comparisons.d.ts +0 -477
  149. package/dist/excalidraw/scene/comparisons.js +0 -37
  150. package/dist/excalidraw/scene/export.d.ts +7 -0
  151. package/dist/excalidraw/scene/export.js +107 -43
  152. package/dist/excalidraw/scene/index.d.ts +1 -1
  153. package/dist/excalidraw/scene/index.js +1 -1
  154. package/dist/excalidraw/scene/selection.js +4 -1
  155. package/dist/excalidraw/types.d.ts +15 -0
  156. package/dist/excalidraw/utility-types.d.ts +1 -0
  157. package/dist/excalidraw/utils.d.ts +8 -1
  158. package/dist/excalidraw/utils.js +9 -0
  159. package/dist/excalidraw/visualdebug.d.ts +8 -1
  160. package/dist/excalidraw/visualdebug.js +3 -0
  161. package/dist/math/line.d.ts +19 -0
  162. package/dist/math/line.js +32 -3
  163. package/dist/math/point.d.ts +10 -0
  164. package/dist/math/point.js +12 -1
  165. package/dist/prod/index.css +1 -1
  166. package/dist/prod/index.js +29 -44
  167. package/dist/{dev/locales/en-ZXYG7GCR.json → prod/locales/en-V6KXFSCK.json} +8 -1
  168. package/package.json +5 -2
  169. package/dist/browser/dev/excalidraw-assets-dev/chunk-JGDL4H2X.js.map +0 -7
  170. package/dist/browser/dev/excalidraw-assets-dev/chunk-V7NFEZA6.js.map +0 -7
  171. package/dist/browser/prod/excalidraw-assets/chunk-S2XKB3DE.js +0 -62
  172. package/dist/browser/prod/excalidraw-assets/image-OFI2YYMP.js +0 -1
  173. package/dist/excalidraw/element/routing.d.ts +0 -12
  174. package/dist/excalidraw/element/routing.js +0 -642
  175. package/dist/excalidraw/jotai.d.ts +0 -34
  176. package/dist/excalidraw/jotai.js +0 -18
  177. /package/dist/browser/dev/excalidraw-assets-dev/{en-ZSVWGT55.js.map → en-7IBTMWBG.js.map} +0 -0
  178. /package/dist/browser/dev/excalidraw-assets-dev/{image-RJG3J34Y.js.map → image-N5AC7SEK.js.map} +0 -0
@@ -9,7 +9,7 @@ import { FontPicker } from "../components/FontPicker/FontPicker";
9
9
  // TODO barnabasmolnar/editor-redesign
10
10
  // TextAlignTopIcon, TextAlignBottomIcon,TextAlignMiddleIcon,
11
11
  // ArrowHead icons
12
- import { ArrowheadArrowIcon, ArrowheadBarIcon, ArrowheadCircleIcon, ArrowheadTriangleIcon, ArrowheadNoneIcon, StrokeStyleDashedIcon, StrokeStyleDottedIcon, TextAlignTopIcon, TextAlignBottomIcon, TextAlignMiddleIcon, FillHachureIcon, FillCrossHatchIcon, FillSolidIcon, SloppinessArchitectIcon, SloppinessArtistIcon, SloppinessCartoonistIcon, StrokeWidthBaseIcon, StrokeWidthBoldIcon, StrokeWidthExtraBoldIcon, FontSizeSmallIcon, FontSizeMediumIcon, FontSizeLargeIcon, FontSizeExtraLargeIcon, EdgeSharpIcon, EdgeRoundIcon, TextAlignLeftIcon, TextAlignCenterIcon, TextAlignRightIcon, FillZigZagIcon, ArrowheadTriangleOutlineIcon, ArrowheadCircleOutlineIcon, ArrowheadDiamondIcon, ArrowheadDiamondOutlineIcon, fontSizeIcon, sharpArrowIcon, roundArrowIcon, elbowArrowIcon, } from "../components/icons";
12
+ import { ArrowheadArrowIcon, ArrowheadBarIcon, ArrowheadCircleIcon, ArrowheadTriangleIcon, ArrowheadNoneIcon, StrokeStyleDashedIcon, StrokeStyleDottedIcon, TextAlignTopIcon, TextAlignBottomIcon, TextAlignMiddleIcon, FillHachureIcon, FillCrossHatchIcon, FillSolidIcon, SloppinessArchitectIcon, SloppinessArtistIcon, SloppinessCartoonistIcon, StrokeWidthBaseIcon, StrokeWidthBoldIcon, StrokeWidthExtraBoldIcon, FontSizeSmallIcon, FontSizeMediumIcon, FontSizeLargeIcon, FontSizeExtraLargeIcon, EdgeSharpIcon, EdgeRoundIcon, TextAlignLeftIcon, TextAlignCenterIcon, TextAlignRightIcon, FillZigZagIcon, ArrowheadTriangleOutlineIcon, ArrowheadCircleOutlineIcon, ArrowheadDiamondIcon, ArrowheadDiamondOutlineIcon, fontSizeIcon, sharpArrowIcon, roundArrowIcon, elbowArrowIcon, ArrowheadCrowfootIcon, ArrowheadCrowfootOneIcon, ArrowheadCrowfootOneOrManyIcon, } from "../components/icons";
13
13
  import { ARROW_TYPE, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, FONT_FAMILY, ROUNDNESS, STROKE_WIDTH, VERTICAL_ALIGN, } from "../constants";
14
14
  import { getNonDeletedElements, isTextElement, redrawTextBoundingBox, } from "../element";
15
15
  import { mutateElement, newElementWith } from "../element/mutateElement";
@@ -24,10 +24,10 @@ import { arrayToMap, getFontFamilyString, getShortcutKey, tupleToCoors, } from "
24
24
  import { register } from "./register";
25
25
  import { StoreAction } from "../store";
26
26
  import { Fonts, getLineHeight } from "../fonts";
27
- import { bindLinearElement, bindPointToSnapToElementOutline, calculateFixedPointForElbowArrowBinding, getHoveredElementForBinding, } from "../element/binding";
28
- import { mutateElbowArrow } from "../element/routing";
27
+ import { bindLinearElement, bindPointToSnapToElementOutline, calculateFixedPointForElbowArrowBinding, getHoveredElementForBinding, updateBoundElements, } from "../element/binding";
29
28
  import { LinearElementEditor } from "../element/linearElementEditor";
30
- import { pointFrom, vector } from "../../math";
29
+ import { pointFrom } from "../../math";
30
+ import { Range } from "../components/Range";
31
31
  const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1;
32
32
  export const changeProperty = (elements, appState, callback, includeBoundText = false) => {
33
33
  const selectedElementIds = arrayToMap(getSelectedElements(elements, appState, {
@@ -83,20 +83,30 @@ const offsetElementAfterFontResize = (prevElement, nextElement) => {
83
83
  };
84
84
  const changeFontSize = (elements, appState, app, getNewFontSize, fallbackValue) => {
85
85
  const newFontSizes = new Set();
86
+ const updatedElements = changeProperty(elements, appState, (oldElement) => {
87
+ if (isTextElement(oldElement)) {
88
+ const newFontSize = getNewFontSize(oldElement);
89
+ newFontSizes.add(newFontSize);
90
+ let newElement = newElementWith(oldElement, {
91
+ fontSize: newFontSize,
92
+ });
93
+ redrawTextBoundingBox(newElement, app.scene.getContainerElement(oldElement), app.scene.getNonDeletedElementsMap());
94
+ newElement = offsetElementAfterFontResize(oldElement, newElement);
95
+ return newElement;
96
+ }
97
+ return oldElement;
98
+ }, true);
99
+ // Update arrow elements after text elements have been updated
100
+ const updatedElementsMap = arrayToMap(updatedElements);
101
+ getSelectedElements(elements, appState, {
102
+ includeBoundTextElement: true,
103
+ }).forEach((element) => {
104
+ if (isTextElement(element)) {
105
+ updateBoundElements(element, updatedElementsMap);
106
+ }
107
+ });
86
108
  return {
87
- elements: changeProperty(elements, appState, (oldElement) => {
88
- if (isTextElement(oldElement)) {
89
- const newFontSize = getNewFontSize(oldElement);
90
- newFontSizes.add(newFontSize);
91
- let newElement = newElementWith(oldElement, {
92
- fontSize: newFontSize,
93
- });
94
- redrawTextBoundingBox(newElement, app.scene.getContainerElement(oldElement), app.scene.getNonDeletedElementsMap());
95
- newElement = offsetElementAfterFontResize(oldElement, newElement);
96
- return newElement;
97
- }
98
- return oldElement;
99
- }, true),
109
+ elements: updatedElements,
100
110
  appState: {
101
111
  ...appState,
102
112
  // update state only if we've set all select text elements to
@@ -315,7 +325,7 @@ export const actionChangeOpacity = register({
315
325
  storeAction: StoreAction.CAPTURE,
316
326
  };
317
327
  },
318
- PanelComponent: ({ elements, appState, updateData }) => (_jsxs("label", { className: "control-label", children: [t("labels.opacity"), _jsx("input", { type: "range", min: "0", max: "100", step: "10", onChange: (event) => updateData(+event.target.value), value: getFormValue(elements, appState, (element) => element.opacity, true, appState.currentItemOpacity) ?? undefined })] })),
328
+ PanelComponent: ({ elements, appState, updateData }) => (_jsx(Range, { updateData: updateData, elements: elements, appState: appState, testId: "opacity" })),
319
329
  });
320
330
  export const actionChangeFontSize = register({
321
331
  name: "changeFontSize",
@@ -817,58 +827,64 @@ const getArrowheadOptions = (flip) => {
817
827
  icon: _jsx(ArrowheadArrowIcon, { flip: flip }),
818
828
  },
819
829
  {
820
- value: "bar",
821
- text: t("labels.arrowhead_bar"),
830
+ value: "triangle",
831
+ text: t("labels.arrowhead_triangle"),
832
+ icon: _jsx(ArrowheadTriangleIcon, { flip: flip }),
822
833
  keyBinding: "e",
823
- icon: _jsx(ArrowheadBarIcon, { flip: flip }),
824
834
  },
825
835
  {
826
- value: "dot",
827
- text: t("labels.arrowhead_circle"),
828
- keyBinding: null,
829
- icon: _jsx(ArrowheadCircleIcon, { flip: flip }),
830
- showInPicker: false,
836
+ value: "triangle_outline",
837
+ text: t("labels.arrowhead_triangle_outline"),
838
+ icon: _jsx(ArrowheadTriangleOutlineIcon, { flip: flip }),
839
+ keyBinding: "r",
831
840
  },
832
841
  {
833
842
  value: "circle",
834
843
  text: t("labels.arrowhead_circle"),
835
- keyBinding: "r",
844
+ keyBinding: "a",
836
845
  icon: _jsx(ArrowheadCircleIcon, { flip: flip }),
837
- showInPicker: false,
838
846
  },
839
847
  {
840
848
  value: "circle_outline",
841
849
  text: t("labels.arrowhead_circle_outline"),
842
- keyBinding: null,
850
+ keyBinding: "s",
843
851
  icon: _jsx(ArrowheadCircleOutlineIcon, { flip: flip }),
844
- showInPicker: false,
845
- },
846
- {
847
- value: "triangle",
848
- text: t("labels.arrowhead_triangle"),
849
- icon: _jsx(ArrowheadTriangleIcon, { flip: flip }),
850
- keyBinding: "t",
851
- },
852
- {
853
- value: "triangle_outline",
854
- text: t("labels.arrowhead_triangle_outline"),
855
- icon: _jsx(ArrowheadTriangleOutlineIcon, { flip: flip }),
856
- keyBinding: null,
857
- showInPicker: false,
858
852
  },
859
853
  {
860
854
  value: "diamond",
861
855
  text: t("labels.arrowhead_diamond"),
862
856
  icon: _jsx(ArrowheadDiamondIcon, { flip: flip }),
863
- keyBinding: null,
864
- showInPicker: false,
857
+ keyBinding: "d",
865
858
  },
866
859
  {
867
860
  value: "diamond_outline",
868
861
  text: t("labels.arrowhead_diamond_outline"),
869
862
  icon: _jsx(ArrowheadDiamondOutlineIcon, { flip: flip }),
870
- keyBinding: null,
871
- showInPicker: false,
863
+ keyBinding: "f",
864
+ },
865
+ {
866
+ value: "bar",
867
+ text: t("labels.arrowhead_bar"),
868
+ keyBinding: "z",
869
+ icon: _jsx(ArrowheadBarIcon, { flip: flip }),
870
+ },
871
+ {
872
+ value: "crowfoot_one",
873
+ text: t("labels.arrowhead_crowfoot_one"),
874
+ icon: _jsx(ArrowheadCrowfootOneIcon, { flip: flip }),
875
+ keyBinding: "c",
876
+ },
877
+ {
878
+ value: "crowfoot_many",
879
+ text: t("labels.arrowhead_crowfoot_many"),
880
+ icon: _jsx(ArrowheadCrowfootIcon, { flip: flip }),
881
+ keyBinding: "x",
882
+ },
883
+ {
884
+ value: "crowfoot_one_or_many",
885
+ text: t("labels.arrowhead_crowfoot_one_or_many"),
886
+ icon: _jsx(ArrowheadCrowfootOneOrManyIcon, { flip: flip }),
887
+ keyBinding: "v",
872
888
  },
873
889
  ];
874
890
  };
@@ -909,9 +925,9 @@ export const actionChangeArrowhead = register({
909
925
  const isRTL = getLanguage().rtl;
910
926
  return (_jsxs("fieldset", { children: [_jsx("legend", { children: t("labels.arrowheads") }), _jsxs("div", { className: "iconSelectList buttonList", children: [_jsx(IconPicker, { label: "arrowhead_start", options: getArrowheadOptions(!isRTL), value: getFormValue(elements, appState, (element) => isLinearElement(element) && canHaveArrowheads(element.type)
911
927
  ? element.startArrowhead
912
- : appState.currentItemStartArrowhead, true, appState.currentItemStartArrowhead), onChange: (value) => updateData({ position: "start", type: value }) }), _jsx(IconPicker, { label: "arrowhead_end", group: "arrowheads", options: getArrowheadOptions(!!isRTL), value: getFormValue(elements, appState, (element) => isLinearElement(element) && canHaveArrowheads(element.type)
928
+ : appState.currentItemStartArrowhead, true, appState.currentItemStartArrowhead), onChange: (value) => updateData({ position: "start", type: value }), numberOfOptionsToAlwaysShow: 4 }), _jsx(IconPicker, { label: "arrowhead_end", group: "arrowheads", options: getArrowheadOptions(!!isRTL), value: getFormValue(elements, appState, (element) => isLinearElement(element) && canHaveArrowheads(element.type)
913
929
  ? element.endArrowhead
914
- : appState.currentItemEndArrowhead, true, appState.currentItemEndArrowhead), onChange: (value) => updateData({ position: "end", type: value }) })] })] }));
930
+ : appState.currentItemEndArrowhead, true, appState.currentItemEndArrowhead), onChange: (value) => updateData({ position: "end", type: value }), numberOfOptionsToAlwaysShow: 4 })] })] }));
915
931
  },
916
932
  });
917
933
  export const actionChangeArrowType = register({
@@ -919,76 +935,89 @@ export const actionChangeArrowType = register({
919
935
  label: "Change arrow types",
920
936
  trackEvent: false,
921
937
  perform: (elements, appState, value, app) => {
922
- return {
923
- elements: changeProperty(elements, appState, (el) => {
924
- if (!isArrowElement(el)) {
925
- return el;
926
- }
927
- const newElement = newElementWith(el, {
928
- roundness: value === ARROW_TYPE.round
938
+ const newElements = changeProperty(elements, appState, (el) => {
939
+ if (!isArrowElement(el)) {
940
+ return el;
941
+ }
942
+ const newElement = newElementWith(el, {
943
+ roundness: value === ARROW_TYPE.round
944
+ ? {
945
+ type: ROUNDNESS.PROPORTIONAL_RADIUS,
946
+ }
947
+ : null,
948
+ elbowed: value === ARROW_TYPE.elbow,
949
+ points: value === ARROW_TYPE.elbow || el.elbowed
950
+ ? [el.points[0], el.points[el.points.length - 1]]
951
+ : el.points,
952
+ });
953
+ if (isElbowArrow(newElement)) {
954
+ const elementsMap = app.scene.getNonDeletedElementsMap();
955
+ app.dismissLinearEditor();
956
+ const startGlobalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(newElement, 0, elementsMap);
957
+ const endGlobalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(newElement, -1, elementsMap);
958
+ const startHoveredElement = !newElement.startBinding &&
959
+ getHoveredElementForBinding(tupleToCoors(startGlobalPoint), elements, elementsMap, appState.zoom, false, true);
960
+ const endHoveredElement = !newElement.endBinding &&
961
+ getHoveredElementForBinding(tupleToCoors(endGlobalPoint), elements, elementsMap, appState.zoom, false, true);
962
+ const startElement = startHoveredElement
963
+ ? startHoveredElement
964
+ : newElement.startBinding &&
965
+ elementsMap.get(newElement.startBinding.elementId);
966
+ const endElement = endHoveredElement
967
+ ? endHoveredElement
968
+ : newElement.endBinding &&
969
+ elementsMap.get(newElement.endBinding.elementId);
970
+ const finalStartPoint = startHoveredElement
971
+ ? bindPointToSnapToElementOutline(startGlobalPoint, endGlobalPoint, startHoveredElement, elementsMap)
972
+ : startGlobalPoint;
973
+ const finalEndPoint = endHoveredElement
974
+ ? bindPointToSnapToElementOutline(endGlobalPoint, startGlobalPoint, endHoveredElement, elementsMap)
975
+ : endGlobalPoint;
976
+ startHoveredElement &&
977
+ bindLinearElement(newElement, startHoveredElement, "start", elementsMap);
978
+ endHoveredElement &&
979
+ bindLinearElement(newElement, endHoveredElement, "end", elementsMap);
980
+ mutateElement(newElement, {
981
+ points: [finalStartPoint, finalEndPoint].map((p) => pointFrom(p[0] - newElement.x, p[1] - newElement.y)),
982
+ ...(startElement && newElement.startBinding
929
983
  ? {
930
- type: ROUNDNESS.PROPORTIONAL_RADIUS,
984
+ startBinding: {
985
+ // @ts-ignore TS cannot discern check above
986
+ ...newElement.startBinding,
987
+ ...calculateFixedPointForElbowArrowBinding(newElement, startElement, "start", elementsMap),
988
+ },
931
989
  }
932
- : null,
933
- elbowed: value === ARROW_TYPE.elbow,
934
- points: value === ARROW_TYPE.elbow || el.elbowed
935
- ? [el.points[0], el.points[el.points.length - 1]]
936
- : el.points,
990
+ : {}),
991
+ ...(endElement && newElement.endBinding
992
+ ? {
993
+ endBinding: {
994
+ // @ts-ignore TS cannot discern check above
995
+ ...newElement.endBinding,
996
+ ...calculateFixedPointForElbowArrowBinding(newElement, endElement, "end", elementsMap),
997
+ },
998
+ }
999
+ : {}),
937
1000
  });
938
- if (isElbowArrow(newElement)) {
939
- const elementsMap = app.scene.getNonDeletedElementsMap();
940
- app.dismissLinearEditor();
941
- const startGlobalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(newElement, 0, elementsMap);
942
- const endGlobalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(newElement, -1, elementsMap);
943
- const startHoveredElement = !newElement.startBinding &&
944
- getHoveredElementForBinding(tupleToCoors(startGlobalPoint), elements, elementsMap, true);
945
- const endHoveredElement = !newElement.endBinding &&
946
- getHoveredElementForBinding(tupleToCoors(endGlobalPoint), elements, elementsMap, true);
947
- const startElement = startHoveredElement
948
- ? startHoveredElement
949
- : newElement.startBinding &&
950
- elementsMap.get(newElement.startBinding.elementId);
951
- const endElement = endHoveredElement
952
- ? endHoveredElement
953
- : newElement.endBinding &&
954
- elementsMap.get(newElement.endBinding.elementId);
955
- const finalStartPoint = startHoveredElement
956
- ? bindPointToSnapToElementOutline(startGlobalPoint, endGlobalPoint, startHoveredElement, elementsMap)
957
- : startGlobalPoint;
958
- const finalEndPoint = endHoveredElement
959
- ? bindPointToSnapToElementOutline(endGlobalPoint, startGlobalPoint, endHoveredElement, elementsMap)
960
- : endGlobalPoint;
961
- startHoveredElement &&
962
- bindLinearElement(newElement, startHoveredElement, "start", elementsMap);
963
- endHoveredElement &&
964
- bindLinearElement(newElement, endHoveredElement, "end", elementsMap);
965
- mutateElbowArrow(newElement, elementsMap, [finalStartPoint, finalEndPoint].map((p) => pointFrom(p[0] - newElement.x, p[1] - newElement.y)), vector(0, 0), {
966
- ...(startElement && newElement.startBinding
967
- ? {
968
- startBinding: {
969
- // @ts-ignore TS cannot discern check above
970
- ...newElement.startBinding,
971
- ...calculateFixedPointForElbowArrowBinding(newElement, startElement, "start", elementsMap),
972
- },
973
- }
974
- : {}),
975
- ...(endElement && newElement.endBinding
976
- ? {
977
- endBinding: {
978
- // @ts-ignore TS cannot discern check above
979
- ...newElement.endBinding,
980
- ...calculateFixedPointForElbowArrowBinding(newElement, endElement, "end", elementsMap),
981
- },
982
- }
983
- : {}),
984
- });
985
- }
986
- return newElement;
987
- }),
988
- appState: {
989
- ...appState,
990
- currentItemArrowType: value,
991
- },
1001
+ LinearElementEditor.updateEditorMidPointsCache(newElement, elementsMap, app.state);
1002
+ }
1003
+ return newElement;
1004
+ });
1005
+ const newState = {
1006
+ ...appState,
1007
+ currentItemArrowType: value,
1008
+ };
1009
+ // Change the arrow type and update any other state settings for
1010
+ // the arrow.
1011
+ const selectedId = appState.selectedLinearElement?.elementId;
1012
+ if (selectedId) {
1013
+ const selected = newElements.find((el) => el.id === selectedId);
1014
+ if (selected) {
1015
+ newState.selectedLinearElement = new LinearElementEditor(selected);
1016
+ }
1017
+ }
1018
+ return {
1019
+ elements: newElements,
1020
+ appState: newState,
992
1021
  storeAction: StoreAction.CAPTURE,
993
1022
  };
994
1023
  },
@@ -4,7 +4,6 @@ import { selectGroupsForSelectedElements } from "../groups";
4
4
  import { getNonDeletedElements, isTextElement } from "../element";
5
5
  import { isLinearElement } from "../element/typeChecks";
6
6
  import { LinearElementEditor } from "../element/linearElementEditor";
7
- import { excludeElementsInFramesFromSelection } from "../scene/selection";
8
7
  import { selectAllIcon } from "../components/icons";
9
8
  import { StoreAction } from "../store";
10
9
  export const actionSelectAll = register({
@@ -17,9 +16,11 @@ export const actionSelectAll = register({
17
16
  if (appState.editingLinearElement) {
18
17
  return false;
19
18
  }
20
- const selectedElementIds = excludeElementsInFramesFromSelection(elements.filter((element) => !element.isDeleted &&
19
+ const selectedElementIds = elements
20
+ .filter((element) => !element.isDeleted &&
21
21
  !(isTextElement(element) && element.containerId) &&
22
- !element.locked)).reduce((map, element) => {
22
+ !element.locked)
23
+ .reduce((map, element) => {
23
24
  map[element.id] = true;
24
25
  return map;
25
26
  }, {});
@@ -1,4 +1,4 @@
1
1
  import type { SubtypeOf } from "../utility-types";
2
2
  import type { ActionName } from "./types";
3
- export type ShortcutName = SubtypeOf<ActionName, "toggleTheme" | "loadScene" | "clearCanvas" | "cut" | "copy" | "paste" | "copyStyles" | "pasteStyles" | "selectAll" | "deleteSelectedElements" | "duplicateSelection" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyAsPng" | "group" | "ungroup" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "addToLibrary" | "viewMode" | "flipHorizontal" | "flipVertical" | "hyperlink" | "toggleElementLock" | "resetZoom" | "zoomOut" | "zoomIn" | "zoomToFit" | "zoomToFitSelectionInViewport" | "zoomToFitSelection" | "toggleEraserTool" | "toggleHandTool" | "setFrameAsActiveTool" | "saveFileToDisk" | "saveToActiveFile" | "toggleShortcuts"> | "saveScene" | "imageExport" | "commandPalette" | "searchMenu";
3
+ export type ShortcutName = SubtypeOf<ActionName, "toggleTheme" | "loadScene" | "clearCanvas" | "cut" | "copy" | "paste" | "copyStyles" | "pasteStyles" | "selectAll" | "deleteSelectedElements" | "duplicateSelection" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyAsPng" | "group" | "ungroup" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "addToLibrary" | "viewMode" | "flipHorizontal" | "flipVertical" | "hyperlink" | "toggleElementLock" | "resetZoom" | "zoomOut" | "zoomIn" | "zoomToFit" | "zoomToFitSelectionInViewport" | "zoomToFitSelection" | "toggleEraserTool" | "toggleHandTool" | "setFrameAsActiveTool" | "saveFileToDisk" | "saveToActiveFile" | "toggleShortcuts" | "wrapSelectionInFrame"> | "saveScene" | "imageExport" | "commandPalette" | "searchMenu";
4
4
  export declare const getShortcutFromShortcutName: (name: ShortcutName, idx?: number) => string;
@@ -60,6 +60,7 @@ const shortcutMap = {
60
60
  saveToActiveFile: [getShortcutKey("CtrlOrCmd+S")],
61
61
  toggleShortcuts: [getShortcutKey("?")],
62
62
  searchMenu: [getShortcutKey("CtrlOrCmd+F")],
63
+ wrapSelectionInFrame: [],
63
64
  };
64
65
  export const getShortcutFromShortcutName = (name, idx = 0) => {
65
66
  const shortcuts = shortcutMap[name];
@@ -14,7 +14,7 @@ export type ActionResult = {
14
14
  type ActionFn = (elements: readonly OrderedExcalidrawElement[], appState: Readonly<AppState>, formData: any, app: AppClassProperties) => ActionResult | Promise<ActionResult>;
15
15
  export type UpdaterFn = (res: ActionResult) => void;
16
16
  export type ActionFilterFn = (action: Action) => void;
17
- export type ActionName = "copy" | "cut" | "paste" | "copyAsPng" | "copyAsSvg" | "copyText" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyStyles" | "selectAll" | "pasteStyles" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "changeStrokeColor" | "changeBackgroundColor" | "changeFillStyle" | "changeStrokeWidth" | "changeStrokeShape" | "changeSloppiness" | "changeStrokeStyle" | "changeArrowhead" | "changeArrowType" | "changeOpacity" | "changeFontSize" | "toggleCanvasMenu" | "toggleEditMenu" | "undo" | "redo" | "finalize" | "changeProjectName" | "changeExportBackground" | "changeExportEmbedScene" | "changeExportScale" | "saveToActiveFile" | "saveFileToDisk" | "loadScene" | "duplicateSelection" | "deleteSelectedElements" | "changeViewBackgroundColor" | "clearCanvas" | "zoomIn" | "zoomOut" | "resetZoom" | "zoomToFit" | "zoomToFitSelection" | "zoomToFitSelectionInViewport" | "changeFontFamily" | "changeTextAlign" | "changeVerticalAlign" | "toggleFullScreen" | "toggleShortcuts" | "group" | "ungroup" | "goToCollaborator" | "addToLibrary" | "changeRoundness" | "alignTop" | "alignBottom" | "alignLeft" | "alignRight" | "alignVerticallyCentered" | "alignHorizontallyCentered" | "distributeHorizontally" | "distributeVertically" | "flipHorizontal" | "flipVertical" | "viewMode" | "exportWithDarkMode" | "toggleTheme" | "increaseFontSize" | "decreaseFontSize" | "unbindText" | "hyperlink" | "bindText" | "unlockAllElements" | "toggleElementLock" | "toggleLinearEditor" | "toggleEraserTool" | "toggleHandTool" | "selectAllElementsInFrame" | "removeAllElementsFromFrame" | "updateFrameRendering" | "setFrameAsActiveTool" | "setEmbeddableAsActiveTool" | "createContainerFromText" | "wrapTextInContainer" | "commandPalette" | "autoResize" | "elementStats" | "searchMenu" | "copyElementLink" | "linkToElement" | "cropEditor";
17
+ export type ActionName = "copy" | "cut" | "paste" | "copyAsPng" | "copyAsSvg" | "copyText" | "sendBackward" | "bringForward" | "sendToBack" | "bringToFront" | "copyStyles" | "selectAll" | "pasteStyles" | "gridMode" | "zenMode" | "objectsSnapMode" | "stats" | "changeStrokeColor" | "changeBackgroundColor" | "changeFillStyle" | "changeStrokeWidth" | "changeStrokeShape" | "changeSloppiness" | "changeStrokeStyle" | "changeArrowhead" | "changeArrowType" | "changeOpacity" | "changeFontSize" | "toggleCanvasMenu" | "toggleEditMenu" | "undo" | "redo" | "finalize" | "changeProjectName" | "changeExportBackground" | "changeExportEmbedScene" | "changeExportScale" | "saveToActiveFile" | "saveFileToDisk" | "loadScene" | "duplicateSelection" | "deleteSelectedElements" | "changeViewBackgroundColor" | "clearCanvas" | "zoomIn" | "zoomOut" | "resetZoom" | "zoomToFit" | "zoomToFitSelection" | "zoomToFitSelectionInViewport" | "changeFontFamily" | "changeTextAlign" | "changeVerticalAlign" | "toggleFullScreen" | "toggleShortcuts" | "group" | "ungroup" | "goToCollaborator" | "addToLibrary" | "changeRoundness" | "alignTop" | "alignBottom" | "alignLeft" | "alignRight" | "alignVerticallyCentered" | "alignHorizontallyCentered" | "distributeHorizontally" | "distributeVertically" | "flipHorizontal" | "flipVertical" | "viewMode" | "exportWithDarkMode" | "toggleTheme" | "increaseFontSize" | "decreaseFontSize" | "unbindText" | "hyperlink" | "bindText" | "unlockAllElements" | "toggleElementLock" | "toggleLinearEditor" | "toggleEraserTool" | "toggleHandTool" | "selectAllElementsInFrame" | "removeAllElementsFromFrame" | "updateFrameRendering" | "setFrameAsActiveTool" | "setEmbeddableAsActiveTool" | "createContainerFromText" | "wrapTextInContainer" | "commandPalette" | "autoResize" | "elementStats" | "searchMenu" | "copyElementLink" | "linkToElement" | "cropEditor" | "wrapSelectionInFrame";
18
18
  export type PanelComponentProps = {
19
19
  elements: readonly ExcalidrawElement[];
20
20
  appState: AppState;
@@ -1,6 +1,7 @@
1
1
  import type { ElementsMap, ExcalidrawElement } from "./element/types";
2
+ import type Scene from "./scene/Scene";
2
3
  export interface Alignment {
3
4
  position: "start" | "center" | "end";
4
5
  axis: "x" | "y";
5
6
  }
6
- export declare const alignElements: (selectedElements: ExcalidrawElement[], elementsMap: ElementsMap, alignment: Alignment) => ExcalidrawElement[];
7
+ export declare const alignElements: (selectedElements: ExcalidrawElement[], elementsMap: ElementsMap, alignment: Alignment, scene: Scene) => ExcalidrawElement[];
@@ -1,15 +1,24 @@
1
- import { newElementWith } from "./element/mutateElement";
1
+ import { mutateElement } from "./element/mutateElement";
2
2
  import { getCommonBoundingBox } from "./element/bounds";
3
3
  import { getMaximumGroups } from "./groups";
4
- export const alignElements = (selectedElements, elementsMap, alignment) => {
4
+ import { updateBoundElements } from "./element/binding";
5
+ export const alignElements = (selectedElements, elementsMap, alignment, scene) => {
5
6
  const groups = getMaximumGroups(selectedElements, elementsMap);
6
7
  const selectionBoundingBox = getCommonBoundingBox(selectedElements);
7
8
  return groups.flatMap((group) => {
8
9
  const translation = calculateTranslation(group, selectionBoundingBox, alignment);
9
- return group.map((element) => newElementWith(element, {
10
- x: element.x + translation.x,
11
- y: element.y + translation.y,
12
- }));
10
+ return group.map((element) => {
11
+ // update element
12
+ const updatedEle = mutateElement(element, {
13
+ x: element.x + translation.x,
14
+ y: element.y + translation.y,
15
+ });
16
+ // update bound elements
17
+ updateBoundElements(element, scene.getNonDeletedElementsMap(), {
18
+ simultaneouslyUpdated: group,
19
+ });
20
+ return updatedEle;
21
+ });
13
22
  });
14
23
  };
15
24
  const calculateTranslation = (group, selectionBoundingBox, { axis, position }) => {
@@ -21,8 +21,17 @@ export declare const probablySupportsClipboardWriteText: boolean;
21
21
  export declare const probablySupportsClipboardBlob: boolean;
22
22
  export declare const createPasteEvent: ({ types, files, }: {
23
23
  types?: {
24
- "text/html"?: string | undefined;
25
- "text/plain"?: string | undefined;
24
+ "text/plain"?: string | File | undefined;
25
+ "text/html"?: string | File | undefined;
26
+ "image/svg+xml"?: string | File | undefined;
27
+ "image/png"?: string | File | undefined;
28
+ "image/jpeg"?: string | File | undefined;
29
+ "image/gif"?: string | File | undefined;
30
+ "image/webp"?: string | File | undefined;
31
+ "image/bmp"?: string | File | undefined;
32
+ "image/x-icon"?: string | File | undefined;
33
+ "image/avif"?: string | File | undefined;
34
+ "image/jfif"?: string | File | undefined;
26
35
  } | undefined;
27
36
  files?: File[] | undefined;
28
37
  }) => ClipboardEvent;
@@ -31,12 +40,25 @@ export declare const serializeAsClipboardJSON: ({ elements, files, }: {
31
40
  files: BinaryFiles | null;
32
41
  }) => string;
33
42
  export declare const copyToClipboard: (elements: readonly NonDeletedExcalidrawElement[], files: BinaryFiles | null, clipboardEvent?: ClipboardEvent | null) => Promise<void>;
43
+ /**
44
+ * Reads OS clipboard programmatically. May not work on all browsers.
45
+ * Will prompt user for permission if not granted.
46
+ */
34
47
  export declare const readSystemClipboard: () => Promise<{
35
- "text/html"?: string | undefined;
36
- "text/plain"?: string | undefined;
48
+ "text/plain"?: string | File | undefined;
49
+ "text/html"?: string | File | undefined;
50
+ "image/svg+xml"?: string | File | undefined;
51
+ "image/png"?: string | File | undefined;
52
+ "image/jpeg"?: string | File | undefined;
53
+ "image/gif"?: string | File | undefined;
54
+ "image/webp"?: string | File | undefined;
55
+ "image/bmp"?: string | File | undefined;
56
+ "image/x-icon"?: string | File | undefined;
57
+ "image/avif"?: string | File | undefined;
58
+ "image/jfif"?: string | File | undefined;
37
59
  }>;
38
60
  /**
39
- * Attempts to parse clipboard. Prefers system clipboard.
61
+ * Attempts to parse clipboard event.
40
62
  */
41
63
  export declare const parseClipboard: (event: ClipboardEvent, isPlainPaste?: boolean) => Promise<ClipboardData>;
42
64
  export declare const copyBlobToClipboardAsPng: (blob: Blob | Promise<Blob>) => Promise<void>;