suneditor 3.0.0-beta.9 → 3.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +65 -57
  2. package/dist/suneditor-contents.min.css +1 -0
  3. package/dist/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +1 -1
  5. package/package.json +110 -61
  6. package/src/assets/design/color.css +36 -17
  7. package/src/assets/design/size.css +2 -0
  8. package/src/assets/icons/defaultIcons.js +17 -2
  9. package/src/assets/suneditor-contents.css +51 -16
  10. package/src/assets/suneditor.css +116 -43
  11. package/src/core/config/contextProvider.js +288 -0
  12. package/src/core/config/eventManager.js +188 -0
  13. package/src/core/config/instanceCheck.js +59 -0
  14. package/src/core/config/optionProvider.js +452 -0
  15. package/src/core/editor.js +166 -1637
  16. package/src/core/event/actions/index.js +229 -0
  17. package/src/core/event/effects/common.registry.js +74 -0
  18. package/src/core/event/effects/keydown.registry.js +573 -0
  19. package/src/core/event/effects/ruleHelpers.js +148 -0
  20. package/src/core/event/eventOrchestrator.js +944 -0
  21. package/src/core/event/executor.js +27 -0
  22. package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +27 -28
  23. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +10 -8
  24. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +22 -23
  25. package/src/core/event/handlers/handler_ww_input.js +75 -0
  26. package/src/core/event/handlers/handler_ww_key.js +228 -0
  27. package/src/core/event/handlers/handler_ww_mouse.js +166 -0
  28. package/src/core/event/ports.js +211 -0
  29. package/src/core/event/reducers/keydown.reducer.js +97 -0
  30. package/src/core/event/rules/keydown.rule.arrow.js +63 -0
  31. package/src/core/event/rules/keydown.rule.backspace.js +208 -0
  32. package/src/core/event/rules/keydown.rule.delete.js +132 -0
  33. package/src/core/event/rules/keydown.rule.enter.js +150 -0
  34. package/src/core/event/rules/keydown.rule.tab.js +35 -0
  35. package/src/core/event/support/defaultLineManager.js +136 -0
  36. package/src/core/event/support/selectionState.js +204 -0
  37. package/src/core/kernel/coreKernel.js +320 -0
  38. package/src/core/kernel/kernelInjector.js +19 -0
  39. package/src/core/kernel/store.js +173 -0
  40. package/src/core/{class → logic/dom}/char.js +42 -45
  41. package/src/core/logic/dom/format.js +1075 -0
  42. package/src/core/{class → logic/dom}/html.js +743 -624
  43. package/src/core/logic/dom/inline.js +1847 -0
  44. package/src/core/logic/dom/listFormat.js +601 -0
  45. package/src/core/{class → logic/dom}/nodeTransform.js +92 -72
  46. package/src/core/{class → logic/dom}/offset.js +254 -317
  47. package/src/core/logic/dom/selection.js +754 -0
  48. package/src/core/logic/panel/menu.js +389 -0
  49. package/src/core/logic/panel/toolbar.js +449 -0
  50. package/src/core/logic/panel/viewer.js +761 -0
  51. package/src/core/logic/shell/_commandExecutor.js +380 -0
  52. package/src/core/logic/shell/commandDispatcher.js +241 -0
  53. package/src/core/logic/shell/component.js +970 -0
  54. package/src/core/logic/shell/focusManager.js +110 -0
  55. package/src/core/{base → logic/shell}/history.js +110 -60
  56. package/src/core/logic/shell/pluginManager.js +363 -0
  57. package/src/core/logic/shell/shortcuts.js +130 -0
  58. package/src/core/logic/shell/ui.js +904 -0
  59. package/src/core/schema/context.js +66 -0
  60. package/src/core/schema/frameContext.js +160 -0
  61. package/src/core/schema/options.js +628 -0
  62. package/src/core/section/constructor.js +194 -500
  63. package/src/core/section/documentType.js +297 -222
  64. package/src/events.js +808 -543
  65. package/src/helper/clipboard.js +27 -16
  66. package/src/helper/converter.js +100 -78
  67. package/src/helper/dom/domCheck.js +56 -30
  68. package/src/helper/dom/domQuery.js +159 -89
  69. package/src/helper/dom/domUtils.js +114 -49
  70. package/src/helper/dom/index.js +5 -1
  71. package/src/helper/env.js +26 -26
  72. package/src/helper/index.js +1 -1
  73. package/src/helper/keyCodeMap.js +25 -28
  74. package/src/helper/numbers.js +4 -8
  75. package/src/helper/unicode.js +4 -8
  76. package/src/hooks/base.js +307 -0
  77. package/src/hooks/params.js +130 -0
  78. package/src/interfaces/contracts.js +227 -0
  79. package/src/interfaces/index.js +7 -0
  80. package/src/interfaces/plugins.js +239 -0
  81. package/src/langs/ckb.js +4 -4
  82. package/src/langs/cs.js +4 -4
  83. package/src/langs/da.js +4 -4
  84. package/src/langs/de.js +4 -4
  85. package/src/langs/en.js +4 -4
  86. package/src/langs/es.js +4 -4
  87. package/src/langs/fa.js +4 -4
  88. package/src/langs/fr.js +4 -4
  89. package/src/langs/he.js +4 -4
  90. package/src/langs/hu.js +4 -4
  91. package/src/langs/it.js +4 -4
  92. package/src/langs/ja.js +4 -4
  93. package/src/langs/km.js +4 -4
  94. package/src/langs/ko.js +4 -4
  95. package/src/langs/lv.js +4 -4
  96. package/src/langs/nl.js +4 -4
  97. package/src/langs/pl.js +4 -4
  98. package/src/langs/pt_br.js +13 -13
  99. package/src/langs/ro.js +4 -4
  100. package/src/langs/ru.js +4 -4
  101. package/src/langs/se.js +4 -4
  102. package/src/langs/tr.js +4 -4
  103. package/src/langs/uk.js +4 -4
  104. package/src/langs/ur.js +4 -4
  105. package/src/langs/zh_cn.js +4 -4
  106. package/src/modules/{Browser.js → contract/Browser.js} +119 -128
  107. package/src/modules/{ColorPicker.js → contract/ColorPicker.js} +132 -142
  108. package/src/modules/contract/Controller.js +589 -0
  109. package/src/modules/{Figure.js → contract/Figure.js} +591 -411
  110. package/src/modules/{HueSlider.js → contract/HueSlider.js} +125 -86
  111. package/src/modules/contract/Modal.js +357 -0
  112. package/src/modules/contract/index.js +9 -0
  113. package/src/modules/manager/ApiManager.js +197 -0
  114. package/src/modules/{FileManager.js → manager/FileManager.js} +128 -160
  115. package/src/modules/manager/index.js +5 -0
  116. package/src/modules/{ModalAnchorEditor.js → ui/ModalAnchorEditor.js} +108 -138
  117. package/src/modules/{SelectMenu.js → ui/SelectMenu.js} +119 -120
  118. package/src/modules/{_DragHandle.js → ui/_DragHandle.js} +1 -1
  119. package/src/modules/ui/index.js +6 -0
  120. package/src/plugins/browser/audioGallery.js +23 -26
  121. package/src/plugins/browser/fileBrowser.js +25 -28
  122. package/src/plugins/browser/fileGallery.js +20 -23
  123. package/src/plugins/browser/imageGallery.js +24 -23
  124. package/src/plugins/browser/videoGallery.js +27 -29
  125. package/src/plugins/command/blockquote.js +11 -17
  126. package/src/plugins/command/exportPDF.js +26 -26
  127. package/src/plugins/command/fileUpload.js +138 -133
  128. package/src/plugins/command/list_bulleted.js +48 -44
  129. package/src/plugins/command/list_numbered.js +48 -44
  130. package/src/plugins/dropdown/align.js +64 -50
  131. package/src/plugins/dropdown/backgroundColor.js +34 -35
  132. package/src/plugins/dropdown/{formatBlock.js → blockStyle.js} +43 -37
  133. package/src/plugins/dropdown/font.js +50 -36
  134. package/src/plugins/dropdown/fontColor.js +34 -35
  135. package/src/plugins/dropdown/hr.js +55 -50
  136. package/src/plugins/dropdown/layout.js +20 -15
  137. package/src/plugins/dropdown/lineHeight.js +46 -30
  138. package/src/plugins/dropdown/list.js +32 -33
  139. package/src/plugins/dropdown/paragraphStyle.js +40 -34
  140. package/src/plugins/dropdown/table/index.js +915 -0
  141. package/src/plugins/dropdown/table/render/table.html.js +308 -0
  142. package/src/plugins/dropdown/table/render/table.menu.js +121 -0
  143. package/src/plugins/dropdown/table/services/table.cell.js +465 -0
  144. package/src/plugins/dropdown/table/services/table.clipboard.js +414 -0
  145. package/src/plugins/dropdown/table/services/table.grid.js +504 -0
  146. package/src/plugins/dropdown/table/services/table.resize.js +463 -0
  147. package/src/plugins/dropdown/table/services/table.selection.js +466 -0
  148. package/src/plugins/dropdown/table/services/table.style.js +844 -0
  149. package/src/plugins/dropdown/table/shared/table.constants.js +109 -0
  150. package/src/plugins/dropdown/table/shared/table.utils.js +219 -0
  151. package/src/plugins/dropdown/template.js +20 -15
  152. package/src/plugins/dropdown/textStyle.js +28 -22
  153. package/src/plugins/field/mention.js +54 -49
  154. package/src/plugins/index.js +5 -5
  155. package/src/plugins/input/fontSize.js +100 -97
  156. package/src/plugins/input/pageNavigator.js +13 -10
  157. package/src/plugins/modal/audio.js +208 -219
  158. package/src/plugins/modal/drawing.js +99 -104
  159. package/src/plugins/modal/embed.js +323 -312
  160. package/src/plugins/modal/image/index.js +942 -0
  161. package/src/plugins/modal/image/render/image.html.js +150 -0
  162. package/src/plugins/modal/image/services/image.size.js +198 -0
  163. package/src/plugins/modal/image/services/image.upload.js +216 -0
  164. package/src/plugins/modal/image/shared/image.constants.js +20 -0
  165. package/src/plugins/modal/link.js +74 -54
  166. package/src/plugins/modal/math.js +126 -119
  167. package/src/plugins/modal/video/index.js +858 -0
  168. package/src/plugins/modal/video/render/video.html.js +131 -0
  169. package/src/plugins/modal/video/services/video.size.js +281 -0
  170. package/src/plugins/modal/video/services/video.upload.js +92 -0
  171. package/src/plugins/popup/anchor.js +57 -49
  172. package/src/suneditor.js +73 -61
  173. package/src/themes/cobalt.css +155 -0
  174. package/src/themes/dark.css +143 -120
  175. package/src/typedef.js +214 -63
  176. package/types/assets/icons/defaultIcons.d.ts +8 -0
  177. package/types/assets/suneditor-contents.css.d.ts +1 -0
  178. package/types/assets/suneditor.css.d.ts +1 -0
  179. package/types/core/config/contextProvider.d.ts +148 -0
  180. package/types/core/config/eventManager.d.ts +68 -0
  181. package/types/core/config/instanceCheck.d.ts +33 -0
  182. package/types/core/config/optionProvider.d.ts +147 -0
  183. package/types/core/editor.d.ts +27 -586
  184. package/types/core/event/actions/index.d.ts +50 -0
  185. package/types/core/event/effects/common.registry.d.ts +56 -0
  186. package/types/core/event/effects/keydown.registry.d.ts +80 -0
  187. package/types/core/event/effects/ruleHelpers.d.ts +36 -0
  188. package/types/core/event/eventOrchestrator.d.ts +191 -0
  189. package/types/core/event/executor.d.ts +13 -0
  190. package/types/core/event/handlers/handler_toolbar.d.ts +38 -0
  191. package/types/core/event/handlers/handler_ww_clipboard.d.ts +36 -0
  192. package/types/core/event/handlers/handler_ww_dragDrop.d.ts +26 -0
  193. package/types/core/event/handlers/handler_ww_input.d.ts +38 -0
  194. package/types/core/event/handlers/handler_ww_key.d.ts +40 -0
  195. package/types/core/event/handlers/handler_ww_mouse.d.ts +47 -0
  196. package/types/core/event/ports.d.ts +256 -0
  197. package/types/core/event/reducers/keydown.reducer.d.ts +84 -0
  198. package/types/core/event/rules/keydown.rule.arrow.d.ts +19 -0
  199. package/types/core/event/rules/keydown.rule.backspace.d.ts +18 -0
  200. package/types/core/event/rules/keydown.rule.delete.d.ts +18 -0
  201. package/types/core/event/rules/keydown.rule.enter.d.ts +18 -0
  202. package/types/core/event/rules/keydown.rule.tab.d.ts +18 -0
  203. package/types/core/event/support/defaultLineManager.d.ts +22 -0
  204. package/types/core/event/support/selectionState.d.ts +29 -0
  205. package/types/core/kernel/coreKernel.d.ts +219 -0
  206. package/types/core/kernel/kernelInjector.d.ts +16 -0
  207. package/types/core/kernel/store.d.ts +170 -0
  208. package/types/core/logic/dom/char.d.ts +46 -0
  209. package/types/core/logic/dom/format.d.ts +234 -0
  210. package/types/core/logic/dom/html.d.ts +290 -0
  211. package/types/core/logic/dom/inline.d.ts +93 -0
  212. package/types/core/logic/dom/listFormat.d.ts +101 -0
  213. package/types/core/logic/dom/nodeTransform.d.ts +110 -0
  214. package/types/core/logic/dom/offset.d.ts +335 -0
  215. package/types/core/logic/dom/selection.d.ts +165 -0
  216. package/types/core/logic/panel/menu.d.ts +93 -0
  217. package/types/core/logic/panel/toolbar.d.ts +128 -0
  218. package/types/core/logic/panel/viewer.d.ts +89 -0
  219. package/types/core/logic/shell/_commandExecutor.d.ts +18 -0
  220. package/types/core/logic/shell/commandDispatcher.d.ts +65 -0
  221. package/types/core/logic/shell/component.d.ts +182 -0
  222. package/types/core/logic/shell/focusManager.d.ts +31 -0
  223. package/types/core/{base → logic/shell}/history.d.ts +13 -12
  224. package/types/core/logic/shell/pluginManager.d.ts +115 -0
  225. package/types/core/logic/shell/shortcuts.d.ts +131 -0
  226. package/types/core/logic/shell/ui.d.ts +261 -0
  227. package/types/core/schema/context.d.ts +104 -0
  228. package/types/core/schema/frameContext.d.ts +320 -0
  229. package/types/core/schema/options.d.ts +1241 -0
  230. package/types/core/section/constructor.d.ts +117 -652
  231. package/types/core/section/documentType.d.ts +43 -61
  232. package/types/events.d.ts +796 -65
  233. package/types/helper/clipboard.d.ts +5 -4
  234. package/types/helper/converter.d.ts +55 -43
  235. package/types/helper/dom/domCheck.d.ts +27 -19
  236. package/types/helper/dom/domQuery.d.ts +76 -57
  237. package/types/helper/dom/domUtils.d.ts +62 -39
  238. package/types/helper/dom/index.d.ts +87 -1
  239. package/types/helper/env.d.ts +16 -13
  240. package/types/helper/index.d.ts +8 -2
  241. package/types/helper/keyCodeMap.d.ts +24 -23
  242. package/types/helper/numbers.d.ts +4 -6
  243. package/types/helper/unicode.d.ts +4 -3
  244. package/types/hooks/base.d.ts +239 -0
  245. package/types/hooks/params.d.ts +65 -0
  246. package/types/index.d.ts +20 -117
  247. package/types/interfaces/contracts.d.ts +183 -0
  248. package/types/interfaces/index.d.ts +3 -0
  249. package/types/interfaces/plugins.d.ts +168 -0
  250. package/types/langs/_Lang.d.ts +2 -2
  251. package/types/langs/index.d.ts +2 -2
  252. package/types/modules/contract/Browser.d.ts +262 -0
  253. package/types/modules/contract/ColorPicker.d.ts +99 -0
  254. package/types/modules/contract/Controller.d.ts +204 -0
  255. package/types/modules/contract/Figure.d.ts +529 -0
  256. package/types/modules/{HueSlider.d.ts → contract/HueSlider.d.ts} +39 -28
  257. package/types/modules/contract/Modal.d.ts +62 -0
  258. package/types/modules/contract/index.d.ts +7 -0
  259. package/types/modules/manager/ApiManager.d.ts +106 -0
  260. package/types/modules/manager/FileManager.d.ts +124 -0
  261. package/types/modules/manager/index.d.ts +3 -0
  262. package/types/modules/ui/ModalAnchorEditor.d.ts +152 -0
  263. package/types/modules/ui/SelectMenu.d.ts +107 -0
  264. package/types/modules/{_DragHandle.d.ts → ui/_DragHandle.d.ts} +1 -0
  265. package/types/modules/ui/index.d.ts +4 -0
  266. package/types/plugins/browser/audioGallery.d.ts +33 -41
  267. package/types/plugins/browser/fileBrowser.d.ts +42 -50
  268. package/types/plugins/browser/fileGallery.d.ts +33 -41
  269. package/types/plugins/browser/imageGallery.d.ts +30 -37
  270. package/types/plugins/browser/videoGallery.d.ts +33 -41
  271. package/types/plugins/command/blockquote.d.ts +4 -21
  272. package/types/plugins/command/exportPDF.d.ts +23 -33
  273. package/types/plugins/command/fileUpload.d.ts +80 -100
  274. package/types/plugins/command/list_bulleted.d.ts +9 -35
  275. package/types/plugins/command/list_numbered.d.ts +9 -35
  276. package/types/plugins/dropdown/align.d.ts +23 -46
  277. package/types/plugins/dropdown/backgroundColor.d.ts +35 -53
  278. package/types/plugins/dropdown/blockStyle.d.ts +45 -0
  279. package/types/plugins/dropdown/font.d.ts +18 -41
  280. package/types/plugins/dropdown/fontColor.d.ts +35 -53
  281. package/types/plugins/dropdown/hr.d.ts +26 -52
  282. package/types/plugins/dropdown/layout.d.ts +19 -25
  283. package/types/plugins/dropdown/lineHeight.d.ts +21 -39
  284. package/types/plugins/dropdown/list.d.ts +6 -34
  285. package/types/plugins/dropdown/paragraphStyle.d.ts +34 -45
  286. package/types/plugins/dropdown/table/index.d.ts +158 -0
  287. package/types/plugins/dropdown/table/render/table.html.d.ts +71 -0
  288. package/types/plugins/dropdown/table/render/table.menu.d.ts +59 -0
  289. package/types/plugins/dropdown/table/services/table.cell.d.ts +76 -0
  290. package/types/plugins/dropdown/table/services/table.clipboard.d.ts +26 -0
  291. package/types/plugins/dropdown/table/services/table.grid.d.ts +77 -0
  292. package/types/plugins/dropdown/table/services/table.resize.d.ts +72 -0
  293. package/types/plugins/dropdown/table/services/table.selection.d.ts +59 -0
  294. package/types/plugins/dropdown/table/services/table.style.d.ts +162 -0
  295. package/types/plugins/dropdown/table/shared/table.constants.d.ts +134 -0
  296. package/types/plugins/dropdown/table/shared/table.utils.d.ts +91 -0
  297. package/types/plugins/dropdown/template.d.ts +19 -25
  298. package/types/plugins/dropdown/textStyle.d.ts +23 -30
  299. package/types/plugins/field/mention.d.ts +66 -72
  300. package/types/plugins/index.d.ts +41 -40
  301. package/types/plugins/input/fontSize.d.ts +57 -96
  302. package/types/plugins/input/pageNavigator.d.ts +5 -8
  303. package/types/plugins/modal/audio.d.ts +60 -153
  304. package/types/plugins/modal/drawing.d.ts +16 -118
  305. package/types/plugins/modal/embed.d.ts +46 -166
  306. package/types/plugins/modal/image/index.d.ts +281 -0
  307. package/types/plugins/modal/image/render/image.html.d.ts +45 -0
  308. package/types/plugins/modal/image/services/image.size.d.ts +55 -0
  309. package/types/plugins/modal/image/services/image.upload.d.ts +24 -0
  310. package/types/plugins/modal/image/shared/image.constants.d.ts +17 -0
  311. package/types/plugins/modal/link.d.ts +46 -66
  312. package/types/plugins/modal/math.d.ts +17 -86
  313. package/types/plugins/modal/{video.d.ts → video/index.d.ts} +89 -221
  314. package/types/plugins/modal/video/render/video.html.d.ts +37 -0
  315. package/types/plugins/modal/video/services/video.size.d.ts +74 -0
  316. package/types/plugins/modal/video/services/video.upload.d.ts +19 -0
  317. package/types/plugins/popup/anchor.d.ts +8 -38
  318. package/types/suneditor.d.ts +55 -24
  319. package/types/typedef.d.ts +344 -228
  320. package/CONTRIBUTING.md +0 -186
  321. package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
  322. package/src/core/base/eventHandlers/handler_ww_mouse.js +0 -194
  323. package/src/core/base/eventManager.js +0 -1523
  324. package/src/core/class/component.js +0 -856
  325. package/src/core/class/format.js +0 -3433
  326. package/src/core/class/menu.js +0 -346
  327. package/src/core/class/selection.js +0 -610
  328. package/src/core/class/shortcuts.js +0 -98
  329. package/src/core/class/toolbar.js +0 -431
  330. package/src/core/class/ui.js +0 -424
  331. package/src/core/class/viewer.js +0 -750
  332. package/src/core/section/actives.js +0 -266
  333. package/src/core/section/context.js +0 -102
  334. package/src/editorInjector/_classes.js +0 -36
  335. package/src/editorInjector/_core.js +0 -87
  336. package/src/editorInjector/index.js +0 -73
  337. package/src/modules/ApiManager.js +0 -191
  338. package/src/modules/Controller.js +0 -474
  339. package/src/modules/Modal.js +0 -346
  340. package/src/modules/index.js +0 -14
  341. package/src/plugins/dropdown/table.js +0 -4034
  342. package/src/plugins/modal/image.js +0 -1376
  343. package/src/plugins/modal/video.js +0 -1226
  344. package/types/core/base/eventHandlers/handler_toolbar.d.ts +0 -41
  345. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +0 -40
  346. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +0 -35
  347. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +0 -45
  348. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +0 -39
  349. package/types/core/base/eventManager.d.ts +0 -401
  350. package/types/core/class/char.d.ts +0 -61
  351. package/types/core/class/component.d.ts +0 -213
  352. package/types/core/class/format.d.ts +0 -623
  353. package/types/core/class/html.d.ts +0 -430
  354. package/types/core/class/menu.d.ts +0 -126
  355. package/types/core/class/nodeTransform.d.ts +0 -93
  356. package/types/core/class/offset.d.ts +0 -522
  357. package/types/core/class/selection.d.ts +0 -188
  358. package/types/core/class/shortcuts.d.ts +0 -142
  359. package/types/core/class/toolbar.d.ts +0 -189
  360. package/types/core/class/ui.d.ts +0 -164
  361. package/types/core/class/viewer.d.ts +0 -140
  362. package/types/core/section/actives.d.ts +0 -46
  363. package/types/core/section/context.d.ts +0 -45
  364. package/types/editorInjector/_classes.d.ts +0 -41
  365. package/types/editorInjector/_core.d.ts +0 -87
  366. package/types/editorInjector/index.d.ts +0 -69
  367. package/types/modules/ApiManager.d.ts +0 -125
  368. package/types/modules/Browser.d.ts +0 -326
  369. package/types/modules/ColorPicker.d.ts +0 -135
  370. package/types/modules/Controller.d.ts +0 -251
  371. package/types/modules/Figure.d.ts +0 -517
  372. package/types/modules/FileManager.d.ts +0 -202
  373. package/types/modules/Modal.d.ts +0 -111
  374. package/types/modules/ModalAnchorEditor.d.ts +0 -236
  375. package/types/modules/SelectMenu.d.ts +0 -194
  376. package/types/modules/index.d.ts +0 -26
  377. package/types/plugins/dropdown/formatBlock.d.ts +0 -55
  378. package/types/plugins/dropdown/table.d.ts +0 -627
  379. package/types/plugins/modal/image.d.ts +0 -451
  380. /package/{LICENSE → LICENSE.txt} +0 -0
@@ -1,15 +1,7 @@
1
- import EditorInjector from '../../editorInjector';
2
- import { Modal, Figure } from '../../modules';
1
+ import { PluginModal } from '../../interfaces';
2
+ import { Modal, Figure } from '../../modules/contract';
3
3
  import { dom, numbers, env, keyCodeMap } from '../../helper';
4
- const { NO_EVENT } = env;
5
-
6
- /**
7
- * @typedef {import('../../events').ProcessInfo} ProcessInfo_embed
8
- */
9
-
10
- /**
11
- * @typedef {import('../../modules/Figure').FigureControls} FigureControls_embed
12
- */
4
+ const { _w, NO_EVENT } = env;
13
5
 
14
6
  /**
15
7
  * @typedef {Object} EmbedPluginOptions
@@ -22,7 +14,7 @@ const { NO_EVENT } = env;
22
14
  * @property {Object<string, string>} [uploadHeaders] - Headers to include in file upload requests.
23
15
  * @property {number} [uploadSizeLimit] - The total file upload size limit in bytes.
24
16
  * @property {number} [uploadSingleSizeLimit] - The single file upload size limit in bytes.
25
- * @property {Object<string, string>} [iframeTagAttributes] - Additional attributes to set on the iframe tag.
17
+ * @property {Object<string, string>} [iframeTagAttributes] - Additional attributes to set on the `IFRAME` tag.
26
18
  * @property {string} [query_youtube] - YouTube query parameter.
27
19
  * @property {string} [query_vimeo] - Vimeo query parameter.
28
20
  * @property {Array<RegExp>} [urlPatterns] - Additional URL patterns for embed.
@@ -45,43 +37,104 @@ const { NO_EVENT } = env;
45
37
  * },
46
38
  * // Additional services...
47
39
  * }
48
- * @property {FigureControls_embed} [controls] - Figure controls.
40
+ * @property {SunEditor.Module.Figure.Controls} [controls] - Figure controls.
41
+ * @property {SunEditor.ComponentInsertType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: `options.get('componentInsertBehavior')`]
42
+ * - `auto`: Move cursor to the next line if possible, otherwise select the component.
43
+ * - `select`: Always select the inserted component.
44
+ * - `line`: Move cursor to the next line if possible, or create a new line and move there.
45
+ * - `none`: Do nothing.
49
46
  */
50
47
 
51
48
  /**
52
49
  * @class
53
50
  * @description Embed modal plugin.
54
- * - This plugin provides a modal interface for embedding external content (e.g., videos, iframes) into the editor.
51
+ * - This plugin provides a modal interface for embedding external content (e.g., videos, `IFRAME` elements) into the editor.
55
52
  */
56
- class Embed extends EditorInjector {
53
+ class Embed extends PluginModal {
57
54
  static key = 'embed';
58
- static type = 'modal';
59
55
  static className = '';
56
+
60
57
  /**
61
- * @this {Embed}
62
58
  * @param {HTMLElement} node - The node to check.
63
59
  * @returns {HTMLElement|null} Returns a node if the node is a valid component.
64
60
  */
65
61
  static component(node) {
62
+ const children = node.children;
66
63
  let src = '';
67
- if (dom.check.isIFrame(node)) src = node.src;
68
- if (/^DIV$/i.test(node?.nodeName) && dom.check.isIFrame(node.firstElementChild)) src = node.firstElementChild.src;
64
+ let target = null;
65
+
66
+ if (dom.check.isIFrame(node)) {
67
+ target = node;
68
+ src = node.src;
69
+ }
70
+ if (!src && /^DIV$/i.test(node?.nodeName) && dom.check.isIFrame(children[0])) {
71
+ target = children[0];
72
+ src = target.src;
73
+ }
74
+ if (!src && dom.utils.hasClass(node, 'se-embed-container')) {
75
+ /** @type {*} */
76
+ const srcNode = dom.query.getChildNode(node, (current) => current.src || current.href);
77
+ target = srcNode;
78
+ src = target?.src || target?.href;
79
+ }
80
+
81
+ if (/^BLOCKQUOTE$/i.test(node?.nodeName)) {
82
+ const link = node.querySelector('a');
83
+ if (link && link.href) {
84
+ target = node;
85
+ src = link.href;
86
+ return this.#checkContentType(src) ? target : null;
87
+ }
88
+ }
69
89
 
70
90
  if (src) {
71
- return this.checkContentType(src) ? node : null;
91
+ return this.#checkContentType(src) ? target : null;
72
92
  }
73
- return null;
93
+
94
+ return target;
74
95
  }
75
96
 
97
+ /**
98
+ * @description Checks if the given URL matches any of the defined URL patterns.
99
+ * @param {string} url - The URL to check.
100
+ * @returns {boolean} `true` if the URL matches a known pattern; otherwise, `false`.
101
+ */
102
+ static #checkContentType(url) {
103
+ url = url?.toLowerCase() || '';
104
+ if (this.#urlPatterns.some((pattern) => pattern.test(url))) {
105
+ return true;
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ /** @type {Array<RegExp>} */
112
+ static #urlPatterns = null;
113
+
114
+ #defaultSizeX;
115
+ #defaultSizeY;
116
+ #origin_w;
117
+ #origin_h;
118
+ #resizing;
119
+ #onlyPercentage;
120
+ #nonResizing;
121
+
122
+ #linkValue = '';
123
+ #align = 'none';
124
+ #element = null;
125
+ #cover = null;
126
+ #container = null;
127
+ #ratio = { w: 0, h: 0 };
128
+
76
129
  /**
77
130
  * @constructor
78
- * @param {__se__EditorCore} editor - The root editor instance
131
+ * @param {SunEditor.Kernel} editor - The core kernel
79
132
  * @param {EmbedPluginOptions} pluginOptions
80
133
  */
81
134
  constructor(editor, pluginOptions) {
82
- // plugin bisic properties
135
+ // plugin basic properties
83
136
  super(editor);
84
- this.title = this.lang.embed;
137
+ this.title = this.$.lang.embed;
85
138
  this.icon = 'embed';
86
139
 
87
140
  // define plugin options
@@ -97,57 +150,54 @@ class Embed extends EditorInjector {
97
150
  uploadSingleSizeLimit: numbers.get(pluginOptions.uploadSingleSizeLimit, 0),
98
151
  iframeTagAttributes: pluginOptions.iframeTagAttributes || null,
99
152
  query_youtube: pluginOptions.query_youtube || '',
100
- query_vimeo: pluginOptions.query_vimeo || ''
153
+ query_vimeo: pluginOptions.query_vimeo || '',
154
+ insertBehavior: pluginOptions.insertBehavior,
101
155
  };
102
156
 
103
157
  // create HTML
104
158
  const sizeUnit = this.pluginOptions.percentageOnlySize ? '%' : 'px';
105
- const modalEl = CreateHTML_modal(editor, this.pluginOptions);
106
- const figureControls = pluginOptions.controls || !this.pluginOptions.canResize ? [['align', 'edit', 'copy', 'remove']] : [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']];
159
+ const modalEl = CreateHTML_modal(this.$, this.pluginOptions);
160
+ const figureControls = pluginOptions.controls || (!this.pluginOptions.canResize ? [['align', 'edit', 'copy', 'remove']] : [['resize_auto,75,50', 'align', 'edit', 'revert', 'copy', 'remove']]);
107
161
 
108
162
  // show align
109
163
  if (!figureControls.some((subArray) => subArray.includes('align'))) modalEl.figureAlignBtn.style.display = 'none';
110
164
 
111
165
  // modules
112
- this.modal = new Modal(this, modalEl.html);
113
- this.figure = new Figure(this, figureControls, { sizeUnit: sizeUnit });
166
+ this.modal = new Modal(this, this.$, modalEl.html);
167
+ this.figure = new Figure(this, this.$, figureControls, { sizeUnit: sizeUnit });
114
168
 
115
169
  // members
116
170
  this.fileModalWrapper = modalEl.fileModalWrapper;
117
171
  this.embedInput = modalEl.embedInput;
118
172
  this.focusElement = this.embedInput;
119
173
  this.previewSrc = modalEl.previewSrc;
120
- this._linkValue = '';
121
- this._align = 'none';
122
- this._defaultSizeX = this.pluginOptions.defaultWidth;
123
- this._defaultSizeY = this.pluginOptions.defaultHeight;
124
174
  this.sizeUnit = sizeUnit;
125
175
  this.proportion = null;
126
176
  this.inputX = null;
127
177
  this.inputY = null;
128
- this._element = null;
129
- this._cover = null;
130
- this._container = null;
131
- this._ratio = { w: 1, h: 1 };
132
- this._origin_w = this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
133
- this._origin_h = this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
134
- this._resizing = this.pluginOptions.canResize;
135
- this._onlyPercentage = this.pluginOptions.percentageOnlySize;
136
- this._nonResizing = !this._resizing || !this.pluginOptions.showHeightInput || this._onlyPercentage;
178
+
179
+ this.#defaultSizeX = this.pluginOptions.defaultWidth;
180
+ this.#defaultSizeY = this.pluginOptions.defaultHeight;
181
+ this.#origin_w = this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
182
+ this.#origin_h = this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
183
+ this.#resizing = this.pluginOptions.canResize;
184
+ this.#onlyPercentage = this.pluginOptions.percentageOnlySize;
185
+ this.#nonResizing = !this.#resizing || !this.pluginOptions.showHeightInput || this.#onlyPercentage;
186
+
137
187
  this.query = {
138
188
  facebook: {
139
189
  pattern: /(?:https?:\/\/)?(?:www\.)?(?:facebook\.com)\/(.+)/i,
140
190
  action: (url) => {
141
191
  return `https://www.facebook.com/plugins/post.php?href=${encodeURIComponent(url)}&show_text=true&width=500`;
142
192
  },
143
- tag: 'iframe'
193
+ tag: 'iframe',
144
194
  },
145
195
  twitter: {
146
- pattern: /(?:https?:\/\/)?(?:www\.)?(?:twitter\.com)\/(status|embed)\/(.+)/i,
196
+ pattern: /^(?:https?:\/\/)?(?:(?:www\.)?(?:twitter\.com|x\.com)\/(?:[^/?#]+\/)?status\/\d+(?:[/?#]|$)|platform\.twitter\.com\/embed\/Tweet\.html(?:[?#].*)?$)/i,
147
197
  action: (url) => {
148
198
  return `https://platform.twitter.com/embed/Tweet.html?url=${encodeURIComponent(url)}`;
149
199
  },
150
- tag: 'iframe'
200
+ tag: 'iframe',
151
201
  },
152
202
  instagram: {
153
203
  pattern: /(?:https?:\/\/)?(?:www\.)?(?:instagram\.com)\/p\/(.+)/i,
@@ -155,14 +205,14 @@ class Embed extends EditorInjector {
155
205
  const postId = url.match(this.query.instagram.pattern)[1];
156
206
  return `https://www.instagram.com/p/${postId}/embed`;
157
207
  },
158
- tag: 'iframe'
208
+ tag: 'iframe',
159
209
  },
160
210
  linkedin: {
161
211
  pattern: /(?:https?:\/\/)?(?:www\.)?(?:linkedin\.com)\/(.+)\/(.+)/i,
162
212
  action: (url) => {
163
213
  return `https://www.linkedin.com/embed/feed/update/${encodeURIComponent(url.split('/').pop())}`;
164
214
  },
165
- tag: 'iframe'
215
+ tag: 'iframe',
166
216
  },
167
217
  pinterest: {
168
218
  pattern: /(?:https?:\/\/)?(?:www\.)?(?:pinterest\.com)\/pin\/(.+)/i,
@@ -170,7 +220,7 @@ class Embed extends EditorInjector {
170
220
  const pinId = url.match(this.query.pinterest.pattern)[1];
171
221
  return `https://assets.pinterest.com/ext/embed.html?id=${pinId}`;
172
222
  },
173
- tag: 'iframe'
223
+ tag: 'iframe',
174
224
  },
175
225
  spotify: {
176
226
  pattern: /(?:https?:\/\/)?(?:open\.)?(?:spotify\.com)\/(track|album|playlist|show|episode)\/(.+)/i,
@@ -180,7 +230,7 @@ class Embed extends EditorInjector {
180
230
  const id = match[2];
181
231
  return `https://open.spotify.com/embed/${type}/${id}`;
182
232
  },
183
- tag: 'iframe'
233
+ tag: 'iframe',
184
234
  },
185
235
  codepen: {
186
236
  pattern: /(?:https?:\/\/)?(?:www\.)?(?:codepen\.io)\/(.+)\/pen\/(.+)/i,
@@ -188,244 +238,167 @@ class Embed extends EditorInjector {
188
238
  const [, user, penId] = url.match(this.query.codepen.pattern);
189
239
  return `https://codepen.io/${user}/embed/${penId}`;
190
240
  },
191
- tag: 'iframe'
241
+ tag: 'iframe',
192
242
  },
193
- ...pluginOptions.embedQuery
243
+ ...pluginOptions.embedQuery,
194
244
  };
195
245
 
196
246
  const urlPatterns = [];
197
247
  for (const key in this.query) {
198
248
  urlPatterns.push(this.query[key].pattern);
199
249
  }
200
- this.urlPatterns = urlPatterns.concat(pluginOptions.urlPatterns || []);
250
+ Embed.#urlPatterns = urlPatterns.concat(pluginOptions.urlPatterns || []);
201
251
 
202
252
  // init
203
- this.eventManager.addEvent(this.embedInput, 'input', this.#OnLinkPreview.bind(this));
253
+ this.$.eventManager.addEvent(this.embedInput, 'input', this.#OnLinkPreview.bind(this));
204
254
 
205
- if (this._resizing) {
255
+ if (this.#resizing) {
206
256
  this.proportion = modalEl.proportion;
207
257
  this.inputX = modalEl.inputX;
208
258
  this.inputY = modalEl.inputY;
209
259
  this.inputX.value = this.pluginOptions.defaultWidth;
210
260
  this.inputY.value = this.pluginOptions.defaultHeight;
211
261
 
212
- this.eventManager.addEvent(this.inputX, 'keyup', this.#OnInputSize.bind(this, 'x'));
213
- this.eventManager.addEvent(this.inputY, 'keyup', this.#OnInputSize.bind(this, 'y'));
214
- this.eventManager.addEvent(modalEl.revertBtn, 'click', this.#OnClickRevert.bind(this));
262
+ this.$.eventManager.addEvent(this.inputX, 'keyup', this.#OnInputSize.bind(this, 'x'));
263
+ this.$.eventManager.addEvent(this.inputY, 'keyup', this.#OnInputSize.bind(this, 'y'));
264
+ this.$.eventManager.addEvent(modalEl.revertBtn, 'click', this.#OnClickRevert.bind(this));
215
265
  }
216
266
  }
217
267
 
218
268
  /**
219
- * @editorMethod Modules.Modal
220
- * @description Executes the method that is called when a "Modal" module's is opened.
269
+ * @override
270
+ * @type {PluginModal['open']}
221
271
  */
222
272
  open() {
223
273
  this.modal.open();
224
274
  }
225
275
 
226
276
  /**
227
- * @editorMethod Modules.Controller(Figure)
228
- * @description Executes the method that is called when a target component is edited.
277
+ * @hook Editor.Core
278
+ * @type {SunEditor.Hook.Core.RetainFormat}
229
279
  */
230
- edit() {
231
- this.modal.open();
280
+ retainFormat() {
281
+ return {
282
+ query: 'iframe',
283
+ /** @param {HTMLIFrameElement} element */
284
+ method: async (element) => {
285
+ if (!Embed.#checkContentType(element.src)) return;
286
+
287
+ const figureInfo = Figure.GetContainer(element);
288
+ if (figureInfo && figureInfo.container && figureInfo.cover) return;
289
+
290
+ this.#ready(element, true);
291
+ const line = this.$.format.getLine(element);
292
+ if (line) this.#align = line.style.textAlign || line.style.float;
293
+
294
+ this.#fixTagStructure(element);
295
+ },
296
+ };
232
297
  }
233
298
 
234
299
  /**
235
- * @editorMethod Modules.Modal
236
- * @description Executes the method that is called when a plugin's modal is opened.
237
- * @param {boolean} isUpdate "Indicates whether the modal is for editing an existing component (true) or registering a new one (false)."
300
+ * @hook Modules.Modal
301
+ * @type {SunEditor.Hook.Modal.On}
238
302
  */
239
- on(isUpdate) {
240
- if (!isUpdate && this._resizing) {
241
- this.inputX.value = this._origin_w = this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
242
- this.inputY.value = this._origin_h = this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
303
+ modalOn(isUpdate) {
304
+ if (!isUpdate && this.#resizing) {
305
+ this.inputX.value = this.#origin_w = this.pluginOptions.defaultWidth === 'auto' ? '' : this.pluginOptions.defaultWidth;
306
+ this.inputY.value = this.#origin_h = this.pluginOptions.defaultHeight === 'auto' ? '' : this.pluginOptions.defaultHeight;
243
307
  this.proportion.disabled = true;
308
+ } else if (isUpdate) {
309
+ this.#linkValue = this.previewSrc.textContent = this.embedInput.value = this.#cover.getAttribute('data-se-origin') || '';
244
310
  }
245
311
  }
246
312
 
247
313
  /**
248
- * @editorMethod Modules.Modal
249
- * @description This function is called when a form within a modal window is "submit".
250
- * @returns {Promise<boolean>} Success / failure
314
+ * @hook Modules.Modal
315
+ * @type {SunEditor.Hook.Modal.Action}
251
316
  */
252
317
  async modalAction() {
253
- this._align = /** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_embed_radio"]:checked')).value;
318
+ this.#align = /** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_embed_radio"]:checked')).value;
254
319
 
255
320
  let result = false;
256
- if (this._linkValue.length > 0) {
257
- result = await this.submitSRC(this._linkValue);
321
+ if (this.#linkValue.length > 0) {
322
+ result = await this.submitSRC(this.#linkValue);
258
323
  }
259
324
 
260
- if (result) this._w.setTimeout(this.component.select.bind(this.component, this._element, Embed.key), 0);
325
+ if (result) _w.setTimeout(this.$.component.select.bind(this.$.component, this.#element, Embed.key), 0);
261
326
 
262
327
  return result;
263
328
  }
264
329
 
265
330
  /**
266
- * @editorMethod Editor.core
267
- * @description This method is used to validate and preserve the format of the component within the editor.
268
- * - It ensures that the structure and attributes of the element are maintained and secure.
269
- * - The method checks if the element is already wrapped in a valid container and updates its attributes if necessary.
270
- * - If the element isn't properly contained, a new container is created to retain the format.
271
- * @returns {{query: string, method: (element: HTMLIFrameElement) => void}} The format retention object containing the query and method to process the element.
272
- * - query: The selector query to identify the relevant elements (in this case, 'audio').
273
- * - method:The function to execute on the element to validate and preserve its format.
274
- * - The function takes the element as an argument, checks if it is contained correctly, and applies necessary adjustments.
275
- */
276
- retainFormat() {
277
- return {
278
- query: 'iframe',
279
- method: async (element) => {
280
- if (!this.checkContentType(element.src)) return;
281
-
282
- const figureInfo = Figure.GetContainer(element);
283
- if (figureInfo && figureInfo.container && figureInfo.cover) return;
284
-
285
- this._ready(element);
286
- const line = this.format.getLine(element);
287
- if (line) this._align = line.style.textAlign || line.style.float;
288
-
289
- this._update(element);
290
- }
291
- };
292
- }
293
-
294
- /**
295
- * @editorMethod Modules.Modal
296
- * @description This function is called before the modal window is opened, but before it is closed.
331
+ * @hook Modules.Modal
332
+ * @type {SunEditor.Hook.Modal.Init}
297
333
  */
298
- init() {
334
+ modalInit() {
299
335
  Modal.OnChangeFile(this.fileModalWrapper, []);
300
- this._linkValue = this.previewSrc.textContent = this.embedInput.value = '';
336
+ this.#linkValue = this.previewSrc.textContent = this.embedInput.value = '';
301
337
 
302
338
  /** @type {HTMLInputElement} */ (this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]')).checked = true;
303
- this._ratio = { w: 1, h: 1 };
304
- this._nonResizing = false;
339
+ this.#ratio = { w: 0, h: 0 };
340
+ this.#nonResizing = false;
305
341
 
306
- if (this._resizing) {
307
- this.inputX.value = this.pluginOptions.defaultWidth === this._defaultSizeX ? '' : this.pluginOptions.defaultWidth;
308
- this.inputY.value = this.pluginOptions.defaultHeight === this._defaultSizeY ? '' : this.pluginOptions.defaultHeight;
342
+ if (this.#resizing) {
343
+ this.inputX.value = this.pluginOptions.defaultWidth === this.#defaultSizeX ? '' : this.pluginOptions.defaultWidth;
344
+ this.inputY.value = this.pluginOptions.defaultHeight === this.#defaultSizeY ? '' : this.pluginOptions.defaultHeight;
309
345
  this.proportion.checked = false;
310
346
  this.proportion.disabled = true;
311
347
  }
312
348
  }
313
349
 
314
350
  /**
315
- * @editorMethod Editor.Component
316
- * @description Executes the method that is called when a component of a plugin is selected.
317
- * @param {HTMLElement} target Target component element
351
+ * @hook Editor.Component
352
+ * @type {SunEditor.Hook.Component.Select}
318
353
  */
319
- select(target) {
320
- this._ready(target);
354
+ componentSelect(target) {
355
+ this.#ready(target);
321
356
  }
322
357
 
323
358
  /**
324
- * @private
325
- * @description Prepares the component for selection.
326
- * - Ensures that the controller is properly positioned and initialized.
327
- * - Prevents duplicate event handling if the component is already selected.
328
- * @param {HTMLElement} target - The selected element.
359
+ * @hook Editor.Component
360
+ * @type {SunEditor.Hook.Component.Edit}
329
361
  */
330
- _ready(target) {
331
- if (!target) return;
332
- const figureInfo = this.figure.open(target, { nonResizing: this._nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, __fileManagerInfo: false });
333
-
334
- this._element = target;
335
- this._cover = figureInfo.cover;
336
- this._container = figureInfo.container;
337
- this._caption = figureInfo.caption;
338
- this._align = figureInfo.align;
339
- target.style.float = '';
340
-
341
- this._origin_w = String(figureInfo.originWidth || figureInfo.w || '');
342
- this._origin_h = String(figureInfo.originHeight || figureInfo.h || '');
343
-
344
- /** @type {HTMLInputElement} */
345
- const activeAlign = this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="' + this._align + '"]') || this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]');
346
- activeAlign.checked = true;
347
-
348
- if (!this._resizing) return;
349
-
350
- const percentageRotation = this._onlyPercentage && this.figure.isVertical;
351
- let w = percentageRotation ? '' : figureInfo.width;
352
- if (this._onlyPercentage) {
353
- w = numbers.get(w, 2);
354
- if (w > 100) w = 100;
355
- }
356
-
357
- this.inputX.value = String(w === 'auto' ? '' : w);
358
-
359
- if (!this._onlyPercentage) {
360
- const h = percentageRotation ? '' : figureInfo.height;
361
- this.inputY.value = String(h === 'auto' ? '' : h);
362
- }
363
-
364
- this.proportion.checked = true;
365
- this.inputX.disabled = percentageRotation ? true : false;
366
- this.inputY.disabled = percentageRotation ? true : false;
367
- this.proportion.disabled = percentageRotation ? true : false;
368
-
369
- this._ratio = this.proportion.checked
370
- ? figureInfo.ratio
371
- : {
372
- w: 1,
373
- h: 1
374
- };
362
+ componentEdit() {
363
+ this.modal.open();
375
364
  }
376
365
 
377
366
  /**
378
- * @editorMethod Editor.Component
379
- * @description Method to delete a component of a plugin, called by the "FileManager", "Controller" module.
380
- * @param {HTMLElement} target Target element
381
- * @returns {Promise<void>}
367
+ * @hook Editor.Component
368
+ * @type {SunEditor.Hook.Component.Destroy}
382
369
  */
383
- async destroy(target) {
384
- const targetEl = target || this._element;
370
+ async componentDestroy(target) {
371
+ const targetEl = target || this.#element;
385
372
  const container = dom.query.getParentElement(targetEl, Figure.is) || targetEl;
386
373
  const focusEl = container.previousElementSibling || container.nextElementSibling;
387
374
  const emptyDiv = container.parentNode;
388
375
 
389
- const message = await this.triggerEvent('onEmbedDeleteBefore', { element: targetEl, container, align: this._align, url: this._linkValue });
376
+ const message = await this.$.eventManager.triggerEvent('onEmbedDeleteBefore', { element: targetEl, container, align: this.#align, url: this.#linkValue });
390
377
  if (message === false) return;
391
378
 
392
379
  dom.utils.removeItem(container);
393
- this.init();
380
+ this.modalInit();
394
381
 
395
- if (emptyDiv !== this.editor.frameContext.get('wysiwyg')) {
396
- this.nodeTransform.removeAllParents(
382
+ if (emptyDiv !== this.$.frameContext.get('wysiwyg')) {
383
+ this.$.nodeTransform.removeAllParents(
397
384
  emptyDiv,
398
385
  function (current) {
399
386
  return current.childNodes.length === 0;
400
387
  },
401
- null
388
+ null,
402
389
  );
403
390
  }
404
391
 
405
392
  // focus
406
- this.editor.focusEdge(focusEl);
407
- this.history.push(false);
408
- }
409
-
410
- /**
411
- * @description Checks if the given URL matches any of the defined URL patterns.
412
- * @param {string} url - The URL to check.
413
- * @returns {boolean} True if the URL matches a known pattern; otherwise, false.
414
- */
415
- checkContentType(url) {
416
- url = url?.toLowerCase() || '';
417
- if (this.urlPatterns.some((pattern) => pattern.test(url))) {
418
- return true;
419
- }
420
-
421
- return false;
393
+ this.$.focusManager.focusEdge(focusEl);
394
+ this.$.history.push(false);
422
395
  }
423
396
 
424
397
  /**
425
398
  * @description Finds and processes the URL for embedding by matching it against known service patterns.
426
399
  * @param {string} url - The original URL.
427
- * @returns {{origin: string, url: string, tag: string}|null} An object containing the original URL, the processed URL, and the tag type (e.g., 'iframe'),
428
- * or null if no matching pattern is found.
400
+ * @returns {{origin: string, url: string, tag: string}|null} An object containing the original URL, the processed URL, and the tag type (e.g., `iframe`),
401
+ * or `null` if no matching pattern is found.
429
402
  */
430
403
  findProcessUrl(url) {
431
404
  const query = this.query;
@@ -435,7 +408,7 @@ class Embed extends EditorInjector {
435
408
  return {
436
409
  origin: url,
437
410
  url: service.action(url),
438
- tag: service.tag
411
+ tag: service.tag,
439
412
  };
440
413
  }
441
414
  }
@@ -447,34 +420,36 @@ class Embed extends EditorInjector {
447
420
  * @description Processes the provided source (URL or embed code) and submits it for embedding.
448
421
  * - It parses the input, triggers any necessary events, and creates or updates the embed component.
449
422
  * @param {string} [src] - The embed source. If not provided, uses the internally stored link value.
450
- * @returns {Promise<boolean>} A promise that resolves to true on success or false on failure.
423
+ * @returns {Promise<boolean>} A promise that resolves to `true` on success or `false` on failure.
451
424
  */
452
425
  async submitSRC(src) {
453
- if (!src) src = this._linkValue;
454
- if (!src) return false;
426
+ if (!(src ||= this.#linkValue)) return false;
455
427
 
456
428
  let embedInfo = null;
457
429
  if (/^<iframe\s|^<blockquote\s/i.test(src)) {
458
430
  const embedDOM = new DOMParser().parseFromString(src, 'text/html').body.children;
459
431
  if (embedDOM.length === 0) return false;
460
- embedInfo = { children: embedDOM, ...this._getInfo(), process: null };
432
+ embedInfo = { children: embedDOM, ...this.#getInfo(), process: null };
461
433
  } else {
462
434
  const processUrl = this.findProcessUrl(src);
463
435
  if (!processUrl) return false;
464
436
  src = processUrl.url;
465
- embedInfo = { url: src, ...this._getInfo(), process: processUrl };
437
+
438
+ embedInfo = {
439
+ ...this.#getInfo(),
440
+ url: src,
441
+ process: processUrl,
442
+ };
466
443
  }
467
444
 
468
- const handler = function (infos, newInfos) {
445
+ const handler = function (uploadCallback, infos, newInfos) {
469
446
  infos = newInfos || infos;
470
- this._create(infos.process, infos.url, infos.children, infos.inputWidth, infos.inputHeight, infos.align, infos.isUpdate);
471
- }.bind(this, embedInfo);
472
- // se-ts-ignore
473
- void this._create;
447
+ uploadCallback(src, infos.process, infos.url, infos.children, infos.inputWidth, infos.inputHeight, infos.align, infos.isUpdate);
448
+ }.bind(this, this.#create.bind(this), embedInfo);
474
449
 
475
- const result = await this.triggerEvent('onEmbedInputBefore', {
450
+ const result = await this.$.eventManager.triggerEvent('onEmbedInputBefore', {
476
451
  ...embedInfo,
477
- handler
452
+ handler,
478
453
  });
479
454
 
480
455
  if (result === undefined) return true;
@@ -487,39 +462,90 @@ class Embed extends EditorInjector {
487
462
  }
488
463
 
489
464
  /**
490
- * @private
491
- * @description Creates an iframe element for embedding external content.
492
- * @returns {HTMLIFrameElement} The created iframe element.
465
+ * @description Prepares the component for selection.
466
+ * - Ensures that the controller is properly positioned and initialized.
467
+ * - Prevents duplicate event handling if the component is already selected.
468
+ * @param {HTMLElement} target - The selected element.
469
+ * @param {boolean} [infoOnly=false] - If `true`, only retrieves information without opening the controller.
470
+ */
471
+ #ready(target, infoOnly = false) {
472
+ if (!target) return;
473
+ const figureInfo = this.figure.open(target, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly });
474
+
475
+ this.#element = target;
476
+ this.#cover = figureInfo.cover;
477
+ this.#container = figureInfo.container;
478
+ this._caption = figureInfo.caption;
479
+ this.#align = figureInfo.align;
480
+
481
+ if (!this.#cover?.getAttribute?.('data-se-origin')) {
482
+ const src = target?.getAttribute?.('src') || target?.querySelector?.('a')?.href;
483
+ if (src && Embed.#checkContentType(src)) {
484
+ this.#cover.setAttribute('data-se-origin', src);
485
+ }
486
+ }
487
+
488
+ target.style.float = '';
489
+
490
+ this.#origin_w = String(figureInfo.originWidth || figureInfo.w || '');
491
+ this.#origin_h = String(figureInfo.originHeight || figureInfo.h || '');
492
+
493
+ /** @type {HTMLInputElement} */
494
+ const activeAlign = this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="' + this.#align + '"]') || this.modal.form.querySelector('input[name="suneditor_embed_radio"][value="none"]');
495
+ activeAlign.checked = true;
496
+
497
+ if (!this.#resizing) return;
498
+
499
+ const percentageRotation = this.#onlyPercentage && this.figure.isVertical;
500
+ const { dw, dh } = this.figure.getSize(target);
501
+ this.inputX.value = dw === 'auto' ? '' : dw;
502
+ this.inputY.value = dh === 'auto' ? '' : dh;
503
+
504
+ this.proportion.checked = true;
505
+ this.inputX.disabled = percentageRotation ? true : false;
506
+ this.inputY.disabled = percentageRotation ? true : false;
507
+ this.proportion.disabled = percentageRotation ? true : false;
508
+
509
+ this.#ratio = this.proportion.checked
510
+ ? figureInfo.ratio
511
+ : {
512
+ w: 0,
513
+ h: 0,
514
+ };
515
+ }
516
+
517
+ /**
518
+ * @description Creates an `IFRAME` element for embedding external content.
519
+ * @returns {HTMLIFrameElement} The created `IFRAME` element.
493
520
  */
494
- _createIframeTag() {
521
+ #createIframeTag() {
495
522
  /** @type {HTMLIFrameElement} */
496
523
  const iframeTag = dom.utils.createElement('IFRAME');
497
- this._setIframeAttrs(iframeTag);
524
+ this.#setIframeAttrs(iframeTag);
498
525
  return iframeTag;
499
526
  }
500
527
 
501
528
  /**
502
- * @private
503
- * @description Creates an blockquote element for embedding external content.
504
- * @returns {HTMLElement} The created iframe element.
529
+ * @description Creates a `BLOCKQUOTE` element for embedding external content.
530
+ * @returns {HTMLElement} The created `BLOCKQUOTE` element.
505
531
  */
506
- _createEmbedTag() {
532
+ #createEmbedTag() {
507
533
  const quoteTag = dom.utils.createElement('BLOCKQUOTE');
508
534
  return quoteTag;
509
535
  }
510
536
 
511
537
  /**
512
- * @private
513
- * @description Creates an embed component (iframe or blockquote) and inserts it into the editor.
514
- * @param {?ProcessInfo_embed} process - Processed embed information.
515
- * @param {?string} src - The source URL.
516
- * @param {?Node[]} children - The embed elements.
538
+ * @description Creates an embed component (`IFRAME` or `BLOCKQUOTE`) and inserts it into the editor.
539
+ * @param {string} originSrc - The origin input source.
540
+ * @param {SunEditor.EventParams.ProcessInfo} process - Processed embed information.
541
+ * @param {string} src - The source URL.
542
+ * @param {Node[]} children - The embed elements.
517
543
  * @param {string} width - The width of the embed component.
518
544
  * @param {string} height - The height of the embed component.
519
545
  * @param {string} align - The alignment of the embed component.
520
546
  * @param {boolean} isUpdate - Whether this is an update to an existing embed component.
521
547
  */
522
- _create(process, src, children, width, height, align, isUpdate) {
548
+ #create(originSrc, process, src, children, width, height, align, isUpdate) {
523
549
  let oFrame = null;
524
550
  let cover = null;
525
551
  let container = null;
@@ -527,16 +553,16 @@ class Embed extends EditorInjector {
527
553
 
528
554
  /** update */
529
555
  if (isUpdate) {
530
- oFrame = this._element;
556
+ oFrame = this.#element;
531
557
  if (oFrame.src !== src) {
532
558
  const processUrl = this.findProcessUrl(src);
533
559
  if (/^iframe$/i.test(processUrl?.tag) && !/^iframe$/i.test(oFrame.nodeName)) {
534
- const newTag = this._createIframeTag();
560
+ const newTag = this.#createIframeTag();
535
561
  newTag.src = src;
536
562
  oFrame.replaceWith(newTag);
537
563
  oFrame = newTag;
538
564
  } else if (/^blockquote$/i.test(processUrl?.tag) && !/^blockquote$/i.test(oFrame.nodeName)) {
539
- const newTag = this._createEmbedTag();
565
+ const newTag = this.#createEmbedTag();
540
566
  newTag.setAttribute('src', src);
541
567
  oFrame.replaceWith(newTag);
542
568
  oFrame = newTag;
@@ -544,12 +570,12 @@ class Embed extends EditorInjector {
544
570
  oFrame.src = src;
545
571
  }
546
572
  }
547
- container = this._container;
573
+ container = this.#container;
548
574
  cover = dom.query.getParentElement(oFrame, 'FIGURE');
549
575
  } else {
550
576
  /** create */
551
577
  if (process) {
552
- oFrame = this._createIframeTag();
578
+ oFrame = this.#createIframeTag();
553
579
  oFrame.src = src;
554
580
  const figure = Figure.CreateContainer(oFrame, 'se-embed-container');
555
581
  cover = figure.cover;
@@ -560,12 +586,10 @@ class Embed extends EditorInjector {
560
586
  cover = figure.cover;
561
587
  container = figure.container;
562
588
 
563
- let chd = null;
564
- let index = 0;
565
- while ((chd = /** @type {Element} */ (children[index]))) {
589
+ const childNodes = Array.from(children);
590
+ for (const chd of childNodes) {
566
591
  if (/^script$/i.test(chd.nodeName)) {
567
- scriptTag = dom.utils.createElement('script', { src: chd.getAttribute('src'), async: 'true' }, null);
568
- index++;
592
+ scriptTag = dom.utils.createElement('script', { src: /** @type {Element} */ (chd).getAttribute('src'), async: 'true' }, null);
569
593
  continue;
570
594
  }
571
595
  cover.appendChild(chd);
@@ -574,31 +598,35 @@ class Embed extends EditorInjector {
574
598
  }
575
599
 
576
600
  /** rendering */
577
- this._element = oFrame;
578
- this._cover = cover;
579
- this._container = container;
580
- this.figure.open(oFrame, { nonResizing: this._nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, __fileManagerInfo: true });
601
+ this.#element = oFrame;
602
+ this.#cover = cover;
603
+ this.#container = container;
604
+ this.figure.open(oFrame, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
605
+
606
+ width ||= this.#defaultSizeX;
607
+ height ||= this.#defaultSizeY;
581
608
 
582
- width = width || this._defaultSizeX;
583
- height = height || this._defaultSizeY;
584
609
  const size = this.figure.getSize(oFrame);
585
610
  const inputUpdate = size.w !== width || size.h !== height;
586
611
  const changeSize = !isUpdate || inputUpdate;
587
612
 
588
613
  // set size
589
614
  if (changeSize) {
590
- this._applySize(width, height);
615
+ this.#applySize(width, height);
591
616
  }
592
617
 
593
618
  // align
594
619
  this.figure.setAlign(oFrame, align);
595
620
 
621
+ // origin src
622
+ cover.setAttribute('data-se-origin', originSrc);
623
+
596
624
  if (!isUpdate) {
597
- this.component.insert(container, { skipCharCount: false, skipSelection: true, skipHistory: true });
625
+ this.$.component.insert(container, { skipHistory: true, scrollTo: false, insertBehavior: this.pluginOptions.insertBehavior });
598
626
 
599
627
  if (scriptTag) {
600
628
  try {
601
- this.history.pause();
629
+ this.$.history.pause();
602
630
 
603
631
  scriptTag.onload = () => {
604
632
  dom.utils.removeItem(scriptTag);
@@ -610,8 +638,8 @@ class Embed extends EditorInjector {
610
638
  for (const mutation of mutations) {
611
639
  if (mutation.type === 'childList') {
612
640
  if (!oFrame.parentElement) {
613
- this.history.resume();
614
- this.history.push(false);
641
+ this.$.history.resume();
642
+ this.$.history.push(false);
615
643
  observer.disconnect();
616
644
  break;
617
645
  }
@@ -619,38 +647,35 @@ class Embed extends EditorInjector {
619
647
  }
620
648
  });
621
649
 
622
- observer.observe(this.editor.frameContext.get('wysiwyg'), {
650
+ observer.observe(this.$.frameContext.get('wysiwyg'), {
623
651
  subtree: true,
624
- childList: true
652
+ childList: true,
625
653
  });
626
654
  } catch (e) {
627
- this.history.resume();
655
+ this.$.history.resume();
628
656
  console.warn('[SUNEDITOR] Embed tag script load error.', e);
629
657
  }
630
658
  }
631
659
 
632
- if (!this.options.get('componentAutoSelect')) {
633
- const line = this.format.addLine(container, null);
634
- if (line) this.selection.setRange(line, 0, line, 0);
660
+ if (!this.$.options.get('componentInsertBehavior')) {
661
+ const line = this.$.format.addLine(container, null);
662
+ if (line) this.$.selection.setRange(line, 0, line, 0);
635
663
  }
636
664
  return;
637
665
  }
638
666
 
639
- if (this._resizing && changeSize && this.figure.isVertical) this.figure.setTransform(oFrame, width, height, 0);
640
- if (!scriptTag) this.history.push(false);
667
+ if (!this.#resizing || !changeSize || !this.figure.isVertical) this.figure.setTransform(oFrame, width, height, 0);
668
+ if (!scriptTag) this.$.history.push(false);
641
669
  }
642
670
 
643
671
  /**
644
- * @private
645
672
  * @description Updates an existing embed component within the editor.
646
673
  * @param {HTMLIFrameElement} oFrame - The existing embed element to be updated.
647
674
  */
648
- _update(oFrame) {
675
+ #fixTagStructure(oFrame) {
649
676
  if (!oFrame) return;
650
677
 
651
- this._setIframeAttrs(oFrame);
652
-
653
- let existElement = this.format.isBlock(oFrame.parentNode) || dom.check.isWysiwygFrame(oFrame.parentNode) ? oFrame : this.format.getLine(oFrame) || oFrame;
678
+ this.#setIframeAttrs(oFrame);
654
679
 
655
680
  const prevFrame = oFrame;
656
681
  oFrame = /** @type {HTMLIFrameElement} */ (oFrame.cloneNode(true));
@@ -658,53 +683,40 @@ class Embed extends EditorInjector {
658
683
  const container = figure.container;
659
684
 
660
685
  // size
661
- this.figure.open(oFrame, { nonResizing: this._nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, __fileManagerInfo: true });
686
+ this.figure.open(oFrame, { nonResizing: this.#nonResizing, nonSizeInfo: false, nonBorder: false, figureTarget: false, infoOnly: true });
662
687
  const size = (oFrame.getAttribute('data-se-size') || ',').split(',');
663
- this._applySize(size[0] || prevFrame.style.width || prevFrame.width || '', size[1] || prevFrame.style.height || prevFrame.height || '');
688
+
689
+ const width = size[0] || prevFrame.width || '';
690
+ const height = size[1] || prevFrame.height || '';
691
+ this.#applySize(width, height);
664
692
 
665
693
  // align
666
- const format = this.format.getLine(prevFrame);
667
- if (format) this._align = format.style.textAlign || format.style.float;
668
- this.figure.setAlign(oFrame, this._align);
669
-
670
- if (dom.query.getParentElement(prevFrame, dom.check.isExcludeFormat)) {
671
- prevFrame.replaceWith(container);
672
- } else if (dom.check.isListCell(existElement)) {
673
- const refer = dom.query.getParentElement(prevFrame, (current) => current.parentNode === existElement);
674
- existElement.insertBefore(container, refer);
675
- dom.utils.removeItem(prevFrame);
676
- this.nodeTransform.removeEmptyNode(refer, null, true);
677
- } else if (this.format.isLine(existElement)) {
678
- const refer = dom.query.getParentElement(prevFrame, (current) => current.parentNode === existElement);
679
- existElement = this.nodeTransform.split(existElement, refer);
680
- existElement.parentNode.insertBefore(container, existElement);
681
- dom.utils.removeItem(prevFrame);
682
- this.nodeTransform.removeEmptyNode(existElement, null, true);
683
- } else {
684
- /** @type {Element} */ (existElement).replaceWith(container);
685
- }
694
+ const format = this.$.format.getLine(prevFrame);
695
+ if (format) this.#align = format.style.textAlign || format.style.float;
696
+ this.figure.setAlign(oFrame, this.#align);
697
+
698
+ this.figure.retainFigureFormat(container, this.#element, null, null);
686
699
 
687
700
  return oFrame;
688
701
  }
689
702
 
690
703
  /**
691
- * @private
692
704
  * @description Applies width and height to the embed component.
693
705
  * @param {string|number} w - The width to apply.
694
706
  * @param {string|number} h - The height to apply.
695
707
  */
696
- _applySize(w, h) {
697
- if (!w) w = this.inputX?.value || this.pluginOptions.defaultWidth;
698
- if (!h) h = this.inputY?.value || this.pluginOptions.defaultHeight;
699
- if (this._onlyPercentage) {
708
+ #applySize(w, h) {
709
+ w ||= this.inputX?.value || this.pluginOptions.defaultWidth;
710
+ h ||= this.inputY?.value || this.pluginOptions.defaultHeight;
711
+
712
+ if (this.#onlyPercentage) {
700
713
  if (!w) w = '100%';
701
- else if (/%$/.test(w + '')) w += '%';
714
+ else if (!/%$/.test(w + '')) w += '%';
702
715
  }
703
716
  this.figure.setSize(w, h);
704
717
  }
705
718
 
706
719
  /**
707
- * @private
708
720
  * @description Retrieves embed component size and alignment information.
709
721
  * @returns {{inputWidth: string, inputHeight: string, align: string, isUpdate: boolean, element: Element}} An object containing
710
722
  * - inputWidth : The width of the embed component.
@@ -713,22 +725,21 @@ class Embed extends EditorInjector {
713
725
  * - isUpdate : Whether the component is being updated.
714
726
  * - element : The target element.
715
727
  */
716
- _getInfo() {
728
+ #getInfo() {
717
729
  return {
718
730
  inputWidth: this.inputX?.value || '',
719
731
  inputHeight: this.inputY?.value || '',
720
- align: this._align,
732
+ align: this.#align,
721
733
  isUpdate: this.modal.isUpdate,
722
- element: this._element
734
+ element: this.#element,
723
735
  };
724
736
  }
725
737
 
726
738
  /**
727
- * @private
728
- * @description Sets default attributes for an iframe element.
729
- * @param {HTMLIFrameElement} element - The iframe element to modify.
739
+ * @description Sets default attributes for an `IFRAME` element.
740
+ * @param {HTMLIFrameElement} element - The `IFRAME` element to modify.
730
741
  */
731
- _setIframeAttrs(element) {
742
+ #setIframeAttrs(element) {
732
743
  element.frameBorder = '0';
733
744
  element.allowFullscreen = true;
734
745
 
@@ -749,25 +760,25 @@ class Embed extends EditorInjector {
749
760
  const eventTarget = dom.query.getEventTarget(e);
750
761
  const value = eventTarget.value.trim();
751
762
  if (/^<iframe.*\/iframe>$/.test(value)) {
752
- this._linkValue = value;
763
+ this.#linkValue = value;
753
764
  this.previewSrc.textContent = '<IFrame :src=".."></IFrame>';
754
765
  } else {
755
- this._linkValue = this.previewSrc.textContent = !value
766
+ this.#linkValue = this.previewSrc.textContent = !value
756
767
  ? ''
757
- : this.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
758
- ? this.options.get('defaultUrlProtocol') + value
759
- : !value.includes('://')
760
- ? '/' + value
761
- : value;
768
+ : this.$.options.get('defaultUrlProtocol') && !value.includes('://') && value.indexOf('#') !== 0
769
+ ? this.$.options.get('defaultUrlProtocol') + value
770
+ : !value.includes('://')
771
+ ? '/' + value
772
+ : value;
762
773
  }
763
774
  }
764
775
 
765
776
  #OnClickRevert() {
766
- if (this._onlyPercentage) {
767
- this.inputX.value = Number(this._origin_w) > 100 ? '100' : this._origin_w;
777
+ if (this.#onlyPercentage) {
778
+ this.inputX.value = Number(this.#origin_w) > 100 ? '100' : this.#origin_w;
768
779
  } else {
769
- this.inputX.value = this._origin_w;
770
- this.inputY.value = this._origin_h;
780
+ this.inputX.value = this.#origin_w;
781
+ this.inputY.value = this.#origin_h;
771
782
  }
772
783
  }
773
784
 
@@ -784,10 +795,10 @@ class Embed extends EditorInjector {
784
795
  /** @type {HTMLInputElement} */
785
796
  const eventTarget = dom.query.getEventTarget(e);
786
797
 
787
- if (xy === 'x' && this._onlyPercentage && Number(eventTarget.value) > 100) {
798
+ if (xy === 'x' && this.#onlyPercentage && Number(eventTarget.value) > 100) {
788
799
  eventTarget.value = '100';
789
800
  } else if (this.proportion.checked) {
790
- const ratioSize = Figure.CalcRatio(this.inputX.value, this.inputY.value, this.sizeUnit, this._ratio);
801
+ const ratioSize = Figure.CalcRatio(this.inputX.value, this.inputY.value, this.sizeUnit, this.#ratio);
791
802
  if (xy === 'x') {
792
803
  this.inputY.value = String(ratioSize.h);
793
804
  } else {
@@ -798,7 +809,7 @@ class Embed extends EditorInjector {
798
809
  }
799
810
 
800
811
  /**
801
- * @param {__se__EditorCore} editor Editor instance
812
+ * @param {SunEditor.Deps} $ Kernel deps
802
813
  * @param {*} pluginOptions
803
814
  * @returns {{
804
815
  * html: HTMLElement,
@@ -879,7 +890,7 @@ function CreateHTML_modal({ lang, icons }, pluginOptions) {
879
890
  proportion: content.querySelector('._se_check_proportion'),
880
891
  inputX: content.querySelector('._se_size_x'),
881
892
  inputY: content.querySelector('._se_size_y'),
882
- revertBtn: content.querySelector('.se-modal-btn-revert')
893
+ revertBtn: content.querySelector('.se-modal-btn-revert'),
883
894
  };
884
895
  }
885
896