Slider.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof3 = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  9. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  10. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  11. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  12. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  13. var _classnames = _interopRequireDefault(require("classnames"));
  14. var _useEvent = _interopRequireDefault(require("rc-util/lib/hooks/useEvent"));
  15. var _useMergedState3 = _interopRequireDefault(require("rc-util/lib/hooks/useMergedState"));
  16. var _isEqual = _interopRequireDefault(require("rc-util/lib/isEqual"));
  17. var _warning = _interopRequireDefault(require("rc-util/lib/warning"));
  18. var React = _interopRequireWildcard(require("react"));
  19. var _Handles = _interopRequireDefault(require("./Handles"));
  20. var _Marks = _interopRequireDefault(require("./Marks"));
  21. var _Steps = _interopRequireDefault(require("./Steps"));
  22. var _Tracks = _interopRequireDefault(require("./Tracks"));
  23. var _context = _interopRequireDefault(require("./context"));
  24. var _useDrag3 = _interopRequireDefault(require("./hooks/useDrag"));
  25. var _useOffset3 = _interopRequireDefault(require("./hooks/useOffset"));
  26. var _useRange3 = _interopRequireDefault(require("./hooks/useRange"));
  27. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  28. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof3(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  29. /**
  30. * New:
  31. * - click mark to update range value
  32. * - handleRender
  33. * - Fix handle with count not correct
  34. * - Fix pushable not work in some case
  35. * - No more FindDOMNode
  36. * - Move all position related style into inline style
  37. * - Key: up is plus, down is minus
  38. * - fix Key with step = null not align with marks
  39. * - Change range should not trigger onChange
  40. * - keyboard support pushable
  41. */
  42. var Slider = /*#__PURE__*/React.forwardRef(function (props, ref) {
  43. var _props$prefixCls = props.prefixCls,
  44. prefixCls = _props$prefixCls === void 0 ? 'rc-slider' : _props$prefixCls,
  45. className = props.className,
  46. style = props.style,
  47. classNames = props.classNames,
  48. styles = props.styles,
  49. id = props.id,
  50. _props$disabled = props.disabled,
  51. disabled = _props$disabled === void 0 ? false : _props$disabled,
  52. _props$keyboard = props.keyboard,
  53. keyboard = _props$keyboard === void 0 ? true : _props$keyboard,
  54. autoFocus = props.autoFocus,
  55. onFocus = props.onFocus,
  56. onBlur = props.onBlur,
  57. _props$min = props.min,
  58. min = _props$min === void 0 ? 0 : _props$min,
  59. _props$max = props.max,
  60. max = _props$max === void 0 ? 100 : _props$max,
  61. _props$step = props.step,
  62. step = _props$step === void 0 ? 1 : _props$step,
  63. value = props.value,
  64. defaultValue = props.defaultValue,
  65. range = props.range,
  66. count = props.count,
  67. onChange = props.onChange,
  68. onBeforeChange = props.onBeforeChange,
  69. onAfterChange = props.onAfterChange,
  70. onChangeComplete = props.onChangeComplete,
  71. _props$allowCross = props.allowCross,
  72. allowCross = _props$allowCross === void 0 ? true : _props$allowCross,
  73. _props$pushable = props.pushable,
  74. pushable = _props$pushable === void 0 ? false : _props$pushable,
  75. reverse = props.reverse,
  76. vertical = props.vertical,
  77. _props$included = props.included,
  78. included = _props$included === void 0 ? true : _props$included,
  79. startPoint = props.startPoint,
  80. trackStyle = props.trackStyle,
  81. handleStyle = props.handleStyle,
  82. railStyle = props.railStyle,
  83. dotStyle = props.dotStyle,
  84. activeDotStyle = props.activeDotStyle,
  85. marks = props.marks,
  86. dots = props.dots,
  87. handleRender = props.handleRender,
  88. activeHandleRender = props.activeHandleRender,
  89. track = props.track,
  90. _props$tabIndex = props.tabIndex,
  91. tabIndex = _props$tabIndex === void 0 ? 0 : _props$tabIndex,
  92. ariaLabelForHandle = props.ariaLabelForHandle,
  93. ariaLabelledByForHandle = props.ariaLabelledByForHandle,
  94. ariaRequired = props.ariaRequired,
  95. ariaValueTextFormatterForHandle = props.ariaValueTextFormatterForHandle;
  96. var handlesRef = React.useRef(null);
  97. var containerRef = React.useRef(null);
  98. var direction = React.useMemo(function () {
  99. if (vertical) {
  100. return reverse ? 'ttb' : 'btt';
  101. }
  102. return reverse ? 'rtl' : 'ltr';
  103. }, [reverse, vertical]);
  104. // ============================ Range =============================
  105. var _useRange = (0, _useRange3.default)(range),
  106. _useRange2 = (0, _slicedToArray2.default)(_useRange, 5),
  107. rangeEnabled = _useRange2[0],
  108. rangeEditable = _useRange2[1],
  109. rangeDraggableTrack = _useRange2[2],
  110. minCount = _useRange2[3],
  111. maxCount = _useRange2[4];
  112. var mergedMin = React.useMemo(function () {
  113. return isFinite(min) ? min : 0;
  114. }, [min]);
  115. var mergedMax = React.useMemo(function () {
  116. return isFinite(max) ? max : 100;
  117. }, [max]);
  118. // ============================= Step =============================
  119. var mergedStep = React.useMemo(function () {
  120. return step !== null && step <= 0 ? 1 : step;
  121. }, [step]);
  122. // ============================= Push =============================
  123. var mergedPush = React.useMemo(function () {
  124. if (typeof pushable === 'boolean') {
  125. return pushable ? mergedStep : false;
  126. }
  127. return pushable >= 0 ? pushable : false;
  128. }, [pushable, mergedStep]);
  129. // ============================ Marks =============================
  130. var markList = React.useMemo(function () {
  131. return Object.keys(marks || {}).map(function (key) {
  132. var mark = marks[key];
  133. var markObj = {
  134. value: Number(key)
  135. };
  136. if (mark && (0, _typeof2.default)(mark) === 'object' && ! /*#__PURE__*/React.isValidElement(mark) && ('label' in mark || 'style' in mark)) {
  137. markObj.style = mark.style;
  138. markObj.label = mark.label;
  139. } else {
  140. markObj.label = mark;
  141. }
  142. return markObj;
  143. }).filter(function (_ref) {
  144. var label = _ref.label;
  145. return label || typeof label === 'number';
  146. }).sort(function (a, b) {
  147. return a.value - b.value;
  148. });
  149. }, [marks]);
  150. // ============================ Format ============================
  151. var _useOffset = (0, _useOffset3.default)(mergedMin, mergedMax, mergedStep, markList, allowCross, mergedPush),
  152. _useOffset2 = (0, _slicedToArray2.default)(_useOffset, 2),
  153. formatValue = _useOffset2[0],
  154. offsetValues = _useOffset2[1];
  155. // ============================ Values ============================
  156. var _useMergedState = (0, _useMergedState3.default)(defaultValue, {
  157. value: value
  158. }),
  159. _useMergedState2 = (0, _slicedToArray2.default)(_useMergedState, 2),
  160. mergedValue = _useMergedState2[0],
  161. setValue = _useMergedState2[1];
  162. var rawValues = React.useMemo(function () {
  163. var valueList = mergedValue === null || mergedValue === undefined ? [] : Array.isArray(mergedValue) ? mergedValue : [mergedValue];
  164. var _valueList = (0, _slicedToArray2.default)(valueList, 1),
  165. _valueList$ = _valueList[0],
  166. val0 = _valueList$ === void 0 ? mergedMin : _valueList$;
  167. var returnValues = mergedValue === null ? [] : [val0];
  168. // Format as range
  169. if (rangeEnabled) {
  170. returnValues = (0, _toConsumableArray2.default)(valueList);
  171. // When count provided or value is `undefined`, we fill values
  172. if (count || mergedValue === undefined) {
  173. var pointCount = count >= 0 ? count + 1 : 2;
  174. returnValues = returnValues.slice(0, pointCount);
  175. // Fill with count
  176. while (returnValues.length < pointCount) {
  177. var _returnValues;
  178. returnValues.push((_returnValues = returnValues[returnValues.length - 1]) !== null && _returnValues !== void 0 ? _returnValues : mergedMin);
  179. }
  180. }
  181. returnValues.sort(function (a, b) {
  182. return a - b;
  183. });
  184. }
  185. // Align in range
  186. returnValues.forEach(function (val, index) {
  187. returnValues[index] = formatValue(val);
  188. });
  189. return returnValues;
  190. }, [mergedValue, rangeEnabled, mergedMin, count, formatValue]);
  191. // =========================== onChange ===========================
  192. var getTriggerValue = function getTriggerValue(triggerValues) {
  193. return rangeEnabled ? triggerValues : triggerValues[0];
  194. };
  195. var triggerChange = (0, _useEvent.default)(function (nextValues) {
  196. // Order first
  197. var cloneNextValues = (0, _toConsumableArray2.default)(nextValues).sort(function (a, b) {
  198. return a - b;
  199. });
  200. // Trigger event if needed
  201. if (onChange && !(0, _isEqual.default)(cloneNextValues, rawValues, true)) {
  202. onChange(getTriggerValue(cloneNextValues));
  203. }
  204. // We set this later since it will re-render component immediately
  205. setValue(cloneNextValues);
  206. });
  207. var finishChange = (0, _useEvent.default)(function (draggingDelete) {
  208. // Trigger from `useDrag` will tell if it's a delete action
  209. if (draggingDelete) {
  210. handlesRef.current.hideHelp();
  211. }
  212. var finishValue = getTriggerValue(rawValues);
  213. onAfterChange === null || onAfterChange === void 0 || onAfterChange(finishValue);
  214. (0, _warning.default)(!onAfterChange, '[rc-slider] `onAfterChange` is deprecated. Please use `onChangeComplete` instead.');
  215. onChangeComplete === null || onChangeComplete === void 0 || onChangeComplete(finishValue);
  216. });
  217. var onDelete = function onDelete(index) {
  218. if (disabled || !rangeEditable || rawValues.length <= minCount) {
  219. return;
  220. }
  221. var cloneNextValues = (0, _toConsumableArray2.default)(rawValues);
  222. cloneNextValues.splice(index, 1);
  223. onBeforeChange === null || onBeforeChange === void 0 || onBeforeChange(getTriggerValue(cloneNextValues));
  224. triggerChange(cloneNextValues);
  225. var nextFocusIndex = Math.max(0, index - 1);
  226. handlesRef.current.hideHelp();
  227. handlesRef.current.focus(nextFocusIndex);
  228. };
  229. var _useDrag = (0, _useDrag3.default)(containerRef, direction, rawValues, mergedMin, mergedMax, formatValue, triggerChange, finishChange, offsetValues, rangeEditable, minCount),
  230. _useDrag2 = (0, _slicedToArray2.default)(_useDrag, 5),
  231. draggingIndex = _useDrag2[0],
  232. draggingValue = _useDrag2[1],
  233. draggingDelete = _useDrag2[2],
  234. cacheValues = _useDrag2[3],
  235. onStartDrag = _useDrag2[4];
  236. /**
  237. * When `rangeEditable` will insert a new value in the values array.
  238. * Else it will replace the value in the values array.
  239. */
  240. var changeToCloseValue = function changeToCloseValue(newValue, e) {
  241. if (!disabled) {
  242. // Create new values
  243. var cloneNextValues = (0, _toConsumableArray2.default)(rawValues);
  244. var valueIndex = 0;
  245. var valueBeforeIndex = 0; // Record the index which value < newValue
  246. var valueDist = mergedMax - mergedMin;
  247. rawValues.forEach(function (val, index) {
  248. var dist = Math.abs(newValue - val);
  249. if (dist <= valueDist) {
  250. valueDist = dist;
  251. valueIndex = index;
  252. }
  253. if (val < newValue) {
  254. valueBeforeIndex = index;
  255. }
  256. });
  257. var focusIndex = valueIndex;
  258. if (rangeEditable && valueDist !== 0 && (!maxCount || rawValues.length < maxCount)) {
  259. cloneNextValues.splice(valueBeforeIndex + 1, 0, newValue);
  260. focusIndex = valueBeforeIndex + 1;
  261. } else {
  262. cloneNextValues[valueIndex] = newValue;
  263. }
  264. // Fill value to match default 2 (only when `rawValues` is empty)
  265. if (rangeEnabled && !rawValues.length && count === undefined) {
  266. cloneNextValues.push(newValue);
  267. }
  268. var nextValue = getTriggerValue(cloneNextValues);
  269. onBeforeChange === null || onBeforeChange === void 0 || onBeforeChange(nextValue);
  270. triggerChange(cloneNextValues);
  271. if (e) {
  272. var _document$activeEleme, _document$activeEleme2;
  273. (_document$activeEleme = document.activeElement) === null || _document$activeEleme === void 0 || (_document$activeEleme2 = _document$activeEleme.blur) === null || _document$activeEleme2 === void 0 || _document$activeEleme2.call(_document$activeEleme);
  274. handlesRef.current.focus(focusIndex);
  275. onStartDrag(e, focusIndex, cloneNextValues);
  276. } else {
  277. // https://github.com/ant-design/ant-design/issues/49997
  278. onAfterChange === null || onAfterChange === void 0 || onAfterChange(nextValue);
  279. (0, _warning.default)(!onAfterChange, '[rc-slider] `onAfterChange` is deprecated. Please use `onChangeComplete` instead.');
  280. onChangeComplete === null || onChangeComplete === void 0 || onChangeComplete(nextValue);
  281. }
  282. }
  283. };
  284. // ============================ Click =============================
  285. var onSliderMouseDown = function onSliderMouseDown(e) {
  286. e.preventDefault();
  287. var _containerRef$current = containerRef.current.getBoundingClientRect(),
  288. width = _containerRef$current.width,
  289. height = _containerRef$current.height,
  290. left = _containerRef$current.left,
  291. top = _containerRef$current.top,
  292. bottom = _containerRef$current.bottom,
  293. right = _containerRef$current.right;
  294. var clientX = e.clientX,
  295. clientY = e.clientY;
  296. var percent;
  297. switch (direction) {
  298. case 'btt':
  299. percent = (bottom - clientY) / height;
  300. break;
  301. case 'ttb':
  302. percent = (clientY - top) / height;
  303. break;
  304. case 'rtl':
  305. percent = (right - clientX) / width;
  306. break;
  307. default:
  308. percent = (clientX - left) / width;
  309. }
  310. var nextValue = mergedMin + percent * (mergedMax - mergedMin);
  311. changeToCloseValue(formatValue(nextValue), e);
  312. };
  313. // =========================== Keyboard ===========================
  314. var _React$useState = React.useState(null),
  315. _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
  316. keyboardValue = _React$useState2[0],
  317. setKeyboardValue = _React$useState2[1];
  318. var onHandleOffsetChange = function onHandleOffsetChange(offset, valueIndex) {
  319. if (!disabled) {
  320. var next = offsetValues(rawValues, offset, valueIndex);
  321. onBeforeChange === null || onBeforeChange === void 0 || onBeforeChange(getTriggerValue(rawValues));
  322. triggerChange(next.values);
  323. setKeyboardValue(next.value);
  324. }
  325. };
  326. React.useEffect(function () {
  327. if (keyboardValue !== null) {
  328. var valueIndex = rawValues.indexOf(keyboardValue);
  329. if (valueIndex >= 0) {
  330. handlesRef.current.focus(valueIndex);
  331. }
  332. }
  333. setKeyboardValue(null);
  334. }, [keyboardValue]);
  335. // ============================= Drag =============================
  336. var mergedDraggableTrack = React.useMemo(function () {
  337. if (rangeDraggableTrack && mergedStep === null) {
  338. if (process.env.NODE_ENV !== 'production') {
  339. (0, _warning.default)(false, '`draggableTrack` is not supported when `step` is `null`.');
  340. }
  341. return false;
  342. }
  343. return rangeDraggableTrack;
  344. }, [rangeDraggableTrack, mergedStep]);
  345. var onStartMove = (0, _useEvent.default)(function (e, valueIndex) {
  346. onStartDrag(e, valueIndex);
  347. onBeforeChange === null || onBeforeChange === void 0 || onBeforeChange(getTriggerValue(rawValues));
  348. });
  349. // Auto focus for updated handle
  350. var dragging = draggingIndex !== -1;
  351. React.useEffect(function () {
  352. if (!dragging) {
  353. var valueIndex = rawValues.lastIndexOf(draggingValue);
  354. handlesRef.current.focus(valueIndex);
  355. }
  356. }, [dragging]);
  357. // =========================== Included ===========================
  358. var sortedCacheValues = React.useMemo(function () {
  359. return (0, _toConsumableArray2.default)(cacheValues).sort(function (a, b) {
  360. return a - b;
  361. });
  362. }, [cacheValues]);
  363. // Provide a range values with included [min, max]
  364. // Used for Track, Mark & Dot
  365. var _React$useMemo = React.useMemo(function () {
  366. if (!rangeEnabled) {
  367. return [mergedMin, sortedCacheValues[0]];
  368. }
  369. return [sortedCacheValues[0], sortedCacheValues[sortedCacheValues.length - 1]];
  370. }, [sortedCacheValues, rangeEnabled, mergedMin]),
  371. _React$useMemo2 = (0, _slicedToArray2.default)(_React$useMemo, 2),
  372. includedStart = _React$useMemo2[0],
  373. includedEnd = _React$useMemo2[1];
  374. // ============================= Refs =============================
  375. React.useImperativeHandle(ref, function () {
  376. return {
  377. focus: function focus() {
  378. handlesRef.current.focus(0);
  379. },
  380. blur: function blur() {
  381. var _containerRef$current2;
  382. var _document = document,
  383. activeElement = _document.activeElement;
  384. if ((_containerRef$current2 = containerRef.current) !== null && _containerRef$current2 !== void 0 && _containerRef$current2.contains(activeElement)) {
  385. activeElement === null || activeElement === void 0 || activeElement.blur();
  386. }
  387. }
  388. };
  389. });
  390. // ========================== Auto Focus ==========================
  391. React.useEffect(function () {
  392. if (autoFocus) {
  393. handlesRef.current.focus(0);
  394. }
  395. }, []);
  396. // =========================== Context ============================
  397. var context = React.useMemo(function () {
  398. return {
  399. min: mergedMin,
  400. max: mergedMax,
  401. direction: direction,
  402. disabled: disabled,
  403. keyboard: keyboard,
  404. step: mergedStep,
  405. included: included,
  406. includedStart: includedStart,
  407. includedEnd: includedEnd,
  408. range: rangeEnabled,
  409. tabIndex: tabIndex,
  410. ariaLabelForHandle: ariaLabelForHandle,
  411. ariaLabelledByForHandle: ariaLabelledByForHandle,
  412. ariaRequired: ariaRequired,
  413. ariaValueTextFormatterForHandle: ariaValueTextFormatterForHandle,
  414. styles: styles || {},
  415. classNames: classNames || {}
  416. };
  417. }, [mergedMin, mergedMax, direction, disabled, keyboard, mergedStep, included, includedStart, includedEnd, rangeEnabled, tabIndex, ariaLabelForHandle, ariaLabelledByForHandle, ariaRequired, ariaValueTextFormatterForHandle, styles, classNames]);
  418. // ============================ Render ============================
  419. return /*#__PURE__*/React.createElement(_context.default.Provider, {
  420. value: context
  421. }, /*#__PURE__*/React.createElement("div", {
  422. ref: containerRef,
  423. className: (0, _classnames.default)(prefixCls, className, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "".concat(prefixCls, "-disabled"), disabled), "".concat(prefixCls, "-vertical"), vertical), "".concat(prefixCls, "-horizontal"), !vertical), "".concat(prefixCls, "-with-marks"), markList.length)),
  424. style: style,
  425. onMouseDown: onSliderMouseDown,
  426. id: id
  427. }, /*#__PURE__*/React.createElement("div", {
  428. className: (0, _classnames.default)("".concat(prefixCls, "-rail"), classNames === null || classNames === void 0 ? void 0 : classNames.rail),
  429. style: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, railStyle), styles === null || styles === void 0 ? void 0 : styles.rail)
  430. }), track !== false && /*#__PURE__*/React.createElement(_Tracks.default, {
  431. prefixCls: prefixCls,
  432. style: trackStyle,
  433. values: rawValues,
  434. startPoint: startPoint,
  435. onStartMove: mergedDraggableTrack ? onStartMove : undefined
  436. }), /*#__PURE__*/React.createElement(_Steps.default, {
  437. prefixCls: prefixCls,
  438. marks: markList,
  439. dots: dots,
  440. style: dotStyle,
  441. activeStyle: activeDotStyle
  442. }), /*#__PURE__*/React.createElement(_Handles.default, {
  443. ref: handlesRef,
  444. prefixCls: prefixCls,
  445. style: handleStyle,
  446. values: cacheValues,
  447. draggingIndex: draggingIndex,
  448. draggingDelete: draggingDelete,
  449. onStartMove: onStartMove,
  450. onOffsetChange: onHandleOffsetChange,
  451. onFocus: onFocus,
  452. onBlur: onBlur,
  453. handleRender: handleRender,
  454. activeHandleRender: activeHandleRender,
  455. onChangeComplete: finishChange,
  456. onDelete: rangeEditable ? onDelete : undefined
  457. }), /*#__PURE__*/React.createElement(_Marks.default, {
  458. prefixCls: prefixCls,
  459. marks: markList,
  460. onClick: changeToCloseValue
  461. })));
  462. });
  463. if (process.env.NODE_ENV !== 'production') {
  464. Slider.displayName = 'Slider';
  465. }
  466. var _default = exports.default = Slider;