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 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
@@ -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 };
@@ -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 };