@@ -18,9 +18,15 @@ type Option = RawOption | LabeledOption;
1818
1919type Options = Option [ ] ;
2020
21+ type ExtendedHTMLInputElement = Omit < HTMLInputElement , 'value' > & {
22+ value : RawOption ;
23+ } ;
24+
2125export interface SegmentedProps extends React . HTMLProps < HTMLDivElement > {
2226 options : Options ;
2327 defaultValue ?: RawOption ;
28+ value ?: RawOption ;
29+ onChange ?: ( e : React . ChangeEvent < ExtendedHTMLInputElement > ) => void ;
2430 disabled ?: boolean ;
2531 prefixCls ?: string ;
2632 direction ?: 'ltr' | 'rtl' ;
@@ -61,7 +67,7 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
6167 direction,
6268 options,
6369 disabled,
64- onClick ,
70+ onChange ,
6571 prefixCls : customizePrefixCls ,
6672 className = '' ,
6773 ...restProps
@@ -97,30 +103,8 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
97103 className ,
98104 ) ;
99105
100- const handleItemClick = React . useCallback (
101- (
102- segmentedOption : LabeledOption ,
103- event : React . MouseEvent < HTMLDivElement > ,
104- ) => {
105- if ( disabled || segmentedOption . disabled ) {
106- return ;
107- }
108-
109- if ( segmentedOption . value !== selected ) {
110- calcThumbMoveStyle ( event ) ;
111- }
112-
113- setSelected ( segmentedOption . value ) ;
114-
115- onClick ?.( event ) ;
116- } ,
117- [ selected ] ,
118- ) ;
119-
120- const calcThumbMoveStyle = ( event : React . MouseEvent < HTMLDivElement > ) => {
121- const toElement = ( event . target as HTMLElement ) . closest (
122- `.${ prefixCls } -item` ,
123- ) ;
106+ const calcThumbMoveStyle = ( event : React . ChangeEvent < HTMLInputElement > ) => {
107+ const toElement = event . target . closest ( `.${ prefixCls } -item` ) ;
124108
125109 const fromElement = containerRef . current ?. querySelector (
126110 `.${ prefixCls } -item-selected` ,
@@ -136,6 +120,37 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
136120 }
137121 } ;
138122
123+ const handleChange = React . useCallback (
124+ (
125+ event : React . ChangeEvent < HTMLInputElement > ,
126+ segmentedOption : LabeledOption ,
127+ ) => {
128+ if ( disabled || segmentedOption . disabled ) {
129+ return ;
130+ }
131+
132+ if ( segmentedOption . value !== selected ) {
133+ calcThumbMoveStyle ( event ) ;
134+ }
135+
136+ setSelected ( segmentedOption . value ) ;
137+ if ( onChange ) {
138+ const mutationTarget = Object . create ( event . target , {
139+ value : {
140+ value : segmentedOption . value ,
141+ } ,
142+ } ) ;
143+ const mutatedEvent = Object . create ( event , {
144+ target : {
145+ value : mutationTarget ,
146+ } ,
147+ } ) ;
148+ onChange ( mutatedEvent ) ;
149+ }
150+ } ,
151+ [ selected , disabled ] ,
152+ ) ;
153+
139154 // --- motion event handlers for thumb move
140155 const handleThumbEnterStart = ( ) => {
141156 const fromStyle = thumbMoveStyles . current . from ;
@@ -179,26 +194,31 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
179194 { ( { className : motionClassName , style : motionStyle } ) => {
180195 return (
181196 < div
182- className = { classNames ( `${ prefixCls } -thumb` , motionClassName ) }
183197 style = { motionStyle }
198+ className = { classNames ( `${ prefixCls } -thumb` , motionClassName ) }
184199 />
185200 ) ;
186201 } }
187202 </ CSSMotion >
188203 { segmentedOptions . map ( ( segmentedOption ) => (
189- < div
204+ < label
190205 key = { segmentedOption . value }
191206 className = { classNames ( `${ prefixCls } -item` , {
192207 [ `${ prefixCls } -item-selected` ] :
193208 segmentedOption . value === visualSelected ,
194209 [ `${ prefixCls } -item-disabled` ] : ! ! segmentedOption . disabled ,
195210 } ) }
196- onClick = { ( e ) => handleItemClick ( segmentedOption , e ) }
197211 >
212+ < input
213+ className = { `${ prefixCls } -item-input` }
214+ type = "radio"
215+ checked = { segmentedOption . value === selected }
216+ onChange = { ( e ) => handleChange ( e , segmentedOption ) }
217+ />
198218 < span className = { `${ prefixCls } -item-label` } >
199219 { segmentedOption . label }
200220 </ span >
201- </ div >
221+ </ label >
202222 ) ) }
203223 </ div >
204224 ) ;
0 commit comments