1 | function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2 |
|
3 | import * as React from 'react';
|
4 | import { Animated, TextInput as NativeTextInput } from 'react-native';
|
5 | import TextInputOutlined from './TextInputOutlined';
|
6 | import TextInputFlat from './TextInputFlat';
|
7 | import TextInputIcon from './Adornment/TextInputIcon';
|
8 | import TextInputAffix from './Adornment/TextInputAffix';
|
9 | import { withTheme } from '../../core/theming';
|
10 | const BLUR_ANIMATION_DURATION = 180;
|
11 | const FOCUS_ANIMATION_DURATION = 150;
|
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 | const TextInput = React.forwardRef((_ref, ref) => {
|
58 | let {
|
59 | mode = 'flat',
|
60 | dense = false,
|
61 | disabled = false,
|
62 | error: errorProp = false,
|
63 | multiline = false,
|
64 | editable = true,
|
65 | render = props => React.createElement(NativeTextInput, props),
|
66 | ...rest
|
67 | } = _ref;
|
68 | const isControlled = rest.value !== undefined;
|
69 | const validInputValue = isControlled ? rest.value : rest.defaultValue;
|
70 | const {
|
71 | current: labeled
|
72 | } = React.useRef(new Animated.Value(validInputValue ? 0 : 1));
|
73 | const {
|
74 | current: error
|
75 | } = React.useRef(new Animated.Value(errorProp ? 1 : 0));
|
76 | const [focused, setFocused] = React.useState(false);
|
77 | const [placeholder, setPlaceholder] = React.useState('');
|
78 | const [uncontrolledValue, setUncontrolledValue] = React.useState(validInputValue);
|
79 |
|
80 | const value = isControlled ? rest.value : uncontrolledValue;
|
81 | const [labelLayout, setLabelLayout] = React.useState({
|
82 | measured: false,
|
83 | width: 0,
|
84 | height: 0
|
85 | });
|
86 | const [leftLayout, setLeftLayout] = React.useState({
|
87 | width: null,
|
88 | height: null
|
89 | });
|
90 | const [rightLayout, setRightLayout] = React.useState({
|
91 | width: null,
|
92 | height: null
|
93 | });
|
94 | const timer = React.useRef();
|
95 | const root = React.useRef();
|
96 | const {
|
97 | scale
|
98 | } = rest.theme.animation;
|
99 | React.useImperativeHandle(ref, () => ({
|
100 | focus: () => {
|
101 | var _root$current;
|
102 |
|
103 | return (_root$current = root.current) === null || _root$current === void 0 ? void 0 : _root$current.focus();
|
104 | },
|
105 | clear: () => {
|
106 | var _root$current2;
|
107 |
|
108 | return (_root$current2 = root.current) === null || _root$current2 === void 0 ? void 0 : _root$current2.clear();
|
109 | },
|
110 | setNativeProps: args => {
|
111 | var _root$current3;
|
112 |
|
113 | return (_root$current3 = root.current) === null || _root$current3 === void 0 ? void 0 : _root$current3.setNativeProps(args);
|
114 | },
|
115 | isFocused: () => {
|
116 | var _root$current4;
|
117 |
|
118 | return ((_root$current4 = root.current) === null || _root$current4 === void 0 ? void 0 : _root$current4.isFocused()) || false;
|
119 | },
|
120 | blur: () => {
|
121 | var _root$current5;
|
122 |
|
123 | return (_root$current5 = root.current) === null || _root$current5 === void 0 ? void 0 : _root$current5.blur();
|
124 | },
|
125 | forceFocus: () => {
|
126 | var _root$current6;
|
127 |
|
128 | return (_root$current6 = root.current) === null || _root$current6 === void 0 ? void 0 : _root$current6.focus();
|
129 | }
|
130 | }));
|
131 | React.useEffect(() => {
|
132 |
|
133 | if (errorProp) {
|
134 |
|
135 | Animated.timing(error, {
|
136 | toValue: 1,
|
137 | duration: FOCUS_ANIMATION_DURATION * scale,
|
138 |
|
139 | useNativeDriver: true
|
140 | }).start();
|
141 | } else {
|
142 |
|
143 | {
|
144 | Animated.timing(error, {
|
145 | toValue: 0,
|
146 | duration: BLUR_ANIMATION_DURATION * scale,
|
147 |
|
148 | useNativeDriver: true
|
149 | }).start();
|
150 | }
|
151 | }
|
152 | }, [errorProp, scale, error]);
|
153 | React.useEffect(() => {
|
154 |
|
155 |
|
156 |
|
157 | if (focused || !rest.label) {
|
158 |
|
159 |
|
160 | timer.current = setTimeout(() => setPlaceholder(rest.placeholder), 50);
|
161 | } else {
|
162 |
|
163 | setPlaceholder('');
|
164 | }
|
165 |
|
166 | return () => {
|
167 | if (timer.current) {
|
168 | clearTimeout(timer.current);
|
169 | }
|
170 | };
|
171 | }, [focused, rest.label, rest.placeholder]);
|
172 | React.useEffect(() => {
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | if (value || focused) {
|
178 |
|
179 | Animated.timing(labeled, {
|
180 | toValue: 0,
|
181 | duration: BLUR_ANIMATION_DURATION * scale,
|
182 |
|
183 | useNativeDriver: true
|
184 | }).start();
|
185 | } else {
|
186 |
|
187 | {
|
188 | Animated.timing(labeled, {
|
189 | toValue: 1,
|
190 | duration: FOCUS_ANIMATION_DURATION * scale,
|
191 |
|
192 | useNativeDriver: true
|
193 | }).start();
|
194 | }
|
195 | }
|
196 | }, [focused, value, labeled, scale]);
|
197 |
|
198 | const onLeftAffixLayoutChange = event => {
|
199 | setLeftLayout({
|
200 | height: event.nativeEvent.layout.height,
|
201 | width: event.nativeEvent.layout.width
|
202 | });
|
203 | };
|
204 |
|
205 | const onRightAffixLayoutChange = event => {
|
206 | setRightLayout({
|
207 | width: event.nativeEvent.layout.width,
|
208 | height: event.nativeEvent.layout.height
|
209 | });
|
210 | };
|
211 |
|
212 | const handleFocus = args => {
|
213 | var _rest$onFocus;
|
214 |
|
215 | if (disabled || !editable) {
|
216 | return;
|
217 | }
|
218 |
|
219 | setFocused(true);
|
220 | (_rest$onFocus = rest.onFocus) === null || _rest$onFocus === void 0 ? void 0 : _rest$onFocus.call(rest, args);
|
221 | };
|
222 |
|
223 | const handleBlur = args => {
|
224 | var _rest$onBlur;
|
225 |
|
226 | if (!editable) {
|
227 | return;
|
228 | }
|
229 |
|
230 | setFocused(false);
|
231 | (_rest$onBlur = rest.onBlur) === null || _rest$onBlur === void 0 ? void 0 : _rest$onBlur.call(rest, args);
|
232 | };
|
233 |
|
234 | const handleChangeText = value => {
|
235 | var _rest$onChangeText;
|
236 |
|
237 | if (!editable || disabled) {
|
238 | return;
|
239 | }
|
240 |
|
241 | if (!isControlled) {
|
242 |
|
243 | setUncontrolledValue(value);
|
244 | }
|
245 |
|
246 | (_rest$onChangeText = rest.onChangeText) === null || _rest$onChangeText === void 0 ? void 0 : _rest$onChangeText.call(rest, value);
|
247 | };
|
248 |
|
249 | const handleLayoutAnimatedText = e => {
|
250 | setLabelLayout({
|
251 | width: e.nativeEvent.layout.width,
|
252 | height: e.nativeEvent.layout.height,
|
253 | measured: true
|
254 | });
|
255 | };
|
256 |
|
257 | const forceFocus = () => {
|
258 | var _root$current7;
|
259 |
|
260 | return (_root$current7 = root.current) === null || _root$current7 === void 0 ? void 0 : _root$current7.focus();
|
261 | };
|
262 |
|
263 | const {
|
264 | maxFontSizeMultiplier = 1.5
|
265 | } = rest;
|
266 |
|
267 | if (mode === 'outlined') {
|
268 | return React.createElement(TextInputOutlined, _extends({
|
269 | dense: dense,
|
270 | disabled: disabled,
|
271 | error: errorProp,
|
272 | multiline: multiline,
|
273 | editable: editable,
|
274 | render: render
|
275 | }, rest, {
|
276 | value: value,
|
277 | parentState: {
|
278 | labeled,
|
279 | error,
|
280 | focused,
|
281 | placeholder,
|
282 | value,
|
283 | labelLayout,
|
284 | leftLayout,
|
285 | rightLayout
|
286 | },
|
287 | innerRef: ref => {
|
288 | root.current = ref;
|
289 | },
|
290 | onFocus: handleFocus,
|
291 | forceFocus: forceFocus,
|
292 | onBlur: handleBlur,
|
293 | onChangeText: handleChangeText,
|
294 | onLayoutAnimatedText: handleLayoutAnimatedText,
|
295 | onLeftAffixLayoutChange: onLeftAffixLayoutChange,
|
296 | onRightAffixLayoutChange: onRightAffixLayoutChange,
|
297 | maxFontSizeMultiplier: maxFontSizeMultiplier
|
298 | }));
|
299 | }
|
300 |
|
301 | return React.createElement(TextInputFlat, _extends({
|
302 | dense: dense,
|
303 | disabled: disabled,
|
304 | error: errorProp,
|
305 | multiline: multiline,
|
306 | editable: editable,
|
307 | render: render
|
308 | }, rest, {
|
309 | value: value,
|
310 | parentState: {
|
311 | labeled,
|
312 | error,
|
313 | focused,
|
314 | placeholder,
|
315 | value,
|
316 | labelLayout,
|
317 | leftLayout,
|
318 | rightLayout
|
319 | },
|
320 | innerRef: ref => {
|
321 | root.current = ref;
|
322 | },
|
323 | onFocus: handleFocus,
|
324 | forceFocus: forceFocus,
|
325 | onBlur: handleBlur,
|
326 | onChangeText: handleChangeText,
|
327 | onLayoutAnimatedText: handleLayoutAnimatedText,
|
328 | onLeftAffixLayoutChange: onLeftAffixLayoutChange,
|
329 | onRightAffixLayoutChange: onRightAffixLayoutChange,
|
330 | maxFontSizeMultiplier: maxFontSizeMultiplier
|
331 | }));
|
332 | });
|
333 |
|
334 | TextInput.Icon = TextInputIcon;
|
335 |
|
336 |
|
337 | TextInput.Affix = TextInputAffix;
|
338 | export default withTheme(TextInput);
|
339 |
|
\ | No newline at end of file |