forked from inKindCards/react-native-money
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.tsx
114 lines (100 loc) · 2.75 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import React, {
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react'
import {
findNodeHandle,
NativeModules,
TextInput,
TextInputProps,
} from 'react-native'
const {RNMoneyInput} = NativeModules as {RNMoneyInput: NativeExports}
export const {
initializeMoneyInput,
extractValue,
formatMoney,
} = RNMoneyInput
if (!RNMoneyInput) {
throw new Error(`NativeModule: RNMoneyInput is null.
To fix this issue try these steps:
• Rebuild and restart the app.
• Run the packager with \`--clearCache\` flag.
• If happening on iOS, run \`pod install\` in the \`ios\` directory and then rebuild and re-run the app.
`)
}
type NativeExports = {
initializeMoneyInput: (reactNode: Number, options: any) => void
formatMoney: (value: Number, locale?: string) => string
extractValue: (label: string) => number
}
type MoneyInputProps = TextInputProps & {
value?: number
defaultValue?: number
locale?: string
onChangeText?: (value: number, label: string) => void
}
interface Handles {
focus: () => void
blur: () => void
}
const MoneyInput = forwardRef<Handles, MoneyInputProps>(
({defaultValue, value, onChangeText, locale, onFocus, ...rest}, ref) => {
// Create a default input
const [ defaultMoney ] = useState(value ?? defaultValue)
const [ defaultLabel ] = useState(defaultMoney != null ? formatMoney(
defaultMoney,
locale
) : '')
// Keep a reference to the actual text input
const input = useRef<TextInput>(null)
const [rawValue, setValue] = useState<number|undefined>(defaultMoney)
const [label, setLabel] = useState<string>(defaultLabel)
// Keep numeric prop in sync with out state
useEffect(() => {
if (value != null && rawValue != value) {
setLabel(formatMoney(
value,
locale
))
}
}, [value])
// Convert TextInput to MoneyInput native type
useEffect(() => {
const nodeId = findNodeHandle(input.current)
if (nodeId) initializeMoneyInput(nodeId, { locale })
}, [locale])
// Create a false ref interface
useImperativeHandle(ref, () => ({
focus: () => {
input.current?.focus()
},
blur: () => {
input.current?.blur()
},
}))
return (
<TextInput
{...rest}
ref={input}
value={label}
onFocus={e => {
if (defaultLabel == "" && !rawValue) {
setValue(0)
setLabel(formatMoney(0, locale));
}
onFocus?.(e)
}}
onChangeText={async label => {
const computedValue = extractValue(label)
setLabel(label)
setValue(computedValue)
onChangeText?.(computedValue, label)
}}
/>
)
}
)
export default MoneyInput