currency-fomatter 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +558 -35
- package/dist/cjs/components/currency/hooks.d.ts +52 -0
- package/dist/cjs/components/currency/hooks.js +130 -0
- package/dist/cjs/components/currency/hooks.js.map +1 -0
- package/dist/cjs/components/currency/index.d.ts +44 -107
- package/dist/cjs/components/currency/index.js +509 -505
- package/dist/cjs/components/currency/index.js.map +1 -1
- package/dist/cjs/components/currency/locales.d.ts +55 -0
- package/dist/cjs/components/currency/locales.js +382 -0
- package/dist/cjs/components/currency/locales.js.map +1 -0
- package/dist/cjs/components/currency/utils.d.ts +108 -20
- package/dist/cjs/components/currency/utils.js +344 -70
- package/dist/cjs/components/currency/utils.js.map +1 -1
- package/dist/cjs/components/test/index.d.ts +3 -6
- package/dist/cjs/components/test/index.js +121 -15
- package/dist/cjs/components/test/index.js.map +1 -1
- package/dist/cjs/index.d.ts +4 -2
- package/dist/cjs/index.js +19 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/currency/hooks.d.ts +52 -0
- package/dist/esm/components/currency/hooks.js +126 -0
- package/dist/esm/components/currency/hooks.js.map +1 -0
- package/dist/esm/components/currency/index.d.ts +44 -107
- package/dist/esm/components/currency/index.js +497 -508
- package/dist/esm/components/currency/index.js.map +1 -1
- package/dist/esm/components/currency/locales.d.ts +55 -0
- package/dist/esm/components/currency/locales.js +370 -0
- package/dist/esm/components/currency/locales.js.map +1 -0
- package/dist/esm/components/currency/utils.d.ts +108 -20
- package/dist/esm/components/currency/utils.js +338 -66
- package/dist/esm/components/currency/utils.js.map +1 -1
- package/dist/esm/components/test/index.d.ts +3 -6
- package/dist/esm/components/test/index.js +123 -16
- package/dist/esm/components/test/index.js.map +1 -1
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.js +13 -2
- package/dist/esm/index.js.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -1,46 +1,569 @@
|
|
|
1
1
|
# currency-fomatter
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import { CurrencyFormat } from "currency-fomatter"
|
|
3
|
+
A React component for formatting currency, phone numbers, credit cards, and other numeric inputs with full TypeScript support.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
## Screenshots
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install currency-fomatter
|
|
15
|
+
# or
|
|
16
|
+
yarn add currency-fomatter
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- Currency formatting with thousand separators
|
|
22
|
+
- Phone number and credit card masking
|
|
23
|
+
- Custom format patterns
|
|
24
|
+
- Support for multiple number systems (US, Indian, etc.)
|
|
25
|
+
- Prefix and suffix support
|
|
26
|
+
- Decimal scale control
|
|
27
|
+
- Negative number support
|
|
28
|
+
- Custom input component support
|
|
29
|
+
- Full TypeScript support
|
|
30
|
+
- **Standalone utility functions** (`formatCurrency`, `parseCurrency`)
|
|
31
|
+
- **Compact format** (`formatCompact` - 1K, 1M, 1B)
|
|
32
|
+
- **Locale presets** (en-US, vi-VN, de-DE, ja-JP, etc.)
|
|
33
|
+
- **React hook** (`useCurrencyFormat`) for easy state management
|
|
34
|
+
- **ref forwarding** for form library integration
|
|
35
|
+
|
|
36
|
+
## Basic Usage
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { CurrencyFormat } from "currency-fomatter";
|
|
40
|
+
|
|
41
|
+
function App() {
|
|
42
|
+
return (
|
|
43
|
+
<CurrencyFormat
|
|
44
|
+
value="1234567.89"
|
|
45
|
+
thousandSeparator=","
|
|
46
|
+
decimalSeparator="."
|
|
47
|
+
prefix="$"
|
|
48
|
+
decimalScale={2}
|
|
49
|
+
fixedDecimalScale
|
|
50
|
+
onValueChange={(values) => {
|
|
51
|
+
console.log(values.formattedValue); // "$1,234,567.89"
|
|
52
|
+
console.log(values.value); // "1234567.89"
|
|
53
|
+
console.log(values.floatValue); // 1234567.89
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
11
57
|
}
|
|
12
58
|
```
|
|
13
59
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
### Currency Format
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<CurrencyFormat
|
|
66
|
+
value={1234.56}
|
|
67
|
+
thousandSeparator=","
|
|
68
|
+
prefix="$"
|
|
69
|
+
decimalScale={2}
|
|
70
|
+
fixedDecimalScale
|
|
71
|
+
/>
|
|
72
|
+
// Output: $1,234.56
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Phone Number Format
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<CurrencyFormat
|
|
79
|
+
format="+1 (###) ###-####"
|
|
80
|
+
mask="_"
|
|
81
|
+
placeholder="+1 (___) ___-____"
|
|
82
|
+
/>
|
|
83
|
+
// Output: +1 (555) 123-4567
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Credit Card Format
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<CurrencyFormat
|
|
90
|
+
format="#### #### #### ####"
|
|
91
|
+
mask="_"
|
|
92
|
+
/>
|
|
93
|
+
// Output: 4111 1111 1111 1111
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Percentage with Validation
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
<CurrencyFormat
|
|
100
|
+
value="75.5"
|
|
101
|
+
suffix="%"
|
|
102
|
+
decimalScale={2}
|
|
103
|
+
isAllowed={(values) => values.floatValue <= 100}
|
|
104
|
+
/>
|
|
105
|
+
// Output: 75.50%
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Indian Number System
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
<CurrencyFormat
|
|
112
|
+
value="1234567"
|
|
113
|
+
thousandSeparator=","
|
|
114
|
+
thousandSpacing="2s"
|
|
115
|
+
prefix="₹"
|
|
116
|
+
/>
|
|
117
|
+
// Output: ₹12,34,567
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Display as Text (Read-only)
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<CurrencyFormat
|
|
124
|
+
value={9999.99}
|
|
125
|
+
displayType="text"
|
|
126
|
+
thousandSeparator=","
|
|
127
|
+
prefix="$"
|
|
128
|
+
/>
|
|
129
|
+
// Output: <span>$9,999.99</span>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Custom Input Component
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
const CustomInput = (props) => (
|
|
136
|
+
<input {...props} className="custom-input" />
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
<CurrencyFormat
|
|
140
|
+
value="1000"
|
|
141
|
+
customInput={CustomInput}
|
|
142
|
+
thousandSeparator=","
|
|
143
|
+
prefix="$"
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Props
|
|
148
|
+
|
|
149
|
+
| Prop | Type | Default | Description |
|
|
150
|
+
|------|------|---------|-------------|
|
|
151
|
+
| `value` | `string \| number` | - | Input value |
|
|
152
|
+
| `format` | `string \| Function` | - | Format pattern (e.g., `"+1 (###) ###-####"`) or custom format function |
|
|
153
|
+
| `decimalScale` | `number` | - | Maximum decimal places |
|
|
154
|
+
| `decimalSeparator` | `string` | `"."` | Decimal separator character |
|
|
155
|
+
| `thousandSeparator` | `string \| boolean` | `","` | Thousand separator (`true` = `","`) |
|
|
156
|
+
| `thousandSpacing` | `"2" \| "2s" \| "3" \| "4"` | `"3"` | Thousand grouping pattern |
|
|
157
|
+
| `mask` | `string \| string[]` | `" "` | Mask character for empty format positions |
|
|
158
|
+
| `prefix` | `string` | `""` | Text before the number (e.g., `"$"`) |
|
|
159
|
+
| `suffix` | `string` | `""` | Text after the number (e.g., `"%"`) |
|
|
160
|
+
| `allowNegative` | `boolean` | `true` | Allow negative values |
|
|
161
|
+
| `fixedDecimalScale` | `boolean` | `false` | Always show decimal places |
|
|
162
|
+
| `isNumericString` | `boolean` | `false` | Treat value as numeric string |
|
|
163
|
+
| `isAllowed` | `(values: ValueObject) => boolean` | - | Custom validation function |
|
|
164
|
+
| `onValueChange` | `(values: ValueObject) => void` | - | Callback when value changes |
|
|
165
|
+
| `type` | `"text" \| "tel"` | `"text"` | Input type |
|
|
166
|
+
| `displayType` | `"input" \| "text"` | `"input"` | Render as input or text |
|
|
167
|
+
| `customInput` | `React.ComponentType` | - | Custom input component |
|
|
168
|
+
| `renderText` | `(value, props) => ReactNode` | - | Custom text renderer |
|
|
169
|
+
| `name` | `string` | - | Field name (included in ValueObject) |
|
|
170
|
+
| `getInputRef` | `(el: HTMLInputElement) => void` | - | Callback to get input element ref |
|
|
171
|
+
|
|
172
|
+
### Thousand Spacing Options
|
|
173
|
+
|
|
174
|
+
| Value | Description | Example |
|
|
175
|
+
|-------|-------------|---------|
|
|
176
|
+
| `"3"` | Groups of 3 (US/EU) | `1,234,567` |
|
|
177
|
+
| `"2"` | Groups of 2 | `12,34,56,7` |
|
|
178
|
+
| `"2s"` | Indian system (Lakhs/Crores) | `12,34,567` |
|
|
179
|
+
| `"4"` | Groups of 4 | `123,4567` |
|
|
180
|
+
|
|
181
|
+
## Utility Functions
|
|
182
|
+
|
|
183
|
+
### formatCurrency
|
|
184
|
+
|
|
185
|
+
Format a number/string without rendering a component:
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
import { formatCurrency } from "currency-fomatter";
|
|
189
|
+
|
|
190
|
+
// Basic usage
|
|
191
|
+
formatCurrency(1234567.89);
|
|
192
|
+
// Output: "1,234,567.89"
|
|
193
|
+
|
|
194
|
+
// With options
|
|
195
|
+
formatCurrency(1234567.89, {
|
|
196
|
+
prefix: "$",
|
|
197
|
+
decimalScale: 2,
|
|
198
|
+
fixedDecimalScale: true,
|
|
199
|
+
thousandSeparator: ",",
|
|
200
|
+
});
|
|
201
|
+
// Output: "$1,234,567.89"
|
|
202
|
+
|
|
203
|
+
// Indian format
|
|
204
|
+
formatCurrency(1234567, {
|
|
205
|
+
prefix: "₹",
|
|
206
|
+
thousandSpacing: "2s",
|
|
207
|
+
});
|
|
208
|
+
// Output: "₹12,34,567"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### parseCurrency
|
|
212
|
+
|
|
213
|
+
Parse a formatted currency string back to numeric values:
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import { parseCurrency } from "currency-fomatter";
|
|
217
|
+
|
|
218
|
+
const result = parseCurrency("$1,234.56", {
|
|
219
|
+
prefix: "$",
|
|
220
|
+
thousandSeparator: ",",
|
|
221
|
+
});
|
|
222
|
+
// result = {
|
|
223
|
+
// value: "1234.56",
|
|
224
|
+
// floatValue: 1234.56,
|
|
225
|
+
// formattedValue: "$1,234.56"
|
|
226
|
+
// }
|
|
227
|
+
|
|
228
|
+
// Euro format
|
|
229
|
+
const euroResult = parseCurrency("1.234,56€", {
|
|
230
|
+
suffix: "€",
|
|
231
|
+
thousandSeparator: ".",
|
|
232
|
+
decimalSeparator: ",",
|
|
233
|
+
});
|
|
234
|
+
// euroResult.floatValue = 1234.56
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### formatCompact
|
|
238
|
+
|
|
239
|
+
Format large numbers in compact notation (1K, 1M, 1B):
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import { formatCompact } from "currency-fomatter";
|
|
243
|
+
|
|
244
|
+
// Basic usage
|
|
245
|
+
formatCompact(1234567);
|
|
246
|
+
// Output: "1.23M"
|
|
247
|
+
|
|
248
|
+
formatCompact(2500000000);
|
|
249
|
+
// Output: "2.5B"
|
|
250
|
+
|
|
251
|
+
// With currency prefix
|
|
252
|
+
formatCompact(1500000, { prefix: "$", decimalScale: 1 });
|
|
253
|
+
// Output: "$1.5M"
|
|
254
|
+
|
|
255
|
+
// Vietnamese format
|
|
256
|
+
formatCompact(1500000000, {
|
|
257
|
+
compactDisplay: {
|
|
258
|
+
thousand: " nghìn",
|
|
259
|
+
million: " triệu",
|
|
260
|
+
billion: " tỷ",
|
|
261
|
+
},
|
|
262
|
+
suffix: " ₫",
|
|
263
|
+
});
|
|
264
|
+
// Output: "1.5 tỷ ₫"
|
|
265
|
+
|
|
266
|
+
// Parse compact format back to number
|
|
267
|
+
import { parseCompact } from "currency-fomatter";
|
|
268
|
+
|
|
269
|
+
parseCompact("2.5M");
|
|
270
|
+
// Output: { value: "2500000", floatValue: 2500000 }
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Locale Support
|
|
274
|
+
|
|
275
|
+
### Dynamic Locale Detection (Recommended)
|
|
276
|
+
|
|
277
|
+
Uses browser's `Intl.NumberFormat` to auto-detect format for ANY locale:
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
import {
|
|
281
|
+
detectLocaleFormat,
|
|
282
|
+
createLocaleConfig,
|
|
283
|
+
getAutoLocaleConfig,
|
|
284
|
+
formatWithIntl,
|
|
285
|
+
} from "currency-fomatter";
|
|
286
|
+
|
|
287
|
+
// Auto-detect user's browser locale
|
|
288
|
+
const autoConfig = getAutoLocaleConfig("USD");
|
|
289
|
+
// Automatically detects separators, prefix/suffix based on user's browser
|
|
290
|
+
|
|
291
|
+
// Detect format for any locale (no hardcoding!)
|
|
292
|
+
const thaiFormat = detectLocaleFormat("th-TH", "THB");
|
|
293
|
+
// { thousandSeparator: ",", decimalSeparator: ".", prefix: "฿", ... }
|
|
294
|
+
|
|
295
|
+
const arabicFormat = detectLocaleFormat("ar-SA", "SAR");
|
|
296
|
+
// Correctly detects Arabic number formatting
|
|
297
|
+
|
|
298
|
+
// Create complete config dynamically
|
|
299
|
+
const config = createLocaleConfig("es-MX", "MXN");
|
|
300
|
+
// Full config with compactDisplay labels from Intl
|
|
301
|
+
|
|
302
|
+
// Direct Intl formatting (most accurate)
|
|
303
|
+
formatWithIntl(1234567.89, "de-DE", { style: "currency", currency: "EUR" });
|
|
304
|
+
// Output: "1.234.567,89 €"
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Use with CurrencyFormat
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
import { getFormatOptionsFromLocale, CurrencyFormat } from "currency-fomatter";
|
|
311
|
+
|
|
312
|
+
// Works with ANY locale - dynamic detection fallback
|
|
313
|
+
<CurrencyFormat
|
|
314
|
+
value={1234567}
|
|
315
|
+
{...getFormatOptionsFromLocale("th-TH", { currency: "THB" })}
|
|
316
|
+
/>
|
|
317
|
+
|
|
318
|
+
// Auto-detect from browser
|
|
319
|
+
import { getAutoLocaleConfig } from "currency-fomatter";
|
|
320
|
+
|
|
321
|
+
const { prefix, suffix, thousandSeparator, decimalSeparator } = getAutoLocaleConfig("USD");
|
|
322
|
+
<CurrencyFormat value={1234.56} prefix={prefix} suffix={suffix} ... />
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Static Presets (Fallback)
|
|
326
|
+
|
|
327
|
+
Pre-configured locales for common countries:
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
import { localePresets, getLocaleConfig } from "currency-fomatter";
|
|
331
|
+
|
|
332
|
+
// Available presets: en-US, vi-VN, de-DE, ja-JP, en-IN, fr-FR, zh-CN, ko-KR, pt-BR, en-GB
|
|
333
|
+
|
|
334
|
+
const vnConfig = getLocaleConfig("vi-VN");
|
|
335
|
+
// Uses preset if available, falls back to dynamic detection
|
|
336
|
+
|
|
337
|
+
<CurrencyFormat
|
|
338
|
+
value={1234567}
|
|
339
|
+
{...getFormatOptionsFromLocale("vi-VN")}
|
|
340
|
+
/>
|
|
341
|
+
// Output: 1.234.567 ₫
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Custom Locale Registry
|
|
345
|
+
|
|
346
|
+
Register your own locale configurations:
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
import { registerLocale, unregisterLocale, getLocaleConfig } from "currency-fomatter";
|
|
350
|
+
|
|
351
|
+
// Register custom locale
|
|
352
|
+
registerLocale("my-company", {
|
|
353
|
+
locale: "my-company",
|
|
354
|
+
prefix: "₿ ",
|
|
355
|
+
thousandSeparator: " ",
|
|
356
|
+
decimalSeparator: ",",
|
|
357
|
+
decimalScale: 8,
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Use it
|
|
361
|
+
const config = getLocaleConfig("my-company");
|
|
362
|
+
|
|
363
|
+
// Unregister when done
|
|
364
|
+
unregisterLocale("my-company");
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## useCurrencyFormat Hook
|
|
368
|
+
|
|
369
|
+
A React hook for easy currency state management:
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
import { useCurrencyFormat, CurrencyFormat } from "currency-fomatter";
|
|
373
|
+
|
|
374
|
+
function PriceInput() {
|
|
375
|
+
const {
|
|
376
|
+
value, // number: 1234.56
|
|
377
|
+
formattedValue, // string: "$1,234.56"
|
|
378
|
+
setValue, // (num: number | string) => void
|
|
379
|
+
inputProps, // Props to spread on CurrencyFormat
|
|
380
|
+
reset, // Reset to initial value
|
|
381
|
+
clear, // Clear value
|
|
382
|
+
} = useCurrencyFormat({
|
|
383
|
+
locale: "en-US",
|
|
384
|
+
initialValue: 1000,
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
return (
|
|
388
|
+
<div>
|
|
389
|
+
<CurrencyFormat {...inputProps} />
|
|
390
|
+
<p>Raw value: {value}</p>
|
|
391
|
+
<p>Formatted: {formattedValue}</p>
|
|
392
|
+
<button onClick={() => setValue(2000)}>Set $2000</button>
|
|
393
|
+
<button onClick={reset}>Reset</button>
|
|
394
|
+
<button onClick={clear}>Clear</button>
|
|
395
|
+
</div>
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Hook with Custom Options
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
const { inputProps, formattedValue } = useCurrencyFormat({
|
|
404
|
+
locale: "vi-VN",
|
|
405
|
+
initialValue: 1000000,
|
|
406
|
+
decimalScale: 0,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// formattedValue = "1.000.000 ₫"
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Hook without Locale
|
|
413
|
+
|
|
414
|
+
```tsx
|
|
415
|
+
const { inputProps, value } = useCurrencyFormat({
|
|
416
|
+
initialValue: 99.99,
|
|
417
|
+
prefix: "$",
|
|
418
|
+
decimalScale: 2,
|
|
419
|
+
fixedDecimalScale: true,
|
|
420
|
+
});
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Using with Form Libraries
|
|
424
|
+
|
|
425
|
+
### react-hook-form
|
|
426
|
+
|
|
427
|
+
The component supports `ref` forwarding for seamless integration:
|
|
428
|
+
|
|
429
|
+
```tsx
|
|
430
|
+
import { useForm } from "react-hook-form";
|
|
431
|
+
import { CurrencyFormat } from "currency-fomatter";
|
|
432
|
+
|
|
433
|
+
function MyForm() {
|
|
434
|
+
const { register, handleSubmit, setValue } = useForm();
|
|
435
|
+
|
|
436
|
+
return (
|
|
437
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
438
|
+
<CurrencyFormat
|
|
439
|
+
{...register("price")}
|
|
440
|
+
name="price"
|
|
441
|
+
thousandSeparator=","
|
|
442
|
+
prefix="$"
|
|
443
|
+
onValueChange={(values, sourceInfo) => {
|
|
444
|
+
// Only update form when user interacts, not on prop changes
|
|
445
|
+
if (sourceInfo?.source === "event") {
|
|
446
|
+
setValue("price", values.floatValue);
|
|
447
|
+
}
|
|
448
|
+
}}
|
|
449
|
+
/>
|
|
450
|
+
</form>
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Multiple Fields
|
|
456
|
+
|
|
457
|
+
Use the `name` prop to identify fields in shared handlers:
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
function PriceForm() {
|
|
461
|
+
const [prices, setPrices] = useState({ min: 0, max: 0 });
|
|
462
|
+
|
|
463
|
+
const handleValueChange = (values, sourceInfo) => {
|
|
464
|
+
if (values.name) {
|
|
465
|
+
setPrices(prev => ({
|
|
466
|
+
...prev,
|
|
467
|
+
[values.name]: values.floatValue
|
|
468
|
+
}));
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
return (
|
|
473
|
+
<>
|
|
474
|
+
<CurrencyFormat
|
|
475
|
+
name="min"
|
|
476
|
+
value={prices.min}
|
|
477
|
+
onValueChange={handleValueChange}
|
|
478
|
+
prefix="$"
|
|
479
|
+
/>
|
|
480
|
+
<CurrencyFormat
|
|
481
|
+
name="max"
|
|
482
|
+
value={prices.max}
|
|
483
|
+
onValueChange={handleValueChange}
|
|
484
|
+
prefix="$"
|
|
485
|
+
/>
|
|
486
|
+
</>
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## TypeScript
|
|
492
|
+
|
|
493
|
+
The package includes full TypeScript support with exported types:
|
|
494
|
+
|
|
495
|
+
```tsx
|
|
496
|
+
import CurrencyFormat, {
|
|
497
|
+
// Component props
|
|
498
|
+
CurrencyFormatProps,
|
|
499
|
+
ValueObject,
|
|
500
|
+
ThousandSpacing,
|
|
501
|
+
|
|
502
|
+
// Utility function types
|
|
503
|
+
FormatCurrencyOptions,
|
|
504
|
+
ParseCurrencyOptions,
|
|
505
|
+
CompactDisplayOptions,
|
|
506
|
+
FormatCompactOptions,
|
|
507
|
+
|
|
508
|
+
// Hook types
|
|
509
|
+
UseCurrencyFormatOptions,
|
|
510
|
+
UseCurrencyFormatReturn,
|
|
511
|
+
|
|
512
|
+
// Locale types
|
|
513
|
+
LocaleConfig,
|
|
514
|
+
|
|
515
|
+
// Callback types
|
|
516
|
+
FormatFunction,
|
|
517
|
+
IsAllowedFunction,
|
|
518
|
+
OnValueChangeFunction,
|
|
519
|
+
} from "currency-fomatter";
|
|
520
|
+
|
|
521
|
+
// ValueObject type
|
|
522
|
+
interface ValueObject {
|
|
523
|
+
formattedValue: string; // Formatted display value
|
|
524
|
+
value: string; // Unformatted numeric string
|
|
525
|
+
floatValue: number; // Parsed float value
|
|
526
|
+
name?: string; // Field name (if provided)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// onValueChange callback signature
|
|
530
|
+
type OnValueChangeFunction = (
|
|
531
|
+
values: ValueObject,
|
|
532
|
+
sourceInfo?: {
|
|
533
|
+
event?: ChangeEvent<HTMLInputElement>;
|
|
534
|
+
source: "event" | "prop"; // "event" = user input, "prop" = value prop changed
|
|
535
|
+
}
|
|
536
|
+
) => void;
|
|
537
|
+
|
|
538
|
+
// Locale config type
|
|
539
|
+
interface LocaleConfig {
|
|
540
|
+
locale: string;
|
|
541
|
+
currency?: string;
|
|
542
|
+
currencySymbol?: string;
|
|
543
|
+
prefix?: string;
|
|
544
|
+
suffix?: string;
|
|
545
|
+
thousandSeparator?: string | boolean;
|
|
546
|
+
decimalSeparator?: string;
|
|
547
|
+
thousandSpacing?: ThousandSpacing;
|
|
548
|
+
decimalScale?: number;
|
|
549
|
+
compactDisplay?: CompactDisplayOptions;
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
## Event Handlers
|
|
554
|
+
|
|
555
|
+
All standard input event handlers are supported:
|
|
43
556
|
|
|
557
|
+
```tsx
|
|
558
|
+
<CurrencyFormat
|
|
559
|
+
onChange={(e) => console.log("onChange", e)}
|
|
560
|
+
onKeyDown={(e) => console.log("onKeyDown", e)}
|
|
561
|
+
onMouseUp={(e) => console.log("onMouseUp", e)}
|
|
562
|
+
onFocus={(e) => console.log("onFocus", e)}
|
|
563
|
+
onBlur={(e) => console.log("onBlur", e)}
|
|
564
|
+
/>
|
|
44
565
|
```
|
|
45
566
|
|
|
567
|
+
## License
|
|
46
568
|
|
|
569
|
+
MIT
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { FormatCurrencyOptions, ValueObject } from "./utils";
|
|
2
|
+
import { LocaleConfig } from "./locales";
|
|
3
|
+
export interface UseCurrencyFormatOptions extends FormatCurrencyOptions {
|
|
4
|
+
locale?: string;
|
|
5
|
+
initialValue?: number | string;
|
|
6
|
+
}
|
|
7
|
+
export interface UseCurrencyFormatReturn {
|
|
8
|
+
/** Raw numeric value as number */
|
|
9
|
+
value: number;
|
|
10
|
+
/** Raw numeric value as string (preserves precision) */
|
|
11
|
+
valueAsString: string;
|
|
12
|
+
/** Formatted display value */
|
|
13
|
+
formattedValue: string;
|
|
14
|
+
/** Set value from number or string */
|
|
15
|
+
setValue: (value: number | string) => void;
|
|
16
|
+
/** Set value from formatted string (parses it first) */
|
|
17
|
+
setFormattedValue: (formatted: string) => void;
|
|
18
|
+
/** Format options derived from locale or props */
|
|
19
|
+
formatOptions: FormatCurrencyOptions;
|
|
20
|
+
/** Props to spread on CurrencyFormat component */
|
|
21
|
+
inputProps: {
|
|
22
|
+
value: number | string;
|
|
23
|
+
onValueChange: (values: ValueObject) => void;
|
|
24
|
+
decimalSeparator: string;
|
|
25
|
+
thousandSeparator: string | boolean;
|
|
26
|
+
prefix: string;
|
|
27
|
+
suffix: string;
|
|
28
|
+
decimalScale?: number;
|
|
29
|
+
fixedDecimalScale?: boolean;
|
|
30
|
+
allowNegative?: boolean;
|
|
31
|
+
};
|
|
32
|
+
/** Reset to initial value */
|
|
33
|
+
reset: () => void;
|
|
34
|
+
/** Clear value */
|
|
35
|
+
clear: () => void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Hook for managing currency format state
|
|
39
|
+
* Makes it easy to use currency formatting in forms
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* const { value, formattedValue, inputProps } = useCurrencyFormat({
|
|
44
|
+
* locale: "en-US",
|
|
45
|
+
* initialValue: 1000,
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* return <CurrencyFormat {...inputProps} />;
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function useCurrencyFormat(options?: UseCurrencyFormatOptions): UseCurrencyFormatReturn;
|
|
52
|
+
export type { LocaleConfig };
|