UNPKG

28.2 kBJavaScriptView Raw
1import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2import _extends from "@babel/runtime/helpers/esm/extends";
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import clsx from 'clsx';
6import { chainPropTypes } from '@material-ui/utils';
7import withStyles from '../styles/withStyles';
8import useTheme from '../styles/useTheme';
9import { alpha, lighten, darken } from '../styles/colorManipulator';
10import useIsFocusVisible from '../utils/useIsFocusVisible';
11import ownerDocument from '../utils/ownerDocument';
12import useEventCallback from '../utils/useEventCallback';
13import useForkRef from '../utils/useForkRef';
14import capitalize from '../utils/capitalize';
15import useControlled from '../utils/useControlled';
16import ValueLabel from './ValueLabel';
17
18function asc(a, b) {
19 return a - b;
20}
21
22function clamp(value, min, max) {
23 return Math.min(Math.max(min, value), max);
24}
25
26function findClosest(values, currentValue) {
27 const {
28 index: closestIndex
29 } = values.reduce((acc, value, index) => {
30 const distance = Math.abs(currentValue - value);
31
32 if (acc === null || distance < acc.distance || distance === acc.distance) {
33 return {
34 distance,
35 index
36 };
37 }
38
39 return acc;
40 }, null);
41 return closestIndex;
42}
43
44function trackFinger(event, touchId) {
45 if (touchId.current !== undefined && event.changedTouches) {
46 for (let i = 0; i < event.changedTouches.length; i += 1) {
47 const touch = event.changedTouches[i];
48
49 if (touch.identifier === touchId.current) {
50 return {
51 x: touch.clientX,
52 y: touch.clientY
53 };
54 }
55 }
56
57 return false;
58 }
59
60 return {
61 x: event.clientX,
62 y: event.clientY
63 };
64}
65
66function valueToPercent(value, min, max) {
67 return (value - min) * 100 / (max - min);
68}
69
70function percentToValue(percent, min, max) {
71 return (max - min) * percent + min;
72}
73
74function getDecimalPrecision(num) {
75 // This handles the case when num is very small (0.00000001), js will turn this into 1e-8.
76 // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.
77 if (Math.abs(num) < 1) {
78 const parts = num.toExponential().split('e-');
79 const matissaDecimalPart = parts[0].split('.')[1];
80 return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10);
81 }
82
83 const decimalPart = num.toString().split('.')[1];
84 return decimalPart ? decimalPart.length : 0;
85}
86
87function roundValueToStep(value, step, min) {
88 const nearest = Math.round((value - min) / step) * step + min;
89 return Number(nearest.toFixed(getDecimalPrecision(step)));
90}
91
92function setValueIndex({
93 values,
94 source,
95 newValue,
96 index
97}) {
98 // Performance shortcut
99 if (values[index] === newValue) {
100 return source;
101 }
102
103 const output = values.slice();
104 output[index] = newValue;
105 return output;
106}
107
108function focusThumb({
109 sliderRef,
110 activeIndex,
111 setActive
112}) {
113 if (!sliderRef.current.contains(document.activeElement) || Number(document.activeElement.getAttribute('data-index')) !== activeIndex) {
114 sliderRef.current.querySelector(`[role="slider"][data-index="${activeIndex}"]`).focus();
115 }
116
117 if (setActive) {
118 setActive(activeIndex);
119 }
120}
121
122const axisProps = {
123 horizontal: {
124 offset: percent => ({
125 left: `${percent}%`
126 }),
127 leap: percent => ({
128 width: `${percent}%`
129 })
130 },
131 'horizontal-reverse': {
132 offset: percent => ({
133 right: `${percent}%`
134 }),
135 leap: percent => ({
136 width: `${percent}%`
137 })
138 },
139 vertical: {
140 offset: percent => ({
141 bottom: `${percent}%`
142 }),
143 leap: percent => ({
144 height: `${percent}%`
145 })
146 }
147};
148
149const Identity = x => x;
150
151export const styles = theme => ({
152 /* Styles applied to the root element. */
153 root: {
154 height: 2,
155 width: '100%',
156 boxSizing: 'content-box',
157 padding: '13px 0',
158 display: 'inline-block',
159 position: 'relative',
160 cursor: 'pointer',
161 touchAction: 'none',
162 color: theme.palette.primary.main,
163 WebkitTapHighlightColor: 'transparent',
164 '&$disabled': {
165 pointerEvents: 'none',
166 cursor: 'default',
167 color: theme.palette.grey[400]
168 },
169 '&$vertical': {
170 width: 2,
171 height: '100%',
172 padding: '0 13px'
173 },
174 // The primary input mechanism of the device includes a pointing device of limited accuracy.
175 '@media (pointer: coarse)': {
176 // Reach 42px touch target, about ~8mm on screen.
177 padding: '20px 0',
178 '&$vertical': {
179 padding: '0 20px'
180 }
181 },
182 '@media print': {
183 colorAdjust: 'exact'
184 }
185 },
186
187 /* Styles applied to the root element if `color="primary"`. */
188 colorPrimary: {// TODO v5: move the style here
189 },
190
191 /* Styles applied to the root element if `color="secondary"`. */
192 colorSecondary: {
193 color: theme.palette.secondary.main
194 },
195
196 /* Styles applied to the root element if `marks` is provided with at least one label. */
197 marked: {
198 marginBottom: 20,
199 '&$vertical': {
200 marginBottom: 'auto',
201 marginRight: 20
202 }
203 },
204
205 /* Pseudo-class applied to the root element if `orientation="vertical"`. */
206 vertical: {},
207
208 /* Pseudo-class applied to the root and thumb element if `disabled={true}`. */
209 disabled: {},
210
211 /* Styles applied to the rail element. */
212 rail: {
213 display: 'block',
214 position: 'absolute',
215 width: '100%',
216 height: 2,
217 borderRadius: 1,
218 backgroundColor: 'currentColor',
219 opacity: 0.38,
220 '$vertical &': {
221 height: '100%',
222 width: 2
223 }
224 },
225
226 /* Styles applied to the track element. */
227 track: {
228 display: 'block',
229 position: 'absolute',
230 height: 2,
231 borderRadius: 1,
232 backgroundColor: 'currentColor',
233 '$vertical &': {
234 width: 2
235 }
236 },
237
238 /* Styles applied to the track element if `track={false}`. */
239 trackFalse: {
240 '& $track': {
241 display: 'none'
242 }
243 },
244
245 /* Styles applied to the track element if `track="inverted"`. */
246 trackInverted: {
247 '& $track': {
248 backgroundColor: // Same logic as the LinearProgress track color
249 theme.palette.type === 'light' ? lighten(theme.palette.primary.main, 0.62) : darken(theme.palette.primary.main, 0.5)
250 },
251 '& $rail': {
252 opacity: 1
253 }
254 },
255
256 /* Styles applied to the thumb element. */
257 thumb: {
258 position: 'absolute',
259 width: 12,
260 height: 12,
261 marginLeft: -6,
262 marginTop: -5,
263 boxSizing: 'border-box',
264 borderRadius: '50%',
265 outline: 0,
266 backgroundColor: 'currentColor',
267 display: 'flex',
268 alignItems: 'center',
269 justifyContent: 'center',
270 transition: theme.transitions.create(['box-shadow'], {
271 duration: theme.transitions.duration.shortest
272 }),
273 '&::after': {
274 position: 'absolute',
275 content: '""',
276 borderRadius: '50%',
277 // reach 42px hit target (2 * 15 + thumb diameter)
278 left: -15,
279 top: -15,
280 right: -15,
281 bottom: -15
282 },
283 '&$focusVisible,&:hover': {
284 boxShadow: `0px 0px 0px 8px ${alpha(theme.palette.primary.main, 0.16)}`,
285 '@media (hover: none)': {
286 boxShadow: 'none'
287 }
288 },
289 '&$active': {
290 boxShadow: `0px 0px 0px 14px ${alpha(theme.palette.primary.main, 0.16)}`
291 },
292 '&$disabled': {
293 width: 8,
294 height: 8,
295 marginLeft: -4,
296 marginTop: -3,
297 '&:hover': {
298 boxShadow: 'none'
299 }
300 },
301 '$vertical &': {
302 marginLeft: -5,
303 marginBottom: -6
304 },
305 '$vertical &$disabled': {
306 marginLeft: -3,
307 marginBottom: -4
308 }
309 },
310
311 /* Styles applied to the thumb element if `color="primary"`. */
312 thumbColorPrimary: {// TODO v5: move the style here
313 },
314
315 /* Styles applied to the thumb element if `color="secondary"`. */
316 thumbColorSecondary: {
317 '&$focusVisible,&:hover': {
318 boxShadow: `0px 0px 0px 8px ${alpha(theme.palette.secondary.main, 0.16)}`
319 },
320 '&$active': {
321 boxShadow: `0px 0px 0px 14px ${alpha(theme.palette.secondary.main, 0.16)}`
322 }
323 },
324
325 /* Pseudo-class applied to the thumb element if it's active. */
326 active: {},
327
328 /* Pseudo-class applied to the thumb element if keyboard focused. */
329 focusVisible: {},
330
331 /* Styles applied to the thumb label element. */
332 valueLabel: {
333 // IE 11 centering bug, to remove from the customization demos once no longer supported
334 left: 'calc(-50% - 4px)'
335 },
336
337 /* Styles applied to the mark element. */
338 mark: {
339 position: 'absolute',
340 width: 2,
341 height: 2,
342 borderRadius: 1,
343 backgroundColor: 'currentColor'
344 },
345
346 /* Styles applied to the mark element if active (depending on the value). */
347 markActive: {
348 backgroundColor: theme.palette.background.paper,
349 opacity: 0.8
350 },
351
352 /* Styles applied to the mark label element. */
353 markLabel: _extends({}, theme.typography.body2, {
354 color: theme.palette.text.secondary,
355 position: 'absolute',
356 top: 26,
357 transform: 'translateX(-50%)',
358 whiteSpace: 'nowrap',
359 '$vertical &': {
360 top: 'auto',
361 left: 26,
362 transform: 'translateY(50%)'
363 },
364 '@media (pointer: coarse)': {
365 top: 40,
366 '$vertical &': {
367 left: 31
368 }
369 }
370 }),
371
372 /* Styles applied to the mark label element if active (depending on the value). */
373 markLabelActive: {
374 color: theme.palette.text.primary
375 }
376});
377const Slider = /*#__PURE__*/React.forwardRef(function Slider(props, ref) {
378 const {
379 'aria-label': ariaLabel,
380 'aria-labelledby': ariaLabelledby,
381 'aria-valuetext': ariaValuetext,
382 classes,
383 className,
384 color = 'primary',
385 component: Component = 'span',
386 defaultValue,
387 disabled = false,
388 getAriaLabel,
389 getAriaValueText,
390 marks: marksProp = false,
391 max = 100,
392 min = 0,
393 name,
394 onChange,
395 onChangeCommitted,
396 onMouseDown,
397 orientation = 'horizontal',
398 scale = Identity,
399 step = 1,
400 ThumbComponent = 'span',
401 track = 'normal',
402 value: valueProp,
403 ValueLabelComponent = ValueLabel,
404 valueLabelDisplay = 'off',
405 valueLabelFormat = Identity
406 } = props,
407 other = _objectWithoutPropertiesLoose(props, ["aria-label", "aria-labelledby", "aria-valuetext", "classes", "className", "color", "component", "defaultValue", "disabled", "getAriaLabel", "getAriaValueText", "marks", "max", "min", "name", "onChange", "onChangeCommitted", "onMouseDown", "orientation", "scale", "step", "ThumbComponent", "track", "value", "ValueLabelComponent", "valueLabelDisplay", "valueLabelFormat"]);
408
409 const theme = useTheme();
410 const touchId = React.useRef(); // We can't use the :active browser pseudo-classes.
411 // - The active state isn't triggered when clicking on the rail.
412 // - The active state isn't transfered when inversing a range slider.
413
414 const [active, setActive] = React.useState(-1);
415 const [open, setOpen] = React.useState(-1);
416 const [valueDerived, setValueState] = useControlled({
417 controlled: valueProp,
418 default: defaultValue,
419 name: 'Slider'
420 });
421 const range = Array.isArray(valueDerived);
422 let values = range ? valueDerived.slice().sort(asc) : [valueDerived];
423 values = values.map(value => clamp(value, min, max));
424 const marks = marksProp === true && step !== null ? [...Array(Math.floor((max - min) / step) + 1)].map((_, index) => ({
425 value: min + step * index
426 })) : marksProp || [];
427 const {
428 isFocusVisible,
429 onBlurVisible,
430 ref: focusVisibleRef
431 } = useIsFocusVisible();
432 const [focusVisible, setFocusVisible] = React.useState(-1);
433 const sliderRef = React.useRef();
434 const handleFocusRef = useForkRef(focusVisibleRef, sliderRef);
435 const handleRef = useForkRef(ref, handleFocusRef);
436 const handleFocus = useEventCallback(event => {
437 const index = Number(event.currentTarget.getAttribute('data-index'));
438
439 if (isFocusVisible(event)) {
440 setFocusVisible(index);
441 }
442
443 setOpen(index);
444 });
445 const handleBlur = useEventCallback(() => {
446 if (focusVisible !== -1) {
447 setFocusVisible(-1);
448 onBlurVisible();
449 }
450
451 setOpen(-1);
452 });
453 const handleMouseOver = useEventCallback(event => {
454 const index = Number(event.currentTarget.getAttribute('data-index'));
455 setOpen(index);
456 });
457 const handleMouseLeave = useEventCallback(() => {
458 setOpen(-1);
459 });
460 const isRtl = theme.direction === 'rtl';
461 const handleKeyDown = useEventCallback(event => {
462 const index = Number(event.currentTarget.getAttribute('data-index'));
463 const value = values[index];
464 const tenPercents = (max - min) / 10;
465 const marksValues = marks.map(mark => mark.value);
466 const marksIndex = marksValues.indexOf(value);
467 let newValue;
468 const increaseKey = isRtl ? 'ArrowLeft' : 'ArrowRight';
469 const decreaseKey = isRtl ? 'ArrowRight' : 'ArrowLeft';
470
471 switch (event.key) {
472 case 'Home':
473 newValue = min;
474 break;
475
476 case 'End':
477 newValue = max;
478 break;
479
480 case 'PageUp':
481 if (step) {
482 newValue = value + tenPercents;
483 }
484
485 break;
486
487 case 'PageDown':
488 if (step) {
489 newValue = value - tenPercents;
490 }
491
492 break;
493
494 case increaseKey:
495 case 'ArrowUp':
496 if (step) {
497 newValue = value + step;
498 } else {
499 newValue = marksValues[marksIndex + 1] || marksValues[marksValues.length - 1];
500 }
501
502 break;
503
504 case decreaseKey:
505 case 'ArrowDown':
506 if (step) {
507 newValue = value - step;
508 } else {
509 newValue = marksValues[marksIndex - 1] || marksValues[0];
510 }
511
512 break;
513
514 default:
515 return;
516 } // Prevent scroll of the page
517
518
519 event.preventDefault();
520
521 if (step) {
522 newValue = roundValueToStep(newValue, step, min);
523 }
524
525 newValue = clamp(newValue, min, max);
526
527 if (range) {
528 const previousValue = newValue;
529 newValue = setValueIndex({
530 values,
531 source: valueDerived,
532 newValue,
533 index
534 }).sort(asc);
535 focusThumb({
536 sliderRef,
537 activeIndex: newValue.indexOf(previousValue)
538 });
539 }
540
541 setValueState(newValue);
542 setFocusVisible(index);
543
544 if (onChange) {
545 onChange(event, newValue);
546 }
547
548 if (onChangeCommitted) {
549 onChangeCommitted(event, newValue);
550 }
551 });
552 const previousIndex = React.useRef();
553 let axis = orientation;
554
555 if (isRtl && orientation !== "vertical") {
556 axis += '-reverse';
557 }
558
559 const getFingerNewValue = ({
560 finger,
561 move = false,
562 values: values2,
563 source
564 }) => {
565 const {
566 current: slider
567 } = sliderRef;
568 const {
569 width,
570 height,
571 bottom,
572 left
573 } = slider.getBoundingClientRect();
574 let percent;
575
576 if (axis.indexOf('vertical') === 0) {
577 percent = (bottom - finger.y) / height;
578 } else {
579 percent = (finger.x - left) / width;
580 }
581
582 if (axis.indexOf('-reverse') !== -1) {
583 percent = 1 - percent;
584 }
585
586 let newValue;
587 newValue = percentToValue(percent, min, max);
588
589 if (step) {
590 newValue = roundValueToStep(newValue, step, min);
591 } else {
592 const marksValues = marks.map(mark => mark.value);
593 const closestIndex = findClosest(marksValues, newValue);
594 newValue = marksValues[closestIndex];
595 }
596
597 newValue = clamp(newValue, min, max);
598 let activeIndex = 0;
599
600 if (range) {
601 if (!move) {
602 activeIndex = findClosest(values2, newValue);
603 } else {
604 activeIndex = previousIndex.current;
605 }
606
607 const previousValue = newValue;
608 newValue = setValueIndex({
609 values: values2,
610 source,
611 newValue,
612 index: activeIndex
613 }).sort(asc);
614 activeIndex = newValue.indexOf(previousValue);
615 previousIndex.current = activeIndex;
616 }
617
618 return {
619 newValue,
620 activeIndex
621 };
622 };
623
624 const handleTouchMove = useEventCallback(event => {
625 const finger = trackFinger(event, touchId);
626
627 if (!finger) {
628 return;
629 }
630
631 const {
632 newValue,
633 activeIndex
634 } = getFingerNewValue({
635 finger,
636 move: true,
637 values,
638 source: valueDerived
639 });
640 focusThumb({
641 sliderRef,
642 activeIndex,
643 setActive
644 });
645 setValueState(newValue);
646
647 if (onChange) {
648 onChange(event, newValue);
649 }
650 });
651 const handleTouchEnd = useEventCallback(event => {
652 const finger = trackFinger(event, touchId);
653
654 if (!finger) {
655 return;
656 }
657
658 const {
659 newValue
660 } = getFingerNewValue({
661 finger,
662 values,
663 source: valueDerived
664 });
665 setActive(-1);
666
667 if (event.type === 'touchend') {
668 setOpen(-1);
669 }
670
671 if (onChangeCommitted) {
672 onChangeCommitted(event, newValue);
673 }
674
675 touchId.current = undefined;
676 const doc = ownerDocument(sliderRef.current);
677 doc.removeEventListener('mousemove', handleTouchMove);
678 doc.removeEventListener('mouseup', handleTouchEnd);
679 doc.removeEventListener('touchmove', handleTouchMove);
680 doc.removeEventListener('touchend', handleTouchEnd);
681 });
682 const handleTouchStart = useEventCallback(event => {
683 // Workaround as Safari has partial support for touchAction: 'none'.
684 event.preventDefault();
685 const touch = event.changedTouches[0];
686
687 if (touch != null) {
688 // A number that uniquely identifies the current finger in the touch session.
689 touchId.current = touch.identifier;
690 }
691
692 const finger = trackFinger(event, touchId);
693 const {
694 newValue,
695 activeIndex
696 } = getFingerNewValue({
697 finger,
698 values,
699 source: valueDerived
700 });
701 focusThumb({
702 sliderRef,
703 activeIndex,
704 setActive
705 });
706 setValueState(newValue);
707
708 if (onChange) {
709 onChange(event, newValue);
710 }
711
712 const doc = ownerDocument(sliderRef.current);
713 doc.addEventListener('touchmove', handleTouchMove);
714 doc.addEventListener('touchend', handleTouchEnd);
715 });
716 React.useEffect(() => {
717 const {
718 current: slider
719 } = sliderRef;
720 slider.addEventListener('touchstart', handleTouchStart);
721 const doc = ownerDocument(slider);
722 return () => {
723 slider.removeEventListener('touchstart', handleTouchStart);
724 doc.removeEventListener('mousemove', handleTouchMove);
725 doc.removeEventListener('mouseup', handleTouchEnd);
726 doc.removeEventListener('touchmove', handleTouchMove);
727 doc.removeEventListener('touchend', handleTouchEnd);
728 };
729 }, [handleTouchEnd, handleTouchMove, handleTouchStart]);
730 const handleMouseDown = useEventCallback(event => {
731 if (onMouseDown) {
732 onMouseDown(event);
733 }
734
735 event.preventDefault();
736 const finger = trackFinger(event, touchId);
737 const {
738 newValue,
739 activeIndex
740 } = getFingerNewValue({
741 finger,
742 values,
743 source: valueDerived
744 });
745 focusThumb({
746 sliderRef,
747 activeIndex,
748 setActive
749 });
750 setValueState(newValue);
751
752 if (onChange) {
753 onChange(event, newValue);
754 }
755
756 const doc = ownerDocument(sliderRef.current);
757 doc.addEventListener('mousemove', handleTouchMove);
758 doc.addEventListener('mouseup', handleTouchEnd);
759 });
760 const trackOffset = valueToPercent(range ? values[0] : min, min, max);
761 const trackLeap = valueToPercent(values[values.length - 1], min, max) - trackOffset;
762
763 const trackStyle = _extends({}, axisProps[axis].offset(trackOffset), axisProps[axis].leap(trackLeap));
764
765 return /*#__PURE__*/React.createElement(Component, _extends({
766 ref: handleRef,
767 className: clsx(classes.root, classes[`color${capitalize(color)}`], className, disabled && classes.disabled, marks.length > 0 && marks.some(mark => mark.label) && classes.marked, track === false && classes.trackFalse, orientation === 'vertical' && classes.vertical, track === 'inverted' && classes.trackInverted),
768 onMouseDown: handleMouseDown
769 }, other), /*#__PURE__*/React.createElement("span", {
770 className: classes.rail
771 }), /*#__PURE__*/React.createElement("span", {
772 className: classes.track,
773 style: trackStyle
774 }), /*#__PURE__*/React.createElement("input", {
775 value: values.join(','),
776 name: name,
777 type: "hidden"
778 }), marks.map((mark, index) => {
779 const percent = valueToPercent(mark.value, min, max);
780 const style = axisProps[axis].offset(percent);
781 let markActive;
782
783 if (track === false) {
784 markActive = values.indexOf(mark.value) !== -1;
785 } else {
786 markActive = track === 'normal' && (range ? mark.value >= values[0] && mark.value <= values[values.length - 1] : mark.value <= values[0]) || track === 'inverted' && (range ? mark.value <= values[0] || mark.value >= values[values.length - 1] : mark.value >= values[0]);
787 }
788
789 return /*#__PURE__*/React.createElement(React.Fragment, {
790 key: mark.value
791 }, /*#__PURE__*/React.createElement("span", {
792 style: style,
793 "data-index": index,
794 className: clsx(classes.mark, markActive && classes.markActive)
795 }), mark.label != null ? /*#__PURE__*/React.createElement("span", {
796 "aria-hidden": true,
797 "data-index": index,
798 style: style,
799 className: clsx(classes.markLabel, markActive && classes.markLabelActive)
800 }, mark.label) : null);
801 }), values.map((value, index) => {
802 const percent = valueToPercent(value, min, max);
803 const style = axisProps[axis].offset(percent);
804 return /*#__PURE__*/React.createElement(ValueLabelComponent, {
805 key: index,
806 valueLabelFormat: valueLabelFormat,
807 valueLabelDisplay: valueLabelDisplay,
808 className: classes.valueLabel,
809 value: typeof valueLabelFormat === 'function' ? valueLabelFormat(scale(value), index) : valueLabelFormat,
810 index: index,
811 open: open === index || active === index || valueLabelDisplay === 'on',
812 disabled: disabled
813 }, /*#__PURE__*/React.createElement(ThumbComponent, {
814 className: clsx(classes.thumb, classes[`thumbColor${capitalize(color)}`], active === index && classes.active, disabled && classes.disabled, focusVisible === index && classes.focusVisible),
815 tabIndex: disabled ? null : 0,
816 role: "slider",
817 style: style,
818 "data-index": index,
819 "aria-label": getAriaLabel ? getAriaLabel(index) : ariaLabel,
820 "aria-labelledby": ariaLabelledby,
821 "aria-orientation": orientation,
822 "aria-valuemax": scale(max),
823 "aria-valuemin": scale(min),
824 "aria-valuenow": scale(value),
825 "aria-valuetext": getAriaValueText ? getAriaValueText(scale(value), index) : ariaValuetext,
826 onKeyDown: handleKeyDown,
827 onFocus: handleFocus,
828 onBlur: handleBlur,
829 onMouseOver: handleMouseOver,
830 onMouseLeave: handleMouseLeave
831 }));
832 }));
833});
834process.env.NODE_ENV !== "production" ? Slider.propTypes = {
835 /**
836 * The label of the slider.
837 */
838 'aria-label': chainPropTypes(PropTypes.string, props => {
839 const range = Array.isArray(props.value || props.defaultValue);
840
841 if (range && props['aria-label'] != null) {
842 return new Error('Material-UI: You need to use the `getAriaLabel` prop instead of `aria-label` when using a range slider.');
843 }
844
845 return null;
846 }),
847
848 /**
849 * The id of the element containing a label for the slider.
850 */
851 'aria-labelledby': PropTypes.string,
852
853 /**
854 * A string value that provides a user-friendly name for the current value of the slider.
855 */
856 'aria-valuetext': chainPropTypes(PropTypes.string, props => {
857 const range = Array.isArray(props.value || props.defaultValue);
858
859 if (range && props['aria-valuetext'] != null) {
860 return new Error('Material-UI: You need to use the `getAriaValueText` prop instead of `aria-valuetext` when using a range slider.');
861 }
862
863 return null;
864 }),
865
866 /**
867 * Override or extend the styles applied to the component.
868 * See [CSS API](#css) below for more details.
869 */
870 classes: PropTypes.object.isRequired,
871
872 /**
873 * @ignore
874 */
875 className: PropTypes.string,
876
877 /**
878 * The color of the component. It supports those theme colors that make sense for this component.
879 */
880 color: PropTypes.oneOf(['primary', 'secondary']),
881
882 /**
883 * The component used for the root node.
884 * Either a string to use a HTML element or a component.
885 */
886 component: PropTypes
887 /* @typescript-to-proptypes-ignore */
888 .elementType,
889
890 /**
891 * The default element value. Use when the component is not controlled.
892 */
893 defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.arrayOf(PropTypes.number)]),
894
895 /**
896 * If `true`, the slider will be disabled.
897 */
898 disabled: PropTypes.bool,
899
900 /**
901 * Accepts a function which returns a string value that provides a user-friendly name for the thumb labels of the slider.
902 *
903 * @param {number} index The thumb label's index to format.
904 * @returns {string}
905 */
906 getAriaLabel: PropTypes.func,
907
908 /**
909 * Accepts a function which returns a string value that provides a user-friendly name for the current value of the slider.
910 *
911 * @param {number} value The thumb label's value to format.
912 * @param {number} index The thumb label's index to format.
913 * @returns {string}
914 */
915 getAriaValueText: PropTypes.func,
916
917 /**
918 * Marks indicate predetermined values to which the user can move the slider.
919 * If `true` the marks will be spaced according the value of the `step` prop.
920 * If an array, it should contain objects with `value` and an optional `label` keys.
921 */
922 marks: PropTypes.oneOfType([PropTypes.bool, PropTypes.array]),
923
924 /**
925 * The maximum allowed value of the slider.
926 * Should not be equal to min.
927 */
928 max: PropTypes.number,
929
930 /**
931 * The minimum allowed value of the slider.
932 * Should not be equal to max.
933 */
934 min: PropTypes.number,
935
936 /**
937 * Name attribute of the hidden `input` element.
938 */
939 name: PropTypes.string,
940
941 /**
942 * Callback function that is fired when the slider's value changed.
943 *
944 * @param {object} event The event source of the callback.
945 * @param {number | number[]} value The new value.
946 */
947 onChange: PropTypes.func,
948
949 /**
950 * Callback function that is fired when the `mouseup` is triggered.
951 *
952 * @param {object} event The event source of the callback.
953 * @param {number | number[]} value The new value.
954 */
955 onChangeCommitted: PropTypes.func,
956
957 /**
958 * @ignore
959 */
960 onMouseDown: PropTypes.func,
961
962 /**
963 * The slider orientation.
964 */
965 orientation: PropTypes.oneOf(['horizontal', 'vertical']),
966
967 /**
968 * A transformation function, to change the scale of the slider.
969 */
970 scale: PropTypes.func,
971
972 /**
973 * The granularity with which the slider can step through values. (A "discrete" slider.)
974 * The `min` prop serves as the origin for the valid values.
975 * We recommend (max - min) to be evenly divisible by the step.
976 *
977 * When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop.
978 */
979 step: PropTypes.number,
980
981 /**
982 * The component used to display the value label.
983 */
984 ThumbComponent: PropTypes.elementType,
985
986 /**
987 * The track presentation:
988 *
989 * - `normal` the track will render a bar representing the slider value.
990 * - `inverted` the track will render a bar representing the remaining slider value.
991 * - `false` the track will render without a bar.
992 */
993 track: PropTypes.oneOf(['normal', false, 'inverted']),
994
995 /**
996 * The value of the slider.
997 * For ranged sliders, provide an array with two values.
998 */
999 value: PropTypes.oneOfType([PropTypes.number, PropTypes.arrayOf(PropTypes.number)]),
1000
1001 /**
1002 * The value label component.
1003 */
1004 ValueLabelComponent: PropTypes.elementType,
1005
1006 /**
1007 * Controls when the value label is displayed:
1008 *
1009 * - `auto` the value label will display when the thumb is hovered or focused.
1010 * - `on` will display persistently.
1011 * - `off` will never display.
1012 */
1013 valueLabelDisplay: PropTypes.oneOf(['on', 'auto', 'off']),
1014
1015 /**
1016 * The format function the value label's value.
1017 *
1018 * When a function is provided, it should have the following signature:
1019 *
1020 * - {number} value The value label's value to format
1021 * - {number} index The value label's index to format
1022 */
1023 valueLabelFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func])
1024} : void 0;
1025export default withStyles(styles, {
1026 name: 'MuiSlider'
1027})(Slider);
\No newline at end of file