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