@bagelink/vue 0.0.974 → 0.0.980

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.
@@ -1,420 +0,0 @@
1
- <script setup lang="ts">
2
- import type { MaterialIcons } from '@bagelink/vue'
3
- import {
4
- FileUpload as $el,
5
- BglVideo,
6
- Btn,
7
- bagelFormUtils,
8
- useModal,
9
- } from '@bagelink/vue'
10
- import Image from '@tiptap/extension-image'
11
- import Table from '@tiptap/extension-table'
12
- import TableCell from '@tiptap/extension-table-cell'
13
- import TableHeader from '@tiptap/extension-table-header'
14
- import TableRow from '@tiptap/extension-table-row'
15
- import YouTube from '@tiptap/extension-youtube'
16
- import StarterKit from '@tiptap/starter-kit'
17
- import { Editor, EditorContent } from '@tiptap/vue-3'
18
- import { onBeforeUnmount, onMounted, watch } from 'vue'
19
-
20
- const props = defineProps<{ modelValue: string }>()
21
- const emit = defineEmits(['update:modelValue'])
22
- // import $el from './FileUploadURL.vue';
23
- const { txtField } = bagelFormUtils
24
- let editor = $ref<Editor>()
25
-
26
- function focus() {
27
- if (!editor) throw new Error('editor is not defined')
28
- return editor.chain().focus()
29
- }
30
- const { showModalForm } = useModal()
31
-
32
- Image.configure({
33
- inline: true,
34
- allowBase64: true,
35
- })
36
-
37
- function addImage() {
38
- showModalForm({
39
- title: 'Add Image',
40
- schema: [
41
- txtField('title', 'Title'),
42
- { $el, id: 'src', attrs: { bindkey: 'url' } },
43
- txtField('alt', 'Alt Text'),
44
- ],
45
- onSubmit: imgObj => focus().setImage(imgObj).run(),
46
- })
47
- }
48
-
49
- const config: {
50
- name: string
51
- command: any
52
- icon: MaterialIcons
53
- option?: { [key: string]: any }
54
- disabled?: () => boolean
55
- }[] = [
56
- {
57
- name: 'Bold',
58
- command: () => focus().toggleBold().run(),
59
- icon: 'format_bold',
60
- disabled: () => !editor?.can().chain().focus().toggleBold().run(),
61
- },
62
- {
63
- name: 'Italic',
64
- command: () => focus().toggleItalic().run(),
65
- icon: 'format_italic',
66
- disabled: () => !editor?.can().chain().focus().toggleItalic().run(),
67
- },
68
- {
69
- name: 'Strike',
70
- command: () => focus().toggleStrike().run(),
71
- icon: 'format_strikethrough',
72
- disabled: () => !editor?.can().chain().focus().toggleStrike().run(),
73
- },
74
- {
75
- name: 'Code Text',
76
- command: () => focus().toggleCode().run(),
77
- icon: 'code',
78
- },
79
- {
80
- name: 'Image',
81
- command: addImage,
82
- icon: 'image',
83
- },
84
- {
85
- name: 'YouTube',
86
- command: () => {
87
- showModalForm({
88
- title: 'Add YouTube Video',
89
- schema: [
90
- txtField('src', 'YouTube URL'),
91
- {
92
- $el: BglVideo,
93
- attrs: { src: (_: any, { src }: { src: string }) => src || '' },
94
- },
95
- ],
96
- onSubmit: videoObj => editor?.commands.setYoutubeVideo(videoObj),
97
- })
98
- },
99
- icon: 'youtube_activity',
100
- },
101
- {
102
- name: 'Clear',
103
- command: () => focus().clearNodes().run(),
104
- icon: 'format_clear',
105
- },
106
- {
107
- name: 'Paragraph',
108
- command: () => focus().setParagraph().run(),
109
- icon: 'format_paragraph',
110
- },
111
- {
112
- name: 'Heading',
113
- command: () => focus().toggleHeading({ level: 1 }).run(),
114
- icon: 'format_h1',
115
- option: { level: 1 },
116
- },
117
- {
118
- name: 'Heading',
119
- command: () => focus().toggleHeading({ level: 2 }).run(),
120
- icon: 'format_h2',
121
- option: { level: 2 },
122
- },
123
- {
124
- name: 'Heading',
125
- command: () => focus().toggleHeading({ level: 3 }).run(),
126
- icon: 'format_h3',
127
- option: { level: 3 },
128
- },
129
- {
130
- name: 'Heading',
131
- command: () => focus().toggleHeading({ level: 4 }).run(),
132
- icon: 'format_h4',
133
- option: { level: 4 },
134
- },
135
- {
136
- name: 'Heading',
137
- command: () => focus().toggleHeading({ level: 5 }).run(),
138
- icon: 'format_h5',
139
- option: { level: 5 },
140
- },
141
- {
142
- name: 'Heading',
143
- command: () => focus().toggleHeading({ level: 6 }).run(),
144
- icon: 'format_h6',
145
- option: { level: 6 },
146
- },
147
- {
148
- name: 'Bullet List',
149
- command: () => focus().toggleBulletList().run(),
150
- icon: 'format_list_bulleted',
151
- },
152
- {
153
- name: 'Ordered List',
154
- command: () => focus().toggleOrderedList().run(),
155
- icon: 'format_list_numbered',
156
- },
157
- {
158
- name: 'Code Block',
159
- command: () => focus().toggleCodeBlock().run(),
160
- icon: 'code_blocks',
161
- },
162
- {
163
- name: 'Blockquote',
164
- command: () => focus().toggleBlockquote().run(),
165
- icon: 'format_quote',
166
- },
167
- {
168
- name: 'Horizontal Rule',
169
- command: () => focus().setHorizontalRule().run(),
170
- icon: 'horizontal_rule',
171
- },
172
- {
173
- name: 'Hard Break',
174
- command: () => focus().setHardBreak().run(),
175
- icon: 'keyboard_return',
176
- },
177
- {
178
- name: 'Table',
179
- command: () => editor
180
- ?.chain()
181
- .focus()
182
- .insertTable({ rows: 3, cols: 3, withHeaderRow: true })
183
- .run(),
184
- icon: 'table_chart',
185
- },
186
- {
187
- name: 'Undo',
188
- command: () => focus().undo().run(),
189
- icon: 'undo',
190
- disabled: () => !editor?.can().chain().focus().undo().run(),
191
- },
192
- {
193
- name: 'Redo',
194
- command: () => focus().redo().run(),
195
- icon: 'redo',
196
- disabled: () => !editor?.can().chain().focus().redo().run(),
197
- },
198
- ]
199
-
200
- function initEditor() {
201
- editor = new Editor({
202
- extensions: [
203
- StarterKit,
204
- Image,
205
- YouTube,
206
- Table,
207
- TableRow,
208
- TableCell,
209
- TableHeader,
210
- ],
211
- content: props.modelValue,
212
- onUpdate: ({ editor }) => { emit('update:modelValue', editor.getHTML()) },
213
- })
214
- }
215
-
216
- watch(
217
- () => props.modelValue,
218
- (value) => {
219
- if (editor?.getHTML() === value) return
220
- editor?.commands.setContent(value, false)
221
- },
222
- { immediate: true },
223
- )
224
-
225
- onMounted(initEditor)
226
-
227
- onBeforeUnmount(() => editor?.destroy())
228
- </script>
229
-
230
- <template>
231
- <div class="RichText">
232
- <div v-if="editor" class="RichText-tools">
233
- <Btn
234
- v-for="item in config"
235
- :key="item.name"
236
- v-tooltip="item.name"
237
- tabindex="-1"
238
- :flat="!editor.isActive(item.name, item.option)"
239
- thin
240
- :icon="item.icon"
241
- :disabled="item.disabled?.()"
242
- @click="item.command"
243
- />
244
- </div>
245
- <EditorContent :editor="editor" />
246
- </div>
247
- </template>
248
-
249
- <style>
250
- /* Basic editor styles */
251
- .tiptap > * + * {
252
- margin-top: 0.75em;
253
- }
254
-
255
- .tiptap ul,
256
- .tiptap ol {
257
- padding: 0 1rem;
258
- }
259
-
260
- .tiptap h1,
261
- .tiptap h2 {
262
- line-height: 1;
263
- }
264
-
265
- .tiptap h3,
266
- .tiptap h4,
267
- .tiptap h5,
268
- .tiptap h6 {
269
- line-height: 1.1;
270
- }
271
-
272
- .tiptap pre {
273
- background: #0d0d0d;
274
- color: var(--bgl-light-text);
275
- font-family: 'JetBrainsMono', monospace;
276
- padding: 0.75rem 1rem;
277
- border-radius: 0.5rem;
278
- margin: 0;
279
- }
280
-
281
- .tiptap pre code {
282
- color: inherit;
283
- padding: 0;
284
- background: none;
285
- font-size: 0.8rem;
286
- }
287
-
288
- .tiptap img {
289
- max-width: 100%;
290
- height: auto;
291
- }
292
-
293
- .tiptap blockquote {
294
- padding-inline-start: 0.5rem;
295
- border-inline-start: 2px solid var(--border-color);
296
- margin: 0.5rem
297
- }
298
-
299
- .tiptap hr {
300
- border: none;
301
- border-top: 2px solid var(--border-color);
302
- margin: 1rem 0;
303
- }
304
-
305
- .tiptap {
306
- min-height: 200px;
307
- background: var(--input-bg);
308
- overflow: auto;
309
- max-height: 500px;
310
- padding: 0.7rem;
311
- color: var(--input-color);
312
- border-radius: var(--input-border-radius);
313
- font-size: var(--input-font-size);
314
- line-height: 1.5;
315
- }
316
- .tiptap.ProseMirror-focused {
317
- outline: none;
318
- box-shadow: inset 0 0 10px #00000012;
319
- }
320
- .RichText {
321
- margin-bottom: 0.5rem;
322
- }
323
- .RichText-tools {
324
- background: var(--input-bg);
325
- margin-bottom: 0.125rem;
326
- border-radius: var(--input-border-radius);
327
- }
328
-
329
- .tiptap {
330
- table {
331
- border-collapse: collapse;
332
- table-layout: fixed;
333
- width: 100%;
334
- margin: 0;
335
- overflow: hidden;
336
-
337
- td,
338
- th {
339
- min-width: 1em;
340
- border: 2px solid var(--border-color);
341
- padding: 3px 5px;
342
- vertical-align: top;
343
- box-sizing: border-box;
344
- position: relative;
345
-
346
- > * {
347
- margin-bottom: 0;
348
- margin-top: 0;
349
- }
350
- }
351
-
352
- th {
353
- font-weight: bold;
354
- text-align: start;
355
- background-color: var(--bgl-gray-80);
356
- }
357
-
358
- .selectedCell:after {
359
- z-index: 2;
360
- position: absolute;
361
- content: '';
362
- left: 0;
363
- right: 0;
364
- top: 0;
365
- bottom: 0;
366
- background: var(--bgl-gray-20);
367
- pointer-events: none;
368
- }
369
- .selectedCell p::selection{
370
- color: var(--bgl-popup-text)
371
- }
372
-
373
- .column-resize-handle {
374
- position: absolute;
375
- inset-inline-start: -2px;
376
- top: 0;
377
- bottom: -2px;
378
- width: 4px;
379
- background-color: #adf;
380
- pointer-events: none;
381
- }
382
-
383
- p {
384
- margin: 0;
385
- }
386
- }
387
- }
388
-
389
- .tableWrapper {
390
- padding: 1rem 0;
391
- overflow-x: auto;
392
- }
393
-
394
- .resize-cursor {
395
- cursor: ew-resize;
396
- cursor: col-resize;
397
- }
398
- .RichText-tools [disabled]{
399
- color: var(--bgl-popup-text) !important;
400
- opacity: 0.3;
401
- }
402
- .RichText iframe{
403
- width: 100%;
404
- max-width: 700px;
405
- margin: 0 auto;
406
- height: auto;
407
- display: block;
408
- border-radius: var(--input-border-radius);
409
- border: none;
410
- aspect-ratio: 16/9;
411
- }
412
- .RichText img{
413
- width: 100%;
414
- max-width: 700px;
415
- margin: 0 auto;
416
- height: auto;
417
- display: block;
418
- border-radius: var(--input-border-radius);
419
- }
420
- </style>