comand-component-library 3.1.44 → 3.1.47

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 (234) hide show
  1. package/dist/comand-component-library.css +1 -1
  2. package/dist/comand-component-library.umd.min.js +1 -1
  3. package/package.json +47 -41
  4. package/src/App.vue +373 -135
  5. package/src/ComponentDocumentation.vue +156 -0
  6. package/src/ComponentLibraryHelp.vue +20 -0
  7. package/src/assets/data/accordion.json +21 -24
  8. package/src/assets/data/address-data.json +34 -0
  9. package/src/assets/data/bank-account-data.json +22 -0
  10. package/src/assets/data/box-product.json +14 -4
  11. package/src/assets/data/box-user.json +48 -22
  12. package/src/assets/data/breadcrumbs.json +11 -3
  13. package/src/assets/data/cookie-disclaimer.json +4 -4
  14. package/src/assets/data/fake-select-colors.json +4 -0
  15. package/src/assets/data/fake-select-countries.json +12 -12
  16. package/src/assets/data/fake-select-filter-options.json +14 -0
  17. package/src/assets/data/fake-select-options-with-icons.json +6 -12
  18. package/src/assets/data/fake-select-options.json +3 -3
  19. package/src/assets/data/list-of-links-section-anchors.json +23 -0
  20. package/src/assets/data/list-of-links-top-header-navigation.json +20 -0
  21. package/src/assets/data/list-of-links.json +42 -0
  22. package/src/assets/data/main-navigation.json +48 -0
  23. package/src/assets/data/multistep-form-progress-bar.json +33 -0
  24. package/src/assets/data/select-options.json +4 -0
  25. package/src/assets/data/{share-buttons.json → share-buttons-page-by-json.json} +8 -8
  26. package/src/assets/data/share-buttons-page-by-property.json +30 -0
  27. package/src/assets/data/switch-language.json +20 -0
  28. package/src/assets/data/table-large.json +1 -1
  29. package/src/assets/data/table-small.json +1 -1
  30. package/src/assets/styles/global-styles.scss +43 -14
  31. package/src/assets/styles/transitions.scss +21 -1
  32. package/src/components/CmdAccordion.vue +43 -42
  33. package/src/components/CmdAddressData.vue +124 -56
  34. package/src/components/CmdBackToTopButton.vue +3 -3
  35. package/src/components/CmdBankAccountData.vue +104 -0
  36. package/src/components/CmdBox.vue +253 -56
  37. package/src/components/CmdBoxSiteSearch.vue +138 -39
  38. package/src/components/CmdBoxWrapper.vue +206 -0
  39. package/src/components/CmdBreadcrumbs.vue +29 -13
  40. package/src/components/CmdCompanyLogo.vue +6 -4
  41. package/src/components/CmdCookieDisclaimer.vue +99 -75
  42. package/src/components/CmdCopyrightInformation.vue +1 -1
  43. package/src/components/CmdCustomHeadline.vue +93 -0
  44. package/src/components/CmdFakeSelect.vue +330 -66
  45. package/src/components/CmdFancyBox.vue +47 -33
  46. package/src/components/CmdForm.vue +107 -0
  47. package/src/components/CmdFormElement.vue +528 -79
  48. package/src/components/CmdFormFilters.vue +25 -11
  49. package/src/components/CmdGoogleMaps.vue +9 -3
  50. package/src/components/CmdImageGallery.vue +28 -5
  51. package/src/components/CmdImageZoom.vue +9 -1
  52. package/src/components/CmdListOfLinks.vue +169 -0
  53. package/src/components/CmdLoginForm.vue +143 -63
  54. package/src/components/CmdMainNavigation.vue +140 -42
  55. package/src/components/CmdMultipleSwitch.vue +33 -2
  56. package/src/components/CmdMultistepFormProgressBar.vue +60 -10
  57. package/src/components/CmdOpeningHours.vue +36 -10
  58. package/src/components/CmdPager.vue +7 -5
  59. package/src/components/CmdProgressBar.vue +20 -3
  60. package/src/components/CmdShareButtons.vue +64 -9
  61. package/src/components/CmdSiteHeader.vue +25 -12
  62. package/src/components/CmdSlideButton.vue +5 -2
  63. package/src/components/CmdSlideshow.vue +23 -7
  64. package/src/components/CmdSwitchButton.vue +10 -3
  65. package/src/components/CmdSwitchLanguage.vue +18 -10
  66. package/src/components/CmdSystemMessage.vue +30 -17
  67. package/src/components/CmdTable.vue +15 -7
  68. package/src/components/CmdTabs.vue +43 -3
  69. package/src/components/CmdThumbnailScroller.vue +22 -6
  70. package/src/components/CmdTooltip.vue +184 -11
  71. package/src/components/CmdUploadForm.vue +198 -92
  72. package/src/components/CmdWidthLimitationWrapper.vue +9 -6
  73. package/src/composables/event.js +8 -0
  74. package/src/composables/scrollspy.js +52 -0
  75. package/src/directives/focus.js +19 -0
  76. package/src/directives/telephone.js +1 -1
  77. package/src/documentation/commonProps.js +6 -0
  78. package/src/documentation/components/ComponentCode.vue +50 -0
  79. package/src/documentation/components/ComponentProperties.vue +237 -0
  80. package/src/documentation/components/ExampleSectionWrapper.vue +46 -0
  81. package/src/documentation/components/ViewCodeData.vue +113 -0
  82. package/src/documentation/data/CmdAccordionHelp.js +22 -0
  83. package/src/documentation/data/CmdAddressDataHelp.js +17 -0
  84. package/src/documentation/data/CmdBackToTopButtonHelp.js +3 -0
  85. package/src/documentation/data/CmdBankAccountDataHelp.js +8 -0
  86. package/src/documentation/data/CmdBoxHelp.js +45 -0
  87. package/src/documentation/data/CmdBoxSiteSearchHelp.js +11 -0
  88. package/src/documentation/data/CmdBreadcrumbsHelp.js +6 -0
  89. package/src/documentation/data/CmdCompanyLogoHelp.js +8 -0
  90. package/src/documentation/data/CmdCookieDisclaimerHelp.js +9 -0
  91. package/src/documentation/data/CmdCopyrightInformation.js +2 -0
  92. package/src/documentation/data/CmdCustomHeadlineHelp.js +8 -0
  93. package/src/documentation/data/CmdFakeSelectHelp.js +60 -0
  94. package/src/documentation/data/CmdFancyBoxHelp.js +7 -0
  95. package/src/documentation/data/CmdFooterNavigationHelp.js +5 -0
  96. package/src/documentation/data/CmdFormElementHelp.js +189 -0
  97. package/src/documentation/data/CmdFormFiltersHelp.js +6 -0
  98. package/src/documentation/data/CmdFormHelp.js +10 -0
  99. package/src/documentation/data/CmdGoogleMapsHelp.js +5 -0
  100. package/src/documentation/data/CmdImageGalleryHelp.js +5 -0
  101. package/src/documentation/data/CmdImageZoomHelp.js +6 -0
  102. package/src/documentation/data/CmdListOfLinksHelp.js +24 -0
  103. package/src/documentation/data/CmdLoginFormHelp.js +6 -0
  104. package/src/documentation/data/CmdMainNavigationHelp.js +7 -0
  105. package/src/documentation/data/CmdMultistepFormProgressBarHelp.js +6 -0
  106. package/src/documentation/data/CmdOpeningHoursHelp.js +10 -0
  107. package/src/documentation/data/CmdPagerHelp.js +7 -0
  108. package/src/documentation/data/CmdProgressBarHelp.js +13 -0
  109. package/src/documentation/data/CmdShareButtonsHelp.js +13 -0
  110. package/src/documentation/data/CmdSiteHeaderHelp.js +21 -0
  111. package/src/documentation/data/CmdSlideButtonHelp.js +10 -0
  112. package/src/documentation/data/CmdSlideshowHelp.js +7 -0
  113. package/src/documentation/data/CmdSwitchLanguageHelp.js +6 -0
  114. package/src/documentation/data/CmdSystemMessageHelp.js +32 -0
  115. package/src/documentation/data/CmdTableHelp.js +14 -0
  116. package/src/documentation/data/CmdTabsHelp.js +10 -0
  117. package/src/documentation/data/CmdThumbnailScrollerHelp.js +5 -0
  118. package/src/documentation/data/CmdTooltipHelp.js +13 -0
  119. package/src/documentation/data/CmdUploadFormHelp.js +17 -0
  120. package/src/documentation/data/CmdWidthLimitationWrapperHelp.js +7 -0
  121. package/src/documentation/data/componentsDescription.json +158 -0
  122. package/src/documentation/generated/CmdAccordionPropertyDescriptions.json +57 -0
  123. package/src/documentation/generated/CmdAddressDataPropertyDescriptions.json +32 -0
  124. package/src/documentation/generated/CmdBackToTopButtonPropertyDescriptions.json +12 -0
  125. package/src/documentation/generated/CmdBankAccountDataPropertyDescriptions.json +34 -0
  126. package/src/documentation/generated/CmdBoxPropertyDescriptions.json +91 -0
  127. package/src/documentation/generated/CmdBoxSiteSearchPropertyDescriptions.json +41 -0
  128. package/src/documentation/generated/CmdBoxWrapperPropertyDescriptions.json +47 -0
  129. package/src/documentation/generated/CmdBreadcrumbsPropertyDescriptions.json +17 -0
  130. package/src/documentation/generated/CmdCompanyLogoPropertyDescriptions.json +27 -0
  131. package/src/documentation/generated/CmdCookieDisclaimerPropertyDescriptions.json +22 -0
  132. package/src/documentation/generated/CmdCustomHeadlinePropertyDescriptions.json +22 -0
  133. package/src/documentation/generated/CmdFakeSelectPropertyDescriptions.json +79 -0
  134. package/src/documentation/generated/CmdFancyBoxPropertyDescriptions.json +62 -0
  135. package/src/documentation/generated/CmdFooterNavigationPropertyDescriptions.json +17 -0
  136. package/src/documentation/generated/CmdFormElementPropertyDescriptions.json +178 -0
  137. package/src/documentation/generated/CmdFormFiltersPropertyDescriptions.json +32 -0
  138. package/src/documentation/generated/CmdFormPropertyDescriptions.json +40 -0
  139. package/src/documentation/generated/CmdGoogleMapsPropertyDescriptions.json +7 -0
  140. package/src/documentation/generated/CmdImageGalleryPropertyDescriptions.json +22 -0
  141. package/src/documentation/generated/CmdImageZoomPropertyDescriptions.json +12 -0
  142. package/src/documentation/generated/CmdListOfLinksPropertyDescriptions.json +60 -0
  143. package/src/documentation/generated/CmdLoginFormPropertyDescriptions.json +90 -0
  144. package/src/documentation/generated/CmdMainNavigationPropertyDescriptions.json +62 -0
  145. package/src/documentation/generated/CmdMultipleSwitchPropertyDescriptions.json +52 -0
  146. package/src/documentation/generated/CmdMultistepFormProgressBarPropertyDescriptions.json +17 -0
  147. package/src/documentation/generated/CmdOpeningHoursPropertyDescriptions.json +42 -0
  148. package/src/documentation/generated/CmdPagerPropertyDescriptions.json +37 -0
  149. package/src/documentation/generated/CmdProgressBarPropertyDescriptions.json +32 -0
  150. package/src/documentation/generated/CmdShareButtonsPropertyDescriptions.json +34 -0
  151. package/src/documentation/generated/CmdSiteHeaderPropertyDescriptions.json +27 -0
  152. package/src/documentation/generated/CmdSlideButtonPropertyDescriptions.json +25 -0
  153. package/src/documentation/generated/CmdSlideshowPropertyDescriptions.json +42 -0
  154. package/src/documentation/generated/CmdSwitchButtonPropertyDescriptions.json +79 -0
  155. package/src/documentation/generated/CmdSwitchLanguagePropertyDescriptions.json +7 -0
  156. package/src/documentation/generated/CmdSystemMessagePropertyDescriptions.json +40 -0
  157. package/src/documentation/generated/CmdTablePropertyDescriptions.json +62 -0
  158. package/src/documentation/generated/CmdTabsPropertyDescriptions.json +27 -0
  159. package/src/documentation/generated/CmdThumbnailScrollerPropertyDescriptions.json +32 -0
  160. package/src/documentation/generated/CmdTooltipPropertyDescriptions.json +17 -0
  161. package/src/documentation/generated/CmdUploadFormPropertyDescriptions.json +90 -0
  162. package/src/documentation/generated/CmdWidthLimitationWrapperPropertyDescriptions.json +41 -0
  163. package/src/documentation/generated/frameworkIcons.json +730 -0
  164. package/src/documentation/generated/logosIcons.json +110 -0
  165. package/src/documentation/tabs.js +46 -0
  166. package/src/documentation/views/ContainerPage.vue +237 -0
  167. package/src/documentation/views/HelpHome.vue +13 -0
  168. package/src/documentation/views/IconFont.vue +80 -0
  169. package/src/documentation/views/components/CmdAccordionHelp.vue +78 -0
  170. package/src/documentation/views/components/CmdAddressDataHelp.vue +65 -0
  171. package/src/documentation/views/components/CmdBackToTopButtonHelp.vue +62 -0
  172. package/src/documentation/views/components/CmdBankAccountDataHelp.vue +88 -0
  173. package/src/documentation/views/components/CmdBoxHelp.vue +137 -0
  174. package/src/documentation/views/components/CmdBoxSiteSearchHelp.vue +60 -0
  175. package/src/documentation/views/components/CmdBoxWrapperHelp.vue +111 -0
  176. package/src/documentation/views/components/CmdBreadcrumbsHelp.vue +51 -0
  177. package/src/documentation/views/components/CmdCompanyLogoHelp.vue +48 -0
  178. package/src/documentation/views/components/CmdCookieDisclaimerHelp.vue +105 -0
  179. package/src/documentation/views/components/CmdCustomHeadlineHelp.vue +53 -0
  180. package/src/documentation/views/components/CmdFakeSelectHelp.vue +175 -0
  181. package/src/documentation/views/components/CmdFancyBoxHelp.vue +79 -0
  182. package/src/documentation/views/components/CmdFormElementHelp.vue +412 -0
  183. package/src/documentation/views/components/CmdFormFiltersHelp.vue +69 -0
  184. package/src/documentation/views/components/CmdFormHelp.vue +41 -0
  185. package/src/documentation/views/components/CmdGoogleMapsHelp.vue +55 -0
  186. package/src/documentation/views/components/CmdImageGalleryHelp.vue +46 -0
  187. package/src/documentation/views/components/CmdImageZoomHelp.vue +34 -0
  188. package/src/documentation/views/components/CmdListOfLinksHelp.vue +64 -0
  189. package/src/documentation/views/components/CmdLoginFormHelp.vue +117 -0
  190. package/src/documentation/views/components/CmdMainNavigationHelp.vue +94 -0
  191. package/src/documentation/views/components/CmdMultistepFormProgressBarHelp.vue +49 -0
  192. package/src/documentation/views/components/CmdOpeningHoursHelp.vue +49 -0
  193. package/src/documentation/views/components/CmdPagerHelp.vue +57 -0
  194. package/src/documentation/views/components/CmdProgressBarHelp.vue +47 -0
  195. package/src/documentation/views/components/CmdShareButtonsHelp.vue +65 -0
  196. package/src/documentation/views/components/CmdSiteHeaderHelp.vue +72 -0
  197. package/src/documentation/views/components/CmdSlideButtonHelp.vue +90 -0
  198. package/src/documentation/views/components/CmdSlideshowHelp.vue +60 -0
  199. package/src/documentation/views/components/CmdSwitchLanguageHelp.vue +64 -0
  200. package/src/documentation/views/components/CmdSystemMessageHelp.vue +86 -0
  201. package/src/documentation/views/components/CmdTableHelp.vue +84 -0
  202. package/src/documentation/views/components/CmdTabsHelp.vue +52 -0
  203. package/src/documentation/views/components/CmdThumbnailScrollerHelp.vue +50 -0
  204. package/src/documentation/views/components/CmdTooltipHelp.vue +59 -0
  205. package/src/documentation/views/components/CmdUploadFormHelp.vue +59 -0
  206. package/src/documentation/views/components/CmdWidthLimitationWrapperHelp.vue +46 -0
  207. package/src/index.js +7 -3
  208. package/src/main.js +25 -15
  209. package/src/mixins/CmdAddressData/DefaultMessageProperties.js +17 -0
  210. package/src/mixins/CmdBox/DefaultMessageProperties.js +10 -0
  211. package/src/mixins/CmdFakeSelect/DefaultMessageProperties.js +9 -0
  212. package/src/mixins/CmdFormElement/DefaultMessageProperties.js +9 -0
  213. package/src/mixins/CmdImageGallery/DefaultMessageProperties.js +9 -0
  214. package/src/mixins/CmdSiteSearch/DefaultMessageProperties.js +14 -0
  215. package/src/mixins/CmdUploadForm/DefaultMessageProperties.js +5 -1
  216. package/src/mixins/FieldValidation.js +220 -0
  217. package/src/mixins/GlobalDefaultMessageProperties.js +15 -0
  218. package/src/mixins/Tooltip.js +26 -0
  219. package/src/router/index.js +67 -0
  220. package/src/utilities.js +3 -6
  221. package/src/utils/common.js +6 -0
  222. package/src/utils/dom.js +8 -0
  223. package/src/utils/globalSequence.js +13 -0
  224. package/src/utils/string.js +8 -0
  225. package/src/assets/data/address.json +0 -13
  226. package/src/assets/data/footer-navigation.json +0 -38
  227. package/src/assets/data/languages.json +0 -31
  228. package/src/assets/data/multisteps.json +0 -27
  229. package/src/assets/data/navigation.json +0 -47
  230. package/src/assets/data/pager.json +0 -11
  231. package/src/assets/data/top-header-navigation.json +0 -27
  232. package/src/components/CmdFooterNavigation.vue +0 -71
  233. package/src/components/CmdMainHeadline.vue +0 -75
  234. package/src/components/CmdTopHeaderNavigation.vue +0 -88
@@ -1,38 +1,83 @@
1
1
  <template>
2
2
  <label v-if="(element === 'input' || element === 'select' || element === 'textarea')"
3
+ :class="[
4
+ 'cmd-form-element',
5
+ validationStatus,
6
+ {
7
+ disabled: $attrs.disabled,
8
+ inline : displayLabelInline,
9
+ checked: isChecked,
10
+ 'toggle-switch-label': toggleSwitch,
11
+ colored: colored,
12
+ on: colored && isChecked,
13
+ off: colored && !isChecked,
14
+ 'has-state': validationStatus
15
+ }]"
3
16
  :for="id"
4
- :class="['cmd-form-element', status, {'inline' : displayLabelInline, 'checked': isChecked}]"
5
17
  ref="label">
6
- <!-- begin label (+ required) -->
18
+
19
+ <!-- begin label-text (+ required asterisk) -->
7
20
  <span v-if="labelText && $attrs.type !== 'checkbox' && $attrs.type !== 'radio'"
8
- :class="{'hidden': hideLabel}">
9
- <span>{{ labelText }}</span>
10
- <sup v-if="$attrs.required">*</sup>
11
- </span>
12
- <!-- end label (+ required) -->
21
+ :class="!showLabel ? 'hidden' : undefined">
22
+ <span>
23
+ {{ labelText }}<sup v-if="$attrs.required">*</sup>
24
+ </span>
25
+ <a v-if="$attrs.required || inputRequirements.length"
26
+ href="#"
27
+ @click.prevent
28
+ :class="getStatusIconClass"
29
+ :title="validationTooltip"
30
+ :aria-errormessage="getValidationMessage"
31
+ aria-live="assertive"
32
+ :id="tooltipId"
33
+ :role="validationStatus === 'error' ? 'alert' : 'dialog'">
34
+ </a>
35
+ </span>
36
+ <!-- end label-text (+ required asterisk) -->
13
37
 
14
38
  <!-- begin icon -->
15
- <span v-if="$attrs.type !== 'checkbox' && $attrs.type !== 'radio' && innerIconClass" class="place-inside"
16
- :class="[status, innerIconClass]"></span>
39
+ <span
40
+ v-if="
41
+ $attrs.type !== 'checkbox' &&
42
+ $attrs.type !== 'radio' &&
43
+ fieldIconClass
44
+ "
45
+ :class="['place-inside', fieldIconClass]"
46
+ ></span>
17
47
  <!-- end icon -->
18
48
 
19
49
  <!-- begin inputfield -->
20
50
  <template
21
51
  v-if="element === 'input' && $attrs.type !== 'checkbox' && $attrs.type !== 'radio' && $attrs.type !== 'search'">
22
52
  <input v-bind="$attrs"
23
- :id="id" :class="htmlClass"
53
+ :id="id"
54
+ :class="htmlClass"
24
55
  @focus="tooltip = true"
25
- @blur="tooltip = false"
56
+ @blur="onBlur"
26
57
  @input="onInput"
27
58
  @mouseover="datalistFocus"
28
- @change="$emit('change', $event)"
59
+ @keyup="checkForCapsLock"
29
60
  :autocomplete="datalist ? 'off' : 'on'"
30
61
  :list="datalist ? datalist.id : false"
31
- :value="value"
62
+ :value="modelValue"
63
+ :maxlength="$attrs.maxlength > 0 ? $attrs.maxlength : 255"
64
+ ref="input"
32
65
  />
33
66
  </template>
34
67
  <!-- end inputfield -->
35
68
 
69
+ <!-- begin show-password-icon -->
70
+ <a v-if="$attrs.type === 'password'"
71
+ href="#"
72
+ class="place-inside icon-visible"
73
+ @mousedown.prevent="showPassword"
74
+ @mouseup.prevent="hidePassword"
75
+ @mouseleave.prevent="hidePassword"
76
+ @click.prevent
77
+ title="Toggle password visibility">
78
+ </a>
79
+ <!-- end show-password-icon -->
80
+
36
81
  <!-- begin datalist -->
37
82
  <template v-if="datalist && datalist.options.length">
38
83
  <datalist :id="datalist.id">
@@ -45,18 +90,32 @@
45
90
  <template v-else-if="element === 'input' && ($attrs.type === 'checkbox' || $attrs.type === 'radio')">
46
91
  <input v-bind="$attrs"
47
92
  @change="onChange"
93
+ @blur="onBlur"
48
94
  :checked="isChecked"
95
+ :role="$attrs.type"
96
+ :aria-checked="isChecked"
49
97
  :value="inputValue"
50
- :class="[htmlClass, status, { 'replace-input-type': replaceInputType }]"
98
+ :class="[htmlClass, validationStatus, { 'replace-input-type': replaceInputType, 'toggle-switch': toggleSwitch }]"
51
99
  :id="id"
52
- :aria-invalid="status === 'error'"
100
+ :aria-invalid="validationStatus === 'error'"
53
101
  :aria-describedby="`status-message-${id}`"
54
102
  />
55
- <span v-if="labelText">
56
- <span>{{ labelText }}</span>
57
- <sup v-if="$attrs.required">*</sup>
58
- </span>
103
+
104
+ <!-- begin labels for toggle-switch -->
105
+ <span v-if="!(onLabel && offLabel)" :class="{ hidden: !showLabel }">
106
+ <span v-if="labelText">{{ labelText }}<sup v-if="$attrs.required">*</sup></span>
107
+ </span>
108
+ <template v-else-if="onLabel && offLabel">
109
+ <span v-if="labelText">
110
+ <span>{{ labelText }}<sup v-if="$attrs.required">*</sup></span>
111
+ </span>
112
+ <div class="toggle-switch switch-label">
113
+ <span class="label">{{ onLabel }}</span>
114
+ <span class="label">{{ offLabel }}</span>
115
+ </div>
116
+ </template>
59
117
  <slot v-else></slot>
118
+ <!-- end labels for toggle-switch -->
60
119
  </template>
61
120
  <!-- end checkbox and radiobutton -->
62
121
 
@@ -64,10 +123,10 @@
64
123
  <select v-if="element === 'select'"
65
124
  v-bind="$attrs"
66
125
  :id="id"
67
- @change="$emit('input', $event.target.value)"
68
- >
126
+ @blur="onBlur"
127
+ @change="$emit('update:modelValue', $event.target.value)">
69
128
  <option v-for="(option, index) in selectOptions" :key="index" :value="option.value"
70
- :selected="option.value === value">{{ option.text }}
129
+ :selected="option.value === modelValue">{{ option.text }}
71
130
  </option>
72
131
  </select>
73
132
  <!-- end selectbox -->
@@ -76,65 +135,124 @@
76
135
  <textarea v-if="element === 'textarea'"
77
136
  v-bind="$attrs"
78
137
  :id="id"
79
- :value="value"
138
+ :value="modelValue"
139
+ :maxlength="getMaxLength"
80
140
  @input="onInput"
81
141
  @focus="tooltip = true"
82
- @blur="tooltip = false">
142
+ @blur="onBlur">
83
143
  </textarea>
144
+ <span v-if="element === 'textarea' && showCharactersTextarea">{{ charactersTextarea }}</span>
84
145
  <!-- end textarea -->
85
146
 
86
- <!-- begin tooltip -->
87
- <CmdTooltip v-if="tooltip && tooltipText" :tooltipText="tooltipText"/>
88
- <!-- end tooltip -->
89
-
90
147
  <!-- begin searchfield -->
91
- <span v-else-if="element === 'input' && $attrs.type === 'search'" class="flex-container no-gap">
92
- <input v-bind="$attrs" :id="id" @input="onInput" :value="value"/>
93
- <button class="no-flex" type="button">
94
- <span class="icon-search"></span>
95
- </button>
96
- </span>
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
+ />
157
+ <button v-if="showSearchButton" class="no-flex" type="button" :title="iconSearch.tooltip">
158
+ <span :class="iconSearch.iconClass"></span>
159
+ </button>
160
+ </span>
97
161
  <!-- end searchfield -->
98
162
  </label>
99
163
 
100
164
  <!-- begin button -->
101
- <button v-else class="button" v-bind="$attrs">
102
- <span v-if="buttonIcon.iconPosition === 'before'" :class="buttonIcon.iconClass"></span>
103
- <span v-if="buttonIcon.iconPosition">{{ buttonText }}</span>
165
+ <button v-else class="button" v-bind="buttonAttrs">
166
+ <span v-if="nativeButton?.icon?.show && (nativeButton?.icon?.position === 'before' || !nativeButton?.icon?.position)" :class="nativeButton?.icon?.iconClass"></span>
167
+ <span v-if="nativeButton?.icon && nativeButton?.text">{{ nativeButton.text }}</span>
104
168
  <template v-else>
105
- {{ buttonText }}
169
+ {{ nativeButton.text }}
106
170
  </template>
107
- <span v-if="buttonIcon.iconPosition === 'after'" :class="buttonIcon.iconClass"></span>
171
+ <span v-if="nativeButton?.icon?.show && nativeButton?.icon?.position === 'after'" :class="nativeButton?.icon?.iconClass"></span>
108
172
  </button>
109
173
  <!-- end button -->
174
+
175
+ <!-- begin CmdTooltip -->
176
+ <CmdTooltip v-if="useCustomTooltip" class="box" :class="validationStatus" :relatedId="tooltipId" :toggle-visibility-by-click="true">
177
+ <!-- begin CmdSystemMessage -->
178
+ <CmdSystemMessage
179
+ v-if="getValidationMessage"
180
+ :message="getValidationMessage"
181
+ :validation-status="validationStatus"
182
+ :iconClose="{show: false}"
183
+ />
184
+ <!-- end CmdSystemMessage -->
185
+
186
+ <template v-if="showRequirements && (validationStatus === '' || validationStatus === 'error')">
187
+ <!-- begin list of requirements -->
188
+ <h6>
189
+ {{ getMessage("cmdformelement.headline.requirements_for_input") }}<br/>
190
+ "{{ labelText }}"
191
+ </h6>
192
+ <dl class="list-of-requirements">
193
+ <template v-for="(requirement, index) in inputRequirements" :key="index">
194
+ <dt aria-live="assertive" :class="requirement.valid(modelValue, $attrs) ? 'success' : 'error'">{{ requirement.message }}:</dt>
195
+ <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
+ </dd>
199
+ </template>
200
+ </dl>
201
+ <!-- end list of requirements -->
202
+
203
+ <!-- begin helplink -->
204
+ <hr v-if="helplink?.show"/>
205
+ <a v-if="helplink?.show && helplink?.url" :href="helplink.url" :target="helplink.target" @click.prevent>
206
+ <span v-if="helplink.icon?.iconClass" :class="helplink.icon?.iconClass" :title="helplink.icon?.tooltip"></span>
207
+ <span v-if="helplink.text">{{ helplink.text }}</span>
208
+ </a>
209
+ <!-- end helplink -->
210
+ </template>
211
+ </CmdTooltip>
212
+ <!-- end CmdTooltip -->
110
213
  </template>
111
214
 
112
215
  <script>
216
+ // import mixins
217
+ import I18n from "../mixins/I18n"
218
+ import DefaultMessageProperties from "../mixins/CmdBox/DefaultMessageProperties"
219
+ import FieldValidation from "../mixins/FieldValidation.js"
220
+ import Tooltip from "../mixins/Tooltip.js"
221
+
222
+ // import components
223
+ import CmdSystemMessage from "./CmdSystemMessage"
113
224
  import CmdTooltip from "./CmdTooltip"
114
225
 
115
226
  export default {
116
227
  inheritAttrs: false,
117
228
  name: "FormElement",
118
229
  components: {
230
+ CmdSystemMessage,
119
231
  CmdTooltip
120
232
  },
233
+ mixins: [
234
+ I18n,
235
+ DefaultMessageProperties,
236
+ FieldValidation,
237
+ Tooltip
238
+ ],
121
239
  data() {
122
240
  return {
123
- tooltip: false
241
+ errorOccurred: 0
124
242
  }
125
243
  },
126
244
  props: {
127
245
  /**
128
- * set value for v-model
246
+ * set value for v-model (must be names modelValue in vue3)
129
247
  */
130
- value: {
248
+ modelValue: {
131
249
  type: [String, Boolean, Array, Number],
132
250
  default: ""
133
251
  },
134
252
  /**
135
253
  * set type of native form-element
136
254
  *
137
- * values: input, select, textarea, button
255
+ * @allowedValues: input, select, textarea, button
138
256
  */
139
257
  element: {
140
258
  type: String,
@@ -151,9 +269,9 @@ export default {
151
269
  *
152
270
  * label may not be removed, because it is required for accessibility
153
271
  */
154
- hideLabel: {
272
+ showLabel: {
155
273
  type: Boolean,
156
- default: false
274
+ default: true
157
275
  },
158
276
  /**
159
277
  * text for label
@@ -162,6 +280,52 @@ export default {
162
280
  type: String,
163
281
  required: false
164
282
  },
283
+ /**
284
+ * set to activate to use toggle-switch-styling
285
+ *
286
+ * element-prop must be set to "input" and type-attribute must be set to "checkbox" or "radio"
287
+ *
288
+ * @affectsStyling: true
289
+ */
290
+ toggleSwitch: {
291
+ type: Boolean,
292
+ default: false
293
+ },
294
+ /**
295
+ * text for on-label
296
+ *
297
+ * set to activate switch-label (=label is placed on toggle-switch (not behind))
298
+ * toggleSwitch-prop must be set to "true"
299
+ * element-prop must be set to "input" and type-attribute must be set to "checkbox" or "radio"
300
+ */
301
+ onLabel: {
302
+ type: String,
303
+ required: false
304
+ },
305
+ /**
306
+ * text for off-label
307
+ *
308
+ * set to activate switch-label (=label is placed on toggle-switch (not behind))
309
+ * toggleSwitch-prop must be set to "true"
310
+ * element-prop must be set to "input" and type-attribute must be set to "checkbox" or "radio"
311
+ */
312
+ offLabel: {
313
+ type: String,
314
+ required: false
315
+ },
316
+ /**
317
+ * on/off-, yes/no-color-styling
318
+ *
319
+ * set to true, if checkbox/radio-buttons should have green/checked and red/unchecked color-coding
320
+ * toggleSwitch-prop must be set to "true"
321
+ * element-prop must be set to "input" and type-attribute must be set to "checkbox" or "radio"
322
+ *
323
+ * @affectsStyling: true
324
+ */
325
+ colored: {
326
+ type: Boolean,
327
+ required: false
328
+ },
165
329
  /**
166
330
  * allow checkbox/radio-buttons to get value from outside
167
331
  */
@@ -171,6 +335,8 @@ export default {
171
335
  },
172
336
  /**
173
337
  * for replacing native checkboxes/radio-buttons by custom ones (based on frontend-framework)
338
+ *
339
+ * @affectsStyling: true
174
340
  */
175
341
  replaceInputType: {
176
342
  type: Boolean,
@@ -209,19 +375,20 @@ export default {
209
375
  required: false
210
376
  },
211
377
  /**
212
- * text for native button
213
- */
214
- buttonText: {
215
- type: String,
216
- required: false
217
- },
218
- /**
219
- * set icon for native button
378
+ * native button
220
379
  */
221
- buttonIcon: {
380
+ nativeButton: {
222
381
  type: Object,
223
382
  default() {
224
- return {}
383
+ return {
384
+ text: "",
385
+ icon: {
386
+ show: true,
387
+ iconClass: "",
388
+ position: "left",
389
+ tooltip: ""
390
+ }
391
+ }
225
392
  }
226
393
  },
227
394
  /**
@@ -236,7 +403,7 @@ export default {
236
403
  *
237
404
  * element-property must be 'input' and type-property may not be checkbox or radio
238
405
  */
239
- innerIconClass: {
406
+ fieldIconClass: {
240
407
  type: String,
241
408
  required: false
242
409
  },
@@ -245,51 +412,174 @@ export default {
245
412
  *
246
413
  * type-property may not be checkbox or radio
247
414
  */
248
- displayLabelInline: {
415
+ displayLabelInline: {
249
416
  type: Boolean,
250
417
  required: false
251
418
  },
252
419
  /**
253
420
  * set status for label and form-element
254
421
  *
255
- * values: error (red-styling), success (green-styling)
422
+ * @allowedValues: error, success
423
+ *
424
+ * @affectsStyling: true
256
425
  */
257
426
  status: {
258
427
  type: String,
259
428
  required: false
429
+ },
430
+ /**
431
+ * toggle display of number of used and allowed characters for textarea
432
+ *
433
+ * type-property must be set to textarea
434
+ */
435
+ showCharactersTextarea: {
436
+ type: Boolean,
437
+ default: true
438
+ },
439
+ /**
440
+ * toggle visibility of search-button (next to search-field)
441
+ */
442
+ showSearchButton: {
443
+ type: Boolean,
444
+ default: true
445
+ },
446
+ /**
447
+ * icon to delete search term
448
+ *
449
+ * element-property must me set to 'input'
450
+ * type-property must be set to 'search'
451
+ *
452
+ */
453
+ iconDelete: {
454
+ type: Object,
455
+ default() {
456
+ return {
457
+ show: true,
458
+ iconClass: "icon-cancel-circle",
459
+ tooltip: "Delete term"
460
+ }
461
+ }
462
+ },
463
+ /**
464
+ * icon to search term
465
+ *
466
+ * element-property must me set to 'input'
467
+ * type-property must be set to 'search'
468
+ *
469
+ */
470
+ iconSearch: {
471
+ type: Object,
472
+ default() {
473
+ return {
474
+ show: true,
475
+ iconClass: "icon-search",
476
+ tooltip: "Search"
477
+ }
478
+ }
260
479
  }
261
480
  },
262
481
  computed: {
482
+ buttonAttrs() {
483
+ // copy all native attributes
484
+ const allAttrs = {...this.$attrs}
485
+
486
+ // check if specific tooltip for icon is set (and add as title-attribute)
487
+ if (this.nativeButton.icon?.tooltip) {
488
+ allAttrs.title = this.nativeButton.icon?.tooltip
489
+ }
490
+
491
+ return allAttrs
492
+ },
493
+ tooltipHeadline() {
494
+ return {
495
+ text: this.labelText,
496
+ level: "5"
497
+ }
498
+ },
263
499
  isChecked() {
264
- if (typeof this.value === "boolean") {
265
- return this.value
500
+ if (typeof this.modelValue === "boolean") {
501
+ return this.modelValue
266
502
  }
267
- if (typeof this.value === "string") {
268
- return this.value === this.inputValue
503
+ if (typeof this.modelValue === "string") {
504
+ return this.modelValue === this.inputValue
269
505
  }
270
- if (typeof this.value === "number") {
271
- return this.value === this.inputValue
506
+ if (typeof this.modelValue === "number") {
507
+ return this.modelValue === this.inputValue
272
508
  }
273
- if (this.value !== undefined) {
274
- return this.value.includes(this.inputValue)
509
+ if (this.modelValue !== undefined) {
510
+ return this.modelValue.includes(this.inputValue)
275
511
  }
276
512
  return false
513
+ },
514
+ charactersTextarea() {
515
+ return "Characters: " + this.modelValue.length + "/" + this.getMaxLength()
516
+ },
517
+ validationTooltip() {
518
+ if (!this.useCustomTooltip) {
519
+ return this.getValidationMessage
520
+ }
521
+
522
+ // set default-tooltip if customTooltip is not set
523
+ if (this.validationStatus === 'error') {
524
+ return "An error occurred!"
525
+ } else if (this.validationStatus === 'success') {
526
+ return "This information is filled correctly!"
527
+ } else if (this.capsLockActivated) {
528
+ return "Attention: Caps lock is activated!"
529
+ }
530
+ return "Open field requirements!"
277
531
  }
278
532
  },
279
533
  methods: {
280
- onChange(e) {
281
- if (typeof this.value === "boolean") {
282
- this.$emit("update:value", e.target.checked)
283
- } else if (typeof this.value === "string") {
284
- this.$emit("update:value", e.target.value)
285
- } else if (this.value !== undefined) {
286
- let values = [...this.value]
287
- if (e.target.checked) {
288
- values.push(e.target.value)
534
+ getDomElement() {
535
+ return this.$refs.label
536
+ },
537
+ getMaxLength() {
538
+ return this.$attrs.maxlength > 0 ? this.$attrs.maxlength : 5000
539
+ },
540
+ onBlur(event) {
541
+ // check if surrounding form with data-use-validation exists
542
+ const useValidation = event.target.closest("form")?.dataset.useValidation === "true"
543
+
544
+ if (useValidation) {
545
+ this.tooltip = false
546
+ this.validationStatus = ""
547
+
548
+ // if input is filled, set status to success (expect for checkboxes and radiobuttons)
549
+ if (!["checkbox", "radio"].includes(this.$attrs.type) && this.modelValue) {
550
+ this.validationStatus = "success"
551
+ }
552
+
553
+ if (typeof event.target.checkValidity === "function" && !event.target.checkValidity()) {
554
+ this.validationStatus = "error"
555
+ } else {
556
+ if (this.customRequirements) {
557
+ // check if customRequirement returns invalid result
558
+ const invalidCustomRequirement = this.customRequirements.some(requirement => {
559
+ return !requirement.valid(this.modelValue)
560
+ })
561
+
562
+ // set validation-status if invalidCustomRequirement returns at least one invalid entry
563
+ if (invalidCustomRequirement) {
564
+ this.validationStatus = "error"
565
+ }
566
+ }
567
+ }
568
+ }
569
+ },
570
+ onChange(event) {
571
+ if (typeof this.modelValue === "boolean") {
572
+ this.$emit("update:modelValue", event.target.checked)
573
+ } else if (typeof this.modelValue === "string") {
574
+ this.$emit("update:modelValue", event.target.value)
575
+ } else if (this.modelValue !== undefined) {
576
+ let values = [...this.modelValue]
577
+ if (event.target.checked) {
578
+ values.push(event.target.value)
289
579
  } else {
290
- values = values.filter(value => value !== e.target.value)
580
+ values = values.filter(value => value !== event.target.value)
291
581
  }
292
- this.$emit("update:value", values)
582
+ this.$emit("update:modelValue", values)
293
583
  }
294
584
  },
295
585
  datalistFocus() {
@@ -298,9 +588,168 @@ export default {
298
588
  this.$refs.label.focus()
299
589
  }
300
590
  },
301
- onInput(e) {
302
- this.$emit('update:value', e.target.value)
591
+ onInput(event) {
592
+ this.$emit('update:modelValue', event.target.value)
593
+ },
594
+ showPassword() {
595
+ // get password-field
596
+ const passwordField = this.$refs.input
597
+
598
+ // get value of password field (to save it temporary)
599
+ const password = passwordField.value
600
+
601
+ // toggle input-type to make password visible
602
+ passwordField.nextElementSibling.classList.replace("icon-visible", "icon-not-visible")
603
+ passwordField.setAttribute("type", "text")
604
+
605
+ // assign saved password back to field
606
+ passwordField.setAttribute("value", password)
607
+ },
608
+ hidePassword() {
609
+ this.$refs.input.nextElementSibling.classList.replace("icon-not-visible", "icon-visible")
610
+ this.$refs.input.setAttribute("type", "password")
611
+ }
612
+ },
613
+ watch: {
614
+ status: {
615
+ handler() {
616
+ this.validationStatus = this.status
617
+ },
618
+ immediate: true
303
619
  }
304
620
  }
305
621
  }
306
622
  </script>
623
+
624
+ <style lang="scss">
625
+ .cmd-form-element {
626
+ input + .place-inside[class*="icon"] {
627
+ left: auto;
628
+ right: .5rem
629
+ }
630
+
631
+ &.has-state, & + .cmd-tooltip {
632
+ &.error {
633
+ --status-color: var(--error-color);
634
+ }
635
+
636
+ &.warning {
637
+ --status-color: var(--warning-color);
638
+ }
639
+
640
+ &.success {
641
+ --status-color: var(--success-color);
642
+ }
643
+
644
+ &.info {
645
+ --status-color: var(--info-color);
646
+ }
647
+
648
+ ::placeholder {
649
+ color: var(--status-color);
650
+ }
651
+
652
+ > span {
653
+ color: var(--status-color);
654
+
655
+ &[class*="icon-"].place-inside {
656
+ color: var(--status-color);
657
+ }
658
+ }
659
+ }
660
+
661
+ & + .cmd-tooltip {
662
+ border-color: var(--status-color);
663
+ }
664
+
665
+ &.inline {
666
+ & > span {
667
+ & > a {
668
+ margin-left: calc(var(--default-margin) / 2);
669
+ }
670
+ }
671
+ }
672
+
673
+ .search-field-wrapper {
674
+ margin: 0;
675
+ }
676
+
677
+ .place-inside {
678
+ + .search-field-wrapper {
679
+ a {
680
+ position: absolute;
681
+ top: 50%;
682
+ right: 1rem;
683
+ transform: translateY(-50%);
684
+ z-index: 100;
685
+
686
+ & + input {
687
+ padding-right: calc(var(--default-padding) * 3);
688
+ }
689
+ }
690
+
691
+ input {
692
+ padding-left: calc(var(--default-padding) * 3);
693
+ }
694
+ }
695
+ }
696
+
697
+ /* begin toggle-switch */
698
+ /* no cmd-prefix-styling (class based on frontend-framework */
699
+ &.toggle-switch {
700
+ &.switch-label {
701
+ input {
702
+ & + .label {
703
+ padding-right: calc(var(--default-padding) / 3 * 2);
704
+
705
+ &::before {
706
+ top: 0.2rem;
707
+ }
708
+
709
+ & + .label {
710
+ padding-left: calc(var(--default-padding) / 3 * 2);
711
+
712
+ &::before {
713
+ top: 0.2rem;
714
+ }
715
+ }
716
+ }
717
+ }
718
+
719
+ &.colored {
720
+ &.off {
721
+ border-color: var(--error-color);
722
+
723
+ span {
724
+ &.label {
725
+ color: var(--error-color);
726
+
727
+ &::before {
728
+ border-color: var(--error-color);
729
+ background-color: var(--pure-white);
730
+ }
731
+ }
732
+ }
733
+ }
734
+
735
+ &.on {
736
+ border-color: var(--success-color);
737
+
738
+ span {
739
+ &.label {
740
+ color: var(--success-color);
741
+
742
+ &::before {
743
+ border-color: var(--success-color);
744
+ background-color: var(--success-color);
745
+ }
746
+ }
747
+ }
748
+ }
749
+ }
750
+ }
751
+ }
752
+
753
+ /* end toggle-switch ------------------------------------------------------------------------------------------ */
754
+ }
755
+ </style>