update FramelessButton, PhoneInput, TextInput
- FramelessButton: use cursor-pointer - PhoneInput: add setCountryByIP with geo lookup - TextInput: add $bindable ref property
This commit is contained in:
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class={[
|
class={[
|
||||||
'text-accent hover:text-primary inline-flex items-center gap-1.5 transition-colors',
|
'text-accent hover:text-primary inline-flex cursor-pointer items-center gap-1.5 transition-colors',
|
||||||
disabled && 'pointer-events-none cursor-not-allowed opacity-50'
|
disabled && 'pointer-events-none cursor-not-allowed opacity-50'
|
||||||
]}
|
]}
|
||||||
{onclick}
|
{onclick}
|
||||||
|
|||||||
@@ -63,6 +63,20 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// setCountryByIP queries ip-api.com for user location based on IP
|
||||||
|
export const setCountryByIP = async (ip: string) => {
|
||||||
|
const res = await fetch(`http://ip-api.com/json/${ip}`);
|
||||||
|
const locationData = await res.json();
|
||||||
|
let country = 'CA'; // default to Canada
|
||||||
|
if (locationData.status !== 'fail') {
|
||||||
|
const { countryCode } = locationData;
|
||||||
|
country = countryCode;
|
||||||
|
console.log('updating country code according to IP', country);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCountryByISO(country);
|
||||||
|
};
|
||||||
|
|
||||||
// set the default country based on the provided ISO code
|
// set the default country based on the provided ISO code
|
||||||
if (defaultISO) {
|
if (defaultISO) {
|
||||||
setCountryByISO(defaultISO);
|
setCountryByISO(defaultISO);
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
placeholder,
|
placeholder,
|
||||||
type,
|
type,
|
||||||
validate: validateOpts,
|
validate: validateOpts,
|
||||||
invalidMessage
|
invalidMessage = 'Field is required',
|
||||||
|
ref = $bindable<HTMLInputElement | null>(null)
|
||||||
}: {
|
}: {
|
||||||
name: string;
|
name: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
type?: HTMLInputElement['type'];
|
type?: HTMLInputElement['type'];
|
||||||
validate?: ValidatorOptions;
|
validate?: ValidatorOptions;
|
||||||
invalidMessage?: string;
|
invalidMessage?: string;
|
||||||
|
ref?: HTMLInputElement | null;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let valid: boolean = $state(true);
|
let valid: boolean = $state(true);
|
||||||
@@ -34,15 +36,18 @@
|
|||||||
{name}
|
{name}
|
||||||
{type}
|
{type}
|
||||||
bind:value
|
bind:value
|
||||||
|
bind:ref
|
||||||
validate={validateOpts}
|
validate={validateOpts}
|
||||||
onvalidate={(e) => {
|
onvalidate={(e) => {
|
||||||
valid = e.detail.valid;
|
valid = e.detail.valid;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class={['opacity-0 transition-opacity', !valid && 'opacity-100']}>
|
{#if validateOpts}
|
||||||
<Label for={name} error>
|
<div class={['opacity-0 transition-opacity', !valid && 'opacity-100']}>
|
||||||
{invalidMessage !== undefined && invalidMessage != '' ? invalidMessage : 'Field is required'}
|
<Label for={name} error>
|
||||||
</Label>
|
{invalidMessage}
|
||||||
</div>
|
</Label>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user