comand-component-library 3.1.57 → 3.1.60

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comand-component-library",
3
- "version": "3.1.57",
3
+ "version": "3.1.60",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -18,7 +18,7 @@
18
18
  ],
19
19
  "dependencies": {
20
20
  "clickout-event": "^1.1.2",
21
- "comand-frontend-framework": "^3.2.44",
21
+ "comand-frontend-framework": "^3.2.46",
22
22
  "core-js": "^3.20.1",
23
23
  "prismjs": "^1.27.0",
24
24
  "vue": "^3.2.31",
package/src/App.vue CHANGED
@@ -414,6 +414,15 @@
414
414
  id="inputfield-date"
415
415
  v-model="inputDate"
416
416
  :status="formElementStatus"/>
417
+ <CmdFormElement element="input"
418
+ labelText="Label (inline) for inputfield (search) without search-button:"
419
+ :displayLabelInline="true"
420
+ type="search"
421
+ id="inputfield-search"
422
+ placeholder="Keyword(s)"
423
+ v-model="inputSearch"
424
+ :showSearchButton="false"
425
+ :status="formElementStatus"/>
417
426
  <CmdFormElement element="input"
418
427
  labelText="Label (inline) for inputfield (search):"
419
428
  :displayLabelInline="true"
@@ -835,8 +844,10 @@
835
844
  <a id="section-tables"></a>
836
845
  <CmdWidthLimitationWrapper>
837
846
  <h2 class="headline-demopage">Tables</h2>
838
- <h3>Table as wide as its content</h3>
839
- <CmdTable :collapsible="true" :fullWidthOnDefault="false" :userCanToggleWidth="true" :table-data="tableDataSmall"/>
847
+ <h3>Table as wide as its content (with caption)</h3>
848
+ <CmdTable :collapsible="true" :fullWidthOnDefault="false" :userCanToggleWidth="true" :table-data="tableDataSmall"/>
849
+ <h3>Table as wide as its content (without caption)</h3>
850
+ <CmdTable :collapsible="true" :fullWidthOnDefault="false" :userCanToggleWidth="true" :caption="{ text: 'Hidden caption', show: false}" :table-data="tableDataSmall"/>
840
851
  <h3>Table as wide as possible</h3>
841
852
  <CmdTable :collapsible="true" :fullWidthOnDefault="false" :userCanToggleWidth="true" :table-data="tableDataLarge"/>
842
853
  </CmdWidthLimitationWrapper>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "caption": {
3
- "show": false,
3
+ "show": true,
4
4
  "text": "This is a caption for a small table"
5
5
  },
6
6
  "thead": [
@@ -107,7 +107,7 @@
107
107
  <CmdSystemMessage
108
108
  v-if="getValidationMessage"
109
109
  :message="getValidationMessage"
110
- :validatioStatus="validationStatus"
110
+ :validationStatus="validationStatus"
111
111
  :iconClose="{show: false}"
112
112
  />
113
113
  <!-- end CmdSystemMessage -->
@@ -275,7 +275,7 @@ export default {
275
275
  computed: {
276
276
  // get the displayed option name
277
277
  optionName() {
278
- // fake a normal checkbox
278
+ // fake a native selectbox
279
279
  if (this.type !== "checkboxOptions" && this.type !== "content" && this.modelValue) {
280
280
  const result = this.selectData.find(option => option.value === this.modelValue)?.text
281
281
 
@@ -288,7 +288,7 @@ export default {
288
288
  // selectbox with checkbox-options
289
289
  else if (this.type === "checkboxOptions") {
290
290
  if (this.modelValue.length === 1) {
291
- return this.selectData.find(option => option.value === this.modelValue[0])?.text
291
+ return this.selectData.find(option => String(option.value) === String(this.modelValue[0]))?.text
292
292
  } else if (this.modelValue.length > 1) {
293
293
  return this.modelValue.length + " options selected"
294
294
  }
@@ -382,7 +382,7 @@ export default {
382
382
  }
383
383
 
384
384
  this.showOptions = false
385
- this.$emit('update:modelValue', optionValue);
385
+ this.$emit('update:modelValue', optionValue)
386
386
  },
387
387
  // check if a checkbox is changed for selectbox with checkboxes
388
388
  optionSelect(event) {
@@ -390,15 +390,15 @@ export default {
390
390
 
391
391
  let value = [...this.modelValue] // copy array from props
392
392
  if (event.target.checked) {
393
- value.push(event.target.value); // attention: value will be transformed into string!
393
+ value.push(event.target.value) // attention: value will be transformed into string!
394
394
  } else {
395
- value = value.filter(v => v !== event.target.value);
395
+ value = value.filter(item => item !== event.target.value && String(item) !== event.target.value)
396
396
  }
397
397
  if (this.$attrs.required !== undefined && !value.length) {
398
398
  this.validationStatus = "error"
399
399
  }
400
400
 
401
- this.$emit('update:modelValue', value);
401
+ this.$emit('update:modelValue', value)
402
402
  },
403
403
  closeOptions() {
404
404
  this.showOptions = false
@@ -69,12 +69,12 @@
69
69
  <!-- begin show-password-icon -->
70
70
  <a v-if="$attrs.type === 'password'"
71
71
  href="#"
72
- class="place-inside icon-visible"
72
+ :class="['place-inside', iconPasswordVisible.iconClass]"
73
73
  @mousedown.prevent="showPassword"
74
74
  @mouseup.prevent="hidePassword"
75
75
  @mouseleave.prevent="hidePassword"
76
76
  @click.prevent
77
- title="Toggle password visibility">
77
+ :title="iconPasswordVisible.tooltip">
78
78
  </a>
79
79
  <!-- end show-password-icon -->
80
80
 
@@ -145,21 +145,23 @@
145
145
  <!-- end textarea -->
146
146
 
147
147
  <!-- begin searchfield -->
148
- <span v-else-if="element === 'input' && $attrs.type === 'search'" class="search-field-wrapper flex-container no-gap">
149
- <a v-if="iconDelete.show" href="#" @click.prevent="$emit('update:modelValue', '')" :class="iconDelete.iconClass" :title="iconDelete.tooltip"/>
150
- <input
151
- v-bind="$attrs"
152
- :id="id"
153
- @input="onInput"
154
- :maxlength="$attrs.maxlength > 0 ? $attrs.maxlength : 255"
155
- :value="modelValue"
156
- />
148
+ <template v-else-if="element === 'input' && $attrs.type === 'search'">
149
+ <div class="search-field-wrapper flex-container no-gap">
150
+ <a v-if="iconDelete.show" href="#" @click.prevent="$emit('update:modelValue', '')" :class="iconDelete.iconClass" :title="iconDelete.tooltip"/>
151
+ <input
152
+ v-bind="$attrs"
153
+ :id="id"
154
+ @input="onInput"
155
+ :maxlength="$attrs.maxlength > 0 ? $attrs.maxlength : 255"
156
+ :value="modelValue"
157
+ />
158
+ </div>
157
159
  <button v-if="showSearchButton" class="no-flex" type="button" :title="iconSearch.tooltip">
158
160
  <span :class="iconSearch.iconClass"></span>
159
161
  </button>
160
- </span>
161
- <!-- end searchfield -->
162
+ </template>
162
163
  </label>
164
+ <!-- end searchfield -->
163
165
 
164
166
  <!-- begin button -->
165
167
  <button v-else class="button" v-bind="buttonAttrs">
@@ -193,8 +195,8 @@
193
195
  <template v-for="(requirement, index) in inputRequirements" :key="index">
194
196
  <dt aria-live="assertive" :class="requirement.valid(modelValue, $attrs) ? 'success' : 'error'">{{ requirement.message }}:</dt>
195
197
  <dd :class="requirement.valid(modelValue, $attrs) ? 'success' : 'error'">
196
- <span aria-live="assertive" :class="requirement.valid(modelValue, $attrs) ? 'icon-check-circle' : 'icon-error-circle'"
197
- :title="requirement.valid(modelValue, $attrs) ? 'success' : 'error'"></span>
198
+ <span aria-live="assertive" :class="requirement.valid(modelValue, $attrs) ? iconHasStateSuccess.iconClass : iconHasStateError.iconClass"
199
+ :title="requirement.valid(modelValue, $attrs) ? iconHasStateSuccess.tooltip : iconHasStateError.tooltip"></span>
198
200
  </dd>
199
201
  </template>
200
202
  </dl>
@@ -243,7 +245,7 @@ export default {
243
245
  },
244
246
  props: {
245
247
  /**
246
- * set value for v-model (must be names modelValue in vue3)
248
+ * set value for v-model (must be named modelValue in vue3 if default v-model should be used)
247
249
  */
248
250
  modelValue: {
249
251
  type: [String, Boolean, Array, Number],
@@ -521,13 +523,13 @@ export default {
521
523
 
522
524
  // set default-tooltip if customTooltip is not set
523
525
  if (this.validationStatus === 'error') {
524
- return "An error occurred!"
526
+ return this.getMessage("cmdformelement.validationTooltip.an_error_occurred")
525
527
  } else if (this.validationStatus === 'success') {
526
- return "This information is filled correctly!"
528
+ return this.getMessage("cmdformelement.validationTooltip.information_is_filled_correctly")
527
529
  } else if (this.capsLockActivated) {
528
- return "Attention: Caps lock is activated!"
530
+ return this.getMessage("cmdformelement.validationTooltip.caps_lock_is_activated")
529
531
  }
530
- return "Open field requirements!"
532
+ return this.getMessage("cmdformelement.validationTooltip.open_field_requirements")
531
533
  }
532
534
  },
533
535
  methods: {
@@ -599,14 +601,14 @@ export default {
599
601
  const password = passwordField.value
600
602
 
601
603
  // toggle input-type to make password visible
602
- passwordField.nextElementSibling.classList.replace("icon-visible", "icon-not-visible")
604
+ passwordField.nextElementSibling.classList.replace(this.iconPasswordVisible.iconClass, this.iconPasswordInvisible.iconClass)
603
605
  passwordField.setAttribute("type", "text")
604
606
 
605
607
  // assign saved password back to field
606
608
  passwordField.setAttribute("value", password)
607
609
  },
608
610
  hidePassword() {
609
- this.$refs.input.nextElementSibling.classList.replace("icon-not-visible", "icon-visible")
611
+ this.$refs.input.nextElementSibling.classList.replace(this.iconPasswordInvisible.iconClass, this.iconPasswordVisible.iconClass)
610
612
  this.$refs.input.setAttribute("type", "password")
611
613
  }
612
614
  },
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="cmd-google-maps responsive-wrapper">
2
+ <div class="cmd-google-maps">
3
3
  <iframe :src="locateAddress"></iframe>
4
4
  </div>
5
5
  </template>
@@ -21,7 +21,7 @@ export default {
21
21
  if(this.address) {
22
22
  const url = new URL("https://maps.google.de/maps?ie=UTF8&t=&z=17&iwloc=B&output=embed")
23
23
  url.searchParams.set("hl", "de")
24
- url.searchParams.set("q", [this.address.streetNo, this.address.zip, this.address.city, this.address.latitude, this.address.longitude, this.location].join(" ").trim())
24
+ url.searchParams.set("q", [this.address.streetNo, this.address.zip, this.address.city, this.address.latitude, this.address.longitude, this.address.location].join(" ").trim())
25
25
  return url.href
26
26
  }
27
27
  return "https://maps.google.de/maps?ie=UTF8&t=&z=17&iwloc=B&output=embed"
@@ -34,6 +34,14 @@ export default {
34
34
  /* begin cmd-google-maps ---------------------------------------------------------------------------------------- */
35
35
  .cmd-google-maps {
36
36
  border: var(--default-border);
37
+
38
+ aspect-ratio: 16/9;
39
+
40
+ iframe {
41
+ display: block;
42
+ width: 100%;
43
+ height: 100%;
44
+ }
37
45
  }
38
46
 
39
47
  /* end cmd-google-maps ------------------------------------------------------------------------------------------ */
@@ -15,7 +15,7 @@
15
15
  type="text"
16
16
  :name="cmdFormElementUsername.name"
17
17
  :id="cmdFormElementUsername.id"
18
- v-model:value="username"
18
+ v-model="username"
19
19
  :inner-icon-class="cmdFormElementUsername.innerIconClass"
20
20
  :labelText="cmdFormElementUsername.labelText"
21
21
  :placeholder="cmdFormElementUsername.placeholder"
@@ -29,7 +29,7 @@
29
29
  :name="cmdFormElementPassword.name"
30
30
  :id="cmdFormElementPassword.id"
31
31
  :inner-icon-class="cmdFormElementPassword.innerIconClass"
32
- v-model:value="password"
32
+ v-model="password"
33
33
  :labelText="cmdFormElementPassword.labelText"
34
34
  :placeholder="cmdFormElementPassword.placeholder"
35
35
  />
@@ -274,13 +274,7 @@ export default {
274
274
  */
275
275
  cmdCustomHeadlineLoginForm: {
276
276
  type: Object,
277
- default() {
278
- return {
279
- show: true,
280
- text: "Login",
281
- level: 2
282
- }
283
- }
277
+ required: false
284
278
  },
285
279
  /**
286
280
  * properties for CmdCustomHeadline-component for send-login-form
@@ -290,8 +284,8 @@ export default {
290
284
  default() {
291
285
  return {
292
286
  show: true,
293
- text: "Send Login",
294
- level: 2
287
+ headlineText: "Send Login",
288
+ headlineLevel: 2
295
289
  }
296
290
  }
297
291
  },
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="cmd-opening-hours">
3
3
  <!-- begin cmd-custom-headline -->
4
- <CmdCustomHeadline v-if="cmdCustomHeadline" :headline="cmdCustomHeadline" />
4
+ <CmdCustomHeadline v-if="cmdCustomHeadline" v-bind="cmdCustomHeadline" />
5
5
  <!-- end cmd-custom-headline -->
6
6
 
7
7
  <!-- begin opening-status with link to detail-page -->
@@ -3,7 +3,7 @@
3
3
  <div
4
4
  v-if="showSystemMessage"
5
5
  :class="['cmd-system-message', 'system-message', 'flex-container', 'vertical', { 'full-width': fullWidth }, validationStatus]"
6
- :role="status === 'error' ? 'alert' : 'dialog'"
6
+ :role="validationStatus === 'error' ? 'alert' : 'dialog'"
7
7
  >
8
8
  <a
9
9
  v-if="iconClose.show && iconClose.iconClass"
@@ -1,11 +1,11 @@
1
1
  <template>
2
- <div :class="['cmd-table-wrapper', {'collapsed': !showTableData, 'full-width': fullWidth}]">
2
+ <div :class="['cmd-table-wrapper', {'collapsed': !showTableData, 'full-width': fullWidth, 'has-caption': hasCaption}]">
3
3
  <div v-if="collapsible || userCanToggleWidth" class="button-wrapper">
4
4
  <a v-if="userCanToggleWidth" class="button"
5
5
  href="#" @click.prevent="fullWidth = !fullWidth"
6
- :title="fullWidth ? iconStretch.tooltip : iconShrink.tooltip"
6
+ :title="iconToggleWidth.tooltip"
7
7
  >
8
- <span :class="fullWidth ? iconStretch.iconClass : iconShrink.iconClass"></span>
8
+ <span :class="iconToggleWidth.iconClass"></span>
9
9
  </a>
10
10
  <a v-if="collapsible" class="button"
11
11
  href="#" @click.prevent="showTableData = !showTableData"
@@ -14,34 +14,38 @@
14
14
  <span :class="showTableData ? iconCollapse.iconClass : iconExpand.iconClass"></span>
15
15
  </a>
16
16
  </div>
17
- <table :class="{'full-width': fullWidth}">
18
- <caption :class="{hidden: !tableData.caption.show}">{{ tableData.caption.text }}</caption>
19
- <thead>
17
+ <div class="inner-wrapper">
18
+ <table :class="{'full-width': fullWidth}">
19
+ <caption v-if="tableData.caption?.text || caption?.text" :class="{ hidden: hideCaption }">
20
+ {{ caption?.text || tableData.caption?.text }}
21
+ </caption>
22
+ <thead>
20
23
  <tr>
21
24
  <th v-for="(tablehead, indexHead) in tableData.thead" :key="indexHead">
22
25
  {{ tablehead }}
23
26
  </th>
24
27
  </tr>
25
- </thead>
26
- <transition name="fade">
27
- <tbody v-show="showTableData" aria-expanded="true">
28
+ </thead>
29
+ <transition name="fade">
30
+ <tbody v-show="showTableData" aria-expanded="true">
28
31
  <tr :class="{'highlighted' : tableData.rowIndexHighlighted === indexRows}" v-for="(tablerows, indexRows) in tableData.tbody" :key="indexRows">
29
32
  <td :class="{'highlighted' : tableData.columnIndexHighlighted === indexData}" v-for="(tabledata, indexData) in tablerows" :key="indexData">
30
33
  {{ tabledata }}
31
34
  </td>
32
35
  </tr>
33
- </tbody>
34
- </transition>
35
- <transition name="fade">
36
- <tfoot v-if="tableData.tfoot && tableData.tfoot.length && showTableData" aria-expanded="true">
36
+ </tbody>
37
+ </transition>
38
+ <transition name="fade">
39
+ <tfoot v-if="tableData.tfoot && tableData.tfoot.length && showTableData" aria-expanded="true">
37
40
  <tr>
38
41
  <td :class="{'highlighted' : tableData.columnIndexHighlighted === indexFoot}" v-for="(tablefoot, indexFoot) in tableData.tfoot" :key="indexFoot">
39
42
  {{ tablefoot }}
40
43
  </td>
41
44
  </tr>
42
- </tfoot>
43
- </transition>
44
- </table>
45
+ </tfoot>
46
+ </transition>
47
+ </table>
48
+ </div>
45
49
  </div>
46
50
  </template>
47
51
 
@@ -62,6 +66,15 @@ export default {
62
66
  type: Object,
63
67
  required: true
64
68
  },
69
+ /**
70
+ * caption for table (shown above table)
71
+ *
72
+ * @requiredForAccessibility: true
73
+ */
74
+ caption: {
75
+ type: Object,
76
+ required: false
77
+ },
65
78
  /**
66
79
  * activate if table should be collapsible
67
80
  */
@@ -116,12 +129,12 @@ export default {
116
129
  *
117
130
  * @requiredForAccessibility: partial
118
131
  */
119
- iconShrink: {
132
+ iconToggleWidth: {
120
133
  type: Object,
121
134
  default: function () {
122
135
  return {
123
- iconClass: "icon-single-arrow-left",
124
- tooltip: "Shrink table"
136
+ iconClass: "icon-table",
137
+ tooltip: "Toggle table width"
125
138
  }
126
139
  }
127
140
  },
@@ -139,6 +152,19 @@ export default {
139
152
  }
140
153
  }
141
154
  }
155
+ },
156
+ computed: {
157
+ hasCaption() {
158
+ if (this.hideCaption) {
159
+ return false
160
+ }
161
+
162
+ // check is a caption-text is defined
163
+ return this.tableData.caption?.text || this.caption?.text
164
+ },
165
+ hideCaption() {
166
+ return this.caption?.show === false || (this.caption?.show !== true && !this.tableData.caption?.show)
167
+ }
142
168
  }
143
169
  }
144
170
  </script>
@@ -147,9 +173,10 @@ export default {
147
173
  /* begin cmd-table-wrapper ---------------------------------------------------------------------------------------- */
148
174
  .cmd-table-wrapper {
149
175
  display: inline-flex;
176
+ flex-direction: column;
150
177
  max-width: 100%;
151
- overflow-x: auto;
152
178
  margin-bottom: var(--default-margin);
179
+ gap: calc(var(--default-margin) / 2);
153
180
 
154
181
  &.collapsed, &.full-width {
155
182
  overflow: hidden;
@@ -162,7 +189,6 @@ export default {
162
189
  }
163
190
 
164
191
  > .button-wrapper {
165
- position: absolute;
166
192
  right: 0;
167
193
  z-index: 100;
168
194
  gap: calc(var(--default-gap) / 2);
@@ -172,6 +198,7 @@ export default {
172
198
  padding: 0;
173
199
  min-width: 2rem;
174
200
  min-height: 2rem;
201
+ background: var(--pure-white);
175
202
 
176
203
  span[class*="icon"] {
177
204
  color: var(--primary-color);
@@ -182,25 +209,39 @@ export default {
182
209
  }
183
210
  }
184
211
  }
185
-
186
- & + table {
187
- margin-top: calc(var(--default-margin) / 2);
188
- }
189
212
  }
190
213
 
191
- table {
192
- table-layout: fixed;
193
- margin: 0;
214
+ .inner-wrapper {
215
+ overflow-x: auto;
216
+ width: 100%;
217
+
218
+ table {
219
+ table-layout: fixed;
220
+ margin: 0;
194
221
 
195
- th {
196
- a[class*='icon-'] {
197
- &, &:hover, &:active, &:focus {
198
- font-size: 1rem;
199
- color: var(--pure-white);
222
+ th {
223
+ a[class*='icon-'] {
224
+ &, &:hover, &:active, &:focus {
225
+ font-size: 1rem;
226
+ color: var(--pure-white);
227
+ }
200
228
  }
201
229
  }
202
230
  }
203
231
  }
232
+
233
+ &.has-caption {
234
+ flex-direction: row;
235
+
236
+ .button-wrapper {
237
+ position: absolute;
238
+ }
239
+
240
+ table {
241
+ margin-top: calc(var(--default-margin) / 2);
242
+ }
243
+ }
244
+
204
245
  }
205
246
 
206
247
  /* end cmd-table-wrapper ------------------------------------------------------------------------------------------ */
@@ -9,7 +9,7 @@
9
9
  </li>
10
10
  </ul>
11
11
  <template v-if="useSlot">
12
- <div v-show="showTab === index" v-for="(tab, index) in tabs" :key="index" aria-live="assertive">
12
+ <div v-show="showTab === index" v-for="index in tabs.length" :key="index" aria-live="assertive">
13
13
  <!-- begin slot-content -->
14
14
  <slot :name="'tab-content-' + index"></slot>
15
15
  <!-- end slot-content -->
@@ -19,10 +19,10 @@
19
19
  <!-- begin CmdCustomHeadline -->
20
20
  <CmdCustomHeadline
21
21
  v-bind="cmdCustomHeadline"
22
- :headlineText="tabs[showTab].headline"
22
+ :headlineText="tabs[showTab].headlineText"
23
+ :headlineLevel="tabs[showTab].headlineLevel"
23
24
  />
24
25
  <!-- end CmdCustomHeadline -->
25
-
26
26
  <div v-html="tabs[showTab].htmlContent"></div>
27
27
  </div>
28
28
  </div>