@afeefa/vue-app 0.0.91 → 0.0.93
Sign up to get free protection for your applications and to get access to all the features.
- package/.afeefa/package/release/version.txt +1 -1
- package/package.json +1 -1
- package/src/components/ARichTextArea.vue +74 -16
- package/src/components/form/fields/FormFieldRichTextArea.vue +5 -1
- package/src/services/escape/CascadingWindowEventDispatcher.js +4 -0
- package/src-admin/components/form/RemoveButton.vue +7 -3
- package/src-admin/config/vuetify.js +6 -4
- package/src-admin/styles.scss +9 -0
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.93
|
package/package.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<template>
|
2
|
-
<div :class="['a-rich-text-editor a-text-input', {'a-text-input-focused':
|
2
|
+
<div :class="['a-rich-text-editor a-text-input', {'a-text-input-focused': editorFocus}]">
|
3
3
|
<div
|
4
4
|
v-if="editor"
|
5
5
|
class="menu-bar"
|
@@ -7,7 +7,8 @@
|
|
7
7
|
<div>
|
8
8
|
<v-btn
|
9
9
|
small
|
10
|
-
:class="['menu-button', {'is-active':
|
10
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('bold')}]"
|
11
|
+
title="fett"
|
11
12
|
@click="editor.chain().focus().toggleBold().run()"
|
12
13
|
>
|
13
14
|
<v-icon>{{ boldIcon }}</v-icon>
|
@@ -15,7 +16,8 @@
|
|
15
16
|
|
16
17
|
<v-btn
|
17
18
|
small
|
18
|
-
:class="['menu-button', {'is-active':
|
19
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('italic')}]"
|
20
|
+
title="kursiv"
|
19
21
|
@click="editor.chain().focus().toggleItalic().run()"
|
20
22
|
>
|
21
23
|
<v-icon>{{ italicIcon }}</v-icon>
|
@@ -23,7 +25,8 @@
|
|
23
25
|
|
24
26
|
<v-btn
|
25
27
|
small
|
26
|
-
:class="['menu-button', 'strike', {'is-active':
|
28
|
+
:class="['menu-button', 'strike', {'is-active': editorFocus && editor.isActive('strike')}]"
|
29
|
+
title="durchgestrichen"
|
27
30
|
@click="editor.chain().focus().toggleStrike().run()"
|
28
31
|
>
|
29
32
|
<v-icon>{{ strikeIcon }}</v-icon>
|
@@ -31,7 +34,8 @@
|
|
31
34
|
|
32
35
|
<v-btn
|
33
36
|
small
|
34
|
-
:class="['menu-button', {'is-active':
|
37
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('heading', {level: 1})}]"
|
38
|
+
title="überschrift 1"
|
35
39
|
@click="editor.chain().focus().toggleHeading({level: 1}).run()"
|
36
40
|
>
|
37
41
|
<v-icon>{{ h1Icon }}</v-icon>
|
@@ -39,7 +43,8 @@
|
|
39
43
|
|
40
44
|
<v-btn
|
41
45
|
small
|
42
|
-
:class="['menu-button', {'is-active':
|
46
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('heading', {level: 2})}]"
|
47
|
+
title="pberschrift 2"
|
43
48
|
@click="editor.chain().focus().toggleHeading({level: 2}).run()"
|
44
49
|
>
|
45
50
|
<v-icon>{{ h2Icon }}</v-icon>
|
@@ -47,7 +52,8 @@
|
|
47
52
|
|
48
53
|
<v-btn
|
49
54
|
small
|
50
|
-
:class="['menu-button', {'is-active':
|
55
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('bulletList')}]"
|
56
|
+
title="punkt-liste"
|
51
57
|
@click="editor.chain().focus().toggleBulletList().run()"
|
52
58
|
>
|
53
59
|
<v-icon>{{ ulIcon }}</v-icon>
|
@@ -55,7 +61,8 @@
|
|
55
61
|
|
56
62
|
<v-btn
|
57
63
|
small
|
58
|
-
:class="['menu-button', {'is-active':
|
64
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('orderedList')}]"
|
65
|
+
title="nummerierte liste"
|
59
66
|
@click="editor.chain().focus().toggleOrderedList().run()"
|
60
67
|
>
|
61
68
|
<v-icon>{{ olIcon }}</v-icon>
|
@@ -63,7 +70,8 @@
|
|
63
70
|
|
64
71
|
<v-btn
|
65
72
|
small
|
66
|
-
:class="['menu-button', {'is-active':
|
73
|
+
:class="['menu-button', {'is-active': editorFocus && editor.isActive('blockquote')}]"
|
74
|
+
title="zitat"
|
67
75
|
@click="editor.chain().focus().toggleBlockquote().run()"
|
68
76
|
>
|
69
77
|
<v-icon>{{ commentIcon }}</v-icon>
|
@@ -72,13 +80,37 @@
|
|
72
80
|
<v-btn
|
73
81
|
small
|
74
82
|
class="menu-button"
|
83
|
+
:class="{ 'is-active': editorFocus && editorSelectionIs('#0000FF')}"
|
84
|
+
title="blau"
|
85
|
+
color="blue--text"
|
86
|
+
@click="editorSelectionIs('#0000FF') ? editor.chain().focus().unsetColor().run() : editor.chain().focus().setColor('#0000FF').run()"
|
87
|
+
>
|
88
|
+
<v-icon>$paletteIcon</v-icon>
|
89
|
+
</v-btn>
|
90
|
+
|
91
|
+
<v-btn
|
92
|
+
small
|
93
|
+
class="menu-button"
|
94
|
+
:class="{ 'is-active': editorFocus && editorSelectionIs('#FF0000')}"
|
95
|
+
title="rot"
|
96
|
+
color="red--text"
|
97
|
+
@click="editorSelectionIs('#FF0000') ? editor.chain().focus().unsetColor().run() : editor.chain().focus().setColor('#FF0000').run()"
|
98
|
+
>
|
99
|
+
<v-icon>$paletteIcon</v-icon>
|
100
|
+
</v-btn>
|
101
|
+
|
102
|
+
<v-btn
|
103
|
+
small
|
104
|
+
class="menu-button undo-button"
|
75
105
|
:disabled="initialValue === editor.getHTML()"
|
106
|
+
title="rückgängig"
|
76
107
|
@click="editor.chain().focus().undo().run()"
|
77
108
|
>
|
78
109
|
<v-icon>{{ undoIcon }}</v-icon>
|
79
110
|
</v-btn>
|
80
111
|
</div>
|
81
112
|
|
113
|
+
|
82
114
|
<div>
|
83
115
|
<slot name="buttons" />
|
84
116
|
</div>
|
@@ -86,7 +118,7 @@
|
|
86
118
|
|
87
119
|
<editor-content
|
88
120
|
:editor="editor"
|
89
|
-
:class="['a-rich-text-editor', {
|
121
|
+
:class="['a-rich-text-editor', {editorFocus}]"
|
90
122
|
/>
|
91
123
|
</div>
|
92
124
|
</template>
|
@@ -108,9 +140,11 @@ import {
|
|
108
140
|
mdiRotateLeft,
|
109
141
|
mdiRotateRight
|
110
142
|
} from '@mdi/js'
|
143
|
+
import { Color } from '@tiptap/extension-color'
|
144
|
+
import TextStyle from '@tiptap/extension-text-style'
|
111
145
|
|
112
146
|
@Component({
|
113
|
-
props: ['value', 'validator'],
|
147
|
+
props: ['value', 'validator', 'focus'],
|
114
148
|
components: {
|
115
149
|
EditorContent
|
116
150
|
}
|
@@ -119,7 +153,7 @@ export default class ARichTextArea extends Vue {
|
|
119
153
|
editor = null
|
120
154
|
internalValue = null
|
121
155
|
initialValue = null
|
122
|
-
|
156
|
+
editorFocus = false
|
123
157
|
|
124
158
|
boldIcon = mdiFormatBold
|
125
159
|
italicIcon = mdiFormatItalic
|
@@ -137,25 +171,34 @@ export default class ARichTextArea extends Vue {
|
|
137
171
|
this.internalValue = this.value
|
138
172
|
}
|
139
173
|
|
174
|
+
changed () {
|
175
|
+
console.log('Changed')
|
176
|
+
}
|
177
|
+
|
140
178
|
mounted () {
|
179
|
+
this.editorFocus = !!this.focus
|
180
|
+
|
141
181
|
if (this.validator) {
|
142
182
|
this.$refs.input.validate(true)
|
143
183
|
}
|
144
184
|
|
145
185
|
this.editor = new Editor({
|
146
186
|
content: this.internalValue,
|
187
|
+
autofocus: this.focus ? 'end' : false,
|
147
188
|
extensions: [
|
148
|
-
StarterKit
|
189
|
+
StarterKit,
|
190
|
+
TextStyle,
|
191
|
+
Color
|
149
192
|
],
|
150
193
|
onUpdate: () => {
|
151
194
|
this.$emit('input', this.editor.getHTML())
|
152
195
|
},
|
153
196
|
onFocus: ({ editor, event }) => {
|
154
|
-
this.
|
197
|
+
this.editorFocus = true
|
155
198
|
this.$emit('focus')
|
156
199
|
},
|
157
200
|
onBlur: ({ editor, event }) => {
|
158
|
-
this.
|
201
|
+
this.editorFocus = false
|
159
202
|
this.$emit('blur')
|
160
203
|
}
|
161
204
|
})
|
@@ -165,6 +208,10 @@ export default class ARichTextArea extends Vue {
|
|
165
208
|
this.editor.destroy()
|
166
209
|
}
|
167
210
|
|
211
|
+
editorSelectionIs (color) {
|
212
|
+
return this.editor.isActive('textStyle', { color: color })
|
213
|
+
}
|
214
|
+
|
168
215
|
/**
|
169
216
|
* reset the text area to disable the undo button
|
170
217
|
* e.g. after saving the form while keeping it open
|
@@ -180,6 +227,10 @@ export default class ARichTextArea extends Vue {
|
|
180
227
|
const isSame = this.editor.getHTML() === this.internalValue
|
181
228
|
if (!isSame) {
|
182
229
|
this.editor.commands.setContent(this.internalValue, false)
|
230
|
+
// witch reusing the editor component, we need to restore the focus state
|
231
|
+
if (this.focus && this.focus === true) {
|
232
|
+
this.editor.commands.focus('end')
|
233
|
+
}
|
183
234
|
}
|
184
235
|
}
|
185
236
|
|
@@ -240,11 +291,18 @@ export default class ARichTextArea extends Vue {
|
|
240
291
|
width: unset;
|
241
292
|
}
|
242
293
|
|
294
|
+
&:disabled {
|
295
|
+
background: none !important;
|
296
|
+
:deep(*) {
|
297
|
+
color: #CCCCCC !important;
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
243
301
|
&.is-active {
|
244
302
|
background: #ECECEC !important;
|
245
303
|
}
|
246
304
|
|
247
|
-
|
305
|
+
&.menu-button:disabled {
|
248
306
|
background: none !important;
|
249
307
|
}
|
250
308
|
}
|
@@ -10,6 +10,10 @@ class CascadingWindowEventDispatcher {
|
|
10
10
|
addEventListener (event, listener) {
|
11
11
|
if (!this.listeners[event]) {
|
12
12
|
this.listeners[event] = []
|
13
|
+
}
|
14
|
+
|
15
|
+
if (!this.listeners[event].length) {
|
16
|
+
this.listeners[event] = []
|
13
17
|
|
14
18
|
window.addEventListener(event, e => {
|
15
19
|
for (const listener of this.listeners[event]) {
|
@@ -4,14 +4,14 @@
|
|
4
4
|
<v-btn
|
5
5
|
:class="'a-btn-standard removeButton-' + dialogId"
|
6
6
|
fab
|
7
|
-
small
|
8
7
|
:color="(hover ? 'red' : 'grey lighten-3')"
|
9
8
|
:title="title"
|
9
|
+
v-bind="{ small: isSmall, ...$attrs}"
|
10
10
|
@click="remove"
|
11
11
|
>
|
12
12
|
<v-icon
|
13
13
|
class="white--hover"
|
14
|
-
size="1.3rem"
|
14
|
+
:size="iconSize || '1.3rem'"
|
15
15
|
>
|
16
16
|
$trashCanIcon
|
17
17
|
</v-icon>
|
@@ -44,13 +44,17 @@ import { DialogEvent } from '@a-vue/events'
|
|
44
44
|
import { randomCssClass } from '@a-vue/utils/random'
|
45
45
|
|
46
46
|
@Component({
|
47
|
-
props: ['title', 'message', 'info', 'itemTitle', 'protect']
|
47
|
+
props: ['iconSize', 'title', 'message', 'info', 'itemTitle', 'protect']
|
48
48
|
})
|
49
49
|
export default class EditPage extends Vue {
|
50
50
|
dialogId = randomCssClass(10)
|
51
51
|
removeKey = null
|
52
52
|
removeConfirmed = null
|
53
53
|
|
54
|
+
get isSmall () {
|
55
|
+
return Object.keys(this.$attrs).filter(k => k.match(/x-small|default|large|x-large/)).length === 0
|
56
|
+
}
|
57
|
+
|
54
58
|
async remove () {
|
55
59
|
if (this.protect) {
|
56
60
|
this.removeKey = [...Array(6)].map(() => Math.floor(Math.random() * 16).toString(16)).join('')
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import {
|
2
2
|
mdiAlarmLightOutline,
|
3
|
-
mdiArrowLeft,
|
4
3
|
mdiAlert,
|
4
|
+
mdiArrowLeft,
|
5
5
|
mdiCalendar,
|
6
6
|
mdiCheck,
|
7
7
|
mdiCheckBold,
|
8
8
|
mdiChevronRight,
|
9
9
|
mdiClose,
|
10
10
|
mdiCloseThick,
|
11
|
+
mdiCurrencyEur,
|
11
12
|
mdiDelete,
|
12
13
|
mdiDotsHorizontal,
|
13
14
|
mdiDotsVertical,
|
@@ -16,11 +17,11 @@ import {
|
|
16
17
|
mdiMagnify,
|
17
18
|
mdiMenuDown,
|
18
19
|
mdiMenuUp,
|
20
|
+
mdiPalette,
|
19
21
|
mdiPencil,
|
20
22
|
mdiPlus,
|
21
23
|
mdiPrinter,
|
22
|
-
mdiThumbUpOutline
|
23
|
-
mdiCurrencyEur
|
24
|
+
mdiThumbUpOutline
|
24
25
|
} from '@mdi/js'
|
25
26
|
import Vue from 'vue'
|
26
27
|
import Vuetify from 'vuetify/lib'
|
@@ -52,7 +53,8 @@ export default new Vuetify({
|
|
52
53
|
caretDownIcon: mdiMenuDown,
|
53
54
|
caretUpIcon: mdiMenuUp,
|
54
55
|
printerIcon: mdiPrinter,
|
55
|
-
euroSymbol: mdiCurrencyEur
|
56
|
+
euroSymbol: mdiCurrencyEur,
|
57
|
+
paletteIcon: mdiPalette
|
56
58
|
}
|
57
59
|
},
|
58
60
|
breakpoint: {
|
package/src-admin/styles.scss
CHANGED
@@ -59,6 +59,10 @@
|
|
59
59
|
opacity: .08;
|
60
60
|
}
|
61
61
|
|
62
|
+
.theme--light.v-input .error--text {
|
63
|
+
color: #616161 !important;
|
64
|
+
}
|
65
|
+
|
62
66
|
.theme--light.v-btn.v-btn--disabled,
|
63
67
|
.theme--light.v-btn.v-btn--disabled span,
|
64
68
|
.theme--light.v-btn.v-btn--disabled .v-icon,
|
@@ -66,6 +70,11 @@
|
|
66
70
|
color: white !important;
|
67
71
|
}
|
68
72
|
|
73
|
+
.theme--light.v-btn:focus-visible {
|
74
|
+
outline: 2px solid #1976d2;
|
75
|
+
}
|
76
|
+
|
77
|
+
|
69
78
|
.theme--light.v-btn.v-btn--disabled.v-btn--has-bg {
|
70
79
|
background-color: #EEEEEE !important;
|
71
80
|
}
|