diff --git a/apps/native-component-list/src/screens/UI/TextFieldScreen.android.tsx b/apps/native-component-list/src/screens/UI/TextFieldScreen.android.tsx index 6e37d46e3ea0ee..1233e9858d94f9 100644 --- a/apps/native-component-list/src/screens/UI/TextFieldScreen.android.tsx +++ b/apps/native-component-list/src/screens/UI/TextFieldScreen.android.tsx @@ -33,6 +33,11 @@ export default function TextFieldScreen() { selection: { start: 0, end: 0 }, }); + const imperativeText = useNativeState('Select me!'); + const imperativeSelection = useNativeState<{ start: number; end: number }>({ start: 0, end: 0 }); + const imperativeRef = React.useRef(null); + const [imperativeSelDisplay, setImperativeSelDisplay] = React.useState({ start: 0, end: 0 }); + const [outlined, setOutlined] = React.useState(false); const [enabled, setEnabled] = React.useState(true); const [readOnly, setReadOnly] = React.useState(false); @@ -179,6 +184,38 @@ export default function TextFieldScreen() { + {/* Imperative Selection */} + + + Imperative Selection + + + Type something... + + + + {`Selection: ${imperativeSelDisplay.start}–${imperativeSelDisplay.end}`} + + + + + + + + {/* Props */} diff --git a/apps/native-component-list/src/screens/UI/TextFieldScreen.ios.tsx b/apps/native-component-list/src/screens/UI/TextFieldScreen.ios.tsx index 685f5756a0f00b..bf5e313e4252cd 100644 --- a/apps/native-component-list/src/screens/UI/TextFieldScreen.ios.tsx +++ b/apps/native-component-list/src/screens/UI/TextFieldScreen.ios.tsx @@ -3,6 +3,7 @@ import { Host, TextField, TextFieldRef, + TextFieldSelection, SecureField, Form, Section, @@ -29,16 +30,23 @@ import { runOnJS } from 'react-native-worklets'; export default function TextFieldScreen() { const textRef = React.useRef(null); - const phoneRef = React.useRef(null); - const [selection, setSelection] = React.useState<{ start: number; end: number } | null>(null); - - const setPhoneCursor = React.useCallback((position: number) => { - phoneRef.current?.setSelection(position, position); - }, []); const username = useNativeState('johndoe'); const imperativeText = useNativeState('Select me!'); + const imperativeSelection = useNativeState({ start: 0, end: 0 }); + const [imperativeSelDisplay, setImperativeSelDisplay] = React.useState({ + start: 0, + end: 0, + }); const maskedPhone = useNativeState(''); + const phoneSelection = useNativeState({ start: 0, end: 0 }); + + const setPhoneCursor = React.useCallback( + (position: number) => { + phoneSelection.value = { start: position, end: position }; + }, + [phoneSelection] + ); const submitLabelOptions = [ 'continue', @@ -101,8 +109,8 @@ export default function TextFieldScreen() { {/* Worklet-based phone masking — updates synchronously on the UI thread */}
{ @@ -175,12 +183,13 @@ export default function TextFieldScreen() { - Selection: {selection ? `${selection.start}–${selection.end}` : 'none'} + {`Selection: ${imperativeSelDisplay.start}–${imperativeSelDisplay.end}`}