@@ -3,22 +3,19 @@ import { normalizeProps, useMachine } from "@zag-js/react"
33import { useId , useState } from "react"
44
55export default function Page ( ) {
6- const [ value , setValue ] = useState ( "0" )
6+ const [ value , setValue ] = useState ( "" )
7+ const [ formatOptions , setFormatOptions ] = useState < Intl . NumberFormatOptions | undefined > ( undefined )
8+ const [ maxFractionDigits , setMaxFractionDigits ] = useState < number | undefined > ( undefined )
79
810 const service = useMachine ( numberInput . machine , {
911 id : useId ( ) ,
1012 value : value ,
11- max : 10 ,
13+ max : 1000 ,
1214 min : 0 ,
13- clampValueOnBlur : true ,
15+ formatOptions :
16+ maxFractionDigits !== undefined ? { ...formatOptions , maximumFractionDigits : maxFractionDigits } : formatOptions ,
1417 onValueChange ( details ) {
15- if ( details . valueAsNumber > 10 ) {
16- setValue ( "10" )
17- } else if ( details . valueAsNumber < 0 ) {
18- setValue ( "0" )
19- } else {
20- setValue ( details . value )
21- }
18+ setValue ( details . value )
2219 } ,
2320 } )
2421
@@ -27,10 +24,68 @@ export default function Page() {
2724 return (
2825 < >
2926 < main className = "number-input" >
27+ < h2 > Controlled Number Input Testing</ h2 >
28+
29+ { /* Test buttons for external value changes */ }
30+ < div style = { { marginBottom : "1rem" , display : "flex" , gap : "0.5rem" , flexWrap : "wrap" } } >
31+ < button data-testid = "set-decimal" onClick = { ( ) => setValue ( "123.456789012345" ) } >
32+ Set High Precision (123.456789012345)
33+ </ button >
34+ < button data-testid = "set-simple" onClick = { ( ) => setValue ( "50.25" ) } >
35+ Set Simple (50.25)
36+ </ button >
37+ < button data-testid = "set-zero" onClick = { ( ) => setValue ( "0" ) } >
38+ Set Zero
39+ </ button >
40+ < button data-testid = "clear-value" onClick = { ( ) => setValue ( "" ) } >
41+ Clear (Uncontrolled)
42+ </ button >
43+ </ div >
44+
45+ { /* Format option controls */ }
46+ < div style = { { marginBottom : "1rem" , display : "flex" , gap : "0.5rem" , flexWrap : "wrap" } } >
47+ < button
48+ data-testid = "no-format"
49+ onClick = { ( ) => {
50+ setFormatOptions ( undefined )
51+ setMaxFractionDigits ( undefined )
52+ } }
53+ >
54+ No Format Options
55+ </ button >
56+ < button
57+ data-testid = "currency-format"
58+ onClick = { ( ) => {
59+ setFormatOptions ( { style : "currency" , currency : "USD" } )
60+ setMaxFractionDigits ( undefined )
61+ } }
62+ >
63+ Currency Format
64+ </ button >
65+ < button
66+ data-testid = "precision-2"
67+ onClick = { ( ) => {
68+ setFormatOptions ( undefined )
69+ setMaxFractionDigits ( 2 )
70+ } }
71+ >
72+ Max 2 Decimals
73+ </ button >
74+ < button
75+ data-testid = "precision-4"
76+ onClick = { ( ) => {
77+ setFormatOptions ( undefined )
78+ setMaxFractionDigits ( 4 )
79+ } }
80+ >
81+ Max 4 Decimals
82+ </ button >
83+ </ div >
84+
3085 < div { ...api . getRootProps ( ) } >
3186 < div data-testid = "scrubber" { ...api . getScrubberProps ( ) } />
3287 < label data-testid = "label" { ...api . getLabelProps ( ) } >
33- Enter number (0-10, clamped during typing ):
88+ Controlled Number Input (0-1000 ):
3489 </ label >
3590 < div { ...api . getControlProps ( ) } >
3691 < button data-testid = "dec-button" { ...api . getDecrementTriggerProps ( ) } >
@@ -43,14 +98,45 @@ export default function Page() {
4398 </ div >
4499 </ div >
45100
46- < div style = { { marginTop : "1rem" } } >
47- < strong > Controlled value:</ strong > { value }
101+ { /* Status display */ }
102+ < div style = { { marginTop : "1rem" , padding : "1rem" , backgroundColor : "#f5f5f5" , borderRadius : "4px" } } >
103+ < div >
104+ < strong > Controlled Value:</ strong > "{ value } "
105+ </ div >
106+ < div >
107+ < strong > Is Controlled:</ strong > { value !== "" ? "Yes" : "No" }
108+ </ div >
109+ < div >
110+ < strong > Format Options:</ strong > { formatOptions ? JSON . stringify ( formatOptions ) : "None" }
111+ </ div >
112+ < div >
113+ < strong > Max Fraction Digits:</ strong > { maxFractionDigits ?? "None" }
114+ </ div >
115+ < div >
116+ < strong > Value As Number:</ strong > { api . valueAsNumber }
117+ </ div >
48118 </ div >
49119
50- < p style = { { marginTop : "1rem" , color : "#666" , fontSize : "0.875rem" } } >
51- Try typing a value greater than 10 (e.g., "100" or "1000"). The input will be clamped back to "10" immediately
52- during typing, not just on blur.
53- </ p >
120+ < div style = { { marginTop : "1rem" , padding : "1rem" , backgroundColor : "#e8f4fd" , borderRadius : "4px" } } >
121+ < h3 > Testing Instructions</ h3 >
122+ < ul style = { { fontSize : "0.875rem" , lineHeight : "1.4" } } >
123+ < li >
124+ < strong > Controlled Mode:</ strong > When you set a value using buttons above, input is controlled
125+ </ li >
126+ < li >
127+ < strong > Uncontrolled Mode:</ strong > When you clear the value, input becomes uncontrolled
128+ </ li >
129+ < li >
130+ < strong > Precision Test:</ strong > Set high precision value, then type to see how precision is preserved
131+ </ li >
132+ < li >
133+ < strong > Format Test:</ strong > Apply different formats to see controlled vs uncontrolled behavior
134+ </ li >
135+ < li >
136+ < strong > External Changes:</ strong > Use buttons to change value externally while typing
137+ </ li >
138+ </ ul >
139+ </ div >
54140 </ main >
55141 </ >
56142 )
0 commit comments