@atlaskit/range
Version:
A range lets users choose an approximate value on a slider.
75 lines (71 loc) • 2.46 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import React, { forwardRef, useCallback, useState } from 'react';
import __noop from '@atlaskit/ds-lib/noop';
import { Input } from './styled';
// Combine omits the keys of the second from the first so in case of overlap the props of the second are used.
// OwnProps is used for external documentation, but does not list every property supported by Range.
// So we combine (a reduced list of) HTMLInputElement attributes with OwnProps to get the full type.
const snapToStep = (value, min, step) => {
// Normalise the value to allow for division properly with different min values
const adjustedValue = value - min;
// Find the number of steps the value covers
const numSteps = Math.round(adjustedValue / step);
// Convert numSteps back into original range
return numSteps * step + min;
};
const getRoundedPercentValue = (value, min, max, step) => {
let percent = '0';
if (min < max && value > min) {
const snappedValue = snapToStep(value, min, step);
percent = ((snappedValue - min) / (max - min) * 100).toFixed(2);
}
return percent;
};
const noop = __noop;
/**
* __Range__
*
* A range lets users choose an approximate value on a slider.
*
* - [Examples](https://atlassian.design/components/range/examples)
* - [Code](https://atlassian.design/components/range/code)
* - [Usage](https://atlassian.design/components/range/usage)
*/
const Range = /*#__PURE__*/forwardRef(function Range(props, ref) {
const {
isDisabled = false,
defaultValue = 50,
max = 100,
min = 0,
onChange = noop,
step = 1,
value: propsValue,
testId,
...rest
} = props;
const spreadProps = {
max,
min,
step,
ref,
...rest
};
const [value, setValue] = useState(propsValue !== undefined ? propsValue : defaultValue);
const handleChange = useCallback(e => {
const newValue = Number(e.target.value);
setValue(newValue);
// Note use of newValue to ensure up=to-date value is used
onChange(newValue);
}, [onChange]);
const renderValue = propsValue !== undefined ? propsValue : value;
const valuePercent = getRoundedPercentValue(renderValue, min, max, step);
return /*#__PURE__*/React.createElement(Input, _extends({
type: "range",
disabled: isDisabled,
onChange: handleChange,
value: renderValue,
valuePercent: valuePercent,
"data-testid": testId
}, spreadProps));
});
export default Range;