comand-component-library 3.3.76 → 3.3.78
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/dist/comand-component-library.js +2119 -2193
- package/dist/comand-component-library.umd.cjs +4 -4
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/CmdBox.vue +2 -2
- package/src/components/CmdImage.vue +65 -194
- package/src/mixins/EditMode.vue +29 -0
- package/src/utils/checkAndUploadFile.js +48 -0
- package/src/utils/editmode.js +42 -0
@@ -1,74 +1,32 @@
|
|
1
1
|
<template>
|
2
2
|
<!-- begin edit-mode -->
|
3
|
-
<figure v-if="
|
4
|
-
<CmdFormElement
|
5
|
-
element="input"
|
6
|
-
type="checkbox"
|
7
|
-
:toggleSwitch="true"
|
8
|
-
labelText="Show figcaption"
|
9
|
-
v-model="editableShowFigcaption"
|
10
|
-
/>
|
11
|
-
<CmdFormElement
|
12
|
-
element="select"
|
13
|
-
labelText="Figcaption Position"
|
14
|
-
:selectOptions="positionOptions"
|
15
|
-
:disabled="!showFigcaption"
|
16
|
-
v-model="editableFigcaptionPosition"
|
17
|
-
/>
|
18
|
-
<CmdFormElement
|
19
|
-
element="select"
|
20
|
-
labelText="Figcaption text alignment"
|
21
|
-
:selectOptions="textAlignOptions"
|
22
|
-
:disabled="!showFigcaption"
|
23
|
-
v-model="editableFigcaptionTextAlign"
|
24
|
-
/>
|
25
|
-
<CmdFormElement element="input" type="text" :required="true" labelText="Alternative Text"
|
26
|
-
v-model="editableAlternativeText"/>
|
27
|
-
<CmdFormElement element="input" type="text" :required="false" labelText="Tooltip" v-model="editableTooltip"/>
|
28
|
-
|
3
|
+
<figure v-if="editing" :class="['cmd-image flex-container vertical', getTextAlign]">
|
29
4
|
<template v-if="figcaption?.position === 'top'">
|
30
|
-
<CmdFormElement
|
31
|
-
|
5
|
+
<CmdFormElement
|
6
|
+
element="input"
|
7
|
+
type="text"
|
8
|
+
:required="true"
|
9
|
+
labelText="Text figcaption"
|
10
|
+
v-model="editableFigcaptionText"
|
11
|
+
/>
|
32
12
|
</template>
|
33
13
|
<div :class="['box drop-area flex-container vertical', { 'allow-drop': allowDrop }]" v-on="dragAndDropHandler" title="Drag new image to this area to replace old one!">
|
34
14
|
<span class="icon-image"></span>
|
35
|
-
<img
|
15
|
+
<img :src="imageSource" :alt="image.alt" :title="image.tooltip"/>
|
36
16
|
</div>
|
37
|
-
|
38
|
-
type="button"
|
39
|
-
:class="['button upload primary', { disabled: uploadInitiated }]"
|
40
|
-
:disabled="uploadInitiated"
|
41
|
-
@click="selectFiles()"
|
42
|
-
>
|
43
|
-
<!-- begin CmdIcon -->
|
44
|
-
<CmdIcon iconClass="icon-loop"/>
|
45
|
-
<!-- end CmdIcon -->
|
46
|
-
<span>Select image</span>
|
47
|
-
</button>
|
17
|
+
|
48
18
|
<template v-if="figcaption?.position !== 'top'">
|
49
19
|
<CmdFormElement
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
20
|
+
element="input"
|
21
|
+
type="text"
|
22
|
+
:class="getTextAlign"
|
23
|
+
:required="true"
|
24
|
+
labelText="Text figcaption"
|
25
|
+
:showLabel="false"
|
26
|
+
v-model="editableFigcaptionText"
|
56
27
|
/>
|
57
28
|
</template>
|
58
29
|
</figure>
|
59
|
-
|
60
|
-
<!-- begin CmdFormElement -->
|
61
|
-
<CmdFormElement
|
62
|
-
v-if="editModeContext?.editing"
|
63
|
-
class="hidden"
|
64
|
-
element="input"
|
65
|
-
type="file"
|
66
|
-
labelText="Select file"
|
67
|
-
:disabled="uploadInitiated"
|
68
|
-
@change="fileSelected"
|
69
|
-
ref="formElement"
|
70
|
-
/>
|
71
|
-
<!-- end CmdFormElement -->
|
72
30
|
<!-- end edit-mode -->
|
73
31
|
|
74
32
|
<figure v-else :class="['cmd-image', getTextAlign]">
|
@@ -79,21 +37,19 @@
|
|
79
37
|
</template>
|
80
38
|
|
81
39
|
<script>
|
82
|
-
import {
|
40
|
+
import {checkAndUploadFile} from "../utils/checkAndUploadFile"
|
41
|
+
import EditMode from "../mixins/EditMode.vue"
|
42
|
+
import {updateHandlerProvider} from "../utils/editmode.js"
|
83
43
|
|
84
44
|
export default {
|
85
45
|
name: "CmdImage",
|
86
|
-
|
87
|
-
editModeContext: {
|
88
|
-
default: null
|
89
|
-
}
|
90
|
-
},
|
46
|
+
mixins: [EditMode],
|
91
47
|
data() {
|
92
48
|
return {
|
93
49
|
mediumMaxWidth: 1023,
|
94
50
|
smallMaxWidth: 600,
|
95
51
|
currentWindowWidth: window.innerWidth,
|
96
|
-
allowedFileExtensions: ["jpg", "jpeg", "png"],
|
52
|
+
allowedFileExtensions: ["jpg", "jpeg", "png", "webp"],
|
97
53
|
uploadInitiated: false,
|
98
54
|
allowDrop: false,
|
99
55
|
showFigcaption: true,
|
@@ -101,6 +57,7 @@ export default {
|
|
101
57
|
figcaptionTextAlign: null,
|
102
58
|
tooltip: null,
|
103
59
|
alternativeText: null,
|
60
|
+
newImageSource: null,
|
104
61
|
positionOptions: [
|
105
62
|
{
|
106
63
|
text: "Above image",
|
@@ -128,13 +85,7 @@ export default {
|
|
128
85
|
figcaptionText: null
|
129
86
|
}
|
130
87
|
},
|
131
|
-
mounted() {
|
132
|
-
this.editModeContext?.addSaveHandler(this.onSave)
|
133
|
-
},
|
134
88
|
props: {
|
135
|
-
editModeContextData: {
|
136
|
-
type: Object
|
137
|
-
},
|
138
89
|
/**
|
139
90
|
* image-object including source, alternative text, tooltip (not required)
|
140
91
|
*/
|
@@ -158,7 +109,7 @@ export default {
|
|
158
109
|
},
|
159
110
|
minImageWidth: {
|
160
111
|
type: Number,
|
161
|
-
default:
|
112
|
+
default: 600
|
162
113
|
}
|
163
114
|
},
|
164
115
|
created() {
|
@@ -175,6 +126,11 @@ export default {
|
|
175
126
|
},
|
176
127
|
computed: {
|
177
128
|
imageSource() {
|
129
|
+
// check if a new image is provided
|
130
|
+
if(this.newImageSource) {
|
131
|
+
return this.newImageSource
|
132
|
+
}
|
133
|
+
|
178
134
|
// if only one src exists
|
179
135
|
const imgSrc = this.image.src
|
180
136
|
|
@@ -194,6 +150,12 @@ export default {
|
|
194
150
|
// else return large (will be used if images for small-and -medium-devices do not exist or if screen resolution is larger than mediumMaxWidth)
|
195
151
|
return imgSrc.large
|
196
152
|
},
|
153
|
+
getTextAlign() {
|
154
|
+
if (this.figcaption?.textAlign) {
|
155
|
+
return "text-" + this.figcaption.textAlign
|
156
|
+
}
|
157
|
+
return ''
|
158
|
+
},
|
197
159
|
dragAndDropHandler() {
|
198
160
|
// register handlers only if drag-and-drop is enabled
|
199
161
|
return {
|
@@ -203,55 +165,9 @@ export default {
|
|
203
165
|
drop: this.drop
|
204
166
|
}
|
205
167
|
},
|
206
|
-
getTextAlign() {
|
207
|
-
if (this.figcaption?.textAlign) {
|
208
|
-
return "text-" + this.figcaption.textAlign
|
209
|
-
}
|
210
|
-
return ''
|
211
|
-
},
|
212
|
-
editableAlternativeText: {
|
213
|
-
get() {
|
214
|
-
return this.alternativeText == null ? this.image.alt : this.alternativeText
|
215
|
-
},
|
216
|
-
set(value) {
|
217
|
-
this.alternativeText = value
|
218
|
-
}
|
219
|
-
},
|
220
|
-
editableTooltip: {
|
221
|
-
get() {
|
222
|
-
return this.tooltip == null ? this.image.tooltip : this.tooltip
|
223
|
-
},
|
224
|
-
set(value) {
|
225
|
-
this.tooltip = value
|
226
|
-
}
|
227
|
-
},
|
228
|
-
editableShowFigcaption: {
|
229
|
-
get() {
|
230
|
-
return this.showFigcaption == null ? this.figcaption.show : this.showFigcaption
|
231
|
-
},
|
232
|
-
set(value) {
|
233
|
-
this.showFigcaption = value
|
234
|
-
}
|
235
|
-
},
|
236
|
-
editableFigcaptionPosition: {
|
237
|
-
get() {
|
238
|
-
return this.figcaptionPosition == null ? this.figcaption.position : this.figcaptionPosition
|
239
|
-
},
|
240
|
-
set(value) {
|
241
|
-
this.figcaptionPosition = value
|
242
|
-
}
|
243
|
-
},
|
244
|
-
editableFigcaptionTextAlign: {
|
245
|
-
get() {
|
246
|
-
return this.figcaptionTextAlign || this.figcaption.textAlign
|
247
|
-
},
|
248
|
-
set(value) {
|
249
|
-
this.figcaptionTextAlign = value
|
250
|
-
}
|
251
|
-
},
|
252
168
|
editableFigcaptionText: {
|
253
169
|
get() {
|
254
|
-
return this.figcaptionText
|
170
|
+
return this.figcaptionText == null ? this.figcaption.text : this.figcaptionText
|
255
171
|
},
|
256
172
|
set(value) {
|
257
173
|
this.figcaptionText = value
|
@@ -273,15 +189,6 @@ export default {
|
|
273
189
|
}
|
274
190
|
}
|
275
191
|
},
|
276
|
-
fileSelected(event) {
|
277
|
-
if (event.target.files.length > 0) {
|
278
|
-
this.checkAndUploadFile(event.target.files[0])
|
279
|
-
}
|
280
|
-
},
|
281
|
-
selectFiles() {
|
282
|
-
let inputFile = this.$refs.formElement.getDomElement().querySelector("input[type='file']")
|
283
|
-
inputFile.click()
|
284
|
-
},
|
285
192
|
dragEnter(event) {
|
286
193
|
this.dragOver(event)
|
287
194
|
},
|
@@ -306,80 +213,40 @@ export default {
|
|
306
213
|
this.allowDrop = false
|
307
214
|
if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length > 0) {
|
308
215
|
event.preventDefault()
|
309
|
-
|
216
|
+
checkAndUploadFile(event.dataTransfer.files[0], this.allowedFileExtensions, this.minImageWidth, this.maxFileUploadSize, (imageSource) => this.newImageSource = imageSource)
|
310
217
|
}
|
311
218
|
},
|
312
|
-
|
313
|
-
const
|
314
|
-
image: {
|
315
|
-
|
316
|
-
|
219
|
+
addHandlerProvider() {
|
220
|
+
const itemStructure = {
|
221
|
+
"image": {
|
222
|
+
"id": createUuid(),
|
223
|
+
"src": "media/images/demo-images/large/landscape-06.jpg",
|
224
|
+
"srcImageLarge": "media/images/demo-images/large/landscape-06.jpg",
|
225
|
+
"alt": "Alternative Text"
|
317
226
|
},
|
318
|
-
figcaption: {
|
319
|
-
|
320
|
-
|
321
|
-
text:
|
322
|
-
|
227
|
+
"figcaption": {
|
228
|
+
"show": true,
|
229
|
+
"position": "bottom",
|
230
|
+
"text": "Figcaption",
|
231
|
+
"textAlign": "center"
|
323
232
|
}
|
324
233
|
}
|
325
|
-
return {
|
326
|
-
|
327
|
-
|
234
|
+
return updateHandlerProvider(this, {
|
235
|
+
item() {
|
236
|
+
return itemStructure
|
237
|
+
}
|
238
|
+
})
|
239
|
+
},
|
240
|
+
updateHandlerProvider() {
|
241
|
+
const figcaptionText = this.editableFigcaptionText
|
242
|
+
return updateHandlerProvider(this, {
|
328
243
|
update(props) {
|
329
|
-
console.log("CmdImage.update", props)
|
330
|
-
if (!props.image) {
|
331
|
-
props.image = {}
|
332
|
-
}
|
333
|
-
props.image.alt = data.image.alt
|
334
|
-
props.image.tooltip = data.image.tooltip
|
335
244
|
if (!props.figcaption) {
|
336
245
|
props.figcaption = {}
|
337
246
|
}
|
338
|
-
props.figcaption.
|
339
|
-
props.figcaption.textAlign = data.figcaption.textAlign
|
340
|
-
props.figcaption.text = data.figcaption.text
|
341
|
-
props.figcaption.show = data.figcaption.show
|
247
|
+
props.figcaption.text = figcaptionText
|
342
248
|
}
|
343
|
-
}
|
344
|
-
},
|
345
|
-
checkAndUploadFile(file) {
|
346
|
-
const errorMessages = []
|
347
|
-
|
348
|
-
// check size for current file
|
349
|
-
if (file.size > this.maxFileUploadSize) {
|
350
|
-
errorMessages.push("file too large")
|
351
|
-
}
|
352
|
-
|
353
|
-
// check if current file has allowed file-type
|
354
|
-
if (!this.allowedFileExtensions.includes(getFileExtension(file.name))) {
|
355
|
-
errorMessages.push("disallowed file extension")
|
356
|
-
}
|
357
|
-
|
358
|
-
if (errorMessages.length) {
|
359
|
-
alert(errorMessages)
|
360
|
-
return
|
361
|
-
}
|
362
|
-
|
363
|
-
// check for min dimensions
|
364
|
-
const image = new Image()
|
365
|
-
|
366
|
-
image.onload = () => {
|
367
|
-
if (image.width < this.minImageWidth) {
|
368
|
-
// errorMessages.push("width (" + image.width + " px) too small - at least " + this.minImageWidth + " px required!")
|
369
|
-
const confirmUpload = confirm("width (" + image.width + " px) too small - at least " + this.minImageWidth + " px required! Use trotzdem!")
|
370
|
-
if (!confirmUpload) {
|
371
|
-
alert("Abbruch")
|
372
|
-
return
|
373
|
-
}
|
374
|
-
}
|
375
|
-
// revoke URL to clean memory
|
376
|
-
URL.revokeObjectURL(image.src)
|
377
|
-
|
378
|
-
// show preview-image by assigning image.src (containing image date (not its path) to do existing contentImage source
|
379
|
-
this.$refs.contentImage.src = image.src
|
380
|
-
}
|
381
|
-
// create data-url (contains content of a file (not its path))
|
382
|
-
image.src = URL.createObjectURL(file)
|
249
|
+
})
|
383
250
|
}
|
384
251
|
}
|
385
252
|
}
|
@@ -388,6 +255,10 @@ export default {
|
|
388
255
|
<style lang="scss">
|
389
256
|
/* begin cmd-image ------------------------------------------------------------------------------------------ */
|
390
257
|
.cmd-image {
|
258
|
+
img {
|
259
|
+
display: block;
|
260
|
+
}
|
261
|
+
|
391
262
|
&.text-center {
|
392
263
|
figcaption {
|
393
264
|
text-align: center;
|
@@ -430,4 +301,4 @@ export default {
|
|
430
301
|
}
|
431
302
|
|
432
303
|
/* end cmd-image ------------------------------------------------------------------------------------------ */
|
433
|
-
</style>
|
304
|
+
</style>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<script>
|
2
|
+
import {findEditComponentWrapper} from "../utils/editmode.js"
|
3
|
+
|
4
|
+
export default {
|
5
|
+
inject: {
|
6
|
+
editModeContext: {
|
7
|
+
default: null
|
8
|
+
}
|
9
|
+
},
|
10
|
+
data() {
|
11
|
+
return {
|
12
|
+
editing: false
|
13
|
+
}
|
14
|
+
},
|
15
|
+
created() {
|
16
|
+
const editComponentWrapper = findEditComponentWrapper(this.$parent)
|
17
|
+
if (editComponentWrapper) {
|
18
|
+
editComponentWrapper.addEditStateListener(editing => this.editing = editing)
|
19
|
+
editComponentWrapper.addUpdateHandlerProvider(this.updateHandlerProvider)
|
20
|
+
editComponentWrapper.setAddHandlerProvider(this.addHandlerProvider)
|
21
|
+
}
|
22
|
+
},
|
23
|
+
methods: {
|
24
|
+
updateHandlerProvider() {
|
25
|
+
return {}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
</script>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import {getFileExtension} from "./getFileExtension.js"
|
2
|
+
|
3
|
+
function checkAndUploadFile(file, allowedFileExtensions, minImageWidth, maxFileUploadSize, imagePreview) {
|
4
|
+
const errorMessages = []
|
5
|
+
|
6
|
+
// check size for current file
|
7
|
+
if (file.size > maxFileUploadSize) {
|
8
|
+
errorMessages.push("file too large")
|
9
|
+
}
|
10
|
+
|
11
|
+
// check if current file has allowed file-type
|
12
|
+
if (!allowedFileExtensions.includes(getFileExtension(file.name))) {
|
13
|
+
errorMessages.push("disallowed file extension")
|
14
|
+
}
|
15
|
+
|
16
|
+
if (errorMessages.length) {
|
17
|
+
alert(errorMessages)
|
18
|
+
return
|
19
|
+
}
|
20
|
+
|
21
|
+
// check for min dimensions
|
22
|
+
const image = new Image()
|
23
|
+
|
24
|
+
image.onload = () => {
|
25
|
+
if (image.width < minImageWidth) {
|
26
|
+
// errorMessages.push("width (" + image.width + " px) too small - at least " + this.minImageWidth + " px required!")
|
27
|
+
const confirmUpload = confirm("width (" + image.width + " px) too small - at least " + minImageWidth + " px required! Use trotzdem!")
|
28
|
+
if (!confirmUpload) {
|
29
|
+
alert("Cancel")
|
30
|
+
return
|
31
|
+
}
|
32
|
+
}
|
33
|
+
// revoke URL to clean memory
|
34
|
+
URL.revokeObjectURL(image.src)
|
35
|
+
|
36
|
+
// show preview-image by assigning image.src (containing image date (not its path) to do existing contentImage source
|
37
|
+
if(typeof imagePreview === "function") {
|
38
|
+
imagePreview(image.src)
|
39
|
+
} else {
|
40
|
+
imagePreview.src = image.src
|
41
|
+
}
|
42
|
+
|
43
|
+
}
|
44
|
+
// create data-url (contains content of a file (not its path))
|
45
|
+
image.src = URL.createObjectURL(file)
|
46
|
+
}
|
47
|
+
|
48
|
+
export { checkAndUploadFile }
|
@@ -0,0 +1,42 @@
|
|
1
|
+
function findEditComponentWrapper(component) {
|
2
|
+
if (component?.$options?.name === "EditComponentWrapper") {
|
3
|
+
return component
|
4
|
+
}
|
5
|
+
if (component?.$parent) {
|
6
|
+
return findEditComponentWrapper(component.$parent)
|
7
|
+
}
|
8
|
+
return null
|
9
|
+
}
|
10
|
+
|
11
|
+
function buildComponentPath(component, ...extraPathElements) {
|
12
|
+
const path = []
|
13
|
+
for (let parent = findEditComponentWrapper(component); parent; parent = findEditComponentWrapper(parent.$parent)) {
|
14
|
+
path.unshift(...parent.componentPath)
|
15
|
+
}
|
16
|
+
path.push(...extraPathElements)
|
17
|
+
return path
|
18
|
+
}
|
19
|
+
|
20
|
+
function componentPathAsString(componentPath) {
|
21
|
+
if (Array.isArray(componentPath) && componentPath.length > 0) {
|
22
|
+
return JSON.stringify(componentPath)
|
23
|
+
}
|
24
|
+
return ""
|
25
|
+
}
|
26
|
+
|
27
|
+
function updateHandlerProvider(component, options) {
|
28
|
+
if (component?.$options?.name) {
|
29
|
+
return {
|
30
|
+
name: component.$options.name,
|
31
|
+
...options
|
32
|
+
}
|
33
|
+
}
|
34
|
+
return options
|
35
|
+
}
|
36
|
+
|
37
|
+
export {
|
38
|
+
findEditComponentWrapper,
|
39
|
+
buildComponentPath,
|
40
|
+
componentPathAsString,
|
41
|
+
updateHandlerProvider
|
42
|
+
}
|