@dwelle/excalidraw 0.5.0-da1c822 → 0.5.0-e56eec7

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 (382) hide show
  1. package/CHANGELOG.md +13 -2
  2. package/dist/browser/dev/excalidraw-assets-dev/{blockDiagram-91b80b7a-RHODGCTM.js → blockDiagram-91b80b7a-NRABZKZA.js} +6 -6
  3. package/dist/browser/dev/excalidraw-assets-dev/{c4Diagram-b2a90758-W7NCR7LR.js → c4Diagram-b2a90758-56M32CJD.js} +4 -4
  4. package/dist/browser/dev/excalidraw-assets-dev/{chunk-TKRIVTWP.js → chunk-5EDB2FTV.js} +3 -3
  5. package/dist/browser/dev/excalidraw-assets-dev/{chunk-52OGG53V.js → chunk-6VTJEXQH.js} +3 -3
  6. package/dist/browser/dev/excalidraw-assets-dev/{chunk-J5HRUYQR.js → chunk-AKQDHN2W.js} +2 -2
  7. package/dist/browser/dev/excalidraw-assets-dev/chunk-AKQDHN2W.js.map +7 -0
  8. package/dist/browser/dev/excalidraw-assets-dev/{chunk-GF7VCOUM.js → chunk-C4OL7SRI.js} +3 -3
  9. package/dist/browser/dev/excalidraw-assets-dev/{chunk-BESQLMCW.js → chunk-E47I6Q7O.js} +5 -5
  10. package/dist/browser/dev/excalidraw-assets-dev/{chunk-UETNA2WX.js → chunk-KDIPICHB.js} +6377 -4340
  11. package/dist/browser/dev/excalidraw-assets-dev/chunk-KDIPICHB.js.map +7 -0
  12. package/dist/browser/dev/excalidraw-assets-dev/{chunk-5747M6KP.js → chunk-OH2YDYHX.js} +3 -3
  13. package/dist/browser/dev/excalidraw-assets-dev/{chunk-GPOYIZPX.js → chunk-PXBR5CBM.js} +28 -28
  14. package/dist/browser/dev/excalidraw-assets-dev/chunk-PXBR5CBM.js.map +7 -0
  15. package/dist/browser/dev/excalidraw-assets-dev/{chunk-GCA4S2OA.js → chunk-RTA6DTUV.js} +3 -3
  16. package/dist/browser/dev/excalidraw-assets-dev/{chunk-DQOPSCYA.js → chunk-TTH3BTHQ.js} +3 -3
  17. package/dist/browser/dev/excalidraw-assets-dev/{chunk-B2MHJWXZ.js → chunk-U4N7TEPH.js} +2 -2
  18. package/dist/browser/dev/excalidraw-assets-dev/{chunk-QFS4M5OJ.js → chunk-V3PA4IDR.js} +3 -3
  19. package/dist/browser/dev/excalidraw-assets-dev/{chunk-SLLUETBM.js → chunk-WFT6ZJE6.js} +7 -7
  20. package/dist/browser/dev/excalidraw-assets-dev/{chunk-PPHFJLL7.js → chunk-XZKEYTKS.js} +4 -4
  21. package/dist/browser/dev/excalidraw-assets-dev/{chunk-USLWOHUZ.js → chunk-YC6VTXEO.js} +4 -4
  22. package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-30eddba6-GJGBT4TV.js → classDiagram-30eddba6-EZJVINS6.js} +6 -6
  23. package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-v2-f2df5561-LYWTIPJA.js → classDiagram-v2-f2df5561-XSUIN44A.js} +9 -9
  24. package/dist/browser/dev/excalidraw-assets-dev/{directory-open-01563666-UREMLRIT.js → directory-open-01563666-KOK2HSB6.js} +2 -2
  25. package/dist/browser/dev/excalidraw-assets-dev/{directory-open-4ed118d0-UN3BUDZZ.js → directory-open-4ed118d0-P3Q3CLF3.js} +2 -2
  26. package/dist/browser/dev/excalidraw-assets-dev/dist-O6HOTHQF.js +10 -0
  27. package/dist/browser/dev/excalidraw-assets-dev/{en-UW5C5KGW.js → en-PSBMWL4S.js} +2 -2
  28. package/dist/browser/dev/excalidraw-assets-dev/{erDiagram-47591fe2-Z7U2XW2Y.js → erDiagram-47591fe2-U7FLWOG3.js} +5 -5
  29. package/dist/browser/dev/excalidraw-assets-dev/{file-open-002ab408-4QG336MG.js → file-open-002ab408-EQEHGU2J.js} +2 -2
  30. package/dist/browser/dev/excalidraw-assets-dev/{file-open-7c801643-3QI4ICCL.js → file-open-7c801643-QQT6O7P5.js} +2 -2
  31. package/dist/browser/dev/excalidraw-assets-dev/{file-save-3189631c-TNNERCWV.js → file-save-3189631c-YXX2C7C6.js} +2 -2
  32. package/dist/browser/dev/excalidraw-assets-dev/{file-save-745eba88-JFMH565P.js → file-save-745eba88-7G554KTZ.js} +2 -2
  33. package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-5540d9b9-PARVG263.js → flowDiagram-5540d9b9-F2VP4JAA.js} +10 -10
  34. package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-v2-3b53844e-ZJOPVRMB.js → flowDiagram-v2-3b53844e-2WQZZRND.js} +10 -10
  35. package/dist/browser/dev/excalidraw-assets-dev/{flowchart-elk-definition-5fe447d6-ULPNBSZX.js → flowchart-elk-definition-5fe447d6-IW6O2F6C.js} +6 -6
  36. package/dist/browser/dev/excalidraw-assets-dev/{ganttDiagram-9a3bba1f-ESSYVTJ4.js → ganttDiagram-9a3bba1f-B5RH7ZAO.js} +3 -3
  37. package/dist/browser/dev/excalidraw-assets-dev/{gitGraphDiagram-96e6b4ee-6V6VVNNP.js → gitGraphDiagram-96e6b4ee-INGQRNLZ.js} +3 -3
  38. package/dist/browser/dev/excalidraw-assets-dev/{image-ZNQQXS62.css → image-FDQLNM24.css} +39 -16
  39. package/dist/browser/dev/excalidraw-assets-dev/image-FDQLNM24.css.map +7 -0
  40. package/dist/browser/dev/excalidraw-assets-dev/{image-3LTGFHLF.js → image-GMAHLVER.js} +6 -6
  41. package/dist/browser/dev/excalidraw-assets-dev/{image-blob-reduce.esm-KTX27DAY.js → image-blob-reduce.esm-OX75MRP3.js} +2 -2
  42. package/dist/browser/dev/excalidraw-assets-dev/{infoDiagram-bcd20f53-I22FLFX3.js → infoDiagram-bcd20f53-43FMAUOR.js} +3 -3
  43. package/dist/browser/dev/excalidraw-assets-dev/{journeyDiagram-4fe6b3dc-WAO6F52C.js → journeyDiagram-4fe6b3dc-KFVOUX4I.js} +4 -4
  44. package/dist/browser/dev/excalidraw-assets-dev/{katex-NWA2YFOP.js → katex-A3GRORPB.js} +2 -2
  45. package/dist/browser/dev/excalidraw-assets-dev/{mindmap-definition-f354de21-K74IKX4Y.js → mindmap-definition-f354de21-D7S3CRQ4.js} +4 -4
  46. package/dist/browser/dev/excalidraw-assets-dev/{pica-3TH2EGXR.js → pica-ZAD7MTGA.js} +2 -2
  47. package/dist/browser/dev/excalidraw-assets-dev/{pieDiagram-79897490-DOB2LVE5.js → pieDiagram-79897490-OON2CRZ5.js} +3 -3
  48. package/dist/browser/dev/excalidraw-assets-dev/{quadrantDiagram-62f64e94-MJV2X7WI.js → quadrantDiagram-62f64e94-5APTNVVS.js} +3 -3
  49. package/dist/browser/dev/excalidraw-assets-dev/{requirementDiagram-05bf5f74-H4YM3XN7.js → requirementDiagram-05bf5f74-FM7WZVKU.js} +5 -5
  50. package/dist/browser/dev/excalidraw-assets-dev/{roundRect-4S3QV2NZ.js → roundRect-AYYHVX5X.js} +2 -2
  51. package/dist/browser/dev/excalidraw-assets-dev/{sankeyDiagram-97764748-7X74ABAN.js → sankeyDiagram-97764748-5HLEFFGY.js} +3 -3
  52. package/dist/browser/dev/excalidraw-assets-dev/{sequenceDiagram-acc0e65c-PPDIJFQP.js → sequenceDiagram-acc0e65c-4ZRSNGPV.js} +4 -4
  53. package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-0ff1cf1a-JVBR7N35.js → stateDiagram-0ff1cf1a-OLTPYRPP.js} +6 -6
  54. package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-v2-9a9d610d-QYAJLQJH.js → stateDiagram-v2-9a9d610d-N3XOTAEE.js} +9 -9
  55. package/dist/browser/dev/excalidraw-assets-dev/{timeline-definition-fea2a41d-GL7U3WDB.js → timeline-definition-fea2a41d-5PDFIYJQ.js} +3 -3
  56. package/dist/browser/dev/excalidraw-assets-dev/{xychartDiagram-ab372869-4U4JE4TW.js → xychartDiagram-ab372869-VIWBP45Y.js} +4 -4
  57. package/dist/browser/dev/index.css +38 -15
  58. package/dist/browser/dev/index.css.map +2 -2
  59. package/dist/browser/dev/index.js +9 -5
  60. package/dist/browser/prod/excalidraw-assets/ar-SA-JA6F2FMJ-MVAFRXH2.js +10 -0
  61. package/dist/browser/prod/excalidraw-assets/az-AZ-GVIENQVH-DULWV7IG.js +1 -0
  62. package/dist/browser/prod/excalidraw-assets/bg-BG-YFNNHCEP-TOMMDX7A.js +5 -0
  63. package/dist/browser/prod/excalidraw-assets/{blockDiagram-91b80b7a-BO7MW3VX.js → blockDiagram-91b80b7a-ZBW6LBXS.js} +1 -1
  64. package/dist/browser/prod/excalidraw-assets/bn-BD-LMEIWSRD-U6EPN6XJ.js +5 -0
  65. package/dist/browser/prod/excalidraw-assets/{c4Diagram-b2a90758-VCUPBVHR.js → c4Diagram-b2a90758-GET6IFET.js} +1 -1
  66. package/dist/browser/prod/excalidraw-assets/ca-ES-C2WGCLOT-4Q2376G3.js +8 -0
  67. package/dist/browser/prod/excalidraw-assets/{chunk-O77Z7CWL.js → chunk-2UGPV7X3.js} +1 -1
  68. package/dist/browser/prod/excalidraw-assets/{chunk-B7CDQVNY.js → chunk-364WSJPQ.js} +21 -21
  69. package/dist/browser/prod/excalidraw-assets/{chunk-NM5B2RBP.js → chunk-4FM7RPKW.js} +1 -1
  70. package/dist/browser/prod/excalidraw-assets/{chunk-CVEF66PS.js → chunk-4SHJFNCN.js} +1 -1
  71. package/dist/browser/prod/excalidraw-assets/{chunk-22FVL4I7.js → chunk-6TNDONBF.js} +1 -1
  72. package/dist/browser/prod/excalidraw-assets/{chunk-QLNFR4AJ.js → chunk-BJTCWAK5.js} +1 -1
  73. package/dist/browser/prod/excalidraw-assets/chunk-CKRG5LOX.js +335 -0
  74. package/dist/browser/prod/excalidraw-assets/{chunk-3HZHH3PT.js → chunk-IW42BK4V.js} +1 -1
  75. package/dist/browser/prod/excalidraw-assets/{chunk-4JYQ3563.js → chunk-MRQWXP64.js} +1 -1
  76. package/dist/browser/prod/excalidraw-assets/{chunk-VXFFPRP2.js → chunk-OG2UUKMT.js} +1 -1
  77. package/dist/browser/prod/excalidraw-assets/chunk-Q6QP4TRB.js +11 -0
  78. package/dist/browser/prod/excalidraw-assets/{chunk-V7HUISEN.js → chunk-QBYA3CCP.js} +1 -1
  79. package/dist/browser/prod/excalidraw-assets/{chunk-5PWM36DG.js → chunk-S3O7MXSU.js} +1 -1
  80. package/dist/browser/prod/excalidraw-assets/chunk-SJBOQTFA.js +1 -0
  81. package/dist/browser/prod/excalidraw-assets/{chunk-3VCRCP5J.js → chunk-T7MBBIYG.js} +1 -1
  82. package/dist/browser/prod/excalidraw-assets/{chunk-HPA5W5VE.js → chunk-X7R4RA7C.js} +1 -1
  83. package/dist/browser/prod/excalidraw-assets/{chunk-7UJZVYSR.js → chunk-Y3NNVSMP.js} +1 -1
  84. package/dist/browser/prod/excalidraw-assets/{classDiagram-30eddba6-VXGNM3LI.js → classDiagram-30eddba6-MJ5GZSCE.js} +1 -1
  85. package/dist/browser/prod/excalidraw-assets/{classDiagram-v2-f2df5561-YALTASVE.js → classDiagram-v2-f2df5561-FU5PRXDD.js} +1 -1
  86. package/dist/browser/prod/excalidraw-assets/cs-CZ-F2NDIQMB-4NMYRMO2.js +11 -0
  87. package/dist/browser/prod/excalidraw-assets/da-DK-WBEQB3CJ-6YAF4DNI.js +5 -0
  88. package/dist/browser/prod/excalidraw-assets/de-DE-VEIMCP7R-NSRLPHDI.js +8 -0
  89. package/dist/browser/prod/excalidraw-assets/{directory-open-01563666-JWXY2QSC.js → directory-open-01563666-UG2J4T6L.js} +1 -1
  90. package/dist/browser/prod/excalidraw-assets/{directory-open-4ed118d0-6AL5X37W.js → directory-open-4ed118d0-FGQD6TMW.js} +1 -1
  91. package/dist/browser/prod/excalidraw-assets/dist-LI3DBBWR.js +1 -0
  92. package/dist/browser/prod/excalidraw-assets/el-GR-TKRKG5GQ-6N4GY2DI.js +10 -0
  93. package/dist/browser/prod/excalidraw-assets/{en-CPU3UVKT.js → en-MPFDZHEH.js} +1 -1
  94. package/dist/browser/prod/excalidraw-assets/en-Q552WR7L-QAV42NF3.js +1 -0
  95. package/dist/browser/prod/excalidraw-assets/{erDiagram-47591fe2-GKYANCN7.js → erDiagram-47591fe2-YGAMNOK6.js} +1 -1
  96. package/dist/browser/prod/excalidraw-assets/es-ES-TOLWEZNW-ODY4LX7F.js +9 -0
  97. package/dist/browser/prod/excalidraw-assets/eu-ES-7CDRJQWJ-KF3KSB2X.js +11 -0
  98. package/dist/browser/prod/excalidraw-assets/fa-IR-527E2XGU-WLLGMWYR.js +8 -0
  99. package/dist/browser/prod/excalidraw-assets/fi-FI-NLQ7RQGZ-EZLGQEWF.js +6 -0
  100. package/dist/browser/prod/excalidraw-assets/{file-open-002ab408-3EPJOH45.js → file-open-002ab408-WLX7QPS6.js} +1 -1
  101. package/dist/browser/prod/excalidraw-assets/{file-open-7c801643-QIP6HK4D.js → file-open-7c801643-YB6IH3XI.js} +1 -1
  102. package/dist/browser/prod/excalidraw-assets/{file-save-3189631c-4TQJBQCS.js → file-save-3189631c-MRYCXU63.js} +1 -1
  103. package/dist/browser/prod/excalidraw-assets/{file-save-745eba88-C4L3ZGCC.js → file-save-745eba88-UZEDMFLR.js} +1 -1
  104. package/dist/browser/prod/excalidraw-assets/{flowDiagram-5540d9b9-QBRW5SLP.js → flowDiagram-5540d9b9-V23UQWYJ.js} +1 -1
  105. package/dist/browser/prod/excalidraw-assets/flowDiagram-v2-3b53844e-UDC2ZAFT.js +1 -0
  106. package/dist/browser/prod/excalidraw-assets/{flowchart-elk-definition-5fe447d6-YYO2EYKS.js → flowchart-elk-definition-5fe447d6-N3ISH6AG.js} +1 -1
  107. package/dist/browser/prod/excalidraw-assets/fr-FR-KUHO4FLU-2OW7FE5V.js +9 -0
  108. package/dist/browser/prod/excalidraw-assets/{ganttDiagram-9a3bba1f-3B2DUUUQ.js → ganttDiagram-9a3bba1f-7SAN2TXA.js} +1 -1
  109. package/dist/browser/prod/excalidraw-assets/{gitGraphDiagram-96e6b4ee-G6CKXXWQ.js → gitGraphDiagram-96e6b4ee-EXV6PWXL.js} +1 -1
  110. package/dist/browser/prod/excalidraw-assets/gl-ES-NEXX3VBB-TESFDR6O.js +10 -0
  111. package/dist/browser/prod/excalidraw-assets/he-IL-MED2VGBZ-N4VYRCHF.js +10 -0
  112. package/dist/browser/prod/excalidraw-assets/hi-IN-5V633W7V-4VXVQ6GE.js +4 -0
  113. package/dist/browser/prod/excalidraw-assets/hu-HU-2FOZGVGR-7CHHZRPD.js +7 -0
  114. package/dist/browser/prod/excalidraw-assets/id-ID-I6BOLXTF-ULJRGCTU.js +10 -0
  115. package/dist/browser/prod/excalidraw-assets/image-ZKACJTPS.js +1 -0
  116. package/dist/browser/prod/excalidraw-assets/{image-blob-reduce.esm-5DTGAOOI.js → image-blob-reduce.esm-GOFU5DPX.js} +1 -1
  117. package/dist/browser/prod/excalidraw-assets/{infoDiagram-bcd20f53-WJTZJERL.js → infoDiagram-bcd20f53-LJZ36XP5.js} +1 -1
  118. package/dist/browser/prod/excalidraw-assets/it-IT-WKPQOK4P-C3FTW2QG.js +11 -0
  119. package/dist/browser/prod/excalidraw-assets/ja-JP-VKA4ISRU-EBXFDMUP.js +8 -0
  120. package/dist/browser/prod/excalidraw-assets/{journeyDiagram-4fe6b3dc-JF22KXXQ.js → journeyDiagram-4fe6b3dc-TFRSU2KH.js} +1 -1
  121. package/dist/browser/prod/excalidraw-assets/kaa-IKPRSBNY-URJPWZZH.js +1 -0
  122. package/dist/browser/prod/excalidraw-assets/kab-KAB-IE4PHQTZ-OMISFOMM.js +8 -0
  123. package/dist/browser/prod/excalidraw-assets/{katex-N6R5DPQX.js → katex-HAQKNIIQ.js} +1 -1
  124. package/dist/browser/prod/excalidraw-assets/kk-KZ-MNJT6XSV-56OVE4EH.js +1 -0
  125. package/dist/browser/prod/excalidraw-assets/km-KH-LADGDFXV-KI7V2Z5A.js +11 -0
  126. package/dist/browser/prod/excalidraw-assets/ko-KR-XD7AVF2F-EFYGITKM.js +9 -0
  127. package/dist/browser/prod/excalidraw-assets/ku-TR-4XBHKDQA-U25XLPMW.js +9 -0
  128. package/dist/browser/prod/excalidraw-assets/lt-LT-QC35R4YH-6TDSRONI.js +3 -0
  129. package/dist/browser/prod/excalidraw-assets/lv-LV-GSD5D3BA-KMXM2FQ7.js +7 -0
  130. package/dist/browser/prod/excalidraw-assets/{mindmap-definition-f354de21-7SH5STU3.js → mindmap-definition-f354de21-J3C2WSJB.js} +1 -1
  131. package/dist/browser/prod/excalidraw-assets/mr-IN-KOLSWM7Y-NVYC6JCO.js +13 -0
  132. package/dist/browser/prod/excalidraw-assets/my-MM-M53KMUET-A2ORJJ2D.js +1 -0
  133. package/dist/browser/prod/excalidraw-assets/nb-NO-XXC6U37A-L4O4DGCC.js +10 -0
  134. package/dist/browser/prod/excalidraw-assets/nl-NL-HCCJQEUO-7Q2LV5NM.js +8 -0
  135. package/dist/browser/prod/excalidraw-assets/nn-NO-6P7Z2PI2-TUT2PFEE.js +8 -0
  136. package/dist/browser/prod/excalidraw-assets/oc-FR-JRJKPLNT-SBQHJH7X.js +8 -0
  137. package/dist/browser/prod/excalidraw-assets/pa-IN-LZWLEPIB-7NKOXI65.js +4 -0
  138. package/dist/browser/prod/excalidraw-assets/percentages-UCQDHIQF-Q4IM6ZEB.js +1 -0
  139. package/dist/browser/prod/excalidraw-assets/{pica-KWHN2PJ6.js → pica-ABPXE5C5.js} +1 -1
  140. package/dist/browser/prod/excalidraw-assets/{pieDiagram-79897490-5O5EBEQB.js → pieDiagram-79897490-FMJ3ZAF7.js} +1 -1
  141. package/dist/browser/prod/excalidraw-assets/pl-PL-3WBLCXI2-E2SMTIVM.js +9 -0
  142. package/dist/browser/prod/excalidraw-assets/pt-BR-O3ZPTUNW-RS7M7EKX.js +9 -0
  143. package/dist/browser/prod/excalidraw-assets/pt-PT-7AQTSAFO-AEANJ2UN.js +9 -0
  144. package/dist/browser/prod/excalidraw-assets/{quadrantDiagram-62f64e94-JTY6WOKB.js → quadrantDiagram-62f64e94-YI32TPUI.js} +1 -1
  145. package/dist/browser/prod/excalidraw-assets/{requirementDiagram-05bf5f74-TSFQFY5X.js → requirementDiagram-05bf5f74-UO2ATL3U.js} +1 -1
  146. package/dist/browser/prod/excalidraw-assets/ro-RO-HJ65JYWV-35XNZ4QJ.js +11 -0
  147. package/dist/browser/prod/excalidraw-assets/{roundRect-PUCZURYS.js → roundRect-UKQBLFKQ.js} +1 -1
  148. package/dist/browser/prod/excalidraw-assets/ru-RU-P7ROIYNC-ERPG3GJT.js +9 -0
  149. package/dist/browser/prod/excalidraw-assets/{sankeyDiagram-97764748-7G2R6W67.js → sankeyDiagram-97764748-3RR36435.js} +1 -1
  150. package/dist/browser/prod/excalidraw-assets/{sequenceDiagram-acc0e65c-CTANNZCO.js → sequenceDiagram-acc0e65c-G2Q6J4UN.js} +1 -1
  151. package/dist/browser/prod/excalidraw-assets/si-LK-7ZSWVION-YHKN25MU.js +1 -0
  152. package/dist/browser/prod/excalidraw-assets/sk-SK-NXVBGLYY-IKQZT26E.js +6 -0
  153. package/dist/browser/prod/excalidraw-assets/sl-SI-VFTWOYNP-UPLNMI3E.js +6 -0
  154. package/dist/browser/prod/excalidraw-assets/{stateDiagram-0ff1cf1a-I5COLKZ4.js → stateDiagram-0ff1cf1a-QEYVXCSB.js} +1 -1
  155. package/dist/browser/prod/excalidraw-assets/{stateDiagram-v2-9a9d610d-IIHI3AJN.js → stateDiagram-v2-9a9d610d-3VKD7UYK.js} +1 -1
  156. package/dist/browser/prod/excalidraw-assets/sv-SE-YONBLQNW-ZG4TE7PV.js +10 -0
  157. package/dist/browser/prod/excalidraw-assets/ta-IN-BSETPMLX-FC54FMQJ.js +9 -0
  158. package/dist/browser/prod/excalidraw-assets/th-TH-URTRDITB-K6QQ2PRO.js +2 -0
  159. package/dist/browser/prod/excalidraw-assets/{timeline-definition-fea2a41d-CXTGKWI4.js → timeline-definition-fea2a41d-H4D6IYVJ.js} +1 -1
  160. package/dist/browser/prod/excalidraw-assets/tr-TR-N5SCAVTB-HMUEG6DN.js +7 -0
  161. package/dist/browser/prod/excalidraw-assets/uk-UA-LBCYVSQZ-DEJZCNRZ.js +6 -0
  162. package/dist/browser/prod/excalidraw-assets/vi-VN-POZWLIUU-EY6QFLQV.js +5 -0
  163. package/dist/browser/prod/excalidraw-assets/{xychartDiagram-ab372869-QZGPPHJP.js → xychartDiagram-ab372869-SUXFHV53.js} +1 -1
  164. package/dist/browser/prod/excalidraw-assets/zh-CN-FUF5V3SC-5UIL2T3T.js +10 -0
  165. package/dist/browser/prod/excalidraw-assets/zh-HK-OB4VW42C-3ID2CCZJ.js +1 -0
  166. package/dist/browser/prod/excalidraw-assets/zh-TW-5JPVKOM7-VUPJBABS.js +9 -0
  167. package/dist/browser/prod/index.css +1 -1
  168. package/dist/browser/prod/index.js +128 -1
  169. package/dist/dev/{en-R7FEFJGC.json → en-Q552WR7L.json} +1 -1
  170. package/dist/dev/index.css +38 -15
  171. package/dist/dev/index.css.map +2 -2
  172. package/dist/dev/index.js +4575 -2598
  173. package/dist/dev/index.js.map +4 -4
  174. package/dist/excalidraw/actions/actionAddToLibrary.d.ts +4 -4
  175. package/dist/excalidraw/actions/actionAddToLibrary.js +4 -3
  176. package/dist/excalidraw/actions/actionAlign.d.ts +20 -20
  177. package/dist/excalidraw/actions/actionAlign.js +7 -6
  178. package/dist/excalidraw/actions/actionBoundText.d.ts +7 -7
  179. package/dist/excalidraw/actions/actionBoundText.js +8 -4
  180. package/dist/excalidraw/actions/actionCanvas.d.ts +49 -49
  181. package/dist/excalidraw/actions/actionCanvas.js +16 -13
  182. package/dist/excalidraw/actions/actionClipboard.d.ts +24 -24
  183. package/dist/excalidraw/actions/actionClipboard.js +14 -13
  184. package/dist/excalidraw/actions/actionDeleteSelected.d.ts +8 -8
  185. package/dist/excalidraw/actions/actionDeleteSelected.js +6 -3
  186. package/dist/excalidraw/actions/actionDistribute.d.ts +8 -8
  187. package/dist/excalidraw/actions/actionDistribute.js +3 -2
  188. package/dist/excalidraw/actions/actionDuplicateSelection.d.ts +5 -6
  189. package/dist/excalidraw/actions/actionDuplicateSelection.js +7 -3
  190. package/dist/excalidraw/actions/actionElementLock.d.ts +8 -8
  191. package/dist/excalidraw/actions/actionElementLock.js +3 -2
  192. package/dist/excalidraw/actions/actionExport.d.ts +36 -36
  193. package/dist/excalidraw/actions/actionExport.js +15 -11
  194. package/dist/excalidraw/actions/actionFinalize.d.ts +8 -8
  195. package/dist/excalidraw/actions/actionFinalize.js +9 -5
  196. package/dist/excalidraw/actions/actionFlip.d.ts +9 -9
  197. package/dist/excalidraw/actions/actionFlip.js +10 -9
  198. package/dist/excalidraw/actions/actionFrame.d.ts +14 -169
  199. package/dist/excalidraw/actions/actionFrame.js +7 -6
  200. package/dist/excalidraw/actions/actionGroup.d.ts +11 -321
  201. package/dist/excalidraw/actions/actionGroup.js +9 -11
  202. package/dist/excalidraw/actions/actionHistory.d.ts +3 -2
  203. package/dist/excalidraw/actions/actionHistory.js +27 -28
  204. package/dist/excalidraw/actions/actionLinearEditor.d.ts +2 -2
  205. package/dist/excalidraw/actions/actionLinearEditor.js +2 -1
  206. package/dist/excalidraw/actions/actionLink.d.ts +5 -5
  207. package/dist/excalidraw/actions/actionLink.js +2 -1
  208. package/dist/excalidraw/actions/actionMenu.d.ts +8 -8
  209. package/dist/excalidraw/actions/actionMenu.js +4 -3
  210. package/dist/excalidraw/actions/actionNavigate.d.ts +3 -3
  211. package/dist/excalidraw/actions/actionNavigate.js +3 -2
  212. package/dist/excalidraw/actions/actionProperties.d.ts +32 -32
  213. package/dist/excalidraw/actions/actionProperties.js +18 -13
  214. package/dist/excalidraw/actions/actionSelectAll.d.ts +4 -4
  215. package/dist/excalidraw/actions/actionSelectAll.js +2 -1
  216. package/dist/excalidraw/actions/actionStyles.d.ts +9 -12
  217. package/dist/excalidraw/actions/actionStyles.js +4 -3
  218. package/dist/excalidraw/actions/actionToggleGridMode.d.ts +6 -4
  219. package/dist/excalidraw/actions/actionToggleGridMode.js +6 -2
  220. package/dist/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +4 -4
  221. package/dist/excalidraw/actions/actionToggleObjectsSnapMode.js +2 -1
  222. package/dist/excalidraw/actions/actionToggleStats.d.ts +4 -4
  223. package/dist/excalidraw/actions/actionToggleStats.js +2 -1
  224. package/dist/excalidraw/actions/actionToggleViewMode.d.ts +4 -4
  225. package/dist/excalidraw/actions/actionToggleViewMode.js +2 -1
  226. package/dist/excalidraw/actions/actionToggleZenMode.d.ts +4 -4
  227. package/dist/excalidraw/actions/actionToggleZenMode.js +2 -1
  228. package/dist/excalidraw/actions/actionZindex.d.ts +19 -19
  229. package/dist/excalidraw/actions/actionZindex.js +5 -4
  230. package/dist/excalidraw/actions/manager.d.ts +3 -3
  231. package/dist/excalidraw/actions/types.d.ts +4 -4
  232. package/dist/excalidraw/appState.d.ts +5 -5
  233. package/dist/excalidraw/change.d.ts +191 -0
  234. package/dist/excalidraw/change.js +894 -0
  235. package/dist/excalidraw/components/App.d.ts +22 -7
  236. package/dist/excalidraw/components/App.js +340 -130
  237. package/dist/excalidraw/components/CommandPalette/CommandPalette.js +1 -0
  238. package/dist/excalidraw/components/HelpDialog.js +1 -1
  239. package/dist/excalidraw/components/Sidebar/Sidebar.d.ts +2 -2
  240. package/dist/excalidraw/components/Stack.d.ts +2 -2
  241. package/dist/excalidraw/components/ToolButton.d.ts +1 -0
  242. package/dist/excalidraw/components/ToolButton.js +1 -1
  243. package/dist/excalidraw/components/canvases/InteractiveCanvas.d.ts +2 -1
  244. package/dist/excalidraw/components/canvases/InteractiveCanvas.js +1 -0
  245. package/dist/excalidraw/components/hyperlink/Hyperlink.js +3 -3
  246. package/dist/excalidraw/components/hyperlink/helpers.js +2 -3
  247. package/dist/excalidraw/components/icons.d.ts +1 -0
  248. package/dist/excalidraw/components/icons.js +1 -0
  249. package/dist/excalidraw/components/main-menu/DefaultItems.d.ts +1 -1
  250. package/dist/excalidraw/constants.d.ts +3 -3
  251. package/dist/excalidraw/constants.js +6 -3
  252. package/dist/excalidraw/data/reconcile.d.ts +6 -0
  253. package/dist/excalidraw/data/reconcile.js +49 -0
  254. package/dist/excalidraw/data/restore.d.ts +3 -3
  255. package/dist/excalidraw/data/restore.js +6 -7
  256. package/dist/excalidraw/data/transform.d.ts +1 -1
  257. package/dist/excalidraw/data/transform.js +4 -3
  258. package/dist/excalidraw/data/url.d.ts +1 -0
  259. package/dist/excalidraw/data/url.js +4 -1
  260. package/dist/excalidraw/element/binding.d.ts +64 -9
  261. package/dist/excalidraw/element/binding.js +634 -96
  262. package/dist/excalidraw/element/bounds.d.ts +0 -1
  263. package/dist/excalidraw/element/bounds.js +0 -3
  264. package/dist/excalidraw/element/collision.d.ts +14 -19
  265. package/dist/excalidraw/element/collision.js +36 -713
  266. package/dist/excalidraw/element/embeddable.d.ts +7 -4
  267. package/dist/excalidraw/element/embeddable.js +88 -27
  268. package/dist/excalidraw/element/index.d.ts +0 -1
  269. package/dist/excalidraw/element/index.js +0 -1
  270. package/dist/excalidraw/element/linearElementEditor.d.ts +11 -11
  271. package/dist/excalidraw/element/linearElementEditor.js +7 -5
  272. package/dist/excalidraw/element/mutateElement.d.ts +1 -2
  273. package/dist/excalidraw/element/newElement.d.ts +1 -1
  274. package/dist/excalidraw/element/newElement.js +2 -1
  275. package/dist/excalidraw/element/resizeElements.d.ts +1 -1
  276. package/dist/excalidraw/element/resizeElements.js +110 -86
  277. package/dist/excalidraw/element/resizeTest.d.ts +4 -4
  278. package/dist/excalidraw/element/resizeTest.js +55 -8
  279. package/dist/excalidraw/element/sizeHelpers.js +3 -0
  280. package/dist/excalidraw/element/textElement.d.ts +1 -2
  281. package/dist/excalidraw/element/textElement.js +5 -34
  282. package/dist/excalidraw/element/transformHandles.d.ts +22 -4
  283. package/dist/excalidraw/element/transformHandles.js +24 -3
  284. package/dist/excalidraw/element/typeChecks.d.ts +2 -2
  285. package/dist/excalidraw/element/types.d.ts +19 -6
  286. package/dist/excalidraw/errors.d.ts +3 -0
  287. package/dist/excalidraw/errors.js +3 -0
  288. package/dist/excalidraw/fractionalIndex.d.ts +40 -0
  289. package/dist/excalidraw/fractionalIndex.js +241 -0
  290. package/dist/excalidraw/frame.d.ts +1 -1
  291. package/dist/excalidraw/groups.d.ts +2 -0
  292. package/dist/excalidraw/groups.js +17 -0
  293. package/dist/excalidraw/history.d.ts +34 -46
  294. package/dist/excalidraw/history.js +100 -167
  295. package/dist/excalidraw/hooks/useEmitter.d.ts +2 -0
  296. package/dist/excalidraw/hooks/useEmitter.js +13 -0
  297. package/dist/excalidraw/index.d.ts +2 -0
  298. package/dist/excalidraw/index.js +2 -0
  299. package/dist/excalidraw/locales/en.json +1 -1
  300. package/dist/excalidraw/renderer/interactiveScene.d.ts +1 -1
  301. package/dist/excalidraw/renderer/interactiveScene.js +8 -7
  302. package/dist/excalidraw/renderer/staticScene.js +14 -3
  303. package/dist/excalidraw/renderer/staticSvgScene.js +10 -0
  304. package/dist/excalidraw/scene/Scene.d.ts +7 -6
  305. package/dist/excalidraw/scene/Scene.js +31 -16
  306. package/dist/excalidraw/scene/export.js +2 -1
  307. package/dist/excalidraw/scene/types.d.ts +2 -1
  308. package/dist/excalidraw/store.d.ts +99 -0
  309. package/dist/excalidraw/store.js +269 -0
  310. package/dist/excalidraw/types.d.ts +18 -4
  311. package/dist/excalidraw/utils.d.ts +6 -0
  312. package/dist/excalidraw/utils.js +7 -0
  313. package/dist/excalidraw/zindex.d.ts +2 -2
  314. package/dist/excalidraw/zindex.js +9 -13
  315. package/dist/prod/{en-R7FEFJGC.json → en-Q552WR7L.json} +1 -1
  316. package/dist/prod/index.css +1 -1
  317. package/dist/prod/index.js +44 -44
  318. package/dist/utils/collision.d.ts +4 -0
  319. package/dist/utils/collision.js +48 -0
  320. package/dist/utils/geometry/geometry.d.ts +71 -0
  321. package/dist/utils/geometry/geometry.js +674 -0
  322. package/dist/utils/geometry/shape.d.ts +56 -0
  323. package/dist/utils/geometry/shape.js +168 -0
  324. package/history.ts +161 -216
  325. package/package.json +2 -1
  326. package/dist/browser/dev/excalidraw-assets-dev/chunk-GPOYIZPX.js.map +0 -7
  327. package/dist/browser/dev/excalidraw-assets-dev/chunk-J5HRUYQR.js.map +0 -7
  328. package/dist/browser/dev/excalidraw-assets-dev/chunk-UETNA2WX.js.map +0 -7
  329. package/dist/browser/dev/excalidraw-assets-dev/dist-Y7S5GOTG.js +0 -10
  330. package/dist/browser/dev/excalidraw-assets-dev/image-ZNQQXS62.css.map +0 -7
  331. package/dist/browser/prod/excalidraw-assets/chunk-EEN6AFMH.js +0 -269
  332. package/dist/browser/prod/excalidraw-assets/dist-7FHVDAZ2.js +0 -1
  333. package/dist/browser/prod/excalidraw-assets/flowDiagram-v2-3b53844e-CRHRHP7H.js +0 -1
  334. package/dist/browser/prod/excalidraw-assets/image-VXYNPVOG.js +0 -1
  335. package/dist/browser/prod/excalidraw-assets/image-WE6NA2G6.css +0 -1
  336. /package/dist/browser/dev/excalidraw-assets-dev/{blockDiagram-91b80b7a-RHODGCTM.js.map → blockDiagram-91b80b7a-NRABZKZA.js.map} +0 -0
  337. /package/dist/browser/dev/excalidraw-assets-dev/{c4Diagram-b2a90758-W7NCR7LR.js.map → c4Diagram-b2a90758-56M32CJD.js.map} +0 -0
  338. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-TKRIVTWP.js.map → chunk-5EDB2FTV.js.map} +0 -0
  339. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-52OGG53V.js.map → chunk-6VTJEXQH.js.map} +0 -0
  340. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-GF7VCOUM.js.map → chunk-C4OL7SRI.js.map} +0 -0
  341. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-BESQLMCW.js.map → chunk-E47I6Q7O.js.map} +0 -0
  342. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-5747M6KP.js.map → chunk-OH2YDYHX.js.map} +0 -0
  343. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-GCA4S2OA.js.map → chunk-RTA6DTUV.js.map} +0 -0
  344. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-DQOPSCYA.js.map → chunk-TTH3BTHQ.js.map} +0 -0
  345. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-B2MHJWXZ.js.map → chunk-U4N7TEPH.js.map} +0 -0
  346. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-QFS4M5OJ.js.map → chunk-V3PA4IDR.js.map} +0 -0
  347. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-SLLUETBM.js.map → chunk-WFT6ZJE6.js.map} +0 -0
  348. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-PPHFJLL7.js.map → chunk-XZKEYTKS.js.map} +0 -0
  349. /package/dist/browser/dev/excalidraw-assets-dev/{chunk-USLWOHUZ.js.map → chunk-YC6VTXEO.js.map} +0 -0
  350. /package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-30eddba6-GJGBT4TV.js.map → classDiagram-30eddba6-EZJVINS6.js.map} +0 -0
  351. /package/dist/browser/dev/excalidraw-assets-dev/{classDiagram-v2-f2df5561-LYWTIPJA.js.map → classDiagram-v2-f2df5561-XSUIN44A.js.map} +0 -0
  352. /package/dist/browser/dev/excalidraw-assets-dev/{directory-open-01563666-UREMLRIT.js.map → directory-open-01563666-KOK2HSB6.js.map} +0 -0
  353. /package/dist/browser/dev/excalidraw-assets-dev/{directory-open-4ed118d0-UN3BUDZZ.js.map → directory-open-4ed118d0-P3Q3CLF3.js.map} +0 -0
  354. /package/dist/browser/dev/excalidraw-assets-dev/{dist-Y7S5GOTG.js.map → dist-O6HOTHQF.js.map} +0 -0
  355. /package/dist/browser/dev/excalidraw-assets-dev/{en-UW5C5KGW.js.map → en-PSBMWL4S.js.map} +0 -0
  356. /package/dist/browser/dev/excalidraw-assets-dev/{erDiagram-47591fe2-Z7U2XW2Y.js.map → erDiagram-47591fe2-U7FLWOG3.js.map} +0 -0
  357. /package/dist/browser/dev/excalidraw-assets-dev/{file-open-002ab408-4QG336MG.js.map → file-open-002ab408-EQEHGU2J.js.map} +0 -0
  358. /package/dist/browser/dev/excalidraw-assets-dev/{file-open-7c801643-3QI4ICCL.js.map → file-open-7c801643-QQT6O7P5.js.map} +0 -0
  359. /package/dist/browser/dev/excalidraw-assets-dev/{file-save-3189631c-TNNERCWV.js.map → file-save-3189631c-YXX2C7C6.js.map} +0 -0
  360. /package/dist/browser/dev/excalidraw-assets-dev/{file-save-745eba88-JFMH565P.js.map → file-save-745eba88-7G554KTZ.js.map} +0 -0
  361. /package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-5540d9b9-PARVG263.js.map → flowDiagram-5540d9b9-F2VP4JAA.js.map} +0 -0
  362. /package/dist/browser/dev/excalidraw-assets-dev/{flowDiagram-v2-3b53844e-ZJOPVRMB.js.map → flowDiagram-v2-3b53844e-2WQZZRND.js.map} +0 -0
  363. /package/dist/browser/dev/excalidraw-assets-dev/{flowchart-elk-definition-5fe447d6-ULPNBSZX.js.map → flowchart-elk-definition-5fe447d6-IW6O2F6C.js.map} +0 -0
  364. /package/dist/browser/dev/excalidraw-assets-dev/{ganttDiagram-9a3bba1f-ESSYVTJ4.js.map → ganttDiagram-9a3bba1f-B5RH7ZAO.js.map} +0 -0
  365. /package/dist/browser/dev/excalidraw-assets-dev/{gitGraphDiagram-96e6b4ee-6V6VVNNP.js.map → gitGraphDiagram-96e6b4ee-INGQRNLZ.js.map} +0 -0
  366. /package/dist/browser/dev/excalidraw-assets-dev/{image-3LTGFHLF.js.map → image-GMAHLVER.js.map} +0 -0
  367. /package/dist/browser/dev/excalidraw-assets-dev/{image-blob-reduce.esm-KTX27DAY.js.map → image-blob-reduce.esm-OX75MRP3.js.map} +0 -0
  368. /package/dist/browser/dev/excalidraw-assets-dev/{infoDiagram-bcd20f53-I22FLFX3.js.map → infoDiagram-bcd20f53-43FMAUOR.js.map} +0 -0
  369. /package/dist/browser/dev/excalidraw-assets-dev/{journeyDiagram-4fe6b3dc-WAO6F52C.js.map → journeyDiagram-4fe6b3dc-KFVOUX4I.js.map} +0 -0
  370. /package/dist/browser/dev/excalidraw-assets-dev/{katex-NWA2YFOP.js.map → katex-A3GRORPB.js.map} +0 -0
  371. /package/dist/browser/dev/excalidraw-assets-dev/{mindmap-definition-f354de21-K74IKX4Y.js.map → mindmap-definition-f354de21-D7S3CRQ4.js.map} +0 -0
  372. /package/dist/browser/dev/excalidraw-assets-dev/{pica-3TH2EGXR.js.map → pica-ZAD7MTGA.js.map} +0 -0
  373. /package/dist/browser/dev/excalidraw-assets-dev/{pieDiagram-79897490-DOB2LVE5.js.map → pieDiagram-79897490-OON2CRZ5.js.map} +0 -0
  374. /package/dist/browser/dev/excalidraw-assets-dev/{quadrantDiagram-62f64e94-MJV2X7WI.js.map → quadrantDiagram-62f64e94-5APTNVVS.js.map} +0 -0
  375. /package/dist/browser/dev/excalidraw-assets-dev/{requirementDiagram-05bf5f74-H4YM3XN7.js.map → requirementDiagram-05bf5f74-FM7WZVKU.js.map} +0 -0
  376. /package/dist/browser/dev/excalidraw-assets-dev/{roundRect-4S3QV2NZ.js.map → roundRect-AYYHVX5X.js.map} +0 -0
  377. /package/dist/browser/dev/excalidraw-assets-dev/{sankeyDiagram-97764748-7X74ABAN.js.map → sankeyDiagram-97764748-5HLEFFGY.js.map} +0 -0
  378. /package/dist/browser/dev/excalidraw-assets-dev/{sequenceDiagram-acc0e65c-PPDIJFQP.js.map → sequenceDiagram-acc0e65c-4ZRSNGPV.js.map} +0 -0
  379. /package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-0ff1cf1a-JVBR7N35.js.map → stateDiagram-0ff1cf1a-OLTPYRPP.js.map} +0 -0
  380. /package/dist/browser/dev/excalidraw-assets-dev/{stateDiagram-v2-9a9d610d-QYAJLQJH.js.map → stateDiagram-v2-9a9d610d-N3XOTAEE.js.map} +0 -0
  381. /package/dist/browser/dev/excalidraw-assets-dev/{timeline-definition-fea2a41d-GL7U3WDB.js.map → timeline-definition-fea2a41d-5PDFIYJQ.js.map} +0 -0
  382. /package/dist/browser/dev/excalidraw-assets-dev/{xychartDiagram-ab372869-4U4JE4TW.js.map → xychartDiagram-ab372869-VIWBP45Y.js.map} +0 -0
@@ -11,29 +11,31 @@ import { actions } from "../actions/register";
11
11
  import { trackEvent } from "../analytics";
12
12
  import { getDefaultAppState, isEraserActive, isHandToolActive, } from "../appState";
13
13
  import { copyTextToSystemClipboard, parseClipboard, } from "../clipboard";
14
- import { APP_NAME, CURSOR_TYPE, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, DEFAULT_VERTICAL_ALIGN, DRAGGING_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, ENV, EVENT, FRAME_STYLE, GRID_SIZE, IMAGE_MIME_TYPES, IMAGE_RENDER_TIMEOUT, isBrave, LINE_CONFIRM_THRESHOLD, MAX_ALLOWED_FILE_BYTES, MIME_TYPES, MQ_MAX_HEIGHT_LANDSCAPE, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_WIDTH_PORTRAIT, MQ_RIGHT_SIDEBAR_MIN_WIDTH, POINTER_BUTTON, ROUNDNESS, SCROLL_TIMEOUT, TAP_TWICE_TIMEOUT, TEXT_TO_CENTER_SNAP_THRESHOLD, THEME, THEME_FILTER, TOUCH_CTX_MENU_TIMEOUT, VERTICAL_ALIGN, YOUTUBE_STATES, ZOOM_STEP, POINTER_EVENTS, TOOL_TYPE, EDITOR_LS_KEYS, isIOS, supportsResizeObserver, } from "../constants";
14
+ import { APP_NAME, CURSOR_TYPE, DEFAULT_MAX_IMAGE_WIDTH_OR_HEIGHT, DEFAULT_VERTICAL_ALIGN, DRAGGING_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, ENV, EVENT, FRAME_STYLE, GRID_SIZE, IMAGE_MIME_TYPES, IMAGE_RENDER_TIMEOUT, isBrave, LINE_CONFIRM_THRESHOLD, MAX_ALLOWED_FILE_BYTES, MIME_TYPES, MQ_MAX_HEIGHT_LANDSCAPE, MQ_MAX_WIDTH_LANDSCAPE, MQ_MAX_WIDTH_PORTRAIT, MQ_RIGHT_SIDEBAR_MIN_WIDTH, POINTER_BUTTON, ROUNDNESS, SCROLL_TIMEOUT, TAP_TWICE_TIMEOUT, TEXT_TO_CENTER_SNAP_THRESHOLD, THEME, THEME_FILTER, TOUCH_CTX_MENU_TIMEOUT, VERTICAL_ALIGN, YOUTUBE_STATES, ZOOM_STEP, POINTER_EVENTS, TOOL_TYPE, EDITOR_LS_KEYS, isIOS, supportsResizeObserver, DEFAULT_COLLISION_THRESHOLD, } from "../constants";
15
15
  import { exportAsImage, loadFromBlob } from "../data";
16
16
  import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
17
17
  import { restore, restoreElements } from "../data/restore";
18
- import { dragNewElement, dragSelectedElements, duplicateElement, getCommonBounds, getCursorForResizingElement, getDragOffsetXY, getElementWithTransformHandleType, getNormalizedDimensions, getResizeArrowDirection, getResizeOffsetXY, getLockedLinearCursorAlignSize, getTransformHandleTypeFromCoords, hitTest, isHittingElementBoundingBoxWithoutHittingElement, isInvisiblySmallElement, isNonDeletedElement, isTextElement, newElement, newLinearElement, newTextElement, newImageElement, transformElements, updateTextElement, redrawTextBoundingBox, } from "../element";
18
+ import { dragNewElement, dragSelectedElements, duplicateElement, getCommonBounds, getCursorForResizingElement, getDragOffsetXY, getElementWithTransformHandleType, getNormalizedDimensions, getResizeArrowDirection, getResizeOffsetXY, getLockedLinearCursorAlignSize, getTransformHandleTypeFromCoords, isInvisiblySmallElement, isNonDeletedElement, isTextElement, newElement, newLinearElement, newTextElement, newImageElement, transformElements, updateTextElement, redrawTextBoundingBox, getElementAbsoluteCoords, } from "../element";
19
19
  import { bindOrUnbindLinearElement, bindOrUnbindSelectedElements, fixBindingsAfterDeletion, fixBindingsAfterDuplication, getEligibleElementsForBinding, getHoveredElementForBinding, isBindingEnabled, isLinearElementSimpleAndAlreadyBound, maybeBindLinearElement, shouldEnableBindingForPointerEvent, unbindLinearElements, updateBoundElements, } from "../element/binding";
20
20
  import { LinearElementEditor } from "../element/linearElementEditor";
21
21
  import { mutateElement, newElementWith } from "../element/mutateElement";
22
22
  import { deepCopyElement, duplicateElements, newFrameElement, newFreeDrawElement, newEmbeddableElement, newMagicFrameElement, newIframeElement, } from "../element/newElement";
23
- import { hasBoundTextElement, isArrowElement, isBindingElement, isBindingElementType, isBoundToContainer, isFrameLikeElement, isImageElement, isEmbeddableElement, isInitializedImageElement, isLinearElement, isLinearElementType, isUsingAdaptiveRadius, isFrameElement, isIframeElement, isIframeLikeElement, isMagicFrameElement, } from "../element/typeChecks";
23
+ import { hasBoundTextElement, isArrowElement, isBindingElement, isBindingElementType, isBoundToContainer, isFrameLikeElement, isImageElement, isEmbeddableElement, isInitializedImageElement, isLinearElement, isLinearElementType, isUsingAdaptiveRadius, isFrameElement, isIframeElement, isIframeLikeElement, isMagicFrameElement, isTextBindableContainer, } from "../element/typeChecks";
24
24
  import { getCenter, getDistance } from "../gesture";
25
25
  import { editGroupForSelectedElement, getElementsInGroup, getSelectedGroupIdForElement, getSelectedGroupIds, isElementInGroup, isSelectedViaGroup, selectGroupsForSelectedElements, } from "../groups";
26
- import History from "../history";
26
+ import { History } from "../history";
27
27
  import { defaultLang, getLanguage, languages, setLanguage, t } from "../i18n";
28
28
  import { CODES, shouldResizeFromCenter, shouldMaintainAspectRatio, shouldRotateWithDiscreteAngle, isArrowKey, KEYS, } from "../keys";
29
29
  import { isElementInViewport } from "../element/sizeHelpers";
30
30
  import { distance2d, getCornerRadius, getGridPoint, isPathALoop, } from "../math";
31
31
  import { clearRenderCache } from "../renderer/renderElement";
32
- import { calculateScrollCenter, getElementsAtPosition, getElementsWithinSelection, getNormalizedZoom, getSelectedElements, hasBackground, isSomeElementSelected, } from "../scene";
32
+ import { calculateScrollCenter, getElementsWithinSelection, getNormalizedZoom, getSelectedElements, hasBackground, isSomeElementSelected, } from "../scene";
33
33
  import Scene from "../scene/Scene";
34
34
  import { getStateForZoom } from "../scene/zoom";
35
35
  import { findShapeByKey } from "../shapes";
36
- import { debounce, distance, getFontString, getNearestScrollableContainer, isInputLike, isToolIcon, isWritableElement, sceneCoordsToViewportCoords, tupleToCoors, viewportCoordsToSceneCoords, wrapEvent, updateObject, updateActiveTool, getShortcutKey, isTransparent, easeToValuesRAF, muteFSAbortError, isTestEnv, easeOut, updateStable, addEventListener, normalizeEOL, getDateTime, } from "../utils";
36
+ import { getClosedCurveShape, getCurveShape, getEllipseShape, getFreedrawShape, getPolygonShape, getSelectionBoxShape, } from "../../utils/geometry/shape";
37
+ import { isPointInShape } from "../../utils/collision";
38
+ import { debounce, distance, getFontString, getNearestScrollableContainer, isInputLike, isToolIcon, isWritableElement, sceneCoordsToViewportCoords, tupleToCoors, viewportCoordsToSceneCoords, wrapEvent, updateObject, updateActiveTool, getShortcutKey, isTransparent, easeToValuesRAF, muteFSAbortError, isTestEnv, easeOut, updateStable, addEventListener, normalizeEOL, getDateTime, isShallowEqual, arrayToMap, } from "../utils";
37
39
  import { createSrcDoc, embeddableURLValidator, maybeParseEmbedSrc, getEmbedLink, } from "../element/embeddable";
38
40
  import { ContextMenu, CONTEXT_MENU_SEPARATOR, } from "./ContextMenu";
39
41
  import LayerUI from "./LayerUI";
@@ -43,8 +45,7 @@ import { dataURLToFile, generateIdFromFile, getDataURL, getFileFromEvent, ImageU
43
45
  import { getInitializedImageElements, loadHTMLImageElement, normalizeSVG, updateImageCache as _updateImageCache, } from "../element/image";
44
46
  import throttle from "lodash.throttle";
45
47
  import { fileOpen } from "../data/filesystem";
46
- import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getDefaultLineHeight, getLineHeightInPx, getTextBindableContainerAtPosition, isMeasureTextSupported, isValidTextContainer, } from "../element/textElement";
47
- import { isHittingElementNotConsideringBoundingBox } from "../element/collision";
48
+ import { bindTextToShapeAfterDuplication, getApproxMinLineHeight, getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, getDefaultLineHeight, getLineHeightInPx, isMeasureTextSupported, isValidTextContainer, } from "../element/textElement";
48
49
  import { showHyperlinkTooltip, hideHyperlinkToolip, Hyperlink, } from "../components/hyperlink/Hyperlink";
49
50
  import { isLocalLink, normalizeLink, toValidURL } from "../data/url";
50
51
  import { shouldShowBoundingBox } from "../element/transformHandles";
@@ -78,13 +79,16 @@ import { ElementCanvasButton } from "./MagicButton";
78
79
  import { MagicIcon, copyIcon, fullscreenIcon } from "./icons";
79
80
  import { EditorLocalStorage } from "../data/EditorLocalStorage";
80
81
  import FollowMode from "./FollowMode/FollowMode";
82
+ import { Store, StoreAction } from "../store";
81
83
  import { AnimationFrameHandler } from "../animation-frame-handler";
82
84
  import { AnimatedTrail } from "../animated-trail";
83
85
  import { LaserTrails } from "../laser-trails";
84
86
  import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
85
87
  import { getRenderOpacity } from "../renderer/renderElement";
88
+ import { hitElementBoundText, hitElementBoundingBoxOnly, hitElementItself, shouldTestInside, } from "../element/collision";
86
89
  import { textWysiwyg } from "../element/textWysiwyg";
87
90
  import { isOverScrollBars } from "../scene/scrollbars";
91
+ import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex";
88
92
  import { isPointHittingLink, isPointHittingLinkIcon, } from "./hyperlink/helpers";
89
93
  import { getShortcutFromShortcutName } from "../actions/shortcuts";
90
94
  const AppContext = React.createContext(null);
@@ -166,6 +170,7 @@ class App extends React.Component {
166
170
  library;
167
171
  libraryItemsFromStorage;
168
172
  id;
173
+ store;
169
174
  history;
170
175
  excalidrawContainerValue;
171
176
  files = {};
@@ -237,6 +242,8 @@ class App extends React.Component {
237
242
  this.canvas = document.createElement("canvas");
238
243
  this.rc = rough.canvas(this.canvas);
239
244
  this.renderer = new Renderer(this.scene);
245
+ this.store = new Store();
246
+ this.history = new History();
240
247
  if (excalidrawAPI) {
241
248
  const api = {
242
249
  updateScene: this.updateScene,
@@ -287,8 +294,8 @@ class App extends React.Component {
287
294
  });
288
295
  this.history = new History();
289
296
  this.actionManager.registerAll(actions);
290
- this.actionManager.registerAction(createUndoAction(this.history));
291
- this.actionManager.registerAction(createRedoAction(this.history));
297
+ this.actionManager.registerAction(createUndoAction(this.history, this.store));
298
+ this.actionManager.registerAction(createRedoAction(this.history, this.store));
292
299
  }
293
300
  onWindowMessage(event) {
294
301
  if (event.origin !== "https://player.vimeo.com" &&
@@ -879,7 +886,7 @@ class App extends React.Component {
879
886
  canvasBackgroundColor: this.state.viewBackgroundColor,
880
887
  embedsValidationStatus: this.embedsValidationStatus,
881
888
  elementsPendingErasure: this.elementsPendingErasure,
882
- } }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, selectedElements: selectedElements, versionNonce: versionNonce, selectionNonce: this.state.selectionElement?.versionNonce, scale: window.devicePixelRatio, appState: this.state, renderInteractiveSceneCallback: this.renderInteractiveSceneCallback, handleCanvasRef: this.handleInteractiveCanvasRef, onContextMenu: this.handleCanvasContextMenu, onPointerMove: this.handleCanvasPointerMove, onPointerUp: this.handleCanvasPointerUp, onPointerCancel: this.removePointer, onTouchMove: this.handleTouchMove, onPointerDown: this.handleCanvasPointerDown, onDoubleClick: this.handleCanvasDoubleClick }), this.state.userToFollow && (_jsx(FollowMode, { width: this.state.width, height: this.state.height, userToFollow: this.state.userToFollow, onDisconnect: this.maybeUnfollowRemoteUser })), this.renderFrameNames()] }), this.renderEmbeddables()] }) }) }) }) }) }) }) }));
889
+ } }), _jsx(InteractiveCanvas, { containerRef: this.excalidrawContainerRef, canvas: this.interactiveCanvas, elementsMap: elementsMap, visibleElements: visibleElements, selectedElements: selectedElements, versionNonce: versionNonce, selectionNonce: this.state.selectionElement?.versionNonce, scale: window.devicePixelRatio, appState: this.state, device: this.device, renderInteractiveSceneCallback: this.renderInteractiveSceneCallback, handleCanvasRef: this.handleInteractiveCanvasRef, onContextMenu: this.handleCanvasContextMenu, onPointerMove: this.handleCanvasPointerMove, onPointerUp: this.handleCanvasPointerUp, onPointerCancel: this.removePointer, onTouchMove: this.handleTouchMove, onPointerDown: this.handleCanvasPointerDown, onDoubleClick: this.handleCanvasDoubleClick }), this.state.userToFollow && (_jsx(FollowMode, { width: this.state.width, height: this.state.height, userToFollow: this.state.userToFollow, onDisconnect: this.maybeUnfollowRemoteUser })), this.renderFrameNames()] }), this.renderEmbeddables()] }) }) }) }) }) }) }) }));
883
890
  }
884
891
  focusContainer = () => {
885
892
  this.excalidrawContainerRef.current?.focus();
@@ -1139,7 +1146,7 @@ class App extends React.Component {
1139
1146
  opacity: 100,
1140
1147
  locked: false,
1141
1148
  });
1142
- this.scene.addNewElement(frame);
1149
+ this.scene.insertElement(frame);
1143
1150
  for (const child of selectedElements) {
1144
1151
  mutateElement(child, { frameId: frame.id });
1145
1152
  }
@@ -1163,13 +1170,13 @@ class App extends React.Component {
1163
1170
  if (shouldUpdateStrokeColor) {
1164
1171
  this.syncActionResult({
1165
1172
  appState: { ...this.state, currentItemStrokeColor: color },
1166
- commitToHistory: true,
1173
+ storeAction: StoreAction.CAPTURE,
1167
1174
  });
1168
1175
  }
1169
1176
  else {
1170
1177
  this.syncActionResult({
1171
1178
  appState: { ...this.state, currentItemBackgroundColor: color },
1172
- commitToHistory: true,
1179
+ storeAction: StoreAction.CAPTURE,
1173
1180
  });
1174
1181
  }
1175
1182
  }
@@ -1183,6 +1190,7 @@ class App extends React.Component {
1183
1190
  }
1184
1191
  return el;
1185
1192
  }),
1193
+ storeAction: StoreAction.CAPTURE,
1186
1194
  });
1187
1195
  }
1188
1196
  },
@@ -1202,10 +1210,13 @@ class App extends React.Component {
1202
1210
  editingElement = element;
1203
1211
  }
1204
1212
  });
1205
- this.scene.replaceAllElements(actionResult.elements);
1206
- if (actionResult.commitToHistory) {
1207
- this.history.resumeRecording();
1213
+ if (actionResult.storeAction === StoreAction.UPDATE) {
1214
+ this.store.shouldUpdateSnapshot();
1215
+ }
1216
+ else if (actionResult.storeAction === StoreAction.CAPTURE) {
1217
+ this.store.shouldCaptureIncrement();
1208
1218
  }
1219
+ this.scene.replaceAllElements(actionResult.elements);
1209
1220
  }
1210
1221
  if (actionResult.files) {
1211
1222
  this.files = actionResult.replaceFiles
@@ -1214,8 +1225,11 @@ class App extends React.Component {
1214
1225
  this.addNewImagesToImageCache();
1215
1226
  }
1216
1227
  if (actionResult.appState || editingElement || this.state.contextMenu) {
1217
- if (actionResult.commitToHistory) {
1218
- this.history.resumeRecording();
1228
+ if (actionResult.storeAction === StoreAction.UPDATE) {
1229
+ this.store.shouldUpdateSnapshot();
1230
+ }
1231
+ else if (actionResult.storeAction === StoreAction.CAPTURE) {
1232
+ this.store.shouldCaptureIncrement();
1219
1233
  }
1220
1234
  let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
1221
1235
  let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
@@ -1254,10 +1268,6 @@ class App extends React.Component {
1254
1268
  name,
1255
1269
  errorMessage,
1256
1270
  });
1257
- }, () => {
1258
- if (actionResult.syncHistory) {
1259
- this.history.setCurrentState(this.state, this.scene.getElementsIncludingDeleted());
1260
- }
1261
1271
  });
1262
1272
  }
1263
1273
  });
@@ -1275,6 +1285,9 @@ class App extends React.Component {
1275
1285
  resetHistory = () => {
1276
1286
  this.history.clear();
1277
1287
  };
1288
+ resetStore = () => {
1289
+ this.store.clear();
1290
+ };
1278
1291
  /**
1279
1292
  * Resets scene & history.
1280
1293
  * ! Do not use to clear scene user action !
@@ -1286,6 +1299,7 @@ class App extends React.Component {
1286
1299
  isLoading: opts?.resetLoadingState ? false : state.isLoading,
1287
1300
  theme: this.state.theme,
1288
1301
  }));
1302
+ this.resetStore();
1289
1303
  this.resetHistory();
1290
1304
  });
1291
1305
  initializeScene = async () => {
@@ -1360,6 +1374,7 @@ class App extends React.Component {
1360
1374
  // text elements on canvas, and rerender them once done. This also
1361
1375
  // seems faster even in browsers that do fire the loadingdone event.
1362
1376
  this.fonts.loadFontsForElements(scene.elements);
1377
+ this.resetStore();
1363
1378
  if (initialData?.scrollX != null) {
1364
1379
  scene.appState.scrollX = initialData.scrollX;
1365
1380
  }
@@ -1369,7 +1384,7 @@ class App extends React.Component {
1369
1384
  this.resetHistory();
1370
1385
  this.syncActionResult({
1371
1386
  ...scene,
1372
- commitToHistory: true,
1387
+ storeAction: StoreAction.UPDATE,
1373
1388
  });
1374
1389
  };
1375
1390
  isMobileBreakpoint = (width, height) => {
@@ -1440,8 +1455,15 @@ class App extends React.Component {
1440
1455
  configurable: true,
1441
1456
  value: this.history,
1442
1457
  },
1458
+ store: {
1459
+ configurable: true,
1460
+ value: this.store,
1461
+ },
1443
1462
  });
1444
1463
  }
1464
+ this.store.onStoreIncrementEmitter.on((increment) => {
1465
+ this.history.record(increment.elementsChange, increment.appStateChange);
1466
+ });
1445
1467
  this.scene.addCallback(this.onSceneUpdated);
1446
1468
  this.addEventListeners();
1447
1469
  if (this.props.autoFocus && this.excalidrawContainerRef.current) {
@@ -1491,6 +1513,7 @@ class App extends React.Component {
1491
1513
  this.laserTrails.stop();
1492
1514
  this.eraserTrail.stop();
1493
1515
  this.onChangeEmitter.clear();
1516
+ this.store.onStoreIncrementEmitter.clear();
1494
1517
  ShapeCache.destroy();
1495
1518
  SnapCache.destroy();
1496
1519
  clearRenderCache();
@@ -1574,7 +1597,8 @@ class App extends React.Component {
1574
1597
  componentDidUpdate(prevProps, prevState) {
1575
1598
  this.updateEmbeddables();
1576
1599
  const elements = this.scene.getElementsIncludingDeleted();
1577
- const elementsMap = this.scene.getNonDeletedElementsMap();
1600
+ const elementsMap = this.scene.getElementsMapIncludingDeleted();
1601
+ const nonDeletedElementsMap = this.scene.getNonDeletedElementsMap();
1578
1602
  if (!this.state.showWelcomeScreen && !elements.length) {
1579
1603
  this.setState({ showWelcomeScreen: true });
1580
1604
  }
@@ -1660,7 +1684,7 @@ class App extends React.Component {
1660
1684
  this.excalidrawContainerRef.current?.classList.toggle("theme--dark", this.state.theme === THEME.DARK);
1661
1685
  if (this.state.editingLinearElement &&
1662
1686
  !this.state.selectedElementIds[this.state.editingLinearElement.elementId]) {
1663
- // defer so that the commitToHistory flag isn't reset via current update
1687
+ // defer so that the storeAction flag isn't reset via current update
1664
1688
  setTimeout(() => {
1665
1689
  // execute only if the condition still holds when the deferred callback
1666
1690
  // executes (it can be scheduled multiple times depending on how
@@ -1685,9 +1709,9 @@ class App extends React.Component {
1685
1709
  multiElement != null &&
1686
1710
  isBindingEnabled(this.state) &&
1687
1711
  isBindingElement(multiElement, false)) {
1688
- maybeBindLinearElement(multiElement, this.state, this.scene, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, elementsMap)), elementsMap);
1712
+ maybeBindLinearElement(multiElement, this.state, tupleToCoors(LinearElementEditor.getPointAtIndexGlobalCoordinates(multiElement, -1, nonDeletedElementsMap)), this);
1689
1713
  }
1690
- this.history.record(this.state, elements);
1714
+ this.store.commit(elementsMap, this.state);
1691
1715
  // Do not notify consumers if we're still loading the scene. Among other
1692
1716
  // potential issues, this fixes a case where the tab isn't focused during
1693
1717
  // init, which would trigger onChange with empty elements, which would then
@@ -1952,16 +1976,15 @@ class App extends React.Component {
1952
1976
  }), {
1953
1977
  randomizeSeed: !opts.retainSeed,
1954
1978
  });
1955
- const allElements = [
1956
- ...this.scene.getElementsIncludingDeleted(),
1957
- ...newElements,
1958
- ];
1979
+ const prevElements = this.scene.getElementsIncludingDeleted();
1980
+ const nextElements = [...prevElements, ...newElements];
1981
+ syncMovedIndices(nextElements, arrayToMap(newElements));
1959
1982
  const topLayerFrame = this.getTopLayerFrameAtSceneCoords({ x, y });
1960
1983
  if (topLayerFrame) {
1961
1984
  const eligibleElements = filterElementsEligibleAsFrameChildren(newElements, topLayerFrame);
1962
- addElementsToFrame(allElements, eligibleElements, topLayerFrame);
1985
+ addElementsToFrame(nextElements, eligibleElements, topLayerFrame);
1963
1986
  }
1964
- this.scene.replaceAllElements(allElements);
1987
+ this.scene.replaceAllElements(nextElements);
1965
1988
  newElements.forEach((newElement) => {
1966
1989
  if (isTextElement(newElement) && isBoundToContainer(newElement)) {
1967
1990
  const container = getContainerElement(newElement, this.scene.getElementsMapIncludingDeleted());
@@ -1971,7 +1994,7 @@ class App extends React.Component {
1971
1994
  if (opts.files) {
1972
1995
  this.files = { ...this.files, ...opts.files };
1973
1996
  }
1974
- this.history.resumeRecording();
1997
+ this.store.shouldCaptureIncrement();
1975
1998
  const nextElementsToSelect = excludeElementsInFramesFromSelection(newElements);
1976
1999
  this.setState({
1977
2000
  ...this.state,
@@ -2129,16 +2152,7 @@ class App extends React.Component {
2129
2152
  if (textElements.length === 0) {
2130
2153
  return;
2131
2154
  }
2132
- const frameId = textElements[0].frameId;
2133
- if (frameId) {
2134
- this.scene.insertElementsAtIndex(textElements, this.scene.getElementIndex(frameId));
2135
- }
2136
- else {
2137
- this.scene.replaceAllElements([
2138
- ...this.scene.getElementsIncludingDeleted(),
2139
- ...textElements,
2140
- ]);
2141
- }
2155
+ this.scene.insertElements(textElements);
2142
2156
  this.setState({
2143
2157
  selectedElementIds: makeNextSelectedElementIds(Object.fromEntries(textElements.map((el) => [el.id, true])), this.state),
2144
2158
  });
@@ -2154,7 +2168,7 @@ class App extends React.Component {
2154
2168
  });
2155
2169
  PLAIN_PASTE_TOAST_SHOWN = true;
2156
2170
  }
2157
- this.history.resumeRecording();
2171
+ this.store.shouldCaptureIncrement();
2158
2172
  }
2159
2173
  setAppState = (state, callback) => {
2160
2174
  this.setState(state, callback);
@@ -2340,14 +2354,31 @@ class App extends React.Component {
2340
2354
  this.addNewImagesToImageCache();
2341
2355
  });
2342
2356
  updateScene = withBatchedUpdates((sceneData) => {
2343
- if (sceneData.commitToHistory) {
2344
- this.history.resumeRecording();
2357
+ const nextElements = syncInvalidIndices(sceneData.elements ?? []);
2358
+ if (sceneData.storeAction && sceneData.storeAction !== StoreAction.NONE) {
2359
+ const prevCommittedAppState = this.store.snapshot.appState;
2360
+ const prevCommittedElements = this.store.snapshot.elements;
2361
+ const nextCommittedAppState = sceneData.appState
2362
+ ? Object.assign({}, prevCommittedAppState, sceneData.appState) // new instance, with partial appstate applied to previously captured one, including hidden prop inside `prevCommittedAppState`
2363
+ : prevCommittedAppState;
2364
+ const nextCommittedElements = sceneData.elements
2365
+ ? this.store.filterUncomittedElements(this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements
2366
+ arrayToMap(nextElements))
2367
+ : prevCommittedElements;
2368
+ // WARN: store action always performs deep clone of changed elements, for ephemeral remote updates (i.e. remote dragging, resizing, drawing) we might consider doing something smarter
2369
+ // do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well
2370
+ if (sceneData.storeAction === StoreAction.CAPTURE) {
2371
+ this.store.captureIncrement(nextCommittedElements, nextCommittedAppState);
2372
+ }
2373
+ else if (sceneData.storeAction === StoreAction.UPDATE) {
2374
+ this.store.updateSnapshot(nextCommittedElements, nextCommittedAppState);
2375
+ }
2345
2376
  }
2346
2377
  if (sceneData.appState) {
2347
2378
  this.setState(sceneData.appState);
2348
2379
  }
2349
2380
  if (sceneData.elements) {
2350
- this.scene.replaceAllElements(sceneData.elements);
2381
+ this.scene.replaceAllElements(nextElements);
2351
2382
  }
2352
2383
  if (sceneData.collaborators) {
2353
2384
  this.setState({ collaborators: sceneData.collaborators });
@@ -2533,7 +2564,7 @@ class App extends React.Component {
2533
2564
  if (!this.state.editingLinearElement ||
2534
2565
  this.state.editingLinearElement.elementId !==
2535
2566
  selectedElements[0].id) {
2536
- this.history.resumeRecording();
2567
+ this.store.shouldCaptureIncrement();
2537
2568
  this.setState({
2538
2569
  editingLinearElement: new LinearElementEditor(selectedElement),
2539
2570
  });
@@ -2662,7 +2693,7 @@ class App extends React.Component {
2662
2693
  const selectedElements = this.scene.getSelectedElements(this.state);
2663
2694
  const elementsMap = this.scene.getNonDeletedElementsMap();
2664
2695
  isBindingEnabled(this.state)
2665
- ? bindOrUnbindSelectedElements(selectedElements, this.scene.getNonDeletedElements(), elementsMap)
2696
+ ? bindOrUnbindSelectedElements(selectedElements, this)
2666
2697
  : unbindLinearElements(selectedElements, elementsMap);
2667
2698
  this.setState({ suggestedBindings: [] });
2668
2699
  }
@@ -2695,6 +2726,9 @@ class App extends React.Component {
2695
2726
  originSnapOffset: null,
2696
2727
  activeEmbeddable: null,
2697
2728
  };
2729
+ if (nextActiveTool.type === "freedraw") {
2730
+ this.store.shouldCaptureIncrement();
2731
+ }
2698
2732
  let nextState;
2699
2733
  if (nextActiveTool.type !== "selection") {
2700
2734
  nextState = {
@@ -2867,7 +2901,7 @@ class App extends React.Component {
2867
2901
  ]);
2868
2902
  }
2869
2903
  if (!isDeleted || isExistingElement) {
2870
- this.history.resumeRecording();
2904
+ this.store.shouldCaptureIncrement();
2871
2905
  }
2872
2906
  this.setState({
2873
2907
  draggingElement: null,
@@ -2905,6 +2939,57 @@ class App extends React.Component {
2905
2939
  }
2906
2940
  return null;
2907
2941
  }
2942
+ /**
2943
+ * get the pure geometric shape of an excalidraw element
2944
+ * which is then used for hit detection
2945
+ */
2946
+ getElementShape(element) {
2947
+ switch (element.type) {
2948
+ case "rectangle":
2949
+ case "diamond":
2950
+ case "frame":
2951
+ case "magicframe":
2952
+ case "embeddable":
2953
+ case "image":
2954
+ case "iframe":
2955
+ case "text":
2956
+ case "selection":
2957
+ return getPolygonShape(element);
2958
+ case "arrow":
2959
+ case "line": {
2960
+ const roughShape = ShapeCache.get(element)?.[0] ??
2961
+ ShapeCache.generateElementShape(element, null)[0];
2962
+ const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
2963
+ return shouldTestInside(element)
2964
+ ? getClosedCurveShape(element, roughShape, [element.x, element.y], element.angle, [cx, cy])
2965
+ : getCurveShape(roughShape, [element.x, element.y], element.angle, [
2966
+ cx,
2967
+ cy,
2968
+ ]);
2969
+ }
2970
+ case "ellipse":
2971
+ return getEllipseShape(element);
2972
+ case "freedraw": {
2973
+ const [, , , , cx, cy] = getElementAbsoluteCoords(element, this.scene.getNonDeletedElementsMap());
2974
+ return getFreedrawShape(element, [cx, cy], shouldTestInside(element));
2975
+ }
2976
+ }
2977
+ }
2978
+ getBoundTextShape(element) {
2979
+ const boundTextElement = getBoundTextElement(element, this.scene.getNonDeletedElementsMap());
2980
+ if (boundTextElement) {
2981
+ if (element.type === "arrow") {
2982
+ return this.getElementShape({
2983
+ ...boundTextElement,
2984
+ // arrow's bound text accurate position is not stored in the element's property
2985
+ // but rather calculated and returned from the following static method
2986
+ ...LinearElementEditor.getBoundTextElementPosition(element, boundTextElement, this.scene.getNonDeletedElementsMap()),
2987
+ });
2988
+ }
2989
+ return this.getElementShape(boundTextElement);
2990
+ }
2991
+ return null;
2992
+ }
2908
2993
  getElementAtPosition(x, y, opts) {
2909
2994
  const allHitElements = this.getElementsAtPosition(x, y, opts?.includeBoundTextElement, opts?.includeLockedElements);
2910
2995
  if (allHitElements.length > 1) {
@@ -2918,9 +3003,20 @@ class App extends React.Component {
2918
3003
  const elementWithHighestZIndex = allHitElements[allHitElements.length - 1];
2919
3004
  // If we're hitting element with highest z-index only on its bounding box
2920
3005
  // while also hitting other element figure, the latter should be considered.
2921
- return isHittingElementBoundingBoxWithoutHittingElement(elementWithHighestZIndex, this.state, this.frameNameBoundsCache, x, y, this.scene.getNonDeletedElementsMap())
2922
- ? allHitElements[allHitElements.length - 2]
2923
- : elementWithHighestZIndex;
3006
+ return hitElementItself({
3007
+ x,
3008
+ y,
3009
+ element: elementWithHighestZIndex,
3010
+ shape: this.getElementShape(elementWithHighestZIndex),
3011
+ // when overlapping, we would like to be more precise
3012
+ // this also avoids the need to update past tests
3013
+ threshold: this.getElementHitThreshold() / 2,
3014
+ frameNameBound: isFrameLikeElement(elementWithHighestZIndex)
3015
+ ? this.frameNameBoundsCache.get(elementWithHighestZIndex)
3016
+ : null,
3017
+ })
3018
+ ? elementWithHighestZIndex
3019
+ : allHitElements[allHitElements.length - 2];
2924
3020
  }
2925
3021
  if (allHitElements.length === 1) {
2926
3022
  return allHitElements[0];
@@ -2928,15 +3024,17 @@ class App extends React.Component {
2928
3024
  return null;
2929
3025
  }
2930
3026
  getElementsAtPosition(x, y, includeBoundTextElement = false, includeLockedElements = false) {
2931
- const elements = includeBoundTextElement && includeLockedElements
3027
+ const iframeLikes = [];
3028
+ const elementsMap = this.scene.getNonDeletedElementsMap();
3029
+ const elements = (includeBoundTextElement && includeLockedElements
2932
3030
  ? this.scene.getNonDeletedElements()
2933
3031
  : this.scene
2934
3032
  .getNonDeletedElements()
2935
3033
  .filter((element) => (includeLockedElements || !element.locked) &&
2936
3034
  (includeBoundTextElement ||
2937
- !(isTextElement(element) && element.containerId)));
2938
- const elementsMap = this.scene.getNonDeletedElementsMap();
2939
- return getElementsAtPosition(elements, (element) => hitTest(element, this.state, this.frameNameBoundsCache, x, y, elementsMap)).filter((element) => {
3035
+ !(isTextElement(element) && element.containerId))))
3036
+ .filter((el) => this.hitElement(x, y, el))
3037
+ .filter((element) => {
2940
3038
  // hitting a frame's element from outside the frame is not considered a hit
2941
3039
  const containingFrame = getContainingFrame(element, elementsMap);
2942
3040
  return containingFrame &&
@@ -2944,8 +3042,81 @@ class App extends React.Component {
2944
3042
  this.state.frameRendering.clip
2945
3043
  ? isCursorInFrame({ x, y }, containingFrame, elementsMap)
2946
3044
  : true;
3045
+ })
3046
+ .filter((el) => {
3047
+ // The parameter elements comes ordered from lower z-index to higher.
3048
+ // We want to preserve that order on the returned array.
3049
+ // Exception being embeddables which should be on top of everything else in
3050
+ // terms of hit testing.
3051
+ if (isIframeElement(el)) {
3052
+ iframeLikes.push(el);
3053
+ return false;
3054
+ }
3055
+ return true;
3056
+ })
3057
+ .concat(iframeLikes);
3058
+ return elements;
3059
+ }
3060
+ getElementHitThreshold() {
3061
+ return DEFAULT_COLLISION_THRESHOLD / this.state.zoom.value;
3062
+ }
3063
+ hitElement(x, y, element, considerBoundingBox = true) {
3064
+ // if the element is selected, then hit test is done against its bounding box
3065
+ if (considerBoundingBox &&
3066
+ this.state.selectedElementIds[element.id] &&
3067
+ shouldShowBoundingBox([element], this.state)) {
3068
+ const selectionShape = getSelectionBoxShape(element, this.scene.getNonDeletedElementsMap(), this.getElementHitThreshold());
3069
+ return isPointInShape([x, y], selectionShape);
3070
+ }
3071
+ // take bound text element into consideration for hit collision as well
3072
+ const hitBoundTextOfElement = hitElementBoundText(x, y, this.getBoundTextShape(element));
3073
+ if (hitBoundTextOfElement) {
3074
+ return true;
3075
+ }
3076
+ return hitElementItself({
3077
+ x,
3078
+ y,
3079
+ element,
3080
+ shape: this.getElementShape(element),
3081
+ threshold: this.getElementHitThreshold(),
3082
+ frameNameBound: isFrameLikeElement(element)
3083
+ ? this.frameNameBoundsCache.get(element)
3084
+ : null,
2947
3085
  });
2948
3086
  }
3087
+ getTextBindableContainerAtPosition(x, y) {
3088
+ const elements = this.scene.getNonDeletedElements();
3089
+ const selectedElements = this.scene.getSelectedElements(this.state);
3090
+ if (selectedElements.length === 1) {
3091
+ return isTextBindableContainer(selectedElements[0], false)
3092
+ ? selectedElements[0]
3093
+ : null;
3094
+ }
3095
+ let hitElement = null;
3096
+ // We need to do hit testing from front (end of the array) to back (beginning of the array)
3097
+ for (let index = elements.length - 1; index >= 0; --index) {
3098
+ if (elements[index].isDeleted) {
3099
+ continue;
3100
+ }
3101
+ const [x1, y1, x2, y2] = getElementAbsoluteCoords(elements[index], this.scene.getNonDeletedElementsMap());
3102
+ if (isArrowElement(elements[index]) &&
3103
+ hitElementItself({
3104
+ x,
3105
+ y,
3106
+ element: elements[index],
3107
+ shape: this.getElementShape(elements[index]),
3108
+ threshold: this.getElementHitThreshold(),
3109
+ })) {
3110
+ hitElement = elements[index];
3111
+ break;
3112
+ }
3113
+ else if (x1 < x && x < x2 && y1 < y && y < y2) {
3114
+ hitElement = elements[index];
3115
+ break;
3116
+ }
3117
+ }
3118
+ return isTextBindableContainer(hitElement, false) ? hitElement : null;
3119
+ }
2949
3120
  startTextEditing = ({ sceneX, sceneY, insertAtParentCenter = true, container, }) => {
2950
3121
  let shouldBindToContainer = false;
2951
3122
  let parentCenterPosition = insertAtParentCenter &&
@@ -3044,7 +3215,7 @@ class App extends React.Component {
3044
3215
  this.scene.insertElementAtIndex(element, containerIndex + 1);
3045
3216
  }
3046
3217
  else {
3047
- this.scene.addNewElement(element);
3218
+ this.scene.insertElement(element);
3048
3219
  }
3049
3220
  }
3050
3221
  this.setState({
@@ -3069,7 +3240,7 @@ class App extends React.Component {
3069
3240
  if (event[KEYS.CTRL_OR_CMD] &&
3070
3241
  (!this.state.editingLinearElement ||
3071
3242
  this.state.editingLinearElement.elementId !== selectedElements[0].id)) {
3072
- this.history.resumeRecording();
3243
+ this.store.shouldCaptureIncrement();
3073
3244
  this.setState({
3074
3245
  editingLinearElement: new LinearElementEditor(selectedElements[0]),
3075
3246
  });
@@ -3084,6 +3255,7 @@ class App extends React.Component {
3084
3255
  const selectedGroupId = hitElement &&
3085
3256
  getSelectedGroupIdForElement(hitElement, this.state.selectedGroupIds);
3086
3257
  if (selectedGroupId) {
3258
+ this.store.shouldCaptureIncrement();
3087
3259
  this.setState((prevState) => ({
3088
3260
  ...prevState,
3089
3261
  ...selectGroupsForSelectedElements({
@@ -3103,11 +3275,17 @@ class App extends React.Component {
3103
3275
  });
3104
3276
  return;
3105
3277
  }
3106
- const container = getTextBindableContainerAtPosition(this.scene.getNonDeletedElements(), this.state, sceneX, sceneY, this.scene.getNonDeletedElementsMap());
3278
+ const container = this.getTextBindableContainerAtPosition(sceneX, sceneY);
3107
3279
  if (container) {
3108
3280
  if (hasBoundTextElement(container) ||
3109
3281
  !isTransparent(container.backgroundColor) ||
3110
- isHittingElementNotConsideringBoundingBox(container, this.state, this.frameNameBoundsCache, [sceneX, sceneY], this.scene.getNonDeletedElementsMap())) {
3282
+ hitElementItself({
3283
+ x: sceneX,
3284
+ y: sceneY,
3285
+ element: container,
3286
+ shape: this.getElementShape(container),
3287
+ threshold: this.getElementHitThreshold(),
3288
+ })) {
3111
3289
  const midPoint = getContainerCenter(container, this.state, this.scene.getNonDeletedElementsMap());
3112
3290
  sceneX = midPoint.x;
3113
3291
  sceneY = midPoint.y;
@@ -3381,15 +3559,23 @@ class App extends React.Component {
3381
3559
  if (selectedElements.length === 1 &&
3382
3560
  !isOverScrollBar &&
3383
3561
  !this.state.editingLinearElement) {
3384
- const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap());
3385
- if (elementWithTransformHandleType &&
3386
- elementWithTransformHandleType.transformHandleType) {
3387
- setCursor(this.interactiveCanvas, getCursorForResizingElement(elementWithTransformHandleType));
3388
- return;
3562
+ // for linear elements, we'd like to prioritize point dragging over edge resizing
3563
+ // therefore, we update and check hovered point index first
3564
+ if (this.state.selectedLinearElement) {
3565
+ this.handleHoverSelectedLinearElement(this.state.selectedLinearElement, scenePointerX, scenePointerY);
3566
+ }
3567
+ if (!this.state.selectedLinearElement ||
3568
+ this.state.selectedLinearElement.hoverPointIndex === -1) {
3569
+ const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
3570
+ if (elementWithTransformHandleType &&
3571
+ elementWithTransformHandleType.transformHandleType) {
3572
+ setCursor(this.interactiveCanvas, getCursorForResizingElement(elementWithTransformHandleType));
3573
+ return;
3574
+ }
3389
3575
  }
3390
3576
  }
3391
3577
  else if (selectedElements.length > 1 && !isOverScrollBar) {
3392
- const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType);
3578
+ const transformHandleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), scenePointerX, scenePointerY, this.state.zoom, event.pointerType, this.device);
3393
3579
  if (transformHandleType) {
3394
3580
  setCursor(this.interactiveCanvas, getCursorForResizingElement({
3395
3581
  transformHandleType,
@@ -3493,7 +3679,7 @@ class App extends React.Component {
3493
3679
  }
3494
3680
  };
3495
3681
  const distance = distance2d(pointerDownState.lastCoords.x, pointerDownState.lastCoords.y, scenePointer.x, scenePointer.y);
3496
- const threshold = 10 / this.state.zoom.value;
3682
+ const threshold = this.getElementHitThreshold();
3497
3683
  const point = { ...pointerDownState.lastCoords };
3498
3684
  let samplingInterval = 0;
3499
3685
  while (samplingInterval <= distance) {
@@ -3539,30 +3725,29 @@ class App extends React.Component {
3539
3725
  handleHoverSelectedLinearElement(linearElementEditor, scenePointerX, scenePointerY) {
3540
3726
  const elementsMap = this.scene.getNonDeletedElementsMap();
3541
3727
  const element = LinearElementEditor.getElement(linearElementEditor.elementId, elementsMap);
3542
- const boundTextElement = getBoundTextElement(element, elementsMap);
3543
3728
  if (!element) {
3544
3729
  return;
3545
3730
  }
3546
3731
  if (this.state.selectedLinearElement) {
3547
3732
  let hoverPointIndex = -1;
3548
3733
  let segmentMidPointHoveredCoords = null;
3549
- if (isHittingElementNotConsideringBoundingBox(element, this.state, this.frameNameBoundsCache, [scenePointerX, scenePointerY], elementsMap)) {
3734
+ if (hitElementItself({
3735
+ x: scenePointerX,
3736
+ y: scenePointerY,
3737
+ element,
3738
+ shape: this.getElementShape(element),
3739
+ })) {
3550
3740
  hoverPointIndex = LinearElementEditor.getPointIndexUnderCursor(element, elementsMap, this.state.zoom, scenePointerX, scenePointerY);
3551
3741
  segmentMidPointHoveredCoords =
3552
3742
  LinearElementEditor.getSegmentMidpointHitCoords(linearElementEditor, { x: scenePointerX, y: scenePointerY }, this.state, this.scene.getNonDeletedElementsMap());
3553
3743
  if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {
3554
3744
  setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
3555
3745
  }
3556
- else {
3746
+ else if (this.hitElement(scenePointerX, scenePointerY, element)) {
3557
3747
  setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
3558
3748
  }
3559
3749
  }
3560
- else if (shouldShowBoundingBox([element], this.state) &&
3561
- isHittingElementBoundingBoxWithoutHittingElement(element, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY, elementsMap)) {
3562
- setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
3563
- }
3564
- else if (boundTextElement &&
3565
- hitTest(boundTextElement, this.state, this.frameNameBoundsCache, scenePointerX, scenePointerY, this.scene.getNonDeletedElementsMap())) {
3750
+ else if (this.hitElement(scenePointerX, scenePointerY, element)) {
3566
3751
  setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
3567
3752
  }
3568
3753
  if (this.state.selectedLinearElement.hoverPointIndex !== hoverPointIndex) {
@@ -3629,6 +3814,7 @@ class App extends React.Component {
3629
3814
  return obj;
3630
3815
  }, {}), this.state),
3631
3816
  },
3817
+ storeAction: StoreAction.UPDATE,
3632
3818
  });
3633
3819
  return;
3634
3820
  }
@@ -4071,8 +4257,11 @@ class App extends React.Component {
4071
4257
  const elements = this.scene.getNonDeletedElements();
4072
4258
  const elementsMap = this.scene.getNonDeletedElementsMap();
4073
4259
  const selectedElements = this.scene.getSelectedElements(this.state);
4074
- if (selectedElements.length === 1 && !this.state.editingLinearElement) {
4075
- const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap());
4260
+ if (selectedElements.length === 1 &&
4261
+ !this.state.editingLinearElement &&
4262
+ !(this.state.selectedLinearElement &&
4263
+ this.state.selectedLinearElement.hoverPointIndex !== -1)) {
4264
+ const elementWithTransformHandleType = getElementWithTransformHandleType(elements, this.state, pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.scene.getNonDeletedElementsMap(), this.device);
4076
4265
  if (elementWithTransformHandleType != null) {
4077
4266
  this.setState({
4078
4267
  resizingElement: elementWithTransformHandleType.element,
@@ -4082,7 +4271,7 @@ class App extends React.Component {
4082
4271
  }
4083
4272
  }
4084
4273
  else if (selectedElements.length > 1) {
4085
- pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType);
4274
+ pointerDownState.resize.handleType = getTransformHandleTypeFromCoords(getCommonBounds(selectedElements), pointerDownState.origin.x, pointerDownState.origin.y, this.state.zoom, event.pointerType, this.device);
4086
4275
  }
4087
4276
  if (pointerDownState.resize.handleType) {
4088
4277
  pointerDownState.resize.isResizing = true;
@@ -4096,7 +4285,7 @@ class App extends React.Component {
4096
4285
  else {
4097
4286
  if (this.state.selectedLinearElement) {
4098
4287
  const linearElementEditor = this.state.editingLinearElement || this.state.selectedLinearElement;
4099
- const ret = LinearElementEditor.handlePointerDown(event, this.state, this.history, pointerDownState.origin, linearElementEditor, this.scene.getNonDeletedElements(), elementsMap);
4288
+ const ret = LinearElementEditor.handlePointerDown(event, this.state, this.store, pointerDownState.origin, linearElementEditor, this);
4100
4289
  if (ret.hitElement) {
4101
4290
  pointerDownState.hit.element = ret.hitElement;
4102
4291
  }
@@ -4257,7 +4446,7 @@ class App extends React.Component {
4257
4446
  return false;
4258
4447
  }
4259
4448
  // How many pixels off the shape boundary we still consider a hit
4260
- const threshold = 10 / this.state.zoom.value;
4449
+ const threshold = this.getElementHitThreshold();
4261
4450
  const [x1, y1, x2, y2] = getCommonBounds(selectedElements);
4262
4451
  return (point.x > x1 - threshold &&
4263
4452
  point.x < x2 + threshold &&
@@ -4277,7 +4466,7 @@ class App extends React.Component {
4277
4466
  includeBoundTextElement: true,
4278
4467
  });
4279
4468
  // FIXME
4280
- let container = getTextBindableContainerAtPosition(this.scene.getNonDeletedElements(), this.state, sceneX, sceneY, this.scene.getNonDeletedElementsMap());
4469
+ let container = this.getTextBindableContainerAtPosition(sceneX, sceneY);
4281
4470
  if (hasBoundTextElement(element)) {
4282
4471
  container = element;
4283
4472
  sceneX = element.x + element.width / 2;
@@ -4335,8 +4524,8 @@ class App extends React.Component {
4335
4524
  points: [[0, 0]],
4336
4525
  pressures,
4337
4526
  });
4338
- const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());
4339
- this.scene.addNewElement(element);
4527
+ const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
4528
+ this.scene.insertElement(element);
4340
4529
  this.setState({
4341
4530
  draggingElement: element,
4342
4531
  editingElement: element,
@@ -4364,10 +4553,7 @@ class App extends React.Component {
4364
4553
  width,
4365
4554
  height,
4366
4555
  });
4367
- this.scene.replaceAllElements([
4368
- ...this.scene.getElementsIncludingDeleted(),
4369
- element,
4370
- ]);
4556
+ this.scene.insertElement(element);
4371
4557
  return element;
4372
4558
  };
4373
4559
  //create rectangle element with youtube top left on nearest grid point width / hight 640/360
@@ -4402,10 +4588,7 @@ class App extends React.Component {
4402
4588
  height: embedLink.intrinsicSize.h,
4403
4589
  link,
4404
4590
  });
4405
- this.scene.replaceAllElements([
4406
- ...this.scene.getElementsIncludingDeleted(),
4407
- element,
4408
- ]);
4591
+ this.scene.insertElement(element);
4409
4592
  return element;
4410
4593
  };
4411
4594
  createImageElement = ({ sceneX, sceneY, addToFrameUnderCursor = true, }) => {
@@ -4513,8 +4696,8 @@ class App extends React.Component {
4513
4696
  mutateElement(element, {
4514
4697
  points: [...element.points, [0, 0]],
4515
4698
  });
4516
- const boundElement = getHoveredElementForBinding(pointerDownState.origin, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());
4517
- this.scene.addNewElement(element);
4699
+ const boundElement = getHoveredElementForBinding(pointerDownState.origin, this);
4700
+ this.scene.insertElement(element);
4518
4701
  this.setState({
4519
4702
  draggingElement: element,
4520
4703
  editingElement: element,
@@ -4574,7 +4757,7 @@ class App extends React.Component {
4574
4757
  });
4575
4758
  }
4576
4759
  else {
4577
- this.scene.addNewElement(element);
4760
+ this.scene.insertElement(element);
4578
4761
  this.setState({
4579
4762
  multiElement: null,
4580
4763
  draggingElement: element,
@@ -4596,10 +4779,7 @@ class App extends React.Component {
4596
4779
  const frame = type === TOOL_TYPE.magicframe
4597
4780
  ? newMagicFrameElement(constructorOpts)
4598
4781
  : newFrameElement(constructorOpts);
4599
- this.scene.replaceAllElements([
4600
- ...this.scene.getElementsIncludingDeleted(),
4601
- frame,
4602
- ]);
4782
+ this.scene.insertElement(frame);
4603
4783
  this.setState({
4604
4784
  multiElement: null,
4605
4785
  draggingElement: frame,
@@ -4857,6 +5037,7 @@ class App extends React.Component {
4857
5037
  }
4858
5038
  }
4859
5039
  const nextSceneElements = [...nextElements, ...elementsToAppend];
5040
+ syncMovedIndices(nextSceneElements, arrayToMap(elementsToAppend));
4860
5041
  bindTextToShapeAfterDuplication(nextElements, elementsToAppend, oldIdToDuplicatedId);
4861
5042
  fixBindingsAfterDuplication(nextSceneElements, elementsToAppend, oldIdToDuplicatedId, "duplicatesServeAsOld");
4862
5043
  bindElementsToFramesAfterDuplication(nextSceneElements, elementsToAppend, oldIdToDuplicatedId);
@@ -5049,7 +5230,7 @@ class App extends React.Component {
5049
5230
  this.actionManager.executeAction(actionFinalize);
5050
5231
  }
5051
5232
  else {
5052
- const editingLinearElement = LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this.scene.getNonDeletedElements(), elementsMap);
5233
+ const editingLinearElement = LinearElementEditor.handlePointerUp(childEvent, this.state.editingLinearElement, this.state, this);
5053
5234
  if (editingLinearElement !== this.state.editingLinearElement) {
5054
5235
  this.setState({
5055
5236
  editingLinearElement,
@@ -5068,7 +5249,7 @@ class App extends React.Component {
5068
5249
  }
5069
5250
  }
5070
5251
  else {
5071
- const linearElementEditor = LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this.scene.getNonDeletedElements(), elementsMap);
5252
+ const linearElementEditor = LinearElementEditor.handlePointerUp(childEvent, this.state.selectedLinearElement, this.state, this);
5072
5253
  const { startBindingElement, endBindingElement } = linearElementEditor;
5073
5254
  const element = this.scene.getElement(linearElementEditor.elementId);
5074
5255
  if (isBindingElement(element)) {
@@ -5137,7 +5318,7 @@ class App extends React.Component {
5137
5318
  }
5138
5319
  if (isLinearElement(draggingElement)) {
5139
5320
  if (draggingElement.points.length > 1) {
5140
- this.history.resumeRecording();
5321
+ this.store.shouldCaptureIncrement();
5141
5322
  }
5142
5323
  const pointerCoords = viewportCoordsToSceneCoords(childEvent, this.state);
5143
5324
  if (!pointerDownState.drag.hasOccurred &&
@@ -5160,7 +5341,7 @@ class App extends React.Component {
5160
5341
  else if (pointerDownState.drag.hasOccurred && !multiElement) {
5161
5342
  if (isBindingEnabled(this.state) &&
5162
5343
  isBindingElement(draggingElement, false)) {
5163
- maybeBindLinearElement(draggingElement, this.state, this.scene, pointerCoords, elementsMap);
5344
+ maybeBindLinearElement(draggingElement, this.state, pointerCoords, this);
5164
5345
  }
5165
5346
  this.setState({ suggestedBindings: [], startBoundElement: null });
5166
5347
  if (!activeTool.locked) {
@@ -5189,11 +5370,15 @@ class App extends React.Component {
5189
5370
  draggingElement &&
5190
5371
  isInvisiblySmallElement(draggingElement)) {
5191
5372
  // remove invisible element which was added in onPointerDown
5192
- this.scene.replaceAllElements(this.scene
5193
- .getElementsIncludingDeleted()
5194
- .filter((el) => el.id !== draggingElement.id));
5195
- this.setState({
5196
- draggingElement: null,
5373
+ // update the store snapshot, so that invisible elements are not captured by the store
5374
+ this.updateScene({
5375
+ elements: this.scene
5376
+ .getElementsIncludingDeleted()
5377
+ .filter((el) => el.id !== draggingElement.id),
5378
+ appState: {
5379
+ draggingElement: null,
5380
+ },
5381
+ storeAction: StoreAction.UPDATE,
5197
5382
  });
5198
5383
  return;
5199
5384
  }
@@ -5274,12 +5459,16 @@ class App extends React.Component {
5274
5459
  mutateElement(draggingElement, getNormalizedDimensions(draggingElement));
5275
5460
  }
5276
5461
  if (resizingElement) {
5277
- this.history.resumeRecording();
5462
+ this.store.shouldCaptureIncrement();
5278
5463
  }
5279
5464
  if (resizingElement && isInvisiblySmallElement(resizingElement)) {
5280
- this.scene.replaceAllElements(this.scene
5281
- .getElementsIncludingDeleted()
5282
- .filter((el) => el.id !== resizingElement.id));
5465
+ // update the store snapshot, so that invisible elements are not captured by the store
5466
+ this.updateScene({
5467
+ elements: this.scene
5468
+ .getElementsIncludingDeleted()
5469
+ .filter((el) => el.id !== resizingElement.id),
5470
+ storeAction: StoreAction.UPDATE,
5471
+ });
5283
5472
  }
5284
5473
  // handle frame membership for resizing frames and/or selected elements
5285
5474
  if (pointerDownState.resize.isResizing) {
@@ -5434,10 +5623,23 @@ class App extends React.Component {
5434
5623
  }));
5435
5624
  }
5436
5625
  }
5437
- if (!pointerDownState.drag.hasOccurred &&
5626
+ if (
5627
+ // not dragged
5628
+ !pointerDownState.drag.hasOccurred &&
5629
+ // not resized
5438
5630
  !this.state.isResizing &&
5631
+ // only hitting the bounding box of the previous hit element
5439
5632
  ((hitElement &&
5440
- isHittingElementBoundingBoxWithoutHittingElement(hitElement, this.state, this.frameNameBoundsCache, pointerDownState.origin.x, pointerDownState.origin.y, this.scene.getNonDeletedElementsMap())) ||
5633
+ hitElementBoundingBoxOnly({
5634
+ x: pointerDownState.origin.x,
5635
+ y: pointerDownState.origin.y,
5636
+ element: hitElement,
5637
+ shape: this.getElementShape(hitElement),
5638
+ threshold: this.getElementHitThreshold(),
5639
+ frameNameBound: isFrameLikeElement(hitElement)
5640
+ ? this.frameNameBoundsCache.get(hitElement)
5641
+ : null,
5642
+ }, elementsMap)) ||
5441
5643
  (!hitElement &&
5442
5644
  pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements))) {
5443
5645
  if (this.state.editingLinearElement) {
@@ -5452,6 +5654,8 @@ class App extends React.Component {
5452
5654
  activeEmbeddable: null,
5453
5655
  });
5454
5656
  }
5657
+ // reset cursor
5658
+ setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO);
5455
5659
  return;
5456
5660
  }
5457
5661
  if (!activeTool.locked &&
@@ -5469,12 +5673,13 @@ class App extends React.Component {
5469
5673
  }));
5470
5674
  }
5471
5675
  if (activeTool.type !== "selection" ||
5472
- isSomeElementSelected(this.scene.getNonDeletedElements(), this.state)) {
5473
- this.history.resumeRecording();
5676
+ isSomeElementSelected(this.scene.getNonDeletedElements(), this.state) ||
5677
+ !isShallowEqual(this.state.previousSelectedElementIds, this.state.selectedElementIds)) {
5678
+ this.store.shouldCaptureIncrement();
5474
5679
  }
5475
5680
  if (pointerDownState.drag.hasOccurred || isResizing || isRotating) {
5476
5681
  isBindingEnabled(this.state)
5477
- ? bindOrUnbindSelectedElements(this.scene.getSelectedElements(this.state), this.scene.getNonDeletedElements(), elementsMap)
5682
+ ? bindOrUnbindSelectedElements(this.scene.getSelectedElements(this.state), this)
5478
5683
  : unbindLinearElements(this.scene.getSelectedElements(this.state), elementsMap);
5479
5684
  }
5480
5685
  if (activeTool.type === "laser") {
@@ -5526,7 +5731,7 @@ class App extends React.Component {
5526
5731
  });
5527
5732
  this.elementsPendingErasure = new Set();
5528
5733
  if (didChange) {
5529
- this.history.resumeRecording();
5734
+ this.store.shouldCaptureIncrement();
5530
5735
  this.scene.replaceAllElements(elements);
5531
5736
  }
5532
5737
  };
@@ -5629,7 +5834,7 @@ class App extends React.Component {
5629
5834
  this.setState({ errorMessage: t("errors.imageToolNotSupported") });
5630
5835
  return;
5631
5836
  }
5632
- this.scene.addNewElement(imageElement);
5837
+ this.scene.insertElement(imageElement);
5633
5838
  try {
5634
5839
  return await this.initializeImage({
5635
5840
  imageFile,
@@ -5818,7 +6023,7 @@ class App extends React.Component {
5818
6023
  }
5819
6024
  };
5820
6025
  maybeSuggestBindingAtCursor = (pointerCoords) => {
5821
- const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());
6026
+ const hoveredBindableElement = getHoveredElementForBinding(pointerCoords, this);
5822
6027
  this.setState({
5823
6028
  suggestedBindings: hoveredBindableElement != null ? [hoveredBindableElement] : [],
5824
6029
  });
@@ -5833,7 +6038,7 @@ class App extends React.Component {
5833
6038
  return;
5834
6039
  }
5835
6040
  const suggestedBindings = pointerCoords.reduce((acc, coords) => {
5836
- const hoveredBindableElement = getHoveredElementForBinding(coords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());
6041
+ const hoveredBindableElement = getHoveredElementForBinding(coords, this);
5837
6042
  if (hoveredBindableElement != null &&
5838
6043
  !isLinearElementSimpleAndAlreadyBound(linearElement, oppositeBindingBoundElement?.id, hoveredBindableElement)) {
5839
6044
  acc.push(hoveredBindableElement);
@@ -5846,7 +6051,7 @@ class App extends React.Component {
5846
6051
  if (selectedElements.length > 50) {
5847
6052
  return;
5848
6053
  }
5849
- const suggestedBindings = getEligibleElementsForBinding(selectedElements, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap());
6054
+ const suggestedBindings = getEligibleElementsForBinding(selectedElements, this);
5850
6055
  this.setState({ suggestedBindings });
5851
6056
  }
5852
6057
  clearSelection(hitElement) {
@@ -5908,7 +6113,7 @@ class App extends React.Component {
5908
6113
  isLoading: false,
5909
6114
  },
5910
6115
  replaceFiles: true,
5911
- commitToHistory: true,
6116
+ storeAction: StoreAction.CAPTURE,
5912
6117
  });
5913
6118
  return;
5914
6119
  }
@@ -5976,9 +6181,10 @@ class App extends React.Component {
5976
6181
  loadFileToCanvas = async (file, fileHandle) => {
5977
6182
  file = await normalizeFile(file);
5978
6183
  try {
6184
+ const elements = this.scene.getElementsIncludingDeleted();
5979
6185
  let ret;
5980
6186
  try {
5981
- ret = await loadSceneOrLibraryFromBlob(file, this.state, this.scene.getElementsIncludingDeleted(), fileHandle);
6187
+ ret = await loadSceneOrLibraryFromBlob(file, this.state, elements, fileHandle);
5982
6188
  }
5983
6189
  catch (error) {
5984
6190
  const imageSceneDataError = error instanceof ImageSceneDataError;
@@ -6003,6 +6209,10 @@ class App extends React.Component {
6003
6209
  return;
6004
6210
  }
6005
6211
  if (ret.type === MIME_TYPES.excalidraw) {
6212
+ // restore the fractional indices by mutating elements
6213
+ syncInvalidIndices(elements.concat(ret.data.elements));
6214
+ // update the store snapshot for old elements, otherwise we would end up with duplicated fractional indices on undo
6215
+ this.store.updateSnapshot(arrayToMap(elements), this.state);
6006
6216
  this.setState({ isLoading: true });
6007
6217
  this.syncActionResult({
6008
6218
  ...ret.data,
@@ -6011,7 +6221,7 @@ class App extends React.Component {
6011
6221
  isLoading: false,
6012
6222
  },
6013
6223
  replaceFiles: true,
6014
- commitToHistory: true,
6224
+ storeAction: StoreAction.CAPTURE,
6015
6225
  });
6016
6226
  }
6017
6227
  else if (ret.type === MIME_TYPES.excalidrawlib) {
@@ -6167,7 +6377,7 @@ class App extends React.Component {
6167
6377
  snapLines,
6168
6378
  });
6169
6379
  }
6170
- if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.length === 1 && isImageElement(selectedElements[0])
6380
+ if (transformElements(pointerDownState.originalElements, transformHandleType, selectedElements, this.scene.getElementsMapIncludingDeleted(), shouldRotateWithDiscreteAngle(event), shouldResizeFromCenter(event), selectedElements.some((element) => isImageElement(element))
6171
6381
  ? !shouldMaintainAspectRatio(event)
6172
6382
  : shouldMaintainAspectRatio(event), resizeX, resizeY, pointerDownState.resize.center.x, pointerDownState.resize.center.y)) {
6173
6383
  this.maybeSuggestBindingForAll(selectedElements);
@@ -6401,7 +6611,7 @@ export const createTestHook = () => {
6401
6611
  return this.app?.scene.getElementsIncludingDeleted();
6402
6612
  },
6403
6613
  set(elements) {
6404
- return this.app?.scene.replaceAllElements(elements);
6614
+ return this.app?.scene.replaceAllElements(syncInvalidIndices(elements));
6405
6615
  },
6406
6616
  },
6407
6617
  });