@atlaskit/range
Version:
A range lets users choose an approximate value on a slider.
87 lines (83 loc) • 4.16 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
var _excluded = ["isDisabled", "defaultValue", "max", "min", "onChange", "step", "value", "testId"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
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.
var snapToStep = function snapToStep(value, min, step) {
// Normalise the value to allow for division properly with different min values
var adjustedValue = value - min;
// Find the number of steps the value covers
var numSteps = Math.round(adjustedValue / step);
// Convert numSteps back into original range
return numSteps * step + min;
};
var getRoundedPercentValue = function getRoundedPercentValue(value, min, max, step) {
var percent = '0';
if (min < max && value > min) {
var snappedValue = snapToStep(value, min, step);
percent = ((snappedValue - min) / (max - min) * 100).toFixed(2);
}
return percent;
};
var 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)
*/
var Range = /*#__PURE__*/forwardRef(function Range(props, ref) {
var _props$isDisabled = props.isDisabled,
isDisabled = _props$isDisabled === void 0 ? false : _props$isDisabled,
_props$defaultValue = props.defaultValue,
defaultValue = _props$defaultValue === void 0 ? 50 : _props$defaultValue,
_props$max = props.max,
max = _props$max === void 0 ? 100 : _props$max,
_props$min = props.min,
min = _props$min === void 0 ? 0 : _props$min,
_props$onChange = props.onChange,
onChange = _props$onChange === void 0 ? noop : _props$onChange,
_props$step = props.step,
step = _props$step === void 0 ? 1 : _props$step,
propsValue = props.value,
testId = props.testId,
rest = _objectWithoutProperties(props, _excluded);
var spreadProps = _objectSpread({
max: max,
min: min,
step: step,
ref: ref
}, rest);
var _useState = useState(propsValue !== undefined ? propsValue : defaultValue),
_useState2 = _slicedToArray(_useState, 2),
value = _useState2[0],
setValue = _useState2[1];
var handleChange = useCallback(function (e) {
var newValue = Number(e.target.value);
setValue(newValue);
// Note use of newValue to ensure up=to-date value is used
onChange(newValue);
}, [onChange]);
var renderValue = propsValue !== undefined ? propsValue : value;
var 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;