UNPKG

15.3 kBJavaScriptView Raw
1import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
3import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4import _typeof from "@babel/runtime/helpers/esm/typeof";
5import * as React from 'react';
6import classNames from 'classnames';
7import isEqual from "rc-util/es/isEqual";
8import useMergedState from "rc-util/es/hooks/useMergedState";
9import Handles from './Handles';
10import useDrag from './hooks/useDrag';
11import SliderContext from './context';
12import Tracks from './Tracks';
13import Marks from './Marks';
14import Steps from './Steps';
15import useOffset from './hooks/useOffset';
16import warning from "rc-util/es/warning";
17var Slider = /*#__PURE__*/React.forwardRef(function (props, ref) {
18 var _classNames;
19 var _props$prefixCls = props.prefixCls,
20 prefixCls = _props$prefixCls === void 0 ? 'rc-slider' : _props$prefixCls,
21 className = props.className,
22 style = props.style,
23 _props$disabled = props.disabled,
24 disabled = _props$disabled === void 0 ? false : _props$disabled,
25 _props$keyboard = props.keyboard,
26 keyboard = _props$keyboard === void 0 ? true : _props$keyboard,
27 autoFocus = props.autoFocus,
28 onFocus = props.onFocus,
29 onBlur = props.onBlur,
30 _props$min = props.min,
31 min = _props$min === void 0 ? 0 : _props$min,
32 _props$max = props.max,
33 max = _props$max === void 0 ? 100 : _props$max,
34 _props$step = props.step,
35 step = _props$step === void 0 ? 1 : _props$step,
36 value = props.value,
37 defaultValue = props.defaultValue,
38 range = props.range,
39 count = props.count,
40 onChange = props.onChange,
41 onBeforeChange = props.onBeforeChange,
42 onAfterChange = props.onAfterChange,
43 _props$allowCross = props.allowCross,
44 allowCross = _props$allowCross === void 0 ? true : _props$allowCross,
45 _props$pushable = props.pushable,
46 pushable = _props$pushable === void 0 ? false : _props$pushable,
47 draggableTrack = props.draggableTrack,
48 reverse = props.reverse,
49 vertical = props.vertical,
50 _props$included = props.included,
51 included = _props$included === void 0 ? true : _props$included,
52 startPoint = props.startPoint,
53 trackStyle = props.trackStyle,
54 handleStyle = props.handleStyle,
55 railStyle = props.railStyle,
56 dotStyle = props.dotStyle,
57 activeDotStyle = props.activeDotStyle,
58 marks = props.marks,
59 dots = props.dots,
60 handleRender = props.handleRender,
61 _props$tabIndex = props.tabIndex,
62 tabIndex = _props$tabIndex === void 0 ? 0 : _props$tabIndex,
63 ariaLabelForHandle = props.ariaLabelForHandle,
64 ariaLabelledByForHandle = props.ariaLabelledByForHandle,
65 ariaValueTextFormatterForHandle = props.ariaValueTextFormatterForHandle;
66 var handlesRef = React.useRef();
67 var containerRef = React.useRef();
68 var direction = React.useMemo(function () {
69 if (vertical) {
70 return reverse ? 'ttb' : 'btt';
71 }
72 return reverse ? 'rtl' : 'ltr';
73 }, [reverse, vertical]);
74 // ============================ Range =============================
75 var mergedMin = React.useMemo(function () {
76 return isFinite(min) ? min : 0;
77 }, [min]);
78 var mergedMax = React.useMemo(function () {
79 return isFinite(max) ? max : 100;
80 }, [max]);
81 // ============================= Step =============================
82 var mergedStep = React.useMemo(function () {
83 return step !== null && step <= 0 ? 1 : step;
84 }, [step]);
85 // ============================= Push =============================
86 var mergedPush = React.useMemo(function () {
87 if (typeof pushable === 'boolean') {
88 return pushable ? mergedStep : false;
89 }
90 return pushable >= 0 ? pushable : false;
91 }, [pushable, mergedStep]);
92 // ============================ Marks =============================
93 var markList = React.useMemo(function () {
94 var keys = Object.keys(marks || {});
95 return keys.map(function (key) {
96 var mark = marks[key];
97 var markObj = {
98 value: Number(key)
99 };
100 if (mark && _typeof(mark) === 'object' && ! /*#__PURE__*/React.isValidElement(mark) && ('label' in mark || 'style' in mark)) {
101 markObj.style = mark.style;
102 markObj.label = mark.label;
103 } else {
104 markObj.label = mark;
105 }
106 return markObj;
107 }).filter(function (_ref) {
108 var label = _ref.label;
109 return label || typeof label === 'number';
110 }).sort(function (a, b) {
111 return a.value - b.value;
112 });
113 }, [marks]);
114 // ============================ Format ============================
115 var _useOffset = useOffset(mergedMin, mergedMax, mergedStep, markList, allowCross, mergedPush),
116 _useOffset2 = _slicedToArray(_useOffset, 2),
117 formatValue = _useOffset2[0],
118 offsetValues = _useOffset2[1];
119 // ============================ Values ============================
120 var _useMergedState = useMergedState(defaultValue, {
121 value: value
122 }),
123 _useMergedState2 = _slicedToArray(_useMergedState, 2),
124 mergedValue = _useMergedState2[0],
125 setValue = _useMergedState2[1];
126 var rawValues = React.useMemo(function () {
127 var valueList = mergedValue === null || mergedValue === undefined ? [] : Array.isArray(mergedValue) ? mergedValue : [mergedValue];
128 var _valueList = _slicedToArray(valueList, 1),
129 _valueList$ = _valueList[0],
130 val0 = _valueList$ === void 0 ? mergedMin : _valueList$;
131 var returnValues = mergedValue === null ? [] : [val0];
132 // Format as range
133 if (range) {
134 returnValues = _toConsumableArray(valueList);
135 // When count provided or value is `undefined`, we fill values
136 if (count || mergedValue === undefined) {
137 var pointCount = count >= 0 ? count + 1 : 2;
138 returnValues = returnValues.slice(0, pointCount);
139 // Fill with count
140 while (returnValues.length < pointCount) {
141 var _returnValues;
142 returnValues.push((_returnValues = returnValues[returnValues.length - 1]) !== null && _returnValues !== void 0 ? _returnValues : mergedMin);
143 }
144 }
145 returnValues.sort(function (a, b) {
146 return a - b;
147 });
148 }
149 // Align in range
150 returnValues.forEach(function (val, index) {
151 returnValues[index] = formatValue(val);
152 });
153 return returnValues;
154 }, [mergedValue, range, mergedMin, count, formatValue]);
155 // =========================== onChange ===========================
156 var rawValuesRef = React.useRef(rawValues);
157 rawValuesRef.current = rawValues;
158 var getTriggerValue = function getTriggerValue(triggerValues) {
159 return range ? triggerValues : triggerValues[0];
160 };
161 var triggerChange = function triggerChange(nextValues) {
162 // Order first
163 var cloneNextValues = _toConsumableArray(nextValues).sort(function (a, b) {
164 return a - b;
165 });
166 // Trigger event if needed
167 if (onChange && !isEqual(cloneNextValues, rawValuesRef.current, true)) {
168 onChange(getTriggerValue(cloneNextValues));
169 }
170 // We set this later since it will re-render component immediately
171 setValue(cloneNextValues);
172 };
173 var changeToCloseValue = function changeToCloseValue(newValue) {
174 if (!disabled) {
175 var valueIndex = 0;
176 var valueDist = mergedMax - mergedMin;
177 rawValues.forEach(function (val, index) {
178 var dist = Math.abs(newValue - val);
179 if (dist <= valueDist) {
180 valueDist = dist;
181 valueIndex = index;
182 }
183 });
184 // Create new values
185 var cloneNextValues = _toConsumableArray(rawValues);
186 cloneNextValues[valueIndex] = newValue;
187 // Fill value to match default 2
188 if (range && !rawValues.length && count === undefined) {
189 cloneNextValues.push(newValue);
190 }
191 onBeforeChange === null || onBeforeChange === void 0 ? void 0 : onBeforeChange(getTriggerValue(cloneNextValues));
192 triggerChange(cloneNextValues);
193 onAfterChange === null || onAfterChange === void 0 ? void 0 : onAfterChange(getTriggerValue(cloneNextValues));
194 }
195 };
196 // ============================ Click =============================
197 var onSliderMouseDown = function onSliderMouseDown(e) {
198 e.preventDefault();
199 var _containerRef$current = containerRef.current.getBoundingClientRect(),
200 width = _containerRef$current.width,
201 height = _containerRef$current.height,
202 left = _containerRef$current.left,
203 top = _containerRef$current.top,
204 bottom = _containerRef$current.bottom,
205 right = _containerRef$current.right;
206 var clientX = e.clientX,
207 clientY = e.clientY;
208 var percent;
209 switch (direction) {
210 case 'btt':
211 percent = (bottom - clientY) / height;
212 break;
213 case 'ttb':
214 percent = (clientY - top) / height;
215 break;
216 case 'rtl':
217 percent = (right - clientX) / width;
218 break;
219 default:
220 percent = (clientX - left) / width;
221 }
222 var nextValue = mergedMin + percent * (mergedMax - mergedMin);
223 changeToCloseValue(formatValue(nextValue));
224 };
225 // =========================== Keyboard ===========================
226 var _React$useState = React.useState(null),
227 _React$useState2 = _slicedToArray(_React$useState, 2),
228 keyboardValue = _React$useState2[0],
229 setKeyboardValue = _React$useState2[1];
230 var onHandleOffsetChange = function onHandleOffsetChange(offset, valueIndex) {
231 if (!disabled) {
232 var next = offsetValues(rawValues, offset, valueIndex);
233 onBeforeChange === null || onBeforeChange === void 0 ? void 0 : onBeforeChange(getTriggerValue(rawValues));
234 triggerChange(next.values);
235 onAfterChange === null || onAfterChange === void 0 ? void 0 : onAfterChange(getTriggerValue(next.values));
236 setKeyboardValue(next.value);
237 }
238 };
239 React.useEffect(function () {
240 if (keyboardValue !== null) {
241 var valueIndex = rawValues.indexOf(keyboardValue);
242 if (valueIndex >= 0) {
243 handlesRef.current.focus(valueIndex);
244 }
245 }
246 setKeyboardValue(null);
247 }, [keyboardValue]);
248 // ============================= Drag =============================
249 var mergedDraggableTrack = React.useMemo(function () {
250 if (draggableTrack && mergedStep === null) {
251 if (process.env.NODE_ENV !== 'production') {
252 warning(false, '`draggableTrack` is not supported when `step` is `null`.');
253 }
254 return false;
255 }
256 return draggableTrack;
257 }, [draggableTrack, mergedStep]);
258 var finishChange = function finishChange() {
259 onAfterChange === null || onAfterChange === void 0 ? void 0 : onAfterChange(getTriggerValue(rawValuesRef.current));
260 };
261 var _useDrag = useDrag(containerRef, direction, rawValues, mergedMin, mergedMax, formatValue, triggerChange, finishChange, offsetValues),
262 _useDrag2 = _slicedToArray(_useDrag, 4),
263 draggingIndex = _useDrag2[0],
264 draggingValue = _useDrag2[1],
265 cacheValues = _useDrag2[2],
266 onStartDrag = _useDrag2[3];
267 var onStartMove = function onStartMove(e, valueIndex) {
268 onStartDrag(e, valueIndex);
269 onBeforeChange === null || onBeforeChange === void 0 ? void 0 : onBeforeChange(getTriggerValue(rawValuesRef.current));
270 };
271 // Auto focus for updated handle
272 var dragging = draggingIndex !== -1;
273 React.useEffect(function () {
274 if (!dragging) {
275 var valueIndex = rawValues.lastIndexOf(draggingValue);
276 handlesRef.current.focus(valueIndex);
277 }
278 }, [dragging]);
279 // =========================== Included ===========================
280 var sortedCacheValues = React.useMemo(function () {
281 return _toConsumableArray(cacheValues).sort(function (a, b) {
282 return a - b;
283 });
284 }, [cacheValues]);
285 // Provide a range values with included [min, max]
286 // Used for Track, Mark & Dot
287 var _React$useMemo = React.useMemo(function () {
288 if (!range) {
289 return [mergedMin, sortedCacheValues[0]];
290 }
291 return [sortedCacheValues[0], sortedCacheValues[sortedCacheValues.length - 1]];
292 }, [sortedCacheValues, range, mergedMin]),
293 _React$useMemo2 = _slicedToArray(_React$useMemo, 2),
294 includedStart = _React$useMemo2[0],
295 includedEnd = _React$useMemo2[1];
296 // ============================= Refs =============================
297 React.useImperativeHandle(ref, function () {
298 return {
299 focus: function focus() {
300 handlesRef.current.focus(0);
301 },
302 blur: function blur() {
303 var _document = document,
304 activeElement = _document.activeElement;
305 if (containerRef.current.contains(activeElement)) {
306 activeElement === null || activeElement === void 0 ? void 0 : activeElement.blur();
307 }
308 }
309 };
310 });
311 // ========================== Auto Focus ==========================
312 React.useEffect(function () {
313 if (autoFocus) {
314 handlesRef.current.focus(0);
315 }
316 }, []);
317 // =========================== Context ============================
318 var context = React.useMemo(function () {
319 return {
320 min: mergedMin,
321 max: mergedMax,
322 direction: direction,
323 disabled: disabled,
324 keyboard: keyboard,
325 step: mergedStep,
326 included: included,
327 includedStart: includedStart,
328 includedEnd: includedEnd,
329 range: range,
330 tabIndex: tabIndex,
331 ariaLabelForHandle: ariaLabelForHandle,
332 ariaLabelledByForHandle: ariaLabelledByForHandle,
333 ariaValueTextFormatterForHandle: ariaValueTextFormatterForHandle
334 };
335 }, [mergedMin, mergedMax, direction, disabled, keyboard, mergedStep, included, includedStart, includedEnd, range, tabIndex, ariaLabelForHandle, ariaLabelledByForHandle, ariaValueTextFormatterForHandle]);
336 // ============================ Render ============================
337 return /*#__PURE__*/React.createElement(SliderContext.Provider, {
338 value: context
339 }, /*#__PURE__*/React.createElement("div", {
340 ref: containerRef,
341 className: classNames(prefixCls, className, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-disabled"), disabled), _defineProperty(_classNames, "".concat(prefixCls, "-vertical"), vertical), _defineProperty(_classNames, "".concat(prefixCls, "-horizontal"), !vertical), _defineProperty(_classNames, "".concat(prefixCls, "-with-marks"), markList.length), _classNames)),
342 style: style,
343 onMouseDown: onSliderMouseDown
344 }, /*#__PURE__*/React.createElement("div", {
345 className: "".concat(prefixCls, "-rail"),
346 style: railStyle
347 }), /*#__PURE__*/React.createElement(Tracks, {
348 prefixCls: prefixCls,
349 style: trackStyle,
350 values: sortedCacheValues,
351 startPoint: startPoint,
352 onStartMove: mergedDraggableTrack ? onStartMove : null
353 }), /*#__PURE__*/React.createElement(Steps, {
354 prefixCls: prefixCls,
355 marks: markList,
356 dots: dots,
357 style: dotStyle,
358 activeStyle: activeDotStyle
359 }), /*#__PURE__*/React.createElement(Handles, {
360 ref: handlesRef,
361 prefixCls: prefixCls,
362 style: handleStyle,
363 values: cacheValues,
364 draggingIndex: draggingIndex,
365 onStartMove: onStartMove,
366 onOffsetChange: onHandleOffsetChange,
367 onFocus: onFocus,
368 onBlur: onBlur,
369 handleRender: handleRender
370 }), /*#__PURE__*/React.createElement(Marks, {
371 prefixCls: prefixCls,
372 marks: markList,
373 onClick: changeToCloseValue
374 })));
375});
376if (process.env.NODE_ENV !== 'production') {
377 Slider.displayName = 'Slider';
378}
379export default Slider;
\No newline at end of file