1 | import { Component, createRef } from "react";
|
2 | import PropTypes from "prop-types";
|
3 |
|
4 | import { Animated, Text } from "react-native";
|
5 |
|
6 | export default class BaseInput extends Component {
|
7 | static propTypes = {
|
8 | label: PropTypes.string,
|
9 | value: PropTypes.string,
|
10 | defaultValue: PropTypes.string,
|
11 | style: PropTypes.any,
|
12 | inputStyle: Text.propTypes?.style,
|
13 | labelStyle: Text.propTypes?.style,
|
14 | easing: PropTypes.func,
|
15 | animationDuration: PropTypes.number,
|
16 | useNativeDriver: PropTypes.bool,
|
17 |
|
18 | editable: PropTypes.bool,
|
19 |
|
20 | |
21 |
|
22 |
|
23 | onBlur: PropTypes.func,
|
24 | onFocus: PropTypes.func,
|
25 | onChange: PropTypes.func,
|
26 | };
|
27 |
|
28 | constructor(props, context) {
|
29 | super(props, context);
|
30 |
|
31 | this.input = createRef();
|
32 | this._onLayout = this._onLayout.bind(this);
|
33 | this._onChange = this._onChange.bind(this);
|
34 | this._onBlur = this._onBlur.bind(this);
|
35 | this._onFocus = this._onFocus.bind(this);
|
36 | this.focus = this.focus.bind(this);
|
37 |
|
38 | const value = props.value || props.defaultValue;
|
39 |
|
40 | this.state = {
|
41 | value,
|
42 | focusedAnim: new Animated.Value(value ? 1 : 0),
|
43 | width: null,
|
44 | };
|
45 | }
|
46 |
|
47 | componentDidUpdate() {
|
48 | const newValue = this.props.value;
|
49 | if (this.props.hasOwnProperty("value") && newValue !== this.state.value) {
|
50 | this.setState({
|
51 | value: newValue,
|
52 | });
|
53 |
|
54 |
|
55 |
|
56 | const isFocused = this.inputRef().isFocused();
|
57 | if (!isFocused) {
|
58 | const isActive = Boolean(newValue);
|
59 | if (isActive !== this.isActive) {
|
60 | this._toggle(isActive);
|
61 | }
|
62 | }
|
63 | }
|
64 | }
|
65 |
|
66 | _onLayout(event) {
|
67 | this.setState({
|
68 | width: event.nativeEvent.layout.width,
|
69 | });
|
70 | }
|
71 |
|
72 | _onChange(event) {
|
73 | this.setState({
|
74 | value: event.nativeEvent.text,
|
75 | });
|
76 |
|
77 | const onChange = this.props.onChange;
|
78 | if (onChange) {
|
79 | onChange(event);
|
80 | }
|
81 | }
|
82 |
|
83 | _onBlur(event) {
|
84 | if (!this.state.value) {
|
85 | this._toggle(false);
|
86 | }
|
87 |
|
88 | const onBlur = this.props.onBlur;
|
89 | if (onBlur) {
|
90 | onBlur(event);
|
91 | }
|
92 | }
|
93 |
|
94 | _onFocus(event) {
|
95 | this._toggle(true);
|
96 |
|
97 | const onFocus = this.props.onFocus;
|
98 | if (onFocus) {
|
99 | onFocus(event);
|
100 | }
|
101 | }
|
102 |
|
103 | _toggle(isActive) {
|
104 | const { animationDuration, easing, useNativeDriver } = this.props;
|
105 | this.isActive = isActive;
|
106 | Animated.timing(this.state.focusedAnim, {
|
107 | toValue: isActive ? 1 : 0,
|
108 | duration: animationDuration,
|
109 | easing,
|
110 | useNativeDriver: useNativeDriver || false,
|
111 | }).start();
|
112 | }
|
113 |
|
114 |
|
115 |
|
116 | inputRef() {
|
117 | return this.input.current;
|
118 | }
|
119 |
|
120 | focus() {
|
121 | if (this.props.editable !== false) {
|
122 | this.inputRef().focus();
|
123 | }
|
124 | }
|
125 |
|
126 | blur() {
|
127 | this.inputRef().blur();
|
128 | }
|
129 |
|
130 | isFocused() {
|
131 | return this.inputRef().isFocused();
|
132 | }
|
133 |
|
134 | clear() {
|
135 | this.inputRef().clear();
|
136 | }
|
137 | }
|