suneditor 2.46.2 → 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.json +64 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/LICENSE.txt +1 -1
  5. package/README.md +174 -805
  6. package/dist/suneditor.min.css +1 -0
  7. package/dist/suneditor.min.js +1 -2
  8. package/package.json +96 -69
  9. package/src/assets/icons/_default.js +194 -0
  10. package/src/assets/suneditor-content.css +646 -0
  11. package/src/assets/suneditor.css +3378 -0
  12. package/src/core/base/eventHandlers/handler_toolbar.js +114 -0
  13. package/src/core/base/eventHandlers/handler_ww_clipboard.js +31 -0
  14. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +69 -0
  15. package/src/core/base/eventHandlers/handler_ww_key_input.js +975 -0
  16. package/src/core/base/eventHandlers/handler_ww_mouse.js +118 -0
  17. package/src/core/base/eventManager.js +1115 -0
  18. package/src/core/base/events.js +320 -0
  19. package/src/core/base/history.js +301 -0
  20. package/src/core/class/char.js +146 -0
  21. package/src/core/class/component.js +627 -0
  22. package/src/core/class/format.js +3255 -0
  23. package/src/core/class/html.js +1621 -0
  24. package/src/core/class/menu.js +260 -0
  25. package/src/core/class/nodeTransform.js +379 -0
  26. package/src/core/class/notice.js +42 -0
  27. package/src/core/class/offset.js +578 -0
  28. package/src/core/class/selection.js +508 -0
  29. package/src/core/class/shortcuts.js +38 -0
  30. package/src/core/class/toolbar.js +440 -0
  31. package/src/core/class/viewer.js +646 -0
  32. package/src/core/editor.js +1593 -0
  33. package/src/core/section/actives.js +107 -0
  34. package/src/core/section/constructor.js +1237 -0
  35. package/src/core/section/context.js +97 -0
  36. package/src/editorInjector/_classes.js +22 -0
  37. package/src/editorInjector/_core.js +28 -0
  38. package/src/editorInjector/index.js +13 -0
  39. package/src/helper/converter.js +313 -0
  40. package/src/helper/domUtils.js +1177 -0
  41. package/src/helper/env.js +250 -0
  42. package/src/helper/index.js +19 -0
  43. package/src/helper/numbers.js +68 -0
  44. package/src/helper/unicode.js +43 -0
  45. package/src/langs/ckb.js +161 -0
  46. package/src/langs/cs.js +161 -0
  47. package/src/langs/da.js +161 -0
  48. package/src/langs/de.js +162 -0
  49. package/src/langs/en.js +199 -0
  50. package/src/langs/es.js +162 -0
  51. package/src/langs/fa.js +159 -0
  52. package/src/langs/fr.js +161 -0
  53. package/src/langs/he.js +162 -0
  54. package/src/{lang → langs}/index.js +0 -2
  55. package/src/langs/it.js +162 -0
  56. package/src/langs/ja.js +162 -0
  57. package/src/langs/ko.js +162 -0
  58. package/src/langs/lv.js +162 -0
  59. package/src/langs/nl.js +162 -0
  60. package/src/langs/pl.js +162 -0
  61. package/src/langs/pt_br.js +162 -0
  62. package/src/langs/ro.js +162 -0
  63. package/src/langs/ru.js +162 -0
  64. package/src/langs/se.js +162 -0
  65. package/src/langs/tr.js +159 -0
  66. package/src/langs/ua.js +162 -0
  67. package/src/langs/ur.js +162 -0
  68. package/src/langs/zh_cn.js +162 -0
  69. package/src/modules/ApiManager.js +168 -0
  70. package/src/modules/ColorPicker.js +302 -0
  71. package/src/modules/Controller.js +315 -0
  72. package/src/modules/Figure.js +1160 -0
  73. package/src/modules/FileBrowser.js +271 -0
  74. package/src/modules/FileManager.js +290 -0
  75. package/src/modules/HueSlider.js +513 -0
  76. package/src/modules/Modal.js +177 -0
  77. package/src/modules/ModalAnchorEditor.js +494 -0
  78. package/src/modules/SelectMenu.js +447 -0
  79. package/src/modules/_DragHandle.js +16 -0
  80. package/src/modules/index.js +14 -0
  81. package/src/plugins/command/blockquote.js +47 -47
  82. package/src/plugins/command/exportPdf.js +168 -0
  83. package/src/plugins/command/fileUpload.js +389 -0
  84. package/src/plugins/command/list_bulleted.js +112 -0
  85. package/src/plugins/command/list_numbered.js +115 -0
  86. package/src/plugins/dropdown/align.js +143 -0
  87. package/src/plugins/dropdown/backgroundColor.js +73 -0
  88. package/src/plugins/dropdown/font.js +113 -0
  89. package/src/plugins/dropdown/fontColor.js +73 -0
  90. package/src/plugins/dropdown/formatBlock.js +141 -0
  91. package/src/plugins/dropdown/hr.js +111 -0
  92. package/src/plugins/dropdown/layout.js +72 -0
  93. package/src/plugins/dropdown/lineHeight.js +114 -0
  94. package/src/plugins/dropdown/list.js +107 -0
  95. package/src/plugins/dropdown/paragraphStyle.js +117 -0
  96. package/src/plugins/dropdown/table.js +2810 -0
  97. package/src/plugins/dropdown/template.js +71 -0
  98. package/src/plugins/dropdown/textStyle.js +137 -0
  99. package/src/plugins/field/mention.js +172 -0
  100. package/src/plugins/fileBrowser/imageGallery.js +76 -59
  101. package/src/plugins/index.js +86 -24
  102. package/src/plugins/input/fontSize.js +357 -0
  103. package/src/plugins/modal/audio.js +510 -0
  104. package/src/plugins/modal/image.js +1062 -0
  105. package/src/plugins/modal/link.js +211 -0
  106. package/src/plugins/modal/math.js +347 -0
  107. package/src/plugins/modal/video.js +870 -0
  108. package/src/suneditor.js +62 -67
  109. package/src/themes/test.css +61 -0
  110. package/typings/CommandPlugin.d.ts +8 -0
  111. package/typings/DialogPlugin.d.ts +20 -0
  112. package/typings/FileBrowserPlugin.d.ts +30 -0
  113. package/typings/Lang.d.ts +124 -0
  114. package/typings/Module.d.ts +15 -0
  115. package/typings/Plugin.d.ts +42 -0
  116. package/typings/SubmenuPlugin.d.ts +8 -0
  117. package/typings/_classes.d.ts +17 -0
  118. package/typings/_colorPicker.d.ts +60 -0
  119. package/typings/_core.d.ts +55 -0
  120. package/typings/align.d.ts +5 -0
  121. package/{src/plugins/dialog → typings}/audio.d.ts +1 -1
  122. package/typings/backgroundColor.d.ts +5 -0
  123. package/{src/plugins/command → typings}/blockquote.d.ts +1 -1
  124. package/typings/char.d.ts +39 -0
  125. package/typings/component.d.ts +38 -0
  126. package/typings/context.d.ts +39 -0
  127. package/typings/converter.d.ts +33 -0
  128. package/typings/dialog.d.ts +28 -0
  129. package/typings/domUtils.d.ts +361 -0
  130. package/typings/editor.d.ts +7 -0
  131. package/typings/editor.ts +542 -0
  132. package/typings/env.d.ts +70 -0
  133. package/typings/eventManager.d.ts +37 -0
  134. package/typings/events.d.ts +262 -0
  135. package/typings/fileBrowser.d.ts +42 -0
  136. package/typings/fileManager.d.ts +67 -0
  137. package/typings/font.d.ts +5 -0
  138. package/typings/fontColor.d.ts +5 -0
  139. package/typings/fontSize.d.ts +5 -0
  140. package/typings/format.d.ts +191 -0
  141. package/typings/formatBlock.d.ts +5 -0
  142. package/typings/history.d.ts +48 -0
  143. package/typings/horizontalRule.d.ts +5 -0
  144. package/{src/plugins/dialog → typings}/image.d.ts +1 -1
  145. package/{src/plugins/fileBrowser → typings}/imageGallery.d.ts +1 -1
  146. package/typings/index.d.ts +21 -0
  147. package/{src/plugins/modules/index.d.ts → typings/index.modules.d.ts} +3 -3
  148. package/typings/index.plugins.d.ts +58 -0
  149. package/typings/lineHeight.d.ts +5 -0
  150. package/{src/plugins/dialog → typings}/link.d.ts +1 -1
  151. package/typings/list.d.ts +5 -0
  152. package/{src/plugins/dialog → typings}/math.d.ts +1 -1
  153. package/typings/mediaContainer.d.ts +25 -0
  154. package/typings/node.d.ts +57 -0
  155. package/typings/notice.d.ts +16 -0
  156. package/typings/numbers.d.ts +29 -0
  157. package/typings/offset.d.ts +24 -0
  158. package/typings/options.d.ts +589 -0
  159. package/typings/paragraphStyle.d.ts +5 -0
  160. package/typings/resizing.d.ts +141 -0
  161. package/typings/selection.d.ts +94 -0
  162. package/typings/shortcuts.d.ts +13 -0
  163. package/typings/suneditor.d.ts +9 -0
  164. package/typings/table.d.ts +5 -0
  165. package/typings/template.d.ts +5 -0
  166. package/typings/textStyle.d.ts +5 -0
  167. package/typings/toolbar.d.ts +32 -0
  168. package/typings/unicode.d.ts +25 -0
  169. package/{src/plugins/dialog → typings}/video.d.ts +1 -1
  170. package/dist/css/suneditor.min.css +0 -1
  171. package/src/assets/css/suneditor-contents.css +0 -562
  172. package/src/assets/css/suneditor.css +0 -566
  173. package/src/assets/defaultIcons.js +0 -103
  174. package/src/lang/Lang.d.ts +0 -144
  175. package/src/lang/ckb.d.ts +0 -5
  176. package/src/lang/ckb.js +0 -188
  177. package/src/lang/cs.d.ts +0 -5
  178. package/src/lang/cs.js +0 -188
  179. package/src/lang/da.d.ts +0 -5
  180. package/src/lang/da.js +0 -191
  181. package/src/lang/de.d.ts +0 -5
  182. package/src/lang/de.js +0 -188
  183. package/src/lang/en.d.ts +0 -5
  184. package/src/lang/en.js +0 -188
  185. package/src/lang/es.d.ts +0 -5
  186. package/src/lang/es.js +0 -188
  187. package/src/lang/fa.d.ts +0 -5
  188. package/src/lang/fa.js +0 -188
  189. package/src/lang/fr.d.ts +0 -5
  190. package/src/lang/fr.js +0 -188
  191. package/src/lang/he.d.ts +0 -5
  192. package/src/lang/he.js +0 -188
  193. package/src/lang/index.d.ts +0 -23
  194. package/src/lang/it.d.ts +0 -5
  195. package/src/lang/it.js +0 -188
  196. package/src/lang/ja.d.ts +0 -5
  197. package/src/lang/ja.js +0 -188
  198. package/src/lang/ko.d.ts +0 -5
  199. package/src/lang/ko.js +0 -188
  200. package/src/lang/lv.d.ts +0 -5
  201. package/src/lang/lv.js +0 -188
  202. package/src/lang/nl.d.ts +0 -5
  203. package/src/lang/nl.js +0 -188
  204. package/src/lang/pl.d.ts +0 -5
  205. package/src/lang/pl.js +0 -188
  206. package/src/lang/pt_br.d.ts +0 -5
  207. package/src/lang/pt_br.js +0 -189
  208. package/src/lang/ro.d.ts +0 -5
  209. package/src/lang/ro.js +0 -188
  210. package/src/lang/ru.d.ts +0 -5
  211. package/src/lang/ru.js +0 -188
  212. package/src/lang/se.d.ts +0 -5
  213. package/src/lang/se.js +0 -191
  214. package/src/lang/tr.d.ts +0 -5
  215. package/src/lang/tr.js +0 -191
  216. package/src/lang/ua.d.ts +0 -5
  217. package/src/lang/ua.js +0 -188
  218. package/src/lang/ur.d.ts +0 -5
  219. package/src/lang/ur.js +0 -188
  220. package/src/lang/zh_cn.d.ts +0 -5
  221. package/src/lang/zh_cn.js +0 -187
  222. package/src/lib/constructor.js +0 -954
  223. package/src/lib/context.d.ts +0 -42
  224. package/src/lib/context.js +0 -71
  225. package/src/lib/core.d.ts +0 -1135
  226. package/src/lib/core.js +0 -9395
  227. package/src/lib/history.d.ts +0 -48
  228. package/src/lib/history.js +0 -219
  229. package/src/lib/util.d.ts +0 -678
  230. package/src/lib/util.js +0 -2131
  231. package/src/options.d.ts +0 -608
  232. package/src/plugins/CommandPlugin.d.ts +0 -8
  233. package/src/plugins/DialogPlugin.d.ts +0 -20
  234. package/src/plugins/FileBrowserPlugin.d.ts +0 -30
  235. package/src/plugins/Module.d.ts +0 -15
  236. package/src/plugins/Plugin.d.ts +0 -42
  237. package/src/plugins/SubmenuPlugin.d.ts +0 -8
  238. package/src/plugins/dialog/audio.js +0 -559
  239. package/src/plugins/dialog/image.js +0 -1126
  240. package/src/plugins/dialog/link.js +0 -223
  241. package/src/plugins/dialog/math.js +0 -295
  242. package/src/plugins/dialog/mention.js +0 -242
  243. package/src/plugins/dialog/video.js +0 -979
  244. package/src/plugins/index.d.ts +0 -79
  245. package/src/plugins/modules/_anchor.js +0 -461
  246. package/src/plugins/modules/_colorPicker.d.ts +0 -60
  247. package/src/plugins/modules/_colorPicker.js +0 -201
  248. package/src/plugins/modules/_notice.d.ts +0 -21
  249. package/src/plugins/modules/_notice.js +0 -72
  250. package/src/plugins/modules/_selectMenu.js +0 -119
  251. package/src/plugins/modules/component.d.ts +0 -25
  252. package/src/plugins/modules/component.js +0 -81
  253. package/src/plugins/modules/dialog.d.ts +0 -28
  254. package/src/plugins/modules/dialog.js +0 -175
  255. package/src/plugins/modules/fileBrowser.d.ts +0 -42
  256. package/src/plugins/modules/fileBrowser.js +0 -374
  257. package/src/plugins/modules/fileManager.d.ts +0 -67
  258. package/src/plugins/modules/fileManager.js +0 -326
  259. package/src/plugins/modules/index.js +0 -9
  260. package/src/plugins/modules/resizing.d.ts +0 -154
  261. package/src/plugins/modules/resizing.js +0 -903
  262. package/src/plugins/submenu/align.d.ts +0 -5
  263. package/src/plugins/submenu/align.js +0 -160
  264. package/src/plugins/submenu/font.d.ts +0 -5
  265. package/src/plugins/submenu/font.js +0 -123
  266. package/src/plugins/submenu/fontColor.d.ts +0 -5
  267. package/src/plugins/submenu/fontColor.js +0 -101
  268. package/src/plugins/submenu/fontSize.d.ts +0 -5
  269. package/src/plugins/submenu/fontSize.js +0 -112
  270. package/src/plugins/submenu/formatBlock.d.ts +0 -5
  271. package/src/plugins/submenu/formatBlock.js +0 -273
  272. package/src/plugins/submenu/hiliteColor.d.ts +0 -5
  273. package/src/plugins/submenu/hiliteColor.js +0 -102
  274. package/src/plugins/submenu/horizontalRule.d.ts +0 -5
  275. package/src/plugins/submenu/horizontalRule.js +0 -98
  276. package/src/plugins/submenu/lineHeight.d.ts +0 -5
  277. package/src/plugins/submenu/lineHeight.js +0 -104
  278. package/src/plugins/submenu/list.d.ts +0 -5
  279. package/src/plugins/submenu/list.js +0 -456
  280. package/src/plugins/submenu/paragraphStyle.d.ts +0 -5
  281. package/src/plugins/submenu/paragraphStyle.js +0 -135
  282. package/src/plugins/submenu/table.d.ts +0 -5
  283. package/src/plugins/submenu/table.js +0 -1431
  284. package/src/plugins/submenu/template.d.ts +0 -5
  285. package/src/plugins/submenu/template.js +0 -72
  286. package/src/plugins/submenu/textStyle.d.ts +0 -5
  287. package/src/plugins/submenu/textStyle.js +0 -167
  288. package/src/suneditor.d.ts +0 -9
  289. package/src/suneditor_build.js +0 -18
  290. /package/{src/plugins/dialog → typings}/mention.d.ts +0 -0
@@ -0,0 +1,1160 @@
1
+ import EditorInjector from '../editorInjector';
2
+ import { Controller, SelectMenu, _DragHandle } from '../modules';
3
+ import { domUtils, numbers, env, converter } from '../helper';
4
+
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' };
7
+ const DIR_DIAGONAL = 'tl|bl|tr|br';
8
+ const DIR_W = 'lw|rw';
9
+ let __resizing_p_wh = false;
10
+ let __resizing_p_ow = false;
11
+ let __resizing_cw = 0;
12
+ let __resizing_sw = 0;
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._floatClassRegExp = '__se__float\\-[a-z]+';
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
+ };
100
+
101
+ /**
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}
106
+ */
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
+
112
+ /**
113
+ * @description Return HTML string of caption(FIGCAPTION) element
114
+ * @param {Element} cover Cover element(FIGURE). "CreateContainer().cover"
115
+ * @returns {Element} caption element
116
+ */
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
+
123
+ /**
124
+ * @description Get the element's container(.se-component) info.
125
+ * @param {Element} element Target element
126
+ * @returns {object} {container, cover, caption}
127
+ */
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
+
138
+ /**
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}}
144
+ */
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;
156
+ }
157
+ }
158
+
159
+ return {
160
+ w: numbers.get(rw, 4),
161
+ h: numbers.get(rh, 4)
162
+ };
163
+ };
164
+
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;
183
+ }
184
+ }
185
+
186
+ return {
187
+ w: w,
188
+ h: h
189
+ };
190
+ };
191
+
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
+ };
201
+
202
+ Figure.prototype = {
203
+ /**
204
+ * @override controller
205
+ */
206
+ close() {
207
+ this.editor._antiBlur = false;
208
+ domUtils.removeClass(this._cover, 'se-figure-selected');
209
+ this.controller.close();
210
+
211
+ if (domUtils.hasClass(this._w.event?.target, 'se-drag-handle|sun-editor-editable')) return;
212
+ this.component._removeDragEvent();
213
+ },
214
+
215
+ open(target, { nonResizing, nonSizeInfo, nonBorder, figureTarget, __fileManagerInfo }) {
216
+ if (!target) {
217
+ console.warn('[SUNEDITOR.modules.Figure.open] The target element is null.');
218
+ return;
219
+ }
220
+
221
+ if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
222
+ this.editor._offCurrentController();
223
+ } else {
224
+ nonBorder = true;
225
+ }
226
+
227
+ const figureInfo = Figure.GetContainer(target);
228
+ if (!figureInfo.container) return { container: null, cover: null };
229
+
230
+ _DragHandle.set('__figureInst', this);
231
+
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());
238
+
239
+ const sizeTarget = figureTarget ? this._cover || this._container || target : target;
240
+ const { w, h, t, l, scrollX, scrollY } = this.offset.getSize(sizeTarget);
241
+
242
+ const dataSize = (target.getAttribute('data-se-size') || '').split(',');
243
+ const ratio = Figure.GetRatio(dataSize[0] || numbers.get(target.style.width, 2) || w, dataSize[1] || numbers.get(target.style.height, 2) || h, this.sizeUnit);
244
+ const targetInfo = {
245
+ container: figureInfo.container,
246
+ cover: figureInfo.cover,
247
+ caption: figureInfo.caption,
248
+ align: this.align,
249
+ ratio: ratio,
250
+ w: w,
251
+ h: h,
252
+ t: t,
253
+ l: l,
254
+ width: dataSize[0] || 'auto',
255
+ height: dataSize[1] || 'auto',
256
+ originWidth: target.naturalWidth || target.offsetWidth,
257
+ originHeight: target.naturalHeight || target.offsetHeight
258
+ };
259
+
260
+ this._width = targetInfo.width;
261
+ this._height = targetInfo.height;
262
+ if (__fileManagerInfo || this.__fileManagerInfo) return targetInfo;
263
+
264
+ const _figure = this.editor.frameContext.get('_figure');
265
+ this.editor._figureContainer = _figure.main;
266
+ _figure.main.style.top = t + 'px';
267
+ _figure.main.style.left = l + 'px';
268
+ _figure.main.style.width = (this.isVertical ? h : w) + 'px';
269
+ _figure.main.style.height = (this.isVertical ? w : h) + 'px';
270
+ _figure.border.style.top = '0px';
271
+ _figure.border.style.left = '0px';
272
+ _figure.border.style.width = (this.isVertical ? h : w) + 'px';
273
+ _figure.border.style.height = (this.isVertical ? w : h) + 'px';
274
+
275
+ this.__offset = { left: l + scrollX, top: t + scrollY };
276
+ this.editor.opendControllers.push({
277
+ position: 'none',
278
+ form: _figure.main,
279
+ target: sizeTarget,
280
+ inst: this,
281
+ notInCarrier: true
282
+ });
283
+
284
+ // percentage active
285
+ const value = /%$/.test(target.style.width) && /%$/.test(figureInfo.container.style.width) ? numbers.get(figureInfo.container.style.width, 0) / 100 + '' : '';
286
+ for (let i = 0, len = this.percentageButtons.length; i < len; i++) {
287
+ if (this.percentageButtons[i].getAttribute('data-value') === value) {
288
+ domUtils.addClass(this.percentageButtons[i], 'active');
289
+ } else {
290
+ domUtils.removeClass(this.percentageButtons[i], 'active');
291
+ }
292
+ }
293
+
294
+ // caption active
295
+ if (this.captionButton) {
296
+ if (figureInfo.caption) {
297
+ domUtils.addClass(this.captionButton, 'active');
298
+ } else {
299
+ domUtils.removeClass(this.captionButton, 'active');
300
+ }
301
+ }
302
+
303
+ _figure.display.style.display = nonSizeInfo ? 'none' : '';
304
+ _figure.border.style.display = nonBorder ? 'none' : '';
305
+ _figure.main.style.display = 'block';
306
+
307
+ if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
308
+ this.editor._visibleControllers(true, true);
309
+ // size
310
+ const size = this.getSize(target);
311
+ domUtils.changeTxt(_figure.display, this.lang[this.align === 'none' ? 'basic' : this.align] + ' (' + size.w + ', ' + size.h + ')');
312
+ this._displayResizeHandles(!nonResizing);
313
+ // selecte
314
+ domUtils.removeClass(this._cover, 'se-figure-over-selected');
315
+ this.controller.open(_figure.main, null, { initMethod: this.__offContainer, isWWTarget: false, addOffset: null });
316
+ this._w.setTimeout(() => _DragHandle.set('__overInfo', false), 0);
317
+ } else {
318
+ domUtils.addClass(this._cover, 'se-figure-over-selected');
319
+ }
320
+
321
+ // set members
322
+ domUtils.addClass(this._cover, 'se-figure-selected');
323
+ this._element_w = this._resize_w = w;
324
+ this._element_h = this._resize_h = h;
325
+ this._element_l = l;
326
+ this._element_t = t;
327
+
328
+ // align button
329
+ this._setAlignIcon();
330
+
331
+ // drag
332
+ if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT || domUtils.hasClass(figureInfo.container, 'se-input-component')) {
333
+ this._setDragEvent(_figure.main);
334
+ }
335
+
336
+ return targetInfo;
337
+ },
338
+
339
+ controllerHide() {
340
+ this.controller.hide();
341
+ },
342
+
343
+ controllerShow() {
344
+ this.controller.show();
345
+ },
346
+
347
+ controllerOpen(target, args) {
348
+ this._element = target;
349
+ this.controller.open(target, null, args);
350
+ },
351
+
352
+ setSize(w, h) {
353
+ if (/%$/.test(w)) {
354
+ this._setPercentSize(w, h);
355
+ } else if ((!w || w === 'auto') && (!h || h === 'auto')) {
356
+ if (this.autoRatio) this._setPercentSize(100, this.autoRatio.default || this.autoRatio.current);
357
+ else this._setAutoSize();
358
+ } else {
359
+ this._applySize(w, h, '');
360
+ }
361
+ },
362
+
363
+ /**
364
+ * @description Gets the Figure size
365
+ * @param {Element|null} target
366
+ * @returns {{w: string, h: string}}
367
+ */
368
+ getSize(target) {
369
+ if (!target) target = this._element;
370
+ if (!target) return { w: '', h: '' };
371
+
372
+ const figure = Figure.GetContainer(target);
373
+ if (!figure.container) {
374
+ return {
375
+ w: '',
376
+ h: target.style.height
377
+ };
378
+ }
379
+
380
+ const w = !/%$/.test(target.style.width) ? target.style.width : ((figure.container && numbers.get(figure.container.style.width, 2)) || 100) + '%';
381
+ const h =
382
+ numbers.get(figure.cover.style.paddingBottom, 0) > 0 && !this.isVertical
383
+ ? figure.cover.style.height
384
+ : !/%$/.test(target.style.height) || !/%$/.test(target.style.width)
385
+ ? target.style.height
386
+ : ((figure.container && numbers.get(figure.container.style.height, 2)) || 100) + '%';
387
+ return {
388
+ w: w || 'auto',
389
+ h: h || 'auto'
390
+ };
391
+ },
392
+
393
+ /**
394
+ * @description Align the container.
395
+ * @param {Element|null} target Target element
396
+ * @param {"none"|"left"|"center"|"right"} align
397
+ */
398
+ setAlign(target, align) {
399
+ if (!target) target = this._element;
400
+ align = align || 'none';
401
+
402
+ const figure = Figure.GetContainer(target);
403
+ const container = figure.container;
404
+
405
+ const cover = figure.cover;
406
+ if (/%$/.test(target.style.width) && align === 'center' && !this.component.isInline(container)) {
407
+ container.style.minWidth = '100%';
408
+ cover.style.width = container.style.width;
409
+ } else {
410
+ container.style.minWidth = '';
411
+ cover.style.width = this.isVertical ? target.style.height || target.offsetHeight : !target.style.width || target.style.width === 'auto' ? '' : target.style.width || '100%';
412
+ }
413
+
414
+ if (!domUtils.hasClass(container, '__se__float-' + align)) {
415
+ domUtils.removeClass(container, this._floatClassRegExp);
416
+ domUtils.addClass(container, '__se__float-' + align);
417
+ }
418
+
419
+ this._setAlignIcon();
420
+ },
421
+
422
+ /**
423
+ * @override controller
424
+ * @param {Element} target Target button element
425
+ * @returns
426
+ */
427
+ controllerAction(target) {
428
+ const command = target.getAttribute('data-command');
429
+ const value = target.getAttribute('data-value');
430
+ const element = this._element;
431
+ if (/^(onalign|onresize)$/.test(command)) return;
432
+
433
+ switch (command) {
434
+ case 'mirror': {
435
+ const info = GetRotateValue(element);
436
+ let x = info.x;
437
+ let y = info.y;
438
+
439
+ if ((value === 'h' && !this.isVertical) || (value === 'v' && this.isVertical)) {
440
+ y = y ? '' : '180';
441
+ } else {
442
+ x = x ? '' : '180';
443
+ }
444
+
445
+ this._setRotate(element, info.r, x, y);
446
+ break;
447
+ }
448
+ case 'rotate':
449
+ this.setTransform(element, null, null, value);
450
+ break;
451
+ case 'caption':
452
+ if (!this._caption) {
453
+ const caption = Figure.CreateCaption(this._cover, this.lang.caption);
454
+ const captionText = domUtils.getEdgeChild(caption, (current) => current.nodeType === 3);
455
+
456
+ if (!captionText) {
457
+ caption.focus();
458
+ } else {
459
+ this.selection.setRange(captionText, 0, captionText, captionText.textContent.length);
460
+ }
461
+
462
+ this.controller.close();
463
+ } else {
464
+ domUtils.removeItem(this._caption);
465
+ this._w.setTimeout(this.component.select.bind(this.component, element, this.kind), 0);
466
+ }
467
+
468
+ this._caption = !this._caption;
469
+ if (/\d+/.test(element.style.height) || (this.isVertical && this._caption)) {
470
+ if (/%$/.test(element.style.width) || /auto/.test(element.style.height)) {
471
+ this.deleteTransform();
472
+ } else {
473
+ this.setTransform(element, element.style.width, element.style.height, 0);
474
+ }
475
+ }
476
+ break;
477
+ case 'revert':
478
+ this._setRevert();
479
+ break;
480
+ case 'edit':
481
+ this.inst.edit(element);
482
+ break;
483
+ case 'remove':
484
+ this.inst.destroy(element);
485
+ this.controller.close();
486
+ break;
487
+ }
488
+
489
+ if (/^__c__/.test(command)) {
490
+ this._action[command](element, value, target);
491
+ return;
492
+ }
493
+
494
+ if (/^edit$/.test(command)) return;
495
+
496
+ this.history.push(false);
497
+ if (!/^remove|caption$/.test(command)) {
498
+ this.component.select(element, this.kind, false);
499
+ }
500
+ },
501
+
502
+ /**
503
+ * @description Initialize the transform style (rotation) of the element.
504
+ * @param {Element|null} element Target element
505
+ */
506
+ deleteTransform(element) {
507
+ if (!element) element = this._element;
508
+
509
+ const size = (element.getAttribute('data-se-size') || '').split(',');
510
+ this.isVertical = false;
511
+
512
+ element.style.maxWidth = '';
513
+ element.style.transform = '';
514
+ element.style.transformOrigin = '';
515
+
516
+ this._deleteCaptionPosition(element);
517
+ this._applySize(size[0] || 'auto', size[1] || '', '');
518
+ },
519
+
520
+ /**
521
+ * @description Set the transform style (rotation) of the element.
522
+ * @param {Element} element Target element
523
+ * @param {Number|null} width Element's width size
524
+ * @param {Number|null} height Element's height size
525
+ */
526
+ setTransform(element, width, height, deg) {
527
+ try {
528
+ this.__preventSizechange = true;
529
+ const info = GetRotateValue(element);
530
+ const slope = info.r + (deg || 0) * 1;
531
+ deg = Math.abs(slope) >= 360 ? 0 : slope;
532
+ const isVertical = (this.isVertical = /^(90|270)$/.test(Math.abs(deg).toString()));
533
+
534
+ width = numbers.get(width, 0);
535
+ height = numbers.get(height, 0);
536
+
537
+ const dataSize = (element.getAttribute('data-se-size') || 'auto,auto').split(',');
538
+ let transOrigin = '';
539
+ if (/auto|%$/.test(dataSize[0]) && !isVertical) {
540
+ if (dataSize[0] === 'auto' && dataSize[1] === 'auto') {
541
+ this._setAutoSize();
542
+ } else {
543
+ this._setPercentSize(dataSize[0], dataSize[1]);
544
+ }
545
+ } else {
546
+ const figureInfo = Figure.GetContainer(element);
547
+ const offsetW = width || element.offsetWidth;
548
+ const offsetH = height || element.offsetHeight;
549
+ const w = (isVertical ? offsetH : offsetW) + 'px';
550
+ const h = (isVertical ? offsetW : offsetH) + 'px';
551
+
552
+ this._deletePercentSize();
553
+ this._applySize(offsetW + 'px', offsetH + 'px', '');
554
+
555
+ figureInfo.cover.style.width = w;
556
+ figureInfo.cover.style.height = figureInfo.caption ? '' : h;
557
+
558
+ if (isVertical) {
559
+ const transW = offsetW / 2 + 'px ' + offsetW / 2 + 'px 0';
560
+ const transH = offsetH / 2 + 'px ' + offsetH / 2 + 'px 0';
561
+ transOrigin = deg === 90 || deg === -270 ? transH : transW;
562
+ }
563
+ }
564
+
565
+ element.style.transformOrigin = transOrigin;
566
+ this._setRotate(element, deg, info.x, info.y);
567
+
568
+ if (isVertical) element.style.maxWidth = 'none';
569
+ else element.style.maxWidth = '';
570
+
571
+ this._setCaptionPosition(element);
572
+ } finally {
573
+ this.__preventSizechange = false;
574
+ }
575
+ },
576
+
577
+ _setRotate(element, r, x, y) {
578
+ let width = (element.offsetWidth - element.offsetHeight) * (/^-/.test(r) ? 1 : -1);
579
+ let translate = '';
580
+
581
+ if (/[1-9]/.test(r) && (x || y)) {
582
+ translate = x ? 'Y' : 'X';
583
+
584
+ switch (r + '') {
585
+ case '90':
586
+ translate = x && y ? 'X' : y ? translate : '';
587
+ break;
588
+ case '270':
589
+ width *= -1;
590
+ translate = x && y ? 'Y' : x ? translate : '';
591
+ break;
592
+ case '-90':
593
+ translate = x && y ? 'Y' : x ? translate : '';
594
+ break;
595
+ case '-270':
596
+ width *= -1;
597
+ translate = x && y ? 'X' : y ? translate : '';
598
+ break;
599
+ default:
600
+ translate = '';
601
+ }
602
+ }
603
+
604
+ if (r % 180 === 0) {
605
+ element.style.maxWidth = '';
606
+ }
607
+
608
+ element.style.transform = 'rotate(' + r + 'deg)' + (x ? ' rotateX(' + x + 'deg)' : '') + (y ? ' rotateY(' + y + 'deg)' : '') + (translate ? ' translate' + translate + '(' + width + 'px)' : '');
609
+ },
610
+
611
+ _applySize(w, h, direction) {
612
+ const onlyW = /^(rw|lw)$/.test(direction) && /\d+/.test(this._element.style.height);
613
+ const onlyH = /^(th|bh)$/.test(direction) && /\d+/.test(this._element.style.width);
614
+ h = h || (this.autoRatio ? this.autoRatio.current || this.autoRatio.default : h);
615
+ w = numbers.is(w) ? w + this.sizeUnit : w;
616
+
617
+ if (!/%$/.test(w) && !/%$/.test(h) && !onlyW && !onlyH) this._deletePercentSize();
618
+
619
+ const sizeTarget = this._cover || this._element;
620
+
621
+ if (this.autoRatio) this._cover.style.width = w;
622
+ if (!onlyH) {
623
+ sizeTarget.style.width = this._element.style.width = w;
624
+ }
625
+ if (!onlyW) {
626
+ h = numbers.is(h) ? h + this.sizeUnit : h;
627
+ sizeTarget.style.height = this._element.style.height = this.autoRatio && !this.isVertical ? '100%' : h;
628
+ if (this.autoRatio) {
629
+ this._cover.style.paddingBottom = h;
630
+ this._cover.style.height = h;
631
+ }
632
+ }
633
+
634
+ if (this.align === 'center') this.setAlign(this._element, this.align);
635
+
636
+ // save current size
637
+ this._saveCurrentSize();
638
+ },
639
+
640
+ _setAutoSize() {
641
+ if (this._caption) this._caption.style.marginTop = '';
642
+ this.deleteTransform();
643
+ this._deletePercentSize();
644
+
645
+ if (this.autoRatio) {
646
+ this._setPercentSize('100%', this.autoRatio.current || this.autoRatio.default);
647
+ } else {
648
+ this._element.style.maxWidth = '';
649
+ this._element.style.width = '';
650
+ this._element.style.height = '';
651
+ this._cover.style.width = '';
652
+ this._cover.style.height = '';
653
+ }
654
+
655
+ this.setAlign(this._element, this.align);
656
+
657
+ // save current size
658
+ this._saveCurrentSize();
659
+ },
660
+
661
+ _setPercentSize(w, h) {
662
+ if (!h) h = this.autoRatio ? (/%$/.test(this.autoRatio.current) ? this.autoRatio.current : this.autoRatio.default) : h;
663
+ 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 : '');
664
+
665
+ const heightPercentage = /%$/.test(h);
666
+ this._container.style.width = numbers.is(w) ? w + '%' : w;
667
+ this._container.style.height = '';
668
+ this._cover.style.width = '100%';
669
+ this._cover.style.height = h;
670
+ this._element.style.width = '100%';
671
+ this._element.style.maxWidth = '';
672
+ this._element.style.height = this.autoRatio ? '100%' : heightPercentage ? '' : h;
673
+
674
+ if (this.autoRatio) this._cover.style.paddingBottom = h;
675
+ if (this.align === 'center') this.setAlign(this._element, this.align);
676
+
677
+ this._setCaptionPosition(this._element);
678
+
679
+ // save current size
680
+ this._saveCurrentSize();
681
+ },
682
+
683
+ _deletePercentSize() {
684
+ this._cover.style.width = '';
685
+ this._cover.style.height = '';
686
+ this._container.style.width = '';
687
+ this._container.style.height = '';
688
+
689
+ domUtils.removeClass(this._container, this._floatClassRegExp);
690
+ domUtils.addClass(this._container, '__se__float-' + this.align);
691
+
692
+ if (this.align === 'center') this.setAlign(this._element, this.align);
693
+ },
694
+
695
+ _setRevert() {
696
+ this.setSize(this.__revertSize.w, this.__revertSize.h);
697
+ },
698
+
699
+ _setAlignIcon() {
700
+ if (!this.alignButton) return;
701
+ domUtils.changeElement(this.alignButton.firstElementChild, this._alignIcons[this.align]);
702
+ },
703
+
704
+ _saveCurrentSize() {
705
+ if (this.__preventSizechange) return;
706
+
707
+ const dataSize = (this._element.getAttribute('data-se-size') || ',').split(',');
708
+ this.__revertSize.w = dataSize[0];
709
+ this.__revertSize.h = dataSize[1];
710
+
711
+ const size = this.getSize(this._element);
712
+ // add too width, height attribute
713
+ this._element.setAttribute('width', size.w.replace('px', ''));
714
+ this._element.setAttribute('height', size.h.replace('px', ''));
715
+ this._element.setAttribute('data-se-size', size.w + ',' + size.h);
716
+ if (this.autoRatio) {
717
+ this.autoRatio.current = /%$/.test(size.h) ? size.h : '';
718
+ }
719
+ },
720
+
721
+ _setCaptionPosition(element) {
722
+ const figcaption = domUtils.getEdgeChild(domUtils.getParentElement(element, 'FIGURE'), 'FIGCAPTION');
723
+ if (figcaption) {
724
+ figcaption.style.marginTop = (this.isVertical ? element.offsetWidth - element.offsetHeight : 0) + 'px';
725
+ }
726
+ },
727
+
728
+ _deleteCaptionPosition(element) {
729
+ const figcaption = domUtils.getEdgeChild(domUtils.getParentElement(element, 'FIGURE'), 'FIGCAPTION');
730
+ if (figcaption) {
731
+ figcaption.style.marginTop = '';
732
+ }
733
+ },
734
+
735
+ _displayResizeHandles(display) {
736
+ display = !display ? 'none' : 'flex';
737
+ this.controller.form.style.display = display;
738
+
739
+ const _figure = this.editor.frameContext.get('_figure');
740
+ const resizeHandles = _figure.handles;
741
+ for (let i = 0, len = resizeHandles.length; i < len; i++) {
742
+ resizeHandles[i].style.display = display;
743
+ }
744
+
745
+ if (display === 'none') {
746
+ domUtils.addClass(_figure.main, 'se-resize-ing');
747
+ this.__onResizeESCEvent = this.eventManager.addGlobalEvent('keydown', this.__containerResizingESC);
748
+ } else {
749
+ domUtils.removeClass(_figure.main, 'se-resize-ing');
750
+ }
751
+ },
752
+
753
+ _offResizeEvent() {
754
+ this.component._removeDragEvent();
755
+ this.eventManager.removeGlobalEvent(this.__onContainerEvent);
756
+ this.eventManager.removeGlobalEvent(this.__offContainerEvent);
757
+ this.eventManager.removeGlobalEvent(this.__onResizeESCEvent);
758
+
759
+ this._displayResizeHandles(true);
760
+ this.editor._offCurrentController();
761
+ this.editor.disableBackWrapper();
762
+ },
763
+
764
+ _setDragEvent(figureMain) {
765
+ const dragHandle = this.editor.frameContext.get('wrapper').querySelector('.se-drag-handle');
766
+ domUtils.removeClass(dragHandle, 'se-drag-handle-full');
767
+
768
+ dragHandle.style.opacity = '';
769
+ dragHandle.style.width = '';
770
+ dragHandle.style.height = '';
771
+
772
+ _DragHandle.set('__dragHandler', dragHandle);
773
+ _DragHandle.set('__dragContainer', this._container);
774
+ _DragHandle.set('__dragCover', this._cover);
775
+ _DragHandle.set('__dragMove', OnScrollDragHandler.bind(this, dragHandle, figureMain));
776
+
777
+ _DragHandle.get('__dragMove')();
778
+
779
+ dragHandle.style.display = 'block';
780
+ },
781
+
782
+ _retainFigureFormat(container, originEl, anchorCover) {
783
+ let existElement = this.format.isBlock(originEl.parentNode) || domUtils.isWysiwygFrame(originEl.parentNode) ? originEl : domUtils.isAnchor(originEl.parentNode) ? originEl.parentNode : this.format.getLine(originEl) || originEl;
784
+
785
+ if (domUtils.getParentElement(originEl, domUtils.isExcludeFormat)) {
786
+ existElement = anchorCover && anchorCover !== originEl ? anchorCover : originEl;
787
+ existElement.parentNode.replaceChild(container, existElement);
788
+ } else if (domUtils.isListCell(existElement)) {
789
+ const refer = domUtils.getParentElement(originEl, (current) => current.parentNode === existElement);
790
+ existElement.insertBefore(container, refer);
791
+ domUtils.removeItem(originEl);
792
+ this.nodeTransform.removeEmptyNode(refer, null, true);
793
+ } else if (this.format.isLine(existElement)) {
794
+ const refer = domUtils.getParentElement(originEl, (current) => current.parentNode === existElement);
795
+ existElement = this.nodeTransform.split(existElement, refer);
796
+ existElement.parentNode.insertBefore(container, existElement);
797
+ domUtils.removeItem(originEl);
798
+ this.nodeTransform.removeEmptyNode(existElement, null, true);
799
+ } else {
800
+ if (this.format.isLineOnly(existElement.parentNode)) {
801
+ const formats = existElement.parentNode;
802
+ formats.parentNode.insertBefore(container, existElement.previousSibling ? formats.nextElementSibling : formats);
803
+ if (this.fileManager.__updateTags.map((current) => existElement.contains(current)).length === 0) domUtils.removeItem(existElement);
804
+ } else {
805
+ existElement = domUtils.isFigure(existElement.parentNode) ? domUtils.getParentElement(existElement.parentNode, Figure.__is) : existElement;
806
+ existElement.parentNode.replaceChild(container, existElement);
807
+ }
808
+ }
809
+ },
810
+
811
+ constructor: Figure
812
+ };
813
+
814
+ function OnScrollDragHandler(dragHandle, figureMain) {
815
+ const offset = this.offset.get(figureMain);
816
+ dragHandle.style.display = 'block';
817
+ dragHandle.style.left = offset.left + (this.options.get('_rtl') ? dragHandle.offsetWidth : figureMain.offsetWidth - dragHandle.offsetWidth * 1.5) + 'px';
818
+ dragHandle.style.top = offset.top - dragHandle.offsetHeight + 'px';
819
+ }
820
+
821
+ function GetRotateValue(element) {
822
+ const transform = element.style.transform;
823
+ if (!transform) return { r: 0, x: '', y: '' };
824
+ return {
825
+ r: ((transform.match(/rotate\(([-0-9]+)deg\)/) || [])[1] || 0) * 1,
826
+ x: (transform.match(/rotateX\(([-0-9]+)deg\)/) || [])[1] || '',
827
+ y: (transform.match(/rotateY\(([-0-9]+)deg\)/) || [])[1] || ''
828
+ };
829
+ }
830
+
831
+ function OnResizeContainer(e) {
832
+ e.stopPropagation();
833
+ e.preventDefault();
834
+
835
+ const inst = _DragHandle.get('__figureInst');
836
+ const direction = (inst._resize_direction = e.target.classList[0]);
837
+ inst._resizeClientX = e.clientX;
838
+ inst._resizeClientY = e.clientY;
839
+ inst.editor.frameContext.get('_figure').main.style.float = /l/.test(direction) ? 'right' : /r/.test(direction) ? 'left' : 'none';
840
+ this.editor.enableBackWrapper(DIRECTION_CURSOR_MAP[direction]);
841
+
842
+ const { w, h } = this.getSize(inst._element);
843
+ __resizing_p_wh = __resizing_p_ow = false;
844
+ __resizing_cw = __resizing_sw = 0;
845
+ if (!this.isVertical) {
846
+ const pw = !w || /auto|%$/.test(w);
847
+ const ph = !h || /auto|%$/.test(h);
848
+ if (DIR_DIAGONAL.includes(direction) && pw && ph) {
849
+ __resizing_p_wh = true;
850
+ } else if (DIR_W.includes(direction) && pw) {
851
+ __resizing_p_ow = true;
852
+ }
853
+
854
+ if (__resizing_p_wh || __resizing_p_ow) {
855
+ const sizeTarget = inst._cover || inst._element;
856
+ __resizing_sw = sizeTarget.offsetWidth;
857
+ __resizing_cw = converter.getWidthInPercentage(sizeTarget, this.editor.frameContext.get('wysiwygFrame')) / 100;
858
+ }
859
+ }
860
+
861
+ inst.__onContainerEvent = inst.eventManager.addGlobalEvent('mousemove', inst.__containerResizing);
862
+ inst.__offContainerEvent = inst.eventManager.addGlobalEvent('mouseup', inst.__containerResizingOff);
863
+ inst._displayResizeHandles(false);
864
+ }
865
+
866
+ function ContainerResizing(e) {
867
+ const direction = this._resize_direction;
868
+ const clientX = e.clientX;
869
+ const clientY = e.clientY;
870
+
871
+ let resultW = this._element_w;
872
+ let resultH = this._element_h;
873
+
874
+ const w = resultW + (/r/.test(direction) ? clientX - this._resizeClientX : this._resizeClientX - clientX);
875
+ const h = resultH + (/b/.test(direction) ? clientY - this._resizeClientY : this._resizeClientY - clientY);
876
+ const wh = (resultH / resultW) * w;
877
+ const resizeBorder = this.editor.frameContext.get('_figure').border;
878
+
879
+ if (/t/.test(direction)) resizeBorder.style.top = resultH - (/h/.test(direction) ? h : wh) + 'px';
880
+ if (/l/.test(direction)) resizeBorder.style.left = resultW - w + 'px';
881
+
882
+ if (/r|l/.test(direction)) {
883
+ resizeBorder.style.width = w + 'px';
884
+ resultW = w;
885
+ }
886
+
887
+ if (/^(t|b)[^h]$/.test(direction)) {
888
+ resizeBorder.style.height = wh + 'px';
889
+ resultH = wh;
890
+ } else if (/^(t|b)h$/.test(direction)) {
891
+ resizeBorder.style.height = h + 'px';
892
+ resultH = h;
893
+ }
894
+
895
+ this._resize_w = /h$/.test(direction) ? this._width : Math.round(resultW);
896
+ this._resize_h = /w$/.test(direction) ? this._height : Math.round(resultH);
897
+ const rw = __resizing_cw ? (this._resize_w / __resizing_sw) * __resizing_cw * 100 : this._resize_w;
898
+ domUtils.changeTxt(this.editor.frameContext.get('_figure').display, __resizing_cw ? numbers.get(rw > 100 ? 100 : rw, 2).toFixed(2) + '%' : rw + ' x ' + this._resize_h);
899
+ }
900
+
901
+ function ContainerResizingOff() {
902
+ this._offResizeEvent();
903
+
904
+ // set size
905
+ let w = this.isVertical ? this._resize_h : this._resize_w;
906
+ let h = this.isVertical ? this._resize_w : this._resize_h;
907
+ w = Math.round(w) || w;
908
+ h = Math.round(h) || h;
909
+
910
+ if (!this.isVertical && !/%$/.test(w)) {
911
+ const limit =
912
+ this.editor.frameContext.get('wysiwygFrame').clientWidth -
913
+ numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-left')) +
914
+ numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-right')) -
915
+ 2;
916
+ if (numbers.get(w, 0) > limit) {
917
+ h = Math.round((h / w) * limit);
918
+ w = limit;
919
+ }
920
+ }
921
+
922
+ if (__resizing_p_wh || __resizing_p_ow) {
923
+ const sizeTarget = this._cover || this._element;
924
+ w = (w / sizeTarget.offsetWidth) * __resizing_cw * 100;
925
+ w = numbers.get(w > 100 ? 100 : w, 2) + '%';
926
+ this._setPercentSize(w, __resizing_p_ow ? this.getSize(this._element).h : '');
927
+ } else {
928
+ this._applySize(w, h, this._resize_direction);
929
+ if (this.isVertical) this.setTransform(this._element, w, h, 0);
930
+ }
931
+
932
+ this.history.push(false);
933
+ this.component.select(this._element, this.kind, false);
934
+ }
935
+
936
+ function ContainerResizingESC(e) {
937
+ if (!/^27$/.test(e.keyCode)) return;
938
+ this._offResizeEvent();
939
+ this.component.select(this._element, this.kind, false);
940
+ }
941
+
942
+ function SetMenuAlign(value) {
943
+ this.setAlign(this._element, value);
944
+ this.selectMenu_align.close();
945
+ this.component.select(this._element, this.kind, false);
946
+ }
947
+
948
+ function SetResize(value) {
949
+ if (value === 'auto') {
950
+ this.deleteTransform();
951
+ this._setAutoSize();
952
+ } else {
953
+ let dataY = this.getSize(this._element).h;
954
+ if (this.isVertical) {
955
+ const dataSize = (this._element.getAttribute('data-se-size') || ',').split(',');
956
+ if (dataSize[1]) dataY = dataSize[1];
957
+ }
958
+
959
+ this.deleteTransform();
960
+ this._setPercentSize(value * 1, numbers.get(dataY, 0) === null || !/%$/.test(dataY) ? '' : dataY);
961
+ }
962
+
963
+ this.selectMenu_resize.close();
964
+ this.component.select(this._element, this.kind, false);
965
+ }
966
+
967
+ function CreateAlign(inst, button) {
968
+ if (!button) return null;
969
+
970
+ const icons = [inst._alignIcons.none, inst._alignIcons.left, inst._alignIcons.center, inst._alignIcons.right];
971
+ const langs = [inst.lang.basic, inst.lang.left, inst.lang.center, inst.lang.right];
972
+ const commands = ['none', 'left', 'center', 'right'];
973
+ const html = [];
974
+ const items = [];
975
+ for (let i = 0; i < commands.length; i++) {
976
+ html.push(/*html*/ `
977
+ <button type="button" class="se-btn-list se-tooltip" data-command="${commands[i]}">
978
+ ${icons[i]}
979
+ <span class="se-tooltip-inner">
980
+ <span class="se-tooltip-text">${langs[i]}</span>
981
+ </span>
982
+ </button>`);
983
+ items.push(commands[i]);
984
+ }
985
+
986
+ return { html: html, items: items };
987
+ }
988
+
989
+ function CreateResize(editor, button) {
990
+ if (!button) return null;
991
+
992
+ const items = button.getAttribute('data-value').split(',');
993
+ const html = [];
994
+ for (let i = 0, n, c, v, l; i < items.length; i++) {
995
+ v = items[i];
996
+ n = numbers.is(v);
997
+ c = n ? 'resize_percent' + v : 'auto';
998
+ l = n ? v + '%' : editor.lang.autoSize;
999
+ html.push('<button type="button" class="se-btn-list" data-command="' + c + '" data-value="' + v + '"><span>' + l + '</span></button>');
1000
+ }
1001
+
1002
+ return { html: html, items: items };
1003
+ }
1004
+
1005
+ function OffFigureContainer() {
1006
+ this.editor.frameContext.get('_figure').main.style.display = 'none';
1007
+ this.editor._figureContainer = null;
1008
+ }
1009
+
1010
+ function OnClick_alignButton() {
1011
+ this.selectMenu_align.open('', '[data-command="' + this.align + '"]');
1012
+ }
1013
+
1014
+ function OnClick_resizeButton() {
1015
+ const size = this.getSize(this._element);
1016
+ const w = size.w;
1017
+ const h = size.h;
1018
+ let command = '';
1019
+ if (this.autoRatio) {
1020
+ if (h === this.autoRatio.default && /%$/.test(w)) {
1021
+ const nw = numbers.get(w);
1022
+ if (nw === 100) command = 'auto';
1023
+ else command = 'resize_percent' + nw;
1024
+ }
1025
+ } else if (h === 'auto') {
1026
+ if (w === 'auto') {
1027
+ command = 'auto';
1028
+ } else if (/%$/.test(w)) {
1029
+ command = 'resize_percent' + numbers.get(w);
1030
+ }
1031
+ }
1032
+
1033
+ this.selectMenu_resize.open('', '[data-command="' + command + '"]');
1034
+ }
1035
+
1036
+ function CreateHTML_resizeDot() {
1037
+ const html = /*html*/ `
1038
+ <div class="se-resize-dot">
1039
+ <span class="tl"></span>
1040
+ <span class="tr"></span>
1041
+ <span class="bl"></span>
1042
+ <span class="br"></span>
1043
+ <span class="lw"></span>
1044
+ <span class="th"></span>
1045
+ <span class="rw"></span>
1046
+ <span class="bh"></span>
1047
+ <div class="se-resize-display"></div>
1048
+ </div>`;
1049
+
1050
+ return domUtils.createElement('DIV', { class: 'se-controller se-resizing-container', style: 'display: none;' }, html);
1051
+ }
1052
+
1053
+ function GET_CONTROLLER_BUTTONS(group) {
1054
+ const g = group.split('_');
1055
+ const command = g[0];
1056
+ const value = g[1];
1057
+ let c, v, l, t, i;
1058
+
1059
+ switch (command) {
1060
+ case 'resize':
1061
+ c = 'onresize';
1062
+ v = value;
1063
+ l = 'resize';
1064
+ i = 'resize';
1065
+ break;
1066
+ case 'auto':
1067
+ c = 'auto';
1068
+ l = 'autoSize';
1069
+ i = 'auto_size';
1070
+ break;
1071
+ case 'rotate':
1072
+ c = 'rotate';
1073
+ v = value === 'l' ? -90 : value === 'r' ? 90 : numbers.get(value);
1074
+ l = v < 0 ? 'rotateLeft' : 'rotateRight';
1075
+ i = v < 0 ? 'rotate_left' : 'rotate_right';
1076
+ break;
1077
+ case 'mirror':
1078
+ c = 'mirror';
1079
+ v = value;
1080
+ l = value === 'h' ? 'mirrorHorizontal' : 'mirrorVertical';
1081
+ i = value === 'h' ? 'mirror_horizontal' : 'mirror_vertical';
1082
+ break;
1083
+ case 'align':
1084
+ c = 'onalign';
1085
+ l = 'align';
1086
+ i = 'align_justify';
1087
+ break;
1088
+ case 'caption':
1089
+ c = 'caption';
1090
+ l = 'caption';
1091
+ i = 'caption';
1092
+ break;
1093
+ case 'revert':
1094
+ c = 'revert';
1095
+ l = 'revert';
1096
+ i = 'revert';
1097
+ break;
1098
+ case 'edit':
1099
+ c = 'edit';
1100
+ l = 'edit';
1101
+ i = 'edit';
1102
+ break;
1103
+ case 'remove':
1104
+ c = 'remove';
1105
+ l = 'remove';
1106
+ i = 'delete';
1107
+ break;
1108
+ }
1109
+
1110
+ if (!c) return null;
1111
+
1112
+ return {
1113
+ c: c,
1114
+ v: v,
1115
+ l: l,
1116
+ t: t,
1117
+ i: i
1118
+ };
1119
+ }
1120
+
1121
+ function CreateHTML_controller(inst, controls) {
1122
+ let html = null;
1123
+
1124
+ if (controls?.length > 0) {
1125
+ const { lang, icons } = inst;
1126
+ html = '<div class="se-arrow se-arrow-up"></div>';
1127
+ for (let i = 0, group; i < controls.length; i++) {
1128
+ group = controls[i];
1129
+ html += '<div class="se-btn-group">';
1130
+ for (let j = 0, len = group.length, m; j < len; j++) {
1131
+ m = group[j];
1132
+
1133
+ if (typeof m?.action === 'function') {
1134
+ const g = m;
1135
+ m = {
1136
+ c: `__c__${g.command}`,
1137
+ v: g.value || '',
1138
+ l: g.title,
1139
+ i: g.icon
1140
+ };
1141
+ inst._action[m.c] = g.action;
1142
+ } else {
1143
+ m = GET_CONTROLLER_BUTTONS(m);
1144
+ if (!m) continue;
1145
+ }
1146
+
1147
+ html += /*html*/ `
1148
+ <button type="button" data-command="${m.c}" data-value="${m.v}" class="${m.t ? 'se-btn-w-auto ' : ''}se-btn se-tooltip">
1149
+ ${icons[m.i] || m.t || m.i}
1150
+ <span class="se-tooltip-inner"><span class="se-tooltip-text">${lang[m.l] || m.l}</span></span>
1151
+ </button>`;
1152
+ }
1153
+ html += '</div>';
1154
+ }
1155
+ }
1156
+
1157
+ return domUtils.createElement('DIV', { class: 'se-controller se-controller-resizing' + (!html ? ' se-empty-controller' : '') }, html);
1158
+ }
1159
+
1160
+ export default Figure;