@@ -104,7 +104,7 @@ const InternalSegmentedOption: React.FC<{
104
104
105
105
return (
106
106
< label
107
- className = { classNames ( ` ${ prefixCls } -item` , className , {
107
+ className = { classNames ( className , {
108
108
[ `${ prefixCls } -item-disabled` ] : disabled ,
109
109
} ) }
110
110
>
@@ -155,7 +155,7 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
155
155
} , [ options ] ) ;
156
156
157
157
const [ selected , setSelected ] = useMergedState ( segmentedOptions [ 0 ] ?. value , {
158
- value,
158
+ value : props . value ,
159
159
defaultValue,
160
160
} ) ;
161
161
@@ -165,24 +165,60 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
165
165
166
166
const [ thumbShow , setThumbShow ] = React . useState ( false ) ;
167
167
168
- const calcThumbMoveStatus = (
169
- event : React . ChangeEvent < HTMLInputElement > ,
170
- ) => {
171
- const toElement = event . target . closest ( `.${ prefixCls } -item` ) ;
168
+ const doThumbAnimation = React . useCallback (
169
+ ( selectedValue : SegmentedRawOption ) => {
170
+ const segmentedItemIndex = segmentedOptions . findIndex (
171
+ ( n ) => n . value === selectedValue ,
172
+ ) ;
172
173
173
- const fromElement = containerRef . current ?. querySelector (
174
- `. ${ prefixCls } -item-selected` ,
175
- ) ;
174
+ if ( segmentedItemIndex < 0 ) {
175
+ return ;
176
+ }
176
177
177
- if ( fromElement && toElement && thumbMoveStatus . current ) {
178
- thumbMoveStatus . current . from = calcThumbStyle (
179
- fromElement as HTMLElement ,
178
+ // find target element
179
+ const toElement = containerRef . current ?. querySelector (
180
+ `. ${ prefixCls } -item:nth-child( ${ segmentedItemIndex + 1 } )` ,
180
181
) ;
181
- thumbMoveStatus . current . to = calcThumbStyle ( toElement as HTMLElement ) ;
182
182
183
- setThumbShow ( true ) ;
183
+ if ( toElement ) {
184
+ // find source element
185
+ const fromElement = containerRef . current ?. querySelector (
186
+ `.${ prefixCls } -item-selected` ,
187
+ ) ;
188
+
189
+ if ( fromElement && toElement && thumbMoveStatus . current ) {
190
+ // calculate for thumb moving animation
191
+ thumbMoveStatus . current . from = calcThumbStyle (
192
+ fromElement as HTMLElement ,
193
+ ) ;
194
+ thumbMoveStatus . current . to = calcThumbStyle (
195
+ toElement as HTMLElement ,
196
+ ) ;
197
+
198
+ // trigger css-motion starts
199
+ setThumbShow ( true ) ;
200
+ }
201
+ }
202
+ } ,
203
+ [ prefixCls , segmentedOptions ] ,
204
+ ) ;
205
+
206
+ // get latest version of `visualSelected`
207
+ const latestVisualSelected = React . useRef ( visualSelected ) ;
208
+ React . useEffect ( ( ) => {
209
+ latestVisualSelected . current = visualSelected ;
210
+ } ) ;
211
+
212
+ React . useEffect ( ( ) => {
213
+ // Syncing `visualSelected` when `selected` changed
214
+ // and do thumb animation
215
+ if (
216
+ ( typeof selected === 'string' || typeof selected === 'number' ) &&
217
+ selected !== latestVisualSelected . current
218
+ ) {
219
+ doThumbAnimation ( selected ) ;
184
220
}
185
- } ;
221
+ } , [ selected ] ) ;
186
222
187
223
const handleChange = (
188
224
event : React . ChangeEvent < HTMLInputElement > ,
@@ -192,8 +228,6 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
192
228
return ;
193
229
}
194
230
195
- calcThumbMoveStatus ( event ) ;
196
-
197
231
setSelected ( val ) ;
198
232
199
233
if ( onChange ) {
@@ -275,10 +309,14 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
275
309
< InternalSegmentedOption
276
310
key = { segmentedOption . value }
277
311
prefixCls = { prefixCls }
278
- className = { classNames ( segmentedOption . className , {
279
- [ `${ prefixCls } -item-selected` ] :
280
- segmentedOption . value === visualSelected ,
281
- } ) }
312
+ className = { classNames (
313
+ segmentedOption . className ,
314
+ `${ prefixCls } -item` ,
315
+ {
316
+ [ `${ prefixCls } -item-selected` ] :
317
+ segmentedOption . value === visualSelected ,
318
+ } ,
319
+ ) }
282
320
checked = { segmentedOption . value === selected }
283
321
onChange = { handleChange }
284
322
{ ...segmentedOption }
0 commit comments