suneditor 3.0.0-alpha.9 → 3.0.0-beta.2

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 (315) hide show
  1. package/CONTRIBUTING.md +170 -22
  2. package/{LICENSE.txt → LICENSE} +9 -9
  3. package/README.md +168 -30
  4. package/dist/suneditor.min.css +1 -1
  5. package/dist/suneditor.min.js +1 -1
  6. package/package.json +47 -21
  7. package/src/assets/design/color.css +121 -0
  8. package/src/assets/design/index.css +3 -0
  9. package/src/assets/design/size.css +35 -0
  10. package/src/assets/design/typography.css +37 -0
  11. package/src/assets/icons/defaultIcons.js +232 -0
  12. package/src/assets/suneditor-contents.css +181 -46
  13. package/src/assets/suneditor.css +1403 -650
  14. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  15. package/src/core/base/eventHandlers/handler_ww_clipboard.js +23 -4
  16. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +49 -10
  17. package/src/core/base/eventHandlers/handler_ww_key_input.js +422 -224
  18. package/src/core/base/eventHandlers/handler_ww_mouse.js +83 -36
  19. package/src/core/base/eventManager.js +520 -179
  20. package/src/core/base/history.js +95 -41
  21. package/src/core/class/char.js +26 -11
  22. package/src/core/class/component.js +345 -137
  23. package/src/core/class/format.js +683 -519
  24. package/src/core/class/html.js +485 -305
  25. package/src/core/class/menu.js +133 -47
  26. package/src/core/class/nodeTransform.js +90 -71
  27. package/src/core/class/offset.js +408 -92
  28. package/src/core/class/selection.js +216 -106
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +422 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +496 -389
  34. package/src/core/section/actives.js +123 -27
  35. package/src/core/section/constructor.js +615 -206
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/events.js +622 -0
  42. package/src/helper/clipboard.js +59 -0
  43. package/src/helper/converter.js +202 -26
  44. package/src/helper/dom/domCheck.js +304 -0
  45. package/src/helper/dom/domQuery.js +669 -0
  46. package/src/helper/dom/domUtils.js +557 -0
  47. package/src/helper/dom/index.js +12 -0
  48. package/src/helper/env.js +46 -56
  49. package/src/helper/index.js +10 -4
  50. package/src/helper/keyCodeMap.js +183 -0
  51. package/src/helper/numbers.js +12 -8
  52. package/src/helper/unicode.js +9 -5
  53. package/src/langs/ckb.js +74 -4
  54. package/src/langs/cs.js +72 -2
  55. package/src/langs/da.js +73 -3
  56. package/src/langs/de.js +73 -4
  57. package/src/langs/en.js +23 -3
  58. package/src/langs/es.js +73 -4
  59. package/src/langs/fa.js +75 -3
  60. package/src/langs/fr.js +73 -3
  61. package/src/langs/he.js +73 -4
  62. package/src/langs/hu.js +230 -0
  63. package/src/langs/index.js +7 -3
  64. package/src/langs/it.js +70 -1
  65. package/src/langs/ja.js +72 -4
  66. package/src/langs/km.js +230 -0
  67. package/src/langs/ko.js +22 -2
  68. package/src/langs/lv.js +74 -5
  69. package/src/langs/nl.js +73 -4
  70. package/src/langs/pl.js +73 -4
  71. package/src/langs/pt_br.js +70 -1
  72. package/src/langs/ro.js +74 -5
  73. package/src/langs/ru.js +73 -4
  74. package/src/langs/se.js +73 -4
  75. package/src/langs/tr.js +73 -1
  76. package/src/langs/{ua.js → uk.js} +75 -6
  77. package/src/langs/ur.js +77 -8
  78. package/src/langs/zh_cn.js +74 -5
  79. package/src/modules/ApiManager.js +77 -54
  80. package/src/modules/Browser.js +667 -0
  81. package/src/modules/ColorPicker.js +162 -102
  82. package/src/modules/Controller.js +273 -142
  83. package/src/modules/Figure.js +925 -484
  84. package/src/modules/FileManager.js +121 -69
  85. package/src/modules/HueSlider.js +113 -61
  86. package/src/modules/Modal.js +291 -122
  87. package/src/modules/ModalAnchorEditor.js +383 -234
  88. package/src/modules/SelectMenu.js +270 -168
  89. package/src/modules/_DragHandle.js +2 -1
  90. package/src/modules/index.js +3 -3
  91. package/src/plugins/browser/audioGallery.js +83 -0
  92. package/src/plugins/browser/fileBrowser.js +103 -0
  93. package/src/plugins/browser/fileGallery.js +83 -0
  94. package/src/plugins/browser/imageGallery.js +81 -0
  95. package/src/plugins/browser/videoGallery.js +103 -0
  96. package/src/plugins/command/blockquote.js +40 -27
  97. package/src/plugins/command/exportPDF.js +134 -0
  98. package/src/plugins/command/fileUpload.js +229 -162
  99. package/src/plugins/command/list_bulleted.js +83 -47
  100. package/src/plugins/command/list_numbered.js +83 -47
  101. package/src/plugins/dropdown/align.js +66 -54
  102. package/src/plugins/dropdown/backgroundColor.js +63 -49
  103. package/src/plugins/dropdown/font.js +71 -47
  104. package/src/plugins/dropdown/fontColor.js +63 -48
  105. package/src/plugins/dropdown/formatBlock.js +70 -33
  106. package/src/plugins/dropdown/hr.js +92 -51
  107. package/src/plugins/dropdown/layout.js +37 -26
  108. package/src/plugins/dropdown/lineHeight.js +54 -38
  109. package/src/plugins/dropdown/list.js +60 -45
  110. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  111. package/src/plugins/dropdown/table.js +2003 -813
  112. package/src/plugins/dropdown/template.js +38 -26
  113. package/src/plugins/dropdown/textStyle.js +43 -31
  114. package/src/plugins/field/mention.js +147 -86
  115. package/src/plugins/index.js +32 -6
  116. package/src/plugins/input/fontSize.js +161 -108
  117. package/src/plugins/input/pageNavigator.js +70 -0
  118. package/src/plugins/modal/audio.js +358 -173
  119. package/src/plugins/modal/drawing.js +531 -0
  120. package/src/plugins/modal/embed.js +886 -0
  121. package/src/plugins/modal/image.js +674 -362
  122. package/src/plugins/modal/link.js +100 -71
  123. package/src/plugins/modal/math.js +367 -167
  124. package/src/plugins/modal/video.js +691 -335
  125. package/src/plugins/popup/anchor.js +222 -0
  126. package/src/suneditor.js +50 -13
  127. package/src/themes/dark.css +122 -0
  128. package/src/typedef.js +130 -0
  129. package/types/assets/icons/defaultIcons.d.ts +153 -0
  130. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  131. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  132. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  133. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  134. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  135. package/types/core/base/eventManager.d.ts +385 -0
  136. package/types/core/base/history.d.ts +81 -0
  137. package/types/core/class/char.d.ts +60 -0
  138. package/types/core/class/component.d.ts +212 -0
  139. package/types/core/class/format.d.ts +616 -0
  140. package/types/core/class/html.d.ts +422 -0
  141. package/types/core/class/menu.d.ts +126 -0
  142. package/types/core/class/nodeTransform.d.ts +93 -0
  143. package/types/core/class/offset.d.ts +522 -0
  144. package/types/core/class/selection.d.ts +188 -0
  145. package/types/core/class/shortcuts.d.ts +142 -0
  146. package/types/core/class/toolbar.d.ts +189 -0
  147. package/types/core/class/ui.d.ts +164 -0
  148. package/types/core/class/viewer.d.ts +140 -0
  149. package/types/core/editor.d.ts +610 -0
  150. package/types/core/section/actives.d.ts +46 -0
  151. package/types/core/section/constructor.d.ts +777 -0
  152. package/types/core/section/context.d.ts +45 -0
  153. package/types/core/section/documentType.d.ts +178 -0
  154. package/types/editorInjector/_classes.d.ts +41 -0
  155. package/types/editorInjector/_core.d.ts +92 -0
  156. package/types/editorInjector/index.d.ts +71 -0
  157. package/types/events.d.ts +273 -0
  158. package/types/helper/clipboard.d.ts +12 -0
  159. package/types/helper/converter.d.ts +197 -0
  160. package/types/helper/dom/domCheck.d.ts +189 -0
  161. package/types/helper/dom/domQuery.d.ts +223 -0
  162. package/types/helper/dom/domUtils.d.ts +226 -0
  163. package/types/helper/dom/index.d.ts +9 -0
  164. package/types/helper/env.d.ts +132 -0
  165. package/types/helper/index.d.ts +174 -0
  166. package/types/helper/keyCodeMap.d.ts +110 -0
  167. package/types/helper/numbers.d.ts +46 -0
  168. package/types/helper/unicode.d.ts +28 -0
  169. package/types/index.d.ts +120 -0
  170. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +173 -103
  171. package/types/langs/ckb.d.ts +3 -0
  172. package/types/langs/cs.d.ts +3 -0
  173. package/types/langs/da.d.ts +3 -0
  174. package/types/langs/de.d.ts +3 -0
  175. package/types/langs/en.d.ts +3 -0
  176. package/types/langs/es.d.ts +3 -0
  177. package/types/langs/fa.d.ts +3 -0
  178. package/types/langs/fr.d.ts +3 -0
  179. package/types/langs/he.d.ts +3 -0
  180. package/types/langs/hu.d.ts +3 -0
  181. package/types/langs/index.d.ts +54 -0
  182. package/types/langs/it.d.ts +3 -0
  183. package/types/langs/ja.d.ts +3 -0
  184. package/types/langs/km.d.ts +3 -0
  185. package/types/langs/ko.d.ts +3 -0
  186. package/types/langs/lv.d.ts +3 -0
  187. package/types/langs/nl.d.ts +3 -0
  188. package/types/langs/pl.d.ts +3 -0
  189. package/types/langs/pt_br.d.ts +3 -0
  190. package/types/langs/ro.d.ts +3 -0
  191. package/types/langs/ru.d.ts +3 -0
  192. package/types/langs/se.d.ts +3 -0
  193. package/types/langs/tr.d.ts +3 -0
  194. package/types/langs/uk.d.ts +3 -0
  195. package/types/langs/ur.d.ts +3 -0
  196. package/types/langs/zh_cn.d.ts +3 -0
  197. package/types/modules/ApiManager.d.ts +125 -0
  198. package/types/modules/Browser.d.ts +326 -0
  199. package/types/modules/ColorPicker.d.ts +131 -0
  200. package/types/modules/Controller.d.ts +251 -0
  201. package/types/modules/Figure.d.ts +517 -0
  202. package/types/modules/FileManager.d.ts +202 -0
  203. package/types/modules/HueSlider.d.ts +136 -0
  204. package/types/modules/Modal.d.ts +111 -0
  205. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  206. package/types/modules/SelectMenu.d.ts +194 -0
  207. package/types/modules/_DragHandle.d.ts +7 -0
  208. package/types/modules/index.d.ts +26 -0
  209. package/types/plugins/browser/audioGallery.d.ts +55 -0
  210. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  211. package/types/plugins/browser/fileGallery.d.ts +55 -0
  212. package/types/plugins/browser/imageGallery.d.ts +51 -0
  213. package/types/plugins/browser/videoGallery.d.ts +57 -0
  214. package/types/plugins/command/blockquote.d.ts +28 -0
  215. package/types/plugins/command/exportPDF.d.ts +46 -0
  216. package/types/plugins/command/fileUpload.d.ts +156 -0
  217. package/types/plugins/command/list_bulleted.d.ts +46 -0
  218. package/types/plugins/command/list_numbered.d.ts +46 -0
  219. package/types/plugins/dropdown/align.d.ts +60 -0
  220. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  221. package/types/plugins/dropdown/font.d.ts +54 -0
  222. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  223. package/types/plugins/dropdown/formatBlock.d.ts +54 -0
  224. package/types/plugins/dropdown/hr.d.ts +71 -0
  225. package/types/plugins/dropdown/layout.d.ts +40 -0
  226. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  227. package/types/plugins/dropdown/list.d.ts +39 -0
  228. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  229. package/types/plugins/dropdown/table.d.ts +627 -0
  230. package/types/plugins/dropdown/template.d.ts +40 -0
  231. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  232. package/types/plugins/field/mention.d.ts +102 -0
  233. package/types/plugins/index.d.ts +107 -0
  234. package/types/plugins/input/fontSize.d.ts +170 -0
  235. package/types/plugins/input/pageNavigator.d.ts +28 -0
  236. package/types/plugins/modal/audio.d.ts +269 -0
  237. package/types/plugins/modal/drawing.d.ts +246 -0
  238. package/types/plugins/modal/embed.d.ts +387 -0
  239. package/types/plugins/modal/image.d.ts +451 -0
  240. package/types/plugins/modal/link.d.ts +128 -0
  241. package/types/plugins/modal/math.d.ts +193 -0
  242. package/types/plugins/modal/video.d.ts +485 -0
  243. package/types/plugins/popup/anchor.d.ts +56 -0
  244. package/types/suneditor.d.ts +51 -0
  245. package/types/typedef.d.ts +233 -0
  246. package/.eslintignore +0 -7
  247. package/.eslintrc.json +0 -64
  248. package/src/assets/icons/_default.js +0 -194
  249. package/src/core/base/events.js +0 -320
  250. package/src/core/class/notice.js +0 -42
  251. package/src/helper/domUtils.js +0 -1177
  252. package/src/modules/FileBrowser.js +0 -271
  253. package/src/plugins/command/exportPdf.js +0 -168
  254. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  255. package/src/themes/test.css +0 -61
  256. package/typings/CommandPlugin.d.ts +0 -8
  257. package/typings/DialogPlugin.d.ts +0 -20
  258. package/typings/FileBrowserPlugin.d.ts +0 -30
  259. package/typings/Module.d.ts +0 -15
  260. package/typings/Plugin.d.ts +0 -42
  261. package/typings/SubmenuPlugin.d.ts +0 -8
  262. package/typings/_classes.d.ts +0 -17
  263. package/typings/_colorPicker.d.ts +0 -60
  264. package/typings/_core.d.ts +0 -55
  265. package/typings/align.d.ts +0 -5
  266. package/typings/audio.d.ts +0 -5
  267. package/typings/backgroundColor.d.ts +0 -5
  268. package/typings/blockquote.d.ts +0 -5
  269. package/typings/char.d.ts +0 -39
  270. package/typings/component.d.ts +0 -38
  271. package/typings/context.d.ts +0 -39
  272. package/typings/converter.d.ts +0 -33
  273. package/typings/dialog.d.ts +0 -28
  274. package/typings/domUtils.d.ts +0 -361
  275. package/typings/editor.d.ts +0 -7
  276. package/typings/editor.ts +0 -542
  277. package/typings/env.d.ts +0 -70
  278. package/typings/eventManager.d.ts +0 -37
  279. package/typings/events.d.ts +0 -262
  280. package/typings/fileBrowser.d.ts +0 -42
  281. package/typings/fileManager.d.ts +0 -67
  282. package/typings/font.d.ts +0 -5
  283. package/typings/fontColor.d.ts +0 -5
  284. package/typings/fontSize.d.ts +0 -5
  285. package/typings/format.d.ts +0 -191
  286. package/typings/formatBlock.d.ts +0 -5
  287. package/typings/history.d.ts +0 -48
  288. package/typings/horizontalRule.d.ts +0 -5
  289. package/typings/image.d.ts +0 -5
  290. package/typings/imageGallery.d.ts +0 -5
  291. package/typings/index.d.ts +0 -21
  292. package/typings/index.modules.d.ts +0 -11
  293. package/typings/index.plugins.d.ts +0 -58
  294. package/typings/lineHeight.d.ts +0 -5
  295. package/typings/link.d.ts +0 -5
  296. package/typings/list.d.ts +0 -5
  297. package/typings/math.d.ts +0 -5
  298. package/typings/mediaContainer.d.ts +0 -25
  299. package/typings/mention.d.ts +0 -5
  300. package/typings/node.d.ts +0 -57
  301. package/typings/notice.d.ts +0 -16
  302. package/typings/numbers.d.ts +0 -29
  303. package/typings/offset.d.ts +0 -24
  304. package/typings/options.d.ts +0 -589
  305. package/typings/paragraphStyle.d.ts +0 -5
  306. package/typings/resizing.d.ts +0 -141
  307. package/typings/selection.d.ts +0 -94
  308. package/typings/shortcuts.d.ts +0 -13
  309. package/typings/suneditor.d.ts +0 -9
  310. package/typings/table.d.ts +0 -5
  311. package/typings/template.d.ts +0 -5
  312. package/typings/textStyle.d.ts +0 -5
  313. package/typings/toolbar.d.ts +0 -32
  314. package/typings/unicode.d.ts +0 -25
  315. package/typings/video.d.ts +0 -5
@@ -0,0 +1,531 @@
1
+ import EditorInjector from '../../editorInjector';
2
+ import { Modal } from '../../modules';
3
+ import { dom, env } from '../../helper';
4
+
5
+ const { _w, isMobile } = env;
6
+
7
+ /**
8
+ * @typedef {Object} DrawingPluginOptions
9
+ * @property {string} [outputFormat="dataurl"] - The output format of the drawing. Options: "dataurl", "svg".
10
+ * @property {boolean} [useFormatType=false] - Whether to enable format type selection (block vs inline).
11
+ * @property {string} [defaultFormatType="block"] - The default format type, either "block" or "inline".
12
+ * @property {boolean} [keepFormatType=false] - Whether to maintain the chosen format type after drawing.
13
+ * @property {number} [lineWidth=5] - The width of the drawing line.
14
+ * @property {boolean} [lineReconnect=false] - Whether to reconnect lines when drawing.
15
+ * @property {CanvasLineCap} [lineCap="round"] - The style of the line cap ("butt", "round", or "square").
16
+ * @property {string} [lineColor=""] - The color of the drawing line.
17
+ * @property {boolean} [canResize=true] - Whether the modal form can be resized.
18
+ * @property {boolean} [maintainRatio=true] - Whether to maintain the aspect ratio when resizing.
19
+ * @property {Object} [formSize={}] - The size configuration for the drawing modal form.
20
+ * @property {string} [formSize.width="750px"] - The width of the modal form.
21
+ * @property {string} [formSize.height="50vh"] - The height of the modal form.
22
+ * @property {string} [formSize.maxWidth=""] - The maximum width of the modal form.
23
+ * @property {string} [formSize.maxHeight=""] - The maximum height of the modal form.
24
+ * @property {string} [formSize.minWidth="150px"] - The minimum width of the modal form.
25
+ * @property {string} [formSize.minHeight="100px"] - The minimum height of the modal form.
26
+ */
27
+
28
+ /**
29
+ * @class
30
+ * @description Drawing modal plugin.
31
+ */
32
+ class Drawing extends EditorInjector {
33
+ static key = 'drawing';
34
+ static type = 'modal';
35
+ static className = '';
36
+
37
+ /**
38
+ * @constructor
39
+ * @param {__se__EditorCore} editor - The root editor instance
40
+ * @param {DrawingPluginOptions} pluginOptions
41
+ */
42
+ constructor(editor, pluginOptions) {
43
+ // plugin basic properties
44
+ super(editor);
45
+ this.title = this.lang.drawing;
46
+ this.icon = 'drawing';
47
+ this.pluginOptions = {
48
+ outputFormat: pluginOptions.outputFormat || 'dataurl', // dataurl, svg
49
+ useFormatType: pluginOptions.useFormatType ?? false,
50
+ defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : 'block',
51
+ keepFormatType: pluginOptions.keepFormatType ?? false,
52
+ lineWidth: pluginOptions.lineWidth || 5,
53
+ lineReconnect: !!pluginOptions.lineReconnect,
54
+ lineCap: ['butt', 'round', 'square'].includes(pluginOptions.lineCap) ? pluginOptions.lineCap : 'round',
55
+ lineColor: pluginOptions.lineColor || '',
56
+ formSize: {
57
+ width: '750px',
58
+ height: '50vh',
59
+ maxWidth: '',
60
+ maxHeight: '',
61
+ minWidth: '150px',
62
+ minHeight: '100px',
63
+ ...pluginOptions.formSize
64
+ },
65
+ canResize: pluginOptions.canResize ?? true,
66
+ maintainRatio: pluginOptions.maintainRatio ?? true
67
+ };
68
+
69
+ // exception
70
+ if (!this.plugins.image) {
71
+ console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need either "image" plugin. Please add the "image" plugin.');
72
+ } else if (this.pluginOptions.outputFormat === 'svg' && !this.plugins.image.pluginOptions.uploadUrl) {
73
+ console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need the "image" plugin with the "uploadUrl" option. Please add the "image" plugin with the "uploadUrl" option.');
74
+ }
75
+
76
+ // create HTML
77
+ const modalEl = CreateHTML_modal(this);
78
+
79
+ // modules
80
+ this.modal = new Modal(this, modalEl);
81
+
82
+ // members
83
+ this.as = this.pluginOptions.defaultFormatType;
84
+ if (this.pluginOptions.useFormatType) {
85
+ this.asBlock = modalEl.querySelector('[data-command="asBlock"]');
86
+ this.asInline = modalEl.querySelector('[data-command="asInline"]');
87
+ this.eventManager.addEvent([this.asBlock, this.asInline], 'click', this.#OnClickAsButton.bind(this));
88
+ }
89
+
90
+ /**
91
+ * @type {HTMLCanvasElement}
92
+ */
93
+ this.canvas = null;
94
+ this.ctx = null;
95
+ this.isDrawing = false;
96
+ this.points = [];
97
+ this.paths = [];
98
+ this.resizeObserver = null;
99
+ this.__events = {
100
+ mousedown: isMobile ? this.#OnCanvasTouchStart.bind(this) : this.#OnCanvasMouseDown.bind(this),
101
+ mousemove: isMobile ? this.#OnCanvasTouchMove.bind(this) : this.#OnCanvasMouseMove.bind(this),
102
+ mouseup: this.#OnCanvasMouseUp.bind(this),
103
+ mouseleave: this.#OnCanvasMouseLeave.bind(this),
104
+ mouseenter: this.#OnCanvasMouseEnter.bind(this)
105
+ };
106
+ this.__eventsRegister = {
107
+ mousedown: null,
108
+ mousemove: null,
109
+ mouseup: null,
110
+ mouseleave: null,
111
+ mouseenter: null
112
+ };
113
+ this.__eventNameMap = {
114
+ mousedown: isMobile ? 'touchstart' : 'mousedown',
115
+ mousemove: isMobile ? 'touchmove' : 'mousemove',
116
+ mouseup: isMobile ? 'touchend' : 'mouseup',
117
+ mouseleave: 'mouseleave',
118
+ mouseenter: 'mouseenter'
119
+ };
120
+
121
+ // init
122
+ this.eventManager.addEvent(modalEl.querySelector('[data-command="remove"]'), 'click', this.#OnRemove.bind(this));
123
+ }
124
+
125
+ /**
126
+ * @editorMethod Modules.Modal
127
+ * @description Executes the method that is called when a "Modal" module's is opened.
128
+ */
129
+ open() {
130
+ if (this.pluginOptions.useFormatType) {
131
+ this._activeAsInline((this.pluginOptions.keepFormatType ? this.as : this.pluginOptions.defaultFormatType) === 'inline');
132
+ }
133
+ this.modal.open();
134
+ this._initDrawing();
135
+ }
136
+
137
+ /**
138
+ * @editorMethod Modules.Modal
139
+ * @description Executes the method that is called when a plugin's "modal" is closed.
140
+ */
141
+ off() {
142
+ this._destroyDrawing();
143
+ }
144
+
145
+ /**
146
+ * @editorMethod Modules.Modal
147
+ * @description This function is called when a form within a modal window is "submit".
148
+ * @returns {boolean} Success or failure
149
+ */
150
+ modalAction() {
151
+ if (this.pluginOptions.outputFormat === 'svg') {
152
+ const files = this._getSVGFileList();
153
+ this.plugins.image.init();
154
+ this.plugins.image.submitFile(files);
155
+ } else {
156
+ // dataurl | svg
157
+ const data = this.canvas.toDataURL();
158
+ const file = { name: 'drawing', size: 0 };
159
+ this.plugins.image.init();
160
+ if (this.as !== 'inline') {
161
+ this.plugins.image.create(data, null, 'auto', '', 'none', file, '');
162
+ } else {
163
+ this.plugins.image.createInline(data, null, 'auto', '', 'none', file, '');
164
+ }
165
+ }
166
+
167
+ return true;
168
+ }
169
+
170
+ /**
171
+ * @private
172
+ * @description Initializes the drawing canvas, sets up event listeners, and configures resize handling.
173
+ */
174
+ _initDrawing() {
175
+ const canvas = (this.canvas = this.modal.form.querySelector('.se-drawing-canvas'));
176
+ this.ctx = canvas.getContext('2d');
177
+ canvas.width = canvas.offsetWidth;
178
+ canvas.height = canvas.offsetHeight;
179
+
180
+ this.points = [];
181
+ this.paths = [];
182
+
183
+ this._setCtx();
184
+
185
+ this.__eventsRegister.mousedown = this.eventManager.addEvent(canvas, this.__eventNameMap.mousedown, this.__events.mousedown, { passive: false, capture: true });
186
+ this.__eventsRegister.mousemove = this.eventManager.addEvent(canvas, this.__eventNameMap.mousemove, this.__events.mousemove, true);
187
+ this.__eventsRegister.mouseup = this.eventManager.addEvent(canvas, this.__eventNameMap.mouseup, this.__events.mouseup, true);
188
+ this.__eventsRegister.mouseleave = this.eventManager.addEvent(canvas, this.__eventNameMap.mouseleave, this.__events.mouseleave);
189
+ this.__eventsRegister.mouseenter = this.eventManager.addEvent(canvas, this.__eventNameMap.mouseenter, this.__events.mouseenter);
190
+
191
+ if (this.resizeObserver) {
192
+ this.resizeObserver.disconnect();
193
+ this.resizeObserver = null;
194
+ }
195
+
196
+ if (env.isResizeObserverSupported) {
197
+ this.resizeObserver = new ResizeObserver(() => {
198
+ const prevWidth = canvas.width;
199
+ const prevHeight = canvas.height;
200
+ const newWidth = canvas.offsetWidth;
201
+ const newHeight = canvas.offsetHeight;
202
+ canvas.width = newWidth;
203
+ canvas.height = newHeight;
204
+ if (prevWidth !== canvas.width || prevHeight !== canvas.height) {
205
+ if (this.pluginOptions.maintainRatio) this._adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight);
206
+ this._drawAll();
207
+ }
208
+ });
209
+
210
+ this.resizeObserver.observe(canvas);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * @private
216
+ * @description Destroys the drawing canvas, removes event listeners, and clears stored drawing data.
217
+ */
218
+ _destroyDrawing() {
219
+ if (this.resizeObserver) {
220
+ this.resizeObserver.disconnect();
221
+ this.resizeObserver = null;
222
+ }
223
+
224
+ if (this.canvas) {
225
+ this.eventManager.removeEvent(this.__eventsRegister.mousedown);
226
+ this.eventManager.removeEvent(this.__eventsRegister.mousemove);
227
+ this.eventManager.removeEvent(this.__eventsRegister.mouseup);
228
+ this.eventManager.removeEvent(this.__eventsRegister.mouseleave);
229
+ this.eventManager.removeEvent(this.__eventsRegister.mouseenter);
230
+ }
231
+
232
+ this.canvas = null;
233
+ this.ctx = null;
234
+ this.points = [];
235
+ this.paths = [];
236
+ this.isDrawing = false;
237
+ }
238
+
239
+ /**
240
+ * @private
241
+ * @description Configures the drawing context (canvas settings like line width, color, etc.).
242
+ */
243
+ _setCtx() {
244
+ this.ctx.lineWidth = this.pluginOptions.lineWidth;
245
+ this.ctx.lineCap = this.pluginOptions.lineCap;
246
+ this.ctx.strokeStyle = this.pluginOptions.lineColor || _w.getComputedStyle(this.carrierWrapper).color;
247
+ }
248
+
249
+ /**
250
+ * @private
251
+ * @description Draws the current stroke based on collected points.
252
+ */
253
+ _draw() {
254
+ this._setCtx();
255
+ this.ctx.beginPath();
256
+ this.points.forEach(([x, y], i) => {
257
+ if (i === 0) {
258
+ this.ctx.moveTo(x, y);
259
+ } else {
260
+ this.ctx.lineTo(x, y);
261
+ }
262
+ });
263
+ this.ctx.stroke();
264
+ }
265
+
266
+ /**
267
+ * @private
268
+ * @description Redraws all stored paths onto the canvas.
269
+ */
270
+ _drawAll() {
271
+ this._setCtx();
272
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
273
+ this.paths.forEach((path) => {
274
+ this.points = path;
275
+ this._draw();
276
+ });
277
+ this.points = [];
278
+ }
279
+
280
+ /**
281
+ * @private
282
+ * @description Adjusts all stored paths to fit new canvas dimensions after a resize event.
283
+ * @param {number} prevWidth - The previous width of the canvas.
284
+ * @param {number} prevHeight - The previous height of the canvas.
285
+ * @param {number} newWidth - The new width of the canvas.
286
+ * @param {number} newHeight - The new height of the canvas.
287
+ */
288
+ _adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight) {
289
+ const xRatio = newWidth / prevWidth;
290
+ const yRatio = newHeight / prevHeight;
291
+
292
+ this.paths = this.paths.map((path) => path.map(([x, y]) => [x * xRatio, y * yRatio]));
293
+ }
294
+
295
+ /**
296
+ * @private
297
+ * @description Clears the canvas and resets stored drawing paths.
298
+ */
299
+ _clearCanvas() {
300
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
301
+ this.points = [];
302
+ this.paths = [];
303
+ }
304
+
305
+ /**
306
+ * @private
307
+ * @description Generates an SVG representation of the drawn content.
308
+ * @returns {*} The generated SVG element.
309
+ */
310
+ _getSVG() {
311
+ const svgNS = 'http://www.w3.org/2000/svg';
312
+ const svg = document.createElementNS(svgNS, 'svg');
313
+ svg.setAttribute('width', this.canvas.width + '');
314
+ svg.setAttribute('height', this.canvas.height + '');
315
+ svg.setAttribute('viewBox', `0 0 ${this.canvas.width} ${this.canvas.height}`);
316
+ svg.setAttribute('xmlns', svgNS);
317
+
318
+ this.paths.forEach((path) => {
319
+ const pathData = path.reduce((acc, [x, y], i) => {
320
+ return acc + (i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`);
321
+ }, '');
322
+ const svgPath = document.createElementNS(svgNS, 'path');
323
+ svgPath.setAttribute('d', pathData);
324
+ svgPath.setAttribute('fill', 'none');
325
+ svgPath.setAttribute('stroke', String(this.ctx.strokeStyle));
326
+ svgPath.setAttribute('stroke-width', this.ctx.lineWidth + '');
327
+ svg.appendChild(svgPath);
328
+ });
329
+
330
+ return svg;
331
+ }
332
+
333
+ /**
334
+ * @private
335
+ * @description Converts the SVG element into a downloadable file.
336
+ * @returns {FileList} A FileList containing the generated SVG file.
337
+ */
338
+ _getSVGFileList() {
339
+ const svgElement = this._getSVG();
340
+ const serializer = new XMLSerializer();
341
+ const svgString = serializer.serializeToString(svgElement);
342
+ const blob = new Blob([svgString], { type: 'image/svg+xml' });
343
+ const file = new File([blob], 'drawing.svg', { type: 'image/svg+xml' });
344
+
345
+ // Creating a FileList
346
+ const dataTransfer = new DataTransfer();
347
+ dataTransfer.items.add(file);
348
+
349
+ return dataTransfer.files;
350
+ }
351
+
352
+ /**
353
+ * @private
354
+ * @description Retrieves touch coordinates relative to the canvas.
355
+ * @param {TouchEvent} e - The touch event.
356
+ * @returns {{x: number, y: number}} An object containing the x and y coordinates.
357
+ */
358
+ _getCanvasTouchPointer(e) {
359
+ const { touches } = e;
360
+ const rect = this.canvas.getBoundingClientRect();
361
+ const x = touches[0].clientX - rect.left;
362
+ const y = touches[0].clientY - rect.top;
363
+ return { x, y };
364
+ }
365
+
366
+ /**
367
+ * @private
368
+ * @description Activates either block or inline format mode for inserted drawings.
369
+ * @param {boolean} isInline - Whether the drawing should be inserted as an inline element.
370
+ */
371
+ _activeAsInline(isInline) {
372
+ if (isInline) {
373
+ dom.utils.addClass(this.asInline, 'on');
374
+ dom.utils.removeClass(this.asBlock, 'on');
375
+ this.as = 'inline';
376
+ } else {
377
+ dom.utils.addClass(this.asBlock, 'on');
378
+ dom.utils.removeClass(this.asInline, 'on');
379
+ this.as = 'block';
380
+ }
381
+ }
382
+
383
+ /**
384
+ * @param {MouseEvent} e - Event object
385
+ */
386
+ #OnCanvasMouseDown(e) {
387
+ e.preventDefault();
388
+ this.isDrawing = true;
389
+ this.points.push([e.offsetX, e.offsetY]);
390
+ this._draw();
391
+ }
392
+
393
+ /**
394
+ * @param {MouseEvent} e - Event object
395
+ */
396
+ #OnCanvasMouseMove(e) {
397
+ e.preventDefault();
398
+ if (!this.isDrawing) return;
399
+ this.points.push([e.offsetX, e.offsetY]);
400
+ this._draw();
401
+ }
402
+
403
+ /**
404
+ * @param {TouchEvent} e - Event object
405
+ */
406
+ #OnCanvasTouchStart(e) {
407
+ e.preventDefault();
408
+ const { x, y } = this._getCanvasTouchPointer(e);
409
+ this.isDrawing = true;
410
+ this.points.push([x, y]);
411
+ this._draw();
412
+ }
413
+
414
+ /**
415
+ * @param {TouchEvent} e - Event object
416
+ */
417
+ #OnCanvasTouchMove(e) {
418
+ e.preventDefault();
419
+ const { x, y } = this._getCanvasTouchPointer(e);
420
+ if (!this.isDrawing) return;
421
+ this.points.push([x, y]);
422
+ this._draw();
423
+ }
424
+
425
+ #OnCanvasMouseUp() {
426
+ this.isDrawing = false;
427
+ if (this.points.length > 0) {
428
+ this.paths.push([...this.points]);
429
+ this.points = [];
430
+ }
431
+ }
432
+
433
+ #OnCanvasMouseLeave() {
434
+ if (this.isDrawing) {
435
+ this.paths.push([...this.points]);
436
+ if (!this.pluginOptions.lineReconnect) {
437
+ this.points = [];
438
+ this.isDrawing = false;
439
+ }
440
+ }
441
+ }
442
+
443
+ /**
444
+ * @param {MouseEvent} e - Event object
445
+ */
446
+ #OnCanvasMouseEnter(e) {
447
+ if (e.buttons === 1) {
448
+ this.isDrawing = true;
449
+ if (!this.pluginOptions.lineReconnect) {
450
+ this.points.push([e.offsetX, e.offsetY]);
451
+ } else {
452
+ const lastPath = this.paths[this.paths.length - 1];
453
+ const lastPoint = lastPath[lastPath.length - 1];
454
+ this.points.push([lastPoint[0], lastPoint[1]]);
455
+ this.points.push([e.offsetX, e.offsetY]);
456
+ }
457
+ this._draw();
458
+ }
459
+ }
460
+
461
+ #OnRemove() {
462
+ this._clearCanvas();
463
+ }
464
+
465
+ /**
466
+ * @param {MouseEvent} e - Event object
467
+ */
468
+ #OnClickAsButton(e) {
469
+ this._activeAsInline(dom.query.getEventTarget(e).getAttribute('data-command') === 'asInline');
470
+ }
471
+ }
472
+
473
+ function CreateHTML_modal({ lang, icons, pluginOptions }) {
474
+ const { width, height, maxWidth, maxHeight, minWidth, minHeight } = pluginOptions.formSize;
475
+ const html = /*html*/ `
476
+ <form>
477
+ <div class="se-modal-header">
478
+ <button type="button" data-command="close" class="se-btn se-close-btn" title="${lang.close}" aria-label="${lang.close}">
479
+ ${icons.cancel}
480
+ </button>
481
+ <span class="se-modal-title">${lang.drawing_modal_title}</span>
482
+ </div>
483
+ <div class="se-modal-body" style="width: ${width}; height: ${height}; min-width: ${minWidth}; min-height: ${minHeight};">
484
+ <canvas class="se-drawing-canvas" style="width: 100%; height: 100%;"></canvas>
485
+ ${pluginOptions.canResize ? '<div class="se-modal-resize-handle-w"></div><div class="se-modal-resize-handle-h"></div><div class="se-modal-resize-handle-c"></div>' : ''}
486
+ </div>
487
+ <div class="se-modal-body-bottom">
488
+ <div class="se-modal-form">
489
+ <div class="se-modal-flex-form">
490
+ ${
491
+ pluginOptions.useFormatType
492
+ ? /*html*/ `
493
+ <div class="se-modal-flex-group">
494
+ <button type="button" class="se-btn se-tooltip" data-command="asBlock" aria-label="${lang.blockStyle}">
495
+ ${icons.as_block}
496
+ ${dom.utils.createTooltipInner(lang.blockStyle)}
497
+ </button>
498
+ <button type="button" class="se-btn se-tooltip" data-command="asInline" aria-label="${lang.inlineStyle}">
499
+ ${icons.as_inline}
500
+ ${dom.utils.createTooltipInner(lang.inlineStyle)}
501
+ </button>
502
+ </div>`
503
+ : ''
504
+ }
505
+ <div class="se-modal-flex-group">
506
+ <button type="button" class="se-btn se-tooltip" data-command="remove" aria-label="${lang.remove}">
507
+ ${icons.eraser}
508
+ ${dom.utils.createTooltipInner(lang.remove)}
509
+ </button>
510
+ </div>
511
+ </div>
512
+ </div>
513
+ </div>
514
+ <div class="se-modal-footer">
515
+ <button type="submit" class="se-btn-primary" title="${lang.submitButton}" aria-label="${lang.submitButton}">
516
+ <span>${lang.submitButton}</span>
517
+ </button>
518
+ </div>
519
+ </form>`;
520
+
521
+ return dom.utils.createElement(
522
+ 'DIV',
523
+ {
524
+ class: 'se-modal-content se-modal-responsive',
525
+ style: `max-width: ${maxWidth}; max-height: ${maxHeight};`
526
+ },
527
+ html
528
+ );
529
+ }
530
+
531
+ export default Drawing;