goodteditor-ui 1.0.26 → 1.0.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 (116) hide show
  1. package/.eslintrc.js +7 -7
  2. package/.prettierrc +14 -14
  3. package/README.md +35 -35
  4. package/babel.config.js +5 -5
  5. package/index.js +53 -53
  6. package/jsconfig.json +13 -13
  7. package/package.json +67 -67
  8. package/src/App.vue +36 -36
  9. package/src/components/ui/Avatar.md +68 -68
  10. package/src/components/ui/Avatar.vue +180 -180
  11. package/src/components/ui/Badge.md +20 -20
  12. package/src/components/ui/Badge.vue +75 -75
  13. package/src/components/ui/Collapse.md +90 -90
  14. package/src/components/ui/Collapse.vue +86 -86
  15. package/src/components/ui/ColorPicker/Alpha.vue +114 -114
  16. package/src/components/ui/ColorPicker/Colors.vue +117 -117
  17. package/src/components/ui/ColorPicker/Hue.vue +113 -113
  18. package/src/components/ui/ColorPicker/Preview.vue +55 -55
  19. package/src/components/ui/ColorPicker/Saturation.vue +123 -123
  20. package/src/components/ui/ColorPicker/mixin.js +105 -105
  21. package/src/components/ui/ColorPicker.md +17 -17
  22. package/src/components/ui/ColorPicker.vue +314 -314
  23. package/src/components/ui/Datalist.md +41 -41
  24. package/src/components/ui/Datalist.vue +164 -164
  25. package/src/components/ui/DatePicker.md +168 -168
  26. package/src/components/ui/DatePicker.vue +527 -527
  27. package/src/components/ui/FileSelector.md +105 -105
  28. package/src/components/ui/FileSelector.vue +82 -82
  29. package/src/components/ui/Grid.md +130 -130
  30. package/src/components/ui/Grid.vue +92 -92
  31. package/src/components/ui/Image.md +59 -59
  32. package/src/components/ui/Image.vue +57 -57
  33. package/src/components/ui/InputAutocomplete.md +115 -115
  34. package/src/components/ui/InputAutocomplete.vue +374 -349
  35. package/src/components/ui/InputColorPicker.md +51 -51
  36. package/src/components/ui/InputColorPicker.vue +151 -151
  37. package/src/components/ui/InputDatePicker.md +121 -121
  38. package/src/components/ui/InputDatePicker.vue +326 -326
  39. package/src/components/ui/InputTags.md +51 -51
  40. package/src/components/ui/InputTags.vue +184 -184
  41. package/src/components/ui/InputTimePicker.md +25 -25
  42. package/src/components/ui/InputTimePicker.vue +253 -253
  43. package/src/components/ui/InputUnits.md +20 -20
  44. package/src/components/ui/InputUnits.vue +257 -257
  45. package/src/components/ui/Lazy.md +37 -37
  46. package/src/components/ui/Lazy.vue +92 -92
  47. package/src/components/ui/Pagination.md +74 -74
  48. package/src/components/ui/Pagination.vue +138 -138
  49. package/src/components/ui/Paginator.md +34 -34
  50. package/src/components/ui/Paginator.vue +83 -83
  51. package/src/components/ui/Popover.md +34 -34
  52. package/src/components/ui/Popover.vue +274 -274
  53. package/src/components/ui/Popup.md +59 -59
  54. package/src/components/ui/Popup.vue +150 -150
  55. package/src/components/ui/ResponsiveContainer.md +58 -58
  56. package/src/components/ui/ResponsiveContainer.vue +99 -99
  57. package/src/components/ui/Select.md +187 -187
  58. package/src/components/ui/Select.vue +421 -421
  59. package/src/components/ui/TimePicker.md +50 -50
  60. package/src/components/ui/TimePicker.vue +252 -252
  61. package/src/components/ui/Tooltip.md +54 -54
  62. package/src/components/ui/Tooltip.vue +113 -113
  63. package/src/components/ui/WysiwygEditor/WysiwygEditor.d.ts +128 -128
  64. package/src/components/ui/WysiwygEditor/constants.js +273 -273
  65. package/src/components/ui/WysiwygEditor/extensions/blockquote.js +15 -15
  66. package/src/components/ui/WysiwygEditor/extensions/bold.js +15 -15
  67. package/src/components/ui/WysiwygEditor/extensions/bullet-list.js +15 -15
  68. package/src/components/ui/WysiwygEditor/extensions/code-block.js +13 -13
  69. package/src/components/ui/WysiwygEditor/extensions/code.js +13 -13
  70. package/src/components/ui/WysiwygEditor/extensions/font-size.js +34 -34
  71. package/src/components/ui/WysiwygEditor/extensions/formatting.js +14 -14
  72. package/src/components/ui/WysiwygEditor/extensions/heading.js +13 -13
  73. package/src/components/ui/WysiwygEditor/extensions/horizontal-rule.js +15 -15
  74. package/src/components/ui/WysiwygEditor/extensions/image.js +37 -33
  75. package/src/components/ui/WysiwygEditor/extensions/index.d.ts +32 -32
  76. package/src/components/ui/WysiwygEditor/extensions/index.js +32 -32
  77. package/src/components/ui/WysiwygEditor/extensions/italic.js +15 -15
  78. package/src/components/ui/WysiwygEditor/extensions/link.js +16 -16
  79. package/src/components/ui/WysiwygEditor/extensions/list-item.js +15 -15
  80. package/src/components/ui/WysiwygEditor/extensions/ordered-list.js +15 -15
  81. package/src/components/ui/WysiwygEditor/extensions/paragraph.js +23 -23
  82. package/src/components/ui/WysiwygEditor/extensions/strike.js +15 -15
  83. package/src/components/ui/WysiwygEditor/extensions/table-cell.js +13 -13
  84. package/src/components/ui/WysiwygEditor/extensions/table-header.js +15 -15
  85. package/src/components/ui/WysiwygEditor/extensions/table-row.js +15 -15
  86. package/src/components/ui/WysiwygEditor/extensions/table.js +29 -29
  87. package/src/components/ui/WysiwygEditor/extensions/text-align.js +6 -6
  88. package/src/components/ui/WysiwygEditor/extensions/text-style.js +12 -12
  89. package/src/components/ui/WysiwygEditor/extensions/underline.js +15 -15
  90. package/src/components/ui/WysiwygEditor/index.d.ts +4 -4
  91. package/src/components/ui/WysiwygEditor/index.js +4 -4
  92. package/src/components/ui/WysiwygEditor/renders/Button.vue +28 -28
  93. package/src/components/ui/WysiwygEditor/renders/ColorPicker.vue +41 -41
  94. package/src/components/ui/WysiwygEditor/renders/Image.vue +200 -162
  95. package/src/components/ui/WysiwygEditor/renders/InputAuto.vue +34 -34
  96. package/src/components/ui/WysiwygEditor/renders/InputUnits.vue +37 -37
  97. package/src/components/ui/WysiwygEditor/renders/Link.vue +82 -82
  98. package/src/components/ui/WysiwygEditor/renders/Select.vue +47 -47
  99. package/src/components/ui/WysiwygEditor/renders/ToolbarPopover.vue +49 -49
  100. package/src/components/ui/WysiwygEditor/renders/components/Popover.vue +15 -0
  101. package/src/components/ui/WysiwygEditor/renders/components/WithPopover.vue +35 -35
  102. package/src/components/ui/WysiwygEditor/renders/index.d.ts +8 -8
  103. package/src/components/ui/WysiwygEditor/renders/index.js +8 -8
  104. package/src/components/ui/WysiwygEditor/renders/mixins/RenderMixin.js +39 -39
  105. package/src/components/ui/WysiwygEditor/renders/mixins/index.js +1 -1
  106. package/src/components/ui/WysiwygEditor/tools-and-commands.js +709 -702
  107. package/src/components/ui/WysiwygEditor/utils.js +72 -72
  108. package/src/components/ui/WysiwygEditor.md +18 -18
  109. package/src/components/ui/WysiwygEditor.vue +266 -266
  110. package/src/components/ui/utils/FormComponent.js +107 -107
  111. package/src/components/ui/utils/Helpers.js +84 -84
  112. package/src/components/ui/utils/WithPopover.js +81 -81
  113. package/src/main.js +8 -8
  114. package/styleguide.config.js +37 -37
  115. package/vue.config.js +8 -8
  116. package/dist/js.png +0 -0
@@ -1,702 +1,709 @@
1
- import {
2
- NodeType,
3
- MarkType,
4
- CommandType,
5
- ToolType,
6
- createButtonTool,
7
- createColorPickerTool,
8
- createCommand,
9
- createInputUnitsTool,
10
- createSelectTool,
11
- createToolbarPopoverTool,
12
- createInputAutoTool,
13
- createLinkTool,
14
- createImageTool,
15
- } from './constants';
16
-
17
- export const CommandMap = {
18
- [CommandType.PARAGRAPH]: createCommand({
19
- name: CommandType.PARAGRAPH,
20
- title: 'Абзац',
21
- exec() {
22
- this.editor
23
- .chain()
24
- .focus()
25
- .setParagraph()
26
- .setParagraphClass('p')
27
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
28
- .run();
29
- },
30
- isActive() {
31
- return this.editor.isActive(NodeType.PARAGRAPH, { class: 'p' });
32
- }
33
- }),
34
- [CommandType.HEADING_1]: createCommand({
35
- name: CommandType.HEADING_1,
36
- title: 'Заголовок 1 (h1)',
37
- exec() {
38
- this.editor
39
- .chain()
40
- .focus()
41
- .setHeading({ level: 1 })
42
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
43
- .run();
44
- },
45
- isActive() {
46
- return this.editor.isActive(NodeType.HEADING, { level: 1 });
47
- }
48
- }),
49
- [CommandType.HEADING_2]: createCommand({
50
- name: CommandType.HEADING_2,
51
- title: 'Заголовок 2 (h2)',
52
- exec() {
53
- this.editor
54
- .chain()
55
- .focus()
56
- .setHeading({ level: 2 })
57
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
58
- .run();
59
- },
60
- isActive() {
61
- return this.editor.isActive(NodeType.HEADING, { level: 2 });
62
- }
63
- }),
64
- [CommandType.HEADING_3]: createCommand({
65
- name: CommandType.HEADING_3,
66
- title: 'Заголовок 3 (h3)',
67
- exec() {
68
- this.editor
69
- .chain()
70
- .focus()
71
- .setHeading({ level: 3 })
72
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
73
- .run();
74
- },
75
- isActive() {
76
- return this.editor.isActive(NodeType.HEADING, { level: 3 });
77
- }
78
- }),
79
- [CommandType.HEADING_4]: createCommand({
80
- name: CommandType.HEADING_4,
81
- title: 'Заголовок 4 (h4)',
82
- exec() {
83
- this.editor
84
- .chain()
85
- .focus()
86
- .setHeading({ level: 4 })
87
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
88
- .run();
89
- },
90
- isActive() {
91
- return this.editor.isActive(NodeType.HEADING, { level: 4 });
92
- }
93
- }),
94
- [CommandType.TEXT_SMALL]: createCommand({
95
- name: CommandType.TEXT_SMALL,
96
- title: 'Small',
97
- exec() {
98
- this.editor
99
- .chain()
100
- .focus()
101
- .setParagraph()
102
- .setParagraphClass('text-small')
103
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
104
- .run();
105
- },
106
- isActive() {
107
- return this.editor.isActive(NodeType.PARAGRAPH, { class: 'text-small' });
108
- }
109
- }),
110
- [CommandType.TEXT_XSMALL]: createCommand({
111
- name: CommandType.TEXT_XSMALL,
112
- title: 'Xsmall',
113
- exec() {
114
- this.editor
115
- .chain()
116
- .focus()
117
- .setParagraph()
118
- .setParagraphClass('text-xsmall')
119
- .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
120
- .run();
121
- },
122
- isActive() {
123
- return this.editor.isActive(NodeType.PARAGRAPH, { class: 'text-xsmall' });
124
- }
125
- }),
126
- [CommandType.CODE_BLOCK]: createCommand({
127
- name: CommandType.CODE_BLOCK,
128
- title: 'Код',
129
- exec() {
130
- this.editor
131
- .chain()
132
- .focus()
133
- .setCodeBlock()
134
- .run();
135
- },
136
- isActive() {
137
- return this.editor.isActive(NodeType.CODE_BLOCK);
138
- }
139
- }),
140
- [CommandType.SINK_LIST_ITEM]: createCommand({
141
- name: CommandType.SINK_LIST_ITEM,
142
- title: 'Опустить элемент списка',
143
- exec() {
144
- this.editor
145
- .chain()
146
- .focus()
147
- .sinkListItem(NodeType.LIST_ITEM)
148
- .run();
149
- },
150
- isEnabled() {
151
- return this.editor.can().sinkListItem(NodeType.LIST_ITEM);
152
- }
153
- }),
154
- [CommandType.LIFT_LIST_ITEM]: createCommand({
155
- name: CommandType.LIFT_LIST_ITEM,
156
- title: 'Поднять элемент списка',
157
- exec() {
158
- this.editor.chain().focus().liftListItem(NodeType.LIST_ITEM).run();
159
- },
160
- isEnabled() {
161
- return this.editor.can().liftListItem(NodeType.LIST_ITEM);
162
- }
163
- })
164
- };
165
-
166
- export const TableOptionsMap = {
167
- [ToolType.INSERT_TABLE]: createButtonTool({
168
- name: ToolType.INSERT_TABLE,
169
- icon: 'table',
170
- title: 'Вставить таблицу',
171
- exec() {
172
- this.editor
173
- .chain()
174
- .focus()
175
- .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
176
- .run();
177
- },
178
- isEnabled() {
179
- return this.editor.can().insertTable();
180
- }
181
- }),
182
- [ToolType.DELETE_TABLE]: createButtonTool({
183
- name: ToolType.DELETE_TABLE,
184
- icon: 'table-remove',
185
- title: 'Удалить таблицу',
186
- exec() {
187
- this.editor.chain().focus().deleteTable().run();
188
- },
189
- isEnabled() {
190
- return this.editor.can().deleteTable();
191
- }
192
- }),
193
- [ToolType.ADD_COLUMN_BEFORE]: createButtonTool({
194
- name: ToolType.ADD_COLUMN_BEFORE,
195
- icon: 'table-column-plus-before',
196
- title: 'Добавить колонку перед',
197
- exec() {
198
- this.editor.chain().focus().addColumnBefore().run();
199
- },
200
- isEnabled() {
201
- return this.editor.can().addColumnBefore();
202
- }
203
- }),
204
- [ToolType.ADD_COLUMN_AFTER]: createButtonTool({
205
- name: ToolType.ADD_COLUMN_AFTER,
206
- icon: 'table-column-plus-after',
207
- title: 'Добавить колонку после',
208
- exec() {
209
- this.editor.chain().focus().addColumnAfter().run();
210
- },
211
- isEnabled() {
212
- return this.editor.can().addColumnAfter();
213
- }
214
- }),
215
- [ToolType.DELETE_COLUMN]: createButtonTool({
216
- name: ToolType.DELETE_COLUMN,
217
- icon: 'table-column-remove',
218
- title: 'Удалить колонку',
219
- exec() {
220
- this.editor.chain().focus().deleteColumn().run();
221
- },
222
- isEnabled() {
223
- return this.editor.can().deleteColumn();
224
- }
225
- }),
226
- [ToolType.ADD_ROW_BEFORE]: createButtonTool({
227
- name: ToolType.ADD_ROW_BEFORE,
228
- icon: 'table-row-plus-before',
229
- title: 'Добавить строку перед',
230
- exec() {
231
- this.editor.chain().focus().addRowBefore().run();
232
- },
233
- isEnabled() {
234
- return this.editor.can().addRowBefore();
235
- }
236
- }),
237
- [ToolType.ADD_ROW_AFTER]: createButtonTool({
238
- name: ToolType.ADD_ROW_AFTER,
239
- icon: 'table-row-plus-after',
240
- title: 'Добавить строку после',
241
- exec() {
242
- this.editor.chain().focus().addRowAfter().run();
243
- },
244
- isEnabled() {
245
- return this.editor.can().addRowAfter();
246
- }
247
- }),
248
- [ToolType.DELETE_ROW]: createButtonTool({
249
- name: ToolType.DELETE_ROW,
250
- icon: 'table-row-remove',
251
- title: 'Удалить строку',
252
- exec() {
253
- this.editor.chain().focus().deleteRow().run();
254
- },
255
- isEnabled() {
256
- return this.editor.can().deleteRow();
257
- }
258
- }),
259
- [ToolType.MERGE_CELLS]: createButtonTool({
260
- name: ToolType.MERGE_CELLS,
261
- icon: 'table-merge-cells',
262
- title: 'Объединить ячейки',
263
- exec() {
264
- this.editor.chain().focus().mergeCells().run();
265
- },
266
- isEnabled() {
267
- return this.editor.can().mergeCells();
268
- }
269
- }),
270
- [ToolType.SPLIT_CELL]: createButtonTool({
271
- name: ToolType.SPLIT_CELL,
272
- icon: 'table-split-cell',
273
- title: 'Разделить ячейки',
274
- exec() {
275
- this.editor.chain().focus().splitCell().run();
276
- },
277
- isEnabled() {
278
- return this.editor.can().splitCell();
279
- }
280
- }),
281
- [ToolType.TOGGLE_HEADER_ROW]: createButtonTool({
282
- name: ToolType.TOGGLE_HEADER_ROW,
283
- icon: 'table-row-height',
284
- title: 'Переключить строку заголовка',
285
- exec() {
286
- this.editor.chain().focus().toggleHeaderRow().run();
287
- },
288
- isEnabled() {
289
- return this.editor.can().toggleHeaderRow();
290
- }
291
- }),
292
- [ToolType.TOGGLE_HEADER_COLUMN]: createButtonTool({
293
- name: ToolType.TOGGLE_HEADER_COLUMN,
294
- icon: 'table-column-width',
295
- title: 'Переключить колонку заголовка',
296
- exec() {
297
- this.editor.chain().focus().toggleHeaderColumn().run();
298
- },
299
- isEnabled() {
300
- return this.editor.can().toggleHeaderColumn();
301
- }
302
- }),
303
- [ToolType.ALIGN_V_TOP]: createButtonTool({
304
- name: ToolType.ALIGN_V_TOP,
305
- icon: 'align-vertical-top',
306
- title: 'Выровнять по верхнему краю',
307
- exec() {
308
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
309
- this.editor.chain().focus().toggleTableAlignment('table-vtop', classNames).run();
310
- },
311
- isEnabled() {
312
- return this.editor.isActive(NodeType.TABLE);
313
- },
314
- isActive() {
315
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
316
- return classNames?.includes('table-vtop') ?? false;
317
- }
318
- }),
319
- [ToolType.ALIGN_V_MID]: createButtonTool({
320
- name: ToolType.ALIGN_V_MID,
321
- icon: 'align-vertical-center',
322
- title: 'Выровнять по центру',
323
- exec() {
324
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
325
- this.editor.chain().focus().toggleTableAlignment('table-vmid', classNames).run();
326
- },
327
- isEnabled() {
328
- return this.editor.isActive(NodeType.TABLE);
329
- },
330
- isActive() {
331
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
332
- return classNames?.includes('table-vmid') ?? false;
333
- }
334
- }),
335
- [ToolType.ALIGN_V_BOT]: createButtonTool({
336
- name: ToolType.ALIGN_V_BOT,
337
- icon: 'align-vertical-bottom',
338
- title: 'Выровнять по нижнему краю',
339
- exec() {
340
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
341
- this.editor.chain().focus().toggleTableAlignment('table-vbot', classNames).run();
342
- },
343
- isEnabled() {
344
- return this.editor.isActive(NodeType.TABLE);
345
- },
346
- isActive() {
347
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
348
- return classNames?.includes('table-vbot') ?? false;
349
- }
350
- }),
351
- [ToolType.TOGGLE_BORDERS]: createButtonTool({
352
- name: ToolType.TOGGLE_BORDERS,
353
- icon: 'border-all',
354
- title: 'Границы',
355
- exec() {
356
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
357
- this.editor.chain().focus().toggleTableClass('table-borders', classNames).run();
358
- },
359
- isEnabled() {
360
- return this.editor.isActive(NodeType.TABLE);
361
- },
362
- isActive() {
363
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
364
- return classNames?.includes('table-borders') ?? false;
365
- }
366
- }),
367
- [ToolType.TOGGLE_ZEBRA]: createButtonTool({
368
- name: ToolType.TOGGLE_ZEBRA,
369
- icon: 'view-stream',
370
- title: 'Стиль "зебра"',
371
- exec() {
372
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
373
- this.editor.chain().focus().toggleTableClass('table-zebra', classNames).run();
374
- },
375
- isEnabled() {
376
- return this.editor.isActive(NodeType.TABLE);
377
- },
378
- isActive() {
379
- const classNames = this.editor.getAttributes(NodeType.TABLE).class;
380
- return classNames?.includes('table-zebra') ?? false;
381
- }
382
- })
383
- };
384
-
385
- export const ToolsMap = {
386
- [ToolType.UNDO]: createButtonTool({
387
- name: ToolType.UNDO,
388
- icon: 'undo-variant',
389
- title: 'Назад',
390
- exec() {
391
- this.editor.commands.undo();
392
- },
393
- isEnabled() {
394
- return this.editor.can().undo();
395
- }
396
- }),
397
- [ToolType.REDO]: createButtonTool({
398
- name: ToolType.REDO,
399
- icon: 'redo-variant',
400
- title: 'Вперед',
401
- exec() {
402
- this.editor.commands.redo();
403
- },
404
- isEnabled() {
405
- return this.editor.can().redo();
406
- }
407
- }),
408
- [ToolType.SAVE]: createButtonTool({
409
- name: ToolType.SAVE,
410
- icon: 'content-save',
411
- title: 'Сохранить',
412
- exec() {
413
- this.onChange();
414
- }
415
- }),
416
- [ToolType.PARAGRAPH_STYLE]: createSelectTool({
417
- name: ToolType.PARAGRAPH_STYLE,
418
- title: 'Стиль параграфа',
419
- exec(command) {
420
- if (command.name in CommandMap && command.isEnabled()) {
421
- command.exec();
422
- }
423
- },
424
- getValue(options) {
425
- return options.find(({ value }) => value.isActive()) ?? null;
426
- },
427
- options: [
428
- CommandMap[CommandType.PARAGRAPH],
429
- CommandMap[CommandType.HEADING_1],
430
- CommandMap[CommandType.HEADING_2],
431
- CommandMap[CommandType.HEADING_3],
432
- CommandMap[CommandType.HEADING_4],
433
- CommandMap[CommandType.TEXT_SMALL],
434
- CommandMap[CommandType.TEXT_XSMALL],
435
- CommandMap[CommandType.CODE_BLOCK]
436
- ]
437
- }),
438
- [ToolType.FONT_SIZE]: createInputUnitsTool({
439
- name: ToolType.FONT_SIZE,
440
- title: 'Размер шрифта',
441
- exec(value) {
442
- this.editor.commands.setFontSize(value);
443
- },
444
- isEnabled() {
445
- const { editor } = this;
446
-
447
- return (
448
- editor.isActive(NodeType.HEADING) ||
449
- editor.isActive(NodeType.PARAGRAPH, { class: 'text-small' }) ||
450
- editor.isActive(NodeType.PARAGRAPH, { class: 'text-xsmall' })
451
- ) === false;
452
- },
453
- getValue() {
454
- return this.editor.getAttributes(MarkType.TEXT_STYLE).fontSize;
455
- },
456
- units: ["rem", "em", "%", "px", "vh", "vw"]
457
- }),
458
- [ToolType.TEXT_COLOR]: createColorPickerTool({
459
- name: ToolType.TEXT_COLOR,
460
- icon: 'format-color-fill',
461
- title: 'Цвет',
462
- exec(value) {
463
- this.editor.chain().focus().setColor(value).run();
464
- },
465
- getValue() {
466
- return this.editor.getAttributes(MarkType.TEXT_STYLE).color;
467
- }
468
- }),
469
- [ToolType.FONT_FAMILY]: createInputAutoTool({
470
- name: ToolType.FONT_FAMILY,
471
- title: 'Семейство шрифта',
472
- exec(value) {
473
- this.editor.commands.setFontFamily(value);
474
- },
475
- getValue() {
476
- return this.editor.getAttributes(MarkType.TEXT_STYLE).fontFamily;
477
- },
478
- options: ['serif', 'sans-serif']
479
- }),
480
- [ToolType.BLOCKQUOTE]: createButtonTool({
481
- name: ToolType.BLOCKQUOTE,
482
- icon: 'format-quote-close-outline',
483
- title: 'Цитата',
484
- exec() {
485
- this.editor
486
- .chain()
487
- .focus()
488
- .toggleBlockquote()
489
- .run();
490
- },
491
- isActive() {
492
- return this.editor.isActive(NodeType.BLOCKQUOTE);
493
- }
494
- }),
495
- [ToolType.HARD_BREAK]: createButtonTool({
496
- name: ToolType.HARD_BREAK,
497
- title: 'Перевод строки',
498
- icon: 'keyboard-return',
499
- exec() {
500
- this.editor.chain().focus().setHardBreak().run();
501
- }
502
- }),
503
- [ToolType.CODE]: createButtonTool({
504
- name: ToolType.CODE,
505
- icon: 'code-not-equal-variant',
506
- title: 'Код',
507
- exec() {
508
- this.editor.chain().focus().toggleCode().run();
509
- },
510
- isActive() {
511
- return this.editor.isActive(MarkType.CODE);
512
- }
513
- }),
514
- [ToolType.IMAGE]: createImageTool({
515
- name: ToolType.IMAGE,
516
- icon: 'image-plus',
517
- title: 'Изображение',
518
- async exec({ url = null, isResponsive, width, height }) {
519
- const setImage = (src) => {
520
- const editor = this.editor.chain().setImage({ src });
521
-
522
- if (isResponsive === false) {
523
- editor.setStyles({ width, height }).toggleResponsive().run();
524
- return;
525
- }
526
- editor.run();
527
- };
528
-
529
- if ([null, ''].includes(url) === false) {
530
- setImage(url);
531
- return;
532
- }
533
-
534
- const imageUrl = await this.getImageUrl();
535
-
536
- if (imageUrl != null) {
537
- setImage(imageUrl);
538
- }
539
- },
540
- getValue() {
541
- return this.editor.getAttributes(NodeType.IMAGE);
542
- }
543
- }),
544
- [ToolType.ORDERED_LIST]: createButtonTool({
545
- name: ToolType.ORDERED_LIST,
546
- icon: 'format-list-numbered',
547
- title: 'Нумерованный список',
548
- exec() {
549
- this.editor.chain().focus().toggleOrderedList().run();
550
- },
551
- isActive() {
552
- return this.editor.isActive(NodeType.ORDERED_LIST);
553
- }
554
- }),
555
- [ToolType.BULLET_LIST]: createButtonTool({
556
- name: ToolType.BULLET_LIST,
557
- icon: 'format-list-bulleted',
558
- title: 'Маркированный список',
559
- exec() {
560
- this.editor.chain().focus().toggleBulletList().run();
561
- },
562
- isActive() {
563
- return this.editor.isActive(NodeType.BULLET_LIST);
564
- }
565
- }),
566
- [ToolType.TEXT_ALIGN_LEFT]: createButtonTool({
567
- name: ToolType.TEXT_ALIGN_LEFT,
568
- icon: 'format-align-left',
569
- title: 'По левому краю',
570
- exec() {
571
- this.editor.chain().focus().setTextAlign('left').run();
572
- },
573
- isActive() {
574
- return this.editor.isActive({ textAlign: 'left' });
575
- }
576
- }),
577
- [ToolType.TEXT_ALIGN_CENTER]: createButtonTool({
578
- name: ToolType.TEXT_ALIGN_CENTER,
579
- icon: 'format-align-center',
580
- title: 'По центру',
581
- exec() {
582
- this.editor.chain().focus().setTextAlign('center').run();
583
- },
584
- isActive() {
585
- return this.editor.isActive({ textAlign: 'center' });
586
- }
587
- }),
588
- [ToolType.TEXT_ALIGN_RIGHT]: createButtonTool({
589
- name: ToolType.TEXT_ALIGN_RIGHT,
590
- icon: 'format-align-right',
591
- title: 'По правому краю',
592
- exec() {
593
- this.editor.chain().focus().setTextAlign('right').run();
594
- },
595
- isActive() {
596
- return this.editor.isActive({ textAlign: 'right' });
597
- }
598
- }),
599
- [ToolType.HORIZONTAL_RULE]: createButtonTool({
600
- name: ToolType.HORIZONTAL_RULE,
601
- icon: 'minus',
602
- title: 'Вертикальный разделитель',
603
- exec() {
604
- this.editor.chain().focus().setHorizontalRule().run();
605
- },
606
- isEnabled() {
607
- return this.editor.can().setHorizontalRule();
608
- }
609
- }),
610
- [ToolType.LINK]: createLinkTool({
611
- name: ToolType.LINK,
612
- icon: 'link-plus',
613
- title: 'Ссылка',
614
- getValue() {
615
- const linkAttrs = this.editor.getAttributes(MarkType.LINK);
616
- const { href: url, target } = linkAttrs;
617
- return { url, target };
618
- },
619
- isEnabled() {
620
- return this.editor.can().setLink();
621
- },
622
- exec({ url, target }) {
623
- const { editor } = this;
624
-
625
- if (url === '') {
626
- editor
627
- .chain()
628
- .focus()
629
- .extendMarkRange(MarkType.LINK)
630
- .unsetLink()
631
- .run();
632
-
633
- return;
634
- }
635
-
636
- editor
637
- .chain()
638
- .focus()
639
- .extendMarkRange(MarkType.LINK)
640
- .setLink({ href: url, ...(target && { target }) })
641
- .run();
642
- }
643
- }),
644
- [ToolType.BOLD]: createButtonTool({
645
- name: ToolType.BOLD,
646
- icon: 'format-bold',
647
- title: 'Жирный',
648
- exec() {
649
- this.editor.chain().focus().toggleBold().run();
650
- },
651
- isActive() {
652
- return this.editor.isActive(MarkType.BOLD);
653
- }
654
- }),
655
- [ToolType.ITALIC]: createButtonTool({
656
- name: ToolType.ITALIC,
657
- icon: 'format-italic',
658
- title: 'Курсив',
659
- exec() {
660
- this.editor.chain().focus().toggleItalic().run();
661
- },
662
- isActive() {
663
- return this.editor.isActive(MarkType.ITALIC);
664
- }
665
- }),
666
- [ToolType.STRIKE]: createButtonTool({
667
- name: ToolType.STRIKE,
668
- icon: 'format-strikethrough-variant',
669
- title: 'Зачеркивание',
670
- exec() {
671
- this.editor.chain().focus().toggleStrike().run();
672
- },
673
- isActive() {
674
- return this.editor.isActive(MarkType.STRIKE);
675
- }
676
- }),
677
- [ToolType.UNDERLINE]: createButtonTool({
678
- name: ToolType.UNDERLINE,
679
- icon: 'format-underline',
680
- title: 'Подчеркивание',
681
- exec() {
682
- this.editor.chain().focus().toggleUnderline().run();
683
- },
684
- isActive() {
685
- return this.editor.isActive(MarkType.UNDERLINE);
686
- }
687
- }),
688
- [ToolType.TABLE]: createToolbarPopoverTool({
689
- name: ToolType.TABLE,
690
- icon: 'table-plus',
691
- title: 'таблица',
692
- options: Object.values(TableOptionsMap)
693
- }),
694
- [ToolType.CLEAR_FORMATTING]: createButtonTool({
695
- name: ToolType.CLEAR_FORMATTING,
696
- icon: 'eraser',
697
- title: 'Очистить форматирование',
698
- exec() {
699
- this.editor.chain().focus().clearFormatting().run();
700
- }
701
- })
702
- };
1
+ import {
2
+ NodeType,
3
+ MarkType,
4
+ CommandType,
5
+ ToolType,
6
+ createButtonTool,
7
+ createColorPickerTool,
8
+ createCommand,
9
+ createInputUnitsTool,
10
+ createSelectTool,
11
+ createToolbarPopoverTool,
12
+ createInputAutoTool,
13
+ createLinkTool,
14
+ createImageTool,
15
+ } from './constants';
16
+
17
+ export const CommandMap = {
18
+ [CommandType.PARAGRAPH]: createCommand({
19
+ name: CommandType.PARAGRAPH,
20
+ title: 'Абзац',
21
+ exec() {
22
+ this.editor
23
+ .chain()
24
+ .focus()
25
+ .setParagraph()
26
+ .setParagraphClass('p')
27
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
28
+ .run();
29
+ },
30
+ isActive() {
31
+ return this.editor.isActive(NodeType.PARAGRAPH, { class: 'p' });
32
+ }
33
+ }),
34
+ [CommandType.HEADING_1]: createCommand({
35
+ name: CommandType.HEADING_1,
36
+ title: 'Заголовок 1 (h1)',
37
+ exec() {
38
+ this.editor
39
+ .chain()
40
+ .focus()
41
+ .setHeading({ level: 1 })
42
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
43
+ .run();
44
+ },
45
+ isActive() {
46
+ return this.editor.isActive(NodeType.HEADING, { level: 1 });
47
+ }
48
+ }),
49
+ [CommandType.HEADING_2]: createCommand({
50
+ name: CommandType.HEADING_2,
51
+ title: 'Заголовок 2 (h2)',
52
+ exec() {
53
+ this.editor
54
+ .chain()
55
+ .focus()
56
+ .setHeading({ level: 2 })
57
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
58
+ .run();
59
+ },
60
+ isActive() {
61
+ return this.editor.isActive(NodeType.HEADING, { level: 2 });
62
+ }
63
+ }),
64
+ [CommandType.HEADING_3]: createCommand({
65
+ name: CommandType.HEADING_3,
66
+ title: 'Заголовок 3 (h3)',
67
+ exec() {
68
+ this.editor
69
+ .chain()
70
+ .focus()
71
+ .setHeading({ level: 3 })
72
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
73
+ .run();
74
+ },
75
+ isActive() {
76
+ return this.editor.isActive(NodeType.HEADING, { level: 3 });
77
+ }
78
+ }),
79
+ [CommandType.HEADING_4]: createCommand({
80
+ name: CommandType.HEADING_4,
81
+ title: 'Заголовок 4 (h4)',
82
+ exec() {
83
+ this.editor
84
+ .chain()
85
+ .focus()
86
+ .setHeading({ level: 4 })
87
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
88
+ .run();
89
+ },
90
+ isActive() {
91
+ return this.editor.isActive(NodeType.HEADING, { level: 4 });
92
+ }
93
+ }),
94
+ [CommandType.TEXT_SMALL]: createCommand({
95
+ name: CommandType.TEXT_SMALL,
96
+ title: 'Small',
97
+ exec() {
98
+ this.editor
99
+ .chain()
100
+ .focus()
101
+ .setParagraph()
102
+ .setParagraphClass('text-small')
103
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
104
+ .run();
105
+ },
106
+ isActive() {
107
+ return this.editor.isActive(NodeType.PARAGRAPH, { class: 'text-small' });
108
+ }
109
+ }),
110
+ [CommandType.TEXT_XSMALL]: createCommand({
111
+ name: CommandType.TEXT_XSMALL,
112
+ title: 'Xsmall',
113
+ exec() {
114
+ this.editor
115
+ .chain()
116
+ .focus()
117
+ .setParagraph()
118
+ .setParagraphClass('text-xsmall')
119
+ .resetAttributes(MarkType.TEXT_STYLE, 'fontSize')
120
+ .run();
121
+ },
122
+ isActive() {
123
+ return this.editor.isActive(NodeType.PARAGRAPH, { class: 'text-xsmall' });
124
+ }
125
+ }),
126
+ [CommandType.CODE_BLOCK]: createCommand({
127
+ name: CommandType.CODE_BLOCK,
128
+ title: 'Код',
129
+ exec() {
130
+ this.editor
131
+ .chain()
132
+ .focus()
133
+ .setCodeBlock()
134
+ .run();
135
+ },
136
+ isActive() {
137
+ return this.editor.isActive(NodeType.CODE_BLOCK);
138
+ }
139
+ }),
140
+ [CommandType.SINK_LIST_ITEM]: createCommand({
141
+ name: CommandType.SINK_LIST_ITEM,
142
+ title: 'Опустить элемент списка',
143
+ exec() {
144
+ this.editor
145
+ .chain()
146
+ .focus()
147
+ .sinkListItem(NodeType.LIST_ITEM)
148
+ .run();
149
+ },
150
+ isEnabled() {
151
+ return this.editor.can().sinkListItem(NodeType.LIST_ITEM);
152
+ }
153
+ }),
154
+ [CommandType.LIFT_LIST_ITEM]: createCommand({
155
+ name: CommandType.LIFT_LIST_ITEM,
156
+ title: 'Поднять элемент списка',
157
+ exec() {
158
+ this.editor.chain().focus().liftListItem(NodeType.LIST_ITEM).run();
159
+ },
160
+ isEnabled() {
161
+ return this.editor.can().liftListItem(NodeType.LIST_ITEM);
162
+ }
163
+ })
164
+ };
165
+
166
+ export const TableOptionsMap = {
167
+ [ToolType.INSERT_TABLE]: createButtonTool({
168
+ name: ToolType.INSERT_TABLE,
169
+ icon: 'table',
170
+ title: 'Вставить таблицу',
171
+ exec() {
172
+ this.editor
173
+ .chain()
174
+ .focus()
175
+ .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
176
+ .run();
177
+ },
178
+ isEnabled() {
179
+ return this.editor.can().insertTable();
180
+ }
181
+ }),
182
+ [ToolType.DELETE_TABLE]: createButtonTool({
183
+ name: ToolType.DELETE_TABLE,
184
+ icon: 'table-remove',
185
+ title: 'Удалить таблицу',
186
+ exec() {
187
+ this.editor.chain().focus().deleteTable().run();
188
+ },
189
+ isEnabled() {
190
+ return this.editor.can().deleteTable();
191
+ }
192
+ }),
193
+ [ToolType.ADD_COLUMN_BEFORE]: createButtonTool({
194
+ name: ToolType.ADD_COLUMN_BEFORE,
195
+ icon: 'table-column-plus-before',
196
+ title: 'Добавить колонку перед',
197
+ exec() {
198
+ this.editor.chain().focus().addColumnBefore().run();
199
+ },
200
+ isEnabled() {
201
+ return this.editor.can().addColumnBefore();
202
+ }
203
+ }),
204
+ [ToolType.ADD_COLUMN_AFTER]: createButtonTool({
205
+ name: ToolType.ADD_COLUMN_AFTER,
206
+ icon: 'table-column-plus-after',
207
+ title: 'Добавить колонку после',
208
+ exec() {
209
+ this.editor.chain().focus().addColumnAfter().run();
210
+ },
211
+ isEnabled() {
212
+ return this.editor.can().addColumnAfter();
213
+ }
214
+ }),
215
+ [ToolType.DELETE_COLUMN]: createButtonTool({
216
+ name: ToolType.DELETE_COLUMN,
217
+ icon: 'table-column-remove',
218
+ title: 'Удалить колонку',
219
+ exec() {
220
+ this.editor.chain().focus().deleteColumn().run();
221
+ },
222
+ isEnabled() {
223
+ return this.editor.can().deleteColumn();
224
+ }
225
+ }),
226
+ [ToolType.ADD_ROW_BEFORE]: createButtonTool({
227
+ name: ToolType.ADD_ROW_BEFORE,
228
+ icon: 'table-row-plus-before',
229
+ title: 'Добавить строку перед',
230
+ exec() {
231
+ this.editor.chain().focus().addRowBefore().run();
232
+ },
233
+ isEnabled() {
234
+ return this.editor.can().addRowBefore();
235
+ }
236
+ }),
237
+ [ToolType.ADD_ROW_AFTER]: createButtonTool({
238
+ name: ToolType.ADD_ROW_AFTER,
239
+ icon: 'table-row-plus-after',
240
+ title: 'Добавить строку после',
241
+ exec() {
242
+ this.editor.chain().focus().addRowAfter().run();
243
+ },
244
+ isEnabled() {
245
+ return this.editor.can().addRowAfter();
246
+ }
247
+ }),
248
+ [ToolType.DELETE_ROW]: createButtonTool({
249
+ name: ToolType.DELETE_ROW,
250
+ icon: 'table-row-remove',
251
+ title: 'Удалить строку',
252
+ exec() {
253
+ this.editor.chain().focus().deleteRow().run();
254
+ },
255
+ isEnabled() {
256
+ return this.editor.can().deleteRow();
257
+ }
258
+ }),
259
+ [ToolType.MERGE_CELLS]: createButtonTool({
260
+ name: ToolType.MERGE_CELLS,
261
+ icon: 'table-merge-cells',
262
+ title: 'Объединить ячейки',
263
+ exec() {
264
+ this.editor.chain().focus().mergeCells().run();
265
+ },
266
+ isEnabled() {
267
+ return this.editor.can().mergeCells();
268
+ }
269
+ }),
270
+ [ToolType.SPLIT_CELL]: createButtonTool({
271
+ name: ToolType.SPLIT_CELL,
272
+ icon: 'table-split-cell',
273
+ title: 'Разделить ячейки',
274
+ exec() {
275
+ this.editor.chain().focus().splitCell().run();
276
+ },
277
+ isEnabled() {
278
+ return this.editor.can().splitCell();
279
+ }
280
+ }),
281
+ [ToolType.TOGGLE_HEADER_ROW]: createButtonTool({
282
+ name: ToolType.TOGGLE_HEADER_ROW,
283
+ icon: 'table-row-height',
284
+ title: 'Переключить строку заголовка',
285
+ exec() {
286
+ this.editor.chain().focus().toggleHeaderRow().run();
287
+ },
288
+ isEnabled() {
289
+ return this.editor.can().toggleHeaderRow();
290
+ }
291
+ }),
292
+ [ToolType.TOGGLE_HEADER_COLUMN]: createButtonTool({
293
+ name: ToolType.TOGGLE_HEADER_COLUMN,
294
+ icon: 'table-column-width',
295
+ title: 'Переключить колонку заголовка',
296
+ exec() {
297
+ this.editor.chain().focus().toggleHeaderColumn().run();
298
+ },
299
+ isEnabled() {
300
+ return this.editor.can().toggleHeaderColumn();
301
+ }
302
+ }),
303
+ [ToolType.ALIGN_V_TOP]: createButtonTool({
304
+ name: ToolType.ALIGN_V_TOP,
305
+ icon: 'align-vertical-top',
306
+ title: 'Выровнять по верхнему краю',
307
+ exec() {
308
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
309
+ this.editor.chain().focus().toggleTableAlignment('table-vtop', classNames).run();
310
+ },
311
+ isEnabled() {
312
+ return this.editor.isActive(NodeType.TABLE);
313
+ },
314
+ isActive() {
315
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
316
+ return classNames?.includes('table-vtop') ?? false;
317
+ }
318
+ }),
319
+ [ToolType.ALIGN_V_MID]: createButtonTool({
320
+ name: ToolType.ALIGN_V_MID,
321
+ icon: 'align-vertical-center',
322
+ title: 'Выровнять по центру',
323
+ exec() {
324
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
325
+ this.editor.chain().focus().toggleTableAlignment('table-vmid', classNames).run();
326
+ },
327
+ isEnabled() {
328
+ return this.editor.isActive(NodeType.TABLE);
329
+ },
330
+ isActive() {
331
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
332
+ return classNames?.includes('table-vmid') ?? false;
333
+ }
334
+ }),
335
+ [ToolType.ALIGN_V_BOT]: createButtonTool({
336
+ name: ToolType.ALIGN_V_BOT,
337
+ icon: 'align-vertical-bottom',
338
+ title: 'Выровнять по нижнему краю',
339
+ exec() {
340
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
341
+ this.editor.chain().focus().toggleTableAlignment('table-vbot', classNames).run();
342
+ },
343
+ isEnabled() {
344
+ return this.editor.isActive(NodeType.TABLE);
345
+ },
346
+ isActive() {
347
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
348
+ return classNames?.includes('table-vbot') ?? false;
349
+ }
350
+ }),
351
+ [ToolType.TOGGLE_BORDERS]: createButtonTool({
352
+ name: ToolType.TOGGLE_BORDERS,
353
+ icon: 'border-all',
354
+ title: 'Границы',
355
+ exec() {
356
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
357
+ this.editor.chain().focus().toggleTableClass('table-borders', classNames).run();
358
+ },
359
+ isEnabled() {
360
+ return this.editor.isActive(NodeType.TABLE);
361
+ },
362
+ isActive() {
363
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
364
+ return classNames?.includes('table-borders') ?? false;
365
+ }
366
+ }),
367
+ [ToolType.TOGGLE_ZEBRA]: createButtonTool({
368
+ name: ToolType.TOGGLE_ZEBRA,
369
+ icon: 'view-stream',
370
+ title: 'Стиль "зебра"',
371
+ exec() {
372
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
373
+ this.editor.chain().focus().toggleTableClass('table-zebra', classNames).run();
374
+ },
375
+ isEnabled() {
376
+ return this.editor.isActive(NodeType.TABLE);
377
+ },
378
+ isActive() {
379
+ const classNames = this.editor.getAttributes(NodeType.TABLE).class;
380
+ return classNames?.includes('table-zebra') ?? false;
381
+ }
382
+ })
383
+ };
384
+
385
+ export const ToolsMap = {
386
+ [ToolType.UNDO]: createButtonTool({
387
+ name: ToolType.UNDO,
388
+ icon: 'undo-variant',
389
+ title: 'Назад',
390
+ exec() {
391
+ this.editor.commands.undo();
392
+ },
393
+ isEnabled() {
394
+ return this.editor.can().undo();
395
+ }
396
+ }),
397
+ [ToolType.REDO]: createButtonTool({
398
+ name: ToolType.REDO,
399
+ icon: 'redo-variant',
400
+ title: 'Вперед',
401
+ exec() {
402
+ this.editor.commands.redo();
403
+ },
404
+ isEnabled() {
405
+ return this.editor.can().redo();
406
+ }
407
+ }),
408
+ [ToolType.SAVE]: createButtonTool({
409
+ name: ToolType.SAVE,
410
+ icon: 'content-save',
411
+ title: 'Сохранить',
412
+ exec() {
413
+ this.onChange();
414
+ }
415
+ }),
416
+ [ToolType.PARAGRAPH_STYLE]: createSelectTool({
417
+ name: ToolType.PARAGRAPH_STYLE,
418
+ title: 'Стиль параграфа',
419
+ exec(command) {
420
+ if (command.name in CommandMap && command.isEnabled()) {
421
+ command.exec();
422
+ }
423
+ },
424
+ getValue(options) {
425
+ return options.find(({ value }) => value.isActive()) ?? null;
426
+ },
427
+ options: [
428
+ CommandMap[CommandType.PARAGRAPH],
429
+ CommandMap[CommandType.HEADING_1],
430
+ CommandMap[CommandType.HEADING_2],
431
+ CommandMap[CommandType.HEADING_3],
432
+ CommandMap[CommandType.HEADING_4],
433
+ CommandMap[CommandType.TEXT_SMALL],
434
+ CommandMap[CommandType.TEXT_XSMALL],
435
+ CommandMap[CommandType.CODE_BLOCK]
436
+ ]
437
+ }),
438
+ [ToolType.FONT_SIZE]: createInputUnitsTool({
439
+ name: ToolType.FONT_SIZE,
440
+ title: 'Размер шрифта',
441
+ exec(value) {
442
+ this.editor.commands.setFontSize(value);
443
+ },
444
+ isEnabled() {
445
+ const { editor } = this;
446
+
447
+ return (
448
+ editor.isActive(NodeType.HEADING) ||
449
+ editor.isActive(NodeType.PARAGRAPH, { class: 'text-small' }) ||
450
+ editor.isActive(NodeType.PARAGRAPH, { class: 'text-xsmall' })
451
+ ) === false;
452
+ },
453
+ getValue() {
454
+ return this.editor.getAttributes(MarkType.TEXT_STYLE).fontSize;
455
+ },
456
+ units: ["rem", "em", "%", "px", "vh", "vw"]
457
+ }),
458
+ [ToolType.TEXT_COLOR]: createColorPickerTool({
459
+ name: ToolType.TEXT_COLOR,
460
+ icon: 'format-color-fill',
461
+ title: 'Цвет',
462
+ exec(value) {
463
+ this.editor.chain().focus().setColor(value).run();
464
+ },
465
+ getValue() {
466
+ return this.editor.getAttributes(MarkType.TEXT_STYLE).color;
467
+ }
468
+ }),
469
+ [ToolType.FONT_FAMILY]: createInputAutoTool({
470
+ name: ToolType.FONT_FAMILY,
471
+ title: 'Семейство шрифта',
472
+ exec(value) {
473
+ this.editor.commands.setFontFamily(value);
474
+ },
475
+ getValue() {
476
+ return this.editor.getAttributes(MarkType.TEXT_STYLE).fontFamily;
477
+ },
478
+ options: ['serif', 'sans-serif']
479
+ }),
480
+ [ToolType.BLOCKQUOTE]: createButtonTool({
481
+ name: ToolType.BLOCKQUOTE,
482
+ icon: 'format-quote-close-outline',
483
+ title: 'Цитата',
484
+ exec() {
485
+ this.editor
486
+ .chain()
487
+ .focus()
488
+ .toggleBlockquote()
489
+ .run();
490
+ },
491
+ isActive() {
492
+ return this.editor.isActive(NodeType.BLOCKQUOTE);
493
+ }
494
+ }),
495
+ [ToolType.HARD_BREAK]: createButtonTool({
496
+ name: ToolType.HARD_BREAK,
497
+ title: 'Перевод строки',
498
+ icon: 'keyboard-return',
499
+ exec() {
500
+ this.editor.chain().focus().setHardBreak().run();
501
+ }
502
+ }),
503
+ [ToolType.CODE]: createButtonTool({
504
+ name: ToolType.CODE,
505
+ icon: 'code-not-equal-variant',
506
+ title: 'Код',
507
+ exec() {
508
+ this.editor.chain().focus().toggleCode().run();
509
+ },
510
+ isActive() {
511
+ return this.editor.isActive(MarkType.CODE);
512
+ }
513
+ }),
514
+ [ToolType.IMAGE]: createImageTool({
515
+ name: ToolType.IMAGE,
516
+ icon: 'image-plus',
517
+ title: 'Изображение',
518
+ async exec({ url = null, isResponsive, align, width, height }) {
519
+ const setImage = (src) => {
520
+ this.editor.commands.setImage({ src });
521
+
522
+ let imageClasses = this.editor.getAttributes(NodeType.IMAGE).class;
523
+
524
+ this.editor.commands.setImageAlign(align, imageClasses);
525
+
526
+ if (isResponsive === false) {
527
+ imageClasses = this.editor.getAttributes(NodeType.IMAGE).class;
528
+ this.editor
529
+ .chain()
530
+ .setStyles({ width, height })
531
+ .resetResponsive(imageClasses)
532
+ .run();
533
+ }
534
+ };
535
+
536
+ if ([null, ''].includes(url) === false) {
537
+ setImage(url);
538
+ return;
539
+ }
540
+
541
+ const imageUrl = await this.getImageUrl();
542
+
543
+ if (imageUrl != null) {
544
+ setImage(imageUrl);
545
+ }
546
+ },
547
+ getValue() {
548
+ return this.editor.getAttributes(NodeType.IMAGE);
549
+ }
550
+ }),
551
+ [ToolType.ORDERED_LIST]: createButtonTool({
552
+ name: ToolType.ORDERED_LIST,
553
+ icon: 'format-list-numbered',
554
+ title: 'Нумерованный список',
555
+ exec() {
556
+ this.editor.chain().focus().toggleOrderedList().run();
557
+ },
558
+ isActive() {
559
+ return this.editor.isActive(NodeType.ORDERED_LIST);
560
+ }
561
+ }),
562
+ [ToolType.BULLET_LIST]: createButtonTool({
563
+ name: ToolType.BULLET_LIST,
564
+ icon: 'format-list-bulleted',
565
+ title: 'Маркированный список',
566
+ exec() {
567
+ this.editor.chain().focus().toggleBulletList().run();
568
+ },
569
+ isActive() {
570
+ return this.editor.isActive(NodeType.BULLET_LIST);
571
+ }
572
+ }),
573
+ [ToolType.TEXT_ALIGN_LEFT]: createButtonTool({
574
+ name: ToolType.TEXT_ALIGN_LEFT,
575
+ icon: 'format-align-left',
576
+ title: 'По левому краю',
577
+ exec() {
578
+ this.editor.chain().focus().setTextAlign('left').run();
579
+ },
580
+ isActive() {
581
+ return this.editor.isActive({ textAlign: 'left' });
582
+ }
583
+ }),
584
+ [ToolType.TEXT_ALIGN_CENTER]: createButtonTool({
585
+ name: ToolType.TEXT_ALIGN_CENTER,
586
+ icon: 'format-align-center',
587
+ title: 'По центру',
588
+ exec() {
589
+ this.editor.chain().focus().setTextAlign('center').run();
590
+ },
591
+ isActive() {
592
+ return this.editor.isActive({ textAlign: 'center' });
593
+ }
594
+ }),
595
+ [ToolType.TEXT_ALIGN_RIGHT]: createButtonTool({
596
+ name: ToolType.TEXT_ALIGN_RIGHT,
597
+ icon: 'format-align-right',
598
+ title: 'По правому краю',
599
+ exec() {
600
+ this.editor.chain().focus().setTextAlign('right').run();
601
+ },
602
+ isActive() {
603
+ return this.editor.isActive({ textAlign: 'right' });
604
+ }
605
+ }),
606
+ [ToolType.HORIZONTAL_RULE]: createButtonTool({
607
+ name: ToolType.HORIZONTAL_RULE,
608
+ icon: 'minus',
609
+ title: 'Вертикальный разделитель',
610
+ exec() {
611
+ this.editor.chain().focus().setHorizontalRule().run();
612
+ },
613
+ isEnabled() {
614
+ return this.editor.can().setHorizontalRule();
615
+ }
616
+ }),
617
+ [ToolType.LINK]: createLinkTool({
618
+ name: ToolType.LINK,
619
+ icon: 'link-plus',
620
+ title: 'Ссылка',
621
+ getValue() {
622
+ const linkAttrs = this.editor.getAttributes(MarkType.LINK);
623
+ const { href: url, target } = linkAttrs;
624
+ return { url, target };
625
+ },
626
+ isEnabled() {
627
+ return this.editor.can().setLink();
628
+ },
629
+ exec({ url, target }) {
630
+ const { editor } = this;
631
+
632
+ if (url === '') {
633
+ editor
634
+ .chain()
635
+ .focus()
636
+ .extendMarkRange(MarkType.LINK)
637
+ .unsetLink()
638
+ .run();
639
+
640
+ return;
641
+ }
642
+
643
+ editor
644
+ .chain()
645
+ .focus()
646
+ .extendMarkRange(MarkType.LINK)
647
+ .setLink({ href: url, ...(target && { target }) })
648
+ .run();
649
+ }
650
+ }),
651
+ [ToolType.BOLD]: createButtonTool({
652
+ name: ToolType.BOLD,
653
+ icon: 'format-bold',
654
+ title: 'Жирный',
655
+ exec() {
656
+ this.editor.chain().focus().toggleBold().run();
657
+ },
658
+ isActive() {
659
+ return this.editor.isActive(MarkType.BOLD);
660
+ }
661
+ }),
662
+ [ToolType.ITALIC]: createButtonTool({
663
+ name: ToolType.ITALIC,
664
+ icon: 'format-italic',
665
+ title: 'Курсив',
666
+ exec() {
667
+ this.editor.chain().focus().toggleItalic().run();
668
+ },
669
+ isActive() {
670
+ return this.editor.isActive(MarkType.ITALIC);
671
+ }
672
+ }),
673
+ [ToolType.STRIKE]: createButtonTool({
674
+ name: ToolType.STRIKE,
675
+ icon: 'format-strikethrough-variant',
676
+ title: 'Зачеркивание',
677
+ exec() {
678
+ this.editor.chain().focus().toggleStrike().run();
679
+ },
680
+ isActive() {
681
+ return this.editor.isActive(MarkType.STRIKE);
682
+ }
683
+ }),
684
+ [ToolType.UNDERLINE]: createButtonTool({
685
+ name: ToolType.UNDERLINE,
686
+ icon: 'format-underline',
687
+ title: 'Подчеркивание',
688
+ exec() {
689
+ this.editor.chain().focus().toggleUnderline().run();
690
+ },
691
+ isActive() {
692
+ return this.editor.isActive(MarkType.UNDERLINE);
693
+ }
694
+ }),
695
+ [ToolType.TABLE]: createToolbarPopoverTool({
696
+ name: ToolType.TABLE,
697
+ icon: 'table-plus',
698
+ title: 'таблица',
699
+ options: Object.values(TableOptionsMap)
700
+ }),
701
+ [ToolType.CLEAR_FORMATTING]: createButtonTool({
702
+ name: ToolType.CLEAR_FORMATTING,
703
+ icon: 'eraser',
704
+ title: 'Очистить форматирование',
705
+ exec() {
706
+ this.editor.chain().focus().clearFormatting().run();
707
+ }
708
+ })
709
+ };