Skip to content

fix: select a phone format that can hold the typed digits (NANP 310 numbers were truncated to 7 digits) - #17

Merged
janicduplessis merged 1 commit into
appandflow:mainfrom
jamesacklin:fix/nanp-310-format-selection
Sep 25, 2026
Merged

janicduplessis merged 1 commit into
appandflow:mainfrom
jamesacklin:fix/nanp-310-format-selection

Conversation

@jamesacklin

Copy link
Copy Markdown
Contributor

Summary

PhoneNumberTransformer silently drops every digit after the seventh for +1 numbers with area code 310 (Los Angeles), so a full 10-digit 310 number can never be entered, in both national mode (country: 'US') and international mode.

Cause

The generated NANP country data lists two formats for every +1 country, in this order:

  1. (\d{3})(\d{4}) → $1-$2, leading digits 310 (Canada's 7-digit 310-XXXX service numbers)
  2. (\d{3})(\d{3})(\d{4}) → ($1) $2-$3, leading digits [2-9]

selectFormat returns the first format whose leadingDigits matches and never considers the number of digits typed, and applyFormat then clamps the input to that format's capacity via getFormatMaxDigits. Any national number starting with 310 is therefore truncated to seven digits:

'+13102705123' → '+1 310-2705'   (expected '+1 (310) 270-5123')

Fix

selectFormat now passes over a leading-digits match whose pattern cannot hold every digit typed so far and continues to the next match. If every matching format overflows, it falls back to the widest match, so overlong input is still clamped exactly as before (the existing "limits to 10 national digits" test is unchanged). This mirrors libphonenumber's AsYouTypeFormatter, which re-chooses a format once the current template is exhausted:

'+1 310-2705'  →  '+1 (310) 270-51'  on the eighth digit

selectFormat moves below getFormatMaxDigits, which it now calls, so the worklet plugin's eager closure capture never sees a const in its temporal dead zone.

Behaviour only changes when a leading-digits match cannot hold the digits typed so far; previously those digits were dropped. In the bundled data 310 is the only prefix whose format shadows a longer one, and every pattern uses plain \d{n} / \d{n,m} groups, so the capacity check is exact.

Tests

Added a formats sharing a leading-digits prefix (NANP 310) block to PhoneNumberTransformer.test.ts covering national and international mode, the genuine 7-digit 310-2705 case, the 7-to-10-digit transition with cursor position, and the 10-digit cap. yarn test, yarn lint, and yarn format:prettier:check pass locally.

Context

Found via a signup form in Tlon Messenger where users with 310 numbers could not register; we are shipping this as a pnpm patch on 0.4.1 in the meantime (tloncorp/tlon-apps#6613).

🤖 Generated with Claude Code

NANP country data lists Canada's 7-digit "310-XXXX" service-number format
ahead of the 10-digit format for every +1 country. selectFormat returned
the first leading-digits match without considering length, and applyFormat
then clamped the input to that format's capacity, so any +1 number with
area code 310 silently dropped every digit after the seventh.

selectFormat now passes over a match whose pattern cannot hold the digits
typed so far and continues to the next match, falling back to the widest
match so overlong input is still clamped. This mirrors libphonenumber's
AsYouTypeFormatter, which re-chooses a format once its template is
exhausted. selectFormat moves below getFormatMaxDigits, which it now calls,
so the worklet plugin's closure capture never sees a const in its temporal
dead zone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@janicduplessis
janicduplessis merged commit 8944479 into appandflow:main Sep 25, 2026
5 checks passed
@MeliValesca MeliValesca mentioned this pull request Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants