@@ -559,30 +559,76 @@ export function useSegmentNavigation({
559559 segmentsRef . current = newSegments
560560 setSegmentVersion ( ( v ) => v + 1 )
561561
562- const updatedSeg = newSegments [ targetIdx ]
563- if ( updatedSeg ) {
564- const newSelStart = Math . max (
565- updatedSeg . start ,
566- Math . min ( updatedSeg . end , updatedSeg . start + selectionStartOffset )
567- )
568- const newSelEnd = Math . max (
569- updatedSeg . start ,
570- Math . min ( updatedSeg . end , updatedSeg . start + selectionEndOffset )
571- )
572- const finalSelStart = Math . min ( newSelStart , newSelEnd )
573- const finalSelEnd = Math . max ( newSelStart , newSelEnd )
574- inputEl . setSelectionRange ( finalSelStart , finalSelEnd )
575- activeIdxRef . current = targetIdx
562+ let newActiveSegmentIdx = - 1
563+
564+ // 1. Try to find the semantically equivalent segment (same type, same dateKey)
565+ const originalSegType = seg . type
566+ const originalSegDateKey = seg . dateKey
567+ const equivalentNewSegmentIdx = newSegments . findIndex (
568+ ( s ) =>
569+ s . type === originalSegType && s . dateKey === originalSegDateKey
570+ )
571+
572+ if ( equivalentNewSegmentIdx !== - 1 ) {
573+ newActiveSegmentIdx = equivalentNewSegmentIdx
576574 } else {
577- if ( targetIdx < newSegments . length ) {
578- selectSegment ( targetIdx )
575+ // 2. Fallback: Try to find a segment at the original index if it's still valid and navigable
576+ // This helps if the type changed but the position is still somewhat relevant.
577+ if (
578+ targetIdx < newSegments . length &&
579+ newSegments [ targetIdx ] ?. type !== 'literal'
580+ ) {
581+ newActiveSegmentIdx = targetIdx
579582 } else {
580- const firstNavIdx = newSegments . findIndex (
583+ // 3. Fallback: Select the first navigable segment in the new list
584+ const firstNavigableNewIdx = newSegments . findIndex (
581585 ( s ) => s . type !== 'literal'
582586 )
583- if ( firstNavIdx !== - 1 ) selectSegment ( firstNavIdx )
584- else inputEl . setSelectionRange ( 0 , 0 )
587+ if ( firstNavigableNewIdx !== - 1 ) {
588+ newActiveSegmentIdx = firstNavigableNewIdx
589+ }
590+ }
591+ }
592+
593+ if ( newActiveSegmentIdx !== - 1 ) {
594+ const segmentToSelect = newSegments [ newActiveSegmentIdx ]
595+
596+ // If the segment type and dateKey are the same as the original adjusted segment,
597+ // try to restore the partial selection. Otherwise, select the whole segment.
598+ if (
599+ segmentToSelect . type === originalSegType &&
600+ segmentToSelect . dateKey === originalSegDateKey
601+ ) {
602+ const newSelStart = Math . max (
603+ segmentToSelect . start ,
604+ Math . min (
605+ segmentToSelect . end ,
606+ segmentToSelect . start + selectionStartOffset
607+ )
608+ )
609+ const newSelEnd = Math . max (
610+ segmentToSelect . start ,
611+ Math . min (
612+ segmentToSelect . end ,
613+ segmentToSelect . start + selectionEndOffset
614+ )
615+ )
616+ // Ensure start is not after end, especially if original selection was a caret (start === end)
617+ const finalSelStart = Math . min ( newSelStart , newSelEnd )
618+ const finalSelEnd = Math . max ( newSelStart , newSelEnd )
619+ inputEl . setSelectionRange ( finalSelStart , finalSelEnd )
620+ } else {
621+ // Segment type/dateKey changed, or it's a fallback to a different segment, so select fully.
622+ inputEl . setSelectionRange (
623+ segmentToSelect . start ,
624+ segmentToSelect . end
625+ )
585626 }
627+ activeIdxRef . current = newActiveSegmentIdx
628+ } else {
629+ // 4. Ultimate Fallback: No navigable segment found, clear selection or go to start
630+ inputEl . setSelectionRange ( 0 , 0 )
631+ activeIdxRef . current = - 1
586632 }
587633 } else {
588634 segmentsRef . current = newSegments
0 commit comments