comand-component-library 3.1.86 → 3.1.89

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,29 +1,39 @@
1
1
  [
2
2
  {
3
3
  "day": "Mo",
4
- "fromTime": "08:00h",
5
- "tillTime": "17:00h"
4
+ "fromTime": "08:00",
5
+ "tillTime": "17:00"
6
6
  },
7
7
  {
8
8
  "day": "Tu",
9
- "fromTime": "08:00h",
10
- "tillTime": "17:00h"
9
+ "fromTime": "08:00",
10
+ "tillTime": "17:00"
11
11
  },
12
12
  {
13
13
  "day": "We",
14
- "fromTime": "08:00h",
15
- "tillTime": "17:30h"
14
+ "fromTime": "08:00",
15
+ "tillTime": "17:30"
16
16
  },
17
17
 
18
18
  {
19
19
  "day": "Th",
20
- "fromTime": "08:00h",
21
- "tillTime": "17:00h"
20
+ "fromTime": "08:00",
21
+ "tillTime": "17:00"
22
22
  },
23
23
  {
24
24
  "day": "Fr",
25
- "fromTime": "08:00h",
26
- "tillTime": "15:00h"
25
+ "fromTime": "08:00",
26
+ "tillTime": "15:00"
27
+ },
28
+ {
29
+ "day": "Sa",
30
+ "fromTime": "08:00",
31
+ "tillTime": "17:28"
32
+ },
33
+ {
34
+ "day": "So",
35
+ "fromTime": "08:00",
36
+ "tillTime": "22:22"
27
37
  }
28
38
  ]
29
39
 
@@ -4,6 +4,12 @@
4
4
  /*
5
5
  - IMPORTS ------------------------
6
6
  - COMPONENTS AND GLOBAL STYLES ------------------------
7
+ * ------------------------
8
+ - main structure
9
+
10
+ A ------------------------
11
+ - avoid-scrolling
12
+
7
13
  E ------------------------
8
14
  - error-styles (for form-elements)
9
15
 
@@ -33,12 +39,23 @@
33
39
  @import 'variables'; /* scss-variables (only used for media-query-breakpoints) */
34
40
  /* ---------------------------------------------- END IMPORTS -------------------------------------------------- */
35
41
 
42
+ /* ---------------------------------------------- BEGIN COMPONENTS AND GLOBAL STYLES -------------------------------------------------- */
43
+ /* begin styles for main structure --------------------------------------------------------------------------------------------------------------------------------------------------- */
44
+ #page-wrapper {
45
+ display: flex;
46
+ flex-direction: column;
47
+ min-height: 100vh;
48
+
49
+ .cmd-site-footer {
50
+ margin-top: auto;
51
+ }
52
+ }
53
+
36
54
  body, .cmd-site-header, .cmd-site-footer, .cmd-copyright-information {
37
55
  transition: background linear .5s;
38
56
  }
57
+ /* end styles for main structure --------------------------------------------------------------------------------------------------------------------------------------------------- */
39
58
 
40
-
41
- /* ---------------------------------------------- BEGIN COMPONENTS AND GLOBAL STYLES -------------------------------------------------- */
42
59
  /* begin .avoid-scrolling --------------------------------------------------------------------------------------------------------------------------------------------------- */
43
60
  body.avoid-scrolling {
44
61
  overflow: hidden;
@@ -271,7 +288,7 @@ html {
271
288
  --color-scheme-background-inverted: var(--light-mode-background-color);
272
289
  --default-background-color-lightness: 20%;
273
290
 
274
- :where(label, .label) .label-text [class*="icon"] {
291
+ :where(label, .label) .label-text > [class*="icon"] {
275
292
  background: var(--dark-gray);
276
293
  }
277
294
  }
@@ -8,7 +8,7 @@
8
8
  <dl>
9
9
  <template v-for="(entry, index) in accountData" :key="index">
10
10
  <dt>{{ entry.text }}</dt>
11
- <dd v-if="allowCopyByClick && entry.allowCopy" class="flex-container no-flex">
11
+ <dd v-if="allowCopyByClick && entry.allowCopy">
12
12
  <span>{{ entry.value }}</span>
13
13
  <a href="#" @click.prevent="copyToClipboard(entry.value)" :title="iconCopy.tooltip">
14
14
  <span :class="iconCopy.iconClass"></span>
@@ -92,7 +92,8 @@ export default {
92
92
  <style lang="scss">
93
93
  /* begin cmd-bank-account-data ---------------------------------------------------------------------------------------- */
94
94
  .cmd-bank-account-data {
95
- dd.flex-container {
95
+ dd {
96
+ display: flex;
96
97
  gap: calc(var(--default-gap) / 2);
97
98
 
98
99
  > span {
@@ -23,15 +23,11 @@
23
23
  <CmdTooltipForInputElements
24
24
  v-if="useCustomTooltip && (validationStatus === '' || validationStatus === 'error')"
25
25
  ref="tooltip"
26
- :showRequirements="showRequirements"
27
- :inputRequirements="inputRequirements"
28
26
  :validationStatus="validationStatus"
29
27
  :validationMessage="getValidationMessage"
30
28
  :validationTooltip="validationTooltip"
31
- :inputAttributes="$attrs"
32
- :inputModelValue="modelValue"
33
- :helplink="helplink"
34
29
  :relatedId="tooltipId"
30
+ :cmdListOfRequirements="listOfRequirements"
35
31
  />
36
32
  <!-- end CmdTooltipForInputElements -->
37
33
 
@@ -22,8 +22,13 @@
22
22
  <!-- begin label-text (+ required asterisk) -->
23
23
  <span v-if="(labelText || $slots.labeltext) && $attrs.type !== 'checkbox' && $attrs.type !== 'radio'"
24
24
  :class="['label-text', !showLabel ? 'hidden' : undefined]">
25
- <span v-if="labelText">{{ labelText }}<sup v-if="$attrs.required">*</sup></span>
26
- <slot name="labeltext" />
25
+ <span>
26
+ <template v-if="labelText">{{ labelText }}</template>
27
+ <!-- begin slot 'labeltext' -->
28
+ <slot v-else name="labeltext" />
29
+ <!-- end slot 'labeltext' -->
30
+ <sup v-if="$attrs.required">*</sup>
31
+ </span>
27
32
 
28
33
  <!-- begin CmdTooltipForInputElements -->
29
34
  <CmdTooltipForInputElements
@@ -108,7 +113,15 @@
108
113
  :disabled="$attrs.disabled"
109
114
  :aria-invalid="validationStatus === 'error'"
110
115
  />
111
- <span v-if="labelText" :class="['label-text', { hidden: !showLabel }]"><span>{{ labelText }}<sup v-if="$attrs.required">*</sup></span></span>
116
+ <span v-if="labelText || $slots.labeltext" :class="['label-text', { hidden: !showLabel }]">
117
+ <span>
118
+ <template v-if="labelText">{{ labelText }}</template>
119
+ <!-- begin slot 'labeltext' -->
120
+ <slot v-else name="labeltext" />
121
+ <!-- end slot 'labeltext' -->
122
+ <sup v-if="$attrs.required">*</sup>
123
+ </span>
124
+ </span>
112
125
  </template>
113
126
 
114
127
  <!-- begin labels for toggle-switch with switch-label -->
@@ -597,33 +610,9 @@ export default {
597
610
  iconClass: "icon-not-visible",
598
611
  }
599
612
  }
600
- },
601
- /**
602
- * properties for CmdListOfRequirements-component
603
- */
604
- cmdListOfRequirements: {
605
- type: Object,
606
- default() {
607
- return {}
608
- }
609
613
  }
610
614
  },
611
615
  computed: {
612
- listOfRequirements() {
613
- if (this.cmdListOfRequirements === undefined) {
614
- return {
615
- showRequirements: true,
616
- showHeadline: true,
617
- validationTooltip: this.validationTooltip,
618
- inputRequirements: [],
619
- inputAttributes: this.$attrs,
620
- inputModelValue: this.modelValue,
621
- helplink: {},
622
- labelText: this.labelText
623
- }
624
- }
625
- return this.cmdListOfRequirements
626
- },
627
616
  elementAttributes() {
628
617
  const commonAttributes = ["name", "required", "readonly", "disabled", "autofocus"]
629
618
  const attributes = {
@@ -807,7 +796,9 @@ export default {
807
796
  },
808
797
  closeTooltipOnBlur() {
809
798
  // close tooltip by calling function from CmdTooltipForInputElements using $refs
810
- this.$refs.tooltip.hideTooltip()
799
+ if(this.$refs.tooltip) {
800
+ this.$refs.tooltip.hideTooltip()
801
+ }
811
802
  }
812
803
  },
813
804
  watch: {
@@ -135,7 +135,7 @@ export default {
135
135
  type: Object,
136
136
  default() {
137
137
  return {
138
- headlineLevel: 4
138
+ headlineLevel: 6
139
139
  }
140
140
  }
141
141
  }
@@ -1,14 +1,14 @@
1
1
  <template>
2
2
  <div
3
3
  :class="[
4
- 'cmd-main-navigation main-navigation-wrapper',
4
+ 'cmd-main-navigation',
5
5
  {
6
6
  'hide-sub-navigation' : !showSubNavigations,
7
7
  'open-off-canvas': showOffcanvas,
8
8
  'persist-on-mobile': persistOnMobile,
9
9
  'show-content-overlay': showContentOverlay
10
10
  }
11
- ]">
11
+ ]" id="main-navigation-wrapper">
12
12
  <nav>
13
13
  <!-- begin main-level -->
14
14
  <ul :class="{'stretch-items' : stretchMainItems}">
@@ -19,7 +19,7 @@
19
19
  </a>
20
20
  </li>
21
21
  <li v-for="(navigationEntry, index) in navigationEntries" :key="index"
22
- :class="{'open' : navigationEntry.open, 'has-subentries': navigationEntry?.subentries?.length}">
22
+ :class="{'active' : navigationEntry.active, 'open' : navigationEntry.open, 'has-subentries': navigationEntry?.subentries?.length}">
23
23
  <!-- begin type === href -->
24
24
  <a
25
25
  v-if="navigationEntry.type === 'href'"
@@ -225,20 +225,27 @@ export default {
225
225
  },
226
226
  methods: {
227
227
  executeLink(event, navigationEntry) {
228
+ // execute default-link
228
229
  if (navigationEntry.target || (navigationEntry.path.length > 1)) {
230
+ this.showOffcanvas = false
229
231
  return true
230
232
  }
231
- if (navigationEntry.path === '#' || navigationEntry.path === '') {
232
- event.preventDefault()
233
- this.$emit('click', navigationEntry.path)
234
233
 
235
- }
236
- if (!(navigationEntry.subentries && navigationEntry.subentries.length > 0)) {
237
- this.showOffcanvas = false
238
- } else {
234
+ // toggle subentries (no link execution)
235
+ if(navigationEntry?.subentries?.length) {
236
+ event.preventDefault()
239
237
  // add entry "open" to navigationEntry-object (will be watched by vue3 automatically)
240
238
  navigationEntry.open = !navigationEntry.open
239
+ return
240
+ }
241
+
242
+ // emit event to handle navigation from outside
243
+ if (navigationEntry.path === '#' || navigationEntry.path === '') {
244
+ event.preventDefault()
245
+ this.$emit('click', navigationEntry.path)
241
246
  }
247
+
248
+ this.showOffcanvas = false
242
249
  },
243
250
  getRoute(navigationEntry) {
244
251
  return getRoute(navigationEntry)
@@ -295,12 +302,12 @@ export default {
295
302
 
296
303
 
297
304
  @media only screen and (max-width: $medium-max-width) {
298
- .cmd-main-navigation {
305
+ .cmd-main-navigation#main-navigation-wrapper {
299
306
  --nav-transition: all .5s linear;
300
307
  display: flex;
301
308
  background: none; /* overwrite framework-css */
302
309
  border: 0; /* overwrite framework-css */
303
- padding: 0 var(--default-padding);
310
+ padding: 0;
304
311
 
305
312
  /* begin offcanvas-navigation */
306
313
  &:not(.persist-on-mobile) {
@@ -386,14 +393,6 @@ export default {
386
393
  }
387
394
  }
388
395
 
389
- > a {
390
- span {
391
- & + span[class*="icon"]::before {
392
- display: inline-block;
393
- }
394
- }
395
- }
396
-
397
396
  /* sub-level 1 */
398
397
  ul {
399
398
  li {
@@ -404,9 +403,15 @@ export default {
404
403
  &:last-child {
405
404
  border-bottom: 0;
406
405
  }
407
-
408
- a {
406
+ > a {
409
407
  padding-left: calc(var(--default-margin) * 2);
408
+
409
+ span {
410
+ & + span[class*="icon"]::before {
411
+ display: inline-block;
412
+ transform: rotate(0);
413
+ }
414
+ }
410
415
  }
411
416
 
412
417
  /* sub-level 2 */
@@ -433,26 +438,6 @@ export default {
433
438
  display: block;
434
439
  opacity: 1;
435
440
  transition: var(--nav-transition);
436
-
437
- > li {
438
- > a {
439
- span {
440
- + span[class*="icon"]::before {
441
-
442
- }
443
- }
444
- }
445
-
446
- &.open {
447
- > a {
448
- span {
449
- + span[class*="icon"]::before {
450
-
451
- }
452
- }
453
- }
454
- }
455
- }
456
441
  }
457
442
  }
458
443
  }
@@ -6,21 +6,21 @@
6
6
 
7
7
  <!-- begin opening-status with link to detail-page -->
8
8
  <template v-if="link && link?.path && link?.show">
9
- <a v-if="link.type === 'href'" :href="link.path" :class="{closed: closed}">{{ textOpenClosed }}</a>
10
- <router-link v-if="link.type === 'router'" :to="link.path" :class="{closed: closed}">{{ textOpenClosed }}</router-link>
11
- <button v-if="link.type === 'button'" :class="['button', {closed: closed}]">{{ textOpenClosed }}</button>
9
+ <a v-if="link.type === 'href'" :href="link.path" :class="{closed: isClosed}">{{ textOpenClosed }}</a>
10
+ <router-link v-if="link.type === 'router'" :to="link.path" :class="{closed: isClosed}">{{ textOpenClosed }}</router-link>
11
+ <button v-if="link.type === 'button'" :class="['button', {closed: isClosed}]">{{ textOpenClosed }}</button>
12
12
  </template>
13
13
  <!-- end opening-status with link to detail-page -->
14
14
 
15
15
  <!-- begin opening-status (without link) -->
16
- <span v-else :class="{'closed': closed}">{{ textOpenClosed }}</span>
16
+ <span v-else :class="{'closed': isClosed}">{{ textOpenClosed }}</span>
17
17
  <!-- end opening-status (without link) -->
18
18
 
19
19
  <!-- begin opening-days and -hours -->
20
20
  <dl>
21
- <template v-for="day in openingHours" :key="day.day">
21
+ <template v-for="day in openingHoursFormatted" :key="day.day">
22
22
  <dt>{{ day.day }}:</dt>
23
- <dd>{{ day.fromTime }}&ndash;{{ day.tillTime }}</dd>
23
+ <dd>{{ getTime(day.fromTime)}}&ndash;{{ getTime(day.tillTime)}}</dd>
24
24
  </template>
25
25
  </dl>
26
26
  <!-- end opening-days and -hours -->
@@ -40,6 +40,36 @@
40
40
  // import components
41
41
  import CmdHeadline from "./CmdHeadline"
42
42
 
43
+ export function localizedTime(language) {
44
+ return (hour, minute) => {
45
+ const now = new Date()
46
+ now.setHours(hour, minute, 0, 0)
47
+ return new Intl.DateTimeFormat(language, {timeStyle: "short"}).format(now)
48
+ }
49
+ }
50
+
51
+ export function timeFormatting(separator, suffix1, suffix2, hoursLeadingZero = true) {
52
+ function addLeadingZero(time, addLeadingZero) {
53
+ if(addLeadingZero && time < 10) {
54
+ return "0" + time
55
+ }
56
+ return time
57
+ }
58
+
59
+ return (hour, minute) => {
60
+ if(suffix2) {
61
+ let hour12 = hour
62
+ let currentSuffix = suffix1
63
+ if(hour12 > 12) {
64
+ hour12 -= 12
65
+ currentSuffix = suffix2
66
+ }
67
+ return addLeadingZero(hour12, hoursLeadingZero) + separator + addLeadingZero(minute, true) + currentSuffix
68
+ }
69
+ return addLeadingZero(hour, hoursLeadingZero) + separator + addLeadingZero(minute, true) + suffix1
70
+ }
71
+ }
72
+
43
73
  export default {
44
74
  name: "CmdOpeningHours",
45
75
  components: {
@@ -63,11 +93,18 @@ export default {
63
93
  default: false
64
94
  },
65
95
  /**
66
- * text for open/closed-information
96
+ * text for 'open'-information
67
97
  */
68
- textOpenClosed: {
98
+ textOpen: {
69
99
  type: String,
70
- required: true
100
+ default: "Open right now!"
101
+ },
102
+ /**
103
+ * text for 'closed'-information
104
+ */
105
+ textClosed: {
106
+ type: String,
107
+ default: "Closed right now!"
71
108
  },
72
109
  /**
73
110
  * list of opening-hours
@@ -96,6 +133,112 @@ export default {
96
133
  cmdHeadline: {
97
134
  type: Object,
98
135
  required: false
136
+ },
137
+ /**
138
+ * option to set custom time format by function
139
+ */
140
+ timeFormatter: {
141
+ type: Function,
142
+ required: false
143
+ },
144
+ /**
145
+ * activate if component should update open-/closed-status on its own
146
+ */
147
+ componentHandlesClosedStatus: {
148
+ type: Boolean,
149
+ default: true
150
+ },
151
+ /**
152
+ * set the interval (in milliseconds) when the open-/closed-status should be checked (and updated)
153
+ */
154
+ checkInterval: {
155
+ type: Number,
156
+ default: 5000
157
+ }
158
+ },
159
+ mounted() {
160
+ if(this.componentHandlesClosedStatus && this.checkInterval > 0) {
161
+ // create new property on component by 'this.property-name' and assign value (id) from setInterval (so it can be cleared in unmount)
162
+ this.$_CmdOpeningHours_intervalId = setInterval(() => {
163
+ // use arrow-function to assure that 'this' is the component
164
+ this.currentTime = new Date()
165
+ }, this.checkInterval)
166
+ }
167
+ },
168
+ data() {
169
+ return {
170
+ currentTime: new Date()
171
+ }
172
+ },
173
+ computed: {
174
+ textOpenClosed() {
175
+ return this.isClosed ? this.textClosed : this.textOpen
176
+ },
177
+ openingHoursFormatted() {
178
+ const weekdays = []
179
+ for(let i = 0; i < this.openingHours.length; i++) {
180
+ const openingHours = {}
181
+ const splitFromTime = this.openingHours[i].fromTime.split(/[:.]/)
182
+ const splitTillTime = this.openingHours[i].tillTime.split(/[:.]/)
183
+
184
+ openingHours.day = this.openingHours[i].day
185
+ openingHours.fromTime = {
186
+ hours: parseInt(splitFromTime[0]),
187
+ mins: parseInt(splitFromTime[1])
188
+ }
189
+ openingHours.tillTime = {
190
+ hours: parseInt(splitTillTime[0]),
191
+ mins: parseInt(splitTillTime[1])
192
+ }
193
+ weekdays.push(openingHours)
194
+ }
195
+ return weekdays
196
+ },
197
+ isClosed() {
198
+ if(!this.componentHandlesClosedStatus) {
199
+ return this.closed
200
+ }
201
+
202
+ let currentDay = this.currentTime.getDay()
203
+
204
+ // fix order and check if currentDay equals 0 === sunday. Data are expected to start with monday
205
+ if (currentDay === 0){
206
+ currentDay = 6
207
+ } else {
208
+ currentDay -= 1
209
+ }
210
+
211
+ const openingHours = this.openingHoursFormatted[currentDay]
212
+
213
+ if(this.openingHoursFormatted[currentDay]) {
214
+ const openingHoursFrom = new Date()
215
+ openingHoursFrom.setHours(openingHours.fromTime.hours, openingHours.fromTime.mins)
216
+
217
+ const openingHoursTill = new Date()
218
+ openingHoursTill.setHours(openingHours.tillTime.hours, openingHours.tillTime.mins)
219
+
220
+ if (openingHoursFrom <= this.currentTime && this.currentTime <= openingHoursTill) {
221
+ return false
222
+ }
223
+ }
224
+ return true
225
+ }
226
+ },
227
+ methods: {
228
+ getTime(time) {
229
+ if(this.timeFormatter) {
230
+ return this.timeFormatter(time.hours, time.mins)
231
+ }
232
+ return timeFormatting(":", " hrs", "", false)(time.hours, time.mins)
233
+ }
234
+ },
235
+ beforeUnmount() {
236
+ if(this.$_CmdOpeningHours_intervalId) {
237
+ // remove interval
238
+ clearInterval(this.$_CmdOpeningHours_intervalId)
239
+
240
+ // clear interval-id
241
+ this.$_CmdOpeningHours_intervalId = null
99
242
  }
100
243
  }
101
244
  }
@@ -89,6 +89,10 @@ export default {
89
89
  padding: 0 var(--default-padding);
90
90
  }
91
91
 
92
+ .cmd-main-navigation nav {
93
+ width: auto;
94
+ }
95
+
92
96
  .top-header {
93
97
  .cmd-list-of-links {
94
98
  padding-top: calc(var(--default-padding) / 2);
@@ -47,9 +47,7 @@ export default {
47
47
  return require("../assets/images/flags/flag-" + isoCode + ".svg")
48
48
  },
49
49
  activeLanguage(language) {
50
- if(language.active || language.iso2 === navigator.language) {
51
- return true
52
- }
50
+ return language.active
53
51
  }
54
52
  }
55
53
  }
@@ -67,7 +65,7 @@ export default {
67
65
  list-style-type: none;
68
66
  margin: 0;
69
67
 
70
- a:not(.active) {
68
+ a:not([class*="active"]) {
71
69
  filter: contrast(.5);
72
70
 
73
71
  &:hover, &:focus, &:active {
@@ -23,8 +23,7 @@ export default {
23
23
  },
24
24
  data() {
25
25
  return {
26
- darkMode: false,
27
- labelText: ""
26
+ darkMode: false
28
27
  }
29
28
  },
30
29
  props: {
@@ -99,6 +98,11 @@ export default {
99
98
  this.darkMode = event.detail === "dark-mode"
100
99
  }
101
100
  },
101
+ computed: {
102
+ labelText() {
103
+ return this.darkMode ? this.labelTextDarkMode : this.labelTextLightMode
104
+ }
105
+ },
102
106
  watch: {
103
107
  darkMode: {
104
108
  handler() {
@@ -106,10 +110,8 @@ export default {
106
110
  const htmlTag = document.documentElement
107
111
  if (this.darkMode) {
108
112
  htmlTag.classList.replace("light-mode", "dark-mode")
109
- this.labelText = this.labelTextDarkMode
110
113
  } else {
111
114
  htmlTag.classList.replace("dark-mode", "light-mode")
112
- this.labelText = this.labelTextLightMode
113
115
  }
114
116
 
115
117
  // emits custom events from html-tag
@@ -9,7 +9,7 @@
9
9
 
10
10
  <!-- begin CmdSystemMessage -->
11
11
  <CmdSystemMessage
12
- v-if="inputAttributes.required && validationMessage"
12
+ v-if="cmdListOfRequirements?.inputAttributes?.required && validationMessage"
13
13
  :systemMessage="validationMessage"
14
14
  :validation-status="validationStatus"
15
15
  :iconClose="{show: false}"
@@ -262,10 +262,5 @@
262
262
  "type-property must be set to 'password'",
263
263
  ""
264
264
  ]
265
- },
266
- "cmdListOfRequirements": {
267
- "comments": [
268
- "properties for CmdListOfRequirements-component"
269
- ]
270
265
  }
271
266
  }