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.
Files changed (38) hide show
  1. package/dist/comand-component-library.js +5630 -3936
  2. package/dist/comand-component-library.umd.cjs +4 -4
  3. package/dist/style.css +1 -1
  4. package/package.json +2 -2
  5. package/src/App.vue +215 -112
  6. package/src/assets/data/component-structure.json +228 -0
  7. package/src/assets/data/form-elements.json +156 -0
  8. package/src/assets/data/opening-hours.json +79 -37
  9. package/src/components/CmdAddressData.vue +187 -201
  10. package/src/components/CmdAddressDataItem.vue +306 -0
  11. package/src/components/CmdBox.vue +1 -0
  12. package/src/components/CmdBoxWrapper.vue +53 -5
  13. package/src/components/CmdFancyBox.vue +31 -4
  14. package/src/components/CmdForm.vue +98 -4
  15. package/src/components/CmdFormElement.vue +5 -1
  16. package/src/components/CmdHeadline.vue +179 -52
  17. package/src/components/CmdImage.vue +150 -21
  18. package/src/components/CmdImageGallery.vue +88 -85
  19. package/src/components/CmdListOfLinks.vue +63 -43
  20. package/src/components/CmdListOfLinksItem.vue +97 -0
  21. package/src/components/CmdLoginForm.vue +3 -6
  22. package/src/components/CmdMultistepFormProgressBar.vue +37 -8
  23. package/src/components/CmdOpeningHours.vue +280 -63
  24. package/src/components/CmdOpeningHoursItem.vue +264 -0
  25. package/src/components/{CmdPager.vue → CmdPagination.vue} +2 -2
  26. package/src/components/CmdSlideshow.vue +137 -10
  27. package/src/components/CmdSocialNetworks.vue +115 -28
  28. package/src/components/CmdSocialNetworksItem.vue +184 -0
  29. package/src/components/CmdTable.vue +0 -1
  30. package/src/components/CmdTextImageBlock.vue +158 -0
  31. package/src/components/CmdThumbnailScroller.vue +132 -12
  32. package/src/components/CmdToggleDarkMode.vue +58 -1
  33. package/src/components/EditComponentWrapper.vue +553 -0
  34. package/src/index.js +2 -2
  35. package/src/mixins/EditMode.vue +28 -9
  36. package/src/utils/editmode.js +30 -5
  37. package/src/components/CmdTextBlock.vue +0 -73
  38. package/src/editmode/editModeContext.js +0 -50
@@ -0,0 +1,264 @@
1
+ <template>
2
+ <!-- begin opening-days and -hours -->
3
+ <template v-if="!editing">
4
+ <dt class="cmd-opening-hours-item">{{ day.day }}</dt>
5
+ <dd>
6
+ <span v-if="day.am" class="am">
7
+ <template v-if="day.am.displayText">{{ day.am.displayText }}</template>
8
+ <template
9
+ v-else>{{ getTime(day.am.fromTime) }} {{ separator }} {{
10
+ getTime(day.am.tillTime)
11
+ }}</template>
12
+ </span>
13
+ <span v-if="day.pm" class="pm">
14
+ <template v-if="day.pm.displayText">{{ day.pm.displayText }}</template>
15
+ <template
16
+ v-else>{{ getTime(day.pm.fromTime) }} {{ separator }} {{
17
+ getTime(day.pm.tillTime)
18
+ }}</template>
19
+ </span>
20
+ </dd>
21
+ </template>
22
+ <!-- end opening-days and -hours -->
23
+
24
+ <!-- begin edit-mode -->
25
+ <template v-else>
26
+ <!-- begin day -->
27
+ <dt>
28
+ <CmdFormElement
29
+ element="input"
30
+ type="text"
31
+ class="edit-mode"
32
+ :showLabel="false"
33
+ labelText="Text for weekday"
34
+ placeholder="Text for weekday"
35
+ v-model="editableDay.day"
36
+ />
37
+ </dt>
38
+ <!-- end day -->
39
+
40
+ <!-- begin hours -->
41
+ <dd class="flex-container no-flex">
42
+ <!-- begin AM -->
43
+ <div class="flex-container no-flex am-wrapper">
44
+ <template v-if="editableDay.amClosed">
45
+ <CmdFormElement
46
+ element="input"
47
+ type="text"
48
+ class="edit-mode"
49
+ :showLabel="false"
50
+ labelText="Text for 'closed'"
51
+ placeholder="Text for 'closed'"
52
+ v-model="editableDay.amDisplayText"
53
+ />
54
+ </template>
55
+ <div v-if="!editableDay.amClosed" class="input-wrapper">
56
+ <CmdFormElement
57
+ element="input"
58
+ type="time"
59
+ class="edit-mode"
60
+ :showLabel="false"
61
+ labelText="Text for AM from"
62
+ placeholder="Text for AM from"
63
+ v-model="editableDay.amFrom"
64
+ />
65
+ <CmdFormElement
66
+ element="input"
67
+ type="time"
68
+ :showLabel="false"
69
+ class="edit-mode"
70
+ :min="editableDay.amFrom"
71
+ labelText="Text for AM till"
72
+ placeholder="Text for AM till"
73
+ v-model="editableDay.amTill"
74
+ />
75
+ </div>
76
+ <a href="#"
77
+ @click.prevent="toggleClosedStatus('am')"
78
+ :title="editableDay.amClosed ? 'Set to open' : 'Set to closed'"
79
+ :class="editableDay.amClosed ? 'icon-clock' : 'icon-blocked'"
80
+ ></a>
81
+ </div>
82
+ <!-- end AM -->
83
+
84
+ <!-- begin PM -->
85
+ <div class="flex-container no-flex pm-wrapper">
86
+ <template v-if="editableDay.pmClosed">
87
+ <CmdFormElement
88
+ element="input"
89
+ type="text"
90
+ class="edit-mode"
91
+ :showLabel="false"
92
+ labelText="Text for 'closed'"
93
+ placeholder="Text for 'closed'"
94
+ v-model="editableDay.pmDisplayText"
95
+ />
96
+ </template>
97
+ <div v-if="!editableDay.pmClosed" class="input-wrapper">
98
+ <CmdFormElement
99
+ element="input"
100
+ type="time"
101
+ :showLabel="false"
102
+ class="edit-mode"
103
+ labelText="Text for PM from"
104
+ placeholder="Text for PM from"
105
+ v-model="editableDay.pmFrom"
106
+ />
107
+ <CmdFormElement
108
+ element="input"
109
+ type="time"
110
+ :showLabel="false"
111
+ class="edit-mode"
112
+ :min="editableDay.pmFrom"
113
+ labelText="Text for PM till"
114
+ placeholder="Text for PM till"
115
+ v-model="editableDay.pmTill"
116
+ />
117
+ </div>
118
+ <a href="#"
119
+ @click.prevent="toggleClosedStatus('pm')"
120
+ :title="editableDay.pmClosed ? 'Set to open' : 'Set to closed'"
121
+ :class="editableDay.pmClosed ? 'icon-clock' : 'icon-blocked'"
122
+ ></a>
123
+ </div>
124
+ <!-- end PM -->
125
+ </dd>
126
+ <!-- end hours -->
127
+ </template>
128
+ <!-- end edit-mode -->
129
+ </template>
130
+
131
+ <script>
132
+ import EditMode from "../mixins/EditMode.vue"
133
+ import {updateHandlerProvider} from "../utils/editmode.js"
134
+
135
+ function timeFormatting(separator, suffix1, suffix2, hoursLeadingZero = true) {
136
+ function addLeadingZero(time, addLeadingZero) {
137
+ if (addLeadingZero && time < 10) {
138
+ return "0" + time
139
+ }
140
+ return time
141
+ }
142
+
143
+ return (hour, minute) => {
144
+ if (suffix2) {
145
+ let hour12 = hour
146
+ let currentSuffix = suffix1
147
+ if (hour12 > 12) {
148
+ hour12 -= 12
149
+ currentSuffix = suffix2
150
+ }
151
+ return addLeadingZero(hour12, hoursLeadingZero) + separator + addLeadingZero(minute, true) + currentSuffix
152
+ }
153
+ return addLeadingZero(hour, hoursLeadingZero) + separator + addLeadingZero(minute, true) + suffix1
154
+ }
155
+ }
156
+
157
+ export default {
158
+ name: "CmdOpeningHoursItem",
159
+ mixins: [EditMode],
160
+ data() {
161
+ return {
162
+ editableDay: {}
163
+ }
164
+ },
165
+ props: {
166
+ /**
167
+ * list of opening-hours
168
+ */
169
+ day: {
170
+ type: Object,
171
+ required: true
172
+ },
173
+ /**
174
+ * separator for time-spans
175
+ */
176
+ separator: {
177
+ type: String,
178
+ default: "–"
179
+ },
180
+ /**
181
+ * abbreviation text for 'hours' (as a unit after displayed times)
182
+ */
183
+ abbreviationText: {
184
+ type: String,
185
+ default: "h"
186
+ },
187
+ /**
188
+ * option to set custom time format by function
189
+ */
190
+ timeFormatter: {
191
+ type: Function,
192
+ required: false
193
+ }
194
+ },
195
+ methods: {
196
+ toggleClosedStatus(period) {
197
+ period === 'am' ? this.editableDay.amClosed = !this.editableDay.amClosed : this.editableDay.pmClosed = !this.editableDay.pmClosed
198
+ },
199
+ getTime(time) {
200
+ if (this.timeFormatter) {
201
+ return this.timeFormatter(time.hours, time.mins)
202
+ }
203
+ return timeFormatting(":", " " + this.abbreviationText, "", false)(time.hours, time.mins)
204
+ },
205
+ updateHandlerProvider() {
206
+ const data = this.editableDay
207
+ return updateHandlerProvider(this, {
208
+ update(props) {
209
+ props.day = data.day
210
+ if (!props.am) {
211
+ props.am = {}
212
+ }
213
+ props.am.fromTime = data.amFrom
214
+ props.am.tillTime = data.amTill
215
+ props.am.displayText = data.amClosed ? data.amDisplayText : ""
216
+ if (!props.pm) {
217
+ props.pm = {}
218
+ }
219
+ props.pm.fromTime = data.pmFrom
220
+ props.pm.tillTime = data.pmTill
221
+ props.pm.displayText = data.pmClosed ? data.pmDisplayText : ""
222
+ }
223
+ })
224
+ }
225
+ },
226
+ watch: {
227
+ day: {
228
+ handler() {
229
+ const timeFormatter = timeFormatting(":", "", "", true)
230
+ this.editableDay = {
231
+ day: this.day.day,
232
+ amFrom: timeFormatter(this.day.am.fromTime.hours, this.day.am.fromTime.mins),
233
+ amTill: timeFormatter(this.day.am.tillTime.hours, this.day.am.tillTime.mins),
234
+ amDisplayText: this.day.am.displayText,
235
+ amClosed: !!this.day.am.displayText,
236
+ pmFrom: timeFormatter(this.day.pm.fromTime.hours, this.day.pm.fromTime.mins),
237
+ pmTill: timeFormatter(this.day.pm.tillTime.hours, this.day.pm.tillTime.mins),
238
+ pmClosed: !!this.day.pm.displayText,
239
+ pmDisplayText: this.day.pm.displayText
240
+ }
241
+ },
242
+ immediate: true,
243
+ deep: true
244
+ }
245
+ }
246
+ }
247
+ </script>
248
+
249
+ <style lang="scss">
250
+ .edit-mode-opening-hours-item {
251
+ .am-wrapper, .pm-wrapper {
252
+ align-items: center;
253
+ gap: calc(var(--default-gap) / 2);
254
+ }
255
+
256
+ label {
257
+ max-width: 11rem;
258
+ }
259
+
260
+ .input-wrapper {
261
+ width: 11rem;
262
+ }
263
+ }
264
+ </style>
@@ -166,7 +166,7 @@ export default {
166
166
  </script>
167
167
 
168
168
  <style lang="scss">
169
- /* begin cmd-pager ---------------------------------------------------------------------------------------- */
169
+ /* begin cmd-pagination ---------------------------------------------------------------------------------------- */
170
170
  @import '../assets/styles/variables';
171
171
 
172
172
  .cmd-pager {
@@ -233,5 +233,5 @@ export default {
233
233
  }
234
234
  }
235
235
 
236
- /* end cmd-pager ------------------------------------------------------------------------------------------ */
236
+ /* end cmd-pagination ------------------------------------------------------------------------------------------ */
237
237
  </style>
@@ -3,8 +3,11 @@
3
3
  <div class="inner-slideshow-wrapper" @mouseenter="pause = true" @mouseleave="pause = false">
4
4
  <!-- begin CmdSlideButton -->
5
5
  <CmdSlideButton
6
+ v-if="showSlideButtons"
6
7
  @click.prevent="showPrevItem"
7
8
  slideButtonType="prev"
9
+ :class="{'disabled': slideshowItemEditing}"
10
+ v-bind="tooltipForSlidebuttons"
8
11
  />
9
12
  <!-- end CmdSlideButton -->
10
13
 
@@ -12,19 +15,34 @@
12
15
  <transition-group name="fade">
13
16
  <template v-if="currentItem">
14
17
  <template v-if="!useSlot">
15
- <a v-if="currentItem?.link?.href" :href="currentItem?.link?.href" :title="currentItem?.link?.tooltip" :key="index">
18
+ <template v-if="!editModeContext">
19
+ <a v-if="currentItem?.link?.href" :href="currentItem?.link?.href"
20
+ :title="currentItem?.link?.tooltip">
16
21
  <!-- begin CmdImage -->
17
22
  <CmdImage :image="currentItem?.image" :figcaption="currentItem?.figcaption"/>
18
23
  <!-- begin CmdImage -->
19
24
  </a>
20
25
 
21
26
  <!-- begin CmdImage -->
22
- <CmdImage v-else :image="currentItem?.image" :figcaption="currentItem?.figcaption" :key="index"/>
27
+ <CmdImage v-else :image="currentItem?.image" :figcaption="currentItem?.figcaption"/>
28
+ <!-- begin CmdImage -->
29
+ </template>
30
+
31
+ <!-- begin edit-mode view -->
23
32
  <!-- begin CmdImage -->
33
+ <CmdImage
34
+ v-else-if="slideshowItems.length"
35
+ :image="currentItem?.image"
36
+ :figcaption="currentItem?.figcaption"
37
+ :componentPath="['props', 'slideshowItems', index]"
38
+ :editModeConfig="imageStructure()"
39
+ />
40
+ <!-- end CmdImage -->
41
+ <!-- end edit-mode view -->
24
42
  </template>
25
43
  <div
26
44
  v-else
27
- class="image-wrapper"
45
+ class="slot-wrapper"
28
46
  :key="index"
29
47
  :style="'background-image: url(' + currentItem.image.srcLarge + ')'"
30
48
  >
@@ -33,35 +51,54 @@
33
51
  <!-- end slot -->
34
52
  </div>
35
53
  </template>
54
+ <button v-else-if="editModeContext" type="button" class="button confirm" @click="onAddItem">
55
+ <span class="icon-plus"></span>
56
+ <span>Add new slideshow-image</span>
57
+ </button>
36
58
  </transition-group>
37
59
  <!-- end area to slide -->
38
60
 
39
61
  <!-- begin CmdSlideButton -->
40
62
  <CmdSlideButton
63
+ v-if="showSlideButtons"
41
64
  @click.prevent="showNextItem"
65
+ :class="{'disabled': slideshowItemEditing}"
66
+ v-bind="tooltipForSlidebuttons"
42
67
  />
43
68
  <!-- end CmdSlideButton -->
44
69
 
45
70
  <ol v-if="showQuickLinkIcons">
46
71
  <li v-for="(item, i) in slideshowItems" :key="i" :class="{active: i === index }">
47
- <a href="#" @click.prevent="index = i" :aria-label="index"></a>
72
+ <a href="#"
73
+ :class="{'disabled': slideshowItemEditing}"
74
+ @click.prevent="showItem(i)"
75
+ :aria-label="index"
76
+ :title="slideshowItemEditing ? 'Not allowed while editing!' : 'Switch to image #' + (i + 1)"
77
+ >
78
+ </a>
48
79
  </li>
49
80
  </ol>
50
- <span v-if="showCounter">{{ index + 1 }}/{{ slideshowItems.length }}</span>
81
+ <span class="item-counter" v-if="showCounter">{{ index + 1 }}/{{ slideshowItems.length }}</span>
51
82
  </div>
52
83
  </div>
53
84
  </template>
54
85
 
55
86
  <script>
87
+ // import mixins
88
+ import EditMode from "../mixins/EditMode.vue"
89
+ import {buildComponentPath, updateHandlerProvider} from "../utils/editmode.js"
90
+ import {createUuid} from "../utils/common.js"
56
91
  export default {
57
92
  name: "CmdSlideshow",
93
+ mixins: [EditMode],
58
94
  data() {
59
95
  return {
60
96
  index: 0,
61
97
  pause: false,
62
98
  hnd: null,
63
99
  fullWidth: false,
64
- currentSlotItem: 0
100
+ currentSlotItem: 0,
101
+ slideshowItemEditing: false
65
102
  }
66
103
  },
67
104
  props: {
@@ -107,9 +144,18 @@ export default {
107
144
  type: Array,
108
145
  required: true
109
146
  },
147
+ /**
148
+ * toggle slide-buttons-visibility
149
+ */
150
+ showSlideButtons: {
151
+ type: Boolean,
152
+ default: false
153
+ },
110
154
  /**
111
155
  * properties for CmdSlideButtons-component
112
156
  *
157
+ * showSlideButtons-property must be activated
158
+ *
113
159
  * @requiredForAccessibility: partial
114
160
  */
115
161
  cmdSlideButtons: {
@@ -140,7 +186,50 @@ export default {
140
186
  }
141
187
  },
142
188
  methods: {
189
+ itemProvider() {
190
+ return {
191
+ "image": {
192
+ "src": {
193
+ "large": "/media/images/slideshow-images/large/slide1.jpg",
194
+ "medium": "/media/images/slideshow-images/medium/slide1.jpg",
195
+ "small": "/media/images/slideshow-images/small/slide1.jpg"
196
+ },
197
+ "alt": "Alternative Text",
198
+ "tooltip": "Tooltip DE"
199
+ },
200
+ "figcaption": {
201
+ "text": "Figcaption DE",
202
+ "position": "bottom",
203
+ "textAlign": "center",
204
+ "show": true
205
+ }
206
+ }
207
+ },
208
+ onAddItem() {
209
+ this.editModeContext.content.addContent(
210
+ buildComponentPath(this, 'props', 'slideshowItems', -1),
211
+ this.itemProvider)
212
+ },
213
+ imageStructure() {
214
+ return {
215
+ itemProviderOverwrite: () => ({
216
+ "image": {
217
+ "src": {
218
+ "large": "/media/images/slideshow-images/large/slide1.jpg",
219
+ "medium": "/media/images/slideshow-images/medium/slide1.jpg",
220
+ "small": "/media/images/slideshow-images/small/slide1.jpg"
221
+ },
222
+ "tooltip": "Tooltip DE"
223
+ }
224
+ })
225
+ }
226
+ },
143
227
  showPrevItem() {
228
+ // avoids slide-button to be clicked in edit-mode
229
+ if (this.slideshowItemEditing) {
230
+ return
231
+ }
232
+
144
233
  if (this.useSlot) {
145
234
  if (this.currentSlotItem > 0) {
146
235
  this.currentSlotItem--
@@ -155,11 +244,16 @@ export default {
155
244
  }
156
245
  },
157
246
  showItem(i) {
158
- if (i >= 0 && i < this.slideshowItems.length) {
247
+ if (!this.slideshowItemEditing && i >= 0 && i < this.slideshowItems.length) {
159
248
  this.index = i;
160
249
  }
161
250
  },
162
251
  showNextItem() {
252
+ // avoids slide-button to be clicked in edit-mode
253
+ if (this.slideshowItemEditing) {
254
+ return
255
+ }
256
+
163
257
  if (this.useSlot) {
164
258
  if (this.currentSlotItem < Object.keys(this.$slots).length - 1) {
165
259
  this.currentSlotItem++
@@ -183,6 +277,15 @@ export default {
183
277
 
184
278
  /* computed property to get current slide */
185
279
  computed: {
280
+ tooltipForSlidebuttons() {
281
+ if (this.slideshowItemEditing) {
282
+ return {
283
+ title: "Not allowed while editing!"
284
+ }
285
+ }
286
+ return {}
287
+ },
288
+ /* computed property to get current slide */
186
289
  currentItem() {
187
290
  if (this.slideshowItems.length <= this.index) {
188
291
  return null
@@ -196,7 +299,15 @@ export default {
196
299
  this.index = 0
197
300
  this.setupSlider()
198
301
  },
199
- immediate: true
302
+ immediate: true,
303
+ deep: true
304
+ },
305
+ currentItem() {
306
+ // wait to nextTick to ensure ref is available
307
+ this.$nextTick(() => {
308
+ this.$refs.slideshowItemComponentWrapper?.addEditStateListener(editing => this.slideshowItemEditing = editing)
309
+ })
310
+
200
311
  }
201
312
  }
202
313
  }
@@ -247,7 +358,7 @@ export default {
247
358
  margin: 0;
248
359
  }
249
360
 
250
- .image-wrapper {
361
+ .slot-wrapper {
251
362
  padding: calc(var(--default-padding) * 5);
252
363
  width: 100%;
253
364
  min-height: 50rem;
@@ -262,6 +373,12 @@ export default {
262
373
  }
263
374
  }
264
375
 
376
+ .image-wrapper {
377
+ width: 100%;
378
+ min-width: 11.1rem; // assure to be as wide as action-buttons in edit-mode
379
+ min-height: 50rem;
380
+ }
381
+
265
382
  > ol {
266
383
  display: -webkit-flex; /* Safari 6-8 */
267
384
  display: flex;
@@ -277,6 +394,7 @@ export default {
277
394
  margin: 0;
278
395
  border: var(--default-border-reduced-opacity);
279
396
  border-radius: var(--full-circle);
397
+ background: var(--light-gray);
280
398
 
281
399
  a {
282
400
  display: block;
@@ -321,7 +439,7 @@ export default {
321
439
  }
322
440
  }
323
441
 
324
- > span {
442
+ > .item-counter {
325
443
  position: absolute;
326
444
  top: .5rem;
327
445
  right: 5.5rem;
@@ -338,5 +456,14 @@ export default {
338
456
  }
339
457
  }
340
458
 
459
+ .edit-mode .cmd-slideshow .image-wrapper.edit-items {
460
+ padding: 0;
461
+ margin-top: 2rem;
462
+
463
+ label.edit-mode input {
464
+ font-size: 3rem;
465
+ }
466
+ }
467
+
341
468
  /* end cmd-slideshow ------------------------------------------------------------------------------------------ */
342
469
  </style>