comand-component-library 3.3.83 → 3.3.85
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/comand-component-library.js +5630 -3936
- package/dist/comand-component-library.umd.cjs +4 -4
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/App.vue +215 -112
- package/src/assets/data/component-structure.json +228 -0
- package/src/assets/data/form-elements.json +156 -0
- package/src/assets/data/opening-hours.json +79 -37
- package/src/components/CmdAddressData.vue +187 -201
- package/src/components/CmdAddressDataItem.vue +306 -0
- package/src/components/CmdBox.vue +1 -0
- package/src/components/CmdBoxWrapper.vue +53 -5
- package/src/components/CmdFancyBox.vue +31 -4
- package/src/components/CmdForm.vue +98 -4
- package/src/components/CmdFormElement.vue +5 -1
- package/src/components/CmdHeadline.vue +179 -52
- package/src/components/CmdImage.vue +150 -21
- package/src/components/CmdImageGallery.vue +88 -85
- package/src/components/CmdListOfLinks.vue +63 -43
- package/src/components/CmdListOfLinksItem.vue +97 -0
- package/src/components/CmdLoginForm.vue +3 -6
- package/src/components/CmdMultistepFormProgressBar.vue +37 -8
- package/src/components/CmdOpeningHours.vue +280 -63
- package/src/components/CmdOpeningHoursItem.vue +264 -0
- package/src/components/{CmdPager.vue → CmdPagination.vue} +2 -2
- package/src/components/CmdSlideshow.vue +137 -10
- package/src/components/CmdSocialNetworks.vue +115 -28
- package/src/components/CmdSocialNetworksItem.vue +184 -0
- package/src/components/CmdTable.vue +0 -1
- package/src/components/CmdTextImageBlock.vue +158 -0
- package/src/components/CmdThumbnailScroller.vue +132 -12
- package/src/components/CmdToggleDarkMode.vue +58 -1
- package/src/components/EditComponentWrapper.vue +553 -0
- package/src/index.js +2 -2
- package/src/mixins/EditMode.vue +28 -9
- package/src/utils/editmode.js +30 -5
- package/src/components/CmdTextBlock.vue +0 -73
- package/src/editmode/editModeContext.js +0 -50
@@ -0,0 +1,553 @@
|
|
1
|
+
<template>
|
2
|
+
<component
|
3
|
+
:is="componentTag || 'div'"
|
4
|
+
:class="['edit-component-wrapper', {active}]"
|
5
|
+
tabindex="0"
|
6
|
+
@click.stop="showActionButtons"
|
7
|
+
ref="editComponent"
|
8
|
+
:title="!active ? 'Click to select this element' : 'Select an action from the buttons in the top-left corner'"
|
9
|
+
:data-identifier="componentIdentifier">
|
10
|
+
<li v-if="componentTag === 'ul'" class="action-buttons-wrapper">
|
11
|
+
<!-- begin action-buttons -->
|
12
|
+
<ul v-show="active" class="flex-container no-flex action-buttons" :data-component="componentName">
|
13
|
+
<!-- begin add -->
|
14
|
+
<li>
|
15
|
+
<a :class="['icon-hexagon button confirm', {disabled: !addHandlerProvider && !itemProvider && !allowAddComponent}]"
|
16
|
+
href="#"
|
17
|
+
@click.prevent="addEntry($event)"
|
18
|
+
:title="!isOuterComponent ? 'Add new item/entry' : 'Add new component'">
|
19
|
+
<CmdIcon :iconClass="!isOuterComponent ? 'icon-plus' : 'icon-plus'"/>
|
20
|
+
</a>
|
21
|
+
</li>
|
22
|
+
<!-- end add -->
|
23
|
+
|
24
|
+
<!-- begin settings -->
|
25
|
+
<li>
|
26
|
+
<a :class="['icon-hexagon button primary', {disabled: editing || !hasSettings}]"
|
27
|
+
:href="editing ? null : '#'"
|
28
|
+
@click.prevent="editSettings"
|
29
|
+
title="Edit settings of this component">
|
30
|
+
<CmdIcon :iconClass="!isOuterComponent ? 'icon-cog' : 'icon-cogs'"/>
|
31
|
+
</a>
|
32
|
+
</li>
|
33
|
+
<!-- end settings -->
|
34
|
+
|
35
|
+
<!-- begin delete -->
|
36
|
+
<li>
|
37
|
+
<a class="icon-hexagon button-delete"
|
38
|
+
href="#"
|
39
|
+
@click.prevent="deleteComponent"
|
40
|
+
title="Delete this component (and its content)">
|
41
|
+
<CmdIcon iconClass="icon-trash"/>
|
42
|
+
</a>
|
43
|
+
</li>
|
44
|
+
<!-- end delete -->
|
45
|
+
|
46
|
+
<!-- begin cancel -->
|
47
|
+
<li v-if="!isOuterComponent">
|
48
|
+
<a :class="['icon-hexagon button-cancel', {disabled: !editing}]"
|
49
|
+
href="#"
|
50
|
+
@click.prevent="cancelComponent"
|
51
|
+
title="Cancel editing (changes will not be saved)">
|
52
|
+
<CmdIcon iconClass="icon-cancel"/>
|
53
|
+
</a>
|
54
|
+
</li>
|
55
|
+
<!-- end cancel -->
|
56
|
+
|
57
|
+
<!-- begin edit/save -->
|
58
|
+
<li v-if="!isOuterComponent">
|
59
|
+
<a v-if="editing"
|
60
|
+
class="icon-hexagon button-save"
|
61
|
+
href="#"
|
62
|
+
@click.prevent="saveComponent"
|
63
|
+
title="Save changes of this component">
|
64
|
+
<CmdIcon iconClass="icon-check"/>
|
65
|
+
</a>
|
66
|
+
<a v-else
|
67
|
+
:class="['icon-hexagon button', {disabled: editModeContext.settings.isEditing(componentIdentifier)}]"
|
68
|
+
href="#"
|
69
|
+
@click.prevent="editComponent"
|
70
|
+
title="Edit content of this component">
|
71
|
+
<CmdIcon iconClass="icon-edit"/>
|
72
|
+
</a>
|
73
|
+
</li>
|
74
|
+
<!-- end edit/save -->
|
75
|
+
</ul>
|
76
|
+
<!-- end action buttons -->
|
77
|
+
</li>
|
78
|
+
<template v-else>
|
79
|
+
<!-- begin action-buttons -->
|
80
|
+
<p v-if="isOuterComponent" class="component-name">{{ componentName }}</p>
|
81
|
+
<ul v-show="active"
|
82
|
+
class="flex-container no-flex action-buttons"
|
83
|
+
:data-component="componentName"
|
84
|
+
@mouseenter="addHighlightRelatedComponent"
|
85
|
+
@mouseleave="removeHighlightRelatedComponent">
|
86
|
+
<!-- begin add -->
|
87
|
+
<li>
|
88
|
+
<a :class="['icon-hexagon use-icon-as-background button confirm', {disabled: !addHandlerProvider && !itemProvider && !allowAddComponent}]"
|
89
|
+
href="#"
|
90
|
+
@click.prevent="addEntry"
|
91
|
+
:title="!isOuterComponent ? 'Add new item/entry' : 'Add new component'">
|
92
|
+
<CmdIcon :iconClass="!isOuterComponent ? 'icon-plus' : 'icon-plus'"/>
|
93
|
+
</a>
|
94
|
+
</li>
|
95
|
+
<!-- end add -->
|
96
|
+
|
97
|
+
<!-- begin settings -->
|
98
|
+
<li>
|
99
|
+
<a :class="['icon-hexagon use-icon-as-background button primary', {disabled: editing || !hasSettings}]"
|
100
|
+
:href="editing ? null : '#'"
|
101
|
+
@click.prevent="editSettings"
|
102
|
+
:title="'Edit settings for ' + componentName">
|
103
|
+
<CmdIcon :iconClass="!isOuterComponent ? 'icon-cog' : 'icon-cogs'"/>
|
104
|
+
</a>
|
105
|
+
</li>
|
106
|
+
<!-- end settings -->
|
107
|
+
|
108
|
+
<!-- begin delete -->
|
109
|
+
<li>
|
110
|
+
<a :class="['icon-hexagon use-icon-as-background button button-delete', {disabled: editing || !allowDeleteComponent}]"
|
111
|
+
href="#"
|
112
|
+
@click.prevent="deleteComponent"
|
113
|
+
:title="'Delete ' + componentName + ' (and its content)'">
|
114
|
+
<CmdIcon iconClass="icon-trash"/>
|
115
|
+
</a>
|
116
|
+
</li>
|
117
|
+
<!-- end delete -->
|
118
|
+
|
119
|
+
<!-- begin edit/save -->
|
120
|
+
<li v-if="!isOuterComponent">
|
121
|
+
<a :class="['icon-hexagon use-icon-as-background button cancel', {disabled: !editing}]"
|
122
|
+
href="#"
|
123
|
+
@click.prevent="cancelComponent"
|
124
|
+
title="Cancel editing (changes will not be saved)">
|
125
|
+
<CmdIcon iconClass="icon-cancel"/>
|
126
|
+
</a>
|
127
|
+
</li>
|
128
|
+
<li v-if="!isOuterComponent">
|
129
|
+
<a v-if="editing"
|
130
|
+
class="icon-hexagon use-icon-as-background button confirm" href="#"
|
131
|
+
@click.prevent="saveComponent"
|
132
|
+
:title="'Save changes of ' + componentName">
|
133
|
+
<CmdIcon iconClass="icon-check"/>
|
134
|
+
</a>
|
135
|
+
<a v-else
|
136
|
+
:class="['icon-hexagon use-icon-as-background button confirm', {disabled: editModeContext.settings.isEditing(componentIdentifier)}]"
|
137
|
+
href="#"
|
138
|
+
@click.prevent="editComponent"
|
139
|
+
:title="'Edit content for ' + componentName">
|
140
|
+
<CmdIcon iconClass="icon-edit"/>
|
141
|
+
</a>
|
142
|
+
</li>
|
143
|
+
<!-- end edit/save -->
|
144
|
+
</ul>
|
145
|
+
<!-- end action buttons -->
|
146
|
+
</template>
|
147
|
+
<!-- begin slot -->
|
148
|
+
<slot :editing="editing"></slot>
|
149
|
+
<!-- end slot -->
|
150
|
+
</component>
|
151
|
+
</template>
|
152
|
+
|
153
|
+
<script>
|
154
|
+
import componentStructure from "../assets/data/component-structure.json"
|
155
|
+
|
156
|
+
import {componentPathAsString, findEditComponentWrapper} from "../utils/editmode.js"
|
157
|
+
import {getCurrentInstance} from "vue"
|
158
|
+
|
159
|
+
export default {
|
160
|
+
name: "EditComponentWrapper",
|
161
|
+
inject: {
|
162
|
+
editModeContext: {
|
163
|
+
default: null
|
164
|
+
}
|
165
|
+
},
|
166
|
+
props: {
|
167
|
+
allowedComponentTypes: {
|
168
|
+
type: Array
|
169
|
+
},
|
170
|
+
componentName: {
|
171
|
+
type: String
|
172
|
+
},
|
173
|
+
componentProps: {
|
174
|
+
type: Object
|
175
|
+
},
|
176
|
+
componentPath: {
|
177
|
+
type: Array,
|
178
|
+
required: true
|
179
|
+
},
|
180
|
+
allowAddComponent: {
|
181
|
+
type: Boolean
|
182
|
+
},
|
183
|
+
allowDeleteComponent: {
|
184
|
+
type: Boolean,
|
185
|
+
default: true
|
186
|
+
},
|
187
|
+
showComponentName: {
|
188
|
+
type: Boolean,
|
189
|
+
default: true
|
190
|
+
},
|
191
|
+
componentTag: {
|
192
|
+
type: String
|
193
|
+
},
|
194
|
+
itemProvider: {
|
195
|
+
type: Function
|
196
|
+
}
|
197
|
+
},
|
198
|
+
data() {
|
199
|
+
return {
|
200
|
+
componentIdentifier: "",
|
201
|
+
editStateListeners: [],
|
202
|
+
updateHandlerProviders: [],
|
203
|
+
addHandlerProvider: null,
|
204
|
+
showComponentSelection: false,
|
205
|
+
showAddComponentButtons: false,
|
206
|
+
addComponentLevel: ""
|
207
|
+
}
|
208
|
+
},
|
209
|
+
computed: {
|
210
|
+
isOuterComponent() {
|
211
|
+
return !findEditComponentWrapper(this.$parent, component => component?.componentName !== "CmdContainer")
|
212
|
+
},
|
213
|
+
active() {
|
214
|
+
if (!this.editModeContext) {
|
215
|
+
return false
|
216
|
+
}
|
217
|
+
const parentEditComponentWrapper = findEditComponentWrapper(this.$parent, component => component?.componentName !== "CmdContainer");
|
218
|
+
if (parentEditComponentWrapper) {
|
219
|
+
return !!this.editModeContext.system.isActiveChildComponent(buildComponentPath(this))
|
220
|
+
}
|
221
|
+
return !!this.editModeContext.system.isActiveComponent(buildComponentPath(this))
|
222
|
+
},
|
223
|
+
editing() {
|
224
|
+
return this.editModeContext?.content.isEditing(this.componentIdentifier)
|
225
|
+
},
|
226
|
+
hasSettings() {
|
227
|
+
const settingsComponentName = `${this.componentName}Settings`
|
228
|
+
return !!getCurrentInstance().appContext.components[settingsComponentName]
|
229
|
+
}
|
230
|
+
},
|
231
|
+
methods: {
|
232
|
+
addHighlightRelatedComponent(event) {
|
233
|
+
const currentElement = event.target
|
234
|
+
currentElement.parentNode.classList.add("highlight")
|
235
|
+
},
|
236
|
+
removeHighlightRelatedComponent(event) {
|
237
|
+
const currentElement = event.target
|
238
|
+
currentElement.parentNode.classList.remove("highlight")
|
239
|
+
},
|
240
|
+
// provide actions from store as methods inside this component
|
241
|
+
showActionButtons() {
|
242
|
+
const parentEditComponentWrapper = findEditComponentWrapper(this.$parent, component => component?.componentName !== "CmdContainer")
|
243
|
+
this.editModeContext.system.setActiveComponent(buildComponentPath(parentEditComponentWrapper), buildComponentPath(this))
|
244
|
+
},
|
245
|
+
deleteComponent() {
|
246
|
+
if (!this.editing && this.allowDeleteComponent && confirm("Delete this component and its content?")) {
|
247
|
+
this.editModeContext?.store.deleteContent(buildComponentPath(this))
|
248
|
+
// close settings sidebar if component is deleted
|
249
|
+
this.editModeContext.settings.stopEditing()
|
250
|
+
}
|
251
|
+
},
|
252
|
+
deleteInnerComponent() {
|
253
|
+
this.editModeContext.store.deleteContent(buildComponentPath(this))
|
254
|
+
// stop editing to close settings-sidebar
|
255
|
+
this.editModeContext.settings.stopEditing()
|
256
|
+
},
|
257
|
+
cancelComponent(event) {
|
258
|
+
if (this.editing) {
|
259
|
+
event.stopPropagation()
|
260
|
+
this.editModeContext.content.stopEditing()
|
261
|
+
}
|
262
|
+
},
|
263
|
+
editComponent(event) {
|
264
|
+
event?.stopPropagation()
|
265
|
+
|
266
|
+
// avoid component from resetting editing-flag
|
267
|
+
if (!event) {
|
268
|
+
this.showActionButtons()
|
269
|
+
}
|
270
|
+
|
271
|
+
const component = this.$refs.editComponent;
|
272
|
+
this.editModeContext.content.startEditing(this.componentIdentifier)
|
273
|
+
// wait until input in inserted into DOM on next tick
|
274
|
+
this.$nextTick(() => component.querySelector("input")?.focus())
|
275
|
+
},
|
276
|
+
saveComponent() {
|
277
|
+
this.editModeContext.store.updateContent(
|
278
|
+
buildComponentPath(this),
|
279
|
+
this.updateHandlerProviders.map(provider => provider()))
|
280
|
+
this.editModeContext.content.stopEditing()
|
281
|
+
},
|
282
|
+
editSettings(event, action) {
|
283
|
+
event.stopPropagation()
|
284
|
+
|
285
|
+
if (!this.editing && this.hasSettings) {
|
286
|
+
this.editModeContext.settings.startEditing(
|
287
|
+
this.componentIdentifier,
|
288
|
+
this.componentName,
|
289
|
+
this.componentProps,
|
290
|
+
this.allowedComponentTypes,
|
291
|
+
buildComponentPath(this),
|
292
|
+
this.saveSettings,
|
293
|
+
this.deleteInnerComponent,
|
294
|
+
action || 'edit'
|
295
|
+
)
|
296
|
+
}
|
297
|
+
},
|
298
|
+
addEntry(event) {
|
299
|
+
if (this.itemProvider) {
|
300
|
+
// if related element is inner component (add item/entry)
|
301
|
+
this.editModeContext.content.addContent(buildComponentPath(this), this.itemProvider)
|
302
|
+
} else {
|
303
|
+
// if related element is outer component (open settings)
|
304
|
+
this.editSettings(event, 'add')
|
305
|
+
}
|
306
|
+
},
|
307
|
+
saveSettings(updateCallback) {
|
308
|
+
this.editModeContext.store.updateSettings(
|
309
|
+
buildComponentPath(this),
|
310
|
+
updateCallback)
|
311
|
+
this.editModeContext.settings.stopEditing()
|
312
|
+
},
|
313
|
+
addEditStateListener(listener) {
|
314
|
+
this.editStateListeners.push(listener)
|
315
|
+
listener(this.editing)
|
316
|
+
},
|
317
|
+
addUpdateHandlerProvider(updateHandlerProvider) {
|
318
|
+
this.updateHandlerProviders.push(updateHandlerProvider)
|
319
|
+
},
|
320
|
+
setAddHandlerProvider(addHandlerProvider) {
|
321
|
+
// assign given function to data-property
|
322
|
+
if (addHandlerProvider) {
|
323
|
+
this.addHandlerProvider = addHandlerProvider
|
324
|
+
}
|
325
|
+
}
|
326
|
+
},
|
327
|
+
watch: {
|
328
|
+
componentPath: {
|
329
|
+
handler() {
|
330
|
+
this.componentIdentifier = componentPathAsString(buildComponentPath(this))
|
331
|
+
},
|
332
|
+
immediate: true,
|
333
|
+
deep: true
|
334
|
+
},
|
335
|
+
editing(value) {
|
336
|
+
this.editStateListeners.forEach(listener => listener(value))
|
337
|
+
}
|
338
|
+
}
|
339
|
+
}
|
340
|
+
|
341
|
+
function buildComponentPath(component) {
|
342
|
+
const path = []
|
343
|
+
for (let parent = component; parent; parent = findEditComponentWrapper(parent.$parent)) {
|
344
|
+
if (parent.componentPath) {
|
345
|
+
path.unshift(...parent.componentPath)
|
346
|
+
}
|
347
|
+
}
|
348
|
+
return path
|
349
|
+
}
|
350
|
+
</script>
|
351
|
+
|
352
|
+
<style lang="scss">
|
353
|
+
@mixin edit-border {
|
354
|
+
border: .1rem dashed transparent;
|
355
|
+
transition: var(--default-transition);
|
356
|
+
|
357
|
+
&:hover, &:active, &:focus {
|
358
|
+
border-color: var(--primary-color);
|
359
|
+
background: hsla(0, 0%, 100%, 0.1);
|
360
|
+
transition: var(--default-transition);
|
361
|
+
}
|
362
|
+
|
363
|
+
&:focus, &.active {
|
364
|
+
border-style: solid;
|
365
|
+
border-color: var(--primary-color);
|
366
|
+
|
367
|
+
.action-buttons {
|
368
|
+
opacity: 1;
|
369
|
+
transition: var(--default-transition);
|
370
|
+
}
|
371
|
+
}
|
372
|
+
}
|
373
|
+
|
374
|
+
.edit-component-wrapper {
|
375
|
+
@include edit-border;
|
376
|
+
|
377
|
+
display: block;
|
378
|
+
|
379
|
+
&.highlight {
|
380
|
+
border-color: var(--hyperlink-color-highlighted);
|
381
|
+
border-style: dotted;
|
382
|
+
}
|
383
|
+
|
384
|
+
.cmd-headline {
|
385
|
+
margin: 0;
|
386
|
+
}
|
387
|
+
|
388
|
+
.component-name {
|
389
|
+
display: none;
|
390
|
+
position: absolute;
|
391
|
+
left: auto;
|
392
|
+
right: 10rem;
|
393
|
+
font-style: italic;
|
394
|
+
z-index: 10;
|
395
|
+
padding: .2rem;
|
396
|
+
background: var(--primary-color);
|
397
|
+
}
|
398
|
+
|
399
|
+
&.active {
|
400
|
+
.component-name {
|
401
|
+
display: block;
|
402
|
+
}
|
403
|
+
}
|
404
|
+
|
405
|
+
.action-buttons {
|
406
|
+
--action-buttons-size: 3.6rem;
|
407
|
+
|
408
|
+
transition: var(--default-transition);
|
409
|
+
gap: 0;
|
410
|
+
position: absolute;
|
411
|
+
top: -1.8rem;
|
412
|
+
right: 0.8rem;
|
413
|
+
z-index: 1;
|
414
|
+
margin: 0;
|
415
|
+
|
416
|
+
li {
|
417
|
+
&:nth-child(odd) {
|
418
|
+
top: 0;
|
419
|
+
}
|
420
|
+
|
421
|
+
&:nth-child(even) {
|
422
|
+
top: -1.6rem;
|
423
|
+
}
|
424
|
+
|
425
|
+
&:nth-child(5) {
|
426
|
+
right: 0;
|
427
|
+
}
|
428
|
+
|
429
|
+
&:nth-child(4) {
|
430
|
+
right: calc(var(--action-buttons-size) * -0.25);
|
431
|
+
}
|
432
|
+
|
433
|
+
&:nth-child(3) {
|
434
|
+
right: calc(var(--action-buttons-size) * -0.5);
|
435
|
+
}
|
436
|
+
|
437
|
+
&:nth-child(2) {
|
438
|
+
right: calc(var(--action-buttons-size) * -0.75);
|
439
|
+
}
|
440
|
+
|
441
|
+
&:nth-child(1) {
|
442
|
+
right: calc(var(--action-buttons-size) * -1);
|
443
|
+
}
|
444
|
+
}
|
445
|
+
}
|
446
|
+
|
447
|
+
.edit-items {
|
448
|
+
.action-buttons {
|
449
|
+
gap: var(--default-gap-third);
|
450
|
+
top: -2.3rem;
|
451
|
+
left: 0;
|
452
|
+
right: auto; /* avoids container to be stretched */
|
453
|
+
flex-wrap: nowrap;
|
454
|
+
border-bottom: 0;
|
455
|
+
backdrop-filter: grayscale(1) brightness(1.5) blur(2rem) opacity(85%);
|
456
|
+
border-radius: .5rem;
|
457
|
+
|
458
|
+
li {
|
459
|
+
top: 0;
|
460
|
+
right: 0;
|
461
|
+
left: auto;
|
462
|
+
|
463
|
+
&:nth-child(5) {
|
464
|
+
right: 0;
|
465
|
+
}
|
466
|
+
|
467
|
+
&:nth-child(4) {
|
468
|
+
right: var(--icon-font-size);
|
469
|
+
}
|
470
|
+
|
471
|
+
&:nth-child(3) {
|
472
|
+
right: calc(var(--icon-font-size) * 2);
|
473
|
+
}
|
474
|
+
|
475
|
+
&:nth-child(2) {
|
476
|
+
right: calc(var(--icon-font-size) * 3);
|
477
|
+
}
|
478
|
+
|
479
|
+
&:nth-child(1) {
|
480
|
+
right: calc(var(--icon-font-size) * 4);
|
481
|
+
}
|
482
|
+
|
483
|
+
a.button {
|
484
|
+
border-radius: var(--full-circle);
|
485
|
+
font-size: 1rem;
|
486
|
+
display: block;
|
487
|
+
padding: 0.5rem;
|
488
|
+
background: var(--button-background-color);
|
489
|
+
|
490
|
+
&:before {
|
491
|
+
content: "";
|
492
|
+
font-size: 1rem;
|
493
|
+
|
494
|
+
}
|
495
|
+
|
496
|
+
span[class*="icon-"] {
|
497
|
+
font-size: var(--icon-size-small);
|
498
|
+
position: relative;
|
499
|
+
top: 0;
|
500
|
+
left: 0;
|
501
|
+
transform: none;
|
502
|
+
}
|
503
|
+
|
504
|
+
&.primary {
|
505
|
+
background: var(--primary-color);
|
506
|
+
}
|
507
|
+
}
|
508
|
+
}
|
509
|
+
}
|
510
|
+
|
511
|
+
&.active {
|
512
|
+
//width: 100%; /* stretch inside flex-container */
|
513
|
+
background: var(--pure-white);
|
514
|
+
}
|
515
|
+
}
|
516
|
+
|
517
|
+
// begin component-level only
|
518
|
+
&:not(.edit-items) {
|
519
|
+
> ul {
|
520
|
+
> li {
|
521
|
+
a.button {
|
522
|
+
background: none !important;
|
523
|
+
}
|
524
|
+
}
|
525
|
+
}
|
526
|
+
}
|
527
|
+
// end component-level only
|
528
|
+
}
|
529
|
+
|
530
|
+
ul.edit-component-wrapper {
|
531
|
+
border: 0;
|
532
|
+
|
533
|
+
> li {
|
534
|
+
list-style-type: none;
|
535
|
+
margin: 0;
|
536
|
+
|
537
|
+
&.action-buttons-wrapper {
|
538
|
+
display: flex;
|
539
|
+
justify-content: flex-end;
|
540
|
+
padding-top: .1rem;
|
541
|
+
|
542
|
+
.action-buttons {
|
543
|
+
position: relative;
|
544
|
+
top: auto;
|
545
|
+
}
|
546
|
+
}
|
547
|
+
|
548
|
+
&.item-wrapper {
|
549
|
+
@include edit-border;
|
550
|
+
}
|
551
|
+
}
|
552
|
+
}
|
553
|
+
</style>
|
package/src/index.js
CHANGED
@@ -25,7 +25,7 @@ export { default as CmdLoginForm } from '@/components/CmdLoginForm.vue'
|
|
25
25
|
export { default as CmdMainNavigation } from '@/components/CmdMainNavigation.vue'
|
26
26
|
export { default as CmdMultistepFormProgressBar } from '@/components/CmdMultistepFormProgressBar.vue'
|
27
27
|
export { default as CmdOpeningHours } from '@/components/CmdOpeningHours.vue'
|
28
|
-
export { default as CmdPager } from '@/components/
|
28
|
+
export { default as CmdPager } from '@/components/CmdPagination.vue'
|
29
29
|
export { default as CmdProgressBar } from '@/components/CmdProgressBar.vue'
|
30
30
|
export { default as CmdSidebar } from '@/components/CmdSidebar.vue'
|
31
31
|
export { default as CmdSiteFooter } from '@/components/CmdSiteFooter.vue'
|
@@ -38,7 +38,7 @@ export { default as CmdSwitchLanguage } from '@/components/CmdSwitchLanguage.vue
|
|
38
38
|
export { default as CmdSystemMessage } from '@/components/CmdSystemMessage.vue'
|
39
39
|
export { default as CmdTable } from '@/components/CmdTable.vue'
|
40
40
|
export { default as CmdTabs } from '@/components/CmdTabs.vue'
|
41
|
-
export { default as
|
41
|
+
export { default as CmdTextImageBlock } from '@/components/CmdTextImageBlock.vue'
|
42
42
|
export { default as CmdThumbnailScroller } from '@/components/CmdThumbnailScroller.vue'
|
43
43
|
export { default as CmdToggleDarkMode } from '@/components/CmdToggleDarkMode.vue'
|
44
44
|
export { default as CmdTooltip } from '@/components/CmdTooltip.vue'
|
package/src/mixins/EditMode.vue
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<script>
|
2
|
-
import {findEditComponentWrapper} from "../utils/editmode.js"
|
2
|
+
import {findEditComponentWrapper, findEditSettingsComponentWrapper, findMainSidebar} from "../utils/editmode.js"
|
3
3
|
|
4
4
|
export default {
|
5
5
|
inject: {
|
@@ -7,20 +7,39 @@ export default {
|
|
7
7
|
default: null
|
8
8
|
}
|
9
9
|
},
|
10
|
+
props: {
|
11
|
+
componentPath: {
|
12
|
+
type: Array
|
13
|
+
},
|
14
|
+
editModeConfig: {
|
15
|
+
type: Object
|
16
|
+
}
|
17
|
+
},
|
10
18
|
data() {
|
11
19
|
return {
|
12
|
-
editing: false
|
20
|
+
editing: false,
|
21
|
+
settingsContext: false,
|
22
|
+
mainSidebarContext: false
|
13
23
|
}
|
14
24
|
},
|
15
|
-
|
16
|
-
|
17
|
-
if (editComponentWrapper) {
|
18
|
-
editComponentWrapper.addEditStateListener(editing => this.editing = editing)
|
19
|
-
editComponentWrapper.addUpdateHandlerProvider(this.updateHandlerProvider)
|
20
|
-
editComponentWrapper.setAddHandlerProvider(this.addHandlerProvider)
|
21
|
-
}
|
25
|
+
mounted() {
|
26
|
+
this.initializeEditMode()
|
22
27
|
},
|
23
28
|
methods: {
|
29
|
+
initializeEditMode() {
|
30
|
+
if (this.$refs.editComponentWrapper) {
|
31
|
+
this.$refs.editComponentWrapper?.addUpdateHandlerProvider(this.updateHandlerProvider)
|
32
|
+
} else {
|
33
|
+
const editComponentWrapper = findEditComponentWrapper(this.$parent);
|
34
|
+
if (editComponentWrapper) {
|
35
|
+
editComponentWrapper.addEditStateListener(editing => this.editing = editing)
|
36
|
+
editComponentWrapper.addUpdateHandlerProvider(this.updateHandlerProvider)
|
37
|
+
editComponentWrapper.setAddHandlerProvider(this.addHandlerProvider)
|
38
|
+
}
|
39
|
+
}
|
40
|
+
this.mainSidebarContext = !!findMainSidebar(this)
|
41
|
+
this.settingsContext = !!findEditSettingsComponentWrapper(this)
|
42
|
+
},
|
24
43
|
updateHandlerProvider() {
|
25
44
|
return {}
|
26
45
|
}
|
package/src/utils/editmode.js
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
-
function findEditComponentWrapper(component) {
|
2
|
-
|
1
|
+
function findEditComponentWrapper(component, filter) {
|
2
|
+
return findParentComponent(component, "EditComponentWrapper", filter)
|
3
|
+
}
|
4
|
+
|
5
|
+
function findEditSettingsComponentWrapper(component) {
|
6
|
+
return findParentComponent(component, "EditModeSettingsSidebar")
|
7
|
+
}
|
8
|
+
|
9
|
+
function findMainSidebar(component) {
|
10
|
+
return findParentComponent(component, "EditModeMainSidebar")
|
11
|
+
}
|
12
|
+
|
13
|
+
function findParentComponent(component, parentComponentName, filter) {
|
14
|
+
if (component?.$options?.name === parentComponentName && (filter == null || filter(component))) {
|
3
15
|
return component
|
4
16
|
}
|
5
17
|
if (component?.$parent) {
|
6
|
-
return
|
18
|
+
return findParentComponent(component.$parent, parentComponentName, filter)
|
7
19
|
}
|
8
20
|
return null
|
9
21
|
}
|
@@ -11,7 +23,9 @@ function findEditComponentWrapper(component) {
|
|
11
23
|
function buildComponentPath(component, ...extraPathElements) {
|
12
24
|
const path = []
|
13
25
|
for (let parent = findEditComponentWrapper(component); parent; parent = findEditComponentWrapper(parent.$parent)) {
|
14
|
-
|
26
|
+
if (parent.componentPath) {
|
27
|
+
path.unshift(...parent.componentPath);
|
28
|
+
}
|
15
29
|
}
|
16
30
|
path.push(...extraPathElements)
|
17
31
|
return path
|
@@ -34,9 +48,20 @@ function updateHandlerProvider(component, options) {
|
|
34
48
|
return options
|
35
49
|
}
|
36
50
|
|
51
|
+
function highlightSection(sectionId) {
|
52
|
+
document.querySelectorAll(".section-wrapper.active").forEach((section) => section.classList.remove("active"))
|
53
|
+
// get the edit-mode-wrapper of a section
|
54
|
+
const element = document.getElementById("edit-mode-" + sectionId)
|
55
|
+
element.scrollIntoView()
|
56
|
+
element.classList.add("active")
|
57
|
+
}
|
58
|
+
|
37
59
|
export {
|
38
60
|
findEditComponentWrapper,
|
61
|
+
findEditSettingsComponentWrapper,
|
62
|
+
findMainSidebar,
|
39
63
|
buildComponentPath,
|
40
64
|
componentPathAsString,
|
41
|
-
updateHandlerProvider
|
65
|
+
updateHandlerProvider,
|
66
|
+
highlightSection
|
42
67
|
}
|