Socket
Socket
Sign inDemoInstall

@react-aria/slider

Package Overview
Dependencies
Maintainers
1
Versions
739
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-aria/slider - npm Package Compare versions

Comparing version 3.0.0-nightly.2414 to 3.0.0-nightly.2416

265

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"));

@@ -48,41 +57,97 @@

fieldProps
} = useLabel(props);
const isSliderEditable = !(props.isDisabled || props.isReadOnly); // Attach id of the label to the state so it can be accessed by useSliderThumb.
} = useLabel(props); // 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 {
onMouseDown,
onMouseEnter,
onMouseOut
} = useDrag1D({
containerRef: trackRef,
reverse: false,
orientation: 'horizontal',
onDrag: dragging => {
if (realTimeTrackDraggingIndex.current !== undefined) {
state.setThumbDragging(realTimeTrackDraggingIndex.current, dragging);
const realTimeTrackDraggingIndex = useRef(null);
const stateRef = useRef(null);
stateRef.current = state;
const reverseX = direction === 'rtl';
const currentPosition = useRef(null);
const moveProps = useMove({
onMoveStart() {
currentPosition.current = null;
},
onMove(_ref) {
let {
deltaX
} = _ref;
if (currentPosition.current == null) {
currentPosition.current = stateRef.current.getThumbPercent(realTimeTrackDraggingIndex.current) * trackRef.current.offsetWidth;
}
isTrackDragging.current = dragging;
currentPosition.current += reverseX ? -deltaX : deltaX;
if (realTimeTrackDraggingIndex.current != null && trackRef.current) {
const percent = clamp(currentPosition.current / trackRef.current.offsetWidth, 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 onDownTrack = (e, clientX) => {
// 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))) {
// Find the closest thumb
const trackPosition = trackRef.current.getBoundingClientRect().left;
const clickPosition = clientX;
const offset = clickPosition - trackPosition;
let percent = offset / trackRef.current.offsetWidth;
if (direction === 'rtl') {
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);
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 = () => {
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 +162,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, e.clientX);
},
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.clientX);
},
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.targetTouches[0].clientX);
}
state.setThumbDragging(realTimeTrackDraggingIndex.current, true);
state.setThumbValue(index, value);
} else {
realTimeTrackDraggingIndex.current = undefined;
}
}
}
}, {
onMouseDown,
onMouseEnter,
onMouseOut
})
}, moveProps)
};

@@ -152,3 +194,2 @@ }

isDisabled,
isReadOnly,
validationState,

@@ -158,2 +199,9 @@ trackRef,

} = opts;
let {
direction
} = useLocale();
let {
addGlobalListener,
removeGlobalListener
} = useGlobalListeners();
let labelId = $dec1906781d9c7cb69245fc4d5344b$export$sliderIds.get(state);

@@ -167,3 +215,2 @@ const {

const value = state.values[index];
const isEditable = !(isDisabled || isReadOnly);
const focusInput = useCallback(() => {

@@ -180,17 +227,41 @@ 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;
if (currentPosition.current == null) {
currentPosition.current = stateRef.current.getThumbPercent(index) * trackRef.current.offsetWidth;
}
if (pointerType === 'keyboard') {
// (invert left/right according to language direction) + (up should always increase)
let delta = ((reverseX ? -deltaX : deltaX) + -deltaY) * stateRef.current.step;
currentPosition.current += delta * trackRef.current.offsetWidth;
stateRef.current.setThumbValue(index, stateRef.current.getThumbValue(index) + delta);
} else {
currentPosition.current += reverseX ? -deltaX : deltaX;
stateRef.current.setThumbPercent(index, clamp(currentPosition.current / trackRef.current.offsetWidth, 0, 1));
}
},
onMoveEnd() {
state.setThumbDragging(index, false);
}
}); // Immediately register editability with the state
state.setThumbEditable(index, isEditable);
state.setThumbEditable(index, !isDisabled);
const {

@@ -201,3 +272,19 @@ focusableProps

onBlur: () => state.setFocusedThumb(undefined)
}), inputRef); // We install mouse handlers for the drag motion on the thumb div, but
}), inputRef);
let onDown = () => {
focusInput();
state.setThumbDragging(index, true);
addGlobalListener(window, 'mouseup', onUp, false);
addGlobalListener(window, 'touchend', onUp, false);
addGlobalListener(window, 'pointerup', onUp, false);
};
let onUp = () => {
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 +294,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,3 +304,2 @@ max: state.getThumbMaxValue(index),

value: value,
readOnly: isReadOnly,
disabled: isDisabled,

@@ -228,8 +315,6 @@ 'aria-orientation': 'horizontal',

}),
thumbProps: isEditable ? mergeProps({
onMouseDown: draggableProps.onMouseDown,
onMouseEnter: draggableProps.onMouseEnter,
onMouseOut: draggableProps.onMouseOut
}, {
onMouseDown: focusInput
thumbProps: !isDisabled ? mergeProps(moveProps, {
onPointerDown: onDown,
onMouseDown: onDown,
onTouchStart: onDown
}) : {},

@@ -236,0 +321,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";

@@ -24,41 +26,97 @@ const $d20491ae7743da17cfa841ff6d87$export$sliderIds = new WeakMap();

fieldProps
} = useLabel(props);
const isSliderEditable = !(props.isDisabled || props.isReadOnly); // Attach id of the label to the state so it can be accessed by useSliderThumb.
} = useLabel(props); // 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 {
onMouseDown,
onMouseEnter,
onMouseOut
} = useDrag1D({
containerRef: trackRef,
reverse: false,
orientation: 'horizontal',
onDrag: dragging => {
if (realTimeTrackDraggingIndex.current !== undefined) {
state.setThumbDragging(realTimeTrackDraggingIndex.current, dragging);
const realTimeTrackDraggingIndex = useRef(null);
const stateRef = useRef(null);
stateRef.current = state;
const reverseX = direction === 'rtl';
const currentPosition = useRef(null);
const moveProps = useMove({
onMoveStart() {
currentPosition.current = null;
},
onMove(_ref) {
let {
deltaX
} = _ref;
if (currentPosition.current == null) {
currentPosition.current = stateRef.current.getThumbPercent(realTimeTrackDraggingIndex.current) * trackRef.current.offsetWidth;
}
isTrackDragging.current = dragging;
currentPosition.current += reverseX ? -deltaX : deltaX;
if (realTimeTrackDraggingIndex.current != null && trackRef.current) {
const percent = clamp(currentPosition.current / trackRef.current.offsetWidth, 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 onDownTrack = (e, clientX) => {
// 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))) {
// Find the closest thumb
const trackPosition = trackRef.current.getBoundingClientRect().left;
const clickPosition = clientX;
const offset = clickPosition - trackPosition;
let percent = offset / trackRef.current.offsetWidth;
if (direction === 'rtl') {
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);
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 = () => {
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 +131,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, e.clientX);
},
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.clientX);
},
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.targetTouches[0].clientX);
}
state.setThumbDragging(realTimeTrackDraggingIndex.current, true);
state.setThumbValue(index, value);
} else {
realTimeTrackDraggingIndex.current = undefined;
}
}
}
}, {
onMouseDown,
onMouseEnter,
onMouseOut
})
}, moveProps)
};

@@ -126,3 +161,2 @@ }

isDisabled,
isReadOnly,
validationState,

@@ -132,2 +166,9 @@ trackRef,

} = opts;
let {
direction
} = useLocale();
let {
addGlobalListener,
removeGlobalListener
} = useGlobalListeners();
let labelId = $d20491ae7743da17cfa841ff6d87$export$sliderIds.get(state);

@@ -141,3 +182,2 @@ const {

const value = state.values[index];
const isEditable = !(isDisabled || isReadOnly);
const focusInput = useCallback(() => {

@@ -154,17 +194,41 @@ 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;
if (currentPosition.current == null) {
currentPosition.current = stateRef.current.getThumbPercent(index) * trackRef.current.offsetWidth;
}
if (pointerType === 'keyboard') {
// (invert left/right according to language direction) + (up should always increase)
let delta = ((reverseX ? -deltaX : deltaX) + -deltaY) * stateRef.current.step;
currentPosition.current += delta * trackRef.current.offsetWidth;
stateRef.current.setThumbValue(index, stateRef.current.getThumbValue(index) + delta);
} else {
currentPosition.current += reverseX ? -deltaX : deltaX;
stateRef.current.setThumbPercent(index, clamp(currentPosition.current / trackRef.current.offsetWidth, 0, 1));
}
},
onMoveEnd() {
state.setThumbDragging(index, false);
}
}); // Immediately register editability with the state
state.setThumbEditable(index, isEditable);
state.setThumbEditable(index, !isDisabled);
const {

@@ -175,3 +239,19 @@ focusableProps

onBlur: () => state.setFocusedThumb(undefined)
}), inputRef); // We install mouse handlers for the drag motion on the thumb div, but
}), inputRef);
let onDown = () => {
focusInput();
state.setThumbDragging(index, true);
addGlobalListener(window, 'mouseup', onUp, false);
addGlobalListener(window, 'touchend', onUp, false);
addGlobalListener(window, 'pointerup', onUp, false);
};
let onUp = () => {
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 +261,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,3 +271,2 @@ max: state.getThumbMaxValue(index),

value: value,
readOnly: isReadOnly,
disabled: isDisabled,

@@ -202,8 +282,6 @@ 'aria-orientation': 'horizontal',

}),
thumbProps: isEditable ? mergeProps({
onMouseDown: draggableProps.onMouseDown,
onMouseEnter: draggableProps.onMouseEnter,
onMouseOut: draggableProps.onMouseOut
}, {
onMouseDown: focusInput
thumbProps: !isDisabled ? mergeProps(moveProps, {
onPointerDown: onDown,
onMouseDown: onDown,
onTouchStart: onDown
}) : {},

@@ -210,0 +288,0 @@ labelProps

{
"name": "@react-aria/slider",
"version": "3.0.0-nightly.2414+0ac271ac",
"version": "3.0.0-nightly.2416+dc6d7873",
"description": "Slider",

@@ -21,11 +21,11 @@ "license": "Apache-2.0",

"@babel/runtime": "^7.6.2",
"@react-aria/focus": "3.0.0-nightly.736+0ac271ac",
"@react-aria/i18n": "3.0.0-nightly.736+0ac271ac",
"@react-aria/interactions": "3.0.0-nightly.736+0ac271ac",
"@react-aria/label": "3.0.0-nightly.736+0ac271ac",
"@react-aria/utils": "3.0.0-nightly.736+0ac271ac",
"@react-stately/radio": "3.0.0-nightly.736+0ac271ac",
"@react-stately/slider": "3.0.0-nightly.2414+0ac271ac",
"@react-types/radio": "3.0.0-nightly.736+0ac271ac",
"@react-types/slider": "3.0.0-nightly.2414+0ac271ac"
"@react-aria/focus": "3.0.0-nightly.738+dc6d7873",
"@react-aria/i18n": "3.0.0-nightly.738+dc6d7873",
"@react-aria/interactions": "3.0.0-nightly.738+dc6d7873",
"@react-aria/label": "3.0.0-nightly.738+dc6d7873",
"@react-aria/utils": "3.0.0-nightly.738+dc6d7873",
"@react-stately/radio": "3.0.0-nightly.738+dc6d7873",
"@react-stately/slider": "3.0.0-nightly.2416+dc6d7873",
"@react-types/radio": "3.0.0-nightly.738+dc6d7873",
"@react-types/slider": "3.0.0-nightly.2416+dc6d7873"
},

@@ -38,3 +38,3 @@ "peerDependencies": {

},
"gitHead": "0ac271ac5508fc6b03e0bd416142aba02546164a"
"gitHead": "dc6d78733fb26fa02afeb1a36e11de7d71c84467"
}

@@ -13,4 +13,4 @@ /*

import {clamp, mergeProps, useGlobalListeners} from '@react-aria/utils';
import {HTMLAttributes, useRef} from 'react';
import {mergeProps, useDrag1D} from '@react-aria/utils';
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';

@@ -50,42 +52,90 @@ interface SliderAria {

const isSliderEditable = !(props.isDisabled || props.isReadOnly);
// Attach id of the label to the state so it can be accessed by useSliderThumb.
sliderIds.set(state, 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 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);
// 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;
},
onMove({deltaX}) {
if (currentPosition.current == null) {
currentPosition.current = stateRef.current.getThumbPercent(realTimeTrackDraggingIndex.current) * trackRef.current.offsetWidth;
}
isTrackDragging.current = dragging;
},
onPositionChange: (position) => {
if (realTimeTrackDraggingIndex.current !== undefined && trackRef.current) {
const percent = position / trackRef.current.offsetWidth;
state.setThumbPercent(realTimeTrackDraggingIndex.current, percent);
currentPosition.current += reverseX ? -deltaX : deltaX;
// 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 (realTimeTrackDraggingIndex.current != null && trackRef.current) {
const percent = clamp(currentPosition.current / trackRef.current.offsetWidth, 0, 1);
stateRef.current.setThumbPercent(realTimeTrackDraggingIndex.current, percent);
}
},
onMoveEnd() {
if (realTimeTrackDraggingIndex.current != null) {
stateRef.current.setThumbDragging(realTimeTrackDraggingIndex.current, false);
realTimeTrackDraggingIndex.current = null;
}
}
});
let onDownTrack = (e: React.UIEvent, clientX: 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))) {
// Find the closest thumb
const trackPosition = trackRef.current.getBoundingClientRect().left;
const clickPosition = clientX;
const offset = clickPosition - trackPosition;
let percent = offset / trackRef.current.offsetWidth;
if (direction === 'rtl') {
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);
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 = () => {
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

@@ -99,39 +149,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, e.clientX); },
onPointerDown(e: React.PointerEvent<HTMLElement>) { onDownTrack(e, e.clientX); },
onTouchStart(e: React.TouchEvent<HTMLElement>) { onDownTrack(e, e.targetTouches[0].clientX); }
}, moveProps)
};
}

@@ -1,3 +0,3 @@

import {ChangeEvent, HTMLAttributes, useCallback, useEffect} from 'react';
import {focusWithoutScrolling, mergeProps, useDrag1D} from '@react-aria/utils';
import {ChangeEvent, HTMLAttributes, useCallback, useEffect, useRef} from 'react';
import {clamp, focusWithoutScrolling, mergeProps, useGlobalListeners} from '@react-aria/utils';
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';

@@ -34,3 +36,3 @@ interface SliderThumbAria {

opts: SliderThumbOptions,
state: SliderState,
state: SliderState
): SliderThumbAria {

@@ -41,3 +43,2 @@ const {

isDisabled,
isReadOnly,
validationState,

@@ -48,2 +49,5 @@ trackRef,

let {direction} = useLocale();
let {addGlobalListener, removeGlobalListener} = useGlobalListeners();
let labelId = sliderIds.get(state);

@@ -56,3 +60,2 @@ const {labelProps, fieldProps} = useLabel({

const value = state.values[index];
const isEditable = !(isDisabled || isReadOnly);

@@ -73,13 +76,27 @@ 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}) {
if (currentPosition.current == null) {
currentPosition.current = stateRef.current.getThumbPercent(index) * trackRef.current.offsetWidth;
}
if (pointerType === 'keyboard') {
// (invert left/right according to language direction) + (up should always increase)
let delta = ((reverseX ? -deltaX : deltaX) + -deltaY) * stateRef.current.step;
currentPosition.current += delta * trackRef.current.offsetWidth;
stateRef.current.setThumbValue(index, stateRef.current.getThumbValue(index) + delta);
} else {
currentPosition.current += reverseX ? -deltaX : deltaX;
stateRef.current.setThumbPercent(index, clamp(currentPosition.current / trackRef.current.offsetWidth, 0, 1));
}
},
onMoveEnd() {
state.setThumbDragging(index, false);
}

@@ -89,3 +106,3 @@ });

// Immediately register editability with the state
state.setThumbEditable(index, isEditable);
state.setThumbEditable(index, !isDisabled);

@@ -100,2 +117,20 @@ const {focusableProps} = useFocusable(

let onDown = () => {
focusInput();
state.setThumbDragging(index, true);
addGlobalListener(window, 'mouseup', onUp, false);
addGlobalListener(window, 'touchend', onUp, false);
addGlobalListener(window, 'pointerup', onUp, false);
};
let onUp = () => {
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 +143,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,3 +149,2 @@ max: state.getThumbMaxValue(index),

value: value,
readOnly: isReadOnly,
disabled: isDisabled,

@@ -126,11 +160,12 @@ 'aria-orientation': 'horizontal',

}),
thumbProps: isEditable ? mergeProps({
onMouseDown: draggableProps.onMouseDown,
onMouseEnter: draggableProps.onMouseEnter,
onMouseOut: draggableProps.onMouseOut
}, {
onMouseDown: focusInput
}) : {},
thumbProps: !isDisabled ? mergeProps(
moveProps,
{
onPointerDown: onDown,
onMouseDown: onDown,
onTouchStart: onDown
}
) : {},
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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc