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
@@ -1,61 +1,101 @@
1
1
  import EditorInjector from '../editorInjector';
2
- import { domUtils, env } from '../helper';
2
+ import { dom, env, keyCodeMap } from '../helper';
3
3
  import { _DragHandle } from '../modules';
4
4
 
5
- const { ON_OVER_COMPONENT } = env;
6
- const NON_RESPONSE_KEYCODE = /^(1[7-9]|20|27|45|11[2-9]|12[0-3]|144|145)$/;
7
- const INDEX_0 = 2147483647;
8
- const INDEX_1 = 2147483646;
9
- const INDEX_2 = 2147483645;
5
+ const { _w, ON_OVER_COMPONENT } = env;
6
+ const INDEX_00 = '2147483646';
7
+ const INDEX_0 = '2147483645';
8
+ const INDEX_S_1 = '2147483641';
9
+ const INDEX_1 = '2147483640';
10
10
 
11
11
  /**
12
- *
13
- * @param {*} inst
14
- * @param {*} element
15
- * @param {{position: "top" | "bottom" | "position", disabled?: boolean}} params params
16
- * When using the "top" position, there should not be an arrow on the controller.
17
- * When using the "bottom" position there should be an arrow on the controller.
12
+ * @typedef {Object} ControllerInfo
13
+ * @property {*} inst The controller instance
14
+ * @property {string} [position="bottom"] The controller position ("bottom"|"top")
15
+ * @property {HTMLElement} [form=null] The controller element
16
+ * @property {HTMLElement|Range} [target=null] The controller target element
17
+ * @property {boolean} [notInCarrier=false] If the controller is not in the "carrierWrapper", set it to true.
18
+ * @property {boolean} [isRangeTarget=false] If the target is a Range, set it to true.
19
+ * @property {boolean} [fixed=false] If the controller is fixed and should not be closed, set it to true.
18
20
  */
19
- const Controller = function (inst, element, params, _name) {
20
- EditorInjector.call(this, inst.editor);
21
-
22
- // members
23
- this.kind = _name || inst.constructor.key || inst.constructor.name;
24
- this.inst = inst;
25
- this.form = element;
26
- this.isOpen = false;
27
- this.currentTarget = null;
28
- this.currentPositionTarget = null;
29
- this.isWWTarget = params.isWWTarget ?? true;
30
- this.position = params.position;
31
- this.disabled = !!params.disabled;
32
- this.parents = params.parents || [];
33
- this.parentsHide = !!params.parentsHide;
34
- this.isInsideForm = !!params.isInsideForm;
35
- this.isOutsideForm = !!params.isOutsideForm;
36
- this._initMethod = typeof params.initMethod === 'function' ? params.initMethod : null;
37
- this.__globalEventHandlers = { keydown: CloseListener_keydown.bind(this), mousedown: CloseListener_mousedown.bind(this) };
38
- this._bindClose_key = null;
39
- this._bindClose_mouse = null;
40
- this.__offset = {};
41
- this.__addOffset = { left: 0, top: 0 };
42
- this.__shadowRootEventForm = null;
43
- this.__shadowRootEventListener = null;
44
-
45
- // add element
46
- this.carrierWrapper.appendChild(element);
47
-
48
- // init
49
- this.eventManager.addEvent(element, 'click', Action.bind(this));
50
- this.eventManager.addEvent(element, 'mouseenter', MouseEnter.bind(this));
51
- this.eventManager.addEvent(element, 'mouseleave', MouseLeave.bind(this));
52
- };
53
-
54
- Controller.prototype = {
21
+
22
+ /**
23
+ * @typedef {Object} ControllerParams
24
+ * @property {"top"|"bottom"} [position="bottom"] Controller position
25
+ * @property {boolean=} [isWWTarget=true] If the controller is in the WYSIWYG area, set it to true.
26
+ * @property {() => void=} [initMethod=null] Method to be called when the controller is closed.
27
+ * @property {boolean=} [disabled=false] If true, When the "controller" is opened, buttons without the "se-component-enabled" class are disabled.
28
+ * @property {Array<HTMLElement>=} [parents=[]] The parent "controller" array when "controller" is opened nested.
29
+ * @property {boolean=} [parentsHide=false] If true, the parent element is hidden when the controller is opened.
30
+ * @property {HTMLElement=} [sibling=null] The related sibling controller element that this controller is positioned relative to.
31
+ * @property {"top"|"side"} [siblingPosition="top"] The relative position of this controller to the sibling element (e.g., display above or beside the sibling).
32
+ * @property {boolean=} [isInsideForm=false] If the controller is inside a form, set it to true.
33
+ * @property {boolean=} [isOutsideForm=false] If the controller is outside a form, set it to true.
34
+ */
35
+
36
+ /**
37
+ * @class
38
+ * @description Controller module class that handles the UI and interaction logic for a specific editor controller element.
39
+ */
40
+ class Controller extends EditorInjector {
41
+ /**
42
+ * @constructor
43
+ * @param {*} inst The instance object that called the constructor.
44
+ * @param {Node} element Controller element
45
+ * @param {ControllerParams} params Controller options
46
+ * @param {?string=} _name An optional name for the controller key.
47
+ */
48
+ constructor(inst, element, params, _name) {
49
+ super(inst.editor);
50
+
51
+ // members
52
+ this.kind = _name || inst.constructor.key || inst.constructor.name;
53
+ this.inst = inst;
54
+ this.form = /** @type {HTMLFormElement} */ (element);
55
+ this.isOpen = false;
56
+ this.currentTarget = null;
57
+ this.currentPositionTarget = null;
58
+ this.isWWTarget = params.isWWTarget ?? true;
59
+ this.position = params.position || 'bottom';
60
+ this.disabled = !!params.disabled;
61
+ this.parents = /** @type {Array<HTMLElement>} */ (params.parents || []);
62
+ this.parentsHide = !!params.parentsHide;
63
+ this.sibling = /** @type {HTMLElement} */ (params.sibling || null);
64
+ this.siblingPosition = ['top', 'side'].includes(params.siblingPosition) ? params.siblingPosition : 'top';
65
+ this.isInsideForm = !!params.isInsideForm;
66
+ this.isOutsideForm = !!params.isOutsideForm;
67
+ this.toTop = false;
68
+ this._reserveIndex = false;
69
+ this._initMethod = typeof params.initMethod === 'function' ? params.initMethod : null;
70
+ this.__globalEventHandlers = { keydown: this.#CloseListener_keydown.bind(this), mousedown: this.#CloseListener_mousedown.bind(this) };
71
+ this._bindClose_key = null;
72
+ this._bindClose_mouse = null;
73
+ /** @type {{left?: number, top?: number, addOfffset?: {left?: number, top?: number}}} */
74
+ this.__offset = {};
75
+ this.__addOffset = { left: 0, top: 0 };
76
+ this.__shadowRootEventForm = null;
77
+ this.__shadowRootEventListener = null;
78
+
79
+ // add element
80
+ this.carrierWrapper.appendChild(element);
81
+
82
+ // init
83
+ this.eventManager.addEvent(element, 'click', this.#Action.bind(this));
84
+ this.eventManager.addEvent(element, 'mouseenter', this.#MouseEnter.bind(this));
85
+ this.eventManager.addEvent(element, 'mouseleave', this.#MouseLeave.bind(this));
86
+ }
87
+
55
88
  /**
56
89
  * @description Open a modal plugin
90
+ * @param {Node|Range} target Target element
91
+ * @param {Node} [positionTarget] Position target element
92
+ * @param {Object} [params={}] params
93
+ * @param {boolean=} params.isWWTarget If the controller is in the WYSIWYG area, set it to true.
94
+ * @param {() => void=} params.initMethod Method to be called when the controller is closed.
95
+ * @param {boolean=} params.disabled If true, When the "controller" is opened, buttons without the "se-component-enabled" class are disabled. (default: this.disabled)
96
+ * @param {{left?: number, top?: number}=} params.addOffset Additional offset values
57
97
  */
58
- open(target, positionTarget, { isWWTarget, initMethod, disabled, addOffset }) {
98
+ open(target, positionTarget, { isWWTarget, initMethod, disabled, addOffset } = {}) {
59
99
  if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) {
60
100
  return;
61
101
  }
@@ -68,19 +108,23 @@ Controller.prototype = {
68
108
  if (this.editor.isBalloon) this.toolbar.hide();
69
109
  else if (this.editor.isSubBalloon) this.subToolbar.hide();
70
110
 
71
- if (disabled ?? this.disabled) domUtils.setDisabled(this.editor._controllerOnDisabledButtons, true);
111
+ if (disabled ?? this.disabled) {
112
+ this.ui.setControllerOnDisabledButtons(true);
113
+ } else {
114
+ this.ui.setControllerOnDisabledButtons(false);
115
+ }
72
116
 
73
- this.currentTarget = target;
74
117
  this.currentPositionTarget = positionTarget || target;
75
118
  this.isWWTarget = isWWTarget ?? this.isWWTarget;
76
119
  if (typeof initMethod === 'function') this._initMethod = initMethod;
77
120
  this.editor.currentControllerName = this.kind;
78
121
 
122
+ this.__addOffset = { left: 0, top: 0 };
79
123
  if (addOffset) this.__addOffset = { ...this.__addOffset, ...addOffset };
80
124
 
81
125
  const parents = this.isOutsideForm ? this.parents : [];
82
126
  this.editor.opendControllers?.forEach((e) => {
83
- if (!parents.includes(e.form)) e.form.style.zIndex = INDEX_2;
127
+ if (!parents.includes(e.form)) e.form.style.zIndex = INDEX_1;
84
128
  });
85
129
 
86
130
  if (this.parentsHide) {
@@ -90,20 +134,34 @@ Controller.prototype = {
90
134
  }
91
135
 
92
136
  this.__addGlobalEvent();
93
- this._setControllerPosition(this.form, this.currentPositionTarget);
94
- this._controllerOn(this.form, target);
137
+
138
+ // add sibling offset
139
+ if (this.sibling) {
140
+ if (this.siblingPosition === 'top') {
141
+ this.__addOffset.top += -this.sibling.offsetHeight + 1;
142
+ } else {
143
+ this.__addOffset.left += this.form.offsetWidth + this.sibling.offsetWidth - 1;
144
+ }
145
+ }
146
+ // display controller
147
+ this._setControllerPosition(this.form, this.currentPositionTarget, false);
148
+
149
+ const isRangeTarget = target instanceof Range;
150
+ this.currentTarget = isRangeTarget ? null : target;
151
+ this._controllerOn(this.form, target, isRangeTarget);
95
152
  this._w.setTimeout(() => _DragHandle.set('__overInfo', false), 0);
96
- },
153
+ }
97
154
 
98
155
  /**
99
156
  * @description Close a modal plugin
100
- * The plugin's "init" method is called.
157
+ * - The plugin's "init" method is called.
158
+ * @param {boolean=} force If true, parent controllers are forcibly closed.
101
159
  */
102
160
  close(force) {
103
161
  if (!this.isOpen) return;
104
162
 
163
+ this.toTop = false;
105
164
  this.isOpen = false;
106
- this.editor._antiBlur = false;
107
165
  this.__offset = {};
108
166
  this.__addOffset = { left: 0, top: 0 };
109
167
 
@@ -121,43 +179,58 @@ Controller.prototype = {
121
179
  if (this.parents.length > 0) return;
122
180
  if (typeof this.inst.close === 'function') this.inst.close();
123
181
  this.component.deselect();
124
- },
182
+ }
125
183
 
126
184
  /**
127
185
  * @description Hide controller
128
186
  */
129
187
  hide() {
130
188
  this.form.style.display = 'none';
131
- },
189
+ }
132
190
 
133
191
  /**
134
192
  * @description Show controller
135
193
  */
136
194
  show() {
137
- this._setControllerPosition(this.form, this.currentPositionTarget);
138
- },
195
+ this._setControllerPosition(this.form, this.currentPositionTarget, false);
196
+ }
197
+
198
+ /**
199
+ * @description Sets whether the element (form) should be brought to the top based on z-index.
200
+ * @param {boolean} value - true: '2147483646', false: '2147483645'.
201
+ */
202
+ bringToTop(value) {
203
+ this.toTop = value;
204
+ this.form.style.zIndex = value ? INDEX_00 : INDEX_0;
205
+ }
139
206
 
140
207
  /**
141
208
  * @description Reset controller position
142
- * @param {Element|undefined} target
209
+ * @param {Node=} target
143
210
  */
144
211
  resetPosition(target) {
145
- this._setControllerPosition(this.form, target || this.currentPositionTarget);
146
- },
212
+ this._setControllerPosition(this.form, target || this.currentPositionTarget, true);
213
+ }
147
214
 
148
215
  /**
216
+ * @private
149
217
  * @description Show controller at editor area (controller elements, function, "controller target element(@Required)", "controller name(@Required)", etc..)
150
- * @param {any} arguments controller elements, function..
218
+ * @param {HTMLFormElement} form Controller element
219
+ * @param {Node|Range} target Controller target element
220
+ * @param {boolean} isRangeTarget If the target is a Range, set it to true.
151
221
  */
152
- _controllerOn(form, target) {
153
- const params = {
222
+ async _controllerOn(form, target, isRangeTarget) {
223
+ /** @type {ControllerInfo} */
224
+ const info = {
154
225
  position: this.position,
155
- form: form,
156
- target: target,
157
- inst: this
226
+ inst: this,
227
+ form: /** @type {HTMLElement} */ (form),
228
+ target: /** @type {HTMLElement} */ (target),
229
+ isRangeTarget,
230
+ notInCarrier: !this.carrierWrapper.contains(form)
158
231
  };
159
232
 
160
- if (this.triggerEvent('onBeforeShowController', { caller: this.kind, frameContext: this.editor.frameContext, params }) === false) return;
233
+ if ((await this.triggerEvent('onBeforeShowController', { caller: this.kind, frameContext: this.editor.frameContext, info })) === false) return;
161
234
 
162
235
  form.style.display = 'block';
163
236
  if (this._shadowRoot) {
@@ -169,72 +242,110 @@ Controller.prototype = {
169
242
  this.editor._controllerTargetContext = this.editor.frameContext.get('topArea');
170
243
 
171
244
  if (!this.isOpen) {
172
- this.editor.opendControllers.push({
173
- position: this.position,
174
- form: form,
175
- target: target,
176
- inst: this
177
- });
245
+ this.editor.opendControllers.push(info);
178
246
  }
179
247
 
180
248
  this.isOpen = true;
181
- this.editor._antiBlur = true;
182
- this.triggerEvent('onShowController', { caller: this.kind, frameContext: this.editor.frameContext, params });
183
- },
249
+ this.editor._preventBlur = true;
250
+ this.editor.status.onSelected = true;
251
+ this.triggerEvent('onShowController', { caller: this.kind, frameContext: this.editor.frameContext, info });
252
+ }
184
253
 
185
254
  /**
186
- * @description Hide controller at editor area (link button, image resize button..)
187
- * @param {KeyboardEvent|MouseEvent|null} e Event object when called from mousedown and keydown events registered in "_controllerOn"
188
255
  * @private
256
+ * @description Hide controller at editor area (link button, image resize button..)
189
257
  */
190
258
  _controllerOff() {
191
259
  this.form.style.display = 'none';
192
260
  this.editor.opendControllers = this.editor.opendControllers.filter((v) => v.form !== this.form);
193
261
  if (this.editor.currentControllerName !== this.kind && this.editor.opendControllers.length > 0) return;
194
262
 
195
- if (this.disabled) domUtils.setDisabled(this.editor._controllerOnDisabledButtons, false);
263
+ this.ui.setControllerOnDisabledButtons(false);
264
+
196
265
  this.editor.frameContext.get('lineBreaker_t').style.display = this.editor.frameContext.get('lineBreaker_b').style.display = 'none';
197
266
  this.editor.effectNode = null;
198
267
  this.editor.currentControllerName = '';
199
- this.editor._antiBlur = false;
268
+ this.editor._preventBlur = false;
200
269
  this.editor._controllerTargetContext = null;
270
+ _w.setTimeout(() => {
271
+ this.editor.status.onSelected = false;
272
+ }, 0);
201
273
  if (this.__shadowRootEventForm) {
202
274
  this.__shadowRootEventForm.removeEventListener('mousedown', this.__shadowRootEventListener);
203
275
  this.__shadowRootEventForm = this.__shadowRootEventListener = null;
204
276
  }
205
277
  if (typeof this.inst.reset === 'function') this.inst.reset();
206
- },
278
+ }
207
279
 
208
280
  /**
281
+ * @private
209
282
  * @description Specify the position of the controller.
210
- * @param {Element} controller Controller element.
211
- * @param {Element} referEl Element that is the basis of the controller's position.
283
+ * @param {HTMLElement} controller Controller element.
284
+ * @param {Node|Range} refer Element or Range that is the basis of the controller's position.
285
+ * @param {boolean} [skipAutoReposition=false] If true, skips scroll/resize-based automatic positioning logic.
212
286
  */
213
- _setControllerPosition(controller, referEl) {
214
- controller.style.zIndex = INDEX_1;
287
+ _setControllerPosition(controller, refer, skipAutoReposition) {
215
288
  controller.style.visibility = 'hidden';
216
289
  controller.style.display = 'block';
217
290
 
218
- if (!this.offset.setAbsPosition(controller, referEl, { addOffset: this.__addOffset, position: this.position, isWWTarget: this.isWWTarget, inst: this })) {
219
- this.hide();
220
- return;
291
+ if (this.selection.isRange(refer)) {
292
+ if (!this.offset.setRangePosition(this.form, /** @type {Range} */ (refer), { position: 'bottom' })) {
293
+ this.hide();
294
+ return;
295
+ }
296
+ } else {
297
+ if (refer) {
298
+ const positionResult = this.offset.setAbsPosition(controller, /** @type {HTMLElement} */ (refer), { addOffset: this.__addOffset, position: this.position, isWWTarget: this.isWWTarget, inst: this });
299
+ if (!positionResult) {
300
+ this.hide();
301
+ return;
302
+ }
303
+
304
+ if (!skipAutoReposition && this.sibling && this.siblingPosition === 'top' && positionResult.position !== this.position) {
305
+ const resetPosition = controller.offsetTop - this.__addOffset.top;
306
+ if (positionResult.position === 'bottom') {
307
+ this._reserveIndex = true;
308
+ controller.style.top = resetPosition + this.sibling.offsetHeight - 2 + 'px';
309
+ } else {
310
+ controller.style.top = resetPosition - this.sibling.offsetHeight + 2 + 'px';
311
+ }
312
+ } else {
313
+ this._reserveIndex = false;
314
+ }
315
+ }
221
316
  }
222
317
 
318
+ controller.style.zIndex = this.toTop ? INDEX_0 : this._reserveIndex ? INDEX_S_1 : INDEX_1;
223
319
  controller.style.visibility = '';
224
- },
320
+ }
225
321
 
322
+ /**
323
+ * @private
324
+ * @description Adds global event listeners.
325
+ * - When the controller is opened
326
+ */
226
327
  __addGlobalEvent() {
227
328
  this.__removeGlobalEvent();
228
329
  this._bindClose_key = this.eventManager.addGlobalEvent('keydown', this.__globalEventHandlers.keydown, true);
229
330
  this._bindClose_mouse = this.eventManager.addGlobalEvent('mousedown', this.__globalEventHandlers.mousedown, true);
230
- },
331
+ }
231
332
 
333
+ /**
334
+ * @private
335
+ * @description Removes global event listeners.
336
+ * - When the ESC key is pressed, the controller is closed.
337
+ */
232
338
  __removeGlobalEvent() {
233
339
  this.component.__removeGlobalEvent();
234
340
  if (this._bindClose_key) this._bindClose_key = this.eventManager.removeGlobalEvent(this._bindClose_key);
235
341
  if (this._bindClose_mouse) this._bindClose_mouse = this.eventManager.removeGlobalEvent(this._bindClose_mouse);
236
- },
342
+ }
237
343
 
344
+ /**
345
+ * @private
346
+ * @description Checks if the controller is fixed and should not be closed.
347
+ * @returns {boolean} True if the controller is fixed.
348
+ */
238
349
  _checkFixed() {
239
350
  if (this.editor.selectMenuOn) return true;
240
351
 
@@ -245,11 +356,17 @@ Controller.prototype = {
245
356
  }
246
357
  }
247
358
  return false;
248
- },
359
+ }
249
360
 
361
+ /**
362
+ * @private
363
+ * @description Checks if the given target is within a form or controller.
364
+ * @param {Node} target The target element.
365
+ * @returns {boolean} True if the target is inside a form or controller.
366
+ */
250
367
  _checkForm(target) {
251
- if (domUtils.isWysiwygFrame(target)) return false;
252
- if (domUtils.hasClass(target, 'se-drag-handle')) return true;
368
+ if (dom.check.isWysiwygFrame(target)) return false;
369
+ if (dom.utils.hasClass(target, 'se-drag-handle')) return true;
253
370
 
254
371
  let isParentForm = false;
255
372
  if (this.isInsideForm && this.parents?.length > 0) {
@@ -261,63 +378,77 @@ Controller.prototype = {
261
378
  });
262
379
  }
263
380
 
264
- return !isParentForm && (domUtils.getParentElement(target, '.se-controller') || target?.contains(this.inst._element));
265
- },
266
-
267
- constructor: Controller
268
- };
381
+ return !isParentForm && (!!dom.query.getParentElement(target, '.se-controller') || target?.contains(this.inst._element));
382
+ }
269
383
 
270
- // @todo
271
- Controller.CreateHTML = function () {
272
- const html = '';
273
- return domUtils.createElement('DIV', { class: '' }, html);
274
- };
384
+ /**
385
+ * @param {MouseEvent} e - Event object
386
+ */
387
+ #Action(e) {
388
+ const eventTarget = dom.query.getEventTarget(e);
389
+ const target = dom.query.getCommandTarget(eventTarget);
390
+ if (!target) return;
275
391
 
276
- function Action(e) {
277
- const target = domUtils.getCommandTarget(e.target);
278
- if (!target) return;
392
+ e.stopPropagation();
393
+ e.preventDefault();
279
394
 
280
- e.stopPropagation();
281
- e.preventDefault();
395
+ this.inst.controllerAction(target);
396
+ }
282
397
 
283
- this.inst.controllerAction(target);
284
- }
398
+ /**
399
+ * @param {MouseEvent} e - Event object
400
+ */
401
+ #MouseEnter(e) {
402
+ this.editor.currentControllerName = this.kind;
403
+ if (this.parents.length > 0 && this.isInsideForm) return;
285
404
 
286
- function MouseEnter(e) {
287
- this.editor.currentControllerName = this.kind;
288
- if (this.parents.length > 0 && this.isInsideForm) return;
289
- e.target.style.zIndex = INDEX_0;
290
- }
405
+ const eventTarget = dom.query.getEventTarget(e);
406
+ eventTarget.style.zIndex = this.toTop ? INDEX_00 : INDEX_0;
407
+ }
291
408
 
292
- function MouseLeave(e) {
293
- if (this.parents.length > 0 && this.isInsideForm) return;
294
- e.target.style.zIndex = INDEX_2;
295
- }
409
+ /**
410
+ * @param {MouseEvent} e - Event object
411
+ */
412
+ #MouseLeave(e) {
413
+ if (this.parents.length > 0 && this.isInsideForm) return;
296
414
 
297
- function CloseListener_keydown(e) {
298
- if (this._checkFixed()) return;
299
- const keyCode = e.keyCode;
300
- const ctrl = e.ctrlKey || e.metaKey || keyCode === 91 || keyCode === 92 || keyCode === 224;
301
- if (ctrl || !NON_RESPONSE_KEYCODE.test(keyCode)) return;
415
+ const eventTarget = dom.query.getEventTarget(e);
416
+ eventTarget.style.zIndex = this.toTop ? INDEX_0 : this._reserveIndex ? INDEX_S_1 : INDEX_1;
417
+ }
302
418
 
303
- if (this.form.contains(e.target) || this._checkForm(e.target)) return;
304
- if (this.editor._fileManager.pluginRegExp.test(this.kind) && keyCode !== 27) return;
419
+ /**
420
+ * @param {KeyboardEvent} e - Event object
421
+ */
422
+ #CloseListener_keydown(e) {
423
+ if (this._checkFixed()) return;
424
+ const keyCode = e.code;
425
+ const ctrl = keyCodeMap.isCtrl(e);
426
+ if (ctrl || !keyCodeMap.isNonResponseKey(keyCode)) return;
305
427
 
306
- this.close();
307
- }
428
+ const eventTarget = dom.query.getEventTarget(e);
429
+ if (this.form.contains(eventTarget) || this._checkForm(eventTarget)) return;
430
+ if (this.editor._fileManager.pluginRegExp.test(this.kind) && !keyCodeMap.isEsc(keyCode)) return;
308
431
 
309
- function CloseListener_mousedown({ target }) {
310
- if (this.inst?._element?.contains(target)) {
311
- this.isOpen = false;
312
- return;
432
+ this.close();
313
433
  }
314
434
 
315
- this.isOpen = true;
316
- if (target === this.inst._element || target === this.currentTarget || this._checkFixed() || this.form.contains(target) || this._checkForm(target)) {
317
- return;
318
- }
435
+ /**
436
+ * @param {KeyboardEvent} e - Event object
437
+ */
438
+ #CloseListener_mousedown(e) {
439
+ const eventTarget = dom.query.getEventTarget(e);
440
+ if (this.inst?._element?.contains(eventTarget)) {
441
+ this.isOpen = false;
442
+ return;
443
+ }
319
444
 
320
- this.close(true);
445
+ this.isOpen = true;
446
+ if (eventTarget === this.inst._element || eventTarget === this.currentTarget || this._checkFixed() || this.form.contains(eventTarget) || this._checkForm(eventTarget)) {
447
+ return;
448
+ }
449
+
450
+ this.close(true);
451
+ }
321
452
  }
322
453
 
323
454
  export default Controller;