@ebl-vue/editor-full 2.31.25 → 2.31.28

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 (114) hide show
  1. package/dist/index.d.ts +1 -28
  2. package/dist/index.mjs +549 -727
  3. package/dist/index.mjs.map +1 -1
  4. package/package.json +3 -3
  5. package/types/index.d.ts +5 -1
  6. package/.postcssrc.yml +0 -33
  7. package/postcss.config.js +0 -15
  8. package/src/components/Editor/Editor.vue +0 -293
  9. package/src/components/Editor/EditorRender.vue +0 -274
  10. package/src/components/index.ts +0 -29
  11. package/src/constants/index.ts +0 -1
  12. package/src/i18n/zh-cn.ts +0 -158
  13. package/src/icons/index.ts +0 -93
  14. package/src/index.ts +0 -22
  15. package/src/installer.ts +0 -21
  16. package/src/plugins/alert/index.css +0 -150
  17. package/src/plugins/alert/index.ts +0 -456
  18. package/src/plugins/block-alignment/index.css +0 -9
  19. package/src/plugins/block-alignment/index.ts +0 -117
  20. package/src/plugins/block-alignment/readme.md +0 -1
  21. package/src/plugins/code/LICENSE +0 -21
  22. package/src/plugins/code/index.css +0 -214
  23. package/src/plugins/code/index.ts +0 -621
  24. package/src/plugins/code/utils/string.ts +0 -34
  25. package/src/plugins/color-picker/index.ts +0 -130
  26. package/src/plugins/color-picker/styles.css +0 -27
  27. package/src/plugins/delimiter/index.css +0 -14
  28. package/src/plugins/delimiter/index.ts +0 -121
  29. package/src/plugins/drag-drop/index.css +0 -19
  30. package/src/plugins/drag-drop/index.ts +0 -151
  31. package/src/plugins/drag-drop/readme.md +0 -1
  32. package/src/plugins/header/H1.ts +0 -404
  33. package/src/plugins/header/H2.ts +0 -403
  34. package/src/plugins/header/H3.ts +0 -404
  35. package/src/plugins/header/H4.ts +0 -404
  36. package/src/plugins/header/H5.ts +0 -403
  37. package/src/plugins/header/H6.ts +0 -404
  38. package/src/plugins/header/index.css +0 -20
  39. package/src/plugins/header/index.ts +0 -15
  40. package/src/plugins/header/types.d.ts +0 -46
  41. package/src/plugins/imageResizeCrop/ImageTune.ts +0 -916
  42. package/src/plugins/imageResizeCrop/index.css +0 -230
  43. package/src/plugins/imageResizeCrop/index.ts +0 -5
  44. package/src/plugins/imageResizeCrop/types.d.ts +0 -23
  45. package/src/plugins/imageTool/index.css +0 -156
  46. package/src/plugins/imageTool/index.ts +0 -538
  47. package/src/plugins/imageTool/types/codexteam__ajax.d.ts +0 -89
  48. package/src/plugins/imageTool/types/types.ts +0 -236
  49. package/src/plugins/imageTool/ui.ts +0 -313
  50. package/src/plugins/imageTool/uploader.ts +0 -272
  51. package/src/plugins/imageTool/utils/dom.ts +0 -24
  52. package/src/plugins/imageTool/utils/index.ts +0 -73
  53. package/src/plugins/imageTool/utils/isPromise.ts +0 -10
  54. package/src/plugins/indent/index.css +0 -86
  55. package/src/plugins/indent/index.ts +0 -695
  56. package/src/plugins/inline-code/index.css +0 -11
  57. package/src/plugins/inline-code/index.ts +0 -202
  58. package/src/plugins/list/ListRenderer/ChecklistRenderer.ts +0 -208
  59. package/src/plugins/list/ListRenderer/ListRenderer.ts +0 -73
  60. package/src/plugins/list/ListRenderer/OrderedListRenderer.ts +0 -123
  61. package/src/plugins/list/ListRenderer/UnorderedListRenderer.ts +0 -123
  62. package/src/plugins/list/ListRenderer/index.ts +0 -6
  63. package/src/plugins/list/ListTabulator/index.ts +0 -1179
  64. package/src/plugins/list/index.ts +0 -480
  65. package/src/plugins/list/styles/CssPrefix.ts +0 -4
  66. package/src/plugins/list/styles/input.css +0 -36
  67. package/src/plugins/list/styles/list.css +0 -165
  68. package/src/plugins/list/types/Elements.ts +0 -14
  69. package/src/plugins/list/types/ItemMeta.ts +0 -40
  70. package/src/plugins/list/types/ListParams.ts +0 -102
  71. package/src/plugins/list/types/ListRenderer.ts +0 -6
  72. package/src/plugins/list/types/OlCounterType.ts +0 -63
  73. package/src/plugins/list/types/index.ts +0 -14
  74. package/src/plugins/list/utils/focusItem.ts +0 -18
  75. package/src/plugins/list/utils/getChildItems.ts +0 -40
  76. package/src/plugins/list/utils/getItemChildWrapper.ts +0 -10
  77. package/src/plugins/list/utils/getItemContentElement.ts +0 -10
  78. package/src/plugins/list/utils/getSiblings.ts +0 -52
  79. package/src/plugins/list/utils/isLastItem.ts +0 -9
  80. package/src/plugins/list/utils/itemHasSublist.ts +0 -10
  81. package/src/plugins/list/utils/normalizeData.ts +0 -83
  82. package/src/plugins/list/utils/removeChildWrapperIfEmpty.ts +0 -31
  83. package/src/plugins/list/utils/renderToolboxInput.ts +0 -105
  84. package/src/plugins/list/utils/stripNumbers.ts +0 -7
  85. package/src/plugins/list/utils/type-guards.ts +0 -8
  86. package/src/plugins/marker/index.css +0 -4
  87. package/src/plugins/marker/index.ts +0 -199
  88. package/src/plugins/outline/index.css +0 -52
  89. package/src/plugins/outline/index.ts +0 -63
  90. package/src/plugins/paragraph/index.css +0 -23
  91. package/src/plugins/paragraph/index.ts +0 -381
  92. package/src/plugins/paragraph/types/icons.d.ts +0 -4
  93. package/src/plugins/paragraph/utils/makeFragment.ts +0 -17
  94. package/src/plugins/quote/index.css +0 -26
  95. package/src/plugins/quote/index.ts +0 -203
  96. package/src/plugins/table/index.ts +0 -4
  97. package/src/plugins/table/plugin.ts +0 -254
  98. package/src/plugins/table/style.css +0 -388
  99. package/src/plugins/table/table.ts +0 -1195
  100. package/src/plugins/table/toolbox.ts +0 -166
  101. package/src/plugins/table/utils/dom.ts +0 -130
  102. package/src/plugins/table/utils/popover.ts +0 -185
  103. package/src/plugins/table/utils/throttled.ts +0 -22
  104. package/src/plugins/underline/index.css +0 -3
  105. package/src/plugins/underline/index.ts +0 -214
  106. package/src/plugins/undo/index.ts +0 -524
  107. package/src/plugins/undo/observer.ts +0 -101
  108. package/src/style.css +0 -114
  109. package/src/types.ts +0 -3
  110. package/src/utils/AxiosService.ts +0 -87
  111. package/src/utils/index.ts +0 -15
  112. package/src/utils/install.ts +0 -19
  113. package/tsconfig.json +0 -37
  114. package/vite.config.ts +0 -81
@@ -1,916 +0,0 @@
1
-
2
- //import Cropper from 'cropperjs';
3
- //import 'cropperjs/dist/cropper.css';
4
- import './index.css';
5
- import type { BlockTune, API, BlockAPI } from '@ebl-vue/editorjs/types'
6
-
7
-
8
- export interface TuneSetting {
9
- name: string;
10
- icon: string;
11
- label: string;
12
- group: string;
13
- }
14
-
15
- export interface ImageToolTuneData {
16
- floatLeft: boolean;
17
- floatRight: boolean;
18
- center: boolean;
19
- sizeSmall: boolean;
20
- sizeMiddle: boolean;
21
- sizeLarge: boolean;
22
- resize: boolean;
23
- resizeSize: number;
24
- crop: boolean;
25
- cropperFrameHeight: number;
26
- cropperFrameWidth: number;
27
- cropperFrameLeft: number;
28
- cropperFrameTop: number;
29
- cropperImageHeight: number;
30
- cropperImageWidth: number;
31
- cropperInterface?: any//Cropper;
32
- }
33
-
34
- export interface ImageToolTuneConfig {
35
- resize: boolean;
36
- crop: boolean;
37
- }
38
-
39
- export interface CustomStyles {
40
- settingsButton: string;
41
- settingsButtonActive: string;
42
- settingsButtonModifier?: string;
43
- settingsButtonModifierActive?: string;
44
- }
45
-
46
- export type ImageToolTuneConstructor = {
47
- api: API;
48
- data: Partial<ImageToolTuneData>;
49
- config?: ImageToolTuneConfig;
50
- block: BlockAPI;
51
- };
52
-
53
- export default class ImageToolTune implements BlockTune {
54
- private settings: TuneSetting[];
55
- private api: API;
56
- private block: BlockAPI;
57
- private data: ImageToolTuneData;
58
- private wrapper: HTMLElement | undefined;
59
- private buttons: HTMLElement[];
60
- private styles: CustomStyles;
61
-
62
- constructor({ api, data, config, block }: ImageToolTuneConstructor) {
63
- this.settings = [
64
-
65
- ];
66
-
67
- this.api = api;
68
- this.block = block;
69
- this.data = {
70
- floatLeft: data?.floatLeft ?? false,
71
- floatRight: data?.floatRight ?? false,
72
- center: data?.center ?? false,
73
- sizeSmall: data?.sizeSmall ?? false,
74
- sizeMiddle: data?.sizeMiddle ?? false,
75
- sizeLarge: data?.sizeLarge ?? false,
76
- resize: data?.resize ?? config?.resize ?? false,
77
- resizeSize: data?.resizeSize ?? 0,
78
- crop: data?.crop ?? config?.crop ?? false,
79
- cropperFrameHeight: data?.cropperFrameHeight ?? 0,
80
- cropperFrameWidth: data?.cropperFrameWidth ?? 0,
81
- cropperFrameLeft: data?.cropperFrameLeft ?? 0,
82
- cropperFrameTop: data?.cropperFrameTop ?? 0,
83
- cropperImageHeight: data?.cropperImageHeight ?? 0,
84
- cropperImageWidth: data?.cropperImageWidth ?? 0,
85
- cropperInterface: undefined,
86
- };
87
- this.wrapper = undefined;
88
- this.buttons = [];
89
- this.styles = {
90
- settingsButton: 'cdx-settings-button',
91
- settingsButtonActive: 'cdx-settings-button--active',
92
- settingsButtonModifier: '',
93
- settingsButtonModifierActive: '',
94
- };
95
- }
96
-
97
- static get isTune(): boolean {
98
- return true;
99
- }
100
-
101
- static get sanitize(): Record<string, object> {
102
- return {
103
- floatLeft: {},
104
- floatRight: {},
105
- center: {},
106
- sizeSmall: {},
107
- sizeMiddle: {},
108
- sizeLarge: {},
109
- resize: {},
110
- resizeSize: {},
111
- crop: {},
112
- cropperFrameHeight: {},
113
- cropperFrameWidth: {},
114
- cropperFrameLeft: {},
115
- cropperFrameTop: {},
116
- cropperImageHeight: {},
117
- cropperImageWidth: {},
118
- cropperInterface: {},
119
- };
120
- }
121
-
122
- /**
123
- * CSS classes
124
- * @return {object}
125
- * @constructor
126
- * @property {string} CSS.wrapper - wrapper for buttons
127
- * @property {string} CSS.button - button
128
- * @property {string} CSS.buttonActive - active button
129
- * @property {string} CSS.buttonModifier - button with modifier
130
- * @property {string} CSS.buttonModifierActive - active button with modifier
131
- */
132
- get CSS(): Record<string, string> {
133
- return {
134
- wrapper: 'cdx-image-tool-tune',
135
- button: this.styles.settingsButton,
136
- buttonActive: this.styles.settingsButtonActive,
137
- buttonModifier: this.styles.settingsButtonModifier || '',
138
- buttonModifierActive: this.styles.settingsButtonModifierActive || '',
139
- isFloatLeft: 'cdx-image-tool-tune--floatLeft',
140
- isFloatRight: 'cdx-image-tool-tune--floatRight',
141
- isCenter: 'cdx-image-tool-tune--center',
142
- isSizeSmall: 'cdx-image-tool-tune--sizeSmall',
143
- isSizeMiddle: 'cdx-image-tool-tune--sizeMiddle',
144
- isSizeLarge: 'cdx-image-tool-tune--sizeLarge',
145
- isResize: 'cdx-image-tool-tune--resize',
146
- isCrop: 'cdx-image-tool-tune--crop',
147
- };
148
- }
149
-
150
- /**
151
- *
152
- * @return {HTMLElement}
153
- * @public
154
- * @readonly
155
- * @property {HTMLElement} wrapper - tune buttons wrapper
156
- */
157
- get view(): HTMLElement {
158
- if (!this.wrapper) {
159
- this.wrapper = this.createView();
160
- }
161
-
162
- return this.wrapper;
163
- }
164
-
165
- /**
166
- * Clicks to one of the tunes
167
- * @param {MouseEvent} e - click
168
- * @param {HTMLElement} tune - clicked tune button
169
- * @private
170
- * @return {void}
171
- * */
172
- tuneClicked(e: MouseEvent, tune: HTMLElement): void {
173
- e.preventDefault();
174
- e.stopPropagation();
175
-
176
- const tuneName = tune.dataset.tune || '';
177
- const tuneGroup = this.settings.find(t => t.name === tuneName)?.group;
178
-
179
- this.buttons.forEach(button => {
180
- //if is the same group
181
- if (
182
- this.settings.find(t => t.name === button.dataset.tune)?.group ===
183
- tuneGroup
184
- ) {
185
- if (button !== tune) {
186
- button.classList.remove(this.CSS.buttonActive);
187
- }
188
- }
189
- });
190
-
191
- tune.classList.toggle(this.CSS.buttonActive);
192
- this.setTune(tuneName);
193
- }
194
-
195
- /**
196
- * Styles the image with a tune
197
- * @param {string} tune - tune name
198
- * @private
199
- * @return {void}
200
- * */
201
- setTune(tune: string): void {
202
- switch (tune) {
203
- case 'floatLeft':
204
- this.data.floatLeft = !this.data.floatLeft;
205
- this.data.floatRight = false;
206
- this.data.center = false;
207
- break;
208
- case 'floatRight':
209
- this.data.floatLeft = false;
210
- this.data.floatRight = !this.data.floatRight;
211
- this.data.center = false;
212
- break;
213
- case 'center':
214
- this.data.center = !this.data.center;
215
- this.data.floatLeft = false;
216
- this.data.floatRight = false;
217
- break;
218
- case 'sizeSmall':
219
- this.data.sizeSmall = !this.data.sizeSmall;
220
- this.data.sizeMiddle = false;
221
- this.data.sizeLarge = false;
222
- this.data.resize = false;
223
- this.data.crop = false;
224
- break;
225
- case 'sizeMiddle':
226
- this.data.sizeSmall = false;
227
- this.data.sizeMiddle = !this.data.sizeMiddle;
228
- this.data.sizeLarge = false;
229
- this.data.resize = false;
230
- this.data.crop = false;
231
- break;
232
- case 'sizeLarge':
233
- this.data.sizeSmall = false;
234
- this.data.sizeMiddle = false;
235
- this.data.sizeLarge = !this.data.sizeLarge;
236
- this.data.resize = false;
237
- this.data.crop = false;
238
- break;
239
- case 'resize':
240
- this.data.sizeSmall = false;
241
- this.data.sizeMiddle = false;
242
- this.data.sizeLarge = false;
243
- this.data.resize = !this.data.resize;
244
- this.data.crop = false;
245
- break;
246
- case 'crop':
247
- this.data.crop = !this.data.crop;
248
- this.data.sizeSmall = false;
249
- this.data.sizeMiddle = false;
250
- this.data.sizeLarge = false;
251
- this.data.resize = false;
252
- this.data.resizeSize = 0;
253
- break;
254
- default:
255
- this.data.floatLeft = false;
256
- this.data.floatRight = false;
257
- this.data.sizeSmall = false;
258
- this.data.sizeMiddle = false;
259
- this.data.sizeLarge = false;
260
- this.data.resize = false;
261
- this.data.crop = false;
262
- break;
263
- }
264
-
265
- if (!this.data.resize) {
266
- this.data.resizeSize = 0;
267
- }
268
-
269
- if (!this.data.crop) {
270
- this.data.cropperFrameHeight = 0;
271
- this.data.cropperFrameWidth = 0;
272
- this.data.cropperFrameLeft = 0;
273
- this.data.cropperFrameTop = 0;
274
- this.data.cropperImageHeight = 0;
275
- this.data.cropperImageWidth = 0;
276
- }
277
-
278
- const blockContent = this.block.holder.querySelector(
279
- '.ce-block__content',
280
- ) as HTMLElement;
281
- this.apply(blockContent);
282
- this.block.dispatchChange();
283
- }
284
-
285
- /**
286
- * Append class to block by tune data
287
- * @param {HTMLElement} blockContent - wrapper for block content
288
- * @public
289
- * @return {void}
290
- * */
291
- apply(blockContent: HTMLElement): void {
292
- if (this.data.floatLeft) {
293
- blockContent.classList.add(this.CSS.isFloatLeft);
294
- } else {
295
- blockContent.classList.remove(this.CSS.isFloatLeft);
296
- }
297
-
298
- if (this.data.floatRight) {
299
- blockContent.classList.add(this.CSS.isFloatRight);
300
- } else {
301
- blockContent.classList.remove(this.CSS.isFloatRight);
302
- }
303
-
304
- if (this.data.center) {
305
- blockContent.classList.add(this.CSS.isCenter);
306
- } else {
307
- blockContent.classList.remove(this.CSS.isCenter);
308
- }
309
-
310
- if (this.data.sizeSmall) {
311
- blockContent.classList.add(this.CSS.isSizeSmall);
312
- } else {
313
- blockContent.classList.remove(this.CSS.isSizeSmall);
314
- }
315
-
316
- if (this.data.sizeMiddle) {
317
- blockContent.classList.add(this.CSS.isSizeMiddle);
318
- } else {
319
- blockContent.classList.remove(this.CSS.isSizeMiddle);
320
- }
321
-
322
- if (this.data.sizeLarge) {
323
- blockContent.classList.add(this.CSS.isSizeLarge);
324
- } else {
325
- blockContent.classList.remove(this.CSS.isSizeLarge);
326
- }
327
-
328
- if (this.data.resize) {
329
- blockContent.classList.add(this.CSS.isResize);
330
-
331
- if (this.data.resizeSize > 0) {
332
- const cdxBlock = blockContent.getElementsByClassName(
333
- 'cdx-block',
334
- )[0] as HTMLElement;
335
- cdxBlock.style.width = this.data.resizeSize + 'px';
336
- }
337
-
338
- this.resize(blockContent);
339
- } else {
340
- blockContent.classList.remove(this.CSS.isResize);
341
- this.unresize(blockContent);
342
- }
343
-
344
- if (this.data.crop) {
345
- blockContent.classList.add(this.CSS.isCrop);
346
-
347
- this.crop(blockContent);
348
- if (this.data.cropperFrameHeight > 0 && this.data.cropperFrameWidth > 0) {
349
- this.applyCrop(blockContent);
350
- }
351
- } else {
352
- blockContent.classList.remove(this.CSS.isCrop);
353
- this.uncrop(blockContent);
354
- }
355
- }
356
-
357
- /**
358
- * Add crop handles to image
359
- * @param {HTMLElement} blockContent - wrapper for block content
360
- * @public
361
- * @return {void}
362
- */
363
- crop(blockContent: HTMLElement): void {
364
- //add append crop button to image-tool__image
365
- //If editor is readOnly, do not add crop button
366
- if (this.api.readOnly.isEnabled) return;
367
-
368
- const image = blockContent.getElementsByClassName(
369
- 'image-tool__image',
370
- )[0] as HTMLElement;
371
- const cropBtn = document.createElement('div');
372
- cropBtn.classList.add('crop-btn', 'btn-crop-action');
373
- cropBtn.innerHTML = this.api.i18n.t('Crop');
374
-
375
- cropBtn.addEventListener('click', () => {
376
- //remove crop button
377
- image.removeChild(cropBtn);
378
- this.appendCrop(blockContent);
379
- });
380
-
381
- image.appendChild(cropBtn);
382
- }
383
-
384
- appendCrop(blockContent: HTMLElement): void {
385
- if (this.api.readOnly.isEnabled) return;
386
-
387
- this.uncrop(blockContent);
388
- const cdxBlock = blockContent.getElementsByClassName(
389
- 'cdx-block',
390
- )[0] as HTMLElement;
391
- const image = cdxBlock.getElementsByTagName('img')[0] as HTMLImageElement;
392
- cdxBlock.classList.add('isCropping');
393
- this.data.cropperInterface = new Cropper(image);
394
-
395
- //append save crop button
396
- const cropSaveBtn = document.createElement('div');
397
- cropSaveBtn.classList.add('crop-save', 'btn-crop-action');
398
- cropSaveBtn.innerHTML = this.api.i18n.t('Apply');
399
-
400
- cropSaveBtn.addEventListener('click', () => {
401
- if (this.data.cropperInterface) {
402
- this.data.cropperFrameHeight =
403
- this.data.cropperInterface.getCropBoxData().height;
404
- this.data.cropperFrameWidth =
405
- this.data.cropperInterface.getCropBoxData().width;
406
- this.data.cropperFrameLeft =
407
- this.data.cropperInterface.getCanvasData().left -
408
- this.data.cropperInterface.getCropBoxData().left;
409
- this.data.cropperFrameTop =
410
- this.data.cropperInterface.getCanvasData().top -
411
- this.data.cropperInterface.getCropBoxData().top;
412
- this.data.cropperImageHeight =
413
- this.data.cropperInterface.getImageData().height;
414
- this.data.cropperImageWidth =
415
- this.data.cropperInterface.getImageData().width;
416
- }
417
- this.applyCrop(blockContent);
418
- });
419
-
420
- const imageToolImage = blockContent.getElementsByClassName(
421
- 'image-tool__image',
422
- )[0] as HTMLElement;
423
- imageToolImage.appendChild(cropSaveBtn);
424
-
425
- //add temporary style to block content so that it comes in front of every other block
426
- blockContent.classList.add('isCropping');
427
- }
428
-
429
- applyCrop(blockContent: HTMLElement): void {
430
- //apply data to image and remove cropper interface and save button, add crop button
431
- const blockEl = blockContent.getElementsByClassName(
432
- 'cdx-block',
433
- )[0] as HTMLElement;
434
- if (blockEl) {
435
- blockEl.style.minWidth = this.data.cropperFrameWidth + 'px';
436
- blockEl.style.maxWidth = this.data.cropperFrameWidth + 'px';
437
-
438
- const image = blockEl.getElementsByTagName('img')[0] as HTMLImageElement;
439
- image.style.width = this.data.cropperImageWidth + 'px';
440
- image.style.height = this.data.cropperImageHeight + 'px';
441
-
442
- const blockImg = blockContent.getElementsByClassName(
443
- 'image-tool__image',
444
- )[0] as HTMLElement;
445
- blockImg.style.width = this.data.cropperFrameWidth + 'px';
446
- blockImg.style.height = this.data.cropperFrameHeight + 'px';
447
-
448
- const imageEl = blockImg.getElementsByTagName(
449
- 'img',
450
- )[0] as HTMLImageElement;
451
- if (imageEl) {
452
- imageEl.style.left = this.data.cropperFrameLeft + 'px';
453
- imageEl.style.top = this.data.cropperFrameTop + 'px';
454
- imageEl.classList.add('isCropped');
455
- }
456
-
457
- blockEl.classList.remove('isCropping');
458
-
459
- const cropSaveBtn = blockContent.getElementsByClassName(
460
- 'btn-crop-action',
461
- )[0] as HTMLElement;
462
- if (cropSaveBtn) {
463
- blockImg.removeChild(cropSaveBtn);
464
- }
465
- }
466
-
467
- //remove cropper interface
468
- if (this.data.cropperInterface) {
469
- this.data.cropperInterface.destroy();
470
- this.data.cropperInterface = undefined;
471
- }
472
-
473
- //add crop button
474
- if (this.api.readOnly.isEnabled) return;
475
- const cropBtn = document.createElement('div');
476
- cropBtn.classList.add('crop-btn', 'btn-crop-action');
477
- cropBtn.innerHTML = this.api.i18n.t('Crop');
478
-
479
- const imageToolImage = blockContent.getElementsByClassName(
480
- 'image-tool__image',
481
- )[0] as HTMLElement;
482
- if (imageToolImage) {
483
- cropBtn.addEventListener('click', () => {
484
- //remove crop button
485
- imageToolImage.removeChild(cropBtn);
486
- this.appendCrop(blockContent);
487
- });
488
-
489
- imageToolImage.appendChild(cropBtn);
490
- }
491
-
492
- blockContent.classList.remove('isCropping');
493
- this.block.dispatchChange();
494
- }
495
-
496
- uncrop(blockContent: HTMLElement): void {
497
- if (this.api.readOnly.isEnabled) return;
498
-
499
- const imageEl = blockContent.getElementsByClassName(
500
- 'image-tool__image',
501
- )[0] as HTMLElement;
502
-
503
- //remove crop and save button
504
- const cropSaveBtn = blockContent.getElementsByClassName(
505
- 'btn-crop-action',
506
- )[0] as HTMLElement;
507
- if (cropSaveBtn && imageEl) {
508
- imageEl.removeChild(cropSaveBtn);
509
- }
510
-
511
- //remove crop button
512
- const cropBtn = blockContent.getElementsByClassName(
513
- 'btn-crop-action',
514
- )[0] as HTMLElement;
515
- if (cropBtn && imageEl) {
516
- imageEl.removeChild(cropBtn);
517
- }
518
-
519
- //remove isCropped class
520
- const blockEl = blockContent.getElementsByClassName(
521
- 'cdx-block',
522
- )[0] as HTMLElement;
523
- if (blockEl) {
524
- const image = blockEl.getElementsByTagName('img')[0] as HTMLImageElement;
525
- if (image) image.classList.remove('isCropped');
526
-
527
- //remove isCropping class
528
- blockEl.classList.remove('isCropping');
529
-
530
- //remove min and max width
531
- blockEl.style.minWidth = '';
532
- blockEl.style.maxWidth = '';
533
- }
534
-
535
- if (imageEl) {
536
- //remove image width and height
537
- imageEl.style.width = '';
538
- imageEl.style.height = '';
539
-
540
- //remove image left and top
541
- const image = imageEl.getElementsByTagName('img')[0] as HTMLImageElement;
542
- if (image) {
543
- image.style.left = '';
544
- image.style.top = '';
545
-
546
- //remove image width and height
547
- image.style.width = '';
548
- image.style.height = '';
549
- }
550
- }
551
-
552
- blockContent.classList.remove('isCropping');
553
-
554
- //remove cropper interface
555
- if (this.data.cropperInterface) {
556
- this.data.cropperInterface.destroy();
557
- this.data.cropperInterface = undefined;
558
- }
559
-
560
- //remove crop data
561
- this.data.cropperFrameHeight = 0;
562
- this.data.cropperFrameWidth = 0;
563
- this.data.cropperFrameLeft = 0;
564
- this.data.cropperFrameTop = 0;
565
- this.data.cropperImageHeight = 0;
566
- this.data.cropperImageWidth = 0;
567
- }
568
-
569
- /**
570
- * Add resize handles to block
571
- * @param {HTMLElement} blockContent - wrapper for block content
572
- * @public
573
- * @return {void}
574
- * */
575
- resize(blockContent: HTMLElement): void {
576
- if (this.api.readOnly.isEnabled) return;
577
- const resizable = document.createElement('div');
578
- resizable.classList.add('resizable');
579
-
580
- const resizers = document.createElement('div');
581
- resizers.classList.add('resizers');
582
-
583
- const resizerTopRight = document.createElement('div');
584
- resizerTopRight.classList.add('resizer', 'top-right');
585
- resizerTopRight.addEventListener('mousedown', e => {
586
- this.resizeClick(
587
- blockContent.getElementsByClassName('cdx-block')[0] as HTMLElement,
588
- "right",
589
- e,
590
- );
591
- });
592
-
593
- const resizerBottomRight = document.createElement('div');
594
- resizerBottomRight.classList.add('resizer', 'bottom-right');
595
- resizerBottomRight.addEventListener('mousedown', e => {
596
- this.resizeClick(
597
- blockContent.getElementsByClassName('cdx-block')[0] as HTMLElement,
598
- "right",
599
- e,
600
- );
601
- });
602
-
603
- const resizerTopLeft = document.createElement('div');
604
- resizerTopLeft.classList.add('resizer', 'top-left');
605
- resizerTopLeft.addEventListener('mousedown', e => {
606
- this.resizeClick(
607
- blockContent.getElementsByClassName('cdx-block')[0] as HTMLElement,
608
- "left",
609
- e,
610
- );
611
- });
612
- const resizerBottomLeft = document.createElement('div');
613
- resizerBottomLeft.classList.add('resizer', 'bottom-left');
614
- resizerBottomLeft.addEventListener('mousedown', e => {
615
- this.resizeClick(
616
- blockContent.getElementsByClassName('cdx-block')[0] as HTMLElement,
617
- "left",
618
- e,
619
- );
620
- });
621
-
622
-
623
- resizers.appendChild(resizerTopRight);
624
- resizers.appendChild(resizerBottomRight);
625
- resizers.appendChild(resizerTopLeft);
626
- resizers.appendChild(resizerBottomLeft);
627
- resizable.appendChild(resizers);
628
- blockContent.getElementsByClassName('cdx-block')[0].appendChild(resizable);
629
- }
630
-
631
- /**
632
- * click event to resize handles
633
- * preserve aspect ratio
634
- * prevent block from moving when dragging resize handles
635
- * max size = 100%
636
- * min size = 50px
637
- * @param {HTMLElement} blockContent - wrapper for block content
638
- * @param {HTMLElement} handle - resize handle
639
- * @param {MouseEvent} e - mouse event
640
- * @public
641
- * @return {void}
642
- * */
643
- resizeClick(blockContent: HTMLElement, handleDirection: String, e: MouseEvent): void {
644
- const maxWidth =
645
- document.getElementsByClassName('ce-block__content')[0].clientWidth;
646
- let startX = 0;
647
- let startWidth = 0;
648
-
649
- const mouseMoveHandler = (e: MouseEvent) => {
650
- const dx = e.clientX - startX;
651
- let newWidth = startWidth;
652
- if (handleDirection === "right") {
653
- newWidth += dx;
654
- }
655
- if (handleDirection === "left") {
656
- newWidth -= dx;
657
- }
658
-
659
- if (newWidth > 50 && newWidth < maxWidth) {
660
- (
661
- blockContent as HTMLElement & { style: CSSStyleDeclaration }
662
- ).style.width = newWidth + 'px';
663
- }
664
- };
665
-
666
- const mouseUpHandler = () => {
667
- const blockWidth = parseInt(
668
- window.getComputedStyle(blockContent).width,
669
- 10,
670
- );
671
-
672
- if (blockWidth > 0) {
673
- this.data.resizeSize = blockWidth;
674
- }
675
-
676
- document.removeEventListener('mousemove', mouseMoveHandler);
677
- document.removeEventListener('mouseup', mouseUpHandler);
678
-
679
- this.block.dispatchChange();
680
- };
681
-
682
- document.addEventListener('mousemove', mouseMoveHandler);
683
- document.addEventListener('mouseup', mouseUpHandler);
684
-
685
- startX = e.clientX;
686
- startWidth = parseInt(window.getComputedStyle(blockContent).width, 10);
687
- }
688
-
689
- /**
690
- * Remove resize handles from block
691
- * @param {HTMLElement} blockContent - wrapper for block content
692
- * @public
693
- * @return {void}
694
- */
695
- unresize(blockContent: HTMLElement): void {
696
- const unresizable = blockContent.getElementsByClassName(
697
- 'resizable',
698
- )[0] as HTMLElement;
699
- if (unresizable) {
700
- blockContent
701
- .getElementsByClassName('cdx-block')[0]
702
- .removeChild(unresizable);
703
- }
704
-
705
- const block: HTMLElement = blockContent.getElementsByClassName(
706
- 'cdx-block',
707
- )[0] as HTMLElement;
708
- block.style.width = 'auto';
709
- }
710
-
711
- /**
712
- * Remove tunes from block wrapper
713
- * @param {HTMLElement} blockContent - wrapper for block content
714
- * @public
715
- * @return {HTMLElement}
716
- */
717
- unwrap(blockContent: HTMLElement): HTMLElement {
718
- //remove tunes from block
719
- this.buttons.forEach(button => {
720
- button.classList.remove(this.CSS.buttonActive);
721
- });
722
-
723
- //remove isFloatLeft class
724
- blockContent.classList.remove(this.CSS.isFloatLeft);
725
-
726
- //remove isFloatRight class
727
- blockContent.classList.remove(this.CSS.isFloatRight);
728
-
729
- //remove isCenter class
730
- blockContent.classList.remove(this.CSS.isCenter);
731
-
732
- //remove isSizeSmall class
733
- blockContent.classList.remove(this.CSS.isSizeSmall);
734
-
735
- //remove isSizeMiddle class
736
- blockContent.classList.remove(this.CSS.isSizeMiddle);
737
-
738
- //remove isSizeLarge class
739
- blockContent.classList.remove(this.CSS.isSizeLarge);
740
-
741
- //remove isResize class
742
- blockContent.classList.remove(this.CSS.isResize);
743
-
744
- //remove isCrop class
745
- blockContent.classList.remove(this.CSS.isCrop);
746
-
747
- //remove isCropped class
748
- const cdxBlock = blockContent.getElementsByClassName(
749
- 'cdx-block',
750
- )[0] as HTMLElement;
751
- const img = cdxBlock.getElementsByTagName('img')[0] as HTMLImageElement;
752
- img.classList.remove('isCropped');
753
-
754
- //remove isCropping class
755
- cdxBlock.classList.remove('isCropping');
756
-
757
- //remove min and max width
758
- cdxBlock.style.minWidth = '';
759
- cdxBlock.style.maxWidth = '';
760
-
761
- //remove image width and height
762
- const imageToolImage = blockContent.getElementsByClassName(
763
- 'image-tool__image',
764
- )[0] as HTMLElement;
765
- imageToolImage.style.width = '';
766
- imageToolImage.style.height = '';
767
-
768
- //remove image left and top
769
- const image = imageToolImage.getElementsByTagName(
770
- 'img',
771
- )[0] as HTMLImageElement;
772
- image.style.left = '';
773
- image.style.top = '';
774
-
775
- //remove image width and height
776
- image.style.width = '';
777
- image.style.height = '';
778
-
779
- //remove resize handles
780
- this.unresize(blockContent);
781
-
782
- //remove crop handles
783
- this.uncrop(blockContent);
784
-
785
- //remove cropper interface
786
- if (this.data.cropperInterface) {
787
- this.data.cropperInterface.destroy();
788
- this.data.cropperInterface = undefined;
789
- }
790
-
791
- //remove crop data
792
- this.data.cropperFrameHeight = 0;
793
- this.data.cropperFrameWidth = 0;
794
- this.data.cropperFrameLeft = 0;
795
- this.data.cropperFrameTop = 0;
796
- this.data.cropperImageHeight = 0;
797
- this.data.cropperImageWidth = 0;
798
-
799
- return blockContent;
800
- }
801
-
802
- /**
803
- * Add tune to block data
804
- * @private
805
- * @return {ImageToolTuneData}
806
- * */
807
- save(): ImageToolTuneData {
808
- return this.data;
809
- }
810
-
811
- /**
812
- * Append tunes to block wrapper
813
- * @param {HTMLElement} blockContent - wrapper for block content
814
- * @public
815
- * @return {HTMLElement}
816
- * */
817
- wrap(blockContent: HTMLElement): HTMLElement {
818
- //createview if not exists
819
- if (!this.wrapper) {
820
- this.wrapper = this.createView();
821
- }
822
-
823
- this.apply(blockContent);
824
- return blockContent;
825
- }
826
-
827
- private tuneNameToI18nKey(tuneName: string): string {
828
- const translation: Record<string, string> = {
829
- crop: 'Crop',
830
- resize: 'Resize',
831
- };
832
- return translation[tuneName];
833
- }
834
-
835
- /**
836
- * Creates a view for tunes
837
- * @return {HTMLElement}
838
- * @private
839
- * */
840
- createView(): HTMLElement {
841
- this.buttons = this.settings.map(tune => {
842
- const el = document.createElement('div');
843
- const buttonIco = document.createElement('span');
844
- const buttonTxt = document.createElement('span');
845
- el.classList.add(this.CSS.button);
846
- buttonTxt.style.fontSize = '8px';
847
- buttonIco.innerHTML = tune.icon;
848
- buttonTxt.innerHTML = tune.label;
849
- el.appendChild(buttonIco);
850
- el.appendChild(buttonTxt);
851
- el.dataset.tune = tune.name;
852
- el.title = tune.label;
853
-
854
- el.addEventListener('click', e => this.tuneClicked(e, el));
855
- this.api.tooltip.onHover(
856
- el,
857
- this.api.i18n.t(this.tuneNameToI18nKey(tune.name)),
858
- );
859
- return el;
860
- });
861
- const wrapper = document.createElement('div');
862
- this.buttons.forEach(button => {
863
- wrapper.appendChild(button);
864
- });
865
- wrapper.classList.add(this.CSS.wrapper);
866
- return wrapper;
867
- }
868
-
869
- /**
870
- * Checks if tune is active
871
- * @param {string} tune - tune name
872
- * @return {boolean}
873
- * @private
874
- * */
875
- isTuneActive(tune: string): boolean {
876
- return !!this.data[tune as keyof ImageToolTuneData];
877
- }
878
-
879
- /**
880
- * Makes buttons with tunes
881
- * @return {HTMLElement}
882
- * @public
883
- * */
884
- render(): HTMLElement {
885
- //when editor is ready
886
- this.buttons.forEach(button => {
887
- const tuneName = button.dataset.tune || '';
888
- button.classList.toggle(
889
- this.CSS.buttonActive,
890
- this.isTuneActive(tuneName),
891
- );
892
- });
893
-
894
- return this.view;
895
- }
896
-
897
- /**
898
- * Destroys the plugin
899
- * @public
900
- * @return {void}
901
- * */
902
- destroy(): void {
903
- this.wrapper = undefined;
904
- this.buttons = [];
905
- }
906
-
907
- /**
908
- * Toggle tune
909
- * @param {string} tuneName - tune name
910
- * @private
911
- * @return {void}
912
- * */
913
- _toggleTune(tuneName: string): void {
914
- this.setTune(tuneName);
915
- }
916
- }