@tbvjaos510/react-native-paste-input 0.9.0
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.
- package/.circleci/config.yml +130 -0
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/android/.project +17 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
- package/android/build.gradle +94 -0
- package/android/generated/java/com/facebook/react/viewmanagers/PasteTextInputManagerDelegate.java +236 -0
- package/android/generated/java/com/facebook/react/viewmanagers/PasteTextInputManagerInterface.java +84 -0
- package/android/generated/jni/CMakeLists.txt +36 -0
- package/android/generated/jni/PasteTextInputSpecs-generated.cpp +27 -0
- package/android/generated/jni/PasteTextInputSpecs.h +28 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/ComponentDescriptors.cpp +22 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/ComponentDescriptors.h +166 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/EventEmitters.cpp +183 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/EventEmitters.h +148 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/PasteTextInputSpecsJSI-generated.cpp +17 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/PasteTextInputSpecsJSI.h +19 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/Props.cpp +640 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/Props.h +144 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/ShadowNodes.cpp +247 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/ShadowNodes.h +95 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/States.cpp +14 -0
- package/android/generated/jni/react/renderer/components/PasteTextInputSpecs/States.h +19 -0
- package/android/gradle.properties +6 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/IPasteInputListener.kt +8 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteInputActionCallback.kt +72 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteInputEditText.kt +60 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteInputFileFromUrl.kt +50 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteInputListener.kt +84 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteTextInputManager.kt +72 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteTextInputPackage.kt +14 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/PasteTextInputPasteEvent.java +41 -0
- package/android/src/main/java/com/mattermost/pasteinputtext/RealPathUtil.kt +174 -0
- package/ios/NSData+MimeType.h +20 -0
- package/ios/NSData+MimeType.m +59 -0
- package/ios/PasteInput-Bridging-Header.h +1 -0
- package/ios/PasteInput.xcodeproj/project.pbxproj +319 -0
- package/ios/PasteInputTextView.h +20 -0
- package/ios/PasteInputTextView.m +68 -0
- package/ios/PasteInputView.h +18 -0
- package/ios/PasteInputView.m +96 -0
- package/ios/PasteTextInput.h +13 -0
- package/ios/PasteTextInput.mm +726 -0
- package/ios/PasteTextInputManager.mm +171 -0
- package/ios/Swime/MimeType.h +70 -0
- package/ios/Swime/MimeType.m +701 -0
- package/ios/Swime/Swime.h +14 -0
- package/ios/Swime/Swime.m +28 -0
- package/ios/Swime/SwimeProxy.h +18 -0
- package/ios/Swime/SwimeProxy.m +66 -0
- package/ios/Swime/SwimeUtils.h +12 -0
- package/ios/Swime/SwimeUtils.m +23 -0
- package/ios/UIImage+ImageEffects.h +112 -0
- package/ios/UIImage+ImageEffects.m +310 -0
- package/ios/UIImage+vImageScaling.h +16 -0
- package/ios/UIImage+vImageScaling.m +48 -0
- package/ios/UIPasteboard+GetImageInfo.h +19 -0
- package/ios/UIPasteboard+GetImageInfo.m +98 -0
- package/ios/generated/PasteTextInputSpecs/ComponentDescriptors.cpp +22 -0
- package/ios/generated/PasteTextInputSpecs/ComponentDescriptors.h +42 -0
- package/ios/generated/PasteTextInputSpecs/EventEmitters.cpp +41 -0
- package/ios/generated/PasteTextInputSpecs/EventEmitters.h +37 -0
- package/ios/generated/PasteTextInputSpecs/PasteTextInputSpecs-generated.mm +16 -0
- package/ios/generated/PasteTextInputSpecs/PasteTextInputSpecs.h +38 -0
- package/ios/generated/PasteTextInputSpecs/Props.cpp +142 -0
- package/ios/generated/PasteTextInputSpecs/Props.h +81 -0
- package/ios/generated/PasteTextInputSpecs/RCTComponentViewHelpers.h +106 -0
- package/ios/generated/PasteTextInputSpecs/ShadowNodes.cpp +127 -0
- package/ios/generated/PasteTextInputSpecs/ShadowNodes.h +85 -0
- package/ios/generated/PasteTextInputSpecs/States.cpp +16 -0
- package/ios/generated/PasteTextInputSpecs/States.h +53 -0
- package/ios/generated/PasteTextInputSpecsJSI-generated.cpp +17 -0
- package/ios/generated/PasteTextInputSpecsJSI.h +19 -0
- package/lib/commonjs/PasteTextInput.js +446 -0
- package/lib/commonjs/PasteTextInput.js.map +1 -0
- package/lib/commonjs/PasteTextInputNativeComponent.ts +277 -0
- package/lib/commonjs/index.js +25 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/module.d.js +2 -0
- package/lib/commonjs/module.d.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/PasteTextInput.js +440 -0
- package/lib/module/PasteTextInput.js.map +1 -0
- package/lib/module/PasteTextInputNativeComponent.ts +277 -0
- package/lib/module/index.js +9 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/module.d.js +2 -0
- package/lib/module/module.d.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/src/PasteTextInput.d.ts +5 -0
- package/lib/typescript/src/PasteTextInput.d.ts.map +1 -0
- package/lib/typescript/src/PasteTextInputNativeComponent.d.ts +168 -0
- package/lib/typescript/src/PasteTextInputNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +56 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +140 -0
- package/react-native-paste-input.podspec +20 -0
- package/react-native.config.js +13 -0
- package/src/PasteTextInput.tsx +615 -0
- package/src/PasteTextInputNativeComponent.ts +277 -0
- package/src/index.ts +13 -0
- package/src/module.d.ts +4 -0
- package/src/types.ts +71 -0
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import PasteTextInputNativeComponent, {
|
|
3
|
+
Commands,
|
|
4
|
+
} from './PasteTextInputNativeComponent';
|
|
5
|
+
import type {
|
|
6
|
+
PasteEvent,
|
|
7
|
+
PasteInputProps,
|
|
8
|
+
PasteTextInputInstance,
|
|
9
|
+
Selection,
|
|
10
|
+
SubmitBehavior,
|
|
11
|
+
} from './types';
|
|
12
|
+
import {
|
|
13
|
+
Platform,
|
|
14
|
+
StyleSheet,
|
|
15
|
+
Text,
|
|
16
|
+
type HostComponent,
|
|
17
|
+
type KeyboardTypeOptions,
|
|
18
|
+
type NativeSyntheticEvent,
|
|
19
|
+
type NativeTouchEvent,
|
|
20
|
+
type ReturnKeyTypeOptions,
|
|
21
|
+
type TextInputChangeEventData,
|
|
22
|
+
type TextInputFocusEventData,
|
|
23
|
+
type TextInputScrollEventData,
|
|
24
|
+
type TextInputSelectionChangeEventData,
|
|
25
|
+
} from 'react-native';
|
|
26
|
+
|
|
27
|
+
import TextAncestor from 'react-native/Libraries/Text/TextAncestor';
|
|
28
|
+
import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
|
|
29
|
+
import usePressability from 'react-native/Libraries/Pressability/usePressability';
|
|
30
|
+
import flattenStyle from 'react-native/Libraries/StyleSheet/flattenStyle';
|
|
31
|
+
import nullthrows from 'nullthrows';
|
|
32
|
+
|
|
33
|
+
const emptyFunctionThatReturnsTrue = () => true;
|
|
34
|
+
|
|
35
|
+
function useMergeRefs<Instance>(
|
|
36
|
+
...refs: ReadonlyArray<React.ForwardedRef<Instance> | null | undefined>
|
|
37
|
+
): (arg0: Instance | null) => void {
|
|
38
|
+
return React.useCallback(
|
|
39
|
+
(current: Instance | null) => {
|
|
40
|
+
for (const ref of refs) {
|
|
41
|
+
if (ref != null) {
|
|
42
|
+
if (typeof ref === 'function') {
|
|
43
|
+
ref(current);
|
|
44
|
+
} else {
|
|
45
|
+
ref.current = current;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
[...refs] // eslint-disable-line react-hooks/exhaustive-deps
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function InternalTextInput(props: PasteInputProps): React.ReactNode {
|
|
55
|
+
const {
|
|
56
|
+
'aria-busy': ariaBusy,
|
|
57
|
+
'aria-checked': ariaChecked,
|
|
58
|
+
'aria-disabled': ariaDisabled,
|
|
59
|
+
'aria-expanded': ariaExpanded,
|
|
60
|
+
'aria-selected': ariaSelected,
|
|
61
|
+
accessibilityState,
|
|
62
|
+
id,
|
|
63
|
+
tabIndex,
|
|
64
|
+
'selection': propsSelection,
|
|
65
|
+
selectionColor,
|
|
66
|
+
// selectionHandleColor,
|
|
67
|
+
// cursorColor,
|
|
68
|
+
...otherProps
|
|
69
|
+
} = props;
|
|
70
|
+
|
|
71
|
+
const inputRef = React.useRef<null | React.ElementRef<HostComponent<any>>>(
|
|
72
|
+
null
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const selection: Selection | null = React.useMemo(
|
|
76
|
+
() =>
|
|
77
|
+
propsSelection == null
|
|
78
|
+
? null
|
|
79
|
+
: {
|
|
80
|
+
start: propsSelection.start,
|
|
81
|
+
end: propsSelection.end ?? propsSelection.start,
|
|
82
|
+
},
|
|
83
|
+
[propsSelection]
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const [mostRecentEventCount, setMostRecentEventCount] =
|
|
87
|
+
React.useState<number>(0);
|
|
88
|
+
const [lastNativeText, setLastNativeText] = React.useState<
|
|
89
|
+
string | undefined
|
|
90
|
+
>(props.value);
|
|
91
|
+
const [lastNativeSelectionState, setLastNativeSelection] = React.useState<{
|
|
92
|
+
selection: Selection;
|
|
93
|
+
mostRecentEventCount: number;
|
|
94
|
+
}>({
|
|
95
|
+
selection: { start: -1, end: -1 },
|
|
96
|
+
mostRecentEventCount,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const lastNativeSelection = lastNativeSelectionState.selection;
|
|
100
|
+
const text =
|
|
101
|
+
typeof props.value === 'string'
|
|
102
|
+
? props.value
|
|
103
|
+
: typeof props.defaultValue === 'string'
|
|
104
|
+
? props.defaultValue
|
|
105
|
+
: undefined;
|
|
106
|
+
|
|
107
|
+
// This is necessary in case native updates the text and JS decides
|
|
108
|
+
// that the update should be ignored and we should stick with the value
|
|
109
|
+
// that we have in JS.
|
|
110
|
+
React.useLayoutEffect(() => {
|
|
111
|
+
const nativeUpdate: { text?: string; selection?: Selection } = {};
|
|
112
|
+
|
|
113
|
+
if (lastNativeText !== props.value && typeof props.value === 'string') {
|
|
114
|
+
nativeUpdate.text = props.value;
|
|
115
|
+
setLastNativeText(props.value);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (
|
|
119
|
+
selection &&
|
|
120
|
+
lastNativeSelection &&
|
|
121
|
+
(lastNativeSelection.start !== selection.start ||
|
|
122
|
+
lastNativeSelection.end !== selection.end)
|
|
123
|
+
) {
|
|
124
|
+
nativeUpdate.selection = selection;
|
|
125
|
+
setLastNativeSelection({ selection, mostRecentEventCount });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (Object.keys(nativeUpdate).length === 0) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (inputRef.current != null) {
|
|
133
|
+
Commands.setTextAndSelection(
|
|
134
|
+
inputRef.current,
|
|
135
|
+
mostRecentEventCount,
|
|
136
|
+
text,
|
|
137
|
+
selection?.start ?? -1,
|
|
138
|
+
selection?.end ?? -1
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}, [
|
|
142
|
+
mostRecentEventCount,
|
|
143
|
+
inputRef,
|
|
144
|
+
props.value,
|
|
145
|
+
props.defaultValue,
|
|
146
|
+
lastNativeText,
|
|
147
|
+
selection,
|
|
148
|
+
lastNativeSelection,
|
|
149
|
+
text,
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
let children = props.children;
|
|
153
|
+
const childCount = React.Children.count(children);
|
|
154
|
+
if (props.value != null && childCount) {
|
|
155
|
+
throw new Error('Cannot specify both value and children');
|
|
156
|
+
}
|
|
157
|
+
if (childCount > 1) {
|
|
158
|
+
children = <Text>{children}</Text>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
React.useLayoutEffect(() => {
|
|
162
|
+
const inputRefValue = inputRef.current;
|
|
163
|
+
|
|
164
|
+
if (inputRefValue != null) {
|
|
165
|
+
TextInputState.registerInput(inputRefValue);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return () => {
|
|
169
|
+
if (inputRefValue != null) {
|
|
170
|
+
TextInputState.unregisterInput(inputRefValue);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (TextInputState.currentlyFocusedInput() === inputRefValue) {
|
|
174
|
+
nullthrows(inputRefValue).blur();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}, [inputRef]);
|
|
178
|
+
|
|
179
|
+
const setLocalRef = React.useCallback(
|
|
180
|
+
(instance: PasteTextInputInstance | null) => {
|
|
181
|
+
inputRef.current = instance;
|
|
182
|
+
if (instance != null) {
|
|
183
|
+
// $FlowFixMe[incompatible-use] - See the explanation above.
|
|
184
|
+
Object.assign(instance, {
|
|
185
|
+
clear(): void {
|
|
186
|
+
if (inputRef.current != null) {
|
|
187
|
+
Commands.setTextAndSelection(
|
|
188
|
+
inputRef.current,
|
|
189
|
+
mostRecentEventCount,
|
|
190
|
+
'',
|
|
191
|
+
0,
|
|
192
|
+
0
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
// TODO: Fix this returning true on null === null, when no input is focused
|
|
197
|
+
isFocused(): boolean {
|
|
198
|
+
return (
|
|
199
|
+
TextInputState.currentlyFocusedInput() ===
|
|
200
|
+
inputRef.current
|
|
201
|
+
);
|
|
202
|
+
},
|
|
203
|
+
getNativeRef(): null | React.ElementRef<
|
|
204
|
+
HostComponent<any>
|
|
205
|
+
> {
|
|
206
|
+
return inputRef.current;
|
|
207
|
+
},
|
|
208
|
+
setSelection(start: number, end: number): void {
|
|
209
|
+
if (inputRef.current != null) {
|
|
210
|
+
Commands.setTextAndSelection(
|
|
211
|
+
inputRef.current,
|
|
212
|
+
mostRecentEventCount,
|
|
213
|
+
null,
|
|
214
|
+
start,
|
|
215
|
+
end
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
[mostRecentEventCount]
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const ref = useMergeRefs<PasteTextInputInstance>(
|
|
226
|
+
setLocalRef,
|
|
227
|
+
props.forwardedRef
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const _onChange = (
|
|
231
|
+
event: NativeSyntheticEvent<TextInputChangeEventData>
|
|
232
|
+
) => {
|
|
233
|
+
const currentText = event.nativeEvent.text;
|
|
234
|
+
props.onChange && props.onChange(event);
|
|
235
|
+
props.onChangeText && props.onChangeText(currentText);
|
|
236
|
+
|
|
237
|
+
if (inputRef.current == null) {
|
|
238
|
+
// calling `props.onChange` or `props.onChangeText`
|
|
239
|
+
// may clean up the input itself. Exits here.
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
setLastNativeText(currentText);
|
|
244
|
+
// This must happen last, after we call setLastNativeText.
|
|
245
|
+
// Different ordering can cause bugs when editing AndroidTextInputs
|
|
246
|
+
// with multiple Fragments.
|
|
247
|
+
// We must update this so that controlled input updates work.
|
|
248
|
+
setMostRecentEventCount(event.nativeEvent.eventCount);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const _onBlur = (event: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
252
|
+
TextInputState.blurInput(inputRef.current);
|
|
253
|
+
if (props.onBlur) {
|
|
254
|
+
props.onBlur(event);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const _onFocus = (event: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
259
|
+
TextInputState.focusInput(inputRef.current);
|
|
260
|
+
if (props.onFocus) {
|
|
261
|
+
props.onFocus(event);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const _onPaste = (event: PasteEvent) => {
|
|
266
|
+
if (props.onPaste) {
|
|
267
|
+
const { data, error } = event.nativeEvent;
|
|
268
|
+
props.onPaste(error?.message, data);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const _onScroll = (
|
|
273
|
+
event: NativeSyntheticEvent<TextInputScrollEventData>
|
|
274
|
+
) => {
|
|
275
|
+
props.onScroll && props.onScroll(event);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const _onSelectionChange = (
|
|
279
|
+
event: NativeSyntheticEvent<TextInputSelectionChangeEventData>
|
|
280
|
+
) => {
|
|
281
|
+
props.onSelectionChange && props.onSelectionChange(event);
|
|
282
|
+
|
|
283
|
+
if (inputRef.current == null) {
|
|
284
|
+
// calling `props.onSelectionChange`
|
|
285
|
+
// may clean up the input itself. Exits here.
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
setLastNativeSelection({
|
|
290
|
+
selection: event.nativeEvent.selection,
|
|
291
|
+
mostRecentEventCount,
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const multiline = props.multiline ?? false;
|
|
296
|
+
|
|
297
|
+
let submitBehavior: SubmitBehavior;
|
|
298
|
+
if (props.submitBehavior != null) {
|
|
299
|
+
// `submitBehavior` is set explicitly
|
|
300
|
+
if (!multiline && props.submitBehavior === 'newline') {
|
|
301
|
+
// For single line text inputs, `'newline'` is not a valid option
|
|
302
|
+
submitBehavior = 'blurAndSubmit';
|
|
303
|
+
} else {
|
|
304
|
+
submitBehavior = props.submitBehavior;
|
|
305
|
+
}
|
|
306
|
+
} else if (multiline) {
|
|
307
|
+
if (props.blurOnSubmit === true) {
|
|
308
|
+
submitBehavior = 'blurAndSubmit';
|
|
309
|
+
} else {
|
|
310
|
+
submitBehavior = 'newline';
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
// Single line
|
|
314
|
+
if (props.blurOnSubmit !== false) {
|
|
315
|
+
submitBehavior = 'blurAndSubmit';
|
|
316
|
+
} else {
|
|
317
|
+
submitBehavior = 'submit';
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const accessible = props.accessible !== false;
|
|
322
|
+
const focusable = props.focusable !== false;
|
|
323
|
+
|
|
324
|
+
const {
|
|
325
|
+
editable,
|
|
326
|
+
hitSlop,
|
|
327
|
+
onPress,
|
|
328
|
+
onPressIn,
|
|
329
|
+
onPressOut,
|
|
330
|
+
rejectResponderTermination,
|
|
331
|
+
} = props;
|
|
332
|
+
|
|
333
|
+
const config = React.useMemo(
|
|
334
|
+
() => ({
|
|
335
|
+
hitSlop,
|
|
336
|
+
onPress: (event: NativeSyntheticEvent<NativeTouchEvent>) => {
|
|
337
|
+
onPress?.(event);
|
|
338
|
+
if (editable !== false) {
|
|
339
|
+
if (inputRef.current != null) {
|
|
340
|
+
inputRef.current.focus();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
onPressIn: onPressIn,
|
|
345
|
+
onPressOut: onPressOut,
|
|
346
|
+
cancelable:
|
|
347
|
+
Platform.OS === 'ios' ? !rejectResponderTermination : null,
|
|
348
|
+
}),
|
|
349
|
+
[
|
|
350
|
+
editable,
|
|
351
|
+
hitSlop,
|
|
352
|
+
onPress,
|
|
353
|
+
onPressIn,
|
|
354
|
+
onPressOut,
|
|
355
|
+
rejectResponderTermination,
|
|
356
|
+
]
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
// Hide caret during test runs due to a flashing caret
|
|
360
|
+
// makes screenshot tests flakey
|
|
361
|
+
let caretHidden = props.caretHidden;
|
|
362
|
+
if (Platform.isTesting) {
|
|
363
|
+
caretHidden = true;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// TextInput handles onBlur and onFocus events
|
|
367
|
+
// so omitting onBlur and onFocus pressability handlers here.
|
|
368
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
369
|
+
const { onBlur, onFocus, ...eventHandlers } = usePressability(config) || {};
|
|
370
|
+
|
|
371
|
+
let _accessibilityState;
|
|
372
|
+
if (
|
|
373
|
+
accessibilityState != null ||
|
|
374
|
+
ariaBusy != null ||
|
|
375
|
+
ariaChecked != null ||
|
|
376
|
+
ariaDisabled != null ||
|
|
377
|
+
ariaExpanded != null ||
|
|
378
|
+
ariaSelected != null
|
|
379
|
+
) {
|
|
380
|
+
_accessibilityState = {
|
|
381
|
+
busy: ariaBusy ?? accessibilityState?.busy,
|
|
382
|
+
checked: ariaChecked ?? accessibilityState?.checked,
|
|
383
|
+
disabled: ariaDisabled ?? accessibilityState?.disabled,
|
|
384
|
+
expanded: ariaExpanded ?? accessibilityState?.expanded,
|
|
385
|
+
selected: ariaSelected ?? accessibilityState?.selected,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const style = flattenStyle(props.style);
|
|
390
|
+
|
|
391
|
+
const useMultilineDefaultStyle =
|
|
392
|
+
props.multiline === true &&
|
|
393
|
+
(style == null ||
|
|
394
|
+
(style.padding == null &&
|
|
395
|
+
style.paddingVertical == null &&
|
|
396
|
+
style.paddingTop == null));
|
|
397
|
+
|
|
398
|
+
const textInput = (
|
|
399
|
+
<PasteTextInputNativeComponent
|
|
400
|
+
ref={ref}
|
|
401
|
+
{...otherProps}
|
|
402
|
+
{...eventHandlers}
|
|
403
|
+
accessibilityState={_accessibilityState}
|
|
404
|
+
accessible={accessible}
|
|
405
|
+
submitBehavior={submitBehavior}
|
|
406
|
+
caretHidden={caretHidden}
|
|
407
|
+
dataDetectorTypes={props.dataDetectorTypes}
|
|
408
|
+
focusable={tabIndex !== undefined ? !tabIndex : focusable}
|
|
409
|
+
mostRecentEventCount={mostRecentEventCount}
|
|
410
|
+
nativeID={id ?? props.nativeID}
|
|
411
|
+
onBlur={_onBlur}
|
|
412
|
+
onChange={_onChange}
|
|
413
|
+
onContentSizeChange={props.onContentSizeChange}
|
|
414
|
+
onFocus={_onFocus}
|
|
415
|
+
onPaste={_onPaste}
|
|
416
|
+
onScroll={_onScroll}
|
|
417
|
+
onSelectionChange={_onSelectionChange}
|
|
418
|
+
onSelectionChangeShouldSetResponder={emptyFunctionThatReturnsTrue}
|
|
419
|
+
selection={selection}
|
|
420
|
+
selectionColor={selectionColor}
|
|
421
|
+
style={StyleSheet.compose(
|
|
422
|
+
useMultilineDefaultStyle ? styles.multilineDefault : null,
|
|
423
|
+
style
|
|
424
|
+
)}
|
|
425
|
+
text={text}
|
|
426
|
+
children={children}
|
|
427
|
+
/>
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
return (
|
|
431
|
+
<TextAncestor.Provider value={true}>{textInput}</TextAncestor.Provider>
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const enterKeyHintToReturnTypeMap: Record<string, ReturnKeyTypeOptions> = {
|
|
436
|
+
enter: 'default',
|
|
437
|
+
done: 'done',
|
|
438
|
+
go: 'go',
|
|
439
|
+
next: 'next',
|
|
440
|
+
previous: 'previous',
|
|
441
|
+
search: 'search',
|
|
442
|
+
send: 'send',
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
const inputModeToKeyboardTypeMap: Record<string, KeyboardTypeOptions> = {
|
|
446
|
+
none: 'default',
|
|
447
|
+
text: 'default',
|
|
448
|
+
decimal: 'decimal-pad',
|
|
449
|
+
numeric: 'number-pad',
|
|
450
|
+
tel: 'phone-pad',
|
|
451
|
+
search: Platform.OS === 'ios' ? 'web-search' : 'default',
|
|
452
|
+
email: 'email-address',
|
|
453
|
+
url: 'url',
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
// Map HTML autocomplete values to Android autoComplete values
|
|
457
|
+
const autoCompleteWebToAutoCompleteAndroidMap: Record<string, string> = {
|
|
458
|
+
'address-line1': 'postal-address-region',
|
|
459
|
+
'address-line2': 'postal-address-locality',
|
|
460
|
+
'bday': 'birthdate-full',
|
|
461
|
+
'bday-day': 'birthdate-day',
|
|
462
|
+
'bday-month': 'birthdate-month',
|
|
463
|
+
'bday-year': 'birthdate-year',
|
|
464
|
+
'cc-csc': 'cc-csc',
|
|
465
|
+
'cc-exp': 'cc-exp',
|
|
466
|
+
'cc-exp-month': 'cc-exp-month',
|
|
467
|
+
'cc-exp-year': 'cc-exp-year',
|
|
468
|
+
'cc-number': 'cc-number',
|
|
469
|
+
'country': 'postal-address-country',
|
|
470
|
+
'current-password': 'password',
|
|
471
|
+
'email': 'email',
|
|
472
|
+
'honorific-prefix': 'name-prefix',
|
|
473
|
+
'honorific-suffix': 'name-suffix',
|
|
474
|
+
'name': 'name',
|
|
475
|
+
'additional-name': 'name-middle',
|
|
476
|
+
'family-name': 'name-family',
|
|
477
|
+
'given-name': 'name-given',
|
|
478
|
+
'new-password': 'password-new',
|
|
479
|
+
'off': 'off',
|
|
480
|
+
'one-time-code': 'sms-otp',
|
|
481
|
+
'postal-code': 'postal-code',
|
|
482
|
+
'sex': 'gender',
|
|
483
|
+
'street-address': 'street-address',
|
|
484
|
+
'tel': 'tel',
|
|
485
|
+
'tel-country-code': 'tel-country-code',
|
|
486
|
+
'tel-national': 'tel-national',
|
|
487
|
+
'username': 'username',
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// Map HTML autocomplete values to iOS textContentType values
|
|
491
|
+
const autoCompleteWebToTextContentTypeMap = {
|
|
492
|
+
'address-line1': 'streetAddressLine1',
|
|
493
|
+
'address-line2': 'streetAddressLine2',
|
|
494
|
+
'bday': 'birthdate',
|
|
495
|
+
'bday-day': 'birthdateDay',
|
|
496
|
+
'bday-month': 'birthdateMonth',
|
|
497
|
+
'bday-year': 'birthdateYear',
|
|
498
|
+
'cc-csc': 'creditCardSecurityCode',
|
|
499
|
+
'cc-exp-month': 'creditCardExpirationMonth',
|
|
500
|
+
'cc-exp-year': 'creditCardExpirationYear',
|
|
501
|
+
'cc-exp': 'creditCardExpiration',
|
|
502
|
+
'cc-given-name': 'creditCardGivenName',
|
|
503
|
+
'cc-additional-name': 'creditCardMiddleName',
|
|
504
|
+
'cc-family-name': 'creditCardFamilyName',
|
|
505
|
+
'cc-name': 'creditCardName',
|
|
506
|
+
'cc-number': 'creditCardNumber',
|
|
507
|
+
'cc-type': 'creditCardType',
|
|
508
|
+
'current-password': 'password',
|
|
509
|
+
'country': 'countryName',
|
|
510
|
+
'email': 'emailAddress',
|
|
511
|
+
'name': 'name',
|
|
512
|
+
'additional-name': 'middleName',
|
|
513
|
+
'family-name': 'familyName',
|
|
514
|
+
'given-name': 'givenName',
|
|
515
|
+
'nickname': 'nickname',
|
|
516
|
+
'honorific-prefix': 'namePrefix',
|
|
517
|
+
'honorific-suffix': 'nameSuffix',
|
|
518
|
+
'new-password': 'newPassword',
|
|
519
|
+
'off': 'none',
|
|
520
|
+
'one-time-code': 'oneTimeCode',
|
|
521
|
+
'organization': 'organizationName',
|
|
522
|
+
'organization-title': 'jobTitle',
|
|
523
|
+
'postal-code': 'postalCode',
|
|
524
|
+
'street-address': 'fullStreetAddress',
|
|
525
|
+
'tel': 'telephoneNumber',
|
|
526
|
+
'url': 'URL',
|
|
527
|
+
'username': 'username',
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
const verticalAlignToTextAlignVerticalMap: Record<string, string> = {
|
|
531
|
+
auto: 'auto',
|
|
532
|
+
top: 'top',
|
|
533
|
+
bottom: 'bottom',
|
|
534
|
+
middle: 'center',
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
const ExportedForwardRef = React.forwardRef(function PasteTextInput(
|
|
538
|
+
{
|
|
539
|
+
allowFontScaling = true,
|
|
540
|
+
rejectResponderTermination = true,
|
|
541
|
+
underlineColorAndroid = 'transparent',
|
|
542
|
+
autoComplete,
|
|
543
|
+
textContentType,
|
|
544
|
+
readOnly,
|
|
545
|
+
editable,
|
|
546
|
+
enterKeyHint,
|
|
547
|
+
returnKeyType,
|
|
548
|
+
inputMode,
|
|
549
|
+
showSoftInputOnFocus,
|
|
550
|
+
keyboardType,
|
|
551
|
+
...restProps
|
|
552
|
+
}: PasteInputProps,
|
|
553
|
+
forwardedRef: React.ForwardedRef<PasteTextInputInstance>
|
|
554
|
+
) {
|
|
555
|
+
let style = flattenStyle(restProps.style);
|
|
556
|
+
|
|
557
|
+
if (style?.verticalAlign != null) {
|
|
558
|
+
style.textAlignVertical =
|
|
559
|
+
verticalAlignToTextAlignVerticalMap[style.verticalAlign];
|
|
560
|
+
delete style.verticalAlign;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return (
|
|
564
|
+
<InternalTextInput
|
|
565
|
+
allowFontScaling={allowFontScaling}
|
|
566
|
+
rejectResponderTermination={rejectResponderTermination}
|
|
567
|
+
underlineColorAndroid={underlineColorAndroid}
|
|
568
|
+
editable={readOnly !== undefined ? !readOnly : editable}
|
|
569
|
+
returnKeyType={
|
|
570
|
+
enterKeyHint
|
|
571
|
+
? enterKeyHintToReturnTypeMap[enterKeyHint]
|
|
572
|
+
: returnKeyType
|
|
573
|
+
}
|
|
574
|
+
keyboardType={
|
|
575
|
+
inputMode ? inputModeToKeyboardTypeMap[inputMode] : keyboardType
|
|
576
|
+
}
|
|
577
|
+
showSoftInputOnFocus={
|
|
578
|
+
inputMode == null ? showSoftInputOnFocus : inputMode !== 'none'
|
|
579
|
+
}
|
|
580
|
+
autoComplete={
|
|
581
|
+
Platform.OS === 'android'
|
|
582
|
+
? // @ts-ignore
|
|
583
|
+
(autoCompleteWebToAutoCompleteAndroidMap[autoComplete] ??
|
|
584
|
+
autoComplete)
|
|
585
|
+
: undefined
|
|
586
|
+
}
|
|
587
|
+
textContentType={
|
|
588
|
+
textContentType != null
|
|
589
|
+
? textContentType
|
|
590
|
+
: Platform.OS === 'ios' &&
|
|
591
|
+
autoComplete &&
|
|
592
|
+
autoComplete in autoCompleteWebToTextContentTypeMap
|
|
593
|
+
? // @ts-ignore
|
|
594
|
+
autoCompleteWebToTextContentTypeMap[autoComplete]
|
|
595
|
+
: textContentType
|
|
596
|
+
}
|
|
597
|
+
{...restProps}
|
|
598
|
+
forwardedRef={forwardedRef}
|
|
599
|
+
style={style}
|
|
600
|
+
/>
|
|
601
|
+
);
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
ExportedForwardRef.displayName = 'PasteTextInput';
|
|
605
|
+
|
|
606
|
+
const styles = StyleSheet.create({
|
|
607
|
+
multilineDefault: {
|
|
608
|
+
// This default top inset makes RCTMultilineTextInputView seem as close as possible
|
|
609
|
+
// to single-line RCTSinglelineTextInputView defaults, using the system defaults
|
|
610
|
+
// of font size 17 and a height of 31 points.
|
|
611
|
+
paddingTop: 5,
|
|
612
|
+
},
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
export default ExportedForwardRef;
|