comand-component-library 3.1.86 → 3.1.87
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.css +1 -1
- package/dist/comand-component-library.umd.min.js +1 -1
- package/package.json +1 -1
- package/src/App.vue +16 -2
- package/src/assets/data/opening-hours.json +10 -10
- package/src/assets/styles/global-styles.scss +1 -1
- package/src/components/CmdFakeSelect.vue +1 -5
- package/src/components/CmdFormElement.vue +19 -28
- package/src/components/CmdListOfRequirements.vue +1 -1
- package/src/components/CmdMainNavigation.vue +4 -2
- package/src/components/CmdOpeningHours.vue +117 -9
- package/src/components/CmdSwitchLanguage.vue +2 -4
- package/src/components/CmdToggleDarkMode.vue +6 -4
- package/src/components/CmdTooltipForInputElements.vue +1 -1
- package/src/documentation/generated/CmdFormElementPropertyDescriptions.json +0 -5
- package/src/documentation/generated/CmdOpeningHoursPropertyDescriptions.json +17 -2
- package/src/mixins/FieldValidation.js +22 -0
package/package.json
CHANGED
package/src/App.vue
CHANGED
@@ -499,6 +499,17 @@
|
|
499
499
|
:status="validationStatus"
|
500
500
|
:disabled="disabledStatus"
|
501
501
|
/>
|
502
|
+
<CmdFormElement element="input"
|
503
|
+
v-model="checkboxValues"
|
504
|
+
inputValue="checkboxValue3"
|
505
|
+
type="checkbox"
|
506
|
+
id="checkbox-with-value-3"
|
507
|
+
:status="validationStatus"
|
508
|
+
:disabled="disabledStatus">
|
509
|
+
<template v-slot:labeltext>
|
510
|
+
Labeltext with <a href="#">link</a> given by slot
|
511
|
+
</template>
|
512
|
+
</CmdFormElement>
|
502
513
|
</div>
|
503
514
|
</div>
|
504
515
|
<h3>Checkboxes (replaced)</h3>
|
@@ -1137,9 +1148,7 @@
|
|
1137
1148
|
:cmdHeadline="{headlineText: 'List of links', headlineLevel: 6}"
|
1138
1149
|
/>
|
1139
1150
|
<CmdOpeningHours :openingHours="openingHoursData"
|
1140
|
-
:closed="true"
|
1141
1151
|
:cmdHeadline="{headlineText: 'Opening hours', headlineLevel: 6}"
|
1142
|
-
textOpenClosed="Closed right now!"
|
1143
1152
|
textHolidaysClosed="Closed on holidays"
|
1144
1153
|
textMiscInfo="Miscellaneous information"
|
1145
1154
|
/>
|
@@ -1248,6 +1257,8 @@ import {openFancyBox} from "@/components/CmdFancyBox"
|
|
1248
1257
|
// import external functions
|
1249
1258
|
import * as functions from "@/mixins/FieldValidation.js"
|
1250
1259
|
|
1260
|
+
import {localizedTime} from "./components/CmdOpeningHours"
|
1261
|
+
|
1251
1262
|
export default {
|
1252
1263
|
name: "App",
|
1253
1264
|
components: {
|
@@ -1422,6 +1433,9 @@ export default {
|
|
1422
1433
|
}
|
1423
1434
|
},
|
1424
1435
|
methods: {
|
1436
|
+
localizedTime(language) {
|
1437
|
+
return (h, m) => (localizedTime(language))(h, m).toLowerCase()
|
1438
|
+
},
|
1425
1439
|
closeCookieDisclaimer(event) {
|
1426
1440
|
this.fancyBoxCookieDisclaimer = false
|
1427
1441
|
alert(event.join(", "))
|
@@ -1,29 +1,29 @@
|
|
1
1
|
[
|
2
2
|
{
|
3
3
|
"day": "Mo",
|
4
|
-
"fromTime": "08:
|
5
|
-
"tillTime": "17:
|
4
|
+
"fromTime": "08:00",
|
5
|
+
"tillTime": "17:00"
|
6
6
|
},
|
7
7
|
{
|
8
8
|
"day": "Tu",
|
9
|
-
"fromTime": "08:
|
10
|
-
"tillTime": "17:
|
9
|
+
"fromTime": "08:00",
|
10
|
+
"tillTime": "17:00"
|
11
11
|
},
|
12
12
|
{
|
13
13
|
"day": "We",
|
14
|
-
"fromTime": "08:
|
15
|
-
"tillTime": "17:
|
14
|
+
"fromTime": "08:00",
|
15
|
+
"tillTime": "17:30"
|
16
16
|
},
|
17
17
|
|
18
18
|
{
|
19
19
|
"day": "Th",
|
20
|
-
"fromTime": "08:
|
21
|
-
"tillTime": "17:
|
20
|
+
"fromTime": "08:00",
|
21
|
+
"tillTime": "17:00"
|
22
22
|
},
|
23
23
|
{
|
24
24
|
"day": "Fr",
|
25
|
-
"fromTime": "08:
|
26
|
-
"tillTime": "15:
|
25
|
+
"fromTime": "08:00",
|
26
|
+
"tillTime": "15:00"
|
27
27
|
}
|
28
28
|
]
|
29
29
|
|
@@ -271,7 +271,7 @@ html {
|
|
271
271
|
--color-scheme-background-inverted: var(--light-mode-background-color);
|
272
272
|
--default-background-color-lightness: 20%;
|
273
273
|
|
274
|
-
:where(label, .label) .label-text [class*="icon"] {
|
274
|
+
:where(label, .label) .label-text > [class*="icon"] {
|
275
275
|
background: var(--dark-gray);
|
276
276
|
}
|
277
277
|
}
|
@@ -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
|
26
|
-
|
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 }]"
|
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
|
799
|
+
if(this.$refs.tooltip) {
|
800
|
+
this.$refs.tooltip.hideTooltip()
|
801
|
+
}
|
811
802
|
}
|
812
803
|
},
|
813
804
|
watch: {
|
@@ -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'"
|
@@ -226,14 +226,16 @@ export default {
|
|
226
226
|
methods: {
|
227
227
|
executeLink(event, navigationEntry) {
|
228
228
|
if (navigationEntry.target || (navigationEntry.path.length > 1)) {
|
229
|
+
this.showOffcanvas = false
|
229
230
|
return true
|
230
231
|
}
|
231
232
|
if (navigationEntry.path === '#' || navigationEntry.path === '') {
|
232
233
|
event.preventDefault()
|
234
|
+
this.showOffcanvas = false
|
233
235
|
this.$emit('click', navigationEntry.path)
|
234
236
|
|
235
237
|
}
|
236
|
-
if (!(navigationEntry
|
238
|
+
if (!(navigationEntry?.subentries?.length)) {
|
237
239
|
this.showOffcanvas = false
|
238
240
|
} else {
|
239
241
|
// add entry "open" to navigationEntry-object (will be watched by vue3 automatically)
|
@@ -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:
|
10
|
-
<router-link v-if="link.type === 'router'" :to="link.path" :class="{closed:
|
11
|
-
<button v-if="link.type === 'button'" :class="['button', {closed:
|
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':
|
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
|
21
|
+
<template v-for="day in openingHoursFormatted" :key="day.day">
|
22
22
|
<dt>{{ day.day }}:</dt>
|
23
|
-
<dd>{{ day.fromTime
|
23
|
+
<dd>{{ getTime(day.fromTime)}}–{{ 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
|
96
|
+
* text for 'open'-information
|
67
97
|
*/
|
68
|
-
|
98
|
+
textOpen: {
|
69
99
|
type: String,
|
70
|
-
|
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,77 @@ export default {
|
|
96
133
|
cmdHeadline: {
|
97
134
|
type: Object,
|
98
135
|
required: false
|
136
|
+
},
|
137
|
+
timeFormatter: {
|
138
|
+
type: Function,
|
139
|
+
required: false
|
140
|
+
},
|
141
|
+
componentHandlesClosedStatus: {
|
142
|
+
type: Boolean,
|
143
|
+
default: true
|
144
|
+
}
|
145
|
+
},
|
146
|
+
computed: {
|
147
|
+
textOpenClosed() {
|
148
|
+
return this.isClosed ? this.textClosed : this.textOpen
|
149
|
+
},
|
150
|
+
openingHoursFormatted() {
|
151
|
+
const weekdays = []
|
152
|
+
for(let i = 0; i < this.openingHours.length; i++) {
|
153
|
+
const openingHours = {}
|
154
|
+
const splitFromTime = this.openingHours[i].fromTime.split(/[:.]/)
|
155
|
+
const splitTillTime = this.openingHours[i].tillTime.split(/[:.]/)
|
156
|
+
|
157
|
+
openingHours.day = this.openingHours[i].day
|
158
|
+
openingHours.fromTime = {
|
159
|
+
hours: parseInt(splitFromTime[0]),
|
160
|
+
mins: parseInt(splitFromTime[1])
|
161
|
+
}
|
162
|
+
openingHours.tillTime = {
|
163
|
+
hours: parseInt(splitTillTime[0]),
|
164
|
+
mins: parseInt(splitTillTime[1])
|
165
|
+
}
|
166
|
+
weekdays.push(openingHours)
|
167
|
+
}
|
168
|
+
return weekdays
|
169
|
+
},
|
170
|
+
isClosed() {
|
171
|
+
if(!this.componentHandlesClosedStatus) {
|
172
|
+
return this.closed
|
173
|
+
}
|
174
|
+
|
175
|
+
const currentDate = new Date()
|
176
|
+
let currentDay = currentDate.getDay()
|
177
|
+
|
178
|
+
// fix order and check if currentDay equals 0 === sunday. Data are expected to start with monday
|
179
|
+
if (currentDay === 0){
|
180
|
+
currentDay = 6
|
181
|
+
} else {
|
182
|
+
currentDay -= 1
|
183
|
+
}
|
184
|
+
|
185
|
+
const openingHours = this.openingHoursFormatted[currentDay]
|
186
|
+
|
187
|
+
if(this.openingHoursFormatted[currentDay]) {
|
188
|
+
const openingHoursFrom = new Date()
|
189
|
+
openingHoursFrom.setHours(openingHours.fromTime.hours, openingHours.fromTime.mins)
|
190
|
+
|
191
|
+
const openingHoursTill = new Date()
|
192
|
+
openingHoursTill.setHours(openingHours.tillTime.hours, openingHours.tillTime.mins)
|
193
|
+
|
194
|
+
if (openingHoursFrom <= currentDate && currentDate <= openingHoursTill) {
|
195
|
+
return false
|
196
|
+
}
|
197
|
+
}
|
198
|
+
return true
|
199
|
+
}
|
200
|
+
},
|
201
|
+
methods: {
|
202
|
+
getTime(time) {
|
203
|
+
if(this.timeFormatter) {
|
204
|
+
return this.timeFormatter(time.hours, time.mins)
|
205
|
+
}
|
206
|
+
return timeFormatting(":", " hrs", "", false)(time.hours, time.mins)
|
99
207
|
}
|
100
208
|
}
|
101
209
|
}
|
@@ -47,9 +47,7 @@ export default {
|
|
47
47
|
return require("../assets/images/flags/flag-" + isoCode + ".svg")
|
48
48
|
},
|
49
49
|
activeLanguage(language) {
|
50
|
-
|
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(
|
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
|
12
|
+
v-if="cmdListOfRequirements?.inputAttributes?.required && validationMessage"
|
13
13
|
:systemMessage="validationMessage"
|
14
14
|
:validation-status="validationStatus"
|
15
15
|
:iconClose="{show: false}"
|
@@ -14,9 +14,14 @@
|
|
14
14
|
]
|
15
15
|
}
|
16
16
|
},
|
17
|
-
"
|
17
|
+
"textOpen": {
|
18
18
|
"comments": [
|
19
|
-
"text for open
|
19
|
+
"text for 'open'-information"
|
20
|
+
]
|
21
|
+
},
|
22
|
+
"textClosed": {
|
23
|
+
"comments": [
|
24
|
+
"text for 'closed'-information"
|
20
25
|
]
|
21
26
|
},
|
22
27
|
"openingHours": {
|
@@ -38,5 +43,15 @@
|
|
38
43
|
"comments": [
|
39
44
|
"properties for CmdHeadline-component"
|
40
45
|
]
|
46
|
+
},
|
47
|
+
"timeFormatter": {
|
48
|
+
"comments": [
|
49
|
+
"properties for CmdHeadline-component"
|
50
|
+
]
|
51
|
+
},
|
52
|
+
"componentHandlesClosedStatus": {
|
53
|
+
"comments": [
|
54
|
+
"properties for CmdHeadline-component"
|
55
|
+
]
|
41
56
|
}
|
42
57
|
}
|
@@ -142,9 +142,31 @@ export default {
|
|
142
142
|
iconClass: "icon-not-visible"
|
143
143
|
}
|
144
144
|
}
|
145
|
+
},
|
146
|
+
/**
|
147
|
+
* properties for CmdListOfRequirements-component
|
148
|
+
*/
|
149
|
+
cmdListOfRequirements: {
|
150
|
+
type: Object,
|
151
|
+
required: false
|
145
152
|
}
|
146
153
|
},
|
147
154
|
computed: {
|
155
|
+
listOfRequirements() {
|
156
|
+
if (this.cmdListOfRequirements == null) {
|
157
|
+
return {
|
158
|
+
showRequirements: true,
|
159
|
+
showHeadline: true,
|
160
|
+
validationTooltip: this.validationTooltip,
|
161
|
+
inputRequirements: this.inputRequirements,
|
162
|
+
inputAttributes: this.$attrs,
|
163
|
+
inputModelValue: this.modelValue,
|
164
|
+
helplink: {},
|
165
|
+
labelText: this.labelText
|
166
|
+
}
|
167
|
+
}
|
168
|
+
return this.cmdListOfRequirements
|
169
|
+
},
|
148
170
|
getValidationMessage() {
|
149
171
|
// check if all requirements are valid
|
150
172
|
// const allRequirementsValid = !this.inputRequirements.some((item) => {
|