@kvass/rich-text 1.3.4 → 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
|
|
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,6 +92,10 @@ 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) {
|
|
@@ -86,12 +106,18 @@ export default {
|
|
|
86
106
|
if (!this.editor) return
|
|
87
107
|
this.editor.setOptions({ editable: !value })
|
|
88
108
|
},
|
|
109
|
+
bubbleState(value) {
|
|
110
|
+
if (!value) return
|
|
111
|
+
this.$refs.editor.$el.children[0].focus()
|
|
112
|
+
setTimeout(() => this.$refs.linkInput.focus(), 1)
|
|
113
|
+
},
|
|
89
114
|
},
|
|
90
115
|
data() {
|
|
91
116
|
return {
|
|
92
117
|
editor: null,
|
|
93
118
|
linkUrl: null,
|
|
94
119
|
bubbleState: null,
|
|
120
|
+
bubbleOptions: { theme: 'primary' },
|
|
95
121
|
}
|
|
96
122
|
},
|
|
97
123
|
computed: {
|
|
@@ -113,7 +139,7 @@ export default {
|
|
|
113
139
|
icon: ['far', 'bold'],
|
|
114
140
|
appearance: {
|
|
115
141
|
menu: true,
|
|
116
|
-
bubble:
|
|
142
|
+
bubble: false,
|
|
117
143
|
},
|
|
118
144
|
},
|
|
119
145
|
{
|
|
@@ -122,7 +148,7 @@ export default {
|
|
|
122
148
|
icon: ['far', 'italic'],
|
|
123
149
|
appearance: {
|
|
124
150
|
menu: true,
|
|
125
|
-
bubble:
|
|
151
|
+
bubble: false,
|
|
126
152
|
},
|
|
127
153
|
},
|
|
128
154
|
{
|
|
@@ -149,10 +175,11 @@ export default {
|
|
|
149
175
|
customFunc: () => {
|
|
150
176
|
this.bubbleState = 'link'
|
|
151
177
|
},
|
|
178
|
+
disabled: this.editor.state.selection.empty,
|
|
152
179
|
icon: ['far', 'link'],
|
|
153
180
|
appearance: {
|
|
154
|
-
menu:
|
|
155
|
-
bubble:
|
|
181
|
+
menu: true,
|
|
182
|
+
bubble: false,
|
|
156
183
|
},
|
|
157
184
|
},
|
|
158
185
|
{
|
|
@@ -171,10 +198,11 @@ export default {
|
|
|
171
198
|
customFunc: () => {
|
|
172
199
|
this.bubbleState = 'cta'
|
|
173
200
|
},
|
|
201
|
+
disabled: this.editor.state.selection.empty,
|
|
174
202
|
icon: ['far', 'mouse-pointer'],
|
|
175
203
|
appearance: {
|
|
176
|
-
menu:
|
|
177
|
-
bubble:
|
|
204
|
+
menu: true,
|
|
205
|
+
bubble: false,
|
|
178
206
|
},
|
|
179
207
|
},
|
|
180
208
|
]
|
|
@@ -195,7 +223,7 @@ export default {
|
|
|
195
223
|
else editor.unsetLink().run()
|
|
196
224
|
break
|
|
197
225
|
case 'cta':
|
|
198
|
-
if (value) editor.setCta({ href: value }).run()
|
|
226
|
+
if (value) editor.setCta({ href: value, 'data-cta': this.bubbleOptions.theme }).run()
|
|
199
227
|
else editor.unsetCta().run()
|
|
200
228
|
break
|
|
201
229
|
}
|
|
@@ -203,6 +231,14 @@ export default {
|
|
|
203
231
|
this.bubbleState = null
|
|
204
232
|
this.linkUrl = null
|
|
205
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
|
+
},
|
|
206
242
|
},
|
|
207
243
|
mounted() {
|
|
208
244
|
this.editor = new Editor({
|
|
@@ -230,11 +266,25 @@ export default {
|
|
|
230
266
|
@import './styles/_mixins';
|
|
231
267
|
.richtext {
|
|
232
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
|
+
}
|
|
233
280
|
|
|
234
281
|
&__editor {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
282
|
+
flex-grow: 1;
|
|
283
|
+
|
|
284
|
+
.ProseMirror {
|
|
285
|
+
padding: 0rem 1rem 1rem;
|
|
286
|
+
min-height: 6rem;
|
|
287
|
+
height: 100%;
|
|
238
288
|
|
|
239
289
|
p:first-child {
|
|
240
290
|
margin-top: 0;
|
|
@@ -248,47 +298,69 @@ export default {
|
|
|
248
298
|
}
|
|
249
299
|
|
|
250
300
|
&:focus {
|
|
251
|
-
outline:
|
|
252
|
-
border-radius: 0 0 var(--border-radius) var(--border-radius);
|
|
301
|
+
outline: none;
|
|
253
302
|
}
|
|
254
303
|
|
|
255
304
|
img {
|
|
256
305
|
max-width: 100%;
|
|
257
306
|
}
|
|
258
307
|
|
|
259
|
-
a[data-cta
|
|
260
|
-
background-color: var(--primary);
|
|
261
|
-
color: white;
|
|
308
|
+
a[data-cta] {
|
|
262
309
|
padding: 0.75em 1.5em;
|
|
263
310
|
border-radius: var(--border-radius);
|
|
264
311
|
text-decoration: none;
|
|
265
312
|
|
|
266
313
|
display: inline-block;
|
|
267
314
|
}
|
|
268
|
-
}
|
|
269
315
|
|
|
270
|
-
|
|
271
|
-
|
|
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
|
+
}
|
|
272
325
|
}
|
|
273
326
|
}
|
|
274
327
|
|
|
275
328
|
&__bubble {
|
|
276
329
|
display: flex;
|
|
277
330
|
background-color: var(--dark);
|
|
331
|
+
color: white;
|
|
278
332
|
border-radius: var(--border-radius);
|
|
279
333
|
|
|
280
334
|
&-form {
|
|
281
335
|
display: flex;
|
|
282
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
|
+
|
|
283
345
|
button {
|
|
284
|
-
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;
|
|
285
357
|
}
|
|
286
358
|
}
|
|
287
359
|
|
|
288
360
|
&-input {
|
|
289
361
|
font: inherit;
|
|
290
362
|
border: none;
|
|
291
|
-
padding:
|
|
363
|
+
padding: 0.5rem;
|
|
292
364
|
background-color: transparent;
|
|
293
365
|
color: #fff !important;
|
|
294
366
|
|
|
@@ -297,9 +369,8 @@ export default {
|
|
|
297
369
|
}
|
|
298
370
|
}
|
|
299
371
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
width: initial !important;
|
|
372
|
+
&__button {
|
|
373
|
+
width: initial;
|
|
303
374
|
padding: 0.5rem 0.75rem !important;
|
|
304
375
|
color: white;
|
|
305
376
|
|
|
@@ -319,28 +390,60 @@ export default {
|
|
|
319
390
|
}
|
|
320
391
|
|
|
321
392
|
&__menubar {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
393
|
+
padding: 0.75rem;
|
|
394
|
+
position: sticky;
|
|
395
|
+
top: 0;
|
|
396
|
+
z-index: 1;
|
|
325
397
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
border-right: 1px solid var(--border-color);
|
|
330
|
-
transition: background-color 150ms ease-out;
|
|
331
|
-
cursor: pointer;
|
|
332
|
-
|
|
333
|
-
&:disabled {
|
|
334
|
-
cursor: not-allowed;
|
|
398
|
+
&-buttons {
|
|
399
|
+
width: max-content;
|
|
400
|
+
box-shadow: 0 2px 4px -2px rgba(black, 0.1);
|
|
335
401
|
}
|
|
336
402
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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;
|
|
409
|
+
|
|
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
|
+
}
|
|
340
438
|
}
|
|
341
439
|
}
|
|
440
|
+
|
|
342
441
|
a {
|
|
343
442
|
word-break: break-all;
|
|
344
443
|
}
|
|
444
|
+
|
|
445
|
+
.tippy-box {
|
|
446
|
+
max-width: initial !important;
|
|
447
|
+
}
|
|
345
448
|
}
|
|
346
449
|
</style>
|
|
File without changes
|