@@ -50,7 +50,7 @@ export default function RangeSlider(props: RangeSliderProps) {
5050
5151 // Track slider dimension (width for horizontal, height for vertical) for conditional input rendering
5252 const [ sliderWidth , setSliderWidth ] = useState < number | null > ( null ) ;
53- const [ showInputs , setShowInputs ] = useState < boolean > ( true ) ;
53+ const [ showInputs , setShowInputs ] = useState < boolean > ( value . length === 2 ) ;
5454 const sliderRef = useRef < HTMLDivElement > ( null ) ;
5555
5656 // Handle initial mount - equivalent to componentWillMount
@@ -72,6 +72,19 @@ export default function RangeSlider(props: RangeSliderProps) {
7272 return ;
7373 }
7474
75+ if ( step === null ) {
76+ // If the user has explicitly disabled stepping (step=None), then
77+ // the slider values are constrained to the given marks and user
78+ // cannot enter arbitrary values via the input element
79+ setShowInputs ( false ) ;
80+ return ;
81+ }
82+
83+ if ( value . length !== 2 ) {
84+ setShowInputs ( false ) ;
85+ return ;
86+ }
87+
7588 const measureWidth = ( ) => {
7689 if ( sliderRef . current ) {
7790 const rect = sliderRef . current . getBoundingClientRect ( ) ;
@@ -106,7 +119,7 @@ export default function RangeSlider(props: RangeSliderProps) {
106119 return ( ) => {
107120 resizeObserver . disconnect ( ) ;
108121 } ;
109- } , [ showInputs , vertical ] ) ;
122+ } , [ showInputs , vertical , step , value ] ) ;
110123
111124 // Handle prop value changes - equivalent to componentWillReceiveProps
112125 useEffect ( ( ) => {
@@ -209,32 +222,49 @@ export default function RangeSlider(props: RangeSliderProps) {
209222 < input
210223 type = "number"
211224 className = "dash-input-container dash-range-slider-input dash-range-slider-min-input"
212- value = { value [ 0 ] || '' }
225+ value = { value [ 0 ] ?? '' }
213226 onChange = { e => {
214- const newMin = parseFloat ( e . target . value ) ;
215- if ( ! isNaN ( newMin ) ) {
216- const newValue = [ newMin , value [ 1 ] ] ;
217- setValue ( newValue ) ;
218- if ( updatemode === 'drag' ) {
219- setProps ( {
220- value : newValue ,
221- drag_value : newValue ,
222- } ) ;
223- } else {
224- setProps ( { drag_value : newValue } ) ;
227+ const inputValue = e . target . value ;
228+ // Allow empty string (user is clearing the field)
229+ if ( inputValue === '' ) {
230+ // Don't update props while user is typing, just update local state
231+ setValue ( [ null as any , value [ 1 ] ] ) ;
232+ } else {
233+ const newMin = parseFloat ( inputValue ) ;
234+ if ( ! isNaN ( newMin ) ) {
235+ const newValue = [ newMin , value [ 1 ] ] ;
236+ setValue ( newValue ) ;
237+ if ( updatemode === 'drag' ) {
238+ setProps ( {
239+ value : newValue ,
240+ drag_value : newValue ,
241+ } ) ;
242+ } else {
243+ setProps ( { drag_value : newValue } ) ;
244+ }
225245 }
226246 }
227247 } }
228248 onBlur = { e => {
229- let newMin =
230- parseFloat ( e . target . value ) ||
231- minMaxValues . min_mark ;
232- newMin = isNaN ( newMin )
233- ? minMaxValues . min_mark
234- : newMin ;
249+ const inputValue = e . target . value ;
250+ let newMin : number ;
251+
252+ // If empty, default to current value or min_mark
253+ if ( inputValue === '' ) {
254+ newMin = value [ 0 ] ?? minMaxValues . min_mark ;
255+ } else {
256+ newMin = parseFloat ( inputValue ) ;
257+ newMin = isNaN ( newMin )
258+ ? minMaxValues . min_mark
259+ : newMin ;
260+ }
261+
235262 const constrainedMin = Math . max (
236263 minMaxValues . min_mark ,
237- Math . min ( value [ 1 ] , newMin )
264+ Math . min (
265+ value [ 1 ] ?? minMaxValues . max_mark ,
266+ newMin
267+ )
238268 ) ;
239269 const newValue = [ constrainedMin , value [ 1 ] ] ;
240270 setValue ( newValue ) ;
@@ -244,6 +274,7 @@ export default function RangeSlider(props: RangeSliderProps) {
244274 } }
245275 min = { minMaxValues . min_mark }
246276 max = { value [ 1 ] }
277+ step = { step || undefined }
247278 disabled = { disabled }
248279 />
249280 ) }
@@ -347,32 +378,49 @@ export default function RangeSlider(props: RangeSliderProps) {
347378 < input
348379 type = "number"
349380 className = "dash-input-container dash-range-slider-input"
350- value = { value [ 1 ] || '' }
381+ value = { value [ 1 ] ?? '' }
351382 onChange = { e => {
352- const newMax = parseFloat ( e . target . value ) ;
353- if ( ! isNaN ( newMax ) ) {
354- const newValue = [ value [ 0 ] , newMax ] ;
355- setValue ( newValue ) ;
356- if ( updatemode === 'drag' ) {
357- setProps ( {
358- value : newValue ,
359- drag_value : newValue ,
360- } ) ;
361- } else {
362- setProps ( { drag_value : newValue } ) ;
383+ const inputValue = e . target . value ;
384+ // Allow empty string (user is clearing the field)
385+ if ( inputValue === '' ) {
386+ // Don't update props while user is typing, just update local state
387+ setValue ( [ value [ 0 ] , null as any ] ) ;
388+ } else {
389+ const newMax = parseFloat ( inputValue ) ;
390+ if ( ! isNaN ( newMax ) ) {
391+ const newValue = [ value [ 0 ] , newMax ] ;
392+ setValue ( newValue ) ;
393+ if ( updatemode === 'drag' ) {
394+ setProps ( {
395+ value : newValue ,
396+ drag_value : newValue ,
397+ } ) ;
398+ } else {
399+ setProps ( { drag_value : newValue } ) ;
400+ }
363401 }
364402 }
365403 } }
366404 onBlur = { e => {
367- let newMax =
368- parseFloat ( e . target . value ) ||
369- minMaxValues . max_mark ;
370- newMax = isNaN ( newMax )
371- ? minMaxValues . max_mark
372- : newMax ;
405+ const inputValue = e . target . value ;
406+ let newMax : number ;
407+
408+ // If empty, default to current value or max_mark
409+ if ( inputValue === '' ) {
410+ newMax = value [ 1 ] ?? minMaxValues . max_mark ;
411+ } else {
412+ newMax = parseFloat ( inputValue ) ;
413+ newMax = isNaN ( newMax )
414+ ? minMaxValues . max_mark
415+ : newMax ;
416+ }
417+
373418 const constrainedMax = Math . min (
374419 minMaxValues . max_mark ,
375- Math . max ( value [ 0 ] , newMax )
420+ Math . max (
421+ value [ 0 ] ?? minMaxValues . min_mark ,
422+ newMax
423+ )
376424 ) ;
377425 const newValue = [ value [ 0 ] , constrainedMax ] ;
378426 setValue ( newValue ) ;
@@ -382,6 +430,7 @@ export default function RangeSlider(props: RangeSliderProps) {
382430 } }
383431 min = { value [ 0 ] }
384432 max = { minMaxValues . max_mark }
433+ step = { step || undefined }
385434 disabled = { disabled }
386435 />
387436 ) }
0 commit comments