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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/CONTRIBUTING.md +170 -22
  2. package/{LICENSE.txt → LICENSE} +9 -9
  3. package/README.md +168 -30
  4. package/dist/suneditor.min.css +1 -1
  5. package/dist/suneditor.min.js +1 -1
  6. package/package.json +47 -21
  7. package/src/assets/design/color.css +121 -0
  8. package/src/assets/design/index.css +3 -0
  9. package/src/assets/design/size.css +35 -0
  10. package/src/assets/design/typography.css +37 -0
  11. package/src/assets/icons/defaultIcons.js +232 -0
  12. package/src/assets/suneditor-contents.css +181 -46
  13. package/src/assets/suneditor.css +1403 -650
  14. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  15. package/src/core/base/eventHandlers/handler_ww_clipboard.js +23 -4
  16. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +49 -10
  17. package/src/core/base/eventHandlers/handler_ww_key_input.js +422 -224
  18. package/src/core/base/eventHandlers/handler_ww_mouse.js +83 -36
  19. package/src/core/base/eventManager.js +520 -179
  20. package/src/core/base/history.js +95 -41
  21. package/src/core/class/char.js +26 -11
  22. package/src/core/class/component.js +345 -137
  23. package/src/core/class/format.js +683 -519
  24. package/src/core/class/html.js +485 -305
  25. package/src/core/class/menu.js +133 -47
  26. package/src/core/class/nodeTransform.js +90 -71
  27. package/src/core/class/offset.js +408 -92
  28. package/src/core/class/selection.js +216 -106
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +422 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +496 -389
  34. package/src/core/section/actives.js +123 -27
  35. package/src/core/section/constructor.js +615 -206
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/events.js +622 -0
  42. package/src/helper/clipboard.js +59 -0
  43. package/src/helper/converter.js +202 -26
  44. package/src/helper/dom/domCheck.js +304 -0
  45. package/src/helper/dom/domQuery.js +669 -0
  46. package/src/helper/dom/domUtils.js +557 -0
  47. package/src/helper/dom/index.js +12 -0
  48. package/src/helper/env.js +46 -56
  49. package/src/helper/index.js +10 -4
  50. package/src/helper/keyCodeMap.js +183 -0
  51. package/src/helper/numbers.js +12 -8
  52. package/src/helper/unicode.js +9 -5
  53. package/src/langs/ckb.js +74 -4
  54. package/src/langs/cs.js +72 -2
  55. package/src/langs/da.js +73 -3
  56. package/src/langs/de.js +73 -4
  57. package/src/langs/en.js +23 -3
  58. package/src/langs/es.js +73 -4
  59. package/src/langs/fa.js +75 -3
  60. package/src/langs/fr.js +73 -3
  61. package/src/langs/he.js +73 -4
  62. package/src/langs/hu.js +230 -0
  63. package/src/langs/index.js +7 -3
  64. package/src/langs/it.js +70 -1
  65. package/src/langs/ja.js +72 -4
  66. package/src/langs/km.js +230 -0
  67. package/src/langs/ko.js +22 -2
  68. package/src/langs/lv.js +74 -5
  69. package/src/langs/nl.js +73 -4
  70. package/src/langs/pl.js +73 -4
  71. package/src/langs/pt_br.js +70 -1
  72. package/src/langs/ro.js +74 -5
  73. package/src/langs/ru.js +73 -4
  74. package/src/langs/se.js +73 -4
  75. package/src/langs/tr.js +73 -1
  76. package/src/langs/{ua.js → uk.js} +75 -6
  77. package/src/langs/ur.js +77 -8
  78. package/src/langs/zh_cn.js +74 -5
  79. package/src/modules/ApiManager.js +77 -54
  80. package/src/modules/Browser.js +667 -0
  81. package/src/modules/ColorPicker.js +162 -102
  82. package/src/modules/Controller.js +273 -142
  83. package/src/modules/Figure.js +925 -484
  84. package/src/modules/FileManager.js +121 -69
  85. package/src/modules/HueSlider.js +113 -61
  86. package/src/modules/Modal.js +291 -122
  87. package/src/modules/ModalAnchorEditor.js +383 -234
  88. package/src/modules/SelectMenu.js +270 -168
  89. package/src/modules/_DragHandle.js +2 -1
  90. package/src/modules/index.js +3 -3
  91. package/src/plugins/browser/audioGallery.js +83 -0
  92. package/src/plugins/browser/fileBrowser.js +103 -0
  93. package/src/plugins/browser/fileGallery.js +83 -0
  94. package/src/plugins/browser/imageGallery.js +81 -0
  95. package/src/plugins/browser/videoGallery.js +103 -0
  96. package/src/plugins/command/blockquote.js +40 -27
  97. package/src/plugins/command/exportPDF.js +134 -0
  98. package/src/plugins/command/fileUpload.js +229 -162
  99. package/src/plugins/command/list_bulleted.js +83 -47
  100. package/src/plugins/command/list_numbered.js +83 -47
  101. package/src/plugins/dropdown/align.js +66 -54
  102. package/src/plugins/dropdown/backgroundColor.js +63 -49
  103. package/src/plugins/dropdown/font.js +71 -47
  104. package/src/plugins/dropdown/fontColor.js +63 -48
  105. package/src/plugins/dropdown/formatBlock.js +70 -33
  106. package/src/plugins/dropdown/hr.js +92 -51
  107. package/src/plugins/dropdown/layout.js +37 -26
  108. package/src/plugins/dropdown/lineHeight.js +54 -38
  109. package/src/plugins/dropdown/list.js +60 -45
  110. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  111. package/src/plugins/dropdown/table.js +2003 -813
  112. package/src/plugins/dropdown/template.js +38 -26
  113. package/src/plugins/dropdown/textStyle.js +43 -31
  114. package/src/plugins/field/mention.js +147 -86
  115. package/src/plugins/index.js +32 -6
  116. package/src/plugins/input/fontSize.js +161 -108
  117. package/src/plugins/input/pageNavigator.js +70 -0
  118. package/src/plugins/modal/audio.js +358 -173
  119. package/src/plugins/modal/drawing.js +531 -0
  120. package/src/plugins/modal/embed.js +886 -0
  121. package/src/plugins/modal/image.js +674 -362
  122. package/src/plugins/modal/link.js +100 -71
  123. package/src/plugins/modal/math.js +367 -167
  124. package/src/plugins/modal/video.js +691 -335
  125. package/src/plugins/popup/anchor.js +222 -0
  126. package/src/suneditor.js +50 -13
  127. package/src/themes/dark.css +122 -0
  128. package/src/typedef.js +130 -0
  129. package/types/assets/icons/defaultIcons.d.ts +153 -0
  130. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  131. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  132. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  133. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  134. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  135. package/types/core/base/eventManager.d.ts +385 -0
  136. package/types/core/base/history.d.ts +81 -0
  137. package/types/core/class/char.d.ts +60 -0
  138. package/types/core/class/component.d.ts +212 -0
  139. package/types/core/class/format.d.ts +616 -0
  140. package/types/core/class/html.d.ts +422 -0
  141. package/types/core/class/menu.d.ts +126 -0
  142. package/types/core/class/nodeTransform.d.ts +93 -0
  143. package/types/core/class/offset.d.ts +522 -0
  144. package/types/core/class/selection.d.ts +188 -0
  145. package/types/core/class/shortcuts.d.ts +142 -0
  146. package/types/core/class/toolbar.d.ts +189 -0
  147. package/types/core/class/ui.d.ts +164 -0
  148. package/types/core/class/viewer.d.ts +140 -0
  149. package/types/core/editor.d.ts +610 -0
  150. package/types/core/section/actives.d.ts +46 -0
  151. package/types/core/section/constructor.d.ts +777 -0
  152. package/types/core/section/context.d.ts +45 -0
  153. package/types/core/section/documentType.d.ts +178 -0
  154. package/types/editorInjector/_classes.d.ts +41 -0
  155. package/types/editorInjector/_core.d.ts +92 -0
  156. package/types/editorInjector/index.d.ts +71 -0
  157. package/types/events.d.ts +273 -0
  158. package/types/helper/clipboard.d.ts +12 -0
  159. package/types/helper/converter.d.ts +197 -0
  160. package/types/helper/dom/domCheck.d.ts +189 -0
  161. package/types/helper/dom/domQuery.d.ts +223 -0
  162. package/types/helper/dom/domUtils.d.ts +226 -0
  163. package/types/helper/dom/index.d.ts +9 -0
  164. package/types/helper/env.d.ts +132 -0
  165. package/types/helper/index.d.ts +174 -0
  166. package/types/helper/keyCodeMap.d.ts +110 -0
  167. package/types/helper/numbers.d.ts +46 -0
  168. package/types/helper/unicode.d.ts +28 -0
  169. package/types/index.d.ts +120 -0
  170. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +173 -103
  171. package/types/langs/ckb.d.ts +3 -0
  172. package/types/langs/cs.d.ts +3 -0
  173. package/types/langs/da.d.ts +3 -0
  174. package/types/langs/de.d.ts +3 -0
  175. package/types/langs/en.d.ts +3 -0
  176. package/types/langs/es.d.ts +3 -0
  177. package/types/langs/fa.d.ts +3 -0
  178. package/types/langs/fr.d.ts +3 -0
  179. package/types/langs/he.d.ts +3 -0
  180. package/types/langs/hu.d.ts +3 -0
  181. package/types/langs/index.d.ts +54 -0
  182. package/types/langs/it.d.ts +3 -0
  183. package/types/langs/ja.d.ts +3 -0
  184. package/types/langs/km.d.ts +3 -0
  185. package/types/langs/ko.d.ts +3 -0
  186. package/types/langs/lv.d.ts +3 -0
  187. package/types/langs/nl.d.ts +3 -0
  188. package/types/langs/pl.d.ts +3 -0
  189. package/types/langs/pt_br.d.ts +3 -0
  190. package/types/langs/ro.d.ts +3 -0
  191. package/types/langs/ru.d.ts +3 -0
  192. package/types/langs/se.d.ts +3 -0
  193. package/types/langs/tr.d.ts +3 -0
  194. package/types/langs/uk.d.ts +3 -0
  195. package/types/langs/ur.d.ts +3 -0
  196. package/types/langs/zh_cn.d.ts +3 -0
  197. package/types/modules/ApiManager.d.ts +125 -0
  198. package/types/modules/Browser.d.ts +326 -0
  199. package/types/modules/ColorPicker.d.ts +131 -0
  200. package/types/modules/Controller.d.ts +251 -0
  201. package/types/modules/Figure.d.ts +517 -0
  202. package/types/modules/FileManager.d.ts +202 -0
  203. package/types/modules/HueSlider.d.ts +136 -0
  204. package/types/modules/Modal.d.ts +111 -0
  205. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  206. package/types/modules/SelectMenu.d.ts +194 -0
  207. package/types/modules/_DragHandle.d.ts +7 -0
  208. package/types/modules/index.d.ts +26 -0
  209. package/types/plugins/browser/audioGallery.d.ts +55 -0
  210. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  211. package/types/plugins/browser/fileGallery.d.ts +55 -0
  212. package/types/plugins/browser/imageGallery.d.ts +51 -0
  213. package/types/plugins/browser/videoGallery.d.ts +57 -0
  214. package/types/plugins/command/blockquote.d.ts +28 -0
  215. package/types/plugins/command/exportPDF.d.ts +46 -0
  216. package/types/plugins/command/fileUpload.d.ts +156 -0
  217. package/types/plugins/command/list_bulleted.d.ts +46 -0
  218. package/types/plugins/command/list_numbered.d.ts +46 -0
  219. package/types/plugins/dropdown/align.d.ts +60 -0
  220. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  221. package/types/plugins/dropdown/font.d.ts +54 -0
  222. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  223. package/types/plugins/dropdown/formatBlock.d.ts +54 -0
  224. package/types/plugins/dropdown/hr.d.ts +71 -0
  225. package/types/plugins/dropdown/layout.d.ts +40 -0
  226. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  227. package/types/plugins/dropdown/list.d.ts +39 -0
  228. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  229. package/types/plugins/dropdown/table.d.ts +627 -0
  230. package/types/plugins/dropdown/template.d.ts +40 -0
  231. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  232. package/types/plugins/field/mention.d.ts +102 -0
  233. package/types/plugins/index.d.ts +107 -0
  234. package/types/plugins/input/fontSize.d.ts +170 -0
  235. package/types/plugins/input/pageNavigator.d.ts +28 -0
  236. package/types/plugins/modal/audio.d.ts +269 -0
  237. package/types/plugins/modal/drawing.d.ts +246 -0
  238. package/types/plugins/modal/embed.d.ts +387 -0
  239. package/types/plugins/modal/image.d.ts +451 -0
  240. package/types/plugins/modal/link.d.ts +128 -0
  241. package/types/plugins/modal/math.d.ts +193 -0
  242. package/types/plugins/modal/video.d.ts +485 -0
  243. package/types/plugins/popup/anchor.d.ts +56 -0
  244. package/types/suneditor.d.ts +51 -0
  245. package/types/typedef.d.ts +233 -0
  246. package/.eslintignore +0 -7
  247. package/.eslintrc.json +0 -64
  248. package/src/assets/icons/_default.js +0 -194
  249. package/src/core/base/events.js +0 -320
  250. package/src/core/class/notice.js +0 -42
  251. package/src/helper/domUtils.js +0 -1177
  252. package/src/modules/FileBrowser.js +0 -271
  253. package/src/plugins/command/exportPdf.js +0 -168
  254. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  255. package/src/themes/test.css +0 -61
  256. package/typings/CommandPlugin.d.ts +0 -8
  257. package/typings/DialogPlugin.d.ts +0 -20
  258. package/typings/FileBrowserPlugin.d.ts +0 -30
  259. package/typings/Module.d.ts +0 -15
  260. package/typings/Plugin.d.ts +0 -42
  261. package/typings/SubmenuPlugin.d.ts +0 -8
  262. package/typings/_classes.d.ts +0 -17
  263. package/typings/_colorPicker.d.ts +0 -60
  264. package/typings/_core.d.ts +0 -55
  265. package/typings/align.d.ts +0 -5
  266. package/typings/audio.d.ts +0 -5
  267. package/typings/backgroundColor.d.ts +0 -5
  268. package/typings/blockquote.d.ts +0 -5
  269. package/typings/char.d.ts +0 -39
  270. package/typings/component.d.ts +0 -38
  271. package/typings/context.d.ts +0 -39
  272. package/typings/converter.d.ts +0 -33
  273. package/typings/dialog.d.ts +0 -28
  274. package/typings/domUtils.d.ts +0 -361
  275. package/typings/editor.d.ts +0 -7
  276. package/typings/editor.ts +0 -542
  277. package/typings/env.d.ts +0 -70
  278. package/typings/eventManager.d.ts +0 -37
  279. package/typings/events.d.ts +0 -262
  280. package/typings/fileBrowser.d.ts +0 -42
  281. package/typings/fileManager.d.ts +0 -67
  282. package/typings/font.d.ts +0 -5
  283. package/typings/fontColor.d.ts +0 -5
  284. package/typings/fontSize.d.ts +0 -5
  285. package/typings/format.d.ts +0 -191
  286. package/typings/formatBlock.d.ts +0 -5
  287. package/typings/history.d.ts +0 -48
  288. package/typings/horizontalRule.d.ts +0 -5
  289. package/typings/image.d.ts +0 -5
  290. package/typings/imageGallery.d.ts +0 -5
  291. package/typings/index.d.ts +0 -21
  292. package/typings/index.modules.d.ts +0 -11
  293. package/typings/index.plugins.d.ts +0 -58
  294. package/typings/lineHeight.d.ts +0 -5
  295. package/typings/link.d.ts +0 -5
  296. package/typings/list.d.ts +0 -5
  297. package/typings/math.d.ts +0 -5
  298. package/typings/mediaContainer.d.ts +0 -25
  299. package/typings/mention.d.ts +0 -5
  300. package/typings/node.d.ts +0 -57
  301. package/typings/notice.d.ts +0 -16
  302. package/typings/numbers.d.ts +0 -29
  303. package/typings/offset.d.ts +0 -24
  304. package/typings/options.d.ts +0 -589
  305. package/typings/paragraphStyle.d.ts +0 -5
  306. package/typings/resizing.d.ts +0 -141
  307. package/typings/selection.d.ts +0 -94
  308. package/typings/shortcuts.d.ts +0 -13
  309. package/typings/suneditor.d.ts +0 -9
  310. package/typings/table.d.ts +0 -5
  311. package/typings/template.d.ts +0 -5
  312. package/typings/textStyle.d.ts +0 -5
  313. package/typings/toolbar.d.ts +0 -32
  314. package/typings/unicode.d.ts +0 -25
  315. package/typings/video.d.ts +0 -5
@@ -2,25 +2,103 @@
2
2
  * @fileoverview Offset class
3
3
  */
4
4
 
5
- import { getParentElement, isWysiwygFrame, hasClass, addClass, removeClass, getClientSize } from '../../helper/domUtils';
6
- import { domUtils, numbers } from '../../helper';
5
+ import CoreInjector from '../../editorInjector/_core';
6
+ import { getParentElement } from '../../helper/dom/domQuery';
7
+ import { isWysiwygFrame, isElement } from '../../helper/dom/domCheck';
8
+ import { hasClass, addClass, removeClass, getClientSize } from '../../helper/dom/domUtils';
9
+ import { numbers } from '../../helper';
7
10
  import { _w, _d } from '../../helper/env';
8
11
 
9
- const Offset = function (editor) {
10
- this.editor = editor;
11
- this.options = editor.options;
12
- this.context = editor.context;
12
+ /**
13
+ * @typedef {Omit<Offset & Partial<__se__EditorInjector>, 'offset'>} OffsetThis
14
+ */
15
+
16
+ /**
17
+ * @typedef {Object} RectsInfo Bounding rectangle information of the selection range.
18
+ * @property {number} rects.left - The left position of the selection.
19
+ * @property {number} rects.right - The right position of the selection.
20
+ * @property {number} rects.top - The top position of the selection.
21
+ * @property {number} rects.bottom - The bottom position of the selection.
22
+ * @property {boolean} [rects.noText] - Whether the selection contains text.
23
+ * @property {number} [rects.width] - The width of the selection.
24
+ * @property {number} [rects.height] - The height of the selection.
25
+ */
26
+
27
+ /**
28
+ * @typedef {Object} OffsetInfo
29
+ * @property {number} top - The top position of the node relative to the entire document, including iframe offsets.
30
+ * @property {number} left - The left position of the node relative to the entire document, including iframe offsets.
31
+ */
32
+
33
+ /**
34
+ * @typedef {Object} OffsetLocalInfo
35
+ * @property {number} top - The top position of the node relative to the WYSIWYG editor.
36
+ * @property {number} left - The left position of the node relative to the WYSIWYG editor.
37
+ * @property {number} right - The right position of the node relative to the WYSIWYG editor.
38
+ * @property {number} scrollX - The horizontal scroll offset inside the WYSIWYG editor.
39
+ * @property {number} scrollY - The vertical scroll offset inside the WYSIWYG editor.
40
+ */
41
+
42
+ /**
43
+ * @typedef {Object} OffsetGlobalInfo
44
+ * @property {number} top - The top position of the element relative to the entire document.
45
+ * @property {number} left - The left position of the element relative to the entire document.
46
+ * @property {number} width - The total width of the element, including its content, padding, and border.
47
+ * @property {number} height - The total height of the element, including its content, padding, and border.
48
+ * @property {number} scrollTop - The amount of vertical scrolling applied to the element.
49
+ * @property {number} scrollLeft - The amount of horizontal scrolling applied to the element.
50
+ */
51
+
52
+ /**
53
+ * @typedef {Object} OffsetGlobalScrollInfo
54
+ * @property {number} top - Total top scroll distance
55
+ * @property {number} left - Total left scroll distance
56
+ * @property {number} width - Total width including scrollable area
57
+ * @property {number} height - Total height including scrollable area
58
+ * @property {number} x - Horizontal offset from the top reference element
59
+ * @property {number} y - Vertical offset from the top reference element
60
+ * @property {HTMLElement|Window|null} ohOffsetEl - Element or window used as the vertical scroll reference
61
+ * @property {HTMLElement|Window|null} owOffsetEl - Element or window used as the horizontal scroll reference
62
+ * @property {number} oh - Height of the vertical scrollable area (clientHeight)
63
+ * @property {number} ow - Width of the horizontal scrollable area (clientWidth)
64
+ * @property {boolean} heightEditorRefer - Indicates if the vertical scroll reference is the editor area
65
+ * @property {boolean} widthEditorRefer - Indicates if the horizontal scroll reference is the editor area
66
+ * @property {number} ts - Top position of the height offset element relative to the viewport
67
+ * @property {number} ls - Left position of the width offset element relative to the viewport
68
+ */
69
+
70
+ /**
71
+ * @typedef {Object} OffsetWWScrollInfo
72
+ * @property {number} top - The top scroll offset inside the WYSIWYG editor.
73
+ * @property {number} left - The left scroll offset inside the WYSIWYG editor.
74
+ * @property {number} width - The total width of the WYSIWYG editor's scrollable area.
75
+ * @property {number} height - The total height of the WYSIWYG editor's scrollable area.
76
+ * @property {number} bottom - The sum of `top` and `height`, representing the bottom-most scrollable position.
77
+ * @property {RectsInfo} rects - The bounding rectangle of the editor's visible area.
78
+ */
79
+
80
+ /**
81
+ * @constructor
82
+ * @this {OffsetThis}
83
+ * @description Offset class, get the position of the element
84
+ * @param {__se__EditorCore} editor - The root editor instance
85
+ */
86
+ function Offset(editor) {
87
+ CoreInjector.call(this, editor);
88
+
89
+ // members
13
90
  this._scrollEvent = null;
14
91
  this._elTop = 0;
15
92
  this._scrollY = 0;
16
93
  this._isFixed = false;
17
- };
94
+ }
18
95
 
19
96
  Offset.prototype = {
20
97
  /**
21
- * @description Gets the position just outside the argument's internal editor(wysiwygFrame). [getLocal() + iframe offset]
22
- * @param {Node} node Target node
23
- * @returns {{top:boolean, left:boolean}}
98
+ * @this {OffsetThis}
99
+ * @description Gets the position just outside the argument's internal editor (wysiwygFrame).
100
+ * @param {Node} node Target node.
101
+ * @returns {OffsetInfo} Position relative to the editor frame.
24
102
  */
25
103
  get(node) {
26
104
  const wFrame = this.editor.frameContext.get('wysiwygFrame');
@@ -34,49 +112,67 @@ Offset.prototype = {
34
112
  },
35
113
 
36
114
  /**
37
- * @description Gets the position in the internal editor of the argument.
38
- * @param {Node} node Target node
39
- * @returns {{top:boolean, left:boolean}}
115
+ * @this {OffsetThis}
116
+ * @description Gets the position inside the internal editor of the argument.
117
+ * @param {Node} node Target node.
118
+ * @returns {OffsetLocalInfo} Position relative to the WYSIWYG editor.
40
119
  */
41
120
  getLocal(node) {
121
+ const target = /** @type {HTMLElement} */ (node);
42
122
  let offsetLeft = 0;
43
123
  let offsetTop = 0;
44
- let offsetElement = node.nodeType === 3 ? node.parentElement : node;
45
- const wysiwyg = getParentElement(node, isWysiwygFrame.bind(this));
124
+ let l = 0;
125
+ let t = 0;
126
+ let r = 0;
127
+ let offsetElement = target.nodeType === 3 ? target.parentElement : target;
128
+ const targetWidth = target.offsetWidth;
129
+ const wysiwyg = getParentElement(target, isWysiwygFrame.bind(this));
46
130
  const self = offsetElement;
47
131
 
48
132
  while (offsetElement && !hasClass(offsetElement, 'se-wrapper') && offsetElement !== wysiwyg) {
49
133
  offsetLeft += offsetElement.offsetLeft - (self !== offsetElement ? offsetElement.scrollLeft : 0);
50
134
  offsetTop += offsetElement.offsetTop + (self !== offsetElement ? offsetElement.scrollTop : 0);
51
- offsetElement = offsetElement.offsetParent;
135
+ offsetElement = /** @type {HTMLElement} */ (offsetElement.offsetParent);
136
+ }
137
+
138
+ const wwFrame = this.editor.frameContext.get('wysiwygFrame');
139
+ if (this.editor.frameContext.get('wysiwyg').contains(target)) {
140
+ l = wwFrame.offsetLeft;
141
+ t = wwFrame.offsetTop;
142
+ r = wwFrame.parentElement.offsetWidth - (wwFrame.offsetLeft + wwFrame.offsetWidth);
52
143
  }
53
144
 
54
145
  const eventWysiwyg = this.editor.frameContext.get('eventWysiwyg');
146
+ offsetLeft += l;
147
+ offsetTop += t - (wysiwyg ? wysiwyg.scrollTop : 0);
55
148
  return {
56
149
  left: offsetLeft,
57
- top: offsetTop - (wysiwyg ? wysiwyg.scrollTop : 0),
150
+ top: offsetTop,
151
+ right: offsetElement?.offsetWidth ? offsetElement.offsetWidth - (offsetLeft - l + targetWidth) + r : 0,
58
152
  scrollX: eventWysiwyg.scrollX || eventWysiwyg.scrollLeft || 0,
59
153
  scrollY: eventWysiwyg.scrollY || eventWysiwyg.scrollTop || 0
60
154
  };
61
155
  },
62
156
 
63
157
  /**
64
- * @description Returns the position of the argument, relative to global document. {left:0, top:0, scroll: 0}
65
- * @param {Element} element Target element
66
- * @returns {{top:boolean, left:boolean}}
158
+ * @this {OffsetThis}
159
+ * @description Returns the position of the argument relative to the global document.
160
+ * @param {?Node=} node Target element.
161
+ * @returns {OffsetGlobalInfo} Global position and scroll values.
67
162
  */
68
- getGlobal(element) {
163
+ getGlobal(node) {
69
164
  const topArea = this.editor.frameContext.get('topArea');
70
165
  const wFrame = this.editor.frameContext.get('wysiwygFrame');
71
166
 
72
167
  let isTop = false;
73
168
  let targetAbs = false;
74
- if (!element) element = topArea;
75
- if (element === topArea) isTop = true;
76
- if (!isTop && element.nodeType === 1) {
77
- targetAbs = _w.getComputedStyle(element).position === 'absolute';
169
+ if (!node) node = topArea;
170
+ if (node === topArea) isTop = true;
171
+ if (!isTop && isElement(node)) {
172
+ targetAbs = _w.getComputedStyle(node).position === 'absolute';
78
173
  }
79
174
 
175
+ let element = /** @type {HTMLElement} */ (node);
80
176
  const w = element.offsetWidth;
81
177
  const h = element.offsetHeight;
82
178
  let t = 0,
@@ -89,15 +185,15 @@ Offset.prototype = {
89
185
  l += element.offsetLeft;
90
186
  st += element.scrollTop;
91
187
  sl += element.scrollLeft;
92
- element = element.offsetParent;
188
+ element = /** @type {HTMLElement} */ (element.offsetParent);
93
189
  }
94
190
 
95
- if (!targetAbs && !isTop && /^iframe$/i.test(wFrame.nodeName) && wFrame.contains(element)) {
191
+ if (!targetAbs && !isTop && /^iframe$/i.test(wFrame.nodeName) && this.editor.frameContext.get('wysiwyg').contains(element)) {
96
192
  element = this.editor.frameContext.get('wrapper');
97
193
  while (element) {
98
194
  t += element.offsetTop;
99
195
  l += element.offsetLeft;
100
- element = element.offsetParent;
196
+ element = /** @type {HTMLElement} */ (element.offsetParent);
101
197
  }
102
198
  }
103
199
 
@@ -112,20 +208,22 @@ Offset.prototype = {
112
208
  },
113
209
 
114
210
  /**
211
+ * @this {OffsetThis}
115
212
  * @description Gets the current editor-relative scroll offset.
116
- * @param {Element} element Target element
117
- * @returns {{top:boolean, left:boolean, width:boolean, height:boolean}}
213
+ * @param {?Node=} node Target element.
214
+ * @returns {OffsetGlobalScrollInfo} Global scroll information.
118
215
  */
119
- getGlobalScroll(element) {
216
+ getGlobalScroll(node) {
120
217
  const topArea = this.editor.frameContext.get('topArea');
121
218
  let isTop = false;
122
219
  let targetAbs = false;
123
- if (!element) element = topArea;
124
- if (element === topArea) isTop = true;
125
- if (!isTop && element.nodeType === 1) {
126
- targetAbs = _w.getComputedStyle(element).position === 'absolute';
220
+ if (!node) node = topArea;
221
+ if (node === topArea) isTop = true;
222
+ if (!isTop && isElement(node)) {
223
+ targetAbs = _w.getComputedStyle(node).position === 'absolute';
127
224
  }
128
225
 
226
+ const element = /** @type {HTMLElement} */ (node);
129
227
  let t = 0,
130
228
  l = 0,
131
229
  h = 0,
@@ -190,7 +288,7 @@ Offset.prototype = {
190
288
  }
191
289
  }
192
290
 
193
- el = this._shadowRoot?.host;
291
+ el = /** @type {HTMLElement} */ (this._shadowRoot?.host);
194
292
  if (el) ohOffsetEl = owOffsetEl = topArea;
195
293
  while (el) {
196
294
  t += el.scrollTop;
@@ -227,8 +325,8 @@ Offset.prototype = {
227
325
  const clientSize = getClientSize(this.editor.frameContext.get('_wd'));
228
326
  return {
229
327
  top: t,
230
- ts: ts,
231
328
  left: l,
329
+ ts: ts,
232
330
  ls: ls,
233
331
  width: w,
234
332
  height: h,
@@ -244,12 +342,13 @@ Offset.prototype = {
244
342
  },
245
343
 
246
344
  /**
345
+ * @this {OffsetThis}
247
346
  * @description Get the scroll info of the WYSIWYG area.
248
- * @returns {{top:boolean, left:boolean}}
347
+ * @returns {OffsetWWScrollInfo} Scroll information within the editor.
249
348
  */
250
349
  getWWScroll() {
251
350
  const eventWysiwyg = this.editor.frameContext.get('wysiwyg');
252
- const rects = this.editor.selection.getRects(eventWysiwyg, 'start').rects;
351
+ const rects = this.selection.getRects(eventWysiwyg, 'start').rects;
253
352
  const top = eventWysiwyg.scrollY || eventWysiwyg.scrollTop || 0;
254
353
  const height = eventWysiwyg.scrollHeight || 0;
255
354
 
@@ -263,6 +362,15 @@ Offset.prototype = {
263
362
  };
264
363
  },
265
364
 
365
+ /**
366
+ * @this {OffsetThis}
367
+ * @description Sets the relative position of an element
368
+ * @param {HTMLElement} element Element to position
369
+ * @param {HTMLElement} e_container Element's root container
370
+ * @param {HTMLElement} target Target element to position against
371
+ * @param {HTMLElement} t_container Target's root container
372
+ * @param {boolean} _reload Whether to reload position
373
+ */
266
374
  setRelPosition(element, e_container, target, t_container, _reload) {
267
375
  this._scrollY = _w.scrollY;
268
376
  let wy = 0;
@@ -272,7 +380,7 @@ Offset.prototype = {
272
380
  wy += this._scrollY;
273
381
  break;
274
382
  }
275
- } while (!domUtils.hasClass(tCon, 'sun-editor') && (tCon = tCon.parentElement));
383
+ } while (!hasClass(tCon, 'sun-editor') && (tCon = tCon.parentElement));
276
384
 
277
385
  if (!_reload) {
278
386
  this.__removeGlobalEvent();
@@ -308,7 +416,7 @@ Offset.prototype = {
308
416
  let offsetEl = target;
309
417
  while (offsetEl && offsetEl !== e_container) {
310
418
  bt += offsetEl.offsetTop;
311
- offsetEl = offsetEl.offsetParent;
419
+ offsetEl = /** @type {HTMLElement} */ (offsetEl.offsetParent);
312
420
  }
313
421
 
314
422
  const menuHeight_bottom = getClientSize(_d).h - (containerTop - scrollTop + bt + target.offsetHeight);
@@ -335,10 +443,23 @@ Offset.prototype = {
335
443
  }
336
444
  },
337
445
 
446
+ /**
447
+ * @this {OffsetThis}
448
+ * @description Sets the absolute position of an element
449
+ * @param {HTMLElement} element Element to position
450
+ * @param {HTMLElement} target Target element
451
+ * @param {Object} params Position parameters
452
+ * @param {boolean} [params.isWWTarget=false] Whether the target is within the editor's WYSIWYG area
453
+ * @param {{left:number, top:number}} [params.addOffset={left:0, top:0}] Additional offset
454
+ * @param {"bottom"|"top"} [params.position="bottom"] Position ('bottom'|'top')
455
+ * @param {*} params.inst Instance object of caller
456
+ * @returns {{position: "top" | "bottom"} | undefined} Success -> {position: current position}
457
+ */
338
458
  setAbsPosition(element, target, params) {
339
- const addOffset = params.addOffset || {
459
+ const addOffset = {
340
460
  left: 0,
341
- top: 0
461
+ top: 0,
462
+ ...params.addOffset
342
463
  };
343
464
  const position = params.position || 'bottom';
344
465
  const inst = params.inst;
@@ -349,14 +470,13 @@ Offset.prototype = {
349
470
  }
350
471
 
351
472
  const isWWTarget = this.editor.frameContext.get('wrapper').contains(target) || params.isWWTarget;
352
- const isCtrlTarget = domUtils.getParentElement(target, '.se-controller');
473
+ const isCtrlTarget = getParentElement(target, '.se-controller');
353
474
  const isTargetAbs = isWWTarget && !isCtrlTarget;
354
475
  const clientSize = getClientSize(_d);
355
476
  const wwScroll = isTargetAbs ? this.getWWScroll() : this._getWindowScroll();
356
- const targetRect = isCtrlTarget ? target.getBoundingClientRect() : this.editor.selection.getRects(target, 'start').rects;
477
+ const targetRect = isCtrlTarget ? target.getBoundingClientRect() : this.selection.getRects(target, 'start').rects;
357
478
  const targetOffset = this.getGlobal(target);
358
- const arrow = hasClass(element.firstElementChild, 'se-arrow') ? element.firstElementChild : null;
359
- const isIframe = isTargetAbs && this.editor.frameOptions.get('iframe');
479
+ const arrow = /** @type {HTMLElement} */ (hasClass(element.firstElementChild, 'se-arrow') ? element.firstElementChild : null);
360
480
 
361
481
  // top ----------------------------------------------------------------------------------------------------
362
482
  const ah = arrow ? arrow.offsetHeight : 0;
@@ -365,51 +485,10 @@ Offset.prototype = {
365
485
  // margin
366
486
  const tmtw = targetRect.top;
367
487
  const tmbw = clientSize.h - targetRect.bottom;
368
- let toolbarH = !this.editor.toolbar._sticky && (this.editor.isBalloon || this.editor.isInline) ? 0 : this.context.get('toolbar.main').offsetHeight;
369
- let rmt, rmb;
370
- let rt = 0;
371
- if (this.editor.frameContext.get('isFullScreen')) {
372
- rmt = tmtw - toolbarH;
373
- rmb = tmbw;
374
- } else {
375
- const tMargin = targetRect.top;
376
- const bMargin = clientSize.h - targetRect.bottom;
377
- const editorOffset = this.getGlobal();
378
- const editorScroll = this.getGlobalScroll();
379
- const statusBarH = this.editor.frameContext.get('statusbar')?.offsetHeight || 0;
380
-
381
- if (isIframe) {
382
- const emt = editorOffset.top - editorScroll.top - editorScroll.ts;
383
- const editorH = this.editor.frameContext.get('topArea').offsetHeight;
384
- rmt = targetRect.top - emt;
385
- rmb = bMargin - (editorScroll.oh - (editorH + emt) + statusBarH);
386
- } else {
387
- rt = !this.editor.toolbar._sticky && !this.options.get('toolbar_container') ? toolbarH : 0;
388
- const wst = !isTargetAbs && /\d+/.test(this.editor.frameOptions.get('height')) ? editorOffset.top - _w.scrollY + rt : 0;
389
- const wsb = !isTargetAbs && /\d+/.test(this.editor.frameOptions.get('height')) ? _w.innerHeight - (editorOffset.top + editorOffset.height - _w.scrollY) : 0;
390
- let st = wst;
391
- if (toolbarH > wst) {
392
- if (this.editor.toolbar._sticky) {
393
- st = toolbarH;
394
- toolbarH = 0;
395
- } else {
396
- st = wst + toolbarH;
397
- }
398
- } else if (this.options.get('toolbar_container')) {
399
- toolbarH = 0;
400
- } else {
401
- st = wst + (this.editor.toolbar._sticky ? toolbarH : 0);
402
- }
403
-
404
- rmt = targetRect.top - st;
405
- rmb = wwScroll.rects.bottom - targetRect.bottom - wsb - statusBarH;
406
- }
407
-
408
- // display margin
409
- rmt = (rmt > 0 ? tMargin : rmt) - toolbarH;
410
- rmb = rmb > 0 ? bMargin : rmb;
411
- }
488
+ const toolbarH = !this.editor.toolbar._sticky && (this.editor.isBalloon || this.editor.isInline) ? 0 : this.context.get('toolbar.main').offsetHeight;
412
489
 
490
+ // check margin
491
+ const { rmt, rmb, rt } = this._getVMargin(tmtw, tmbw, toolbarH, clientSize, targetRect, isTargetAbs, wwScroll);
413
492
  if (isWWTarget && (rmb + targetH <= 0 || rmt + rt + targetH <= 0)) return;
414
493
 
415
494
  let t = addOffset.top;
@@ -512,9 +591,216 @@ Offset.prototype = {
512
591
  addOffset: addOffset
513
592
  };
514
593
 
594
+ return { position: arrowDir === 'up' ? 'bottom' : 'top' };
595
+ },
596
+
597
+ /**
598
+ * @this {OffsetThis}
599
+ * @description Sets the position of an element relative to a range
600
+ * @param {HTMLElement} element Element to position
601
+ * @param {?Range} range Range to position against.
602
+ * - if null, the current selection range is used
603
+ * @param {Object} [options={}] Position options
604
+ * @param {"bottom"|"top"} [options.position="bottom"] Position ('bottom'|'top')
605
+ * @param {number} [options.addTop=0] Additional top offset
606
+ * @returns {boolean} Success / Failure
607
+ */
608
+ setRangePosition(element, range, { position, addTop } = {}) {
609
+ element.style.top = '-10000px';
610
+ element.style.visibility = 'hidden';
611
+ element.style.display = 'block';
612
+
613
+ let positionTop = position === 'top';
614
+ range = range || this.selection.getRange();
615
+ const rectsObj = this.selection.getRects(range, positionTop ? 'start' : 'end');
616
+ positionTop = rectsObj.position === 'start';
617
+
618
+ const isFullScreen = this.editor.frameContext.get('isFullScreen');
619
+ const topArea = this.editor.frameContext.get('topArea');
620
+ const rects = rectsObj.rects;
621
+ const scrollLeft = isFullScreen ? 0 : rectsObj.scrollLeft;
622
+ const scrollTop = isFullScreen ? 0 : rectsObj.scrollTop;
623
+ const editorWidth = topArea.offsetWidth;
624
+ const offsets = this.getGlobal(topArea);
625
+ const editorLeft = offsets.left;
626
+ const toolbarWidth = element.offsetWidth;
627
+ const toolbarHeight = element.offsetHeight;
628
+
629
+ this._setOffsetOnRange(positionTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop);
630
+ if (this.getGlobal(element).top - offsets.top < 0) {
631
+ positionTop = !positionTop;
632
+ this._setOffsetOnRange(positionTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop);
633
+ }
634
+
635
+ if (toolbarWidth !== element.offsetWidth || toolbarHeight !== element.offsetHeight) {
636
+ this._setOffsetOnRange(positionTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop);
637
+ }
638
+
639
+ // check margin
640
+ const isTargetAbs = !this.carrierWrapper.contains(element);
641
+ const clientSize = getClientSize(_d);
642
+ const wwScroll = isTargetAbs ? this.getWWScroll() : this._getWindowScroll();
643
+ const targetH = rects.height;
644
+ const tmtw = rects.top;
645
+ const tmbw = clientSize.h - rects.bottom;
646
+ const toolbarH = !this.editor.toolbar._sticky && (this.editor.isBalloon || this.editor.isInline) ? 0 : this.context.get('toolbar.main').offsetHeight;
647
+
648
+ const { rmt, rmb, rt } = this._getVMargin(tmtw, tmbw, toolbarH, clientSize, rects, isTargetAbs, wwScroll);
649
+ if (rmb + targetH <= 0 || rmt + rt + targetH <= 0) return;
650
+
651
+ _w.setTimeout(() => {
652
+ element.style.visibility = '';
653
+ }, 0);
654
+
515
655
  return true;
516
656
  },
517
657
 
658
+ /**
659
+ * @private
660
+ * @this {OffsetThis}
661
+ * @description Sets the position of an element relative to the selection range in the editor.
662
+ * - This method calculates the top and left offsets for the element, ensuring it
663
+ * - does not overflow the editor boundaries and adjusts the arrow positioning accordingly.
664
+ * @param {boolean} isDirTop - Determines whether the element should be positioned above (`true`) or below (`false`) the target.
665
+ * @param {RectsInfo} rects - Bounding rectangle information of the selection range.
666
+ * @param {HTMLElement} element - The element to be positioned.
667
+ * @param {number} editorLeft - The left position of the editor.
668
+ * @param {number} editorWidth - The width of the editor.
669
+ * @param {number} scrollLeft - The horizontal scroll offset.
670
+ * @param {number} scrollTop - The vertical scroll offset.
671
+ * @param {number} [addTop=0] - Additional top margin adjustment.
672
+ */
673
+ _setOffsetOnRange(isDirTop, rects, element, editorLeft, editorWidth, scrollLeft, scrollTop, addTop = 0) {
674
+ const padding = 1;
675
+ const arrow = /** @type {HTMLElement} */ (element.querySelector('.se-arrow '));
676
+ const arrowMargin = Math.round(arrow.offsetWidth / 2);
677
+ const elW = element.offsetWidth;
678
+ const elH = rects.noText && !isDirTop ? 0 : element.offsetHeight;
679
+
680
+ const absoluteLeft = (isDirTop ? rects.left : rects.right) - editorLeft - elW / 2 + scrollLeft;
681
+ const overRight = absoluteLeft + elW - editorWidth;
682
+
683
+ let t = (isDirTop ? rects.top - elH - arrowMargin : rects.bottom + arrowMargin) - (rects.noText ? 0 : addTop) + scrollTop;
684
+ const l = absoluteLeft < 0 ? padding : overRight < 0 ? absoluteLeft : absoluteLeft - overRight - padding - 1;
685
+
686
+ let resetTop = false;
687
+ const space = t + (isDirTop ? this.getGlobal(this.editor.frameContext.get('topArea')).top : element.offsetHeight - this.editor.frameContext.get('wysiwyg').offsetHeight);
688
+ if (!isDirTop && space > 0 && this._getPageBottomSpace() < space) {
689
+ isDirTop = true;
690
+ resetTop = true;
691
+ } else if (isDirTop && _d.documentElement.offsetTop > space) {
692
+ isDirTop = false;
693
+ resetTop = true;
694
+ }
695
+
696
+ if (resetTop) t = (isDirTop ? rects.top - elH - arrowMargin : rects.bottom + arrowMargin) - (rects.noText ? 0 : addTop) + scrollTop;
697
+
698
+ element.style.left = Math.floor(l) + 'px';
699
+ element.style.top = Math.floor(t) + 'px';
700
+
701
+ if (isDirTop) {
702
+ removeClass(arrow, 'se-arrow-up');
703
+ addClass(arrow, 'se-arrow-down');
704
+ } else {
705
+ removeClass(arrow, 'se-arrow-down');
706
+ addClass(arrow, 'se-arrow-up');
707
+ }
708
+
709
+ const arrow_left = Math.floor(elW / 2 + (absoluteLeft - l));
710
+ arrow.style.left = (arrow_left + arrowMargin > element.offsetWidth ? element.offsetWidth - arrowMargin : arrow_left < arrowMargin ? arrowMargin : arrow_left) + 'px';
711
+ },
712
+
713
+ /**
714
+ * @private
715
+ * @this {OffsetThis}
716
+ * @description Get available space from page bottom
717
+ * @returns {number} Available space
718
+ */
719
+ _getPageBottomSpace() {
720
+ const topArea = this.editor.frameContext.get('topArea');
721
+ return _d.documentElement.scrollHeight - (this.getGlobal(topArea).top + topArea.offsetHeight);
722
+ },
723
+
724
+ /**
725
+ * @private
726
+ * @this {OffsetThis}
727
+ * @description Calculates the vertical margin offsets for the target element relative to the editor frame.
728
+ * - This method determines the top and bottom margins based on various conditions such as
729
+ * - fullscreen mode, iframe usage, toolbar height, and scroll positions.
730
+ * @param {number} tmtw Top margin to window
731
+ * @param {number} tmbw Bottom margin to window
732
+ * @param {number} toolbarH Toolbar height
733
+ * @param {{w: number, h: number}} clientSize documentElement.clientWidth, documentElement.clientHeight
734
+ * @param {RectsInfo} targetRect Target rect object
735
+ * @param {boolean} isTargetAbs Is target absolute position
736
+ * @param {OffsetWWScrollInfo} wwScroll WYSIWYG scroll info
737
+ * @returns {{rmt:number, rmb:number, rt:number}} Margin values (rmt: top margin, rmb: bottom margin, rt: Toolbar height offset adjustment)
738
+ */
739
+ _getVMargin(tmtw, tmbw, toolbarH, clientSize, targetRect, isTargetAbs, wwScroll) {
740
+ let rmt = 0;
741
+ let rmb = 0;
742
+ let rt = 0;
743
+ if (this.editor.frameContext.get('isFullScreen')) {
744
+ rmt = tmtw - toolbarH;
745
+ rmb = tmbw;
746
+ } else {
747
+ const isIframe = isTargetAbs && this.editor.frameOptions.get('iframe');
748
+ const tMargin = targetRect.top;
749
+ const bMargin = clientSize.h - targetRect.bottom;
750
+ const editorOffset = this.getGlobal();
751
+ const editorScroll = this.getGlobalScroll();
752
+ const statusBarH = this.editor.frameContext.get('statusbar')?.offsetHeight || 0;
753
+
754
+ if (isIframe) {
755
+ const emt = editorOffset.top - editorScroll.top - editorScroll.ts;
756
+ const editorH = this.editor.frameContext.get('topArea').offsetHeight;
757
+ rmt = targetRect.top - emt;
758
+ rmb = bMargin - (editorScroll.oh - (editorH + emt) + statusBarH);
759
+ } else {
760
+ rt = !this.editor.toolbar._sticky && !this.options.get('toolbar_container') ? toolbarH : 0;
761
+ const wst = !isTargetAbs && /\d+/.test(this.editor.frameOptions.get('height')) ? editorOffset.top - _w.scrollY + rt : 0;
762
+ const wsb = !isTargetAbs && /\d+/.test(this.editor.frameOptions.get('height')) ? _w.innerHeight - (editorOffset.top + editorOffset.height - _w.scrollY) : 0;
763
+ let st = wst;
764
+ if (toolbarH > wst) {
765
+ if (this.editor.toolbar._sticky) {
766
+ st = toolbarH;
767
+ toolbarH = 0;
768
+ } else {
769
+ st = wst + toolbarH;
770
+ }
771
+ } else if (this.options.get('toolbar_container')) {
772
+ toolbarH = 0;
773
+ } else {
774
+ st = wst + (this.editor.toolbar._sticky ? toolbarH : 0);
775
+ }
776
+
777
+ rmt = targetRect.top - st;
778
+ rmb = wwScroll.rects.bottom - targetRect.bottom - wsb - statusBarH;
779
+ }
780
+
781
+ // display margin
782
+ rmt = (rmt > 0 ? tMargin : rmt) - toolbarH;
783
+ rmb = rmb > 0 ? bMargin : rmb;
784
+ }
785
+
786
+ return {
787
+ rmt,
788
+ rmb,
789
+ rt
790
+ };
791
+ },
792
+
793
+ /**
794
+ * @private
795
+ * @this {OffsetThis}
796
+ * @description Sets the visibility and direction of the arrow element.
797
+ * - This method applies the appropriate class (`se-arrow-up` or `se-arrow-down`)
798
+ * - based on the specified direction key and adjusts the visibility of the arrow.
799
+ * @param {HTMLElement} arrow - The arrow element to be updated.
800
+ * @param {string} key - The direction of the arrow. ("up"|"down"|"")
801
+ * - Accepts `'up'` for an upward arrow, `'down'` for a downward arrow,
802
+ * - or any other value to hide the arrow.
803
+ */
518
804
  _setArrow(arrow, key) {
519
805
  if (key === 'up') {
520
806
  if (arrow) arrow.style.visibility = '';
@@ -529,13 +815,29 @@ Offset.prototype = {
529
815
  }
530
816
  },
531
817
 
818
+ /**
819
+ * @private
820
+ * @this {OffsetThis}
821
+ * @description Retrieves the current window scroll position and viewport size.
822
+ * - Returns an object containing the scroll offsets, viewport dimensions, and boundary rects.
823
+ * @returns {{
824
+ * top: number,
825
+ * left: number,
826
+ * width: number,
827
+ * height: number,
828
+ * bottom: number,
829
+ * rects: RectsInfo
830
+ * }} An object with scroll and viewport information.
831
+ */
832
+
532
833
  _getWindowScroll() {
533
- const viewPort = domUtils.getClientSize(_d);
834
+ const viewPort = getClientSize(_d);
534
835
  return {
535
836
  top: _w.scrollY,
536
837
  left: _w.scrollX,
537
838
  width: viewPort.w,
538
839
  height: viewPort.h,
840
+ bottom: _w.scrollY + viewPort.h,
539
841
  rects: {
540
842
  left: 0,
541
843
  top: 0,
@@ -546,6 +848,12 @@ Offset.prototype = {
546
848
  };
547
849
  },
548
850
 
851
+ /**
852
+ * @private
853
+ * @this {OffsetThis}
854
+ * @description Removes the global scroll event listener from the editor.
855
+ * - Resets related scroll tracking properties.
856
+ */
549
857
  __removeGlobalEvent() {
550
858
  if (this._scrollEvent) {
551
859
  this._scrollEvent = this.editor.eventManager.removeGlobalEvent(this._scrollEvent);
@@ -557,6 +865,14 @@ Offset.prototype = {
557
865
  constructor: Offset
558
866
  };
559
867
 
868
+ /**
869
+ * @private
870
+ * @this {OffsetThis}
871
+ * @param {HTMLElement} element - The element to check for a specific class name.
872
+ * @param {HTMLElement} e_container - The root container of the element.
873
+ * @param {HTMLElement} target - The target element to position against.
874
+ * @param {HTMLElement} t_container - The root container of the target element.
875
+ */
560
876
  function FixedScroll(element, e_container, target, t_container) {
561
877
  const isFixed = /^fixed$/i.test(_w.getComputedStyle(t_container).position);
562
878
  if (!this._isFixed) {