suneditor 3.0.0-beta.2 → 3.0.0-beta.20

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 (177) hide show
  1. package/CONTRIBUTING.md +186 -184
  2. package/LICENSE +21 -21
  3. package/README.md +157 -180
  4. package/dist/suneditor.min.css +1 -1
  5. package/dist/suneditor.min.js +1 -1
  6. package/package.json +126 -123
  7. package/src/assets/design/color.css +131 -121
  8. package/src/assets/design/index.css +3 -3
  9. package/src/assets/design/size.css +37 -35
  10. package/src/assets/design/typography.css +37 -37
  11. package/src/assets/icons/defaultIcons.js +247 -232
  12. package/src/assets/suneditor-contents.css +779 -778
  13. package/src/assets/suneditor.css +43 -35
  14. package/src/core/base/eventHandlers/handler_toolbar.js +135 -135
  15. package/src/core/base/eventHandlers/handler_ww_clipboard.js +56 -56
  16. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +115 -113
  17. package/src/core/base/eventHandlers/handler_ww_key_input.js +1200 -1200
  18. package/src/core/base/eventHandlers/handler_ww_mouse.js +194 -194
  19. package/src/core/base/eventManager.js +1550 -1484
  20. package/src/core/base/history.js +355 -355
  21. package/src/core/class/char.js +163 -162
  22. package/src/core/class/component.js +856 -842
  23. package/src/core/class/format.js +3433 -3422
  24. package/src/core/class/html.js +1927 -1890
  25. package/src/core/class/menu.js +357 -346
  26. package/src/core/class/nodeTransform.js +424 -424
  27. package/src/core/class/offset.js +858 -891
  28. package/src/core/class/selection.js +710 -620
  29. package/src/core/class/shortcuts.js +98 -98
  30. package/src/core/class/toolbar.js +438 -430
  31. package/src/core/class/ui.js +424 -422
  32. package/src/core/class/viewer.js +750 -750
  33. package/src/core/editor.js +1810 -1708
  34. package/src/core/section/actives.js +268 -241
  35. package/src/core/section/constructor.js +1348 -1661
  36. package/src/core/section/context.js +102 -102
  37. package/src/core/section/documentType.js +582 -561
  38. package/src/core/section/options.js +367 -0
  39. package/src/core/util/instanceCheck.js +59 -0
  40. package/src/editorInjector/_classes.js +36 -36
  41. package/src/editorInjector/_core.js +92 -92
  42. package/src/editorInjector/index.js +75 -75
  43. package/src/events.js +634 -622
  44. package/src/helper/clipboard.js +59 -59
  45. package/src/helper/converter.js +586 -564
  46. package/src/helper/dom/domCheck.js +304 -304
  47. package/src/helper/dom/domQuery.js +677 -669
  48. package/src/helper/dom/domUtils.js +618 -557
  49. package/src/helper/dom/index.js +12 -12
  50. package/src/helper/env.js +249 -240
  51. package/src/helper/index.js +25 -25
  52. package/src/helper/keyCodeMap.js +183 -183
  53. package/src/helper/numbers.js +72 -72
  54. package/src/helper/unicode.js +47 -47
  55. package/src/langs/ckb.js +231 -231
  56. package/src/langs/cs.js +231 -231
  57. package/src/langs/da.js +231 -231
  58. package/src/langs/de.js +231 -231
  59. package/src/langs/en.js +230 -230
  60. package/src/langs/es.js +231 -231
  61. package/src/langs/fa.js +231 -231
  62. package/src/langs/fr.js +231 -231
  63. package/src/langs/he.js +231 -231
  64. package/src/langs/hu.js +230 -230
  65. package/src/langs/index.js +28 -28
  66. package/src/langs/it.js +231 -231
  67. package/src/langs/ja.js +230 -230
  68. package/src/langs/km.js +230 -230
  69. package/src/langs/ko.js +230 -230
  70. package/src/langs/lv.js +231 -231
  71. package/src/langs/nl.js +231 -231
  72. package/src/langs/pl.js +231 -231
  73. package/src/langs/pt_br.js +231 -231
  74. package/src/langs/ro.js +231 -231
  75. package/src/langs/ru.js +231 -231
  76. package/src/langs/se.js +231 -231
  77. package/src/langs/tr.js +231 -231
  78. package/src/langs/uk.js +231 -231
  79. package/src/langs/ur.js +231 -231
  80. package/src/langs/zh_cn.js +231 -231
  81. package/src/modules/ApiManager.js +191 -191
  82. package/src/modules/Browser.js +669 -667
  83. package/src/modules/ColorPicker.js +364 -362
  84. package/src/modules/Controller.js +474 -454
  85. package/src/modules/Figure.js +1620 -1617
  86. package/src/modules/FileManager.js +359 -359
  87. package/src/modules/HueSlider.js +577 -565
  88. package/src/modules/Modal.js +346 -346
  89. package/src/modules/ModalAnchorEditor.js +643 -643
  90. package/src/modules/SelectMenu.js +549 -549
  91. package/src/modules/_DragHandle.js +17 -17
  92. package/src/modules/index.js +14 -14
  93. package/src/plugins/browser/audioGallery.js +83 -83
  94. package/src/plugins/browser/fileBrowser.js +103 -103
  95. package/src/plugins/browser/fileGallery.js +83 -83
  96. package/src/plugins/browser/imageGallery.js +81 -81
  97. package/src/plugins/browser/videoGallery.js +103 -103
  98. package/src/plugins/command/blockquote.js +61 -60
  99. package/src/plugins/command/exportPDF.js +134 -134
  100. package/src/plugins/command/fileUpload.js +456 -456
  101. package/src/plugins/command/list_bulleted.js +149 -148
  102. package/src/plugins/command/list_numbered.js +152 -151
  103. package/src/plugins/dropdown/align.js +157 -155
  104. package/src/plugins/dropdown/backgroundColor.js +108 -104
  105. package/src/plugins/dropdown/font.js +141 -137
  106. package/src/plugins/dropdown/fontColor.js +109 -105
  107. package/src/plugins/dropdown/formatBlock.js +170 -178
  108. package/src/plugins/dropdown/hr.js +152 -152
  109. package/src/plugins/dropdown/layout.js +83 -83
  110. package/src/plugins/dropdown/lineHeight.js +131 -130
  111. package/src/plugins/dropdown/list.js +123 -122
  112. package/src/plugins/dropdown/paragraphStyle.js +138 -138
  113. package/src/plugins/dropdown/table.js +4110 -4000
  114. package/src/plugins/dropdown/template.js +83 -83
  115. package/src/plugins/dropdown/textStyle.js +149 -149
  116. package/src/plugins/field/mention.js +242 -242
  117. package/src/plugins/index.js +120 -120
  118. package/src/plugins/input/fontSize.js +414 -410
  119. package/src/plugins/input/pageNavigator.js +71 -70
  120. package/src/plugins/modal/audio.js +677 -677
  121. package/src/plugins/modal/drawing.js +537 -531
  122. package/src/plugins/modal/embed.js +886 -886
  123. package/src/plugins/modal/image.js +1377 -1376
  124. package/src/plugins/modal/link.js +248 -240
  125. package/src/plugins/modal/math.js +563 -563
  126. package/src/plugins/modal/video.js +1226 -1226
  127. package/src/plugins/popup/anchor.js +224 -222
  128. package/src/suneditor.js +114 -107
  129. package/src/themes/dark.css +132 -122
  130. package/src/typedef.js +132 -130
  131. package/types/assets/icons/defaultIcons.d.ts +8 -0
  132. package/types/core/base/eventManager.d.ts +29 -4
  133. package/types/core/class/char.d.ts +2 -1
  134. package/types/core/class/component.d.ts +1 -2
  135. package/types/core/class/format.d.ts +8 -1
  136. package/types/core/class/html.d.ts +8 -0
  137. package/types/core/class/menu.d.ts +8 -0
  138. package/types/core/class/offset.d.ts +24 -26
  139. package/types/core/class/selection.d.ts +2 -0
  140. package/types/core/class/toolbar.d.ts +6 -0
  141. package/types/core/class/ui.d.ts +1 -1
  142. package/types/core/editor.d.ts +34 -12
  143. package/types/core/section/constructor.d.ts +5 -638
  144. package/types/core/section/documentType.d.ts +12 -2
  145. package/types/core/section/options.d.ts +740 -0
  146. package/types/core/util/instanceCheck.d.ts +50 -0
  147. package/types/editorInjector/_core.d.ts +5 -5
  148. package/types/editorInjector/index.d.ts +2 -2
  149. package/types/events.d.ts +2 -0
  150. package/types/helper/converter.d.ts +9 -0
  151. package/types/helper/dom/domQuery.d.ts +5 -5
  152. package/types/helper/dom/domUtils.d.ts +8 -0
  153. package/types/helper/env.d.ts +6 -1
  154. package/types/helper/index.d.ts +4 -1
  155. package/types/index.d.ts +122 -120
  156. package/types/langs/_Lang.d.ts +194 -194
  157. package/types/modules/ColorPicker.d.ts +5 -1
  158. package/types/modules/Controller.d.ts +8 -4
  159. package/types/modules/Figure.d.ts +2 -1
  160. package/types/modules/HueSlider.d.ts +4 -1
  161. package/types/modules/SelectMenu.d.ts +1 -1
  162. package/types/plugins/command/blockquote.d.ts +1 -0
  163. package/types/plugins/command/list_bulleted.d.ts +1 -0
  164. package/types/plugins/command/list_numbered.d.ts +1 -0
  165. package/types/plugins/dropdown/align.d.ts +1 -0
  166. package/types/plugins/dropdown/backgroundColor.d.ts +1 -0
  167. package/types/plugins/dropdown/font.d.ts +1 -0
  168. package/types/plugins/dropdown/fontColor.d.ts +1 -0
  169. package/types/plugins/dropdown/formatBlock.d.ts +3 -2
  170. package/types/plugins/dropdown/lineHeight.d.ts +1 -0
  171. package/types/plugins/dropdown/list.d.ts +1 -0
  172. package/types/plugins/dropdown/table.d.ts +6 -0
  173. package/types/plugins/input/fontSize.d.ts +1 -0
  174. package/types/plugins/modal/drawing.d.ts +4 -0
  175. package/types/plugins/modal/link.d.ts +32 -15
  176. package/types/suneditor.d.ts +13 -9
  177. package/types/typedef.d.ts +8 -0
@@ -1,362 +1,364 @@
1
- import { dom, converter } from '../helper';
2
- import { isElement } from '../helper/dom/domCheck';
3
- import CoreInjector from '../editorInjector/_core';
4
- import { HueSlider } from '../modules';
5
-
6
- const DEFAULT_COLOR_LIST = [
7
- '#ff0000',
8
- '#ff5e00',
9
- '#ffe400',
10
- '#abf200',
11
- '#00d8ff',
12
- '#0055ff',
13
- '#6600ff',
14
- '#ff00dd',
15
- '#000000',
16
- '#ffd8d8',
17
- '#fae0d4',
18
- '#faf4c0',
19
- '#e4f7ba',
20
- '#d4f4fa',
21
- '#d9e5ff',
22
- '#e8d9ff',
23
- '#ffd9fa',
24
- '#f1f1f1',
25
- '#ffa7a7',
26
- '#ffc19e',
27
- '#faed7d',
28
- '#cef279',
29
- '#b2ebf4',
30
- '#b2ccff',
31
- '#d1b2ff',
32
- '#ffb2f5',
33
- '#bdbdbd',
34
- '#f15f5f',
35
- '#f29661',
36
- '#e5d85c',
37
- '#bce55c',
38
- '#5cd1e5',
39
- '#6699ff',
40
- '#a366ff',
41
- '#f261df',
42
- '#8c8c8c',
43
- '#980000',
44
- '#993800',
45
- '#998a00',
46
- '#6b9900',
47
- '#008299',
48
- '#003399',
49
- '#3d0099',
50
- '#990085',
51
- '#353535',
52
- '#670000',
53
- '#662500',
54
- '#665c00',
55
- '#476600',
56
- '#005766',
57
- '#002266',
58
- '#290066',
59
- '#660058',
60
- '#222222'
61
- ];
62
-
63
- const DEFAULLT_COLOR_SPLITNUM = 9;
64
-
65
- /**
66
- * @typedef {import('./HueSlider').HueSliderParams} HueSliderParams_colorPicker
67
- */
68
-
69
- /**
70
- * @typedef {import('./HueSlider').HueSliderColor} HueSliderColor_colorPicker
71
- */
72
-
73
- /**
74
- * @typedef {Object} ColorPickerParams
75
- * @property {Array<string|{value: string, name: string}>=} [colorList=[]] color list
76
- * @property {number=} [splitNum=0] Number of colors to be displayed in one line
77
- * @property {string=} [defaultColor] Default color
78
- * @property {boolean=} [disableHEXInput=false] Disable HEX input
79
- * @property {boolean=} [disableRemove=false] Disable remove button
80
- * @property {HueSliderParams_colorPicker=} [hueSliderOptions] hue slider options
81
- */
82
-
83
- /**
84
- * @class
85
- * @description Create a color picker element and register for related events. (this.target)
86
- * - When calling the color selection, "submit", and "remove" buttons, the "action" method of the instance is called with the "color" value as an argument.
87
- */
88
- class ColorPicker extends CoreInjector {
89
- /**
90
- * @constructor
91
- * @param {*} inst The instance object that called the constructor.
92
- * @param {string} styles style property ("color", "backgroundColor"..)
93
- * @param {ColorPickerParams} params Color picker options
94
- */
95
- constructor(inst, styles, params) {
96
- const editor = inst.editor;
97
- super(editor);
98
-
99
- // members
100
- this.kind = inst.constructor.key || inst.constructor.name;
101
- this.inst = inst;
102
- this.target = CreateHTML(editor, params);
103
- this.targetButton = null;
104
- this.inputElement = /** @type {HTMLInputElement} */ (this.target.querySelector('.se-color-input'));
105
- this.styleProperties = styles;
106
- this.splitNum = params.splitNum || 0;
107
- this.defaultColor = params.defaultColor;
108
- this.hueSliderOptions = params.hueSliderOptions;
109
- this.parentDisplay = '';
110
- this.currentColor = '';
111
- this.parentForm = null;
112
- this.colorList = this.target.querySelectorAll('li button') || [];
113
- this.hueSlider = null;
114
-
115
- // check icon
116
- const parser = new DOMParser();
117
- const svgDoc = parser.parseFromString(this.icons.color_checked, 'image/svg+xml');
118
- this.checkedIcon = svgDoc.documentElement;
119
-
120
- // modules - hex, hue slider
121
- if (!params.disableHEXInput) {
122
- this.hueSlider = new HueSlider(this, params.hueSliderOptions, 'se-dropdown');
123
- this.parentFormDisplay = [];
124
- this.parentForm = params.hueSliderOptions?.controllerOptions?.parents?.length > 0 && !params.hueSliderOptions?.controllerOptions?.isInsideForm ? params.hueSliderOptions.controllerOptions.parents : null;
125
- // hue open
126
- this.eventManager.addEvent(this.target.querySelector('.se-btn-info'), 'click', this.#OnColorPalette.bind(this));
127
- this.eventManager.addEvent(this.inputElement, 'input', this.#OnChangeInput.bind(this));
128
- this.eventManager.addEvent(this.target.querySelector('form'), 'submit', this.#Submit.bind(this));
129
- }
130
-
131
- // remove style
132
- if (!params.disableRemove) {
133
- this.eventManager.addEvent(this.target.querySelector('.__se_remove'), 'click', this.#Remove.bind(this));
134
- }
135
-
136
- this.eventManager.addEvent(this.target, 'click', this.#OnClickColor.bind(this));
137
- }
138
-
139
- /**
140
- * @description Displays or resets the currently selected color at color list.
141
- * @param {Node|string} nodeOrColor Current Selected node
142
- * @param {Node} target target
143
- */
144
- init(nodeOrColor, target) {
145
- this.targetButton = target;
146
-
147
- const computedColor = this.editor.frameContext.get('wwComputedStyle')[this.styleProperties];
148
- const defaultColor = this.defaultColor || converter.isHexColor(computedColor) ? computedColor : converter.rgb2hex(computedColor);
149
-
150
- let fillColor = (typeof nodeOrColor === 'string' ? nodeOrColor : this._getColorInNode(nodeOrColor)) || defaultColor;
151
- fillColor = converter.isHexColor(fillColor) ? fillColor : converter.rgb2hex(fillColor) || fillColor || '';
152
-
153
- const colorList = this.colorList;
154
- for (let i = 0, len = colorList.length, c; i < len; i++) {
155
- c = colorList[i];
156
- if (fillColor.toLowerCase() === c.getAttribute('data-value').toLowerCase()) {
157
- c.appendChild(this.checkedIcon);
158
- dom.utils.addClass(c, 'active');
159
- } else {
160
- dom.utils.removeClass(c, 'active');
161
- if (c.contains(this.checkedIcon)) dom.utils.removeItem(this.checkedIcon);
162
- }
163
- }
164
-
165
- this._setInputText(this._colorName2hex(fillColor));
166
- }
167
-
168
- /**
169
- * @description Store color values
170
- * @param {string} hexColorStr Hax color value
171
- */
172
- setHexColor(hexColorStr) {
173
- this.currentColor = hexColorStr;
174
- this.inputElement.style.borderColor = hexColorStr;
175
- }
176
-
177
- /**
178
- * @description Close hue slider
179
- */
180
- hueSliderClose() {
181
- this.hueSlider.off();
182
- }
183
-
184
- /**
185
- * @private
186
- * @description Set color at input element
187
- * @param {string} hexColorStr Hax color value
188
- */
189
- _setInputText(hexColorStr) {
190
- hexColorStr = /^#/.test(hexColorStr) ? hexColorStr : '#' + hexColorStr;
191
- this.inputElement.value = hexColorStr;
192
- this.setHexColor.call(this, hexColorStr);
193
- }
194
-
195
- /**
196
- * @private
197
- * @description Gets color value at color property of node
198
- * @param {Node} node Selected node
199
- * @returns {string}
200
- */
201
- _getColorInNode(node) {
202
- let findColor = '';
203
- const sp = this.styleProperties;
204
-
205
- while (node && !dom.check.isWysiwygFrame(node) && findColor.length === 0) {
206
- if (isElement(node) && node.style[sp]) findColor = node.style[sp];
207
- node = node.parentNode;
208
- }
209
-
210
- return findColor;
211
- }
212
-
213
- /**
214
- * @private
215
- * @description Converts color values of other formats to hex color values and returns.
216
- * @param {string} colorName Color value
217
- * @returns {string}
218
- */
219
- _colorName2hex(colorName) {
220
- if (/^#/.test(colorName)) return colorName;
221
- const temp = dom.utils.createElement('div', { style: 'display: none; color: ' + colorName });
222
- const colors = this._w
223
- .getComputedStyle(this._d.body.appendChild(temp))
224
- .color.match(/\d+/g)
225
- .map(function (a) {
226
- return parseInt(a, 10);
227
- });
228
- dom.utils.removeItem(temp);
229
- return colors.length >= 3 ? '#' + ((1 << 24) + (colors[0] << 16) + (colors[1] << 8) + colors[2]).toString(16).substring(1) : '';
230
- }
231
-
232
- /**
233
- * @editorMethod Modules.HueSlider
234
- * @description This method is called when the color is selected in the hue slider.
235
- * @param {HueSliderColor_colorPicker} color - Color object
236
- */
237
- hueSliderAction(color) {
238
- this._setInputText(color.hex);
239
- }
240
-
241
- /**
242
- * @editorMethod Modules.HueSlider
243
- * @description This method is called when the hue slider is closed.
244
- */
245
- hueSliderCancelAction() {
246
- if (this.parentForm?.length > 0) {
247
- this.parentFormDisplay.forEach((e) => (e[0].style.display = e[1]));
248
- }
249
- }
250
-
251
- #OnColorPalette() {
252
- if (this.parentForm?.length > 0) {
253
- this.parentForm.forEach((e) => {
254
- this.parentFormDisplay.push([e, e.style.display]);
255
- e.style.display = 'none';
256
- });
257
- }
258
- this.hueSlider.open(this.targetButton);
259
- }
260
-
261
- /**
262
- * @param {SubmitEvent} e Event object
263
- */
264
- #Submit(e) {
265
- e.preventDefault();
266
-
267
- if (typeof this.inst.colorPickerAction !== 'function') return;
268
- this.inst.colorPickerAction(this.currentColor);
269
- }
270
-
271
- /**
272
- * @param {MouseEvent} e Event object
273
- */
274
- #OnClickColor(e) {
275
- const eventTarget = dom.query.getEventTarget(e);
276
- const color = eventTarget.getAttribute('data-value');
277
- if (!color) return;
278
-
279
- if (typeof this.inst.colorPickerAction !== 'function') return;
280
- this.inst.colorPickerAction(color);
281
- }
282
-
283
- #Remove() {
284
- if (typeof this.inst.colorPickerAction !== 'function') return;
285
- this.inst.colorPickerAction(null);
286
- }
287
-
288
- /**
289
- * @param {InputEvent} e Event object
290
- */
291
- #OnChangeInput(e) {
292
- /** @type {HTMLInputElement} */
293
- const eventTarget = dom.query.getEventTarget(e);
294
- this.setHexColor(eventTarget.value);
295
- }
296
- }
297
-
298
- /**
299
- * @private
300
- * @description Create a color picker element
301
- * @param {*} param0
302
- * @param {*} param1
303
- * @returns
304
- */
305
- function CreateHTML({ lang, icons }, { colorList, disableHEXInput, disableRemove, splitNum }) {
306
- colorList = colorList || DEFAULT_COLOR_LIST;
307
- splitNum = colorList === DEFAULT_COLOR_LIST ? DEFAULLT_COLOR_SPLITNUM : splitNum;
308
-
309
- let list = '';
310
- for (let i = 0, len = colorList.length, colorArr = [], color; i < len; i++) {
311
- color = colorList[i];
312
- if (!color) continue;
313
-
314
- if (typeof color === 'string' || color.value) {
315
- colorArr.push(color);
316
- if (i < len - 1) continue;
317
- }
318
- if (colorArr.length > 0) {
319
- list += `<div class="se-selector-color">${_makeColor(colorArr, splitNum)}</div>`;
320
- colorArr = [];
321
- }
322
- if (typeof color === 'object') {
323
- list += `<div class="se-selector-color">${_makeColor(color, splitNum)}</div>`;
324
- }
325
- }
326
- list += /*html*/ `
327
- <form class="se-form-group se-form-w0">
328
- ${disableHEXInput ? '' : `<button type="button" class="se-btn se-btn-info" title="${lang.colorPicker}" aria-label="${lang.colorPicker}">${icons.color_palette}</button>`}
329
- <input type="text" class="se-color-input" ${disableHEXInput ? 'readonly' : ''} placeholder="${lang.color}" />
330
- ${disableHEXInput ? '' : `<button type="submit" class="se-btn se-btn-success" title="${lang.submitButton}" aria-label="${lang.submitButton}">${icons.checked}</button>`}
331
- ${disableRemove ? '' : `<button type="button" class="se-btn __se_remove" title="${lang.remove}" aria-label="${lang.remove}">${icons.remove_color}</button>`}
332
- </form>`;
333
-
334
- return dom.utils.createElement('DIV', { class: 'se-list-inner' }, list);
335
- }
336
-
337
- function _makeColor(colorList, splitNum) {
338
- const ulHTML = `<ul class="se-color-pallet${splitNum ? ' se-list-horizontal' : ''}">`;
339
-
340
- let list = ulHTML;
341
- for (let i = 0, len = colorList.length, color, v, n; i < len; i++) {
342
- color = colorList[i];
343
- if (typeof color === 'string') {
344
- v = color;
345
- n = color;
346
- } else if (typeof color === 'object') {
347
- v = color.value;
348
- n = color.name || v;
349
- }
350
-
351
- if (i > 0 && i % splitNum === 0) {
352
- list += `</ul>${ulHTML}`;
353
- }
354
-
355
- list += /*html*/ `<li><button type="button" data-value="${v}" title="${n}" aria-label="${n}" style="background-color:${v};"></button></li>`;
356
- }
357
- list += '</ul>';
358
-
359
- return list;
360
- }
361
-
362
- export default ColorPicker;
1
+ import { dom, converter } from '../helper';
2
+ import { isElement } from '../helper/dom/domCheck';
3
+ import CoreInjector from '../editorInjector/_core';
4
+ import { HueSlider } from '../modules';
5
+
6
+ const DEFAULT_COLOR_LIST = [
7
+ '#ff0000',
8
+ '#ff5e00',
9
+ '#ffe400',
10
+ '#abf200',
11
+ '#00d8ff',
12
+ '#0055ff',
13
+ '#6600ff',
14
+ '#ff00dd',
15
+ '#000000',
16
+ '#ffd8d8',
17
+ '#fae0d4',
18
+ '#faf4c0',
19
+ '#e4f7ba',
20
+ '#d4f4fa',
21
+ '#d9e5ff',
22
+ '#e8d9ff',
23
+ '#ffd9fa',
24
+ '#f1f1f1',
25
+ '#ffa7a7',
26
+ '#ffc19e',
27
+ '#faed7d',
28
+ '#cef279',
29
+ '#b2ebf4',
30
+ '#b2ccff',
31
+ '#d1b2ff',
32
+ '#ffb2f5',
33
+ '#bdbdbd',
34
+ '#f15f5f',
35
+ '#f29661',
36
+ '#e5d85c',
37
+ '#bce55c',
38
+ '#5cd1e5',
39
+ '#6699ff',
40
+ '#a366ff',
41
+ '#f261df',
42
+ '#8c8c8c',
43
+ '#980000',
44
+ '#993800',
45
+ '#998a00',
46
+ '#6b9900',
47
+ '#008299',
48
+ '#003399',
49
+ '#3d0099',
50
+ '#990085',
51
+ '#353535',
52
+ '#670000',
53
+ '#662500',
54
+ '#665c00',
55
+ '#476600',
56
+ '#005766',
57
+ '#002266',
58
+ '#290066',
59
+ '#660058',
60
+ '#222222'
61
+ ];
62
+
63
+ const DEFAULLT_COLOR_SPLITNUM = 9;
64
+
65
+ /**
66
+ * @typedef {import('./HueSlider').HueSliderParams} HueSliderParams_colorPicker
67
+ */
68
+
69
+ /**
70
+ * @typedef {import('./HueSlider').HueSliderColor} HueSliderColor_colorPicker
71
+ */
72
+
73
+ /**
74
+ * @typedef {Object} ColorPickerParams
75
+ * @property {Array<string|{value: string, name: string}>=} [colorList=[]] color list
76
+ * @property {number=} [splitNum=0] Number of colors to be displayed in one line
77
+ * @property {string=} [defaultColor] Default color
78
+ * @property {boolean=} [disableHEXInput=false] Disable HEX input
79
+ * @property {boolean=} [disableRemove=false] Disable remove button
80
+ * @property {HueSliderParams_colorPicker=} [hueSliderOptions] hue slider options
81
+ */
82
+
83
+ /**
84
+ * @class
85
+ * @description Create a color picker element and register for related events. (this.target)
86
+ * - When calling the color selection, "submit", and "remove" buttons, the "action" method of the instance is called with the "color" value as an argument.
87
+ */
88
+ class ColorPicker extends CoreInjector {
89
+ /**
90
+ * @constructor
91
+ * @param {*} inst The instance object that called the constructor.
92
+ * @param {string} styles style property ("color", "backgroundColor"..)
93
+ * @param {ColorPickerParams} params Color picker options
94
+ */
95
+ constructor(inst, styles, params) {
96
+ const editor = inst.editor;
97
+ super(editor);
98
+
99
+ // members
100
+ this.kind = inst.constructor.key || inst.constructor.name;
101
+ this.inst = inst;
102
+ this.target = CreateHTML(editor, params);
103
+ this.targetButton = null;
104
+ this.inputElement = /** @type {HTMLInputElement} */ (this.target.querySelector('.se-color-input'));
105
+ this.styleProperties = styles;
106
+ this.splitNum = params.splitNum || 0;
107
+ this.defaultColor = params.defaultColor || '';
108
+ this.hueSliderOptions = params.hueSliderOptions;
109
+ this.parentDisplay = '';
110
+ this.currentColor = '';
111
+ this.parentForm = null;
112
+ this.colorList = this.target.querySelectorAll('li button') || [];
113
+ this.hueSlider = null;
114
+
115
+ // check icon
116
+ const parser = new DOMParser();
117
+ const svgDoc = parser.parseFromString(this.icons.color_checked, 'image/svg+xml');
118
+ this.checkedIcon = svgDoc.documentElement;
119
+
120
+ // modules - hex, hue slider
121
+ if (!params.disableHEXInput) {
122
+ this.hueSlider = new HueSlider(this, params.hueSliderOptions, 'se-dropdown');
123
+ this.parentFormDisplay = [];
124
+ this.parentForm = params.hueSliderOptions?.controllerOptions?.parents?.length > 0 && !params.hueSliderOptions?.controllerOptions?.isInsideForm ? params.hueSliderOptions.controllerOptions.parents : null;
125
+ // hue open
126
+ this.eventManager.addEvent(this.target.querySelector('.__se_hue'), 'click', this.#OnColorPalette.bind(this));
127
+ this.eventManager.addEvent(this.inputElement, 'input', this.#OnChangeInput.bind(this));
128
+ this.eventManager.addEvent(this.target.querySelector('form'), 'submit', this.#Submit.bind(this));
129
+ }
130
+
131
+ // remove style
132
+ if (!params.disableRemove) {
133
+ this.eventManager.addEvent(this.target.querySelector('.__se_remove'), 'click', this.#Remove.bind(this));
134
+ }
135
+
136
+ this.eventManager.addEvent(this.target, 'click', this.#OnClickColor.bind(this));
137
+ }
138
+
139
+ /**
140
+ * @description Displays or resets the currently selected color at color list.
141
+ * @param {Node|string} nodeOrColor Current Selected node
142
+ * @param {Node} target target
143
+ * @param {?((current: Node) => boolean)=} stopCondition - A function used to stop traversing parent nodes while finding the color.
144
+ * - When this function returns true, the traversal ends at that node.
145
+ * - e.g., `(node) => this.format.isLine(node)` stops at line-level elements like <p>, <div>.
146
+ */
147
+ init(nodeOrColor, target, stopCondition) {
148
+ this.targetButton = target;
149
+ if (typeof stopCondition !== 'function') stopCondition = () => false;
150
+
151
+ let fillColor = (typeof nodeOrColor === 'string' ? nodeOrColor : this._getColorInNode(nodeOrColor, stopCondition)) || this.defaultColor;
152
+ fillColor = converter.isHexColor(fillColor) ? fillColor : converter.rgb2hex(fillColor) || fillColor || '';
153
+
154
+ const colorList = this.colorList;
155
+ for (let i = 0, len = colorList.length, c; i < len; i++) {
156
+ c = colorList[i];
157
+ if (fillColor.toLowerCase() === c.getAttribute('data-value').toLowerCase()) {
158
+ c.appendChild(this.checkedIcon);
159
+ dom.utils.addClass(c, 'active');
160
+ } else {
161
+ dom.utils.removeClass(c, 'active');
162
+ if (c.contains(this.checkedIcon)) dom.utils.removeItem(this.checkedIcon);
163
+ }
164
+ }
165
+
166
+ this._setInputText(this._colorName2hex(fillColor));
167
+ }
168
+
169
+ /**
170
+ * @description Store color values
171
+ * @param {string} hexColorStr Hax color value
172
+ */
173
+ setHexColor(hexColorStr) {
174
+ this.currentColor = hexColorStr;
175
+ this.inputElement.style.borderColor = hexColorStr;
176
+ }
177
+
178
+ /**
179
+ * @description Close hue slider
180
+ */
181
+ hueSliderClose() {
182
+ this.hueSlider.off();
183
+ }
184
+
185
+ /**
186
+ * @private
187
+ * @description Set color at input element
188
+ * @param {string} hexColorStr Hax color value
189
+ */
190
+ _setInputText(hexColorStr) {
191
+ hexColorStr = !hexColorStr || /^#/.test(hexColorStr) ? hexColorStr : '#' + hexColorStr;
192
+ this.inputElement.value = hexColorStr;
193
+ this.setHexColor.call(this, hexColorStr);
194
+ }
195
+
196
+ /**
197
+ * @private
198
+ * @description Gets color value at color property of node
199
+ * @param {Node} node Selected node
200
+ * @param {(current: Node) => boolean} stopCondition - A function used to stop traversing parent nodes while finding the color.
201
+ * @returns {string}
202
+ */
203
+ _getColorInNode(node, stopCondition) {
204
+ let findColor = '';
205
+ const sp = this.styleProperties;
206
+
207
+ while (node && !stopCondition(node) && !dom.check.isWysiwygFrame(node) && findColor.length === 0) {
208
+ if (isElement(node) && node.style[sp]) findColor = node.style[sp];
209
+ node = node.parentNode;
210
+ }
211
+
212
+ return findColor;
213
+ }
214
+
215
+ /**
216
+ * @private
217
+ * @description Converts color values of other formats to hex color values and returns.
218
+ * @param {string} colorName Color value
219
+ * @returns {string}
220
+ */
221
+ _colorName2hex(colorName) {
222
+ if (!colorName || /^#/.test(colorName)) return colorName;
223
+ const temp = dom.utils.createElement('div', { style: 'display: none; color: ' + colorName });
224
+ const colors = this._w
225
+ .getComputedStyle(this._d.body.appendChild(temp))
226
+ .color.match(/\d+/g)
227
+ .map(function (a) {
228
+ return parseInt(a, 10);
229
+ });
230
+ dom.utils.removeItem(temp);
231
+ return colors.length >= 3 ? '#' + ((1 << 24) + (colors[0] << 16) + (colors[1] << 8) + colors[2]).toString(16).substring(1) : '';
232
+ }
233
+
234
+ /**
235
+ * @editorMethod Modules.HueSlider
236
+ * @description This method is called when the color is selected in the hue slider.
237
+ * @param {HueSliderColor_colorPicker} color - Color object
238
+ */
239
+ hueSliderAction(color) {
240
+ this._setInputText(color.hex);
241
+ }
242
+
243
+ /**
244
+ * @editorMethod Modules.HueSlider
245
+ * @description This method is called when the hue slider is closed.
246
+ */
247
+ hueSliderCancelAction() {
248
+ if (this.parentForm?.length > 0) {
249
+ this.parentFormDisplay.forEach((e) => (e[0].style.display = e[1]));
250
+ }
251
+ }
252
+
253
+ #OnColorPalette() {
254
+ if (this.parentForm?.length > 0) {
255
+ this.parentForm.forEach((e) => {
256
+ this.parentFormDisplay.push([e, e.style.display]);
257
+ e.style.display = 'none';
258
+ });
259
+ }
260
+ this.hueSlider.open(this.targetButton);
261
+ }
262
+
263
+ /**
264
+ * @param {SubmitEvent} e Event object
265
+ */
266
+ #Submit(e) {
267
+ e.preventDefault();
268
+
269
+ if (typeof this.inst.colorPickerAction !== 'function') return;
270
+ this.inst.colorPickerAction(this.currentColor);
271
+ }
272
+
273
+ /**
274
+ * @param {MouseEvent} e Event object
275
+ */
276
+ #OnClickColor(e) {
277
+ const eventTarget = dom.query.getEventTarget(e);
278
+ const color = eventTarget.getAttribute('data-value');
279
+ if (!color) return;
280
+
281
+ if (typeof this.inst.colorPickerAction !== 'function') return;
282
+ this.inst.colorPickerAction(color);
283
+ }
284
+
285
+ #Remove() {
286
+ if (typeof this.inst.colorPickerAction !== 'function') return;
287
+ this.inst.colorPickerAction(null);
288
+ }
289
+
290
+ /**
291
+ * @param {InputEvent} e Event object
292
+ */
293
+ #OnChangeInput(e) {
294
+ /** @type {HTMLInputElement} */
295
+ const eventTarget = dom.query.getEventTarget(e);
296
+ this.setHexColor(eventTarget.value);
297
+ }
298
+ }
299
+
300
+ /**
301
+ * @private
302
+ * @description Create a color picker element
303
+ * @param {*} param0
304
+ * @param {*} param1
305
+ * @returns
306
+ */
307
+ function CreateHTML({ lang, icons }, { colorList, disableHEXInput, disableRemove, splitNum }) {
308
+ colorList = colorList || DEFAULT_COLOR_LIST;
309
+ splitNum = colorList === DEFAULT_COLOR_LIST ? DEFAULLT_COLOR_SPLITNUM : splitNum;
310
+
311
+ let list = '';
312
+ for (let i = 0, len = colorList.length, colorArr = [], color; i < len; i++) {
313
+ color = colorList[i];
314
+ if (!color) continue;
315
+
316
+ if (typeof color === 'string' || color.value) {
317
+ colorArr.push(color);
318
+ if (i < len - 1) continue;
319
+ }
320
+ if (colorArr.length > 0) {
321
+ list += `<div class="se-selector-color">${_makeColor(colorArr, splitNum)}</div>`;
322
+ colorArr = [];
323
+ }
324
+ if (typeof color === 'object') {
325
+ list += `<div class="se-selector-color">${_makeColor(color, splitNum)}</div>`;
326
+ }
327
+ }
328
+ list += /*html*/ `
329
+ <form class="se-form-group se-form-w0">
330
+ ${disableHEXInput ? '' : `<button type="button" class="se-btn __se_hue" title="${lang.colorPicker}" aria-label="${lang.colorPicker}">${icons.color_palette}</button>`}
331
+ <input type="text" class="se-color-input" ${disableHEXInput ? 'readonly' : ''} placeholder="${lang.color}" />
332
+ ${disableHEXInput ? '' : `<button type="submit" class="se-btn se-btn-success" title="${lang.submitButton}" aria-label="${lang.submitButton}">${icons.checked}</button>`}
333
+ ${disableRemove ? '' : `<button type="button" class="se-btn __se_remove" title="${lang.remove}" aria-label="${lang.remove}">${icons.remove_color}</button>`}
334
+ </form>`;
335
+
336
+ return dom.utils.createElement('DIV', { class: 'se-list-inner' }, list);
337
+ }
338
+
339
+ function _makeColor(colorList, splitNum) {
340
+ const ulHTML = `<ul class="se-color-pallet${splitNum ? ' se-list-horizontal' : ''}">`;
341
+
342
+ let list = ulHTML;
343
+ for (let i = 0, len = colorList.length, color, v, n; i < len; i++) {
344
+ color = colorList[i];
345
+ if (typeof color === 'string') {
346
+ v = color;
347
+ n = color;
348
+ } else if (typeof color === 'object') {
349
+ v = color.value;
350
+ n = color.name || v;
351
+ }
352
+
353
+ if (i > 0 && i % splitNum === 0) {
354
+ list += `</ul>${ulHTML}`;
355
+ }
356
+
357
+ list += /*html*/ `<li><button type="button" data-value="${v}" title="${n}" aria-label="${n}" style="background-color:${v};"></button></li>`;
358
+ }
359
+ list += '</ul>';
360
+
361
+ return list;
362
+ }
363
+
364
+ export default ColorPicker;