react-bigint-input 1.0.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 +157 -0
- package/dist/index.d.mts +117 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +475 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +446 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">๐ข react-bigint-input</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
A precision numeric input for BigInt values. Built for DeFi.
|
|
5
|
+
<br />
|
|
6
|
+
<strong>Zero dependencies ยท TypeScript ยท Locale-aware</strong>
|
|
7
|
+
</p>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="https://www.npmjs.com/package/react-bigint-input"><img src="https://img.shields.io/npm/v/react-bigint-input?color=904bff&label=npm" alt="npm" /></a>
|
|
12
|
+
<a href="https://bundlephobia.com/package/react-bigint-input"><img src="https://img.shields.io/bundlephobia/minzip/react-bigint-input?color=904bff&label=size" alt="bundle size" /></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="zero deps" />
|
|
14
|
+
<img src="https://img.shields.io/badge/react-%3E%3D17-61dafb" alt="react >=17" />
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## โจ Features
|
|
20
|
+
|
|
21
|
+
- ๐งฎ **True BigInt** โ no floating point, no precision loss
|
|
22
|
+
- ๐ **Locale-aware formatting** โ `1,000.50` or `1.000,50` or `1,00,000` โ auto-detects or configure per-locale
|
|
23
|
+
- ๐ข **Configurable decimals** โ set 18 for ETH, 6 for USDC, or any token precision
|
|
24
|
+
- ๐ **Paste handling** โ sanitizes pasted values
|
|
25
|
+
- ๐ฏ **Min/max clamping** โ enforced on every keystroke
|
|
26
|
+
- ๐ฆ **Zero dependencies** โ no ethers or viem required
|
|
27
|
+
- ๐๏ธ **Works everywhere** โ React 17, 18, and 19
|
|
28
|
+
|
|
29
|
+
## ๐ฆ Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install react-bigint-input
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## ๐ Quick Start
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { useState } from 'react'
|
|
39
|
+
import { BigIntInput } from 'react-bigint-input'
|
|
40
|
+
|
|
41
|
+
function SwapForm() {
|
|
42
|
+
const [amount, setAmount] = useState(0n)
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<BigIntInput
|
|
46
|
+
value={amount}
|
|
47
|
+
decimals={18}
|
|
48
|
+
onChange={setAmount}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## ๐ Formatting
|
|
55
|
+
|
|
56
|
+
By default, numbers are formatted US-style (`1,000.50`). Most crypto users are familiar with this format regardless of locale.
|
|
57
|
+
|
|
58
|
+
> โ ๏ธ Changing the format can confuse users who expect US formatting. Use at your own risk.
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
// Default (US): 1,000.50 โ recommended for most crypto apps
|
|
62
|
+
<BigIntInput value={amount} decimals={18} onChange={setAmount} />
|
|
63
|
+
|
|
64
|
+
// Auto (browser locale)
|
|
65
|
+
<BigIntInput value={amount} decimals={18} onChange={setAmount} format="auto" />
|
|
66
|
+
|
|
67
|
+
// Specific locale (Indian: 1,00,000 / German: 1.000,50)
|
|
68
|
+
<BigIntInput value={amount} decimals={18} onChange={setAmount} format={{ locale: 'en-IN' }} />
|
|
69
|
+
<BigIntInput value={amount} decimals={18} onChange={setAmount} format={{ locale: 'de-DE' }} />
|
|
70
|
+
|
|
71
|
+
// Custom separators
|
|
72
|
+
<BigIntInput value={amount} decimals={18} onChange={setAmount} format={{ thousand: '.', decimal: ',' }} />
|
|
73
|
+
|
|
74
|
+
// No formatting (raw digits): 1000.50
|
|
75
|
+
<BigIntInput value={amount} decimals={18} onChange={setAmount} format="none" />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## ๐ฏ Min / Max
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<BigIntInput
|
|
82
|
+
value={amount}
|
|
83
|
+
decimals={6}
|
|
84
|
+
onChange={setAmount}
|
|
85
|
+
max={100000000n} // 100 USDC
|
|
86
|
+
min={1000000n} // 1 USDC
|
|
87
|
+
/>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Values are clamped on every keystroke โ no invalid states.
|
|
91
|
+
|
|
92
|
+
## ๐ Props
|
|
93
|
+
|
|
94
|
+
| Prop | Type | Default | Description |
|
|
95
|
+
|------|------|---------|-------------|
|
|
96
|
+
| `value` | `bigint` | โ | Current value in smallest unit (e.g. wei) |
|
|
97
|
+
| `decimals` | `number` | โ | Token decimals (18 for ETH, 6 for USDC) |
|
|
98
|
+
| `onChange` | `(v: bigint) => void` | โ | Fires when value changes |
|
|
99
|
+
| `max` | `bigint` | โ | Clamp to maximum |
|
|
100
|
+
| `min` | `bigint` | โ | Clamp to minimum |
|
|
101
|
+
| `format` | `FormatConfig \| "auto" \| "none"` | `{ thousand: ",", decimal: "." }` | Number formatting |
|
|
102
|
+
| `allowNegative` | `boolean` | `false` | Allow negative values |
|
|
103
|
+
| `showZero` | `boolean` | `false` | Show "0" instead of empty |
|
|
104
|
+
| `placeholder` | `string` | `"0"` | Placeholder text |
|
|
105
|
+
| `disabled` | `boolean` | `false` | Disable input |
|
|
106
|
+
| `readOnly` | `boolean` | `false` | Read-only mode |
|
|
107
|
+
| `className` | `string` | โ | CSS class |
|
|
108
|
+
| `style` | `CSSProperties` | โ | Inline styles |
|
|
109
|
+
|
|
110
|
+
Plus: `name`, `id`, `autoFocus`, `onFocus`, `onBlur`.
|
|
111
|
+
|
|
112
|
+
### FormatConfig
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
interface FormatConfig {
|
|
116
|
+
locale?: string // Use Intl.NumberFormat with this locale (e.g. 'de-DE', 'en-IN')
|
|
117
|
+
thousand?: string // Thousands separator (default: ',')
|
|
118
|
+
decimal?: string // Decimal separator (default: '.')
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
When `locale` is set, grouping uses `Intl.NumberFormat` (handles Indian lakh/crore, etc.). `thousand` and `decimal` can override the detected separators.
|
|
123
|
+
|
|
124
|
+
## ๐งฐ Utilities
|
|
125
|
+
|
|
126
|
+
Format and parse BigInt values outside the input:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { formatValue, parseValue } from 'react-bigint-input'
|
|
130
|
+
|
|
131
|
+
// Format for display
|
|
132
|
+
formatValue(1234567890n, 6) // "1,234.56789"
|
|
133
|
+
formatValue(1234567890n, 6, { locale: 'de-DE' }) // "1.234,56789"
|
|
134
|
+
formatValue(1234567890n, 6, 'none') // "1234.56789"
|
|
135
|
+
|
|
136
|
+
// Parse back to BigInt
|
|
137
|
+
parseValue('1,234.56789', 6) // 1234567890n
|
|
138
|
+
parseValue('1.234,56789', 6, { locale: 'de-DE' }) // 1234567890n
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Same `format` config as the component prop.
|
|
142
|
+
|
|
143
|
+
## ๐ค Why?
|
|
144
|
+
|
|
145
|
+
Every crypto project builds a BigInt input from scratch. Most have bugs:
|
|
146
|
+
|
|
147
|
+
- ๐ฅ Crash when switching token decimals mid-input
|
|
148
|
+
- ๐ข Floating point precision errors (`0.1 + 0.2 โ 0.3`)
|
|
149
|
+
- ๐ Can't handle paste or edge cases
|
|
150
|
+
- ๐ Depend on ethers/viem just for `formatUnits`
|
|
151
|
+
- ๐ค No separator support or cursor jumps around
|
|
152
|
+
|
|
153
|
+
This package does one thing well.
|
|
154
|
+
|
|
155
|
+
## ๐ License
|
|
156
|
+
|
|
157
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React, { Component } from 'react';
|
|
3
|
+
|
|
4
|
+
interface FormatConfig {
|
|
5
|
+
/** Use Intl.NumberFormat with this locale for grouping (e.g. 'de-DE', 'en-IN') */
|
|
6
|
+
locale?: string;
|
|
7
|
+
/** Thousands grouping character (e.g. ',' โ 1,000) */
|
|
8
|
+
thousand?: string;
|
|
9
|
+
/** Decimal point character (e.g. '.' โ 1.5) */
|
|
10
|
+
decimal?: string;
|
|
11
|
+
}
|
|
12
|
+
interface BigIntInputProps {
|
|
13
|
+
/** Current value as BigInt in smallest unit (e.g. wei) */
|
|
14
|
+
value: bigint;
|
|
15
|
+
/** Token decimals (e.g. 18 for ETH, 6 for USDC) */
|
|
16
|
+
decimals: number;
|
|
17
|
+
/** Fires when the BigInt value changes */
|
|
18
|
+
onChange: (value: bigint) => void;
|
|
19
|
+
/** Maximum allowed value (clamped on input) */
|
|
20
|
+
max?: bigint;
|
|
21
|
+
/** Minimum allowed value (clamped on input) */
|
|
22
|
+
min?: bigint;
|
|
23
|
+
/** Number formatting โ "auto" (browser locale), "none" (raw digits), or a config object */
|
|
24
|
+
format?: FormatConfig | 'auto' | 'none';
|
|
25
|
+
/** Allow negative values (default: false) */
|
|
26
|
+
allowNegative?: boolean;
|
|
27
|
+
/** Render "0" instead of empty when value is 0n */
|
|
28
|
+
showZero?: boolean;
|
|
29
|
+
/** Placeholder text */
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
/** Disable the input */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/** Read-only mode */
|
|
34
|
+
readOnly?: boolean;
|
|
35
|
+
/** CSS class name */
|
|
36
|
+
className?: string;
|
|
37
|
+
/** Inline styles */
|
|
38
|
+
style?: React.CSSProperties;
|
|
39
|
+
/** HTML name attribute */
|
|
40
|
+
name?: string;
|
|
41
|
+
/** HTML id attribute */
|
|
42
|
+
id?: string;
|
|
43
|
+
/** Auto-focus on mount */
|
|
44
|
+
autoFocus?: boolean;
|
|
45
|
+
/** Focus callback */
|
|
46
|
+
onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void;
|
|
47
|
+
/** Blur callback */
|
|
48
|
+
onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
|
|
49
|
+
}
|
|
50
|
+
interface BigIntInputState {
|
|
51
|
+
display: string;
|
|
52
|
+
focused: boolean;
|
|
53
|
+
}
|
|
54
|
+
declare class BigIntInput extends Component<BigIntInputProps, BigIntInputState> {
|
|
55
|
+
private inputRef;
|
|
56
|
+
private _resolvedFormat;
|
|
57
|
+
private _intlFormatter;
|
|
58
|
+
private _prevFormatProp;
|
|
59
|
+
private pendingCursor;
|
|
60
|
+
static defaultProps: {
|
|
61
|
+
showZero: boolean;
|
|
62
|
+
placeholder: string;
|
|
63
|
+
format: {
|
|
64
|
+
thousand: string;
|
|
65
|
+
decimal: string;
|
|
66
|
+
};
|
|
67
|
+
allowNegative: boolean;
|
|
68
|
+
};
|
|
69
|
+
constructor(props: BigIntInputProps);
|
|
70
|
+
private get fmt();
|
|
71
|
+
private formatChanged;
|
|
72
|
+
private addThousands;
|
|
73
|
+
private removeThousands;
|
|
74
|
+
private digitIndex;
|
|
75
|
+
private cursorFromDigitIndex;
|
|
76
|
+
private valueToDisplay;
|
|
77
|
+
private sanitize;
|
|
78
|
+
componentDidUpdate(prevProps: BigIntInputProps, _prevState: BigIntInputState): void;
|
|
79
|
+
private handleChange;
|
|
80
|
+
private handleKeyDown;
|
|
81
|
+
private handleFocus;
|
|
82
|
+
private handleBlur;
|
|
83
|
+
private handlePaste;
|
|
84
|
+
focus(): void;
|
|
85
|
+
blur(): void;
|
|
86
|
+
select(): void;
|
|
87
|
+
render(): react_jsx_runtime.JSX.Element;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Format a BigInt value with thousands/decimal separators.
|
|
92
|
+
*
|
|
93
|
+
* formatValue(1500000n, 6) โ "1.5"
|
|
94
|
+
* formatValue(1234567890n, 6) โ "1,234.56789"
|
|
95
|
+
* formatValue(1234567890n, 6, { locale: 'de-DE' }) โ "1.234,56789"
|
|
96
|
+
* formatValue(1234567890n, 6, 'none') โ "1234.56789"
|
|
97
|
+
*/
|
|
98
|
+
declare function formatValue(value: bigint, decimals: number, format?: {
|
|
99
|
+
locale?: string;
|
|
100
|
+
thousand?: string;
|
|
101
|
+
decimal?: string;
|
|
102
|
+
} | 'auto' | 'none'): string;
|
|
103
|
+
/**
|
|
104
|
+
* Parse a formatted string back into a BigInt value.
|
|
105
|
+
*
|
|
106
|
+
* parseValue("1,500.50", 6) โ 1500500000n
|
|
107
|
+
* parseValue("1.500,50", 6, { locale: 'de-DE' }) โ 1500500000n
|
|
108
|
+
* parseValue("1500", 6, 'none') โ 1500000000n
|
|
109
|
+
* parseValue("1,00,000", 6, { locale: 'en-IN' }) โ 100000000000n
|
|
110
|
+
*/
|
|
111
|
+
declare function parseValue(value: string, decimals: number, format?: {
|
|
112
|
+
locale?: string;
|
|
113
|
+
thousand?: string;
|
|
114
|
+
decimal?: string;
|
|
115
|
+
} | 'auto' | 'none'): bigint;
|
|
116
|
+
|
|
117
|
+
export { BigIntInput, type BigIntInputProps, type FormatConfig, formatValue, parseValue };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React, { Component } from 'react';
|
|
3
|
+
|
|
4
|
+
interface FormatConfig {
|
|
5
|
+
/** Use Intl.NumberFormat with this locale for grouping (e.g. 'de-DE', 'en-IN') */
|
|
6
|
+
locale?: string;
|
|
7
|
+
/** Thousands grouping character (e.g. ',' โ 1,000) */
|
|
8
|
+
thousand?: string;
|
|
9
|
+
/** Decimal point character (e.g. '.' โ 1.5) */
|
|
10
|
+
decimal?: string;
|
|
11
|
+
}
|
|
12
|
+
interface BigIntInputProps {
|
|
13
|
+
/** Current value as BigInt in smallest unit (e.g. wei) */
|
|
14
|
+
value: bigint;
|
|
15
|
+
/** Token decimals (e.g. 18 for ETH, 6 for USDC) */
|
|
16
|
+
decimals: number;
|
|
17
|
+
/** Fires when the BigInt value changes */
|
|
18
|
+
onChange: (value: bigint) => void;
|
|
19
|
+
/** Maximum allowed value (clamped on input) */
|
|
20
|
+
max?: bigint;
|
|
21
|
+
/** Minimum allowed value (clamped on input) */
|
|
22
|
+
min?: bigint;
|
|
23
|
+
/** Number formatting โ "auto" (browser locale), "none" (raw digits), or a config object */
|
|
24
|
+
format?: FormatConfig | 'auto' | 'none';
|
|
25
|
+
/** Allow negative values (default: false) */
|
|
26
|
+
allowNegative?: boolean;
|
|
27
|
+
/** Render "0" instead of empty when value is 0n */
|
|
28
|
+
showZero?: boolean;
|
|
29
|
+
/** Placeholder text */
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
/** Disable the input */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/** Read-only mode */
|
|
34
|
+
readOnly?: boolean;
|
|
35
|
+
/** CSS class name */
|
|
36
|
+
className?: string;
|
|
37
|
+
/** Inline styles */
|
|
38
|
+
style?: React.CSSProperties;
|
|
39
|
+
/** HTML name attribute */
|
|
40
|
+
name?: string;
|
|
41
|
+
/** HTML id attribute */
|
|
42
|
+
id?: string;
|
|
43
|
+
/** Auto-focus on mount */
|
|
44
|
+
autoFocus?: boolean;
|
|
45
|
+
/** Focus callback */
|
|
46
|
+
onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void;
|
|
47
|
+
/** Blur callback */
|
|
48
|
+
onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
|
|
49
|
+
}
|
|
50
|
+
interface BigIntInputState {
|
|
51
|
+
display: string;
|
|
52
|
+
focused: boolean;
|
|
53
|
+
}
|
|
54
|
+
declare class BigIntInput extends Component<BigIntInputProps, BigIntInputState> {
|
|
55
|
+
private inputRef;
|
|
56
|
+
private _resolvedFormat;
|
|
57
|
+
private _intlFormatter;
|
|
58
|
+
private _prevFormatProp;
|
|
59
|
+
private pendingCursor;
|
|
60
|
+
static defaultProps: {
|
|
61
|
+
showZero: boolean;
|
|
62
|
+
placeholder: string;
|
|
63
|
+
format: {
|
|
64
|
+
thousand: string;
|
|
65
|
+
decimal: string;
|
|
66
|
+
};
|
|
67
|
+
allowNegative: boolean;
|
|
68
|
+
};
|
|
69
|
+
constructor(props: BigIntInputProps);
|
|
70
|
+
private get fmt();
|
|
71
|
+
private formatChanged;
|
|
72
|
+
private addThousands;
|
|
73
|
+
private removeThousands;
|
|
74
|
+
private digitIndex;
|
|
75
|
+
private cursorFromDigitIndex;
|
|
76
|
+
private valueToDisplay;
|
|
77
|
+
private sanitize;
|
|
78
|
+
componentDidUpdate(prevProps: BigIntInputProps, _prevState: BigIntInputState): void;
|
|
79
|
+
private handleChange;
|
|
80
|
+
private handleKeyDown;
|
|
81
|
+
private handleFocus;
|
|
82
|
+
private handleBlur;
|
|
83
|
+
private handlePaste;
|
|
84
|
+
focus(): void;
|
|
85
|
+
blur(): void;
|
|
86
|
+
select(): void;
|
|
87
|
+
render(): react_jsx_runtime.JSX.Element;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Format a BigInt value with thousands/decimal separators.
|
|
92
|
+
*
|
|
93
|
+
* formatValue(1500000n, 6) โ "1.5"
|
|
94
|
+
* formatValue(1234567890n, 6) โ "1,234.56789"
|
|
95
|
+
* formatValue(1234567890n, 6, { locale: 'de-DE' }) โ "1.234,56789"
|
|
96
|
+
* formatValue(1234567890n, 6, 'none') โ "1234.56789"
|
|
97
|
+
*/
|
|
98
|
+
declare function formatValue(value: bigint, decimals: number, format?: {
|
|
99
|
+
locale?: string;
|
|
100
|
+
thousand?: string;
|
|
101
|
+
decimal?: string;
|
|
102
|
+
} | 'auto' | 'none'): string;
|
|
103
|
+
/**
|
|
104
|
+
* Parse a formatted string back into a BigInt value.
|
|
105
|
+
*
|
|
106
|
+
* parseValue("1,500.50", 6) โ 1500500000n
|
|
107
|
+
* parseValue("1.500,50", 6, { locale: 'de-DE' }) โ 1500500000n
|
|
108
|
+
* parseValue("1500", 6, 'none') โ 1500000000n
|
|
109
|
+
* parseValue("1,00,000", 6, { locale: 'en-IN' }) โ 100000000000n
|
|
110
|
+
*/
|
|
111
|
+
declare function parseValue(value: string, decimals: number, format?: {
|
|
112
|
+
locale?: string;
|
|
113
|
+
thousand?: string;
|
|
114
|
+
decimal?: string;
|
|
115
|
+
} | 'auto' | 'none'): bigint;
|
|
116
|
+
|
|
117
|
+
export { BigIntInput, type BigIntInputProps, type FormatConfig, formatValue, parseValue };
|