@kvass/rich-text 1.3.2 → 1.4.0
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.
package/package.json
CHANGED
package/src/Component.vue
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="richtext">
|
|
3
|
-
<BubbleMenu v-if="editor" :editor="editor">
|
|
4
|
-
<div class="richtext__bubble">
|
|
2
|
+
<div class="richtext" :class="{ 'richtext--disabled': disabled }">
|
|
3
|
+
<BubbleMenu v-if="editor" :editor="editor" :should-show="bubbleShouldShow">
|
|
4
|
+
<div ref="bubble" class="richtext__bubble">
|
|
5
5
|
<form
|
|
6
6
|
class="richtext__bubble-form"
|
|
7
|
-
v-
|
|
7
|
+
v-show="['link', 'cta'].includes(bubbleState)"
|
|
8
8
|
@submit.prevent="setLink(linkUrl)"
|
|
9
9
|
>
|
|
10
10
|
<input
|
|
@@ -13,9 +13,15 @@
|
|
|
13
13
|
v-model="linkUrl"
|
|
14
14
|
placeholder="https://"
|
|
15
15
|
ref="linkInput"
|
|
16
|
-
autofocus
|
|
17
16
|
@keydown.esc="bubbleState = null"
|
|
18
17
|
/>
|
|
18
|
+
<select v-if="bubbleState === 'cta'" v-model="bubbleOptions.theme">
|
|
19
|
+
<option value="primary">{{ labels.primary }}</option>
|
|
20
|
+
<option value="secondary">{{ labels.secondary }}</option>
|
|
21
|
+
</select>
|
|
22
|
+
<button @click="setLink(linkUrl)" :disabled="!linkUrl" type="button">
|
|
23
|
+
<FontAwesomeIcon :icon="['far', 'check']" />
|
|
24
|
+
</button>
|
|
19
25
|
<button @click="setLink(null)" type="button">
|
|
20
26
|
<FontAwesomeIcon :icon="['far', 'times']" />
|
|
21
27
|
</button>
|
|
@@ -25,7 +31,9 @@
|
|
|
25
31
|
<button
|
|
26
32
|
v-for="(item, index) in getCommands('bubble')"
|
|
27
33
|
:key="'bubble' + index"
|
|
34
|
+
class="richtext__bubble-button"
|
|
28
35
|
:class="{ 'is-active': editor.isActive(item.stateKey) }"
|
|
36
|
+
:disabled="disabled || item.disabled"
|
|
29
37
|
@click="
|
|
30
38
|
item.customFunc
|
|
31
39
|
? item.customFunc()
|
|
@@ -39,19 +47,26 @@
|
|
|
39
47
|
</div>
|
|
40
48
|
</BubbleMenu>
|
|
41
49
|
|
|
42
|
-
<
|
|
43
|
-
<button
|
|
44
|
-
v-for="(item, index) in getCommands('menu')"
|
|
45
|
-
:key="'menubar' + index"
|
|
46
|
-
type="button"
|
|
47
|
-
:class="{ 'is-active': editor.isActive(item.stateKey) }"
|
|
48
|
-
@click="editor.chain().focus()[item.commandKey](item.commandProps).run()"
|
|
49
|
-
>
|
|
50
|
-
<FontAwesomeIcon :icon="item.icon" size="sm" />
|
|
51
|
-
</button>
|
|
52
|
-
</div>
|
|
50
|
+
<EditorContent class="richtext__editor" ref="editor" :editor="editor" :editable="!disabled" />
|
|
53
51
|
|
|
54
|
-
<
|
|
52
|
+
<div v-if="editor" class="richtext__menubar">
|
|
53
|
+
<div class="richtext__menubar-buttons">
|
|
54
|
+
<button
|
|
55
|
+
v-for="(item, index) in getCommands('menu')"
|
|
56
|
+
:key="'menubar' + index"
|
|
57
|
+
type="button"
|
|
58
|
+
:class="{ 'is-active': editor.isActive(item.stateKey) }"
|
|
59
|
+
:disabled="disabled || item.disabled"
|
|
60
|
+
@click="
|
|
61
|
+
item.customFunc
|
|
62
|
+
? item.customFunc()
|
|
63
|
+
: editor.chain().focus()[item.commandKey](item.commandProps).run()
|
|
64
|
+
"
|
|
65
|
+
>
|
|
66
|
+
<FontAwesomeIcon :icon="item.icon" size="sm" />
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
55
70
|
</div>
|
|
56
71
|
</template>
|
|
57
72
|
|
|
@@ -59,10 +74,11 @@
|
|
|
59
74
|
import { Editor, EditorContent, BubbleMenu } from '@tiptap/vue-2'
|
|
60
75
|
import Link from '@tiptap/extension-link'
|
|
61
76
|
import Image from '@tiptap/extension-image'
|
|
62
|
-
import CallToAction from './extensions/
|
|
77
|
+
import CallToAction from './extensions/cta'
|
|
63
78
|
import StarterKit from '@tiptap/starter-kit'
|
|
64
79
|
|
|
65
80
|
const DefaultCommands = ['heading', 'bold', 'italic', 'orderedList', 'bulletList', 'link', 'cta']
|
|
81
|
+
const DefaultLabels = { primary: 'Primær', secondary: 'Sekundær' }
|
|
66
82
|
|
|
67
83
|
export { DefaultCommands }
|
|
68
84
|
export default {
|
|
@@ -76,18 +92,32 @@ export default {
|
|
|
76
92
|
type: Array,
|
|
77
93
|
default: () => DefaultCommands,
|
|
78
94
|
},
|
|
95
|
+
labels: {
|
|
96
|
+
type: Object,
|
|
97
|
+
default: () => DefaultLabels,
|
|
98
|
+
},
|
|
79
99
|
},
|
|
80
100
|
watch: {
|
|
81
101
|
value(value) {
|
|
82
102
|
if (this.editor.getHTML() === value) return
|
|
83
103
|
this.editor.commands.setContent(this.value, false)
|
|
84
104
|
},
|
|
105
|
+
disabled(value) {
|
|
106
|
+
if (!this.editor) return
|
|
107
|
+
this.editor.setOptions({ editable: !value })
|
|
108
|
+
},
|
|
109
|
+
bubbleState(value) {
|
|
110
|
+
if (!value) return
|
|
111
|
+
this.$refs.editor.$el.children[0].focus()
|
|
112
|
+
setTimeout(() => this.$refs.linkInput.focus(), 1)
|
|
113
|
+
},
|
|
85
114
|
},
|
|
86
115
|
data() {
|
|
87
116
|
return {
|
|
88
117
|
editor: null,
|
|
89
118
|
linkUrl: null,
|
|
90
119
|
bubbleState: null,
|
|
120
|
+
bubbleOptions: { theme: 'primary' },
|
|
91
121
|
}
|
|
92
122
|
},
|
|
93
123
|
computed: {
|
|
@@ -109,7 +139,7 @@ export default {
|
|
|
109
139
|
icon: ['far', 'bold'],
|
|
110
140
|
appearance: {
|
|
111
141
|
menu: true,
|
|
112
|
-
bubble:
|
|
142
|
+
bubble: false,
|
|
113
143
|
},
|
|
114
144
|
},
|
|
115
145
|
{
|
|
@@ -118,7 +148,7 @@ export default {
|
|
|
118
148
|
icon: ['far', 'italic'],
|
|
119
149
|
appearance: {
|
|
120
150
|
menu: true,
|
|
121
|
-
bubble:
|
|
151
|
+
bubble: false,
|
|
122
152
|
},
|
|
123
153
|
},
|
|
124
154
|
{
|
|
@@ -145,10 +175,11 @@ export default {
|
|
|
145
175
|
customFunc: () => {
|
|
146
176
|
this.bubbleState = 'link'
|
|
147
177
|
},
|
|
178
|
+
disabled: this.editor.state.selection.empty,
|
|
148
179
|
icon: ['far', 'link'],
|
|
149
180
|
appearance: {
|
|
150
|
-
menu:
|
|
151
|
-
bubble:
|
|
181
|
+
menu: true,
|
|
182
|
+
bubble: false,
|
|
152
183
|
},
|
|
153
184
|
},
|
|
154
185
|
{
|
|
@@ -167,10 +198,11 @@ export default {
|
|
|
167
198
|
customFunc: () => {
|
|
168
199
|
this.bubbleState = 'cta'
|
|
169
200
|
},
|
|
201
|
+
disabled: this.editor.state.selection.empty,
|
|
170
202
|
icon: ['far', 'mouse-pointer'],
|
|
171
203
|
appearance: {
|
|
172
|
-
menu:
|
|
173
|
-
bubble:
|
|
204
|
+
menu: true,
|
|
205
|
+
bubble: false,
|
|
174
206
|
},
|
|
175
207
|
},
|
|
176
208
|
]
|
|
@@ -191,7 +223,7 @@ export default {
|
|
|
191
223
|
else editor.unsetLink().run()
|
|
192
224
|
break
|
|
193
225
|
case 'cta':
|
|
194
|
-
if (value) editor.setCta({ href: value }).run()
|
|
226
|
+
if (value) editor.setCta({ href: value, 'data-cta': this.bubbleOptions.theme }).run()
|
|
195
227
|
else editor.unsetCta().run()
|
|
196
228
|
break
|
|
197
229
|
}
|
|
@@ -199,6 +231,14 @@ export default {
|
|
|
199
231
|
this.bubbleState = null
|
|
200
232
|
this.linkUrl = null
|
|
201
233
|
},
|
|
234
|
+
bubbleShouldShow({ editor }) {
|
|
235
|
+
return (
|
|
236
|
+
this.availableCommands
|
|
237
|
+
.filter(a => a.appearance.bubble)
|
|
238
|
+
.map(a => a.stateKey)
|
|
239
|
+
.some(k => editor.isActive(k)) || !this.editor.state.selection.empty
|
|
240
|
+
)
|
|
241
|
+
},
|
|
202
242
|
},
|
|
203
243
|
mounted() {
|
|
204
244
|
this.editor = new Editor({
|
|
@@ -226,11 +266,25 @@ export default {
|
|
|
226
266
|
@import './styles/_mixins';
|
|
227
267
|
.richtext {
|
|
228
268
|
flex-grow: 1;
|
|
269
|
+
display: flex;
|
|
270
|
+
flex-direction: column-reverse;
|
|
271
|
+
|
|
272
|
+
&--disabled {
|
|
273
|
+
background-color: var(--vue-elder-input-color, #fafafa);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
&:not(.richtext--disabled):focus-within {
|
|
277
|
+
outline: 1px solid var(--primary);
|
|
278
|
+
border-radius: var(--border-radius, 3px);
|
|
279
|
+
}
|
|
229
280
|
|
|
230
281
|
&__editor {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
282
|
+
flex-grow: 1;
|
|
283
|
+
|
|
284
|
+
.ProseMirror {
|
|
285
|
+
padding: 0rem 1rem 1rem;
|
|
286
|
+
min-height: 6rem;
|
|
287
|
+
height: 100%;
|
|
234
288
|
|
|
235
289
|
p:first-child {
|
|
236
290
|
margin-top: 0;
|
|
@@ -244,48 +298,69 @@ export default {
|
|
|
244
298
|
}
|
|
245
299
|
|
|
246
300
|
&:focus {
|
|
247
|
-
outline:
|
|
248
|
-
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
|
301
|
+
outline: none;
|
|
249
302
|
}
|
|
250
303
|
|
|
251
304
|
img {
|
|
252
305
|
max-width: 100%;
|
|
253
306
|
}
|
|
254
307
|
|
|
255
|
-
a[data-cta
|
|
256
|
-
background-color: var(--primary);
|
|
257
|
-
color: white;
|
|
308
|
+
a[data-cta] {
|
|
258
309
|
padding: 0.75em 1.5em;
|
|
259
310
|
border-radius: var(--border-radius);
|
|
260
311
|
text-decoration: none;
|
|
261
312
|
|
|
262
313
|
display: inline-block;
|
|
263
314
|
}
|
|
264
|
-
}
|
|
265
315
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
316
|
+
a[data-cta='primary'] {
|
|
317
|
+
background-color: var(--primary);
|
|
318
|
+
color: var(--primary-contrast);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
a[data-cta='secondary'] {
|
|
322
|
+
background-color: var(--secondary);
|
|
323
|
+
color: var(--secondary-contrast);
|
|
324
|
+
}
|
|
269
325
|
}
|
|
270
326
|
}
|
|
271
327
|
|
|
272
328
|
&__bubble {
|
|
273
329
|
display: flex;
|
|
274
330
|
background-color: var(--dark);
|
|
331
|
+
color: white;
|
|
275
332
|
border-radius: var(--border-radius);
|
|
276
333
|
|
|
277
334
|
&-form {
|
|
278
335
|
display: flex;
|
|
279
336
|
|
|
337
|
+
button,
|
|
338
|
+
select {
|
|
339
|
+
background-color: transparent;
|
|
340
|
+
color: inherit;
|
|
341
|
+
border: none;
|
|
342
|
+
border-left: 1px solid rgba(white, 0.1);
|
|
343
|
+
}
|
|
344
|
+
|
|
280
345
|
button {
|
|
281
|
-
padding: 0.5rem
|
|
346
|
+
padding: 0.5rem;
|
|
347
|
+
min-width: 2.5rem;
|
|
348
|
+
|
|
349
|
+
&:disabled {
|
|
350
|
+
opacity: 0.5;
|
|
351
|
+
background-color: rgba(white, 0.1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
select {
|
|
356
|
+
padding: 0.5rem !important;
|
|
282
357
|
}
|
|
283
358
|
}
|
|
284
359
|
|
|
285
360
|
&-input {
|
|
286
361
|
font: inherit;
|
|
287
362
|
border: none;
|
|
288
|
-
padding:
|
|
363
|
+
padding: 0.5rem;
|
|
289
364
|
background-color: transparent;
|
|
290
365
|
color: #fff !important;
|
|
291
366
|
|
|
@@ -294,9 +369,8 @@ export default {
|
|
|
294
369
|
}
|
|
295
370
|
}
|
|
296
371
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
width: initial !important;
|
|
372
|
+
&__button {
|
|
373
|
+
width: initial;
|
|
300
374
|
padding: 0.5rem 0.75rem !important;
|
|
301
375
|
color: white;
|
|
302
376
|
|
|
@@ -316,21 +390,60 @@ export default {
|
|
|
316
390
|
}
|
|
317
391
|
|
|
318
392
|
&__menubar {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
393
|
+
padding: 0.75rem;
|
|
394
|
+
position: sticky;
|
|
395
|
+
top: 0;
|
|
396
|
+
z-index: 1;
|
|
397
|
+
|
|
398
|
+
&-buttons {
|
|
399
|
+
width: max-content;
|
|
400
|
+
box-shadow: 0 2px 4px -2px rgba(black, 0.1);
|
|
401
|
+
}
|
|
322
402
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
403
|
+
button {
|
|
404
|
+
padding: 0.5rem;
|
|
405
|
+
min-width: 2.5rem;
|
|
406
|
+
border: 1px solid var(--border-color);
|
|
407
|
+
cursor: pointer;
|
|
408
|
+
background-color: #ffffff;
|
|
329
409
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
410
|
+
&:focus-visible {
|
|
411
|
+
position: relative;
|
|
412
|
+
border-radius: var(--border-radius, 3px);
|
|
413
|
+
outline: 1px solid var(--primary) !important;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
&:first-child {
|
|
417
|
+
border-top-left-radius: var(--border-radius, 3px);
|
|
418
|
+
border-bottom-left-radius: var(--border-radius, 3px);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
&:last-child {
|
|
422
|
+
border-top-right-radius: var(--border-radius, 3px);
|
|
423
|
+
border-bottom-right-radius: var(--border-radius, 3px);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
& + button {
|
|
427
|
+
border-left: none;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
&:disabled {
|
|
431
|
+
cursor: not-allowed;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
&:hover:not(:disabled),
|
|
435
|
+
&.is-active {
|
|
436
|
+
background-color: darken(#ffffff, 3%);
|
|
437
|
+
}
|
|
333
438
|
}
|
|
334
439
|
}
|
|
440
|
+
|
|
441
|
+
a {
|
|
442
|
+
word-break: break-all;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.tippy-box {
|
|
446
|
+
max-width: initial !important;
|
|
447
|
+
}
|
|
335
448
|
}
|
|
336
449
|
</style>
|
|
File without changes
|