comand-component-library 3.1.86 → 3.1.89

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.
@@ -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
  }