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,1055 @@
1
+ import { getEnv } from '../../env';
2
+ import {
3
+ ObjectEvents,
4
+ TPointerEvent,
5
+ TPointerEventInfo,
6
+ } from '../../EventTypeDefs';
7
+ import { Point } from '../../Point';
8
+ import type { FabricObject } from '../Object/Object';
9
+ import { Text } from '../Text/Text';
10
+ import { animate } from '../../util/animation/animate';
11
+ import { TOnAnimationChangeCallback } from '../../util/animation/types';
12
+ import type { ValueAnimation } from '../../util/animation/ValueAnimation';
13
+ import { TextStyleDeclaration } from '../Text/StyledText';
14
+
15
+ // extend this regex to support non english languages
16
+ const reNonWord = /[ \n\.,;!\?\-]/;
17
+
18
+ export type ITextEvents = ObjectEvents & {
19
+ 'selection:changed': never;
20
+ changed: never | { index: number; action: string };
21
+ tripleclick: TPointerEventInfo;
22
+ 'editing:entered': never | { e: TPointerEvent };
23
+ 'editing:exited': never;
24
+ };
25
+
26
+ export abstract class ITextBehavior<
27
+ EventSpec extends ITextEvents = ITextEvents
28
+ > extends Text<EventSpec> {
29
+ declare abstract isEditing: boolean;
30
+ declare abstract cursorDelay: number;
31
+ declare abstract selectionStart: number;
32
+ declare abstract selectionEnd: number;
33
+ declare abstract cursorDuration: number;
34
+ declare abstract editable: boolean;
35
+ declare abstract editingBorderColor: string;
36
+
37
+ declare abstract compositionStart: number;
38
+ declare abstract compositionEnd: number;
39
+
40
+ declare abstract hiddenTextarea: HTMLTextAreaElement | null;
41
+
42
+ /**
43
+ * Helps determining when the text is in composition, so that the cursor
44
+ * rendering is altered.
45
+ */
46
+ protected declare inCompositionMode: boolean;
47
+
48
+ protected declare _reSpace: RegExp;
49
+ private declare _currentTickState?: ValueAnimation;
50
+ private declare _currentTickCompleteState?: ValueAnimation;
51
+ protected _currentCursorOpacity = 1;
52
+ private declare _textBeforeEdit: string;
53
+ protected declare __selectionStartOnMouseDown: number;
54
+
55
+ protected declare selected: boolean;
56
+ protected declare cursorOffsetCache: { left?: number; top?: number };
57
+ protected declare _savedProps?: {
58
+ hasControls: boolean;
59
+ borderColor: string;
60
+ lockMovementX: boolean;
61
+ lockMovementY: boolean;
62
+ selectable: boolean;
63
+ hoverCursor: CSSStyleDeclaration['cursor'] | null;
64
+ defaultCursor?: CSSStyleDeclaration['cursor'];
65
+ moveCursor?: CSSStyleDeclaration['cursor'];
66
+ };
67
+ protected declare _selectionDirection: 'left' | 'right' | null;
68
+
69
+ abstract initHiddenTextarea(): void;
70
+ abstract _fireSelectionChanged(): void;
71
+ abstract renderCursorOrSelection(): void;
72
+ abstract getSelectionStartFromPointer(e: TPointerEvent): number;
73
+ abstract _getCursorBoundaries(
74
+ index: number,
75
+ skipCaching?: boolean
76
+ ): {
77
+ left: number;
78
+ top: number;
79
+ leftOffset: number;
80
+ topOffset: number;
81
+ };
82
+
83
+ /**
84
+ * Initializes all the interactive behavior of IText
85
+ */
86
+ initBehavior() {
87
+ this._tick = this._tick.bind(this);
88
+ this._onTickComplete = this._onTickComplete.bind(this);
89
+ this.updateSelectionOnMouseMove =
90
+ this.updateSelectionOnMouseMove.bind(this);
91
+ }
92
+
93
+ onDeselect(options?: { e?: TPointerEvent; object?: FabricObject }) {
94
+ this.isEditing && this.exitEditing();
95
+ this.selected = false;
96
+ return super.onDeselect(options);
97
+ }
98
+
99
+ /**
100
+ * @private
101
+ */
102
+ _animateCursor({
103
+ toValue,
104
+ duration,
105
+ delay,
106
+ onComplete,
107
+ }: {
108
+ toValue: number;
109
+ duration: number;
110
+ delay?: number;
111
+ onComplete?: TOnAnimationChangeCallback<number, void>;
112
+ }) {
113
+ return animate({
114
+ startValue: this._currentCursorOpacity,
115
+ endValue: toValue,
116
+ duration,
117
+ delay,
118
+ onComplete,
119
+ abort: () => {
120
+ return (
121
+ !this.canvas ||
122
+ // we do not want to animate a selection, only cursor
123
+ this.selectionStart !== this.selectionEnd
124
+ );
125
+ },
126
+ onChange: (value) => {
127
+ this._currentCursorOpacity = value;
128
+ this.renderCursorOrSelection();
129
+ },
130
+ });
131
+ }
132
+
133
+ private _tick(delay?: number) {
134
+ this._currentTickState = this._animateCursor({
135
+ toValue: 1,
136
+ duration: this.cursorDuration,
137
+ delay,
138
+ onComplete: this._onTickComplete,
139
+ });
140
+ }
141
+
142
+ private _onTickComplete() {
143
+ this._currentTickCompleteState?.abort();
144
+ this._currentTickCompleteState = this._animateCursor({
145
+ toValue: 0,
146
+ duration: this.cursorDuration / 2,
147
+ delay: 100,
148
+ onComplete: this._tick,
149
+ });
150
+ }
151
+
152
+ /**
153
+ * Initializes delayed cursor
154
+ */
155
+ initDelayedCursor(restart?: boolean) {
156
+ this.abortCursorAnimation();
157
+ this._tick(restart ? 0 : this.cursorDelay);
158
+ }
159
+
160
+ /**
161
+ * Aborts cursor animation, clears all timeouts and clear textarea context if necessary
162
+ */
163
+ abortCursorAnimation() {
164
+ let shouldClear = false;
165
+ [this._currentTickState, this._currentTickCompleteState].forEach(
166
+ (cursorAnimation) => {
167
+ if (cursorAnimation && !cursorAnimation.isDone()) {
168
+ shouldClear = true;
169
+ cursorAnimation.abort();
170
+ }
171
+ }
172
+ );
173
+
174
+ this._currentCursorOpacity = 1;
175
+
176
+ // make sure we clear context even if instance is not editing
177
+ if (shouldClear) {
178
+ this.clearContextTop();
179
+ }
180
+ }
181
+
182
+ restartCursorIfNeeded() {
183
+ if (
184
+ [this._currentTickState, this._currentTickCompleteState].some(
185
+ (cursorAnimation) => !cursorAnimation || cursorAnimation.isDone()
186
+ )
187
+ ) {
188
+ this.initDelayedCursor();
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Selects entire text
194
+ */
195
+ selectAll() {
196
+ this.selectionStart = 0;
197
+ this.selectionEnd = this._text.length;
198
+ this._fireSelectionChanged();
199
+ this._updateTextarea();
200
+ return this;
201
+ }
202
+
203
+ /**
204
+ * Returns selected text
205
+ * @return {String}
206
+ */
207
+ getSelectedText(): string {
208
+ return this._text.slice(this.selectionStart, this.selectionEnd).join('');
209
+ }
210
+
211
+ /**
212
+ * Find new selection index representing start of current word according to current selection index
213
+ * @param {Number} startFrom Current selection index
214
+ * @return {Number} New selection index
215
+ */
216
+ findWordBoundaryLeft(startFrom: number): number {
217
+ let offset = 0,
218
+ index = startFrom - 1;
219
+
220
+ // remove space before cursor first
221
+ if (this._reSpace.test(this._text[index])) {
222
+ while (this._reSpace.test(this._text[index])) {
223
+ offset++;
224
+ index--;
225
+ }
226
+ }
227
+ while (/\S/.test(this._text[index]) && index > -1) {
228
+ offset++;
229
+ index--;
230
+ }
231
+
232
+ return startFrom - offset;
233
+ }
234
+
235
+ /**
236
+ * Find new selection index representing end of current word according to current selection index
237
+ * @param {Number} startFrom Current selection index
238
+ * @return {Number} New selection index
239
+ */
240
+ findWordBoundaryRight(startFrom: number): number {
241
+ let offset = 0,
242
+ index = startFrom;
243
+
244
+ // remove space after cursor first
245
+ if (this._reSpace.test(this._text[index])) {
246
+ while (this._reSpace.test(this._text[index])) {
247
+ offset++;
248
+ index++;
249
+ }
250
+ }
251
+ while (/\S/.test(this._text[index]) && index < this._text.length) {
252
+ offset++;
253
+ index++;
254
+ }
255
+
256
+ return startFrom + offset;
257
+ }
258
+
259
+ /**
260
+ * Find new selection index representing start of current line according to current selection index
261
+ * @param {Number} startFrom Current selection index
262
+ * @return {Number} New selection index
263
+ */
264
+ findLineBoundaryLeft(startFrom: number): number {
265
+ let offset = 0,
266
+ index = startFrom - 1;
267
+
268
+ while (!/\n/.test(this._text[index]) && index > -1) {
269
+ offset++;
270
+ index--;
271
+ }
272
+
273
+ return startFrom - offset;
274
+ }
275
+
276
+ /**
277
+ * Find new selection index representing end of current line according to current selection index
278
+ * @param {Number} startFrom Current selection index
279
+ * @return {Number} New selection index
280
+ */
281
+ findLineBoundaryRight(startFrom: number): number {
282
+ let offset = 0,
283
+ index = startFrom;
284
+
285
+ while (!/\n/.test(this._text[index]) && index < this._text.length) {
286
+ offset++;
287
+ index++;
288
+ }
289
+
290
+ return startFrom + offset;
291
+ }
292
+
293
+ /**
294
+ * Finds index corresponding to beginning or end of a word
295
+ * @param {Number} selectionStart Index of a character
296
+ * @param {Number} direction 1 or -1
297
+ * @return {Number} Index of the beginning or end of a word
298
+ */
299
+ searchWordBoundary(selectionStart: number, direction: number): number {
300
+ const text = this._text;
301
+ let index = this._reSpace.test(text[selectionStart])
302
+ ? selectionStart - 1
303
+ : selectionStart,
304
+ _char = text[index];
305
+
306
+ while (!reNonWord.test(_char) && index > 0 && index < text.length) {
307
+ index += direction;
308
+ _char = text[index];
309
+ }
310
+ if (reNonWord.test(_char)) {
311
+ index += direction === 1 ? 0 : 1;
312
+ }
313
+ return index;
314
+ }
315
+
316
+ /**
317
+ * Selects a word based on the index
318
+ * @param {Number} selectionStart Index of a character
319
+ */
320
+ selectWord(selectionStart: number) {
321
+ selectionStart = selectionStart || this.selectionStart;
322
+ const newSelectionStart = this.searchWordBoundary(
323
+ selectionStart,
324
+ -1
325
+ ) /* search backwards */,
326
+ newSelectionEnd = this.searchWordBoundary(
327
+ selectionStart,
328
+ 1
329
+ ); /* search forward */
330
+
331
+ this.selectionStart = newSelectionStart;
332
+ this.selectionEnd = newSelectionEnd;
333
+ this._fireSelectionChanged();
334
+ this._updateTextarea();
335
+ this.renderCursorOrSelection();
336
+ }
337
+
338
+ /**
339
+ * Selects a line based on the index
340
+ * @param {Number} selectionStart Index of a character
341
+ */
342
+ selectLine(selectionStart: number) {
343
+ selectionStart = selectionStart || this.selectionStart;
344
+ const newSelectionStart = this.findLineBoundaryLeft(selectionStart),
345
+ newSelectionEnd = this.findLineBoundaryRight(selectionStart);
346
+
347
+ this.selectionStart = newSelectionStart;
348
+ this.selectionEnd = newSelectionEnd;
349
+ this._fireSelectionChanged();
350
+ this._updateTextarea();
351
+ return this;
352
+ }
353
+
354
+ /**
355
+ * Enters editing state
356
+ */
357
+ enterEditing(e: TPointerEvent) {
358
+ if (this.isEditing || !this.editable) {
359
+ return;
360
+ }
361
+ if (this.canvas) {
362
+ this.canvas.calcOffset();
363
+ this.canvas.textEditingManager.exitTextEditing();
364
+ }
365
+
366
+ this.isEditing = true;
367
+
368
+ this.initHiddenTextarea();
369
+ this.hiddenTextarea!.focus();
370
+ this.hiddenTextarea!.value = this.text;
371
+ this._updateTextarea();
372
+ this._saveEditingProps();
373
+ this._setEditingProps();
374
+ this._textBeforeEdit = this.text;
375
+
376
+ this._tick();
377
+ this.fire('editing:entered', { e });
378
+ this._fireSelectionChanged();
379
+ if (this.canvas) {
380
+ // @ts-expect-error in reality it is an IText instance
381
+ this.canvas.fire('text:editing:entered', { target: this, e });
382
+ this.canvas.requestRenderAll();
383
+ }
384
+ }
385
+
386
+ /**
387
+ * called by {@link canvas#textEditingManager}
388
+ */
389
+ updateSelectionOnMouseMove(e: TPointerEvent) {
390
+ // regain focus
391
+ getEnv().document.activeElement !== this.hiddenTextarea &&
392
+ this.hiddenTextarea!.focus();
393
+
394
+ const newSelectionStart = this.getSelectionStartFromPointer(e),
395
+ currentStart = this.selectionStart,
396
+ currentEnd = this.selectionEnd;
397
+ if (
398
+ (newSelectionStart !== this.__selectionStartOnMouseDown ||
399
+ currentStart === currentEnd) &&
400
+ (currentStart === newSelectionStart || currentEnd === newSelectionStart)
401
+ ) {
402
+ return;
403
+ }
404
+ if (newSelectionStart > this.__selectionStartOnMouseDown) {
405
+ this.selectionStart = this.__selectionStartOnMouseDown;
406
+ this.selectionEnd = newSelectionStart;
407
+ } else {
408
+ this.selectionStart = newSelectionStart;
409
+ this.selectionEnd = this.__selectionStartOnMouseDown;
410
+ }
411
+ if (
412
+ this.selectionStart !== currentStart ||
413
+ this.selectionEnd !== currentEnd
414
+ ) {
415
+ this._fireSelectionChanged();
416
+ this._updateTextarea();
417
+ this.renderCursorOrSelection();
418
+ }
419
+ }
420
+
421
+ /**
422
+ * @private
423
+ */
424
+ _setEditingProps() {
425
+ this.hoverCursor = 'text';
426
+
427
+ if (this.canvas) {
428
+ this.canvas.defaultCursor = this.canvas.moveCursor = 'text';
429
+ }
430
+
431
+ this.borderColor = this.editingBorderColor;
432
+ this.hasControls = this.selectable = false;
433
+ this.lockMovementX = this.lockMovementY = true;
434
+ }
435
+
436
+ /**
437
+ * convert from textarea to grapheme indexes
438
+ */
439
+ fromStringToGraphemeSelection(start: number, end: number, text: string) {
440
+ const smallerTextStart = text.slice(0, start),
441
+ graphemeStart = this.graphemeSplit(smallerTextStart).length;
442
+ if (start === end) {
443
+ return { selectionStart: graphemeStart, selectionEnd: graphemeStart };
444
+ }
445
+ const smallerTextEnd = text.slice(start, end),
446
+ graphemeEnd = this.graphemeSplit(smallerTextEnd).length;
447
+ return {
448
+ selectionStart: graphemeStart,
449
+ selectionEnd: graphemeStart + graphemeEnd,
450
+ };
451
+ }
452
+
453
+ /**
454
+ * convert from fabric to textarea values
455
+ */
456
+ fromGraphemeToStringSelection(
457
+ start: number,
458
+ end: number,
459
+ graphemes: string[]
460
+ ) {
461
+ const smallerTextStart = graphemes.slice(0, start),
462
+ graphemeStart = smallerTextStart.join('').length;
463
+ if (start === end) {
464
+ return { selectionStart: graphemeStart, selectionEnd: graphemeStart };
465
+ }
466
+ const smallerTextEnd = graphemes.slice(start, end),
467
+ graphemeEnd = smallerTextEnd.join('').length;
468
+ return {
469
+ selectionStart: graphemeStart,
470
+ selectionEnd: graphemeStart + graphemeEnd,
471
+ };
472
+ }
473
+
474
+ /**
475
+ * @private
476
+ */
477
+ _updateTextarea() {
478
+ this.cursorOffsetCache = {};
479
+ if (!this.hiddenTextarea) {
480
+ return;
481
+ }
482
+ if (!this.inCompositionMode) {
483
+ const newSelection = this.fromGraphemeToStringSelection(
484
+ this.selectionStart,
485
+ this.selectionEnd,
486
+ this._text
487
+ );
488
+ this.hiddenTextarea.selectionStart = newSelection.selectionStart;
489
+ this.hiddenTextarea.selectionEnd = newSelection.selectionEnd;
490
+ }
491
+ this.updateTextareaPosition();
492
+ }
493
+
494
+ /**
495
+ * @private
496
+ */
497
+ updateFromTextArea() {
498
+ if (!this.hiddenTextarea) {
499
+ return;
500
+ }
501
+ this.cursorOffsetCache = {};
502
+ this.text = this.hiddenTextarea.value;
503
+ if (this._shouldClearDimensionCache()) {
504
+ this.initDimensions();
505
+ this.setCoords();
506
+ }
507
+ const newSelection = this.fromStringToGraphemeSelection(
508
+ this.hiddenTextarea.selectionStart,
509
+ this.hiddenTextarea.selectionEnd,
510
+ this.hiddenTextarea.value
511
+ );
512
+ this.selectionEnd = this.selectionStart = newSelection.selectionEnd;
513
+ if (!this.inCompositionMode) {
514
+ this.selectionStart = newSelection.selectionStart;
515
+ }
516
+ this.updateTextareaPosition();
517
+ }
518
+
519
+ /**
520
+ * @private
521
+ */
522
+ updateTextareaPosition() {
523
+ if (this.selectionStart === this.selectionEnd) {
524
+ const style = this._calcTextareaPosition();
525
+ this.hiddenTextarea!.style.left = style.left;
526
+ this.hiddenTextarea!.style.top = style.top;
527
+ }
528
+ }
529
+
530
+ /**
531
+ * @private
532
+ * @return {Object} style contains style for hiddenTextarea
533
+ */
534
+ _calcTextareaPosition() {
535
+ if (!this.canvas) {
536
+ return { left: '1px', top: '1px' };
537
+ }
538
+ const desiredPosition = this.inCompositionMode
539
+ ? this.compositionStart
540
+ : this.selectionStart,
541
+ boundaries = this._getCursorBoundaries(desiredPosition),
542
+ cursorLocation = this.get2DCursorLocation(desiredPosition),
543
+ lineIndex = cursorLocation.lineIndex,
544
+ charIndex = cursorLocation.charIndex,
545
+ charHeight =
546
+ this.getValueOfPropertyAt(lineIndex, charIndex, 'fontSize') *
547
+ this.lineHeight,
548
+ leftOffset = boundaries.leftOffset,
549
+ retinaScaling = this.getCanvasRetinaScaling(),
550
+ upperCanvas = this.canvas.upperCanvasEl,
551
+ upperCanvasWidth = upperCanvas.width / retinaScaling,
552
+ upperCanvasHeight = upperCanvas.height / retinaScaling,
553
+ maxWidth = upperCanvasWidth - charHeight,
554
+ maxHeight = upperCanvasHeight - charHeight;
555
+
556
+ const p = new Point(
557
+ boundaries.left + leftOffset,
558
+ boundaries.top + boundaries.topOffset + charHeight
559
+ )
560
+ .transform(this.calcTransformMatrix())
561
+ .transform(this.canvas.viewportTransform)
562
+ .multiply(
563
+ new Point(
564
+ upperCanvas.clientWidth / upperCanvasWidth,
565
+ upperCanvas.clientHeight / upperCanvasHeight
566
+ )
567
+ );
568
+
569
+ if (p.x < 0) {
570
+ p.x = 0;
571
+ }
572
+ if (p.x > maxWidth) {
573
+ p.x = maxWidth;
574
+ }
575
+ if (p.y < 0) {
576
+ p.y = 0;
577
+ }
578
+ if (p.y > maxHeight) {
579
+ p.y = maxHeight;
580
+ }
581
+
582
+ // add canvas offset on document
583
+ p.x += this.canvas._offset.left;
584
+ p.y += this.canvas._offset.top;
585
+
586
+ return {
587
+ left: `${p.x}px`,
588
+ top: `${p.y}px`,
589
+ fontSize: `${charHeight}px`,
590
+ charHeight: charHeight,
591
+ };
592
+ }
593
+
594
+ /**
595
+ * @private
596
+ */
597
+ _saveEditingProps() {
598
+ this._savedProps = {
599
+ hasControls: this.hasControls,
600
+ borderColor: this.borderColor,
601
+ lockMovementX: this.lockMovementX,
602
+ lockMovementY: this.lockMovementY,
603
+ hoverCursor: this.hoverCursor,
604
+ selectable: this.selectable,
605
+ defaultCursor: this.canvas && this.canvas.defaultCursor,
606
+ moveCursor: this.canvas && this.canvas.moveCursor,
607
+ };
608
+ }
609
+
610
+ /**
611
+ * @private
612
+ */
613
+ _restoreEditingProps() {
614
+ if (!this._savedProps) {
615
+ return;
616
+ }
617
+
618
+ this.hoverCursor = this._savedProps.hoverCursor;
619
+ this.hasControls = this._savedProps.hasControls;
620
+ this.borderColor = this._savedProps.borderColor;
621
+ this.selectable = this._savedProps.selectable;
622
+ this.lockMovementX = this._savedProps.lockMovementX;
623
+ this.lockMovementY = this._savedProps.lockMovementY;
624
+
625
+ if (this.canvas) {
626
+ this.canvas.defaultCursor =
627
+ this._savedProps.defaultCursor || this.canvas.defaultCursor;
628
+ this.canvas.moveCursor =
629
+ this._savedProps.moveCursor || this.canvas.moveCursor;
630
+ }
631
+
632
+ delete this._savedProps;
633
+ }
634
+
635
+ /**
636
+ * runs the actual logic that exits from editing state, see {@link exitEditing}
637
+ */
638
+ protected _exitEditing() {
639
+ const hiddenTextarea = this.hiddenTextarea;
640
+ this.selected = false;
641
+ this.isEditing = false;
642
+
643
+ if (hiddenTextarea) {
644
+ hiddenTextarea.blur && hiddenTextarea.blur();
645
+ hiddenTextarea.parentNode &&
646
+ hiddenTextarea.parentNode.removeChild(hiddenTextarea);
647
+ }
648
+ this.hiddenTextarea = null;
649
+ this.abortCursorAnimation();
650
+ }
651
+
652
+ /**
653
+ * Exits from editing state and fires relevant events
654
+ */
655
+ exitEditing() {
656
+ const isTextChanged = this._textBeforeEdit !== this.text;
657
+ this.selectionEnd = this.selectionStart;
658
+ this._exitEditing();
659
+ this._restoreEditingProps();
660
+ if (this._shouldClearDimensionCache()) {
661
+ this.initDimensions();
662
+ this.setCoords();
663
+ }
664
+ this.fire('editing:exited');
665
+ isTextChanged && this.fire('modified');
666
+ if (this.canvas) {
667
+ // @ts-expect-error in reality it is an IText instance
668
+ this.canvas.fire('text:editing:exited', { target: this });
669
+ isTextChanged && this.canvas.fire('object:modified', { target: this });
670
+ }
671
+ return this;
672
+ }
673
+
674
+ /**
675
+ * @private
676
+ */
677
+ _removeExtraneousStyles() {
678
+ for (const prop in this.styles) {
679
+ if (!this._textLines[prop as unknown as number]) {
680
+ delete this.styles[prop];
681
+ }
682
+ }
683
+ }
684
+
685
+ /**
686
+ * remove and reflow a style block from start to end.
687
+ * @param {Number} start linear start position for removal (included in removal)
688
+ * @param {Number} end linear end position for removal ( excluded from removal )
689
+ */
690
+ removeStyleFromTo(start: number, end: number) {
691
+ const { lineIndex: lineStart, charIndex: charStart } =
692
+ this.get2DCursorLocation(start, true),
693
+ { lineIndex: lineEnd, charIndex: charEnd } = this.get2DCursorLocation(
694
+ end,
695
+ true
696
+ );
697
+ if (lineStart !== lineEnd) {
698
+ // step1 remove the trailing of lineStart
699
+ if (this.styles[lineStart]) {
700
+ for (
701
+ let i = charStart;
702
+ i < this._unwrappedTextLines[lineStart].length;
703
+ i++
704
+ ) {
705
+ delete this.styles[lineStart][i];
706
+ }
707
+ }
708
+ // step2 move the trailing of lineEnd to lineStart if needed
709
+ if (this.styles[lineEnd]) {
710
+ for (
711
+ let i = charEnd;
712
+ i < this._unwrappedTextLines[lineEnd].length;
713
+ i++
714
+ ) {
715
+ const styleObj = this.styles[lineEnd][i];
716
+ if (styleObj) {
717
+ this.styles[lineStart] || (this.styles[lineStart] = {});
718
+ this.styles[lineStart][charStart + i - charEnd] = styleObj;
719
+ }
720
+ }
721
+ }
722
+ // step3 detects lines will be completely removed.
723
+ for (let i = lineStart + 1; i <= lineEnd; i++) {
724
+ delete this.styles[i];
725
+ }
726
+ // step4 shift remaining lines.
727
+ this.shiftLineStyles(lineEnd, lineStart - lineEnd);
728
+ } else {
729
+ // remove and shift left on the same line
730
+ if (this.styles[lineStart]) {
731
+ const styleObj = this.styles[lineStart];
732
+ const diff = charEnd - charStart;
733
+ for (let i = charStart; i < charEnd; i++) {
734
+ delete styleObj[i];
735
+ }
736
+ for (const char in this.styles[lineStart]) {
737
+ const numericChar = parseInt(char, 10);
738
+ if (numericChar >= charEnd) {
739
+ styleObj[numericChar - diff] = styleObj[char];
740
+ delete styleObj[char];
741
+ }
742
+ }
743
+ }
744
+ }
745
+ }
746
+
747
+ /**
748
+ * Shifts line styles up or down
749
+ * @param {Number} lineIndex Index of a line
750
+ * @param {Number} offset Can any number?
751
+ */
752
+ shiftLineStyles(lineIndex: number, offset: number) {
753
+ const clonedStyles = Object.assign({}, this.styles);
754
+ for (const line in this.styles) {
755
+ const numericLine = parseInt(line, 10);
756
+ if (numericLine > lineIndex) {
757
+ this.styles[numericLine + offset] = clonedStyles[numericLine];
758
+ if (!clonedStyles[numericLine - offset]) {
759
+ delete this.styles[numericLine];
760
+ }
761
+ }
762
+ }
763
+ }
764
+
765
+ /**
766
+ * Handle insertion of more consecutive style lines for when one or more
767
+ * newlines gets added to the text. Since current style needs to be shifted
768
+ * first we shift the current style of the number lines needed, then we add
769
+ * new lines from the last to the first.
770
+ * @param {Number} lineIndex Index of a line
771
+ * @param {Number} charIndex Index of a char
772
+ * @param {Number} qty number of lines to add
773
+ * @param {Array} copiedStyle Array of objects styles
774
+ */
775
+ insertNewlineStyleObject(
776
+ lineIndex: number,
777
+ charIndex: number,
778
+ qty: number,
779
+ copiedStyle?: { [index: number]: TextStyleDeclaration }
780
+ ) {
781
+ const newLineStyles: { [index: number]: TextStyleDeclaration } = {};
782
+ const isEndOfLine =
783
+ this._unwrappedTextLines[lineIndex].length === charIndex;
784
+ let somethingAdded = false;
785
+ qty || (qty = 1);
786
+ this.shiftLineStyles(lineIndex, qty);
787
+ const currentCharStyle = this.styles[lineIndex]
788
+ ? this.styles[lineIndex][charIndex === 0 ? charIndex : charIndex - 1]
789
+ : undefined;
790
+
791
+ // we clone styles of all chars
792
+ // after cursor onto the current line
793
+ for (const index in this.styles[lineIndex]) {
794
+ const numIndex = parseInt(index, 10);
795
+ if (numIndex >= charIndex) {
796
+ somethingAdded = true;
797
+ newLineStyles[numIndex - charIndex] = this.styles[lineIndex][index];
798
+ // remove lines from the previous line since they're on a new line now
799
+ if (!(isEndOfLine && charIndex === 0)) {
800
+ delete this.styles[lineIndex][index];
801
+ }
802
+ }
803
+ }
804
+ let styleCarriedOver = false;
805
+ if (somethingAdded && !isEndOfLine) {
806
+ // if is end of line, the extra style we copied
807
+ // is probably not something we want
808
+ this.styles[lineIndex + qty] = newLineStyles;
809
+ styleCarriedOver = true;
810
+ }
811
+ if (styleCarriedOver) {
812
+ // skip the last line of since we already prepared it.
813
+ qty--;
814
+ }
815
+ // for the all the lines or all the other lines
816
+ // we clone current char style onto the next (otherwise empty) line
817
+ while (qty > 0) {
818
+ if (copiedStyle && copiedStyle[qty - 1]) {
819
+ this.styles[lineIndex + qty] = {
820
+ 0: { ...copiedStyle[qty - 1] },
821
+ };
822
+ } else if (currentCharStyle) {
823
+ this.styles[lineIndex + qty] = {
824
+ 0: { ...currentCharStyle },
825
+ };
826
+ } else {
827
+ delete this.styles[lineIndex + qty];
828
+ }
829
+ qty--;
830
+ }
831
+ this._forceClearCache = true;
832
+ }
833
+
834
+ /**
835
+ * Inserts style object for a given line/char index
836
+ * @param {Number} lineIndex Index of a line
837
+ * @param {Number} charIndex Index of a char
838
+ * @param {Number} quantity number Style object to insert, if given
839
+ * @param {Array} copiedStyle array of style objects
840
+ */
841
+ insertCharStyleObject(
842
+ lineIndex: number,
843
+ charIndex: number,
844
+ quantity: number,
845
+ copiedStyle?: TextStyleDeclaration[]
846
+ ) {
847
+ if (!this.styles) {
848
+ this.styles = {};
849
+ }
850
+ const currentLineStyles = this.styles[lineIndex],
851
+ currentLineStylesCloned = currentLineStyles
852
+ ? { ...currentLineStyles }
853
+ : {};
854
+
855
+ quantity || (quantity = 1);
856
+ // shift all char styles by quantity forward
857
+ // 0,1,2,3 -> (charIndex=2) -> 0,1,3,4 -> (insert 2) -> 0,1,2,3,4
858
+ for (const index in currentLineStylesCloned) {
859
+ const numericIndex = parseInt(index, 10);
860
+ if (numericIndex >= charIndex) {
861
+ currentLineStyles[numericIndex + quantity] =
862
+ currentLineStylesCloned[numericIndex];
863
+ // only delete the style if there was nothing moved there
864
+ if (!currentLineStylesCloned[numericIndex - quantity]) {
865
+ delete currentLineStyles[numericIndex];
866
+ }
867
+ }
868
+ }
869
+ this._forceClearCache = true;
870
+ if (copiedStyle) {
871
+ while (quantity--) {
872
+ if (!Object.keys(copiedStyle[quantity]).length) {
873
+ continue;
874
+ }
875
+ if (!this.styles[lineIndex]) {
876
+ this.styles[lineIndex] = {};
877
+ }
878
+ this.styles[lineIndex][charIndex + quantity] = {
879
+ ...copiedStyle[quantity],
880
+ };
881
+ }
882
+ return;
883
+ }
884
+ if (!currentLineStyles) {
885
+ return;
886
+ }
887
+ const newStyle = currentLineStyles[charIndex ? charIndex - 1 : 1];
888
+ while (newStyle && quantity--) {
889
+ this.styles[lineIndex][charIndex + quantity] = { ...newStyle };
890
+ }
891
+ }
892
+
893
+ /**
894
+ * Inserts style object(s)
895
+ * @param {Array} insertedText Characters at the location where style is inserted
896
+ * @param {Number} start cursor index for inserting style
897
+ * @param {Array} [copiedStyle] array of style objects to insert.
898
+ */
899
+ insertNewStyleBlock(
900
+ insertedText: string[],
901
+ start: number,
902
+ copiedStyle?: TextStyleDeclaration[]
903
+ ) {
904
+ const cursorLoc = this.get2DCursorLocation(start, true),
905
+ addedLines = [0];
906
+ let linesLength = 0;
907
+ // get an array of how many char per lines are being added.
908
+ for (let i = 0; i < insertedText.length; i++) {
909
+ if (insertedText[i] === '\n') {
910
+ linesLength++;
911
+ addedLines[linesLength] = 0;
912
+ } else {
913
+ addedLines[linesLength]++;
914
+ }
915
+ }
916
+ // for the first line copy the style from the current char position.
917
+ if (addedLines[0] > 0) {
918
+ this.insertCharStyleObject(
919
+ cursorLoc.lineIndex,
920
+ cursorLoc.charIndex,
921
+ addedLines[0],
922
+ copiedStyle
923
+ );
924
+ copiedStyle = copiedStyle && copiedStyle.slice(addedLines[0] + 1);
925
+ }
926
+ linesLength &&
927
+ this.insertNewlineStyleObject(
928
+ cursorLoc.lineIndex,
929
+ cursorLoc.charIndex + addedLines[0],
930
+ linesLength
931
+ );
932
+ let i;
933
+ for (i = 1; i < linesLength; i++) {
934
+ if (addedLines[i] > 0) {
935
+ this.insertCharStyleObject(
936
+ cursorLoc.lineIndex + i,
937
+ 0,
938
+ addedLines[i],
939
+ copiedStyle
940
+ );
941
+ } else if (copiedStyle) {
942
+ // this test is required in order to close #6841
943
+ // when a pasted buffer begins with a newline then
944
+ // this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]
945
+ // may be undefined for some reason
946
+ if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {
947
+ this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];
948
+ }
949
+ }
950
+ copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);
951
+ }
952
+ if (addedLines[i] > 0) {
953
+ this.insertCharStyleObject(
954
+ cursorLoc.lineIndex + i,
955
+ 0,
956
+ addedLines[i],
957
+ copiedStyle
958
+ );
959
+ }
960
+ }
961
+
962
+ /**
963
+ * Removes characters from start/end
964
+ * start/end ar per grapheme position in _text array.
965
+ *
966
+ * @param {Number} start
967
+ * @param {Number} end default to start + 1
968
+ */
969
+ removeChars(start: number, end: number) {
970
+ if (typeof end === 'undefined') {
971
+ end = start + 1;
972
+ }
973
+ this.removeStyleFromTo(start, end);
974
+ this._text.splice(start, end - start);
975
+ this.text = this._text.join('');
976
+ this.set('dirty', true);
977
+ if (this._shouldClearDimensionCache()) {
978
+ this.initDimensions();
979
+ this.setCoords();
980
+ }
981
+ this._removeExtraneousStyles();
982
+ }
983
+
984
+ /**
985
+ * insert characters at start position, before start position.
986
+ * start equal 1 it means the text get inserted between actual grapheme 0 and 1
987
+ * if style array is provided, it must be as the same length of text in graphemes
988
+ * if end is provided and is bigger than start, old text is replaced.
989
+ * start/end ar per grapheme position in _text array.
990
+ *
991
+ * @param {String} text text to insert
992
+ * @param {Array} style array of style objects
993
+ * @param {Number} start
994
+ * @param {Number} end default to start + 1
995
+ */
996
+ insertChars(
997
+ text: string,
998
+ style: TextStyleDeclaration[] | undefined,
999
+ start: number,
1000
+ end: number = start
1001
+ ) {
1002
+ if (end > start) {
1003
+ this.removeStyleFromTo(start, end);
1004
+ }
1005
+ const graphemes = this.graphemeSplit(text);
1006
+ this.insertNewStyleBlock(graphemes, start, style);
1007
+ this._text = [
1008
+ ...this._text.slice(0, start),
1009
+ ...graphemes,
1010
+ ...this._text.slice(end),
1011
+ ];
1012
+ this.text = this._text.join('');
1013
+ this.set('dirty', true);
1014
+ if (this._shouldClearDimensionCache()) {
1015
+ this.initDimensions();
1016
+ this.setCoords();
1017
+ }
1018
+ this._removeExtraneousStyles();
1019
+ }
1020
+
1021
+ /**
1022
+ * Set the selectionStart and selectionEnd according to the new position of cursor
1023
+ * mimic the key - mouse navigation when shift is pressed.
1024
+ */
1025
+ setSelectionStartEndWithShift(
1026
+ start: number,
1027
+ end: number,
1028
+ newSelection: number
1029
+ ) {
1030
+ if (newSelection <= start) {
1031
+ if (end === start) {
1032
+ this._selectionDirection = 'left';
1033
+ } else if (this._selectionDirection === 'right') {
1034
+ this._selectionDirection = 'left';
1035
+ this.selectionEnd = start;
1036
+ }
1037
+ this.selectionStart = newSelection;
1038
+ } else if (newSelection > start && newSelection < end) {
1039
+ if (this._selectionDirection === 'right') {
1040
+ this.selectionEnd = newSelection;
1041
+ } else {
1042
+ this.selectionStart = newSelection;
1043
+ }
1044
+ } else {
1045
+ // newSelection is > selection start and end
1046
+ if (end === start) {
1047
+ this._selectionDirection = 'right';
1048
+ } else if (this._selectionDirection === 'left') {
1049
+ this._selectionDirection = 'right';
1050
+ this.selectionStart = end;
1051
+ }
1052
+ this.selectionEnd = newSelection;
1053
+ }
1054
+ }
1055
+ }