suneditor 3.0.0-alpha.2 → 3.0.0-alpha.20

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 (306) hide show
  1. package/.eslintrc.json +4 -3
  2. package/CONTRIBUTING.md +4 -2
  3. package/README.md +19 -11
  4. package/README_V3_TEMP.md +705 -0
  5. package/dist/suneditor.min.css +1 -0
  6. package/dist/suneditor.min.js +1 -0
  7. package/example.md +587 -0
  8. package/package.json +15 -9
  9. package/src/assets/icons/_default.js +166 -131
  10. package/src/assets/{suneditor-content.css → suneditor-contents.css} +182 -45
  11. package/src/assets/suneditor.css +1195 -556
  12. package/src/assets/variables.css +138 -0
  13. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  14. package/src/core/base/eventHandlers/handler_ww_clipboard.js +29 -4
  15. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +59 -15
  16. package/src/core/base/eventHandlers/handler_ww_key_input.js +426 -212
  17. package/src/core/base/eventHandlers/handler_ww_mouse.js +108 -32
  18. package/src/core/base/eventManager.js +540 -209
  19. package/src/core/base/events.js +616 -320
  20. package/src/core/base/history.js +93 -39
  21. package/src/core/class/char.js +29 -13
  22. package/src/core/class/component.js +332 -145
  23. package/src/core/class/format.js +671 -509
  24. package/src/core/class/html.js +504 -290
  25. package/src/core/class/menu.js +114 -47
  26. package/src/core/class/nodeTransform.js +111 -66
  27. package/src/core/class/offset.js +409 -105
  28. package/src/core/class/selection.js +220 -108
  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 +330 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +489 -384
  34. package/src/core/section/actives.js +118 -22
  35. package/src/core/section/constructor.js +504 -170
  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/helper/converter.js +137 -19
  42. package/src/helper/dom/domCheck.js +294 -0
  43. package/src/helper/dom/domQuery.js +609 -0
  44. package/src/helper/dom/domUtils.js +533 -0
  45. package/src/helper/dom/index.js +12 -0
  46. package/src/helper/env.js +42 -19
  47. package/src/helper/index.js +7 -4
  48. package/src/helper/keyCodeMap.js +183 -0
  49. package/src/helper/numbers.js +8 -8
  50. package/src/helper/unicode.js +5 -5
  51. package/src/langs/ckb.js +69 -3
  52. package/src/langs/cs.js +67 -1
  53. package/src/langs/da.js +68 -2
  54. package/src/langs/de.js +68 -3
  55. package/src/langs/en.js +29 -1
  56. package/src/langs/es.js +68 -3
  57. package/src/langs/fa.js +70 -2
  58. package/src/langs/fr.js +68 -2
  59. package/src/langs/he.js +68 -3
  60. package/src/langs/hu.js +226 -0
  61. package/src/langs/index.js +3 -2
  62. package/src/langs/it.js +65 -0
  63. package/src/langs/ja.js +68 -3
  64. package/src/langs/ko.js +66 -1
  65. package/src/langs/lv.js +68 -3
  66. package/src/langs/nl.js +68 -3
  67. package/src/langs/pl.js +68 -3
  68. package/src/langs/pt_br.js +65 -0
  69. package/src/langs/ro.js +69 -4
  70. package/src/langs/ru.js +68 -3
  71. package/src/langs/se.js +68 -3
  72. package/src/langs/tr.js +68 -0
  73. package/src/langs/ua.js +68 -3
  74. package/src/langs/ur.js +71 -6
  75. package/src/langs/zh_cn.js +69 -4
  76. package/src/modules/ApiManager.js +77 -54
  77. package/src/modules/Browser.js +667 -0
  78. package/src/modules/ColorPicker.js +162 -102
  79. package/src/modules/Controller.js +233 -136
  80. package/src/modules/Figure.js +913 -489
  81. package/src/modules/FileManager.js +141 -72
  82. package/src/modules/HueSlider.js +113 -61
  83. package/src/modules/Modal.js +292 -113
  84. package/src/modules/ModalAnchorEditor.js +380 -230
  85. package/src/modules/SelectMenu.js +270 -168
  86. package/src/modules/_DragHandle.js +2 -1
  87. package/src/modules/index.js +3 -3
  88. package/src/plugins/browser/audioGallery.js +83 -0
  89. package/src/plugins/browser/fileBrowser.js +103 -0
  90. package/src/plugins/browser/fileGallery.js +83 -0
  91. package/src/plugins/browser/imageGallery.js +81 -0
  92. package/src/plugins/browser/videoGallery.js +103 -0
  93. package/src/plugins/command/blockquote.js +40 -27
  94. package/src/plugins/command/exportPDF.js +134 -0
  95. package/src/plugins/command/fileUpload.js +226 -158
  96. package/src/plugins/command/list_bulleted.js +93 -47
  97. package/src/plugins/command/list_numbered.js +93 -47
  98. package/src/plugins/dropdown/align.js +66 -54
  99. package/src/plugins/dropdown/backgroundColor.js +76 -45
  100. package/src/plugins/dropdown/font.js +71 -47
  101. package/src/plugins/dropdown/fontColor.js +78 -46
  102. package/src/plugins/dropdown/formatBlock.js +74 -33
  103. package/src/plugins/dropdown/hr.js +102 -51
  104. package/src/plugins/dropdown/layout.js +37 -26
  105. package/src/plugins/dropdown/lineHeight.js +54 -38
  106. package/src/plugins/dropdown/list.js +60 -45
  107. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  108. package/src/plugins/dropdown/table.js +1269 -777
  109. package/src/plugins/dropdown/template.js +38 -26
  110. package/src/plugins/dropdown/textStyle.js +43 -31
  111. package/src/plugins/field/mention.js +144 -82
  112. package/src/plugins/index.js +32 -6
  113. package/src/plugins/input/fontSize.js +161 -108
  114. package/src/plugins/input/pageNavigator.js +70 -0
  115. package/src/plugins/modal/audio.js +341 -169
  116. package/src/plugins/modal/drawing.js +530 -0
  117. package/src/plugins/modal/embed.js +886 -0
  118. package/src/plugins/modal/image.js +673 -358
  119. package/src/plugins/modal/link.js +100 -71
  120. package/src/plugins/modal/math.js +384 -168
  121. package/src/plugins/modal/video.js +693 -336
  122. package/src/plugins/popup/anchor.js +222 -0
  123. package/src/suneditor.js +54 -12
  124. package/src/themes/dark.css +85 -0
  125. package/src/typedef.js +86 -0
  126. package/types/assets/icons/_default.d.ts +152 -0
  127. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  128. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  129. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  130. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  131. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  132. package/types/core/base/eventManager.d.ts +377 -0
  133. package/types/core/base/events.d.ts +297 -0
  134. package/types/core/base/history.d.ts +81 -0
  135. package/types/core/class/char.d.ts +60 -0
  136. package/types/core/class/component.d.ts +259 -0
  137. package/types/core/class/format.d.ts +615 -0
  138. package/types/core/class/html.d.ts +377 -0
  139. package/types/core/class/menu.d.ts +118 -0
  140. package/types/core/class/nodeTransform.d.ts +93 -0
  141. package/types/core/class/offset.d.ts +512 -0
  142. package/types/core/class/selection.d.ts +188 -0
  143. package/types/core/class/shortcuts.d.ts +142 -0
  144. package/types/core/class/toolbar.d.ts +189 -0
  145. package/types/core/class/ui.d.ts +144 -0
  146. package/types/core/class/viewer.d.ts +140 -0
  147. package/types/core/editor.d.ts +606 -0
  148. package/types/core/section/actives.d.ts +46 -0
  149. package/types/core/section/constructor.d.ts +748 -0
  150. package/types/core/section/context.d.ts +45 -0
  151. package/types/core/section/documentType.d.ts +178 -0
  152. package/types/editorInjector/_classes.d.ts +41 -0
  153. package/types/editorInjector/_core.d.ts +92 -0
  154. package/types/editorInjector/index.d.ts +71 -0
  155. package/types/helper/converter.d.ts +150 -0
  156. package/types/helper/dom/domCheck.d.ts +182 -0
  157. package/types/helper/dom/domQuery.d.ts +214 -0
  158. package/types/helper/dom/domUtils.d.ts +211 -0
  159. package/types/helper/dom/index.d.ts +9 -0
  160. package/types/helper/env.d.ts +149 -0
  161. package/types/helper/index.d.ts +163 -0
  162. package/types/helper/keyCodeMap.d.ts +110 -0
  163. package/types/helper/numbers.d.ts +43 -0
  164. package/types/helper/unicode.d.ts +28 -0
  165. package/types/index.d.ts +0 -0
  166. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +170 -103
  167. package/types/langs/ckb.d.ts +384 -0
  168. package/types/langs/cs.d.ts +384 -0
  169. package/types/langs/da.d.ts +384 -0
  170. package/types/langs/de.d.ts +384 -0
  171. package/types/langs/en.d.ts +384 -0
  172. package/types/langs/es.d.ts +384 -0
  173. package/types/langs/fa.d.ts +384 -0
  174. package/types/langs/fr.d.ts +384 -0
  175. package/types/langs/he.d.ts +384 -0
  176. package/types/langs/hu.d.ts +384 -0
  177. package/types/langs/index.d.ts +48 -0
  178. package/types/langs/it.d.ts +384 -0
  179. package/types/langs/ja.d.ts +384 -0
  180. package/types/langs/ko.d.ts +384 -0
  181. package/types/langs/lv.d.ts +384 -0
  182. package/types/langs/nl.d.ts +384 -0
  183. package/types/langs/pl.d.ts +384 -0
  184. package/types/langs/pt_br.d.ts +384 -0
  185. package/types/langs/ro.d.ts +384 -0
  186. package/types/langs/ru.d.ts +384 -0
  187. package/types/langs/se.d.ts +384 -0
  188. package/types/langs/tr.d.ts +384 -0
  189. package/types/langs/ua.d.ts +384 -0
  190. package/types/langs/ur.d.ts +384 -0
  191. package/types/langs/zh_cn.d.ts +384 -0
  192. package/types/modules/ApiManager.d.ts +125 -0
  193. package/types/modules/Browser.d.ts +326 -0
  194. package/types/modules/ColorPicker.d.ts +131 -0
  195. package/types/modules/Controller.d.ts +231 -0
  196. package/types/modules/Figure.d.ts +504 -0
  197. package/types/modules/FileManager.d.ts +202 -0
  198. package/types/modules/HueSlider.d.ts +136 -0
  199. package/types/modules/Modal.d.ts +117 -0
  200. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  201. package/types/modules/SelectMenu.d.ts +194 -0
  202. package/types/modules/_DragHandle.d.ts +7 -0
  203. package/types/modules/index.d.ts +26 -0
  204. package/types/plugins/browser/audioGallery.d.ts +55 -0
  205. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  206. package/types/plugins/browser/fileGallery.d.ts +55 -0
  207. package/types/plugins/browser/imageGallery.d.ts +51 -0
  208. package/types/plugins/browser/videoGallery.d.ts +57 -0
  209. package/types/plugins/command/blockquote.d.ts +28 -0
  210. package/types/plugins/command/exportPDF.d.ts +46 -0
  211. package/types/plugins/command/fileUpload.d.ts +156 -0
  212. package/types/plugins/command/list_bulleted.d.ts +56 -0
  213. package/types/plugins/command/list_numbered.d.ts +56 -0
  214. package/types/plugins/dropdown/align.d.ts +60 -0
  215. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  216. package/types/plugins/dropdown/font.d.ts +54 -0
  217. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  218. package/types/plugins/dropdown/formatBlock.d.ts +58 -0
  219. package/types/plugins/dropdown/hr.d.ts +81 -0
  220. package/types/plugins/dropdown/layout.d.ts +40 -0
  221. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  222. package/types/plugins/dropdown/list.d.ts +39 -0
  223. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  224. package/types/plugins/dropdown/table.d.ts +579 -0
  225. package/types/plugins/dropdown/template.d.ts +40 -0
  226. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  227. package/types/plugins/field/mention.d.ts +102 -0
  228. package/types/plugins/index.d.ts +107 -0
  229. package/types/plugins/input/fontSize.d.ts +170 -0
  230. package/types/plugins/input/pageNavigator.d.ts +28 -0
  231. package/types/plugins/modal/audio.d.ts +269 -0
  232. package/types/plugins/modal/drawing.d.ts +246 -0
  233. package/types/plugins/modal/embed.d.ts +387 -0
  234. package/types/plugins/modal/image.d.ts +451 -0
  235. package/types/plugins/modal/link.d.ts +128 -0
  236. package/types/plugins/modal/math.d.ts +193 -0
  237. package/types/plugins/modal/video.d.ts +485 -0
  238. package/types/plugins/popup/anchor.d.ts +56 -0
  239. package/types/suneditor.d.ts +51 -0
  240. package/types/typedef-global.d.ts +144 -0
  241. package/src/core/class/notice.js +0 -42
  242. package/src/helper/domUtils.js +0 -1177
  243. package/src/modules/FileBrowser.js +0 -271
  244. package/src/plugins/command/exportPdf.js +0 -168
  245. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  246. package/src/themes/test.css +0 -61
  247. package/typings/CommandPlugin.d.ts +0 -8
  248. package/typings/DialogPlugin.d.ts +0 -20
  249. package/typings/FileBrowserPlugin.d.ts +0 -30
  250. package/typings/Module.d.ts +0 -15
  251. package/typings/Plugin.d.ts +0 -42
  252. package/typings/SubmenuPlugin.d.ts +0 -8
  253. package/typings/_classes.d.ts +0 -17
  254. package/typings/_colorPicker.d.ts +0 -60
  255. package/typings/_core.d.ts +0 -55
  256. package/typings/align.d.ts +0 -5
  257. package/typings/audio.d.ts +0 -5
  258. package/typings/backgroundColor.d.ts +0 -5
  259. package/typings/blockquote.d.ts +0 -5
  260. package/typings/char.d.ts +0 -39
  261. package/typings/component.d.ts +0 -38
  262. package/typings/context.d.ts +0 -39
  263. package/typings/converter.d.ts +0 -33
  264. package/typings/dialog.d.ts +0 -28
  265. package/typings/domUtils.d.ts +0 -361
  266. package/typings/editor.d.ts +0 -7
  267. package/typings/editor.ts +0 -542
  268. package/typings/env.d.ts +0 -70
  269. package/typings/eventManager.d.ts +0 -37
  270. package/typings/events.d.ts +0 -262
  271. package/typings/fileBrowser.d.ts +0 -42
  272. package/typings/fileManager.d.ts +0 -67
  273. package/typings/font.d.ts +0 -5
  274. package/typings/fontColor.d.ts +0 -5
  275. package/typings/fontSize.d.ts +0 -5
  276. package/typings/format.d.ts +0 -191
  277. package/typings/formatBlock.d.ts +0 -5
  278. package/typings/history.d.ts +0 -48
  279. package/typings/horizontalRule.d.ts +0 -5
  280. package/typings/image.d.ts +0 -5
  281. package/typings/imageGallery.d.ts +0 -5
  282. package/typings/index.d.ts +0 -21
  283. package/typings/index.modules.d.ts +0 -11
  284. package/typings/index.plugins.d.ts +0 -58
  285. package/typings/lineHeight.d.ts +0 -5
  286. package/typings/link.d.ts +0 -5
  287. package/typings/list.d.ts +0 -5
  288. package/typings/math.d.ts +0 -5
  289. package/typings/mediaContainer.d.ts +0 -25
  290. package/typings/mention.d.ts +0 -5
  291. package/typings/node.d.ts +0 -57
  292. package/typings/notice.d.ts +0 -16
  293. package/typings/numbers.d.ts +0 -29
  294. package/typings/offset.d.ts +0 -24
  295. package/typings/options.d.ts +0 -589
  296. package/typings/paragraphStyle.d.ts +0 -5
  297. package/typings/resizing.d.ts +0 -141
  298. package/typings/selection.d.ts +0 -94
  299. package/typings/shortcuts.d.ts +0 -13
  300. package/typings/suneditor.d.ts +0 -9
  301. package/typings/table.d.ts +0 -5
  302. package/typings/template.d.ts +0 -5
  303. package/typings/textStyle.d.ts +0 -5
  304. package/typings/toolbar.d.ts +0 -32
  305. package/typings/unicode.d.ts +0 -25
  306. package/typings/video.d.ts +0 -5
@@ -1,9 +1,9 @@
1
1
  import EditorInjector from '../editorInjector';
2
2
  import { Controller, SelectMenu, _DragHandle } from '../modules';
3
- import { domUtils, numbers, env, converter } from '../helper';
3
+ import { dom, numbers, env, converter, keyCodeMap } from '../helper';
4
4
 
5
5
  const { ON_OVER_COMPONENT } = env;
6
- const DIRECTION_CURSOR_MAP = { tl: 'nw-resize', tr: 'ne-resize', bl: 'sw-resize', br: 'se-resize', lw: 'w-resize', th: 'n-resize', rw: 'e-resize', bh: 's-resize' };
6
+ const DIRECTION_CURSOR_MAP = { tl: 'nwse-resize', tr: 'nesw-resize', bl: 'nesw-resize', br: 'nwse-resize', lw: 'ew-resize', th: 'ns-resize', rw: 'ew-resize', bh: 'ns-resize' };
7
7
  const DIR_DIAGONAL = 'tl|bl|tr|br';
8
8
  const DIR_W = 'lw|rw';
9
9
  let __resizing_p_wh = false;
@@ -11,233 +11,325 @@ let __resizing_p_ow = false;
11
11
  let __resizing_cw = 0;
12
12
  let __resizing_sw = 0;
13
13
 
14
- const Figure = function (inst, controls, params) {
15
- EditorInjector.call(this, inst.editor);
16
- this.kind = inst.constructor.key || inst.constructor.name;
17
- this._alignIcons = {
18
- none: this.icons.format_float_none,
19
- left: this.icons.format_float_left,
20
- right: this.icons.format_float_right,
21
- center: this.icons.format_float_center
22
- };
23
-
24
- // modules
25
- this._action = {};
26
- const controllerEl = CreateHTML_controller(this, controls || []);
27
- this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true }, this.kind);
28
- // align selectmenu
29
- this.alignButton = controllerEl.querySelector('[data-command="onalign"]');
30
- const alignMenus = CreateAlign(this, this.alignButton);
31
- if (alignMenus) {
32
- this.selectMenu_align = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
33
- this.selectMenu_align.on(this.alignButton, SetMenuAlign.bind(this), { class: 'se-resizing-align-list' });
34
- this.selectMenu_align.create(alignMenus.items, alignMenus.html);
35
- }
36
- // resize selectmenu
37
- this.resizeButton = controllerEl.querySelector('[data-command="onresize"]');
38
- const resizeMenus = CreateResize(this, this.resizeButton);
39
- if (resizeMenus) {
40
- this.selectMenu_resize = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr' });
41
- this.selectMenu_resize.on(this.resizeButton, SetResize.bind(this));
42
- this.selectMenu_resize.create(resizeMenus.items, resizeMenus.html);
43
- }
44
-
45
- // members
46
- this.inst = inst;
47
- this.sizeUnit = params.sizeUnit || 'px';
48
- this.autoRatio = params.autoRatio;
49
- this.isVertical = false;
50
- this.percentageButtons = controllerEl.querySelectorAll('[data-command="resize_percent"]');
51
- this.captionButton = controllerEl.querySelector('[data-command="caption"]');
52
- this.align = 'none';
53
- this._element = null;
54
- this._cover = null;
55
- this._container = null;
56
- this._caption = null;
57
- this._width = 0;
58
- this._height = 0;
59
- this._element_w = 0;
60
- this._element_h = 0;
61
- this._element_l = 0;
62
- this._element_t = 0;
63
- this._resize_w = 0;
64
- this._resize_h = 0;
65
- this._resizeClientX = 0;
66
- this._resizeClientY = 0;
67
- this._resize_direction = '';
68
- this._floatClassStr = '__se__float-none|__se__float-left|__se__float-center|__se__float-right';
69
- this.__preventSizechange = false;
70
- this.__revertSize = { w: '', h: '' };
71
- this.__offset = {};
72
- this.__offContainer = OffFigureContainer.bind(this);
73
- this.__containerResizing = ContainerResizing.bind(this);
74
- this.__containerResizingOff = ContainerResizingOff.bind(this);
75
- this.__containerResizingESC = ContainerResizingESC.bind(this);
76
- this.__onContainerEvent = null;
77
- this.__offContainerEvent = null;
78
- this.__onResizeESCEvent = null;
79
- this.__fileManagerInfo = false;
80
-
81
- // init
82
- this.eventManager.addEvent(this.alignButton, 'click', OnClick_alignButton.bind(this));
83
- this.eventManager.addEvent(this.resizeButton, 'click', OnClick_resizeButton.bind(this));
84
- this.editor.applyFrameRoots((e) => {
85
- if (!e.get('wrapper').querySelector('.se-controller.se-resizing-container')) {
86
- // resizing
87
- const main = CreateHTML_resizeDot();
88
- const handles = main.querySelectorAll('.se-resize-dot > span');
89
- e.set('_figure', {
90
- main: main,
91
- border: main.querySelector('.se-resize-dot'),
92
- display: main.querySelector('.se-resize-display'),
93
- handles: handles
94
- });
95
- e.get('wrapper').appendChild(main);
96
- this.eventManager.addEvent(handles, 'mousedown', OnResizeContainer.bind(this));
97
- }
98
- });
99
- };
14
+ /**
15
+ * @typedef {Object} FigureParams
16
+ * @property {string} [sizeUnit="px"] Size unit
17
+ * @property {{ current: string, default: string }} [autoRatio=null] Auto ratio { current: '00%', default: '00%' }
18
+ */
100
19
 
101
20
  /**
102
- * @description Create a container for the resizing component and insert the element.
103
- * @param {Element} element Target element
104
- * @param {string} className Class name of container (fixed: se-component)
105
- * @returns {object} {container, cover, caption}
21
+ * @typedef {Object} FigureInfo
22
+ * @property {HTMLElement} target Target element (img, iframe, video, audio, table, etc.)
23
+ * @property {HTMLElement} container Container element (div.se-component|span.se-component.se-inline-component)
24
+ * @property {?HTMLElement} cover Cover element (FIGURE|null)
25
+ * @property {?HTMLElement} inlineCover Inline cover element (span.se-inline-component)
26
+ * @property {?HTMLElement} caption Caption element (FIGCAPTION)
106
27
  */
107
- Figure.CreateContainer = function (element, className) {
108
- domUtils.createElement('DIV', { class: 'se-component' + (className ? ' ' + className : '') }, domUtils.createElement('FIGURE', null, element));
109
- return Figure.GetContainer(element);
110
- };
111
28
 
112
29
  /**
113
- * @description Return HTML string of caption(FIGCAPTION) element
114
- * @param {Element} cover Cover element(FIGURE). "CreateContainer().cover"
115
- * @returns {Element} caption element
30
+ * @typedef {Object} FigureTargetInfo
31
+ * @property {HTMLElement} container Container element (div.se-component|span.se-component.se-inline-component)
32
+ * @property {?HTMLElement=} cover Cover element (FIGURE|null)
33
+ * @property {?HTMLElement=} caption Caption element (FIGCAPTION)
34
+ * @property {string} [align] - Alignment of the element.
35
+ * @property {{w:number, h:number}} [ratio] - The aspect ratio of the element.
36
+ * @property {string|number} [w] - Width of the element.
37
+ * @property {string|number} [h] - Height of the element.
38
+ * @property {number} [t] - Top position.
39
+ * @property {number} [l] - Left position.
40
+ * @property {string|number} width - Width, can be a number or 'auto'.
41
+ * @property {string|number} height - Height, can be a number or 'auto'.
42
+ * @property {number} [originWidth] - Original width from `naturalWidth` or `offsetWidth`.
43
+ * @property {number} [originHeight] - Original height from `naturalHeight` or `offsetHeight`.
116
44
  */
117
- Figure.CreateCaption = function (cover, text) {
118
- const caption = domUtils.createElement('FIGCAPTION', null, '<div>' + text + '</div>');
119
- cover.appendChild(caption);
120
- return caption;
121
- };
122
45
 
123
46
  /**
124
- * @description Get the element's container(.se-component) info.
125
- * @param {Element} element Target element
126
- * @returns {object} {container, cover, caption}
47
+ * @typedef {Array<Array<string|{action: (element: Node, value: string, target: Node) => void, command: string, value: string, title: string, icon: string}>>} FigureControls
127
48
  */
128
- Figure.GetContainer = function (element) {
129
- const cover = domUtils.getParentElement(element, 'FIGURE');
130
- return {
131
- target: element,
132
- container: domUtils.getParentElement(element, Figure.__is) || cover,
133
- cover: cover,
134
- caption: domUtils.getEdgeChild(element.parentElement, 'FIGCAPTION')
135
- };
136
- };
137
49
 
138
50
  /**
139
- * @description Ratio calculation
140
- * @param {string|number} w Width size
141
- * @param {string|number} h Height size
142
- * @param {defaultSizeUnit|undefined|null} defaultSizeUnit Default size unit (default: "px")
143
- * @return {{w: number, h: number}}
51
+ * @class
52
+ * @description Controller module class
144
53
  */
145
- Figure.GetRatio = function (w, h, defaultSizeUnit) {
146
- let rw = 1,
147
- rh = 1;
148
- if (/\d+/.test(w) && /\d+/.test(h)) {
149
- const xUnit = (!numbers.is(w) && w.replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
150
- const yUnit = (!numbers.is(h) && h.replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
151
- if (xUnit === yUnit) {
152
- const w_number = numbers.get(w, 4);
153
- const h_number = numbers.get(h, 4);
154
- rw = w_number / h_number;
155
- rh = h_number / w_number;
54
+ class Figure extends EditorInjector {
55
+ /**
56
+ * @constructor
57
+ * @param {*} inst The instance object that called the constructor.
58
+ * @param {FigureControls} controls Controller button array
59
+ * @param {FigureParams} params Figure options
60
+ */
61
+ constructor(inst, controls, params) {
62
+ super(inst.editor);
63
+ this.kind = inst.constructor.key || inst.constructor.name;
64
+ this._alignIcons = {
65
+ none: this.icons.format_float_none,
66
+ left: this.icons.format_float_left,
67
+ right: this.icons.format_float_right,
68
+ center: this.icons.format_float_center
69
+ };
70
+
71
+ // modules
72
+ /** @type {Object<string, *>} */
73
+ this._action = {};
74
+ const controllerEl = CreateHTML_controller(this, controls || []);
75
+ this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true }, this.kind);
76
+ // align selectmenu
77
+ this.alignButton = controllerEl.querySelector('[data-command="onalign"]');
78
+ const alignMenus = CreateAlign(this, this.alignButton);
79
+ if (alignMenus) {
80
+ this.selectMenu_align = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
81
+ this.selectMenu_align.on(this.alignButton, this.#SetMenuAlign.bind(this), { class: 'se-figure-select-list' });
82
+ this.selectMenu_align.create(alignMenus.items, alignMenus.html);
156
83
  }
84
+ // as [block, inline] selectmenu
85
+ this.asButton = controllerEl.querySelector('[data-command="onas"]');
86
+ const asMenus = CreateAs(this, this.asButton);
87
+ if (asMenus) {
88
+ this.selectMenu_as = new SelectMenu(this, { checkList: false, position: 'bottom-center' });
89
+ this.selectMenu_as.on(this.asButton, this.#SetMenuAs.bind(this), { class: 'se-figure-select-list' });
90
+ this.selectMenu_as.create(asMenus.items, asMenus.html);
91
+ }
92
+ // resize selectmenu
93
+ this.resizeButton = controllerEl.querySelector('[data-command="onresize"]');
94
+ const resizeMenus = CreateResize(this, this.resizeButton);
95
+ if (resizeMenus) {
96
+ this.selectMenu_resize = new SelectMenu(this, { checkList: false, position: 'bottom-left', dir: 'ltr' });
97
+ this.selectMenu_resize.on(this.resizeButton, this.#SetResize.bind(this));
98
+ this.selectMenu_resize.create(resizeMenus.items, resizeMenus.html);
99
+ }
100
+
101
+ // members
102
+ this.inst = inst;
103
+ this.sizeUnit = params.sizeUnit || 'px';
104
+ this.autoRatio = params.autoRatio;
105
+ this.isVertical = false;
106
+ this.percentageButtons = controllerEl.querySelectorAll('[data-command="resize_percent"]');
107
+ this.captionButton = controllerEl.querySelector('[data-command="caption"]');
108
+ this.align = 'none';
109
+ this.as = 'block';
110
+ this._element = null;
111
+ this._cover = null;
112
+ this._inlineCover = null;
113
+ this._container = null;
114
+ this._caption = null;
115
+ this._width = '';
116
+ this._height = '';
117
+ this._resize_w = 0;
118
+ this._resize_h = 0;
119
+ this._element_w = 0;
120
+ this._element_h = 0;
121
+ this._element_l = 0;
122
+ this._element_t = 0;
123
+ this._resizeClientX = 0;
124
+ this._resizeClientY = 0;
125
+ this._resize_direction = '';
126
+ this._floatClassStr = '__se__float-none|__se__float-left|__se__float-center|__se__float-right';
127
+ this.__preventSizechange = false;
128
+ this.__revertSize = { w: '', h: '' };
129
+ /** @type {{left?: number, top?: number}} */
130
+ this.__offset = {};
131
+ this.__offContainer = this.#OffFigureContainer.bind(this);
132
+ this.__containerResizing = this.#ContainerResizing.bind(this);
133
+ this.__containerResizingOff = this.#ContainerResizingOff.bind(this);
134
+ this.__containerResizingESC = this.#ContainerResizingESC.bind(this);
135
+ this.__onContainerEvent = null;
136
+ this.__offContainerEvent = null;
137
+ this.__onResizeESCEvent = null;
138
+ this.__fileManagerInfo = false;
139
+
140
+ // init
141
+ this.eventManager.addEvent(this.alignButton, 'click', this.#OnClick_alignButton.bind(this));
142
+ this.eventManager.addEvent(this.asButton, 'click', this.#OnClick_asButton.bind(this));
143
+ this.eventManager.addEvent(this.resizeButton, 'click', this.#OnClick_resizeButton.bind(this));
144
+ this.editor.applyFrameRoots((e) => {
145
+ if (!e.get('wrapper').querySelector('.se-controller.se-resizing-container')) {
146
+ // resizing
147
+ const main = CreateHTML_resizeDot();
148
+ const handles = main.querySelectorAll('.se-resize-dot > span');
149
+ e.set('_figure', {
150
+ main: main,
151
+ border: main.querySelector('.se-resize-dot'),
152
+ display: main.querySelector('.se-resize-display'),
153
+ handles: handles
154
+ });
155
+ e.get('wrapper').appendChild(main);
156
+ this.eventManager.addEvent(handles, 'mousedown', this.#OnResizeContainer.bind(this));
157
+ }
158
+ });
157
159
  }
158
160
 
159
- return {
160
- w: numbers.get(rw, 4),
161
- h: numbers.get(rh, 4)
162
- };
163
- };
161
+ /**
162
+ * @description Create a container for the resizing component and insert the element.
163
+ * @param {Node} element Target element
164
+ * @param {string=} className Class name of container (fixed: se-component)
165
+ * @returns {FigureInfo} {target, container, cover, inlineCover, caption}
166
+ */
167
+ static CreateContainer(element, className) {
168
+ dom.utils.createElement('DIV', { class: 'se-component' + (className ? ' ' + className : '') }, dom.utils.createElement('FIGURE', null, element));
169
+ return Figure.GetContainer(element);
170
+ }
164
171
 
165
- /**
166
- * @description Ratio calculation
167
- * @param {string|number} w Width size
168
- * @param {string|number} h Height size
169
- * @param {defaultSizeUnit|undefined|null} defaultSizeUnit Default size unit (default: "px")
170
- * @param {{w: number, h: number}} ratio Ratio size (Figure.GetRatio)
171
- * @return {{w: string|number, h: string|number}}
172
- */
173
- Figure.CalcRatio = function (w, h, defaultSizeUnit, ratio) {
174
- if (/\d+/.test(w) && /\d+/.test(h)) {
175
- const xUnit = (!numbers.is(w) && w.replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
176
- const yUnit = (!numbers.is(h) && h.replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
177
- if (xUnit === yUnit) {
178
- const dec = xUnit === '%' ? 2 : 0;
179
- const ow = w;
180
- const oh = h;
181
- h = numbers.get(ratio.h * numbers.get(ow, dec), dec) + yUnit;
182
- w = numbers.get(ratio.w * numbers.get(oh, dec), dec) + xUnit;
172
+ /**
173
+ * @description Create a container for the inline resizing component and insert the element.
174
+ * @param {Node} element Target element
175
+ * @param {string} [className] Class name of container (fixed: se-component se-inline-component)
176
+ * @returns {FigureInfo} {target, container, cover, inlineCover, caption}
177
+ */
178
+ static CreateInlineContainer(element, className) {
179
+ dom.utils.createElement('SPAN', { class: 'se-component se-inline-component' + (className ? ' ' + className : '') }, element);
180
+ return Figure.GetContainer(element);
181
+ }
182
+
183
+ /**
184
+ * @description Return HTML string of caption(FIGCAPTION) element
185
+ * @param {Node} cover Cover element(FIGURE). "CreateContainer().cover"
186
+ * @returns {HTMLElement} caption element
187
+ */
188
+ static CreateCaption(cover, text) {
189
+ const caption = dom.utils.createElement('FIGCAPTION', null, '<div>' + text + '</div>');
190
+ cover.appendChild(caption);
191
+ return caption;
192
+ }
193
+
194
+ /**
195
+ * @description Get the element's container(.se-component) info.
196
+ * @param {Node} element Target element
197
+ * @returns {FigureInfo} {target, container, cover, inlineCover, caption}
198
+ */
199
+ static GetContainer(element) {
200
+ const cover = dom.query.getParentElement(element, 'FIGURE', 2);
201
+ const inlineCover = dom.query.getParentElement(element, 'SPAN', 2);
202
+ return {
203
+ target: /** @type {HTMLElement} */ (element),
204
+ container: /** @type {HTMLElement} */ (dom.query.getParentElement(element, Figure.is, 2) || cover),
205
+ cover: /** @type {HTMLElement} */ (cover),
206
+ inlineCover: dom.utils.hasClass(inlineCover, 'se-inline-component') ? /** @type {HTMLElement} */ (inlineCover) : null,
207
+ caption: /** @type {HTMLElement} */ (dom.query.getEdgeChild(element.parentElement, 'FIGCAPTION', false))
208
+ };
209
+ }
210
+
211
+ /**
212
+ * @description Ratio calculation
213
+ * @param {string|number} w Width size
214
+ * @param {string|number} h Height size
215
+ * @param {?string=} [defaultSizeUnit="px"] Default size unit (default: "px")
216
+ * @return {{w: number, h: number}}
217
+ */
218
+ static GetRatio(w, h, defaultSizeUnit) {
219
+ let rw = 1,
220
+ rh = 1;
221
+ if (/\d+/.test(w + '') && /\d+/.test(h + '')) {
222
+ const xUnit = (!numbers.is(w) && String(w).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
223
+ const yUnit = (!numbers.is(h) && String(h).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
224
+ if (xUnit === yUnit) {
225
+ const w_number = numbers.get(w, 4);
226
+ const h_number = numbers.get(h, 4);
227
+ rw = w_number / h_number;
228
+ rh = h_number / w_number;
229
+ }
183
230
  }
231
+
232
+ return {
233
+ w: numbers.get(rw, 4),
234
+ h: numbers.get(rh, 4)
235
+ };
184
236
  }
185
237
 
186
- return {
187
- w: w,
188
- h: h
189
- };
190
- };
238
+ /**
239
+ * @description Ratio calculation
240
+ * @param {string|number} w Width size
241
+ * @param {string|number} h Height size
242
+ * @param {string} defaultSizeUnit Default size unit (default: "px")
243
+ * @param {{w: number, h: number}} ratio Ratio size (Figure.GetRatio)
244
+ * @return {{w: string|number, h: string|number}}
245
+ */
246
+ static CalcRatio(w, h, defaultSizeUnit, ratio) {
247
+ if (/\d+/.test(w + '') && /\d+/.test(h + '')) {
248
+ const xUnit = (!numbers.is(w) && String(w).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
249
+ const yUnit = (!numbers.is(h) && String(h).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
250
+ if (xUnit === yUnit) {
251
+ const dec = xUnit === '%' ? 2 : 0;
252
+ const ow = w;
253
+ const oh = h;
254
+ h = numbers.get(ratio.h * numbers.get(ow, dec), dec) + yUnit;
255
+ w = numbers.get(ratio.w * numbers.get(oh, dec), dec) + xUnit;
256
+ }
257
+ }
191
258
 
192
- /**
193
- * @description It is judged whether it is the component[img, iframe, video, audio, table] cover(class="se-component") and table, hr
194
- * @param {Node} element Target element
195
- * @returns {boolean}
196
- * @private
197
- */
198
- Figure.__is = function (element) {
199
- return domUtils.hasClass(element, 'se-component') || /^(HR)$/.test(element?.nodeName);
200
- };
259
+ return {
260
+ w: w,
261
+ h: h
262
+ };
263
+ }
264
+
265
+ /**
266
+ * @description It is judged whether it is the component[img, iframe, video, audio, table] cover(class="se-component") and table, hr
267
+ * @param {Node} element Target element
268
+ * @returns {boolean}
269
+ */
270
+ static is(element) {
271
+ return dom.utils.hasClass(element, 'se-component') || /^(HR)$/.test(element?.nodeName);
272
+ }
201
273
 
202
- Figure.prototype = {
203
274
  /**
204
- * @override controller
275
+ * @description Close the figure's controller
205
276
  */
206
277
  close() {
207
- this.editor._antiBlur = false;
208
- domUtils.removeClass(this._cover, 'se-figure-selected');
278
+ this.editor._preventBlur = false;
279
+ dom.utils.removeClass(this._cover, 'se-figure-selected');
209
280
  this.controller.close();
210
-
211
- if (domUtils.hasClass(this._w.event?.target, 'se-drag-handle|sun-editor-editable')) return;
212
281
  this.component._removeDragEvent();
213
- },
282
+ }
214
283
 
215
- open(target, { nonResizing, nonSizeInfo, nonBorder, figureTarget, __fileManagerInfo }) {
216
- if (!target) {
217
- console.warn('[SUNEDITOR.modules.Figure.open] The target element is null.');
284
+ /**
285
+ * @description Open the figure's controller
286
+ * @param {Node} targetNode Target element
287
+ * @param {Object} params params
288
+ * @param {boolean} [params.nonResizing=false] Do not display the resizing button
289
+ * @param {boolean} [params.nonSizeInfo=false] Do not display the size information
290
+ * @param {boolean} [params.nonBorder=false] Do not display the selected style line
291
+ * @param {boolean} [params.figureTarget=false] If true, the target is a figure element
292
+ * @param {boolean} [params.__fileManagerInfo=false] If true, the file manager is called
293
+ * @returns {FigureTargetInfo|undefined} figure target info
294
+ */
295
+ open(targetNode, { nonResizing, nonSizeInfo, nonBorder, figureTarget, __fileManagerInfo }) {
296
+ if (!targetNode) {
297
+ console.warn('[SUNEDITOR.modules.Figure.open] The "targetNode" is null.');
218
298
  return;
219
299
  }
220
300
 
221
301
  if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
222
- this.editor._offCurrentController();
302
+ this.ui._offCurrentController();
223
303
  } else {
224
304
  nonBorder = true;
225
305
  }
226
306
 
227
- const figureInfo = Figure.GetContainer(target);
228
- if (!figureInfo.container) return { container: null, cover: null };
307
+ const figureInfo = Figure.GetContainer(targetNode);
308
+ const target = figureInfo.target;
309
+ let exceptionFormat = false;
310
+ if (!figureInfo.container) {
311
+ if (!this.options.get('strictMode').formatFilter) {
312
+ figureInfo.container = target;
313
+ figureInfo.cover = target;
314
+ exceptionFormat = true;
315
+ } else {
316
+ return {
317
+ container: null,
318
+ cover: null,
319
+ width: target.style.width || (!numbers.is(/** @type {HTMLImageElement} */ (target).width) ? /** @type {HTMLImageElement} */ (target).width : '') || '',
320
+ height: target.style.height || (!numbers.is(/** @type {HTMLImageElement} */ (target).height) ? /** @type {HTMLImageElement} */ (target).height : '') || ''
321
+ };
322
+ }
323
+ }
229
324
 
230
325
  _DragHandle.set('__figureInst', this);
231
326
 
232
- this._cover = figureInfo.cover;
233
- this._container = figureInfo.container;
234
- this._caption = figureInfo.caption;
235
- this._element = target;
236
- this.align = (this._container.className.match(/(?:^|\s)__se__float-(none|left|center|right)(?:$|\s)/) || [])[1] || target.style.float || 'none';
237
- this.isVertical = /^(90|270)$/.test(Math.abs(GetRotateValue(target).r).toString());
327
+ this._setFigureInfo(figureInfo);
238
328
 
239
- const sizeTarget = figureTarget ? this._cover || this._container || target : target;
240
- const { w, h, t, l, scrollX, scrollY } = this.offset.getSize(sizeTarget);
329
+ const sizeTarget = /** @type {HTMLElement} */ (figureTarget ? this._cover || this._container || target : target);
330
+ const w = sizeTarget.offsetWidth || null;
331
+ const h = sizeTarget.offsetHeight || null;
332
+ const { top, left, scrollX, scrollY } = this.offset.getLocal(sizeTarget);
241
333
 
242
334
  const dataSize = (target.getAttribute('data-se-size') || '').split(',');
243
335
  const ratio = Figure.GetRatio(dataSize[0] || numbers.get(target.style.width, 2) || w, dataSize[1] || numbers.get(target.style.height, 2) || h, this.sizeUnit);
@@ -247,14 +339,14 @@ Figure.prototype = {
247
339
  caption: figureInfo.caption,
248
340
  align: this.align,
249
341
  ratio: ratio,
250
- w: w,
251
- h: h,
252
- t: t,
253
- l: l,
342
+ w: w || '',
343
+ h: h || '',
344
+ t: top,
345
+ l: left,
254
346
  width: dataSize[0] || 'auto',
255
347
  height: dataSize[1] || 'auto',
256
- originWidth: target.naturalWidth || target.offsetWidth,
257
- originHeight: target.naturalHeight || target.offsetHeight
348
+ originWidth: /** @type {HTMLImageElement} */ (target).naturalWidth || target.offsetWidth,
349
+ originHeight: /** @type {HTMLImageElement} */ (target).naturalHeight || target.offsetHeight
258
350
  };
259
351
 
260
352
  this._width = targetInfo.width;
@@ -263,8 +355,8 @@ Figure.prototype = {
263
355
 
264
356
  const _figure = this.editor.frameContext.get('_figure');
265
357
  this.editor._figureContainer = _figure.main;
266
- _figure.main.style.top = t + 'px';
267
- _figure.main.style.left = l + 'px';
358
+ _figure.main.style.top = top + 'px';
359
+ _figure.main.style.left = left + 'px';
268
360
  _figure.main.style.width = (this.isVertical ? h : w) + 'px';
269
361
  _figure.main.style.height = (this.isVertical ? w : h) + 'px';
270
362
  _figure.border.style.top = '0px';
@@ -272,7 +364,7 @@ Figure.prototype = {
272
364
  _figure.border.style.width = (this.isVertical ? h : w) + 'px';
273
365
  _figure.border.style.height = (this.isVertical ? w : h) + 'px';
274
366
 
275
- this.__offset = { left: l + scrollX, top: t + scrollY };
367
+ this.__offset = { left: left + scrollX, top: top + scrollY };
276
368
  this.editor.opendControllers.push({
277
369
  position: 'none',
278
370
  form: _figure.main,
@@ -285,71 +377,106 @@ Figure.prototype = {
285
377
  const value = /%$/.test(target.style.width) && /%$/.test(figureInfo.container.style.width) ? numbers.get(figureInfo.container.style.width, 0) / 100 + '' : '';
286
378
  for (let i = 0, len = this.percentageButtons.length; i < len; i++) {
287
379
  if (this.percentageButtons[i].getAttribute('data-value') === value) {
288
- domUtils.addClass(this.percentageButtons[i], 'active');
380
+ dom.utils.addClass(this.percentageButtons[i], 'active');
289
381
  } else {
290
- domUtils.removeClass(this.percentageButtons[i], 'active');
382
+ dom.utils.removeClass(this.percentageButtons[i], 'active');
291
383
  }
292
384
  }
293
385
 
294
386
  // caption active
295
387
  if (this.captionButton) {
296
388
  if (figureInfo.caption) {
297
- domUtils.addClass(this.captionButton, 'active');
389
+ dom.utils.addClass(this.captionButton, 'active');
298
390
  } else {
299
- domUtils.removeClass(this.captionButton, 'active');
391
+ dom.utils.removeClass(this.captionButton, 'active');
300
392
  }
301
393
  }
302
394
 
303
- _figure.display.style.display = nonSizeInfo ? 'none' : '';
395
+ _figure.display.style.display = nonSizeInfo || this._inlineCover ? 'none' : '';
304
396
  _figure.border.style.display = nonBorder ? 'none' : '';
305
397
  _figure.main.style.display = 'block';
306
398
 
307
399
  if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
308
400
  // align button
309
401
  this._setAlignIcon();
310
- this.editor._visibleControllers(true, true);
402
+ // as button
403
+ this._setAsIcon();
404
+ this.ui._visibleControllers(true, true);
311
405
  // size
312
406
  const size = this.getSize(target);
313
- domUtils.changeTxt(_figure.display, this.lang[this.align === 'none' ? 'basic' : this.align] + ' (' + size.w + ', ' + size.h + ')');
407
+ dom.utils.changeTxt(_figure.display, this.lang[this.align === 'none' ? 'basic' : this.align] + ' (' + size.w + ', ' + size.h + ')');
314
408
  this._displayResizeHandles(!nonResizing);
409
+ // rotate, aption, align, onresize - display;
410
+ const transformButtons = this.controller.form.querySelectorAll(
411
+ '[data-command="rotate"][data-value="90"], [data-command="rotate"][data-value="-90"], [data-command="caption"], [data-command="onalign"], [data-command="onresize"]'
412
+ );
413
+ const display = this._inlineCover || exceptionFormat ? 'none' : '';
414
+ transformButtons.forEach((button) => {
415
+ /** @type {HTMLButtonElement} */ (button).style.display = display;
416
+ });
417
+ // onas
418
+ const onas = this.controller.form.querySelector('[data-command="onas"]');
419
+ if (onas) {
420
+ /** @type {HTMLButtonElement} */ (onas).style.display = exceptionFormat ? 'none' : '';
421
+ }
315
422
  // selecte
316
- domUtils.removeClass(this._cover, 'se-figure-over-selected');
423
+ dom.utils.removeClass(this._cover, 'se-figure-over-selected');
317
424
  this.controller.open(_figure.main, null, { initMethod: this.__offContainer, isWWTarget: false, addOffset: null });
318
425
  this._w.setTimeout(() => _DragHandle.set('__overInfo', false), 0);
319
426
  } else {
320
- domUtils.addClass(this._cover, 'se-figure-over-selected');
427
+ dom.utils.addClass(this._cover, 'se-figure-over-selected');
321
428
  }
322
429
 
323
430
  // set members
324
- domUtils.addClass(this._cover, 'se-figure-selected');
431
+ dom.utils.addClass(this._cover, 'se-figure-selected');
325
432
  this._element_w = this._resize_w = w;
326
433
  this._element_h = this._resize_h = h;
327
- this._element_l = l;
328
- this._element_t = t;
434
+ this._element_l = left;
435
+ this._element_t = top;
329
436
 
330
437
  // drag
331
- if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT || domUtils.hasClass(figureInfo.container, 'se-input-component')) {
438
+ if (!this._inlineCover && (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT || dom.utils.hasClass(figureInfo.container, 'se-input-component'))) {
332
439
  this._setDragEvent(_figure.main);
333
440
  }
334
441
 
335
442
  return targetInfo;
336
- },
443
+ }
337
444
 
445
+ /**
446
+ * @description Hide the controller
447
+ */
338
448
  controllerHide() {
339
449
  this.controller.hide();
340
- },
450
+ }
341
451
 
452
+ /**
453
+ * @description Hide the controller
454
+ */
342
455
  controllerShow() {
343
456
  this.controller.show();
344
- },
457
+ }
345
458
 
346
- controllerOpen(target, args) {
347
- this._element = target;
348
- this.controller.open(target, null, args);
349
- },
459
+ /**
460
+ * @description Open the figure's controller
461
+ * @param {Node} target Target element
462
+ * @param {Object} [params={}] params
463
+ * @param {boolean=} params.isWWTarget If the controller is in the WYSIWYG area, set it to true.
464
+ * @param {() => void=} params.initMethod Method to be called when the controller is closed.
465
+ * @param {boolean=} params.disabled If true, the controller is disabled.
466
+ * @param {{left: number, top: number}=} params.addOffset Additional offset values
467
+ */
468
+ controllerOpen(target, params) {
469
+ this._element = /** @type {HTMLElement} */ (target);
470
+ this.controller.open(target, null, params);
471
+ }
350
472
 
473
+ /**
474
+ * @description Set the element's container size
475
+ * @param {string|number} w Width size
476
+ * @param {string|number} h Height size
477
+ */
351
478
  setSize(w, h) {
352
- if (/%$/.test(w)) {
479
+ if (/%$/.test(w + '')) {
353
480
  this._setPercentSize(w, h);
354
481
  } else if ((!w || w === 'auto') && (!h || h === 'auto')) {
355
482
  if (this.autoRatio) this._setPercentSize(100, this.autoRatio.default || this.autoRatio.current);
@@ -357,19 +484,27 @@ Figure.prototype = {
357
484
  } else {
358
485
  this._applySize(w, h, '');
359
486
  }
360
- },
487
+ }
361
488
 
362
489
  /**
363
490
  * @description Gets the Figure size
364
- * @param {Element|null} target
491
+ * @param {?Node=} targetNode Target element, default is the current element
365
492
  * @returns {{w: string, h: string}}
366
493
  */
367
- getSize(target) {
368
- if (!target) target = this._element;
369
- if (!target) return { w: '', h: '' };
494
+ getSize(targetNode) {
495
+ if (!targetNode) targetNode = this._element;
496
+ if (!targetNode) return { w: '', h: '' };
370
497
 
371
- const figure = Figure.GetContainer(target);
498
+ const figure = Figure.GetContainer(targetNode);
499
+ const target = figure.target;
372
500
  if (!figure.container) {
501
+ // exceptionFormat
502
+ if (!this.options.get('strictMode').formatFilter) {
503
+ return {
504
+ w: target.style.width || 'auto',
505
+ h: target.style.height || 'auto'
506
+ };
507
+ }
373
508
  return {
374
509
  w: '',
375
510
  h: target.style.height
@@ -377,42 +512,45 @@ Figure.prototype = {
377
512
  }
378
513
 
379
514
  const w = !/%$/.test(target.style.width) ? target.style.width : ((figure.container && numbers.get(figure.container.style.width, 2)) || 100) + '%';
380
- const h =
381
- numbers.get(figure.cover.style.paddingBottom, 0) > 0 && !this.isVertical
382
- ? figure.cover.style.height
383
- : !/%$/.test(target.style.height) || !/%$/.test(target.style.width)
384
- ? target.style.height
385
- : ((figure.container && numbers.get(figure.container.style.height, 2)) || 100) + '%';
515
+ const h = figure.inlineCover
516
+ ? figure.inlineCover.style.height
517
+ : numbers.get(figure.cover.style.paddingBottom, 0) > 0 && !this.isVertical
518
+ ? figure.cover.style.height
519
+ : !/%$/.test(target.style.height) || !/%$/.test(target.style.width)
520
+ ? target.style.height
521
+ : ((figure.container && numbers.get(figure.container.style.height, 2)) || 100) + '%';
386
522
  return {
387
523
  w: w || 'auto',
388
524
  h: h || 'auto'
389
525
  };
390
- },
526
+ }
391
527
 
392
528
  /**
393
529
  * @description Align the container.
394
- * @param {Element|null} target Target element
395
- * @param {"none"|"left"|"center"|"right"} align
530
+ * @param {?Node} targetNode Target element
531
+ * @param {string} align "none"|"left"|"center"|"right"
396
532
  */
397
- setAlign(target, align) {
398
- if (!target) target = this._element;
533
+ setAlign(targetNode, align) {
534
+ if (!targetNode) targetNode = this._element;
399
535
  this.align = align = align || 'none';
400
536
 
401
- const figure = Figure.GetContainer(target);
402
- const container = figure.container;
537
+ const figure = Figure.GetContainer(targetNode);
538
+ if (!figure.cover) return;
403
539
 
540
+ const target = figure.target;
541
+ const container = figure.container;
404
542
  const cover = figure.cover;
405
543
  if (/%$/.test(target.style.width) && align === 'center' && !this.component.isInline(container)) {
406
544
  container.style.minWidth = '100%';
407
545
  cover.style.width = container.style.width;
408
546
  } else {
409
547
  container.style.minWidth = '';
410
- cover.style.width = this.isVertical ? target.style.height || target.offsetHeight : !target.style.width || target.style.width === 'auto' ? '' : target.style.width || '100%';
548
+ cover.style.width = this.isVertical ? target.style.height || target.offsetHeight + 'px' : !target.style.width || target.style.width === 'auto' ? '' : target.style.width || '100%';
411
549
  }
412
550
 
413
- if (!domUtils.hasClass(container, '__se__float-' + align)) {
414
- domUtils.removeClass(container, this._floatClassStr);
415
- domUtils.addClass(container, '__se__float-' + align);
551
+ if (!dom.utils.hasClass(container, '__se__float-' + align)) {
552
+ dom.utils.removeClass(container, this._floatClassStr);
553
+ dom.utils.addClass(container, '__se__float-' + align);
416
554
  }
417
555
 
418
556
  if (this.autoRatio) {
@@ -421,22 +559,116 @@ Figure.prototype = {
421
559
  }
422
560
 
423
561
  this._setAlignIcon();
424
- },
562
+ }
563
+
564
+ /**
565
+ * @description As style[block, inline] the component
566
+ * @param {?Node} targetNode Target element
567
+ * @param {"block"|"inline"} formatStyle Format style
568
+ */
569
+ convertAsFormat(targetNode, formatStyle) {
570
+ if (!targetNode) targetNode = this._element;
571
+ this.as = formatStyle || 'block';
572
+ const { container, inlineCover, target } = Figure.GetContainer(targetNode);
573
+ const { w, h } = this.getSize(target);
574
+
575
+ const newTarget = /** @type {HTMLElement} */ (target.cloneNode(false));
576
+
577
+ switch (formatStyle) {
578
+ case 'inline': {
579
+ if (inlineCover) break;
580
+ this.component.deselect();
581
+
582
+ const next = container.nextElementSibling;
583
+ const parent = container.parentElement;
584
+
585
+ newTarget.style.width = '';
586
+ newTarget.style.height = '';
587
+ const figure = Figure.CreateInlineContainer(newTarget);
588
+ dom.utils.addClass(
589
+ figure.container,
590
+ container.className
591
+ .split(' ')
592
+ .filter((v) => v !== 'se-figure-selected' && v !== 'se-component-selected')
593
+ .join('|')
594
+ );
595
+
596
+ this._asFormatChange(figure, w, h);
597
+
598
+ const line = dom.utils.createElement(this.options.get('defaultLine'), null, figure.container);
599
+ parent.insertBefore(line, next);
600
+ dom.utils.removeItem(container);
601
+
602
+ break;
603
+ }
604
+ case 'block': {
605
+ if (!inlineCover) break;
606
+ this.component.deselect();
607
+
608
+ this.selection.setRange(container, 0, container, 1);
609
+ const r = this.html.remove();
610
+ const s = this.nodeTransform.split(r.container, r.offset, 0);
611
+
612
+ if (s?.previousElementSibling && dom.check.isZeroWidth(s.previousElementSibling)) {
613
+ dom.utils.removeItem(s.previousElementSibling);
614
+ }
615
+
616
+ newTarget.style.width = '';
617
+ newTarget.style.height = '';
618
+ const figure = Figure.CreateContainer(newTarget);
619
+ dom.utils.addClass(
620
+ figure.container,
621
+ container.className
622
+ .split(' ')
623
+ .filter((v) => v !== 'se-inline-component' && v !== 'se-figure-selected' && v !== 'se-component-selected')
624
+ .join('|')
625
+ );
626
+
627
+ this._asFormatChange(figure, w, h);
628
+
629
+ (s || r.container).parentElement.insertBefore(figure.container, s);
630
+
631
+ break;
632
+ }
633
+ }
634
+ }
635
+
636
+ /**
637
+ * @private
638
+ * @description Handles format conversion (block/inline) for the figure component and applies size changes.
639
+ * @param {FigureInfo} figureinfo {target, container, cover, inlineCover, caption}
640
+ * @param {string|number} w Width value.
641
+ * @param {string|number} h Height value.
642
+ */
643
+ _asFormatChange(figureinfo, w, h) {
644
+ const kind = this.kind;
645
+ figureinfo.target.onload = () => this.component.select(figureinfo.target, kind, false);
646
+
647
+ this._setFigureInfo(figureinfo);
648
+
649
+ if (figureinfo.inlineCover) {
650
+ this.setAlign(figureinfo.target, 'none');
651
+ this.deleteTransform();
652
+ }
653
+
654
+ this.setSize(w, h);
655
+ }
425
656
 
426
657
  /**
427
- * @override controller
428
- * @param {Element} target Target button element
658
+ * @description Controller button action
659
+ * @param {HTMLButtonElement} target Target button element
429
660
  * @returns
430
661
  */
431
662
  controllerAction(target) {
432
663
  const command = target.getAttribute('data-command');
433
664
  const value = target.getAttribute('data-value');
665
+ const type = target.getAttribute('data-type');
434
666
  const element = this._element;
435
- if (/^(onalign|onresize)$/.test(command)) return;
667
+ if (/^on.+/.test(command) || type === 'selectMenu') return;
436
668
 
437
669
  switch (command) {
438
670
  case 'mirror': {
439
- const info = GetRotateValue(element);
671
+ const info = this.#GetRotateValue(element);
440
672
  let x = info.x;
441
673
  let y = info.y;
442
674
 
@@ -455,7 +687,7 @@ Figure.prototype = {
455
687
  case 'caption':
456
688
  if (!this._caption) {
457
689
  const caption = Figure.CreateCaption(this._cover, this.lang.caption);
458
- const captionText = domUtils.getEdgeChild(caption, (current) => current.nodeType === 3);
690
+ const captionText = dom.query.getEdgeChild(caption, (current) => current.nodeType === 3, false);
459
691
 
460
692
  if (!captionText) {
461
693
  caption.focus();
@@ -465,7 +697,7 @@ Figure.prototype = {
465
697
 
466
698
  this.controller.close();
467
699
  } else {
468
- domUtils.removeItem(this._caption);
700
+ dom.utils.removeItem(this._caption);
469
701
  this._w.setTimeout(this.component.select.bind(this.component, element, this.kind), 0);
470
702
  }
471
703
 
@@ -501,15 +733,57 @@ Figure.prototype = {
501
733
  if (!/^remove|caption$/.test(command)) {
502
734
  this.component.select(element, this.kind, false);
503
735
  }
504
- },
736
+ }
737
+
738
+ /**
739
+ * @description Inspect the figure component format and change it to the correct format.
740
+ * @param {Node} container - The container element of the figure component.
741
+ * @param {Node} originEl - The original element of the figure component.
742
+ * @param {Node} anchorCover - The anchor cover element of the figure component.
743
+ * @param {import('./FileManager').default} [fileManagerInst=null] - FileManager module instance, if used.
744
+ */
745
+ retainFigureFormat(container, originEl, anchorCover, fileManagerInst) {
746
+ const isInline = this.component.isInline(container);
747
+ let existElement = this.format.isBlock(originEl.parentNode) || dom.check.isWysiwygFrame(originEl.parentNode) ? originEl : dom.check.isAnchor(originEl.parentNode) ? originEl.parentNode : this.format.getLine(originEl) || originEl;
748
+
749
+ if (dom.query.getParentElement(originEl, dom.check.isExcludeFormat)) {
750
+ existElement = anchorCover && anchorCover !== originEl ? anchorCover : originEl;
751
+ existElement.parentNode.replaceChild(container, existElement);
752
+ } else if (isInline && this.format.isLine(existElement)) {
753
+ const refer = isInline && /^SPAN$/i.test(originEl.parentElement.nodeName) ? originEl.parentElement : originEl;
754
+ refer.parentElement.replaceChild(container, refer);
755
+ } else if (dom.check.isListCell(existElement)) {
756
+ const refer = dom.query.getParentElement(originEl, (current) => current.parentNode === existElement);
757
+ existElement.insertBefore(container, refer);
758
+ dom.utils.removeItem(originEl);
759
+ this.nodeTransform.removeEmptyNode(refer, null, true);
760
+ } else if (this.format.isLine(existElement)) {
761
+ const refer = dom.query.getParentElement(originEl, (current) => current.parentNode === existElement);
762
+ existElement = this.nodeTransform.split(existElement, refer);
763
+ existElement.parentNode.insertBefore(container, existElement);
764
+ dom.utils.removeItem(originEl);
765
+ this.nodeTransform.removeEmptyNode(existElement, null, true);
766
+ } else {
767
+ if (this.format.isLine(existElement.parentNode)) {
768
+ const formats = existElement.parentNode;
769
+ formats.parentNode.insertBefore(container, existElement.previousSibling ? formats.nextElementSibling : formats);
770
+ if (fileManagerInst?.__updateTags.map((current) => existElement.contains(current)).length === 0) dom.utils.removeItem(existElement);
771
+ else if (dom.check.isZeroWidth(existElement)) dom.utils.removeItem(existElement);
772
+ } else {
773
+ existElement = dom.check.isFigure(existElement.parentNode) ? dom.query.getParentElement(existElement.parentNode, Figure.is) : existElement;
774
+ existElement.parentNode.replaceChild(container, existElement);
775
+ }
776
+ }
777
+ }
505
778
 
506
779
  /**
507
780
  * @description Initialize the transform style (rotation) of the element.
508
- * @param {Element|null} element Target element
781
+ * @param {?Node=} node Target element, default is the current element
509
782
  */
510
- deleteTransform(element) {
511
- if (!element) element = this._element;
783
+ deleteTransform(node) {
784
+ if (!node) node = this._element;
512
785
 
786
+ const element = /** @type {HTMLElement} */ (node);
513
787
  const size = (element.getAttribute('data-se-size') || '').split(',');
514
788
  this.isVertical = false;
515
789
 
@@ -519,18 +793,18 @@ Figure.prototype = {
519
793
 
520
794
  this._deleteCaptionPosition(element);
521
795
  this._applySize(size[0] || 'auto', size[1] || '', '');
522
- },
796
+ }
523
797
 
524
798
  /**
525
799
  * @description Set the transform style (rotation) of the element.
526
- * @param {Element} element Target element
527
- * @param {Number|null} width Element's width size
528
- * @param {Number|null} height Element's height size
800
+ * @param {Node} node Target element
801
+ * @param {?string|number} width Element's width size
802
+ * @param {?string|number} height Element's height size
529
803
  */
530
- setTransform(element, width, height, deg) {
804
+ setTransform(node, width, height, deg) {
531
805
  try {
532
806
  this.__preventSizechange = true;
533
- const info = GetRotateValue(element);
807
+ const info = this.#GetRotateValue(node);
534
808
  const slope = info.r + (deg || 0) * 1;
535
809
  deg = Math.abs(slope) >= 360 ? 0 : slope;
536
810
  const isVertical = (this.isVertical = /^(90|270)$/.test(Math.abs(deg).toString()));
@@ -538,6 +812,7 @@ Figure.prototype = {
538
812
  width = numbers.get(width, 0);
539
813
  height = numbers.get(height, 0);
540
814
 
815
+ const element = /** @type {HTMLElement} */ (node);
541
816
  const dataSize = (element.getAttribute('data-se-size') || 'auto,auto').split(',');
542
817
  let transOrigin = '';
543
818
  if (/auto|%$/.test(dataSize[0]) && !isVertical) {
@@ -548,6 +823,7 @@ Figure.prototype = {
548
823
  }
549
824
  } else {
550
825
  const figureInfo = Figure.GetContainer(element);
826
+ const cover = figureInfo.cover || figureInfo.inlineCover;
551
827
  const offsetW = width || element.offsetWidth;
552
828
  const offsetH = height || element.offsetHeight;
553
829
  const w = (isVertical ? offsetH : offsetW) + 'px';
@@ -556,8 +832,8 @@ Figure.prototype = {
556
832
  this._deletePercentSize();
557
833
  this._applySize(offsetW + 'px', offsetH + 'px', '');
558
834
 
559
- figureInfo.cover.style.width = w;
560
- figureInfo.cover.style.height = figureInfo.caption ? '' : h;
835
+ cover.style.width = w;
836
+ cover.style.height = figureInfo.caption || figureInfo.inlineCover ? '' : h;
561
837
 
562
838
  if (isVertical) {
563
839
  const transW = offsetW / 2 + 'px ' + offsetW / 2 + 'px 0';
@@ -576,13 +852,37 @@ Figure.prototype = {
576
852
  } finally {
577
853
  this.__preventSizechange = false;
578
854
  }
579
- },
855
+ }
580
856
 
857
+ /**
858
+ * @private
859
+ * @description Sets figure component properties such as cover, container, caption, and alignment.
860
+ * @param {FigureInfo} figureInfo - {target, container, cover, inlineCover, caption}
861
+ */
862
+ _setFigureInfo(figureInfo) {
863
+ this._inlineCover = figureInfo.inlineCover;
864
+ this._cover = figureInfo.cover || this._inlineCover;
865
+ this._container = figureInfo.container;
866
+ this._caption = figureInfo.caption;
867
+ this._element = figureInfo.target;
868
+ this.align = (this._container.className.match(/(?:^|\s)__se__float-(none|left|center|right)(?:$|\s)/) || [])[1] || figureInfo.target.style.float || 'none';
869
+ this.as = this._inlineCover ? 'inline' : 'block';
870
+ this.isVertical = /^(90|270)$/.test(Math.abs(this.#GetRotateValue(figureInfo.target).r).toString());
871
+ }
872
+
873
+ /**
874
+ * @private
875
+ * @description Applies rotation transformation to the target element.
876
+ * @param {HTMLElement} element Target element.
877
+ * @param {number} r Rotation degree.
878
+ * @param {number} x X-axis rotation value.
879
+ * @param {number} y Y-axis rotation value.
880
+ */
581
881
  _setRotate(element, r, x, y) {
582
- let width = (element.offsetWidth - element.offsetHeight) * (/^-/.test(r) ? 1 : -1);
882
+ let width = (element.offsetWidth - element.offsetHeight) * (/^-/.test(r + '') ? 1 : -1);
583
883
  let translate = '';
584
884
 
585
- if (/[1-9]/.test(r) && (x || y)) {
885
+ if (/[1-9]/.test(r + '') && (x || y)) {
586
886
  translate = x ? 'Y' : 'X';
587
887
 
588
888
  switch (r + '') {
@@ -610,13 +910,20 @@ Figure.prototype = {
610
910
  }
611
911
 
612
912
  element.style.transform = 'rotate(' + r + 'deg)' + (x ? ' rotateX(' + x + 'deg)' : '') + (y ? ' rotateY(' + y + 'deg)' : '') + (translate ? ' translate' + translate + '(' + width + 'px)' : '');
613
- },
913
+ }
614
914
 
915
+ /**
916
+ * @private
917
+ * @description Applies size adjustments to the figure element.
918
+ * @param {string|number} w Width value.
919
+ * @param {string|number} h Height value.
920
+ * @param {string} direction Resize direction.
921
+ */
615
922
  _applySize(w, h, direction) {
616
923
  const onlyW = /^(rw|lw)$/.test(direction) && /\d+/.test(this._element.style.height);
617
924
  const onlyH = /^(th|bh)$/.test(direction) && /\d+/.test(this._element.style.width);
618
- h = h || (this.autoRatio ? this.autoRatio.current || this.autoRatio.default : h);
619
- w = numbers.is(w) ? w + this.sizeUnit : w;
925
+ h = /** @type {string} */ (h || (this.autoRatio ? this.autoRatio.current || this.autoRatio.default : h));
926
+ w = /** @type {string} */ (numbers.is(w) ? w + this.sizeUnit : w);
620
927
 
621
928
  if (!/%$/.test(w) && !/%$/.test(h) && !onlyW && !onlyH) this._deletePercentSize();
622
929
 
@@ -639,17 +946,29 @@ Figure.prototype = {
639
946
 
640
947
  // save current size
641
948
  this._saveCurrentSize();
642
- },
949
+ }
643
950
 
951
+ /**
952
+ * @private
953
+ * @description Sets padding-bottom for cover elements based on width and height.
954
+ * @param {string} w Width value.
955
+ * @param {string} h Height value.
956
+ */
644
957
  __setCoverPaddingBottom(w, h) {
958
+ if (this._inlineCover === this._cover) return;
959
+
645
960
  this._cover.style.height = h;
646
961
  if (/%$/.test(w) && this.align === 'center') {
647
962
  this._cover.style.paddingBottom = !/%$/.test(h) ? h : numbers.get((numbers.get(h, 2) / 100) * numbers.get(w, 2), 2) + '%';
648
963
  } else {
649
964
  this._cover.style.paddingBottom = h;
650
965
  }
651
- },
966
+ }
652
967
 
968
+ /**
969
+ * @private
970
+ * @description Sets the figure element to its auto size.
971
+ */
653
972
  _setAutoSize() {
654
973
  if (this._caption) this._caption.style.marginTop = '';
655
974
  this.deleteTransform();
@@ -669,53 +988,93 @@ Figure.prototype = {
669
988
 
670
989
  // save current size
671
990
  this._saveCurrentSize();
672
- },
991
+ }
673
992
 
993
+ /**
994
+ * @private
995
+ * @description Sets the figure element's size in percentage.
996
+ * @param {string|number} w Width percentage.
997
+ * @param {string|number} h Height percentage.
998
+ */
674
999
  _setPercentSize(w, h) {
675
1000
  if (!h) h = this.autoRatio ? (/%$/.test(this.autoRatio.current) ? this.autoRatio.current : this.autoRatio.default) : h;
676
- h = h && !/%$/.test(h) && !numbers.get(h, 0) ? (numbers.is(h) ? h + '%' : h) : numbers.is(h) ? h + this.sizeUnit : h || (this.autoRatio ? this.autoRatio.default : '');
1001
+ h = h && !/%$/.test(h + '') && !numbers.get(h, 0) ? (numbers.is(h) ? h + '%' : h) : numbers.is(h) ? h + this.sizeUnit : h || (this.autoRatio ? this.autoRatio.default : '');
677
1002
 
678
- const heightPercentage = /%$/.test(h);
679
- this._container.style.width = numbers.is(w) ? w + '%' : w;
1003
+ const heightPercentage = /%$/.test(h + '');
1004
+ this._container.style.width = String(numbers.is(w) ? w + '%' : w);
680
1005
  this._container.style.height = '';
681
- this._cover.style.width = '100%';
682
- this._cover.style.height = h;
1006
+
1007
+ // exceptionFormat
1008
+ if (this._element === this._cover && !this.options.get('strictMode').formatFilter) {
1009
+ this._saveCurrentSize();
1010
+ return;
1011
+ }
1012
+
1013
+ if (this._inlineCover !== this._cover) {
1014
+ this._cover.style.width = '100%';
1015
+ this._cover.style.height = String(h);
1016
+ }
683
1017
  this._element.style.width = '100%';
684
1018
  this._element.style.maxWidth = '';
685
- this._element.style.height = this.autoRatio ? '100%' : heightPercentage ? '' : h;
1019
+ this._element.style.height = String(this.autoRatio ? '100%' : heightPercentage ? '' : h);
686
1020
 
687
1021
  if (this.align === 'center') this.setAlign(this._element, this.align);
688
1022
  if (this.autoRatio) {
689
- this.__setCoverPaddingBottom(w, h);
1023
+ this.__setCoverPaddingBottom(String(w), String(h));
690
1024
  }
691
1025
 
692
1026
  this._setCaptionPosition(this._element);
693
1027
 
694
1028
  // save current size
695
1029
  this._saveCurrentSize();
696
- },
1030
+ }
697
1031
 
1032
+ /**
1033
+ * @private
1034
+ * @description Deletes percentage-based sizing from the figure element.
1035
+ */
698
1036
  _deletePercentSize() {
699
1037
  this._cover.style.width = '';
700
1038
  this._cover.style.height = '';
701
1039
  this._container.style.width = '';
702
1040
  this._container.style.height = '';
703
1041
 
704
- domUtils.removeClass(this._container, this._floatClassStr);
705
- domUtils.addClass(this._container, '__se__float-' + this.align);
1042
+ dom.utils.removeClass(this._container, this._floatClassStr);
1043
+ dom.utils.addClass(this._container, '__se__float-' + this.align);
706
1044
 
707
1045
  if (this.align === 'center') this.setAlign(this._element, this.align);
708
- },
1046
+ }
709
1047
 
1048
+ /**
1049
+ * @private
1050
+ * @description Reverts the figure element to its previously saved size.
1051
+ */
710
1052
  _setRevert() {
711
1053
  this.setSize(this.__revertSize.w, this.__revertSize.h);
712
- },
1054
+ }
713
1055
 
1056
+ /**
1057
+ * @private
1058
+ * @description Updates the figure's alignment icon.
1059
+ */
714
1060
  _setAlignIcon() {
715
1061
  if (!this.alignButton) return;
716
- domUtils.changeElement(this.alignButton.firstElementChild, this._alignIcons[this.align]);
717
- },
1062
+ dom.utils.changeElement(this.alignButton.firstElementChild, this._alignIcons[this.align]);
1063
+ }
718
1064
 
1065
+ /**
1066
+ * @private
1067
+ * @description Updates the figure's block/inline format icon.
1068
+ */
1069
+ _setAsIcon() {
1070
+ if (!this.asButton) return;
1071
+ dom.utils.changeElement(this.asButton.firstElementChild, this.icons[`as_${this.as}`]);
1072
+ }
1073
+
1074
+ /**
1075
+ * @private
1076
+ * @description Saves the current size of the figure component.
1077
+ */
719
1078
  _saveCurrentSize() {
720
1079
  if (this.__preventSizechange) return;
721
1080
 
@@ -731,40 +1090,59 @@ Figure.prototype = {
731
1090
  if (this.autoRatio) {
732
1091
  this.autoRatio.current = /%$/.test(size.h) ? size.h : '';
733
1092
  }
734
- },
1093
+ }
735
1094
 
1095
+ /**
1096
+ * @private
1097
+ * @description Adjusts the position of the caption within the figure.
1098
+ * @param {HTMLElement} element Target element.
1099
+ */
736
1100
  _setCaptionPosition(element) {
737
- const figcaption = domUtils.getEdgeChild(domUtils.getParentElement(element, 'FIGURE'), 'FIGCAPTION');
1101
+ const figcaption = /** @type {HTMLElement} */ (dom.query.getEdgeChild(dom.query.getParentElement(element, 'FIGURE'), 'FIGCAPTION', false));
738
1102
  if (figcaption) {
739
1103
  figcaption.style.marginTop = (this.isVertical ? element.offsetWidth - element.offsetHeight : 0) + 'px';
740
1104
  }
741
- },
1105
+ }
742
1106
 
1107
+ /**
1108
+ * @private
1109
+ * @description Removes the margin top property from the figure caption.
1110
+ * @param {HTMLElement} element Target element.
1111
+ */
743
1112
  _deleteCaptionPosition(element) {
744
- const figcaption = domUtils.getEdgeChild(domUtils.getParentElement(element, 'FIGURE'), 'FIGCAPTION');
1113
+ const figcaption = /** @type {HTMLElement} */ (dom.query.getEdgeChild(dom.query.getParentElement(element, 'FIGURE'), 'FIGCAPTION', false));
745
1114
  if (figcaption) {
746
1115
  figcaption.style.marginTop = '';
747
1116
  }
748
- },
1117
+ }
749
1118
 
1119
+ /**
1120
+ * @private
1121
+ * @description Displays or hides the resize handles of the figure component.
1122
+ * @param {boolean} display Whether to display resize handles.
1123
+ */
750
1124
  _displayResizeHandles(display) {
751
- display = !display ? 'none' : 'flex';
752
- this.controller.form.style.display = display;
1125
+ const type = !display ? 'none' : 'flex';
1126
+ this.controller.form.style.display = type;
753
1127
 
754
1128
  const _figure = this.editor.frameContext.get('_figure');
755
1129
  const resizeHandles = _figure.handles;
756
1130
  for (let i = 0, len = resizeHandles.length; i < len; i++) {
757
- resizeHandles[i].style.display = display;
1131
+ resizeHandles[i].style.display = type;
758
1132
  }
759
1133
 
760
- if (display === 'none') {
761
- domUtils.addClass(_figure.main, 'se-resize-ing');
1134
+ if (type === 'none') {
1135
+ dom.utils.addClass(_figure.main, 'se-resize-ing');
762
1136
  this.__onResizeESCEvent = this.eventManager.addGlobalEvent('keydown', this.__containerResizingESC);
763
1137
  } else {
764
- domUtils.removeClass(_figure.main, 'se-resize-ing');
1138
+ dom.utils.removeClass(_figure.main, 'se-resize-ing');
765
1139
  }
766
- },
1140
+ }
767
1141
 
1142
+ /**
1143
+ * @private
1144
+ * @description Removes the resize event listeners.
1145
+ */
768
1146
  _offResizeEvent() {
769
1147
  this.component._removeDragEvent();
770
1148
  this.eventManager.removeGlobalEvent(this.__onContainerEvent);
@@ -772,13 +1150,18 @@ Figure.prototype = {
772
1150
  this.eventManager.removeGlobalEvent(this.__onResizeESCEvent);
773
1151
 
774
1152
  this._displayResizeHandles(true);
775
- this.editor._offCurrentController();
776
- this.editor.disableBackWrapper();
777
- },
1153
+ this.ui._offCurrentController();
1154
+ this.ui.disableBackWrapper();
1155
+ }
778
1156
 
1157
+ /**
1158
+ * @private
1159
+ * @description Sets up drag event handling for the figure component.
1160
+ * @param {Node} figureMain The main figure container element.
1161
+ */
779
1162
  _setDragEvent(figureMain) {
780
1163
  const dragHandle = this.editor.frameContext.get('wrapper').querySelector('.se-drag-handle');
781
- domUtils.removeClass(dragHandle, 'se-drag-handle-full');
1164
+ dom.utils.removeClass(dragHandle, 'se-drag-handle-full');
782
1165
 
783
1166
  dragHandle.style.opacity = '';
784
1167
  dragHandle.style.width = '';
@@ -787,195 +1170,240 @@ Figure.prototype = {
787
1170
  _DragHandle.set('__dragHandler', dragHandle);
788
1171
  _DragHandle.set('__dragContainer', this._container);
789
1172
  _DragHandle.set('__dragCover', this._cover);
790
- _DragHandle.set('__dragMove', OnScrollDragHandler.bind(this, dragHandle, figureMain));
1173
+ _DragHandle.set('__dragMove', this.#OnScrollDragHandler.bind(this, dragHandle, figureMain));
791
1174
 
792
1175
  _DragHandle.get('__dragMove')();
793
1176
 
794
1177
  dragHandle.style.display = 'block';
795
- },
1178
+ }
796
1179
 
797
- _retainFigureFormat(container, originEl, anchorCover) {
798
- let existElement = this.format.isBlock(originEl.parentNode) || domUtils.isWysiwygFrame(originEl.parentNode) ? originEl : domUtils.isAnchor(originEl.parentNode) ? originEl.parentNode : this.format.getLine(originEl) || originEl;
1180
+ /**
1181
+ * @param {HTMLElement} dragHandle Drag handle element
1182
+ * @param {HTMLElement} figureMain Figure container element
1183
+ */
1184
+ #OnScrollDragHandler(dragHandle, figureMain) {
1185
+ dragHandle.style.display = 'block';
1186
+ dragHandle.style.left = figureMain.offsetLeft + (this.options.get('_rtl') ? dragHandle.offsetWidth : figureMain.offsetWidth - dragHandle.offsetWidth * 1.5) + 'px';
1187
+ dragHandle.style.top = figureMain.offsetTop - dragHandle.offsetHeight + 'px';
1188
+ }
799
1189
 
800
- if (domUtils.getParentElement(originEl, domUtils.isExcludeFormat)) {
801
- existElement = anchorCover && anchorCover !== originEl ? anchorCover : originEl;
802
- existElement.parentNode.replaceChild(container, existElement);
803
- } else if (domUtils.isListCell(existElement)) {
804
- const refer = domUtils.getParentElement(originEl, (current) => current.parentNode === existElement);
805
- existElement.insertBefore(container, refer);
806
- domUtils.removeItem(originEl);
807
- this.nodeTransform.removeEmptyNode(refer, null, true);
808
- } else if (this.format.isLine(existElement)) {
809
- const refer = domUtils.getParentElement(originEl, (current) => current.parentNode === existElement);
810
- existElement = this.nodeTransform.split(existElement, refer);
811
- existElement.parentNode.insertBefore(container, existElement);
812
- domUtils.removeItem(originEl);
813
- this.nodeTransform.removeEmptyNode(existElement, null, true);
814
- } else {
815
- if (this.format.isLineOnly(existElement.parentNode)) {
816
- const formats = existElement.parentNode;
817
- formats.parentNode.insertBefore(container, existElement.previousSibling ? formats.nextElementSibling : formats);
818
- if (this.fileManager.__updateTags.map((current) => existElement.contains(current)).length === 0) domUtils.removeItem(existElement);
819
- } else {
820
- existElement = domUtils.isFigure(existElement.parentNode) ? domUtils.getParentElement(existElement.parentNode, Figure.__is) : existElement;
821
- existElement.parentNode.replaceChild(container, existElement);
1190
+ /**
1191
+ * @param {MouseEvent} e Event object
1192
+ */
1193
+ #OnResizeContainer(e) {
1194
+ e.stopPropagation();
1195
+ e.preventDefault();
1196
+
1197
+ const eventTarget = dom.query.getEventTarget(e);
1198
+ const inst = _DragHandle.get('__figureInst');
1199
+ const direction = (inst._resize_direction = eventTarget.classList[0]);
1200
+ inst._resizeClientX = e.clientX;
1201
+ inst._resizeClientY = e.clientY;
1202
+ inst.editor.frameContext.get('_figure').main.style.float = /l/.test(direction) ? 'right' : /r/.test(direction) ? 'left' : 'none';
1203
+ this.ui.enableBackWrapper(DIRECTION_CURSOR_MAP[direction]);
1204
+
1205
+ const { w, h } = this.getSize(inst._element);
1206
+ __resizing_p_wh = __resizing_p_ow = false;
1207
+ __resizing_cw = __resizing_sw = 0;
1208
+ if (!this.isVertical) {
1209
+ const pw = !w || /auto|%$/.test(w);
1210
+ const ph = !h || /auto|%$/.test(h);
1211
+ if (DIR_DIAGONAL.includes(direction) && pw && ph) {
1212
+ __resizing_p_wh = true;
1213
+ } else if (DIR_W.includes(direction) && pw) {
1214
+ __resizing_p_ow = true;
1215
+ }
1216
+
1217
+ if (__resizing_p_wh || __resizing_p_ow) {
1218
+ const sizeTarget = inst._cover || inst._element;
1219
+ __resizing_sw = sizeTarget.offsetWidth;
1220
+ __resizing_cw = converter.getWidthInPercentage(sizeTarget, this.editor.frameContext.get('wysiwygFrame')) / 100;
822
1221
  }
823
1222
  }
824
- },
825
1223
 
826
- constructor: Figure
827
- };
1224
+ inst.__onContainerEvent = inst.eventManager.addGlobalEvent('mousemove', inst.__containerResizing);
1225
+ inst.__offContainerEvent = inst.eventManager.addGlobalEvent('mouseup', inst.__containerResizingOff);
1226
+ inst._displayResizeHandles(false);
828
1227
 
829
- function OnScrollDragHandler(dragHandle, figureMain) {
830
- dragHandle.style.display = 'block';
831
- dragHandle.style.left = figureMain.offsetLeft + (this.options.get('_rtl') ? dragHandle.offsetWidth : figureMain.offsetWidth - dragHandle.offsetWidth * 1.5) + 'px';
832
- dragHandle.style.top = figureMain.offsetTop - dragHandle.offsetHeight + 'px';
833
- }
1228
+ const _display = this.editor.frameContext.get('_figure').display;
1229
+ _display.style.display = 'block';
1230
+ dom.utils.changeTxt(_display, w + ' x ' + h);
1231
+ }
834
1232
 
835
- function GetRotateValue(element) {
836
- const transform = element.style.transform;
837
- if (!transform) return { r: 0, x: '', y: '' };
838
- return {
839
- r: ((transform.match(/rotate\(([-0-9]+)deg\)/) || [])[1] || 0) * 1,
840
- x: (transform.match(/rotateX\(([-0-9]+)deg\)/) || [])[1] || '',
841
- y: (transform.match(/rotateY\(([-0-9]+)deg\)/) || [])[1] || ''
842
- };
843
- }
1233
+ /**
1234
+ * @description Handles the resizing of the figure container.
1235
+ * @param {MouseEvent} e Mouse event.
1236
+ */
1237
+ #ContainerResizing(e) {
1238
+ const direction = this._resize_direction;
1239
+ const clientX = e.clientX;
1240
+ const clientY = e.clientY;
1241
+
1242
+ let resultW = this._element_w;
1243
+ let resultH = this._element_h;
1244
+
1245
+ const w = resultW + (/r/.test(direction) ? clientX - this._resizeClientX : this._resizeClientX - clientX);
1246
+ const h = resultH + (/b/.test(direction) ? clientY - this._resizeClientY : this._resizeClientY - clientY);
1247
+ const wh = (resultH / resultW) * w;
1248
+ const resizeBorder = this.editor.frameContext.get('_figure').border;
844
1249
 
845
- function OnResizeContainer(e) {
846
- e.stopPropagation();
847
- e.preventDefault();
848
-
849
- const inst = _DragHandle.get('__figureInst');
850
- const direction = (inst._resize_direction = e.target.classList[0]);
851
- inst._resizeClientX = e.clientX;
852
- inst._resizeClientY = e.clientY;
853
- inst.editor.frameContext.get('_figure').main.style.float = /l/.test(direction) ? 'right' : /r/.test(direction) ? 'left' : 'none';
854
- this.editor.enableBackWrapper(DIRECTION_CURSOR_MAP[direction]);
855
-
856
- const { w, h } = this.getSize(inst._element);
857
- __resizing_p_wh = __resizing_p_ow = false;
858
- __resizing_cw = __resizing_sw = 0;
859
- if (!this.isVertical) {
860
- const pw = !w || /auto|%$/.test(w);
861
- const ph = !h || /auto|%$/.test(h);
862
- if (DIR_DIAGONAL.includes(direction) && pw && ph) {
863
- __resizing_p_wh = true;
864
- } else if (DIR_W.includes(direction) && pw) {
865
- __resizing_p_ow = true;
1250
+ if (/t/.test(direction)) resizeBorder.style.top = resultH - (/h/.test(direction) ? h : wh) + 'px';
1251
+ if (/l/.test(direction)) resizeBorder.style.left = resultW - w + 'px';
1252
+
1253
+ if (/r|l/.test(direction)) {
1254
+ resizeBorder.style.width = w + 'px';
1255
+ resultW = w;
866
1256
  }
867
1257
 
868
- if (__resizing_p_wh || __resizing_p_ow) {
869
- const sizeTarget = inst._cover || inst._element;
870
- __resizing_sw = sizeTarget.offsetWidth;
871
- __resizing_cw = converter.getWidthInPercentage(sizeTarget, this.editor.frameContext.get('wysiwygFrame')) / 100;
1258
+ if (/^(t|b)[^h]$/.test(direction)) {
1259
+ resizeBorder.style.height = wh + 'px';
1260
+ resultH = wh;
1261
+ } else if (/^(t|b)h$/.test(direction)) {
1262
+ resizeBorder.style.height = h + 'px';
1263
+ resultH = h;
872
1264
  }
873
- }
874
1265
 
875
- inst.__onContainerEvent = inst.eventManager.addGlobalEvent('mousemove', inst.__containerResizing);
876
- inst.__offContainerEvent = inst.eventManager.addGlobalEvent('mouseup', inst.__containerResizingOff);
877
- inst._displayResizeHandles(false);
878
- }
1266
+ this._resize_w = /** @type {number} */ (/h$/.test(direction) ? this._width : Math.round(resultW));
1267
+ this._resize_h = /** @type {number} */ (/w$/.test(direction) ? this._height : Math.round(resultH));
1268
+ const rw = __resizing_cw ? (this._resize_w / __resizing_sw) * __resizing_cw * 100 : this._resize_w;
1269
+ dom.utils.changeTxt(this.editor.frameContext.get('_figure').display, __resizing_cw ? numbers.get(rw > 100 ? 100 : rw, 2).toFixed(2) + '%' : rw + ' x ' + this._resize_h);
1270
+ }
879
1271
 
880
- function ContainerResizing(e) {
881
- const direction = this._resize_direction;
882
- const clientX = e.clientX;
883
- const clientY = e.clientY;
1272
+ /**
1273
+ * @description Finalizes the resizing process of the figure container.
1274
+ */
1275
+ #ContainerResizingOff() {
1276
+ this._offResizeEvent();
1277
+
1278
+ // set size
1279
+ let w = this.isVertical ? this._resize_h : this._resize_w;
1280
+ let h = this.isVertical ? this._resize_w : this._resize_h;
1281
+ w = Math.round(w) || w;
1282
+ h = Math.round(h) || h;
1283
+
1284
+ if (!this.isVertical && !/%$/.test(w + '')) {
1285
+ const limit =
1286
+ this.editor.frameContext.get('wysiwygFrame').clientWidth -
1287
+ numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-left')) +
1288
+ numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-right')) -
1289
+ 2;
1290
+ if (numbers.get(w, 0) > limit) {
1291
+ h = Math.round((h / w) * limit);
1292
+ w = limit;
1293
+ }
1294
+ }
884
1295
 
885
- let resultW = this._element_w;
886
- let resultH = this._element_h;
1296
+ if (__resizing_p_wh || __resizing_p_ow) {
1297
+ const sizeTarget = this._cover || this._element;
1298
+ w = (w / sizeTarget.offsetWidth) * __resizing_cw * 100;
1299
+ const wp = numbers.get(w > 100 ? 100 : w, 2) + '%';
1300
+ this._setPercentSize(wp, __resizing_p_ow ? this.getSize(this._element).h : '');
1301
+ } else {
1302
+ this._applySize(w, h, this._resize_direction);
1303
+ if (this.isVertical) this.setTransform(this._element, w, h, 0);
1304
+ }
887
1305
 
888
- const w = resultW + (/r/.test(direction) ? clientX - this._resizeClientX : this._resizeClientX - clientX);
889
- const h = resultH + (/b/.test(direction) ? clientY - this._resizeClientY : this._resizeClientY - clientY);
890
- const wh = (resultH / resultW) * w;
891
- const resizeBorder = this.editor.frameContext.get('_figure').border;
1306
+ this.history.push(false);
1307
+ this.component.select(this._element, this.kind, false);
1308
+ }
892
1309
 
893
- if (/t/.test(direction)) resizeBorder.style.top = resultH - (/h/.test(direction) ? h : wh) + 'px';
894
- if (/l/.test(direction)) resizeBorder.style.left = resultW - w + 'px';
1310
+ /**
1311
+ * @description Cancels the resizing process when the escape key is pressed.
1312
+ * @param {KeyboardEvent} e Keyboard event.
1313
+ */
1314
+ #ContainerResizingESC(e) {
1315
+ if (!keyCodeMap.isEsc(e.code)) return;
1316
+ this._offResizeEvent();
1317
+ this.component.select(this._element, this.kind, false);
1318
+ }
895
1319
 
896
- if (/r|l/.test(direction)) {
897
- resizeBorder.style.width = w + 'px';
898
- resultW = w;
1320
+ /**
1321
+ * @param { "none"|"left"|"center"|"right"} value align value
1322
+ */
1323
+ #SetMenuAlign(value) {
1324
+ this.setAlign(this._element, value);
1325
+ this.selectMenu_align.close();
1326
+ this.component.select(this._element, this.kind, false);
899
1327
  }
900
1328
 
901
- if (/^(t|b)[^h]$/.test(direction)) {
902
- resizeBorder.style.height = wh + 'px';
903
- resultH = wh;
904
- } else if (/^(t|b)h$/.test(direction)) {
905
- resizeBorder.style.height = h + 'px';
906
- resultH = h;
1329
+ /**
1330
+ * @param {"block"|"inline"} value Format style
1331
+ */
1332
+ #SetMenuAs(value) {
1333
+ this.convertAsFormat(this._element, value);
1334
+ this.selectMenu_as.close();
907
1335
  }
908
1336
 
909
- this._resize_w = /h$/.test(direction) ? this._width : Math.round(resultW);
910
- this._resize_h = /w$/.test(direction) ? this._height : Math.round(resultH);
911
- const rw = __resizing_cw ? (this._resize_w / __resizing_sw) * __resizing_cw * 100 : this._resize_w;
912
- domUtils.changeTxt(this.editor.frameContext.get('_figure').display, __resizing_cw ? numbers.get(rw > 100 ? 100 : rw, 2).toFixed(2) + '%' : rw + ' x ' + this._resize_h);
913
- }
1337
+ /**
1338
+ * @param {"auto"|number} value Resize value
1339
+ */
1340
+ #SetResize(value) {
1341
+ if (value === 'auto') {
1342
+ this.deleteTransform();
1343
+ this._setAutoSize();
1344
+ } else {
1345
+ let dataY = this.getSize(this._element).h;
1346
+ if (this.isVertical) {
1347
+ const dataSize = (this._element.getAttribute('data-se-size') || ',').split(',');
1348
+ if (dataSize[1]) dataY = dataSize[1];
1349
+ }
914
1350
 
915
- function ContainerResizingOff() {
916
- this._offResizeEvent();
917
-
918
- // set size
919
- let w = this.isVertical ? this._resize_h : this._resize_w;
920
- let h = this.isVertical ? this._resize_w : this._resize_h;
921
- w = Math.round(w) || w;
922
- h = Math.round(h) || h;
923
-
924
- if (!this.isVertical && !/%$/.test(w)) {
925
- const limit =
926
- this.editor.frameContext.get('wysiwygFrame').clientWidth -
927
- numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-left')) +
928
- numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-right')) -
929
- 2;
930
- if (numbers.get(w, 0) > limit) {
931
- h = Math.round((h / w) * limit);
932
- w = limit;
1351
+ this.deleteTransform();
1352
+ this._setPercentSize(value * 1, numbers.get(dataY, 0) === null || !/%$/.test(dataY) ? '' : dataY);
933
1353
  }
934
- }
935
1354
 
936
- if (__resizing_p_wh || __resizing_p_ow) {
937
- const sizeTarget = this._cover || this._element;
938
- w = (w / sizeTarget.offsetWidth) * __resizing_cw * 100;
939
- w = numbers.get(w > 100 ? 100 : w, 2) + '%';
940
- this._setPercentSize(w, __resizing_p_ow ? this.getSize(this._element).h : '');
941
- } else {
942
- this._applySize(w, h, this._resize_direction);
943
- if (this.isVertical) this.setTransform(this._element, w, h, 0);
1355
+ this.selectMenu_resize.close();
1356
+ this.component.select(this._element, this.kind, false);
944
1357
  }
945
1358
 
946
- this.history.push(false);
947
- this.component.select(this._element, this.kind, false);
948
- }
1359
+ #OffFigureContainer() {
1360
+ this.editor.frameContext.get('_figure').main.style.display = 'none';
1361
+ this.editor._figureContainer = null;
1362
+ }
949
1363
 
950
- function ContainerResizingESC(e) {
951
- if (!/^27$/.test(e.keyCode)) return;
952
- this._offResizeEvent();
953
- this.component.select(this._element, this.kind, false);
954
- }
1364
+ #OnClick_alignButton() {
1365
+ this.selectMenu_align.open('', '[data-command="' + this.align + '"]');
1366
+ }
955
1367
 
956
- function SetMenuAlign(value) {
957
- this.setAlign(this._element, value);
958
- this.selectMenu_align.close();
959
- this.component.select(this._element, this.kind, false);
960
- }
1368
+ #OnClick_asButton() {
1369
+ this.selectMenu_as.open('', '[data-command="' + this.as + '"]');
1370
+ }
961
1371
 
962
- function SetResize(value) {
963
- if (value === 'auto') {
964
- this.deleteTransform();
965
- this._setAutoSize();
966
- } else {
967
- let dataY = this.getSize(this._element).h;
968
- if (this.isVertical) {
969
- const dataSize = (this._element.getAttribute('data-se-size') || ',').split(',');
970
- if (dataSize[1]) dataY = dataSize[1];
1372
+ #OnClick_resizeButton() {
1373
+ const size = this.getSize(this._element);
1374
+ const w = size.w;
1375
+ const h = size.h;
1376
+ let command = '';
1377
+ if (this.autoRatio) {
1378
+ if (h === this.autoRatio.default && /%$/.test(w)) {
1379
+ const nw = numbers.get(w);
1380
+ if (nw === 100) command = 'auto';
1381
+ else command = 'resize_percent' + nw;
1382
+ }
1383
+ } else if (h === 'auto') {
1384
+ if (w === 'auto') {
1385
+ command = 'auto';
1386
+ } else if (/%$/.test(w)) {
1387
+ command = 'resize_percent' + numbers.get(w);
1388
+ }
971
1389
  }
972
1390
 
973
- this.deleteTransform();
974
- this._setPercentSize(value * 1, numbers.get(dataY, 0) === null || !/%$/.test(dataY) ? '' : dataY);
1391
+ this.selectMenu_resize.open('', '[data-command="' + command + '"]');
975
1392
  }
976
1393
 
977
- this.selectMenu_resize.close();
978
- this.component.select(this._element, this.kind, false);
1394
+ /**
1395
+ * @param {Node} element Target element
1396
+ * @returns {{ r: *, x: *, y: * }} Rotation value
1397
+ */
1398
+ #GetRotateValue(element) {
1399
+ const transform = /** @type {HTMLElement} */ (element).style.transform;
1400
+ if (!transform) return { r: 0, x: '', y: '' };
1401
+ return {
1402
+ r: Number((transform.match(/rotate\(([-0-9]+)deg\)/) || [])[1] || 0),
1403
+ x: (transform.match(/rotateX\(([-0-9]+)deg\)/) || [])[1] || '',
1404
+ y: (transform.match(/rotateY\(([-0-9]+)deg\)/) || [])[1] || ''
1405
+ };
1406
+ }
979
1407
  }
980
1408
 
981
1409
  function CreateAlign(inst, button) {
@@ -988,7 +1416,29 @@ function CreateAlign(inst, button) {
988
1416
  const items = [];
989
1417
  for (let i = 0; i < commands.length; i++) {
990
1418
  html.push(/*html*/ `
991
- <button type="button" class="se-btn-list se-tooltip" data-command="${commands[i]}">
1419
+ <button type="button" class="se-btn-list se-tooltip" data-command="${commands[i]}" data-type="selectMenu" >
1420
+ ${icons[i]}
1421
+ <span class="se-tooltip-inner">
1422
+ <span class="se-tooltip-text">${langs[i]}</span>
1423
+ </span>
1424
+ </button>`);
1425
+ items.push(commands[i]);
1426
+ }
1427
+
1428
+ return { html: html, items: items };
1429
+ }
1430
+
1431
+ function CreateAs(inst, button) {
1432
+ if (!button) return null;
1433
+
1434
+ const icons = [inst.icons.as_block, inst.icons.as_inline];
1435
+ const langs = [inst.lang.asBlock, inst.lang.asInline];
1436
+ const commands = ['block', 'inline'];
1437
+ const html = [];
1438
+ const items = [];
1439
+ for (let i = 0; i < commands.length; i++) {
1440
+ html.push(/*html*/ `
1441
+ <button type="button" class="se-btn-list se-tooltip" data-command="${commands[i]}" data-type="selectMenu" >
992
1442
  ${icons[i]}
993
1443
  <span class="se-tooltip-inner">
994
1444
  <span class="se-tooltip-text">${langs[i]}</span>
@@ -1016,37 +1466,6 @@ function CreateResize(editor, button) {
1016
1466
  return { html: html, items: items };
1017
1467
  }
1018
1468
 
1019
- function OffFigureContainer() {
1020
- this.editor.frameContext.get('_figure').main.style.display = 'none';
1021
- this.editor._figureContainer = null;
1022
- }
1023
-
1024
- function OnClick_alignButton() {
1025
- this.selectMenu_align.open('', '[data-command="' + this.align + '"]');
1026
- }
1027
-
1028
- function OnClick_resizeButton() {
1029
- const size = this.getSize(this._element);
1030
- const w = size.w;
1031
- const h = size.h;
1032
- let command = '';
1033
- if (this.autoRatio) {
1034
- if (h === this.autoRatio.default && /%$/.test(w)) {
1035
- const nw = numbers.get(w);
1036
- if (nw === 100) command = 'auto';
1037
- else command = 'resize_percent' + nw;
1038
- }
1039
- } else if (h === 'auto') {
1040
- if (w === 'auto') {
1041
- command = 'auto';
1042
- } else if (/%$/.test(w)) {
1043
- command = 'resize_percent' + numbers.get(w);
1044
- }
1045
- }
1046
-
1047
- this.selectMenu_resize.open('', '[data-command="' + command + '"]');
1048
- }
1049
-
1050
1469
  function CreateHTML_resizeDot() {
1051
1470
  const html = /*html*/ `
1052
1471
  <div class="se-resize-dot">
@@ -1061,7 +1480,7 @@ function CreateHTML_resizeDot() {
1061
1480
  <div class="se-resize-display"></div>
1062
1481
  </div>`;
1063
1482
 
1064
- return domUtils.createElement('DIV', { class: 'se-controller se-resizing-container', style: 'display: none;' }, html);
1483
+ return dom.utils.createElement('DIV', { class: 'se-controller se-resizing-container', style: 'display: none;' }, html);
1065
1484
  }
1066
1485
 
1067
1486
  function GET_CONTROLLER_BUTTONS(group) {
@@ -1114,6 +1533,11 @@ function GET_CONTROLLER_BUTTONS(group) {
1114
1533
  l = 'edit';
1115
1534
  i = 'edit';
1116
1535
  break;
1536
+ case 'as':
1537
+ c = 'onas';
1538
+ l = 'blockStyle';
1539
+ i = 'as_block';
1540
+ break;
1117
1541
  case 'remove':
1118
1542
  c = 'remove';
1119
1543
  l = 'remove';
@@ -1159,8 +1583,8 @@ function CreateHTML_controller(inst, controls) {
1159
1583
  }
1160
1584
 
1161
1585
  html += /*html*/ `
1162
- <button type="button" data-command="${m.c}" data-value="${m.v}" class="${m.t ? 'se-btn-w-auto ' : ''}se-btn se-tooltip">
1163
- ${icons[m.i] || m.t || m.i}
1586
+ <button type="button" data-command="${m.c}" data-value="${m.v}" class="se-btn se-tooltip">
1587
+ ${icons[m.i] || m.i}
1164
1588
  <span class="se-tooltip-inner"><span class="se-tooltip-text">${lang[m.l] || m.l}</span></span>
1165
1589
  </button>`;
1166
1590
  }
@@ -1168,7 +1592,7 @@ function CreateHTML_controller(inst, controls) {
1168
1592
  }
1169
1593
  }
1170
1594
 
1171
- return domUtils.createElement('DIV', { class: 'se-controller se-controller-resizing' + (!html ? ' se-empty-controller' : '') }, html);
1595
+ return dom.utils.createElement('DIV', { class: 'se-controller se-controller-resizing' + (!html ? ' se-empty-controller' : '') }, html);
1172
1596
  }
1173
1597
 
1174
1598
  export default Figure;