suneditor 2.46.1 → 3.0.0-alpha.1

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 (290) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.json +64 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/LICENSE.txt +1 -1
  5. package/README.md +174 -805
  6. package/dist/suneditor.min.css +1 -0
  7. package/dist/suneditor.min.js +1 -2
  8. package/package.json +96 -70
  9. package/src/assets/icons/_default.js +194 -0
  10. package/src/assets/suneditor-content.css +646 -0
  11. package/src/assets/suneditor.css +3378 -0
  12. package/src/core/base/eventHandlers/handler_toolbar.js +114 -0
  13. package/src/core/base/eventHandlers/handler_ww_clipboard.js +31 -0
  14. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +69 -0
  15. package/src/core/base/eventHandlers/handler_ww_key_input.js +975 -0
  16. package/src/core/base/eventHandlers/handler_ww_mouse.js +118 -0
  17. package/src/core/base/eventManager.js +1115 -0
  18. package/src/core/base/events.js +320 -0
  19. package/src/core/base/history.js +301 -0
  20. package/src/core/class/char.js +146 -0
  21. package/src/core/class/component.js +627 -0
  22. package/src/core/class/format.js +3255 -0
  23. package/src/core/class/html.js +1621 -0
  24. package/src/core/class/menu.js +260 -0
  25. package/src/core/class/nodeTransform.js +379 -0
  26. package/src/core/class/notice.js +42 -0
  27. package/src/core/class/offset.js +578 -0
  28. package/src/core/class/selection.js +508 -0
  29. package/src/core/class/shortcuts.js +38 -0
  30. package/src/core/class/toolbar.js +440 -0
  31. package/src/core/class/viewer.js +646 -0
  32. package/src/core/editor.js +1593 -0
  33. package/src/core/section/actives.js +107 -0
  34. package/src/core/section/constructor.js +1237 -0
  35. package/src/core/section/context.js +97 -0
  36. package/src/editorInjector/_classes.js +22 -0
  37. package/src/editorInjector/_core.js +28 -0
  38. package/src/editorInjector/index.js +13 -0
  39. package/src/helper/converter.js +313 -0
  40. package/src/helper/domUtils.js +1177 -0
  41. package/src/helper/env.js +250 -0
  42. package/src/helper/index.js +19 -0
  43. package/src/helper/numbers.js +68 -0
  44. package/src/helper/unicode.js +43 -0
  45. package/src/langs/ckb.js +161 -0
  46. package/src/langs/cs.js +161 -0
  47. package/src/langs/da.js +161 -0
  48. package/src/langs/de.js +162 -0
  49. package/src/langs/en.js +199 -0
  50. package/src/langs/es.js +162 -0
  51. package/src/langs/fa.js +159 -0
  52. package/src/langs/fr.js +161 -0
  53. package/src/langs/he.js +162 -0
  54. package/src/{lang → langs}/index.js +0 -2
  55. package/src/langs/it.js +162 -0
  56. package/src/langs/ja.js +162 -0
  57. package/src/langs/ko.js +162 -0
  58. package/src/langs/lv.js +162 -0
  59. package/src/langs/nl.js +162 -0
  60. package/src/langs/pl.js +162 -0
  61. package/src/langs/pt_br.js +162 -0
  62. package/src/langs/ro.js +162 -0
  63. package/src/langs/ru.js +162 -0
  64. package/src/langs/se.js +162 -0
  65. package/src/langs/tr.js +159 -0
  66. package/src/langs/ua.js +162 -0
  67. package/src/langs/ur.js +162 -0
  68. package/src/langs/zh_cn.js +162 -0
  69. package/src/modules/ApiManager.js +168 -0
  70. package/src/modules/ColorPicker.js +302 -0
  71. package/src/modules/Controller.js +315 -0
  72. package/src/modules/Figure.js +1160 -0
  73. package/src/modules/FileBrowser.js +271 -0
  74. package/src/modules/FileManager.js +290 -0
  75. package/src/modules/HueSlider.js +513 -0
  76. package/src/modules/Modal.js +177 -0
  77. package/src/modules/ModalAnchorEditor.js +494 -0
  78. package/src/modules/SelectMenu.js +447 -0
  79. package/src/modules/_DragHandle.js +16 -0
  80. package/src/modules/index.js +14 -0
  81. package/src/plugins/command/blockquote.js +47 -47
  82. package/src/plugins/command/exportPdf.js +168 -0
  83. package/src/plugins/command/fileUpload.js +389 -0
  84. package/src/plugins/command/list_bulleted.js +112 -0
  85. package/src/plugins/command/list_numbered.js +115 -0
  86. package/src/plugins/dropdown/align.js +143 -0
  87. package/src/plugins/dropdown/backgroundColor.js +73 -0
  88. package/src/plugins/dropdown/font.js +113 -0
  89. package/src/plugins/dropdown/fontColor.js +73 -0
  90. package/src/plugins/dropdown/formatBlock.js +141 -0
  91. package/src/plugins/dropdown/hr.js +111 -0
  92. package/src/plugins/dropdown/layout.js +72 -0
  93. package/src/plugins/dropdown/lineHeight.js +114 -0
  94. package/src/plugins/dropdown/list.js +107 -0
  95. package/src/plugins/dropdown/paragraphStyle.js +117 -0
  96. package/src/plugins/dropdown/table.js +2810 -0
  97. package/src/plugins/dropdown/template.js +71 -0
  98. package/src/plugins/dropdown/textStyle.js +137 -0
  99. package/src/plugins/field/mention.js +172 -0
  100. package/src/plugins/fileBrowser/imageGallery.js +76 -59
  101. package/src/plugins/index.js +86 -24
  102. package/src/plugins/input/fontSize.js +357 -0
  103. package/src/plugins/modal/audio.js +510 -0
  104. package/src/plugins/modal/image.js +1062 -0
  105. package/src/plugins/modal/link.js +211 -0
  106. package/src/plugins/modal/math.js +347 -0
  107. package/src/plugins/modal/video.js +870 -0
  108. package/src/suneditor.js +62 -67
  109. package/src/themes/test.css +61 -0
  110. package/typings/CommandPlugin.d.ts +8 -0
  111. package/typings/DialogPlugin.d.ts +20 -0
  112. package/typings/FileBrowserPlugin.d.ts +30 -0
  113. package/typings/Lang.d.ts +124 -0
  114. package/typings/Module.d.ts +15 -0
  115. package/typings/Plugin.d.ts +42 -0
  116. package/typings/SubmenuPlugin.d.ts +8 -0
  117. package/typings/_classes.d.ts +17 -0
  118. package/typings/_colorPicker.d.ts +60 -0
  119. package/typings/_core.d.ts +55 -0
  120. package/typings/align.d.ts +5 -0
  121. package/{src/plugins/dialog → typings}/audio.d.ts +1 -1
  122. package/typings/backgroundColor.d.ts +5 -0
  123. package/{src/plugins/command → typings}/blockquote.d.ts +1 -1
  124. package/typings/char.d.ts +39 -0
  125. package/typings/component.d.ts +38 -0
  126. package/typings/context.d.ts +39 -0
  127. package/typings/converter.d.ts +33 -0
  128. package/typings/dialog.d.ts +28 -0
  129. package/typings/domUtils.d.ts +361 -0
  130. package/typings/editor.d.ts +7 -0
  131. package/typings/editor.ts +542 -0
  132. package/typings/env.d.ts +70 -0
  133. package/typings/eventManager.d.ts +37 -0
  134. package/typings/events.d.ts +262 -0
  135. package/typings/fileBrowser.d.ts +42 -0
  136. package/typings/fileManager.d.ts +67 -0
  137. package/typings/font.d.ts +5 -0
  138. package/typings/fontColor.d.ts +5 -0
  139. package/typings/fontSize.d.ts +5 -0
  140. package/typings/format.d.ts +191 -0
  141. package/typings/formatBlock.d.ts +5 -0
  142. package/typings/history.d.ts +48 -0
  143. package/typings/horizontalRule.d.ts +5 -0
  144. package/{src/plugins/dialog → typings}/image.d.ts +1 -1
  145. package/{src/plugins/fileBrowser → typings}/imageGallery.d.ts +1 -1
  146. package/typings/index.d.ts +21 -0
  147. package/{src/plugins/modules/index.d.ts → typings/index.modules.d.ts} +3 -3
  148. package/typings/index.plugins.d.ts +58 -0
  149. package/typings/lineHeight.d.ts +5 -0
  150. package/{src/plugins/dialog → typings}/link.d.ts +1 -1
  151. package/typings/list.d.ts +5 -0
  152. package/{src/plugins/dialog → typings}/math.d.ts +1 -1
  153. package/typings/mediaContainer.d.ts +25 -0
  154. package/typings/node.d.ts +57 -0
  155. package/typings/notice.d.ts +16 -0
  156. package/typings/numbers.d.ts +29 -0
  157. package/typings/offset.d.ts +24 -0
  158. package/typings/options.d.ts +589 -0
  159. package/typings/paragraphStyle.d.ts +5 -0
  160. package/typings/resizing.d.ts +141 -0
  161. package/typings/selection.d.ts +94 -0
  162. package/typings/shortcuts.d.ts +13 -0
  163. package/typings/suneditor.d.ts +9 -0
  164. package/typings/table.d.ts +5 -0
  165. package/typings/template.d.ts +5 -0
  166. package/typings/textStyle.d.ts +5 -0
  167. package/typings/toolbar.d.ts +32 -0
  168. package/typings/unicode.d.ts +25 -0
  169. package/{src/plugins/dialog → typings}/video.d.ts +1 -1
  170. package/dist/css/suneditor.min.css +0 -1
  171. package/src/assets/css/suneditor-contents.css +0 -562
  172. package/src/assets/css/suneditor.css +0 -566
  173. package/src/assets/defaultIcons.js +0 -103
  174. package/src/lang/Lang.d.ts +0 -144
  175. package/src/lang/ckb.d.ts +0 -5
  176. package/src/lang/ckb.js +0 -188
  177. package/src/lang/cs.d.ts +0 -5
  178. package/src/lang/cs.js +0 -188
  179. package/src/lang/da.d.ts +0 -5
  180. package/src/lang/da.js +0 -191
  181. package/src/lang/de.d.ts +0 -5
  182. package/src/lang/de.js +0 -188
  183. package/src/lang/en.d.ts +0 -5
  184. package/src/lang/en.js +0 -188
  185. package/src/lang/es.d.ts +0 -5
  186. package/src/lang/es.js +0 -188
  187. package/src/lang/fa.d.ts +0 -5
  188. package/src/lang/fa.js +0 -188
  189. package/src/lang/fr.d.ts +0 -5
  190. package/src/lang/fr.js +0 -188
  191. package/src/lang/he.d.ts +0 -5
  192. package/src/lang/he.js +0 -188
  193. package/src/lang/index.d.ts +0 -23
  194. package/src/lang/it.d.ts +0 -5
  195. package/src/lang/it.js +0 -188
  196. package/src/lang/ja.d.ts +0 -5
  197. package/src/lang/ja.js +0 -188
  198. package/src/lang/ko.d.ts +0 -5
  199. package/src/lang/ko.js +0 -188
  200. package/src/lang/lv.d.ts +0 -5
  201. package/src/lang/lv.js +0 -188
  202. package/src/lang/nl.d.ts +0 -5
  203. package/src/lang/nl.js +0 -188
  204. package/src/lang/pl.d.ts +0 -5
  205. package/src/lang/pl.js +0 -188
  206. package/src/lang/pt_br.d.ts +0 -5
  207. package/src/lang/pt_br.js +0 -189
  208. package/src/lang/ro.d.ts +0 -5
  209. package/src/lang/ro.js +0 -188
  210. package/src/lang/ru.d.ts +0 -5
  211. package/src/lang/ru.js +0 -188
  212. package/src/lang/se.d.ts +0 -5
  213. package/src/lang/se.js +0 -191
  214. package/src/lang/tr.d.ts +0 -5
  215. package/src/lang/tr.js +0 -191
  216. package/src/lang/ua.d.ts +0 -5
  217. package/src/lang/ua.js +0 -188
  218. package/src/lang/ur.d.ts +0 -5
  219. package/src/lang/ur.js +0 -188
  220. package/src/lang/zh_cn.d.ts +0 -5
  221. package/src/lang/zh_cn.js +0 -187
  222. package/src/lib/constructor.js +0 -954
  223. package/src/lib/context.d.ts +0 -42
  224. package/src/lib/context.js +0 -71
  225. package/src/lib/core.d.ts +0 -1135
  226. package/src/lib/core.js +0 -9395
  227. package/src/lib/history.d.ts +0 -48
  228. package/src/lib/history.js +0 -219
  229. package/src/lib/util.d.ts +0 -678
  230. package/src/lib/util.js +0 -2131
  231. package/src/options.d.ts +0 -608
  232. package/src/plugins/CommandPlugin.d.ts +0 -8
  233. package/src/plugins/DialogPlugin.d.ts +0 -20
  234. package/src/plugins/FileBrowserPlugin.d.ts +0 -30
  235. package/src/plugins/Module.d.ts +0 -15
  236. package/src/plugins/Plugin.d.ts +0 -42
  237. package/src/plugins/SubmenuPlugin.d.ts +0 -8
  238. package/src/plugins/dialog/audio.js +0 -559
  239. package/src/plugins/dialog/image.js +0 -1126
  240. package/src/plugins/dialog/link.js +0 -223
  241. package/src/plugins/dialog/math.js +0 -295
  242. package/src/plugins/dialog/mention.js +0 -242
  243. package/src/plugins/dialog/video.js +0 -979
  244. package/src/plugins/index.d.ts +0 -79
  245. package/src/plugins/modules/_anchor.js +0 -461
  246. package/src/plugins/modules/_colorPicker.d.ts +0 -60
  247. package/src/plugins/modules/_colorPicker.js +0 -201
  248. package/src/plugins/modules/_notice.d.ts +0 -21
  249. package/src/plugins/modules/_notice.js +0 -72
  250. package/src/plugins/modules/_selectMenu.js +0 -119
  251. package/src/plugins/modules/component.d.ts +0 -25
  252. package/src/plugins/modules/component.js +0 -81
  253. package/src/plugins/modules/dialog.d.ts +0 -28
  254. package/src/plugins/modules/dialog.js +0 -175
  255. package/src/plugins/modules/fileBrowser.d.ts +0 -42
  256. package/src/plugins/modules/fileBrowser.js +0 -374
  257. package/src/plugins/modules/fileManager.d.ts +0 -67
  258. package/src/plugins/modules/fileManager.js +0 -326
  259. package/src/plugins/modules/index.js +0 -9
  260. package/src/plugins/modules/resizing.d.ts +0 -154
  261. package/src/plugins/modules/resizing.js +0 -903
  262. package/src/plugins/submenu/align.d.ts +0 -5
  263. package/src/plugins/submenu/align.js +0 -160
  264. package/src/plugins/submenu/font.d.ts +0 -5
  265. package/src/plugins/submenu/font.js +0 -123
  266. package/src/plugins/submenu/fontColor.d.ts +0 -5
  267. package/src/plugins/submenu/fontColor.js +0 -101
  268. package/src/plugins/submenu/fontSize.d.ts +0 -5
  269. package/src/plugins/submenu/fontSize.js +0 -112
  270. package/src/plugins/submenu/formatBlock.d.ts +0 -5
  271. package/src/plugins/submenu/formatBlock.js +0 -273
  272. package/src/plugins/submenu/hiliteColor.d.ts +0 -5
  273. package/src/plugins/submenu/hiliteColor.js +0 -102
  274. package/src/plugins/submenu/horizontalRule.d.ts +0 -5
  275. package/src/plugins/submenu/horizontalRule.js +0 -98
  276. package/src/plugins/submenu/lineHeight.d.ts +0 -5
  277. package/src/plugins/submenu/lineHeight.js +0 -104
  278. package/src/plugins/submenu/list.d.ts +0 -5
  279. package/src/plugins/submenu/list.js +0 -456
  280. package/src/plugins/submenu/paragraphStyle.d.ts +0 -5
  281. package/src/plugins/submenu/paragraphStyle.js +0 -135
  282. package/src/plugins/submenu/table.d.ts +0 -5
  283. package/src/plugins/submenu/table.js +0 -1431
  284. package/src/plugins/submenu/template.d.ts +0 -5
  285. package/src/plugins/submenu/template.js +0 -72
  286. package/src/plugins/submenu/textStyle.d.ts +0 -5
  287. package/src/plugins/submenu/textStyle.js +0 -167
  288. package/src/suneditor.d.ts +0 -9
  289. package/src/suneditor_build.js +0 -18
  290. /package/{src/plugins/dialog → typings}/mention.d.ts +0 -0
@@ -0,0 +1,627 @@
1
+ /**
2
+ * @fileoverview Component class
3
+ */
4
+
5
+ import CoreInjector from '../../editorInjector/_core';
6
+ import { domUtils, env, numbers, unicode } from '../../helper';
7
+ import { Figure, _DragHandle } from '../../modules';
8
+
9
+ const { _w, ON_OVER_COMPONENT } = env;
10
+ const DIR_KEYCODE = /^(3[7-9]|40)$/;
11
+ const DIR_UP_KEYCODE = /^3[7-8]$/;
12
+
13
+ const Component = function (editor) {
14
+ CoreInjector.call(this, editor);
15
+
16
+ // members
17
+ this.info = null;
18
+ this.isSelected = false;
19
+ this.currentTarget = null;
20
+ this.currentPlugin = null;
21
+ this.currentPluginName = '';
22
+ this.currentInfo = null;
23
+ this.__globalEvents = {
24
+ copy: OnCopy_component.bind(this),
25
+ cut: OnCut_component.bind(this),
26
+ keydown: OnKeyDown_component.bind(this),
27
+ mousedown: CloseListener_mousedown.bind(this)
28
+ };
29
+ this._bindClose_copy = null;
30
+ this._bindClose_cut = null;
31
+ this._bindClose_keydown = null;
32
+ this._bindClose_mousedown = null;
33
+ this._bindClose_touchstart = null;
34
+ this.__selectionSelected = false;
35
+
36
+ this.editor.applyFrameRoots((e) => {
37
+ // drag
38
+ const dragHandle = domUtils.createElement('DIV', { class: 'se-drag-handle', draggable: 'true' }, this.icons.selection);
39
+ e.get('wrapper').appendChild(dragHandle);
40
+ this.eventManager.addEvent(dragHandle, 'mouseenter', OnDragEnter.bind(this));
41
+ this.eventManager.addEvent(dragHandle, 'mouseleave', OnDragLeave.bind(this));
42
+ this.eventManager.addEvent(dragHandle, 'dragstart', OnDragStart.bind(this));
43
+ this.eventManager.addEvent(dragHandle, 'dragend', OnDragEnd.bind(this));
44
+ this.eventManager.addEvent(dragHandle, 'click', OnDragClick.bind(this));
45
+ });
46
+ };
47
+
48
+ Component.prototype = {
49
+ /**
50
+ * @description The method to insert a element and return. (used elements : table, hr, image, video)
51
+ * If "element" is "HR", insert and return the new line.
52
+ * @param {Element} element Element to be inserted
53
+ * @param {boolean} notCheckCharCount If true, it will be inserted even if "frameOptions.get('charCounter_max')" is exceeded.
54
+ * @param {boolean} notSelect If true, Do not automatically select the inserted component.
55
+ * @returns {Element}
56
+ */
57
+ insert(element, notCheckCharCount, notSelect) {
58
+ if (this.editor.frameContext.get('isReadOnly') || (!notCheckCharCount && !this.char.check(element))) {
59
+ return null;
60
+ }
61
+
62
+ const r = this.html.remove();
63
+ const isInline = this.isInline(element);
64
+ this.selection.getRangeAndAddLine(this.selection.getRange(), r.container);
65
+ const selectionNode = this.selection.getNode();
66
+ let oNode = null;
67
+ let formatEl = this.format.getLine(selectionNode, null);
68
+
69
+ if (domUtils.isListCell(formatEl)) {
70
+ this.html.insertNode(element, isInline ? null : selectionNode === formatEl ? null : r.container.nextSibling, true);
71
+ if (!isInline && !element.nextSibling) element.parentNode.appendChild(domUtils.createElement('BR'));
72
+ } else {
73
+ if (this.selection.getRange().collapsed && (r.container.nodeType === 3 || domUtils.isBreak(r.container))) {
74
+ const depthFormat = domUtils.getParentElement(r.container, this.format.isBlock.bind(this.format));
75
+ oNode = this.nodeTransform.split(r.container, r.offset, !depthFormat ? 0 : domUtils.getNodeDepth(depthFormat) + 1);
76
+ if (oNode) formatEl = oNode.previousSibling;
77
+ }
78
+ this.html.insertNode(element, isInline ? null : this.format.isBlock(formatEl) ? null : formatEl, true);
79
+ if (!isInline && formatEl && domUtils.isZeroWith(formatEl)) domUtils.removeItem(formatEl);
80
+ }
81
+
82
+ if (isInline) {
83
+ const empty = domUtils.createTextNode(unicode.zeroWidthSpace);
84
+ element.parentNode.insertBefore(empty, element.nextSibling);
85
+ }
86
+
87
+ this.history.push(false);
88
+
89
+ if (!notSelect) {
90
+ this.selection.setRange(element, 0, element, 0);
91
+ const fileComponentInfo = this.get(element);
92
+ if (fileComponentInfo) {
93
+ this.select(fileComponentInfo.target, fileComponentInfo.pluginName);
94
+ } else if (oNode) {
95
+ oNode = domUtils.getEdgeChildNodes(oNode, null).sc || oNode;
96
+ this.selection.setRange(oNode, 0, oNode, 0);
97
+ }
98
+ }
99
+
100
+ return oNode || element;
101
+ },
102
+
103
+ /**
104
+ * @description Gets the file component and that plugin name
105
+ * return: {target, component, pluginName} | null
106
+ * @param {Element} element Target element (figure tag, component div, file tag)
107
+ * @returns {Object|null}
108
+ */
109
+ get(element) {
110
+ if (!element) return null;
111
+
112
+ let target;
113
+ let pluginName = '';
114
+ let options = {};
115
+ let isFile = false;
116
+
117
+ if (this.is(element)) {
118
+ if (domUtils.hasClass(element, 'se-component') && !domUtils.hasClass(element, 'se-inline-component')) element = element.firstElementChild || element;
119
+ if (/^FIGURE$/i.test(element.nodeName)) element = element.firstElementChild;
120
+ if (!element) return null;
121
+
122
+ const comp = this.editor._componentManager.map((f) => f(element)).find((e) => e);
123
+ if (!comp) return null;
124
+ target = comp.target;
125
+ pluginName = comp.pluginName;
126
+ options = comp.options;
127
+ }
128
+
129
+ if (!target && element.nodeName) {
130
+ if (this.__isFiles(element)) {
131
+ isFile = true;
132
+ }
133
+ const comp = this.editor._componentManager.map((f) => f(element)).find((e) => e);
134
+ if (!comp) return null;
135
+ target = comp.target;
136
+ pluginName = comp.pluginName;
137
+ options = comp.options;
138
+ }
139
+
140
+ if (!target) {
141
+ return null;
142
+ }
143
+
144
+ const figureInfo = Figure.GetContainer(target);
145
+ return (this.info = {
146
+ target,
147
+ pluginName,
148
+ options,
149
+ container: figureInfo.container || figureInfo.cover || target,
150
+ cover: figureInfo.cover,
151
+ caption: figureInfo.caption,
152
+ isFile: isFile
153
+ });
154
+ },
155
+
156
+ /**
157
+ * @description The component(image, video) is selected and the resizing module is called.
158
+ * @param {Element} element Element tag (img, iframe, video)
159
+ * @param {string} pluginName Plugin name (image, video)
160
+ */
161
+ select(element, pluginName, isInput) {
162
+ const info = this.get(element);
163
+ if (!info || domUtils.isUneditable(domUtils.getParentElement(element, this.is.bind(this))) || domUtils.isUneditable(element)) return false;
164
+
165
+ const plugin = this.plugins[pluginName];
166
+ if (!plugin) return;
167
+
168
+ if (!isInput && _DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
169
+ this.editor._antiBlur = true;
170
+ this.__selectionSelected = true;
171
+ if (this.isInline(info.container)) {
172
+ this.selection.setRange(info.container, 0, info.container, 0);
173
+ }
174
+ this.editor.blur();
175
+ _w.setTimeout(() => {
176
+ this.__selectionSelected = false;
177
+ });
178
+ }
179
+
180
+ this.isSelected = true;
181
+
182
+ let isNonFigureComponent;
183
+ if (typeof plugin.select === 'function') isNonFigureComponent = plugin.select(element);
184
+
185
+ if (!isNonFigureComponent && !domUtils.hasClass(info.container, 'se-inline-component')) this._setComponentLineBreaker(info.container || info.cover || element);
186
+
187
+ this.currentTarget = element;
188
+ this.currentPlugin = plugin;
189
+ this.currentPluginName = pluginName;
190
+ this.currentInfo = info;
191
+
192
+ _DragHandle.set('__dragInst', this);
193
+
194
+ const __overInfo = _DragHandle.get('__overInfo');
195
+ _w.setTimeout(() => {
196
+ _DragHandle.set('__overInfo', __overInfo === ON_OVER_COMPONENT ? undefined : false);
197
+ if (__overInfo !== ON_OVER_COMPONENT) this.__addGlobalEvent();
198
+ if (!info.isFile) this.__addNotFileGlobalEvent();
199
+ }, 0);
200
+ domUtils.addClass(info.container, 'se-component-selected');
201
+
202
+ if (__overInfo !== ON_OVER_COMPONENT) {
203
+ domUtils.setDisabled(this.editor._controllerOnDisabledButtons, true);
204
+
205
+ // set zero width space
206
+ if (!this.isInline(info.container)) return;
207
+
208
+ const oNode = info.container;
209
+ let zeroWidth = null;
210
+ if (!oNode.previousSibling || domUtils.isBreak(oNode.previousSibling)) {
211
+ zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
212
+ oNode.parentNode.insertBefore(zeroWidth, oNode);
213
+ }
214
+
215
+ if (!oNode.nextSibling || domUtils.isBreak(oNode.nextSibling)) {
216
+ zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
217
+ oNode.parentNode.insertBefore(zeroWidth, oNode.nextSibling);
218
+ }
219
+ } else if (!domUtils.hasClass(info.container, 'se-input-component')) {
220
+ const dragHandle = this.editor.frameContext.get('wrapper').querySelector('.se-drag-handle');
221
+ domUtils.addClass(dragHandle, 'se-drag-handle-full');
222
+ this.editor._visibleControllers(false, false);
223
+
224
+ const sizeTarget = info.caption ? info.target : info.cover || info.container || info.target;
225
+ const { w, h, t, l } = this.offset.getSize(sizeTarget);
226
+
227
+ dragHandle.style.opacity = 0;
228
+ dragHandle.style.width = w + 'px';
229
+ dragHandle.style.height = h + 'px';
230
+ dragHandle.style.top = t + 'px';
231
+ dragHandle.style.left = l + 'px';
232
+
233
+ _DragHandle.set('__dragHandler', dragHandle);
234
+ _DragHandle.set('__dragContainer', info.container);
235
+ _DragHandle.set('__dragCover', info.cover);
236
+
237
+ dragHandle.style.display = 'block';
238
+ }
239
+ },
240
+
241
+ deselect() {
242
+ this.editor._antiBlur = false;
243
+ _DragHandle.set('__overInfo', null);
244
+ this._removeDragEvent(this);
245
+ domUtils.removeClass(this.currentInfo?.container, 'se-component-selected|');
246
+ domUtils.removeClass(this.currentInfo?.cover, 'se-figure-over-selected');
247
+
248
+ const { frameContext } = this.editor;
249
+ frameContext.get('lineBreaker_t').style.display = frameContext.get('lineBreaker_b').style.display = 'none';
250
+
251
+ if (this.currentPlugin && typeof this.currentPlugin.deselect === 'function') {
252
+ this.currentPlugin.deselect(this.currentTarget);
253
+ }
254
+
255
+ this.isSelected = false;
256
+ this.currentPlugin = null;
257
+ this.currentTarget = null;
258
+ this.currentPluginName = '';
259
+ this.currentInfo = null;
260
+ this.__removeGlobalEvent();
261
+ this.editor.__offControllers();
262
+
263
+ domUtils.setDisabled(this.editor._controllerOnDisabledButtons, false);
264
+ },
265
+
266
+ /**
267
+ * @description Determines if the specified node is a block component (e.g., img, iframe, video, audio, table) with the class "se-component"
268
+ * or a direct FIGURE node. This function checks if the node itself is a component
269
+ * or if it belongs to any components identified by the component manager.
270
+ * @param {Node} element The DOM node to check.
271
+ * @returns {boolean} True if the node is a block component or part of it, otherwise false.
272
+ */
273
+ is(element) {
274
+ if (!element) return false;
275
+
276
+ if (/^FIGURE$/i.test(element.nodeName) || domUtils.hasClass(element, 'se-component')) return true;
277
+ if (this.editor._componentManager.find((f) => f(element))) return true;
278
+
279
+ return false;
280
+ },
281
+
282
+ /**
283
+ * @description Checks if the given node is an inline component (class "se-inline-component").
284
+ * If the node is a FIGURE, it checks the parent element instead.
285
+ * It also verifies whether the node is part of an inline component recognized by the component manager.
286
+ * @param {Node} element The DOM node to check.
287
+ * @returns {boolean} True if the node is an inline component or part of it, otherwise false.
288
+ */
289
+ isInline(element) {
290
+ if (!element) return false;
291
+
292
+ if (/^FIGURE$/i.test(element.nodeName)) element = element.parentElement;
293
+ if (domUtils.hasClass(element, 'se-inline-component')) return true;
294
+
295
+ const container = this.editor._componentManager.find((f) => f(element));
296
+ if (container && domUtils.hasClass(element, 'se-inline-component')) return true;
297
+
298
+ return false;
299
+ },
300
+
301
+ /**
302
+ * @description Checks if the specified node qualifies as a basic component within the editor.
303
+ * This function verifies whether the node is recognized as a component by the `is` function, while also ensuring that it is not an inline component as determined by the `isInline` function.
304
+ * This is used to identify block-level elements or standalone components that are not part of the inline component classification.
305
+ * @param {Node} element The DOM node to check.
306
+ * @returns {boolean} True if the node is a basic (non-inline) component, otherwise false.
307
+ */
308
+ isBasic(element) {
309
+ return this.is(element) && !this.isInline(element);
310
+ },
311
+
312
+ __isFiles(element) {
313
+ const nodeName = element.nodeName.toLowerCase();
314
+ return this.editor._fileManager.regExp.test(nodeName) && (!this.editor._fileManager.tagAttrs[nodeName] || this.editor._fileManager.tagAttrs[nodeName]?.every((v) => element.hasAttribute(v)));
315
+ },
316
+
317
+ /**
318
+ * @description Set line breaker of component
319
+ * @param {Element} element Element tag
320
+ * @private
321
+ */
322
+ _setComponentLineBreaker(element) {
323
+ this.eventManager._lineBreakComp = null;
324
+ const fc = this.editor.frameContext;
325
+ const wysiwyg = fc.get('wysiwyg');
326
+
327
+ const info = this.get(element);
328
+ if (!info) return;
329
+
330
+ const yScroll = wysiwyg.scrollY || wysiwyg.scrollTop || 0;
331
+ const wScroll = wysiwyg.scrollX || wysiwyg.scrollLeft || 0;
332
+ const container = info.container;
333
+ const isNonSelected = domUtils.hasClass(container, 'se-flex-component');
334
+ const lb_t = fc.get('lineBreaker_t');
335
+ const lb_b = fc.get('lineBreaker_b');
336
+ const t_style = lb_t.style;
337
+ const b_style = lb_b.style;
338
+ const offsetTarget = container.offsetWidth < element.offsetWidth ? container : element;
339
+ const target = this.editor._figureContainer?.style.display === 'block' ? this.editor._figureContainer : offsetTarget;
340
+ const isList = domUtils.isListCell(container.parentNode);
341
+
342
+ // top
343
+ let componentTop, w;
344
+ const isRtl = this.options.get('_rtl');
345
+ const dir = isRtl ? ['right', 'left'] : ['left', 'right'];
346
+ if (isList ? !container.previousSibling : !this.format.isLine(container.previousElementSibling)) {
347
+ const tH = numbers.get(_w.getComputedStyle(lb_t).height, 1);
348
+ this.eventManager._lineBreakComp = container;
349
+ componentTop = this.offset.get(offsetTarget).top + yScroll;
350
+ w = target.offsetWidth / 2 / 2;
351
+ t_style.top = componentTop - yScroll - tH / 2 + 'px';
352
+ t_style[dir[0]] = (isNonSelected ? 4 : this.offset.get(target).left + w) + 'px';
353
+ t_style[dir[1]] = '';
354
+ lb_t.setAttribute('data-offset', yScroll + ',' + wScroll);
355
+ t_style.display = 'block';
356
+ } else {
357
+ t_style.display = 'none';
358
+ }
359
+
360
+ // bottom
361
+ if (isList ? !container.nextSibling : !this.format.isLine(container.nextElementSibling)) {
362
+ const cStyle = _w.getComputedStyle(lb_b);
363
+ const bH = numbers.get(cStyle.height, 1);
364
+ const bW = numbers.get(cStyle.width, 1);
365
+
366
+ if (!componentTop) {
367
+ this.eventManager._lineBreakComp = container;
368
+ componentTop = this.offset.get(offsetTarget).top + yScroll;
369
+ w = target.offsetWidth / 2 / 2;
370
+ }
371
+
372
+ b_style.top = componentTop + target.offsetHeight - yScroll - bH / 2 + 'px';
373
+ b_style.right = '';
374
+ b_style.left = this.offset.get(target).left + (isRtl ? 0 : target.offsetWidth) - (isNonSelected ? 0 : w) - (isNonSelected ? bW / 2 : bW) + 'px';
375
+
376
+ const bDir = 'left';
377
+ lb_b.setAttribute('data-offset', yScroll + ',' + bDir + ',' + wScroll);
378
+ b_style.display = 'block';
379
+ } else {
380
+ b_style.display = 'none';
381
+ }
382
+ },
383
+
384
+ __addGlobalEvent() {
385
+ this.__removeGlobalEvent();
386
+ this._bindClose_copy = this.eventManager.addGlobalEvent('copy', this.__globalEvents.copy);
387
+ this._bindClose_cut = this.eventManager.addGlobalEvent('cut', this.__globalEvents.cut);
388
+ this._bindClose_keydown = this.eventManager.addGlobalEvent('keydown', this.__globalEvents.keydown);
389
+ },
390
+
391
+ __removeGlobalEvent() {
392
+ this.__removeNotFileGlobalEvent();
393
+ if (this._bindClose_copy) this._bindClose_copy = this.eventManager.removeGlobalEvent(this._bindClose_copy);
394
+ if (this._bindClose_cut) this._bindClose_cut = this.eventManager.removeGlobalEvent(this._bindClose_cut);
395
+ if (this._bindClose_keydown) this._bindClose_keydown = this.eventManager.removeGlobalEvent(this._bindClose_keydown);
396
+ },
397
+
398
+ __addNotFileGlobalEvent() {
399
+ this.__removeNotFileGlobalEvent();
400
+ this._bindClose_mousedown = this.eventManager.addGlobalEvent('mousedown', this.__globalEvents.mousedown, true);
401
+ this._bindClose_touchstart = this.eventManager.addGlobalEvent('touchstart', this.__globalEvents.mousedown, true);
402
+ },
403
+
404
+ __removeNotFileGlobalEvent() {
405
+ if (this._bindClose_mousedown) this._bindClose_mousedown = this.eventManager.removeGlobalEvent(this._bindClose_mousedown);
406
+ if (this._bindClose_touchstart) this._bindClose_touchstart = this.eventManager.removeGlobalEvent(this._bindClose_touchstart);
407
+ },
408
+
409
+ _removeDragEvent() {
410
+ this.carrierWrapper.querySelector('.se-drag-cursor').style.left = '-10000px';
411
+ if (_DragHandle.get('__dragHandler')) _DragHandle.get('__dragHandler').style.display = 'none';
412
+
413
+ domUtils.removeClass([_DragHandle.get('__dragHandler'), _DragHandle.get('__dragContainer')], 'se-dragging');
414
+ domUtils.removeClass([_DragHandle.get('__dragCover'), _DragHandle.get('__dragContainer')], 'se-drag-over');
415
+
416
+ _DragHandle.set('__figureInst', null);
417
+ _DragHandle.set('__dragInst', null);
418
+ _DragHandle.set('__dragHandler', null);
419
+ _DragHandle.set('__dragContainer', null);
420
+ _DragHandle.set('__dragCover', null);
421
+ _DragHandle.set('__dragMove', null);
422
+ _DragHandle.set('__overInfo', null);
423
+ },
424
+
425
+ constructor: Component
426
+ };
427
+
428
+ function OnDragEnter() {
429
+ this.editor._antiBlur = true;
430
+ this.editor._visibleControllers(false, domUtils.hasClass(_DragHandle.get('__dragHandler'), 'se-drag-handle-full'));
431
+ domUtils.addClass(_DragHandle.get('__dragCover') || _DragHandle.get('__dragContainer'), 'se-drag-over');
432
+ }
433
+
434
+ function OnDragLeave() {
435
+ this.editor._antiBlur = false;
436
+ if (!domUtils.hasClass(_DragHandle.get('__dragHandler'), 'se-drag-handle-full')) this.editor._visibleControllers(true, true);
437
+ domUtils.removeClass([_DragHandle.get('__dragCover'), _DragHandle.get('__dragContainer')], 'se-drag-over');
438
+ }
439
+
440
+ function OnDragStart(e) {
441
+ const cover = _DragHandle.get('__dragCover') || _DragHandle.get('__dragContainer');
442
+
443
+ if (!cover) {
444
+ e.preventDefault();
445
+ return;
446
+ }
447
+
448
+ this.editor._antiBlur = false;
449
+ domUtils.addClass(_DragHandle.get('__dragHandler'), 'se-dragging');
450
+ domUtils.addClass(_DragHandle.get('__dragContainer'), 'se-dragging');
451
+ e.dataTransfer.setDragImage(cover, this.options.get('_rtl') ? cover.offsetWidth : -5, -5);
452
+ }
453
+
454
+ function OnDragEnd() {
455
+ this.editor._antiBlur = false;
456
+ domUtils.removeClass([_DragHandle.get('__dragHandler'), _DragHandle.get('__dragContainer')], 'se-dragging');
457
+ this._removeDragEvent();
458
+ }
459
+
460
+ function OnDragClick({ target }) {
461
+ if (!domUtils.hasClass(target, 'se-drag-handle-full')) return;
462
+ const dragInst = _DragHandle.get('__dragInst');
463
+ this.select(dragInst.currentTarget, dragInst.currentPluginName, false);
464
+ }
465
+
466
+ function CloseListener_mousedown({ target }) {
467
+ if (
468
+ this.currentTarget?.contains(target) ||
469
+ domUtils.getParentElement(target, '.se-controller') ||
470
+ domUtils.hasClass(target, 'se-drag-handle') ||
471
+ (this.currentPluginName === this.editor.currentControllerName && this.editor.opendControllers.some(({ form }) => form.contains(target)))
472
+ ) {
473
+ return;
474
+ }
475
+ this.deselect();
476
+ }
477
+
478
+ function OnCopy_component(e) {
479
+ if (domUtils.isInputElement(e.target) && domUtils.getParentElement(e.target, '.se-modal')) return;
480
+
481
+ const info = this.info;
482
+ if (!info) return;
483
+
484
+ SetClipboardComponent(e, info.container, e.clipboardData);
485
+ domUtils.addClass(info.container, 'se-copy');
486
+ // copy effect
487
+ _w.setTimeout(() => {
488
+ domUtils.removeClass(info.container, 'se-copy');
489
+ }, 120);
490
+ }
491
+
492
+ function OnCut_component(e) {
493
+ const info = this.info;
494
+ if (!info) return;
495
+
496
+ SetClipboardComponent(e, info.container, e.clipboardData);
497
+ this.deselect();
498
+ domUtils.removeItem(info.container);
499
+ }
500
+
501
+ function OnKeyDown_component(e) {
502
+ if (this.editor.selectMenuOn) return;
503
+
504
+ const keyCode = e.keyCode;
505
+ const ctrl = e.ctrlKey || e.metaKey || keyCode === 91 || keyCode === 92 || keyCode === 224;
506
+
507
+ // redo, undo
508
+ if (ctrl) {
509
+ if (keyCode !== 17) {
510
+ const info = this.editor.shortcutsKeyMap.get(keyCode + (e.shiftKey ? 1000 : 0));
511
+ if (/^(redo|undo)$/.test(info?.c)) {
512
+ e.preventDefault();
513
+ e.stopPropagation();
514
+ this.editor.run(info.c, info.t, info.e);
515
+ }
516
+ }
517
+ return;
518
+ }
519
+
520
+ // backspace, delete
521
+ if (keyCode === 8 || keyCode === 46) {
522
+ e.preventDefault();
523
+ e.stopPropagation();
524
+ if (typeof this.currentPlugin?.destroy === 'function') {
525
+ this.currentPlugin.destroy(this.currentTarget);
526
+ this.deselect();
527
+ this.editor.focus();
528
+ return;
529
+ }
530
+ }
531
+
532
+ // enter
533
+ if (keyCode === 13) {
534
+ e.preventDefault();
535
+ const compContext = this.currentInfo || this.get(this.currentTarget);
536
+ const container = compContext.container || compContext.target;
537
+ const sibling = container.previousElementSibling || container.nextElementSibling;
538
+ let newEl = null;
539
+ if (domUtils.isListCell(container.parentNode)) {
540
+ newEl = domUtils.createElement('BR');
541
+ } else {
542
+ newEl = domUtils.createElement(this.format.isLine(sibling) && !this.format.isBlock(sibling) ? sibling.nodeName : this.options.get('defaultLine'), null, '<br>');
543
+ }
544
+
545
+ const pluginName = this.currentPluginName;
546
+ this.deselect();
547
+ container.parentNode.insertBefore(newEl, container);
548
+ if (this.select(compContext.target, pluginName) === false) this.editor.blur();
549
+ this.history.push(false);
550
+
551
+ return;
552
+ }
553
+
554
+ // up down, left right
555
+ if (DIR_KEYCODE.test(keyCode)) {
556
+ const { container } = this.get(this.currentTarget);
557
+ const isInline = this.isInline(container || this.currentTarget);
558
+
559
+ let el = null;
560
+ let offset = 1;
561
+ if (isInline) {
562
+ switch (keyCode) {
563
+ case 37: // left
564
+ el = container.previousSibling;
565
+ offset = el?.nodeType === 3 ? el.textContent.length : 1;
566
+ break;
567
+ case 39: // right
568
+ el = container.nextSibling;
569
+ break;
570
+ case 38: {
571
+ // up
572
+ const line = this.format.getLine(container, null);
573
+ el = line?.previousElementSibling;
574
+ offset = 0;
575
+ break;
576
+ }
577
+ case 40: {
578
+ // down
579
+ const line = this.format.getLine(container, null);
580
+ el = line?.nextElementSibling;
581
+ break;
582
+ }
583
+ }
584
+ } else {
585
+ if (DIR_UP_KEYCODE.test(keyCode)) {
586
+ el = container.previousElementSibling;
587
+ } else {
588
+ el = container.nextElementSibling;
589
+ offset = 0;
590
+ }
591
+ }
592
+
593
+ if (!el) return;
594
+
595
+ this.deselect();
596
+
597
+ const elComp = this.get(el);
598
+ if (elComp?.container) {
599
+ e.stopPropagation();
600
+ e.preventDefault();
601
+ this.select(elComp.target, elComp.pluginName);
602
+ } else {
603
+ e.stopPropagation();
604
+ e.preventDefault();
605
+ this.selection.setRange(el, offset, el, offset);
606
+ }
607
+
608
+ return;
609
+ }
610
+
611
+ // ESC
612
+ if (keyCode === 27) {
613
+ this.deselect();
614
+ return;
615
+ }
616
+ }
617
+
618
+ function SetClipboardComponent(e, container, clipboardData) {
619
+ e.preventDefault();
620
+ e.stopPropagation();
621
+ const pasteContainer = container.cloneNode(true);
622
+ domUtils.removeClass(pasteContainer, 'se-component-selected');
623
+ pasteContainer.querySelectorAll('.se-figure-selected').forEach((el) => domUtils.removeClass(el, 'se-figure-selected'));
624
+ clipboardData.setData('text/html', pasteContainer.outerHTML);
625
+ }
626
+
627
+ export default Component;