comand-component-library 3.1.57 → 3.1.60

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/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>