PluginProbe
The Innovative Form Builder – IvyForms / 0.2
The Innovative Form Builder – IvyForms v0.2
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / views / _components / input / IvyPhoneInput.vue

IvyPhoneInput.vue in The Innovative Form Builder – IvyForms 0.2, at frontend/src/views/_components/input/IvyPhoneInput.vue

418 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <MazPhoneNumberInput
3 v-model="localModelValue"
4 :class="['ivyforms-phone-input', { 'is-secondary': isSecondary }]"
5 v-bind="{ ...$props, ...$attrs }"
6 :fetch-country="fetchCountry"
7 label=""
8 show-code-on-list
9 :ignored-countries="['AC', 'GP', 'MF', 'CX', 'KN', 'WF', 'YT', 'RE', 'SH', 'PM']"
10 @blur="onBlur()"
11 >
12 <template #no-results>
13 <div
14 class="ivyforms-flex ivyforms-gap-8 ivyforms-flex-direction-column ivyforms-align-items-center ivyforms-px-16 ivyforms-py-8"
15 >
16 <span class="medium-14"> {{ getLabel('no_results_found_phone') }}</span>
17 <span class="regular-12 text-align-center">
18 {{ getLabel('adjusting_your_search_phone') }}
19 </span>
20 </div>
21 </template>
22 <template #selector-flag="{ countryCode: countryCode }">
23 <IvyIcon
24 class="selector__country-flag"
25 :category="'flags'"
26 size="d"
27 :name="getThreeLetterCode(countryCode)"
28 :aria-label="getLabel('flag')"
29 />
30 </template>
31 <template #country-list-flag="{ countryCode: countryCode }">
32 <IvyIcon
33 class="selector__country-flag"
34 :category="'flags'"
35 size="s"
36 :name="getThreeLetterCode(countryCode as string)"
37 :aria-label="getLabel('flag')"
38 />
39 </template>
40 </MazPhoneNumberInput>
41 </template>
42
43 <script setup lang="ts">
44 import MazPhoneNumberInput from 'maz-ui/components/MazPhoneNumberInput'
45 import { computed, inject, type StyleValue } from 'vue'
46 import 'maz-ui/styles'
47 import { countryMapper } from '@/constants/countries.ts'
48 import { useLabels } from '@/composables/useLabels'
49 const { getLabel } = useLabels()
50
51 interface Props {
52 modelValue?: string | undefined
53 fetchCountry?: boolean
54 noFlags?: boolean
55 style?: StyleValue
56 }
57
58 const props = withDefaults(defineProps<Props>(), {
59 fetchCountry: true,
60 modelValue: '',
61 style: null,
62 })
63
64 const emit = defineEmits(['update:modelValue', 'blur'])
65 const localModelValue = computed({
66 get() {
67 return props.modelValue
68 },
69 set(value) {
70 emit('update:modelValue', value)
71 },
72 })
73
74 const onBlur = () => {
75 emit('blur')
76 }
77
78 const getThreeLetterCode = (twoLetterCode: string) => {
79 return countryMapper[twoLetterCode.toUpperCase()] || null
80 }
81
82 const isSecondary = inject('isSecondary', false)
83 </script>
84
85 <style lang="scss">
86 // Phone Input
87 .ivyforms-phone-input {
88 // Moz Phone Number Input
89 &.m-phone-number-input {
90 flex-direction: row !important;
91 width: 100%;
92
93 // Hover
94 &:hover {
95 .m-phone-input,
96 .m-country-selector .m-select-input {
97 .m-input-wrapper {
98 border-color: var(--map-base-dusk-stroke-0) !important;
99 }
100 }
101 }
102
103 // Common Input (Country Selector & Phone Input)
104 .m-input {
105 height: 40px;
106
107 // Input Wrapper
108 .m-input-wrapper {
109 border-width: 1px;
110 border-color: var(--map-base-dusk-stroke--2);
111 border-radius: 8px;
112 background-color: var(--map-base-dusk-o05);
113
114 // Input Wrapper Input
115 .m-input-wrapper-input {
116 height: 38px;
117 input::placeholder {
118 color: var(--map-base-text-0);
119 opacity: 0.5;
120 }
121 // Native Input
122 input {
123 font-size: 16px;
124 font-style: normal;
125 font-weight: 400;
126 padding: 0 5px;
127 color: var(--map-base-text-0);
128 box-shadow: none;
129 outline: none;
130 }
131
132 // Input Label
133 .m-input-label {
134 display: none;
135 }
136 }
137 }
138
139 // Active & Focus
140 &.--is-active,
141 &.--is-focused,
142 &:focus-within {
143 .m-input-wrapper {
144 border-color: 1px solid var(--map-base-brand-fill-0) !important;
145 }
146
147 // Secondary
148 &.is-secondary {
149 .m-input-wrapper {
150 border: 1px solid var(--map-base-purple-stroke-0);
151 }
152 }
153 }
154
155 // Filled
156 &.--is-filled {
157 .m-input-wrapper {
158 border: 1px solid var(--map-base-dusk-stroke--2);
159 }
160 }
161 }
162
163 // Country Selector
164 .m-country-selector {
165 min-width: inherit !important;
166
167 // Select
168 .m-country-selector__select {
169 width: 54px !important;
170
171 // Input
172 .m-input {
173 // Select Input
174 &.m-select-input {
175 width: 64px;
176
177 // Input Wrapper
178 .m-input-wrapper {
179 border-bottom-left-radius: 8px;
180 border-top-left-radius: 8px;
181 border-right: none;
182
183 // Input Wrapper Input
184 .m-input-wrapper-input {
185 // Native Input
186 input {
187 width: 0;
188 padding: 0 !important;
189 }
190 }
191
192 // Arrow
193 .m-input-wrapper-right {
194 padding: 0;
195
196 // Button
197 button {
198 outline: none;
199 background: url('../../../assets/icons/arrows/line/chevron-down.svg') no-repeat
200 center;
201 background-size: contain;
202 width: 20px;
203 height: 20px;
204 cursor: pointer;
205 opacity: 1 !important;
206
207 svg {
208 display: none;
209 }
210 }
211 }
212 }
213 }
214
215 // Search Input
216 &.m-select-list__search-input {
217 padding: 0 8px 8px;
218 // Input Wrapper
219 .m-input-wrapper {
220 border-radius: 8px;
221
222 // Input Wrapper Left
223 .m-input-wrapper-left {
224 width: 24px;
225 box-sizing: content-box;
226 padding-left: 8px;
227
228 .maz-text-muted {
229 color: var(--map-base-text-0);
230 }
231
232 // Button
233 button {
234 outline: none;
235 background: url('../../../assets/icons/arrows/line/chevron-down.svg') no-repeat
236 center;
237 background-size: contain;
238 width: 20px;
239 height: 20px;
240 cursor: pointer;
241 opacity: 1 !important;
242 transform: rotate(180deg);
243
244 svg {
245 display: none;
246 }
247 }
248 }
249
250 // Input Wrapper Input
251 .m-input-wrapper-input {
252 height: 30px;
253
254 // Native Input
255 input {
256 cursor: text;
257 font-size: 16px;
258 font-style: normal;
259 font-weight: 400;
260
261 // Placeholder
262 &::placeholder {
263 color: var(--map-base-text--1);
264 }
265 }
266 }
267 }
268 }
269 }
270
271 // Open
272 &.--is-open {
273 // Arrow
274 .m-input-wrapper-right {
275 // Button
276 button {
277 transform: rotate(180deg);
278 }
279 }
280 }
281
282 // Popper
283 .m-select-list {
284 transform: translate(0, 4px) !important;
285 box-shadow: var(--shadow-100);
286 border-radius: 4px;
287 border: none;
288 background-color: var(--primitive-white);
289 min-width: 250px !important;
290 padding: 8px 0;
291
292 // Scroll Wrapper
293 .m-select-list__scroll-wrapper {
294 gap: 0;
295 margin-left: 4px;
296 @include scrollbar();
297
298 // Option
299 .m-select-list-item {
300 padding: 0 8px;
301 height: 36px;
302 overflow: hidden;
303 border-radius: 0;
304 cursor: pointer;
305 -webkit-tap-highlight-color: transparent;
306 color: var(--map-base-text-0);
307
308 // Hover & Keyboard Selected
309 &:hover,
310 &.--is-keyboard-selected {
311 background: var(--map-base-purple-o05) !important;
312 }
313
314 // Selected
315 &.--is-selected {
316 background: var(--map-base-purple-o05) !important;
317
318 // Item
319 .m-country-selector__select__item {
320 color: var(--map-base-purple-symbol-0) !important;
321
322 // Code
323 :nth-child(2) {
324 color: var(--map-base-purple-symbol-0) !important;
325 }
326 }
327 }
328
329 // Item
330 .m-country-selector__select__item {
331 gap: 8px;
332 font-size: 14px;
333 font-style: normal;
334 font-weight: 400;
335
336 // Code
337 :nth-child(2) {
338 order: 2;
339 text-align: right;
340 color: var(--map-base-text--2);
341 }
342
343 // Selected
344 .maz-font-semibold {
345 font-weight: 400;
346 }
347 }
348 }
349 }
350 }
351 }
352
353 // Flag
354 .m-country-selector__country-flag {
355 top: 50%;
356 transform: translateY(-50%);
357 bottom: unset;
358 height: 100%;
359 left: 0;
360 margin-left: 8px;
361 padding-right: 0;
362 max-height: 24px;
363 max-width: 24px;
364
365 // Icon
366 .ivyforms-icon {
367 pointer-events: none;
368 }
369 }
370 }
371
372 // Phone Input
373 .m-phone-input {
374 margin-top: 0 !important;
375 min-width: unset;
376 flex: 1 1 auto !important;
377 margin-left: 0;
378
379 // Input Wrapper
380 .m-input-wrapper {
381 width: 100%;
382 border-top-right-radius: 8px !important;
383 border-bottom-right-radius: 8px !important;
384 border-left: none;
385 }
386
387 // Focused
388 &.--is-focused:not(.--has-state) {
389 // Example
390 .m-input-label {
391 line-height: normal;
392 color: var(--map-base-text--1);
393 padding: 0;
394 transform: none;
395 display: flex;
396 font-size: 16px;
397 font-style: normal;
398 font-weight: 400;
399 left: 4px;
400 }
401 }
402 }
403
404 // Focus Within
405 &:focus-within {
406 // Phone Input & Country Selector Input
407 .m-phone-input,
408 .m-country-selector .m-select-input {
409 // Input Wrapper
410 .m-input-wrapper {
411 border-color: var(--map-base-dusk-stroke-0) !important;
412 }
413 }
414 }
415 }
416 }
417 </style>
418