@onekeyfe/react-native-text-input 0.2.9 → 3.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/OneKeyTextInput.podspec +18 -0
  2. package/README.md +10 -28
  3. package/android/build.gradle +3 -3
  4. package/android/gradle.properties +5 -5
  5. package/android/src/main/java/com/textinput/TextInputViewManager.kt +11 -7
  6. package/ios/OneKeyTextInputPasteObserver.h +11 -0
  7. package/ios/OneKeyTextInputPasteObserver.mm +204 -0
  8. package/lib/module/AndroidTextInputNativeComponent.js +111 -0
  9. package/lib/{commonjs → module}/Input.js +128 -156
  10. package/lib/module/enum.js +7 -0
  11. package/lib/module/index.js +11 -0
  12. package/lib/module/package.json +1 -0
  13. package/lib/module/type.js +4 -0
  14. package/lib/typescript/package.json +1 -0
  15. package/lib/typescript/src/index.d.ts +4 -4
  16. package/lib/typescript/src/type.d.ts +2 -2
  17. package/package.json +32 -117
  18. package/react-native.config.js +12 -0
  19. package/src/AndroidTextInputNativeComponent.js +77 -88
  20. package/src/Input.js +243 -1121
  21. package/src/enum.ts +1 -1
  22. package/src/index.tsx +5 -5
  23. package/src/type.ts +2 -2
  24. package/android/generated/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/OneKeyTextInputManagerDelegate.java +0 -26
  25. package/android/generated/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/OneKeyTextInputManagerInterface.java +0 -17
  26. package/android/generated/android/app/build/generated/source/codegen/jni/CMakeLists.txt +0 -36
  27. package/android/generated/android/app/build/generated/source/codegen/jni/RNTextInputViewSpec-generated.cpp +0 -22
  28. package/android/generated/android/app/build/generated/source/codegen/jni/RNTextInputViewSpec.h +0 -24
  29. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/ComponentDescriptors.cpp +0 -22
  30. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/ComponentDescriptors.h +0 -24
  31. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/EventEmitters.cpp +0 -24
  32. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/EventEmitters.h +0 -25
  33. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/Props.cpp +0 -25
  34. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/Props.h +0 -27
  35. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/RNTextInputViewSpecJSI-generated.cpp +0 -17
  36. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/RNTextInputViewSpecJSI.h +0 -19
  37. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/ShadowNodes.cpp +0 -17
  38. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/ShadowNodes.h +0 -32
  39. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/States.cpp +0 -16
  40. package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/RNTextInputViewSpec/States.h +0 -29
  41. package/android/src/newarch/TextInputViewManagerSpec.kt +0 -21
  42. package/android/src/oldarch/TextInputViewManagerSpec.kt +0 -9
  43. package/ios/TextInputViewManager.mm +0 -23
  44. package/ios/Utils.h +0 -8
  45. package/ios/Utils.m +0 -26
  46. package/ios/generated/build/generated/ios/RNTextInputViewSpec/RNTextInputViewSpec-generated.mm +0 -16
  47. package/ios/generated/build/generated/ios/RNTextInputViewSpec/RNTextInputViewSpec.h +0 -38
  48. package/ios/generated/build/generated/ios/RNTextInputViewSpecJSI-generated.cpp +0 -17
  49. package/ios/generated/build/generated/ios/RNTextInputViewSpecJSI.h +0 -19
  50. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/ComponentDescriptors.cpp +0 -22
  51. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/ComponentDescriptors.h +0 -24
  52. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/EventEmitters.cpp +0 -24
  53. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/EventEmitters.h +0 -25
  54. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/Props.cpp +0 -25
  55. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/Props.h +0 -27
  56. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/RCTComponentViewHelpers.h +0 -20
  57. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/ShadowNodes.cpp +0 -17
  58. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/ShadowNodes.h +0 -32
  59. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/States.cpp +0 -16
  60. package/ios/generated/build/generated/ios/react/renderer/components/RNTextInputViewSpec/States.h +0 -29
  61. package/lib/commonjs/AndroidTextInputNativeComponent.js +0 -152
  62. package/lib/commonjs/AndroidTextInputNativeComponent.js.map +0 -1
  63. package/lib/commonjs/Input.js.map +0 -1
  64. package/lib/commonjs/TextInputViewNativeComponent.ts +0 -9
  65. package/lib/commonjs/enum.js +0 -11
  66. package/lib/commonjs/enum.js.map +0 -1
  67. package/lib/commonjs/index.js +0 -28
  68. package/lib/commonjs/index.js.map +0 -1
  69. package/lib/commonjs/package.json +0 -1
  70. package/lib/commonjs/type.js +0 -6
  71. package/lib/commonjs/type.js.map +0 -1
  72. package/lib/typescript/src/TextInputViewNativeComponent.d.ts +0 -8
  73. package/lib/typescript/src/TextInputViewNativeComponent.d.ts.map +0 -1
  74. package/lib/typescript/src/enum.d.ts.map +0 -1
  75. package/lib/typescript/src/index.d.ts.map +0 -1
  76. package/lib/typescript/src/type.d.ts.map +0 -1
  77. package/src/TextInputViewNativeComponent.ts +0 -9
package/src/Input.js CHANGED
@@ -1,5 +1,3 @@
1
- /* eslint-disable prettier/prettier */
2
-
3
1
  /**
4
2
  * Copyright (c) Meta Platforms, Inc. and affiliates.
5
3
  *
@@ -13,30 +11,79 @@
13
11
  import type {HostInstance} from 'react-native/src/private/types/HostInstance';
14
12
  import type {____TextStyle_Internal as TextStyleInternal} from 'react-native/Libraries/StyleSheet/StyleSheetTypes';
15
13
  import type {
14
+ BlurEvent,
15
+ FocusEvent,
16
16
  GestureResponderEvent,
17
- NativeSyntheticEvent,
18
17
  ScrollEvent,
19
18
  } from 'react-native/Libraries/Types/CoreEventTypes';
20
- import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
21
- import type {TextInputInstance, TextInputType} from 'react-native/Libraries/Components/TextInput/TextInput.flow';
22
-
23
- import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags.js';
24
- import usePressability from 'react-native/Libraries/Pressability/usePressability.js';
25
- import flattenStyle from 'react-native/Libraries/StyleSheet/flattenStyle.js';
26
- import StyleSheet, {
27
- type ColorValue,
28
- type TextStyleProp,
29
- type ViewStyleProp,
30
- } from 'react-native/Libraries/StyleSheet/StyleSheet';
19
+ import type {
20
+ AutoCapitalize,
21
+ EnterKeyHintType,
22
+ EnterKeyHintTypeAndroid,
23
+ EnterKeyHintTypeIOS,
24
+ EnterKeyHintTypeOptions,
25
+ InputModeOptions,
26
+ KeyboardType,
27
+ KeyboardTypeAndroid,
28
+ KeyboardTypeIOS,
29
+ KeyboardTypeOptions,
30
+ ReturnKeyType,
31
+ ReturnKeyTypeAndroid,
32
+ ReturnKeyTypeIOS,
33
+ ReturnKeyTypeOptions,
34
+ Selection,
35
+ SubmitBehavior,
36
+ TextContentType,
37
+ TextInputAndroidProps,
38
+ TextInputBlurEvent,
39
+ TextInputChangeEvent,
40
+ TextInputContentSizeChangeEvent,
41
+ TextInputEditingEvent,
42
+ TextInputEndEditingEvent,
43
+ TextInputEvent,
44
+ TextInputFocusEvent,
45
+ TextInputInstance,
46
+ TextInputIOSProps,
47
+ TextInputKeyPressEvent,
48
+ TextInputProps,
49
+ TextInputSelectionChangeEvent,
50
+ TextInputSubmitEditingEvent,
51
+ TextInputType,
52
+ } from 'react-native/Libraries/Components/TextInput/TextInput.flow';
53
+
54
+ import usePressability from 'react-native/Libraries/Pressability/usePressability';
55
+ import flattenStyle from 'react-native/Libraries/StyleSheet/flattenStyle';
56
+ import StyleSheet, {type TextStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
31
57
  import Text from 'react-native/Libraries/Text/Text';
32
- import TextAncestor from 'react-native/Libraries/Text/TextAncestor';
58
+ import TextAncestorContext from 'react-native/Libraries/Text/TextAncestorContext';
33
59
  import Platform from 'react-native/Libraries/Utilities/Platform';
34
60
  import useMergeRefs from 'react-native/Libraries/Utilities/useMergeRefs';
35
61
  import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
36
62
  import invariant from 'invariant';
37
63
  import nullthrows from 'nullthrows';
38
64
  import * as React from 'react';
39
- import {useCallback, useLayoutEffect, useRef, useState} from 'react';
65
+ import {useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
66
+ import {findNodeHandle, NativeEventEmitter, NativeModules} from 'react-native';
67
+
68
+ type OneKeyPasteItem = Readonly<{
69
+ type: string,
70
+ data: string,
71
+ }>;
72
+
73
+ type OneKeyPasteEvent = Readonly<{
74
+ nativeEvent: Readonly<{
75
+ items: ReadonlyArray<OneKeyPasteItem>,
76
+ }>,
77
+ }>;
78
+
79
+ type OneKeyTextInputProps = TextInputProps & {
80
+ onPaste?: ?(event: OneKeyPasteEvent) => void,
81
+ };
82
+
83
+ const iosPasteEmitter =
84
+ Platform.OS === 'ios' && NativeModules.OneKeyTextInputPasteObserver != null
85
+ ? new NativeEventEmitter(NativeModules.OneKeyTextInputPasteObserver)
86
+ : null;
40
87
 
41
88
  let AndroidTextInput;
42
89
  let AndroidTextInputCommands;
@@ -60,939 +107,70 @@ if (Platform.OS === 'android') {
60
107
  require('react-native/Libraries/Components/TextInput/RCTMultilineTextInputNativeComponent').Commands;
61
108
  }
62
109
 
63
- export type TextInputChangeEventData = $ReadOnly<{
64
- eventCount: number,
65
- target: number,
66
- text: string,
67
- }>;
68
-
69
- export type TextInputChangeEvent =
70
- NativeSyntheticEvent<TextInputChangeEventData>;
71
-
72
- export type TextInputEvent = NativeSyntheticEvent<
73
- $ReadOnly<{
74
- eventCount: number,
75
- previousText: string,
76
- range: $ReadOnly<{
77
- start: number,
78
- end: number,
79
- }>,
80
- target: number,
81
- text: string,
82
- }>,
83
- >;
84
-
85
- export type TextInputContentSizeChangeEventData = $ReadOnly<{
86
- target: number,
87
- contentSize: $ReadOnly<{
88
- width: number,
89
- height: number,
90
- }>,
91
- }>;
92
-
93
- export type TextInputContentSizeChangeEvent =
94
- NativeSyntheticEvent<TextInputContentSizeChangeEventData>;
95
-
96
- export type TargetEvent = $ReadOnly<{
97
- target: number,
98
- }>;
99
-
100
- export type TextInputFocusEventData = TargetEvent;
101
-
102
- export type TextInputBlurEvent = NativeSyntheticEvent<TextInputFocusEventData>;
103
- export type TextInputFocusEvent = NativeSyntheticEvent<TextInputFocusEventData>;
104
-
105
- type Selection = $ReadOnly<{
106
- start: number,
107
- end: number,
108
- }>;
109
-
110
- export type TextInputSelectionChangeEventData = $ReadOnly<{
111
- ...TargetEvent,
112
- selection: Selection,
113
- }>;
114
-
115
- export type TextInputSelectionChangeEvent =
116
- NativeSyntheticEvent<TextInputSelectionChangeEventData>;
117
-
118
- type TextInputKeyPressEventData = $ReadOnly<{
119
- ...TargetEvent,
120
- key: string,
121
- target?: ?number,
122
- eventCount?: ?number,
123
- }>;
124
-
125
- export type TextInputKeyPressEvent =
126
- NativeSyntheticEvent<TextInputKeyPressEventData>;
127
-
128
- export type TextInputEndEditingEventData = $ReadOnly<{
129
- ...TargetEvent,
130
- eventCount: number,
131
- text: string,
132
- }>;
133
-
134
- export type TextInputEditingEvent =
135
- NativeSyntheticEvent<TextInputEndEditingEventData>;
136
-
137
- type DataDetectorTypesType =
138
- | 'phoneNumber'
139
- | 'link'
140
- | 'address'
141
- | 'calendarEvent'
142
- | 'trackingNumber'
143
- | 'flightNumber'
144
- | 'lookupSuggestion'
145
- | 'none'
146
- | 'all';
147
-
148
- export type KeyboardType =
149
- | 'default'
150
- | 'email-address'
151
- | 'numeric'
152
- | 'phone-pad'
153
- | 'number-pad'
154
- | 'decimal-pad'
155
- | 'url';
156
-
157
- export type KeyboardTypeIOS =
158
- | 'ascii-capable'
159
- | 'numbers-and-punctuation'
160
- | 'name-phone-pad'
161
- | 'twitter'
162
- | 'web-search'
163
- // iOS 10+ only
164
- | 'ascii-capable-number-pad';
165
-
166
- export type KeyboardTypeAndroid = 'visible-password';
167
-
168
- export type KeyboardTypeOptions =
169
- | KeyboardType
170
- | KeyboardTypeIOS
171
- | KeyboardTypeAndroid;
172
-
173
- export type InputModeOptions =
174
- | 'none'
175
- | 'text'
176
- | 'decimal'
177
- | 'numeric'
178
- | 'tel'
179
- | 'search'
180
- | 'email'
181
- | 'url';
182
-
183
- export type ReturnKeyType = 'done' | 'go' | 'next' | 'search' | 'send';
184
-
185
- export type ReturnKeyTypeIOS =
186
- | 'default'
187
- | 'emergency-call'
188
- | 'google'
189
- | 'join'
190
- | 'route'
191
- | 'yahoo';
192
-
193
- export type ReturnKeyTypeAndroid = 'none' | 'previous';
194
-
195
- export type ReturnKeyTypeOptions =
196
- | ReturnKeyType
197
- | ReturnKeyTypeIOS
198
- | ReturnKeyTypeAndroid;
199
-
200
- export type SubmitBehavior = 'submit' | 'blurAndSubmit' | 'newline';
201
-
202
- export type AutoCapitalize = 'none' | 'sentences' | 'words' | 'characters';
203
-
204
- export type TextContentType =
205
- | 'none'
206
- | 'URL'
207
- | 'addressCity'
208
- | 'addressCityAndState'
209
- | 'addressState'
210
- | 'countryName'
211
- | 'creditCardNumber'
212
- | 'creditCardExpiration'
213
- | 'creditCardExpirationMonth'
214
- | 'creditCardExpirationYear'
215
- | 'creditCardSecurityCode'
216
- | 'creditCardType'
217
- | 'creditCardName'
218
- | 'creditCardGivenName'
219
- | 'creditCardMiddleName'
220
- | 'creditCardFamilyName'
221
- | 'emailAddress'
222
- | 'familyName'
223
- | 'fullStreetAddress'
224
- | 'givenName'
225
- | 'jobTitle'
226
- | 'location'
227
- | 'middleName'
228
- | 'name'
229
- | 'namePrefix'
230
- | 'nameSuffix'
231
- | 'nickname'
232
- | 'organizationName'
233
- | 'postalCode'
234
- | 'streetAddressLine1'
235
- | 'streetAddressLine2'
236
- | 'sublocality'
237
- | 'telephoneNumber'
238
- | 'username'
239
- | 'password'
240
- | 'newPassword'
241
- | 'oneTimeCode'
242
- | 'birthdate'
243
- | 'birthdateDay'
244
- | 'birthdateMonth'
245
- | 'birthdateYear'
246
- | 'cellularEID'
247
- | 'cellularIMEI'
248
- | 'dateTime'
249
- | 'flightNumber'
250
- | 'shipmentTrackingNumber';
251
-
252
- export type EnterKeyHintTypeAndroid = 'previous';
253
-
254
- export type EnterKeyHintTypeIOS = 'enter';
255
-
256
- export type EnterKeyHintType = 'done' | 'go' | 'next' | 'search' | 'send';
257
-
258
- export type EnterKeyHintTypeOptions =
259
- | EnterKeyHintType
260
- | EnterKeyHintTypeAndroid
261
- | EnterKeyHintTypeIOS;
262
-
263
- type PasswordRules = string;
264
-
265
- export type TextInputIOSProps = $ReadOnly<{
266
- /**
267
- * If true, the keyboard shortcuts (undo/redo and copy buttons) are disabled. The default value is false.
268
- * @platform ios
269
- */
270
- disableKeyboardShortcuts?: ?boolean,
271
-
272
- /**
273
- * When the clear button should appear on the right side of the text view.
274
- * This property is supported only for single-line TextInput component.
275
- * @platform ios
276
- */
277
- clearButtonMode?: ?('never' | 'while-editing' | 'unless-editing' | 'always'),
278
-
279
- /**
280
- * If `true`, clears the text field automatically when editing begins.
281
- * @platform ios
282
- */
283
- clearTextOnFocus?: ?boolean,
284
-
285
- /**
286
- * Determines the types of data converted to clickable URLs in the text input.
287
- * Only valid if `multiline={true}` and `editable={false}`.
288
- * By default no data types are detected.
289
- *
290
- * You can provide one type or an array of many types.
291
- *
292
- * Possible values for `dataDetectorTypes` are:
293
- *
294
- * - `'phoneNumber'`
295
- * - `'link'`
296
- * - `'address'`
297
- * - `'calendarEvent'`
298
- * - `'none'`
299
- * - `'all'`
300
- *
301
- * @platform ios
302
- */
303
- dataDetectorTypes?:
304
- | ?DataDetectorTypesType
305
- | $ReadOnlyArray<DataDetectorTypesType>,
306
-
307
- /**
308
- * If `true`, the keyboard disables the return key when there is no text and
309
- * automatically enables it when there is text. The default value is `false`.
310
- * @platform ios
311
- */
312
- enablesReturnKeyAutomatically?: ?boolean,
313
-
314
- /**
315
- * An optional identifier which links a custom InputAccessoryView to
316
- * this text input. The InputAccessoryView is rendered above the
317
- * keyboard when this text input is focused.
318
- * @platform ios
319
- */
320
- inputAccessoryViewID?: ?string,
321
-
322
- /**
323
- * An optional label that overrides the default input accessory view button label.
324
- * @platform ios
325
- */
326
- inputAccessoryViewButtonLabel?: ?string,
327
-
328
- /**
329
- * Determines the color of the keyboard.
330
- * @platform ios
331
- */
332
- keyboardAppearance?: ?('default' | 'light' | 'dark'),
333
-
334
- /**
335
- * Provide rules for your password.
336
- * For example, say you want to require a password with at least eight characters consisting of a mix of uppercase and lowercase letters, at least one number, and at most two consecutive characters.
337
- * "required: upper; required: lower; required: digit; max-consecutive: 2; minlength: 8;"
338
- * @platform ios
339
- */
340
- passwordRules?: ?PasswordRules,
341
-
342
- /*
343
- * If `true`, allows TextInput to pass touch events to the parent component.
344
- * This allows components to be swipeable from the TextInput on iOS,
345
- * as is the case on Android by default.
346
- * If `false`, TextInput always asks to handle the input (except when disabled).
347
- * @platform ios
348
- */
349
- rejectResponderTermination?: ?boolean,
350
-
351
- /**
352
- * If `false`, scrolling of the text view will be disabled.
353
- * The default value is `true`. Does only work with 'multiline={true}'.
354
- * @platform ios
355
- */
356
- scrollEnabled?: ?boolean,
357
-
358
- /**
359
- * If `false`, disables spell-check style (i.e. red underlines).
360
- * The default value is inherited from `autoCorrect`.
361
- * @platform ios
362
- */
363
- spellCheck?: ?boolean,
364
-
365
- /**
366
- * Give the keyboard and the system information about the
367
- * expected semantic meaning for the content that users enter.
368
- * `autoComplete` property accomplishes same behavior and is recommended as its supported by both platforms.
369
- * Avoid using both `autoComplete` and `textContentType`, you can use `Platform.select` for differing platform behaviors.
370
- * For backwards compatibility, when both set, `textContentType` takes precedence on iOS.
371
- * @platform ios
372
- */
373
- textContentType?: ?TextContentType,
374
-
375
- /**
376
- * Set line break strategy on iOS.
377
- * @platform ios
378
- */
379
- lineBreakStrategyIOS?: ?('none' | 'standard' | 'hangul-word' | 'push-out'),
380
-
381
- /**
382
- * Set line break mode on iOS.
383
- * @platform ios
384
- */
385
- lineBreakModeIOS?: ?(
386
- | 'wordWrapping'
387
- | 'char'
388
- | 'clip'
389
- | 'head'
390
- | 'middle'
391
- | 'tail'
392
- ),
393
-
394
- /**
395
- * If `false`, the iOS system will not insert an extra space after a paste operation
396
- * neither delete one or two spaces after a cut or delete operation.
397
- *
398
- * The default value is `true`.
399
- *
400
- * @platform ios
401
- */
402
- smartInsertDelete?: ?boolean,
403
- }>;
404
-
405
- export type TextInputAndroidProps = $ReadOnly<{
406
- /**
407
- * When provided it will set the color of the cursor (or "caret") in the component.
408
- * Unlike the behavior of `selectionColor` the cursor color will be set independently
409
- * from the color of the text selection box.
410
- * @platform android
411
- */
412
- cursorColor?: ?ColorValue,
413
-
414
- /**
415
- * When `false`, if there is a small amount of space available around a text input
416
- * (e.g. landscape orientation on a phone), the OS may choose to have the user edit
417
- * the text inside of a full screen text input mode. When `true`, this feature is
418
- * disabled and users will always edit the text directly inside of the text input.
419
- * Defaults to `false`.
420
- * @platform android
421
- */
422
- disableFullscreenUI?: ?boolean,
423
-
424
- importantForAutofill?: ?(
425
- | 'auto'
426
- | 'no'
427
- | 'noExcludeDescendants'
428
- | 'yes'
429
- | 'yesExcludeDescendants'
430
- ),
431
-
432
- /**
433
- * If defined, the provided image resource will be rendered on the left.
434
- * The image resource must be inside `/android/app/src/main/res/drawable` and referenced
435
- * like
436
- * ```
437
- * <TextInput
438
- * inlineImageLeft='search_icon'
439
- * />
440
- * ```
441
- * @platform android
442
- */
443
- inlineImageLeft?: ?string,
444
-
445
- /**
446
- * Padding between the inline image, if any, and the text input itself.
447
- * @platform android
448
- */
449
- inlineImagePadding?: ?number,
450
-
451
- /**
452
- * Sets the number of lines for a `TextInput`. Use it with multiline set to
453
- * `true` to be able to fill the lines.
454
- * @platform android
455
- */
456
- numberOfLines?: ?number,
457
-
458
- /**
459
- * Sets the return key to the label. Use it instead of `returnKeyType`.
460
- * @platform android
461
- */
462
- returnKeyLabel?: ?string,
463
-
464
- /**
465
- * Sets the number of rows for a `TextInput`. Use it with multiline set to
466
- * `true` to be able to fill the lines.
467
- * @platform android
468
- */
469
- rows?: ?number,
470
-
471
- /**
472
- * When `false`, it will prevent the soft keyboard from showing when the field is focused.
473
- * Defaults to `true`.
474
- */
475
- showSoftInputOnFocus?: ?boolean,
476
-
477
- /**
478
- * Set text break strategy on Android API Level 23+, possible values are `simple`, `highQuality`, `balanced`
479
- * The default value is `simple`.
480
- * @platform android
481
- */
482
- textBreakStrategy?: ?('simple' | 'highQuality' | 'balanced'),
483
-
484
- /**
485
- * The color of the `TextInput` underline.
486
- * @platform android
487
- */
488
- underlineColorAndroid?: ?ColorValue,
489
- }>;
490
-
491
- export type TextInputProps = $ReadOnly<{
492
- ...$Diff<ViewProps, $ReadOnly<{style: ?ViewStyleProp}>>,
493
- ...TextInputIOSProps,
494
- ...TextInputAndroidProps,
495
-
496
- /**
497
- * Can tell `TextInput` to automatically capitalize certain characters.
498
- *
499
- * - `characters`: all characters.
500
- * - `words`: first letter of each word.
501
- * - `sentences`: first letter of each sentence (*default*).
502
- * - `none`: don't auto capitalize anything.
503
- */
504
- autoCapitalize?: ?AutoCapitalize,
505
-
506
- /**
507
- * Specifies autocomplete hints for the system, so it can provide autofill.
508
- * On Android, the system will always attempt to offer autofill by using heuristics to identify the type of content.
509
- * To disable autocomplete, set autoComplete to off.
510
- *
511
- * The following values work across platforms:
512
- *
513
- * - `additional-name`
514
- * - `address-line1`
515
- * - `address-line2`
516
- * - `birthdate-day` (iOS 17+)
517
- * - `birthdate-full` (iOS 17+)
518
- * - `birthdate-month` (iOS 17+)
519
- * - `birthdate-year` (iOS 17+)
520
- * - `cc-number`
521
- * - `cc-csc` (iOS 17+)
522
- * - `cc-exp` (iOS 17+)
523
- * - `cc-exp-day` (iOS 17+)
524
- * - `cc-exp-month` (iOS 17+)
525
- * - `cc-exp-year` (iOS 17+)
526
- * - `country`
527
- * - `current-password`
528
- * - `email`
529
- * - `family-name`
530
- * - `given-name`
531
- * - `honorific-prefix`
532
- * - `honorific-suffix`
533
- * - `name`
534
- * - `new-password`
535
- * - `off`
536
- * - `one-time-code`
537
- * - `postal-code`
538
- * - `street-address`
539
- * - `tel`
540
- * - `username`
541
- *
542
- * The following values work on iOS only:
543
- *
544
- * - `cc-name` (iOS 17+)
545
- * - `cc-given-name` (iOS 17+)
546
- * - `cc-middle-name` (iOS 17+)
547
- * - `cc-family-name` (iOS 17+)
548
- * - `cc-type` (iOS 17+)
549
- * - `nickname`
550
- * - `organization`
551
- * - `organization-title`
552
- * - `url`
553
- *
554
- * The following values work on Android only:
555
- *
556
- * - `gender`
557
- * - `name-family`
558
- * - `name-given`
559
- * - `name-middle`
560
- * - `name-middle-initial`
561
- * - `name-prefix`
562
- * - `name-suffix`
563
- * - `password`
564
- * - `password-new`
565
- * - `postal-address`
566
- * - `postal-address-country`
567
- * - `postal-address-extended`
568
- * - `postal-address-extended-postal-code`
569
- * - `postal-address-locality`
570
- * - `postal-address-region`
571
- * - `sms-otp`
572
- * - `tel-country-code`
573
- * - `tel-national`
574
- * - `tel-device`
575
- * - `username-new`
576
- */
577
- autoComplete?: ?(
578
- | 'additional-name'
579
- | 'address-line1'
580
- | 'address-line2'
581
- | 'birthdate-day'
582
- | 'birthdate-full'
583
- | 'birthdate-month'
584
- | 'birthdate-year'
585
- | 'cc-csc'
586
- | 'cc-exp'
587
- | 'cc-exp-day'
588
- | 'cc-exp-month'
589
- | 'cc-exp-year'
590
- | 'cc-number'
591
- | 'cc-name'
592
- | 'cc-given-name'
593
- | 'cc-middle-name'
594
- | 'cc-family-name'
595
- | 'cc-type'
596
- | 'country'
597
- | 'current-password'
598
- | 'email'
599
- | 'family-name'
600
- | 'gender'
601
- | 'given-name'
602
- | 'honorific-prefix'
603
- | 'honorific-suffix'
604
- | 'name'
605
- | 'name-family'
606
- | 'name-given'
607
- | 'name-middle'
608
- | 'name-middle-initial'
609
- | 'name-prefix'
610
- | 'name-suffix'
611
- | 'new-password'
612
- | 'nickname'
613
- | 'one-time-code'
614
- | 'organization'
615
- | 'organization-title'
616
- | 'password'
617
- | 'password-new'
618
- | 'postal-address'
619
- | 'postal-address-country'
620
- | 'postal-address-extended'
621
- | 'postal-address-extended-postal-code'
622
- | 'postal-address-locality'
623
- | 'postal-address-region'
624
- | 'postal-code'
625
- | 'street-address'
626
- | 'sms-otp'
627
- | 'tel'
628
- | 'tel-country-code'
629
- | 'tel-national'
630
- | 'tel-device'
631
- | 'url'
632
- | 'username'
633
- | 'username-new'
634
- | 'off'
635
- ),
636
-
637
- /**
638
- * If `false`, disables auto-correct. The default value is `true`.
639
- */
640
- autoCorrect?: ?boolean,
641
-
642
- /**
643
- * If `true`, focuses the input on `componentDidMount`.
644
- * The default value is `false`.
645
- */
646
- autoFocus?: ?boolean,
647
-
648
- /**
649
- * Specifies whether fonts should scale to respect Text Size accessibility settings. The
650
- * default is `true`.
651
- */
652
- allowFontScaling?: ?boolean,
653
-
654
- /**
655
- * If `true`, caret is hidden. The default value is `false`.
656
- *
657
- * On Android devices manufactured by Xiaomi with Android Q,
658
- * when keyboardType equals 'email-address'this will be set
659
- * in native to 'true' to prevent a system related crash. This
660
- * will cause cursor to be disabled as a side-effect.
661
- *
662
- */
663
- caretHidden?: ?boolean,
664
-
665
- /*
666
- * If `true`, contextMenuHidden is hidden. The default value is `false`.
667
- */
668
- contextMenuHidden?: ?boolean,
669
-
670
- /**
671
- * Provides an initial value that will change when the user starts typing.
672
- * Useful for simple use-cases where you do not want to deal with listening
673
- * to events and updating the value prop to keep the controlled state in sync.
674
- */
675
- defaultValue?: ?Stringish,
676
-
677
- /**
678
- * If `false`, text is not editable. The default value is `true`.
679
- */
680
- editable?: ?boolean,
681
-
682
- forwardedRef?: ?React.RefSetter<TextInputInstance>,
683
-
684
- /**
685
- * `enterKeyHint` defines what action label (or icon) to present for the enter key on virtual keyboards.
686
- *
687
- * The following values is supported:
688
- *
689
- * - `enter`
690
- * - `done`
691
- * - `go`
692
- * - `next`
693
- * - `previous`
694
- * - `search`
695
- * - `send`
696
- */
697
- enterKeyHint?: ?EnterKeyHintTypeOptions,
698
-
699
- /**
700
- * `inputMode` works like the `inputmode` attribute in HTML, it determines which
701
- * keyboard to open, e.g.`numeric` and has precedence over keyboardType
702
- *
703
- * Support the following values:
704
- *
705
- * - `none`
706
- * - `text`
707
- * - `decimal`
708
- * - `numeric`
709
- * - `tel`
710
- * - `search`
711
- * - `email`
712
- * - `url`
713
- */
714
- inputMode?: ?InputModeOptions,
715
-
716
- /**
717
- * Determines which keyboard to open, e.g.`numeric`.
718
- *
719
- * The following values work across platforms:
720
- *
721
- * - `default`
722
- * - `numeric`
723
- * - `number-pad`
724
- * - `decimal-pad`
725
- * - `email-address`
726
- * - `phone-pad`
727
- * - `url`
728
- *
729
- * *iOS Only*
730
- *
731
- * The following values work on iOS only:
732
- *
733
- * - `ascii-capable`
734
- * - `numbers-and-punctuation`
735
- * - `name-phone-pad`
736
- * - `twitter`
737
- * - `web-search`
738
- *
739
- * *Android Only*
740
- *
741
- * The following values work on Android only:
742
- *
743
- * - `visible-password`
744
- *
745
- */
746
- keyboardType?: ?KeyboardTypeOptions,
747
-
748
- /**
749
- * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled.
750
- * Possible values:
751
- * `null/undefined` (default): inherit from the parent node or the global default (0)
752
- * `0`: no max, ignore parent/global default
753
- * `>= 1`: sets the maxFontSizeMultiplier of this node to this value
754
- */
755
- maxFontSizeMultiplier?: ?number,
756
-
757
- /**
758
- * Limits the maximum number of characters that can be entered. Use this
759
- * instead of implementing the logic in JS to avoid flicker.
760
- */
761
- maxLength?: ?number,
762
-
763
- /**
764
- * If `true`, the text input can be multiple lines.
765
- * The default value is `false`.
766
- */
767
- multiline?: ?boolean,
768
-
769
- /**
770
- * Callback that is called when the text input is blurred.
771
- */
772
- onBlur?: ?(e: TextInputBlurEvent) => mixed,
773
-
774
- /**
775
- * Callback that is called when the text input's text changes.
776
- */
777
- onChange?: ?(e: TextInputChangeEvent) => mixed,
778
-
779
- /**
780
- * Callback that is called when the text input's text changes.
781
- * Changed text is passed as an argument to the callback handler.
782
- */
783
- onChangeText?: ?(text: string) => mixed,
784
-
785
- /**
786
- * Callback that is called when the text input's content size changes.
787
- * This will be called with
788
- * `{ nativeEvent: { contentSize: { width, height } } }`.
789
- *
790
- * Only called for multiline text inputs.
791
- */
792
- onContentSizeChange?: ?(e: TextInputContentSizeChangeEvent) => mixed,
793
-
794
- /**
795
- * Callback that is called when text input ends.
796
- */
797
- onEndEditing?: ?(e: TextInputEditingEvent) => mixed,
798
-
799
- /**
800
- * Callback that is called when the text input is focused.
801
- */
802
- onFocus?: ?(e: TextInputFocusEvent) => mixed,
803
-
804
- /**
805
- * Callback that is called when a key is pressed.
806
- * This will be called with `{ nativeEvent: { key: keyValue } }`
807
- * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and
808
- * the typed-in character otherwise including `' '` for space.
809
- * Fires before `onChange` callbacks.
810
- */
811
- onKeyPress?: ?(e: TextInputKeyPressEvent) => mixed,
812
-
813
- /**
814
- * Called when a single tap gesture is detected.
815
- */
816
- onPress?: ?(event: GestureResponderEvent) => mixed,
817
-
818
- /**
819
- * Called when a touch is engaged.
820
- */
821
- onPressIn?: ?(event: GestureResponderEvent) => mixed,
822
-
823
- /**
824
- * Called when a touch is released.
825
- */
826
- onPressOut?: ?(event: GestureResponderEvent) => mixed,
827
-
828
- /**
829
- * Callback that is called when the text input selection is changed.
830
- * This will be called with
831
- * `{ nativeEvent: { selection: { start, end } } }`.
832
- */
833
- onSelectionChange?: ?(e: TextInputSelectionChangeEvent) => mixed,
834
-
835
- /**
836
- * Callback that is called when the text input's submit button is pressed.
837
- * Invalid if `multiline={true}` is specified.
838
- */
839
- onSubmitEditing?: ?(e: TextInputEditingEvent) => mixed,
840
-
841
- /**
842
- * Invoked on content scroll with `{ nativeEvent: { contentOffset: { x, y } } }`.
843
- * May also contain other properties from ScrollEvent but on Android contentSize
844
- * is not provided for performance reasons.
845
- */
846
- onScroll?: ?(e: ScrollEvent) => mixed,
847
-
848
- /**
849
- * The string that will be rendered before text input has been entered.
850
- */
851
- placeholder?: ?Stringish,
852
-
853
- /**
854
- * The text color of the placeholder string.
855
- */
856
- placeholderTextColor?: ?ColorValue,
857
-
858
- /** `readOnly` works like the `readonly` attribute in HTML.
859
- * If `true`, text is not editable. The default value is `false`.
860
- * See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly
861
- * for more details.
862
- */
863
- readOnly?: ?boolean,
864
-
865
- /**
866
- * Determines how the return key should look. On Android you can also use
867
- * `returnKeyLabel`.
868
- *
869
- * *Cross platform*
870
- *
871
- * The following values work across platforms:
872
- *
873
- * - `done`
874
- * - `go`
875
- * - `next`
876
- * - `search`
877
- * - `send`
878
- *
879
- * *Android Only*
880
- *
881
- * The following values work on Android only:
882
- *
883
- * - `none`
884
- * - `previous`
885
- *
886
- * *iOS Only*
887
- *
888
- * The following values work on iOS only:
889
- *
890
- * - `default`
891
- * - `emergency-call`
892
- * - `google`
893
- * - `join`
894
- * - `route`
895
- * - `yahoo`
896
- */
897
- returnKeyType?: ?ReturnKeyTypeOptions,
898
-
899
- /**
900
- * If `true`, the text input obscures the text entered so that sensitive text
901
- * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'.
902
- */
903
- secureTextEntry?: ?boolean,
904
-
905
- /**
906
- * The start and end of the text input's selection. Set start and end to
907
- * the same value to position the cursor.
908
- */
909
- selection?: ?$ReadOnly<{
910
- start: number,
911
- end?: ?number,
912
- }>,
913
-
914
- /**
915
- * The highlight and cursor color of the text input.
916
- */
917
- selectionColor?: ?ColorValue,
918
-
919
- /**
920
- * The text selection handle color.
921
- * @platform android
922
- */
923
- selectionHandleColor?: ?ColorValue,
924
-
925
- /**
926
- * If `true`, all text will automatically be selected on focus.
927
- */
928
- selectTextOnFocus?: ?boolean,
110
+ export type {
111
+ AutoCapitalize,
112
+ BlurEvent,
113
+ EnterKeyHintType,
114
+ EnterKeyHintTypeAndroid,
115
+ EnterKeyHintTypeIOS,
116
+ EnterKeyHintTypeOptions,
117
+ FocusEvent,
118
+ InputModeOptions,
119
+ KeyboardType,
120
+ KeyboardTypeAndroid,
121
+ KeyboardTypeIOS,
122
+ KeyboardTypeOptions,
123
+ ReturnKeyType,
124
+ ReturnKeyTypeAndroid,
125
+ ReturnKeyTypeIOS,
126
+ ReturnKeyTypeOptions,
127
+ SubmitBehavior,
128
+ TextContentType,
129
+ TextInputAndroidProps,
130
+ TextInputBlurEvent,
131
+ TextInputChangeEvent,
132
+ TextInputContentSizeChangeEvent,
133
+ TextInputEditingEvent,
134
+ TextInputEndEditingEvent,
135
+ TextInputEvent,
136
+ TextInputFocusEvent,
137
+ TextInputIOSProps,
138
+ TextInputKeyPressEvent,
139
+ TextInputProps,
140
+ TextInputSelectionChangeEvent,
141
+ TextInputSubmitEditingEvent,
142
+ };
929
143
 
144
+ type TextInputStateType = Readonly<{
930
145
  /**
931
- * If `true`, the text field will blur when submitted.
932
- * The default value is true for single-line fields and false for
933
- * multiline fields. Note that for multiline fields, setting `blurOnSubmit`
934
- * to `true` means that pressing return will blur the field and trigger the
935
- * `onSubmitEditing` event instead of inserting a newline into the field.
936
- *
937
- * @deprecated
938
- * Note that `submitBehavior` now takes the place of `blurOnSubmit` and will
939
- * override any behavior defined by `blurOnSubmit`.
940
- * @see submitBehavior
146
+ * @deprecated Use currentlyFocusedInput
147
+ * Returns the ID of the currently focused text field, if one exists
148
+ * If no text field is focused it returns null
941
149
  */
942
- blurOnSubmit?: ?boolean,
150
+ currentlyFocusedField: () => ?number,
943
151
 
944
152
  /**
945
- * When the return key is pressed,
946
- *
947
- * For single line inputs:
948
- *
949
- * - `'newline`' defaults to `'blurAndSubmit'`
950
- * - `undefined` defaults to `'blurAndSubmit'`
951
- *
952
- * For multiline inputs:
953
- *
954
- * - `'newline'` adds a newline
955
- * - `undefined` defaults to `'newline'`
956
- *
957
- * For both single line and multiline inputs:
958
- *
959
- * - `'submit'` will only send a submit event and not blur the input
960
- * - `'blurAndSubmit`' will both blur the input and send a submit event
153
+ * Returns the ref of the currently focused text field, if one exists
154
+ * If no text field is focused it returns null
961
155
  */
962
- submitBehavior?: ?SubmitBehavior,
156
+ currentlyFocusedInput: () => ?HostInstance,
963
157
 
964
158
  /**
965
- * Note that not all Text styles are supported, an incomplete list of what is not supported includes:
966
- *
967
- * - `borderLeftWidth`
968
- * - `borderTopWidth`
969
- * - `borderRightWidth`
970
- * - `borderBottomWidth`
971
- * - `borderTopLeftRadius`
972
- * - `borderTopRightRadius`
973
- * - `borderBottomRightRadius`
974
- * - `borderBottomLeftRadius`
975
- *
976
- * see [Issue#7070](https://github.com/facebook/react-native/issues/7070)
977
- * for more detail.
978
- *
979
- * [Styles](docs/style.html)
159
+ * @param textField ref of the text field to focus
160
+ * Focuses the specified text field
161
+ * noop if the text field was already focused
980
162
  */
981
- style?: ?TextStyleProp,
163
+ focusTextInput: (textField: ?HostInstance) => void,
982
164
 
983
165
  /**
984
- * The value to show for the text input. `TextInput` is a controlled
985
- * component, which means the native value will be forced to match this
986
- * value prop if provided. For most uses, this works great, but in some
987
- * cases this may cause flickering - one common cause is preventing edits
988
- * by keeping value the same. In addition to simply setting the same value,
989
- * either set `editable={false}`, or set/update `maxLength` to prevent
990
- * unwanted edits without flicker.
166
+ * @param textField ref of the text field to focus
167
+ * Unfocuses the specified text field
168
+ * noop if it wasn't focused
991
169
  */
992
- value?: ?Stringish,
170
+ blurTextInput: (textField: ?HostInstance) => void,
993
171
  }>;
994
172
 
995
- type ViewCommands = $NonMaybeType<
173
+ type ViewCommands = NonNullable<
996
174
  | typeof AndroidTextInputCommands
997
175
  | typeof RCTMultilineTextInputNativeCommands
998
176
  | typeof RCTSinglelineTextInputNativeCommands,
@@ -1010,7 +188,7 @@ const emptyFunctionThatReturnsTrue = () => true;
1010
188
  * in native and in JavaScript. This is necessary due to the asynchronous nature
1011
189
  * of text input events.
1012
190
  */
1013
- function useTextInputStateSynchronization_STATE({
191
+ function useTextInputStateSynchronization({
1014
192
  props,
1015
193
  mostRecentEventCount,
1016
194
  selection,
@@ -1031,8 +209,8 @@ function useTextInputStateSynchronization_STATE({
1031
209
  const [lastNativeText, setLastNativeText] = useState<?Stringish>(props.value);
1032
210
  const [lastNativeSelectionState, setLastNativeSelection] =
1033
211
  useState<LastNativeSelection>({
1034
- selection: {start: -1, end: -1},
1035
- mostRecentEventCount: mostRecentEventCount,
212
+ mostRecentEventCount,
213
+ selection: {end: -1, start: -1},
1036
214
  });
1037
215
 
1038
216
  const lastNativeSelection = lastNativeSelectionState.selection;
@@ -1055,7 +233,7 @@ function useTextInputStateSynchronization_STATE({
1055
233
  lastNativeSelection.end !== selection.end)
1056
234
  ) {
1057
235
  nativeUpdate.selection = selection;
1058
- setLastNativeSelection({selection, mostRecentEventCount});
236
+ setLastNativeSelection({mostRecentEventCount, selection});
1059
237
  }
1060
238
 
1061
239
  if (Object.keys(nativeUpdate).length === 0) {
@@ -1083,95 +261,7 @@ function useTextInputStateSynchronization_STATE({
1083
261
  viewCommands,
1084
262
  ]);
1085
263
 
1086
- return {setLastNativeText, setLastNativeSelection};
1087
- }
1088
-
1089
- /**
1090
- * This hook handles the synchronization between the state of the text input
1091
- * in native and in JavaScript. This is necessary due to the asynchronous nature
1092
- * of text input events.
1093
- */
1094
- function useTextInputStateSynchronization_REFS({
1095
- props,
1096
- mostRecentEventCount,
1097
- selection,
1098
- inputRef,
1099
- text,
1100
- viewCommands,
1101
- }: {
1102
- props: TextInputProps,
1103
- mostRecentEventCount: number,
1104
- selection: ?Selection,
1105
- inputRef: React.RefObject<null | TextInputInstance>,
1106
- text?: string,
1107
- viewCommands: ViewCommands,
1108
- }): {
1109
- setLastNativeText: string => void,
1110
- setLastNativeSelection: LastNativeSelection => void,
1111
- } {
1112
- const lastNativeTextRef = useRef<?Stringish>(props.value);
1113
- const lastNativeSelectionRef = useRef<LastNativeSelection>({
1114
- selection: {start: -1, end: -1},
1115
- mostRecentEventCount: mostRecentEventCount,
1116
- });
1117
-
1118
- // This is necessary in case native updates the text and JS decides
1119
- // that the update should be ignored and we should stick with the value
1120
- // that we have in JS.
1121
- useLayoutEffect(() => {
1122
- const nativeUpdate: {text?: string, selection?: Selection} = {};
1123
-
1124
- const lastNativeSelection = lastNativeSelectionRef.current.selection;
1125
-
1126
- if (
1127
- lastNativeTextRef.current !== props.value &&
1128
- typeof props.value === 'string'
1129
- ) {
1130
- nativeUpdate.text = props.value;
1131
- lastNativeTextRef.current = props.value;
1132
- }
1133
-
1134
- if (
1135
- selection &&
1136
- lastNativeSelection &&
1137
- (lastNativeSelection.start !== selection.start ||
1138
- lastNativeSelection.end !== selection.end)
1139
- ) {
1140
- nativeUpdate.selection = selection;
1141
- lastNativeSelectionRef.current = {selection, mostRecentEventCount};
1142
- }
1143
-
1144
- if (Object.keys(nativeUpdate).length === 0) {
1145
- return;
1146
- }
1147
-
1148
- if (inputRef.current != null) {
1149
- viewCommands.setTextAndSelection(
1150
- inputRef.current,
1151
- mostRecentEventCount,
1152
- text,
1153
- selection?.start ?? -1,
1154
- selection?.end ?? -1,
1155
- );
1156
- }
1157
- }, [
1158
- mostRecentEventCount,
1159
- inputRef,
1160
- props.value,
1161
- props.defaultValue,
1162
- selection,
1163
- text,
1164
- viewCommands,
1165
- ]);
1166
-
1167
- return {
1168
- setLastNativeText: lastNativeText => {
1169
- lastNativeTextRef.current = lastNativeText;
1170
- },
1171
- setLastNativeSelection: lastNativeSelection => {
1172
- lastNativeSelectionRef.current = lastNativeSelection;
1173
- },
1174
- };
264
+ return {setLastNativeSelection, setLastNativeText};
1175
265
  }
1176
266
 
1177
267
  /**
@@ -1285,7 +375,7 @@ function useTextInputStateSynchronization_REFS({
1285
375
  * or control this param programmatically with native code.
1286
376
  *
1287
377
  */
1288
- function InternalTextInput(props: TextInputProps): React.Node {
378
+ function InternalTextInput(props: OneKeyTextInputProps): React.Node {
1289
379
  const {
1290
380
  'aria-busy': ariaBusy,
1291
381
  'aria-checked': ariaChecked,
@@ -1299,17 +389,34 @@ function InternalTextInput(props: TextInputProps): React.Node {
1299
389
  selectionColor,
1300
390
  selectionHandleColor,
1301
391
  cursorColor,
392
+ onPaste,
1302
393
  ...otherProps
1303
394
  } = props;
1304
395
 
1305
396
  const inputRef = useRef<null | TextInputInstance>(null);
1306
397
 
398
+ useEffect(() => {
399
+ if (Platform.OS !== 'ios' || iosPasteEmitter == null || onPaste == null) {
400
+ return;
401
+ }
402
+ const subscription = iosPasteEmitter.addListener(
403
+ 'OneKeyTextInputPaste',
404
+ (event: {target: number, items: Array<OneKeyPasteItem>}) => {
405
+ const target = findNodeHandle(inputRef.current);
406
+ if (target != null && target === event.target) {
407
+ onPaste({nativeEvent: {items: event.items}});
408
+ }
409
+ },
410
+ );
411
+ return () => subscription.remove();
412
+ }, [onPaste]);
413
+
1307
414
  const selection: ?Selection =
1308
415
  propsSelection == null
1309
416
  ? null
1310
417
  : {
1311
- start: propsSelection.start,
1312
418
  end: propsSelection.end ?? propsSelection.start,
419
+ start: propsSelection.start,
1313
420
  };
1314
421
 
1315
422
  const text =
@@ -1326,15 +433,11 @@ function InternalTextInput(props: TextInputProps): React.Node {
1326
433
  : RCTSinglelineTextInputNativeCommands);
1327
434
 
1328
435
  const [mostRecentEventCount, setMostRecentEventCount] = useState<number>(0);
1329
- const useTextInputStateSynchronization =
1330
- ReactNativeFeatureFlags.useRefsForTextInputState()
1331
- ? useTextInputStateSynchronization_REFS
1332
- : useTextInputStateSynchronization_STATE;
1333
436
  const {setLastNativeText, setLastNativeSelection} =
1334
437
  useTextInputStateSynchronization({
1335
- props,
1336
438
  inputRef,
1337
439
  mostRecentEventCount,
440
+ props,
1338
441
  selection,
1339
442
  text,
1340
443
  viewCommands,
@@ -1384,7 +487,14 @@ function InternalTextInput(props: TextInputProps): React.Node {
1384
487
  before we can get to the long term breaking change.
1385
488
  */
1386
489
  if (instance != null) {
490
+ // Register the input immediately when the ref is set so that focus()
491
+ // can be called from ref callbacks
492
+ // Double registering during useLayoutEffect is fine, because the underlying
493
+ // state is a Set.
494
+ TextInputState.registerInput(instance);
495
+
1387
496
  // $FlowFixMe[prop-missing] - See the explanation above.
497
+ // $FlowFixMe[unsafe-object-assign]
1388
498
  Object.assign(instance, {
1389
499
  clear(): void {
1390
500
  if (inputRef.current != null) {
@@ -1397,13 +507,17 @@ function InternalTextInput(props: TextInputProps): React.Node {
1397
507
  );
1398
508
  }
1399
509
  },
1400
- // TODO: Fix this returning true on null === null, when no input is focused
1401
- isFocused(): boolean {
1402
- return TextInputState.currentlyFocusedInput() === inputRef.current;
1403
- },
1404
510
  getNativeRef(): ?TextInputInstance {
1405
511
  return inputRef.current;
1406
512
  },
513
+ isFocused(): boolean {
514
+ const currentlyFocusedInput =
515
+ TextInputState.currentlyFocusedInput();
516
+ return (
517
+ currentlyFocusedInput != null &&
518
+ currentlyFocusedInput === inputRef.current
519
+ );
520
+ },
1407
521
  setSelection(start: number, end: number): void {
1408
522
  if (inputRef.current != null) {
1409
523
  viewCommands.setTextAndSelection(
@@ -1421,7 +535,7 @@ function InternalTextInput(props: TextInputProps): React.Node {
1421
535
  [mostRecentEventCount, viewCommands],
1422
536
  );
1423
537
 
1424
- // $FlowExpectedError[incompatible-call]
538
+ // $FlowExpectedError[incompatible-type]
1425
539
  const ref = useMergeRefs<HostInstance>(setLocalRef, props.forwardedRef);
1426
540
 
1427
541
  const _onChange = (event: TextInputChangeEvent) => {
@@ -1453,19 +567,19 @@ function InternalTextInput(props: TextInputProps): React.Node {
1453
567
  }
1454
568
 
1455
569
  setLastNativeSelection({
1456
- selection: event.nativeEvent.selection,
1457
570
  mostRecentEventCount,
571
+ selection: event.nativeEvent.selection,
1458
572
  });
1459
573
  };
1460
574
 
1461
- const _onFocus = (event: TextInputFocusEvent) => {
575
+ const _onFocus = (event: FocusEvent) => {
1462
576
  TextInputState.focusInput(inputRef.current);
1463
577
  if (props.onFocus) {
1464
578
  props.onFocus(event);
1465
579
  }
1466
580
  };
1467
581
 
1468
- const _onBlur = (event: TextInputBlurEvent) => {
582
+ const _onBlur = (event: BlurEvent) => {
1469
583
  TextInputState.blurInput(inputRef.current);
1470
584
  if (props.onBlur) {
1471
585
  props.onBlur(event);
@@ -1516,8 +630,9 @@ function InternalTextInput(props: TextInputProps): React.Node {
1516
630
  rejectResponderTermination,
1517
631
  } = props;
1518
632
 
1519
- const config = React.useMemo(
633
+ const config = useMemo(
1520
634
  () => ({
635
+ cancelable: Platform.OS === 'ios' ? !rejectResponderTermination : null,
1521
636
  hitSlop,
1522
637
  onPress: (event: GestureResponderEvent) => {
1523
638
  onPress?.(event);
@@ -1527,9 +642,8 @@ function InternalTextInput(props: TextInputProps): React.Node {
1527
642
  }
1528
643
  }
1529
644
  },
1530
- onPressIn: onPressIn,
1531
- onPressOut: onPressOut,
1532
- cancelable: Platform.OS === 'ios' ? !rejectResponderTermination : null,
645
+ onPressIn,
646
+ onPressOut,
1533
647
  }),
1534
648
  [
1535
649
  editable,
@@ -1552,6 +666,9 @@ function InternalTextInput(props: TextInputProps): React.Node {
1552
666
  // so omitting onBlur and onFocus pressability handlers here.
1553
667
  const {onBlur, onFocus, ...eventHandlers} = usePressability(config);
1554
668
 
669
+ const _accessibilityLabel =
670
+ props?.['aria-label'] ?? props?.accessibilityLabel;
671
+
1555
672
  let _accessibilityState;
1556
673
  if (
1557
674
  accessibilityState != null ||
@@ -1576,14 +693,14 @@ function InternalTextInput(props: TextInputProps): React.Node {
1576
693
  if (flattenedStyle != null) {
1577
694
  let overrides: ?{...TextStyleInternal} = null;
1578
695
  if (typeof flattenedStyle?.fontWeight === 'number') {
1579
- overrides = overrides || ({}: {...TextStyleInternal});
696
+ overrides = overrides || ({} as {...TextStyleInternal});
1580
697
  overrides.fontWeight =
1581
- // $FlowFixMe[incompatible-cast]
1582
- (flattenedStyle.fontWeight.toString(): TextStyleInternal['fontWeight']);
698
+ // $FlowFixMe[incompatible-type]
699
+ flattenedStyle.fontWeight.toString() as TextStyleInternal['fontWeight'];
1583
700
  }
1584
701
 
1585
702
  if (flattenedStyle.verticalAlign != null) {
1586
- overrides = overrides || ({}: {...TextStyleInternal});
703
+ overrides = overrides || ({} as {...TextStyleInternal});
1587
704
  overrides.textAlignVertical =
1588
705
  verticalAlignToTextAlignVerticalMap[flattenedStyle.verticalAlign];
1589
706
  overrides.verticalAlign = undefined;
@@ -1608,13 +725,19 @@ function InternalTextInput(props: TextInputProps): React.Node {
1608
725
  flattenedStyle.paddingVertical == null &&
1609
726
  flattenedStyle.paddingTop == null));
1610
727
 
728
+ const _accessibilityElementsHidden =
729
+ props['aria-hidden'] ?? props.accessibilityElementsHidden;
730
+
1611
731
  textInput = (
1612
732
  <RCTTextInputView
1613
733
  // Figure out imperative + forward refs.
1614
- ref={(ref: $FlowFixMe)}
734
+ ref={ref as $FlowFixMe}
1615
735
  {...otherProps}
1616
736
  {...eventHandlers}
737
+ acceptDragAndDropTypes={props.experimental_acceptDragAndDropTypes}
738
+ accessibilityLabel={_accessibilityLabel}
1617
739
  accessibilityState={_accessibilityState}
740
+ accessibilityElementsHidden={_accessibilityElementsHidden}
1618
741
  accessible={accessible}
1619
742
  submitBehavior={submitBehavior}
1620
743
  caretHidden={caretHidden}
@@ -1643,6 +766,10 @@ function InternalTextInput(props: TextInputProps): React.Node {
1643
766
  const autoCapitalize = props.autoCapitalize || 'sentences';
1644
767
  const _accessibilityLabelledBy =
1645
768
  props?.['aria-labelledby'] ?? props?.accessibilityLabelledBy;
769
+ const _importantForAccessibility =
770
+ props['aria-hidden'] === true
771
+ ? ('no-hide-descendants' as const)
772
+ : undefined;
1646
773
  const placeholder = props.placeholder ?? '';
1647
774
  let children = props.children;
1648
775
  const childCount = React.Children.count(children);
@@ -1655,14 +782,13 @@ function InternalTextInput(props: TextInputProps): React.Node {
1655
782
  }
1656
783
  // For consistency with iOS set cursor/selectionHandle color as selectionColor
1657
784
  const colorProps = {
785
+ cursorColor: cursorColor === undefined ? selectionColor : cursorColor,
1658
786
  selectionColor,
1659
787
  selectionHandleColor:
1660
788
  selectionHandleColor === undefined
1661
789
  ? selectionColor
1662
790
  : selectionHandleColor,
1663
- cursorColor: cursorColor === undefined ? selectionColor : cursorColor,
1664
791
  };
1665
- const { onPaste, ...rest } = otherProps;
1666
792
  textInput = (
1667
793
  /* $FlowFixMe[prop-missing] the types for AndroidTextInput don't match up
1668
794
  * exactly with the props for TextInput. This will need to get fixed */
@@ -1674,30 +800,33 @@ function InternalTextInput(props: TextInputProps): React.Node {
1674
800
  * fixed */
1675
801
  <AndroidTextInput
1676
802
  // Figure out imperative + forward refs.
1677
- ref={(ref: $FlowFixMe)}
1678
- {...rest}
803
+ ref={ref as $FlowFixMe}
804
+ {...otherProps}
1679
805
  {...colorProps}
1680
806
  {...eventHandlers}
1681
- onPaste={onPaste}
1682
- accessibilityState={_accessibilityState}
807
+ accessibilityLabel={_accessibilityLabel}
1683
808
  accessibilityLabelledBy={_accessibilityLabelledBy}
809
+ accessibilityState={_accessibilityState}
1684
810
  accessible={accessible}
811
+ acceptDragAndDropTypes={props.experimental_acceptDragAndDropTypes}
1685
812
  autoCapitalize={autoCapitalize}
1686
813
  submitBehavior={submitBehavior}
1687
814
  caretHidden={caretHidden}
1688
815
  children={children}
1689
816
  disableFullscreenUI={props.disableFullscreenUI}
1690
817
  focusable={tabIndex !== undefined ? !tabIndex : focusable}
818
+ importantForAccessibility={_importantForAccessibility}
1691
819
  mostRecentEventCount={mostRecentEventCount}
1692
820
  nativeID={id ?? props.nativeID}
1693
821
  numberOfLines={props.rows ?? props.numberOfLines}
1694
822
  onBlur={_onBlur}
1695
823
  onChange={_onChange}
1696
824
  onFocus={_onFocus}
825
+ onPaste={onPaste}
1697
826
  /* $FlowFixMe[prop-missing] the types for AndroidTextInput don't match
1698
827
  * up exactly with the props for TextInput. This will need to get fixed
1699
828
  */
1700
- /* $FlowFixMe[incompatible-type-arg] the types for AndroidTextInput
829
+ /* $FlowFixMe[incompatible-type] the types for AndroidTextInput
1701
830
  * don't match up exactly with the props for TextInput. This will need
1702
831
  * to get fixed */
1703
832
  onScroll={_onScroll}
@@ -1709,34 +838,34 @@ function InternalTextInput(props: TextInputProps): React.Node {
1709
838
  />
1710
839
  );
1711
840
  }
1712
- return (
1713
- <TextAncestor.Provider value={true}>{textInput}</TextAncestor.Provider>
1714
- );
841
+ return <TextAncestorContext value={true}>{textInput}</TextAncestorContext>;
1715
842
  }
1716
843
 
1717
844
  const enterKeyHintToReturnTypeMap = {
1718
- enter: 'default',
1719
845
  done: 'done',
846
+ enter: 'default',
1720
847
  go: 'go',
1721
848
  next: 'next',
1722
849
  previous: 'previous',
1723
850
  search: 'search',
1724
851
  send: 'send',
1725
- };
852
+ } as const;
1726
853
 
1727
854
  const inputModeToKeyboardTypeMap = {
1728
- none: 'default',
1729
- text: 'default',
1730
855
  decimal: 'decimal-pad',
856
+ email: 'email-address',
857
+ none: 'default',
1731
858
  numeric: 'number-pad',
859
+ search:
860
+ Platform.OS === 'ios' ? ('web-search' as const) : ('default' as const),
1732
861
  tel: 'phone-pad',
1733
- search: Platform.OS === 'ios' ? 'web-search' : 'default',
1734
- email: 'email-address',
862
+ text: 'default',
1735
863
  url: 'url',
1736
- };
864
+ } as const;
1737
865
 
1738
866
  // Map HTML autocomplete values to Android autoComplete values
1739
867
  const autoCompleteWebToAutoCompleteAndroidMap = {
868
+ 'additional-name': 'name-middle',
1740
869
  'address-line1': 'postal-address-region',
1741
870
  'address-line2': 'postal-address-locality',
1742
871
  bday: 'birthdate-full',
@@ -1751,12 +880,11 @@ const autoCompleteWebToAutoCompleteAndroidMap = {
1751
880
  country: 'postal-address-country',
1752
881
  'current-password': 'password',
1753
882
  email: 'email',
883
+ 'family-name': 'name-family',
884
+ 'given-name': 'name-given',
1754
885
  'honorific-prefix': 'name-prefix',
1755
886
  'honorific-suffix': 'name-suffix',
1756
887
  name: 'name',
1757
- 'additional-name': 'name-middle',
1758
- 'family-name': 'name-family',
1759
- 'given-name': 'name-given',
1760
888
  'new-password': 'password-new',
1761
889
  off: 'off',
1762
890
  'one-time-code': 'sms-otp',
@@ -1767,37 +895,37 @@ const autoCompleteWebToAutoCompleteAndroidMap = {
1767
895
  'tel-country-code': 'tel-country-code',
1768
896
  'tel-national': 'tel-national',
1769
897
  username: 'username',
1770
- };
898
+ } as const;
1771
899
 
1772
900
  // Map HTML autocomplete values to iOS textContentType values
1773
901
  const autoCompleteWebToTextContentTypeMap = {
902
+ 'additional-name': 'middleName',
1774
903
  'address-line1': 'streetAddressLine1',
1775
904
  'address-line2': 'streetAddressLine2',
1776
905
  bday: 'birthdate',
1777
906
  'bday-day': 'birthdateDay',
1778
907
  'bday-month': 'birthdateMonth',
1779
908
  'bday-year': 'birthdateYear',
909
+ 'cc-additional-name': 'creditCardMiddleName',
1780
910
  'cc-csc': 'creditCardSecurityCode',
911
+ 'cc-exp': 'creditCardExpiration',
1781
912
  'cc-exp-month': 'creditCardExpirationMonth',
1782
913
  'cc-exp-year': 'creditCardExpirationYear',
1783
- 'cc-exp': 'creditCardExpiration',
1784
- 'cc-given-name': 'creditCardGivenName',
1785
- 'cc-additional-name': 'creditCardMiddleName',
1786
914
  'cc-family-name': 'creditCardFamilyName',
915
+ 'cc-given-name': 'creditCardGivenName',
1787
916
  'cc-name': 'creditCardName',
1788
917
  'cc-number': 'creditCardNumber',
1789
918
  'cc-type': 'creditCardType',
1790
- 'current-password': 'password',
1791
919
  country: 'countryName',
920
+ 'current-password': 'password',
1792
921
  email: 'emailAddress',
1793
- name: 'name',
1794
- 'additional-name': 'middleName',
1795
922
  'family-name': 'familyName',
1796
923
  'given-name': 'givenName',
1797
- nickname: 'nickname',
1798
924
  'honorific-prefix': 'namePrefix',
1799
925
  'honorific-suffix': 'nameSuffix',
926
+ name: 'name',
1800
927
  'new-password': 'newPassword',
928
+ nickname: 'nickname',
1801
929
  off: 'none',
1802
930
  'one-time-code': 'oneTimeCode',
1803
931
  organization: 'organizationName',
@@ -1807,29 +935,30 @@ const autoCompleteWebToTextContentTypeMap = {
1807
935
  tel: 'telephoneNumber',
1808
936
  url: 'URL',
1809
937
  username: 'username',
1810
- };
938
+ } as const;
1811
939
 
1812
- const ExportedForwardRef: component(
1813
- ref: React.RefSetter<TextInputInstance>,
940
+ const TextInput: component(
941
+ ref?: React.RefSetter<TextInputInstance>,
1814
942
  ...props: React.ElementConfig<typeof InternalTextInput>
1815
- ) = React.forwardRef(function TextInput(
1816
- {
1817
- allowFontScaling = true,
1818
- rejectResponderTermination = true,
1819
- underlineColorAndroid = 'transparent',
1820
- autoComplete,
1821
- textContentType,
1822
- readOnly,
1823
- editable,
1824
- enterKeyHint,
1825
- returnKeyType,
1826
- inputMode,
1827
- showSoftInputOnFocus,
1828
- keyboardType,
1829
- ...restProps
1830
- },
1831
- forwardedRef: React.RefSetter<TextInputInstance>,
1832
- ) {
943
+ ) = function TextInput({
944
+ ref: forwardedRef,
945
+ allowFontScaling = true,
946
+ rejectResponderTermination = true,
947
+ underlineColorAndroid = 'transparent',
948
+ autoComplete,
949
+ textContentType,
950
+ readOnly,
951
+ editable,
952
+ enterKeyHint,
953
+ returnKeyType,
954
+ inputMode,
955
+ showSoftInputOnFocus,
956
+ keyboardType,
957
+ ...restProps
958
+ }: {
959
+ ref?: React.RefSetter<TextInputInstance>,
960
+ ...React.ElementConfig<typeof InternalTextInput>,
961
+ }) {
1833
962
  return (
1834
963
  <InternalTextInput
1835
964
  allowFontScaling={allowFontScaling}
@@ -1849,8 +978,8 @@ const ExportedForwardRef: component(
1849
978
  Platform.OS === 'android'
1850
979
  ? // $FlowFixMe[invalid-computed-prop]
1851
980
  // $FlowFixMe[prop-missing]
1852
- autoCompleteWebToAutoCompleteAndroidMap[autoComplete] ??
1853
- autoComplete
981
+ (autoCompleteWebToAutoCompleteAndroidMap[autoComplete] ??
982
+ autoComplete)
1854
983
  : undefined
1855
984
  }
1856
985
  textContentType={
@@ -1859,8 +988,7 @@ const ExportedForwardRef: component(
1859
988
  : Platform.OS === 'ios' &&
1860
989
  autoComplete &&
1861
990
  autoComplete in autoCompleteWebToTextContentTypeMap
1862
- ? // $FlowFixMe[invalid-computed-prop]
1863
- // $FlowFixMe[prop-missing]
991
+ ? // $FlowFixMe[prop-missing]
1864
992
  autoCompleteWebToTextContentTypeMap[autoComplete]
1865
993
  : textContentType
1866
994
  }
@@ -1868,26 +996,20 @@ const ExportedForwardRef: component(
1868
996
  forwardedRef={forwardedRef}
1869
997
  />
1870
998
  );
1871
- });
999
+ };
1872
1000
 
1873
- ExportedForwardRef.displayName = 'TextInput';
1001
+ TextInput.displayName = 'TextInput';
1874
1002
 
1875
1003
  // $FlowFixMe[prop-missing]
1876
- ExportedForwardRef.State = {
1877
- currentlyFocusedInput: TextInputState.currentlyFocusedInput,
1878
-
1004
+ TextInput.State = {
1005
+ blurTextInput: TextInputState.blurTextInput,
1879
1006
  currentlyFocusedField: TextInputState.currentlyFocusedField,
1007
+ currentlyFocusedInput: TextInputState.currentlyFocusedInput,
1880
1008
  focusTextInput: TextInputState.focusTextInput,
1881
- blurTextInput: TextInputState.blurTextInput,
1882
1009
  };
1883
1010
 
1884
- export type TextInputComponentStatics = $ReadOnly<{
1885
- State: $ReadOnly<{
1886
- currentlyFocusedInput: typeof TextInputState.currentlyFocusedInput,
1887
- currentlyFocusedField: typeof TextInputState.currentlyFocusedField,
1888
- focusTextInput: typeof TextInputState.focusTextInput,
1889
- blurTextInput: typeof TextInputState.blurTextInput,
1890
- }>,
1011
+ export type TextInputComponentStatics = Readonly<{
1012
+ State: TextInputStateType,
1891
1013
  }>;
1892
1014
 
1893
1015
  const styles = StyleSheet.create({
@@ -1901,10 +1023,10 @@ const styles = StyleSheet.create({
1901
1023
 
1902
1024
  const verticalAlignToTextAlignVerticalMap = {
1903
1025
  auto: 'auto',
1904
- top: 'top',
1905
1026
  bottom: 'bottom',
1906
1027
  middle: 'center',
1907
- };
1028
+ top: 'top',
1029
+ } as const;
1908
1030
 
1909
1031
  // $FlowFixMe[unclear-type] Unclear type. Using `any` type is not safe.
1910
- export default ExportedForwardRef as any as TextInputType;
1032
+ export default TextInput as any as TextInputType;