@@ -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,34 +155,66 @@ 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
162
162
const [ visualSelected , setVisualSelected ] = React . useState <
163
163
SegmentedRawOption | undefined
164
164
> ( selected ) ;
165
165
166
- const [ thumbShow , setThumbShow ] = React . useState ( false ) ;
166
+ const latestVisualSelected = React . useRef ( visualSelected ) ;
167
167
168
- const calcThumbMoveStatus = (
169
- event : React . ChangeEvent < HTMLInputElement > ,
170
- ) => {
171
- const toElement = event . target . closest ( `.${ prefixCls } -item` ) ;
168
+ React . useEffect ( ( ) => {
169
+ latestVisualSelected . current = visualSelected ;
170
+ } ) ;
171
+
172
+ const [ thumbShow , setThumbShow ] = React . useState ( false ) ;
172
173
173
- const fromElement = containerRef . current ?. querySelector (
174
- `.${ prefixCls } -item-selected` ,
175
- ) ;
174
+ const doThumbAnimation = React . useCallback (
175
+ ( selectedValue : SegmentedRawOption ) => {
176
+ const segmentedItemIndex = segmentedOptions . findIndex (
177
+ ( n ) => n . value === selectedValue ,
178
+ ) ;
176
179
177
- if ( fromElement && toElement && thumbMoveStatus . current ) {
178
- thumbMoveStatus . current . from = calcThumbStyle (
179
- fromElement as HTMLElement ,
180
+ // find target element
181
+ const toElement = containerRef . current ?. querySelector (
182
+ `. ${ prefixCls } -item:nth-child( ${ segmentedItemIndex + 1 } )` ,
180
183
) ;
181
- thumbMoveStatus . current . to = calcThumbStyle ( toElement as HTMLElement ) ;
182
184
183
- setThumbShow ( true ) ;
185
+ if ( toElement ) {
186
+ // find source element
187
+ const fromElement = containerRef . current ?. querySelector (
188
+ `.${ prefixCls } -item-selected` ,
189
+ ) ;
190
+
191
+ if ( fromElement && toElement && thumbMoveStatus . current ) {
192
+ // calculate for thumb moving animation
193
+ thumbMoveStatus . current . from = calcThumbStyle (
194
+ fromElement as HTMLElement ,
195
+ ) ;
196
+ thumbMoveStatus . current . to = calcThumbStyle (
197
+ toElement as HTMLElement ,
198
+ ) ;
199
+
200
+ // trigger css-motion starts
201
+ setThumbShow ( true ) ;
202
+ }
203
+ }
204
+ } ,
205
+ [ prefixCls , segmentedOptions ] ,
206
+ ) ;
207
+
208
+ React . useEffect ( ( ) => {
209
+ // Syncing `visualSelected` when `selected` changed
210
+ // and do thumb animation
211
+ if (
212
+ ( typeof selected === 'string' || typeof selected === 'number' ) &&
213
+ selected !== latestVisualSelected . current
214
+ ) {
215
+ doThumbAnimation ( selected ) ;
184
216
}
185
- } ;
217
+ } , [ selected ] ) ;
186
218
187
219
const handleChange = (
188
220
event : React . ChangeEvent < HTMLInputElement > ,
@@ -192,8 +224,6 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
192
224
return ;
193
225
}
194
226
195
- calcThumbMoveStatus ( event ) ;
196
-
197
227
setSelected ( val ) ;
198
228
199
229
if ( onChange ) {
@@ -275,10 +305,14 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
275
305
< InternalSegmentedOption
276
306
key = { segmentedOption . value }
277
307
prefixCls = { prefixCls }
278
- className = { classNames ( segmentedOption . className , {
279
- [ `${ prefixCls } -item-selected` ] :
280
- segmentedOption . value === visualSelected ,
281
- } ) }
308
+ className = { classNames (
309
+ segmentedOption . className ,
310
+ `${ prefixCls } -item` ,
311
+ {
312
+ [ `${ prefixCls } -item-selected` ] :
313
+ segmentedOption . value === visualSelected ,
314
+ } ,
315
+ ) }
282
316
checked = { segmentedOption . value === selected }
283
317
onChange = { handleChange }
284
318
{ ...segmentedOption }
0 commit comments