comand-component-library 4.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
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')