comand-component-library 4.0.0 → 4.0.1

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.
Files changed (31) hide show
  1. package/dist/comand-component-library.js +1670 -1603
  2. package/dist/comand-component-library.umd.cjs +4 -4
  3. package/dist/style.css +1 -1
  4. package/package.json +2 -2
  5. package/src/{App.vue → ComponentLibrary.vue} +875 -413
  6. package/src/assets/data/main-navigation.json +2 -0
  7. package/src/components/CmdAddressData.vue +1 -1
  8. package/src/components/CmdBox.vue +40 -4
  9. package/src/components/CmdBoxWrapper.vue +15 -5
  10. package/src/components/CmdFormElement.vue +37 -33
  11. package/src/components/CmdHeadline.vue +97 -33
  12. package/src/components/CmdInputGroup.vue +6 -5
  13. package/src/components/CmdListOfLinks.vue +24 -24
  14. package/src/components/CmdLoginForm.vue +1 -0
  15. package/src/components/CmdMainNavigation.vue +20 -9
  16. package/src/components/CmdMultistepFormProgressBar.vue +43 -1
  17. package/src/components/CmdNewsletterSubscription.vue +7 -7
  18. package/src/components/CmdOpeningHours.vue +33 -18
  19. package/src/components/CmdOpeningHoursItem.vue +21 -13
  20. package/src/components/CmdPagination.vue +2 -2
  21. package/src/components/CmdSidebar.vue +6 -1
  22. package/src/components/CmdSiteHeader.vue +2 -0
  23. package/src/components/CmdSiteSearch.vue +12 -11
  24. package/src/components/CmdSystemMessage.vue +1 -0
  25. package/src/components/CmdTable.vue +9 -1
  26. package/src/components/CmdTextImageBlock.vue +2 -0
  27. package/src/components/CmdThumbnailScroller.vue +52 -32
  28. package/src/components/CmdTooltip.vue +5 -0
  29. package/src/components/CmdUploadForm.vue +67 -41
  30. package/src/components/ComponentSettings.vue +171 -0
  31. package/src/main.js +3 -3
@@ -24,22 +24,24 @@
24
24
  </CmdSystemMessage>
25
25
  <!-- end CmdSystemMessage -->
26
26
 
27
- <div :class="['box drop-area flex-container vertical', { 'allow-drop': allowDrop }]" v-on="dragAndDropHandler">
27
+ <div :class="['box flex-container vertical', { 'drop-area': enableDragAndDrop, 'allow-drop': allowDrop }]" v-on="dragAndDropHandler">
28
28
  <template v-if="!listOfFiles.length">
29
+ <!-- begin CmdHeadline -->
29
30
  <CmdHeadline v-if="allowMultipleFileUploads" v-bind="cmdHeadlineNoFilesToUpload" headlineLevel="4">
30
- {{ getMessage("cmduploadform.no_files_to_upload") }}
31
- </CmdHeadline>
32
- <CmdHeadline v-else v-bind="cmdHeadlineNoFilesToUpload" headlineLevel="4">
33
- {{ getMessage("cmduploadform.no_file_to_upload") }}
31
+ {{ headlineTextNoFilesToUpload }}
34
32
  </CmdHeadline>
33
+ <!-- end CmdHeadline -->
35
34
  </template>
36
35
 
37
36
  <!-- begin total-upload information -->
38
37
  <div v-else class="flex-container vertical">
39
38
  <div v-if="showTotalUpload && listOfFiles.length !== 1" class="flex-container vertical list-files-wrapper">
39
+ <!-- begin CmdHeadline -->
40
40
  <CmdHeadline v-bind="cmdHeadlineSummaryOfAllFiles" headlineLevel="4">
41
41
  {{ getMessage("cmduploadform.headline.summary_of_all_files") }}
42
42
  </CmdHeadline>
43
+ <!-- end CmdHeadline -->
44
+
43
45
  <ul v-if="showTotalUpload && listOfFiles.length !== 1" class="list-of-files total-files">
44
46
  <li class="flex-container no-flex">
45
47
  <a
@@ -83,9 +85,12 @@
83
85
 
84
86
  <div class="flex-container vertical list-files-wrapper">
85
87
  <!-- begin list of selected files -->
88
+ <!-- begin CmdHeadline -->
86
89
  <CmdHeadline v-bind="cmdHeadlineListOfSelectedFiles" headlineLevel="4">
87
90
  {{ getMessage("cmduploadform.headline.list_of_selected_files") }}
88
91
  </CmdHeadline>
92
+ <!-- end CmdHeadline -->
93
+
89
94
  <ul class="list-of-files">
90
95
  <li
91
96
  v-for="(uploadFile, index) in listOfFiles"
@@ -108,20 +113,21 @@
108
113
  { error: uploadFile.error }
109
114
  ]">
110
115
  {{ uploadFile.file.name }} <small>({{ formatSize(uploadFile.file.size) }})</small>
111
- </span>
112
- <template v-if="uploadInitiated && !uploadFile.error">
113
- <span class="progressbar">
114
- <span>{{ getPercentage(uploadFile.progress) }}</span>
115
- <!-- do not place inside progress-tag (will not be displayed then) -->
116
- <progress
117
- max="100"
118
- :value="uploadFile.progress"
119
- :title="
120
- formatSize(uploadFile.uploadedBytes) + '/' + formatSize(uploadFile.file.size)
121
- "
122
- ></progress>
123
- </span>
124
- </template>
116
+ </span>
117
+
118
+ <!-- begin progressbar -->
119
+ <span class="progressbar" v-if="uploadInitiated && !uploadFile.error">
120
+ <span>{{ getPercentage(uploadFile.progress) }}</span>
121
+ <!-- do not place inside progress-tag (will not be displayed then) -->
122
+ <progress
123
+ max="100"
124
+ :value="uploadFile.progress"
125
+ :title="
126
+ formatSize(uploadFile.uploadedBytes) + '/' + formatSize(uploadFile.file.size)
127
+ "
128
+ ></progress>
129
+ </span>
130
+ <!-- end progressbar -->
125
131
  </li>
126
132
  </ul>
127
133
  <a
@@ -137,12 +143,18 @@
137
143
  <!-- end list of selected files -->
138
144
 
139
145
  <!-- begin upload conditions -->
146
+ <!-- begin CmdHeadline -->
140
147
  <CmdHeadline v-if="allowMultipleFileUploads && listOfFiles.length" v-bind="cmdHeadlineSelectAdditionalFiles" headlineLevel="4">
141
148
  {{ getMessage("cmduploadform.headline.select_additional_files") }}
142
149
  </CmdHeadline>
150
+ <!-- end CmdHeadline -->
151
+
152
+ <!-- begin CmdHeadline -->
143
153
  <CmdHeadline v-if="!allowMultipleFileUploads && listOfFiles.length" v-bind="cmdHeadlineSelectNewFile" headlineLevel="4">
144
154
  {{ getMessage("cmduploadform.headline.select_new_file") }}
145
155
  </CmdHeadline>
156
+ <!-- end CmdHeadline -->
157
+
146
158
  <dl class="small">
147
159
  <template v-if="maxTotalUploadSize > 0">
148
160
  <dt :class="{ error: totalSize > maxTotalUploadSize }">
@@ -188,7 +200,8 @@
188
200
  </dl>
189
201
  <!-- end upload conditions -->
190
202
 
191
- <div>
203
+ <!-- begin upload-button and drag-and-drop-text -->
204
+ <div class="flex-container vertical no-gap">
192
205
  <button
193
206
  type="button"
194
207
  :class="['button upload primary', { disabled: uploadInitiated }]"
@@ -217,7 +230,9 @@
217
230
  </strong>
218
231
  </p>
219
232
  </div>
233
+ <!-- end upload-button and drag-and-drop-text -->
220
234
  </div>
235
+
221
236
  <!-- begin CmdFormElement -->
222
237
  <CmdFormElement
223
238
  v-if="enableComment"
@@ -268,7 +283,8 @@
268
283
  <!-- end advanced mode -->
269
284
 
270
285
  <!-- begin simple mode -->
271
- <a v-else href="#" @click.prevent="selectFiles" :class="['cmd-upload-form drop-area', {'allow-drop': allowDrop }]" v-on="dragAndDropHandler">
286
+ <a v-else href="#" @click.prevent="selectFiles" :class="['cmd-upload-form box', { 'drop-area': enableDragAndDrop, 'allow-drop': allowDrop }]" v-on="dragAndDropHandler">
287
+ <!-- begin progressbar -->
272
288
  <span class="progressbar" v-if="uploadInitiated">
273
289
  <span>{{ getPercentage(totalUploadProgress) }}</span>
274
290
  <progress
@@ -277,10 +293,11 @@
277
293
  :title="totalBytesUploaded">
278
294
  </progress>
279
295
  </span>
296
+ <!-- end progressbar -->
280
297
 
281
298
  <!-- begin slot-content -->
282
299
  <slot>
283
- <template v-if="enableDragAndDrop">
300
+ <template v-if="!enableDragAndDrop">
284
301
  <template v-if="fileTypeImage">
285
302
  <span>{{ getMessage("cmduploadform.select_image") }}</span>
286
303
  <!-- begin CmdIcon -->
@@ -455,6 +472,22 @@ export default {
455
472
  type: Boolean,
456
473
  default: true
457
474
  },
475
+ /**
476
+ * toggle visibility for legend-text
477
+ */
478
+ showLegend: {
479
+ type: Boolean,
480
+ default: true
481
+ },
482
+ /**
483
+ * text for legend
484
+ *
485
+ * @requiredForAccessibility: true
486
+ */
487
+ textLegend: {
488
+ type: String,
489
+ required: false
490
+ },
458
491
  /**
459
492
  * set icon for delete-icons
460
493
  */
@@ -611,25 +644,12 @@ export default {
611
644
  cmdHeadlineSelectNewFile: {
612
645
  type: Object,
613
646
  required: false
614
- },
615
- /**
616
- * toggle visibility for legend-text
617
- */
618
- showLegend: {
619
- type: Boolean,
620
- default: true
621
- },
622
- /**
623
- * text for legend
624
- *
625
- * @requiredForAccessibility: true
626
- */
627
- textLegend: {
628
- type: String,
629
- required: false
630
647
  }
631
648
  },
632
649
  computed: {
650
+ headlineTextNoFilesToUpload() {
651
+ return this.allowMultipleFileUploads ? this.getMessage("cmduploadform.no_files_to_upload") : this.this.getMessage("cmduploadform.no_file_to_upload")
652
+ },
633
653
  fileTypeImage() {
634
654
  return this.allowedFileExtensions.some(extension => extension.includes('jpg'));
635
655
  },
@@ -1076,7 +1096,7 @@ export default {
1076
1096
  overflow-x: hidden;
1077
1097
  overflow-y: auto;
1078
1098
  border: var(--default-border);
1079
- padding: calc(var(--default-padding) * 2);
1099
+ padding: var(--default-padding);
1080
1100
  margin: 0;
1081
1101
 
1082
1102
  > li {
@@ -1187,14 +1207,20 @@ export default {
1187
1207
  }
1188
1208
  }
1189
1209
 
1190
- &.drop-area {
1210
+ &.box {
1191
1211
  display: inline-flex;
1192
1212
  flex-direction: column;
1193
- text-decoration: none;
1194
1213
  background: var(--default-background-color);
1214
+ text-decoration: none;
1215
+ text-align: center;
1216
+ padding: var(--default-padding);
1195
1217
 
1196
1218
  span {
1197
1219
  margin: 0;
1220
+
1221
+ &[class*="icon-"] {
1222
+ font-size: 5rem;
1223
+ }
1198
1224
  }
1199
1225
  }
1200
1226
  }
@@ -0,0 +1,171 @@
1
+ <template>
2
+ <CmdBox
3
+ :use-slots="['body']"
4
+ :collapsible="true"
5
+ :cmdHeadline="{headlineText: readableName(componentName), headlineLevel: 4, headlineIcon: {iconClass: 'icon-settings-template'}}"
6
+ :openCollapsedBox="true"
7
+ boxBodyClass="settings-body"
8
+ >
9
+ <template v-slot:body>
10
+ <CmdFormElement
11
+ v-for="(prop) in filteredProps" :key="prop.name"
12
+ :element="formElement(prop)"
13
+ :type="formType(prop)"
14
+ :labelText="readableName(prop.name)"
15
+ :placeholder="readableName(prop.name)"
16
+ :toggleSwitch="prop.toggleSwitch"
17
+ :colored="true"
18
+ :selectOptions="selectOptions(prop)"
19
+ :modelValue="prop.value"
20
+ @update:modelValue="onUpdateProperty(prop.name, $event)"
21
+ />
22
+ </template>
23
+ </CmdBox>
24
+ </template>
25
+
26
+ <script>
27
+
28
+ export default {
29
+ name: "ComponentSettings",
30
+ data() {
31
+ return {
32
+ currentComponentName: ""
33
+ }
34
+ },
35
+ props: {
36
+ componentName: {
37
+ type: String,
38
+ default: ""
39
+ },
40
+ componentProps: {
41
+ type: Object,
42
+ required: true
43
+ },
44
+ componentSettings: {
45
+ type: Object,
46
+ required: true
47
+ },
48
+ componentControls: {
49
+ type: Object
50
+ }
51
+ },
52
+ computed: {
53
+ filteredProps() {
54
+ return this.filterProperties(this.componentProps, [])
55
+ }
56
+ },
57
+ methods: {
58
+ filterProperties(properties, nameParts) {
59
+ const allProps = []
60
+
61
+ for (let key in properties) {
62
+ const propType = typeof properties[key]
63
+ if (propType === "boolean" || propType === "string" || propType === "number" || (propType === "object" && key.slice(0, 3) === "cmd")) {
64
+
65
+ if(propType === "object") {
66
+ this.filterProperties(properties[key], [...nameParts, key]).forEach((item) => allProps.push(item))
67
+ } else {
68
+ const prop = {}
69
+
70
+ if (propType === "boolean") {
71
+ prop.toggleSwitch = true
72
+ }
73
+
74
+ prop.name = [...nameParts, key].join(".")
75
+ prop.type = propType
76
+ prop.value = properties[key]
77
+
78
+ allProps.push(prop)
79
+ }
80
+ }
81
+ }
82
+
83
+ return allProps
84
+ },
85
+ onUpdateProperty(propName, value) {
86
+ const nameParts = propName.split(".")
87
+ let settings = this.componentSettings
88
+ for (let i = 0; i < nameParts.length - 1; i++) {
89
+ settings = settings[nameParts.shift()]
90
+ }
91
+
92
+ if (typeof settings[nameParts[0]] === "number") {
93
+ settings[nameParts[0]] = Number(value)
94
+ } else {
95
+ settings[nameParts[0]] = value
96
+ }
97
+ },
98
+ readableName(name) {
99
+ // remove prefix from current component-name
100
+ let nameWithoutPrefix = name.replace("Cmd", "")
101
+
102
+ // remove entire prefix (componentName) for inner-component-properties
103
+ nameWithoutPrefix = nameWithoutPrefix.replace(/^[^.]*\./, '');
104
+
105
+ // use a regular expression to find the positions of capital letters
106
+ let capitalPositions = []
107
+ nameWithoutPrefix.replace(/[A-Z]/g, function (match, index) {
108
+ capitalPositions.push(index)
109
+ return match
110
+ })
111
+
112
+ // add a space before each capital letter based on the found positions
113
+ for (let i = capitalPositions.length - 1; i >= 0; i--) {
114
+ nameWithoutPrefix = nameWithoutPrefix.slice(0, capitalPositions[i]) + ' ' + nameWithoutPrefix.slice(capitalPositions[i])
115
+ }
116
+
117
+ // capitalize first letter
118
+ nameWithoutPrefix = nameWithoutPrefix.charAt(0).toUpperCase() + nameWithoutPrefix.slice(1)
119
+
120
+ return nameWithoutPrefix
121
+ },
122
+ formType(prop) {
123
+ if (Array.isArray(this.componentControls?.[prop.name])) {
124
+ return null
125
+ }
126
+
127
+ switch (prop.type) {
128
+ case "boolean":
129
+ return "checkbox"
130
+
131
+ case "number":
132
+ return "number"
133
+
134
+ default:
135
+ return "text"
136
+
137
+ }
138
+ },
139
+ formElement(prop) {
140
+ if (Array.isArray(this.componentControls?.[prop.name])) {
141
+ return "select"
142
+ } else {
143
+ return "input"
144
+ }
145
+ },
146
+ selectOptions(prop) {
147
+ if (Array.isArray(this.componentControls?.[prop.name])) {
148
+ return this.componentControls[prop.name]
149
+ } else {
150
+ return null
151
+ }
152
+ }
153
+ },
154
+ watch: {
155
+ componentName: {
156
+ handler() {
157
+ this.currentComponentName = this.componentName
158
+ },
159
+ immediate: true
160
+ }
161
+ }
162
+ }
163
+ </script>
164
+
165
+ <style>
166
+ .cmd-box .settings-body > div {
167
+ display: flex;
168
+ flex-direction: column;
169
+ gap: calc(var(--default-gap) / 2);
170
+ }
171
+ </style>
package/src/main.js CHANGED
@@ -4,8 +4,8 @@ import "comand-frontend-framework/styles"
4
4
 
5
5
  import { createApp } from "vue"
6
6
 
7
- // import App from "./App.vue"
8
- import App from "./App.vue"
7
+ // import ComponentLibrary from "./ComponentLibrary.vue"
8
+ import ComponentLibrary from "./ComponentLibrary.vue"
9
9
  //import { createRouter, createWebHistory } from "vue-router"
10
10
  import "clickout-event"
11
11
 
@@ -53,4 +53,4 @@ import router from "./router"
53
53
  // })
54
54
 
55
55
  // createApp(App).use(router).directive('telephone', directiveTelephone).directive('focus', directiveFocus).mount('#app')
56
- createApp(App).use(router).directive('telephone', directiveTelephone).directive('focus', directiveFocus).mount('#app')
56
+ createApp(ComponentLibrary).use(router).directive('telephone', directiveTelephone).directive('focus', directiveFocus).mount('#app')