@@ -55,6 +55,11 @@ type ReducerActions =
5555 index : number
5656 value : string
5757 }
58+ | {
59+ type : 'focus'
60+ index : number
61+ position : 'begin' | 'end'
62+ }
5863 | {
5964 type : 'clearEdit'
6065 }
@@ -63,6 +68,7 @@ type InputState = {
6368 value : string [ ]
6469 editingValue : string [ ] | null
6570 selectIndex : number | null
71+ selectIndexPosition : 'begin' | 'end' | null
6672}
6773
6874export function BreadCrumbTextInput ( {
@@ -89,9 +95,11 @@ export function BreadCrumbTextInput({
8995 newState . editingValue ??= newState . value ?? [ ]
9096 if ( action . index === undefined ) {
9197 newState . selectIndex = newState . editingValue . push ( '' ) - 1
98+ newState . selectIndexPosition = 'end'
9299 } else {
93100 newState . editingValue . splice ( action . index , 0 , '' )
94101 newState . selectIndex = action . index
102+ newState . selectIndexPosition = 'end'
95103 }
96104 break
97105 }
@@ -100,8 +108,10 @@ export function BreadCrumbTextInput({
100108 newState . editingValue . splice ( action . index , 1 )
101109 if ( action . selectPrevious ) {
102110 newState . selectIndex = Math . max ( 0 , action . index - 1 )
111+ newState . selectIndexPosition = 'end'
103112 } else {
104113 newState . selectIndex = null
114+ newState . selectIndexPosition = 'end'
105115 }
106116 break
107117 }
@@ -112,6 +122,11 @@ export function BreadCrumbTextInput({
112122 }
113123 case 'clearEdit' : {
114124 newState . editingValue = null
125+ break
126+ }
127+ case 'focus' : {
128+ newState . selectIndex = action . index
129+ newState . selectIndexPosition = action . position
115130 }
116131 }
117132
@@ -120,14 +135,15 @@ export function BreadCrumbTextInput({
120135 {
121136 editingValue : null ,
122137 selectIndex : null ,
138+ selectIndexPosition : null ,
123139 value,
124140 }
125141 )
126142
127143 useEffect ( ( ) => {
128144 dispatch ( {
129145 type : 'setValue' ,
130- value
146+ value,
131147 } )
132148 } , [ dispatch , value ] )
133149
@@ -185,6 +201,8 @@ export function BreadCrumbTextInput({
185201 index : index + 1 ,
186202 } )
187203 event . stopPropagation ( )
204+
205+ delete event . currentTarget . dataset [ 'backspace' ]
188206 } else if ( event . key === 'Backspace' ) {
189207 if ( ! event . currentTarget . value ) {
190208 if ( ! event . currentTarget . dataset [ 'backspace' ] ) {
@@ -202,6 +220,22 @@ export function BreadCrumbTextInput({
202220 }
203221 }
204222 }
223+ } else if ( event . key === 'ArrowLeft' && event . currentTarget . selectionStart === 0 ) {
224+ dispatch ( {
225+ type : 'focus' ,
226+ index : index - 1 ,
227+ position : 'end'
228+ } )
229+ event . preventDefault ( )
230+ delete event . currentTarget . dataset [ 'backspace' ]
231+ } else if ( event . key === 'ArrowRight' && event . currentTarget . selectionEnd === event . currentTarget . value . length ) {
232+ dispatch ( {
233+ type : 'focus' ,
234+ index : index + 1 ,
235+ position : 'begin' ,
236+ } )
237+ event . preventDefault ( )
238+ delete event . currentTarget . dataset [ 'backspace' ]
205239 } else {
206240 delete event . currentTarget . dataset [ 'backspace' ]
207241 }
@@ -250,7 +284,16 @@ export function BreadCrumbTextInput({
250284 if ( ! inputToFocus || ! ( inputToFocus instanceof HTMLInputElement ) ) return
251285
252286 inputToFocus . focus ( )
253- } , [ inputState . selectIndex ] )
287+
288+ if ( inputState . selectIndexPosition === null ) return
289+ if ( inputState . selectIndexPosition === 'end' ) {
290+ inputToFocus . selectionStart = inputToFocus . value . length
291+ inputToFocus . selectionEnd = inputToFocus . selectionStart
292+ } else if ( inputState . selectIndexPosition === 'begin' ) {
293+ inputToFocus . selectionStart = 0
294+ inputToFocus . selectionEnd = 0
295+ }
296+ } , [ inputState . selectIndex , inputState . selectIndexPosition ] )
254297
255298 return (
256299 < div className = "input-breadcrumbtext" ref = { inputRef } tabIndex = { 0 } onBlur = { handleBlur } >
0 commit comments