@@ -18,12 +18,14 @@ import type {BaseTextInputProps, BaseTextInputRef} from '@components/TextInput/B
18
18
import * as styleConst from '@components/TextInput/styleConst' ;
19
19
import TextInputClearButton from '@components/TextInput/TextInputClearButton' ;
20
20
import TextInputLabel from '@components/TextInput/TextInputLabel' ;
21
+ import TextInputMeasurement from '@components/TextInput/TextInputMeasurement' ;
21
22
import useHtmlPaste from '@hooks/useHtmlPaste' ;
22
23
import useLocalize from '@hooks/useLocalize' ;
23
24
import useMarkdownStyle from '@hooks/useMarkdownStyle' ;
24
25
import useStyleUtils from '@hooks/useStyleUtils' ;
25
26
import useTheme from '@hooks/useTheme' ;
26
27
import useThemeStyles from '@hooks/useThemeStyles' ;
28
+ import getPlatform from '@libs/getPlatform' ;
27
29
import isInputAutoFilled from '@libs/isInputAutoFilled' ;
28
30
import variables from '@styles/variables' ;
29
31
import CONST from '@src/CONST' ;
@@ -78,6 +80,10 @@ function BaseTextInput(
78
80
} : BaseTextInputProps ,
79
81
ref : ForwardedRef < BaseTextInputRef > ,
80
82
) {
83
+ // For iOS, we don't need to measure the text input because it already has auto grow behavior
84
+ // See TextInputMeasurement.ios.tsx for more details
85
+ const isExternalAutoGrowMeasurement = getPlatform ( ) !== CONST . PLATFORM . IOS && autoGrow ;
86
+
81
87
const InputComponent = InputComponentMap . get ( type ) ?? RNTextInput ;
82
88
const isMarkdownEnabled = type === 'markdown' ;
83
89
const isAutoGrowHeightMarkdown = isMarkdownEnabled && autoGrowHeight ;
@@ -247,7 +253,7 @@ function BaseTextInput(
247
253
styles . textInputContainer ,
248
254
textInputContainerStyles ,
249
255
! ! contentWidth && StyleUtils . getWidthStyle ( textInputWidth ) ,
250
- autoGrow && StyleUtils . getAutoGrowWidthInputContainerStyles ( textInputWidth , autoGrowExtraSpace ) ,
256
+ isExternalAutoGrowMeasurement && StyleUtils . getAutoGrowWidthInputContainerStyles ( textInputWidth , autoGrowExtraSpace ) ,
251
257
! hideFocusedState && isFocused && styles . borderColorFocus ,
252
258
( ! ! hasError || ! ! errorText ) && styles . borderColorDanger ,
253
259
autoGrowHeight && { scrollPaddingTop : typeof maxAutoGrowHeight === 'number' ? 2 * maxAutoGrowHeight : undefined } ,
@@ -259,6 +265,10 @@ function BaseTextInput(
259
265
260
266
// Height fix is needed only for Text single line inputs
261
267
const shouldApplyHeight = ! isMultiline && ! isMarkdownEnabled ;
268
+
269
+ // Fix iOS cursor jumping when entering first character using HW keyboard https://github.com/Expensify/App/pull/59078#issuecomment-2802834037
270
+ const selection = inputProps . selection ?. end === 0 && inputProps . selection ?. start === 0 ? undefined : inputProps . selection ;
271
+
262
272
return (
263
273
< >
264
274
< View style = { [ containerStyles ] } >
@@ -345,8 +355,8 @@ function BaseTextInput(
345
355
placeholderTextColor = { placeholderTextColor ?? theme . placeholderText }
346
356
underlineColorAndroid = "transparent"
347
357
style = { [
348
- styles . flex1 ,
349
- styles . w100 ,
358
+ ! autoGrow && styles . flex1 ,
359
+ ! autoGrow && styles . w100 ,
350
360
inputStyle ,
351
361
( ! hasLabel || isMultiline ) && styles . pv0 ,
352
362
inputPaddingLeft ,
@@ -377,7 +387,7 @@ function BaseTextInput(
377
387
keyboardType = { inputProps . keyboardType }
378
388
inputMode = { ! disableKeyboard ? inputProps . inputMode : CONST . INPUT_MODE . NONE }
379
389
value = { uncontrolled ? undefined : value }
380
- selection = { inputProps . selection }
390
+ selection = { selection }
381
391
readOnly = { isReadOnly }
382
392
defaultValue = { defaultValue }
383
393
markdownStyle = { markdownStyle }
@@ -441,55 +451,21 @@ function BaseTextInput(
441
451
/>
442
452
) }
443
453
</ View >
444
- { ! ! contentWidth && isPrefixCharacterPaddingCalculated && (
445
- < View
446
- style = { [ inputStyle as ViewStyle , styles . hiddenElementOutsideOfWindow , styles . visibilityHidden , styles . wAuto , inputPaddingLeft ] }
447
- onLayout = { ( e ) => {
448
- if ( e . nativeEvent . layout . width === 0 && e . nativeEvent . layout . height === 0 ) {
449
- return ;
450
- }
451
- setTextInputWidth ( e . nativeEvent . layout . width ) ;
452
- setTextInputHeight ( e . nativeEvent . layout . height ) ;
453
- } }
454
- >
455
- < Text
456
- style = { [
457
- inputStyle ,
458
- autoGrowHeight && styles . autoGrowHeightHiddenInput ( width ?? 0 , typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : undefined ) ,
459
- { width : contentWidth } ,
460
- ] }
461
- >
462
- { /* \u200B added to solve the issue of not expanding the text input enough when the value ends with '\n' (https://github.com/Expensify/App/issues/21271) */ }
463
- { value ? `${ value } ${ value . endsWith ( '\n' ) ? '\u200B' : '' } ` : placeholder }
464
- </ Text >
465
- </ View >
466
- ) }
467
- { /*
468
- Text input component doesn't support auto grow by default.
469
- This text view is used to calculate width or height of the input value given textStyle in this component.
470
- This Text component is intentionally positioned out of the screen.
471
- */ }
472
- { ( ! ! autoGrow || autoGrowHeight ) && ! isAutoGrowHeightMarkdown && (
473
- < Text
474
- style = { [
475
- inputStyle ,
476
- autoGrowHeight && styles . autoGrowHeightHiddenInput ( width ?? 0 , typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : undefined ) ,
477
- styles . hiddenElementOutsideOfWindow ,
478
- styles . visibilityHidden ,
479
- ] }
480
- onLayout = { ( e ) => {
481
- if ( e . nativeEvent . layout . width === 0 && e . nativeEvent . layout . height === 0 ) {
482
- return ;
483
- }
484
- // Add +2 to width so that cursor is not cut off / covered at the end of text content
485
- setTextInputWidth ( e . nativeEvent . layout . width + 2 ) ;
486
- setTextInputHeight ( e . nativeEvent . layout . height ) ;
487
- } }
488
- >
489
- { /* \u200B added to solve the issue of not expanding the text input enough when the value ends with '\n' (https://github.com/Expensify/App/issues/21271) */ }
490
- { value ? `${ value } ${ value . endsWith ( '\n' ) ? '\u200B' : '' } ` : placeholder }
491
- </ Text >
492
- ) }
454
+ < TextInputMeasurement
455
+ value = { value }
456
+ placeholder = { placeholder }
457
+ contentWidth = { contentWidth }
458
+ autoGrowHeight = { autoGrowHeight }
459
+ maxAutoGrowHeight = { maxAutoGrowHeight }
460
+ width = { width }
461
+ inputStyle = { inputStyle }
462
+ inputPaddingLeft = { inputPaddingLeft }
463
+ autoGrow = { autoGrow }
464
+ isAutoGrowHeightMarkdown = { isAutoGrowHeightMarkdown }
465
+ onSetTextInputWidth = { setTextInputWidth }
466
+ onSetTextInputHeight = { setTextInputHeight }
467
+ isPrefixCharacterPaddingCalculated = { isPrefixCharacterPaddingCalculated }
468
+ />
493
469
</ >
494
470
) ;
495
471
}
0 commit comments