diff --git a/apps/docs/src/remix-hook-form/phone-input.test.tsx b/apps/docs/src/remix-hook-form/phone-input.test.tsx index b5888e1b..fe53d9c1 100644 --- a/apps/docs/src/remix-hook-form/phone-input.test.tsx +++ b/apps/docs/src/remix-hook-form/phone-input.test.tsx @@ -116,6 +116,21 @@ describe('PhoneInput Component', () => { }); }); + it('handles 11-digit US numbers with leading 1 (autofill case)', async () => { + const user = userEvent.setup(); + render(); + + const usaPhoneInput = screen.getByLabelText('USA Phone Number') as HTMLInputElement; + + // Simulate autofill with 11 digits starting with 1 + await user.type(usaPhoneInput, '12025550123'); + + // Should format correctly by removing the leading 1 + await waitFor(() => { + expect(usaPhoneInput.value).toBe('(202) 555-0123'); + }); + }); + it('accepts international number with + and inserts spaces', async () => { const user = userEvent.setup(); render(); diff --git a/package.json b/package.json index 80343420..609afa67 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,10 @@ "name": "forms", "version": "0.2.0", "private": true, - "workspaces": ["apps/*", "packages/*"], + "workspaces": [ + "apps/*", + "packages/*" + ], "scripts": { "start": "yarn dev", "dev": "turbo run dev", diff --git a/packages/components/package.json b/packages/components/package.json index 40735d67..208adedd 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@lambdacurry/forms", - "version": "0.19.4", + "version": "0.19.5", "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/packages/components/src/ui/phone-input.tsx b/packages/components/src/ui/phone-input.tsx index 9c86dab9..9c2f96bd 100644 --- a/packages/components/src/ui/phone-input.tsx +++ b/packages/components/src/ui/phone-input.tsx @@ -23,7 +23,14 @@ function extractDigits(input: string): string { } function formatUS(digits: string): string { - const d = digits.slice(0, 10); + // Handle case where an 11-digit number with leading "1" is provided (common in autofill) + let d = digits; + if (digits.length === 11 && digits.startsWith('1')) { + d = digits.slice(1); // Remove the leading "1" country code + } else { + d = digits.slice(0, 10); // Otherwise just take first 10 digits as before + } + if (d.length === 0) return ''; if (d.length <= 3) return `(${d}`; if (d.length <= 6) return `(${d.slice(0, 3)}) ${d.slice(3)}`; @@ -62,7 +69,8 @@ export const PhoneNumberInput = ({ const formatted = typer.input(normalized); setDisplay(formatted); } else { - const digits = extractDigits(String(value)).slice(0, 10); + // Remove the slice(0, 10) to allow handling 11-digit numbers with leading 1 + const digits = extractDigits(String(value)); setDisplay(formatUS(digits)); } }, [value, isInternational]); @@ -80,10 +88,19 @@ export const PhoneNumberInput = ({ return; } - const digits = extractDigits(raw).slice(0, 10); + // Remove the slice(0, 10) to allow handling 11-digit numbers with leading 1 + const digits = extractDigits(raw); + // Handle case where an 11-digit number with leading "1" is provided + let normalizedDigits = digits; + if (digits.length === 11 && digits.startsWith('1')) { + normalizedDigits = digits.slice(1); // Remove the leading "1" country code + } else { + normalizedDigits = digits.slice(0, 10); // Otherwise just take first 10 digits + } + const formatted = formatUS(digits); setDisplay(formatted); - onChange?.(digits || undefined); + onChange?.(normalizedDigits || undefined); }; const handleKeyDown = (e: KeyboardEvent) => { @@ -92,13 +109,17 @@ export const PhoneNumberInput = ({ const isNumberKey = NUMBER_KEY_REGEX.test(e.key); const isModifier = e.ctrlKey || e.metaKey || e.altKey; const allowed = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Home', 'End', 'Enter']; - if (!isModifier && isNumberKey && currentDigits.length >= 10) { + + // Allow typing if we have fewer than 10 digits or if we have 11 digits but the first is '1' + const isComplete = currentDigits.length >= 10 && !(currentDigits.length === 11 && currentDigits.startsWith('1')); + + if (!isModifier && isNumberKey && isComplete) { // Prevent adding more digits once 10-digit US number is complete e.preventDefault(); return; } if (allowed.includes(e.key)) return; - // Allow other typical keys; restriction handled by formatting and slice(0,10) + // Allow other typical keys; restriction handled by formatting } };