diff --git a/frontend/src/lib/components/ui/email-input/EmailInput.svelte b/frontend/src/lib/components/ui/email-input/EmailInput.svelte new file mode 100644 index 0000000..d82f907 --- /dev/null +++ b/frontend/src/lib/components/ui/email-input/EmailInput.svelte @@ -0,0 +1,91 @@ + + +
+ + {#if error} +

{error}

+ {/if} +
diff --git a/frontend/src/lib/components/ui/email-input/index.ts b/frontend/src/lib/components/ui/email-input/index.ts new file mode 100644 index 0000000..b787b1a --- /dev/null +++ b/frontend/src/lib/components/ui/email-input/index.ts @@ -0,0 +1,3 @@ +import EmailInput from './EmailInput.svelte'; + +export { EmailInput }; diff --git a/frontend/src/lib/utils/email.ts b/frontend/src/lib/utils/email.ts new file mode 100644 index 0000000..22620cb --- /dev/null +++ b/frontend/src/lib/utils/email.ts @@ -0,0 +1,27 @@ +/** + * Normalizes an email: trims whitespace and lowercases. + */ +export function normalizeEmail(value: string): string { + return value.trim().toLowerCase(); +} + +/** + * Validates an email address. + * Checks: non-empty, max 254 chars, passes a basic RFC-aware regex + * and a mailto: URI test via HTMLInputElement. + */ +export function isValidEmail(email: string): boolean { + const trimmed = email.trim(); + if (!trimmed) return false; + if (trimmed.length > 254) return false; + + // Basic structural regex — no RFC 5322 full validation, but catches obvious junk + if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(trimmed)) return false; + + // Use the browser's built-in email validation via type=email + // (catches things like multiple @ signs) + const input = document.createElement('input'); + input.type = 'email'; + input.value = trimmed; + return input.checkValidity(); +}