11/* eslint-disable no-nested-ternary */
22import { shouldDisplayColors } from '../../../../public/node/output.js'
3- import React , { useEffect , useState } from 'react'
3+ import React , { useState } from 'react'
44import { Text , useInput } from 'ink'
55import chalk from 'chalk'
66import figures from 'figures'
@@ -29,18 +29,11 @@ const TextInput: FunctionComponent<TextInputProps> = ({
2929} : TextInputProps ) => {
3030 const [ cursorOffset , setCursorOffset ] = useState ( ( originalValue || '' ) . length )
3131
32- // if the updated value is shorter than the last one we need to reset the cursor
33- useEffect ( ( ) => {
34- setCursorOffset ( ( previousOffset ) => {
35- const newValue = originalValue || ''
36-
37- if ( previousOffset > newValue . length - 1 ) {
38- return newValue . length
39- }
40-
41- return previousOffset
42- } )
43- } , [ originalValue ] )
32+ // Clamp cursor synchronously so useInput never sees a stale offset
33+ const clampedCursorOffset = Math . min ( cursorOffset , ( originalValue || '' ) . length )
34+ if ( clampedCursorOffset !== cursorOffset ) {
35+ setCursorOffset ( clampedCursorOffset )
36+ }
4437
4538 const value = password ? '*' . repeat ( originalValue . length ) : originalValue
4639 let renderedValue
@@ -60,15 +53,15 @@ const TextInput: FunctionComponent<TextInputProps> = ({
6053 renderedValue = value
6154 . split ( '' )
6255 . map ( ( char , index ) => {
63- if ( index === cursorOffset ) {
56+ if ( index === clampedCursorOffset ) {
6457 return noColor ? cursorChar : chalk . inverse ( char )
6558 } else {
6659 return char
6760 }
6861 } )
6962 . join ( '' )
7063
71- if ( cursorOffset === value . length ) {
64+ if ( clampedCursorOffset === value . length ) {
7265 renderedValue = (
7366 < Text >
7467 { renderedValue }
@@ -89,25 +82,29 @@ const TextInput: FunctionComponent<TextInputProps> = ({
8982 }
9083 }
9184
92- let nextCursorOffset = cursorOffset
85+ let nextCursorOffset = clampedCursorOffset
9386 let nextValue = originalValue
9487
9588 if ( key . leftArrow ) {
96- if ( cursorOffset > 0 ) {
89+ if ( clampedCursorOffset > 0 ) {
9790 nextCursorOffset --
9891 }
9992 } else if ( key . rightArrow ) {
100- if ( cursorOffset < originalValue . length ) {
93+ if ( clampedCursorOffset < originalValue . length ) {
10194 nextCursorOffset ++
10295 }
10396 } else if ( key . backspace || key . delete ) {
104- if ( cursorOffset > 0 ) {
105- nextValue = originalValue . slice ( 0 , cursorOffset - 1 ) + originalValue . slice ( cursorOffset , originalValue . length )
97+ if ( clampedCursorOffset > 0 ) {
98+ nextValue =
99+ originalValue . slice ( 0 , clampedCursorOffset - 1 ) +
100+ originalValue . slice ( clampedCursorOffset , originalValue . length )
106101 nextCursorOffset --
107102 }
108103 } else {
109104 nextValue =
110- originalValue . slice ( 0 , cursorOffset ) + input + originalValue . slice ( cursorOffset , originalValue . length )
105+ originalValue . slice ( 0 , clampedCursorOffset ) +
106+ input +
107+ originalValue . slice ( clampedCursorOffset , originalValue . length )
111108 nextCursorOffset += input . length
112109 }
113110
0 commit comments