1- import React , { Component } from 'react' ;
2- import { Animated , Easing , Keyboard , TextInput , TouchableOpacity } from 'react-native' ;
3- import { Palette , Style , CleanStyle , DirtyStyle } from "./style" ;
4- import validator from "validator" ;
5-
61/**
7- * Text Input Validator
2+ * react-native-input-validator
83 * @author Marco Cesarato <[email protected] > 94 */
10- class InputValidator extends Component {
11-
12- /**
13- * Constructor
14- * @param props
15- */
16- constructor ( props ) {
17- super ( props ) ;
18-
19- const value = this . parseValue ( this . props . value ) ;
20-
21- this . state = {
22- value : value ,
23- validated : true ,
24- dirty : ( value || this . props . placeholder ) ,
25- inputStyle : {
26- borderBottomColor : "#ccc"
27- } ,
28- } ;
29-
30- this . style = this . state . dirty ? DirtyStyle : CleanStyle ;
31-
32- this . state . labelStyle = {
33- fontSize : new Animated . Value ( this . style . fontSize ) ,
34- top : new Animated . Value ( this . style . top )
35- } ;
36- }
37-
38- /**
39- * Component did update
40- * @param prevProps
41- */
42- componentDidUpdate ( prevProps ) {
43- const value = this . parseValue ( this . props . value ) ;
44- if ( ! validator . isEmpty ( value ) && value !== this . state . value && prevProps . value !== value ) {
45- this . validate ( value ) ;
46- }
47- }
48-
49- /**
50- * Component did mount
51- */
52- componentDidMount ( ) {
53- this . validate ( ) ;
54- }
55-
56- /**
57- * Get input type
58- * @returns {string }
59- */
60- getType ( ) {
61- return ( this . props . type != null ? this . props . type : "" ) ;
62- }
63-
64- /**
65- * Get Label Style
66- * @returns {{fontSize: *|AnimatedValue|AnimatedImplementation.Value, top: *|AnimatedValue|AnimatedImplementation.Value} }
67- */
68- getLabelStyle ( ) {
69- return {
70- fontSize : new Animated . Value ( this . state . style . fontSize ) ,
71- top : new Animated . Value ( this . state . style . top )
72- } ;
73- }
74-
75- /**
76- * Null to empty
77- * @param value
78- * @returns string
79- */
80- parseValue ( value ) {
81- value = ( value == null ? '' : value ) ;
82- value = String ( value ) . trim ( ) ;
83- return value ;
84- }
85-
86- /**
87- * Is valid
88- * @param _text
89- * @returns {boolean }
90- */
91- isValid ( _text ) {
92-
93- let is_valid = true ;
94- const text = this . parseValue ( _text != null ? _text : this . state . value ) . trim ( ) ;
95-
96- switch ( this . getType ( ) ) {
97- case "email" :
98- if ( ! validator . isEmail ( text ) ) {
99- is_valid = false ;
100- }
101- break ;
102- case "phone" :
103- if ( ! validator . isMobilePhone ( text , 'any' ) ) {
104- is_valid = false ;
105- }
106- break ;
107- case "postal-code" :
108- if ( ! validator . isPostalCode ( text , 'any' ) ) {
109- is_valid = false ;
110- }
111- break ;
112- case "numeric" :
113- if ( ! validator . isInt ( text ) ) {
114- is_valid = false ;
115- }
116- break ;
117- default :
118- is_valid = ! ( this . props . required ) ;
119- }
120-
121- if ( validator . isEmpty ( text ) ) {
122- is_valid = ! ( this . props . required ) ;
123- }
124-
125- return is_valid ;
126- }
127-
128- /**
129- * Validate
130- * @param _text
131- */
132- validate ( _text ) {
133-
134- let text = this . parseValue ( _text != null ? _text : this . state . value ) ;
135-
136- this . setState ( { value : text , dirty : ( text != null && ! validator . isEmpty ( text ) || this . input . isFocused ( ) ) } ) ;
137- this . animate ( ( text != null && ! validator . isEmpty ( text ) || this . input . isFocused ( ) ) ) ;
138-
139- let is_valid = this . isValid ( text ) ;
140-
141- let labelStyle = { ...this . state . labelStyle } ;
142- let inputStyle = { ...this . state . inputStyle } ;
143-
144- if ( is_valid === false ) {
145- inputStyle . borderBottomColor = Palette . dangerColor ;
146- labelStyle . color = Palette . dangerColor ;
147- } else if ( text != null && ! validator . isEmpty ( text ) && is_valid === true ) {
148- inputStyle . borderBottomColor = Palette . successColor ;
149- labelStyle . color = Palette . successColor ;
150- } else {
151- inputStyle . borderBottomColor = "#ccc" ;
152- labelStyle . color = "#AAA" ;
153- }
154-
155- this . setState ( { labelStyle : labelStyle , inputStyle : inputStyle , validated : is_valid } ) ;
156- }
157-
158- /**
159- * Animate floating label
160- * @param dirty
161- */
162- animate ( dirty ) {
163- let nextStyle = dirty ? DirtyStyle : CleanStyle ;
164- let labelStyle = this . state . labelStyle ;
165- let anims = Object . keys ( nextStyle ) . map ( prop => {
166- return Animated . timing (
167- labelStyle [ prop ] ,
168- {
169- toValue : nextStyle [ prop ] ,
170- duration : 200
171- } ,
172- Easing . ease
173- )
174- } ) ;
175-
176- Animated . parallel ( anims ) . start ( )
177- }
178-
179- /**
180- * Blur
181- */
182- blur ( ) {
183- this . input . blur ( ) ;
184- Keyboard . dismiss ( ) ;
185- }
186-
187- /**
188- * On Focus
189- * @param event
190- * @param refName
191- */
192- onFocus ( event , refName ) {
193- this . animate ( true ) ;
194- this . setState ( { dirty : true } ) ;
195- if ( this . props . onFocus ) {
196- this . props . onFocus ( event , refName ) ;
197- }
198-
199- }
200-
201- /**
202- * On Blur
203- */
204- onBlur ( ) {
205- Keyboard . dismiss ( ) ;
206- if ( this . state . value == null || validator . isEmpty ( this . state . value ) ) {
207- this . animate ( false ) ;
208- this . setState ( { dirty : false } ) ;
209- }
210- if ( this . props . onBlur ) {
211- this . props . onBlur ( arguments ) ;
212- }
213- }
214-
215- /**
216- * On Change Text
217- * @param text
218- */
219- onChangeText ( text ) {
220- this . validate ( text ) ;
221- if ( this . props . onChangeText ) {
222- this . props . onChangeText ( text ) ;
223- }
224- }
225-
226- /**
227- * On ending Editing
228- * @param event
229- */
230- onEndEditing ( event ) {
231- Keyboard . dismiss ( ) ;
232- if ( this . props . onEndEditing ) {
233- this . props . onEndEditing ( event ) ;
234- }
235- }
236-
237- /**
238- * Render label
239- * @returns {* }
240- */
241- renderLabel ( ) {
242- return (
243- < Animated . Text
244- ref = 'label'
245- pointerEvents = { "none" }
246- numberOfLines = { this . props . numberOfLines }
247- style = { [ Style . label , this . props . labelStyle , this . state . labelStyle ] } >
248- { this . props . children } { this . props . required ? "(*)" : "" }
249- </ Animated . Text >
250- )
251- }
252-
253- /**
254- * Render
255- * @returns {* }
256- */
257- render ( ) {
258-
259- let props = {
260- ...this . props ,
261- onBlur : this . onBlur . bind ( this ) ,
262- onChangeText : this . onChangeText . bind ( this ) ,
263- onEndEditing : this . onEndEditing . bind ( this ) ,
264- onFocus : this . onFocus . bind ( this ) ,
265- password : this . props . secureTextEntry || this . props . password , // Compatibility
266- secureTextEntry : this . props . secureTextEntry || this . props . password , // Compatibility
267- style : [ Style . input , this . state . inputStyle ] ,
268- } , elementStyles = [ Style . element ] ;
269-
270- if ( this . props . inputStyle ) {
271- props . style . push ( this . props . inputStyle ) ;
272- }
273-
274- if ( this . props . style ) {
275- elementStyles . push ( this . props . style ) ;
276- }
277-
278- let keyboardType = "default" ;
279-
280- if ( this . props . type ) {
281- switch ( this . props . type ) {
282- case "email" :
283- keyboardType = "email-address" ;
284- break ;
285- case "numeric" :
286- keyboardType = "numeric" ;
287- break ;
288- case "phone" :
289- keyboardType = "phone-pad" ;
290- break ;
291- }
292- }
293-
294- let onPress = props . onTouchStart ;
295-
296- delete props . children ;
297- delete props . placeholder ;
298- delete props . inputStyle ;
299- delete props . labelStyle ;
300- delete props . onTouchStart ;
301-
302- if ( props . editable === false )
303- props . pointerEvents = "none" ;
304-
305- return (
306- < View style = { elementStyles } >
307- { this . renderLabel ( ) }
308- < TextInput
309- ref = { ( r ) => {
310- this . input = r ;
311- } }
312- keyboardType = { keyboardType }
313- autoFocus = { false }
314- { ...props }
315- underlineColorAndroid = { 'transparent' } >
316- </ TextInput >
317- </ View >
318- ) ;
319- }
320- }
3215
322- export default InputValidator ;
6+ export { default as InputValidator } from "./src/InputValidator" ;
7+ export { default as InputText } from "./src/InputText" ;
0 commit comments