fabric 7.0.0 → 7.2.0

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 (323) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/CHANGELOG.md +21 -0
  3. package/dist/extensions/cropping_controls/croppingControls.d.ts +16 -0
  4. package/dist/extensions/cropping_controls/croppingControls.d.ts.map +1 -0
  5. package/dist/extensions/cropping_controls/croppingHandlers.d.ts +39 -0
  6. package/dist/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -0
  7. package/dist/extensions/cropping_controls/enterCropMode.d.ts +7 -0
  8. package/dist/extensions/cropping_controls/enterCropMode.d.ts.map +1 -0
  9. package/dist/extensions/cropping_controls/renderCornerControl.d.ts +14 -0
  10. package/dist/extensions/cropping_controls/renderCornerControl.d.ts.map +1 -0
  11. package/dist/extensions/index.d.ts +3 -0
  12. package/dist/extensions/index.d.ts.map +1 -1
  13. package/dist/fabric.d.ts +1 -0
  14. package/dist/fabric.d.ts.map +1 -1
  15. package/dist/index.js +628 -537
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.min.js +1 -1
  18. package/dist/index.min.js.map +1 -1
  19. package/dist/index.min.mjs +1 -1
  20. package/dist/index.min.mjs.map +1 -1
  21. package/dist/index.mjs +628 -537
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/index.node.cjs +628 -537
  24. package/dist/index.node.cjs.map +1 -1
  25. package/dist/index.node.mjs +628 -537
  26. package/dist/index.node.mjs.map +1 -1
  27. package/dist/package.json.min.mjs +1 -1
  28. package/dist/package.json.mjs +1 -1
  29. package/dist/src/EventTypeDefs.d.ts +5 -0
  30. package/dist/src/EventTypeDefs.d.ts.map +1 -1
  31. package/dist/src/Pattern/Pattern.d.ts.map +1 -1
  32. package/dist/src/Pattern/Pattern.min.mjs +1 -1
  33. package/dist/src/Pattern/Pattern.min.mjs.map +1 -1
  34. package/dist/src/Pattern/Pattern.mjs +2 -1
  35. package/dist/src/Pattern/Pattern.mjs.map +1 -1
  36. package/dist/src/Shadow.d.ts +1 -1
  37. package/dist/src/Shadow.d.ts.map +1 -1
  38. package/dist/src/Shadow.min.mjs +1 -1
  39. package/dist/src/Shadow.min.mjs.map +1 -1
  40. package/dist/src/Shadow.mjs +5 -4
  41. package/dist/src/Shadow.mjs.map +1 -1
  42. package/dist/src/canvas/CanvasOptions.d.ts.map +1 -1
  43. package/dist/src/canvas/CanvasOptions.min.mjs.map +1 -1
  44. package/dist/src/canvas/CanvasOptions.mjs.map +1 -1
  45. package/dist/src/canvas/SelectableCanvas.d.ts +2 -0
  46. package/dist/src/canvas/SelectableCanvas.d.ts.map +1 -1
  47. package/dist/src/canvas/SelectableCanvas.min.mjs +1 -1
  48. package/dist/src/canvas/SelectableCanvas.min.mjs.map +1 -1
  49. package/dist/src/canvas/SelectableCanvas.mjs +33 -13
  50. package/dist/src/canvas/SelectableCanvas.mjs.map +1 -1
  51. package/dist/src/canvas/StaticCanvas.d.ts.map +1 -1
  52. package/dist/src/canvas/StaticCanvas.min.mjs +1 -1
  53. package/dist/src/canvas/StaticCanvas.min.mjs.map +1 -1
  54. package/dist/src/canvas/StaticCanvas.mjs +3 -1
  55. package/dist/src/canvas/StaticCanvas.mjs.map +1 -1
  56. package/dist/src/canvas/StaticCanvasOptions.d.ts.map +1 -1
  57. package/dist/src/canvas/StaticCanvasOptions.min.mjs.map +1 -1
  58. package/dist/src/canvas/StaticCanvasOptions.mjs.map +1 -1
  59. package/dist/src/constants.d.ts +1 -0
  60. package/dist/src/constants.d.ts.map +1 -1
  61. package/dist/src/constants.min.mjs.map +1 -1
  62. package/dist/src/constants.mjs.map +1 -1
  63. package/dist/src/controls/Control.d.ts +22 -1
  64. package/dist/src/controls/Control.d.ts.map +1 -1
  65. package/dist/src/controls/Control.min.mjs +1 -1
  66. package/dist/src/controls/Control.min.mjs.map +1 -1
  67. package/dist/src/controls/Control.mjs +45 -1
  68. package/dist/src/controls/Control.mjs.map +1 -1
  69. package/dist/src/controls/changeWidth.d.ts +22 -0
  70. package/dist/src/controls/changeWidth.d.ts.map +1 -1
  71. package/dist/src/controls/changeWidth.min.mjs +1 -1
  72. package/dist/src/controls/changeWidth.min.mjs.map +1 -1
  73. package/dist/src/controls/changeWidth.mjs +46 -18
  74. package/dist/src/controls/changeWidth.mjs.map +1 -1
  75. package/dist/src/controls/controlRendering.d.ts.map +1 -1
  76. package/dist/src/controls/controlRendering.min.mjs +1 -1
  77. package/dist/src/controls/controlRendering.min.mjs.map +1 -1
  78. package/dist/src/controls/controlRendering.mjs +18 -34
  79. package/dist/src/controls/controlRendering.mjs.map +1 -1
  80. package/dist/src/controls/index.d.ts +2 -1
  81. package/dist/src/controls/index.d.ts.map +1 -1
  82. package/dist/src/controls/index.min.mjs +1 -1
  83. package/dist/src/controls/index.mjs +1 -1
  84. package/dist/src/gradient/Gradient.d.ts.map +1 -1
  85. package/dist/src/gradient/Gradient.min.mjs +1 -1
  86. package/dist/src/gradient/Gradient.min.mjs.map +1 -1
  87. package/dist/src/gradient/Gradient.mjs +19 -6
  88. package/dist/src/gradient/Gradient.mjs.map +1 -1
  89. package/dist/src/shapes/Circle.d.ts.map +1 -1
  90. package/dist/src/shapes/Circle.min.mjs +1 -1
  91. package/dist/src/shapes/Circle.min.mjs.map +1 -1
  92. package/dist/src/shapes/Circle.mjs +10 -7
  93. package/dist/src/shapes/Circle.mjs.map +1 -1
  94. package/dist/src/shapes/Ellipse.d.ts.map +1 -1
  95. package/dist/src/shapes/Ellipse.min.mjs +1 -1
  96. package/dist/src/shapes/Ellipse.min.mjs.map +1 -1
  97. package/dist/src/shapes/Ellipse.mjs +2 -1
  98. package/dist/src/shapes/Ellipse.mjs.map +1 -1
  99. package/dist/src/shapes/Group.d.ts.map +1 -1
  100. package/dist/src/shapes/Group.min.mjs +1 -1
  101. package/dist/src/shapes/Group.min.mjs.map +1 -1
  102. package/dist/src/shapes/Group.mjs +2 -1
  103. package/dist/src/shapes/Group.mjs.map +1 -1
  104. package/dist/src/shapes/IText/IText.d.ts.map +1 -1
  105. package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
  106. package/dist/src/shapes/IText/IText.mjs.map +1 -1
  107. package/dist/src/shapes/Image.d.ts +1 -1
  108. package/dist/src/shapes/Image.d.ts.map +1 -1
  109. package/dist/src/shapes/Image.min.mjs +1 -1
  110. package/dist/src/shapes/Image.min.mjs.map +1 -1
  111. package/dist/src/shapes/Image.mjs +4 -3
  112. package/dist/src/shapes/Image.mjs.map +1 -1
  113. package/dist/src/shapes/Line.d.ts.map +1 -1
  114. package/dist/src/shapes/Line.min.mjs +1 -1
  115. package/dist/src/shapes/Line.min.mjs.map +1 -1
  116. package/dist/src/shapes/Line.mjs +6 -10
  117. package/dist/src/shapes/Line.mjs.map +1 -1
  118. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
  119. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs +1 -1
  120. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs.map +1 -1
  121. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs +5 -4
  122. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs.map +1 -1
  123. package/dist/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
  124. package/dist/src/shapes/Object/InteractiveObject.min.mjs.map +1 -1
  125. package/dist/src/shapes/Object/InteractiveObject.mjs.map +1 -1
  126. package/dist/src/shapes/Object/Object.d.ts.map +1 -1
  127. package/dist/src/shapes/Object/Object.min.mjs +1 -1
  128. package/dist/src/shapes/Object/Object.min.mjs.map +1 -1
  129. package/dist/src/shapes/Object/Object.mjs +3 -0
  130. package/dist/src/shapes/Object/Object.mjs.map +1 -1
  131. package/dist/src/shapes/Object/ObjectGeometry.min.mjs +1 -1
  132. package/dist/src/shapes/Object/ObjectGeometry.min.mjs.map +1 -1
  133. package/dist/src/shapes/Object/ObjectGeometry.mjs +1 -1
  134. package/dist/src/shapes/Object/ObjectGeometry.mjs.map +1 -1
  135. package/dist/src/shapes/Object/types/FabricObjectProps.d.ts.map +1 -1
  136. package/dist/src/shapes/Object/types/ObjectProps.d.ts.map +1 -1
  137. package/dist/src/shapes/Path.d.ts.map +1 -1
  138. package/dist/src/shapes/Path.min.mjs.map +1 -1
  139. package/dist/src/shapes/Path.mjs +1 -2
  140. package/dist/src/shapes/Path.mjs.map +1 -1
  141. package/dist/src/shapes/Polyline.d.ts.map +1 -1
  142. package/dist/src/shapes/Polyline.min.mjs +1 -1
  143. package/dist/src/shapes/Polyline.min.mjs.map +1 -1
  144. package/dist/src/shapes/Polyline.mjs +10 -6
  145. package/dist/src/shapes/Polyline.mjs.map +1 -1
  146. package/dist/src/shapes/Rect.d.ts.map +1 -1
  147. package/dist/src/shapes/Rect.min.mjs +1 -1
  148. package/dist/src/shapes/Rect.min.mjs.map +1 -1
  149. package/dist/src/shapes/Rect.mjs +2 -1
  150. package/dist/src/shapes/Rect.mjs.map +1 -1
  151. package/dist/src/shapes/Text/StyledText.d.ts.map +1 -1
  152. package/dist/src/shapes/Text/StyledText.min.mjs.map +1 -1
  153. package/dist/src/shapes/Text/StyledText.mjs +0 -3
  154. package/dist/src/shapes/Text/StyledText.mjs.map +1 -1
  155. package/dist/src/shapes/Text/Text.d.ts.map +1 -1
  156. package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
  157. package/dist/src/shapes/Text/Text.mjs.map +1 -1
  158. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
  159. package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs +1 -1
  160. package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs.map +1 -1
  161. package/dist/src/shapes/Text/TextSVGExportMixin.mjs +5 -6
  162. package/dist/src/shapes/Text/TextSVGExportMixin.mjs.map +1 -1
  163. package/dist/src/shapes/Textbox.d.ts.map +1 -1
  164. package/dist/src/shapes/Textbox.min.mjs.map +1 -1
  165. package/dist/src/shapes/Textbox.mjs.map +1 -1
  166. package/dist/src/shapes/Triangle.d.ts.map +1 -1
  167. package/dist/src/shapes/Triangle.min.mjs.map +1 -1
  168. package/dist/src/shapes/Triangle.mjs.map +1 -1
  169. package/dist/src/util/lang_string.d.ts +1 -1
  170. package/dist/src/util/lang_string.d.ts.map +1 -1
  171. package/dist/src/util/lang_string.min.mjs +1 -1
  172. package/dist/src/util/lang_string.min.mjs.map +1 -1
  173. package/dist/src/util/lang_string.mjs +1 -1
  174. package/dist/src/util/lang_string.mjs.map +1 -1
  175. package/dist/src/util/misc/svgParsing.d.ts.map +1 -1
  176. package/dist/src/util/misc/svgParsing.min.mjs +1 -1
  177. package/dist/src/util/misc/svgParsing.min.mjs.map +1 -1
  178. package/dist/src/util/misc/svgParsing.mjs +2 -1
  179. package/dist/src/util/misc/svgParsing.mjs.map +1 -1
  180. package/dist-extensions/cropping_controls/croppingControls.mjs +140 -0
  181. package/dist-extensions/cropping_controls/croppingControls.mjs.map +1 -0
  182. package/dist-extensions/cropping_controls/croppingHandlers.mjs +228 -0
  183. package/dist-extensions/cropping_controls/croppingHandlers.mjs.map +1 -0
  184. package/dist-extensions/cropping_controls/enterCropMode.mjs +38 -0
  185. package/dist-extensions/cropping_controls/enterCropMode.mjs.map +1 -0
  186. package/dist-extensions/cropping_controls/renderCornerControl.mjs +45 -0
  187. package/dist-extensions/cropping_controls/renderCornerControl.mjs.map +1 -0
  188. package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts +16 -0
  189. package/dist-extensions/extensions/cropping_controls/croppingControls.d.ts.map +1 -0
  190. package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts +39 -0
  191. package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -0
  192. package/dist-extensions/extensions/cropping_controls/enterCropMode.d.ts +7 -0
  193. package/dist-extensions/extensions/cropping_controls/enterCropMode.d.ts.map +1 -0
  194. package/dist-extensions/extensions/cropping_controls/renderCornerControl.d.ts +14 -0
  195. package/dist-extensions/extensions/cropping_controls/renderCornerControl.d.ts.map +1 -0
  196. package/dist-extensions/extensions/index.d.ts +3 -0
  197. package/dist-extensions/extensions/index.d.ts.map +1 -1
  198. package/dist-extensions/fabric-extensions.min.js +1 -1
  199. package/dist-extensions/fabric-extensions.min.js.map +1 -1
  200. package/dist-extensions/fabric.d.ts +1 -0
  201. package/dist-extensions/fabric.d.ts.map +1 -1
  202. package/dist-extensions/index.mjs +3 -0
  203. package/dist-extensions/index.mjs.map +1 -1
  204. package/dist-extensions/src/EventTypeDefs.d.ts +5 -0
  205. package/dist-extensions/src/EventTypeDefs.d.ts.map +1 -1
  206. package/dist-extensions/src/Pattern/Pattern.d.ts.map +1 -1
  207. package/dist-extensions/src/Shadow.d.ts +1 -1
  208. package/dist-extensions/src/Shadow.d.ts.map +1 -1
  209. package/dist-extensions/src/canvas/CanvasOptions.d.ts.map +1 -1
  210. package/dist-extensions/src/canvas/SelectableCanvas.d.ts +2 -0
  211. package/dist-extensions/src/canvas/SelectableCanvas.d.ts.map +1 -1
  212. package/dist-extensions/src/canvas/StaticCanvas.d.ts.map +1 -1
  213. package/dist-extensions/src/canvas/StaticCanvasOptions.d.ts.map +1 -1
  214. package/dist-extensions/src/constants.d.ts +1 -0
  215. package/dist-extensions/src/constants.d.ts.map +1 -1
  216. package/dist-extensions/src/controls/Control.d.ts +22 -1
  217. package/dist-extensions/src/controls/Control.d.ts.map +1 -1
  218. package/dist-extensions/src/controls/changeWidth.d.ts +22 -0
  219. package/dist-extensions/src/controls/changeWidth.d.ts.map +1 -1
  220. package/dist-extensions/src/controls/controlRendering.d.ts.map +1 -1
  221. package/dist-extensions/src/controls/index.d.ts +2 -1
  222. package/dist-extensions/src/controls/index.d.ts.map +1 -1
  223. package/dist-extensions/src/gradient/Gradient.d.ts.map +1 -1
  224. package/dist-extensions/src/shapes/Circle.d.ts.map +1 -1
  225. package/dist-extensions/src/shapes/Ellipse.d.ts.map +1 -1
  226. package/dist-extensions/src/shapes/Group.d.ts.map +1 -1
  227. package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
  228. package/dist-extensions/src/shapes/Image.d.ts.map +1 -1
  229. package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
  230. package/dist-extensions/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
  231. package/dist-extensions/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
  232. package/dist-extensions/src/shapes/Object/Object.d.ts.map +1 -1
  233. package/dist-extensions/src/shapes/Object/types/FabricObjectProps.d.ts.map +1 -1
  234. package/dist-extensions/src/shapes/Object/types/ObjectProps.d.ts.map +1 -1
  235. package/dist-extensions/src/shapes/Path.d.ts +1 -1
  236. package/dist-extensions/src/shapes/Path.d.ts.map +1 -1
  237. package/dist-extensions/src/shapes/Polyline.d.ts.map +1 -1
  238. package/dist-extensions/src/shapes/Rect.d.ts.map +1 -1
  239. package/dist-extensions/src/shapes/Text/StyledText.d.ts.map +1 -1
  240. package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
  241. package/dist-extensions/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
  242. package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
  243. package/dist-extensions/src/shapes/Triangle.d.ts.map +1 -1
  244. package/dist-extensions/src/util/lang_string.d.ts +1 -1
  245. package/dist-extensions/src/util/lang_string.d.ts.map +1 -1
  246. package/dist-extensions/src/util/misc/svgParsing.d.ts.map +1 -1
  247. package/eslint.config.mjs +2 -0
  248. package/extensions/cropping_controls/croppingControls.spec.ts +115 -0
  249. package/extensions/cropping_controls/croppingControls.ts +150 -0
  250. package/extensions/cropping_controls/croppingHandlers.spec.ts +579 -0
  251. package/extensions/cropping_controls/croppingHandlers.ts +285 -0
  252. package/extensions/cropping_controls/enterCropMode.ts +30 -0
  253. package/extensions/cropping_controls/renderCornerControl.ts +53 -0
  254. package/extensions/index.ts +9 -0
  255. package/fabric.ts +1 -0
  256. package/package.json +17 -8
  257. package/src/ClassRegistry.spec.ts +18 -19
  258. package/src/EventTypeDefs.ts +15 -11
  259. package/src/Pattern/Pattern.spec.ts +12 -0
  260. package/src/Pattern/Pattern.ts +3 -2
  261. package/src/Shadow.ts +9 -8
  262. package/src/brushes/PencilBrush.spec.ts +11 -11
  263. package/src/canvas/Canvas-dispose.spec.ts +8 -7
  264. package/src/canvas/Canvas.spec.ts +27 -29
  265. package/src/canvas/CanvasOptions.ts +2 -1
  266. package/src/canvas/SelectableCanvas.ts +38 -15
  267. package/src/canvas/StaticCanvas.spec.ts +20 -0
  268. package/src/canvas/StaticCanvas.ts +7 -4
  269. package/src/canvas/StaticCanvasOptions.ts +1 -3
  270. package/src/constants.ts +1 -0
  271. package/src/controls/Control.spec.ts +102 -0
  272. package/src/controls/Control.ts +71 -2
  273. package/src/controls/changeHeight.spec.ts +147 -0
  274. package/src/controls/changeWidth.ts +68 -35
  275. package/src/controls/controlRendering.ts +20 -48
  276. package/src/controls/index.ts +7 -1
  277. package/src/gradient/Gradient.spec.ts +101 -46
  278. package/src/gradient/Gradient.ts +27 -14
  279. package/src/shapes/Circle.spec.ts +10 -39
  280. package/src/shapes/Circle.ts +11 -11
  281. package/src/shapes/Ellipse.spec.ts +8 -37
  282. package/src/shapes/Ellipse.ts +7 -7
  283. package/src/shapes/Group.ts +3 -3
  284. package/src/shapes/IText/IText-click-behavior.spec.ts +36 -49
  285. package/src/shapes/IText/IText.ts +5 -6
  286. package/src/shapes/IText/ITextKeyBehavior.test.ts +0 -1
  287. package/src/shapes/IText/__snapshots__/ITextBehavior.test.ts.snap +6 -6
  288. package/src/shapes/Image.spec.ts +17 -33
  289. package/src/shapes/Image.ts +15 -11
  290. package/src/shapes/Line.spec.ts +4 -30
  291. package/src/shapes/Line.ts +11 -16
  292. package/src/shapes/Object/FabricObjectSVGExportMixin.ts +11 -4
  293. package/src/shapes/Object/InteractiveObject.ts +4 -4
  294. package/src/shapes/Object/Object.ts +6 -5
  295. package/src/shapes/Object/ObjectGeometry.spec.ts +15 -0
  296. package/src/shapes/Object/ObjectGeometry.ts +1 -1
  297. package/src/shapes/Object/objectSvgExport.spec.ts +112 -0
  298. package/src/shapes/Object/types/FabricObjectProps.ts +1 -4
  299. package/src/shapes/Object/types/ObjectProps.ts +1 -3
  300. package/src/shapes/Path.spec.ts +4 -27
  301. package/src/shapes/Path.ts +2 -4
  302. package/src/shapes/Polygon.spec.ts +4 -31
  303. package/src/shapes/Polyline.spec.ts +4 -31
  304. package/src/shapes/Polyline.ts +11 -12
  305. package/src/shapes/Rect.spec.ts +25 -33
  306. package/src/shapes/Rect.ts +7 -7
  307. package/src/shapes/Text/StyledText.ts +0 -3
  308. package/src/shapes/Text/Text.spec.ts +3 -32
  309. package/src/shapes/Text/Text.ts +5 -6
  310. package/src/shapes/Text/TextSVGExportMixin.spec.ts +9 -0
  311. package/src/shapes/Text/TextSVGExportMixin.ts +14 -16
  312. package/src/shapes/Text/__snapshots__/Text.spec.ts.snap +1 -1
  313. package/src/shapes/Text/__snapshots__/TextSVGExportMixin.spec.ts.snap +1 -1
  314. package/src/shapes/Textbox.spec.ts +5 -5
  315. package/src/shapes/Textbox.ts +6 -5
  316. package/src/shapes/Triangle.ts +4 -4
  317. package/src/shapes/__snapshots__/Image.spec.ts.snap +4 -4
  318. package/src/shapes/__snapshots__/Textbox.spec.ts.snap +5 -5
  319. package/src/util/lang_string.ts +3 -2
  320. package/src/util/misc/svgParsing.ts +2 -1
  321. package/tsconfig.spec.json +1 -0
  322. package/vitest.config.ts +12 -2
  323. package/vitest.extend.ts +6 -2
@@ -6,18 +6,25 @@ import type {
6
6
  } from '../EventTypeDefs';
7
7
  import { Intersection } from '../Intersection';
8
8
  import { Point } from '../Point';
9
- import { SCALE } from '../constants';
9
+ import { FILL, SCALE, STROKE } from '../constants';
10
10
  import type {
11
11
  InteractiveFabricObject,
12
12
  TOCoord,
13
13
  } from '../shapes/Object/InteractiveObject';
14
- import type { TCornerPoint, TDegree, TMat2D } from '../typedefs';
14
+ import type {
15
+ TCornerPoint,
16
+ TDegree,
17
+ TMat2D,
18
+ TOriginX,
19
+ TOriginY,
20
+ } from '../typedefs';
15
21
  import {
16
22
  createRotateMatrix,
17
23
  createScaleMatrix,
18
24
  createTranslateMatrix,
19
25
  multiplyTransformMatrixArray,
20
26
  } from '../util/misc/matrix';
27
+ import { degreesToRadians } from '../util/misc/radiansDegreesConversion';
21
28
  import type { ControlRenderingStyleOverride } from './controlRendering';
22
29
  import { renderCircleControl, renderSquareControl } from './controlRendering';
23
30
 
@@ -142,10 +149,27 @@ export class Control {
142
149
  */
143
150
  withConnection = false;
144
151
 
152
+ declare transformAnchorPoint?: {
153
+ x: TOriginX;
154
+ y: TOriginY;
155
+ };
156
+
145
157
  constructor(options?: Partial<Control>) {
146
158
  Object.assign(this, options);
147
159
  }
148
160
 
161
+ getTransformAnchorPoint(): {
162
+ x: TOriginX;
163
+ y: TOriginY;
164
+ } {
165
+ return (
166
+ // return the control transformAnchorPoint
167
+ this.transformAnchorPoint ??
168
+ // otherwise will return the opposite origin of where the control is located.
169
+ new Point(-this.x + 0.5, -this.y + 0.5)
170
+ );
171
+ }
172
+
149
173
  /**
150
174
  * The control actionHandler, provide one to handle action ( control being moved )
151
175
  * @param {Event} eventData the native mouse event
@@ -337,6 +361,51 @@ export class Control {
337
361
  };
338
362
  }
339
363
 
364
+ /**
365
+ * This is an helper method to prepare the canvas to render a control
366
+ * It detectes common control properties and sets the correct fill and
367
+ * stroke styles on the context. It does not execute translations or
368
+ * rotations since different controls need differnt combination of these.
369
+ */
370
+ commonRenderProps(
371
+ ctx: CanvasRenderingContext2D,
372
+ left: number,
373
+ top: number,
374
+ fabricObject: InteractiveFabricObject,
375
+ styleOverride: ControlRenderingStyleOverride = {},
376
+ ): {
377
+ stroke: boolean;
378
+ xSize: number;
379
+ ySize: number;
380
+ transparentCorners: boolean;
381
+ opName: 'stroke' | 'fill';
382
+ } {
383
+ const { cornerSize, cornerColor, transparentCorners, cornerStrokeColor } =
384
+ styleOverride,
385
+ sizeFromProps = cornerSize || fabricObject.cornerSize,
386
+ xSize = this.sizeX || sizeFromProps,
387
+ ySize = this.sizeY || sizeFromProps,
388
+ transparent =
389
+ typeof transparentCorners !== 'undefined'
390
+ ? transparentCorners
391
+ : fabricObject.transparentCorners,
392
+ opName = transparent ? STROKE : FILL,
393
+ strokeColor = cornerStrokeColor || fabricObject.cornerStrokeColor,
394
+ stroke = !transparent && !!strokeColor;
395
+ ctx.fillStyle = cornerColor || fabricObject.cornerColor || '';
396
+ ctx.strokeStyle = strokeColor || '';
397
+ ctx.translate(left, top);
398
+ // angle is relative to canvas plane
399
+ ctx.rotate(degreesToRadians(fabricObject.getTotalAngle()));
400
+ return {
401
+ stroke,
402
+ xSize,
403
+ ySize,
404
+ transparentCorners: transparent,
405
+ opName,
406
+ };
407
+ }
408
+
340
409
  /**
341
410
  * Render function for the control.
342
411
  * When this function runs the context is unscaled. unrotate. Just retina scaled.
@@ -0,0 +1,147 @@
1
+ import type { FabricObject } from '../../fabric';
2
+ import type { Transform } from '../EventTypeDefs';
3
+ import { Point } from '../Point';
4
+ import { Canvas } from '../canvas/Canvas';
5
+ import { Rect } from '../shapes/Rect';
6
+ import { changeHeight } from './changeWidth';
7
+
8
+ import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest';
9
+
10
+ describe('changeHeight', () => {
11
+ let canvas: Canvas;
12
+ let target: Rect;
13
+ let transform: any;
14
+ let eventData: any;
15
+
16
+ function prepareTransform(target: FabricObject, corner: string): Transform {
17
+ const origin = canvas._getOriginFromCorner(target, corner);
18
+ return {
19
+ target,
20
+ corner,
21
+ originX: origin.x,
22
+ originY: origin.y,
23
+ } as Transform;
24
+ }
25
+
26
+ beforeEach(() => {
27
+ canvas = new Canvas();
28
+ target = new Rect({ left: 50, top: 50, width: 100, height: 100 });
29
+ canvas.add(target);
30
+ eventData = {};
31
+ transform = prepareTransform(target, 'mb');
32
+ });
33
+
34
+ afterEach(() => {
35
+ canvas.off();
36
+ canvas.clear();
37
+ });
38
+
39
+ test('changeHeight changes the height', () => {
40
+ expect(target.height).toBe(100);
41
+ const changed = changeHeight(eventData, transform, 300, 200);
42
+ expect(changed).toBe(true);
43
+ expect(target.height).toBe(199.5);
44
+ expect(target.top).toBe(99.75);
45
+ expect(target.left).toBe(50);
46
+ });
47
+
48
+ test('changeHeight changes the height with decimals', () => {
49
+ expect(target.height).toBe(100);
50
+ const changed = changeHeight(eventData, transform, 300, 200.2);
51
+ expect(changed).toBe(true);
52
+ expect(target.height).toBe(199.7);
53
+ expect(target.top).toBe(99.85);
54
+ expect(target.left).toBe(50);
55
+ });
56
+
57
+ test('changeHeight does not change the height', () => {
58
+ const target = new Rect({ width: 100, height: 100, canvas });
59
+ vi.spyOn(target, '_set').mockImplementation(function _set(this: Rect) {
60
+ return this;
61
+ });
62
+ expect(target.height).toBe(100);
63
+ const changed = changeHeight(eventData, { ...transform, target }, 300, 200);
64
+ expect(changed).toBe(false);
65
+ expect(target.height).toBe(100);
66
+ expect(target.left).toBe(0);
67
+ expect(target.top).toBe(0);
68
+ });
69
+
70
+ test("changeHeight does not change the height of target's other side", () => {
71
+ expect(target.height).toBe(100);
72
+ const changed = changeHeight(
73
+ eventData,
74
+ prepareTransform(target, 'mt'),
75
+ 300,
76
+ 200,
77
+ );
78
+ expect(changed).toBe(false);
79
+ expect(target.height).toBe(100);
80
+ const changed2 = changeHeight(
81
+ eventData,
82
+ prepareTransform(target, 'mb'),
83
+ 300,
84
+ -200,
85
+ );
86
+ expect(changed2).toBe(false);
87
+ expect(target.height).toBe(100);
88
+ expect(target.left).toBe(50);
89
+ expect(target.top).toBe(50);
90
+ });
91
+
92
+ test('changeHeight changes the height with centered transform', () => {
93
+ transform.originX = 'center';
94
+ transform.originY = 'center';
95
+ expect(target.height).toBe(100);
96
+ changeHeight(eventData, transform, 300, 200);
97
+ expect(target.height).toBe(299);
98
+ expect(target.left).toBe(50);
99
+ expect(target.top).toBe(50);
100
+ });
101
+
102
+ test('changeHeight changes the height with big strokeWidth', () => {
103
+ transform.target.strokeWidth = 15;
104
+ changeHeight(eventData, transform, 300, 200);
105
+ expect(target.height).toBe(192.5);
106
+ });
107
+
108
+ test('changeHeight changes the height with big strokeWidth and strokeUniform', () => {
109
+ transform.target.strokeWidth = 15;
110
+ transform.target.strokeUniform = true;
111
+ changeHeight(eventData, transform, 300, 200);
112
+ expect(target.height).toBe(192.5);
113
+ });
114
+
115
+ test('changeHeight changes the height with big strokeWidth and strokeUniform + scaling', () => {
116
+ transform.target.strokeWidth = 15;
117
+ transform.target.strokeUniform = true;
118
+ transform.target.scaleY = 3;
119
+ changeHeight(eventData, transform, 300, 200);
120
+ expect(Math.ceil(target.height)).toBe(98);
121
+ });
122
+
123
+ test('changeHeight changes the height with big strokeWidth + scaling', () => {
124
+ transform.target.strokeWidth = 15;
125
+ transform.target.scaleY = 3;
126
+ changeHeight(eventData, transform, 300, 200);
127
+ expect(Math.ceil(target.height)).toBe(93);
128
+ });
129
+
130
+ test('changeHeight will fire events on canvas and target resizing', () => {
131
+ target.canvas?.on('object:resizing', (options) => {
132
+ expect(options.target).toBe(target);
133
+ });
134
+ const resizePromise = new Promise<void>((resolve) => {
135
+ target.on('resizing', (options) => {
136
+ expect(options).toEqual({
137
+ e: eventData,
138
+ transform,
139
+ pointer: new Point(300, 200),
140
+ });
141
+ resolve();
142
+ });
143
+ });
144
+ changeHeight(eventData, transform, 300, 200);
145
+ return resizePromise;
146
+ });
147
+ });
@@ -1,55 +1,88 @@
1
1
  import type { TransformActionHandler } from '../EventTypeDefs';
2
- import { CENTER, LEFT, RESIZING, RIGHT } from '../constants';
2
+ import { RESIZING } from '../constants';
3
3
  import { resolveOrigin } from '../util/misc/resolveOrigin';
4
4
  import { getLocalPoint, isTransformCentered } from './util';
5
5
  import { wrapWithFireEvent } from './wrapWithFireEvent';
6
6
  import { wrapWithFixedAnchor } from './wrapWithFixedAnchor';
7
7
 
8
+ export const changeObjectDimensionGen =
9
+ (
10
+ dimension: 'width' | 'height',
11
+ origin: 'originX' | 'originY',
12
+ xorY: 'x' | 'y',
13
+ scale: 'scaleX' | 'scaleY',
14
+ ): TransformActionHandler =>
15
+ (eventData, transform, x, y) => {
16
+ const localPoint = getLocalPoint(
17
+ transform,
18
+ transform.originX,
19
+ transform.originY,
20
+ x,
21
+ y,
22
+ );
23
+ const localPointValue = localPoint[xorY];
24
+ // make sure the control changes width ONLY from it's side of target
25
+ const originValue = resolveOrigin(transform[origin]);
26
+ if (
27
+ originValue === 0 ||
28
+ (originValue > 0 && localPointValue < 0) ||
29
+ (originValue < 0 && localPointValue > 0)
30
+ ) {
31
+ const { target } = transform,
32
+ strokePadding =
33
+ target.strokeWidth / (target.strokeUniform ? target[scale] : 1),
34
+ multiplier = isTransformCentered(transform) ? 2 : 1,
35
+ oldWidth = target[dimension],
36
+ newWidth =
37
+ Math.abs((localPointValue * multiplier) / target[scale]) -
38
+ strokePadding;
39
+ target.set(dimension, Math.max(newWidth, 1));
40
+ // check against actual target width in case `newWidth` was rejected
41
+ return oldWidth !== target[dimension];
42
+ }
43
+ return false;
44
+ };
45
+
8
46
  /**
9
47
  * Action handler to change object's width
10
48
  * Needs to be wrapped with `wrapWithFixedAnchor` to be effective
49
+ * You want to use this only if you are building a new control handler and you want
50
+ * to reuse some logic. use "changeWidth" if you are looking to just use a control for width
11
51
  * @param {Event} eventData javascript event that is doing the transform
12
52
  * @param {Object} transform javascript object containing a series of information around the current transform
13
53
  * @param {number} x current mouse x position, canvas normalized
14
54
  * @param {number} y current mouse y position, canvas normalized
15
55
  * @return {Boolean} true if some change happened
16
56
  */
17
- export const changeObjectWidth: TransformActionHandler = (
18
- eventData,
19
- transform,
20
- x,
21
- y,
22
- ) => {
23
- const localPoint = getLocalPoint(
24
- transform,
25
- transform.originX,
26
- transform.originY,
27
- x,
28
- y,
29
- );
30
- // make sure the control changes width ONLY from it's side of target
31
- if (
32
- resolveOrigin(transform.originX) === resolveOrigin(CENTER) ||
33
- (resolveOrigin(transform.originX) === resolveOrigin(RIGHT) &&
34
- localPoint.x < 0) ||
35
- (resolveOrigin(transform.originX) === resolveOrigin(LEFT) &&
36
- localPoint.x > 0)
37
- ) {
38
- const { target } = transform,
39
- strokePadding =
40
- target.strokeWidth / (target.strokeUniform ? target.scaleX : 1),
41
- multiplier = isTransformCentered(transform) ? 2 : 1,
42
- oldWidth = target.width,
43
- newWidth =
44
- Math.abs((localPoint.x * multiplier) / target.scaleX) - strokePadding;
45
- target.set('width', Math.max(newWidth, 1));
46
- // check against actual target width in case `newWidth` was rejected
47
- return oldWidth !== target.width;
48
- }
49
- return false;
50
- };
57
+ export const changeObjectWidth: TransformActionHandler =
58
+ changeObjectDimensionGen('width', 'originX', 'x', 'scaleX');
51
59
 
60
+ /**
61
+ * Action handler to change object's height
62
+ * Needs to be wrapped with `wrapWithFixedAnchor` to be effective
63
+ * You want to use this only if you are building a new control handler and you want
64
+ * to reuse some logic. use "changeHeight" if you are looking to just use a control for height
65
+ * @param {Event} eventData javascript event that is doing the transform
66
+ * @param {Object} transform javascript object containing a series of information around the current transform
67
+ * @param {number} x current mouse x position, canvas normalized
68
+ * @param {number} y current mouse y position, canvas normalized
69
+ * @return {Boolean} true if some change happened
70
+ */
71
+ export const changeObjectHeight: TransformActionHandler =
72
+ changeObjectDimensionGen('height', 'originY', 'y', 'scaleY');
73
+
74
+ /**
75
+ * Control handler for changing width
76
+ */
52
77
  export const changeWidth = wrapWithFireEvent(
53
78
  RESIZING,
54
79
  wrapWithFixedAnchor(changeObjectWidth),
55
80
  );
81
+
82
+ /**
83
+ * Control handler for changing height
84
+ */
85
+ export const changeHeight = wrapWithFireEvent(
86
+ RESIZING,
87
+ wrapWithFixedAnchor(changeObjectHeight),
88
+ );
@@ -1,6 +1,5 @@
1
- import { FILL, STROKE, twoMathPi } from '../constants';
1
+ import { twoMathPi } from '../constants';
2
2
  import type { InteractiveFabricObject } from '../shapes/Object/InteractiveObject';
3
- import { degreesToRadians } from '../util/misc/radiansDegreesConversion';
4
3
  import type { Control } from './Control';
5
4
 
6
5
  export type ControlRenderingStyleOverride = Partial<
@@ -44,40 +43,25 @@ export function renderCircleControl(
44
43
  styleOverride: ControlRenderingStyleOverride,
45
44
  fabricObject: InteractiveFabricObject,
46
45
  ) {
47
- styleOverride = styleOverride || {};
48
- const xSize =
49
- this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,
50
- ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,
51
- transparentCorners =
52
- typeof styleOverride.transparentCorners !== 'undefined'
53
- ? styleOverride.transparentCorners
54
- : fabricObject.transparentCorners,
55
- methodName = transparentCorners ? STROKE : FILL,
56
- stroke =
57
- !transparentCorners &&
58
- (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor);
59
- let myLeft = left,
60
- myTop = top,
61
- size;
62
46
  ctx.save();
63
- ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor || '';
64
- ctx.strokeStyle =
65
- styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor || '';
47
+ const { stroke, xSize, ySize, opName } = this.commonRenderProps(
48
+ ctx,
49
+ left,
50
+ top,
51
+ fabricObject,
52
+ styleOverride,
53
+ );
54
+ let size = xSize;
66
55
  // TODO: use proper ellipse code.
67
56
  if (xSize > ySize) {
68
- size = xSize;
69
57
  ctx.scale(1.0, ySize / xSize);
70
- myTop = (top * xSize) / ySize;
71
58
  } else if (ySize > xSize) {
72
59
  size = ySize;
73
60
  ctx.scale(xSize / ySize, 1.0);
74
- myLeft = (left * ySize) / xSize;
75
- } else {
76
- size = xSize;
77
61
  }
78
62
  ctx.beginPath();
79
- ctx.arc(myLeft, myTop, size / 2, 0, twoMathPi, false);
80
- ctx[methodName]();
63
+ ctx.arc(0, 0, size / 2, 0, twoMathPi, false);
64
+ ctx[opName]();
81
65
  if (stroke) {
82
66
  ctx.stroke();
83
67
  }
@@ -103,32 +87,20 @@ export function renderSquareControl(
103
87
  styleOverride: ControlRenderingStyleOverride,
104
88
  fabricObject: InteractiveFabricObject,
105
89
  ) {
106
- styleOverride = styleOverride || {};
107
- const xSize =
108
- this.sizeX || styleOverride.cornerSize || fabricObject.cornerSize,
109
- ySize = this.sizeY || styleOverride.cornerSize || fabricObject.cornerSize,
110
- transparentCorners =
111
- typeof styleOverride.transparentCorners !== 'undefined'
112
- ? styleOverride.transparentCorners
113
- : fabricObject.transparentCorners,
114
- methodName = transparentCorners ? STROKE : FILL,
115
- stroke =
116
- !transparentCorners &&
117
- (styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor),
90
+ ctx.save();
91
+ const { stroke, xSize, ySize, opName } = this.commonRenderProps(
92
+ ctx,
93
+ left,
94
+ top,
95
+ fabricObject,
96
+ styleOverride,
97
+ ),
118
98
  xSizeBy2 = xSize / 2,
119
99
  ySizeBy2 = ySize / 2;
120
- ctx.save();
121
- ctx.fillStyle = styleOverride.cornerColor || fabricObject.cornerColor || '';
122
- ctx.strokeStyle =
123
- styleOverride.cornerStrokeColor || fabricObject.cornerStrokeColor || '';
124
- ctx.translate(left, top);
125
- // angle is relative to canvas plane
126
- const angle = fabricObject.getTotalAngle();
127
- ctx.rotate(degreesToRadians(angle));
128
100
  // this does not work, and fixed with ( && ) does not make sense.
129
101
  // to have real transparent corners we need the controls on upperCanvas
130
102
  // transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
131
- ctx[`${methodName}Rect`](-xSizeBy2, -ySizeBy2, xSize, ySize);
103
+ ctx[`${opName}Rect`](-xSizeBy2, -ySizeBy2, xSize, ySize);
132
104
  if (stroke) {
133
105
  ctx.strokeRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
134
106
  }
@@ -1,5 +1,11 @@
1
- export { changeWidth } from './changeWidth';
1
+ export {
2
+ changeWidth,
3
+ changeObjectWidth,
4
+ changeHeight,
5
+ changeObjectHeight,
6
+ } from './changeWidth';
2
7
  export { renderCircleControl, renderSquareControl } from './controlRendering';
8
+ export type { ControlRenderingStyleOverride } from './controlRendering';
3
9
  export * from './commonControls';
4
10
  export { dragHandler } from './drag';
5
11
  export * from './polyControl';