@srcker/editor-vue-next 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/.vscode/extensions.json +3 -0
  2. package/README.md +50 -0
  3. package/index.html +13 -0
  4. package/index.ts +11 -0
  5. package/jsconfig.json +8 -0
  6. package/package.json +69 -0
  7. package/public/favicon.ico +0 -0
  8. package/src/App.vue +9 -0
  9. package/src/App.vue.js +17 -0
  10. package/src/Button/BackgroundButton.vue +331 -0
  11. package/src/Button/BackgroundButton.vue.js +243 -0
  12. package/src/Button/BlockQuoteButton.vue +26 -0
  13. package/src/Button/BlockQuoteButton.vue.js +56 -0
  14. package/src/Button/BoldButton.vue +29 -0
  15. package/src/Button/BoldButton.vue.js +56 -0
  16. package/src/Button/BulletListButton.vue +114 -0
  17. package/src/Button/BulletListButton.vue.js +147 -0
  18. package/src/Button/CodeBlockButton.vue +28 -0
  19. package/src/Button/CodeBlockButton.vue.js +56 -0
  20. package/src/Button/CodeButton.vue +30 -0
  21. package/src/Button/CodeButton.vue.js +56 -0
  22. package/src/Button/FontSizeButton.vue +85 -0
  23. package/src/Button/FontSizeButton.vue.js +131 -0
  24. package/src/Button/FormatButton.vue +25 -0
  25. package/src/Button/FormatButton.vue.js +54 -0
  26. package/src/Button/HeadingButton.vue +103 -0
  27. package/src/Button/HeadingButton.vue.js +164 -0
  28. package/src/Button/ImageUploadButton.vue +93 -0
  29. package/src/Button/ImageUploadButton.vue.js +123 -0
  30. package/src/Button/IndentLeftButton.vue +25 -0
  31. package/src/Button/IndentLeftButton.vue.js +54 -0
  32. package/src/Button/IndentRightButton.vue +29 -0
  33. package/src/Button/IndentRightButton.vue.js +54 -0
  34. package/src/Button/ItalicButton.vue +29 -0
  35. package/src/Button/ItalicButton.vue.js +56 -0
  36. package/src/Button/LineHeightButton.vue +88 -0
  37. package/src/Button/LineHeightButton.vue.js +131 -0
  38. package/src/Button/LinkButton.vue +44 -0
  39. package/src/Button/LinkButton.vue.js +69 -0
  40. package/src/Button/OrderedListButton.vue +121 -0
  41. package/src/Button/OrderedListButton.vue.js +146 -0
  42. package/src/Button/RedoButton.vue +29 -0
  43. package/src/Button/RedoButton.vue.js +55 -0
  44. package/src/Button/StrikeButton.vue +30 -0
  45. package/src/Button/StrikeButton.vue.js +56 -0
  46. package/src/Button/SubscriptButton.vue +29 -0
  47. package/src/Button/SubscriptButton.vue.js +56 -0
  48. package/src/Button/SuperscriptButton.vue +29 -0
  49. package/src/Button/SuperscriptButton.vue.js +56 -0
  50. package/src/Button/TextAlignCenterButton.vue +26 -0
  51. package/src/Button/TextAlignCenterButton.vue.js +56 -0
  52. package/src/Button/TextAlignLeftButton.vue +26 -0
  53. package/src/Button/TextAlignLeftButton.vue.js +56 -0
  54. package/src/Button/TextAlignRightButton.vue +26 -0
  55. package/src/Button/TextAlignRightButton.vue.js +56 -0
  56. package/src/Button/TextColorButton.vue +329 -0
  57. package/src/Button/TextColorButton.vue.js +243 -0
  58. package/src/Button/ThemeButton.vue +34 -0
  59. package/src/Button/ThemeButton.vue.js +63 -0
  60. package/src/Button/UnderLineButton.vue +29 -0
  61. package/src/Button/UnderLineButton.vue.js +56 -0
  62. package/src/Button/UndoButton.vue +29 -0
  63. package/src/Button/UndoButton.vue.js +55 -0
  64. package/src/Components/IconArrow.vue +16 -0
  65. package/src/Components/IconArrow.vue.js +30 -0
  66. package/src/Components/IconCheck.vue +40 -0
  67. package/src/Components/IconCheck.vue.js +59 -0
  68. package/src/EditorToolbar.vue +150 -0
  69. package/src/EditorToolbar.vue.js +306 -0
  70. package/src/Extensions/BulletListStyle.js +19 -0
  71. package/src/Extensions/BulletListStyle.ts +24 -0
  72. package/src/Extensions/FontSize.js +27 -0
  73. package/src/Extensions/FontSize.ts +37 -0
  74. package/src/Extensions/Indent.js +58 -0
  75. package/src/Extensions/Indent.ts +73 -0
  76. package/src/Extensions/OrderedListStyle.js +19 -0
  77. package/src/Extensions/OrderedListStyle.ts +24 -0
  78. package/src/Extensions/UploadImage.js +18 -0
  79. package/src/Extensions/UploadImage.ts +22 -0
  80. package/src/Extensions/shims.d.ts +26 -0
  81. package/src/RichEditor.vue +191 -0
  82. package/src/RichEditor.vue.js +199 -0
  83. package/src/env.d.ts +7 -0
  84. package/src/index.js +6 -0
  85. package/src/index.ts +11 -0
  86. package/src/main.js +4 -0
  87. package/src/main.ts +7 -0
  88. package/src/styles/style.scss +196 -0
  89. package/src/styles/theme.css +28 -0
  90. package/src/styles/variables.css +158 -0
  91. package/src/styles/variables.scss +175 -0
  92. package/src/types.js +1 -0
  93. package/src/types.ts +7 -0
  94. package/tsconfig.json +17 -0
  95. package/vite.config.ts +29 -0
@@ -0,0 +1,243 @@
1
+ import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
2
+ import IconCheck from '../components/IconCheck.vue';
3
+ const isOpen = ref(false);
4
+ const wrapperRef = ref(null);
5
+ const colorPalette = [
6
+ // 黑白灰
7
+ '#000000',
8
+ '#262626',
9
+ '#595959',
10
+ '#8C8C8C',
11
+ '#BFBFBF',
12
+ '#D9D9D9',
13
+ '#E9E9E9',
14
+ '#F5F5F5',
15
+ '#FAFAFA',
16
+ '#FFFFFF',
17
+ // 基础色
18
+ '#F5222D',
19
+ '#FA541C',
20
+ '#FA8C16',
21
+ '#FADB14',
22
+ '#52C41A',
23
+ '#13C2C2',
24
+ '#1890FF',
25
+ '#2F54EB',
26
+ '#722ED1',
27
+ '#EB2F96',
28
+ // 浅色系
29
+ '#FFE8E6',
30
+ '#FFECE0',
31
+ '#FFEF D1'.replace(' ', ''),
32
+ '#FCFCCA',
33
+ '#E4F7D2',
34
+ '#D3F5F0',
35
+ '#D4EEFC',
36
+ '#DEE8FC',
37
+ '#EFE1FA',
38
+ '#FAE1EB',
39
+ // 中色系
40
+ '#FFA39E',
41
+ '#FFBB96',
42
+ '#FFD591',
43
+ '#FFFB8F',
44
+ '#B7EB8F',
45
+ '#87E8DE',
46
+ '#91D5FF',
47
+ '#ADC6FF',
48
+ '#D3ADF7',
49
+ '#FFADD2',
50
+ // 深色系
51
+ '#FF4D4F',
52
+ '#FF7A45',
53
+ '#FFA940',
54
+ '#FFEC3D',
55
+ '#73D13D',
56
+ '#36CFC9',
57
+ '#40A9FF',
58
+ '#597EF7',
59
+ '#9254DE',
60
+ '#F759AB',
61
+ // 暗色系
62
+ '#CF1322',
63
+ '#D4380D',
64
+ '#D46B08',
65
+ '#D4B106',
66
+ '#389E0D',
67
+ '#08979C',
68
+ '#096DD9',
69
+ '#1D39C4',
70
+ '#531DAB',
71
+ '#C41D7F',
72
+ // 极深色
73
+ '#820014',
74
+ '#871400',
75
+ '#873800',
76
+ '#614700',
77
+ '#135200',
78
+ '#00474F',
79
+ '#003A8C',
80
+ '#061178',
81
+ '#22075E',
82
+ '#780650'
83
+ ];
84
+ const setColor = (color) => {
85
+ props.editor.chain().focus().setBackgroundColor(color).run();
86
+ isOpen.value = false;
87
+ };
88
+ const getColor = computed(() => {
89
+ if (!props.editor)
90
+ return '#fff';
91
+ const color = props.editor.getAttributes('textStyle').backgroundColor;
92
+ return color || '#000';
93
+ });
94
+ const props = defineProps({
95
+ editor: {
96
+ type: Object,
97
+ required: true
98
+ }
99
+ });
100
+ const handleClickOutside = (e) => {
101
+ if (!wrapperRef.value)
102
+ return;
103
+ if (!wrapperRef.value.contains(e.target)) {
104
+ isOpen.value = false;
105
+ }
106
+ };
107
+ onMounted(() => {
108
+ document.addEventListener('mousedown', handleClickOutside);
109
+ });
110
+ onBeforeUnmount(() => {
111
+ document.removeEventListener('mousedown', handleClickOutside);
112
+ });
113
+ const __VLS_ctx = {
114
+ ...{},
115
+ ...{},
116
+ ...{},
117
+ ...{},
118
+ };
119
+ let __VLS_components;
120
+ let __VLS_intrinsics;
121
+ let __VLS_directives;
122
+ /** @type {__VLS_StyleScopedClasses['icon']} */ ;
123
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
124
+ ...{ onClick: (...[$event]) => {
125
+ __VLS_ctx.isOpen = !__VLS_ctx.isOpen;
126
+ // @ts-ignore
127
+ [isOpen, isOpen,];
128
+ } },
129
+ ...{ class: "color-button" },
130
+ ref: "wrapperRef",
131
+ ...{ class: ({ 'open': __VLS_ctx.isOpen }) },
132
+ title: "背景颜色",
133
+ });
134
+ /** @type {__VLS_StyleScopedClasses['color-button']} */ ;
135
+ /** @type {__VLS_StyleScopedClasses['open']} */ ;
136
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
137
+ ...{ class: "trigger" },
138
+ });
139
+ /** @type {__VLS_StyleScopedClasses['trigger']} */ ;
140
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
141
+ ...{ class: "icon" },
142
+ });
143
+ /** @type {__VLS_StyleScopedClasses['icon']} */ ;
144
+ __VLS_asFunctionalElement1(__VLS_intrinsics.svg, __VLS_intrinsics.svg)({
145
+ xmlns: "http://www.w3.org/2000/svg",
146
+ viewBox: "0 0 512 512",
147
+ });
148
+ __VLS_asFunctionalElement1(__VLS_intrinsics.path)({
149
+ fill: "currentColor",
150
+ stroke: "currentColor",
151
+ 'stroke-width': "4",
152
+ 'stroke-linecap': "round",
153
+ 'stroke-linejoin': "round",
154
+ d: "M296 64c6.9 0 13.5 2.7 18.3 7.6L440.4 197.7c4.9 4.9 7.6 11.5 7.6 18.3s-2.7 13.5-7.6 18.3L386.7 288 65.3 288c1.3-3.9 3.4-7.4 6.3-10.3l96.4-96.4 33.4 33.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L213.3 136 277.7 71.6c4.9-4.9 11.5-7.6 18.3-7.6zM122.7 136L26.3 232.4C9.5 249.3 0 272.1 0 296s9.5 46.7 26.3 63.6L152.4 485.7C169.3 502.5 192.1 512 216 512s46.7-9.5 63.6-26.3L485.7 279.6C502.5 262.7 512 239.9 512 216s-9.5-46.7-26.3-63.6L359.6 26.3C342.7 9.5 319.9 0 296 0s-46.7 9.5-63.6 26.3L168 90.7 118.6 41.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L122.7 136z",
155
+ });
156
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
157
+ ...{ class: "bar" },
158
+ ...{ style: ({ backgroundColor: __VLS_ctx.getColor || '#000' }) },
159
+ });
160
+ /** @type {__VLS_StyleScopedClasses['bar']} */ ;
161
+ if (__VLS_ctx.isOpen) {
162
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
163
+ ...{ class: "dropdown" },
164
+ });
165
+ /** @type {__VLS_StyleScopedClasses['dropdown']} */ ;
166
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
167
+ ...{ class: "grid" },
168
+ });
169
+ /** @type {__VLS_StyleScopedClasses['grid']} */ ;
170
+ for (const [color] of __VLS_vFor((__VLS_ctx.colorPalette))) {
171
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
172
+ ...{ onClick: (...[$event]) => {
173
+ if (!(__VLS_ctx.isOpen))
174
+ return;
175
+ __VLS_ctx.setColor(color);
176
+ // @ts-ignore
177
+ [isOpen, isOpen, getColor, colorPalette, setColor,];
178
+ } },
179
+ key: (color),
180
+ ...{ class: "item" },
181
+ ...{ style: ({ backgroundColor: color }) },
182
+ title: (color),
183
+ });
184
+ /** @type {__VLS_StyleScopedClasses['item']} */ ;
185
+ if (__VLS_ctx.editor.isActive('textStyle', { color })) {
186
+ const __VLS_0 = IconCheck;
187
+ // @ts-ignore
188
+ const __VLS_1 = __VLS_asFunctionalComponent1(__VLS_0, new __VLS_0({
189
+ size: (10),
190
+ color: "#fff",
191
+ }));
192
+ const __VLS_2 = __VLS_1({
193
+ size: (10),
194
+ color: "#fff",
195
+ }, ...__VLS_functionalComponentArgsRest(__VLS_1));
196
+ }
197
+ // @ts-ignore
198
+ [editor,];
199
+ }
200
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
201
+ ...{ class: "footer" },
202
+ });
203
+ /** @type {__VLS_StyleScopedClasses['footer']} */ ;
204
+ __VLS_asFunctionalElement1(__VLS_intrinsics.label, __VLS_intrinsics.label)({});
205
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
206
+ ...{ class: "input" },
207
+ });
208
+ /** @type {__VLS_StyleScopedClasses['input']} */ ;
209
+ __VLS_asFunctionalElement1(__VLS_intrinsics.input)({
210
+ ...{ onInput: (...[$event]) => {
211
+ if (!(__VLS_ctx.isOpen))
212
+ return;
213
+ __VLS_ctx.editor.chain().focus().setBackgroundColor($event.target.value).run();
214
+ // @ts-ignore
215
+ [editor,];
216
+ } },
217
+ type: "color",
218
+ value: (__VLS_ctx.getColor),
219
+ });
220
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
221
+ ...{ onClick: (...[$event]) => {
222
+ if (!(__VLS_ctx.isOpen))
223
+ return;
224
+ __VLS_ctx.editor.chain().focus().unsetBackgroundColor().run();
225
+ ;
226
+ // @ts-ignore
227
+ [getColor, editor,];
228
+ } },
229
+ ...{ class: "button" },
230
+ });
231
+ /** @type {__VLS_StyleScopedClasses['button']} */ ;
232
+ }
233
+ // @ts-ignore
234
+ [];
235
+ const __VLS_export = (await import('vue')).defineComponent({
236
+ props: {
237
+ editor: {
238
+ type: Object,
239
+ required: true
240
+ }
241
+ },
242
+ });
243
+ export default {};
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <button
3
+ class="icon-button"
4
+ :class="{ 'active': editor.isActive('blockquote') }"
5
+ @click="editor.chain().focus().toggleBlockquote().run()" >
6
+
7
+ <div class="icon">
8
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
9
+ <path fill="currentColor" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M0 216C0 149.7 53.7 96 120 96l8 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-8 0c-30.9 0-56 25.1-56 56l0 8 64 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64l-64 0c-35.3 0-64-28.7-64-64L0 216zm256 0c0-66.3 53.7-120 120-120l8 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-8 0c-30.9 0-56 25.1-56 56l0 8 64 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64l-64 0c-35.3 0-64-28.7-64-64l0-136z"/>
10
+ </svg>
11
+ </div>
12
+
13
+ <div class="tips">引用</div>
14
+ </button>
15
+ </template>
16
+
17
+
18
+ <script setup>
19
+ const props = defineProps({
20
+ editor: {
21
+ type: Object,
22
+ required: true
23
+ }
24
+ })
25
+
26
+ </script>
@@ -0,0 +1,56 @@
1
+ const props = defineProps({
2
+ editor: {
3
+ type: Object,
4
+ required: true
5
+ }
6
+ });
7
+ const __VLS_ctx = {
8
+ ...{},
9
+ ...{},
10
+ ...{},
11
+ };
12
+ let __VLS_components;
13
+ let __VLS_intrinsics;
14
+ let __VLS_directives;
15
+ __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({
16
+ ...{ onClick: (...[$event]) => {
17
+ __VLS_ctx.editor.chain().focus().toggleBlockquote().run();
18
+ // @ts-ignore
19
+ [editor,];
20
+ } },
21
+ ...{ class: "icon-button" },
22
+ ...{ class: ({ 'active': __VLS_ctx.editor.isActive('blockquote') }) },
23
+ });
24
+ /** @type {__VLS_StyleScopedClasses['icon-button']} */ ;
25
+ /** @type {__VLS_StyleScopedClasses['active']} */ ;
26
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
27
+ ...{ class: "icon" },
28
+ });
29
+ /** @type {__VLS_StyleScopedClasses['icon']} */ ;
30
+ __VLS_asFunctionalElement1(__VLS_intrinsics.svg, __VLS_intrinsics.svg)({
31
+ xmlns: "http://www.w3.org/2000/svg",
32
+ viewBox: "0 0 448 512",
33
+ });
34
+ __VLS_asFunctionalElement1(__VLS_intrinsics.path)({
35
+ fill: "currentColor",
36
+ stroke: "currentColor",
37
+ 'stroke-width': "4",
38
+ 'stroke-linecap': "round",
39
+ 'stroke-linejoin': "round",
40
+ d: "M0 216C0 149.7 53.7 96 120 96l8 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-8 0c-30.9 0-56 25.1-56 56l0 8 64 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64l-64 0c-35.3 0-64-28.7-64-64L0 216zm256 0c0-66.3 53.7-120 120-120l8 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-8 0c-30.9 0-56 25.1-56 56l0 8 64 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64l-64 0c-35.3 0-64-28.7-64-64l0-136z",
41
+ });
42
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
43
+ ...{ class: "tips" },
44
+ });
45
+ /** @type {__VLS_StyleScopedClasses['tips']} */ ;
46
+ // @ts-ignore
47
+ [editor,];
48
+ const __VLS_export = (await import('vue')).defineComponent({
49
+ props: {
50
+ editor: {
51
+ type: Object,
52
+ required: true
53
+ }
54
+ },
55
+ });
56
+ export default {};
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <button
3
+ class="icon-button"
4
+ :class="{ 'active': editor.isActive('bold') }"
5
+ @click="editor.chain().focus().toggleBold().run()" >
6
+
7
+ <div class="icon">
8
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
9
+ <path fill="currentColor" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l32 0 0 320-32 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l224 0c70.7 0 128-57.3 128-128 0-46.5-24.8-87.3-62-109.7 18.7-22.3 30-51 30-82.3 0-70.7-57.3-128-128-128L32 32zM288 160c0 35.3-28.7 64-64 64l-96 0 0-128 96 0c35.3 0 64 28.7 64 64zM128 416l0-128 128 0c35.3 0 64 28.7 64 64s-28.7 64-64 64l-128 0z"/>
10
+ </svg>
11
+ </div>
12
+
13
+ <div class="tips">加粗</div>
14
+ </button>
15
+ </template>
16
+
17
+
18
+ <script setup>
19
+ const props = defineProps({
20
+ editor: {
21
+ type: Object,
22
+ required: true
23
+ }
24
+ })
25
+
26
+
27
+
28
+ </script>
29
+
@@ -0,0 +1,56 @@
1
+ const props = defineProps({
2
+ editor: {
3
+ type: Object,
4
+ required: true
5
+ }
6
+ });
7
+ const __VLS_ctx = {
8
+ ...{},
9
+ ...{},
10
+ ...{},
11
+ };
12
+ let __VLS_components;
13
+ let __VLS_intrinsics;
14
+ let __VLS_directives;
15
+ __VLS_asFunctionalElement1(__VLS_intrinsics.button, __VLS_intrinsics.button)({
16
+ ...{ onClick: (...[$event]) => {
17
+ __VLS_ctx.editor.chain().focus().toggleBold().run();
18
+ // @ts-ignore
19
+ [editor,];
20
+ } },
21
+ ...{ class: "icon-button" },
22
+ ...{ class: ({ 'active': __VLS_ctx.editor.isActive('bold') }) },
23
+ });
24
+ /** @type {__VLS_StyleScopedClasses['icon-button']} */ ;
25
+ /** @type {__VLS_StyleScopedClasses['active']} */ ;
26
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
27
+ ...{ class: "icon" },
28
+ });
29
+ /** @type {__VLS_StyleScopedClasses['icon']} */ ;
30
+ __VLS_asFunctionalElement1(__VLS_intrinsics.svg, __VLS_intrinsics.svg)({
31
+ xmlns: "http://www.w3.org/2000/svg",
32
+ viewBox: "0 0 512 512",
33
+ });
34
+ __VLS_asFunctionalElement1(__VLS_intrinsics.path)({
35
+ fill: "currentColor",
36
+ stroke: "currentColor",
37
+ 'stroke-width': "4",
38
+ 'stroke-linecap': "round",
39
+ 'stroke-linejoin': "round",
40
+ d: "M32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l32 0 0 320-32 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l224 0c70.7 0 128-57.3 128-128 0-46.5-24.8-87.3-62-109.7 18.7-22.3 30-51 30-82.3 0-70.7-57.3-128-128-128L32 32zM288 160c0 35.3-28.7 64-64 64l-96 0 0-128 96 0c35.3 0 64 28.7 64 64zM128 416l0-128 128 0c35.3 0 64 28.7 64 64s-28.7 64-64 64l-128 0z",
41
+ });
42
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
43
+ ...{ class: "tips" },
44
+ });
45
+ /** @type {__VLS_StyleScopedClasses['tips']} */ ;
46
+ // @ts-ignore
47
+ [editor,];
48
+ const __VLS_export = (await import('vue')).defineComponent({
49
+ props: {
50
+ editor: {
51
+ type: Object,
52
+ required: true
53
+ }
54
+ },
55
+ });
56
+ export default {};
@@ -0,0 +1,114 @@
1
+ <template>
2
+
3
+ <div class="dropdown-button list-button" ref="wrapperRef">
4
+ <div class="trigger" @click="isOpen = !isOpen" :class="{ 'open': isOpen, 'active': editor.isActive('bulletList') }">
5
+ <div class="icon">
6
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
7
+ <path fill="currentColor" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M48 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L192 64zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zM48 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM96 256a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z"/>
8
+ </svg>
9
+ </div>
10
+ </div>
11
+
12
+ <transition name="dropdown">
13
+ <div class="dropdown" v-show="isOpen">
14
+ <div
15
+ class="item"
16
+ v-for="item in list"
17
+ :key="item.value"
18
+ :class="{ 'is-selected': editor.isActive('bulletList') && editor.getAttributes('bulletList').listStyleType === item.value }"
19
+ @click="setBulletListStyle(item.value)">
20
+ <div class="icon">{{item.icon}}</div>
21
+ <span class="text">{{ item.label }}</span>
22
+ </div>
23
+ </div>
24
+ </transition>
25
+ </div>
26
+
27
+ </template>
28
+
29
+
30
+ <script setup>
31
+ import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
32
+
33
+
34
+ const isOpen = ref(false)
35
+ const wrapperRef = ref(null)
36
+
37
+ const list = [
38
+ { icon:'●', label: '实心圆', value: 'disc' },
39
+ { icon:'○', label: '空心圆', value: 'circle' },
40
+ { icon:'■', label: '方块', value: 'square' },
41
+ { icon:'', label: '无', value: 'none' },
42
+ ]
43
+
44
+
45
+ const setBulletListStyle = (value) => {
46
+ if(props.editor.isActive('bulletList') && value != 'none'){
47
+ props.editor.chain().focus()
48
+ .updateAttributes('bulletList', { listStyleType: value })
49
+ .run()
50
+ }else{
51
+ props.editor.chain().focus()
52
+ .toggleBulletList()
53
+ .updateAttributes('bulletList', { listStyleType: value })
54
+ .run()
55
+ }
56
+ isOpen.value = false
57
+ }
58
+
59
+
60
+
61
+ const sizeLabel = computed(() => {
62
+ if (!props.editor) return '16px'
63
+ const size = props.editor.getAttributes('textStyle').fontSize
64
+ return size || '16px'
65
+ })
66
+
67
+
68
+
69
+ const props = defineProps({
70
+ editor: {
71
+ type: Object,
72
+ required: true
73
+ }
74
+ })
75
+
76
+ const handleClickOutside = (e) => {
77
+ if (!wrapperRef.value) return
78
+
79
+ if (!wrapperRef.value.contains(e.target)) {
80
+ isOpen.value = false
81
+ }
82
+ }
83
+
84
+ onMounted(() => {
85
+ document.addEventListener('mousedown', handleClickOutside)
86
+ })
87
+
88
+ onBeforeUnmount(() => {
89
+ document.removeEventListener('mousedown', handleClickOutside)
90
+ })
91
+
92
+ </script>
93
+
94
+
95
+ <style lang="scss" scoped>
96
+
97
+ .list-button {
98
+
99
+ .dropdown {
100
+ .item {
101
+ .icon {
102
+ display: inline-flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ font-size: 12px;
106
+ }
107
+ }
108
+ }
109
+ }
110
+
111
+ </style>
112
+
113
+
114
+
@@ -0,0 +1,147 @@
1
+ import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
2
+ const isOpen = ref(false);
3
+ const wrapperRef = ref(null);
4
+ const list = [
5
+ { icon: '●', label: '实心圆', value: 'disc' },
6
+ { icon: '○', label: '空心圆', value: 'circle' },
7
+ { icon: '■', label: '方块', value: 'square' },
8
+ { icon: '', label: '无', value: 'none' },
9
+ ];
10
+ const setBulletListStyle = (value) => {
11
+ if (props.editor.isActive('bulletList') && value != 'none') {
12
+ props.editor.chain().focus()
13
+ .updateAttributes('bulletList', { listStyleType: value })
14
+ .run();
15
+ }
16
+ else {
17
+ props.editor.chain().focus()
18
+ .toggleBulletList()
19
+ .updateAttributes('bulletList', { listStyleType: value })
20
+ .run();
21
+ }
22
+ isOpen.value = false;
23
+ };
24
+ const sizeLabel = computed(() => {
25
+ if (!props.editor)
26
+ return '16px';
27
+ const size = props.editor.getAttributes('textStyle').fontSize;
28
+ return size || '16px';
29
+ });
30
+ const props = defineProps({
31
+ editor: {
32
+ type: Object,
33
+ required: true
34
+ }
35
+ });
36
+ const handleClickOutside = (e) => {
37
+ if (!wrapperRef.value)
38
+ return;
39
+ if (!wrapperRef.value.contains(e.target)) {
40
+ isOpen.value = false;
41
+ }
42
+ };
43
+ onMounted(() => {
44
+ document.addEventListener('mousedown', handleClickOutside);
45
+ });
46
+ onBeforeUnmount(() => {
47
+ document.removeEventListener('mousedown', handleClickOutside);
48
+ });
49
+ const __VLS_ctx = {
50
+ ...{},
51
+ ...{},
52
+ ...{},
53
+ ...{},
54
+ };
55
+ let __VLS_components;
56
+ let __VLS_intrinsics;
57
+ let __VLS_directives;
58
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
59
+ ...{ class: "dropdown-button list-button" },
60
+ ref: "wrapperRef",
61
+ });
62
+ /** @type {__VLS_StyleScopedClasses['dropdown-button']} */ ;
63
+ /** @type {__VLS_StyleScopedClasses['list-button']} */ ;
64
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
65
+ ...{ onClick: (...[$event]) => {
66
+ __VLS_ctx.isOpen = !__VLS_ctx.isOpen;
67
+ // @ts-ignore
68
+ [isOpen, isOpen,];
69
+ } },
70
+ ...{ class: "trigger" },
71
+ ...{ class: ({ 'open': __VLS_ctx.isOpen, 'active': __VLS_ctx.editor.isActive('bulletList') }) },
72
+ });
73
+ /** @type {__VLS_StyleScopedClasses['trigger']} */ ;
74
+ /** @type {__VLS_StyleScopedClasses['open']} */ ;
75
+ /** @type {__VLS_StyleScopedClasses['active']} */ ;
76
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
77
+ ...{ class: "icon" },
78
+ });
79
+ /** @type {__VLS_StyleScopedClasses['icon']} */ ;
80
+ __VLS_asFunctionalElement1(__VLS_intrinsics.svg, __VLS_intrinsics.svg)({
81
+ xmlns: "http://www.w3.org/2000/svg",
82
+ viewBox: "0 0 512 512",
83
+ });
84
+ __VLS_asFunctionalElement1(__VLS_intrinsics.path)({
85
+ fill: "currentColor",
86
+ stroke: "currentColor",
87
+ 'stroke-width': "4",
88
+ 'stroke-linecap': "round",
89
+ 'stroke-linejoin': "round",
90
+ d: "M48 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L192 64zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zM48 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM96 256a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z",
91
+ });
92
+ let __VLS_0;
93
+ /** @ts-ignore @type {typeof __VLS_components.transition | typeof __VLS_components.Transition | typeof __VLS_components.transition | typeof __VLS_components.Transition} */
94
+ transition;
95
+ // @ts-ignore
96
+ const __VLS_1 = __VLS_asFunctionalComponent1(__VLS_0, new __VLS_0({
97
+ name: "dropdown",
98
+ }));
99
+ const __VLS_2 = __VLS_1({
100
+ name: "dropdown",
101
+ }, ...__VLS_functionalComponentArgsRest(__VLS_1));
102
+ const { default: __VLS_5 } = __VLS_3.slots;
103
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
104
+ ...{ class: "dropdown" },
105
+ });
106
+ __VLS_asFunctionalDirective(__VLS_directives.vShow, {})(null, { ...__VLS_directiveBindingRestFields, value: (__VLS_ctx.isOpen) }, null, null);
107
+ /** @type {__VLS_StyleScopedClasses['dropdown']} */ ;
108
+ for (const [item] of __VLS_vFor((__VLS_ctx.list))) {
109
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
110
+ ...{ onClick: (...[$event]) => {
111
+ __VLS_ctx.setBulletListStyle(item.value);
112
+ // @ts-ignore
113
+ [isOpen, isOpen, editor, list, setBulletListStyle,];
114
+ } },
115
+ ...{ class: "item" },
116
+ key: (item.value),
117
+ ...{ class: ({ 'is-selected': __VLS_ctx.editor.isActive('bulletList') && __VLS_ctx.editor.getAttributes('bulletList').listStyleType === item.value }) },
118
+ });
119
+ /** @type {__VLS_StyleScopedClasses['item']} */ ;
120
+ /** @type {__VLS_StyleScopedClasses['is-selected']} */ ;
121
+ __VLS_asFunctionalElement1(__VLS_intrinsics.div, __VLS_intrinsics.div)({
122
+ ...{ class: "icon" },
123
+ });
124
+ /** @type {__VLS_StyleScopedClasses['icon']} */ ;
125
+ (item.icon);
126
+ __VLS_asFunctionalElement1(__VLS_intrinsics.span, __VLS_intrinsics.span)({
127
+ ...{ class: "text" },
128
+ });
129
+ /** @type {__VLS_StyleScopedClasses['text']} */ ;
130
+ (item.label);
131
+ // @ts-ignore
132
+ [editor, editor,];
133
+ }
134
+ // @ts-ignore
135
+ [];
136
+ var __VLS_3;
137
+ // @ts-ignore
138
+ [];
139
+ const __VLS_export = (await import('vue')).defineComponent({
140
+ props: {
141
+ editor: {
142
+ type: Object,
143
+ required: true
144
+ }
145
+ },
146
+ });
147
+ export default {};