@react-aria/slider
Advanced tools
Comparing version 3.0.0-alpha.2 to 3.0.0-alpha.3
311
dist/main.js
@@ -6,2 +6,10 @@ var { | ||
var { | ||
useMove | ||
} = require("@react-aria/interactions"); | ||
var { | ||
useLocale | ||
} = require("@react-aria/i18n"); | ||
var { | ||
useLabel | ||
@@ -11,8 +19,2 @@ } = require("@react-aria/label"); | ||
var { | ||
mergeProps, | ||
useDrag1D, | ||
focusWithoutScrolling | ||
} = require("@react-aria/utils"); | ||
var { | ||
useRef, | ||
@@ -23,2 +25,9 @@ useCallback, | ||
var { | ||
clamp, | ||
mergeProps, | ||
useGlobalListeners, | ||
focusWithoutScrolling | ||
} = require("@react-aria/utils"); | ||
var _babelRuntimeHelpersExtends = $parcel$interopDefault(require("@babel/runtime/helpers/extends")); | ||
@@ -45,44 +54,120 @@ | ||
const { | ||
let { | ||
labelProps, | ||
fieldProps | ||
} = useLabel(props); | ||
const isSliderEditable = !(props.isDisabled || props.isReadOnly); // Attach id of the label to the state so it can be accessed by useSliderThumb. | ||
let isVertical = props.orientation === 'vertical'; // Attach id of the label to the state so it can be accessed by useSliderThumb. | ||
$dec1906781d9c7cb69245fc4d5344b$export$sliderIds.set(state, (_labelProps$id = labelProps.id) != null ? _labelProps$id : fieldProps.id); // When the user clicks or drags the track, we want the motion to set and drag the | ||
// closest thumb. Hence we also need to install useDrag1D() on the track element. | ||
$dec1906781d9c7cb69245fc4d5344b$export$sliderIds.set(state, (_labelProps$id = labelProps.id) != null ? _labelProps$id : fieldProps.id); | ||
let { | ||
direction | ||
} = useLocale(); | ||
let { | ||
addGlobalListener, | ||
removeGlobalListener | ||
} = useGlobalListeners(); // When the user clicks or drags the track, we want the motion to set and drag the | ||
// closest thumb. Hence we also need to install useMove() on the track element. | ||
// Here, we keep track of which index is the "closest" to the drag start point. | ||
// It is set onMouseDown; see trackProps below. | ||
// It is set onMouseDown/onTouchDown; see trackProps below. | ||
const realTimeTrackDraggingIndex = useRef(undefined); | ||
const isTrackDragging = useRef(false); | ||
const realTimeTrackDraggingIndex = useRef(null); | ||
const stateRef = useRef(null); | ||
stateRef.current = state; | ||
const reverseX = direction === 'rtl'; | ||
const currentPosition = useRef(null); | ||
const { | ||
onMouseDown, | ||
onMouseEnter, | ||
onMouseOut | ||
} = useDrag1D({ | ||
containerRef: trackRef, | ||
reverse: false, | ||
orientation: 'horizontal', | ||
onDrag: dragging => { | ||
if (realTimeTrackDraggingIndex.current !== undefined) { | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, dragging); | ||
moveProps | ||
} = useMove({ | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
}, | ||
onMove(_ref) { | ||
let { | ||
deltaX, | ||
deltaY | ||
} = _ref; | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
if (currentPosition.current == null) { | ||
currentPosition.current = stateRef.current.getThumbPercent(realTimeTrackDraggingIndex.current) * size; | ||
} | ||
isTrackDragging.current = dragging; | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
delta = -delta; | ||
} | ||
currentPosition.current += delta; | ||
if (realTimeTrackDraggingIndex.current != null && trackRef.current) { | ||
const percent = clamp(currentPosition.current / size, 0, 1); | ||
stateRef.current.setThumbPercent(realTimeTrackDraggingIndex.current, percent); | ||
} | ||
}, | ||
onPositionChange: position => { | ||
if (realTimeTrackDraggingIndex.current !== undefined && trackRef.current) { | ||
const percent = position / trackRef.current.offsetWidth; | ||
state.setThumbPercent(realTimeTrackDraggingIndex.current, percent); // When track-dragging ends, onDrag is called before a final onPositionChange is | ||
// called, so we can't reset realTimeTrackDraggingIndex until onPositionChange, | ||
// as we still needed to update the thumb position one last time. Hence we | ||
// track whether we're dragging, and the actual dragged index, separately. | ||
if (!isTrackDragging.current) { | ||
realTimeTrackDraggingIndex.current = undefined; | ||
} | ||
onMoveEnd() { | ||
if (realTimeTrackDraggingIndex.current != null) { | ||
stateRef.current.setThumbDragging(realTimeTrackDraggingIndex.current, false); | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
} | ||
}); | ||
let currentPointer = useRef(undefined); | ||
let onDownTrack = (e, id, clientX, clientY) => { | ||
// We only trigger track-dragging if the user clicks on the track itself and nothing is currently being dragged. | ||
if (trackRef.current && !props.isDisabled && state.values.every((_, i) => !state.isThumbDragging(i))) { | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; // Find the closest thumb | ||
const trackPosition = trackRef.current.getBoundingClientRect()[isVertical ? 'top' : 'left']; | ||
const clickPosition = isVertical ? clientY : clientX; | ||
const offset = clickPosition - trackPosition; | ||
let percent = offset / size; | ||
if (direction === 'rtl' || isVertical) { | ||
percent = 1 - percent; | ||
} | ||
let value = state.getPercentValue(percent); // Only compute the diff for thumbs that are editable, as only they can be dragged | ||
const minDiff = Math.min(...state.values.map((v, index) => state.isThumbEditable(index) ? Math.abs(v - value) : Number.POSITIVE_INFINITY)); | ||
const index = state.values.findIndex(v => Math.abs(v - value) === minDiff); | ||
if (minDiff !== Number.POSITIVE_INFINITY && index >= 0) { | ||
// Don't unfocus anything | ||
e.preventDefault(); | ||
realTimeTrackDraggingIndex.current = index; | ||
state.setFocusedThumb(index); | ||
currentPointer.current = id; | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, true); | ||
state.setThumbValue(index, value); | ||
addGlobalListener(window, 'mouseup', onUpTrack, false); | ||
addGlobalListener(window, 'touchend', onUpTrack, false); | ||
addGlobalListener(window, 'pointerup', onUpTrack, false); | ||
} else { | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
} | ||
}; | ||
let onUpTrack = e => { | ||
var _e$pointerId, _e$changedTouches; | ||
let id = (_e$pointerId = e.pointerId) != null ? _e$pointerId : (_e$changedTouches = e.changedTouches) == null ? void 0 : _e$changedTouches[0].identifier; | ||
if (id === currentPointer.current) { | ||
if (realTimeTrackDraggingIndex.current != null) { | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, false); | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
removeGlobalListener(window, 'mouseup', onUpTrack, false); | ||
removeGlobalListener(window, 'touchend', onUpTrack, false); | ||
removeGlobalListener(window, 'pointerup', onUpTrack, false); | ||
} | ||
}; | ||
return { | ||
@@ -97,38 +182,15 @@ labelProps, | ||
trackProps: mergeProps({ | ||
onMouseDown: e => { | ||
// We only trigger track-dragging if the user clicks on the track itself. | ||
if (trackRef.current && isSliderEditable) { | ||
// Find the closest thumb | ||
const trackPosition = trackRef.current.getBoundingClientRect().left; | ||
const clickPosition = e.clientX; | ||
const offset = clickPosition - trackPosition; | ||
const percent = offset / trackRef.current.offsetWidth; | ||
const value = state.getPercentValue(percent); // Only compute the diff for thumbs that are editable, as only they can be dragged | ||
onMouseDown(e) { | ||
onDownTrack(e, undefined, e.clientX, e.clientY); | ||
}, | ||
const minDiff = Math.min(...state.values.map((v, index) => state.isThumbEditable(index) ? Math.abs(v - value) : Number.POSITIVE_INFINITY)); | ||
const index = state.values.findIndex(v => Math.abs(v - value) === minDiff); | ||
onPointerDown(e) { | ||
onDownTrack(e, e.pointerId, e.clientX, e.clientY); | ||
}, | ||
if (minDiff !== Number.POSITIVE_INFINITY && index >= 0) { | ||
// Don't unfocus anything | ||
e.preventDefault(); | ||
realTimeTrackDraggingIndex.current = index; | ||
state.setFocusedThumb(index); // We immediately toggle state to dragging and set the value on mouse down. | ||
// We set the value now, instead of waiting for onDrag, so that the thumb | ||
// is updated while you're still holding the mouse button down. And we | ||
// set dragging on now, so that onChangeEnd() won't fire yet when we set | ||
// the value. Dragging state will be reset to false in onDrag above, even | ||
// if no dragging actually occurs. | ||
onTouchStart(e) { | ||
onDownTrack(e, e.changedTouches[0].identifier, e.changedTouches[0].clientX, e.changedTouches[0].clientY); | ||
} | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, true); | ||
state.setThumbValue(index, value); | ||
} else { | ||
realTimeTrackDraggingIndex.current = undefined; | ||
} | ||
} | ||
} | ||
}, { | ||
onMouseDown, | ||
onMouseEnter, | ||
onMouseOut | ||
}) | ||
}, moveProps) | ||
}; | ||
@@ -148,7 +210,6 @@ } | ||
const { | ||
let { | ||
index, | ||
isRequired, | ||
isDisabled, | ||
isReadOnly, | ||
validationState, | ||
@@ -158,2 +219,10 @@ trackRef, | ||
} = opts; | ||
let isVertical = opts.orientation === 'vertical'; | ||
let { | ||
direction | ||
} = useLocale(); | ||
let { | ||
addGlobalListener, | ||
removeGlobalListener | ||
} = useGlobalListeners(); | ||
let labelId = $dec1906781d9c7cb69245fc4d5344b$export$sliderIds.get(state); | ||
@@ -167,3 +236,2 @@ const { | ||
const value = state.values[index]; | ||
const isEditable = !(isDisabled || isReadOnly); | ||
const focusInput = useCallback(() => { | ||
@@ -180,17 +248,50 @@ if (inputRef.current) { | ||
}, [isFocused, focusInput]); | ||
const draggableProps = useDrag1D({ | ||
containerRef: trackRef, | ||
reverse: false, | ||
orientation: 'horizontal', | ||
onDrag: dragging => { | ||
state.setThumbDragging(index, dragging); | ||
focusInput(); | ||
const stateRef = useRef(null); | ||
stateRef.current = state; | ||
let reverseX = direction === 'rtl'; | ||
let currentPosition = useRef(null); | ||
let { | ||
moveProps | ||
} = useMove({ | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
state.setThumbDragging(index, true); | ||
}, | ||
onPositionChange: position => { | ||
const percent = position / trackRef.current.offsetWidth; | ||
state.setThumbPercent(index, percent); | ||
onMove(_ref) { | ||
let { | ||
deltaX, | ||
deltaY, | ||
pointerType | ||
} = _ref; | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
if (currentPosition.current == null) { | ||
currentPosition.current = stateRef.current.getThumbPercent(index) * size; | ||
} | ||
if (pointerType === 'keyboard') { | ||
// (invert left/right according to language direction) + (according to vertical) | ||
let delta = ((reverseX ? -deltaX : deltaX) + (isVertical ? -deltaY : -deltaY)) * stateRef.current.step; | ||
currentPosition.current += delta * size; | ||
stateRef.current.setThumbValue(index, stateRef.current.getThumbValue(index) + delta); | ||
} else { | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
delta = -delta; | ||
} | ||
currentPosition.current += delta; | ||
stateRef.current.setThumbPercent(index, clamp(currentPosition.current / size, 0, 1)); | ||
} | ||
}, | ||
onMoveEnd() { | ||
state.setThumbDragging(index, false); | ||
} | ||
}); // Immediately register editability with the state | ||
state.setThumbEditable(index, isEditable); | ||
state.setThumbEditable(index, !isDisabled); | ||
const { | ||
@@ -201,3 +302,27 @@ focusableProps | ||
onBlur: () => state.setFocusedThumb(undefined) | ||
}), inputRef); // We install mouse handlers for the drag motion on the thumb div, but | ||
}), inputRef); | ||
let currentPointer = useRef(undefined); | ||
let onDown = id => { | ||
focusInput(); | ||
currentPointer.current = id; | ||
state.setThumbDragging(index, true); | ||
addGlobalListener(window, 'mouseup', onUp, false); | ||
addGlobalListener(window, 'touchend', onUp, false); | ||
addGlobalListener(window, 'pointerup', onUp, false); | ||
}; | ||
let onUp = e => { | ||
var _e$pointerId, _e$changedTouches; | ||
let id = (_e$pointerId = e.pointerId) != null ? _e$pointerId : (_e$changedTouches = e.changedTouches) == null ? void 0 : _e$changedTouches[0].identifier; | ||
if (id === currentPointer.current) { | ||
focusInput(); | ||
state.setThumbDragging(index, false); | ||
removeGlobalListener(window, 'mouseup', onUp, false); | ||
removeGlobalListener(window, 'touchend', onUp, false); | ||
removeGlobalListener(window, 'pointerup', onUp, 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, | ||
@@ -207,6 +332,7 @@ // we focus the range input, and let the browser handle the keyboard | ||
return { | ||
inputProps: mergeProps(focusableProps, fieldProps, { | ||
type: 'range', | ||
tabIndex: isEditable ? 0 : undefined, | ||
tabIndex: !isDisabled ? 0 : undefined, | ||
min: state.getThumbMinValue(index), | ||
@@ -216,5 +342,4 @@ max: state.getThumbMaxValue(index), | ||
value: value, | ||
readOnly: isReadOnly, | ||
disabled: isDisabled, | ||
'aria-orientation': 'horizontal', | ||
'aria-orientation': opts.orientation, | ||
'aria-valuetext': state.getThumbValueLabel(index), | ||
@@ -228,8 +353,12 @@ 'aria-required': isRequired || undefined, | ||
}), | ||
thumbProps: isEditable ? mergeProps({ | ||
onMouseDown: draggableProps.onMouseDown, | ||
onMouseEnter: draggableProps.onMouseEnter, | ||
onMouseOut: draggableProps.onMouseOut | ||
}, { | ||
onMouseDown: focusInput | ||
thumbProps: !isDisabled ? mergeProps(moveProps, { | ||
onMouseDown: () => { | ||
onDown(null); | ||
}, | ||
onPointerDown: e => { | ||
onDown(e.pointerId); | ||
}, | ||
onTouchStart: e => { | ||
onDown(e.changedTouches[0].identifier); | ||
} | ||
}) : {}, | ||
@@ -236,0 +365,0 @@ labelProps |
import { useFocusable } from "@react-aria/focus"; | ||
import { useMove } from "@react-aria/interactions"; | ||
import { useLocale } from "@react-aria/i18n"; | ||
import { useLabel } from "@react-aria/label"; | ||
import { mergeProps, useDrag1D, focusWithoutScrolling } from "@react-aria/utils"; | ||
import { useRef, useCallback, useEffect } from "react"; | ||
import { clamp, mergeProps, useGlobalListeners, focusWithoutScrolling } from "@react-aria/utils"; | ||
import _babelRuntimeHelpersEsmExtends from "@babel/runtime/helpers/esm/extends"; | ||
@@ -21,44 +23,120 @@ const $d20491ae7743da17cfa841ff6d87$export$sliderIds = new WeakMap(); | ||
const { | ||
let { | ||
labelProps, | ||
fieldProps | ||
} = useLabel(props); | ||
const isSliderEditable = !(props.isDisabled || props.isReadOnly); // Attach id of the label to the state so it can be accessed by useSliderThumb. | ||
let isVertical = props.orientation === 'vertical'; // Attach id of the label to the state so it can be accessed by useSliderThumb. | ||
$d20491ae7743da17cfa841ff6d87$export$sliderIds.set(state, (_labelProps$id = labelProps.id) != null ? _labelProps$id : fieldProps.id); // When the user clicks or drags the track, we want the motion to set and drag the | ||
// closest thumb. Hence we also need to install useDrag1D() on the track element. | ||
$d20491ae7743da17cfa841ff6d87$export$sliderIds.set(state, (_labelProps$id = labelProps.id) != null ? _labelProps$id : fieldProps.id); | ||
let { | ||
direction | ||
} = useLocale(); | ||
let { | ||
addGlobalListener, | ||
removeGlobalListener | ||
} = useGlobalListeners(); // When the user clicks or drags the track, we want the motion to set and drag the | ||
// closest thumb. Hence we also need to install useMove() on the track element. | ||
// Here, we keep track of which index is the "closest" to the drag start point. | ||
// It is set onMouseDown; see trackProps below. | ||
// It is set onMouseDown/onTouchDown; see trackProps below. | ||
const realTimeTrackDraggingIndex = useRef(undefined); | ||
const isTrackDragging = useRef(false); | ||
const realTimeTrackDraggingIndex = useRef(null); | ||
const stateRef = useRef(null); | ||
stateRef.current = state; | ||
const reverseX = direction === 'rtl'; | ||
const currentPosition = useRef(null); | ||
const { | ||
onMouseDown, | ||
onMouseEnter, | ||
onMouseOut | ||
} = useDrag1D({ | ||
containerRef: trackRef, | ||
reverse: false, | ||
orientation: 'horizontal', | ||
onDrag: dragging => { | ||
if (realTimeTrackDraggingIndex.current !== undefined) { | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, dragging); | ||
moveProps | ||
} = useMove({ | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
}, | ||
onMove(_ref) { | ||
let { | ||
deltaX, | ||
deltaY | ||
} = _ref; | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
if (currentPosition.current == null) { | ||
currentPosition.current = stateRef.current.getThumbPercent(realTimeTrackDraggingIndex.current) * size; | ||
} | ||
isTrackDragging.current = dragging; | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
delta = -delta; | ||
} | ||
currentPosition.current += delta; | ||
if (realTimeTrackDraggingIndex.current != null && trackRef.current) { | ||
const percent = clamp(currentPosition.current / size, 0, 1); | ||
stateRef.current.setThumbPercent(realTimeTrackDraggingIndex.current, percent); | ||
} | ||
}, | ||
onPositionChange: position => { | ||
if (realTimeTrackDraggingIndex.current !== undefined && trackRef.current) { | ||
const percent = position / trackRef.current.offsetWidth; | ||
state.setThumbPercent(realTimeTrackDraggingIndex.current, percent); // When track-dragging ends, onDrag is called before a final onPositionChange is | ||
// called, so we can't reset realTimeTrackDraggingIndex until onPositionChange, | ||
// as we still needed to update the thumb position one last time. Hence we | ||
// track whether we're dragging, and the actual dragged index, separately. | ||
if (!isTrackDragging.current) { | ||
realTimeTrackDraggingIndex.current = undefined; | ||
} | ||
onMoveEnd() { | ||
if (realTimeTrackDraggingIndex.current != null) { | ||
stateRef.current.setThumbDragging(realTimeTrackDraggingIndex.current, false); | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
} | ||
}); | ||
let currentPointer = useRef(undefined); | ||
let onDownTrack = (e, id, clientX, clientY) => { | ||
// We only trigger track-dragging if the user clicks on the track itself and nothing is currently being dragged. | ||
if (trackRef.current && !props.isDisabled && state.values.every((_, i) => !state.isThumbDragging(i))) { | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; // Find the closest thumb | ||
const trackPosition = trackRef.current.getBoundingClientRect()[isVertical ? 'top' : 'left']; | ||
const clickPosition = isVertical ? clientY : clientX; | ||
const offset = clickPosition - trackPosition; | ||
let percent = offset / size; | ||
if (direction === 'rtl' || isVertical) { | ||
percent = 1 - percent; | ||
} | ||
let value = state.getPercentValue(percent); // Only compute the diff for thumbs that are editable, as only they can be dragged | ||
const minDiff = Math.min(...state.values.map((v, index) => state.isThumbEditable(index) ? Math.abs(v - value) : Number.POSITIVE_INFINITY)); | ||
const index = state.values.findIndex(v => Math.abs(v - value) === minDiff); | ||
if (minDiff !== Number.POSITIVE_INFINITY && index >= 0) { | ||
// Don't unfocus anything | ||
e.preventDefault(); | ||
realTimeTrackDraggingIndex.current = index; | ||
state.setFocusedThumb(index); | ||
currentPointer.current = id; | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, true); | ||
state.setThumbValue(index, value); | ||
addGlobalListener(window, 'mouseup', onUpTrack, false); | ||
addGlobalListener(window, 'touchend', onUpTrack, false); | ||
addGlobalListener(window, 'pointerup', onUpTrack, false); | ||
} else { | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
} | ||
}; | ||
let onUpTrack = e => { | ||
var _e$pointerId, _e$changedTouches; | ||
let id = (_e$pointerId = e.pointerId) != null ? _e$pointerId : (_e$changedTouches = e.changedTouches) == null ? void 0 : _e$changedTouches[0].identifier; | ||
if (id === currentPointer.current) { | ||
if (realTimeTrackDraggingIndex.current != null) { | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, false); | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
removeGlobalListener(window, 'mouseup', onUpTrack, false); | ||
removeGlobalListener(window, 'touchend', onUpTrack, false); | ||
removeGlobalListener(window, 'pointerup', onUpTrack, false); | ||
} | ||
}; | ||
return { | ||
@@ -73,38 +151,15 @@ labelProps, | ||
trackProps: mergeProps({ | ||
onMouseDown: e => { | ||
// We only trigger track-dragging if the user clicks on the track itself. | ||
if (trackRef.current && isSliderEditable) { | ||
// Find the closest thumb | ||
const trackPosition = trackRef.current.getBoundingClientRect().left; | ||
const clickPosition = e.clientX; | ||
const offset = clickPosition - trackPosition; | ||
const percent = offset / trackRef.current.offsetWidth; | ||
const value = state.getPercentValue(percent); // Only compute the diff for thumbs that are editable, as only they can be dragged | ||
onMouseDown(e) { | ||
onDownTrack(e, undefined, e.clientX, e.clientY); | ||
}, | ||
const minDiff = Math.min(...state.values.map((v, index) => state.isThumbEditable(index) ? Math.abs(v - value) : Number.POSITIVE_INFINITY)); | ||
const index = state.values.findIndex(v => Math.abs(v - value) === minDiff); | ||
onPointerDown(e) { | ||
onDownTrack(e, e.pointerId, e.clientX, e.clientY); | ||
}, | ||
if (minDiff !== Number.POSITIVE_INFINITY && index >= 0) { | ||
// Don't unfocus anything | ||
e.preventDefault(); | ||
realTimeTrackDraggingIndex.current = index; | ||
state.setFocusedThumb(index); // We immediately toggle state to dragging and set the value on mouse down. | ||
// We set the value now, instead of waiting for onDrag, so that the thumb | ||
// is updated while you're still holding the mouse button down. And we | ||
// set dragging on now, so that onChangeEnd() won't fire yet when we set | ||
// the value. Dragging state will be reset to false in onDrag above, even | ||
// if no dragging actually occurs. | ||
onTouchStart(e) { | ||
onDownTrack(e, e.changedTouches[0].identifier, e.changedTouches[0].clientX, e.changedTouches[0].clientY); | ||
} | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, true); | ||
state.setThumbValue(index, value); | ||
} else { | ||
realTimeTrackDraggingIndex.current = undefined; | ||
} | ||
} | ||
} | ||
}, { | ||
onMouseDown, | ||
onMouseEnter, | ||
onMouseOut | ||
}) | ||
}, moveProps) | ||
}; | ||
@@ -122,7 +177,6 @@ } | ||
const { | ||
let { | ||
index, | ||
isRequired, | ||
isDisabled, | ||
isReadOnly, | ||
validationState, | ||
@@ -132,2 +186,10 @@ trackRef, | ||
} = opts; | ||
let isVertical = opts.orientation === 'vertical'; | ||
let { | ||
direction | ||
} = useLocale(); | ||
let { | ||
addGlobalListener, | ||
removeGlobalListener | ||
} = useGlobalListeners(); | ||
let labelId = $d20491ae7743da17cfa841ff6d87$export$sliderIds.get(state); | ||
@@ -141,3 +203,2 @@ const { | ||
const value = state.values[index]; | ||
const isEditable = !(isDisabled || isReadOnly); | ||
const focusInput = useCallback(() => { | ||
@@ -154,17 +215,50 @@ if (inputRef.current) { | ||
}, [isFocused, focusInput]); | ||
const draggableProps = useDrag1D({ | ||
containerRef: trackRef, | ||
reverse: false, | ||
orientation: 'horizontal', | ||
onDrag: dragging => { | ||
state.setThumbDragging(index, dragging); | ||
focusInput(); | ||
const stateRef = useRef(null); | ||
stateRef.current = state; | ||
let reverseX = direction === 'rtl'; | ||
let currentPosition = useRef(null); | ||
let { | ||
moveProps | ||
} = useMove({ | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
state.setThumbDragging(index, true); | ||
}, | ||
onPositionChange: position => { | ||
const percent = position / trackRef.current.offsetWidth; | ||
state.setThumbPercent(index, percent); | ||
onMove(_ref) { | ||
let { | ||
deltaX, | ||
deltaY, | ||
pointerType | ||
} = _ref; | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
if (currentPosition.current == null) { | ||
currentPosition.current = stateRef.current.getThumbPercent(index) * size; | ||
} | ||
if (pointerType === 'keyboard') { | ||
// (invert left/right according to language direction) + (according to vertical) | ||
let delta = ((reverseX ? -deltaX : deltaX) + (isVertical ? -deltaY : -deltaY)) * stateRef.current.step; | ||
currentPosition.current += delta * size; | ||
stateRef.current.setThumbValue(index, stateRef.current.getThumbValue(index) + delta); | ||
} else { | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
delta = -delta; | ||
} | ||
currentPosition.current += delta; | ||
stateRef.current.setThumbPercent(index, clamp(currentPosition.current / size, 0, 1)); | ||
} | ||
}, | ||
onMoveEnd() { | ||
state.setThumbDragging(index, false); | ||
} | ||
}); // Immediately register editability with the state | ||
state.setThumbEditable(index, isEditable); | ||
state.setThumbEditable(index, !isDisabled); | ||
const { | ||
@@ -175,3 +269,27 @@ focusableProps | ||
onBlur: () => state.setFocusedThumb(undefined) | ||
}), inputRef); // We install mouse handlers for the drag motion on the thumb div, but | ||
}), inputRef); | ||
let currentPointer = useRef(undefined); | ||
let onDown = id => { | ||
focusInput(); | ||
currentPointer.current = id; | ||
state.setThumbDragging(index, true); | ||
addGlobalListener(window, 'mouseup', onUp, false); | ||
addGlobalListener(window, 'touchend', onUp, false); | ||
addGlobalListener(window, 'pointerup', onUp, false); | ||
}; | ||
let onUp = e => { | ||
var _e$pointerId, _e$changedTouches; | ||
let id = (_e$pointerId = e.pointerId) != null ? _e$pointerId : (_e$changedTouches = e.changedTouches) == null ? void 0 : _e$changedTouches[0].identifier; | ||
if (id === currentPointer.current) { | ||
focusInput(); | ||
state.setThumbDragging(index, false); | ||
removeGlobalListener(window, 'mouseup', onUp, false); | ||
removeGlobalListener(window, 'touchend', onUp, false); | ||
removeGlobalListener(window, 'pointerup', onUp, 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, | ||
@@ -181,6 +299,7 @@ // we focus the range input, and let the browser handle the keyboard | ||
return { | ||
inputProps: mergeProps(focusableProps, fieldProps, { | ||
type: 'range', | ||
tabIndex: isEditable ? 0 : undefined, | ||
tabIndex: !isDisabled ? 0 : undefined, | ||
min: state.getThumbMinValue(index), | ||
@@ -190,5 +309,4 @@ max: state.getThumbMaxValue(index), | ||
value: value, | ||
readOnly: isReadOnly, | ||
disabled: isDisabled, | ||
'aria-orientation': 'horizontal', | ||
'aria-orientation': opts.orientation, | ||
'aria-valuetext': state.getThumbValueLabel(index), | ||
@@ -202,8 +320,12 @@ 'aria-required': isRequired || undefined, | ||
}), | ||
thumbProps: isEditable ? mergeProps({ | ||
onMouseDown: draggableProps.onMouseDown, | ||
onMouseEnter: draggableProps.onMouseEnter, | ||
onMouseOut: draggableProps.onMouseOut | ||
}, { | ||
onMouseDown: focusInput | ||
thumbProps: !isDisabled ? mergeProps(moveProps, { | ||
onMouseDown: () => { | ||
onDown(null); | ||
}, | ||
onPointerDown: e => { | ||
onDown(e.pointerId); | ||
}, | ||
onTouchStart: e => { | ||
onDown(e.changedTouches[0].identifier); | ||
} | ||
}) : {}, | ||
@@ -210,0 +332,0 @@ labelProps |
@@ -1,2 +0,2 @@ | ||
import { HTMLAttributes } from "react"; | ||
import React, { HTMLAttributes } from "react"; | ||
import { SliderProps, SliderThumbProps } from "@react-types/slider"; | ||
@@ -31,3 +31,3 @@ import { SliderState } from "@react-stately/slider"; | ||
} | ||
interface SliderThumbOptions extends SliderThumbProps { | ||
export interface SliderThumbOptions extends SliderThumbProps { | ||
trackRef: React.RefObject<HTMLElement>; | ||
@@ -34,0 +34,0 @@ inputRef: React.RefObject<HTMLInputElement>; |
{ | ||
"name": "@react-aria/slider", | ||
"version": "3.0.0-alpha.2", | ||
"version": "3.0.0-alpha.3", | ||
"description": "Slider", | ||
@@ -21,11 +21,11 @@ "license": "Apache-2.0", | ||
"@babel/runtime": "^7.6.2", | ||
"@react-aria/focus": "^3.2.2", | ||
"@react-aria/i18n": "^3.1.2", | ||
"@react-aria/interactions": "^3.2.1", | ||
"@react-aria/focus": "^3.2.3", | ||
"@react-aria/i18n": "^3.1.3", | ||
"@react-aria/interactions": "^3.3.0", | ||
"@react-aria/label": "^3.1.1", | ||
"@react-aria/utils": "^3.3.0", | ||
"@react-aria/utils": "^3.4.0", | ||
"@react-stately/radio": "^3.2.1", | ||
"@react-stately/slider": "3.0.0-alpha.2", | ||
"@react-stately/slider": "3.0.0-alpha.3", | ||
"@react-types/radio": "^3.1.1", | ||
"@react-types/slider": "3.0.0-alpha.1" | ||
"@react-types/slider": "3.0.0-alpha.2" | ||
}, | ||
@@ -38,3 +38,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "0778f71a3c13e1e24388a23b6d525e3b9f5b98f1" | ||
"gitHead": "9f738a06ea4e256c8d975f00502b4b0bbabb8f65" | ||
} |
@@ -13,4 +13,4 @@ /* | ||
import {HTMLAttributes, useRef} from 'react'; | ||
import {mergeProps, useDrag1D} from '@react-aria/utils'; | ||
import {clamp, mergeProps, useGlobalListeners} from '@react-aria/utils'; | ||
import React, {HTMLAttributes, useRef} from 'react'; | ||
import {sliderIds} from './utils'; | ||
@@ -20,2 +20,4 @@ import {SliderProps} from '@react-types/slider'; | ||
import {useLabel} from '@react-aria/label'; | ||
import {useLocale} from '@react-aria/i18n'; | ||
import {useMove} from '@react-aria/interactions'; | ||
@@ -48,5 +50,5 @@ interface SliderAria { | ||
): SliderAria { | ||
const {labelProps, fieldProps} = useLabel(props); | ||
let {labelProps, fieldProps} = useLabel(props); | ||
const isSliderEditable = !(props.isDisabled || props.isReadOnly); | ||
let isVertical = props.orientation === 'vertical'; | ||
@@ -56,37 +58,101 @@ // Attach id of the label to the state so it can be accessed by useSliderThumb. | ||
let {direction} = useLocale(); | ||
let {addGlobalListener, removeGlobalListener} = useGlobalListeners(); | ||
// When the user clicks or drags the track, we want the motion to set and drag the | ||
// closest thumb. Hence we also need to install useDrag1D() on the track element. | ||
// closest thumb. Hence we also need to install useMove() on the track element. | ||
// Here, we keep track of which index is the "closest" to the drag start point. | ||
// It is set onMouseDown; see trackProps below. | ||
const realTimeTrackDraggingIndex = useRef<number | undefined>(undefined); | ||
const isTrackDragging = useRef(false); | ||
const {onMouseDown, onMouseEnter, onMouseOut} = useDrag1D({ | ||
containerRef: trackRef as any, | ||
reverse: false, | ||
orientation: 'horizontal', | ||
onDrag: (dragging) => { | ||
if (realTimeTrackDraggingIndex.current !== undefined) { | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, dragging); | ||
} | ||
isTrackDragging.current = dragging; | ||
// It is set onMouseDown/onTouchDown; see trackProps below. | ||
const realTimeTrackDraggingIndex = useRef<number | null>(null); | ||
const stateRef = useRef<SliderState>(null); | ||
stateRef.current = state; | ||
const reverseX = direction === 'rtl'; | ||
const currentPosition = useRef<number>(null); | ||
const {moveProps} = useMove({ | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
}, | ||
onPositionChange: (position) => { | ||
if (realTimeTrackDraggingIndex.current !== undefined && trackRef.current) { | ||
const percent = position / trackRef.current.offsetWidth; | ||
state.setThumbPercent(realTimeTrackDraggingIndex.current, percent); | ||
onMove({deltaX, deltaY}) { | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
// When track-dragging ends, onDrag is called before a final onPositionChange is | ||
// called, so we can't reset realTimeTrackDraggingIndex until onPositionChange, | ||
// as we still needed to update the thumb position one last time. Hence we | ||
// track whether we're dragging, and the actual dragged index, separately. | ||
if (!isTrackDragging.current) { | ||
realTimeTrackDraggingIndex.current = undefined; | ||
} | ||
if (currentPosition.current == null) { | ||
currentPosition.current = stateRef.current.getThumbPercent(realTimeTrackDraggingIndex.current) * size; | ||
} | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
delta = -delta; | ||
} | ||
currentPosition.current += delta; | ||
if (realTimeTrackDraggingIndex.current != null && trackRef.current) { | ||
const percent = clamp(currentPosition.current / size, 0, 1); | ||
stateRef.current.setThumbPercent(realTimeTrackDraggingIndex.current, percent); | ||
} | ||
}, | ||
onMoveEnd() { | ||
if (realTimeTrackDraggingIndex.current != null) { | ||
stateRef.current.setThumbDragging(realTimeTrackDraggingIndex.current, false); | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
} | ||
}); | ||
let currentPointer = useRef<number | null | undefined>(undefined); | ||
let onDownTrack = (e: React.UIEvent, id: number, clientX: number, clientY: number) => { | ||
// We only trigger track-dragging if the user clicks on the track itself and nothing is currently being dragged. | ||
if (trackRef.current && !props.isDisabled && state.values.every((_, i) => !state.isThumbDragging(i))) { | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
// Find the closest thumb | ||
const trackPosition = trackRef.current.getBoundingClientRect()[isVertical ? 'top' : 'left']; | ||
const clickPosition = isVertical ? clientY : clientX; | ||
const offset = clickPosition - trackPosition; | ||
let percent = offset / size; | ||
if (direction === 'rtl' || isVertical) { | ||
percent = 1 - percent; | ||
} | ||
let value = state.getPercentValue(percent); | ||
// Only compute the diff for thumbs that are editable, as only they can be dragged | ||
const minDiff = Math.min(...state.values.map((v, index) => state.isThumbEditable(index) ? Math.abs(v - value) : Number.POSITIVE_INFINITY)); | ||
const index = state.values.findIndex(v => Math.abs(v - value) === minDiff); | ||
if (minDiff !== Number.POSITIVE_INFINITY && index >= 0) { | ||
// Don't unfocus anything | ||
e.preventDefault(); | ||
realTimeTrackDraggingIndex.current = index; | ||
state.setFocusedThumb(index); | ||
currentPointer.current = id; | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, true); | ||
state.setThumbValue(index, value); | ||
addGlobalListener(window, 'mouseup', onUpTrack, false); | ||
addGlobalListener(window, 'touchend', onUpTrack, false); | ||
addGlobalListener(window, 'pointerup', onUpTrack, false); | ||
} else { | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
} | ||
}; | ||
let onUpTrack = (e) => { | ||
let id = e.pointerId ?? e.changedTouches?.[0].identifier; | ||
if (id === currentPointer.current) { | ||
if (realTimeTrackDraggingIndex.current != null) { | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, false); | ||
realTimeTrackDraggingIndex.current = null; | ||
} | ||
removeGlobalListener(window, 'mouseup', onUpTrack, false); | ||
removeGlobalListener(window, 'touchend', onUpTrack, false); | ||
removeGlobalListener(window, 'pointerup', onUpTrack, false); | ||
} | ||
}; | ||
return { | ||
labelProps, | ||
// The root element of the Slider will have role="group" to group together | ||
@@ -100,39 +166,7 @@ // all the thumb inputs in the Slider. The label of the Slider will | ||
trackProps: mergeProps({ | ||
onMouseDown: (e: React.MouseEvent<HTMLElement>) => { | ||
// We only trigger track-dragging if the user clicks on the track itself. | ||
if (trackRef.current && isSliderEditable) { | ||
// Find the closest thumb | ||
const trackPosition = trackRef.current.getBoundingClientRect().left; | ||
const clickPosition = e.clientX; | ||
const offset = clickPosition - trackPosition; | ||
const percent = offset / trackRef.current.offsetWidth; | ||
const value = state.getPercentValue(percent); | ||
// Only compute the diff for thumbs that are editable, as only they can be dragged | ||
const minDiff = Math.min(...state.values.map((v, index) => state.isThumbEditable(index) ? Math.abs(v - value) : Number.POSITIVE_INFINITY)); | ||
const index = state.values.findIndex(v => Math.abs(v - value) === minDiff); | ||
if (minDiff !== Number.POSITIVE_INFINITY && index >= 0) { | ||
// Don't unfocus anything | ||
e.preventDefault(); | ||
realTimeTrackDraggingIndex.current = index; | ||
state.setFocusedThumb(index); | ||
// We immediately toggle state to dragging and set the value on mouse down. | ||
// We set the value now, instead of waiting for onDrag, so that the thumb | ||
// is updated while you're still holding the mouse button down. And we | ||
// set dragging on now, so that onChangeEnd() won't fire yet when we set | ||
// the value. Dragging state will be reset to false in onDrag above, even | ||
// if no dragging actually occurs. | ||
state.setThumbDragging(realTimeTrackDraggingIndex.current, true); | ||
state.setThumbValue(index, value); | ||
} else { | ||
realTimeTrackDraggingIndex.current = undefined; | ||
} | ||
} | ||
} | ||
}, { | ||
onMouseDown, onMouseEnter, onMouseOut | ||
}) | ||
onMouseDown(e: React.MouseEvent<HTMLElement>) { onDownTrack(e, undefined, e.clientX, e.clientY); }, | ||
onPointerDown(e: React.PointerEvent<HTMLElement>) { onDownTrack(e, e.pointerId, e.clientX, e.clientY); }, | ||
onTouchStart(e: React.TouchEvent<HTMLElement>) { onDownTrack(e, e.changedTouches[0].identifier, e.changedTouches[0].clientX, e.changedTouches[0].clientY); } | ||
}, moveProps) | ||
}; | ||
} |
@@ -1,3 +0,3 @@ | ||
import {ChangeEvent, HTMLAttributes, useCallback, useEffect} from 'react'; | ||
import {focusWithoutScrolling, mergeProps, useDrag1D} from '@react-aria/utils'; | ||
import {clamp, focusWithoutScrolling, mergeProps, useGlobalListeners} from '@react-aria/utils'; | ||
import React, {ChangeEvent, HTMLAttributes, useCallback, useEffect, useRef} from 'react'; | ||
import {sliderIds} from './utils'; | ||
@@ -8,2 +8,4 @@ import {SliderState} from '@react-stately/slider'; | ||
import {useLabel} from '@react-aria/label'; | ||
import {useLocale} from '@react-aria/i18n'; | ||
import {useMove} from '@react-aria/interactions'; | ||
@@ -21,3 +23,3 @@ interface SliderThumbAria { | ||
interface SliderThumbOptions extends SliderThumbProps { | ||
export interface SliderThumbOptions extends SliderThumbProps { | ||
trackRef: React.RefObject<HTMLElement>, | ||
@@ -35,9 +37,8 @@ inputRef: React.RefObject<HTMLInputElement> | ||
opts: SliderThumbOptions, | ||
state: SliderState, | ||
state: SliderState | ||
): SliderThumbAria { | ||
const { | ||
let { | ||
index, | ||
isRequired, | ||
isDisabled, | ||
isReadOnly, | ||
validationState, | ||
@@ -48,2 +49,7 @@ trackRef, | ||
let isVertical = opts.orientation === 'vertical'; | ||
let {direction} = useLocale(); | ||
let {addGlobalListener, removeGlobalListener} = useGlobalListeners(); | ||
let labelId = sliderIds.get(state); | ||
@@ -56,3 +62,2 @@ const {labelProps, fieldProps} = useLabel({ | ||
const value = state.values[index]; | ||
const isEditable = !(isDisabled || isReadOnly); | ||
@@ -73,13 +78,34 @@ const focusInput = useCallback(() => { | ||
const draggableProps = useDrag1D({ | ||
containerRef: trackRef as any, | ||
reverse: false, | ||
orientation: 'horizontal', | ||
onDrag: (dragging) => { | ||
state.setThumbDragging(index, dragging); | ||
focusInput(); | ||
const stateRef = useRef<SliderState>(null); | ||
stateRef.current = state; | ||
let reverseX = direction === 'rtl'; | ||
let currentPosition = useRef<number>(null); | ||
let {moveProps} = useMove({ | ||
onMoveStart() { | ||
currentPosition.current = null; | ||
state.setThumbDragging(index, true); | ||
}, | ||
onPositionChange: (position) => { | ||
const percent = position / trackRef.current.offsetWidth; | ||
state.setThumbPercent(index, percent); | ||
onMove({deltaX, deltaY, pointerType}) { | ||
let size = isVertical ? trackRef.current.offsetHeight : trackRef.current.offsetWidth; | ||
if (currentPosition.current == null) { | ||
currentPosition.current = stateRef.current.getThumbPercent(index) * size; | ||
} | ||
if (pointerType === 'keyboard') { | ||
// (invert left/right according to language direction) + (according to vertical) | ||
let delta = ((reverseX ? -deltaX : deltaX) + (isVertical ? -deltaY : -deltaY)) * stateRef.current.step; | ||
currentPosition.current += delta * size; | ||
stateRef.current.setThumbValue(index, stateRef.current.getThumbValue(index) + delta); | ||
} else { | ||
let delta = isVertical ? deltaY : deltaX; | ||
if (isVertical || reverseX) { | ||
delta = -delta; | ||
} | ||
currentPosition.current += delta; | ||
stateRef.current.setThumbPercent(index, clamp(currentPosition.current / size, 0, 1)); | ||
} | ||
}, | ||
onMoveEnd() { | ||
state.setThumbDragging(index, false); | ||
} | ||
@@ -89,3 +115,3 @@ }); | ||
// Immediately register editability with the state | ||
state.setThumbEditable(index, isEditable); | ||
state.setThumbEditable(index, !isDisabled); | ||
@@ -100,2 +126,25 @@ const {focusableProps} = useFocusable( | ||
let currentPointer = useRef<number | null | undefined>(undefined); | ||
let onDown = (id: number | null) => { | ||
focusInput(); | ||
currentPointer.current = id; | ||
state.setThumbDragging(index, true); | ||
addGlobalListener(window, 'mouseup', onUp, false); | ||
addGlobalListener(window, 'touchend', onUp, false); | ||
addGlobalListener(window, 'pointerup', onUp, false); | ||
}; | ||
let onUp = (e) => { | ||
let id = e.pointerId ?? e.changedTouches?.[0].identifier; | ||
if (id === currentPointer.current) { | ||
focusInput(); | ||
state.setThumbDragging(index, false); | ||
removeGlobalListener(window, 'mouseup', onUp, false); | ||
removeGlobalListener(window, 'touchend', onUp, false); | ||
removeGlobalListener(window, 'pointerup', onUp, false); | ||
} | ||
}; | ||
// We install mouse handlers for the drag motion on the thumb div, but | ||
@@ -108,3 +157,3 @@ // not the key handler for moving the thumb with the slider. Instead, | ||
type: 'range', | ||
tabIndex: isEditable ? 0 : undefined, | ||
tabIndex: !isDisabled ? 0 : undefined, | ||
min: state.getThumbMinValue(index), | ||
@@ -114,5 +163,4 @@ max: state.getThumbMaxValue(index), | ||
value: value, | ||
readOnly: isReadOnly, | ||
disabled: isDisabled, | ||
'aria-orientation': 'horizontal', | ||
'aria-orientation': opts.orientation, | ||
'aria-valuetext': state.getThumbValueLabel(index), | ||
@@ -126,11 +174,12 @@ 'aria-required': isRequired || undefined, | ||
}), | ||
thumbProps: isEditable ? mergeProps({ | ||
onMouseDown: draggableProps.onMouseDown, | ||
onMouseEnter: draggableProps.onMouseEnter, | ||
onMouseOut: draggableProps.onMouseOut | ||
}, { | ||
onMouseDown: focusInput | ||
}) : {}, | ||
thumbProps: !isDisabled ? mergeProps( | ||
moveProps, | ||
{ | ||
onMouseDown: () => {onDown(null);}, | ||
onPointerDown: (e: React.PointerEvent) => {onDown(e.pointerId);}, | ||
onTouchStart: (e: React.TouchEvent) => {onDown(e.changedTouches[0].identifier);} | ||
} | ||
) : {}, | ||
labelProps | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
102333
941
31
62
6
+ Added@react-stately/slider@3.0.0-alpha.3(transitive)
+ Added@react-types/slider@3.0.0-alpha.2(transitive)
- Removed@react-stately/slider@3.0.0-alpha.2(transitive)
- Removed@react-types/slider@3.0.0-alpha.1(transitive)
Updated@react-aria/focus@^3.2.3
Updated@react-aria/i18n@^3.1.3
Updated@react-aria/utils@^3.4.0