88 Pressable ,
99 TextInput ,
1010 Image ,
11+ Platform ,
1112} from 'react-native' ;
1213import {
1314 TypeRichTextInput ,
@@ -32,7 +33,7 @@ export default function App() {
3233 end : 0 ,
3334 } ) ;
3435 const [ image , setImage ] = useState < onPasteImageEventData | null > ( null ) ;
35- const [ value , setValue ] = useState < string > ( '' ) ;
36+ const [ value , setValue ] = useState < string > ( 'hhh ' ) ;
3637
3738 const multilineValue = `hello
3839 div
@@ -43,16 +44,19 @@ export default function App() {
4344 // };
4445
4546 const handleFocus = ( ) => {
47+ console . log ( 'focus commands' ) ;
4648 inputRef . current ?. focus ( ) ;
4749 } ;
4850
4951 const handleBlur = ( ) => {
52+ console . log ( 'blur commands' ) ;
5053 inputRef . current ?. blur ( ) ;
5154 } ;
5255
53- const handleSetValue = ( value = 'default value' ) => {
54- textRef . current = value ;
55- inputRef . current ?. setText ( value ) ;
56+ const handleSetValue = ( text = 'default value' ) => {
57+ textRef . current = text ;
58+ inputRef . current ?. setText ( text ) ;
59+ inputRef . current ?. setSelection ( text . length , text . length ) ;
5660 } ;
5761
5862 const handleSetSelection = ( ) => {
@@ -94,14 +98,36 @@ export default function App() {
9498 }
9599
96100 const handleInsertTextAtCursor = ( ) => {
97- const textToInsert = 'Test' ;
98- inputRef . current ?. insertTextAt (
99- selectionRef . current . start ,
100- selectionRef . current . end ,
101- textToInsert
102- ) ;
101+ const insert = 'Test' ;
102+
103+ const { start, end } = selectionRef . current ;
104+ const currentText = textRef . current ?? '' ;
105+
106+ const nextText =
107+ currentText . slice ( 0 , start ) + insert + currentText . slice ( end ) ;
108+
109+ textRef . current = nextText ;
110+
111+ inputRef . current ?. insertTextAt ( start , end , insert ) ;
103112 } ;
104113
114+ function handleFastTypingProgrammatically ( ) {
115+ const randomWords = [ 'hii' , 'hello' , ' ' , 'my name is' , 'test' , 'div' ] ;
116+ let i = 0 ;
117+
118+ const interval = setInterval ( ( ) => {
119+ if ( i >= 100 ) {
120+ clearInterval ( interval ) ;
121+ return ;
122+ }
123+
124+ const index = Math . floor ( Math . random ( ) * randomWords . length ) ;
125+ handleSetValue ( textRef . current + randomWords [ index ] ) ;
126+
127+ i ++ ;
128+ } , 100 ) ; // 50ms
129+ }
130+
105131 return (
106132 < >
107133 < ScrollView
@@ -118,12 +144,13 @@ export default function App() {
118144 < View style = { styles . editor } >
119145 < TypeRichTextInput
120146 ref = { inputRef }
121- value = { value }
147+ // value={value}
148+ defaultValue = { textRef . current }
122149 style = { styles . editorInput }
123150 placeholder = "custom textinput"
124151 placeholderTextColor = "rgb(0, 26, 114)"
125- selectionColor = "deepskyblue "
126- cursorColor = "dodgerblue "
152+ selectionColor = "green "
153+ cursorColor = "red "
127154 autoCapitalize = "words"
128155 autoFocus
129156 onChangeText = { ( text : string ) => {
@@ -139,20 +166,20 @@ export default function App() {
139166 // ANDROID_EXPERIMENTAL_SYNCHRONOUS_EVENTS
140167 // }
141168 multiline
142- numberOfLines = { 4 }
169+ // numberOfLines={5} // prefer maxHeight on iOS
170+ scrollEnabled
143171 onPasteImageData = { ( e ) => {
144172 setImage ( e ) ;
145173 console . log ( e ) ;
146174 } }
147- defaultValue = { textRef . current }
148175 keyboardAppearance = "dark"
149176 editable = { true }
150177 lineHeight = { 22 }
151- fontFamily = " serif"
178+ fontFamily = { Platform . select ( { ios : 'georgia' , android : ' serif' } ) } // fontweight won't work unless this is used
152179 fontStyle = "italic"
153- fontWeight = { '700 ' }
154- fontSize = { 12 }
155- color = "darkgreen "
180+ fontWeight = { '200 ' }
181+ fontSize = { 24 }
182+ color = "indigo "
156183 />
157184 </ View >
158185 < TextInput
@@ -163,8 +190,8 @@ export default function App() {
163190 width : '100%' ,
164191 marginVertical : 20 ,
165192 } }
166- // multiline={false}
167- // numberOfLines={2 }
193+ // multiline
194+ // numberOfLines={4 }
168195 />
169196 < View style = { styles . btnContainer } >
170197 < View style = { styles . buttonStack } >
@@ -206,11 +233,13 @@ export default function App() {
206233 < Text style = { styles . label2 } > set controlled Value</ Text >
207234 </ Pressable >
208235 < Pressable
209- disabled
210- onPress = { ( ) => { } }
211- style = { [ styles . button , { backgroundColor : 'gray' } ] }
236+ onPress = { ( ) => {
237+ // works only with the programmatic setText use
238+ handleFastTypingProgrammatically ( ) ;
239+ } }
240+ style = { [ styles . button ] }
212241 >
213- < Text style = { styles . label2 } > Todo </ Text >
242+ < Text style = { styles . label2 } > very Fast Typing </ Text >
214243 </ Pressable >
215244 </ View >
216245 < View style = { styles . buttonStack } >
@@ -230,6 +259,21 @@ export default function App() {
230259
231260 // this MUST preserve cursor after native fix
232261 inputRef . current ?. setText ( next ) ;
262+ let { start : selStart , end : selEnd } = selectionRef . current ;
263+
264+ if ( selStart <= start ) {
265+ // before wrap → no change
266+ } else if ( selStart < end ) {
267+ // inside wrapped range → +1
268+ selStart += 1 ;
269+ selEnd += 1 ;
270+ } else {
271+ // at or after end → +2
272+ selStart += 2 ;
273+ selEnd += 2 ;
274+ }
275+
276+ inputRef . current ?. setSelection ( selStart , selEnd ) ;
233277 } }
234278 >
235279 < Text style = { styles . label2 } > Wrap middle with * *</ Text >
@@ -251,7 +295,23 @@ export default function App() {
251295 ) ;
252296}
253297
254- const ImageInfo = ( { image } : { image : any } ) => {
298+ const ImageInfo = ( { image } : { image : onPasteImageEventData } ) => {
299+ function formatFileSize ( bytes : number ) : string {
300+ if ( bytes <= 0 ) return '0 KB' ;
301+
302+ const KB = 1024 ;
303+ const MB = KB * KB ;
304+
305+ const sizeInMB = bytes / MB ;
306+
307+ if ( sizeInMB < 0.9 ) {
308+ const sizeInKB = bytes / KB ;
309+ return `${ sizeInKB . toFixed ( 1 ) } KB` ;
310+ }
311+
312+ return `${ sizeInMB . toFixed ( 2 ) } MB` ;
313+ }
314+
255315 return (
256316 < View >
257317 < Text style = { { color : 'red' , fontWeight : 'bold' } } >
@@ -275,7 +335,7 @@ const ImageInfo = ({ image }: { image: any }) => {
275335 fontWeight : 'regular' ,
276336 } }
277337 >
278- { image . fileSize }
338+ { image . fileSize } ( { formatFileSize ( image . fileSize ) } )
279339 </ Text >
280340 </ Text >
281341 < Text style = { { color : 'red' , fontWeight : 'bold' } } >
@@ -323,7 +383,7 @@ const ImageInfo = ({ image }: { image: any }) => {
323383 fontWeight : 'regular' ,
324384 } }
325385 >
326- { image . error ?. message ?? 'no error' }
386+ { image . error ?. message || 'no error' }
327387 </ Text >
328388 </ Text >
329389 </ View >
@@ -377,12 +437,12 @@ const styles = StyleSheet.create({
377437 editorInput : {
378438 marginTop : 24 ,
379439 width : '100%' ,
380- // maxHeight: 180 ,
440+ maxHeight : 280 ,
381441 backgroundColor : 'gainsboro' ,
382442 // fontSize: 34,
383443 fontFamily : 'Nunito-Regular' ,
384- paddingVertical : 12 ,
385- paddingHorizontal : 14 ,
444+ // paddingVertical: 12,
445+ // paddingHorizontal: 14,
386446 } ,
387447 scrollPlaceholder : {
388448 marginTop : 24 ,
0 commit comments