File: //var/www/quadcode.com/src/components/form/input/InputFieldPhone.svelte
<script lang="ts">
import intlTelInput from 'intl-tel-input';
import type { Plugin } from 'intl-tel-input';
import { onDestroy, onMount } from 'svelte';
import 'intl-tel-input/build/css/intlTelInput.min.css';
import '../../../scss/iti-sprite.scss';
import '../../../scss/iti.scss';
import stickIcon from '../../../assets/icons/stick.svg';
import errorIcon from '../../../assets/icons/error.svg';
export let className = '';
export let name = '';
export let isValid: boolean | null = null;
export let placeholder = '';
export let value = '';
export let onChange: (e: Event & { currentTarget: EventTarget & HTMLInputElement }) => void;
export let error: string | undefined = undefined;
export let useFullscreenPopup: boolean = true;
let focus = false;
let iti: Plugin;
let input: HTMLElement;
onMount(async () => {
// await import('intl-tel-input/build/js/utils');
iti = intlTelInput(input, {
initialCountry: 'auto',
geoIpLookup: function (callback) {
fetch('https://ipapi.co/json')
.then(function (res) {
return res.json();
})
.then(function (data) {
localStorage.setItem('param__country_code', data.country_code);
callback(data.country_code);
})
.catch(function () {
localStorage.setItem('param__country_code', 'us');
callback('us');
});
},
nationalMode: false,
countrySearch: false,
autoInsertDialCode: true,
formatOnDisplay: true,
autoHideDialCode: true,
showSelectedDialCode: true,
separateDialCode: true,
autoPlaceholder: false,
preferredCountries: ['gb', 'us', 'de', 'es', 'fr', 'it', 'pt', 'zh'],
useFullscreenPopup,
});
});
onDestroy(() => iti && iti.destroy());
</script>
<div class="input {value ? 'value' : ''} {focus ? 'focus' : ''} {error ? 'error' : ''} {className}">
<label class="inputContainer" for={name}>
<input
id={name}
{name}
type="tel"
bind:this={input}
bind:value
class="inputInput"
on:input={onChange}
on:focusout={() => (focus = false)}
on:focus={() => (focus = true)}
/>
<span class="inputPlaceholder">{placeholder}</span>
<span class="inputIcon">
{#if isValid !== null}
{#if isValid}
<img src={stickIcon} alt="" />
{:else}
<img src={errorIcon} alt="" />
{/if}
{/if}
</span>
{#if error !== undefined}
<p class="inputError">{error}</p>
{/if}
</label>
</div>
<style lang="scss">
@import '../../../scss/variables';
@import '../../../scss/media';
// @import '../../../scss/intl-tel-input/build/css/intlTelInput.css';
.input {
.inputContainer {
display: block;
position: relative;
}
.inputInput {
width: 100%;
height: 62px;
outline: none;
padding: 23px 68px 9px 24px;
border-radius: 4px;
border: 1px solid $techBlueSecondary;
background: $techBlue1;
transition: 0.3s cubic-bezier(0.65, 0.05, 0.36, 1);
@include breakpoint-down('deskL') {
height: auto;
}
@include breakpoint-down('deskS') {
padding-top: 20.4px;
padding-bottom: 8px;
}
&:-webkit-autofill {
border: thin solid #d9d7cc;
}
}
.inputPlaceholder {
display: block;
pointer-events: none;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 24px;
right: 24px;
transition: 0.2s cubic-bezier(0.46, 0.03, 0.52, 0.96);
will-change: transform;
color: $techBluePrimary;
}
.inputIcon {
display: flex;
pointer-events: none;
position: absolute;
right: 18px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
> img {
width: 100%;
height: 100%;
object-fit: contain;
object-position: center;
}
}
.inputError {
position: absolute;
top: -9px;
right: 24px;
z-index: 5;
border-radius: 4px;
background: $redPrimary;
padding: 2px 8px;
color: $techWhite;
font-size: 10px;
font-weight: 400;
line-height: 14px;
}
&.focus {
.inputInput {
border: 1px solid $techGrey;
box-shadow: 0 4px 15px 0 rgba(0, 0, 0, 0.15);
}
.inputPlaceholder {
top: 10px;
font-size: 10px;
font-weight: 400;
line-height: 14px;
transform: none;
@include breakpoint-down('deskL') {
font-size: 9px;
line-height: 12px;
}
}
}
&.value {
.inputInput {
border: 1px solid $techBlueSecondary;
box-shadow: none;
}
.inputPlaceholder {
top: 10px;
font-size: 10px;
font-weight: 400;
line-height: 14px;
transform: none;
@include breakpoint-down('deskL') {
font-size: 9px;
line-height: 12px;
}
}
}
&.error {
.inputInput {
border: 1px solid $redPrimary;
background: $redPrimary10;
}
.inputPlaceholder {
color: $fontPrimary;
}
}
&.bordered {
:global(.iti .iti__flag-container) {
width: 104px;
}
:global(.iti .inputInput) {
width: calc(100% - 113px) !important;
@include breakpoint-down('tabM') {
font-size: 12px;
line-height: 14.4px;
}
}
:global(.iti + .inputPlaceholder) {
left: 126px !important;
}
&.value,
&.focus {
.inputPlaceholder {
@include breakpoint-down('tabL') {
top: 8px;
}
@include breakpoint-down('tabM') {
top: 5px;
}
}
}
}
}
.inputOnce {
.inputInput {
border-radius: 12px;
padding: 18px 12px 6px !important;
@include breakpoint-down('deskS') {
font-size: 16px;
line-height: 19.49px;
}
@include breakpoint-down('tabM') {
font-size: 12px;
line-height: 14.4px;
}
}
& :global(.iti__selected-flag) {
border-radius: 12px;
@include breakpoint-down('tabM') {
padding-left: 12px;
}
}
& :global(.iti .iti__flag-container) {
width: 122px;
@include breakpoint-down('tabM') {
width: 85px;
}
}
& :global(.iti .inputInput) {
width: calc(100% - 132px) !important;
@include breakpoint-down('tabM') {
width: calc(100% - 90px) !important;
}
}
& :global(.iti .iti__arrow) {
display: none;
}
& :global(.iti + .inputPlaceholder) {
left: 154px !important;
@include breakpoint-down('tabM') {
left: 102px !important;
}
}
}
</style>