suneditor 3.0.0-beta.3 → 3.0.0-beta.30

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 (241) hide show
  1. package/CONTRIBUTING.md +8 -8
  2. package/README.md +44 -49
  3. package/dist/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +1 -1
  5. package/package.json +95 -53
  6. package/src/assets/design/color.css +2 -2
  7. package/src/assets/design/size.css +2 -0
  8. package/src/assets/icons/defaultIcons.js +16 -1
  9. package/src/assets/suneditor-contents.css +9 -8
  10. package/src/assets/suneditor.css +29 -26
  11. package/src/core/{section → base}/actives.js +20 -12
  12. package/src/core/base/history.js +4 -4
  13. package/src/core/class/char.js +10 -10
  14. package/src/core/class/component.js +146 -57
  15. package/src/core/class/format.js +94 -2458
  16. package/src/core/class/html.js +187 -129
  17. package/src/core/class/inline.js +1853 -0
  18. package/src/core/class/listFormat.js +582 -0
  19. package/src/core/class/menu.js +14 -3
  20. package/src/core/class/nodeTransform.js +9 -14
  21. package/src/core/class/offset.js +162 -197
  22. package/src/core/class/selection.js +137 -34
  23. package/src/core/class/toolbar.js +73 -52
  24. package/src/core/class/ui.js +11 -11
  25. package/src/core/class/viewer.js +56 -55
  26. package/src/core/config/context.js +122 -0
  27. package/src/core/config/frameContext.js +204 -0
  28. package/src/core/config/options.js +639 -0
  29. package/src/core/editor.js +181 -108
  30. package/src/core/event/actions/index.js +229 -0
  31. package/src/core/event/effects/common.registry.js +60 -0
  32. package/src/core/event/effects/keydown.registry.js +551 -0
  33. package/src/core/event/effects/ruleHelpers.js +145 -0
  34. package/src/core/{base → event}/eventManager.js +119 -201
  35. package/src/core/event/executor.js +21 -0
  36. package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +4 -4
  37. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +2 -2
  38. package/src/core/event/handlers/handler_ww_input.js +77 -0
  39. package/src/core/event/handlers/handler_ww_key.js +228 -0
  40. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.js +3 -3
  41. package/src/core/event/ports.js +211 -0
  42. package/src/core/event/reducers/keydown.reducer.js +89 -0
  43. package/src/core/event/rules/keydown.rule.arrow.js +54 -0
  44. package/src/core/event/rules/keydown.rule.backspace.js +202 -0
  45. package/src/core/event/rules/keydown.rule.delete.js +126 -0
  46. package/src/core/event/rules/keydown.rule.enter.js +144 -0
  47. package/src/core/event/rules/keydown.rule.tab.js +29 -0
  48. package/src/core/section/constructor.js +79 -388
  49. package/src/core/section/documentType.js +47 -26
  50. package/src/core/util/instanceCheck.js +59 -0
  51. package/src/editorInjector/_classes.js +4 -0
  52. package/src/editorInjector/_core.js +17 -7
  53. package/src/editorInjector/index.js +10 -2
  54. package/src/events.js +6 -0
  55. package/src/helper/clipboard.js +24 -10
  56. package/src/helper/converter.js +17 -12
  57. package/src/helper/dom/domCheck.js +22 -3
  58. package/src/helper/dom/domQuery.js +91 -45
  59. package/src/helper/dom/domUtils.js +93 -19
  60. package/src/helper/dom/index.js +4 -0
  61. package/src/helper/env.js +11 -7
  62. package/src/helper/keyCodeMap.js +4 -3
  63. package/src/langs/ckb.js +1 -1
  64. package/src/langs/cs.js +1 -1
  65. package/src/langs/da.js +1 -1
  66. package/src/langs/de.js +1 -1
  67. package/src/langs/en.js +1 -1
  68. package/src/langs/es.js +1 -1
  69. package/src/langs/fa.js +1 -1
  70. package/src/langs/fr.js +1 -1
  71. package/src/langs/he.js +1 -1
  72. package/src/langs/hu.js +1 -1
  73. package/src/langs/it.js +1 -1
  74. package/src/langs/ja.js +1 -1
  75. package/src/langs/km.js +1 -1
  76. package/src/langs/ko.js +1 -1
  77. package/src/langs/lv.js +1 -1
  78. package/src/langs/nl.js +1 -1
  79. package/src/langs/pl.js +1 -1
  80. package/src/langs/pt_br.js +10 -10
  81. package/src/langs/ro.js +1 -1
  82. package/src/langs/ru.js +1 -1
  83. package/src/langs/se.js +1 -1
  84. package/src/langs/tr.js +1 -1
  85. package/src/langs/uk.js +1 -1
  86. package/src/langs/ur.js +1 -1
  87. package/src/langs/zh_cn.js +1 -1
  88. package/src/modules/ApiManager.js +25 -18
  89. package/src/modules/Browser.js +52 -61
  90. package/src/modules/ColorPicker.js +37 -38
  91. package/src/modules/Controller.js +85 -79
  92. package/src/modules/Figure.js +275 -187
  93. package/src/modules/FileManager.js +86 -92
  94. package/src/modules/HueSlider.js +67 -35
  95. package/src/modules/Modal.js +84 -77
  96. package/src/modules/ModalAnchorEditor.js +62 -79
  97. package/src/modules/SelectMenu.js +89 -86
  98. package/src/plugins/browser/audioGallery.js +9 -5
  99. package/src/plugins/browser/fileBrowser.js +10 -6
  100. package/src/plugins/browser/fileGallery.js +9 -5
  101. package/src/plugins/browser/imageGallery.js +9 -5
  102. package/src/plugins/browser/videoGallery.js +11 -6
  103. package/src/plugins/command/blockquote.js +1 -0
  104. package/src/plugins/command/exportPDF.js +11 -8
  105. package/src/plugins/command/fileUpload.js +41 -29
  106. package/src/plugins/command/list_bulleted.js +2 -1
  107. package/src/plugins/command/list_numbered.js +2 -1
  108. package/src/plugins/dropdown/align.js +8 -2
  109. package/src/plugins/dropdown/backgroundColor.js +19 -11
  110. package/src/plugins/dropdown/font.js +15 -9
  111. package/src/plugins/dropdown/fontColor.js +19 -11
  112. package/src/plugins/dropdown/formatBlock.js +7 -2
  113. package/src/plugins/dropdown/hr.js +7 -3
  114. package/src/plugins/dropdown/layout.js +6 -2
  115. package/src/plugins/dropdown/lineHeight.js +8 -3
  116. package/src/plugins/dropdown/list.js +2 -1
  117. package/src/plugins/dropdown/paragraphStyle.js +15 -11
  118. package/src/plugins/dropdown/{table.js → table/index.js} +514 -362
  119. package/src/plugins/dropdown/template.js +6 -2
  120. package/src/plugins/dropdown/textStyle.js +7 -3
  121. package/src/plugins/field/mention.js +33 -27
  122. package/src/plugins/input/fontSize.js +44 -37
  123. package/src/plugins/input/pageNavigator.js +3 -2
  124. package/src/plugins/modal/audio.js +90 -85
  125. package/src/plugins/modal/drawing.js +58 -66
  126. package/src/plugins/modal/embed.js +193 -180
  127. package/src/plugins/modal/image.js +441 -439
  128. package/src/plugins/modal/link.js +31 -8
  129. package/src/plugins/modal/math.js +23 -22
  130. package/src/plugins/modal/video.js +233 -230
  131. package/src/plugins/popup/anchor.js +24 -18
  132. package/src/suneditor.js +69 -24
  133. package/src/typedef.js +42 -19
  134. package/types/assets/icons/defaultIcons.d.ts +8 -0
  135. package/types/core/class/char.d.ts +1 -1
  136. package/types/core/class/component.d.ts +29 -7
  137. package/types/core/class/format.d.ts +4 -354
  138. package/types/core/class/html.d.ts +13 -4
  139. package/types/core/class/inline.d.ts +263 -0
  140. package/types/core/class/listFormat.d.ts +135 -0
  141. package/types/core/class/menu.d.ts +10 -2
  142. package/types/core/class/offset.d.ts +24 -26
  143. package/types/core/class/selection.d.ts +2 -0
  144. package/types/core/class/toolbar.d.ts +24 -11
  145. package/types/core/class/ui.d.ts +1 -1
  146. package/types/core/class/viewer.d.ts +1 -1
  147. package/types/core/config/context.d.ts +157 -0
  148. package/types/core/config/frameContext.d.ts +367 -0
  149. package/types/core/config/options.d.ts +1119 -0
  150. package/types/core/editor.d.ts +101 -66
  151. package/types/core/event/actions/index.d.ts +47 -0
  152. package/types/core/event/effects/common.registry.d.ts +50 -0
  153. package/types/core/event/effects/keydown.registry.d.ts +73 -0
  154. package/types/core/event/effects/ruleHelpers.d.ts +31 -0
  155. package/types/core/{base → event}/eventManager.d.ts +15 -46
  156. package/types/core/event/executor.d.ts +6 -0
  157. package/types/core/event/handlers/handler_ww_input.d.ts +41 -0
  158. package/types/core/{base/eventHandlers/handler_ww_key_input.d.ts → event/handlers/handler_ww_key.d.ts} +4 -6
  159. package/types/core/event/ports.d.ts +255 -0
  160. package/types/core/event/reducers/keydown.reducer.d.ts +75 -0
  161. package/types/core/event/rules/keydown.rule.arrow.d.ts +8 -0
  162. package/types/core/event/rules/keydown.rule.backspace.d.ts +9 -0
  163. package/types/core/event/rules/keydown.rule.delete.d.ts +9 -0
  164. package/types/core/event/rules/keydown.rule.enter.d.ts +9 -0
  165. package/types/core/event/rules/keydown.rule.tab.d.ts +9 -0
  166. package/types/core/section/constructor.d.ts +101 -631
  167. package/types/core/section/documentType.d.ts +14 -4
  168. package/types/core/util/instanceCheck.d.ts +50 -0
  169. package/types/editorInjector/_classes.d.ts +4 -0
  170. package/types/editorInjector/_core.d.ts +17 -7
  171. package/types/editorInjector/index.d.ts +10 -2
  172. package/types/events.d.ts +1 -0
  173. package/types/helper/clipboard.d.ts +2 -2
  174. package/types/helper/converter.d.ts +6 -9
  175. package/types/helper/dom/domCheck.d.ts +7 -0
  176. package/types/helper/dom/domQuery.d.ts +19 -8
  177. package/types/helper/dom/domUtils.d.ts +24 -2
  178. package/types/helper/dom/index.d.ts +86 -1
  179. package/types/helper/env.d.ts +6 -1
  180. package/types/helper/index.d.ts +7 -1
  181. package/types/helper/keyCodeMap.d.ts +3 -3
  182. package/types/index.d.ts +23 -117
  183. package/types/langs/index.d.ts +2 -2
  184. package/types/modules/ApiManager.d.ts +1 -8
  185. package/types/modules/Browser.d.ts +4 -62
  186. package/types/modules/ColorPicker.d.ts +4 -21
  187. package/types/modules/Controller.d.ts +8 -64
  188. package/types/modules/Figure.d.ts +54 -50
  189. package/types/modules/FileManager.d.ts +1 -13
  190. package/types/modules/HueSlider.d.ts +13 -3
  191. package/types/modules/Modal.d.ts +0 -43
  192. package/types/modules/ModalAnchorEditor.d.ts +0 -73
  193. package/types/modules/SelectMenu.d.ts +0 -85
  194. package/types/modules/index.d.ts +3 -3
  195. package/types/plugins/browser/audioGallery.d.ts +29 -18
  196. package/types/plugins/browser/fileBrowser.d.ts +38 -27
  197. package/types/plugins/browser/fileGallery.d.ts +29 -18
  198. package/types/plugins/browser/imageGallery.d.ts +24 -16
  199. package/types/plugins/browser/videoGallery.d.ts +29 -18
  200. package/types/plugins/command/blockquote.d.ts +1 -0
  201. package/types/plugins/command/exportPDF.d.ts +18 -18
  202. package/types/plugins/command/fileUpload.d.ts +65 -45
  203. package/types/plugins/command/list_bulleted.d.ts +1 -0
  204. package/types/plugins/command/list_numbered.d.ts +1 -0
  205. package/types/plugins/dropdown/align.d.ts +13 -8
  206. package/types/plugins/dropdown/backgroundColor.d.ts +30 -19
  207. package/types/plugins/dropdown/font.d.ts +13 -12
  208. package/types/plugins/dropdown/fontColor.d.ts +30 -19
  209. package/types/plugins/dropdown/formatBlock.d.ts +13 -8
  210. package/types/plugins/dropdown/hr.d.ts +15 -11
  211. package/types/plugins/dropdown/layout.d.ts +15 -11
  212. package/types/plugins/dropdown/lineHeight.d.ts +16 -11
  213. package/types/plugins/dropdown/list.d.ts +1 -0
  214. package/types/plugins/dropdown/paragraphStyle.d.ts +31 -27
  215. package/types/plugins/dropdown/table/index.d.ts +582 -0
  216. package/types/plugins/dropdown/table.d.ts +41 -86
  217. package/types/plugins/dropdown/template.d.ts +15 -11
  218. package/types/plugins/dropdown/textStyle.d.ts +19 -11
  219. package/types/plugins/field/mention.d.ts +58 -56
  220. package/types/plugins/index.d.ts +38 -38
  221. package/types/plugins/input/fontSize.d.ts +46 -50
  222. package/types/plugins/modal/audio.d.ts +26 -56
  223. package/types/plugins/modal/drawing.d.ts +0 -85
  224. package/types/plugins/modal/embed.d.ts +15 -79
  225. package/types/plugins/modal/image.d.ts +24 -136
  226. package/types/plugins/modal/link.d.ts +34 -15
  227. package/types/plugins/modal/math.d.ts +0 -16
  228. package/types/plugins/modal/video.d.ts +17 -86
  229. package/types/plugins/popup/anchor.d.ts +1 -8
  230. package/types/suneditor.d.ts +70 -19
  231. package/types/typedef.d.ts +60 -46
  232. package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
  233. package/src/core/section/context.js +0 -102
  234. package/types/core/section/context.d.ts +0 -45
  235. package/types/langs/_Lang.d.ts +0 -194
  236. /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +0 -0
  237. /package/types/core/{section → base}/actives.d.ts +0 -0
  238. /package/types/core/{base/eventHandlers → event/handlers}/handler_toolbar.d.ts +0 -0
  239. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.d.ts +0 -0
  240. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.d.ts +0 -0
  241. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.d.ts +0 -0
@@ -2,7 +2,7 @@ import EditorInjector from '../editorInjector';
2
2
  import { Controller, SelectMenu, _DragHandle } from '../modules';
3
3
  import { dom, numbers, env, converter, keyCodeMap } from '../helper';
4
4
 
5
- const { ON_OVER_COMPONENT } = env;
5
+ const { _w, ON_OVER_COMPONENT } = env;
6
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';
@@ -24,6 +24,7 @@ let __resizing_sw = 0;
24
24
  * @property {?HTMLElement} cover Cover element (FIGURE|null)
25
25
  * @property {?HTMLElement} inlineCover Inline cover element (span.se-inline-component)
26
26
  * @property {?HTMLElement} caption Caption element (FIGCAPTION)
27
+ * @property {boolean} isVertical Whether to rotate vertically
27
28
  */
28
29
 
29
30
  /**
@@ -33,6 +34,7 @@ let __resizing_sw = 0;
33
34
  * @property {?HTMLElement=} caption Caption element (FIGCAPTION)
34
35
  * @property {string} [align] - Alignment of the element.
35
36
  * @property {{w:number, h:number}} [ratio] - The aspect ratio of the element.
37
+ * @property {boolean} isVertical Whether to rotate vertically
36
38
  * @property {string|number} [w] - Width of the element.
37
39
  * @property {string|number} [h] - Height of the element.
38
40
  * @property {number} [t] - Top position.
@@ -62,6 +64,19 @@ let __resizing_sw = 0;
62
64
  * @description Controller module class
63
65
  */
64
66
  class Figure extends EditorInjector {
67
+ #width;
68
+ #height;
69
+ #resize_w;
70
+ #resize_h;
71
+ #element_w;
72
+ #element_h;
73
+ #floatClassStr;
74
+ #preventSizechange;
75
+ #revertSize;
76
+ #offContainer;
77
+ #containerResizingESC;
78
+ #onResizeESCEvent;
79
+
65
80
  /**
66
81
  * @constructor
67
82
  * @param {*} inst The instance object that called the constructor.
@@ -117,35 +132,33 @@ class Figure extends EditorInjector {
117
132
  this.captionButton = controllerEl.querySelector('[data-command="caption"]');
118
133
  this.align = 'none';
119
134
  this.as = 'block';
135
+ /** @type {{left?: number, top?: number}} */
136
+ this.__offset = {};
120
137
  this._element = null;
121
138
  this._cover = null;
122
139
  this._inlineCover = null;
123
140
  this._container = null;
124
141
  this._caption = null;
125
- this._width = '';
126
- this._height = '';
127
- this._resize_w = 0;
128
- this._resize_h = 0;
129
- this._element_w = 0;
130
- this._element_h = 0;
131
- this._element_l = 0;
132
- this._element_t = 0;
133
142
  this._resizeClientX = 0;
134
143
  this._resizeClientY = 0;
135
144
  this._resize_direction = '';
136
- this._floatClassStr = '__se__float-none|__se__float-left|__se__float-center|__se__float-right';
137
- this.__preventSizechange = false;
138
- this.__revertSize = { w: '', h: '' };
139
- /** @type {{left?: number, top?: number}} */
140
- this.__offset = {};
141
- this.__offContainer = this.#OffFigureContainer.bind(this);
142
- this.__containerResizing = this.#ContainerResizing.bind(this);
143
145
  this.__containerResizingOff = this.#ContainerResizingOff.bind(this);
144
- this.__containerResizingESC = this.#ContainerResizingESC.bind(this);
146
+ this.__containerResizing = this.#ContainerResizing.bind(this);
145
147
  this.__onContainerEvent = null;
146
148
  this.__offContainerEvent = null;
147
- this.__onResizeESCEvent = null;
148
- this.__fileManagerInfo = false;
149
+
150
+ this.#width = '';
151
+ this.#height = '';
152
+ this.#resize_w = 0;
153
+ this.#resize_h = 0;
154
+ this.#element_w = 0;
155
+ this.#element_h = 0;
156
+ this.#floatClassStr = '__se__float-none|__se__float-left|__se__float-center|__se__float-right';
157
+ this.#preventSizechange = false;
158
+ this.#revertSize = { w: '', h: '' };
159
+ this.#offContainer = this.#OffFigureContainer.bind(this);
160
+ this.#containerResizingESC = this.#ContainerResizingESC.bind(this);
161
+ this.#onResizeESCEvent = null;
149
162
 
150
163
  // init
151
164
  this.eventManager.addEvent(this.alignButton, 'click', this.#OnClick_alignButton.bind(this));
@@ -209,12 +222,16 @@ class Figure extends EditorInjector {
209
222
  static GetContainer(element) {
210
223
  const cover = dom.query.getParentElement(element, 'FIGURE', 2);
211
224
  const inlineCover = dom.query.getParentElement(element, 'SPAN', 2);
225
+ const anyCover = cover || inlineCover;
226
+ const target = dom.query.getParentElement(element, (current) => current.parentElement === anyCover, 0) || /** @type {HTMLElement} */ (element);
227
+
212
228
  return {
213
- target: /** @type {HTMLElement} */ (element),
214
- container: /** @type {HTMLElement} */ (dom.query.getParentElement(element, Figure.is, 2) || cover),
215
- cover: /** @type {HTMLElement} */ (cover),
229
+ target,
230
+ container: dom.query.getParentElement(target, Figure.is, 3) || cover,
231
+ cover: cover,
216
232
  inlineCover: dom.utils.hasClass(inlineCover, 'se-inline-component') ? /** @type {HTMLElement} */ (inlineCover) : null,
217
- caption: /** @type {HTMLElement} */ (dom.query.getEdgeChild(element.parentElement, 'FIGCAPTION', false))
233
+ caption: dom.query.getEdgeChild(target.parentElement, 'FIGCAPTION', false),
234
+ isVertical: IsVertical(target)
218
235
  };
219
236
  }
220
237
 
@@ -226,8 +243,8 @@ class Figure extends EditorInjector {
226
243
  * @return {{w: number, h: number}}
227
244
  */
228
245
  static GetRatio(w, h, defaultSizeUnit) {
229
- let rw = 1,
230
- rh = 1;
246
+ let rw = 0,
247
+ rh = 0;
231
248
  if (/\d+/.test(w + '') && /\d+/.test(h + '')) {
232
249
  const xUnit = (!numbers.is(w) && String(w).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
233
250
  const yUnit = (!numbers.is(h) && String(h).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
@@ -250,11 +267,11 @@ class Figure extends EditorInjector {
250
267
  * @param {string|number} w Width size
251
268
  * @param {string|number} h Height size
252
269
  * @param {string} defaultSizeUnit Default size unit (default: "px")
253
- * @param {{w: number, h: number}} ratio Ratio size (Figure.GetRatio)
270
+ * @param {?{w: number, h: number}=} ratio Ratio size (Figure.GetRatio)
254
271
  * @return {{w: string|number, h: string|number}}
255
272
  */
256
273
  static CalcRatio(w, h, defaultSizeUnit, ratio) {
257
- if (/\d+/.test(w + '') && /\d+/.test(h + '')) {
274
+ if (ratio?.w && ratio?.h && /\d+/.test(w + '') && /\d+/.test(h + '')) {
258
275
  const xUnit = (!numbers.is(w) && String(w).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
259
276
  const yUnit = (!numbers.is(h) && String(h).replace(/\d+|\./g, '')) || defaultSizeUnit || 'px';
260
277
  if (xUnit === yUnit) {
@@ -278,7 +295,7 @@ class Figure extends EditorInjector {
278
295
  * @returns {boolean}
279
296
  */
280
297
  static is(element) {
281
- return dom.utils.hasClass(element, 'se-component') || /^(HR)$/.test(element?.nodeName);
298
+ return dom.check.isComponentContainer(element) || /^(HR)$/.test(element?.nodeName);
282
299
  }
283
300
 
284
301
  /**
@@ -299,18 +316,16 @@ class Figure extends EditorInjector {
299
316
  * @param {boolean} [params.nonSizeInfo=false] Do not display the size information
300
317
  * @param {boolean} [params.nonBorder=false] Do not display the selected style line
301
318
  * @param {boolean} [params.figureTarget=false] If true, the target is a figure element
302
- * @param {boolean} [params.__fileManagerInfo=false] If true, the file manager is called
319
+ * @param {boolean} [params.infoOnly=false] If true, returns only the figure target info without opening the controller
303
320
  * @returns {FigureTargetInfo|undefined} figure target info
304
321
  */
305
- open(targetNode, { nonResizing, nonSizeInfo, nonBorder, figureTarget, __fileManagerInfo }) {
322
+ open(targetNode, { nonResizing, nonSizeInfo, nonBorder, figureTarget, infoOnly }) {
306
323
  if (!targetNode) {
307
324
  console.warn('[SUNEDITOR.modules.Figure.open] The "targetNode" is null.');
308
325
  return;
309
326
  }
310
327
 
311
- if (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT) {
312
- this.ui._offCurrentController();
313
- } else {
328
+ if (_DragHandle.get('__overInfo') === ON_OVER_COMPONENT) {
314
329
  nonBorder = true;
315
330
  }
316
331
 
@@ -326,8 +341,9 @@ class Figure extends EditorInjector {
326
341
  return {
327
342
  container: null,
328
343
  cover: null,
329
- width: target.style.width || (!numbers.is(/** @type {HTMLImageElement} */ (target).width) ? /** @type {HTMLImageElement} */ (target).width : '') || '',
330
- height: target.style.height || (!numbers.is(/** @type {HTMLImageElement} */ (target).height) ? /** @type {HTMLImageElement} */ (target).height : '') || ''
344
+ width: target.style.width || /** @type {HTMLImageElement} */ (target).width || '',
345
+ height: target.style.height || /** @type {HTMLImageElement} */ (target).height || '',
346
+ isVertical: this.isVertical
331
347
  };
332
348
  }
333
349
  }
@@ -342,13 +358,19 @@ class Figure extends EditorInjector {
342
358
  const { top, left, scrollX, scrollY } = this.offset.getLocal(sizeTarget);
343
359
 
344
360
  const dataSize = (target.getAttribute('data-se-size') || '').split(',');
345
- const ratio = Figure.GetRatio(dataSize[0] || numbers.get(target.style.width, 2) || w, dataSize[1] || numbers.get(target.style.height, 2) || h, this.sizeUnit);
361
+
362
+ let rw = numbers.get(target.style.width, 2) || w;
363
+ let rh = numbers.get(target.style.height, 2) || h;
364
+ if (this.isVertical) [rw, rh] = [rh, rw];
365
+ const ratio = Figure.GetRatio(rw, rh, this.sizeUnit);
366
+
346
367
  const targetInfo = {
347
368
  container: figureInfo.container,
348
369
  cover: figureInfo.cover,
349
370
  caption: figureInfo.caption,
350
371
  align: this.align,
351
372
  ratio: ratio,
373
+ isVertical: this.isVertical,
352
374
  w: w || '',
353
375
  h: h || '',
354
376
  t: top,
@@ -359,11 +381,11 @@ class Figure extends EditorInjector {
359
381
  originHeight: /** @type {HTMLImageElement} */ (target).naturalHeight || target.offsetHeight
360
382
  };
361
383
 
362
- this._width = targetInfo.width;
363
- this._height = targetInfo.height;
364
- if (__fileManagerInfo || this.__fileManagerInfo) return targetInfo;
384
+ this.#width = targetInfo.width;
385
+ this.#height = targetInfo.height;
386
+ if (infoOnly) return targetInfo;
365
387
 
366
- const _figure = this.editor.frameContext.get('_figure');
388
+ const _figure = this.frameContext.get('_figure');
367
389
  this.editor._figureContainer = _figure.main;
368
390
  _figure.main.style.top = top + 'px';
369
391
  _figure.main.style.left = left + 'px';
@@ -414,7 +436,7 @@ class Figure extends EditorInjector {
414
436
  this.ui._visibleControllers(true, true);
415
437
  // size
416
438
  const size = this.getSize(target);
417
- dom.utils.changeTxt(_figure.display, this.lang[this.align === 'none' ? 'basic' : this.align] + ' (' + size.w + ', ' + size.h + ')');
439
+ dom.utils.changeTxt(_figure.display, this.lang[this.align === 'none' ? 'basic' : this.align] + ' (' + size.dw + ', ' + size.dh + ')');
418
440
  this._displayResizeHandles(!nonResizing);
419
441
  // rotate, aption, align, onresize - display;
420
442
  const transformButtons = this.controller.form.querySelectorAll(
@@ -431,18 +453,16 @@ class Figure extends EditorInjector {
431
453
  }
432
454
  // selecte
433
455
  dom.utils.removeClass(this._cover, 'se-figure-over-selected');
434
- this.controller.open(_figure.main, null, { initMethod: this.__offContainer, isWWTarget: false, addOffset: null });
435
- this._w.setTimeout(() => _DragHandle.set('__overInfo', false), 0);
456
+ this.controller.open(_figure.main, null, { initMethod: this.#offContainer, isWWTarget: false, addOffset: null });
457
+ _w.setTimeout(() => _DragHandle.set('__overInfo', false), 0);
436
458
  } else {
437
459
  dom.utils.addClass(this._cover, 'se-figure-over-selected');
438
460
  }
439
461
 
440
462
  // set members
441
463
  dom.utils.addClass(this._cover, 'se-figure-selected');
442
- this._element_w = this._resize_w = w;
443
- this._element_h = this._resize_h = h;
444
- this._element_l = left;
445
- this._element_t = top;
464
+ this.#element_w = this.#resize_w = w;
465
+ this.#element_h = this.#resize_h = h;
446
466
 
447
467
  // drag
448
468
  if (!this._inlineCover && (_DragHandle.get('__overInfo') !== ON_OVER_COMPONENT || dom.utils.hasClass(figureInfo.container, 'se-input-component'))) {
@@ -485,7 +505,7 @@ class Figure extends EditorInjector {
485
505
  * @param {string|number} w Width size
486
506
  * @param {string|number} h Height size
487
507
  */
488
- setSize(w, h) {
508
+ setFigureSize(w, h) {
489
509
  if (/%$/.test(w + '')) {
490
510
  this._setPercentSize(w, h);
491
511
  } else if ((!w || w === 'auto') && (!h || h === 'auto')) {
@@ -496,42 +516,67 @@ class Figure extends EditorInjector {
496
516
  }
497
517
  }
498
518
 
519
+ /**
520
+ * @description Set the element's container size from plugins input value
521
+ * @param {string|number} w Width size
522
+ * @param {string|number} h Height size
523
+ */
524
+ setSize(w, h) {
525
+ const v = this.isVertical;
526
+ if (v) [w, h] = [h, w];
527
+ this.setFigureSize(w, h);
528
+ if (v) this.setTransform(this._element, w, h, 0);
529
+ }
530
+
499
531
  /**
500
532
  * @description Gets the Figure size
501
533
  * @param {?Node=} targetNode Target element, default is the current element
502
- * @returns {{w: string, h: string}}
534
+ * @returns {{w: string, h: string, dw: string, dh: string}}
503
535
  */
504
536
  getSize(targetNode) {
505
- if (!targetNode) targetNode = this._element;
506
- if (!targetNode) return { w: '', h: '' };
537
+ targetNode ||= this._element;
538
+
539
+ const v = IsVertical(targetNode);
540
+ let w = '';
541
+ let h = '';
542
+ let dw = '';
543
+ let dh = '';
544
+
545
+ if (!targetNode) return { w, h, dw, dh };
507
546
 
508
547
  const figure = Figure.GetContainer(targetNode);
509
548
  const target = figure.target;
510
549
  if (!figure.container) {
511
550
  // exceptionFormat
512
551
  if (!this.options.get('strictMode').formatFilter) {
513
- return {
514
- w: target.style.width || 'auto',
515
- h: target.style.height || 'auto'
516
- };
552
+ w = target.style.width || 'auto';
553
+ h = target.style.height || 'auto';
554
+ } else {
555
+ w = '';
556
+ h = target.style.height;
517
557
  }
518
- return {
519
- w: '',
520
- h: target.style.height
521
- };
558
+ } else {
559
+ w = !/%$/.test(target.style.width) ? target.style.width : ((figure.container && numbers.get(figure.container.style.width, 2)) || 100) + '%';
560
+ h = figure.inlineCover
561
+ ? figure.inlineCover.style.height || /** @type {HTMLElement} */ (targetNode).style.height || String(/** @type {HTMLImageElement} */ (targetNode).height || '')
562
+ : numbers.get(figure.cover?.style.paddingBottom, 0) > 0 && !v
563
+ ? figure.cover?.style.height
564
+ : !/%$/.test(target.style.height) || !/%$/.test(target.style.width)
565
+ ? target.style.height
566
+ : ((figure.container && numbers.get(figure.container.style.height, 2)) || 100) + '%';
567
+
568
+ w ||= 'auto';
569
+ h ||= 'auto';
522
570
  }
523
571
 
524
- const w = !/%$/.test(target.style.width) ? target.style.width : ((figure.container && numbers.get(figure.container.style.width, 2)) || 100) + '%';
525
- const h = figure.inlineCover
526
- ? figure.inlineCover.style.height
527
- : numbers.get(figure.cover.style.paddingBottom, 0) > 0 && !this.isVertical
528
- ? figure.cover.style.height
529
- : !/%$/.test(target.style.height) || !/%$/.test(target.style.width)
530
- ? target.style.height
531
- : ((figure.container && numbers.get(figure.container.style.height, 2)) || 100) + '%';
572
+ dw = v ? h : w;
573
+ dh = v ? w : h;
574
+
532
575
  return {
533
- w: w || 'auto',
534
- h: h || 'auto'
576
+ w,
577
+ h,
578
+ dw,
579
+ dh
535
580
  };
536
581
  }
537
582
 
@@ -541,8 +586,8 @@ class Figure extends EditorInjector {
541
586
  * @param {string} align "none"|"left"|"center"|"right"
542
587
  */
543
588
  setAlign(targetNode, align) {
544
- if (!targetNode) targetNode = this._element;
545
- this.align = align = align || 'none';
589
+ targetNode ||= this._element;
590
+ this.align = align ||= 'none';
546
591
 
547
592
  const figure = Figure.GetContainer(targetNode);
548
593
  if (!figure.cover) return;
@@ -559,7 +604,7 @@ class Figure extends EditorInjector {
559
604
  }
560
605
 
561
606
  if (!dom.utils.hasClass(container, '__se__float-' + align)) {
562
- dom.utils.removeClass(container, this._floatClassStr);
607
+ dom.utils.removeClass(container, this.#floatClassStr);
563
608
  dom.utils.addClass(container, '__se__float-' + align);
564
609
  }
565
610
 
@@ -575,14 +620,19 @@ class Figure extends EditorInjector {
575
620
  * @description As style[block, inline] the component
576
621
  * @param {?Node} targetNode Target element
577
622
  * @param {"block"|"inline"} formatStyle Format style
623
+ * @returns {HTMLElement} New target element after conversion
578
624
  */
579
625
  convertAsFormat(targetNode, formatStyle) {
580
- if (!targetNode) targetNode = this._element;
626
+ targetNode ||= this._element;
581
627
  this.as = formatStyle || 'block';
582
628
  const { container, inlineCover, target } = Figure.GetContainer(targetNode);
583
629
  const { w, h } = this.getSize(target);
584
630
 
585
631
  const newTarget = /** @type {HTMLElement} */ (target.cloneNode(false));
632
+ newTarget.style.width = '';
633
+ newTarget.style.height = '';
634
+ newTarget.removeAttribute('width');
635
+ newTarget.removeAttribute('height');
586
636
 
587
637
  switch (formatStyle) {
588
638
  case 'inline': {
@@ -592,8 +642,6 @@ class Figure extends EditorInjector {
592
642
  const next = container.nextElementSibling;
593
643
  const parent = container.parentElement;
594
644
 
595
- newTarget.style.width = '';
596
- newTarget.style.height = '';
597
645
  const figure = Figure.CreateInlineContainer(newTarget);
598
646
  dom.utils.addClass(
599
647
  figure.container,
@@ -623,8 +671,6 @@ class Figure extends EditorInjector {
623
671
  dom.utils.removeItem(s.previousElementSibling);
624
672
  }
625
673
 
626
- newTarget.style.width = '';
627
- newTarget.style.height = '';
628
674
  const figure = Figure.CreateContainer(newTarget);
629
675
  dom.utils.addClass(
630
676
  figure.container,
@@ -641,27 +687,8 @@ class Figure extends EditorInjector {
641
687
  break;
642
688
  }
643
689
  }
644
- }
645
-
646
- /**
647
- * @private
648
- * @description Handles format conversion (block/inline) for the figure component and applies size changes.
649
- * @param {FigureInfo} figureinfo {target, container, cover, inlineCover, caption}
650
- * @param {string|number} w Width value.
651
- * @param {string|number} h Height value.
652
- */
653
- _asFormatChange(figureinfo, w, h) {
654
- const kind = this.kind;
655
- figureinfo.target.onload = () => this.component.select(figureinfo.target, kind);
656
-
657
- this._setFigureInfo(figureinfo);
658
-
659
- if (figureinfo.inlineCover) {
660
- this.setAlign(figureinfo.target, 'none');
661
- this.deleteTransform();
662
- }
663
690
 
664
- this.setSize(w, h);
691
+ return newTarget;
665
692
  }
666
693
 
667
694
  /**
@@ -678,7 +705,7 @@ class Figure extends EditorInjector {
678
705
 
679
706
  switch (command) {
680
707
  case 'mirror': {
681
- const info = this.#GetRotateValue(element);
708
+ const info = GetRotateValue(element);
682
709
  let x = info.x;
683
710
  let y = info.y;
684
711
 
@@ -691,10 +718,11 @@ class Figure extends EditorInjector {
691
718
  this._setRotate(element, info.r, x, y);
692
719
  break;
693
720
  }
694
- case 'rotate':
695
- this.setTransform(element, null, null, value);
721
+ case 'rotate': {
722
+ this.setTransform(element, null, null, Number(value));
696
723
  break;
697
- case 'caption':
724
+ }
725
+ case 'caption': {
698
726
  if (!this._caption) {
699
727
  const caption = Figure.CreateCaption(this._cover, this.lang.caption);
700
728
  const captionText = dom.query.getEdgeChild(caption, (current) => current.nodeType === 3, false);
@@ -708,7 +736,7 @@ class Figure extends EditorInjector {
708
736
  this.controller.close();
709
737
  } else {
710
738
  dom.utils.removeItem(this._caption);
711
- this._w.setTimeout(this.component.select.bind(this.component, element, this.kind), 0);
739
+ _w.setTimeout(this.component.select.bind(this.component, element, this.kind), 0);
712
740
  }
713
741
 
714
742
  this._caption = !this._caption;
@@ -720,20 +748,24 @@ class Figure extends EditorInjector {
720
748
  }
721
749
  }
722
750
  break;
723
- case 'revert':
751
+ }
752
+ case 'revert': {
724
753
  this._setRevert();
725
754
  break;
726
- case 'edit':
755
+ }
756
+ case 'edit': {
727
757
  this.inst.edit(element);
728
758
  break;
759
+ }
729
760
  case 'copy': {
730
761
  this.component.copy(this._container);
731
762
  break;
732
763
  }
733
- case 'remove':
764
+ case 'remove': {
734
765
  this.inst.destroy(element);
735
766
  this.controller.close();
736
767
  break;
768
+ }
737
769
  }
738
770
 
739
771
  if (/^__c__/.test(command)) {
@@ -758,7 +790,8 @@ class Figure extends EditorInjector {
758
790
  */
759
791
  retainFigureFormat(container, originEl, anchorCover, fileManagerInst) {
760
792
  const isInline = this.component.isInline(container);
761
- 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;
793
+ const originParent = originEl.parentNode;
794
+ let existElement = this.format.isBlock(originParent) || dom.check.isWysiwygFrame(originParent) ? originEl : Figure.GetContainer(originEl)?.container || originParent || originEl;
762
795
 
763
796
  if (dom.query.getParentElement(originEl, dom.check.isExcludeFormat)) {
764
797
  existElement = anchorCover && anchorCover !== originEl ? anchorCover : originEl;
@@ -795,7 +828,7 @@ class Figure extends EditorInjector {
795
828
  * @param {?Node=} node Target element, default is the current element
796
829
  */
797
830
  deleteTransform(node) {
798
- if (!node) node = this._element;
831
+ node ||= this._element;
799
832
 
800
833
  const element = /** @type {HTMLElement} */ (node);
801
834
  const size = (element.getAttribute('data-se-size') || '').split(',');
@@ -814,20 +847,23 @@ class Figure extends EditorInjector {
814
847
  * @param {Node} node Target element
815
848
  * @param {?string|number} width Element's width size
816
849
  * @param {?string|number} height Element's height size
850
+ * @param {?number} deg rotate value
817
851
  */
818
852
  setTransform(node, width, height, deg) {
819
853
  try {
820
- this.__preventSizechange = true;
821
- const info = this.#GetRotateValue(node);
854
+ this.#preventSizechange = true;
855
+ const info = GetRotateValue(node);
822
856
  const slope = info.r + (deg || 0) * 1;
823
857
  deg = Math.abs(slope) >= 360 ? 0 : slope;
824
- const isVertical = (this.isVertical = /^(90|270)$/.test(Math.abs(deg).toString()));
858
+ const isVertical = (this.isVertical = IsVertical(deg));
825
859
 
826
860
  width = numbers.get(width, 0);
827
861
  height = numbers.get(height, 0);
828
862
 
829
863
  const element = /** @type {HTMLElement} */ (node);
830
864
  const dataSize = (element.getAttribute('data-se-size') || 'auto,auto').split(',');
865
+ if (isVertical) this._setRotate(element, deg, info.x, info.y);
866
+
831
867
  let transOrigin = '';
832
868
  if (/auto|%$/.test(dataSize[0]) && !isVertical) {
833
869
  if (dataSize[0] === 'auto' && dataSize[1] === 'auto') {
@@ -846,8 +882,10 @@ class Figure extends EditorInjector {
846
882
  this._deletePercentSize();
847
883
  this._applySize(offsetW + 'px', offsetH + 'px', '');
848
884
 
849
- cover.style.width = w;
850
- cover.style.height = figureInfo.caption || figureInfo.inlineCover ? '' : h;
885
+ if (cover) {
886
+ cover.style.width = w;
887
+ cover.style.height = figureInfo.caption || figureInfo.inlineCover ? '' : h;
888
+ }
851
889
 
852
890
  if (isVertical) {
853
891
  const transW = offsetW / 2 + 'px ' + offsetW / 2 + 'px 0';
@@ -857,21 +895,65 @@ class Figure extends EditorInjector {
857
895
  }
858
896
 
859
897
  element.style.transformOrigin = transOrigin;
860
- this._setRotate(element, deg, info.x, info.y);
898
+ if (!isVertical) this._setRotate(element, deg, info.x, info.y);
861
899
 
862
900
  if (isVertical) element.style.maxWidth = 'none';
863
901
  else element.style.maxWidth = '';
864
902
 
865
903
  this._setCaptionPosition(element);
866
904
  } finally {
867
- this.__preventSizechange = false;
905
+ this.#preventSizechange = false;
906
+ }
907
+ }
908
+
909
+ /**
910
+ * @private
911
+ * @description Displays or hides the resize handles of the figure component.
912
+ * @param {boolean} display Whether to display resize handles.
913
+ */
914
+ _displayResizeHandles(display) {
915
+ const type = !display ? 'none' : 'flex';
916
+ this.controller.form.style.display = type;
917
+
918
+ const _figure = this.frameContext.get('_figure');
919
+ const resizeHandles = _figure.handles;
920
+ for (let i = 0, len = resizeHandles.length; i < len; i++) {
921
+ resizeHandles[i].style.display = type;
922
+ }
923
+
924
+ if (type === 'none') {
925
+ dom.utils.addClass(_figure.main, 'se-resize-ing');
926
+ this.#onResizeESCEvent = this.eventManager.addGlobalEvent('keydown', this.#containerResizingESC);
927
+ } else {
928
+ dom.utils.removeClass(_figure.main, 'se-resize-ing');
868
929
  }
869
930
  }
870
931
 
932
+ /**
933
+ * @private
934
+ * @description Handles format conversion (block/inline) for the figure component and applies size changes.
935
+ * @param {FigureInfo} figureinfo {target, container, cover, inlineCover, caption}
936
+ * @param {string|number} w Width value.
937
+ * @param {string|number} h Height value.
938
+ */
939
+ _asFormatChange(figureinfo, w, h) {
940
+ const kind = this.kind;
941
+ figureinfo.target.onload = () => this.component.select(figureinfo.target, kind);
942
+
943
+ this._setFigureInfo(figureinfo);
944
+
945
+ if (figureinfo.inlineCover) {
946
+ this.setAlign(figureinfo.target, 'none');
947
+ this.deleteTransform();
948
+ }
949
+
950
+ this.setFigureSize(w, h);
951
+ }
952
+
871
953
  /**
872
954
  * @private
873
955
  * @description Sets figure component properties such as cover, container, caption, and alignment.
874
- * @param {FigureInfo} figureInfo - {target, container, cover, inlineCover, caption}
956
+ * @param {FigureInfo} figureInfo - {target, container, cover, inlineCover, caption, isVertical}
875
957
  */
876
958
  _setFigureInfo(figureInfo) {
877
959
  this._inlineCover = figureInfo.inlineCover;
@@ -881,7 +963,7 @@ class Figure extends EditorInjector {
881
963
  this._element = figureInfo.target;
882
964
  this.align = (this._container.className.match(/(?:^|\s)__se__float-(none|left|center|right)(?:$|\s)/) || [])[1] || figureInfo.target.style.float || 'none';
883
965
  this.as = this._inlineCover ? 'inline' : 'block';
884
- this.isVertical = /^(90|270)$/.test(Math.abs(this.#GetRotateValue(figureInfo.target).r).toString());
966
+ this.isVertical = IsVertical(figureInfo.target);
885
967
  }
886
968
 
887
969
  /**
@@ -943,14 +1025,14 @@ class Figure extends EditorInjector {
943
1025
 
944
1026
  const sizeTarget = this._cover || this._element;
945
1027
 
946
- if (this.autoRatio) this._cover.style.width = w;
1028
+ if (this.autoRatio && this._cover) this._cover.style.width = w;
947
1029
  if (!onlyH) {
948
1030
  sizeTarget.style.width = this._element.style.width = w;
949
1031
  }
950
1032
  if (!onlyW) {
951
1033
  h = numbers.is(h) ? h + this.sizeUnit : h;
952
1034
  sizeTarget.style.height = this._element.style.height = this.autoRatio && !this.isVertical ? '100%' : h;
953
- if (this.autoRatio) {
1035
+ if (this.autoRatio && this._cover) {
954
1036
  this._cover.style.height = h;
955
1037
  this.__setCoverPaddingBottom(w, h);
956
1038
  }
@@ -971,6 +1053,10 @@ class Figure extends EditorInjector {
971
1053
  __setCoverPaddingBottom(w, h) {
972
1054
  if (this._inlineCover === this._cover) return;
973
1055
 
1056
+ if (this.isVertical) {
1057
+ [w, h] = [h, w];
1058
+ }
1059
+
974
1060
  this._cover.style.height = h;
975
1061
  if (/%$/.test(w) && this.align === 'center') {
976
1062
  this._cover.style.paddingBottom = !/%$/.test(h) ? h : numbers.get((numbers.get(h, 2) / 100) * numbers.get(w, 2), 2) + '%';
@@ -994,8 +1080,10 @@ class Figure extends EditorInjector {
994
1080
  this._element.style.maxWidth = '';
995
1081
  this._element.style.width = '';
996
1082
  this._element.style.height = '';
997
- this._cover.style.width = '';
998
- this._cover.style.height = '';
1083
+ if (this._cover) {
1084
+ this._cover.style.width = '';
1085
+ this._cover.style.height = '';
1086
+ }
999
1087
  }
1000
1088
 
1001
1089
  this.setAlign(this._element, this.align);
@@ -1011,7 +1099,7 @@ class Figure extends EditorInjector {
1011
1099
  * @param {string|number} h Height percentage.
1012
1100
  */
1013
1101
  _setPercentSize(w, h) {
1014
- if (!h) h = this.autoRatio ? (/%$/.test(this.autoRatio.current) ? this.autoRatio.current : this.autoRatio.default) : h;
1102
+ h ||= this.autoRatio ? (/%$/.test(this.autoRatio.current) ? this.autoRatio.current : this.autoRatio.default) : h;
1015
1103
  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 : '');
1016
1104
 
1017
1105
  const heightPercentage = /%$/.test(h + '');
@@ -1024,10 +1112,11 @@ class Figure extends EditorInjector {
1024
1112
  return;
1025
1113
  }
1026
1114
 
1027
- if (this._inlineCover !== this._cover) {
1115
+ if (this._inlineCover !== this._cover && this._cover) {
1028
1116
  this._cover.style.width = '100%';
1029
1117
  this._cover.style.height = String(h);
1030
1118
  }
1119
+
1031
1120
  this._element.style.width = '100%';
1032
1121
  this._element.style.maxWidth = '';
1033
1122
  this._element.style.height = String(this.autoRatio ? '100%' : heightPercentage ? '' : h);
@@ -1048,12 +1137,15 @@ class Figure extends EditorInjector {
1048
1137
  * @description Deletes percentage-based sizing from the figure element.
1049
1138
  */
1050
1139
  _deletePercentSize() {
1051
- this._cover.style.width = '';
1052
- this._cover.style.height = '';
1140
+ if (this._cover) {
1141
+ this._cover.style.width = '';
1142
+ this._cover.style.height = '';
1143
+ }
1144
+
1053
1145
  this._container.style.width = '';
1054
1146
  this._container.style.height = '';
1055
1147
 
1056
- dom.utils.removeClass(this._container, this._floatClassStr);
1148
+ dom.utils.removeClass(this._container, this.#floatClassStr);
1057
1149
  dom.utils.addClass(this._container, '__se__float-' + this.align);
1058
1150
 
1059
1151
  if (this.align === 'center') this.setAlign(this._element, this.align);
@@ -1064,7 +1156,7 @@ class Figure extends EditorInjector {
1064
1156
  * @description Reverts the figure element to its previously saved size.
1065
1157
  */
1066
1158
  _setRevert() {
1067
- this.setSize(this.__revertSize.w, this.__revertSize.h);
1159
+ this.setFigureSize(this.#revertSize.w, this.#revertSize.h);
1068
1160
  }
1069
1161
 
1070
1162
  /**
@@ -1090,11 +1182,11 @@ class Figure extends EditorInjector {
1090
1182
  * @description Saves the current size of the figure component.
1091
1183
  */
1092
1184
  _saveCurrentSize() {
1093
- if (this.__preventSizechange) return;
1185
+ if (this.#preventSizechange) return;
1094
1186
 
1095
1187
  const dataSize = (this._element.getAttribute('data-se-size') || ',').split(',');
1096
- this.__revertSize.w = dataSize[0];
1097
- this.__revertSize.h = dataSize[1];
1188
+ this.#revertSize.w = dataSize[0];
1189
+ this.#revertSize.h = dataSize[1];
1098
1190
 
1099
1191
  const size = this.getSize(this._element);
1100
1192
  // add too width, height attribute
@@ -1114,7 +1206,12 @@ class Figure extends EditorInjector {
1114
1206
  _setCaptionPosition(element) {
1115
1207
  const figcaption = /** @type {HTMLElement} */ (dom.query.getEdgeChild(dom.query.getParentElement(element, 'FIGURE'), 'FIGCAPTION', false));
1116
1208
  if (figcaption) {
1117
- figcaption.style.marginTop = (this.isVertical ? element.offsetWidth - element.offsetHeight : 0) + 'px';
1209
+ figcaption.style.marginTop = (this.isVertical && !this.autoRatio ? element.offsetWidth - element.offsetHeight : 0) + 'px';
1210
+ if (this.isVertical && this.autoRatio) {
1211
+ element.style.marginTop = figcaption.offsetHeight + 'px';
1212
+ } else {
1213
+ element.style.marginTop = '';
1214
+ }
1118
1215
  }
1119
1216
  }
1120
1217
 
@@ -1130,29 +1227,6 @@ class Figure extends EditorInjector {
1130
1227
  }
1131
1228
  }
1132
1229
 
1133
- /**
1134
- * @private
1135
- * @description Displays or hides the resize handles of the figure component.
1136
- * @param {boolean} display Whether to display resize handles.
1137
- */
1138
- _displayResizeHandles(display) {
1139
- const type = !display ? 'none' : 'flex';
1140
- this.controller.form.style.display = type;
1141
-
1142
- const _figure = this.editor.frameContext.get('_figure');
1143
- const resizeHandles = _figure.handles;
1144
- for (let i = 0, len = resizeHandles.length; i < len; i++) {
1145
- resizeHandles[i].style.display = type;
1146
- }
1147
-
1148
- if (type === 'none') {
1149
- dom.utils.addClass(_figure.main, 'se-resize-ing');
1150
- this.__onResizeESCEvent = this.eventManager.addGlobalEvent('keydown', this.__containerResizingESC);
1151
- } else {
1152
- dom.utils.removeClass(_figure.main, 'se-resize-ing');
1153
- }
1154
- }
1155
-
1156
1230
  /**
1157
1231
  * @private
1158
1232
  * @description Removes the resize event listeners.
@@ -1161,7 +1235,7 @@ class Figure extends EditorInjector {
1161
1235
  this.component._removeDragEvent();
1162
1236
  this.eventManager.removeGlobalEvent(this.__onContainerEvent);
1163
1237
  this.eventManager.removeGlobalEvent(this.__offContainerEvent);
1164
- this.eventManager.removeGlobalEvent(this.__onResizeESCEvent);
1238
+ this.eventManager.removeGlobalEvent(this.#onResizeESCEvent);
1165
1239
 
1166
1240
  this._displayResizeHandles(true);
1167
1241
  this.ui._offCurrentController();
@@ -1174,7 +1248,7 @@ class Figure extends EditorInjector {
1174
1248
  * @param {Node} figureMain The main figure container element.
1175
1249
  */
1176
1250
  _setDragEvent(figureMain) {
1177
- const dragHandle = this.editor.frameContext.get('wrapper').querySelector('.se-drag-handle');
1251
+ const dragHandle = this.frameContext.get('wrapper').querySelector('.se-drag-handle');
1178
1252
  dom.utils.removeClass(dragHandle, 'se-drag-handle-full');
1179
1253
 
1180
1254
  dragHandle.style.opacity = '';
@@ -1208,15 +1282,17 @@ class Figure extends EditorInjector {
1208
1282
  e.stopPropagation();
1209
1283
  e.preventDefault();
1210
1284
 
1211
- const eventTarget = dom.query.getEventTarget(e);
1212
1285
  const inst = _DragHandle.get('__figureInst');
1286
+ if (!inst) return;
1287
+
1288
+ const eventTarget = dom.query.getEventTarget(e);
1213
1289
  const direction = (inst._resize_direction = eventTarget.classList[0]);
1214
1290
  inst._resizeClientX = e.clientX;
1215
1291
  inst._resizeClientY = e.clientY;
1216
- inst.editor.frameContext.get('_figure').main.style.float = /l/.test(direction) ? 'right' : /r/.test(direction) ? 'left' : 'none';
1292
+ inst.frameContext.get('_figure').main.style.float = /l/.test(direction) ? 'right' : /r/.test(direction) ? 'left' : 'none';
1217
1293
  this.ui.enableBackWrapper(DIRECTION_CURSOR_MAP[direction]);
1218
1294
 
1219
- const { w, h } = this.getSize(inst._element);
1295
+ const { w, h, dw, dh } = this.getSize(inst._element);
1220
1296
  __resizing_p_wh = __resizing_p_ow = false;
1221
1297
  __resizing_cw = __resizing_sw = 0;
1222
1298
  if (!this.isVertical) {
@@ -1231,7 +1307,7 @@ class Figure extends EditorInjector {
1231
1307
  if (__resizing_p_wh || __resizing_p_ow) {
1232
1308
  const sizeTarget = inst._cover || inst._element;
1233
1309
  __resizing_sw = sizeTarget.offsetWidth;
1234
- __resizing_cw = converter.getWidthInPercentage(sizeTarget, this.editor.frameContext.get('wysiwygFrame')) / 100;
1310
+ __resizing_cw = converter.getWidthInPercentage(sizeTarget, this.frameContext.get('wysiwygFrame')) / 100;
1235
1311
  }
1236
1312
  }
1237
1313
 
@@ -1239,9 +1315,9 @@ class Figure extends EditorInjector {
1239
1315
  inst.__offContainerEvent = inst.eventManager.addGlobalEvent('mouseup', inst.__containerResizingOff);
1240
1316
  inst._displayResizeHandles(false);
1241
1317
 
1242
- const _display = this.editor.frameContext.get('_figure').display;
1318
+ const _display = this.frameContext.get('_figure').display;
1243
1319
  _display.style.display = 'block';
1244
- dom.utils.changeTxt(_display, w + ' x ' + h);
1320
+ dom.utils.changeTxt(_display, dw + ' * ' + dh);
1245
1321
  }
1246
1322
 
1247
1323
  /**
@@ -1252,14 +1328,15 @@ class Figure extends EditorInjector {
1252
1328
  const direction = this._resize_direction;
1253
1329
  const clientX = e.clientX;
1254
1330
  const clientY = e.clientY;
1331
+ const v = this.isVertical;
1255
1332
 
1256
- let resultW = this._element_w;
1257
- let resultH = this._element_h;
1333
+ let resultW = v ? this.#element_h : this.#element_w;
1334
+ let resultH = v ? this.#element_w : this.#element_h;
1258
1335
 
1259
1336
  const w = resultW + (/r/.test(direction) ? clientX - this._resizeClientX : this._resizeClientX - clientX);
1260
1337
  const h = resultH + (/b/.test(direction) ? clientY - this._resizeClientY : this._resizeClientY - clientY);
1261
1338
  const wh = (resultH / resultW) * w;
1262
- const resizeBorder = this.editor.frameContext.get('_figure').border;
1339
+ const resizeBorder = this.frameContext.get('_figure').border;
1263
1340
 
1264
1341
  if (/t/.test(direction)) resizeBorder.style.top = resultH - (/h/.test(direction) ? h : wh) + 'px';
1265
1342
  if (/l/.test(direction)) resizeBorder.style.left = resultW - w + 'px';
@@ -1277,10 +1354,13 @@ class Figure extends EditorInjector {
1277
1354
  resultH = h;
1278
1355
  }
1279
1356
 
1280
- this._resize_w = /** @type {number} */ (/h$/.test(direction) ? this._width : Math.round(resultW));
1281
- this._resize_h = /** @type {number} */ (/w$/.test(direction) ? this._height : Math.round(resultH));
1282
- const rw = __resizing_cw ? (this._resize_w / __resizing_sw) * __resizing_cw * 100 : this._resize_w;
1283
- 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);
1357
+ const resize_w = /** @type {number} */ (!v && /h$/.test(direction) ? this.#width : Math.round(resultW));
1358
+ const resize_h = /** @type {number} */ (!v && /w$/.test(direction) ? this.#height : Math.round(resultH));
1359
+ const rw = __resizing_cw ? (resize_w / __resizing_sw) * __resizing_cw * 100 : resize_w;
1360
+ dom.utils.changeTxt(this.frameContext.get('_figure').display, __resizing_cw ? numbers.get(rw > 100 ? 100 : rw, 2).toFixed(2) + '%' : rw + ' * ' + resize_h);
1361
+
1362
+ this.#resize_w = resize_w;
1363
+ this.#resize_h = resize_h;
1284
1364
  }
1285
1365
 
1286
1366
  /**
@@ -1290,16 +1370,16 @@ class Figure extends EditorInjector {
1290
1370
  this._offResizeEvent();
1291
1371
 
1292
1372
  // set size
1293
- let w = this.isVertical ? this._resize_h : this._resize_w;
1294
- let h = this.isVertical ? this._resize_w : this._resize_h;
1373
+ let w = this.isVertical ? this.#resize_h : this.#resize_w;
1374
+ let h = this.isVertical ? this.#resize_w : this.#resize_h;
1295
1375
  w = Math.round(w) || w;
1296
1376
  h = Math.round(h) || h;
1297
1377
 
1298
1378
  if (!this.isVertical && !/%$/.test(w + '')) {
1299
1379
  const limit =
1300
- this.editor.frameContext.get('wysiwygFrame').clientWidth -
1301
- numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-left')) +
1302
- numbers.get(this.editor.frameContext.get('wwComputedStyle').getPropertyValue('padding-right')) -
1380
+ this.frameContext.get('wysiwygFrame').clientWidth -
1381
+ numbers.get(this.frameContext.get('wwComputedStyle').getPropertyValue('padding-left')) +
1382
+ numbers.get(this.frameContext.get('wwComputedStyle').getPropertyValue('padding-right')) -
1303
1383
  2;
1304
1384
  if (numbers.get(w, 0) > limit) {
1305
1385
  h = Math.round((h / w) * limit);
@@ -1371,7 +1451,7 @@ class Figure extends EditorInjector {
1371
1451
  }
1372
1452
 
1373
1453
  #OffFigureContainer() {
1374
- this.editor.frameContext.get('_figure').main.style.display = 'none';
1454
+ this.frameContext.get('_figure').main.style.display = 'none';
1375
1455
  this.editor._figureContainer = null;
1376
1456
  }
1377
1457
 
@@ -1404,20 +1484,28 @@ class Figure extends EditorInjector {
1404
1484
 
1405
1485
  this.selectMenu_resize.open('', '[data-command="' + command + '"]');
1406
1486
  }
1487
+ }
1407
1488
 
1408
- /**
1409
- * @param {Node} element Target element
1410
- * @returns {{ r: *, x: *, y: * }} Rotation value
1411
- */
1412
- #GetRotateValue(element) {
1413
- const transform = /** @type {HTMLElement} */ (element).style.transform;
1414
- if (!transform) return { r: 0, x: '', y: '' };
1415
- return {
1416
- r: Number((transform.match(/rotate\(([-0-9]+)deg\)/) || [])[1] || 0),
1417
- x: (transform.match(/rotateX\(([-0-9]+)deg\)/) || [])[1] || '',
1418
- y: (transform.match(/rotateY\(([-0-9]+)deg\)/) || [])[1] || ''
1419
- };
1420
- }
1489
+ /**
1490
+ * @param {Node} element Target element
1491
+ * @returns {{ r: *, x: *, y: * }} Rotation value
1492
+ */
1493
+ function GetRotateValue(element) {
1494
+ const transform = /** @type {HTMLElement} */ (element).style.transform;
1495
+ if (!transform) return { r: 0, x: '', y: '' };
1496
+ return {
1497
+ r: Number((transform.match(/rotate\(([-0-9]+)deg\)/) || [])[1] || 0),
1498
+ x: (transform.match(/rotateX\(([-0-9]+)deg\)/) || [])[1] || '',
1499
+ y: (transform.match(/rotateY\(([-0-9]+)deg\)/) || [])[1] || ''
1500
+ };
1501
+ }
1502
+
1503
+ /**
1504
+ * @param {Node|number} elementOrDeg Target element
1505
+ * @returns {boolean} Whether to rotate vertically
1506
+ */
1507
+ function IsVertical(elementOrDeg) {
1508
+ return /^(90|270)$/.test(Math.abs(numbers.is(elementOrDeg) ? elementOrDeg : GetRotateValue(/** @type{Node} */ (elementOrDeg)).r).toString());
1421
1509
  }
1422
1510
 
1423
1511
  function CreateAlign(inst, button) {