@@ -10,32 +10,82 @@ const {
1010 choose
1111} = actions ;
1212const fetchMachine = createMachine ( {
13- id : "rating" ,
14- initial : "idle" ,
15- context : {
16- "isValueEmpty" : false ,
17- "isRadioFocused" : false
13+ props ( {
14+ props
15+ } ) {
16+ return {
17+ name : "rating" ,
18+ count : 5 ,
19+ dir : "ltr" ,
20+ value : - 1 ,
21+ ...compact ( props ) ,
22+ translations : {
23+ ratingValueText : index => `${ index } stars` ,
24+ ...props . translations
25+ }
26+ } ;
27+ } ,
28+ initialState ( ) {
29+ return "idle" ;
30+ } ,
31+ context ( {
32+ prop,
33+ bindable
34+ } ) {
35+ return {
36+ value : bindable ( ( ) => ( {
37+ defaultValue : prop ( "defaultValue" ) ,
38+ value : prop ( "value" ) ,
39+ onChange ( value ) {
40+ prop ( "onValueChange" ) ?. ( {
41+ value
42+ } ) ;
43+ }
44+ } ) ) ,
45+ hoveredValue : bindable ( ( ) => ( {
46+ defaultValue : - 1 ,
47+ onChange ( value ) {
48+ prop ( "onHoverChange" ) ?. ( {
49+ hoveredValue : value
50+ } ) ;
51+ }
52+ } ) ) ,
53+ fieldsetDisabled : bindable ( ( ) => ( {
54+ defaultValue : false
55+ } ) )
56+ } ;
1857 } ,
19- activities : [ "trackFormControlState" ] ,
58+ watch ( {
59+ track,
60+ action,
61+ prop
62+ } ) {
63+ track ( [ ( ) => prop ( "allowHalf" ) ] , ( ) => {
64+ action ( [ "roundValueIfNeeded" ] ) ;
65+ } ) ;
66+ } ,
67+ effects : [ "trackFormControlState" ] ,
2068 on : {
2169 SET_VALUE : {
2270 actions : [ "setValue" ]
2371 } ,
2472 CLEAR_VALUE : {
2573 actions : [ "clearValue" ]
26- }
27- } ,
28- on : {
74+ } ,
2975 UPDATE_CONTEXT : {
3076 actions : "updateContext"
3177 }
3278 } ,
3379 states : {
3480 idle : {
35- entry : "clearHoveredValue" ,
81+ entry : [ "clearHoveredValue" ] ,
3682 on : {
37- GROUP_POINTER_OVER : "hover" ,
38- FOCUS : "focus" ,
83+ GROUP_POINTER_OVER : {
84+ target : "hover"
85+ } ,
86+ FOCUS : {
87+ target : "focus"
88+ } ,
3989 CLICK : {
4090 actions : [ "setValue" , "focusActiveRadio" ]
4191 }
@@ -44,12 +94,14 @@ const fetchMachine = createMachine({
4494 focus : {
4595 on : {
4696 POINTER_OVER : {
47- actions : "setHoveredValue"
97+ actions : [ "setHoveredValue" ]
4898 } ,
4999 GROUP_POINTER_LEAVE : {
50- actions : "clearHoveredValue"
100+ actions : [ "clearHoveredValue" ]
101+ } ,
102+ BLUR : {
103+ target : "idle"
51104 } ,
52- BLUR : "idle" ,
53105 SPACE : {
54106 cond : "isValueEmpty" ,
55107 actions : [ "setValue" ]
@@ -74,21 +126,123 @@ const fetchMachine = createMachine({
74126 hover : {
75127 on : {
76128 POINTER_OVER : {
77- actions : "setHoveredValue"
129+ actions : [ "setHoveredValue" ]
78130 } ,
79131 GROUP_POINTER_LEAVE : [ {
80132 cond : "isRadioFocused" ,
81133 target : "focus" ,
82- actions : "clearHoveredValue"
134+ actions : [ "clearHoveredValue" ]
83135 } , {
84136 target : "idle" ,
85- actions : "clearHoveredValue"
137+ actions : [ "clearHoveredValue" ]
86138 } ] ,
87139 CLICK : {
88140 actions : [ "setValue" , "focusActiveRadio" ]
89141 }
90142 }
91143 }
144+ } ,
145+ implementations : {
146+ guards : {
147+ isInteractive : ( {
148+ prop
149+ } ) => ! ( prop ( "disabled" ) || prop ( "readOnly" ) ) ,
150+ isHoveredValueEmpty : ( {
151+ context : {
152+ "isValueEmpty" : false ,
153+ "isRadioFocused" : false
154+ }
155+ } ) => context . get ( "hoveredValue" ) === - 1 ,
156+ isValueEmpty : ( {
157+ context
158+ } ) => context . get ( "value" ) <= 0 ,
159+ isRadioFocused : ( {
160+ scope
161+ } ) => ! ! dom . getControlEl ( scope ) ?. contains ( scope . getActiveElement ( ) )
162+ } ,
163+ effects : {
164+ trackFormControlState ( {
165+ context,
166+ scope
167+ } ) {
168+ return trackFormControl ( dom . getHiddenInputEl ( scope ) , {
169+ onFieldsetDisabledChange ( disabled ) {
170+ context . set ( "fieldsetDisabled" , disabled ) ;
171+ } ,
172+ onFormReset ( ) {
173+ context . set ( "value" , context . initial ( "value" ) ) ;
174+ }
175+ } ) ;
176+ }
177+ } ,
178+ actions : {
179+ clearHoveredValue ( {
180+ context
181+ } ) {
182+ context . set ( "hoveredValue" , - 1 ) ;
183+ } ,
184+ focusActiveRadio ( {
185+ scope,
186+ context
187+ } ) {
188+ raf ( ( ) => dom . getRadioEl ( scope , context . get ( "value" ) ) ?. focus ( ) ) ;
189+ } ,
190+ setPrevValue ( {
191+ context,
192+ prop
193+ } ) {
194+ const factor = prop ( "allowHalf" ) ? 0.5 : 1 ;
195+ context . set ( "value" , Math . max ( 0 , context . get ( "value" ) - factor ) ) ;
196+ } ,
197+ setNextValue ( {
198+ context,
199+ prop
200+ } ) {
201+ const factor = prop ( "allowHalf" ) ? 0.5 : 1 ;
202+ const value = context . get ( "value" ) === - 1 ? 0 : context . get ( "value" ) ;
203+ context . set ( "value" , Math . min ( prop ( "count" ) , value + factor ) ) ;
204+ } ,
205+ setValueToMin ( {
206+ context
207+ } ) {
208+ context . set ( "value" , 1 ) ;
209+ } ,
210+ setValueToMax ( {
211+ context,
212+ prop
213+ } ) {
214+ context . set ( "value" , prop ( "count" ) ) ;
215+ } ,
216+ setValue ( {
217+ context,
218+ event
219+ } ) {
220+ const hoveredValue = context . get ( "hoveredValue" ) ;
221+ const value = hoveredValue === - 1 ? event . value : hoveredValue ;
222+ context . set ( "value" , value ) ;
223+ } ,
224+ clearValue ( {
225+ context
226+ } ) {
227+ context . set ( "value" , - 1 ) ;
228+ } ,
229+ setHoveredValue ( {
230+ context,
231+ prop,
232+ event
233+ } ) {
234+ const half = prop ( "allowHalf" ) && event . isMidway ;
235+ const factor = half ? 0.5 : 0 ;
236+ context . set ( "hoveredValue" , event . index - factor ) ;
237+ } ,
238+ roundValueIfNeeded ( {
239+ context,
240+ prop
241+ } ) {
242+ if ( prop ( "allowHalf" ) ) return ;
243+ context . set ( "value" , Math . round ( context . get ( "value" ) ) ) ;
244+ }
245+ }
92246 }
93247} , {
94248 actions : {
0 commit comments