@mirweb/mir-web-components 1.15.2 → 2.0.0

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 (184) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/index-Cl4fzBs2.js +17 -0
  3. package/dist/assets/scss/globals.scss +231 -0
  4. package/dist/assets/scss/index.scss +4 -0
  5. package/dist/assets/scss/normalize.scss +393 -0
  6. package/dist/assets/scss/reset.scss +102 -0
  7. package/dist/assets/scss/variables.scss +95 -0
  8. package/dist/components/atoms/button/button.vue +81 -0
  9. package/dist/components/atoms/checkbox/checkbox.vue +125 -0
  10. package/dist/components/atoms/chip/chip.vue +55 -0
  11. package/dist/components/atoms/dropdown/dropdown.vue +490 -0
  12. package/dist/components/atoms/image/image.vue +42 -0
  13. package/dist/components/atoms/label/label.vue +52 -0
  14. package/dist/components/atoms/link/link.vue +166 -0
  15. package/dist/components/atoms/radio-button/radio-button.vue +110 -0
  16. package/dist/components/atoms/select/select.vue +116 -0
  17. package/dist/components/atoms/select-multiple/select-multiple.vue +210 -0
  18. package/dist/components/atoms/slider/slider.vue +322 -0
  19. package/dist/components/atoms/text-field/text-field.vue +273 -0
  20. package/dist/components/atoms/textarea/textarea.vue +179 -0
  21. package/dist/components/atoms/video/video.vue +98 -0
  22. package/dist/components/blocks/accordion/accordion.vue +222 -0
  23. package/dist/components/blocks/card-display/card-display.vue +125 -0
  24. package/dist/components/blocks/column-grid/column-grid.vue +201 -0
  25. package/dist/components/blocks/facts/facts.vue +156 -0
  26. package/dist/components/blocks/features/features.vue +176 -0
  27. package/dist/components/blocks/flashcards/flashcards.vue +212 -0
  28. package/dist/components/blocks/form-script/form-script.vue +172 -0
  29. package/dist/components/blocks/frontpage-hero/frontpage-hero.vue +214 -0
  30. package/dist/components/blocks/headline/headline.vue +93 -0
  31. package/dist/components/blocks/hero/hero.vue +173 -0
  32. package/dist/components/blocks/image/image.vue +93 -0
  33. package/dist/components/blocks/image-gallery/image-gallery.vue +289 -0
  34. package/dist/components/blocks/logo-wall/logo-wall.vue +125 -0
  35. package/dist/components/blocks/micro-stories/micro-stories.vue +316 -0
  36. package/dist/components/blocks/pallet-jack/pallet-jack.vue +440 -0
  37. package/dist/components/blocks/policy/policy.vue +106 -0
  38. package/dist/components/blocks/product-hero/product-hero.vue +140 -0
  39. package/dist/components/blocks/promo/promo.vue +403 -0
  40. package/dist/components/blocks/quote/quote.vue +127 -0
  41. package/dist/components/blocks/rich-text/rich-text-columns.vue +159 -0
  42. package/dist/components/blocks/rich-text/rich-text.vue +296 -0
  43. package/dist/components/blocks/timeline/timeline.vue +232 -0
  44. package/dist/components/blocks/vimeo/vimeo.vue +52 -0
  45. package/dist/components/index.ts +51 -0
  46. package/dist/components/molecules/address/address.vue +123 -0
  47. package/dist/components/molecules/bullet-list/bullet-list.vue +99 -0
  48. package/dist/components/molecules/card/card.vue +302 -0
  49. package/dist/components/molecules/column-card/column-card.vue +178 -0
  50. package/dist/components/molecules/event-card/event-card.vue +111 -0
  51. package/dist/components/molecules/flashcard/flashcard.vue +293 -0
  52. package/dist/components/molecules/modal/modal.vue +113 -0
  53. package/dist/components/molecules/text-card/text-card.vue +74 -0
  54. package/dist/components/organisms/404/404.vue +79 -0
  55. package/dist/components/organisms/filter/filter.vue +89 -0
  56. package/dist/components/organisms/footer/footer.vue +356 -0
  57. package/dist/components/organisms/header/header.vue +754 -0
  58. package/dist/components/organisms/language-switcher/language-switcher.vue +68 -0
  59. package/dist/components/organisms/pagination/pagination.vue +85 -0
  60. package/dist/components/organisms/search/search.vue +153 -0
  61. package/dist/components/templates/404-error-page.vue +0 -0
  62. package/dist/directives/clickOutside.ts +15 -0
  63. package/dist/fonts/OpenSans-Light.woff2 +0 -0
  64. package/dist/fonts/OpenSans-Medium.woff2 +0 -0
  65. package/dist/fonts/OpenSans-Regular.woff2 +0 -0
  66. package/dist/fonts/OpenSans-SemiBold.woff2 +0 -0
  67. package/dist/fonts/Oscine_Bd.woff2 +0 -0
  68. package/dist/fonts/Oscine_Lt.woff2 +0 -0
  69. package/dist/fonts/Oscine_Rg.woff2 +0 -0
  70. package/dist/index.html +12 -0
  71. package/dist/main.css +1 -0
  72. package/package.json +8 -10
  73. package/dist/components/atoms/button/button.vue.d.ts +0 -5
  74. package/dist/components/atoms/button/button.vue.d.ts.map +0 -1
  75. package/dist/components/atoms/checkbox/checkbox.vue.d.ts +0 -5
  76. package/dist/components/atoms/checkbox/checkbox.vue.d.ts.map +0 -1
  77. package/dist/components/atoms/chip/chip.vue.d.ts +0 -5
  78. package/dist/components/atoms/chip/chip.vue.d.ts.map +0 -1
  79. package/dist/components/atoms/dropdown/dropdown.vue.d.ts +0 -5
  80. package/dist/components/atoms/dropdown/dropdown.vue.d.ts.map +0 -1
  81. package/dist/components/atoms/image/image.vue.d.ts +0 -5
  82. package/dist/components/atoms/image/image.vue.d.ts.map +0 -1
  83. package/dist/components/atoms/label/label.vue.d.ts +0 -5
  84. package/dist/components/atoms/label/label.vue.d.ts.map +0 -1
  85. package/dist/components/atoms/link/link.vue.d.ts +0 -5
  86. package/dist/components/atoms/link/link.vue.d.ts.map +0 -1
  87. package/dist/components/atoms/radio-button/radio-button.vue.d.ts +0 -5
  88. package/dist/components/atoms/radio-button/radio-button.vue.d.ts.map +0 -1
  89. package/dist/components/atoms/select/select.vue.d.ts +0 -5
  90. package/dist/components/atoms/select/select.vue.d.ts.map +0 -1
  91. package/dist/components/atoms/select-multiple/select-multiple.vue.d.ts +0 -5
  92. package/dist/components/atoms/select-multiple/select-multiple.vue.d.ts.map +0 -1
  93. package/dist/components/atoms/slider/slider.vue.d.ts +0 -5
  94. package/dist/components/atoms/slider/slider.vue.d.ts.map +0 -1
  95. package/dist/components/atoms/text-field/text-field.vue.d.ts +0 -5
  96. package/dist/components/atoms/text-field/text-field.vue.d.ts.map +0 -1
  97. package/dist/components/atoms/textarea/textarea.vue.d.ts +0 -5
  98. package/dist/components/atoms/textarea/textarea.vue.d.ts.map +0 -1
  99. package/dist/components/atoms/video/video.vue.d.ts +0 -5
  100. package/dist/components/atoms/video/video.vue.d.ts.map +0 -1
  101. package/dist/components/blocks/accordion/accordion.vue.d.ts +0 -5
  102. package/dist/components/blocks/accordion/accordion.vue.d.ts.map +0 -1
  103. package/dist/components/blocks/card-display/card-display.vue.d.ts +0 -6
  104. package/dist/components/blocks/card-display/card-display.vue.d.ts.map +0 -1
  105. package/dist/components/blocks/column-grid/column-grid.vue.d.ts +0 -5
  106. package/dist/components/blocks/column-grid/column-grid.vue.d.ts.map +0 -1
  107. package/dist/components/blocks/facts/facts.vue.d.ts +0 -5
  108. package/dist/components/blocks/facts/facts.vue.d.ts.map +0 -1
  109. package/dist/components/blocks/features/features.vue.d.ts +0 -5
  110. package/dist/components/blocks/features/features.vue.d.ts.map +0 -1
  111. package/dist/components/blocks/flashcards/flashcards.vue.d.ts +0 -5
  112. package/dist/components/blocks/flashcards/flashcards.vue.d.ts.map +0 -1
  113. package/dist/components/blocks/form-script/form-script.vue.d.ts +0 -5
  114. package/dist/components/blocks/form-script/form-script.vue.d.ts.map +0 -1
  115. package/dist/components/blocks/frontpage-hero/frontpage-hero.vue.d.ts +0 -5
  116. package/dist/components/blocks/frontpage-hero/frontpage-hero.vue.d.ts.map +0 -1
  117. package/dist/components/blocks/headline/headline.vue.d.ts +0 -5
  118. package/dist/components/blocks/headline/headline.vue.d.ts.map +0 -1
  119. package/dist/components/blocks/hero/hero.vue.d.ts +0 -5
  120. package/dist/components/blocks/hero/hero.vue.d.ts.map +0 -1
  121. package/dist/components/blocks/image/image.vue.d.ts +0 -5
  122. package/dist/components/blocks/image/image.vue.d.ts.map +0 -1
  123. package/dist/components/blocks/image-gallery/image-gallery.vue.d.ts +0 -5
  124. package/dist/components/blocks/image-gallery/image-gallery.vue.d.ts.map +0 -1
  125. package/dist/components/blocks/logo-wall/logo-wall.vue.d.ts +0 -5
  126. package/dist/components/blocks/logo-wall/logo-wall.vue.d.ts.map +0 -1
  127. package/dist/components/blocks/micro-stories/micro-stories.vue.d.ts +0 -5
  128. package/dist/components/blocks/micro-stories/micro-stories.vue.d.ts.map +0 -1
  129. package/dist/components/blocks/pallet-jack/pallet-jack.vue.d.ts +0 -5
  130. package/dist/components/blocks/pallet-jack/pallet-jack.vue.d.ts.map +0 -1
  131. package/dist/components/blocks/policy/policy.vue.d.ts +0 -4
  132. package/dist/components/blocks/policy/policy.vue.d.ts.map +0 -1
  133. package/dist/components/blocks/product-hero/product-hero.vue.d.ts +0 -5
  134. package/dist/components/blocks/product-hero/product-hero.vue.d.ts.map +0 -1
  135. package/dist/components/blocks/promo/promo.vue.d.ts +0 -5
  136. package/dist/components/blocks/promo/promo.vue.d.ts.map +0 -1
  137. package/dist/components/blocks/quote/quote.vue.d.ts +0 -5
  138. package/dist/components/blocks/quote/quote.vue.d.ts.map +0 -1
  139. package/dist/components/blocks/rich-text/rich-text-columns.vue.d.ts +0 -4
  140. package/dist/components/blocks/rich-text/rich-text-columns.vue.d.ts.map +0 -1
  141. package/dist/components/blocks/rich-text/rich-text.vue.d.ts +0 -5
  142. package/dist/components/blocks/rich-text/rich-text.vue.d.ts.map +0 -1
  143. package/dist/components/blocks/timeline/timeline.vue.d.ts +0 -5
  144. package/dist/components/blocks/timeline/timeline.vue.d.ts.map +0 -1
  145. package/dist/components/blocks/vimeo/vimeo.vue.d.ts +0 -5
  146. package/dist/components/blocks/vimeo/vimeo.vue.d.ts.map +0 -1
  147. package/dist/components/index.d.ts +0 -51
  148. package/dist/components/main.d.ts +0 -59
  149. package/dist/components/molecules/address/address.vue.d.ts +0 -5
  150. package/dist/components/molecules/address/address.vue.d.ts.map +0 -1
  151. package/dist/components/molecules/bullet-list/bullet-list.vue.d.ts +0 -5
  152. package/dist/components/molecules/bullet-list/bullet-list.vue.d.ts.map +0 -1
  153. package/dist/components/molecules/card/card.vue.d.ts +0 -5
  154. package/dist/components/molecules/card/card.vue.d.ts.map +0 -1
  155. package/dist/components/molecules/column-card/column-card.vue.d.ts +0 -5
  156. package/dist/components/molecules/column-card/column-card.vue.d.ts.map +0 -1
  157. package/dist/components/molecules/event-card/event-card.vue.d.ts +0 -5
  158. package/dist/components/molecules/event-card/event-card.vue.d.ts.map +0 -1
  159. package/dist/components/molecules/flashcard/flashcard.vue.d.ts +0 -5
  160. package/dist/components/molecules/flashcard/flashcard.vue.d.ts.map +0 -1
  161. package/dist/components/molecules/modal/modal.vue.d.ts +0 -5
  162. package/dist/components/molecules/modal/modal.vue.d.ts.map +0 -1
  163. package/dist/components/molecules/text-card/text-card.vue.d.ts +0 -5
  164. package/dist/components/molecules/text-card/text-card.vue.d.ts.map +0 -1
  165. package/dist/components/organisms/404/404.vue.d.ts +0 -5
  166. package/dist/components/organisms/404/404.vue.d.ts.map +0 -1
  167. package/dist/components/organisms/filter/filter.vue.d.ts +0 -5
  168. package/dist/components/organisms/filter/filter.vue.d.ts.map +0 -1
  169. package/dist/components/organisms/footer/footer.vue.d.ts +0 -5
  170. package/dist/components/organisms/footer/footer.vue.d.ts.map +0 -1
  171. package/dist/components/organisms/header/header.vue.d.ts +0 -6
  172. package/dist/components/organisms/header/header.vue.d.ts.map +0 -1
  173. package/dist/components/organisms/language-switcher/language-switcher.vue.d.ts +0 -5
  174. package/dist/components/organisms/language-switcher/language-switcher.vue.d.ts.map +0 -1
  175. package/dist/components/organisms/pagination/pagination.vue.d.ts +0 -5
  176. package/dist/components/organisms/pagination/pagination.vue.d.ts.map +0 -1
  177. package/dist/components/organisms/search/search.vue.d.ts +0 -4
  178. package/dist/components/organisms/search/search.vue.d.ts.map +0 -1
  179. package/dist/directives/clickOutside.d.ts +0 -4
  180. package/dist/main.d.ts +0 -1
  181. package/dist/mir-web-components.cjs.js +0 -1
  182. package/dist/mir-web-components.css +0 -1
  183. package/dist/mir-web-components.es.js +0 -3184
  184. package/dist/mir-web-components.umd.js +0 -2
@@ -0,0 +1,322 @@
1
+ <template>
2
+ <div>
3
+ <div class="slider__wrapper">
4
+ <div class="slider__label">
5
+ <label :for="id" :class="[variant, '']">{{ label }}</label
6
+ ><i
7
+ v-if="information"
8
+ role="button"
9
+ :class="[variant, 'slider__information']"
10
+ :aria-label="informationLabel"
11
+ tabindex="0"
12
+ aria-haspopup="dialog"
13
+ @click="showModal = !showModal"
14
+ @keyup.enter="showModal = !showModal"
15
+ ></i>
16
+ </div>
17
+
18
+ <div class="slider__content">
19
+ <span :class="[variant, 'slider__minmax']">{{ min }}</span>
20
+ <input
21
+ :id="id"
22
+ ref="slider"
23
+ type="range"
24
+ :name="name"
25
+ :value="modelValue"
26
+ :min="min"
27
+ :step="step"
28
+ :max="max"
29
+ :class="variant"
30
+ @input="
31
+ ({ target }) =>
32
+ (sliderValue = parseFloat((target as HTMLInputElement).value))
33
+ "
34
+ />
35
+ <span :class="[variant, 'slider__minmax']">{{ max }}</span>
36
+ </div>
37
+ <span :class="[variant, 'slider__value']">{{ modelValue }}</span>
38
+ </div>
39
+ <molecule-modal
40
+ v-if="information"
41
+ :show="showModal"
42
+ @update:show="showModal = $event"
43
+ >
44
+ <p class="modal-information">{{ information }}</p>
45
+ </molecule-modal>
46
+ </div>
47
+ </template>
48
+
49
+ <script setup lang="ts">
50
+ import { ref, watchEffect } from "vue";
51
+ import MoleculeModal from "../../molecules/modal/modal.vue";
52
+
53
+ const VARIANTS = { light: "light", dark: "dark" } as const;
54
+
55
+ type Variant = keyof typeof VARIANTS;
56
+
57
+ export type Props = {
58
+ label: string;
59
+ id: string;
60
+ name: string;
61
+ modelValue: number;
62
+ min: number;
63
+ max: number;
64
+ step: string;
65
+ variant: Variant;
66
+ information: string;
67
+ informationLabel: string;
68
+ };
69
+
70
+ const props = withDefaults(defineProps<Props>(), {
71
+ step: "1",
72
+ variant: "light",
73
+ information: "",
74
+ informationLabel: "Additional information",
75
+ });
76
+
77
+ const emit = defineEmits(["update:modelValue"]);
78
+ const sliderValue = ref(props.modelValue);
79
+ const slider = ref<HTMLInputElement>();
80
+ const showModal = ref(false);
81
+ const getProgress = (value: number, min: number, max: number) => {
82
+ return ((value - min) / (max - min)) * 100;
83
+ };
84
+
85
+ const setCSSProgress = (progress: number) => {
86
+ slider.value?.style.setProperty("--ProgressPercent", `${progress}%`);
87
+ };
88
+
89
+ watchEffect(() => {
90
+ if (slider.value) {
91
+ emit("update:modelValue", sliderValue.value);
92
+ const progress = getProgress(sliderValue.value, props.min, props.max);
93
+ let extraWidth = (50 - progress) / 100;
94
+ setCSSProgress(progress + extraWidth);
95
+ }
96
+ });
97
+ </script>
98
+
99
+ <style scoped lang="scss">
100
+ @use "../../../assets/scss/variables.scss" as *;
101
+ .slider {
102
+ &__wrapper {
103
+ display: flex;
104
+ flex-direction: column;
105
+ align-items: center;
106
+ justify-content: center;
107
+ width: 100%;
108
+ }
109
+
110
+ &__label {
111
+ font-size: $font-size-xsm;
112
+ margin-bottom: 7px;
113
+ display: flex;
114
+
115
+ label {
116
+ font-weight: 300;
117
+ }
118
+ }
119
+
120
+ &__information {
121
+ cursor: pointer;
122
+ background-repeat: no-repeat;
123
+ background-position: center;
124
+ background-size: contain;
125
+ height: 21px;
126
+ width: 21px;
127
+ margin-left: 7px;
128
+
129
+ &.light {
130
+ background-image: url("https://a.storyblok.com/f/230581/22x22/31d1e5f857/info-dark-blue.svg?cv=1695125825975");
131
+ &:hover,
132
+ &:focus,
133
+ &:active,
134
+ &:target {
135
+ background-image: url("https://a.storyblok.com/f/230581/22x22/00b84adecf/info-blue.svg?cv=1695125825586");
136
+ transition: $transition-color;
137
+ }
138
+ }
139
+
140
+ &.dark {
141
+ background-image: url("https://a.storyblok.com/f/230581/22x22/a1d6e51695/info-white.svg?cv=1695125825722");
142
+ &:hover,
143
+ &:focus,
144
+ &:active,
145
+ &:target {
146
+ background-image: url("https://a.storyblok.com/f/230581/22x22/00b84adecf/info-blue.svg?cv=1695125825586");
147
+ transition: $transition-color;
148
+ }
149
+ }
150
+ }
151
+
152
+ &__minmax {
153
+ font-family: $font-opensans;
154
+ font-size: $font-size-xsm;
155
+ font-weight: 300;
156
+ width: 24px;
157
+
158
+ &:first-child {
159
+ margin-right: 10px;
160
+ text-align: right;
161
+ }
162
+
163
+ &:last-child {
164
+ margin-left: 10px;
165
+ text-align: left;
166
+ }
167
+ }
168
+
169
+ &__content {
170
+ --trackHeight: 3px;
171
+ align-items: center;
172
+ justify-content: center;
173
+ display: flex;
174
+ width: 100%;
175
+
176
+ input[type="range"] {
177
+ position: relative;
178
+ appearance: none;
179
+ cursor: pointer;
180
+ border-radius: 999px;
181
+ z-index: 0;
182
+ width: 100%;
183
+
184
+ &::before {
185
+ content: "";
186
+ position: absolute;
187
+ width: var(--ProgressPercent, 100%);
188
+ height: 100%;
189
+ pointer-events: none;
190
+ border-radius: 999px;
191
+ }
192
+
193
+ &::-webkit-slider-runnable-track {
194
+ appearance: none;
195
+ height: var(--trackHeight);
196
+ border-radius: 999px;
197
+ }
198
+
199
+ &::-moz-range-track {
200
+ appearance: none;
201
+ height: var(--trackHeight);
202
+ border-radius: 999px;
203
+ }
204
+
205
+ &::-webkit-slider-thumb {
206
+ position: relative;
207
+ top: 50%;
208
+ transform: translate(0, -50%);
209
+ width: 15px;
210
+ height: 15px;
211
+ border-radius: 999px;
212
+ pointer-events: all;
213
+ appearance: none;
214
+ z-index: 1;
215
+ transition:
216
+ width 0.15s ease,
217
+ height 0.15s ease;
218
+ }
219
+
220
+ &::-moz-range-thumb {
221
+ position: relative;
222
+ width: 15px;
223
+ height: 15px;
224
+ border: none;
225
+ border-radius: 999px;
226
+ pointer-events: all;
227
+ appearance: none;
228
+ z-index: 1;
229
+ transition:
230
+ width 0.15s ease,
231
+ height 0.15s ease;
232
+ }
233
+
234
+ &:hover,
235
+ &:focus,
236
+ &:active,
237
+ &:target {
238
+ &::-webkit-slider-thumb {
239
+ width: 20px;
240
+ height: 20px;
241
+ transition:
242
+ width 0.15s ease,
243
+ height 0.15s ease;
244
+ }
245
+ &::-moz-range-thumb {
246
+ width: 20px;
247
+ height: 20px;
248
+ transition:
249
+ width 0.15s ease,
250
+ height 0.15s ease;
251
+ }
252
+ }
253
+ }
254
+ }
255
+
256
+ &__value {
257
+ font-family: $font-opensans;
258
+ font-size: $font-size-xsm;
259
+ font-weight: 700;
260
+ }
261
+ }
262
+
263
+ .light {
264
+ color: $blue-900;
265
+
266
+ &::before {
267
+ background: $blue-900;
268
+ }
269
+
270
+ &::-webkit-slider-runnable-track {
271
+ background: $blue-200;
272
+ }
273
+
274
+ &::-moz-range-track {
275
+ background: $blue-200;
276
+ }
277
+
278
+ &::-moz-range-progress {
279
+ background: $blue-900;
280
+ }
281
+
282
+ &::-webkit-slider-thumb {
283
+ background: $blue-900;
284
+ }
285
+
286
+ &::-moz-range-thumb {
287
+ background: $blue-900;
288
+ }
289
+ }
290
+
291
+ .dark {
292
+ color: $white;
293
+
294
+ &::before {
295
+ background: $white;
296
+ }
297
+
298
+ &::-webkit-slider-runnable-track {
299
+ background: $blue-600;
300
+ }
301
+
302
+ &::-moz-range-track {
303
+ background: $blue-600;
304
+ }
305
+
306
+ &::-moz-range-progress {
307
+ background: $white;
308
+ }
309
+
310
+ &::-webkit-slider-thumb {
311
+ background: $white;
312
+ }
313
+
314
+ &::-moz-range-thumb {
315
+ background: $white;
316
+ }
317
+ }
318
+ .modal-information {
319
+ padding: 15px;
320
+ font-family: $font-opensans;
321
+ }
322
+ </style>
@@ -0,0 +1,273 @@
1
+ <template>
2
+ <div class="text-field__wrapper">
3
+ <label
4
+ :for="id"
5
+ :class="[
6
+ required ? 'required' : '',
7
+ disabled ? 'disabled' : '',
8
+ search ? 'search' : '',
9
+ ]"
10
+ >{{ label }}</label
11
+ >
12
+ <div v-if="selectedType === 'password'">
13
+ <input
14
+ :id="id"
15
+ ref="passwordField"
16
+ :type="passwordFieldType"
17
+ :value="modelValue"
18
+ :placeholder="placeholder"
19
+ :required="required"
20
+ :disabled="disabled"
21
+ :name="fieldName"
22
+ @input="
23
+ $emit('update:modelValue', ($event.target as HTMLInputElement).value)
24
+ "
25
+ />
26
+ <i
27
+ role="button"
28
+ :class="[passwordFieldIcon]"
29
+ aria-controls="password"
30
+ :aria-expanded="!hidePassword"
31
+ @click="hidePassword = !hidePassword"
32
+ ></i>
33
+ </div>
34
+ <input
35
+ v-else
36
+ :id="id"
37
+ ref="textField"
38
+ :type="selectedType"
39
+ :value="modelValue"
40
+ :placeholder="placeholder"
41
+ :required="required"
42
+ :class="[
43
+ invalid ? 'invalid' : '',
44
+ valid ? 'valid' : '',
45
+ search ? 'search' : '',
46
+ ]"
47
+ :disabled="disabled"
48
+ :name="fieldName"
49
+ @input="
50
+ $emit('update:modelValue', ($event.target as HTMLInputElement).value)
51
+ "
52
+ />
53
+ <button v-if="search" class="search"></button>
54
+ <strong v-if="errorMessage" class="errorMessage">{{ errorMessage }}</strong>
55
+ <span v-if="helperText" class="helperText">{{ helperText }}</span>
56
+ </div>
57
+ </template>
58
+
59
+ <script lang="ts" setup>
60
+ import { computed, ref } from "vue";
61
+
62
+ const TYPES = {
63
+ text: "text",
64
+ email: "email",
65
+ password: "password",
66
+ number: "number",
67
+ tel: "tel",
68
+ url: "url",
69
+ search: "search",
70
+ } as const;
71
+
72
+ type Type = keyof typeof TYPES;
73
+
74
+ export type Props = {
75
+ type: Type;
76
+ fieldName?: string;
77
+ modelValue: string;
78
+ placeholder?: string;
79
+ label?: string;
80
+ id: string;
81
+ disabled?: boolean;
82
+ required?: boolean;
83
+ invalid?: boolean;
84
+ errorMessage?: string;
85
+ helperText?: string;
86
+ search?: boolean;
87
+ valid?: boolean;
88
+ };
89
+
90
+ const props = withDefaults(defineProps<Props>(), {
91
+ type: "text",
92
+ fieldName: "",
93
+ placeholder: "",
94
+ label: "",
95
+ disabled: false,
96
+ required: false,
97
+ invalid: false,
98
+ errorMessage: "",
99
+ helperText: "",
100
+ search: false,
101
+ valid: false,
102
+ });
103
+
104
+ const selectedType = computed(() => TYPES[props.type]);
105
+
106
+ defineEmits(["update:modelValue"]);
107
+
108
+ const hidePassword = ref(true);
109
+ const passwordFieldIcon = computed(() =>
110
+ hidePassword.value ? "showPassword" : "hidePassword",
111
+ );
112
+ const passwordFieldType = computed(() =>
113
+ hidePassword.value ? "password" : "text",
114
+ );
115
+ </script>
116
+
117
+ <style scoped lang="scss">
118
+ @use "../../../assets/scss/variables.scss" as *;
119
+ .text-field {
120
+ &__wrapper {
121
+ label {
122
+ font-family: $font-opensans;
123
+ font-size: $font-size-xsm;
124
+ margin-bottom: 7px;
125
+ display: block;
126
+ font-weight: 300;
127
+
128
+ &.disabled {
129
+ color: $grey-600;
130
+ }
131
+
132
+ &.required::after {
133
+ content: "\00a0*";
134
+ display: inline-block;
135
+ }
136
+
137
+ &.search {
138
+ display: none;
139
+ }
140
+ }
141
+
142
+ // Types: text, email, password & url
143
+
144
+ input[type="text"],
145
+ input[type="email"],
146
+ input[type="password"],
147
+ input[type="number"],
148
+ input[type="tel"],
149
+ input[type="url"] {
150
+ width: 100%;
151
+ height: 42px;
152
+ line-height: 19px;
153
+ border: 1px solid $grey-400;
154
+ font-family: $font-opensans;
155
+ font-size: $font-size-xsm;
156
+ border-radius: $border-radius;
157
+ outline: none;
158
+ padding: 10px 15px;
159
+ -webkit-box-sizing: border-box;
160
+ -moz-box-sizing: border-box;
161
+ box-sizing: border-box;
162
+ font-weight: 300;
163
+
164
+ &:hover,
165
+ &:active,
166
+ &:focus,
167
+ &:target {
168
+ box-shadow: $box-shadow;
169
+ border: 1px solid $blue-500;
170
+ transition: $transition-box-shadow;
171
+ transition: $transition-border;
172
+ }
173
+
174
+ &:focus {
175
+ & ~ .helperText {
176
+ color: $blue-500;
177
+ transition: $transition-color;
178
+ display: block;
179
+ visibility: visible;
180
+ }
181
+ }
182
+
183
+ &:disabled,
184
+ &:read-only {
185
+ background-color: $grey-100;
186
+ border: 1px solid $grey-400;
187
+ pointer-events: none;
188
+
189
+ &:hover,
190
+ &:active,
191
+ &:focus,
192
+ &:target {
193
+ box-shadow: none;
194
+ }
195
+ }
196
+
197
+ &.invalid {
198
+ border: 1px solid $warning;
199
+ box-shadow: none;
200
+ color: $warning;
201
+ transition: $transition-color;
202
+ transition: $transition-border;
203
+ background: $grey-100 right 15px center no-repeat
204
+ url("https://a.storyblok.com/f/230581/22x22/ff2897a955/info-red.svg?cv=1695125825848");
205
+ }
206
+
207
+ &.valid {
208
+ transition: $transition-color;
209
+ transition: $transition-border;
210
+ background: right 15px center no-repeat
211
+ url("https://a.storyblok.com/f/230581/22x23/1669b6b82d/done.svg?cv=1695125826015");
212
+ }
213
+
214
+ &.search {
215
+ background: no-repeat
216
+ url("https://a.storyblok.com/f/230581/21x21/ebbdca38d3/search-icon.svg?cv=1695125825901");
217
+ background-position: 30px 25.5px;
218
+ background-size: 21px;
219
+ text-indent: 50px;
220
+ height: 72px;
221
+ }
222
+
223
+ &::placeholder {
224
+ color: $grey-400;
225
+ }
226
+ }
227
+
228
+ .showPassword {
229
+ background-image: url("https://a.storyblok.com/f/230581/21x21/5876ed1137/visible.svg?cv=1695125825884");
230
+ height: 15px;
231
+ width: 21px;
232
+ float: right;
233
+ margin-right: 15px;
234
+ margin-top: -27px;
235
+ background-repeat: no-repeat;
236
+ cursor: pointer;
237
+ position: relative;
238
+ vertical-align: middle;
239
+ }
240
+
241
+ .hidePassword {
242
+ background-image: url("https://a.storyblok.com/f/230581/21x21/171d9c4bb2/hidden.svg?cv=1695125825708");
243
+ height: 19px;
244
+ width: 21px;
245
+ float: right;
246
+ margin-right: 15px;
247
+ margin-top: -32px;
248
+ background-repeat: no-repeat;
249
+ cursor: pointer;
250
+ vertical-align: middle;
251
+ position: relative;
252
+ }
253
+
254
+ .errorMessage {
255
+ color: $warning;
256
+ font-family: $font-opensans;
257
+ font-size: $font-size-xsm;
258
+ margin-top: 7px;
259
+ display: block;
260
+ font-weight: 700;
261
+ }
262
+
263
+ .helperText {
264
+ font-family: $font-opensans;
265
+ font-size: $font-size-xsm;
266
+ margin-top: 7px;
267
+ display: none;
268
+ visibility: hidden;
269
+ font-weight: 300;
270
+ }
271
+ }
272
+ }
273
+ </style>