suneditor 2.46.2 → 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.json +64 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/LICENSE.txt +1 -1
  5. package/README.md +174 -805
  6. package/dist/suneditor.min.css +1 -0
  7. package/dist/suneditor.min.js +1 -2
  8. package/package.json +96 -69
  9. package/src/assets/icons/_default.js +194 -0
  10. package/src/assets/suneditor-content.css +646 -0
  11. package/src/assets/suneditor.css +3378 -0
  12. package/src/core/base/eventHandlers/handler_toolbar.js +114 -0
  13. package/src/core/base/eventHandlers/handler_ww_clipboard.js +31 -0
  14. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +69 -0
  15. package/src/core/base/eventHandlers/handler_ww_key_input.js +975 -0
  16. package/src/core/base/eventHandlers/handler_ww_mouse.js +118 -0
  17. package/src/core/base/eventManager.js +1115 -0
  18. package/src/core/base/events.js +320 -0
  19. package/src/core/base/history.js +301 -0
  20. package/src/core/class/char.js +146 -0
  21. package/src/core/class/component.js +627 -0
  22. package/src/core/class/format.js +3255 -0
  23. package/src/core/class/html.js +1621 -0
  24. package/src/core/class/menu.js +260 -0
  25. package/src/core/class/nodeTransform.js +379 -0
  26. package/src/core/class/notice.js +42 -0
  27. package/src/core/class/offset.js +578 -0
  28. package/src/core/class/selection.js +508 -0
  29. package/src/core/class/shortcuts.js +38 -0
  30. package/src/core/class/toolbar.js +440 -0
  31. package/src/core/class/viewer.js +646 -0
  32. package/src/core/editor.js +1593 -0
  33. package/src/core/section/actives.js +107 -0
  34. package/src/core/section/constructor.js +1237 -0
  35. package/src/core/section/context.js +97 -0
  36. package/src/editorInjector/_classes.js +22 -0
  37. package/src/editorInjector/_core.js +28 -0
  38. package/src/editorInjector/index.js +13 -0
  39. package/src/helper/converter.js +313 -0
  40. package/src/helper/domUtils.js +1177 -0
  41. package/src/helper/env.js +250 -0
  42. package/src/helper/index.js +19 -0
  43. package/src/helper/numbers.js +68 -0
  44. package/src/helper/unicode.js +43 -0
  45. package/src/langs/ckb.js +161 -0
  46. package/src/langs/cs.js +161 -0
  47. package/src/langs/da.js +161 -0
  48. package/src/langs/de.js +162 -0
  49. package/src/langs/en.js +199 -0
  50. package/src/langs/es.js +162 -0
  51. package/src/langs/fa.js +159 -0
  52. package/src/langs/fr.js +161 -0
  53. package/src/langs/he.js +162 -0
  54. package/src/{lang → langs}/index.js +0 -2
  55. package/src/langs/it.js +162 -0
  56. package/src/langs/ja.js +162 -0
  57. package/src/langs/ko.js +162 -0
  58. package/src/langs/lv.js +162 -0
  59. package/src/langs/nl.js +162 -0
  60. package/src/langs/pl.js +162 -0
  61. package/src/langs/pt_br.js +162 -0
  62. package/src/langs/ro.js +162 -0
  63. package/src/langs/ru.js +162 -0
  64. package/src/langs/se.js +162 -0
  65. package/src/langs/tr.js +159 -0
  66. package/src/langs/ua.js +162 -0
  67. package/src/langs/ur.js +162 -0
  68. package/src/langs/zh_cn.js +162 -0
  69. package/src/modules/ApiManager.js +168 -0
  70. package/src/modules/ColorPicker.js +302 -0
  71. package/src/modules/Controller.js +315 -0
  72. package/src/modules/Figure.js +1160 -0
  73. package/src/modules/FileBrowser.js +271 -0
  74. package/src/modules/FileManager.js +290 -0
  75. package/src/modules/HueSlider.js +513 -0
  76. package/src/modules/Modal.js +177 -0
  77. package/src/modules/ModalAnchorEditor.js +494 -0
  78. package/src/modules/SelectMenu.js +447 -0
  79. package/src/modules/_DragHandle.js +16 -0
  80. package/src/modules/index.js +14 -0
  81. package/src/plugins/command/blockquote.js +47 -47
  82. package/src/plugins/command/exportPdf.js +168 -0
  83. package/src/plugins/command/fileUpload.js +389 -0
  84. package/src/plugins/command/list_bulleted.js +112 -0
  85. package/src/plugins/command/list_numbered.js +115 -0
  86. package/src/plugins/dropdown/align.js +143 -0
  87. package/src/plugins/dropdown/backgroundColor.js +73 -0
  88. package/src/plugins/dropdown/font.js +113 -0
  89. package/src/plugins/dropdown/fontColor.js +73 -0
  90. package/src/plugins/dropdown/formatBlock.js +141 -0
  91. package/src/plugins/dropdown/hr.js +111 -0
  92. package/src/plugins/dropdown/layout.js +72 -0
  93. package/src/plugins/dropdown/lineHeight.js +114 -0
  94. package/src/plugins/dropdown/list.js +107 -0
  95. package/src/plugins/dropdown/paragraphStyle.js +117 -0
  96. package/src/plugins/dropdown/table.js +2810 -0
  97. package/src/plugins/dropdown/template.js +71 -0
  98. package/src/plugins/dropdown/textStyle.js +137 -0
  99. package/src/plugins/field/mention.js +172 -0
  100. package/src/plugins/fileBrowser/imageGallery.js +76 -59
  101. package/src/plugins/index.js +86 -24
  102. package/src/plugins/input/fontSize.js +357 -0
  103. package/src/plugins/modal/audio.js +510 -0
  104. package/src/plugins/modal/image.js +1062 -0
  105. package/src/plugins/modal/link.js +211 -0
  106. package/src/plugins/modal/math.js +347 -0
  107. package/src/plugins/modal/video.js +870 -0
  108. package/src/suneditor.js +62 -67
  109. package/src/themes/test.css +61 -0
  110. package/typings/CommandPlugin.d.ts +8 -0
  111. package/typings/DialogPlugin.d.ts +20 -0
  112. package/typings/FileBrowserPlugin.d.ts +30 -0
  113. package/typings/Lang.d.ts +124 -0
  114. package/typings/Module.d.ts +15 -0
  115. package/typings/Plugin.d.ts +42 -0
  116. package/typings/SubmenuPlugin.d.ts +8 -0
  117. package/typings/_classes.d.ts +17 -0
  118. package/typings/_colorPicker.d.ts +60 -0
  119. package/typings/_core.d.ts +55 -0
  120. package/typings/align.d.ts +5 -0
  121. package/{src/plugins/dialog → typings}/audio.d.ts +1 -1
  122. package/typings/backgroundColor.d.ts +5 -0
  123. package/{src/plugins/command → typings}/blockquote.d.ts +1 -1
  124. package/typings/char.d.ts +39 -0
  125. package/typings/component.d.ts +38 -0
  126. package/typings/context.d.ts +39 -0
  127. package/typings/converter.d.ts +33 -0
  128. package/typings/dialog.d.ts +28 -0
  129. package/typings/domUtils.d.ts +361 -0
  130. package/typings/editor.d.ts +7 -0
  131. package/typings/editor.ts +542 -0
  132. package/typings/env.d.ts +70 -0
  133. package/typings/eventManager.d.ts +37 -0
  134. package/typings/events.d.ts +262 -0
  135. package/typings/fileBrowser.d.ts +42 -0
  136. package/typings/fileManager.d.ts +67 -0
  137. package/typings/font.d.ts +5 -0
  138. package/typings/fontColor.d.ts +5 -0
  139. package/typings/fontSize.d.ts +5 -0
  140. package/typings/format.d.ts +191 -0
  141. package/typings/formatBlock.d.ts +5 -0
  142. package/typings/history.d.ts +48 -0
  143. package/typings/horizontalRule.d.ts +5 -0
  144. package/{src/plugins/dialog → typings}/image.d.ts +1 -1
  145. package/{src/plugins/fileBrowser → typings}/imageGallery.d.ts +1 -1
  146. package/typings/index.d.ts +21 -0
  147. package/{src/plugins/modules/index.d.ts → typings/index.modules.d.ts} +3 -3
  148. package/typings/index.plugins.d.ts +58 -0
  149. package/typings/lineHeight.d.ts +5 -0
  150. package/{src/plugins/dialog → typings}/link.d.ts +1 -1
  151. package/typings/list.d.ts +5 -0
  152. package/{src/plugins/dialog → typings}/math.d.ts +1 -1
  153. package/typings/mediaContainer.d.ts +25 -0
  154. package/typings/node.d.ts +57 -0
  155. package/typings/notice.d.ts +16 -0
  156. package/typings/numbers.d.ts +29 -0
  157. package/typings/offset.d.ts +24 -0
  158. package/typings/options.d.ts +589 -0
  159. package/typings/paragraphStyle.d.ts +5 -0
  160. package/typings/resizing.d.ts +141 -0
  161. package/typings/selection.d.ts +94 -0
  162. package/typings/shortcuts.d.ts +13 -0
  163. package/typings/suneditor.d.ts +9 -0
  164. package/typings/table.d.ts +5 -0
  165. package/typings/template.d.ts +5 -0
  166. package/typings/textStyle.d.ts +5 -0
  167. package/typings/toolbar.d.ts +32 -0
  168. package/typings/unicode.d.ts +25 -0
  169. package/{src/plugins/dialog → typings}/video.d.ts +1 -1
  170. package/dist/css/suneditor.min.css +0 -1
  171. package/src/assets/css/suneditor-contents.css +0 -562
  172. package/src/assets/css/suneditor.css +0 -566
  173. package/src/assets/defaultIcons.js +0 -103
  174. package/src/lang/Lang.d.ts +0 -144
  175. package/src/lang/ckb.d.ts +0 -5
  176. package/src/lang/ckb.js +0 -188
  177. package/src/lang/cs.d.ts +0 -5
  178. package/src/lang/cs.js +0 -188
  179. package/src/lang/da.d.ts +0 -5
  180. package/src/lang/da.js +0 -191
  181. package/src/lang/de.d.ts +0 -5
  182. package/src/lang/de.js +0 -188
  183. package/src/lang/en.d.ts +0 -5
  184. package/src/lang/en.js +0 -188
  185. package/src/lang/es.d.ts +0 -5
  186. package/src/lang/es.js +0 -188
  187. package/src/lang/fa.d.ts +0 -5
  188. package/src/lang/fa.js +0 -188
  189. package/src/lang/fr.d.ts +0 -5
  190. package/src/lang/fr.js +0 -188
  191. package/src/lang/he.d.ts +0 -5
  192. package/src/lang/he.js +0 -188
  193. package/src/lang/index.d.ts +0 -23
  194. package/src/lang/it.d.ts +0 -5
  195. package/src/lang/it.js +0 -188
  196. package/src/lang/ja.d.ts +0 -5
  197. package/src/lang/ja.js +0 -188
  198. package/src/lang/ko.d.ts +0 -5
  199. package/src/lang/ko.js +0 -188
  200. package/src/lang/lv.d.ts +0 -5
  201. package/src/lang/lv.js +0 -188
  202. package/src/lang/nl.d.ts +0 -5
  203. package/src/lang/nl.js +0 -188
  204. package/src/lang/pl.d.ts +0 -5
  205. package/src/lang/pl.js +0 -188
  206. package/src/lang/pt_br.d.ts +0 -5
  207. package/src/lang/pt_br.js +0 -189
  208. package/src/lang/ro.d.ts +0 -5
  209. package/src/lang/ro.js +0 -188
  210. package/src/lang/ru.d.ts +0 -5
  211. package/src/lang/ru.js +0 -188
  212. package/src/lang/se.d.ts +0 -5
  213. package/src/lang/se.js +0 -191
  214. package/src/lang/tr.d.ts +0 -5
  215. package/src/lang/tr.js +0 -191
  216. package/src/lang/ua.d.ts +0 -5
  217. package/src/lang/ua.js +0 -188
  218. package/src/lang/ur.d.ts +0 -5
  219. package/src/lang/ur.js +0 -188
  220. package/src/lang/zh_cn.d.ts +0 -5
  221. package/src/lang/zh_cn.js +0 -187
  222. package/src/lib/constructor.js +0 -954
  223. package/src/lib/context.d.ts +0 -42
  224. package/src/lib/context.js +0 -71
  225. package/src/lib/core.d.ts +0 -1135
  226. package/src/lib/core.js +0 -9395
  227. package/src/lib/history.d.ts +0 -48
  228. package/src/lib/history.js +0 -219
  229. package/src/lib/util.d.ts +0 -678
  230. package/src/lib/util.js +0 -2131
  231. package/src/options.d.ts +0 -608
  232. package/src/plugins/CommandPlugin.d.ts +0 -8
  233. package/src/plugins/DialogPlugin.d.ts +0 -20
  234. package/src/plugins/FileBrowserPlugin.d.ts +0 -30
  235. package/src/plugins/Module.d.ts +0 -15
  236. package/src/plugins/Plugin.d.ts +0 -42
  237. package/src/plugins/SubmenuPlugin.d.ts +0 -8
  238. package/src/plugins/dialog/audio.js +0 -559
  239. package/src/plugins/dialog/image.js +0 -1126
  240. package/src/plugins/dialog/link.js +0 -223
  241. package/src/plugins/dialog/math.js +0 -295
  242. package/src/plugins/dialog/mention.js +0 -242
  243. package/src/plugins/dialog/video.js +0 -979
  244. package/src/plugins/index.d.ts +0 -79
  245. package/src/plugins/modules/_anchor.js +0 -461
  246. package/src/plugins/modules/_colorPicker.d.ts +0 -60
  247. package/src/plugins/modules/_colorPicker.js +0 -201
  248. package/src/plugins/modules/_notice.d.ts +0 -21
  249. package/src/plugins/modules/_notice.js +0 -72
  250. package/src/plugins/modules/_selectMenu.js +0 -119
  251. package/src/plugins/modules/component.d.ts +0 -25
  252. package/src/plugins/modules/component.js +0 -81
  253. package/src/plugins/modules/dialog.d.ts +0 -28
  254. package/src/plugins/modules/dialog.js +0 -175
  255. package/src/plugins/modules/fileBrowser.d.ts +0 -42
  256. package/src/plugins/modules/fileBrowser.js +0 -374
  257. package/src/plugins/modules/fileManager.d.ts +0 -67
  258. package/src/plugins/modules/fileManager.js +0 -326
  259. package/src/plugins/modules/index.js +0 -9
  260. package/src/plugins/modules/resizing.d.ts +0 -154
  261. package/src/plugins/modules/resizing.js +0 -903
  262. package/src/plugins/submenu/align.d.ts +0 -5
  263. package/src/plugins/submenu/align.js +0 -160
  264. package/src/plugins/submenu/font.d.ts +0 -5
  265. package/src/plugins/submenu/font.js +0 -123
  266. package/src/plugins/submenu/fontColor.d.ts +0 -5
  267. package/src/plugins/submenu/fontColor.js +0 -101
  268. package/src/plugins/submenu/fontSize.d.ts +0 -5
  269. package/src/plugins/submenu/fontSize.js +0 -112
  270. package/src/plugins/submenu/formatBlock.d.ts +0 -5
  271. package/src/plugins/submenu/formatBlock.js +0 -273
  272. package/src/plugins/submenu/hiliteColor.d.ts +0 -5
  273. package/src/plugins/submenu/hiliteColor.js +0 -102
  274. package/src/plugins/submenu/horizontalRule.d.ts +0 -5
  275. package/src/plugins/submenu/horizontalRule.js +0 -98
  276. package/src/plugins/submenu/lineHeight.d.ts +0 -5
  277. package/src/plugins/submenu/lineHeight.js +0 -104
  278. package/src/plugins/submenu/list.d.ts +0 -5
  279. package/src/plugins/submenu/list.js +0 -456
  280. package/src/plugins/submenu/paragraphStyle.d.ts +0 -5
  281. package/src/plugins/submenu/paragraphStyle.js +0 -135
  282. package/src/plugins/submenu/table.d.ts +0 -5
  283. package/src/plugins/submenu/table.js +0 -1431
  284. package/src/plugins/submenu/template.d.ts +0 -5
  285. package/src/plugins/submenu/template.js +0 -72
  286. package/src/plugins/submenu/textStyle.d.ts +0 -5
  287. package/src/plugins/submenu/textStyle.js +0 -167
  288. package/src/suneditor.d.ts +0 -9
  289. package/src/suneditor_build.js +0 -18
  290. /package/{src/plugins/dialog → typings}/mention.d.ts +0 -0
@@ -0,0 +1,513 @@
1
+ import { domUtils, env } from '../helper';
2
+ import Controller from './Controller';
3
+
4
+ const { isMobile } = env;
5
+
6
+ const SIZE = 240;
7
+ const BAR_H = 28;
8
+ const MIDDLE = SIZE / 2;
9
+ const LIGHTNESS_CONT_VALUE = 50;
10
+ const CLOSE_TO_CENTER_THRESHOLD = 3;
11
+ const FIXED_DEC = 10;
12
+ const SATURATION = 1;
13
+ const GRADIENT_RADIUS = 14;
14
+ const DEFAULT_COLOR_VALUE = { hex: '#FFFFFF', r: 255, g: 255, b: 255, h: 0, s: 1, l: 1 };
15
+
16
+ let LIGHTNESS = 0;
17
+ let isWheelragging = false;
18
+ let isBarDragging = false;
19
+ let wheelX = SIZE / 2;
20
+ let wheelY = SIZE / 2;
21
+ let finalColor = DEFAULT_COLOR_VALUE;
22
+ let ctx;
23
+
24
+ function CreateSliderCtx() {
25
+ const offscreenCanvas = document.createElement('canvas');
26
+ offscreenCanvas.width = SIZE;
27
+ offscreenCanvas.height = SIZE;
28
+
29
+ const html = /*html*/ `
30
+ <div class="se-hue-slider-container" style="width: ${SIZE}px; height: ${SIZE}px;">
31
+ <canvas class="se-hue-wheel" width="${SIZE}" height="${SIZE}"></canvas>
32
+ <div class="se-hue-wheel-pointer"></div>
33
+ </div>
34
+ <div class="se-hue-gradient-container">
35
+ <canvas class="se-hue-gradient" width="${SIZE}" height="${BAR_H}"></canvas>
36
+ <div class="se-hue-gradient-pointer"></div>
37
+ </div>
38
+ <div class="se-hue-final-hex" style="width:${SIZE}px; height: ${BAR_H}px;">
39
+ <div style="flex: 3; line-height: 1.5;">${DEFAULT_COLOR_VALUE.hex}</div>
40
+ <div style="flex: 1; height: 100%; border: 1px solid #fff; outline: 1px solid #000;"></div>
41
+ </div>
42
+ `;
43
+
44
+ const slider = domUtils.createElement('DIV', { class: 'se-hue-slider' }, html);
45
+ const wheelCanvas = slider.querySelector('.se-hue-wheel');
46
+ const gradientBarCanvas = slider.querySelector('.se-hue-gradient');
47
+ const currentColors = slider.querySelector('.se-hue-final-hex').children;
48
+
49
+ return {
50
+ slider,
51
+ offscreenCanvas,
52
+ offscreenCtx: offscreenCanvas.getContext('2d'),
53
+ wheel: wheelCanvas,
54
+ wheelCtx: wheelCanvas.getContext('2d'),
55
+ wheelPointer: slider.querySelector('.se-hue-wheel-pointer'),
56
+ gradientBar: gradientBarCanvas,
57
+ gradientPointer: slider.querySelector('.se-hue-gradient-pointer'),
58
+ fanalColorHex: currentColors[0],
59
+ fanalColorBackground: currentColors[1]
60
+ };
61
+ }
62
+
63
+ /**
64
+ * @description Create a Hue slider. (only create one at a time)
65
+ * When you call the .attach() method, the hue slider is appended to the form element.
66
+ * It must be called every time it is used.
67
+ * @param {{form: Element}} params {form: Element}
68
+ */
69
+ const HueSlider = function (inst, params, className) {
70
+ if (!params) params = {};
71
+
72
+ this.editor = inst.editor;
73
+ this.eventManager = inst.eventManager;
74
+ this.inst = inst;
75
+
76
+ // members
77
+ this.form = params.form;
78
+ this.ctx = {
79
+ wheelX: wheelX,
80
+ wheelY: wheelY,
81
+ lightness: LIGHTNESS,
82
+ wheelPointerX: '50%',
83
+ wheelPointerY: '50%',
84
+ gradientPointerX: 'calc(100% - 14px)',
85
+ color: DEFAULT_COLOR_VALUE
86
+ };
87
+ this.isOpen = false;
88
+ this.controlle = null;
89
+ this.__globalMouseDown = null;
90
+ this.__globalMouseMove = null;
91
+ this.__globalMouseUp = null;
92
+
93
+ // init default controller
94
+ if (!params.isNewForm) {
95
+ const hueController = CreateHTML_basicControllerForm(inst.editor, className);
96
+ this.form = hueController.querySelector('.se-hue');
97
+ this.controller = new Controller(this, hueController, { position: 'top', isWWTarget: false, ...params.controllerOptions });
98
+
99
+ // buttons
100
+ this.eventManager.addEvent(hueController.querySelector('.se-btn-success'), 'click', () => {
101
+ inst.hueSliderAction(this.get());
102
+ this.close();
103
+ });
104
+ this.eventManager.addEvent(hueController.querySelector('.se-btn-danger'), 'click', () => {
105
+ this.close();
106
+ });
107
+ }
108
+ };
109
+
110
+ HueSlider.prototype = {
111
+ get() {
112
+ return finalColor;
113
+ },
114
+
115
+ open(target) {
116
+ this.attach();
117
+ this.controller.open(target, null, { isWWTarget: false, initMethod: null, addOffset: null });
118
+ },
119
+
120
+ off() {
121
+ this.ctx = {
122
+ gradientPointerX: gradientPointer.style.left,
123
+ wheelPointerX: wheelPointer.style.left,
124
+ wheelPointerY: wheelPointer.style.top,
125
+ wheelX: wheelX,
126
+ wheelY: wheelY,
127
+ lightness: LIGHTNESS,
128
+ color: ctx?.color || getWheelColor(wheelCtx)
129
+ };
130
+
131
+ this.controller.close();
132
+ this.init();
133
+ },
134
+
135
+ close() {
136
+ this.off();
137
+ this.inst.hueSliderCancelAction();
138
+ },
139
+
140
+ attach(form) {
141
+ // drow
142
+ this.init();
143
+ (form || this.form).appendChild(slider);
144
+ ctx = this.ctx;
145
+ if (ctx) {
146
+ wheelX = ctx.wheelX;
147
+ wheelY = ctx.wheelY;
148
+ LIGHTNESS = ctx.lightness;
149
+ wheelPointer.style.left = ctx.wheelPointerX;
150
+ wheelPointer.style.top = ctx.wheelPointerY;
151
+ gradientPointer.style.left = ctx.gradientPointerX;
152
+ setHex(ctx.color.hex);
153
+
154
+ drawColorWheel();
155
+ createGradientBar(getDefaultColor());
156
+ }
157
+
158
+ // event
159
+ const downEvent = { name: 'mousedown', func: OnMousedown };
160
+ const moveEvent = { name: 'mousemove', func: OnMousemove, option: true };
161
+ const upEvent = {
162
+ name: 'mouseup',
163
+ func: () => {
164
+ isWheelragging = false;
165
+ isBarDragging = false;
166
+ }
167
+ };
168
+
169
+ if (isMobile) {
170
+ // mobile name
171
+ downEvent.name = 'touchstart';
172
+ moveEvent.name = 'touchmove';
173
+ upEvent.name = 'touchend';
174
+ // mobile func
175
+ downEvent.func = OnTouchstart;
176
+ moveEvent.func = OnTouchmove;
177
+ }
178
+
179
+ this.__globalMouseDown = this.eventManager.addGlobalEvent(downEvent.name, downEvent.func, { passive: false, useCapture: true });
180
+ this.__globalMouseMove = this.eventManager.addGlobalEvent(moveEvent.name, moveEvent.func, true);
181
+ this.__globalMouseUp = this.eventManager.addGlobalEvent(upEvent.name, upEvent.func, true);
182
+ this.isOpen = true;
183
+ },
184
+
185
+ init() {
186
+ this.isOpen = false;
187
+ isWheelragging = false;
188
+ isBarDragging = false;
189
+ if (this.__globalMouseDown) this.__globalMouseDown = this.eventManager.removeGlobalEvent(this.__globalMouseDown);
190
+ if (this.__globalMouseMove) this.__globalMouseMove = this.eventManager.removeGlobalEvent(this.__globalMouseMove);
191
+ if (this.__globalMouseUp) this.__globalMouseUp = this.eventManager.removeGlobalEvent(this.__globalMouseUp);
192
+ },
193
+
194
+ constructor: HueSlider
195
+ };
196
+
197
+ // init
198
+ const { slider, offscreenCanvas, offscreenCtx, wheel, wheelCtx, wheelPointer, gradientBar, gradientPointer, fanalColorHex, fanalColorBackground } = CreateSliderCtx();
199
+
200
+ // mobile
201
+ function OnTouchstart(event) {
202
+ const { target, touches } = event;
203
+ const clientX = touches[0].clientX;
204
+ const clientY = touches[0].clientY;
205
+
206
+ if (target === wheel) {
207
+ event.preventDefault();
208
+ isBarDragging = false;
209
+ isWheelragging = true;
210
+ updatePointer_wheel(clientX, clientY);
211
+ } else if (target === gradientBar) {
212
+ event.preventDefault();
213
+ isBarDragging = true;
214
+ isWheelragging = false;
215
+ updatePointer_bar(clientX);
216
+ }
217
+ }
218
+
219
+ function OnTouchmove(event) {
220
+ event.preventDefault();
221
+
222
+ const { touches } = event;
223
+ const clientX = touches[0].clientX;
224
+ const clientY = touches[0].clientY;
225
+
226
+ if (isWheelragging) {
227
+ updatePointer_wheel(clientX, clientY);
228
+ } else if (isBarDragging) {
229
+ updatePointer_bar(clientX);
230
+ }
231
+ }
232
+
233
+ // pc
234
+ function OnMousedown({ target, clientX, clientY }) {
235
+ if (target === wheel) {
236
+ isBarDragging = false;
237
+ isWheelragging = true;
238
+ updatePointer_wheel(clientX, clientY);
239
+ } else if (target === gradientBar) {
240
+ isBarDragging = true;
241
+ isWheelragging = false;
242
+ updatePointer_bar(clientX);
243
+ }
244
+ }
245
+
246
+ function OnMousemove({ clientX, clientY }) {
247
+ if (isWheelragging) {
248
+ updatePointer_wheel(clientX, clientY);
249
+ } else if (isBarDragging) {
250
+ updatePointer_bar(clientX);
251
+ }
252
+ }
253
+
254
+ function updatePointer_wheel(x, y) {
255
+ const rect = wheel.getBoundingClientRect();
256
+ x = x - rect.left - MIDDLE;
257
+ y = y - rect.top - MIDDLE;
258
+
259
+ const angle = (Math.atan2(y, x) * 180) / Math.PI;
260
+ const distance = Math.min(Math.sqrt(x * x + y * y), MIDDLE);
261
+
262
+ const posX = MIDDLE + distance * Math.cos((angle * Math.PI) / 180);
263
+ const posY = MIDDLE + distance * Math.sin((angle * Math.PI) / 180);
264
+
265
+ wheelPointer.style.left = `${posX}px`;
266
+ wheelPointer.style.top = `${posY}px`;
267
+
268
+ wheelPickedColor(posX, posY);
269
+ setFinalColor();
270
+ }
271
+
272
+ function updatePointer_bar(x) {
273
+ const rect = gradientBar.getBoundingClientRect();
274
+ let posX = x - rect.left;
275
+ posX = Math.max(GRADIENT_RADIUS, Math.min(posX, rect.width - GRADIENT_RADIUS));
276
+
277
+ gradientPointer.style.left = `${posX}px`;
278
+
279
+ selectGradientColor(x);
280
+ setFinalColor();
281
+ }
282
+
283
+ function wheelPickedColor(posX, posY) {
284
+ wheelX = posX;
285
+ wheelY = posY;
286
+ createGradientBar(getDefaultColor());
287
+ }
288
+
289
+ function createGradientBar(color) {
290
+ const gradientBarCtx = gradientBar.getContext('2d');
291
+ const gradient = gradientBarCtx.createLinearGradient(0, 0, gradientBar.width, 0);
292
+
293
+ gradient.addColorStop(0, 'black'); // 왼쪽은 검은색
294
+ gradient.addColorStop(1, color.hex); // 오른쪽은 선택한 색상
295
+
296
+ gradientBarCtx.fillStyle = gradient;
297
+ gradientBarCtx.fillRect(0, 0, gradientBar.width, gradientBar.height);
298
+ }
299
+
300
+ function getDefaultColor() {
301
+ return getWheelColor(offscreenCtx);
302
+ }
303
+
304
+ function setFinalColor() {
305
+ ctx.color = finalColor = getWheelColor(wheelCtx);
306
+ setHex(finalColor.hex);
307
+ }
308
+
309
+ function setHex(hex) {
310
+ fanalColorBackground.style.backgroundColor = fanalColorHex.textContent = hex;
311
+ }
312
+
313
+ function getWheelColor(wCtx) {
314
+ const pixel = wCtx.getImageData(wheelX, wheelY, 1, 1).data;
315
+ // eslint-disable-next-line prefer-const
316
+ let [h, s, l] = rgbToHsl(pixel);
317
+
318
+ // Calculate distance from the center of the wheel
319
+ const dx = wheelX - MIDDLE;
320
+ const dy = wheelY - MIDDLE;
321
+ const distance = Math.sqrt(dx * dx + dy * dy);
322
+
323
+ if (distance < CLOSE_TO_CENTER_THRESHOLD) {
324
+ l = 1 - LIGHTNESS;
325
+ }
326
+
327
+ if (l > 1) l = 1;
328
+ if (l < 0) l = 0;
329
+
330
+ // Adjust lightness based on LIGHTNESS value
331
+ const { r, g, b } = hslToRgb([h, s, l]);
332
+
333
+ // Convert RGB to HEX
334
+ const hex = `#${rgbToHex({ r, g, b })}`;
335
+
336
+ return {
337
+ hex,
338
+ r,
339
+ g,
340
+ b,
341
+ h,
342
+ s,
343
+ l: roundNumber(l)
344
+ };
345
+ }
346
+
347
+ function selectGradientColor(x) {
348
+ const boundingRect = gradientBar.getBoundingClientRect();
349
+ let posX = x - boundingRect.left;
350
+
351
+ if (posX < 0) posX = 0;
352
+ if (posX > boundingRect.width) posX = boundingRect.width;
353
+
354
+ const tolerance = GRADIENT_RADIUS;
355
+
356
+ // If a click occurs near the end, the value is corrected all the way to the end.
357
+ if (posX >= gradientBar.width - tolerance) {
358
+ posX = gradientBar.width;
359
+ } else if (posX <= tolerance) {
360
+ posX = 0;
361
+ }
362
+
363
+ const normalizedLightness = 1 - posX / boundingRect.width; // 1 ~ 0
364
+ LIGHTNESS = normalizedLightness; // 0 ~ 1
365
+
366
+ drawColorWheel();
367
+ }
368
+
369
+ function drawColorWheel() {
370
+ // init main canvas
371
+ wheelCtx.clearRect(0, 0, SIZE, SIZE);
372
+
373
+ // copy offscreen to main canvas
374
+ wheelCtx.drawImage(offscreenCanvas, 0, 0);
375
+
376
+ // drow dark wheel
377
+ drawWheelGradient();
378
+ }
379
+
380
+ function drawWheelGradient() {
381
+ wheelCtx.globalAlpha = LIGHTNESS; // 0: white, 1: black
382
+ wheelCtx.fillStyle = 'black';
383
+ wheelCtx.beginPath();
384
+ wheelCtx.arc(MIDDLE, MIDDLE, MIDDLE, 0, 2 * Math.PI);
385
+ wheelCtx.fill();
386
+ wheelCtx.globalAlpha = 1.0;
387
+ }
388
+
389
+ function drawColorWheelToContext(context) {
390
+ if (!context) throw new Error('Context not found.');
391
+
392
+ const fixedSaturation = SATURATION * 100;
393
+
394
+ for (let h = 0; h <= 360; h += 0.5) {
395
+ for (let distance = 0; distance <= MIDDLE; distance += 1) {
396
+ context.beginPath();
397
+
398
+ const dynamicLightness = LIGHTNESS_CONT_VALUE + ((MIDDLE - distance) / MIDDLE) * 50;
399
+
400
+ context.fillStyle = `hsl(${h}, ${fixedSaturation}%, ${dynamicLightness}%)`;
401
+
402
+ const posX = MIDDLE + Math.cos(degreeToRadian(h)) * distance;
403
+ const posY = MIDDLE - Math.sin(degreeToRadian(h)) * distance;
404
+
405
+ context.arc(posX, posY, 1.5, 0, 2 * Math.PI);
406
+ context.fill();
407
+ }
408
+ }
409
+ }
410
+
411
+ function degreeToRadian(deg) {
412
+ return (deg * Math.PI) / 180;
413
+ }
414
+
415
+ function rgbToHsl([r, g, b]) {
416
+ r /= 255;
417
+ g /= 255;
418
+ b /= 255;
419
+
420
+ const max = Math.max(r, g, b),
421
+ min = Math.min(r, g, b);
422
+ let h, s;
423
+ const l = (max + min) / 2;
424
+
425
+ if (max === min) {
426
+ h = s = 0; // achromatic
427
+ } else {
428
+ const d = max - min;
429
+ s = l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
430
+
431
+ switch (max) {
432
+ case r:
433
+ h = (g - b) / d + (g < b ? 6 : 0);
434
+ break;
435
+ case g:
436
+ h = (b - r) / d + 2;
437
+ break;
438
+ case b:
439
+ h = (r - g) / d + 4;
440
+ break;
441
+ }
442
+
443
+ h /= 6;
444
+ }
445
+
446
+ return [roundNumber(h), roundNumber(s), roundNumber(l)];
447
+ }
448
+
449
+ function hslToRgb([h, s, l]) {
450
+ let r, g, b;
451
+
452
+ if (s === 0) {
453
+ r = g = b = l; // achromatic
454
+ } else {
455
+ const hue2rgb = function hue2rgb(p, q, t) {
456
+ if (t < 0) t += 1;
457
+ if (t > 1) t -= 1;
458
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
459
+ if (t < 1 / 2) return q;
460
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
461
+ return p;
462
+ };
463
+
464
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
465
+ const p = 2 * l - q;
466
+ r = hue2rgb(p, q, h + 1 / 3);
467
+ g = hue2rgb(p, q, h);
468
+ b = hue2rgb(p, q, h - 1 / 3);
469
+ }
470
+
471
+ return {
472
+ r: Math.round(r * 255),
473
+ g: Math.round(g * 255),
474
+ b: Math.round(b * 255)
475
+ };
476
+ }
477
+
478
+ function rgbToHex({ r, g, b }) {
479
+ let hexR = Math.floor(r).toString(16);
480
+ if (r < 16) hexR = `0${hexR}`;
481
+ let hexG = Math.floor(g).toString(16);
482
+ if (g < 16) hexG = `0${hexG}`;
483
+ let hexB = Math.floor(b).toString(16);
484
+ if (b < 16) hexB = `0${hexB}`;
485
+ return `${hexR}${hexG}${hexB}`.toUpperCase();
486
+ }
487
+
488
+ function roundNumber(num) {
489
+ const factor = Math.pow(10, FIXED_DEC);
490
+ return Math.round(num * factor) / factor;
491
+ }
492
+
493
+ // create
494
+ drawColorWheelToContext(offscreenCtx);
495
+ drawColorWheel();
496
+
497
+ function CreateHTML_basicControllerForm({ lang, icons }, className) {
498
+ const hueController = domUtils.createElement(
499
+ 'DIV',
500
+ { class: `se-controller ${className}` },
501
+ /*html*/ `
502
+ <div class="se-hue"></div>
503
+ <div class="se-form-group se-form-w0 se-form-flex-btn">
504
+ <button type="button" class="se-btn se-btn-success" title="${lang.submitButton}" aria-label="${lang.submitButton}">${icons.checked}</button>
505
+ <button type="button" class="se-btn se-btn-danger" title="${lang.close}" aria-label="${lang.close}">${icons.cancel}</button>
506
+ </div>
507
+ `
508
+ );
509
+
510
+ return hueController;
511
+ }
512
+
513
+ export default HueSlider;
@@ -0,0 +1,177 @@
1
+ import CoreInjector from '../editorInjector/_core';
2
+ import { CreateTooltipInner } from '../core/section/constructor';
3
+
4
+ const Modal = function (inst, element) {
5
+ CoreInjector.call(this, inst.editor);
6
+
7
+ // members
8
+ this.inst = inst;
9
+ this.kind = inst.constructor.key || inst.constructor.name;
10
+ this.form = element;
11
+ this.focusElement = element.querySelector('[data-focus]');
12
+ this.isUpdate = false;
13
+ this._modalArea = this.carrierWrapper.querySelector('.se-modal');
14
+ this._modalBack = this.carrierWrapper.querySelector('.se-modal-back');
15
+ this._modalInner = this.carrierWrapper.querySelector('.se-modal-inner');
16
+ this._closeListener = [CloseListener.bind(this), OnClick_dialog.bind(this)];
17
+ this._bindClose = null;
18
+ this._onClickEvent = null;
19
+ this._closeSignal = false;
20
+
21
+ // add element
22
+ this._modalInner.appendChild(element);
23
+
24
+ // init
25
+ this.eventManager.addEvent(element.querySelector('form'), 'submit', Action.bind(this));
26
+ this._closeSignal = !this.eventManager.addEvent(element.querySelector('[data-command="close"]'), 'click', this.close.bind(this));
27
+ };
28
+
29
+ Modal.prototype = {
30
+ /**
31
+ * @description Open a modal plugin
32
+ */
33
+ open() {
34
+ this.editor._offCurrentModal();
35
+ this._fixCurrentController(true);
36
+
37
+ if (this._closeSignal) this._modalInner.addEventListener('click', this._closeListener[1]);
38
+ if (this._bindClose) this._bindClose = this.eventManager.removeGlobalEvent(this._bindClose);
39
+ this._bindClose = this.eventManager.addGlobalEvent('keydown', this._closeListener[0]);
40
+ this.isUpdate = this.kind === this.editor.currentControllerName;
41
+ this.editor.opendModal = this;
42
+
43
+ if (!this.isUpdate && typeof this.inst.init === 'function') this.inst.init();
44
+ if (typeof this.inst.on === 'function') this.inst.on(this.isUpdate);
45
+
46
+ this._modalArea.style.display = 'block';
47
+ this._modalBack.style.display = 'block';
48
+ this._modalInner.style.display = 'block';
49
+ this.form.style.display = 'block';
50
+
51
+ if (this.focusElement) this.focusElement.focus();
52
+ },
53
+
54
+ /**
55
+ * @description Close a modal plugin
56
+ * The plugin's "init" method is called.
57
+ */
58
+ close() {
59
+ this._fixCurrentController(false);
60
+ this.editor.opendModal = null;
61
+
62
+ if (this._closeSignal) this._modalInner.removeEventListener('click', this._closeListener[1]);
63
+ if (this._bindClose) this._bindClose = this.eventManager.removeGlobalEvent(this._bindClose);
64
+
65
+ // close
66
+ this.form.style.display = 'none';
67
+ this._modalBack.style.display = 'none';
68
+ this._modalArea.style.display = 'none';
69
+
70
+ if (typeof this.inst.init === 'function') this.inst.init();
71
+ this.editor.focus();
72
+ },
73
+
74
+ _fixCurrentController(fixed) {
75
+ const cont = this.editor.opendControllers;
76
+ for (let i = 0; i < cont.length; i++) {
77
+ cont[i].fixed = fixed;
78
+ cont[i].form.style.display = fixed ? 'none' : 'block';
79
+ }
80
+ },
81
+
82
+ constructor: Modal
83
+ };
84
+
85
+ /**
86
+ * The loading bar is executed before "modalAction" is executed.
87
+ * return type -
88
+ * true : the loading bar and modal window are closed.
89
+ * false : only the loading bar is closed.
90
+ * undefined : only the modal window is closed.
91
+ * -
92
+ * exception occurs : the modal window and loading bar are closed.
93
+ */
94
+ async function Action(e) {
95
+ e.preventDefault();
96
+ e.stopPropagation();
97
+
98
+ this.editor.showLoading();
99
+
100
+ try {
101
+ const result = await this.inst.modalAction();
102
+ if (result === false) {
103
+ this.editor.hideLoading();
104
+ } else if (result === undefined) {
105
+ this.close();
106
+ } else {
107
+ this.close();
108
+ this.editor.hideLoading();
109
+ }
110
+ } catch (error) {
111
+ this.close();
112
+ this.editor.hideLoading();
113
+ throw Error(`[SUNEDITOR.Modal[${this.kind}].warn] ${error.message}`);
114
+ }
115
+ }
116
+
117
+ function OnClick_dialog(e) {
118
+ if (/close/.test(e.target.getAttribute('data-command')) || e.target === this._modalInner) {
119
+ this.close();
120
+ }
121
+ }
122
+
123
+ function CloseListener(e) {
124
+ if (!/27/.test(e.keyCode)) return;
125
+ this.close();
126
+ }
127
+
128
+ // HTML Creator ======================================================================================================
129
+
130
+ // Create a file input tag
131
+ Modal.CreateFileInput = function ({ icons, lang }, { acceptedFormats, allowMultiple }) {
132
+ return /*html*/ `
133
+ <div class="se-modal-form-files">
134
+ <div class="se-flex-input-wrapper">
135
+ <div class="se-input-form-abs">
136
+ <div>
137
+ <div class="se-input-file-w">
138
+ <div class="se-input-file-icon-up">${icons.upload_tray}</div>
139
+ <div class="se-input-file-icon-files">${icons.file_plus}</div>
140
+ <span class="se-input-file-cnt"></span>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ <input class="se-input-form __se__file_input" data-focus type="file" accept="${acceptedFormats}"${allowMultiple ? ' multiple="multiple"' : ''}/>
145
+ </div>
146
+ <button type="button" class="se-btn se-modal-files-edge-button se-file-remove se-tooltip" aria-label="${lang.remove}">
147
+ ${icons.selection_remove}
148
+ ${CreateTooltipInner(lang.remove)}
149
+ </button>
150
+ </div>`;
151
+ };
152
+ Modal.OnChangeFile = function (wrapper, files) {
153
+ if (!wrapper || !files) return;
154
+
155
+ const fileCnt = wrapper.querySelector('.se-input-file-cnt');
156
+ const fileUp = wrapper.querySelector('.se-input-file-icon-up');
157
+ const fileSelected = wrapper.querySelector('.se-input-file-icon-files');
158
+
159
+ if (files.length > 1) {
160
+ fileUp.style.display = 'none';
161
+ fileSelected.style.display = 'inline-block';
162
+ fileCnt.style.display = '';
163
+ fileCnt.textContent = ` ..${files.length}`;
164
+ } else if (files.length > 0) {
165
+ fileUp.style.display = 'none';
166
+ fileSelected.style.display = 'none';
167
+ fileCnt.style.display = 'block';
168
+ fileCnt.textContent = files[0].name;
169
+ } else {
170
+ fileUp.style.display = 'inline-block';
171
+ fileSelected.style.display = 'none';
172
+ fileCnt.style.display = '';
173
+ fileCnt.textContent = '';
174
+ }
175
+ };
176
+
177
+ export default Modal;