-
Notifications
You must be signed in to change notification settings - Fork 24.4k
/
TextInputState.js
191 lines (161 loc) · 5.08 KB
/
TextInputState.js
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
// This class is responsible for coordinating the "focused" state for
// TextInputs. All calls relating to the keyboard should be funneled
// through here.
'use strict';
const React = require('react');
const Platform = require('../../Utilities/Platform');
const {findNodeHandle} = require('../../Renderer/shims/ReactNative');
import {Commands as AndroidTextInputCommands} from '../../Components/TextInput/AndroidTextInputNativeComponent';
import {Commands as iOSTextInputCommands} from '../../Components/TextInput/RCTSingelineTextInputNativeComponent';
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
type ComponentRef = React.ElementRef<HostComponent<mixed>>;
let currentlyFocusedInputRef: ?ComponentRef = null;
const inputs = new Set();
function currentlyFocusedInput(): ?ComponentRef {
return currentlyFocusedInputRef;
}
/**
* Returns the ID of the currently focused text field, if one exists
* If no text field is focused it returns null
*/
function currentlyFocusedField(): ?number {
if (__DEV__) {
console.error(
'currentlyFocusedField is deprecated and will be removed in a future release. Use currentlyFocusedInput',
);
}
return findNodeHandle(currentlyFocusedInputRef);
}
function focusInput(textField: ?ComponentRef): void {
if (currentlyFocusedInputRef !== textField && textField != null) {
currentlyFocusedInputRef = textField;
}
}
function blurInput(textField: ?ComponentRef): void {
if (currentlyFocusedInputRef === textField && textField != null) {
currentlyFocusedInputRef = null;
}
}
function focusField(textFieldID: ?number): void {
if (__DEV__) {
console.error('focusField no longer works. Use focusInput');
}
return;
}
function blurField(textFieldID: ?number) {
if (__DEV__) {
console.error('blurField no longer works. Use blurInput');
}
return;
}
/**
* @param {number} TextInputID id of the text field to focus
* Focuses the specified text field
* noop if the text field was already focused
*/
function focusTextInput(textField: ?ComponentRef) {
if (typeof textField === 'number') {
if (__DEV__) {
console.error(
'focusTextInput must be called with a host component. Passing a react tag is deprecated.',
);
}
return;
}
if (currentlyFocusedInputRef !== textField && textField != null) {
focusInput(textField);
if (Platform.OS === 'ios') {
// This isn't necessarily a single line text input
// But commands don't actually care as long as the thing being passed in
// actually has a command with that name. So this should work with single
// and multiline text inputs. Ideally we'll merge them into one component
// in the future.
iOSTextInputCommands.focus(textField);
} else if (Platform.OS === 'android') {
AndroidTextInputCommands.focus(textField);
}
}
}
/**
* @param {number} textFieldID id of the text field to unfocus
* Unfocuses the specified text field
* noop if it wasn't focused
*/
function blurTextInput(textField: ?ComponentRef) {
if (typeof textField === 'number') {
if (__DEV__) {
console.error(
'focusTextInput must be called with a host component. Passing a react tag is deprecated.',
);
}
return;
}
if (currentlyFocusedInputRef === textField && textField != null) {
blurInput(textField);
if (Platform.OS === 'ios') {
// This isn't necessarily a single line text input
// But commands don't actually care as long as the thing being passed in
// actually has a command with that name. So this should work with single
// and multiline text inputs. Ideally we'll merge them into one component
// in the future.
iOSTextInputCommands.blur(textField);
} else if (Platform.OS === 'android') {
AndroidTextInputCommands.blur(textField);
}
}
}
function registerInput(textField: ComponentRef) {
if (typeof textField === 'number') {
if (__DEV__) {
console.error(
'registerInput must be called with a host component. Passing a react tag is deprecated.',
);
}
return;
}
inputs.add(textField);
}
function unregisterInput(textField: ComponentRef) {
if (typeof textField === 'number') {
if (__DEV__) {
console.error(
'unregisterInput must be called with a host component. Passing a react tag is deprecated.',
);
}
return;
}
inputs.delete(textField);
}
function isTextInput(textField: ComponentRef): boolean {
if (typeof textField === 'number') {
if (__DEV__) {
console.error(
'isTextInput must be called with a host component. Passing a react tag is deprecated.',
);
}
return false;
}
return inputs.has(textField);
}
module.exports = {
currentlyFocusedInput,
focusInput,
blurInput,
currentlyFocusedField,
focusField,
blurField,
focusTextInput,
blurTextInput,
registerInput,
unregisterInput,
isTextInput,
};