-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Have slider work like color area #2819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f270683
dbb0d0f
45f8553
16c304d
433886f
6c0281a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,9 @@ import {getSliderThumbId, sliderIds} from './utils'; | |
import React, {ChangeEvent, HTMLAttributes, InputHTMLAttributes, LabelHTMLAttributes, RefObject, useCallback, useEffect, useRef} from 'react'; | ||
import {SliderState} from '@react-stately/slider'; | ||
import {useFocusable} from '@react-aria/focus'; | ||
import {useKeyboard, useMove} from '@react-aria/interactions'; | ||
import {useLabel} from '@react-aria/label'; | ||
import {useLocale} from '@react-aria/i18n'; | ||
import {useMove} from '@react-aria/interactions'; | ||
|
||
interface SliderThumbAria { | ||
/** Props for the root thumb element; handles the dragging motion. */ | ||
|
@@ -77,44 +77,76 @@ export function useSliderThumb( | |
stateRef.current = state; | ||
let reverseX = direction === 'rtl'; | ||
let currentPosition = useRef<number>(null); | ||
|
||
let {keyboardProps} = useKeyboard({ | ||
onKeyDown(e) { | ||
let { | ||
getThumbMaxValue, | ||
getThumbMinValue, | ||
pageSize | ||
} = stateRef.current; | ||
// these are the cases that useMove or useSlider don't handle | ||
if (!/^(PageUp|PageDown|Home|End)$/.test(e.key)) { | ||
e.continuePropagation(); | ||
return; | ||
} | ||
// same handling as useMove, stopPropagation to prevent useSlider from handling the event as well. | ||
e.preventDefault(); | ||
// remember to set this so that onChangeEnd is fired | ||
state.setThumbDragging(index, true); | ||
switch (e.key) { | ||
case 'PageUp': | ||
stateRef.current.incrementThumb(index, pageSize); | ||
break; | ||
case 'PageDown': | ||
stateRef.current.decrementThumb(index, pageSize); | ||
break; | ||
case 'Home': | ||
state.setThumbValue(index, getThumbMinValue(index)); | ||
break; | ||
case 'End': | ||
state.setThumbValue(index, getThumbMaxValue(index)); | ||
break; | ||
} | ||
state.setThumbDragging(index, false); | ||
} | ||
}); | ||
|
||
let {moveProps} = useMove({ | ||
onMoveStart({pointerType}) { | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
// Don't start dragging for keyboard events unless the value has changed. | ||
if (pointerType !== 'keyboard') { | ||
stateRef.current.setThumbDragging(index, true); | ||
} | ||
stateRef.current.setThumbDragging(index, true); | ||
}, | ||
onMove({deltaX, deltaY, pointerType}) { | ||
onMove({deltaX, deltaY, pointerType, shiftKey}) { | ||
const { | ||
getThumbPercent, | ||
getThumbMaxValue, | ||
getThumbMinValue, | ||
getThumbValue, | ||
setThumbDragging, | ||
setThumbPercent, | ||
setThumbValue, | ||
step | ||
getThumbPercent, | ||
setThumbPercent, | ||
step, | ||
pageSize | ||
} = stateRef.current; | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
|
||
if (currentPosition.current == null) { | ||
currentPosition.current = getThumbPercent(index) * size; | ||
} | ||
if (pointerType === 'keyboard') { | ||
const currentValue = getThumbValue(index); | ||
// (invert left/right according to language direction) + (according to vertical) | ||
const delta = ((reverseX ? -deltaX : deltaX) + (isVertical ? -deltaY : -deltaY)) * step; | ||
if (delta > 0 && currentValue === getThumbMaxValue(index)) { | ||
return; | ||
} | ||
if (delta < 0 && currentValue === getThumbMinValue(index)) { | ||
return; | ||
if (deltaX > 0) { | ||
if (reverseX) { | ||
stateRef.current.decrementThumb(index, shiftKey ? pageSize : step); | ||
} else { | ||
stateRef.current.incrementThumb(index, shiftKey ? pageSize : step); | ||
} | ||
} else if (deltaY < 0) { | ||
stateRef.current.incrementThumb(index, shiftKey ? pageSize : step); | ||
} else if (deltaX < 0) { | ||
if (reverseX) { | ||
stateRef.current.incrementThumb(index, shiftKey ? pageSize : step); | ||
} else { | ||
stateRef.current.decrementThumb(index, shiftKey ? pageSize : step); | ||
} | ||
} else if (deltaY > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to group the deltaX and deltaY portions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure I know what you're saying? I think this is pretty easy to follow, only X direction is influenced by locale direction |
||
stateRef.current.decrementThumb(index, shiftKey ? pageSize : step); | ||
} | ||
currentPosition.current += delta * size; | ||
setThumbDragging(index, true); | ||
setThumbValue(index, currentValue + delta); | ||
setThumbDragging(index, false); | ||
} else { | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
|
@@ -125,11 +157,8 @@ export function useSliderThumb( | |
setThumbPercent(index, clamp(currentPosition.current / size, 0, 1)); | ||
} | ||
}, | ||
onMoveEnd({pointerType}) { | ||
// Don't end dragging, triggering onChangeEnd, for keyboard events unless the value has changed. | ||
if (pointerType !== 'keyboard') { | ||
stateRef.current.setThumbDragging(index, false); | ||
} | ||
onMoveEnd() { | ||
stateRef.current.setThumbDragging(index, false); | ||
} | ||
}); | ||
|
||
|
@@ -167,8 +196,6 @@ export function useSliderThumb( | |
} | ||
}; | ||
|
||
let inputting = false; | ||
|
||
// We install mouse handlers for the drag motion on the thumb div, but | ||
// not the key handler for moving the thumb with the slider. Instead, | ||
// we focus the range input, and let the browser handle the keyboard | ||
|
@@ -187,22 +214,12 @@ export function useSliderThumb( | |
'aria-required': isRequired || undefined, | ||
'aria-invalid': validationState === 'invalid' || undefined, | ||
'aria-errormessage': opts['aria-errormessage'], | ||
onInput: () => { | ||
// Flag native keyboard input. | ||
inputting = true; | ||
}, | ||
onChange: (e: ChangeEvent<HTMLInputElement>) => { | ||
if (parseFloat(e.target.value) !== state.getThumbValue(index)) { | ||
// On native keyboard input, set thumb dragging so that onChangeEnd will be fired. | ||
inputting && state.setThumbDragging(index, true); | ||
state.setThumbValue(index, parseFloat(e.target.value)); | ||
// After native keyboard input, unset thumb dragging so that onChangeEnd will be fired. | ||
inputting && state.setThumbDragging(index, false); | ||
} | ||
inputting = false; | ||
stateRef.current.setThumbValue(index, parseFloat(e.target.value)); | ||
} | ||
}), | ||
thumbProps: !isDisabled ? mergeProps( | ||
keyboardProps, | ||
moveProps, | ||
{ | ||
onMouseDown: (e: React.MouseEvent<HTMLElement>) => { | ||
|
Uh oh!
There was an error while loading. Please reload this page.