phone input: fix broken incoming values

This commit is contained in:
Elijah Duffy
2025-07-04 03:17:16 -07:00
parent cc27f0599c
commit 604cf0ee0d

View File

@@ -6,6 +6,7 @@
import { AsYouType, type PhoneNumber, type CountryCode } from 'libphonenumber-js'; import { AsYouType, type PhoneNumber, type CountryCode } from 'libphonenumber-js';
import { generateIdentifier } from './util'; import { generateIdentifier } from './util';
import type { ClassValue } from 'svelte/elements'; import type { ClassValue } from 'svelte/elements';
import { untrack } from 'svelte';
interface Props { interface Props {
name?: string; name?: string;
@@ -31,6 +32,7 @@
const id = $derived(generateIdentifier('phone-input', name)); const id = $derived(generateIdentifier('phone-input', name));
let lastRawValue = $state(''); let lastRawValue = $state('');
let lastValue = $state<PhoneNumber | undefined>(value);
let country = $state<ICountry | undefined>(); let country = $state<ICountry | undefined>();
let selectedCountryItem = $state<ComboboxOption | undefined>(); let selectedCountryItem = $state<ComboboxOption | undefined>();
let countriesOpen = $state<boolean>(false); let countriesOpen = $state<boolean>(false);
@@ -101,6 +103,19 @@
if (country) return country.isoCode as CountryCode; if (country) return country.isoCode as CountryCode;
return undefined; return undefined;
}); });
let renderValue = value?.formatNational() ?? '';
let renderInputElement = $state<HTMLInputElement | null>(null);
$effect(() => {
if (value) {
untrack(() => {
if (renderInputElement) {
renderInputElement.value = value?.formatNational() ?? '';
}
});
}
});
</script> </script>
{#snippet renderIcon(item: ComboboxOption)} {#snippet renderIcon(item: ComboboxOption)}
@@ -139,6 +154,8 @@
<div class="w-full"> <div class="w-full">
<StyledRawInput <StyledRawInput
value={renderValue}
bind:ref={renderInputElement}
type="tel" type="tel"
{placeholder} {placeholder}
validate={{ validate={{
@@ -178,18 +195,21 @@
input.value = formatted; input.value = formatted;
}, 1); }, 1);
} }
value = formatter.getNumber(); lastValue = formatter.getNumber();
if (formatter.isValid() && formatter.isInternational() && value) { if (formatter.isValid() && formatter.isInternational() && value) {
const country = formatter.getCountry(); const country = formatter.getCountry();
if (country) { if (country) {
setCountryByISO(country); setCountryByISO(country);
setTimeout(() => { setTimeout(() => {
if (value) input.value = value.formatNational(); if (lastValue) input.value = lastValue.formatNational();
}, 1); }, 1);
} }
} }
}} }}
onblur={() => {
value = lastValue;
}}
/> />
</div> </div>
</div> </div>