tiptapify 0.0.4 → 0.0.6

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 (36) hide show
  1. package/README.md +9 -1
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/tiptapify.es.js +20861 -19932
  4. package/dist/tiptapify.umd.js +39 -32
  5. package/package.json +23 -10
  6. package/src/components/MenuBubble.vue +25 -20
  7. package/src/components/MenuFloating.vue +35 -31
  8. package/src/components/Tiptapify.vue +51 -14
  9. package/src/components/Toolbar/Group.vue +78 -0
  10. package/src/components/Toolbar/Index.vue +44 -71
  11. package/src/components/Toolbar/Toggle.vue +33 -0
  12. package/src/components/Toolbar/fonts.ts +118 -0
  13. package/src/components/Toolbar/items/actions.ts +32 -0
  14. package/src/components/Toolbar/items/alignment.ts +60 -0
  15. package/src/components/Toolbar/items/format.ts +73 -0
  16. package/src/components/Toolbar/items/formatExtra.ts +73 -0
  17. package/src/components/Toolbar/items/list.ts +70 -0
  18. package/src/components/Toolbar/items/media.ts +25 -0
  19. package/src/components/Toolbar/items/misc.ts +50 -0
  20. package/src/components/Toolbar/items/style.ts +146 -0
  21. package/src/components/Toolbar/items.ts +72 -635
  22. package/src/components/editorExtensions.ts +3 -1
  23. package/src/components/extensions/components/LinkDialog.vue +1 -1
  24. package/src/components/extensions/components/ShowSource.vue +124 -0
  25. package/src/components/extensions/view-source.ts +53 -0
  26. package/src/i18n/locales/de.json +67 -0
  27. package/src/i18n/locales/en.json +11 -2
  28. package/src/i18n/locales/es.json +67 -0
  29. package/src/i18n/locales/fr.json +67 -0
  30. package/src/i18n/locales/it.json +67 -0
  31. package/src/i18n/locales/pl.json +67 -0
  32. package/src/i18n/locales/ru.json +11 -2
  33. package/src/i18n/locales/ua.json +11 -2
  34. package/components.d.ts +0 -20
  35. package/tsconfig.json +0 -22
  36. package/vite.config.ts +0 -86
@@ -1,129 +1,12 @@
1
- import { computed, ComputedRef, Ref, ref } from "vue";
2
- import * as mdi from '@mdi/js'
3
-
4
- const fonts = ref([
5
- {
6
- name: 'Arial',
7
- fontFamily: 'arial'
8
- },
9
- {
10
- name: 'Arial Black',
11
- fontFamily: 'arial black'
12
- },
13
- {
14
- name: 'Baskerville',
15
- fontFamily: 'baskerville'
16
- },
17
- {
18
- name: 'Bodoni MT',
19
- fontFamily: 'bodoni mt'
20
- },
21
- {
22
- name: 'Brush Script MT',
23
- fontFamily: 'brush script mt'
24
- },
25
- {
26
- name: 'Calibri',
27
- fontFamily: 'calibri'
28
- },
29
- {
30
- name: 'Calisto MT',
31
- fontFamily: 'calisto mt'
32
- },
33
- {
34
- name: 'Cambria',
35
- fontFamily: 'cambria'
36
- },
37
- {
38
- name: 'Century Gothic',
39
- fontFamily: 'century gothic'
40
- },
41
- {
42
- name: 'Consolas',
43
- fontFamily: 'consolas'
44
- },
45
- {
46
- name: 'Comic Sans',
47
- fontFamily: 'comic sans ms, comic sans'
48
- },
49
- {
50
- name: 'Courier',
51
- fontFamily: 'Courier'
52
- },
53
- {
54
- name: 'Courier New',
55
- fontFamily: 'courier new'
56
- },
57
- {
58
- name: 'Cursive',
59
- fontFamily: 'cursive'
60
- },
61
- {
62
- name: 'Dejavu Sans',
63
- fontFamily: 'dejavu sans'
64
- },
65
- {
66
- name: 'Franklin Gothic',
67
- fontFamily: 'franklin gothic'
68
- },
69
- {
70
- name: 'Garamond',
71
- fontFamily: 'garamond'
72
- },
73
- {
74
- name: 'Georgia',
75
- fontFamily: 'georgia'
76
- },
77
- {
78
- name: 'Helvetica',
79
- fontFamily: 'helvetica'
80
- },
81
- {
82
- name: 'Impact',
83
- fontFamily: 'impact'
84
- },
85
- {
86
- name: 'Inter',
87
- fontFamily: 'inter'
88
- },
89
- {
90
- name: 'Monospace',
91
- fontFamily: 'monospace'
92
- },
93
- {
94
- name: 'Optima',
95
- fontFamily: 'optima'
96
- },
97
- {
98
- name: 'Segoe UI',
99
- fontFamily: 'segoe ui'
100
- },
101
- {
102
- name: 'Serif',
103
- fontFamily: 'serif'
104
- },
105
- {
106
- name: 'Tahoma',
107
- fontFamily: 'tahoma'
108
- },
109
- {
110
- name: 'Time New Roman',
111
- fontFamily: 'times new roman'
112
- },
113
- {
114
- name: 'Trebuchet MS',
115
- fontFamily: 'trebuchet ms'
116
- },
117
- {
118
- name: 'Verdana',
119
- fontFamily: 'verdana'
120
- },
121
- ])
122
-
123
- interface MDIIcons {
124
- [key: string]: string
125
- }
126
- const mdiIcons = mdi as MDIIcons
1
+ import { getActionsItems } from "@tiptapify/components/Toolbar/items/actions";
2
+ import { getAlignmentItems } from "@tiptapify/components/Toolbar/items/alignment";
3
+ import { getFormatExtraItems } from "@tiptapify/components/Toolbar/items/formatExtra";
4
+ import { getFormatItems } from "@tiptapify/components/Toolbar/items/format";
5
+ import { getListItems } from "@tiptapify/components/Toolbar/items/list";
6
+ import { getMediaItems } from "@tiptapify/components/Toolbar/items/media";
7
+ import { getMiscItems } from "@tiptapify/components/Toolbar/items/misc";
8
+ import { getStyleItems } from "@tiptapify/components/Toolbar/items/style";
9
+ import { ComputedRef, Ref, ref } from "vue";
127
10
 
128
11
  interface ToolbarItemAttrs {
129
12
  [key: string]: Function | any
@@ -133,26 +16,32 @@ interface ToolbarItemProps {
133
16
  [key: string]: any
134
17
  }
135
18
 
136
- interface ToolbarItem {
19
+ export interface ToolbarItem {
137
20
  name: string|number,
138
21
  tooltip: string,
139
22
  icon: string|ComputedRef<string>,
140
23
  noI18n?: boolean,
141
24
  enabled: boolean,
142
25
  modelValue?: any,
143
- section?: string,
144
26
  group?: boolean,
27
+ toggle?: boolean,
145
28
  props?: ToolbarItemProps,
146
29
  attrs?: ToolbarItemAttrs,
147
- children?: ToolbarItem[],
30
+ children?: ToolbarItems|ToolbarItem[],
148
31
  }
149
32
 
150
33
  export interface ToolbarItems {
151
34
  [key: string]: ToolbarItem
152
35
  }
153
36
 
37
+ export interface ToolbarItemSection {
38
+ group?: boolean,
39
+ toggle?: boolean,
40
+ items: ToolbarItems,
41
+ }
42
+
154
43
  export interface ToolbarItemSections {
155
- [key: string]: ToolbarItems
44
+ [key: string]: ToolbarItemSection
156
45
  }
157
46
 
158
47
  export function toolbarItems(
@@ -162,500 +51,37 @@ export function toolbarItems(
162
51
  customHeadingLevels: Array<number>,
163
52
  toolbarLinkButton: Ref,
164
53
  ): ToolbarItemSections {
165
- const headingLevels = ref([1, 2, 3, 4, 5, 6])
166
- if (customHeadingLevels.length) {
167
- customHeadingLevels.forEach(level => {
168
- if (level <= 0 || level > 6) {
169
- throw new Error('customHeadingLevels must be between 1 and 6')
170
- }
171
- })
172
-
173
- headingLevels.value = customHeadingLevels
174
- }
175
-
176
- const fontSizes = [6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 32, 48, 64, 96]
177
-
178
- const lineHeights = [1, 1.5, 2, 3, 4]
179
-
180
- const allMenuItems: ToolbarItems = {
54
+ const styleItems = ref(getStyleItems(editor.value, fontMeasure, customHeadingLevels))
55
+ const formatItems = ref(getFormatItems(editor.value))
56
+ const formatExtraItems = ref(getFormatExtraItems(editor.value))
57
+ const alignmentItems = ref(getAlignmentItems(editor.value))
58
+ const listItems = ref(getListItems(editor.value))
59
+ const actionsItems = ref(getActionsItems(editor.value))
60
+ const miscItems = ref(getMiscItems(editor.value))
61
+ const mediaItems = ref(getMediaItems(editor.value, toolbarLinkButton))
62
+
63
+ const allMenuItems: ToolbarItemSections = {
181
64
  /**
182
65
  * todo
183
66
  *
184
67
  * font color, backgroundcolor
185
68
  * tables
186
69
  * media (image, video)
187
- * unsetmarks, clearnodes
188
70
  */
189
- heading: {
190
- name: 'heading',
191
- tooltip: 'style.heading',
192
- icon: mdi.mdiFormatHeaderPound,
193
- section: 'style',
194
- modelValue: null,
195
- enabled: true,
196
- attrs: {
197
- click: () => editor.value.chain().focus().setParagraph().run()
198
- },
199
- props: {
200
- color: computed(() => editor.value.isActive('heading') ? 'primary' : ''),
201
- },
202
- children: headingLevels.value.map(level => {
203
- return {
204
- name: `H${level}`,
205
- tooltip: `style.headings.h${level}`,
206
- icon: mdiIcons[`mdiFormatHeader${level}`],
207
- noI18n: true,
208
- enabled: true,
209
- props: {
210
- color: computed(() => {
211
- return editor.value.isActive('heading', { level }) ? 'primary' : ''
212
- }),
213
- },
214
- attrs: {
215
- click: () => editor.value.chain().focus().toggleHeading({ level }).run()
216
- }
217
- }
218
- })
219
- },
220
- fontFamily: {
221
- name: 'font-family',
222
- tooltip: 'style.fontFamily',
223
- icon: mdi.mdiFormatFont,
224
- section: 'style',
225
- modelValue: null,
226
- enabled: true,
227
- attrs: {
228
- click: () => editor.value.chain().focus().unsetFontFamily().run()
229
- },
230
- children: fonts.value.map((font) => {
231
- return {
232
- name: font.name,
233
- tooltip: '',
234
- icon: '',
235
- enabled: true,
236
- noI18n: true,
237
- props: {
238
- color: computed(() => editor.value.isActive('textStyle', { fontFamily: font.fontFamily }) ? 'primary' : ''),
239
- style: `font-family: ${font.fontFamily};`
240
- },
241
- attrs: {
242
- click: () => editor.value.chain().focus().setFontFamily(font.fontFamily).run()
243
- }
244
- }
245
- })
246
- },
247
- fontSize: {
248
- name: 'font-size',
249
- tooltip: 'style.fontSize',
250
- icon: mdi.mdiFormatSize,
251
- section: 'style',
252
- modelValue: computed(() => editor.value.getAttributes('textStyle').fontSize || null),
253
- enabled: true,
254
- attrs: {
255
- click: () => editor.value.chain().focus().unsetFontSize().run()
256
- },
257
- children: fontSizes.map((fontSize) => {
258
- return {
259
- name: `${fontSize}${fontMeasure}`,
260
- tooltip: '',
261
- icon: '',
262
- enabled: true,
263
- noI18n: true,
264
- props: {
265
- color: computed(() => editor.value.isActive('textStyle', { fontSizes: fontSize }) ? 'primary' : ''),
266
- },
267
- attrs: {
268
- click: () => editor.value.chain().focus().setFontSize(`${fontSize}${fontMeasure}`).run()
269
- }
270
- }
271
- })
272
- },
273
- lineHeight: {
274
- name: 'line-height',
275
- tooltip: 'style.lineHeight',
276
- icon: mdi.mdiFormatLineHeight,
277
- section: 'style',
278
- modelValue: null,
279
- enabled: true,
280
- attrs: {
281
- click: () => editor.value.chain().focus().unsetLineHeight().run()
282
- },
283
- children: lineHeights.map((lineHeight) => {
284
- return {
285
- name: lineHeight,
286
- tooltip: '',
287
- icon: '',
288
- enabled: true,
289
- noI18n: true,
290
- props: {
291
- color: computed(() => editor.value.isActive('textStyle', { lineHeights: lineHeight }) ? 'primary' : ''),
292
- },
293
- attrs: {
294
- click: () => editor.value.chain().focus().setLineHeight(lineHeight).run()
295
- }
296
- }
297
- })
298
- },
299
-
300
- bold: {
301
- name: 'bold',
302
- tooltip: 'format.bold',
303
- icon: mdi.mdiFormatBold,
304
- section: 'format',
305
- enabled: true,
306
- props: {
307
- disabled: computed(() => !editor.value.can().chain().focus().toggleBold().run()),
308
- color: computed(() => editor.value.isActive('bold') ? 'primary' : ''),
309
- },
310
- attrs: {
311
- click: () => editor.value.chain().focus().toggleBold().run()
312
- }
313
- },
314
- italic: {
315
- name: 'italic',
316
- tooltip: 'format.italic',
317
- icon: mdi.mdiFormatItalic,
318
- section: 'format',
319
- enabled: true,
320
- props: {
321
- disabled: computed(() => !editor.value.can().chain().focus().toggleItalic().run()),
322
- color: computed(() => editor.value.isActive('italic') ? 'primary' : ''),
323
- },
324
- attrs: {
325
- click: () => editor.value.chain().focus().toggleItalic().run()
326
- }
327
- },
328
- strike: {
329
- name: 'strike',
330
- tooltip: 'format.strike',
331
- icon: mdi.mdiFormatStrikethroughVariant,
332
- section: 'format',
333
- enabled: true,
334
- props: {
335
- disabled: computed(() => !editor.value.can().chain().focus().toggleStrike().run()),
336
- color: computed(() => editor.value.isActive('strike') ? 'primary' : ''),
337
- },
338
- attrs: {
339
- click: () => editor.value.chain().focus().toggleStrike().run()
340
- }
341
- },
342
- underline: {
343
- name: 'underline',
344
- tooltip: 'format.underline',
345
- icon: mdi.mdiFormatUnderline,
346
- section: 'format',
347
- enabled: true,
348
- props: {
349
- disabled: computed(() => !editor.value.can().chain().focus().toggleUnderline().run()),
350
- color: computed(() => editor.value.isActive('underline') ? 'primary' : ''),
351
- },
352
- attrs: {
353
- click: () => editor.value.chain().focus().toggleUnderline().run()
354
- }
355
- },
356
- highlight: {
357
- name: 'highlight',
358
- tooltip: 'format.highlight',
359
- icon: mdi.mdiMarker,
360
- section: 'format',
361
- enabled: true,
362
- props: {
363
- disabled: computed(() => !editor.value.can().chain().focus().toggleHighlight().run()),
364
- color: computed(() => editor.value.isActive('highlight') ? 'primary' : ''),
365
- },
366
- attrs: {
367
- click: () => editor.value.chain().focus().toggleHighlight().run()
368
- }
369
- },
370
- formatClear: {
371
- name: 'format clear',
372
- tooltip: 'format.formatClear',
373
- icon: mdi.mdiFormatClear,
374
- section: 'format',
375
- enabled: true,
376
- props: {
377
- disabled: computed(() => !editor.value.can().chain().focus().unsetAllMarks().run()),
378
- },
379
- attrs: {
380
- click: () => editor.value.chain().focus().unsetAllMarks().clearNodes().run()
381
- }
382
- },
383
-
384
- code: {
385
- name: 'code',
386
- tooltip: 'format.code',
387
- icon: mdi.mdiXml,
388
- section: 'format_extra',
389
- enabled: true,
390
- props: {
391
- disabled: computed(() => !editor.value.can().chain().focus().toggleCode().run()),
392
- color: computed(() => editor.value.isActive('code') ? 'primary' : ''),
393
- },
394
- attrs: {
395
- click: () => editor.value.chain().focus().toggleCode().run()
396
- }
397
- },
398
- codeBlock: {
399
- name: 'codeblock',
400
- tooltip: 'format.codeblock',
401
- icon: mdi.mdiCodeBlockTags,
402
- section: 'format_extra',
403
- enabled: true,
404
- props: {
405
- disabled: computed(() => !editor.value.can().chain().focus().toggleCodeBlock().run()),
406
- color: computed(() => editor.value.isActive('codeBlock') ? 'primary' : ''),
407
- },
408
- attrs: {
409
- click: () => editor.value.chain().focus().toggleCodeBlock().run()
410
- }
411
- },
412
- blockquote: {
413
- name: 'blockquote',
414
- tooltip: 'format.blockquote',
415
- icon: mdi.mdiCommentQuote,
416
- section: 'format_extra',
417
- enabled: true,
418
- props: {
419
- disabled: computed(() => !editor.value.can().chain().focus().toggleBlockquote().run()),
420
- color: computed(() => editor.value.isActive('blockquote') ? 'primary' : ''),
421
- },
422
- attrs: {
423
- click: () => editor.value.chain().focus().toggleBlockquote().run()
424
- }
425
- },
426
-
427
- sup: {
428
- name: 'sup',
429
- tooltip: 'format.sup',
430
- icon: mdi.mdiFormatSuperscript,
431
- enabled: true,
432
- props: {
433
- disabled: computed(() => !editor.value.can().chain().focus().toggleSuperscript().run()),
434
- color: computed(() => editor.value.isActive('superscript') ? 'primary' : ''),
435
- },
436
- attrs: {
437
- click: () => editor.value.chain().focus().toggleSuperscript().run()
438
- }
439
- },
440
- sub: {
441
- name: 'sub',
442
- tooltip: 'format.sub',
443
- icon: mdi.mdiFormatSubscript,
444
- enabled: true,
445
- props: {
446
- disabled: computed(() => !editor.value.can().chain().focus().toggleSubscript().run()),
447
- color: computed(() => editor.value.isActive('subscript') ? 'primary' : ''),
448
- },
449
- attrs: {
450
- click: () => editor.value.chain().focus().toggleSubscript().run()
451
- }
452
- },
453
-
454
- alignment: {
455
- name: 'alignment',
456
- tooltip: 'alignment',
457
- icon: '',
458
- section: 'alignment',
459
- enabled: true,
460
- group: true,
461
- children: [
462
- {
463
- name: 'alignments.left',
464
- tooltip: 'alignments.left',
465
- icon: mdi.mdiFormatAlignLeft,
466
- enabled: true,
467
- props: {
468
- color: computed(() => editor.value.isActive('text-align', { align: 'left' }) ? 'primary' : ''),
469
- },
470
- attrs: {
471
- click: () => editor.value.chain().focus().toggleTextAlign('left').run()
472
- }
473
- },
474
- {
475
- name: 'alignments.center',
476
- tooltip: 'alignments.center',
477
- icon: mdi.mdiFormatAlignCenter,
478
- enabled: true,
479
- props: {
480
- color: computed(() => editor.value.isActive('text-align', { align: 'center' }) ? 'primary' : ''),
481
- },
482
- attrs: {
483
- click: () => editor.value.chain().focus().toggleTextAlign('center').run()
484
- }
485
- },
486
- {
487
- name: 'alignments.right',
488
- tooltip: 'alignments.right',
489
- icon: mdi.mdiFormatAlignRight,
490
- enabled: true,
491
- props: {
492
- color: computed(() => editor.value.isActive('text-align', { align: 'right' }) ? 'primary' : ''),
493
- },
494
- attrs: {
495
- click: () => editor.value.chain().focus().toggleTextAlign('right').run()
496
- }
497
- },
498
- {
499
- name: 'alignments.justify',
500
- tooltip: 'alignments.justify',
501
- icon: mdi.mdiFormatAlignJustify,
502
- enabled: true,
503
- props: {
504
- color: computed(() => editor.value.isActive('text-align', { align: 'justify' }) ? 'primary' : ''),
505
- },
506
- attrs: {
507
- click: () => editor.value.chain().focus().toggleTextAlign('justify').run()
508
- }
509
- },
510
- ]
511
- },
512
-
513
- list: {
514
- name: 'list',
515
- tooltip: 'list',
516
- icon: mdi.mdiFormatListGroup,
517
- section: 'list',
518
- enabled: true,
519
- group: true,
520
- children: [
521
- {
522
- name: 'lists.bullet',
523
- tooltip: 'lists.bullet',
524
- icon: mdi.mdiFormatListBulleted,
525
- enabled: true,
526
- props: {
527
- color: computed(() => editor.value.isActive('bulletList') ? 'primary' : ''),
528
- },
529
- attrs: {
530
- click: () => editor.value.chain().focus().toggleBulletList().run()
531
- }
532
- },
533
- {
534
- name: 'lists.numbered',
535
- tooltip: 'lists.numbered',
536
- icon: mdi.mdiFormatListNumbered,
537
- enabled: true,
538
- props: {
539
- color: computed(() => editor.value.isActive('orderedList') ? 'primary' : ''),
540
- },
541
- attrs: {
542
- click: () => editor.value.chain().focus().toggleOrderedList().run()
543
- }
544
- },
545
- {
546
- name: 'lists.task',
547
- tooltip: 'lists.task',
548
- icon: mdi.mdiFormatListChecks,
549
- enabled: true,
550
- props: {
551
- color: computed(() => editor.value.isActive('taskList') ? 'primary' : ''),
552
- },
553
- attrs: {
554
- click: () => editor.value.chain().focus().toggleTaskList().run()
555
- }
556
- },
557
- {
558
- name: 'lists.indent',
559
- tooltip: 'lists.indent',
560
- icon: mdi.mdiFormatIndentIncrease,
561
- enabled: true,
562
- props: {
563
- disabled: computed(() => !editor.value.can().sinkListItem('listItem')),
564
- active: false,
565
- },
566
- attrs: {
567
- click: () => editor.value.chain().focus().sinkListItem('listItem').run()
568
- }
569
- },
570
- {
571
- name: 'lists.outdent',
572
- tooltip: 'lists.outdent',
573
- icon: mdi.mdiFormatIndentDecrease,
574
- enabled: true,
575
- props: {
576
- disabled: computed(() => !editor.value.can().liftListItem('listItem')),
577
- active: false,
578
- },
579
- attrs: {
580
- click: () => editor.value.chain().focus().liftListItem('listItem').run()
581
- }
582
- },
583
- ]
584
- },
585
-
586
- link: {
587
- name: 'format.link',
588
- tooltip: 'format.link',
589
- icon: computed(() => editor.value.isActive('link') ? mdi.mdiLinkOff : mdi.mdiLink),
590
- section: 'media',
591
- enabled: true,
592
- props: {
593
- color: computed(() => editor.value.isActive('link') ? 'primary' : ''),
594
- disabled: computed(() => editor.value.isActive('code') || editor.value.isActive('codeBlock')),
595
- },
596
- attrs: {
597
- click: computed(() => {
598
- return editor.value.isActive('link')
599
- ? editor.value.chain().focus().unsetLink().run
600
- : toolbarLinkButton.value?.open
601
- })
602
- }
603
- },
604
-
605
- undo: {
606
- name: 'undo',
607
- tooltip: 'action.undo',
608
- icon: mdi.mdiUndo,
609
- section: 'actions',
610
- enabled: true,
611
- props: {
612
- disabled: computed(() => !editor.value.can().chain().focus().undo().run()),
613
- },
614
- attrs: {
615
- click: () => editor.value.chain().focus().undo().run()
616
- }
617
- },
618
- redo: {
619
- name: 'redo',
620
- tooltip: 'action.redo',
621
- icon: mdi.mdiRedo,
622
- section: 'actions',
623
- enabled: true,
624
- props: {
625
- disabled: computed(() => !editor.value.can().chain().focus().redo().run()),
626
- },
627
- attrs: {
628
- click: () => editor.value.chain().focus().redo().run()
629
- }
630
- },
631
-
632
- line: {
633
- name: 'line',
634
- tooltip: 'format.line',
635
- icon: mdi.mdiMinus,
636
- section: 'misc',
637
- enabled: true,
638
- props: {},
639
- attrs: {
640
- click: () => editor.value.chain().focus().setHorizontalRule().run()
641
- }
642
- },
643
- break: {
644
- name: 'break',
645
- tooltip: 'format.break',
646
- icon: mdi.mdiFormatPageBreak,
647
- section: 'misc',
648
- enabled: true,
649
- props: {},
650
- attrs: {
651
- click: () => editor.value.chain().focus().setHardBreak().run()
652
- }
653
- },
71
+ style: { group: true, items: styleItems.value },
72
+ format: { group: true, items: formatItems.value },
73
+ format_extra: { group: true, items: formatExtraItems.value },
74
+ media: { group: true, items: mediaItems.value },
75
+ alignment: { toggle: true, items: alignmentItems.value },
76
+ list: { group: true, items: listItems.value },
77
+ actions: { group: true, items: actionsItems.value },
78
+ misc: { group: true, items: miscItems.value },
654
79
  }
655
80
 
656
-
657
-
658
- const pluginsList = Object.keys(allMenuItems)
81
+ const pluginsList: Array<string> = []
82
+ Object.keys(allMenuItems).forEach(section => {
83
+ Object.keys(allMenuItems[section]).forEach(item => pluginsList.push(item))
84
+ })
659
85
 
660
86
  if (items.list.length) {
661
87
  items.list.forEach(item => {
@@ -665,31 +91,42 @@ export function toolbarItems(
665
91
  })
666
92
  }
667
93
 
94
+ const toolbarItems: ToolbarItemSections = {}
95
+
668
96
  const sections = {}
669
- const toolbarItems: { [key: string]: ToolbarItems } = {}
670
- pluginsList.forEach(key => {
671
- const item = allMenuItems[key]
672
97
 
673
- if (items.list.length) {
674
- item.enabled = items.list.includes(key)
675
- if (items.exclude) {
676
- item.enabled = !item.enabled
98
+ Object.keys(allMenuItems).forEach(sectionName => {
99
+ const section = allMenuItems[sectionName]
100
+ Object.keys(section.items).forEach(plugin => {
101
+ const item = section.items[plugin]
102
+
103
+ if (items.list.length) {
104
+ item.enabled = items.list.includes(plugin)
105
+ if (items.exclude) {
106
+ item.enabled = !item.enabled
107
+ }
677
108
  }
678
- }
679
- const section = item.section ?? 'misc'
680
- if (typeof toolbarItems[section] === 'undefined') {
681
- sections[section] = 0
682
- toolbarItems[section] = {}
683
- }
684
- toolbarItems[section][key] = allMenuItems[key]
685
- if (allMenuItems[key].enabled) {
686
- sections[section]++
687
- }
109
+
110
+ if (typeof toolbarItems[sectionName] === 'undefined') {
111
+ sections[sectionName] = 0
112
+ toolbarItems[sectionName] = {
113
+ group: section.group ?? false,
114
+ toggle: section.toggle ?? false,
115
+ items: {},
116
+ }
117
+ }
118
+
119
+ toolbarItems[sectionName].items[plugin] = item
120
+
121
+ if (item.enabled) {
122
+ sections[sectionName]++
123
+ }
124
+ })
688
125
  })
689
126
 
690
- Object.keys(sections).forEach(key => {
691
- if (sections[key] === 0) {
692
- delete toolbarItems[key]
127
+ Object.keys(sections).forEach(sectionName => {
128
+ if (sections[sectionName] === 0) {
129
+ delete toolbarItems[sectionName]
693
130
  }
694
131
  })
695
132