1
1
import type { ReactElement } from 'react' ;
2
2
import React from 'react' ;
3
3
import type { CurrencyCodeType } from '@razorpay/i18nify-js/currency' ;
4
- import { formatNumber , formatNumberByParts } from '@razorpay/i18nify-js/currency' ;
4
+ import { formatNumberByParts } from '@razorpay/i18nify-js/currency' ;
5
5
import type { AmountTypeProps } from './amountTokens' ;
6
6
import { normalAmountSizes , subtleFontSizes , amountLineHeights } from './amountTokens' ;
7
7
import type { BaseTextProps } from '~components/Typography/BaseText/types' ;
@@ -19,6 +19,43 @@ import { Text } from '~components/Typography';
19
19
import { opacity } from '~tokens/global' ;
20
20
import type { FontFamily } from '~tokens/global' ;
21
21
22
+ /**
23
+ * Pollyfill function to get around the node 18 error
24
+ *
25
+ * This function is maintained by i18nify team. Reach out to them for any change regarding this.
26
+ */
27
+ const stripTrailingZerosFromParts = (
28
+ parts : ReturnType < typeof formatNumberByParts > ,
29
+ ) : ReturnType < typeof formatNumberByParts > => {
30
+ const decimalPart = parts . rawParts
31
+ . filter ( ( { type } ) => type === 'fraction' )
32
+ . map ( ( { value } ) => value )
33
+ . join ( '' ) ;
34
+
35
+ const hasFraction = parts . rawParts . some ( ( { type } ) => type === 'fraction' ) ;
36
+
37
+ if ( hasFraction && / ^ 0 + $ / . test ( decimalPart ) ) {
38
+ delete parts . decimal ;
39
+ delete parts . fraction ;
40
+ parts . rawParts = parts . rawParts . filter ( ( { type } ) => type !== 'decimal' && type !== 'fraction' ) ;
41
+ }
42
+
43
+ return parts ;
44
+ } ;
45
+
46
+ /**
47
+ * Wrapper that uses pollyfill of i18nify team
48
+ */
49
+ const pollyfilledFormatNumberByParts : typeof formatNumberByParts = ( value , options ) => {
50
+ const parts = formatNumberByParts ( value , options ) ;
51
+
52
+ if ( options ?. intlOptions ?. trailingZeroDisplay === 'stripIfInteger' ) {
53
+ return stripTrailingZerosFromParts ( parts ) ;
54
+ }
55
+
56
+ return parts ;
57
+ } ;
58
+
22
59
type AmountCommonProps = {
23
60
/**
24
61
* The value to be rendered within the component.
@@ -82,7 +119,7 @@ const getTextColorProps = ({ color }: { color: AmountProps['color'] }): ColorPro
82
119
return props ;
83
120
} ;
84
121
85
- type AmountType = Partial < ReturnType < typeof formatNumberByParts > > & { formatted : string } ;
122
+ type AmountType = Partial < ReturnType < typeof formatNumberByParts > > ;
86
123
87
124
interface AmountValue extends Omit < AmountProps , 'value' > {
88
125
amountValueColor : BaseTextProps [ 'color' ] ;
@@ -141,35 +178,38 @@ const AmountValue = ({
141
178
color = { amountValueColor }
142
179
lineHeight = { amountLineHeights [ type ] [ size ] }
143
180
>
144
- { amount . formatted }
181
+ { amount . integer }
182
+ { amount . decimal }
183
+ { amount . fraction }
184
+ { amount . compact }
145
185
</ BaseText >
146
186
) ;
147
187
} ;
148
188
149
189
type FormatAmountWithSuffixType = {
150
190
suffix : AmountProps [ 'suffix' ] ;
151
191
value : number ;
192
+ currency : AmountProps [ 'currency' ] ;
152
193
} ;
153
194
154
195
/**
155
196
* Returns a parsed object based on the suffix passed in parameters
156
197
* === Logic ===
157
198
* value = 12500.45
158
199
* if suffix === 'decimals' => {
159
- "formatted": "12,500.45",
160
200
"integer": "12,500",
161
201
"decimal": ".",
162
202
"fraction": "45",
203
+ "compact": "K",
163
204
"isPrefixSymbol": false,
164
205
"rawParts": [{"type": "integer","value": "12"},{"type": "group","value": ","},{"type": "integer","value": "500"},{"type": "decimal","value": "."},{"type": "fraction","value": "45"}]
165
206
}
166
- * else if suffix === 'humanize' => { formatted: "1.2T" }
167
- * else => { formatted: "1,23,456" }
168
207
* @returns {AmountType }
169
208
*/
170
- export const formatAmountWithSuffix = ( {
209
+ export const getAmountByParts = ( {
171
210
suffix,
172
211
value,
212
+ currency,
173
213
} : FormatAmountWithSuffixType ) : AmountType => {
174
214
try {
175
215
switch ( suffix ) {
@@ -179,40 +219,37 @@ export const formatAmountWithSuffix = ({
179
219
maximumFractionDigits : 2 ,
180
220
minimumFractionDigits : 2 ,
181
221
} ,
182
- } ;
183
- return {
184
- ...formatNumberByParts ( value , options ) ,
185
- formatted : formatNumber ( value , options ) ,
186
- } ;
222
+ currency,
223
+ } as const ;
224
+ return pollyfilledFormatNumberByParts ( value , options ) ;
187
225
}
188
226
case 'humanize' : {
189
- const formatted = formatNumber ( value , {
227
+ const options = {
190
228
intlOptions : {
191
229
notation : 'compact' ,
192
230
maximumFractionDigits : 2 ,
193
231
trailingZeroDisplay : 'stripIfInteger' ,
194
232
} ,
195
- } ) ;
196
- return {
197
- formatted,
198
- } ;
233
+ currency,
234
+ } as const ;
235
+ return pollyfilledFormatNumberByParts ( value , options ) ;
199
236
}
200
237
201
238
default : {
202
- const formatted = formatNumber ( value , {
239
+ const options = {
203
240
intlOptions : {
204
241
maximumFractionDigits : 0 ,
205
242
roundingMode : 'floor' ,
206
243
} ,
207
- } ) ;
208
- return {
209
- formatted,
210
- } ;
244
+ currency,
245
+ } as const ;
246
+ return pollyfilledFormatNumberByParts ( value , options ) ;
211
247
}
212
248
}
213
249
} catch ( err : unknown ) {
214
250
return {
215
- formatted : `${ value } ` ,
251
+ integer : `${ value } ` ,
252
+ currency,
216
253
} ;
217
254
}
218
255
} ;
@@ -275,20 +312,11 @@ const _Amount = ({
275
312
color,
276
313
} ) ;
277
314
278
- let isPrefixSymbol , currencySymbol ;
279
- try {
280
- const byParts = formatNumberByParts ( value , {
281
- currency,
282
- } ) ;
283
- isPrefixSymbol = byParts . isPrefixSymbol ;
284
- currencySymbol = byParts . currency ;
285
- } catch ( err : unknown ) {
286
- isPrefixSymbol = true ;
287
- currencySymbol = currency ;
288
- }
315
+ const renderedValue = getAmountByParts ( { suffix, value, currency } ) ;
316
+ const isPrefixSymbol = renderedValue . isPrefixSymbol ?? true ;
317
+ const currencySymbol = renderedValue . currency ?? currency ;
289
318
290
319
const currencyPosition = isPrefixSymbol ? 'left' : 'right' ;
291
- const renderedValue = formatAmountWithSuffix ( { suffix, value } ) ;
292
320
const currencySymbolOrCode = currencyIndicator === 'currency-symbol' ? currencySymbol : currency ;
293
321
294
322
const currencyFontSize = isAffixSubtle
@@ -309,6 +337,18 @@ const _Amount = ({
309
337
flexDirection = "row"
310
338
position = "relative"
311
339
>
340
+ { renderedValue . minusSign ? (
341
+ < BaseText
342
+ fontSize = { normalAmountSizes [ type ] [ size ] }
343
+ fontWeight = { weight }
344
+ lineHeight = { amountLineHeights [ type ] [ size ] }
345
+ color = { amountValueColor }
346
+ as = { isReactNative ? undefined : 'span' }
347
+ marginX = "spacing.2"
348
+ >
349
+ { renderedValue . minusSign }
350
+ </ BaseText >
351
+ ) : null }
312
352
{ currencyPosition === 'left' && (
313
353
< BaseText
314
354
marginRight = "spacing.1"
0 commit comments