comand-component-library 3.3.84 → 3.3.86
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 +5623 -3929
- 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 +205 -76
- 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
|
}
|