fabric 5.3.0 → 6.0.0-beta1

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 (533) hide show
  1. package/.babelrc +11 -0
  2. package/.babelrcAlt +19 -0
  3. package/.browserslistrc +5 -0
  4. package/.eslintrc.js +43 -0
  5. package/.eslintrc.json +38 -46
  6. package/.eslintrc_tests +12 -0
  7. package/.gitattributes +2 -0
  8. package/.prettierignore +16 -0
  9. package/.prettierrc +4 -0
  10. package/CHANGELOG.md +491 -189
  11. package/CONTRIBUTING.md +226 -58
  12. package/README.md +188 -239
  13. package/bower.json +1 -3
  14. package/dist/fabric.d.ts +1021 -0
  15. package/dist/index.cjs +28027 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.min.js +1 -0
  19. package/dist/index.mjs +27964 -0
  20. package/dist/index.mjs.map +1 -0
  21. package/dist/index.node.cjs +28092 -0
  22. package/dist/index.node.cjs.map +1 -0
  23. package/dist/index.node.d.ts +15 -0
  24. package/dist/index.node.mjs +28035 -0
  25. package/dist/index.node.mjs.map +1 -0
  26. package/dist/src/Collection.d.ts +126 -0
  27. package/dist/src/CommonMethods.d.ts +32 -0
  28. package/dist/src/EventTypeDefs.d.ts +226 -0
  29. package/dist/src/Intersection.d.ts +100 -0
  30. package/dist/src/Observable.d.ts +54 -0
  31. package/dist/src/Pattern.d.ts +104 -0
  32. package/dist/src/Point.d.ts +232 -0
  33. package/dist/src/Shadow.d.ts +87 -0
  34. package/dist/src/brushes/BaseBrush.d.ts +105 -0
  35. package/dist/src/brushes/CircleBrush.d.ts +49 -0
  36. package/dist/src/brushes/PatternBrush.d.ts +23 -0
  37. package/dist/src/brushes/PencilBrush.d.ts +92 -0
  38. package/dist/src/brushes/SprayBrush.d.ts +79 -0
  39. package/dist/src/cache.d.ts +46 -0
  40. package/dist/src/canvas/Canvas.d.ts +567 -0
  41. package/dist/src/canvas/SelectableCanvas.d.ts +723 -0
  42. package/dist/src/canvas/StaticCanvas.d.ts +751 -0
  43. package/dist/src/canvas/TextEditingManager.d.ts +17 -0
  44. package/dist/src/canvas/canvas_gestures.mixin.d.ts +2 -0
  45. package/dist/src/color/Color.d.ts +174 -0
  46. package/dist/src/color/color_map.d.ts +155 -0
  47. package/dist/src/color/constants.d.ts +22 -0
  48. package/dist/src/color/util.d.ts +12 -0
  49. package/dist/src/config.d.ts +115 -0
  50. package/dist/src/constants.d.ts +14 -0
  51. package/dist/src/controls/Control.d.ts +228 -0
  52. package/dist/src/controls/changeWidth.d.ts +13 -0
  53. package/dist/src/controls/controls.render.d.ts +29 -0
  54. package/dist/src/controls/default_controls.d.ts +50 -0
  55. package/dist/src/controls/drag.d.ts +12 -0
  56. package/dist/src/controls/polyControl.d.ts +5 -0
  57. package/dist/src/controls/rotate.d.ts +12 -0
  58. package/dist/src/controls/scale.d.ts +47 -0
  59. package/dist/src/controls/scaleSkew.d.ts +39 -0
  60. package/dist/src/controls/skew.d.ts +33 -0
  61. package/dist/src/controls/util.d.ts +41 -0
  62. package/dist/src/controls/wrapWithFireEvent.d.ts +8 -0
  63. package/dist/src/controls/wrapWithFixedAnchor.d.ts +9 -0
  64. package/dist/src/env/browser.d.ts +3 -0
  65. package/dist/src/env/index.d.ts +7 -0
  66. package/dist/src/env/node.d.ts +3 -0
  67. package/dist/src/env/types.d.ts +15 -0
  68. package/dist/src/filters/BaseFilter.d.ts +156 -0
  69. package/dist/src/filters/BlendColor.d.ts +80 -0
  70. package/dist/src/filters/BlendImage.d.ts +90 -0
  71. package/dist/src/filters/Blur.d.ts +50 -0
  72. package/dist/src/filters/Boilerplate.d.ts +46 -0
  73. package/dist/src/filters/Brightness.d.ts +46 -0
  74. package/dist/src/filters/Canvas2dFilterBackend.d.ts +27 -0
  75. package/dist/src/filters/ColorMatrix.d.ts +62 -0
  76. package/dist/src/filters/ColorMatrixFilters.d.ts +1169 -0
  77. package/dist/src/filters/Composed.d.ts +47 -0
  78. package/dist/src/filters/Contrast.d.ts +44 -0
  79. package/dist/src/filters/Convolute.d.ts +82 -0
  80. package/dist/src/filters/FilterBackend.d.ts +14 -0
  81. package/dist/src/filters/Gamma.d.ts +53 -0
  82. package/dist/src/filters/Grayscale.d.ts +45 -0
  83. package/dist/src/filters/HueRotation.d.ts +24 -0
  84. package/dist/src/filters/Invert.d.ts +54 -0
  85. package/dist/src/filters/Noise.d.ts +53 -0
  86. package/dist/src/filters/Pixelate.d.ts +43 -0
  87. package/dist/src/filters/RemoveColor.d.ts +62 -0
  88. package/dist/src/filters/Resize.d.ts +134 -0
  89. package/dist/src/filters/Saturation.d.ts +47 -0
  90. package/dist/src/filters/Vibrance.d.ts +47 -0
  91. package/dist/src/filters/WebGLFilterBackend.d.ts +126 -0
  92. package/dist/src/filters/WebGLProbe.d.ts +28 -0
  93. package/dist/src/filters/typedefs.d.ts +49 -0
  94. package/dist/src/gradient/Gradient.d.ts +149 -0
  95. package/dist/src/gradient/constants.d.ts +15 -0
  96. package/dist/src/gradient/parser/index.d.ts +4 -0
  97. package/dist/src/gradient/parser/misc.d.ts +4 -0
  98. package/dist/src/gradient/parser/parseColorStops.d.ts +6 -0
  99. package/dist/src/gradient/parser/parseCoords.d.ts +17 -0
  100. package/dist/src/gradient/typedefs.d.ts +93 -0
  101. package/dist/src/mixins/eraser_brush.mixin.d.ts +2 -0
  102. package/dist/src/mixins/stateful.mixin.d.ts +18 -0
  103. package/dist/src/parkinglot/canvas_animation.mixin.d.ts +2 -0
  104. package/dist/src/parkinglot/straighten.d.ts +2 -0
  105. package/dist/src/parser/applyViewboxTransform.d.ts +5 -0
  106. package/dist/src/parser/attributes.d.ts +6 -0
  107. package/dist/src/parser/constants.d.ts +54 -0
  108. package/dist/src/parser/doesSomeParentMatch.d.ts +2 -0
  109. package/dist/src/parser/elementById.d.ts +6 -0
  110. package/dist/src/parser/elementMatchesRule.d.ts +5 -0
  111. package/dist/src/parser/elements_parser.d.ts +3 -0
  112. package/dist/src/parser/getCSSRules.d.ts +7 -0
  113. package/dist/src/parser/getGlobalStylesForElement.d.ts +5 -0
  114. package/dist/src/parser/getGradientDefs.d.ts +7 -0
  115. package/dist/src/parser/getMultipleNodes.d.ts +2 -0
  116. package/dist/src/parser/getSvgRegex.d.ts +2 -0
  117. package/dist/src/parser/hasAncestorWithNodeName.d.ts +2 -0
  118. package/dist/src/parser/loadSVGFromString.d.ts +12 -0
  119. package/dist/src/parser/loadSVGFromURL.d.ts +13 -0
  120. package/dist/src/parser/normalizeAttr.d.ts +2 -0
  121. package/dist/src/parser/normalizeValue.d.ts +2 -0
  122. package/dist/src/parser/parseAttributes.d.ts +9 -0
  123. package/dist/src/parser/parseElements.d.ts +11 -0
  124. package/dist/src/parser/parseFontDeclaration.d.ts +10 -0
  125. package/dist/src/parser/parsePointsAttribute.d.ts +12 -0
  126. package/dist/src/parser/parseSVGDocument.d.ts +15 -0
  127. package/dist/src/parser/parseStyleAttribute.d.ts +9 -0
  128. package/dist/src/parser/parseStyleObject.d.ts +2 -0
  129. package/dist/src/parser/parseStyleString.d.ts +2 -0
  130. package/dist/src/parser/parseTransformAttribute.d.ts +10 -0
  131. package/dist/src/parser/parseUseDirectives.d.ts +2 -0
  132. package/dist/src/parser/percent.d.ts +9 -0
  133. package/dist/src/parser/recursivelyParseGradientsXlink.d.ts +2 -0
  134. package/dist/src/parser/rotateMatrix.d.ts +2 -0
  135. package/dist/src/parser/scaleMatrix.d.ts +2 -0
  136. package/dist/src/parser/selectorMatches.d.ts +2 -0
  137. package/dist/src/parser/setStrokeFillOpacity.d.ts +6 -0
  138. package/dist/src/parser/skewMatrix.d.ts +2 -0
  139. package/dist/src/parser/translateMatrix.d.ts +2 -0
  140. package/dist/src/shapes/ActiveSelection.d.ts +66 -0
  141. package/dist/src/shapes/Circle.d.ts +80 -0
  142. package/dist/src/shapes/Ellipse.d.ts +74 -0
  143. package/dist/src/shapes/Group.d.ts +381 -0
  144. package/dist/src/shapes/IText/DraggableTextDelegate.d.ts +78 -0
  145. package/dist/src/shapes/IText/IText.d.ts +322 -0
  146. package/dist/src/shapes/IText/ITextBehavior.d.ts +285 -0
  147. package/dist/src/shapes/IText/ITextClickBehavior.d.ts +81 -0
  148. package/dist/src/shapes/IText/ITextKeyBehavior.d.ts +193 -0
  149. package/dist/src/shapes/IText/constants.d.ts +13 -0
  150. package/dist/src/shapes/Image.d.ts +283 -0
  151. package/dist/src/shapes/Line.d.ts +117 -0
  152. package/dist/src/shapes/Object/AnimatableObject.d.ts +33 -0
  153. package/dist/src/shapes/Object/FabricObject.d.ts +9 -0
  154. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts +74 -0
  155. package/dist/src/shapes/Object/InteractiveObject.d.ts +282 -0
  156. package/dist/src/shapes/Object/Object.d.ts +906 -0
  157. package/dist/src/shapes/Object/ObjectGeometry.d.ts +343 -0
  158. package/dist/src/shapes/Object/ObjectOrigin.d.ts +178 -0
  159. package/dist/src/shapes/Object/StackedObject.d.ts +62 -0
  160. package/dist/src/shapes/Object/defaultValues.d.ts +77 -0
  161. package/dist/src/shapes/Path.d.ts +123 -0
  162. package/dist/src/shapes/Polygon.d.ts +7 -0
  163. package/dist/src/shapes/Polyline.d.ts +130 -0
  164. package/dist/src/shapes/Rect.d.ts +62 -0
  165. package/dist/src/shapes/Text/StyledText.d.ts +118 -0
  166. package/dist/src/shapes/Text/Text.d.ts +656 -0
  167. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts +32 -0
  168. package/dist/src/shapes/Textbox.d.ts +170 -0
  169. package/dist/src/shapes/Triangle.d.ts +17 -0
  170. package/dist/src/typedefs.d.ts +93 -0
  171. package/dist/src/util/animation/AnimationBase.d.ts +54 -0
  172. package/dist/src/util/animation/AnimationFrameProvider.d.ts +8 -0
  173. package/dist/src/util/animation/AnimationRegistry.d.ts +29 -0
  174. package/dist/src/util/animation/ArrayAnimation.d.ts +10 -0
  175. package/dist/src/util/animation/ColorAnimation.d.ts +11 -0
  176. package/dist/src/util/animation/ValueAnimation.d.ts +10 -0
  177. package/dist/src/util/animation/animate.d.ts +37 -0
  178. package/dist/src/util/animation/easing.d.ts +130 -0
  179. package/dist/src/util/animation/types.d.ts +87 -0
  180. package/dist/src/util/applyMixins.d.ts +8 -0
  181. package/dist/src/util/class_registry.d.ts +14 -0
  182. package/dist/src/util/dom_event.d.ts +5 -0
  183. package/dist/src/util/dom_misc.d.ts +40 -0
  184. package/dist/src/util/dom_request.d.ts +14 -0
  185. package/dist/src/util/dom_style.d.ts +7 -0
  186. package/dist/src/util/fireEvent.d.ts +3 -0
  187. package/dist/src/util/internals/cloneDeep.d.ts +2 -0
  188. package/dist/src/util/internals/getRandomInt.d.ts +8 -0
  189. package/dist/src/util/internals/ifNaN.d.ts +8 -0
  190. package/dist/src/util/internals/index.d.ts +4 -0
  191. package/dist/src/util/internals/removeFromArray.d.ts +9 -0
  192. package/dist/src/util/internals/uid.d.ts +2 -0
  193. package/dist/src/util/lang_class.d.ts +12 -0
  194. package/dist/src/util/lang_string.d.ts +22 -0
  195. package/dist/src/util/misc/boundingBoxFromPoints.d.ts +9 -0
  196. package/dist/src/util/misc/capValue.d.ts +2 -0
  197. package/dist/src/util/misc/cos.d.ts +10 -0
  198. package/dist/src/util/misc/dom.d.ts +28 -0
  199. package/dist/src/util/misc/findScaleTo.d.ts +29 -0
  200. package/dist/src/util/misc/groupSVGElements.d.ts +9 -0
  201. package/dist/src/util/misc/isTransparent.d.ts +11 -0
  202. package/dist/src/util/misc/matrix.d.ts +92 -0
  203. package/dist/src/util/misc/mergeClipPaths.d.ts +23 -0
  204. package/dist/src/util/misc/objectEnlive.d.ts +56 -0
  205. package/dist/src/util/misc/objectTransforms.d.ts +68 -0
  206. package/dist/src/util/misc/pick.d.ts +8 -0
  207. package/dist/src/util/misc/planeChange.d.ts +84 -0
  208. package/dist/src/util/misc/projectStroke/StrokeLineCapProjections.d.ts +51 -0
  209. package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.d.ts +81 -0
  210. package/dist/src/util/misc/projectStroke/StrokeProjectionsBase.d.ts +25 -0
  211. package/dist/src/util/misc/projectStroke/index.d.ts +11 -0
  212. package/dist/src/util/misc/projectStroke/types.d.ts +23 -0
  213. package/dist/src/util/misc/radiansDegreesConversion.d.ts +14 -0
  214. package/dist/src/util/misc/resolveOrigin.d.ts +9 -0
  215. package/dist/src/util/misc/rotatePoint.d.ts +12 -0
  216. package/dist/src/util/misc/sin.d.ts +10 -0
  217. package/dist/src/util/misc/svgParsing.d.ts +53 -0
  218. package/dist/src/util/misc/textStyles.d.ts +32 -0
  219. package/dist/src/util/misc/toFixed.d.ts +8 -0
  220. package/dist/src/util/misc/vectors.d.ts +57 -0
  221. package/dist/src/util/path.d.ts +108 -0
  222. package/dist/src/util/transform_matrix_removal.d.ts +14 -0
  223. package/dist/src/util/types.d.ts +19 -0
  224. package/fabric.ts +427 -0
  225. package/index.node.ts +43 -0
  226. package/index.ts +1 -0
  227. package/package.json +90 -39
  228. package/publish.js +0 -26
  229. package/rollup.config.mjs +79 -0
  230. package/rollup.test.config.js +24 -0
  231. package/scripts/build.mjs +50 -0
  232. package/scripts/buildLock.mjs +115 -0
  233. package/scripts/buildReporter.mjs +15 -0
  234. package/scripts/buildStats.mjs +139 -0
  235. package/scripts/dirname.mjs +14 -0
  236. package/scripts/index.mjs +679 -0
  237. package/scripts/transform_files.mjs +504 -0
  238. package/src/Collection.ts +311 -0
  239. package/src/CommonMethods.ts +63 -0
  240. package/src/EventTypeDefs.ts +294 -0
  241. package/src/Intersection.ts +273 -0
  242. package/src/Observable.ts +175 -0
  243. package/src/Pattern.ts +211 -0
  244. package/src/Point.ts +388 -0
  245. package/src/Shadow.ts +215 -0
  246. package/src/brushes/{base_brush.class.js → BaseBrush.ts} +65 -42
  247. package/src/brushes/CircleBrush.ts +145 -0
  248. package/src/brushes/PatternBrush.ts +70 -0
  249. package/src/brushes/PencilBrush.ts +300 -0
  250. package/src/brushes/SprayBrush.ts +219 -0
  251. package/src/cache.ts +89 -0
  252. package/src/canvas/Canvas.ts +1672 -0
  253. package/src/canvas/SelectableCanvas.ts +1636 -0
  254. package/src/canvas/StaticCanvas.ts +1709 -0
  255. package/src/canvas/TextEditingManager.ts +48 -0
  256. package/src/canvas/canvas_gestures.mixin.ts +207 -0
  257. package/src/color/Color.ts +404 -0
  258. package/src/color/color_map.ts +154 -0
  259. package/src/color/constants.ts +26 -0
  260. package/src/color/util.ts +32 -0
  261. package/src/config.ts +159 -0
  262. package/src/constants.ts +19 -0
  263. package/src/controls/Control.ts +377 -0
  264. package/src/controls/changeWidth.ts +52 -0
  265. package/src/controls/controls.render.ts +138 -0
  266. package/src/controls/default_controls.ts +132 -0
  267. package/src/controls/drag.ts +31 -0
  268. package/src/controls/polyControl.ts +135 -0
  269. package/src/controls/rotate.ts +87 -0
  270. package/src/controls/scale.ts +277 -0
  271. package/src/controls/scaleSkew.ts +92 -0
  272. package/src/controls/skew.ts +242 -0
  273. package/src/controls/util.ts +154 -0
  274. package/src/controls/wrapWithFireEvent.ts +25 -0
  275. package/src/controls/wrapWithFixedAnchor.ts +20 -0
  276. package/src/env/browser.ts +28 -0
  277. package/src/env/index.ts +19 -0
  278. package/src/env/node.ts +52 -0
  279. package/src/env/types.ts +15 -0
  280. package/src/filters/{base_filter.class.js → BaseFilter.ts} +201 -149
  281. package/src/filters/BlendColor.ts +258 -0
  282. package/src/filters/BlendImage.ts +254 -0
  283. package/src/filters/Blur.ts +202 -0
  284. package/src/filters/Boilerplate.ts +91 -0
  285. package/src/filters/Brightness.ts +93 -0
  286. package/src/filters/Canvas2dFilterBackend.ts +65 -0
  287. package/src/filters/ColorMatrix.ts +156 -0
  288. package/src/filters/ColorMatrixFilters.ts +106 -0
  289. package/src/filters/Composed.ts +85 -0
  290. package/src/filters/Contrast.ts +94 -0
  291. package/src/filters/Convolute.ts +341 -0
  292. package/src/filters/FilterBackend.ts +32 -0
  293. package/src/filters/Gamma.ts +127 -0
  294. package/src/filters/Grayscale.ts +137 -0
  295. package/src/filters/HueRotation.ts +66 -0
  296. package/src/filters/Invert.ts +117 -0
  297. package/src/filters/Noise.ts +109 -0
  298. package/src/filters/Pixelate.ts +114 -0
  299. package/src/filters/RemoveColor.ts +148 -0
  300. package/src/filters/Resize.ts +540 -0
  301. package/src/filters/Saturation.ts +100 -0
  302. package/src/filters/Vibrance.ts +103 -0
  303. package/src/filters/WebGLFilterBackend.ts +430 -0
  304. package/src/filters/WebGLProbe.ts +62 -0
  305. package/src/filters/typedefs.ts +65 -0
  306. package/src/gradient/Gradient.ts +401 -0
  307. package/src/gradient/constants.ts +12 -0
  308. package/src/gradient/parser/index.ts +3 -0
  309. package/src/gradient/parser/misc.ts +13 -0
  310. package/src/gradient/parser/parseColorStops.ts +55 -0
  311. package/src/gradient/parser/parseCoords.ts +73 -0
  312. package/src/gradient/typedefs.ts +104 -0
  313. package/src/mixins/{eraser_brush.mixin.js → eraser_brush.mixin.ts} +350 -239
  314. package/src/mixins/stateful.mixin.ts +104 -0
  315. package/src/parkinglot/canvas_animation.mixin.ts +121 -0
  316. package/src/parkinglot/straighten.ts +58 -0
  317. package/src/parser/applyViewboxTransform.ts +162 -0
  318. package/src/parser/attributes.ts +25 -0
  319. package/src/parser/constants.ts +118 -0
  320. package/src/parser/doesSomeParentMatch.ts +19 -0
  321. package/src/parser/elementById.ts +23 -0
  322. package/src/parser/elementMatchesRule.ts +19 -0
  323. package/src/parser/elements_parser.ts +191 -0
  324. package/src/parser/getCSSRules.ts +62 -0
  325. package/src/parser/getGlobalStylesForElement.ts +19 -0
  326. package/src/parser/getGradientDefs.ts +32 -0
  327. package/src/parser/getMultipleNodes.ts +15 -0
  328. package/src/parser/getSvgRegex.ts +5 -0
  329. package/src/parser/hasAncestorWithNodeName.ts +14 -0
  330. package/src/parser/loadSVGFromString.ts +26 -0
  331. package/src/parser/loadSVGFromURL.ts +40 -0
  332. package/src/parser/normalizeAttr.ts +10 -0
  333. package/src/parser/normalizeValue.ts +63 -0
  334. package/src/parser/parseAttributes.ts +90 -0
  335. package/src/parser/parseElements.ts +28 -0
  336. package/src/parser/parseFontDeclaration.ts +44 -0
  337. package/src/parser/parsePointsAttribute.ts +36 -0
  338. package/src/parser/parseSVGDocument.ts +106 -0
  339. package/src/parser/parseStyleAttribute.ts +27 -0
  340. package/src/parser/parseStyleObject.ts +15 -0
  341. package/src/parser/parseStyleString.ts +16 -0
  342. package/src/parser/parseTransformAttribute.ts +155 -0
  343. package/src/parser/parseUseDirectives.ts +79 -0
  344. package/src/parser/percent.ts +27 -0
  345. package/src/parser/recursivelyParseGradientsXlink.ts +42 -0
  346. package/src/parser/rotateMatrix.ts +21 -0
  347. package/src/parser/scaleMatrix.ts +9 -0
  348. package/src/parser/selectorMatches.ts +25 -0
  349. package/src/parser/setStrokeFillOpacity.ts +40 -0
  350. package/src/parser/skewMatrix.ts +6 -0
  351. package/src/parser/translateMatrix.ts +8 -0
  352. package/src/shapes/ActiveSelection.ts +157 -0
  353. package/src/shapes/Circle.ts +205 -0
  354. package/src/shapes/Ellipse.ts +154 -0
  355. package/src/shapes/Group.ts +1053 -0
  356. package/src/shapes/IText/DraggableTextDelegate.ts +394 -0
  357. package/src/shapes/IText/IText.ts +666 -0
  358. package/src/shapes/IText/ITextBehavior.ts +1055 -0
  359. package/src/shapes/IText/ITextClickBehavior.ts +321 -0
  360. package/src/shapes/IText/ITextKeyBehavior.ts +683 -0
  361. package/src/shapes/IText/constants.ts +47 -0
  362. package/src/shapes/Image.ts +789 -0
  363. package/src/shapes/Line.ts +329 -0
  364. package/src/shapes/Object/AnimatableObject.ts +106 -0
  365. package/src/shapes/Object/FabricObject.ts +19 -0
  366. package/src/shapes/Object/FabricObjectSVGExportMixin.ts +277 -0
  367. package/src/shapes/Object/InteractiveObject.ts +645 -0
  368. package/src/shapes/Object/Object.ts +1896 -0
  369. package/src/shapes/Object/ObjectGeometry.ts +830 -0
  370. package/src/shapes/Object/ObjectOrigin.ts +354 -0
  371. package/src/shapes/Object/StackedObject.ts +191 -0
  372. package/src/shapes/Object/defaultValues.ts +112 -0
  373. package/src/shapes/Path.ts +395 -0
  374. package/src/shapes/Polygon.ts +19 -0
  375. package/src/shapes/Polyline.ts +333 -0
  376. package/src/shapes/Rect.ts +199 -0
  377. package/src/shapes/Text/StyledText.ts +319 -0
  378. package/src/shapes/Text/Text.ts +1948 -0
  379. package/src/shapes/Text/TextSVGExportMixin.ts +288 -0
  380. package/src/shapes/Textbox.ts +471 -0
  381. package/src/shapes/Triangle.ts +45 -0
  382. package/src/typedefs.ts +119 -0
  383. package/src/util/animation/AnimationBase.ts +166 -0
  384. package/src/util/animation/AnimationFrameProvider.ts +28 -0
  385. package/src/util/animation/AnimationRegistry.ts +58 -0
  386. package/src/util/animation/ArrayAnimation.ts +27 -0
  387. package/src/util/animation/ColorAnimation.ts +74 -0
  388. package/src/util/animation/ValueAnimation.ts +29 -0
  389. package/src/util/animation/animate.ts +74 -0
  390. package/src/util/animation/easing.ts +327 -0
  391. package/src/util/animation/types.ts +136 -0
  392. package/src/util/applyMixins.ts +22 -0
  393. package/src/util/class_registry.ts +54 -0
  394. package/src/util/dom_event.ts +28 -0
  395. package/src/util/dom_misc.ts +138 -0
  396. package/src/util/dom_request.ts +64 -0
  397. package/src/util/dom_style.ts +20 -0
  398. package/src/util/fireEvent.ts +15 -0
  399. package/src/util/internals/cloneDeep.ts +2 -0
  400. package/src/util/internals/getRandomInt.ts +8 -0
  401. package/src/util/internals/ifNaN.ts +9 -0
  402. package/src/util/internals/index.ts +3 -0
  403. package/src/util/internals/removeFromArray.ts +14 -0
  404. package/src/util/internals/uid.ts +3 -0
  405. package/src/util/lang_class.ts +90 -0
  406. package/src/util/lang_string.ts +79 -0
  407. package/src/util/misc/boundingBoxFromPoints.ts +37 -0
  408. package/src/util/misc/capValue.ts +2 -0
  409. package/src/util/misc/cos.ts +24 -0
  410. package/src/util/misc/dom.ts +50 -0
  411. package/src/util/misc/findScaleTo.ts +44 -0
  412. package/src/util/misc/groupSVGElements.ts +15 -0
  413. package/src/util/misc/isTransparent.ts +51 -0
  414. package/src/util/misc/matrix.ts +207 -0
  415. package/src/util/misc/mergeClipPaths.ts +40 -0
  416. package/src/util/misc/objectEnlive.ts +189 -0
  417. package/src/util/misc/objectTransforms.ts +129 -0
  418. package/src/util/misc/pick.ts +17 -0
  419. package/src/util/misc/planeChange.ts +136 -0
  420. package/src/util/misc/projectStroke/StrokeLineCapProjections.ts +112 -0
  421. package/src/util/misc/projectStroke/StrokeLineJoinProjections.ts +231 -0
  422. package/src/util/misc/projectStroke/StrokeProjectionsBase.ts +75 -0
  423. package/src/util/misc/projectStroke/index.ts +53 -0
  424. package/src/util/misc/projectStroke/types.ts +24 -0
  425. package/src/util/misc/radiansDegreesConversion.ts +18 -0
  426. package/src/util/misc/resolveOrigin.ts +22 -0
  427. package/src/util/misc/rotatePoint.ts +15 -0
  428. package/src/util/misc/sin.ts +26 -0
  429. package/src/util/misc/svgParsing.ts +181 -0
  430. package/src/util/misc/textStyles.ts +133 -0
  431. package/src/util/misc/toFixed.ts +8 -0
  432. package/src/util/misc/vectors.ts +82 -0
  433. package/src/util/path.ts +941 -0
  434. package/src/util/transform_matrix_removal.ts +60 -0
  435. package/src/util/types.ts +78 -0
  436. package/tsconfig.json +106 -0
  437. package/HEADER.js +0 -203
  438. package/build.js +0 -287
  439. package/dist/fabric.js +0 -31187
  440. package/dist/fabric.min.js +0 -1
  441. package/old-travis-reference.yml +0 -97
  442. package/src/brushes/circle_brush.class.js +0 -144
  443. package/src/brushes/pattern_brush.class.js +0 -61
  444. package/src/brushes/pencil_brush.class.js +0 -310
  445. package/src/brushes/spray_brush.class.js +0 -219
  446. package/src/canvas.class.js +0 -1312
  447. package/src/color.class.js +0 -636
  448. package/src/control.class.js +0 -339
  449. package/src/controls.actions.js +0 -740
  450. package/src/controls.render.js +0 -99
  451. package/src/elements_parser.js +0 -152
  452. package/src/filters/2d_backend.class.js +0 -65
  453. package/src/filters/blendcolor_filter.class.js +0 -251
  454. package/src/filters/blendimage_filter.class.js +0 -247
  455. package/src/filters/blur_filter.class.js +0 -217
  456. package/src/filters/brightness_filter.class.js +0 -113
  457. package/src/filters/colormatrix_filter.class.js +0 -159
  458. package/src/filters/composed_filter.class.js +0 -72
  459. package/src/filters/contrast_filter.class.js +0 -113
  460. package/src/filters/convolute_filter.class.js +0 -352
  461. package/src/filters/filter_boilerplate.js +0 -111
  462. package/src/filters/filter_generator.js +0 -85
  463. package/src/filters/gamma_filter.class.js +0 -136
  464. package/src/filters/grayscale_filter.class.js +0 -154
  465. package/src/filters/hue_rotation.class.js +0 -107
  466. package/src/filters/invert_filter.class.js +0 -111
  467. package/src/filters/noise_filter.class.js +0 -134
  468. package/src/filters/pixelate_filter.class.js +0 -137
  469. package/src/filters/removecolor_filter.class.js +0 -173
  470. package/src/filters/resize_filter.class.js +0 -490
  471. package/src/filters/saturate_filter.class.js +0 -119
  472. package/src/filters/vibrance_filter.class.js +0 -122
  473. package/src/filters/webgl_backend.class.js +0 -396
  474. package/src/globalFabric.js +0 -4
  475. package/src/gradient.class.js +0 -490
  476. package/src/intersection.class.js +0 -172
  477. package/src/log.js +0 -11
  478. package/src/mixins/animation.mixin.js +0 -231
  479. package/src/mixins/canvas_dataurl_exporter.mixin.js +0 -97
  480. package/src/mixins/canvas_events.mixin.js +0 -974
  481. package/src/mixins/canvas_gestures.mixin.js +0 -149
  482. package/src/mixins/canvas_grouping.mixin.js +0 -177
  483. package/src/mixins/canvas_serialization.mixin.js +0 -228
  484. package/src/mixins/collection.mixin.js +0 -170
  485. package/src/mixins/default_controls.js +0 -114
  486. package/src/mixins/itext.svg_export.js +0 -241
  487. package/src/mixins/itext_behavior.mixin.js +0 -940
  488. package/src/mixins/itext_click_behavior.mixin.js +0 -278
  489. package/src/mixins/itext_key_behavior.mixin.js +0 -694
  490. package/src/mixins/object.svg_export.js +0 -258
  491. package/src/mixins/object_geometry.mixin.js +0 -683
  492. package/src/mixins/object_interactivity.mixin.js +0 -314
  493. package/src/mixins/object_origin.mixin.js +0 -255
  494. package/src/mixins/object_stacking.mixin.js +0 -80
  495. package/src/mixins/object_straightening.mixin.js +0 -80
  496. package/src/mixins/observable.mixin.js +0 -141
  497. package/src/mixins/shared_methods.mixin.js +0 -94
  498. package/src/mixins/stateful.mixin.js +0 -107
  499. package/src/mixins/text_style.mixin.js +0 -324
  500. package/src/parser.js +0 -1090
  501. package/src/pattern.class.js +0 -189
  502. package/src/point.class.js +0 -337
  503. package/src/shadow.class.js +0 -195
  504. package/src/shapes/active_selection.class.js +0 -155
  505. package/src/shapes/circle.class.js +0 -210
  506. package/src/shapes/ellipse.class.js +0 -181
  507. package/src/shapes/group.class.js +0 -593
  508. package/src/shapes/image.class.js +0 -764
  509. package/src/shapes/itext.class.js +0 -526
  510. package/src/shapes/line.class.js +0 -324
  511. package/src/shapes/object.class.js +0 -2008
  512. package/src/shapes/path.class.js +0 -384
  513. package/src/shapes/polygon.class.js +0 -81
  514. package/src/shapes/polyline.class.js +0 -268
  515. package/src/shapes/rect.class.js +0 -187
  516. package/src/shapes/text.class.js +0 -1696
  517. package/src/shapes/textbox.class.js +0 -461
  518. package/src/shapes/triangle.class.js +0 -93
  519. package/src/static_canvas.class.js +0 -1881
  520. package/src/util/anim_ease.js +0 -398
  521. package/src/util/animate.js +0 -254
  522. package/src/util/animate_color.js +0 -74
  523. package/src/util/dom_event.js +0 -50
  524. package/src/util/dom_misc.js +0 -300
  525. package/src/util/dom_request.js +0 -54
  526. package/src/util/dom_style.js +0 -70
  527. package/src/util/lang_array.js +0 -94
  528. package/src/util/lang_class.js +0 -115
  529. package/src/util/lang_object.js +0 -75
  530. package/src/util/lang_string.js +0 -110
  531. package/src/util/misc.js +0 -1330
  532. package/src/util/named_accessors.mixin.js +0 -428
  533. package/src/util/path.js +0 -829
@@ -0,0 +1,1672 @@
1
+ import { LEFT_CLICK, MIDDLE_CLICK, RIGHT_CLICK } from '../constants';
2
+ import { getEnv } from '../env';
3
+ import {
4
+ CanvasEvents,
5
+ DragEventData,
6
+ ObjectEvents,
7
+ TPointerEvent,
8
+ TPointerEventInfo,
9
+ TPointerEventNames,
10
+ Transform,
11
+ } from '../EventTypeDefs';
12
+ import { Point } from '../Point';
13
+ import { ActiveSelection } from '../shapes/ActiveSelection';
14
+ import { Group } from '../shapes/Group';
15
+ import type { FabricObject } from '../shapes/Object/FabricObject';
16
+ import { AssertKeys } from '../typedefs';
17
+ import { isTouchEvent, stopEvent } from '../util/dom_event';
18
+ import { createCanvasElement } from '../util/misc/dom';
19
+ import { sendPointToPlane } from '../util/misc/planeChange';
20
+ import {
21
+ isActiveSelection,
22
+ isFabricObjectWithDragSupport,
23
+ isInteractiveTextObject,
24
+ } from '../util/types';
25
+ import { SelectableCanvas } from './SelectableCanvas';
26
+ import { TextEditingManager } from './TextEditingManager';
27
+
28
+ const addEventOptions = { passive: false } as EventListenerOptions;
29
+
30
+ function checkClick(e: TPointerEvent, value: number) {
31
+ return !!(e as MouseEvent).button && (e as MouseEvent).button === value - 1;
32
+ }
33
+
34
+ // just to be clear, the utils are now deprecated and those are here exactly as minifier helpers
35
+ // because el.addEventListener can't me be minified while a const yes and we use it 47 times in this file.
36
+ // few bytes but why give it away.
37
+ const addListener = (
38
+ el: HTMLElement | Document,
39
+ ...args: Parameters<HTMLElement['addEventListener']>
40
+ ) => el.addEventListener(...args);
41
+ const removeListener = (
42
+ el: HTMLElement | Document,
43
+ ...args: Parameters<HTMLElement['removeEventListener']>
44
+ ) => el.removeEventListener(...args);
45
+
46
+ const syntheticEventConfig = {
47
+ mouse: {
48
+ in: 'over',
49
+ out: 'out',
50
+ targetIn: 'mouseover',
51
+ targetOut: 'mouseout',
52
+ canvasIn: 'mouse:over',
53
+ canvasOut: 'mouse:out',
54
+ },
55
+ drag: {
56
+ in: 'enter',
57
+ out: 'leave',
58
+ targetIn: 'dragenter',
59
+ targetOut: 'dragleave',
60
+ canvasIn: 'drag:enter',
61
+ canvasOut: 'drag:leave',
62
+ },
63
+ } as const;
64
+
65
+ type TSyntheticEventContext = {
66
+ mouse: { e: TPointerEvent };
67
+ drag: DragEventData;
68
+ };
69
+
70
+ export class Canvas extends SelectableCanvas {
71
+ /**
72
+ * Contains the id of the touch event that owns the fabric transform
73
+ * @type Number
74
+ * @private
75
+ */
76
+ declare mainTouchId: null | number;
77
+
78
+ /**
79
+ * When the option is enabled, PointerEvent is used instead of TPointerEvent.
80
+ * @type Boolean
81
+ * @default
82
+ */
83
+ declare enablePointerEvents: boolean;
84
+
85
+ /**
86
+ * Holds a reference to a setTimeout timer for event synchronization
87
+ * @type number
88
+ * @private
89
+ */
90
+ private declare _willAddMouseDown: number;
91
+
92
+ /**
93
+ * Holds a reference to an object on the canvas that is receiving the drag over event.
94
+ * @type FabricObject
95
+ * @private
96
+ */
97
+ private declare _draggedoverTarget?: FabricObject;
98
+
99
+ /**
100
+ * Holds a reference to an object on the canvas from where the drag operation started
101
+ * @type FabricObject
102
+ * @private
103
+ */
104
+ private declare _dragSource?: FabricObject;
105
+
106
+ /**
107
+ * Holds a reference to an object on the canvas that is the current drop target
108
+ * May differ from {@link _draggedoverTarget}
109
+ * @todo inspect whether {@link _draggedoverTarget} and {@link _dropTarget} should be merged somehow
110
+ * @type FabricObject
111
+ * @private
112
+ */
113
+ private declare _dropTarget: FabricObject<ObjectEvents> | undefined;
114
+
115
+ declare currentTarget?: FabricObject;
116
+
117
+ declare currentSubTargets?: FabricObject[];
118
+
119
+ /**
120
+ * Holds a reference to a pointer during mousedown to compare on mouse up and determine
121
+ * if it was a click event
122
+ * @type FabricObject
123
+ * @private
124
+ */
125
+ declare _previousPointer: Point;
126
+
127
+ private _isClick: boolean;
128
+
129
+ textEditingManager = new TextEditingManager();
130
+
131
+ constructor(el: string | HTMLCanvasElement, options = {}) {
132
+ super(el, options);
133
+ // bind event handlers
134
+ (
135
+ [
136
+ '_onMouseDown',
137
+ '_onTouchStart',
138
+ '_onMouseMove',
139
+ '_onMouseUp',
140
+ '_onTouchEnd',
141
+ '_onResize',
142
+ // '_onGesture',
143
+ // '_onDrag',
144
+ // '_onShake',
145
+ // '_onLongPress',
146
+ // '_onOrientationChange',
147
+ '_onMouseWheel',
148
+ '_onMouseOut',
149
+ '_onMouseEnter',
150
+ '_onContextMenu',
151
+ '_onDoubleClick',
152
+ '_onDragStart',
153
+ '_onDragEnd',
154
+ '_onDragProgress',
155
+ '_onDragOver',
156
+ '_onDragEnter',
157
+ '_onDragLeave',
158
+ '_onDrop',
159
+ ] as (keyof this)[]
160
+ ).forEach((eventHandler) => {
161
+ this[eventHandler] = (this[eventHandler] as Function).bind(this);
162
+ });
163
+ // register event handlers
164
+ this.addOrRemove(addListener, 'add');
165
+ }
166
+
167
+ /**
168
+ * return an event prefix pointer or mouse.
169
+ * @private
170
+ */
171
+ private _getEventPrefix() {
172
+ return this.enablePointerEvents ? 'pointer' : 'mouse';
173
+ }
174
+
175
+ addOrRemove(functor: any, eventjsFunctor: 'add' | 'remove') {
176
+ const canvasElement = this.upperCanvasEl,
177
+ eventTypePrefix = this._getEventPrefix();
178
+ functor(getEnv().window, 'resize', this._onResize);
179
+ functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);
180
+ functor(
181
+ canvasElement,
182
+ `${eventTypePrefix}move`,
183
+ this._onMouseMove,
184
+ addEventOptions
185
+ );
186
+ functor(canvasElement, `${eventTypePrefix}out`, this._onMouseOut);
187
+ functor(canvasElement, `${eventTypePrefix}enter`, this._onMouseEnter);
188
+ functor(canvasElement, 'wheel', this._onMouseWheel);
189
+ functor(canvasElement, 'contextmenu', this._onContextMenu);
190
+ functor(canvasElement, 'dblclick', this._onDoubleClick);
191
+ functor(canvasElement, 'dragstart', this._onDragStart);
192
+ functor(canvasElement, 'dragend', this._onDragEnd);
193
+ functor(canvasElement, 'dragover', this._onDragOver);
194
+ functor(canvasElement, 'dragenter', this._onDragEnter);
195
+ functor(canvasElement, 'dragleave', this._onDragLeave);
196
+ functor(canvasElement, 'drop', this._onDrop);
197
+ if (!this.enablePointerEvents) {
198
+ functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);
199
+ }
200
+ // if (typeof eventjs !== 'undefined' && eventjsFunctor in eventjs) {
201
+ // eventjs[eventjsFunctor](canvasElement, 'gesture', this._onGesture);
202
+ // eventjs[eventjsFunctor](canvasElement, 'drag', this._onDrag);
203
+ // eventjs[eventjsFunctor](
204
+ // canvasElement,
205
+ // 'orientation',
206
+ // this._onOrientationChange
207
+ // );
208
+ // eventjs[eventjsFunctor](canvasElement, 'shake', this._onShake);
209
+ // eventjs[eventjsFunctor](canvasElement, 'longpress', this._onLongPress);
210
+ // }
211
+ }
212
+
213
+ /**
214
+ * Removes all event listeners
215
+ */
216
+ removeListeners() {
217
+ this.addOrRemove(removeListener, 'remove');
218
+ // if you dispose on a mouseDown, before mouse up, you need to clean document to...
219
+ const eventTypePrefix = this._getEventPrefix();
220
+ removeListener(
221
+ getEnv().document,
222
+ `${eventTypePrefix}up`,
223
+ this._onMouseUp as EventListener
224
+ );
225
+ removeListener(
226
+ getEnv().document,
227
+ 'touchend',
228
+ this._onTouchEnd as EventListener,
229
+ addEventOptions
230
+ );
231
+ removeListener(
232
+ getEnv().document,
233
+ `${eventTypePrefix}move`,
234
+ this._onMouseMove as EventListener,
235
+ addEventOptions
236
+ );
237
+ removeListener(
238
+ getEnv().document,
239
+ 'touchmove',
240
+ this._onMouseMove as EventListener,
241
+ addEventOptions
242
+ );
243
+ }
244
+
245
+ /**
246
+ * @private
247
+ * @param {Event} [e] Event object fired on wheel event
248
+ */
249
+ private _onMouseWheel(e: MouseEvent) {
250
+ this.__onMouseWheel(e);
251
+ }
252
+
253
+ /**
254
+ * @private
255
+ * @param {Event} e Event object fired on mousedown
256
+ */
257
+ private _onMouseOut(e: TPointerEvent) {
258
+ const target = this._hoveredTarget;
259
+ const shared = {
260
+ e,
261
+ isClick: false,
262
+ pointer: this.getPointer(e),
263
+ absolutePointer: this.getPointer(e, true),
264
+ };
265
+ this.fire('mouse:out', { ...shared, target });
266
+ this._hoveredTarget = undefined;
267
+ target && target.fire('mouseout', { ...shared });
268
+ this._hoveredTargets.forEach((nestedTarget) => {
269
+ this.fire('mouse:out', { ...shared, target: nestedTarget });
270
+ nestedTarget && nestedTarget.fire('mouseout', { ...shared });
271
+ });
272
+ this._hoveredTargets = [];
273
+ }
274
+
275
+ /**
276
+ * @private
277
+ * @param {Event} e Event object fired on mouseenter
278
+ */
279
+ private _onMouseEnter(e: TPointerEvent) {
280
+ // This find target and consequent 'mouse:over' is used to
281
+ // clear old instances on hovered target.
282
+ // calling findTarget has the side effect of killing target.__corner.
283
+ // as a short term fix we are not firing this if we are currently transforming.
284
+ // as a long term fix we need to separate the action of finding a target with the
285
+ // side effects we added to it.
286
+ if (!this._currentTransform && !this.findTarget(e)) {
287
+ this.fire('mouse:over', {
288
+ e,
289
+ isClick: false,
290
+ pointer: this.getPointer(e),
291
+ absolutePointer: this.getPointer(e, true),
292
+ });
293
+ this._hoveredTarget = undefined;
294
+ this._hoveredTargets = [];
295
+ }
296
+ }
297
+
298
+ /**
299
+ * supports native like text dragging
300
+ * @private
301
+ * @param {DragEvent} e
302
+ */
303
+ private _onDragStart(e: DragEvent) {
304
+ this._isClick = false;
305
+ const activeObject = this.getActiveObject();
306
+ if (
307
+ isFabricObjectWithDragSupport(activeObject) &&
308
+ activeObject.onDragStart(e)
309
+ ) {
310
+ this._dragSource = activeObject;
311
+ const options = { e, target: activeObject };
312
+ this.fire('dragstart', options);
313
+ activeObject.fire('dragstart', options);
314
+ addListener(
315
+ this.upperCanvasEl,
316
+ 'drag',
317
+ this._onDragProgress as EventListener
318
+ );
319
+ return;
320
+ }
321
+ stopEvent(e);
322
+ }
323
+
324
+ /**
325
+ * First we clear top context where the effects are being rendered.
326
+ * Then we render the effects.
327
+ * Doing so will render the correct effect for all cases including an overlap between `source` and `target`.
328
+ * @private
329
+ */
330
+ private _renderDragEffects(
331
+ e: DragEvent,
332
+ source?: FabricObject,
333
+ target?: FabricObject
334
+ ) {
335
+ let dirty = false;
336
+ // clear top context
337
+ const dropTarget = this._dropTarget;
338
+ if (dropTarget && dropTarget !== source && dropTarget !== target) {
339
+ dropTarget.clearContextTop();
340
+ dirty = true;
341
+ }
342
+ source?.clearContextTop();
343
+ target !== source && target?.clearContextTop();
344
+ // render effects
345
+ const ctx = this.contextTop;
346
+ ctx.save();
347
+ ctx.transform(...this.viewportTransform);
348
+ if (source) {
349
+ ctx.save();
350
+ source.transform(ctx);
351
+ (source as AssertKeys<FabricObject, 'canvas'>).renderDragSourceEffect(e);
352
+ ctx.restore();
353
+ dirty = true;
354
+ }
355
+ if (target) {
356
+ ctx.save();
357
+ target.transform(ctx);
358
+ (target as AssertKeys<FabricObject, 'canvas'>).renderDropTargetEffect(e);
359
+ ctx.restore();
360
+ dirty = true;
361
+ }
362
+ ctx.restore();
363
+ dirty && (this.contextTopDirty = true);
364
+ }
365
+
366
+ /**
367
+ * supports native like text dragging
368
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag
369
+ * @private
370
+ * @param {DragEvent} e
371
+ */
372
+ private _onDragEnd(e: DragEvent) {
373
+ const didDrop = !!e.dataTransfer && e.dataTransfer.dropEffect !== 'none',
374
+ dropTarget = didDrop ? this._activeObject : undefined,
375
+ options = {
376
+ e,
377
+ target: this._dragSource as FabricObject,
378
+ subTargets: this.targets,
379
+ dragSource: this._dragSource as FabricObject,
380
+ didDrop,
381
+ dropTarget: dropTarget as FabricObject,
382
+ };
383
+ removeListener(
384
+ this.upperCanvasEl,
385
+ 'drag',
386
+ this._onDragProgress as EventListener
387
+ );
388
+ this.fire('dragend', options);
389
+ this._dragSource && this._dragSource.fire('dragend', options);
390
+ delete this._dragSource;
391
+ // we need to call mouse up synthetically because the browser won't
392
+ this._onMouseUp(e);
393
+ }
394
+
395
+ /**
396
+ * fire `drag` event on canvas and drag source
397
+ * @private
398
+ * @param {DragEvent} e
399
+ */
400
+ private _onDragProgress(e: DragEvent) {
401
+ const options = {
402
+ e,
403
+ target: this._dragSource as FabricObject | undefined,
404
+ dragSource: this._dragSource as FabricObject | undefined,
405
+ dropTarget: this._draggedoverTarget as FabricObject,
406
+ };
407
+ this.fire('drag', options);
408
+ this._dragSource && this._dragSource.fire('drag', options);
409
+ }
410
+
411
+ /**
412
+ * As opposed to {@link findTarget} we want the top most object to be returned w/o the active object cutting in line.
413
+ * Override at will
414
+ */
415
+ protected findDragTargets(e: DragEvent) {
416
+ this.targets = [];
417
+ const target = this._searchPossibleTargets(
418
+ this._objects,
419
+ this.getPointer(e, true)
420
+ );
421
+ return {
422
+ target,
423
+ targets: [...this.targets],
424
+ };
425
+ }
426
+
427
+ /**
428
+ * prevent default to allow drop event to be fired
429
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#specifying_drop_targets
430
+ * @private
431
+ * @param {DragEvent} [e] Event object fired on Event.js shake
432
+ */
433
+ private _onDragOver(e: DragEvent) {
434
+ const eventType = 'dragover';
435
+ const { target, targets } = this.findDragTargets(e);
436
+ const dragSource = this._dragSource as FabricObject;
437
+ const options = {
438
+ e,
439
+ target,
440
+ subTargets: targets,
441
+ dragSource,
442
+ canDrop: false,
443
+ dropTarget: undefined,
444
+ };
445
+ let dropTarget;
446
+ // fire on canvas
447
+ this.fire(eventType, options);
448
+ // make sure we fire dragenter events before dragover
449
+ // if dragleave is needed, object will not fire dragover so we don't need to trouble ourselves with it
450
+ this._fireEnterLeaveEvents(target, options);
451
+ if (target) {
452
+ if (target.canDrop(e)) {
453
+ dropTarget = target;
454
+ }
455
+ target.fire(eventType, options);
456
+ }
457
+ // propagate the event to subtargets
458
+ for (let i = 0; i < targets.length; i++) {
459
+ const subTarget = targets[i];
460
+ // accept event only if previous targets didn't (the accepting target calls `preventDefault` to inform that the event is taken)
461
+ // TODO: verify if those should loop in inverse order then?
462
+ // what is the order of subtargets?
463
+ if (subTarget.canDrop(e)) {
464
+ dropTarget = subTarget;
465
+ }
466
+ subTarget.fire(eventType, options);
467
+ }
468
+ // render drag effects now that relations between source and target is clear
469
+ this._renderDragEffects(e, dragSource, dropTarget);
470
+ this._dropTarget = dropTarget;
471
+ }
472
+
473
+ /**
474
+ * fire `dragleave` on `dragover` targets
475
+ * @private
476
+ * @param {Event} [e] Event object fired on Event.js shake
477
+ */
478
+ private _onDragEnter(e: DragEvent) {
479
+ const { target, targets } = this.findDragTargets(e);
480
+ const options = {
481
+ e,
482
+ target,
483
+ subTargets: targets,
484
+ dragSource: this._dragSource,
485
+ };
486
+ this.fire('dragenter', options);
487
+ // fire dragenter on targets
488
+ this._fireEnterLeaveEvents(target, options);
489
+ }
490
+
491
+ /**
492
+ * fire `dragleave` on `dragover` targets
493
+ * @private
494
+ * @param {Event} [e] Event object fired on Event.js shake
495
+ */
496
+ private _onDragLeave(e: DragEvent) {
497
+ const options = {
498
+ e,
499
+ target: this._draggedoverTarget,
500
+ subTargets: this.targets,
501
+ dragSource: this._dragSource,
502
+ };
503
+ this.fire('dragleave', options);
504
+
505
+ // fire dragleave on targets
506
+ this._fireEnterLeaveEvents(undefined, options);
507
+ this._renderDragEffects(e, this._dragSource);
508
+ this._dropTarget = undefined;
509
+ // clear targets
510
+ this.targets = [];
511
+ this._hoveredTargets = [];
512
+ }
513
+
514
+ /**
515
+ * `drop:before` is a an event that allows you to schedule logic
516
+ * before the `drop` event. Prefer `drop` event always, but if you need
517
+ * to run some drop-disabling logic on an event, since there is no way
518
+ * to handle event handlers ordering, use `drop:before`
519
+ * @private
520
+ * @param {Event} e
521
+ */
522
+ private _onDrop(e: DragEvent) {
523
+ const { target, targets } = this.findDragTargets(e);
524
+ const options = this._basicEventHandler('drop:before', {
525
+ e,
526
+ target,
527
+ subTargets: targets,
528
+ dragSource: this._dragSource,
529
+ pointer: this.getPointer(e),
530
+ });
531
+ // will be set by the drop target
532
+ options.didDrop = false;
533
+ // will be set by the drop target, used in case options.target refuses the drop
534
+ options.dropTarget = undefined;
535
+ // fire `drop`
536
+ this._basicEventHandler('drop', options);
537
+ // inform canvas of the drop
538
+ // we do this because canvas was unaware of what happened at the time the `drop` event was fired on it
539
+ // use for side effects
540
+ this.fire('drop:after', options);
541
+ }
542
+
543
+ /**
544
+ * @private
545
+ * @param {Event} e Event object fired on mousedown
546
+ */
547
+ private _onContextMenu(e: TPointerEvent): false {
548
+ const target = this.findTarget(e),
549
+ subTargets = this.targets || [];
550
+ const options = this._basicEventHandler('contextmenu:before', {
551
+ e,
552
+ target,
553
+ subTargets,
554
+ });
555
+ // TODO: this line is silly because the dev can subscribe to the event and prevent it themselves
556
+ this.stopContextMenu && stopEvent(e);
557
+ this._basicEventHandler('contextmenu', options);
558
+ return false;
559
+ }
560
+
561
+ /**
562
+ * @private
563
+ * @param {Event} e Event object fired on mousedown
564
+ */
565
+ private _onDoubleClick(e: TPointerEvent) {
566
+ this._cacheTransformEventData(e);
567
+ this._handleEvent(e, 'dblclick');
568
+ this._resetTransformEventData();
569
+ }
570
+
571
+ /**
572
+ * Return a the id of an event.
573
+ * returns either the pointerId or the identifier or 0 for the mouse event
574
+ * @private
575
+ * @param {Event} evt Event object
576
+ */
577
+ getPointerId(evt: TouchEvent | PointerEvent): number {
578
+ const changedTouches = (evt as TouchEvent).changedTouches;
579
+
580
+ if (changedTouches) {
581
+ return changedTouches[0] && changedTouches[0].identifier;
582
+ }
583
+
584
+ if (this.enablePointerEvents) {
585
+ return (evt as PointerEvent).pointerId;
586
+ }
587
+
588
+ return -1;
589
+ }
590
+
591
+ /**
592
+ * Determines if an event has the id of the event that is considered main
593
+ * @private
594
+ * @param {evt} event Event object
595
+ */
596
+ _isMainEvent(evt: TPointerEvent): boolean {
597
+ if ((evt as PointerEvent).isPrimary === true) {
598
+ return true;
599
+ }
600
+ if ((evt as PointerEvent).isPrimary === false) {
601
+ return false;
602
+ }
603
+ if (evt.type === 'touchend' && (evt as TouchEvent).touches.length === 0) {
604
+ return true;
605
+ }
606
+ if ((evt as TouchEvent).changedTouches) {
607
+ return (
608
+ (evt as TouchEvent).changedTouches[0].identifier === this.mainTouchId
609
+ );
610
+ }
611
+ return true;
612
+ }
613
+
614
+ /**
615
+ * @private
616
+ * @param {Event} e Event object fired on mousedown
617
+ */
618
+ _onTouchStart(e: TouchEvent) {
619
+ e.preventDefault();
620
+ if (this.mainTouchId === null) {
621
+ this.mainTouchId = this.getPointerId(e);
622
+ }
623
+ this.__onMouseDown(e);
624
+ this._resetTransformEventData();
625
+ const canvasElement = this.upperCanvasEl,
626
+ eventTypePrefix = this._getEventPrefix();
627
+ addListener(
628
+ getEnv().document,
629
+ 'touchend',
630
+ this._onTouchEnd as EventListener,
631
+ addEventOptions
632
+ );
633
+ addListener(
634
+ getEnv().document,
635
+ 'touchmove',
636
+ this._onMouseMove as EventListener,
637
+ addEventOptions
638
+ );
639
+ // Unbind mousedown to prevent double triggers from touch devices
640
+ removeListener(
641
+ canvasElement,
642
+ eventTypePrefix + 'down',
643
+ this._onMouseDown as EventListener
644
+ );
645
+ }
646
+
647
+ /**
648
+ * @private
649
+ * @param {Event} e Event object fired on mousedown
650
+ */
651
+ _onMouseDown(e: TPointerEvent) {
652
+ this.__onMouseDown(e);
653
+ this._resetTransformEventData();
654
+ const canvasElement = this.upperCanvasEl,
655
+ eventTypePrefix = this._getEventPrefix();
656
+ removeListener(
657
+ canvasElement,
658
+ `${eventTypePrefix}move`,
659
+ this._onMouseMove as EventListener,
660
+ addEventOptions
661
+ );
662
+ addListener(
663
+ getEnv().document,
664
+ `${eventTypePrefix}up`,
665
+ this._onMouseUp as EventListener
666
+ );
667
+ addListener(
668
+ getEnv().document,
669
+ `${eventTypePrefix}move`,
670
+ this._onMouseMove as EventListener,
671
+ addEventOptions
672
+ );
673
+ }
674
+
675
+ /**
676
+ * @private
677
+ * @param {Event} e Event object fired on mousedown
678
+ */
679
+ _onTouchEnd(e: TouchEvent) {
680
+ if (e.touches.length > 0) {
681
+ // if there are still touches stop here
682
+ return;
683
+ }
684
+ this.__onMouseUp(e);
685
+ this._resetTransformEventData();
686
+ this.mainTouchId = null;
687
+ const eventTypePrefix = this._getEventPrefix();
688
+ removeListener(
689
+ getEnv().document,
690
+ 'touchend',
691
+ this._onTouchEnd as EventListener,
692
+ addEventOptions
693
+ );
694
+ removeListener(
695
+ getEnv().document,
696
+ 'touchmove',
697
+ this._onMouseMove as EventListener,
698
+ addEventOptions
699
+ );
700
+ if (this._willAddMouseDown) {
701
+ clearTimeout(this._willAddMouseDown);
702
+ }
703
+ this._willAddMouseDown = setTimeout(() => {
704
+ // Wait 400ms before rebinding mousedown to prevent double triggers
705
+ // from touch devices
706
+ addListener(
707
+ this.upperCanvasEl,
708
+ eventTypePrefix + 'down',
709
+ this._onMouseDown as EventListener
710
+ );
711
+ this._willAddMouseDown = 0;
712
+ }, 400) as unknown as number;
713
+ }
714
+
715
+ /**
716
+ * @private
717
+ * @param {Event} e Event object fired on mouseup
718
+ */
719
+ _onMouseUp(e: TPointerEvent) {
720
+ this.__onMouseUp(e);
721
+ this._resetTransformEventData();
722
+ const canvasElement = this.upperCanvasEl,
723
+ eventTypePrefix = this._getEventPrefix();
724
+ if (this._isMainEvent(e)) {
725
+ removeListener(
726
+ getEnv().document,
727
+ `${eventTypePrefix}up`,
728
+ this._onMouseUp as EventListener
729
+ );
730
+ removeListener(
731
+ getEnv().document,
732
+ `${eventTypePrefix}move`,
733
+ this._onMouseMove as EventListener,
734
+ addEventOptions
735
+ );
736
+ addListener(
737
+ canvasElement,
738
+ `${eventTypePrefix}move`,
739
+ this._onMouseMove as EventListener,
740
+ addEventOptions
741
+ );
742
+ }
743
+ }
744
+
745
+ /**
746
+ * @private
747
+ * @param {Event} e Event object fired on mousemove
748
+ */
749
+ _onMouseMove(e: TPointerEvent) {
750
+ const activeObject = this.getActiveObject();
751
+ !this.allowTouchScrolling &&
752
+ (!activeObject ||
753
+ // a drag event sequence is started by the active object flagging itself on mousedown / mousedown:before
754
+ // we must not prevent the event's default behavior in order for the window to start dragging
755
+ (isFabricObjectWithDragSupport(activeObject) &&
756
+ !activeObject.shouldStartDragging())) &&
757
+ e.preventDefault &&
758
+ e.preventDefault();
759
+ this.__onMouseMove(e);
760
+ }
761
+
762
+ /**
763
+ * @private
764
+ */
765
+ _onResize() {
766
+ this.calcOffset();
767
+ this._resetTransformEventData();
768
+ }
769
+
770
+ /**
771
+ * Decides whether the canvas should be redrawn in mouseup and mousedown events.
772
+ * @private
773
+ * @param {Object} target
774
+ */
775
+ _shouldRender(target: FabricObject | undefined) {
776
+ const activeObject = this.getActiveObject();
777
+
778
+ // if just one of them is available or if they are both but are different objects
779
+ if (
780
+ !!activeObject !== !!target ||
781
+ (activeObject && target && activeObject !== target)
782
+ ) {
783
+ // this covers: switch of target, from target to no target, selection of target
784
+ // multiSelection with key and mouse
785
+ return true;
786
+ } else if (isInteractiveTextObject(activeObject)) {
787
+ // if we mouse up/down over a editing textbox a cursor change,
788
+ // there is no need to re render
789
+ return false;
790
+ }
791
+ return false;
792
+ }
793
+
794
+ /**
795
+ * Method that defines the actions when mouse is released on canvas.
796
+ * The method resets the currentTransform parameters, store the image corner
797
+ * position in the image object and render the canvas on top.
798
+ * @private
799
+ * @param {Event} e Event object fired on mouseup
800
+ */
801
+ __onMouseUp(e: TPointerEvent) {
802
+ const transform = this._currentTransform;
803
+ this._cacheTransformEventData(e);
804
+ const target = this._target;
805
+ const isClick = this._isClick;
806
+ this._handleEvent(e, 'up:before');
807
+ // if right/middle click just fire events and return
808
+ // target undefined will make the _handleEvent search the target
809
+ if (checkClick(e, RIGHT_CLICK)) {
810
+ if (this.fireRightClick) {
811
+ this._handleEvent(e, 'up', RIGHT_CLICK, isClick);
812
+ }
813
+ return;
814
+ }
815
+
816
+ if (checkClick(e, MIDDLE_CLICK)) {
817
+ if (this.fireMiddleClick) {
818
+ this._handleEvent(e, 'up', MIDDLE_CLICK, isClick);
819
+ }
820
+ this._resetTransformEventData();
821
+ return;
822
+ }
823
+
824
+ if (this.isDrawingMode && this._isCurrentlyDrawing) {
825
+ this._onMouseUpInDrawingMode(e);
826
+ return;
827
+ }
828
+
829
+ if (!this._isMainEvent(e)) {
830
+ return;
831
+ }
832
+ let shouldRender = false;
833
+ if (transform) {
834
+ this._finalizeCurrentTransform(e);
835
+ shouldRender = transform.actionPerformed;
836
+ }
837
+ if (!isClick) {
838
+ const targetWasActive = target === this._activeObject;
839
+ this._maybeGroupObjects(e);
840
+ if (!shouldRender) {
841
+ shouldRender =
842
+ this._shouldRender(target) ||
843
+ (!targetWasActive && target === this._activeObject);
844
+ }
845
+ }
846
+ let pointer, corner;
847
+ if (target) {
848
+ corner = target._findTargetCorner(
849
+ this.getPointer(e, true),
850
+ isTouchEvent(e)
851
+ );
852
+ if (
853
+ target.selectable &&
854
+ target !== this._activeObject &&
855
+ target.activeOn === 'up'
856
+ ) {
857
+ this.setActiveObject(target, e);
858
+ shouldRender = true;
859
+ } else {
860
+ const control = target.controls[corner as string];
861
+ const mouseUpHandler =
862
+ control && control.getMouseUpHandler(e, target, control);
863
+ if (mouseUpHandler) {
864
+ pointer = this.getPointer(e);
865
+ mouseUpHandler(e, transform!, pointer.x, pointer.y);
866
+ }
867
+ }
868
+ target.isMoving = false;
869
+ }
870
+ // if we are ending up a transform on a different control or a new object
871
+ // fire the original mouse up from the corner that started the transform
872
+ if (
873
+ transform &&
874
+ (transform.target !== target || transform.corner !== corner)
875
+ ) {
876
+ const originalControl =
877
+ transform.target && transform.target.controls[transform.corner],
878
+ originalMouseUpHandler =
879
+ originalControl &&
880
+ originalControl.getMouseUpHandler(
881
+ e,
882
+ transform.target,
883
+ originalControl
884
+ );
885
+ pointer = pointer || this.getPointer(e);
886
+ originalMouseUpHandler &&
887
+ originalMouseUpHandler(e, transform, pointer.x, pointer.y);
888
+ }
889
+ this._setCursorFromEvent(e, target);
890
+ this._handleEvent(e, 'up', LEFT_CLICK, isClick);
891
+ this._groupSelector = null;
892
+ this._currentTransform = null;
893
+ // reset the target information about which corner is selected
894
+ target && (target.__corner = undefined);
895
+ if (shouldRender) {
896
+ this.requestRenderAll();
897
+ } else if (
898
+ !isClick &&
899
+ !(
900
+ isInteractiveTextObject(this._activeObject) &&
901
+ this._activeObject.isEditing
902
+ )
903
+ ) {
904
+ this.renderTop();
905
+ }
906
+ }
907
+
908
+ _basicEventHandler<T extends keyof (CanvasEvents | ObjectEvents)>(
909
+ eventType: T,
910
+ options: (CanvasEvents & ObjectEvents)[T]
911
+ ) {
912
+ const { target, subTargets = [] } = options as {
913
+ target?: FabricObject;
914
+ subTargets: FabricObject[];
915
+ };
916
+ this.fire(eventType, options);
917
+ target && target.fire(eventType, options);
918
+ for (let i = 0; i < subTargets.length; i++) {
919
+ subTargets[i].fire(eventType, options);
920
+ }
921
+ return options;
922
+ }
923
+
924
+ /**
925
+ * @private
926
+ * Handle event firing for target and subtargets
927
+ * @param {Event} e event from mouse
928
+ * @param {String} eventType event to fire (up, down or move)
929
+ * @param {fabric.Object} targetObj receiving event
930
+ * @param {Number} [button] button used in the event 1 = left, 2 = middle, 3 = right
931
+ * @param {Boolean} isClick for left button only, indicates that the mouse up happened without move.
932
+ */
933
+ _handleEvent(
934
+ e: TPointerEvent,
935
+ eventType: TPointerEventNames,
936
+ button = LEFT_CLICK,
937
+ isClick = false
938
+ ) {
939
+ const target = this._target,
940
+ targets = this.targets || [],
941
+ options: TPointerEventInfo = {
942
+ e: e,
943
+ target: target,
944
+ subTargets: targets,
945
+ button,
946
+ isClick,
947
+ pointer: this.getPointer(e),
948
+ absolutePointer: this.getPointer(e, true),
949
+ transform: this._currentTransform,
950
+ };
951
+ if (eventType === 'up') {
952
+ options.currentTarget = this.findTarget(e);
953
+ options.currentSubTargets = this.targets;
954
+ }
955
+ this.fire(`mouse:${eventType}`, options);
956
+ // this may be a little be more complicated of what we want to handle
957
+ target && target.fire(`mouse${eventType}`, options);
958
+ for (let i = 0; i < targets.length; i++) {
959
+ targets[i].fire(`mouse${eventType}`, options);
960
+ }
961
+ }
962
+
963
+ /**
964
+ * End the current transform.
965
+ * You don't usually need to call this method unless you are interrupting a user initiated transform
966
+ * because of some other event ( a press of key combination, or something that block the user UX )
967
+ * @param {Event} [e] send the mouse event that generate the finalize down, so it can be used in the event
968
+ */
969
+ endCurrentTransform(e: TPointerEvent) {
970
+ const transform = this._currentTransform;
971
+ this._finalizeCurrentTransform(e);
972
+ if (transform && transform.target) {
973
+ // this could probably go inside _finalizeCurrentTransform
974
+ transform.target.isMoving = false;
975
+ }
976
+ this._currentTransform = null;
977
+ }
978
+
979
+ /**
980
+ * @private
981
+ * @param {Event} e send the mouse event that generate the finalize down, so it can be used in the event
982
+ */
983
+ _finalizeCurrentTransform(e: TPointerEvent) {
984
+ const transform = this._currentTransform!,
985
+ target = transform.target,
986
+ options = {
987
+ e,
988
+ target,
989
+ transform,
990
+ action: transform.action,
991
+ };
992
+
993
+ if (target._scaling) {
994
+ target._scaling = false;
995
+ }
996
+
997
+ target.setCoords();
998
+
999
+ if (transform.actionPerformed) {
1000
+ this.fire('object:modified', options);
1001
+ target.fire('modified', options);
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * @private
1007
+ * @param {Event} e Event object fired on mousedown
1008
+ */
1009
+ _onMouseDownInDrawingMode(e: TPointerEvent) {
1010
+ this._isCurrentlyDrawing = true;
1011
+ if (this.getActiveObject()) {
1012
+ this.discardActiveObject(e);
1013
+ this.requestRenderAll();
1014
+ }
1015
+ const pointer = this.getPointer(e);
1016
+ this.freeDrawingBrush &&
1017
+ this.freeDrawingBrush.onMouseDown(pointer, { e, pointer });
1018
+ this._handleEvent(e, 'down');
1019
+ }
1020
+
1021
+ /**
1022
+ * @private
1023
+ * @param {Event} e Event object fired on mousemove
1024
+ */
1025
+ _onMouseMoveInDrawingMode(e: TPointerEvent) {
1026
+ if (this._isCurrentlyDrawing) {
1027
+ const pointer = this.getPointer(e);
1028
+ this.freeDrawingBrush &&
1029
+ this.freeDrawingBrush.onMouseMove(pointer, {
1030
+ e,
1031
+ pointer,
1032
+ });
1033
+ }
1034
+ this.setCursor(this.freeDrawingCursor);
1035
+ this._handleEvent(e, 'move');
1036
+ }
1037
+
1038
+ /**
1039
+ * @private
1040
+ * @param {Event} e Event object fired on mouseup
1041
+ */
1042
+ _onMouseUpInDrawingMode(e: TPointerEvent) {
1043
+ const pointer = this.getPointer(e);
1044
+ if (this.freeDrawingBrush) {
1045
+ this._isCurrentlyDrawing = !!this.freeDrawingBrush.onMouseUp({
1046
+ e: e,
1047
+ pointer: pointer,
1048
+ });
1049
+ } else {
1050
+ this._isCurrentlyDrawing = false;
1051
+ }
1052
+ this._handleEvent(e, 'up');
1053
+ }
1054
+
1055
+ /**
1056
+ * Method that defines the actions when mouse is clicked on canvas.
1057
+ * The method inits the currentTransform parameters and renders all the
1058
+ * canvas so the current image can be placed on the top canvas and the rest
1059
+ * in on the container one.
1060
+ * @private
1061
+ * @param {Event} e Event object fired on mousedown
1062
+ */
1063
+ __onMouseDown(e: TPointerEvent) {
1064
+ this._isClick = true;
1065
+ this._cacheTransformEventData(e);
1066
+ this._handleEvent(e, 'down:before');
1067
+ let target: FabricObject | undefined = this._target;
1068
+ // if right click just fire events
1069
+ if (checkClick(e, RIGHT_CLICK)) {
1070
+ if (this.fireRightClick) {
1071
+ this._handleEvent(e, 'down', RIGHT_CLICK);
1072
+ }
1073
+ return;
1074
+ }
1075
+
1076
+ if (checkClick(e, MIDDLE_CLICK)) {
1077
+ if (this.fireMiddleClick) {
1078
+ this._handleEvent(e, 'down', MIDDLE_CLICK);
1079
+ }
1080
+ return;
1081
+ }
1082
+
1083
+ if (this.isDrawingMode) {
1084
+ this._onMouseDownInDrawingMode(e);
1085
+ return;
1086
+ }
1087
+
1088
+ if (!this._isMainEvent(e)) {
1089
+ return;
1090
+ }
1091
+
1092
+ // ignore if some object is being transformed at this moment
1093
+ if (this._currentTransform) {
1094
+ return;
1095
+ }
1096
+
1097
+ const pointer = this.getPointer(e, true);
1098
+ // save pointer for check in __onMouseUp event
1099
+ this._previousPointer = pointer;
1100
+ const shouldRender = this._shouldRender(target),
1101
+ shouldGroup = this._shouldGroup(e, target);
1102
+ if (this._shouldClearSelection(e, target)) {
1103
+ this.discardActiveObject(e);
1104
+ } else if (shouldGroup) {
1105
+ // in order for shouldGroup to be true, target needs to be true
1106
+ this._handleGrouping(e, target!);
1107
+ target = this._activeObject;
1108
+ }
1109
+ // we start a group selector rectangle if
1110
+ // selection is enabled
1111
+ // and there is no target, or the following 3 condition both apply
1112
+ // target is not selectable ( otherwise we selected it )
1113
+ // target is not editing
1114
+ // target is not already selected ( otherwise we drage )
1115
+ if (
1116
+ this.selection &&
1117
+ (!target ||
1118
+ (!target.selectable &&
1119
+ // @ts-ignore
1120
+ !target.isEditing &&
1121
+ target !== this._activeObject))
1122
+ ) {
1123
+ const p = this.getPointer(e);
1124
+ this._groupSelector = {
1125
+ ex: p.x,
1126
+ ey: p.y,
1127
+ top: 0,
1128
+ left: 0,
1129
+ };
1130
+ }
1131
+
1132
+ if (target) {
1133
+ const alreadySelected = target === this._activeObject;
1134
+ if (target.selectable && target.activeOn === 'down') {
1135
+ this.setActiveObject(target, e);
1136
+ }
1137
+ const corner = target._findTargetCorner(
1138
+ this.getPointer(e, true),
1139
+ isTouchEvent(e)
1140
+ );
1141
+ if (target === this._activeObject && (corner || !shouldGroup)) {
1142
+ this._setupCurrentTransform(e, target, alreadySelected);
1143
+ const control = target.controls[corner],
1144
+ pointer = this.getPointer(e),
1145
+ mouseDownHandler =
1146
+ control && control.getMouseDownHandler(e, target, control);
1147
+ if (mouseDownHandler) {
1148
+ mouseDownHandler(e, this._currentTransform!, pointer.x, pointer.y);
1149
+ }
1150
+ }
1151
+ }
1152
+ const invalidate = shouldRender || shouldGroup;
1153
+ // we clear `_objectsToRender` in case of a change in order to repopulate it at rendering
1154
+ // run before firing the `down` event to give the dev a chance to populate it themselves
1155
+ invalidate && (this._objectsToRender = undefined);
1156
+ this._handleEvent(e, 'down');
1157
+ // we must renderAll so that we update the visuals
1158
+ invalidate && this.requestRenderAll();
1159
+ }
1160
+
1161
+ /**
1162
+ * reset cache form common information needed during event processing
1163
+ * @private
1164
+ */
1165
+ _resetTransformEventData() {
1166
+ this._target = undefined;
1167
+ this._pointer = undefined;
1168
+ this._absolutePointer = undefined;
1169
+ }
1170
+
1171
+ /**
1172
+ * Cache common information needed during event processing
1173
+ * @private
1174
+ * @param {Event} e Event object fired on event
1175
+ */
1176
+ _cacheTransformEventData(e: TPointerEvent) {
1177
+ // reset in order to avoid stale caching
1178
+ this._resetTransformEventData();
1179
+ this._pointer = this.getPointer(e, true);
1180
+ this._absolutePointer = this.restorePointerVpt(this._pointer);
1181
+ this._target = this._currentTransform
1182
+ ? this._currentTransform.target
1183
+ : this.findTarget(e);
1184
+ }
1185
+
1186
+ /**
1187
+ * @private
1188
+ */
1189
+ _beforeTransform(e: TPointerEvent) {
1190
+ const t = this._currentTransform!;
1191
+ this.fire('before:transform', {
1192
+ e,
1193
+ transform: t,
1194
+ });
1195
+ }
1196
+
1197
+ /**
1198
+ * Method that defines the actions when mouse is hovering the canvas.
1199
+ * The currentTransform parameter will define whether the user is rotating/scaling/translating
1200
+ * an image or neither of them (only hovering). A group selection is also possible and would cancel
1201
+ * all any other type of action.
1202
+ * In case of an image transformation only the top canvas will be rendered.
1203
+ * @private
1204
+ * @param {Event} e Event object fired on mousemove
1205
+ */
1206
+ __onMouseMove(e: TPointerEvent) {
1207
+ this._isClick = false;
1208
+ this._handleEvent(e, 'move:before');
1209
+ this._cacheTransformEventData(e);
1210
+
1211
+ if (this.isDrawingMode) {
1212
+ this._onMouseMoveInDrawingMode(e);
1213
+ return;
1214
+ }
1215
+
1216
+ if (!this._isMainEvent(e)) {
1217
+ return;
1218
+ }
1219
+
1220
+ const groupSelector = this._groupSelector;
1221
+
1222
+ // We initially clicked in an empty area, so we draw a box for multiple selection
1223
+ if (groupSelector) {
1224
+ const pointer = this.getPointer(e);
1225
+
1226
+ groupSelector.left = pointer.x - groupSelector.ex;
1227
+ groupSelector.top = pointer.y - groupSelector.ey;
1228
+
1229
+ this.renderTop();
1230
+ } else if (!this._currentTransform) {
1231
+ const target = this.findTarget(e);
1232
+ this._setCursorFromEvent(e, target);
1233
+ this._fireOverOutEvents(e, target);
1234
+ } else {
1235
+ this._transformObject(e);
1236
+ }
1237
+ this.textEditingManager.onMouseMove(e);
1238
+ this._handleEvent(e, 'move');
1239
+ this._resetTransformEventData();
1240
+ }
1241
+
1242
+ /**
1243
+ * Manage the mouseout, mouseover events for the fabric object on the canvas
1244
+ * @param {Fabric.Object} target the target where the target from the mousemove event
1245
+ * @param {Event} e Event object fired on mousemove
1246
+ * @private
1247
+ */
1248
+ _fireOverOutEvents(e: TPointerEvent, target?: FabricObject) {
1249
+ const _hoveredTarget = this._hoveredTarget,
1250
+ _hoveredTargets = this._hoveredTargets,
1251
+ targets = this.targets,
1252
+ length = Math.max(_hoveredTargets.length, targets.length);
1253
+
1254
+ this.fireSyntheticInOutEvents('mouse', {
1255
+ e,
1256
+ target,
1257
+ oldTarget: _hoveredTarget,
1258
+ fireCanvas: true,
1259
+ });
1260
+ for (let i = 0; i < length; i++) {
1261
+ this.fireSyntheticInOutEvents('mouse', {
1262
+ e,
1263
+ target: targets[i],
1264
+ oldTarget: _hoveredTargets[i],
1265
+ });
1266
+ }
1267
+ this._hoveredTarget = target;
1268
+ this._hoveredTargets = this.targets.concat();
1269
+ }
1270
+
1271
+ /**
1272
+ * Manage the dragEnter, dragLeave events for the fabric objects on the canvas
1273
+ * @param {Fabric.Object} target the target where the target from the onDrag event
1274
+ * @param {Object} data Event object fired on dragover
1275
+ * @private
1276
+ */
1277
+ _fireEnterLeaveEvents(target: FabricObject | undefined, data: DragEventData) {
1278
+ const draggedoverTarget = this._draggedoverTarget,
1279
+ _hoveredTargets = this._hoveredTargets,
1280
+ targets = this.targets,
1281
+ length = Math.max(_hoveredTargets.length, targets.length);
1282
+
1283
+ this.fireSyntheticInOutEvents('drag', {
1284
+ ...data,
1285
+ target,
1286
+ oldTarget: draggedoverTarget,
1287
+ fireCanvas: true,
1288
+ });
1289
+ for (let i = 0; i < length; i++) {
1290
+ this.fireSyntheticInOutEvents('drag', {
1291
+ ...data,
1292
+ target: targets[i],
1293
+ oldTarget: _hoveredTargets[i],
1294
+ });
1295
+ }
1296
+ this._draggedoverTarget = target;
1297
+ }
1298
+
1299
+ /**
1300
+ * Manage the synthetic in/out events for the fabric objects on the canvas
1301
+ * @param {Fabric.Object} target the target where the target from the supported events
1302
+ * @param {Object} data Event object fired
1303
+ * @param {Object} config configuration for the function to work
1304
+ * @param {String} config.targetName property on the canvas where the old target is stored
1305
+ * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out
1306
+ * @param {String} config.evtOut name of the event to fire for out
1307
+ * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in
1308
+ * @param {String} config.evtIn name of the event to fire for in
1309
+ * @private
1310
+ */
1311
+ fireSyntheticInOutEvents<T extends keyof TSyntheticEventContext>(
1312
+ type: T,
1313
+ {
1314
+ target,
1315
+ oldTarget,
1316
+ fireCanvas,
1317
+ e,
1318
+ ...data
1319
+ }: TSyntheticEventContext[T] & {
1320
+ target?: FabricObject;
1321
+ oldTarget?: FabricObject;
1322
+ fireCanvas?: boolean;
1323
+ }
1324
+ ) {
1325
+ const { targetIn, targetOut, canvasIn, canvasOut } =
1326
+ syntheticEventConfig[type];
1327
+ const targetChanged = oldTarget !== target;
1328
+
1329
+ if (oldTarget && targetChanged) {
1330
+ const outOpt = {
1331
+ ...data,
1332
+ e,
1333
+ target: oldTarget,
1334
+ nextTarget: target,
1335
+ isClick: false,
1336
+ pointer: this.getPointer(e),
1337
+ absolutePointer: this.getPointer(e, true),
1338
+ };
1339
+ fireCanvas && this.fire(canvasIn, outOpt);
1340
+ oldTarget.fire(targetOut, outOpt);
1341
+ }
1342
+ if (target && targetChanged) {
1343
+ const inOpt: TPointerEventInfo = {
1344
+ ...data,
1345
+ e,
1346
+ target,
1347
+ previousTarget: oldTarget,
1348
+ isClick: false,
1349
+ pointer: this.getPointer(e),
1350
+ absolutePointer: this.getPointer(e, true),
1351
+ };
1352
+ fireCanvas && this.fire(canvasOut, inOpt);
1353
+ target.fire(targetIn, inOpt);
1354
+ }
1355
+ }
1356
+
1357
+ /**
1358
+ * Method that defines actions when an Event Mouse Wheel
1359
+ * @param {Event} e Event object fired on mouseup
1360
+ */
1361
+ __onMouseWheel(e: TPointerEvent) {
1362
+ this._cacheTransformEventData(e);
1363
+ this._handleEvent(e, 'wheel');
1364
+ this._resetTransformEventData();
1365
+ }
1366
+
1367
+ /**
1368
+ * @private
1369
+ * @param {Event} e Event fired on mousemove
1370
+ */
1371
+ _transformObject(e: TPointerEvent) {
1372
+ const pointer = this.getPointer(e),
1373
+ transform = this._currentTransform!,
1374
+ target = transform.target,
1375
+ // transform pointer to target's containing coordinate plane
1376
+ // both pointer and object should agree on every point
1377
+ localPointer = target.group
1378
+ ? sendPointToPlane(
1379
+ pointer,
1380
+ undefined,
1381
+ target.group.calcTransformMatrix()
1382
+ )
1383
+ : pointer;
1384
+ // seems used only here.
1385
+ // @TODO: investigate;
1386
+ // @ts-ignore
1387
+ transform.reset = false;
1388
+ transform.shiftKey = e.shiftKey;
1389
+ transform.altKey = !!this.centeredKey && e[this.centeredKey];
1390
+
1391
+ this._performTransformAction(e, transform, localPointer);
1392
+ transform.actionPerformed && this.requestRenderAll();
1393
+ }
1394
+
1395
+ /**
1396
+ * @private
1397
+ */
1398
+ _performTransformAction(
1399
+ e: TPointerEvent,
1400
+ transform: Transform,
1401
+ pointer: Point
1402
+ ) {
1403
+ const x = pointer.x,
1404
+ y = pointer.y,
1405
+ action = transform.action,
1406
+ actionHandler = transform.actionHandler;
1407
+ let actionPerformed = false;
1408
+ // this object could be created from the function in the control handlers
1409
+
1410
+ if (actionHandler) {
1411
+ actionPerformed = actionHandler(e, transform, x, y);
1412
+ }
1413
+ if (action === 'drag' && actionPerformed) {
1414
+ transform.target.isMoving = true;
1415
+ this.setCursor(transform.target.moveCursor || this.moveCursor);
1416
+ }
1417
+ transform.actionPerformed = transform.actionPerformed || actionPerformed;
1418
+ }
1419
+
1420
+ /**
1421
+ * Sets the cursor depending on where the canvas is being hovered.
1422
+ * Note: very buggy in Opera
1423
+ * @param {Event} e Event object
1424
+ * @param {Object} target Object that the mouse is hovering, if so.
1425
+ */
1426
+ _setCursorFromEvent(e: TPointerEvent, target?: FabricObject) {
1427
+ if (!target) {
1428
+ this.setCursor(this.defaultCursor);
1429
+ return;
1430
+ }
1431
+ let hoverCursor = target.hoverCursor || this.hoverCursor;
1432
+ const activeSelection = isActiveSelection(this._activeObject)
1433
+ ? this._activeObject
1434
+ : null,
1435
+ // only show proper corner when group selection is not active
1436
+ corner =
1437
+ (!activeSelection || !activeSelection.contains(target)) &&
1438
+ // here we call findTargetCorner always with undefined for the touch parameter.
1439
+ // we assume that if you are using a cursor you do not need to interact with
1440
+ // the bigger touch area.
1441
+ target._findTargetCorner(this.getPointer(e, true));
1442
+
1443
+ if (!corner) {
1444
+ if ((target as Group).subTargetCheck) {
1445
+ // hoverCursor should come from top-most subTarget,
1446
+ // so we walk the array backwards
1447
+ this.targets
1448
+ .concat()
1449
+ .reverse()
1450
+ .map((_target) => {
1451
+ hoverCursor = _target.hoverCursor || hoverCursor;
1452
+ });
1453
+ }
1454
+ this.setCursor(hoverCursor);
1455
+ } else {
1456
+ const control = target.controls[corner];
1457
+ this.setCursor(control.cursorStyleHandler(e, control, target));
1458
+ }
1459
+ }
1460
+
1461
+ // Grouping objects mixin
1462
+
1463
+ /**
1464
+ * Return true if the current mouse event that generated a new selection should generate a group
1465
+ * @private
1466
+ * @param {TPointerEvent} e Event object
1467
+ * @param {FabricObject} target
1468
+ * @return {Boolean}
1469
+ */
1470
+ _shouldGroup(e: TPointerEvent, target?: FabricObject): boolean {
1471
+ const activeObject = this._activeObject;
1472
+ // check if an active object exists on canvas and if the user is pressing the `selectionKey` while canvas supports multi selection.
1473
+ return (
1474
+ !!activeObject &&
1475
+ this._isSelectionKeyPressed(e) &&
1476
+ this.selection &&
1477
+ // on top of that the user also has to hit a target that is selectable.
1478
+ !!target &&
1479
+ target.selectable &&
1480
+ // if all pre-requisite pass, the target is either something different from the current
1481
+ // activeObject or if an activeSelection already exists
1482
+ // TODO at time of writing why `activeObject.type === 'activeSelection'` matter is unclear.
1483
+ // is a very old condition uncertain if still valid.
1484
+ (activeObject !== target || activeObject.type === 'activeSelection') &&
1485
+ // make sure `activeObject` and `target` aren't ancestors of each other
1486
+ !target.isDescendantOf(activeObject) &&
1487
+ !activeObject.isDescendantOf(target) &&
1488
+ // target accepts selection
1489
+ !target.onSelect({ e: e })
1490
+ );
1491
+ }
1492
+
1493
+ /**
1494
+ * Handles active selection creation for user event
1495
+ * @private
1496
+ * @param {TPointerEvent} e Event object
1497
+ * @param {FabricObject} target
1498
+ */
1499
+ _handleGrouping(e: TPointerEvent, target: FabricObject) {
1500
+ let groupingTarget: FabricObject | undefined = target;
1501
+ // Called always a shouldGroup, meaning that we can trust this._activeObject exists.
1502
+ const activeObject = this._activeObject!;
1503
+ // avoid multi select when shift click on a corner
1504
+ if (activeObject.__corner) {
1505
+ return;
1506
+ }
1507
+ if (groupingTarget === activeObject) {
1508
+ // if it's a group, find target again, using activeGroup objects
1509
+ groupingTarget = this.findTarget(e, true);
1510
+ // if even object is not found or we are on activeObjectCorner, bail out
1511
+ if (!groupingTarget || !groupingTarget.selectable) {
1512
+ return;
1513
+ }
1514
+ }
1515
+ if (activeObject && activeObject.type === 'activeSelection') {
1516
+ this._updateActiveSelection(e, groupingTarget);
1517
+ } else {
1518
+ this._createActiveSelection(e, groupingTarget);
1519
+ }
1520
+ }
1521
+
1522
+ /**
1523
+ * @private
1524
+ */
1525
+ _updateActiveSelection(e: TPointerEvent, target: FabricObject) {
1526
+ const activeSelection = this._activeObject! as ActiveSelection,
1527
+ currentActiveObjects = activeSelection.getObjects();
1528
+ if (target.group === activeSelection) {
1529
+ activeSelection.remove(target);
1530
+ this._hoveredTarget = target;
1531
+ this._hoveredTargets = this.targets.concat();
1532
+ if (activeSelection.size() === 1) {
1533
+ // activate last remaining object
1534
+ this._setActiveObject(activeSelection.item(0) as FabricObject, e);
1535
+ }
1536
+ } else {
1537
+ activeSelection.add(target);
1538
+ this._hoveredTarget = activeSelection;
1539
+ this._hoveredTargets = this.targets.concat();
1540
+ }
1541
+ this._fireSelectionEvents(currentActiveObjects as FabricObject[], e);
1542
+ }
1543
+
1544
+ /**
1545
+ * Generates and set as active the active selection from user events
1546
+ * @private
1547
+ */
1548
+ _createActiveSelection(e: TPointerEvent, target: FabricObject) {
1549
+ const currentActive = this.getActiveObject()!;
1550
+ const groupObjects = target.isInFrontOf(currentActive)
1551
+ ? [currentActive, target]
1552
+ : [target, currentActive];
1553
+ // @ts-ignore
1554
+ currentActive.isEditing && currentActive.exitEditing();
1555
+ // handle case: target is nested
1556
+ const newActiveSelection = new ActiveSelection(groupObjects, {
1557
+ canvas: this,
1558
+ });
1559
+ this._hoveredTarget = newActiveSelection;
1560
+ // ISSUE 4115: should we consider subTargets here?
1561
+ // this._hoveredTargets = [];
1562
+ // this._hoveredTargets = this.targets.concat();
1563
+ this._setActiveObject(newActiveSelection, e);
1564
+ this._fireSelectionEvents([currentActive], e);
1565
+ }
1566
+
1567
+ /**
1568
+ * Finds objects inside the selection rectangle and group them
1569
+ * @private
1570
+ * @param {Event} e mouse event
1571
+ */
1572
+ _groupSelectedObjects(e: TPointerEvent) {
1573
+ const group = this._collectObjects(e);
1574
+ // do not create group for 1 element only
1575
+ if (group.length === 1) {
1576
+ this.setActiveObject(group[0], e);
1577
+ } else if (group.length > 1) {
1578
+ const aGroup = new ActiveSelection(group.reverse(), {
1579
+ canvas: this,
1580
+ });
1581
+ this.setActiveObject(aGroup, e);
1582
+ }
1583
+ }
1584
+
1585
+ /**
1586
+ * @private
1587
+ */
1588
+ _collectObjects(e: TPointerEvent) {
1589
+ const group: FabricObject[] = [],
1590
+ _groupSelector = this._groupSelector,
1591
+ point1 = new Point(_groupSelector.ex, _groupSelector.ey),
1592
+ point2 = point1.add(new Point(_groupSelector.left, _groupSelector.top)),
1593
+ selectionX1Y1 = point1.min(point2),
1594
+ selectionX2Y2 = point1.max(point2),
1595
+ allowIntersect = !this.selectionFullyContained,
1596
+ isClick = point1.eq(point2);
1597
+ // we iterate reverse order to collect top first in case of click.
1598
+ for (let i = this._objects.length; i--; ) {
1599
+ const currentObject = this._objects[i];
1600
+
1601
+ if (
1602
+ !currentObject ||
1603
+ !currentObject.selectable ||
1604
+ !currentObject.visible
1605
+ ) {
1606
+ continue;
1607
+ }
1608
+
1609
+ if (
1610
+ (allowIntersect &&
1611
+ currentObject.intersectsWithRect(
1612
+ selectionX1Y1,
1613
+ selectionX2Y2,
1614
+ true
1615
+ )) ||
1616
+ currentObject.isContainedWithinRect(
1617
+ selectionX1Y1,
1618
+ selectionX2Y2,
1619
+ true
1620
+ ) ||
1621
+ (allowIntersect &&
1622
+ currentObject.containsPoint(selectionX1Y1, undefined, true)) ||
1623
+ (allowIntersect &&
1624
+ currentObject.containsPoint(selectionX2Y2, undefined, true))
1625
+ ) {
1626
+ group.push(currentObject);
1627
+ // only add one object if it's a click
1628
+ if (isClick) {
1629
+ break;
1630
+ }
1631
+ }
1632
+ }
1633
+
1634
+ if (group.length > 1) {
1635
+ return group.filter((object) => !object.onSelect({ e }));
1636
+ }
1637
+
1638
+ return group;
1639
+ }
1640
+
1641
+ /**
1642
+ * @private
1643
+ */
1644
+ _maybeGroupObjects(e: TPointerEvent) {
1645
+ if (this.selection && this._groupSelector) {
1646
+ this._groupSelectedObjects(e);
1647
+ }
1648
+ this.setCursor(this.defaultCursor);
1649
+ // clear selection and current transformation
1650
+ this._groupSelector = null;
1651
+ }
1652
+
1653
+ exitTextEditing() {
1654
+ this.textEditingManager.exitTextEditing();
1655
+ }
1656
+
1657
+ /**
1658
+ * @override clear {@link textEditingManager}
1659
+ */
1660
+ clear() {
1661
+ this.textEditingManager.dispose();
1662
+ super.clear();
1663
+ }
1664
+
1665
+ /**
1666
+ * @override clear {@link textEditingManager}
1667
+ */
1668
+ destroy() {
1669
+ super.destroy();
1670
+ this.textEditingManager.dispose();
1671
+ }
1672
+ }