From d10cb1417c08e724b17cf0ef56065360b95f9b80 Mon Sep 17 00:00:00 2001 From: Anurag Bevinal Date: Fri, 14 Aug 2026 12:53:45 +0530 Subject: [PATCH 1/5] fix(android): key affixes by distance from the digits A token outside the number was keyed by its offset in the string (`O$i`), so any glyph before or after the digits lost its identity the moment the number gained or lost one: $999 -> $1,000 killed the $ at offset 0 and created a new one at offset 0, a full born/died cycle instead of a slide. Keys are now counted outward from the nearest end of the number: P0 is the character immediately before the first digit, X0 the one immediately after the last. $1.00 and ($1.00) therefore agree that $ is P0 and differ only in the bracket that one of them also carries. The old scheme was unreachable in practice, since a plain grouped decimal only ever produces digits, group and decimal marks, and a sign. It becomes reachable with currency and percent. 6 new cases in TransitionLogicTest; 25 Kotlin tests pass. --- .../java/com/numerictext/TransitionLogic.kt | 28 +++++++++- .../com/numerictext/TransitionLogicTest.kt | 52 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/numerictext/TransitionLogic.kt b/android/src/main/java/com/numerictext/TransitionLogic.kt index 42f6082..1ad9432 100644 --- a/android/src/main/java/com/numerictext/TransitionLogic.kt +++ b/android/src/main/java/com/numerictext/TransitionLogic.kt @@ -28,7 +28,15 @@ object TransitionLogic { val utf16End: Int, ) - /** Integer digits keep visual identity from the left; fractions from the decimal point. */ + /** + * Integer digits keep visual identity from the left; fractions from the decimal point; anything + * outside the number keeps it from whichever end of the number it sits against. + * + * That last rule is what a currency needs. A symbol, an ISO code, a percent sign or an + * accounting bracket is keyed by its distance from the digits rather than by its offset in the + * string, so `$999` -> `$1,000` moves one `$` sideways instead of killing it and being born + * again a digit-width to the left, and `999 €` -> `1.000 €` does the same for a suffix. + */ fun layoutKeyedSlots( formatted: String, groupSep: Char, @@ -41,6 +49,8 @@ object TransitionLogic { val tokens = tokenize(formatted, groupSep, decimalSep, minusSign) val decimalIndex = tokens.indexOfFirst { it.kind == TokenKind.DECIMAL_SEPARATOR } val integerEnd = if (decimalIndex >= 0) decimalIndex else tokens.size + val firstDigit = tokens.indexOfFirst { it.kind == TokenKind.DIGIT } + val lastDigit = tokens.indexOfLast { it.kind == TokenKind.DIGIT } val integerDigitsToRight = IntArray(tokens.size) var digitsToRight = 0 @@ -70,7 +80,7 @@ object TransitionLogic { TokenKind.GROUP_SEPARATOR -> "G${integerDigitsToRight[i]}" TokenKind.DECIMAL_SEPARATOR -> "DEC" TokenKind.SIGN -> "S" - TokenKind.OTHER -> "O$i" + TokenKind.OTHER -> affixKey(i, firstDigit, lastDigit) } result.add( @@ -91,6 +101,20 @@ object TransitionLogic { return result } + /** + * A key for a token outside the digits, counted outwards from the nearest end of the number. + * + * `P0` is the character immediately before the first digit and `X0` the one immediately after + * the last, so `$1.00` and `($1.00)` agree that `$` is `P0` and disagree only about the bracket + * that `($1.00)` also has. A token with no digits to sit against, which a formatter should never + * produce, falls back to its position in the string. + */ + private fun affixKey(index: Int, firstDigit: Int, lastDigit: Int): String = when { + firstDigit >= 0 && index < firstDigit -> "P${firstDigit - index - 1}" + lastDigit >= 0 && index > lastDigit -> "X${index - lastDigit - 1}" + else -> "O$index" + } + private fun tokenize( text: String, groupSep: Char, diff --git a/android/src/test/java/com/numerictext/TransitionLogicTest.kt b/android/src/test/java/com/numerictext/TransitionLogicTest.kt index 57f906a..ac9aa8f 100644 --- a/android/src/test/java/com/numerictext/TransitionLogicTest.kt +++ b/android/src/test/java/com/numerictext/TransitionLogicTest.kt @@ -69,6 +69,58 @@ class TransitionLogicTest { assertEquals("1", keyMap("-1")["I0"]) } + @Test + fun currencySymbol_keepsItsKeyWhenTheNumberGrowsADigit() { + // The whole point of keying an affix from the digits rather than from the string: `$` has to + // stay one column that slides left, not die at offset 0 and be reborn at offset 0. + assertEquals("$", keyMap("\$999")["P0"]) + assertEquals("$", keyMap("\$1,000")["P0"]) + } + + @Test + fun currencySymbol_keepsItsKeyAcrossASignChange() { + assertEquals("$", keyMap("\$1.00")["P0"]) + assertEquals("$", keyMap("-\$1.00")["P0"]) + assertEquals("-", keyMap("-\$1.00")["S"]) + } + + @Test + fun accountingBrackets_sitOutsideTheSymbol() { + val accounting = keyMap("(\$1.00)") + assertEquals("$", accounting["P0"]) + assertEquals("(", accounting["P1"]) + assertEquals(")", accounting["X0"]) + } + + @Test + fun trailingSymbol_isKeyedFromTheEndOfTheNumber() { + // de-DE writes the symbol after the number, with a no-break space between. + val small = TransitionLogic.layoutKeyedSlots("999,00\u00A0€", '.', ',', '-', line("999,00\u00A0€")) + .associate { it.key to it.char } + val large = + TransitionLogic.layoutKeyedSlots("1.000,00\u00A0€", '.', ',', '-', line("1.000,00\u00A0€")) + .associate { it.key to it.char } + + assertEquals("€", small["X1"]) + assertEquals("€", large["X1"]) + assertEquals("\u00A0", small["X0"]) + assertEquals("\u00A0", large["X0"]) + } + + @Test + fun percentSign_isKeyedFromTheEndOfTheNumber() { + assertEquals("%", keyMap("9%")["X0"]) + assertEquals("%", keyMap("99%")["X0"]) + } + + @Test + fun currencyName_keysEachLetterOutwardFromTheNumber() { + val letters = keyMap("1.00 US dollars") + assertEquals(" ", letters["X0"]) + assertEquals("U", letters["X1"]) + assertEquals("s", letters["X10"]) + } + @Test fun tokenBoundsComeFromTheFullLineGeometry() { val slots = keyed("1,000") From 6e59194ac9e7a2607b14b0efc7a1d7dcb4f34f68 Mon Sep 17 00:00:00 2001 From: Anurag Bevinal Date: Fri, 14 Aug 2026 12:53:54 +0530 Subject: [PATCH 2/5] chore(android): add currency and latin glyphs to the bundled font subset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The subset carried digits, separators and signs only: no $, no €, no letters. A currency format would have driven the coverage check in NumericTextView to fall the whole line back to the platform font, losing the rounded face the library exists to provide. Adds the currency symbols, the whole U+20A0-20C0 currency-signs block, the accounting brackets, and A-Z a-z for `currencyDisplay: 'code'` and `'name'`. Cost: 46 -> 144 glyphs, ~11 KB -> ~33 KB a weight, ~97 KB -> ~300 KB for the nine. The packed tarball goes to 263.7 kB. Digit and separator advances are unchanged to four decimals (Regular: 0 = 0.5953, 8 = 0.6057, . = 0.2541), so the DIGIT_EM and SEPARATOR_EM constants in src/measureBox.ts still hold. --- .agent/tools/subset_font.sh | 19 +++++++++++++++--- .../main/assets/fonts/SunghyunSans-Black.ttf | Bin 11008 -> 33840 bytes .../main/assets/fonts/SunghyunSans-Bold.ttf | Bin 11680 -> 34976 bytes .../assets/fonts/SunghyunSans-ExtraBold.ttf | Bin 11560 -> 35388 bytes .../assets/fonts/SunghyunSans-ExtraLight.ttf | Bin 10788 -> 33148 bytes .../main/assets/fonts/SunghyunSans-Light.ttf | Bin 11216 -> 34840 bytes .../main/assets/fonts/SunghyunSans-Medium.ttf | Bin 11028 -> 34156 bytes .../assets/fonts/SunghyunSans-Regular.ttf | Bin 11108 -> 34096 bytes .../assets/fonts/SunghyunSans-SemiBold.ttf | Bin 11252 -> 34592 bytes .../main/assets/fonts/SunghyunSans-Thin.ttf | Bin 10712 -> 32836 bytes 10 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.agent/tools/subset_font.sh b/.agent/tools/subset_font.sh index 73b2850..ee516d9 100755 --- a/.agent/tools/subset_font.sh +++ b/.agent/tools/subset_font.sh @@ -3,8 +3,9 @@ # # The upstream release is ~710 KB per weight, 6.1 MB for the nine — far too much to ship in a # library. This view only ever draws a formatted number, so the subset keeps digits, the separators -# and signs that NumberFormat emits for Latin-script locales, and the "NaN"/"∞" it falls back to. -# That lands at ~15 KB per weight, ~130 KB for all nine. +# and signs that NumberFormat emits for Latin-script locales, the currency symbols and Latin +# letters a money format needs, and the "NaN"/"∞" it falls back to. That lands at ~33 KB per +# weight, ~300 KB for all nine. # # Locales whose digits are outside this set (ar-EG, hi-IN, …) are handled at runtime, not here: # NumericTextView checks hasGlyph on the formatted string and falls back to the system typeface @@ -27,7 +28,19 @@ UNICODES="$UNICODES,U+0030-0039" UNICODES="$UNICODES,U+002B,U+002D,U+2212,U+2013" UNICODES="$UNICODES,U+002C,U+002E,U+0027,U+2019,U+00B7,U+066B,U+066C,U+FF0C,U+FF0E" UNICODES="$UNICODES,U+0025,U+2030,U+221E" -UNICODES="$UNICODES,U+0045,U+004E,U+0061" + +# Money. Currency symbols, the whole currency-signs block (€ ₹ ₩ ₪ ₫ ₺ ₽ ₿ and the rest), the +# fullwidth and Arabic forms, and the brackets an accounting format wraps a negative amount in. +UNICODES="$UNICODES,U+0024,U+00A2-00A5,U+0192,U+058F,U+060B,U+07FE-07FF,U+09F2-09F3,U+09FB" +UNICODES="$UNICODES,U+0AF1,U+0BF9,U+0E3F,U+17DB,U+20A0-20C0,U+A838,U+FDFC,U+FE69,U+FF04" +UNICODES="$UNICODES,U+FFE0-FFE1,U+FFE5-FFE6" +UNICODES="$UNICODES,U+0028,U+0029" + +# Letters, for `currencyDisplay: 'code'` (`USD 1,234.56`) and `'name'` (`1,234.56 US dollars`). +# They are the reason this subset is ~33 KB a weight rather than ~11 KB; without them the coverage +# check in NumericTextView falls the whole line back to the platform font, so a caller asking for +# a code or a name would silently lose the rounded face the library exists to provide. +UNICODES="$UNICODES,U+0041-005A,U+0061-007A" WEIGHTS=(Thin ExtraLight Light Regular Medium SemiBold Bold ExtraBold Black) diff --git a/android/src/main/assets/fonts/SunghyunSans-Black.ttf b/android/src/main/assets/fonts/SunghyunSans-Black.ttf index 1b36326a1a041553960b3a223a4fce23d8f0affd..424db248682ccd11c903c588ef55ca5d02866f88 100644 GIT binary patch literal 33840 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 RW2<`nUBPD%l$S(%@fR%C9%}#q delta 1050 zcmYk5YiJx*6vzK}c6VM`xBH0pwQVMw?KVm6W{oALV08C0c5g(0P>4#d2Z5kC9~_xEktiXLJ-6qRAIbBdj?o>ClCrw z*?TG_3d3A5&bK}_J-ciCtEcu+Om3XWPudeb508He+`?&ekCMj<_TG}>58pwqlC8(=!elCQR~OLA0L0l+aqXV+^_^lf z(DtV*C_OP*+MR2e15)mZe{>doN1RsU(861hq*$n}JEM!0&S-j#h&prWHIY~!q!hif z?#n9*e26;7(+kesnYU||oa%hD`*I~vcNM3Az^gi_Pz3{(5+4HUFM1pbv>}(@l$W(; zkM*?6Gk`Wg4+Vy&KhOEF$7ZWLe~{ef=^HGUuW`K#-VQn;Koo{J$`pmfPj3pU7cj5=j(K$s z+ng(fp}21V2b3=4wZpi^@k2urV-1IKby*!(op5nPY;>lJ?W?M88Gw5@*mpqh1H)OI zg(XAIiDG93CuvK;;*nH7*I_-6y%}3@KWrSuY0I!;)=Ddrh$hy`pbRll>>E$F0h#~l zG*8#@pH5zqOY&FN<}>-ed`H%#EqB!QIy(edG%reF2pxu-XZNz4+p00|x4OZ=YQ(Ud zwTPf;A@lejk%*6F@G~zOZ-ExHIOS(&dz+EqcajmM7<(()(2k9`m0E>`3URe47c%ML R=2WNEX+mAOB`!QPn_&|#Qemq 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 delta 1049 zcmY+CZ)_7~9LK-UwRgSt>an&&*k6xs&M~%i6hhP>EDYSD3tOy&$dv5XjSZx%ZiRp` zX*CPH5f~mCH4CZH7y^qgEMQ`g7wQXMOhbq!7$YfT*_LPmL|(uWc>G>55%2Omcc0(y z`~3O+$)8a2y;%qVAx>VDb!^`9B3?ioX!?=XXh%9cRoJPS1I zq;(*Y5|GPtd<^n1<>*p&dLhN3I)A zWe%=cQgNPs9)JsbN0RoZUwz2^mba33rtE`h#aq@wrVZ9UJ2lu)xv>ps5-bT z%)_mM(KJoEg7oNMdUvw+ZJ^;A`IfWjnRHD5@xpv)SQP%OKdFmyCl{+0Vdqq=Iuz-G zlw!M_^R$Xf@F46=#|ln%_1A@w!Hn*-@0-c0i>~AhpvHNM2bze278C(3uUA2VuhZpA za#p)iVm<0|j{bXGp@7koXX*dG#DNx<9rD$Z-dO7LU(_Ef`GfDc`~m&H=v7&6@I?6k z3ry4HoSf4Z^cwmt_lns0U`lDj6>{XE%V*`BGR~+JgqaC82wHeZ0D1Um>%jz$(l%oT zp|W=#Jul;==oFub-;|BYRZoNGv^P=b?eos7$$#IY>ZE#BEvOgOc`dB9Yj0`=?YeJN zUkH3@gp6_{YBU;g<9TC~@sjb1vBT&$_86lE%Tc<3=&t3+@{OWiREyl;df*Q!{A@$Nn`ig2oD<`bWlJAHX|6;B z%UFvLo+?c2_k}|qmch%s`1lIcqSl!`a;SX;qWrJpjp}*#2CPIQn$bk9!a|wcD$I=n TT;b+ar!~M~VHL?$tN{K2`ep`{ diff --git a/android/src/main/assets/fonts/SunghyunSans-ExtraBold.ttf b/android/src/main/assets/fonts/SunghyunSans-ExtraBold.ttf index 5cf36567ea3a4d79d74ce06b8a4e189c66950e57..b78b887b6053a2326faee6a18c240f33a07c0cc6 100644 GIT binary patch literal 35388 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 IQ>1`@00$!ebN~PV diff --git a/android/src/main/assets/fonts/SunghyunSans-ExtraLight.ttf b/android/src/main/assets/fonts/SunghyunSans-ExtraLight.ttf index 26bb0e478c4fcfc5f5d59fa0e66038564bfef816..a2a7015d96164837aab86eb45348804cf5249f13 100644 GIT binary patch literal 33148 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 diff --git a/android/src/main/assets/fonts/SunghyunSans-Light.ttf b/android/src/main/assets/fonts/SunghyunSans-Light.ttf index 62c38572ca7331d9ddcc1d9de4b9c888df39b457..6010a5e47b681f574d2f80c2395ca75f5b8ca365 100644 GIT binary patch literal 34840 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 OFlzC!(N6Lejle%?nFT)p diff --git a/android/src/main/assets/fonts/SunghyunSans-Regular.ttf b/android/src/main/assets/fonts/SunghyunSans-Regular.ttf index 4c7099063bb91c74f110da49c1f87248c5e97e8a..189e28e21969d1a5368d782c4b750c5f85039851 100644 GIT binary patch literal 34096 zcmbrn31C!3wmx2U@9o>2J?X5ZL#I2vCFw0>C&bVs0YVZ&*g_JvBqU)G5D^doF$f|e zB1S|+hCu|}5F12v7{sXPD1(k7<2LBaFplCnJjV@4-~7L-?oNWsy!ZRRVE5f`SDiX_ z&UdzwP(nxyz9bSox_sm)X{a=dkabBoJ7aY1xQXS7Pop0 zA&WJHM2639zF`rbi^lu#A)49qZ)$&G_fi|~O(EpkiaBk~t-~j^2!t$n6xZ|T;Dr9u zn2UJ70mtS!3zjVZ%Y%()alM-mp=ADbvzljLGq#41`RnkGv<1z}7YS>l2jjRE_Zt>A zFKDy3kGP$XTk-q!(?!?autdovFB7sB?<9sri`y2>on=}HlQ%YApH@kKP(p=w#ce(F@ayQcybP^NA|~P@Wgbr?6;!lZLsdi&Rl;l{ zNn|E^Qa4sjMUl>wDWy|rjoCbC5Xk2;I~|#WOoP&lsdz&|UPxG?-C)g&$<5C(W=pKC z>Uh0?jbt*K^Yim^tyYsU#;EPzrBQB|Ls<3~s@wG3w$>L`-lM$vxo?qZeRbNrSJo(z z^wV+A%$fAm8YP>)>b9$^ozA;|c<|Xb(&OY+|9s&0-)}lUam)0%PtEap#GO-i&z-hq zlCKHFLOOdtQI~2`$PnW3T;oJv22m;q)iUc9Q3)Lc#1`mk^h;_+59`Ka1jJ?{iql05 zJsxvgZFyFUI!tFLR+~#OrAb0ev{uT=&d)FK4@G>OS{5Xefv^h%z11fA$3|YA6`8*G zqm{>%cMlw(na5Y2+m{}hm0oGHOSzvb$6in_DQy=n&>_)H@A0mUKjfoZ{qb=L4&C3)`?3e8P(Au z)hV>dMBE++S}00_I2%n0Fc1i>0{^H~Q&fz|CSo*NjFvn`TtOnJsqNlZ@a`TY;=%6*1R9zhL zW0cQMKBs)}#FNzZ!T}nxO;k$xP)~EX-c{EATe+yTeDVq1PUV+r^_Tgw(>6iXVX{2& z#}mqyUc$NZ9vXJUZFe~Fck5+k{hO4~bJRnJy%|6sPb>hVhTh%ZVL0{*Z9-F-FFke2+^yjDxYCUC7B7-~$0wxp4%Ox$oqew)a2$@CjyTM;$zfKSP z-;cLzNbrqJ`k*&0y`M-I@xD}&?y*E++-No9DTvDsyb&+QL~I7vPluE&unv(R#YwP3 z7@RaK29OOG6XyvDkSKXE;4f+_WW@481Q>l#((m?WWv#U%N7p?(O2qbyR z06x<&-eM!4WF$DlE)@@)-g5{7gzDvg#ACFu0ZJ$Ni8-QQ%@W zDuTdSmNPGDMr)>%8mrZs#+g?j#-Nrn5N(VAJ<+EQ&Dt3C{?C;*<#NATqcVN)^PdhV z?;a1Tz~eOYfbf!HQhEpKGRPE@@)FKmccNeOouJo&CS1G86F{?g2xXuqnTmu8A{~H7 zn3@9vB_+0 zKKl3zWrCl*9#cO2;~$mxpYScVyTwzVzx?t)dk*;N=HYbHkpfcWDM${1rp?d`60ijZ znt=)kb4gqe4i8FlL6BOY`5?)y<|1oGj?83uaQ-LeYxAN9(z8G`3+e!nNVD2(av#88 zq?hCj(bxPv+9`AODQrR+{pT zGJ4|=se{)lE z1JPhWgf~$(GfPOZ(_G*(2hboOY?>^`$0Z~rCMHOnztSL;ua@Z?>e_7Pm|U$n2S_+D zq^fJ(k@hbhy6w-4Rz24C=9hGeS2^_AE6QKG43axzlFc2Se&w-E=R4*-dCO(r565Wf z$){-A@xi!OuIjO-FJ3+6fu`2mD|Lm%zAKL@-#)nHuXjgl(yZy}x2&D^$buOi<4mLO zqiY_e@|MMKtc}(fEv)y8F?P!_lLj&A2(g3dYyPjO zM6LfNkf{NqV= zu&L0EQr*~Ei(TWJ5IMxQ7~+3|Cc`#KLrj)So$|s8m=+3y>)fq!V>8>~&)mGc=vLeKfn>Q|AnG~%|iXS(pMqQI68!gqB&d9E6i;Ztg zsnOb>4%bx6noB=bqs8;UC+pB+2g4GUK~W+s2(G6X)xb5(>;u^xBs0ILfMJOM-TaDl z0EU3p@)HrgDWHKq(bBwF`bjjs5SL?VwPa|0U4lo8c|FpmBu6VLINOf1LXGbT&bDgE z;MAUPM6Dr3pPZoYncuTepOmaG7KI)qbudF1VyC!OHz-+;cEc{0nbna>^d6l)J_Hh} z4+HsGys#igM0;W4_)!-d?Y>s`u{dqbu*@*$YK7<|AsX$O!CE=P&+9YP2U3#tXwy1z zmA_3_j`*~U<%Mq~uH!q=igeEP77rMJ1Z*)hK!hn49Bm^>wdL6u@v`|$E1*|{cUevQ zfX^Fl7@V0s0@Ll%yAD^h_R71W!e-!=Ot(GFn5&bs0~64IgG;9act{}2d(WvV zipg!B$T%pbLaHV!8p$S$p9!O)OhKvykjhL%StW}qkcwefS*Fb(6DXuo z3C(J#exXUI(RtE;<2GnXMjCcAm;tvocwz`~J8c&HmLV2?1`YG`_{~i}F6U(NBNt{Z zn7GSFt7WzVGt(Ijg?J8PU<0_VWM)Wb34`S-%Ew9FyRhhKCS5OR;>f~xS6($ z094PQFytX20CT9+0c%c>pe!Lxn?VuKK@?TZ%&f<-SIiJ= zNrqcW+w<@H45#RvPcP7Ur)C^nqK!hvs4 zmGbs!x^edNtJb`FgT`=@wte{poquYF@~HA{xZS<${IU@RgLV4kn25U{7I$_0`G%WL z-^BE6HX&lCrU|}F<^z+6N|aP{1&XuH@Xv{21G6^$nhUoSnk}Xr3wNXV{W|^T9`mzu z1%a=8n1~7d1{-U8e0+{r4!PUoa(L|SolJ!6ocqf9Avx)p#?&P1nj3p$I0=&Aj zF)rJG>nV@D?*WQ8QB@lZmtTJnVywZFkds45PHE1FVMEcQAq7^OxgeCeOn(7~^J2JY zA0Q5L0?L?80?8C~2nT?5j&PUKbI>HYZ8cVBY{m;4PkkJh*?45bG3A5D_>_3M&Yk48 z7dl)Am9sBF=(nA`^X@;jw!M0{Z})`XT^Fh~TGFiJCmuaU3rEeVdzLnS`8l2T$A;D_ zK0PjHy`bDA)~@;XvHd-p?(O;gL;v2uIH?PM3coJ}UaM$$t>D+;azT6=644yC87XCpf&w%+(eM@JgD1kQ9BXYpEh4T#q zfLhSE1*CD6N9|vDGZ!Wvw_OEH4fhfpX84WXSAAXdJpT=w|2HnvU&2!~dFDb561U>arT#dPuC`TIwSgA(K4RGq;OUHa;y@8LjnxW2_4@Kby} zBy&2+^S~!Vq5NUub5#S#9(1P(Lc`brfH@t$EO-qWU>?}Bfsk&XWyxjizW|}oN1($RVW8 zlgvkeU8T6na7f?922V6DdPoTvG~Z%HFlO*T62<2*xt5UV-}GxAa4D0|zvS8g>G(X0 z%X;s=t$!IBUHr|SyWUyG`}5=-bGFyI9B?9!y`z5Wu9=*Qeumn;LOv30V#z< z`uUV>couf$uTRQAw|{$9`ukVd{phYQIyj!3v}^wL-dTKB_H}2C((^)aQZ9R9Dw~vk zWbqAJ&b(+2poBh1q++2mh-gY-@kV1*qEn;wNeQ?y(kjE<+=m7N{;6N+{x;?1g9qs~ zfB6f&=HNl)<-cq@-P(G3oB!MJ3Z3)i*L3cyuPXO{{iU+~mG^g2)$e~#)w^~nmwx|y z<;qSbAG&;9vKDRg=$~)wf=SXRW4Kj%VRW2nwC}oS)-a&R9RkvrH^Opr;I(a0qZVW8XgIgA?nIOtr(I z>Dkuy%ErxqYMb?^Et^iZ`np^W^(H2_cGNWYEvvT^ctajnZ}vHTg4 z%J9GXdCWotAV2{KP^F^HqJKUC&~YF*fEXCtz2gqYS=s5#0R6xE2 zMmaiV*`7wL-DxppB`@^04iFt%s+W$SZbz}psgkBY+};Bt1+Co(3~vB87ZKPb`8=Nc zpFDWnDB(lo_uv(gLZ>O;`3nyo9C*wuK~Tm#z<TP0vh`NjDUO*N&brU!U*#>w~wxx#aO}JbVVvQSVpcGW8-D zQY?z9l2o@b+yNkta5F<=(35N?PUn#wSX((3^Qf|)VOp4q1^FDns!dEKGu{j0+u*#6 z$q{p*nZ8;$Elulm+cVN54cB(vw26u6Ou;Ya2u^2~JzEqSk93H~IKHI` zYz``4a2ekFm1;FGf?tM9@V^9PIBPnW*M3P3AP#N{oCGfKljP{l02xk$fU3_xg3BPy z`YT>SX=4z~*xk`ZpYPk+y_%nxe1FUIXO^k<2jPv|{`k!g-b$qt;xcxsXXk=_jWdp~ zXKil>?(0O`QwV&8iICxtlwdBdXM(|*6p~y};P(}BPaJc_AygJ{*9HBDsyUe&B@`aQ z7Tb_WMT1O?8tl-G(R5Q1{A?smA0KM|}6VkK8mDiG#Q}N^Ks#P`dQK_ctE61c!HcR!D6H=+oVoKF&FCVs9 zEHlU5q>^!sRx-<8t{7B!YV`(M*;L;_4AJF1>lARhk)au%boTB&*Px=L(oLc~%T!iBP~YkKj59I7~6~IRz5|#?-WbM89^^ z_#|P|9i52YUHjbPx%=kEXq*`(8AF8lLp1)8qtv_)hV1Ld6qg7*0RQo=80WOyWWl@T znMbG2-8Fg4`l)t%h9&xe3%A^_^!$FwUx9X&6bw7kY0&bQFzQw4PZb&Gsm`S;sT84D zfF*bbC_C#7omCDiKaYUUoSB9+Lj%FDMDF!Mwj z=qcd7BY%!qpR!^T?P?WJ3e{Pf)Q@7%bw z`*%DrUcKtY`2cGNm&|x<)u0G_`lxi5pnriTKm0r$`~ansc3r#f#db>npd34ua^0!h zG?8iP*7VA2hfdu)chP|+J`<+=eqP&-$wL=ZX4tH0(VE*%UAL`g>*C|L>Z9Y%0RsIVD2yM%p)54OhIBQN zaU^3%RVryF#`PCNT1VIW>EuhwYhE^9J3)h5@U;!m{4t(U z%-5}h(KEmSArj{KpUW{ZA3O&5{XS6y^wZPfyC_J{&vM}v$k*$0^|Fk>0a0H-g@DsL z$3KC2(71nkBb1yYyrw+)!Erj{;x4K>k^$s63eN8#uWWwg+cn7zG-mHJH2axD$_sC; z{Od|eZ#;AB+P~dGSG;#y$`SfBolVO_uA|9#eLIckAY-lv6LhpuF;2 z_o}lUH^052%_c}7kkR>h>FKOhXjm>0~*K?v`c+Jp%t+ME$7 zF782o3F1?m9j>sbo~_y(OQlhlI7r?D4Fa6ybk?V3r(9}HGe9Vlt)O=~=xs!THP(NLp5AI$mLLvt(0P(gjw?h&&hD z`a|uJ0uu{~EIYH0#)&d${0lGR{mPMN1!2JpOWGcoNa-Uq{n&HV_9&&3x3}K#0`gG) zpgi-=miLxWy7GhDH+;B45Ej4Rx#Vbj+cV3SA8l=ac4!mf2mp|SV=ea(KQr?b0p@BHfzx3xXJX#U>K<&Hy=zK<|5#oE z<3G&82&gJ(3Q;YqMOdVWV@gzjl@3p&EX`$3Tfc)B6ENUuK$gzcJeU>>Cgd(yNgIos zVAz270Fv+Hb3(3 zTT>d9|9<$W^2Re>T6$*XyDM)zv-Z{xJ668CR+I9yGEUi{Y*z&3r-iTI&deLLb@94m zwE4$1cRxk*UwobxJ=?wNotwdhYtG)d^voJ?;j!L}f|XA5`_eGE{1yV>1NNDtgyrQ) z+yrB8D`uz3COUl5kRieUqWku+!+fN3d?)BPq>HLaP48Dfy+lF|5&GOuFM0Fq?CLSG zQm{%#adjk^vC)53Yz$oO@|_SykuHqNsCwK@m!Wm%(K-=#A7`y2hlL&~S3JkOJ)RVd z6wXay@Rns$P%@6Ux-XlM2SWlDmr;@-uYB2Tq6lw_eu2!@3cRad2tBHK|G(aDAY ziOsbnSZvXgHcgnYX_D5Uw_1j1k3LVOwZdAOl&Tv%D9*4$X;OxK@PRT!Y1&~-OiE7F z(Lur;6p8+@3J~Bw+t&g>pxZzoKF`pHH>m-FJ8k;w%}zXaT*? zce8RK6|tcB!8_<~`j-zrpnsve11(TK^WCUyU@cfB^$3DmAu+_@LDC(!>)1dxvq7ul zId?H6DnF3^8HYK?%q6rZ7Nnu?+2zOMY7I8KutHl~r&d_DgzsRr%@nN>YHQj1y{clm z1yYpzf`9hnpznPkuw*tZZNZp1m?}o*Hr)Le*{%@naN&JAjM-0`Y4CB(@r1gdhoYg6 z1Q^nT;g&HF6_F*CJlF3F(5U^sfPP23&Z7_B!Y<-AK_X0XaW@Et-tQeQB11FH7ITKl z!r&L0*M~3CprZ46EzJtb#hA$;i%f%;p&P89+wa56jMx&35m)S zpFp95Ek+z|XMqEkgPynBCY+*i8~REdLNn99 z@d3b`#{J@!?;aRX?|^f(ujWDMVs#I~ZeNqS;lZ}X&67nR90@#IPyI2h#uPG?tnh~d z)1gG5Q5dLGQKIrEddM1ofE2k2Eg?|FO#AELbNbn>vdpbwai#`tZR`%by}^?-7{xJz zhYl{tc4wwr((t3nNG1#Q=LhuxSDtq{AY5h?`W?hb_D8xGn;wCfxKaA@-vT$fuD{v$ z4d1~mIrdNRRyF*Y+Et5ry7a$)^o^3qw?8P5tiZN!Zs@pz;st+D>oUkFBC{QHEVE;S zc#uJno(bRo8}b~Jm)GNzkxLHDt_g*$2py%#7cpBdYsNUyIWDPak!LG z{=%U56>9}67oza+;Z`ar3jdrE1Rvs!s1^#$%R=S!oUqna=~B_SeYRU~9p z7GMiR*P?Jx4(xV)Bn=~)kTA_`5*kWpV$y<;5i}%(pcsUk;yRCuJtEx3pHQv;A0KG& zq?MNs9ZE=fP5IdB%AsXLL4Hz53UYI@TqZV!qgWUkQ<%|`vsPdV^RP3fGA~LB)+VXh zATVXkXEfuCmzgdIzf!dH^ZCps z^}+aU|JWFu)c1bY8U47!g;{^q+#XoZ#QZKqT?%<6js%n(+v1h;0svVR}x%@0&I4LPHHaL}HS>G)dN^2VF=y00CXzU5n# zy?d1{Ay9OiBJTe25mvWkvpsM$=F)-KqxbvkoA!UdIbt)T>y|_sMo-a9{QENvPlP>j zIYHTXDp9UUJf-aY5>gE{bt+bLS3o?Z*fX>^ElC>&SvD-kX%bZ|8i3A2$pbNC4*S!2 zQ3L^zxQQ38*MB{2?=UxTi#xinXXh!d1&E+hw9z-&ct``ab*qr8RsHs+oA@YoA+E9sv%$$@8%WYV87F;qC3in_>fDuB35SENC&=AzQ!ObK} z>q$sRzfVSF;XYKm)lE*;I+C>odFJ9!2rVFjIJMZHu4RLln|nL^`GnQ5*wlQ&xt7L|d zl;or&<-(YE)-zVCUQ~0r`l>=YX=imxQk;H!VqPy9BO-k?i8}6}Cy}noYwLvV{PO0w ztc#VG3zb){RqYgBP&#{iE+?se8X9vM1)cuNLJw@VapZPSw2i9dQaDM5#)gWbz~mpp zYEC!}kjwr5@m^&;u01$q-Un8qDefJX$dqM;F*7pSIe*jT8 zTM^7WTcIgBgbf*ngMl(x9Rouc)0x>yzg3$UtYt)oSz=J-`UA8P39dWsw){fC@D_2rWsO_&7s_B!RHSGjIcHe5Z21o7WnrW&`xAVAkuGSJX_ZS*O>V2b&D~b#t$5ypxi- z>kJ0dV5?rgaqPtEiq(3(mEFALTIGj(cGD>24gB}+hm>y~dWdQtN@;0aY%o}jscHJ< z*HXHvlZMXUXiS9-Xwa{pP~SLdqrs4_H>4UjEkLyWPT%}h`m|J|)nHgQwe91BH2nbd z#FI}#AskTNKgi@4P{Rahui-#kpyT@C z`_)oDP`(im?_9bEl)sIG_otM9Kf%0_tT4m;=es8Oe)t`YJpie{o2nkyv8oK4JJQ;< zp%#T44=V4y34vev<~Brug^pu$P{ScH<-b0B`Kk5(Dvj&bL<(Oeph9EE58JiSdX1Yx zm%XwQ*UZ-R_7#ynPXg*Xb}7p4$n_4F+`i2rY>Aw@Y4YVSS{`g>#T|mL6x3XyRLXmy z2lL4&Qb!&|^j;mp;;k%KxqzrcLPOM{9l%q}nJdt_Q8b){g@?`J1cVCU4z`(NBWY-; z+#I11WEp@~=Nb0DeiA}y3V&SF96>djCJjtWfrXGOe-*c0BtPl*BUK zPz(QN2XwFFq+OD>1a?=u{y}TsxZ}Io*6@TxyFTUd zm)4(u*d|<5IZ|~A5c`JWbh9V0yYI7QixaYQb&2-WF;z$C#Lta`LsL>LrgDQB6_b4T z3p(-X@#6;D6Lnd+2`iR@vwS-^pTY;~RyJR9|cVWEOr zBdP~D^NB_iG80o`N(d$ZTrh!02&N5TA*^3M+W$aS#ys*FHD@5IRh{7q)7{_Eva50G z@0$>|&1YQany~f*^nQ?OqdmQ(3cv` z6b)lc1TE2b^xk3$#S}N7<=l>9bNaXXdG$O;6+<^`dpFXi;R`}1`l{*u=VATBwzu+G zshZD_0b-JY5`X1UK0}oc5vAl>Mm-N&W(dm?B4r*=zLQ%?k|z&Q1`AYlZY zMcw(ox2FqgvOp-e6(!dyy{YvNy5_I%az zkNXkN@Erjwll72F6_84HQcq@jriGx(!>L*WdkKBVdKeu<1GuVDGo3+1B%#hGVWCvk zz?Bw`baL9vJs$v|Afng?32km*n+TIztd0`)1(!-(e#w#%>JVCi3n-=?IKhRF_9uqf)0+^}j@?96 zT{M|ySu7olV=jNo#JD)8u;}qU!iV6XEu}?&c;fEkI^5ry;S^GpL&~==DgV4b$IbIk zRgn&tx@ci5GM>!QE4!}${^h z?>{hVQ=!|A8RvAe`GS=khz$~36@uAW7VelY{{n~myH^xHQFwdsBJ_^cq`?(Sx!=*F(YbwD_a!u@5e zaDRgElH}zRr)PJdJb#69o|WgrNw$Os>VzMdZ19DO27e{Lk5$$kLl0xo!+L_OyUJXF zs;9(-sgd0U-cjSan$Bef&_qUjpN0Ba5(p0wV>OM5wK-+OEO|q7%|p0d>F0_Vs1|i! zFX2>R(6vt*G8YUJ9ezlh&v6@P9;V9rfI>n7f)(6p##|VxbeALD?zUeu%+7Zft?r~L zuL@lGUtY+_aYoa*XZhdm!&Qe1$yFY=9XofuvnpJ4IV&fIgx}OAzQTlHwnpQ7laYkJ zKVG@;;v33KPxo_0(n`AQzq)Age+@mw2(?v`;CXX8PZgX|-h0mJZhZ8=M=EKIE0BCE zmteLvlJTAz2j&?()@qFkN!lGDR22$CTqVs#!euyv1yC{?O~58c^x0pSiwc7&lWS|n zj2=}!{2EKX8S>R)84?NIV#bUK(x^nRagEN&(!VEKxh_X(GWRR`*RH`Vi|r#a#|g}# zVN7I`lb@GMfQFLo?&PFwd(j|4;38(d+`*`^DpY=$8lK+$-Mz6wR(iF~5f(RZQ)T_0 z_HYV^mCK-Y%z1VY_I*$%!IjEQ@^Yzat@0{Ah_V>^Ty6bZ4r;HUo)n8Itl>gp?R(JJI(yW%d zVWZyfPk)SqPzV{P!WMt&gTL@;$>9QEJUfJ|P3mW;RMAu~STnr{p1LyXM8gp;6;TEQ}vz7u`E zXv(4BfIEX=ouzaqB(g}E>b(q2Y2NCxb?>YM?6$k7ZW!IxIhNN2TuiRXwPk4NTgLxx z+}*;j^5o3uq$Q6`pZ!SjvcXlkayLtN+pAAoartP^B2MV-*WFdp`0%wo+t?A^?t63; zyG81_*!G9zJtx^oe_HB3((L;`)lX>AQAUQ^9jqq5hEb(^6xPL zZ!^Znil!K9%rnxQJd^r6OsXYI*wk9W*ZPQ6>V0##n1>!?m-x5aUT@Bgqum0cX%!CF zlAhw-%GU1FabhOTSJLUpxW`p+<;U6G7x=gD1k545(89KumZjX$e}R7soer07u&cJ$ApkhP^U_!WB4)4&?@E95v86Gy9L_`F#P@)0T)xt~_E39o88$}}{ zNppzCKj%@`#)@Og|KHz(xiE#lOw-KZD~wjWi#2}S|N33rAe%Wh&^~}AmMr?q*LoWM zZ*Po@3^dXIauOBQ*JS2bGS^KeWKG8n*UxI2);M{3-E@q_#PPM&l}=LzI8%!imB5$% zNP+<<14-;FxASuo4_A4RlffE8^*ogIGxjG%T5iapnO@aCdIe;6^%l4gk? zC}sMfG)v+69|erjASLEdLxC}#LTtrTtI-&*UIuZpSm07+Pnq)kWu=mcB#x@)^KWW)xK17M zd3Nrk%Zsz-(~6xtS^f=^9s5DKG!lzxBa$pQ^@4~g4v1+q8S2Sr`F1k$NwL_VCV-Io zeBdDi5K?(5k{IHV$zb8|asV)=8k5S#j`)K3?>1m;Hqbw#lbjDrdW<5DSny%xxXPri<5f}P#kIUg& zxO3DOZaXXry5%p_eD9{uZ%faVw4rW$)q=ulCpIdJoX&i^`-@0T!t=8M%3+}`24?iH z(2_y2J#P3am@y&3=4LDA`Rxc8VJMzRM)_ZIMzSp}70bCK@=|8D4hP3N{rnIFiAHVU zN&qw(ERZrBTXa3Q9JrMLj1z3@7&6gQTagz6 zV@QXW;LEG}7CiN2u5)M8A=rDbRP_LvTZ#Nkv@ z%JFcasiA3xbpU}887VZwK{0b|L|7D}=VEhc2=X?jGf9FtGYAJ?~) z-OyPt!aFtS$ZOQRW4rR%^XvaK23Z~@cK46B&OUPetjYJ?qm4G0Ew%^uxg6~dSJN_T zquzf$t32`PgXd>vKY#bC7v|EWs%vT|nMPX2Ox84vKe(>rsmXPR*WLQm1S*_-g*JY) z=u0}|WzFR|<&8yR6Rmjkw6g7s(zlgk&o)o@EoYNem8RUeug)Q@8f2F#KfkGTHRiRQ773Kjmm(_DMvVg@ec}$v*=v1WJ zRC$fK74_Cv--;v~|I!k_xIGKEyZUYyWeFaKzF!#d7`UVFN3ecN@cjr)s<6(>&z@uU zdw($&+Qpy-5(meRLkCCLOo=W#iWpN^IkA5&T9g{aiV&wjvuvIMGazj+Hi#Xp>n?_iuQ7 z*pSxa9i?;OGAT`noIH8V`0Pb{k`R?remagk<2uouWlt)eG$TE`zOZ2-P1Ow=BGy~9q+DP{l?0bZ>(N`)hoTq_lo2_UpI5>#Hgt7oD6fdq@6f&>BF>Ec{MAY z&R4di8RUv1t11sa{*Qf?qvsZ`T!2Aq?EOTw0vgLh9;@;W0^QR|2%_sDatF*Vm<-61 zhwmdSRD*u;6e$6PL)?>yVP%nE$A7$^uL}dGb&KEosPkk7Z|ARMuSe)>F8?it8hGhn z;ARXD^FMpY@ZzC7$`WfSw{ZWnU*y9MNk|wbAhiLZU^bTni)gaFz|{7;Xqk}3wLU9E zRe@P@G=Ai$xaiuNp=HlMth~<+H|`7Q;DHqimrIMobu^IH*RyNPAP%dDVa2sZ-0Q+Z|R*TFH&DbOk)mNLLT!NqCkOK8meBhc>bK0X>wTT zh~fF!87e7Es-BGGqAGv>8p==vH5^bKEa6Wb+5n3HA$CDji*2ADX$CDIDZ|2efE}s% zY{?=jXauT(+eO13(u9JN|LGCLY!@xOcJA!9hAERK)KrfyFCLng<93(}G9y?r8=wQ? zi{N*Ek~u@k%)J0kXR&v_9GpZj4R|z>lbEr5pA*8`x65c9i1H@#$rB$BhbY|4Y;nRg zwFGFLmy36*6XR8t4afI=p!{v;#?d3|T|)k-tcp$f)tIs~ z*31|(;^DvFxAV$9o4&kD4mVrv_O%a=zpHWTy6Ktq%6tFxDoXJ*hs$CbC5NIq+vRA= zoyXUp61F&ls%~&#LTFrNwWhV=>b5VpvVTTjdD$JkJq|!6G zBv+8tR*V&^uYfaTJ=7kOT-EYys52E(4w29_7p4;xr@+s{yv`yWk6|56Mp+B8ZD~Wx zW36FwAVUQ_Z2~S-V-Z2{I~xX+<{<#gyv6x^L0kmZL0lt7hoPas5qOe&Mz)hw z^TR~lVL6561s7Fs{_qwm^juC%l{ABNVp2-B0VTD!uVuxOg*MB|wPr)KHXqCOvYW?Z zHJB}+&JswMS3sRHWQJ#Ic?9}Qh9VMJm=pBQ>FNwfv5W&$;-EHw0V$PQ zL<*-$KyA@#mP-QG?_XvTG#f)kXIe()CT0Y)d}D%WY5=fOt77s=EQkaVpvL3iR?slU zFD}661qFEn_PK-*7P@G0QbLNMT-nvP^EI`_2`n?yNu%FXc7Ibc$8J9nmo(UDG<_1> z;xfy3R+KH_nbzV;{hkklJ3W^Li0fjfJIkefp=>%TiCK0rr7kqXQf$kPY5%ZqkD_oF z@}n3=);9H<*p4QR)L!MyhMbLPoH%xv(_szK5cqp^1CNn04DSOI#yLn72CNPx9q=s> zq#lBxAt78x){PB^Z6U&i#uHqTO4AIfJ4MaZb0!{j|H`8R5*~$+xp)N6hKiIW>kN2| zH7l?GF}9oxVNe(mDE#h!eAqJ#y}+Yk9VCpvfJFM%|Nd#FxZ@h8j2~AuW@H%zmc@qT z0z(9|A~C@JEEA>y`Zaev>_l$!tC7cLv#~M9HwtLDCSgL)rWO)%;6Z?RlH;*(E~FPT z`;n=_&cW8d5Spzoj4Zi)1gqK1e{to`lXZfJYG~oA9bd1BOU_K#bRczbT3Sa99skOq zX<4qHl-GAfb$BP2ZJkha%{XDBAvDvv{ER+1GiA@QSI?nvK*(<&l$e!JOE*v6zjW^Y z={LQytaAIgB@ceMG+anXSl^M5wlU?wKgC=zjsbq=8C;at$$C>>>%ehH*f*Ty-28Zim<*O$S zC|~V4-*RB_^-s3=uucG?pCnX^{$4{yz(X;HRCy}OERpbZ((334EF`0%k>Q~lBo0zC zhZQCwq8k+^@F;j`DP%`Q>B!QNBRqJ1*wDg!q;F(vSzdEm40y<36Z`rqG8TgHNQ^Zy zKXBic$yhO9yO~Vfm2C5;H^=708ZF3Xrq~J%@t>S#o!@c}(b39@F=y$v_v30;P0)Tw zx1NowWy|G%%ole*eI5%~j*Gvb%=rXsS~}u3DBWWFhUoRe>A3aE$2B6%FPN#KgM~_K zdQOPt)zv-6#nKv!QBLYP%c<9MqNZ9b$2VOkgm=>mN|G;52!{*?tyIh>F`8gicCZ2q z;Zblda||PZhvm>v+$zmR>HxhK7~76zzEO7bJDcFGakx%v_(t4rh}NaTJ0rY?S@ISrA(A?_ zumsL5?j@RRSg|7HY&So%4)^rHQzMdj^a49WTEJ^XcuF8k)7djSV70QjCX!`B6BH38 zKah=bn(8RQYIB|p=zW#Y06JshL8!5?J6}3bP%%w!B7Bya*vf%GTK!giA3E)$Dkr5l z+N~hD2QJ3f-1cms%~PB}`7TE`R)wIaa1!o|*O)s{DRersk?{b>3mhq-!a+Gw-1`5c zl1tSM2o%g461Vb~@}EJESJ0A>U8*g_f(+$K#!scLBo!Pu_@8M2$z#DCiKvk5gH?f~ z2DZu$ZAK2F#4yh2k;O&1*{Eu?5OcaUGeqWVt0GT|<#R&N4lt{1vN~XRGsBBJVsTFa z1E(B@ngMwD3Y#qZHUY+0ex6u#so79qO3AUcT)O{$-`1_Z`|rQhG9s@cyXB{C4=DF; zMcrOkU1$CDhpVfG+Y8cndZ*l5r>?E*tef%JXw&cn?eMCHp2U%A%gxP$OYGKSbIU5c zW4p5TrkNwg)MwAU>0adlyw}&!SvR4gYHCrbbti7ef0IWW$EGArt=ds{?-Wcl@?P&h zG+$`+pt}xP0|lgthWjmL2Lhs@AO_Q-5`qJgJddM#7Sdw10<7{eG9+A7sr(t5%ofY~ zm1nrSq|Y4q<#Wt-&ix;si$rb0l)$gD3<&m{o@_9vfNWkCyZw1n+0XvULrfKC78W`j zDJg74gu<%AF{Q&D1&;jetQ31nra3KI7oD8ImXC_GMzN|q6kws2H8|cjf0_hTE>a}^ z(>00V+W{+TFe97(>(~rRn~!y@eQtWwa~*AMEv;?W&Tf;Y2TtGm+>8OIFYhxZs3KAE zr?+IpUH&#c$DAdNS@B<6w|um6<+*$A{jZhu;A8i7KKf|q*2gb@x#Ht{@A-J;%8&2q z{Ft4;_uj|Yr&E`x*Q*=#$@-*0gMZquPl3zhz25WT+XjsHXjlZZX|8|Fv+=)9i1d%S zhDt~{=^OQMKI*YyF(MoHxCm`Xv})kU=l|-H;o%$w2TZ|Vf0~Vd(f{JtFLEi5OX~k1-*hMUGiILV(*?0N%geTVVB* zl;r57=tMrV1M9v0a`h7%O~~Q#b(Bpc{@VH{t-kdOcT&xD4`3CPmjAQ{O559)m4$Nn zeE&Kq552=QGcx9R)|WsE^*E+jphDWlHS{!9|T7G;@E<4_h<4OGf5{Vsu!QaR3A3mQQ@9n#ebqNFa*YW#D@ca8) zcq?lmX-D<;SELKik5brius&P>ie*TGkS*jR5=wSKvatWF))sOX&h5Is+y-Da2E{HC%Lp+3Jic0B0=~GpU>P6WjFPD$WSJac#UiH5xCx(X?4Q;aE}4c?<)lbW9Tz2Ts7lJQ8IC+#cKbkmRK9p>*XPg~n9UG{A`H|KhDyYq(SmE~3E zP0E{=*P1s!Z%N*&ymfh-^0wyf%-aj)sD&itpWdGqvF)d~ zzkc(NCwmU2dT~C=px;! zw@8ax#(8`~cH>$KK82)HJ{#C}0Ss}hfvgJ+KZzNs9GSZ0;w!N>ikLq21t}A37=|X$DJ-_^_Em3^ZSrx_DSe0S9`d~W6M0D;PB!D*DYR)P-nUx* z5Hg1CW5x*GAmO!qdrbI>%)#-o(4C|!bSGUVeM%0i>UzHr--Z3~F4-#FN>&Nw#48zy zj?qm6`V6EY>mR4(yP)5j#LMY|{;JbSt@;#sRj%ya&uA;ZMb@hyC%HIxO#Y7SWZRG; z(xs^;nc-P@=Z9o@xB+xMg*Jk&>=SX8RLW=IIygfbv1R?8DA$uEnzN)>y@5;$tszCK zZc-GwQ+N%Z#rUj4KU%Qep-v({sFRQtlSEd8oFwl>EF$j-t3U(LNxqDBUZ&fzy@byh zd^Y2w;IkW_FYwtL*!O}q?JS3o@m=VbzIv1i*Zp|%hr=l>!|Uq5yNRT}hi<`4ChB_m zG%mj9--$JA;b`C z7-YyYypX0%)Avff;k}W)fA9SiQi{FZOl-ijS+KX8@!Yj|ZcpGjHGj@+*gfF6?%sc5 zt=+%lN%p7deX;kCy~lf>?`?)K+oGKKR@*(SyRbWtUHtgkkDKTc6#folN4(X!B%i=) z9qk$RM0sr5HC9wY{ksA@;T*<04y~JVg zlF9WW8w`f3=SbxEDz7}TvEG}j^QJd6wHr20uJ;O-=09jKDzj#pT69LEmo#`unW_9R z`c~Fd>hw~F*U;4N^a>7>(PVUbMTepFX)!LIl$Lp8%M49TrH6#LveH8qvCJ!!O&4*Bm!i;!Pr3>+D}z@A2L7Q3^nw%!10Y-~1oLu>1saK^x{g|fYT zwwK?eYXV@@fm+`1vRPg-q25cX*v&>9!zZa{d-|&8=c36hcE@un($dh-+T7r!_J)Q) z4;l=u=#Qzi!Rb{w3?mI*$r&s3W1|P-#C27}i#u^!iSj4pwu zIK66zH>Avd7?Y4wU4uhYsR`_2DsA=(E$v=93k~tAGo9WLhk>;=65WzW3vNMsJxvYl zmZoyv+EB;gkVsNCvNY4!$2eh*s~IWW{}yUT6Uxx_Cd0^$re-#%oY+Li2E=R7p^?E> zVrWgx<^G?D_>ITCW;}(5`?@ypp-9I6rqZV)AcIC?h;$}nLnfFw%5g{#MtWPD%bnh6 z2fAP|c%#ZHS5Cv*_>XjqiRz9 zA*r>z!R(D_Gc9*|V;xoF>#HXEPwI>~AIs0jISvtR+2r~|T5Xw^HkW#1>}<+`wMq{~ zv9D-+d1(U1LbTM@A7b+m2 z4B;U{Voe}&nU|CthS#0*L%f3=BErZ?^O)7ZUt+I4AQ?*#NQ-tP1!Is05$yd_sUJ6w8`M|(&=orIK7Sm7Zds}Uhlu?9B|Rv zcX6@*qQODDQTE^LCpz_vzpJdD1N&!0{|snX8v4h!CiIVO&FCN7TF^hXwW5D)YeWCo zHXZ$A+YI!NZ8On7wskoS#e5>U9fl@vQj-Bfk2W!$XvWs-VmzDW@Vf0@H|FCIOoh?l z*k7HHrshHu6YT%-4zQ!sn;jhDLy_`G#&O;unTJ#~eq=p_A{)h=0p$6udvYCyJl^s= zyv_ffk-roZkUqcKT6Uf!9DzneX>N(B@K7#|XMN2FJ<&KpKC{w9@}vTWll--4b1wTfD@kew*=PZlQPrR zGij4QC5U7OU7Oaf9U0!b5`sL;tloOoVDtk?wVE%}S6*KPI)Ie{THPwmdW7FHLM#gP-m9#(H zTP00aNxig7_0^_GMct0pr35dLmti{UcDC}ccU<~diIM)IveBS1cN<0Q(N&gi%;Vr< z`2r_sNmF&{&JjjhjFD$5l!;E)v(`xO*FFFLb?NN$I@rtfVzIZ(WAR9Pc;k}(vN2yS zXO;=Lqt&y@ZbF@{8>P*}F6G)(Ot1$NG?`(~*$E?jbCoWIqqCNY`v7F(J`|oM(j&st=p*52^s(?XIx2bgKpT`i1r#Jt z0iQ^o0*(o1H(*FO0)~Yn;J9!EoY3V;gFe;e5;UUACFnCmVd zCB+2;g?B(``mPu#gsTP$;Tqgs z6@AxrNb9>{pwMp`DD){(?lSsr87PF3fkL<)o#A$N&TL&fJi~+RJzO-gmgSSJZfMx8 z+thpBThQAS7l6O^b2@2#$69AD`A$u%U^21n^4QUXsqLGCYO4;fng|Vra-rRJ9B<@? zV6eU%eaSA`N9+Usr2lQZIiRB(lHJQ*PrR0BO1zp_nOL3(K2$-q9DWl5m8jZ8@RMBc zr>8erQ+-@QObtkQC_TMJ!Vf~qM5uH=JiS?>ehy7?$8uuoSWYt$$S1MttbN=*Z144V z`D3;d2sUheU@csC{ok^}r)L90c$Cv}M)7i=r|PMCq#lW%!sa{oFti@OY2(5la}SY} zWeZP2NEebp08Z_eTP$;21OY=W?*wY*OjhhFI?o*-1b$^%jiw`k~uR&hq!OzCp^J6go zKu^eEo)A*MmvJ3;Wc*pier_Xo$~d6bS$oUaR$HtgmC~Mv3-}#I@KDH|gN{6W&R4uQ zIbw!69>Q}ms^u3nl9&Q9djUNo znsEj%M~qZs_(I;)`U-@Kq(4dAIC0}O`L+>b@_pl9%G6I;PLQ$)_cV{4$GFpE8{Vf* zYMaB?atKsgBdBM_8LfJ>L!(zU*I$o5Q@uJbd^KYqNI6V7d zS->;4lJ!K~apvPwuW<3diMSRv3wv*8-@#__PMALSIs8!EbBpK6!W(sz{c$#4T*GEz zr6T)tJbxpvIOBDusFiO$FC64q<#c9Wj!x~D%(PcdfRVQ_FZi^)p;(w0rT=*>pXT@` zM$ep74Ht(`kKr3MsbtSPAQ&XvZ>Hlygf>u{tLhrL-%vNzl)9x#>bAP0zUQ|RADg_L XP2LHSp;U{h>XBUGw+hkMPI~nZc{%iF delta 1078 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 TB)P)&)L>RJOvFjHq8|7Mqa6zj diff --git a/android/src/main/assets/fonts/SunghyunSans-Thin.ttf b/android/src/main/assets/fonts/SunghyunSans-Thin.ttf index f2bb8b27aaafc869deea8c87db75d2a53757c216..fc69e62de582afae1202ffb1cb1fff8e0b095db2 100644 GIT binary patch literal 32836 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 Kf-@tKtv>-SW!@P8 delta 1116 zcmY+CUrZcT6vn?hJ9l?xSvKr$p|%A(uq;9WL6SBVp>1f9##q5@iA~h%^1sb)SuJiT zCS9<7@DD`7w8Rh}YFg8VY&24BO;Z!K#MDI57&WA(W;OUij2eqtAL#hqw{=U15i0kYgt=Idvs6g;pfP&ldZOBXUiK`X19~C zlBe6Fbqy!t%ijToaq`pMiCD7d+Q}ICGxGKB)R1-l=Dt^f$Rr^2zGQ!*tIjh96rBS6 zzW&(JbdtgX22@|8KYpyQ@xIwXikpDo%s_9fXXi{;7+80J>)Qrs*jy9%gd6N7mk%U{ zh6_?wIoG)XF2x7CV<$uD9#(Xld@vCkPHK9AhrCF(j>HnZk!#KG02NF?TuBb@I68DE zg8fXOLkW`4_9hQ?hesIu4Efg-H`K@cA)xAAa(RjyjPj*N zxUL(V;Knb?2^m0UjACf;EGWM0EXhkbHojHN0;KZLU@j~Eoa?XU*sCd?Bd_`AttkFF z7fP%)89y6;7^|i<^UXrD#Eh7==2o-WY&G{Wx=KK_ zZ}Ofle8tZ6Z_V2#ii}24BtOQq{r*5lv6w@b=EI_UK@@RpG+)5DF@pKLQ<%52haMNT zcGKZ48%NbC0J}JNF@fFtJEQmzmgBca4>zQtE Date: Fri, 14 Aug 2026 12:54:17 +0530 Subject: [PATCH 3/5] feat: intl currency, percent and digit bounds, formatted natively MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a `format` prop shaped like `Intl.NumberFormatOptions`, resolved by each platform's own formatter: `NumberFormatter` on iOS, `android.icu` on Android, `Intl` on web. The string has to be produced where it is drawn, because the renderers animate the structure of a formatted number rather than a string handed to them ready-made. // $1,234.50 // 1.234,50 € // 42% Supported: style decimal/currency/percent, currency, currencyDisplay symbol/code/name, currencySign standard/accounting, useGrouping, minimumIntegerDigits, and the fraction and significant digit bounds. `currency` is a top-level shorthand; `useGrouping` and the fraction bounds stay as shorthands, so nothing breaks. Left out on purpose, each for a stated reason in NumericTextFormat's doc comment: notation compact (the two platforms carry different CLDR vintages and would disagree on the string), signDisplay, narrowSymbol, unit, roundingIncrement (below one platform's floor). Two behaviour changes worth knowing: - Digit bounds now follow ECMA-402 exactly, implemented identically in all three places. Android previously clamped `minimumFractionDigits={4}` down to 3 while iOS honoured it, because java.text.NumberFormat pulls the minimum down to meet a lower maximum. - Rounding is pinned to half-away-from-zero, which is Intl's default and neither platform's. `2.5` at zero decimals previously read 3 on web, 2 on iOS and 2 on Android; it now reads 3 everywhere. Not exposed as an option: two renderers disagreeing about the number they draw is a bug, not a preference. Android also reads the locale's *monetary* decimal mark for a currency format, so the fraction columns stay keyed where a locale distinguishes the two, and re-checks the bundled typeface against the characters the current format will actually draw rather than against the locale's digits alone. measureBox charges currency symbols and letters as glyphs (0.62 em) rather than as punctuation (0.2541 em); `$` measures 0.6064 em in the bundled Regular, so the old estimate under-reserved the box by most of a digit per symbol. Verified: 39 JS tests, 25 Kotlin tests, compileDebugKotlin, swiftc -typecheck in both configs, a full xcodebuild of the example, and both renderers driven by hand on a simulator through every format. Not verified against a ground-truth recording; see .agent/NEXT.md. --- .agent/NEXT.md | 18 ++ README.md | 114 ++++++++-- .../com/numerictext/NumericTextFormatter.kt | 213 ++++++++++++++++++ .../java/com/numerictext/NumericTextView.kt | 147 +++++------- .../com/numerictext/NumericTextViewManager.kt | 41 +++- ios/NumericTextSwiftUIHost.swift | 180 ++++++++++++--- ios/NumericTextView.mm | 31 ++- src/NumericTextFallback.tsx | 19 +- src/NumericTextView.native.tsx | 45 ++-- src/NumericTextViewNativeComponent.ts | 14 +- src/__tests__/measureBox.test.ts | 21 ++ src/__tests__/numberFormat.test.ts | 166 ++++++++++++++ src/index.tsx | 2 +- src/measureBox.ts | 49 +++- src/numberFormat.ts | 199 ++++++++++++++++ src/types.ts | 94 +++++++- 16 files changed, 1171 insertions(+), 182 deletions(-) create mode 100644 android/src/main/java/com/numerictext/NumericTextFormatter.kt create mode 100644 src/__tests__/numberFormat.test.ts create mode 100644 src/numberFormat.ts diff --git a/.agent/NEXT.md b/.agent/NEXT.md index acc47f7..9f17b0e 100644 --- a/.agent/NEXT.md +++ b/.agent/NEXT.md @@ -624,6 +624,24 @@ shrinking a glyph and dimming it are the same act. **Measure before hypothesising, replicate before chasing.** Two burst defects were reported from one run each and both turned out to be in the *other* direction once replicated three times. +**Formatting is now three implementations of one rule, and they have to stay in step.** +`src/numberFormat.ts` resolves the `format` prop; `NumericTextFormatter.kt` and the `FormatSpec` +half of `NumericTextSwiftUIHost.swift` each reproduce it natively. All three implement ECMA-402's +digit-bound rule and round half-away-from-zero, which is `Intl`'s default and neither platform's. +Changing one without the other two makes the two renderers draw different numbers, and the JS +width estimate size a box for a third. + +The transition side of that is the affix key in `TransitionLogic`: a currency symbol, a percent +sign and an accounting bracket are keyed by distance from the digits (`P0` inward from the left, +`X0` inward from the right), so they survive the number gaining or losing a digit. Keyed by string +offset, which is what `O$i` did, a `$` dies and is reborn on every carry. + +Verified so far: 39 JS unit tests, 25 Kotlin unit tests, `compileDebugKotlin`, `swiftc -typecheck` +in both configurations, a full `xcodebuild` of the example, and both renderers driven by hand on a +simulator through every format. **Not** verified against a recording: no ground-truth run has been +taken with a currency format, so the affix's motion during a carry is reasoned-about rather than +measured. That is the first thing to do if the affix ever looks wrong. + ## Next, in order The drum is **done and kept** and did not do what it was expected to do: it halved the single diff --git a/README.md b/README.md index 6763434..e950cb9 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,11 @@ and it has to keep behaving correctly when updates arrive continuously rather th - Stable interruption and rapid-retarget behaviour. - Continuous increment/decrement updates without resetting the whole animation. - Structural handling of integer digits, fractional digits, grouping separators, decimal separators, and signs. -- Locale-aware native number formatting. -- Configurable grouping and fractional precision. +- Locale-aware native number formatting through an `Intl.NumberFormat`-shaped `format` prop. +- Native currency display: symbol, ISO code, or name, with the accounting sign for negatives. +- Native percent display. +- Configurable grouping, integer padding, fractional precision, and significant digits. +- Identical rounding on iOS, Android, and web. - Automatic, forced-up, and forced-down transition direction. - System-aware reduced-motion support. - Android 12+ hardware blur path. @@ -121,14 +124,65 @@ Formatting is resolved before the transition is built; separators are not decora ``` This keeps locale-specific punctuation structurally associated with the digits while the value changes. +The `format` prop is a subset of `Intl.NumberFormatOptions`, and each platform resolves it with its own formatter: `NumberFormatter` on iOS, `android.icu` on Android, `Intl` on web. The string is produced where it is drawn, because the renderer animates the structure of a formatted number rather than a string handed to it ready-made. + +`format` is an object, so `NumericText` will re-render whenever the parent does unless you keep it stable. Hoist it to module scope or wrap it in `useMemo` if you rely on the memo skipping renders. + +### Currency + +```tsx + // $1,234.50 + // ¥1,235 + // 1.234,50 € +``` + +`currency` is shorthand for `format={{ style: 'currency', currency }}`. The full form adds how the currency is written and how a negative amount is signed: + +```tsx + +// USD 1,234.50 + + +// 1,234.50 US dollars + + +// ($1,234.50) +``` + +The currency affix takes part in the transition rather than sitting on top of it. It is keyed by its distance from the digits, not by its offset in the string, so `$999` → `$1,000` slides one `$` left instead of destroying it and creating another one, and a trailing `1.234,50 €` keeps its symbol through the same change. Where a locale uses a different decimal mark for money than for plain numbers, the renderers key on the monetary one, so the decimal boundary still holds the fraction digits still. + +Fraction digits follow the currency when you do not set them: two for `USD`, none for `JPY`, three for `BHD`. + +`currencySign: 'accounting'` applies with `currencyDisplay: 'symbol'`, the one combination both platforms format natively; with `'code'` or `'name'` the standard sign is used. `Intl`'s `currencyDisplay: 'narrowSymbol'` is not offered, because neither platform's native formatter exposes it at the versions this library supports. + +### Percent, padding, and significant digits + +```tsx + // 42% + // 09 + // 1,230 +``` + +`minimumIntegerDigits` is what holds a clock at `05:09` and stops a counter changing width as it crosses a power of ten. Significant digits take precedence over fraction digits when either bound is set, matching `Intl`. + +### Fractions and rounding + +A decimal mark is structural, not punctuation. Integer digits keep their identity from the left, fraction digits from the decimal mark, and the mark itself holds still, so `9.99` → `10.00` moves the digits it has to and leaves the rest alone. + +Set `minimumFractionDigits` to hold a fixed number of decimals through a change that would otherwise drop one. Without it, `1.50` renders as `1.5` and the fraction columns restructure under a roll that should only have moved digits: + +```tsx + +``` + +Rounding is half-away-from-zero on both platforms and on web: `2.5` at zero decimals reads as `3` everywhere. That is `Intl`'s default and neither platform's (`NumberFormatter` and ICU both round half-to-even left alone), so it is set explicitly rather than exposed as an option. Two renderers disagreeing about the number they draw is a bug, not a preference. + ## Direction By default, direction follows the numeric change: @@ -162,26 +216,54 @@ During rapid updates, automatic direction is resolved against the value the rend |---|---|---|---| | `value` | `number` | required | Number to display. The first render does not animate. | | `locale` | `string` | `'en-US'` | BCP-47 locale used for native number formatting. | +| `format` | `NumericTextFormat` | `{}` | How to shape the number. See below. | +| `currency` | `string` | none | Shorthand for `format={{ style: 'currency', currency }}`. `format` wins where the two overlap. | | `direction` | `'automatic' \| 'up' \| 'down'` | `'automatic'` | Direction of the numeric transition. | | `animationDuration` | `number` | `80` | Android only. Nominal timing input used to scale the native transition; it is not a hard duration clamp. | | `reduceMotion` | `'system' \| 'always' \| 'never'` | `'system'` | Accessibility behaviour for motion. | -| `useGrouping` | `boolean` | `true` | Enables grouping separators. | -| `minimumFractionDigits` | `number` | `0` | Minimum number of fractional digits. | -| `maximumFractionDigits` | `number` | `3` | Maximum number of fractional digits. | -| `style` | `StyleProp` | — | Text/view style. `fontSize`, `fontWeight`, `fontFamily`, and `color` are forwarded to the native renderer. | -| `testID` | `string` | — | React Native test identifier. | +| `useGrouping` | `boolean` | `true` | Shorthand for the same field of `format`. | +| `minimumFractionDigits` | `number` | none | Shorthand for the same field of `format`. | +| `maximumFractionDigits` | `number` | none | Shorthand for the same field of `format`. | +| `style` | `StyleProp` | none | Text/view style. `fontSize`, `fontWeight`, `fontFamily`, and `color` are forwarded to the native renderer. | +| `testID` | `string` | none | React Native test identifier. | When `fontSize` or `color` are omitted, the native defaults are `48` and black. +### `NumericTextFormat` + +A subset of `Intl.NumberFormatOptions`. Every option is resolved by the platform's own formatter, and means the same thing on both. + +| Option | Type | Default | Description | +|---|---|---|---| +| `style` | `'decimal' \| 'currency' \| 'percent'` | `'decimal'` | `'currency'` needs `currency` and falls back to `'decimal'` without it. `'percent'` multiplies by 100. | +| `currency` | `string` | none | ISO 4217 code. | +| `currencyDisplay` | `'symbol' \| 'code' \| 'name'` | `'symbol'` | `$1,234.56`, `USD 1,234.56`, `1,234.56 US dollars`. | +| `currencySign` | `'standard' \| 'accounting'` | `'standard'` | `'accounting'` brackets a negative amount. Applies with `currencyDisplay: 'symbol'`. | +| `useGrouping` | `boolean` | `true` | Enables grouping separators. | +| `minimumIntegerDigits` | `number` | none | Pads with leading zeros to at least this width. | +| `minimumFractionDigits` | `number` | style's own | `0` for a plain number, `0` for a percentage, the currency's count for money. | +| `maximumFractionDigits` | `number` | style's own | `3` for a plain number, `0` for a percentage, the currency's count for money. | +| `minimumSignificantDigits` | `number` | none | Takes precedence over the fraction bounds. | +| `maximumSignificantDigits` | `number` | none | Takes precedence over the fraction bounds. | + +`Intl` options that are **not** supported, and why: + +| Option | Reason | +|---|---| +| `notation: 'compact'` (`1.2K`) | Both platforms can produce it, but from different CLDR vintages, so they would disagree on the string for the same input. | +| `signDisplay` | Android's `NumberFormatter` is API 30; iOS's `NumberFormatter` has no equivalent. | +| `currencyDisplay: 'narrowSymbol'` | Same. | +| `unit`, `unitDisplay`, `roundingIncrement`, `roundingMode` | Same, except `roundingMode`, which is fixed at half-away-from-zero on purpose. | + ## Platform behaviour | Platform | Behaviour | |---|---| -| iOS 17+ | Native SwiftUI `.contentTransition(.numericText())`. | +| iOS 17+ | Native SwiftUI `.contentTransition(.numericText())`, formatted by `NumberFormatter`. | | Earlier supported iOS | Native formatting and rendering without the unavailable numeric content transition. | -| Android API 31+ | Native renderer using `RenderNode` and `RenderEffect` for the blur path. | +| Android API 31+ | Native renderer using `RenderNode` and `RenderEffect` for the blur path, formatted by `android.icu`. | | Android API 24-30 | Same transition model with a temporary software-layer blur path while animating. | -| Web | Correctly formatted static `Text`; numeric transitions are not currently animated. | +| Web | Correctly formatted static `Text` via `Intl`; numeric transitions are not currently animated. | The minimum Android SDK is **24**. @@ -193,7 +275,7 @@ The renderer is built around a small set of invariants: 1. **Typeset the complete formatted line first.** Layout and glyph positions come from the full value before the line is partitioned into logical transition slots. 2. **Keep immutable value rasters.** Outgoing content keeps the pixels that belonged to its original formatted value while incoming content references the new target value. -3. **Use structural identity.** Integer digits are anchored from the left, fractional digits from the decimal boundary, and punctuation receives stable semantic identity. +3. **Use structural identity.** Integer digits are anchored from the left, fractional digits from the decimal boundary, and punctuation receives stable semantic identity. A currency affix, a percent sign and an accounting bracket are keyed by their distance from the digits, so they survive the number growing or losing one. 4. **Preserve history during retriggers.** A new target does not require the previous transition to finish first. 5. **Keep frame work bounded.** Expensive bitmap extraction and per-slot bitmap creation stay out of the normal render/update hot path. 6. **Use analytic motion evaluation.** Native transition state can be evaluated directly for the current frame instead of integrating a simulation with frame-rate-dependent state. @@ -235,7 +317,9 @@ Android includes a subset of [Sunghyun Sans](https://github.com/anaclumos/sunghy /> ``` -The bundled Android subset contains Latin-script numeric-formatting glyphs. When a locale requires glyphs unavailable in the bundled face, the renderer falls back to the platform font rather than drawing missing-glyph boxes. +The bundled Android subset contains Latin-script numeric-formatting glyphs: digits, the separators and signs a locale formats with, the currency symbols, and the Latin letters an ISO code or a currency name needs. That is about 33 KB a weight, 300 KB for the nine. + +Coverage is checked against the characters the current format will actually draw, not against the locale alone, so a currency symbol or a currency name is part of the question. When any of them is missing from the bundled face, the renderer falls back to the platform font rather than drawing missing-glyph boxes. The full font license is included at `android/src/main/assets/fonts/OFL.txt`. diff --git a/android/src/main/java/com/numerictext/NumericTextFormatter.kt b/android/src/main/java/com/numerictext/NumericTextFormatter.kt new file mode 100644 index 0000000..16e8ea0 --- /dev/null +++ b/android/src/main/java/com/numerictext/NumericTextFormatter.kt @@ -0,0 +1,213 @@ +package com.numerictext + +import android.icu.math.BigDecimal +import android.icu.text.DecimalFormat +import android.icu.text.DecimalFormatSymbols +import android.icu.text.NumberFormat +import android.icu.util.Currency +import java.util.Locale + +/** A digit bound the caller left out, so the format applies its own default. */ +const val DIGITS_UNSET = -1 + +/** + * The formatting props, exactly as `src/numberFormat.ts` resolved them. + * + * They arrive one at a time from the view manager, so the spec is a value the view can copy with + * one field changed and hand back to [NumericTextFormatter.of]. + */ +internal data class NumericFormatSpec( + val locale: String = "en-US", + val numberStyle: String = "decimal", + val currency: String = "", + val currencyDisplay: String = "symbol", + val currencySign: String = "standard", + val useGrouping: Boolean = true, + val minimumIntegerDigits: Int = DIGITS_UNSET, + val minimumFractionDigits: Int = DIGITS_UNSET, + val maximumFractionDigits: Int = DIGITS_UNSET, + val minimumSignificantDigits: Int = DIGITS_UNSET, + val maximumSignificantDigits: Int = DIGITS_UNSET, +) + +/** + * Formats the number, and reports the marks the transition has to key on. + * + * `android.icu` rather than `java.text` throughout. The ISO-code, currency-name and accounting + * forms are ICU styles with no `java.text` equivalent at this library's minimum SDK, and mixing + * the two packages would leave the separators read from one formatter and the string produced by + * another. Android's `java.text` delegates here anyway, so the plain decimal case is unchanged. + * + * The separators matter as much as the string. `TransitionLogic` splits the formatted line on + * them, and a currency format may use the locale's *monetary* decimal mark rather than its + * ordinary one; keying on the wrong character turns the fraction digits into unkeyed punctuation + * and the decimal boundary stops holding still under a roll. + */ +internal class NumericTextFormatter private constructor( + private val format: NumberFormat, + val groupingSeparator: Char, + val decimalSeparator: Char, + val minusSign: Char, + /** + * Every character this formatter can put on screen, for the bundled font's coverage check. It + * is produced by formatting rather than by listing, so a currency symbol, an ISO code's letters + * and an accounting form's parentheses are all included without enumerating them. + */ + val glyphProbe: String, +) { + + fun format(value: Double): String = format.format(value) + + companion object { + fun of(spec: NumericFormatSpec): NumericTextFormatter { + val locale = localeOf(spec.locale) + val currency = currencyOf(spec.currency) + val money = spec.numberStyle == "currency" && currency != null + + val format = NumberFormat.getInstance(locale, styleOf(spec, money)) + if (money) format.currency = currency + format.isGroupingUsed = spec.useGrouping + + // Intl rounds halves away from zero; ICU and Foundation both default to half-even. Follow + // Intl, so `2.5` at zero decimals reads as `3` on Android, on iOS, and on the web fallback + // rather than as `3`, `2`, `2`. + format.roundingMode = BigDecimal.ROUND_HALF_UP + + if (spec.minimumIntegerDigits >= 0) { + format.minimumIntegerDigits = spec.minimumIntegerDigits + } + applyDigitBounds(format, spec, money, currency) + + val symbols = symbolsOf(format, locale) + return NumericTextFormatter( + format = format, + groupingSeparator = + if (money) symbols.monetaryGroupingSeparator else symbols.groupingSeparator, + decimalSeparator = + if (money) symbols.monetaryDecimalSeparator else symbols.decimalSeparator, + minusSign = symbols.minusSign, + glyphProbe = glyphProbeOf(format, symbols), + ) + } + + private fun styleOf(spec: NumericFormatSpec, money: Boolean): Int = when { + !money -> + if (spec.numberStyle == "percent") NumberFormat.PERCENTSTYLE + else NumberFormat.NUMBERSTYLE + spec.currencyDisplay == "code" -> NumberFormat.ISOCURRENCYSTYLE + spec.currencyDisplay == "name" -> NumberFormat.PLURALCURRENCYSTYLE + // Accounting is a distinct CLDR pattern, so it is a style rather than a modifier, and it + // only exists alongside the symbol. `code` and `name` above therefore win over it. + spec.currencySign == "accounting" -> NumberFormat.ACCOUNTINGCURRENCYSTYLE + else -> NumberFormat.CURRENCYSTYLE + } + + /** + * ECMA-402's rule for resolving digit bounds, so the three implementations of this component + * round the same number to the same string. + * + * Significant digits win over fraction digits when either bound is given. Otherwise a bound + * that was left out is filled from the style: 0 and 3 for a plain number, 0 and 0 for a + * percentage, and the currency's own count twice over for money, which is what makes `USD` + * show `1.50` and `JPY` show `150` without either being asked for. + */ + private fun applyDigitBounds( + format: NumberFormat, + spec: NumericFormatSpec, + money: Boolean, + currency: Currency?, + ) { + val decimal = format as? DecimalFormat + if ( + decimal != null && + (spec.minimumSignificantDigits >= 0 || spec.maximumSignificantDigits >= 0) + ) { + val (min, max) = + boundsOf(spec.minimumSignificantDigits, spec.maximumSignificantDigits, 1, 21) + decimal.setSignificantDigitsUsed(true) + decimal.maximumSignificantDigits = max + decimal.minimumSignificantDigits = min + return + } + + val defaultMax = when { + money -> (currency?.defaultFractionDigits ?: 2).coerceAtLeast(0) + spec.numberStyle == "percent" -> 0 + else -> 3 + } + // A plain number is the only style that may drop a trailing zero, so it is the only one + // whose minimum differs from its maximum. + val defaultMin = if (money || spec.numberStyle == "percent") defaultMax else 0 + + val (min, max) = + boundsOf( + spec.minimumFractionDigits, + spec.maximumFractionDigits, + defaultMin, + defaultMax, + ) + + // Maximum first: ICU pulls the minimum down to meet a lower maximum, and the pair here is + // already ordered, so setting it this way round never disturbs the other bound. + format.maximumFractionDigits = max + format.minimumFractionDigits = min + } + + /** + * A given bound with the other one filled in, never crossed. + * + * `Intl` throws when a caller gives a maximum below a minimum. This clamps instead: a number + * with one decimal more than was asked for beats a formatter that refuses to draw. + */ + private fun boundsOf( + min: Int, + max: Int, + defaultMin: Int, + defaultMax: Int, + ): Pair = when { + min >= 0 && max >= 0 -> min to maxOf(min, max) + min >= 0 -> min to maxOf(defaultMax, min) + max >= 0 -> minOf(defaultMin, max) to max + else -> defaultMin to defaultMax + } + + /** The formatter's own symbols where it has them, so the marks belong to the string drawn. */ + private fun symbolsOf(format: NumberFormat, locale: Locale): DecimalFormatSymbols = + (format as? DecimalFormat)?.decimalFormatSymbols + ?: DecimalFormatSymbols.getInstance(locale) + + private fun glyphProbeOf( + format: NumberFormat, + symbols: DecimalFormatSymbols, + ): String = buildString { + val zero = symbols.zeroDigit + for (offset in 0..9) append(zero + offset) + append(symbols.groupingSeparator) + append(symbols.decimalSeparator) + append(symbols.monetaryGroupingSeparator) + append(symbols.monetaryDecimalSeparator) + append(symbols.minusSign) + // A negative and a zero between them carry the sign, the affix and any accounting bracket. + append(runCatching { format.format(-1234.5) }.getOrDefault("")) + append(runCatching { format.format(0.0) }.getOrDefault("")) + } + + private fun currencyOf(code: String): Currency? { + if (code.isEmpty()) return null + return try { + Currency.getInstance(code) + } catch (_: IllegalArgumentException) { + null + } catch (_: NullPointerException) { + null + } + } + + private fun localeOf(tag: String): Locale = try { + Locale.forLanguageTag(tag.replace("_", "-")).takeIf { it.language.isNotEmpty() } + ?: Locale.US + } catch (_: Exception) { + Locale.US + } + } +} diff --git a/android/src/main/java/com/numerictext/NumericTextView.kt b/android/src/main/java/com/numerictext/NumericTextView.kt index f2392d6..53ac03f 100644 --- a/android/src/main/java/com/numerictext/NumericTextView.kt +++ b/android/src/main/java/com/numerictext/NumericTextView.kt @@ -21,9 +21,6 @@ import android.text.TextPaint import android.view.Choreographer import android.view.View import com.facebook.react.common.assets.ReactFontManager -import java.text.DecimalFormatSymbols -import java.text.NumberFormat -import java.util.Locale import kotlin.math.ceil import kotlin.math.floor import kotlin.math.max @@ -51,12 +48,11 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall private var targetText: String = "0" private var hasSettledOnce = false - var numericLocale: String = "en-US"; private set + /** Everything about the shape of the number, as `src/numberFormat.ts` resolved it. */ + private var formatSpec = NumericFormatSpec() + var numericDirection: String = "automatic"; private set var animationDurationMs: Long = 320L; private set - var numericUseGrouping: Boolean = true; private set - var numericMinFractionDigits: Int = 0; private set - var numericMaxFractionDigits: Int = 3; private set var numericReduceMotion: String = "system"; private set var numericFontSize: Float = 48f; private set var numericFontWeight: String = "normal"; private set @@ -86,6 +82,17 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall val minus: Char, ) + /** + * Two formats can key the same characters differently: a comma is a grouping mark in `en-US` + * and a decimal mark in `de-DE`. The marks in force are therefore part of the cache key. + */ + private fun preparedKeyFor(text: String) = PreparedKey( + text, + formatter.groupingSeparator, + formatter.decimalSeparator, + formatter.minusSign, + ) + private data class PreparedText( val layout: List, val raster: NumericTextRaster, @@ -103,16 +110,11 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall private val gaussianEffectCache = HashMap(24) // Formatter - private var formatter: NumberFormat? = null - private var currentFormatterLocale: Locale? = null - private var currentGroupSep: Char = ',' - private var currentDecimalSep: Char = '.' - private var currentMinusSign: Char = '-' + private var formatter: NumericTextFormatter = NumericTextFormatter.of(formatSpec) init { clipToOutline = true recalcTextPaint() - recalcFormatter() } private fun hHeadroom(): Float = textHeightPx * 0.36f + 4f @@ -144,7 +146,6 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall override fun onAttachedToWindow() { super.onAttachedToWindow() NumericTextFrameRecorder.configure(this) - recalcFormatter() if (engine.isRunning) { beginAnimationRenderPath() postFrame() @@ -519,38 +520,31 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall } } + /** + * Rebuilds the formatter after a formatting prop changed, and re-checks the typeface with it. + * + * The second half is what a currency needs. The bundled face is a subset, and which glyphs the + * view is about to need depends on the format as much as on the locale: `USD` in `en-US` wants + * `$`, `currencyDisplay: 'name'` wants a run of letters, and the accounting form wants brackets. + * Re-resolving the typeface here keeps the fallback to the system font a decision about the + * characters that will actually be drawn. It is compared before it is applied because + * `recalcTextPaint` throws away every cached raster, which is far too expensive to do on a prop + * update that did not change the answer. + */ private fun recalcFormatter() { - formatter = null - currentFormatterLocale = null - } - - private fun formatNumber(value: Double): String { - val locale = resolveLocale() - if (formatter == null || currentFormatterLocale != locale) { - formatter = NumberFormat.getNumberInstance(locale) - currentFormatterLocale = locale - val symbols = DecimalFormatSymbols.getInstance(locale) - currentGroupSep = symbols.groupingSeparator - currentDecimalSep = symbols.decimalSeparator - currentMinusSign = symbols.minusSign - } - formatter?.let { - it.isGroupingUsed = numericUseGrouping - it.minimumFractionDigits = numericMinFractionDigits - it.maximumFractionDigits = numericMaxFractionDigits - } - return formatter?.format(value) ?: value.toString() + formatter = NumericTextFormatter.of(formatSpec) + if (textPaint.typeface != resolveTypeface()) recalcTextPaint() } - private fun resolveLocale(): Locale = try { - Locale.forLanguageTag(numericLocale.replace("_", "-")) - } catch (_: Exception) { - val parts = numericLocale.split("-", "_") - when (parts.size) { - 1 -> Locale(parts[0]) - 2 -> Locale(parts[0], parts[1]) - else -> Locale.US - } + private fun formatNumber(value: Double): String = formatter.format(value) + + /** Applies [change] to the formatting props, and reformats if it changed anything. */ + private fun updateFormat(change: (NumericFormatSpec) -> NumericFormatSpec) { + val next = change(formatSpec) + if (next == formatSpec) return + formatSpec = next + recalcFormatter() + reformatAtRest() } private fun recalcTextPaint() { @@ -578,15 +572,15 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall } private fun preparedTextOf(text: String): PreparedText { - val key = PreparedKey(text, currentGroupSep, currentDecimalSep, currentMinusSign) + val key = preparedKeyFor(text) preparedByKey[key]?.let { return it } val line = lineGeometryOf(text) val layout = TransitionLogic.layoutKeyedSlots( text, - currentGroupSep, - currentDecimalSep, - currentMinusSign, + formatter.groupingSeparator, + formatter.decimalSeparator, + formatter.minusSign, line, ) val raster = NumericTextRasterizer.rasterize( @@ -655,22 +649,7 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall } val bundled = NumericTextFonts.bundled(context.assets, weight) ?: return system val probe = TextPaint(textPaint).apply { typeface = bundled } - return if (NumericTextFonts.canRender(probe, localeGlyphProbe())) bundled else system - } - - private fun localeGlyphProbe(): String { - val symbols = try { - DecimalFormatSymbols.getInstance(resolveLocale()) - } catch (_: Exception) { - return "0123456789,.-" - } - val zero = symbols.zeroDigit - return buildString { - for (i in 0..9) append(zero + i) - append(symbols.groupingSeparator) - append(symbols.decimalSeparator) - append(symbols.minusSign) - } + return if (NumericTextFonts.canRender(probe, formatter.glyphProbe)) bundled else system } private fun baselineY(centerY: Float): Float = centerY + textHeightPx / 2f - fmDescent @@ -698,33 +677,27 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall fun setAnimationDuration(value: Double) { animationDurationMs = value.toLong().coerceAtLeast(80L) } fun setReduceMotion(value: String) { numericReduceMotion = value } - fun setLocale(value: String) { - if (value == numericLocale) return - numericLocale = value - recalcFormatter() - reformatAtRest() - } + fun setLocale(value: String) = updateFormat { it.copy(locale = value) } + fun setNumberStyle(value: String) = updateFormat { it.copy(numberStyle = value) } + fun setCurrency(value: String) = updateFormat { it.copy(currency = value) } + fun setCurrencyDisplay(value: String) = updateFormat { it.copy(currencyDisplay = value) } + fun setCurrencySign(value: String) = updateFormat { it.copy(currencySign = value) } + fun setUseGrouping(value: Boolean) = updateFormat { it.copy(useGrouping = value) } - fun setUseGrouping(value: Boolean) { - if (value == numericUseGrouping) return - numericUseGrouping = value - recalcFormatter() - reformatAtRest() - } + fun setMinimumIntegerDigits(value: Int) = + updateFormat { it.copy(minimumIntegerDigits = value) } - fun setMinimumFractionDigits(value: Int) { - if (value == numericMinFractionDigits) return - numericMinFractionDigits = value - recalcFormatter() - reformatAtRest() - } + fun setMinimumFractionDigits(value: Int) = + updateFormat { it.copy(minimumFractionDigits = value) } - fun setMaximumFractionDigits(value: Int) { - if (value == numericMaxFractionDigits) return - numericMaxFractionDigits = value - recalcFormatter() - reformatAtRest() - } + fun setMaximumFractionDigits(value: Int) = + updateFormat { it.copy(maximumFractionDigits = value) } + + fun setMinimumSignificantDigits(value: Int) = + updateFormat { it.copy(minimumSignificantDigits = value) } + + fun setMaximumSignificantDigits(value: Int) = + updateFormat { it.copy(maximumSignificantDigits = value) } private fun reformatAtRest() { if (engine.isRunning) { diff --git a/android/src/main/java/com/numerictext/NumericTextViewManager.kt b/android/src/main/java/com/numerictext/NumericTextViewManager.kt index a1850b6..3c19aae 100644 --- a/android/src/main/java/com/numerictext/NumericTextViewManager.kt +++ b/android/src/main/java/com/numerictext/NumericTextViewManager.kt @@ -45,11 +45,41 @@ class NumericTextViewManager : SimpleViewManager(), view?.setAnimationDuration(value) } + @ReactProp(name = "reduceMotion") + override fun setReduceMotion(view: NumericTextView?, mode: String?) { + view?.setReduceMotion(mode ?: "system") + } + + @ReactProp(name = "numberStyle") + override fun setNumberStyle(view: NumericTextView?, value: String?) { + view?.setNumberStyle(value ?: "decimal") + } + + @ReactProp(name = "currency") + override fun setCurrency(view: NumericTextView?, value: String?) { + view?.setCurrency(value ?: "") + } + + @ReactProp(name = "currencyDisplay") + override fun setCurrencyDisplay(view: NumericTextView?, value: String?) { + view?.setCurrencyDisplay(value ?: "symbol") + } + + @ReactProp(name = "currencySign") + override fun setCurrencySign(view: NumericTextView?, value: String?) { + view?.setCurrencySign(value ?: "standard") + } + @ReactProp(name = "useGrouping") override fun setUseGrouping(view: NumericTextView?, value: Boolean) { view?.setUseGrouping(value) } + @ReactProp(name = "minimumIntegerDigits") + override fun setMinimumIntegerDigits(view: NumericTextView?, value: Int) { + view?.setMinimumIntegerDigits(value) + } + @ReactProp(name = "minimumFractionDigits") override fun setMinimumFractionDigits(view: NumericTextView?, value: Int) { view?.setMinimumFractionDigits(value) @@ -60,9 +90,14 @@ class NumericTextViewManager : SimpleViewManager(), view?.setMaximumFractionDigits(value) } - @ReactProp(name = "reduceMotion") - override fun setReduceMotion(view: NumericTextView?, mode: String?) { - view?.setReduceMotion(mode ?: "system") + @ReactProp(name = "minimumSignificantDigits") + override fun setMinimumSignificantDigits(view: NumericTextView?, value: Int) { + view?.setMinimumSignificantDigits(value) + } + + @ReactProp(name = "maximumSignificantDigits") + override fun setMaximumSignificantDigits(view: NumericTextView?, value: Int) { + view?.setMaximumSignificantDigits(value) } @ReactProp(name = "fontSize") diff --git a/ios/NumericTextSwiftUIHost.swift b/ios/NumericTextSwiftUIHost.swift index 02b8803..da885cf 100644 --- a/ios/NumericTextSwiftUIHost.swift +++ b/ios/NumericTextSwiftUIHost.swift @@ -28,6 +28,13 @@ public final class NumericTextSwiftUIHost: UIView { /// number moved. `nil` until the first render, which must not animate. private var lastValue: Double? + /// The formatting props, exactly as `src/numberFormat.ts` resolved them, and the formatter they + /// build. Kept together so the formatter is rebuilt only when something about it changed: + /// `updateProps:` forwards every prop on every value change, and a `NumberFormatter` per frame + /// of a press-and-hold is real work for no result. + private var formatSpec = FormatSpec() + private lazy var formatter = Self.makeFormatter(formatSpec) + @objc public override init(frame: CGRect) { super.init(frame: frame) @@ -53,28 +60,57 @@ public final class NumericTextSwiftUIHost: UIView { fatalError("NumericTextSwiftUIHost is created in code only") } + /** + * The formatting props. Applied before the value, because the value is drawn through them. + * + * Separate from `apply` so neither selector grows past reading: between them they carry + * everything the component exposes, and Objective-C spells every argument out. + */ // swiftlint:disable:next function_parameter_count - @objc(applyValue:locale:direction:reduceMotion:useGrouping:minimumFractionDigits:maximumFractionDigits:fontSize:fontWeight:fontFamily:textColor:) - public func apply( - value: Double, + @objc(applyFormatWithLocale:numberStyle:currency:currencyDisplay:currencySign:useGrouping:minimumIntegerDigits:minimumFractionDigits:maximumFractionDigits:minimumSignificantDigits:maximumSignificantDigits:) + public func applyFormat( locale: String, - direction: String, - reduceMotion: String, + numberStyle: String, + currency: String, + currencyDisplay: String, + currencySign: String, useGrouping: Bool, + minimumIntegerDigits: Int, minimumFractionDigits: Int, maximumFractionDigits: Int, - fontSize: CGFloat, - fontWeight: String, - fontFamily: String?, - textColor: UIColor? + minimumSignificantDigits: Int, + maximumSignificantDigits: Int ) { - model.text = Self.format( - value, + let next = FormatSpec( locale: locale, + numberStyle: numberStyle, + currency: currency, + currencyDisplay: currencyDisplay, + currencySign: currencySign, useGrouping: useGrouping, + minimumIntegerDigits: minimumIntegerDigits, minimumFractionDigits: minimumFractionDigits, - maximumFractionDigits: maximumFractionDigits + maximumFractionDigits: maximumFractionDigits, + minimumSignificantDigits: minimumSignificantDigits, + maximumSignificantDigits: maximumSignificantDigits ) + guard next != formatSpec else { return } + formatSpec = next + formatter = Self.makeFormatter(next) + } + + // swiftlint:disable:next function_parameter_count + @objc(applyValue:direction:reduceMotion:fontSize:fontWeight:fontFamily:textColor:) + public func apply( + value: Double, + direction: String, + reduceMotion: String, + fontSize: CGFloat, + fontWeight: String, + fontFamily: String?, + textColor: UIColor? + ) { + model.text = formatter.string(from: NSNumber(value: value)) ?? String(value) model.fontSize = fontSize > 0 ? fontSize : 48 model.weight = Self.weight(from: fontWeight) model.fontFamily = fontFamily @@ -151,23 +187,113 @@ public final class NumericTextSwiftUIHost: UIView { } } - private static func format( - _ value: Double, - locale: String, - useGrouping: Bool, - minimumFractionDigits: Int, - maximumFractionDigits: Int - ) -> String { + // MARK: - Formatting + + /// The formatting props, as `src/numberFormat.ts` resolved them. A digit bound of -1 means the + /// caller left it out and the style should supply its own. + private struct FormatSpec: Equatable { + var locale: String = "en-US" + var numberStyle: String = "decimal" + var currency: String = "" + var currencyDisplay: String = "symbol" + var currencySign: String = "standard" + var useGrouping: Bool = true + var minimumIntegerDigits: Int = -1 + var minimumFractionDigits: Int = -1 + var maximumFractionDigits: Int = -1 + var minimumSignificantDigits: Int = -1 + var maximumSignificantDigits: Int = -1 + } + + private static func makeFormatter(_ spec: FormatSpec) -> NumberFormatter { let formatter = NumberFormatter() - formatter.locale = Locale(identifier: locale.isEmpty ? "en-US" : locale) - formatter.numberStyle = .decimal - formatter.usesGroupingSeparator = useGrouping - formatter.minimumFractionDigits = max(0, minimumFractionDigits) - formatter.maximumFractionDigits = max( - max(0, minimumFractionDigits), - maximumFractionDigits + formatter.locale = Locale(identifier: spec.locale.isEmpty ? "en-US" : spec.locale) + + let money = spec.numberStyle == "currency" && !spec.currency.isEmpty + formatter.numberStyle = style(spec, money: money) + if money { formatter.currencyCode = spec.currency } + formatter.usesGroupingSeparator = spec.useGrouping + + // Intl rounds halves away from zero; Foundation and ICU both default to half-even. Follow + // Intl, so `2.5` at zero decimals reads as `3` on iOS, on Android, and on the web fallback + // rather than as `3`, `2`, `2`. + formatter.roundingMode = .halfUp + + if spec.minimumIntegerDigits >= 0 { + formatter.minimumIntegerDigits = spec.minimumIntegerDigits + } + + if spec.minimumSignificantDigits >= 0 || spec.maximumSignificantDigits >= 0 { + let (low, high) = bounds( + spec.minimumSignificantDigits, + spec.maximumSignificantDigits, + defaultMinimum: 1, + defaultMaximum: 21 + ) + formatter.usesSignificantDigits = true + formatter.maximumSignificantDigits = high + formatter.minimumSignificantDigits = low + return formatter + } + + // Read before it is written: with the style and the code set, the formatter is already + // carrying the currency's own fraction digits (2 for USD, 0 for JPY, 3 for BHD), and that is + // exactly the default Intl would have applied. + let percent = !money && spec.numberStyle == "percent" + let defaultMaximum: Int + if money { + defaultMaximum = max(0, formatter.maximumFractionDigits) + } else if percent { + defaultMaximum = 0 + } else { + defaultMaximum = 3 + } + // A plain number is the only style that may drop a trailing zero, so it is the only one whose + // minimum differs from its maximum. + let defaultMinimum = (money || percent) ? defaultMaximum : 0 + + let (low, high) = bounds( + spec.minimumFractionDigits, + spec.maximumFractionDigits, + defaultMinimum: defaultMinimum, + defaultMaximum: defaultMaximum ) - return formatter.string(from: NSNumber(value: value)) ?? String(value) + formatter.maximumFractionDigits = high + formatter.minimumFractionDigits = low + return formatter + } + + private static func style(_ spec: FormatSpec, money: Bool) -> NumberFormatter.Style { + guard money else { + return spec.numberStyle == "percent" ? .percent : .decimal + } + switch spec.currencyDisplay { + case "code": return .currencyISOCode + case "name": return .currencyPlural + // Accounting is a distinct CLDR pattern, so it is a style rather than a modifier, and it only + // exists alongside the symbol. `code` and `name` above therefore win over it. + default: return spec.currencySign == "accounting" ? .currencyAccounting : .currency + } + } + + /** + * ECMA-402's rule for resolving digit bounds, so the three implementations of this component + * round the same number to the same string. + * + * A bound that was left out is filled from the style, and a maximum below its minimum is + * clamped rather than rejected. `Intl` throws on that pair; a formatter that refuses to draw is + * worse than a number carrying one more decimal than was asked for. + */ + private static func bounds( + _ minimum: Int, + _ maximum: Int, + defaultMinimum: Int, + defaultMaximum: Int + ) -> (Int, Int) { + if minimum >= 0 && maximum >= 0 { return (minimum, max(minimum, maximum)) } + if minimum >= 0 { return (minimum, max(defaultMaximum, minimum)) } + if maximum >= 0 { return (min(defaultMinimum, maximum), maximum) } + return (defaultMinimum, defaultMaximum) } } diff --git a/ios/NumericTextView.mm b/ios/NumericTextView.mm index 4b6d53e..cc0a911 100644 --- a/ios/NumericTextView.mm +++ b/ios/NumericTextView.mm @@ -54,17 +54,28 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & // Every prop is forwarded on every update rather than diffed here. The SwiftUI side ignores an // unchanged value on its own — its animation is scoped to `value` — and a partial forward is how // a number ends up still drawn in the previous font after a style change. + // + // Formatting first: the value is drawn through it, so a change to both in one commit has to + // reach the formatter before it reaches the text. + [_host applyFormatWithLocale:RCTNSStringFromString(next.locale) + numberStyle:RCTNSStringFromString(next.numberStyle) + currency:RCTNSStringFromString(next.currency) + currencyDisplay:RCTNSStringFromString(next.currencyDisplay) + currencySign:RCTNSStringFromString(next.currencySign) + useGrouping:next.useGrouping + minimumIntegerDigits:next.minimumIntegerDigits + minimumFractionDigits:next.minimumFractionDigits + maximumFractionDigits:next.maximumFractionDigits + minimumSignificantDigits:next.minimumSignificantDigits + maximumSignificantDigits:next.maximumSignificantDigits]; + [_host applyValue:next.value - locale:RCTNSStringFromString(next.locale) - direction:RCTNSStringFromString(next.direction) - reduceMotion:RCTNSStringFromString(next.reduceMotion) - useGrouping:next.useGrouping - minimumFractionDigits:next.minimumFractionDigits - maximumFractionDigits:next.maximumFractionDigits - fontSize:next.fontSize - fontWeight:RCTNSStringFromString(next.fontWeight) - fontFamily:RCTNSStringFromString(next.fontFamily) - textColor:RCTUIColorFromSharedColor(next.textColor)]; + direction:RCTNSStringFromString(next.direction) + reduceMotion:RCTNSStringFromString(next.reduceMotion) + fontSize:next.fontSize + fontWeight:RCTNSStringFromString(next.fontWeight) + fontFamily:RCTNSStringFromString(next.fontFamily) + textColor:RCTUIColorFromSharedColor(next.textColor)]; [super updateProps:props oldProps:oldProps]; } diff --git a/src/NumericTextFallback.tsx b/src/NumericTextFallback.tsx index 2fdbf1f..9ac357d 100644 --- a/src/NumericTextFallback.tsx +++ b/src/NumericTextFallback.tsx @@ -1,5 +1,6 @@ import { memo } from 'react'; import { Text } from 'react-native'; +import { DEFAULT_LOCALE, formatNumber, resolveFormat } from './numberFormat'; import type { NumericTextProps } from './types'; /** @@ -9,20 +10,10 @@ import type { NumericTextProps } from './types'; * native path so snapshots and web renders keep the same number formatting; only the transition is * missing. */ -function NumericTextFallbackImpl({ - value, - locale = 'en-US', - minimumFractionDigits = 0, - maximumFractionDigits = 3, - useGrouping = true, - style, - testID, -}: NumericTextProps) { - const formatted = value.toLocaleString(locale, { - minimumFractionDigits, - maximumFractionDigits, - useGrouping, - }); +function NumericTextFallbackImpl(props: NumericTextProps) { + const { value, locale = DEFAULT_LOCALE, style, testID } = props; + const formatted = formatNumber(value, locale, resolveFormat(props)); + return ( {formatted} diff --git a/src/NumericTextView.native.tsx b/src/NumericTextView.native.tsx index c6beb2c..39cbbe4 100644 --- a/src/NumericTextView.native.tsx +++ b/src/NumericTextView.native.tsx @@ -1,6 +1,12 @@ import { memo, useEffect, useRef, useState } from 'react'; import NumericTextViewNativeComponent from './NumericTextViewNativeComponent'; import { measureBox, widest, type Box } from './measureBox'; +import { + DEFAULT_LOCALE, + formatNumber, + nativeFormatProps, + resolveFormat, +} from './numberFormat'; import { resolveTextStyle } from './resolveTextStyle'; import type { NumericTextProps } from './types'; @@ -16,26 +22,27 @@ import type { NumericTextProps } from './types'; * `animationDuration` reaches Android only; SwiftUI's numeric transition is a spring with no * duration to set. Both sides otherwise read the same props, including the text properties pulled * out of `style` — each renderer draws its own glyphs, so it needs them as props. + * + * Formatting is props too, not a finished string. The renderers animate the structure of a + * formatted number: which digit is which, where the decimal mark sits, which side the currency + * symbol is on. Each renderer therefore formats it natively, and JS only reproduces the result to + * size the box. */ -function NumericTextViewImpl({ - value, - locale = 'en-US', - direction = 'automatic', - animationDuration = 80, - reduceMotion = 'system', - minimumFractionDigits = 0, - maximumFractionDigits = 3, - useGrouping = true, - style, - testID, -}: NumericTextProps) { +function NumericTextViewImpl(props: NumericTextProps) { + const { + value, + locale = DEFAULT_LOCALE, + direction = 'automatic', + animationDuration = 80, + reduceMotion = 'system', + style, + testID, + } = props; + const text = resolveTextStyle(style); + const format = resolveFormat(props); - const formatted = value.toLocaleString(locale, { - minimumFractionDigits, - maximumFractionDigits, - useGrouping, - }); + const formatted = formatNumber(value, locale, format); const box = useShrinkHeldBox( measureBox(formatted, text.fontSize), Math.max(animationDuration, 500) + 400 @@ -47,10 +54,8 @@ function NumericTextViewImpl({ direction={direction} locale={locale} animationDuration={animationDuration} - useGrouping={useGrouping} - minimumFractionDigits={minimumFractionDigits} - maximumFractionDigits={maximumFractionDigits} reduceMotion={reduceMotion} + {...nativeFormatProps(format)} fontSize={text.fontSize} fontWeight={text.fontWeight} fontFamily={text.fontFamily} diff --git a/src/NumericTextViewNativeComponent.ts b/src/NumericTextViewNativeComponent.ts index 64cb8c3..059c514 100644 --- a/src/NumericTextViewNativeComponent.ts +++ b/src/NumericTextViewNativeComponent.ts @@ -10,10 +10,22 @@ interface NativeProps extends ViewProps { readonly direction?: string; readonly locale?: string; readonly animationDuration?: Double; + readonly reduceMotion?: string; + + // Formatting. Flat scalars rather than one object: this is the shape codegen carries well, and + // `src/numberFormat.ts` is where the `Intl`-shaped prop is resolved down to them. + readonly numberStyle?: string; + readonly currency?: string; + readonly currencyDisplay?: string; + readonly currencySign?: string; readonly useGrouping?: boolean; + /** A digit count, or -1 for "the format's own default"; see `DIGITS_UNSET`. */ + readonly minimumIntegerDigits?: Int32; readonly minimumFractionDigits?: Int32; readonly maximumFractionDigits?: Int32; - readonly reduceMotion?: string; + readonly minimumSignificantDigits?: Int32; + readonly maximumSignificantDigits?: Int32; + readonly fontSize?: Float; readonly fontWeight?: string; readonly fontFamily?: string; diff --git a/src/__tests__/measureBox.test.ts b/src/__tests__/measureBox.test.ts index 86e8e67..52211a1 100644 --- a/src/__tests__/measureBox.test.ts +++ b/src/__tests__/measureBox.test.ts @@ -24,6 +24,27 @@ describe('widthInEm', () => { expect(widthInEm('-1')).toBeGreaterThan(widthInEm('1')); expect(widthInEm('−1')).toBe(widthInEm('-1')); }); + + it('charges a currency symbol as a glyph rather than as punctuation', () => { + // `$` measures 0.6064 em in the bundled Regular and a comma 0.2541. Charging the first at the + // second's width under-reserves the box by most of a digit, which the headroom cannot absorb + // once a format carries several of them. + for (const symbol of ['$', '€', '£', '¥', '₹', '%']) { + expect(widthInEm(symbol)).toBeGreaterThan(widthInEm(',')); + } + }); + + it('charges the letters of a code or a name', () => { + expect(widthInEm('US dollars')).toBeGreaterThan(9 * widthInEm(',')); + }); + + it('keeps the spaces a locale groups with narrow', () => { + // fr-FR groups with a narrow no-break space and puts a no-break space before the symbol. + // Charging either as a glyph would reserve most of a digit for a gap. + for (const space of ['\u00a0', '\u2007', '\u2008', '\u2009', '\u202f']) { + expect(widthInEm(space)).toBe(widthInEm(',')); + } + }); }); describe('measureBox', () => { diff --git a/src/__tests__/numberFormat.test.ts b/src/__tests__/numberFormat.test.ts new file mode 100644 index 0000000..b456ddc --- /dev/null +++ b/src/__tests__/numberFormat.test.ts @@ -0,0 +1,166 @@ +import { describe, expect, it } from '@jest/globals'; +import { + DIGITS_UNSET, + formatNumber, + intlOptions, + nativeFormatProps, + resolveFormat, +} from '../numberFormat'; + +describe('resolveFormat', () => { + it('reads the currency shorthand as a currency style', () => { + expect(resolveFormat({ currency: 'USD' })).toEqual({ + style: 'currency', + currency: 'USD', + }); + }); + + it('lets format override the shorthands where they overlap', () => { + expect( + resolveFormat({ + currency: 'USD', + useGrouping: true, + format: { currency: 'EUR', useGrouping: false }, + }) + ).toEqual({ + style: 'currency', + currency: 'EUR', + useGrouping: false, + }); + }); + + it('leaves an absent prop absent rather than defaulting it', () => { + // The renderers need to tell "0 fraction digits" from "the currency's own count", so a prop + // nobody set must not arrive as a number. + expect(resolveFormat({})).toEqual({}); + }); +}); + +describe('formatNumber', () => { + it('formats a plain number to at most three decimals', () => { + expect(formatNumber(1234.5678, 'en-US', {})).toBe('1,234.568'); + }); + + it('takes the currencys own fraction digits when none were given', () => { + expect( + formatNumber(1234.5, 'en-US', resolveFormat({ currency: 'USD' })) + ).toBe('$1,234.50'); + expect( + formatNumber(1234.5, 'en-US', resolveFormat({ currency: 'JPY' })) + ).toBe('¥1,235'); + }); + + it('puts the symbol where the locale puts it', () => { + // Written escaped because the space before the symbol is a no-break one, which is exactly the + // kind of character the transition has to key on and a reader cannot see. + expect( + formatNumber(1234.5, 'de-DE', resolveFormat({ currency: 'EUR' })) + ).toBe('1.234,50\u00a0€'); + }); + + it('writes the currency as a code or a name on request', () => { + const currency = 'USD'; + expect( + formatNumber(1234.5, 'en-US', { + style: 'currency', + currency, + currencyDisplay: 'code', + }) + ).toBe('USD\u00a01,234.50'); + expect( + formatNumber(1234.5, 'en-US', { + style: 'currency', + currency, + currencyDisplay: 'name', + }) + ).toBe('1,234.50 US dollars'); + }); + + it('brackets a negative amount in the accounting sign', () => { + expect( + formatNumber(-1234.5, 'en-US', { + style: 'currency', + currency: 'USD', + currencySign: 'accounting', + }) + ).toBe('($1,234.50)'); + }); + + it('multiplies a percentage by a hundred and drops its decimals', () => { + expect(formatNumber(0.425, 'en-US', { style: 'percent' })).toBe('43%'); + }); + + it('pads to a minimum integer width', () => { + expect(formatNumber(9, 'en-US', { minimumIntegerDigits: 2 })).toBe('09'); + }); + + it('rounds a half away from zero, which is Intls rule and neither platforms', () => { + // Both native formatters are told to do the same. The three implementations disagreeing about + // whether 2.5 reads as 2 or 3 would be a bug, so it is not left to each platform's default. + expect(formatNumber(2.5, 'en-US', { maximumFractionDigits: 0 })).toBe('3'); + expect(formatNumber(-2.5, 'en-US', { maximumFractionDigits: 0 })).toBe( + '-3' + ); + }); + + it('falls back to a plain number rather than throwing on an unknown currency', () => { + expect( + formatNumber(12, 'en-US', { style: 'currency', currency: 'NOPE' }) + ).toBe('12'); + }); + + it('treats a currency style with no code as a plain number', () => { + // Intl throws on this pair. The renderers cannot, so all three agree to ignore it. + expect(formatNumber(1234.5, 'en-US', { style: 'currency' })).toBe( + '1,234.5' + ); + }); +}); + +describe('intlOptions', () => { + it('never asks for a maximum below its minimum', () => { + // Intl throws on that pair; the native formatters clamp. Clamping here keeps a bad prop from + // taking a render down. + const options = intlOptions({ + minimumFractionDigits: 4, + maximumFractionDigits: 1, + }); + expect(options.maximumFractionDigits).toBe(4); + expect(() => (1).toLocaleString('en-US', options)).not.toThrow(); + }); + + it('passes a bound through untouched so Intl applies its own default to the other', () => { + expect(intlOptions({ maximumFractionDigits: 1 })).not.toHaveProperty( + 'minimumFractionDigits' + ); + }); +}); + +describe('nativeFormatProps', () => { + it('marks an absent bound so the renderer can apply the same default', () => { + expect(nativeFormatProps({})).toEqual({ + numberStyle: 'decimal', + currency: '', + currencyDisplay: 'symbol', + currencySign: 'standard', + useGrouping: true, + minimumIntegerDigits: DIGITS_UNSET, + minimumFractionDigits: DIGITS_UNSET, + maximumFractionDigits: DIGITS_UNSET, + minimumSignificantDigits: DIGITS_UNSET, + maximumSignificantDigits: DIGITS_UNSET, + }); + }); + + it('carries a currency down as flat scalars', () => { + const props = nativeFormatProps(resolveFormat({ currency: 'EUR' })); + expect(props.numberStyle).toBe('currency'); + expect(props.currency).toBe('EUR'); + }); + + it('drops a currency style that has no code, as the formatters do', () => { + const props = nativeFormatProps({ style: 'currency' }); + expect(props.numberStyle).toBe('decimal'); + expect(props.currency).toBe(''); + }); +}); diff --git a/src/index.tsx b/src/index.tsx index 2c8e758..cd89bb1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,4 +1,4 @@ export { NumericTextView } from './NumericTextView'; /** Preferred name. `NumericTextView` is the same component, kept for the original import path. */ export { NumericTextView as NumericText } from './NumericTextView'; -export type { NumericTextProps } from './types'; +export type { NumericTextFormat, NumericTextProps } from './types'; diff --git a/src/measureBox.ts b/src/measureBox.ts index e6e494e..d1488b2 100644 --- a/src/measureBox.ts +++ b/src/measureBox.ts @@ -8,7 +8,9 @@ * * The estimate is per character rather than a flat average because the bundled font's tabular * digits and its separators differ by more than a factor of two, and a four-digit grouped number - * is a quarter separator by character count. + * is a quarter separator by character count. Once a number can carry a currency (`$1,234.56`, + * `1.234,56 €`, `1,234.56 US dollars`) the spread is wider still, so symbols and letters are + * charged separately from punctuation rather than being lumped in with the comma. */ /** Advance widths as a fraction of font size, from the bundled Sunghyun Sans with `tnum` on. */ @@ -16,6 +18,16 @@ const DIGIT_EM = 0.6167; const SEPARATOR_EM = 0.2541; const SIGN_EM = 0.36; +/** + * Currency symbols, the percent sign, and the letters of an ISO code or a currency name. + * + * One estimate covers all of them because they land close together in this face and because the + * box is a minimum with headroom on top: `$` measures near a digit, `%` slightly wider, and a + * lower-case letter narrower. Over-charging a letter costs a few pixels of reserved width; + * under-charging one clips `US dollars`. + */ +const GLYPH_EM = 0.62; + /** Room for the transition's own overspill: a dying glyph drifts outward and carries a blur halo. */ const HEADROOM_EM = 0.5; @@ -36,11 +48,44 @@ export function widthInEm(formatted: string): number { for (const ch of formatted) { if (ch >= '0' && ch <= '9') em += DIGIT_EM; else if (ch === '-' || ch === '−' || ch === '+') em += SIGN_EM; - else em += SEPARATOR_EM; + else if (isNarrow(ch)) em += SEPARATOR_EM; + else em += GLYPH_EM; } return em; } +/** + * Whether [ch] is punctuation or a space rather than something with ink to spare. + * + * The separators a formatter emits are few and known: the comma, the stop, the apostrophe forms, + * the middle dot, the Arabic marks, and the several fixed-width spaces a French or Swiss locale + * groups with. They are therefore listed rather than derived. Anything else in a formatted number is a + * digit, a sign, or a symbol or letter that carries a currency, and those are charged as glyphs. + */ +function isNarrow(ch: string): boolean { + return NARROW.has(ch); +} + +const NARROW = new Set([ + ',', + '.', + "'", + '’', // right single quote, the Swiss grouping separator + '·', // middle dot + '٫', // Arabic decimal separator + '٬', // Arabic thousands separator + ',', // fullwidth comma + '.', // fullwidth stop + '(', + ')', + ' ', + ' ', // no-break space + ' ', // figure space + ' ', // punctuation space + ' ', // thin space + ' ', // narrow no-break space +]); + export function measureBox( formatted: string, fontSize: number | undefined diff --git a/src/numberFormat.ts b/src/numberFormat.ts new file mode 100644 index 0000000..6610443 --- /dev/null +++ b/src/numberFormat.ts @@ -0,0 +1,199 @@ +import type { NumericTextFormat, NumericTextProps } from './types'; + +/** + * One description of "what this number should read as", shared by the three places that have to + * agree on it: the web fallback, the JS width estimate, and the props handed to the native + * renderers. + * + * The native renderers do the real formatting, because the string that is drawn has to be + * produced where it is drawn: the transition animates the structure of a formatted number, not a + * string handed over ready-made. But the layout box is estimated in JS from a string JS formats + * itself, so the two must resolve the same options from the same props. Everything that decides + * the shape of the number therefore lives here rather than being spelled out again per platform. + */ + +/** + * The value a digit bound carries to native when the caller did not give one. + * + * A bound is a digit count, so it is never negative and -1 cannot be mistaken for a real one. The + * renderer needs the difference: "0 fraction digits" and "however many this currency uses" are + * different instructions, and an absent prop means the second. + */ +export const DIGITS_UNSET = -1; + +export const DEFAULT_LOCALE = 'en-US'; + +/** The props that describe the number rather than the motion or the typography. */ +type FormatProps = Pick< + NumericTextProps, + | 'format' + | 'currency' + | 'useGrouping' + | 'minimumFractionDigits' + | 'maximumFractionDigits' +>; + +/** The flat scalars the native prop surface carries. `Intl` shapes are not codegen shapes. */ +export type NativeFormatProps = { + numberStyle: string; + currency: string; + currencyDisplay: string; + currencySign: string; + useGrouping: boolean; + minimumIntegerDigits: number; + minimumFractionDigits: number; + maximumFractionDigits: number; + minimumSignificantDigits: number; + maximumSignificantDigits: number; +}; + +/** + * The single format the whole component works from. + * + * The top-level shorthands are folded in first and [FormatProps.format] is laid over them, so a + * component can say `currency="USD"` for the common case and still reach for the full options + * object without the two contradicting each other. + */ +export function resolveFormat(props: FormatProps): NumericTextFormat { + const { + format, + currency, + useGrouping, + minimumFractionDigits, + maximumFractionDigits, + } = props; + + const shorthand: NumericTextFormat = {}; + if (currency !== undefined) { + shorthand.style = 'currency'; + shorthand.currency = currency; + } + if (useGrouping !== undefined) shorthand.useGrouping = useGrouping; + if (minimumFractionDigits !== undefined) { + shorthand.minimumFractionDigits = minimumFractionDigits; + } + if (maximumFractionDigits !== undefined) { + shorthand.maximumFractionDigits = maximumFractionDigits; + } + + return format ? { ...shorthand, ...format } : shorthand; +} + +/** + * Whether [format] asks for money. + * + * `style: 'currency'` without a code is not money, it is a mistake. `Intl` throws on it; the + * renderers cannot, so both they and this treat it as a plain number. + */ +function isCurrency(format: NumericTextFormat): boolean { + return format.style === 'currency' && !!format.currency; +} + +/** + * [format] as `Intl.NumberFormat` options. + * + * A digit bound is passed through rather than defaulted, so `Intl` applies its own rule: 0..3 + * digits for a plain number, 0 for a percentage, and the currency's own count for money. Both + * native renderers implement that same rule, which is what keeps a JS-measured box the size of a + * natively drawn number. + * + * The one thing not passed through is a maximum below its minimum. `Intl` throws on that pair; + * the native formatters silently clamp, and a formatter that throws inside a render is worse than + * a number carrying one more decimal than was asked for. + */ +export function intlOptions( + format: NumericTextFormat +): Intl.NumberFormatOptions { + const options: Intl.NumberFormatOptions = { + useGrouping: format.useGrouping ?? true, + }; + + if (isCurrency(format)) { + options.style = 'currency'; + options.currency = format.currency; + options.currencyDisplay = format.currencyDisplay ?? 'symbol'; + options.currencySign = format.currencySign ?? 'standard'; + } else if (format.style === 'percent') { + options.style = 'percent'; + } + + if (format.minimumIntegerDigits !== undefined) { + options.minimumIntegerDigits = format.minimumIntegerDigits; + } + + assignBounds( + options, + 'minimumSignificantDigits', + 'maximumSignificantDigits', + format.minimumSignificantDigits, + format.maximumSignificantDigits + ); + assignBounds( + options, + 'minimumFractionDigits', + 'maximumFractionDigits', + format.minimumFractionDigits, + format.maximumFractionDigits + ); + + return options; +} + +function assignBounds( + options: Intl.NumberFormatOptions, + minKey: 'minimumFractionDigits' | 'minimumSignificantDigits', + maxKey: 'maximumFractionDigits' | 'maximumSignificantDigits', + min: number | undefined, + max: number | undefined +): void { + if (min !== undefined) options[minKey] = min; + if (max !== undefined) { + options[maxKey] = min === undefined ? max : Math.max(min, max); + } +} + +/** + * [format] as the flat props the native renderers read. Absent bounds become [DIGITS_UNSET] so + * each platform can apply the same default rule rather than being handed a guess made in JS. + */ +export function nativeFormatProps( + format: NumericTextFormat +): NativeFormatProps { + const currency = isCurrency(format); + return { + numberStyle: currency + ? 'currency' + : format.style === 'percent' + ? 'percent' + : 'decimal', + currency: currency ? format.currency! : '', + currencyDisplay: format.currencyDisplay ?? 'symbol', + currencySign: format.currencySign ?? 'standard', + useGrouping: format.useGrouping ?? true, + minimumIntegerDigits: format.minimumIntegerDigits ?? DIGITS_UNSET, + minimumFractionDigits: format.minimumFractionDigits ?? DIGITS_UNSET, + maximumFractionDigits: format.maximumFractionDigits ?? DIGITS_UNSET, + minimumSignificantDigits: format.minimumSignificantDigits ?? DIGITS_UNSET, + maximumSignificantDigits: format.maximumSignificantDigits ?? DIGITS_UNSET, + }; +} + +/** + * [value] as the number the renderer will draw. + * + * Falls back to plain formatting when the options are rejected, which happens for an unknown + * currency code and on a JS engine built without the full `Intl` data. Neither is worth throwing + * out of a render: the native side formats the number that is actually shown, and this string + * only has to be close enough to size the box. + */ +export function formatNumber( + value: number, + locale: string, + format: NumericTextFormat +): string { + try { + return value.toLocaleString(locale, intlOptions(format)); + } catch { + return value.toLocaleString(locale); + } +} diff --git a/src/types.ts b/src/types.ts index 87ca465..f03d91f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,82 @@ import type { StyleProp, TextStyle } from 'react-native'; +/** + * How to turn the value into the number that is drawn: a subset of `Intl.NumberFormatOptions`, + * resolved natively by `NumberFormatter` on iOS and `android.icu` on Android. + * + * It is a subset because every option here has to mean the same thing on both platforms at the + * versions this library supports, and has to survive being animated: the renderers transition the + * *structure* of a formatted number, so the string has to be produced where it is drawn rather + * than passed in ready-made. + * + * Left out on purpose, and why: + * + * - `notation: 'compact'` (`1.2K`). Both platforms can produce it, but from different CLDR + * vintages, so the two would disagree on the string for the same input. + * - `signDisplay`, `roundingIncrement`, `unit`. Neither platform exposes them below its floor + * (Android's `NumberFormatter` is API 30, and `NumberFormatter` on iOS has no equivalent). + * - `currencyDisplay: 'narrowSymbol'`. Same reason. + * + * Rounding is fixed at half-away-from-zero on both platforms, which is `Intl`'s own default and + * neither platform's. It is not an option because the two renderers disagreeing about whether + * `2.5` reads as `2` or `3` is a bug, not a preference. + */ +export type NumericTextFormat = { + /** + * `'currency'` needs [currency] set and falls back to `'decimal'` without it. `'percent'` + * multiplies by 100 and appends the locale's percent sign, so `0.42` reads as `42%`. + */ + style?: 'decimal' | 'currency' | 'percent'; + + /** + * ISO 4217 code (`'USD'`, `'EUR'`, `'JPY'`). The symbol, which side of the number it sits on, + * the space around it, and the currency's own fraction digits all come from the platform's + * locale data: `'en-US'` gives `$1,234.56` and `'de-DE'` gives `1.234,56 €`. + */ + currency?: string; + + /** + * How to write the currency: its symbol (`$1,234.56`), its ISO code (`USD 1,234.56`), or its + * name in the locale (`1,234.56 US dollars`). + */ + currencyDisplay?: 'symbol' | 'code' | 'name'; + + /** + * How to write a negative amount. `'accounting'` uses the locale's accounting form, which in + * most locales means parentheses: `($1,234.56)` rather than `-$1,234.56`. Applied only with + * `currencyDisplay: 'symbol'`, the one combination both platforms format natively. + */ + currencySign?: 'standard' | 'accounting'; + + /** Group separators (`1,000` vs `1000`). */ + useGrouping?: boolean; + + /** + * Pads with leading zeros to at least this many integer digits, which is what holds a clock at + * `05:09` and stops a counter changing width as it crosses a power of ten. + */ + minimumIntegerDigits?: number; + + /** + * How many digits to keep after the decimal mark. Left out, a plain number rounds to between 0 + * and 3, a percentage to 0, and an amount of money takes the currency's own count: 2 for + * `'USD'`, 0 for `'JPY'`, 3 for `'BHD'`. + * + * Set [minimumFractionDigits] to hold a fixed number of decimals through a change that would + * otherwise drop one. That is what keeps `1.50` from reading as `1.5`, and what stops the + * fraction columns restructuring under a roll that should only have moved digits. + */ + minimumFractionDigits?: number; + maximumFractionDigits?: number; + + /** + * Round to a number of significant digits instead of a number of decimals. Setting either bound + * takes precedence over the fraction bounds, matching `Intl`. + */ + minimumSignificantDigits?: number; + maximumSignificantDigits?: number; +}; + /** * A number that animates between values the way SwiftUI's * `.contentTransition(.numericText())` does: each digit column rolls on its own spring, digits @@ -17,6 +94,18 @@ export type NumericTextProps = { */ locale?: string; + /** + * Everything about the shape of the number: currency, percent, grouping, digit bounds. See + * [NumericTextFormat]. + */ + format?: NumericTextFormat; + + /** + * Shorthand for `format={{ style: 'currency', currency }}`, which is the common case: + * ``. [format] overrides it where the two overlap. + */ + currency?: string; + /** * Which way digits roll. `'automatic'` rolls up when the value grows and down when it shrinks, * which is what SwiftUI does; the other two force a direction regardless of the value. @@ -36,10 +125,11 @@ export type NumericTextProps = { */ reduceMotion?: 'system' | 'always' | 'never'; + /** Shorthand for the same field of [format]. */ minimumFractionDigits?: number; + /** Shorthand for the same field of [format]. */ maximumFractionDigits?: number; - - /** Group separators (`1,000` vs `1000`). */ + /** Shorthand for the same field of [format]. */ useGrouping?: boolean; /** From 95a4141a2afad1778fff270fb9a4287c34cd679c Mon Sep 17 00:00:00 2001 From: Anurag Bevinal Date: Fri, 14 Aug 2026 14:26:07 +0530 Subject: [PATCH 4/5] docs: credit number-flow for the format prop shape The `format` prop takes its shape from number-flow (https://github.com/barvian/number-flow) by Maxwell Barvian: one object shaped like `Intl.NumberFormatOptions` rather than a growing row of flat props, and a bound passed through untouched so `Intl`'s own defaulting rule decides the rest. Credited in the Origin section, beside the prop in the formatting section, and in the doc comment on `NumericTextFormat` itself. --- README.md | 8 +++++++- src/types.ts | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e950cb9..e6ad6c5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,11 @@ The platform strategy is intentionally asymmetric: The goal is not to pretend both platforms render text identically. The goal is to give the same React Native component the same class of polished numeric interaction on both platforms. -This project is independent and is not affiliated with Expo or Apple. +The formatting API is a second borrowed idea. [`number-flow`](https://github.com/barvian/number-flow) by Maxwell Barvian solves the same problem on the web, and its answer to "how should a component be told what shape a number takes" is one `format` object shaped like `Intl.NumberFormatOptions` rather than a growing row of flat props. That shape is taken from it directly, including the choice to pass a bound through untouched so `Intl`'s own defaulting rule decides the rest. + +The two libraries reach it from opposite ends: `number-flow` renders real text nodes and lets the browser lay them out, so it inherits `Intl` for free; here the string has to be produced natively on each platform, by `NumberFormatter` and `android.icu`, because the renderers animate the structure of a formatted number rather than a string handed to them. The API is the same either way, which is the point of copying it. + +This project is independent and is not affiliated with Expo, Apple, or `number-flow`. ## Why numeric text needs its own transition model @@ -132,6 +136,8 @@ This keeps locale-specific punctuation structurally associated with the digits w The `format` prop is a subset of `Intl.NumberFormatOptions`, and each platform resolves it with its own formatter: `NumberFormatter` on iOS, `android.icu` on Android, `Intl` on web. The string is produced where it is drawn, because the renderer animates the structure of a formatted number rather than a string handed to it ready-made. +The shape of this prop is borrowed from [`number-flow`](https://github.com/barvian/number-flow); see [Origin](#origin). + `format` is an object, so `NumericText` will re-render whenever the parent does unless you keep it stable. Hoist it to module scope or wrap it in `useMemo` if you rely on the memo skipping renders. ### Currency diff --git a/src/types.ts b/src/types.ts index f03d91f..ddc45c9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,6 +4,11 @@ import type { StyleProp, TextStyle } from 'react-native'; * How to turn the value into the number that is drawn: a subset of `Intl.NumberFormatOptions`, * resolved natively by `NumberFormatter` on iOS and `android.icu` on Android. * + * The shape is taken from `number-flow` (https://github.com/barvian/number-flow), which answers + * the same question on the web with one `format` object rather than a growing row of flat props. + * Borrowed with it: passing a bound through untouched so `Intl`'s own defaulting rule decides the + * rest, instead of guessing a default here and handing each platform a number it did not ask for. + * * It is a subset because every option here has to mean the same thing on both platforms at the * versions this library supports, and has to survive being animated: the renderers transition the * *structure* of a formatted number, so the string has to be produced where it is drawn rather From cc78100d2d89007f7eb84a30e881f677dea0c44d Mon Sep 17 00:00:00 2001 From: Anurag Bevinal Date: Fri, 14 Aug 2026 15:24:27 +0530 Subject: [PATCH 5/5] feat: hold the decimal mark while a fraction digit is still being typed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `value` is a number and a number cannot hold `7.`, so someone typing 7 . 5 produces the values 7, 7, 7.5 and the mark they typed has nowhere to live between the second and third keystroke. `trailingDecimalSeparator` gives it one. The mark becomes a real column: the locale's own character, drawn by the same typesetter, keyed as `DEC`, and already in place when the first fraction digit is born beside it. It goes after the last digit rather than at the end of the string, so `de-DE` gives `1.234, €` rather than `1.234 €,`. It is a no-op once a fraction digit arrives and when the format already prints a mark, so pairing it with `minimumFractionDigits` is safe. The workaround it replaces is a sibling `` holding a `.`, which cannot be made to line up: the view reserves half an em of headroom for the transition's overspill and centres the number inside it, so the distance from the last digit to the right edge is not fixed and moves with both the value and the font. Measured on an emulator at fontSize 44: the number occupied x 0.391-0.578 of the screen and the sibling dot sat at 0.577-0.608 on a different baseline. With the prop the same state renders as one view whose accessibility label reads `$0.` rather than `$0`. 7 new JS cases; 46 JS and 25 Kotlin tests pass, compileDebugKotlin and swiftc -typecheck clean, and the before/after was compared on a device. --- README.md | 21 ++++++++ .../com/numerictext/NumericTextFormatter.kt | 26 +++++++++- .../java/com/numerictext/NumericTextView.kt | 3 ++ .../com/numerictext/NumericTextViewManager.kt | 5 ++ ios/NumericTextSwiftUIHost.swift | 44 ++++++++++++++-- ios/NumericTextView.mm | 3 +- src/NumericTextFallback.tsx | 15 +++++- src/NumericTextView.native.tsx | 9 +++- src/NumericTextViewNativeComponent.ts | 1 + src/__tests__/numberFormat.test.ts | 44 ++++++++++++++++ src/numberFormat.ts | 52 ++++++++++++++++++- src/types.ts | 24 +++++++++ 12 files changed, 236 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e6ad6c5..acca0f9 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,26 @@ Set `minimumFractionDigits` to hold a fixed number of decimals through a change ``` +### Amount fields, and the decimal you are still typing + +`value` is a number, and a number cannot hold `7.`. Someone typing `7`, `.`, `5` produces the values 7, 7, 7.5, so between the second and third keystroke the mark they typed has nowhere to live. `trailingDecimalSeparator` gives it one: + +```tsx +const [raw, setRaw] = useState(''); + + +``` + +The mark becomes a real column: the locale's own character, the same font, the same baseline, keyed as `DEC`, and already in place when the first fraction digit is born beside it. It is a no-op once a fraction digit arrives or when the format already prints a mark, so pairing it with `minimumFractionDigits` is safe. It goes after the last digit rather than at the end of the string, so `de-DE` gives `1.234, €` and not `1.234 €,`. + +Do not reach for a sibling `` holding a `.` instead. It cannot be made to line up: this view reserves half an em of headroom for the transition's overspill and centres the number inside it, so the distance from the last digit to the right edge of the view is not fixed, and it moves with the value and with the font. + +### Rounding + Rounding is half-away-from-zero on both platforms and on web: `2.5` at zero decimals reads as `3` everywhere. That is `Intl`'s default and neither platform's (`NumberFormatter` and ICU both round half-to-even left alone), so it is set explicitly rather than exposed as an option. Two renderers disagreeing about the number they draw is a bug, not a preference. ## Direction @@ -224,6 +244,7 @@ During rapid updates, automatic direction is resolved against the value the rend | `locale` | `string` | `'en-US'` | BCP-47 locale used for native number formatting. | | `format` | `NumericTextFormat` | `{}` | How to shape the number. See below. | | `currency` | `string` | none | Shorthand for `format={{ style: 'currency', currency }}`. `format` wins where the two overlap. | +| `trailingDecimalSeparator` | `boolean` | `false` | Draws the decimal mark after the last digit when no fraction digit follows it yet. For amount fields; see above. | | `direction` | `'automatic' \| 'up' \| 'down'` | `'automatic'` | Direction of the numeric transition. | | `animationDuration` | `number` | `80` | Android only. Nominal timing input used to scale the native transition; it is not a hard duration clamp. | | `reduceMotion` | `'system' \| 'always' \| 'never'` | `'system'` | Accessibility behaviour for motion. | diff --git a/android/src/main/java/com/numerictext/NumericTextFormatter.kt b/android/src/main/java/com/numerictext/NumericTextFormatter.kt index 16e8ea0..665ed8f 100644 --- a/android/src/main/java/com/numerictext/NumericTextFormatter.kt +++ b/android/src/main/java/com/numerictext/NumericTextFormatter.kt @@ -28,6 +28,7 @@ internal data class NumericFormatSpec( val maximumFractionDigits: Int = DIGITS_UNSET, val minimumSignificantDigits: Int = DIGITS_UNSET, val maximumSignificantDigits: Int = DIGITS_UNSET, + val trailingDecimalSeparator: Boolean = false, ) /** @@ -45,6 +46,7 @@ internal data class NumericFormatSpec( */ internal class NumericTextFormatter private constructor( private val format: NumberFormat, + private val trailing: Boolean, val groupingSeparator: Char, val decimalSeparator: Char, val minusSign: Char, @@ -56,7 +58,28 @@ internal class NumericTextFormatter private constructor( val glyphProbe: String, ) { - fun format(value: Double): String = format.format(value) + /** + * The formatted number, with the decimal mark held after the last digit when the caller asked + * for it and the format produced none. + * + * After the last *digit*, not at the end of the string: `de-DE` writes `1.234 €`, and a mark + * appended blindly would land beyond the currency symbol. + */ + fun format(value: Double): String { + val text = format.format(value) + if (!trailing || text.indexOf(decimalSeparator) >= 0) return text + + var end = -1 + var i = 0 + while (i < text.length) { + val cp = text.codePointAt(i) + val width = Character.charCount(cp) + if (Character.isDigit(cp)) end = i + width + i += width + } + return if (end < 0) text + decimalSeparator + else text.substring(0, end) + decimalSeparator + text.substring(end) + } companion object { fun of(spec: NumericFormatSpec): NumericTextFormatter { @@ -81,6 +104,7 @@ internal class NumericTextFormatter private constructor( val symbols = symbolsOf(format, locale) return NumericTextFormatter( format = format, + trailing = spec.trailingDecimalSeparator, groupingSeparator = if (money) symbols.monetaryGroupingSeparator else symbols.groupingSeparator, decimalSeparator = diff --git a/android/src/main/java/com/numerictext/NumericTextView.kt b/android/src/main/java/com/numerictext/NumericTextView.kt index 53ac03f..f4a80ec 100644 --- a/android/src/main/java/com/numerictext/NumericTextView.kt +++ b/android/src/main/java/com/numerictext/NumericTextView.kt @@ -684,6 +684,9 @@ class NumericTextView(context: Context) : View(context), Choreographer.FrameCall fun setCurrencySign(value: String) = updateFormat { it.copy(currencySign = value) } fun setUseGrouping(value: Boolean) = updateFormat { it.copy(useGrouping = value) } + fun setTrailingDecimalSeparator(value: Boolean) = + updateFormat { it.copy(trailingDecimalSeparator = value) } + fun setMinimumIntegerDigits(value: Int) = updateFormat { it.copy(minimumIntegerDigits = value) } diff --git a/android/src/main/java/com/numerictext/NumericTextViewManager.kt b/android/src/main/java/com/numerictext/NumericTextViewManager.kt index 3c19aae..3ae6b7f 100644 --- a/android/src/main/java/com/numerictext/NumericTextViewManager.kt +++ b/android/src/main/java/com/numerictext/NumericTextViewManager.kt @@ -75,6 +75,11 @@ class NumericTextViewManager : SimpleViewManager(), view?.setUseGrouping(value) } + @ReactProp(name = "trailingDecimalSeparator") + override fun setTrailingDecimalSeparator(view: NumericTextView?, value: Boolean) { + view?.setTrailingDecimalSeparator(value) + } + @ReactProp(name = "minimumIntegerDigits") override fun setMinimumIntegerDigits(view: NumericTextView?, value: Int) { view?.setMinimumIntegerDigits(value) diff --git a/ios/NumericTextSwiftUIHost.swift b/ios/NumericTextSwiftUIHost.swift index da885cf..fb429c3 100644 --- a/ios/NumericTextSwiftUIHost.swift +++ b/ios/NumericTextSwiftUIHost.swift @@ -67,7 +67,7 @@ public final class NumericTextSwiftUIHost: UIView { * everything the component exposes, and Objective-C spells every argument out. */ // swiftlint:disable:next function_parameter_count - @objc(applyFormatWithLocale:numberStyle:currency:currencyDisplay:currencySign:useGrouping:minimumIntegerDigits:minimumFractionDigits:maximumFractionDigits:minimumSignificantDigits:maximumSignificantDigits:) + @objc(applyFormatWithLocale:numberStyle:currency:currencyDisplay:currencySign:useGrouping:minimumIntegerDigits:minimumFractionDigits:maximumFractionDigits:minimumSignificantDigits:maximumSignificantDigits:trailingDecimalSeparator:) public func applyFormat( locale: String, numberStyle: String, @@ -79,7 +79,8 @@ public final class NumericTextSwiftUIHost: UIView { minimumFractionDigits: Int, maximumFractionDigits: Int, minimumSignificantDigits: Int, - maximumSignificantDigits: Int + maximumSignificantDigits: Int, + trailingDecimalSeparator: Bool ) { let next = FormatSpec( locale: locale, @@ -92,7 +93,8 @@ public final class NumericTextSwiftUIHost: UIView { minimumFractionDigits: minimumFractionDigits, maximumFractionDigits: maximumFractionDigits, minimumSignificantDigits: minimumSignificantDigits, - maximumSignificantDigits: maximumSignificantDigits + maximumSignificantDigits: maximumSignificantDigits, + trailingDecimalSeparator: trailingDecimalSeparator ) guard next != formatSpec else { return } formatSpec = next @@ -110,7 +112,11 @@ public final class NumericTextSwiftUIHost: UIView { fontFamily: String?, textColor: UIColor? ) { - model.text = formatter.string(from: NSNumber(value: value)) ?? String(value) + model.text = Self.text( + value, + formatter: formatter, + trailingDecimalSeparator: formatSpec.trailingDecimalSeparator + ) model.fontSize = fontSize > 0 ? fontSize : 48 model.weight = Self.weight(from: fontWeight) model.fontFamily = fontFamily @@ -203,6 +209,36 @@ public final class NumericTextSwiftUIHost: UIView { var maximumFractionDigits: Int = -1 var minimumSignificantDigits: Int = -1 var maximumSignificantDigits: Int = -1 + var trailingDecimalSeparator: Bool = false + } + + /** + * The formatted number, with the decimal mark held after the last digit when the caller asked + * for it and the format produced none. + * + * After the last *digit*, not at the end of the string: `de-DE` writes `1.234 €`, and a mark + * appended blindly would land beyond the currency symbol. + */ + private static func text( + _ value: Double, + formatter: NumberFormatter, + trailingDecimalSeparator: Bool + ) -> String { + let formatted = formatter.string(from: NSNumber(value: value)) ?? String(value) + guard trailingDecimalSeparator else { return formatted } + + // A currency format may use a different mark from a plain number in the same locale, so ask + // the formatter for the one belonging to the style it is actually in. + let money = formatter.numberStyle != .decimal && formatter.numberStyle != .percent + let mark = + (money ? formatter.currencyDecimalSeparator : formatter.decimalSeparator) ?? "." + guard !formatted.contains(mark) else { return formatted } + + guard let lastDigit = formatted.lastIndex(where: { $0.isNumber }) else { + return formatted + mark + } + let after = formatted.index(after: lastDigit) + return String(formatted[.. NumberFormatter { diff --git a/ios/NumericTextView.mm b/ios/NumericTextView.mm index cc0a911..35a35f6 100644 --- a/ios/NumericTextView.mm +++ b/ios/NumericTextView.mm @@ -67,7 +67,8 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & minimumFractionDigits:next.minimumFractionDigits maximumFractionDigits:next.maximumFractionDigits minimumSignificantDigits:next.minimumSignificantDigits - maximumSignificantDigits:next.maximumSignificantDigits]; + maximumSignificantDigits:next.maximumSignificantDigits + trailingDecimalSeparator:next.trailingDecimalSeparator]; [_host applyValue:next.value direction:RCTNSStringFromString(next.direction) diff --git a/src/NumericTextFallback.tsx b/src/NumericTextFallback.tsx index 9ac357d..d788096 100644 --- a/src/NumericTextFallback.tsx +++ b/src/NumericTextFallback.tsx @@ -11,8 +11,19 @@ import type { NumericTextProps } from './types'; * missing. */ function NumericTextFallbackImpl(props: NumericTextProps) { - const { value, locale = DEFAULT_LOCALE, style, testID } = props; - const formatted = formatNumber(value, locale, resolveFormat(props)); + const { + value, + locale = DEFAULT_LOCALE, + trailingDecimalSeparator = false, + style, + testID, + } = props; + const formatted = formatNumber( + value, + locale, + resolveFormat(props), + trailingDecimalSeparator + ); return ( diff --git a/src/NumericTextView.native.tsx b/src/NumericTextView.native.tsx index 39cbbe4..33aeae0 100644 --- a/src/NumericTextView.native.tsx +++ b/src/NumericTextView.native.tsx @@ -35,6 +35,7 @@ function NumericTextViewImpl(props: NumericTextProps) { direction = 'automatic', animationDuration = 80, reduceMotion = 'system', + trailingDecimalSeparator = false, style, testID, } = props; @@ -42,7 +43,12 @@ function NumericTextViewImpl(props: NumericTextProps) { const text = resolveTextStyle(style); const format = resolveFormat(props); - const formatted = formatNumber(value, locale, format); + const formatted = formatNumber( + value, + locale, + format, + trailingDecimalSeparator + ); const box = useShrinkHeldBox( measureBox(formatted, text.fontSize), Math.max(animationDuration, 500) + 400 @@ -56,6 +62,7 @@ function NumericTextViewImpl(props: NumericTextProps) { animationDuration={animationDuration} reduceMotion={reduceMotion} {...nativeFormatProps(format)} + trailingDecimalSeparator={trailingDecimalSeparator} fontSize={text.fontSize} fontWeight={text.fontWeight} fontFamily={text.fontFamily} diff --git a/src/NumericTextViewNativeComponent.ts b/src/NumericTextViewNativeComponent.ts index 059c514..5d39458 100644 --- a/src/NumericTextViewNativeComponent.ts +++ b/src/NumericTextViewNativeComponent.ts @@ -19,6 +19,7 @@ interface NativeProps extends ViewProps { readonly currencyDisplay?: string; readonly currencySign?: string; readonly useGrouping?: boolean; + readonly trailingDecimalSeparator?: boolean; /** A digit count, or -1 for "the format's own default"; see `DIGITS_UNSET`. */ readonly minimumIntegerDigits?: Int32; readonly minimumFractionDigits?: Int32; diff --git a/src/__tests__/numberFormat.test.ts b/src/__tests__/numberFormat.test.ts index b456ddc..4b51f1f 100644 --- a/src/__tests__/numberFormat.test.ts +++ b/src/__tests__/numberFormat.test.ts @@ -117,6 +117,50 @@ describe('formatNumber', () => { }); }); +describe('formatNumber, trailing decimal separator', () => { + // `value` is a number and a number cannot hold `7.`, so typing 7 . 5 produces 7, 7, 7.5. The + // flag is what gives the mark somewhere to live between the second and third keystroke. + it('holds the mark after the last digit when nothing follows it yet', () => { + expect(formatNumber(7, 'en-US', {}, true)).toBe('7.'); + }); + + it('is a no-op once a fraction digit arrives', () => { + expect(formatNumber(7.5, 'en-US', {}, true)).toBe('7.5'); + }); + + it('is a no-op when the format already prints a mark', () => { + const fixed = { minimumFractionDigits: 2, maximumFractionDigits: 2 }; + expect(formatNumber(7, 'en-US', fixed, true)).toBe('7.00'); + }); + + it('uses the locale mark, not a full stop', () => { + expect(formatNumber(1234, 'de-DE', {}, true)).toBe('1.234,'); + }); + + it('goes after the last digit rather than at the end of the string', () => { + // de-DE writes the symbol last. Appending blindly would put the mark beyond the euro sign. + const euro = resolveFormat({ currency: 'EUR' }); + const zeroDecimals = { + ...euro, + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; + expect(formatNumber(1234, 'de-DE', zeroDecimals, true)).toBe('1.234, €'); + }); + + it('keeps a leading currency symbol outside the mark', () => { + const usd = { + ...resolveFormat({ currency: 'USD' }), + maximumFractionDigits: 0, + }; + expect(formatNumber(7, 'en-US', usd, true)).toBe('$7.'); + }); + + it('does nothing when the flag is off, which is the default', () => { + expect(formatNumber(7, 'en-US', {})).toBe('7'); + }); +}); + describe('intlOptions', () => { it('never asks for a maximum below its minimum', () => { // Intl throws on that pair; the native formatters clamp. Clamping here keeps a bad prop from diff --git a/src/numberFormat.ts b/src/numberFormat.ts index 6610443..5c0657b 100644 --- a/src/numberFormat.ts +++ b/src/numberFormat.ts @@ -188,12 +188,60 @@ export function nativeFormatProps( */ export function formatNumber( value: number, + locale: string, + format: NumericTextFormat, + trailingDecimalSeparator = false +): string { + let text: string; + try { + text = value.toLocaleString(locale, intlOptions(format)); + } catch { + text = value.toLocaleString(locale); + } + return trailingDecimalSeparator + ? withTrailingSeparator(text, decimalSeparatorFor(locale, format)) + : text; +} + +/** + * The decimal mark this locale and format would use. + * + * Read from the formatter rather than from a table, because a currency format may use a different + * mark from a plain number in the same locale. A probe value with one forced fraction digit is the + * only way to make `formatToParts` emit the mark when the format itself asks for none, which is + * exactly the case this is needed for. + */ +function decimalSeparatorFor( locale: string, format: NumericTextFormat ): string { try { - return value.toLocaleString(locale, intlOptions(format)); + const probe: Intl.NumberFormatOptions = { ...intlOptions(format) }; + delete probe.minimumSignificantDigits; + delete probe.maximumSignificantDigits; + probe.minimumFractionDigits = 1; + probe.maximumFractionDigits = 1; + + const parts = new Intl.NumberFormat(locale, probe).formatToParts(1.1); + return parts.find((part) => part.type === 'decimal')?.value ?? '.'; } catch { - return value.toLocaleString(locale); + return '.'; + } +} + +/** + * [text] with [mark] after its last digit, unless it already carries one. + * + * After the last *digit*, not at the end of the string: `de-DE` writes `1.234 €`, and a mark + * appended blindly would land beyond the currency symbol. `\p{Nd}` rather than `0-9` because a + * locale may format in Arabic-Indic or Devanagari digits. + */ +function withTrailingSeparator(text: string, mark: string): string { + if (text.includes(mark)) return text; + + let end = -1; + for (const match of text.matchAll(/\p{Nd}/gu)) { + end = match.index + match[0].length; } + return end < 0 ? text + mark : text.slice(0, end) + mark + text.slice(end); } diff --git a/src/types.ts b/src/types.ts index ddc45c9..59d59a2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -111,6 +111,30 @@ export type NumericTextProps = { */ currency?: string; + /** + * Draws the decimal mark after the last digit even though no fraction digit follows it yet. + * + * This exists for one case, and it is the case every amount field hits: `value` is a number, and + * a number cannot hold `7.`. Someone typing `7`, `.`, `5` produces the values 7, 7, 7.5, so the + * mark they typed has nowhere to live until the digit after it arrives, and the field either + * swallows the keystroke or grows a second `.` of its own beside the component. A sibling `Text` + * cannot be made to line up: this view reserves half an em of headroom for the transition's + * overspill and centres the number inside it, so the gap to the right of the last digit is not a + * fixed distance, and it moves with the value and the font. + * + * Set this from the raw input instead, and the mark becomes a real column: same font, same + * baseline, keyed as `DEC`, and already in place when the first fraction digit is born beside it. + * + * ```tsx + * + * ``` + * + * It is a no-op whenever the number already has a decimal mark, so pairing it with + * `minimumFractionDigits` is safe. The mark is the locale's own, and it is placed after the last + * digit rather than at the end of the string, so a trailing currency symbol stays outside it. + */ + trailingDecimalSeparator?: boolean; + /** * Which way digits roll. `'automatic'` rolls up when the value grows and down when it shrinks, * which is what SwiftUI does; the other two force a direction regardless of the value.